1
0
Fork 0

Com: Implement tag programming

Define the protocol allowing the software to track tags
and program them, in the README.

The data structure is shared between a programming command and an
information message, so create a new struct for it and an array
to keep track of it and expose to the rest of the program.
The goal is to keep the protocol core and message construction
entirely inside Com, so this intermediary buffer allows exposing
it outside while hiding the protocol details.

This means that we are starting to receive data from the software,
so implement generic functions to check and receive data as well
as receiveMessage() which parses the message and handles them.
This commit is contained in:
Teo-CD 2024-01-06 00:32:19 +00:00
parent 324cf50653
commit b5b5268b79
3 changed files with 148 additions and 1 deletions

View file

@ -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** : `#`

View file

@ -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

View file

@ -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;
}
}