Browse Source

refactored a crap ton....lots of testing required

curiousmuch 4 years ago
parent
commit
91fe0ce143

+ 5 - 5
components/aprs/afsk_modulator.c

@@ -16,11 +16,11 @@
 #define LUT_SIZE 256		// was 7 bits, but increase to 8 for more phase resolution...
 #define DAC_MAX 64			// cc1200 DAC is only 7 bits (+/- 64)
 
-/* Public Variables */
-float delta_phi_1, delta_phi_2;		// phase deltas for two tones used in AFSK modulation
-float phase = 0;					// current phase as AFSK modulator must be phase continous
-int32_t phase_i = 0;				// integer of phase which is used by LUT
-DRAM_ATTR int8_t LUT[LUT_SIZE];		// look up table used for tone generation
+/* Local Global Variables */
+static float delta_phi, delta_phi_1, delta_phi_2;		// phase deltas for two tones used in AFSK modulation
+static float phase = 0;					// current phase as AFSK modulator must be phase continous
+static int32_t phase_i = 0;				// integer of phase which is used by LUT
+static DRAM_ATTR int8_t LUT[LUT_SIZE];		// look up table used for tone generation
 
 /* Private Functions */
 // Returns the phase for the LUT based on the current symbol being

+ 47 - 20
components/aprs/aprs_decoder.c

@@ -7,11 +7,11 @@
 
 #include "aprs_decoder.h"
 
-/* Public Variables */
-decoder_varibles_t v;
+/* Local Global Variables */
+static decoder_varibles_t v;
 
 /* Private Functions */
-uint32_t fcs_calc(uint8_t *data, uint32_t len)
+static uint32_t fcs_calc(uint8_t *data, uint32_t len)
 {
 	uint32_t crc, aprs_polynomial, i, j, byte_lsb, crc_lsb;
 	crc = 0xFFFF;
@@ -32,13 +32,40 @@ uint32_t fcs_calc(uint8_t *data, uint32_t len)
 	return crc & 0xFFFF;
 }
 
-void frame_buffer_init(uint8_t *buf, uint32_t len)
+void ax25_buffer_init(uint8_t *buf, uint32_t len)
 {
 	v.frame_buffer = buf;
 	v.frame_buffer_len = len;
 }
 
-void aprs_decoder_reset(void)
+uint8_t get_rx_status(void)
+{
+	if (v.packet_rx)
+		return 1;
+	else
+		return 0;
+}
+
+uint8_t flag_found(void)
+{
+	if (v.flag_buffer == 0x7E)
+	{
+		return 1;
+	}
+	else
+	{
+		return 0;
+	}
+}
+
+/* Public Functions */
+
+uint8_t ax25_decoder_get_cs(void)
+{
+	return get_rx_status();
+}
+
+void ax25_decoder_reset(void)
 {
 	v.decoder_state = FLAG_SEARCH;
 	v.frame_buffer_index = 0;
@@ -55,24 +82,24 @@ void aprs_decoder_reset(void)
 	v.packet_rx = 0;
 }
 
-uint8_t get_rx_status(void)
+void ax25_decoder_init(uint8_t *frame_buffer, uint32_t frame_len)
 {
-	if (v.packet_rx)
-		return 1;
-	else
-		return 0;
+	// reset state-machine variables
+	ax25_decoder_reset();
+
+	// setup frame buffer
+	ax25_buffer_init(frame_buffer, frame_len);
 }
 
-uint8_t flag_found(void)
+uint32_t ax25_decoder_get_frame_len(void)
 {
-	if (v.flag_buffer == 0x7E)
-	{
-		return 1;
-	}
-	else
-	{
-		return 0;
-	}
+	// could we have a race condition?
+	return v.frame_len;
+}
+
+uint8_t * ax25_decoder_get_frame(void)
+{
+	return v.frame_buffer;
 }
 
 decoder_output_t ax25_decoder_feed_bit(uint8_t nrzi_bit)
@@ -254,7 +281,7 @@ decoder_output_t ax25_decoder_feed_bit(uint8_t nrzi_bit)
 	if (v.decoder_state == ABORT)
 	{
 		// re-initialize state machine
-		aprs_decoder_init();
+		ax25_decoder_reset();
 	}
 	return NORMAL;
 }

+ 6 - 3
components/aprs/aprs_encoder.c

@@ -13,11 +13,13 @@
 #include "esp_log.h"
 #include "sdkconfig.h"
 
+#include "aprs_encoder.h"
+
 /* Debugging Tag */
 #define ENC_TAG "AX.25 Encoder"
 
 /* Public Variables */
-ax25_enc_var_t enc_var = {.state = NOCONFIG};		// TODO: Should this be stored in DRAM?
+ax25_enc_var_t enc_var;		// TODO: Should this be stored in DRAM?
 ax25_enc_param_t enc_param;
 
 /* Private Functions */
@@ -47,7 +49,8 @@ void ax25_encoder_init(uint8_t tx_delay, uint8_t tx_tail)
 	enc_param.tx_delay = round(tx_delay * 1.5 + 1);	// calculate the number of
 	enc_param.tx_tail = round(tx_tail * 1.5 + 1);
 
-	enc_var.state = STOP;
+	//enc_var.state = STOP;
+	enc_var.status = STOP;
 }
 
 // feed frame to state machine
@@ -73,7 +76,7 @@ ax25_enc_status_t ax25_encoder_encode(uint8_t *frame, int32_t frame_len)
   	return enc_var.status;
 }
 
-ax25_enc_state_t ax25_encoder_get_status(void)
+ax25_enc_status_t ax25_encoder_get_status(void)
 {
 	return enc_var.status;
 }

+ 5 - 5
components/aprs/include/aprs_decoder.h

