void menu_key_test(void) { u8 i; u16 bit; // cleanup screen and disable possible low bat warning buzzer_off(); key_beep(); menu_battery_low = 0; // it will be set automatically again battery_low_shutup = 0; // do full screen blink lcd_set_full_on(); delay_menu_always(2); while (btns(BTN_ENTER)) stop(); // wait for release of ENTER lcd_clear(); button_autorepeat(0); // disable autorepeats btnra(); // show intro text lcd_chars("KEY"); lcd_update_stop(); // wait for key while (1) { if (btnl(BTN_BACK | BTN_ENTER)) break; for (i = 0, bit = 1; i < 16; i++, bit <<= 1) { if (btn(bit)) { key_beep(); lcd_chars(key_ids[i]); if (btnl(bit)) lcd_7seg(L7_L); else lcd_set(L7SEG, LB_EMPTY); lcd_update(); break; } } btnra(); stop(); } key_beep(); apply_model_config(); }
int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer BCSCTL1 = CALBC1_8MHZ; // Set DCO to 8Mhz DCOCTL = CALDCO_8MHZ; // Set DCO to 8Mhz P2DIR |= (BIT0|BIT1|BIT2|BIT3); P2OUT |= BIT0|BIT1|BIT2|BIT3; uart_init(); __bis_SR_register(GIE); unsigned char i; while(1) { i = uart_get(); btns(i); } return 0; }
// change val, temporary show new value (not always) // end when another key pressed static u8 menu_popup_key(u8 key_id) { u16 delay_time; u16 buttons_state_last; u16 btnx; config_key_map_s *km = &ck.key_map[key_id]; key_functions_s *kf; key_functions_s *kfl; u8 flags; u8 is_long = 0; u8 *mbs = &menu_buttons_state[key_id]; s16 *pv = &menu_buttons_previous_values[key_id]; // do nothing when both short and long set to OFF if (!km->function && !km->function_long) return 0; // prepare more variables kf = &key_functions[km->function]; btnx = key_buttons[key_id]; // remember buttons state buttons_state_last = buttons_state & ~btnx; // check momentary setting // when something changed, show value for 5s while checking buttons // during initialize show nothing if (km->function && (kf->flags & KF_2STATE) && km->momentary) { static @near u8 ch3_has_middle; // set to 1 if ch3 has middle state u8 state; // new button state u8 value_showed = 0; u16 btnx_orig = btnx; // for CH3 button add MIDDLE state also if (key_id == 0) btnx |= BTN_CH3_MID; while (1) { // set actual state of btnx to buttons_state_last buttons_state_last &= ~btnx; buttons_state_last |= buttons_state & btnx; // check button flags = FF_NONE; state = MBS_RELEASED; if (key_id == 0 && btns(BTN_CH3_MID)) { // special check for CH3 button middle flags |= FF_MID; state = MBS_MIDDLE; ch3_has_middle = 1; } else if (btns(btnx_orig)) { flags |= FF_ON; state = MBS_PRESSED; } if (km->reverse) flags |= FF_REVERSE; if (key_id == 0 && ch3_has_middle) flags |= FF_HAS_MID; if (km->previous_val) flags |= FF_PREVIOUS; // end if button state didn't changed if (state == *mbs) break; // end when initialize if (*mbs == MBS_INITIALIZE) { // call func when not previous_val if (!km->previous_val || state == MBS_PRESSED) kf->func(kf->name, kf->param, flags, pv); *mbs = state; break; } *mbs = state; btnr(btnx); key_beep(); // if value showing disabled, exit if (kf->flags & KF_NOSHOW) break; // if another button was pressed, leave this screen if (buttons) break; if (buttons_state != buttons_state_last) break; // show function id first time if (!value_showed) { value_showed = 1; menu_key_empty_id(); } // call function to set value and show it flags |= FF_SHOW; kf->func(kf->name, kf->param, flags, pv); lcd_update(); // sleep 5s, and if no button was changed during, end this screen delay_time = POPUP_DELAY * 200; while (delay_time && !(buttons & ~btnx) && (buttons_state == buttons_state_last)) delay_time = delay_menu(delay_time); if ((buttons_state & btnx) == (buttons_state_last & btnx)) break; } btnr(btnx); if (value_showed) lcd_menu(0); // set MENU off return value_showed; } // non-momentary key kfl = &key_functions[km->function_long]; // if button is not initialized, do it if (*mbs == MBS_INITIALIZE) { if (km->function && (kf->flags & KF_2STATE) && !km->previous_val) kf->func(kf->name, kf->param, (u8)(km->reverse ? FF_REVERSE : 0), pv); if (km->function_long && (kfl->flags & KF_2STATE) && !km->previous_val_long) kfl->func(kfl->name, kfl->param, (u8)(km->reverse_long ? FF_REVERSE : 0), pv); *mbs = 0; // both are OFF } // return when key was not pressed if (!btn(btnx)) return 0; // clear some lcd segments menu_key_empty_id(); while (1) { if (km->function_long && btnl(btnx)) { // long key press key_beep(); flags = 0; if (!(kfl->flags & KF_NOSHOW)) flags = FF_SHOW; if (kfl->flags & KF_2STATE) { // ON/OFF is only for 2-state if (*mbs & MBS_ON_LONG) { // is ON, switch to OFF *mbs &= (u8)~MBS_ON_LONG; } else { // is OFF, switch to ON *mbs |= MBS_ON_LONG; flags |= FF_ON; } if (km->reverse_long) flags |= FF_REVERSE; if (km->previous_val_long) flags |= FF_PREVIOUS; } kfl->func(kfl->name, kfl->param, flags, pv); // switch value if (kfl->flags & KF_NOSHOW) { btnr(btnx); return 0; } lcd_update(); is_long = 1; } else if (km->function && btn(btnx)) { // short key press key_beep(); flags = 0; if (!(kf->flags & KF_NOSHOW)) flags = FF_SHOW; if (kf->flags & KF_2STATE) { // ON/OFF is only for 2-state if (*mbs & MBS_ON) { // is ON, switch to OFF *mbs &= (u8)~MBS_ON; } else { // is OFF, switch to ON *mbs |= MBS_ON; flags |= FF_ON; } if (km->reverse) flags |= FF_REVERSE; if (km->previous_val) flags |= FF_PREVIOUS; } kf->func(kf->name, kf->param, flags, pv); // switch value if (kf->flags & KF_NOSHOW) { btnr(btnx); return 0; } lcd_update(); } else { // nothing to do btnr(btnx); return 0; } btnr(btnx); // if another button was pressed, leave this screen if (buttons) break; if ((buttons_state & ~btnx) != buttons_state_last) break; // sleep 5s, and if no button was changed during, end this screen delay_time = POPUP_DELAY * 200; while (delay_time && !buttons && ((buttons_state & ~btnx) == buttons_state_last)) delay_time = delay_menu(delay_time); if (!buttons) break; // timeouted without button press if (is_long) { // if long required but short pressed, end if (!btnl(btnx)) break; } else { // if short required, but long pressed with function_long // specified, end if (km->function_long && btnl(btnx)) break; } } // set MENU off lcd_menu(0); return 1; // popup was showed }
static u8 menu_popup_et(u8 trim_id) { u16 delay_time; s16 val; u8 step; u16 buttons_state_last; u16 btn_l = ETB_L(trim_id); u16 btn_r = ETB_R(trim_id); u16 btn_lr = btn_l | btn_r; config_et_map_s *etm = &ck.et_map[trim_id]; #define SF_ROTATE etm->rotate et_functions_s *etf = &et_functions[etm->function]; u8 *mbs = &menu_buttons_state[NUM_KEYS + 2 * trim_id]; // read value RVAL(val); // remember buttons state buttons_state_last = buttons_state & ~btn_lr; // handle momentary keys // when something changed, show value for 5s while checking buttons // during initialize show nothing if (etm->buttons == ETB_MOMENTARY) { s16 *pv = &menu_buttons_previous_values[NUM_KEYS + 2 * trim_id]; u8 value_showed = 0; u8 state; while (1) { // set actual state of btn_lr to buttons_state_last buttons_state_last &= ~btn_lr; buttons_state_last |= buttons_state & btn_lr; // check buttons if (btns(btn_l)) { // left if (*mbs == MBS_LEFT) break; // already was left state = MBS_LEFT; *pv = val; // save previous value val = etm->reverse ? etf->max : etf->min; } else if (btns(btn_r)) { // right if (*mbs == MBS_RIGHT) break; // already was right state = MBS_RIGHT; *pv = val; // save previous value val = etm->reverse ? etf->min : etf->max; } else { // center if (*mbs == MBS_RELEASED) break; // already was center state = MBS_RELEASED; if (etm->previous_val) { if (*mbs != MBS_INITIALIZE) val = *pv; } else val = etf->reset; } AVAL(val); if (*mbs == MBS_INITIALIZE) { // show nothing when doing initialize *mbs = state; break; } *mbs = state; btnr(btn_lr); key_beep(); // if another button was pressed, leave this screen if (buttons) break; if (buttons_state != buttons_state_last) break; // show function id first time if (!value_showed) { value_showed = 1; menu_et_function_show_id(etf); } // show current value if (etf->show_func) etf->show_func(etf->name, val); else lcd_char_num3(val); lcd_update(); // sleep 5s, and if no button was changed during, end this screen delay_time = POPUP_DELAY * 200; while (delay_time && !(buttons & ~btn_lr) && (buttons_state == buttons_state_last)) delay_time = delay_menu(delay_time); if ((buttons_state & btn_lr) == (buttons_state_last & btn_lr)) break; } btnr(btn_lr); if (value_showed) lcd_menu(0); // set MENU off return value_showed; } // if button is not initialized, do it if (*mbs == MBS_INITIALIZE) { // set value to default only for non-config values (mixes, channels...) if (etf->flags & EF_NOCONFIG) { val = etf->reset; AVAL(val); } *mbs = MBS_RELEASED; } // return when key was not pressed if (!btn(btn_lr)) return 0; // convert steps step = steps_map[etm->step]; // show MENU and CHANNEL menu_et_function_show_id(etf); while (1) { u8 val_set_to_reset = 0; // check value left/right if (btnl_all(btn_lr)) { // both long keys together key_beep(); if (etf->long_func && etm->buttons == ETB_SPECIAL) // special handling etf->long_func(etf->name, &val, btn_l, btn_r); else { // reset to given reset value val = etf->reset; } AVAL(val); if (val == etf->reset) val_set_to_reset = 1; btnr(btn_lr); } else if (btn(btn_lr)) { if (!btns_all(btn_lr)) { // only one key is currently pressed key_beep(); if (etf->long_func && etm->buttons == ETB_SPECIAL && btnl(btn_lr)) // special handling etf->long_func(etf->name, &val, btn_l, btn_r); else if ((etm->buttons == ETB_LONG_RESET || etm->buttons == ETB_LONG_ENDVAL) && btnl(btn_lr)) { // handle long key press if (etm->buttons == ETB_LONG_RESET) { val = etf->reset; } else { // set side value if ((u8)(btn(btn_l) ? 1 : 0) ^ etm->reverse) val = etf->min; else val = etf->max; } } else { // handle short key press if ((u8)(btn(btn_l) ? 1 : 0) ^ etm->reverse) { val -= step; if (val < etf->min) { if (etm->rotate) val = etf->max; else val = etf->min; } if (etm->opposite_reset && val > etf->reset) val = etf->reset; } else { val += step; if (val > etf->max) { if (etm->rotate) val = etf->min; else val = etf->max; } if (etm->opposite_reset && val < etf->reset) val = etf->reset; } } AVAL(val); if (val == etf->reset) val_set_to_reset = 1; btnr(btn_lr); } else btnr_nolong(btn_lr); // keep long-presses for testing-both } else if (btn(BTN_ROT_ALL)) { s16 val2 = val; val = menu_change_val(val, etf->min, etf->max, etf->rot_fast_step, etm->rotate); // if encoder skipped reset value, set it to reset value if (val2 < etf->reset && val > etf->reset || val2 > etf->reset && val < etf->reset) val = etf->reset; AVAL(val); if (val == etf->reset) val_set_to_reset = 1; } btnr(BTN_ROT_ALL); // longer beep at value reset value if (val_set_to_reset) BEEP_RESET; // if another button was pressed, leave this screen if (buttons) break; if ((buttons_state & ~btn_lr) != buttons_state_last) break; // show current value if (etf->show_func) etf->show_func(etf->name, val); else lcd_char_num3(val); lcd_update(); // if reset value was reached, ignore rotate/btn_lr for some time delay_time = POPUP_DELAY * 200; if (val_set_to_reset) { u8 delay = RESET_VALUE_DELAY; while (delay && !(buttons & ~(btn_lr | BTN_ROT_ALL)) && ((buttons_state & ~btn_lr) == buttons_state_last)) delay = (u8)delay_menu(delay); btnr(BTN_ROT_ALL | btn_lr); delay_time -= RESET_VALUE_DELAY; } // sleep 5s, and if no button was changed during, end this screen while (delay_time && !buttons && ((buttons_state & ~btn_lr) == buttons_state_last)) delay_time = delay_menu(delay_time); if (!buttons) break; // timeouted without button press } btnr(btn_lr); // reset also long values // set MENU off lcd_menu(0); // save model config config_model_save(); return 1; }