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