00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 extern "C"
00023 {
00024 #include <Wire.h>
00025 #include <string.h>
00026 }
00027 #include "SM130.h"
00028
00029
00030 void arrayToHex(char *s, byte array[], byte len);
00031 char toHex(byte b);
00032
00033
00034
00035
00036
00037
00038
00039
00040 SM130::SM130()
00041 {
00042 address = 0x42;
00043 pinRESET = 3;
00044 pinDREADY = 4;
00045 debug = false;
00046 t = millis() + 10;
00047 }
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 void SM130::reset()
00066 {
00067
00068 if (pinDREADY != 0xff)
00069 {
00070 pinMode(pinDREADY, INPUT);
00071 }
00072
00073
00074 if (pinRESET != 0xff)
00075 {
00076 pinMode(pinRESET, OUTPUT);
00077 digitalWrite(pinRESET, HIGH);
00078 delay(10);
00079 digitalWrite(pinRESET, LOW);
00080 }
00081 else
00082 {
00083 sendCommand(CMD_RESET);
00084 }
00085
00086
00087 delay(200);
00088
00089
00090 setAntennaPower(1);
00091
00092
00093 haltTag();
00094 }
00095
00096
00097
00098 const char* SM130::getFirmwareVersion()
00099 {
00100
00101 if (*versionString != 0)
00102 return versionString;
00103
00104
00105 for (byte n = 0; n < 10; n++)
00106 {
00107 sendCommand(CMD_VERSION);
00108 if (available() && getCommand() == CMD_VERSION)
00109 return versionString;
00110 delay(100);
00111 }
00112
00113 return 0;
00114 }
00115
00116
00117
00118
00119
00120
00121
00122
00123 boolean SM130::available()
00124 {
00125
00126 if (cmd == CMD_SEEK_TAG && pinDREADY != 0xff)
00127 {
00128 if (!digitalRead(pinDREADY))
00129 return false;
00130 }
00131
00132
00133 byte len;
00134 switch(cmd)
00135 {
00136 case CMD_ANTENNA_POWER:
00137 case CMD_AUTHENTICATE:
00138 case CMD_DEC_VALUE:
00139 case CMD_INC_VALUE:
00140 case CMD_WRITE_KEY:
00141 case CMD_HALT_TAG:
00142 case CMD_SLEEP:
00143 len = 4;
00144 break;
00145 case CMD_WRITE4:
00146 case CMD_WRITE_VALUE:
00147 case CMD_READ_VALUE:
00148 len = 8;
00149 case CMD_SEEK_TAG:
00150 case CMD_SELECT_TAG:
00151 len = 11;
00152 break;
00153 default:
00154 len = SIZE_PACKET;
00155 }
00156
00157
00158 if (receiveData(len) > 0)
00159 {
00160
00161 tagType = tagLength = *tagString = 0;
00162
00163
00164 errorCode = getPacketLength() < 3 ? data[2] : 0;
00165
00166
00167 switch (getCommand())
00168 {
00169 case CMD_RESET:
00170 case CMD_VERSION:
00171
00172 len = min(getPacketLength(), sizeof(versionString)) - 1;
00173 memcpy(versionString, data + 2, len);
00174 versionString[len] = 0;
00175 break;
00176
00177 case CMD_SEEK_TAG:
00178 case CMD_SELECT_TAG:
00179
00180 if(errorCode == 0 && getPacketLength() >= 6)
00181 {
00182 tagLength = getPacketLength() - 2;
00183 tagType = data[2];
00184 memcpy(tagNumber, data + 3, tagLength);
00185 arrayToHex(tagString, tagNumber, tagLength);
00186 }
00187 break;
00188
00189 case CMD_AUTHENTICATE:
00190 break;
00191
00192 case CMD_READ16:
00193 break;
00194
00195 case CMD_WRITE16:
00196 case CMD_WRITE4:
00197 break;
00198
00199 case CMD_ANTENNA_POWER:
00200 errorCode = 0;
00201 antennaPower = data[2];
00202 break;
00203
00204 case CMD_SLEEP:
00205
00206 return false;
00207 }
00208
00209
00210 return true;
00211 }
00212
00213 return false;
00214 }
00215
00216
00217
00218
00219
00220 const char* SM130::getErrorMessage()
00221 {
00222 switch(errorCode)
00223 {
00224 case 'L':
00225 if(getCommand() == CMD_SEEK_TAG) return "Seek in progress";
00226 case 0:
00227 return "OK";
00228 case 'N':
00229 if(getCommand() == CMD_WRITE_KEY) return "Write master key failed";
00230 if(getCommand() == CMD_SET_BAUD) return "Set baud rate failed";
00231 if(getCommand() == CMD_AUTHENTICATE) return "No tag present or login failed";
00232 return "No tag present";
00233 case 'U':
00234 if(getCommand() == CMD_AUTHENTICATE) return "Authentication failed";
00235 if(getCommand() == CMD_WRITE16 || getCommand() == CMD_WRITE4) return "Verification failed";
00236 return "Antenna off";
00237 case 'F':
00238 if(getCommand() == CMD_READ16) return "Read failed";
00239 return "Write failed";
00240 case 'I':
00241 return "Invalid value block";
00242 case 'X':
00243 return "Block is read-protected";
00244 case 'E':
00245 return "Invalid key format in EEPROM";
00246 default:
00247 return "Unknown error";
00248 }
00249 }
00250
00251
00252
00253
00254
00255 void SM130::setAntennaPower(byte level)
00256 {
00257 antennaPower = level;
00258 data[0] = 2;
00259 data[1] = CMD_ANTENNA_POWER;
00260 data[2] = antennaPower;
00261 transmitData();
00262 }
00263
00264
00265
00266
00267
00268 void SM130::authenticate(byte block)
00269 {
00270 data[0] = 3;
00271 data[1] = CMD_AUTHENTICATE;
00272 data[2] = block;
00273 data[3] = 0xff;
00274 transmitData();
00275 }
00276
00277
00278
00279
00280
00281
00282
00283 void SM130::authenticate(byte block, byte keyType, byte key[6])
00284 {
00285 data[0] = 9;
00286 data[1] = CMD_AUTHENTICATE;
00287 data[2] = block;
00288 data[3] = keyType;
00289 memcpy(data + 4, key, 6);
00290 transmitData();
00291 }
00292
00293
00294
00295
00296
00297 void SM130::readBlock(byte block)
00298 {
00299 data[0] = 2;
00300 data[1] = CMD_READ16;
00301 data[2] = block;
00302 transmitData();
00303 }
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 void SM130::writeBlock(byte block, const char* message)
00314 {
00315 data[0] = 18;
00316 data[1] = CMD_WRITE16;
00317 data[2] = block;
00318 strncpy((char*)data + 3, message, 15);
00319 data[18] = 0;
00320 transmitData();
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
00330 void SM130::writeFourByteBlock(byte block, const char* message)
00331 {
00332 data[0] = 6;
00333 data[1] = CMD_WRITE4;
00334 data[2] = block;
00335 strncpy((char*)data + 3, message, 3);
00336 data[6] = 0;
00337 transmitData();
00338 }
00339
00340
00341
00342
00343
00344 void SM130::sendCommand(byte cmd)
00345 {
00346 data[0] = 1;
00347 data[1] = cmd;
00348 transmitData();
00349 }
00350
00351
00352
00353
00354
00355
00356 void SM130::transmitData()
00357 {
00358
00359 while(t > millis());
00360 t = millis() + 20;
00361
00362
00363 byte sum = 0;
00364 byte len = data[0] + 1;
00365
00366
00367 cmd = data[1];
00368
00369
00370 Wire.beginTransmission(address);
00371 for (int i = 0; i < len; i++)
00372 {
00373 Wire.send(data[i]);
00374 sum += data[i];
00375 }
00376 Wire.send(sum);
00377 Wire.endTransmission();
00378
00379
00380 if (debug)
00381 {
00382 Serial.print("> ");
00383 printArrayHex(data, len);
00384 Serial.print(' ');
00385 printHex(sum);
00386 Serial.println();
00387 }
00388 }
00389
00390
00391
00392
00393
00394
00395 byte SM130::receiveData(byte length)
00396 {
00397
00398 while(t > millis());
00399 t = millis() + 20;
00400
00401
00402 Wire.requestFrom(address, length);
00403 byte n = Wire.available();
00404
00405
00406 if(n > 0)
00407 {
00408 for (byte i = 0; i < n;)
00409 {
00410 data[i++] = Wire.receive();
00411 }
00412
00413
00414 if (debug && data[0] > 0 )
00415 {
00416 Serial.print("< ");
00417 printArrayHex(data, n);
00418 Serial.println();
00419 }
00420
00421
00422 if (data[0] > 0 && data[0] <= SIZE_PAYLOAD)
00423 {
00424 byte i, sum;
00425 for (i = 0, sum = 0; i <= data[0]; i++)
00426 {
00427 sum += data[i];
00428 }
00429
00430 return sum == data[i] ? data[0] : -1;
00431 }
00432 }
00433 return 0;
00434 }
00435
00436
00437
00438
00439
00440
00441 const char* SM130::tagName(byte type)
00442 {
00443 switch(type)
00444 {
00445 case 1: return "Mifare UL";
00446 case 2: return "Mifare 1K";
00447 case 3: return "Mifare 4K";
00448 default: return "Unknown Tag";
00449 }
00450 }
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 void arrayToHex(char *s, byte array[], byte len)
00461 {
00462 for (byte i = 0; i < len; i++)
00463 {
00464 *s++ = toHex(array[i] >> 4);
00465 *s++ = toHex(array[i]);
00466 }
00467 *s = 0;
00468 }
00469
00470
00471
00472
00473
00474
00475 char toHex(byte b)
00476 {
00477 b = b & 0x0f;
00478 return b < 10 ? b + '0' : b + 'A' - 10;
00479 }
00480
00481
00482
00483
00484
00485
00486
00487
00488 void printArrayAscii(byte array[], byte len)
00489 {
00490 for (byte i = 0; i < len;)
00491 {
00492 char c = array[i++];
00493 if (c < 0x20 || c > 0x7e)
00494 {
00495 Serial.print('.');
00496 }
00497 else
00498 {
00499 Serial.print(char(c));
00500 }
00501 }
00502 }
00503
00504
00505
00506
00507
00508
00509 void printArrayHex(byte array[], byte len)
00510 {
00511 for (byte i = 0; i < len;)
00512 {
00513 printHex(array[i++]);
00514 if (i < len)
00515 {
00516 Serial.print(' ');
00517 }
00518 }
00519 }
00520
00521
00522
00523
00524 void printHex(byte val)
00525 {
00526 if (val < 0x10)
00527 {
00528 Serial.print('0');
00529 }
00530 Serial.print(val, HEX);
00531 }