diff --git a/components/base_nodemcu/uart.c b/components/base_nodemcu/uart.c index e7f4193c..5669b98c 100644 --- a/components/base_nodemcu/uart.c +++ b/components/base_nodemcu/uart.c @@ -172,6 +172,20 @@ static int uart_setup( lua_State* L ) return 1; } +static int uart_setmode(lua_State* L) +{ + unsigned id, mode; + uint32_t res; + + id = luaL_checkinteger( L, 1 ); + MOD_CHECK_ID( uart, id ); + mode = luaL_checkinteger( L, 2 ); + + platform_uart_setmode(id, mode); + + return 0; +} + // Lua: write( id, string1, [string2], ..., [stringn] ) static int uart_write( lua_State* L ) { @@ -231,6 +245,7 @@ static const LUA_REG_TYPE uart_map[] = { { LSTRKEY( "start" ), LFUNCVAL( uart_start ) }, { LSTRKEY( "stop" ), LFUNCVAL( uart_stop ) }, { LSTRKEY( "on" ), LFUNCVAL( uart_on ) }, + { LSTRKEY( "setmode" ), LFUNCVAL( uart_setmode ) }, { LSTRKEY( "STOPBITS_1" ), LNUMVAL( PLATFORM_UART_STOPBITS_1 ) }, { LSTRKEY( "STOPBITS_1_5" ), LNUMVAL( PLATFORM_UART_STOPBITS_1_5 ) }, { LSTRKEY( "STOPBITS_2" ), LNUMVAL( PLATFORM_UART_STOPBITS_2 ) }, @@ -240,6 +255,11 @@ static const LUA_REG_TYPE uart_map[] = { { LSTRKEY( "FLOWCTRL_NONE" ), LNUMVAL( PLATFORM_UART_FLOW_NONE ) }, { LSTRKEY( "FLOWCTRL_CTS" ), LNUMVAL( PLATFORM_UART_FLOW_CTS ) }, { LSTRKEY( "FLOWCTRL_RTS" ), LNUMVAL( PLATFORM_UART_FLOW_RTS ) }, + { LSTRKEY( "MODE_UART" ), LNUMVAL( PLATFORM_UART_MODE_UART ) }, + { LSTRKEY( "MODE_RS485_COLLISION_DETECT" ), LNUMVAL( PLATFORM_UART_MODE_RS485_COLLISION_DETECT ) }, + { LSTRKEY( "MODE_RS485_APP_CONTROL" ), LNUMVAL( PLATFORM_UART_MODE_RS485_APP_CONTROL ) }, + { LSTRKEY( "MODE_RS485_HALF_DUPLEX" ), LNUMVAL( PLATFORM_UART_MODE_HALF_DUPLEX ) }, + { LSTRKEY( "MODE_IRDA" ), LNUMVAL( PLATFORM_UART_MODE_IRDA ) }, { LNILKEY, LNILVAL } }; diff --git a/components/platform/include/platform.h b/components/platform/include/platform.h index c15701ac..e3434504 100644 --- a/components/platform/include/platform.h +++ b/components/platform/include/platform.h @@ -50,6 +50,15 @@ int platform_gpio_output_exists( unsigned gpio ); #define UART_BUFFER_SIZE 512 +enum +{ + PLATFORM_UART_MODE_UART = 0x0, + PLATFORM_UART_MODE_RS485_COLLISION_DETECT = 0x1, + PLATFORM_UART_MODE_RS485_APP_CONTROL = 0x2, + PLATFORM_UART_MODE_HALF_DUPLEX = 0x3, + PLATFORM_UART_MODE_IRDA = 0x4 +}; + // Parity enum { @@ -107,6 +116,7 @@ typedef struct { // The platform UART functions static inline int platform_uart_exists( unsigned id ) { return id < NUM_UART; } uint32_t platform_uart_setup( unsigned id, uint32_t baud, int databits, int parity, int stopbits, uart_pins_t* pins ); +void platform_uart_setmode(unsigned id, unsigned mode); void platform_uart_send_multi( unsigned id, const char *data, size_t len ); void platform_uart_send( unsigned id, uint8_t data ); void platform_uart_flush( unsigned id ); diff --git a/components/platform/platform.c b/components/platform/platform.c index 48046da8..1c707b61 100644 --- a/components/platform/platform.c +++ b/components/platform/platform.c @@ -76,7 +76,6 @@ void uart_event_task( task_param_t param, task_prio_t prio ) { } free(post->data); - free(post); } else { char *err; switch(post->type) { @@ -92,6 +91,7 @@ void uart_event_task( task_param_t param, task_prio_t prio ) { } uart_on_error_cb(id, err, strlen(err)); } + free(post); } static void task_uart( void *pvParameters ){ @@ -130,6 +130,7 @@ static void task_uart( void *pvParameters ){ } post->id = id; post->type = PLATFORM_UART_EVENT_BREAK; + break; case UART_FIFO_OVF: case UART_BUFFER_FULL: case UART_PARITY_ERR: @@ -242,6 +243,26 @@ uint32_t platform_uart_setup( unsigned id, uint32_t baud, int databits, int pari } } +void platform_uart_setmode(unsigned id, unsigned mode) +{ + uart_mode_t uartMode; + + switch(mode) + { + case PLATFORM_UART_MODE_IRDA: + uartMode = UART_MODE_IRDA; break; + case PLATFORM_UART_MODE_RS485_COLLISION_DETECT: + uartMode = UART_MODE_RS485_COLLISION_DETECT; break; + case PLATFORM_UART_MODE_RS485_APP_CONTROL: + uartMode = UART_MODE_RS485_APP_CTRL; break; + case PLATFORM_UART_MODE_HALF_DUPLEX: + uartMode = UART_MODE_RS485_HALF_DUPLEX; break; + case PLATFORM_UART_MODE_UART: + default: + uartMode = UART_MODE_UART; break; + } + uart_set_mode(id, uartMode); +} void platform_uart_send_multi( unsigned id, const char *data, size_t len ) { diff --git a/docs/en/modules/uart.md b/docs/en/modules/uart.md index 46efedf1..ee17ae55 100644 --- a/docs/en/modules/uart.md +++ b/docs/en/modules/uart.md @@ -131,6 +131,26 @@ Stop the UART. You should not call `stop()` on the console uart. `nil` +## uart.setmode() + +Set UART controllers communication mode + +#### Syntax + +`uart.setmode(id, mode)` + +#### Parameters +- `id` uart id +- `mode` value should be one of + - `uart.MODE_UART` default UART mode, is set after uart.setup() call + - `uart.MODE_RS485_COLLISION_DETECT` receiver must be always enabled, transmitter is automatically switched using RTS pin, collision is detected by UART hardware (note: no event is generated on collision, limitation of esp-idf) + - `uart.MODE_RS485_APP_CONTROL` receiver/transmitter control is left to the application + - `uart.MODE_RS485_HALF_DUPLEX` receiver/transmitter are controlled by RTS pin + - `uart.MODE_IRDA` + +#### Returns +`nil` + ## uart.write() Write string or byte to the UART.