PMT9123 OTS on Nucleo (Initial Release)

Fork of Pixart_9123_Nucleo_Library by PixArt Imaging

OTC.cpp

Committer:
pixus_mbed
Date:
2017-05-11
Revision:
0:7aefc9ab3301

File content as of revision 0:7aefc9ab3301:

#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];
}