1
0
mirror of https://github.com/peterantypas/maiana.git synced 2025-05-20 09:20:10 -07:00
2020-10-02 18:40:04 -07:00

195 lines
4.0 KiB
C++

/*
* RFIC.cpp
*
* Created on: May 21, 2016
* Author: peter
*/
#include "RFIC.hpp"
#include "radio_config.h"
#include "Utils.hpp"
#include "printf2.h"
#include "EZRadioPRO.h"
#include <cstring>
#include "_assert.h"
RFIC::RFIC( SPI_TypeDef *spi,
GPIO_TypeDef *sdnPort,
uint16_t sdnPin,
GPIO_TypeDef *csPort,
uint16_t csPin,
GPIO_TypeDef *gpio1Port,
uint16_t gpio1Pin,
GPIO_TypeDef *gpio3Port,
uint16_t gpio3Pin)
{
mSPI = spi;
mSDNP = sdnPort;
mCSP = csPort;
mGPIO1P = gpio1Port;
mGPIO3P = gpio3Port;
mSDNPin = sdnPin;
mCSPin = csPin;
mGPIO1Pin = gpio1Pin;
mGPIO3Pin = gpio3Pin;
mRSSIAdjustment = 0;
mSPIBusy = false;
if ( !isUp() )
powerOnReset();
}
RFIC::~RFIC()
{
}
void RFIC::setRSSIAdjustment(short adj)
{
mRSSIAdjustment = adj;
}
void RFIC::spiOn()
{
GPIO_ResetBits(mCSP, mCSPin);
}
void RFIC::spiOff()
{
GPIO_SetBits(mCSP, mCSPin);
}
uint8_t RFIC::sendSPIByte(uint8_t data)
{
/*
* See this URL for an explanation:
http://www.eevblog.com/forum/microcontrollers/stm32f0-spi-8bit-communication-frame-(errata)/
*/
while((mSPI->SR & SPI_I2S_FLAG_TXE)==RESET)
;
SPI_SendData8(mSPI, data);
while((mSPI->SR & SPI_I2S_FLAG_RXNE)==RESET)
;
return SPI_ReceiveData8(mSPI);
}
void RFIC::sendCmd(uint8_t cmd, void* params, uint8_t paramLen, void* result, uint8_t resultLen)
{
ASSERT(!mSPIBusy);
mSPIBusy = true;
spiOn();
sendSPIByte(cmd);
uint8_t *b = (uint8_t*) params;
for ( int i = 0; i < paramLen; ++i ) {
sendSPIByte(b[i]);
}
spiOff(); // The Si446x needs CS asserted after every request to trigger an internal interrupt
while (receiveSPIData(result, resultLen) == false)
; // wait for valid response
mSPIBusy = false;
}
// This is borrowed from the dAISy project. Thank you Adrian :)
bool RFIC::receiveSPIData(void *data, uint8_t length)
{
spiOn();
sendSPIByte(0x44);
if ( sendSPIByte(0) != 0xff ) {
spiOff();
return false;
}
uint8_t* b = (uint8_t*) data;
uint8_t i = 0;
while (i < length) {
b[i] = sendSPIByte(0);
++i;
}
spiOff();
return true;
}
void RFIC::configure()
{
uint8_t radio_configuration[] = RADIO_CONFIGURATION_DATA_ARRAY;
uint8_t *cfg = radio_configuration;
while (*cfg) { // configuration array stops with 0
uint8_t count = (*cfg++) - 1; // 1st byte: number of bytes, incl. command
uint8_t cmd = *cfg++; // 2nd byte: command
sendCmd(cmd, cfg, count, NULL, 0); // send bytes to chip
cfg += count; // point at next line
}
}
bool RFIC::isUp()
{
GPIO_SetBits(mSDNP, mSDNPin);
Utils::delay(1000000);
GPIO_ResetBits(mSDNP, mSDNPin);
Utils::delay(10000000);
printf2("Checking RF chip status\r\n");
CHIP_STATUS_REPLY chip_status;
memset(&chip_status, 0, sizeof chip_status);
sendCmd(GET_CHIP_STATUS, NULL, 0, &chip_status, sizeof chip_status);
printf2("Chip status: %.2x\r\n", chip_status.Current);
if ( chip_status.Current & 0x08 ) {
return false;
}
else {
return true;
}
}
void RFIC::powerOnReset()
{
// Put SDN high
GPIO_SetBits(mSDNP, mSDNPin);
// Wait at least 10 microseconds
Utils::delay(500000);
// Put SDN low and poll the status of GPIO1
GPIO_ResetBits(mSDNP, mSDNPin);
printf2("Waiting for GPIO1\r\n");
while ( GPIO_ReadInputDataBit(mGPIO1P, mGPIO1Pin) == 0 )
;
// We're done!
printf2("Radio Ready!\r\n");
}
uint8_t RFIC::readRSSI()
{
MODEM_STATUS_REPLY s;
sendCmd(GET_MODEM_STATUS, NULL, 0, &s, sizeof s);
return s.CurrentRSSI;
}
bool RFIC::checkStatus()
{
DEVICE_STATE s;
sendCmd(REQ_DEVICE_STATE, NULL, 0, &s, sizeof s);
if ( s.state != 8 && s.state != 7 )
return false;
else
return true;
}