parent
e738c1e3a8
commit
6c4c5fb1fd
@ -0,0 +1,15 @@ |
||||
//
|
||||
// Created by MightyPork on 2018/04/03.
|
||||
//
|
||||
|
||||
#ifndef GEX_NRF_CRC32_H |
||||
#define GEX_NRF_CRC32_H |
||||
|
||||
uint32_t CRC32_Start(void); |
||||
|
||||
uint32_t CRC32_Add(uint32_t cksum, uint8_t byte); |
||||
|
||||
uint32_t CRC32_End(uint32_t cksum); |
||||
|
||||
|
||||
#endif //GEX_NRF_CRC32_H
|
@ -0,0 +1,157 @@ |
||||
//
|
||||
// Created by MightyPork on 2018/04/02.
|
||||
//
|
||||
|
||||
#ifndef GEX_NRF_NRF_H |
||||
#define GEX_NRF_NRF_H |
||||
|
||||
/*
|
||||
* nordic.h |
||||
* |
||||
* Created:12/16/2013 3:36:04 PM |
||||
* Author: Tom |
||||
* |
||||
* NRF24L01+ Library II |
||||
* |
||||
*/ |
||||
|
||||
|
||||
#ifndef NORDIC_H_ |
||||
#define NORDIC_H_ |
||||
|
||||
#include "main.h" |
||||
|
||||
// Initialize SPI and the Nordic
|
||||
|
||||
/**
|
||||
* Initialize the NRF module |
||||
* |
||||
* @param pSpeed |
||||
*/ |
||||
void NRF_Init(uint8_t pSpeed); |
||||
|
||||
#define NRF_SPEED_500k 0b00100110 |
||||
#define NRF_SPEED_2M 0b00001110 |
||||
#define NRF_SPEED_1M 0b00000110 |
||||
|
||||
/**
|
||||
* Set reception address |
||||
* @param pipenum - pipe to set |
||||
* @param AddrByte - byte 0 |
||||
*/ |
||||
void NRF_SetRxAddress(uint8_t pipenum, uint8_t AddrByte); |
||||
|
||||
/**
|
||||
* Set communication channel |
||||
*/ |
||||
void NRF_SetChannel(uint8_t Ch) ; // 0 through 83 only!
|
||||
|
||||
/**
|
||||
* Power down the transceiver |
||||
*/ |
||||
void NRF_PowerDown(void); |
||||
|
||||
/**
|
||||
* Selecr RX mode |
||||
*/ |
||||
void NRF_ModeRX(void); |
||||
|
||||
/**
|
||||
* Select TX mode |
||||
*/ |
||||
void NRF_ModeTX(void); |
||||
|
||||
/**
|
||||
* @return NRF is power down |
||||
*/ |
||||
uint8_t NRF_IsModePowerDown(void); |
||||
|
||||
/**
|
||||
* @return NRF in TX mode |
||||
*/ |
||||
uint8_t NRF_IsModeTX(void); |
||||
|
||||
/**
|
||||
* @return NRF in RX mode |
||||
*/ |
||||
uint8_t NRF_IsModeRx(void); |
||||
|
||||
/**
|
||||
* Add a pipe to the next free slot |
||||
* |
||||
* @param AddrByte - address byte of the peer |
||||
* @param[out] PipeNum - pipe number is written here |
||||
* @return success |
||||
*/ |
||||
bool NRF_AddPipe(uint8_t AddrByte, uint8_t *PipeNum); |
||||
|
||||
/**
|
||||
* Convert pipe number to address byte |
||||
* |
||||
* @param pipe_num - pipe number |
||||
* @return address byte |
||||
*/ |
||||
uint8_t NRF_PipeNum2Addr(uint8_t pipe_num); |
||||
|
||||
/**
|
||||
* Convert address to a pipe number |
||||
* |
||||
* @param addr |
||||
* @return |
||||
*/ |
||||
uint8_t NRF_Addr2PipeNum(uint8_t addr); |
||||
|
||||
/**
|
||||
* Reset as much as possible (incl. removing pipes) |
||||
*/ |
||||
void NRF_Reset(void); |
||||
|
||||
/**
|
||||
* Send a packet (takes care of mode switching etc) |
||||
* |
||||
* @param PipeNum - pipe number |
||||
* @param Packet - packet bytes |
||||
* @param Length - packet length |
||||
* @return success (ACK'd) |
||||
*/ |
||||
bool NRF_SendPacket(uint8_t PipeNum, const uint8_t *Packet, uint8_t Length); |
||||
|
||||
/**
|
||||
* Receive a packet |
||||
* |
||||
* @param[out] Packet - the receiuved packet - buffer that is written |
||||
* @param[out] PipeNum - pipe number that was received from |
||||
* @return packet size, 0 on failure |
||||
*/ |
||||
uint8_t NRF_ReceivePacket(uint8_t *Packet, uint8_t *PipeNum); |
||||
|
||||
/**
|
||||
* Set base address |
||||
* @param Bytes4 |
||||
*/ |
||||
void NRF_SetBaseAddress(const uint8_t *Bytes4); |
||||
|
||||
/**
|
||||
* Check if there's a packet to be read |
||||
* |
||||
* @return 1 if any to read |
||||
*/ |
||||
bool NRF_IsRxPacket(void); |
||||
|
||||
/**
|
||||
* Enable a pipe |
||||
* |
||||
* @param pipenum - pipe number 0-5 |
||||
*/ |
||||
void NRF_EnablePipe(uint8_t pipenum); |
||||
|
||||
/**
|
||||
* Disable a pipe |
||||
* |
||||
* @param pipenum - pipe number 0-5 |
||||
*/ |
||||
void NRF_DisablePipe(uint8_t pipenum); |
||||
|
||||
#endif /* NORDIC_H_ */ |
||||
|
||||
#endif //GEX_NRF_NRF_H
|
@ -0,0 +1,67 @@ |
||||
//
|
||||
// Created by MightyPork on 2018/04/03.
|
||||
//
|
||||
|
||||
#include "main.h" |
||||
#include "crc32.h" |
||||
|
||||
static const uint32_t crc32_table[] = { /* CRC polynomial 0xedb88320 */ |
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, |
||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, |
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, |
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, |
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, |
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, |
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, |
||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, |
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, |
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, |
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, |
||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, |
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, |
||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, |
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, |
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, |
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, |
||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, |
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, |
||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, |
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, |
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, |
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, |
||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, |
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, |
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, |
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, |
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, |
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, |
||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, |
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, |
||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, |
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, |
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, |
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, |
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, |
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, |
||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, |
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, |
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, |
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, |
||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, |
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d |
||||
}; |
||||
|
||||
uint32_t CRC32_Start(void) |
||||
{ |
||||
return (uint32_t) 0xFFFFFFFF; |
||||
} |
||||
|
||||
uint32_t CRC32_Add(uint32_t cksum, uint8_t byte) |
||||
{ |
||||
return crc32_table[((cksum) ^ ((uint8_t) byte)) & 0xff] ^ ((cksum) >> 8); |
||||
} |
||||
|
||||
uint32_t CRC32_End(uint32_t cksum) |
||||
{ |
||||
return (uint32_t) ~cksum; |
||||
} |
@ -0,0 +1,470 @@ |
||||
//
|
||||
// Created by MightyPork on 2018/04/02.
|
||||
//
|
||||
|
||||
#include <string.h> |
||||
#include "nrf.h" |
||||
#include "main.h" |
||||
#include "debug.h" |
||||
|
||||
/**
|
||||
* Read a register |
||||
* |
||||
* @param reg - register number (max 83) |
||||
* @return register value |
||||
*/ |
||||
static uint8_t NRF_ReadRegister(uint8_t reg); |
||||
|
||||
/**
|
||||
* Write a register |
||||
* |
||||
* @param reg - register number (max 83) |
||||
* @param value - register value |
||||
* @return status register value |
||||
*/ |
||||
static uint8_t NRF_WriteRegister(uint8_t reg, uint8_t value); |
||||
|
||||
// Internal use
|
||||
static uint8_t NRF_WriteBuffer(uint8_t reg, const uint8_t *pBuf, uint8_t bytes); |
||||
|
||||
static uint8_t NRF_ReadBuffer(uint8_t reg, uint8_t *pBuf, uint8_t bytes); |
||||
|
||||
/**
|
||||
* Set TX address for next frame |
||||
* |
||||
* @param SendTo - addr |
||||
*/ |
||||
static void NRF_SetTxAddress(uint8_t ToAddr); |
||||
|
||||
//----------------------------------------------------------
|
||||
|
||||
/** Tight asm loop */ |
||||
#define __asm_loop(cycles) \ |
||||
do { \
|
||||
register uint32_t _count asm ("r4") = cycles; \
|
||||
asm volatile( \
|
||||
".syntax unified\n" \
|
||||
".thumb\n" \
|
||||
"0:" \
|
||||
"subs %0, #1\n" \
|
||||
"bne 0b\n" \
|
||||
: "+r" (_count)); \
|
||||
} while(0) |
||||
|
||||
// inaccurate!
|
||||
#define _delay_us(n) __asm_loop((n)*12) |
||||
|
||||
static inline void CE(bool level) { |
||||
if (level) LL_GPIO_SetOutputPin(NRF_CE_GPIO_Port, NRF_CE_Pin); |
||||
else LL_GPIO_ResetOutputPin(NRF_CE_GPIO_Port, NRF_CE_Pin); |
||||
} |
||||
|
||||
static inline void NSS(bool level) { |
||||
if (level) LL_GPIO_SetOutputPin(NRF_NSS_GPIO_Port, NRF_NSS_Pin); |
||||
else LL_GPIO_ResetOutputPin(NRF_NSS_GPIO_Port, NRF_NSS_Pin); |
||||
} |
||||
|
||||
static uint8_t spi(uint8_t tx) { |
||||
while (! LL_SPI_IsActiveFlag_TXE(SPI1)); |
||||
LL_SPI_TransmitData8(SPI1, tx); |
||||
|
||||
while (! LL_SPI_IsActiveFlag_RXNE(SPI1)); |
||||
return LL_SPI_ReceiveData8(SPI1); |
||||
} |
||||
|
||||
//-------
|
||||
|
||||
/*
|
||||
* from: http://barefootelectronics.com/NRF24L01.aspx
|
||||
*/ |
||||
|
||||
#define CMD_READ_REG 0x00 // Read command to register
|
||||
#define CMD_WRITE_REG 0x20 // Write command to register
|
||||
#define CMD_RD_RX_PLD 0x61 // Read RX payload register address
|
||||
#define CMD_WR_TX_PLD 0xA0 // Write TX payload register address
|
||||
#define CMD_FLUSH_TX 0xE1 // Flush TX register command
|
||||
#define CMD_FLUSH_RX 0xE2 // Flush RX register command
|
||||
#define CMD_REUSE_TX_PL 0xE3 // Reuse TX payload register command
|
||||
#define CMD_RD_RX_PL_WIDTH 0x60 // Read RX Payload Width
|
||||
#define CMD_WR_ACK_PLD 0xA8 // Write ACK payload for Pipe (Add pipe number 0-6)
|
||||
#define CMD_WR_TX_PLD_NK 0xB0 // Write ACK payload for not ack
|
||||
#define CMD_NOP 0xFF // No Operation, might be used to read status register
|
||||
|
||||
// SPI(nRF24L01) registers(addresses)
|
||||
#define RG_CONFIG 0x00 // 'Config' register address
|
||||
#define RG_EN_AA 0x01 // 'Enable Auto Acknowledgment' register address
|
||||
#define RG_EN_RXADDR 0x02 // 'Enabled RX addresses' register address
|
||||
#define RG_SETUP_AW 0x03 // 'Setup address width' register address
|
||||
#define RG_SETUP_RETR 0x04 // 'Setup Auto. Retrans' register address
|
||||
#define RG_RF_CH 0x05 // 'RF channel' register address
|
||||
#define RG_RF_SETUP 0x06 // 'RF setup' register address
|
||||
#define RG_STATUS 0x07 // 'Status' register address
|
||||
#define RG_OBSERVE_TX 0x08 // 'Observe TX' register address
|
||||
#define RG_CD 0x09 // 'Carrier Detect' register address
|
||||
#define RG_RX_ADDR_P0 0x0A // 'RX address pipe0' register address
|
||||
#define RG_RX_ADDR_P1 0x0B // 'RX address pipe1' register address
|
||||
#define RG_RX_ADDR_P2 0x0C // 'RX address pipe2' register address
|
||||
#define RG_RX_ADDR_P3 0x0D // 'RX address pipe3' register address
|
||||
#define RG_RX_ADDR_P4 0x0E // 'RX address pipe4' register address
|
||||
#define RG_RX_ADDR_P5 0x0F // 'RX address pipe5' register address
|
||||
#define RG_TX_ADDR 0x10 // 'TX address' register address
|
||||
#define RG_RX_PW_P0 0x11 // 'RX payload width, pipe0' register address
|
||||
#define RG_RX_PW_P1 0x12 // 'RX payload width, pipe1' register address
|
||||
#define RG_RX_PW_P2 0x13 // 'RX payload width, pipe2' register address
|
||||
#define RG_RX_PW_P3 0x14 // 'RX payload width, pipe3' register address
|
||||
#define RG_RX_PW_P4 0x15 // 'RX payload width, pipe4' register address
|
||||
#define RG_RX_PW_P5 0x16 // 'RX payload width, pipe5' register address
|
||||
#define RG_FIFO_STATUS 0x17 // 'FIFO Status Register' register address
|
||||
#define RG_DYNPD 0x1C // 'Enable dynamic payload length
|
||||
#define RG_FEATURE 0x1D // 'Feature register
|
||||
|
||||
#define RD_STATUS_TX_FULL 0x01 // tx queue full
|
||||
#define RD_STATUS_RX_PNO 0x0E // pipe number of the received payload
|
||||
#define RD_STATUS_MAX_RT 0x10 // max retransmissions
|
||||
#define RD_STATUS_TX_DS 0x20 // data sent
|
||||
#define RD_STATUS_RX_DR 0x40 // data ready
|
||||
|
||||
#define RD_CONFIG_PRIM_RX 0x01 // is primary receiver
|
||||
#define RD_CONFIG_PWR_UP 0x02 // power up
|
||||
#define RD_CONFIG_CRCO 0x04 // 2-byte CRC
|
||||
#define RD_CONFIG_EN_CRC 0x08 // enable CRC
|
||||
#define RD_CONFIG_DISABLE_IRQ_MAX_RT 0x10 |
||||
#define RD_CONFIG_DISABLE_IRQ_TX_DS 0x20 |
||||
#define RD_CONFIG_DISABLE_IRQ_RX_DR 0x40 |
||||
|
||||
// Config register bits (excluding the bottom two that are changed dynamically)
|
||||
// enable only Rx IRQ
|
||||
#define ModeBits (RD_CONFIG_DISABLE_IRQ_MAX_RT | \ |
||||
RD_CONFIG_DISABLE_IRQ_TX_DS | \
|
||||
RD_CONFIG_EN_CRC | \
|
||||
RD_CONFIG_CRCO) |
||||
|
||||
#define CEHIGH CE(1) |
||||
#define CELOW CE(0) |
||||
|
||||
static inline uint8_t CS(uint8_t hl) |
||||
{ |
||||
if (hl == 1) { |
||||
NSS(0); |
||||
} |
||||
else { |
||||
NSS(1); |
||||
} |
||||
return hl; |
||||
} |
||||
|
||||
#define CHIPSELECT for (uint8_t cs = CS(1); cs==1; cs = CS(0)) |
||||
|
||||
// Base NRF address - byte 4 may be modified before writing to a pipe register,
|
||||
// the first 4 bytes are shared in the network. Master is always code 0.
|
||||
static uint8_t nrf_base_address[5]; |
||||
|
||||
static uint8_t nrf_pipe_addr[6]; |
||||
static bool nrf_pipe_enabled[6]; |
||||
|
||||
static uint8_t NRF_WriteRegister(uint8_t reg, uint8_t value) |
||||
{ |
||||
uint8_t status = 0; |
||||
CHIPSELECT { |
||||
status = spi(CMD_WRITE_REG | reg); |
||||
spi(value); |
||||
} |
||||
return status; |
||||
} |
||||
|
||||
static uint8_t NRF_ReadRegister(uint8_t reg) |
||||
{ |
||||
uint8_t reg_val = 0; |
||||
CHIPSELECT { |
||||
spi(CMD_READ_REG | reg); |
||||
reg_val = spi(0); |
||||
} |
||||
return reg_val; |
||||
} |
||||
|
||||
static uint8_t NRF_ReadStatus(void) |
||||
{ |
||||
uint8_t reg_val = 0; |
||||
CHIPSELECT { |
||||
reg_val = spi(CMD_NOP); |
||||
} |
||||
return reg_val; |
||||
} |
||||
|
||||
static uint8_t NRF_WriteBuffer(uint8_t reg, const uint8_t *pBuf, uint8_t bytes) |
||||
{ |
||||
uint8_t status = 0, i = 0; |
||||
CHIPSELECT { |
||||
status = spi(CMD_WRITE_REG | reg); |
||||
for (i = 0; i < bytes; i++) { |
||||
spi(*pBuf++); |
||||
} |
||||
} |
||||
return status; |
||||
} |
||||
|
||||
static uint8_t NRF_ReadBuffer(uint8_t reg, uint8_t *pBuf, uint8_t bytes) |
||||
{ |
||||
uint8_t status = 0, i; |
||||
CHIPSELECT { |
||||
status = spi(CMD_READ_REG | reg); |
||||
for (i = 0; i < bytes; i++) { |
||||
pBuf[i] = spi(0); |
||||
} |
||||
} |
||||
return status; |
||||
} |
||||
|
||||
void NRF_SetBaseAddress(const uint8_t *Bytes4) |
||||
{ |
||||
memcpy(nrf_base_address, Bytes4, 4); |
||||
nrf_base_address[4] = 0; |
||||
} |
||||
|
||||
void NRF_SetRxAddress(uint8_t pipenum, uint8_t AddrByte) |
||||
{ |
||||
if (pipenum > 5) { |
||||
dbg("!! bad pipe %d", pipenum); |
||||
return; |
||||
} |
||||
|
||||
nrf_base_address[4] = AddrByte; |
||||
|
||||
nrf_pipe_addr[pipenum] = AddrByte; |
||||
|
||||
if (pipenum == 0) { |
||||
NRF_WriteBuffer(RG_RX_ADDR_P0, nrf_base_address, 5); |
||||
} |
||||
else if (pipenum == 1) { |
||||
NRF_WriteBuffer(RG_RX_ADDR_P1, nrf_base_address, 5); |
||||
} |
||||
else { |
||||
NRF_WriteRegister(RG_RX_ADDR_P2 + (pipenum - 2), AddrByte); |
||||
} |
||||
} |
||||
|
||||
bool NRF_AddPipe(uint8_t AddrByte, uint8_t *PipeNum) |
||||
{ |
||||
for (uint8_t i = 0; i < 6; i++) { |
||||
if(!nrf_pipe_enabled[i]) { |
||||
NRF_SetRxAddress(i, AddrByte); |
||||
*PipeNum = i; |
||||
NRF_EnablePipe(i); |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
uint8_t NRF_PipeNum2Addr(uint8_t pipe_num) |
||||
{ |
||||
if (pipe_num > 5) return 0; // fail
|
||||
return nrf_pipe_addr[pipe_num]; |
||||
} |
||||
|
||||
uint8_t NRF_Addr2PipeNum(uint8_t addr) |
||||
{ |
||||
for (int i = 0; i < 6; i++) { |
||||
if (nrf_pipe_addr[i] == addr) return (uint8_t) i; |
||||
} |
||||
return 0xFF; |
||||
} |
||||
|
||||
void NRF_EnablePipe(uint8_t pipenum) |
||||
{ |
||||
uint8_t enabled = NRF_ReadRegister(RG_EN_RXADDR); |
||||
enabled |= 1 << pipenum; |
||||
NRF_WriteRegister(RG_EN_RXADDR, enabled); |
||||
|
||||
nrf_pipe_enabled[pipenum] = 1; |
||||
} |
||||
|
||||
void NRF_DisablePipe(uint8_t pipenum) |
||||
{ |
||||
uint8_t enabled = NRF_ReadRegister(RG_EN_RXADDR); |
||||
enabled &= ~(1 << pipenum); |
||||
NRF_WriteRegister(RG_EN_RXADDR, enabled); |
||||
|
||||
nrf_pipe_enabled[pipenum] = 0; |
||||
} |
||||
|
||||
static void NRF_SetTxAddress(uint8_t SendTo) |
||||
{ |
||||
nrf_base_address[4] = SendTo; |
||||
NRF_WriteBuffer(RG_TX_ADDR, nrf_base_address, 5); |
||||
NRF_WriteBuffer(RG_RX_ADDR_P0, nrf_base_address, 5); // the ACK will come to pipe 0
|
||||
} |
||||
|
||||
void NRF_PowerDown(void) |
||||
{ |
||||
CELOW; |
||||
NRF_WriteRegister(RG_CONFIG, ModeBits); |
||||
} |
||||
|
||||
void NRF_ModeTX(void) |
||||
{ |
||||
CELOW; |
||||
uint8_t m = NRF_ReadRegister(RG_CONFIG); |
||||
NRF_WriteRegister(RG_CONFIG, ModeBits | RD_CONFIG_PWR_UP); |
||||
if ((m & RD_CONFIG_PWR_UP) == 0) LL_mDelay(5); |
||||
} |
||||
|
||||
void NRF_ModeRX(void) |
||||
{ |
||||
NRF_WriteRegister(RG_CONFIG, ModeBits | RD_CONFIG_PWR_UP | RD_CONFIG_PRIM_RX); |
||||
NRF_SetRxAddress(0, nrf_pipe_addr[0]); // set the P0 address - it was changed during Rx for ACK reception
|
||||
CEHIGH; |
||||
|
||||
//if ((m&2)==0) LL_mDelay()(5); You don't need to wait. Just nothing will come for 5ms or more
|
||||
} |
||||
|
||||
uint8_t NRF_IsModePowerDown(void) |
||||
{ |
||||
uint8_t ret = 0; |
||||
if ((NRF_ReadRegister(RG_CONFIG) & RD_CONFIG_PWR_UP) == 0) ret = 1; |
||||
return ret; |
||||
} |
||||
|
||||
uint8_t NRF_IsModeTX(void) |
||||
{ |
||||
uint8_t m = NRF_ReadRegister(RG_CONFIG); |
||||
if ((m & RD_CONFIG_PWR_UP) == 0) return 0; // OFF
|
||||
if ((m & RD_CONFIG_PRIM_RX) == 0) return 1; |
||||
return 0; |
||||
} |
||||
|
||||
uint8_t NRF_IsModeRx(void) |
||||
{ |
||||
uint8_t m = NRF_ReadRegister(RG_CONFIG); |
||||
if ((m & RD_CONFIG_PWR_UP) == 0) return 0; // OFF
|
||||
if ((m & RD_CONFIG_PRIM_RX) == 0) return 0; |
||||
return 1; |
||||
} |
||||
|
||||
void NRF_SetChannel(uint8_t Ch) |
||||
{ |
||||
NRF_WriteRegister(RG_RF_CH, Ch); |
||||
} |
||||
|
||||
uint8_t NRF_ReceivePacket(uint8_t *Packet, uint8_t *PipeNum) |
||||
{ |
||||
uint8_t pw = 0, status; |
||||
if (!NRF_IsRxPacket()) return 0; |
||||
|
||||
CELOW; |
||||
CHIPSELECT { |
||||
status = spi(CMD_RD_RX_PL_WIDTH); |
||||
pw = spi(0); |
||||
} |
||||
|
||||
if (pw > 32) { |
||||
CHIPSELECT { |
||||
spi(CMD_FLUSH_RX); |
||||
} |
||||
NRF_WriteRegister(RG_STATUS, RD_STATUS_RX_DR); |
||||
return 0; |
||||
} |
||||
|
||||
// Read the reception pipe number
|
||||
*PipeNum = (status & RD_STATUS_RX_PNO) >> 1; |
||||
|
||||
CHIPSELECT { |
||||
spi(CMD_RD_RX_PLD); |
||||
for (uint8_t i = 0; i < pw; i++) Packet[i] = spi(0); |
||||
} |
||||
NRF_WriteRegister(RG_STATUS, RD_STATUS_RX_DR); // Clear the RX_DR interrupt
|
||||
CEHIGH; |
||||
return pw; |
||||
} |
||||
|
||||
bool NRF_IsRxPacket(void) |
||||
{ |
||||
uint8_t ret = NRF_ReadRegister(RG_STATUS) & RD_STATUS_RX_DR; |
||||
return 0 != ret; |
||||
} |
||||
|
||||
bool NRF_SendPacket(uint8_t PipeNum, const uint8_t *Packet, uint8_t Length) |
||||
{ |
||||
if (!nrf_pipe_enabled[PipeNum]) { |
||||
dbg("!! Pipe %d not enabled", PipeNum); |
||||
return 0; |
||||
} |
||||
|
||||
const uint8_t orig_conf = NRF_ReadRegister(RG_CONFIG); |
||||
CELOW; |
||||
NRF_ModeTX(); // Make sure in TX mode
|
||||
NRF_SetTxAddress(nrf_pipe_addr[PipeNum]); |
||||
|
||||
CHIPSELECT { |
||||
spi(CMD_FLUSH_TX); |
||||
}; |
||||
|
||||
CHIPSELECT { |
||||
spi(CMD_WR_TX_PLD); |
||||
for (uint8_t i = 0; i < Length; i++) spi(Packet[i]); |
||||
}; |
||||
|
||||
CEHIGH; |
||||
_delay_us(15); // At least 10 us
|
||||
CELOW; |
||||
|
||||
uint8_t st = 0; |
||||
while ((st & (RD_STATUS_MAX_RT|RD_STATUS_TX_DS)) == 0) { |
||||
st = NRF_ReadStatus(); // Packet acked or timed out
|
||||
} |
||||
|
||||
NRF_WriteRegister(RG_STATUS, st & (RD_STATUS_MAX_RT|RD_STATUS_TX_DS)); // Clear the bit
|
||||
|
||||
if ((orig_conf & RD_CONFIG_PWR_UP) == 0) { |
||||
NRF_PowerDown(); |
||||
} |
||||
else if ((orig_conf & RD_CONFIG_PRIM_RX) == RD_CONFIG_PRIM_RX) { |
||||
NRF_ModeRX(); |
||||
} |
||||
|
||||
return 0 != (st & RD_STATUS_TX_DS); // success
|
||||
} |
||||
|
||||
void NRF_Reset(void) |
||||
{ |
||||
NSS(1); |
||||
CELOW; |
||||
NRF_PowerDown(); |
||||
|
||||
NRF_WriteRegister(RG_EN_RXADDR, 0); // disable all pipes
|
||||
|
||||
for (int i = 0; i < 6; i++) { |
||||
nrf_pipe_addr[i] = 0; |
||||
nrf_pipe_enabled[i] = 0; |
||||
} |
||||
} |
||||
|
||||
void NRF_Init(uint8_t pSpeed) |
||||
{ |
||||
// Set the required output pins
|
||||
NSS(1); |
||||
CELOW; |
||||
|
||||
LL_mDelay(200); |
||||
|
||||
NRF_WriteRegister(RG_CONFIG, ModeBits); |
||||
NRF_WriteRegister(RG_SETUP_AW, 0b11); // 5 byte addresses
|
||||
|
||||
// default
|
||||
// NRF_EnablePipe(0);
|
||||
|
||||
NRF_WriteRegister(RG_SETUP_RETR, 0x18); // 8 retries
|
||||
NRF_WriteRegister(RG_RF_CH, 2); // channel 2 NO HIGHER THAN 83 in USA!
|
||||
|
||||
NRF_WriteRegister(RG_RF_SETUP, pSpeed); |
||||
|
||||
NRF_WriteRegister(RG_DYNPD, 0b111111); // Dynamic packet length
|
||||
NRF_WriteRegister(RG_FEATURE, 0b100); // Enable dynamic payload, and no payload in the ack.
|
||||
|
||||
for (int i = 0; i < 6; i++) { |
||||
NRF_WriteRegister(RG_RX_PW_P0+i, 32); // Receive 32 byte packets - XXX this is probably not needed with dynamic length
|
||||
} |
||||
|
||||
//NRFModePowerDown(); // Already in power down mode, dummy
|
||||
} |
Loading…
Reference in new issue