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.
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 Tue Jul 12 2022 19:31:19 by
