PMT9123 OTS on Nucleo (Initial Release)
Fork of Pixart_9123_Nucleo_Library by
Revision 0:7aefc9ab3301, committed 2017-05-11
- Comitter:
- pixus_mbed
- Date:
- Thu May 11 17:32:04 2017 +0000
- Commit message:
- PMT9123 OTS on Nucleo (Initial Release)
Changed in this revision
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]))