コード例 #1
0
ファイル: menu_service.c プロジェクト: Micha500/gt3b
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();
}
コード例 #2
0
ファイル: menu_global.c プロジェクト: losikid/gt3b
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();
}
コード例 #3
0
ファイル: menu_popup.c プロジェクト: Andyboby/gt3b
// 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
}
コード例 #4
0
ファイル: menu_popup.c プロジェクト: Andyboby/gt3b
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;
}
コード例 #5
0
ファイル: menu.c プロジェクト: Micha500/gt3b
// choose from menu items
static void select_menu(void) {
    u8 menu = LM_MODEL;
    lcd_menu(menu);
    main_screen(MS_NAME);	// show model number and name

    while (1) {
	btnra();
	menu_stop();

	// Back/End key to end this menu
	if (btn(BTN_BACK | BTN_END))  break;

	// Enter key - goto submenu
	if (btn(BTN_ENTER)) {
	    key_beep();
	    if (menu == LM_MODEL) {
		if (btnl(BTN_ENTER))	menu_model(1);
		else {
					menu_model(0);
					break;
		}
	    }
	    else if (menu == LM_NAME) {
		if (btnl(BTN_ENTER))	menu_channels_reset();
		else			menu_name();
	    }
	    else if (menu == LM_REV) {
		if (btnl(BTN_ENTER))	menu_key_mapping();
		else			menu_reverse();
	    }
	    else if (menu == LM_EPO) {
		if (btnl(BTN_ENTER))	menu_mix();
		else			menu_endpoint();
	    }
	    else if (menu == LM_TRIM) {
		if (btnl(BTN_ENTER))	menu_subtrim();
		else			menu_trim();
	    }
	    else if (menu == LM_DR) {
		if (btnl(BTN_ENTER))	menu_speed();
		else			menu_dualrate();
	    }
	    else if (menu == LM_EXP) {
		if (btnl(BTN_ENTER))	menu_channel_value();
		else			menu_expo();
	    }
	    else {
		if (btnl(BTN_ENTER))	break;
		else			menu_abs();
	    }
	    main_screen(MS_NAME);	// show model number and name
	    // exit when BACK
	    if (btn(BTN_BACK))  break;
	}

	// rotate keys
	else if (btn(BTN_ROT_ALL)) {
	    if (btn(BTN_ROT_R)) {
		menu >>= 1;
		if (!menu)  menu = LM_MODEL;
	    }
	    else {
		menu <<= 1;
		if (!menu)  menu = LM_ABS;
	    }
	    lcd_menu(menu);
	    lcd_update();
	}
    }
コード例 #6
0
ファイル: menu_service.c プロジェクト: Micha500/gt3b
// 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();
}