Debug Serial para programa resetar o buffer quando houver tamanhos errados na mensagem

Dependencies:   pulga-lorawan-drv PingPong-P2P-ClickButtonToWork-SX1272

serial.cpp

Committer:
MatteusCarr
Date:
2021-04-29
Revision:
15:b27ab44dc2c8
Parent:
14:88373765b9a9

File content as of revision 15:b27ab44dc2c8:

#include "serial.h"

RawSerial pc(P0_28, P0_25);

static char circ_buffer[512];
static int rd_index = 0;
static int wr_index = 0;
static int buf_len = 0;

void SerialRx(void)
{
    char msg[256];
    int msg_incompleta;
    int msg_len;
    int i, j;
    
    /// Execucao do comando nao deve fazer parte da recepcao de dados serial!
    /// Deve existir separacao entre camada fisica, protocolo de baixo nivel
    /// e de alto nivel.

    /// 1) Vamos implementar a parte de recepcao serial com buffer circular.
    /// 2) Vamos implementar rejeicao de ruido.
    /// 3) Interpretamos, executamos ou descartamos comandos.

     /// Recepcao serial
    while(pc.readable())
    {
        /// buffer circular cheio entao sai do loop
        if (buf_len >= sizeof(circ_buffer)) {
            break;
        }
        circ_buffer[wr_index] = pc.getc();
        //pc.printf("gettou o char %c\n", circ_buffer[wr_index]);
        buf_len++;
        wr_index++;
        
        if (wr_index >= sizeof(circ_buffer)) {
            wr_index = 0;
        }
    }

    /// Vamos retirar todos os caracteres invalidos antes do comando
    /// Um comando sempre inicia com '<'
    while(buf_len > 0)
    {
        if (circ_buffer[rd_index] == '<') {
            break; /// rd_index fica com o indice do inicio da mensagem
        }

        buf_len--;
        rd_index++;

        if (rd_index >= sizeof(circ_buffer)) {
            rd_index = 0;
        }
    }

    /// Se ficou vazio, tudo era ruido, limpa todas as variaveis globais e sai
    if (buf_len <= 0)
    {
        //printf("ruido\n");
        rd_index = 0;
        wr_index = 0;
        buf_len = 0;
        pc.attach(&serial_post_to_queue, RawSerial::RxIrq);
        return;
    }

    /// Agora vamos verificar se a mensagem esta completa.
    /// Procura o final (terminada em '>').
    /// Nao altero rd_index!!
    i = 0;
    j = rd_index;
    msg_incompleta = 1;
    int lenght = circ_buffer[j+2];
    //int new_index = rd_index + lenght;
    //pc.printf("index %d and new_index %d\n", rd_index, new_index);
    //pc.printf("msg size: %d \n",lenght);
    while (i < buf_len)
    {
       if (i==lenght+3)
        {
            if(circ_buffer[j] == '>'){
                //pc.printf("msg size = %d \n", i);
                pc.printf("msgOK\n", circ_buffer[j]);
                ///encontrou final de cmd
                msg_incompleta = 0;
                break;
            }else{
                rd_index=0;
                wr_index=0;
                buf_len=0;
                pc.attach(&serial_post_to_queue, RawSerial::RxIrq);
                return;
            }
        }
        j++;
        i++;

        if (j >= sizeof(circ_buffer)) {
            j = 0;
            pc.printf("j>lenght!");
        }
    }

    /// Se a mensagem esta incompleta, deixa para a proxima vez.
    /// Mas aqui tem uma sacada, se o buffer circular estiver cheio,
    /// nunca receberei o final... Entao o codigo nao receberia nunca mais.
    /// Para evitar o travamento permanente, limpa tudo nesse caso.
    /// <------------ Isso causava o erro !!!!!!
    if (msg_incompleta)
    {
        if (buf_len >= sizeof(circ_buffer))
        {
            rd_index = 0;
            wr_index = 0;
            buf_len = 0;
            pc.printf("msg 2 big!");
        }
        pc.attach(&serial_post_to_queue, RawSerial::RxIrq);
        return;
    }

    /// Finalmente copio a msg
    msg_len = 0;
    while(buf_len > 0)
    {
        if (msg_len < sizeof(msg))
        {
            msg[msg_len] = circ_buffer[rd_index];
            msg_len++;
        }
        else
        {
            /// A mensagem esta errada, grande demais.
            msg_len = 0;
            break;
            pc.printf("lenght 2 big!");
        }

       //if (rd_index==new_index+3 && circ_buffer[rd_index] == '>')
       if (buf_len==1 && circ_buffer[rd_index] == '>')
        {
            ///encontrou final de cmd
            pc.printf("msglen = %d \n", msg_len);
            pc.printf("charchar = %c \n", circ_buffer[rd_index]);
            break;
        }

        buf_len--;
        rd_index++;

        if (rd_index >= sizeof(circ_buffer)) {
            rd_index = 0;
            //pc.printf("j>rd_index!");
            
        }
    }

    /// Agora posso limpar todo o buffer circular
    rd_index = 0;
    wr_index = 0;
    buf_len = 0;

    /// A mensagem foi truncada entao sai.
    if (msg_len == 0) {
        pc.attach(&serial_post_to_queue, RawSerial::RxIrq);
        return;
    }

    /// Troco o '>' do final por null
    msg[msg_len - 1] = '\0';
    
    SerialCommandRun(msg);
    
    pc.attach(&serial_post_to_queue, RawSerial::RxIrq);
    return;
}


void PrintDebugMsg(char *msg){
    pc.printf(msg);
}