1616#define MODE_DUAL 1
1717
1818
19-
20-
21-
22-
2319// Init UART1 to be able to stream WS2812 data to GPIO2 pin
2420// If DUAL mode is selected, init UART0 to stream to TXD0 as well
2521// You HAVE to redirect LUA's output somewhere else
@@ -168,15 +164,15 @@ static int ws2812_write(lua_State* L) {
168164 return 0 ;
169165}
170166
171- static ptrdiff_t posrelat (ptrdiff_t pos , size_t len ) {
167+ static ptrdiff_t posrelat (ptrdiff_t pos , size_t len ) {
172168 /* relative string position: negative means back from end */
173169 if (pos < 0 ) pos += (ptrdiff_t )len + 1 ;
174- return ( pos >= 0 ) ? pos : 0 ;
170+ return MIN ( MAX ( pos , 1 ), len ) ;
175171}
176172
177173static ws2812_buffer * allocate_buffer (lua_State * L , int leds , int colorsPerLed ) {
178174 // Allocate memory
179- size_t size = sizeof (ws2812_buffer ) + colorsPerLed * leds * sizeof ( uint8_t ) ;
175+ size_t size = sizeof (ws2812_buffer ) + colorsPerLed * leds ;
180176 ws2812_buffer * buffer = (ws2812_buffer * )lua_newuserdata (L , size );
181177
182178 // Associate its metatable
@@ -245,17 +241,11 @@ static int ws2812_buffer_fill_lua(lua_State* L) {
245241 return 0 ;
246242}
247243
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 ) {
255245 uint8_t * p = & buffer -> values [0 ];
256246 int val = 0 ;
257247 int i ;
258- for (i = 0 ; i < buffer -> size * buffer -> colorsPerLed ; i ++ )
248+ for (i = 0 ; i < buffer -> size * buffer -> colorsPerLed ; i ++ )
259249 {
260250 if (direction == FADE_OUT )
261251 {
@@ -269,78 +259,101 @@ static int ws2812_buffer_fade(lua_State* L) {
269259 * p ++ = val ;
270260 }
271261 }
262+ }
272263
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 ;
274274}
275275
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+ }
276284
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 ){
278286
279287 ptrdiff_t start = posrelat (pos_start , buffer -> size );
280288 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 ;
283289
284290 start -- ;
285291 int size = end - start ;
286292 size_t offset = start * buffer -> colorsPerLed ;
287293
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" );
289295
290296 int shift = shiftValue >= 0 ? shiftValue : - shiftValue ;
291297
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 ;
300298 size_t shift_len , remaining_len ;
301299 // calculate length of shift section and remaining section
302300 shift_len = shift * buffer -> colorsPerLed ;
303301 remaining_len = (size - shift )* buffer -> colorsPerLed ;
304302
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 )
306324 {
307325 // 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 );
309327 // 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 );
311329 // Fill beginning with temp data
312- if (shift_type == SHIFT_LOGICAL )
330+ if (prepare -> shift_type == SHIFT_LOGICAL )
313331 {
314- memset (& buffer -> values [offset ], 0 , shift_len );
332+ memset (& prepare -> buffer -> values [prepare -> offset ], 0 , prepare -> shift_len );
315333 }
316334 else
317335 {
318- memcpy (& buffer -> values [offset ], tmp_pixels , shift_len );
336+ memcpy (& prepare -> buffer -> values [prepare -> offset ], prepare -> tmp_pixels , prepare -> shift_len );
319337 }
320338 }
321339 else
322340 {
323341 // 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 );
325343 // 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 );
327345 // Fill beginning with temp data
328- if (shift_type == SHIFT_LOGICAL )
346+ if (prepare -> shift_type == SHIFT_LOGICAL )
329347 {
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 );
331349 }
332350 else
333351 {
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 );
335353 }
336354 }
337- // Free memory
338- free (tmp_pixels );
339-
340- return 0 ;
341355}
342356
343-
344357static int ws2812_buffer_shift_lua (lua_State * L ) {
345358
346359 ws2812_buffer * buffer = (ws2812_buffer * )luaL_checkudata (L , 1 , "ws2812.buffer" );
@@ -351,11 +364,10 @@ static int ws2812_buffer_shift_lua(lua_State* L) {
351364 const int pos_end = luaL_optinteger (L , 5 , -1 );
352365
353366
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 );
355368 return 0 ;
356369}
357370
358-
359371static int ws2812_buffer_dump (lua_State * L ) {
360372 ws2812_buffer * buffer = (ws2812_buffer * )luaL_checkudata (L , 1 , "ws2812.buffer" );
361373
@@ -366,8 +378,7 @@ static int ws2812_buffer_dump(lua_State* L) {
366378
367379static int ws2812_buffer_replace (lua_State * L ) {
368380 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 );
371382
372383 uint8_t * src ;
373384 size_t srcLen ;
@@ -425,8 +436,8 @@ static int ws2812_buffer_mix(lua_State* L) {
425436 val += (int32_t )(source [src ].values [i ] * source [src ].factor );
426437 }
427438
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
430441
431442 if (val < 0 ) {
432443 val = 0 ;
@@ -501,7 +512,7 @@ static int ws2812_buffer_set(lua_State* L) {
501512 // Overflow check
502513 if ( buffer -> colorsPerLed * led + len > buffer -> colorsPerLed * buffer -> size )
503514 {
504- return luaL_error (L , "string size will exceed strip length" );
515+ return luaL_error (L , "string size will exceed strip length" );
505516 }
506517
507518 memcpy (& buffer -> values [buffer -> colorsPerLed * led ], buf , len );
@@ -531,8 +542,6 @@ static int ws2812_buffer_sub(lua_State* L) {
531542 size_t l = lhs -> size ;
532543 ptrdiff_t start = posrelat (luaL_checkinteger (L , 2 ), l );
533544 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 ;
536545 if (start <= end ) {
537546 ws2812_buffer * result = allocate_buffer (L , end - start + 1 , lhs -> colorsPerLed );
538547 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) {
591600 return 1 ;
592601}
593602
594-
595603LROT_BEGIN (ws2812_buffer )
596604 LROT_FUNCENTRY ( dump , ws2812_buffer_dump )
597- LROT_FUNCENTRY ( fade , ws2812_buffer_fade )
605+ LROT_FUNCENTRY ( fade , ws2812_buffer_fade_lua )
598606 LROT_FUNCENTRY ( fill , ws2812_buffer_fill_lua )
599607 LROT_FUNCENTRY ( get , ws2812_buffer_get )
600608 LROT_FUNCENTRY ( replace , ws2812_buffer_replace )
@@ -609,8 +617,6 @@ LROT_BEGIN(ws2812_buffer)
609617 LROT_FUNCENTRY ( __tostring , ws2812_buffer_tostring )
610618LROT_END ( ws2812_buffer , ws2812_buffer , LROT_MASK_INDEX )
611619
612-
613-
614620LROT_BEGIN (ws2812 )
615621 LROT_FUNCENTRY ( init , ws2812_init )
616622 LROT_FUNCENTRY ( newBuffer , ws2812_new_buffer )
@@ -623,7 +629,6 @@ LROT_BEGIN(ws2812)
623629 LROT_NUMENTRY ( SHIFT_CIRCULAR , SHIFT_CIRCULAR )
624630LROT_END ( ws2812 , NULL , 0 )
625631
626-
627632int luaopen_ws2812 (lua_State * L ) {
628633 // TODO: Make sure that the GPIO system is initialized
629634 luaL_rometatable (L , "ws2812.buffer" , LROT_TABLEREF (ws2812_buffer ));
0 commit comments