mirror of https://github.com/giuliof/nRF24-key.git
278 lines
6.9 KiB
C++
278 lines
6.9 KiB
C++
#include <avr/io.h>
|
|
#include <util/delay.h>
|
|
#include <avr/eeprom.h>
|
|
#include "nRF24L01.h"
|
|
#include "UART.h"
|
|
|
|
static void SPI_Init() {
|
|
// Set DO and SCL as output with pullups
|
|
DDRB |= _BV(PB6); // as output (DO) - data out
|
|
DDRB |= _BV(PB7); // as output (USISCK) - clock
|
|
DDRB &= ~_BV(PB5); // as input (DI) - data in
|
|
PORTB |= _BV(PB5); // pullup on (DI)
|
|
|
|
DDR(PIN_SPI_CS) |= _BV(PIN(PIN_SPI_CS));
|
|
|
|
SPI_CS_HIGH();
|
|
}
|
|
|
|
static uint8_t SPI_ReadWriteByte(uint8_t dat) {
|
|
USIDR = dat;
|
|
|
|
// Clear Overflow Interrupt Flag
|
|
USISR = _BV(USIOIF);
|
|
|
|
// Do this loop 16times
|
|
do {
|
|
// Send clock pulse
|
|
USICR |= _BV(USITC) | _BV(USIWM0) | _BV(USICS1) | _BV(USICLK);
|
|
// 100kHz SPI
|
|
_delay_us(5);
|
|
} while (!(USISR & _BV(USIOIF)));
|
|
|
|
return USIDR;
|
|
}
|
|
|
|
|
|
/* NRF24L01_Read_Reg: read an nRF register content
|
|
* reg: register address
|
|
* Return value: register's content
|
|
*/
|
|
static uint8_t NRF24L01_Read_Reg(uint8_t reg) {
|
|
uint8_t reg_val;
|
|
|
|
SPI_CS_LOW();
|
|
SPI_ReadWriteByte(reg);
|
|
reg_val = SPI_ReadWriteByte(0XFF);
|
|
SPI_CS_HIGH();
|
|
|
|
return reg_val;
|
|
}
|
|
|
|
/* NRF24L01_Write_Reg: write an nRF register
|
|
* reg: register address
|
|
* value: register value
|
|
* Return value: status
|
|
*/
|
|
static uint8_t NRF24L01_Write_Reg(uint8_t reg, uint8_t value) {
|
|
uint8_t status;
|
|
|
|
SPI_CS_LOW();
|
|
status = SPI_ReadWriteByte(reg);
|
|
SPI_ReadWriteByte(value);
|
|
SPI_CS_HIGH();
|
|
|
|
return status;
|
|
}
|
|
|
|
/* NRF24L01_Read_Buf: read specified data length at specified nRF address
|
|
* reg: nRF register location
|
|
* pBuf: data buffer
|
|
* len: data length
|
|
* return value: status register value
|
|
*/
|
|
static uint8_t NRF24L01_Read_Buf(uint8_t reg, uint8_t *pBuf, uint8_t len) {
|
|
uint8_t status;
|
|
|
|
SPI_CS_LOW();
|
|
status = SPI_ReadWriteByte(reg);
|
|
for (uint8_t c = 0; c < len; c++)
|
|
pBuf[c] = SPI_ReadWriteByte(0xFF); // gibberish data
|
|
SPI_CS_HIGH();
|
|
|
|
return status;
|
|
}
|
|
|
|
/* NRF24L01_Write_Buf: write data buffer to certain nRF address
|
|
* reg: nRF register location
|
|
* pBuf: data buffer
|
|
* len: data length
|
|
* return value: status register value
|
|
*/
|
|
static uint8_t NRF24L01_Write_Buf(uint8_t reg, uint8_t *pBuf, uint8_t len) {
|
|
uint8_t status;
|
|
|
|
SPI_CS_LOW();
|
|
_delay_us(5);
|
|
status = SPI_ReadWriteByte(reg);
|
|
for (uint8_t c = 0; c < len; c++) {
|
|
SPI_ReadWriteByte(*pBuf++);
|
|
}
|
|
_delay_us(5);
|
|
SPI_CS_HIGH();
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
// NRF24L01 initialisation
|
|
void NRF24L01_Init() {
|
|
DDR(PIN_24L01_CE) |= _BV(PIN(PIN_24L01_CE));
|
|
DDR(PIN_24L01_IRQ) &= ~_BV(PIN(PIN_24L01_IRQ));
|
|
OUT(PIN_24L01_IRQ) |= _BV(PIN(PIN_24L01_IRQ));
|
|
|
|
SPI_Init();
|
|
|
|
NRF24L01_CE_LOW();
|
|
SPI_CS_HIGH();
|
|
}
|
|
|
|
// Check presence of nRF24 module
|
|
uint8_t NRF24L01_Check() {
|
|
uint8_t buf[5] = {0xA5, 0xA5, 0xA5, 0xA5, 0xA5};
|
|
uint8_t i;
|
|
|
|
NRF24L01_Write_Buf(NRF_WRITE_REG + TX_ADDR, buf, 5);
|
|
NRF24L01_Read_Buf(TX_ADDR, buf, 5);
|
|
for (i = 0; i < 5; i++)
|
|
if (buf[i] != 0xA5)
|
|
break;
|
|
if (i != 5)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
void NRF24L01_SetUp() {
|
|
// Data buffer containing setting read from EEPROM
|
|
uint8_t eebuffer[7];
|
|
|
|
NRF24L01_CE_LOW();
|
|
|
|
eeprom_read_block(eebuffer, (const void*)0, 7);
|
|
for (uint8_t i = 0; i < 7; i++)
|
|
NRF24L01_Write_Reg(NRF_WRITE_REG + CONFIG + i, eebuffer[i]); // Enable CRC, 16-bit wide
|
|
|
|
// Set RX address 0
|
|
eeprom_read_block(eebuffer, (const void*)7, RX_ADR_WIDTH);
|
|
//UART_sendHex(eebuffer, 5);
|
|
NRF24L01_Write_Buf(NRF_WRITE_REG + RX_ADDR_P0, eebuffer, RX_ADR_WIDTH);
|
|
// Set RX address 1
|
|
eeprom_read_block(eebuffer, (const void*)12, RX_ADR_WIDTH);
|
|
//UART_sendHex(eebuffer, 5);
|
|
NRF24L01_Write_Buf(NRF_WRITE_REG + RX_ADDR_P1, eebuffer, RX_ADR_WIDTH);
|
|
// Set RX address 2-5
|
|
eeprom_read_block(eebuffer, (const void*)17, 4);
|
|
//UART_sendHex(eebuffer, 4);
|
|
for (uint8_t i = 0; i < 4; i++)
|
|
NRF24L01_Write_Reg(NRF_WRITE_REG + RX_ADDR_P2 + i, eebuffer[i]);
|
|
|
|
// Set TX address
|
|
eeprom_read_block(eebuffer, (const void*)21, TX_ADR_WIDTH);
|
|
//UART_sendHex(eebuffer, 5);
|
|
NRF24L01_Write_Buf(NRF_WRITE_REG + TX_ADDR, eebuffer, TX_ADR_WIDTH);
|
|
|
|
// Set RX_ADDR_P*
|
|
eeprom_read_block(eebuffer, (const void*)26, 6);
|
|
//UART_sendHex(eebuffer, 6);
|
|
for (uint8_t i = 0; i < 6; i++)
|
|
NRF24L01_Write_Reg(NRF_WRITE_REG + RX_PW_P0 + i, eebuffer[i]);
|
|
|
|
NRF24L01_CE_HIGH();
|
|
}
|
|
|
|
/* NRF24L01_TxPacket: send data packet with nRF24
|
|
* txbuf: address of first byte to send
|
|
* Return value: send completion status
|
|
*/
|
|
uint8_t NRF24L01_TxPacket(uint8_t *txbuf) {
|
|
uint8_t status;
|
|
|
|
NRF24L01_CE_LOW();
|
|
NRF24L01_Write_Buf(WR_TX_PLOAD, txbuf, TX_PLOAD_WIDTH);
|
|
NRF24L01_CE_HIGH();
|
|
|
|
while (NRF24L01_IRQ() != 0)
|
|
;
|
|
|
|
status = NRF24L01_Read_Reg(STATUS);
|
|
NRF24L01_Write_Reg(NRF_WRITE_REG + STATUS, status);
|
|
|
|
// Maximum number of retransmission reached
|
|
if (status & MAX_TX) {
|
|
NRF24L01_Write_Reg(FLUSH_TX, 0xff);
|
|
return MAX_TX;
|
|
}
|
|
|
|
if (status & TX_OK)
|
|
return TX_OK;
|
|
|
|
return 0xff;
|
|
}
|
|
|
|
/* NRF24L01_RxPacket: receive data packet with nRF24
|
|
* rxbuf: address of first byte of receive data buffer
|
|
* Return value: 0 if success, 1 if no data present
|
|
*/
|
|
uint8_t NRF24L01_RxPacket(uint8_t *rxbuf) {
|
|
uint8_t status;
|
|
|
|
status = NRF24L01_Read_Reg(STATUS);
|
|
NRF24L01_Write_Reg(NRF_WRITE_REG + STATUS, status);
|
|
if (status & RX_OK) {
|
|
NRF24L01_Read_Buf(RD_RX_PLOAD, rxbuf, RX_PLOAD_WIDTH);
|
|
NRF24L01_Write_Reg(FLUSH_RX, 0xff);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
void NRF24L01_RX_Mode() {
|
|
uint8_t cfg;
|
|
cfg = NRF24L01_Read_Reg(NRF_READ_REG + CONFIG);
|
|
NRF24L01_CE_LOW();
|
|
NRF24L01_Write_Reg(NRF_WRITE_REG + CONFIG, cfg | _BV(0));
|
|
NRF24L01_CE_HIGH();
|
|
}
|
|
|
|
void NRF24L01_TX_Mode() {
|
|
uint8_t cfg;
|
|
cfg = NRF24L01_Read_Reg(NRF_READ_REG + CONFIG);
|
|
NRF24L01_CE_LOW();
|
|
NRF24L01_Write_Reg(NRF_WRITE_REG + CONFIG, cfg & ~_BV(0));
|
|
NRF24L01_CE_HIGH();
|
|
}
|
|
|
|
void NRF24L01_DumpCfg() {
|
|
uint8_t eebuffer[7];
|
|
|
|
for (uint8_t i = 0; i < 7; i++)
|
|
eebuffer[i] = NRF24L01_Read_Reg(NRF_READ_REG + CONFIG + i); // Enable CRC, 16-bit wide
|
|
UART_sendHex(eebuffer, 7);
|
|
|
|
NRF24L01_Read_Buf(NRF_READ_REG + RX_ADDR_P0, eebuffer, RX_ADR_WIDTH);
|
|
UART_sendHex(eebuffer, 5);
|
|
|
|
NRF24L01_Read_Buf(NRF_READ_REG + RX_ADDR_P1, eebuffer, RX_ADR_WIDTH);
|
|
UART_sendHex(eebuffer, 5);
|
|
|
|
for (uint8_t i = 0; i < 4; i++)
|
|
eebuffer[i] = NRF24L01_Read_Reg(NRF_READ_REG + RX_ADDR_P2 + i);
|
|
UART_sendHex(eebuffer, 4);
|
|
|
|
|
|
NRF24L01_Read_Buf(NRF_READ_REG + TX_ADDR, eebuffer, TX_ADR_WIDTH);
|
|
UART_sendHex(eebuffer, 5);
|
|
|
|
for (uint8_t i = 0; i < 6; i++)
|
|
eebuffer[i] = NRF24L01_Read_Reg(NRF_READ_REG + RX_PW_P0 + i);
|
|
UART_sendHex(eebuffer, 6);
|
|
}
|
|
|
|
void NRF24L01_UpdateCfg() {
|
|
// flush previous data
|
|
while (UART_RXC())
|
|
uint8_t tmp = UDR;
|
|
|
|
for (uint8_t* i = 0; i < (const uint8_t*)32; i++) {
|
|
uint8_t data;
|
|
// send ready to receive
|
|
UDR = (int)i;
|
|
|
|
// wait for data
|
|
while (!UART_RXC())
|
|
;
|
|
|
|
data = UDR;
|
|
eeprom_update_byte(i, data);
|
|
}
|
|
} |