PMT9123 OTS on Nucleo (Initial Release)
Fork of Pixart_9123_Nucleo_Library by
Diff: OTC.cpp
- 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