From: Wintermute Date: Mon, 14 Oct 2013 19:35:33 +0000 (+0200) Subject: Teile des r0ket-nrf-Treibers. X-Git-Url: https://git.rohieb.name/hackover2013-badge-firmware.git/commitdiff_plain/a4d6194c75193f60e930fb997c0e69c0b78988b3 Teile des r0ket-nrf-Treibers. --- diff --git a/.gitignore b/.gitignore index 4484329..c81c744 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ *.elf *.ld *.dep +*.lvl lpcrc diff --git a/funk/nrf24l01p.c b/funk/nrf24l01p.c new file mode 100644 index 0000000..4ff27db --- /dev/null +++ b/funk/nrf24l01p.c @@ -0,0 +1,334 @@ +#ifdef R0KET +#include +#else +#include + +#define RB_SPI_NRF_CS HOB_PORT(HOB_RADIO_CS),HOB_PIN(HOB_RADIO_CS) +#define RB_NRF_CE HOB_PORT(HOB_RADIO_CE),HOB_PIN(HOB_RADIO_CE) +#define RB_NRF_IRQ HOB_PORT(HOB_RADIO_IRQ),HOB_PIN(HOB_RADIO_IRQ) + +#define RB_SPI_NRF_CS_IO HOB_IOCON(HOB_RADIO_CS) +#define RB_NRF_CE_IO HOB_IOCON(HOB_RADIO_CE) +#define RB_NRF_IRQ_IO HOB_IOCON(HOB_RADIO_IRQ) +#endif + +#include "nrf24l01p.h" +#include +#include + +#define DEFAULT_SPEED R_RF_SETUP_DR_2M + +uint8_t _nrfresets=0; + +/*-----------------------------------------------------------------------*/ +/* Transmit a byte via SPI */ +/*-----------------------------------------------------------------------*/ +static inline void xmit_spi(uint8_t dat) { + sspSend(0, (uint8_t*) &dat, 1); +} + +static inline void rcv_spi(uint8_t *dat) { + sspReceive(0, dat, 1); +} + +#define CS_LOW() gpioSetValue(RB_SPI_NRF_CS, 0) +#define CS_HIGH() gpioSetValue(RB_SPI_NRF_CS, 1) +#define CE_LOW() gpioSetValue(RB_NRF_CE, 0) +#define CE_HIGH() gpioSetValue(RB_NRF_CE, 1) + +void nrf_cmd(uint8_t cmd){ + CS_LOW(); + xmit_spi(cmd); + CS_HIGH(); +} + +uint8_t nrf_cmd_status(uint8_t cmd){ + CS_LOW(); + sspSendReceive(0, &cmd, 1); + CS_HIGH(); + return cmd; +} + +void nrf_cmd_rw_long(uint8_t* data, int len){ + CS_LOW(); + sspSendReceive(0,data,len); + CS_HIGH(); +} + + +void nrf_write_reg(const uint8_t reg, const uint8_t val){ + CS_LOW(); + xmit_spi(C_W_REGISTER | reg); + xmit_spi(val); + CS_HIGH(); +} + +uint8_t nrf_read_reg(const uint8_t reg){ + uint8_t val; + CS_LOW(); + xmit_spi(C_R_REGISTER | reg); + rcv_spi(&val); + CS_HIGH(); + return val; +} + +void nrf_read_long(const uint8_t cmd, int len, uint8_t* data){ + CS_LOW(); + xmit_spi(cmd); + for(int i=0;i32 || len==0){ + return -2; // no packet error + }; + + if(len>maxsize){ + return -1; // packet too large + }; + + nrf_read_pkt(len,pkt); + + return len; +} + +void nrf_rcv_pkt_end(void){ + CE_LOW(); + nrf_cmd(C_FLUSH_RX); + nrf_write_reg(R_STATUS,R_STATUS_RX_DR); +} + +void nrf_set_rx_mac(int pipe, int rxlen, int maclen, const uint8_t * mac){ +#ifdef SAFE + assert(maclen>=1 || maclen<=5); + assert(rxlen>=1 || rxlen<=32); + assert(pipe>=0 || pipe<=5); + assert(mac!=NULL); + if(pipe>1) + assert(maclen==1); +#endif + nrf_write_reg(R_RX_PW_P0+pipe,rxlen); + + nrf_write_reg_long(R_RX_ADDR_P0+pipe,maclen,mac); + nrf_write_reg(R_EN_RXADDR, + nrf_read_reg(R_EN_RXADDR) | (1<=1 || maclen<=5); + assert(mac!=NULL); +#endif + nrf_write_reg_long(R_TX_ADDR,maclen,mac); +} + +void nrf_disable_pipe(int pipe){ +#ifdef SAFE + assert(pipe>=0 || pipe<=5); +#endif + nrf_write_reg(R_EN_RXADDR, + nrf_read_reg(R_EN_RXADDR) & ~(1<channel); + + for(int i=0;inrmacs;i++){ + nrf_write_reg(R_RX_PW_P0+i,config->maclen[i]); + if(i==0){ + nrf_write_reg_long(R_RX_ADDR_P0,5,config->mac0); + }else if(i==1){ + nrf_write_reg_long(R_RX_ADDR_P1,5,config->mac1); + }else if(i>1){ + nrf_write_reg_long(R_RX_ADDR_P0+i,1,config->mac2345+i-2); + }; + }; + + nrf_write_reg_long(R_TX_ADDR,5,config->txmac); + + nrf_write_reg(R_EN_RXADDR,(1<nrmacs)-1); +} + +void nrf_config_get(nrfconfig config){ +// nrf_write_reg(R_SETUP_AW,R_SETUP_AW_5); + + config->channel=nrf_read_reg(R_RF_CH); + + config->nrmacs=nrf_read_reg(R_EN_RXADDR); + if(config->nrmacs & R_EN_RXADDR_ERX_P5 ) + config->nrmacs=6; + else if(config->nrmacs & R_EN_RXADDR_ERX_P4 ) + config->nrmacs=5; + else if(config->nrmacs & R_EN_RXADDR_ERX_P3 ) + config->nrmacs=4; + else if(config->nrmacs & R_EN_RXADDR_ERX_P2 ) + config->nrmacs=3; + else if(config->nrmacs & R_EN_RXADDR_ERX_P1 ) + config->nrmacs=2; + else + config->nrmacs=1; + +// config->nrmacs=6; + + for(int i=0;inrmacs;i++){ + config->maclen[i]=nrf_read_reg(R_RX_PW_P0+i); + if(i==0){ + nrf_read_long(R_RX_ADDR_P0,5,config->mac0); + }else if(i==1){ + nrf_read_long(R_RX_ADDR_P1,5,config->mac1); + }else if(i>1){ + nrf_read_long(R_RX_ADDR_P0+i,1,config->mac2345+i-2); + }; + }; + + nrf_read_long(R_TX_ADDR,5,config->txmac); + +} + +void nrf_set_strength(unsigned char strength){ + if(strength>3) + strength=3; + nrf_write_reg(R_RF_SETUP,DEFAULT_SPEED|(strength<<1)); +} + +void nrf_init() { + // Enable SPI correctly + sspInit(0, sspClockPolarity_Low, sspClockPhase_RisingEdge); + + // Enable CS & CE pins + gpioSetDir(RB_SPI_NRF_CS, gpioDirection_Output); + gpioSetPullup(&RB_SPI_NRF_CS_IO, gpioPullupMode_Inactive); + gpioSetDir(RB_NRF_CE, gpioDirection_Output); + gpioSetPullup(&RB_NRF_CE_IO, gpioPullupMode_PullUp); + CE_LOW(); + + // Setup for nrf24l01+ + // power up takes 1.5ms - 3.5ms (depending on crystal) + CS_LOW(); + nrf_write_reg(R_CONFIG, + R_CONFIG_PRIM_RX| // Receive mode + R_CONFIG_PWR_UP| // Power on + R_CONFIG_EN_CRC // CRC on, single byte + ); + + nrf_write_reg(R_EN_AA, 0); // Disable Enhanced ShockBurst; + + // Set speed / strength + nrf_write_reg(R_RF_SETUP,DEFAULT_SPEED|R_RF_SETUP_RF_PWR_3); + + // Clear MAX_RT, just in case. + nrf_write_reg(R_STATUS,R_STATUS_MAX_RT); +} + +void nrf_off() { + nrf_write_reg(R_CONFIG, + R_CONFIG_MASK_RX_DR| + R_CONFIG_MASK_TX_DS| + R_CONFIG_MASK_MAX_RT + ); // Most important: no R_CONFIG_PWR_UP +} + +void nrf_startCW() { + // Enable SPI correctly + sspInit(0, sspClockPolarity_Low, sspClockPhase_RisingEdge); + + // Enable CS & CE pins + gpioSetDir(RB_SPI_NRF_CS, gpioDirection_Output); + gpioSetPullup(&RB_SPI_NRF_CS_IO, gpioPullupMode_Inactive); + gpioSetDir(RB_NRF_CE, gpioDirection_Output); + gpioSetPullup(&RB_NRF_CE_IO, gpioPullupMode_PullUp); + CE_LOW(); + + // Setup for nrf24l01+ + // power up takes 1.5ms - 3.5ms (depending on crystal) + CS_LOW(); + + nrf_write_reg(R_CONFIG, R_CONFIG_PWR_UP); + systickDelay(2); + nrf_write_reg(R_RF_SETUP, R_RF_SETUP_CONT_WAVE | + R_RF_SETUP_PLL_LOCK | + R_RF_SETUP_RF_PWR_3); + nrf_write_reg(R_RF_CH, 81); + CE_HIGH(); +} + +void nrf_check_reset(void){ + if(nrf_cmd_status(C_NOP) & R_STATUS_MAX_RT){ + _nrfresets++; + nrf_init(); + }; +} diff --git a/funk/nrf24l01p.h b/funk/nrf24l01p.h new file mode 100644 index 0000000..1f2121a --- /dev/null +++ b/funk/nrf24l01p.h @@ -0,0 +1,175 @@ +#ifndef _NRF24L01P_H +#define _NRF24L01P_H 1 +#include + +#define MAX_PKT (32) // space for crc is supplied by the caller + +// SPI commands +#define C_R_REGISTER 0x00 +#define C_W_REGISTER 0x20 +#define C_R_RX_PAYLOAD 0x61 +#define C_W_TX_PAYLOAD 0xA0 +#define C_FLUSH_TX 0xE1 +#define C_FLUSH_RX 0xE2 +#define C_REUSE_TX_PL 0xE3 +#define C_R_RX_PL_WID 0x60 +#define C_W_ACK_PAYLOAD 0xA8 +#define C_W_TX_PAYLOAD_NOCACK 0xB0 +#define C_NOP 0xFF + +// Registers +#define R_CONFIG 0x00 +#define R_EN_AA 0x01 +#define R_EN_RXADDR 0x02 +#define R_SETUP_AW 0x03 +#define R_SETUP_RETR 0x04 +#define R_RF_CH 0x05 +#define R_RF_SETUP 0x06 +#define R_STATUS 0x07 +#define R_OBSERVE_TX 0x08 +#define R_RPD 0x09 +#define R_RX_ADDR_P0 0x0A + #define R_RX_ADDR_P0_LEN 5 +#define R_RX_ADDR_P1 0x0B + #define R_RX_ADDR_P1_LEN 5 +#define R_RX_ADDR_P2 0x0C + #define R_RX_ADDR_P2_LEN 1 +#define R_RX_ADDR_P3 0x0D + #define R_RX_ADDR_P3_LEN 1 +#define R_RX_ADDR_P4 0x0E + #define R_RX_ADDR_P4_LEN 1 +#define R_RX_ADDR_P5 0x0F + #define R_RX_ADDR_P5_LEN 1 +#define R_TX_ADDR 0x10 + #define R_TX_ADDR_LEN 5 +#define R_RX_PW_P0 0x11 +#define R_RX_PW_P1 0x12 +#define R_RX_PW_P2 0x13 +#define R_RX_PW_P3 0x14 +#define R_RX_PW_P4 0x15 +#define R_RX_PW_P5 0x16 +#define R_FIFO_STATUS 0x17 +#define R_DYNPD 0x1c + +// Register Flags + +//CONFIG register definitions +#define R_CONFIG_RESERVED 0x80 +#define R_CONFIG_MASK_RX_DR 0x40 +#define R_CONFIG_MASK_TX_DS 0x20 +#define R_CONFIG_MASK_MAX_RT 0x10 +#define R_CONFIG_EN_CRC 0x08 +#define R_CONFIG_CRCO 0x04 +#define R_CONFIG_PWR_UP 0x02 +#define R_CONFIG_PRIM_RX 0x01 + +//EN_AA register definitions +#define R_EN_AA_ENAA_P5 0x20 +#define R_EN_AA_ENAA_P4 0x10 +#define R_EN_AA_ENAA_P3 0x08 +#define R_EN_AA_ENAA_P2 0x04 +#define R_EN_AA_ENAA_P1 0x02 +#define R_EN_AA_ENAA_P0 0x01 +#define R_EN_AA_ENAA_NONE 0x00 + +//EN_RXADDR register definitions +#define R_EN_RXADDR_ERX_P5 0x20 +#define R_EN_RXADDR_ERX_P4 0x10 +#define R_EN_RXADDR_ERX_P3 0x08 +#define R_EN_RXADDR_ERX_P2 0x04 +#define R_EN_RXADDR_ERX_P1 0x02 +#define R_EN_RXADDR_ERX_P0 0x01 +#define R_EN_RXADDR_ERX_NONE 0x00 + +// RF_CH register definitions +#define R_RF_CH_BITS 0x7f + +//RF_SETUP register definitions +#define R_RF_SETUP_CONT_WAVE 0x80 +#define R_RF_SETUP_RF_DR_LOW 0x20 +#define R_RF_SETUP_PLL_LOCK 0x10 +#define R_RF_SETUP_RF_DR_HIGH 0x08 +#define R_RF_SETUP_RF_PWR_0 0x00 +#define R_RF_SETUP_RF_PWR_1 0x02 +#define R_RF_SETUP_RF_PWR_2 0x04 +#define R_RF_SETUP_RF_PWR_3 0x06 + +#define R_RF_SETUP_DR_1M 0x00 +#define R_RF_SETUP_DR_2M 0x08 +#define R_RF_SETUP_DR_250K 0x20 + +//SETUP_AW register definitions +#define R_SETUP_AW_3 0x01 +#define R_SETUP_AW_4 0x02 +#define R_SETUP_AW_5 0x03 + +//STATUS register definitions +#define R_STATUS_RX_DR 0x40 +#define R_STATUS_TX_DS 0x20 +#define R_STATUS_MAX_RT 0x10 +#define R_STATUS_RX_P_NO 0x0E +#define R_STATUS_GET_RX_P_NO(x) ((x&R_STATUS_RX_P_NO)>>1) +#define R_STATUS_RX_FIFO_EMPTY 0x0E +#define R_STATUS_TX_FULL 0x01 + +/* config structure */ + +struct NRF_CFG { + uint8_t channel; + uint8_t txmac[5]; + uint8_t mac0[5]; + uint8_t mac1[5]; + uint8_t mac2345[4]; + uint8_t nrmacs; + uint8_t maclen[5]; +}; + +typedef struct NRF_CFG * nrfconfig; + + +/* exported functions */ +#define nrf_rcv_pkt_time(maxtime, maxsize, pkt) \ + nrf_rcv_pkt_time_encr(maxtime, maxsize, pkt, NULL) + +int nrf_rcv_pkt_time_encr(int maxtime, int maxsize, uint8_t * pkt, uint32_t const k[4]); + +#define nrf_snd_pkt_crc(size, pkt) \ + nrf_snd_pkt_crc_encr(size, pkt, NULL) +char nrf_snd_pkt_crc_encr(int size, uint8_t * pkt, uint32_t const k[4]); + +void nrf_init() ; +void nrf_off() ; +void nrf_startCW(); + +void nrf_cmd(uint8_t cmd); +uint8_t nrf_cmd_status(uint8_t cmd); +void nrf_cmd_rw_long(uint8_t* data, int len); +void nrf_read_long(const uint8_t reg, int len, uint8_t* data); +void nrf_write_reg(const uint8_t reg, const uint8_t val); +uint8_t nrf_read_reg(const uint8_t reg); +void nrf_write_long(const uint8_t cmd, int len, const uint8_t* data); + +void nrf_set_rx_mac(int pipe, int rxlen, int maclen, const uint8_t * mac); +void nrf_set_tx_mac(int maclen, const uint8_t * mac); +void nrf_disable_pipe(int pipe); +void nrf_set_channel(int channel); + +void nrf_config_set(nrfconfig config); +void nrf_config_get(nrfconfig config); + +void nrf_set_strength(unsigned char strength); + +// new receive IF +void nrf_rcv_pkt_start(void); +int nrf_rcv_pkt_poll(int maxsize, uint8_t * pkt); +int nrf_rcv_pkt_poll_dec(int maxsize, uint8_t * pkt, uint32_t const key[4]); + +// more utility. +void nrf_rcv_pkt_end(void); +void nrf_check_reset(void); +extern uint8_t _nrfresets; + +/* END */ + +#endif /* _NRF24L01P_H */ +