1 /** 2 * @file APDS_9960.c 3 * @brief APDS-9960传感器源文件 4 * @version 0.1 5 * @date 2019-07-02 6 * 7 * @copyright Copyright (c) 2019 Chipintelli Technology Co., Ltd. 8 * 9 */ 10 /*----------------------------------------------------------------------------- 11 header 12 -----------------------------------------------------------------------------*/ 13 #include "string.h" 14 #include "APDS_9960.h" 15 #include "ci110x_i2c.h" 16 #include "ci110x_gpio.h" 17 #include "ci110x_scu.h" 18 #include "ci_misc.h" 19 #include "ci_log.h" 20 21 /*----------------------------------------------------------------------------- 22 define 23 -----------------------------------------------------------------------------*/ 24 #define DEBUG 0 25 26 /* APDS-9960 I2C address */ 27 #define APDS9960_I2C_ADDR 0x39/*!< APDS-9960传感器IIC总线地址 */ 28 29 /* Gesture parameters */ 30 #define GESTURE_THRESHOLD_OUT 10 31 #define GESTURE_SENSITIVITY_1 50 32 #define GESTURE_SENSITIVITY_2 20 33 34 /* Error code for returned values */ 35 #define ERROR xFF 36 37 /* Acceptable device IDs */ 38 #define APDS9960_ID_1 0xAB 39 #define APDS9960_ID_2 0x9C 40 41 /* Misc parameters */ 42 #define FIFO_PAUSE_TIME 30 /*!< Wait period (ms) between FIFO reads */ 43 44 /* APDS-9960 register addresses */ 45 #define APDS9960_ENABLE 0x80 46 #define APDS9960_ATIME 0x81 47 #define APDS9960_WTIME 0x83 48 #define APDS9960_AILTL 0x84 49 #define APDS9960_AILTH 0x85 50 #define APDS9960_AIHTL 0x86 51 #define APDS9960_AIHTH 0x87 52 #define APDS9960_PILT 0x89 53 #define APDS9960_PIHT 0x8B 54 #define APDS9960_PERS 0x8C 55 #define APDS9960_CONFIG1 0x8D 56 #define APDS9960_PPULSE 0x8E 57 #define APDS9960_CONTROL 0x8F 58 #define APDS9960_CONFIG2 0x90 59 #define APDS9960_ID 0x92 60 #define APDS9960_STATUS 0x93 61 #define APDS9960_CDATAL 0x94 62 #define APDS9960_CDATAH 0x95 63 #define APDS9960_RDATAL 0x96 64 #define APDS9960_RDATAH 0x97 65 #define APDS9960_GDATAL 0x98 66 #define APDS9960_GDATAH 0x99 67 #define APDS9960_BDATAL 0x9A 68 #define APDS9960_BDATAH 0x9B 69 #define APDS9960_PDATA 0x9C 70 #define APDS9960_POFFSET_UR 0x9D 71 #define APDS9960_POFFSET_DL 0x9E 72 #define APDS9960_CONFIG3 0x9F 73 #define APDS9960_GPENTH 0xA0 74 #define APDS9960_GEXTH 0xA1 75 #define APDS9960_GCONF1 0xA2 76 #define APDS9960_GCONF2 0xA3 77 #define APDS9960_GOFFSET_U 0xA4 78 #define APDS9960_GOFFSET_D 0xA5 79 #define APDS9960_GOFFSET_L 0xA7 80 #define APDS9960_GOFFSET_R 0xA9 81 #define APDS9960_GPULSE 0xA6 82 #define APDS9960_GCONF3 0xAA 83 #define APDS9960_GCONF4 0xAB 84 #define APDS9960_GFLVL 0xAE 85 #define APDS9960_GSTATUS 0xAF 86 #define APDS9960_IFORCE 0xE4 87 #define APDS9960_PICLEAR 0xE5 88 #define APDS9960_CICLEAR 0xE6 89 #define APDS9960_AICLEAR 0xE7 90 #define APDS9960_GFIFO_U 0xFC 91 #define APDS9960_GFIFO_D 0xFD 92 #define APDS9960_GFIFO_L 0xFE 93 #define APDS9960_GFIFO_R 0xFF 94 95 /* Bit fields */ 96 #define APDS9960_PON 0x01 97 #define APDS9960_AEN 0x02 98 #define APDS9960_PEN 0x04 99 #define APDS9960_WEN 0x08 100 #define APSD9960_AIEN 0x10 101 #define APDS9960_PIEN 0x20 102 #define APDS9960_GEN 0x40 103 #define APDS9960_GVALID 0x01 104 105 /* On/Off definitions */ 106 #define OFF 0 107 #define ON 1 108 109 /* Acceptable parameters for set_mode */ 110 #define POWER 0 111 #define AMBIENT_LIGHT 1 112 #define PROXIMITY 2 113 #define WAIT 3 114 #define AMBIENT_LIGHT_INT 4 115 #define PROXIMITY_INT 5 116 #define GESTURE 6 117 #define ALL 7 118 119 /* LED Drive values */ 120 #define LED_DRIVE_100MA 0 121 #define LED_DRIVE_50MA 1 122 #define LED_DRIVE_25MA 2 123 #define LED_DRIVE_12_5MA 3 124 125 /* Proximity Gain (PGAIN) values */ 126 #define PGAIN_1X 0 127 #define PGAIN_2X 1 128 #define PGAIN_4X 2 129 #define PGAIN_8X 3 130 131 /* ALS Gain (AGAIN) values */ 132 #define AGAIN_1X 0 133 #define AGAIN_4X 1 134 #define AGAIN_16X 2 135 #define AGAIN_64X 3 136 137 /* Gesture Gain (GGAIN) values */ 138 #define GGAIN_1X 0 139 #define GGAIN_2X 1 140 #define GGAIN_4X 2 141 #define GGAIN_8X 3 142 143 /* LED Boost values */ 144 #define LED_BOOST_100 0 145 #define LED_BOOST_150 1 146 #define LED_BOOST_200 2 147 #define LED_BOOST_300 3 148 149 /* Gesture wait time values */ 150 #define GWTIME_0MS 0 151 #define GWTIME_2_8MS 1 152 #define GWTIME_5_6MS 2 153 #define GWTIME_8_4MS 3 154 #define GWTIME_14_0MS 4 155 #define GWTIME_22_4MS 5 156 #define GWTIME_30_8MS 6 157 #define GWTIME_39_2MS 7 158 159 /* Default values */ 160 #define DEFAULT_ATIME 219 // 103ms 161 #define DEFAULT_WTIME 246 // 27ms 162 #define DEFAULT_PROX_PPULSE 0x87 // 16us, 8 pulses 163 #define DEFAULT_GESTURE_PPULSE 0x89 // 16us, 10 pulses 164 #define DEFAULT_POFFSET_UR 0 // 0 offset 165 #define DEFAULT_POFFSET_DL 0 // 0 offset 166 #define DEFAULT_CONFIG1 0x60 // No 12x wait (WTIME) factor 167 #define DEFAULT_LDRIVE LED_DRIVE_100MA 168 #define DEFAULT_PGAIN PGAIN_4X 169 #define DEFAULT_AGAIN AGAIN_4X 170 #define DEFAULT_PILT 0 // Low proximity threshold 171 #define DEFAULT_PIHT 50 // High proximity threshold 172 #define DEFAULT_AILT 0xFFFF // Force interrupt for calibration 173 #define DEFAULT_AIHT 0 174 #define DEFAULT_PERS 0x11 // 2 consecutive prox or ALS for int. 175 #define DEFAULT_CONFIG2 0x01 // No saturation interrupts or LED boost 176 #define DEFAULT_CONFIG3 0 // Enable all photodiodes, no SAI 177 #define DEFAULT_GPENTH 40 // Threshold for entering gesture mode 178 #define DEFAULT_GEXTH 30 // Threshold for exiting gesture mode 179 #define DEFAULT_GCONF1 0x40 // 4 gesture events for int., 1 for exit 180 #define DEFAULT_GGAIN GGAIN_4X 181 #define DEFAULT_GLDRIVE LED_DRIVE_100MA 182 #define DEFAULT_GWTIME GWTIME_2_8MS 183 #define DEFAULT_GOFFSET 0 // No offset scaling for gesture mode 184 #define DEFAULT_GPULSE 0xC9 // 32us, 10 pulses 185 #define DEFAULT_GCONF3 0 // All photodiodes active during gesture 186 #define DEFAULT_GIEN 0 // Disable gesture interrupts 187 188 /*----------------------------------------------------------------------------- 189 extern 190 -----------------------------------------------------------------------------*/ 191 192 /*----------------------------------------------------------------------------- 193 struct / enum / union 194 -----------------------------------------------------------------------------*/ 195 /* Direction definitions */ 196 enum 197 { 198 DIR_NONE, 199 DIR_LEFT, 200 DIR_RIGHT, 201 DIR_UP, 202 DIR_DOWN, 203 DIR_NEAR, 204 DIR_FAR, 205 DIR_ALL 206 }; 207 208 /* State definitions */ 209 enum 210 { 211 NA_STATE, 212 NEAR_STATE, 213 FAR_STATE, 214 ALL_STATE 215 }; 216 /* Container for gesture data */ 217 typedef struct 218 { 219 uint8_t u_data[32]; 220 uint8_t d_data[32]; 221 uint8_t l_data[32]; 222 uint8_t r_data[32]; 223 uint8_t index; 224 uint8_t total_gestures; 225 uint8_t in_threshold; 226 uint8_t out_threshold; 227 }gesture_data_type; 228 229 /*----------------------------------------------------------------------------- 230 global 231 -----------------------------------------------------------------------------*/ 232 /* Members */ 233 gesture_data_type gesture_data_; 234 235 int gesture_ud_delta_; 236 int gesture_lr_delta_; 237 int gesture_ud_count_; 238 int gesture_lr_count_; 239 int gesture_near_count_; 240 int gesture_far_count_; 241 int gesture_state_; 242 int gesture_motion_; 243 244 void (*apds_callback)(void); 245 246 /*----------------------------------------------------------------------------- 247 declare 248 -----------------------------------------------------------------------------*/ 249 250 /*----------------------------------------------------------------------------- 251 function 252 -----------------------------------------------------------------------------*/ 253 static void delay_ms(int ms) 254 { 255 int i=0; 256 while(ms--) 257 { 258 for(i=0;i<0x1A80;i++); 259 } 260 } 261 262 /** 263 * @brief Constructor - Instantiates sparkfun_apds9960 object 264 */ 265 void sparkfun_apds9960(void) 266 { 267 gesture_ud_delta_ = 0; 268 gesture_lr_delta_ = 0; 269 gesture_ud_count_ = 0; 270 gesture_lr_count_ = 0; 271 gesture_near_count_ = 0; 272 gesture_far_count_ = 0; 273 gesture_state_ = 0; 274 gesture_motion_ = DIR_NONE; 275 } 276 277 /** 278 * @brief IIC 读取一个byte 279 * 280 * @param reg 281 * @param val 282 * @return true 283 * @return false 284 */ 285 int8_t wire_read_data_byte(uint8_t reg,uint8_t *val) 286 { 287 char buf[256] = { 0}; 288 struct i2c_client client = { 0}; 289 client.flags = 1; 290 client.addr = APDS9960_I2C_ADDR; 291 strcpy(client.name,"apds9960"); 292 buf[0] = reg; 293 i2c_master_recv(IIC1,&client,buf,2); 294 *val = buf[0]; 295 delay_ms(5); 296 return RETURN_OK; 297 } 298 299 /** 300 * @brief IIC 写入一个byte 301 * 302 * @param reg 303 * @param val 304 * @return true 305 * @return false 306 */ 307 int8_t wire_write_data_byte(uint8_t reg,uint8_t val) 308 { 309 char buf[256] = { 0}; 310 struct i2c_client client = { 0}; 311 client.flags = 0; 312 client.addr = APDS9960_I2C_ADDR; 313 strcpy(client.name,"apds9960"); 314 buf[0] = reg; 315 buf[1] = val; 316 i2c_master_send(IIC1,&client,buf,2); 317 delay_ms(5); 318 return RETURN_OK; 319 } 320 321 /** 322 * @brief IIC 读取多个byte 323 * 324 * @param reg 325 * @param data 326 * @param len 327 * @return int8_t 328 */ 329 int8_t wire_read_data_block(uint8_t reg,uint8_t *data,uint32_t len) 330 { 331 char buf[256] = { 0}; 332 struct i2c_client client = { 0}; 333 client.flags = 1; 334 client.addr = APDS9960_I2C_ADDR; 335 strcpy(client.name,"apds9960"); 336 buf[0] = reg; 337 i2c_master_recv(IIC1,&client,buf,len + 1); 338 memcpy(data,buf,len); 339 delay_ms(5); 340 return len; 341 } 342 343 /** 344 * @brief IIC 写入多个byte 345 * 346 * @param reg 347 * @param data 348 * @param len 349 * @return int8_t 350 */ 351 int8_t wire_write_data_block(uint8_t reg,uint8_t *data,uint32_t len) 352 { 353 char buf[256] = { 0}; 354 struct i2c_client client = { 0}; 355 client.flags = 0; 356 client.addr = APDS9960_I2C_ADDR; 357 strcpy(client.name,"apds9960"); 358 buf[0] = reg; 359 strncpy(&buf[1],(char const*)data,len); 360 i2c_master_send(IIC1,&client,buf,len + 1); 361 delay_ms(5); 362 return len; 363 } 364 365 /** 366 * @brief Reads and returns the contents of the ENABLE register 367 * 368 * @return Contents of the ENABLE register. 0xFF if error. 369 */ 370 uint8_t get_mode(void) 371 { 372 uint8_t enable_value; 373 374 /* Read current ENABLE register */ 375 if( !wire_read_data_byte(APDS9960_ENABLE, &enable_value) ) 376 { 377 return ERROR; 378 } 379 380 return enable_value; 381 } 382 383 /** 384 * @brief Enables or disables a feature in the APDS-9960 385 * 386 #define POWER 0 387 #define AMBIENT_LIGHT 1 388 #define PROXIMITY 2 389 #define WAIT 3 390 #define AMBIENT_LIGHT_INT 4 391 #define PROXIMITY_INT 5 392 #define GESTURE 6 393 #define ALL 7 394 * @param[in] mode which feature to enable 395 * @param[in] enable ON (1) or OFF (0) 396 * @return True if operation success. False otherwise. 397 mode = ALL 7 enable = OFF 0 398 */ 399 int8_t set_mode(int8_t mode, uint8_t enable) 400 { 401 uint8_t reg_val; 402 403 /* Read current ENABLE register */ 404 reg_val = get_mode(); 405 mprintf("First_setMode_regval = %.2x\n",reg_val);//打印读取到的使能寄存器的值 0x80 = 0x4d 406 if( reg_val == ERROR ) { //如果读取到的值为0xFF,则错误 407 return RETURN_ERR; 408 } 409 410 /* Change bit(s) in ENABLE register */ 411 enable = enable & 0x01; 412 if((mode >= 0) && (mode <= 6)) //使能或失能某个位 413 { 414 if(enable) //使能 415 { 416 reg_val |= (1 << mode); 417 } 418 else //失能 419 { 420 reg_val &= ~(1 << mode); 421 } 422 } 423 else if( mode == ALL ) //使能全部 424 { 425 if (enable) 426 { 427 reg_val = 0x7F;//0x80=0x7F 全部使能 428 } 429 else //全部使能 430 { 431 reg_val = 0x00;//0x80=0x00 432 mprintf("0x80 = 0x00 all disable\n"); 433 } 434 } 435 436 mprintf("Last_setMode_regval = %.2x\n",reg_val);//打印读取到的使能寄存器的值 0x80 = 0x4d 437 /* Write value back to ENABLE register */ 438 if( !wire_write_data_byte(APDS9960_ENABLE, reg_val) ) 439 { 440 return RETURN_ERR; 441 } 442 443 return RETURN_OK; 444 } 445 446 /** 447 * @brief Determines if there is a gesture available for reading 448 * 确定是否有用于阅读的手势 449 * @return True if gesture available. False otherwise. 450 */ 451 int8_t is_gesture_available(void) 452 { 453 uint8_t val; 454 455 /*读0xAF*/ 456 if( !wire_read_data_byte(APDS9960_GSTATUS, &val) ) 457 { 458 return ERROR; 459 } 460 mprintf("AF_val = 0x%.2x\n",val); 461 /* Shift and mask out GVALID bit */ 462 val &= APDS9960_GVALID;//判断0xAF最低位GVALID是否为1 463 464 /* Return RETURN_OK/RETURN_ERR based on GVALID bit */ 465 if( val == 1) 466 { 467 return RETURN_OK; 468 } 469 else 470 { 471 return RETURN_ERR; 472 } 473 } 474 475 /** 476 * 处理原始手势数据确定滑动方向 477 * 478 * @return True if near or far state seen. False otherwise. 479 */ 480 int8_t process_gesture_data(void) 481 { 482 uint8_t u_first = 0; 483 uint8_t d_first = 0; 484 uint8_t l_first = 0; 485 uint8_t r_first = 0; 486 uint8_t u_last = 0; 487 uint8_t d_last = 0; 488 uint8_t l_last = 0; 489 uint8_t r_last = 0; 490 int ud_ratio_first; 491 int lr_ratio_first; 492 int ud_ratio_last; 493 int lr_ratio_last; 494 int ud_delta; 495 int lr_delta; 496 int i; 497 498 /* If we have less than 4 total gestures, that's not enough */ 499 if( gesture_data_.total_gestures <= 4 ) 500 { 501 return RETURN_ERR; 502 } 503 504 /* Check to make sure our data isn't out of bounds */ 505 if( (gesture_data_.total_gestures <= 32) && \ 506 (gesture_data_.total_gestures > 0) ) 507 { 508 509 /* Find the first value in U/D/L/R above the threshold */ 510 for( i = 0; i < gesture_data_.total_gestures; i++ ) 511 { 512 if( (gesture_data_.u_data[i] > GESTURE_THRESHOLD_OUT) && 513 (gesture_data_.d_data[i] > GESTURE_THRESHOLD_OUT) && 514 (gesture_data_.l_data[i] > GESTURE_THRESHOLD_OUT) && 515 (gesture_data_.r_data[i] > GESTURE_THRESHOLD_OUT) ) 516 { 517 518 u_first = gesture_data_.u_data[i]; 519 d_first = gesture_data_.d_data[i]; 520 l_first = gesture_data_.l_data[i]; 521 r_first = gesture_data_.r_data[i]; 522 #if DEBUG 523 mprintf("*********************************************\n"); 元器件数据手册、IC替代型号,打造电子元器件IC百科大全!