// show model number, extra function to handle more than 10 models static void show_model_number(u8 model) { lcd_7seg((u8)(model % 10)); lcd_segment(LS_SYM_RIGHT, (u8)((u8)(model / 10) & 1)); lcd_segment(LS_SYM_LEFT, (u8)((u8)(model / 20) & 1)); lcd_segment(LS_SYM_PERCENT, (u8)((u8)(model / 40) & 1)); lcd_segment(LS_SYM_MODELNO, LS_ON); }
static void mix_4WS(u8 action) { u8 val; if (action == MLA_CHG) { // change value switch (menu_set) { case 0: // channel number/off val = cm.channel_4WS; if (!val) val = 2; val = (u8)menu_change_val(val, 2, channels, 1, 1); if (val == 2) cm.channel_4WS = 0; else cm.channel_4WS = val; break; case 1: // mix value menu_4WS_mix = (s8)menu_change_val(menu_4WS_mix, -100, 100, MIX_FAST, 0); break; case 2: // crab/no-crab menu_4WS_crab ^= 1; } } else if (action == MLA_NEXT) { // select next value if (++menu_set > 2) menu_set = 0; if (!cm.channel_4WS) menu_set = 0; } // show value lcd_7seg(4); switch (menu_set) { case 0: // channel number/OFF if (!cm.channel_4WS) lcd_chars("OFF"); else lcd_char_num3(cm.channel_4WS); lcd_segment(LS_SYM_CHANNEL, LS_ON); break; case 1: // mix value lcd_char_num3(menu_4WS_mix); lcd_segment(LS_SYM_PERCENT, LS_ON); break; case 2: // crab/no-crab lcd_chars("CR"); lcd_char(LCHR3, (u8)(menu_4WS_crab + '0')); menu_blink &= (u8)~(MCB_CHR1 | MCB_CHR2); } }
// set endpoints void sf_endpoint(u8 channel, u8 change) { u8 *addr = &cm.endpoint[channel][menu_adc_direction]; if (change) *addr = (u8)menu_change_val(*addr, 0, cg.endpoint_max, ENDPOINT_FAST, 0); lcd_segment(LS_SYM_PERCENT, LS_ON); lcd_char_num3(*addr); }
// set dualrate static void sf_dualrate(u8 channel, u8 change) { u8 *addr = &cm.dualrate[channel]; if (channel == 1 && menu_adc_direction) addr = &cm.dualrate[2]; if (change) *addr = (u8)menu_change_val(*addr, 0, 100, DUALRATE_FAST, 0); lcd_segment(LS_SYM_PERCENT, LS_ON); lcd_char_num3(*addr); }
// change model name static void menu_name_func(u8 action, void *p) { u8 letter; if (action == MCA_SET_CHG) { // change letter letter = cm.name[menu_set]; if (btn(BTN_ROT_L)) { // lower if (letter == '0') letter = 'Z'; else if (letter == 'A') letter = '9'; else letter--; } else { // upper if (letter == '9') letter = 'A'; else if (letter == 'Z') letter = '0'; else letter++; } cm.name[menu_set] = letter; } else if (action == MCA_SET_NEXT) { // next char if (++menu_set > 2) menu_set = 0; } // show name menu_blink = (u8)(1 << menu_set); // blink only selected char lcd_segment(LS_SYM_MODELNO, LS_ON); lcd_chars(cm.name); }
// set expos static void sf_expo(u8 channel, u8 change) { s8 *addr = &cm.expo[channel]; if (channel == 1 && menu_adc_direction) addr = &cm.expo[2]; if (change) *addr = (s8)menu_change_val(*addr, -EXPO_MAX, EXPO_MAX, EXPO_FAST, 0); lcd_segment(LS_SYM_PERCENT, LS_ON); lcd_char_num3(*addr); }
static void gs_endpoint_max(u8 change) { u8 *addr = &cg.endpoint_max; if (change == 0xff) { lcd_segment(LS_MENU_EPO, LS_OFF); lcd_segment(LS_SYM_PERCENT, LS_OFF); lcd_set(L7SEG, LB_EMPTY); return; } if (change) *addr = (u8)menu_change_val(*addr, 100, 150, 5, 0); lcd_segment(LS_SYM_PERCENT, LS_ON); lcd_segment(LS_MENU_EPO, LS_ON); lcd_char_num3(*addr); if (*addr > 120) { lcd_7seg(L7_D); lcd_set_blink(L7SEG, LB_SPC); } else lcd_set(L7SEG, LB_EMPTY); }
static void menu_abs_func(u8 action, void *p) { // change value if (action == MCA_SET_CHG) cm.abs_type = (u8)menu_change_val(cm.abs_type, 0, ABS_LABEL_SIZE-1, 1, 1); // show value lcd_segment(LS_SYM_CHANNEL, LS_ON); lcd_7seg(2); lcd_chars(abs_labels[cm.abs_type]); }
static void mix_DIG(u8 action) { u8 val; if (action == MLA_CHG) { // change value switch (menu_set) { case 0: // channel number/off val = cm.channel_DIG; if (!val) val = 2; val = (u8)menu_change_val(val, 1, channels, 1, 1); if (val == 2) cm.channel_DIG = 0; else cm.channel_DIG = val; break; case 1: // mix value menu_DIG_mix = (s8)menu_change_val(menu_DIG_mix, -100, 100, MIX_FAST, 0); break; } } else if (action == MLA_NEXT) { // select next value if (++menu_set > 1) menu_set = 0; if (!cm.channel_DIG) menu_set = 0; } // show value lcd_7seg(L7_D); switch (menu_set) { case 0: // channel number/OFF if (!cm.channel_DIG) lcd_chars("OFF"); else lcd_char_num3(cm.channel_DIG); lcd_segment(LS_SYM_CHANNEL, LS_ON); break; case 1: // mix value lcd_char_num3(menu_DIG_mix); lcd_segment(LS_SYM_PERCENT, LS_ON); break; } }
static void menu_model_func(u8 action, u8 *model) { if (action == MCA_ID_CHG) *model = (u8)menu_change_val((s16)*model, 0, MIN(CONFIG_MODEL_MAX, 40) - 1, MODEL_FAST, 1); lcd_segment(LS_SYM_MODELNO, LS_ON); show_model_number(*model); lcd_chars(config_model_name(*model)); }
// set number of model channels static void menu_channels(u8 action) { // change value if (action == MLA_CHG) cm.channels = (u8)(menu_change_val(cm.channels + 1, 2, MAX_CHANNELS, 1, 0) - 1); // show value lcd_7seg(L7_C); lcd_segment(LS_SYM_CHANNEL, LS_ON); lcd_char_num3(cm.channels + 1); }
// multi-position show and set value static void show_MP(u8 *name, s16 val) { u8 mp_id = (u8)(name[2] - '1'); s8 *multi_position; u8 channel_MP; u8 num_MP = config_get_MP(mp_id, &channel_MP, &multi_position); // show also selected channel/DIG if (channel_MP == MP_DIG) { lcd_7seg(L7_D); lcd_menu(LM_EPO); lcd_set_blink(LMENU, LB_SPC); lcd_segment(LS_SYM_CHANNEL, LS_OFF); lcd_segment(LS_SYM_PERCENT, LS_ON); } else { lcd_7seg(channel_MP); lcd_segment(LS_SYM_CHANNEL, LS_ON); } lcd_char_num3(multi_position[menu_MP_index[mp_id]]); }
// show main screen (model number and name/battery/...) static void main_screen(u8 item) { menu_adc_wakeup = 0; // chars is item dependent if (item == MS_NAME) { // model name lcd_segment(LS_SYM_CHANNEL, LS_OFF); lcd_segment(LS_SYM_DOT, LS_OFF); lcd_segment(LS_SYM_VOLTS, LS_OFF); show_model_number(cg.model); lcd_chars(cm.name); } else if (item == MS_BATTERY) { static u16 bat_val; static u16 bat_time; // battery voltage lcd_segment(LS_SYM_CHANNEL, LS_OFF); lcd_segment(LS_SYM_DOT, LS_ON); lcd_segment(LS_SYM_VOLTS, LS_ON); show_model_number(cg.model); // calculate voltage from current raw value and calib value if (time_sec >= bat_time) { bat_time = time_sec + 2; bat_val = (u16)(((u32)adc_battery * 100 + 300) / cg.battery_calib); } lcd_char_num3(bat_val); menu_adc_wakeup = 1; } else { // timers menu_timer_show((u8)(item - MS_TIMER0)); } lcd_update(); }
// show functions ID static void menu_et_function_show_id(et_functions_s *etf) { lcd_menu(etf->menu); if (etf->flags & EF_BLINK) lcd_set_blink(LMENU, LB_SPC); lcd_segment(LS_SYM_MODELNO, LS_OFF); lcd_segment(LS_SYM_DOT, LS_OFF); lcd_segment(LS_SYM_VOLTS, LS_OFF); lcd_segment(LS_SYM_PERCENT, (u8)(etf->flags & EF_PERCENT ? LS_ON : LS_OFF)); lcd_segment(LS_SYM_LEFT, (u8)(etf->flags & EF_LEFT ? LS_ON : LS_OFF)); lcd_segment(LS_SYM_RIGHT, (u8)(etf->flags & EF_RIGHT ? LS_ON : LS_OFF)); lcd_segment(LS_SYM_CHANNEL, (u8)(etf->flags & EF_NOCHANNEL ? LS_OFF : LS_ON)); lcd_7seg(etf->channel); }
void menu_key_mapping_func(u8 action, void *p) { if (action == MCA_SET_CHG) { km_trim_key(1); } else if (action == MCA_SET_NEXT) { km_trim_key(2); } else if (action == MCA_ID_CHG) { while (1) { // select prev/next menu_id menu_id = (u8)menu_change_val(menu_id, 0, 3 * NUM_TRIMS + NUM_KEYS - 1, 1, 1); // trims and 3keys (CH3/BACK/END) always if (menu_id < NUM_TRIMS + NUM_KEYS) break; // check trim keys and use them only when corresponding // trim is off if (ck.key_map[menu_id - NUM_TRIMS].is_trim) continue; break; } } // show value if (menu_id < NUM_TRIMS + NUM_KEYS) // standard trims and buttons lcd_7seg(key_ids[menu_id]); else { // trims as buttons, use arrows to show them lcd_7seg(key_ids[(u8)((u8)(menu_id - NUM_TRIMS - NUM_KEYS) >> 1)]); if ((u8)(menu_id - NUM_TRIMS - NUM_KEYS) & 1) // right trim key lcd_segment(LS_SYM_RIGHT, LS_ON); else // left trim key lcd_segment(LS_SYM_LEFT, LS_ON); } if (action != MCA_SET_NEXT && action != MCA_SET_CHG) km_trim_key(0); }
static void menu_channel_func(u8 action, menu_channel_t *p) { switch (action) { case MCA_INIT: menu_set_adc_force(menu_id, p->use_adc, p->forced_values); break; case MCA_SET_CHG: p->func(menu_id, 1); break; case MCA_ID_CHG: menu_id = (u8)menu_change_val(menu_id, 0, p->end_channel - 1, 1, 1); menu_set_adc_force(menu_id, p->use_adc, p->forced_values); break; case MCA_ADC_PRE: menu_set_adc_direction(menu_id); return; // show nothing at ADC_PRE case MCA_ADC_POST: // do nothing if left-right didn't changed if (p->last_direction == menu_adc_direction) return; // else flag it to show value menu_id_set = 1; // flag that new value is showed return; } // show value lcd_segment(LS_SYM_CHANNEL, LS_ON); if (action != MCA_SET_CHG) { // already showed lcd_7seg((u8)(menu_id + 1)); p->func(menu_id, 0); } if (menu_adc_wakeup) { // show arrow if (menu_adc_direction) lcd_segment(LS_SYM_RIGHT, LS_ON); else lcd_segment(LS_SYM_LEFT, LS_ON); } p->last_direction = menu_adc_direction; }
// set servo speed static void sf_speed(u8 channel, u8 change) { u8 *addr = &cm.speed[channel]; u8 thfwdonly = (u8)(channel == 1 && menu_adc_direction ? 1 : 0); if (channel == 0 && menu_adc_direction) addr = &cm.stspd_return; if (change) { if (thfwdonly) // throttle forward only setting cm.thspd_onlyfwd ^= 1; else *addr = (u8)menu_change_val(*addr, 1, 100, SPEED_FAST, 0); } if (thfwdonly) lcd_chars(cm.thspd_onlyfwd ? "OFF" : "ON "); else { lcd_char_num3(*addr); lcd_segment(LS_SYM_PERCENT, LS_ON); } }
static void gs_battery_low(u8 change) { u8 *addr = &cg.battery_low; if (change == 0xff) { lcd_segment(LS_SYM_LOWPWR, LS_OFF); lcd_segment(LS_SYM_DOT, LS_OFF); lcd_segment(LS_SYM_VOLTS, LS_OFF); return; } if (change) *addr = (u8)menu_change_val(*addr, 60, 105, 2, 0); lcd_segment(LS_SYM_LOWPWR, LS_ON); lcd_segment(LS_SYM_DOT, LS_ON); lcd_segment(LS_SYM_VOLTS, LS_ON); lcd_char_num3(cg.battery_low); }
// set LCD element id to given bitmap void lcd_set(u8 id, u8 *bitmap) { struct lcd_items_s *li = &lcd_items[id]; u8 *seg = li->segments; // actual lcd segment pointer u8 sp = *seg++; // actual lcd segment u8 bits = li->bits; // number of bits in bitmap u8 bitpos = 8; // bit position in bitmap byte u8 fake_bitmap = (u8)(bitmap >= (u8 *)0xff00); u8 bm; // actual byte of bitmap if (fake_bitmap) { // special addresses are actually bitmap for all segments bm = (u8)((u16)bitmap & 0xff); } else { bm = *bitmap++; } do { // for seven-bits bitmaps, rotate first if (bitpos > bits) { bm <<= 1; bitpos -= 1; } // set segment lcd_segment(sp, (u8)(bm & 0x80 ? LS_ON : LS_OFF)); if (!(sp = *seg++)) break; // to next bitmap bit/byte if (--bitpos) { // next bit bm <<= 1; } else { // next bitmap byte bitpos = 8; if (fake_bitmap) { bm = (u8)((u16)bitmap & 0xff); } else { bm = *bitmap++; } } } while (1); }
// show model number, extra function to handle more than 10 models static void show_model_number(u8 model) { lcd_7seg((u8)(model % 10)); lcd_segment(LS_SYM_RIGHT, (u8)((u8)(model / 10) & 1)); lcd_segment(LS_SYM_LEFT, (u8)((u8)(model / 20) & 1)); }
// calibrate menu void menu_calibrate(u8 at_poweron) { u8 channel = 1; u16 last_val = 0xffff; u16 val; u8 seg; u8 bat_volts; u16 update_time = 0; u16 update_val = 0; menu_adc_wakeup = 1; // cleanup screen and disable possible low bat warning buzzer_off(); if (at_poweron) buzzer_on(30, 30, 2); else key_beep(); menu_battery_low = 0; // it will be set automatically again battery_low_shutup = 0; backlight_set_default(BACKLIGHT_MAX); backlight_on(); lcd_clear(); btnra(); // show intro text lcd_chars("CAL"); lcd_update(); delay_menu_always(2); // show channel number and not-yet calibrated values lcd_segment(LS_SYM_CHANNEL, LS_ON); lcd_7seg(channel); lcd_menu(LM_MODEL | LM_NAME | LM_REV | LM_TRIM | LM_DR | LM_EXP); lcd_set_blink(LMENU, LB_SPC); while (1) { // check keys if (btnl(BTN_BACK | BTN_ENTER)) break; if (btn(BTN_END | BTN_ROT_ALL)) { if (btn(BTN_END)) key_beep(); // change channel number channel = (u8)menu_change_val(channel, 1, 4, 1, 1); lcd_7seg(channel); lcd_update(); update_time = 0; } else if (btn(BTN_ENTER)) { // save calibrate value for channels 1 and 2 // select actual voltage for channel 4 if (channel == 1) { key_beep(); val = ADC_OVS(steering); if (val < CALIB_ST_LOW_MID) { cg.calib_steering_left = val; seg = LS_MENU_MODEL; } else if (val <= CALIB_ST_MID_HIGH) { cg.calib_steering_mid = val; seg = LS_MENU_NAME; } else { cg.calib_steering_right = val; seg = LS_MENU_REV; } lcd_segment(seg, LS_OFF); lcd_update(); } else if (channel == 2) { key_beep(); val = ADC_OVS(throttle); if (val < CALIB_TH_LOW_MID) { cg.calib_throttle_fwd = val; seg = LS_MENU_TRIM; } else if (val <= CALIB_TH_MID_HIGH) { cg.calib_throttle_mid = val; seg = LS_MENU_DR; } else { cg.calib_throttle_bck = val; seg = LS_MENU_EXP; } lcd_segment(seg, LS_OFF); // set corresponding LCD off lcd_update(); } else if (channel == 4) { key_beep(); // allow to set actual battery voltage lcd_segment(LS_SYM_DOT, LS_ON); lcd_segment(LS_SYM_VOLTS, LS_ON); bat_volts = (u8)(((u32)adc_battery * 100 + 300) / cg.battery_calib); lcd_char_num3(bat_volts); lcd_update(); while (1) { btnra(); stop(); if (btnl(BTN_BACK) || btn(BTN_ENTER | BTN_END)) break; if (btn(BTN_ROT_ALL)) { if (btn(BTN_ROT_L)) bat_volts--; else bat_volts++; lcd_char_num3(bat_volts); lcd_update(); } } key_beep(); lcd_segment(LS_SYM_DOT, LS_OFF); lcd_segment(LS_SYM_VOLTS, LS_OFF); last_val = 0xffff; // show ADC value if (!btn(BTN_END)) { // recalculate calibrate value for 10V cg.battery_calib = (u16)(((u32)adc_battery * 100 + 40) / bat_volts); if (btnl(BTN_BACK | BTN_ENTER)) break; } } } // show ADC value if other than last val switch (channel) { case 1: val = ADC_OVS(steering); break; case 2: val = ADC_OVS(throttle); break; case 3: val = ADC_OVS(ch3); break; case 4: val = adc_battery; break; default: // to eliminate compiler warning val = 0; } // only update display every 1s if (time_sec >= update_time) { update_time = time_sec + 1; update_val = val; } if (update_val != last_val) { last_val = update_val; lcd_char_num3(val); lcd_update(); } btnra(); stop(); } menu_adc_wakeup = 0; beep(60); lcd_menu(0); lcd_update(); config_global_save(); apply_global_config(); }
// 7seg: C b E 1l 1r 2l 2r 3l 3r dl dr // chars: // function // OFF -> function_long // 2STATE -> momentary // switch -> reverse -> prev_val -> function_long // momentary -> reverse -> prev_val // other -> function_long // // function_long (identified by symbol V) // OFF // 2STATE -> reverse -> prev_val // other static void km_key(u8 action) { config_key_map_s *km = &ck.key_map[menu_id - NUM_TRIMS]; u8 idx, new_idx = 0; if (action == 1) { // change value switch (menu_set) { case 0: // function // select new function, map through key_functions idx = menu_key_function_idx(km->function); while (1) { idx = (u8)menu_change_val(idx, 0, key_functions_max, 1, 1); new_idx = key_functions[idx]; if (!new_idx) continue; // empty slot new_idx--; // was one more if (menu_key_function_is_allowed(new_idx)) break; // we have it } // set values to defaults if (km->momentary) *(u16 *)km = 0; // was momentary, zero all else { // zero only no-long function parameters km->reverse = 0; km->previous_val = 0; } km->function = new_idx; break; case 1: // momentary setting km->momentary ^= 1; // after change momentary, reset long setting km->function_long = 0; km->reverse_long = 0; km->previous_val_long = 0; break; case 2: // reverse km->reverse ^= 1; break; case 3: // previous_val km->previous_val ^= 1; break; case 4: // function long // select new function, map through key_functions idx = menu_key_function_idx(km->function_long); while (1) { idx = (u8)menu_change_val(idx, 0, key_functions_max, 1, 1); new_idx = key_functions[idx]; if (!new_idx) continue; // empty slot new_idx--; // was one more if (menu_key_function_is_allowed(new_idx)) break; // we have it } // set values to defaults km->reverse_long = 0; km->previous_val_long = 0; km->function_long = new_idx; break; case 5: // reverse_long km->reverse_long ^= 1; break; case 6: // previous_val_long km->previous_val_long ^= 1; break; } } else if (action == 2) { // switch to next setting switch (menu_set) { case 0: if (menu_key_function_2state(km->function)) menu_set = 1; else menu_set = 4; break; case 1: menu_set = 2; break; case 2: menu_set = 3; break; case 3: if (km->momentary) menu_set = 0; else menu_set = 4; break; case 4: if (menu_key_function_2state(km->function_long)) menu_set = 5; else menu_set = 0; break; case 5: menu_set = 6; break; case 6: menu_set = 0; break; } } // show value of menu_set switch (menu_set) { case 0: // function lcd_chars(menu_key_function_name(km->function)); break; case 1: // momentary setting lcd_chars("MO"); lcd_char(LCHR3, (u8)(km->momentary + '0')); menu_blink &= (u8)~(MCB_CHR1 | MCB_CHR2); break; case 2: // reverse lcd_chars("RE"); lcd_char(LCHR3, (u8)(km->reverse + '0')); menu_blink &= (u8)~(MCB_CHR1 | MCB_CHR2); break; case 3: // previous_val lcd_chars("PV"); lcd_char(LCHR3, (u8)(km->previous_val + '0')); menu_blink &= (u8)~(MCB_CHR1 | MCB_CHR2); break; case 4: // function long lcd_chars(menu_key_function_name(km->function_long)); lcd_segment(LS_SYM_VOLTS, LS_ON); break; case 5: // reverse_long lcd_chars("RE"); lcd_char(LCHR3, (u8)(km->reverse_long + '0')); menu_blink &= (u8)~(MCB_CHR1 | MCB_CHR2); lcd_segment(LS_SYM_VOLTS, LS_ON); break; case 6: // previous_val_long lcd_chars("PV"); lcd_char(LCHR3, (u8)(km->previous_val_long + '0')); menu_blink &= (u8)~(MCB_CHR1 | MCB_CHR2); lcd_segment(LS_SYM_VOLTS, LS_ON); break; } }
// 7seg: 1 2 3 d // chars: // function // OFF // other -> buttons // MO -> reverse -> prev_val // NL/RP/RE/EN -> step -> reverse -> opp_reset -> rotate // id: V static void km_trim(u8 action) { config_et_map_s *etm = &ck.et_map[menu_id]; u8 idx, btn, new_idx = 0; if (action == 1) { // change value switch (menu_set) { case 0: // function // select new function, map through trim_functions if (!etm->is_trim) etm->function = 0; idx = menu_et_function_idx(etm->function); while (1) { idx = (u8)menu_change_val(idx, 0, trim_functions_max, 1, 1); new_idx = trim_functions[idx]; if (!new_idx) continue; // empty slot new_idx--; // was one more if (menu_et_function_is_allowed(new_idx)) break; // we have it } // set values to defaults ((u16 *)etm)[0] = 0; ((u16 *)etm)[1] = 0; etm->function = new_idx; if (etm->function) etm->is_trim = etm->is_trim2 = 1; break; case 1: // buttons // show special ("SP") only when selected function has it if (menu_et_function_long_special(etm->function)) idx = 1; else idx = 2; btn = etm->buttons; btn = (u8)menu_change_val(btn, 0, TRIM_BUTTONS_SIZE - idx, 1, 1); // skip MOMentary for list functions if (btn == ETB_MOMENTARY && menu_et_function_is_list(etm->function)) { if (etm->buttons < ETB_MOMENTARY) btn++; else btn--; } etm->buttons = btn; break; case 2: // step etm->step = (u8)menu_change_val(etm->step, 0, STEPS_MAP_SIZE - 1, 1, 0); break; case 3: // reverse etm->reverse ^= 1; break; case 4: // opposite reset etm->opposite_reset ^= 1; break; case 5: // return to previous value etm->previous_val ^= 1; break; case 6: etm->rotate ^= 1; break; } } else if (action == 2) { // switch to next setting if (menu_set || etm->is_trim) { if (etm->buttons == ETB_MOMENTARY) { if (++menu_set > 5) menu_set = 0; else if (menu_set == 2) menu_set = 3; // skip "step" for momentary else if (menu_set == 4) menu_set = 5; // skip "opposite_reset" } else { if (++menu_set > 4) menu_set = 0; else if (menu_et_function_is_list(etm->function)) { if (menu_set == 2) { // skip "step" menu_set++; etm->step = 0; } else if (menu_set == 4) { // skip "opposite reset" menu_set = 6; etm->opposite_reset = 0; } } } } } // show value of menu_set switch (menu_set) { case 0: // function if (!etm->is_trim) lcd_chars("OFF"); else lcd_chars(menu_et_function_name(etm->function)); break; case 1: // buttons lcd_char(LCHR1, 'B'); lcd_chars2(trim_buttons[etm->buttons]); menu_blink &= (u8)~MCB_CHR1; break; case 2: // step lcd_char_num3(steps_map[etm->step]); lcd_segment(LS_SYM_VOLTS, LS_ON); break; case 3: // reverse lcd_chars("RE"); lcd_char(LCHR3, (u8)(etm->reverse + '0')); menu_blink &= (u8)~(MCB_CHR1 | MCB_CHR2); break; case 4: // opposite reset lcd_chars("OR"); lcd_char(LCHR3, (u8)(etm->opposite_reset + '0')); menu_blink &= (u8)~(MCB_CHR1 | MCB_CHR2); break; case 5: // previous val lcd_chars("PV"); lcd_char(LCHR3, (u8)(etm->previous_val + '0')); menu_blink &= (u8)~(MCB_CHR1 | MCB_CHR2); break; case 6: // rotate lcd_chars("RO"); lcd_char(LCHR3, (u8)(etm->rotate + '0')); menu_blink &= (u8)~(MCB_CHR1 | MCB_CHR2); break; } }
void menu_global_setup(void) { u8 item = 0; u8 item_val = 0; // now selecting item global_setup_t func = gs_config[item]; // cleanup screen and disable possible low bat warning buzzer_off(); key_beep(); menu_battery_low = 0; // it will be set automatically again backlight_set_default(BACKLIGHT_MAX); backlight_on(); lcd_clear(); lcd_segment(LS_MENU_MODEL, LS_ON); lcd_segment_blink(LS_MENU_MODEL, LB_INV); lcd_segment_blink(LS_MENU_NAME, LB_INV); lcd_update(); func(0); // show current value while (1) { btnra(); stop(); if (btnl(BTN_BACK | BTN_ENTER)) break; if (btn(BTN_ENTER)) { if (item > 0) { // not for firmware version key_beep(); item_val = (u8)(1 - item_val); if (item_val) { // changing value lcd_chars_blink(LB_SPC); } else { // selecting item lcd_chars_blink(LB_OFF); } } } else if (btn(BTN_ROT_ALL)) { if (item_val) { // change item value func(1); lcd_chars_blink(LB_SPC); } else { // select another item func(0xff); // un-show labels if (btn(BTN_ROT_L)) { if (item) item--; else item = GS_CONFIG_SIZE - 1; } else { if (++item >= GS_CONFIG_SIZE) item = 0; } func = gs_config[item]; func(0); // show current value } lcd_update(); } } func(0xff); // un-show labels, apply resets beep(60); lcd_clear(); config_global_save(); apply_global_config(); }
static void mix_MultiPosition(u8 action) { s8 val; if (action == MLA_CHG) { // change value if (menu_set == 0) { // channel number/off val = cm.channel_MP; if (!val) val = 2; else if (val == MP_DIG) val = (s8)(channels + 1); val = (u8)menu_change_val(val, 2, channels + 1, 1, 1); if (val == 2) cm.channel_MP = 0; else if (val == (s8)(channels + 1)) cm.channel_MP = MP_DIG; else cm.channel_MP = val; } else { // position value + END state (END not for first position) val = cm.multi_position[menu_set - 1]; if (val == MULTI_POSITION_END) val = -101; val = (s8)menu_change_val(val, menu_set == 1 ? -100 : -101, 100, CHANNEL_FAST, 0); if (val == -101) { // set all from this to END value memset(&cm.multi_position[menu_set - 1], (u8)MULTI_POSITION_END, NUM_MULTI_POSITION + 1 - menu_set); } else cm.multi_position[menu_set - 1] = val; } } else if (action == MLA_NEXT) { // select next value if (cm.channel_MP) { if (menu_set == 0) menu_set = 1; else if (cm.multi_position[menu_set - 1] == MULTI_POSITION_END || ++menu_set > NUM_MULTI_POSITION) menu_set = 0; } // allow forcing channel value if (menu_set && cm.channel_MP && cm.channel_MP <= channels) { menu_force_value_channel = cm.channel_MP; } else menu_force_value_channel = 0; } // show value lcd_7seg(L7_P); if (menu_set == 0) { // channel number/OFF if (!cm.channel_MP) lcd_chars("OFF"); else if (cm.channel_MP == MP_DIG) lcd_chars("DIG"); else lcd_char_num3(cm.channel_MP); lcd_segment(LS_SYM_CHANNEL, LS_ON); } else { // position value val = cm.multi_position[menu_set - 1]; if (val == MULTI_POSITION_END) { lcd_chars("END"); val = -100; } else lcd_char_num3(val); if (cm.channel_MP == MP_DIG) menu_DIG_mix = val; else menu_force_value = val * PPM(5); } }