Update version of EALib.
Dependencies: FATFileSystem
Fork of EALib by
AR1021.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 "AR1021.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 AR1021::AR1021(PinName mosi, PinName miso, PinName sck, PinName cs, PinName siq) : 00077 _spi(mosi, miso, sck), _cs(cs), _siq(siq), _siqIrq(siq) 00078 { 00079 _cs = 1; // active low 00080 00081 _spi.format(8, 1); 00082 _spi.frequency(500000); 00083 00084 // default calibration inset is 25 -> (25/2 = 12.5%) 00085 _inset = 25; 00086 00087 // make sure _calibPoint has an invalid value to begin with 00088 // correct value is set in calibrateStart() 00089 _calibPoint = AR1021_NUM_CALIB_POINTS+1; 00090 00091 _x = 0; 00092 _y = 0; 00093 _pen = 0; 00094 00095 _initialized = false; 00096 } 00097 00098 00099 bool AR1021::read(touchCoordinate_t &coord) { 00100 00101 if (!_initialized) return false; 00102 00103 coord.x = _x * _width/4095; 00104 coord.y = _y * _height/4095; 00105 coord.z = _pen; 00106 00107 return true; 00108 } 00109 00110 00111 bool AR1021::init(uint16_t width, uint16_t height) { 00112 int result = 0; 00113 bool ok = false; 00114 int attempts = 0; 00115 00116 _width = width; 00117 _height = height; 00118 00119 while (1) { 00120 00121 do { 00122 // disable touch 00123 result = cmd(AR1021_CMD_DISABLE_TOUCH, NULL, 0, NULL, 0); 00124 if (result == -AR1021_RESP_STAT_CANCEL_CALIB) { 00125 debug("calibration was cancelled, short delay and try again"); 00126 wait_us(50); 00127 result = cmd(AR1021_CMD_DISABLE_TOUCH, NULL, 0, NULL, 0); 00128 } 00129 if (result != 0) { 00130 debug("disable touch failed (%d)\n", result); 00131 break; 00132 } 00133 wait_us(50); 00134 00135 char regOffset = 0; 00136 int regOffLen = 1; 00137 result = cmd(AR1021_CMD_REGISTER_START_ADDR_REQUEST, NULL, 0, 00138 ®Offset, ®OffLen); 00139 if (result != 0) { 00140 debug("register offset request failed (%d)\n", result); 00141 break; 00142 } 00143 00144 // enable calibrated coordinates 00145 // high, low address, len, value 00146 char toptions[4] = {0x00, AR1021_REG_TOUCH_OPTIONS+regOffset, 0x01, 0x01}; 00147 result = cmd(AR1021_CMD_REGISTER_WRITE, toptions, 4, NULL, 0); 00148 if (result != 0) { 00149 debug("register write request failed (%d)\n", result); 00150 break; 00151 } 00152 00153 // save registers to eeprom 00154 result = cmd(AR1021_CMD_REGISTER_WRITE_TO_EEPROM, NULL, 0, NULL, 0); 00155 if (result != 0) { 00156 debug("register write to eeprom failed (%d)\n", result); 00157 break; 00158 } 00159 00160 // enable touch 00161 result = cmd(AR1021_CMD_ENABLE_TOUCH, NULL, 0, NULL, 0); 00162 if (result != 0) { 00163 debug("enable touch failed (%d)\n", result); 00164 break; 00165 } 00166 00167 _siqIrq.rise(this, &AR1021::readTouchIrq); 00168 00169 _initialized = true; 00170 ok = true; 00171 00172 } while(0); 00173 00174 if (ok) break; 00175 00176 // try to run the initialize sequence at most 2 times 00177 if(++attempts >= 2) break; 00178 } 00179 00180 00181 return ok; 00182 } 00183 00184 bool AR1021::calibrateStart() { 00185 bool ok = false; 00186 int result = 0; 00187 int attempts = 0; 00188 00189 if (!_initialized) return false; 00190 00191 _siqIrq.rise(NULL); 00192 00193 while(1) { 00194 00195 do { 00196 // disable touch 00197 result = cmd(AR1021_CMD_DISABLE_TOUCH, NULL, 0, NULL, 0); 00198 if (result != 0) { 00199 debug("disable touch failed (%d)\n", result); 00200 break; 00201 } 00202 00203 char regOffset = 0; 00204 int regOffLen = 1; 00205 result = cmd(AR1021_CMD_REGISTER_START_ADDR_REQUEST, NULL, 0, 00206 ®Offset, ®OffLen); 00207 if (result != 0) { 00208 debug("register offset request failed (%d)\n", result); 00209 break; 00210 } 00211 00212 // set insets 00213 // enable calibrated coordinates 00214 // high, low address, len, value 00215 char insets[4] = {0x00, AR1021_REG_CALIB_INSETS+regOffset, 0x01, _inset}; 00216 result = cmd(AR1021_CMD_REGISTER_WRITE, insets, 4, NULL, 0); 00217 if (result != 0) { 00218 debug("register write request failed (%d)\n", result); 00219 break; 00220 } 00221 00222 // calibration mode 00223 char calibType = 4; 00224 result = cmd(AR1021_CMD_CALIBRATE_MODE, &calibType, 1, NULL, 0, false); 00225 if (result != 0) { 00226 debug("calibration mode failed (%d)\n", result); 00227 break; 00228 } 00229 00230 _calibPoint = 0; 00231 ok = true; 00232 00233 } while(0); 00234 00235 if (ok) break; 00236 00237 // try to run the calibrate mode sequence at most 2 times 00238 if (++attempts >= 2) break; 00239 } 00240 00241 return ok; 00242 } 00243 00244 bool AR1021::getNextCalibratePoint(uint16_t* x, uint16_t* y) { 00245 00246 if (!_initialized) return false; 00247 if (x == NULL || y == NULL) return false; 00248 00249 int xInset = (_width * _inset / 100) / 2; 00250 int yInset = (_height * _inset / 100) / 2; 00251 00252 switch(_calibPoint) { 00253 case 0: 00254 *x = xInset; 00255 *y = yInset; 00256 break; 00257 case 1: 00258 *x = _width - xInset; 00259 *y = yInset; 00260 break; 00261 case 2: 00262 *x = _width - xInset; 00263 *y = _height - yInset; 00264 break; 00265 case 3: 00266 *x = xInset; 00267 *y = _height - yInset; 00268 break; 00269 default: 00270 return false; 00271 } 00272 00273 return true; 00274 } 00275 00276 bool AR1021::waitForCalibratePoint(bool* morePoints, uint32_t timeout) { 00277 int result = 0; 00278 bool ret = false; 00279 00280 if (!_initialized) return false; 00281 00282 do { 00283 if (morePoints == NULL || _calibPoint >= AR1021_NUM_CALIB_POINTS) { 00284 break; 00285 } 00286 00287 // wait for response 00288 result = waitForCalibResponse(timeout); 00289 if (result != 0) { 00290 debug("wait for calibration response failed (%d)\n", result); 00291 break; 00292 } 00293 00294 _calibPoint++; 00295 *morePoints = (_calibPoint < AR1021_NUM_CALIB_POINTS); 00296 00297 00298 // no more points -> enable touch 00299 if (!(*morePoints)) { 00300 00301 // wait for calibration data to be written to eeprom 00302 // before enabling touch 00303 result = waitForCalibResponse(timeout); 00304 if (result != 0) { 00305 debug("wait for calibration response failed (%d)\n", result); 00306 break; 00307 } 00308 00309 00310 // clear chip-select since calibration is done; 00311 _cs = 1; 00312 00313 result = cmd(AR1021_CMD_ENABLE_TOUCH, NULL, 0, NULL, 0); 00314 if (result != 0) { 00315 debug("enable touch failed (%d)\n", result); 00316 break; 00317 } 00318 00319 _siqIrq.rise(this, &AR1021::readTouchIrq); 00320 } 00321 00322 ret = true; 00323 00324 } while (0); 00325 00326 00327 00328 if (!ret) { 00329 // make sure to set chip-select off in case of an error 00330 _cs = 1; 00331 // calibration must restart if an error occurred 00332 _calibPoint = AR1021_NUM_CALIB_POINTS+1; 00333 } 00334 00335 00336 00337 return ret; 00338 } 00339 00340 int AR1021::cmd(char cmd, char* data, int len, char* respBuf, int* respLen, 00341 bool setCsOff) { 00342 00343 int ret = 0; 00344 00345 // command request 00346 // --------------- 00347 // 0x55 len cmd data 00348 // 0x55 = header 00349 // len = data length + cmd (1) 00350 // data = data to send 00351 00352 _cs = 0; 00353 00354 _spi.write(0x55); 00355 wait_us(50); // according to data sheet there must be an inter-byte delay of ~50us 00356 _spi.write(len+1); 00357 wait_us(50); 00358 _spi.write(cmd); 00359 wait_us(50); 00360 00361 for(int i = 0; i < len; i++) { 00362 _spi.write(data[i]); 00363 wait_us(50); 00364 } 00365 00366 00367 // wait for response (siq goes high when response is available) 00368 Timer t; 00369 t.start(); 00370 while(_siq.read() != 1 && t.read_ms() < 1000); 00371 00372 00373 // command response 00374 // --------------- 00375 // 0x55 len status cmd data 00376 // 0x55 = header 00377 // len = number of bytes following the len byte 00378 // status = status 00379 // cmd = command ID 00380 // data = data to receive 00381 00382 00383 do { 00384 00385 if (t.read_ms() >= 1000) { 00386 ret = AR1021_ERR_TIMEOUT; 00387 break; 00388 } 00389 00390 int head = _spi.write(0); 00391 if (head != 0x55) { 00392 ret = AR1021_ERR_NO_HDR; 00393 break; 00394 } 00395 00396 wait_us(50); 00397 int len = _spi.write(0); 00398 if (len < 2) { 00399 ret = AR1021_ERR_INV_LEN; 00400 break; 00401 } 00402 00403 wait_us(50); 00404 int status = _spi.write(0); 00405 if (status != AR1021_RESP_STAT_OK) { 00406 ret = -status; 00407 break; 00408 } 00409 00410 wait_us(50); 00411 int cmdId = _spi.write(0); 00412 if (cmdId != cmd) { 00413 ret = AR1021_ERR_INV_RESP; 00414 break; 00415 } 00416 00417 if ( ((len-2) > 0 && respLen == NULL) 00418 || ((len-2) > 0 && respLen != NULL && *respLen < (len-2))) { 00419 ret = AR1021_ERR_INV_RESPLEN; 00420 break; 00421 } 00422 00423 for (int i = 0; i < len-2;i++) { 00424 wait_us(50); 00425 respBuf[i] = _spi.write(0); 00426 } 00427 if (respLen != NULL) { 00428 *respLen = len-2; 00429 } 00430 00431 // make sure we wait 50us before issuing a new cmd 00432 wait_us(50); 00433 00434 } while (0); 00435 00436 00437 00438 // disable chip-select if setCsOff is true or if an error occurred 00439 if (setCsOff || ret != 0) { 00440 _cs = 1; 00441 } 00442 00443 00444 00445 return ret; 00446 } 00447 00448 int AR1021::waitForCalibResponse(uint32_t timeout) { 00449 Timer t; 00450 int ret = 0; 00451 00452 t.start(); 00453 00454 // wait for siq 00455 while (_siq.read() != 1 && 00456 (timeout == 0 || (uint32_t)t.read_ms() < (int)timeout)); 00457 00458 00459 do { 00460 00461 if (timeout > 0 && (uint32_t)t.read_ms() >= timeout) { 00462 ret = AR1021_ERR_TIMEOUT; 00463 break; 00464 } 00465 00466 int head = _spi.write(0); 00467 if (head != 0x55) { 00468 ret = AR1021_ERR_NO_HDR; 00469 break; 00470 } 00471 00472 wait_us(50); 00473 int len = _spi.write(0); 00474 if (len != 2) { 00475 ret = AR1021_ERR_INV_LEN; 00476 break; 00477 } 00478 00479 wait_us(50); 00480 int status = _spi.write(0); 00481 if (status != AR1021_RESP_STAT_OK) { 00482 ret = -status; 00483 break; 00484 } 00485 00486 wait_us(50); 00487 int cmdId = _spi.write(0); 00488 if (cmdId != 0x14) { 00489 ret = AR1021_ERR_INV_RESP; 00490 break; 00491 } 00492 00493 00494 // make sure we wait 50us before issuing a new cmd 00495 wait_us(50); 00496 00497 } while (0); 00498 00499 00500 return ret; 00501 } 00502 00503 00504 void AR1021::readTouchIrq() { 00505 while(_siq.read() == 1) { 00506 00507 _cs = 0; 00508 00509 // touch coordinates are sent in a 5-byte data packet 00510 00511 int pen = _spi.write(0); 00512 wait_us(50); 00513 00514 int xlo = _spi.write(0); 00515 wait_us(50); 00516 00517 int xhi = _spi.write(0); 00518 wait_us(50); 00519 00520 int ylo = _spi.write(0); 00521 wait_us(50); 00522 00523 int yhi = _spi.write(0); 00524 wait_us(50); 00525 00526 _cs = 1; 00527 00528 00529 // pen down 00530 if ((pen&AR1021_PEN_MASK) == (1<<7|1<<0)) { 00531 _pen = 1; 00532 } 00533 // pen up 00534 else if ((pen&AR1021_PEN_MASK) == (1<<7)){ 00535 _pen = 0; 00536 } 00537 // invalid value 00538 else { 00539 continue; 00540 } 00541 00542 _x = ((xhi<<7)|xlo); 00543 _y = ((yhi<<7)|ylo); 00544 00545 } 00546 } 00547
Generated on Thu Jul 14 2022 09:42:14 by 1.7.2