diff --git a/firmware/target/arm/imx233/button-imx233.c b/firmware/target/arm/imx233/button-imx233.c index 4ebba41ad3..a77d3d76c9 100644 --- a/firmware/target/arm/imx233/button-imx233.c +++ b/firmware/target/arm/imx233/button-imx233.c @@ -42,6 +42,11 @@ static int hold_idx = -1; /* index of hold button in map */ static int jack_idx = -1; /* index of jack detect in map */ #endif +/* LRADC margin for buttons */ +#ifndef IMX233_BUTTON_LRADC_MARGIN +#define IMX233_BUTTON_LRADC_MARGIN 30 +#endif + /* shortcut of button map */ #define MAP imx233_button_map @@ -89,7 +94,21 @@ static bool imx233_button_read_cooked(int idx) int rel = MAP[idx].u.lradc.relative; if(rel != -1) raw = (raw * MAP[rel].u.lradc.value) / imx233_button_read_raw(rel); - res = abs(raw - MAP[idx].u.lradc.value) <= 30; + switch(MAP[idx].u.lradc.op) + { + case IMX233_BUTTON_EQ: + res = abs(raw - MAP[idx].u.lradc.value) <= MAP[idx].u.lradc.margin; + break; + case IMX233_BUTTON_GT: + res = raw > MAP[idx].u.lradc.value; + break; + case IMX233_BUTTON_LT: + res = raw < MAP[idx].u.lradc.value; + break; + default: + res = false; + break; + } } else if(MAP[idx].periph == IMX233_BUTTON_PSWITCH) { @@ -214,6 +233,9 @@ void imx233_button_init(void) } else if(MAP[i].periph == IMX233_BUTTON_LRADC) { + /* use default value for margin */ + if(MAP[i].u.lradc.margin == 0) + MAP[i].u.lradc.margin = IMX233_BUTTON_LRADC_MARGIN; int src = MAP[i].u.lradc.src; /* if channel was already acquired, there is nothing to do */ if(src_mask & (1 << src)) @@ -258,4 +280,4 @@ void imx233_button_init(void) /* otherwise we need to regularly poll for other buttons */ else tick_add_task(do_round); -} \ No newline at end of file +} diff --git a/firmware/target/arm/imx233/button-imx233.h b/firmware/target/arm/imx233/button-imx233.h index 27ae03c63f..9e244e01ac 100644 --- a/firmware/target/arm/imx233/button-imx233.h +++ b/firmware/target/arm/imx233/button-imx233.h @@ -42,6 +42,11 @@ #define IMX233_BUTTON_INVERTED (1 << 0) /* invert button detection */ #define IMX233_BUTTON_PULLUP (1 << 1) /* pin needs a pullup (GPIO) */ +/* values for the .op field */ +#define IMX233_BUTTON_EQ 0 /* channel is equal to value up to error margin */ +#define IMX233_BUTTON_GT 1 /* channel is greater than value */ +#define IMX233_BUTTON_LT 2 /* channel is less than value */ + /** target-defined * NOTE for proper operation: * - the table must end which a dummy entry of type IMX233_BUTTON_END @@ -68,7 +73,9 @@ struct imx233_button_map_t struct { int src; /* source channel */ - int value; /* expected value */ + int value; /* comparison value */ + int op; /* comparison operation */ + int margin; /* error margin for equal operation (0 means default) */ int relative; /* button to which it is relative or -1 if none */ }lradc; struct @@ -84,12 +91,17 @@ struct imx233_button_map_t int threshold; /* round threshold for acceptance */ }; -/* macros for the common cases */ +/* macros for the common cases (see below for explanation) */ + #define IMX233_BUTTON_PATH_GPIO(bank_, pin_) .periph = IMX233_BUTTON_GPIO, \ .u = {.gpio = {.bank = bank_, .pin = pin_}} -#define IMX233_BUTTON_PATH_LRADC_REL(src_, val_, rel_) .periph = IMX233_BUTTON_LRADC, \ - .u = {.lradc = {.src = src_, .value = val_, .relative = rel_}} -#define IMX233_BUTTON_PATH_LRADC(src_, val_) IMX233_BUTTON_PATH_LRADC_REL(src_, val_, -1) +#define IMX233_BUTTON_PATH_LRADC_EX(src_, op_, val_, rel_, margin_) .periph = IMX233_BUTTON_LRADC, \ + .u = {.lradc = {.src = src_, .value = val_, .relative = rel_, .margin = margin_, \ + .op = IMX233_BUTTON_##op_}} +#define IMX233_BUTTON_PATH_LRADC_REL(src_, val_, rel_) \ + IMX233_BUTTON_PATH_LRADC_EX(src_, EQ, val_, rel_, 0) +#define IMX233_BUTTON_PATH_LRADC(src_, val_) \ + IMX233_BUTTON_PATH_LRADC_REL(src_, val_, -1) #define IMX233_BUTTON_PATH_PSWITCH(lvl_) .periph = IMX233_BUTTON_PSWITCH, \ .u = {.pswitch = {.level = lvl_}} #define IMX233_BUTTON_PATH_END() .periph = -1 @@ -126,6 +138,10 @@ struct imx233_button_map_t * - GPIO(bank, pin) * - LRADC(src, value) * - LRADC_REL(src, value, rel_idx) + * - LRADC_EX(src, op, val, rel_idx, margin) where op must one of EQ, GT, LT + * and margin is the error margin for EQ (use 0 for default value). Operation + * EQ means the src value must match val within error margin. Operation GT + * (resp. LT) means src value must greater (resp. lower) than val. * - PSWITCH(level) * - END() * The optional flags are specified as a list, without the IMX233_BUTTON_ prefix. @@ -146,6 +162,12 @@ struct imx233_button_map_t * * The driver also provides default implementations for headphones_inserted() * and button_hold() which can be overriden since they have weak linkage. + * + * The button-target.h header can also define IMX233_BUTTON_LRADC_MARGIN + * to control the error margin allowed for button using LRADC. The default + * margin is 30. Obviously, the margin should be less than M/2 where M is the + * minimum LRADC value between two buttons. The margin can be overriden one a + * per button basis using LRADC_EX. */ extern struct imx233_button_map_t imx233_button_map[]; diff --git a/firmware/target/arm/imx233/debug-imx233.c b/firmware/target/arm/imx233/debug-imx233.c index 916ec33518..fa913a9532 100644 --- a/firmware/target/arm/imx233/debug-imx233.c +++ b/firmware/target/arm/imx233/debug-imx233.c @@ -1039,36 +1039,50 @@ bool dbg_hw_info_button(void) { bool val = imx233_button_read_btn(i); int raw = imx233_button_read_raw(i); + char type[20]; char path[128]; char flags[128]; if(MAP[i].periph == IMX233_BUTTON_GPIO) - snprintf(path, sizeof(path), "gpio(%d,%d)", MAP[i].u.gpio.bank, MAP[i].u.gpio.pin); + { + snprintf(type, sizeof(type), "gpio"); + snprintf(path, sizeof(path), "bank=%d pin=%d", MAP[i].u.gpio.bank, MAP[i].u.gpio.pin); + } else if(MAP[i].periph == IMX233_BUTTON_LRADC) { - if(MAP[i].u.lradc.relative == -1) - snprintf(path, sizeof(path), "adc(%d,%d)", MAP[i].u.lradc.src, - MAP[i].u.lradc.value); + static const char *op_name[] = + { + [IMX233_BUTTON_EQ] = "eq", + [IMX233_BUTTON_GT] = "gt", + [IMX233_BUTTON_LT] = "lt" + }; + char rel_name[20]; + snprintf(type, sizeof(type), "adc"); + if(MAP[i].u.lradc.relative != -1) + snprintf(rel_name, sizeof(rel_name), " %s", MAP[MAP[i].u.lradc.relative].name); else - snprintf(path, sizeof(path), "adc(%d,%d,%s)", MAP[i].u.lradc.src, - MAP[i].u.lradc.value, MAP[MAP[i].u.lradc.relative].name); + rel_name[0] = 0; + snprintf(path, sizeof(path), "%d %s %d%s %d", MAP[i].u.lradc.src, + op_name[MAP[i].u.lradc.op], MAP[i].u.lradc.value, rel_name, + MAP[i].u.lradc.margin); } else if(MAP[i].periph == IMX233_BUTTON_PSWITCH) - snprintf(path, sizeof(path), "pswith(%d)", MAP[i].u.pswitch.level); + { + snprintf(type, sizeof(type), "psw"); + snprintf(path, sizeof(path), "level=%d", MAP[i].u.pswitch.level); + } else + { + snprintf(type, sizeof(type), "unk"); snprintf(path, sizeof(path), "unknown"); + } flags[0] = 0; if(MAP[i].flags & IMX233_BUTTON_INVERTED) strcat(flags, " inv"); if(MAP[i].flags & IMX233_BUTTON_PULLUP) strcat(flags, " pull"); -#if LCD_WIDTH < 240 - lcd_putsf(0, line++, "%s: %d[%d/%d] r=%d", MAP[i].name, val, - MAP[i].rounds, MAP[i].threshold, raw); - lcd_putsf(0, line++, " %s%s", path, flags); -#else - lcd_putsf(0, line++, "%s: %d[%d/%d] r=%d %s%s", MAP[i].name, val, - MAP[i].rounds, MAP[i].threshold, raw, path, flags); -#endif + lcd_putsf(0, line++, "%s %d %d/%d %d %s", MAP[i].name, val, + MAP[i].rounds, MAP[i].threshold, raw, type); + lcd_putsf(0, line++, " %s%s", path, flags); } #undef MAP