diff options
-rw-r--r-- | src/fsm/cw.c | 87 | ||||
-rw-r--r-- | src/fsm/fsm.c | 51 | ||||
-rw-r--r-- | src/fsm/fsm.h | 12 | ||||
-rw-r--r-- | src/fsm/main.c | 81 |
4 files changed, 129 insertions, 102 deletions
diff --git a/src/fsm/cw.c b/src/fsm/cw.c index ee0ba77..654df22 100644 --- a/src/fsm/cw.c +++ b/src/fsm/cw.c @@ -45,7 +45,8 @@ #include "queue.h" #include "semphr.h" -#define ON_BUFFER_SIZE 1024 +#define MAX_MESSAGE_LEN 1024 +#define MAX_ON_BUFFER_LEN 8192 const uint8_t cw_mapping[60] = { // {{{ // Read bits from right to left @@ -110,11 +111,9 @@ const uint8_t cw_mapping[60] = { // {{{ 0b1010111, // SK , ASCII '\' }; //}}} -struct cw_out_message_s { - // Contains a sequence of ones and zeros corresponding to - // TX on/TX off CW data to be sent - uint8_t on_buffer[ON_BUFFER_SIZE]; - size_t on_buffer_end; +struct cw_message_s { + char message[MAX_MESSAGE_LEN]; + size_t message_len; int freq; int dit_duration; @@ -136,7 +135,7 @@ void cw_init(unsigned int samplerate) cw_samplerate = samplerate; cw_transmit_ongoing = 0; - cw_msg_queue = xQueueCreate(15, sizeof(struct cw_out_message_s)); + cw_msg_queue = xQueueCreate(15, sizeof(struct cw_message_s)); if (cw_msg_queue == 0) { while(1); /* fatal error */ } @@ -155,31 +154,35 @@ void cw_init(unsigned int samplerate) NULL); } -void cw_symbol(uint8_t sym, struct cw_out_message_s *msg) +/* Parse one CW letter/symbol, and fill in the on_buffer. + * Returns number of uint8_t written. + */ +size_t cw_symbol(uint8_t sym, uint8_t *on_buffer, size_t on_buffer_size) { uint8_t p = 0; uint8_t val = cw_mapping[sym]; + size_t pos = 0; while((val >> p) != 0b1) { if (((val >> p) & 0b1) == 0b1) { - if (msg->on_buffer_end + 2 < ON_BUFFER_SIZE) { + if (pos + 2 < on_buffer_size) { // tone(1) - msg->on_buffer[msg->on_buffer_end++] = 1; + on_buffer[pos++] = 1; // silence(1) - msg->on_buffer[msg->on_buffer_end++] = 0; + on_buffer[pos++] = 0; } } else { - if (msg->on_buffer_end + 4 < ON_BUFFER_SIZE) { + if (pos + 4 < on_buffer_size) { // tone(3) - msg->on_buffer[msg->on_buffer_end++] = 1; - msg->on_buffer[msg->on_buffer_end++] = 1; - msg->on_buffer[msg->on_buffer_end++] = 1; + on_buffer[pos++] = 1; + on_buffer[pos++] = 1; + on_buffer[pos++] = 1; // silence(1) - msg->on_buffer[msg->on_buffer_end++] = 0; + on_buffer[pos++] = 0; } } @@ -187,11 +190,13 @@ void cw_symbol(uint8_t sym, struct cw_out_message_s *msg) } // silence(2) - if (msg->on_buffer_end + 2 < ON_BUFFER_SIZE) { + if (pos + 2 < on_buffer_size) { for (int i = 0; i < 2; i++) { - msg->on_buffer[msg->on_buffer_end++] = 0; + on_buffer[pos++] = 0; } } + + return pos; } // Transmit a string in morse code. Supported range: @@ -199,30 +204,46 @@ void cw_symbol(uint8_t sym, struct cw_out_message_s *msg) // numerals and capital letters. void cw_push_message(const char* text, int dit_duration, int frequency) { - struct cw_out_message_s msg; - for (int i = 0; i < ON_BUFFER_SIZE; i++) { - msg.on_buffer[i] = 0; + const int text_len = strlen(text); + + struct cw_message_s msg; + for (int i = 0; i < MAX_MESSAGE_LEN; i++) { + if (i < text_len) { + msg.message[i] = text[i]; + } + else { + msg.message[i] = '\0'; + } } - msg.on_buffer_end = 0; + msg.message_len = text_len; msg.freq = frequency; msg.dit_duration = dit_duration; - const char* sym = text; + xQueueSendToBack(cw_msg_queue, &msg, portMAX_DELAY); /* Send Message */ +} + +/* Parse the message and fill the on_buffer with CW on/CW off information. + * Returns the number of on/off bits written. + */ +size_t cw_text_to_on_buffer(const char *msg, uint8_t *on_buffer, size_t on_buffer_size) +{ + size_t pos = 0; + const char* sym = msg; do { if (*sym < '+' || *sym > '\\') { - if (msg.on_buffer_end + 3 < ON_BUFFER_SIZE) { + if (pos + 3 < on_buffer_size) { for (int i = 0; i < 3; i++) { - msg.on_buffer[msg.on_buffer_end++] = 0; + on_buffer[pos++] = 0; } } } else { - cw_symbol(*sym - '+', &msg); + pos += cw_symbol(*sym - '+', on_buffer + pos, on_buffer_size - pos); } sym++; } while (*sym != '\0'); - xQueueSendToBack(cw_msg_queue, &msg, portMAX_DELAY); /* Send Message */ + return pos; } size_t cw_fill_buffer(int16_t *buf, size_t bufsize) @@ -236,7 +257,8 @@ size_t cw_fill_buffer(int16_t *buf, size_t bufsize) } static int16_t cw_audio_buf[AUDIO_BUF_LEN]; -static struct cw_out_message_s cw_fill_msg_current; +static uint8_t cw_on_buffer[MAX_ON_BUFFER_LEN]; +static struct cw_message_s cw_fill_msg_current; static void cw_task(void *pvParameters) { float nco_phase = 0.0f; @@ -248,6 +270,11 @@ static void cw_task(void *pvParameters) int status = xQueueReceive(cw_msg_queue, &cw_fill_msg_current, portMAX_DELAY); if (status == pdTRUE) { + size_t on_buffer_len = cw_text_to_on_buffer( + cw_fill_msg_current.message, + cw_on_buffer, + MAX_ON_BUFFER_LEN); + cw_transmit_ongoing = 1; const int samples_per_dit = @@ -257,12 +284,12 @@ static void cw_task(void *pvParameters) const float omega = 2.0f * FLOAT_PI * cw_fill_msg_current.freq / (float)cw_samplerate; - for (int i = 0; i < cw_fill_msg_current.on_buffer_end; i++) { + for (int i = 0; i < on_buffer_len; i++) { for (int t = 0; t < samples_per_dit; t++) { int16_t s = 0; // Remove clicks from CW - if (cw_fill_msg_current.on_buffer[i]) { + if (cw_on_buffer[i]) { const float remaining = 32768.0f - ampl; ampl += remaining / 64.0f; } diff --git a/src/fsm/fsm.c b/src/fsm/fsm.c index 88211d8..1ef92bf 100644 --- a/src/fsm/fsm.c +++ b/src/fsm/fsm.c @@ -92,8 +92,9 @@ void fsm_update() { fsm_out.tx_on = 0; fsm_out.modulation = 0; fsm_out.cw_trigger = 0; + fsm_out.psk_trigger = 0; fsm_out.cw_dit_duration = 50; - fsm_out.cw_frequency = 960; + fsm_out.msg_frequency = 960; // other output signals keep their value switch (current_state) { @@ -134,10 +135,10 @@ void fsm_update() { case FSM_LETTRE: fsm_out.tx_on = 1; fsm_out.modulation = 1; - fsm_out.cw_msg = fsm_select_letter(); - if (fsm_out.cw_msg[0] == 'G') { + fsm_out.msg = fsm_select_letter(); + if (fsm_out.msg[0] == 'G') { // The letter 'G' is a bit different - fsm_out.cw_frequency = 696; + fsm_out.msg_frequency = 696; fsm_out.cw_dit_duration = 70; } fsm_out.cw_trigger = 1; @@ -205,7 +206,7 @@ void fsm_update() { case FSM_ANTI_BAVARD: fsm_out.tx_on = 1; // No modulation! - fsm_out.cw_msg = "HI HI"; + fsm_out.msg = "HI HI"; fsm_out.cw_trigger = 1; if (fsm_in.cw_done) { @@ -222,9 +223,9 @@ void fsm_update() { case FSM_TEXTE_73: fsm_out.tx_on = 1; fsm_out.modulation = 1; - fsm_out.cw_frequency = 696; + fsm_out.msg_frequency = 696; fsm_out.cw_dit_duration = 70; - fsm_out.cw_msg = "73"; + fsm_out.msg = "73"; fsm_out.cw_trigger = 1; if (fsm_in.sq) { @@ -238,9 +239,9 @@ void fsm_update() { case FSM_TEXTE_HB9G: fsm_out.tx_on = 1; fsm_out.modulation = 1; - fsm_out.cw_frequency = 696; + fsm_out.msg_frequency = 696; fsm_out.cw_dit_duration = 70; - fsm_out.cw_msg = "HB9G"; + fsm_out.msg = "HB9G"; fsm_out.cw_trigger = 1; if (fsm_in.sq) { @@ -255,14 +256,14 @@ void fsm_update() { fsm_out.tx_on = 1; fsm_out.modulation = 1; - fsm_out.cw_frequency = 696; + fsm_out.msg_frequency = 696; fsm_out.cw_dit_duration = 70; if (random_bool()) { - fsm_out.cw_msg = "HB9G 1628M"; + fsm_out.msg = "HB9G 1628M"; } else { - fsm_out.cw_msg = "HB9G JN36BK"; + fsm_out.msg = "HB9G JN36BK"; } fsm_out.cw_trigger = 1; @@ -277,42 +278,42 @@ void fsm_update() { case FSM_BALISE_LONGUE: fsm_out.tx_on = 1; - fsm_out.cw_frequency = 588; + fsm_out.msg_frequency = 588; fsm_out.cw_dit_duration = 110; // TODO transmit humidity // TODO read voltage if (fsm_in.wind_generator_ok) { - fsm_out.cw_msg = "HB9G JN36BK 1628M U 10V5 = T 11 73"; + fsm_out.msg = "HB9G JN36BK 1628M U 10V5 = T 11 73"; // = means same voltage as previous // + means higher // - means lower } else { - fsm_out.cw_msg = "HB9G JN36BK 1628M U 10V5 = T 11 #"; + fsm_out.msg = "HB9G JN36BK 1628M U 10V5 = T 11 #"; // The # is the SK digraph } - fsm_out.cw_trigger = 1; + fsm_out.psk_trigger = 1; if (fsm_in.sq) { next_state = FSM_OPEN2; } - else if (fsm_in.cw_done) { + else if (fsm_in.psk_done) { next_state = FSM_OISIF; } break; case FSM_BALISE_SPECIALE: fsm_out.tx_on = 1; - fsm_out.cw_frequency = 696; + fsm_out.msg_frequency = 696; fsm_out.cw_dit_duration = 70; // TODO read voltage if (fsm_in.wind_generator_ok) { - fsm_out.cw_msg = "HB9G U 10V5 73"; + fsm_out.msg = "HB9G U 10V5 73"; } else { - fsm_out.cw_msg = "HB9G U 10V5 #"; // The # is the SK digraph + fsm_out.msg = "HB9G U 10V5 #"; // The # is the SK digraph } fsm_out.cw_trigger = 1; @@ -327,23 +328,23 @@ void fsm_update() { case FSM_BALISE_COURTE: fsm_out.tx_on = 1; - fsm_out.cw_frequency = 696; + fsm_out.msg_frequency = 696; fsm_out.cw_dit_duration = 70; { int rand = random_bool() * 2 + random_bool(); if (rand == 0) { - fsm_out.cw_msg = "HB9G"; + fsm_out.msg = "HB9G"; } else if (rand == 1) { - fsm_out.cw_msg = "HB9G JN36BK"; + fsm_out.msg = "HB9G JN36BK"; } else if (rand == 2) { - fsm_out.cw_msg = "HB9G 1628M"; + fsm_out.msg = "HB9G 1628M"; } else { - fsm_out.cw_msg = "HB9G JN36BK 1628M"; + fsm_out.msg = "HB9G JN36BK 1628M"; } } fsm_out.cw_trigger = 1; diff --git a/src/fsm/fsm.h b/src/fsm/fsm.h index 110f6bf..49853b1 100644 --- a/src/fsm/fsm.h +++ b/src/fsm/fsm.h @@ -62,8 +62,9 @@ struct fsm_input_signals_t { int tone_1750; // Detect 1750Hz tone int sstv_mode; // The 1750Hz filter is disabled, permitting SSTV usage - /* Signals coming from CW generator */ + /* Signals coming from CW and PSK generator */ int cw_done; // The CW generator has finished transmitting the message + int psk_done; // The PSK generator has finished transmitting the message /* Signal coming from the standing wave ratio meter */ int swr_high; // We see a lot of return power @@ -77,11 +78,12 @@ struct fsm_output_signals_t { int tx_on; // Enable TX circuitry int modulation; // Enable repeater RX to TX modulation - /* Signals to the CW generator */ - const char* cw_msg; // The message to transmit - int cw_frequency; // What audio frequency for the CW message + /* Signals to the CW and PSK generator */ + const char* msg; // The message to transmit + int msg_frequency; // What audio frequency for the CW or PSK message int cw_dit_duration;// CW speed, dit duration in ms - int cw_trigger; // Set to true to trigger a transmission + int cw_trigger; // Set to true to trigger a CW transmission + int psk_trigger; // Set to true to trigger a PSK transmission }; // Initialise local structures diff --git a/src/fsm/main.c b/src/fsm/main.c index 0dc2ffc..0bd00ef 100644 --- a/src/fsm/main.c +++ b/src/fsm/main.c @@ -136,7 +136,7 @@ static void launcher_task(void *pvParameters) xTaskCreate( gps_monit_task, "TaskGPSMonit", - 6*configMINIMAL_STACK_SIZE, + 4*configMINIMAL_STACK_SIZE, (void*) NULL, tskIDLE_PRIORITY + 2UL, &task_handle); @@ -163,22 +163,28 @@ static void launcher_task(void *pvParameters) static void detect_button_press(void *pvParameters) { + int pin_high_count = 0; + const int pin_high_thresh = 10; while (1) { - if (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)>0) { - - while (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) > 0) { - vTaskDelay(100 / portTICK_RATE_MS); /* Button Debounce Delay */ + if (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == Bit_SET) { + if (pin_high_count < pin_high_thresh) { + pin_high_count++; } - - tm_trigger = 1; - - while (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 0) { - vTaskDelay(100 / portTICK_RATE_MS); /* Button Debounce Delay */ + } + else { + if (pin_high_count > 0) { + pin_high_count--; } + } + vTaskDelay(10 / portTICK_RATE_MS); /* Debounce Delay */ + + if (pin_high_count == pin_high_thresh) { + tm_trigger = 1; + } + else if (pin_high_count == 0) { tm_trigger = 0; } - taskYIELD(); } } @@ -216,15 +222,11 @@ static void audio_callback(void* context, int select_buffer) } -static char psk31_msg[256]; static struct gps_time_s gps_time; static void gps_monit_task(void *pvParameters) { GPIO_SetBits(GPIOD, GPIOD_BOARD_LED_BLUE); - int trigger_psk31 = 0; - int last_trigger_psk31 = 0; - while (1) { if (gps_locked()) { @@ -236,33 +238,9 @@ static void gps_monit_task(void *pvParameters) else { GPIO_ResetBits(GPIOD, GPIOD_BOARD_LED_BLUE); } - - if (gps_time.sec == 0 || gps_time.sec == 20 || gps_time.sec == 40) { - trigger_psk31 = 1; - } - else { - trigger_psk31 = 0; - } - - } - - if (trigger_psk31 && !last_trigger_psk31) { - snprintf(psk31_msg, 255, "Hello PSK31\nDate: %4d-%02d-%02d %02d:%02d:%02d\n73!", - gps_time.year, gps_time.month, gps_time.day, - gps_time.hour, gps_time.min, gps_time.sec); - - psk31_push_message(psk31_msg, 400); } - last_trigger_psk31 = trigger_psk31; - if (psk31_busy()) { - GPIO_SetBits(GPIOD, GPIOD_BOARD_LED_GREEN); - } - else { - GPIO_ResetBits(GPIOD, GPIOD_BOARD_LED_GREEN); - } - - taskYIELD(); + vTaskDelay(100 / portTICK_RATE_MS); } } @@ -270,6 +248,7 @@ static struct fsm_input_signals_t fsm_input; static void exercise_fsm(void *pvParameters) { int cw_last_trigger = 0; + int psk31_last_trigger = 0; int last_tm_trigger = 0; fsm_input.humidity = 0; @@ -278,11 +257,14 @@ static void exercise_fsm(void *pvParameters) fsm_input.sstv_mode = 0; fsm_input.wind_generator_ok = 1; while (1) { + vTaskDelay(10 / portTICK_RATE_MS); + pio_set_fsm_signals(&fsm_input); fsm_input.start_tm = (tm_trigger == 1 && last_tm_trigger == 0) ? 1 : 0; last_tm_trigger = tm_trigger; fsm_input.sq = fsm_input.carrier; // TODO clarify + fsm_input.cw_done = !cw_busy(); if (fsm_input.cw_done) { @@ -292,6 +274,16 @@ static void exercise_fsm(void *pvParameters) GPIO_SetBits(GPIOD, GPIOD_BOARD_LED_ORANGE); } + fsm_input.psk_done = !psk31_busy(); + + if (fsm_input.psk_done) { + GPIO_SetBits(GPIOD, GPIOD_BOARD_LED_GREEN); + } + else { + GPIO_ResetBits(GPIOD, GPIOD_BOARD_LED_GREEN); + } + + fsm_update_inputs(&fsm_input); fsm_update(); @@ -304,10 +296,15 @@ static void exercise_fsm(void *pvParameters) // Add message to CW generator only on rising edge of trigger if (fsm_out.cw_trigger && !cw_last_trigger) { - cw_push_message(fsm_out.cw_msg, fsm_out.cw_dit_duration, fsm_out.cw_frequency); + cw_push_message(fsm_out.msg, fsm_out.cw_dit_duration, fsm_out.msg_frequency); } - cw_last_trigger = fsm_out.cw_trigger; + + // Same for PSK31 + if (fsm_out.psk_trigger && !psk31_last_trigger) { + psk31_push_message(fsm_out.msg, fsm_out.msg_frequency); + } + psk31_last_trigger = fsm_out.psk_trigger; } } |