{
if (IOCIF) {
if (IOCBF0) {
- _btn_pbdis();
+ btn_pbdis();
tmr_start(TMR_BTN_PB, 1);
}
if (IOCBF4) {
- _btn_rsdis();
+ btn_rsdis();
tmr_start(TMR_BTN_RS, 1);
}
if (IOCBF5) {
- _btn_rsdis();
+ btn_rsdis();
tmr_start(TMR_BTN_RS, 1);
}
}
if (tmr_fired(TMR_BTN_PB))
- _task_post(TASK_BTN_PB);
+ task_post(TASK_BTN_PB);
if (tmr_fired(TMR_BTN_RS))
- _task_post(TASK_BTN_RS);
+ task_post(TASK_BTN_RS);
}
/* Read the current state of the rocker switch */
#define btn_rs() ((RB4 + ((unsigned char)RB5 << 1)) % 3)
-/* Enable the pushbutton from ISR */
-#define _btn_pben() do { \
- IOCBP0 = 1; IOCBN0 = 1; IOCBF0 = 0; \
- } while (0)
-
-/* Disable the pushbutton from ISR */
-#define _btn_pbdis() do { \
- IOCBP0 = 0; IOCBN0 = 0; IOCBF0 = 0; \
- } while (0)
-
-/* Enable the rocker switch from ISR */
-#define _btn_rsen() do { \
- IOCBP4 = 1; IOCBN4 = 1; IOCBF4 = 0; \
- IOCBP5 = 1; IOCBN5 = 1; IOCBF5 = 0; \
- } while (0)
-
-/* Disable the rocker switch from ISR */
-#define _btn_rsdis() do { \
- IOCBP4 = 0; IOCBN4 = 0; IOCBF4 = 0; \
- IOCBP5 = 0; IOCBN5 = 0; IOCBF5 = 0; \
- } while (0)
-
/* Enable the pushbutton from user code */
#define btn_pben() do { \
ndi(); \
- _btn_pben(); \
+ IOCBP0 = 1; IOCBN0 = 1; IOCBF0 = 0; \
nei(); \
} while (0)
/* Disable the pushbutton from user code */
#define btn_pbdis() do { \
ndi(); \
- _btn_pbdis(); \
+ IOCBP0 = 0; IOCBN0 = 0; IOCBF0 = 0; \
nei(); \
} while (0)
/* Enable the rocker switch from user code */
#define btn_rsen() do { \
ndi(); \
- _btn_rsen(); \
+ IOCBP4 = 1; IOCBN4 = 1; IOCBF4 = 0; \
+ IOCBP5 = 1; IOCBN5 = 1; IOCBF5 = 0; \
nei(); \
} while (0)
/* Disable the rocker switch from user code */
#define btn_rsdis() do { \
ndi(); \
- _btn_rsdis(); \
+ IOCBP4 = 0; IOCBN4 = 0; IOCBF4 = 0; \
+ IOCBP5 = 0; IOCBN5 = 0; IOCBF5 = 0; \
nei(); \
} while (0)
#include "btn.h"
#include "task.h"
-bit isr_gie; /* Used to store the state of GIE for nested ndi()/nei() */
-unsigned char isr_di; /* Count of nested ndi() */
+bit _isr_gie; /* Used to store the state of GIE for nested ndi()/nei() */
+unsigned char _isr_di; /* Count of nested ndi() */
void interrupt isr()
{
btn_isr();
if (tmr_fired(TMR_AUTO_OFFON))
- _task_post(TASK_AUTO_OFFON);
+ task_post(TASK_AUTO_OFFON);
if (tmr_fired(TMR_FADE))
- _task_post(TASK_FADE);
+ task_post(TASK_FADE);
if (tmr_fired(TMR_INCOLOR))
- _task_post(TASK_INCOLOR);
+ task_post(TASK_INCOLOR);
#if 0
if (tmr_fired(TMR_DIM))
- _task_post(TMR_DIM);
+ task_post(TMR_DIM);
#endif
}
#include <htc.h>
-extern bit isr_gie;
-extern unsigned char isr_di;
+extern bit _isr_gie;
+extern unsigned char _isr_di;
-/* Nested disable interrupts inline function, for use outside ISR */
+/* Nested disable interrupts inline function. Should be OK even in ISR. */
#define ndi() \
do { \
- if (isr_di++ == 0) \
- isr_gie = GIE; \
- if (isr_gie) \
- di(); \
+ if (_isr_di++ == 0) { \
+ _isr_gie = GIE; \
+ di(); \
+ } \
} while (0)
-/* Nested enable interrupts inline function, for use outside ISR */
+/* Nested enable interrupts inline function. Should be OK even in ISR. */
#define nei() \
do { \
- if (--isr_di == 0) \
- if (isr_gie) { \
- isr_gie = 0; \
- ei(); \
- } \
+ if (--_isr_di == 0 && _isr_gie) \
+ ei(); \
} while (0)
void interrupt isr();
/* Process tasks forever */
user_tasks(1);
+
+ /* Prevent return from main, which causes a device reset */
+ while (1);
}
task_id_t task_get(unsigned char block)
{
- task_id_t t = 0;
+ task_id_t t = -1;
unsigned long ids;
do {
ids = _task_ids;
nei();
if (ids) {
- for (unsigned char i = 0; t == 0 && i < TASK_COUNT; i++) {
- if (ids & (1UL << _task_bitno))
+ for (unsigned char i = 0; t == -1 && i < TASK_COUNT; i++) {
+ if (bit_get(ids, _task_bitno))
t = _task_bitno;
_task_bitno = (_task_bitno + 1) % TASK_COUNT;
}
else
SLEEP();
#endif
- } while (t == 0 && block == 1);
+ } while (t == -1 && block == 1);
+ if (t) {
+ ndi();
+ bit_clr(_task_ids, t);
+ nei();
+ }
return t;
}
-void task_post(task_id_t t)
-{
- ndi();
- _task_post(t);
- nei();
-}
-
#include "task_defs.h"
#include "bit.h"
-typedef unsigned char task_id_t;
+typedef signed char task_id_t;
/* Do not use directly; only for the 'inline' functions below */
extern unsigned long _task_ids;
extern task_id_t _task_bitno;
-/* Post task t from ISR */
-#define _task_post(t) do { _task_ids |= 1UL << t; } while (0)
+/* Post task t. No need for ndi() since bit_set is a single instruction. */
+#define task_post(t) do { bit_set(_task_ids, t); } while (0)
/* Initialize the task subsystem */
#define task_init() do { _task_ids = 0; _task_bitno = 0; } while (0)
*/
task_id_t task_get(unsigned char block);
-/* Post task t from user code */
-void task_post(task_id_t t);
-
#endif
persistent tmr_time_t _tmr_ticks;
tmr_bitno_t _tmr_on;
tmr_bitno_t _tmr_periodic;
-static tmr_bitno_t _tmr_fired;
+static tmr_bitno_t _tmr_flag;
static tmr_time_t _tmr_t0[TMR_COUNT];
static tmr_time_t _tmr_elapsed[TMR_COUNT];
ndi();
bit_set(_tmr_on, t);
bit_clr(_tmr_periodic, t);
- bit_clr(_tmr_fired, t);
+ bit_clr(_tmr_flag, t);
_tmr_t0[t] = _tmr_ticks;
_tmr_elapsed[t] = elapsed;
nei();
ndi();
bit_set(_tmr_on, t);
bit_clr(_tmr_periodic, t);
- bit_clr(_tmr_fired, t);
- _tmr_t0[t] = t0 + elapsed;
+ bit_clr(_tmr_flag, t);
+ _tmr_t0[t] = t0;
nei();
}
ndi();
bit_set(_tmr_on, t);
bit_set(_tmr_periodic, t);
- bit_clr(_tmr_fired, t);
- _tmr_t0[t] = _tmr_ticks + elapsed;
+ bit_clr(_tmr_flag, t);
+ _tmr_t0[t] = _tmr_ticks;
_tmr_elapsed[t] = elapsed;
nei();
}
ndi();
bit_set(_tmr_on, t);
bit_set(_tmr_periodic, t);
- bit_clr(_tmr_fired, t);
- _tmr_t0[t] = t0 + elapsed;
+ bit_clr(_tmr_flag, t);
+ _tmr_t0[t] = t0;
_tmr_elapsed[t] = elapsed;
nei();
}
bit tmr_fired(tmr_bitno_t t)
{
- /* FIXME: if called from ISR ndi()/nei() is not required */
- static unsigned char last_fired;
unsigned char fired;
ndi();
- fired = bit_get(_tmr_fired, t) != 0;
+ fired = bit_get(_tmr_flag, t);
if (fired)
- bit_clr(_tmr_fired, t);
+ bit_clr(_tmr_flag, t);
nei();
- return fired;
+ return fired != 0;
}
void tmr_isr()
TMR0IF = 0;
_tmr_ticks++;
for (tmr_bitno_t t = 0; t < TMR_COUNT; t++) {
- if (_tmr_ticks - _tmr_t0[t] <= 0) {
- bit_set(_tmr_fired, t);
+ if (bit_get(_tmr_on, t) && _tmr_ticks - _tmr_t0[t] <= _tmr_elapsed[t]) {
+ bit_set(_tmr_flag, t);
if (bit_get(_tmr_periodic, t))
_tmr_t0[t] += _tmr_elapsed[t];
else
/* FIXME: this may not be atomic WRT ISR */
#define tmr_periodic(t) (bit_get(_tmr_periodic, (t)))
-/* Start a timer, expecting it to fire in elapsed ticks */
+/* Start a timer, expecting it to fire in elapsed ticks, user code */
void tmr_start(tmr_bitno_t t, tmr_time_t elapsed);
/* Start a timer, expecting it to fire in elapsed ticks from t0 */
nei(); \
} while(0)
-/* Return 1 if the timer has fired, resetting the fired bit */
+/* Return 1 if the timer has fired, resetting the fired bit, user code */
bit tmr_fired(tmr_bitno_t t);
/* Return the current number of timer ticks, for use outside ISR */
#define tmr_cwait(c) \
do { \
unsigned t0 = TMR0; \
- while ((unsigned)(TMR0 - t0) <= c); /* cast prevents integral promotion */ \
+ while (TMR0 - t0 <= c); /* cast prevents integral promotion */ \
} while (0)
/* Wait for a number of us. This is pretty accurate. */