Production Test Program (PTP) for the LPC4088 Experiment Base Board
Dependencies: EALib I2S LM75B SDFileSystem mbed
AR1021I2C.cpp
00001 /* 00002 * Copyright 2013 Embedded Artists AB 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 /****************************************************************************** 00018 * Includes 00019 *****************************************************************************/ 00020 00021 #include "mbed.h" 00022 #include "mbed_debug.h" 00023 00024 #include "AR1021I2C.h" 00025 00026 /****************************************************************************** 00027 * Defines and typedefs 00028 *****************************************************************************/ 00029 00030 #define AR1021_REG_TOUCH_THRESHOLD (0x02) 00031 #define AR1021_REG_SENS_FILTER (0x03) 00032 #define AR1021_REG_SAMPLING_FAST (0x04) 00033 #define AR1021_REG_SAMPLING_SLOW (0x05) 00034 #define AR1021_REG_ACC_FILTER_FAST (0x06) 00035 #define AR1021_REG_ACC_FILTER_SLOW (0x07) 00036 #define AR1021_REG_SPEED_THRESHOLD (0x08) 00037 #define AR1021_REG_SLEEP_DELAY (0x0A) 00038 #define AR1021_REG_PEN_UP_DELAY (0x0B) 00039 #define AR1021_REG_TOUCH_MODE (0x0C) 00040 #define AR1021_REG_TOUCH_OPTIONS (0x0D) 00041 #define AR1021_REG_CALIB_INSETS (0x0E) 00042 #define AR1021_REG_PEN_STATE_REPORT_DELAY (0x0F) 00043 #define AR1021_REG_TOUCH_REPORT_DELAY (0x11) 00044 00045 00046 #define AR1021_CMD_GET_VERSION (0x10) 00047 #define AR1021_CMD_ENABLE_TOUCH (0x12) 00048 #define AR1021_CMD_DISABLE_TOUCH (0x13) 00049 #define AR1021_CMD_CALIBRATE_MODE (0x14) 00050 #define AR1021_CMD_REGISTER_READ (0x20) 00051 #define AR1021_CMD_REGISTER_WRITE (0x21) 00052 #define AR1021_CMD_REGISTER_START_ADDR_REQUEST (0x22) 00053 #define AR1021_CMD_REGISTER_WRITE_TO_EEPROM (0x23) 00054 #define AR1021_CMD_EEPROM_READ (0x28) 00055 #define AR1021_CMD_EEPROM_WRITE (0x29) 00056 #define AR1021_CMD_EEPROM_WRITE_TO_REGISTERS (0x2B) 00057 00058 #define AR1021_RESP_STAT_OK (0x00) 00059 #define AR1021_RESP_STAT_CMD_UNREC (0x01) 00060 #define AR1021_RESP_STAT_HDR_UNREC (0x03) 00061 #define AR1021_RESP_STAT_TIMEOUT (0x04) 00062 #define AR1021_RESP_STAT_CANCEL_CALIB (0xFC) 00063 00064 00065 #define AR1021_ERR_NO_HDR (-1000) 00066 #define AR1021_ERR_INV_LEN (-1001) 00067 #define AR1021_ERR_INV_RESP (-1002) 00068 #define AR1021_ERR_INV_RESPLEN (-1003) 00069 #define AR1021_ERR_TIMEOUT (-1004) 00070 00071 // bit 7 is always 1 and bit 0 defines pen up or down 00072 #define AR1021_PEN_MASK (0x81) 00073 00074 #define AR1021_NUM_CALIB_POINTS (4) 00075 00076 #define AR1021_ADDR (0x4D << 1) 00077 00078 #define AR1021_TIMEOUT 1000 //how many ms to wait for responce 00079 #define AR1021_RETRY 5 //how many times to retry sending command 00080 00081 #define AR1021_MIN(__a, __b) (((__a)<(__b))?(__a):(__b)) 00082 00083 00084 AR1021I2C::AR1021I2C(PinName sda, PinName scl, PinName siq) : 00085 _i2c(sda, scl), _siq(siq), _siqIrq(siq) 00086 { 00087 _i2c.frequency(200000); 00088 00089 // default calibration inset is 25 -> (25/2 = 12.5%) 00090 _inset = 25; 00091 00092 // make sure _calibPoint has an invalid value to begin with 00093 // correct value is set in calibrateStart() 00094 _calibPoint = AR1021_NUM_CALIB_POINTS+1; 00095 00096 _x = 0; 00097 _y = 0; 00098 _pen = 0; 00099 00100 _initialized = false; 00101 } 00102 00103 00104 bool AR1021I2C::read(touchCoordinate_t &coord) { 00105 00106 if (!_initialized) return false; 00107 00108 coord.x = _x * _width/4095; 00109 coord.y = _y * _height/4095; 00110 coord.z = _pen; 00111 00112 return true; 00113 } 00114 00115 00116 bool AR1021I2C::init(uint16_t width, uint16_t height) { 00117 int result = 0; 00118 bool ok = false; 00119 int attempts = 0; 00120 00121 _width = width; 00122 _height = height; 00123 00124 while (1) { 00125 00126 do { 00127 // disable touch 00128 result = cmd(AR1021_CMD_DISABLE_TOUCH, NULL, 0, NULL, 0); 00129 if (result != 0) { 00130 debug("disable touch failed (%d)\n", result); 00131 break; 00132 } 00133 00134 char regOffset = 0; 00135 int regOffLen = 1; 00136 result = cmd(AR1021_CMD_REGISTER_START_ADDR_REQUEST, NULL, 0, 00137 ®Offset, ®OffLen); 00138 if (result != 0) { 00139 debug("register offset request failed (%d)\n", result); 00140 break; 00141 } 00142 00143 // enable calibrated coordinates 00144 // high, low address, len, value 00145 char toptions[4] = {0x00, AR1021_REG_TOUCH_OPTIONS+regOffset, 0x01, 0x01}; 00146 result = cmd(AR1021_CMD_REGISTER_WRITE, toptions, 4, NULL, 0); 00147 if (result != 0) { 00148 debug("register write request failed (%d)\n", result); 00149 break; 00150 } 00151 00152 // save registers to eeprom 00153 result = cmd(AR1021_CMD_REGISTER_WRITE_TO_EEPROM, NULL, 0, NULL, 0); 00154 if (result != 0) { 00155 debug("register write to eeprom failed (%d)\n", result); 00156 break; 00157 } 00158 00159 // enable touch 00160 result = cmd(AR1021_CMD_ENABLE_TOUCH, NULL, 0, NULL, 0); 00161 if (result != 0) { 00162 debug("enable touch failed (%d)\n", result); 00163 break; 00164 } 00165 00166 _siqIrq.rise(this, &AR1021I2C::readTouchIrq); 00167 00168 _initialized = true; 00169 ok = true; 00170 00171 } while(0); 00172 00173 if (ok) break; 00174 00175 // try to run the initialize sequence at most 2 times 00176 if(++attempts >= 2) break; 00177 } 00178 00179 00180 return ok; 00181 } 00182 00183 bool AR1021I2C::calibrateStart() { 00184 bool ok = false; 00185 int result = 0; 00186 int attempts = 0; 00187 00188 if (!_initialized) return false; 00189 00190 _siqIrq.rise(NULL); 00191 00192 while(1) { 00193 00194 do { 00195 // disable touch 00196 result = cmd(AR1021_CMD_DISABLE_TOUCH, NULL, 0, NULL, 0); 00197 if (result != 0) { 00198 debug("disable touch failed (%d)\n", result); 00199 break; 00200 } 00201 00202 char regOffset = 0; 00203 int regOffLen = 1; 00204 result = cmd(AR1021_CMD_REGISTER_START_ADDR_REQUEST, NULL, 0, 00205 ®Offset, ®OffLen); 00206 if (result != 0) { 00207 debug("register offset request failed (%d)\n", result); 00208 break; 00209 } 00210 00211 // set insets 00212 // enable calibrated coordinates 00213 // high, low address, len, value 00214 char insets[4] = {0x00, AR1021_REG_CALIB_INSETS+regOffset, 0x01, _inset}; 00215 result = cmd(AR1021_CMD_REGISTER_WRITE, insets, 4, NULL, 0); 00216 if (result != 0) { 00217 debug("register write request failed (%d)\n", result); 00218 break; 00219 } 00220 00221 // calibration mode 00222 char calibType = 4; 00223 result = cmd(AR1021_CMD_CALIBRATE_MODE, &calibType, 1, NULL, 0, false); 00224 if (result != 0) { 00225 debug("calibration mode failed (%d)\n", result); 00226 break; 00227 } 00228 00229 _calibPoint = 0; 00230 ok = true; 00231 00232 } while(0); 00233 00234 if (ok) break; 00235 00236 // try to run the calibrate mode sequence at most 2 times 00237 if (++attempts >= 2) break; 00238 } 00239 00240 return ok; 00241 } 00242 00243 bool AR1021I2C::getNextCalibratePoint(uint16_t* x, uint16_t* y) { 00244 00245 if (!_initialized) return false; 00246 if (x == NULL || y == NULL) return false; 00247 00248 int xInset = (_width * _inset / 100) / 2; 00249 int yInset = (_height * _inset / 100) / 2; 00250 00251 switch(_calibPoint) { 00252 case 0: 00253 *x = xInset; 00254 *y = yInset; 00255 break; 00256 case 1: 00257 *x = _width - xInset; 00258 *y = yInset; 00259 break; 00260 case 2: 00261 *x = _width - xInset; 00262 *y = _height - yInset; 00263 break; 00264 case 3: 00265 *x = xInset; 00266 *y = _height - yInset; 00267 break; 00268 default: 00269 return false; 00270 } 00271 00272 return true; 00273 } 00274 00275 bool AR1021I2C::waitForCalibratePoint(bool* morePoints, uint32_t timeout) { 00276 int result = 0; 00277 bool ret = false; 00278 00279 if (!_initialized) return false; 00280 00281 do { 00282 if (morePoints == NULL || _calibPoint >= AR1021_NUM_CALIB_POINTS) { 00283 break; 00284 } 00285 00286 // wait for response 00287 result = waitForCalibResponse(timeout); 00288 if (result != 0) { 00289 debug("wait for calibration response failed (%d)\n", result); 00290 break; 00291 } 00292 00293 _calibPoint++; 00294 *morePoints = (_calibPoint < AR1021_NUM_CALIB_POINTS); 00295 00296 00297 // no more points -> enable touch 00298 if (!(*morePoints)) { 00299 00300 // wait for calibration data to be written to eeprom 00301 // before enabling touch 00302 result = waitForCalibResponse(timeout); 00303 if (result != 0) { 00304 debug("wait for calibration response failed (%d)\n", result); 00305 break; 00306 } 00307 00308 00309 // clear chip-select since calibration is done; 00310 // _cs = 1; 00311 00312 result = cmd(AR1021_CMD_ENABLE_TOUCH, NULL, 0, NULL, 0); 00313 if (result != 0) { 00314 debug("enable touch failed (%d)\n", result); 00315 break; 00316 } 00317 00318 _siqIrq.rise(this, &AR1021I2C::readTouchIrq); 00319 } 00320 00321 ret = true; 00322 00323 } while (0); 00324 00325 00326 00327 if (!ret) { 00328 // make sure to set chip-select off in case of an error 00329 // _cs = 1; 00330 // calibration must restart if an error occurred 00331 _calibPoint = AR1021_NUM_CALIB_POINTS+1; 00332 } 00333 00334 00335 00336 return ret; 00337 } 00338 00339 int AR1021I2C::cmd(char cmd, char* data, int len, char* respBuf, int* respLen, 00340 bool setCsOff) { 00341 00342 int ret = 0; 00343 int readLen = (respLen == NULL) ? 0 : *respLen; 00344 for (int attempt = 1; attempt <= AR1021_RETRY; attempt++) { 00345 if (attempt > 1) { 00346 wait_ms(50); 00347 } 00348 00349 // command request 00350 // --------------- 00351 // 0x00 0x55 len cmd data 00352 // 0x00 = protocol command byte 00353 // 0x55 = header 00354 // len = data length + cmd (1) 00355 // data = data to send 00356 00357 _i2c.start(); 00358 _i2c.write(AR1021_ADDR); //send write address 00359 _i2c.write(0x00); 00360 _i2c.write(0x55); //header 00361 _i2c.write(len+1); //message length 00362 _i2c.write(cmd); 00363 for (int i = 0; i < len; i++) { 00364 _i2c.write(data[i]); 00365 } 00366 wait_us(60); 00367 _i2c.stop(); 00368 00369 // wait for response (siq goes high when response is available) 00370 Timer t; 00371 t.start(); 00372 while(_siq.read() != 1 && t.read_ms() < AR1021_TIMEOUT); 00373 00374 if (t.read_ms() < AR1021_TIMEOUT) { 00375 00376 // command response 00377 // --------------- 00378 // 0x55 len status cmd data 00379 // 0x55 = header 00380 // len = number of bytes following the len byte (i.e. including the status&cmd) 00381 // status = status 00382 // cmd = command ID 00383 // data = data to receive 00384 _i2c.start(); 00385 _i2c.write(AR1021_ADDR + 1); //send read address 00386 char header = _i2c.read(1); //header should always be 0x55 00387 if (header != 0x55) { 00388 ret = AR1021_ERR_NO_HDR; 00389 continue; 00390 } 00391 char length = _i2c.read(1); //data length 00392 if (length < 2) { 00393 ret = AR1021_ERR_INV_LEN; //must have at least status and command bytes 00394 continue; 00395 } 00396 length -= 2; 00397 if (length > readLen) { 00398 ret = AR1021_ERR_INV_LEN; //supplied buffer is not enough 00399 continue; 00400 } 00401 00402 char status = _i2c.read(1); //command status 00403 char usedCmd; 00404 if (readLen <= 0) { 00405 usedCmd = _i2c.read(0); //no data => read command byte + NACK 00406 } else { 00407 usedCmd = _i2c.read(1); //which command 00408 00409 //we need to send a NACK on the last read. 00410 int i; 00411 for (i = 0; i < (length-1); i++) { 00412 respBuf[i] = _i2c.read(1); 00413 } 00414 respBuf[i] = _i2c.read(0); //last returned data byte + NACK 00415 } 00416 _i2c.stop(); 00417 00418 00419 if (status != AR1021_RESP_STAT_OK) { 00420 ret = -status; 00421 continue; 00422 } 00423 if (usedCmd != cmd) { 00424 ret = AR1021_ERR_INV_RESP; 00425 continue; 00426 } 00427 00428 // success 00429 ret = 0; 00430 break; 00431 00432 } else { 00433 ret = AR1021_ERR_TIMEOUT; 00434 continue; 00435 } 00436 } 00437 00438 return ret; 00439 } 00440 00441 int AR1021I2C::waitForCalibResponse(uint32_t timeout) { 00442 Timer t; 00443 int ret = 0; 00444 00445 t.start(); 00446 00447 // wait for siq 00448 while (_siq.read() != 1 && 00449 (timeout == 0 || (uint32_t)t.read_ms() < (int)timeout)); 00450 00451 00452 do { 00453 00454 if (timeout > 0 && (uint32_t)t.read_ms() >= timeout) { 00455 ret = AR1021_ERR_TIMEOUT; 00456 break; 00457 } 00458 00459 // command response 00460 // --------------- 00461 // 0x55 len status cmd data 00462 // 0x55 = header 00463 // len = number of bytes following the len byte (should be 2) 00464 // status = status 00465 // cmd = command ID 00466 _i2c.start(); 00467 _i2c.write(AR1021_ADDR + 1); //send read address 00468 char header = _i2c.read(1); //header should always be 0x55 00469 char length = _i2c.read(1); //data length 00470 00471 if (header != 0x55) { 00472 ret = AR1021_ERR_NO_HDR; 00473 break; 00474 } 00475 if (length < 2) { 00476 ret = AR1021_ERR_INV_LEN; 00477 break; 00478 } 00479 char status = _i2c.read(1); //status 00480 char cmd = _i2c.read(0); //command, should be NACK'ed 00481 _i2c.stop(); 00482 if (status != AR1021_RESP_STAT_OK) { 00483 ret = -status; 00484 break; 00485 } 00486 if (cmd != AR1021_CMD_CALIBRATE_MODE) { 00487 ret = AR1021_ERR_INV_RESP; 00488 break; 00489 } 00490 00491 // success 00492 ret = 0; 00493 00494 } while (0); 00495 00496 return ret; 00497 } 00498 00499 00500 void AR1021I2C::readTouchIrq() { 00501 while(_siq.read() == 1) { 00502 00503 // touch coordinates are sent in a 5-byte data packet 00504 _i2c.start(); 00505 _i2c.write(AR1021_ADDR + 1); //send read address 00506 int pen = _i2c.read(1); 00507 int xlo = _i2c.read(1); 00508 int xhi = _i2c.read(1); 00509 int ylo = _i2c.read(1); 00510 int yhi = _i2c.read(0); 00511 _i2c.stop(); 00512 00513 // pen down 00514 if ((pen&AR1021_PEN_MASK) == (1<<7|1<<0)) { 00515 _pen = 1; 00516 } 00517 // pen up 00518 else if ((pen&AR1021_PEN_MASK) == (1<<7)){ 00519 _pen = 0; 00520 } 00521 // invalid value 00522 else { 00523 continue; 00524 } 00525 00526 _x = ((xhi<<7)|xlo); 00527 _y = ((yhi<<7)|ylo); 00528 } 00529 } 00530 00531 bool AR1021I2C::info(int* verHigh, int* verLow, int* resBits, int* type) 00532 { 00533 char buff[3] = {0,0,0}; 00534 int read = 3; 00535 int res = cmd(AR1021_CMD_GET_VERSION, NULL, 0, buff, &read); 00536 if (res == 0) { 00537 *verHigh = buff[0]; 00538 *verLow = buff[1]; 00539 switch(buff[2] & 3) { 00540 case 0: 00541 *resBits = 8; 00542 break; 00543 case 1: 00544 *resBits = 10; 00545 break; 00546 case 2: 00547 *resBits = 12; 00548 break; 00549 case 3: 00550 *resBits = 12; 00551 break; 00552 default: 00553 res = 25; 00554 printf("Invalid resolution %d\n", buff[2]&3); 00555 break; 00556 } 00557 *type = buff[2]>>2; 00558 } 00559 return (res == 0); 00560 }
Generated on Sun Jul 17 2022 08:29:10 by 1.7.2