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
yihui 0:88960f3eeb2c 2 #include "llcp.h"
yihui 0:88960f3eeb2c 3 #include "PN532_debug.h"
yihui 0:88960f3eeb2c 4
yihui 0:88960f3eeb2c 5 // LLCP PDU Type Values
yihui 0:88960f3eeb2c 6 #define PDU_SYMM 0x00
yihui 0:88960f3eeb2c 7 #define PDU_PAX 0x01
yihui 0:88960f3eeb2c 8 #define PDU_CONNECT 0x04
yihui 0:88960f3eeb2c 9 #define PDU_DISC 0x05
yihui 0:88960f3eeb2c 10 #define PDU_CC 0x06
yihui 0:88960f3eeb2c 11 #define PDU_DM 0x07
yihui 0:88960f3eeb2c 12 #define PDU_I 0x0c
yihui 0:88960f3eeb2c 13 #define PDU_RR 0x0d
yihui 0:88960f3eeb2c 14
yihui 0:88960f3eeb2c 15 uint8_t LLCP::SYMM_PDU[2] = {0, 0};
yihui 0:88960f3eeb2c 16
yihui 0:88960f3eeb2c 17 inline uint8_t getPType(const uint8_t *buf)
yihui 0:88960f3eeb2c 18 {
yihui 0:88960f3eeb2c 19 return ((buf[0] & 0x3) << 2) + (buf[1] >> 6);
yihui 0:88960f3eeb2c 20 }
yihui 0:88960f3eeb2c 21
yihui 0:88960f3eeb2c 22 inline uint8_t getSSAP(const uint8_t *buf)
yihui 0:88960f3eeb2c 23 {
yihui 0:88960f3eeb2c 24 return buf[1] & 0x3f;
yihui 0:88960f3eeb2c 25 }
yihui 0:88960f3eeb2c 26
yihui 0:88960f3eeb2c 27 inline uint8_t getDSAP(const uint8_t *buf)
yihui 0:88960f3eeb2c 28 {
yihui 0:88960f3eeb2c 29 return buf[0] >> 2;
yihui 0:88960f3eeb2c 30 }
yihui 0:88960f3eeb2c 31
yihui 0:88960f3eeb2c 32 int8_t LLCP::activate(uint16_t timeout)
yihui 0:88960f3eeb2c 33 {
yihui 0:88960f3eeb2c 34 return link.activateAsTarget(timeout);
yihui 0:88960f3eeb2c 35 }
yihui 0:88960f3eeb2c 36
yihui 0:88960f3eeb2c 37 int8_t LLCP::waitForConnection(uint16_t timeout)
yihui 0:88960f3eeb2c 38 {
yihui 0:88960f3eeb2c 39 uint8_t type;
yihui 0:88960f3eeb2c 40
yihui 0:88960f3eeb2c 41 mode = 1;
yihui 0:88960f3eeb2c 42 ns = 0;
yihui 0:88960f3eeb2c 43 nr = 0;
yihui 0:88960f3eeb2c 44
yihui 0:88960f3eeb2c 45 // Get CONNECT PDU
yihui 0:88960f3eeb2c 46 DMSG("wait for a CONNECT PDU\n");
yihui 0:88960f3eeb2c 47 do {
yihui 0:88960f3eeb2c 48 if (2 > link.read(headerBuf, headerBufLen)) {
yihui 0:88960f3eeb2c 49 return -1;
yihui 0:88960f3eeb2c 50 }
yihui 0:88960f3eeb2c 51
yihui 0:88960f3eeb2c 52 type = getPType(headerBuf);
yihui 0:88960f3eeb2c 53 if (PDU_CONNECT == type) {
yihui 0:88960f3eeb2c 54 break;
yihui 0:88960f3eeb2c 55 } else if (PDU_SYMM == type) {
yihui 0:88960f3eeb2c 56 if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) {
yihui 0:88960f3eeb2c 57 return -2;
yihui 0:88960f3eeb2c 58 }
yihui 0:88960f3eeb2c 59 } else {
yihui 0:88960f3eeb2c 60 return -3;
yihui 0:88960f3eeb2c 61 }
yihui 0:88960f3eeb2c 62
yihui 0:88960f3eeb2c 63 } while (1);
yihui 0:88960f3eeb2c 64
yihui 0:88960f3eeb2c 65 // Put CC PDU
yihui 0:88960f3eeb2c 66 DMSG("put a CC(Connection Complete) PDU to response the CONNECT PDU\n");
yihui 0:88960f3eeb2c 67 ssap = getDSAP(headerBuf);
yihui 0:88960f3eeb2c 68 dsap = getSSAP(headerBuf);
yihui 0:88960f3eeb2c 69 headerBuf[0] = (dsap << 2) + ((PDU_CC >> 2) & 0x3);
yihui 0:88960f3eeb2c 70 headerBuf[1] = ((PDU_CC & 0x3) << 6) + ssap;
yihui 0:88960f3eeb2c 71 if (!link.write(headerBuf, 2)) {
yihui 0:88960f3eeb2c 72 return -2;
yihui 0:88960f3eeb2c 73 }
yihui 0:88960f3eeb2c 74
yihui 0:88960f3eeb2c 75 return 1;
yihui 0:88960f3eeb2c 76 }
yihui 0:88960f3eeb2c 77
yihui 0:88960f3eeb2c 78 int8_t LLCP::waitForDisconnection(uint16_t timeout)
yihui 0:88960f3eeb2c 79 {
yihui 0:88960f3eeb2c 80 uint8_t type;
yihui 0:88960f3eeb2c 81
yihui 0:88960f3eeb2c 82 // Get DISC PDU
yihui 0:88960f3eeb2c 83 DMSG("wait for a DISC PDU\n");
yihui 0:88960f3eeb2c 84 do {
yihui 0:88960f3eeb2c 85 if (2 > link.read(headerBuf, headerBufLen)) {
yihui 0:88960f3eeb2c 86 return -1;
yihui 0:88960f3eeb2c 87 }
yihui 0:88960f3eeb2c 88
yihui 0:88960f3eeb2c 89 type = getPType(headerBuf);
yihui 0:88960f3eeb2c 90 if (PDU_DISC == type) {
yihui 0:88960f3eeb2c 91 break;
yihui 0:88960f3eeb2c 92 } else if (PDU_SYMM == type) {
yihui 0:88960f3eeb2c 93 if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) {
yihui 0:88960f3eeb2c 94 return -2;
yihui 0:88960f3eeb2c 95 }
yihui 0:88960f3eeb2c 96 } else {
yihui 0:88960f3eeb2c 97 return -3;
yihui 0:88960f3eeb2c 98 }
yihui 0:88960f3eeb2c 99
yihui 0:88960f3eeb2c 100 } while (1);
yihui 0:88960f3eeb2c 101
yihui 0:88960f3eeb2c 102 // Put DM PDU
yihui 0:88960f3eeb2c 103 DMSG("put a DM(Disconnect Mode) PDU to response the DISC PDU\n");
yihui 0:88960f3eeb2c 104 // ssap = getDSAP(headerBuf);
yihui 0:88960f3eeb2c 105 // dsap = getSSAP(headerBuf);
yihui 0:88960f3eeb2c 106 headerBuf[0] = (dsap << 2) + (PDU_DM >> 2);
yihui 0:88960f3eeb2c 107 headerBuf[1] = ((PDU_DM & 0x3) << 6) + ssap;
yihui 0:88960f3eeb2c 108 if (!link.write(headerBuf, 2)) {
yihui 0:88960f3eeb2c 109 return -2;
yihui 0:88960f3eeb2c 110 }
yihui 0:88960f3eeb2c 111
yihui 0:88960f3eeb2c 112 return 1;
yihui 0:88960f3eeb2c 113 }
yihui 0:88960f3eeb2c 114
yihui 0:88960f3eeb2c 115 int8_t LLCP::connect(uint16_t timeout)
yihui 0:88960f3eeb2c 116 {
yihui 0:88960f3eeb2c 117 uint8_t type;
yihui 0:88960f3eeb2c 118
yihui 0:88960f3eeb2c 119 mode = 0;
yihui 0:88960f3eeb2c 120 dsap = LLCP_DEFAULT_DSAP;
yihui 0:88960f3eeb2c 121 ssap = LLCP_DEFAULT_SSAP;
yihui 0:88960f3eeb2c 122 ns = 0;
yihui 0:88960f3eeb2c 123 nr = 0;
yihui 0:88960f3eeb2c 124
yihui 0:88960f3eeb2c 125 // try to get a SYMM PDU
yihui 0:88960f3eeb2c 126 if (2 > link.read(headerBuf, headerBufLen)) {
yihui 0:88960f3eeb2c 127 return -1;
yihui 0:88960f3eeb2c 128 }
yihui 0:88960f3eeb2c 129 type = getPType(headerBuf);
yihui 0:88960f3eeb2c 130 if (PDU_SYMM != type) {
yihui 0:88960f3eeb2c 131 return -1;
yihui 0:88960f3eeb2c 132 }
yihui 0:88960f3eeb2c 133
yihui 0:88960f3eeb2c 134 // put a CONNECT PDU
yihui 0:88960f3eeb2c 135 headerBuf[0] = (LLCP_DEFAULT_DSAP << 2) + (PDU_CONNECT >> 2);
yihui 0:88960f3eeb2c 136 headerBuf[1] = ((PDU_CONNECT & 0x03) << 6) + LLCP_DEFAULT_SSAP;
yihui 0:88960f3eeb2c 137 uint8_t body[] = " urn:nfc:sn:snep";
yihui 0:88960f3eeb2c 138 body[0] = 0x06;
yihui 0:88960f3eeb2c 139 body[1] = sizeof(body) - 2 - 1;
yihui 0:88960f3eeb2c 140 if (!link.write(headerBuf, 2, body, sizeof(body) - 1)) {
yihui 0:88960f3eeb2c 141 return -2;
yihui 0:88960f3eeb2c 142 }
yihui 0:88960f3eeb2c 143
yihui 0:88960f3eeb2c 144 // wait for a CC PDU
yihui 0:88960f3eeb2c 145 DMSG("wait for a CC PDU\n");
yihui 0:88960f3eeb2c 146 do {
yihui 0:88960f3eeb2c 147 if (2 > link.read(headerBuf, headerBufLen)) {
yihui 0:88960f3eeb2c 148 return -1;
yihui 0:88960f3eeb2c 149 }
yihui 0:88960f3eeb2c 150
yihui 0:88960f3eeb2c 151 type = getPType(headerBuf);
yihui 0:88960f3eeb2c 152 if (PDU_CC == type) {
yihui 0:88960f3eeb2c 153 break;
yihui 0:88960f3eeb2c 154 } else if (PDU_SYMM == type) {
yihui 0:88960f3eeb2c 155 if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) {
yihui 0:88960f3eeb2c 156 return -2;
yihui 0:88960f3eeb2c 157 }
yihui 0:88960f3eeb2c 158 } else {
yihui 0:88960f3eeb2c 159 return -3;
yihui 0:88960f3eeb2c 160 }
yihui 0:88960f3eeb2c 161
yihui 0:88960f3eeb2c 162 } while (1);
yihui 0:88960f3eeb2c 163
yihui 0:88960f3eeb2c 164 return 1;
yihui 0:88960f3eeb2c 165 }
yihui 0:88960f3eeb2c 166
yihui 0:88960f3eeb2c 167 int8_t LLCP::disconnect(uint16_t timeout)
yihui 0:88960f3eeb2c 168 {
yihui 0:88960f3eeb2c 169 uint8_t type;
yihui 0:88960f3eeb2c 170
yihui 0:88960f3eeb2c 171 // try to get a SYMM PDU
yihui 0:88960f3eeb2c 172 if (2 > link.read(headerBuf, headerBufLen)) {
yihui 0:88960f3eeb2c 173 return -1;
yihui 0:88960f3eeb2c 174 }
yihui 0:88960f3eeb2c 175 type = getPType(headerBuf);
yihui 0:88960f3eeb2c 176 if (PDU_SYMM != type) {
yihui 0:88960f3eeb2c 177 return -1;
yihui 0:88960f3eeb2c 178 }
yihui 0:88960f3eeb2c 179
yihui 0:88960f3eeb2c 180 // put a DISC PDU
yihui 0:88960f3eeb2c 181 headerBuf[0] = (LLCP_DEFAULT_DSAP << 2) + (PDU_DISC >> 2);
yihui 0:88960f3eeb2c 182 headerBuf[1] = ((PDU_DISC & 0x03) << 6) + LLCP_DEFAULT_SSAP;
yihui 0:88960f3eeb2c 183 if (!link.write(headerBuf, 2)) {
yihui 0:88960f3eeb2c 184 return -2;
yihui 0:88960f3eeb2c 185 }
yihui 0:88960f3eeb2c 186
yihui 0:88960f3eeb2c 187 // wait for a DM PDU
yihui 0:88960f3eeb2c 188 DMSG("wait for a DM PDU\n");
yihui 0:88960f3eeb2c 189 do {
yihui 0:88960f3eeb2c 190 if (2 > link.read(headerBuf, headerBufLen)) {
yihui 0:88960f3eeb2c 191 return -1;
yihui 0:88960f3eeb2c 192 }
yihui 0:88960f3eeb2c 193
yihui 0:88960f3eeb2c 194 type = getPType(headerBuf);
yihui 0:88960f3eeb2c 195 if (PDU_CC == type) {
yihui 0:88960f3eeb2c 196 break;
yihui 0:88960f3eeb2c 197 } else if (PDU_DM == type) {
yihui 0:88960f3eeb2c 198 if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) {
yihui 0:88960f3eeb2c 199 return -2;
yihui 0:88960f3eeb2c 200 }
yihui 0:88960f3eeb2c 201 } else {
yihui 0:88960f3eeb2c 202 return -3;
yihui 0:88960f3eeb2c 203 }
yihui 0:88960f3eeb2c 204
yihui 0:88960f3eeb2c 205 } while (1);
yihui 0:88960f3eeb2c 206
yihui 0:88960f3eeb2c 207 return 1;
yihui 0:88960f3eeb2c 208 }
yihui 0:88960f3eeb2c 209
yihui 0:88960f3eeb2c 210 bool LLCP::write(const uint8_t *header, uint8_t hlen, const uint8_t *body, uint8_t blen)
yihui 0:88960f3eeb2c 211 {
yihui 0:88960f3eeb2c 212 uint8_t type;
yihui 0:88960f3eeb2c 213 uint8_t buf[3];
yihui 0:88960f3eeb2c 214
yihui 0:88960f3eeb2c 215 if (mode) {
yihui 0:88960f3eeb2c 216 // Get a SYMM PDU
yihui 0:88960f3eeb2c 217 if (2 != link.read(buf, sizeof(buf))) {
yihui 0:88960f3eeb2c 218 return false;
yihui 0:88960f3eeb2c 219 }
yihui 0:88960f3eeb2c 220 }
yihui 0:88960f3eeb2c 221
yihui 0:88960f3eeb2c 222 if (headerBufLen < (hlen + 3)) {
yihui 0:88960f3eeb2c 223 return false;
yihui 0:88960f3eeb2c 224 }
yihui 0:88960f3eeb2c 225
yihui 0:88960f3eeb2c 226 for (int8_t i = hlen - 1; i >= 0; i--) {
yihui 0:88960f3eeb2c 227 headerBuf[i + 3] = header[i];
yihui 0:88960f3eeb2c 228 }
yihui 0:88960f3eeb2c 229
yihui 0:88960f3eeb2c 230 headerBuf[0] = (dsap << 2) + (PDU_I >> 2);
yihui 0:88960f3eeb2c 231 headerBuf[1] = ((PDU_I & 0x3) << 6) + ssap;
yihui 0:88960f3eeb2c 232 headerBuf[2] = (ns << 4) + nr;
yihui 0:88960f3eeb2c 233 if (!link.write(headerBuf, 3 + hlen, body, blen)) {
yihui 0:88960f3eeb2c 234 return false;
yihui 0:88960f3eeb2c 235 }
yihui 0:88960f3eeb2c 236
yihui 0:88960f3eeb2c 237 ns++;
yihui 0:88960f3eeb2c 238
yihui 0:88960f3eeb2c 239 // Get a RR PDU
yihui 0:88960f3eeb2c 240 int16_t status;
yihui 0:88960f3eeb2c 241 do {
yihui 0:88960f3eeb2c 242 status = link.read(headerBuf, headerBufLen);
yihui 0:88960f3eeb2c 243 if (2 > status) {
yihui 0:88960f3eeb2c 244 return false;
yihui 0:88960f3eeb2c 245 }
yihui 0:88960f3eeb2c 246
yihui 0:88960f3eeb2c 247 type = getPType(headerBuf);
yihui 0:88960f3eeb2c 248 if (PDU_RR == type) {
yihui 0:88960f3eeb2c 249 break;
yihui 0:88960f3eeb2c 250 } else if (PDU_SYMM == type) {
yihui 0:88960f3eeb2c 251 if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) {
yihui 0:88960f3eeb2c 252 return false;
yihui 0:88960f3eeb2c 253 }
yihui 0:88960f3eeb2c 254 } else {
yihui 0:88960f3eeb2c 255 return false;
yihui 0:88960f3eeb2c 256 }
yihui 0:88960f3eeb2c 257 } while (1);
yihui 0:88960f3eeb2c 258
yihui 0:88960f3eeb2c 259 if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) {
yihui 0:88960f3eeb2c 260 return false;
yihui 0:88960f3eeb2c 261 }
yihui 0:88960f3eeb2c 262
yihui 0:88960f3eeb2c 263 return true;
yihui 0:88960f3eeb2c 264 }
yihui 0:88960f3eeb2c 265
yihui 0:88960f3eeb2c 266 int16_t LLCP::read(uint8_t *buf, uint8_t length)
yihui 0:88960f3eeb2c 267 {
yihui 0:88960f3eeb2c 268 uint8_t type;
yihui 0:88960f3eeb2c 269 uint16_t status;
yihui 0:88960f3eeb2c 270
yihui 0:88960f3eeb2c 271 // Get INFO PDU
yihui 0:88960f3eeb2c 272 do {
yihui 0:88960f3eeb2c 273 status = link.read(buf, length);
yihui 0:88960f3eeb2c 274 if (2 > status) {
yihui 0:88960f3eeb2c 275 return -1;
yihui 0:88960f3eeb2c 276 }
yihui 0:88960f3eeb2c 277
yihui 0:88960f3eeb2c 278 type = getPType(buf);
yihui 0:88960f3eeb2c 279 if (PDU_I == type) {
yihui 0:88960f3eeb2c 280 break;
yihui 0:88960f3eeb2c 281 } else if (PDU_SYMM == type) {
yihui 0:88960f3eeb2c 282 if (!link.write(SYMM_PDU, sizeof(SYMM_PDU))) {
yihui 0:88960f3eeb2c 283 return -2;
yihui 0:88960f3eeb2c 284 }
yihui 0:88960f3eeb2c 285 } else {
yihui 0:88960f3eeb2c 286 return -3;
yihui 0:88960f3eeb2c 287 }
yihui 0:88960f3eeb2c 288
yihui 0:88960f3eeb2c 289 } while (1);
yihui 0:88960f3eeb2c 290
yihui 0:88960f3eeb2c 291 uint8_t len = status - 3;
yihui 0:88960f3eeb2c 292 ssap = getDSAP(buf);
yihui 0:88960f3eeb2c 293 dsap = getSSAP(buf);
yihui 0:88960f3eeb2c 294
yihui 0:88960f3eeb2c 295 headerBuf[0] = (dsap << 2) + (PDU_RR >> 2);
yihui 0:88960f3eeb2c 296 headerBuf[1] = ((PDU_RR & 0x3) << 6) + ssap;
yihui 0:88960f3eeb2c 297 headerBuf[2] = (buf[2] >> 4) + 1;
yihui 0:88960f3eeb2c 298 if (!link.write(headerBuf, 3)) {
yihui 0:88960f3eeb2c 299 return -2;
yihui 0:88960f3eeb2c 300 }
yihui 0:88960f3eeb2c 301
yihui 0:88960f3eeb2c 302 for (uint8_t i = 0; i < len; i++) {
yihui 0:88960f3eeb2c 303 buf[i] = buf[i + 3];
yihui 0:88960f3eeb2c 304 }
yihui 0:88960f3eeb2c 305
yihui 0:88960f3eeb2c 306 nr++;
yihui 0:88960f3eeb2c 307
yihui 0:88960f3eeb2c 308 return len;
yihui 0:88960f3eeb2c 309 }