@@ -61,11 +61,11 @@ typedef struct {
 } decoder_varibles_t;
 
 /* Public Functions */
-uint8_t get_rx_status(void);
-void frame_buffer_init(uint8_t *buf, uint32_t len);
-void aprs_decoder_init(void);
-
-void ax25_decoder_init(uint8_t *frame_buffer, uint32_t frame_len)
+void ax25_decoder_init(uint8_t *frame_buffer, uint32_t frame_len);
+void ax25_decoder_reset(void);
+uint8_t ax25_decoder_get_cs(void);
+uint32_t ax25_decoder_get_frame_len(void);
+uint8_t * ax25_decoder_get_frame(void);
 decoder_output_t ax25_decoder_feed_bit(uint8_t nrzi_bit);
 
 #endif /* APRS_DECODER_H_ */

+ 22 - 19
components/aprs/include/aprs_encoder.h

@@ -11,6 +11,26 @@
 #include <stdint.h>
 
 /* Data Structures */
+
+typedef enum {
+	NOCONFIG = 0,
+	STOP,
+	READY,
+	ERROR,
+} ax25_enc_status_t;
+
+typedef struct {
+	uint8_t tx_delay;
+	uint8_t tx_tail;
+} ax25_enc_param_t;
+
+typedef enum {
+	PREAMBLE = 0,
+	FRAME,
+	TAIL,
+	DONE
+} ax25_enc_state_t;
+
 typedef struct {
 	uint8_t *frame;				// frame buffer ptr
 	uint32_t frame_len;			// frame buffer len
@@ -26,30 +46,13 @@ typedef struct {
 	ax25_enc_state_t state;		// state of the encoding state machine
 } ax25_enc_var_t;
 
-typedef struct {
-	uint8_t tx_delay;
-	uint8_t tx_tail;
-} ax25_enc_param_t;
-
-typedef enum {
-	NOCONFIG = 0,
-	STOP,
-	READY,
-	ERROR,
-} ax25_enc_status_t;
 
-typedef enum {
-	PREAMBLE = 0,
-	FRAME,
-	TAIL,
-	DONE
-} ax25_enc_state_t;
 
 /* Public Functions*/
-void ax25_encoder_init(uint8_t tx_delay , uint8_t tx_delay);
+void ax25_encoder_init(uint8_t tx_delay, uint8_t tx_tail);
 ax25_enc_status_t ax25_encoder_encode(uint8_t *frame, int32_t frame_len);
 uint8_t ax25_encoder_get_bit(void);
-ax25_enc_state_t ax25_encoder_get_status(void);
+ax25_enc_status_t ax25_encoder_get_status(void);
 
 
 #endif /* COMPONENTS_APRS_INCLUDE_APRS_ENCODER_H_ */

+ 7 - 13
components/kiss/include/kiss.h

@@ -12,7 +12,7 @@
 #define TNC_TAG "KISS"
 
 // Frame Buffer
-#define FRAME_BUFFER_SIZE 512
+#define FRAME_BUFFER_SIZE 1024
 
 // KISS Specific Characters
 #define KISS_FEND 	0xC0
@@ -40,18 +40,13 @@
 // SetHardware: Custom
 // Return: Exit Kiss
 
-typedef void (*tnc_cb_t)(uint8_t *, uint32_t);
+typedef void (*kiss_cb_t)(uint8_t *, uint32_t);
 
  typedef struct {
-	uint8_t tx_delay;
-	uint8_t persistence;
-	uint8_t slot_time;
-	uint8_t tx_tail;
-	uint8_t full_duplex;
-	uint32_t spp_handle;
-	tnc_cb_t rx_callback;
-	tnc_cb_t tx_callback;
-} tnc_settings_t;
+	uint8_t tnc_number;
+	kiss_cb_t rx_callback;
+	kiss_cb_t tx_callback;
+} kiss_settings_t;
 
 
 typedef enum {
@@ -85,8 +80,7 @@ typedef struct {
 
 /* Public Functions */
 void kiss_receive(uint8_t *data, uint16_t len);
-void kiss_init(void);
-void kiss_configure(void);
+void kiss_init(uint8_t tnc_number, kiss_cb_t tx_cb, kiss_cb_t rx_cb);
 void kiss_transmit(uint8_t type, uint8_t *data, uint32_t len);
 
 

+ 21 - 85
components/kiss/kiss.c

@@ -19,7 +19,7 @@
 
 kiss_buffer_t rx_buffer;
 kiss_buffer_t tx_buffer;
-tnc_settings_t tnc_settings;
+kiss_settings_t kiss_settings;
 
 void static kiss_clear_tx_buffer(void)
 {
@@ -46,6 +46,7 @@ void kiss_transmit(uint8_t type, uint8_t *data, uint32_t len)
 	uint32_t i;
 
 	// TODO: Cancel TX to BLE TX Buffer if overflow is detected
+	// TODO: Can we eliminate TX buffer and use BLE Buffer only?????
 
 	kiss_clear_tx_buffer();
 	kiss_append_tx_buffer(KISS_FEND);
@@ -71,9 +72,10 @@ void kiss_transmit(uint8_t type, uint8_t *data, uint32_t len)
 	}
 
 	kiss_append_tx_buffer(KISS_FEND);
-	bt_spp_tx(tx_buffer.buf, tx_buffer.index);
 
-	// send via BLE or feed to TX buffer
+	// activate callback function
+	kiss_settings.tx_callback(tx_buffer.buf, tx_buffer.index);
+
 }
 
 void kiss_clear_buffer(void)
@@ -95,108 +97,42 @@ void kiss_append_buffer(uint8_t chr)
 	rx_buffer.index = rx_buffer.index + 1;
 }
 
