1
0
Fork 0

Compare commits

..

No commits in common. "5618f52a0e444866ac6617b06333fe0a8b72fae3" and "a438cb13d4f9f53fc9dc68a89f69968fba0b7290" have entirely different histories.

6 changed files with 11 additions and 257 deletions

View file

@ -216,61 +216,6 @@ Octet 1
`D`: bit 7, 1 si enlevé, 0 sinon `D`: bit 7, 1 si enlevé, 0 sinon
`C`: bit 6, 1 si personnage, 0 si année `C`: bit 6, 1 si personnage, 0 si année
### Requête d'information pour la programmation de tag
**En-tête** : `?`
**Longueur** : 0 octets
**Description** : Message **vide** envoyé du logiciel vers l'objet pour
demander les informations complètes qui permettront de programmer les tags.
Il attend une réponse de l'objet, décrit dans la catégorie suivante.
### Réponse d'information pour la programmation de tag
**En-tête** : `!`
**Longueur** : 1 + 5*n octets, n le nombre de figurines présentes (>=0)
**Description** : Message de réponse à la requête d'information pour la programmation
des tags.
Le premier octet est fixé et indique le nombre de figurines présentes, et donc
le nombre d'entrées dans le message.
Ensuite, chaque entrée est constituée de l'ID actuel, sur un octet, puis de l'UID
du tag, sur quatre octets.
C'est l'UID qui est utilisé dans la demande de programmation pour sélectionner le tag.
#### Schéma
```
│Optional, N records
┌─┼────┬──┬────┬──┐
│N│UID1│I1│UID2│I2│...
└─┴────┴──┴────┴──┘
0 1 5 6 10 11 - Octets
```
`N` : Nombre de tags présents, 1 octet
`UIDn` : UID du tag n, 4 octets
`In` : ID du tag n, 1 octet
### Message de programmation de tag
**En-tête** : `=`
**Longueur** : 5 octets
**Description** : Message envoyé par le logiciel à l'objet, permet de changer
(programmer) l'ID stocké dans un tag.
Le contenu est formaté de façon similaire à la réponse d'information :
l'UID du tag à programmer, sur quatre octets, puis le nouvel identifiant du tag,
sur un octet.
On ne programme qu'un tag à la fois.
#### Schéma
```
┌─────┬────┐
│ UID │ ID │
└─────┴────┘
0 4 5 - Octets
```
`UID` : UID du tag à programmer, 4 octets
`ID` : Nouvel ID à programmer, 1 octet
### Message informatif ### Message informatif
**En-tête** : `#` **En-tête** : `#`

View file

@ -13,43 +13,8 @@
* functions for the fixed protocols. * functions for the fixed protocols.
*/ */
namespace Com { namespace Com {
enum ReceivedMessage {
NO_MESSAGE,
TAG_INFO_REQUEST,
TAG_PROGRAMMING,
INVALID_MESSAGE,
};
/**
* Struct used for tag info responses and tag programming.
* Would be 8 bytes if not packed due to padding.
*/
struct __attribute__((packed)) TagInfoRecord {
uint32_t uid;
uint8_t figId;
};
void sendFigUpdate(int8_t event); void sendFigUpdate(int8_t event);
void sendComment(const char message[62], ...); void sendComment(const char message[62], ...);
/**
* Send the response to the tag info request.
* The TagInfoRecord buffer needs to be properly filled through getTagRecords().
* @param tagCount The amount of tags that are present in the response.
*/
void sendTagInfo(uint8_t tagCount);
/**
* @return Pointer to a buffer of TagInfoRecords
*/
TagInfoRecord* getTagRecords();
/**
* Check for any incoming message and handle it if needed, returning the
* kind of message received if known, no message if there was nothing to read
* and invalid message otherwise.
* @return Kind of message received.
*/
ReceivedMessage receiveMessage();
} }
#endif //JIN_BARBAPAPA_COM_H #endif //JIN_BARBAPAPA_COM_H

