diff --git a/app/driver/sigma_delta.c b/app/driver/sigma_delta.c new file mode 100644 index 00000000..50c99005 --- /dev/null +++ b/app/driver/sigma_delta.c @@ -0,0 +1,33 @@ + +#include "driver/sigma_delta.h" + + +void sigma_delta_setup( void ) +{ + GPIO_REG_WRITE(GPIO_SIGMA_DELTA, + GPIO_SIGMA_DELTA_SET(GPIO_SIGMA_DELTA_ENABLE) | + GPIO_SIGMA_DELTA_TARGET_SET(0x00) | + GPIO_SIGMA_DELTA_PRESCALE_SET(0x00)); +} + +void sigma_delta_stop( void ) +{ + GPIO_REG_WRITE(GPIO_SIGMA_DELTA, + GPIO_SIGMA_DELTA_SET(GPIO_SIGMA_DELTA_DISABLE) | + GPIO_SIGMA_DELTA_TARGET_SET(0x00) | + GPIO_SIGMA_DELTA_PRESCALE_SET(0x00) ); +} + +void sigma_delta_set_prescale_target( sint16 prescale, sint16 target ) +{ + uint32_t prescale_mask, target_mask; + + prescale_mask = prescale >= 0 ? GPIO_SIGMA_DELTA_PRESCALE_MASK : 0x00; + target_mask = target >= 0 ? GPIO_SIGMA_DELTA_TARGET_MASK : 0x00; + + // set prescale and target with one register access to avoid glitches + GPIO_REG_WRITE(GPIO_SIGMA_DELTA, + (GPIO_REG_READ(GPIO_SIGMA_DELTA) & ~(prescale_mask | target_mask)) | + (GPIO_SIGMA_DELTA_PRESCALE_SET(prescale) & prescale_mask) | + (GPIO_SIGMA_DELTA_TARGET_SET(target) & target_mask)); +} diff --git a/app/include/driver/sigma_delta.h b/app/include/driver/sigma_delta.h new file mode 100644 index 00000000..13148e19 --- /dev/null +++ b/app/include/driver/sigma_delta.h @@ -0,0 +1,11 @@ +#ifndef SIGMA_DELTA_APP_H +#define SIGMA_DELTA_APP_H + +#include "eagle_soc.h" +#include "os_type.h" + +void sigma_delta_setup( void ); +void sigma_delta_stop( void ); +void sigma_delta_set_prescale_target( sint16 prescale, sint16 target ); + +#endif diff --git a/app/include/user_modules.h b/app/include/user_modules.h index a250e060..79e32a1f 100644 --- a/app/include/user_modules.h +++ b/app/include/user_modules.h @@ -37,6 +37,7 @@ #define LUA_USE_MODULES_RTCFIFO #define LUA_USE_MODULES_RTCMEM #define LUA_USE_MODULES_RTCTIME +//#define LUA_USE_MODULES_SIGMA_DELTA #define LUA_USE_MODULES_SNTP #define LUA_USE_MODULES_SPI #define LUA_USE_MODULES_TMR diff --git a/app/modules/sigma_delta.c b/app/modules/sigma_delta.c new file mode 100644 index 00000000..7bcbb7e7 --- /dev/null +++ b/app/modules/sigma_delta.c @@ -0,0 +1,87 @@ +// Module for interfacing with sigma-delta hardware + +#include "module.h" +#include "lauxlib.h" +#include "platform.h" + + +// Lua: setup( pin ) +static int sigma_delta_setup( lua_State *L ) +{ + int pin = luaL_checkinteger( L, 1 ); + + MOD_CHECK_ID(sigma_delta, pin); + + platform_sigma_delta_setup( pin ); + + return 0; +} + +// Lua: close( pin ) +static int sigma_delta_close( lua_State *L ) +{ + int pin = luaL_checkinteger( L, 1 ); + + MOD_CHECK_ID(sigma_delta, pin); + + platform_sigma_delta_close( pin ); + + return 0; +} + + +// Lua: setpwmduty( duty_cycle ) +static int sigma_delta_setpwmduty( lua_State *L ) +{ + int duty = luaL_checkinteger( L, 1 ); + + if (duty < 0 || duty > 255) { + return luaL_error( L, "wrong arg range" ); + } + + platform_sigma_delta_set_pwmduty( duty ); + + return 0; +} + +// Lua: setprescale( value ) +static int sigma_delta_setprescale( lua_State *L ) +{ + int prescale = luaL_checkinteger( L, 1 ); + + if (prescale < 0 || prescale > 255) { + return luaL_error( L, "wrong arg range" ); + } + + platform_sigma_delta_set_prescale( prescale ); + + return 0; +} + +// Lua: settarget( value ) +static int sigma_delta_settarget( lua_State *L ) +{ + int target = luaL_checkinteger( L, 1 ); + + if (target < 0 || target > 255) { + return luaL_error( L, "wrong arg range" ); + } + + platform_sigma_delta_set_target( target ); + + return 0; +} + + +// Module function map +static const LUA_REG_TYPE sigma_delta_map[] = +{ + { LSTRKEY( "setup" ), LFUNCVAL( sigma_delta_setup ) }, + { LSTRKEY( "close" ), LFUNCVAL( sigma_delta_close ) }, + { LSTRKEY( "setpwmduty" ), LFUNCVAL( sigma_delta_setpwmduty ) }, + { LSTRKEY( "setprescale" ), LFUNCVAL( sigma_delta_setprescale ) }, + { LSTRKEY( "settarget" ), LFUNCVAL( sigma_delta_settarget ) }, + { LNILKEY, LNILVAL } +}; + +NODEMCU_MODULE(SIGMA_DELTA, "sigma_delta", sigma_delta_map, NULL); diff --git a/app/platform/platform.c b/app/platform/platform.c index 4215f5d8..3bff446c 100755 --- a/app/platform/platform.c +++ b/app/platform/platform.c @@ -12,6 +12,7 @@ #include "driver/i2c_master.h" #include "driver/spi.h" #include "driver/uart.h" +#include "driver/sigma_delta.h" static void pwms_init(); @@ -444,6 +445,69 @@ void platform_pwm_stop( unsigned pin ) } } + +// ***************************************************************************** +// Sigma-Delta platform interface + +uint8_t platform_sigma_delta_setup( uint8_t pin ) +{ + if (pin < 1 || pin > NUM_GPIO) + return 0; + + sigma_delta_setup(); + + // set GPIO output mode for this pin + platform_gpio_mode( pin, PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_FLOAT ); + platform_gpio_write( pin, PLATFORM_GPIO_LOW ); + + // enable sigma-delta on this pin + GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(pin_num[pin])), + (GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(pin_num[pin]))) &(~GPIO_PIN_SOURCE_MASK)) | + GPIO_PIN_SOURCE_SET( SIGMA_AS_PIN_SOURCE )); + + return 1; +} + +uint8_t platform_sigma_delta_close( uint8_t pin ) +{ + if (pin < 1 || pin > NUM_GPIO) + return 0; + + sigma_delta_stop(); + + // set GPIO input mode for this pin + platform_gpio_mode( pin, PLATFORM_GPIO_INPUT, PLATFORM_GPIO_PULLUP ); + + // CONNECT GPIO TO PIN PAD + GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(pin_num[pin])), + (GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(pin_num[pin]))) &(~GPIO_PIN_SOURCE_MASK)) | + GPIO_PIN_SOURCE_SET( GPIO_AS_PIN_SOURCE )); + + return 1; +} + +void platform_sigma_delta_set_pwmduty( uint8_t duty ) +{ + uint8_t target = 0, prescale = 0; + + target = duty > 128 ? 256 - duty : duty; + prescale = target == 0 ? 0 : target-1; + + //freq = 80000 (khz) /256 /duty_target * (prescale+1) + sigma_delta_set_prescale_target( prescale, duty ); +} + +void platform_sigma_delta_set_prescale( uint8_t prescale ) +{ + sigma_delta_set_prescale_target( prescale, -1 ); +} + +void platform_sigma_delta_set_target( uint8_t target ) +{ + sigma_delta_set_prescale_target( -1, target ); +} + + // ***************************************************************************** // I2C platform interface diff --git a/app/platform/platform.h b/app/platform/platform.h index d514b583..2905d5f9 100644 --- a/app/platform/platform.h +++ b/app/platform/platform.h @@ -203,6 +203,19 @@ static inline int platform_ow_exists( unsigned id ) { return ((id < NUM_OW) && ( static inline int platform_tmr_exists( unsigned id ) { return id < NUM_TMR; } +// ***************************************************************************** +// Sigma-Delta platform interface + +// **************************************************************************** +// Sigma-Delta functions + +static inline int platform_sigma_delta_exists( unsigned id ) {return ((id < NUM_GPIO) && (id > 0)); } +uint8_t platform_sigma_delta_setup( uint8_t pin ); +uint8_t platform_sigma_delta_close( uint8_t pin ); +void platform_sigma_delta_set_pwmduty( uint8_t duty ); +void platform_sigma_delta_set_prescale( uint8_t prescale ); +void platform_sigma_delta_set_target( uint8_t target ); + // ***************************************************************************** // I2C platform interface diff --git a/docs/en/modules/sigma-delta.md b/docs/en/modules/sigma-delta.md new file mode 100644 index 00000000..aa5a8d91 --- /dev/null +++ b/docs/en/modules/sigma-delta.md @@ -0,0 +1,94 @@ +# sigma delta Module +This module provides access to the sigma-delta component. It's a hardware signal generator that can be routed to any of the GPIOs except pin 0. + +The signal generation is controlled by the [`setprescale()`](#sigma_deltasetprescale) and [`settarget()`](#sigma_deltasettarget) functions. + * 0 < target <= 128
+ thigh = (prescale + 1) / 80 µs
+ tperiod = thigh * 256 / target + * 128 < target < 256
+ tlow = (prescale + 1) / 80 µs
+ tperiod = tlow * 256 / (256 - target) + * target = 0
+ signal stopped at low + +Fixed frequency PWM at ~312.5 kHz is availble with the [`setpwmduty()`](#sigma_deltasetpwmduty) function. + +## sigma_delta.close() +Stops signal generation and reenables GPIO functionality at the specified pin. + +#### Syntax +`sigma_delta.close(pin)` + +#### Parameters +`pin` 1~12, IO index + +#### Returns +`nil` + +## sigma_delta.setprescale() +Sets the prescale value. + +#### Syntax +`sigma_delta.setprescale(value) + +#### Parameters +`value` prescale 1 to 255 + +#### Returns +`nil` + +#### See also +[`sigma_delta.settarget()`](#sigma_deltasettarget) + +## sigma_delta.setpwmduty() +Operate the sigma-delta module in PWM-like mode with fixed base frequency. + +#### Syntax +`sigma_delta.setpwmduty(ratio)` + +#### Parameters +`ratio` 0...255 for duty cycle 0...100%, 0 stops the signal at low + +#### Returns +`nil` + +#### Example +```lua +-- attach generator to pin 2 +sigma_delta.setup(2) +-- set 50% duty cycle ratio (and implicitly start signal) +sigma_delta.setpwmduty(128) +-- stop +sigma_delta.setpwmduty(0) +-- resume with ~99.6% ratio +sigma_delta.setpwmduty(255) +-- stop and detach generator from pin 2 +sigma_delta.close(2) +``` + +## sigma_delta.settarget() +Sets the target value. + +#### Syntax +`sigma_delta.settarget(value) + +#### Parameters +`value` target 0 to 255 + +#### Returns +`nil` + +#### See also +[`sigma_delta.setprescale()`](#sigma_deltasetprescale) + +## sigma_delta.setup() +Stops the signal generator and routes it to the specified pin. + +#### Syntax +`sigma_delta.setup(pin)` + +#### Parameters +`pin` 1~12, IO index + +#### Returns +`nil` diff --git a/mkdocs.yml b/mkdocs.yml index 3ea3fade..ba7c42fa 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -56,6 +56,7 @@ pages: - 'rtcmem': 'en/modules/rtcmem.md' - 'rtctime': 'en/modules/rtctime.md' - 'rtcfifo': 'en/modules/rtcfifo.md' + - 'sigma delta': 'en/modules/sigma-delta.md' - 'sntp': 'en/modules/sntp.md' - 'spi': 'en/modules/spi.md' - 'tmr': 'en/modules/tmr.md' diff --git a/sdk-overrides/include/eagle_soc.h b/sdk-overrides/include/eagle_soc.h new file mode 100644 index 00000000..efca7dc5 --- /dev/null +++ b/sdk-overrides/include/eagle_soc.h @@ -0,0 +1,32 @@ +#ifndef _SDK_OVERRIDE_EAGLE_SOC_H_ +#define _SDK_OVERRIDE_EAGLE_SOC_H_ + + +#include_next "eagle_soc.h" + +#define GPIO_SIGMA_DELTA 0x00000068 //defined in gpio register.xls + +#define GPIO_SIGMA_DELTA_SETTING_MASK (0x00000001ff) + +#define GPIO_SIGMA_DELTA_ENABLE 1 +#define GPIO_SIGMA_DELTA_DISABLE (~GPIO_SIGMA_DELTA_ENABLE) +#define GPIO_SIGMA_DELTA_MSB 16 +#define GPIO_SIGMA_DELTA_LSB 16 +#define GPIO_SIGMA_DELTA_MASK (0x00000001<> GPIO_SIGMA_DELTA_LSB) +#define GPIO_SIGMA_DELTA_SET(x) (((x) << GPIO_SIGMA_DELTA_LSB) & GPIO_SIGMA_DELTA_MASK) + +#define GPIO_SIGMA_DELTA_TARGET_MSB 7 +#define GPIO_SIGMA_DELTA_TARGET_LSB 0 +#define GPIO_SIGMA_DELTA_TARGET_MASK (0x000000FF<> GPIO_SIGMA_DELTA_TARGET_LSB) +#define GPIO_SIGMA_DELTA_TARGET_SET(x) (((x) << GPIO_SIGMA_DELTA_TARGET_LSB) & GPIO_SIGMA_DELTA_TARGET_MASK) + +#define GPIO_SIGMA_DELTA_PRESCALE_MSB 15 +#define GPIO_SIGMA_DELTA_PRESCALE_LSB 8 +#define GPIO_SIGMA_DELTA_PRESCALE_MASK (0x000000FF<> GPIO_SIGMA_DELTA_PRESCALE_LSB) +#define GPIO_SIGMA_DELTA_PRESCALE_SET(x) (((x) << GPIO_SIGMA_DELTA_PRESCALE_LSB) & GPIO_SIGMA_DELTA_PRESCALE_MASK) + + +#endif