pixel_pi 0.0.2 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/examples/strandtest.rb +12 -11
- data/ext/pixel_pi/leds.c +225 -19
- data/lib/pixel_pi/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c158234b67ccd01d55b48cf274c5ccb437ae77a
|
4
|
+
data.tar.gz: 5125b6c0d47381ca23ba8fc942ac73d22f9f3bbb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d010f3d8e722cb39aea7cd13cb78e92621628014799899bb08def77a0b0e1333dcf88362aa797f88ccdf2949b6d524f80bf23fa3302951e875e974fbf0e7a80b
|
7
|
+
data.tar.gz: acdac849b6517a354918be99681e360592a8edb77ca18a77bc741aba66008c56b42a62a760500a9026f6bd41c7d6d1a7794d5085765e3a39fee56637ef8129e0
|
data/.gitignore
CHANGED
data/examples/strandtest.rb
CHANGED
@@ -54,11 +54,11 @@ module StrandTest
|
|
54
54
|
spacing = opts.fetch(:spacing, 3)
|
55
55
|
|
56
56
|
iterations.times do
|
57
|
-
spacing.times do |
|
58
|
-
|
57
|
+
spacing.times do |sp|
|
58
|
+
self.clear
|
59
|
+
(sp...self.length).step(spacing) { |ii| self[ii] = color }
|
59
60
|
self.show
|
60
61
|
sleep(wait_ms / 1000.0)
|
61
|
-
(0...self.length).step(spacing) { |ii| self[ii+jj] = 0 }
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
@@ -71,6 +71,7 @@ module StrandTest
|
|
71
71
|
#
|
72
72
|
# Returns a 24-bit RGB color value.
|
73
73
|
def wheel( pos )
|
74
|
+
pos = pos & 0xff
|
74
75
|
if pos < 85
|
75
76
|
return PixelPi::Color(pos * 3, 255 - pos * 3, 0)
|
76
77
|
elsif pos < 170
|
@@ -94,7 +95,7 @@ module StrandTest
|
|
94
95
|
iterations = opts.fetch(:iterations, 1)
|
95
96
|
|
96
97
|
(0...256*iterations).each do |jj|
|
97
|
-
self.
|
98
|
+
self.fill { |ii| wheel(ii+jj) }
|
98
99
|
self.show
|
99
100
|
sleep(wait_ms / 1000.0)
|
100
101
|
end
|
@@ -114,7 +115,7 @@ module StrandTest
|
|
114
115
|
iterations = opts.fetch(:iterations, 5)
|
115
116
|
|
116
117
|
(0...256*iterations).each do |jj|
|
117
|
-
self.
|
118
|
+
self.fill { |ii| wheel((ii * 256 / self.length) + jj) }
|
118
119
|
self.show
|
119
120
|
sleep(wait_ms / 1000.0)
|
120
121
|
end
|
@@ -135,10 +136,10 @@ module StrandTest
|
|
135
136
|
|
136
137
|
256.times do |jj|
|
137
138
|
spacing.times do |sp|
|
138
|
-
|
139
|
+
self.clear
|
140
|
+
(sp...self.length).step(spacing) { |ii| self[ii] = wheel((ii+jj) % 255) }
|
139
141
|
self.show
|
140
142
|
sleep(wait_ms / 1000.0)
|
141
|
-
(0...self.length).step(spacing) { |ii| self[ii+sp] = 0 }
|
142
143
|
end
|
143
144
|
end
|
144
145
|
|
@@ -158,10 +159,10 @@ strip = PixelPi::Leds.new \
|
|
158
159
|
strip.extend StrandTest
|
159
160
|
|
160
161
|
trap("SIGINT") do
|
161
|
-
strip.clear
|
162
|
-
strip.close
|
163
|
-
exit
|
164
|
-
end
|
162
|
+
strip.clear.show # turn off all the LEDs
|
163
|
+
strip.close # close is not explicitly needed - the finalizer will
|
164
|
+
exit # gracefully shutdown the PWM channel and release the
|
165
|
+
end # DMA memory
|
165
166
|
|
166
167
|
STDOUT.puts "Press Ctrl-C to quit."
|
167
168
|
|
data/ext/pixel_pi/leds.c
CHANGED
@@ -3,6 +3,10 @@
|
|
3
3
|
|
4
4
|
#define RGB2COLOR(r,g,b) ((((r) & 0xff) << 16) | (((g) & 0xff) << 8) | ((b) & 0xff))
|
5
5
|
|
6
|
+
#ifndef MIN
|
7
|
+
#define MIN(a,b) (((a)<(b))?(a):(b))
|
8
|
+
#endif
|
9
|
+
|
6
10
|
VALUE mPixelPi;
|
7
11
|
VALUE cLeds;
|
8
12
|
VALUE ePixelPiError;
|
@@ -69,9 +73,9 @@ pp_leds_struct( VALUE self )
|
|
69
73
|
static int
|
70
74
|
pp_rgb_to_color( VALUE red, VALUE green, VALUE blue )
|
71
75
|
{
|
72
|
-
int r =
|
73
|
-
int g =
|
74
|
-
int b =
|
76
|
+
int r = FIX2INT(red);
|
77
|
+
int g = FIX2INT(green);
|
78
|
+
int b = FIX2INT(blue);
|
75
79
|
return RGB2COLOR(r, g, b);
|
76
80
|
}
|
77
81
|
|
@@ -110,7 +114,7 @@ pp_leds_initialize( int argc, VALUE* argv, VALUE self )
|
|
110
114
|
|
111
115
|
/* get the number of pixels */
|
112
116
|
if (TYPE(length) == T_FIXNUM) {
|
113
|
-
ledstring->channel[0].count =
|
117
|
+
ledstring->channel[0].count = FIX2INT(length);
|
114
118
|
if (ledstring->channel[0].count < 0) {
|
115
119
|
rb_raise( rb_eArgError, "length cannot be negative: %d", ledstring->channel[0].count );
|
116
120
|
}
|
@@ -120,7 +124,7 @@ pp_leds_initialize( int argc, VALUE* argv, VALUE self )
|
|
120
124
|
|
121
125
|
/* get the GPIO number */
|
122
126
|
if (TYPE(gpio) == T_FIXNUM) {
|
123
|
-
ledstring->channel[0].gpionum =
|
127
|
+
ledstring->channel[0].gpionum = FIX2INT(gpio);
|
124
128
|
if (ledstring->channel[0].gpionum < 0) {
|
125
129
|
rb_raise( rb_eArgError, "GPIO cannot be negative: %d", ledstring->channel[0].gpionum );
|
126
130
|
}
|
@@ -135,7 +139,7 @@ pp_leds_initialize( int argc, VALUE* argv, VALUE self )
|
|
135
139
|
tmp = rb_hash_lookup( opts, sym_dma );
|
136
140
|
if (!NIL_P(tmp)) {
|
137
141
|
if (TYPE(tmp) == T_FIXNUM) {
|
138
|
-
ledstring->dmanum =
|
142
|
+
ledstring->dmanum = FIX2INT(tmp);
|
139
143
|
if (ledstring->dmanum < 0) {
|
140
144
|
rb_raise( rb_eArgError, "DMA channel cannot be negative: %d", ledstring->dmanum );
|
141
145
|
}
|
@@ -148,7 +152,7 @@ pp_leds_initialize( int argc, VALUE* argv, VALUE self )
|
|
148
152
|
tmp = rb_hash_lookup( opts, sym_frequency );
|
149
153
|
if (!NIL_P(tmp)) {
|
150
154
|
if (TYPE(tmp) == T_FIXNUM) {
|
151
|
-
ledstring->freq =
|
155
|
+
ledstring->freq = FIX2UINT(tmp);
|
152
156
|
} else {
|
153
157
|
rb_raise( rb_eTypeError, "frequency must be a number: %s", rb_obj_classname(tmp) );
|
154
158
|
}
|
@@ -158,7 +162,7 @@ pp_leds_initialize( int argc, VALUE* argv, VALUE self )
|
|
158
162
|
tmp = rb_hash_lookup( opts, sym_brightness );
|
159
163
|
if (!NIL_P(tmp)) {
|
160
164
|
if (TYPE(tmp) == T_FIXNUM) {
|
161
|
-
ledstring->channel[0].brightness = (
|
165
|
+
ledstring->channel[0].brightness = (FIX2UINT(tmp) & 0xff);
|
162
166
|
if (ledstring->channel[0].brightness < 0) {
|
163
167
|
rb_raise( rb_eArgError, "brightness cannot be negative: %d", ledstring->channel[0].brightness );
|
164
168
|
}
|
@@ -273,7 +277,7 @@ static VALUE
|
|
273
277
|
pp_leds_brightness_set( VALUE self, VALUE brightness )
|
274
278
|
{
|
275
279
|
ws2811_t *ledstring = pp_leds_struct( self );
|
276
|
-
ledstring->channel[0].brightness = (
|
280
|
+
ledstring->channel[0].brightness = (FIX2UINT(brightness) & 0xff);
|
277
281
|
return brightness;
|
278
282
|
}
|
279
283
|
|
@@ -308,24 +312,23 @@ pp_leds_clear( VALUE self )
|
|
308
312
|
{
|
309
313
|
ws2811_t *ledstring = pp_leds_struct( self );
|
310
314
|
ws2811_channel_t channel = ledstring->channel[0];
|
311
|
-
int ii
|
315
|
+
int ii;
|
312
316
|
|
313
317
|
for (ii=0; ii<channel.count; ii++) {
|
314
318
|
channel.leds[ii] = 0;
|
315
319
|
}
|
316
320
|
|
317
|
-
resp = ws2811_render( ledstring );
|
318
|
-
if (resp < 0) {
|
319
|
-
rb_raise( rb_eRuntimeError, "PixelPi::Leds failed to render: %d", resp );
|
320
|
-
}
|
321
|
-
|
322
321
|
return self;
|
323
322
|
}
|
324
323
|
|
325
324
|
/* call-seq:
|
326
325
|
* close
|
327
326
|
*
|
328
|
-
*
|
327
|
+
* Shutdown the NeoPixels connected to the DMA / PWM channel. After this method
|
328
|
+
* the current PixelPi::Leds instance will no longer be usable; a new instance
|
329
|
+
* will need to be created. This method is automatically invoked when the
|
330
|
+
* instance is deallcoated by the Ruby garbage collector. It does not need to be
|
331
|
+
* explicitly invoked.
|
329
332
|
*
|
330
333
|
* Returns `nil`.
|
331
334
|
*/
|
@@ -350,7 +353,7 @@ pp_leds_get_pixel_color( VALUE self, VALUE num )
|
|
350
353
|
ws2811_t *ledstring = pp_leds_struct( self );
|
351
354
|
ws2811_channel_t channel = ledstring->channel[0];
|
352
355
|
|
353
|
-
int n =
|
356
|
+
int n = FIX2INT(num);
|
354
357
|
if (n < 0 || n >= channel.count) {
|
355
358
|
rb_raise( rb_eIndexError, "index %d is outside of LED range: 0...%d", n, channel.count-1 );
|
356
359
|
}
|
@@ -372,9 +375,9 @@ pp_leds_set_pixel_color( VALUE self, VALUE num, VALUE color )
|
|
372
375
|
ws2811_t *ledstring = pp_leds_struct( self );
|
373
376
|
ws2811_channel_t channel = ledstring->channel[0];
|
374
377
|
|
375
|
-
int n =
|
378
|
+
int n = FIX2INT(num);
|
376
379
|
if (n >= 0 && n < channel.count) {
|
377
|
-
channel.leds[n] =
|
380
|
+
channel.leds[n] = FIX2UINT(color);
|
378
381
|
}
|
379
382
|
return self;
|
380
383
|
}
|
@@ -415,6 +418,204 @@ pp_leds_set_pixel_color2( int argc, VALUE* argv, VALUE self )
|
|
415
418
|
return self;
|
416
419
|
}
|
417
420
|
|
421
|
+
/* call-seq:
|
422
|
+
* to_a
|
423
|
+
*
|
424
|
+
* Takes the current list of 24-bit RGB values stored in the LED strings and
|
425
|
+
* returns them as an Array. These colors might not be actively displayed; it
|
426
|
+
* all depends if `show` has been called on the PixelPi::Leds instance.
|
427
|
+
*
|
428
|
+
* Returns an Array of 24-bit RGB values.
|
429
|
+
*/
|
430
|
+
static VALUE
|
431
|
+
pp_leds_to_a( VALUE self )
|
432
|
+
{
|
433
|
+
ws2811_t *ledstring = pp_leds_struct( self );
|
434
|
+
ws2811_channel_t channel = ledstring->channel[0];
|
435
|
+
int ii;
|
436
|
+
VALUE ary;
|
437
|
+
|
438
|
+
ary = rb_ary_new2( channel.count );
|
439
|
+
for (ii=0; ii<channel.count; ii++) {
|
440
|
+
rb_ary_push( ary, INT2NUM(channel.leds[ii]) );
|
441
|
+
}
|
442
|
+
|
443
|
+
return ary;
|
444
|
+
}
|
445
|
+
|
446
|
+
/* call-seq:
|
447
|
+
* replace( ary )
|
448
|
+
*
|
449
|
+
* Replace the LED colors with the 24-bit RGB color values found in the `ary`.
|
450
|
+
* If the `ary` is longer than the LED string then the extra color values will
|
451
|
+
* be ignored. If the `ary` is shorter than the LED string then only the LEDS
|
452
|
+
* up to `ary.length` will be changed.
|
453
|
+
*
|
454
|
+
* You must call `show` for the new colors to be displayed.
|
455
|
+
*
|
456
|
+
* Returns this PixelPi::Leds instance.
|
457
|
+
*/
|
458
|
+
static VALUE
|
459
|
+
pp_leds_replace( VALUE self, VALUE ary )
|
460
|
+
{
|
461
|
+
ws2811_t *ledstring = pp_leds_struct( self );
|
462
|
+
ws2811_channel_t channel = ledstring->channel[0];
|
463
|
+
int ii, min;
|
464
|
+
|
465
|
+
Check_Type( ary, T_ARRAY );
|
466
|
+
min = MIN(channel.count, RARRAY_LEN(ary));
|
467
|
+
|
468
|
+
for (ii=0; ii<min; ii++) {
|
469
|
+
channel.leds[ii] = FIX2UINT(rb_ary_entry( ary, ii ));
|
470
|
+
}
|
471
|
+
|
472
|
+
return self;
|
473
|
+
}
|
474
|
+
|
475
|
+
static void
|
476
|
+
pp_leds_reverse( ws2811_led_t *p1, ws2811_led_t *p2 )
|
477
|
+
{
|
478
|
+
while (p1 < p2) {
|
479
|
+
ws2811_led_t tmp = *p1;
|
480
|
+
*p1++ = *p2;
|
481
|
+
*p2-- = tmp;
|
482
|
+
}
|
483
|
+
}
|
484
|
+
|
485
|
+
/* call-seq:
|
486
|
+
* reverse
|
487
|
+
*
|
488
|
+
* Reverse the order of the LED colors.
|
489
|
+
*
|
490
|
+
* Returns this PixelPi::Leds instance.
|
491
|
+
*/
|
492
|
+
static VALUE
|
493
|
+
pp_leds_reverse_m( VALUE self )
|
494
|
+
{
|
495
|
+
ws2811_t *ledstring = pp_leds_struct( self );
|
496
|
+
ws2811_channel_t channel = ledstring->channel[0];
|
497
|
+
ws2811_led_t *ptr = channel.leds;
|
498
|
+
int len = channel.count;
|
499
|
+
|
500
|
+
if (--len > 0) pp_leds_reverse( ptr, ptr + len );
|
501
|
+
|
502
|
+
return self;
|
503
|
+
}
|
504
|
+
|
505
|
+
/* call-seq:
|
506
|
+
* rotate( count = 1 )
|
507
|
+
*
|
508
|
+
* Rotates the LED colors in place so that the color at `count` comes first. If
|
509
|
+
* `count` is negative then it rotates in the opposite direction, starting from
|
510
|
+
* the end of the LEDs where -1 is the last LED.
|
511
|
+
*
|
512
|
+
* Returns this PixelPi::Leds instance.
|
513
|
+
*/
|
514
|
+
static VALUE
|
515
|
+
pp_leds_rotate( int argc, VALUE* argv, VALUE self )
|
516
|
+
{
|
517
|
+
ws2811_t *ledstring = pp_leds_struct( self );
|
518
|
+
ws2811_channel_t channel = ledstring->channel[0];
|
519
|
+
int cnt = 1;
|
520
|
+
|
521
|
+
switch (argc) {
|
522
|
+
case 1: cnt = FIX2INT(argv[0]);
|
523
|
+
case 0: break;
|
524
|
+
default: rb_scan_args( argc, argv, "01", NULL );
|
525
|
+
}
|
526
|
+
|
527
|
+
if (cnt != 0) {
|
528
|
+
ws2811_led_t *ptr = channel.leds;
|
529
|
+
int len = channel.count;
|
530
|
+
cnt = (cnt < 0) ? (len - (~cnt % len) - 1) : (cnt % len);
|
531
|
+
|
532
|
+
if (len > 0 && cnt > 0) {
|
533
|
+
--len;
|
534
|
+
if (cnt < len) pp_leds_reverse( ptr + cnt, ptr + len );
|
535
|
+
if (--cnt > 0) pp_leds_reverse( ptr, ptr + cnt );
|
536
|
+
if (len > 0) pp_leds_reverse( ptr, ptr + len );
|
537
|
+
}
|
538
|
+
}
|
539
|
+
|
540
|
+
return self;
|
541
|
+
}
|
542
|
+
|
543
|
+
/* call-seq:
|
544
|
+
* fill( color )
|
545
|
+
* fill( color, start [, length] )
|
546
|
+
* fill( color, range )
|
547
|
+
* fill { |index| block }
|
548
|
+
* fill( start [, length] ) { |index| block }
|
549
|
+
* fill( range ) { |index| block }
|
550
|
+
*
|
551
|
+
* Set the selected LEDs to the given `color`. The `color` msut be given as a
|
552
|
+
* 24-bit RGB value. You can also supply a block that receives an LED index and
|
553
|
+
* returns a 24-bit RGB color.
|
554
|
+
*
|
555
|
+
* Examples:
|
556
|
+
* leds.fill( 0x00FF00 )
|
557
|
+
* leds.fill( 0xFF0000, 2, 2 )
|
558
|
+
* leds.fill( 0x0000FF, (4...8) )
|
559
|
+
* leds.fill { |i| 256 << i }
|
560
|
+
*
|
561
|
+
* Returns this PixelPi::Leds instance.
|
562
|
+
*/
|
563
|
+
static VALUE
|
564
|
+
pp_leds_fill( int argc, VALUE* argv, VALUE self )
|
565
|
+
{
|
566
|
+
ws2811_t *ledstring = pp_leds_struct( self );
|
567
|
+
ws2811_channel_t channel = ledstring->channel[0];
|
568
|
+
ws2811_led_t color = 0;
|
569
|
+
|
570
|
+
VALUE item, arg1, arg2, v;
|
571
|
+
long ii, beg = 0, end = 0, len = 0;
|
572
|
+
int block_p = 0;
|
573
|
+
|
574
|
+
if (rb_block_given_p()) {
|
575
|
+
block_p = 1;
|
576
|
+
rb_scan_args( argc, argv, "02", &arg1, &arg2 );
|
577
|
+
argc += 1;
|
578
|
+
} else {
|
579
|
+
rb_scan_args( argc, argv, "12", &item, &arg1, &arg2 );
|
580
|
+
color = FIX2UINT(item);
|
581
|
+
}
|
582
|
+
|
583
|
+
switch (argc) {
|
584
|
+
case 1:
|
585
|
+
beg = 0;
|
586
|
+
len = channel.count;
|
587
|
+
break;
|
588
|
+
case 2:
|
589
|
+
if (rb_range_beg_len(arg1, &beg, &len, channel.count, 1)) {
|
590
|
+
break;
|
591
|
+
}
|
592
|
+
/* fall through */
|
593
|
+
case 3:
|
594
|
+
beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
|
595
|
+
if (beg < 0) {
|
596
|
+
beg = channel.count + beg;
|
597
|
+
if (beg < 0) beg = 0;
|
598
|
+
}
|
599
|
+
len = NIL_P(arg2) ? channel.count - beg : NUM2LONG(arg2);
|
600
|
+
break;
|
601
|
+
}
|
602
|
+
|
603
|
+
if (len < 0) return self;
|
604
|
+
|
605
|
+
end = beg + len;
|
606
|
+
end = MIN((long) channel.count, end);
|
607
|
+
|
608
|
+
for (ii=beg; ii<end; ii++) {
|
609
|
+
if (block_p) {
|
610
|
+
v = rb_yield(INT2NUM(ii));
|
611
|
+
color = FIX2UINT(v);
|
612
|
+
}
|
613
|
+
channel.leds[ii] = color;
|
614
|
+
}
|
615
|
+
|
616
|
+
return self;
|
617
|
+
}
|
618
|
+
|
418
619
|
/* call-seq:
|
419
620
|
* PixelPi::Color(red, green, blue) #=> 24-bit color
|
420
621
|
*
|
@@ -456,6 +657,11 @@ void Init_leds( )
|
|
456
657
|
rb_define_method( cLeds, "[]", pp_leds_get_pixel_color, 1 );
|
457
658
|
rb_define_method( cLeds, "[]=", pp_leds_set_pixel_color, 2 );
|
458
659
|
rb_define_method( cLeds, "set_pixel", pp_leds_set_pixel_color2, -1 );
|
660
|
+
rb_define_method( cLeds, "to_a", pp_leds_to_a, 0 );
|
661
|
+
rb_define_method( cLeds, "replace", pp_leds_replace, 1 );
|
662
|
+
rb_define_method( cLeds, "reverse", pp_leds_reverse_m, 0 );
|
663
|
+
rb_define_method( cLeds, "rotate", pp_leds_rotate, -1 );
|
664
|
+
rb_define_method( cLeds, "fill", pp_leds_fill, -1 );
|
459
665
|
|
460
666
|
rb_define_module_function( mPixelPi, "Color", pp_color, 3 );
|
461
667
|
|
data/lib/pixel_pi/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pixel_pi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tim Pease
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-12-
|
11
|
+
date: 2014-12-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|