Jamie Smith / Mbed OS CC1200-Examples

Dependencies:   CC1200

TestCC1200.cpp

Committer:
MultipleMonomials
Date:
2020-08-28
Revision:
1:7e7812669c9c
Parent:
0:ea2678a73bde
Child:
2:ff257762763e

File content as of revision 1:7e7812669c9c:

//
// Test suite for the CC1200 radio driver.
// Provides a menu to configure radio options, and
// attempts to send and receive a signal using two radios connected
// to the processor.
//

#include <mbed.h>
#include <SerialStream.h>

#include <CC1200.h>
#include <cinttypes>

// Pin definitions
// change these to match your board setup
#define PIN_SPI_MOSI P0_9
#define PIN_SPI_MISO P0_8
#define PIN_SPI_SCLK P0_7

#define PIN_TX_CS P0_6
#define PIN_TX_RST P0_29

#define PIN_RX_CS P0_4
#define PIN_RX_RST P0_30

BufferedSerial serial(USBTX, USBRX, 115200);
SerialStream<BufferedSerial> pc(serial);

CC1200 txRadio(PIN_SPI_MOSI, PIN_SPI_MISO, PIN_SPI_SCLK, PIN_TX_CS, PIN_TX_RST, &pc);
CC1200 rxRadio(PIN_SPI_MOSI, PIN_SPI_MISO, PIN_SPI_SCLK, PIN_RX_CS, PIN_RX_RST, &pc);

void checkExistance()
{
	pc.printf("Checking TX radio.....\n");
	bool txSuccess = txRadio.begin();
	pc.printf("TX radio initialized: %s\n", txSuccess ? "true" : "false");

	pc.printf("Checking RX radio.....\n");
	bool rxSuccess = rxRadio.begin();
	pc.printf("RX radio initialized: %s\n", rxSuccess ? "true" : "false");
}

