The wait in mci_WaitForEvent will delay all card transactions.

Dependencies:   FATFileSystem

Fork of EALib by EmbeddedArtists AB

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers AR1021.cpp Source File

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                     &regOffset, &regOffLen);
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                     &regOffset, &regOffLen);
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