diff --git a/config.h b/config.h index f59de8d..16daa13 100644 --- a/config.h +++ b/config.h @@ -3,23 +3,28 @@ #ifndef _CONFIG_H_ #define _CONFIG_H_ -#define CONFIG_FREQUENCY 902 +#define CONFIG_FREQUENCY 433 #define OPTION_TIME_DISPLAY 0 -// CONFIG_METRIC_ONLY is not set +#define CONFIG_METRIC_ONLY +#define FIXEDPOINT #ifndef THIS_DEVICE_ADDRESS #define THIS_DEVICE_ADDRESS {0xed,0xc0,0xbb,0x25} #endif // THIS_DEVICE_ADDRESS // USE_LCD_CHARGE_PUMP is not set -#define USE_WATCHDOG +// USE_WATCHDOG is not set // DEBUG is not set #define CONFIG_DAY_OF_WEEK -#define CONFIG_TEST -// CONFIG_EGGTIMER is not set +// CONFIG_TEST is not set +#define CONFIG_EGGTIMER // CONFIG_PHASE_CLOCK is not set #define CONFIG_ALTITUDE -// CONFIG_VARIO is not set +#define CONFIG_VARIO +// CONFIG_ALTI_ACCUMULATOR is not set // CONFIG_PROUT is not set +// CONFIG_SIDEREAL is not set +// CONFIG_INFOMEM is not set #define CONFIG_ACCEL +// CONFIG_STRENGTH is not set #define CONFIG_ALARM #define CONFIG_BATTERY #define CONFIG_CLOCK @@ -27,5 +32,11 @@ #define CONFIG_RFBSL #define CONFIG_STOP_WATCH #define CONFIG_TEMP +#define CONFIG_USEPPT +// CONFIG_USE_SYNC_TOSET_TIME is not set +// CONFIG_USE_DISCRET_RFBSL is not set +// CONFIG_USE_GPS is not set +// CONFIG_CW_TIME is not set +#define CONFIG_CW #endif // _CONFIG_H_ diff --git a/driver/buzzer.c b/driver/buzzer.c index 9a59b54..4eebc6b 100644 --- a/driver/buzzer.c +++ b/driver/buzzer.c @@ -56,14 +56,35 @@ void toggle_buzzer(void); void countdown_buzzer(void); +#ifdef CONFIG_CW +void my_start_buzzer(); +#endif /*CONFIG_CW*/ + // ************************************************************************************************* // Defines section +#ifdef CONFIG_CW +#define BUZZER_QUEUE_SIZE 100 +struct buzzer_queue_element { + u8 cycles; + u16 on_time; + u16 off_time; +}; +struct buzzer_queue { + u8 first; + u8 last; + struct buzzer_queue_element queue[BUZZER_QUEUE_SIZE]; +}; + +#endif /*CONFIG_CW*/ // ************************************************************************************************* // Global Variable section struct buzzer sBuzzer; +#ifdef CONFIG_CW +struct buzzer_queue sBuzzer_queue; +#endif /*CONFIG_CW*/ // ************************************************************************************************* @@ -96,6 +117,33 @@ void reset_buzzer(void) // ************************************************************************************************* void start_buzzer(u8 cycles, u16 on_time, u16 off_time) { +#ifdef CONFIG_CW +// cw play requires queue!! + sBuzzer_queue.queue[ sBuzzer_queue.last ].cycles = cycles; + sBuzzer_queue.queue[ sBuzzer_queue.last ].on_time = on_time; + sBuzzer_queue.queue[ sBuzzer_queue.last ].off_time = off_time; + + sBuzzer_queue.last = (sBuzzer_queue.last + 1) % BUZZER_QUEUE_SIZE ; // no queue full check, queue MUST be long enought + + if (sBuzzer.state == BUZZER_OFF) { + // if not playing start! + my_start_buzzer(); + } +} + +void my_start_buzzer() +{ + u8 cycles = sBuzzer_queue.queue[ sBuzzer_queue.first ].cycles; + u16 on_time = sBuzzer_queue.queue[ sBuzzer_queue.first ].on_time; + u16 off_time = sBuzzer_queue.queue[ sBuzzer_queue.first ].off_time; + + if (sBuzzer_queue.first == sBuzzer_queue.last) { + // queue empty + return; + } + sBuzzer_queue.first = (sBuzzer_queue.first + 1) % BUZZER_QUEUE_SIZE ; + +#endif /*CONFIG_CW*/ // Store new buzzer duration while buzzer is off if (sBuzzer.time == 0) { @@ -109,23 +157,45 @@ void start_buzzer(u8 cycles, u16 on_time, u16 off_time) TA1CTL = TACLR | MC_1 | TASSEL__ACLK; // Set PWM frequency - TA1CCR0 = sBuzzer.steps; + TA1CCR0 = sBuzzer.steps; // Enable IRQ, set output mode "toggle" TA1CCTL0 = OUTMOD_4; - // Allow buzzer PWM output on P2.7 - P2SEL |= BIT7; - // Activate Timer0_A3 periodic interrupts fptr_Timer0_A3_function = toggle_buzzer; - Timer0_A3_Start(sBuzzer.on_time); - // Preload timer advance variable - sTimer.timer0_A3_ticks = sBuzzer.off_time; +#ifdef CONFIG_CW + if (on_time > 0 ) { // we use on_time = 0 to play only silence +#endif /*CONFIG_CW*/ + // Allow buzzer PWM output on P2.7 + P2SEL |= BIT7; + + Timer0_A3_Start(sBuzzer.on_time); + + // Preload timer advance variable + sTimer.timer0_A3_ticks = sBuzzer.off_time; + + // Start with buzzer output on + sBuzzer.state = BUZZER_ON_OUTPUT_ENABLED; +#ifdef CONFIG_CW + } else { + // we use on_time = 0 to play only silence - // Start with buzzer output on - sBuzzer.state = BUZZER_ON_OUTPUT_ENABLED; + // Reset and disable buzzer PWM output + P2OUT &= ~BIT7; + P2SEL &= ~BIT7; + + Timer0_A3_Start(sBuzzer.off_time); + + // Preload timer advance variable even if we know it's 0 + sTimer.timer0_A3_ticks = sBuzzer.on_time; + + // Start with buzzer output off + sBuzzer.state = BUZZER_ON_OUTPUT_DISABLED; + + } +#endif /*CONFIG_CW*/ } } @@ -179,6 +249,11 @@ void toggle_buzzer(void) // Reload Timer0_A4 IRQ to turn off output sTimer.timer0_A3_ticks = sBuzzer.off_time; +#ifdef CONFIG_CW + } else { + // play next sequence if any + my_start_buzzer(); +#endif /*CONFIG_CW*/ } } } @@ -238,3 +313,116 @@ void countdown_buzzer(void) stop_buzzer(); } } + + +#ifdef CONFIG_CW +// All this will be put in a separate file later + +#include "clock.h" + +// some ideas from cwlib +#define DOT_MAGIC 1200 /* Dot length magic number. The Dot + length is 1200/WPM msec */ +#define INITIAL_SEND_SPEED 18 /* Initial send speed in WPM */ + + +#define DOT_TICKS CONV_MS_TO_TICKS(DOT_MAGIC/INITIAL_SEND_SPEED) +#define DASH_TICKS CONV_MS_TO_TICKS(DOT_MAGIC/INITIAL_SEND_SPEED*3) + +#define FIRST_CW_CHAR '0' +#define LAST_CW_CHAR 'Z' +struct cw_char { + u8 nsymbols; + u8 *symbols; // use a sort of compression: symbols represent number of dots if < 128 else number of dash in 1-complement +} cw_font[] = { + {1, (u8[]) {250}}, // 0 ----- + {2, (u8[]) {1, 251}}, // 1 .---- + {2, (u8[]) {2, 252}}, // 2 ..--- + {2, (u8[]) {3, 253}}, // 3 ...-- + {2, (u8[]) {4, 254}}, // 4 ....- + {1, (u8[]) {5}}, // 5 ..... + {2, (u8[]) {254, 4}}, // 6 _.... + {2, (u8[]) {253, 3}}, // 7 --... + {2, (u8[]) {252, 2}}, // 8 ---.. + {2, (u8[]) {251, 1}}, // 9 ----. + {2, (u8[]) {252, 3}}, // : ---... + {0, NULL}, // ; NONE + {0, NULL}, // < NONE + {3, (u8[]) {254, 3 ,254}}, // = -...- + {0, NULL}, // > NONE + {3, (u8[]) {253, 2, 253}}, // ? ..--.. + {0, NULL}, // @ NONE + {2, (u8[]) {1, 254}}, // A .- + {2, (u8[]) {254, 3}}, // B -... + {4, (u8[]) {254, 1, 254, 1}},// C -.-. + {2, (u8[]) {254, 2}}, // D -.. + {1, (u8[]) {1}}, // E . + {3, (u8[]) {2, 254, 1}}, // F ..-. + {2, (u8[]) {253, 1}}, // G --. + {1, (u8[]) {4}}, // H .... + {1, (u8[]) {2}}, // I .. + {2, (u8[]) {1, 252}}, // J .--- + {3, (u8[]) {254, 1, 254}}, // K -.- + {3, (u8[]) {1, 254, 2}}, // L .-.. + {1, (u8[]) {253}}, // M -- + {2, (u8[]) {254, 1}}, // N -. + {1, (u8[]) {252}}, // O --- + {3, (u8[]) {1, 253, 1}}, // P .--. + {3, (u8[]) {253, 1, 254}}, // Q --.- + {3, (u8[]) {1, 254, 1}}, // R .-. + {1, (u8[]) {3}}, // S ... + {1, (u8[]) {254}}, // T - + {2, (u8[]) {2, 254}}, // U ..- + {2, (u8[]) {3, 254}}, // V ...- + {2, (u8[]) {1, 253}}, // W .-- + {3, (u8[]) {254, 2, 254}}, // X -..- + {3, (u8[]) {254, 1, 253}}, // Y -.-- + {2, (u8[]) {253, 2}} // Z --.. +}; + +void cw_chars(char *str) +{ + // quick and dirty use of pointer + for (; *str != 0; str++) { + u8 c = (u8) (*str); + struct cw_char cw_c; + u8 i; + + c = (cLAST_CW_CHAR) ? ('?' - FIRST_CW_CHAR) : (c - FIRST_CW_CHAR) ; + // transmit a ? for all unknown char + // and calculate symbol table index + cw_c = cw_font[c]; + for (i = 0; i < cw_c.nsymbols; i++) { + if (cw_c.symbols[i] < 128 ) { + // play dots + start_buzzer(cw_c.symbols[i], DOT_TICKS, DOT_TICKS); + } else { + // play dash + start_buzzer(~cw_c.symbols[i], DASH_TICKS, DOT_TICKS); + } + } + // every symbol end with a "dot silent" so add rest of a "dash silent" to end the char + start_buzzer(1, 0, DASH_TICKS - DOT_TICKS); + } + // extra delay to separate next word (minus usual end char silent) + start_buzzer(1, 0, DOT_TICKS * 7 - DASH_TICKS); +} + +void cw_say_time() +{ + char now[5]; + u8 *str; + + str = itoa(sTime.hour, 2, 0); + now[0] = *str; + now[1] = *(str+1); + str = itoa(sTime.minute, 2, 0); + now[2] = *str; + now[3] = *(str+1); + now[4] = 0; + + cw_chars(now); +} + + +#endif diff --git a/driver/buzzer.h b/driver/buzzer.h index 0892967..012458e 100644 --- a/driver/buzzer.h +++ b/driver/buzzer.h @@ -51,6 +51,10 @@ extern void toggle_buzzer(void); extern u8 is_buzzer(void); extern void countdown_buzzer(void); +#ifdef CONFIG_CW +void cw_chars(char *str); +void cw_say_time(); +#endif /*CONFIG_CW*/ // ************************************************************************************************* // Defines section diff --git a/ezchronos.c b/ezchronos.c index 5a2ab71..3cdb689 100644 --- a/ezchronos.c +++ b/ezchronos.c @@ -170,6 +170,10 @@ int main(void) display_all_off(); #endif +#ifdef CONFIG_CW + cw_chars("V01"); // say version number to the world +#endif /*CONFIG_CW*/ + // Main control loop: wait in low power mode until some event needs to be processed while(1) { @@ -534,7 +538,12 @@ void wakeup_event(void) // Clear button flag button.flag.down = 0; - } + } else if (button.flag.backlight) { +#ifdef CONFIG_CW + cw_say_time(); +#endif // CONFIG_CW + button.flag.backlight = 0; + } } // Process internal events @@ -658,8 +667,17 @@ void display_update(void) line = LINE2; // Select message to display - if (message.flag.type_locked) memcpy(string, " LOCT", 6); - else if (message.flag.type_unlocked) memcpy(string, " OPEN", 6); + if (message.flag.type_locked) { + memcpy(string, " LOCT", 6); +#ifdef CONFIG_CW + cw_chars("LOCK"); +#endif /*CONFIG_CW*/ + } else if (message.flag.type_unlocked) { + memcpy(string, " OPEN", 6); +#ifdef CONFIG_CW + cw_chars("UNLOCK"); +#endif /*CONFIG_CW*/ + } else if (message.flag.type_lobatt) memcpy(string, "LOBATT", 6); else if (message.flag.type_no_beep_on) memcpy(string, " SILNT", 6); else if (message.flag.type_no_beep_off) memcpy(string, " BEEP", 6); diff --git a/tools/config.py b/tools/config.py index 60b0d90..59775b8 100755 --- a/tools/config.py +++ b/tools/config.py @@ -214,8 +214,7 @@ def rand_hw(): "name": "Temperature", "depends": [], "default": True} - - + ###IMPLEMENTED BY LeanChronos. gventosa 09.10.2010 DATA["CONFIG_USEPPT"] = { "name": "Use PPT", @@ -243,6 +242,14 @@ def rand_hw(): "default": False, "help": "Send time in morse code"} +# by IZ3GME new modules with cw playing +DATA["CONFIG_CW"] = { + "name": "CW Extensions", + "depends": [], + "default": False, + "help": "A more general CW extention (different and indipendent from CW_TIME)"} + + HEADER = """ #ifndef _CONFIG_H_ #define _CONFIG_H_