Read data from an ADIS16355 IMU and write it to the USB port.

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
yahugh
Date:
Wed Aug 10 21:50:36 2011 +0000
Commit message:
initial release, still has some problems but might be of interest to others regardless

Changed in this revision

imu-spi.cpp Show annotated file Show diff for this revision Revisions of this file
imu-spi.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
usb-serial.cpp Show annotated file Show diff for this revision Revisions of this file
usb-serial.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r c6ee363ac724 imu-spi.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imu-spi.cpp	Wed Aug 10 21:50:36 2011 +0000
@@ -0,0 +1,98 @@
+//
+// imu-spi.cpp
+//
+// copyright 2010 Hugh Shane
+//
+#include "mbed.h"
+#include "imu-spi.h"
+
+ImuSpi::ImuSpi(void) :
+    spi(p5, p6, p7), // mosi, miso, sclk
+    cs(p8), // IMU chip select
+    reset(p8), // IMU reset. CAUTION! This also resets the altimeter.
+    diag(p21), // diagnostic output
+    imuDataReady(p11) // interrupt on IMU data-ready
+{
+    // Setup the spi for 16 bit data, high steady state clock,
+    // second edge capture, with a 1 MHz clock rate
+    spi.format(16,3);
+    spi.frequency(1000000);
+    
+    // init the pingpong buffer
+    pingpong = 0;
+    
+    // init the interrupt semaphore
+    dataReady = false;    
+    
+    // interrupt on the falling edge of the IMU data-ready signal
+    diag = 0;
+    imuDataReady.fall(this, &ImuSpi::DataReadyISR);
+    
+    // init the IMU
+    InitImu();
+
+}
+
+void  ImuSpi::reinitInterrupts(void) {
+    imuDataReady.fall(this, &ImuSpi::DataReadyISR);
+}
+
+// initialize the IMU
+void ImuSpi::InitImu(void) {
+    // deselect the IMU
+    cs = 1;
+    reset = 1;
+    // perform a hard reset
+    reset = 0; wait(.1); reset = 1;    
+    // send initialization commands
+    Write(0x34, 0x04); // enable active low data ready on DIO1
+    Write(0x38, 0x00); // Set the FIR filter to its widest possible bandwidth
+}
+
+// read the IMU accelerometer and gyro registers into the pingpong buffer
+void ImuSpi::BurstRead(void) {
+    static int16_t imuRegs[] = {0x04,0x06,0x08,0x0A,0x0C,0x0E,0x3C};
+    int16_t* wp = GetBufferWritePtr();
+    Read(imuRegs[0]); // set up the first register read operation
+    wait(0.000024); // required to meet IMU t(datarate) spec
+    
+    // send register read commands & read the registers
+    for (int i = 1; i <= 6; i++) {
+        *wp++ = Read(imuRegs[i]);
+        wait(0.000024);
+    }
+    *wp = Read(0); // read the last register output
+}
+
+int16_t ImuSpi::Read(char adr) {
+    int16_t cmd = 0x3f00 & (adr << 8);
+    int16_t response;
+    cs = 0;
+    response = spi.write(cmd);
+    cs = 1;
+    return response;
+}
+
+
+void ImuSpi::Write(char adr, char data) {
+    int16_t cmd = 0x8000 | (adr << 8) | data;
+    cs = 0;
+    spi.write(cmd);
+    cs = 1;
+}
+
+bool ImuSpi::IsDataReady(void) {
+    if (dataReady == true) {
+        dataReady = false;
+        return true;
+    } else {
+        return false;
+    }
+}
+
+void ImuSpi::DataReadyISR(void) {
+diag = 1;
+    TogglePingpong();
+    dataReady = true;
+diag = 0;
+}
diff -r 000000000000 -r c6ee363ac724 imu-spi.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imu-spi.h	Wed Aug 10 21:50:36 2011 +0000
@@ -0,0 +1,31 @@
+//
+// imu-spi.h
+//
+// copyright 2010 Hugh Shane
+//
+
+class ImuSpi {
+private:
+    const static int bufferSize = 7;
+    int16_t buffer[2][bufferSize]; // ping-pong IMU data buffer
+    unsigned pingpong;
+    bool dataReady;
+    SPI spi; 
+    DigitalOut cs; 
+    DigitalOut reset; 
+    DigitalOut diag; 
+    InterruptIn imuDataReady;
+    void InitImu(void);
+    void DataReadyISR(void);
+    int16_t Read(char);
+    void Write(char, char);        
+    void TogglePingpong() {pingpong = (~pingpong) & 1U;}; 
+    int16_t* GetBufferWritePtr() {return buffer[pingpong & 1U];};
+public:
+    ImuSpi(void);  
+    void BurstRead(void);
+    int16_t* GetBufferReadPtr() {return buffer[(~pingpong) & 1U];};    
+    bool IsDataReady(void);
+    int GetBufferSize(void) {return bufferSize*sizeof(int16_t);};
+    void reinitInterrupts(void);
+};
\ No newline at end of file
diff -r 000000000000 -r c6ee363ac724 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Aug 10 21:50:36 2011 +0000
@@ -0,0 +1,51 @@
+//
+// main.cpp
+//
+// Container class for mbed-based ADIS16355 IMU data acquisition system
+//
+// copyright 2010 Hugh Shane
+//
+#include "mbed.h"
+#include "imu-spi.h"
+#include "usb-serial.h"
+
+int main() {
+    DigitalOut diag_led(LED1);          
+    ImuSpi imu;
+    usb_serial_init();
+    char* imubuffer;
+    bool overflow;
+    Timer timer;
+    timer.start();
+    int now, last = 0, elapsed;
+    int nbytes = 12;
+     
+    while (1) {
+    
+        // acquire the IMU data
+        while (!imu.IsDataReady()) {} // wait for the IMU data-ready signal
+        now = timer.read_us(); // grab the elapsed time in microseconds
+        elapsed = now - last;
+        last = now;
+        imu.BurstRead(); // read the IMU output data registers
+        imubuffer = (char*)imu.GetBufferReadPtr(); // get a pointer to the IMU output data
+        
+        // transmit a data packet on the USB serial port
+        overflow = usb_serial_putc(0x55); // start of packet
+        overflow = usb_serial_putc((uint8_t)elapsed); // time marker, just the lower bits
+        
+        for (int i = 0; i < nbytes; i++) {
+            overflow = usb_serial_putc(*imubuffer++); // IMU data
+        }
+        
+        overflow = usb_serial_putc(0xAA); // end of packet
+
+        // diagnostic LED
+        if (overflow)
+            diag_led = 1;
+        else
+            diag_led = 0;
+            
+    }
+
+}
\ No newline at end of file
diff -r 000000000000 -r c6ee363ac724 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Aug 10 21:50:36 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/e2ac27c8e93e
diff -r 000000000000 -r c6ee363ac724 usb-serial.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usb-serial.cpp	Wed Aug 10 21:50:36 2011 +0000
@@ -0,0 +1,65 @@
+#include "mbed.h"
+#include "usb-serial.h"
+
+volatile unsigned wp, rp;
+static const int outbuf_size = 128;
+static const unsigned pointer_mask = 0x007fU;
+char usb_outbuf[outbuf_size];
+static bool overflow;
+DigitalOut mydiag(p22);;
+
+extern "C" static void txReadyISR() __irq {
+
+    mydiag = 1;
+    // If the output buffer has data, copy the head to the UART
+    if (rp != wp) {
+        LPC_UART0->THR = usb_outbuf[rp];
+        rp = (rp+1) & pointer_mask;
+    }
+    
+    // If the output buffer is empty, disable the transmit buffer empty 
+    // interrupt
+    if (rp == wp)
+       LPC_UART0->IER = 0;
+
+
+    mydiag = 0;
+}
+
+void usb_serial_init(void) {
+    
+    // init the output FIFO
+    wp = 0; rp = 0;
+    overflow = false;
+
+    // init the serial port
+    Serial usb_serial(USBTX, USBRX);    
+    usb_serial.baud(/*115200*/230400);
+    usb_serial.format(8, Serial::None, 1);
+    LPC_UART0->FCR = 7UL;
+    NVIC_SetVector(UART0_IRQn, (uint32_t)txReadyISR);
+    NVIC_EnableIRQ(UART0_IRQn);
+    LPC_UART0->THR = 0; // this is required to start the interrupts, don't understand why
+}
+
+bool usb_serial_putc(char c) {
+
+    if (overflow == false) {
+        usb_outbuf[wp] = c;      
+        LPC_UART0->IER = 0; // ---- critical
+        wp = (wp+1) & pointer_mask;
+
+        if (wp == rp)
+            overflow = true;
+        else
+            overflow = false;
+
+        LPC_UART0->IER = 2UL;  // ---- \critical
+    } else {
+        // reinit the output FIFO
+        wp = 0; rp = 0;
+        overflow = false;
+    }
+    
+    return overflow;
+}
\ No newline at end of file
diff -r 000000000000 -r c6ee363ac724 usb-serial.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usb-serial.h	Wed Aug 10 21:50:36 2011 +0000
@@ -0,0 +1,2 @@
+void usb_serial_init(void);
+bool usb_serial_putc(char);
\ No newline at end of file