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
Diff: pat9125_mbed/pat9125_mbed.cpp
- Revision:
- 0:411244c71423
- Child:
- 4:1cd61816c013
- Child:
- 5:61318505e528
diff -r 000000000000 -r 411244c71423 pat9125_mbed/pat9125_mbed.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pat9125_mbed/pat9125_mbed.cpp Tue Oct 03 07:26:38 2017 +0000
@@ -0,0 +1,336 @@
+
+#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();
+}
\ No newline at end of file
PAT9125EL - Miniature Optical Navigation for Surface Tracking