mirror of
https://github.com/semerad/gt3b.git
synced 2026-02-20 03:21:32 +01:00
add possibility to connect potentiometer instead of CH3 button
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
*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
|
||||
|
||||
19
MANUAL.txt
19
MANUAL.txt
@@ -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
|
||||
|
||||
6
TODO
6
TODO
@@ -1,10 +1,4 @@
|
||||
|
||||
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
|
||||
|
||||
23
calc.c
23
calc.c
@@ -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
|
||||
|
||||
11
config.c
11
config.c
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
13
config.h
13
config.h
@@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
7
input.c
7
input.c
@@ -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;
|
||||
|
||||
3
menu.h
3
menu.h
@@ -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
|
||||
|
||||
72
menu_key.c
72
menu_key.c
@@ -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();
|
||||
|
||||
21
menu_popup.c
21
menu_popup.c
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user