Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
pat9125_mbed/pat9125_mbed.cpp
- Committer:
- pixus_mbed
- Date:
- 2017-10-03
- Revision:
- 0:411244c71423
- Child:
- 4:1cd61816c013
- Child:
- 5:61318505e528
File content as of revision 0:411244c71423:
#include "pat9125_mbed.h" #define delay(ms) wait_ms(ms) //define OTS state - X #define OTS_ROT_NO_CHANGE 0x00 #define OTS_ROT_UP 0x01 #define OTS_ROT_DOWN 0x02 //define downscale factor for rotation of shaft #define EXPECTED_COUNT_PER_ROUND 360 #define REAL_AVG_COUNT_PER_ROUND 446 //base on: sensor Reg0x0d=0x65, shaft diameter=2mm, sensor-to-shaft distance=2mm //define OTS state - Y #define OTS_BTN_NO_CHANGE 0x00 #define OTS_BTN_RELEASE 0x01 #define OTS_BTN_PRESS 0x02 #define LOW 0 #define HIGH 1 #define digitalRead(pin) *pin static pat9125_mbed_state_s *gp_state ; #define PIN_BTN_L gp_state->pBTN_L #define PIN_BTN_R gp_state->pBTN_R #define PIN_SEN_MOTION gp_state->pINT #define PIN_RLED gp_state->pRLED #define PIN_GLED gp_state->pGLED #define digitalWrite(pin,level) *pin = level #define LED_RED_ON digitalWrite(PIN_RLED,LOW) #define LED_RED_OFF digitalWrite(PIN_RLED,HIGH) #define LED_GREEN_ON digitalWrite(PIN_GLED,LOW) #define LED_GREEN_OFF digitalWrite(PIN_GLED,HIGH) #define attachInterrupt(pin,b,c) //pin->enable_irq() #define digitalPinToInterrupt(pin) pin #define detachInterrupt(pin) //pin->disable_irq() #define LCM_DisplayString_Reset gp_state->pLCM->LCM_DisplayString_Reset #define LCM_DisplayDecimal(a,b,c,d) gp_state->pLCM->LCM_DisplayDecimal(a,b,c,d) #define LCM_DisplayString(a,b,c) gp_state->pLCM->LCM_DisplayString(a,b,c) #define I2C_RESET gp_state->p_i2c = gp_state->p_i2c->reset(); //workaround for nRF51 mbed //for OTS signed int deltaX16; signed int deltaY16; unsigned char OTS_ROT_Status; unsigned char OTS_BTN_Status; signed long x_sum=0; signed long ds_x_sum=0; signed long pre_dsCountX=0; unsigned int OTS_BTN_Press_Cnt=0; volatile unsigned char MotionPinEventTriggered=0; // Register write function void OTS_Write_Reg(unsigned char address, unsigned char value) { int ret ; char data_write[2]; data_write[0] = address; data_write[1] = value; ret = gp_state->p_i2c->write(gp_state->slave_id, data_write, 2, 0); } // Register Read function unsigned char OTS_Read_Reg(unsigned char address) { unsigned char rdata = 0; gp_state->p_i2c->write(gp_state->slave_id, (char *)&address, 1, 0); gp_state->p_i2c->read(gp_state->slave_id, (char *)&rdata, 1, 0); return(rdata); } // Register write & read back check function void OTS_WriteRead_Reg(unsigned char address, unsigned char wdata) { unsigned char rdata; do { OTS_Write_Reg(address, wdata); // Write data to specified address rdata = OTS_Read_Reg(address); // Read back previous written data } while(rdata != wdata); // Check if the data is correctly written } boolean OTS_Sensor_Init(void) { unsigned char sensor_pid=0; boolean read_id_ok=false; // Read sensor_pid in address 0x00 to check if the serial link is valid, PID should be 0x31 sensor_pid = OTS_Read_Reg(0x00); if(sensor_pid == 0x31) { read_id_ok = true; //PAT9125 sensor recommended settings as below: OTS_Write_Reg(0x7F, 0x00); // switch to bank0, not allowed to perform OTS_WriteRead_Reg OTS_Write_Reg(0x06, 0x97); // Software Reset (i.e. set bit7 to 1), then it will reset to 0 automatically I2C_RESET; delay(1); // delay 1ms OTS_Write_Reg(0x06, 0x17); // ensure the sensor has left the reset state. OTS_WriteRead_Reg(0x09, 0x5A); // disable write protect OTS_WriteRead_Reg(0x0D, 0x65); // set X-axis resolution (depends on application) OTS_WriteRead_Reg(0x0E, 0xFF); // set Y-axis resolution (depends on application) OTS_WriteRead_Reg(0x19, 0x04); // set 12-bit X/Y data format (depends on application) //OTS_WriteRead_Reg(0x4B, 0x04); // ONLY for VDD=VDDA=1.7~1.9V: for power saving if(OTS_Read_Reg(0x5E) == 0x04) { OTS_WriteRead_Reg(0x5E, 0x08); if(OTS_Read_Reg(0x5D) == 0x10) OTS_WriteRead_Reg(0x5D, 0x19); } OTS_WriteRead_Reg(0x09, 0x00); // enable write protect } return read_id_ok; } // Read motion void OTS_Read_Motion(signed int *dx16, signed int *dy16) { int shift = (sizeof(signed int) << 3) - 12 ; signed int deltaX_l=0, deltaY_l=0, deltaXY_h=0; signed int deltaX_h=0, deltaY_h=0; char motion = OTS_Read_Reg(0x02) ; if(motion & 0x80) //check motion bit in bit7 { deltaX_l = OTS_Read_Reg(0x03); deltaY_l = OTS_Read_Reg(0x04); deltaXY_h = OTS_Read_Reg(0x12); deltaX_h = (deltaXY_h<<4) & 0xF00; deltaX_h = (deltaX_h << shift) >> shift ; //if(deltaX_h & 0x800) deltaX_h |= 0xfffff000; // 12-bit data convert to 16-bit deltaY_h = (deltaXY_h<<8) & 0xF00; //if(deltaY_h & 0x800) deltaY_h |= 0xfffff000; // 12-bit data convert to 16-bit deltaY_h = (deltaY_h << shift) >> shift ; } *dx16 = -(deltaX_h | deltaX_l); //inverse the data (depends on sensor's orientation and application) *dy16 = -(deltaY_h | deltaY_l); //inverse the data (depends on sensor's orientation and application) } void OTS_Reset_Variables(void) { //reset variables x_sum=0; ds_x_sum=0; pre_dsCountX=0; OTS_BTN_Press_Cnt=0; LCM_DisplayString_Reset(); } unsigned char Detect_Rotation(signed long dsCountX) { #define EVENT_NUM_PER_ROUND 360//10 #define EVENT_COUNT_TH (EXPECTED_COUNT_PER_ROUND / EVENT_NUM_PER_ROUND) //360/10=36 //360/360=1 signed long diff_count = 0; unsigned char OutRotState = OTS_ROT_NO_CHANGE; diff_count = dsCountX - pre_dsCountX; if( diff_count >= EVENT_COUNT_TH ) { pre_dsCountX = dsCountX; OutRotState = OTS_ROT_UP; } else if( diff_count <= (-EVENT_COUNT_TH) ) { pre_dsCountX = dsCountX; OutRotState = OTS_ROT_DOWN; } return OutRotState; } signed long OTS_Resolution_Downscale(signed int delta_count) { x_sum += delta_count; return (x_sum * EXPECTED_COUNT_PER_ROUND / REAL_AVG_COUNT_PER_ROUND); } unsigned char OTS_Detect_Rotation(signed int dx16, signed int dy16) { ds_x_sum = OTS_Resolution_Downscale(dx16); LCM_DisplayDecimal(1,12,ds_x_sum,4);//show downscale value return Detect_Rotation(ds_x_sum); } unsigned char OTS_Detect_Pressing(signed int dx16, signed int dy16) { #define PRESS 1 #define RELEASE 0 #define DX_ROTATE_TH 2 #define DY_VALID_TH 1 #define ACCY_PRESS_TH 5 #define DY_RELEASE_TH (-2) unsigned char OutBtnState = OTS_BTN_NO_CHANGE; static signed long AccY = 0; static unsigned char State = RELEASE; //0:release, 1:press if((dx16 >= DX_ROTATE_TH)||(dx16 <= (-DX_ROTATE_TH))) { AccY = 0; } else { if(State == PRESS) { if(dy16 <= DY_RELEASE_TH) { State = RELEASE; OutBtnState = OTS_BTN_RELEASE; } } else { if(dy16 < DY_VALID_TH) { AccY = 0; } else { AccY += dy16; if(AccY >= ACCY_PRESS_TH) { AccY = 0; State = PRESS; OutBtnState = OTS_BTN_PRESS; } } } } return OutBtnState; } //----------------------------------------------------------------------- void OTS_MotionPin_ISR(void) { detachInterrupt(digitalPinToInterrupt(PIN_SEN_MOTION)); MotionPinEventTriggered=1; } //----------------------------------------------------------------------- void loop() { if(digitalRead(PIN_BTN_L) == LOW)//or reset whenever idle_timer timeout { OTS_Reset_Variables(); } if(MotionPinEventTriggered==1) { MotionPinEventTriggered=0;//clear flag after read 'Motion Status and Data' OTS_Read_Motion(&deltaX16,&deltaY16); if(deltaX16 || deltaY16) { OTS_ROT_Status = OTS_Detect_Rotation(deltaX16,deltaY16); OTS_BTN_Status = OTS_Detect_Pressing(deltaX16,deltaY16); if(OTS_ROT_Status == OTS_ROT_UP) { LED_RED_ON; LCM_DisplayString(1,8,"Up "); } else if(OTS_ROT_Status == OTS_ROT_DOWN) { LED_GREEN_ON; LCM_DisplayString(1,8,"Dn "); } if(OTS_BTN_Status == OTS_BTN_PRESS) { OTS_BTN_Press_Cnt++; if(OTS_BTN_Press_Cnt > 999) { OTS_BTN_Press_Cnt=0; } LCM_DisplayString(2,8,"Pre"); LCM_DisplayDecimal(2,12,OTS_BTN_Press_Cnt,4); } else if(OTS_BTN_Status == OTS_BTN_RELEASE) { LCM_DisplayString(2,8,"Rel"); } } //re-enable interrupt for MOTION pin attachInterrupt(digitalPinToInterrupt(PIN_SEN_MOTION), OTS_MotionPin_ISR, LOW); } if(digitalRead(PIN_SEN_MOTION) == HIGH) { LED_GREEN_OFF; LED_RED_OFF; } } pat9125_mbed::pat9125_mbed(pat9125_mbed_state_s *state) { gp_state = state ; //gp_state->p_pc->printf("PAT9125 ADDR0 %x\n", OTS_Read_Reg(0)); gp_state->sen_status = OTS_Sensor_Init(); gp_state->p_pc->printf("OTS_Sensor_Init\n"); gp_state->pINT->fall(&OTS_MotionPin_ISR); //interrupt at low state } void pat9125_mbed::task() { if(digitalRead(PIN_SEN_MOTION) == LOW) { //gp_state->p_pc->printf("Motion Low\n"); MotionPinEventTriggered = 1 ; } loop(); }