void checkSignalTransmit()
{
	pc.printf("Initializing CC1200s.....\n");
	txRadio.begin();
	rxRadio.begin();

	pc.printf("Configuring RF settings.....\n");

	int config=-1;
	//MENU. ADD AN OPTION FOR EACH TEST.
	pc.printf("Select a config: \n");
	// This is similar to the SmartRF "100ksps ARIB Standard" configuration, except it doesn't use zero-if
	pc.printf("1.  915MHz 100ksps 2-GFSK DEV=50kHz CHF=208kHz\n");
	// This should be identical to the SmartRF "500ksps 4-GFSK Max Throughput ARIB Standard" configuration
	pc.printf("2.  915MHz 500ksps 4-GFSK DEV=400kHz CHF=1666kHz Zero-IF\n");
	pc.printf("3.  915MHz 38.4ksps 2-GFSK DEV=20kHz CHF=833kHz\n");
	pc.printf("4.  915MHz 100ksps 2-GFSK DEV=50kHz CHF=208kHz Fixed Length\n");


	pc.scanf("%d", &config);
	printf("Running test with config %d:\n\n", config);

	CC1200::PacketMode mode = CC1200::PacketMode::VARIABLE_LENGTH;
	CC1200::Band band = CC1200::Band::BAND_820_960MHz;
	float frequency = 915e6;
	const float txPower = 0;
	float fskDeviation;
	float symbolRate;
	float rxFilterBW;
	CC1200::ModFormat modFormat;
	uint8_t ifCfg = 0b101; // max IF
	bool imageCompEnabled = true;
	bool dcOffsetCorrEnabled = true;
	uint8_t agcRefLevel;

	uint8_t dcFiltSettingCfg = 1; // default chip setting
	uint8_t dcFiltCutoffCfg = 4; // default chip setting

	CC1200::SyncMode syncMode = CC1200::SyncMode::SYNC_32_BITS;
	uint32_t syncWord = 0x930B51DE; // default sync word
	uint8_t syncThreshold = 8; // TI seems to recommend this threshold for most configs above 100ksps

	uint8_t preableLengthCfg = 5; // default chip setting
	uint8_t preambleFormatCfg = 0; // default chip setting

	if(config == 1)
	{
		fskDeviation = 49896;
		symbolRate = 100000;
		rxFilterBW = 208300;
		modFormat = CC1200::ModFormat::GFSK_2;
		agcRefLevel = 0x2A;
	}
	else if(config == 2)
	{
		// SmartRF "500ksps 4-GFSK ARIB standard" config
		fskDeviation = 399169;
		symbolRate = 500000;
		rxFilterBW = 1666700;
		ifCfg = 0;
		imageCompEnabled = false;
		dcOffsetCorrEnabled = true;
		modFormat = CC1200::ModFormat::GFSK_4;
		agcRefLevel = 0x2F;
	}
	else if(config == 3)
	{
		fskDeviation = 19989;
		symbolRate = 38400;
		rxFilterBW = 104200;
		modFormat = CC1200::ModFormat::GFSK_2;
		agcRefLevel = 0x27;
	}
	else if(config == 4)
	{
		fskDeviation = 49896;
		symbolRate = 100000;
		rxFilterBW = 208300;
		modFormat = CC1200::ModFormat::GFSK_2;
		agcRefLevel = 0x2A;
		mode = CC1200::PacketMode::FIXED_LENGTH;
	}
	else
	{
		pc.printf("Invalid config number!");
		return;
	}

	for(CC1200 & radio : {std::ref(txRadio), std::ref(rxRadio)})
	{

		radio.configureFIFOMode();
		radio.setPacketMode(mode);
		radio.setModulationFormat(modFormat);
		radio.setFSKDeviation(fskDeviation);
		radio.setSymbolRate(symbolRate);
		radio.setOutputPower(txPower);
		radio.setRadioFrequency(band, frequency);
		radio.setIFMixCFG(ifCfg);
		radio.configureDCFilter(dcOffsetCorrEnabled, dcFiltSettingCfg, dcFiltCutoffCfg);
		radio.setIQMismatchCompensationEnabled(imageCompEnabled);
		radio.setRXFilterBandwidth(rxFilterBW);
		radio.configureSyncWord(syncWord, syncMode, syncThreshold);
		radio.configurePreamble(preableLengthCfg, preambleFormatCfg);

		// AGC configuration (straight from SmartRF)
		radio.setAGCReferenceLevel(agcRefLevel);
		radio.setAGCSyncBehavior(CC1200::SyncBehavior::FREEZE_NONE);
		if(ifCfg == 0)
		{
			radio.setAGCGainTable(CC1200::GainTable::ZERO_IF, 11, 0);
		}
		else
		{
			// enable all AGC steps for NORMAL mode
			radio.setAGCGainTable(CC1200::GainTable::NORMAL, 17, 0);
		}
		radio.setAGCHysteresis(0b10);
		radio.setAGCSlewRate(0);
	}

	// configure on-transmit actions
	txRadio.setOnTransmitState(CC1200::State::TX);
	rxRadio.setOnReceiveState(CC1200::State::RX, CC1200::State::RX);

	pc.printf("Starting transmission.....\n");

	txRadio.startTX();
	rxRadio.startRX();

	const char message[] = "Hello world!";
	char receiveBuffer[sizeof(message)];

	if(mode == CC1200::PacketMode::FIXED_LENGTH)
	{
		txRadio.setPacketLength(sizeof(message) - 1);
		rxRadio.setPacketLength(sizeof(message) - 1);
	}

	while(true)
	{
		ThisThread::sleep_for(1s);

		pc.printf("\n---------------------------------\n");

		pc.printf("<<SENDING: %s\n", message);
		txRadio.enqueuePacket(message, sizeof(message) - 1);


		// update TX radio
		pc.printf("TX radio: state = 0x%" PRIx8 ", TX FIFO len = %zu, FS lock = 0x%u\n",
				  static_cast<uint8_t>(txRadio.getState()), txRadio.getTXFIFOLen(), txRadio.readRegister(CC1200::ExtRegister::FSCAL_CTRL) & 1);

		// wait a while for the packet to come in.
		ThisThread::sleep_for(10ms);

		// wait the time we expect the message to take, with a safety factor of 2
		auto timeoutTime = std::chrono::microseconds(static_cast<int64_t>((1/symbolRate) * 1e-6f * sizeof(message) * 2));

		Timer packetReceiveTimeout;
		packetReceiveTimeout.start();
		bool hasPacket;
		do
		{
			hasPacket = rxRadio.hasReceivedPacket();
		}
		while(packetReceiveTimeout.elapsed_time() < timeoutTime && !hasPacket);

		pc.printf("RX radio: state = 0x%" PRIx8 ", RX FIFO len = %zu\n",
				  static_cast<uint8_t>(rxRadio.getState()), rxRadio.getRXFIFOLen());
		if(hasPacket)
		{
			rxRadio.receivePacket(receiveBuffer, sizeof(message) - 1);
			receiveBuffer[sizeof(message)-1] = '\0';
			pc.printf(">>RECEIVED: %s\n", receiveBuffer);
		}
		else
		{
			pc.printf(">>No packet received!\n");
		}
	}
}


int main()
{
	pc.printf("\nCC1200 Radio Test Suite:\n");

	while(1){
		int test=-1;
		//MENU. ADD AN OPTION FOR EACH TEST.
		pc.printf("Select a test: \n");
		pc.printf("1.  Exit Test Suite\n");
		pc.printf("2.  Check Existence\n");
		pc.printf("3.  Check Transmitting Signal\n");

		pc.scanf("%d", &test);
		printf("Running test %d:\n\n", test);
		//SWITCH. ADD A CASE FOR EACH TEST.
		switch(test) {
			case 1:         pc.printf("Exiting test suite.\n");    return 0;
			case 2:         checkExistance();              break;
			case 3:         checkSignalTransmit();              break;
			default:        pc.printf("Invalid test number. Please run again.\n"); continue;
		}
		pc.printf("done.\r\n");
	}

	return 0;

}