initial commit

This commit is contained in:
2026-02-23 18:35:45 +01:00
commit fa4728b922
14 changed files with 2387 additions and 0 deletions

50
.gitignore vendored Normal file
View File

@@ -0,0 +1,50 @@
# PlatformIO
.pio/
.pioenvs/
.piolibdeps/
.clang_complete
.c_cpp_properties.json
compile_commands.json
# VS Code
.vscode/
!.vscode/extensions.json
!.vscode/settings.json
# Build artifacts
build/
dist/
*.o
*.a
*.so
*.elf
*.hex
*.bin
# IDE and editors
*.swp
*.swo
*~
.DS_Store
.project
.pydevproject
.settings/
*.sublime-workspace
# Python
__pycache__/
*.py[cod]
*$py.class
*.egg-info/
*.egg
.Python
venv/
env/
# Dependencies
lib/
node_modules/
# OS files
.DS_Store
Thumbs.db

239
AP300_TOOL/AP300_TOOL.ino Normal file
View File

@@ -0,0 +1,239 @@
/*
* BruteForce, Remote sniffing and Status-Tool for Pluggit AP300
*
* If you have an "normal" nRF905 module, the distance between the nRF905 and the AP300 wireless module must be less than 1m!!!
*/
/*
* PIN config for Arduino Pro Mini to nRF905
*
* 7 -> PWR
* 8 -> CE
* 9 -> TxEN
* 2 -> CD
* 3 -> DR
* 10 -> CSN
* 12 -> MISO
* 11 -> MOSI
* 13 -> SCK
*/
#include <nRF905.h>
#include <SPI.h>
/*
* ONLY USE BRUTEFORCE OR REMOTE_SNIFFING
*/
#define BRUTEFORCE 1 // enable(1)/disable(0) bruteforce
#if BRUTEFORCE
#define TIMEOUT 250 // 250ms data timeout
#else
#define TIMEOUT 1000 // 1 secon data timeout
#endif
#define REMOTE_SNIFFING 0 // enable(1)/disable(0) remote sniffing
uint8_t payload[4][NRF905_MAX_PAYLOAD];
uint8_t plCounter;
//////////////////////////////////////////////////////////////////////////
void nRF905_Config(byte buf1[], byte buf2[])
{
// Set control register 0 - CHANNEL
nRF905_setConfigReg0(0x76);
// config reg 1
nRF905_setConfigReg1(0x0E);
// config reg 2
nRF905_setConfigReg2(0x44);
// Set payload sizes
nRF905_setPayloadSizes(0x20);
// set TX and Rx addresses
nRF905_setTXAddress(buf1);
// set Rx addres
nRF905_setRXAddress(buf2);
// read config register 9 - just to be conform with data detected by sniffing
nRF905_getConfigReg(9);
// set config register 9
nRF905_setConfigReg9(0xDB);
// Clear DR by reading receive payload
nRF905_flushRecBuffer();
}
//////////////////////////////////////////////////////////////////////////
void nRF905_Initialise(byte buf1[], byte buf2[])
{
pinMode(PWR_MODE, OUTPUT);
digitalWrite(PWR_MODE, LOW); // activate power down mode
pinMode(TRX_EN, OUTPUT);
digitalWrite(TRX_EN, LOW); // activate standby mode
pinMode(TX_EN, OUTPUT);
pinMode(CSN, OUTPUT);
pinMode(CD, INPUT);
pinMode(DR, INPUT);
digitalWrite(CSN, HIGH);
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV2);
nRF905_Config(buf1, buf2);
Serial.println(F("nRF905 configured..."));
#if NRF905_INTERRUPTS
// Set interrupts
REG_EXTERNAL_INT_CTL |= BIT_EXTERNAL_INT_CTL;
nRF905_interrupt_on();
Serial.println(F("nRF905 interrupts..."));
#endif
// leave config mode
nRF905_powerUp();
Serial.println(F("nRF905 powered up..."));
}
///////////////////////////////////////////////////////////////////
void setup()
{
byte buf1[] = {0x00, 0x00, 0x07, 0x7A}; // Address of device to send to (4 bytes) = TXADDR
byte buf2[] = {0x00, 0x00, 0x07, 0x7A}; // Address of this device (4 bytes) = RXADDR
Serial.begin(57600);
Serial.println(F("Client started"));
// Start up
nRF905_Initialise(buf1, buf2);
Serial.println(F("nRF905 initialised"));
plCounter = 0;
}
//////////////////////////////////////////////////////
nRF905_radio_state_t nRF905_getStatus(void)
{
if (!digitalRead(PWR_MODE)) return NRF905_RADIO_STATE_POWER_DOWN;
else if (!digitalRead(TRX_EN)) return NRF905_RADIO_STATE_STANDBY;
else if (!digitalRead(TX_EN)) {
if (!digitalRead(DR)) return NRF905_RADIO_STATE_RX;
else return NRF905_RADIO_STATE_RX_END;
} else {
if (!digitalRead(DR)) return NRF905_RADIO_STATE_TX;
else return NRF905_RADIO_STATE_TX_END;
}
}
/////////////////////////////////////////////////////////////
// brute force counter
byte bf[] = {0x00, 0x00};
/////////////////////////////////////////////////////////////
void loop()
{
byte ret;
// HEX-Code for getting the address in brute force mode
char wr_for_bruteforce[] = {0x90, 0x80, 0x03, 0x04, 0x00, 0x00, 0x0C};
// HEX-Code from Remote Control to get status from AP300 (This code are sniffed from the remote control after having the valid address and set this programm in received mode and not sending data!!!!!)
char wr_get_status[] = {0x90, 0x80, 0x03, 0x04, 0x00, 0x00, 0x0C, 0xF3, 0xDB, 0xDA, 0xD3, 0xB7, 0x3E, 0x67, 0x7E, 0x0F, 0xEC, 0x3F, 0x30, 0xC0, 0xDF, 0xB5, 0xFF, 0x4D, 0xCC, 0x7C, 0xF5, 0x8F, 0xD5, 0xD0, 0x2F, 0x7B};
//// BRUTE FORCE
#if !REMOTE_SNIFFING
#if BRUTEFORCE
nRF905_powerDown();
byte buf1[] = {0x00, 0x00, bf[0], bf[1]}; // Address of device to send to (4 bytes) = TXADDR
byte buf2[] = {0x00, 0x00, bf[0], bf[1]}; // Address of this device (4 bytes) = RXADDR
byte view[] = {0x00, 0x00, bf[0], bf[1]}; // Address of this device (4 bytes) = VIEW
Serial.print(F("TESTING ADDRESS: 0x"));
Serial.print(view[2], HEX);
Serial.print(F(", 0x"));
Serial.println(view[3], HEX);
// very simple counter
if(bf[1] == 255) {
bf[0]++;
bf[1] = 0;
} else {
bf[1]++;
}
nRF905_Initialise(buf1, buf2); //slow but good ;-)
#endif
#endif
// set start time for timeout
unsigned long startTime = millis();
//// SET DATA
#if !REMOTE_SNIFFING
Serial.println(F("setting data ..."));
// Set payload data
#if BRUTEFORCE
ret = nRF905_setData(wr_for_bruteforce, sizeof(wr_for_bruteforce));
#else
ret = nRF905_setData(wr_get_status, sizeof(wr_get_status));
#endif
if (ret) Serial.println(F("Error by setting data!"));
//// SEND DATA
Serial.println(F("sending data ..."));
// Send payload (send fails if other transmissions are going on, keep trying until success)
while(1) {
ret = nRF905_send();
if (ret==0) break;
else {
Serial.print(F("nRF905_send returned: "));
Serial.println(ret);
delay(100);
}
}
#endif
//// RECEIVE DATA
Serial.println(F("receiving data ..."));
// Put into receive mode
nRF905_receive();
//// GETTING DATA
#define buffer payload // Make buffer for reply
unsigned long time0 = millis() + TIMEOUT; // Wait for reply with timeout
while(1)
{
ret = nRF905_getData(&buffer[plCounter][0], NRF905_MAX_PAYLOAD);
if (ret==0) {plCounter++; break;} // Got data
// check timeout
if ( millis() > time0 ) break;
}
//// EVALUATE DATA
if ( ret==0 )
{ // data received. Do nothing, wait for time-out for display received data
#if BRUTEFORCE
Serial.print(F("Reply from Pluggit AP300. The brute force was successful. The matching Address is: {0x00, 0x00, 0x"));
Serial.print(view[2], HEX);
Serial.print(F(", 0x"));
Serial.print(view[3], HEX);
Serial.println(F("}"));
while (1);
#else
Serial.print(F("Reply from Pluggit AP300: "));
for (uint8_t y = 0; y<plCounter; y++) {
for (byte i=0; i<NRF905_MAX_PAYLOAD; i++) {
ret = buffer[y][i];
if (ret<16) Serial.print(0, HEX);
Serial.print(ret, HEX);
}
Serial.println();
}
ret = 0;
plCounter = 0;
Serial.println();
// wait 5 seconds for next status
delay(5000);
#endif
} else { // time-out
Serial.println(F("time-out"));
Serial.println();
}
}

37
include/README Normal file
View File

