Пример #1
0
// 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);
}
Пример #2
0
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);
    }
}
Пример #3
0
// 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);
}
Пример #4
0
// 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);
}
Пример #5
0
// 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);
}
Пример #6
0
// 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);
}
Пример #7
0
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);
}
Пример #8
0
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]);
}
Пример #9
0
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;
    }
}
Пример #10
0
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));
}
Пример #11
0
// 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);
}
Пример #12
0
// 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]]);
}
Пример #13
0
// 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();
}
Пример #14
0
// 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);
}
Пример #15
0
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);
}
Пример #16
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;
}
Пример #17
0
// 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);
    }
}
Пример #18
0
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);
}
Пример #19
0
// 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);
}
Пример #20
0
// 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));
}
Пример #21
0
// 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();
}
Пример #22
0
// 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;
    }
}
Пример #23
0
// 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;
    }
}
Пример #24
0
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();
}
Пример #25
0
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);
    }
}