View file

@ -15,7 +15,6 @@
#include <MFRC522DriverPinSimple.h> #include <MFRC522DriverPinSimple.h>
#include <MFRC522DriverSPI.h> #include <MFRC522DriverSPI.h>
#include "Com.h"
#include "IDs.h" #include "IDs.h"
#include "Pinout.h" #include "Pinout.h"
@ -31,8 +30,6 @@ struct uidNode {
class RFID { class RFID {
public: public:
static constexpr int maxTags = 2;
/*** /***
* Use the main SPI port and NFC chip select by default, but allow choosing * Use the main SPI port and NFC chip select by default, but allow choosing
* an alternate chip select and/or SPI bus if needed to allow multiple * an alternate chip select and/or SPI bus if needed to allow multiple
@ -51,26 +48,11 @@ public:
* @return 0 if no change, ID if new tag detected, ID & sign bit if the tag left. * @return 0 if no change, ID if new tag detected, ID & sign bit if the tag left.
*/ */
int8_t checkTags(); int8_t checkTags();
/***
* Populate an already allocated array of sufficient size to fit
* maxTags number of TagInfoRecords.
* @param tagData Pointer to an array of size maxTags*sizeof(Com::TagInfoRecord)
* @return Number of tags actually put in the array.
*/
uint8_t gatherTagInfo(Com::TagInfoRecord* tagData);
/***
* Change the ID stored in a tag so that it matches tagToProgram.
* @param tagToProgram Pointer to an existing struct with the data to program.
* @return True if the programming succeeded.
*/
bool programTag(Com::TagInfoRecord* tagToProgram);
private: private:
static const byte tagIdBlock = 0x11;
/* Used for "encrypted" communication with the tags. */ /* Used for "encrypted" communication with the tags. */
static MFRC522Constants::MIFARE_Key defaultKey; static MFRC522Constants::MIFARE_Key defaultKey;
static int currentActiveTags; static constexpr int maxTags = 2;
int currentActiveTags = 0;
/* /*
* The linked list tracking active tags. * The linked list tracking active tags.
@ -108,22 +90,11 @@ private:
/** /**
* Read block at blockADdr from tagUid and return if the read succeeded or not. * Read block at blockADdr from tagUid and return if the read succeeded or not.
* The read block will be in comData. * The read block will be in comData.
* The tag needs to be already woken up.
* @param tagUid Uid of the tag to be read. * @param tagUid Uid of the tag to be read.
* @param blockAddr Address of the block to be read. * @param blockAddr Address of the block to be read.
* @return True if read succeeded, false otherwise. * @return True if read succeeded, false otherwise.
*/ */
bool readBlock(MFRC522Constants::Uid &tagUid, byte blockAddr); bool readBlock(MFRC522Constants::Uid &tagUid, byte blockAddr);
/**
* Write data to tagUid at blockAddr and return if the write succeeded or not.
* The tag needs to be already woken up.
* @param tagUid Uid of the tag to write to.
* @param blockAddr Address of the block to write to.
* @param data Byte to write.
* @return True if write succeeded, false otherwise.
*/
bool writeBlock(MFRC522Constants::Uid &tagUid, byte blockAddr, uint8_t data);
}; };
#endif //JIN_BARBAPAPA_RFID_H #endif //JIN_BARBAPAPA_RFID_H

View file

@ -3,12 +3,9 @@
// //
#include "Com.h" #include "Com.h"
#include "RFID.h"
namespace Com { namespace Com {
byte buffer[64]; byte buffer[64];
TagInfoRecord records[RFID::maxTags] = {};
/** /**
* Will flush buffer through either HID or Serial depending on build * Will flush buffer through either HID or Serial depending on build
* options. * options.
@ -22,7 +19,7 @@ namespace Com {
Serial.write((const char*)buffer); Serial.write((const char*)buffer);
#endif #endif
/* Clear the buffer. */ /* Clear the buffer. */
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, 64);
} }
void sendFigUpdate(int8_t event) { void sendFigUpdate(int8_t event) {
@ -39,58 +36,4 @@ namespace Com {
va_end(args); va_end(args);
flushBuffer(); flushBuffer();
} }
void sendTagInfo(uint8_t tagCount) {
buffer[0] = '!';
buffer[1] = tagCount;
memcpy(buffer + 2, records, sizeof(TagInfoRecord)*tagCount);
flushBuffer();
}
TagInfoRecord* getTagRecords() {
return records;
}
inline bool dataAvailable() {
#ifdef USB_RAWHID
return usb_rawhid_available();
#else
/* Serial is used for debug, do not care about message length. */
return Serial.available();
#endif
}
inline void receiveData() {
memset(buffer, 0, sizeof(buffer));
#ifdef USB_RAWHID
/* We know we have data, don't need to set a timeout. */
usb_rawhid_recv(buffer, 0);
#else
/* Could lead to incomplete messages, but should be OK on Teensy. */
Serial.readBytes(buffer, Serial.available());
#endif
}
ReceivedMessage receiveMessage() {
if (!dataAvailable())
return NO_MESSAGE;
receiveData();
ReceivedMessage messageType;
switch (buffer[0]) {
case '?':
messageType = TAG_INFO_REQUEST;
break;
case '=':
messageType = TAG_PROGRAMMING;
/* Make the record available to the rest of the code. */
memset(records, 0, sizeof(records));
memcpy(records, buffer + 1, sizeof(TagInfoRecord));
break;
default:
messageType = INVALID_MESSAGE;
Serial.printf("Invalid header received : %c\n", buffer[0]);
}
return messageType;
}
} }

