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