diff --git a/README.md b/README.md index c9c577c..f1bc184 100644 --- a/README.md +++ b/README.md @@ -216,6 +216,61 @@ Octet 1 `D`: bit 7, 1 si enlevé, 0 sinon `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 **En-tête** : `#` diff --git a/include/Com.h b/include/Com.h index 8165ebe..ac3a688 100644 --- a/include/Com.h +++ b/include/Com.h @@ -13,8 +13,43 @@ * functions for the fixed protocols. */ 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 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 diff --git a/src/Com.cpp b/src/Com.cpp index adafc82..8c45eaa 100644 --- a/src/Com.cpp +++ b/src/Com.cpp @@ -3,9 +3,12 @@ // #include "Com.h" +#include "RFID.h" namespace Com { byte buffer[64]; + TagInfoRecord records[RFID::maxTags] = {}; + /** * Will flush buffer through either HID or Serial depending on build * options. @@ -19,7 +22,7 @@ namespace Com { Serial.write((const char*)buffer); #endif /* Clear the buffer. */ - memset(buffer, 0, 64); + memset(buffer, 0, sizeof(buffer)); } void sendFigUpdate(int8_t event) { @@ -36,4 +39,58 @@ namespace Com { va_end(args); 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; + } }