[realtek-ambz] Move common digital/analog utils into core
This commit is contained in:
@@ -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
|
||||
|
||||
99
arduino/libretuya/core/LibreTuyaCustom.c
Normal file
99
arduino/libretuya/core/LibreTuyaCustom.c
Normal 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) {}
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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];
|
||||
|
||||
Reference in New Issue
Block a user