Library for the nRF2401A Transceiver

Dependents:   nRF2401A_Hello_World nRF2401A_Wireless_Accelerometer_joypad nRF2401A_Gameduino_Invaders

Revision:
0:17cb4be1e37f
Child:
1:8c57f88ff574
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nRF2401A.h	Fri Oct 04 16:14:49 2013 +0000
@@ -0,0 +1,340 @@
+/* mbed nRF2401A  Library
+ *
+ * Copyright (c) 2011, Per Söderstam
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+ 
+
+#include <mbed.h>
+#include <inttypes.h>
+#define   Ts         1     /**< Setup time from data to rising clock edge on write (accualy 500 ns). */
+#define   Th         1     /**< Hold time from rising clock to data toggle/falling clock (accualy 500 ns). */
+#define   Tcs2data   5     /**< Min delay from CS assert to data, in us. */
+#define   Tce2data   5     /**< Min delay from CE assert to data, in us. */
+#define   Td         1     /**< Minimum delay between edges (actually 50 ns). */
+#define   Tpd2cfgm   3     /**< Minimum delay from power up of tranciever to configuration. */
+#define   Tsby2txSB  195   /**< Minimum delay from tx initation to air, in us. */
+#define   Thmin      5     /**< */
+#define   Tclk2data  1     /**< */
+
+/** Servo control class, based on a PwmOut
+ *
+ * Example:
+ * @code
+ * #include "mbed.h"
+ * #include "nRF2401A.h"
+ *
+ * DigitalOut  myled(LED1);
+ * nRF2401A    rf1(p10, p11, p12, p13, p14);
+ * nRF2401A    rf2(p21, p22, p23, p24, p25);
+ *
+ * Serial pc(USBTX, USBRX);
+ *
+ * int main() {
+ *
+ *     wait(0.005);
+ *
+ *     pc.printf("Hello nRF2401A\n\r");
+ *   
+ *     rf1.setDataPayloadLength(4 << 3)
+ *        .setAddress(0x0, 0x0, 0xa6, 0xa6, 0xa6, 3 << 3)
+ *        .setCRCMode(nRF2401A::NO_CRC)
+ *        .setDataRate(nRF2401A::BIT_RATE_250KBITS)
+ *        .setChannel(0x02);
+ *        
+ *     rf1.printControlPacket(pc);
+ *     
+ *     rf2.setDataPayloadLength(4 << 3)
+ *        .setAddress(0x0, 0x0, 0x53, 0x53, 0x53, 3 << 3)
+ *        .setCRCMode(nRF2401A::NO_CRC)
+ *        .setDataRate(nRF2401A::BIT_RATE_250KBITS)
+ *        .setChannel(0x02);
+ *        
+ *     rf2.printControlPacket(pc);
+ *     
+ *     rf1.flushControlPacket();
+ *     rf2.flushControlPacket();
+ *     
+ *     nRF2401A::address_t rf2_addr = {0x0, 0x0, 0x53, 0x53, 0x53};
+ *     uint8_t msg[] = {0x01, 0x01, 0x01, 0x01};
+ *     uint32_t *msg32 = (uint32_t *) msg;
+ *         
+ *     while(1) {
+ *             
+ *         rf1.sendMsg(rf2_addr, 3 << 3, msg, 4 << 3);
+ *         *msg32 += 1;
+ *         
+ *         myled = 1;
+ *         wait(0.25);
+ *         
+ *         rf2.printDataPacket(pc);
+ *         
+ *         myled = 0;
+ *         wait(0.25);
+ *     }
+ * }
+ * @endcode
+ */
+
+/** ISR handler prototype for receiving messages.
+ * A function of this type is registered and called when the DR pin on the
+ * nRF tranciever signals the reception of a message. The void * argument
+ * is likewise supplied when registering and is returned at call time.
+ */
+typedef void (*nRF2401A_rx_handler_t)(void *);
+
+/**
+ *
+ *
+ */
+class nRF2401A
+{
+    public:
+        /** Class constructor.
+         * The constructor assigns the specified pinout, attatch the
+         * DR1 to a pin interrupt and sets up inmutable control packet
+         * fields.
+         * \param ce Chip Enable (CE) pin of the nRF2401A.
+         * \param c2 Chip Select (CS) pin of the nRF2401A.
+         * \param dr1 Data Ready 1 (DR1) pin of the nRF2401A.
+         * \param clk1 Clock 1 (CLK1) pin of the nRF2401A.
+         * \param data Data (DATA) pin of the nRF2401A.
+         */
+        nRF2401A(PinName ce,
+                 PinName cs,
+                 PinName dr1,
+                 PinName clk1,
+                 PinName data);
+                 
+        /** Class destructor.
+         * Pretty much useless in the embedded world...
+         */
+        virtual ~nRF2401A() { return; }
+        
+        /** Set the payload length, in bits.
+         * Set the control packet field for length, in number of bits, of the message payload.
+         * \param n Number of bits of the message payload.
+         * \return Reference to the invoked object (for chaining operations).
+         */
+        nRF2401A& setDataPayloadLength(uint8_t n) 
+        { 
+            _ctrl_packet_buf.channel_1_data_payload_len = n; 
+            return *this; 
+        }
+        
+        /** Set the address of channel 1.
+         * The channel address is a up to 40 bit number identifying the tranciever.
+         * \param addr4 Bits 39-32 of the address.
+         * \param addr4 Bits 31-24 of the address.
+         * \param addr4 Bits 23-16 of the address.
+         * \param addr4 Bits 15-8 of the address.
+         * \param addr4 Bits 7-0 of the address.
+         * \param n_bits Number of bits used in the address.
+         * \return Reference to the invoked object (for chaining operations).
+         */
+        nRF2401A& setAddress(uint8_t addr4, uint8_t addr3, uint8_t addr2, uint8_t addr1, uint8_t addr0, uint8_t n_bits)
+        {
+            _ctrl_packet_buf.channel_1_address[0] = addr4;
+            _ctrl_packet_buf.channel_1_address[1] = addr3;
+            _ctrl_packet_buf.channel_1_address[2] = addr2;
+            _ctrl_packet_buf.channel_1_address[3] = addr1;
+            _ctrl_packet_buf.channel_1_address[4] = addr0;
+            _ctrl_packet_buf.channel_address_len = n_bits;
+            
+            return *this;
+        }
+        
+        /** CRC settings.
+         * Type covering the allowed settings for use of CRC.
+         */
+        typedef enum 
+        {
+            NO_CRC = 0x0,   /**< Do not use CRC. */
+            CRC_8 = 0x1,    /**< Use a 8-bit CRC. */
+            CRC_16 = 0x3    /**< Use a 16-bit CRC. */
+        } CRC_T;
+        
+        /** Set CRC use.
+         * Set the CRC mode field of the control packet.
+         * \param mode The CRC mode of choise.
+         * \return Reference to the invoked object (for chaining operations).
+         */
+        nRF2401A& setCRCMode(CRC_T mode) 
+        { 
+            _ctrl_packet_buf.crc_config = mode; 
+            return *this; 
+        }
+        
+        /** Data rate settings.
+         * Type covering the allowed settings for the tranciever data rate.
+         */
+        typedef enum
+        {
+            BIT_RATE_250KBITS = 0x0,    /**< */
+            BIT_RATE_1MBITS = 0x1       /**< */
+        } DATA_RATE_T;
+        
+        /** Set tranciever data rate.
+         * Sets the data rate field to either 250 kbit/s or 1 Mbit/s data transfer rate.
+         * \param mode The data rate of choise.
+         * \return Reference to the invoked object (for chaining operations).
+         */
+        nRF2401A& setDataRate(DATA_RATE_T data_rate)
+        {
+            _ctrl_packet_buf.rf_data_rate = data_rate;
+            return *this;
+        }
+        
+        /** Set RF channel.
+         * Sets the control packet field for channel number. Channel numbers are from 0 to 127
+         * representing channel frequencies equal to (2400 + channel number) MHz.
+         * \param ch Channel number, from the range [0, 127].
+         * \return Reference to the invoked object (for chaining operations).
+         */
+        nRF2401A& setChannel(uint8_t ch)
+        {
+            _ctrl_packet_buf.rf_channel = ch;
+            return *this;
+        }
+        
+        /** Send the control packet to the nRF2401A.
+         * This function transfer the control packet image to the nRF2401A.
+         * \return Reference to the invoked object (for chaining operations).
+         */
+        nRF2401A& flushControlPacket();
+        
+        /**
+         *
+         */
+        void activate(bool active = true);
+        
+        /**
+         *
+         */
+        typedef uint8_t address_t[5];
+        
+        /** Send a message.
+         * This routine will transfer the data from the supplied buffer and send
+         * it to the specified address using the current control packet settings.
+         * \param addr The address to send to.
+         * \param addr_len Length of address, in bits.
+         * \param msg_buf Message body.
+         * \param msg_len Length of message,  in bits.
+         * \return Reference to the invoked object (for chaining operations).
+         */
+        nRF2401A& sendMsg(address_t addr, uint8_t addr_len, uint8_t *msg_buf, uint8_t msg_len);
+        
+        /** Register a receive action callback.
+         * Attach a callback that will be called when the tranciever intercept a
+         * message. This callback will be called in the context of an interrupt
+         * routine and should act accordingly.
+         * \param handler The callback, of type nRF2401_rx_handler_t.
+         * \param arg Pointer to data supplied to the handler at call time.
+         * \return Reference to the invoked object (for chaining operations).
+         */     
+        nRF2401A& attachRXHandler(nRF2401A_rx_handler_t handler, void *arg);
+        
+        void printControlPacket(Serial& port);
+        void printDataPacket(Serial& port);
+        
+    private:
+    
+        DigitalOut      _ce;    /**< Chip Enable pin. */
+        DigitalOut      _cs;    /**< Chip select pin. */
+        DigitalIn       _dr1;   /**< Data Ready 1 pin. */
+        DigitalOut      _clk1;  /**< Clock 1 pin. */
+        DigitalInOut    _data;  /**< Data pin. */
+        
+        /**
+         *
+         */
+        typedef enum 
+        { 
+            UNDEF,      /**< The start state. */
+            RX,         /**< The tranciever is in receive mode. */
+            TX,         /**< The tranciever is transmitting. */
+            STANDBY     /**< The tranciever goes into stanby mode. */
+        } STATE_T;
+        
+        STATE_T  _state;
+        
+        /** Contol packet data.
+         *
+         */
+        struct nRF2401A_ctrl_packet_t
+        {
+            uint8_t     channel_2_data_payload_len;     /**< */
+            uint8_t     channel_1_data_payload_len;     /**< */
+            uint8_t     channel_2_address[5];           /**< */
+            uint8_t     channel_1_address[5];           /**< */
+            
+            uint8_t     crc_config : 2;                 /**< */
+            uint8_t     channel_address_len : 6;        /**< */
+            
+            uint8_t     rf_power : 2;                   /**< */
+            uint8_t     xo_frequency : 3;               /**< */
+            uint8_t     rf_data_rate : 1;               /**< */
+            uint8_t     communication_mode : 1;         /**< */
+            uint8_t     enable_dual_channel_mode : 1;   /**< */
+            
+            uint8_t     txr_switch : 1;                 /**< */
+            uint8_t     rf_channel : 7;                 /**< */
+            
+        }                                       _ctrl_packet_buf;   /**< */
+        
+        uint8_t         *_ctrl_packet;  /**< */
+        
+        uint8_t         _data_buf[32];  /**< */        
+        
+        nRF2401A_rx_handler_t   _rx_handler;        /**< */
+        void                    *_rx_handler_arg;   /**< */
+        
+        /** Receive ISR.
+         * This handler is attached to the rising flank of the DR1 pin. It
+         * will thus be called when the nRF2401A receives a packet in ShockBurst
+         * mode (the mode used). It will in turn call the attached handler.
+         */
+        void dataReadyHandler(void);
+        
+        /**
+         *
+         */
+        InterruptIn     _dr1_isr;
+        
+        /*
+         *
+         */
+        typedef enum { RX_MODE = 0x1, TX_MODE = 0x0 } TXR_T;
+        
+        /** Write to the data bus.
+         * Write n_bits bits on the DATA line.
+         * \param buf Data buffer.
+         * \param n_bits Number of bits to transfer.
+         * \param is_ctrl True if the tranfered data is control word, false if data.
+         */
+        void pushCtrl(uint8_t *buf, uint8_t n_bits, bool is_ctrl = true);
+        
+        /** Read a message from the tranciever.
+         * Read until DR1 goes low.
+         * \param buf Data buffer.
+         * \return Number of bits read.
+         */
+        int pull(uint8_t *buf);
+};
\ No newline at end of file