@@ -154,7 +154,13 @@ Display dispArray[ROW] = {
154154 {" " , " Aguardando Registro" , " " , 0 , 0 , 0 , KEEP_AT_ZERO, 0 }
155155 };
156156
157-
157+ /* *
158+ * @var char* VERSION
159+ * @brief Versão do _firmware_.
160+ *
161+ * @note É retornado junto com o serviço ping.
162+ */
163+ const char * VERSION = " 1.0" ;
158164
159165char strReply[80 ];
160166char auxStr[80 ];
@@ -176,6 +182,29 @@ SerialProtocol usbProto;
176182/* ****************************************************************************/
177183/* */
178184/* ****************************************************************************/
185+ /* *
186+ * @brief Copia um trecho de uma string de origem para um buffer de destino,
187+ * ajustando posição inicial e preenchendo com espaços em branco, se necessário.
188+ *
189+ * Esta função garante que o conteúdo copiado caiba exatamente no tamanho
190+ * do display (ou outro destino), ajustando o índice inicial (`start`) caso:
191+ * - A string de origem seja menor ou igual ao destino → começa da posição zero.
192+ * - A string de origem seja maior que o destino, mas o ponto inicial da cópia desejada ultrapasse os limites → recua
193+ * o início para preencher completamente o destino.
194+ *
195+ * Após a cópia, o restante do buffer de destino é preenchido com espaços em branco,
196+ * e o finalizador `'\0'` é adicionado ao fim.
197+ *
198+ * @param[out] dest Buffer de destino (receberá a string copiada).
199+ * @param[in] sizeDest Tamanho do buffer de destino (número de caracteres visíveis no display).
200+ * @param[in] origem String de origem.
201+ * @param[in] sizeOrigem Tamanho da string de origem.
202+ * @param[in] start Posição inicial na string de origem a partir da qual
203+ * a cópia deve começar (pode ser ajustada internamente).
204+ *
205+ * @note Usa `min(sizeDest, sizeOrigem)` para calcular o máximo de caracteres a copiar.
206+ * O destino é sempre terminado em `'\0'`.
207+ */
179208void copiaN (char dest[], int sizeDest, char origem[], int sizeOrigem, int start ) {
180209
181210 // Se a string cabe no display, não pode iniciar impressão para além da posição zero
@@ -204,6 +233,35 @@ void copiaN(char dest[], int sizeDest, char origem[], int sizeOrigem, int start
204233/* ****************************************************************************/
205234/* */
206235/* ****************************************************************************/
236+ /* *
237+ * @brief Atualiza o conteúdo exibido no display LCD linha a linha.
238+ *
239+ * Esta função gerencia a exibição de mensagens no display, considerando:
240+ * - **Tempo mínimo entre atualizações** (usando `millis()` e `DISPLAY_UPDATE_DELAY`).
241+ * - **Mensagens temporárias (TTL)**: quando expiram, voltam para a mensagem padrão.
242+ * - **Rolagem (scroll)**: caso a mensagem seja maior que o número de colunas (`COL`),
243+ * realiza deslocamento progressivo, mantendo o início por alguns ciclos
244+ * (`KEEP_AT_ZERO`) antes de avançar.
245+ *
246+ * O comportamento difere conforme a mensagem ativa:
247+ * - Se `dispArray[i].TTL` expirou → mostra `defaultMessage` com rolagem.
248+ * - Caso contrário → mostra `message` com rolagem.
249+ *
250+ * @param[in] lines Índice da linha a ser atualizada:
251+ * - `-1` → atualiza todas as linhas.
252+ * - `0..ROW-1` → atualiza apenas a linha especificada.
253+ *
254+ * @note
255+ * - Usa `copiaN()` para preencher o buffer de exibição (`toPrint`).
256+ * - Usa o estado da máquina (`usbProto.machState`) para evitar atualizações
257+ * durante recepção de dados.
258+ * - O cursor do LCD é posicionado no início de cada linha (`lcd.setCursor(0,i)`).
259+ *
260+ * ### Regras de rolagem
261+ * - Quando `startPosition == 0`, mantém a mensagem parada por `KEEP_AT_ZERO` ciclos.
262+ * - Depois, incrementa `startPosition` até o limite calculado,
263+ * com espera em `KEEP_AT_LAST` no final.
264+ */
207265void atualizaDisplay (int lines) {
208266 static unsigned long nextUpdate = 0 ;
209267 unsigned long currentTime = millis ();
@@ -261,6 +319,19 @@ void atualizaDisplay(int lines) {
261319/* ****************************************************************************/
262320/* */
263321/* ****************************************************************************/
322+ /* *
323+ * @brief Interpreta a mensagem recebida pela serial USB e atualiza a estrutura global netMessage.
324+ *
325+ * Esta função:
326+ * - Remove os marcadores de acentuação gráfica da string recebida (`usbProto.receivedChars`).
327+ * - Usa `strtok` para separar os campos da mensagem, assumindo o caractere `|` como delimitador.
328+ * - Converte o primeiro campo para um código numérico (`netMessage.code`).
329+ * - Copia o segundo campo como texto da mensagem (`netMessage.message`).
330+ * - Converte o terceiro campo em milissegundos para o tempo de vida (`netMessage.TTL`).
331+ *
332+ * @note A função não recebe parâmetros nem retorna valor.
333+ * Atua diretamente sobre as variáveis globais `usbProto` e `netMessage`.
334+ */
264335void parseMessage () {
265336 char * strtokIndx; // this is used by strtok() as an index
266337 usbProto.removeAccentMarker (usbProto.receivedChars );
@@ -277,17 +348,36 @@ void parseMessage() {
277348/* ****************************************************************************/
278349/* */
279350/* ****************************************************************************/
351+ /* *
352+ * @brief Configuração inicial do sistema Arduino.
353+ *
354+ * Esta função é chamada automaticamente pelo _framework_ Arduino
355+ * logo após o reset ou inicialização da placa.
356+ * Ela é chamada uma única vez.
357+ *
358+ * Inicializações realizadas:
359+ * - Define o pino do buzzer (`BUZZER`) como saída.
360+ * - Inicializa o display LCD (`lcd.init()`).
361+ * - Configura contraste e backlight do display (mas não tem efeito no display que usamos).
362+ * - Desativa _autoscroll_ e cursor piscante.
363+ * - Limpa a tela do display (`lcd.clear()`).
364+ * - Configura a taxa de comunicação serial (`usbProto.setBaudRate(9600)`).
365+ * - Ajusta os tamanhos das mensagens padrão em `dispArray`.
366+ *
367+ * @note Esta função não recebe parâmetros e não retorna valor.
368+ * É executada uma única vez antes de `loop()`.
369+ */
280370void setup () // Incia o display
281371{
282372 pinMode (BUZZER, OUTPUT);
283- lcd.init (); // Serve para iniciar a comunicação com o display já conectado
373+ lcd.init (); // Serve para iniciar a comunicação com o display já conectado
284374 // lcd.backlight(); // Serve para ligar a luz do display
285375 lcd.setContrast (255 );
286376 lcd.setBacklight (255 );
287377 lcd.noAutoscroll ();
288378 lcd.noBlink ();
289- lcd.clear (); // Serve para limpar a tela do display
290- usbProto.setBaudRate (9600 ); // send and receive at 9600 baud
379+ lcd.clear (); // Serve para limpar a tela do display
380+ usbProto.setBaudRate (9600 ); // Envia e recebe a 9600 baud
291381 // Ajusta o tamanho das strings default em dispArray
292382 for (int i = 0 ; i < ROW; i++) {
293383 dispArray[i].messageSize = strlen (dispArray[i].message );
@@ -298,6 +388,44 @@ void setup() //Incia o display
298388/* ****************************************************************************/
299389/* */
300390/* ****************************************************************************/
391+ /* *
392+ * @brief Loop principal do firmware.
393+ *
394+ * O `loop()` executa continuamente o ciclo de atualização do display,
395+ * recepção de mensagens da TV-Box e execução dos comandos recebidos.
396+ *
397+ * O comportamento segue o protocolo definido:
398+ * - **PING (100):** responde com uptime em ms e versão do firmware.
399+ * - **TIME (200):** atualiza linha 0 (sala, data, hora).
400+ * - **LECTURE_NAME (300):** atualiza linha 1 (nome da palestra).
401+ * - **SPEAKER (400):** atualiza linha 2 (nome do professor).
402+ * - **ATTENDEE (500):** atualiza linha 3 (participante) e força atualização imediata.
403+ * - **SUCCESS (600):** feedback sonoro curto (registro aceito).
404+ * - **FAIL (601):** feedback sonoro duplo (registro rejeitado).
405+ *
406+ * ### Estrutura do loop
407+ * 1. Atualiza o display (`atualizaDisplay(-1)`).
408+ * 2. Recebe frame via `usbProto.receiveFrame()`.
409+ * 3. Se um frame válido foi recebido (`machState == RECEIVED`):
410+ * - Chama `parseMessage()` para decodificar.
411+ * - Executa ação conforme `netMessage.code`.
412+ * - Responde sempre `"002|OK"` após comandos de atualização.
413+ * - Atualiza mensagens em `dispArray` (conteúdo, tamanho, TTL, rolagem).
414+ * - Gera sinais sonoros quando uma digital for lida ou usuário/senha do teclado.
415+ * - Reinicia estado da máquina (`machState = START`).
416+ * - Reinicia o ciclo (`goto CONTINUE`) sem esperar o `delay`.
417+ * 4. Se nada foi recebido → aguarda `LOOP_DELAY` antes do próximo ciclo.
418+ *
419+ * @note
420+ * - O `goto CONTINUE` garante responsividade, reiniciando o ciclo imediatamente
421+ * após processar uma mensagem (sem aguardar `LOOP_DELAY`).
422+ * - O uso de `atualizaDisplay(3)` no caso `ATTENDEE` deixa a linha 3 mais
423+ * responsiva a eventos de digitação no teclado.
424+ * - A comunicação usa `usbProto`, responsável por framing com caracteres de escape.
425+ *
426+ * @see atualizaDisplay
427+ * @see parseMessage
428+ */
301429void loop ()
302430{
303431 CONTINUE:
0 commit comments