Browse Source

Merge CC1200 code from cc1200-afsk-rx branch

curiousmuch 4 years ago
parent
commit
60f21eca97
3 changed files with 999 additions and 0 deletions
  1. 624 0
      main/cc1200.c
  2. 298 0
      main/cc1200.h
  3. 77 0
      main/cc1200_protocol.h

+ 624 - 0
main/cc1200.c

@@ -0,0 +1,624 @@
+/*
+ * Project: Arrow
+ * Author: 	curiousmuch
+ */
+#include <stdio.h>
+#include <math.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "driver/gpio.h"
+#include "sdkconfig.h"
+#include "driver/spi_master.h"
+#include "esp_err.h"
+#include "cc1200.h"
+#include "cc1200_protocol.h"
+#include "board.h"
+#include "esp_task_wdt.h"
+#include "freertos/ringbuf.h"
+
+#define CC1200_WRITE_BIT 	0
+#define CC1200_READ_BIT 	BIT(1)
+#define CC1200_BURST_BIT 	BIT(0)
+
+// Public Configurations for CC1120 SPI Driver
+spi_bus_config_t bus_config =
+{
+	.miso_io_num = CC1120_MISO,
+	.mosi_io_num = CC1120_MOSI,
+	.sclk_io_num = CC1120_SCLK,
+	.quadwp_io_num = -1,
+	.quadhd_io_num = -1,
+	.max_transfer_sz = 150,
+	.flags = ESP_INTR_FLAG_IRAM
+};
+
+
+spi_device_interface_config_t interface_config =
+{
+	.command_bits = 2,
+	.address_bits = 6,
+	.dummy_bits = 0,
+	.mode = 0,
+	.spics_io_num = CC1120_CS,
+	.clock_speed_hz = (APB_CLK_FREQ/20),
+	.flags = 0,
+	.queue_size = 20
+
+};
+
+spi_device_handle_t spi;
+
+// Private CC1120 Driver Functions
+void cc1200_gpio_init(void)
+{
+	gpio_config_t reset_pin_config =
+	{
+			.pin_bit_mask = (uint64_t)(BIT64(CC1120_RESET)),
+			.mode = GPIO_MODE_OUTPUT,
+			.pull_up_en = GPIO_PULLUP_DISABLE,
+			.pull_down_en = GPIO_PULLDOWN_DISABLE,
+			.intr_type = GPIO_INTR_DISABLE
+
+	};
+	gpio_config_t gpio_pin_config =
+	{
+			.pin_bit_mask = (uint64_t) (BIT64(CC1120_GPIO0)|BIT64(CC1120_GPIO2)|BIT64(CC1120_GPIO3)),
+			.mode = GPIO_MODE_INPUT,
+			.pull_up_en = GPIO_PULLUP_DISABLE,
+			.pull_down_en = GPIO_PULLDOWN_DISABLE,
+			.intr_type = GPIO_INTR_DISABLE
+	};
+	gpio_config_t debug_pin_config =
+	{
+			.pin_bit_mask = (uint64_t) (BIT64(DEBUG_0)|BIT64(DEBUG_1)),
+			.mode = GPIO_MODE_OUTPUT,
+			.pull_up_en = GPIO_PULLUP_DISABLE,
+			.pull_down_en = GPIO_PULLDOWN_DISABLE,
+			.intr_type = GPIO_INTR_DISABLE
+	};
+
+	gpio_config(&reset_pin_config);
+	gpio_config(&gpio_pin_config);
+	gpio_config(&debug_pin_config);
+
+
+	gpio_set_level(CC1120_RESET, 1);
+
+}
+
+void cc1200_spi_init(void)
+{
+	esp_err_t ret;
+	ret = spi_bus_initialize(VSPI_HOST, &bus_config, 0);	// this uses DMA channel 1
+	ESP_ERROR_CHECK(ret);
+	ret = spi_bus_add_device(VSPI_HOST, &interface_config, &spi);
+	ESP_ERROR_CHECK(ret);
+}
+
+void IRAM_ATTR cc1200_spi_write_byte(uint16_t addr, uint8_t data)
+{
+	esp_err_t ret;
+	spi_transaction_t tx_trans =
+	{
+		.flags = SPI_TRANS_USE_TXDATA,
+		.cmd = CC1200_WRITE_BIT,
+		.addr = addr,
+		.length = 8,
+		.rxlength = 0,
+		.tx_data[0] = data
+
+	};
+
+	if ((addr & 0xFF00) != 0) // send data with extended address in command field
+	{
+		tx_trans.flags |= (SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR);
+		spi_transaction_ext_t tx_trans_ext =
+		{
+				.base = tx_trans,
+				.command_bits = 2,
+				.address_bits = 14
+		};
+		ret = spi_device_polling_transmit(spi, (spi_transaction_t*)&tx_trans_ext);
+	}
+	else
+	{
+		ret = spi_device_polling_transmit(spi, &tx_trans);
+	}
+	ESP_ERROR_CHECK(ret);
+}
+
+void IRAM_ATTR cc1200_spi_write_bytes(uint16_t addr, uint8_t* data, uint8_t len)
+{
+	esp_err_t ret;
+	spi_transaction_t tx_trans =
+	{
+		.cmd = (CC1200_WRITE_BIT | CC1200_BURST_BIT),
+		.addr = addr,
+		.length = 8*len,
+		.tx_buffer = data
+	};
+	if ((addr & 0xFF00) != 0) // send data with extended address in command field
+	{
+		tx_trans.flags |= (SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR);
+		spi_transaction_ext_t tx_trans_ext =
+		{
+				.base = tx_trans,
+				.command_bits = 2,
+				.address_bits = 14
+		};
+		ret = spi_device_polling_transmit(spi, (spi_transaction_t*)&tx_trans_ext);
+	}
+	else
+	{
+		ret = spi_device_polling_transmit(spi, &tx_trans);
+	}
+	ESP_ERROR_CHECK(ret);
+}
+
+void IRAM_ATTR cc1200_spi_read_byte(uint16_t addr, uint8_t* data)
+{
+	esp_err_t ret;
+	spi_transaction_t rx_trans =
+	{
+		.cmd = CC1200_READ_BIT,
+		.addr = addr,
+		.length = 8,
+		.rxlength = 8,
+		.rx_buffer = data
+	};
+	if ((addr & 0xFF00) != 0) // read data with extended address in command field
+	{
+		rx_trans.flags |= (SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR);
+		spi_transaction_ext_t rx_trans_ext =
+		{
+				.base = rx_trans,
+				.command_bits = 2,
+				.address_bits = 14
+		};
+		ret = spi_device_polling_transmit(spi, (spi_transaction_t*)&rx_trans_ext);
+	}
+	else
+	{
+		ret = spi_device_polling_transmit(spi, &rx_trans);
+	}
+	ESP_ERROR_CHECK(ret);
+}
+
+void cc1200_spi_read_bytes(uint16_t addr, uint8_t* data, uint8_t len)
+{
+	esp_err_t ret;
+	spi_transaction_t rx_trans =
+	{
+		.cmd = (CC1200_READ_BIT | CC1200_BURST_BIT),
+		.addr = addr,
+		.length = 8*len,
+		.rxlength = 8*len,
+		.rx_buffer = data
+	};
+	if ((addr & 0xFF00) != 0) // read data with extended address in command field
+	{
+		rx_trans.flags |= (SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR);
+		spi_transaction_ext_t rx_trans_ext =
+		{
+				.base = rx_trans,
+				.command_bits = 2,
+				.address_bits = 14
+		};
+		ret = spi_device_polling_transmit(spi, (spi_transaction_t*)&rx_trans_ext);
+	}
+	else
+	{
+		ret = spi_device_polling_transmit(spi, &rx_trans);
+	}
+	ESP_ERROR_CHECK(ret);
+}
+
+rf_status_t IRAM_ATTR cc1200_spi_strobe(uint8_t cmd)
+{
+	esp_err_t ret;
+	uint8_t temp=0;
+	spi_transaction_t rx_trans =
+	{
+		.flags = (SPI_TRANS_USE_TXDATA | SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_ADDR),
+		.length = 8,
+		.rxlength = 8,
+		.rx_buffer = &temp,
+		.tx_data[0] = cmd
+	};
+	spi_transaction_ext_t rx_trans_ext =
+	{
+			.base = rx_trans,
+			.command_bits = 0,
+			.address_bits = 0
+	};
+	ret = spi_device_transmit(spi, (spi_transaction_t*)&rx_trans_ext);
+	ESP_ERROR_CHECK(ret);
+	return (temp & 0xF0);
+}
+
+// Public CC1120 Driver Functions
+// These function should have there own error codes as they're dependent upon the radio and
+// not the ESP32 :)
+
+rf_status_t cc1200_radio_reset(void)
+{
+	rf_status_t status;
+	uint8_t retry_count = 0;
+	cc1200_spi_strobe(CC120X_SRES);
+	status = cc1200_spi_strobe(CC120X_SNOP);
+
+	vTaskDelay(10 / portTICK_PERIOD_MS);
+
+	while((CC120X_RDYn_BIT & (status & 0x80)))
+	{
+		vTaskDelay(10 / portTICK_PERIOD_MS);
+		if (retry_count > 3)
+		{
+			// place error CC1120 timeout
+			printf("CC1120 Reset Failure\n");
+			break;
+		}
+		status = cc1200_spi_strobe(CC120X_SNOP);
+		retry_count++;
+	}
+	printf("%x\n", retry_count);
+	return status;
+}
+
+// f_RF = f_VCO / LO Divider
+#define CC1200_LO_DIVIDER	24 			// 136.7 - 160 MHz Band
+#define CC1200_XOSC 		40000000	// 40MHz
+// f_VCO = FREQ / 2^16 * f_XOSX + FREQOFF / 2^18 * F_XOSC
+
+esp_err_t cc1200_radio_frequency(uint32_t freq)
+{
+	// calculate FREQ0, FREQ, FREQ2 registers
+	volatile double temp_freq;
+	temp_freq = ((double) freq * 65536 * CC1200_LO_DIVIDER) / CC1200_XOSC;
+	freq = (uint32_t)temp_freq;
+	cc1200_spi_write_byte(CC120X_FREQ0, ((uint8_t *)&freq)[0]);
+	cc1200_spi_write_byte(CC120X_FREQ1, ((uint8_t *)&freq)[1]);
+	cc1200_spi_write_byte(CC120X_FREQ2, ((uint8_t *)&freq)[2]);
+	return ESP_OK;
+}
+
+esp_err_t cc1200_radio_sleep(void)
+{
+	return ESP_OK;
+}
+
+esp_err_t cc1200_radio_power(uint8_t txPower)
+{
+	return ESP_OK;
+}
+
+
+#define HDLC_FLAG 0x7E
+#define HDLC_FLAG_LEN 10
+
+uint8_t packet_len = 0;
+uint8_t test_vector[] = {0x71, 0x01, 023, 0xAE, 0x75};
+volatile uint8_t sample_count = 0;
+uint8_t toggle;
+uint8_t toggle2;
+uint8_t prev_sample_count = 0;
+uint32_t tx_symbol = 0;
+uint8_t prev_tx_symbol = 0;
+
+
+
+#define SAMPLE_FREQUENCY 13200
+#define DAC_MAX 64
+#define LUT_SIZE 128
+
+DRAM_ATTR int8_t LUT[LUT_SIZE];
+
+int32_t phase_i = 0;
+volatile uint8_t new_sample = 0;
+
+float phase = 0.0f;
+float delta_phi = 0.0f;
+float const delta_phi_1 = (float) 1200 / SAMPLE_FREQUENCY * LUT_SIZE;
+float const delta_phi_2 = (float) 2200 / SAMPLE_FREQUENCY * LUT_SIZE;
+uint8_t data;
+
+//const uint8_t APRS_TEST_PACKET[] = {168,138,166,168, 64, 64,224,174,132,100,158,166,180,255,  3,240, 44, 84,
+//									 104,101, 32,113,117,105, 99,107, 32, 98,114,111,119,110, 32,102,111,120,
+//									  32,106,117,109,112,115, 32,111,118,101,114, 32,116,104,101, 32,108, 97,
+//									 122,121, 32,100,111,103, 33, 32, 32, 49, 32,111,102, 32, 52, 40,110};
+
+const uint8_t APRS_TEST_PACKET[] = { 0x82, 0x98, 0x98, 0x40, 0x40, 0x40, 0xe0, 0x96, 0x84, 0x66, 0xaa, 0x96, 0xac, 0xe0, 0xae, 0x92,
+									 0x88, 0x8a, 0x62, 0x40, 0x62, 0xae, 0x92, 0x88, 0x8a, 0x64, 0x40, 0x65, 0x03, 0xf0, 0x3a, 0x4b,
+									 0x42, 0x33, 0x55, 0x4b, 0x56, 0x2d, 0x32, 0x20, 0x3a, 0x48, 0x69, 0x21, 0x20, 0x54, 0x68, 0x69, 0x73,
+									 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x54, 0x65, 0x73, 0x74, 0x7b, 0x31, 0xad, 0xa1 };
+
+//#define APRS_TEST_PACKET fbuf
+
+extern unsigned char *fbuf;
+extern uint32_t flen;
+//const uint8_t APRS_TEST_PACKET[] = {0xFF, 0xFF, 0xFF};
+
+// The output needs to be continous phase.
+
+typedef struct {
+	uint8_t one_count;
+	uint32_t sample_count;
+	uint32_t byte;
+	uint32_t packet_len;
+	uint8_t prev_bit;
+	uint8_t cur_bit;
+	uint8_t tone;
+} aprs_flags_t;
+
+aprs_flags_t DRAM_ATTR aprs_flags = {
+		.one_count = 0,
+		.sample_count = 0,
+		.byte = 0,
+		.packet_len = sizeof(APRS_TEST_PACKET)/sizeof(uint8_t),
+		.prev_bit = 0,
+		.cur_bit = 0,
+		.tone = 0
+};
+
+static void IRAM_ATTR LUT_lookup(void)
+{
+	if (aprs_flags.tone)
+		delta_phi = delta_phi_1;
+	else
+		delta_phi = delta_phi_2;
+
+    phase_i = (int32_t)phase;        // get integer part of our phase
+
+    phase += delta_phi;              // increment phase
+
+    if (phase >= (float)LUT_SIZE)    // handle wraparound
+        phase -= (float)LUT_SIZE;
+}
+
+static void IRAM_ATTR cc1200_aprs_tx_isr(void* arg)
+{
+    cc1200_spi_write_byte(CC120X_CFM_TX_DATA_IN, LUT[phase_i]);
+
+    sample_count++;
+    new_sample = 1;
+
+	toggle = toggle ^ 1;
+	gpio_set_level(DEBUG_1, toggle);
+}
+
+void cc1200_lut_init(void)
+{
+	int16_t i=0;
+	for (i=0; i<LUT_SIZE; ++i)
+	{
+		LUT[i] = (int8_t)roundf(DAC_MAX * sinf(2.0f * M_PI * (float)i / LUT_SIZE));
+		//printf("%d,\n", LUT[i]);
+	}
+}
+
+#define PREAMBLE_LENGTH 20
+#define SUFFIX_LENGTH 1
+
+// test function to generate APRS s1 or s2
+void IRAM_ATTR cc1200_radio_APRSTXPacket(void)
+{
+	// start CW transmission
+	cc1200_spi_write_byte(CC120X_FIFO, 0x12);
+	cc1200_spi_strobe(CC120X_STX);
+
+	// enable interrupt pin for CC1120 for timing packets
+	gpio_install_isr_service(ESP_INTR_FLAG_IRAM);
+
+	gpio_isr_handler_add(CC1120_GPIO3, cc1200_aprs_tx_isr, NULL);
+	gpio_set_intr_type(CC1120_GPIO3, GPIO_INTR_POSEDGE);
+
+	// acquire SPI bus for fastest possible SPI transactions
+	spi_device_acquire_bus(spi, portMAX_DELAY);
+
+	int16_t i,j;
+
+	while(1)
+	{
+		// start CW transmission
+		cc1200_spi_write_byte(CC120X_FIFO, 0x12);
+		cc1200_spi_strobe(CC120X_STX);
+
+		sample_count = 0;
+		new_sample = 0;
+		/* Send Flag */
+		for (i = 0; i<PREAMBLE_LENGTH; i++)
+		{
+			aprs_flags.byte = 0x7E;
+			for(j=0; j<8; j++)
+			{
+				aprs_flags.cur_bit = aprs_flags.byte & 0x01;
+
+				// NRZ-I Encoding
+				if (aprs_flags.cur_bit)
+				{
+					// do nothing
+					aprs_flags.one_count++;
+
+				}
+				else
+				{
+					aprs_flags.tone = aprs_flags.tone ^ 1; // switch tone
+					aprs_flags.one_count = 0;
+				}
+
+				aprs_flags.byte = (aprs_flags.byte >> 1);
+
+				while(sample_count < 11)	// wait for symbol to be sent
+				{
+					if ( new_sample )
+					{
+						LUT_lookup();
+						new_sample = 0;
+					}
+				}
+				sample_count = 0;
+				//printf("Symbol: %x\n", aprs_flags.cur_bit);
+
+			}
+		}
+		aprs_flags.one_count = 0;
+
+		/* Send Packet */
+		for (i=0;i<aprs_flags.packet_len;i++)
+		{
+			aprs_flags.byte = APRS_TEST_PACKET[i];
+			for(j=0; j<8; j++)
+			{
+				aprs_flags.cur_bit = aprs_flags.byte & 0x01;	// bool of first bit
+
+				// Zero Stuffing
+				if (aprs_flags.one_count == 5)
+				{
+					aprs_flags.tone = aprs_flags.tone ^ 1;
+					aprs_flags.one_count = 0;
+
+					// wait for symbol to be sent
+					while(sample_count < 11)
+					{
+						if ( new_sample )
+						{
+							LUT_lookup();
+							new_sample = 0;
+						}
+					}
+					toggle2 = toggle2 ^ 1;
+					gpio_set_level(DEBUG_0, toggle2);
+					sample_count = 0;
+				}
+
+				// NRZ-I Encoding
+				if (aprs_flags.cur_bit)
+				{
+					// do nothing
+					aprs_flags.one_count++;
+
+				}
+				else
+				{
+					aprs_flags.tone = aprs_flags.tone ^ 1; // switch tone
+					aprs_flags.one_count = 0;
+				}
+
+				aprs_flags.byte = (aprs_flags.byte >> 1);
+
+				while(sample_count < 11)	// wait for symbol to be sent
+				{
+					if ( new_sample )
+					{
+						LUT_lookup();
+						new_sample = 0;
+					}
+				}
+				toggle2 = toggle2 ^ 1;
+				gpio_set_level(DEBUG_0, toggle2);
+				sample_count = 0;
+				//printf("Symbol: %x\n", aprs_flags.cur_bit);
+			}
+		}
+		aprs_flags.one_count = 0;
+
+		/* Send Flag */
+		for (i = 0; i<SUFFIX_LENGTH; i++)
+		{
+			aprs_flags.byte = 0x7E;
+			for(j=0; j<8;j++)
+			{
+				aprs_flags.cur_bit = aprs_flags.byte & 0x01;
+
+				// NRZ-I Encoding
+				if (aprs_flags.cur_bit)
+				{
+					// do nothing
+					aprs_flags.one_count++;
+
+				}
+				else
+				{
+					aprs_flags.tone = aprs_flags.tone ^ 1; // switch tone
+					aprs_flags.one_count = 0;
+				}
+
+				aprs_flags.byte = (aprs_flags.byte >> 1);
+
+				while(sample_count < 11)	// wait for symbol to be sent
+				{
+					if ( new_sample )
+					{
+						LUT_lookup();
+						new_sample = 0;
+					}
+				}
+				sample_count = 0;
+
+			}
+		}
+		cc1200_spi_strobe(CC120X_SIDLE);
+
+		vTaskDelay(10000/portTICK_PERIOD_MS);
+	}
+}
+
+extern RingbufHandle_t cfm_buf_handle;
+
+static void IRAM_ATTR cc1200_aprs_rx_isr(void* arg)
+{
+	//uint8_t data = 0;
+
+	cc1200_spi_read_byte(CC120X_CFM_RX_DATA_OUT, &data);
+
+	toggle = toggle ^ 1;
+	gpio_set_level(DEBUG_1, toggle);
+	xRingbufferSendFromISR(cfm_buf_handle, &data, sizeof(data), NULL);
+	//ets_write_char_uart(data);
+    //new_sample = 1;
+
+}
+
+void IRAM_ATTR cc1200_radio_APRSRXPacket(void)
+{
+	printf("Starting Continuous RX\n");
+	// start RX transmission
+	//cc1120_spi_write_byte(CC112X_FIFO, 0x12);
+	cc1200_spi_strobe(CC120X_SRX);
+	vTaskDelay(20/portTICK_PERIOD_MS);
+	cc1200_spi_strobe(CC120X_SRX);
+
+	// acquire SPI bus for fastest possible SPI transactions
+	spi_device_acquire_bus(spi, portMAX_DELAY);
+
+	// enable interrupt pin for CC1120 for timing packets
+	gpio_install_isr_service(ESP_INTR_FLAG_IRAM);
+
+	gpio_isr_handler_add(CC1120_GPIO3, cc1200_aprs_rx_isr, NULL);
+	gpio_set_intr_type(CC1120_GPIO3, GPIO_INTR_POSEDGE);
+
+}
+
+void cc1200_radio_init(const cc1200_reg_settings_t* rf_settings, uint8_t len)
+{
+	cc1200_gpio_init();
+	cc1200_spi_init();
+	cc1200_lut_init();
+
+	cc1200_radio_reset();	gpio_set_level(CC1120_RESET, 1);
+
+	uint8_t data;
+	cc1200_spi_read_byte(CC120X_PARTNUMBER, &data);
+	printf("%x", data);
+
+
+	uint8_t i;
+
+	for (i=0;i<len;i++)
+	{
+		cc1200_spi_write_byte(rf_settings[i].addr, rf_settings[i].data);
+	}
+}
+
+
+

