diff --git a/.depend b/.depend index de01f17..f5a7e6f 100644 --- a/.depend +++ b/.depend @@ -28,4 +28,6 @@ menu_mix.o: menu_mix.c menu.h gt3b.h stm8.h task.h \ config.h eeprom.h calc.h timer.h ppm.h lcd.h buzzer.h input.h menu_key.o: menu_key.c menu.h gt3b.h stm8.h task.h \ config.h eeprom.h calc.h timer.h ppm.h lcd.h buzzer.h input.h +menu_timer.o: menu_timer.c menu.h gt3b.h stm8.h \ + task.h lcd.h config.h eeprom.h vector.o: vector.c diff --git a/Makefile b/Makefile index 8a3849a..0621a13 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ PROGRAM = gt3b -SRCC = task.c main.c ppm.c lcd.c input.c buzzer.c timer.c eeprom.c config.c calc.c menu_common.c menu.c menu_service.c menu_global.c menu_popup.c menu_mix.c menu_key.c +SRCC = task.c main.c ppm.c lcd.c input.c buzzer.c timer.c eeprom.c config.c calc.c menu_common.c menu.c menu_service.c menu_global.c menu_popup.c menu_mix.c menu_key.c menu_timer.c INTRS = vector.c SMODE = #SMODE = l diff --git a/compile.bat b/compile.bat index 8e53ace..068f1c5 100644 --- a/compile.bat +++ b/compile.bat @@ -19,6 +19,7 @@ %TOOLSET%/cxstm8 +warn +proto +mods0 +debug -i. -i%TOOLSET%/Hstm8 -l -pxp -ac -dMAX_CHANNELS=%CHANNELS% menu_popup.c %TOOLSET%/cxstm8 +warn +proto +mods0 +debug -i. -i%TOOLSET%/Hstm8 -l -pxp -ac -dMAX_CHANNELS=%CHANNELS% menu_mix.c %TOOLSET%/cxstm8 +warn +proto +mods0 +debug -i. -i%TOOLSET%/Hstm8 -l -pxp -ac -dMAX_CHANNELS=%CHANNELS% menu_key.c +%TOOLSET%/cxstm8 +warn +proto +mods0 +debug -i. -i%TOOLSET%/Hstm8 -l -pxp -ac -dMAX_CHANNELS=%CHANNELS% menu_timer.c %TOOLSET%/cxstm8 +warn +proto +mods0 +debug -i. -i%TOOLSET%/Hstm8 -l -pxp -ac -dMAX_CHANNELS=%CHANNELS% vector.c %TOOLSET%/clnk -l%TOOLSET%/Lib -o gt3b.sm8 -mgt3b.map compile.lkf %TOOLSET%/cvdwarf gt3b.sm8 diff --git a/compile.lkf b/compile.lkf index 071baba..53ba458 100644 --- a/compile.lkf +++ b/compile.lkf @@ -8,7 +8,7 @@ +seg .data -b 0x100 -m 0x6ff+1-0x100 -n .data +seg .bss -a .data -n .bss crtsi0.sm8 -task.o main.o ppm.o lcd.o input.o buzzer.o timer.o eeprom.o config.o calc.o menu_common.o menu.o menu_service.o menu_global.o menu_popup.o menu_mix.o menu_key.o +task.o main.o ppm.o lcd.o input.o buzzer.o timer.o eeprom.o config.o calc.o menu_common.o menu.o menu_service.o menu_global.o menu_popup.o menu_mix.o menu_key.o menu_timer.o libis0.sm8 libm0.sm8 diff --git a/config.c b/config.c index 8206772..866b9a2 100644 --- a/config.c +++ b/config.c @@ -90,7 +90,7 @@ static const config_key_mapping_s default_key_mapping = { { { 0, 0, 0, 0, 0, 0, 0, 0 }, // CH3 to nothing { 0, 0, 0, 0, 0, 0, 0, 0 }, // BACK to nothing - { 0, 0, 0, 0, 20, 0, 0, 0 } // END-long to battery low shutup + { 0, 0, 0, 0, 1, 0, 0, 0 } // END-long to battery low shutup }, // trims: function, reverse, step, buttons { diff --git a/config.h b/config.h index bb3fe6d..a81181f 100644 --- a/config.h +++ b/config.h @@ -126,7 +126,7 @@ typedef struct { // change MAGIC number when changing model config // also add code to setting default values // 24 + 22(keys) + channels * 4 bytes -#define CONFIG_MODEL_MAGIC (0xf920 | (MAX_CHANNELS - 1)) +#define CONFIG_MODEL_MAGIC (0xf820 | (MAX_CHANNELS - 1)) typedef struct { u8 name[3]; u8 reverse; // bit for each channel diff --git a/menu.c b/menu.c index 7cd2bbb..ff5dbf8 100644 --- a/menu.c +++ b/menu.c @@ -36,12 +36,9 @@ // variables to be used in CALC task u8 menu_force_value_channel; // set PPM value for this channel s16 menu_force_value; // to this value (-500..500) -_Bool menu_tmp_flag; -// -u8 menu_lap_count; // lap count @@ -49,6 +46,8 @@ u8 menu_lap_count; // lap count _Bool menu_wants_adc; // don't stop main loop and check keys u8 menu_check_keys; +// temporary flag used when doing reset (global/all models/model) +_Bool menu_tmp_flag; @@ -66,18 +65,17 @@ static void show_model_number(u8 model) { // show main screen (model number and name/battery/...) static void main_screen(u8 item) { - lcd_segment(LS_SYM_MODELNO, LS_ON); - lcd_segment(LS_SYM_CHANNEL, LS_OFF); - lcd_segment(LS_SYM_PERCENT, LS_OFF); - show_model_number(cg.model); - menu_wants_adc = 0; // chars is item dependent if (item == MS_NAME) { // model name + lcd_segment(LS_SYM_MODELNO, LS_ON); + lcd_segment(LS_SYM_CHANNEL, LS_OFF); + lcd_segment(LS_SYM_PERCENT, 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) { @@ -85,8 +83,12 @@ static void main_screen(u8 item) { static u16 bat_time; // battery voltage + lcd_segment(LS_SYM_MODELNO, LS_ON); + lcd_segment(LS_SYM_CHANNEL, LS_OFF); + lcd_segment(LS_SYM_PERCENT, 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; @@ -95,11 +97,9 @@ static void main_screen(u8 item) { lcd_char_num3(bat_val); menu_wants_adc = 1; } - else if (item == MS_LAP_COUNT) { - lcd_segment(LS_SYM_DOT, LS_OFF); - lcd_segment(LS_SYM_VOLTS, LS_OFF); - lcd_segment(LS_SYM_PERCENT, LS_ON); - lcd_char_num3(menu_lap_count); + else { + // timers + menu_timer_show((u8)(item - MS_TIMER1)); } lcd_update(); } @@ -662,10 +662,16 @@ static void menu_loop(void) { // don't wanted in submenus, will be set back in main_screen() menu_wants_adc = 0; + menu_timer_wakeup = 0; // Enter long key - global/calibrate/key-test if (btnl(BTN_ENTER)) { - if (adc_steering_ovs > (CALIB_ST_MID_HIGH << ADC_OVS_SHIFT)) + if (menu_main_screen >= MS_TIMER1) { + key_beep(); + menu_timer_lap_times((u8)(menu_main_screen - MS_TIMER1)); + btnra(); + } + else if (adc_steering_ovs > (CALIB_ST_MID_HIGH << ADC_OVS_SHIFT)) menu_calibrate(0); else if (adc_steering_ovs < (CALIB_ST_LOW_MID << ADC_OVS_SHIFT)) menu_key_test(); @@ -675,7 +681,9 @@ static void menu_loop(void) { // Enter key - menu else if (btn(BTN_ENTER)) { key_beep(); - select_menu(); + if (menu_main_screen >= MS_TIMER1) + menu_timer_setup((u8)(menu_main_screen - MS_TIMER1)); + else select_menu(); btnra(); } diff --git a/menu.h b/menu.h index 33bb4f2..9b266cb 100644 --- a/menu.h +++ b/menu.h @@ -40,6 +40,7 @@ #define CHANNEL_FAST 5 #define MIX_FAST 5 #define SPEED_FAST 5 +#define TIMER_ALARM_FAST 5 // delay in seconds of popup menu (trim, dualrate, ...) #define POPUP_DELAY 5 @@ -66,12 +67,8 @@ extern s8 menu_4WS_mix; // mix -100..100 extern _Bool menu_4WS_crab; // when 1, crab steering extern s8 menu_DIG_mix; // mix -100..100 extern u8 menu_MP_index; // index of MultiPosition channel -extern _Bool menu_tmp_flag; -// -extern u8 menu_lap_count; // lap count - @@ -89,6 +86,8 @@ extern _Bool battery_low_shutup; // stop bat low beeping extern u16 battery_low_raw; // don't stop main loop and check keys extern u8 menu_check_keys; +// temporary flag used when doing reset (global/all models/model) +extern _Bool menu_tmp_flag; @@ -123,8 +122,9 @@ extern void menu_buttons_initialize(void); extern u8 menu_main_screen; #define MS_NAME 0 #define MS_BATTERY 1 -#define MS_LAP_COUNT 2 -#define MS_MAX 3 +#define MS_TIMER1 2 +#define MS_TIMER2 3 +#define MS_MAX 4 // common menus, select item in 7SEG and then modify its setting at CHR3 // val_id: 1..num_values - which param of this item to change // action: 0=show, 1=change, 2=get_next_val_id @@ -132,5 +132,49 @@ typedef u8 (*menu_func_t)(u8 val_id, u8 action, u8 *chars_blink); extern void menu_common(menu_func_t *menu_funcs, u8 menu_nitems, u8 use_stop); + +// timers +// types +#define TIMER_NUM 2 +#define TIMER_OFF 0 +#define TIMER_UP 1 +#define TIMER_DOWN 2 +#define TIMER_LAP 3 +#define TIMER_LAPCNT 4 +#define TIMER_TYPE_MAX 4 + +#define TIMER_TYPE(tid) ((u8)(tid ? cg.timer2_type : cg.timer1_type)) +#define TIMER_TYPE_SET(tid, val) \ + if (tid) cg.timer2_type = (u8)val; \ + else cg.timer1_type = (u8)val; + +#define TIMER_ALARM(tid) ((u8)(tid ? cg.timer2_alarm : cg.timer1_alarm)) +#define TIMER_ALARM_SET(tid, val) \ + if (tid) cg.timer2_alarm = (u8)val; \ + else cg.timer1_alarm = (u8)val; + +// menu task will be waked-up periodically to show timer value +extern _Bool menu_timer_wakeup; +extern u8 menu_timer_running; // running timers, one bit for one timer +extern @near u8 menu_timer_throttle; // throttle start, one bit for one timer + +typedef struct { + u16 sec; // timer seconds + u8 hdr; // timers 0.01 seconds +} menu_timer_s; +extern @near menu_timer_s menu_timer[]; // actual timer values +#define TIMER_READ(pt, tsec, thdr) \ + sim(); \ + tsec = pt->sec; \ + thdr = pt->hdr; \ + rim(); + +void menu_timer_show(u8 tid); +void menu_timer_setup(u8 tid); +void menu_timer_lap_times(u8 tid); +void kf_menu_timer_start(u8 *id, u8 *param, u8 flags, s16 *pv); +void kf_menu_timer_reset(u8 *id, u8 *param, u8 flags, s16 *pv); + + #endif diff --git a/menu_popup.c b/menu_popup.c index 1dd9aa3..61ebd15 100644 --- a/menu_popup.c +++ b/menu_popup.c @@ -619,7 +619,7 @@ typedef struct { #define SF_ROTATE 1 -// set channel value to one endpoint +// set channel value to one endpoint (also to middle with 3-pos CH3) static void kf_set_switch(u8 *id, u8 *param, u8 flags, s16 *prev_val) { u8 *name = param ? param : id; et_functions_s *etf = menu_et_function_find_name(name); @@ -732,16 +732,6 @@ static void kf_multi_position_reset(u8 *id, u8 *param, u8 flags, s16 *pv) { } } -// lap counter -static void kf_lap_count(u8 *id, u8 *param, u8 flags, s16 *pv) { - menu_lap_count++; - menu_main_screen = MS_LAP_COUNT; -} -static void kf_lap_count_reset(u8 *id, u8 *param, u8 flags, s16 *pv) { - menu_lap_count = 0; - menu_main_screen = MS_LAP_COUNT; -} - // shut up battery low beeper static void kf_battery_low_shutup(u8 *id, u8 *param, u8 flags, s16 *pv) { battery_low_shutup = 1; @@ -754,6 +744,7 @@ static void kf_battery_low_shutup(u8 *id, u8 *param, u8 flags, s16 *pv) { // table of key functions static const key_functions_s key_functions[] = { { 0, "OFF", KF_NONE, NULL, NULL, 0 }, + { 22, "BLS", KF_NOSHOW, kf_battery_low_shutup, NULL, 0 }, // default END-long { 1, "CH3", KF_2STATE, kf_set_switch, NULL, 3 }, { 7, "C3R", KF_NONE, kf_reset, "CH3", 3 }, #if MAX_CHANNELS >= 4 @@ -781,9 +772,10 @@ static const key_functions_s key_functions[] = { { 15, "DGR", KF_NONE, kf_reset, "DIG", 3 }, { 16, "MPO", KF_NONE, kf_multi_position, NULL, 3 }, { 17, "MPR", KF_NONE, kf_multi_position_reset, NULL, 3 }, - { 18, "LCI", KF_NOSHOW, kf_lap_count, NULL, 0 }, - { 19, "LCR", KF_NOSHOW, kf_lap_count_reset, NULL, 0 }, - { 20, "BLS", KF_NOSHOW, kf_battery_low_shutup, NULL, 0 }, // default END-long + { 18, "T1S", KF_NOSHOW, kf_menu_timer_start, (u8 *)0, 0 }, + { 19, "T1R", KF_NOSHOW, kf_menu_timer_reset, (u8 *)0, 0 }, + { 20, "T2S", KF_NOSHOW, kf_menu_timer_start, (u8 *)1, 0 }, + { 21, "T2R", KF_NOSHOW, kf_menu_timer_reset, (u8 *)1, 0 }, }; #define KEY_FUNCTIONS_SIZE (sizeof(key_functions) / sizeof(key_functions_s)) diff --git a/menu_timer.c b/menu_timer.c new file mode 100644 index 0000000..9a508b7 --- /dev/null +++ b/menu_timer.c @@ -0,0 +1,258 @@ +/* + menu - handle popup menus + Copyright (C) 2011 Pavel Semerad + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + + +#include +#include "menu.h" +#include "lcd.h" +#include "config.h" + + + + +// menu task will be waked-up peridodically to show timer value +_Bool menu_timer_wakeup; + + +// actual timer values +u8 menu_timer_running; // running timers +@near u8 menu_timer_throttle; // throttle start for each timer +@near menu_timer_s menu_timer[TIMER_NUM]; // actual timer values +// number of laps +static @near u8 timer_lap_count[TIMER_NUM]; +// time for each lap +#define TIMER_MAX_LAPS 100 +static @near menu_timer_s timer_lap_time[TIMER_NUM][TIMER_MAX_LAPS]; + + + + + +// show actual timer value +void menu_timer_show(u8 tid) { + u8 type = TIMER_TYPE(tid); + + menu_clear_symbols(); + lcd_7seg((u8)(tid + 1)); + + switch (type) { + + case TIMER_OFF: + lcd_chars("OFF"); + break; + + case TIMER_UP: + lcd_chars("NDY"); // XXX + break; + + case TIMER_DOWN: + lcd_chars("NDY"); // XXX + break; + + case TIMER_LAP: + lcd_chars("NDY"); // XXX + break; + + case TIMER_LAPCNT: + lcd_char_num3(timer_lap_count[tid]); + break; + + } +} + + + + +// clear timer +static void timer_clear(u8 tid) { + menu_timer_s *pt = &menu_timer[tid]; + pt->sec = 0; + pt->hdr = 0; + menu_timer_running &= (u8)~(u8)(1 << tid); + timer_lap_count[tid] = 0; + memset(&timer_lap_time[tid], 0, TIMER_MAX_LAPS * sizeof(menu_timer_s)); +} + + + + +// setup timer + +static u8 timer_id; // for setup to know which timer to operate +static u8 timer_setup_throttle(u8 val_id, u8 action, u8 *chars_blink) { + // change value + if (action == 1) + menu_timer_throttle ^= (u8)(1 << timer_id); + + // select next value + else if (action == 2) timer_clear(timer_id); + + // show value + lcd_7seg(L7_H); + lcd_chars(menu_timer_throttle & (u8)(1 << timer_id) ? "ON " : "OFF"); + + return 1; // only one value +} + +static u8 timer_setup_alarm(u8 val_id, u8 action, u8 *chars_blink) { + u8 val = TIMER_ALARM(timer_id); + + // change value + if (action == 1) { + val = (u8)menu_change_val(val, 0, 255, TIMER_ALARM_FAST, 0); + TIMER_ALARM_SET(timer_id, val); + } + + // select next value + else if (action == 2) timer_clear(timer_id); + + // show value + lcd_7seg(L7_A); + lcd_char_num3(val); + + return 1; // only one value +} + +static const u8 timer_type_labels[][5] = { + "OFF", "UP ", "DWN", "LPT", "LPC" +}; +static u8 timer_setup_type(u8 val_id, u8 action, u8 *chars_blink) { + u8 val = TIMER_TYPE(timer_id); + + // change value + if (action == 1) { + val = (u8)menu_change_val(val, 0, TIMER_TYPE_MAX, 1, 1); + TIMER_TYPE_SET(timer_id, val); + } + + // select next value + else if (action == 2) timer_clear(timer_id); + + // show value + lcd_7seg(L7_P); + lcd_chars(timer_type_labels[val]); + + return 1; // only one value +} + +static const menu_func_t timer_setup_funcs[] = { + timer_setup_throttle, + timer_setup_alarm, + timer_setup_type, +}; + +void menu_timer_setup(u8 tid) { + timer_id = tid; + menu_common(timer_setup_funcs, sizeof(timer_setup_funcs) / sizeof(void *), 0); + config_global_save(); +} + + + + + +// show timer lap times +void menu_timer_lap_times(u8 tid) { + u8 type = TIMER_TYPE(tid); + + switch (type) { + + case TIMER_OFF: + case TIMER_UP: + case TIMER_LAPCNT: + // no lap times + return; + break; + + case TIMER_DOWN: + case TIMER_LAP: + // show lap times XXX + break; + + } +} + + + + +// key functions +void kf_menu_timer_start(u8 *id, u8 *param, u8 flags, s16 *pv) { + u8 tid = (u8)(u16)param; + u8 type = TIMER_TYPE(tid); + menu_timer_s *pt = &menu_timer[tid]; + + switch (type) { + + case TIMER_OFF: + return; + break; + + case TIMER_UP: + // XXX + break; + + case TIMER_DOWN: + // XXX + break; + + case TIMER_LAP: + // XXX + break; + + case TIMER_LAPCNT: + timer_lap_count[tid]++; + break; + + } + + menu_main_screen = (u8)(MS_TIMER1 + tid); +} + +void kf_menu_timer_reset(u8 *id, u8 *param, u8 flags, s16 *pv) { + u8 tid = (u8)(u16)param; + u8 type = TIMER_TYPE(tid); + menu_timer_s *pt = &menu_timer[tid]; + + switch (type) { + + case TIMER_OFF: + return; + break; + + case TIMER_UP: + // XXX + break; + + case TIMER_DOWN: + // XXX + break; + + case TIMER_LAP: + // XXX + break; + + case TIMER_LAPCNT: + timer_lap_count[tid] = 0; + break; + + } + + menu_main_screen = (u8)(MS_TIMER1 + tid); +} +