to colorize a colorful pixel with a simple touch using nfc technology

Dependencies:   Chainable_RGB_LED mbed

use Arch, NFC Shield and Grove - Chainable RGB LED to DIY a touch pixel. Then use an Android with NFC support to colorize it.

The project is on https://github.com/Seeed-Studio/TouchPixel

Committer:
yihui
Date:
Fri Dec 27 01:46:32 2013 +0000
Revision:
0:88960f3eeb2c
initial

Who changed what in which revision?

UserRevisionLine numberNew contents of line
yihui 0:88960f3eeb2c 1 #include "MifareUltralight.h"
yihui 0:88960f3eeb2c 2
yihui 0:88960f3eeb2c 3 #include "PN532_debug.h"
yihui 0:88960f3eeb2c 4
yihui 0:88960f3eeb2c 5 #define ULTRALIGHT_PAGE_SIZE 4
yihui 0:88960f3eeb2c 6 #define ULTRALIGHT_READ_SIZE 4 // we should be able to read 16 uint8_ts at a time
yihui 0:88960f3eeb2c 7
yihui 0:88960f3eeb2c 8 #define ULTRALIGHT_DATA_START_PAGE 4
yihui 0:88960f3eeb2c 9 #define ULTRALIGHT_MESSAGE_LENGTH_INDEX 1
yihui 0:88960f3eeb2c 10 #define ULTRALIGHT_DATA_START_INDEX 2
yihui 0:88960f3eeb2c 11 #define ULTRALIGHT_MAX_PAGE 63
yihui 0:88960f3eeb2c 12
yihui 0:88960f3eeb2c 13 #define NFC_FORUM_TAG_TYPE_2 ("NFC Forum Type 2")
yihui 0:88960f3eeb2c 14
yihui 0:88960f3eeb2c 15 MifareUltralight::MifareUltralight(PN532& nfcShield)
yihui 0:88960f3eeb2c 16 {
yihui 0:88960f3eeb2c 17 nfc = &nfcShield;
yihui 0:88960f3eeb2c 18 ndefStartIndex = 0;
yihui 0:88960f3eeb2c 19 messageLength = 0;
yihui 0:88960f3eeb2c 20 }
yihui 0:88960f3eeb2c 21
yihui 0:88960f3eeb2c 22 MifareUltralight::~MifareUltralight()
yihui 0:88960f3eeb2c 23 {
yihui 0:88960f3eeb2c 24 }
yihui 0:88960f3eeb2c 25
yihui 0:88960f3eeb2c 26 NfcTag MifareUltralight::read(uint8_t * uid, unsigned int uidLength)
yihui 0:88960f3eeb2c 27 {
yihui 0:88960f3eeb2c 28 if (isUnformatted())
yihui 0:88960f3eeb2c 29 {
yihui 0:88960f3eeb2c 30 DMSG("WARNING: Tag is not formatted.");
yihui 0:88960f3eeb2c 31 return NfcTag(uid, uidLength, NFC_FORUM_TAG_TYPE_2);
yihui 0:88960f3eeb2c 32 }
yihui 0:88960f3eeb2c 33
yihui 0:88960f3eeb2c 34 readCapabilityContainer(); // meta info for tag
yihui 0:88960f3eeb2c 35 findNdefMessage();
yihui 0:88960f3eeb2c 36 calculateBufferSize();
yihui 0:88960f3eeb2c 37
yihui 0:88960f3eeb2c 38 if (messageLength == 0) { // data is 0x44 0x03 0x00 0xFE
yihui 0:88960f3eeb2c 39 NdefMessage message = NdefMessage();
yihui 0:88960f3eeb2c 40 message.addEmptyRecord();
yihui 0:88960f3eeb2c 41 return NfcTag(uid, uidLength, NFC_FORUM_TAG_TYPE_2, message);
yihui 0:88960f3eeb2c 42 }
yihui 0:88960f3eeb2c 43
yihui 0:88960f3eeb2c 44 bool success;
yihui 0:88960f3eeb2c 45 uint8_t page;
yihui 0:88960f3eeb2c 46 uint8_t index = 0;
yihui 0:88960f3eeb2c 47 uint8_t buffer[bufferSize];
yihui 0:88960f3eeb2c 48 for (page = ULTRALIGHT_DATA_START_PAGE; page < ULTRALIGHT_MAX_PAGE; page++)
yihui 0:88960f3eeb2c 49 {
yihui 0:88960f3eeb2c 50 // read the data
yihui 0:88960f3eeb2c 51 success = nfc->mifareultralight_ReadPage(page, &buffer[index]);
yihui 0:88960f3eeb2c 52 if (success)
yihui 0:88960f3eeb2c 53 {
yihui 0:88960f3eeb2c 54 #ifdef MIFARE_ULTRALIGHT_DEBUG
yihui 0:88960f3eeb2c 55 DMSG("Page ");Serial.print(page);DMSG(" ");
yihui 0:88960f3eeb2c 56 nfc->PrintHexChar(&buffer[index], ULTRALIGHT_PAGE_SIZE);
yihui 0:88960f3eeb2c 57 #endif
yihui 0:88960f3eeb2c 58 }
yihui 0:88960f3eeb2c 59 else
yihui 0:88960f3eeb2c 60 {
yihui 0:88960f3eeb2c 61 DMSG("Read failed ");DMSG_INT(page);
yihui 0:88960f3eeb2c 62 // TODO error handling
yihui 0:88960f3eeb2c 63 messageLength = 0;
yihui 0:88960f3eeb2c 64 break;
yihui 0:88960f3eeb2c 65 }
yihui 0:88960f3eeb2c 66
yihui 0:88960f3eeb2c 67 if (index >= (messageLength + ndefStartIndex))
yihui 0:88960f3eeb2c 68 {
yihui 0:88960f3eeb2c 69 break;
yihui 0:88960f3eeb2c 70 }
yihui 0:88960f3eeb2c 71
yihui 0:88960f3eeb2c 72 index += ULTRALIGHT_PAGE_SIZE;
yihui 0:88960f3eeb2c 73 }
yihui 0:88960f3eeb2c 74
yihui 0:88960f3eeb2c 75 NdefMessage ndefMessage = NdefMessage(&buffer[ndefStartIndex], messageLength);
yihui 0:88960f3eeb2c 76 return NfcTag(uid, uidLength, NFC_FORUM_TAG_TYPE_2, ndefMessage);
yihui 0:88960f3eeb2c 77
yihui 0:88960f3eeb2c 78 }
yihui 0:88960f3eeb2c 79
yihui 0:88960f3eeb2c 80 bool MifareUltralight::isUnformatted()
yihui 0:88960f3eeb2c 81 {
yihui 0:88960f3eeb2c 82 uint8_t page = 4;
yihui 0:88960f3eeb2c 83 uint8_t data[ULTRALIGHT_READ_SIZE];
yihui 0:88960f3eeb2c 84 bool success = nfc->mifareultralight_ReadPage (page, data);
yihui 0:88960f3eeb2c 85 if (success)
yihui 0:88960f3eeb2c 86 {
yihui 0:88960f3eeb2c 87 return (data[0] == 0xFF && data[1] == 0xFF && data[2] == 0xFF && data[3] == 0xFF);
yihui 0:88960f3eeb2c 88 }
yihui 0:88960f3eeb2c 89 else
yihui 0:88960f3eeb2c 90 {
yihui 0:88960f3eeb2c 91 DMSG("Error. Failed read page ");DMSG_INT(page);
yihui 0:88960f3eeb2c 92 return false;
yihui 0:88960f3eeb2c 93 }
yihui 0:88960f3eeb2c 94 }
yihui 0:88960f3eeb2c 95
yihui 0:88960f3eeb2c 96 // page 3 has tag capabilities
yihui 0:88960f3eeb2c 97 void MifareUltralight::readCapabilityContainer()
yihui 0:88960f3eeb2c 98 {
yihui 0:88960f3eeb2c 99 uint8_t data[ULTRALIGHT_PAGE_SIZE];
yihui 0:88960f3eeb2c 100 int success = nfc->mifareultralight_ReadPage (3, data);
yihui 0:88960f3eeb2c 101 if (success)
yihui 0:88960f3eeb2c 102 {
yihui 0:88960f3eeb2c 103 // See AN1303 - different rules for Mifare Family uint8_t2 = (additional data + 48)/8
yihui 0:88960f3eeb2c 104 tagCapacity = data[2] * 8;
yihui 0:88960f3eeb2c 105 #ifdef MIFARE_ULTRALIGHT_DEBUG
yihui 0:88960f3eeb2c 106 DMSG("Tag capacity "));Serial.print(tagCapacity);DMSG(F(" uint8_ts");
yihui 0:88960f3eeb2c 107 #endif
yihui 0:88960f3eeb2c 108
yihui 0:88960f3eeb2c 109 // TODO future versions should get lock information
yihui 0:88960f3eeb2c 110 }
yihui 0:88960f3eeb2c 111 }
yihui 0:88960f3eeb2c 112
yihui 0:88960f3eeb2c 113 // read enough of the message to find the ndef message length
yihui 0:88960f3eeb2c 114 void MifareUltralight::findNdefMessage()
yihui 0:88960f3eeb2c 115 {
yihui 0:88960f3eeb2c 116 int page;
yihui 0:88960f3eeb2c 117 uint8_t data[12]; // 3 pages
yihui 0:88960f3eeb2c 118 uint8_t* data_ptr = &data[0];
yihui 0:88960f3eeb2c 119
yihui 0:88960f3eeb2c 120 // the nxp read command reads 4 pages, unfortunately adafruit give me one page at a time
yihui 0:88960f3eeb2c 121 bool success = true;
yihui 0:88960f3eeb2c 122 for (page = 4; page < 6; page++)
yihui 0:88960f3eeb2c 123 {
yihui 0:88960f3eeb2c 124 success = success && nfc->mifareultralight_ReadPage(page, data_ptr);
yihui 0:88960f3eeb2c 125 #ifdef MIFARE_ULTRALIGHT_DEBUG
yihui 0:88960f3eeb2c 126 DMSG("Page "));Serial.print(page);Serial.print(F(" - ");
yihui 0:88960f3eeb2c 127 nfc->PrintHexChar(data_ptr, 4);
yihui 0:88960f3eeb2c 128 #endif
yihui 0:88960f3eeb2c 129 data_ptr += ULTRALIGHT_PAGE_SIZE;
yihui 0:88960f3eeb2c 130 }
yihui 0:88960f3eeb2c 131
yihui 0:88960f3eeb2c 132 if (success)
yihui 0:88960f3eeb2c 133 {
yihui 0:88960f3eeb2c 134 if (data[0] == 0x03)
yihui 0:88960f3eeb2c 135 {
yihui 0:88960f3eeb2c 136 messageLength = data[1];
yihui 0:88960f3eeb2c 137 ndefStartIndex = 2;
yihui 0:88960f3eeb2c 138 }
yihui 0:88960f3eeb2c 139 else if (data[5] == 0x3) // page 5 uint8_t 1
yihui 0:88960f3eeb2c 140 {
yihui 0:88960f3eeb2c 141 // TODO should really read the lock control TLV to ensure uint8_t[5] is correct
yihui 0:88960f3eeb2c 142 messageLength = data[6];
yihui 0:88960f3eeb2c 143 ndefStartIndex = 7;
yihui 0:88960f3eeb2c 144 }
yihui 0:88960f3eeb2c 145 }
yihui 0:88960f3eeb2c 146
yihui 0:88960f3eeb2c 147 #ifdef MIFARE_ULTRALIGHT_DEBUG
yihui 0:88960f3eeb2c 148 DMSG("messageLength ");DMSG(messageLength);
yihui 0:88960f3eeb2c 149 DMSG("ndefStartIndex ");DMSG(ndefStartIndex);
yihui 0:88960f3eeb2c 150 #endif
yihui 0:88960f3eeb2c 151 }
yihui 0:88960f3eeb2c 152
yihui 0:88960f3eeb2c 153 // buffer is larger than the message, need to handle some data before and after
yihui 0:88960f3eeb2c 154 // message and need to ensure we read full pages
yihui 0:88960f3eeb2c 155 void MifareUltralight::calculateBufferSize()
yihui 0:88960f3eeb2c 156 {
yihui 0:88960f3eeb2c 157 // TLV terminator 0xFE is 1 uint8_t
yihui 0:88960f3eeb2c 158 bufferSize = messageLength + ndefStartIndex + 1;
yihui 0:88960f3eeb2c 159
yihui 0:88960f3eeb2c 160 if (bufferSize % ULTRALIGHT_READ_SIZE != 0)
yihui 0:88960f3eeb2c 161 {
yihui 0:88960f3eeb2c 162 // buffer must be an increment of page size
yihui 0:88960f3eeb2c 163 bufferSize = ((bufferSize / ULTRALIGHT_READ_SIZE) + 1) * ULTRALIGHT_READ_SIZE;
yihui 0:88960f3eeb2c 164 }
yihui 0:88960f3eeb2c 165 }