-extern RingbufHandle_t radio_tx_buf;
+//extern RingbufHandle_t radio_tx_buf;
 
 // Frame Format
 // [ Command Byte ][ Data ]
 void kiss_process_frame(void)
 {
-    uint8_t data_byte, tnc_number;
-    data_byte = rx_buffer.buf[0];
-    tnc_number = (data_byte >> 4) & 0x0F;	// TODO: Have KISS code respect TNC number
+	// minimum kiss frame is 2 bytes
+    if (rx_buffer.index < 1)
+    	return;
 
-	switch( data_byte ) {
-		case KISS_DATAFRAME: {
-			ESP_LOGI(TNC_TAG, "Received Data Frame - Length %d", (rx_buffer.index));
-			// unblock AX.25 code to process code
-			uint32_t fcs = fcs_calc(&rx_buffer.buf[1], rx_buffer.index-1);
-			rx_buffer.buf[rx_buffer.index] = fcs & 0xFF;
-			rx_buffer.buf[rx_buffer.index+1] = fcs>>8 & 0xFF;
-			xRingbufferSend(radio_tx_buf, &rx_buffer.buf[1], ((rx_buffer.index+1)*sizeof(uint8_t)), 10/portTICK_PERIOD_MS);
-			ESP_LOG_BUFFER_HEXDUMP(TNC_TAG, &rx_buffer.buf[1], rx_buffer.index+1, ESP_LOG_INFO);
-			//cc1200_radio_APRSTXPacket(rx_buffer.buf, (rx_buffer.index+2), tnc_settings.tx_delay, tnc_settings.tx_tail);
-			break;
-		}
-		case KISS_CMD_TXDELAY: {
-			ESP_LOGI(TNC_TAG, "Updated TX Delay");
-			tnc_settings.tx_delay = rx_buffer.buf[1];
-			break;
-		}
-		case KISS_CMD_P: {
-			ESP_LOGI(TNC_TAG, "Update Persistence");
-			tnc_settings.persistence = rx_buffer.buf[1];
-			break;
-		}
-		case KISS_CMD_SLOTTIME: {
-			ESP_LOGI(TNC_TAG, "Updated Slottime");
-			tnc_settings.slot_time = rx_buffer.buf[1];
-			break;
-		}
-		case KISS_CMD_TXTAIL: {
-			ESP_LOGI(TNC_TAG, "Updated TX Tail");
-			tnc_settings.tx_tail= rx_buffer.buf[1];
-			break;
-		}
-		case KISS_CMD_FULLDUPLEX: {
-			ESP_LOGI(TNC_TAG, "Updated Full/Half Duplex Setting");
-			tnc_settings.full_duplex = rx_buffer.buf[1];
-			break;
-		}
-//		case KISS_CMD_SETHARDWARE: {
-//			break;
-//		}
-//		case KISS_CMD_RETURN: {
-//			tnc_settings.tx_delay = rx_buffer.buff_ptr[1];
-//			break;
-//		}
-		default: {
-			// error
-			break;
-		}
-	}
-	kiss_clear_buffer();
-	return;
-}
+    uint8_t data_byte, tnc_number;
 
-void kiss_set_tnc_paramters(tnc_settings_t s)
-{
-		tnc_settings.tx_delay = s.tx_delay;
-		tnc_settings.persistence = s.persistence;
-		tnc_settings.slot_time = s.slot_time;
-		tnc_settings.tx_tail = s.tx_tail;
-		tnc_settings.full_duplex = s.full_duplex;
-//		tnc_settings.tnc_number = s.tnc_number;
-}
+    data_byte = rx_buffer.buf[0];
+    tnc_number = (data_byte >> 4) & 0x0F;
 
-void kiss_set_tx_cb(tnc_cb_t tx_cb)
-{
-	tnc_settings.tx_callback = tx_cb;
+    // confirm packet is for this device
+    if (tnc_number == kiss_settings.tnc_number)
+    	kiss_settings.rx_callback(rx_buffer.buf, rx_buffer.index);
 }
 
-void kiss_set_rx_cb(tnc_cb_t rx_cb)
-{
-	tnc_settings.rx_callback = rx_cb;
-}
 
 // TNC needs the ability to RX KISS frame, decode it, schedule it, and then send out via APRS or Arrow-Net
 // TNC needs the ability to switch to RX mode,
 
-void kiss_init(void)
+void kiss_init(uint8_t tnc_number, kiss_cb_t tx_cb, kiss_cb_t rx_cb)
 {
 	// TODO: make frame buffer dynamic
 	rx_buffer.max_len = FRAME_BUFFER_SIZE;
 	tx_buffer.max_len = FRAME_BUFFER_SIZE;
 
-	// TODO: Store / retrieve default TNC settings from flash?
-
-	// set default TNC settings
-	tnc_settings.tx_delay = 5;
-	tnc_settings.persistence = 63;
-	tnc_settings.slot_time = 10;
-	tnc_settings.tx_tail = 1;
-	tnc_settings.full_duplex = 0;
+	// set tnc number
+	kiss_settings.tnc_number = tnc_number;
 
-	// setup TNC task with queue
+	// set callback functions
+	kiss_settings.rx_callback = rx_cb;
+	kiss_settings.tx_callback = tx_cb;
 }
 
 // Decode KISS-TNC data from SPP Interface and combine until there is

+ 1 - 1
components/radio/cc1200.c

@@ -263,7 +263,7 @@ uint8_t IRAM_ATTR cc1200_radio_read_CFM(void)
 	return data;
 }
 
-void IRAM_ATTR cc1200_radio_write_CFM(uint8_t data)
+void IRAM_ATTR cc1200_radio_write_CFM(int8_t data)
 {
 	cc1200_spi_write_byte(CC120X_CFM_TX_DATA_IN, data);
 }

