862 lines
21 KiB
C++
862 lines
21 KiB
C++
|
/*
|
||
|
* Functions for using SX127x in FSK mode (mainly receive)
|
||
|
* Copyright (C) 2019 Hansi Reiser, dl9rdz
|
||
|
*
|
||
|
* Partially based on the SX1278 libraray for managing Semtech modules
|
||
|
* Copyright (C) 2015 Wireless Open Source
|
||
|
* http://wirelessopensource.com
|
||
|
*
|
||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||
|
*/
|
||
|
|
||
|
#include "SX1278FSK.h"
|
||
|
#include "SPI.h"
|
||
|
#include <Sonde.h>
|
||
|
#include <Display.h>
|
||
|
|
||
|
SX1278FSK::SX1278FSK()
|
||
|
{
|
||
|
// Initialize class variables
|
||
|
};
|
||
|
|
||
|
|
||
|
static SPISettings spiset = SPISettings(40000000L, MSBFIRST, SPI_MODE0);
|
||
|
|
||
|
/*
|
||
|
Function: Turns the module ON.
|
||
|
Returns: 0 on success, 1 otherwise
|
||
|
*/
|
||
|
uint8_t SX1278FSK::ON()
|
||
|
{
|
||
|
uint8_t state = 2;
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.println();
|
||
|
Serial.println(F("Starting 'ON'"));
|
||
|
#endif
|
||
|
|
||
|
// Powering the module
|
||
|
pinMode(SX1278_SS, OUTPUT);
|
||
|
digitalWrite(SX1278_SS, HIGH);
|
||
|
|
||
|
//Configure the MISO, MOSI, CS, SPCR.
|
||
|
SPI.begin();
|
||
|
//Set most significant bit first
|
||
|
SPI.setBitOrder(MSBFIRST);
|
||
|
//Divide the clock frequency
|
||
|
SPI.setClockDivider(SPI_CLOCK_DIV2);
|
||
|
//Set data mode
|
||
|
SPI.setDataMode(SPI_MODE0);
|
||
|
|
||
|
// Set Maximum Over Current Protection
|
||
|
state = setMaxCurrent(0x1B);
|
||
|
if( state == 0 )
|
||
|
{
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.println(F("## Setting ON with maximum current supply ##"));
|
||
|
Serial.println();
|
||
|
#endif
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
// set FSK mode
|
||
|
state = setFSK();
|
||
|
return state;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Function: Turn the module OFF.
|
||
|
Returns: Nothing
|
||
|
*/
|
||
|
void SX1278FSK::OFF()
|
||
|
{
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.println();
|
||
|
Serial.println(F("Starting 'OFF'"));
|
||
|
#endif
|
||
|
|
||
|
SPI.end();
|
||
|
// Powering the module
|
||
|
pinMode(SX1278_SS,OUTPUT);
|
||
|
digitalWrite(SX1278_SS,LOW);
|
||
|
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.println(F("## Setting OFF ##"));
|
||
|
Serial.println();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Function: Reads the indicated register.
|
||
|
Returns: The content of the register
|
||
|
Parameters:
|
||
|
address: address register to read from
|
||
|
*/
|
||
|
byte SX1278FSK::readRegister(byte address)
|
||
|
{
|
||
|
byte value = 0x00;
|
||
|
|
||
|
SPI.beginTransaction(spiset);
|
||
|
digitalWrite(SX1278_SS,LOW);
|
||
|
|
||
|
//delay(1);
|
||
|
bitClear(address, 7); // Bit 7 cleared to write in registers
|
||
|
SPI.transfer(address);
|
||
|
value = SPI.transfer(0x00);
|
||
|
digitalWrite(SX1278_SS,HIGH);
|
||
|
SPI.endTransaction();
|
||
|
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
if(address!=0x3F) {
|
||
|
Serial.print(F("## Reading: ##\t"));
|
||
|
Serial.print(F("Register "));
|
||
|
Serial.print(address, HEX);
|
||
|
Serial.print(F(": "));
|
||
|
Serial.print(value, HEX);
|
||
|
Serial.println();
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Function: Writes on the indicated register.
|
||
|
Returns: Nothing
|
||
|
Parameters:
|
||
|
address: address register to write in
|
||
|
data: value to write in the register
|
||
|
*/
|
||
|
void SX1278FSK::writeRegister(byte address, byte data)
|
||
|
{
|
||
|
SPI.beginTransaction(spiset);
|
||
|
digitalWrite(SX1278_SS,LOW);
|
||
|
|
||
|
//delay(1);
|
||
|
bitSet(address, 7); // Bit 7 set to read from registers
|
||
|
SPI.transfer(address);
|
||
|
SPI.transfer(data);
|
||
|
digitalWrite(SX1278_SS,HIGH);
|
||
|
SPI.endTransaction();
|
||
|
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.print(F("## Writing: ##\t"));
|
||
|
Serial.print(F("Register "));
|
||
|
bitClear(address, 7);
|
||
|
Serial.print(address, HEX);
|
||
|
Serial.print(F(": "));
|
||
|
Serial.print(data, HEX);
|
||
|
Serial.println();
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Function: Clears the IRQ flags
|
||
|
*
|
||
|
* Configuration registers are accessed through the SPI interface.
|
||
|
* Registers are readable in all device mode including Sleep. However, they
|
||
|
* should be written only in Sleep and Stand-by modes.
|
||
|
*
|
||
|
* Returns: Nothing
|
||
|
*/
|
||
|
void SX1278FSK::clearIRQFlags()
|
||
|
{
|
||
|
byte st0;
|
||
|
|
||
|
// Save the previous status
|
||
|
st0 = readRegister(REG_OP_MODE);
|
||
|
// Stdby mode to write in registers
|
||
|
writeRegister(REG_OP_MODE, FSK_STANDBY_MODE);
|
||
|
// FSK mode flags1 register
|
||
|
writeRegister(REG_IRQ_FLAGS1, 0xFF);
|
||
|
// FSK mode flags2 register
|
||
|
writeRegister(REG_IRQ_FLAGS2, 0xFF);
|
||
|
// Getting back to previous status
|
||
|
if(st0 != FSK_STANDBY_MODE) {
|
||
|
writeRegister(REG_OP_MODE, st0);
|
||
|
}
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.println(F("## FSK flags cleared ##"));
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Function: Sets the module in FSK mode.
|
||
|
Returns: Integer that determines if there has been any error
|
||
|
state = 2 --> The command has not been executed
|
||
|
state = 1 --> There has been an error while executing the command
|
||
|
state = 0 --> The command has been executed with no errors
|
||
|
*/
|
||
|
uint8_t SX1278FSK::setFSK()
|
||
|
{
|
||
|
uint8_t state = 2;
|
||
|
byte st0;
|
||
|
byte config1;
|
||
|
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.println();
|
||
|
Serial.println(F("Starting 'setFSK'"));
|
||
|
#endif
|
||
|
|
||
|
writeRegister(REG_OP_MODE, FSK_SLEEP_MODE); // Sleep mode (mandatory to change mode)
|
||
|
// If we are in LORA mode, above line activate Sleep mode, but does not change mode to FSK
|
||
|
// as mode change is only allowed in sleep mode. Next line changes to FSK
|
||
|
writeRegister(REG_OP_MODE, FSK_SLEEP_MODE);
|
||
|
|
||
|
writeRegister(REG_OP_MODE, FSK_STANDBY_MODE); // FSK standby mode
|
||
|
|
||
|
//writeRegister(REG_FIFO_THRESH, 0x80); // condition to start packet tx
|
||
|
//config1 = readRegister(REG_SYNC_CONFIG);
|
||
|
//config1 = config1 & B00111111;
|
||
|
//writeRegister(REG_SYNC_CONFIG,config1);
|
||
|
|
||
|
delay(100);
|
||
|
|
||
|
st0 = readRegister(REG_OP_MODE); // Reading config mode
|
||
|
if( st0 == FSK_STANDBY_MODE )
|
||
|
{ // FSK mode
|
||
|
state = 0;
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.println(F("## FSK set with success ##"));
|
||
|
Serial.println();
|
||
|
#endif
|
||
|
} else { // LoRa mode
|
||
|
state = 1;
|
||
|
Serial.println( st0 );
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.println(F("** There has been an error while setting FSK **"));
|
||
|
Serial.println();
|
||
|
#endif
|
||
|
}
|
||
|
return state;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Function: Sets FSK bitrate
|
||
|
* Returns: 0 for success, >0 in case of error
|
||
|
* Parameters: bps: requested bitrate
|
||
|
* (raw data rate, for Mancester encoding, the effective bitrate is bps/2)
|
||
|
*/
|
||
|
|
||
|
uint8_t SX1278FSK::setBitrate(float bps)
|
||
|
{
|
||
|
// TODO: Check if FSK mode is active
|
||
|
|
||
|
// check if bitrate is allowed allowed bitrate
|
||
|
if((bps < 1200) || (bps > 300000)) {
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
// set mode to FSK STANDBY
|
||
|
writeRegister(REG_OP_MODE, FSK_STANDBY_MODE);
|
||
|
|
||
|
// set bit rate
|
||
|
uint16_t bitRate = (SX127X_CRYSTAL_FREQ * 1.0) / bps;
|
||
|
writeRegister(REG_BITRATE_MSB, (bitRate & 0xFF00) >> 8);
|
||
|
writeRegister(REG_BITRATE_LSB, (bitRate & 0x00FF));
|
||
|
|
||
|
// also set fractional part
|
||
|
uint16_t fracRate = (SX127X_CRYSTAL_FREQ * 16.0) / bps - bitRate * 16 + 0.5;
|
||
|
writeRegister(REG_BIT_RATE_FRAC, fracRate&0x0F);
|
||
|
return 0;
|
||
|
}
|
||
|
/* Function: Gets configured bitrate
|
||
|
* Returns bitrate in bit/second
|
||
|
*/
|
||
|
float SX1278FSK::getBitrate()
|
||
|
{
|
||
|
uint8_t fmsb = readRegister(REG_BITRATE_MSB);
|
||
|
uint8_t flsb = readRegister(REG_BITRATE_LSB);
|
||
|
uint8_t ffrac = readRegister(REG_BIT_RATE_FRAC) & 0x0F;
|
||
|
return SX127X_CRYSTAL_FREQ / ( (fmsb<<8) + flsb + ffrac / 16.0 );
|
||
|
}
|
||
|
|
||
|
//typedef struct rxbwset { float bw; uint8_t mant; uint8_t rxp; } st_rxbwsettings;
|
||
|
|
||
|
uint8_t SX1278FSK::setRxBandwidth(float bw)
|
||
|
{
|
||
|
// TODO: Check if in FSK mode
|
||
|
//
|
||
|
if(bw<2600 || bw>250000) { return 1; /* invalid */ }
|
||
|
|
||
|
uint8_t rxbwexp = 1;
|
||
|
bw = SX127X_CRYSTAL_FREQ / bw / 8;
|
||
|
while(bw>31) { rxbwexp++; bw/=2.0; }
|
||
|
uint8_t rxbwmant = bw<17?0 : bw<21? 1:2;
|
||
|
|
||
|
// set mode to FSK STANDBY
|
||
|
writeRegister(REG_OP_MODE, FSK_STANDBY_MODE);
|
||
|
|
||
|
writeRegister(REG_RX_BW, rxbwexp | (rxbwmant<<3));
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
float SX1278FSK::getRxBandwidth()
|
||
|
{
|
||
|
uint8_t rxbw = readRegister(REG_RX_BW);
|
||
|
uint8_t rxbwexp = rxbw&0x07;
|
||
|
uint8_t rxbwmant = (rxbw>>3)&0x03;
|
||
|
rxbwmant = 16 + 4*rxbwmant;
|
||
|
return SX127X_CRYSTAL_FREQ / ( rxbwmant << (rxbwexp+2));
|
||
|
}
|
||
|
|
||
|
uint8_t SX1278FSK::setAFCBandwidth(float bw)
|
||
|
{
|
||
|
// TODO: Check if in FSK mode
|
||
|
//
|
||
|
if(bw<2600 || bw>250000) { return 1; /* invalid */ }
|
||
|
|
||
|
uint8_t rxbwexp = 1;
|
||
|
bw = SX127X_CRYSTAL_FREQ / bw / 8;
|
||
|
while(bw>31) { rxbwexp++; bw/=2.0; }
|
||
|
uint8_t rxbwmant = bw<17?0 : bw<21? 1:2;
|
||
|
|
||
|
// set mode to FSK STANDBY
|
||
|
writeRegister(REG_OP_MODE, FSK_STANDBY_MODE);
|
||
|
|
||
|
writeRegister(REG_AFC_BW, rxbwexp | (rxbwmant<<3));
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
float SX1278FSK::getAFCBandwidth()
|
||
|
{
|
||
|
uint8_t rxbw = readRegister(REG_AFC_BW);
|
||
|
uint8_t rxbwexp = rxbw&0x07;
|
||
|
uint8_t rxbwmant = (rxbw>>3)&0x03;
|
||
|
rxbwmant = 16 + 4*rxbwmant;
|
||
|
return SX127X_CRYSTAL_FREQ / ( rxbwmant << (rxbwexp+2));
|
||
|
}
|
||
|
|
||
|
|
||
|
uint8_t SX1278FSK::setFrequency(float freq) {
|
||
|
|
||
|
// set mode to FSK STANDBY
|
||
|
writeRegister(REG_OP_MODE, FSK_STANDBY_MODE);
|
||
|
freq += sonde.config.freqofs; // manual frequency correction
|
||
|
|
||
|
uint32_t frf = freq * 1.0 * (1<<19) / SX127X_CRYSTAL_FREQ;
|
||
|
writeRegister(REG_FRF_MSB, (frf&0xff0000)>>16);
|
||
|
writeRegister(REG_FRF_MID, (frf&0x00ff00)>>8);
|
||
|
writeRegister(REG_FRF_LSB, (frf&0x0000ff));
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
float SX1278FSK::getFrequency() {
|
||
|
uint8_t fmsb = readRegister(REG_FRF_MSB);
|
||
|
uint8_t fmid = readRegister(REG_FRF_MID);
|
||
|
uint8_t flsb = readRegister(REG_FRF_LSB);
|
||
|
return ((fmsb<<16)|(fmid<<8)|flsb) * 1.0 / (1<<19) * SX127X_CRYSTAL_FREQ;
|
||
|
}
|
||
|
|
||
|
|
||
|
static int gaintab[]={-999,0,-6,-12,-24,-36,-48,-999};
|
||
|
int SX1278FSK::getLNAGain() {
|
||
|
int gain = (readRegister(REG_LNA)>>5)&0x07;
|
||
|
return gaintab[gain];
|
||
|
}
|
||
|
uint8_t SX1278FSK::setLNAGain(int gain) {
|
||
|
uint8_t g=1;
|
||
|
while(gain<gaintab[g] && g<6) {g++; }
|
||
|
writeRegister(REG_LNA, g<<5);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
uint8_t SX1278FSK::getRxConf() {
|
||
|
return readRegister(REG_RX_CONFIG);
|
||
|
}
|
||
|
uint8_t SX1278FSK::setRxConf(uint8_t conf) {
|
||
|
writeRegister(REG_RX_CONFIG, conf);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
uint8_t SX1278FSK::setSyncConf(uint8_t conf, int len, const uint8_t *syncpattern) {
|
||
|
int res=0;
|
||
|
writeRegister(REG_SYNC_CONFIG, conf);
|
||
|
if(len>8) return 1;
|
||
|
for(int i=0; i<len; i++) {
|
||
|
writeRegister(REG_SYNC_VALUE1+i, syncpattern[i]);
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
uint8_t SX1278FSK::getSyncConf() {
|
||
|
return sx1278.readRegister(REG_SYNC_CONFIG);
|
||
|
}
|
||
|
|
||
|
uint8_t SX1278FSK::setPreambleDetect(uint8_t conf) {
|
||
|
sx1278.writeRegister(REG_PREAMBLE_DETECT, conf);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
uint8_t SX1278FSK::getPreambleDetect() {
|
||
|
return sx1278.readRegister(REG_PREAMBLE_DETECT);
|
||
|
}
|
||
|
|
||
|
uint8_t SX1278FSK::setPacketConfig(uint8_t conf1, uint8_t conf2)
|
||
|
{
|
||
|
uint8_t ret=0;
|
||
|
sx1278.writeRegister(REG_PACKET_CONFIG1, conf1);
|
||
|
sx1278.writeRegister(REG_PACKET_CONFIG2, conf2);
|
||
|
return ret;
|
||
|
};
|
||
|
uint16_t SX1278FSK::getPacketConfig() {
|
||
|
uint8_t c1 = sx1278.readRegister(REG_PACKET_CONFIG1);
|
||
|
uint8_t c2 = sx1278.readRegister(REG_PACKET_CONFIG2);
|
||
|
return (c2<<8)|c1;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Function: Gets the preamble length from the module.
|
||
|
Returns: preamble length
|
||
|
*/
|
||
|
uint16_t SX1278FSK::getPreambleLength()
|
||
|
{
|
||
|
uint16_t p_length;
|
||
|
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.println();
|
||
|
Serial.println(F("Starting 'getPreambleLength'"));
|
||
|
#endif
|
||
|
|
||
|
p_length = readRegister(REG_PREAMBLE_MSB_FSK);
|
||
|
p_length = (p_length<<8) | readRegister(REG_PREAMBLE_LSB_FSK);
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.print(F("## Preamble length configured is "));
|
||
|
Serial.print(p_length, HEX);
|
||
|
Serial.print(F(" ##"));
|
||
|
Serial.println();
|
||
|
#endif
|
||
|
return p_length;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Function: Sets the preamble length in the module
|
||
|
Returns: Integer that determines if there has been any error
|
||
|
state = 2 --> The command has not been executed
|
||
|
state = 1 --> There has been an error while executing the command
|
||
|
state = 0 --> The command has been executed with no errors
|
||
|
Parameters:
|
||
|
l: length value to set as preamble length.
|
||
|
*/
|
||
|
uint8_t SX1278FSK::setPreambleLength(uint16_t l)
|
||
|
{
|
||
|
byte st0;
|
||
|
int8_t state = 2;
|
||
|
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.println();
|
||
|
Serial.println(F("Starting 'setPreambleLength'"));
|
||
|
#endif
|
||
|
|
||
|
st0 = readRegister(REG_OP_MODE); // Save the previous status
|
||
|
|
||
|
writeRegister(REG_OP_MODE, FSK_STANDBY_MODE); // Set Standby mode to write in registers
|
||
|
// Storing MSB preamble length in FSK mode
|
||
|
writeRegister(REG_PREAMBLE_MSB_FSK, l>>8);
|
||
|
writeRegister(REG_PREAMBLE_LSB_FSK, l&0xFF);
|
||
|
|
||
|
state = 0;
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.print(F("## Preamble length "));
|
||
|
Serial.print(l, HEX);
|
||
|
Serial.println(F(" has been successfully set ##"));
|
||
|
Serial.println();
|
||
|
#endif
|
||
|
|
||
|
if(st0 != FSK_STANDBY_MODE) {
|
||
|
writeRegister(REG_OP_MODE, st0); // Getting back to previous status
|
||
|
}
|
||
|
return state;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Function: Gets the payload length from the module.
|
||
|
Returns: configured length; -1 on error
|
||
|
*/
|
||
|
int SX1278FSK::getPayloadLength()
|
||
|
{
|
||
|
int length;
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.println();
|
||
|
Serial.println(F("Starting 'getPayloadLength'"));
|
||
|
#endif
|
||
|
length = readRegister(REG_PAYLOAD_LENGTH_FSK);
|
||
|
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.print(F("## Payload length configured is "));
|
||
|
Serial.print(length);
|
||
|
Serial.println(F(" ##"));
|
||
|
#endif
|
||
|
return length;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Function: Sets the payload length from the module.
|
||
|
Returns: 0 for ok, otherwise error
|
||
|
// TODO: Larger than 255 bytes?
|
||
|
*/
|
||
|
uint8_t SX1278FSK::setPayloadLength(int len)
|
||
|
{
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.print(F("Starting 'setPayloadLength'"));
|
||
|
Serial.println(len);
|
||
|
#endif
|
||
|
uint8_t conf2 = readRegister(REG_PACKET_CONFIG2);
|
||
|
conf2 = (conf2 & 0xF8) | ( (len>>8)&0x7 );
|
||
|
writeRegister(REG_PACKET_CONFIG2, conf2);
|
||
|
writeRegister(REG_PAYLOAD_LENGTH_FSK, len&0xFF);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Function: Gets the current value of RSSI.
|
||
|
Returns: RSSI value
|
||
|
*/
|
||
|
int16_t SX1278FSK::getRSSI()
|
||
|
{
|
||
|
int16_t RSSI;
|
||
|
//int rssi_mean = 0;
|
||
|
int total = 1;
|
||
|
|
||
|
/// FSK mode
|
||
|
// get mean value of RSSI
|
||
|
for(int i = 0; i < total; i++)
|
||
|
{
|
||
|
RSSI = readRegister(REG_RSSI_VALUE_FSK);
|
||
|
//rssi_mean += _RSSI;
|
||
|
}
|
||
|
//rssi_mean = rssi_mean / total;
|
||
|
//RSSI = rssi_mean;
|
||
|
|
||
|
#if (SX1278FSK_debug_mode > 0)
|
||
|
Serial.print(F("## RSSI value is "));
|
||
|
Serial.print(RSSI);
|
||
|
Serial.println(F(" ##"));
|
||
|
#endif
|
||
|
return RSSI;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Function: Gets the current value of FEI (frequency error indication)
|
||
|
Returns: FEI value in Hz
|
||
|
*/
|
||
|
int32_t SX1278FSK::getFEI()
|
||
|
{
|
||
|
int32_t FEI;
|
||
|
int16_t regval = (readRegister(REG_FEI_MSB)<<8) | readRegister(REG_FEI_LSB);
|
||
|
//Serial.printf("feireg: %04x\n", regval);
|
||
|
FEI = (int32_t)(regval * SX127X_FSTEP);
|
||
|
return FEI;
|
||
|
}
|
||
|
/*
|
||
|
Function: Gets the current value of AFC (automated frequency correction)
|
||
|
Returns: AFC value in Hz
|
||
|
*/
|
||
|
int32_t SX1278FSK::getAFC()
|
||
|
{
|
||
|
int32_t AFC;
|
||
|
int16_t regval = (readRegister(REG_AFC_MSB)<<8) | readRegister(REG_AFC_LSB);
|
||
|
//Serial.printf("afcreg: %04x\n", regval);
|
||
|
AFC = (int32_t)(regval * SX127X_FSTEP);
|
||
|
return AFC;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Function: Gets the current supply limit of the power amplifier, protecting battery chemistries.
|
||
|
Returns: Integer that determines if there has been any error
|
||
|
state = 2 --> The command has not been executed
|
||
|
state = 1 --> There has been an error while executing the command
|
||
|
state = 0 --> The command has been executed with no errors
|
||
|
Parameters:
|
||
|
rate: value to compute the maximum current supply. Maximum current is 45+5*'rate' [mA]
|
||
|
*/
|
||
|
int SX1278FSK::getMaxCurrent()
|
||
|
{
|
||
|
int value;
|
||
|
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.println();
|
||
|
Serial.println(F("Starting 'getMaxCurrent'"));
|
||
|
#endif
|
||
|
|
||
|
value = readRegister(REG_OCP);
|
||
|
|
||
|
// extract only the OcpTrim value from the OCP register
|
||
|
value &= B00011111;
|
||
|
|
||
|
if( value <= 15 ) {
|
||
|
value = (45 + (5 * value));
|
||
|
} else if( value <= 27 ) {
|
||
|
value = (-30 + (10 * value));
|
||
|
} else {
|
||
|
value = 240;
|
||
|
}
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.print(F("## Maximum current supply configured is "));
|
||
|
Serial.print(value, DEC);
|
||
|
Serial.println(F(" mA ##"));
|
||
|
Serial.println();
|
||
|
#endif
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Function: Limits the current supply of the power amplifier, protecting battery chemistries.
|
||
|
Returns: Integer that determines if there has been any error
|
||
|
state = 2 --> The command has not been executed
|
||
|
state = 1 --> There has been an error while executing the command
|
||
|
state = 0 --> The command has been executed with no errors
|
||
|
state = -1 --> Forbidden parameter value for this function
|
||
|
Parameters:
|
||
|
rate: value to compute the maximum current supply. Range: 0x00 to 0x1B. The
|
||
|
Maximum current is:
|
||
|
Imax = 45+5*OcpTrim [mA] if OcpTrim <= 15 (120 mA) /
|
||
|
Imax = -30+10*OcpTrim [mA] if 15 < OcpTrim <= 27 (130 to 240 mA)
|
||
|
Imax = 240mA for higher settings
|
||
|
*/
|
||
|
int8_t SX1278FSK::setMaxCurrent(uint8_t rate)
|
||
|
{
|
||
|
int8_t state = 2;
|
||
|
byte st0;
|
||
|
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.println();
|
||
|
Serial.println(F("Starting 'setMaxCurrent'"));
|
||
|
#endif
|
||
|
|
||
|
// Maximum rate value = 0x1B, because maximum current supply = 240 mA
|
||
|
if (rate > 0x1B)
|
||
|
{
|
||
|
state = -1;
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.print(F("** Maximum current supply is 240 mA, "));
|
||
|
Serial.println(F("so maximum parameter value must be 27 (DEC) or 0x1B (HEX) **"));
|
||
|
Serial.println();
|
||
|
#endif
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Enable Over Current Protection
|
||
|
rate |= B00100000;
|
||
|
|
||
|
state = 1;
|
||
|
st0 = readRegister(REG_OP_MODE); // Save the previous status
|
||
|
writeRegister(REG_OP_MODE, FSK_STANDBY_MODE); // Set FSK Standby mode to write in registers
|
||
|
writeRegister(REG_OCP, rate); // Modifying maximum current supply
|
||
|
if(st0 != FSK_STANDBY_MODE) {
|
||
|
writeRegister(REG_OP_MODE, st0); // Getting back to previous status
|
||
|
}
|
||
|
state = 0;
|
||
|
}
|
||
|
return state;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
Function: Configures the module to receive information.
|
||
|
Returns: Integer that determines if there has been any error
|
||
|
state = 2 --> The command has not been executed
|
||
|
state = 1 --> There has been an error while executing the command
|
||
|
state = 0 --> The command has been executed with no errors
|
||
|
*/
|
||
|
uint8_t SX1278FSK::receive()
|
||
|
{
|
||
|
uint8_t state = 1;
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.println();
|
||
|
Serial.println(F("Starting 'receive'"));
|
||
|
#endif
|
||
|
// TODO: Is there anything else to be done?
|
||
|
//
|
||
|
writeRegister(REG_OP_MODE, FSK_RX_MODE);
|
||
|
state = 0;
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.println(F("## Receiving FSK mode activated with success ##"));
|
||
|
#endif
|
||
|
return state;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Function: Configures the module to receive a packet
|
||
|
Returns: Integer that determines if there has been any error
|
||
|
state = 2 --> The command has not been executed
|
||
|
state = 1 --> There has been an error while executing the command
|
||
|
state = 0 --> The command has been executed with no errors
|
||
|
Parameters:
|
||
|
wait: timeout in ms
|
||
|
data: memory where to place received data
|
||
|
*/
|
||
|
uint8_t SX1278FSK::receivePacketTimeout(uint32_t wait, byte *data)
|
||
|
{
|
||
|
int di=0;
|
||
|
uint8_t state = 2;
|
||
|
unsigned long previous;
|
||
|
byte value = 0x00;
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.println();
|
||
|
Serial.println(F("Starting 'receivePacketTimeout'"));
|
||
|
#endif
|
||
|
// set RX mode
|
||
|
state = receive();
|
||
|
if(state != 0) { return state; }
|
||
|
|
||
|
#if (SX1278FSK_debug_mode > 0)
|
||
|
Serial.println(F("RX mode sucessfully activated"));
|
||
|
#endif
|
||
|
previous = millis();
|
||
|
/// FSK mode
|
||
|
value = readRegister(REG_IRQ_FLAGS2);
|
||
|
byte ready=0;
|
||
|
// while not yet done or FIFO not yet empty
|
||
|
while( (!ready || bitRead(value,6)==0) && (millis() - previous < wait) )
|
||
|
{
|
||
|
if( bitRead(value,2)==1 ) ready=1;
|
||
|
if( bitRead(value, 6) == 0 ) { // FIFO not empty
|
||
|
data[di++] = readRegister(REG_FIFO);
|
||
|
// It's a bit of a hack.... get RSSI and AFC (a) at beginning of packet and
|
||
|
// for RS41 after about 0.5 sec. It might be more logical to put this decoder-specific
|
||
|
// code into RS41.cpp instead of this file... (maybe TODO?)
|
||
|
|
||
|
if(di==1 || di==290 ) {
|
||
|
int rssi=getRSSI();
|
||
|
int afc=getAFC();
|
||
|
#if 0
|
||
|
Serial.printf("Test(%d): RSSI=%d", rxtask.currentSonde, rssi/2);
|
||
|
Serial.print("Test: AFC="); Serial.println(afc);
|
||
|
#endif
|
||
|
sonde.sondeList[rxtask.currentSonde].rssi = rssi;
|
||
|
sonde.sondeList[rxtask.currentSonde].afc = afc;
|
||
|
if(rxtask.receiveResult==0xFFFF)
|
||
|
rxtask.receiveResult = RX_UPDATERSSI;
|
||
|
//sonde.si()->rssi = rssi;
|
||
|
//sonde.si()->afc = afc;
|
||
|
}
|
||
|
if(di>520) {
|
||
|
// TODO
|
||
|
Serial.println("TOO MUCH DATA");
|
||
|
break;
|
||
|
}
|
||
|
previous = millis(); // reset timeout after receiving data
|
||
|
} else {
|
||
|
delay(10);
|
||
|
}
|
||
|
value = readRegister(REG_IRQ_FLAGS2);
|
||
|
}
|
||
|
if( !ready || bitRead(value, 6)==0) {
|
||
|
#if 1&&(SX1278FSK_debug_mode > 0)
|
||
|
Serial.println(F("** The timeout has expired **"));
|
||
|
Serial.println();
|
||
|
#endif
|
||
|
sonde.si()->rssi = getRSSI();
|
||
|
writeRegister(REG_OP_MODE, FSK_STANDBY_MODE); // Setting standby FSK mode
|
||
|
return 1; // TIMEOUT
|
||
|
}
|
||
|
|
||
|
#if (SX1278FSK_debug_mode > 0)
|
||
|
Serial.println(F("## Packet received:"));
|
||
|
for(unsigned int i = 0; i < di; i++)
|
||
|
{
|
||
|
Serial.print(data[i], HEX); // Printing payload
|
||
|
Serial.print("|");
|
||
|
}
|
||
|
Serial.println(F(" ##"));
|
||
|
#endif
|
||
|
state = 0;
|
||
|
// Initializing flags
|
||
|
clearIRQFlags();
|
||
|
|
||
|
return state;
|
||
|
}
|
||
|
|
||
|
|
||
|
#if 0
|
||
|
/*
|
||
|
Function: It gets the temperature from the measurement block module.
|
||
|
Returns: Integer that determines if there has been any error
|
||
|
state = 2 --> The command has not been executed
|
||
|
state = 1 --> There has been an error while executing the command
|
||
|
state = 0 --> The command has been executed with no errors
|
||
|
*/
|
||
|
uint8_t SX1278FSK::getTemp()
|
||
|
{
|
||
|
byte st0;
|
||
|
uint8_t state = 2;
|
||
|
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.println();
|
||
|
Serial.println(F("Starting 'getTemp'"));
|
||
|
#endif
|
||
|
|
||
|
st0 = readRegister(REG_OP_MODE); // Save the previous status
|
||
|
|
||
|
if( _modem == LORA )
|
||
|
{ // Allowing access to FSK registers while in LoRa standby mode
|
||
|
writeRegister(REG_OP_MODE, LORA_STANDBY_FSK_REGS_MODE);
|
||
|
}
|
||
|
|
||
|
state = 1;
|
||
|
// Saving temperature value
|
||
|
_temp = readRegister(REG_TEMP);
|
||
|
if( _temp & 0x80 ) // The SNR sign bit is 1
|
||
|
{
|
||
|
// Invert and divide by 4
|
||
|
_temp = ( ( ~_temp + 1 ) & 0xFF );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Divide by 4
|
||
|
_temp = ( _temp & 0xFF );
|
||
|
}
|
||
|
|
||
|
|
||
|
#if (SX1278FSK_debug_mode > 1)
|
||
|
Serial.print(F("## Temperature is: "));
|
||
|
Serial.print(_temp);
|
||
|
Serial.println(F(" ##"));
|
||
|
Serial.println();
|
||
|
#endif
|
||
|
|
||
|
if( _modem == LORA )
|
||
|
{
|
||
|
writeRegister(REG_OP_MODE, st0); // Getting back to previous status
|
||
|
}
|
||
|
|
||
|
state = 0;
|
||
|
return state;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Function: It prints the registers related to RX
|
||
|
Returns: Integer that determines if there has been any error
|
||
|
state = 2 --> The command has not been executed
|
||
|
state = 1 --> There has been an error while executing the command
|
||
|
state = 0 --> The command has been executed with no errors
|
||
|
*/
|
||
|
void SX1278FSK::showRxRegisters()
|
||
|
{
|
||
|
Serial.println(F("\n--- Show RX register ---"));
|
||
|
|
||
|
// variable
|
||
|
byte reg;
|
||
|
|
||
|
for(int i = 0x00; i < 0x80; i++)
|
||
|
{
|
||
|
reg = readRegister(i);
|
||
|
Serial.print(F("Reg 0x"));
|
||
|
Serial.print(i, HEX);
|
||
|
Serial.print(F(":"));
|
||
|
Serial.print(reg, HEX);
|
||
|
Serial.println();
|
||
|
delay(100);
|
||
|
}
|
||
|
|
||
|
Serial.println(F("------------------------"));
|
||
|
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
SX1278FSK sx1278 = SX1278FSK();
|