diff --git a/Examples/DoorBellMote/DoorBellMote.ino b/Examples/DoorBellMote/DoorBellMote.ino new file mode 100644 index 0000000..728c7f1 --- /dev/null +++ b/Examples/DoorBellMote/DoorBellMote.ino @@ -0,0 +1,222 @@ +// ********************************************************************************** +// DoorBellMote sketch works with Moteinos equipped with RFM69W/RFM69HW +// Can be adapted to use Moteinos/Arduinos using RFM12B or other RFM69 variants (RFM69CW, RFM69HCW) +// http://www.LowPowerLab.com/ +// 2015-07-22 (C) Felix Rusu of http://www.LowPowerLab.com/ +// ********************************************************************************** +// It detects current flow at the doorbell transformer and send a message each time to the gateway +// It can trigger doorbell through a relay powered from pins D6+D7 +// Deploy and forget: wirelessly programmable via Moteino + WirelessHEX69 library +// ********************************************************************************** +// License +// ********************************************************************************** +// This program is free software; you can redistribute it +// and/or modify it under the terms of the GNU General +// Public License as published by the Free Software +// Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will +// be useful, but WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A +// PARTICULAR PURPOSE. See the GNU General Public +// License for more details. +// +// You should have received a copy of the GNU General +// Public License along with this program. +// If not, see . +// +// Licence can be viewed at +// http://www.gnu.org/licenses/gpl-3.0.txt +// +// Please maintain this license information along with authorship +// and copyright notices in any redistribution of this code +// ********************************************************************************** +#include //get it here: http://github.com/lowpowerlab/rfm69 +#include //get it here: http://github.com/lowpowerlab/spiflash +#include //get it here: https://github.com/LowPowerLab/WirelessProgramming +#include //comes with Arduino IDE (www.arduino.cc) + +//***************************************************************************************************************************** +// ADJUST THE SETTINGS BELOW DEPENDING ON YOUR HARDWARE/SITUATION! +//***************************************************************************************************************************** +#define GATEWAYID 1 +#define NODEID 133 +#define NETWORKID 100 +//#define FREQUENCY RF69_433MHZ +//#define FREQUENCY RF69_868MHZ +#define FREQUENCY RF69_915MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ) +#define ENCRYPTKEY "sampleEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less! +//#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! + +#define CHIMEPIN 4 // active HIGH chime signal from detector H11AA1 circuit +#define RELAYPIN1 6 //for the bell ring relay we just need 2 digital pins together to activate the relay for a short pulse +#define RELAYPIN2 7 //for the bell ring relay we just need 2 digital pins together to activate the relay for a short pulse +#define DISABLE_RELAY 5 //for the bell disable relay we use a single digital pin through a transistor +#define RELAY_PULSE_MS 250 //just enough that the doorbell chime will trigger +#define RINGDELAY 3000 //time between rings (avoid fast repeated rings) +//***************************************************************************************************************************** +#define LED 9 //pin connected to onboard LED +#define SERIAL_BAUD 115200 +#define SERIAL_EN //comment out if you don't want any serial output + +#ifdef SERIAL_EN + #define DEBUG(input) Serial.print(input) + #define DEBUGln(input) Serial.println(input) +#else + #define DEBUG(input) + #define DEBUGln(input) +#endif + +RFM69 radio; +///////////////////////////////////////////////////////////////////////////// +// flash(SPI_CS, MANUFACTURER_ID) +// SPI_CS - CS pin attached to SPI flash chip (8 in case of Moteino) +// MANUFACTURER_ID - OPTIONAL, 0xEF30 for windbond 4mbit flash (Moteino OEM) +///////////////////////////////////////////////////////////////////////////// +SPIFlash flash(8, 0xEF30); //regular Moteinos have FLASH MEM on D8, MEGA has it on D4 +char buff[50]; + +void setup(void) +{ + Serial.begin(SERIAL_BAUD); + pinMode(CHIMEPIN, INPUT); + pinMode(RELAYPIN1, OUTPUT); + pinMode(RELAYPIN2, OUTPUT); + pinMode(DISABLE_RELAY, OUTPUT); + pinMode(LED, OUTPUT); + + radio.initialize(FREQUENCY,NODEID,NETWORKID); +#ifdef IS_RFM69HW + radio.setHighPower(); //uncomment only for RFM69HW! +#endif + radio.encrypt(ENCRYPTKEY); + + sprintf(buff, "DoorBellMote : %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); + DEBUGln(buff); + + if (flash.initialize()) + DEBUGln("SPI Flash Init OK"); + else + DEBUGln("SPI Flash Init FAIL! (is chip present?)"); + + radio.sendWithRetry(GATEWAYID, "START", 6); + Blink(LED, 100); + Blink(LED, 100); + Blink(LED, 100); +} + +uint32_t doorPulseCount = 0; +uint32_t lastStatusTimestamp=0; +uint32_t LEDCYCLETIMER=0; +byte LEDSTATE=LOW; +char input; +boolean ring=false; +boolean disable=false; +byte disableStatus=0; + +void loop() +{ + if (Serial.available()) + input = Serial.read(); + + if (input=='r') + { + DEBUGln("Relay test..."); + pulseRelay(); + input = 0; + } + + if (millis()-(lastStatusTimestamp)>RINGDELAY) + { + if (digitalRead(CHIMEPIN) == HIGH) + { + lastStatusTimestamp = millis(); + radio.sendWithRetry(GATEWAYID, "RING", 4); + Blink(LED,20); + Blink(LED,20); + Blink(LED,20); + } + } + + if (radio.receiveDone()) + { + DEBUG('[');DEBUG(radio.SENDERID);DEBUG("] "); + for (byte i = 0; i < radio.DATALEN; i++) + DEBUG((char)radio.DATA[i]); + + if (radio.DATALEN==4) + if (radio.DATA[0]=='R' && radio.DATA[1]=='I' && radio.DATA[2]=='N' && radio.DATA[3]=='G') + ring = true; + + if (radio.DATALEN==6) + if (radio.DATA[0]=='B' && radio.DATA[1]=='E' && radio.DATA[2]=='L' && radio.DATA[3]=='L' && radio.DATA[4]==':') + if (radio.DATA[5]=='0') + { + disableStatus = 1; + disable = true; + } + else if (radio.DATA[5]=='1') + { + disableStatus = 0; + disable = true; + } + + // wireless programming token check + // DO NOT REMOVE, or GarageMote will not be wirelessly programmable any more! + CheckForWirelessHEX(radio, flash, true); + + //first send any ACK to request + DEBUG(" [RX_RSSI:");DEBUG(radio.RSSI);DEBUG("]"); + if (radio.ACKRequested()) + { + radio.sendACK(); + DEBUG(" - ACK sent."); + } + + if (ring) + { + //if other relay is ON we must temporarily turn it off while we pulse the RING relay, to avoid any rail collapse and reset + if (disableStatus) digitalWrite(DISABLE_RELAY, 0); + pulseRelay(); + if (disableStatus) digitalWrite(DISABLE_RELAY, 1); + radio.sendWithRetry(GATEWAYID, "RING OK", 4); + ring = false; + } + + if (disable) + { + digitalWrite(DISABLE_RELAY, disableStatus); //disable it + sprintf(buff, "BELL:%d", disableStatus ? 0 : 1); + radio.sendWithRetry(GATEWAYID, buff, 6); + disable=false; + } + + DEBUGln(); + } + + if (millis() - LEDCYCLETIMER > 2000) //flip onboard LED state every so often to indicate activity + { + LEDCYCLETIMER = millis(); + LEDSTATE = !LEDSTATE; + digitalWrite(LED, LEDSTATE); + } +} + +void pulseRelay() +{ + digitalWrite(RELAYPIN1, HIGH); + digitalWrite(RELAYPIN2, HIGH); + delay(RELAY_PULSE_MS); + digitalWrite(RELAYPIN1, LOW); + digitalWrite(RELAYPIN2, LOW); +} + +void Blink(byte PIN, byte DELAY_MS) +{ + pinMode(PIN, OUTPUT); + digitalWrite(PIN,HIGH); + delay(DELAY_MS/2); + digitalWrite(PIN,LOW); + delay(DELAY_MS/2); +} \ No newline at end of file diff --git a/Examples/GarageMote/GarageMote.ino b/Examples/GarageMote/GarageMote.ino index bbe57d0..768270f 100644 --- a/Examples/GarageMote/GarageMote.ino +++ b/Examples/GarageMote/GarageMote.ino @@ -1,7 +1,8 @@ // ********************************************************************************************************** -// GarageMote garage door controller sketch that works with Moteinos equipped with HopeRF RFM69W/RFM69HW -// Can be adapted to use Moteinos using RFM12B -// 2014-07-14 (C) felix@lowpowerlab.com, http://www.LowPowerLab.com +// GarageMote garage door controller sketch that works with Moteinos equipped with RFM69W/RFM69HW +// Can be adapted to use Moteinos/Arduinos using RFM12B or other RFM69 variants (RFM69CW, RFM69HCW) +// http://www.LowPowerLab.com/GarageMote +// 2015-05-05 (C) Felix Rusu of http://www.LowPowerLab.com/ // ********************************************************************************************************** // It uses 2 hall effect sensors (and magnets mounted on the garage belt/chain) to detect the position of the // door, and a small signal relay to be able to toggle the garage opener. @@ -11,28 +12,55 @@ // - solid OFF - door is in closed position // - blinking - door is not in either open/close position // - pulsing - door is in motion -// ********************************************************************************************************** -// Creative Commons Attrib Share-Alike License -// You are free to use/extend this code/library but please abide with the CCSA license: -// http://creativecommons.org/licenses/by-sa/4.0/ // ********************************************************************************** - +// License +// ********************************************************************************** +// This program is free software; you can redistribute it +// and/or modify it under the terms of the GNU General +// Public License as published by the Free Software +// Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will +// be useful, but WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A +// PARTICULAR PURPOSE. See the GNU General Public +// License for more details. +// +// You should have received a copy of the GNU General +// Public License along with this program. +// If not, see . +// +// Licence can be viewed at +// http://www.gnu.org/licenses/gpl-3.0.txt +// +// Please maintain this license information along with authorship +// and copyright notices in any redistribution of this code +// *************************************************************************************************************************** +//#define WEATHERSHIELD //uncomment if WeatherShield is present to report temp/humidity/pressure periodically +//#define WEATHERSENDDELAY 300000 // send WeatherShield data every so often (ms) +// *************************************************************************************************************************** #include //get it here: http://github.com/lowpowerlab/rfm69 #include //get it here: http://github.com/lowpowerlab/spiflash #include //get it here: https://github.com/LowPowerLab/WirelessProgramming #include //comes with Arduino IDE (www.arduino.cc) +#ifdef WEATHERSHIELD + #include //get it here: https://github.com/LowPowerLab/SFE_BMP180 + #include //get it here: https://github.com/LowPowerLab/SI7021 + #include +#endif //***************************************************************************************************************************** -// ADJUST THE SETTINGS BELOW DEPENDING ON YOUR HARDWARE/SITUATION! +// ADJUST THE SETTINGS BELOW DEPENDING ON YOUR HARDWARE/TRANSCEIVER SETTINGS/REQUIREMENTS //***************************************************************************************************************************** #define GATEWAYID 1 -#define NODEID 122 -#define NETWORKID 100 +#define NODEID 11 +#define NETWORKID 250 //#define FREQUENCY RF69_433MHZ //#define FREQUENCY RF69_868MHZ #define FREQUENCY RF69_915MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ) #define ENCRYPTKEY "sampleEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less! -#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! +#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! #define HALLSENSOR1 A0 #define HALLSENSOR1_EN 4 @@ -71,24 +99,34 @@ #define DEBUGln(input); #endif +#ifdef WEATHERSHIELD + SI7021 weatherShield_SI7021; + SFE_BMP180 weatherShield_BMP180; +#endif + +//function prototypes void setStatus(byte newSTATUS, boolean reportStatus=true); +void reportStatus(); +boolean hallSensorRead(byte which); +void pulseRelay(); + +//global program variables byte STATUS; unsigned long lastStatusTimestamp=0; unsigned long ledPulseTimestamp=0; -byte lastRequesterNodeID=GATEWAYID; +unsigned long lastWeatherSent=0; int ledPulseValue=0; boolean ledPulseDirection=false; //false=down, true=up RFM69 radio; -///////////////////////////////////////////////////////////////////////////// -// flash(SPI_CS, MANUFACTURER_ID) -// SPI_CS - CS pin attached to SPI flash chip (8 in case of Moteino) -// MANUFACTURER_ID - OPTIONAL, 0xEF30 for windbond 4mbit flash (Moteino OEM) -///////////////////////////////////////////////////////////////////////////// -SPIFlash flash(8, 0xEF30); +char Pstr[10]; +char sendBuf[30]; +SPIFlash flash(8, 0xEF30); //WINDBOND 4MBIT flash chip on CS pin D8 (default for Moteino) void setup(void) { +#ifdef SERIAL_EN Serial.begin(SERIAL_BAUD); +#endif pinMode(HALLSENSOR1, INPUT); pinMode(HALLSENSOR2, INPUT); pinMode(HALLSENSOR1_EN, OUTPUT); @@ -112,16 +150,27 @@ void setup(void) if (hallSensorRead(HALLSENSOR_CLOSEDSIDE)==true) setStatus(STATUS_CLOSED); else setStatus(STATUS_UNKNOWN); + +#ifdef WEATHERSHIELD + //initialize weather shield sensors + weatherShield_SI7021.begin(); + if (weatherShield_BMP180.begin()) + { DEBUGln("BMP180 init success"); } + else { DEBUGln("BMP180 init fail\n"); } +#endif } unsigned long doorPulseCount = 0; -char input; +char input=0; +double P; void loop() { +#ifdef SERIAL_EN if (Serial.available()) input = Serial.read(); - +#endif + if (input=='r') { DEBUGln("Relay test..."); @@ -169,7 +218,6 @@ void loop() { byte newStatus=STATUS; boolean reportStatusRequest=false; - lastRequesterNodeID = radio.SENDERID; DEBUG('[');DEBUG(radio.SENDERID);DEBUG("] "); for (byte i = 0; i < radio.DATALEN; i++) DEBUG((char)radio.DATA[i]); @@ -256,6 +304,19 @@ void loop() ledPulseTimestamp = millis(); } } + +#ifdef WEATHERSHIELD + if (millis()-lastWeatherSent > WEATHERSENDDELAY) + { + lastWeatherSent = millis(); + P = getPressure(); + P*=0.0295333727; //transform to inHg + dtostrf(P, 3,2, Pstr); + sprintf(sendBuf, "F:%d H:%d P:%s", weatherShield_SI7021.getFahrenheitHundredths(), weatherShield_SI7021.getHumidityPercent(), Pstr); + byte sendLen = strlen(sendBuf); + radio.send(GATEWAYID, sendBuf, sendLen); + } +#endif } //returns TRUE if magnet is next to sensor, FALSE if magnet is away @@ -269,22 +330,21 @@ boolean hallSensorRead(byte which) return reading==0; } -void setStatus(byte newSTATUS, boolean reportStatusRequest) +void setStatus(byte newSTATUS, boolean reportIt) { if (STATUS != newSTATUS) lastStatusTimestamp = millis(); STATUS = newSTATUS; DEBUGln(STATUS==STATUS_CLOSED ? "CLOSED" : STATUS==STATUS_CLOSING ? "CLOSING" : STATUS==STATUS_OPENING ? "OPENING" : STATUS==STATUS_OPEN ? "OPEN" : "UNKNOWN"); - if (reportStatusRequest) + if (reportIt) reportStatus(); } -boolean reportStatus() +void reportStatus(void) { - if (lastRequesterNodeID == 0) return false; char buff[10]; sprintf(buff, STATUS==STATUS_CLOSED ? "CLOSED" : STATUS==STATUS_CLOSING ? "CLOSING" : STATUS==STATUS_OPENING ? "OPENING" : STATUS==STATUS_OPEN ? "OPEN" : "UNKNOWN"); byte len = strlen(buff); - return radio.sendWithRetry(lastRequesterNodeID, buff, len); + radio.sendWithRetry(GATEWAYID, buff, len); } void pulseRelay() @@ -302,4 +362,58 @@ void Blink(byte PIN, byte DELAY_MS) digitalWrite(PIN,HIGH); delay(DELAY_MS); digitalWrite(PIN,LOW); -} \ No newline at end of file +} + +#ifdef WEATHERSHIELD +double getPressure() +{ + char status; + double T,P,p0,a; + // If you want sea-level-compensated pressure, as used in weather reports, + // you will need to know the altitude at which your measurements are taken. + // We're using a constant called ALTITUDE in this sketch: + + // If you want to measure altitude, and not pressure, you will instead need + // to provide a known baseline pressure. This is shown at the end of the sketch. + // You must first get a temperature measurement to perform a pressure reading. + // Start a temperature measurement: + // If request is successful, the number of ms to wait is returned. + // If request is unsuccessful, 0 is returned. + status = weatherShield_BMP180.startTemperature(); + if (status != 0) + { + // Wait for the measurement to complete: + delay(status); + + // Retrieve the completed temperature measurement: + // Note that the measurement is stored in the variable T. + // Function returns 1 if successful, 0 if failure. + status = weatherShield_BMP180.getTemperature(T); + if (status != 0) + { + // Start a pressure measurement: + // The parameter is the oversampling setting, from 0 to 3 (highest res, longest wait). + // If request is successful, the number of ms to wait is returned. + // If request is unsuccessful, 0 is returned. + status = weatherShield_BMP180.startPressure(3); + if (status != 0) + { + // Wait for the measurement to complete: + delay(status); + + // Retrieve the completed pressure measurement: + // Note that the measurement is stored in the variable P. + // Note also that the function requires the previous temperature measurement (T). + // (If temperature is stable, you can do one temperature measurement for a number of pressure measurements.) + // Function returns 1 if successful, 0 if failure. + status = weatherShield_BMP180.getPressure(P,T); + if (status != 0) + { + return P; + } + } + } + } + return 0; +} +#endif \ No newline at end of file diff --git a/Examples/Gateway/Gateway.ino b/Examples/Gateway/Gateway.ino index d934b88..bd1dd17 100644 --- a/Examples/Gateway/Gateway.ino +++ b/Examples/Gateway/Gateway.ino @@ -4,9 +4,9 @@ // Library and code by Felix Rusu - felix@lowpowerlab.com // Get the RFM69 and SPIFlash library at: https://github.com/LowPowerLab/ -#include +#include //get it here: https://www.github.com/lowpowerlab/rfm69 #include -#include +#include //get it here: https://www.github.com/lowpowerlab/spiflash #define NODEID 1 //unique for each node on same network #define NETWORKID 100 //the same on all nodes that talk to each other @@ -16,7 +16,6 @@ //#define FREQUENCY RF69_915MHZ #define ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes! //#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! -#define ACK_TIME 30 // max # of ms to wait for an ack #define SERIAL_BAUD 115200 #ifdef __AVR_ATmega1284P__ @@ -40,19 +39,21 @@ void setup() { #endif radio.encrypt(ENCRYPTKEY); radio.promiscuous(promiscuousMode); + //radio.setFrequency(919000000); char buff[50]; sprintf(buff, "\nListening at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); Serial.println(buff); if (flash.initialize()) { - Serial.print("SPI Flash Init OK ... UniqueID (MAC): "); + Serial.print("SPI Flash Init OK. Unique MAC = ["); flash.readUniqueId(); for (byte i=0;i<8;i++) { Serial.print(flash.UNIQUEID[i], HEX); - Serial.print(' '); + if (i!=8) Serial.print(':'); } - + Serial.println(']'); + //alternative way to read it: //byte* MAC = flash.readUniqueId(); //for (byte i=0;i<8;i++) @@ -60,12 +61,14 @@ void setup() { // Serial.print(MAC[i], HEX); // Serial.print(' '); //} + } else Serial.println("SPI Flash Init FAIL! (is chip present?)"); } byte ackCount=0; +uint32_t packetCount = 0; void loop() { //process any serial input if (Serial.available() > 0) @@ -123,6 +126,9 @@ void loop() { if (radio.receiveDone()) { + Serial.print("#["); + Serial.print(++packetCount); + Serial.print(']'); Serial.print('[');Serial.print(radio.SENDERID, DEC);Serial.print("] "); if (promiscuousMode) { @@ -163,4 +169,4 @@ void Blink(byte PIN, int DELAY_MS) digitalWrite(PIN,HIGH); delay(DELAY_MS); digitalWrite(PIN,LOW); -} \ No newline at end of file +} diff --git a/Examples/MightyBoostControl/MightyBoostControl.ino b/Examples/MightyBoostControl/MightyBoostControl.ino index d9754f9..6abbd31 100644 --- a/Examples/MightyBoostControl/MightyBoostControl.ino +++ b/Examples/MightyBoostControl/MightyBoostControl.ino @@ -1,8 +1,18 @@ // ************************************************************************************************************* // MightyBoost control sample sketch // ************************************************************************************************************* -// Copyright Felix Rusu (2014), felix@lowpowerlab.com -// http://lowpowerlab.com/ +// Copyright (2015) Felix Rusu of http://lowpowerlab.com +// http://lowpowerlab.com/mightyboost +// MightyBoost is a smart backup PSU controllable by Moteino, and this sketch is a sample control sketch to run +// MightyBoost in this mode. +// Be sure to check back for code updates and patches +// ************************************************************************************************************* +// This sketch will provide control over the essential features of MightyBoost: +// - provide switched 5V power to a sensitive load like RaspberryPi which should not lose power instantly +// - Control the "5V*" output via Moteino+PowerButton (momentary tactile) +// - Monitor input supply and switch to battery backup when external power is lost +// - Monitor battery voltage and issue a shutdown/reboot signal when battery runs low +// This sketch may be extended to include integration with other LowPowerLab automation products // ************************************************************************************************************* // License // ************************************************************************************************************* @@ -29,23 +39,10 @@ // Please maintain this license information along with authorship // and copyright notices in any redistribution of this code // ************************************************************************************************************* -// MightyBoost is a smart backup PSU controllable by Moteino, and this sketch is a sample control sketch to run -// MightyBoost in this mode. -// http://moteino.com -// http://github.com/lowpowerlab -// Be sure to check back for code updates and patches -// ************************************************************************************************************* -// This sketch will provide control over the essential features of MightyBoost: -// - provide switched 5V power to a sensitive load like RaspberryPi which should not lose power instantly -// - Control the "5V*" output via Moteino+PowerButton (momentary tactile) -// - Monitor input supply and switch to battery backup when external power is lost -// - Monitor battery voltage and issue a shutdown signal when battery runs low -// This sketch may be extended to include integration with other LowPowerLab automation products -// ************************************************************************************************************* #define LED 5 // LED pin, should be analog for fading effect (PWM) #define BUTTON 3 // Power button pin -#define SIG_REQUESTHALT 6 // Signal to Pi to ask for a shutdown -#define SIG_OKTOCUTOFF A0 // Signal from Pi that it's OK to cutoff power +#define SIG_SHUTOFF 6 // Signal to Pi to ask for a shutdown +#define SIG_BOOTOK A0 // Signal from Pi that it's OK to cutoff power // !!NOTE!! Originally this was D7 but it was moved to A0 at least temporarily. // On MightyBoost R1 you need to connect D7 and A0 with a jumper wire. // The explanation for this is given here: http://lowpowerlab.com/mightyboost/#source @@ -55,24 +52,26 @@ // when plugged in this should be 4.80v, nothing to worry about // when on battery power this should decrease from 4.15v (fully charged Lipoly) to 3.3v (discharged Lipoly) // trigger a shutdown to the target device once voltage is around 3.4v to allow 30sec safe shutdown -#define LOWBATTERYTHRESHOLD 3.7 // a shutdown will be triggered to the target device when battery voltage drops below this (Volts) +#define LOWBATTERYTHRESHOLD 3.5 // a shutdown will be triggered to the target device when battery voltage drops below this (Volts) -#define ButtonHoldTime 1800 // Button must be hold this many mseconds before a shutdown sequence is started (should be much less than PIForceShutdownDelay) -#define PIShutdownDelay_Min 6000 // will start checking the SIG_OKTOCUTOFF line after this long -#define PIShutdownDelay_Max 38000 // window of time in which SIG_OKTOCUTOFF is expected to go HIGH +#define RESETHOLDTIME 500 // Button must be hold this many mseconds before a reset is issued (should be much less than SHUTDOWNHOLDTIME) +#define SHUTDOWNHOLDTIME 2000 // Button must be hold this many mseconds before a shutdown sequence is started (should be much less than ForcedShutoffDelay) +#define ShutoffTriggerDelay 6000 // will start checking the SIG_BOOTOK line after this long +#define RecycleTime 50000 // window of time in which SIG_BOOTOK is expected to go HIGH // should be at least 3000 more than Min // if nothing happens after this window, if button is // still pressed, force cutoff power, otherwise switch back to normal ON state -#define PIForceShutdownDelay 6500 // when SIG_OKTOCUTOFF==0 (PI in unknown state): if button is held - // for this long, force shutdown (this should be less than PIShutdownDelay_Max) -#define ShutdownFINALDELAY 4000 // after shutdown signal is received, delay for this long +#define RESETPULSETIME 500 // When reset is issued, the SHUTOFF signal is held HIGH this many ms +#define ForcedShutoffDelay 7500 // when SIG_BOOTOK==0 (PI in unknown state): if button is held + // for this long, force shutdown (this should be less than RecycleTime) +#define ShutdownFinalDelay 4500 // after shutdown signal is received, delay for this long // to allow all PI LEDs to stop activity (pulse LED faster) -#define PRINTPERIOD 1000 +#define PRINTPERIOD 10000 int lastValidReading = 1; unsigned long lastValidReadingTime = 0; -unsigned long now=0; +unsigned long NOW=0; int PowerState = 0; long lastPeriod = -1; float systemVoltage = 5; @@ -80,46 +79,85 @@ float systemVoltage = 5; void setup() { Serial.begin(115200); pinMode(BUTTON, INPUT_PULLUP); - pinMode(SIG_OKTOCUTOFF, INPUT); - pinMode(SIG_REQUESTHALT, OUTPUT); + pinMode(SIG_BOOTOK, INPUT); + pinMode(SIG_SHUTOFF, OUTPUT); pinMode(LED, OUTPUT); pinMode(OUTPUT_5V, OUTPUT); pinMode(A7, INPUT); - digitalWrite(SIG_REQUESTHALT, LOW);//added after sudden shutdown quirks, DO NOT REMOVE! + digitalWrite(SIG_SHUTOFF, LOW);//added after sudden shutdown quirks, DO NOT REMOVE! digitalWrite(OUTPUT_5V, LOW);//added after sudden shutdown quirks, DO NOT REMOVE! } void loop() { int reading = digitalRead(BUTTON); - now = millis(); - digitalWrite(SIG_REQUESTHALT, LOW);//added after sudden shutdown quirks, DO NOT REMOVE! - + NOW = millis(); + digitalWrite(SIG_SHUTOFF, LOW);//added after sudden shutdown quirks, DO NOT REMOVE! boolean batteryLow = systemVoltage < LOWBATTERYTHRESHOLD; - - if (batteryLow || reading != lastValidReading && now - lastValidReadingTime > 200) { + + if (batteryLow || reading != lastValidReading && NOW - lastValidReadingTime > 200) + { lastValidReading = reading; - lastValidReadingTime = now; - //((PowerState==0 && ()) || (PowerState==1 && (now - lastValidReadingTime > ButtonHoldTime))) + lastValidReadingTime = NOW; + if (batteryLow || reading == 0) { - //make sure the button is held down for at least 'ButtonHoldTime' before taking action (this is to avoid accidental button presses and consequently Pi shutdowns) - now = millis(); - while (!batteryLow && (PowerState == 1 && millis()-now < ButtonHoldTime)) { delay(10); if (digitalRead(BUTTON) != 0) return; } - - //SIG_OKTOCUTOFF must be HIGH when Pi is ON. During boot, this will take a while to happen (till it executes the "shutdowncheck" script + //make sure the button is held down for at least 'RESETHOLDTIME' before taking action (this is to avoid accidental button presses and consequently Pi shutdowns) + NOW = millis(); + while (!batteryLow && (PowerState == 1 && millis()-NOW < RESETHOLDTIME)) { delay(10); if (digitalRead(BUTTON) != 0) return; } + + //RESETHOLDTIME is satisfied, now check if button still held until SHUTDOWNHOLDTIME is satisfied + analogWrite(LED, 128); //dim the LED to show something's going on + while (!batteryLow && (PowerState == 1 && millis()-NOW < SHUTDOWNHOLDTIME)) + { + if (digitalRead(BUTTON) != 0) + { + if (BOOTOK()) //SIG_BOOTOK is HIGH so Pi is running the shutdowncheck.sh script, ready to intercept the RESET PULSE + { + digitalWrite(SIG_SHUTOFF, HIGH); + delay(RESETPULSETIME); + digitalWrite(SIG_SHUTOFF, LOW); + + NOW = millis(); + boolean recycleDetected=false; + while (millis()-NOW < RecycleTime) //blink LED while waiting for BOOTOK to go high + { + //blink 3 times and pause + digitalWrite(LED, LOW); + delay(100); + digitalWrite(LED, HIGH); + delay(100); + digitalWrite(LED, LOW); + delay(100); + digitalWrite(LED, HIGH); + delay(100); + digitalWrite(LED, LOW); + delay(100); + digitalWrite(LED, HIGH); + delay(500); + + if (!BOOTOK()) recycleDetected = true; + else if (BOOTOK() && recycleDetected) + return; + } + return; //reboot pulse sent but it appears a reboot failed; exit all checks + } + else return; //ignore everything else (button was held for RESETHOLDTIME, but SIG_BOOTOK was LOW) + } + } + + //SIG_BOOTOK must be HIGH when Pi is ON. During boot, this will take a while to happen (till it executes the "shutdowncheck" script) //so I dont want to cutoff power before it had a chance to fully boot up - //if (batteryLow || (PowerState == 1 && digitalRead(SIG_OKTOCUTOFF)==1)) - if (batteryLow || (PowerState == 1 && analogRead(SIG_OKTOCUTOFF)>800)) + if (batteryLow || (PowerState == 1 && BOOTOK())) { // signal Pi to shutdown - digitalWrite(SIG_REQUESTHALT, HIGH); + digitalWrite(SIG_SHUTOFF, HIGH); //now wait for the Pi to signal back - now = millis(); + NOW = millis(); float in, out; boolean forceShutdown = true; - while (millis()-now < PIShutdownDelay_Max) + while (millis()-NOW < RecycleTime) { if (in > 6.283) in = 0; in += .00628; @@ -128,29 +166,26 @@ void loop() { analogWrite(LED,out); delayMicroseconds(1500); - //account for force-shutdown action (if button held for PIForceShutdownDelay, then force shutdown regardless) - if (millis()-now <= (PIForceShutdownDelay-ButtonHoldTime) && digitalRead(BUTTON) != 0) + //account for force-shutdown action (if button held for ForcedShutoffDelay, then force shutdown regardless) + if (millis()-NOW <= (ForcedShutoffDelay-SHUTDOWNHOLDTIME) && digitalRead(BUTTON) != 0) forceShutdown = false; - if (millis()-now >= (PIForceShutdownDelay-ButtonHoldTime) && forceShutdown) + if (millis()-NOW >= (ForcedShutoffDelay-SHUTDOWNHOLDTIME) && forceShutdown) { PowerState = 0; digitalWrite(LED, PowerState); //turn off LED to indicate power is being cutoff - digitalWrite(OUTPUT_5V, PowerState); //digitalWrite(LED, PowerState); + digitalWrite(OUTPUT_5V, PowerState); break; } - if (millis() - now > PIShutdownDelay_Min) + if (millis() - NOW > ShutoffTriggerDelay) { // Pi signaling OK to turn off - //if (digitalRead(SIG_OKTOCUTOFF) == 0) - if (analogRead(SIG_OKTOCUTOFF) < 800) + if (!BOOTOK()) { PowerState = 0; digitalWrite(LED, PowerState); //turn off LED to indicate power is being cutoff - - //delay(3500); //takes about 3sec between SIG_OKTOCUTOFF going LOW and Pi LEDs activity to stop - now = millis(); - while (millis()-now < ShutdownFINALDELAY) + NOW = millis(); + while (millis()-NOW < ShutdownFinalDelay) { if (in > 6.283) in = 0; in += .00628; @@ -160,7 +195,7 @@ void loop() { delayMicroseconds(300); } - digitalWrite(OUTPUT_5V, PowerState); //digitalWrite(LED, PowerState); + digitalWrite(OUTPUT_5V, PowerState); break; } } @@ -173,22 +208,21 @@ void loop() { digitalWrite(OUTPUT_5V, PowerState); } - digitalWrite(SIG_REQUESTHALT, LOW); + digitalWrite(SIG_SHUTOFF, LOW); } - //else if (PowerState == 1 && digitalRead(SIG_OKTOCUTOFF)==0) - else if (PowerState == 1 && analogRead(SIG_OKTOCUTOFF)<800) + else if (PowerState == 1 && !BOOTOK()) { - now = millis(); - unsigned long now2 = millis(); - int analogstep = 255 / ((PIForceShutdownDelay-ButtonHoldTime)/100); //every 500ms decrease LED intensity + NOW = millis(); + unsigned long NOW2 = millis(); + int analogstep = 255 / ((ForcedShutoffDelay-SHUTDOWNHOLDTIME)/100); //every 500ms decrease LED intensity while (digitalRead(BUTTON) == 0) { - if (millis()-now2 > 100) + if (millis()-NOW2 > 100) { - analogWrite(LED, 255 - ((millis()-now)/100)*analogstep); - now2 = millis(); + analogWrite(LED, 255 - ((millis()-NOW)/100)*analogstep); + NOW2 = millis(); } - if (millis()-now > PIForceShutdownDelay-ButtonHoldTime) + if (millis()-NOW > ForcedShutoffDelay-SHUTDOWNHOLDTIME) { //TODO: add blinking here to signal final shutdown delay PowerState = 0; @@ -203,10 +237,10 @@ void loop() { digitalWrite(OUTPUT_5V, PowerState); //digitalWrite(LED, PowerState); } } - + digitalWrite(LED, PowerState); } - + int currPeriod = millis()/PRINTPERIOD; if (currPeriod != lastPeriod) { @@ -218,4 +252,8 @@ void loop() { Serial.println(" (plugged in)"); else Serial.println(" (running from battery!)"); } +} + +boolean BOOTOK() { + return analogRead(SIG_BOOTOK) > 800; } \ No newline at end of file diff --git a/Examples/Node/Node.ino b/Examples/Node/Node.ino index c040a76..2ea21aa 100644 --- a/Examples/Node/Node.ino +++ b/Examples/Node/Node.ino @@ -17,7 +17,6 @@ //#define FREQUENCY RF69_915MHZ #define ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes! //#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! -#define ACK_TIME 30 // max # of ms to wait for an ack #ifdef __AVR_ATmega1284P__ #define LED 15 // Moteino MEGAs have LEDs on D15 #define FLASH_SS 23 // and FLASH SS on D23 @@ -28,7 +27,7 @@ #define SERIAL_BAUD 115200 -int TRANSMITPERIOD = 300; //transmit a packet to gateway so often (in ms) +int TRANSMITPERIOD = 150; //transmit a packet to gateway so often (in ms) char payload[] = "123 ABCDEFGHIJKLMNOPQRSTUVWXYZ"; char buff[20]; byte sendSize=0; @@ -43,6 +42,7 @@ void setup() { radio.setHighPower(); //uncomment only for RFM69HW! #endif radio.encrypt(ENCRYPTKEY); + //radio.setFrequency(919000000); //set frequency to some custom frequency char buff[50]; sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); Serial.println(buff); @@ -125,33 +125,37 @@ void loop() { radio.sendACK(); Serial.print(" - ACK sent"); } - Blink(LED,5); + Blink(LED,3); Serial.println(); } - //send FLASH id - if(sendSize==0) - { - sprintf(buff, "FLASH_MEM_ID:0x%X", flash.readDeviceId()); - byte buffLen=strlen(buff); - radio.sendWithRetry(GATEWAYID, buff, buffLen); - sendSize = (sendSize + 1) % 31; - } - int currPeriod = millis()/TRANSMITPERIOD; if (currPeriod != lastPeriod) { lastPeriod=currPeriod; - Serial.print("Sending["); - Serial.print(sendSize); - Serial.print("]: "); - for(byte i = 0; i < sendSize; i++) - Serial.print((char)payload[i]); - - if (radio.sendWithRetry(GATEWAYID, payload, sendSize)) - Serial.print(" ok!"); - else Serial.print(" nothing..."); - + + //send FLASH id + if(sendSize==0) + { + sprintf(buff, "FLASH_MEM_ID:0x%X", flash.readDeviceId()); + byte buffLen=strlen(buff); + if (radio.sendWithRetry(GATEWAYID, buff, buffLen)) + Serial.print(" ok!"); + else Serial.print(" nothing..."); + //sendSize = (sendSize + 1) % 31; + } + else + { + Serial.print("Sending["); + Serial.print(sendSize); + Serial.print("]: "); + for(byte i = 0; i < sendSize; i++) + Serial.print((char)payload[i]); + + if (radio.sendWithRetry(GATEWAYID, payload, sendSize)) + Serial.print(" ok!"); + else Serial.print(" nothing..."); + } sendSize = (sendSize + 1) % 31; Serial.println(); Blink(LED,3); @@ -164,4 +168,4 @@ void Blink(byte PIN, int DELAY_MS) digitalWrite(PIN,HIGH); delay(DELAY_MS); digitalWrite(PIN,LOW); -} \ No newline at end of file +} diff --git a/Examples/OLEDMote/OLEDMote.ino b/Examples/OLEDMote/OLEDMote.ino index 7ab07f5..31be141 100644 --- a/Examples/OLEDMote/OLEDMote.ino +++ b/Examples/OLEDMote/OLEDMote.ino @@ -59,7 +59,7 @@ #define BUTTON_PIN 3 //user button on interrupt 1 RFM69 radio; -U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); // I2C / TWI SSD1306 OLED 128x64 +U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); // I2C / TWI SSD1306 OLED 128x64 bool promiscuousMode = true; //set to 'true' to sniff all packets on the same network void setup() { diff --git a/Examples/PiGateway/PiGateway.ino b/Examples/PiGateway/PiGateway.ino new file mode 100644 index 0000000..b9d3dd2 --- /dev/null +++ b/Examples/PiGateway/PiGateway.ino @@ -0,0 +1,146 @@ +// ********************************************************************************************************** +// GarageMote garage door controller base receiver sketch that works with Moteinos equipped with HopeRF RFM69W/RFM69HW +// Can be adapted to use Moteinos using RFM12B +// This is the sketch for the base, not the controller itself, and meant as another example on how to use a +// Moteino as a gateway/base/receiver +// 2014-07-14 (C) felix@lowpowerlab.com, http://www.LowPowerLab.com +// ********************************************************************************************************** +// Creative Commons Attrib Share-Alike License +// You are free to use/extend this code/library but please abide with the CCSA license: +// http://creativecommons.org/licenses/by-sa/4.0/ +// ********************************************************************************** + +#include //get it here: http://github.com/lowpowerlab/rfm69 +#include //get it here: http://github.com/lowpowerlab/spiflash +#include //get it here: https://github.com/LowPowerLab/WirelessProgramming +#include //comes with Arduino IDE (www.arduino.cc) + +//***************************************************************************************************************************** +// ADJUST THE SETTINGS BELOW DEPENDING ON YOUR HARDWARE/SITUATION! +//***************************************************************************************************************************** +#define NODEID 1 +#define NETWORKID 200 +#define FREQUENCY RF69_915MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ) +#define ENCRYPTKEY "sampleEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less! +#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! +#define LED 9 +#define FLASH_CS 8 +#define SERIAL_BAUD 115200 +#define SERIAL_EN //comment out if you don't want any serial verbose output +#define ACK_TIME 30 // # of ms to wait for an ack +//***************************************************************************************************************************** + +#ifdef SERIAL_EN + #define DEBUG(input) {Serial.print(input); delay(1);} + #define DEBUGln(input) {Serial.println(input); delay(1);} +#else + #define DEBUG(input); + #define DEBUGln(input); +#endif + +RFM69 radio; +SPIFlash flash(FLASH_CS, 0xEF30); //EF40 for 16mbit windbond chip + +void setup() { + Serial.begin(SERIAL_BAUD); + delay(10); + radio.initialize(FREQUENCY,NODEID,NETWORKID); +#ifdef IS_RFM69HW + radio.setHighPower(); //uncomment only for RFM69HW! +#endif + radio.encrypt(ENCRYPTKEY); + char buff[50]; + sprintf(buff, "\nListening at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); + DEBUGln(buff); + if (flash.initialize()) + { + DEBUGln("SPI Flash Init OK!"); + } + else + DEBUGln("SPI Flash Init FAIL! (is chip present?)"); +} + +byte ackCount=0; +byte inputLen=0; +char input[64]; +byte buff[61]; +String inputstr; +void loop() { + inputLen = readSerialLine(input); + inputstr = String(input); + inputstr.toUpperCase(); + + if (inputLen > 0) + { + if (inputstr.equals("KEY?")) + { + DEBUG("ENCRYPTKEY:"); + DEBUG(ENCRYPTKEY); + } + + byte targetId = inputstr.toInt(); //extract ID if any + byte colonIndex = inputstr.indexOf(":"); //find position of first colon + if (targetId > 0) inputstr = inputstr.substring(colonIndex+1); //trim "ID:" if any + if (targetId > 0 && targetId != NODEID && targetId != RF69_BROADCAST_ADDR && colonIndex>0 && colonIndex<4 && inputstr.length()>0) + { + + inputstr.getBytes(buff, 61); + //DEBUGln((char*)buff); + //DEBUGln(targetId); + //DEBUGln(colonIndex); + if (radio.sendWithRetry(targetId, buff, inputstr.length())) + { + DEBUGln("ACK:OK"); + } + else + DEBUGln("ACK:NOK"); + } + } + + if (radio.receiveDone()) + { + int rssi = radio.RSSI; + DEBUG('[');DEBUG(radio.SENDERID);DEBUG("] "); + if (radio.DATALEN > 0) + { + for (byte i = 0; i < radio.DATALEN; i++) + DEBUG((char)radio.DATA[i]); + DEBUG(" [RSSI:");DEBUG(rssi);DEBUG("]"); + } + + CheckForWirelessHEX(radio, flash, false); //non verbose DEBUG + + if (radio.ACKRequested()) + { + byte theNodeID = radio.SENDERID; + radio.sendACK(); + DEBUG("[ACK-sent]"); + } + DEBUGln(); + Blink(LED,3); + } +} + +void Blink(byte PIN, int DELAY_MS) +{ + pinMode(PIN, OUTPUT); + digitalWrite(PIN,HIGH); + delay(DELAY_MS); + digitalWrite(PIN,LOW); +} + +//readSerialLine already defined in WirelessHEX69 +// reads a line feed (\n) terminated line from the serial stream +// returns # of bytes read, up to 255 +// timeout in ms, will timeout and return after so long +//byte readSerialLine(char* input, char endOfLineChar=10, byte maxLength=64, uint16_t timeout=10); +//byte readSerialLine(char* input, char endOfLineChar, byte maxLength, uint16_t timeout) +//{ +// byte inputLen = 0; +// Serial.setTimeout(timeout); +// inputLen = Serial.readBytesUntil(endOfLineChar, input, maxLength); +// input[inputLen]=0;//null-terminate it +// Serial.setTimeout(0); +// //Serial.println(); +// return inputLen; +//} diff --git a/Examples/PiGateway/PiGateway_withLCD.ino b/Examples/PiGateway/PiGateway_withLCD.ino new file mode 100644 index 0000000..da80fe5 --- /dev/null +++ b/Examples/PiGateway/PiGateway_withLCD.ino @@ -0,0 +1,186 @@ +// ********************************************************************************************************** +// GarageMote garage door controller base receiver sketch that works with Moteinos equipped with HopeRF RFM69W/RFM69HW +// Can be adapted to use Moteinos using RFM12B +// This is the sketch for the base, not the controller itself, and meant as another example on how to use a +// Moteino as a gateway/base/receiver +// 2014-07-14 (C) felix@lowpowerlab.com, http://www.LowPowerLab.com +// ********************************************************************************************************** +// Creative Commons Attrib Share-Alike License +// You are free to use/extend this code/library but please abide with the CCSA license: +// http://creativecommons.org/licenses/by-sa/4.0/ +// ********************************************************************************** + +#include //get it here: http://github.com/lowpowerlab/rfm69 +#include //get it here: http://github.com/lowpowerlab/spiflash +#include //get it here: https://github.com/LowPowerLab/WirelessProgramming +#include //comes with Arduino IDE (www.arduino.cc) +#include "ST7036.h" //get it from here: https://bitbucket.org/fmalpartida/st7036-display-driver/src/ +#include "LCD_C0220BiZ.h" //get it from here: https://bitbucket.org/fmalpartida/st7036-display-driver/src/ +#include //comes with Arduino + +//***************************************************************************************************************************** +// ADJUST THE SETTINGS BELOW DEPENDING ON YOUR HARDWARE/SITUATION! +//***************************************************************************************************************************** +#define NODEID 1 +#define NETWORKID 200 +#define FREQUENCY RF69_915MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ) +#define ENCRYPTKEY "thisIsEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less! +#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! +#define LED 9 +#define FLASH_CS 8 +#define SERIAL_BAUD 115200 +#define SERIAL_EN //comment out if you don't want any serial verbose output +#define ACK_TIME 30 // # of ms to wait for an ack +#define BACKLIGHTPIN 5 //3=R,5=G,6=B +//***************************************************************************************************************************** + +#ifdef SERIAL_EN + #define DEBUG(input) {Serial.print(input); delay(1);} + #define DEBUGln(input) {Serial.println(input); delay(1);} +#else + #define DEBUG(input); + #define DEBUGln(input); +#endif + +RFM69 radio; +SPIFlash flash(FLASH_CS, 0xEF30); //EF40 for 16mbit windbond chip + +//initialize LCD +ST7036 lcd = ST7036(2, 20, 0x78, BACKLIGHTPIN); //row count, column count, I2C addr, pin for backlight PWM +byte battChar[8] = {0b00000,0b01110,0b11111,0b11111,0b11111,0b11111,0b11111,0}; +byte rssiChar[8] = {0b00000,0b00100,0b10101,0b01110,0b00100,0b00100,0b00100,0}; + +void setup() { + Serial.begin(SERIAL_BAUD); + delay(10); + radio.initialize(FREQUENCY,NODEID,NETWORKID); +#ifdef IS_RFM69HW + radio.setHighPower(); //uncomment only for RFM69HW! +#endif + radio.encrypt(ENCRYPTKEY); + char buff[50]; + sprintf(buff, "\nListening @ %dmhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); + DEBUGln(buff); + if (flash.initialize()) + { + DEBUGln("SPI Flash Init OK!"); + } + else + DEBUGln("SPI Flash Init FAIL! (is chip present?)"); + + lcd.init(); + lcd.setContrast(10); + lcd.clear(); + lcd.load_custom_character(0, battChar); + lcd.load_custom_character(1, rssiChar); + lcd.setCursor(0,0); + lcd.print(buff); +} + +byte ackCount=0; +byte inputLen=0; +char input[64]; +byte buff[61]; +char LO[20]; +char BAT[20]; +char temp[25]; +String inputstr; +void loop() { + inputLen = readSerialLine(input, 10, 64, 10); //readSerialLine(char* input, char endOfLineChar=10, byte maxLength=64, uint16_t timeout=10); + inputstr = String(input); + inputstr.toUpperCase(); + + if (inputLen > 0) + { + if (inputstr.equals("KEY?")) + { + DEBUG("ENCRYPTKEY:"); + DEBUG(ENCRYPTKEY); + } + + byte targetId = inputstr.toInt(); //extract ID if any + byte colonIndex = inputstr.indexOf(":"); //find position of first colon + if (targetId > 0) inputstr = inputstr.substring(colonIndex+1); //trim "ID:" if any + if (targetId > 0 && targetId != NODEID && targetId != RF69_BROADCAST_ADDR && colonIndex>0 && colonIndex<4 && inputstr.length()>0) + { + + inputstr.getBytes(buff, 61); + //DEBUGln((char*)buff); + //DEBUGln(targetId); + //DEBUGln(colonIndex); + if (radio.sendWithRetry(targetId, buff, inputstr.length())) + { + DEBUGln("ACK:OK"); + } + else + DEBUGln("ACK:NOK"); + } + } + + if (radio.receiveDone()) + { + int rssi = radio.RSSI; + DEBUG('[');DEBUG(radio.SENDERID);DEBUG("] "); + if (radio.DATALEN > 0) + { + for (byte i = 0; i < radio.DATALEN; i++) + DEBUG((char)radio.DATA[i]); + DEBUG(" [RSSI:");DEBUG(rssi);DEBUG("]"); + } + + CheckForWirelessHEX(radio, flash, false); //non verbose DEBUG + + if (radio.ACKRequested()) + { + byte theNodeID = radio.SENDERID; + radio.sendACK(); + DEBUG("[ACK-sent]"); + } + DEBUGln(); + Blink(LED,3); + + lcd.clear(); + lcd.setCursor(0,0); + + //if (radio.DATALEN < RF69_MAX_DATA_LEN) radio.DATA[radio.DATALEN]=0; + byte matches = sscanf((const char*)radio.DATA, "%s BAT:%s", LO, BAT); + if (matches==2) + { + lcd.print(LO); + lcd.setCursor(0,14); + lcd.print(char(0)); + lcd.setCursor(0,15); + lcd.print(BAT); + } + else lcd.print((const char*)radio.DATA); + + lcd.setCursor(1,14); + lcd.print(char(1)); + lcd.setCursor(1,16); + lcd.print(rssi); + } +} + +void Blink(byte PIN, int DELAY_MS) +{ + pinMode(PIN, OUTPUT); + digitalWrite(PIN,HIGH); + delay(DELAY_MS); + digitalWrite(PIN,LOW); +} + +//readSerialLine already defined in WirelessHEX69 +// reads a line feed (\n) terminated line from the serial stream +// returns # of bytes read, up to 255 +// timeout in ms, will timeout and return after so long +//byte readSerialLine(char* input, char endOfLineChar=10, byte maxLength=64, uint16_t timeout=10); +//byte readSerialLine(char* input, char endOfLineChar, byte maxLength, uint16_t timeout) +//{ +// byte inputLen = 0; +// Serial.setTimeout(timeout); +// inputLen = Serial.readBytesUntil(endOfLineChar, input, maxLength); +// input[inputLen]=0;//null-terminate it +// Serial.setTimeout(0); +// //Serial.println(); +// return inputLen; +//} diff --git a/Examples/PulseMeter/PulseMeter.ino b/Examples/PulseMeter/PulseMeter.ino new file mode 100644 index 0000000..335303d --- /dev/null +++ b/Examples/PulseMeter/PulseMeter.ino @@ -0,0 +1,261 @@ +// Sample RFM69 sketch for PulseMote - reading an EE-SY310 based water/pulse meter +// Example: https://lowpowerlab.com/blog/2013/02/02/meet-the-watermote-moteino-based-water-meter-reader-ee-sy310/ +// Copyright (c) 2015 Felix Rusu (felix@lowpowerlab.com). All rights reserved. +// ********************************************************************************** +// License +// ********************************************************************************** +// This program is free software; you can redistribute it +// and/or modify it under the terms of the GNU General +// Public License as published by the Free Software +// Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will +// be useful, but WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A +// PARTICULAR PURPOSE. See the GNU General Public +// License for more details. +// +// You should have received a copy of the GNU General +// Public License along with this program. +// If not, see . +// +// Licence can be viewed at +// http://www.gnu.org/licenses/gpl-3.0.txt +// +// Please maintain this license information along with authorship +// and copyright notices in any redistribution of this code +// *************************************************************************************************************************** +#include //get it here: http://github.com/lowpowerlab/rfm69 +#include //get it here: http://github.com/lowpowerlab/spiflash +#include //get it here: https://github.com/LowPowerLab/WirelessProgramming +#include +#include +#include +//********************************************************************************************* +//************ IMPORTANT SETTINGS - YOU MUST CHANGE/ONFIGURE TO FIT YOUR HARDWARE ************* +//********************************************************************************************* +#define NODEID 5 +#define GATEWAYID 1 +#define NETWORKID 250 +#define FREQUENCY RF69_915MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ) +#define ENCRYPTKEY "sampleEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less! +//#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! +#define PULSESPERGALLON 45 //how many pulses from sensor equal 1 gallon +#define GPMTHRESHOLD 8000 // GPM will reset after this many MS if no pulses are registered +#define XMITPERIOD 5000 // GPMthreshold should be less than 2*XMITPERIOD +//********************************************************************************************* +#ifdef __AVR_ATmega1284P__ + #define LED 15 // Moteino MEGAs have LEDs on D15 + #define INTERRUPTPIN 1 //INT1 = digital pin 11 (must be a hardware interrupt pin!) +#else + #define LED 9 // Moteinos have LEDs on D9 + #define INTERRUPTPIN 1 //INT1 = digital pin 3 (must be a hardware interrupt pin!) +#endif +//********************************************************************************************* +#define SERIAL_EN //uncomment this line to enable serial IO (when you debug Moteino and need serial output) +#define SERIAL_BAUD 115200 +#ifdef SERIAL_EN + #define DEBUG(input) {Serial.print(input);} + #define DEBUGln(input) {Serial.println(input);} +#else + #define DEBUG(input); + #define DEBUGln(input); +#endif + +RFM69 radio; +SPIFlash flash(8, 0xEF30); //WINDBOND 4MBIT flash chip on CS pin D8 (default for Moteino) + +volatile byte ledState = LOW; +volatile unsigned long PulseCounterVolatile = 0; // use volatile for shared variables +unsigned long NOW = 0; +unsigned long PulseCounter = 0; +unsigned long LASTMINUTEMARK = 0; +unsigned long PULSECOUNTLASTMINUTEMARK = 0; //keeps pulse count at the last minute mark + +byte COUNTEREEPROMSLOTS = 10; +unsigned long COUNTERADDRBASE = 8; //address in EEPROM that points to the first possible slot for a counter +unsigned long COUNTERADDR = 0; //address in EEPROM that points to the latest Counter in EEPROM +byte secondCounter = 0; + +unsigned long TIMESTAMP_pulse_prev = 0; +unsigned long TIMESTAMP_pulse_curr = 0; +int pulseAVGInterval = 0; +int pulsesPerXMITperiod = 0; +float GPM=0, GLM=0, GAL=0, GALlast=0, GPMlast=0, GLMlast=0; +byte sendLen; +char buff[80]; +char* GALstr="99999999999999.99"; //longest expected GAL message +char* GPMstr="99999.99"; //longest expected GPM message +char* GLMstr="9999999.99"; //longest expected GLM message +boolean WPReady = false; + +void setup() { + #ifdef SERIAL_EN + Serial.begin(SERIAL_BAUD); + #endif + + radio.initialize(FREQUENCY,NODEID,NETWORKID); +#ifdef IS_RFM69HW + radio.setHighPower(); //uncomment only for RFM69HW! +#endif + radio.encrypt(ENCRYPTKEY); + pinMode(LED, OUTPUT); + + //initialize counter from EEPROM + unsigned long savedCounter = EEPROM_Read_Counter(); + if (savedCounter <=0) savedCounter = 1; //avoid division by 0 + PulseCounterVolatile = PulseCounter = PULSECOUNTLASTMINUTEMARK = savedCounter; + attachInterrupt(INTERRUPTPIN, pulseCounterInterrupt, RISING); + Timer1.initialize(XMITPERIOD * 1000L); + Timer1.attachInterrupt(XMIT); + + sprintf(buff, "\nTransmitting at %d Mhz, id:%d nid:%d gid:%d", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915, NODEID, NETWORKID, GATEWAYID); + DEBUG(buff); + for (byte i=0;i GPMTHRESHOLD) + //more than 'GPMthreshold' seconds passed since last pulse... resetting GPM + pulsesPerXMITperiod=pulseAVGInterval=0; + else + { + pulsesPerXMITperiod++; + pulseAVGInterval += TIMESTAMP_pulse_curr - TIMESTAMP_pulse_prev; + } + interrupts(); +} + +void XMIT() +{ + noInterrupts(); + PulseCounter = PulseCounterVolatile; + interrupts(); + + if (millis() - TIMESTAMP_pulse_curr >= 5000) + { + ledState = !ledState; + digitalWrite(LED, ledState); + } + + //calculate Gallons counter + GAL = ((float)PulseCounter)/PULSESPERGALLON; + DEBUG("PulseCounter:");DEBUG(PulseCounter);DEBUG(", GAL: "); DEBUGln(GAL); + + //calculate & output GPM + GPM = pulseAVGInterval > 0 ? 60.0 * 1000 * (1.0/PULSESPERGALLON)/(pulseAVGInterval/pulsesPerXMITperiod) + : 0; + dtostrf(GAL,3,2, GALstr); + dtostrf(GPM,3,2, GPMstr); + + pulsesPerXMITperiod = 0; + pulseAVGInterval = 0; + secondCounter += XMITPERIOD/1000; + + //once per minute, output a GallonsLastMinute count + if (secondCounter>=60) + { + //DEBUG("60sec mark ... "); + secondCounter=0; + GLM = ((float)(PulseCounter - PULSECOUNTLASTMINUTEMARK))/PULSESPERGALLON; + PULSECOUNTLASTMINUTEMARK = PulseCounter; + EEPROM_Write_Counter(PulseCounter); + dtostrf(GLM,3,2, GLMstr); + sprintf(buff, "GAL:%s GPM:%s GLM:%s", GALstr, GPMstr, GLMstr); + //DEBUGln("done"); + } + else + { + sprintf(buff, "GAL:%s GPM:%s", GALstr, GPMstr); + } + + if (GPM!=GPMlast || GAL!=GALlast || GLM!=GLMlast) + { + sendLen = strlen(buff); + radio.sendWithRetry(GATEWAYID, buff, sendLen); + GALlast = GAL; + GPMlast = GPM; + GLMlast = GLM; + } + + DEBUGln(buff); +} + +unsigned long EEPROM_Read_Counter() +{ + return EEPROM_Read_ULong(EEPROM_Read_ULong(COUNTERADDR)); +} + +void EEPROM_Write_Counter(unsigned long counterNow) +{ + if (counterNow == EEPROM_Read_Counter()) + { + DEBUG("{EEPROM-SKIP(no changes)}"); + return; //skip if nothing changed + } + + DEBUG("{EEPROM-SAVE("); + DEBUG(EEPROM_Read_ULong(COUNTERADDR)); + DEBUG(")="); + DEBUG(PulseCounter); + DEBUG("}"); + + unsigned long CounterAddr = EEPROM_Read_ULong(COUNTERADDR); + if (CounterAddr == COUNTERADDRBASE+8*(COUNTEREEPROMSLOTS-1)) + CounterAddr = COUNTERADDRBASE; + else CounterAddr += 8; + + EEPROM_Write_ULong(CounterAddr, counterNow); + EEPROM_Write_ULong(COUNTERADDR, CounterAddr); +} + +unsigned long EEPROM_Read_ULong(int address) +{ + unsigned long temp; + for (byte i=0; i<8; i++) + temp = (temp << 8) + EEPROM.read(address++); + return temp; +} + +void EEPROM_Write_ULong(int address, unsigned long data) +{ + for (byte i=0; i<8; i++) + { + EEPROM.write(address+7-i, data); + data = data >> 8; + } +} diff --git a/Examples/SonarMote/SonarMote_DistanceReader/SonarMote_DistanceReader.ino b/Examples/SonarMote/SonarMote_DistanceReader/SonarMote_DistanceReader.ino new file mode 100644 index 0000000..000e220 --- /dev/null +++ b/Examples/SonarMote/SonarMote_DistanceReader/SonarMote_DistanceReader.ino @@ -0,0 +1,97 @@ +// Sample sketch for the SonarMote - Simple distance reading +// http://lowpowerlab.com/sonar +// Ultrasonic sensor (HC-SR04) connected to D6 (Trig), D7 (Echo), and power enabled through D5 +// Make sure you adjust the settings in the configuration section below !!! +// ********************************************************************************** +// Copyright Felix Rusu, LowPowerLab.com +// Library and code by Felix Rusu - felix@lowpowerlab.com +// ********************************************************************************** +// License +// ********************************************************************************** +// This program is free software; you can redistribute it +// and/or modify it under the terms of the GNU General +// Public License as published by the Free Software +// Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will +// be useful, but WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A +// PARTICULAR PURPOSE. See the GNU General Public +// License for more details. +// +// You should have received a copy of the GNU General +// Public License along with this program. +// If not, see . +// +// Licence can be viewed at +// http://www.gnu.org/licenses/gpl-3.0.txt +// +// Please maintain this license information along with authorship +// and copyright notices in any redistribution of this code +// ********************************************************************************** +#define TRIG 6 +#define ECHO 7 +#define EN 5 + +void setup() { + pinMode (TRIG,OUTPUT);//attach pin 2 to vcc + pinMode (ECHO,OUTPUT);//attach pin 2 to vcc + pinMode (EN,OUTPUT);//attach pin 5 to GND + pinMode (ECHO, INPUT);//attach pin 4 to Echo + // initialize serial communication: + Serial.begin(115200); + digitalWrite(EN, LOW); +} + +long cm; +void loop() +{ + cm = readDistanceCM(); + Serial.print(cm); Serial.println("cm"); + delay(500); +} + +long readDistanceCM() +{ + digitalWrite(EN, HIGH); + delay(75); + // The PING))) is triggered by a HIGH pulse of 2 or more microseconds. + // Give a short LOW pulse beforehand to ensure a clean HIGH pulse: + digitalWrite(TRIG, LOW); + delayMicroseconds(2); + digitalWrite(TRIG, HIGH); + delayMicroseconds(5); + digitalWrite(TRIG, LOW); + pulseIn(ECHO, HIGH); + delay(16); + digitalWrite(TRIG, LOW); + delayMicroseconds(2); + digitalWrite(TRIG, HIGH); + delayMicroseconds(5); + digitalWrite(TRIG, LOW); + // The same pin is used to read the signal from the PING))): a HIGH + // pulse whose duration is the time (in microseconds) from the sending + // of the ping to the reception of its echo off of an object. + long duration = pulseIn(ECHO, HIGH); + digitalWrite(EN, LOW); + return microsecondsToCentimeters(duration); +} + +long microsecondsToInches(long microseconds) +{ + // According to Parallax's datasheet for the PING))), there are + // 73.746 microseconds per inch (i.e. sound travels at 1130 feet per + // second). This gives the distance travelled by the ping, outbound + // and return, so we divide by 2 to get the distance of the obstacle. + // See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf + return microseconds / 74 / 2; +} + +long microsecondsToCentimeters(long microseconds) +{ + // The speed of sound is 340 m/s or 29 microseconds per centimeter. + // The ping travels out and back, so to find the distance of the + // object we take half of the distance travelled. + return microseconds / 29 / 2; +} diff --git a/Examples/SonarMote/SonarMote_DistanceTracker/SonarMote_DistanceTracker.ino b/Examples/SonarMote/SonarMote_DistanceTracker/SonarMote_DistanceTracker.ino new file mode 100644 index 0000000..fd15b46 --- /dev/null +++ b/Examples/SonarMote/SonarMote_DistanceTracker/SonarMote_DistanceTracker.ino @@ -0,0 +1,277 @@ +// Sample RFM69 sender/node sketch for the SonarMote - Distance tracker +// Can be used for inventory control - ex to measure distance in a multi lane cigarette pack rack +// More info/photos at: http://lowpowerlab.com/sonar +// Ultrasonic sensor (HC-SR04) connected to D6 (Trig), D7 (Echo), and power enabled through D5 +// This sketch sleeps the Moteino and sensor most of the time. It wakes up every few seconds to take +// a distance reading. If it detects an approaching object (car) it increases the sampling rate +// and starts lighting up the LED (from green to yellow to red to blinking red). Once there is no more +// motion the LED is turned off and the cycle is back to a few seconds in between sensor reads. +// Button is connected on D3. Holding the button for a few seconds enters the "red zone adjust" mode (RZA). +// By default the red zone limit is at 25cm (LED turns RED below this and starts blinking faster and faster). +// In RZA, readings are taken for 5 seconds. In this time you have the chance to set a new red zone limit. +// Valid new red zone readings are between the RED__LIMIT_UPPER (default 25cm) and MAX_ADJUST_DISTANCE (cm). +// In RZA mode the BLU Led blinks fast to indicate new red limit distance. It blinks slow if the readings are invalid +// If desired this value could be saved to EEPROM to persist if unit is turned off +// Get the RFM69 at: https://github.com/LowPowerLab/ +// Make sure you adjust the settings in the configuration section below !!! +// ********************************************************************************** +// Copyright Felix Rusu, LowPowerLab.com +// Library and code by Felix Rusu - felix@lowpowerlab.com +// ********************************************************************************** +// License +// ********************************************************************************** +// This program is free software; you can redistribute it +// and/or modify it under the terms of the GNU General +// Public License as published by the Free Software +// Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will +// be useful, but WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A +// PARTICULAR PURPOSE. See the GNU General Public +// License for more details. +// +// You should have received a copy of the GNU General +// Public License along with this program. +// If not, see . +// +// Licence can be viewed at +// http://www.gnu.org/licenses/gpl-3.0.txt +// +// Please maintain this license information along with authorship +// and copyright notices in any redistribution of this code +// ********************************************************************************** +#include +#include //get it here: https://www.github.com/lowpowerlab/rfm69 +#include //get it here: https://github.com/LowPowerLab/SPIFlash +#include //get library from: https://github.com/lowpowerlab/lowpower + //writeup here: http://www.rocketscream.com/blog/2011/07/04/lightweight-low-power-arduino-library/ + +//********************************************************************************************* +//************ IMPORTANT SETTINGS - YOU MUST CHANGE/ONFIGURE TO FIT YOUR HARDWARE ************* +//********************************************************************************************* +#define NODEID 22 //unique for each node on same network +#define NETWORKID 100 //the same on all nodes that talk to each other +#define GATEWAYID 1 +//Match frequency to the hardware version of the radio on your Moteino (uncomment one): +//#define FREQUENCY RF69_433MHZ +//#define FREQUENCY RF69_868MHZ +#define FREQUENCY RF69_915MHZ +#define IS_RFM69HW //uncomment only for RFM69HW! Remove/comment if you have RFM69W! +#define ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes! +#define SENDLOOPS 80 //default:80 //if no message was sent for this many sleep loops/cycles, then force a send +#define READ_SAMPLES 3 +//********************************************************************************************* +//#define BUZZER_ENABLE //uncomment this line if you have the BUZZER soldered and want the sketch to make sounds +#define SERIAL_EN //uncomment if you want serial debugging output +//********************************************************************************************* +#define SLEEP_FASTEST SLEEP_15MS +#define SLEEP_FAST SLEEP_250MS +#define SLEEP_SEC SLEEP_1S +#define SLEEP_LONG SLEEP_2S +#define SLEEP_LONGER SLEEP_4S +#define SLEEP_LONGEST SLEEP_8S +period_t sleepTime = SLEEP_LONGEST; //period_t is an enum type defined in the LowPower library (LowPower.h) +//********************************************************************************************* +#ifdef __AVR_ATmega1284P__ + #define LED 15 // Moteino MEGAs have LEDs on D15 + #define FLASH_SS 23 +#else + #define LED 9 // Moteinos have LEDs on D9 + #define FLASH_SS 8 +#endif +#define TRIG 6 // digital pin wired to TRIG pin of ultrasonic sensor +#define ECHO 7 // digital pin wired to ECHO pin of ultrasonic sensor +#define SENSOR_EN 5 // digital pin that enables power to ultrasonic sensor +#define BUZZER 4 // digital pin that is connected to onboard buzzer +#define MAX_DISTANCE 150 // maximum valid distance +#define MIN_DISTANCE 2 // minimum valid distance +#define MAX_ADJUST_DISTANCE (MAX_DISTANCE-GRN_LIMIT_UPPER) //this is the amount by which the RED_LIMIT_UPPER can by increased + +// +#ifdef SERIAL_EN + #define SERIAL_BAUD 115200 + #define DEBUG(input) {Serial.print(input);} + #define DEBUGln(input) {Serial.println(input);} + #define SERIALFLUSH() {Serial.flush();} +#else + #define DEBUG(input); + #define DEBUGln(input); + #define SERIALFLUSH(); +#endif + +#define BATT_MONITOR A7 // Sense VBAT_COND signal (when powered externally should read ~3.25v/3.3v (1000-1023), when external power is cutoff it should start reading around 2.85v/3.3v * 1023 ~= 883 (ratio given by 10k+4.7K divider from VBAT_COND = 1.47 multiplier) +#define BATT_CYCLES SENDLOOPS // read and report battery voltage every this many sleep cycles (ex 30cycles * 8sec sleep = 240sec/4min). For 450 cycles you would get ~1 hour intervals between readings +#define BATT_FORMULA(reading) reading * 0.00322 * 1.475 // >>> fine tune this parameter to match your voltage when fully charged +#define BATT_LOW 3.3 + +byte sendLen; +byte sendLoops=SENDLOOPS; +float distance=0; +float prevDistance=0; +float batteryVolts = 5; +char buff[50]; //this is just an empty string used as a buffer to place the payload for the radio +char* BATstr="BAT:5.00v"; //longest battery voltage reading message = 9chars +char* DISTstr="99999.99cm"; //longest distance reading message = 5chars +void checkBattery(byte samples=10); //take 10 samples by default +float readDistance(byte samples=1); //take 1 samples by default +SPIFlash flash(FLASH_SS, 0xEF30); //EF30 for 4mbit Windbond chip (W25X40CL) +RFM69 radio; + +void setup() { +#ifdef SERIAL_EN + Serial.begin(SERIAL_BAUD); // Open serial monitor at 115200 baud to see ping results. +#endif + + radio.initialize(FREQUENCY,NODEID,NETWORKID); +#ifdef IS_RFM69HW + radio.setHighPower(); //uncomment only for RFM69HW! +#endif + radio.encrypt(ENCRYPTKEY); + //sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); + sprintf(buff, "\nTransmitting at %d Mhz, id:%d nid:%d gid:%d", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915, NODEID, NETWORKID, GATEWAYID); + DEBUG(buff); + for (byte i=0;i 1 || diff < -1) || (--sendLoops==0)) //only send a new message if the distance has changed by at least 1cm + { + if (distance > MAX_DISTANCE || distance < MIN_DISTANCE) + DISTstr = "0"; // zero, out of range + else dtostrf(distance,3,2, DISTstr); + + sprintf(buff, "%scm BAT:%s", DISTstr, BATstr); + sendLen = strlen(buff); + + digitalWrite(LED, HIGH); + DEBUG(buff); + if (radio.sendWithRetry(GATEWAYID, buff, sendLen)) + { + prevDistance = distance; + DEBUG(" - ACK:OK! RSSI:"); + DEBUGln(radio.RSSI); + } + else DEBUGln(" - ACK:NOK..."); + digitalWrite(LED, LOW); + sendLoops = SENDLOOPS; //reset loop counter + } + radio.sleep(); + SERIALFLUSH(); + +// if (radio.sendWithRetry(1, "123 TEST", 8)) +// { +// //prevDistance = distance; +// DEBUG(" - ACK:OK! RSSI:"); +// DEBUGln(radio.RSSI); +// } +// else DEBUGln(" - ACK:NOK..."); +// SERIALFLUSH(); + + LowPower.powerDown(sleepTime, ADC_OFF, BOD_OFF); //put microcontroller to sleep to save battery life +} + +float readDistance(byte samples) +{ + if (samples == 0) samples = 1; + if (samples > 10) samples = 10; + digitalWrite(SENSOR_EN, HIGH); + //need about 60-75ms after power up before HC-SR04 will be usable, so just sleep in the meantime + LowPower.powerDown(SLEEP_60MS, ADC_OFF, BOD_OFF); + LowPower.powerDown(SLEEP_15MS, ADC_OFF, BOD_OFF); + PING(); + LowPower.powerDown(SLEEP_15MS, ADC_OFF, BOD_OFF); + + unsigned long duration = 0; + for (byte i=0; i 1) LowPower.powerDown(SLEEP_15MS, ADC_OFF, BOD_OFF); + } + digitalWrite(SENSOR_EN, LOW); + return microsecondsToCentimeters(duration / samples); +} + +long PING() +{ + digitalWrite(TRIG, LOW); + delayMicroseconds(2); + digitalWrite(TRIG, HIGH); + delayMicroseconds(5); + digitalWrite(TRIG, LOW); + return pulseIn(ECHO, HIGH); +} + +byte cycleCount=BATT_CYCLES; +void checkBattery(byte samples) +{ + if (cycleCount++ == BATT_CYCLES) //only read battery every BATT_CYCLES sleep cycles + { + unsigned int readings=0; + for (byte i=0; i0) delay(repeatsDelay); + } +} +#endif + +void Blink(byte pin) +{ + pinMode(pin, OUTPUT); + digitalWrite(pin, HIGH); + delay(2); + digitalWrite(pin, LOW); +} diff --git a/Examples/SonarMote/SonarMote_Parking/SonarMote_Parking.ino b/Examples/SonarMote/SonarMote_Parking/SonarMote_Parking.ino new file mode 100644 index 0000000..f1f7718 --- /dev/null +++ b/Examples/SonarMote/SonarMote_Parking/SonarMote_Parking.ino @@ -0,0 +1,417 @@ +// Sample sketch for the SonarMote - Standalone parking assist with RGB LED indicator +// This example uses the NewPing library from https://code.google.com/p/arduino-new-ping/ +// but that could be replaced by raw reading of the sonar sensor as seen in other SonarMote examples +// More info/photos at: http://lowpowerlab.com/sonar +// Ultrasonic sensor (HC-SR04) connected to D6 (Trig), D7 (Echo), and power enabled through D5 +// This sketch sleeps the Moteino and sensor most of the time. It wakes up every few seconds to take +// a distance reading. If it detects an approaching object (car) it increases the sampling rate +// and starts lighting up the LED (from green to yellow to red to blinking red). Once there is no more +// motion the LED is turned off and the cycle is back to a few seconds in between sensor reads. +// Button is connected on D3. Holding the button for a few seconds enters the "red zone adjust" mode (RZA). +// By default the red zone limit is at 25cm (LED turns RED below this and starts blinking faster and faster). +// In RZA, readings are taken for 5 seconds. In this time you have the chance to set a new red zone limit. +// Valid new red zone readings are between the RED__LIMIT_UPPER (default 25cm) and MAX_ADJUST_DISTANCE (cm). +// In RZA mode the BLU Led blinks fast to indicate new red limit distance. It blinks slow if the readings are invalid +// If desired this value could be saved to EEPROM to persist if unit is turned off +// Make sure you adjust the settings in the configuration section below !!! + +// ********************************************************************************** +// Copyright Felix Rusu, LowPowerLab.com +// Library and code by Felix Rusu - felix@lowpowerlab.com +// ********************************************************************************** +// License +// ********************************************************************************** +// This program is free software; you can redistribute it +// and/or modify it under the terms of the GNU General +// Public License as published by the Free Software +// Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will +// be useful, but WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A +// PARTICULAR PURPOSE. See the GNU General Public +// License for more details. +// +// You should have received a copy of the GNU General +// Public License along with this program. +// If not, see . +// +// Licence can be viewed at +// http://www.gnu.org/licenses/gpl-3.0.txt +// +// Please maintain this license information along with authorship +// and copyright notices in any redistribution of this code +// ********************************************************************************** +#include // get this library at: https://code.google.com/p/arduino-new-ping/ +#include // get this library at: http://www.rocketscream.com/blog/2011/07/04/lightweight-low-power-arduino-library/ + +#define TRIG 6 // digital pin wired to TRIG pin of ultrasonic sensor +#define ECHO 7 // digital pin wired to ECHO pin of ultrasonic sensor +#define SENSOR_EN 5 // digital pin that enables power to ultrasonic sensor +#define RED A0 // pin connected to red LED +#define GRN A1 // pin connected to green LED +#define BLU A2 // pin connected to blue LED +#define BUTTON_INT 1 // user button on interrupt 1 (D3) +#define BUTTON_PIN 3 // user button on interrupt 1 (D3) +#define BUTTON_HOLD_MS 3000 // hold button this many ms before entering red zone adjust +#define MOTEINOLED 9 // moteino onboard LED +#define MAX_DISTANCE 220 // maximum valid distance +#define MIN_DISTANCE 2 // minimum valid distance + +#define GRN_LIMIT_UPPER 180+redZoneAdjust // upper limit distance for GREEN +#define YLW_LIMIT_UPPER 40+redZoneAdjust // upper limit distance for YELLOW +#define RED_LIMIT_UPPER 25+redZoneAdjust // upper limit distance for RED + +#define MAX_ADJUST_DISTANCE (MAX_DISTANCE-GRN_LIMIT_UPPER) //this is the amount by which the RED_LIMIT_UPPER can by increased + +//possible states of LED status +#define STATE_SOLID 0 +#define STATE_BLINK 1 + +//possible states for LED color +#define STATE_OFF 0 +#define STATE_GRN 1 +#define STATE_YLW 2 +#define STATE_RED 3 + +byte state_LED = STATE_SOLID; +byte state_LEDCOLOR = STATE_OFF; +byte state_LEDONOFF = LOW; +byte redZoneAdjust = 0; //this is adjustable via the button (press button for a few seconds, then take a reading) + +#define LED_RED {digitalWrite(RED,HIGH);digitalWrite(GRN,LOW);} +#define LED_GRN {digitalWrite(RED,LOW);digitalWrite(GRN,HIGH);} +#define LED_YLW {digitalWrite(RED,HIGH);digitalWrite(GRN,HIGH);} +#define LED_OFF {digitalWrite(RED,LOW);digitalWrite(GRN,LOW);} + +#define SERIAL_EN //uncomment if you want serial debugging output +#ifdef SERIAL_EN + #define SERIAL_BAUD 115200 + #define DEBUG(input) {Serial.print(input);} + #define DEBUGln(input) {Serial.println(input);} + #define SERIALFLUSH() {Serial.flush();} +#else + #define DEBUG(input); + #define DEBUGln(input); + #define SERIALFLUSH(); +#endif + +#define SLEEP_MINILOOP SLEEP_15MS +#define SLEEP_LOOP SLEEP_250MS +#define SLEEP_LONG SLEEP_2S +#define SLEEP_LOBATT SLEEP_4S +#define SLEEP_HIBERNATE SLEEP_8S + +#define BATT_MONITOR A7 // Sense VBAT_COND signal (when powered externally should read ~3.25v/3.3v (1000-1023), when external power is cutoff it should start reading around 2.85v/3.3v * 1023 ~= 883 (ratio given by 10k+4.7K divider from VBAT_COND = 1.47 multiplier) +#define BATT_CYCLES 120 // read and report battery voltage every this many sleep cycles (ex 30cycles * 8sec sleep = 240sec/4min). For 450 cyclesyou would get ~1 hour intervals +#define BATT_FORMULA(reading) reading * 0.00322 * 1.475 // >>> fine tune this parameter to match your voltage when fully charged +#define BATT_LOW 3.35 + +NewPing sensor(TRIG, ECHO, MAX_DISTANCE); // NewPing setup of pins and maximum distance. +float readDistance(byte samples=3); //take 3 samples by default +void checkBattery(byte samples=10); //take 10 samples by default +float batteryVolts = 5; + +void setup() { +#ifdef SERIAL_EN + Serial.begin(SERIAL_BAUD); // Open serial monitor at 115200 baud to see ping results. +#endif + pinMode(TRIG, OUTPUT); + pinMode(ECHO, INPUT); + pinMode(RED, OUTPUT); + pinMode(GRN, OUTPUT); + pinMode(BLU, OUTPUT); + pinMode(SENSOR_EN, OUTPUT); + digitalWrite(SENSOR_EN, LOW); + pinMode(BUTTON_PIN, INPUT_PULLUP); + attachInterrupt(BUTTON_INT, buttonInterrupt, FALLING); +} + +#define FLAG_INTERRUPT 0x01 +volatile int mainEventFlags = 0; +boolean buttonPressed = false; +void buttonInterrupt() +{ + mainEventFlags |= FLAG_INTERRUPT; +} + +long distance=0; +long lastDistance=0; +long lastSigDistance=0; +byte loops=0; +byte miniLoops=0; +byte skipBlinkingLoops=5; +unsigned long now=0; +period_t sleepTime = SLEEP_LONG; //period_t is an enum type defined in the LowPower library (LowPower.h) + +void loop() { + if (mainEventFlags & FLAG_INTERRUPT) + { + LowPower.powerDown(SLEEP_30MS, ADC_OFF, BOD_ON); + mainEventFlags &= ~FLAG_INTERRUPT; + if (!digitalRead(BUTTON_PIN)) { + buttonPressed=true; + } + } + + if (buttonPressed) + { + detachInterrupt(BUTTON_INT); + DEBUGln("BUTTON PRESS!"); + unsigned long timestamp = millis(); + while (millis() - timestamp < BUTTON_HOLD_MS) + { + if (digitalRead(BUTTON_PIN)) + { + buttonPressed = false; + break; + } + DEBUG('.');SERIALFLUSH(); + LowPower.powerDown(SLEEP_30MS, ADC_OFF, BOD_ON); + timestamp-=40; + } + + //if it's still pressed after BUTTON_HOLD_MS then enter red zone adjust mode + if (buttonPressed) + { + DEBUG("STILL_PRESSED");SERIALFLUSH(); + handleRedZoneAdjust(); + } + else + { + DEBUG("ABORTED");SERIALFLUSH(); + } + attachInterrupt(BUTTON_INT, buttonInterrupt, FALLING); + } + + + if (miniLoops>0) + { + miniLoops--; + sleepTime = SLEEP_MINILOOP; + //when looping fast we need to wake the sensor about 60-75ms before doing a reading (about 5 miniloops assuming 1 miniloop=15ms) + //otherwise there will be a visible delay in the LED blinking + if (miniLoops == 5) digitalWrite(SENSOR_EN, HIGH); + } + else if (loops > 0) + { + loops--; + miniLoops=16; //16 mini loops translate + sleepTime = SLEEP_MINILOOP; + } + else + //sleep longer when no significant state changes happened + //if battery is low, sleep even longer to try to squeeze more life + sleepTime = (batteryVolts > BATT_LOW ? SLEEP_LONG : SLEEP_LOBATT); + + if ((loops == 0 && miniLoops == 0) || ((miniLoops % skipBlinkingLoops) == 0)) + { + DEBUG('*'); + handleLEDState(); + } + + SERIALFLUSH(); //flush any characters in the serial buffer before sleeping otherwise they get lost or garbled + LowPower.powerDown(sleepTime, ADC_OFF, BOD_OFF); //put microcontroller to sleep to save battery life + if (miniLoops > 0) { DEBUG('.');return; } //as long as we still have miniloops we skip readings + //only proceed to a reading every loop + now = millis(); + distance = readDistance(); + + DEBUGln(); + DEBUG("Read: "); + DEBUG(distance); // Convert ping time to distance in cm and print result (0 = outside set distance range) + DEBUG("cm"); + DEBUG(" ["); + DEBUG(millis()-now); + DEBUGln("]ms"); + + if (distance > MAX_DISTANCE || distance < MIN_DISTANCE) + { + DEBUGln("Out of range"); + loops=0; + lastDistance = distance; + return; + } + + if (distance < GRN_LIMIT_UPPER && distance > YLW_LIMIT_UPPER && abs(lastSigDistance-distance)>20) + { + if (distance < lastSigDistance) + loops=12; //begin looping fast only when object is approaching + lastSigDistance = distance; + } + else if (distance < YLW_LIMIT_UPPER && abs(lastSigDistance-distance)>5) + { + if (distance < lastSigDistance) + loops=12; //begin looping fast only when object is approaching + lastSigDistance = distance; + } + + //if the looping was started, determine the state we're in + if (loops > 0) + { + if (distance >= YLW_LIMIT_UPPER) { state_LEDCOLOR = STATE_GRN; state_LED = STATE_SOLID; } + else if (distance >= RED_LIMIT_UPPER) { state_LEDCOLOR=STATE_YLW; state_LED = STATE_SOLID; } + else { state_LEDCOLOR=STATE_RED; state_LED = STATE_BLINK; } + } + else { state_LEDCOLOR=STATE_OFF; state_LED = STATE_SOLID; } + + //adjust the blinking rate based on the distance to the object + if (state_LEDCOLOR==STATE_RED) + { + if (distance > RED_LIMIT_UPPER-2) + skipBlinkingLoops = 8; + else if (distance > RED_LIMIT_UPPER-6) + skipBlinkingLoops = 6; + else if (lastDistance > RED_LIMIT_UPPER-10) + skipBlinkingLoops = 4; + else if (lastDistance > RED_LIMIT_UPPER-14) + skipBlinkingLoops = 2; + else + { + skipBlinkingLoops = 1; + state_LED = STATE_SOLID; + } + } + else skipBlinkingLoops = 1; + lastDistance = distance; //remember the last reading + checkBattery(); + if (batteryVolts < BATT_LOW) + Blink(BLU); + else Blink(MOTEINOLED); + DEBUG("Batt: "); + DEBUG(batteryVolts); + DEBUGln("v"); +} + +//reads the ultrasonic sensor, takes 3 samples by default +float uS; +float readDistance(byte samples) +{ + uS = 0; + if (loops == 0 && miniLoops == 0) + { + digitalWrite(SENSOR_EN, HIGH); + //need about 60-75ms after power up before HC-SR04 will be usable, so just sleep in the meantime + LowPower.powerDown(SLEEP_60MS, ADC_OFF, BOD_OFF); + LowPower.powerDown(SLEEP_15MS, ADC_OFF, BOD_OFF); + } + + sensor.ping(); + for (byte i=0; i1) delay(4); //need a short delay between samples + } + digitalWrite(SENSOR_EN, LOW); + return (uS / samples) / US_ROUNDTRIP_CM; +} + + +////reads the ultrasonic sensor, takes 3 samples by default +//float readDistance(byte samples) +//{ +// long duration, distance; +// digitalWrite(SENSOR_EN, HIGH); +// delay(75); +// +// digitalWrite(TRIG, LOW); // Added this line +// delayMicroseconds(2); // Added this line +// digitalWrite(TRIG, HIGH); +// delayMicroseconds(10); // Added this line +// digitalWrite(TRIG, LOW); +// pulseIn(ECHO, HIGH); +// +// digitalWrite(TRIG, LOW); // Added this line +// delayMicroseconds(2); // Added this line +// digitalWrite(TRIG, HIGH); +// delayMicroseconds(10); // Added this line +// digitalWrite(TRIG, LOW); +// duration = pulseIn(ECHO, HIGH); +// distance = (duration/2) / 29.1; +// digitalWrite(SENSOR_EN, LOW); +// return distance; +//} + +//handles the status and color of the LED depending what state we are in +void handleLEDState() +{ + switch(state_LEDCOLOR) + { + case STATE_OFF: LED_OFF; break; + case STATE_GRN: LED_GRN; break; + case STATE_YLW: LED_YLW; break; + case STATE_RED: + if (state_LED == STATE_BLINK) + { + if (state_LEDONOFF == HIGH) + { + LED_OFF; + state_LEDONOFF = LOW; + } + else + { + LED_RED; + state_LEDONOFF = HIGH; + } + } + else LED_RED; + break; + } +} + +void Blink(byte pin) +{ + pinMode(pin, OUTPUT); + digitalWrite(pin, HIGH); + delay(2); + digitalWrite(pin, LOW); +} + +byte cycleCount=BATT_CYCLES; +void checkBattery(byte samples) +{ + if (cycleCount++ == BATT_CYCLES) //only read battery every BATT_CYCLES sleep cycles + { + unsigned int readings=0; + for (byte i=0; i MAX_ADJUST_DISTANCE + RED_LIMIT_UPPER-redZoneAdjust) + delay(300); + else if (distance <= RED_LIMIT_UPPER-redZoneAdjust) + state = HIGH; //keep LED on + else + delay (distance); + + DEBUG(distance);DEBUGln("cm");SERIALFLUSH(); + Blink(MOTEINOLED); + } + + digitalWrite(BLU, LOW); //turn LED off + if (distance > RED_LIMIT_UPPER-redZoneAdjust && distance <= MAX_ADJUST_DISTANCE + RED_LIMIT_UPPER-redZoneAdjust) + { + redZoneAdjust = distance - RED_LIMIT_UPPER - redZoneAdjust; + DEBUG("New RED_ZONE_SHIFT = "); DEBUGln(redZoneAdjust);SERIALFLUSH(); + } +} diff --git a/Examples/SonarMote/SonarMote_Parking_Sound_OLED/SonarMote_Parking_Sound_OLED.ino b/Examples/SonarMote/SonarMote_Parking_Sound_OLED/SonarMote_Parking_Sound_OLED.ino new file mode 100644 index 0000000..43f41b7 --- /dev/null +++ b/Examples/SonarMote/SonarMote_Parking_Sound_OLED/SonarMote_Parking_Sound_OLED.ino @@ -0,0 +1,511 @@ +// Sample sketch for the SonarMote - Standalone parking assist with RGB LED indicator, piezo buzzer and OLED display +// This example uses the NewPing library from https://code.google.com/p/arduino-new-ping/ +// but that could be replaced by raw reading of the sonar sensor as seen in other SonarMote examples +// More info/photos at: http://lowpowerlab.com/sonar +// Ultrasonic sensor (HC-SR04) connected to D6 (Trig), D7 (Echo), and power enabled through D5 +// This sketch sleeps the Moteino and sensor most of the time. It wakes up every few seconds to take +// a distance reading. If it detects an approaching object (car) it increases the sampling rate +// and starts lighting up the LED (from green to yellow to red to blinking red). Once there is no more +// motion the LED is turned off and the cycle is back to a few seconds in between sensor reads. +// Button is connected on D3. Holding the button for a few seconds enters the "red zone adjust" mode (RZA). +// By default the red zone limit is at 25cm (LED turns RED below this and starts blinking faster and faster). +// In RZA, readings are taken for 5 seconds. In this time you have the chance to set a new red zone limit. +// Valid new red zone readings are between the RED__LIMIT_UPPER (default 25cm) and MAX_ADJUST_DISTANCE (cm). +// In RZA mode the BLU Led blinks fast to indicate new red limit distance. It blinks slow if the readings are invalid +// If desired this value could be saved to EEPROM to persist if unit is turned off +// Make sure you adjust the settings in the configuration section below !!! + +// ********************************************************************************** +// Copyright Felix Rusu, LowPowerLab.com +// Library and code by Felix Rusu - felix@lowpowerlab.com +// ********************************************************************************** +// License +// ********************************************************************************** +// This program is free software; you can redistribute it +// and/or modify it under the terms of the GNU General +// Public License as published by the Free Software +// Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will +// be useful, but WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A +// PARTICULAR PURPOSE. See the GNU General Public +// License for more details. +// +// You should have received a copy of the GNU General +// Public License along with this program. +// If not, see . +// +// Licence can be viewed at +// http://www.gnu.org/licenses/gpl-3.0.txt +// +// Please maintain this license information along with authorship +// and copyright notices in any redistribution of this code +// ********************************************************************************** +#include // get this library at: http://www.rocketscream.com/blog/2011/07/04/lightweight-low-power-arduino-library/ +//#define BUZZER_ENABLE //uncomment this line if you have the BUZZER soldered and want the sketch to make sounds +//#define OLED_ENABLE //uncomment this line if you have an OLED attached on the SonarMote and want to see the distance printed on it + //the OLED drawing will cause a visible delay in the LED blinking, nothing much to do about it without complicating the sketch a lot more + +#ifdef OLED_ENABLE + #include "U8glib.h" //get library from: https://code.google.com/p/u8glib/ +#endif + +#ifdef __AVR_ATmega1284P__ + #define LED 15 // Moteino MEGAs have LEDs on D15 +#else + #define LED 9 // Moteinos have LEDs on D9 +#endif + +#define TRIG 6 // digital pin wired to TRIG pin of ultrasonic sensor +#define ECHO 7 // digital pin wired to ECHO pin of ultrasonic sensor +#define SENSOR_EN 5 // digital pin that enables power to ultrasonic sensor +#define RED A0 // pin connected to red LED +#define GRN A1 // pin connected to green LED +#define BLU A2 // pin connected to blue LED +#define BUZZER 4 +#define BUTTON_INT 1 // user button on interrupt 1 (D3) +#define BUTTON_PIN 3 // user button on interrupt 1 (D3) +#define BUTTON_HOLD_MS 3000 // hold button this many ms before entering red zone adjust +#define MAX_DISTANCE 220 // maximum valid distance +#define MIN_DISTANCE 2 // minimum valid distance + +#define GRN_LIMIT_UPPER 180+redZoneAdjust // upper limit distance for GREEN +#define YLW_LIMIT_UPPER 40+redZoneAdjust // upper limit distance for YELLOW +#define RED_LIMIT_UPPER 25+redZoneAdjust // upper limit distance for RED + +#define MAX_ADJUST_DISTANCE (MAX_DISTANCE-GRN_LIMIT_UPPER) //this is the amount by which the RED_LIMIT_UPPER can by increased + +//possible states of LED status +#define STATE_SOLID 0 +#define STATE_BLINK 1 + +//possible states for LED color +#define STATE_OFF 0 +#define STATE_GRN 1 +#define STATE_YLW 2 +#define STATE_RED 3 + +byte state_LED = STATE_SOLID; +byte state_LEDCOLOR = STATE_OFF; +byte state_LEDONOFF = LOW; +byte redZoneAdjust = 0; //this is adjustable via the button (press button for a few seconds, then take a reading) + +#define LED_RED {digitalWrite(RED,HIGH);digitalWrite(GRN,LOW);} +#define LED_GRN {digitalWrite(RED,LOW);digitalWrite(GRN,HIGH);} +#define LED_YLW {digitalWrite(RED,HIGH);digitalWrite(GRN,HIGH);} +#define LED_OFF {digitalWrite(RED,LOW);digitalWrite(GRN,LOW);} + +#define SERIAL_EN //uncomment if you want serial debugging output +#ifdef SERIAL_EN + #define SERIAL_BAUD 115200 + #define DEBUG(input) {Serial.print(input);} + #define DEBUGln(input) {Serial.println(input);} + #define SERIALFLUSH() {Serial.flush();} +#else + #define DEBUG(input); + #define DEBUGln(input); + #define SERIALFLUSH(); +#endif + +#define SLEEP_MINILOOP SLEEP_15MS +#define SLEEP_LOOP SLEEP_250MS +#define SLEEP_LONG SLEEP_2S +#define SLEEP_LOBATT SLEEP_4S +#define SLEEP_HIBERNATE SLEEP_8S + +#define BATT_MONITOR A7 // Sense VBAT_COND signal (when powered externally should read ~3.25v/3.3v (1000-1023), when external power is cutoff it should start reading around 2.85v/3.3v * 1023 ~= 883 (ratio given by 10k+4.7K divider from VBAT_COND = 1.47 multiplier) +#define BATT_CYCLES 120 // read and report battery voltage every this many sleep cycles (ex 30cycles * 8sec sleep = 240sec/4min). For 450 cyclesyou would get ~1 hour intervals +#define BATT_FORMULA(reading) reading * 0.00322 * 1.475 // >>> fine tune this parameter to match your voltage when fully charged +#define BATT_LOW 3.35 + +#ifdef OLED_ENABLE + U8GLIB_SSD1306_128X64 OLED(U8G_I2C_OPT_NONE); // I2C / TWI SSD1306 OLED 128x64 +#endif +void checkBattery(byte samples=10); //take 10 samples by default +float batteryVolts = 5; +char buff[50]; + +void setup() { +#ifdef SERIAL_EN + Serial.begin(SERIAL_BAUD); // Open serial monitor at 115200 baud to see ping results. +#endif + pinMode(TRIG, OUTPUT); + pinMode(ECHO, INPUT); + pinMode(RED, OUTPUT); + pinMode(GRN, OUTPUT); + pinMode(BLU, OUTPUT); + pinMode(SENSOR_EN, OUTPUT); + pinMode(BUZZER, OUTPUT); + digitalWrite(SENSOR_EN, LOW); + pinMode(BUTTON_PIN, INPUT_PULLUP); + attachInterrupt(BUTTON_INT, buttonInterrupt, FALLING); + +#ifdef OLED_ENABLE + OLED.setRot180(); //flip screen + // assign default color value + if (OLED.getMode() == U8G_MODE_R3G3B2 ) + OLED.setColorIndex(255); // white + else if (OLED.getMode() == U8G_MODE_GRAY2BIT) + OLED.setColorIndex(3); // max intensity + else if (OLED.getMode() == U8G_MODE_BW) + OLED.setColorIndex(1); // pixel on + else if (OLED.getMode() == U8G_MODE_HICOLOR) + OLED.setHiColorByRGB(255,255,255); + OLED.begin(); + + OLED.firstPage(); + OLED.setFont(u8g_font_unifont); + do { + OLED.drawStr(0, 10, "SonarMote"); + } while(OLED.nextPage()); +#endif + +#ifdef BUZZER_ENABLE + buzzer(50,2,100); +#endif + + readDistance(); //first reading seems to always be low +} + +#define FLAG_INTERRUPT 0x01 +volatile int mainEventFlags = 0; +boolean buttonPressed = false; +void buttonInterrupt() +{ + mainEventFlags |= FLAG_INTERRUPT; +} + +long distance=0; +long lastDistance=0; +long lastSigDistance=0; +byte loops=0; +byte miniLoops=0; +byte skipBlinkingLoops=5; +unsigned long now=0; +period_t sleepTime = SLEEP_LONG; //period_t is an enum type defined in the LowPower library (LowPower.h) + +void loop() { + if (mainEventFlags & FLAG_INTERRUPT) + { + LowPower.powerDown(SLEEP_30MS, ADC_OFF, BOD_ON); + mainEventFlags &= ~FLAG_INTERRUPT; + if (!digitalRead(BUTTON_PIN)) { + buttonPressed=true; + } + } + + if (buttonPressed) + { + detachInterrupt(BUTTON_INT); + DEBUGln("BUTTON PRESS!"); + unsigned long timestamp = millis(); + while (millis() - timestamp < BUTTON_HOLD_MS) + { + if (digitalRead(BUTTON_PIN)) + { + buttonPressed = false; + break; + } + DEBUG('.');SERIALFLUSH(); + LowPower.powerDown(SLEEP_30MS, ADC_OFF, BOD_ON); + timestamp-=40; + } + + //if it's still pressed after BUTTON_HOLD_MS then enter red zone adjust mode + if (buttonPressed) + { + DEBUG("STILL_PRESSED");SERIALFLUSH(); + handleRedZoneAdjust(); + } + else + { + DEBUG("ABORTED");SERIALFLUSH(); + } + attachInterrupt(BUTTON_INT, buttonInterrupt, FALLING); + } + + if (miniLoops>0) + { + miniLoops--; //miniloops starts at + sleepTime = SLEEP_MINILOOP; + //EARLY SENSOR WAKEUP + //When looping fast we need to wake the sensor about 60-75ms before doing a reading (about 5 miniloops assuming 1 miniloop=15ms) + //otherwise there will be a visible delay in the LED blinking + if (miniLoops == 6) digitalWrite(SENSOR_EN, HIGH); + else if (miniLoops == 1) sacrificialPing(); //need 5 miniloops (75ms) between wakeup and dummy reading and another 15ms (1 miniloop) to real reading + //reading will happen when miniLoops==0 + } + else if (loops > 0) + { + loops--; + miniLoops=16; //16 "miniloops" form 1 "loop" (~240ms) + sleepTime = SLEEP_MINILOOP; + } + else + //sleep longer when no significant state changes happened + //if battery is low, sleep even longer to try to squeeze more life + sleepTime = (batteryVolts > BATT_LOW ? SLEEP_LONG : SLEEP_LOBATT); + + if ((loops == 0 && miniLoops == 0) || ((miniLoops % skipBlinkingLoops) == 0)) + { + DEBUG('*'); + handleLEDState(); + } + + SERIALFLUSH(); //flush any characters in the serial buffer before sleeping otherwise they get lost or garbled + LowPower.powerDown(sleepTime, ADC_OFF, BOD_OFF); //put microcontroller to sleep to save battery life + if (miniLoops > 0) { DEBUG('.');return; } //as long as we still have miniloops we skip readings + //only proceed to a reading every loop + now = millis(); + distance = readDistance(); + byte d = millis()-now; +#ifdef OLED_ENABLE + draw(distance); +#endif + + DEBUG("Read: "); + DEBUG(distance); // Convert ping time to distance in cm and print result (0 = outside set distance range) + DEBUG("cm"); + DEBUG(" ["); + DEBUG(d); + DEBUGln("]ms"); + + if (distance > MAX_DISTANCE || distance < MIN_DISTANCE) + { + DEBUGln("Out of range"); + loops=0; + lastDistance = distance; + return; + } + + if (distance < GRN_LIMIT_UPPER && distance > YLW_LIMIT_UPPER && abs(lastSigDistance-distance)>20) + { + if (distance < lastSigDistance) + loops=12; //begin looping fast only when object is approaching + lastSigDistance = distance; + } + else if (distance < YLW_LIMIT_UPPER && abs(lastSigDistance-distance)>5) + { + if (distance < lastSigDistance) + loops=12; //begin looping fast only when object is approaching + lastSigDistance = distance; + } + + //if the looping was started, determine the state we're in + if (loops > 0) + { + if (distance >= YLW_LIMIT_UPPER) { state_LEDCOLOR = STATE_GRN; state_LED = STATE_SOLID; } + else if (distance >= RED_LIMIT_UPPER) { state_LEDCOLOR=STATE_YLW; state_LED = STATE_SOLID; } + else { state_LEDCOLOR=STATE_RED; state_LED = STATE_BLINK; } + } + else { state_LEDCOLOR=STATE_OFF; state_LED = STATE_SOLID; } + + //adjust the blinking rate based on the distance to the object + if (state_LEDCOLOR==STATE_RED) + { + if (distance > RED_LIMIT_UPPER-2) + skipBlinkingLoops = 8; + else if (distance > RED_LIMIT_UPPER-6) + skipBlinkingLoops = 6; + else if (lastDistance > RED_LIMIT_UPPER-10) + skipBlinkingLoops = 4; + else if (lastDistance > RED_LIMIT_UPPER-14) + skipBlinkingLoops = 2; + else + { + skipBlinkingLoops = 1; + state_LED = STATE_SOLID; + } + } + else skipBlinkingLoops = 1; + lastDistance = distance; //remember the last reading + checkBattery(); + if (batteryVolts < BATT_LOW) + Blink(BLU); + else Blink(LED); + DEBUG("Batt: "); + DEBUG(batteryVolts); + DEBUGln("v"); +} + +float readDistance() +{ + //To save battery we need to sleep the HC-SR04 sonar sensor in between readings. + //However to get valid readings it requires special waking up and delay + //It needs to be powered up for ~75ms, then a dummy reading has to be made which is typically bogus + //Then another 15ms needs to pass before doing the real reading + //Because the main loop sleeps between readings and we want to avoid visible delays in the LED blinking + // we need to wake up the sensor in the main loop, look for "EARLY SENSOR WAKEUP". + // When looping fast in the main loop (aka minilooping, to allow fast LED blinking) + // each "miniloop" is about 15ms of sleep time. So we should wake up the sensor 5 miniloops before we do the reading + // and do the sacrificial dummy reading 1 miniloop before the real reading. See the "EARLY SENSOR WAKEUP" code in the main loop. + + //when not looping fast in the main loop, just do the special sensor wakeup here + //first enable sensor power and sleep MCU while sensor settles (needs)75ms + if (loops == 0 && miniLoops == 0) + { + digitalWrite(SENSOR_EN, HIGH); + //need about 60-75ms after power up before HC-SR04 will be usable, so just sleep in the meantime + LowPower.powerDown(SLEEP_60MS, ADC_OFF, BOD_OFF); + LowPower.powerDown(SLEEP_15MS, ADC_OFF, BOD_OFF); + // do a dummy reading first and wait another 15ms for the real reading + sacrificialPing(); + LowPower.powerDown(SLEEP_15MS, ADC_OFF, BOD_OFF); + } + + // Now do the real reading + // The PING))) is triggered by a HIGH pulse of 2 or more microseconds. + // Give a short LOW pulse beforehand to ensure a clean HIGH pulse: + digitalWrite(TRIG, LOW); + delayMicroseconds(2); + digitalWrite(TRIG, HIGH); + delayMicroseconds(5); + digitalWrite(TRIG, LOW); + // The same pin is used to read the signal from the PING))): a HIGH + // pulse whose duration is the time (in microseconds) from the sending + // of the ping to the reception of its echo off of an object. + long duration = pulseIn(ECHO, HIGH); + digitalWrite(SENSOR_EN, LOW); + return microsecondsToCentimeters(duration); +} + +void sacrificialPing() +{ + digitalWrite(TRIG, LOW); + delayMicroseconds(2); + digitalWrite(TRIG, HIGH); + delayMicroseconds(5); + digitalWrite(TRIG, LOW); + pulseIn(ECHO, HIGH); +} + +//handles the status and color of the LED depending what state we are in +void handleLEDState() +{ + switch(state_LEDCOLOR) + { + case STATE_OFF: LED_OFF; break; + case STATE_GRN: LED_GRN; break; + case STATE_YLW: LED_YLW; break; + case STATE_RED: + if (state_LED == STATE_BLINK) + { + if (state_LEDONOFF == HIGH) + { + LED_OFF; + state_LEDONOFF = LOW; + } + else + { + LED_RED; + state_LEDONOFF = HIGH; +#ifdef BUZZER_ENABLE + buzzer(skipBlinkingLoops,0,0); +#endif + } + } + else LED_RED; + break; + } +} + +void Blink(byte pin) +{ + pinMode(pin, OUTPUT); + digitalWrite(pin, HIGH); + delay(2); + digitalWrite(pin, LOW); +} + +byte cycleCount=BATT_CYCLES; +void checkBattery(byte samples) +{ + if (cycleCount++ == BATT_CYCLES) //only read battery every BATT_CYCLES sleep cycles + { + unsigned int readings=0; + for (byte i=0; i MAX_ADJUST_DISTANCE + RED_LIMIT_UPPER-redZoneAdjust) + delay(300); + else if (distance <= RED_LIMIT_UPPER-redZoneAdjust) + state = HIGH; //keep LED on + else + delay (distance); + + DEBUG(distance);DEBUGln("cm");SERIALFLUSH(); + Blink(LED); + } + + digitalWrite(BLU, LOW); //turn LED off + if (distance > RED_LIMIT_UPPER-redZoneAdjust && distance <= MAX_ADJUST_DISTANCE + RED_LIMIT_UPPER-redZoneAdjust) + { + redZoneAdjust = distance - RED_LIMIT_UPPER - redZoneAdjust; + DEBUG("New RED_ZONE_SHIFT = "); DEBUGln(redZoneAdjust);SERIALFLUSH(); + } +} + +float microsecondsToInches(long microseconds) +{ + // According to Parallax's datasheet for the PING))), there are + // 73.746 microseconds per inch (i.e. sound travels at 1130 feet per + // second). This gives the distance travelled by the ping, outbound + // and return, so we divide by 2 to get the distance of the obstacle. + // See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf + return microseconds / 74.0 / 2.0f; +} + +float microsecondsToCentimeters(long microseconds) +{ + // The speed of sound is 340 m/s or 29 microseconds per centimeter. + // The ping travels out and back, so to find the distance of the + // object we take half of the distance travelled. + return (float)microseconds / 29.0f / 2.0f; +} + +#ifdef OLED_ENABLE +void draw(byte distance) { + OLED.firstPage(); + OLED.setFont(u8g_font_unifont); + sprintf(buff, "Reading: %dcm", distance); + + do { + OLED.drawStr(0, 10, buff); + } while(OLED.nextPage()); +} +#endif + +#ifdef BUZZER_ENABLE +void buzzer(byte soundTime, byte repeats, byte repeatsDelay) +{ + for (byte i=0;i<=repeats;i++) + { + tone(BUZZER, 4500); //4500hz makes a nice audible sound from a 3.3v Moteino digital pin + delay(soundTime); + noTone(BUZZER); + if (repeats>0) delay(repeatsDelay); + } +} +#endif diff --git a/Examples/Struct_receive/Struct_receive.ino b/Examples/Struct_receive/Struct_receive.ino index 4b82487..1dd8c5b 100644 --- a/Examples/Struct_receive/Struct_receive.ino +++ b/Examples/Struct_receive/Struct_receive.ino @@ -5,7 +5,7 @@ #define NODEID 1 #define NETWORKID 100 #define FREQUENCY RF69_433MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ) -#define KEY "thisIsEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less! +#define KEY "sampleEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less! #define LED 9 #define SERIAL_BAUD 115200 #define ACK_TIME 30 // # of ms to wait for an ack @@ -14,7 +14,7 @@ RFM69 radio; SPIFlash flash(8, 0xEF30); //EF40 for 16mbit windbond chip bool promiscuousMode = false; //set to 'true' to sniff all packets on the same network -typedef struct { +typedef struct { int nodeId; //store this nodeId unsigned long uptime; //uptime in ms float temp; //temperature maybe? @@ -88,10 +88,10 @@ void loop() { Serial.print('[');Serial.print(radio.SENDERID, DEC);Serial.print("] "); Serial.print(" [RX_RSSI:");Serial.print(radio.readRSSI());Serial.print("]"); if (promiscuousMode) - { + { Serial.print("to [");Serial.print(radio.TARGETID, DEC);Serial.print("] "); } - + if (radio.DATALEN != sizeof(Payload)) Serial.print("Invalid payload received, not matching Payload struct!"); else diff --git a/Examples/Struct_send/Struct_send.ino b/Examples/Struct_send/Struct_send.ino index 19f7bae..4260244 100644 --- a/Examples/Struct_send/Struct_send.ino +++ b/Examples/Struct_send/Struct_send.ino @@ -6,7 +6,7 @@ #define NETWORKID 100 #define GATEWAYID 1 #define FREQUENCY RF69_433MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ) -#define KEY "thisIsEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less! +#define KEY "sampleEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less! #define LED 9 #define SERIAL_BAUD 115200 #define ACK_TIME 30 // # of ms to wait for an ack @@ -17,7 +17,7 @@ boolean requestACK = false; SPIFlash flash(8, 0xEF30); //EF40 for 16mbit windbond chip RFM69 radio; -typedef struct { +typedef struct { int nodeId; //store this nodeId unsigned long uptime; //uptime in ms float temp; //temperature maybe? diff --git a/Examples/TxRxBlinky/TxRxBlinky.ino b/Examples/TxRxBlinky/TxRxBlinky.ino index 3e084a5..05b038b 100644 --- a/Examples/TxRxBlinky/TxRxBlinky.ino +++ b/Examples/TxRxBlinky/TxRxBlinky.ino @@ -12,7 +12,7 @@ // On the sender, hook up a momentary tactile button to D3 like this: // __-__ // __| |___ -// GND ----> BTN ----> D3 +// GND ----> BTN ----> D3 (D11 on MoteinoMEGA) // Load this sketch on the RECEIVER with NODEID=RECEIVER (adjust in config section below) // Load this sketch on the SENDER with NODEID=SENDER (adjust in config section below) // RFM69 library and code by Felix Rusu - felix@lowpowerlab.com @@ -65,11 +65,21 @@ #define ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes! #define IS_RFM69HW //uncomment only for RFM69HW! Remove/comment if you have RFM69W! //********************************************************************************************* - #define SERIAL_BAUD 115200 -#define LED 9 //Moteinos have onboard LEDs on D9 -#define BUTTON_INT 1 //user button on interrupt 1 (D3) -#define BUTTON_PIN 3 //user button on interrupt 1 (D3) +#ifdef __AVR_ATmega1284P__ + #define LED 15 // Moteino MEGAs have LEDs on D15 + #define BUTTON_INT 1 //user button on interrupt 1 (D3) + #define BUTTON_PIN 11 //user button on interrupt 1 (D3) +#else + #define LED 9 // Moteinos have LEDs on D9 + #define BUTTON_INT 1 //user button on interrupt 1 (D3) + #define BUTTON_PIN 3 //user button on interrupt 1 (D3) +#endif + +#define LED_GREEN 4 //GREEN LED on the SENDER +#define LED_RED 5 //RED LED on the SENDER +#define RX_TOGGLE_PIN 7 //GPIO to toggle on the RECEIVER + RFM69 radio; void setup() { @@ -86,6 +96,12 @@ void setup() { pinMode(BUTTON_PIN, INPUT_PULLUP); pinMode(LED, OUTPUT); attachInterrupt(BUTTON_INT, handleButton, FALLING); + + pinMode(LED_GREEN, OUTPUT); + pinMode(LED_RED, OUTPUT); + pinMode(RX_TOGGLE_PIN, OUTPUT); + digitalWrite(LED_GREEN, LOW); + digitalWrite(LED_RED, HIGH); } //******** THIS IS INTERRUPT BASED DEBOUNCING FOR BUTTON ATTACHED TO D3 (INTERRUPT 1) @@ -102,7 +118,7 @@ void loop() { //******** THIS IS INTERRUPT BASED DEBOUNCING FOR BUTTON ATTACHED TO D3 (INTERRUPT 1) if (mainEventFlags & FLAG_INTERRUPT) { - LowPower.powerDown(SLEEP_30MS, ADC_OFF, BOD_ON); + LowPower.powerDown(SLEEP_120MS, ADC_OFF, BOD_ON); mainEventFlags &= ~FLAG_INTERRUPT; if (!digitalRead(BUTTON_PIN)) { buttonPressed=true; @@ -113,6 +129,20 @@ void loop() { { Serial.println("Button pressed!"); buttonPressed = false; + + if(LEDSTATE==LOW) + { + LEDSTATE=HIGH; + digitalWrite(LED_GREEN, HIGH); + digitalWrite(LED_RED, LOW); + } + else + { + LEDSTATE=LOW; + digitalWrite(LED_GREEN, LOW); + digitalWrite(LED_RED, HIGH); + } + if (radio.sendWithRetry(RECEIVER, "Hi", 2)) //target node Id, message as string or byte array, message length Blink(LED, 40, 3); //blink LED 3 times, 40ms between blinks } @@ -133,6 +163,7 @@ void loop() { LEDSTATE=HIGH; else LEDSTATE=LOW; digitalWrite(LED, LEDSTATE); + digitalWrite(RX_TOGGLE_PIN, LEDSTATE); } //check if sender wanted an ACK @@ -157,4 +188,4 @@ void Blink(byte PIN, byte DELAY_MS, byte loops) digitalWrite(PIN,LOW); delay(DELAY_MS); } -} +} \ No newline at end of file diff --git a/Examples/WeatherNode/WeatherNode.ino b/Examples/WeatherNode/WeatherNode.ino new file mode 100644 index 0000000..ce4400d --- /dev/null +++ b/Examples/WeatherNode/WeatherNode.ino @@ -0,0 +1,269 @@ +// ********************************************************************************************************** +// WeatherShield sketch that works with Moteinos equipped with RFM69W/RFM69HW and WeatherShield +// It sends periodic highly accurate weather readings (temp, hum, atm pressure) from the +// WeatherShield to the base node/gateway Moteino +// Can be adapted to use Moteinos/Arduinos using RFM12B or other RFM69 variants (RFM69CW, RFM69HCW) +// For use with MoteinoMEGA you will have to revisit the pin definitions defined below +// http://www.LowPowerLab.com/WeatherShield +// Used in this project: http://lowpowerlab.com/blog/2015/07/24/attic-fan-cooling-tests/ +// 2015-07-23 (C) Felix Rusu of http://www.LowPowerLab.com/ +// ********************************************************************************************************** +// License +// ********************************************************************************************************** +// This program is free software; you can redistribute it +// and/or modify it under the terms of the GNU General +// Public License as published by the Free Software +// Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will +// be useful, but WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A +// PARTICULAR PURPOSE. See the GNU General Public +// License for more details. +// +// You should have received a copy of the GNU General +// Public License along with this program. +// If not, see . +// +// Licence can be viewed at +// http://www.gnu.org/licenses/gpl-3.0.txt +// +// Please maintain this license information along with authorship +// and copyright notices in any redistribution of this code +// *************************************************************************************************************************** +#include //get it here: http://github.com/lowpowerlab/rfm69 +#include //get it here: http://github.com/lowpowerlab/spiflash +#include //get it here: https://github.com/LowPowerLab/WirelessProgramming +#include //comes with Arduino + +#include //get it here: https://github.com/LowPowerLab/SFE_BMP180 +#include //get it here: https://github.com/LowPowerLab/SI7021 +#include //comes with Arduino + +#include //get library from: https://github.com/lowpowerlab/lowpower + //writeup here: http://www.rocketscream.com/blog/2011/07/04/lightweight-low-power-arduino-library/ + +//***************************************************************************************************************************** +// ADJUST THE SETTINGS BELOW DEPENDING ON YOUR HARDWARE/TRANSCEIVER SETTINGS/REQUIREMENTS +//***************************************************************************************************************************** +#define GATEWAYID 1 +#define NODEID 164 +#define NETWORKID 100 +//#define FREQUENCY RF69_433MHZ +//#define FREQUENCY RF69_868MHZ +#define FREQUENCY RF69_915MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ) +#define ENCRYPTKEY "sampleEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less! +//#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! +#define SEND_LOOPS 15 //send data this many sleep loops (15 loops of 8sec cycles = 120sec ~ 2 minutes) +//********************************************************************************************* +#define SLEEP_FASTEST SLEEP_15MS +#define SLEEP_FAST SLEEP_250MS +#define SLEEP_SEC SLEEP_1S +#define SLEEP_LONG SLEEP_2S +#define SLEEP_LONGER SLEEP_4S +#define SLEEP_LONGEST SLEEP_8S +period_t sleepTime = SLEEP_LONGEST; //period_t is an enum type defined in the LowPower library (LowPower.h) +//********************************************************************************************* +#define BATT_MONITOR_EN A3 //enables battery voltage divider to get a reading from a battery, disable it to save power +#define BATT_MONITOR A7 //through 1Meg+470Kohm and 0.1uF cap from battery VCC - this ratio divides the voltage to bring it below 3.3V where it is scaled to a readable range +#define BATT_CYCLES 2 //read and report battery voltage every this many sleep cycles (ex 30cycles * 8sec sleep = 240sec/4min). For 450 cyclesyou would get ~1 hour intervals +#define BATT_FORMULA(reading) reading * 0.00322 * 1.475 // >>> fine tune this parameter to match your voltage when fully charged +#define BATT_LOW 3.6 //(volts) +#define BATT_READ_LOOPS SEND_LOOPS*10 // read and report battery voltage every this many sleep cycles (ex 30cycles * 8sec sleep = 240sec/4min). For 450 cycles you would get ~1 hour intervals between readings +//***************************************************************************************************************************** +#define LED 9 //pin connected to onboard LED on regular Moteinos +//#define BLINK_EN //uncomment to blink LED on every send +#define SERIAL_EN //comment out if you don't want any serial output + +#ifdef SERIAL_EN + #define SERIAL_BAUD 115200 + #define DEBUG(input) {Serial.print(input);} + #define DEBUGln(input) {Serial.println(input);} + #define SERIALFLUSH() {Serial.flush();} +#else + #define DEBUG(input); + #define DEBUGln(input); + #define SERIALFLUSH(); +#endif +//***************************************************************************************************************************** + +//global program variables +SI7021 weatherShield_SI7021; +SFE_BMP180 weatherShield_BMP180; +RFM69 radio; +char Pstr[10]; +char buffer[50]; +SPIFlash flash(8, 0xEF30); //WINDBOND 4MBIT flash chip on CS pin D8 (default for Moteino) + +void setup(void) +{ +#ifdef SERIAL_EN + Serial.begin(SERIAL_BAUD); +#endif + pinMode(LED, OUTPUT); + + radio.initialize(FREQUENCY,NODEID,NETWORKID); +#ifdef IS_RFM69HW + radio.setHighPower(); //uncomment only for RFM69HW! +#endif + radio.encrypt(ENCRYPTKEY); + + sprintf(buffer, "WeatherMote - transmitting at: %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); + DEBUGln(buffer); + + //initialize weather shield sensors + weatherShield_SI7021.begin(); + if (weatherShield_BMP180.begin()) + { DEBUGln("BMP180 init success"); } + else { DEBUGln("BMP180 init fail\n"); } + + radio.sendWithRetry(GATEWAYID, "START", 6); + Blink(LED, 100);Blink(LED, 100);Blink(LED, 100); + + SERIALFLUSH(); + readBattery(); +} + +unsigned long doorPulseCount = 0; +char input=0; +double P; +byte sendLoops=0; +byte battReadLoops=0; +float batteryVolts = 5; +char* BATstr="BAT:5.00v"; //longest battery voltage reading message = 9chars +byte sendLen; + +void loop() +{ + if (battReadLoops--<=0) //only read battery every BATT_READ_LOOPS cycles + { + readBattery(); + battReadLoops = BATT_READ_LOOPS-1; + } + + if (sendLoops--<=0) //send readings every SEND_LOOPS + { + sendLoops = SEND_LOOPS-1; + P = getPressure(); + P*=0.0295333727; //transform to inHg + dtostrf(P, 3,2, Pstr); + sprintf(buffer, "BAT:%sv F:%d H:%d P:%s", BATstr, weatherShield_SI7021.getFahrenheitHundredths(), weatherShield_SI7021.getHumidityPercent(), Pstr); + + sendLen = strlen(buffer); + radio.sendWithRetry(GATEWAYID, buffer, sendLen, 1); //retry one time + DEBUG(buffer); DEBUG(" (packet length:"); DEBUG(sendLen); DEBUGln(")"); + + #ifdef BLINK_EN + Blink(LED, 5); + #endif + } + + //When this sketch is on a node where you can afford the power to keep the radio awake all the time + // you can make it receive messages and also make it wirelessly programmable + // otherwise this section can be removed + if (radio.receiveDone()) + { + boolean reportStatusRequest=false; + DEBUG('[');DEBUG(radio.SENDERID);DEBUG("] "); + for (byte i = 0; i < radio.DATALEN; i++) + DEBUG((char)radio.DATA[i]); + + // wireless programming token check - this only works when radio is kept awake to listen for WP tokens + CheckForWirelessHEX(radio, flash, true); + + //first send any ACK to request + DEBUG(" [RX_RSSI:");DEBUG(radio.RSSI);DEBUG("]"); + if (radio.ACKRequested()) + { + radio.sendACK(); + DEBUG(" - ACK sent."); + } + DEBUGln(); + } + + SERIALFLUSH(); + radio.sleep(); //you can comment out this line if you want this node to listen for wireless programming requests + LowPower.powerDown(sleepTime, ADC_OFF, BOD_OFF); + DEBUGln("WAKEUP"); +} + +double getPressure() +{ + char status; + double T,P,p0,a; + // If you want sea-level-compensated pressure, as used in weather reports, + // you will need to know the altitude at which your measurements are taken. + // We're using a constant called ALTITUDE in this sketch: + + // If you want to measure altitude, and not pressure, you will instead need + // to provide a known baseline pressure. This is shown at the end of the sketch. + // You must first get a temperature measurement to perform a pressure reading. + // Start a temperature measurement: + // If request is successful, the number of ms to wait is returned. + // If request is unsuccessful, 0 is returned. + status = weatherShield_BMP180.startTemperature(); + if (status != 0) + { + // Wait for the measurement to complete: + delay(status); + + // Retrieve the completed temperature measurement: + // Note that the measurement is stored in the variable T. + // Function returns 1 if successful, 0 if failure. + status = weatherShield_BMP180.getTemperature(T); + if (status != 0) + { + // Start a pressure measurement: + // The parameter is the oversampling setting, from 0 to 3 (highest res, longest wait). + // If request is successful, the number of ms to wait is returned. + // If request is unsuccessful, 0 is returned. + status = weatherShield_BMP180.startPressure(3); + if (status != 0) + { + // Wait for the measurement to complete: + delay(status); + + // Retrieve the completed pressure measurement: + // Note that the measurement is stored in the variable P. + // Note also that the function requires the previous temperature measurement (T). + // (If temperature is stable, you can do one temperature measurement for a number of pressure measurements.) + // Function returns 1 if successful, 0 if failure. + status = weatherShield_BMP180.getPressure(P,T); + if (status != 0) + { + return P; + } + } + } + } + return 0; +} + +void readBattery() +{ + unsigned int readings=0; + + //enable battery monitor on WeatherShield (via mosfet controlled by A3) + pinMode(BATT_MONITOR_EN, OUTPUT); + digitalWrite(BATT_MONITOR_EN, LOW); + + for (byte i=0; i<5; i++) //take several samples, and average + readings+=analogRead(BATT_MONITOR); + + //disable battery monitor + pinMode(BATT_MONITOR_EN, INPUT); //highZ mode will allow p-mosfet to be pulled high and disconnect the voltage divider on the weather shield + + batteryVolts = BATT_FORMULA(readings / 5.0); + dtostrf(batteryVolts,3,2, BATstr); //update the BATStr which gets sent every BATT_CYCLES or along with the MOTION message + if (batteryVolts <= BATT_LOW) BATstr = "LOW"; +} + +void Blink(byte PIN, byte DELAY_MS) +{ + pinMode(PIN, OUTPUT); + digitalWrite(PIN,HIGH); + delay(DELAY_MS/2); + digitalWrite(PIN,LOW); + delay(DELAY_MS/2); +} \ No newline at end of file diff --git a/Examples/WirelessProgramming_gateway/WirelessProgramming_gateway.ino b/Examples/WirelessProgramming_gateway/WirelessProgramming_gateway.ino index ab5faa8..bb842da 100644 --- a/Examples/WirelessProgramming_gateway/WirelessProgramming_gateway.ino +++ b/Examples/WirelessProgramming_gateway/WirelessProgramming_gateway.ino @@ -1,30 +1,49 @@ -/* - * Copyright (c) 2013 by Felix Rusu - * - * This file is free software; you can redistribute it and/or modify - * it under the terms of either the GNU General Public License version 2 - * or the GNU Lesser General Public License version 2.1, both as - * published by the Free Software Foundation. - */ - +// ********************************************************************************** // This sketch is an example of how wireless programming can be achieved with a Moteino -// that was loaded with a custom 1k Optiboot that is capable of loading a new sketch from -// an external SPI flash chip +// that was loaded with a custom 1k bootloader (DualOptiboot) that is capable of loading +// a new sketch from an external SPI flash chip // This is the GATEWAY node, it does not need a custom Optiboot nor any external FLASH memory chip // (ONLY the target node will need those) // The sketch includes logic to receive the new sketch from the serial port (from a host computer) and // transmit it wirelessly to the target node // The handshake protocol that receives the sketch from the serial port -// is handled by the SPIFLash/WirelessHEX69 library, which also relies on the RFM12B library +// is handled by the SPIFLash/WirelessHEX69 library, which also relies on the RFM69 library // These libraries and custom 1k Optiboot bootloader for the target node are at: http://github.com/lowpowerlab - -#include +// ********************************************************************************** +// Copyright Felix Rusu, LowPowerLab.com +// Library and code by Felix Rusu - felix@lowpowerlab.com +// ********************************************************************************** +// License +// ********************************************************************************** +// This program is free software; you can redistribute it +// and/or modify it under the terms of the GNU General +// Public License as published by the Free Software +// Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will +// be useful, but WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A +// PARTICULAR PURPOSE. See the GNU General Public +// License for more details. +// +// You should have received a copy of the GNU General +// Public License along with this program. +// If not, see . +// +// Licence can be viewed at +// http://www.gnu.org/licenses/gpl-3.0.txt +// +// Please maintain this license information along with authorship +// and copyright notices in any redistribution of this code +// ********************************************************************************** +#include //get it here: https://www.github.com/lowpowerlab/rfm69 #include -#include -#include +#include //get it here: https://www.github.com/lowpowerlab/spiflash +#include //get it here: https://github.com/LowPowerLab/WirelessProgramming/tree/master/WirelessHEX69 -#define NETWORKID 250 //what network this node is on #define NODEID 254 //this node's ID, should be unique among nodes on this NETWORKID +#define NETWORKID 250 //what network this node is on //Match frequency to the hardware version of the radio on your Moteino (uncomment one): //#define FREQUENCY RF69_433MHZ //#define FREQUENCY RF69_868MHZ diff --git a/Examples/WirelessProgramming_node/WirelessProgramming_node.ino b/Examples/WirelessProgramming_node/WirelessProgramming_node.ino index 80581c4..267c677 100644 --- a/Examples/WirelessProgramming_node/WirelessProgramming_node.ino +++ b/Examples/WirelessProgramming_node/WirelessProgramming_node.ino @@ -1,35 +1,54 @@ -/* - * Copyright (c) 2013 by Felix Rusu - * - * This file is free software; you can redistribute it and/or modify - * it under the terms of either the GNU General Public License version 2 - * or the GNU Lesser General Public License version 2.1, both as - * published by the Free Software Foundation. - */ - +// ********************************************************************************** // This sketch is an example of how wireless programming can be achieved with a Moteino -// that was loaded with a custom 1k Optiboot that is capable of loading a new sketch from -// an external SPI flash chip +// that was loaded with a custom 1k bootloader (DualOptiboot) that is capable of loading +// a new sketch from an external SPI flash chip // The sketch includes logic to receive the new sketch 'over-the-air' and store it in // the FLASH chip, then restart the Moteino so the bootloader can continue the job of // actually reflashing the internal flash memory from the external FLASH memory chip flash image // The handshake protocol that receives the sketch wirelessly by means of the RFM69 radio // is handled by the SPIFLash/WirelessHEX69 library, which also relies on the RFM69 library // These libraries and custom 1k Optiboot bootloader are at: http://github.com/lowpowerlab - -#include +// ********************************************************************************** +// Copyright Felix Rusu, LowPowerLab.com +// Library and code by Felix Rusu - felix@lowpowerlab.com +// ********************************************************************************** +// License +// ********************************************************************************** +// This program is free software; you can redistribute it +// and/or modify it under the terms of the GNU General +// Public License as published by the Free Software +// Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will +// be useful, but WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A +// PARTICULAR PURPOSE. See the GNU General Public +// License for more details. +// +// You should have received a copy of the GNU General +// Public License along with this program. +// If not, see . +// +// Licence can be viewed at +// http://www.gnu.org/licenses/gpl-3.0.txt +// +// Please maintain this license information along with authorship +// and copyright notices in any redistribution of this code +// ********************************************************************************** +#include //get it here: https://www.github.com/lowpowerlab/rfm69 #include -#include +#include //get it here: https://www.github.com/lowpowerlab/spiflash #include -#include +#include //get it here: https://github.com/LowPowerLab/WirelessProgramming/tree/master/WirelessHEX69 -#define MYID 55 // node ID used for this unit +#define NODEID 123 // node ID used for this unit #define NETWORKID 250 //Match frequency to the hardware version of the radio on your Moteino (uncomment one): //#define FREQUENCY RF69_433MHZ //#define FREQUENCY RF69_868MHZ #define FREQUENCY RF69_915MHZ -#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! +//#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W! #define SERIAL_BAUD 115200 #define ACK_TIME 30 // # of ms to wait for an ack #define ENCRYPTKEY "sampleEncryptKey" //(16 bytes of your choice - keep the same on all encrypted nodes) @@ -59,7 +78,7 @@ SPIFlash flash(FLASH_SS, 0xEF30); //EF30 for windbond 4mbit flash void setup(){ pinMode(LED, OUTPUT); Serial.begin(SERIAL_BAUD); - radio.initialize(FREQUENCY,MYID,NETWORKID); + radio.initialize(FREQUENCY,NODEID,NETWORKID); radio.encrypt(ENCRYPTKEY); //OPTIONAL #ifdef IS_RFM69HW radio.setHighPower(); //only for RFM69HW! diff --git a/README.md b/README.md index 7d563ee..cb78848 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,15 @@ RFM69 Library ---------------- -By Felix Rusu (felix@lowpowerlab.com) +By Felix Rusu, [LowPowerLab.com](http://LowPowerLab.com)
RFM69 library for RFM69W, RFM69HW, RFM69CW, RFM69HCW (semtech SX1231, SX1231H) +
+The latest examples, new features and bug fixes are found in the [original repository](https://github.com/LowPowerLab/RFM69) of this library. ##License -GPL 3.0, please see the License.txt file - +GPL 3.0, please see the [License.txt](https://github.com/LowPowerLab/RFM69/blob/master/License.txt) file for details. Be sure to include the same license with any fork or redistribution of this library. ##Features -Among others, this is a set of features implemented in this library: - - easy to use API with a few simple functions for basic usage - 255 possible nodes on 256 possible networks - 61 bytes max message length (limited to 61 to support AES hardware encryption) @@ -21,40 +20,40 @@ Among others, this is a set of features implemented in this library: - hardware preamble, synch recognition and CRC check - digital RSSI can be read at any time with readRSSI() - interrupt driven -- tested on [Moteino R3, R4, R4-USB (ATMega328p)](http://lowpowerlab.com/shop/Moteino-R4) +- tested on [Moteino R3, R4, R4-USB (ATMega328p), MEGA (ATMega1284p)](https://lowpowerlab.com/shop/Moteino-R4) - works with RFM69W, RFM69HW, RFM69CW, RFM69HCW, Semtech SX1231/SX1231H transceivers - promiscuous mode allows any node to listen to any packet on same network -I consider this an initial beta release, it could contain bugs, but the provided Gateway and Node examples should work out of the box. Please let me know if you find issues. - -###Installation +###Library Installation (Arduino IDE) Copy the content of this library in the "Arduino/libraries/RFM69" folder.
To find your Arduino folder go to File>Preferences in the Arduino IDE.
See [this tutorial](http://learn.adafruit.com/arduino-tips-tricks-and-techniques/arduino-libraries) on Arduino libraries. -###MISC / possible issues -- The library and examples are continuously improved as bugs and stability issues are discovered. Be sure to check back often for changes. -- Moteino boards are loaded with fuses that will delay startup. This means that other boards like Duemilanove/UNO might need a delay() in the setup() function before doing anything - to allow the transceiver to power up. +###Hardware & programming +The easiest way to get started is with the well documented and supported [Moteino](http://moteino.com) microcontroller platform which is [easily programmable](https://lowpowerlab.com/programming) from the Arduino IDE. This includes the [Moteino, MoteinoUSB & MoteinoMEGA](https://lowpowerlab.com/shop/Moteino). RFM69 transceivers were extensively tested on Moteinos for the purpose of building internet of things (IoT) devices that can be controlled wirelessly. This platform has matured over time and there is now a [dedicated page](https://lowpowerlab.com/gateway) where you can review how these devices can interact with each other via a RaspberryPi gateway interface. Here's a video overview:
+https://www.youtube.com/watch?v=YUUZ6k0pBHg +
+https://www.youtube.com/watch?v=I9MNZQgqKHA +
+https://www.youtube.com/watch?v=F15dEqZ4pMM -###Sample usage -- [Node](https://github.com/LowPowerLab/RFM69/blob/master/Examples/Node/Node.ino) -- [Gateway](https://github.com/LowPowerLab/RFM69/blob/master/Examples/Gateway/Gateway.ino) +###Basic sample usage +- The [Gateway](https://github.com/LowPowerLab/RFM69/blob/master/Examples/Gateway/Gateway.ino) example listens for incoming data from remote nodes and responds to any ACK requests +- The [Node](https://github.com/LowPowerLab/RFM69/blob/master/Examples/Node/Node.ino) example is a loop that sends increasingly longer packets to the gateway and waits for an ACK each time +- More examples are added from time to time, check all the [examples](https://github.com/LowPowerLab/RFM69/tree/master/Examples), visit the [LowPowerLab blog](http://lowpowerlab.com) for latest news and projects, and check out the [LowPowerLab forums](https://lowpowerlab.com/forum) for projects and discussion ##Blog writeup -http://lowpowerlab.com/blog/2013/06/20/rfm69-library/ +See the [library release blog post](http://lowpowerlab.com/blog/2013/06/20/rfm69-library/) -##Why -- I have spent a lot of time developing this library for RFM69W/HW transceivers. I made it open source because I believe a lot of people can benefit from this new powerful transceiver. I hope people will also contribute and build on my work +##Why RFM69 +- I have spent a lot of time developing this library for RFM69W/HW transceivers. I made it open source because I believe a lot of people can benefit from this new powerful transceiver. I hope others will also contribute and build on my work - I have long researched alternative transceivers for RFM12B which is still an excellent transceiver but it is much lower output power and has limited built in features which need to be implemented in firmware (PREAMBLE, SYNC, CRC, packet engine, encryption etc). -- I wanted a transceiver that could still be very small, easy to use, but have the longer range that I wanted -- RFM69 comes in 2 variants that have the same layout/connections: RFM69W (13dBm, 45mA TX) and RFM69HW (20dBm, 130mA TX) +- I wanted a transceiver that could still be very small, easy to use, and have the longer range that I needed +- RFM69 comes in 2 variants that have the same pinout layout: RFM69W (13dBm, 45mA TX) and RFM69HW (20dBm, 130mA TX). Other variants include the RFM69CW (up to 13dBm power) which is pin compatible with RFM12B, and RFM69HCW (20dBm output power). -##RFM69W range -- I have tested open-air range on these transceivers (the W only) in various combinations. -- I am happy to say that a range of upwards of 350m can be achieved. I went to local parks and in very large parking spaces and I ran out of space, so more than 350m is possible. Some users reported upwards of 500m by lowering the bitrate, and a forum user reported 1.5miles at 1.2Kbps: see http://lowpowerlab.com/forum/index.php/topic,112.msg288.html and http://lowpowerlab.com/moteino/#antennas -- The caveat with these higher RF power units is that they need more DC power when they transmit. For battery powered motes, you will need to keep them powered down and only transmit periodically. Use the sleep() function to put the radios in low power mode and use the [LowPower](https://github.com/rocketscream/Low-Power) or [Narcoleptic](https://code.google.com/p/narcoleptic/) libraries to power down your arduino - -##License -GPL 3.0. See License.txt file. +##RFM69W range and antennas +- I have tested open-air range on these transceivers in various combinations. +- I am happy to say that a range of upwards of 350m can be achieved with the default settings provided in the library.Some users reported upwards of 500m by lowering the bitrate, and a forum user reported 1.5miles at 1.2Kbps: see [this forum post](http://lowpowerlab.com/forum/index.php/topic,112.msg288.html) and [this blog page](http://lowpowerlab.com/moteino/#antennas) +- The caveat with these higher RF power units is that they need more DC power when they transmit. For battery powered motes, you will need to keep them powered down and only transmit periodically. Use the sleep() function to put the radios in low power mode and use the [LowPower](https://github.com/lowpowerlab/lowpower) or [Narcoleptic](https://code.google.com/p/narcoleptic/) libraries to power down your Moteino/Arduino diff --git a/RFM69.cpp b/RFM69.cpp index cb4e509..bcc4926 100644 --- a/RFM69.cpp +++ b/RFM69.cpp @@ -9,22 +9,21 @@ // This program is free software; you can redistribute it // and/or modify it under the terms of the GNU General // Public License as published by the Free Software -// Foundation; either version 2 of the License, or +// Foundation; either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will // be useful, but WITHOUT ANY WARRANTY; without even the // implied warranty of MERCHANTABILITY or FITNESS FOR A -// PARTICULAR PURPOSE. See the GNU General Public +// PARTICULAR PURPOSE. See the GNU General Public // License for more details. // // You should have received a copy of the GNU General -// Public License along with this program; if not, write -// to the Free Software Foundation, Inc., -// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// Public License along with this program. +// If not, see . // // Licence can be viewed at -// http://www.fsf.org/licenses/gpl.txt +// http://www.gnu.org/licenses/gpl-3.0.txt // // Please maintain this license information along with authorship // and copyright notices in any redistribution of this code @@ -33,76 +32,78 @@ #include #include -volatile byte RFM69::DATA[RF69_MAX_DATA_LEN]; -volatile byte RFM69::_mode; // current transceiver state -volatile byte RFM69::DATALEN; -volatile byte RFM69::SENDERID; -volatile byte RFM69::TARGETID; //should match _address -volatile byte RFM69::PAYLOADLEN; -volatile byte RFM69::ACK_REQUESTED; -volatile byte RFM69::ACK_RECEIVED; /// Should be polled immediately after sending a packet with ACK request -volatile int RFM69::RSSI; //most accurate RSSI during reception (closest to the reception) +volatile uint8_t RFM69::DATA[RF69_MAX_DATA_LEN]; +volatile uint8_t RFM69::_mode; // current transceiver state +volatile uint8_t RFM69::DATALEN; +volatile uint8_t RFM69::SENDERID; +volatile uint8_t RFM69::TARGETID; // should match _address +volatile uint8_t RFM69::PAYLOADLEN; +volatile uint8_t RFM69::ACK_REQUESTED; +volatile uint8_t RFM69::ACK_RECEIVED; // should be polled immediately after sending a packet with ACK request +volatile int16_t RFM69::RSSI; // most accurate RSSI during reception (closest to the reception) RFM69* RFM69::selfPointer; -bool RFM69::initialize(byte freqBand, byte nodeID, byte networkID) +bool RFM69::initialize(uint8_t freqBand, uint8_t nodeID, uint8_t networkID) { - const byte CONFIG[][2] = + const uint8_t CONFIG[][2] = { /* 0x01 */ { REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_LISTEN_OFF | RF_OPMODE_STANDBY }, - /* 0x02 */ { REG_DATAMODUL, RF_DATAMODUL_DATAMODE_PACKET | RF_DATAMODUL_MODULATIONTYPE_FSK | RF_DATAMODUL_MODULATIONSHAPING_00 }, //no shaping - /* 0x03 */ { REG_BITRATEMSB, RF_BITRATEMSB_55555}, //default:4.8 KBPS + /* 0x02 */ { REG_DATAMODUL, RF_DATAMODUL_DATAMODE_PACKET | RF_DATAMODUL_MODULATIONTYPE_FSK | RF_DATAMODUL_MODULATIONSHAPING_00 }, // no shaping + /* 0x03 */ { REG_BITRATEMSB, RF_BITRATEMSB_55555}, // default: 4.8 KBPS /* 0x04 */ { REG_BITRATELSB, RF_BITRATELSB_55555}, - /* 0x05 */ { REG_FDEVMSB, RF_FDEVMSB_50000}, //default:5khz, (FDEV + BitRate/2 <= 500Khz) + /* 0x05 */ { REG_FDEVMSB, RF_FDEVMSB_50000}, // default: 5KHz, (FDEV + BitRate / 2 <= 500KHz) /* 0x06 */ { REG_FDEVLSB, RF_FDEVLSB_50000}, - /* 0x07 */ { REG_FRFMSB, (freqBand==RF69_315MHZ ? RF_FRFMSB_315 : (freqBand==RF69_433MHZ ? RF_FRFMSB_433 : (freqBand==RF69_868MHZ ? RF_FRFMSB_868 : RF_FRFMSB_915))) }, - /* 0x08 */ { REG_FRFMID, (freqBand==RF69_315MHZ ? RF_FRFMID_315 : (freqBand==RF69_433MHZ ? RF_FRFMID_433 : (freqBand==RF69_868MHZ ? RF_FRFMID_868 : RF_FRFMID_915))) }, - /* 0x09 */ { REG_FRFLSB, (freqBand==RF69_315MHZ ? RF_FRFLSB_315 : (freqBand==RF69_433MHZ ? RF_FRFLSB_433 : (freqBand==RF69_868MHZ ? RF_FRFLSB_868 : RF_FRFLSB_915))) }, - + /* 0x07 */ { REG_FRFMSB, (uint8_t) (freqBand==RF69_315MHZ ? RF_FRFMSB_315 : (freqBand==RF69_433MHZ ? RF_FRFMSB_433 : (freqBand==RF69_868MHZ ? RF_FRFMSB_868 : RF_FRFMSB_915))) }, + /* 0x08 */ { REG_FRFMID, (uint8_t) (freqBand==RF69_315MHZ ? RF_FRFMID_315 : (freqBand==RF69_433MHZ ? RF_FRFMID_433 : (freqBand==RF69_868MHZ ? RF_FRFMID_868 : RF_FRFMID_915))) }, + /* 0x09 */ { REG_FRFLSB, (uint8_t) (freqBand==RF69_315MHZ ? RF_FRFLSB_315 : (freqBand==RF69_433MHZ ? RF_FRFLSB_433 : (freqBand==RF69_868MHZ ? RF_FRFLSB_868 : RF_FRFLSB_915))) }, + // looks like PA1 and PA2 are not implemented on RFM69W, hence the max output power is 13dBm // +17dBm and +20dBm are possible on RFM69HW - // +13dBm formula: Pout=-18+OutputPower (with PA0 or PA1**) - // +17dBm formula: Pout=-14+OutputPower (with PA1 and PA2)** - // +20dBm formula: Pout=-11+OutputPower (with PA1 and PA2)** and high power PA settings (section 3.3.7 in datasheet) + // +13dBm formula: Pout = -18 + OutputPower (with PA0 or PA1**) + // +17dBm formula: Pout = -14 + OutputPower (with PA1 and PA2)** + // +20dBm formula: Pout = -11 + OutputPower (with PA1 and PA2)** and high power PA settings (section 3.3.7 in datasheet) ///* 0x11 */ { REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | RF_PALEVEL_OUTPUTPOWER_11111}, - ///* 0x13 */ { REG_OCP, RF_OCP_ON | RF_OCP_TRIM_95 }, //over current protection (default is 95mA) - - // RXBW defaults are { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_5} (RxBw: 10.4khz) - /* 0x19 */ { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_16 | RF_RXBW_EXP_2 }, //(BitRate < 2 * RxBw) - //for BR-19200: //* 0x19 */ { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_3 }, - /* 0x25 */ { REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01 }, //DIO0 is the only IRQ we're using - /* 0x29 */ { REG_RSSITHRESH, 220 }, //must be set to dBm = (-Sensitivity / 2) - default is 0xE4=228 so -114dBm - ///* 0x2d */ { REG_PREAMBLELSB, RF_PREAMBLESIZE_LSB_VALUE } // default 3 preamble bytes 0xAAAAAA - /* 0x2e */ { REG_SYNCCONFIG, RF_SYNC_ON | RF_SYNC_FIFOFILL_AUTO | RF_SYNC_SIZE_2 | RF_SYNC_TOL_0 }, - /* 0x2f */ { REG_SYNCVALUE1, 0x2D }, //attempt to make this compatible with sync1 byte of RFM12B lib - /* 0x30 */ { REG_SYNCVALUE2, networkID }, //NETWORK ID + ///* 0x13 */ { REG_OCP, RF_OCP_ON | RF_OCP_TRIM_95 }, // over current protection (default is 95mA) + + // RXBW defaults are { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_5} (RxBw: 10.4KHz) + /* 0x19 */ { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_16 | RF_RXBW_EXP_2 }, // (BitRate < 2 * RxBw) + //for BR-19200: /* 0x19 */ { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_3 }, + /* 0x25 */ { REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01 }, // DIO0 is the only IRQ we're using + /* 0x26 */ { REG_DIOMAPPING2, RF_DIOMAPPING2_CLKOUT_OFF }, // DIO5 ClkOut disable for power saving + /* 0x28 */ { REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN }, // writing to this bit ensures that the FIFO & status flags are reset + /* 0x29 */ { REG_RSSITHRESH, 220 }, // must be set to dBm = (-Sensitivity / 2), default is 0xE4 = 228 so -114dBm + ///* 0x2D */ { REG_PREAMBLELSB, RF_PREAMBLESIZE_LSB_VALUE } // default 3 preamble bytes 0xAAAAAA + /* 0x2E */ { REG_SYNCCONFIG, RF_SYNC_ON | RF_SYNC_FIFOFILL_AUTO | RF_SYNC_SIZE_2 | RF_SYNC_TOL_0 }, + /* 0x2F */ { REG_SYNCVALUE1, 0x2D }, // attempt to make this compatible with sync1 byte of RFM12B lib + /* 0x30 */ { REG_SYNCVALUE2, networkID }, // NETWORK ID /* 0x37 */ { REG_PACKETCONFIG1, RF_PACKET1_FORMAT_VARIABLE | RF_PACKET1_DCFREE_OFF | RF_PACKET1_CRC_ON | RF_PACKET1_CRCAUTOCLEAR_ON | RF_PACKET1_ADRSFILTERING_OFF }, - /* 0x38 */ { REG_PAYLOADLENGTH, 66 }, //in variable length mode: the max frame size, not used in TX - //* 0x39 */ { REG_NODEADRS, nodeID }, //turned off because we're not using address filtering - /* 0x3C */ { REG_FIFOTHRESH, RF_FIFOTHRESH_TXSTART_FIFONOTEMPTY | RF_FIFOTHRESH_VALUE }, //TX on FIFO not empty - /* 0x3d */ { REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_2BITS | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF }, //RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent) - //for BR-19200: //* 0x3d */ { REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_NONE | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF }, //RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent) - //* 0x6F */ { REG_TESTDAGC, RF_DAGC_CONTINUOUS }, // run DAGC continuously in RX mode - /* 0x6F */ { REG_TESTDAGC, RF_DAGC_IMPROVED_LOWBETA0 }, // run DAGC continuously in RX mode, recommended default for AfcLowBetaOn=0 + /* 0x38 */ { REG_PAYLOADLENGTH, 66 }, // in variable length mode: the max frame size, not used in TX + ///* 0x39 */ { REG_NODEADRS, nodeID }, // turned off because we're not using address filtering + /* 0x3C */ { REG_FIFOTHRESH, RF_FIFOTHRESH_TXSTART_FIFONOTEMPTY | RF_FIFOTHRESH_VALUE }, // TX on FIFO not empty + /* 0x3D */ { REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_2BITS | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF }, // RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent) + //for BR-19200: /* 0x3D */ { REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_NONE | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF }, // RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent) + /* 0x6F */ { REG_TESTDAGC, RF_DAGC_IMPROVED_LOWBETA0 }, // run DAGC continuously in RX mode for Fading Margin Improvement, recommended default for AfcLowBetaOn=0 {255, 0} }; + digitalWrite(_slaveSelectPin, HIGH); pinMode(_slaveSelectPin, OUTPUT); SPI.begin(); - - do writeReg(REG_SYNCVALUE1, 0xaa); while (readReg(REG_SYNCVALUE1) != 0xaa); - do writeReg(REG_SYNCVALUE1, 0x55); while (readReg(REG_SYNCVALUE1) != 0x55); - for (byte i = 0; CONFIG[i][0] != 255; i++) + do writeReg(REG_SYNCVALUE1, 0xAA); while (readReg(REG_SYNCVALUE1) != 0xAA); + do writeReg(REG_SYNCVALUE1, 0x55); while (readReg(REG_SYNCVALUE1) != 0x55); + + for (uint8_t i = 0; CONFIG[i][0] != 255; i++) writeReg(CONFIG[i][0], CONFIG[i][1]); // Encryption is persistent between resets and can trip you up during debugging. // Disable it during initialization so we always start from a known state. encrypt(0); - setHighPower(_isRFM69HW); //called regardless if it's a RFM69W or RFM69HW + setHighPower(_isRFM69HW); // called regardless if it's a RFM69W or RFM69HW setMode(RF69_MODE_STANDBY); - while ((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // Wait for ModeReady + while ((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // wait for ModeReady attachInterrupt(_interruptNum, RFM69::isr0, RISING); selfPointer = this; @@ -110,66 +111,98 @@ bool RFM69::initialize(byte freqBand, byte nodeID, byte networkID) return true; } -void RFM69::setFrequency(uint32_t FRF) +// return the frequency (in Hz) +uint32_t RFM69::getFrequency() { - writeReg(REG_FRFMSB, FRF >> 16); - writeReg(REG_FRFMID, FRF >> 8); - writeReg(REG_FRFLSB, FRF); + return RF69_FSTEP * (((uint32_t) readReg(REG_FRFMSB) << 16) + ((uint16_t) readReg(REG_FRFMID) << 8) + readReg(REG_FRFLSB)); } -void RFM69::setMode(byte newMode) +// set the frequency (in Hz) +void RFM69::setFrequency(uint32_t freqHz) { - if (newMode == _mode) return; //TODO: can remove this? + uint8_t oldMode = _mode; + if (oldMode == RF69_MODE_TX) { + setMode(RF69_MODE_RX); + } + freqHz /= RF69_FSTEP; // divide down by FSTEP to get FRF + writeReg(REG_FRFMSB, freqHz >> 16); + writeReg(REG_FRFMID, freqHz >> 8); + writeReg(REG_FRFLSB, freqHz); + if (oldMode == RF69_MODE_RX) { + setMode(RF69_MODE_SYNTH); + } + setMode(oldMode); +} - switch (newMode) { - case RF69_MODE_TX: - writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_TRANSMITTER); +void RFM69::setMode(uint8_t newMode) +{ + if (newMode == _mode) + return; + + switch (newMode) { + case RF69_MODE_TX: + writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_TRANSMITTER); if (_isRFM69HW) setHighPowerRegs(true); - break; - case RF69_MODE_RX: - writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_RECEIVER); + break; + case RF69_MODE_RX: + writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_RECEIVER); if (_isRFM69HW) setHighPowerRegs(false); - break; - case RF69_MODE_SYNTH: - writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_SYNTHESIZER); - break; - case RF69_MODE_STANDBY: - writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_STANDBY); - break; - case RF69_MODE_SLEEP: - writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_SLEEP); - break; - default: return; - } + break; + case RF69_MODE_SYNTH: + writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_SYNTHESIZER); + break; + case RF69_MODE_STANDBY: + writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_STANDBY); + break; + case RF69_MODE_SLEEP: + writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_SLEEP); + break; + default: + return; + } - // we are using packet mode, so this check is not really needed + // we are using packet mode, so this check is not really needed // but waiting for mode ready is necessary when going from sleep because the FIFO may not be immediately available from previous mode - while (_mode == RF69_MODE_SLEEP && (readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // Wait for ModeReady + while (_mode == RF69_MODE_SLEEP && (readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // wait for ModeReady - _mode = newMode; + _mode = newMode; } +//put transceiver in sleep mode to save battery - to wake or resume receiving just call receiveDone() void RFM69::sleep() { setMode(RF69_MODE_SLEEP); } -void RFM69::setAddress(byte addr) +//set this node's address +void RFM69::setAddress(uint8_t addr) { _address = addr; - writeReg(REG_NODEADRS, _address); + writeReg(REG_NODEADRS, _address); } -// set output power: 0=min, 31=max -// this results in a "weaker" transmitted signal, and directly results in a lower RSSI at the receiver -void RFM69::setPowerLevel(byte powerLevel) +//set this node's network id +void RFM69::setNetwork(uint8_t networkID) { - _powerLevel = powerLevel; - writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0xE0) | (_powerLevel > 31 ? 31 : _powerLevel)); + writeReg(REG_SYNCVALUE2, networkID); +} + +// set *transmit/TX* output power: 0=min, 31=max +// this results in a "weaker" transmitted signal, and directly results in a lower RSSI at the receiver +// the power configurations are explained in the SX1231H datasheet (Table 10 on p21; RegPaLevel p66): http://www.semtech.com/images/datasheet/sx1231h.pdf +// valid powerLevel parameter values are 0-31 and result in a directly proportional effect on the output/transmission power +// this function implements 2 modes as follows: +// - for RFM69W the range is from 0-31 [-18dBm to 13dBm] (PA0 only on RFIO pin) +// - for RFM69HW the range is from 0-31 [5dBm to 20dBm] (PA1 & PA2 on PA_BOOST pin & high Power PA settings - see section 3.3.7 in datasheet, p22) +void RFM69::setPowerLevel(uint8_t powerLevel) +{ + _powerLevel = (powerLevel > 31 ? 31 : powerLevel); + if (_isRFM69HW) _powerLevel /= 2; + writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0xE0) | _powerLevel); } bool RFM69::canSend() { - if (_mode == RF69_MODE_RX && PAYLOADLEN == 0 && readRSSI() < CSMA_LIMIT) //if signal stronger than -100dBm is detected assume channel activity + if (_mode == RF69_MODE_RX && PAYLOADLEN == 0 && readRSSI() < CSMA_LIMIT) // if signal stronger than -100dBm is detected assume channel activity { setMode(RF69_MODE_STANDBY); return true; @@ -177,90 +210,98 @@ bool RFM69::canSend() return false; } -void RFM69::send(byte toAddress, const void* buffer, byte bufferSize, bool requestACK) +void RFM69::send(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool requestACK) { writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) | RF_PACKET2_RXRESTART); // avoid RX deadlocks - long now = millis(); - while (!canSend() && millis()-now < RF69_CSMA_LIMIT_MS) receiveDone(); + uint32_t now = millis(); + while (!canSend() && millis() - now < RF69_CSMA_LIMIT_MS) receiveDone(); sendFrame(toAddress, buffer, bufferSize, requestACK, false); } // to increase the chance of getting a packet across, call this function instead of send // and it handles all the ACK requesting/retrying for you :) // The only twist is that you have to manually listen to ACK requests on the other side and send back the ACKs -// The reason for the semi-automaton is that the lib is ingterrupt driven and +// The reason for the semi-automaton is that the lib is interrupt driven and // requires user action to read the received data and decide what to do with it -// replies usually take only 5-8ms at 50kbps@915Mhz -bool RFM69::sendWithRetry(byte toAddress, const void* buffer, byte bufferSize, byte retries, byte retryWaitTime) { - long sentTime; - for (byte i=0; i<=retries; i++) +// replies usually take only 5..8ms at 50kbps@915MHz +bool RFM69::sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferSize, uint8_t retries, uint8_t retryWaitTime) { + uint32_t sentTime; + for (uint8_t i = 0; i <= retries; i++) { send(toAddress, buffer, bufferSize, true); sentTime = millis(); - while (millis()-sentTime RF69_MAX_DATA_LEN) bufferSize = RF69_MAX_DATA_LEN; - //write to FIFO - select(); - SPI.transfer(REG_FIFO | 0x80); - SPI.transfer(bufferSize + 3); - SPI.transfer(toAddress); - SPI.transfer(_address); - - //control byte + // control byte + uint8_t CTLbyte = 0x00; if (sendACK) - SPI.transfer(0x80); + CTLbyte = 0x80; else if (requestACK) - SPI.transfer(0x40); - else SPI.transfer(0x00); - - for (byte i = 0; i < bufferSize; i++) - SPI.transfer(((byte*)buffer)[i]); - unselect(); + CTLbyte = 0x40; - /* no need to wait for transmit mode to be ready since its handled by the radio */ - setMode(RF69_MODE_TX); - while (digitalRead(_interruptPin) == 0); //wait for DIO0 to turn HIGH signalling transmission finish - //while (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PACKETSENT == 0x00); // Wait for ModeReady + // write to FIFO + select(); + SPI.transfer(REG_FIFO | 0x80); + SPI.transfer(bufferSize + 3); + SPI.transfer(toAddress); + SPI.transfer(_address); + SPI.transfer(CTLbyte); + + for (uint8_t i = 0; i < bufferSize; i++) + SPI.transfer(((uint8_t*) buffer)[i]); + unselect(); + + // no need to wait for transmit mode to be ready since its handled by the radio + setMode(RF69_MODE_TX); + uint32_t txStart = millis(); + while (digitalRead(_interruptPin) == 0 && millis() - txStart < RF69_TX_LIMIT_MS); // wait for DIO0 to turn HIGH signalling transmission finish + //while (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PACKETSENT == 0x00); // wait for ModeReady setMode(RF69_MODE_STANDBY); } +// internal function - interrupt gets called when a packet is received void RFM69::interruptHandler() { //pinMode(4, OUTPUT); //digitalWrite(4, 1); @@ -269,29 +310,32 @@ void RFM69::interruptHandler() { //RSSI = readRSSI(); setMode(RF69_MODE_STANDBY); select(); - SPI.transfer(REG_FIFO & 0x7f); + SPI.transfer(REG_FIFO & 0x7F); PAYLOADLEN = SPI.transfer(0); - PAYLOADLEN = PAYLOADLEN > 66 ? 66 : PAYLOADLEN; //precaution + PAYLOADLEN = PAYLOADLEN > 66 ? 66 : PAYLOADLEN; // precaution TARGETID = SPI.transfer(0); - if(!(_promiscuousMode || TARGETID==_address || TARGETID==RF69_BROADCAST_ADDR)) //match this node's address, or broadcast address or anything in promiscuous mode + if(!(_promiscuousMode || TARGETID == _address || TARGETID == RF69_BROADCAST_ADDR) // match this node's address, or broadcast address or anything in promiscuous mode + || PAYLOADLEN < 3) // address situation could receive packets that are malformed and don't fit this libraries extra fields { PAYLOADLEN = 0; unselect(); + receiveBegin(); //digitalWrite(4, 0); return; } + DATALEN = PAYLOADLEN - 3; SENDERID = SPI.transfer(0); - byte CTLbyte = SPI.transfer(0); - - ACK_RECEIVED = CTLbyte & 0x80; //extract ACK-requested flag - ACK_REQUESTED = CTLbyte & 0x40; //extract ACK-received flag - - for (byte i= 0; i < DATALEN; i++) + uint8_t CTLbyte = SPI.transfer(0); + + ACK_RECEIVED = CTLbyte & 0x80; // extract ACK-received flag + ACK_REQUESTED = CTLbyte & 0x40; // extract ACK-requested flag + + for (uint8_t i = 0; i < DATALEN; i++) { DATA[i] = SPI.transfer(0); } - if (DATALENinterruptHandler(); } +// internal function void RFM69::receiveBegin() { DATALEN = 0; SENDERID = 0; @@ -311,22 +357,23 @@ void RFM69::receiveBegin() { RSSI = 0; if (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY) writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) | RF_PACKET2_RXRESTART); // avoid RX deadlocks - writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01); //set DIO0 to "PAYLOADREADY" in receive mode + writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01); // set DIO0 to "PAYLOADREADY" in receive mode setMode(RF69_MODE_RX); } +// checks if a packet was received and/or puts transceiver in receive (ie RX or listen) mode bool RFM69::receiveDone() { -// ATOMIC_BLOCK(ATOMIC_FORCEON) -// { - noInterrupts(); //re-enabled in unselect() via setMode() or via receiveBegin() - if (_mode == RF69_MODE_RX && PAYLOADLEN>0) +//ATOMIC_BLOCK(ATOMIC_FORCEON) +//{ + noInterrupts(); // re-enabled in unselect() via setMode() or via receiveBegin() + if (_mode == RF69_MODE_RX && PAYLOADLEN > 0) { - setMode(RF69_MODE_STANDBY); //enables interrupts + setMode(RF69_MODE_STANDBY); // enables interrupts return true; } - else if (_mode == RF69_MODE_RX) //already in RX no payload yet + else if (_mode == RF69_MODE_RX) // already in RX no payload yet { - interrupts(); //explicitly re-enable interrupts + interrupts(); // explicitly re-enable interrupts return false; } receiveBegin(); @@ -339,40 +386,41 @@ bool RFM69::receiveDone() { // KEY HAS TO BE 16 bytes !!! void RFM69::encrypt(const char* key) { setMode(RF69_MODE_STANDBY); - if (key!=0) + if (key != 0) { select(); SPI.transfer(REG_AESKEY1 | 0x80); - for (byte i = 0; i<16; i++) + for (uint8_t i = 0; i < 16; i++) SPI.transfer(key[i]); unselect(); } writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFE) | (key ? 1 : 0)); } -int RFM69::readRSSI(bool forceTrigger) { - int rssi = 0; +// get the received signal strength indicator (RSSI) +int16_t RFM69::readRSSI(bool forceTrigger) { + int16_t rssi = 0; if (forceTrigger) { - //RSSI trigger not needed if DAGC is in continuous mode + // RSSI trigger not needed if DAGC is in continuous mode writeReg(REG_RSSICONFIG, RF_RSSI_START); - while ((readReg(REG_RSSICONFIG) & RF_RSSI_DONE) == 0x00); // Wait for RSSI_Ready + while ((readReg(REG_RSSICONFIG) & RF_RSSI_DONE) == 0x00); // wait for RSSI_Ready } rssi = -readReg(REG_RSSIVALUE); rssi >>= 1; return rssi; } -byte RFM69::readReg(byte addr) +uint8_t RFM69::readReg(uint8_t addr) { select(); SPI.transfer(addr & 0x7F); - byte regval = SPI.transfer(0); + uint8_t regval = SPI.transfer(0); unselect(); return regval; } -void RFM69::writeReg(byte addr, byte value) +void RFM69::writeReg(uint8_t addr, uint8_t value) { select(); SPI.transfer(addr | 0x80); @@ -380,51 +428,55 @@ void RFM69::writeReg(byte addr, byte value) unselect(); } -/// Select the transceiver +// select the RFM69 transceiver (save SPI settings, set CS low) void RFM69::select() { noInterrupts(); - //save current SPI settings + // save current SPI settings _SPCR = SPCR; _SPSR = SPSR; - //set RFM69 SPI settings + // set RFM69 SPI settings SPI.setDataMode(SPI_MODE0); SPI.setBitOrder(MSBFIRST); - SPI.setClockDivider(SPI_CLOCK_DIV4); //decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present + SPI.setClockDivider(SPI_CLOCK_DIV4); // decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present digitalWrite(_slaveSelectPin, LOW); } -/// UNselect the transceiver chip +// unselect the RFM69 transceiver (set CS high, restore SPI settings) void RFM69::unselect() { digitalWrite(_slaveSelectPin, HIGH); - //restore SPI settings to what they were before talking to RFM69 + // restore SPI settings to what they were before talking to RFM69 SPCR = _SPCR; SPSR = _SPSR; interrupts(); } -// ON = disable filtering to capture all frames on network -// OFF = enable node+broadcast filtering to capture only frames sent to this/broadcast address +// true = disable filtering to capture all frames on network +// false = enable node/broadcast filtering to capture only frames sent to this/broadcast address void RFM69::promiscuous(bool onOff) { - _promiscuousMode=onOff; + _promiscuousMode = onOff; //writeReg(REG_PACKETCONFIG1, (readReg(REG_PACKETCONFIG1) & 0xF9) | (onOff ? RF_PACKET1_ADRSFILTERING_OFF : RF_PACKET1_ADRSFILTERING_NODEBROADCAST)); } +// for RFM69HW only: you must call setHighPower(true) after initialize() or else transmission won't work void RFM69::setHighPower(bool onOff) { _isRFM69HW = onOff; writeReg(REG_OCP, _isRFM69HW ? RF_OCP_OFF : RF_OCP_ON); - if (_isRFM69HW) //turning ON - writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0x1F) | RF_PALEVEL_PA1_ON | RF_PALEVEL_PA2_ON); //enable P1 & P2 amplifier stages + if (_isRFM69HW) // turning ON + writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0x1F) | RF_PALEVEL_PA1_ON | RF_PALEVEL_PA2_ON); // enable P1 & P2 amplifier stages else - writeReg(REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | _powerLevel); //enable P0 only + writeReg(REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | _powerLevel); // enable P0 only } +// internal function void RFM69::setHighPowerRegs(bool onOff) { writeReg(REG_TESTPA1, onOff ? 0x5D : 0x55); writeReg(REG_TESTPA2, onOff ? 0x7C : 0x70); } -void RFM69::setCS(byte newSPISlaveSelect) { +// set the slave select (CS) pin +void RFM69::setCS(uint8_t newSPISlaveSelect) { _slaveSelectPin = newSPISlaveSelect; + digitalWrite(_slaveSelectPin, HIGH); pinMode(_slaveSelectPin, OUTPUT); } @@ -447,23 +499,23 @@ void SerialPrint_P(PGM_P str, void (*f)(uint8_t) = SerialWrite ) { void RFM69::readAllRegs() { - byte regVal; + uint8_t regVal; #if REGISTER_DETAIL int capVal; //... State Variables for intelligent decoding - byte modeFSK = 0; + uint8_t modeFSK = 0; int bitRate = 0; int freqDev = 0; long freqCenter = 0; #endif SerialPrint ( "Address - HEX - BIN\n" ); - for (byte regAddr = 1; regAddr <= 0x4F; regAddr++) - { + for (uint8_t regAddr = 1; regAddr <= 0x4F; regAddr++) + { select(); - SPI.transfer(regAddr & 0x7f); // send address + r/w bit + SPI.transfer(regAddr & 0x7F); // send address + r/w bit regVal = SPI.transfer(0); unselect(); @@ -474,7 +526,8 @@ void RFM69::readAllRegs() Serial.println(regVal,BIN); #if REGISTER_DETAIL - switch ( regAddr ) { + switch ( regAddr ) + { case 0x1 : { SerialPrint ( "Controls the automatic Sequencer ( see section 4.2 )\nSequencerOff : " ); if ( 0x80 & regVal ) { @@ -705,33 +758,22 @@ void RFM69::readAllRegs() default : { } - } #endif - - - - - - - - - - - } + } unselect(); } -byte RFM69::readTemperature(byte calFactor) //returns centigrade +uint8_t RFM69::readTemperature(uint8_t calFactor) // returns centigrade { setMode(RF69_MODE_STANDBY); writeReg(REG_TEMP1, RF_TEMP1_MEAS_START); - while ((readReg(REG_TEMP1) & RF_TEMP1_MEAS_RUNNING)) Serial.print('*'); - return ~readReg(REG_TEMP2) + COURSE_TEMP_COEF + calFactor; //'complement'corrects the slope, rising temp = rising val -} // COURSE_TEMP_COEF puts reading in the ballpark, user can add additional correction + while ((readReg(REG_TEMP1) & RF_TEMP1_MEAS_RUNNING)); + return ~readReg(REG_TEMP2) + COURSE_TEMP_COEF + calFactor; // 'complement' corrects the slope, rising temp = rising val +} // COURSE_TEMP_COEF puts reading in the ballpark, user can add additional correction void RFM69::rcCalibration() { writeReg(REG_OSC1, RF_OSC1_RCCAL_START); while ((readReg(REG_OSC1) & RF_OSC1_RCCAL_DONE) == 0x00); -} \ No newline at end of file +} diff --git a/RFM69.h b/RFM69.h index 23eb044..8811bf9 100644 --- a/RFM69.h +++ b/RFM69.h @@ -9,73 +9,81 @@ // This program is free software; you can redistribute it // and/or modify it under the terms of the GNU General // Public License as published by the Free Software -// Foundation; either version 2 of the License, or +// Foundation; either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will // be useful, but WITHOUT ANY WARRANTY; without even the // implied warranty of MERCHANTABILITY or FITNESS FOR A -// PARTICULAR PURPOSE. See the GNU General Public +// PARTICULAR PURPOSE. See the GNU General Public // License for more details. // // You should have received a copy of the GNU General -// Public License along with this program; if not, write -// to the Free Software Foundation, Inc., -// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// Public License along with this program. +// If not, see . // // Licence can be viewed at -// http://www.fsf.org/licenses/gpl.txt +// http://www.gnu.org/licenses/gpl-3.0.txt // // Please maintain this license information along with authorship // and copyright notices in any redistribution of this code // ********************************************************************************** #ifndef RFM69_h #define RFM69_h -#include //assumes Arduino IDE v1.0 or greater +#include // assumes Arduino IDE v1.0 or greater -#define RF69_MAX_DATA_LEN 61 // to take advantage of the built in AES/CRC we want to limit the frame size to the internal FIFO size (66 bytes - 3 bytes overhead) -#define RF69_SPI_CS SS // SS is the SPI slave select pin, for instance D10 on atmega328 +#define RF69_MAX_DATA_LEN 61 // to take advantage of the built in AES/CRC we want to limit the frame size to the internal FIFO size (66 bytes - 3 bytes overhead - 2 bytes crc) +#define RF69_SPI_CS SS // SS is the SPI slave select pin, for instance D10 on ATmega328 -// INT0 on AVRs should be connected to RFM69's DIO0 (ex on Atmega328 it's D2, on Atmega644/1284 it's D2) -#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__) || defined(__AVR_ATmega32U4__) +// INT0 on AVRs should be connected to RFM69's DIO0 (ex on ATmega328 it's D2, on ATmega644/1284 it's D2) +#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__) #define RF69_IRQ_PIN 2 #define RF69_IRQ_NUM 0 #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__) #define RF69_IRQ_PIN 2 #define RF69_IRQ_NUM 2 +#elif defined(__AVR_ATmega32U4__) + #define RF69_IRQ_PIN 3 + #define RF69_IRQ_NUM 0 +#else + #define RF69_IRQ_PIN 2 + #define RF69_IRQ_NUM 0 #endif -#define CSMA_LIMIT -90 // upper RX signal sensitivity threshold in dBm for carrier sense access -#define RF69_MODE_SLEEP 0 // XTAL OFF -#define RF69_MODE_STANDBY 1 // XTAL ON -#define RF69_MODE_SYNTH 2 // PLL ON -#define RF69_MODE_RX 3 // RX MODE -#define RF69_MODE_TX 4 // TX MODE -//available frequency bands -#define RF69_315MHZ 31 // non trivial values to avoid misconfiguration -#define RF69_433MHZ 43 -#define RF69_868MHZ 86 -#define RF69_915MHZ 91 +#define CSMA_LIMIT -90 // upper RX signal sensitivity threshold in dBm for carrier sense access +#define RF69_MODE_SLEEP 0 // XTAL OFF +#define RF69_MODE_STANDBY 1 // XTAL ON +#define RF69_MODE_SYNTH 2 // PLL ON +#define RF69_MODE_RX 3 // RX MODE +#define RF69_MODE_TX 4 // TX MODE + +// available frequency bands +#define RF69_315MHZ 31 // non trivial values to avoid misconfiguration +#define RF69_433MHZ 43 +#define RF69_868MHZ 86 +#define RF69_915MHZ 91 #define null 0 #define COURSE_TEMP_COEF -90 // puts the temperature reading in the ballpark, user can fine tune the returned value #define RF69_BROADCAST_ADDR 255 #define RF69_CSMA_LIMIT_MS 1000 +#define RF69_TX_LIMIT_MS 1000 +#define RF69_FSTEP 61.03515625 // == FXOSC / 2^19 = 32MHz / 2^19 (p13 in datasheet) class RFM69 { public: - static volatile byte DATA[RF69_MAX_DATA_LEN]; // recv/xmit buf, including hdr & crc bytes - static volatile byte DATALEN; - static volatile byte SENDERID; - static volatile byte TARGETID; //should match _address - static volatile byte PAYLOADLEN; - static volatile byte ACK_REQUESTED; - static volatile byte ACK_RECEIVED; /// Should be polled immediately after sending a packet with ACK request - static volatile int RSSI; //most accurate RSSI during reception (closest to the reception) - static volatile byte _mode; //should be protected? - - RFM69(byte slaveSelectPin=RF69_SPI_CS, byte interruptPin=RF69_IRQ_PIN, bool isRFM69HW=false, byte interruptNum=RF69_IRQ_NUM) { + static volatile uint8_t DATA[RF69_MAX_DATA_LEN]; // recv/xmit buf, including header & crc bytes + static volatile uint8_t DATALEN; + static volatile uint8_t SENDERID; + static volatile uint8_t TARGETID; // should match _address + static volatile uint8_t PAYLOADLEN; + static volatile uint8_t ACK_REQUESTED; + static volatile uint8_t ACK_RECEIVED; // should be polled immediately after sending a packet with ACK request + static volatile int16_t RSSI; // most accurate RSSI during reception (closest to the reception) + static volatile uint8_t _mode; // should be protected? + + RFM69(uint8_t slaveSelectPin=RF69_SPI_CS, uint8_t interruptPin=RF69_IRQ_PIN, bool isRFM69HW=false, uint8_t interruptNum=RF69_IRQ_NUM) { _slaveSelectPin = slaveSelectPin; _interruptPin = interruptPin; _interruptNum = interruptNum; @@ -85,49 +93,51 @@ class RFM69 { _isRFM69HW = isRFM69HW; } - bool initialize(byte freqBand, byte ID, byte networkID=1); - void setAddress(byte addr); + bool initialize(uint8_t freqBand, uint8_t ID, uint8_t networkID=1); + void setAddress(uint8_t addr); + void setNetwork(uint8_t networkID); bool canSend(); - void send(byte toAddress, const void* buffer, byte bufferSize, bool requestACK=false); - bool sendWithRetry(byte toAddress, const void* buffer, byte bufferSize, byte retries=2, byte retryWaitTime=40); //40ms roundtrip req for 61byte packets + void send(uint8_t toAddress, const void* buffer, uint8_t bufferSize, bool requestACK=false); + bool sendWithRetry(uint8_t toAddress, const void* buffer, uint8_t bufferSize, uint8_t retries=2, uint8_t retryWaitTime=40); // 40ms roundtrip req for 61byte packets bool receiveDone(); - bool ACKReceived(byte fromNodeID); + bool ACKReceived(uint8_t fromNodeID); bool ACKRequested(); void sendACK(const void* buffer = "", uint8_t bufferSize=0); - void setFrequency(uint32_t FRF); + uint32_t getFrequency(); + void setFrequency(uint32_t freqHz); void encrypt(const char* key); - void setCS(byte newSPISlaveSelect); - int readRSSI(bool forceTrigger=false); + void setCS(uint8_t newSPISlaveSelect); + int16_t readRSSI(bool forceTrigger=false); void promiscuous(bool onOff=true); - void setHighPower(bool onOFF=true); //have to call it after initialize for RFM69HW - void setPowerLevel(byte level); //reduce/increase transmit power level + void setHighPower(bool onOFF=true); // has to be called after initialize() for RFM69HW + void setPowerLevel(uint8_t level); // reduce/increase transmit power level void sleep(); - byte readTemperature(byte calFactor=0); //get CMOS temperature (8bit) - void rcCalibration(); //calibrate the internal RC oscillator for use in wide temperature variations - see datasheet section [4.3.5. RC Timer Accuracy] + uint8_t readTemperature(uint8_t calFactor=0); // get CMOS temperature (8bit) + void rcCalibration(); // calibrate the internal RC oscillator for use in wide temperature variations - see datasheet section [4.3.5. RC Timer Accuracy] // allow hacking registers by making these public - byte readReg(byte addr); - void writeReg(byte addr, byte val); + uint8_t readReg(uint8_t addr); + void writeReg(uint8_t addr, uint8_t val); void readAllRegs(); protected: static void isr0(); void virtual interruptHandler(); - void sendFrame(byte toAddress, const void* buffer, byte size, bool requestACK=false, bool sendACK=false); + void sendFrame(uint8_t toAddress, const void* buffer, uint8_t size, bool requestACK=false, bool sendACK=false); static RFM69* selfPointer; - byte _slaveSelectPin; - byte _interruptPin; - byte _interruptNum; - byte _address; + uint8_t _slaveSelectPin; + uint8_t _interruptPin; + uint8_t _interruptNum; + uint8_t _address; bool _promiscuousMode; - byte _powerLevel; + uint8_t _powerLevel; bool _isRFM69HW; - byte _SPCR; - byte _SPSR; + uint8_t _SPCR; + uint8_t _SPSR; void receiveBegin(); - void setMode(byte mode); + void setMode(uint8_t mode); void setHighPowerRegs(bool onOff); void select(); void unselect(); diff --git a/RFM69registers.h b/RFM69registers.h index ff720b1..2d815ec 100644 --- a/RFM69registers.h +++ b/RFM69registers.h @@ -1,7 +1,7 @@ // ********************************************************************************** // Registers used in driver definition for HopeRF RFM69W/RFM69HW, Semtech SX1231/1231H // ********************************************************************************** -// Copyright Felix Rusu (2014), felix@lowpowerlab.com +// Copyright Felix Rusu (2015), felix@lowpowerlab.com // http://lowpowerlab.com/ // ********************************************************************************** // License @@ -31,1039 +31,1079 @@ // ********************************************************************************** // RFM69/SX1231 Internal registers addresses //************************************************** -#define REG_FIFO 0x00 -#define REG_OPMODE 0x01 -#define REG_DATAMODUL 0x02 -#define REG_BITRATEMSB 0x03 -#define REG_BITRATELSB 0x04 -#define REG_FDEVMSB 0x05 -#define REG_FDEVLSB 0x06 -#define REG_FRFMSB 0x07 -#define REG_FRFMID 0x08 -#define REG_FRFLSB 0x09 -#define REG_OSC1 0x0A -#define REG_AFCCTRL 0x0B -#define REG_LOWBAT 0x0C -#define REG_LISTEN1 0x0D -#define REG_LISTEN2 0x0E -#define REG_LISTEN3 0x0F -#define REG_VERSION 0x10 -#define REG_PALEVEL 0x11 -#define REG_PARAMP 0x12 -#define REG_OCP 0x13 -#define REG_AGCREF 0x14 -#define REG_AGCTHRESH1 0x15 -#define REG_AGCTHRESH2 0x16 -#define REG_AGCTHRESH3 0x17 -#define REG_LNA 0x18 -#define REG_RXBW 0x19 -#define REG_AFCBW 0x1A -#define REG_OOKPEAK 0x1B -#define REG_OOKAVG 0x1C -#define REG_OOKFIX 0x1D -#define REG_AFCFEI 0x1E -#define REG_AFCMSB 0x1F -#define REG_AFCLSB 0x20 -#define REG_FEIMSB 0x21 -#define REG_FEILSB 0x22 -#define REG_RSSICONFIG 0x23 -#define REG_RSSIVALUE 0x24 -#define REG_DIOMAPPING1 0x25 -#define REG_DIOMAPPING2 0x26 -#define REG_IRQFLAGS1 0x27 -#define REG_IRQFLAGS2 0x28 -#define REG_RSSITHRESH 0x29 -#define REG_RXTIMEOUT1 0x2A -#define REG_RXTIMEOUT2 0x2B -#define REG_PREAMBLEMSB 0x2C -#define REG_PREAMBLELSB 0x2D -#define REG_SYNCCONFIG 0x2E -#define REG_SYNCVALUE1 0x2F -#define REG_SYNCVALUE2 0x30 -#define REG_SYNCVALUE3 0x31 -#define REG_SYNCVALUE4 0x32 -#define REG_SYNCVALUE5 0x33 -#define REG_SYNCVALUE6 0x34 -#define REG_SYNCVALUE7 0x35 -#define REG_SYNCVALUE8 0x36 -#define REG_PACKETCONFIG1 0x37 -#define REG_PAYLOADLENGTH 0x38 -#define REG_NODEADRS 0x39 -#define REG_BROADCASTADRS 0x3A -#define REG_AUTOMODES 0x3B -#define REG_FIFOTHRESH 0x3C -#define REG_PACKETCONFIG2 0x3D -#define REG_AESKEY1 0x3E -#define REG_AESKEY2 0x3F -#define REG_AESKEY3 0x40 -#define REG_AESKEY4 0x41 -#define REG_AESKEY5 0x42 -#define REG_AESKEY6 0x43 -#define REG_AESKEY7 0x44 -#define REG_AESKEY8 0x45 -#define REG_AESKEY9 0x46 -#define REG_AESKEY10 0x47 -#define REG_AESKEY11 0x48 -#define REG_AESKEY12 0x49 -#define REG_AESKEY13 0x4A -#define REG_AESKEY14 0x4B -#define REG_AESKEY15 0x4C -#define REG_AESKEY16 0x4D -#define REG_TEMP1 0x4E -#define REG_TEMP2 0x4F -#define REG_TESTPA1 0x5A //only present on RFM69HW/SX1231H -#define REG_TESTPA2 0x5C //only present on RFM69HW/SX1231H +#define REG_FIFO 0x00 +#define REG_OPMODE 0x01 +#define REG_DATAMODUL 0x02 +#define REG_BITRATEMSB 0x03 +#define REG_BITRATELSB 0x04 +#define REG_FDEVMSB 0x05 +#define REG_FDEVLSB 0x06 +#define REG_FRFMSB 0x07 +#define REG_FRFMID 0x08 +#define REG_FRFLSB 0x09 +#define REG_OSC1 0x0A +#define REG_AFCCTRL 0x0B +#define REG_LOWBAT 0x0C +#define REG_LISTEN1 0x0D +#define REG_LISTEN2 0x0E +#define REG_LISTEN3 0x0F +#define REG_VERSION 0x10 +#define REG_PALEVEL 0x11 +#define REG_PARAMP 0x12 +#define REG_OCP 0x13 +#define REG_AGCREF 0x14 // not present on RFM69/SX1231 +#define REG_AGCTHRESH1 0x15 // not present on RFM69/SX1231 +#define REG_AGCTHRESH2 0x16 // not present on RFM69/SX1231 +#define REG_AGCTHRESH3 0x17 // not present on RFM69/SX1231 +#define REG_LNA 0x18 +#define REG_RXBW 0x19 +#define REG_AFCBW 0x1A +#define REG_OOKPEAK 0x1B +#define REG_OOKAVG 0x1C +#define REG_OOKFIX 0x1D +#define REG_AFCFEI 0x1E +#define REG_AFCMSB 0x1F +#define REG_AFCLSB 0x20 +#define REG_FEIMSB 0x21 +#define REG_FEILSB 0x22 +#define REG_RSSICONFIG 0x23 +#define REG_RSSIVALUE 0x24 +#define REG_DIOMAPPING1 0x25 +#define REG_DIOMAPPING2 0x26 +#define REG_IRQFLAGS1 0x27 +#define REG_IRQFLAGS2 0x28 +#define REG_RSSITHRESH 0x29 +#define REG_RXTIMEOUT1 0x2A +#define REG_RXTIMEOUT2 0x2B +#define REG_PREAMBLEMSB 0x2C +#define REG_PREAMBLELSB 0x2D +#define REG_SYNCCONFIG 0x2E +#define REG_SYNCVALUE1 0x2F +#define REG_SYNCVALUE2 0x30 +#define REG_SYNCVALUE3 0x31 +#define REG_SYNCVALUE4 0x32 +#define REG_SYNCVALUE5 0x33 +#define REG_SYNCVALUE6 0x34 +#define REG_SYNCVALUE7 0x35 +#define REG_SYNCVALUE8 0x36 +#define REG_PACKETCONFIG1 0x37 +#define REG_PAYLOADLENGTH 0x38 +#define REG_NODEADRS 0x39 +#define REG_BROADCASTADRS 0x3A +#define REG_AUTOMODES 0x3B +#define REG_FIFOTHRESH 0x3C +#define REG_PACKETCONFIG2 0x3D +#define REG_AESKEY1 0x3E +#define REG_AESKEY2 0x3F +#define REG_AESKEY3 0x40 +#define REG_AESKEY4 0x41 +#define REG_AESKEY5 0x42 +#define REG_AESKEY6 0x43 +#define REG_AESKEY7 0x44 +#define REG_AESKEY8 0x45 +#define REG_AESKEY9 0x46 +#define REG_AESKEY10 0x47 +#define REG_AESKEY11 0x48 +#define REG_AESKEY12 0x49 +#define REG_AESKEY13 0x4A +#define REG_AESKEY14 0x4B +#define REG_AESKEY15 0x4C +#define REG_AESKEY16 0x4D +#define REG_TEMP1 0x4E +#define REG_TEMP2 0x4F +#define REG_TESTLNA 0x58 +#define REG_TESTPA1 0x5A // only present on RFM69HW/SX1231H +#define REG_TESTPA2 0x5C // only present on RFM69HW/SX1231H #define REG_TESTDAGC 0x6F //****************************************************** // RF69/SX1231 bit control definition //****************************************************** + // RegOpMode -#define RF_OPMODE_SEQUENCER_OFF 0x80 -#define RF_OPMODE_SEQUENCER_ON 0x00 // Default +#define RF_OPMODE_SEQUENCER_OFF 0x80 +#define RF_OPMODE_SEQUENCER_ON 0x00 // Default -#define RF_OPMODE_LISTEN_ON 0x40 -#define RF_OPMODE_LISTEN_OFF 0x00 // Default +#define RF_OPMODE_LISTEN_ON 0x40 +#define RF_OPMODE_LISTEN_OFF 0x00 // Default -#define RF_OPMODE_LISTENABORT 0x20 +#define RF_OPMODE_LISTENABORT 0x20 + +#define RF_OPMODE_SLEEP 0x00 +#define RF_OPMODE_STANDBY 0x04 // Default +#define RF_OPMODE_SYNTHESIZER 0x08 +#define RF_OPMODE_TRANSMITTER 0x0C +#define RF_OPMODE_RECEIVER 0x10 -#define RF_OPMODE_SLEEP 0x00 -#define RF_OPMODE_STANDBY 0x04 // Default -#define RF_OPMODE_SYNTHESIZER 0x08 -#define RF_OPMODE_TRANSMITTER 0x0C -#define RF_OPMODE_RECEIVER 0x10 // RegDataModul -#define RF_DATAMODUL_DATAMODE_PACKET 0x00 // Default -#define RF_DATAMODUL_DATAMODE_CONTINUOUS 0x40 -#define RF_DATAMODUL_DATAMODE_CONTINUOUSNOBSYNC 0x60 +#define RF_DATAMODUL_DATAMODE_PACKET 0x00 // Default +#define RF_DATAMODUL_DATAMODE_CONTINUOUS 0x40 +#define RF_DATAMODUL_DATAMODE_CONTINUOUSNOBSYNC 0x60 -#define RF_DATAMODUL_MODULATIONTYPE_FSK 0x00 // Default -#define RF_DATAMODUL_MODULATIONTYPE_OOK 0x08 +#define RF_DATAMODUL_MODULATIONTYPE_FSK 0x00 // Default +#define RF_DATAMODUL_MODULATIONTYPE_OOK 0x08 + +#define RF_DATAMODUL_MODULATIONSHAPING_00 0x00 // Default +#define RF_DATAMODUL_MODULATIONSHAPING_01 0x01 +#define RF_DATAMODUL_MODULATIONSHAPING_10 0x02 +#define RF_DATAMODUL_MODULATIONSHAPING_11 0x03 -#define RF_DATAMODUL_MODULATIONSHAPING_00 0x00 // Default -#define RF_DATAMODUL_MODULATIONSHAPING_01 0x01 -#define RF_DATAMODUL_MODULATIONSHAPING_10 0x02 -#define RF_DATAMODUL_MODULATIONSHAPING_11 0x03 // RegBitRate (bits/sec) example bit rates -#define RF_BITRATEMSB_1200 0x68 -#define RF_BITRATELSB_1200 0x2B -#define RF_BITRATEMSB_2400 0x34 -#define RF_BITRATELSB_2400 0x15 -#define RF_BITRATEMSB_4800 0x1A // Default -#define RF_BITRATELSB_4800 0x0B // Default -#define RF_BITRATEMSB_9600 0x0D -#define RF_BITRATELSB_9600 0x05 -#define RF_BITRATEMSB_19200 0x06 -#define RF_BITRATELSB_19200 0x83 -#define RF_BITRATEMSB_38400 0x03 -#define RF_BITRATELSB_38400 0x41 +#define RF_BITRATEMSB_1200 0x68 +#define RF_BITRATELSB_1200 0x2B +#define RF_BITRATEMSB_2400 0x34 +#define RF_BITRATELSB_2400 0x15 +#define RF_BITRATEMSB_4800 0x1A // Default +#define RF_BITRATELSB_4800 0x0B // Default +#define RF_BITRATEMSB_9600 0x0D +#define RF_BITRATELSB_9600 0x05 +#define RF_BITRATEMSB_19200 0x06 +#define RF_BITRATELSB_19200 0x83 +#define RF_BITRATEMSB_38400 0x03 +#define RF_BITRATELSB_38400 0x41 -#define RF_BITRATEMSB_38323 0x03 -#define RF_BITRATELSB_38323 0x43 +#define RF_BITRATEMSB_38323 0x03 +#define RF_BITRATELSB_38323 0x43 -#define RF_BITRATEMSB_34482 0x03 -#define RF_BITRATELSB_34482 0xA0 +#define RF_BITRATEMSB_34482 0x03 +#define RF_BITRATELSB_34482 0xA0 + +#define RF_BITRATEMSB_76800 0x01 +#define RF_BITRATELSB_76800 0xA1 +#define RF_BITRATEMSB_153600 0x00 +#define RF_BITRATELSB_153600 0xD0 +#define RF_BITRATEMSB_57600 0x02 +#define RF_BITRATELSB_57600 0x2C +#define RF_BITRATEMSB_115200 0x01 +#define RF_BITRATELSB_115200 0x16 +#define RF_BITRATEMSB_12500 0x0A +#define RF_BITRATELSB_12500 0x00 +#define RF_BITRATEMSB_25000 0x05 +#define RF_BITRATELSB_25000 0x00 +#define RF_BITRATEMSB_50000 0x02 +#define RF_BITRATELSB_50000 0x80 +#define RF_BITRATEMSB_100000 0x01 +#define RF_BITRATELSB_100000 0x40 +#define RF_BITRATEMSB_150000 0x00 +#define RF_BITRATELSB_150000 0xD5 +#define RF_BITRATEMSB_200000 0x00 +#define RF_BITRATELSB_200000 0xA0 +#define RF_BITRATEMSB_250000 0x00 +#define RF_BITRATELSB_250000 0x80 +#define RF_BITRATEMSB_300000 0x00 +#define RF_BITRATELSB_300000 0x6B +#define RF_BITRATEMSB_32768 0x03 +#define RF_BITRATELSB_32768 0xD1 +// custom bit rates +#define RF_BITRATEMSB_55555 0x02 +#define RF_BITRATELSB_55555 0x40 +#define RF_BITRATEMSB_200KBPS 0x00 +#define RF_BITRATELSB_200KBPS 0xa0 -#define RF_BITRATEMSB_76800 0x01 -#define RF_BITRATELSB_76800 0xA1 -#define RF_BITRATEMSB_153600 0x00 -#define RF_BITRATELSB_153600 0xD0 -#define RF_BITRATEMSB_57600 0x02 -#define RF_BITRATELSB_57600 0x2C -#define RF_BITRATEMSB_115200 0x01 -#define RF_BITRATELSB_115200 0x16 -#define RF_BITRATEMSB_12500 0x0A -#define RF_BITRATELSB_12500 0x00 -#define RF_BITRATEMSB_25000 0x05 -#define RF_BITRATELSB_25000 0x00 -#define RF_BITRATEMSB_50000 0x02 -#define RF_BITRATELSB_50000 0x80 -#define RF_BITRATEMSB_100000 0x01 -#define RF_BITRATELSB_100000 0x40 -#define RF_BITRATEMSB_150000 0x00 -#define RF_BITRATELSB_150000 0xD5 -#define RF_BITRATEMSB_200000 0x00 -#define RF_BITRATELSB_200000 0xA0 -#define RF_BITRATEMSB_250000 0x00 -#define RF_BITRATELSB_250000 0x80 -#define RF_BITRATEMSB_300000 0x00 -#define RF_BITRATELSB_300000 0x6B -#define RF_BITRATEMSB_32768 0x03 -#define RF_BITRATELSB_32768 0xD1 -//custom bit rates -#define RF_BITRATEMSB_55555 0x02 -#define RF_BITRATELSB_55555 0x40 -#define RF_BITRATEMSB_200KBPS 0x00 -#define RF_BITRATELSB_200KBPS 0xa0 // RegFdev - frequency deviation (Hz) -#define RF_FDEVMSB_2000 0x00 -#define RF_FDEVLSB_2000 0x21 -#define RF_FDEVMSB_5000 0x00 // Default -#define RF_FDEVLSB_5000 0x52 // Default -#define RF_FDEVMSB_7500 0x00 -#define RF_FDEVLSB_7500 0x7B -#define RF_FDEVMSB_10000 0x00 -#define RF_FDEVLSB_10000 0xA4 -#define RF_FDEVMSB_15000 0x00 -#define RF_FDEVLSB_15000 0xF6 -#define RF_FDEVMSB_20000 0x01 -#define RF_FDEVLSB_20000 0x48 -#define RF_FDEVMSB_25000 0x01 -#define RF_FDEVLSB_25000 0x9A -#define RF_FDEVMSB_30000 0x01 -#define RF_FDEVLSB_30000 0xEC -#define RF_FDEVMSB_35000 0x02 -#define RF_FDEVLSB_35000 0x3D -#define RF_FDEVMSB_40000 0x02 -#define RF_FDEVLSB_40000 0x8F -#define RF_FDEVMSB_45000 0x02 -#define RF_FDEVLSB_45000 0xE1 -#define RF_FDEVMSB_50000 0x03 -#define RF_FDEVLSB_50000 0x33 -#define RF_FDEVMSB_55000 0x03 -#define RF_FDEVLSB_55000 0x85 -#define RF_FDEVMSB_60000 0x03 -#define RF_FDEVLSB_60000 0xD7 -#define RF_FDEVMSB_65000 0x04 -#define RF_FDEVLSB_65000 0x29 -#define RF_FDEVMSB_70000 0x04 -#define RF_FDEVLSB_70000 0x7B -#define RF_FDEVMSB_75000 0x04 -#define RF_FDEVLSB_75000 0xCD -#define RF_FDEVMSB_80000 0x05 -#define RF_FDEVLSB_80000 0x1F -#define RF_FDEVMSB_85000 0x05 -#define RF_FDEVLSB_85000 0x71 -#define RF_FDEVMSB_90000 0x05 -#define RF_FDEVLSB_90000 0xC3 -#define RF_FDEVMSB_95000 0x06 -#define RF_FDEVLSB_95000 0x14 -#define RF_FDEVMSB_100000 0x06 -#define RF_FDEVLSB_100000 0x66 -#define RF_FDEVMSB_110000 0x07 -#define RF_FDEVLSB_110000 0x0A -#define RF_FDEVMSB_120000 0x07 -#define RF_FDEVLSB_120000 0xAE -#define RF_FDEVMSB_130000 0x08 -#define RF_FDEVLSB_130000 0x52 -#define RF_FDEVMSB_140000 0x08 -#define RF_FDEVLSB_140000 0xF6 -#define RF_FDEVMSB_150000 0x09 -#define RF_FDEVLSB_150000 0x9A -#define RF_FDEVMSB_160000 0x0A -#define RF_FDEVLSB_160000 0x3D -#define RF_FDEVMSB_170000 0x0A -#define RF_FDEVLSB_170000 0xE1 -#define RF_FDEVMSB_180000 0x0B -#define RF_FDEVLSB_180000 0x85 -#define RF_FDEVMSB_190000 0x0C -#define RF_FDEVLSB_190000 0x29 -#define RF_FDEVMSB_200000 0x0C -#define RF_FDEVLSB_200000 0xCD -#define RF_FDEVMSB_210000 0x0D -#define RF_FDEVLSB_210000 0x71 -#define RF_FDEVMSB_220000 0x0E -#define RF_FDEVLSB_220000 0x14 -#define RF_FDEVMSB_230000 0x0E -#define RF_FDEVLSB_230000 0xB8 -#define RF_FDEVMSB_240000 0x0F -#define RF_FDEVLSB_240000 0x5C -#define RF_FDEVMSB_250000 0x10 -#define RF_FDEVLSB_250000 0x00 -#define RF_FDEVMSB_260000 0x10 -#define RF_FDEVLSB_260000 0xA4 -#define RF_FDEVMSB_270000 0x11 -#define RF_FDEVLSB_270000 0x48 -#define RF_FDEVMSB_280000 0x11 -#define RF_FDEVLSB_280000 0xEC -#define RF_FDEVMSB_290000 0x12 -#define RF_FDEVLSB_290000 0x8F -#define RF_FDEVMSB_300000 0x13 -#define RF_FDEVLSB_300000 0x33 +#define RF_FDEVMSB_2000 0x00 +#define RF_FDEVLSB_2000 0x21 +#define RF_FDEVMSB_5000 0x00 // Default +#define RF_FDEVLSB_5000 0x52 // Default +#define RF_FDEVMSB_7500 0x00 +#define RF_FDEVLSB_7500 0x7B +#define RF_FDEVMSB_10000 0x00 +#define RF_FDEVLSB_10000 0xA4 +#define RF_FDEVMSB_15000 0x00 +#define RF_FDEVLSB_15000 0xF6 +#define RF_FDEVMSB_20000 0x01 +#define RF_FDEVLSB_20000 0x48 +#define RF_FDEVMSB_25000 0x01 +#define RF_FDEVLSB_25000 0x9A +#define RF_FDEVMSB_30000 0x01 +#define RF_FDEVLSB_30000 0xEC +#define RF_FDEVMSB_35000 0x02 +#define RF_FDEVLSB_35000 0x3D +#define RF_FDEVMSB_40000 0x02 +#define RF_FDEVLSB_40000 0x8F +#define RF_FDEVMSB_45000 0x02 +#define RF_FDEVLSB_45000 0xE1 +#define RF_FDEVMSB_50000 0x03 +#define RF_FDEVLSB_50000 0x33 +#define RF_FDEVMSB_55000 0x03 +#define RF_FDEVLSB_55000 0x85 +#define RF_FDEVMSB_60000 0x03 +#define RF_FDEVLSB_60000 0xD7 +#define RF_FDEVMSB_65000 0x04 +#define RF_FDEVLSB_65000 0x29 +#define RF_FDEVMSB_70000 0x04 +#define RF_FDEVLSB_70000 0x7B +#define RF_FDEVMSB_75000 0x04 +#define RF_FDEVLSB_75000 0xCD +#define RF_FDEVMSB_80000 0x05 +#define RF_FDEVLSB_80000 0x1F +#define RF_FDEVMSB_85000 0x05 +#define RF_FDEVLSB_85000 0x71 +#define RF_FDEVMSB_90000 0x05 +#define RF_FDEVLSB_90000 0xC3 +#define RF_FDEVMSB_95000 0x06 +#define RF_FDEVLSB_95000 0x14 +#define RF_FDEVMSB_100000 0x06 +#define RF_FDEVLSB_100000 0x66 +#define RF_FDEVMSB_110000 0x07 +#define RF_FDEVLSB_110000 0x0A +#define RF_FDEVMSB_120000 0x07 +#define RF_FDEVLSB_120000 0xAE +#define RF_FDEVMSB_130000 0x08 +#define RF_FDEVLSB_130000 0x52 +#define RF_FDEVMSB_140000 0x08 +#define RF_FDEVLSB_140000 0xF6 +#define RF_FDEVMSB_150000 0x09 +#define RF_FDEVLSB_150000 0x9A +#define RF_FDEVMSB_160000 0x0A +#define RF_FDEVLSB_160000 0x3D +#define RF_FDEVMSB_170000 0x0A +#define RF_FDEVLSB_170000 0xE1 +#define RF_FDEVMSB_180000 0x0B +#define RF_FDEVLSB_180000 0x85 +#define RF_FDEVMSB_190000 0x0C +#define RF_FDEVLSB_190000 0x29 +#define RF_FDEVMSB_200000 0x0C +#define RF_FDEVLSB_200000 0xCD +#define RF_FDEVMSB_210000 0x0D +#define RF_FDEVLSB_210000 0x71 +#define RF_FDEVMSB_220000 0x0E +#define RF_FDEVLSB_220000 0x14 +#define RF_FDEVMSB_230000 0x0E +#define RF_FDEVLSB_230000 0xB8 +#define RF_FDEVMSB_240000 0x0F +#define RF_FDEVLSB_240000 0x5C +#define RF_FDEVMSB_250000 0x10 +#define RF_FDEVLSB_250000 0x00 +#define RF_FDEVMSB_260000 0x10 +#define RF_FDEVLSB_260000 0xA4 +#define RF_FDEVMSB_270000 0x11 +#define RF_FDEVLSB_270000 0x48 +#define RF_FDEVMSB_280000 0x11 +#define RF_FDEVLSB_280000 0xEC +#define RF_FDEVMSB_290000 0x12 +#define RF_FDEVLSB_290000 0x8F +#define RF_FDEVMSB_300000 0x13 +#define RF_FDEVLSB_300000 0x33 + // RegFrf (MHz) - carrier frequency // 315Mhz band -#define RF_FRFMSB_314 0x4E -#define RF_FRFMID_314 0x80 -#define RF_FRFLSB_314 0x00 -#define RF_FRFMSB_315 0x4E -#define RF_FRFMID_315 0xC0 -#define RF_FRFLSB_315 0x00 -#define RF_FRFMSB_316 0x4F -#define RF_FRFMID_316 0x00 -#define RF_FRFLSB_316 0x00 +#define RF_FRFMSB_314 0x4E +#define RF_FRFMID_314 0x80 +#define RF_FRFLSB_314 0x00 +#define RF_FRFMSB_315 0x4E +#define RF_FRFMID_315 0xC0 +#define RF_FRFLSB_315 0x00 +#define RF_FRFMSB_316 0x4F +#define RF_FRFMID_316 0x00 +#define RF_FRFLSB_316 0x00 // 433mhz band -#define RF_FRFMSB_433 0x6C -#define RF_FRFMID_433 0x40 -#define RF_FRFLSB_433 0x00 -#define RF_FRFMSB_434 0x6C -#define RF_FRFMID_434 0x80 -#define RF_FRFLSB_434 0x00 -#define RF_FRFMSB_435 0x6C -#define RF_FRFMID_435 0xC0 -#define RF_FRFLSB_435 0x00 +#define RF_FRFMSB_433 0x6C +#define RF_FRFMID_433 0x40 +#define RF_FRFLSB_433 0x00 +#define RF_FRFMSB_434 0x6C +#define RF_FRFMID_434 0x80 +#define RF_FRFLSB_434 0x00 +#define RF_FRFMSB_435 0x6C +#define RF_FRFMID_435 0xC0 +#define RF_FRFLSB_435 0x00 // 868Mhz band -#define RF_FRFMSB_863 0xD7 -#define RF_FRFMID_863 0xC0 -#define RF_FRFLSB_863 0x00 -#define RF_FRFMSB_864 0xD8 -#define RF_FRFMID_864 0x00 -#define RF_FRFLSB_864 0x00 -#define RF_FRFMSB_865 0xD8 -#define RF_FRFMID_865 0x40 -#define RF_FRFLSB_865 0x00 -#define RF_FRFMSB_866 0xD8 -#define RF_FRFMID_866 0x80 -#define RF_FRFLSB_866 0x00 -#define RF_FRFMSB_867 0xD8 -#define RF_FRFMID_867 0xC0 -#define RF_FRFLSB_867 0x00 -#define RF_FRFMSB_868 0xD9 -#define RF_FRFMID_868 0x00 -#define RF_FRFLSB_868 0x00 -#define RF_FRFMSB_869 0xD9 -#define RF_FRFMID_869 0x40 -#define RF_FRFLSB_869 0x00 -#define RF_FRFMSB_870 0xD9 -#define RF_FRFMID_870 0x80 -#define RF_FRFLSB_870 0x00 +#define RF_FRFMSB_863 0xD7 +#define RF_FRFMID_863 0xC0 +#define RF_FRFLSB_863 0x00 +#define RF_FRFMSB_864 0xD8 +#define RF_FRFMID_864 0x00 +#define RF_FRFLSB_864 0x00 +#define RF_FRFMSB_865 0xD8 +#define RF_FRFMID_865 0x40 +#define RF_FRFLSB_865 0x00 +#define RF_FRFMSB_866 0xD8 +#define RF_FRFMID_866 0x80 +#define RF_FRFLSB_866 0x00 +#define RF_FRFMSB_867 0xD8 +#define RF_FRFMID_867 0xC0 +#define RF_FRFLSB_867 0x00 +#define RF_FRFMSB_868 0xD9 +#define RF_FRFMID_868 0x00 +#define RF_FRFLSB_868 0x00 +#define RF_FRFMSB_869 0xD9 +#define RF_FRFMID_869 0x40 +#define RF_FRFLSB_869 0x00 +#define RF_FRFMSB_870 0xD9 +#define RF_FRFMID_870 0x80 +#define RF_FRFLSB_870 0x00 // 915Mhz band -#define RF_FRFMSB_902 0xE1 -#define RF_FRFMID_902 0x80 -#define RF_FRFLSB_902 0x00 -#define RF_FRFMSB_903 0xE1 -#define RF_FRFMID_903 0xC0 -#define RF_FRFLSB_903 0x00 -#define RF_FRFMSB_904 0xE2 -#define RF_FRFMID_904 0x00 -#define RF_FRFLSB_904 0x00 -#define RF_FRFMSB_905 0xE2 -#define RF_FRFMID_905 0x40 -#define RF_FRFLSB_905 0x00 -#define RF_FRFMSB_906 0xE2 -#define RF_FRFMID_906 0x80 -#define RF_FRFLSB_906 0x00 -#define RF_FRFMSB_907 0xE2 -#define RF_FRFMID_907 0xC0 -#define RF_FRFLSB_907 0x00 -#define RF_FRFMSB_908 0xE3 -#define RF_FRFMID_908 0x00 -#define RF_FRFLSB_908 0x00 -#define RF_FRFMSB_909 0xE3 -#define RF_FRFMID_909 0x40 -#define RF_FRFLSB_909 0x00 -#define RF_FRFMSB_910 0xE3 -#define RF_FRFMID_910 0x80 -#define RF_FRFLSB_910 0x00 -#define RF_FRFMSB_911 0xE3 -#define RF_FRFMID_911 0xC0 -#define RF_FRFLSB_911 0x00 -#define RF_FRFMSB_912 0xE4 -#define RF_FRFMID_912 0x00 -#define RF_FRFLSB_912 0x00 -#define RF_FRFMSB_913 0xE4 -#define RF_FRFMID_913 0x40 -#define RF_FRFLSB_913 0x00 -#define RF_FRFMSB_914 0xE4 -#define RF_FRFMID_914 0x80 -#define RF_FRFLSB_914 0x00 -#define RF_FRFMSB_915 0xE4 // Default -#define RF_FRFMID_915 0xC0 // Default -#define RF_FRFLSB_915 0x00 // Default -#define RF_FRFMSB_916 0xE5 -#define RF_FRFMID_916 0x00 -#define RF_FRFLSB_916 0x00 -#define RF_FRFMSB_917 0xE5 -#define RF_FRFMID_917 0x40 -#define RF_FRFLSB_917 0x00 -#define RF_FRFMSB_918 0xE5 -#define RF_FRFMID_918 0x80 -#define RF_FRFLSB_918 0x00 -#define RF_FRFMSB_919 0xE5 -#define RF_FRFMID_919 0xC0 -#define RF_FRFLSB_919 0x00 -#define RF_FRFMSB_920 0xE6 -#define RF_FRFMID_920 0x00 -#define RF_FRFLSB_920 0x00 -#define RF_FRFMSB_921 0xE6 -#define RF_FRFMID_921 0x40 -#define RF_FRFLSB_921 0x00 -#define RF_FRFMSB_922 0xE6 -#define RF_FRFMID_922 0x80 -#define RF_FRFLSB_922 0x00 -#define RF_FRFMSB_923 0xE6 -#define RF_FRFMID_923 0xC0 -#define RF_FRFLSB_923 0x00 -#define RF_FRFMSB_924 0xE7 -#define RF_FRFMID_924 0x00 -#define RF_FRFLSB_924 0x00 -#define RF_FRFMSB_925 0xE7 -#define RF_FRFMID_925 0x40 -#define RF_FRFLSB_925 0x00 -#define RF_FRFMSB_926 0xE7 -#define RF_FRFMID_926 0x80 -#define RF_FRFLSB_926 0x00 -#define RF_FRFMSB_927 0xE7 -#define RF_FRFMID_927 0xC0 -#define RF_FRFLSB_927 0x00 -#define RF_FRFMSB_928 0xE8 -#define RF_FRFMID_928 0x00 -#define RF_FRFLSB_928 0x00 +#define RF_FRFMSB_902 0xE1 +#define RF_FRFMID_902 0x80 +#define RF_FRFLSB_902 0x00 +#define RF_FRFMSB_903 0xE1 +#define RF_FRFMID_903 0xC0 +#define RF_FRFLSB_903 0x00 +#define RF_FRFMSB_904 0xE2 +#define RF_FRFMID_904 0x00 +#define RF_FRFLSB_904 0x00 +#define RF_FRFMSB_905 0xE2 +#define RF_FRFMID_905 0x40 +#define RF_FRFLSB_905 0x00 +#define RF_FRFMSB_906 0xE2 +#define RF_FRFMID_906 0x80 +#define RF_FRFLSB_906 0x00 +#define RF_FRFMSB_907 0xE2 +#define RF_FRFMID_907 0xC0 +#define RF_FRFLSB_907 0x00 +#define RF_FRFMSB_908 0xE3 +#define RF_FRFMID_908 0x00 +#define RF_FRFLSB_908 0x00 +#define RF_FRFMSB_909 0xE3 +#define RF_FRFMID_909 0x40 +#define RF_FRFLSB_909 0x00 +#define RF_FRFMSB_910 0xE3 +#define RF_FRFMID_910 0x80 +#define RF_FRFLSB_910 0x00 +#define RF_FRFMSB_911 0xE3 +#define RF_FRFMID_911 0xC0 +#define RF_FRFLSB_911 0x00 +#define RF_FRFMSB_912 0xE4 +#define RF_FRFMID_912 0x00 +#define RF_FRFLSB_912 0x00 +#define RF_FRFMSB_913 0xE4 +#define RF_FRFMID_913 0x40 +#define RF_FRFLSB_913 0x00 +#define RF_FRFMSB_914 0xE4 +#define RF_FRFMID_914 0x80 +#define RF_FRFLSB_914 0x00 +#define RF_FRFMSB_915 0xE4 // Default +#define RF_FRFMID_915 0xC0 // Default +#define RF_FRFLSB_915 0x00 // Default +#define RF_FRFMSB_916 0xE5 +#define RF_FRFMID_916 0x00 +#define RF_FRFLSB_916 0x00 +#define RF_FRFMSB_917 0xE5 +#define RF_FRFMID_917 0x40 +#define RF_FRFLSB_917 0x00 +#define RF_FRFMSB_918 0xE5 +#define RF_FRFMID_918 0x80 +#define RF_FRFLSB_918 0x00 +#define RF_FRFMSB_919 0xE5 +#define RF_FRFMID_919 0xC0 +#define RF_FRFLSB_919 0x00 +#define RF_FRFMSB_920 0xE6 +#define RF_FRFMID_920 0x00 +#define RF_FRFLSB_920 0x00 +#define RF_FRFMSB_921 0xE6 +#define RF_FRFMID_921 0x40 +#define RF_FRFLSB_921 0x00 +#define RF_FRFMSB_922 0xE6 +#define RF_FRFMID_922 0x80 +#define RF_FRFLSB_922 0x00 +#define RF_FRFMSB_923 0xE6 +#define RF_FRFMID_923 0xC0 +#define RF_FRFLSB_923 0x00 +#define RF_FRFMSB_924 0xE7 +#define RF_FRFMID_924 0x00 +#define RF_FRFLSB_924 0x00 +#define RF_FRFMSB_925 0xE7 +#define RF_FRFMID_925 0x40 +#define RF_FRFLSB_925 0x00 +#define RF_FRFMSB_926 0xE7 +#define RF_FRFMID_926 0x80 +#define RF_FRFLSB_926 0x00 +#define RF_FRFMSB_927 0xE7 +#define RF_FRFMID_927 0xC0 +#define RF_FRFLSB_927 0x00 +#define RF_FRFMSB_928 0xE8 +#define RF_FRFMID_928 0x00 +#define RF_FRFLSB_928 0x00 // RegOsc1 -#define RF_OSC1_RCCAL_START 0x80 -#define RF_OSC1_RCCAL_DONE 0x40 +#define RF_OSC1_RCCAL_START 0x80 +#define RF_OSC1_RCCAL_DONE 0x40 + + +// RegAfcCtrl +#define RF_AFCCTRL_LOWBETA_OFF 0x00 // Default +#define RF_AFCCTRL_LOWBETA_ON 0x20 + // RegLowBat -#define RF_LOWBAT_MONITOR 0x10 -#define RF_LOWBAT_ON 0x08 -#define RF_LOWBAT_OFF 0x00 // Default +#define RF_LOWBAT_MONITOR 0x10 +#define RF_LOWBAT_ON 0x08 +#define RF_LOWBAT_OFF 0x00 // Default -#define RF_LOWBAT_TRIM_1695 0x00 -#define RF_LOWBAT_TRIM_1764 0x01 -#define RF_LOWBAT_TRIM_1835 0x02 // Default -#define RF_LOWBAT_TRIM_1905 0x03 -#define RF_LOWBAT_TRIM_1976 0x04 -#define RF_LOWBAT_TRIM_2045 0x05 -#define RF_LOWBAT_TRIM_2116 0x06 -#define RF_LOWBAT_TRIM_2185 0x07 +#define RF_LOWBAT_TRIM_1695 0x00 +#define RF_LOWBAT_TRIM_1764 0x01 +#define RF_LOWBAT_TRIM_1835 0x02 // Default +#define RF_LOWBAT_TRIM_1905 0x03 +#define RF_LOWBAT_TRIM_1976 0x04 +#define RF_LOWBAT_TRIM_2045 0x05 +#define RF_LOWBAT_TRIM_2116 0x06 +#define RF_LOWBAT_TRIM_2185 0x07 // RegListen1 -#define RF_LISTEN1_RESOL_64 0x50 -#define RF_LISTEN1_RESOL_4100 0xA0 // Default -#define RF_LISTEN1_RESOL_262000 0xF0 +#define RF_LISTEN1_RESOL_64 0x50 +#define RF_LISTEN1_RESOL_4100 0xA0 // Default +#define RF_LISTEN1_RESOL_262000 0xF0 -#define RF_LISTEN1_CRITERIA_RSSI 0x00 // Default -#define RF_LISTEN1_CRITERIA_RSSIANDSYNC 0x08 +#define RF_LISTEN1_RESOL_IDLE_64 0x40 +#define RF_LISTEN1_RESOL_IDLE_4100 0x80 // Default +#define RF_LISTEN1_RESOL_IDLE_262000 0xC0 -#define RF_LISTEN1_END_00 0x00 -#define RF_LISTEN1_END_01 0x02 // Default -#define RF_LISTEN1_END_10 0x04 +#define RF_LISTEN1_RESOL_RX_64 0x10 +#define RF_LISTEN1_RESOL_RX_4100 0x20 // Default +#define RF_LISTEN1_RESOL_RX_262000 0x30 + +#define RF_LISTEN1_CRITERIA_RSSI 0x00 // Default +#define RF_LISTEN1_CRITERIA_RSSIANDSYNC 0x08 + +#define RF_LISTEN1_END_00 0x00 +#define RF_LISTEN1_END_01 0x02 // Default +#define RF_LISTEN1_END_10 0x04 // RegListen2 -#define RF_LISTEN2_COEFIDLE_VALUE 0xF5 // Default +#define RF_LISTEN2_COEFIDLE_VALUE 0xF5 // Default + // RegListen3 -#define RF_LISTEN3_COEFRX_VALUE 0x20 // Default +#define RF_LISTEN3_COEFRX_VALUE 0x20 // Default + + +// RegVersion +#define RF_VERSION_VER 0x24 // Default + // RegPaLevel -#define RF_PALEVEL_PA0_ON 0x80 // Default -#define RF_PALEVEL_PA0_OFF 0x00 -#define RF_PALEVEL_PA1_ON 0x40 -#define RF_PALEVEL_PA1_OFF 0x00 // Default -#define RF_PALEVEL_PA2_ON 0x20 -#define RF_PALEVEL_PA2_OFF 0x00 // Default +#define RF_PALEVEL_PA0_ON 0x80 // Default +#define RF_PALEVEL_PA0_OFF 0x00 +#define RF_PALEVEL_PA1_ON 0x40 +#define RF_PALEVEL_PA1_OFF 0x00 // Default +#define RF_PALEVEL_PA2_ON 0x20 +#define RF_PALEVEL_PA2_OFF 0x00 // Default -#define RF_PALEVEL_OUTPUTPOWER_00000 0x00 -#define RF_PALEVEL_OUTPUTPOWER_00001 0x01 -#define RF_PALEVEL_OUTPUTPOWER_00010 0x02 -#define RF_PALEVEL_OUTPUTPOWER_00011 0x03 -#define RF_PALEVEL_OUTPUTPOWER_00100 0x04 -#define RF_PALEVEL_OUTPUTPOWER_00101 0x05 -#define RF_PALEVEL_OUTPUTPOWER_00110 0x06 -#define RF_PALEVEL_OUTPUTPOWER_00111 0x07 -#define RF_PALEVEL_OUTPUTPOWER_01000 0x08 -#define RF_PALEVEL_OUTPUTPOWER_01001 0x09 -#define RF_PALEVEL_OUTPUTPOWER_01010 0x0A -#define RF_PALEVEL_OUTPUTPOWER_01011 0x0B -#define RF_PALEVEL_OUTPUTPOWER_01100 0x0C -#define RF_PALEVEL_OUTPUTPOWER_01101 0x0D -#define RF_PALEVEL_OUTPUTPOWER_01110 0x0E -#define RF_PALEVEL_OUTPUTPOWER_01111 0x0F -#define RF_PALEVEL_OUTPUTPOWER_10000 0x10 -#define RF_PALEVEL_OUTPUTPOWER_10001 0x11 -#define RF_PALEVEL_OUTPUTPOWER_10010 0x12 -#define RF_PALEVEL_OUTPUTPOWER_10011 0x13 -#define RF_PALEVEL_OUTPUTPOWER_10100 0x14 -#define RF_PALEVEL_OUTPUTPOWER_10101 0x15 -#define RF_PALEVEL_OUTPUTPOWER_10110 0x16 -#define RF_PALEVEL_OUTPUTPOWER_10111 0x17 -#define RF_PALEVEL_OUTPUTPOWER_11000 0x18 -#define RF_PALEVEL_OUTPUTPOWER_11001 0x19 -#define RF_PALEVEL_OUTPUTPOWER_11010 0x1A -#define RF_PALEVEL_OUTPUTPOWER_11011 0x1B -#define RF_PALEVEL_OUTPUTPOWER_11100 0x1C -#define RF_PALEVEL_OUTPUTPOWER_11101 0x1D -#define RF_PALEVEL_OUTPUTPOWER_11110 0x1E -#define RF_PALEVEL_OUTPUTPOWER_11111 0x1F // Default +#define RF_PALEVEL_OUTPUTPOWER_00000 0x00 +#define RF_PALEVEL_OUTPUTPOWER_00001 0x01 +#define RF_PALEVEL_OUTPUTPOWER_00010 0x02 +#define RF_PALEVEL_OUTPUTPOWER_00011 0x03 +#define RF_PALEVEL_OUTPUTPOWER_00100 0x04 +#define RF_PALEVEL_OUTPUTPOWER_00101 0x05 +#define RF_PALEVEL_OUTPUTPOWER_00110 0x06 +#define RF_PALEVEL_OUTPUTPOWER_00111 0x07 +#define RF_PALEVEL_OUTPUTPOWER_01000 0x08 +#define RF_PALEVEL_OUTPUTPOWER_01001 0x09 +#define RF_PALEVEL_OUTPUTPOWER_01010 0x0A +#define RF_PALEVEL_OUTPUTPOWER_01011 0x0B +#define RF_PALEVEL_OUTPUTPOWER_01100 0x0C +#define RF_PALEVEL_OUTPUTPOWER_01101 0x0D +#define RF_PALEVEL_OUTPUTPOWER_01110 0x0E +#define RF_PALEVEL_OUTPUTPOWER_01111 0x0F +#define RF_PALEVEL_OUTPUTPOWER_10000 0x10 +#define RF_PALEVEL_OUTPUTPOWER_10001 0x11 +#define RF_PALEVEL_OUTPUTPOWER_10010 0x12 +#define RF_PALEVEL_OUTPUTPOWER_10011 0x13 +#define RF_PALEVEL_OUTPUTPOWER_10100 0x14 +#define RF_PALEVEL_OUTPUTPOWER_10101 0x15 +#define RF_PALEVEL_OUTPUTPOWER_10110 0x16 +#define RF_PALEVEL_OUTPUTPOWER_10111 0x17 +#define RF_PALEVEL_OUTPUTPOWER_11000 0x18 +#define RF_PALEVEL_OUTPUTPOWER_11001 0x19 +#define RF_PALEVEL_OUTPUTPOWER_11010 0x1A +#define RF_PALEVEL_OUTPUTPOWER_11011 0x1B +#define RF_PALEVEL_OUTPUTPOWER_11100 0x1C +#define RF_PALEVEL_OUTPUTPOWER_11101 0x1D +#define RF_PALEVEL_OUTPUTPOWER_11110 0x1E +#define RF_PALEVEL_OUTPUTPOWER_11111 0x1F // Default // RegPaRamp -#define RF_PARAMP_3400 0x00 -#define RF_PARAMP_2000 0x01 -#define RF_PARAMP_1000 0x02 -#define RF_PARAMP_500 0x03 -#define RF_PARAMP_250 0x04 -#define RF_PARAMP_125 0x05 -#define RF_PARAMP_100 0x06 -#define RF_PARAMP_62 0x07 -#define RF_PARAMP_50 0x08 -#define RF_PARAMP_40 0x09 // Default -#define RF_PARAMP_31 0x0A -#define RF_PARAMP_25 0x0B -#define RF_PARAMP_20 0x0C -#define RF_PARAMP_15 0x0D -#define RF_PARAMP_12 0x0E -#define RF_PARAMP_10 0x0F +#define RF_PARAMP_3400 0x00 +#define RF_PARAMP_2000 0x01 +#define RF_PARAMP_1000 0x02 +#define RF_PARAMP_500 0x03 +#define RF_PARAMP_250 0x04 +#define RF_PARAMP_125 0x05 +#define RF_PARAMP_100 0x06 +#define RF_PARAMP_62 0x07 +#define RF_PARAMP_50 0x08 +#define RF_PARAMP_40 0x09 // Default +#define RF_PARAMP_31 0x0A +#define RF_PARAMP_25 0x0B +#define RF_PARAMP_20 0x0C +#define RF_PARAMP_15 0x0D +#define RF_PARAMP_12 0x0E +#define RF_PARAMP_10 0x0F // RegOcp -#define RF_OCP_OFF 0x0F -#define RF_OCP_ON 0x1A // Default +#define RF_OCP_OFF 0x0F +#define RF_OCP_ON 0x1A // Default -#define RF_OCP_TRIM_45 0x00 -#define RF_OCP_TRIM_50 0x01 -#define RF_OCP_TRIM_55 0x02 -#define RF_OCP_TRIM_60 0x03 -#define RF_OCP_TRIM_65 0x04 -#define RF_OCP_TRIM_70 0x05 -#define RF_OCP_TRIM_75 0x06 -#define RF_OCP_TRIM_80 0x07 -#define RF_OCP_TRIM_85 0x08 -#define RF_OCP_TRIM_90 0x09 -#define RF_OCP_TRIM_95 0x0A -#define RF_OCP_TRIM_100 0x0B // Default -#define RF_OCP_TRIM_105 0x0C -#define RF_OCP_TRIM_110 0x0D -#define RF_OCP_TRIM_115 0x0E -#define RF_OCP_TRIM_120 0x0F +#define RF_OCP_TRIM_45 0x00 +#define RF_OCP_TRIM_50 0x01 +#define RF_OCP_TRIM_55 0x02 +#define RF_OCP_TRIM_60 0x03 +#define RF_OCP_TRIM_65 0x04 +#define RF_OCP_TRIM_70 0x05 +#define RF_OCP_TRIM_75 0x06 +#define RF_OCP_TRIM_80 0x07 +#define RF_OCP_TRIM_85 0x08 +#define RF_OCP_TRIM_90 0x09 +#define RF_OCP_TRIM_95 0x0A // Default +#define RF_OCP_TRIM_100 0x0B +#define RF_OCP_TRIM_105 0x0C +#define RF_OCP_TRIM_110 0x0D +#define RF_OCP_TRIM_115 0x0E +#define RF_OCP_TRIM_120 0x0F -// RegAgcRef -#define RF_AGCREF_AUTO_ON 0x40 // Default -#define RF_AGCREF_AUTO_OFF 0x00 +// RegAgcRef - not present on RFM69/SX1231 +#define RF_AGCREF_AUTO_ON 0x40 // Default +#define RF_AGCREF_AUTO_OFF 0x00 -#define RF_AGCREF_LEVEL_MINUS80 0x00 // Default -#define RF_AGCREF_LEVEL_MINUS81 0x01 -#define RF_AGCREF_LEVEL_MINUS82 0x02 -#define RF_AGCREF_LEVEL_MINUS83 0x03 -#define RF_AGCREF_LEVEL_MINUS84 0x04 -#define RF_AGCREF_LEVEL_MINUS85 0x05 -#define RF_AGCREF_LEVEL_MINUS86 0x06 -#define RF_AGCREF_LEVEL_MINUS87 0x07 -#define RF_AGCREF_LEVEL_MINUS88 0x08 -#define RF_AGCREF_LEVEL_MINUS89 0x09 -#define RF_AGCREF_LEVEL_MINUS90 0x0A -#define RF_AGCREF_LEVEL_MINUS91 0x0B -#define RF_AGCREF_LEVEL_MINUS92 0x0C -#define RF_AGCREF_LEVEL_MINUS93 0x0D -#define RF_AGCREF_LEVEL_MINUS94 0x0E -#define RF_AGCREF_LEVEL_MINUS95 0x0F -#define RF_AGCREF_LEVEL_MINUS96 0x10 -#define RF_AGCREF_LEVEL_MINUS97 0x11 -#define RF_AGCREF_LEVEL_MINUS98 0x12 -#define RF_AGCREF_LEVEL_MINUS99 0x13 -#define RF_AGCREF_LEVEL_MINUS100 0x14 -#define RF_AGCREF_LEVEL_MINUS101 0x15 -#define RF_AGCREF_LEVEL_MINUS102 0x16 -#define RF_AGCREF_LEVEL_MINUS103 0x17 -#define RF_AGCREF_LEVEL_MINUS104 0x18 -#define RF_AGCREF_LEVEL_MINUS105 0x19 -#define RF_AGCREF_LEVEL_MINUS106 0x1A -#define RF_AGCREF_LEVEL_MINUS107 0x1B -#define RF_AGCREF_LEVEL_MINUS108 0x1C -#define RF_AGCREF_LEVEL_MINUS109 0x1D -#define RF_AGCREF_LEVEL_MINUS110 0x1E -#define RF_AGCREF_LEVEL_MINUS111 0x1F -#define RF_AGCREF_LEVEL_MINUS112 0x20 -#define RF_AGCREF_LEVEL_MINUS113 0x21 -#define RF_AGCREF_LEVEL_MINUS114 0x22 -#define RF_AGCREF_LEVEL_MINUS115 0x23 -#define RF_AGCREF_LEVEL_MINUS116 0x24 -#define RF_AGCREF_LEVEL_MINUS117 0x25 -#define RF_AGCREF_LEVEL_MINUS118 0x26 -#define RF_AGCREF_LEVEL_MINUS119 0x27 -#define RF_AGCREF_LEVEL_MINUS120 0x28 -#define RF_AGCREF_LEVEL_MINUS121 0x29 -#define RF_AGCREF_LEVEL_MINUS122 0x2A -#define RF_AGCREF_LEVEL_MINUS123 0x2B -#define RF_AGCREF_LEVEL_MINUS124 0x2C -#define RF_AGCREF_LEVEL_MINUS125 0x2D -#define RF_AGCREF_LEVEL_MINUS126 0x2E -#define RF_AGCREF_LEVEL_MINUS127 0x2F -#define RF_AGCREF_LEVEL_MINUS128 0x30 -#define RF_AGCREF_LEVEL_MINUS129 0x31 -#define RF_AGCREF_LEVEL_MINUS130 0x32 -#define RF_AGCREF_LEVEL_MINUS131 0x33 -#define RF_AGCREF_LEVEL_MINUS132 0x34 -#define RF_AGCREF_LEVEL_MINUS133 0x35 -#define RF_AGCREF_LEVEL_MINUS134 0x36 -#define RF_AGCREF_LEVEL_MINUS135 0x37 -#define RF_AGCREF_LEVEL_MINUS136 0x38 -#define RF_AGCREF_LEVEL_MINUS137 0x39 -#define RF_AGCREF_LEVEL_MINUS138 0x3A -#define RF_AGCREF_LEVEL_MINUS139 0x3B -#define RF_AGCREF_LEVEL_MINUS140 0x3C -#define RF_AGCREF_LEVEL_MINUS141 0x3D -#define RF_AGCREF_LEVEL_MINUS142 0x3E -#define RF_AGCREF_LEVEL_MINUS143 0x3F +#define RF_AGCREF_LEVEL_MINUS80 0x00 // Default +#define RF_AGCREF_LEVEL_MINUS81 0x01 +#define RF_AGCREF_LEVEL_MINUS82 0x02 +#define RF_AGCREF_LEVEL_MINUS83 0x03 +#define RF_AGCREF_LEVEL_MINUS84 0x04 +#define RF_AGCREF_LEVEL_MINUS85 0x05 +#define RF_AGCREF_LEVEL_MINUS86 0x06 +#define RF_AGCREF_LEVEL_MINUS87 0x07 +#define RF_AGCREF_LEVEL_MINUS88 0x08 +#define RF_AGCREF_LEVEL_MINUS89 0x09 +#define RF_AGCREF_LEVEL_MINUS90 0x0A +#define RF_AGCREF_LEVEL_MINUS91 0x0B +#define RF_AGCREF_LEVEL_MINUS92 0x0C +#define RF_AGCREF_LEVEL_MINUS93 0x0D +#define RF_AGCREF_LEVEL_MINUS94 0x0E +#define RF_AGCREF_LEVEL_MINUS95 0x0F +#define RF_AGCREF_LEVEL_MINUS96 0x10 +#define RF_AGCREF_LEVEL_MINUS97 0x11 +#define RF_AGCREF_LEVEL_MINUS98 0x12 +#define RF_AGCREF_LEVEL_MINUS99 0x13 +#define RF_AGCREF_LEVEL_MINUS100 0x14 +#define RF_AGCREF_LEVEL_MINUS101 0x15 +#define RF_AGCREF_LEVEL_MINUS102 0x16 +#define RF_AGCREF_LEVEL_MINUS103 0x17 +#define RF_AGCREF_LEVEL_MINUS104 0x18 +#define RF_AGCREF_LEVEL_MINUS105 0x19 +#define RF_AGCREF_LEVEL_MINUS106 0x1A +#define RF_AGCREF_LEVEL_MINUS107 0x1B +#define RF_AGCREF_LEVEL_MINUS108 0x1C +#define RF_AGCREF_LEVEL_MINUS109 0x1D +#define RF_AGCREF_LEVEL_MINUS110 0x1E +#define RF_AGCREF_LEVEL_MINUS111 0x1F +#define RF_AGCREF_LEVEL_MINUS112 0x20 +#define RF_AGCREF_LEVEL_MINUS113 0x21 +#define RF_AGCREF_LEVEL_MINUS114 0x22 +#define RF_AGCREF_LEVEL_MINUS115 0x23 +#define RF_AGCREF_LEVEL_MINUS116 0x24 +#define RF_AGCREF_LEVEL_MINUS117 0x25 +#define RF_AGCREF_LEVEL_MINUS118 0x26 +#define RF_AGCREF_LEVEL_MINUS119 0x27 +#define RF_AGCREF_LEVEL_MINUS120 0x28 +#define RF_AGCREF_LEVEL_MINUS121 0x29 +#define RF_AGCREF_LEVEL_MINUS122 0x2A +#define RF_AGCREF_LEVEL_MINUS123 0x2B +#define RF_AGCREF_LEVEL_MINUS124 0x2C +#define RF_AGCREF_LEVEL_MINUS125 0x2D +#define RF_AGCREF_LEVEL_MINUS126 0x2E +#define RF_AGCREF_LEVEL_MINUS127 0x2F +#define RF_AGCREF_LEVEL_MINUS128 0x30 +#define RF_AGCREF_LEVEL_MINUS129 0x31 +#define RF_AGCREF_LEVEL_MINUS130 0x32 +#define RF_AGCREF_LEVEL_MINUS131 0x33 +#define RF_AGCREF_LEVEL_MINUS132 0x34 +#define RF_AGCREF_LEVEL_MINUS133 0x35 +#define RF_AGCREF_LEVEL_MINUS134 0x36 +#define RF_AGCREF_LEVEL_MINUS135 0x37 +#define RF_AGCREF_LEVEL_MINUS136 0x38 +#define RF_AGCREF_LEVEL_MINUS137 0x39 +#define RF_AGCREF_LEVEL_MINUS138 0x3A +#define RF_AGCREF_LEVEL_MINUS139 0x3B +#define RF_AGCREF_LEVEL_MINUS140 0x3C +#define RF_AGCREF_LEVEL_MINUS141 0x3D +#define RF_AGCREF_LEVEL_MINUS142 0x3E +#define RF_AGCREF_LEVEL_MINUS143 0x3F -// RegAgcThresh1 -#define RF_AGCTHRESH1_SNRMARGIN_000 0x00 -#define RF_AGCTHRESH1_SNRMARGIN_001 0x20 -#define RF_AGCTHRESH1_SNRMARGIN_010 0x40 -#define RF_AGCTHRESH1_SNRMARGIN_011 0x60 -#define RF_AGCTHRESH1_SNRMARGIN_100 0x80 -#define RF_AGCTHRESH1_SNRMARGIN_101 0xA0 // Default -#define RF_AGCTHRESH1_SNRMARGIN_110 0xC0 -#define RF_AGCTHRESH1_SNRMARGIN_111 0xE0 +// RegAgcThresh1 - not present on RFM69/SX1231 +#define RF_AGCTHRESH1_SNRMARGIN_000 0x00 +#define RF_AGCTHRESH1_SNRMARGIN_001 0x20 +#define RF_AGCTHRESH1_SNRMARGIN_010 0x40 +#define RF_AGCTHRESH1_SNRMARGIN_011 0x60 +#define RF_AGCTHRESH1_SNRMARGIN_100 0x80 +#define RF_AGCTHRESH1_SNRMARGIN_101 0xA0 // Default +#define RF_AGCTHRESH1_SNRMARGIN_110 0xC0 +#define RF_AGCTHRESH1_SNRMARGIN_111 0xE0 -#define RF_AGCTHRESH1_STEP1_0 0x00 -#define RF_AGCTHRESH1_STEP1_1 0x01 -#define RF_AGCTHRESH1_STEP1_2 0x02 -#define RF_AGCTHRESH1_STEP1_3 0x03 -#define RF_AGCTHRESH1_STEP1_4 0x04 -#define RF_AGCTHRESH1_STEP1_5 0x05 -#define RF_AGCTHRESH1_STEP1_6 0x06 -#define RF_AGCTHRESH1_STEP1_7 0x07 -#define RF_AGCTHRESH1_STEP1_8 0x08 -#define RF_AGCTHRESH1_STEP1_9 0x09 -#define RF_AGCTHRESH1_STEP1_10 0x0A -#define RF_AGCTHRESH1_STEP1_11 0x0B -#define RF_AGCTHRESH1_STEP1_12 0x0C -#define RF_AGCTHRESH1_STEP1_13 0x0D -#define RF_AGCTHRESH1_STEP1_14 0x0E -#define RF_AGCTHRESH1_STEP1_15 0x0F -#define RF_AGCTHRESH1_STEP1_16 0x10 // Default -#define RF_AGCTHRESH1_STEP1_17 0x11 -#define RF_AGCTHRESH1_STEP1_18 0x12 -#define RF_AGCTHRESH1_STEP1_19 0x13 -#define RF_AGCTHRESH1_STEP1_20 0x14 -#define RF_AGCTHRESH1_STEP1_21 0x15 -#define RF_AGCTHRESH1_STEP1_22 0x16 -#define RF_AGCTHRESH1_STEP1_23 0x17 -#define RF_AGCTHRESH1_STEP1_24 0x18 -#define RF_AGCTHRESH1_STEP1_25 0x19 -#define RF_AGCTHRESH1_STEP1_26 0x1A -#define RF_AGCTHRESH1_STEP1_27 0x1B -#define RF_AGCTHRESH1_STEP1_28 0x1C -#define RF_AGCTHRESH1_STEP1_29 0x1D -#define RF_AGCTHRESH1_STEP1_30 0x1E -#define RF_AGCTHRESH1_STEP1_31 0x1F +#define RF_AGCTHRESH1_STEP1_0 0x00 +#define RF_AGCTHRESH1_STEP1_1 0x01 +#define RF_AGCTHRESH1_STEP1_2 0x02 +#define RF_AGCTHRESH1_STEP1_3 0x03 +#define RF_AGCTHRESH1_STEP1_4 0x04 +#define RF_AGCTHRESH1_STEP1_5 0x05 +#define RF_AGCTHRESH1_STEP1_6 0x06 +#define RF_AGCTHRESH1_STEP1_7 0x07 +#define RF_AGCTHRESH1_STEP1_8 0x08 +#define RF_AGCTHRESH1_STEP1_9 0x09 +#define RF_AGCTHRESH1_STEP1_10 0x0A +#define RF_AGCTHRESH1_STEP1_11 0x0B +#define RF_AGCTHRESH1_STEP1_12 0x0C +#define RF_AGCTHRESH1_STEP1_13 0x0D +#define RF_AGCTHRESH1_STEP1_14 0x0E +#define RF_AGCTHRESH1_STEP1_15 0x0F +#define RF_AGCTHRESH1_STEP1_16 0x10 // Default +#define RF_AGCTHRESH1_STEP1_17 0x11 +#define RF_AGCTHRESH1_STEP1_18 0x12 +#define RF_AGCTHRESH1_STEP1_19 0x13 +#define RF_AGCTHRESH1_STEP1_20 0x14 +#define RF_AGCTHRESH1_STEP1_21 0x15 +#define RF_AGCTHRESH1_STEP1_22 0x16 +#define RF_AGCTHRESH1_STEP1_23 0x17 +#define RF_AGCTHRESH1_STEP1_24 0x18 +#define RF_AGCTHRESH1_STEP1_25 0x19 +#define RF_AGCTHRESH1_STEP1_26 0x1A +#define RF_AGCTHRESH1_STEP1_27 0x1B +#define RF_AGCTHRESH1_STEP1_28 0x1C +#define RF_AGCTHRESH1_STEP1_29 0x1D +#define RF_AGCTHRESH1_STEP1_30 0x1E +#define RF_AGCTHRESH1_STEP1_31 0x1F -// RegAgcThresh2 -#define RF_AGCTHRESH2_STEP2_0 0x00 -#define RF_AGCTHRESH2_STEP2_1 0x10 -#define RF_AGCTHRESH2_STEP2_2 0x20 -#define RF_AGCTHRESH2_STEP2_3 0x30 // XXX wrong -- Default -#define RF_AGCTHRESH2_STEP2_4 0x40 -#define RF_AGCTHRESH2_STEP2_5 0x50 -#define RF_AGCTHRESH2_STEP2_6 0x60 -#define RF_AGCTHRESH2_STEP2_7 0x70 // default -#define RF_AGCTHRESH2_STEP2_8 0x80 -#define RF_AGCTHRESH2_STEP2_9 0x90 -#define RF_AGCTHRESH2_STEP2_10 0xA0 -#define RF_AGCTHRESH2_STEP2_11 0xB0 -#define RF_AGCTHRESH2_STEP2_12 0xC0 -#define RF_AGCTHRESH2_STEP2_13 0xD0 -#define RF_AGCTHRESH2_STEP2_14 0xE0 -#define RF_AGCTHRESH2_STEP2_15 0xF0 +// RegAgcThresh2 - not present on RFM69/SX1231 +#define RF_AGCTHRESH2_STEP2_0 0x00 +#define RF_AGCTHRESH2_STEP2_1 0x10 +#define RF_AGCTHRESH2_STEP2_2 0x20 +#define RF_AGCTHRESH2_STEP2_3 0x30 // XXX wrong -- Default +#define RF_AGCTHRESH2_STEP2_4 0x40 +#define RF_AGCTHRESH2_STEP2_5 0x50 +#define RF_AGCTHRESH2_STEP2_6 0x60 +#define RF_AGCTHRESH2_STEP2_7 0x70 // default +#define RF_AGCTHRESH2_STEP2_8 0x80 +#define RF_AGCTHRESH2_STEP2_9 0x90 +#define RF_AGCTHRESH2_STEP2_10 0xA0 +#define RF_AGCTHRESH2_STEP2_11 0xB0 +#define RF_AGCTHRESH2_STEP2_12 0xC0 +#define RF_AGCTHRESH2_STEP2_13 0xD0 +#define RF_AGCTHRESH2_STEP2_14 0xE0 +#define RF_AGCTHRESH2_STEP2_15 0xF0 -#define RF_AGCTHRESH2_STEP3_0 0x00 -#define RF_AGCTHRESH2_STEP3_1 0x01 -#define RF_AGCTHRESH2_STEP3_2 0x02 -#define RF_AGCTHRESH2_STEP3_3 0x03 -#define RF_AGCTHRESH2_STEP3_4 0x04 -#define RF_AGCTHRESH2_STEP3_5 0x05 -#define RF_AGCTHRESH2_STEP3_6 0x06 -#define RF_AGCTHRESH2_STEP3_7 0x07 -#define RF_AGCTHRESH2_STEP3_8 0x08 -#define RF_AGCTHRESH2_STEP3_9 0x09 -#define RF_AGCTHRESH2_STEP3_10 0x0A -#define RF_AGCTHRESH2_STEP3_11 0x0B // Default -#define RF_AGCTHRESH2_STEP3_12 0x0C -#define RF_AGCTHRESH2_STEP3_13 0x0D -#define RF_AGCTHRESH2_STEP3_14 0x0E -#define RF_AGCTHRESH2_STEP3_15 0x0F +#define RF_AGCTHRESH2_STEP3_0 0x00 +#define RF_AGCTHRESH2_STEP3_1 0x01 +#define RF_AGCTHRESH2_STEP3_2 0x02 +#define RF_AGCTHRESH2_STEP3_3 0x03 +#define RF_AGCTHRESH2_STEP3_4 0x04 +#define RF_AGCTHRESH2_STEP3_5 0x05 +#define RF_AGCTHRESH2_STEP3_6 0x06 +#define RF_AGCTHRESH2_STEP3_7 0x07 +#define RF_AGCTHRESH2_STEP3_8 0x08 +#define RF_AGCTHRESH2_STEP3_9 0x09 +#define RF_AGCTHRESH2_STEP3_10 0x0A +#define RF_AGCTHRESH2_STEP3_11 0x0B // Default +#define RF_AGCTHRESH2_STEP3_12 0x0C +#define RF_AGCTHRESH2_STEP3_13 0x0D +#define RF_AGCTHRESH2_STEP3_14 0x0E +#define RF_AGCTHRESH2_STEP3_15 0x0F -// RegAgcThresh3 -#define RF_AGCTHRESH3_STEP4_0 0x00 -#define RF_AGCTHRESH3_STEP4_1 0x10 -#define RF_AGCTHRESH3_STEP4_2 0x20 -#define RF_AGCTHRESH3_STEP4_3 0x30 -#define RF_AGCTHRESH3_STEP4_4 0x40 -#define RF_AGCTHRESH3_STEP4_5 0x50 -#define RF_AGCTHRESH3_STEP4_6 0x60 -#define RF_AGCTHRESH3_STEP4_7 0x70 -#define RF_AGCTHRESH3_STEP4_8 0x80 -#define RF_AGCTHRESH3_STEP4_9 0x90 // Default -#define RF_AGCTHRESH3_STEP4_10 0xA0 -#define RF_AGCTHRESH3_STEP4_11 0xB0 -#define RF_AGCTHRESH3_STEP4_12 0xC0 -#define RF_AGCTHRESH3_STEP4_13 0xD0 -#define RF_AGCTHRESH3_STEP4_14 0xE0 -#define RF_AGCTHRESH3_STEP4_15 0xF0 +// RegAgcThresh3 - not present on RFM69/SX1231 +#define RF_AGCTHRESH3_STEP4_0 0x00 +#define RF_AGCTHRESH3_STEP4_1 0x10 +#define RF_AGCTHRESH3_STEP4_2 0x20 +#define RF_AGCTHRESH3_STEP4_3 0x30 +#define RF_AGCTHRESH3_STEP4_4 0x40 +#define RF_AGCTHRESH3_STEP4_5 0x50 +#define RF_AGCTHRESH3_STEP4_6 0x60 +#define RF_AGCTHRESH3_STEP4_7 0x70 +#define RF_AGCTHRESH3_STEP4_8 0x80 +#define RF_AGCTHRESH3_STEP4_9 0x90 // Default +#define RF_AGCTHRESH3_STEP4_10 0xA0 +#define RF_AGCTHRESH3_STEP4_11 0xB0 +#define RF_AGCTHRESH3_STEP4_12 0xC0 +#define RF_AGCTHRESH3_STEP4_13 0xD0 +#define RF_AGCTHRESH3_STEP4_14 0xE0 +#define RF_AGCTHRESH3_STEP4_15 0xF0 -#define RF_AGCTHRESH3_STEP5_0 0x00 -#define RF_AGCTHRESH3_STEP5_1 0x01 -#define RF_AGCTHRESH3_STEP5_2 0x02 -#define RF_AGCTHRESH3_STEP5_3 0x03 -#define RF_AGCTHRESH3_STEP5_4 0x04 -#define RF_AGCTHRESH3_STEP5_5 0x05 -#define RF_AGCTHRESH3_STEP5_6 0x06 -#define RF_AGCTHRESH3_STEP5_7 0x07 -#define RF_AGCTHRES33_STEP5_8 0x08 -#define RF_AGCTHRESH3_STEP5_9 0x09 -#define RF_AGCTHRESH3_STEP5_10 0x0A -#define RF_AGCTHRESH3_STEP5_11 0x0B // Default -#define RF_AGCTHRESH3_STEP5_12 0x0C -#define RF_AGCTHRESH3_STEP5_13 0x0D -#define RF_AGCTHRESH3_STEP5_14 0x0E -#define RF_AGCTHRESH3_STEP5_15 0x0F +#define RF_AGCTHRESH3_STEP5_0 0x00 +#define RF_AGCTHRESH3_STEP5_1 0x01 +#define RF_AGCTHRESH3_STEP5_2 0x02 +#define RF_AGCTHRESH3_STEP5_3 0x03 +#define RF_AGCTHRESH3_STEP5_4 0x04 +#define RF_AGCTHRESH3_STEP5_5 0x05 +#define RF_AGCTHRESH3_STEP5_6 0x06 +#define RF_AGCTHRESH3_STEP5_7 0x07 +#define RF_AGCTHRES33_STEP5_8 0x08 +#define RF_AGCTHRESH3_STEP5_9 0x09 +#define RF_AGCTHRESH3_STEP5_10 0x0A +#define RF_AGCTHRESH3_STEP5_11 0x0B // Default +#define RF_AGCTHRESH3_STEP5_12 0x0C +#define RF_AGCTHRESH3_STEP5_13 0x0D +#define RF_AGCTHRESH3_STEP5_14 0x0E +#define RF_AGCTHRESH3_STEP5_15 0x0F // RegLna -#define RF_LNA_ZIN_50 0x00 -#define RF_LNA_ZIN_200 0x80 // Default +#define RF_LNA_ZIN_50 0x00 // Reset value +#define RF_LNA_ZIN_200 0x80 // Recommended default -#define RF_LNA_LOWPOWER_OFF 0x00 // Default -#define RF_LNA_LOWPOWER_ON 0x40 +#define RF_LNA_LOWPOWER_OFF 0x00 // Default +#define RF_LNA_LOWPOWER_ON 0x40 -#define RF_LNA_CURRENTGAIN 0x08 +#define RF_LNA_CURRENTGAIN 0x08 -#define RF_LNA_GAINSELECT_AUTO 0x00 // Default -#define RF_LNA_GAINSELECT_MAX 0x01 -#define RF_LNA_GAINSELECT_MAXMINUS6 0x02 -#define RF_LNA_GAINSELECT_MAXMINUS12 0x03 -#define RF_LNA_GAINSELECT_MAXMINUS24 0x04 -#define RF_LNA_GAINSELECT_MAXMINUS36 0x05 -#define RF_LNA_GAINSELECT_MAXMINUS48 0x06 +#define RF_LNA_GAINSELECT_AUTO 0x00 // Default +#define RF_LNA_GAINSELECT_MAX 0x01 +#define RF_LNA_GAINSELECT_MAXMINUS6 0x02 +#define RF_LNA_GAINSELECT_MAXMINUS12 0x03 +#define RF_LNA_GAINSELECT_MAXMINUS24 0x04 +#define RF_LNA_GAINSELECT_MAXMINUS36 0x05 +#define RF_LNA_GAINSELECT_MAXMINUS48 0x06 // RegRxBw -#define RF_RXBW_DCCFREQ_000 0x00 -#define RF_RXBW_DCCFREQ_001 0x20 -#define RF_RXBW_DCCFREQ_010 0x40 // Default -#define RF_RXBW_DCCFREQ_011 0x60 -#define RF_RXBW_DCCFREQ_100 0x80 -#define RF_RXBW_DCCFREQ_101 0xA0 -#define RF_RXBW_DCCFREQ_110 0xC0 -#define RF_RXBW_DCCFREQ_111 0xE0 +#define RF_RXBW_DCCFREQ_000 0x00 +#define RF_RXBW_DCCFREQ_001 0x20 +#define RF_RXBW_DCCFREQ_010 0x40 // Recommended default +#define RF_RXBW_DCCFREQ_011 0x60 +#define RF_RXBW_DCCFREQ_100 0x80 // Reset value +#define RF_RXBW_DCCFREQ_101 0xA0 +#define RF_RXBW_DCCFREQ_110 0xC0 +#define RF_RXBW_DCCFREQ_111 0xE0 -#define RF_RXBW_MANT_16 0x00 -#define RF_RXBW_MANT_20 0x08 -#define RF_RXBW_MANT_24 0x10 // Default +#define RF_RXBW_MANT_16 0x00 // Reset value +#define RF_RXBW_MANT_20 0x08 +#define RF_RXBW_MANT_24 0x10 // Recommended default -#define RF_RXBW_EXP_0 0x00 -#define RF_RXBW_EXP_1 0x01 -#define RF_RXBW_EXP_2 0x02 -#define RF_RXBW_EXP_3 0x03 -#define RF_RXBW_EXP_4 0x04 -#define RF_RXBW_EXP_5 0x05 // Default -#define RF_RXBW_EXP_6 0x06 -#define RF_RXBW_EXP_7 0x07 +#define RF_RXBW_EXP_0 0x00 +#define RF_RXBW_EXP_1 0x01 +#define RF_RXBW_EXP_2 0x02 +#define RF_RXBW_EXP_3 0x03 +#define RF_RXBW_EXP_4 0x04 +#define RF_RXBW_EXP_5 0x05 // Recommended default +#define RF_RXBW_EXP_6 0x06 // Reset value +#define RF_RXBW_EXP_7 0x07 // RegAfcBw -#define RF_AFCBW_DCCFREQAFC_000 0x00 -#define RF_AFCBW_DCCFREQAFC_001 0x20 -#define RF_AFCBW_DCCFREQAFC_010 0x40 -#define RF_AFCBW_DCCFREQAFC_011 0x60 -#define RF_AFCBW_DCCFREQAFC_100 0x80 // Default -#define RF_AFCBW_DCCFREQAFC_101 0xA0 -#define RF_AFCBW_DCCFREQAFC_110 0xC0 -#define RF_AFCBW_DCCFREQAFC_111 0xE0 +#define RF_AFCBW_DCCFREQAFC_000 0x00 +#define RF_AFCBW_DCCFREQAFC_001 0x20 +#define RF_AFCBW_DCCFREQAFC_010 0x40 +#define RF_AFCBW_DCCFREQAFC_011 0x60 +#define RF_AFCBW_DCCFREQAFC_100 0x80 // Default +#define RF_AFCBW_DCCFREQAFC_101 0xA0 +#define RF_AFCBW_DCCFREQAFC_110 0xC0 +#define RF_AFCBW_DCCFREQAFC_111 0xE0 -#define RF_AFCBW_MANTAFC_16 0x00 -#define RF_AFCBW_MANTAFC_20 0x08 // Default -#define RF_AFCBW_MANTAFC_24 0x10 +#define RF_AFCBW_MANTAFC_16 0x00 +#define RF_AFCBW_MANTAFC_20 0x08 // Default +#define RF_AFCBW_MANTAFC_24 0x10 -#define RF_AFCBW_EXPAFC_0 0x00 -#define RF_AFCBW_EXPAFC_1 0x01 -#define RF_AFCBW_EXPAFC_2 0x02 -#define RF_AFCBW_EXPAFC_3 0x03 // Default -#define RF_AFCBW_EXPAFC_4 0x04 -#define RF_AFCBW_EXPAFC_5 0x05 -#define RF_AFCBW_EXPAFC_6 0x06 -#define RF_AFCBW_EXPAFC_7 0x07 +#define RF_AFCBW_EXPAFC_0 0x00 +#define RF_AFCBW_EXPAFC_1 0x01 +#define RF_AFCBW_EXPAFC_2 0x02 // Reset value +#define RF_AFCBW_EXPAFC_3 0x03 // Recommended default +#define RF_AFCBW_EXPAFC_4 0x04 +#define RF_AFCBW_EXPAFC_5 0x05 +#define RF_AFCBW_EXPAFC_6 0x06 +#define RF_AFCBW_EXPAFC_7 0x07 // RegOokPeak -#define RF_OOKPEAK_THRESHTYPE_FIXED 0x00 -#define RF_OOKPEAK_THRESHTYPE_PEAK 0x40 // Default -#define RF_OOKPEAK_THRESHTYPE_AVERAGE 0x80 +#define RF_OOKPEAK_THRESHTYPE_FIXED 0x00 +#define RF_OOKPEAK_THRESHTYPE_PEAK 0x40 // Default +#define RF_OOKPEAK_THRESHTYPE_AVERAGE 0x80 -#define RF_OOKPEAK_PEAKTHRESHSTEP_000 0x00 // Default -#define RF_OOKPEAK_PEAKTHRESHSTEP_001 0x08 -#define RF_OOKPEAK_PEAKTHRESHSTEP_010 0x10 -#define RF_OOKPEAK_PEAKTHRESHSTEP_011 0x18 -#define RF_OOKPEAK_PEAKTHRESHSTEP_100 0x20 -#define RF_OOKPEAK_PEAKTHRESHSTEP_101 0x28 -#define RF_OOKPEAK_PEAKTHRESHSTEP_110 0x30 -#define RF_OOKPEAK_PEAKTHRESHSTEP_111 0x38 +#define RF_OOKPEAK_PEAKTHRESHSTEP_000 0x00 // Default +#define RF_OOKPEAK_PEAKTHRESHSTEP_001 0x08 +#define RF_OOKPEAK_PEAKTHRESHSTEP_010 0x10 +#define RF_OOKPEAK_PEAKTHRESHSTEP_011 0x18 +#define RF_OOKPEAK_PEAKTHRESHSTEP_100 0x20 +#define RF_OOKPEAK_PEAKTHRESHSTEP_101 0x28 +#define RF_OOKPEAK_PEAKTHRESHSTEP_110 0x30 +#define RF_OOKPEAK_PEAKTHRESHSTEP_111 0x38 -#define RF_OOKPEAK_PEAKTHRESHDEC_000 0x00 // Default -#define RF_OOKPEAK_PEAKTHRESHDEC_001 0x01 -#define RF_OOKPEAK_PEAKTHRESHDEC_010 0x02 -#define RF_OOKPEAK_PEAKTHRESHDEC_011 0x03 -#define RF_OOKPEAK_PEAKTHRESHDEC_100 0x04 -#define RF_OOKPEAK_PEAKTHRESHDEC_101 0x05 -#define RF_OOKPEAK_PEAKTHRESHDEC_110 0x06 -#define RF_OOKPEAK_PEAKTHRESHDEC_111 0x07 +#define RF_OOKPEAK_PEAKTHRESHDEC_000 0x00 // Default +#define RF_OOKPEAK_PEAKTHRESHDEC_001 0x01 +#define RF_OOKPEAK_PEAKTHRESHDEC_010 0x02 +#define RF_OOKPEAK_PEAKTHRESHDEC_011 0x03 +#define RF_OOKPEAK_PEAKTHRESHDEC_100 0x04 +#define RF_OOKPEAK_PEAKTHRESHDEC_101 0x05 +#define RF_OOKPEAK_PEAKTHRESHDEC_110 0x06 +#define RF_OOKPEAK_PEAKTHRESHDEC_111 0x07 // RegOokAvg -#define RF_OOKAVG_AVERAGETHRESHFILT_00 0x00 -#define RF_OOKAVG_AVERAGETHRESHFILT_01 0x40 -#define RF_OOKAVG_AVERAGETHRESHFILT_10 0x80 // Default -#define RF_OOKAVG_AVERAGETHRESHFILT_11 0xC0 +#define RF_OOKAVG_AVERAGETHRESHFILT_00 0x00 +#define RF_OOKAVG_AVERAGETHRESHFILT_01 0x40 +#define RF_OOKAVG_AVERAGETHRESHFILT_10 0x80 // Default +#define RF_OOKAVG_AVERAGETHRESHFILT_11 0xC0 // RegOokFix -#define RF_OOKFIX_FIXEDTHRESH_VALUE 0x06 // Default +#define RF_OOKFIX_FIXEDTHRESH_VALUE 0x06 // Default // RegAfcFei -#define RF_AFCFEI_FEI_DONE 0x40 -#define RF_AFCFEI_FEI_START 0x20 -#define RF_AFCFEI_AFC_DONE 0x10 -#define RF_AFCFEI_AFCAUTOCLEAR_ON 0x08 -#define RF_AFCFEI_AFCAUTOCLEAR_OFF 0x00 // Default +#define RF_AFCFEI_FEI_DONE 0x40 +#define RF_AFCFEI_FEI_START 0x20 +#define RF_AFCFEI_AFC_DONE 0x10 +#define RF_AFCFEI_AFCAUTOCLEAR_ON 0x08 +#define RF_AFCFEI_AFCAUTOCLEAR_OFF 0x00 // Default -#define RF_AFCFEI_AFCAUTO_ON 0x04 -#define RF_AFCFEI_AFCAUTO_OFF 0x00 // Default +#define RF_AFCFEI_AFCAUTO_ON 0x04 +#define RF_AFCFEI_AFCAUTO_OFF 0x00 // Default + +#define RF_AFCFEI_AFC_CLEAR 0x02 +#define RF_AFCFEI_AFC_START 0x01 -#define RF_AFCFEI_AFC_CLEAR 0x02 -#define RF_AFCFEI_AFC_START 0x01 // RegRssiConfig -#define RF_RSSI_FASTRX_ON 0x08 -#define RF_RSSI_FASTRX_OFF 0x00 // Default -#define RF_RSSI_DONE 0x02 -#define RF_RSSI_START 0x01 +#define RF_RSSI_FASTRX_ON 0x08 // not present on RFM69/SX1231 +#define RF_RSSI_FASTRX_OFF 0x00 // Default + +#define RF_RSSI_DONE 0x02 +#define RF_RSSI_START 0x01 // RegDioMapping1 -#define RF_DIOMAPPING1_DIO0_00 0x00 // Default -#define RF_DIOMAPPING1_DIO0_01 0x40 -#define RF_DIOMAPPING1_DIO0_10 0x80 -#define RF_DIOMAPPING1_DIO0_11 0xC0 +#define RF_DIOMAPPING1_DIO0_00 0x00 // Default +#define RF_DIOMAPPING1_DIO0_01 0x40 +#define RF_DIOMAPPING1_DIO0_10 0x80 +#define RF_DIOMAPPING1_DIO0_11 0xC0 -#define RF_DIOMAPPING1_DIO1_00 0x00 // Default -#define RF_DIOMAPPING1_DIO1_01 0x10 -#define RF_DIOMAPPING1_DIO1_10 0x20 -#define RF_DIOMAPPING1_DIO1_11 0x30 +#define RF_DIOMAPPING1_DIO1_00 0x00 // Default +#define RF_DIOMAPPING1_DIO1_01 0x10 +#define RF_DIOMAPPING1_DIO1_10 0x20 +#define RF_DIOMAPPING1_DIO1_11 0x30 -#define RF_DIOMAPPING1_DIO2_00 0x00 // Default -#define RF_DIOMAPPING1_DIO2_01 0x04 -#define RF_DIOMAPPING1_DIO2_10 0x08 -#define RF_DIOMAPPING1_DIO2_11 0x0C +#define RF_DIOMAPPING1_DIO2_00 0x00 // Default +#define RF_DIOMAPPING1_DIO2_01 0x04 +#define RF_DIOMAPPING1_DIO2_10 0x08 +#define RF_DIOMAPPING1_DIO2_11 0x0C -#define RF_DIOMAPPING1_DIO3_00 0x00 // Default -#define RF_DIOMAPPING1_DIO3_01 0x01 -#define RF_DIOMAPPING1_DIO3_10 0x02 -#define RF_DIOMAPPING1_DIO3_11 0x03 +#define RF_DIOMAPPING1_DIO3_00 0x00 // Default +#define RF_DIOMAPPING1_DIO3_01 0x01 +#define RF_DIOMAPPING1_DIO3_10 0x02 +#define RF_DIOMAPPING1_DIO3_11 0x03 // RegDioMapping2 -#define RF_DIOMAPPING2_DIO4_00 0x00 // Default -#define RF_DIOMAPPING2_DIO4_01 0x40 -#define RF_DIOMAPPING2_DIO4_10 0x80 -#define RF_DIOMAPPING2_DIO4_11 0xC0 +#define RF_DIOMAPPING2_DIO4_00 0x00 // Default +#define RF_DIOMAPPING2_DIO4_01 0x40 +#define RF_DIOMAPPING2_DIO4_10 0x80 +#define RF_DIOMAPPING2_DIO4_11 0xC0 -#define RF_DIOMAPPING2_DIO5_00 0x00 // Default -#define RF_DIOMAPPING2_DIO5_01 0x10 -#define RF_DIOMAPPING2_DIO5_10 0x20 -#define RF_DIOMAPPING2_DIO5_11 0x30 +#define RF_DIOMAPPING2_DIO5_00 0x00 // Default +#define RF_DIOMAPPING2_DIO5_01 0x10 +#define RF_DIOMAPPING2_DIO5_10 0x20 +#define RF_DIOMAPPING2_DIO5_11 0x30 -#define RF_DIOMAPPING2_CLKOUT_32 0x00 -#define RF_DIOMAPPING2_CLKOUT_16 0x01 -#define RF_DIOMAPPING2_CLKOUT_8 0x02 -#define RF_DIOMAPPING2_CLKOUT_4 0x03 -#define RF_DIOMAPPING2_CLKOUT_2 0x04 -#define RF_DIOMAPPING2_CLKOUT_1 0x05 -#define RF_DIOMAPPING2_CLKOUT_RC 0x06 -#define RF_DIOMAPPING2_CLKOUT_OFF 0x07 // Default +#define RF_DIOMAPPING2_CLKOUT_32 0x00 +#define RF_DIOMAPPING2_CLKOUT_16 0x01 +#define RF_DIOMAPPING2_CLKOUT_8 0x02 +#define RF_DIOMAPPING2_CLKOUT_4 0x03 +#define RF_DIOMAPPING2_CLKOUT_2 0x04 +#define RF_DIOMAPPING2_CLKOUT_1 0x05 // Reset value +#define RF_DIOMAPPING2_CLKOUT_RC 0x06 +#define RF_DIOMAPPING2_CLKOUT_OFF 0x07 // Recommended default // RegIrqFlags1 -#define RF_IRQFLAGS1_MODEREADY 0x80 -#define RF_IRQFLAGS1_RXREADY 0x40 -#define RF_IRQFLAGS1_TXREADY 0x20 -#define RF_IRQFLAGS1_PLLLOCK 0x10 -#define RF_IRQFLAGS1_RSSI 0x08 -#define RF_IRQFLAGS1_TIMEOUT 0x04 -#define RF_IRQFLAGS1_AUTOMODE 0x02 -#define RF_IRQFLAGS1_SYNCADDRESSMATCH 0x01 +#define RF_IRQFLAGS1_MODEREADY 0x80 +#define RF_IRQFLAGS1_RXREADY 0x40 +#define RF_IRQFLAGS1_TXREADY 0x20 +#define RF_IRQFLAGS1_PLLLOCK 0x10 +#define RF_IRQFLAGS1_RSSI 0x08 +#define RF_IRQFLAGS1_TIMEOUT 0x04 +#define RF_IRQFLAGS1_AUTOMODE 0x02 +#define RF_IRQFLAGS1_SYNCADDRESSMATCH 0x01 + // RegIrqFlags2 -#define RF_IRQFLAGS2_FIFOFULL 0x80 -#define RF_IRQFLAGS2_FIFONOTEMPTY 0x40 -#define RF_IRQFLAGS2_FIFOLEVEL 0x20 -#define RF_IRQFLAGS2_FIFOOVERRUN 0x10 -#define RF_IRQFLAGS2_PACKETSENT 0x08 -#define RF_IRQFLAGS2_PAYLOADREADY 0x04 -#define RF_IRQFLAGS2_CRCOK 0x02 -#define RF_IRQFLAGS2_LOWBAT 0x01 +#define RF_IRQFLAGS2_FIFOFULL 0x80 +#define RF_IRQFLAGS2_FIFONOTEMPTY 0x40 +#define RF_IRQFLAGS2_FIFOLEVEL 0x20 +#define RF_IRQFLAGS2_FIFOOVERRUN 0x10 +#define RF_IRQFLAGS2_PACKETSENT 0x08 +#define RF_IRQFLAGS2_PAYLOADREADY 0x04 +#define RF_IRQFLAGS2_CRCOK 0x02 +#define RF_IRQFLAGS2_LOWBAT 0x01 // not present on RFM69/SX1231 + // RegRssiThresh -#define RF_RSSITHRESH_VALUE 0xE4 // Default +#define RF_RSSITHRESH_VALUE 0xE4 // Default + // RegRxTimeout1 -#define RF_RXTIMEOUT1_RXSTART_VALUE 0x00 // Default +#define RF_RXTIMEOUT1_RXSTART_VALUE 0x00 // Default + // RegRxTimeout2 -#define RF_RXTIMEOUT2_RSSITHRESH_VALUE 0x00 // Default +#define RF_RXTIMEOUT2_RSSITHRESH_VALUE 0x00 // Default + // RegPreamble -#define RF_PREAMBLESIZE_MSB_VALUE 0x00 // Default -#define RF_PREAMBLESIZE_LSB_VALUE 0x03 // Default +#define RF_PREAMBLESIZE_MSB_VALUE 0x00 // Default +#define RF_PREAMBLESIZE_LSB_VALUE 0x03 // Default // RegSyncConfig -#define RF_SYNC_ON 0x80 // Default -#define RF_SYNC_OFF 0x00 +#define RF_SYNC_ON 0x80 // Default +#define RF_SYNC_OFF 0x00 -#define RF_SYNC_FIFOFILL_AUTO 0x00 // Default -- when sync interrupt occurs -#define RF_SYNC_FIFOFILL_MANUAL 0x40 +#define RF_SYNC_FIFOFILL_AUTO 0x00 // Default -- when sync interrupt occurs +#define RF_SYNC_FIFOFILL_MANUAL 0x40 -#define RF_SYNC_SIZE_1 0x00 -#define RF_SYNC_SIZE_2 0x08 -#define RF_SYNC_SIZE_3 0x10 -#define RF_SYNC_SIZE_4 0x18 // Default -#define RF_SYNC_SIZE_5 0x20 -#define RF_SYNC_SIZE_6 0x28 -#define RF_SYNC_SIZE_7 0x30 -#define RF_SYNC_SIZE_8 0x38 +#define RF_SYNC_SIZE_1 0x00 +#define RF_SYNC_SIZE_2 0x08 +#define RF_SYNC_SIZE_3 0x10 +#define RF_SYNC_SIZE_4 0x18 // Default +#define RF_SYNC_SIZE_5 0x20 +#define RF_SYNC_SIZE_6 0x28 +#define RF_SYNC_SIZE_7 0x30 +#define RF_SYNC_SIZE_8 0x38 -#define RF_SYNC_TOL_0 0x00 // Default -#define RF_SYNC_TOL_1 0x01 -#define RF_SYNC_TOL_2 0x02 -#define RF_SYNC_TOL_3 0x03 -#define RF_SYNC_TOL_4 0x04 -#define RF_SYNC_TOL_5 0x05 -#define RF_SYNC_TOL_6 0x06 -#define RF_SYNC_TOL_7 0x07 +#define RF_SYNC_TOL_0 0x00 // Default +#define RF_SYNC_TOL_1 0x01 +#define RF_SYNC_TOL_2 0x02 +#define RF_SYNC_TOL_3 0x03 +#define RF_SYNC_TOL_4 0x04 +#define RF_SYNC_TOL_5 0x05 +#define RF_SYNC_TOL_6 0x06 +#define RF_SYNC_TOL_7 0x07 // RegSyncValue1-8 -#define RF_SYNC_BYTE1_VALUE 0x00 // Default -#define RF_SYNC_BYTE2_VALUE 0x00 // Default -#define RF_SYNC_BYTE3_VALUE 0x00 // Default -#define RF_SYNC_BYTE4_VALUE 0x00 // Default -#define RF_SYNC_BYTE5_VALUE 0x00 // Default -#define RF_SYNC_BYTE6_VALUE 0x00 // Default -#define RF_SYNC_BYTE7_VALUE 0x00 // Default -#define RF_SYNC_BYTE8_VALUE 0x00 // Default +#define RF_SYNC_BYTE1_VALUE 0x00 // Default +#define RF_SYNC_BYTE2_VALUE 0x00 // Default +#define RF_SYNC_BYTE3_VALUE 0x00 // Default +#define RF_SYNC_BYTE4_VALUE 0x00 // Default +#define RF_SYNC_BYTE5_VALUE 0x00 // Default +#define RF_SYNC_BYTE6_VALUE 0x00 // Default +#define RF_SYNC_BYTE7_VALUE 0x00 // Default +#define RF_SYNC_BYTE8_VALUE 0x00 // Default // RegPacketConfig1 -#define RF_PACKET1_FORMAT_FIXED 0x00 // Default -#define RF_PACKET1_FORMAT_VARIABLE 0x80 +#define RF_PACKET1_FORMAT_FIXED 0x00 // Default +#define RF_PACKET1_FORMAT_VARIABLE 0x80 -#define RF_PACKET1_DCFREE_OFF 0x00 // Default -#define RF_PACKET1_DCFREE_MANCHESTER 0x20 -#define RF_PACKET1_DCFREE_WHITENING 0x40 +#define RF_PACKET1_DCFREE_OFF 0x00 // Default +#define RF_PACKET1_DCFREE_MANCHESTER 0x20 +#define RF_PACKET1_DCFREE_WHITENING 0x40 -#define RF_PACKET1_CRC_ON 0x10 // Default -#define RF_PACKET1_CRC_OFF 0x00 +#define RF_PACKET1_CRC_ON 0x10 // Default +#define RF_PACKET1_CRC_OFF 0x00 -#define RF_PACKET1_CRCAUTOCLEAR_ON 0x00 // Default -#define RF_PACKET1_CRCAUTOCLEAR_OFF 0x08 +#define RF_PACKET1_CRCAUTOCLEAR_ON 0x00 // Default +#define RF_PACKET1_CRCAUTOCLEAR_OFF 0x08 -#define RF_PACKET1_ADRSFILTERING_OFF 0x00 // Default -#define RF_PACKET1_ADRSFILTERING_NODE 0x02 -#define RF_PACKET1_ADRSFILTERING_NODEBROADCAST 0x04 +#define RF_PACKET1_ADRSFILTERING_OFF 0x00 // Default +#define RF_PACKET1_ADRSFILTERING_NODE 0x02 +#define RF_PACKET1_ADRSFILTERING_NODEBROADCAST 0x04 // RegPayloadLength -#define RF_PAYLOADLENGTH_VALUE 0x40 // Default +#define RF_PAYLOADLENGTH_VALUE 0x40 // Default + // RegBroadcastAdrs -#define RF_BROADCASTADDRESS_VALUE 0x00 +#define RF_BROADCASTADDRESS_VALUE 0x00 // RegAutoModes -#define RF_AUTOMODES_ENTER_OFF 0x00 // Default -#define RF_AUTOMODES_ENTER_FIFONOTEMPTY 0x20 -#define RF_AUTOMODES_ENTER_FIFOLEVEL 0x40 -#define RF_AUTOMODES_ENTER_CRCOK 0x60 -#define RF_AUTOMODES_ENTER_PAYLOADREADY 0x80 -#define RF_AUTOMODES_ENTER_SYNCADRSMATCH 0xA0 -#define RF_AUTOMODES_ENTER_PACKETSENT 0xC0 -#define RF_AUTOMODES_ENTER_FIFOEMPTY 0xE0 +#define RF_AUTOMODES_ENTER_OFF 0x00 // Default +#define RF_AUTOMODES_ENTER_FIFONOTEMPTY 0x20 +#define RF_AUTOMODES_ENTER_FIFOLEVEL 0x40 +#define RF_AUTOMODES_ENTER_CRCOK 0x60 +#define RF_AUTOMODES_ENTER_PAYLOADREADY 0x80 +#define RF_AUTOMODES_ENTER_SYNCADRSMATCH 0xA0 +#define RF_AUTOMODES_ENTER_PACKETSENT 0xC0 +#define RF_AUTOMODES_ENTER_FIFOEMPTY 0xE0 -#define RF_AUTOMODES_EXIT_OFF 0x00 // Default -#define RF_AUTOMODES_EXIT_FIFOEMPTY 0x04 -#define RF_AUTOMODES_EXIT_FIFOLEVEL 0x08 -#define RF_AUTOMODES_EXIT_CRCOK 0x0C -#define RF_AUTOMODES_EXIT_PAYLOADREADY 0x10 -#define RF_AUTOMODES_EXIT_SYNCADRSMATCH 0x14 -#define RF_AUTOMODES_EXIT_PACKETSENT 0x18 -#define RF_AUTOMODES_EXIT_RXTIMEOUT 0x1C +#define RF_AUTOMODES_EXIT_OFF 0x00 // Default +#define RF_AUTOMODES_EXIT_FIFOEMPTY 0x04 +#define RF_AUTOMODES_EXIT_FIFOLEVEL 0x08 +#define RF_AUTOMODES_EXIT_CRCOK 0x0C +#define RF_AUTOMODES_EXIT_PAYLOADREADY 0x10 +#define RF_AUTOMODES_EXIT_SYNCADRSMATCH 0x14 +#define RF_AUTOMODES_EXIT_PACKETSENT 0x18 +#define RF_AUTOMODES_EXIT_RXTIMEOUT 0x1C -#define RF_AUTOMODES_INTERMEDIATE_SLEEP 0x00 // Default -#define RF_AUTOMODES_INTERMEDIATE_STANDBY 0x01 -#define RF_AUTOMODES_INTERMEDIATE_RECEIVER 0x02 -#define RF_AUTOMODES_INTERMEDIATE_TRANSMITTER 0x03 +#define RF_AUTOMODES_INTERMEDIATE_SLEEP 0x00 // Default +#define RF_AUTOMODES_INTERMEDIATE_STANDBY 0x01 +#define RF_AUTOMODES_INTERMEDIATE_RECEIVER 0x02 +#define RF_AUTOMODES_INTERMEDIATE_TRANSMITTER 0x03 // RegFifoThresh -#define RF_FIFOTHRESH_TXSTART_FIFOTHRESH 0x00 -#define RF_FIFOTHRESH_TXSTART_FIFONOTEMPTY 0x80 // Default +#define RF_FIFOTHRESH_TXSTART_FIFOTHRESH 0x00 // Reset value +#define RF_FIFOTHRESH_TXSTART_FIFONOTEMPTY 0x80 // Recommended default -#define RF_FIFOTHRESH_VALUE 0x0F // Default +#define RF_FIFOTHRESH_VALUE 0x0F // Default // RegPacketConfig2 -#define RF_PACKET2_RXRESTARTDELAY_1BIT 0x00 // Default -#define RF_PACKET2_RXRESTARTDELAY_2BITS 0x10 -#define RF_PACKET2_RXRESTARTDELAY_4BITS 0x20 -#define RF_PACKET2_RXRESTARTDELAY_8BITS 0x30 -#define RF_PACKET2_RXRESTARTDELAY_16BITS 0x40 -#define RF_PACKET2_RXRESTARTDELAY_32BITS 0x50 -#define RF_PACKET2_RXRESTARTDELAY_64BITS 0x60 -#define RF_PACKET2_RXRESTARTDELAY_128BITS 0x70 -#define RF_PACKET2_RXRESTARTDELAY_256BITS 0x80 -#define RF_PACKET2_RXRESTARTDELAY_512BITS 0x90 -#define RF_PACKET2_RXRESTARTDELAY_1024BITS 0xA0 -#define RF_PACKET2_RXRESTARTDELAY_2048BITS 0xB0 -#define RF_PACKET2_RXRESTARTDELAY_NONE 0xC0 -#define RF_PACKET2_RXRESTART 0x04 +#define RF_PACKET2_RXRESTARTDELAY_1BIT 0x00 // Default +#define RF_PACKET2_RXRESTARTDELAY_2BITS 0x10 +#define RF_PACKET2_RXRESTARTDELAY_4BITS 0x20 +#define RF_PACKET2_RXRESTARTDELAY_8BITS 0x30 +#define RF_PACKET2_RXRESTARTDELAY_16BITS 0x40 +#define RF_PACKET2_RXRESTARTDELAY_32BITS 0x50 +#define RF_PACKET2_RXRESTARTDELAY_64BITS 0x60 +#define RF_PACKET2_RXRESTARTDELAY_128BITS 0x70 +#define RF_PACKET2_RXRESTARTDELAY_256BITS 0x80 +#define RF_PACKET2_RXRESTARTDELAY_512BITS 0x90 +#define RF_PACKET2_RXRESTARTDELAY_1024BITS 0xA0 +#define RF_PACKET2_RXRESTARTDELAY_2048BITS 0xB0 +#define RF_PACKET2_RXRESTARTDELAY_NONE 0xC0 +#define RF_PACKET2_RXRESTART 0x04 -#define RF_PACKET2_AUTORXRESTART_ON 0x02 // Default -#define RF_PACKET2_AUTORXRESTART_OFF 0x00 +#define RF_PACKET2_AUTORXRESTART_ON 0x02 // Default +#define RF_PACKET2_AUTORXRESTART_OFF 0x00 -#define RF_PACKET2_AES_ON 0x01 -#define RF_PACKET2_AES_OFF 0x00 // Default +#define RF_PACKET2_AES_ON 0x01 +#define RF_PACKET2_AES_OFF 0x00 // Default // RegAesKey1-16 -#define RF_AESKEY1_VALUE 0x00 // Default -#define RF_AESKEY2_VALUE 0x00 // Default -#define RF_AESKEY3_VALUE 0x00 // Default -#define RF_AESKEY4_VALUE 0x00 // Default -#define RF_AESKEY5_VALUE 0x00 // Default -#define RF_AESKEY6_VALUE 0x00 // Default -#define RF_AESKEY7_VALUE 0x00 // Default -#define RF_AESKEY8_VALUE 0x00 // Default -#define RF_AESKEY9_VALUE 0x00 // Default -#define RF_AESKEY10_VALUE 0x00 // Default -#define RF_AESKEY11_VALUE 0x00 // Default -#define RF_AESKEY12_VALUE 0x00 // Default -#define RF_AESKEY13_VALUE 0x00 // Default -#define RF_AESKEY14_VALUE 0x00 // Default -#define RF_AESKEY15_VALUE 0x00 // Default -#define RF_AESKEY16_VALUE 0x00 // Default +#define RF_AESKEY1_VALUE 0x00 // Default +#define RF_AESKEY2_VALUE 0x00 // Default +#define RF_AESKEY3_VALUE 0x00 // Default +#define RF_AESKEY4_VALUE 0x00 // Default +#define RF_AESKEY5_VALUE 0x00 // Default +#define RF_AESKEY6_VALUE 0x00 // Default +#define RF_AESKEY7_VALUE 0x00 // Default +#define RF_AESKEY8_VALUE 0x00 // Default +#define RF_AESKEY9_VALUE 0x00 // Default +#define RF_AESKEY10_VALUE 0x00 // Default +#define RF_AESKEY11_VALUE 0x00 // Default +#define RF_AESKEY12_VALUE 0x00 // Default +#define RF_AESKEY13_VALUE 0x00 // Default +#define RF_AESKEY14_VALUE 0x00 // Default +#define RF_AESKEY15_VALUE 0x00 // Default +#define RF_AESKEY16_VALUE 0x00 // Default // RegTemp1 -#define RF_TEMP1_MEAS_START 0x08 -#define RF_TEMP1_MEAS_RUNNING 0x04 -#define RF_TEMP1_ADCLOWPOWER_ON 0x01 // Default -#define RF_TEMP1_ADCLOWPOWER_OFF 0x00 +#define RF_TEMP1_MEAS_START 0x08 +#define RF_TEMP1_MEAS_RUNNING 0x04 +// not present on RFM69/SX1231 +#define RF_TEMP1_ADCLOWPOWER_ON 0x01 // Default +#define RF_TEMP1_ADCLOWPOWER_OFF 0x00 -// RegTestDagc 0x6F: demodulator config and IO mode config + +// RegTestLna +#define RF_TESTLNA_NORMAL 0x1B +#define RF_TESTLNA_HIGH_SENSITIVITY 0x2D + + +// RegTestDagc #define RF_DAGC_NORMAL 0x00 // Reset value -#define RF_DAGC_IMPROVED_LOWBETA1 0x20 // +#define RF_DAGC_IMPROVED_LOWBETA1 0x20 #define RF_DAGC_IMPROVED_LOWBETA0 0x30 // Recommended default - diff --git a/keywords.txt b/keywords.txt index c8a14a7..cda3bd4 100644 --- a/keywords.txt +++ b/keywords.txt @@ -23,15 +23,21 @@ receiveDone KEYWORD2 ACKReceived KEYWORD2 sendACK KEYWORD2 setFrequency KEYWORD2 +getFrequency KEYWORD2 encrypt KEYWORD2 setCS KEYWORD2 readRSSI KEYWORD2 promiscuous KEYWORD2 setHighPower KEYWORD2 -CryptFunction KEYWORD2 sleep KEYWORD2 readReg KEYWORD2 writeReg KEYWORD2 +setNetwork KEYWORD2 +ACKRequested KEYWORD2 +setPowerLevel KEYWORD2 +readTemperature KEYWORD2 +rcCalibration KEYWORD2 +readAllRegs KEYWORD2 ####################################### # Constants (LITERAL1) @@ -49,4 +55,5 @@ SENDERID LITERAL2 TARGETID LITERAL2 PAYLOADLEN LITERAL2 ACK_REQUESTED LITERAL2 -ACK_RECEIVED LITERAL2 \ No newline at end of file +ACK_RECEIVED LITERAL2 +RSSI LITERAL2 diff --git a/library.json b/library.json new file mode 100644 index 0000000..e01526e --- /dev/null +++ b/library.json @@ -0,0 +1,12 @@ +{ + "name": "RFM69", + "keywords": "rf, radio, wireless, spi", + "description": "RFM69 library for RFM69W, RFM69HW, RFM69CW, RFM69HCW (semtech SX1231, SX1231H)", + "repository": + { + "type": "git", + "url": "https://github.com/LowPowerLab/RFM69.git" + }, + "frameworks": "arduino", + "platforms": "atmelavr" +}