|
@@ -28,11 +28,14 @@
|
|
#include "ax25_pad.h"
|
|
#include "ax25_pad.h"
|
|
#include "fcs_calc.h"
|
|
#include "fcs_calc.h"
|
|
|
|
|
|
|
|
+
|
|
#include "math.h"
|
|
#include "math.h"
|
|
|
|
|
|
#include "driver/timer.h"
|
|
#include "driver/timer.h"
|
|
#include "aprs_decoder.h"
|
|
#include "aprs_decoder.h"
|
|
|
|
+#include "kiss.h"
|
|
|
|
|
|
|
|
+#include "afsk_demodulator.h"
|
|
|
|
|
|
//#include "esp_dsp.h"
|
|
//#include "esp_dsp.h"
|
|
|
|
|
|
@@ -42,74 +45,17 @@ uint8_t APRS_TEST_PACKET[] = { 0x82, 0x98, 0x98, 0x40, 0x40, 0x40, 0xe0, 0x96, 0
|
|
0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x54, 0x65, 0x73, 0x74, 0x7b, 0x31, 0xad, 0xa1 };
|
|
0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x54, 0x65, 0x73, 0x74, 0x7b, 0x31, 0xad, 0xa1 };
|
|
|
|
|
|
RingbufHandle_t radio_tx_buf;
|
|
RingbufHandle_t radio_tx_buf;
|
|
|
|
+RingbufHandle_t radio_rx_buf;
|
|
|
|
+
|
|
SemaphoreHandle_t xRadioRXISRSemaphore;
|
|
SemaphoreHandle_t xRadioRXISRSemaphore;
|
|
SemaphoreHandle_t xRadioRXSemaphore;
|
|
SemaphoreHandle_t xRadioRXSemaphore;
|
|
SemaphoreHandle_t xRadioTXSemaphore;
|
|
SemaphoreHandle_t xRadioTXSemaphore;
|
|
|
|
+SemaphoreHandle_t xRadioMutex;
|
|
|
|
|
|
//RingbufHandle_t radio_rx_buf;
|
|
//RingbufHandle_t radio_rx_buf;
|
|
|
|
|
|
extern int8_t EXTERNAL_DATA;
|
|
extern int8_t EXTERNAL_DATA;
|
|
-
|
|
|
|
-#define WINDOW_SIZE 7
|
|
|
|
-#define SAMPLEFREQUENCY 6000
|
|
|
|
-
|
|
|
|
-int window[WINDOW_SIZE];
|
|
|
|
-int lpf_window[WINDOW_SIZE];
|
|
|
|
-
|
|
|
|
-double goertzelFilter(int samples[], double freq, int N)
|
|
|
|
-{
|
|
|
|
- double s_prev = 0.0;
|
|
|
|
- double s_prev2 = 0.0;
|
|
|
|
- double coeff,normalizedfreq,power,s;
|
|
|
|
- int i;
|
|
|
|
- normalizedfreq = freq / SAMPLEFREQUENCY;
|
|
|
|
- coeff = 2*cos(2*M_PI*normalizedfreq);
|
|
|
|
- for (i=0; i<N; i++) {
|
|
|
|
- s = samples[i] + coeff * s_prev - s_prev2;
|
|
|
|
- s_prev2 = s_prev;
|
|
|
|
- s_prev = s;
|
|
|
|
- }
|
|
|
|
- power = s_prev2*s_prev2+s_prev*s_prev-coeff*s_prev*s_prev2;
|
|
|
|
- return power;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-//double calculate_symbols_energy(int samples[], int N)
|
|
|
|
-//{
|
|
|
|
-// double E_s1, E_s2;
|
|
|
|
-// E_s1 = goertzelFilter(samples, 1200, N);
|
|
|
|
-// E_s2 = goertzelFilter(samples, 2200, N);
|
|
|
|
-// return (E_s1 - E_s2);
|
|
|
|
-//}
|
|
|
|
-
|
|
|
|
-void window_init(void)
|
|
|
|
-{
|
|
|
|
- for(int i=0;i<WINDOW_SIZE;i++)
|
|
|
|
- {
|
|
|
|
- window[i] = 0;
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void window_add(int sample)
|
|
|
|
-{
|
|
|
|
- for(int i=0;i<(WINDOW_SIZE-1);i++)
|
|
|
|
- {
|
|
|
|
- window[(WINDOW_SIZE-1)-i] = window[(WINDOW_SIZE-2)-i];
|
|
|
|
- }
|
|
|
|
- window[0] = sample;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-int* window_get(void)
|
|
|
|
-{
|
|
|
|
- return window;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-int window_get_size(void)
|
|
|
|
-{
|
|
|
|
- return WINDOW_SIZE;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-// APRS Decoder
|
|
|
|
-
|
|
|
|
|
|
+extern decoder_varibles_t v;
|
|
|
|
|
|
// Timer Functions
|
|
// Timer Functions
|
|
void IRAM_ATTR rx_timer_isr(void *para)
|
|
void IRAM_ATTR rx_timer_isr(void *para)
|
|
@@ -139,8 +85,7 @@ void IRAM_ATTR rx_timer_isr(void *para)
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-// The TX Task should have the highest
|
|
|
|
-void TX_Task(void *pvParameters)
|
|
|
|
|
|
+void Radio_Task(void *pvParameters)
|
|
{
|
|
{
|
|
size_t p_size;
|
|
size_t p_size;
|
|
|
|
|
|
@@ -212,30 +157,89 @@ void TX_Task(void *pvParameters)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
// Phase Locked Loop (PLL) Parameters
|
|
// Phase Locked Loop (PLL) Parameters
|
|
#define BAUD_RATE (1200)
|
|
#define BAUD_RATE (1200)
|
|
#define SAMPLES_BIT (SAMPLEFREQUENCY / BAUD_RATE)
|
|
#define SAMPLES_BIT (SAMPLEFREQUENCY / BAUD_RATE)
|
|
#define D_PLL_INC (SAMPLES_BIT * 1)
|
|
#define D_PLL_INC (SAMPLES_BIT * 1)
|
|
#define D_PLL_MAX (D_PLL_INC * SAMPLES_BIT *1)
|
|
#define D_PLL_MAX (D_PLL_INC * SAMPLES_BIT *1)
|
|
-#define D_PLL_MARGIN (1)
|
|
|
|
|
|
+#define D_PLL_MARGIN (dpll_margin)
|
|
|
|
|
|
uint8_t aprs_buf[256];
|
|
uint8_t aprs_buf[256];
|
|
|
|
|
|
-void RX_Task(void *pvParameters)
|
|
|
|
|
|
+void dsps_biquad_gen_lpf_f32(float *coeffs, float f, float qFactor)
|
|
{
|
|
{
|
|
- // debugging variables
|
|
|
|
- uint8_t toggle = 0;
|
|
|
|
- uint8_t count = 0;
|
|
|
|
|
|
+ if (qFactor <= 0.0001) {
|
|
|
|
+ qFactor = 0.0001;
|
|
|
|
+ }
|
|
|
|
+ float Fs = 1;
|
|
|
|
+
|
|
|
|
+ float w0 = 2 * M_PI * f / Fs;
|
|
|
|
+ float c = cosf(w0);
|
|
|
|
+ float s = sinf(w0);
|
|
|
|
+ float alpha = s / (2 * qFactor);
|
|
|
|
+
|
|
|
|
+ float b0 = (1 - c) / 2;
|
|
|
|
+ float b1 = 1 - c;
|
|
|
|
+ float b2 = b0;
|
|
|
|
+ float a0 = 1 + alpha;
|
|
|
|
+ float a1 = -2 * c;
|
|
|
|
+ float a2 = 1 - alpha;
|
|
|
|
+
|
|
|
|
+ coeffs[0] = b0 / a0;
|
|
|
|
+ coeffs[1] = b1 / a0;
|
|
|
|
+ coeffs[2] = b2 / a0;
|
|
|
|
+ coeffs[3] = a1 / a0;
|
|
|
|
+ coeffs[4] = a2 / a0;
|
|
|
|
+ return;
|
|
|
|
+}
|
|
|
|
|
|
|
|
+void dsps_biquad_f32_ansi(const float *input, float *output, int len, float *coef, float *w)
|
|
|
|
+{
|
|
|
|
+ for (int i = 0 ; i < len ; i++) {
|
|
|
|
+ float d0 = input[i] - coef[3] * w[0] - coef[4] * w[1];
|
|
|
|
+ output[i] = coef[0] * d0 + coef[1] * w[0] + coef[2] * w[1];
|
|
|
|
+ w[1] = w[0];
|
|
|
|
+ w[0] = d0;
|
|
|
|
+ }
|
|
|
|
+ return;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+float lpf_coef[5];
|
|
|
|
+float lpf_delay[2];
|
|
|
|
+
|
|
|
|
+void lpf_init(void)
|
|
|
|
+{
|
|
|
|
+ // generate filter coef
|
|
|
|
+ dsps_biquad_gen_lpf_f32(lpf_coef, 0.1999, 1);
|
|
|
|
+
|
|
|
|
+ // setup delay line and lpf_input window
|
|
|
|
+ int i;
|
|
|
|
+ for(i=0;i<sizeof(lpf_delay)/sizeof(float);i++)
|
|
|
|
+ {
|
|
|
|
+ lpf_delay[i] = 0;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+float lpf_baseband(float input)
|
|
|
|
+{
|
|
|
|
+ float output;
|
|
|
|
+ dsps_biquad_f32_ansi(&input, &output, 1, lpf_coef, lpf_delay);
|
|
|
|
+ return output;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+void RX_DSP_Task(void *pvParameters)
|
|
|
|
+{
|
|
// algorithm variables
|
|
// algorithm variables
|
|
- double E_s1=0, E_s2=0;
|
|
|
|
|
|
+ volatile float E_s1=0, E_s2=0, lpf_output;
|
|
uint8_t raw_bit=0, previous_raw_bit=0;
|
|
uint8_t raw_bit=0, previous_raw_bit=0;
|
|
- int32_t d_pll=0, dpll_error=0, err_div=2;
|
|
|
|
- int lpf_input = 0;
|
|
|
|
- int lpf_output = 0;
|
|
|
|
|
|
+ volatile int32_t d_pll=0, dpll_error=0, err_div=0, dpll_margin = 1;
|
|
|
|
+ uint32_t success = 0;
|
|
|
|
|
|
aprs_decoder_init();
|
|
aprs_decoder_init();
|
|
frame_buffer_init(aprs_buf, 256);
|
|
frame_buffer_init(aprs_buf, 256);
|
|
|
|
+ lpf_init();
|
|
|
|
|
|
// Sampling Semaphore
|
|
// Sampling Semaphore
|
|
xRadioRXISRSemaphore = xSemaphoreCreateBinary();
|
|
xRadioRXISRSemaphore = xSemaphoreCreateBinary();
|
|
@@ -246,53 +250,64 @@ void RX_Task(void *pvParameters)
|
|
{
|
|
{
|
|
|
|
|
|
//enable_debug_IO(DEBUG_0);
|
|
//enable_debug_IO(DEBUG_0);
|
|
- EXTERNAL_DATA = (int)cc1200_radio_read_CFM();
|
|
|
|
|
|
+ if (xSemaphoreTake(xRadioMutex, 0) == pdTRUE)
|
|
|
|
+ {
|
|
|
|
+ //disable_debug_IO(DEBUG_0);
|
|
|
|
+ //enable_debug_IO(DEBUG_0);
|
|
|
|
+ EXTERNAL_DATA = (int)cc1200_radio_read_CFM();
|
|
|
|
+ xSemaphoreGive(xRadioMutex);
|
|
|
|
+ //disable_debug_IO(DEBUG_0);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ ESP_LOGE("Radio", "Sampling Failure");
|
|
|
|
+ }
|
|
//disable_debug_IO(DEBUG_0);
|
|
//disable_debug_IO(DEBUG_0);
|
|
//enable_debug_IO(DEBUG_0);
|
|
//enable_debug_IO(DEBUG_0);
|
|
- //lpf_output += (50000 * (((int)EXTERNAL_DATA) - lpf_output)) / 100000;
|
|
|
|
- window_add((int) EXTERNAL_DATA);
|
|
|
|
- E_s1 = goertzelFilter(window, 1200, WINDOW_SIZE);
|
|
|
|
- E_s2 = goertzelFilter(window, 2200, WINDOW_SIZE);
|
|
|
|
|
|
|
|
- if (E_s1 > E_s2)
|
|
|
|
|
|
+ window_add(EXTERNAL_DATA);
|
|
|
|
+ int8_t *window = window_get();
|
|
|
|
+ E_s1 = goertzelFilter2(window, 1200, WINDOW_SIZE);
|
|
|
|
+ E_s2 = goertzelFilter2(window, 2200, WINDOW_SIZE);
|
|
|
|
+ lpf_output = lpf_baseband((E_s1 - E_s2));
|
|
|
|
+
|
|
|
|
+ if (lpf_output > 0)
|
|
{
|
|
{
|
|
raw_bit = 1;
|
|
raw_bit = 1;
|
|
enable_debug_IO(DEBUG_2);
|
|
enable_debug_IO(DEBUG_2);
|
|
- enable_debug_IO(DEBUG_0);
|
|
|
|
|
|
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
raw_bit = 0;
|
|
raw_bit = 0;
|
|
disable_debug_IO(DEBUG_2);
|
|
disable_debug_IO(DEBUG_2);
|
|
- disable_debug_IO(DEBUG_0);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
//disable_debug_IO(DEBUG_0);
|
|
//disable_debug_IO(DEBUG_0);
|
|
//enable_debug_IO(DEBUG_0);
|
|
//enable_debug_IO(DEBUG_0);
|
|
|
|
+
|
|
// DPLL for sampling
|
|
// DPLL for sampling
|
|
if (raw_bit != previous_raw_bit)
|
|
if (raw_bit != previous_raw_bit)
|
|
{
|
|
{
|
|
dpll_error = d_pll - (D_PLL_MAX / 2);
|
|
dpll_error = d_pll - (D_PLL_MAX / 2);
|
|
if (dpll_error > (D_PLL_MARGIN))
|
|
if (dpll_error > (D_PLL_MARGIN))
|
|
{
|
|
{
|
|
- d_pll -= get_rx_status() ? D_PLL_MARGIN:
|
|
|
|
- (dpll_error + err_div / 2) / err_div;
|
|
|
|
|
|
+ d_pll -= get_rx_status() ? D_PLL_MARGIN:
|
|
|
|
+ (err_div + dpll_error);//(dpll_error + err_div / 2) / err_div;
|
|
}
|
|
}
|
|
else if (dpll_error < (-D_PLL_MARGIN))
|
|
else if (dpll_error < (-D_PLL_MARGIN))
|
|
{
|
|
{
|
|
- d_pll += get_rx_status() ? D_PLL_MARGIN:
|
|
|
|
- (dpll_error + err_div / 2) / err_div;
|
|
|
|
|
|
+ d_pll += get_rx_status() ? D_PLL_MARGIN:
|
|
|
|
+ -(err_div + dpll_error); //(dpll_error + err_div / 2) / err_div;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
d_pll += D_PLL_INC;
|
|
d_pll += D_PLL_INC;
|
|
|
|
|
|
- disable_debug_IO(DEBUG_3);
|
|
|
|
if (d_pll >= D_PLL_MAX)
|
|
if (d_pll >= D_PLL_MAX)
|
|
{
|
|
{
|
|
// set clock debug I/O high
|
|
// set clock debug I/O high
|
|
- enable_debug_IO(DEBUG_3);
|
|
|
|
|
|
+ enable_debug_IO(DEBUG_0);
|
|
|
|
|
|
// feed bit to aprs decoder algorithm
|
|
// feed bit to aprs decoder algorithm
|
|
switch(aprs_decoder_feed_bit(raw_bit))
|
|
switch(aprs_decoder_feed_bit(raw_bit))
|
|
@@ -300,9 +315,10 @@ void RX_Task(void *pvParameters)
|
|
case NORMAL:
|
|
case NORMAL:
|
|
break;
|
|
break;
|
|
case FRAME_DECODED:
|
|
case FRAME_DECODED:
|
|
- ESP_LOGI("APRS RX", "AX.25 Frame Received");
|
|
|
|
|
|
+ ESP_LOGI("APRS RX", "AX.25 Frame Received [%d]", success++);
|
|
// send via KISS TNC to over BLE SPP
|
|
// send via KISS TNC to over BLE SPP
|
|
//ESP_LOG_BUFFER_HEXDUMP("APRS RX", aprs_buf, 100, ESP_LOG_INFO);
|
|
//ESP_LOG_BUFFER_HEXDUMP("APRS RX", aprs_buf, 100, ESP_LOG_INFO);
|
|
|
|
+ kiss_transmit(KISS_DATAFRAME, v.frame_buffer, v.frame_len);
|
|
break;
|
|
break;
|
|
case ERROR_FCS_MISMATCH:
|
|
case ERROR_FCS_MISMATCH:
|
|
ESP_LOGV("APRS RX", "AX.25 FCS Error\n");
|
|
ESP_LOGV("APRS RX", "AX.25 FCS Error\n");
|
|
@@ -317,22 +333,25 @@ void RX_Task(void *pvParameters)
|
|
else
|
|
else
|
|
{
|
|
{
|
|
// set clock debug I/O low
|
|
// set clock debug I/O low
|
|
|
|
+ disable_debug_IO(DEBUG_0);
|
|
}
|
|
}
|
|
previous_raw_bit = raw_bit;
|
|
previous_raw_bit = raw_bit;
|
|
- //disable_debug_IO(DEBUG_0);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
void radio_init()
|
|
void radio_init()
|
|
{
|
|
{
|
|
// Setup Task Communications
|
|
// Setup Task Communications
|
|
radio_tx_buf = xRingbufferCreate(1028, RINGBUF_TYPE_NOSPLIT);
|
|
radio_tx_buf = xRingbufferCreate(1028, RINGBUF_TYPE_NOSPLIT);
|
|
|
|
+ radio_rx_buf = xRingbufferCreate(1028, RINGBUF_TYPE_NOSPLIT);
|
|
xRadioRXSemaphore = xSemaphoreCreateBinary();
|
|
xRadioRXSemaphore = xSemaphoreCreateBinary();
|
|
xRadioTXSemaphore = xSemaphoreCreateBinary();
|
|
xRadioTXSemaphore = xSemaphoreCreateBinary();
|
|
|
|
+ xRadioMutex = xSemaphoreCreateMutex();
|
|
|
|
|
|
- xTaskCreatePinnedToCore(TX_Task, "TX Task", 1024*4, 0, 2, NULL, 1);
|
|
|
|
- xTaskCreatePinnedToCore(RX_Task, "RX Task", 1024*4, 0, 1, NULL, 1);
|
|
|
|
|
|
+ xTaskCreatePinnedToCore(Radio_Task, "Radio Controller", 1024*4, 0, 2, NULL, 1);
|
|
|
|
+ xTaskCreatePinnedToCore(RX_DSP_Task, "Radio DSP", 1024*4, 0, 1, NULL, 1);
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
@@ -352,9 +371,12 @@ void IRAM_ATTR app_main()
|
|
// Radio Task Initialize
|
|
// Radio Task Initialize
|
|
radio_init();
|
|
radio_init();
|
|
|
|
|
|
- // Setup Kiss Decoder and Encoder
|
|
|
|
|
|
+ // AFSK Decoder and Encoder
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // Kiss Decoder and Encoder
|
|
kiss_init();
|
|
kiss_init();
|
|
|
|
|
|
- // Initalize BLE
|
|
|
|
|
|
+ // BLE and SPP
|
|
bt_spp_init();
|
|
bt_spp_init();
|
|
}
|
|
}
|