RM3100 SPI sample code

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
BeiZhang
Date:
Sun Mar 10 01:45:12 2019 +0000
Commit message:
RM3100 SPI Sample Code

Changed in this revision

RM3100.cpp Show annotated file Show diff for this revision Revisions of this file
RM3100.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
main.h 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
diff -r 000000000000 -r 71d5c1c75f0b RM3100.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RM3100.cpp	Sun Mar 10 01:45:12 2019 +0000
@@ -0,0 +1,431 @@
+/**
+* @file         RM3100.cpp
+*
+* @brief        Sample interface for RM3100.
+*
+* @authors      Betty Zhang
+* @date         05/21/2018
+* @copyright    (C) 2018 PNI Corp, Protonex LLC
+*
+* @copyright    Disclosure to third parties or reproduction in any form
+*               whatsoever, without prior written consent, is strictly forbidden
+*
+*/
+#include "RM3100.h"
+#include "main.h"
+
+void RM3100::ClearDrdyInt()
+{
+    //Clear Interrupt first
+    cs = 0;
+    spi.write(RM3100_STATUS_REG);
+    int status = spi.write(0x00);
+    cs = 1;
+    if (status & 0x80)
+    {
+        ReadRM3100();
+        status = 0;
+    }
+}
+    
+void RM3100::RunCMM(int flag)
+{
+    //Set current sample rate if it changes
+    if (sample_rate != prev_rate)
+    {
+        SetSampleRateReg(sample_rate);
+        prev_rate = sample_rate;
+    }
+    
+    if (flag) {
+        //Set Cycle Count if it changes
+        SetCycleCountReg();
+
+        //Confirm new setting and update "gain"
+        DisplayCycleCount();
+    }
+
+    RegCMM cmm_reg;
+    cmm_reg.bits.LDM = 0;
+    cmm_reg.bits.CMX = 1;
+    cmm_reg.bits.CMY = 1;
+    cmm_reg.bits.CMZ = 1;
+    cmm_reg.bits.Drdm = 2; //0 on any axis, 2 Drdy after completion of XYZ
+    cmm_reg.bits.Alarm = 0;
+
+    if (flag) {
+        //Start CMM run
+        cmm_reg.bits.Start = 1;
+        cmm_reg.bits.CMX = 1;
+        cmm_reg.bits.CMY = 1;
+        cmm_reg.bits.CMZ = 1;
+    } else {
+        //Stop CMM run
+        cmm_reg.bits.Start = 0;
+        cmm_reg.bits.CMX = 0;
+        cmm_reg.bits.CMY = 0;
+        cmm_reg.bits.CMZ = 0;
+    }
+    
+    cs = 0;
+    spi.write(RM3100_CMM_REG);
+    spi.write(cmm_reg.reg);
+    cs = 1;
+}
+
+void RM3100::ChangeSampleRate(int flag)
+{
+    if (flag > 0)
+        sample_rate *= 2; //increase 2 times
+    if (flag < 0)
+        sample_rate /= 2; //decrease 2 times
+    
+    if (sample_rate < 1)
+        sample_rate = 1; //1hz
+    else if (sample_rate > 600)
+        sample_rate = 600;
+}
+
+void RM3100::SetSampleRateReg(int rate)
+{
+    int value;
+    
+    sample_rate = rate;
+        
+    if ((rate <= 600) && (rate >= 300))
+        value = 0x92;
+    else if ((rate < 300) && (rate >= 150))
+        value = 0x93;
+    else if ((rate < 150) && (rate >= 75))
+        value = 0x94;
+    else if ((rate < 75) && (rate >= 37))
+        value = 0x95;
+    else if ((rate < 37) && (rate >= 18))
+        value = 0x96;
+    else if ((rate < 18) && (rate >= 9))
+        value = 0x97;
+    else if ((rate < 9) && (rate >= 4))
+        value = 0x98;
+    else if ((rate < 4) && (rate >= 3))
+        value = 0x99;
+    else if ((rate < 3) && (rate >= 2))
+        value = 0x9A;
+    else if ((rate < 2) && (rate >= 1))
+        value = 0x9B;   //About 1Hz
+    else 
+        value = 0x9C;   //About 0.6Hz
+        
+    cs = 0;
+    //set sample rate
+    spi.write(RM3100_TMRC_REG);
+    spi.write(value); //about 1Hz
+    cs = 1;
+}
+
+int RM3100::GetSampleRate(int *tmrc_reg_val)
+{
+    cs = 0;
+    //set sample rate
+    spi.write(RM3100_TMRC_REG | 0x80); //Read TMRC reg
+    * tmrc_reg_val = spi.write(0);
+    cs = 1;
+    
+    return sample_rate;
+}
+    
+void RM3100::ReadRM3100()
+{
+    int mag[9];
+    int count[3];
+
+    __disable_irq();    // Disable Interrupts
+    cs = 0;
+    spi.write(RM3100_MX_REG);
+
+    comport.printf("Mag = 0x");
+    for (int i = 0; i < 9; i++) {
+        mag[i] = spi.write(0x00);
+        comport.printf("%x", mag[i]);
+        if ((i < 8) && ((i+1) % 3) == 0)
+            comport.printf(" 0x");
+    }
+    cs = 1;
+        
+    comport.printf(", ");
+    //Process the 24-bit signed measurement in count
+    int measurement = 0;
+    int index = 0;
+    for (int j = 0; j < 9; j += 3) {
+        if (mag[j] & 0x80)
+            measurement = 0xFF;
+        measurement <<= 24; //left shift 24-bit
+        measurement |= (mag[j+2] | (mag[j+1] | (mag[j] << 8)) << 8);
+        comport.printf("%d ", measurement);
+        count[index] = measurement;
+        measurement = 0;
+        index++;
+    }
+
+    comport.printf(", ");
+    //Convert to uT (microTesla)
+    for (int k = 0; k < 3; k++) {
+        comport.printf("%5.3fuT ", (float)count[k]/current_gain[k]);
+    }
+
+    comport.printf("\n\r");
+    
+    __enable_irq();     // Enable Interrupts
+
+}
+
+void RM3100::SetDrdyIntFlag(u8 flag)
+{
+    rm3100_service_flag = flag;
+    if (flag)
+        drdy.disable_irq();
+    else
+        drdy.enable_irq();
+}
+
+u8 RM3100::GetDrdyIntFlag(void)
+{
+    return rm3100_service_flag;
+}
+
+void RM3100::ProcessDrdyInt()
+{
+    SetDrdyIntFlag(1);
+}
+
+void RM3100::DrdyCallBack(void)
+{
+    // attach ProcessDrdyInt function of this RM3100 instance
+    drdy.rise(callback(this, &RM3100::ProcessDrdyInt)); 
+}
+
+void RM3100::DisplayCycleCount()
+{
+    int cc[6];
+    int c_count[3];
+    float maxrate;
+
+    //Read CC reg
+    __disable_irq();    // Disable Interrupts
+    cs = 0;
+    int cc_reg = RM3100_CCXLSB_REG | 0x80; //"| 0x80" to read CC Reg
+    spi.write(cc_reg);
+
+    comport.printf("CC = 0x");
+    for (int i = 0; i < 6; i++) {
+        cc[i] = spi.write(0);
+        comport.printf("%x", cc[i]);
+        if ((i < 5) && ((i+1) % 2) == 0)
+            comport.printf(" 0x");
+    }
+    cs = 1;
+
+    comport.printf(", ");
+    //Process the 16-bit unsigned cycle count
+    int temp = 0;
+    int index = 0;
+    for (int j = 0; j < 6; j += 2) {
+        if (cc[j] & 0x80)
+            temp = 0xFF;
+        temp <<= 8; //left shift 8-bit
+        temp |= (cc[j+1] | (cc[j] << 8));
+        c_count[index++] = temp; //save CC values 
+        comport.printf("%d ", temp);
+        temp = 0;
+    }
+
+    //Calculate gain from CC, gain = 0.375 * cc;
+    comport.printf(", Gain = ");
+    for (int k = 0; k < 3; k++) {
+        if (c_count[k])
+            current_gain[k] = c_count[k] * DEFAULTGAIN/DEFAULTCCOUNT;
+        comport.printf("%d ", current_gain[k]);
+    }
+    
+    //Calculate max sample rate, assume CC same for 3 axes
+    if (c_count[0] == 50)
+        maxrate = 1600.0 / 3.0;
+    else if (c_count[0] == 100)
+        maxrate = 850.0 / 3.0;
+    else if (c_count[0] == 200)
+        maxrate = 440.0 / 3.0;
+    else if (c_count[0] == 225)
+        maxrate = 370.0 / 3.0;
+    else if (c_count[0] == 250)
+        maxrate = 350.0 / 3.0;
+    else if (c_count[0] < 100)
+        maxrate = (-15.0 * c_count[0] + 2350.0) / 3.0;
+    else if (c_count[0] < 225)
+        maxrate = (-14.0 * c_count[0]/5.0 + 1000.0) / 3.0;
+    else if (c_count[0] < 250)
+        maxrate = (-4.0 * c_count[0]/5.0 + 550.0) / 3.0;
+    else if (c_count[0] <= 400)
+        maxrate = (-4.0 * c_count[0] /5.0 + 550.0) / 3.0;
+
+    comport.printf("MaxRate = %3.2f Hz\n\r", maxrate);
+
+    __enable_irq();     // Enable Interrupts
+}
+
+void RM3100::DisplayREVIDReg()
+{
+    //Read REVID reg
+    __disable_irq();    // Disable Interrupts
+    cs = 0;
+    int reg = RM3100_REVID_REG;
+    spi.write(reg);
+    int revid = spi.write(0);
+    __enable_irq();    // Enable Interrupts
+    cs = 1;
+
+    comport.printf("RM3100 REVID = %2D\n\r", revid);
+}
+
+void RM3100::SelfTest()
+{
+    comport.printf("SelfTest \n\r");
+
+    RegBIST regbist;
+    RegPOLL regpoll;
+
+    //Set BIST
+    //bit#7 STE=1, bit#6#5#4 = 0, bit#3 BW1=1, bit#2 BW0=1, bit#1 BP1=1, bit#0 BP0=1
+    regbist.bits.BP = 3;
+    regbist.bits.BW = 3;
+    regbist.bits.XYZOK = 0;
+    regbist.bits.STE = 1;
+
+    //Set POLL reg
+    regpoll.bits.LowNibble = 0;
+    regpoll.bits.PMX = 1;
+    regpoll.bits.PMY = 1;
+    regpoll.bits.PMZ = 1;
+    regpoll.bits.MSB = 0;
+
+    //Start Self Test
+    __disable_irq();    // Disable Interrupts
+    cs = 0;
+
+    //stop continuous mode
+    spi.write(RM3100_CMM_REG);
+    spi.write(0);
+    cs = 1;
+
+    cs = 0;
+    spi.write(RM3100_BIST_REG);
+    spi.write(regbist.reg);
+    comport.printf("bist val= 0x%X, poll val = 0x%X \n\r", regbist.reg, regpoll.reg);
+
+    cs = 1;
+
+    cs = 0;
+    //POLL 1 measurement on XYZ
+    spi.write(RM3100_POLL_REG);
+    spi.write(regpoll.reg);
+    cs = 1;
+
+    //Get result
+    cs = 0;
+    spi.write(RM3100_STATUS_REG | 0x80);
+    int value = spi.write(0);
+    comport.printf("Poll a measurement and Check status reg val = 0x%X \n\r", value);
+
+    cs = 1;
+
+    if (value) {
+        //Read RM3100_BIST_REG;
+        cs = 0;
+        spi.write(RM3100_BIST_REG | 0x80);
+        value = spi.write(0);
+        cs = 1;
+
+        //Check result here
+        comport.printf("Check BIST reg 0x%X\n\r", value);
+        if (value & 0x70)
+            comport.printf("Result = 0x%X Pass\n\r", value);
+        else
+            comport.printf("Result = 0x%X Fail\n\r", value);
+
+    } else
+        comport.printf("Measurement not Ready\n\r");
+
+    //It's important to Reset SeltTest reg
+    cs = 0;
+    spi.write(RM3100_BIST_REG);
+    spi.write(0);
+    cs = 1;
+
+    __enable_irq();    // Enable Interrupts
+
+}
+
+void RM3100::ChangeCycleCount(int flag)
+{    
+    for (int i = 0; i < 3; i++)
+    {
+        if (flag > 0) 
+        {
+            current_ccount[i] += 10;
+        } 
+        else if (flag < 0) 
+        {
+            current_ccount[i] -= 10;
+        }
+        
+        if (current_ccount[i] < LOWERCYCLECOUNT)
+            current_ccount[i] = LOWERCYCLECOUNT;
+            
+        if (current_ccount[i] > UPPERCYCLECOUNT)
+            current_ccount[i] = UPPERCYCLECOUNT;
+          
+    }
+}
+
+
+//Set Cycle Count Reg
+void RM3100::SetCycleCountReg()
+{   
+    static int prev_ccount = DEFAULTCCOUNT;
+    
+    //Check any changes on CC. Should check 3 axes, just X-axis as example
+    if (prev_ccount != current_ccount[0]) {
+        
+        prev_ccount = current_ccount[0];
+
+        //Read CC reg
+        __disable_irq();    // Disable Interrupts
+        cs = 0;
+        int cc_reg = RM3100_CCXLSB_REG;
+        spi.write(cc_reg);
+
+        for (int i = 0; i < 3; i++) {
+            spi.write((current_ccount[i] & 0xFF00)>>8); //MSB
+            spi.write(current_ccount[i] & 0x00FF); //LSB
+        }
+        cs = 1;
+
+        __enable_irq();     // Enable Interrupts
+    }
+}
+
+
+//constructor
+RM3100::RM3100(): rm3100_service_flag(0),   //init to 0
+    sample_rate(1), //init to 1 Hz
+    prev_rate(1),  //init to 1 Hz
+    cs(SPI_CS),     //init to SPI_CS
+    drdy(D9),        //init to D9
+    spi(SPI_MOSI, SPI_MISO, SPI_SCK) //spi pins init
+{ 
+    //Init to default
+    for (int i = 0; i < 3; i++)
+    {
+        current_ccount[i] = DEFAULTCCOUNT;
+        current_gain[i] = DEFAULTGAIN;
+    }
+        
+};
diff -r 000000000000 -r 71d5c1c75f0b RM3100.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RM3100.h	Sun Mar 10 01:45:12 2019 +0000
@@ -0,0 +1,210 @@
+/**
+* @file         RM3100.h
+*
+* @brief        Sample interface for RM3100.
+*
+* @authors      Betty Zhang
+* @date         05/21/2018
+* @copyright    (C) 2018 PNI Corp, Protonex LLC
+*
+* @copyright    Disclosure to third parties or reproduction in any form
+*               whatsoever, without prior written consent, is strictly forbidden
+*
+*/
+#include "mbed.h"
+
+
+// Global typedef
+typedef signed char     s8;
+typedef char            u8;    
+typedef short           s16;   
+typedef unsigned short  u16;   
+typedef int             s32;   
+typedef unsigned int    u32;   
+typedef unsigned long   u64;
+
+//RM3100 Registers 
+#define RM3100_POLL_REG     0x00 /**< RW; Poll for a single measurement*/
+#define RM3100_CMM_REG      0x01 /**< RW; Initiate continuous measurement mode*/
+#define RM3100_CCXLSB_REG   0x04 /**< RW; Cycle count X-axis */
+#define RM3100_CCXMSB_REG   0x05
+#define RM3100_CCYLSB_REG   0x06 /**< RW; Cycle count Y-axis */
+#define RM3100_CCYMSB_REG   0x07
+#define RM3100_CCZLSB_REG   0x08 /**< RW; Cycle count Z-axis */
+#define RM3100_CCZMSB_REG   0x09
+#define RM3100_TMRC_REG     0x0B /**< RW; Set data rate in continuous measurement mode*/
+#define RM3100_MX_REG       0x24 /**< RW; Measurement Result X-axis, Signed 24-bit */
+#define RM3100_BIST_REG     0x33 /**< RW; Built-in self test */
+#define RM3100_STATUS_REG   0x34 /**< R; Status of DRDY */
+#define RM3100_REVID_REG    0x36 /**< R; Revision ID, default 0x22 */
+
+//RM3100 Default values
+#define DEFAULTCCOUNT 200 //200
+#define DEFAULTGAIN 75    //200 Cycle Count, Gain 75
+
+//Other Settings
+#define UPPERCYCLECOUNT 400
+#define LOWERCYCLECOUNT 30
+
+
+ /**
+ * \brief Host interface control
+ */
+#pragma pack(push, 1)
+typedef union RegCMM
+{
+    /**
+    * \brief Direct access to the complete 8bit register
+    */
+    u8 reg;
+    /**
+    * \brief Access to individual bits in the register.
+    */
+    struct
+    {
+        u8 Start : 1;             /**< bit 0: Initiate Continuous Measurement Mode */
+        u8 Alarm : 1;             /**< bit 1: Go high if measurment outside a prefefined range */
+        u8 Drdm :  2;             /**< bit 2: DRDM bits establish required condition to trigger DRDY */
+                                  /**< 0 = drdy high when Alarm = 1 and complete of full measurement set by CMX CMY CMZ */
+                                  /**< 1 = drdy high after complete of measurement on any axis */
+                                  /**< 2 = drdy high after complete of full measurement set by CMX CMY CMZ */
+                                  /**< 3 = drdy high when Alarm = 1 */
+        u8 CMX : 1;               /**< bit 4: 1 means measurement on this Axis */
+        u8 CMY : 1;               /**< bit 5: 1 means measurement on this Axis */
+        u8 CMZ : 1;               /**< bit 6: 1 means measurement on this Axis */
+        u8 LDM : 1;               /**< bit 7: 0 absolute alarm mode, 1 relative alarm mode */
+    }
+    bits;
+}
+RegCMM;                          /**< typedef for storing CMM register values */
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef union RegTMRC
+{
+    /**
+    * \brief Direct access to the complete 8bit register
+    */
+    u8 reg;
+    /**
+    * \brief Access to individual bits in the register.
+    */
+    struct
+    {
+        u8 TMRC : 4;             /**< bit 0 - 3: Time between measurement in CCM moden 1-axis */
+                                 /**< value 0b0010 to 0b1111, 0x2 to 0xF, bigger value longer interval */
+        u8 Resv : 4;             /**< bit 4 - 7: Fixed as 0b1001, 0x9 */
+    }
+    bits;
+}
+RegTMRC;                          /**< typedef for storing TMRC register values */
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef union RegBIST
+{
+    /**
+    * \brief Direct access to the complete 8bit register
+    */
+    u8 reg;
+    /**
+    * \brief Access to individual bits in the register.
+    */
+    struct
+    {
+        u8 BP : 2;             /**< bit 0-1: Define number of LR periods for measurement */
+                               /**< 0 = unused */
+                               /**< 1 = 1 LR Period */
+                               /**< 2 = 2 LR Periods */
+                               /**< 3 = 4 LR Periods */
+        u8 BW : 2;             /**< bit 2-3: Define timeout period for LR oscillator perriod */
+                               /**< 0 = unused */
+                               /**< 1 = 1 sleep oscillation cycle,  30us */
+                               /**< 2 = 2 sleep oscillation cycles,  60us */
+                               /**< 3 = 4 sleep oscillation cycles,  120us */
+        u8 XYZOK : 3;          /**< bit 4-6: Read only */
+                               /**< bit 4: 1 X ok, 0 not ok */
+                               /**< bit 5: 1 Y ok, 0 not ok */
+                               /**< bit 6: 1 Z ok, 0 not ok */
+        u8 STE : 1;            /**< bit 7: write 1 to enable the self test */
+    }
+    bits;
+}
+RegBIST;                          /**< typedef for storing TMRC register values */
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+typedef union RegPOLL
+{
+    /**
+    * \brief Direct access to the complete 8bit register
+    */
+    u8 reg;
+    /**
+    * \brief Access to individual bits in the register.
+    */
+    struct
+    {
+        u8 LowNibble : 4;      /**< bit 0-3: Reserved */
+        u8 PMX : 1;            /**< bit 4: Measure X axis */
+        u8 PMY : 1;            /**< bit 5: Measure Y axis */
+        u8 PMZ : 1;            /**< bit 6: Measure Z axis */
+        u8 MSB : 1;            /**< bit 7: Reserved */
+    }
+    bits;
+}
+RegPOLL;                          /**< typedef for storing TMRC register values */
+#pragma pack(pop)
+
+
+//RM3100 class
+class RM3100
+{
+
+public:
+    void ClearDrdyInt(void);
+    
+    void RunCMM(int flag);
+    
+    void ChangeSampleRate(int flag);
+    
+    void SetSampleRateReg(int rate); 
+    
+    int GetSampleRate(int * reg_val); 
+    
+    void ChangeCycleCount(int flag);
+    
+    void SetCycleCountReg();
+
+    void ReadRM3100(); 
+    
+    void SetDrdyIntFlag(u8 flag);
+    
+    u8 GetDrdyIntFlag(void);
+    
+    void DrdyCallBack(void);
+    
+    void ProcessDrdyInt(void);
+    
+    void DisplayCycleCount();
+    
+    void DisplayREVIDReg();
+        
+    void SelfTest();
+    
+    //constructor
+    RM3100();
+    
+private:
+    u8 rm3100_service_flag;
+    int current_gain[3];
+    int current_ccount[3];
+    int sample_rate;
+    int prev_rate;
+    
+    DigitalOut cs; //ssel
+    InterruptIn drdy; //Drdy pin D9
+    
+    SPI spi;
+
+};
diff -r 000000000000 -r 71d5c1c75f0b main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Mar 10 01:45:12 2019 +0000
@@ -0,0 +1,189 @@
+/**
+* @file         main.cpp
+*
+* @brief        Sample interface for RM3100.
+*
+* @authors      Betty Zhang
+* @date         05/21/2018
+* @copyright    (C) 2018 PNI Corp, Protonex LLC
+*
+* @copyright    Disclosure to third parties or reproduction in any form
+*               whatsoever, without prior written consent, is strictly forbidden
+*
+*/
+
+#include "mbed.h"
+#include "main.h"
+#include "RM3100.h"
+
+
+Serial comport(SERIAL_TX, SERIAL_RX);
+
+RM3100 rm3100;
+
+//Global variables
+int serial_inchar;
+float actual_rate;
+
+void OnSerial(void)
+{
+    serial_inchar = comport.getc();
+}
+
+//=============================================================================
+//  Serial input Character (Key) Commands, courtesy of JM.
+//=============================================================================
+// This function is called upon every incomming serial character 
+void processSerialInchar(char key)
+{
+    // The Simple Serial protocal mostly consists of single character commands
+    // send '?' to list available commands
+
+    serial_inchar = NULL;
+    int tmrc_val, rate;
+
+    switch (key) {
+        case '+':
+            rm3100.ChangeSampleRate(1);
+            break;
+
+        case '-':
+            rm3100.ChangeSampleRate(-1);
+            break;
+
+        case '>':
+            rm3100.ChangeCycleCount(1);
+            break;
+
+        case '<':
+            rm3100.ChangeCycleCount(-1);
+            break;
+
+        case 'a':
+            rm3100.DisplayREVIDReg();
+            break;
+        case 'b':
+            rate = rm3100.GetSampleRate(&tmrc_val);
+            comport.printf("Host process rate = %3.1f Hz, reqRate = %d, TMRC=0x%X\n\r",actual_rate, rate, tmrc_val);
+            break;
+        case 'c':
+            rm3100.DisplayCycleCount();
+            break;
+
+        case 'q':
+            rm3100.SelfTest();
+            break;
+        case 'r':
+            rm3100.RunCMM(1); //Run CMM
+            rm3100.ClearDrdyInt();
+            break;
+
+        case 's':
+            rm3100.RunCMM(0); //Stop
+            rate = rm3100.GetSampleRate(&tmrc_val);
+            comport.printf("Host process rate = %3.1f Hz, reqRate = %d, TMRC=0x%X\n\r",actual_rate, rate, tmrc_val);
+            break;
+
+        case '?': {
+            u8 bar[45];
+            memset(bar, 205, sizeof(bar));
+            bar[sizeof(bar)-1] = 0;
+            comport.printf("\n\r");
+            comport.printf("                  RM3100 Commands\n\r");
+            comport.printf("                  Revision: %s\n\r",REVISION);
+            comport.printf("  %c%s%c\n\r", 201, bar, 187);
+            comport.printf("  %c        Commands  (case sensitive)          %c\n\r", 186, 186);
+            // Status and configuration
+            comport.printf("  %c%s%c\n\r", 204, bar, 185);
+            comport.printf("  %c         Settings and Status                %c\n\r", 186, 186);
+            comport.printf("  %c%s%c\n\r", 204, bar, 185);
+            comport.printf("  %c a : Display REVID                          %c\n\r", 186, 186);
+            comport.printf("  %c b : Display host rate, request rate & TMRC %c\n\r", 186, 186);
+            comport.printf("  %c c : Display cycle count, gain & max rate   %c\n\r", 186, 186);
+            comport.printf("  %c + : Increase Sample Rate                   %c\n\r", 186, 186);
+            comport.printf("  %c - : Decrease Sample Rate                   %c\n\r", 186, 186);
+            comport.printf("  %c > : Increase Cycle Count                   %c\n\r", 186, 186);
+            comport.printf("  %c < : Decrease Cycle Count                   %c\n\r", 186, 186);
+
+            // Tests
+            comport.printf("  %c%s%c\n\r", 204, bar, 185);
+            comport.printf("  %c                  Tests                     %c\n\r", 186, 186);
+            comport.printf("  %c%s%c\n\r", 204, bar, 185);
+            comport.printf("  %c q : Run sensor Self tests                  %c\n\r", 186, 186);
+            comport.printf("  %c r : Run continous mode                     %c\n\r", 186, 186);
+            comport.printf("  %c s : Stop continous mode                    %c\n\r", 186, 186);
+
+            comport.printf("  %c%s%c\n\r", 200, bar, 188);
+
+        }
+        default:
+            break;
+    }
+}
+        
+int main() {
+    
+    int counter = 0;
+    Timer timer;
+    
+    
+    // Init user serial interface
+    comport.baud(921600);
+    comport.printf("\n\rRM3100 Host SPI Sample Code Ver %s on mBed\n\r",REVISION);
+        
+    //Set sample rate
+    rm3100.SetSampleRateReg(1); //in Hz
+                
+    //Start to CMM run
+    rm3100.RunCMM(1);
+   
+    // Setup interrupt callback functions
+    comport.attach(&OnSerial);  // user input from serial term 
+    
+    // Callback function to the rising edge
+    rm3100.DrdyCallBack();
+    
+    //Clear Interrupt first
+    rm3100.ClearDrdyInt();
+        
+    while (1) 
+    {
+
+        if (serial_inchar) 
+        {
+            processSerialInchar(serial_inchar); // process user key commands
+            serial_inchar = NULL;
+        }
+        
+        if (counter <= 1)
+            timer.start();
+        else if (counter >= 10)
+        {
+            timer.stop();
+            float time = timer.read();
+            actual_rate = 10.0/time;
+            if (actual_rate <= 150) {
+                __disable_irq();    // Disable Interrupts
+                comport.printf("Counter=%d, time=%3.3f s, Host Proc rate = %3.1f Hz\n\r",counter, time, actual_rate);
+                __enable_irq();    // Enable Interrupts
+            }
+            counter = 0;
+            timer.reset();
+        }
+        
+        //Process Drdy Interrupt
+        if (rm3100.GetDrdyIntFlag())
+        {
+            rm3100.SetDrdyIntFlag(0);
+            
+            //If sample rate is higher than 150Hz, serial port cannot process in time
+            //skip samples to make the host keep up, but to clear drdy interrupt
+            if ((actual_rate <= 150) || (counter == 1))
+                rm3100.ReadRM3100();
+            else
+                rm3100.ClearDrdyInt(); 
+            
+            counter++;
+        }
+    }
+}
diff -r 000000000000 -r 71d5c1c75f0b main.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.h	Sun Mar 10 01:45:12 2019 +0000
@@ -0,0 +1,22 @@
+
+/**
+* @file         main.h
+*
+* @brief        Sample interface for RM3100.
+*
+* @authors      Betty Zhang
+* @date         05/21/2018
+* @copyright    (C) 2018 PNI Corp, Protonex LLC
+*
+* @copyright    Disclosure to third parties or reproduction in any form
+*               whatsoever, without prior written consent, is strictly forbidden
+*
+*/
+
+#include "mbed.h"
+
+#define REVISION "1.0"
+
+extern SPI spi;
+extern DigitalOut cs; //ssel
+extern Serial comport;
diff -r 000000000000 -r 71d5c1c75f0b mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sun Mar 10 01:45:12 2019 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/5aab5a7997ee
\ No newline at end of file