@@ -32,10 +32,6 @@ typedef struct {
32
32
uint8_t armed ;
33
33
} softuart_t ;
34
34
35
- typedef struct {
36
- softuart_t * softuart ;
37
- } softuart_userdata ;
38
-
39
35
// Array of pointers to SoftUART instances
40
36
softuart_t * softuart_gpio_instances [SOFTUART_GPIO_COUNT ] = {NULL };
41
37
// Array of callback reference to be able to find which callback is used to which rx pin
@@ -60,7 +56,7 @@ static inline uint8_t checkbit(uint8_t data, uint8_t bit)
60
56
}
61
57
}
62
58
63
- uint32_t ICACHE_RAM_ATTR softuart_intr_handler (uint32_t ret_gpio_status )
59
+ static uint32_t ICACHE_RAM_ATTR softuart_intr_handler (uint32_t ret_gpio_status )
64
60
{
65
61
// Disable all interrupts
66
62
ets_intr_lock ();
@@ -74,12 +70,12 @@ uint32_t ICACHE_RAM_ATTR softuart_intr_handler(uint32_t ret_gpio_status)
74
70
// Load instance which has rx pin on interrupt pin attached
75
71
softuart_t * s = softuart_gpio_instances [pin_num_inv [gpio_bit ]];
76
72
if (s == NULL ) continue ;
77
- if (softuart_rx_cb_ref [pin_num_inv [gpio_bit ]] == LUA_NOREF ) continue ;
78
- if (!s -> armed ) continue ;
79
- // There is SoftUART rx instance on that pin
80
73
// Clear interrupt status on that pin
81
74
GPIO_REG_WRITE (GPIO_STATUS_W1TC_ADDRESS , gpio_status & (1 << pin_num [s -> pin_rx ]));
82
75
ret_gpio_status &= ~(1 << pin_num [s -> pin_rx ]);
76
+ if (softuart_rx_cb_ref [pin_num_inv [gpio_bit ]] == LUA_NOREF ) continue ;
77
+ if (!s -> armed ) continue ;
78
+ // There is an armed SoftUART rx instance on that pin
83
79
// Start listening to transmission
84
80
// TODO: inverted
85
81
if (! (GPIO_INPUT_GET (GPIO_ID_PIN (pin_num [s -> pin_rx ])))) {
@@ -156,6 +152,7 @@ static void softuart_putchar(softuart_t *s, char data)
156
152
// Set start bit
157
153
GPIO_OUTPUT_SET (GPIO_ID_PIN (pin_num [s -> pin_tx ]), 0 );
158
154
for (uint32_t i = 0 ; i < 8 ; i ++ ) {
155
+ // Wait to transmit another bit
159
156
while ((uint32_t )(asm_ccount () - start_time ) < s -> bit_time );
160
157
161
158
GPIO_OUTPUT_SET (GPIO_ID_PIN (pin_num [s -> pin_tx ]), checkbit (data , 1 << i ));
@@ -172,9 +169,8 @@ static void softuart_putchar(softuart_t *s, char data)
172
169
ets_intr_unlock ();
173
170
}
174
171
175
- static void softuart_init (softuart_t * s )
172
+ static int softuart_init (softuart_t * s )
176
173
{
177
- NODE_DBG ("SoftUART initialize gpio\n" );
178
174
179
175
// Init tx pin
180
176
if (s -> pin_tx != 0xFF ){
@@ -185,12 +181,17 @@ static void softuart_init(softuart_t *s)
185
181
// Init rx pin
186
182
if (s -> pin_rx != 0xFF ){
187
183
platform_gpio_mode (s -> pin_rx , PLATFORM_GPIO_INT , PLATFORM_GPIO_PULLUP );
188
- uint32_t mask = 1 << pin_num [s -> pin_rx ];
189
- platform_gpio_register_intr_hook (mask , softuart_intr_handler );
190
-
191
- softuart_gpio_instances [s -> pin_rx ] = s ;
192
184
// Enable interrupt for pin on falling edge
193
185
platform_gpio_intr_init (s -> pin_rx , GPIO_PIN_INTR_NEGEDGE );
186
+ softuart_gpio_instances [s -> pin_rx ] = s ;
187
+ // Preserve other rx gpio pins
188
+ uint32_t mask = 0 ;
189
+ for (uint8_t i = 0 ; i < SOFTUART_GPIO_COUNT ; i ++ ) {
190
+ if (softuart_gpio_instances [i ] != NULL ) {
191
+ mask = mask | (1 << pin_num [softuart_gpio_instances [i ]-> pin_rx ]);
192
+ }
193
+ }
194
+ return platform_gpio_register_intr_hook (mask , softuart_intr_handler );
194
195
}
195
196
}
196
197
@@ -199,70 +200,59 @@ static int softuart_setup(lua_State *L)
199
200
{
200
201
uint32_t baudrate ;
201
202
uint8_t tx_gpio_id , rx_gpio_id ;
202
- uint8_t stack = 1 ;
203
- softuart_userdata * suart = NULL ;
204
-
205
- NODE_DBG ("SoftUART setup called\n" );
206
-
207
- if (lua_isnumber (L , stack )) {
208
- baudrate = (uint32_t )luaL_checkinteger ( L , stack );
209
- //230400 Is the max baudrate the author of Arduino-Esp8266-Software-UART tested
210
- if (baudrate <= 0 || baudrate > 230400 ) {
211
- return luaL_error (L , "Invalid baud rate" );
212
- }
213
- stack ++ ;
214
- } else {
215
- return luaL_error (L , "Invalid argument type" );
216
- }
203
+ softuart_t * softuart = NULL ;
204
+
205
+ NODE_DBG ("[SoftUART]: setup called\n" );
206
+ baudrate = (uint32_t )luaL_checkinteger (L , 1 ); // Get Baudrate from
207
+ luaL_argcheck (L , (baudrate > 0 && baudrate < 230400 ), 1 , "Invalid baud rate" );
208
+ lua_remove (L , 1 ); // Remove baudrate argument from stack
209
+ if (lua_gettop (L ) == 2 ) { // 2 arguments: 1st can be nil
210
+ if (lua_isnil (L , 1 )) {
211
+ tx_gpio_id = 0xFF ;
212
+ } else {
213
+ tx_gpio_id = (uint8_t )luaL_checkinteger (L , 1 );
214
+ luaL_argcheck (L , (platform_gpio_exists (tx_gpio_id ) && tx_gpio_id != 0 )
215
+ , 2 , "Invalid SoftUART tx GPIO" );
216
+ }
217
+ rx_gpio_id = (uint8_t )luaL_checkinteger (L , 2 );
218
+ luaL_argcheck (L , (platform_gpio_exists (rx_gpio_id ) && rx_gpio_id != 0 )
219
+ , 3 , "Invalid SoftUART rx GPIO" );
220
+ luaL_argcheck (L , softuart_gpio_instances [rx_gpio_id ] == NULL
221
+ , 3 , "SoftUART rx already configured on the pin" );
217
222
218
- if (lua_isnumber (L , stack )) {
219
- tx_gpio_id = (uint8_t )luaL_checkinteger ( L , stack );
220
- if (!platform_gpio_exists (tx_gpio_id ) || tx_gpio_id == 0 ) {
221
- return luaL_error (L , "SoftUART tx GPIO not valid" );
222
- }
223
- stack ++ ;
224
- } else {
225
- tx_gpio_id = 0xFF ;
226
- stack ++ ;
227
- }
228
- if (lua_isnumber (L , stack )) {
229
- rx_gpio_id = (uint8_t )luaL_checkinteger ( L , stack );
230
- if (!platform_gpio_exists (rx_gpio_id ) || rx_gpio_id == 0 ) {
231
- return luaL_error (L , "SoftUART rx GPIO not valid" );
232
- }
233
- if (softuart_gpio_instances [rx_gpio_id ] != NULL ) {
234
- return luaL_error ( L , "SoftUART rx already configured on the pin." );
235
- }
236
- } else {
223
+ } else if (lua_gettop (L ) == 1 ) { // 1 argument: transmit part only
237
224
rx_gpio_id = 0xFF ;
225
+ tx_gpio_id = (uint8_t )luaL_checkinteger (L , 1 );
226
+ luaL_argcheck (L , (platform_gpio_exists (tx_gpio_id ) && tx_gpio_id != 0 )
227
+ , 2 , "Invalid SoftUART tx GPIO" );
228
+ } else {
229
+ // SoftUART object without receive and transmit part would be useless
230
+ return luaL_error (L , "Not enough arguments" );
238
231
}
239
232
240
- suart = (softuart_userdata * )lua_newuserdata (L , sizeof (softuart_userdata ));
241
- suart -> softuart = malloc (sizeof (softuart_t ));
242
- if (!suart -> softuart ) {
243
- free (suart -> softuart );
244
- suart -> softuart = NULL ;
245
- return luaL_error (L , "Not enough memory" );
246
- }
247
- suart -> softuart -> pin_rx = rx_gpio_id ;
248
- suart -> softuart -> pin_tx = tx_gpio_id ;
249
- suart -> softuart -> need_len = RX_BUFF_SIZE ;
250
- suart -> softuart -> armed = 0 ;
233
+ softuart = (softuart_t * )lua_newuserdata (L , sizeof (softuart_t ));
234
+ softuart -> pin_rx = rx_gpio_id ;
235
+ softuart -> pin_tx = tx_gpio_id ;
236
+ softuart -> need_len = RX_BUFF_SIZE ;
237
+ softuart -> armed = 0 ;
251
238
252
239
// Set buffer
253
- suart -> softuart -> buffer .buffer_first = 0 ;
254
- suart -> softuart -> buffer .buffer_last = 0 ;
255
- suart -> softuart -> buffer .bytes_count = 0 ;
256
- suart -> softuart -> buffer .buffer_overflow = 0 ;
240
+ softuart -> buffer .buffer_first = 0 ;
241
+ softuart -> buffer .buffer_last = 0 ;
242
+ softuart -> buffer .bytes_count = 0 ;
243
+ softuart -> buffer .buffer_overflow = 0 ;
257
244
258
245
// Set bit time
259
- suart -> softuart -> bit_time = system_get_cpu_freq () * 1000000 / baudrate ;
246
+ softuart -> bit_time = system_get_cpu_freq () * 1000000 / baudrate ;
260
247
261
248
// Set metatable
262
249
luaL_getmetatable (L , "softuart.port" );
263
250
lua_setmetatable (L , -2 );
264
251
// Init SoftUART
265
- softuart_init (suart -> softuart );
252
+ int result = softuart_init (softuart );
253
+ if (result == 0 ) {
254
+ luaL_error (L , "Couldn't register interrupt" );
255
+ }
266
256
return 1 ;
267
257
}
268
258
@@ -293,103 +283,59 @@ static void softuart_rx_callback(task_param_t arg)
293
283
// Arguments: event name, minimum buffer filled to run callback, callback function
294
284
static int softuart_on (lua_State * L )
295
285
{
296
- NODE_DBG ("SoftUART on called\n" );
297
- softuart_userdata * suart = NULL ;
286
+ NODE_DBG ("[SoftUART] on: called\n" );
298
287
size_t name_len , arg_len ;
299
- uint8_t stack = 1 ;
300
288
301
- suart = (softuart_userdata * )luaL_checkudata (L , 1 , "softuart.port" );
302
- luaL_argcheck (L , suart , stack , "softuart.port expected" );
303
- if (suart == NULL ) {
304
- NODE_DBG ("Userdata is nil\n" );
305
- return 0 ;
306
- }
307
- stack ++ ;
308
-
309
- const char * method = luaL_checklstring (L , stack , & name_len );
310
- if (method == NULL )
311
- return luaL_error (L , "Wrong argument type" );
312
- stack ++ ;
313
-
314
- if (lua_type (L , stack ) == LUA_TNUMBER ) {
315
- suart -> softuart -> need_len = (uint16_t )luaL_checkinteger ( L , stack );
316
- stack ++ ;
317
- suart -> softuart -> end_char = 0 ;
318
- if (suart -> softuart -> need_len > SOFTUART_MAX_RX_BUFF ) {
319
- suart -> softuart -> need_len = 0 ;
320
- return luaL_error (L , "Argument bigger than SoftUART buffer" );
321
- }
322
- suart -> softuart -> armed = 1 ;
323
- } else if (lua_isstring (L , stack )) {
324
- const char * end = luaL_checklstring (L , stack , & arg_len );
325
- stack ++ ;
326
- if ( arg_len != 1 ) {
327
- return luaL_error (L , "Wrong end char length" );
328
- }
329
- suart -> softuart -> end_char = end [0 ];
330
- suart -> softuart -> need_len = 0 ;
331
- suart -> softuart -> armed = 1 ;
289
+ softuart_t * softuart = (softuart_t * )luaL_checkudata (L , 1 , "softuart.port" );
290
+ const char * method = luaL_checklstring (L , 2 , & name_len );
291
+
292
+ if (lua_isnumber (L , 3 )) {
293
+ luaL_argcheck (L , luaL_checkinteger (L , 3 ) < SOFTUART_MAX_RX_BUFF ,
294
+ 2 , "Argument bigger than SoftUART buffer" );
295
+ softuart -> end_char = 0 ;
296
+ softuart -> need_len = (uint16_t ) luaL_checkinteger (L , 3 );
297
+ softuart -> armed = 1 ;
298
+ } else if (lua_isstring (L , 3 )) {
299
+ const char * end = luaL_checklstring (L , 3 , & arg_len );
300
+ luaL_argcheck (L , arg_len == 1 , 3 , "Wrong end char length" );
301
+ softuart -> end_char = end [0 ];
302
+ softuart -> need_len = 0 ;
303
+ softuart -> armed = 1 ;
332
304
} else {
333
305
return luaL_error (L , "Wrong argument type" );
334
306
}
335
307
336
-
337
- if (lua_type (L , stack ) == LUA_TFUNCTION ) {
338
- lua_pushvalue (L , stack ); // Copy to top of the stack
339
- } else {
340
- lua_pushnil (L );
341
- }
342
-
343
- if (name_len == 4 && strcmp (method , "data" ) == 0 ) {
344
-
345
- if (suart -> softuart -> pin_rx == 0xFF ) {
346
- return luaL_error (L , "Rx pin was not declared" );
347
- }
348
-
349
- if (softuart_rx_cb_ref [suart -> softuart -> pin_rx ] != LUA_NOREF ) {
350
- luaL_unref (L , LUA_REGISTRYINDEX , softuart_rx_cb_ref [suart -> softuart -> pin_rx ]);
351
- softuart_rx_cb_ref [suart -> softuart -> pin_rx ] = LUA_NOREF ;
352
- }
353
- if (! lua_isnil (L , -1 )) {
354
- softuart_rx_cb_ref [suart -> softuart -> pin_rx ] = luaL_ref (L , LUA_REGISTRYINDEX );
355
- } else {
356
- lua_pop (L , 1 );
357
- }
358
- } else {
359
- lua_pop (L , 1 );
360
- return luaL_error (L , "Method not supported" );
308
+ luaL_argcheck (L , lua_isfunction (L , 4 ), -1 , "No callback function specified" );
309
+ luaL_argcheck (L , (name_len == 4 && strcmp (method , "data" ) == 0 ), 2 , "Method not supported" );
310
+ luaL_argcheck (L , softuart -> pin_rx != 0xFF , 1 , "Rx pin was not declared" );
311
+ lua_settop (L , 4 ); // Move to the top of the stack
312
+ if (softuart_rx_cb_ref [softuart -> pin_rx ] != LUA_NOREF ) {
313
+ // Remove old callback and add new one
314
+ luaL_unref (L , LUA_REGISTRYINDEX , softuart_rx_cb_ref [softuart -> pin_rx ]);
361
315
}
316
+ // Register callback
317
+ softuart_rx_cb_ref [softuart -> pin_rx ] = luaL_ref (L , LUA_REGISTRYINDEX );
318
+
362
319
return 0 ;
363
320
}
364
321
365
322
static int softuart_write (lua_State * L )
366
323
{
367
- NODE_DBG ("SoftUART write called\n" );
368
- softuart_userdata * suart = NULL ;
369
- uint8_t stack = 1 ;
324
+ softuart_t * softuart = NULL ;
370
325
size_t str_len ;
371
- suart = (softuart_userdata * )luaL_checkudata (L , 1 , "softuart.port" );
372
- luaL_argcheck (L , suart , stack , "softuart.port expected" );
373
- if (suart == NULL ) {
374
- NODE_DBG ("Userdata is nil\n" );
375
- return 0 ;
376
- }
377
- stack ++ ;
378
- if (suart -> softuart -> pin_tx == 0xFF ) {
379
- return luaL_error (L , "Tx pin was not declared" );
380
- }
381
- if (lua_type (L , stack ) == LUA_TNUMBER ) {
326
+ softuart = (softuart_t * ) luaL_checkudata (L , 1 , "softuart.port" );
327
+ luaL_argcheck (L , softuart -> pin_tx != 0xFF , 1 , "Tx pin was not declared" );
328
+
329
+ if (lua_isnumber (L , 2 )) {
382
330
// Send byte
383
- uint32_t byte = (uint32_t )luaL_checkinteger ( L , stack );
384
- if (byte > 255 ) {
385
- return luaL_error (L , "Integer too large for a byte" );
386
- }
387
- softuart_putchar (suart -> softuart , (char )byte );
388
- } else if (lua_isstring (L , stack )) {
331
+ uint32_t byte = (uint32_t )luaL_checkinteger (L , 2 );
332
+ luaL_argcheck (L , byte < 256 , 2 , "Integer too large for a byte" );
333
+ softuart_putchar (softuart , (char )byte );
334
+ } else if (lua_isstring (L , 2 )) {
389
335
// Send string
390
- const char * string = luaL_checklstring (L , stack , & str_len );
336
+ const char * string = luaL_checklstring (L , 2 , & str_len );
391
337
for (size_t i = 0 ; i < str_len ; i ++ ) {
392
- softuart_putchar (suart -> softuart , string [i ]);
338
+ softuart_putchar (softuart , string [i ]);
393
339
}
394
340
} else {
395
341
return luaL_error (L , "Wrong argument type" );
@@ -400,17 +346,11 @@ static int softuart_write(lua_State *L)
400
346
static int softuart_gcdelete (lua_State * L )
401
347
{
402
348
NODE_DBG ("SoftUART GC called\n" );
403
- softuart_userdata * suart = NULL ;
404
- suart = (softuart_userdata * )luaL_checkudata (L , 1 , "softuart.port" );
405
- luaL_argcheck (L , suart , 1 , "softuart.port expected" );
406
- if (suart == NULL ) {
407
- NODE_DBG ("Userdata is nil\n" );
408
- return 0 ;
409
- }
410
- softuart_gpio_instances [suart -> softuart -> pin_rx ] = NULL ;
411
- luaL_unref (L , LUA_REGISTRYINDEX , softuart_rx_cb_ref [suart -> softuart -> pin_rx ]);
412
- softuart_rx_cb_ref [suart -> softuart -> pin_rx ] = LUA_NOREF ;
413
- free (suart -> softuart );
349
+ softuart_t * softuart = NULL ;
350
+ softuart = (softuart_t * ) luaL_checkudata (L , 1 , "softuart.port" );
351
+ softuart_gpio_instances [softuart -> pin_rx ] = NULL ;
352
+ luaL_unref (L , LUA_REGISTRYINDEX , softuart_rx_cb_ref [softuart -> pin_rx ]);
353
+ softuart_rx_cb_ref [softuart -> pin_rx ] = LUA_NOREF ;
414
354
return 0 ;
415
355
}
416
356
0 commit comments