Files
MySensors/Bootloader/MyOtaBootloaderRF24.h
T
ToSa27 1c475da8d0 OTA Bootloader
- including adjustments to  library header files to allow usage across C
(bootloader) and C++ (firmware sketches)
- including definition of new message types for firmware config and
firmware code
2014-07-24 13:37:44 +02:00

254 lines
6.2 KiB
C

#ifndef MyOtaBootloaderRF24_H
#define MyOtaBootloaderRF24_H
#include "MyOtaBootloaderHW.h"
#include "../libraries/MySensors/utility/nRF24L01.h"
#include <stdlib.h>
// hardware-agnostic interface to transceiver
// ******************************************
// static void begin()
// static void address(uint8_t addr)
// static boolean write(uint8_t next, uint8_t* packet, uint8_t length, boolean multicast)
// static bool available(uint8_t* pipe_num)
// static void read(uint8_t* buf, uint8_t pipe)
typedef enum { RF24_PA_MIN = 0,RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX, RF24_PA_ERROR } rf24_pa_dbm_e ;
typedef enum { RF24_1MBPS = 0, RF24_2MBPS, RF24_250KBPS } rf24_datarate_e;
uint64_t pipe0_reading_address; /**< Last address set on pipe 0 for reading. */
static uint8_t read_register(uint8_t reg)
{
csnlow();
SPItransfer( R_REGISTER | ( REGISTER_MASK & reg ) );
uint8_t result = SPItransfer(0xff);
csnhigh();
return result;
}
static uint8_t write_registers(uint8_t reg, const uint8_t* buf, uint8_t len)
{
uint8_t status;
csnlow();
status = SPItransfer( W_REGISTER | ( REGISTER_MASK & reg ) );
while ( len-- )
SPItransfer(*buf++);
csnhigh();
return status;
}
static uint8_t write_register(uint8_t reg, uint8_t value)
{
uint8_t status;
csnlow();
status = SPItransfer( W_REGISTER | ( REGISTER_MASK & reg ) );
SPItransfer(value);
csnhigh();
return status;
}
static uint8_t read_payload(uint8_t* buf, uint8_t data_len)
{
#ifdef UART_DEBUG
uart_puts("-> ");
#endif
uint8_t status;
uint8_t* current = buf;
csnlow();
status = SPItransfer( R_RX_PAYLOAD );
while ( data_len-- ) {
*current = SPItransfer(0xFF);
#ifdef UART_DEBUG
uart_puti(*current);
uart_putc(',');
#endif
current++;
}
csnhigh();
#ifdef UART_DEBUG
uart_putc('\n');
#endif
return status;
}
#define get_status() spiTrans(NOP)
static void powerUp(void)
{
if (!(read_register(CONFIG) & _BV(PWR_UP))){
write_register(CONFIG,read_register(CONFIG) | _BV(PWR_UP));
delaym(5);
}
}
#define convert_64_bit_to_byte_array(value, data) ((*(uint64_t *)(data)) = (uint64_t)(value))
static void startListening(void)
{
powerUp();
write_register(CONFIG, read_register(CONFIG) | _BV(PRIM_RX));
write_register(STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
if (pipe0_reading_address){
uint8_t addressa[8];
convert_64_bit_to_byte_array(pipe0_reading_address, addressa);
write_registers(RX_ADDR_P0, addressa, 5);
}
spiTrans(FLUSH_RX);
spiTrans(FLUSH_TX);
cehigh();
}
static void stopListening(void)
{
celow();
spiTrans(FLUSH_TX);
spiTrans(FLUSH_RX);
write_register(CONFIG, read_register(CONFIG) & ~_BV(PRIM_RX));
}
static void write_payload(const uint8_t* buf, uint8_t data_len, const uint8_t writeType)
{
#ifdef UART_DEBUG
uart_puts("<- ");
#endif
const uint8_t* current = buf;
csnlow();
SPItransfer(writeType);
while ( data_len-- ) {
#ifdef UART_DEBUG
uart_puti(*current);
uart_putc(',');
#endif
SPItransfer(*current++);
}
csnhigh();
#ifdef UART_DEBUG
uart_putc('\n');
#endif
}
static bool writem( const uint8_t* buf, uint8_t len, const bool multicast )
{
write_payload( buf, len, multicast ? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD) ;
cehigh();
celow();
while( ! ( get_status() & ( _BV(TX_DS) | _BV(MAX_RT) ))) { }
uint8_t status = write_register(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
if( status & _BV(MAX_RT)){
spiTrans(FLUSH_TX);
return 0;
}
return 1;
}
static uint8_t getDynamicPayloadSize(void)
{
uint8_t result = 0;
csnlow();
SPItransfer( R_RX_PL_WID );
result = SPItransfer(0xff);
csnhigh();
if(result > 32) {
spiTrans(FLUSH_RX);
return 0;
}
return result;
}
static bool available(uint8_t* pipe_num)
{
if (!(read_register(FIFO_STATUS) & _BV(RX_EMPTY) )){
if (pipe_num) {
uint8_t status = get_status();
*pipe_num = ( status >> RX_P_NO ) & 0b111;
}
return 1;
}
return 0;
}
static void writeAckPayload(uint8_t pipe, const uint8_t* buf, uint8_t len)
{
const uint8_t* current = buf;
uint8_t data_len = len;
csnlow();
SPItransfer(W_ACK_PAYLOAD | ( pipe & 0b111 ) );
while ( data_len-- )
SPItransfer(*current++);
csnhigh();
}
static void read( uint8_t* buf, uint8_t pipe ){
read_payload(buf, getDynamicPayloadSize());
write_register(STATUS,_BV(RX_DR) | _BV(MAX_RT) | _BV(TX_DS));
writeAckPayload(pipe,&pipe, 1 );
}
static void openWritingPipe(uint64_t value)
{
uint8_t valuea[8];
convert_64_bit_to_byte_array(value, valuea);
write_registers(RX_ADDR_P0, valuea, 5);
write_registers(TX_ADDR, valuea, 5);
}
static void openReadingPipe(uint8_t child, uint64_t address)
{
if (child == 0)
pipe0_reading_address = address;
uint8_t addressa[8];
convert_64_bit_to_byte_array(address, addressa);
if ( child < 2 )
write_registers(RX_ADDR_P0 + child, addressa, 5);
write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(ERX_P0 + child));
}
static boolean write(uint8_t next, uint8_t* packet, uint8_t length, boolean multicast) {
powerUp();
stopListening();
openWritingPipe(TO_ADDR(next));
bool ok = writem(packet, length, multicast);
startListening();
return ok;
}
static void address(uint8_t addr)
{
if (addr != BROADCAST_ADDRESS) {
openReadingPipe(WRITE_PIPE, TO_ADDR(addr));
openReadingPipe(CURRENT_NODE_PIPE, TO_ADDR(addr));
}
}
static void begin(void)
{
pipe0_reading_address = 0;
SPIinit();
delaym( 10 ) ;
write_register(SETUP_RETR, 5 << ARD | 15 << ARC);
write_register(EN_AA, 0b00111111 & ~_BV(BROADCAST_PIPE)) ;
write_register(RF_CH, RF24_CHANNEL);
write_register(RF_SETUP, (read_register(RF_SETUP) & 0b11010000) | ((RF24_PA_LEVEL << 1) + 1) | ((RF24_DATARATE & 0b00000010 ) << 4) | ((RF24_DATARATE & 0b00000001 ) << 3));
write_register(CONFIG, read_register(CONFIG) | _BV(CRCO) | _BV(EN_CRC)) ;
write_register(STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT));
csnlow();
SPItransfer(ACTIVATE);
SPItransfer(0x73);
csnhigh();
write_register(FEATURE, read_register(FEATURE) | _BV(EN_ACK_PAY) | _BV(EN_DPL) );
write_register(DYNPD, read_register(DYNPD) | _BV(DPL_P5) | _BV(DPL_P4) | _BV(DPL_P3) | _BV(DPL_P2) | _BV(DPL_P1) | _BV(DPL_P0));
spiTrans(FLUSH_RX);
spiTrans(FLUSH_TX);
powerUp(); //Power up by default when begin() is called
write_register(CONFIG, read_register(CONFIG) & ~_BV(PRIM_RX));
openReadingPipe(BROADCAST_PIPE, TO_ADDR(BROADCAST_ADDRESS));
}
#endif // MyOtaBootloaderRF24_H