labsw/fw/labsw.c: improved debouncing and cleaned up button logic

This commit is contained in:
Werner Almesberger 2011-09-11 13:03:20 -03:00
parent 165d799b17
commit a400f9a018
1 changed files with 81 additions and 42 deletions

View File

@ -24,7 +24,60 @@
int local = 1;
#define DEBOUNCE_CYCLES 10
/*
* SDCC complains a lot about code that's unreachable due to constant
* conditional expressions.
*/
#pragma disable_warning 126 /* unreachable code */
/* ----- Button debouncing ------------------------------------------------- */
/* In the version of 2011-09-11, 10000 cycles are about 128 ms */
#define PREBOUNCE_CYCLES 2000
#define POSTBOUNCE_CYCLES 5000
#define TURN(ch, on) \
do { \
CH##ch##_RELAY = on; \
CH##ch##_OPT = !on; \
if (on) \
LED(CH##ch, R); \
else \
LED(CH##ch, G); \
} while (0)
#define DEBOUNCE(BUT, but) \
do { \
last_##but = but_##but; \
if (postbounce_##but) { \
postbounce_##but--; \
break; \
} \
if (but_##but == !BUT_##BUT) { \
prebounce_##but = 0; \
break; \
} \
if (prebounce_##but != PREBOUNCE_CYCLES) { \
prebounce_##but++; \
break; \
} \
prebounce_##but = 0; \
postbounce_##but = POSTBOUNCE_CYCLES; \
but_##but = !but_##but; \
} while (0)
#define PRESSED(but) (but_##but && !last_##but)
#define RELEASED(but) (!but_##but && last_##but)
/* ----- LED and channel control ------------------------------------------- */
#define IS_ON(ch) (CH##ch##_RELAY || !CH##ch##_OPT)
@ -36,21 +89,15 @@ int local = 1;
#define LED_G_COLOR_G 1
#define LED_G_COLOR_OFF 0
#define LED(ch, color) \
do { \
LED_##ch##_R = LED_R_COLOR_##color; \
LED_##ch##_G = LED_G_COLOR_##color; \
} while (0)
#define TURN(ch, on) \
do { \
CH##ch##_RELAY = on; \
CH##ch##_OPT = !on; \
if (on) \
LED(CH##ch, R); \
else \
LED(CH##ch, G); \
} while (0)
/* ----- I/O setup --------------------------------------------------------- */
static void init_io(void)
@ -78,11 +125,15 @@ static void init_io(void)
}
/* ----- Main loop --------------------------------------------------------- */
void main(void)
{
int debounce_main = 0, last_main = 0, but_main = 0;
int debounce_ch1 = 0, last_ch1 = 0, but_ch1 = 0;
int debounce_ch2 = 0, last_ch2 = 0, but_ch2 = 0;
int prebounce_main = 0, postbounce_main = 0;
int last_main = 0, but_main = 0;
int prebounce_ch1 = 0, postbounce_ch1 = 0, last_ch1 = 0, but_ch1 = 0;
int prebounce_ch2 = 0, postbounce_ch2 = 0, last_ch2 = 0, but_ch2 = 0;
init_io();
usb_init();
@ -93,34 +144,15 @@ void main(void)
TURN(2, 0);
while (1) {
if (debounce_main)
debounce_main--;
else {
last_main = but_main;
but_main = !BUT_MAIN;
if (last_main != but_main)
debounce_main = DEBOUNCE_CYCLES;
}
DEBOUNCE(MAIN, main);
DEBOUNCE(CH1, ch1);
DEBOUNCE(CH2, ch2);
if (debounce_ch1)
debounce_ch1--;
else {
last_ch1 = but_ch1;
but_ch1 = !BUT_CH1;
if (last_ch1 != but_ch1)
debounce_ch1 = DEBOUNCE_CYCLES;
}
if (debounce_ch2)
debounce_ch2--;
else {
last_ch2 = but_ch2;
but_ch2 = !BUT_CH2;
if (last_ch2 != but_ch2)
debounce_ch2 = DEBOUNCE_CYCLES;
}
if (but_main && !last_main) {
/*
* Pressing MAIN forces local mode. Pressing it in local mode,
* it turns off both front channels.
*/
if (PRESSED(main)) {
if (local) {
TURN(1, 0);
TURN(2, 0);
@ -128,6 +160,9 @@ void main(void)
local = 1;
}
/*
* Update LEDs in local mode.
*/
if (local) {
LED(MAIN, G);
if (IS_ON(1))
@ -140,10 +175,14 @@ void main(void)
TURN(2, 0);
}
/*
* In local mode, buttons CH1 and CH2 toggle the respective
* channel.
*/
if (local) {
if (but_ch1 && !last_ch1)
if (PRESSED(ch1))
TURN(1, !IS_ON(1));
if (but_ch2 && !last_ch2)
if (PRESSED(ch2))
TURN(2, !IS_ON(2));
}