PixArt / Mbed 2 deprecated PAT9125_OTS_L476RG

Dependencies:   mbed

Revision:
0:411244c71423
Child:
4:1cd61816c013
Child:
5:61318505e528
--- /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