16
16
#define MODE_DUAL 1
17
17
18
18
19
-
20
-
21
-
22
-
23
19
// Init UART1 to be able to stream WS2812 data to GPIO2 pin
24
20
// If DUAL mode is selected, init UART0 to stream to TXD0 as well
25
21
// You HAVE to redirect LUA's output somewhere else
@@ -168,15 +164,15 @@ static int ws2812_write(lua_State* L) {
168
164
return 0 ;
169
165
}
170
166
171
- static ptrdiff_t posrelat (ptrdiff_t pos , size_t len ) {
167
+ static ptrdiff_t posrelat (ptrdiff_t pos , size_t len ) {
172
168
/* relative string position: negative means back from end */
173
169
if (pos < 0 ) pos += (ptrdiff_t )len + 1 ;
174
- return ( pos >= 0 ) ? pos : 0 ;
170
+ return MIN ( MAX ( pos , 1 ), len ) ;
175
171
}
176
172
177
173
static ws2812_buffer * allocate_buffer (lua_State * L , int leds , int colorsPerLed ) {
178
174
// Allocate memory
179
- size_t size = sizeof (ws2812_buffer ) + colorsPerLed * leds * sizeof ( uint8_t ) ;
175
+ size_t size = sizeof (ws2812_buffer ) + colorsPerLed * leds ;
180
176
ws2812_buffer * buffer = (ws2812_buffer * )lua_newuserdata (L , size );
181
177
182
178
// Associate its metatable
@@ -245,17 +241,11 @@ static int ws2812_buffer_fill_lua(lua_State* L) {
245
241
return 0 ;
246
242
}
247
243
248
- static int ws2812_buffer_fade (lua_State * L ) {
249
- ws2812_buffer * buffer = (ws2812_buffer * )luaL_checkudata (L , 1 , "ws2812.buffer" );
250
- const int fade = luaL_checkinteger (L , 2 );
251
- unsigned direction = luaL_optinteger ( L , 3 , FADE_OUT );
252
-
253
- luaL_argcheck (L , fade > 0 , 2 , "fade value should be a strict positive number" );
254
-
244
+ void ws2812_buffer_fade (ws2812_buffer * buffer , int fade , unsigned direction ) {
255
245
uint8_t * p = & buffer -> values [0 ];
256
246
int val = 0 ;
257
247
int i ;
258
- for (i = 0 ; i < buffer -> size * buffer -> colorsPerLed ; i ++ )
248
+ for (i = 0 ; i < buffer -> size * buffer -> colorsPerLed ; i ++ )
259
249
{
260
250
if (direction == FADE_OUT )
261
251
{
@@ -269,78 +259,101 @@ static int ws2812_buffer_fade(lua_State* L) {
269
259
* p ++ = val ;
270
260
}
271
261
}
262
+ }
272
263
273
- return 0 ;
264
+ static int ws2812_buffer_fade_lua (lua_State * L ) {
265
+ ws2812_buffer * buffer = (ws2812_buffer * )luaL_checkudata (L , 1 , "ws2812.buffer" );
266
+ const int fade = luaL_checkinteger (L , 2 );
267
+ unsigned direction = luaL_optinteger ( L , 3 , FADE_OUT );
268
+
269
+ luaL_argcheck (L , fade > 0 , 2 , "fade value should be a strict positive number" );
270
+
271
+ ws2812_buffer_fade (buffer , fade , direction );
272
+
273
+ return 0 ;
274
274
}
275
275
276
+ int ws2812_buffer_shift (lua_State * L , ws2812_buffer * buffer , int shiftValue , unsigned shift_type , int pos_start , int pos_end ){
277
+
278
+ ws2812_buffer_shift_prepare * prepare = ws2812_buffer_get_shift_prepare (L , buffer , shiftValue , shift_type , pos_start , pos_end );
279
+ ws2812_buffer_shift_prepared (prepare );
280
+ // Free memory
281
+ luaM_free (L , prepare );
282
+ return 0 ;
283
+ }
276
284
277
- int ws2812_buffer_shift ( ws2812_buffer * buffer , int shiftValue , unsigned shift_type , int pos_start , int pos_end ) {
285
+ ws2812_buffer_shift_prepare * ws2812_buffer_get_shift_prepare ( lua_State * L , ws2812_buffer * buffer , int shiftValue , unsigned shift_type , int pos_start , int pos_end ){
278
286
279
287
ptrdiff_t start = posrelat (pos_start , buffer -> size );
280
288
ptrdiff_t end = posrelat (pos_end , buffer -> size );
281
- if (start < 1 ) start = 1 ;
282
- if (end > (ptrdiff_t )buffer -> size ) end = (ptrdiff_t )buffer -> size ;
283
289
284
290
start -- ;
285
291
int size = end - start ;
286
292
size_t offset = start * buffer -> colorsPerLed ;
287
293
288
- // luaL_argcheck(L, shiftValue > 0-size && shiftValue < size, 2, "shifting more elements than buffer size");
294
+ luaL_argcheck (L , shiftValue >= 0 - size && shiftValue <= size , 2 , "shifting more elements than buffer size" );
289
295
290
296
int shift = shiftValue >= 0 ? shiftValue : - shiftValue ;
291
297
292
- // check if we want to shift at all
293
- if (shift == 0 || size <= 0 )
294
- {
295
- return 0 ;
296
- }
297
-
298
- uint8_t * tmp_pixels = malloc (buffer -> colorsPerLed * sizeof (uint8_t ) * shift );
299
- int i ,j ;
300
298
size_t shift_len , remaining_len ;
301
299
// calculate length of shift section and remaining section
302
300
shift_len = shift * buffer -> colorsPerLed ;
303
301
remaining_len = (size - shift )* buffer -> colorsPerLed ;
304
302
305
- if (shiftValue > 0 )
303
+ ws2812_buffer_shift_prepare * prepare = luaM_malloc (L , sizeof (ws2812_buffer_shift_prepare ) + shift_len );
304
+ prepare -> offset = offset ;
305
+ prepare -> tmp_pixels = (uint8_t * )(prepare + 1 );
306
+ prepare -> shiftValue = shiftValue ;
307
+ prepare -> shift_len = shift_len ;
308
+ prepare -> remaining_len = remaining_len ;
309
+ prepare -> shift_type = shift_type ;
310
+ prepare -> buffer = buffer ;
311
+
312
+ return prepare ;
313
+ }
314
+
315
+ void ws2812_buffer_shift_prepared (ws2812_buffer_shift_prepare * prepare ) {
316
+
317
+ // check if we want to shift at all
318
+ if (prepare -> shift_len == 0 || (prepare -> shift_len + prepare -> remaining_len ) <= 0 )
319
+ {
320
+ return ;
321
+ }
322
+
323
+ if (prepare -> shiftValue > 0 )
306
324
{
307
325
// Store the values which are moved out of the array (last n pixels)
308
- memcpy (tmp_pixels , & buffer -> values [offset + ( size - shift ) * buffer -> colorsPerLed ], shift_len );
326
+ memcpy (prepare -> tmp_pixels , & prepare -> buffer -> values [prepare -> offset + prepare -> remaining_len ], prepare -> shift_len );
309
327
// Move pixels to end
310
- os_memmove (& buffer -> values [offset + shift * buffer -> colorsPerLed ], & buffer -> values [offset ], remaining_len );
328
+ os_memmove (& prepare -> buffer -> values [prepare -> offset + prepare -> shift_len ], & prepare -> buffer -> values [prepare -> offset ], prepare -> remaining_len );
311
329
// Fill beginning with temp data
312
- if (shift_type == SHIFT_LOGICAL )
330
+ if (prepare -> shift_type == SHIFT_LOGICAL )
313
331
{
314
- memset (& buffer -> values [offset ], 0 , shift_len );
332
+ memset (& prepare -> buffer -> values [prepare -> offset ], 0 , prepare -> shift_len );
315
333
}
316
334
else
317
335
{
318
- memcpy (& buffer -> values [offset ], tmp_pixels , shift_len );
336
+ memcpy (& prepare -> buffer -> values [prepare -> offset ], prepare -> tmp_pixels , prepare -> shift_len );
319
337
}
320
338
}
321
339
else
322
340
{
323
341
// Store the values which are moved out of the array (last n pixels)
324
- memcpy (tmp_pixels , & buffer -> values [offset ], shift_len );
342
+ memcpy (prepare -> tmp_pixels , & prepare -> buffer -> values [prepare -> offset ], prepare -> shift_len );
325
343
// Move pixels to end
326
- os_memmove (& buffer -> values [offset ], & buffer -> values [offset + shift * buffer -> colorsPerLed ], remaining_len );
344
+ os_memmove (& prepare -> buffer -> values [prepare -> offset ], & prepare -> buffer -> values [prepare -> offset + prepare -> shift_len ], prepare -> remaining_len );
327
345
// Fill beginning with temp data
328
- if (shift_type == SHIFT_LOGICAL )
346
+ if (prepare -> shift_type == SHIFT_LOGICAL )
329
347
{
330
- memset (& buffer -> values [offset + ( size - shift ) * buffer -> colorsPerLed ], 0 , shift_len );
348
+ memset (& prepare -> buffer -> values [prepare -> offset + prepare -> remaining_len ], 0 , prepare -> shift_len );
331
349
}
332
350
else
333
351
{
334
- memcpy (& buffer -> values [offset + ( size - shift ) * buffer -> colorsPerLed ], tmp_pixels , shift_len );
352
+ memcpy (& prepare -> buffer -> values [prepare -> offset + prepare -> remaining_len ], prepare -> tmp_pixels , prepare -> shift_len );
335
353
}
336
354
}
337
- // Free memory
338
- free (tmp_pixels );
339
-
340
- return 0 ;
341
355
}
342
356
343
-
344
357
static int ws2812_buffer_shift_lua (lua_State * L ) {
345
358
346
359
ws2812_buffer * buffer = (ws2812_buffer * )luaL_checkudata (L , 1 , "ws2812.buffer" );
@@ -351,11 +364,10 @@ static int ws2812_buffer_shift_lua(lua_State* L) {
351
364
const int pos_end = luaL_optinteger (L , 5 , -1 );
352
365
353
366
354
- ws2812_buffer_shift (buffer , shiftValue , shift_type , pos_start , pos_end );
367
+ ws2812_buffer_shift (L , buffer , shiftValue , shift_type , pos_start , pos_end );
355
368
return 0 ;
356
369
}
357
370
358
-
359
371
static int ws2812_buffer_dump (lua_State * L ) {
360
372
ws2812_buffer * buffer = (ws2812_buffer * )luaL_checkudata (L , 1 , "ws2812.buffer" );
361
373
@@ -366,8 +378,7 @@ static int ws2812_buffer_dump(lua_State* L) {
366
378
367
379
static int ws2812_buffer_replace (lua_State * L ) {
368
380
ws2812_buffer * buffer = (ws2812_buffer * )luaL_checkudata (L , 1 , "ws2812.buffer" );
369
- size_t l = buffer -> size ;
370
- ptrdiff_t start = posrelat (luaL_optinteger (L , 3 , 1 ), l );
381
+ ptrdiff_t start = posrelat (luaL_optinteger (L , 3 , 1 ), buffer -> size );
371
382
372
383
uint8_t * src ;
373
384
size_t srcLen ;
@@ -425,8 +436,8 @@ static int ws2812_buffer_mix(lua_State* L) {
425
436
val += (int32_t )(source [src ].values [i ] * source [src ].factor );
426
437
}
427
438
428
- val += 128 ; // rounding istead of floor
429
- val >>= 8 ;
439
+ val += 128 ; // rounding istead of floor
440
+ val /= 256 ; // do not use implemetation dependant right shift
430
441
431
442
if (val < 0 ) {
432
443
val = 0 ;
@@ -501,7 +512,7 @@ static int ws2812_buffer_set(lua_State* L) {
501
512
// Overflow check
502
513
if ( buffer -> colorsPerLed * led + len > buffer -> colorsPerLed * buffer -> size )
503
514
{
504
- return luaL_error (L , "string size will exceed strip length" );
515
+ return luaL_error (L , "string size will exceed strip length" );
505
516
}
506
517
507
518
memcpy (& buffer -> values [buffer -> colorsPerLed * led ], buf , len );
@@ -531,8 +542,6 @@ static int ws2812_buffer_sub(lua_State* L) {
531
542
size_t l = lhs -> size ;
532
543
ptrdiff_t start = posrelat (luaL_checkinteger (L , 2 ), l );
533
544
ptrdiff_t end = posrelat (luaL_optinteger (L , 3 , -1 ), l );
534
- if (start < 1 ) start = 1 ;
535
- if (end > (ptrdiff_t )l ) end = (ptrdiff_t )l ;
536
545
if (start <= end ) {
537
546
ws2812_buffer * result = allocate_buffer (L , end - start + 1 , lhs -> colorsPerLed );
538
547
memcpy (result -> values , lhs -> values + lhs -> colorsPerLed * (start - 1 ), lhs -> colorsPerLed * (end - start + 1 ));
@@ -591,10 +600,9 @@ static int ws2812_buffer_tostring(lua_State* L) {
591
600
return 1 ;
592
601
}
593
602
594
-
595
603
LROT_BEGIN (ws2812_buffer )
596
604
LROT_FUNCENTRY ( dump , ws2812_buffer_dump )
597
- LROT_FUNCENTRY ( fade , ws2812_buffer_fade )
605
+ LROT_FUNCENTRY ( fade , ws2812_buffer_fade_lua )
598
606
LROT_FUNCENTRY ( fill , ws2812_buffer_fill_lua )
599
607
LROT_FUNCENTRY ( get , ws2812_buffer_get )
600
608
LROT_FUNCENTRY ( replace , ws2812_buffer_replace )
@@ -609,8 +617,6 @@ LROT_BEGIN(ws2812_buffer)
609
617
LROT_FUNCENTRY ( __tostring , ws2812_buffer_tostring )
610
618
LROT_END ( ws2812_buffer , ws2812_buffer , LROT_MASK_INDEX )
611
619
612
-
613
-
614
620
LROT_BEGIN (ws2812 )
615
621
LROT_FUNCENTRY ( init , ws2812_init )
616
622
LROT_FUNCENTRY ( newBuffer , ws2812_new_buffer )
@@ -623,7 +629,6 @@ LROT_BEGIN(ws2812)
623
629
LROT_NUMENTRY ( SHIFT_CIRCULAR , SHIFT_CIRCULAR )
624
630
LROT_END ( ws2812 , NULL , 0 )
625
631
626
-
627
632
int luaopen_ws2812 (lua_State * L ) {
628
633
// TODO: Make sure that the GPIO system is initialized
629
634
luaL_rometatable (L , "ws2812.buffer" , LROT_TABLEREF (ws2812_buffer ));
0 commit comments