[realtek-ambz] Move common digital/analog utils into core

This commit is contained in:
Kuba Szczodrzyński
2022-06-20 20:38:19 +02:00
parent c91b188f96
commit a83a845d5a
5 changed files with 160 additions and 95 deletions

View File

@@ -5,14 +5,13 @@
* [📁 Project structure](docs/project-structure.md)
* 🔖 Code reference
* [LibreTuya API](docs/reference/lt-api.md)
* [Class reference](ltapi/class_libre_tuya.md)
* [LT class reference](ltapi/class_libre_tuya.md)
* [Common methods](ltapi/_libre_tuya_a_p_i_8h.md)
* [Family-provided methods](ltapi/_libre_tuya_custom_8h.md)
* [Wiring custom methods](ltapi/_libre_tuya_custom_8h.md)
* [Logger](ltapi/lt__logger_8h.md)
* [Chip & family IDs](ltapi/_chip_type_8h_source.md)
* [POSIX utilities](ltapi/lt__posix__api_8h.md)
* Common API
* [Flash](ltapi/class_i_flash_class.md)
* [FS](ltapi/classfs_1_1_f_s.md)
* [Preferences](ltapi/class_i_preferences.md)
* [WiFi API](ltapi/class_i_wi_fi_generic_class.md)
@@ -24,6 +23,7 @@
* [TCP Server](ltapi/class_i_wi_fi_server.md)
* [LibreTuya libraries](docs/libs-built-in.md)
* [base64](ltapi/classbase64.md)
* [Flash](ltapi/class_flash_class.md)
* [HTTPClient](ltapi/class_h_t_t_p_client.md)
* [mDNS](ltapi/classm_d_n_s.md)
* NetUtils

View File

@@ -0,0 +1,99 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-20. */
#include "LibreTuyaCustom.h"
int _analogReadResolution = 10; // 0-1023
int _analogWriteResolution = 8; // 0-255
int _analogWritePeriod = 20000; // 50 Hz
/**
* @brief Check if pin is invalid (too low or too high).
*/
bool pinInvalid(pin_size_t pinNumber) {
return pinNumber < 0 || pinNumber >= PINS_COUNT;
}
/**
* @brief Get PinInfo struct for the specified number.
* Returns NULL if pin number is invalid.
*/
PinInfo *pinInfo(pin_size_t pinNumber) {
if (pinInvalid(pinNumber))
return NULL;
return &(pinTable[pinNumber]);
}
/**
* @brief Check if pin supports all features represented by 'mask'.
*/
bool pinHasFeat(PinInfo *pin, uint32_t mask) {
return (pin->features & mask) == mask;
}
/**
* @brief Check if pin has all features represented by 'mask' enabled.
*/
bool pinIsFeat(PinInfo *pin, uint32_t mask) {
return (pin->types & mask) == mask;
}
/**
* @brief Check if GPIO pin is configured as output.
*/
bool pinIsOutput(PinInfo *pin) {
return pin->mode == OUTPUT || pin->mode == OUTPUT_OPENDRAIN;
}
/**
* @brief Check if GPIO pin is configured as output.
*/
bool pinIsInput(PinInfo *pin) {
return pin->mode == INPUT || pin->mode == INPUT_PULLUP || pin->mode == INPUT_PULLDOWN;
}
/**
* @brief Read voltage from ADC and return a value between 0 and
* the current reading resolution.
*/
int analogRead(pin_size_t pinNumber) {
float voltage = analogReadVoltage(pinNumber);
float maxVoltage = analogReadMaxVoltage(pinNumber);
uint16_t ret = round((1 << _analogReadResolution) * voltage / maxVoltage);
if (ret >= (1 << _analogReadResolution))
ret = (1 << _analogReadResolution) - 1;
return ret;
}
/**
* @brief Set resolution of values (in bits) returned by analogRead().
* Defaults to 10 bit (0-1023).
*/
void analogReadResolution(int res) {
_analogReadResolution = res;
}
/**
* @brief Set resolution of values (in bits) expected by analogWrite().
* Defaults to 8 bit (0-255).
*/
void analogWriteResolution(int res) {
_analogWriteResolution = res;
}
/**
* @brief Set PWM output frequency (in Hz).
* Defaults to 50 Hz (20,000 uS).
*/
void analogWriteFrequency(int hz) {
_analogWritePeriod = 1E6 / hz;
}
/**
* @brief Set PWM output frequency (cycle period) in microseconds.
* Defaults to 20,000 uS (50 Hz).
*/
void analogWritePeriod(int us) {
_analogWritePeriod = us;
}
__attribute__((weak)) void analogReference(uint8_t mode) {}

