diff --git a/components/modules/Kconfig b/components/modules/Kconfig index 4ec367be..c0e946fb 100644 --- a/components/modules/Kconfig +++ b/components/modules/Kconfig @@ -91,6 +91,13 @@ config LUA_MODULE_NODE help Includes the node module (recommended). +config LUA_MODULE_SIGMADELTA + bool "Sigma-Delta module" + default "n" + help + Includes the sigma_delta module. This module provides access to the + sigma-delta hardware. + config LUA_MODULE_STRUCT bool "Struct module" default "n" diff --git a/components/modules/sigma_delta.c b/components/modules/sigma_delta.c new file mode 100644 index 00000000..ebed3a60 --- /dev/null +++ b/components/modules/sigma_delta.c @@ -0,0 +1,90 @@ +// Module for interfacing with sigma-delta hardware + +#include "module.h" +#include "lauxlib.h" +#include "platform.h" + + +// Lua: setup( channel, pin ) +static int sigma_delta_setup( lua_State *L ) +{ + int channel = luaL_checkinteger( L, 1 ); + int pin = luaL_checkinteger( L, 2 ); + + MOD_CHECK_ID(sigma_delta, channel); + + if (!platform_sigma_delta_setup( channel, pin )) + luaL_error( L, "command failed" ); + + return 0; +} + +// Lua: close( channel ) +static int sigma_delta_close( lua_State *L ) +{ + int channel = luaL_checkinteger( L, 1 ); + + MOD_CHECK_ID(sigma_delta, channel); + + platform_sigma_delta_close( channel ); + + return 0; +} + +#if 0 +// Lua: setpwmduty( channel, duty_cycle ) +static int sigma_delta_setpwmduty( lua_State *L ) +{ + int channel = luaL_checkinteger( L, 1 ); + int duty = luaL_checkinteger( L, 2 ); + + MOD_CHECK_ID(sigma_delta, channel); + + if (!platform_sigma_delta_set_pwmduty( channel, duty )) + luaL_error( L, "command failed" ); + + return 0; +} +#endif + +// Lua: setprescale( channel, value ) +static int sigma_delta_setprescale( lua_State *L ) +{ + int channel = luaL_checkinteger( L, 1 ); + int prescale = luaL_checkinteger( L, 2 ); + + MOD_CHECK_ID(sigma_delta, channel); + + if (!platform_sigma_delta_set_prescale( channel, prescale )) + luaL_error( L, "command failed" ); + + return 0; +} + +// Lua: setduty( channel, value ) +static int sigma_delta_setduty( lua_State *L ) +{ + int channel = luaL_checkinteger( L, 1 ); + int duty = luaL_checkinteger( L, 2 ); + + MOD_CHECK_ID(sigma_delta, channel); + + if (!platform_sigma_delta_set_duty( channel, duty )) + luaL_error( L, "command failed" ); + + 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( "setduty" ), LFUNCVAL( sigma_delta_setduty ) }, + { LNILKEY, LNILVAL } +}; + +NODEMCU_MODULE(SIGMADELTA, "sigma_delta", sigma_delta_map, NULL); diff --git a/components/platform/include/platform.h b/components/platform/include/platform.h index bf3b5cf3..d2fcb840 100644 --- a/components/platform/include/platform.h +++ b/components/platform/include/platform.h @@ -68,6 +68,18 @@ void platform_uart_send( unsigned id, uint8_t data ); int platform_uart_set_flow_control( unsigned id, int type ); +// ***************************************************************************** +// Sigma-Delta subsection +int platform_sigma_delta_exists( unsigned channel ); + +uint8_t platform_sigma_delta_setup( uint8_t channel, uint8_t gpio_num ); +uint8_t platform_sigma_delta_close( uint8_t channel ); +// PWM emulation not possible, code kept for future reference +//uint8_t platform_sigma_delta_set_pwmduty( uint8_t channel, uint8_t duty ); +uint8_t platform_sigma_delta_set_prescale( uint8_t channel, uint8_t prescale ); +uint8_t platform_sigma_delta_set_duty( uint8_t channel, int8_t duty ); + + // Internal flash erase/write functions uint32_t platform_flash_get_sector_of_address( uint32_t addr ); diff --git a/components/platform/platform.c b/components/platform/platform.c index 67088633..7b515bff 100644 --- a/components/platform/platform.c +++ b/components/platform/platform.c @@ -1,5 +1,6 @@ #include "platform.h" #include "driver/console.h" +#include "driver/sigmadelta.h" #include int platform_init (void) @@ -58,3 +59,82 @@ void platform_uart_send( unsigned id, uint8_t data ) if (id == CONSOLE_UART) putchar (data); } + +// ***************************************************************************** +// Sigma-Delta platform interface + +static gpio_num_t platform_sigma_delta_channel2gpio[SIGMADELTA_CHANNEL_MAX]; + +int platform_sigma_delta_exists( unsigned channel ) { + return (channel < SIGMADELTA_CHANNEL_MAX); +} + +uint8_t platform_sigma_delta_setup( uint8_t channel, uint8_t gpio_num ) +{ +#if 0 + // signal generator can't be stopped this way + // stop signal generator + if (ESP_OK != sigmadelta_set_prescale( channel, 0 )) + return 0; +#endif + + // note channel to gpio assignment + platform_sigma_delta_channel2gpio[channel] = gpio_num; + + return ESP_OK == sigmadelta_set_pin( channel, gpio_num ) ? 1 : 0; +} + +uint8_t platform_sigma_delta_close( uint8_t channel ) +{ +#if 0 + // Note: signal generator can't be stopped this way + // stop signal generator + if (ESP_OK != sigmadelta_set_prescale( channel, 0 )) + return 0; +#endif + + gpio_set_level( platform_sigma_delta_channel2gpio[channel], 1 ); + gpio_config_t cfg; + // force pin back to GPIO + cfg.intr_type = GPIO_INTR_DISABLE; + cfg.mode = GPIO_MODE_OUTPUT; // essential to switch IO matrix to GPIO + cfg.pull_down_en = GPIO_PULLDOWN_DISABLE; + cfg.pull_up_en = GPIO_PULLUP_ENABLE; + cfg.pin_bit_mask = 1 << platform_sigma_delta_channel2gpio[channel]; + if (ESP_OK != gpio_config( &cfg )) + return 0; + + // and set it finally to input with pull-up enabled + cfg.mode = GPIO_MODE_INPUT; + + return ESP_OK == gpio_config( &cfg ) ? 1 : 0; +} + +#if 0 +// PWM emulation not possible, code kept for future reference +uint8_t platform_sigma_delta_set_pwmduty( uint8_t channel, 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) + if (ESP_OK != sigmadelta_set_prescale( channel, prescale )) + return 0; + if (ESP_OK != sigmadelta_set_duty( channel, duty-128 )) + return 0; + + return 1; +} +#endif + +uint8_t platform_sigma_delta_set_prescale( uint8_t channel, uint8_t prescale ) +{ + return ESP_OK == sigmadelta_set_prescale( channel, prescale ) ? 1 : 0; +} + +uint8_t IRAM_ATTR platform_sigma_delta_set_duty( uint8_t channel, int8_t duty ) +{ + return ESP_OK == sigmadelta_set_duty( channel, duty ) ? 1 : 0; +} diff --git a/docs/en/modules/sigma-delta.md b/docs/en/modules/sigma-delta.md new file mode 100644 index 00000000..6f25d899 --- /dev/null +++ b/docs/en/modules/sigma-delta.md @@ -0,0 +1,72 @@ +# Sigma-delta Module +| Since | Origin / Contributor | Maintainer | Source | +| :----- | :-------------------- | :---------- | :------ | +| 2017-01-13 | [Arnim Läuger](https://github.com/devsaurus) | [Arnim Läuger](https://github.com/devsaurus) | [sigma_delta.c](../../../app/modules/sigma_delta.c)| + +This module provides access to the [sigma-delta](https://en.wikipedia.org/wiki/Delta-sigma_modulation) component. It's a hardware signal generator that can be routed to any of the output GPIOs. + +The signal generation is controlled by the [`setprescale()`](#sigma_deltasetprescale) and [`setduty()`](#sigma_deltasetduty) functions. + +## sigma_delta.close() +Reenables GPIO functionality at the related pin. + +#### Syntax +`sigma_delta.close(channel)` + +#### Parameters +- `channel` 0~7, sigma-delta channel index + +#### Returns +`nil` + +## sigma_delta.setprescale() +Sets the prescale value. + +#### Syntax +`sigma_delta.setprescale(channel, value) + +#### Parameters +- `channel` 0~7, sigma-delta channel index +- `value` prescale 1 to 255 + +#### Returns +`nil` + +#### See also +[`sigma_delta.setduty()`](#sigma_deltasetduty) + +## sigma_delta.setduty() +Sets the duty value. + +#### Syntax +`sigma_delta.setduty(channel, value)` + +#### Parameters +- `channel` 0~7, sigma-delta channel index +- `value` duty -128 to 127 + +#### Returns +`nil` + +#### See also +[`sigma_delta.setprescale()`](#sigma_deltasetprescale) + +## sigma_delta.setup() +Routes the sigma-delta channel to the specified pin. Target prescale and duty values should be applied prior to enabling the output with this command. + +#### Syntax +`sigma_delta.setup(channel, pin)` + +#### Parameters +- `channel` 0~7, sigma-delta channel index +- `pin` 0~33, IO index + +#### Returns +`nil` + +#### Example +```lua +sigma_delta.setprescale(0, 128) +sigma_delta.setduty(0, 0) +sigma_delta.setup(0, 4) +``` diff --git a/mkdocs.yml b/mkdocs.yml index f23530d2..aaeed83d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -30,11 +30,12 @@ pages: - Extension Developer FAQ: 'en/extn-developer-faq.md' - Support: 'en/support.md' - Modules: - - 'bit': 'en/modules/bit.md' - - 'bthci': 'en/modules/bthci.md' - - 'file': 'en/modules/file.md' - - 'node': 'en/modules/node.md' - - 'struct': 'en/modules/struct.md' - - 'uart': 'en/modules/uart.md' - - 'wifi': 'en/modules/wifi.md' + - 'bit': 'en/modules/bit.md' + - 'bthci': 'en/modules/bthci.md' + - 'file': 'en/modules/file.md' + - 'node': 'en/modules/node.md' + - 'sigma delta': 'en/modules/sigma-delta.md' + - 'struct': 'en/modules/struct.md' + - 'uart': 'en/modules/uart.md' + - 'wifi': 'en/modules/wifi.md'