TX

Dependencies:   mbed BufferedSerial SX1276GenericLib X_NUCLEO_IKS01A2

Files at this revision

API Documentation at this revision

Comitter:
TMRL123
Date:
Wed Jun 05 00:20:00 2019 +0000
Parent:
0:a73914f20498
Commit message:
Telemetry TX

Changed in this revision

BufferedSerial.lib Show annotated file Show diff for this revision Revisions of this file
SDCard_Y.cpp Show annotated file Show diff for this revision Revisions of this file
SDCard_Y.hh Show annotated file Show diff for this revision Revisions of this file
UbxGpsNavSol.cpp Show annotated file Show diff for this revision Revisions of this file
UbxGpsNavSol.hh Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BufferedSerial.lib	Wed Jun 05 00:20:00 2019 +0000
@@ -0,0 +1,1 @@
+https://mbed.org/users/sam_grove/code/BufferedSerial/#a0d37088b405
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDCard_Y.cpp	Wed Jun 05 00:20:00 2019 +0000
@@ -0,0 +1,244 @@
+#include "SDCard_Y.hh"
+
+
+
+#define SD_COMMAND_TIMEOUT 5000
+
+#define R1_IDLE_STATE           (1 << 0)
+#define R1_ERASE_RESET          (1 << 1)
+#define R1_ILLEGAL_COMMAND      (1 << 2)
+#define R1_COM_CRC_ERROR        (1 << 3)
+#define R1_ERASE_SEQUENCE_ERROR (1 << 4)
+#define R1_ADDRESS_ERROR        (1 << 5)
+#define R1_PARAMETER_ERROR      (1 << 6)
+
+
+
+
+SDCard::SDCard(SPI *t_spi, PinName t_cs) : cs(t_cs)
+{
+  spi = t_spi;
+  cs = 1;
+}
+
+SDCard::~SDCard()
+{
+  delete spi;
+}
+
+int SDCard::init(void)
+{
+  spi->frequency(100000);
+  cs = 1;
+
+  for( int i=0 ; i<16 ; i++)
+    spi->write(0xFF);
+
+  if(cmd(0,0) != R1_IDLE_STATE)
+    return -1;
+
+  int r = cmd8();
+
+  if(r == R1_IDLE_STATE){
+    return init_card_v2();      
+  } else if(r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) {
+    return init_card_v1();
+  } else {
+    return -1;
+  }
+  
+  return 0;
+}
+
+int SDCard::init_card_v1()
+{
+  for (int i = 0; i < SD_COMMAND_TIMEOUT; i++)
+    {
+      cmd(55, 0);
+      if(cmd(41, 0) == 0)
+	{
+	  cdv = 512;
+          return 1;
+        }
+    }
+
+  return -1;
+}
+
+
+int SDCard::init_card_v2()
+{
+  for (int i = 0; i < SD_COMMAND_TIMEOUT; i++)
+    {
+      wait_ms(50);
+      cmd58();
+      cmd(55, 0);
+      if (cmd(41, 0x40000000) == 0)
+	{
+	  cmd58();
+          cdv = 1;
+          return 2;
+        }
+    }
+
+  return -1;
+}
+
+
+int SDCard::cmd(int cmd, int arg)
+{
+  cs = 0;
+  spi->write(0x40 | cmd);
+  spi->write(arg >> 24);
+  spi->write(arg >> 16);
+  spi->write(arg >> 8);
+  spi->write(arg >> 0);
+  spi->write(0x95);
+
+  for( int i=0 ; i<SD_COMMAND_TIMEOUT ; i++)
+    {
+      int respuesta = spi->write(0xFF);
+      if( !(respuesta & 0x80) )
+	{
+	  cs = 1;
+	  spi->write(0xFF);
+	  return respuesta;
+	}
+    }
+
+  cs = 1;
+  spi->write(0xFF);
+  return -1;
+
+}
+
+
+int SDCard::cmd8()
+{
+  cs = 0;
+
+  spi->write(0x40 | 8); // CMD8
+  spi->write(0x00);     // reserved
+  spi->write(0x00);     // reserved
+  spi->write(0x01);     // 3.3v
+  spi->write(0xAA);     // check pattern
+  spi->write(0x87);     // crc
+
+  for( int i=0 ; i<SD_COMMAND_TIMEOUT * 1000 ; i++)
+    {
+      char respuesta[5];
+      respuesta[0] = spi->write(0xFF);
+      
+      if( !(respuesta[0] & 0x80))
+	{
+	  for( int j=1; j<5 ; j++)
+	    respuesta[i] = spi->write(0xFF);
+
+	  cs = 1;
+	  spi->write(0xFF);
+	  return respuesta[0];
+	}
+    }
+
+  cs = 1;
+  spi->write(0xFF);
+  return -1;
+  
+}
+
+
+
+int SDCard::cmd58()
+{
+  cs = 0;
+  
+  int arg = 0;
+
+  spi->write(0x40 | 58);
+  spi->write(arg >> 24);
+  spi->write(arg >> 16);
+  spi->write(arg >> 8);
+  spi->write(arg >> 0);
+  spi->write(0x95);
+
+  // wait for the repsonse (response[7] == 0)
+  for(int i = 0; i < SD_COMMAND_TIMEOUT; i++)
+    {
+      int respuesta = spi->write(0xFF);
+
+      if( !(respuesta & 0x80) )
+	{
+	  int ocr = spi->write(0xFF) << 24;
+          ocr |= spi->write(0xFF) << 16;
+          ocr |= spi->write(0xFF) << 8;
+          ocr |= spi->write(0xFF) << 0;
+          cs = 1;
+          spi->write(0xFF);
+          return respuesta;
+        }
+    }
+    cs = 1;
+    spi->write(0xFF);
+    
+    return -1; // timeout
+}
+
+
+
+bool SDCard::read(uint8_t *vect, int post)
+{
+  while( cmd(17,post*512) == -1);
+
+  cs = 0;
+
+  while (spi->write(0xFF) != 0xFE);
+
+  for (uint32_t i = 0; i < 512; i++)
+    *(vect+i) = spi->write(0xFF);
+
+  spi->write(0xFF); // checksum
+  spi->write(0xFF);
+
+  cs = 1;
+  spi->write(0xFF);
+
+  while(cmd(12,512) == -1);
+
+  return 1;
+}
+
+
+
+bool SDCard::write(uint8_t *vect, int post)
+{
+  
+  while( cmd(24,post*512) == -1 );
+  
+  cs = 0;
+  
+  spi->write(0xFE);
+  
+  for (uint32_t i = 0; i < 512; i++)
+    spi->write(*(vect+i));
+
+  spi->write(0xFF);
+  spi->write(0xFF);
+
+  if( (spi->write(0xFF) & 0x1F) != 0x05 )
+    {
+      cs = 1;
+      spi->write(0xFF);
+      return 0;
+    }
+
+  while(spi->write(0xFF) == 0);
+
+  cs = 1;
+  spi->write(0xFF);
+
+  while(cmd(12,512) == -1);
+
+  return 1;
+    
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDCard_Y.hh	Wed Jun 05 00:20:00 2019 +0000
@@ -0,0 +1,30 @@
+#include "mbed.h"
+
+
+class SDCard
+{
+public:
+
+  SDCard(SPI *t_spi, PinName t_cs);
+  ~SDCard();
+
+  int init(void);
+  
+  bool read(uint8_t *vect, int post);  //Lextura de un bloque de 512
+  bool write(uint8_t *vect, int post); //Escritura de un bloque de 512
+
+private:
+
+  SPI *spi;
+  DigitalOut cs;
+  int cdv;
+
+  int init_card_v1();
+  int init_card_v2();
+  
+  int cmd(int cmd, int arg);
+  int cmd8();
+  int cmd58();
+  
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UbxGpsNavSol.cpp	Wed Jun 05 00:20:00 2019 +0000
@@ -0,0 +1,427 @@
+#include "UbxGpsNavSol.hh"
+#include "mbed.h"
+
+UbxGpsNavSol::UbxGpsNavSol(PinName tx, PinName rx, int baud):UARTSerial(tx, rx, baud){
+    this->carriagePosition = 0;
+    // this->setLength(52);
+    this->offsetClassProperties = 8;
+    this->offsetHeaders = 4;
+}
+
+UbxGpsNavSol::~UbxGpsNavSol(){}
+
+bool UbxGpsNavSol::ready(){
+    //unsigned char buffer[60];
+
+    if(this->readable()){
+      for(int k = 0; k < 60; k++)
+        this->buffer[k] = 0;
+
+      this->read(this->buffer, 60);
+    }
+
+    if(this->buffer[0] != UBX_NAV_SOL_HEADER_1 || this->buffer[1] != UBX_NAV_SOL_HEADER_2)
+      return false;
+
+    if(this->buffer[2] != UBX_NAV_SOL_CLASS || this->buffer[3] != UBX_NAV_SOL_ID)
+      return false;
+
+    payload_length = this->buffer[5];
+    payload_length = payload_length << 8;
+    payload_length = this->buffer[4];
+
+    if(payload_length != UBX_NAV_SOL_PAYLOAD_LENGTH)
+      return false;
+
+     if(calculateChecksum(buffer) == false)
+       return false;
+
+    iTOW = this->buffer[9] << 8;
+    iTOW |= this->buffer[8];
+    iTOW <<= 8;
+    iTOW |= this->buffer[7];
+    iTOW <<= 8;
+    iTOW |= this->buffer[6];
+
+    fTOW = this->buffer[13] << 8;
+    fTOW |= this->buffer[12];
+    fTOW <<= 8;
+    fTOW |= this->buffer[11];
+    fTOW <<= 8;
+    fTOW |= this->buffer[10];
+
+    week = this->buffer[15] << 8;
+    week |= this->buffer[14];
+
+    gpsFix = this->buffer[16];
+
+    flags = this->buffer[17];
+
+    ecefX = this->buffer[21] << 8;
+    ecefX |= this->buffer[20];
+    ecefX <<= 8;
+    ecefX |= this->buffer[19];
+    ecefX <<= 8;
+    ecefX |= this->buffer[18];
+
+    ecefY = this->buffer[25] << 8;
+    ecefY |= this->buffer[24];
+    ecefY <<= 8;
+    ecefY |= this->buffer[23];
+    ecefY <<= 8;
+    ecefY |= this->buffer[22];
+
+    ecefZ = this->buffer[29] << 8;
+    ecefZ |= this->buffer[28];
+    ecefZ <<= 8;
+    ecefZ |= this->buffer[27];
+    ecefZ <<= 8;
+    ecefZ |= this->buffer[26];
+
+    pAcc = this->buffer[33] << 8;
+    pAcc |= this->buffer[32];
+    pAcc <<= 8;
+    pAcc |= this->buffer[31];
+    pAcc <<= 8;
+    pAcc |= this->buffer[30];
+
+    ecefVX = this->buffer[37] << 8;
+    ecefVX |= this->buffer[36];
+    ecefVX <<= 8;
+    ecefVX |= this->buffer[35];
+    ecefVX <<= 8;
+    ecefVX |= this->buffer[34];
+
+    ecefVY = this->buffer[41] << 8;
+    ecefVY |= this->buffer[40];
+    ecefVY <<= 8;
+    ecefVY |= this->buffer[39];
+    ecefVY <<= 8;
+    ecefVY |= this->buffer[38];
+
+    ecefVZ = this->buffer[45] << 8;
+    ecefVZ |= this->buffer[44];
+    ecefVZ <<= 8;
+    ecefVZ |= this->buffer[43];
+    ecefVZ <<= 8;
+    ecefVZ |= this->buffer[42];
+
+    sAcc = this->buffer[49] << 8;
+    sAcc |= this->buffer[48];
+    sAcc <<= 8;
+    sAcc |= this->buffer[47];
+    sAcc <<= 8;
+    sAcc |= this->buffer[46];
+
+    pDOP = this->buffer[51] << 8;
+    pDOP |= this->buffer[50];
+
+    reserved1 = this->buffer[52];
+
+    numSV = this->buffer[53];
+
+    reserved2 = this->buffer[57] << 8;
+    reserved2 |= this->buffer[56];
+    reserved2 <<= 8;
+    reserved2 |= this->buffer[55];
+    reserved2 <<= 8;
+    reserved2 |= this->buffer[54];
+
+    return true;
+}
+
+bool UbxGpsNavSol::calculateChecksum(unsigned char *buffer){
+  uint8_t check_a, check_b;
+  check_a = check_b = 0;
+
+  for(int i = 2; i < 58; i++){
+    check_a += buffer[i];
+    check_b += check_a;
+  }
+
+  if(check_a == buffer[59] && check_b == buffer[58])
+    return true;
+
+  else
+    return false;
+}
+
+bool UbxGpsNavSol::enableNAVSOL(){
+  const uint8_t buffer[] = {
+    0xB5, // sync char 1 1
+    0x62, // sync char 2 2
+    0x06, // class 3
+    0x01, // id 4
+    0x02, // length 5
+    0x00, // length 6
+    0x01, // payload 7
+    0x06, // payload 8
+    0x10,//CKA
+    0x39,//CKB
+
+  };
+  if(this->writable()){
+    this->write(buffer, 10);
+    return true;
+  }
+
+  return false;
+}
+
+bool UbxGpsNavSol::restoreDefaults(){
+  const uint8_t packet[] = {
+    0xB5, // sync char 1
+    0x62, // sync char 2
+    0x06, // class
+    0x09, // id
+    0x0D, // length
+    0x00, // length
+    0xFF, // payload
+    0xFF, // payload
+    0x00, // payload
+    0x00, // payload
+    0x00, // payload
+    0x00, // payload
+    0x00, // payload
+    0x00, // payload
+    0xFF, // payload
+    0xFF, // payload
+    0x00, // payload
+    0x00, // payload
+    0x17, // payload
+    0x2F, // CK_A
+    0xAE, // CK_B
+  };
+
+  if(this->writable()){
+    this->write(packet, 21);
+    return true;
+  }
+
+  return false;
+}
+
+void UbxGpsNavSol::disableNmea(){
+  const uint8_t messages[][2] = {
+      {0xF0, 0x0A},
+      {0xF0, 0x09},
+      {0xF0, 0x00},
+      {0xF0, 0x01},
+      {0xF0, 0x0D},
+      {0xF0, 0x06},
+      {0xF0, 0x02},
+      {0xF0, 0x07},
+      {0xF0, 0x03},
+      {0xF0, 0x04},
+      {0xF0, 0x0E},
+      {0xF0, 0x0F},
+      {0xF0, 0x05},
+      {0xF0, 0x08},
+      {0xF1, 0x00},
+      {0xF1, 0x01},
+      {0xF1, 0x03},
+      {0xF1, 0x04},
+      {0xF1, 0x05},
+      {0xF1, 0x06},
+  };
+
+  // CFG-MSG packet buffer
+  uint8_t packet[] = {
+      0xB5, // sync char 1
+      0x62, // sync char 2
+      0x06, // class
+      0x01, // id
+      0x03, // length
+      0x00, // length
+      0x00, // payload (first byte from messages array element)
+      0x00, // payload (second byte from messages array element)
+      0x00, // payload (not changed in the case)
+      0x00, // CK_A
+      0x00, // CK_B
+  };
+
+  uint8_t packetSize = sizeof(packet);
+
+  // Offset to the place where payload starts
+  uint8_t payloadOffset = 6;
+
+  // Iterate over the messages array
+  for (uint8_t i = 0; i < sizeof(messages) / sizeof(*messages); i++)
+  {
+      // Copy two bytes of payload to the packet buffer
+      for (uint8_t j = 0; j < sizeof(*messages); j++)
+      {
+          packet[payloadOffset + j] = messages[i][j];
+      }
+
+      // Set checksum bytes to the null
+      packet[packetSize - 2] = 0x00;
+      packet[packetSize - 1] = 0x00;
+
+      // Calculate checksum over the packet buffer excluding sync (first two) and checksum chars (last two)
+      for (uint8_t j = 0; j < packetSize - 4; j++)
+      {
+          packet[packetSize - 2] += packet[2 + j];
+          packet[packetSize - 1] += packet[packetSize - 2];
+      }
+
+      if(this->writable()){
+        this->write(packet, packetSize);
+      }
+    }
+}
+
+bool UbxGpsNavSol::changeBaudrate(){
+  const uint8_t packet[] = {
+    0xB5, // sync char 1
+    0x62, // sync char 2
+    0x06, // class
+    0x00, // id
+    0x20, // length
+    0x00, // length
+    0x02, // payload - portID
+    0x00, // payload - reserved0
+    0x00, // payload - txReady
+    0x00, // payload - txReady
+    0xD0, // payload - mode
+    0x08, // payload - mode
+    0x00, // payload - mode
+    0x00, // payload - mode
+    0x00, // payload - reserved3
+    0xC2, // payload - reserved3
+    0x01, // payload - reserved3
+    0x00, // payload - reserved3
+    0x07, // payload - inProtoMask
+    0x00, // payload - inProtoMask
+    0x03, // payload - outProtoMask --> activate NMEA???
+    0x00, // payload - outProtoMask
+    0x00, // payload - flags
+    0x00, // payload - flags
+    0x00, // payload - reserved5
+    0x00, // payload - reserved5
+    0xCC, // CK_A
+    0xBA, // CK_B
+  };
+
+  if(this->writable()){
+    this->write(packet, sizeof(packet));
+    return true;
+  }
+
+  return false;
+}
+
+bool UbxGpsNavSol::disableUnnecessaryChannels(){
+  const uint8_t packet[] = {
+    0xB5, // sync char 1
+    0x62, // sync char 2
+    0x06, // class
+    0x3E, // id
+    0x24, // length
+    0x00, // length
+
+    0x00, 0x00, 0x16, 0x04, 0x00, 0x04, 0xFF, 0x00, // payload
+    0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x03, 0x00, // payload
+    0x00, 0x00, 0x00, 0x01, 0x05, 0x00, 0x03, 0x00, // payload
+    0x00, 0x00, 0x00, 0x01, 0x06, 0x08, 0xFF, 0x00, // payload
+    0x00, 0x00, 0x00, 0x01,                         // payload
+
+    0xA4, // CK_A
+    0x25, // CK_B
+  };
+
+  if(this->writable()){
+    this->write(packet, sizeof(packet));
+    return true;
+  }
+
+  return false;
+}
+
+bool UbxGpsNavSol::changeFrequency(){
+  const uint8_t packet[] = {
+        0xB5, // sync char 1
+        0x62, // sync char 2
+        0x06, // class
+        0x08, // id
+        0x06, // length
+        0x00, // length
+        0x64, // payload
+        0x00, // payload
+        0x01, // payload
+        0x00, // payload
+        0x01, // payload
+        0x00, // payload
+        0x7A, // CK_A
+        0x12, // CK_B
+    };
+
+    if(this->writable()){
+      this->write(packet, sizeof(packet));
+      return true;
+    }
+
+    return false;
+}
+
+bool UbxGpsNavSol::disableGNSS(){
+    const uint8_t packet[] = {
+      0xB5, 0x62, 0x06, 0x3E, 0x3C, 0x00,
+      0x00, 0x00, 0x20, 0x07, 0x00, 0x08,
+      0x10, 0x00, 0x01, 0x00, 0x01, 0x01,
+      0x01, 0x01, 0x03, 0x00, 0x00, 0x00,
+      0x01, 0x01, 0x02, 0x04, 0x08, 0x00,
+      0x00, 0x00, 0x01, 0x01, 0x03, 0x08,
+      0x10, 0x00, 0x00, 0x00, 0x01, 0x01,
+      0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
+      0x01, 0x01, 0x05, 0x00, 0x03, 0x00,
+      0x00, 0x00, 0x01, 0x01, 0x06, 0x08,
+      0x0E, 0x00, 0x00, 0x00, 0x01, 0x01,
+      0x2C, 0x4D
+    };
+
+    if(this->writable()){
+      this->write(packet, sizeof(packet));
+      return true;
+    }
+
+    return false;
+}
+
+void UbxGpsNavSol::baud(int baud){
+  this->set_baud(baud);
+}
+
+bool UbxGpsNavSol::saveConfiguration() {
+    const uint8_t packet[] = {
+    0xB5, // sync char 1
+    0x62, // sync char 2
+    0x06, // class
+    0x09, // id
+    0x0D, // length
+    0x00, // length
+    0x00, // payload
+    0x00, // payload
+    0x00, // payload
+    0x00, // payload
+    0xFF, // payload
+    0xFF, // payload
+    0x00, // payload
+    0x00, // payload
+    0x00, // payload
+    0x00, // payload
+    0x00, // payload
+    0x00, // payload
+    0x17, // payload
+    0x31, // CK_A
+    0xBF, // CK_B
+  };
+
+    if(this->writable()){
+      this->write(packet, sizeof(packet));
+      return true;
+    }
+
+    return false;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UbxGpsNavSol.hh	Wed Jun 05 00:20:00 2019 +0000
@@ -0,0 +1,66 @@
+#ifndef UBXGPSNAVSOL_H_
+#define UBXGPSNAVSOL_H_
+
+#include "mbed.h"
+
+#define  UBX_NAV_SOL_HEADER_1          (0xB5)
+#define  UBX_NAV_SOL_HEADER_2          (0x62)
+#define  UBX_NAV_SOL_CLASS                (0x01)
+#define  UBX_NAV_SOL_ID             (0x06)
+#define  UBX_NAV_SOL_PAYLOAD_LENGTH    (52)
+
+class UbxGpsNavSol : public UARTSerial{
+  public:
+    UbxGpsNavSol(PinName tx, PinName rx, int baud);
+    virtual ~UbxGpsNavSol();
+    
+    uint8_t buffer [60];
+    bool ready();
+    void disableNmea();
+    bool enableNAVSOL();
+    bool changeFrequency();
+    bool changeBaudrate();
+    bool disableUnnecessaryChannels();
+    bool disableGNSS();
+    bool restoreDefaults();
+    void baud(int baud);
+    bool saveConfiguration();
+    // void setLength(unsigned char length);
+    // Type         Name           Unit     Description (scaling)
+    unsigned long   iTOW;       // ms       GPS time of week of the navigation epoch. See the description of iTOW for
+                                //          details
+    long            fTOW;       // ns       Fractional part of iTOW (range: +/-500000). The precise GPS time of week in
+                                //          seconds is: (iTOW * 1e-3) + (fTOW * 1e-9)
+    short           week;       // weeks    GPS week number of the navigation epoch
+    unsigned char   gpsFix;     // -        GPSfix Type, range 0..5
+    char            flags;      // -        Fix Status Flags (see graphic below)
+    long            ecefX;      // cm       ECEF X coordinate
+    long            ecefY;      // cm       ECEF Y coordinate
+    long            ecefZ;      // cm       ECEF Z coordinate
+    unsigned long   pAcc;       // cm       3D Position Accuracy Estimate
+    long            ecefVX;     // cm/s     ECEF X velocity
+    long            ecefVY;     // cm/s     ECEF Y velocity
+    long            ecefVZ;     // cm/s     ECEF Z velocity
+    unsigned long   sAcc;       // cm/s     Speed Accuracy Estimate
+    unsigned short  pDOP;       // -        Position DOP (0.01)
+    unsigned char   reserved1;  // -        Reserved
+    unsigned char   numSV;      // -        Number of satellites used in Nav Solution
+    unsigned long   reserved2;  // -        Reserved
+
+  private:
+    bool calculateChecksum(unsigned char *data);
+    // Class properties
+    unsigned char offsetClassProperties;
+    unsigned char offsetHeaders;
+    unsigned char size;
+    unsigned char carriagePosition;
+    unsigned char checksum[2];
+
+    // Headers (common).
+    unsigned char headerClass;
+    unsigned char headerId;
+    unsigned short headerLength;
+    uint16_t payload_length;
+};
+#endif
+
--- a/main.cpp	Thu Apr 18 13:56:50 2019 +0000
+++ b/main.cpp	Wed Jun 05 00:20:00 2019 +0000
@@ -7,16 +7,42 @@
 #include "PinMap.h" 
 #include "sx1276-mbed-hal.h" 
 
+/* Serial communication include */
+#include "BufferedSerial.h"
+
+/* SD card includes */
+#include "SDCard_Y.hh"
+
+/* GPS include */
+#include "UbxGpsNavSol.hh"
+
+
+/* GPS definitions */
+#define GPS_BAUDRATE 115200
+//#define GPS_EN
+
+/* Definition of buzzer time in ms */
+#define BUZZER_TIME 500
+
+/* Definition of Disable enable flag */
+//#define KEY_ENABLE
+
+/* Definition of the SD card */
+#define SPI_FREQUENCY 1000000
+
+/* Definition of the SD card */
+//#define SD_EN
+
 /* LoRa definitions */
 
-/* Set this flag to '1' to display debug messages on the console */
-#define DEBUG_MESSAGE   1
+/* Set this flag to display debug messages on the console */
+#define DEBUG_MESSAGE
 
-/* Set this flag to '1' to use the LoRa modulation or to '0' to use FSK modulation */
-#define USE_MODEM_LORA  1
-#define USE_MODEM_FSK   !USE_MODEM_LORA
+/* Set this flag to '1' to use the LoRa modulation */
+#define USE_MODEM_LORA          1
+#define USE_MODEM_FSK           !USE_MODEM_LORA
 #define RF_FREQUENCY            RF_FREQUENCY_915_0  // Hz
-#define TX_OUTPUT_POWER         14                  // 14 dBm
+#define TX_OUTPUT_POWER         14                  // 20 dBm
 
 #if USE_MODEM_LORA == 1
 
@@ -35,13 +61,12 @@
 #endif 
 
 
-#define RX_TIMEOUT_VALUE    3500    // in ms
-
-//#define BUFFER_SIZE       32        // Define the payload size here
-#define BUFFER_SIZE         512       // Define the payload size here
+#define RX_TIMEOUT_VALUE    0       // In ms
+#define TX_TIMEOUT_VALUE    1000000 // In ms
 
 /* Sensors instances */
 
+
 /* Instantiate the expansion board */
 static XNucleoIKS01A2 *mems_expansion_board = XNucleoIKS01A2::instance(D14, D15, D4, D5);
 
@@ -52,180 +77,422 @@
 static LSM6DSLSensor *acc_gyro = mems_expansion_board->acc_gyro;
 static LSM303AGRAccSensor *accelerometer = mems_expansion_board->accelerometer;
 
-char buffer1[32], buffer2[32]; // buffers to help theprinting of doubles
+typedef struct {
+    /* Header for identification of updated informations */
+    bool header [8];
+    int time; // Time between transmissions
+    int32_t ag[3]; // Acceleration of the accelerometer and gyroscope LSM6DSL 
+    int32_t w[3]; // Angular velocity of LSM6DSL
+    int32_t a[3]; // Acceleration of the accelerometer LSM303AGR
+    int32_t m [3]; // Heading of LSM303AGR
+    float p;  // Pressure of LPS22HB
+    float temperatureLPS22HB; // Temperature from LPS22HB
+    float humidity; // Humidity of HTS221 
+    float temperatureHTS221; // Temperature from HTS221
+    unsigned long timeOfWeek; //GPS time of week
+    long timeOfWeekFracPart; // GPS time of week fractional part
+    unsigned char gpsFix; // GPS fix
+    long ecefx; // GPS X posiition
+    long ecefy; // GPS Y posistion
+    long ecefz; // GPS Z postion
+    unsigned long positionAcc3D; // GPS 3D position accuracy
+    long ecefvx; // GPS X velocity
+    long ecefvy; // GPS Y velocity
+    long ecefvz; // GPS Z velocity
+    unsigned long speedAcc; // GPS speed accuracy
+    unsigned char numbSat; // GPS number of satellites conected
+    bool drogueStatus; // Drogue parachute status provided by Avionics
+    bool mainStatus; //Main parachute status provided by Avionics
+    float pressureBar; // Pressure by COTS Altimeter
+    float temperature; // Temperature by COTS Altimeter
+    bool mainStatusCOTS; // Main parachute status provided by COTS Altimeter
+    bool drogueStatusCOTS; // Drogue status provided by COTS Altimeter
+    int16_t timeStamp; //Timestamp from COTS Altimeter
+    int16_t aglAlt; //AGL Altitude from COTS Altimeter
+    int8_t battery; //Battery voltage reading from COTS Altimeter
+}Data; // Data struct
 
-uint32_t dados[16]; //data vector
+Data data;
+
 
 /* LoRa modem instances and configurations */
 
 static RadioEvents_t RadioEvents; // Calback functions struct
 
-SX1276Generic *Radio; //Defenition of a Radio object
+SX1276Generic *Radio; // Definition of a Radio object
 
-/*Configuration function*/
+/* Configuration function */
 void SystemClock_Config(void);
 
- bool transmited = true;
+bool transmited = true;// Flag to indicate the end of transmission
 
 /* Callback functions prototypes */
+
+// Brief Function to be executed on Radio Tx Done event
 void OnTxDone(void *radio, void *userThisPtr, void *userData);
 
+// Brief Function to be executed on Radio Rx Done event
 void OnRxDone(void *radio, void *userThisPtr, void *userData, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr );
 
+// Brief Function executed on Radio Tx Timeout event
 void OnTxTimeout(void *radio, void *userThisPtr, void *userData);
 
+// Brief Function executed on Radio Rx Timeout event
 void OnRxTimeout(void *radio, void *userThisPtr, void *userData);
 
+// Brief Function executed on Radio Rx Error event
 void OnRxError(void *radio, void *userThisPtr, void *userData);
 
+// Brief Function executed on Radio Fhss Change Channel event
 void OnFhssChangeChannel(void *radio, void *userThisPtr, void *userData, uint8_t channelIndex);
 
-void OnCadDone(void *radio, void *userThisPtr, void *userData);
-
+#ifdef DEBUG_MESSAGE
 /* Serial communication to debug program */
+BufferedSerial *ser;
+#endif
 
-Serial pc(USBTX,USBRX);
+/* Buzzer definition */
+DigitalOut buzzer (PA_0);
+
+#ifdef KEY_ENABLE
+/* Key  digital input port */
+DigitalIn key (PA_8);
+#endif
 
 int main() {
-    /* General Header*/
+    #ifdef KEY_ENABLE
+    while (key == 0);
+    #endif
+    buzzer = 0;
+    /* Power on*/
+    buzzer = 1;
+    wait_ms (BUZZER_TIME);
+    buzzer = 0;
+    wait_ms (BUZZER_TIME);
+    /* Set to zero all parameters of the data struct */
+    data.header [0] = 0;
+    data.header [1] = 0; 
+    data.header [2] = 0; 
+    data.header [3] = 0; 
+    data.header [4] = 0; 
+    data.header [5] = 0; 
+    data.header [6] = 0; 
+    data.header [7] = 0;  
+    data.time = 0; 
+    data.ag[0] = 0;
+    data.ag[1] = 0;
+    data.ag[2] = 0;
+    data.w[0] = 0;
+    data.w[1] = 0;
+    data.w[2] = 0;
+    data.a[0] = 0;
+    data.a[1] = 0;
+    data.a[2] = 0;
+    data.m [0] = 0;
+    data.m [1] = 0;
+    data.m [2] = 0;
+    data.p = 0;  
+    data.temperatureLPS22HB = 0; 
+    data.humidity = 0; 
+    data.temperatureHTS221 = 0; 
+    data.timeOfWeek = 0; 
+    data.timeOfWeekFracPart = 0;
+    data.gpsFix = 0; 
+    data.ecefx = 0; 
+    data.ecefy = 0; 
+    data.ecefz = 0; 
+    data.positionAcc3D = 0; 
+    data.ecefvx = 0; 
+    data.ecefvy = 0; 
+    data.ecefvz = 0; 
+    data.speedAcc = 0; 
+    data.numbSat = 0; 
+    data.drogueStatus = 0; 
+    data.mainStatus = 0; 
+    data.pressureBar = 0; 
+    data.temperature = 0; 
+    data.mainStatusCOTS = 0; 
+    data.drogueStatusCOTS = 0; 
+    data.timeStamp = 0; 
+    data.aglAlt = 0; 
+    data.battery = 0;
+         
+    #ifdef GPS_EN
+    //Serial connections (GPS)(TX,RX,baud)
+    UbxGpsNavSol gps(PA_9, PA_10, GPS_BAUDRATE);
+    #endif
     
-    pc.printf("Telemetry Tx inicial version program\r\n\r\n");
+    SystemClock_Config(); /* Synchronize clock for TX and RX boards */
     
+    /* Serial configuration */
+    #ifdef DEBUG_MESSAGE
+    ser = new BufferedSerial(USBTX, USBRX);
+    ser->baud(115200);
+    ser->format(8);
+    #endif
+        
+    /* General Header*/
+    #ifdef DEBUG_MESSAGE
+    ser->printf ("Telemetry Tx inicial version program\r\n\r\n");
     uint8_t id; //Sensor id parameter for debug purpose
+    #endif
     
     /* Enable all sensors */
-    hum_temp->enable();
-    press_temp->enable();
-    magnetometer->enable();
-    accelerometer->enable();
-    acc_gyro->enable_x();
-    acc_gyro->enable_g();
-      
-    pc.printf("\r\n--- Starting the sensors ---\r\n");
+    if (hum_temp->enable() != 0) {
+        #ifdef DEBUG_MESSAGE
+        ser->printf ("Humidity sensor not enabled\r\n");
+        #endif
+    }
+    if (press_temp->enable() != 0) {
+        #ifdef DEBUG_MESSAGE
+        ser->printf ("Temperature sensor not enabled\r\n");
+        #endif
+    }    
+    if (magnetometer->enable() != 0) {
+        #ifdef DEBUG_MESSAGE
+        ser->printf ("Magnetometer sensor not enabled\r\n");
+        #endif
+    }
+    if (accelerometer->enable() != 0) {
+        #ifdef DEBUG_MESSAGE
+        ser->printf ("Accelerometer1 sensor not enabled\r\n");
+        #endif
+    }
+    if (acc_gyro->enable_x() != 0) {
+        #ifdef DEBUG_MESSAGE
+        ser->printf ("Gyroscope sensor not enabled\r\n");
+        #endif
+    }    
+    if (acc_gyro->enable_g() != 0) {
+        #ifdef DEBUG_MESSAGE
+        ser->printf ("Accelerometer2 sensor not enabled\r\n");
+        #endif
+    }
     
+    #ifdef  DEBUG_MESSAGE
+    ser->printf("\r\n--- Starting the sensors ---\r\n");
+        
     hum_temp->read_id(&id);
-    pc.printf("HTS221  humidity & temperature    = 0x%X\r\n", id);
+    ser->printf("HTS221  humidity & temperature    = 0x%X\r\n", id);
     press_temp->read_id(&id);
-    pc.printf("LPS22HB  pressure & temperature   = 0x%X\r\n", id);
+    ser->printf("LPS22HB  pressure & temperature   = 0x%X\r\n", id);
     magnetometer->read_id(&id);
-    pc.printf("LSM303AGR magnetometer            = 0x%X\r\n", id);
+    ser->printf("LSM303AGR magnetometer            = 0x%X\r\n", id);
     accelerometer->read_id(&id);
-    pc.printf("LSM303AGR accelerometer           = 0x%X\r\n", id);
+    ser->printf("LSM303AGR accelerometer           = 0x%X\r\n", id);
     acc_gyro->read_id(&id);
-    pc.printf("LSM6DSL accelerometer & gyroscope = 0x%X\r\n", id);
-    
-    pc.printf("\r\n");
+    ser->printf("LSM6DSL accelerometer & gyroscope = 0x%X\r\n", id);
+        
+    ser->printf("\r\n");
+    #endif
     
-        /* Radio setup */
-     pc.printf("\r\n--- Starting the modem LoRa ---\r\n");
-    
+    /* Radio setup */
+    #ifdef DEBUG_MESSAGE
+    ser->printf("\r\n--- Starting the modem LoRa ---\r\n");
+    #endif
     Radio = new SX1276Generic(NULL, MURATA_SX1276,
             LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET,
             LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5,
             LORA_ANT_RX, LORA_ANT_TX, LORA_ANT_BOOST, LORA_TCXO);
-    pc.printf("SX1276 Simple transmission aplication\r\n" );
-    pc.printf("Frequency: %.1f\r\n", (double)RF_FREQUENCY/1000000.0);
-    pc.printf("TXPower: %d dBm\r\n",  TX_OUTPUT_POWER);
-    pc.printf("Bandwidth: %d Hz\r\n", LORA_BANDWIDTH);
-    pc.printf("Spreading factor: SF%d\r\n", LORA_SPREADING_FACTOR);
+    #ifdef DEBUG_MESSAGE
+    ser->printf("SX1276 Simple transmission aplication\r\n" );
+    ser->printf("Frequency: %.1f\r\n", (double)RF_FREQUENCY/1000000.0);
+    ser->printf("TXPower: %d dBm\r\n",  TX_OUTPUT_POWER);
+    ser->printf("Bandwidth: %d Hz\r\n", LORA_BANDWIDTH);
+    ser->printf("Spreading factor: SF%d\r\n", LORA_SPREADING_FACTOR);
+    #endif
     
     // Initialize Radio driver
     RadioEvents.TxDone = OnTxDone;
     RadioEvents.RxDone = OnRxDone;
     RadioEvents.RxError = OnRxError;
     RadioEvents.TxTimeout = OnTxTimeout;
-    RadioEvents.RxTimeout = OnRxTimeout;    
-    while (Radio->Init( &RadioEvents ) == false) {
-        pc.printf("Radio could not be detected!\r\n");
-        wait( 1 );
+    RadioEvents.RxTimeout = OnRxTimeout; 
+    
+    for (int i = 0; Radio->Init( &RadioEvents ) != true && i < 40; i++) {
+        #ifdef DEBUG_MESSAGE
+        ser->printf("Radio could not be detected!\r\n");
+        #endif
+        buzzer = 1;
+        wait_ms (BUZZER_TIME);
+        buzzer = 0;
+        wait_ms (BUZZER_TIME);
     }
     
+    // Display the board type
+    #ifdef DEBUG_MESSAGE
     switch(Radio->DetectBoardType()) {
         case SX1276MB1LAS:
-            if (DEBUG_MESSAGE)
-                pc.printf(" > Board Type: SX1276MB1LAS <\r\n");
+            ser->printf(" > Board Type: SX1276MB1LAS <\r\n");
             break;
         case SX1276MB1MAS:
-            if (DEBUG_MESSAGE)
-                pc.printf(" > Board Type: SX1276MB1LAS <\r\n");
+            ser->printf(" > Board Type: SX1276MB1LAS <\r\n");
+            break;
         case MURATA_SX1276:
-            if (DEBUG_MESSAGE)
-                pc.printf(" > Board Type: MURATA_SX1276_STM32L0 <\r\n");
+            ser->printf(" > Board Type: MURATA_SX1276_STM32L0 <\r\n");
             break;
         case RFM95_SX1276:
-            if (DEBUG_MESSAGE)
-                pc.printf(" > HopeRF RFM95xx <\r\n");
+            ser->printf(" > HopeRF RFM95xx <\r\n");
             break;
         default:
-            pc.printf(" > Board Type: unknown <\r\n");
+            ser->printf(" > Board Type: unknown <\r\n");
     }
-    
-    Radio->SetChannel(RF_FREQUENCY );
+    #endif
+    Radio->SetChannel(RF_FREQUENCY ); // Sets the frequency of the communication
     
-    if (LORA_FHSS_ENABLED)
-        pc.printf("             > LORA FHSS Mode <\r\n");
-    if (!LORA_FHSS_ENABLED)
-        pc.printf("             > LORA Mode <\r\n");
-        
-    pc.printf("\r\n");
-        
+    // Debug message of the state of fhss
+    #ifdef DEBUG_MESSAGE
+    if (LORA_FHSS_ENABLED) {
+        ser->printf("             > LORA FHSS Mode <\r\n");
+    }    
+    if (!LORA_FHSS_ENABLED) {
+        ser->printf("             > LORA Mode <\r\n");
+    }
+    #endif
+    // Sets the configuration of the transmission    
     Radio->SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
                          LORA_SPREADING_FACTOR, LORA_CODINGRATE,
                          LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
                          LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 
                          LORA_IQ_INVERSION_ON, 2000 );
     
+    // Sets the configuration of the reception
     Radio->SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
                          LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
                          LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, 0,
                          LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 
                          LORA_IQ_INVERSION_ON, true );
       
-    Radio->Tx(1000000);
+    
+    #ifdef SD_EN
+    SPI spi (PA_7, PA_6, PA_5);
+    spi.frequency (SPI_FREQUENCY);
+    SDCard sdCard (&spi, PB_10);
+    uint8_t sdData[sizeof(data)];
+    int block = 0;
+    #endif
+    
+    
+    Radio->Tx(TX_TIMEOUT_VALUE); // Puts the device in transmission mode for a long period
+    
+    Timer timer; // Timer
+    timer.start(); // Starting timer
     
     while(1) {   
-        float p; //pressure
-        float temperatureHTS221; //temperature from HTS221
-        float humidity; //humidity
-        float temperatureLPS22HB; //temperature from LPS22HB
-        int32_t w[3]; //angular velocity
-        int32_t a[3]; //acceleration of the accelerometer LSM303AGR
-        int32_t ag[3]; //acceleration of the accelerometer and gyroscope LSM6DSL 
-        int32_t m [3]; //heading 
-        
-        press_temp->get_pressure(&p); //get the pressure
-        press_temp->get_temperature(&temperatureLPS22HB); //get temperature from LPS22HB
-        accelerometer->get_x_axes(a);//get the acceleration
-        acc_gyro->get_x_axes(ag);//get the acceleration
-        acc_gyro->get_g_axes(w);//get the angular velocity
-        magnetometer->get_m_axes(m); //get the magnetometer heading
-        hum_temp->get_temperature(&temperatureHTS221); //get temperature from HTS221
-        hum_temp->get_humidity(&humidity); //get humidity
-        
         
-        //sensors data
+        if (press_temp->get_pressure(&data.p) == 0) { // Get the pressure
+            data.header[3] = 1; // LPS22HB updated
+            #ifdef DEBUG_MESSAGE
+            //ser->printf("The pressure data from LPS22HB was read\r\n");
+            #endif
+        } else {
+            data.header[3] = 0; // LPS22HB was not updated
+        }
+        if (press_temp->get_temperature(&data.temperatureLPS22HB) == 0) { // Get temperature from LPS22HB
+            data.header [3] = 1; // LPS22HB updated
+            #ifdef DEBUG_MESSAGE
+            //ser->printf("The temperature data from LPS22HB was read\r\n");
+            #endif
+        } else {
+            data.header[3] = 0; // LPS22HB not updated
+        }
+        if (accelerometer->get_x_axes(data.a) == 0) {// Get the acceleration
+            data.header [2] = 1; // LSM303AGR updated
+            #ifdef DEBUG_MESSAGE
+            //ser->printf("The acceleration data from LSM303AGR was read\r\n");
+            #endif
+        } else {
+            data.header [2] = 0; // LSM303AGR not updated
+        }
+        if (acc_gyro->get_x_axes(data.ag) == 0) {// Get the acceleration
+            data.header [1] = 1; // LSM6DSL updated 
+            #ifdef DEBUG_MESSAGE
+            //ser->printf("The acceleration data from LSM6DSL was read\r\n");
+            #endif
+        } else {
+            data.header [1] = 0; // LSM6DSL not updated
+        }
+        if (acc_gyro->get_g_axes(data.w) == 0) {// Get the angular velocity
+            data.header [1] = 1; // LSM6DSL updated 
+            #ifdef DEBUG_MESSAGE
+            //ser->printf("The angular velocity data from LSM6DSL was read\r\n");
+            #endif
+        } else {
+            data.header [1] = 0; // LSM6DSL not updated    
+        }
+        if (magnetometer->get_m_axes(data.m) == 0) { // Get the magnetometer heading
+            data.header [2] = 1; // LSM303AGR updated
+            #ifdef DEBUG_MESSAGE
+            //ser->printf("The heading data from LSM6DSL was read\r\n");
+            #endif
+        } else {
+            data.header [2] = 0; // LSM303AGR not updated
+        }
+        if (timer.read_ms() >= 10) {
+            if (hum_temp->get_humidity(&data.humidity)) { // Get humidity
+                data.header [4] = 1; // HTS221 updated
+                #ifdef DEBUG_MESSAGE
+                //ser->printf("The humidity data from HTS221 was read\r\n");
+                #endif
+            } else {
+                data.header [4] = 0; // HTS221 not updated
+            }
+            if (hum_temp->get_temperature(&data.temperatureHTS221)== 0) { // Get temperature from HTS221
+                data.header [4] = 1; // HTS221 updated
+                #ifdef DEBUG_MESSAGE
+                //ser->printf("The temperature data from HTS221 was read\r\n");
+                #endif
+            } else {
+                data.header [4] = 0; // HTS221 not updated
+            }
+            #ifdef GPS_EN
+            if (gps.readable()) {
+                if (gps.ready()) {
+                    data.ecefx = gps.ecefX;
+                    data.ecefy = gps.ecefY;
+                    data.ecefz = gps.ecefZ;
+                    data.ecefvx = gps.ecefVX;
+                    data.ecefvy = gps.ecefVY;
+                    data.ecefvz = gps.ecefVZ;
+                    data.timeOfWeek = gps.iTOW;
+                    data.timeOfWeekFracPart = gps.fTOW;
+                    data.positionAcc3D = gps.pAcc;
+                    data.speedAcc = gps.sAcc;
+                    data.numbSat = gps.numSV;
+                    data.gpsFix = gps.gpsFix;
+                    data.header [5] = 1; // GPS updated
+                    #ifdef DEBUG_MESSAGE
+                    ser->printf("The GPS data was read\r\n");
+                    #endif  
+                } else {
+                    data.header [5] = 1; // GPS not updated
+                }
+            }
+            #endif
+            timer.reset();
+        }    
+        /* Check internal comunication for avionicas data */  
+        // Implement this part here
+        //...
+        //end
+         
+        #ifdef SD_EN    
+        // Saving the data on SD Card
+        memcpy (sdData, &data, sizeof(data));
+        while(sdCard.write(&sdData[0],block) == 0);
+        block ++;
+        while (sdCard.write (&sdData[64],block) == 0);
+        block++;
+        while (sdCard.write(&sdData[128],block) == 0);
+        block++;
+        #endif
         
-        dados[0] = a[0];
-        dados[1] = a[1];
-        dados[2] = a[2];
-        dados[3] = ag[0];
-        dados[4] = ag[1];
-        dados[5] = ag[2];
-        dados[6] = w[0];
-        dados[7] = w[1];
-        dados[8] = w[2];
-        dados[9] = m[0];
-        dados[10] = m[1];
-        dados[11] = m[2];
-        dados[12] = humidity;
-        dados[13] = temperatureHTS221;
-        dados[14] = temperatureLPS22HB;
-        dados[15] = p;
-        
+        // Only sends a new packet when the device already have transmited the previous one 
         if (transmited==true) {
             transmited = false;
             wait_ms(10);
-            Radio->Send( dados, sizeof(dados) );
+            Radio->Send( &data, sizeof(data) );
+            ser->printf("%d\r\n", sizeof(data));
         }
     }
 }
@@ -274,77 +541,56 @@
 #endif
 }
 
-/* Helper function for printing floats & doubles */
-static char *print_double(char* str, double v, int decimalDigits=2)
-{
-  int i = 1;
-  int intPart, fractPart;
-  int len;
-  char *ptr;
 
-  /* prepare decimal digits multiplicator */
-  for (;decimalDigits!=0; i*=10, decimalDigits--);
-
-  /* calculate integer & fractinal parts */
-  intPart = (int)v;
-  fractPart = (int)((v-(double)(int)v)*i);
-
-  /* fill in integer part */
-  sprintf(str, "%i.", intPart);
-
-  /* prepare fill in of fractional part */
-  len = strlen(str);
-  ptr = &str[len];
-
-  /* fill in leading fractional zeros */
-  for (i/=10;i>1; i/=10, ptr++) {
-    if (fractPart >= i) {
-      break;
-    }
-    *ptr = '0';
-  }
-
-  /* fill in (rest of) fractional part */
-  sprintf(ptr, "%i", fractPart);
-
-  return str;
-}
 
 void OnTxDone(void *radio, void *userThisPtr, void *userData)
 {   
     Radio->Sleep( );
     transmited = true;
-    if (DEBUG_MESSAGE) {
-        pc.printf("> OnTxDone\r\n");
-        pc.printf("I transmited %6ld, %6ld, %6ld, %6ld, %6ld, %6ld, %6ld, %6ld, %6ld\r\n", dados[0], dados[1], dados[2], dados[3], dados[4], dados[5], dados[6], dados[7], dados[8]);
-        pc.printf("and %6ld, %6ld, %6ld, %s, %7s, %7s %s\r\n", dados[9], dados[10], dados[11], print_double(buffer2, dados[12]), print_double(buffer1, dados[13]), print_double(buffer1, dados[14]), print_double(buffer2, dados[15]));
-    }    
+    #ifdef DEBUG_MESSAGE
+    ser->printf("> OnTxDone\r\n");
+    ser->printf("I transmited %d mg, %d mg, %d mg, %d mg, %d mg, %d mg, %d mdps, %d mdps, %d mdps\r\n", data.a[0], data.a[1], data.a[2], data.ag[0], data.ag[1], data.ag[2], data.w[0], data.w[1], data.w[2]);
+    ser->printf("and %d mG, %d mG, %d mG, %g %%, %g C, %g C, %g mBar\r\n", data.m[0], data.m[1], data.m[2], data.humidity, data.temperatureHTS221, data.temperatureLPS22HB, data.p);
+    ser->printf("and time - %d ms, time of the week - %d ms, time of week frac part - %d ns\r\n",data.time, data.timeOfWeek, data.timeOfWeekFracPart);
+    ser->printf("and GPS fix %c, ECEFX %d cm, ECEFY %d cm, ECEFZ %d cm\r\n", data.gpsFix, data.ecefx, data.ecefy, data.ecefz);
+    ser->printf("and 3D Position accuracy %d cm, ECEFVX %d cm/s, ECEFVY %d cm/s, ECEFVZ %d cm/s, Speed accuracy %d cm/s\r\n", data.positionAcc3D, data.ecefvx, data.ecefvy, data.ecefvz, data.speedAcc);    
+    ser->printf("and Number of satelites %x, Drogue Status %x, Main status %x, BMP280 %f bar, temperature %f C\r\n", data.numbSat, data.drogueStatus, data.mainStatus, data.pressureBar, data.temperature);
+    ser->printf("Main Status COTS %x, Drogue Status COTS %x, Time Stamp %d s, AGL altitude %d m, Battery voltage %d V\r\n",data.mainStatusCOTS, data.drogueStatusCOTS, data.timeStamp, data.aglAlt, data.battery);
+    ser->printf("Header: %d, %d, %d, %d, %d, %d, %d, %d\r\n",data.header[0], data.header[1], data.header[2], data.header[3], data.header[4], data.header[5], data.header[6], data.header[7]);
+    uint8_t payload[sizeof(data)];
+    memcpy(payload, &data, sizeof(data));
+    ser->printf("%x\r\n", *payload);
+    #endif
 }
 
 void OnRxDone(void *radio, void *userThisPtr, void *userData, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
 {
     Radio->Sleep( );
-    if (DEBUG_MESSAGE)
-        pc.printf("> OnRxDone: RssiValue=%d dBm, SnrValue=%d\r\n", rssi, snr);
+    #ifdef DEBUG_MESSAGE
+    ser->printf("> OnRxDone: RssiValue=%d dBm, SnrValue=%d\r\n", rssi, snr);
+    #endif
 }
 
 void OnTxTimeout(void *radio, void *userThisPtr, void *userData)
 {
     Radio->Sleep( );
-    if(DEBUG_MESSAGE)
-        pc.printf("> OnTxTimeout\r\n");
+    #ifdef DEBUG_MESSAGE
+    ser->printf("> OnTxTimeout\r\n");
+    #endif
 }
 
 void OnRxTimeout(void *radio, void *userThisPtr, void *userData)
 {
     Radio->Sleep( );
-    if (DEBUG_MESSAGE)
-        pc.printf("> OnRxTimeout\r\n");
+    #ifdef DEBUG_MESSAGE
+    ser->printf("> OnRxTimeout\r\n");
+    #endif
 }
 
 void OnRxError(void *radio, void *userThisPtr, void *userData)
 {
     Radio->Sleep( );
-    if (DEBUG_MESSAGE)
-        pc.printf("> OnRxError\r\n");
+    #ifdef DEBUG_MESSAGE
+    ser->printf("> OnRxError\r\n");
+    #endif
 }