View File

@@ -53,30 +53,34 @@ typedef struct {
extern PinInfo pinTable[];
// Custom Wiring methods
bool pinInvalid(pin_size_t pinNumber);
PinInfo *pinInfo(pin_size_t pinNumber);
bool pinHasFeat(PinInfo *pin, uint32_t mask);
bool pinIsFeat(PinInfo *pin, uint32_t mask);
bool pinIsOutput(PinInfo *pin);
bool pinIsInput(PinInfo *pin);
int analogRead(pin_size_t pinNumber);
void analogReadResolution(int res);
void analogWriteResolution(int res);
void analogWriteFrequency(int hz);
void analogWritePeriod(int us);
extern int _analogReadResolution;
extern int _analogWriteResolution;
extern int _analogWritePeriod;
/**
* @brief Read voltage from analog input (in millivolts).
*/
uint16_t analogReadVoltage(pin_size_t pinNumber);
/**
* @brief Set resolution of values (in bits) returned by analogRead().
* @brief Get max reading voltage for the specified pin (millivolts).
*/
void analogReadResolution(int res);
/**
* @brief Set PWM output frequency (in Hz).
*/
void analogWriteFrequency(int hz);
/**
* @brief Set PWM output frequency (cycle period) in microseconds.
*/
void analogWritePeriod(int us);
/**
* @brief Set resolution of values (in bits) expected by analogWrite().
*/
void analogWriteResolution(int res);
uint16_t analogReadMaxVoltage(pin_size_t pinNumber);
#ifdef __cplusplus
} // extern "C"

View File