+ 4 - 2
components/radio/include/radio.h

@@ -27,6 +27,8 @@ typedef enum {
 typedef struct {
 	radio_config_t type;
 	radio_status_t status;
+	void (*rx_cb)(uint8_t *, uint32_t);
+	void (*tx_cb)(uint8_t *, uint32_t);
 } radio_param_t;
 
 typedef struct {
@@ -37,8 +39,8 @@ typedef struct {
 	uint32_t symbol1_freq;
 	uint8_t *rx_buf;
 	uint32_t rx_buf_len;
-	void *rx_cb;
-	void *tx_cb;
+	void (*rx_cb)(uint8_t *, uint32_t);
+	uint8_t cpu_core;
 } ax25_param_t;
 
 /* Public Functions */

+ 134 - 21
components/radio/radio.c

@@ -10,14 +10,18 @@
 #include <math.h>
 
 #include "freertos/FreeRTOS.h"
-#include "freertos/semphr.h"
 #include "freertos/task.h"
+#include "freertos/semphr.h"
 
 #include "sdkconfig.h"
 #include "esp_log.h"
 
+#include "driver/timer.h"
+
 #include "radio.h"
 #include "cc1200.h"
+#include "cc1200_protocol.h"
+
 #include "afsk_modulator.h"
 #include "afsk_demodulator.h"
 #include "aprs_decoder.h"
@@ -26,9 +30,9 @@
 /* Debugging Tag */
 #define RADIO_TAG "Radio"
 
-/* Public Variables */
-radio_param_t radio_param;				// radio configuraiton
-SemaphoreHandle_t xRadioSemaphore;		// semphore for sample timing
+/* Local Global Variables */
+static radio_param_t radio_param;				// radio configuraiton
+static SemaphoreHandle_t xRadioSemaphore;		// semphore for sample timing
 
 /* Private Functions */
 void IRAM_ATTR radio_timer_isr(void *param)
@@ -91,22 +95,45 @@ void timer_radio_stop(void)
 }
 
 /* HAL Layer */
+
+void radio_rx_task(void *para);
+
+void radio_idle(void)
+{
+	// disable all radio tasks
+	//vTaskSuspend(radio_rx_task);
+
+	// disable all radio timers
+	timer_radio_stop();
+
+	cc1200_radio_idle();
+	radio_param.status = RADIO_IDLE;
+}
+
 void radio_tx(void)
 {
+	if (radio_param.status != RADIO_IDLE)
+		radio_idle();
+
 	cc1200_radio_tx();
 	radio_param.status = RADIO_TX;
 }
 
 void radio_rx(void)
 {
+	if (radio_param.status != RADIO_IDLE)
+		radio_idle();
+
 	cc1200_radio_rx();
 	radio_param.status = RADIO_RX;
 }
 
-void radio_idle(void)
+int8_t radio_get_cs()
 {
-	cc1200_radio_idle();
-	radio_param.status = RADIO_IDLE;
+	if (radio_param.status != RADIO_RX)
+		return 0;
+	else
+		return ax25_decoder_get_cs();
 }
 
 void radio_init(radio_config_t type, void *settings)
@@ -118,7 +145,7 @@ void radio_init(radio_config_t type, void *settings)
 			radio_param.type = AX25;
 
 			// cast setting struct
-			ax25_param_t p = (ax25_param_t)settings;
+			ax25_param_t *p = (ax25_param_t *)settings;
 
 			// setup LUT for AFSK demodulator
 			afsk_mod_init(p->sample_rate, p->symbol0_freq, p->symbol1_freq);
@@ -129,22 +156,27 @@ void radio_init(radio_config_t type, void *settings)
 			// setup encoder for ax25
 			ax25_encoder_init(p->tx_delay, p->tx_tail);
 
+			// setup ax25 decoder
+			ax25_decoder_init(p->rx_buf, p->rx_buf_len);
+			radio_param.rx_cb = p->rx_cb;
+
 			// setup timer for TX / RX
 			timer_radio_init(p->sample_rate, radio_timer_isr);
 
-			// create task for sampling
-			// TODO: Reduce stack requirements?
-			// TODO: Should there be an option on which core the driver pins the task too>
-			xTaskCreatePinnedToCore(radio_rx_task, "AFSK Sample Task", 1024*4, 0, 1, NULL, 1);
-			// xTaskCreatePinnedToCore()
-			vTaskSuspend(radio_rx_task);
-
 			// configure CC1200
 			cc1200_radio_init(AX25_SETTINGS, sizeof(AX25_SETTINGS)/sizeof(cc1200_reg_settings_t));
 
 			// put chip to idle
 			radio_idle();
 
+			// task communication
+			xRadioSemaphore = xSemaphoreCreateBinary();
+
+			// create task for sampling
+			// TODO: Reduce stack requirements?
+			xTaskCreatePinnedToCore(radio_rx_task, "radio rx", 1024*4, 0, 1, NULL, p->cpu_core);
+			//vTaskSuspend(radio_rx_task);
+
 			break;
 		}
 		default: {
@@ -182,7 +214,7 @@ void radio_packet_tx(uint8_t *data, int32_t len, void *settings)
 			// start sampling timer
 			timer_radio_start();
 
-			while(ax25_encoder_get_status == READY)
+			while(ax25_encoder_get_status() == READY)
 			{
 				// TODO: Do we need to feed the WDT here?
 
@@ -205,7 +237,7 @@ void radio_packet_tx(uint8_t *data, int32_t len, void *settings)
 				}
 				else
 				{
-					ESP_LOGE(RADIO_TAG, "sample timeout error");
+					ESP_LOGE(RADIO_TAG, "sampling timeout error");
 					break;
 				}
 
@@ -223,13 +255,91 @@ void radio_packet_tx(uint8_t *data, int32_t len, void *settings)
 
 void radio_rx_task(void *para)
 {
-	// setup
+	// analog variables
+	int8_t cfm_value=0;
+
+	// demod variables
+	uint8_t raw_bit=0, prev_raw_bit=0;
+
+	// pll variables and settings
+	int32_t d_pll=0, dpll_error=0, err_div=0;
+
+	// TODO: The following group should be made user setable fed via the settings
+	const int32_t SAMPLE_FREQUENCY = 132000;
+	const int32_t BAUD_RATE = 1200;
+	const int32_t SAMPLES_BIT = SAMPLE_FREQUENCY / BAUD_RATE;
+
+
+	const int32_t D_PLL_INC = (SAMPLES_BIT * 1);
+	const int32_t D_PLL_MAX = (D_PLL_INC * SAMPLES_BIT * 1);
+	const int32_t D_PLL_MARGIN = 1;
+
+	// decoder variables
+	uint32_t success=0;
 
 	// task
 	while(1)
 	{
+		// block until semphore is given or there has been a timing error
+		if (xSemaphoreTake(xRadioSemaphore, portMAX_DELAY) == pdTRUE)
+		{
+			// read register analog value from radio
+			cfm_value = cc1200_radio_read_CFM();
+
+			// afsk demod
+			raw_bit = afsk_demod_add_sample(cfm_value);
+
+			// clock synchronizer for sampling
+			if (raw_bit != prev_raw_bit)
+			{
+				dpll_error = d_pll - (D_PLL_MAX / 2);
+				if (dpll_error > D_PLL_MARGIN)
+				{
+					d_pll -= ax25_decoder_get_cs() ? D_PLL_MARGIN:
+							(err_div + dpll_error); //(dpll_error + err_div / 2) / err_div;
+
+				}
+				else if (dpll_error < -D_PLL_MARGIN)
+				{
+					d_pll += ax25_decoder_get_cs() ? D_PLL_MARGIN :
+							-(err_div + dpll_error); // (dpll_error + err_div / 2) / err_div;
+				}
+
+			}
 
+			// increment clock
+			d_pll += D_PLL_INC;
 
+			// slice
+			if (d_pll >= D_PLL_MAX)
+			{
+				switch (ax25_decoder_feed_bit(raw_bit))
+				{
+					case NORMAL:
+						break;
+					case FRAME_DECODED:
+						ESP_LOGI("APRS RX", "AX.25 Frame Received [%d]", success++);
+						// send via KISS TNC to over BLE SPP
+						//ESP_LOG_BUFFER_HEXDUMP("APRS RX", aprs_buf, 100, ESP_LOG_INFO);
+						//kiss_transmit(KISS_DATAFRAME, v.frame_buffer, v.frame_len);
+						if (radio_param.rx_cb != NULL)
+							radio_param.rx_cb(ax25_decoder_get_frame(), ax25_decoder_get_frame_len());
+						break;
+					case ERROR_FCS_MISMATCH:
+						ESP_LOGV("APRS RX", "AX.25 FCS Error\n");
+						break;
+					default:
+						//printf("Weird Error\n");
+						break;
+				}
+				d_pll -= D_PLL_MAX;
+			}
+			prev_raw_bit = raw_bit;
+		}
+		else
+		{
+			ESP_LOGE(RADIO_TAG, "sampling timeout error");
+		}
 	}
 }
 
@@ -240,10 +350,14 @@ void radio_packet_rx(void *settings)
 	switch(radio_param.type)
 	{
 		case AX25: {
-			// setup sampling timer
+			// setup radio
+			radio_rx();
 
+			// setup sampling timer
+			timer_radio_start();
 
-			// un-suspend sampling task
+			// unsuspend task
+			vTaskResume(radio_rx_task); //??????? should this be top or bottom
 
 			break;
 		}
@@ -253,5 +367,4 @@ void radio_packet_rx(void *settings)
 		}
 
 	}