@@ -0,0 +1,37 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the convention is to give header files names that end with `.h'.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

View File

@@ -0,0 +1,67 @@
#######################################
# Syntax Coloring Map nRF905
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
nRF905 KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
nRF905_init KEYWORD2
nRF905_setFrequency KEYWORD2
nRF905_setChannel KEYWORD2
nRF905_setAutoRetransmit KEYWORD2
nRF905_setLowRxPower KEYWORD2
nRF905_setTransmitPower KEYWORD2
nRF905_setCRC KEYWORD2
nRF905_setClockOut KEYWORD2
nRF905_setPayloadSize KEYWORD2
nRF905_setTXAddress KEYWORD2
nRF905_setRXAddress KEYWORD2
nRF905_setData KEYWORD2
nRF905_send KEYWORD2
nRF905_getState KEYWORD2
nRF905_receive KEYWORD2
nRF905_getData KEYWORD2
nRF905_powerUp KEYWORD2
nRF905_powerDown KEYWORD2
nRF905_enterStandBy KEYWORD2
nRF905_leaveStandBy KEYWORD2
nRF905_receiveBusy KEYWORD2
nRF905_airwayBusy KEYWORD2
nRF905_interrupt_on KEYWORD2
nRF905_interrupt_off KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
NRF905_RADIO_STATE_IDLE LITERAL1
NRF905_RADIO_STATE_TX LITERAL1
NRF905_RADIO_STATE_RX LITERAL1
NRF905_BAND_433MHZ LITERAL1
NRF905_BAND_868MHZ LITERAL1
NRF905_BAND_915MHZ LITERAL1
NRF905_PWR_n10 LITERAL1
NRF905_PWR_n2 LITERAL1
NRF905_PWR_6 LITERAL1
NRF905_PWR_10 LITERAL1
NRF905_LOW_RX_ENABLE LITERAL1
NRF905_LOW_RX_DISABLE LITERAL1
NRF905_AUTO_RETRAN_ENABLE LITERAL1
NRF905_AUTO_RETRAN_DISABLE LITERAL1
NRF905_OUTCLK_DISABLE LITERAL1
NRF905_OUTCLK_4MHZ LITERAL1
NRF905_OUTCLK_2MHZ LITERAL1
NRF905_OUTCLK_1MHZ LITERAL1
NRF905_OUTCLK_500KHZ LITERAL1
NRF905_CRC_DISABLE LITERAL1
NRF905_CRC_MODE_8 LITERAL1
NRF905_CRC_MODE_16 LITERAL1
NRF905_ADDR_SIZE_1 LITERAL1
NRF905_ADDR_SIZE_4 LITERAL1
NRF905_MAX_PAYLOAD LITERAL1

View File

@@ -0,0 +1,10 @@
name=nRF905
author=Zak Kemble
email=contact@zakkemble.co.uk
sentence=nRF905 Radio Library
paragraph=
url=http://blog.zakkemble.co.uk/nrf905-avrarduino-librarydriver/
architectures=avr
version=2.0
dependencies=
core-dependencies=arduino (>=1.5.0)

View File

@@ -0,0 +1,640 @@
/*
* Project: nRF905 AVR/Arduino Library/Driver
* Author: Zak Kemble, contact@zakkemble.co.uk
* Copyright: (C) 2013 by Zak Kemble
* License: GNU GPL v3 (see License.txt)
* Web: http://blog.zakkemble.co.uk/nrf905-avrarduino-librarydriver/
*/
#include <string.h>
// AVR-specific headers (only for AVR targets)
#if defined(__AVR__)
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#endif
#ifdef ARDUINO
#include <Arduino.h>
#include <SPI.h>
#else
#include "nRF905_spi.h"
#endif
#include "nRF905.h"
#include "nRF905_config.h"
#include "nRF905_defs.h"
#include "nRF905_types.h"
#define noinline __attribute__ ((__noinline__))
#define AM_IS_USED_SW (NRF905_AM_SW)
#define NEED_SW_STATUS_SUPPORT (AM_IS_USED_SW || NRF905_DR_SW)
//#define DISABLE_STANDBY_MODE() (nRF905_leaveStandBy())
//#define ENABLE_STANDBY_MODE() (nRF905_enterStandBy())
static inline bool cselect(void)
{
nRF905_interrupt_off();
// spi_enable();
SPI_SELECT();
return true;
}
static inline bool cdeselect(void)
{
SPI_DESELECT();
// spi_disable();
nRF905_interrupt_on();
return false;
}
// Need to be in standby mode to write registers?
#define STANDBY (ENABLE_STANDBY_MODE())
#define CHIPSELECT(standby) standby; \
for(bool cs = cselect(); cs; cs = cdeselect())
static inline bool interrupt_off(void)
{
nRF905_interrupt_off();
return true;
}
static inline bool interrupt_on(void)
{
nRF905_interrupt_on();
return false;
}
#define NRF905_ATOMIC() for(bool cs = interrupt_off(); cs; cs = interrupt_on())
typedef struct
{
uint8_t reg1; // Change to array
uint8_t reg2;
uint8_t payloadSize;
} config_s;
typedef struct{
nRF905_radio_state_t state;
bool goToRxMode;
} state_s;
typedef struct{
uint8_t buffer[NRF905_MAX_PAYLOAD];
bool ready;
} data_s;
static void setConfigRegister(uint8_t, uint8_t);
static noinline void defaultConfig(void);
static void setAddress(uint8_t * addr, uint8_t cmd);
#if !NRF905_INTERRUPTS
static bool dataReady(void);
#endif
static inline void stateTx(void);
#if NEED_SW_STATUS_SUPPORT
static uint8_t readStatus(void);
#endif
// We could instead read the registers over SPI, but that would be a bit slower
static config_s config;
#if NRF905_INTERRUPTS
#define DATA_BUFFERS 4 // must be power of 2 !!!
static data_s rxData[DATA_BUFFERS];
static volatile state_s radio;
static volatile uint8_t rxRecPtr;
static volatile uint8_t rxReadPtr;
#else
static state_s radio;
#endif
static void spi_transfer_nr(uint8_t cmd, uint8_t * address, uint8_t len)
{
SPI_SELECT();
spi_transfer(cmd);
for(uint8_t i = 0; i<len; i++)
address[i] = spi_transfer(address[i]);
SPI_DESELECT();
}
#if 1
///////////////////////////////////////////////////////////
void nRF905_init()
{
#ifdef ARDUINO
pinMode(TRX_EN, OUTPUT);
pinMode(PWR_MODE, OUTPUT);
pinMode(TX_EN, OUTPUT);
#if NRF905_COLLISION_AVOID
pinMode(CD, INPUT);
#endif
#if AM_IS_USED_HW
pinMode(AM, INPUT);
#endif
#if !NRF905_DR_SW
pinMode(DR, INPUT);
#endif
pinMode(CSN, OUTPUT);
digitalWrite(CSN, HIGH);
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV2);
#else
TRX_EN_DDR |= _BV(TRX_EN_BIT);
PWR_MODE_DDR |= _BV(PWR_MODE_BIT);
TX_EN_DDR |= _BV(TX_EN_BIT);
#if NRF905_COLLISION_AVOID
CD_DDR &= ~_BV(CD_BIT);
#endif
#if AM_IS_USED_HW
AM_DDR &= ~_BV(AM_BIT);
#endif
#if !NRF905_DR_SW
DR_DDR &= ~_BV(DR_BIT);
#endif
spi_init();
#endif
radio.state = NRF905_RADIO_STATE_POWER_DOWN;
// Startup
ENABLE_STANDBY_MODE();
RECEIVE_MODE();
nRF905_powerDown();
delay(3);
defaultConfig();
#if NRF905_INTERRUPTS
// Set interrupts
REG_EXTERNAL_INT_CTL |= BIT_EXTERNAL_INT_CTL;
nRF905_interrupt_on();
#endif
nRF905_powerUp();
}
#endif
// Set frequency, workout the channel from the frequency
void nRF905_setFrequency(nRF905_band_t band, uint32_t freq)
{
nRF905_setChannel(band, NRF905_CALC_CHANNEL(freq, band));
}
///////////////////////////////////////////////////////////////////////////
#if 1
// Set channel
void nRF905_setChannel(nRF905_band_t band, uint16_t channel)
{
config.reg1 = (config.reg1 & NRF905_MASK_CHANNEL) | band | ((channel>>8) & 0x01);
SPI_SELECT();
spi_transfer(NRF905_CMD_W_CONFIG | NRF905_REG_CHANNEL);
spi_transfer(channel);
spi_transfer(config.reg1);
SPI_DESELECT();
}
#endif
#if 0
// Set auto retransmit
void nRF905_setAutoRetransmit(nRF905_auto_retran_t val)
{
setConfigReg1(val, NRF905_MASK_AUTO_RETRAN, NRF905_REG_AUTO_RETRAN);
}
// Set low power receive
void nRF905_setLowRxPower(nRF905_low_rx_t val)
{
setConfigReg1(val, NRF905_MASK_LOW_RX, NRF905_REG_LOW_RX);
}
// Set output power
void nRF905_setTransmitPower(nRF905_pwr_t val)
{
setConfigReg1(val, NRF905_MASK_PWR, NRF905_REG_PWR);
}
// Set CRC
void nRF905_setCRC(nRF905_crc_t val)
{
setConfigReg2(val, NRF905_MASK_CRC, NRF905_REG_CRC);
}
// Set clock output
void nRF905_setClockOut(nRF905_outclk_t val)
{
setConfigReg2(val, NRF905_MASK_OUTCLK, NRF905_REG_OUTCLK);
}
#endif
//////////////////////////////////////////////////////////////////////
void nRF905_setConfigReg0(uint8_t val)
{
setConfigRegister(NRF905_CMD_W_CONFIG, val);
}
void nRF905_setConfigReg1(uint8_t val)
{
config.reg1 = val;
setConfigRegister(NRF905_CMD_W_CONFIG | 1, val);
}
void nRF905_setConfigReg2(uint8_t val)
{
config.reg2 = val;
setConfigRegister(NRF905_CMD_W_CONFIG | 2, val);
}
void nRF905_setConfigReg9(uint8_t val)
{
setConfigRegister(NRF905_CMD_W_CONFIG | 9, val);
}
static void setConfigRegister(uint8_t cmd, uint8_t val)
{
SPI_SELECT();
spi_transfer(cmd);
spi_transfer(val);
SPI_DESELECT();
}
uint8_t nRF905_getConfigReg(uint8_t reg)
{
SPI_SELECT();
spi_transfer(NRF905_CMD_R_CONFIG | reg);
uint8_t retVal = spi_transfer(0);
SPI_DESELECT();
return retVal;
}
void nRF905_flushRecBuffer(void)
{
SPI_SELECT();
spi_transfer(NRF905_CMD_R_RX_PAYLOAD);
for(uint8_t i=NRF905_MAX_PAYLOAD; i>0;i--)
spi_transfer(NRF905_CMD_NOP);
SPI_DESELECT();
#if NRF905_INTERRUPTS
rxRecPtr = 0;
rxReadPtr = 0;
#endif
}
#if 1
// Set configuration
// Radio should be in standby mode and interrupts disabled
static noinline void defaultConfig()
{
uint16_t channel = NRF905_CALC_CHANNEL(NRF905_FREQ, NRF905_BAND);
uint8_t reg1 = NRF905_AUTO_RETRAN | NRF905_LOW_RX | NRF905_PWR | NRF905_BAND | ((channel>>8) & 0x01);
uint8_t reg2 = NRF905_CRC | NRF905_CLK_FREQ | NRF905_OUTCLK;
config.reg1 = reg1;
config.reg2 = reg2;
config.payloadSize = NRF905_PAYLOAD_SIZE;
// Set control registers
SPI_SELECT();
spi_transfer(NRF905_CMD_W_CONFIG);
spi_transfer(channel);
spi_transfer(reg1);
spi_transfer((NRF905_ADDR_SIZE<<4) | NRF905_ADDR_SIZE);
spi_transfer(NRF905_PAYLOAD_SIZE); // RX payload size
spi_transfer(NRF905_PAYLOAD_SIZE); // TX payload size
for(uint8_t i=4;i--;)
spi_transfer(0xE7); // Default receive address
spi_transfer(reg2);
SPI_DESELECT();
// Default transmit address
SPI_SELECT();
spi_transfer(NRF905_CMD_W_TX_ADDRESS);
for(uint8_t i=4;i--;)
spi_transfer(0xE7);
SPI_DESELECT();
// Clear transmit payload
SPI_SELECT();
spi_transfer(NRF905_CMD_W_TX_PAYLOAD);
for(uint8_t i=NRF905_MAX_PAYLOAD;i--;)
spi_transfer(0x00);
SPI_DESELECT();
// Clear DR by reading receive payload
SPI_SELECT();
spi_transfer(NRF905_CMD_R_RX_PAYLOAD);
for(uint8_t i=NRF905_MAX_PAYLOAD;i--;)
spi_transfer(NRF905_CMD_NOP);
SPI_DESELECT();
}
#endif
// Payload size
void nRF905_setPayloadSizes(uint8_t size)
{
if(size > NRF905_MAX_PAYLOAD)
size = NRF905_MAX_PAYLOAD;
config.payloadSize = size;
SPI_SELECT();
spi_transfer(NRF905_CMD_W_CONFIG | NRF905_REG_RX_PAYLOAD_SIZE);
spi_transfer(size);
spi_transfer(size);
SPI_DESELECT();
}
// Power up
void nRF905_powerUp()
{
radio.state = NRF905_RADIO_STATE_STANDBY;
ENABLE_STANDBY_MODE();
POWER_UP();
// Give it time to turn on
delay(3);
}
void nRF905_powerDown()
{
ENABLE_STANDBY_MODE();
POWER_DOWN();
radio.state = NRF905_RADIO_STATE_POWER_DOWN;
}
void nRF905_enterStandBy()
{
ENABLE_STANDBY_MODE();
radio.state = NRF905_RADIO_STATE_STANDBY;
}
/*
//
void nRF905_setAddressSize(uint8_t size)
{
CHIPSELECT(STANDBY)
{
spi_transfer_nr(NRF905_CMD_W_CONFIG | NRF905_REG_ADDR_WIDTH);
spi_transfer_nr((size<<4) | size);
}
}
*/
// Set address
static void setAddress(uint8_t cmd, uint8_t * address)
{
// Address bytes are sent in reverse order, which is fine as long as both ends do the same thing.
spi_transfer_nr(cmd, address, NRF905_ADDR_SIZE);
}
// Set address of device to send to
void nRF905_setTXAddress(uint8_t * address)
{
setAddress(NRF905_CMD_W_TX_ADDRESS, address);
}
// Set address for this device
void nRF905_setRXAddress(uint8_t * address)
{
setAddress(NRF905_CMD_W_CONFIG | NRF905_REG_RX_ADDRESS, address);
}
// Set the payload data
uint8_t nRF905_setData(uint8_t * data, uint8_t len)
{
/* // Busy transmitting something else
if(radio.state == NRF905_RADIO_STATE_TX)
return 1;//false;
*/
nRF905_enterStandBy();
uint8_t maxPayload = config.payloadSize;
if(len > maxPayload)
len = maxPayload;
// Load data
spi_transfer_nr(NRF905_CMD_W_TX_PAYLOAD, data, len);
return 0;//true;
}
// See if device is receiving something
// Hardware: Address match pin high
// Software: Address match status bit set
bool nRF905_receiveBusy()
{
#if (!AM_IS_USED_HW && !AM_IS_USED_SW)
return false;
#elif AM_IS_USED_SW
return (readStatus() & _BV(NRF905_STATUS_AM));
#else
return digitalRead(AM);
#endif
}
// See if data ready, true if received new data/finished transmitting
// Hardware: Data ready pin high
// Software: Data ready status bit set
#if !NRF905_INTERRUPTS
static bool dataReady()
{
#if NRF905_DR_SW
return (readStatus() & _BV(NRF905_STATUS_DR));
#else
return digitalRead(DR);
#endif
}
#endif
///////////////////////////////////////////////////////////
// Transmit payload
///////////////////////////////////////////////////////////
uint8_t nRF905_send(void)
{
// Already transmitting
if(radio.state == NRF905_RADIO_STATE_TX)
return 1;//false;
#if NRF905_COLLISION_AVOID
// Don't transmit if busy
else if(nRF905_airwayBusy())
return 2;//false;
#endif
// Put into transmit mode
TRANSMIT_MODE();
radio.state = NRF905_RADIO_STATE_TX;
// Pulse standby pin to start transmission
DISABLE_STANDBY_MODE();
delay(10);
#if NRF905_AUTO_RETRAN == NRF905_AUTO_RETRAN_DISABLE
// Radio will go back into standby mode after transmission, unless nRF905_receive()
// is called in which case it will go straight to receive mode after transmission.
// If auto-retransmission is disabled and if the radio isn't set to go into standby or receive mode then it will
// transmit a carrier signal with no data.
ENABLE_STANDBY_MODE();
#endif
return 0;//true;
}
// Return radio state
nRF905_radio_state_t nRF905_getState(void)
{
return radio.state;
}
// Get radio status by reading pin states
nRF905_radio_state_t nRF905_getStatus(void)
{
if (!digitalRead(PWR_MODE))
return NRF905_RADIO_STATE_POWER_DOWN;
else if (!digitalRead(TRX_EN))
return NRF905_RADIO_STATE_STANDBY;
else if (!digitalRead(TX_EN)) {
if (!digitalRead(DR))
return NRF905_RADIO_STATE_RX;
else
return NRF905_RADIO_STATE_RX_END;
} else {
if (!digitalRead(DR))
return NRF905_RADIO_STATE_TX;
else
return NRF905_RADIO_STATE_TX_END;
}
}
// Put into receive mode
void nRF905_receive(void)
{
// NRF905_ATOMIC()
// {
if(radio.state == NRF905_RADIO_STATE_TX) // Currently transmitting, so wait until finished then go into receive mode
while (nRF905_getStatus()==NRF905_RADIO_STATE_TX); //radio.goToRxMode = true;
// else
// {
RECEIVE_MODE();
DISABLE_STANDBY_MODE();
radio.state = NRF905_RADIO_STATE_RX;
delay(1);
// }
// }
}
// Get received data if available
uint8_t nRF905_getData(uint8_t * data, uint8_t len)
{
static uint8_t i;
static uint8_t * ptr;
if(len > config.payloadSize)
len = config.payloadSize;
#if NRF905_INTERRUPTS
/* // No data received
if(!rxData.ready)
return 1;//false;
*/
if (rxReadPtr==rxRecPtr)
return 1;//false;
// retrun actual read ptr
// NRF905_ATOMIC()
// {
// Copy and clear data buffer
//memcpy(data, (uint8_t*)rxData.buffer, len);
ptr = rxData[rxReadPtr].buffer;
for (i=0; i<len; i++)
data[i] = *ptr++;
//memset((uint8_t*)rxData.buffer, 0, sizeof(rxData.buffer));
rxData[rxReadPtr].ready = false;
rxReadPtr = (rxReadPtr+1)&(DATA_BUFFERS-1);
// }
return 0;//true;
#else
// No data ready
if(!dataReady())
return 2;//false;
uint8_t remaining;
switch(radio.state)
{
case NRF905_RADIO_STATE_TX:
// Finished transmitting payload
//stateTx();
break;
case NRF905_RADIO_STATE_RX:
// New payload received
SPI_SELECT();
spi_transfer(NRF905_CMD_R_RX_PAYLOAD);
// Get received payload
for(uint8_t i=0;i<len;i++)
data[i] = spi_transfer(NRF905_CMD_NOP);
// Must make sure all of the payload has been read, otherwise DR never goes low
remaining = config.payloadSize - len;
while(remaining--)
spi_transfer(NRF905_CMD_NOP);
SPI_DESELECT();
// We're still in receive mode
return 0;//true;
default:
break;
}
return 3;//false;
#endif
}
/*
static inline void stateTx()
{
if(radio.goToRxMode)
{
// We want to go into receive mode
radio.goToRxMode = false;
RECEIVE_MODE();
DISABLE_STANDBY_MODE();
radio.state = NRF905_RADIO_STATE_RX;
}
else
{
// If we didn't want to go into receive mode then we're now in standby mode
radio.state = NRF905_RADIO_STATE_IDLE;
}
}
*/
#if NEED_SW_STATUS_SUPPORT
// Read status register
static uint8_t readStatus()
{
uint8_t status;
CHIPSELECT()
status = spi_transfer(NRF905_CMD_NOP);
return status;
}
#endif
#if NRF905_INTERRUPTS
// Data ready pin interrupt
ISR(INT_VECTOR)
{
switch(radio.state)
{
case NRF905_RADIO_STATE_TX:
// Finished transmitting payload
//stateTx();
break;
case NRF905_RADIO_STATE_RX:
// New payload received
spi_transfer_nr(NRF905_CMD_R_RX_PAYLOAD, (uint8_t*)rxData[rxRecPtr].buffer, config.payloadSize);
rxData[rxRecPtr].ready = true;
rxRecPtr = (rxRecPtr+1)&(DATA_BUFFERS-1);
// We're still in receive mode
break;
default:
break;
}
}
#endif

View File

@@ -0,0 +1,377 @@
/*
* Project: nRF905 AVR/Arduino Library/Driver
* Author: Zak Kemble, contact@zakkemble.co.uk
* Copyright: (C) 2013 by Zak Kemble
* License: GNU GPL v3 (see License.txt)
* Web: http://blog.zakkemble.co.uk/nrf905-avrarduino-librarydriver/
*/
#ifndef NRF905_H_
#define NRF905_H_
#include <Arduino.h>
#include "nRF905_config.h"
//#define nRF905_packet nrf905_packet_s;
/**
* \enum nRF905_radio_state_t
* \brief Radio state
*/
typedef enum
{
NRF905_RADIO_STATE_POWER_DOWN, /**< Power down mode */
NRF905_RADIO_STATE_STANDBY, /**< standby mode*/
NRF905_RADIO_STATE_RX, /**< Receive mode */
NRF905_RADIO_STATE_RX_END, /**< Received data available */
NRF905_RADIO_STATE_TX, /**< Transmitting started */
NRF905_RADIO_STATE_TX_END, /**< Transmitting finished */
} nRF905_radio_state_t;
/**
* \enum nRF905_band_t
* \brief Frequency bands.
*/
typedef enum
{
// NOTE:
// When using NRF905_BAND_868 and NRF905_BAND_915 for calculating channel (NRF905_CALC_CHANNEL(f, b)) they should be value 0x01,
// but when using them for setting registers their value should be 0x02.
// They're defined as 0x02 here so when used for calculating channel they're right shifted by 1
NRF905_BAND_433 = 0x00, /**< 433MHz band */
NRF905_BAND_868 = 0x02, /**< 868MHz band */
NRF905_BAND_915 = 0x02 /**< 915MHz band */
} nRF905_band_t;
/**
* \enum nRF905_pwr_t
* \brief Output power (n means negative, n10 = -10).
*/
typedef enum
{
NRF905_PWR_n10 = 0x00, /**< -10dBm = 100uW */
NRF905_PWR_n2 = 0x04, /**< -2dBm = 631uW */
NRF905_PWR_6 = 0x08, /**< 6dBm = 4mW */
NRF905_PWR_10 = 0x0C /**< 10dBm = 10mW */
} nRF905_pwr_t;
/**
* \enum nRF905_low_rx_t
* \brief Save a few mA by reducing receive sensitivity.
*/
typedef enum
{
NRF905_LOW_RX_DISABLE = 0x00, /**< Disable low power receive */
NRF905_LOW_RX_ENABLE = 0x10 /**< Enable low power receive */
} nRF905_low_rx_t;
/**
* \enum nRF905_auto_retran_t
* \brief Constantly retransmit payload while in transmit mode.
*
* Can be useful in areas with lots of interference, but you'll need to make sure you can differentiate between re-transmitted packets and new packets (like an ID number).
*
* Other transmissions will be blocked if collision avoidance is enabled.
*/
typedef enum
{
NRF905_AUTO_RETRAN_DISABLE = 0x00, /**< Disable auto re-transmit */
NRF905_AUTO_RETRAN_ENABLE = 0x20 /**< Enable auto re-transmit */
} nRF905_auto_retran_t;
/**
* \enum nRF905_outclk_t
* \brief Output a clock signal on pin 3 of IC.
*/
typedef enum
{
NRF905_OUTCLK_DISABLE = 0x00, /**< Disable output clock */
NRF905_OUTCLK_4MHZ = 0x04, /**< 4MHz clock */
NRF905_OUTCLK_2MHZ = 0x05, /**< 2MHz clock */
NRF905_OUTCLK_1MHZ = 0x06, /**< 1MHz clock */
NRF905_OUTCLK_500KHZ = 0x07, /**< 500KHz clock */
} nRF905_outclk_t;
/**
* \enum nRF905_crc_t
* \brief CRC Checksum.
*/
typedef enum
{
NRF905_CRC_DISABLE = 0x00, /**< Disable CRC */
NRF905_CRC_8 = 0x40, /**< 8bit CRC */
NRF905_CRC_16 = 0xC0, /**< 16bit CRC */
} nRF905_crc_t;
/**
* \enum nRF905_addr_size_t
* \brief Address size.
*/
typedef enum
{
NRF905_ADDR_SIZE_1 = 0x01, /**< 1 byte */
NRF905_ADDR_SIZE_4 = 0x04, /**< 4 bytes */
} nRF905_addr_size_t;
// Setting options
//#define NRF905_BAND_433 0x00
//#define NRF905_BAND_868 0x02
//#define NRF905_BAND_915 0x02
//#define NRF905_PWR_n10 0x00
//#define NRF905_PWR_n2 0x04
//#define NRF905_PWR_6 0x08
//#define NRF905_PWR_10 0x0C
//#define NRF905_LOW_RX_ENABLE 0x10
//#define NRF905_LOW_RX_DISABLE 0x00
//#define NRF905_AUTO_RETRAN_ENABLE 0x20
//#define NRF905_AUTO_RETRAN_DISABLE 0x00
//#define NRF905_OUTCLK_DISABLE 0x00
//#define NRF905_OUTCLK_4MHZ 0x04
//#define NRF905_OUTCLK_2MHZ 0x05
//#define NRF905_OUTCLK_1MHZ 0x06
//#define NRF905_OUTCLK_500KHZ 0x07
//#define NRF905_CRC_DISABLE 0x00
//#define NRF905_CRC_8 0x40
//#define NRF905_CRC_16 0xC0
//#define NRF905_ADDR_SIZE_1 0x01
//#define NRF905_ADDR_SIZE_4 0x04
/**
* Maximum payload size
*/
#define NRF905_MAX_PAYLOAD 32
void nRF905_setConfigReg0(uint8_t value);
void nRF905_setConfigReg1(uint8_t value);
void nRF905_setConfigReg2(uint8_t value);
void nRF905_setConfigReg9(uint8_t value);
void nRF905_flushRecBuffer(void);
uint8_t nRF905_getConfigReg(uint8_t reg);
nRF905_radio_state_t nRF905_getStatus(void);
/**
* Initialise, must be called before anything else!
*
* @return (none)
*/
void nRF905_init(void);
/**
* Set frequency, workout the channel from the frequency
*
* 433MHz band: 422.4MHz - 473.5MHz, 100KHz steps
*
* 868/915MHz band: 844.8MHz - 947MHz, 200KHz steps
*
* @param [band] Frequency band
* @param [freq] Frequency in Hz
* @return (none)
*/
void nRF905_setFrequency(nRF905_band_t band, uint32_t freq);
/**
* Just set the channel, this skips having to workout the channel from the frequency
*
* @param [band] Frequency band
* @param [channel] The channel (0 - 511)
* @return (none)
*/
void nRF905_setChannel(nRF905_band_t band, uint16_t channel);
#if 0
/**
* Set auto retransmit
*
* @param [val] Enable/disable auto retransmit
* @return (none)
*/
void nRF905_setAutoRetransmit(nRF905_auto_retran_t val);
/**
* Set low power receive
*
* @param [val] Enable/disable low power receive
* @return (none)
*/
void nRF905_setLowRxPower(nRF905_low_rx_t val);
/**
* Set output power
*
* @param [val] Output power level
* @return (none)
*/
void nRF905_setTransmitPower(nRF905_pwr_t val);
/**
* Set CRC
*
* @param [val] CRC Type
* @return (none)
*/
void nRF905_setCRC(nRF905_crc_t val);
/**
* Set clock output
*
* @param [val] Clock out frequency
* @return (none)
*/
void nRF905_setClockOut(nRF905_outclk_t val);
#endif
/**
* Payload size
*
* @param [size] Payload size (1 - 32)
* @return (none)
*/
void nRF905_setPayloadSizes(uint8_t size);
//**
//* Address size
//*
//* @param [size] Address size
//* @return (none)
//*/
//void nRF905_setAddressSize(nRF905_addr_size_t size);
/**
* Destination radio address
*
* @param [address] The address (usually a byte array of 1 or 4 bytes depending on NRF905_ADDR_SIZE)
* @return (none)
*/
void nRF905_setTXAddress(uint8_t * address);
/**
* Address of this radio
*
* @param [address] The address (usually a byte array of 1 or 4 bytes depending on NRF905_ADDR_SIZE)
* @return (none)
*/
void nRF905_setRXAddress(uint8_t * address);
/**
* Set payload data
*
* @param [data] Pointer to data
* @param [len] How many bytes to copy (max NRF905_MAX_PAYLOAD)
* @return false if the radio is currently transmitting something else, true otherwise
*/
uint8_t nRF905_setData(uint8_t * data, uint8_t len);
/**
* Send the payload.
*
* @return false if other transmissions are going on and collision detection is enabled or if the radio is currently transmitting, true if transmission has successfully began
*/
uint8_t nRF905_send(void);
//
//bool nRF905_sendPacket(nrf905_packet_s*);
/**
* Get current radio state, transmitting etc.
*
* @return Radio state
*/
nRF905_radio_state_t nRF905_getState(void);
/**
* Receive mode. If the radio is currently transmitting then receive mode will be entered once it has finished.
*
* @return (none)
*/
void nRF905_receive(void);
/**
* Get received payload if available.
*
* @param [data] Pointer to buffer to place data
* @param [len] How many bytes to copy
* @return false if no data available, otherwise true
*/
uint8_t nRF905_getData(uint8_t * data, uint8_t len);
/**
* Wake up into standby mode.
* Will take 3ms to complete.
*
* @return (none)
*/
void nRF905_powerUp(void);
/**
* Sleep.
*
* @note Must call nRF905_powerUp() before transmitting or receiving again.
* @return (none)
*/
void nRF905_powerDown(void);
/**
* Enter standby mode.
*
* @return (none)
*/
void nRF905_enterStandBy(void);
/**
* Leave standby and go into receive mode (same as just calling nRF905_receive()).
*
* @return (none)
*/
inline void nRF905_leaveStandBy(void)
{
nRF905_receive();
}
/**
* blah
*
* @return blah
*/
bool nRF905_receiveBusy(void);
/**
* See if airway is busy (carrier detect pin high).
*
* @return true if other transmissions detected, otherwise false
*/
inline bool nRF905_airwayBusy(void)
{
return digitalRead(CD);
}
/**
* Disable data ready interrupt.
*
* If NRF905_INTERRUPTS is enabled then this function must be called before doing SPI communications with any other device.
*
* @return (none)
*/
inline void nRF905_interrupt_off(void)
{
#if NRF905_INTERRUPTS
REG_EXTERNAL_INT &= ~_BV(BIT_EXTERNAL_INT);
#endif
}
/**
* Enable data ready interrupt.
*
* If NRF905_INTERRUPTS is enabled then this function must be called once you have finished doing SPI communications with another device.
*
* @return (none)
*/
inline void nRF905_interrupt_on(void)
{
#if NRF905_INTERRUPTS
REG_EXTERNAL_INT |= _BV(BIT_EXTERNAL_INT);
#endif
}
#endif /* NRF905_H_ */

View File

@@ -0,0 +1,258 @@
/*
* Project: nRF905 AVR/Arduino Library/Driver
* Author: Zak Kemble, contact@zakkemble.co.uk
* Copyright: (C) 2013 by Zak Kemble
* License: GNU GPL v3 (see License.txt)
* Web: http://blog.zakkemble.co.uk/nrf905-avrarduino-librarydriver/
*/
/*
* Time how long it takes to send some data and get a reply
* Should be around 14-16ms with default settings.
*
* 7 -> PWR == PWR_MODE
* 8 -> CE == TRX_EN
* 9 -> TXE == TX_EN
* 2 -> CD
* 3 -> DR - uses INT1 interrupt
* 10 -> CSN
* 12 -> SO
* 11 -> SI
* 13 -> SCK
*/
#include <nRF905.h>
#include <SPI.h>
#define RXADDR {0x00, 0x00, 0x0A, 0x7A} // Address of this device (4 bytes)
#define TXADDR {0x00, 0x00, 0x0A, 0x7A} // Address of device to send to (4 bytes)
#define TIMEOUT 1000 // 1 second ping timeout
uint8_t payload[4][NRF905_MAX_PAYLOAD];
uint8_t plCounter;
//#define DBG_PIN 5
//////////////////////////////////////////////////////////////////////////
void nRF905_Config(void)
{
// Set control register 0 - CHANNEL
nRF905_setConfigReg0(0x76);
// config reg 1
nRF905_setConfigReg1(0x0E);
// config reg 2
nRF905_setConfigReg2(0x44);
// Set payload sizes
nRF905_setPayloadSizes(0x20);
// set TX and Rx addresses
static byte buf1[] = TXADDR;
nRF905_setTXAddress(buf1);
// set Rx addres
static byte buf2[] = RXADDR;
nRF905_setRXAddress(buf2);
// read config register 9 - just to be conform with data detected by sniffing
nRF905_getConfigReg(9);
// set config register 9
nRF905_setConfigReg9(0xDB);
// Clear DR by reading receive payload
nRF905_flushRecBuffer();
// Set interrupts
// REG_EXTERNAL_INT_CTL |= BIT_EXTERNAL_INT_CTL;
// nRF905_interrupt_on();
}
//////////////////////////////////////////////////////////////////////////
void nRF905_Initialise()
{
pinMode(PWR_MODE, OUTPUT);
digitalWrite(PWR_MODE, LOW); // activate power down mode
pinMode(TRX_EN, OUTPUT);
digitalWrite(TRX_EN, LOW); // activate standby mode
pinMode(TX_EN, OUTPUT);
pinMode(CSN, OUTPUT);
pinMode(CD, INPUT);
pinMode(DR, INPUT);
digitalWrite(CSN, HIGH);
#ifdef DBG_PIN
pinMode(DBG_PIN, OUTPUT);
#endif
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV2);
nRF905_Config();
#if NRF905_INTERRUPTS
// Set interrupts
REG_EXTERNAL_INT_CTL |= BIT_EXTERNAL_INT_CTL;
nRF905_interrupt_on();
#endif
Serial.println(F("nRF905 configured..."));
StatusPins();
// leave config mode
nRF905_powerUp();
Serial.println(F("nRF905 powered up..."));
StatusPins();
// Put into receive mode
// nRF905_receive();
}
//////////////////////////////////////////////////////////////////
void StatusPins(void)
{
return;
/**/
Serial.print(F("pins: "));
Serial.print(digitalRead(CD));
Serial.print(",");
Serial.print(digitalRead(DR));
Serial.print(",");
Serial.print(digitalRead(PWR_MODE));
Serial.print(",");
Serial.print(digitalRead(TRX_EN));
Serial.print(",");
Serial.println(digitalRead(TX_EN));
}
///////////////////////////////////////////////////////////////////
void setup()
{
Serial.begin(57600);
Serial.println(F("Client started"));
StatusPins();
// Start up
nRF905_Initialise();
StatusPins();
Serial.println(F("nRF905 initialised"));
plCounter = 0;
}
//////////////////////////////////////////////////////
nRF905_radio_state_t nRF905_getStatus(void)
{
if (!digitalRead(PWR_MODE)) return NRF905_RADIO_STATE_POWER_DOWN;
else if (!digitalRead(TRX_EN)) return NRF905_RADIO_STATE_STANDBY;
else if (!digitalRead(TX_EN)) {
if (!digitalRead(DR)) return NRF905_RADIO_STATE_RX;
else return NRF905_RADIO_STATE_RX_END;
} else {
if (!digitalRead(DR)) return NRF905_RADIO_STATE_TX;
else return NRF905_RADIO_STATE_TX_END;
}
}
/////////////////////////////////////////////////////////////
char wr1[] PROGMEM = {0x90, 0x80, 0x03, 0x04, 0x00, 0x00, 0x0C};
char wr2[] PROGMEM = {0x90, 0x80, 0x03, 0x04, 0x0C, 0x00, 0x0C};
static byte counter = 0;
static byte recOK = 0;
/////////////////////////////////////////////////////////////
void loop()
{
byte ret;
// Make data
strcpy_P((char*)payload, wr1);
counter++;
Serial.println(counter);
#ifdef DBG_PIN
digitalWrite(DBG_PIN, 1);
#endif
unsigned long startTime = millis();
/* // Set address of device to send to
byte addr[] = TXADDR;
nRF905_setTXAddress(addr);
*/
#if 0
//// SET DATA
StatusPins();
Serial.println(F("setting data ..."));
// Set payload data
ret = nRF905_setData(payload, sizeof(wr1));
if (ret) Serial.println(F("Error by setting data!"));
//// SEND DATA
StatusPins();
Serial.println(F("sending data ..."));
// Send payload (send fails if other transmissions are going on, keep trying until success)
while(1) {
ret = nRF905_send();
if (ret==0) break;
else {
Serial.print(F("nRF905_send returned: "));
Serial.println(ret);
delay(100);
}
StatusPins();
};
#endif
//// RECEIVE DATA
#ifdef DBG_PIN
digitalWrite(DBG_PIN, 0);
StatusPins();
Serial.println(F("receiving data ..."));
#endif
// Put into receive mode
nRF905_receive();
// Make buffer for reply
// byte buffer[NRF905_MAX_PAYLOAD];
#define buffer payload
//// GETTING DATA
#ifdef DBG_PIN
StatusPins();
Serial.println(F("getting data ..."));
#endif
// Wait for reply with timeout
unsigned long time0 = millis();
while(1)
{
ret = nRF905_getData(&buffer[plCounter][0], NRF905_MAX_PAYLOAD);
if (ret==0) {plCounter++; recOK = true; break;} // Got data
else {
#ifdef DBG_PIN
Serial.print(F("getData returned: "));
Serial.println(ret);
#endif
}
// StatusPins();
// check timeout
if( millis() > (time0 + TIMEOUT) ) break;
}
//// EVALUATE DATA
#ifdef DBG_PIN
StatusPins();
Serial.println(F("evaluating data..."));
#endif
if(!ret)
{ // data received. Do nothing, wait for time-out for display received data
#ifdef DBG_PIN
unsigned int totalTime = millis() - startTime;
Serial.print(F("Ping time: "));
Serial.print(totalTime);
Serial.println(F("ms"));
// Printout ping contents
Serial.print(F("Replay from AP300: "));
#endif
}
else if (recOK) {
// Serial.print(F("Replay from AP300: "));
for (uint8_t y = 0; y<plCounter; y++) {
for (byte i=0; i<NRF905_MAX_PAYLOAD; i++) {
ret = buffer[y][i];
if (ret<16) Serial.print(0, HEX);
Serial.print(ret, HEX);
}
Serial.println();
}
recOK = false;
plCounter = 0;
Serial.println();
} else // time-out
Serial.println(F("time-out"));
/*
if (counter>=100)
while (1); // stop here
// delay(100);
*/
}

View File

@@ -0,0 +1,164 @@
/*
* Project: nRF905 AVR/Arduino Library/Driver
* Author: Zak Kemble, contact@zakkemble.co.uk
* Copyright: (C) 2013 by Zak Kemble
* License: GNU GPL v3 (see License.txt)
* Web: http://blog.zakkemble.co.uk/nrf905-avrarduino-librarydriver/
*/
#ifndef NRF905_CONFIG_H_
#define NRF905_CONFIG_H_
#include "nRF905_defs.h"
// Crystal frequency (the one the radio IC/module is using)
// NRF905_CLK_4MHZ
// NRF905_CLK_8MHZ
// NRF905_CLK_12MHZ
// NRF905_CLK_16MHZ
// NRF905_CLK_20MHZ
#define NRF905_CLK_FREQ NRF905_CLK_16MHZ
// Use pin interrupt for data ready
// NOTE: If you have other devices connected that use the SPI bus then you will need to call nRF905_interrupt_off() before using SPI comms and then RF905_interrupt_on() once you've finished.
// Disabled for ESP32 - using polling mode
#define NRF905_INTERRUPTS 0
// Buffer count
// Only used if interrupts are used (see NRF905_INTERRUPTS)
// NOT YET IMPLEMENTED
//#define BUFFER_COUNT_RX 1
// Buffer count
// NOT YET IMPLEMENTED
//#define BUFFER_COUNT_TX 1
//
// NOT YET IMPLEMENTED
//#define NRF905_MAX_PACKET_SIZE 64
// Use software to get address match state instead of reading pin for high/low state
// Not used in this library yet
#define NRF905_AM_SW 0
// Use software to get data ready state instead of reading pin for high/low state
// Interrupts and software DR can not be enabled together
#define NRF905_DR_SW 1
// Don't transmit if airway is busy (other transmissions are going on)
#define NRF905_COLLISION_AVOID 0
///////////////////
// Pin stuff - ESP32 Configuration
///////////////////
// ESP32 GPIO pins for nRF905
#define PWR_MODE 4 // Power mode pin (GPIO4)
#define TRX_EN 16 // Enable/standby pin (GPIO16)
#define TX_EN 17 // TX / RX mode pin (GPIO17)
#define CD 27 // Carrier detect pin (GPIO27) - optional
#define CSN 5 // SPI slave select pin (GPIO5)
// Data ready pin
// If using interrupts (NRF905_INTERRUPTS 1) then this must be
// an external interrupt pin that matches the interrupt register settings below.
#define DR 26 // Data ready (GPIO26) - optional for interrupts
// Address match pin (not used by library)
// blah
//#define AM 4
///////////////////
// Interrupt register stuff
// Only needed if NRF905_INTERRUPTS is 1
///////////////////
// Interrupt number (INT0, INT1 etc)
// This must match the INT that is connected to DR
#define INTERRUPT_NUM 1
// ATmega48/88/168/328
// INT0 = D2 (Arduino UNO pin 2)
// INT1 = D3 (Arduino UNO pin 3)
// ATmega640/1280/1281/2560/2561
// INT0 = D0 (Arduino MEGA pin 21)
// INT1 = D1 (Arduino MEGA pin 20)
// INT2 = D2 (Arduino MEGA pin 19)
// INT3 = D3 (Arduino MEGA pin 18)
// INT4 = E4 (Arduino MEGA pin 2)
// INT5 = E5 (Arduino MEGA pin 3)
// INT6 = E6 (Arduino MEGA N/A)
// INT7 = E7 (Arduino MEGA N/A)
// Leave these commented out to let the library figure out what registers to use
// Which interrupt to use for data ready (DR)
//#define REG_EXTERNAL_INT EIMSK
//#define BIT_EXTERNAL_INT INT1
//#define INT_VECTOR INT1_vect
// Set interrupt to trigger on rising edge
//#define REG_EXTERNAL_INT_CTL EICRA
//#define BIT_EXTERNAL_INT_CTL (_BV(ISC11)|_BV(ISC10))
///////////////////
// Default radio settings
///////////////////
// Frequency
#define NRF905_FREQ 868200000UL
// Frequency band
// NRF905_BAND_433
// NRF905_BAND_868
// NRF905_BAND_915
#define NRF905_BAND NRF905_BAND_868
// Output power
// n means negative, n10 = -10
// NRF905_PWR_n10 (-10dBm = 100uW)
// NRF905_PWR_n2 (-2dBm = 631uW)
// NRF905_PWR_6 (6dBm = 4mW)
// NRF905_PWR_10 (10dBm = 10mW)
#define NRF905_PWR NRF905_PWR_10
// Save a few mA by reducing receive sensitivity
// NRF905_LOW_RX_DISABLE
// NRF905_LOW_RX_ENABLE
#define NRF905_LOW_RX NRF905_LOW_RX_DISABLE
// Constantly retransmit payload while in transmit mode
// Can be useful in areas with lots of interference, but you'll need to make sure you can differentiate between re-transmitted packets and new packets (like an ID number).
// It will also block other transmissions if collision avoidance is enabled.
// NRF905_AUTO_RETRAN_DISABLE
// NRF905_AUTO_RETRAN_ENABLE
#define NRF905_AUTO_RETRAN NRF905_AUTO_RETRAN_DISABLE
// Output a clock signal on pin 3 of IC
// NRF905_OUTCLK_DISABLE
// NRF905_OUTCLK_500KHZ
// NRF905_OUTCLK_1MHZ
// NRF905_OUTCLK_2MHZ
// NRF905_OUTCLK_4MHZ
#define NRF905_OUTCLK NRF905_OUTCLK_DISABLE
// CRC checksum
// NRF905_CRC_DISABLE
// NRF905_CRC_8
// NRF905_CRC_16
#define NRF905_CRC NRF905_CRC_16
// Address size
// Number of bytes for address
// NRF905_ADDR_SIZE_1
// NRF905_ADDR_SIZE_4
#define NRF905_ADDR_SIZE NRF905_ADDR_SIZE_4
// Payload size (1 - 32)
#define NRF905_PAYLOAD_SIZE 32 //NRF905_MAX_PAYLOAD
#endif /* NRF905_CONFIG_H_ */

View File

@@ -0,0 +1,121 @@
/*
* Project: nRF905 AVR/Arduino Library/Driver
* Author: Zak Kemble, contact@zakkemble.co.uk
* Copyright: (C) 2013 by Zak Kemble
* License: GNU GPL v3 (see License.txt)
* Web: http://blog.zakkemble.co.uk/nrf905-avrarduino-librarydriver/
*/
#ifndef NRF905_DEFS_H_
#define NRF905_DEFS_H_
#define AM_IS_USED_HW (!NRF905_AM_SW && defined(AM))
#define POWER_UP() (digitalWrite(PWR_MODE, HIGH))
#define POWER_DOWN() (digitalWrite(PWR_MODE, LOW))
#define DISABLE_STANDBY_MODE() (digitalWrite(TRX_EN, HIGH))
#define ENABLE_STANDBY_MODE() (digitalWrite(TRX_EN, LOW))
#define SPI_SELECT() (digitalWrite(CSN, LOW))
#define SPI_DESELECT() (digitalWrite(CSN, HIGH))
#define RECEIVE_MODE() (digitalWrite(TX_EN, LOW))
#define TRANSMIT_MODE() (digitalWrite(TX_EN, HIGH))
#define spi_transfer(data) (SPI.transfer(data))
//#define spi_transfer_nr(data) (SPI.transfer(data))
// Instructions
#define NRF905_CMD_NOP 0xFF
#define NRF905_CMD_W_CONFIG 0x00
#define NRF905_CMD_R_CONFIG 0x10
#define NRF905_CMD_W_TX_PAYLOAD 0x20
#define NRF905_CMD_R_TX_PAYLOAD 0x21
#define NRF905_CMD_W_TX_ADDRESS 0x22
#define NRF905_CMD_R_TX_ADDRESS 0x23
#define NRF905_CMD_R_RX_PAYLOAD 0x24
#define NRF905_CMD_CHAN_CONFIG 0x80
// Registers
#define NRF905_REG_CHANNEL 0x00
//#define NRF905_REG_AUTO_RETRAN 0x01
//#define NRF905_REG_LOW_RX 0x01
//#define NRF905_REG_PWR 0x01
#define NRF905_REG_BAND 0x01
#define NRF905_REG_CRC 0x09
#define NRF905_REG_CLK 0x09
#define NRF905_REG_OUTCLK 0x09
#define NRF905_REG_OUTCLK_FREQ 0x09
#define NRF905_REG_RX_ADDRESS 0x05
#define NRF905_REG_RX_PAYLOAD_SIZE 0x03
#define NRF905_REG_TX_PAYLOAD_SIZE 0x04
#define NRF905_REG_ADDR_WIDTH 0x02
// Clock options
#define NRF905_CLK_4MHZ 0x00
#define NRF905_CLK_8MHZ 0x08
#define NRF905_CLK_12MHZ 0x10
#define NRF905_CLK_16MHZ 0x18
#define NRF905_CLK_20MHZ 0x20
// Register masks
#define NRF905_MASK_CHANNEL 0xFC
#define NRF905_MASK_AUTO_RETRAN ~(NRF905_AUTO_RETRAN_ENABLE | NRF905_AUTO_RETRAN_DISABLE) //0xDF
#define NRF905_MASK_LOW_RX ~(NRF905_LOW_RX_ENABLE | NRF905_LOW_RX_DISABLE) //0xEF
#define NRF905_MASK_PWR ~(NRF905_PWR_n10 | NRF905_PWR_n2 | NRF905_PWR_6 | NRF905_PWR_10) //0xF3
#define NRF905_MASK_BAND ~(NRF905_BAND_433 | NRF905_BAND_868 | NRF905_BAND_915) //0xFD
#define NRF905_MASK_CRC (uint8_t)(~(NRF905_CRC_DISABLE | NRF905_CRC_8 | NRF905_CRC_16)) //0x3F // typecast to stop compiler moaning about large integer truncation
#define NRF905_MASK_CLK ~(NRF905_CLK_4MHZ | NRF905_CLK_8MHZ | NRF905_CLK_12MHZ | NRF905_CLK_16MHZ | NRF905_CLK_20MHZ) //0xC7
#define NRF905_MASK_OUTCLK ~(NRF905_OUTCLK_DISABLE | NRF905_OUTCLK_4MHZ | NRF905_OUTCLK_2MHZ | NRF905_OUTCLK_1MHZ | NRF905_OUTCLK_500KHZ) // 0xF8
// Bit positions
#define NRF905_STATUS_DR 5
#define NRF905_STATUS_AM 7
#include "nRF905_config.h"
#if (NRF905_DR_SW && NRF905_INTERRUPTS)
#error "NRF905_INTERRUPTS and NRF905_DR_SW can not both be enabled"
#endif
// Workout channel from frequency & band
#define NRF905_CALC_CHANNEL(f, b) ((((f) / (1 + (b>>1))) - 422400000UL) / 100000UL)
#define CONCAT(a, b) a ## b
#define CONCAT2(a, b, c) a ## b ## c
#define INTCONCAT(num) CONCAT(INT, num)
#define ISCCONCAT(num, bit) CONCAT2(ISC, num, bit)
#define INTVECTCONCAT(num) CONCAT2(INT, num, _vect)
#ifndef REG_EXTERNAL_INT
#ifdef EIMSK
#define REG_EXTERNAL_INT EIMSK
#elif defined GICR
#define REG_EXTERNAL_INT GICR
#else
#define REG_EXTERNAL_INT GIMSK
#endif
#endif
#ifndef REG_EXTERNAL_INT_CTL
#ifdef EICRA
#if INTERRUPT_NUM < 4
#define REG_EXTERNAL_INT_CTL EICRA
#else
#define REG_EXTERNAL_INT_CTL EICRB
#endif
#else
#define REG_EXTERNAL_INT_CTL MCUCR
#endif
#endif
#ifndef BIT_EXTERNAL_INT
#define BIT_EXTERNAL_INT INTCONCAT(INTERRUPT_NUM)
#endif
#ifndef BIT_EXTERNAL_INT_CTL
#define BIT_EXTERNAL_INT_CTL (_BV(ISCCONCAT(INTERRUPT_NUM, 1))|_BV(ISCCONCAT(INTERRUPT_NUM, 0)))
#endif
#ifndef INT_VECTOR
#define INT_VECTOR INTVECTCONCAT(INTERRUPT_NUM)
#endif
#endif /* NRF905_DEFS_H_ */

View File

@@ -0,0 +1,23 @@
/*
* Project: nRF905 AVR/Arduino Library/Driver
* Author: Zak Kemble, contact@zakkemble.co.uk
* Copyright: (C) 2013 by Zak Kemble
* License: GNU GPL v3 (see License.txt)
* Web: http://blog.zakkemble.co.uk/nrf905-avrarduino-librarydriver/
*/
#ifndef NRF905_TYPES_H_
#define NRF905_TYPES_H_
#ifndef ARDUINO
#include <stdbool.h>
#endif
#include "nRF905_config.h"
/*
typedef struct {
uint8_t len;
uint8_t dstAddress[NRF905_ADDR_SIZE];
uint8_t buffer[64];
} nrf905_packet_s;
*/
#endif /* NRF905_TYPES_H_ */

20
platformio.ini Normal file
View File

@@ -0,0 +1,20 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:upesy_wroom]
platform = espressif32
board = upesy_wroom
framework = arduino
monitor_speed = 115200
build_flags =
-I nRF905_Pluggit_AP300
build_src_filter =
+<*>
+<../nRF905_Pluggit_AP300/*.cpp>

370
src/main.cpp Normal file
View File

@@ -0,0 +1,370 @@
#include <Arduino.h>
#include <SPI.h>
#include "../nRF905_Pluggit_AP300/nRF905.h"
/*
* nRF905 Pin Configuration for ESP32
*
* SPI Pins (Hardware SPI):
* - MOSI: GPIO23
* - MISO: GPIO19
* - SCK: GPIO18
* - CSN: GPIO5 (Chip Select)
*
* Control Pins:
* - PWR_MODE: GPIO4 (Power control)
* - TRX_EN: GPIO16 (TX/RX Enable)
* - TX_EN: GPIO17 (TX/RX Mode select)
*
* Optional Pins (configured in nRF905_config.h):
* - DR: GPIO26 (Data Ready - for interrupts)
* - CD: GPIO27 (Carrier Detect - for collision avoidance)
*/
// Statistics
uint32_t lastPacketTime = 0;
uint32_t packetCount = 0;
uint32_t pollCount = 0;
bool initialized = false;
void setup() {
// Initialize Serial communication
Serial.begin(115200);
delay(1000);
Serial.println("\n\n========================================");
Serial.println(" nRF905 ESP32 Test & Receiver");
Serial.println("========================================\n");
// Step 1: Initialize nRF905
Serial.println("[1/4] Initializing nRF905...");
Serial.println(" Pins configured:");
Serial.println(" MOSI: GPIO23, MISO: GPIO19, SCK: GPIO18");
Serial.println(" CSN: GPIO5");
Serial.println(" PWR: GPIO4, CE: GPIO16, TXE: GPIO17");
Serial.println(" DR: GPIO26 (Data Ready)");
// Configure GPIO pins BEFORE calling nRF905_init()
pinMode(4, OUTPUT); // PWR_MODE
pinMode(16, OUTPUT); // TRX_EN
pinMode(17, OUTPUT); // TX_EN
pinMode(5, OUTPUT); // CSN
pinMode(26, INPUT); // DR (Data Ready)
pinMode(27, INPUT); // CD (Carrier Detect)
digitalWrite(5, HIGH); // CSN high
nRF905_init();
delay(100);
Serial.println(" ✓ nRF905 initialized");
// Step 2: Test SPI communication by reading config registers
Serial.println("\n[2/4] Testing SPI communication...");
bool spiOk = false;
for (int reg = 0; reg < 10; reg++) {
uint8_t value = nRF905_getConfigReg(reg);
Serial.print(" Config Reg[");
Serial.print(reg);
Serial.print("]: 0x");
if (value < 0x10) Serial.print("0");
Serial.println(value, HEX);
// Check if we're reading something (not all 0x00 or all 0xFF)
if (value != 0x00 && value != 0xFF) {
spiOk = true;
}
}
if (spiOk) {
Serial.println(" ✓ SPI communication working!");
initialized = true;
} else {
Serial.println(" ✗ SPI communication FAILED!");
Serial.println(" Check wiring, especially:");
Serial.println(" - MOSI, MISO, SCK, CSN connections");
Serial.println(" - Power (3.3V) and Ground");
Serial.println(" - PWR_MODE, TRX_EN, TX_EN control pins");
}
if (!initialized) {
Serial.println("\n*** INITIALIZATION FAILED ***");
Serial.println("System halted. Check wiring and reset.");
while (true) delay(1000);
}
// Step 3: Configure nRF905 for Pluggit AP300 (868 MHz)
// Using exact configuration from working AP300 code
Serial.println("\n[3/4] Configuring nRF905...");
// Set control register 0 - CHANNEL (0x76 = 868.4 MHz for 868 band)
nRF905_setConfigReg0(0x76);
Serial.println(" ✓ Channel: 0x76 (868.4 MHz)");
// Set control register 1 - Band, Power, Auto-retransmit, Low RX
// 0x0E = 868MHz band, 10dBm power, no auto-retransmit, normal RX
nRF905_setConfigReg1(0x0E);
Serial.println(" ✓ Config Reg1: 0x0E (868MHz, 10dBm)");
// Set control register 2 - Address width
// 0x44 = 4 bytes TX address, 4 bytes RX address
nRF905_setConfigReg2(0x44);
Serial.println(" ✓ Config Reg2: 0x44 (4-byte addresses)");
// Set payload size to 32 bytes (0x20)
nRF905_setPayloadSizes(0x20);
Serial.println(" ✓ Payload size: 32 bytes");
// Set RX and TX addresses (Pluggit AP300: 0x00, 0x00, 0x07, 0x7A)
uint8_t rxAddr[4] = {0x00, 0x00, 0x07, 0x7A};
nRF905_setTXAddress(rxAddr);
nRF905_setRXAddress(rxAddr);
Serial.print(" ✓ RX/TX Address: ");
for (int i = 0; i < 4; i++) {
if (rxAddr[i] < 0x10) Serial.print("0");
Serial.print(rxAddr[i], HEX);
if (i < 3) Serial.print(" ");
}
Serial.println();
// Set control register 9 - CRC and clock settings
// 0xDB = 16-bit CRC, 16MHz crystal, clock output disabled
nRF905_setConfigReg9(0xDB);
Serial.println(" ✓ Config Reg9: 0xDB (16-bit CRC, 16MHz XTAL)");
// Flush receive buffer to clear any old data
nRF905_flushRecBuffer();
Serial.println(" ✓ RX buffer flushed");
// Verify configuration by reading back registers
Serial.println("\n Configuration verification:");
Serial.print(" Reg0 (Channel): 0x");
Serial.println(nRF905_getConfigReg(0), HEX);
Serial.print(" Reg1 (Band/Pwr): 0x");
Serial.println(nRF905_getConfigReg(1), HEX);
Serial.print(" Reg9 (CRC/CLK): 0x");
Serial.println(nRF905_getConfigReg(9), HEX);
// Step 4: Enter receive mode
Serial.println("\n[4/4] Starting receive mode...");
// Show initial pin states
Serial.print(" Initial pins - PWR:");
Serial.print(digitalRead(4));
Serial.print(" CE:");
Serial.print(digitalRead(16));
Serial.print(" TXE:");
Serial.print(digitalRead(17));
Serial.print(" DR:");
Serial.println(digitalRead(26));
// Power up the radio
nRF905_powerUp();
delay(10);
Serial.println(" ✓ Radio powered up");
// Enter receive mode
nRF905_receive();
delay(10);
Serial.println(" ✓ Receive mode active");
// Show pin states after entering receive mode
Serial.print(" RX mode pins - PWR:");
Serial.print(digitalRead(4));
Serial.print(" CE:");
Serial.print(digitalRead(16));
Serial.print(" TXE:");
Serial.print(digitalRead(17));
Serial.print(" DR:");
Serial.println(digitalRead(26));
// Check radio state
nRF905_radio_state_t state = nRF905_getState();
Serial.print(" Radio state: ");
switch(state) {
case NRF905_RADIO_STATE_POWER_DOWN:
Serial.println("POWER_DOWN");
break;
case NRF905_RADIO_STATE_STANDBY:
Serial.println("STANDBY");
break;
case NRF905_RADIO_STATE_RX:
Serial.println("RX (Receiving)");
break;
case NRF905_RADIO_STATE_RX_END:
Serial.println("RX_END (Data Ready!)");
break;
case NRF905_RADIO_STATE_TX:
Serial.println("TX (Transmitting)");
break;
case NRF905_RADIO_STATE_TX_END:
Serial.println("TX_END");
break;
default:
Serial.println("UNKNOWN");
}
Serial.println("\n========================================");
Serial.println(" Listening for packets...");
Serial.println(" Frequency: 868.4 MHz (Channel 0x76)");
Serial.println(" Address: 0x00 0x00 0x07 0x7A");
Serial.println("========================================\n");
}
void loop() {
if (!initialized) {
delay(1000);
return;
}
// Get current time once per loop iteration
uint32_t now = millis();
// Poll for data with timeout (like the working examples)
static uint32_t lastPollTime = 0;
// Try to get data every 50ms to avoid excessive polling
if (now - lastPollTime > 50) {
lastPollTime = now;
pollCount++;
// Prepare buffer for received data
uint8_t rxData[NRF905_MAX_PAYLOAD];
memset(rxData, 0, NRF905_MAX_PAYLOAD);
// Try to read data (returns 0 on success, 1 if no data available)
uint8_t result = nRF905_getData(rxData, NRF905_MAX_PAYLOAD);
if (result == 0) {
// Data received!
packetCount++;
uint32_t currentTime = millis();
uint32_t timeSinceLastPacket = (lastPacketTime > 0) ? (currentTime - lastPacketTime) : 0;
lastPacketTime = currentTime;
// Print packet header
Serial.println("\n┌─────────────────────────────────────────────");
Serial.print("│ [");
Serial.print(currentTime);
Serial.print("ms] PACKET #");
Serial.print(packetCount);
if (timeSinceLastPacket > 0) {
Serial.print(" | Gap: ");
Serial.print(timeSinceLastPacket);
Serial.print("ms");
}
Serial.println();
// Print HEX data
Serial.print("│ HEX: ");
for (int i = 0; i < NRF905_MAX_PAYLOAD; i++) {
if (rxData[i] < 0x10) Serial.print("0");
Serial.print(rxData[i], HEX);
if (i < NRF905_MAX_PAYLOAD - 1) Serial.print(" ");
if ((i + 1) % 16 == 0 && i < NRF905_MAX_PAYLOAD - 1) {
Serial.println();
Serial.print("");
}
}
Serial.println();
// Try ASCII display (if any printable characters exist)
bool hasAscii = false;
for (int i = 0; i < NRF905_MAX_PAYLOAD; i++) {
if (rxData[i] >= 32 && rxData[i] <= 126) {
hasAscii = true;
break;
}
}
if (hasAscii) {
Serial.print("│ ASCII: ");
for (int i = 0; i < NRF905_MAX_PAYLOAD; i++) {
if (rxData[i] >= 32 && rxData[i] <= 126) {
Serial.print((char)rxData[i]);
} else if (rxData[i] == 0) {
Serial.print("·"); // Middle dot for null
} else {
Serial.print(".");
}
}
Serial.println();
}
// Analyze data patterns
bool allZero = true;
bool allSame = true;
uint8_t firstByte = rxData[0];
for (int i = 0; i < NRF905_MAX_PAYLOAD; i++) {
if (rxData[i] != 0) allZero = false;
if (rxData[i] != firstByte) allSame = false;
}
if (allZero) {
Serial.println("│ [INFO] All zeros - possible empty/idle packet");
} else if (allSame) {
Serial.print("│ [INFO] All bytes same value: 0x");
if (firstByte < 0x10) Serial.print("0");
Serial.println(firstByte, HEX);
}
Serial.println("└─────────────────────────────────────────────\n");
// Return to receive mode after reading data
nRF905_receive();
}
}
// Status update every 5 seconds
static uint32_t lastStatusTime = 0;
if (now - lastStatusTime > 5000) {
lastStatusTime = now;
Serial.print("[STATUS] Uptime: ");
Serial.print(now / 1000);
Serial.print("s | Packets: ");
Serial.print(packetCount);
Serial.print(" | Polls: ");
Serial.print(pollCount);
// Read pin states for debugging
Serial.print(" | Pins[PWR:");
Serial.print(digitalRead(4));
Serial.print(" CE:");
Serial.print(digitalRead(16));
Serial.print(" TXE:");
Serial.print(digitalRead(17));
Serial.print(" DR:");
Serial.print(digitalRead(26));
Serial.print("] | State: ");
nRF905_radio_state_t currentState = nRF905_getStatus();
switch(currentState) {
case NRF905_RADIO_STATE_POWER_DOWN:
Serial.println("POWER_DOWN");
break;
case NRF905_RADIO_STATE_STANDBY:
Serial.println("STANDBY");
break;
case NRF905_RADIO_STATE_RX:
Serial.println("RX (Listening)");
break;
case NRF905_RADIO_STATE_RX_END:
Serial.println("RX_END (Data Ready!)");
break;
case NRF905_RADIO_STATE_TX:
Serial.println("TX");
break;
case NRF905_RADIO_STATE_TX_END:
Serial.println("TX_END");
break;
default:
Serial.println("UNKNOWN");
}
pollCount = 0;
}
// Small delay to prevent excessive CPU usage
delay(1);
}

11
test/README Normal file
View File

@@ -0,0 +1,11 @@
This directory is intended for PlatformIO Test Runner and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PlatformIO Unit Testing:
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html