1 /******************************************************************************/
3 /******************************************************************************/
5 #include <stdint.h> /* For uint8_t definition */
6 #include <stdbool.h> /* For true/false definition */
8 #include "user.h" /* User funct/params, such as InitApp */
14 /******************************************************************************/
15 /* User Global Variable Declaration */
16 /******************************************************************************/
18 /* i.e. uint8_t <variable_name>; */
21 void RGBWheel(uint16_t pos, uint8_t *r, uint8_t *g, uint8_t *b)
26 *r = (127 - pos % 128);
31 *g = (127 - pos % 128);
43 /* connect Fixed Voltage Reference to A2D convertor
44 * input, set Vdd as reference, read value.
45 * (val / 1024) * Vref == Vdd
47 bool test_battery(void)
51 // Read Vdd by sampling FVR
52 FVRCONbits.ADFVR = 0b10; // 2.048v // 1.024v
53 FVRCONbits.FVREN = 1; // enable
54 while (!FVRCONbits.FVRRDY) {}; // wait for it to stabilise
56 ADCON1bits.ADCS = 0b110; // slowest sample clock
57 ADCON1bits.ADFM = 1; // right justify
58 ADCON0bits.CHS = 0b11111; // FVR input
59 ADCON1bits.ADPREF = 0b00; // +ve ref Vdd
60 ADCON0bits.ADON = 1; // enable ADC
62 ADCON0bits.GO = 1; // start conversion
63 while (ADCON0bits.GO) {}; // wait til finished
65 volt = (ADRESH << 8) | ADRESL;
72 // first pixel faint red, rest black
75 for (i=0; i<RGB_COUNT; i++) *p++=0;
87 static uint8_t random_byte = 0xB4;
89 /* generate a random number */
93 asm("RRF _random_byte,W");
94 asm("BTFSC STATUS,0");
96 asm("MOVWF _random_byte");
101 uint16_t dorand(void)
103 static uint16_t lfsr = 0xACE1u;
104 lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xB400u);
111 #define CHECK_MSEC 5 // sample key every 5 mS
112 #define PRESS_MSEC 10 // stable before presses
113 #define RELEASE_MSEC 100 // stable before released
116 /* test to see if the button has been pressed */
117 bool test_button(void)
119 static bool down = false;
120 static uint8_t count = PRESS_MSEC / CHECK_MSEC;
124 if (PORTAbits.RA1 == 0)
127 count = PRESS_MSEC / CHECK_MSEC;
128 // has been down for the count, flip state
131 count = RELEASE_MSEC / CHECK_MSEC;
134 if (PORTAbits.RA1 == 1)
137 count = RELEASE_MSEC / CHECK_MSEC;
138 // has been back up for the count
139 // flip state, and say we saw one cycle
142 count = PRESS_MSEC / CHECK_MSEC;
153 /* blank everything */
154 for (i=0; i<RGB_COUNT; i++) rgbdata[i]=0;
157 /* how much rainbow to show 0-384 */
158 static const uint32_t quant = 384; //200;
160 bool rainbow_draw(void)
168 for (i=0; i<16; i++) {
169 RGBWheel((i * quant / 16) % 384, &r, &g, &b);
174 for (i=16; i>0; i--) {
175 RGBWheel(((i-1) * quant / 16) % 384, &r, &g, &b);
184 unsigned char rain_delay = RAIN_UNIT;
186 bool rainbow_rotate(void)
188 static unsigned char delay = 0;
195 if ((delay--) > 0) return false;
197 // rotate the colours
204 for (i=0; i<15*3; i++) {
212 // left eye, other direction
219 for (i=0; i<15*3; i++) {
233 colour bouncing blobs mode
236 int8_t rspeed, gspeed, bspeed;
237 #define MAX_SPEED 30;
239 #define MAX_BRIGHT 32
241 bool bouncer_draw(void)
245 rspeed = dorand() % MAX_SPEED;
246 gspeed = dorand() % MAX_SPEED;
247 bspeed = dorand() % MAX_SPEED;
251 for (i=(dorand() % MAX_LEN)+1; i>0; i--) {
252 rgbdata[(3*i)+1] = MAX_BRIGHT;
254 // draw rand len green
255 for (i=(dorand() % MAX_LEN)+1; i>0; i--) {
256 rgbdata[(3*i)] = MAX_BRIGHT;
258 // draw rand len blue
259 for (i=(dorand() % MAX_LEN)+1; i>0; i--) {
260 rgbdata[(3*i)+2] = MAX_BRIGHT;
266 bool bouncer_rotate(uint8_t loop)
271 if (loop % rspeed == 0) {
274 if (rgbdata[ (LED_COUNT-1)*3+1 ] == 0) {
275 // still space to move up
276 p = rgbdata + RGB_COUNT - 5;
277 for (i=LED_COUNT-1; i > 0; i--) {
287 if (rgbdata[1] == 0 || (rgbdata[1]!=0 && rgbdata[4]!=0)) {
288 // still space to move down
290 for (i=LED_COUNT-1; i>0; i++) {
294 rgbdata[RGB_COUNT-2] = 0;
296 rspeed = dorand() % MAX_SPEED;
297 for (i=(dorand() % MAX_LEN)+1; i>0; i--) {
298 rgbdata[(3*i)+1] = MAX_BRIGHT;
303 if (loop % gspeed == 0) {
306 if (rgbdata[ (LED_COUNT-1)*3 ] == 0) {
307 // still space to move up
308 p = rgbdata + RGB_COUNT - 6;
309 for (i=LED_COUNT-1; i > 0; i--) {
319 if (rgbdata[0] == 0 || (rgbdata[0]!=0 && rgbdata[3]!=0)) {
320 // still space to move down
322 for (i=LED_COUNT-1; i>0; i++) {
326 rgbdata[RGB_COUNT-3] = 0;
328 gspeed = dorand() % MAX_SPEED;
329 // draw rand len green
330 for (i=(dorand() % MAX_LEN)+1; i>0; i--) {
331 rgbdata[(3*i)] = MAX_BRIGHT;
336 if (loop % bspeed == 0) {
339 if (rgbdata[ (LED_COUNT-1)*3+2 ] == 0) {
340 // still space to move up
341 p = rgbdata + RGB_COUNT - 4;
342 for (i=LED_COUNT-1; i > 0; i--) {
352 if (rgbdata[2] == 0 || (rgbdata[2]!=0 && rgbdata[5]!=0)) {
353 // still space to move down
355 for (i=LED_COUNT-1; i>0; i++) {
359 rgbdata[RGB_COUNT-1] = 0;
361 bspeed = dorand() % MAX_SPEED;
362 // draw rand len blue
363 for (i=(dorand() % MAX_LEN)+1; i>0; i--) {
364 rgbdata[(3*i)+2] = MAX_BRIGHT;
373 /* fade in and out mode */
374 bool glow_draw(uint8_t r, uint8_t g, uint8_t b)
383 bool glow_rotate(uint8_t loop)
388 uint8_t val = loop & 0x7F;
393 val /= 2; /* range is now 0-63 */
396 g = (uint16_t)gspeed * val / 64;
397 r = (uint16_t)rspeed * val / 64;
398 b = (uint16_t)bspeed * val / 64;
402 for (i=0; i<LED_COUNT; i++) {
411 bool dot_draw(uint8_t r, uint8_t g, uint8_t b)
414 uint8_t *p = rgbdata;
415 for (i=0; i<RGB_COUNT;i++) *(p++)=0;
420 rgbdata[48+0] = g / 8;
421 rgbdata[48+1] = r / 8;
422 rgbdata[48+2] = b / 8;
427 /******************************************************************************/
429 /******************************************************************************/
438 unsigned char mode = 2;
439 bool changed = false;
442 /* Initialize I/O and Peripherals for application */
446 /* initial pattern */
455 CLRWDT(); // tell watchdog we are still awake
457 /* test if the battery is dead, stop if it is */
458 if (test_battery()) {
462 /* if button is pressed, change mode */
464 mode = (mode + 1) % MAX_MODE;
467 // initialise the new mode
470 rain_delay = RAIN_UNIT;
471 changed = rainbow_draw();
474 changed = bouncer_draw();
477 changed = glow_draw(0,255,0);
480 changed = glow_draw(255,0,0);
483 changed = glow_draw(0,0,255);
486 changed = glow_draw(255,0,255);
489 changed = dot_draw(255,255,255);
492 changed = dot_draw(0,8,0);
496 /* otherwise run mode maintenance */
499 changed = rainbow_rotate();
502 changed = bouncer_rotate(loop);
507 changed = glow_rotate(loop);
511 uint16_t n = dorand() % quant;
513 RGBWheel(n, &r, &g, &b);
514 changed = glow_draw(r, g, b);
516 changed = glow_rotate(loop);
519 changed = rainbow_rotate();
522 if (loop==0) changed = rainbow_rotate();
527 /* transmit the latest data set */
528 if (changed) ws2811_transmit();