View file

@ -4,11 +4,7 @@
#include "RFID.h" #include "RFID.h"
static_assert(RFID::maxTags * sizeof(Com::TagInfoRecord) <= 62,
"RFID::maxTags too high, protocol cannot support it.\n");
MFRC522Constants::MIFARE_Key RFID::defaultKey = {0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; MFRC522Constants::MIFARE_Key RFID::defaultKey = {0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
int RFID::currentActiveTags = 0;
void RFID::init() { void RFID::init() {
// Create and set up a static linked list to manage active tags. // Create and set up a static linked list to manage active tags.
@ -62,47 +58,15 @@ int8_t RFID::checkTags() {
return 0; return 0;
} }
// If the read fails, we cannot use this tag anyway so remove it from the list. // If the read fails, we cannot use this tag anyway so remove it from the list.
if (!readBlock(newTag->uid, tagIdBlock) ) { if (!readBlock(newTag->uid, 0x11) ) {
removeActiveTag(newTag, nullptr); removeActiveTag(newTag, nullptr);
return 0; return 0;
} }
// Don' t check the ID, otherwise we cannot program the tag. // TODO: ID check ?
newTag->tag_ID = comData[0]; newTag->tag_ID = comData[0];
return newTag->tag_ID; return newTag->tag_ID;
} }
uint8_t RFID::gatherTagInfo(Com::TagInfoRecord *tagData) {
int tagCount = 0;
for (uidNode* node = activeTags; node; node = node->next) {
// The protocol does not support UIDs other than 4 bytes, so assume it
// is the case here directly.
tagData[tagCount].uid = *(uint32_t*)(node->uid.uidByte);
tagData[tagCount].figId = node->tag_ID;
tagCount++;
}
return tagCount;
}
bool RFID::programTag(Com::TagInfoRecord *tagToProgram) {
byte comSize = sizeof(comData);
mfrc.uid.size = 4;
*(uint32_t*)(mfrc.uid.uidByte) = tagToProgram->uid;
mfrc.PICC_WakeupA(comData, &comSize);
if (mfrc.PICC_Select(&mfrc.uid, mfrc.uid.size) != MFRC522Constants::STATUS_OK) {
Serial.println("Failed to wakeup for programming. Is tag still there ?\n");
mfrc.PICC_HaltA();
return false;
}
if (!writeBlock(mfrc.uid, tagIdBlock, tagToProgram->figId)) {
Serial.println("Failed to program tag.");
return false;
}
return true;
}
uidNode* RFID::addActiveTag(const MFRC522Constants::Uid &newTag) { uidNode* RFID::addActiveTag(const MFRC522Constants::Uid &newTag) {
if (!nextFreeTagSlot) { if (!nextFreeTagSlot) {
return nullptr; return nullptr;
@ -137,40 +101,16 @@ bool RFID::readBlock(MFRC522Constants::Uid &uidToRead, byte blockAddr) {
if (mfrc.PCD_Authenticate( if (mfrc.PCD_Authenticate(
MFRC522Constants::PICC_Command::PICC_CMD_MF_AUTH_KEY_A, MFRC522Constants::PICC_Command::PICC_CMD_MF_AUTH_KEY_A,
blockAddr, (&defaultKey),&uidToRead)!= MFRC522Constants::STATUS_OK) { blockAddr, (&defaultKey),&uidToRead)!= MFRC522Constants::STATUS_OK) {
Serial.println("readBlock: Failed to authenticate"); Serial.println("Failed to authenticate");
mfrc.PICC_HaltA();
return false; return false;
} } else {
byte size = sizeof(comData); byte size = sizeof(comData);
MFRC522::StatusCode status = mfrc.MIFARE_Read(blockAddr, comData, &size); mfrc.MIFARE_Read(blockAddr, comData, &size);
// Serial.printf("Read block : 0x%lX\n", *(uint32_t *)comData); // Serial.printf("Read block : 0x%lX\n", *(uint32_t *)comData);
}
// Needed otherwise no new communications can happen. // Needed otherwise no new communications can happen.
mfrc.PCD_StopCrypto1(); mfrc.PCD_StopCrypto1();
// No need to keep the tag active. // No need to keep the tag active.
mfrc.PICC_HaltA(); mfrc.PICC_HaltA();
return status == MFRC522Constants::STATUS_OK; return true;
}
bool RFID::writeBlock(MFRC522Constants::Uid &uidToRead, byte blockAddr, uint8_t data) {
if (mfrc.PCD_Authenticate(
MFRC522Constants::PICC_Command::PICC_CMD_MF_AUTH_KEY_A,
blockAddr, (&defaultKey),&uidToRead)!= MFRC522Constants::STATUS_OK) {
Serial.println("writeBlock: Failed to authenticate");
mfrc.PICC_HaltA();
return false;
}
byte size = sizeof(comData);
for (byte& bufferByte: comData)
bufferByte = 0;
*comData = data;
MFRC522::StatusCode status = mfrc.MIFARE_Write(blockAddr, comData, size);
// Needed otherwise no new communications can happen.
mfrc.PCD_StopCrypto1();
// No need to keep the tag active.
mfrc.PICC_HaltA();
return status == MFRC522Constants::STATUS_OK;
} }

View file

@ -77,16 +77,6 @@ __attribute__((noreturn)) int main() {
} }
} }
Com::ReceivedMessage message = Com::receiveMessage();
if (message == Com::TAG_INFO_REQUEST) {
uint8_t tagCount = rfid.gatherTagInfo(Com::getTagRecords());
Com::sendTagInfo(tagCount);
} else if (message == Com::TAG_PROGRAMMING) {
if (!rfid.programTag(Com::getTagRecords())) {
Com::sendComment("Tag programming failed.");
}
}
/* TODO: Drop delay, WFE+timer interrupt(s) ? */ /* TODO: Drop delay, WFE+timer interrupt(s) ? */
delay(25); delay(25);
} }