Commit e05d4801 authored by Pavel Semerad's avatar Pavel Semerad
Browse files

add possibility to connect potentiometer instead of CH3 button

parent 5d6c1561
*0.5.1 ()
added possibility to connect potentiometer instead of CH3 button
*0.5.0 (23 Apr 2012)
global menu was restructuralized
added ability to select number of channels (2-MAX_CHANNELS) for each
......
......@@ -197,6 +197,14 @@ Standard menu:
identified by "V" symbol
- reverse_long: same as "reverse" + "V" symbol
- prev_val_long: same as "prev_val" + "V" symbol
-----
steps of settings of ch3 potentiometer (if enabled at global config):
- sequence:
function -> reverse
- function: selected function listed at the end of manual
- RE reverse:
0 - no change
1 - swap left/right sides
......@@ -255,14 +263,22 @@ Operating timers:
Calibrate menu:
===============
- enter it by wheel right-turn and ENTER-long
- 6 menu items starts to blink
- 6 menu items starts to blink (+ 2 arrows if CH3 is potentiometer)
- use END or ROTATE to change channels
- there is also channel 3 representing CH3 button (for those who will do
some 3-position switch/potentiometer modification)
> There is 1K resistor connected between CH3 button and +5V, so
simply connecting linear potentiometer instead of CH3 button
will not work. Usefull results can be done with logarithmic
potentiometer 10K which has 1K at half of turn. Or eliminate
internal resistor to +5V, connect potentiometer between +5V
and GND and potentiometer output instead of CH3 button.
- there is also channal 4 representing battery voltage
- calibrate as usual (for channel 1/2 left+mid+right and ENTER)
> calibrated value will disappear from menu
> it is not needed to calibrate all values
- calibrate CH3 potentiometer (if selected at global config)
> only left + right positions
- calibrate battery (it will not be probably needed to use this)
> select channel 4
> press ENTER
......@@ -313,6 +329,7 @@ Global setup menu:
d long press key delay 100...1000 miliseconds
H setting of hardware features
reverse rotate encoder E_N/E_R (Normal/Reverse) - for GT3C
ch3 is potentiometer P3N/P3Y (No/Yes)
select ppm sync/frame PTS/PTF (constant SYNC/frame length)
select ppm length Lxx - 3-18ms for constant SYNC length
9-24ms for constant frame length
......
linear CH3 with potentiometer
- global option to choose CH3 is a pot
- don't read CH3 key in read_keys()
- key mapping assign trim function and reverse
- at begin of CALC, convert CH3 val to assigned function
- calibrate low and high values at calib menu
? use also flash memory to store model configs
- some models in EEPROM
- other models in FLASH, one empty place
......
......@@ -269,6 +269,29 @@ static void calc_loop(void) {
u16 adc_steering, adc_throttle; // last 4 or 1 ADC values
while (1) {
// handle channel3 potentiometer, cannot use channel_calib,
// because we don't have calib middle and dead zone
if (cg.ch3_pot && !menu_ch3_pot_disabled) {
// do it only if some function is assigned to CH3 pot
if (*ck_ch3_pot_func) {
if (cg.adc_ovs_last) val = adc_ch3_last << ADC_OVS_SHIFT;
else val = adc_ch3_ovs;
// map ch3 pot -5000..5000 range
val -= cg.calib_ch3_left << ADC_OVS_SHIFT;
val2 = (s16)((s32)(val) * PPM(1000) /
((cg.calib_ch3_right - cg.calib_ch3_left) << ADC_OVS_SHIFT))
- PPM(500);
// safety checks to -5000..5000 limits
if (val2 < PPM(-500)) val2 = PPM(-500);
else if (val2 > PPM(500)) val2 = PPM(500);
// do reverse
if (*ck_ch3_pot_rev) val2 = -val2;
// set value to function
menu_et_function_set_from_linear(*ck_ch3_pot_func, val2);
}
}
DIG_mix = menu_DIG_mix * PPM(5); // to -5000..5000 range
// set used ADC values
......
......@@ -59,7 +59,6 @@ u8 config_global_set_default(void) {
cg.reset_beep = 1;
cg.poweron_beep = 1;
cg.poweron_warn = 0;
cg.rotate_reverse = 0; // not-reversed
cg.timer1_type = 0; // OFF
cg.timer2_type = 0;
......@@ -68,12 +67,12 @@ u8 config_global_set_default(void) {
cg.ppm_sync_frame = 0; // to constant SYNC length
cg.ppm_length = 1; // 4ms constant SYNC length
cg.rotate_reverse = 0; // not-reversed
cg.ch3_pot = 0; // CH3 is button
cg.unused1 = 0;
cg.unused2 = 0;
cg.unused3 = 0;
cg.unused4 = 0;
cg.unused5 = 0;
// set calibrate values only when they are out of limits
cc |= check_val(&cg.calib_steering_left, 0, CALIB_ST_LOW_MID, 0);
......@@ -82,6 +81,8 @@ u8 config_global_set_default(void) {
cc |= check_val(&cg.calib_throttle_fwd, 0, CALIB_TH_LOW_MID, 0);
cc |= check_val(&cg.calib_throttle_mid, CALIB_TH_LOW_MID, CALIB_TH_MID_HIGH, 600);
cc |= check_val(&cg.calib_throttle_bck, CALIB_TH_MID_HIGH, 1023, 1023);
check_val(&cg.calib_ch3_left, 0, 512, 0);
check_val(&cg.calib_ch3_right, 512, 1023, 1023);
return cc;
}
......@@ -141,6 +142,10 @@ void config_model_set_default(void) {
cm.channels = MAX_CHANNELS - 1; // it is one lower to fit also 8
cm.unused = 0;
memcpy(&cm.key_mapping, &default_key_mapping, sizeof(config_key_mapping_s));
if (cg.ch3_pot) {
*ck_ch3_pot_func = 0;
*ck_ch3_pot_rev = 0;
}
}
......
......@@ -63,11 +63,12 @@ typedef struct {
u8 ppm_length:4; // length of PPM sync signal (3..) or frame length (9..)
u8 ppm_sync_frame:1; // 0 = constant SYNC length, 1 = constant frame length
u8 unused1:3; // reserve
u8 ch3_pot:1; // potentiometer connected instead of CH3 button
u8 unused1:2; // reserve
u8 unused2;
u16 calib_ch3_left;
u16 calib_ch3_right;
u16 unused3;
u16 unused4;
u16 unused5;
} config_global_s;
extern config_global_s config_global;
......@@ -164,8 +165,10 @@ typedef struct {
} config_model_s;
extern config_model_s config_model;
#define cm config_model
#define ck cm.key_mapping
#define cm config_model
#define ck cm.key_mapping
#define ck_ch3_pot_func ((u8 *)&ck.key_map[0])
#define ck_ch3_pot_rev ((u8 *)&ck.key_map[0] + 1)
......
......@@ -196,8 +196,11 @@ static void read_keys(void) {
// add CH3 button, middle state will be only in buttons_state,
// not in buttons
if (adc_ch3_last <= BTN_CH3_LOW) buttons1 |= BTN_CH3;
else if (adc_ch3_last < BTN_CH3_HIGH) buttons1 |= BTN_CH3_MID;
// do only when CH3 is button, not potentiometer
if (!cg.ch3_pot) {
if (adc_ch3_last <= BTN_CH3_LOW) buttons1 |= BTN_CH3;
else if (adc_ch3_last < BTN_CH3_HIGH) buttons1 |= BTN_CH3_MID;
}
// combine last 3 readed buttons
buttons_state |= buttons1 & buttons2 & buttons3;
......
......@@ -90,6 +90,8 @@ extern u16 battery_low_raw;
extern u8 menu_check_keys;
// temporary flag used when doing reset (global/all models/model)
extern _Bool menu_tmp_flag;
// temporary disable ch3 potentiometer when in key mapping menu
extern _Bool menu_ch3_pot_disabled;
......@@ -114,6 +116,7 @@ extern u8 *menu_key_function_name(u8 n);
extern s8 menu_key_function_idx(u8 n);
extern u8 menu_key_function_2state(u8 n);
extern u8 menu_key_function_is_allowed(u8 n);
extern void menu_et_function_set_from_linear(u8 n, s16 val);
extern const u8 steps_map[];
#define STEPS_MAP_SIZE 11
extern const u16 et_buttons[][2];
......
......@@ -279,6 +279,9 @@ static void gs_hardware(u8 action) {
cg.rotate_reverse ^= 1;
break;
case 1:
cg.ch3_pot ^= 1;
break;
case 2:
if (cg.ppm_sync_frame) {
cg.ppm_sync_frame = 0;
cg.ppm_length = 1; // 4ms SYNC
......@@ -288,7 +291,7 @@ static void gs_hardware(u8 action) {
cg.ppm_length = 11; // 20ms frame
}
break;
case 2:
case 3:
if (cg.ppm_sync_frame)
// constant frame length
cg.ppm_length =
......@@ -303,7 +306,7 @@ static void gs_hardware(u8 action) {
// select next value
else if (action == MLA_NEXT) {
if (++menu_set > 2) menu_set = 0;
if (++menu_set > 3) menu_set = 0;
}
// show values
......@@ -315,10 +318,14 @@ static void gs_hardware(u8 action) {
lcd_char(LCHR3, (u8)(cg.rotate_reverse ? 'R' : 'N'));
break;
case 1:
lcd_chars("P3");
lcd_char(LCHR3, (u8)(cg.ch3_pot ? 'Y' : 'N'));
break;
case 2:
lcd_chars("PT");
lcd_char(LCHR3, (u8)(cg.ppm_sync_frame ? 'F' : 'S'));
break;
case 2:
case 3:
lcd_char_num3(cg.ppm_length + (u8)(cg.ppm_sync_frame ? 9 : 3));
lcd_char(LCHR1, 'L');
menu_blink |= MCB_CHR2; // blink char2 too
......
......@@ -191,6 +191,67 @@ static void km_trim(u8 action) {
}
// special function for ch3 potentiometer, select function and reverse
static void km_ch3_pot(u8 action) {
s8 idx;
u8 new_idx = 0;
u8 *func = ck_ch3_pot_func;
u8 *rev = ck_ch3_pot_rev;
if (action == 1) {
// change value
switch (menu_set) {
case 0:
// function
// select new function, map through trim_functions
idx = menu_et_function_idx(*func);
if (idx == -1) {
// there can be some bad value from timer when ch3 was not
// set to potentiometer
*func = 0;
idx = 0;
}
while (1) {
idx = (s8)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
*func = new_idx;
break;
case 1:
// reverse
if (*rev) *rev = 0;
else *rev = 1;
break;
}
}
else if (action == 2) {
// switch to next setting
if (menu_set || *func) {
if (++menu_set > 1) menu_set = 0;
}
}
// show value of menu_set
switch (menu_set) {
case 0:
// function
lcd_chars(menu_et_function_name(*func));
break;
case 1:
// reverse
lcd_chars("RE");
lcd_char(LCHR3, (u8)(*rev ? '1' : '0'));
menu_blink &= (u8)~(MCB_CHR1 | MCB_CHR2);
break;
}
}
#define KEY_FUNCTIONS_SIZE 32
......@@ -362,8 +423,11 @@ static void km_key(u8 action) {
@inline static void km_trim_key(u8 action) {
if (menu_id < NUM_TRIMS) km_trim(action);
else km_key(action);
if (menu_id < NUM_TRIMS)
km_trim(action);
else if (cg.ch3_pot && menu_id == NUM_TRIMS)
km_ch3_pot(action);
else km_key(action);
}
static const u8 key_ids[] = {
......@@ -409,11 +473,15 @@ void menu_key_mapping_func(u8 action, void *p) {
km_trim_key(0);
}
// temporary disable ch3 potentiometer when in key mapping menu
_Bool menu_ch3_pot_disabled;
void menu_key_mapping(void) {
lcd_set_blink(LMENU, LB_SPC);
menu_ch3_pot_disabled = 1;
menu_common(menu_key_mapping_func, NULL, MCF_NONE);
menu_ch3_pot_disabled = 0;
lcd_set_blink(LMENU, LB_OFF);
config_model_save();
apply_model_config();
......
......@@ -269,6 +269,24 @@ u8 menu_et_function_is_allowed(u8 n) {
return 0; // channel too big
}
// set function value from linear channel value
// lin_val in range -5000..5000
#define AVAL(x) \
if (etf->set_func) etf->set_func(&x, SF_ROTATE); \
*(s8 *)etf->aval = (s8)(x)
#define SF_ROTATE 0
void menu_et_function_set_from_linear(u8 n, s16 lin_val) {
et_functions_s *etf = &et_functions[n];
s16 val;
if (n == 0 || n >= ET_FUNCTIONS_SIZE) return; // OFF or bad
// map lin_val between min and max
val = (s16)((s32)(lin_val + PPM(500)) * (etf->max - etf->min + 1)
/ PPM(1000)) + etf->min;
if (val > etf->max) val = etf->max; // lin_val was full right
AVAL(val);
}
#undef SF_ROTATE
// find function by name
static et_functions_s *menu_et_function_find_name(u8 *name) {
u8 i, *n;
......@@ -310,9 +328,6 @@ const u8 steps_map[STEPS_MAP_SIZE] = {
#define RVAL(x) \
if (etf->min >= 0) x = *(u8 *)etf->aval; \
else x = *(s8 *)etf->aval;
#define AVAL(x) \
if (etf->set_func) etf->set_func(&x, SF_ROTATE); \
*(s8 *)etf->aval = (s8)(x)
static u8 menu_popup_et(u8 trim_id) {
u16 delay_time;
s16 val;
......
......@@ -64,6 +64,13 @@ void menu_calibrate(u8 at_poweron) {
lcd_7seg(channel);
lcd_menu(LM_MODEL | LM_NAME | LM_REV | LM_TRIM | LM_DR | LM_EXP);
lcd_set_blink(LMENU, LB_SPC);
// blink arrows for ch3 potentiometer also
if (cg.ch3_pot) {
lcd_segment(LS_SYM_LEFT, LS_ON);
lcd_segment(LS_SYM_RIGHT, LS_ON);
lcd_segment_blink(LS_SYM_LEFT, LB_SPC);
lcd_segment_blink(LS_SYM_RIGHT, LB_SPC);
}
while (1) {
// check keys
......@@ -79,7 +86,7 @@ void menu_calibrate(u8 at_poweron) {
}
else if (btn(BTN_ENTER)) {
// save calibrate value for channels 1 and 2
// save calibrate value for channels 1 and 2 (and 3 if ch3_pot)
// select actual voltage for channel 4
if (channel == 1) {
key_beep();
......@@ -117,6 +124,21 @@ void menu_calibrate(u8 at_poweron) {
lcd_segment(seg, LS_OFF); // set corresponding LCD off
lcd_update();
}
else if (channel == 3 && cg.ch3_pot) {
// only if ch3 is potentiometer
key_beep();
val = ADC_OVS(ch3);
if (val < 512) {
cg.calib_ch3_left = val;
seg = LS_SYM_LEFT;
}
else {
cg.calib_ch3_right = val;
seg = LS_SYM_RIGHT;
}
lcd_segment(seg, LS_OFF); // set corresponding LCD off
lcd_update();
}
else if (channel == 4) {
key_beep();
// allow to set actual battery voltage
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment