Patricio Silva / Mbed 2 deprecated c3auto

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
elpatosilva
Date:
Wed Oct 23 14:07:50 2019 +0000
Commit message:
first commit

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Oct 23 14:07:50 2019 +0000
@@ -0,0 +1,374 @@
+#include "mbed.h"
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Conf IO
+DigitalOut led1(LED1); // HeartBeat
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Timers
+Ticker timer100ms;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Comunicación Serial
+
+#define RXBUFFERSIZE 256
+#define TXBUFFERSIZE 256
+#define RXCMDTIME 50000
+#define TXCMDTIME 50000
+// Header
+const uint8_t header[7] = {0x55, 0x4E, 0x45, 0x52, 0x00, 0x00, 0x3A};
+
+Serial pc(USBTX, USBRX); // tx, rx
+
+//////////////////////////////////////////
+// Tipos de dato
+//////////////////////////////////////////
+
+/*
+ * Indices de lectura y escritura del buffer circular
+ * checksum y marcas de tiempo para el envio por puerto serie
+ * empty indica si la cola esta vacia o llena cuando indexR=indexW
+ */
+typedef struct{
+  uint8_t indexR;
+  uint8_t indexW;
+  uint8_t buf[RXBUFFERSIZE];
+  uint8_t chksum;
+  bool empty;
+  uint64_t cmdTime;
+  uint8_t chksumHeader;
+} _txbuffer;
+
+/*
+ * Indices de lectura y escritura del buffer circular
+ * marcas de tiempo, indice de comando y tamaño del comando
+ */
+typedef struct{
+  uint8_t indexR;
+  uint8_t indexW;
+  uint8_t buf[RXBUFFERSIZE];
+  uint64_t cmdTime;
+  uint8_t cmdIndex;
+  uint8_t stage;
+  bool cmd;
+  uint8_t chksum;
+  uint16_t payloadSize;
+} _rxbuffer;
+
+
+///////////////////////////////
+// Variables
+////////////////////////////////
+
+// defino los buffer
+_txbuffer TX;
+_rxbuffer RX;
+
+
+///////////////////////////////
+// Prototipos Serial
+///////////////////////////////
+
+void serialSetup(uint16_t);
+
+
+/* Escribe en el puerto serie los datos del buffer
+ * en cualquier escribo solo de a 1 byte por llamada
+ */
+void serialSubmit();
+
+
+/* Carga al buffer lo recibido por puerto serie
+ */
+void serialReceive();
+
+
+/*  Busca si hay un frame en el buffer que esté correcto y verifica el checksum
+ *  Si hay un header mueve el indice RX.cmdIndex a la posicion donde comienza el comando
+ *  y setea a true el flag RX.cmd. Mueve RX.indexR a esa posición para liberar el espacio
+ *  ocupado por el header. No procesa un nuevo comando hasta que no se ha procesado el anterior
+ *  notificandolo con clearCmd()
+ */
+void getFrame();
+
+
+/*
+ * Escribe en el buffer de salida un frame con un tamaño de comando+payload+checksum = s
+ * retorna true cuando termina de escribir, falso si no hay suficiente espacio (y restablece los indices)
+ */
+bool serialEnqueueHeader(uint16_t);
+
+
+/* Escribe el byte en el buffer de salida, retorna falso si no hay lugar suficiente para hacerlo
+ */
+bool serialEnqueueData(uint8_t);
+
+
+/* Encola el checksum
+ */
+bool serialEnqueueChksum();
+
+/* Borra el comando actual para que se pueda recibir el siguiente
+ */
+void cleanCmd();
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Prototipos de Utilidades
+void heartBeat();
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Funciones
+
+
+/*
+ * Señal de activo, dos parpadeos de 100ms cada dos segundos
+ */
+void heartBeat(){
+  static int count = 0;
+  switch (count++){
+    case 0:
+    case 2:
+        led1 = 0;
+        break;
+    case 1:
+    case 3:
+        led1 = 1;
+        break;
+    case 20:
+        count = 0;
+        break;
+    }
+}
+
+
+
+void serialSetup(uint16_t br){
+    RX.indexR=0;
+    RX.indexW=0;
+    RX.stage=0;
+    RX.cmd=false;
+    TX.indexR=0;
+    TX.indexW=0;
+    TX.empty=true;
+    // Calculo el checksum del header
+    TX.chksumHeader = header[0];
+    for (uint8_t i = 1 ; i < 4 ; i++){
+        TX.chksumHeader ^= header[i];
+    }
+    pc.baud(19200);
+    pc.attach(&serialReceive);
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+// Funciones para el manejo del protocolo
+////////////////////////////////////////////////////////////////////////
+
+// Carga al buffer lo recibido por puerto serie
+void serialReceive(){
+  while (pc.readable() && (uint8_t)(RX.indexW+1) != RX.indexR){
+    RX.buf[RX.indexW++] = pc.getc();;
+  }
+}
+
+
+
+/* Escribe en el puerto serie los datos del buffer
+ * en cualquier escribo solo de a 1 byte por llamada
+ */
+void serialSubmit(){
+    if(TX.indexR!=TX.indexW){
+      pc.putc(TX.buf[TX.indexR++]);
+    }
+  TX.empty = (TX.indexR==TX.indexW);
+}
+
+
+
+/*  Busca si hay un frame en el buffer que esté correcto y verifica el checksum
+ *  Si hay un header mueve el indice RX.cmdIndex a la posicion donde comienza el comando
+ *  y setea a true el flag RX.cmd. Mueve RX.indexR a esa posición para liberar el espacio
+ *  ocupado por el header
+ */
+void getFrame(){
+  uint8_t index;
+  
+  // No logré completar el comando dentro de la ventana de tiempo, considero vacio el buffer de entrada
+  if(RX.stage > 0 && RX.cmdTime+RXCMDTIME < us_ticker_read()){
+    RX.indexR = RX.indexW;
+    RX.stage = 0;
+    return;
+  }
+
+  // mientras hay bytes disponibles en el buffer, proceso desde donde quedé
+  index = RX.indexR+RX.stage;
+  while (index != RX.indexW){
+    switch (RX.stage){
+      case 0:
+          RX.cmdTime = us_ticker_read();
+      case 1:
+      case 2:
+      case 3:{
+          if(RX.buf[index] == header[RX.stage]){
+            RX.stage++;
+            index++;
+          }else{ // No coincide con un header, descarto hasta acá y empiezo de nuevo en el proximo ciclo
+            RX.indexR +=RX.stage;
+            RX.stage=0;
+            return;
+          }
+          break;
+      }
+      case 4:{
+          RX.payloadSize = RX.buf[index];
+          RX.stage++;
+          index++;
+          break;
+      }
+      case 5:{
+          RX.payloadSize += RX.buf[index]*256;
+          RX.stage++;
+          index++;
+          break;
+      }
+      case 6:{
+          if (RX.buf[index] == header[RX.stage]){ // Llego al separador ":", marco la posicion sigiente como cmdIndex
+            RX.stage++;
+            index++;
+          }else{
+            RX.indexR += 3; // Continuo desde la direccion de tamaño del payload
+            RX.stage = 0;
+            return;
+          }
+          break;
+      }
+      case 7:{
+          // empiezo a incrementar index hasta alcanzar el fin de trama (RX.indexR+RX.payloadSize+7)
+          // No avanzo si aún hay un comando por ejecutar
+          if(!RX.cmd && index == (uint8_t)(RX.indexR+RX.payloadSize+6)){ // alcance la posicion del checksum
+            // Calculo checksum y comparo
+            RX.chksum = RX.buf[RX.indexR];
+            for (uint16_t i = 1 ; i < RX.payloadSize+6 ; i++){
+              RX.chksum ^= RX.buf[(uint8_t)(RX.indexR+i)];
+             }
+            if(RX.buf[(uint8_t)(RX.indexR+RX.payloadSize+6)] == RX.chksum){
+              RX.cmd = true;
+              RX.cmdIndex = RX.indexR+7;
+              RX.indexR = RX.cmdIndex;
+              TX.cmdTime = us_ticker_read(); // marca de tiempo para responder el comando
+              RX.stage = 0;
+              return;
+            }else{
+              RX.indexR += 3; // checksum incorrecto, continuo procesando desde la direccion de tamaño del payload
+              RX.stage = 0;
+            }
+            return;
+          }else{
+            index++;
+          }
+          break;
+      }
+      default:{
+          RX.stage = 0;
+          return;
+      }
+    }
+  }
+}
+
+
+ 
+/*
+ * Escribe en el buffer de salida un frame con un tamaño de comando+payload+checksum = s
+ * retorna true cuando termina de escribir, falso si no hay suficiente espacio (y restablece los indices)
+ */
+bool serialEnqueueHeader(uint16_t s){
+  uint8_t index = TX.indexW;
+  // Inicializo chechsum
+  TX.chksum = TX.chksumHeader;
+
+  // escribo la cabecera
+  for (uint8_t i = 0 ; i < 4 ; i++){
+      if(TX.indexR != TX.indexW || TX.empty){
+        TX.buf[TX.indexW++] = header[i];
+      }else{
+        TX.indexW = index;
+        return false;
+      }
+  }
+  // Escribo el tamaño
+  if(TX.indexR != TX.indexW || TX.empty){
+    TX.buf[TX.indexW++] = (uint8_t)s;
+    TX.chksum ^= (uint8_t)s;
+  }else{
+    TX.indexW = index;
+    return false;
+  }
+  if(TX.indexR != TX.indexW || TX.empty){
+    TX.buf[TX.indexW++] = (uint8_t)(s/256);
+    TX.chksum ^= (uint8_t)(s/256);
+  }else{
+    TX.indexW = index;
+    return false;
+  }
+  // escribo el separador
+  if(TX.indexR != TX.indexW || TX.empty){
+    TX.buf[TX.indexW++] = header[6];
+    TX.chksum ^= header[6];
+  }else{
+    TX.indexW = index;
+    return false;
+  }
+  return true;
+}
+
+// Escribe el byte en el buffer de salida, retorna falso si no hay lugar suficiente para hacerlo
+bool serialEnqueueData(uint8_t d){
+  if(TX.indexR != TX.indexW || TX.empty){
+    TX.buf[TX.indexW++] = d;
+    TX.chksum ^= d;
+    return true;
+  }else{
+    TX.indexW--;
+    return false;
+  }
+}
+
+// Encola el checksum
+bool serialEnqueueChksum(){
+  return serialEnqueueData(TX.chksum);
+}
+
+
+/* 
+ * Borra el comando actual para que getFrame pueda recibir el siguiente
+ * Necesario por cada overflow de us_ticker_read()
+ */
+void cleanCmd(){
+    RX.cmd = false;
+    RX.cmdTime = 0;
+    RX.indexR = RX.cmdIndex+RX.payloadSize;
+    TX.cmdTime = 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// MAIN
+
+
+int main(){
+    uint32_t maxUsTicker = us_ticker_read();
+    timer100ms.attach(&heartBeat, 0.1);
+    serialSetup(19200);
+    while(1){
+        // Overflow de us_ticker_read(), reseteo todo lo que utiliza este dato
+        if(maxUsTicker > us_ticker_read()){
+            maxUsTicker = us_ticker_read();
+            cleanCmd();
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Oct 23 14:07:50 2019 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/mbed_official/code/mbed/builds/3a7713b1edbc
\ No newline at end of file