X-Git-Url: https://oss.titaniummirror.com/gitweb?a=blobdiff_plain;f=main.c;h=e98dd0474b6a05b6e26f73c936899f3a82fc9728;hb=4f58810d846981a1c180c60aa617fdcaba44d1a7;hp=840d83aab4542727f239d6614fca593239885f84;hpb=5b10a3069f7ca5913d81892ea67160848bb4955e;p=rgblamp.git diff --git a/main.c b/main.c index 840d83a..e98dd04 100644 --- a/main.c +++ b/main.c @@ -15,8 +15,8 @@ * - ( 9) RB3 - CCP1 PWM for red LED * - (10) RB4 - rocker switch position B (right) * - (11) RB5 - rocker switch position A (left) - * - (12) RB6 - unused - * - (13) RB7 - unused + * - (12) RB6 - unused (future crystal) + * - (13) RB7 - unused (future crystal) * - (14) Vdd * - (15) RA6 - unused * - (16) RA7 - CCP2 PWM for grn LED @@ -29,13 +29,19 @@ #include #include "picinit.h" #include "unused.h" -#include "buttons.h" +#include "btn.h" #include "rgb.h" -#include "timer.h" +#include "tmr.h" +#include "task.h" +#include "adc_random.h" -#define AUTO_OFF_COUNT 549316UL /* 5 hrs in 32.768 ms units */ -#define reset_steps() do { incolor_steps = 1; fade_steps = 0; } \ - while (0) +#if 0 +#define AUTO_OFF_COUNT 549316UL /* 5 hrs in 32.768 ms units */ +#define AUTO_ON_COUNT 2087402UL /* 19 hrs in 32.768 ms units */ +#else +#define AUTO_OFF_COUNT 1831 /* 1 minute in 32.768 ms units */ +#define AUTO_ON_COUNT 3662 /* 2 minutes in 32.768 ms units */ +#endif #define rand_u8() (rand() & 0xff) #define rand_u16() ((rand() << 8) + rand_u8()) #define rand_incolor_steps(s) (min_incolor_steps[s & 3] + \ @@ -43,26 +49,23 @@ #define rand_fade_steps(s) (min_fade_steps[s & 3] + \ (rand() % range_fade_steps[s & 3])) #define leds_set(r,g,b,w) rgb_set((r).value >> 7, \ - (g).value >> 7, \ - (b).value >> 7, \ - 0) - -#define dbgpin_init() \ -do { \ - /* Set RA2 as output low */ \ - PORTA &= ~0x04; \ - TRISA &= ~0x04; \ -} while (0) - -#define dbgpin_high() PORTA |= 0x04; -#define dbgpin_low() PORTA &= ~0x04; + (g).value >> 7, \ + (b).value >> 7, \ + 0) +#define dbgpin_init() do { \ + /* Set RA2 as output low */ \ + RA2 = 0; \ + TRISA2 = 0; \ + } while (0) +#define dbgpin_high() (RA2 = 1) +#define dbgpin_low() (RA2 = 0) +#define dbgpin_toggle() (RA2 = (LATA2 == 0) ? 1 : 0) typedef struct { int value; int increment; - char remainder; + signed char remainder; } led_t; -#define INIT_LED { 0, 0, 0 } /* The index of all step arrays is the speed variable */ #if 1 @@ -77,108 +80,195 @@ const static int min_fade_steps[4] = { 64, 32, 16, 8 }; const static int range_fade_steps[4] = { 1, 1, 1, 1 }; #endif -int main(void) +led_t red; +led_t grn; +led_t blu; +led_t wht; +bit on; +unsigned char speed; +int fade_steps; + +void start_fade() +{ + /* RGB PWM values are 8 bits, but computations are done in 15 + * (leaving room for a sign bit), so leds_set() uses >>7 to convert + * to PWM values. + */ + int newr, newg, newb, neww; + + /* New RGB values; all zero is not a valid option */ + do { + newr = rand(); + newg = rand(); + newb = rand(); + neww = rand(); + } while (newr == 0 && newg == 0 && newb == 0 && neww == 0); + + /* Random # of steps to reach the new color */ + fade_steps = rand_fade_steps(speed); + + /* Compute increment per fade step, and remainder, for each led */ + red.increment = (newr - red.value) / fade_steps; + red.remainder = newr - (red.value + red.increment * fade_steps); + grn.increment = (newg - grn.value) / fade_steps; + grn.remainder = newg - (grn.value + grn.increment * fade_steps); + blu.increment = (newb - blu.value) / fade_steps; + blu.remainder = newb - (blu.value + blu.increment * fade_steps); + wht.increment = (neww - wht.value) / fade_steps; + wht.remainder = neww - (wht.value + wht.increment * fade_steps); + + /* Start the fade timer */ + tmr_startPeriodic(TMR_FADE, 1); /* 32.768 msec */ +} + +void turnOn() +{ + dbgpin_high(); + on = 1; + red.value = 0; + grn.value = 0; + blu.value = 0; + wht.value = 0; + leds_set(red, grn, blu, wht); + rgb_on(); + start_fade(); +} + +void turnOff() +{ + /* Event on to off, either by switch or auto-off timer */ + tmr_stop(TMR_INCOLOR); + tmr_stop(TMR_FADE); + rgb_off(); + dbgpin_low(); + on = 0; +} + +void pb_task() +{ + if (btn_pb() == BTN_PB_UP) { + speed = (speed + 1) & ~4; + tmr_stop(TMR_INCOLOR); + start_fade(); + } + btn_pben(); +} + +void rs_task() +{ + switch (btn_rs()) { + case BTN_RS_OFF: + tmr_stop(TMR_AUTO_OFFON); + turnOff(); + break; + case BTN_RS_RIGHT: + tmr_start(TMR_AUTO_OFFON, AUTO_OFF_COUNT); + /* fall through */ + case BTN_RS_LEFT: + turnOn(); + break; + } + btn_rsen(); +} + +void fade_task() { - led_t red = INIT_LED; - led_t grn = INIT_LED; - led_t blu = INIT_LED; - led_t wht = INIT_LED; - unsigned char speed = 0; - unsigned incolor_steps; - int fade_steps; - unsigned long auto_off = 0; - - - pic_init(); - unused_init(); - buttons_init(); - rgb_init(); - timer_init(); - dbgpin_init(); - - reset_steps(); - if (buttons_on()) - rgb_on(); - - dbgpin_high(); - while (1) { - unsigned char buttons = buttons_read(); - - if ((buttons & IN_ROCKERB) && auto_off == 0) - auto_off = AUTO_OFF_COUNT; - - if (((buttons & IN_ROCKERB) && auto_off && --auto_off == 0) || - (!(buttons & (IN_ROCKERA | IN_ROCKERB)))) { - /* Sleep when auto-off time has expired or if rocker switch is - * turned off. - */ - rgb_off(); - dbgpin_low(); - auto_off = 0; - buttons_sleep(); - dbgpin_high(); - reset_steps(); - rgb_on(); - red.value = 0; - grn.value = 0; - blu.value = 0; - wht.value = 0; - } else { - /* Crappy way to detect rising edges to change state of speed var */ - if (!(speed & 4) && (buttons & IN_PUSHBTN)) - speed |= 4; - else if ((speed & 4) && !(buttons & IN_PUSHBTN)) { - speed = (speed + 1) & ~4; - reset_steps(); - } - - if (fade_steps) { - fade_steps--; - /* Continue the in-progress fade */ - red.value += red.increment; - grn.value += grn.increment; - blu.value += blu.increment; - wht.value += wht.increment; - if (fade_steps == 0) { - red.value += red.remainder; - grn.value += grn.remainder; - blu.value += blu.remainder; - wht.value += wht.remainder; - } - leds_set(red, grn, blu, wht); - } else if (--incolor_steps == 0) { - int newr, newg, newb, neww, tmp; - - /* Next led color. All off is not a valid option. - * RGB values are stored and processed as 15-bit non-negative - * integers. Since the RGB pwm values are 8 bits in width, - * leds_set() uses >> 7 to convert each color's value. - */ - do { - newr = rand(); - newg = rand(); - newb = rand(); - neww = rand(); - } while (newr == 0 && newg == 0 && newb == 0 && neww == 0); - - /* Next incolor and fade steps */ - incolor_steps = rand_incolor_steps(speed); - fade_steps = (buttons & IN_ROCKERA) ? 1 : rand_fade_steps(speed); - - /* Compute increment and remainder for each led */ - red.increment = (newr - red.value) / fade_steps; - red.remainder = newr - (red.value + red.increment * fade_steps); - grn.increment = (newg - grn.value) / fade_steps; - grn.remainder = newg - (grn.value + grn.increment * fade_steps); - blu.increment = (newb - blu.value) / fade_steps; - blu.remainder = newb - (blu.value + blu.increment * fade_steps); - wht.increment = (neww - wht.value) / fade_steps; - wht.remainder = neww - (wht.value + wht.increment * fade_steps); - } - dbgpin_low(); - timer_owait(); /* wait 32 ms since last return from last call() */ - dbgpin_high(); - } + red.value += red.increment; + grn.value += grn.increment; + blu.value += blu.increment; + wht.value += wht.increment; + if (--fade_steps == 0) { + /* This is the last fade step. Finalize the RGB led states and decide how + * long to stay in this color. + */ + red.value += red.remainder; + grn.value += grn.remainder; + blu.value += blu.remainder; + wht.value += wht.remainder; + tmr_stop(TMR_FADE); + tmr_start(TMR_INCOLOR, rand_incolor_steps(speed)); + } + leds_set(red, grn, blu, wht); +} + +void auto_offon_task() +{ + if (on) { + turnOff(); + if (btn_rs() == BTN_RS_RIGHT) + tmr_start(TMR_AUTO_OFFON, AUTO_ON_COUNT); + } else /* off */ { + turnOn(); + if (btn_rs() == BTN_RS_RIGHT) + tmr_start(TMR_AUTO_OFFON, AUTO_OFF_COUNT); + } +} + +void user_boot() +{ + dbgpin_high(); + srand((adc_random() << 8) + adc_random()); + pb_task(); + rs_task(); +} + +void user_tasks(unsigned char block) +{ + task_id_t tid; + + while ((tid = task_get(block)) >= 0) { + switch (tid) { + case TASK_BTN_PB: /* pushbutton state change */ + pb_task(); + break; + case TASK_BTN_RS: /* rocker switch state change */ + rs_task(); + break; + case TASK_FADE: /* fade timer has fired */ + fade_task(); + break; + case TASK_INCOLOR: /* in-color timer has fired */ + start_fade(); + break; + case TASK_AUTO_OFFON: /* auto on/off timer has fired */ + auto_offon_task(); + break; } - return 0; + } +} + +int main(void) +{ + /* Platform initialization */ + pic_init(); + unused_init(); + btn_init(); + rgb_init(); + tmr_init(); + task_init(); + dbgpin_init(); + +#if 0 + /* Execute tasks until the queue empties */ + user_tasks(0); +#endif + +#if 0 + /* Software initialization */ +#endif + +#if 0 + /* Execute tasks until the queue empties */ + user_tasks(0); +#endif + + /* Run user boot code */ + user_boot(); + + /* Process tasks forever */ + user_tasks(1); + + /* Prevent return from main, which causes a device reset */ + while (1); } +