pixel_pi 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 08cca7dba9a29b50641d0408dcbe81a1f5c86e7e
4
- data.tar.gz: 7aaf72769a673bac2c41d23111fbec22658b0c73
3
+ metadata.gz: 1c158234b67ccd01d55b48cf274c5ccb437ae77a
4
+ data.tar.gz: 5125b6c0d47381ca23ba8fc942ac73d22f9f3bbb
5
5
  SHA512:
6
- metadata.gz: 50a6c2996d7421024e4c657cc17936b7ee28da810fb6820fbb94199200d1e3025e9899c3338adb29bb40fa827acdc6fe419f2f3f9878e62949932d2761cfaf64
7
- data.tar.gz: b9e70d44aeb4e8e7332f3d04f7321e0f3922c1253fb52f7afcea9deb4d004d1803df44b536de3759a33dbfbcdd837ba0870d5a37cd66d989695bbf2f6a743603
6
+ metadata.gz: d010f3d8e722cb39aea7cd13cb78e92621628014799899bb08def77a0b0e1333dcf88362aa797f88ccdf2949b6d524f80bf23fa3302951e875e974fbf0e7a80b
7
+ data.tar.gz: acdac849b6517a354918be99681e360592a8edb77ca18a77bc741aba66008c56b42a62a760500a9026f6bd41c7d6d1a7794d5085765e3a39fee56637ef8129e0
data/.gitignore CHANGED
@@ -1 +1,2 @@
1
+ *.gem
1
2
  tmp
@@ -54,11 +54,11 @@ module StrandTest
54
54
  spacing = opts.fetch(:spacing, 3)
55
55
 
56
56
  iterations.times do
57
- spacing.times do |jj|
58
- (0...self.length).step(spacing) { |ii| self[ii+jj] = color }
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.length.times { |ii| self[ii] = wheel((ii+jj) & 0xff) }
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.length.times { |ii| self[ii] = wheel(((ii * 256 / self.length) + jj) & 0xff) }
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
- (0...self.length).step(spacing) { |ii| self[ii+sp] = wheel((ii+jj) % 255) }
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 # not explicitly needed - the finalizer will gracefully shutdown
163
- exit # the PWM channel and release the DMA memory
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
 
@@ -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 = NUM2INT(red);
73
- int g = NUM2INT(green);
74
- int b = NUM2INT(blue);
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 = NUM2INT(length);
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 = NUM2INT(gpio);
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 = NUM2INT(tmp);
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 = NUM2UINT(tmp);
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 = (NUM2UINT(tmp) & 0xff);
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 = (NUM2UINT(brightness) & 0xff);
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, resp;
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
- * FIXME
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 = NUM2INT(num);
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 = NUM2INT(num);
378
+ int n = FIX2INT(num);
376
379
  if (n >= 0 && n < channel.count) {
377
- channel.leds[n] = NUM2INT(color);
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
 
@@ -1,3 +1,3 @@
1
1
  module PixelPi
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
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.2
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-21 00:00:00.000000000 Z
11
+ date: 2014-12-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler