pixel_pi 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/README.md +85 -0
- data/Rakefile +16 -0
- data/examples/strandtest.rb +186 -0
- data/ext/pixel_pi/extconf.rb +18 -0
- data/ext/pixel_pi/leds.c +464 -0
- data/ext/ws2811/LICENSE +24 -0
- data/ext/ws2811/clk.h +60 -0
- data/ext/ws2811/dma.c +192 -0
- data/ext/ws2811/dma.h +146 -0
- data/ext/ws2811/gpio.h +108 -0
- data/ext/ws2811/pwm.c +112 -0
- data/ext/ws2811/pwm.h +122 -0
- data/ext/ws2811/ws2811.c +757 -0
- data/ext/ws2811/ws2811.h +68 -0
- data/lib/pixel_pi/version.rb +3 -0
- data/lib/pixel_pi.rb +2 -0
- data/pixel_pi.gemspec +23 -0
- metadata +77 -0
data/ext/pixel_pi/leds.c
ADDED
@@ -0,0 +1,464 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include "ws2811.h"
|
3
|
+
|
4
|
+
#define RGB2COLOR(r,g,b) ((((r) & 0xff) << 16) | (((g) & 0xff) << 8) | ((b) & 0xff))
|
5
|
+
|
6
|
+
VALUE mPixelPi;
|
7
|
+
VALUE cLeds;
|
8
|
+
VALUE ePixelPiError;
|
9
|
+
|
10
|
+
static VALUE sym_dma, sym_frequency, sym_invert, sym_brightness;
|
11
|
+
|
12
|
+
/* ======================================================================= */
|
13
|
+
|
14
|
+
static void
|
15
|
+
pp_leds_free( void *ptr )
|
16
|
+
{
|
17
|
+
ws2811_t *ledstring;
|
18
|
+
if (NULL == ptr) return;
|
19
|
+
|
20
|
+
ledstring= (ws2811_t*) ptr;
|
21
|
+
if (ledstring->device) ws2811_fini( ledstring );
|
22
|
+
xfree( ledstring );
|
23
|
+
}
|
24
|
+
|
25
|
+
static VALUE
|
26
|
+
pp_leds_allocate( VALUE klass )
|
27
|
+
{
|
28
|
+
int ii;
|
29
|
+
ws2811_t *ledstring;
|
30
|
+
|
31
|
+
ledstring = ALLOC_N( ws2811_t, 1 );
|
32
|
+
if (!ledstring) {
|
33
|
+
rb_raise(rb_eNoMemError, "could not allocate PixelPi::Leds instance");
|
34
|
+
}
|
35
|
+
|
36
|
+
ledstring->freq = WS2811_TARGET_FREQ;
|
37
|
+
ledstring->dmanum = 5;
|
38
|
+
ledstring->device = NULL;
|
39
|
+
|
40
|
+
for (ii=0; ii<RPI_PWM_CHANNELS; ii++) {
|
41
|
+
ledstring->channel[ii].gpionum = 0;
|
42
|
+
ledstring->channel[ii].count = 0;
|
43
|
+
ledstring->channel[ii].invert = 0;
|
44
|
+
ledstring->channel[ii].brightness = 255;
|
45
|
+
ledstring->channel[ii].leds = NULL;
|
46
|
+
}
|
47
|
+
|
48
|
+
return Data_Wrap_Struct( klass, NULL, pp_leds_free, ledstring );
|
49
|
+
}
|
50
|
+
|
51
|
+
static ws2811_t*
|
52
|
+
pp_leds_struct( VALUE self )
|
53
|
+
{
|
54
|
+
ws2811_t *ledstring;
|
55
|
+
|
56
|
+
if (TYPE(self) != T_DATA
|
57
|
+
|| RDATA(self)->dfree != (RUBY_DATA_FUNC) pp_leds_free) {
|
58
|
+
rb_raise( rb_eTypeError, "expecting a PixelPi::Leds object" );
|
59
|
+
}
|
60
|
+
Data_Get_Struct( self, ws2811_t, ledstring );
|
61
|
+
|
62
|
+
if (!ledstring->device) {
|
63
|
+
rb_raise( ePixelPiError, "Leds are not initialized" );
|
64
|
+
}
|
65
|
+
|
66
|
+
return ledstring;
|
67
|
+
}
|
68
|
+
|
69
|
+
static int
|
70
|
+
pp_rgb_to_color( VALUE red, VALUE green, VALUE blue )
|
71
|
+
{
|
72
|
+
int r = NUM2INT(red);
|
73
|
+
int g = NUM2INT(green);
|
74
|
+
int b = NUM2INT(blue);
|
75
|
+
return RGB2COLOR(r, g, b);
|
76
|
+
}
|
77
|
+
|
78
|
+
/* ======================================================================= */
|
79
|
+
/* call-seq:
|
80
|
+
* PixelPi::Leds.new( length, gpio, options = {} )
|
81
|
+
*
|
82
|
+
* Create a new PixelPi::Leds instance that can be used to control a string of
|
83
|
+
* NeoPixels from a RaspberryPi. The length of the pixel string must be given as
|
84
|
+
* well as the GPIO pin number used to control the string. The remaining options
|
85
|
+
* have sensible defaults.
|
86
|
+
*
|
87
|
+
* length - the nubmer of leds in the string
|
88
|
+
* gpio - the GPIO pin number
|
89
|
+
* options - Hash of arguments
|
90
|
+
* :dma - DMA channel defaults to 5
|
91
|
+
* :frequency - output frequency defaults to 800,000 Hz
|
92
|
+
* :invert - defaults to `false`
|
93
|
+
* :brightness - defaults to 255
|
94
|
+
*/
|
95
|
+
static VALUE
|
96
|
+
pp_leds_initialize( int argc, VALUE* argv, VALUE self )
|
97
|
+
{
|
98
|
+
ws2811_t *ledstring;
|
99
|
+
VALUE length, gpio, opts, tmp;
|
100
|
+
int resp;
|
101
|
+
|
102
|
+
if (TYPE(self) != T_DATA
|
103
|
+
|| RDATA(self)->dfree != (RUBY_DATA_FUNC) pp_leds_free) {
|
104
|
+
rb_raise( rb_eTypeError, "expecting a PixelPi::Leds object" );
|
105
|
+
}
|
106
|
+
Data_Get_Struct( self, ws2811_t, ledstring );
|
107
|
+
|
108
|
+
/* parse out the length, gpio, and optional arguments if given */
|
109
|
+
rb_scan_args( argc, argv, "21", &length, &gpio, &opts );
|
110
|
+
|
111
|
+
/* get the number of pixels */
|
112
|
+
if (TYPE(length) == T_FIXNUM) {
|
113
|
+
ledstring->channel[0].count = NUM2INT(length);
|
114
|
+
if (ledstring->channel[0].count < 0) {
|
115
|
+
rb_raise( rb_eArgError, "length cannot be negative: %d", ledstring->channel[0].count );
|
116
|
+
}
|
117
|
+
} else {
|
118
|
+
rb_raise( rb_eTypeError, "length must be a number: %s", rb_obj_classname(length) );
|
119
|
+
}
|
120
|
+
|
121
|
+
/* get the GPIO number */
|
122
|
+
if (TYPE(gpio) == T_FIXNUM) {
|
123
|
+
ledstring->channel[0].gpionum = NUM2INT(gpio);
|
124
|
+
if (ledstring->channel[0].gpionum < 0) {
|
125
|
+
rb_raise( rb_eArgError, "GPIO cannot be negative: %d", ledstring->channel[0].gpionum );
|
126
|
+
}
|
127
|
+
} else {
|
128
|
+
rb_raise( rb_eTypeError, "GPIO must be a number: %s", rb_obj_classname(gpio) );
|
129
|
+
}
|
130
|
+
|
131
|
+
if (!NIL_P(opts)) {
|
132
|
+
Check_Type( opts, T_HASH );
|
133
|
+
|
134
|
+
/* get the DMA channel */
|
135
|
+
tmp = rb_hash_lookup( opts, sym_dma );
|
136
|
+
if (!NIL_P(tmp)) {
|
137
|
+
if (TYPE(tmp) == T_FIXNUM) {
|
138
|
+
ledstring->dmanum = NUM2INT(tmp);
|
139
|
+
if (ledstring->dmanum < 0) {
|
140
|
+
rb_raise( rb_eArgError, "DMA channel cannot be negative: %d", ledstring->dmanum );
|
141
|
+
}
|
142
|
+
} else {
|
143
|
+
rb_raise( rb_eTypeError, "DMA channel must be a number: %s", rb_obj_classname(tmp) );
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
147
|
+
/* get the frequency */
|
148
|
+
tmp = rb_hash_lookup( opts, sym_frequency );
|
149
|
+
if (!NIL_P(tmp)) {
|
150
|
+
if (TYPE(tmp) == T_FIXNUM) {
|
151
|
+
ledstring->freq = NUM2UINT(tmp);
|
152
|
+
} else {
|
153
|
+
rb_raise( rb_eTypeError, "frequency must be a number: %s", rb_obj_classname(tmp) );
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
157
|
+
/* get the brightness */
|
158
|
+
tmp = rb_hash_lookup( opts, sym_brightness );
|
159
|
+
if (!NIL_P(tmp)) {
|
160
|
+
if (TYPE(tmp) == T_FIXNUM) {
|
161
|
+
ledstring->channel[0].brightness = (NUM2UINT(tmp) & 0xff);
|
162
|
+
if (ledstring->channel[0].brightness < 0) {
|
163
|
+
rb_raise( rb_eArgError, "brightness cannot be negative: %d", ledstring->channel[0].brightness );
|
164
|
+
}
|
165
|
+
} else {
|
166
|
+
rb_raise( rb_eTypeError, "brightness must be a number: %s", rb_obj_classname(tmp) );
|
167
|
+
}
|
168
|
+
}
|
169
|
+
|
170
|
+
/* get the invert flag */
|
171
|
+
tmp = rb_hash_lookup( opts, sym_invert );
|
172
|
+
if (!NIL_P(tmp)) {
|
173
|
+
if (RTEST(tmp)) ledstring->channel[0].invert = 1;
|
174
|
+
else ledstring->channel[0].invert = 0;
|
175
|
+
}
|
176
|
+
}
|
177
|
+
|
178
|
+
/* initialize the DMA and PWM cycle */
|
179
|
+
resp = ws2811_init( ledstring );
|
180
|
+
if (resp < 0) {
|
181
|
+
rb_raise( ePixelPiError, "Leds could not be initialized: %d", resp );
|
182
|
+
}
|
183
|
+
|
184
|
+
return self;
|
185
|
+
}
|
186
|
+
|
187
|
+
/* call-seq:
|
188
|
+
* length
|
189
|
+
*
|
190
|
+
* Returns the number of pixels in the LED string.
|
191
|
+
*/
|
192
|
+
static VALUE
|
193
|
+
pp_leds_length_get( VALUE self )
|
194
|
+
{
|
195
|
+
ws2811_t *ledstring = pp_leds_struct( self );
|
196
|
+
return INT2FIX(ledstring->channel[0].count);
|
197
|
+
}
|
198
|
+
|
199
|
+
/* call-seq:
|
200
|
+
* gpio
|
201
|
+
*
|
202
|
+
* Returns the GPIO number used to control the pixels.
|
203
|
+
*/
|
204
|
+
static VALUE
|
205
|
+
pp_leds_gpio_get( VALUE self )
|
206
|
+
{
|
207
|
+
ws2811_t *ledstring = pp_leds_struct( self );
|
208
|
+
return INT2FIX(ledstring->channel[0].gpionum);
|
209
|
+
}
|
210
|
+
|
211
|
+
/* call-seq:
|
212
|
+
* dma
|
213
|
+
*
|
214
|
+
* Returns the DMA channel used to control the pixels.
|
215
|
+
*/
|
216
|
+
static VALUE
|
217
|
+
pp_leds_dma_get( VALUE self )
|
218
|
+
{
|
219
|
+
ws2811_t *ledstring = pp_leds_struct( self );
|
220
|
+
return INT2FIX(ledstring->dmanum);
|
221
|
+
}
|
222
|
+
|
223
|
+
/* call-seq:
|
224
|
+
* frequency
|
225
|
+
*
|
226
|
+
* Returns the output frequency.
|
227
|
+
*/
|
228
|
+
static VALUE
|
229
|
+
pp_leds_frequency_get( VALUE self )
|
230
|
+
{
|
231
|
+
ws2811_t *ledstring = pp_leds_struct( self );
|
232
|
+
return INT2FIX(ledstring->freq);
|
233
|
+
}
|
234
|
+
|
235
|
+
/* call-seq:
|
236
|
+
* invert
|
237
|
+
*
|
238
|
+
* Returns `true` if the invert flag is set and `false` if it is not set.
|
239
|
+
*/
|
240
|
+
static VALUE
|
241
|
+
pp_leds_invert_get( VALUE self )
|
242
|
+
{
|
243
|
+
ws2811_t *ledstring = pp_leds_struct( self );
|
244
|
+
if (ledstring->channel[0].invert) {
|
245
|
+
return Qtrue;
|
246
|
+
} else {
|
247
|
+
return Qfalse;
|
248
|
+
}
|
249
|
+
}
|
250
|
+
|
251
|
+
/* call-seq:
|
252
|
+
* brightness
|
253
|
+
*
|
254
|
+
* Returns the brightness.
|
255
|
+
*/
|
256
|
+
static VALUE
|
257
|
+
pp_leds_brightness_get( VALUE self )
|
258
|
+
{
|
259
|
+
ws2811_t *ledstring = pp_leds_struct( self );
|
260
|
+
return INT2FIX(ledstring->channel[0].brightness);
|
261
|
+
}
|
262
|
+
|
263
|
+
/* call-seq:
|
264
|
+
* brightness = 128 # value between 0 and 255
|
265
|
+
*
|
266
|
+
* Set the pixel brightness. This is a value between 0 and 255. All pixels will
|
267
|
+
* be scaled by this value. The hue is not affected; only the luminosity is
|
268
|
+
* affected.
|
269
|
+
*
|
270
|
+
* Returns the new brightness.
|
271
|
+
*/
|
272
|
+
static VALUE
|
273
|
+
pp_leds_brightness_set( VALUE self, VALUE brightness )
|
274
|
+
{
|
275
|
+
ws2811_t *ledstring = pp_leds_struct( self );
|
276
|
+
ledstring->channel[0].brightness = (NUM2UINT(brightness) & 0xff);
|
277
|
+
return brightness;
|
278
|
+
}
|
279
|
+
|
280
|
+
/* call-seq:
|
281
|
+
* show
|
282
|
+
*
|
283
|
+
* Update the display with the data from the LED buffer.
|
284
|
+
*
|
285
|
+
* Returns this PixelPi::Leds instance.
|
286
|
+
*/
|
287
|
+
static VALUE
|
288
|
+
pp_leds_show( VALUE self )
|
289
|
+
{
|
290
|
+
ws2811_t *ledstring = pp_leds_struct( self );
|
291
|
+
int resp = ws2811_render( ledstring );
|
292
|
+
if (resp < 0) {
|
293
|
+
rb_raise( ePixelPiError, "PixelPi::Leds failed to render: %d", resp );
|
294
|
+
}
|
295
|
+
return self;
|
296
|
+
}
|
297
|
+
|
298
|
+
/* call-seq:
|
299
|
+
* clear
|
300
|
+
*
|
301
|
+
* Clear the display. This will set all values in the LED buffer to zero, and
|
302
|
+
* then update the display. All pixels will be turned off by this method.
|
303
|
+
*
|
304
|
+
* Returns this PixelPi::Leds instance.
|
305
|
+
*/
|
306
|
+
static VALUE
|
307
|
+
pp_leds_clear( VALUE self )
|
308
|
+
{
|
309
|
+
ws2811_t *ledstring = pp_leds_struct( self );
|
310
|
+
ws2811_channel_t channel = ledstring->channel[0];
|
311
|
+
int ii, resp;
|
312
|
+
|
313
|
+
for (ii=0; ii<channel.count; ii++) {
|
314
|
+
channel.leds[ii] = 0;
|
315
|
+
}
|
316
|
+
|
317
|
+
resp = ws2811_render( ledstring );
|
318
|
+
if (resp < 0) {
|
319
|
+
rb_raise( rb_eRuntimeError, "PixelPi::Leds failed to render: %d", resp );
|
320
|
+
}
|
321
|
+
|
322
|
+
return self;
|
323
|
+
}
|
324
|
+
|
325
|
+
/* call-seq:
|
326
|
+
* close
|
327
|
+
*
|
328
|
+
* FIXME
|
329
|
+
*
|
330
|
+
* Returns `nil`.
|
331
|
+
*/
|
332
|
+
static VALUE
|
333
|
+
pp_leds_close( VALUE self )
|
334
|
+
{
|
335
|
+
ws2811_t *ledstring = pp_leds_struct( self );
|
336
|
+
if (ledstring->device) ws2811_fini( ledstring );
|
337
|
+
return Qnil;
|
338
|
+
}
|
339
|
+
|
340
|
+
/* call-seq:
|
341
|
+
* leds[num]
|
342
|
+
*
|
343
|
+
* Get the 24-bit RGB color value for the LED at position `num`.
|
344
|
+
*
|
345
|
+
* Returns a 24-bit RGB color value.
|
346
|
+
*/
|
347
|
+
static VALUE
|
348
|
+
pp_leds_get_pixel_color( VALUE self, VALUE num )
|
349
|
+
{
|
350
|
+
ws2811_t *ledstring = pp_leds_struct( self );
|
351
|
+
ws2811_channel_t channel = ledstring->channel[0];
|
352
|
+
|
353
|
+
int n = NUM2INT(num);
|
354
|
+
if (n < 0 || n >= channel.count) {
|
355
|
+
rb_raise( rb_eIndexError, "index %d is outside of LED range: 0...%d", n, channel.count-1 );
|
356
|
+
}
|
357
|
+
|
358
|
+
return INT2FIX(channel.leds[n]);
|
359
|
+
}
|
360
|
+
|
361
|
+
/* call-seq:
|
362
|
+
* leds[num] = color
|
363
|
+
* leds[num] = PixelPi::Color( red, green, blue )
|
364
|
+
*
|
365
|
+
* Set the LED at position `num` to the provided 24-bit RGB color value.
|
366
|
+
*
|
367
|
+
* Returns the 24-bit RGB color value.
|
368
|
+
*/
|
369
|
+
static VALUE
|
370
|
+
pp_leds_set_pixel_color( VALUE self, VALUE num, VALUE color )
|
371
|
+
{
|
372
|
+
ws2811_t *ledstring = pp_leds_struct( self );
|
373
|
+
ws2811_channel_t channel = ledstring->channel[0];
|
374
|
+
|
375
|
+
int n = NUM2INT(num);
|
376
|
+
if (n >= 0 && n < channel.count) {
|
377
|
+
channel.leds[n] = NUM2INT(color);
|
378
|
+
}
|
379
|
+
return self;
|
380
|
+
}
|
381
|
+
|
382
|
+
/* call-seq:
|
383
|
+
* set_pixel( num, color )
|
384
|
+
* set_pixel( num, red, green, blue )
|
385
|
+
*
|
386
|
+
* Set the LED at position `num` to the given color. The color can be a single
|
387
|
+
* 24-bit RGB `color` value or three separate color values - one for `red`, one
|
388
|
+
* for `green`, and one for `blue`.
|
389
|
+
*
|
390
|
+
* Returns this PixelPi::Leds instance.
|
391
|
+
*/
|
392
|
+
static VALUE
|
393
|
+
pp_leds_set_pixel_color2( int argc, VALUE* argv, VALUE self )
|
394
|
+
{
|
395
|
+
VALUE num, color, red, green, blue;
|
396
|
+
rb_scan_args( argc, argv, "22", &num, &red, &green, &blue );
|
397
|
+
|
398
|
+
switch (argc) {
|
399
|
+
case 2: {
|
400
|
+
color = red;
|
401
|
+
break;
|
402
|
+
}
|
403
|
+
case 4: {
|
404
|
+
int c = pp_rgb_to_color( red, green, blue );
|
405
|
+
color = INT2FIX(c);
|
406
|
+
break;
|
407
|
+
}
|
408
|
+
default: {
|
409
|
+
rb_raise( rb_eArgError, "expecting either 2 or 4 arguments: %d", argc );
|
410
|
+
break;
|
411
|
+
}
|
412
|
+
}
|
413
|
+
|
414
|
+
pp_leds_set_pixel_color( self, num, color );
|
415
|
+
return self;
|
416
|
+
}
|
417
|
+
|
418
|
+
/* call-seq:
|
419
|
+
* PixelPi::Color(red, green, blue) #=> 24-bit color
|
420
|
+
*
|
421
|
+
* Given a set of RGB values return a single 24-bit color value. The RGB values
|
422
|
+
* are nubmers in the range 0..255.
|
423
|
+
*
|
424
|
+
* Returns a 24-bit RGB color value.
|
425
|
+
*/
|
426
|
+
static VALUE
|
427
|
+
pp_color( VALUE klass, VALUE red, VALUE green, VALUE blue )
|
428
|
+
{
|
429
|
+
int color = pp_rgb_to_color( red, green, blue );
|
430
|
+
return INT2FIX(color);
|
431
|
+
}
|
432
|
+
|
433
|
+
void Init_leds( )
|
434
|
+
{
|
435
|
+
sym_dma = ID2SYM(rb_intern( "dma" ));
|
436
|
+
sym_frequency = ID2SYM(rb_intern( "frequency" ));
|
437
|
+
sym_invert = ID2SYM(rb_intern( "invert" ));
|
438
|
+
sym_brightness = ID2SYM(rb_intern( "brightness" ));
|
439
|
+
|
440
|
+
mPixelPi = rb_define_module( "PixelPi" );
|
441
|
+
|
442
|
+
cLeds = rb_define_class_under( mPixelPi, "Leds", rb_cObject );
|
443
|
+
rb_define_alloc_func( cLeds, pp_leds_allocate );
|
444
|
+
rb_define_method( cLeds, "initialize", pp_leds_initialize, -1 );
|
445
|
+
|
446
|
+
rb_define_method( cLeds, "length", pp_leds_length_get, 0 );
|
447
|
+
rb_define_method( cLeds, "gpio", pp_leds_gpio_get, 0 );
|
448
|
+
rb_define_method( cLeds, "dma", pp_leds_dma_get, 0 );
|
449
|
+
rb_define_method( cLeds, "frequency", pp_leds_frequency_get, 0 );
|
450
|
+
rb_define_method( cLeds, "invert", pp_leds_invert_get, 0 );
|
451
|
+
rb_define_method( cLeds, "brightness", pp_leds_brightness_get, 0 );
|
452
|
+
rb_define_method( cLeds, "brightness=", pp_leds_brightness_set, 1 );
|
453
|
+
rb_define_method( cLeds, "show", pp_leds_show, 0 );
|
454
|
+
rb_define_method( cLeds, "clear", pp_leds_clear, 0 );
|
455
|
+
rb_define_method( cLeds, "close", pp_leds_close, 0 );
|
456
|
+
rb_define_method( cLeds, "[]", pp_leds_get_pixel_color, 1 );
|
457
|
+
rb_define_method( cLeds, "[]=", pp_leds_set_pixel_color, 2 );
|
458
|
+
rb_define_method( cLeds, "set_pixel", pp_leds_set_pixel_color2, -1 );
|
459
|
+
|
460
|
+
rb_define_module_function( mPixelPi, "Color", pp_color, 3 );
|
461
|
+
|
462
|
+
/* Define the PixelPi::Error class */
|
463
|
+
ePixelPiError = rb_define_class_under( mPixelPi, "Error", rb_eStandardError );
|
464
|
+
}
|
data/ext/ws2811/LICENSE
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
Copyright (c) 2014, jgarff
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
* Redistributions of source code must retain the above copyright notice, this
|
8
|
+
list of conditions and the following disclaimer.
|
9
|
+
|
10
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
this list of conditions and the following disclaimer in the documentation
|
12
|
+
and/or other materials provided with the distribution.
|
13
|
+
|
14
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
15
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
16
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
17
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
18
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
19
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
20
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
21
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
22
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
23
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
24
|
+
|
data/ext/ws2811/clk.h
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
/*
|
2
|
+
* clk.h
|
3
|
+
*
|
4
|
+
* Copyright (c) 2014 Jeremy Garff <jer @ jers.net>
|
5
|
+
*
|
6
|
+
* All rights reserved.
|
7
|
+
*
|
8
|
+
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
9
|
+
* provided that the following conditions are met:
|
10
|
+
*
|
11
|
+
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
12
|
+
* conditions and the following disclaimer.
|
13
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
14
|
+
* of conditions and the following disclaimer in the documentation and/or other materials
|
15
|
+
* provided with the distribution.
|
16
|
+
* 3. Neither the name of the owner nor the names of its contributors may be used to endorse
|
17
|
+
* or promote products derived from this software without specific prior written permission.
|
18
|
+
*
|
19
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
20
|
+
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
21
|
+
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
|
22
|
+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
23
|
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
24
|
+
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
25
|
+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
26
|
+
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
*
|
28
|
+
*/
|
29
|
+
|
30
|
+
#ifndef __CLK_H__
|
31
|
+
#define __CLK_H__
|
32
|
+
|
33
|
+
|
34
|
+
typedef struct {
|
35
|
+
uint32_t ctl;
|
36
|
+
#define CM_PWM_CTL_PASSWD (0x5a << 24)
|
37
|
+
#define CM_PWM_CTL_MASH(val) ((val & 0x3) << 9)
|
38
|
+
#define CM_PWM_CTL_FLIP (1 << 8)
|
39
|
+
#define CM_PWM_CTL_BUSY (1 << 7)
|
40
|
+
#define CM_PWM_CTL_KILL (1 << 5)
|
41
|
+
#define CM_PWM_CTL_ENAB (1 << 4)
|
42
|
+
#define CM_PWM_CTL_SRC_GND (0 << 0)
|
43
|
+
#define CM_PWM_CTL_SRC_OSC (1 << 0)
|
44
|
+
#define CM_PWM_CTL_SRC_TSTDBG0 (2 << 0)
|
45
|
+
#define CM_PWM_CTL_SRC_TSTDBG1 (3 << 0)
|
46
|
+
#define CM_PWM_CTL_SRC_PLLA (4 << 0)
|
47
|
+
#define CM_PWM_CTL_SRC_PLLC (5 << 0)
|
48
|
+
#define CM_PWM_CTL_SRC_PLLD (6 << 0)
|
49
|
+
#define CM_PWM_CTL_SRC_HDMIAUX (7 << 0)
|
50
|
+
uint32_t div;
|
51
|
+
#define CM_PWM_DIV_PASSWD (0x5a << 24)
|
52
|
+
#define CM_PWM_DIV_DIVI(val) ((val & 0xfff) << 12)
|
53
|
+
#define CM_PWM_DIV_DIVF(val) ((val & 0xfff) << 0)
|
54
|
+
} __attribute__ ((packed)) cm_pwm_t;
|
55
|
+
|
56
|
+
|
57
|
+
#define CM_PWM (0x201010a0) // 0x7e1010a0
|
58
|
+
|
59
|
+
|
60
|
+
#endif /* __CLK_H__ */
|