aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/fsm/cw.c87
-rw-r--r--src/fsm/fsm.c51
-rw-r--r--src/fsm/fsm.h12
-rw-r--r--src/fsm/main.c81
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;
}
}