From bdb1e0ae6aa9374becf3ae012e30d1f806841e88 Mon Sep 17 00:00:00 2001 From: "R. Steve McKown" Date: Sun, 11 Dec 2011 19:46:33 -0700 Subject: [PATCH] Add tmr32 module * tmr32 module uses Timer 1 + crystal * Use tmr32 to time auto on and off events * Put the CPU in sleep when off, either by switch or timer. Use the tmr32 module or a button ISR to wake back up. --- isr.c | 4 ++-- main.c | 24 ++++++++++++++++-------- task_defs.h | 2 +- tmr32.c | 43 +++++++++++++++++++++++++++++++++++++++++++ tmr32.h | 35 +++++++++++++++++++++++++++++++++++ 5 files changed, 97 insertions(+), 11 deletions(-) create mode 100644 tmr32.c create mode 100644 tmr32.h diff --git a/isr.c b/isr.c index 8db018f..957fc49 100644 --- a/isr.c +++ b/isr.c @@ -7,6 +7,7 @@ #include #include "tmr.h" +#include "tmr32.h" #include "btn.h" #include "task.h" @@ -32,9 +33,8 @@ void interrupt isr() { tmr_isr(); btn_isr(); + tmr32_isr(); - if (tmr_fired(TMR_AUTO_OFFON)) - task_post(TASK_AUTO_OFFON); if (tmr_fired(TMR_FADE)) task_post(TASK_FADE); if (tmr_fired(TMR_INCOLOR)) diff --git a/main.c b/main.c index 6d20042..0726aaf 100644 --- a/main.c +++ b/main.c @@ -41,11 +41,17 @@ #include "btn.h" #include "rgb.h" #include "tmr.h" +#include "tmr32.h" #include "task.h" #include "adc_random.h" -#define AUTO_OFF_COUNT 549316UL /* 5 hrs in 32.768 ms units */ -#define AUTO_ON_COUNT 2087402UL /* 19 hrs in 32.768 ms units */ +#if 1 +#define AUTO_OFF_COUNT 1800U /* 1 hr in 2 sec units */ +#define AUTO_ON_COUNT 19800U /* 11 hrs in 2 sec units */ +#else +#define AUTO_OFF_COUNT 9000U /* 5 hrs in 2 sec units */ +#define AUTO_ON_COUNT 34200U /* 19 hrs in 2 sec units */ +#endif #define leds_set(r,g,b,w) rgb_set((r).value >> 7, (g).value >> 7, \ (b).value >> 7, 0) #define dbgpin_init() do { \ @@ -136,6 +142,7 @@ void turnOff() tmr_stop(TMR_FADE); rgb_off(); dbgpin_low(); + SLEEP(); on = 0; } @@ -153,19 +160,19 @@ void pb_task() void rs_task() { + btn_rsen(); switch (btn_rs()) { case BTN_RS_OFF: - tmr_stop(TMR_AUTO_OFFON); + tmr32_set(0); turnOff(); break; case BTN_RS_RIGHT: - tmr_start(TMR_AUTO_OFFON, AUTO_OFF_COUNT); + tmr32_set(AUTO_OFF_COUNT); /* fall through */ case BTN_RS_LEFT: turnOn(); break; } - btn_rsen(); } void fade_task() @@ -194,11 +201,11 @@ void auto_offon_task() if (on) { turnOff(); if (btn_rs() == BTN_RS_RIGHT) - tmr_start(TMR_AUTO_OFFON, AUTO_ON_COUNT); + tmr32_set(AUTO_ON_COUNT); } else /* off */ { turnOn(); if (btn_rs() == BTN_RS_RIGHT) - tmr_start(TMR_AUTO_OFFON, AUTO_OFF_COUNT); + tmr32_set(AUTO_OFF_COUNT); } } @@ -227,7 +234,7 @@ void user_tasks(unsigned char block) case TASK_INCOLOR: /* in-color timer has fired */ start_fade(); break; - case TASK_AUTO_OFFON: /* auto on/off timer has fired */ + case TASK_TMR32: /* auto on/off event */ auto_offon_task(); break; } @@ -242,6 +249,7 @@ int main(void) btn_init(); rgb_init(); tmr_init(); + tmr32_init(); task_init(); dbgpin_init(); diff --git a/task_defs.h b/task_defs.h index 2a43168..dac07dd 100644 --- a/task_defs.h +++ b/task_defs.h @@ -21,7 +21,7 @@ enum { TASK_BTN_RS, TASK_FADE, TASK_INCOLOR, - TASK_AUTO_OFFON, + TASK_TMR32, TASK_COUNT }; diff --git a/tmr32.c b/tmr32.c new file mode 100644 index 0000000..a5dc5d5 --- /dev/null +++ b/tmr32.c @@ -0,0 +1,43 @@ +/* + * File: tmr32.c + * + * A very simple module that triggers an ISR once every 2 seconds. tmr32 relies + * on Timer 1 and a watch crystal. + */ + + +#include +#include "tmr32.h" +#include "isr.h" +#include "task.h" + +static unsigned _tmr32_count; + +void tmr32_init() +{ + /* Configure Timer 1 */ + T1CON = 0b10001001; + while (!T1OSCR); + + /* Setup timer to run during sleep, and wake CPU on overflow */ + nT1SYNC = 1; + TMR1IE = 1; + PEIE = 1; + GIE = 1; +} + +void tmr32_set(unsigned twosecs) +{ + ndi(); + _tmr32_count = twosecs; + nei(); +} + +void tmr32_isr() +{ + if (TMR1IF) { + TMR1IF = 0; + if (_tmr32_count && --_tmr32_count == 0) + task_post(TASK_TMR32); + } +} diff --git a/tmr32.h b/tmr32.h new file mode 100644 index 0000000..f5691b8 --- /dev/null +++ b/tmr32.h @@ -0,0 +1,35 @@ +/* + * File: tmr32.h + * + * A very simple module that triggers an ISR once every 2 seconds. tmr32 relies + * on Timer 1 and a watch crystal. + * + * Later tmr and tmr32 modules can merge into a generic solution. To that end, + * one should note that Timer 1 must be in sync to use a compare moudule when + * the CPU is running, and it must not be synced to run while the CPU is in + * sleep. When in sleep, the comparator can't work, but Timer 1 overflow events + * will trigger and wake the CPU. + */ + +#ifndef _TMR32_H +#define _TMR32_H + +/* Initialize the tmr subsystem */ +void tmr32_init(); + +/* Set the number of seconds, which is decremented by 2 every 2 seconds. When + * zero is reached, TASK_TMR32 is posted. + */ +void tmr32_set(unsigned twosecs); + +/* The tmr32 isr */ +void tmr32_isr(); + +/* Wait for c clocks, 0 <= c < 32768. */ +#define tmr32_cwait(c) \ + do { \ + unsigned t0 = TMR1; \ + while (TMR0 - t0 <= c); \ + } while (0) + +#endif -- 2.39.2