+ 298 - 0
main/cc1200.h

@@ -0,0 +1,298 @@
+/*
+ * cc1200.h
+ *
+ *  Created on: Jan 11, 2019
+ *      Author: curiousmuch
+ */
+
+#ifndef MAIN_CC1200_H_
+#define MAIN_CC1200_H_
+
+#include <stdio.h>
+#include <stdint.h>
+
+/* configuration registers */
+#define CC120X_IOCFG3                   0x0000
+#define CC120X_IOCFG2                   0x0001
+#define CC120X_IOCFG1                   0x0002
+#define CC120X_IOCFG0                   0x0003
+#define CC120X_SYNC3                    0x0004
+#define CC120X_SYNC2                    0x0005
+#define CC120X_SYNC1                    0x0006
+#define CC120X_SYNC0                    0x0007
+#define CC120X_SYNC_CFG1                0x0008
+#define CC120X_SYNC_CFG0                0x0009
+#define CC120X_DEVIATION_M              0x000A
+#define CC120X_MODCFG_DEV_E             0x000B
+#define CC120X_DCFILT_CFG               0x000C
+#define CC120X_PREAMBLE_CFG1            0x000D
+#define CC120X_PREAMBLE_CFG0            0x000E
+#define CC120X_IQIC                     0x000F
+#define CC120X_CHAN_BW                  0x0010
+#define CC120X_MDMCFG1                  0x0011
+#define CC120X_MDMCFG0                  0x0012
+#define CC120X_SYMBOL_RATE2             0x0013
+#define CC120X_SYMBOL_RATE1             0x0014
+#define CC120X_SYMBOL_RATE0             0x0015
+#define CC120X_AGC_REF                  0x0016
+#define CC120X_AGC_CS_THR               0x0017
+#define CC120X_AGC_GAIN_ADJUST          0x0018
+#define CC120X_AGC_CFG3                 0x0019
+#define CC120X_AGC_CFG2                 0x001A
+#define CC120X_AGC_CFG1                 0x001B
+#define CC120X_AGC_CFG0                 0x001C
+#define CC120X_FIFO_CFG                 0x001D
+#define CC120X_DEV_ADDR                 0x001E
+#define CC120X_SETTLING_CFG             0x001F
+#define CC120X_FS_CFG                   0x0020
+#define CC120X_WOR_CFG1                 0x0021
+#define CC120X_WOR_CFG0                 0x0022
+#define CC120X_WOR_EVENT0_MSB           0x0023
+#define CC120X_WOR_EVENT0_LSB           0x0024
+#define CC120X_RXDCM_TIME               0x0025
+#define CC120X_PKT_CFG2                 0x0026
+#define CC120X_PKT_CFG1                 0x0027
+#define CC120X_PKT_CFG0                 0x0028
+#define CC120X_RFEND_CFG1               0x0029
+#define CC120X_RFEND_CFG0               0x002A
+#define CC120X_PA_CFG1                  0x002B
+#define CC120X_PA_CFG0                  0x002C
+#define CC120X_ASK_CFG                  0x002D
+#define CC120X_PKT_LEN                  0x002E
+
+/* Extended Configuration Registers */
+#define CC120X_IF_MIX_CFG               0x2F00
+#define CC120X_FREQOFF_CFG              0x2F01
+#define CC120X_TOC_CFG                  0x2F02
+#define CC120X_MARC_SPARE               0x2F03
+#define CC120X_ECG_CFG                  0x2F04
+#define CC120X_MDMCFG2                  0x2F05
+#define CC120X_EXT_CTRL                 0x2F06
+#define CC120X_RCCAL_FINE               0x2F07
+#define CC120X_RCCAL_COARSE             0x2F08
+#define CC120X_RCCAL_OFFSET             0x2F09
+#define CC120X_FREQOFF1                 0x2F0A
+#define CC120X_FREQOFF0                 0x2F0B
+#define CC120X_FREQ2                    0x2F0C
+#define CC120X_FREQ1                    0x2F0D
+#define CC120X_FREQ0                    0x2F0E
+#define CC120X_IF_ADC2                  0x2F0F
+#define CC120X_IF_ADC1                  0x2F10
+#define CC120X_IF_ADC0                  0x2F11
+#define CC120X_FS_DIG1                  0x2F12
+#define CC120X_FS_DIG0                  0x2F13
+#define CC120X_FS_CAL3                  0x2F14
+#define CC120X_FS_CAL2                  0x2F15
+#define CC120X_FS_CAL1                  0x2F16
+#define CC120X_FS_CAL0                  0x2F17
+#define CC120X_FS_CHP                   0x2F18
+#define CC120X_FS_DIVTWO                0x2F19
+#define CC120X_FS_DSM1                  0x2F1A
+#define CC120X_FS_DSM0                  0x2F1B
+#define CC120X_FS_DVC1                  0x2F1C
+#define CC120X_FS_DVC0                  0x2F1D
+#define CC120X_FS_LBI                   0x2F1E
+#define CC120X_FS_PFD                   0x2F1F
+#define CC120X_FS_PRE                   0x2F20
+#define CC120X_FS_REG_DIV_CML           0x2F21
+#define CC120X_FS_SPARE                 0x2F22
+#define CC120X_FS_VCO4                  0x2F23
+#define CC120X_FS_VCO3                  0x2F24
+#define CC120X_FS_VCO2                  0x2F25
+#define CC120X_FS_VCO1                  0x2F26
+#define CC120X_FS_VCO0                  0x2F27
+#define CC120X_GBIAS6                   0x2F28
+#define CC120X_GBIAS5                   0x2F29
+#define CC120X_GBIAS4                   0x2F2A
+#define CC120X_GBIAS3                   0x2F2B
+#define CC120X_GBIAS2                   0x2F2C
+#define CC120X_GBIAS1                   0x2F2D
+#define CC120X_GBIAS0                   0x2F2E
+#define CC120X_IFAMP                    0x2F2F
+#define CC120X_LNA                      0x2F30
+#define CC120X_RXMIX                    0x2F31
+#define CC120X_XOSC5                    0x2F32
+#define CC120X_XOSC4                    0x2F33
+#define CC120X_XOSC3                    0x2F34
+#define CC120X_XOSC2                    0x2F35
+#define CC120X_XOSC1                    0x2F36
+#define CC120X_XOSC0                    0x2F37
+#define CC120X_ANALOG_SPARE             0x2F38
+#define CC120X_PA_CFG3                  0x2F39
+#define CC120X_IRQ0M                    0x2F3F
+#define CC120X_IRQ0F                    0x2F40
+
+/* Status Registers */
+#define CC120X_WOR_TIME1                0x2F64
+#define CC120X_WOR_TIME0                0x2F65
+#define CC120X_WOR_CAPTURE1             0x2F66
+#define CC120X_WOR_CAPTURE0             0x2F67
+#define CC120X_BIST                     0x2F68
+#define CC120X_DCFILTOFFSET_I1          0x2F69
+#define CC120X_DCFILTOFFSET_I0          0x2F6A
+#define CC120X_DCFILTOFFSET_Q1          0x2F6B
+#define CC120X_DCFILTOFFSET_Q0          0x2F6C
+#define CC120X_IQIE_I1                  0x2F6D
+#define CC120X_IQIE_I0                  0x2F6E
+#define CC120X_IQIE_Q1                  0x2F6F
+#define CC120X_IQIE_Q0                  0x2F70
+#define CC120X_RSSI1                    0x2F71
+#define CC120X_RSSI0                    0x2F72
+#define CC120X_MARCSTATE                0x2F73
+#define CC120X_LQI_VAL                  0x2F74
+#define CC120X_PQT_SYNC_ERR             0x2F75
+#define CC120X_DEM_STATUS               0x2F76
+#define CC120X_FREQOFF_EST1             0x2F77
+#define CC120X_FREQOFF_EST0             0x2F78
+#define CC120X_AGC_GAIN3                0x2F79
+#define CC120X_AGC_GAIN2                0x2F7A
+#define CC120X_AGC_GAIN1                0x2F7B
+#define CC120X_AGC_GAIN0                0x2F7C
+#define CC120X_CFM_RX_DATA_OUT         0x2F7D
+#define CC120X_CFM_TX_DATA_IN          0x2F7E
+#define CC120X_ASK_SOFT_RX_DATA         0x2F7F
+#define CC120X_RNDGEN                   0x2F80
+#define CC120X_MAGN2                    0x2F81
+#define CC120X_MAGN1                    0x2F82
+#define CC120X_MAGN0                    0x2F83
+#define CC120X_ANG1                     0x2F84
+#define CC120X_ANG0                     0x2F85
+#define CC120X_CHFILT_I2                0x2F86
+#define CC120X_CHFILT_I1                0x2F87
+#define CC120X_CHFILT_I0                0x2F88
+#define CC120X_CHFILT_Q2                0x2F89
+#define CC120X_CHFILT_Q1                0x2F8A
+#define CC120X_CHFILT_Q0                0x2F8B
+#define CC120X_GPIO_STATUS              0x2F8C
+#define CC120X_FSCAL_CTRL               0x2F8D
+#define CC120X_PHASE_ADJUST             0x2F8E
+#define CC120X_PARTNUMBER               0x2F8F
+#define CC120X_PARTVERSION              0x2F90
+#define CC120X_SERIAL_STATUS            0x2F91
+#define CC120X_MODEM_STATUS1            0x2F92
+#define CC120X_MODEM_STATUS0            0x2F93
+#define CC120X_MARC_STATUS1             0x2F94
+#define CC120X_MARC_STATUS0             0x2F95
+#define CC120X_PA_IFAMP_TEST            0x2F96
+#define CC120X_FSRF_TEST                0x2F97
+#define CC120X_PRE_TEST                 0x2F98
+#define CC120X_PRE_OVR                  0x2F99
+#define CC120X_ADC_TEST                 0x2F9A
+#define CC120X_DVC_TEST                 0x2F9B
+#define CC120X_ATEST                    0x2F9C
+#define CC120X_ATEST_LVDS               0x2F9D
+#define CC120X_ATEST_MODE               0x2F9E
+#define CC120X_XOSC_TEST1               0x2F9F
+#define CC120X_XOSC_TEST0               0x2FA0
+#define CC120X_AES                      0x2FA1
+#define CC120X_MDM_TEST                 0x2FA2
+
+#define CC120X_RXFIRST                  0x2FD2
+#define CC120X_TXFIRST                  0x2FD3
+#define CC120X_RXLAST                   0x2FD4
+#define CC120X_TXLAST                   0x2FD5
+#define CC120X_NUM_TXBYTES              0x2FD6  /* Number of bytes in TXFIFO */
+#define CC120X_NUM_RXBYTES              0x2FD7  /* Number of bytes in RXFIFO */
+#define CC120X_FIFO_NUM_TXBYTES         0x2FD8
+#define CC120X_FIFO_NUM_RXBYTES         0x2FD9
+#define CC120X_RXFIFO_PRE_BUF           0x2FDA
+
+/* DATA FIFO Access */
+#define CC120X_SINGLE_TXFIFO            0x003F     /*  TXFIFO  - Single accecss to Transmit FIFO */
+#define CC120X_BURST_TXFIFO             0x007F     /*  TXFIFO  - Burst accecss to Transmit FIFO  */
+#define CC120X_SINGLE_RXFIFO            0x00BF     /*  RXFIFO  - Single accecss to Receive FIFO  */
+#define CC120X_BURST_RXFIFO             0x00FF     /*  RXFIFO  - Busrrst ccecss to Receive FIFO  */
+
+/* AES Workspace */
+/* AES Key */
+#define CC120X_AES_KEY                  0x2FE0     /*  AES_KEY    - Address for AES key input  */
+#define CC120X_AES_KEY15	        0x2FE0
+#define CC120X_AES_KEY14	        0x2FE1
+#define CC120X_AES_KEY13	        0x2FE2
+#define CC120X_AES_KEY12	        0x2FE3
+#define CC120X_AES_KEY11	        0x2FE4
+#define CC120X_AES_KEY10	        0x2FE5
+#define CC120X_AES_KEY9	                0x2FE6
+#define CC120X_AES_KEY8	                0x2FE7
+#define CC120X_AES_KEY7	                0x2FE8
+#define CC120X_AES_KEY6	                0x2FE9
+#define CC120X_AES_KEY5	                0x2FE10
+#define CC120X_AES_KEY4	                0x2FE11
+#define CC120X_AES_KEY3	                0x2FE12
+#define CC120X_AES_KEY2	                0x2FE13
+#define CC120X_AES_KEY1	                0x2FE14
+#define CC120X_AES_KEY0	                0x2FE15
+
+/* AES Buffer */
+#define CC120X_AES_BUFFER               0x2FF0     /*  AES_BUFFER - Address for AES Buffer     */
+#define CC120X_AES_BUFFER15		0x2FF0
+#define CC120X_AES_BUFFER14		0x2FF1
+#define CC120X_AES_BUFFER13		0x2FF2
+#define CC120X_AES_BUFFER12		0x2FF3
+#define CC120X_AES_BUFFER11		0x2FF4
+#define CC120X_AES_BUFFER10		0x2FF5
+#define CC120X_AES_BUFFER9		0x2FF6
+#define CC120X_AES_BUFFER8		0x2FF7
+#define CC120X_AES_BUFFER7		0x2FF8
+#define CC120X_AES_BUFFER6		0x2FF9
+#define CC120X_AES_BUFFER5		0x2FF10
+#define CC120X_AES_BUFFER4		0x2FF11
+#define CC120X_AES_BUFFER3		0x2FF12
+#define CC120X_AES_BUFFER2		0x2FF13
+#define CC120X_AES_BUFFER1		0x2FF14
+#define CC120X_AES_BUFFER0		0x2FF15
+
+#define CC120X_LQI_CRC_OK_BM            0x80
+#define CC120X_LQI_EST_BM               0x7F
+
+/* Command strobe registers */
+#define CC120X_SRES                     0x30      /*  SRES    - Reset chip. */
+#define CC120X_SFSTXON                  0x31      /*  SFSTXON - Enable and calibrate frequency synthesizer. */
+#define CC120X_SXOFF                    0x32      /*  SXOFF   - Turn off crystal oscillator. */
+#define CC120X_SCAL                     0x33      /*  SCAL    - Calibrate frequency synthesizer and turn it off. */
+#define CC120X_SRX                      0x34      /*  SRX     - Enable RX. Perform calibration if enabled. */
+#define CC120X_STX                      0x35      /*  STX     - Enable TX. If in RX state, only enable TX if CCA passes. */
+#define CC120X_SIDLE                    0x36      /*  SIDLE   - Exit RX / TX, turn off frequency synthesizer. */
+#define CC120X_SAFC                     0x37      /*  AFC     - Automatic Frequency Correction */
+#define CC120X_SWOR                     0x38      /*  SWOR    - Start automatic RX polling sequence (Wake-on-Radio) */
+#define CC120X_SPWD                     0x39      /*  SPWD    - Enter power down mode when CSn goes high. */
+#define CC120X_SFRX                     0x3A      /*  SFRX    - Flush the RX FIFO buffer. */
+#define CC120X_SFTX                     0x3B      /*  SFTX    - Flush the TX FIFO buffer. */
+#define CC120X_SWORRST                  0x3C      /*  SWORRST - Reset real time clock. */
+#define CC120X_SNOP                     0x3D      /*  SNOP    - No operation. Returns status byte. */
+
+/* Chip states returned in status byte */
+#define CC120X_STATE_IDLE               0x00
+#define CC120X_STATE_RX                 0x10
+#define CC120X_STATE_TX                 0x20
+#define CC120X_STATE_FSTXON             0x30
+#define CC120X_STATE_CALIBRATE          0x40
+#define CC120X_STATE_SETTLING           0x50
+#define CC120X_STATE_RXFIFO_ERROR       0x60
+#define CC120X_STATE_TXFIFO_ERROR       0x70
+#define CC120X_RDYn_BIT					BIT(7)
+
+/* FIFO Address */
+#define CC120X_FIFO						0x3F
+
+
+/* Data Structures */
+typedef uint8_t rf_status_t;
+
+typedef struct {
+	uint16_t addr;
+	uint8_t data;
+} cc1200_reg_settings_t;
+
+/* Public Functions */
+void cc1200_radio_init(const cc1200_reg_settings_t*, uint8_t);
+esp_err_t cc1200_radio_frequency(uint32_t);
+rf_status_t cc1200_radio_reset(void);
+esp_err_t cc1200_radio_sleep(void);
+void cc1200_radio_APRSTXPacket(void);
+void cc1200_radio_APRSRXPacket(void);
+
+
+#endif// CC120X_SPI_H
+
+

