X-Git-Url: https://oss.titaniummirror.com/gitweb?a=blobdiff_plain;f=main.c;h=65cff5565ab684b1d875cdc5e0667a5c10dab461;hb=65079ad3f1ecdbcfc6c8d35040a818994f8af94f;hp=3e8a52d12cb75e375ce71b767fd62fe338a73ab0;hpb=22ef3537176d9839409dd5cdf06fc6a03cee3b0b;p=rgblamp.git diff --git a/main.c b/main.c index 3e8a52d..65cff55 100644 --- a/main.c +++ b/main.c @@ -1,116 +1,190 @@ /* * File: main.c * - * Created on August 16, 2010, 12:09 PM + * PWM test program + * + * PIC resources in use, 18-pin DIP, by pin: + * - ( 1) RA2 - unused + * - ( 2) RA3 - CCP3 PWM for blu LED + * - ( 3) RA4 - CCP4 PWM for wht LED. ICSP pin 6, PGM/LVP. + * - ( 4) RA5 - ICSP pin 1, MCLR#/Vpp + * - ( 5) Vss + * - ( 6) RB0 - pushbutton + * - ( 7) RB1 - unused + * - ( 8) RB2 - unused + * - ( 9) RB3 - CCP1 PWM for red LED + * - (10) RB4 - rocker switch position B (right) + * - (11) RB5 - rocker switch position A (left) + * - (12) RB6 - unused (future crystal) + * - (13) RB7 - unused (future crystal) + * - (14) Vdd + * - (15) RA6 - unused + * - (16) RA7 - CCP2 PWM for grn LED + * - (17) RA0 - unused + * - (18) RA1 - unused + * */ - #include -#include - -#define RUNAT32MHZ /* else 16 MHz */ -#define BRIGHT_STEP 16 /* starts at 0 */ -#define BRIGHT_STEPS 16 /* includes 0 */ -#define LEDBIT 0x01 /* PORTB.3 */ - -#if defined(RUNAT32MHZ) -__CONFIG(WDTE_OFF & FOSC_INTOSC); -__CONFIG(LVP_OFF & PLLEN_ON); +#include +#include "picinit.h" +#include "unused.h" +#include "buttons.h" +#include "rgb.h" +#include "tmr.h" +#include "adc_random.h" + +#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 -__CONFIG(WDTE_OFF); -__CONFIG(LVP_OFF); +#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 - -void pic_init() -{ -#if defined(RUNAT32MHZ) - OSCCON = 0b11110000; -#else /* 16 MHz */ - OSCCON = 0b01111010; +#define reset_steps() do { incolor_steps = 1; fade_steps = 0; } \ + while (0) +#define rand_u8() (rand() & 0xff) +#define rand_u16() ((rand() << 8) + rand_u8()) +#define rand_incolor_steps(s) (min_incolor_steps[s & 3] + \ + (rand() % range_incolor_steps[s & 3])) +#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 */ \ + 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; + signed char remainder; +} led_t; +#define INIT_LED { 0, 0, 0 } + +/* The index of all step arrays is the speed variable */ +#if 1 +const static unsigned min_incolor_steps[4] = { 320, 32, 32, 1 }; +const static unsigned range_incolor_steps[4] = { 32768, 128, 32, 8 }; +const static int min_fade_steps[4] = { 64, 32, 32, 1 }; +const static int range_fade_steps[4] = { 416, 128, 32, 8 }; +#else /* for debugging */ +const static unsigned min_incolor_steps[4] = { 64, 32, 16, 8 }; +const static unsigned range_incolor_steps[4] = { 1, 1, 1, 1 }; +const static int min_fade_steps[4] = { 64, 32, 16, 8 }; +const static int range_fade_steps[4] = { 1, 1, 1, 1 }; #endif - /* OSCSTAT.HFIOFL is set when oscillator is locked (accurate within 2%) */ - while (!HFIOFL); -} - -void pwm_init() -{ - /* Initialize PWM on PORTB.0 - * - Fosc = 32MHz - * - Prescale = 16 - * - PRx value = 0xff - * = f(pwm) = 1.95 kHz - */ - - /* Disable output on PORTB.0 */ - TRISB |= 0x08; - - /* Configure ECCP1 */ - CCP1CON = 0b00001100; - CCPR1L = 0; /* Initial PWM value; only using 8 LSBs */ - - /* Configure Timer2 */ - CCPTMRS = CCPTMRS & ~0x03; /* bits 1:0 denote CCP1 uses Timer 2 */ - TMR2IF = 0; - PR2 = 0xff; - T2CON = 0b00000111; - - /* Enable PWM output, PORTB.0 */ - while (!TMR2IF); /* wait until timer overflow */ - TRISB &= ~0x08; -} - -void led_init() -{ - PORTB &= ~LEDBIT; /* Led is PORTB.3 */ - TRISB &= ~LEDBIT; -} - -void led_set(unsigned short led) -{ - if (led) - PORTB |= LEDBIT; - else - PORTB &= ~LEDBIT; -} - -void pwm_set(unsigned short step) -{ - CCPR1L = step * BRIGHT_STEP; -} - -void delay() -{ - for (unsigned counter = 0; counter < 50000; counter++); -} - int main(void) { - unsigned short fwd = 1; - short int step = 0; - short int led = 0; + 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(); - led_init(); - pwm_init(); + unused_init(); + buttons_init(); + rgb_init(); + tmr_init(); + dbgpin_init(); + + srand((adc_random() << 8) + adc_random()); + reset_steps(); + if (buttons_on()) + rgb_on(); + + dbgpin_high(); + tmr_startPeriodic(TMR_FADE, 1); /* 32.768 msec */ while (1) { - led = 1 - led; - led_set(led); - pwm_set(step); - if (fwd == 0) { - step--; - if (step == -1) { - fwd = 1; - step++; + unsigned char buttons = buttons_read(); + + if ((buttons & IN_ROCKERB) && auto_off == 0) + tmr_startPeriodic(TMR_AUTO_OFFON, AUTO_OFF_COUNT); + + if ((buttons & IN_ROCKERB) && tmr_fired(TMR_AUTO_OFFON) || + (!(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(); } - } else /* fwd == 1 */ { - step++; - if (step == BRIGHT_STEPS) { - fwd = 0; - step--; + + 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; + + /* 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 = 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(); + while (!tmr_fired(TMR_FADE)); + dbgpin_high(); } - delay(); delay(); } return 0; }