+
+void pb_task()
+{
+ static unsigned char pbPrev = BTN_PB_UP;
+ unsigned char pb;
+
+ pb = btn_pb();
+ if (pbPrev == BTN_PB_UP) {
+ if (pb == BTN_PB_UP)
+ pb_clicked();
+ else /* (pb == BTN_PB_DOWN) */ {
+ tmr_startPeriodic(TMR_BTN_PB_HELD, HELD_TMR_PERIODS);
+ pbHeldCount = -HELD_PERIODS;
+ }
+ } else /* if (pbPrev == BTN_PB_DOWN) */ {
+ if (pb == BTN_PB_UP) {
+ tmr_stop(TMR_BTN_PB_HELD);
+ if (pbHeldCount < 0)
+ pb_clicked();
+ } /* nothing to do if button is down */
+ }
+ pbPrev = pb;
+ btn_pben();
+}
+
+void rs_task()
+{
+ btn_rsen();
+ switch (btn_rs()) {
+ case BTN_RS_OFF:
+ tmr32_set(0);
+ turnOff();
+ break;
+ case BTN_RS_RIGHT:
+ tmr32_set(AUTO_OFF_COUNT);
+ /* fall through */
+ case BTN_RS_LEFT:
+ turnOn();
+ break;
+ }
+}
+
+void fade_task()
+{
+ 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);
+ if (mode == MODE_CYCLE)
+ tmr_start(TMR_INCOLOR, STD_INCOLOR);
+ else if (mode == MODE_PARTY)
+ tmr_start(TMR_INCOLOR, PARTY_MIN + (rand() % PARTY_RANGE));
+ }
+ leds_set();
+}
+
+void auto_offon_task()
+{
+ if (on) {
+ turnOff();
+ if (btn_rs() == BTN_RS_RIGHT)
+ tmr32_set(AUTO_ON_COUNT);
+ } else /* off */ {
+ turnOn();
+ if (btn_rs() == BTN_RS_RIGHT)
+ tmr32_set(AUTO_OFF_COUNT);
+ }
+}
+
+void user_boot()
+{
+ dbgpin_high();
+ srand((adc_random() << 8) + adc_random());
+ cfg_read(mode, color);
+ 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_BTN_PB_HELD: /* pushbutton is being held down */
+ pb_held_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_TMR32: /* auto on/off event */
+ auto_offon_task();
+ break;
+ case TASK_CFG: /* Save config to EEPROM event */
+ cfg_write(mode, color);
+ break;
+ }
+ }
+}
+
+int main(void)
+{
+ /* Platform initialization */
+ pic_init();
+ unused_init();
+ btn_init();
+ rgb_init();
+ tmr_init();
+ tmr32_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);
+}
+