yono / Mbed 2 deprecated Pixart

Dependencies:   BLE_API mbed nRF51822 paw8001motion32_5_m0_keil_split

Fork of Pixart by Lonnie Zhang

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001  /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "mbed.h"
00018 #include "BLE.h"
00019 #include "HeartRateService.h"
00020 #include "BatteryService.h"
00021 #include "DeviceInformationService.h"
00022 
00023 BLEDevice  ble;
00024 DigitalOut led1(LED1);
00025 /* ---------------------------------------------------------------
00026  * Below for PAH8001 code
00027 *///--------------------------------------------------------------
00028 #include "app_util_platform.h"
00029 #include "nrf_soc.h"
00030 #include "app_util.h"
00031 #include "PAH8001Set.h"
00032 extern "C"
00033 {
00034     #include "pxialg.h"
00035 }
00036 Serial  pc(USBTX, USBRX);
00037 I2C i2c(I2C_SDA0, I2C_SCL0);
00038 Ticker  ticker;
00039 /* Power optimized, 1.0mA @disconnection, 4.5mA @connection */
00040 #define MIN_CONN_INTERVAL   MSEC_TO_UNITS(379, UNIT_1_25_MS)              /**< Minimum connection interval (379 ms) */
00041 #define MAX_CONN_INTERVAL   MSEC_TO_UNITS(399, UNIT_1_25_MS)              /**< Maximum connection interval (399 ms). */
00042 #define SLAVE_LATENCY       4                                             /**< Slave latency. */
00043 #define CONN_SUP_TIMEOUT    MSEC_TO_UNITS(6000, UNIT_10_MS)               /**< Connection supervisory timeout (6 seconds). */
00044 void rs232talk(void);
00045 /* ---------------------------------------------------------------
00046  * End of PAH8001 code
00047 *///--------------------------------------------------------------
00048 
00049 const static char     DEVICE_NAME[]        = "PixArt_HRmbed";
00050 static const uint16_t uuid16_list[]        = {GattService::UUID_HEART_RATE_SERVICE,
00051                                               GattService::UUID_BATTERY_SERVICE,
00052                                               GattService::UUID_DEVICE_INFORMATION_SERVICE};
00053  /* ---------------------------------------------------------------
00054  * Below for PAH8001 code
00055 *///--------------------------------------------------------------
00056 static volatile bool  triggerSensorPolling = false;
00057 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
00058 {
00059     ble.gap().startAdvertising();
00060     triggerSensorPolling = false;
00061     PxiAlg_Close();//close and reset algorithm
00062 }
00063 
00064 void onconnectionCallback(const Gap::ConnectionCallbackParams_t *p_conn_param)
00065 //void onconnectionCallback(Gap::Handle_t handle, Gap::addr_type_t peerAddrType, const Gap::address_t peerAddr, const Gap::ConnectionParams_t *p_conn_param)
00066 {
00067     triggerSensorPolling = true;
00068     Gap::ConnectionParams_t gap_conn_params;
00069     gap_conn_params.minConnectionInterval = MIN_CONN_INTERVAL;
00070     gap_conn_params.maxConnectionInterval = MAX_CONN_INTERVAL;
00071     gap_conn_params.slaveLatency = SLAVE_LATENCY;
00072     gap_conn_params.connectionSupervisionTimeout = CONN_SUP_TIMEOUT;
00073     ble.gap().updateConnectionParams(p_conn_param->handle, &gap_conn_params);
00074 }
00075 
00076 void periodicCallback(void)
00077 {uint8_t tmp;
00078     if(triggerSensorPolling == true){
00079         HR_Cnt++;
00080         //CRITICAL_REGION_ENTER();
00081         Pixart_HRD();
00082         //CRITICAL_REGION_EXIT();
00083         
00084         led1 = 1;
00085         if(Pop(&ppg_mems_data)) //Get data from FIFO
00086         {
00087             MEMS_Data[0] = ppg_mems_data.MEMS_Data[0];
00088             MEMS_Data[1] = ppg_mems_data.MEMS_Data[1];
00089             MEMS_Data[2] = ppg_mems_data.MEMS_Data[2];
00090             
00091             tmp = PxiAlg_Process(ppg_mems_data.HRD_Data, MEMS_Data);
00092             if( tmp != FLAG_DATA_READY)
00093             {
00094                 pc.printf("AlgoProcssRtn: %d\n\r", tmp);
00095                 pc.printf("PPG[8]: %d\n\r", ppg_mems_data.HRD_Data[8]);
00096             }
00097             else{
00098                 PxiAlg_HrGet(&myHR);
00099                 PxiAlg_GetSigGrade(&grade);
00100             }
00101         }
00102         led1 = 0;
00103         
00104         
00105     }
00106     else
00107         HR_Cnt = 0;
00108 }
00109 
00110 int main(void)
00111 {
00112     pc.baud (115200);
00113     pc.printf("\n\rStart initialization\n\r");  
00114     i2c.frequency(400000);  
00115     
00116     led1 = 1;
00117     PAH8001_init(); //PAH8001 initialization
00118 
00119     ble.init();
00120     ble.gap().onDisconnection(disconnectionCallback);
00121     ble.gap().onConnection(onconnectionCallback);
00122     /* Setup primary service. */
00123     uint8_t hrmCounter = 100;
00124     HeartRateService hrService(ble, hrmCounter, HeartRateService::LOCATION_FINGER);
00125 
00126     /* Setup auxiliary services. */
00127     BatteryService           battery(ble);
00128     DeviceInformationService deviceInfo(ble, "ARM", "Model1", "SN1", "hw-rev1", "fw-rev1", "soft-rev1");
00129 
00130     /* Setup advertising. */
00131     ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
00132     ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
00133     ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);
00134     ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
00135     ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
00136     ble.setAdvertisingInterval(1600); /* 1000ms; in multiples of 0.625ms. */
00137     ble.startAdvertising();
00138     
00139     pc.printf("Before while 1\n\r");
00140     while (true) {
00141         rs232talk();
00142         
00143         if(triggerSensorPolling == true)
00144         {
00145             if( (HR_Cnt>HR_Rpt) && (ppg_mems_data.HRD_Data[11]==0x80) )
00146             {
00147                 HR_Cnt = 0;
00148                 
00149                 pc.printf("SG: %d   ", (uint8_t)grade);
00150                 pc.printf("HR: %d\n\r", (uint8_t)myHR);
00151     
00152                 hrmCounter = (uint8_t)myHR;
00153                 hrService.updateHeartRate(hrmCounter);
00154             }
00155         }
00156         else
00157             ble.waitForEvent();
00158     }
00159 }
00160 
00161 
00162 
00163 void PAH8001_init()
00164 {   uint16_t q;
00165     uint8_t bank=0, temp; float grade=0;
00166 
00167     if(readRegister(0x00) == 0x30)
00168         pc.printf("PAH8001 I2C Link Successful!\n\r");
00169     else
00170         pc.printf("PAH8001 I2C Link Fail!\n\r");
00171         
00172     alg_version = PxiAlg_Version();
00173     pc.printf("Algo Ver: %d\n\r", alg_version);
00174     
00175 
00176 #ifdef DEBUG_8001
00177     writeRegister(0x09, 0x5A); writeRegister(0x54, 0xEE);
00178     pc.printf("\n\r~~~Start Test Pattern~~~ \n\r");
00179     pc.printf("Reg0x09: %d\n\r", readRegister(0x09));
00180     pc.printf("Reg0x54: %d\n\r", readRegister(0x54));
00181     pc.printf("Reg0x1E: %d\n\r", readRegister(0x1E));
00182     
00183     float MEMS_Data[3] = {0 ,0, 0}; //apply test pattern
00184     float myHR = 0 ;
00185     /*for(q=0;q<PPG_PATTERN_SIZE;q++)
00186         PxiAlg_Process((unsigned char*)PPG_Data[q], MEMS_Data);
00187     PxiAlg_HrGet(&myHR);
00188     pc.printf("HR: %f\n\r", myHR);*/
00189     
00190     PxiAlg_SetMemsScale(1);
00191     for(q=0;q<PPG_PATTERN_SIZE;q++)
00192     {
00193         PxiAlg_Process((unsigned char*)PPG_Data[q], (float*)iMEMS_Data[q]);
00194         PxiAlg_HrGet(&myHR);    PxiAlg_GetSigGrade(&grade);
00195         pc.printf("SG: %f   ", grade);
00196         pc.printf("HR: %f\n\r", myHR);
00197     }
00198     pc.printf("~~~End of Test Pattern~~~ \n\r");
00199     while(1);
00200 #endif
00201     
00202 #ifndef DEBUG_8001
00203     PxiAlg_SetMemsScale(1);
00204     //PxiAlg_EnableFastOutput(true);
00205     PxiAlg_EnableFastOutput(false);
00206     PxiAlg_EnableAutoMode(true);
00207     PxiAlg_EnableMotionMode(false);
00208     ticker.attach_us(&periodicCallback, PAH8001_Poll*1000);
00209     
00210     pc.printf("\n\r~~~Start Real-time HRM~~~ \n\r");
00211     //Initialization settings
00212     writeRegister(0x06, 0x82);  //Reset sensor
00213     wait_ms(10);    //make a delay
00214     
00215     for(q=0;q<INIT_PPG_REG_ARRAY_SIZE;q++){
00216         if(init_ppg_register_array[q][0] == 0x7F)
00217             bank = init_ppg_register_array[q][1];
00218 
00219         if((bank == 0) && (init_ppg_register_array[q][0] == 0x17) )
00220         {
00221             //read and write bit7=1
00222             temp = readRegister(0x17);
00223             temp |= 0x80 ;
00224             writeRegister(0x17, temp) ;
00225         }
00226         else
00227             writeRegister(init_ppg_register_array[q][0], init_ppg_register_array[q][1]);
00228     }
00229 #endif
00230 }
00231 
00232 void writeRegister(uint8_t addr, uint8_t data)
00233 {
00234     char data_write[2];
00235     
00236     data_write[0] = addr;
00237     data_write[1] = data;
00238     i2c.write(I2C_ADDR, data_write, 2, 0);
00239 }
00240 uint8_t readRegister(uint8_t addr)
00241 {
00242     char data_write[2];
00243     char data_read[2];
00244     
00245     data_write[0] = addr;
00246     i2c.write(I2C_ADDR, data_write, 1, 0);
00247     i2c.read(I2C_ADDR, data_read, 1, 0);
00248     return data_read[0];
00249 }
00250 
00251 bool Pixart_HRD(void)
00252 {
00253     uint8_t tmp=0;
00254     char data_write[2];
00255     char data_read[4];
00256     ppg_mems_data_t ppg_mems_data;
00257     //Check Touch Status for power saving
00258     writeRegister(0x7F,0x00); //bank0
00259     tmp = readRegister(0x59)&0x80;
00260     led_ctrl(tmp);
00261 
00262     //writeRegister(0x7F,0x01); //bank1
00263     ppg_mems_data.HRD_Data[0]=readRegister(0x68)&0x0f; //check status: 0 is not ready, 1 is ready, 2 is loss one data?
00264 
00265     if(ppg_mems_data.HRD_Data[0] ==0)
00266     {
00267         writeRegister(0x7F,0x00); //bank0
00268         return false;
00269     }
00270     else
00271     {
00272         //Only support burst read (0x64~0x67), when using I2C interface
00273         data_write[0] = 0x64;
00274         i2c.write(PAH8001_ADDR, data_write, 1, 1);
00275         i2c.read(PAH8001_ADDR, data_read, 4, 0);
00276         ppg_mems_data.HRD_Data[1]=data_read[0]&0xff;
00277         ppg_mems_data.HRD_Data[2]=data_read[1]&0xff;
00278         ppg_mems_data.HRD_Data[3]=data_read[2]&0xff;
00279         ppg_mems_data.HRD_Data[4]=data_read[3]&0xff;
00280 
00281         //Only support burst read (0x1A~0x1C), when using I2C interface
00282         data_write[0] = 0x1A;
00283         i2c.write(PAH8001_ADDR, data_write, 1, 1);
00284         i2c.read(PAH8001_ADDR, data_read, 3, 0);
00285         ppg_mems_data.HRD_Data[5]=data_read[0]&0xff;
00286         ppg_mems_data.HRD_Data[6]=data_read[1]&0xff;
00287         ppg_mems_data.HRD_Data[7]=data_read[2]&0xff;
00288 
00289         ppg_mems_data.HRD_Data[8]=Frame_Count++;
00290         ppg_mems_data.HRD_Data[9]=0;
00291         ppg_mems_data.HRD_Data[10]=_led_current_change_flag;
00292         writeRegister(0x7F,0x00); //bank0
00293         //bit7 is Touch Flag (bit7=1 is meant Touch, and bit7=0 is meant No Touch)
00294         ppg_mems_data.HRD_Data[11]=(readRegister(0x59)&0x80); //Check Touch Flag
00295         ppg_mems_data.HRD_Data[12]= ppg_mems_data.HRD_Data[6];
00296         
00297         //If no G sensor, please set G_Sensor_Data[3] = {0};
00298         ppg_mems_data.MEMS_Data[0] = 0;//ReadGSensorX();
00299         ppg_mems_data.MEMS_Data[1] = 0;//ReadGSensorY();
00300         ppg_mems_data.MEMS_Data[2] = 0;//ReadGSensorZ();
00301         Push(&ppg_mems_data); //Save data into FIFO
00302         
00303         return true;
00304     }
00305 }
00306 
00307 bool isFIFOEmpty(void)
00308 {
00309     return (_write_index == _read_index);
00310 }
00311 
00312 bool Push(ppg_mems_data_t *data)
00313 {
00314     int tmp = _write_index;
00315     tmp++;
00316     if(tmp >= FIFO_SIZE)
00317         tmp = 0;
00318     if(tmp == _read_index)
00319         return false;
00320     _ppg_mems_data[tmp] = *data;
00321     _write_index = tmp;
00322     
00323     return true;
00324 }
00325 
00326 bool Pop(ppg_mems_data_t *data)
00327 {
00328     int tmp;
00329     if(isFIFOEmpty())
00330         return false;
00331     *data = _ppg_mems_data[_read_index];
00332     tmp = _read_index + 1;
00333     if(tmp >= FIFO_SIZE)
00334         tmp = 0;
00335     _read_index = tmp;
00336     
00337     return true;
00338 }
00339 
00340 /***********************LED Control Start***********************************/
00341 void led_ctrl(uint8_t touch)    {
00342     if(touch == 0x80)   {
00343         uint8_t data;
00344         //uint16_t Frame_Average, EP_L, EP_H, Exposure_Line;
00345         uint16_t EP_L, EP_H, Exposure_Line;
00346         writeRegister(0x7f,0x00);
00347         writeRegister(0x05,0x98);
00348         writeRegister(0x7f,0x01);
00349         //writeRegister(0x42,0xA4);
00350         writeRegister(0x7f,0x00);
00351         data = readRegister(0x33);
00352         EP_H=data&0x03;
00353         data = readRegister(0x32);
00354         EP_L=data;
00355         Exposure_Line=(EP_H<<8)+EP_L;
00356         writeRegister(0x7f,0x01);
00357         if(_sleepflag==1)   {
00358             writeRegister(0x38, (0xE0|DEFAULT_LED_STEP));
00359             _sleepflag = 0 ;
00360         }
00361 
00362         if (_state_count <= STATE_COUNT_TH) {
00363             _state_count++;
00364             _led_current_change_flag = 0;
00365         }
00366         else {
00367             _state_count = 0;
00368             if(_state == 0) {
00369                 if( (Exposure_Line>=LED_CTRL_EXPO_TIME_HI_BOUND) || (Exposure_Line<=LED_CTRL_EXPO_TIME_LOW_BOUND) ) {
00370                     //writeRegister(0x7f,0x01);
00371                     data = readRegister(0x38);
00372                     _led_step=data&0x1f;
00373                     if( (Exposure_Line>=LED_CTRL_EXPO_TIME_HI_BOUND) && (_led_step < LED_CURRENT_HI) )  {
00374                         _state = 1 ;
00375                         _led_step=_led_step+LED_INC_DEC_STEP;
00376 
00377                         if(_led_step>LED_CURRENT_HI)
00378                             _led_step=LED_CURRENT_HI;
00379                         writeRegister(0x38, (_led_step|0xE0));
00380                         _led_current_change_flag = 1;
00381                     }
00382                     else if((Exposure_Line<=LED_CTRL_EXPO_TIME_LOW_BOUND) && (_led_step > LED_CURRENT_LOW) )    {
00383                         _state = 2 ;
00384                         if(_led_step<=(LED_CURRENT_LOW+LED_INC_DEC_STEP))
00385                             _led_step=LED_CURRENT_LOW;
00386                         else
00387                             _led_step=_led_step-LED_INC_DEC_STEP;
00388                         writeRegister(0x38, (_led_step|0xE0));
00389                         _led_current_change_flag = 1;
00390                     }
00391                     else    {
00392                         _state = 0 ;
00393                         _led_current_change_flag = 0;
00394                     }
00395                 }
00396                 else {
00397                     _led_current_change_flag = 0;
00398                 }
00399             }
00400             else if(_state == 1)    {
00401                 if(Exposure_Line > LED_CTRL_EXPO_TIME_HI)   {
00402                     _state = 1 ;
00403                     _led_step=_led_step+LED_INC_DEC_STEP;
00404                     if(_led_step>=LED_CURRENT_HI)   {
00405                         _state = 0 ;
00406                         _led_step=LED_CURRENT_HI;
00407                     }
00408                     writeRegister(0x38, (_led_step|0xE0));
00409                     _led_current_change_flag = 1;
00410                 }
00411                 else    {
00412                     _state = 0 ;
00413                     _led_current_change_flag = 0;
00414                 }
00415             }
00416             else    {
00417                 if(Exposure_Line < LED_CTRL_EXPO_TIME_LOW)  {
00418                     _state = 2 ;
00419                     if(_led_step<=(LED_CURRENT_LOW+LED_INC_DEC_STEP))   {
00420                         _state = 0 ;
00421                         _led_step=LED_CURRENT_LOW;
00422                     }
00423                     else
00424                         _led_step=_led_step-LED_INC_DEC_STEP;
00425                     writeRegister(0x38, (_led_step|0xE0));
00426                     _led_current_change_flag = 1;
00427                 }
00428                 else    {
00429                     _state = 0;
00430                     _led_current_change_flag = 0;
00431                 }
00432             }
00433         }
00434     }
00435     else    {
00436         writeRegister(0x7f,0x00);
00437         writeRegister(0x05,0xB8);
00438         writeRegister(0x7F,0x01);
00439         //writeRegister(0x42,0xA0);
00440         _led_step = DEFAULT_LED_STEP;
00441         writeRegister(0x38, 0xFF);
00442         _sleepflag = 1;
00443         _led_current_change_flag = 0;
00444     }
00445 }
00446 /***********************LED Control End ***********************************/
00447 
00448 
00449 void rs232talk(void)
00450 {uint8_t tmp, reg_tmp[5], reg[2];
00451     if(pc.readable()) {
00452     //pc.putc(pc.getc());
00453         tmp = pc.getc();
00454         if(tmp == 's')//for start polling
00455         {
00456             pc.printf("\n\rForce Start Polling\n\r");
00457             triggerSensorPolling = true;
00458         }
00459         if(tmp == 'p')//for stop polling
00460         {
00461             pc.printf("\n\rForce Stop Polling\n\r");
00462             triggerSensorPolling = false;
00463             PxiAlg_Close();//close and reset algorithm
00464         }
00465         
00466         if(tmp == 'w')//write register
00467         {
00468             //writeRegister(0x06, 0x08);
00469         }
00470         if(tmp == 'r')//read register
00471         {
00472             //writeRegister(0x06, 0x00);
00473         }
00474     }
00475 }
00476 /* ---------------------------------------------------------------
00477  * End of PAH8001 code
00478 *///--------------------------------------------------------------