+ 77 - 0
main/cc1200_protocol.h

@@ -0,0 +1,77 @@
+/*
+ * CC120X_protocol.h
+ *
+ *  Created on: Apr 13, 2019
+ *      Author: curiousmuch
+ */
+
+
+// Address Config = No address check
+// Bit Rate = 0.825
+// Carrier Frequency = 144.174988
+// Deviation = 2.994537
+// Device Address = 0
+// Manchester Enable = false
+// Modulation Format = 2-FSK
+// Packet Bit Length = 0
+// Packet Length = 63
+// Packet Length Mode = Not supported
+// RX Filter BW = 14.880952
+// Symbol rate = 0.825
+// Whitening = false
+
+#include <stdio.h>
+#include <stdint.h>
+#include "cc1200.h"
+
+static const cc1200_reg_settings_t APRS_SETTINGS[]=
+{
+  {CC120X_IOCFG3,            0x1e},	// 0x1e for TX 0x1D for RX
+  {CC120X_IOCFG0,            0x09},
+  {CC120X_SYNC_CFG1,         0xAB},
+  {CC120X_DEVIATION_M,       0x9D},
+  {CC120X_MODCFG_DEV_E,      0x00},
+  {CC120X_DCFILT_CFG,        0x5D},
+  {CC120X_PREAMBLE_CFG1,     0x00},
+  {CC120X_PREAMBLE_CFG0,     0x8A},
+  {CC120X_IQIC,              0xCB},
+  {CC120X_CHAN_BW,           0x9C},
+  {CC120X_MDMCFG0,           0x05},
+  {CC120X_SYMBOL_RATE2,      0x35},
+  {CC120X_SYMBOL_RATE1,      0xA0},
+  {CC120X_SYMBOL_RATE0,      0x7B},
+  {CC120X_AGC_REF,           0x30},
+  {CC120X_AGC_CS_THR,        0xEC},
+  {CC120X_AGC_CFG1,          0x51},
+  {CC120X_AGC_CFG0,          0x87},
+  {CC120X_FIFO_CFG,          0x00},
+  {CC120X_FS_CFG,            0x1B},
+  {CC120X_PKT_CFG2,          0x02},
+  {CC120X_PKT_CFG1,          0x00},
+  {CC120X_PKT_CFG0,          0x40},
+  {CC120X_PA_CFG1,           0x3F},
+  {CC120X_PKT_LEN,           0x3F},
+  {CC120X_IF_MIX_CFG,        0x1C},
+  {CC120X_FREQOFF_CFG,       0x22},
+  {CC120X_MDMCFG2,           0x0D},		// need to set CFM_DATA_EN bit for CFM mode
+  {CC120X_FREQ2,             0x56},
+  {CC120X_FREQ1,             0x81},
+  {CC120X_FREQ0,             0x47},
+  {CC120X_IF_ADC1,           0xEE},
+  {CC120X_IF_ADC0,           0x10},
+  {CC120X_FS_DIG1,           0x07},
+  {CC120X_FS_DIG0,           0xAF},
+  {CC120X_FS_CAL1,           0x40},
+  {CC120X_FS_CAL0,           0x0E},
+  {CC120X_FS_DIVTWO,         0x03},
+  {CC120X_FS_DSM0,           0x33},
+  {CC120X_FS_DVC0,           0x17},
+  {CC120X_FS_PFD,            0x00},
+  {CC120X_FS_PRE,            0x6E},
+  {CC120X_FS_REG_DIV_CML,    0x1C},
+  {CC120X_FS_SPARE,          0xAC},
+  {CC120X_FS_VCO0,           0xB5},
+  {CC120X_XOSC5,             0x0E},
+  {CC120X_XOSC1,             0x03},
+};
+