aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/fsm/cw.c66
-rw-r--r--src/fsm/cw.h68
-rw-r--r--src/fsm/gps.c2
-rw-r--r--src/fsm/main.c43
-rw-r--r--src/fsm/psk31.c194
-rw-r--r--src/fsm/psk31.h136
6 files changed, 277 insertions, 232 deletions
diff --git a/src/fsm/cw.c b/src/fsm/cw.c
index 96c510a..ee0ba77 100644
--- a/src/fsm/cw.c
+++ b/src/fsm/cw.c
@@ -47,6 +47,69 @@
#define ON_BUFFER_SIZE 1024
+const uint8_t cw_mapping[60] = { // {{{
+ // Read bits from right to left
+
+ 0b110101, //+ ASCII 43
+ 0b110101, //, ASCII 44
+ 0b1011110, //- ASCII 45
+
+ 0b1010101, //., ASCII 46
+ 0b110110, // / ASCII 47
+
+ 0b100000, // 0, ASCII 48
+ 0b100001, // 1
+ 0b100011,
+ 0b100111,
+ 0b101111,
+ 0b111111,
+ 0b111110,
+ 0b111100,
+ 0b111000,
+ 0b110000, // 9, ASCII 57
+
+ // The following are mostly invalid, but
+ // required to fill the gap in ASCII between
+ // numerals and capital letters
+ 0b10, // :
+ 0b10, // ;
+ 0b10, // <
+ 0b10, // =
+ 0b10, // >
+ 0b1110011, // ?
+ 0b1101001, //@
+
+ 0b101, // A ASCII 65
+ 0b11110,
+ 0b11010,
+ 0b1110,
+ 0b11,
+ 0b11011,
+ 0b1100,
+ 0b11111,
+ 0b111,
+ 0b10001,
+ 0b1010,
+ 0b11101,
+ 0b100, //M
+ 0b110,
+ 0b1000,
+ 0b11001,
+ 0b10100,
+ 0b1101,
+ 0b1111,
+ 0b10,
+ 0b1011,
+ 0b10111,
+ 0b1001,
+ 0b10110,
+ 0b10010,
+ 0b11100, // Z
+
+ 0b101010, //Start, ASCII [
+ 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
@@ -173,10 +236,9 @@ 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 void cw_task(void *pvParameters)
{
- struct cw_out_message_s cw_fill_msg_current;
-
float nco_phase = 0.0f;
float ampl = 0.0f;
diff --git a/src/fsm/cw.h b/src/fsm/cw.h
index 3c09441..0cbb29c 100644
--- a/src/fsm/cw.h
+++ b/src/fsm/cw.h
@@ -22,6 +22,9 @@
* SOFTWARE.
*/
+#ifndef __CW_H_
+#define __CW_H_
+
#include <stdint.h>
#include <stddef.h>
@@ -37,69 +40,8 @@ void cw_push_message(const char* text, int dit_duration, int frequency);
// Write the waveform into the buffer (stereo)
size_t cw_fill_buffer(int16_t *buf, size_t bufsize);
-// Return 1 if the CW generator has completed transmission
+// Return 1 if the CW generator is running
int cw_busy(void);
-const uint8_t cw_mapping[60] = { // {{{
- // Read bits from right to left
-
- 0b110101, //+ ASCII 43
- 0b110101, //, ASCII 44
- 0b1011110, //- ASCII 45
-
- 0b1010101, //., ASCII 46
- 0b110110, // / ASCII 47
-
- 0b100000, // 0, ASCII 48
- 0b100001, // 1
- 0b100011,
- 0b100111,
- 0b101111,
- 0b111111,
- 0b111110,
- 0b111100,
- 0b111000,
- 0b110000, // 9, ASCII 57
-
- // The following are mostly invalid, but
- // required to fill the gap in ASCII between
- // numerals and capital letters
- 0b10, // :
- 0b10, // ;
- 0b10, // <
- 0b10, // =
- 0b10, // >
- 0b1110011, // ?
- 0b1101001, //@
-
- 0b101, // A ASCII 65
- 0b11110,
- 0b11010,
- 0b1110,
- 0b11,
- 0b11011,
- 0b1100,
- 0b11111,
- 0b111,
- 0b10001,
- 0b1010,
- 0b11101,
- 0b100, //M
- 0b110,
- 0b1000,
- 0b11001,
- 0b10100,
- 0b1101,
- 0b1111,
- 0b10,
- 0b1011,
- 0b10111,
- 0b1001,
- 0b10110,
- 0b10010,
- 0b11100, // Z
-
- 0b101010, //Start, ASCII [
- 0b1010111, // SK , ASCII '\'
-}; //}}}
+#endif // __CW_H_
diff --git a/src/fsm/gps.c b/src/fsm/gps.c
index 9ebd0b8..2b6d058 100644
--- a/src/fsm/gps.c
+++ b/src/fsm/gps.c
@@ -82,7 +82,7 @@ static void gps_task(void *pvParameters)
if (minmea_parse_rmc(&frame, rxbuf)) {
xSemaphoreTake(timeutc_semaphore, portMAX_DELAY);
gps_timeutc_last_updated = xTaskGetTickCount();
- gps_timeutc.year = frame.date.year;
+ gps_timeutc.year = 2000 + frame.date.year;
gps_timeutc.month = frame.date.month;
gps_timeutc.day = frame.date.day;
gps_timeutc.hour = frame.time.hours;
diff --git a/src/fsm/main.c b/src/fsm/main.c
index 9ae21fa..0dc2ffc 100644
--- a/src/fsm/main.c
+++ b/src/fsm/main.c
@@ -35,6 +35,7 @@
#include "timers.h"
#include "semphr.h"
#include "cw.h"
+#include "psk31.h"
#include "pio.h"
#include "i2c.h"
#include "gps.h"
@@ -101,6 +102,7 @@ int main(void) {
static void launcher_task(void *pvParameters)
{
cw_init(16000);
+ psk31_init(16000);
pio_init();
i2c_init();
common_init();
@@ -134,7 +136,7 @@ static void launcher_task(void *pvParameters)
xTaskCreate(
gps_monit_task,
"TaskGPSMonit",
- 4*configMINIMAL_STACK_SIZE,
+ 6*configMINIMAL_STACK_SIZE,
(void*) NULL,
tskIDLE_PRIORITY + 2UL,
&task_handle);
@@ -161,8 +163,6 @@ static void launcher_task(void *pvParameters)
static void detect_button_press(void *pvParameters)
{
- GPIO_SetBits(GPIOD, GPIOD_BOARD_LED_GREEN);
-
while (1) {
if (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)>0) {
@@ -171,14 +171,12 @@ static void detect_button_press(void *pvParameters)
}
tm_trigger = 1;
- GPIO_SetBits(GPIOD, GPIOD_BOARD_LED_GREEN);
while (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 0) {
vTaskDelay(100 / portTICK_RATE_MS); /* Button Debounce Delay */
}
tm_trigger = 0;
- GPIO_ResetBits(GPIOD, GPIOD_BOARD_LED_GREEN);
}
taskYIELD();
}
@@ -200,7 +198,11 @@ static void audio_callback(void* context, int select_buffer)
select_buffer = 0;
}
- size_t samples_len = cw_fill_buffer(samples, AUDIO_BUF_LEN);
+ size_t samples_len = psk31_fill_buffer(samples, AUDIO_BUF_LEN);
+
+ if (samples_len == 0) {
+ samples_len = cw_fill_buffer(samples, AUDIO_BUF_LEN);
+ }
if (samples_len == 0) {
for (int i = 0; i < AUDIO_BUF_LEN; i++) {
@@ -214,11 +216,15 @@ 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()) {
@@ -230,7 +236,32 @@ 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();
}
}
diff --git a/src/fsm/psk31.c b/src/fsm/psk31.c
index 6eafa53..a4e770a 100644
--- a/src/fsm/psk31.c
+++ b/src/fsm/psk31.c
@@ -53,12 +53,148 @@
* The psk31_fill_buffer() function can be called to fetch audio from the audio_queue
*/
-#define PSK31_MAX_MESSAGE_LEN 10240
+/*
+ * PSK31 Varicode
+ * http://aintel.bi.ehu.es/psk31.html
+ */
+const char *psk31_varicode[] = { // {{{
+ "1010101011",
+ "1011011011",
+ "1011101101",
+ "1101110111",
+ "1011101011",
+ "1101011111",
+ "1011101111",
+ "1011111101",
+ "1011111111",
+ "11101111",
+ "11101",
+ "1101101111",
+ "1011011101",
+ "11111",
+ "1101110101",
+ "1110101011",
+ "1011110111",
+ "1011110101",
+ "1110101101",
+ "1110101111",
+ "1101011011",
+ "1101101011",
+ "1101101101",
+ "1101010111",
+ "1101111011",
+ "1101111101",
+ "1110110111",
+ "1101010101",
+ "1101011101",
+ "1110111011",
+ "1011111011",
+ "1101111111",
+ "1",
+ "111111111",
+ "101011111",
+ "111110101",
+ "111011011",
+ "1011010101",
+ "1010111011",
+ "101111111",
+ "11111011",
+ "11110111",
+ "101101111",
+ "111011111",
+ "1110101",
+ "110101",
+ "1010111",
+ "110101111",
+ "10110111",
+ "10111101",
+ "11101101",
+ "11111111",
+ "101110111",
+ "101011011",
+ "101101011",
+ "110101101",
+ "110101011",
+ "110110111",
+ "11110101",
+ "110111101",
+ "111101101",
+ "1010101",
+ "111010111",
+ "1010101111",
+ "1010111101",
+ "1111101",
+ "11101011",
+ "10101101",
+ "10110101",
+ "1110111",
+ "11011011",
+ "11111101",
+ "101010101",
+ "1111111",
+ "111111101",
+ "101111101",
+ "11010111",
+ "10111011",
+ "11011101",
+ "10101011",
+ "11010101",
+ "111011101",
+ "10101111",
+ "1101111",
+ "1101101",
+ "101010111",
+ "110110101",
+ "101011101",
+ "101110101",
+ "101111011",
+ "1010101101",
+ "111110111",
+ "111101111",
+ "111111011",
+ "1010111111",
+ "101101101",
+ "1011011111",
+ "1011",
+ "1011111",
+ "101111",
+ "101101",
+ "11",
+ "111101",
+ "1011011",
+ "101011",
+ "1101",
+ "111101011",
+ "10111111",
+ "11011",
+ "111011",
+ "1111",
+ "111",
+ "111111",
+ "110111111",
+ "10101",
+ "10111",
+ "101",
+ "110111",
+ "1111011",
+ "1101011",
+ "11011111",
+ "1011101",
+ "111010101",
+ "1010110111",
+ "110111011",
+ "1010110101",
+ "1011010111",
+ "1110110101",
+}; //}}}
+
+
+#define PSK31_MAX_MESSAGE_LEN 4096
#define PHASE_BUFFER_SIZE (20 + PSK31_MAX_MESSAGE_LEN + 20)
struct psk31_out_message_s {
- // Contains a sequence of ones and zeros corresponding to
- // the BPSK31 phase
+ // Contains a string sequence of '0' and '1' corresponding to
+ // the BPSK31 phase. Is terminated with '\0'
char phase_buffer[PHASE_BUFFER_SIZE];
size_t phase_buffer_end;
@@ -75,7 +211,7 @@ static int psk31_samplerate;
static int psk31_transmit_ongoing;
static void psk31_task(void *pvParameters);
-static void psk31_str_to_bits(const char* instr, char* outbits);
+static int psk31_str_to_bits(const char* instr, char* outbits);
void psk31_init(unsigned int samplerate)
@@ -83,20 +219,20 @@ void psk31_init(unsigned int samplerate)
psk31_samplerate = samplerate;
psk31_transmit_ongoing = 0;
- psk31_msg_queue = xQueueCreate(15, sizeof(struct psk31_out_message_s));
+ psk31_msg_queue = xQueueCreate(1, sizeof(struct psk31_out_message_s));
if (psk31_msg_queue == 0) {
while(1); /* fatal error */
}
- psk31_audio_queue = xQueueCreate(2, AUDIO_BUF_LEN * sizeof(int16_t));
+ psk31_audio_queue = xQueueCreate(1, AUDIO_BUF_LEN * sizeof(int16_t));
if (psk31_audio_queue == 0) {
while(1); /* fatal error */
}
xTaskCreate(
psk31_task,
- "TaskPSK31",
- 8*configMINIMAL_STACK_SIZE,
+ "TaskPSK",
+ 5*configMINIMAL_STACK_SIZE,
(void*) NULL,
tskIDLE_PRIORITY + 2UL,
NULL);
@@ -112,7 +248,7 @@ int psk31_push_message(const char* text, int frequency)
msg.phase_buffer_end = 0;
msg.freq = frequency;
- psk31_str_to_bits(text, msg.phase_buffer);
+ msg.phase_buffer_end = psk31_str_to_bits(text, msg.phase_buffer);
xQueueSendToBack(psk31_msg_queue, &msg, portMAX_DELAY);
@@ -120,16 +256,25 @@ int psk31_push_message(const char* text, int frequency)
}
// Write the waveform into the buffer (stereo)
-size_t psk31_fill_buffer(int16_t *buf, size_t bufsize);
+size_t psk31_fill_buffer(int16_t *buf, size_t bufsize)
+{
+ if (xQueueReceiveFromISR(psk31_audio_queue, buf, NULL)) {
+ return bufsize;
+ }
+ else {
+ return 0;
+ }
+}
-// Return 1 if the psk31 generator has completed transmission
-int psk31_busy(void);
+int psk31_busy(void)
+{
+ return psk31_transmit_ongoing;
+}
static int16_t psk31_audio_buf[AUDIO_BUF_LEN];
+static struct psk31_out_message_s psk31_fill_msg_current;
static void psk31_task(void *pvParameters)
{
- struct psk31_out_message_s psk31_fill_msg_current;
-
float nco_phase = 0.0f;
float ampl = 0.0f;
@@ -141,6 +286,8 @@ static void psk31_task(void *pvParameters)
psk31_transmit_ongoing = 1;
+ const float base_ampl = 20000.0f;
+
/* BPSK31 is at 31.25 symbols per second. */
const int samples_per_symbol = psk31_samplerate * 100 / 3125;
@@ -148,20 +295,17 @@ static void psk31_task(void *pvParameters)
const float omega = 2.0f * FLOAT_PI * psk31_fill_msg_current.freq /
(float)psk31_samplerate;
- int current_psk_phase = 0;
+ int current_psk_phase = 1;
for (int i = 0; i < psk31_fill_msg_current.phase_buffer_end; i++) {
for (int t = 0; t < samples_per_symbol; t++) {
int16_t s = 0;
- if (psk31_fill_msg_current.phase_buffer[i]) {
- ampl = 32000.0f;
+ if (psk31_fill_msg_current.phase_buffer[i] == '1') {
+ ampl = base_ampl;
}
else {
- ampl =
- (float)current_psk_phase *
- 32000.0f *
- arm_cos_f32(
+ ampl = base_ampl * arm_cos_f32(
FLOAT_PI*(float)t/(float)samples_per_symbol);
}
@@ -170,7 +314,8 @@ static void psk31_task(void *pvParameters)
nco_phase -= 2.0f * FLOAT_PI;
}
- s = ampl * arm_sin_f32(nco_phase);
+ s = ampl * arm_sin_f32(nco_phase +
+ (current_psk_phase == 1 ? 0.0f : FLOAT_PI));
if (buf_pos == AUDIO_BUF_LEN) {
xQueueSendToBack(psk31_audio_queue, &psk31_audio_buf, portMAX_DELAY);
@@ -187,7 +332,7 @@ static void psk31_task(void *pvParameters)
}
- if (! psk31_fill_msg_current.phase_buffer[i]) {
+ if (psk31_fill_msg_current.phase_buffer[i] == '0') {
current_psk_phase *= -1;
}
}
@@ -206,7 +351,7 @@ static void psk31_task(void *pvParameters)
* outstr must be at least size 20 + strlen(instr)*12 + 20 to accomodate
* the header and tail
*/
-static void psk31_str_to_bits(const char* instr, char* outbits)
+static int psk31_str_to_bits(const char* instr, char* outbits)
{
int i=0, j, k;
@@ -232,6 +377,7 @@ static void psk31_str_to_bits(const char* instr, char* outbits)
/* NULL terminate */
outbits[i] = 0;
+ return i;
}
#if 0
diff --git a/src/fsm/psk31.h b/src/fsm/psk31.h
index 3e47f4c..3f08ecf 100644
--- a/src/fsm/psk31.h
+++ b/src/fsm/psk31.h
@@ -44,141 +44,5 @@ size_t psk31_fill_buffer(int16_t *buf, size_t bufsize);
// Return 1 if the psk31 generator has completed transmission
int psk31_busy(void);
-
-/*
- * PSK31 Varicode
- * http://aintel.bi.ehu.es/psk31.html
- */
-const char *psk31_varicode[] = {
- "1010101011",
- "1011011011",
- "1011101101",
- "1101110111",
- "1011101011",
- "1101011111",
- "1011101111",
- "1011111101",
- "1011111111",
- "11101111",
- "11101",
- "1101101111",
- "1011011101",
- "11111",
- "1101110101",
- "1110101011",
- "1011110111",
- "1011110101",
- "1110101101",
- "1110101111",
- "1101011011",
- "1101101011",
- "1101101101",
- "1101010111",
- "1101111011",
- "1101111101",
- "1110110111",
- "1101010101",
- "1101011101",
- "1110111011",
- "1011111011",
- "1101111111",
- "1",
- "111111111",
- "101011111",
- "111110101",
- "111011011",
- "1011010101",
- "1010111011",
- "101111111",
- "11111011",
- "11110111",
- "101101111",
- "111011111",
- "1110101",
- "110101",
- "1010111",
- "110101111",
- "10110111",
- "10111101",
- "11101101",
- "11111111",
- "101110111",
- "101011011",
- "101101011",
- "110101101",
- "110101011",
- "110110111",
- "11110101",
- "110111101",
- "111101101",
- "1010101",
- "111010111",
- "1010101111",
- "1010111101",
- "1111101",
- "11101011",
- "10101101",
- "10110101",
- "1110111",
- "11011011",
- "11111101",
- "101010101",
- "1111111",
- "111111101",
- "101111101",
- "11010111",
- "10111011",
- "11011101",
- "10101011",
- "11010101",
- "111011101",
- "10101111",
- "1101111",
- "1101101",
- "101010111",
- "110110101",
- "101011101",
- "101110101",
- "101111011",
- "1010101101",
- "111110111",
- "111101111",
- "111111011",
- "1010111111",
- "101101101",
- "1011011111",
- "1011",
- "1011111",
- "101111",
- "101101",
- "11",
- "111101",
- "1011011",
- "101011",
- "1101",
- "111101011",
- "10111111",
- "11011",
- "111011",
- "1111",
- "111",
- "111111",
- "110111111",
- "10101",
- "10111",
- "101",
- "110111",
- "1111011",
- "1101011",
- "11011111",
- "1011101",
- "111010101",
- "1010110111",
- "110111011",
- "1010110101",
- "1011010111",
- "1110110101",
-};
-
#endif // __PSK_31_H_