-	cc1200_radio_rx();
 }

+ 1 - 0
main/component.mk

@@ -2,3 +2,4 @@
 # "main" pseudo-component makefile.
 #
 # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
+

+ 146 - 322
main/main.c

@@ -10,374 +10,178 @@
  * TODO: Abstract includes to be nicer (#include aprs.h) for example
  * TODO: Isolate CC1200 functions from other parts / maybe integrate most of TX scheme into task.
  */
+
+/* Standard Includes */
 #include <stdio.h>
+
+/* ESP-IDF */
+#include "sdkconfig.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
 #include "freertos/semphr.h"
 #include "freertos/ringbuf.h"
-
-#include "driver/gpio.h"
-#include "sdkconfig.h"
-#include "esp_task_wdt.h"
-
-#include "cc1200.h"
-#include "cc1200_protocol.h"
-#include "board.h"
-
 #include "nvs.h"
 #include "nvs_flash.h"
 #include "esp_log.h"
-#include "esp_bt.h"
-#include "esp_bt_main.h"
-#include "esp_gap_bt_api.h"
-#include "esp_bt_device.h"
-#include "esp_spp_api.h"
-#include "bt_spp.h"
-
-#include "ax25_pad2.h"
-#include "ax25_pad.h"
-#include "fcs_calc.h"
 
 
-#include "math.h"
-
-#include "driver/timer.h"
-#include "aprs_decoder.h"
+/* Application Specific */
+#include "bt_spp.h"
+#include "board.h"
+#include "radio.h"
 #include "kiss.h"
+#include "fcs_calc.h"
 
-#include "afsk_demodulator.h"
-
-//#include "esp_dsp.h"
 
-RingbufHandle_t radio_tx_buf;
-RingbufHandle_t radio_rx_buf;
+/* Data Structures */
+typedef struct {
+	uint8_t tnc_number;
+	uint8_t tx_delay;
+	uint8_t P;
+	uint8_t slot_time;
+	uint8_t full_duplex;
+	uint8_t tx_tail;
+} tnc_settings_t;
 
-SemaphoreHandle_t xRadioRXISRSemaphore;
-SemaphoreHandle_t xRadioRXSemaphore;
-SemaphoreHandle_t xRadioTXSemaphore;
-SemaphoreHandle_t xRadioMutex;
+/* Public Variables */
+tnc_settings_t tnc_settings;
 
-//RingbufHandle_t radio_rx_buf;
+uint8_t ax25_rx_buf[1024];
+RingbufHandle_t ax25_tx_buf;
 
-extern int8_t EXTERNAL_DATA;
-extern decoder_varibles_t v;
+/* Functions and Main */
 
-// Timer Functions
-void IRAM_ATTR rx_timer_isr(void *para)
+/* Radio Callback Functions */
+// callback function for when radio rx'd AX25 packet
+// unblocks task on other core and packet to another buffer
+// so we can continue processing
+void radio_rx_ax25_cb(uint8_t *frame, uint32_t len)
 {
-
-    //GPIO.out_w1ts = (1 << DEBUG_0);
-	int timer_idx = (int) para;
-
-    /* Clear the interrupt
-         and update the alarm time for the timer with without reload */
-    TIMERG0.int_clr_timers.t0 = 1;
-
-    // after the alarm has been triggered
-    //  we need enable it again, so it is triggered the next time
-    TIMERG0.hw_timer[0].config.alarm_en = TIMER_ALARM_EN;
-
-	static BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-
-    xSemaphoreGiveFromISR(xRadioRXISRSemaphore, &xHigherPriorityTaskWoken);
-	if (xHigherPriorityTaskWoken == pdTRUE)
-	{
-		portYIELD_FROM_ISR( );
-	}
-
-	//GPIO.out_w1tc = (1 << DEBUG_0);
+	ESP_LOGV("AX25 CB", "We Here");
+	// unblock receive task on CPU0
 
 }
 
-void Radio_Task(void *pvParameters)
+/* KISS callback Functions */
+void kiss_tx_cb(uint8_t *frame, uint32_t len)
 {
-	size_t p_size;
-
-    // Setup Timer for TX Task
-	timer_config_t config;
-    config.divider = 2;
-    config.counter_dir = TIMER_COUNT_UP;
-    config.counter_en = TIMER_PAUSE;
-    config.alarm_en = TIMER_ALARM_EN;
-    config.intr_type = TIMER_INTR_LEVEL;
-    config.auto_reload = TIMER_AUTORELOAD_EN;
-    timer_init(TIMER_GROUP_0, TIMER_1, &config);
-    timer_set_counter_value(TIMER_GROUP_0, TIMER_1, 0x00000000ULL);
-    timer_set_alarm_value(TIMER_GROUP_0, TIMER_1, 3030);
-    timer_isr_register(TIMER_GROUP_0, TIMER_1, cc1200_aprs_tx_isr,
-    		(void *) TIMER_1, ESP_INTR_FLAG_IRAM, NULL);
-
-	// Setup Sampling Timer for RX Task
-	timer_config_t rx_config;
-	rx_config.divider = 2;
-	rx_config.counter_dir = TIMER_COUNT_UP;
-	rx_config.counter_en = TIMER_PAUSE;
-	rx_config.alarm_en = TIMER_ALARM_EN;
-	rx_config.intr_type = TIMER_INTR_LEVEL;
-	rx_config.auto_reload = TIMER_AUTORELOAD_EN;
-    timer_init(TIMER_GROUP_0, TIMER_0, &rx_config);
-    timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0x00000000ULL);
-    timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 3030);
-    timer_isr_register(TIMER_GROUP_0, TIMER_0, rx_timer_isr,
-    		(void *) TIMER_0, ESP_INTR_FLAG_IRAM, NULL);
-
-	// Initialize Radio
-	cc1200_radio_init(APRS_SETTINGS, sizeof(APRS_SETTINGS)/sizeof(cc1200_reg_settings_t));
-	cc1200_radio_frequency(144390000);
-
-
-	while(1)
-	{
-		// setup LEDs for RX mode
-		disable_red_led();
-		enable_green_led();
-		cc1200_radio_start_APRSRX();
-	    timer_enable_intr(TIMER_GROUP_0, TIMER_0);
-	    timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0x00000000ULL);
-	    timer_start(TIMER_GROUP_0, TIMER_0);
-
-
-		// block until packet is in queue
-		uint8_t *p = (uint8_t *)xRingbufferReceive(radio_tx_buf, &p_size, portMAX_DELAY);
-
-		// send packet
-		if (p != NULL)
-		{
-
-			// disable RX mode
-		    timer_disable_intr(TIMER_GROUP_0, TIMER_0);
-			timer_pause(TIMER_GROUP_0, TIMER_0);
-			cc1200_radio_stop_APRSRX();
-
-			// setup LEDs for TX mode
-			enable_red_led();
-			disable_green_led();
-
-			cc1200_radio_APRSTXPacket(p, p_size, 4, 1);
-
-			vRingbufferReturnItem(radio_tx_buf, (void *)p);
-
-		}
-	}
+	// send data to UART / via bluetooth
+	bt_spp_tx(frame, len);
 }
 
