302 lines
8.2 KiB
C++
302 lines
8.2 KiB
C++
#include "RF69.h"
|
|
|
|
RF69::RF69(Module* module) {
|
|
_mod = module;
|
|
}
|
|
|
|
uint8_t RF69::begin() {
|
|
// set module properties
|
|
_mod->init(USE_SPI, INT_0);
|
|
|
|
// try to find the RF69 chip
|
|
uint8_t i = 0;
|
|
bool flagFound = false;
|
|
while((i < 10) && !flagFound) {
|
|
uint8_t version = _mod->SPIreadRegister(RF69_REG_VERSION);
|
|
if(version == 0x24) {
|
|
flagFound = true;
|
|
} else {
|
|
#ifdef DEBUG
|
|
Serial.print("RF69 not found! (");
|
|
Serial.print(i + 1);
|
|
Serial.print(" of 10 tries) RF69_REG_VERSION == ");
|
|
|
|
char buffHex[5];
|
|
sprintf(buffHex, "0x%02X", version);
|
|
Serial.print(buffHex);
|
|
Serial.println();
|
|
#endif
|
|
delay(1000);
|
|
i++;
|
|
}
|
|
}
|
|
|
|
if(!flagFound) {
|
|
#ifdef DEBUG
|
|
Serial.println("No RF69 found!");
|
|
#endif
|
|
SPI.end();
|
|
return(ERR_CHIP_NOT_FOUND);
|
|
}
|
|
#ifdef DEBUG
|
|
else {
|
|
Serial.println("Found RF69! (match by RF69_REG_VERSION == 0x12)");
|
|
}
|
|
#endif
|
|
|
|
return(config());
|
|
}
|
|
|
|
uint8_t RF69::transmit(Packet& pack) {
|
|
char buffer[256];
|
|
|
|
// copy packet source and destination addresses into buffer
|
|
for(uint8_t i = 0; i < 8; i++) {
|
|
buffer[i] = pack.source[i];
|
|
buffer[i+8] = pack.destination[i];
|
|
}
|
|
|
|
// copy packet data into buffer
|
|
for(uint8_t i = 0; i < pack.length; i++) {
|
|
buffer[i+16] = pack.data[i];
|
|
}
|
|
|
|
// set mode to standby
|
|
setMode(RF69_STANDBY);
|
|
|
|
// set DIO pin mapping
|
|
_mod->SPIsetRegValue(RF69_REG_DIO_MAPPING_1, RF69_DIO0_PACK_PACKET_SENT, 7, 6);
|
|
|
|
// clear interrupt flags
|
|
clearIRQFlags();
|
|
|
|
// check overall packet length
|
|
if(pack.length > 256) {
|
|
return(ERR_PACKET_TOO_LONG);
|
|
}
|
|
|
|
// write packet to FIFO
|
|
_mod->SPIwriteRegister(RF69_REG_FIFO, pack.length);
|
|
_mod->SPIwriteRegisterBurstStr(RF69_REG_FIFO, buffer, pack.length);
|
|
|
|
// set mode to transmit
|
|
setMode(RF69_TX);
|
|
_mod->SPIsetRegValue(RF69_REG_TEST_PA1, RF69_PA1_20_DBM);
|
|
_mod->SPIsetRegValue(RF69_REG_TEST_PA2, RF69_PA2_20_DBM);
|
|
|
|
// wait for transmission end
|
|
while(!_mod->getInt0State()) {
|
|
#ifdef DEBUG
|
|
Serial.print('.');
|
|
#endif
|
|
}
|
|
|
|
// clear interrupt flags
|
|
clearIRQFlags();
|
|
|
|
return(ERR_NONE);
|
|
}
|
|
|
|
uint8_t RF69::receive(Packet& pack) {
|
|
char buffer[256];
|
|
|
|
// set mode to standby
|
|
setMode(RF69_STANDBY);
|
|
|
|
// set DIO pin mapping
|
|
//_mod->SPIsetRegValue(RF69_REG_DIO_MAPPING_1, RF69_DIO0_PACK_PAYLOAD_READY | RF69_DIO1_PACK_TIMEOUT, 7, 4);
|
|
_mod->SPIsetRegValue(RF69_REG_DIO_MAPPING_1, RF69_DIO0_PACK_PAYLOAD_READY, 7, 6);
|
|
|
|
// clear interrupt flags
|
|
clearIRQFlags();
|
|
|
|
// set mode to receive
|
|
setMode(RF69_RX);
|
|
_mod->SPIsetRegValue(RF69_REG_TEST_PA1, RF69_PA1_NORMAL);
|
|
_mod->SPIsetRegValue(RF69_REG_TEST_PA2, RF69_PA2_NORMAL);
|
|
|
|
// wait for packet reception or timeout
|
|
/*while(!_mod->getInt0State()) {
|
|
if(_mod->getInt1State()) {
|
|
clearIRQFlags();
|
|
return(ERR_RX_TIMEOUT);
|
|
}
|
|
}*/
|
|
unsigned long start = millis();
|
|
while(!_mod->getInt0State()) {
|
|
if(millis() - start > 2000) {
|
|
clearIRQFlags();
|
|
return(ERR_RX_TIMEOUT);
|
|
}
|
|
}
|
|
|
|
// read packet from FIFO
|
|
pack.length = _mod->SPIreadRegister(RF69_REG_FIFO);
|
|
_mod->SPIreadRegisterBurstStr(RF69_REG_FIFO, pack.length, buffer);
|
|
|
|
// clear interrupt flags
|
|
clearIRQFlags();
|
|
|
|
// get packet source and destination addresses from buffer
|
|
for(uint8_t i = 0; i < 8; i++) {
|
|
pack.source[i] = buffer[i];
|
|
pack.destination[i] = buffer[i+8];
|
|
}
|
|
|
|
// get packet source and destination addresses from buffer
|
|
for(uint8_t i = 16; i < pack.length; i++) {
|
|
pack.data[i-16] = buffer[i];
|
|
}
|
|
pack.data[pack.length-16] = 0;
|
|
|
|
return(ERR_NONE);
|
|
}
|
|
|
|
uint8_t RF69::sleep() {
|
|
return(setMode(RF69_SLEEP));
|
|
}
|
|
|
|
uint8_t RF69::standby() {
|
|
return(setMode(RF69_STANDBY));
|
|
}
|
|
|
|
uint8_t RF69::config() {
|
|
uint8_t status = ERR_NONE;
|
|
|
|
//set mode to STANDBY
|
|
status = setMode(RF69_STANDBY);
|
|
if(status != ERR_NONE) {
|
|
return(status);
|
|
}
|
|
|
|
//set operation modes
|
|
status = _mod->SPIsetRegValue(RF69_REG_OP_MODE, RF69_SEQUENCER_ON | RF69_LISTEN_OFF, 7, 6);
|
|
if(status != ERR_NONE) {
|
|
return(status);
|
|
}
|
|
|
|
//enable over-current protection
|
|
status = _mod->SPIsetRegValue(RF69_REG_OCP, RF69_OCP_ON, 4, 4);
|
|
if(status != ERR_NONE) {
|
|
return(status);
|
|
}
|
|
|
|
//set data mode and modulation type
|
|
status = _mod->SPIsetRegValue(RF69_REG_DATA_MODUL, RF69_PACKET_MODE | RF69_FSK, 6, 3);
|
|
status = _mod->SPIsetRegValue(RF69_REG_DATA_MODUL, RF69_NO_SHAPING, 1, 0);
|
|
if(status != ERR_NONE) {
|
|
return(status);
|
|
}
|
|
|
|
//set bit rate (4.8 kbps by default)
|
|
status = _mod->SPIsetRegValue(RF69_REG_BITRATE_MSB, RF69_BITRATE_MSB, 7, 0);
|
|
status = _mod->SPIsetRegValue(RF69_REG_BITRATE_LSB, RF69_BITRATE_LSB, 7, 0);
|
|
if(status != ERR_NONE) {
|
|
return(status);
|
|
}
|
|
|
|
//set allowed frequency deviation (5 kHz by default)
|
|
status = _mod->SPIsetRegValue(RF69_REG_FDEV_MSB, RF69_FDEV_MSB, 5, 0);
|
|
status = _mod->SPIsetRegValue(RF69_REG_FDEV_LSB, RF69_FDEV_LSB, 7, 0);
|
|
if(status != ERR_NONE) {
|
|
return(status);
|
|
}
|
|
|
|
//set carrier frequency
|
|
status = _mod->SPIsetRegValue(RF69_REG_FRF_MSB, RF69_FRF_MSB, 7, 0);
|
|
status = _mod->SPIsetRegValue(RF69_REG_FRF_MID, RF69_FRF_MID, 7, 0);
|
|
status = _mod->SPIsetRegValue(RF69_REG_FRF_LSB, RF69_FRF_LSB, 7, 0);
|
|
if(status != ERR_NONE) {
|
|
return(status);
|
|
}
|
|
|
|
//set Rx bandwidth
|
|
status = _mod->SPIsetRegValue(RF69_REG_RX_BW, RF69_DCC_FREQ | RF69_RX_BW_MANT_16 | RF69_RX_BW_EXP, 7, 0);
|
|
if(status != ERR_NONE) {
|
|
return(status);
|
|
}
|
|
|
|
//set RSSI threshold
|
|
status = _mod->SPIsetRegValue(RF69_REG_RSSI_THRESH, RF69_RSSI_THRESHOLD, 7, 0);
|
|
if(status != ERR_NONE) {
|
|
return(status);
|
|
}
|
|
|
|
//reset FIFO flags
|
|
status = _mod->SPIsetRegValue(RF69_REG_IRQ_FLAGS_2, RF69_IRQ_FIFO_OVERRUN, 4, 4);
|
|
if(status != ERR_NONE) {
|
|
return(status);
|
|
}
|
|
|
|
//disable ClkOut on DIO5
|
|
status = _mod->SPIsetRegValue(RF69_REG_DIO_MAPPING_2, RF69_CLK_OUT_OFF, 2, 0);
|
|
if(status != ERR_NONE) {
|
|
return(status);
|
|
}
|
|
|
|
//set synchronization
|
|
status = _mod->SPIsetRegValue(RF69_REG_SYNC_CONFIG, RF69_SYNC_ON | RF69_FIFO_FILL_CONDITION_SYNC | RF69_SYNC_SIZE | RF69_SYNC_TOL, 7, 0);
|
|
if(status != ERR_NONE) {
|
|
return(status);
|
|
}
|
|
|
|
//set sync word
|
|
status = _mod->SPIsetRegValue(RF69_REG_SYNC_VALUE_1, 0x2D, 7, 0);
|
|
status = _mod->SPIsetRegValue(RF69_REG_SYNC_VALUE_2, 100, 7, 0);
|
|
if(status != ERR_NONE) {
|
|
return(status);
|
|
}
|
|
|
|
//set packet configuration and disable encryption
|
|
status = _mod->SPIsetRegValue(RF69_REG_PACKET_CONFIG_1, RF69_PACKET_FORMAT_VARIABLE | RF69_DC_FREE_NONE | RF69_CRC_ON | RF69_CRC_AUTOCLEAR_ON | RF69_ADDRESS_FILTERING_OFF, 7, 1);
|
|
status = _mod->SPIsetRegValue(RF69_REG_PACKET_CONFIG_2, RF69_INTER_PACKET_RX_DELAY, 7, 4);
|
|
status = _mod->SPIsetRegValue(RF69_REG_PACKET_CONFIG_2, RF69_AUTO_RX_RESTART_ON | RF69_AES_OFF, 1, 0);
|
|
if(status != ERR_NONE) {
|
|
return(status);
|
|
}
|
|
|
|
//set payload length
|
|
status = _mod->SPIsetRegValue(RF69_REG_PAYLOAD_LENGTH, RF69_PAYLOAD_LENGTH, 7, 0);
|
|
if(status != ERR_NONE) {
|
|
return(status);
|
|
}
|
|
|
|
//set FIFO threshold
|
|
status = _mod->SPIsetRegValue(RF69_REG_FIFO_THRESH, RF69_TX_START_CONDITION_FIFO_NOT_EMPTY | RF69_FIFO_THRESHOLD, 7, 0);
|
|
if(status != ERR_NONE) {
|
|
return(status);
|
|
}
|
|
|
|
//set output power
|
|
status = _mod->SPIsetRegValue(RF69_REG_PA_LEVEL, RF69_PA0_ON | RF69_PA1_OFF | RF69_PA2_OFF | RF69_OUTPUT_POWER, 7, 0);
|
|
if(status != ERR_NONE) {
|
|
return(status);
|
|
}
|
|
|
|
//set Rx timeouts
|
|
//status = _mod->SPIsetRegValue(RF69_REG_RX_TIMEOUT_1, RF69_TIMEOUT_RX_START, 7, 0);
|
|
status = _mod->SPIsetRegValue(RF69_REG_RX_TIMEOUT_1, RF69_TIMEOUT_RX_START_OFF, 7, 0);
|
|
//status = _mod->SPIsetRegValue(RF69_REG_RX_TIMEOUT_2, RF69_TIMEOUT_RSSI_THRESH, 7, 0);
|
|
status = _mod->SPIsetRegValue(RF69_REG_RX_TIMEOUT_2, RF69_TIMEOUT_RSSI_THRESH_OFF, 7, 0);
|
|
if(status != ERR_NONE) {
|
|
return(status);
|
|
}
|
|
|
|
//enable improved fading margin
|
|
status = _mod->SPIsetRegValue(RF69_REG_TEST_DAGC, RF69_CONTINUOUS_DAGC_LOW_BETA_OFF, 7, 0);
|
|
if(status != ERR_NONE) {
|
|
return(status);
|
|
}
|
|
|
|
return(ERR_NONE);
|
|
}
|
|
|
|
uint8_t RF69::setMode(uint8_t mode) {
|
|
_mod->SPIsetRegValue(RF69_REG_OP_MODE, mode, 4, 2);
|
|
return(ERR_NONE);
|
|
}
|
|
|
|
void RF69::clearIRQFlags() {
|
|
_mod->SPIwriteRegister(RF69_REG_IRQ_FLAGS_1, 0b11111111);
|
|
_mod->SPIwriteRegister(RF69_REG_IRQ_FLAGS_2, 0b11111111);
|
|
}
|