pyrorf/rf24.c
2019-09-06 16:44:33 +02:00

270 lines
7.4 KiB
C

#include "rf24.h"
#include <util/delay.h>
uint8_t PTX=0;
uint8_t rf24_CONFIG = _BV(EN_CRC) | _BV(CRCO);
uint8_t rf24_EN_AA = 0x3F; //ENAA_P0 - ENAA_P5
uint8_t rf24_EN_RXADDR = _BV(ERX_P0)|_BV(ERX_P1);
uint8_t rf24_SETUP_AW = 0x03; // 5 bytes addresses
uint8_t rf24_SETUP_RETR = 0x03;
uint8_t rf24_RF_CH = 0x02; // Channel
uint8_t rf24_RF_SETUP = _BV(RF_DR_HIGH) | _BV(RF_PWR_LOW) | _BV(RF_PWR_HIGH);
uint8_t rf24_FEATURE = 0;
uint8_t rf24_DYNPD= 0;
uint8_t rf24_RX_PW[6] = { 32,32,0,0,0,0 };
void inline rf24_ceHi(){
//CE_PIN_PORT |= _BV(CE_PIN_BIT);
}
void inline rf24_ceLow(){
//CE_PIN_PORT &= ~_BV(CE_PIN_BIT);
}
void inline rf24_csnHi(){
CSN_PIN_PORT |= _BV(CSN_PIN_BIT);
}
void inline rf24_csnLow(){
CSN_PIN_PORT &= ~_BV(CSN_PIN_BIT);
}
void rf24_init()
{
//CE_PIN_DDR |= _BV(CE_PIN_BIT);
CSN_PIN_DDR |= _BV(CSN_PIN_BIT);
rf24_ceLow();
rf24_csnHi();
// Initialize spi module
spi_begin();
_delay_ms(2);
rf24_configure();
}
void inline rf24_transferSync(uint8_t *dataout,uint8_t *datain,uint8_t len){
uint8_t i;
for(i = 0;i < len;i++){
datain[i] = spi_transfer(dataout[i]);
}
}
void inline rf24_transmitSync(uint8_t *dataout,uint8_t len){
uint8_t i;
for(i = 0;i < len;i++){
spi_transfer(dataout[i]);
}
}
void inline rf24_configRegister(uint8_t reg, uint8_t value)
// Clocks only one byte into the given MiRF register
{
rf24_csnLow();
spi_transfer(W_REGISTER | (REGISTER_MASK & reg));
spi_transfer(value);
rf24_csnHi();
}
void inline rf24_readRegister(uint8_t reg, uint8_t * value, uint8_t len)
// Reads an array of bytes from the given start position in the MiRF registers.
{
rf24_csnLow();
spi_transfer(R_REGISTER | (REGISTER_MASK & reg));
rf24_transferSync(value,value,len);
rf24_csnHi();
}
void inline rf24_writeRegister(uint8_t reg, uint8_t * value, uint8_t len)
// Writes an array of bytes into inte the MiRF registers.
{
rf24_csnLow();
spi_transfer(W_REGISTER | (REGISTER_MASK & reg));
rf24_transmitSync(value,len);
rf24_csnHi();
}
void rf24_getData(uint8_t * data,uint8_t len)
{
rf24_csnLow(); // Pull down chip select
spi_transfer( R_RX_PAYLOAD ); // Send cmd to read rx payload
rf24_transferSync(data,data,len); // Read payload
rf24_csnHi(); // Pull up chip select
// NVI: per product spec, p 67, note c:
// "The RX_DR IRQ is asserted by a new packet arrival event. The procedure
// for handling this interrupt should be: 1) read payload through SPI,
// 2) clear RX_DR IRQ, 3) read FIFO_STATUS to check if there are more
// payloads available in RX FIFO, 4) if there are more data in RX FIFO,
// repeat from step 1)."
// So if we're going to clear RX_DR here, we need to check the RX FIFO
// in the dataReady() function
rf24_configRegister(STATUS,(1<<RX_DR)); // Reset status register
}
uint8_t rf24_getDataDL(uint8_t * data,uint8_t len)
// Reads payload bytes into data array
{
uint8_t to_read;
rf24_csnLow(); // Pull down chip select
spi_transfer( R_RX_PL_WID ); // Send cmd to read rx payload len
to_read = spi_transfer(0); // Read payload
rf24_csnHi(); // Pull up chip select
if(len>to_read && to_read>0 ) len=to_read;
rf24_csnLow(); // Pull down chip select
spi_transfer( R_RX_PAYLOAD ); // Send cmd to read rx payload
rf24_transferSync(data,data,len); // Read payload
if(to_read!=len){
to_read-=len;
while((to_read--)>0) // read remaining
spi_transfer(0);
}
rf24_csnHi(); // Pull up chip select
// NVI: per product spec, p 67, note c:
// "The RX_DR IRQ is asserted by a new packet arrival event. The procedure
// for handling this interrupt should be: 1) read payload through SPI,
// 2) clear RX_DR IRQ, 3) read FIFO_STATUS to check if there are more
// payloads available in RX FIFO, 4) if there are more data in RX FIFO,
// repeat from step 1)."
// So if we're going to clear RX_DR here, we need to check the RX FIFO
// in the dataReady() function
rf24_configRegister(STATUS,(1<<RX_DR)); // Reset status register
return to_read;
}
uint8_t inline rf24_dataReady()
// Checks if data is available for reading
{
// See note in getData() function - just checking RX_DR isn't good enough
uint8_t status = rf24_getStatus();
// We can short circuit on RX_DR, but if it's not set, we still need
// to check the FIFO for any pending packets
if ( status & (1 << RX_DR) ) return 1;
return !rf24_rxFifoEmpty();
}
uint8_t inline rf24_rxFifoEmpty(){
uint8_t fifoStatus;
rf24_readRegister(FIFO_STATUS,&fifoStatus,sizeof(fifoStatus));
return (fifoStatus & (1 << RX_EMPTY));
}
void rf24_send(uint8_t * value,uint8_t len)
// Sends a data package to the default address. Be sure to send the correct
// amount of bytes as configured as payload on the receiver.
{
uint8_t status;
status = rf24_getStatus();
if((status & ((1 << TX_DS) | (1 << MAX_RT)))){
rf24_configRegister(STATUS,(1 << TX_DS) | (1 << MAX_RT));
}
rf24_ceLow();
rf24_powerUpTx(); // Set to transmitter mode , Power up
rf24_csnLow(); // Pull down chip select
spi_transfer( FLUSH_TX ); // Write cmd to flush tx fifo
rf24_csnHi(); // Pull up chip select
rf24_csnLow(); // Pull down chip select
spi_transfer( W_TX_PAYLOAD ); // Write cmd to write payload
rf24_transmitSync(value,len); // Write payload
rf24_csnHi(); // Pull up chip select
rf24_ceHi(); // Start transmission
}
uint8_t inline rf24_isSending(){
uint8_t status;
if(PTX){
status = rf24_getStatus();
/*
* if sending successful (TX_DS) or max retries exceded (MAX_RT).
*/
if((status & ((1 << TX_DS) | (1 << MAX_RT)))){
return 0;
}
return 1;
}
return 0;
}
uint8_t inline rf24_getStatus(){
uint8_t rv;
rf24_csnLow();
rv=spi_transfer(NOP);
rf24_csnHi();
return rv;
}
void inline rf24_powerUpRx(){
PTX = 0;
rf24_ceLow();
rf24_configRegister(CONFIG, rf24_CONFIG | ( (1<<PWR_UP) | (1<<PRIM_RX) ) );
rf24_ceHi();
rf24_configRegister(STATUS,(1 << TX_DS) | (1 << MAX_RT));
}
void inline rf24_flushRx(){
rf24_csnLow();
spi_transfer( FLUSH_RX );
rf24_csnHi();
}
void inline rf24_powerUpTx(){
PTX = 1;
rf24_configRegister(CONFIG, rf24_CONFIG | ( (1<<PWR_UP) | (0<<PRIM_RX) ) );
}
void inline rf24_powerDown(){
rf24_ceLow();
rf24_configRegister(CONFIG, rf24_CONFIG );
}
void rf24_configure(){
uint8_t data;
rf24_configRegister(CONFIG,rf24_CONFIG);
rf24_configRegister(FEATURE,rf24_FEATURE);
// Check Feature register ...
rf24_readRegister(FEATURE,&data,1);
if(rf24_FEATURE != data){ // ACTIVATE & retry
rf24_csnLow();
spi_transfer(ACTIVATE);
spi_transfer(0x73);
rf24_csnHi();
rf24_configRegister(FEATURE,rf24_FEATURE);
}
rf24_configRegister(EN_AA,rf24_EN_AA);
rf24_configRegister(EN_RXADDR,rf24_EN_RXADDR);
rf24_configRegister(SETUP_AW,rf24_SETUP_AW);
rf24_configRegister(SETUP_RETR,rf24_SETUP_RETR);
rf24_configRegister(RF_CH,rf24_RF_CH);
rf24_configRegister(RF_SETUP,rf24_RF_SETUP);
rf24_configRegister(DYNPD,rf24_DYNPD);
for(int i=0; i<6;i++)
rf24_configRegister(RX_PW_P0+i,rf24_RX_PW[i]);
}