PMT9123 OTS on Nucleo (Initial Release)

Fork of Pixart_9123_Nucleo_Library by PixArt Imaging

Files at this revision

API Documentation at this revision

Comitter:
pixus_mbed
Date:
Thu May 11 17:32:04 2017 +0000
Commit message:
PMT9123 OTS on Nucleo (Initial Release)

Changed in this revision

OTC.cpp Show annotated file Show diff for this revision Revisions of this file
OTC.h Show annotated file Show diff for this revision Revisions of this file
PMT9123Set.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 7aefc9ab3301 OTC.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OTC.cpp	Thu May 11 17:32:04 2017 +0000
@@ -0,0 +1,192 @@
+#include "mbed.h"
+#include "PMT9123Set.h"
+#include "OTC.h"
+
+
+
+#define PMT9123_ADDR     (0x66) //PMT9123 address shift 1-bit
+#define I2C_ADDR PMT9123_ADDR
+#define PXI_PID 0x41
+#define DebounceT 300       //debounce time, unit:ms
+
+// Structure for motion data
+union 
+{
+  unsigned char d[10];
+  struct
+  {
+    unsigned char motion;
+    unsigned char deltaX;
+    unsigned char deltaY;
+    unsigned char deltaXY;
+    unsigned char squal;
+    //unsigned short shutter;
+    unsigned char shutterH;
+    unsigned char shutterL;
+    unsigned char pix_max;
+    unsigned char pix_avg;
+    unsigned char pix_min;
+  } m;
+} MotionData;
+
+
+Pixart_OTS::Pixart_OTS(I2C *i2c, int Period,OTSCallback callback,bool &Result)
+{    
+    m_i2c = i2c;
+    m_OTSCallback = callback;
+    //m_pc = pc;
+    m_Period = Period;
+    m_Address = 0x00;   // Default address to PID
+    
+    Result=PMT9123_init();    
+}
+
+
+
+bool Pixart_OTS::PMT9123_init()
+{
+    uint8_t v;
+   
+    // Power up sequence
+    // Drive NRESET low for 20us
+    //digitalWrite(PIN_NRESET_NCS,LOW);
+    //delayMicroseconds(20);
+    //digitalWrite(PIN_NRESET_NCS,HIGH);
+    // wait for 1.5ms
+    //delayMicroseconds(1500);
+   
+    // Enable register write
+    writeRegister(0x41, 0xba);
+    m_WriteEnable = true;   // set to true for the write below to not repeat turning on
+    wait_us(300);
+    // Write 0x00 to register 0x1D
+    Register_Write(0x1D, 0x00);
+    wait_ms(10);
+    v = Register_Read(0x1D);
+    // Check if the bit 0 to 4 is set or not
+    /*if (!IS_BIT_SET(v, 0x1F))
+    {
+        // Error handling
+        return false;
+    }*/
+    Register_Write(0x48, 0x10);      // Default resolution set to 2000 cpi
+
+    // Write in peformance optimization registers
+    for(v = 0; v < INIT_PMT9123_REG_ARRAY_SIZE; v++)
+        Register_Write(init_PMT9123_register_array[v][0], init_PMT9123_register_array[v][1]);
+
+    // Disable register write
+    writeRegister(0x41, 0xb5);
+    m_WriteEnable = false;   // set to false for subsequent write to enable and disable it when writing register
+    // Soft reset
+    writeRegister(0x3a, 0x96);
+
+    wait_ms(50);
+
+    
+    m_ticker.attach_us(this,&Pixart_OTS::periodicCallback, m_Period*1000);
+    
+    //m_pc->printf("\n\r~~~Start Real-time Gesture Demo~~~ \n\r");
+    
+    return true;
+}
+
+void Pixart_OTS::periodicCallback(void)
+{
+    PMT9123_ReadMotion();
+}
+
+void Pixart_OTS::PMT9123_ReadMotion(void)
+{
+    int16_t temp_deltaXH, temp_deltaYH, deltaX16bit, deltaY16bit; 
+    int i = 0;
+
+    // Normal motion reading
+    for (i = 0; i < 10; i++)
+    {
+      MotionData.d[i] = readRegister((0x02+i)); // using the single read version as motion cannot be double read and not affected
+    }
+
+    temp_deltaXH = (MotionData.m.deltaXY<<4) & 0xF00;
+    if(temp_deltaXH & 0x800)                 // -ve value spotted convert to 16-bit
+    {
+      temp_deltaXH |= 0xf000;
+    }                       
+    temp_deltaYH = (MotionData.m.deltaXY<<8) & 0xF00;
+    if(temp_deltaYH & 0x800)                 // -ve value spotted convert to 16-bit
+    {
+      temp_deltaYH |= 0xf000;
+    }  
+    
+    // Delta X is the vertical axis of the chip, only used if the ring can move up and down
+    deltaX16bit = MotionData.m.deltaX | temp_deltaXH;
+    // Delta Y is the value that it tracks on when turning the ring
+    deltaY16bit = MotionData.m.deltaY | temp_deltaYH;                        
+    
+    if (deltaY16bit != 0)
+        m_OTSCallback(deltaY16bit);
+}
+
+uint8_t Pixart_OTS::Register_Write(uint8_t addr, uint8_t data)
+{
+  uint8_t result;
+  unsigned char i = 1;
+  
+  switch (addr)
+  {
+    // if WO registers, just bail out with value 0
+    case 0x3A:
+    case 0x3B:
+    case 0x41:
+      i = 0;  // flag it
+      break;
+    default:
+      if (!m_WriteEnable)
+      {
+          // For others, we need to enale register write first
+          writeRegister(0x41, 0xba);
+          wait_us(300);
+      }
+      break;
+  }
+  writeRegister(addr, data);
+  if (i == 0)
+    return 0;
+  
+  // read back to confirm matching the write value, if not write again to maximum 3 times
+  while ((result = Register_Read(addr)) != data)
+  {
+    if (i++ >= 3)
+      break;
+    writeRegister(addr, data);
+  }
+  if (!m_WriteEnable)
+    writeRegister(0x41, 0xb5);
+  return result;
+}
+
+void Pixart_OTS::writeRegister(uint8_t addr, uint8_t data)
+{
+    char data_write[2];
+    
+    data_write[0] = addr;
+    data_write[1] = data;
+    m_i2c->write(I2C_ADDR, data_write, 2, 0);
+}
+
+uint8_t Pixart_OTS::Register_Read(uint8_t addr)
+{
+    readRegister(addr);
+    return readRegister(addr);  // only take second read as valid return value
+}
+
+uint8_t Pixart_OTS::readRegister(uint8_t addr)
+{
+    char data_write[2];
+    char data_read[2];
+    
+    data_write[0] = addr;
+    m_i2c->write(I2C_ADDR, data_write, 1, 0);
+    m_i2c->read(I2C_ADDR, data_read, 1, 0);
+    return data_read[0];
+}
\ No newline at end of file
diff -r 000000000000 -r 7aefc9ab3301 OTC.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OTC.h	Thu May 11 17:32:04 2017 +0000
@@ -0,0 +1,45 @@
+
+/* The callback function when motion happen
+   
+ */
+typedef  void (*OTSCallback)(int16_t value);
+
+// Helper macro
+#define BIT_CLEAR(REG,MASK)         (REG &= ~MASK)
+#define BIT_SET(REG,MASK)           (REG |=  MASK)
+#define IS_BIT_CLEAR(REG,MASK)      ((REG & MASK)==0x00)
+#define IS_BIT_SET(REG,MASK)        ((REG & MASK)==MASK)
+
+class Pixart_OTS
+{
+    private:
+       Ticker  m_ticker;
+       I2C     *m_i2c;
+       //Serial  *m_pc;
+       int m_Period;
+       uint8_t m_Address;
+       bool m_WriteEnable;
+       
+       OTSCallback m_OTSCallback;       
+       void periodicCallback(void);       
+       bool PMT9123_init();
+       void PMT9123_ReadMotion();
+       
+       // Internal read and write function that is only single transaction
+       void writeRegister(uint8_t addr, uint8_t data);
+       uint8_t readRegister(uint8_t addr);       
+       
+    public:           
+       /* 
+        * The initial function for Gesture class 
+        * i2c ==> The I2C object from outside, the clock rate should be 400k
+        * Period ==> The polling rate for gesture, in ms
+        * callback ==> The call back function for gesture status
+        * Result ==> The result for initialize
+        */
+       Pixart_OTS(I2C *i2c, int Period,OTSCallback callback,bool &Result);                                             
+       
+       // Public register read and write function, which include steps to ensure successful write and read
+       uint8_t Register_Write(uint8_t addr, uint8_t data);
+       uint8_t Register_Read(uint8_t addr);
+};
\ No newline at end of file
diff -r 000000000000 -r 7aefc9ab3301 PMT9123Set.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PMT9123Set.h	Thu May 11 17:32:04 2017 +0000
@@ -0,0 +1,35 @@
+const uint8_t init_PMT9123_register_array[][2] = {
+                        // Tracking Optimization
+                        {0x11,0xfc},
+                        {0x14,0xff},
+                        {0x38,0x17},
+                        {0x39,0x06},
+                        {0x25,0x0f}, 
+                        {0x27,0xaa}, 
+                        {0x34,0x80}, 
+                        {0x35,0x03}, 
+                        {0x39,0x89}, 
+                        {0x4d,0x79}, 
+                        {0x53,0x96}, 
+                        {0x58,0x66}, 
+                        {0x5d,0x56}, 
+                        {0x5e,0xf5}, 
+                        {0x5f,0xca}, 
+                        {0x61,0xd3}, 
+                        {0x6f,0xef}, 
+                        {0x70,0xb2}, 
+                        {0x7d,0xa2},
+                        // Latency Improvement
+                        {0x1c,0x24}, 
+                        {0x26,0xa2}, 
+                        {0x56,0x32}, 
+                        {0x65,0x1f}, 
+                        // Z-Height Optimization
+                        {0x75,0x2a}, 
+                        {0x76,0x00}, 
+                        {0x77,0x12}, 
+                        {0x7a,0x01}, 
+                        {0x7b,0x01}, 
+};
+
+#define INIT_PMT9123_REG_ARRAY_SIZE (sizeof(init_PMT9123_register_array)/sizeof(init_PMT9123_register_array[0]))