@@ -35,34 +35,8 @@ extern void *gpio_pin_struct[];
extern void pinRemoveMode(pin_size_t pinNumber);
static int _readResolution = 10;
static int _writeResolution = 8;
static int _writePeriod = 20000; // 50 Hz
// TODO implement custom ADC calibration
void analogReadResolution(int res) {
_readResolution = res;
}
void analogWriteFrequency(int hz) {
_writePeriod = 1E6 / hz;
}
void analogWritePeriod(int us) {
_writePeriod = us;
}
void analogWriteResolution(int res) {
_writeResolution = res;
}
uint8_t analog_reference = 0;
void analogReference(uint8_t mode) {
analog_reference = mode;
}
uint16_t analogReadVoltage(pin_size_t pinNumber) {
uint16_t ret = 0;
switch (pinNumber) {
@@ -102,42 +76,30 @@ uint16_t analogReadVoltage(pin_size_t pinNumber) {
return AD2MV(ret, 0x418, 0x342);
}
int analogRead(pin_size_t pinNumber) {
float voltage = analogReadVoltage(pinNumber);
uint16_t ret = 0;
if (pinNumber != PIN_A1) {
ret = round((1 << _readResolution) * voltage / 3300);
} else {
ret = round((1 << _readResolution) * voltage / 5000);
}
if (ret >= (1 << _readResolution))
ret = (1 << _readResolution) - 1;
return ret;
uint16_t analogReadMaxVoltage(pin_size_t pinNumber) {
if (pinNumber == PIN_A1)
return 5000;
return 3300;
}
void analogOutputInit(void) {
// nop
}
// Right now, PWM output only works on the pins with
// hardware support. These are defined in the appropriate
// pins_*.c file. For the rest of the pins, we default
// to digital output.
void analogWrite(pin_size_t pinNumber, int value) {
PinInfo *pin = pinInfo(pinNumber);
if (!pin)
return;
pwmout_t *obj;
if ((pinTable[pinNumber].features & PIN_PWM) == PIN_PWM) {
float percent = value * 1.0 / (1 << _writeResolution);
if (pinTable[pinNumber].types != PIN_PWM) {
if ((pinTable[pinNumber].types == PIN_GPIO) || (pinTable[pinNumber].types == PIN_IRQ)) {
if (pinHasFeat(pin, PIN_PWM)) {
float percent = value * 1.0 / (1 << _analogWriteResolution);
if (pin->types != PIN_PWM) {
if ((pin->types == PIN_GPIO) || (pin->types == PIN_IRQ)) {
pinRemoveMode(pinNumber);
}
gpio_pin_struct[pinNumber] = malloc(sizeof(pwmout_t));
pwmout_t *obj = (pwmout_t *)gpio_pin_struct[pinNumber];
pwmout_init(obj, pinTable[pinNumber].gpio);
pwmout_period_us(obj, _writePeriod);
pwmout_init(obj, pin->gpio);
pwmout_period_us(obj, _analogWritePeriod);
pwmout_write(obj, percent);
pinTable[pinNumber].types = PIN_PWM;
pin->types = PIN_PWM;
} else {
pwmout_t *obj = (pwmout_t *)gpio_pin_struct[pinNumber];
// pwmout_period_us(obj, _writePeriod);

View File

@@ -6,65 +6,63 @@
extern void *gpio_pin_struct[PINS_COUNT];
bool pinInvalid(pin_size_t pinNumber) {
return pinNumber < 0 || pinNumber >= PINS_COUNT || pinTable[pinNumber].gpio == NC;
}
void pinRemoveMode(pin_size_t pinNumber) {
if (pinInvalid(pinNumber))
PinInfo *pin = pinInfo(pinNumber);
if (!pin)
return;
if (pinTable[pinNumber].types & PIN_PWM) {
if (pinIsFeat(pin, PIN_PWM)) {
pwmout_t *obj = (pwmout_t *)gpio_pin_struct[pinNumber];
pwmout_free(obj);
}
if (pinTable[pinNumber].types & PIN_GPIO) {
if (pinIsFeat(pin, PIN_GPIO)) {
gpio_t *obj = (gpio_t *)gpio_pin_struct[pinNumber];
gpio_deinit(obj, pinTable[pinNumber].gpio);
gpio_deinit(obj, pin->gpio);
free(obj);
}
if (pinTable[pinNumber].types & PIN_IRQ) {
if (pinIsFeat(pin, PIN_IRQ)) {
gpio_irq_t *obj = (gpio_irq_t *)gpio_pin_struct[pinNumber];
gpio_irq_deinit(obj);
free(obj);
}
gpio_pin_struct[pinNumber] = NULL;
pinTable[pinNumber].types = PIN_NONE;
pin->types = PIN_NONE;
}
void pinMode(pin_size_t pinNumber, PinModeArduino pinMode) {
if (pinInvalid(pinNumber))
PinInfo *pin = pinInfo(pinNumber);
if (!pin)
return;
if (pinTable[pinNumber].types == PIN_GPIO && pinTable[pinNumber].mode == pinMode)
if (pinIsFeat(pin, PIN_GPIO) && pin->mode == pinMode)
// Nothing changes in pin mode
return;
if ((pinTable[pinNumber].features & PIN_GPIO) != PIN_GPIO)
if (!pinHasFeat(pin, PIN_GPIO))
// cannot set ADC as I/O
return;
/* if (pinTable[pinNumber].types == PIN_PWM) {
/* if (pin->types == PIN_PWM) {
// If this pin has been configured as PWM, then it cannot change to another mode
return;
} */
if (pinTable[pinNumber].types != PIN_GPIO)
if (pin->types != PIN_GPIO)
// pin mode changes; deinit gpio and free memory
pinRemoveMode(pinNumber);
gpio_t *gpio;
if (pinTable[pinNumber].types == PIN_NONE) {
if (pin->types == PIN_NONE) {
// allocate memory if pin not used before
gpio = malloc(sizeof(gpio_t));
gpio_pin_struct[pinNumber] = gpio;
gpio_init(gpio, pinTable[pinNumber].gpio);
pinTable[pinNumber].types = PIN_GPIO;
gpio_init(gpio, pin->gpio);
pin->types = PIN_GPIO;
} else {
// pin already used as gpio
gpio = (gpio_t *)gpio_pin_struct[pinNumber];
}
pinTable[pinNumber].mode = pinMode;
pin->mode = pinMode;
PinDirection dir;
PinMode mode;
@@ -99,9 +97,10 @@ void pinMode(pin_size_t pinNumber, PinModeArduino pinMode) {
}
void digitalWrite(pin_size_t pinNumber, PinStatus status) {
if (pinInvalid(pinNumber))
PinInfo *pin = pinInfo(pinNumber);
if (!pin)
return;
if (pinTable[pinNumber].types != PIN_GPIO)
if (pin->types != PIN_GPIO)
return;
gpio_t *gpio = (gpio_t *)gpio_pin_struct[pinNumber];
@@ -109,9 +108,10 @@ void digitalWrite(pin_size_t pinNumber, PinStatus status) {
}
PinStatus digitalRead(pin_size_t pinNumber) {
if (pinInvalid(pinNumber))
PinInfo *pin = pinInfo(pinNumber);
if (!pin)
return;
if (pinTable[pinNumber].types != PIN_GPIO)
if (pin->types != PIN_GPIO)
return;
gpio_t *gpio = (gpio_t *)gpio_pin_struct[pinNumber];