Teile des r0ket-nrf-Treibers.
authorWintermute <wintermute@hannover.ccc.de>
Mon, 14 Oct 2013 19:35:33 +0000 (21:35 +0200)
committerWintermute <wintermute@hannover.ccc.de>
Mon, 14 Oct 2013 19:35:33 +0000 (21:35 +0200)
.gitignore
funk/nrf24l01p.c [new file with mode: 0644]
funk/nrf24l01p.h [new file with mode: 0644]

index 4484329..c81c744 100644 (file)
@@ -4,4 +4,5 @@
 *.elf
 *.ld
 *.dep
+*.lvl
 lpcrc
diff --git a/funk/nrf24l01p.c b/funk/nrf24l01p.c
new file mode 100644 (file)
index 0000000..4ff27db
--- /dev/null
@@ -0,0 +1,334 @@
+#ifdef R0KET
+#include <r0ketports.h>
+#else
+#include <badge/pinconfig.h>
+
+#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 <core/ssp/ssp.h>
+#include <core/systick/systick.h>
+
+#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;i<len;i++)
+        data[i] = 0x00;
+    sspSendReceive(0,data,len);
+    CS_HIGH();
+}
+
+void nrf_read_pkt(int len, uint8_t* data){
+    CS_LOW();
+    xmit_spi(C_R_RX_PAYLOAD);
+    sspReceive(0,data,len);
+    CS_HIGH();
+}
+
+void nrf_read_pkt_crc(int len, uint8_t* data, uint8_t* crc){
+    CS_LOW();
+    xmit_spi(C_R_RX_PAYLOAD);
+    sspReceive(0,data,len);
+    sspReceive(0,crc,2);
+    CS_HIGH();
+}
+
+void nrf_write_long(const uint8_t cmd, int len, const uint8_t* data){
+    CS_LOW();
+    xmit_spi(cmd);
+    sspSend(0,data,len);
+    CS_HIGH();
+}
+
+#define nrf_write_reg_long(reg, len, data) \
+    nrf_write_long(C_W_REGISTER|(reg), len, data)
+
+// High-Level:
+void nrf_rcv_pkt_start(void){
+
+    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_cmd(C_FLUSH_RX);
+    nrf_write_reg(R_STATUS,0);
+
+    CE_HIGH();
+}
+
+int nrf_rcv_pkt_poll(int maxsize, uint8_t * pkt){
+    uint8_t len;
+    uint8_t status=0;
+
+    for(int i=0;i<maxsize;i++) pkt[i] = 0x00; // Sanity: clear packet buffer
+
+    status =nrf_cmd_status(C_NOP);
+
+    if((status & R_STATUS_RX_P_NO) == R_STATUS_RX_FIFO_EMPTY){
+        if( (status & R_STATUS_RX_DR) == R_STATUS_RX_DR){
+#ifdef USB_CDC
+            puts("FIFO empty, but RX?\r\n");
+#endif
+            nrf_write_reg(R_STATUS,R_STATUS_RX_DR);
+        };
+        return 0;
+    };
+
+    nrf_read_long(C_R_RX_PL_WID,1,&len);
+
+    nrf_write_reg(R_STATUS,R_STATUS_RX_DR);
+    if(len>32 || 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<<pipe)
+            );
+}
+
+void nrf_set_tx_mac(int maclen, const uint8_t * mac){
+#ifdef SAFE
+    assert(maclen>=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<<pipe)
+            );
+}
+
+void nrf_set_channel(int channel){
+#ifdef SAFE
+    assert(channel &~R_RF_CH_BITS ==0);
+#endif
+    nrf_write_reg(R_RF_CH, channel);
+}
+
+void nrf_config_set(nrfconfig config){
+    nrf_write_reg(R_SETUP_AW,R_SETUP_AW_5);
+
+    nrf_set_channel(config->channel);
+
+    for(int i=0;i<config->nrmacs;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<<config->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;i<config->nrmacs;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 (file)
index 0000000..1f2121a
--- /dev/null
@@ -0,0 +1,175 @@
+#ifndef _NRF24L01P_H
+#define _NRF24L01P_H 1
+#include <stdint.h>
+
+#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 */
+
This page took 0.028838 seconds and 4 git commands to generate.