-
-// Phase Locked Loop (PLL) Parameters
-#define BAUD_RATE (1200)
-#define SAMPLES_BIT (SAMPLEFREQUENCY / BAUD_RATE)
-#define D_PLL_INC (SAMPLES_BIT * 1)
-#define D_PLL_MAX (D_PLL_INC * SAMPLES_BIT *1)
-#define D_PLL_MARGIN (dpll_margin)
-
-uint8_t aprs_buf[256];
-
-
-void dsps_biquad_gen_lpf_f32(float *coeffs, float f, float qFactor)
+void kiss_rx_cb(uint8_t *frame, uint32_t len)
 {
-    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_coef0[5];
-float lpf_coef1[5];
-float lpf_delay0[2];
-float lpf_delay1[2];
-
-void lpf_init(void)
-{
-	// generate filter coef
-	dsps_biquad_gen_lpf_f32(lpf_coef0, 0.10, 0.54119610);
-	dsps_biquad_gen_lpf_f32(lpf_coef1, 0.10, 1.3065630);
-
+	uint8_t data_byte;
+	data_byte = frame[0] & 0x0F;	// tnc_number information
 
-	// setup delay line and lpf_input window
-	int i;
-	for(i=0;i<2;i++)
+	// process dataframe
+	if (data_byte == KISS_DATAFRAME)
 	{
-		lpf_delay0[i] = 0;
-		lpf_delay1[i] = 0;
+		// feed packet to ring buffer
+		uint32_t fcs = fcs_calc(&frame[1], len-1);
+		frame[len] = fcs & 0xFF;
+		frame[len+1] = fcs>>8 & 0xFF;
+		xRingbufferSend(ax25_tx_buf, &frame[1], ((len+1)*sizeof(uint8_t)),10/portTICK_PERIOD_MS);
 	}
-}
-
-float lpf_baseband(float input)
-{
-	float output, temp;
-	dsps_biquad_f32_ansi(&input, &temp, 1, lpf_coef0, lpf_delay0);
-	dsps_biquad_f32_ansi(&temp, &output, 1, lpf_coef1, lpf_delay1);
+	else // assume command
+	{
+		switch(data_byte)
+		{
+			case KISS_CMD_TXDELAY:
+				ESP_LOGI("TNC", "updated tx delay");
+				tnc_settings.tx_delay = frame[1];
+				break;
+			case KISS_CMD_P:
+				ESP_LOGI("TNC", "updated persistance");
+				tnc_settings.P = frame[1];
+				break;
+			case KISS_CMD_SLOTTIME:
+				ESP_LOGI("TNC", "updated slot time");
+				tnc_settings.slot_time = frame[1];
+				break;
+			case KISS_CMD_TXTAIL:
+				ESP_LOGI("TNC", "updated tx tail");
+				tnc_settings.tx_tail = frame[1];
+				break;
+			case KISS_CMD_FULLDUPLEX:
+				ESP_LOGI("TNC", "updated duplex setting");
+				tnc_settings.full_duplex = frame[1];
+				break;
+			case KISS_CMD_SETHARDWARE:
+				ESP_LOGI("TNC", "updated hardware settings");
+				break;
+			case KISS_CMD_RETURN:
+				ESP_LOGI("TNC", "wtf is return");
+				break;
+			default:
+				ESP_LOGE("KISS", "unknown data byte");
+		}
 
-	return output;
+		// reload for parameter changes to take effect
+	}
 }
 
+/* TNC Tasks */
+// schedules transmissions based on p-persistance
+// settings and carrier sense from radio a
+// TODO: Latch CS during slot time?
 
-void RX_DSP_Task(void *pvParameters)
+void tnc_task(void *para)
 {
-	// algorithm variables
-	volatile float E_s1=0, E_s2=0, lpf_output;
-	volatile uint8_t raw_bit=0, previous_raw_bit=1;
-	volatile int32_t d_pll=0, dpll_error=0, err_div=0, dpll_margin = 1;
-	uint32_t success = 0;
-	float coeff0, coeff1;
-	uint8_t EXTERNAL_DATA= 0;
-
-	volatile uint32_t count_start, count_stop; // needed for debuging
-
-
-	aprs_decoder_init();
-	frame_buffer_init(aprs_buf, 256);
-	goertzel_init(1200, 2200, &coeff0, &coeff1);
-	lpf_init();
-
-	// Sampling Semaphore
-	xRadioRXISRSemaphore = xSemaphoreCreateBinary();
-
+	radio_packet_rx(NULL);
+	uint8_t *packet;
+	size_t packet_size;
 	while(1)
 	{
-		count_start = xthal_get_ccount();
-		if( xSemaphoreTake(xRadioRXISRSemaphore, portMAX_DELAY) == pdTRUE)
-		{
-
-			//enable_debug_IO(DEBUG_0);
-			if (xSemaphoreTake(xRadioMutex, 0) == pdTRUE)
-			{
-				//disable_debug_IO(DEBUG_0);
-				//enable_debug_IO(DEBUG_0);
-				EXTERNAL_DATA = (int)cc1200_radio_read_CFM();
-				//EXTERNAL_DATA = gpio_get_level(CC1120_GPIO2);
-				xSemaphoreGive(xRadioMutex);
-				//disable_debug_IO(DEBUG_0);
-			}
-			else
-			{
-				ESP_LOGE("Radio", "Sampling Failure");
-			}
-			//disable_debug_IO(DEBUG_0);
-			//enable_debug_IO(DEBUG_0);
-
-			window_add(EXTERNAL_DATA);
-			int8_t *window = window_get();
-			E_s1 = goertzel_filter(window, coeff0, WINDOW_SIZE);
-			E_s2 = goertzel_filter(window, coeff1, WINDOW_SIZE);
-			//E_s1 = goertzelFilter(window, 1200, WINDOW_SIZE);
-			//E_s1 = goertzelFilter(window, 2200, WINDOW_SIZE);
-			lpf_output = lpf_baseband((E_s1 - E_s2));
-
-			if (lpf_output > 0)
-			{
-				raw_bit = 1;
-				enable_debug_IO(DEBUG_2);
-
-			}
-			else
-			{
-				raw_bit = 0;
-				disable_debug_IO(DEBUG_2);
-			}
+		// indicate RX
+		enable_green_led();
+		disable_red_led();
 
-			//disable_debug_IO(DEBUG_0);
-			//enable_debug_IO(DEBUG_0);
+		// check ring buffer for packet
+		packet = xRingbufferReceive(ax25_tx_buf, &packet_size, portMAX_DELAY);
 
-			// DPLL for sampling
-			if (raw_bit != previous_raw_bit)
+		if (packet != NULL)
+		{
+			uint8_t P;
+			// wait based on persistance algorithm
+			while (1)
 			{
-				dpll_error = d_pll - (D_PLL_MAX / 2);
-				if (dpll_error >  (D_PLL_MARGIN))
-				{
-					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))
+				if (!radio_get_cs())
 				{
-					d_pll += get_rx_status()  ? D_PLL_MARGIN:
-							-(err_div + dpll_error); //(dpll_error + err_div / 2) / err_div;
+					P = (uint8_t) esp_random();
+					if (P <= tnc_settings.P)
+					{
+						break;
+					}
+					else
+					{
+						vTaskDelay(tnc_settings.slot_time * 10 / portTICK_PERIOD_MS);
+					}
 				}
+				taskYIELD(); // make sure to yield for RX'ing task
 			}
 
-			d_pll += D_PLL_INC;
-
-			if (d_pll >= D_PLL_MAX)
-			{
-				// set clock debug I/O high
-				enable_debug_IO(DEBUG_3);
-
-				// feed bit to aprs decoder algorithm
-				switch(aprs_decoder_feed_bit(raw_bit))
-				{
-					case NORMAL:
-						break;
-					case FRAME_DECODED:
-						ESP_LOGI("APRS RX", "AX.25 Frame Received [%d]", success++);
-						// send via KISS TNC to over BLE SPP
-						//ESP_LOG_BUFFER_HEXDUMP("APRS RX", aprs_buf, 100, ESP_LOG_INFO);
-						kiss_transmit(KISS_DATAFRAME, v.frame_buffer, v.frame_len);
-						break;
-					case ERROR_FCS_MISMATCH:
-						ESP_LOGV("APRS RX", "AX.25 FCS Error\n");
-						break;
-					default:
-						//printf("Weird Error\n");
-						break;
-				}
+			// indicate TX
+			enable_red_led();
+			disable_green_led();
 
-				d_pll -= D_PLL_MAX;
-			}
-			else
+			// dump all the packets in the buffer
+			while(packet != NULL)
 			{
-				// set clock debug I/O low
-				disable_debug_IO(DEBUG_3);
+				radio_packet_tx(packet, packet_size, NULL);
+				vRingbufferReturnItem(ax25_tx_buf, (void *)packet);
+				packet = xRingbufferReceive(ax25_tx_buf, &packet_size, 0);
 			}
-			count_stop = xthal_get_ccount();
-			previous_raw_bit = raw_bit;
 		}
+		else
+		{
+			printf("Why we here \n");
+		}
+		// setup again for reception
+		radio_packet_rx(NULL);
 	}
 }
 
-
-void radio_init()
-{
-	// Setup Task Communications
-	radio_tx_buf = xRingbufferCreate(1028, RINGBUF_TYPE_NOSPLIT);
-	radio_rx_buf = xRingbufferCreate(1028, RINGBUF_TYPE_NOSPLIT);
-	xRadioRXSemaphore = xSemaphoreCreateBinary();
-	xRadioTXSemaphore = xSemaphoreCreateBinary();
-	xRadioMutex = xSemaphoreCreateMutex();
-
-	xTaskCreatePinnedToCore(Radio_Task, "Radio Controller", 1024*4, 0, 2, NULL, 1);
-	xTaskCreatePinnedToCore(RX_DSP_Task, "Radio DSP", 1024*4, 0, 1, NULL, 1);
-
-}
-
 void IRAM_ATTR app_main()
 {
 	// Initialize Flash
@@ -391,15 +195,35 @@ void IRAM_ATTR app_main()
 	// Board IO Initialize
 	board_init();
 
+	// Load Settings from Flash
+
+
 	// Radio Task Initialize
-	radio_init();
+	ax25_param_t ax25_param;
 
-	// AFSK Modulator and Demodulator
+	ax25_param.tx_tail = 10;
+	ax25_param.tx_delay = 10;
+	ax25_param.sample_rate = 13200;
+	ax25_param.symbol0_freq = 1200;
+	ax25_param.symbol1_freq = 2200;
+	ax25_param.rx_cb = radio_rx_ax25_cb;
+	ax25_param.rx_buf = ax25_rx_buf;
+	ax25_param.rx_buf_len = sizeof(ax25_rx_buf) / sizeof(ax25_rx_buf[0]);
+	ax25_param.cpu_core = 1;
 
+	radio_init(AX25, &ax25_param);
 
 	// Kiss Decoder and Encoder
-	kiss_init();
+	kiss_init(0, kiss_tx_cb, kiss_rx_cb);
+
 
 	// BLE and SPP
 	bt_spp_init();
+
+	// Inter-Task Communication
+	ax25_tx_buf = xRingbufferCreate(1028, RINGBUF_TYPE_NOSPLIT);
+
+	// Tasks
+	xTaskCreatePinnedToCore(tnc_task, "tnc task", 1024*4, 0, 2, NULL, 1);
+
 }