Matthias Grob & Manuel Stalder / Mbed 2 deprecated DecaWave

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
manumaet
Date:
Sun Nov 16 09:53:25 2014 +0000
Child:
1:1311e7af0a5c
Commit message:
draft with first success to send a hello world frame to the other node :)

Changed in this revision

DW1000/DW1000.cpp Show annotated file Show diff for this revision Revisions of this file
DW1000/DW1000.h Show annotated file Show diff for this revision Revisions of this file
PC/PC.cpp Show annotated file Show diff for this revision Revisions of this file
PC/PC.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DW1000/DW1000.cpp	Sun Nov 16 09:53:25 2014 +0000
@@ -0,0 +1,78 @@
+#include "DW1000.h"
+
+DW1000::DW1000(PinName MOSI, PinName MISO, PinName SCLK, PinName CS) : spi(MOSI, MISO, SCLK), cs(CS)
+{
+    deselect();                         // Chip must be deselected first
+    spi.format(8,0);                    // Setup the spi for standard 8 bit data and SPI-Mode 0 (GPIO5, GPIO6 open circuit or ground on DW1000)
+    spi.frequency(1000000);             // with a 1MHz clock rate (worked up to 49MHz in our Test)
+}
+
+uint32_t DW1000::getDeviceID() {
+    uint32_t result;
+    readRegister(DW1000_DEV_ID, 0, (uint8_t*)&result, 4);
+    return result;
+}
+
+uint64_t DW1000::getEUI() {
+    uint64_t result;
+    readRegister(DW1000_EUI, 0, (uint8_t*)&result, 8);
+    return result;
+}
+
+void DW1000::setEUI(uint64_t EUI) {
+    writeRegister(DW1000_EUI, 0, (uint8_t*)&EUI, 8);
+}
+
+float DW1000::getVoltage() {
+    uint8_t buffer[7] = {0x80, 0x0A, 0x0F, 0x01, 0x00}; // form DW1000 User Manual p57
+    writeRegister(DW1000_RF_CONF, 0x11, buffer, 2);
+    writeRegister(DW1000_RF_CONF, 0x12, &buffer[2], 1);
+    writeRegister(DW1000_TX_CAL, 0x00, &buffer[3], 1);
+    writeRegister(DW1000_TX_CAL, 0x00, &buffer[4], 1);
+    readRegister(DW1000_TX_CAL, 0x03, &buffer[5], 2);   // get the 8-Bit readings for Voltage and Temperature
+    float Voltage = buffer[5] * 0.0057 + 2.3;
+    float Temperature = buffer[6] * 1.13 - 113.0;      // TODO: getTemperature was always ~35 degree with better formula/calibration see instance_common.c row 391
+    return Voltage;
+}
+
+
+// SPI Interface ------------------------------------------------------------------------------------
+void DW1000::readRegister(uint8_t reg, uint16_t subaddress, uint8_t *buffer, int length)
+{
+    setupTransaction(reg, subaddress, false);
+    
+    // get data
+    for(int i=0; i<length; i++)
+        buffer[i] = spi.write(0x00);
+    deselect();
+}
+
+void DW1000::writeRegister(uint8_t reg, uint16_t subaddress, uint8_t *buffer, int length)
+{
+    setupTransaction(reg, subaddress, true);
+    
+    // put data
+    for(int i=0; i<length; i++)
+        spi.write(buffer[i]);
+    deselect();
+}
+
+void DW1000::setupTransaction(uint8_t reg, uint16_t subaddress, bool write)
+{
+    reg |=  (write * DW1000_WRITE_FLAG);
+    select();
+    if (subaddress > 0) {                                                       // there's a subadress, we need to set flag and send second header byte
+        spi.write(reg | DW1000_SUBADDRESS_FLAG);
+        if (subaddress > 127) {                                                 // sub address too long, we need to set flag and send third header byte
+            spi.write((uint8_t)(subaddress & 0x7F) | DW1000_2_SUBADDRESS_FLAG);
+            spi.write((uint8_t)(subaddress >> 7));
+        } else {
+            spi.write((uint8_t)subaddress);
+        }
+    } else {
+        spi.write(reg);
+    }
+}
+
+void DW1000::select() { cs = 0; }    //Set CS low to start transmission
+void DW1000::deselect() { cs = 1; }    //Set CS high to stop transmission
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DW1000/DW1000.h	Sun Nov 16 09:53:25 2014 +0000
@@ -0,0 +1,108 @@
+// by Manuel Stalder & Matthias Grob 2015
+
+#ifndef DW1000_H
+#define DW1000_H
+
+#include "mbed.h"
+
+// register addresses
+//      Mnemonic                    Address Byte Description
+#define DW1000_DEV_ID               0x00 //    4 Device Identifier – includes device type and revision information
+#define DW1000_EUI                  0x01 //    8 Extended Unique Identifier
+#define DW1000_PANADR               0x03 //    4 PAN Identifier and Short Address
+#define DW1000_SYS_CFG              0x04 //    4 System Configuration bitmap
+#define DW1000_SYS_TIME             0x06 //    5 System Time Counter (40-bit)
+#define DW1000_TX_FCTRL             0x08 //    5 Transmit Frame Control
+#define DW1000_TX_BUFFER            0x09 // 1024 Transmit Data Buffer
+#define DW1000_DX_TIME              0x0A //    5 Delayed Send or Receive Time (40-bit)
+#define DW1000_RX_FWTO              0x0C //    2 Receive Frame Wait Timeout Period
+#define DW1000_SYS_CTRL             0x0D //    4 System Control Register
+#define DW1000_SYS_MASK             0x0E //    4 System Event Mask Register
+#define DW1000_SYS_STATUS           0x0F //    5 System Event Status Register
+#define DW1000_RX_FINFO             0x10 //    4 RX Frame Information                (in double buffer set)
+#define DW1000_RX_BUFFER            0x11 // 1024 Receive Data Buffer                 (in double buffer set)
+#define DW1000_RX_FQUAL             0x12 //    8 Rx Frame Quality information        (in double buffer set)
+#define DW1000_RX_TTCKI             0x13 //    4 Receiver Time Tracking Interval     (in double buffer set)
+#define DW1000_RX_TTCKO             0x14 //    5 Receiver Time Tracking Offset       (in double buffer set)
+#define DW1000_RX_TIME              0x15 //   14 Receive Message Time of Arrival     (in double buffer set)
+#define DW1000_TX_TIME              0x17 //   10 Transmit Message Time of Sending    (in double buffer set)
+#define DW1000_TX_ANTD              0x18 //    2 16-bit Delay from Transmit to Antenna
+#define DW1000_SYS_STATE            0x19 //    5 System State information
+#define DW1000_ACK_RESP_T           0x1A //    4 Acknowledgement Time and Response Time
+#define DW1000_RX_SNIFF             0x1D //    4 Pulsed Preamble Reception Configuration
+#define DW1000_TX_POWER             0x1E //    4 TX Power Control
+#define DW1000_CHAN_CTRL            0x1F //    4 Channel Control
+#define DW1000_USR_SFD              0x21 //   41 User-specified short/long TX/RX SFD sequences
+#define DW1000_AGC_CTRL             0x23 //   32 Automatic Gain Control configuration
+#define DW1000_EXT_SYNC             0x24 //   12 External synchronisation control.
+#define DW1000_ACC_MEM              0x25 // 4064 Read access to accumulator data
+#define DW1000_GPIO_CTRL            0x26 //   44 Peripheral register bus 1 access - GPIO control
+#define DW1000_DRX_CONF             0x27 //   44 Digital Receiver configuration
+#define DW1000_RF_CONF              0x28 //   58 Analog RF Configuration
+#define DW1000_TX_CAL               0x2A //   52 Transmitter calibration block
+#define DW1000_FS_CTRL              0x2B //   21 Frequency synthesiser control block
+#define DW1000_AON                  0x2C //   12 Always-On register set
+#define DW1000_OTP_IF               0x2D //   18 One Time Programmable Memory Interface
+#define DW1000_LDE_CTRL             0x2E //    - Leading edge detection control block
+#define DW1000_DIG_DIAG             0x2F //   41 Digital Diagnostics Interface
+#define DW1000_PMSC                 0x36 //   48 Power Management System Control Block
+
+#define DW1000_WRITE_FLAG           0x80 // First Bit of the address has to be 1 to indicate we want to write
+#define DW1000_SUBADDRESS_FLAG      0x40 // if we have a sub address second Bit has to be 1
+#define DW1000_2_SUBADDRESS_FLAG    0x80 // if we have a long sub adress (more than 7 Bit) we set this Bit in the first part
+
+class DW1000
+{
+    public:            
+        DW1000(PinName MOSI, PinName MISO, PinName SCLK, PinName CS);                           // constructor, uses SPI class
+
+        // Device API
+        uint32_t getDeviceID();
+        uint64_t getEUI();
+        void setEUI(uint64_t EUI);
+        float getVoltage();
+        
+    //private:
+        
+        // SPI Inteface
+        SPI spi;                                                                                // SPI Bus
+        DigitalOut cs;                                                                          // Slave selector for SPI-Bus (here explicitly needed to start and end SPI transactions also usable to wake up DW1000)
+        
+        void readRegister(uint8_t reg, uint16_t subaddress, uint8_t *buffer, int length);
+        void writeRegister(uint8_t reg, uint16_t subaddress, uint8_t *buffer, int length);
+        void setupTransaction(uint8_t reg, uint16_t subaddress, bool write);                    // writes bytes to SPI to setup a write or read transaction the register address and subaddress
+        void select();                                                                          // selects the only slave for a transaction
+        void deselect();                                                                        // deselects the only slave after transaction
+};
+
+// -------------------------------------------------------------------------------------------------------------------
+// structure from original Driver to hold device data (to be removed!)
+typedef struct
+{
+    uint32_t      deviceID;
+    uint32_t      partID ;
+    uint32_t      lotID ;
+    uint8_t       chan;               // added chan here - used in the reading of acc
+    uint8_t       longFrames ;        // flag in non-standard long frame mode
+    uint32_t      txFCTRL ;           // keep TX_FCTRL register config
+    uint16_t      rfrxDly;            // rf delay (delay though the RF blocks before the signal comes out of the antenna i.e. "antenna delay")
+    uint16_t      rftxDly;            // rf delay (delay though the RF blocks before the signal comes out of the antenna i.e. "antenna delay")
+    uint32_t      antennaDly;         // antenna delay read from OTP 64 PRF value is in high 16 bits and 16M PRF in low 16 bits
+    uint8_t       xtrim;              // xtrim value read from OTP
+    uint32_t      sysCFGreg ;         // local copy of system config register
+    uint32_t      txPowCfg[12];       // stores the Tx power configuration read from OTP (6 channels consecutively with PRF16 then 64, e.g. Ch 1 PRF16 is index 0 and 64 index 1)
+    uint8_t       dblbuffon;          // double rx buffer mode flag
+                                    // the dwt_isr() will only process the events that "enabled" (i.e. the ones that generate interrupt)
+    //dwt_callback_data_t cdata;      // callback data structure
+
+    uint32_t      states[3] ;         //MP workaround debug states register
+    uint8_t       statescount ;
+    uint8_t       wait4resp ;         //wait 4 response was set with last TX start command
+    int         prfIndex ;
+
+    //void (*dwt_txcallback)(const dwt_callback_data_t *txd);
+    //void (*dwt_rxcallback)(const dwt_callback_data_t *rxd);
+
+} dwt_local_data_t ;
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PC/PC.cpp	Sun Nov 16 09:53:25 2014 +0000
@@ -0,0 +1,38 @@
+#include "PC.h"
+#include "mbed.h"
+
+PC::PC(PinName tx, PinName rx, int baudrate) : Serial(tx, rx) 
+{
+    baud(baudrate);
+    cls();
+    
+    command[0] = '\0';
+    command_char_count = 0;
+}
+
+
+void PC::cls() 
+{
+    printf("\x1B[2J");
+}
+
+
+void PC::locate(int Spalte, int Zeile) 
+{
+    printf("\x1B[%d;%dH", Zeile + 1, Spalte + 1);
+}
+
+void PC::readcommand(void (*executer)(char*))
+{
+    char input = getc();             // get the character from serial bus
+    if(input == '\r') {                 // if return was pressed, the command must be executed
+        command[command_char_count] = '\0';
+        executer(&command[0]);
+        
+        command_char_count = 0;                 // reset command
+        command[command_char_count] = '\0';
+    } else if (command_char_count < COMMAND_MAX_LENGHT) {
+        command[command_char_count] = input;
+        command_char_count++;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PC/PC.h	Sun Nov 16 09:53:25 2014 +0000
@@ -0,0 +1,20 @@
+#include "mbed.h"
+
+#ifndef PC_H
+#define PC_H
+
+#define COMMAND_MAX_LENGHT 300
+
+class PC : public Serial 
+{
+    public:
+        PC(PinName tx, PinName rx, int baud);
+        void cls();                                                                        // to clear the display
+        void locate(int column, int row);                                                  // to relocate the cursor
+        void readcommand(void (*executer)(char*));                  // to read a char from the pc to the command string
+        
+        char command[COMMAND_MAX_LENGHT];
+    private:
+        int command_char_count;
+};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Nov 16 09:53:25 2014 +0000
@@ -0,0 +1,65 @@
+#include "mbed.h"
+#include "PC.h"                         // Serial Port via USB for debugging with Terminal
+#include "DW1000.h"
+
+PC          pc(USBTX, USBRX, 921600);   // USB UART Terminal
+DW1000      dw(D11, D12, D13, D10);     // SPI1 on Nucleo Board (MOSI, MISO, SCLK, CS)
+
+/*uint32_t read32Bit(uint8_t reg, uint16_t subaddress) {
+    uint32_t result = 0;
+    
+}*/
+
+int main() {
+    pc.printf("DecaWave 0.1\r\nup and running!\r\n");
+    
+    dw.setEUI(0xFAEDCD01FAEDCD01);
+    
+    int i=0;
+    while(1) {
+        i++;
+        pc.printf("%d DEVICE_ID register: 0x%X\r\n", i, dw.getDeviceID());
+        pc.printf("%d EUI register: %016llX\r\n", i, dw.getEUI());
+        pc.printf("%d Voltage: %f\r\n", i, dw.getVoltage());
+        
+        // read System Configuration
+        uint32_t conf = 0;
+        dw.readRegister(DW1000_SYS_CFG, 0, (uint8_t*)&conf, 4);
+        pc.printf("%d System Configuration: %X\r\n", i, conf);
+        
+# if 1                      // to make one node sender and one receiver
+        // Send something
+        uint8_t message[13] = "HELLO WORLD!";   // fill buffer
+        dw.writeRegister(DW1000_TX_BUFFER, 0, message, 13);
+        uint8_t messagecheck[13];
+        dw.readRegister(DW1000_TX_BUFFER, 0, messagecheck, 13);
+        pc.printf("Message in buffer: %s\r\n", messagecheck);
+        
+        uint16_t framelength = 13;              // put length of frame
+        dw.writeRegister(DW1000_TX_FCTRL, 0, (uint8_t*)&framelength, 1);
+        
+        if (i == 4) {
+            uint8_t txstart = 0x02;             // trigger sending process
+            dw.writeRegister(DW1000_SYS_CTRL, 0, &txstart, 1);
+        }
+# else
+        // Receive something
+        uint8_t rxenable = 0x01;                // start listening
+        dw.writeRegister(DW1000_SYS_CTRL, 1, &rxenable, 1);
+        
+        //uint8_t frameready = 0;                 // check if frame received
+        //while (frameready != 0x20) {
+        //    i++;
+        //    pc.printf("%d Waiting for frame... \r\n", i);
+        //    dw.readRegister(DW1000_SYS_STATUS, 1, &frameready, 13);
+        //    wait(0.5);
+        //}
+        
+        uint8_t receive[13] = "NOTHING IN!!";   // get data from buffer
+        dw.readRegister(DW1000_RX_BUFFER, 0, receive, 13);
+        pc.printf("Message received: %s\r\n", receive);
+# endif
+        
+        wait(0.5);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sun Nov 16 09:53:25 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/031413cf7a89
\ No newline at end of file