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);
+}
+