aboutsummaryrefslogtreecommitdiffstats
path: root/src/fsm/psk31.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fsm/psk31.c')
-rw-r--r--src/fsm/psk31.c194
1 files changed, 170 insertions, 24 deletions
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