PMT9123 OTS on Nucleo (Initial Release)

Fork of Pixart_9123_Nucleo_Library by PixArt Imaging

Revision:
0:7aefc9ab3301
--- /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