Ryota Hanyu / Mbed 2 deprecated RC-S620_test

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RCS620S.cpp Source File

RCS620S.cpp

00001 /*
00002  * RC-S620/S sample library for Arduino
00003  *
00004  * Copyright 2010 Sony Corporation
00005  *
00006  * Rewrite for mbed
00007  *
00008  * modified by SWITCHSCIENCE
00009  * 
00010  */
00011 
00012 #include <stdio.h>
00013 #include <string.h>
00014 #include <stdint.h>
00015 #include "RCS620S.h"
00016 #include "mbed.h"
00017 
00018 extern Serial serial;
00019 
00020 /* --------------------------------
00021  * Constant
00022  * -------------------------------- */
00023 
00024 #define RCS620S_DEFAULT_TIMEOUT  1000
00025 
00026 /* --------------------------------
00027  * Variable
00028  * -------------------------------- */
00029 
00030 /* --------------------------------
00031  * Prototype Declaration
00032  * -------------------------------- */
00033 
00034 /* --------------------------------
00035  * Macro
00036  * -------------------------------- */
00037 
00038 /* --------------------------------
00039  * Function
00040  * -------------------------------- */
00041 
00042 /* ------------------------
00043  * public
00044  * ------------------------ */
00045 
00046 RCS620S::RCS620S()
00047 {
00048     this->timeout = RCS620S_DEFAULT_TIMEOUT;
00049 
00050 }
00051 
00052 int RCS620S::initDevice(void)
00053 {
00054     int ret;
00055     uint8_t response[RCS620S_MAX_RW_RESPONSE_LEN];
00056     uint16_t responseLen;
00057 
00058     /* RFConfiguration (various timings) */
00059     ret = rwCommand((const uint8_t*)"\xd4\x32\x02\x00\x00\x00", 6,
00060                     response, &responseLen);
00061     if (!ret || (responseLen != 2) ||
00062         (memcmp(response, "\xd5\x33", 2) != 0)) {
00063         return 0;
00064     }
00065 
00066     /* RFConfiguration (max retries) */
00067     ret = rwCommand((const uint8_t*)"\xd4\x32\x05\x00\x00\x00", 6,
00068                     response, &responseLen);
00069     if (!ret || (responseLen != 2) ||
00070         (memcmp(response, "\xd5\x33", 2) != 0)) {
00071         return 0;
00072     }
00073 
00074     /* RFConfiguration (additional wait time = 24ms) */
00075     ret = rwCommand((const uint8_t*)"\xd4\x32\x81\xb7", 4,
00076                     response, &responseLen);
00077     if (!ret || (responseLen != 2) ||
00078         (memcmp(response, "\xd5\x33", 2) != 0)) {
00079         return 0;
00080     }
00081 
00082     return 1;
00083 }
00084 
00085 int RCS620S::polling(uint16_t systemCode)
00086 {
00087     int ret;
00088     uint8_t buf[9];
00089     uint8_t response[RCS620S_MAX_RW_RESPONSE_LEN];
00090     uint16_t responseLen;
00091 
00092     /* InListPassiveTarget */
00093     memcpy(buf, "\xd4\x4a\x01\x01\x00\xff\xff\x00\x00", 9);
00094     buf[5] = (uint8_t)((systemCode >> 8) & 0xff);
00095     buf[6] = (uint8_t)((systemCode >> 0) & 0xff);
00096 
00097     ret = rwCommand(buf, 9, response, &responseLen);
00098     if (!ret || (responseLen != 22) ||
00099         (memcmp(response, "\xd5\x4b\x01\x01\x12\x01", 6) != 0)) {
00100         return 0;
00101     }
00102 
00103     memcpy(this->idm, response + 6, 8);
00104     memcpy(this->pmm, response + 14, 8);
00105 
00106     return 1;
00107 }
00108 
00109 int RCS620S::cardCommand(
00110     const uint8_t* command,
00111     uint8_t commandLen,
00112     uint8_t response[RCS620S_MAX_CARD_RESPONSE_LEN],
00113     uint8_t* responseLen)
00114 {
00115     int ret;
00116     uint16_t commandTimeout;
00117     uint8_t buf[RCS620S_MAX_RW_RESPONSE_LEN];
00118     uint16_t len;
00119 
00120     if (this->timeout >= (0x10000 / 2)) {
00121         commandTimeout = 0xffff;
00122     } else {
00123         commandTimeout = (uint16_t)(this->timeout * 2);
00124     }
00125 
00126     /* CommunicateThruEX */
00127     buf[0] = 0xd4;
00128     buf[1] = 0xa0;
00129     buf[2] = (uint8_t)((commandTimeout >> 0) & 0xff);
00130     buf[3] = (uint8_t)((commandTimeout >> 8) & 0xff);
00131     buf[4] = (uint8_t)(commandLen + 1);
00132     memcpy(buf + 5, command, commandLen);
00133 
00134     ret = rwCommand(buf, 5 + commandLen, buf, &len);
00135     if (!ret || (len < 4) ||
00136         (buf[0] != 0xd5) || (buf[1] != 0xa1) || (buf[2] != 0x00) ||
00137         (len != (3 + buf[3]))) {
00138         return 0;
00139     }
00140 
00141     *responseLen = (uint8_t)(buf[3] - 1);
00142     memcpy(response, buf + 4, *responseLen);
00143 
00144     return 1;
00145 }
00146 
00147 int RCS620S::rfOff(void)
00148 {
00149     int ret;
00150     uint8_t response[RCS620S_MAX_RW_RESPONSE_LEN];
00151     uint16_t responseLen;
00152 
00153     /* RFConfiguration (RF field) */
00154     ret = rwCommand((const uint8_t*)"\xd4\x32\x01\x00", 4,
00155                     response, &responseLen);
00156     if (!ret || (responseLen != 2) ||
00157         (memcmp(response, "\xd5\x33", 2) != 0)) {
00158         return 0;
00159     }
00160 
00161     return 1;
00162 }
00163 
00164 int RCS620S::push(
00165     const uint8_t* data,
00166     uint8_t dataLen)
00167 {
00168     int ret;
00169     uint8_t buf[RCS620S_MAX_CARD_RESPONSE_LEN];
00170     uint8_t responseLen;
00171 
00172     if (dataLen > 224) {
00173         return 0;
00174     }
00175 
00176     /* Push */
00177     buf[0] = 0xb0;
00178     memcpy(buf + 1, this->idm, 8);
00179     buf[9] = dataLen;
00180     memcpy(buf + 10, data, dataLen);
00181 
00182     ret = cardCommand(buf, 10 + dataLen, buf, &responseLen);
00183     if (!ret || (responseLen != 10) || (buf[0] != 0xb1) ||
00184         (memcmp(buf + 1, this->idm, 8) != 0) || (buf[9] != dataLen)) {
00185         return 0;
00186     }
00187 
00188     buf[0] = 0xa4;
00189     memcpy(buf + 1, this->idm, 8);
00190     buf[9] = 0x00;
00191 
00192     ret = cardCommand(buf, 10, buf, &responseLen);
00193     if (!ret || (responseLen != 10) || (buf[0] != 0xa5) ||
00194         (memcmp(buf + 1, this->idm, 8) != 0) || (buf[9] != 0x00)) {
00195         return 0;
00196     }
00197 
00198     wait(1);
00199     return 1;
00200 }
00201 
00202 /* ------------------------
00203  * private
00204  * ------------------------ */
00205 
00206 int RCS620S::rwCommand(
00207     const uint8_t* command,
00208     uint16_t commandLen,
00209     uint8_t response[RCS620S_MAX_RW_RESPONSE_LEN],
00210     uint16_t* responseLen)
00211 {
00212     int ret;
00213     uint8_t buf[9];
00214 
00215     flushSerial();
00216 
00217     uint8_t dcs = calcDCS(command, commandLen);
00218 
00219     /* transmit the command */
00220     buf[0] = 0x00;
00221     buf[1] = 0x00;
00222     buf[2] = 0xff;
00223     if (commandLen <= 255) {
00224         /* normal frame */
00225         buf[3] = commandLen;
00226         buf[4] = (uint8_t)-buf[3];
00227         writeSerial(buf, 5);
00228     } else {
00229         /* extended frame */
00230         buf[3] = 0xff;
00231         buf[4] = 0xff;
00232         buf[5] = (uint8_t)((commandLen >> 8) & 0xff);
00233         buf[6] = (uint8_t)((commandLen >> 0) & 0xff);
00234         buf[7] = (uint8_t)-(buf[5] + buf[6]);
00235         writeSerial(buf, 8);
00236     }
00237     writeSerial(command, commandLen);
00238     buf[0] = dcs;
00239     buf[1] = 0x00;
00240     writeSerial(buf, 2);
00241 
00242     /* receive an ACK */
00243     ret = readSerial(buf, 6);
00244     if (!ret || (memcmp(buf, "\x00\x00\xff\x00\xff\x00", 6) != 0)) {
00245         cancel();
00246         return 0;
00247     }
00248 
00249     /* receive a response */
00250     ret = readSerial(buf, 5);
00251     if (!ret) {
00252         cancel();
00253         return 0;
00254     } else if  (memcmp(buf, "\x00\x00\xff", 3) != 0) {
00255         return 0;
00256     }
00257     if ((buf[3] == 0xff) && (buf[4] == 0xff)) {
00258         ret = readSerial(buf + 5, 3);
00259         if (!ret || (((buf[5] + buf[6] + buf[7]) & 0xff) != 0)) {
00260             return 0;
00261         }
00262         *responseLen = (((uint16_t)buf[5] << 8) |
00263                         ((uint16_t)buf[6] << 0));
00264     } else {
00265         if (((buf[3] + buf[4]) & 0xff) != 0) {
00266             return 0;
00267         }
00268         *responseLen = buf[3];
00269     }
00270     if (*responseLen > RCS620S_MAX_RW_RESPONSE_LEN) {
00271         return 0;
00272     }
00273 
00274     ret = readSerial(response, *responseLen);
00275     if (!ret) {
00276         cancel();
00277         return 0;
00278     }
00279 
00280     dcs = calcDCS(response, *responseLen);
00281 
00282     ret = readSerial(buf, 2);
00283     if (!ret || (buf[0] != dcs) || (buf[1] != 0x00)) {
00284         cancel();
00285         return 0;
00286     }
00287 
00288     return 1;
00289 }
00290 
00291 void RCS620S::cancel(void)
00292 {
00293     /* transmit an ACK */
00294     writeSerial((const uint8_t*)"\x00\x00\xff\x00\xff\x00", 6);
00295     wait(1);
00296     flushSerial();
00297 }
00298 
00299 uint8_t RCS620S::calcDCS(
00300     const uint8_t* data,
00301     uint16_t len)
00302 {
00303     uint8_t sum = 0;
00304 
00305     for (uint16_t i = 0; i < len; i++) {
00306         sum += data[i];
00307     }
00308 
00309     return (uint8_t)-(sum & 0xff);
00310 }
00311 
00312 void RCS620S::writeSerial(
00313     const uint8_t* data,
00314     uint16_t len)
00315 {
00316 //    Serial.write(data, len);
00317     uint16_t nwrite = 0;
00318 
00319     while (nwrite < len) {
00320         serial.putc( *(data + nwrite) );
00321         nwrite++;
00322     }
00323 }
00324 
00325 
00326 int RCS620S::readSerial(
00327     uint8_t* data,
00328     uint16_t len)
00329 {
00330     uint16_t nread = 0;
00331     time_t t0 = time(NULL);
00332 
00333     while (nread < len) {
00334         if ((checkTimeout(t0))) {
00335             return 0;
00336         }
00337 
00338         if (serial.readable() > 0) {
00339             data[nread] = serial.getc();
00340             nread++;
00341         }
00342     }
00343 
00344     return 1;
00345 }
00346 
00347 
00348 void RCS620S::flushSerial(void)
00349 {
00350     while( serial.readable() );     
00351 }
00352 
00353 
00354 int RCS620S::checkTimeout(time_t t0)
00355 {
00356     time_t t = time(NULL);
00357 
00358     if ((t - t0) >= this->timeout) {
00359         return 1;
00360     }
00361 
00362     return 0;
00363 }