Space / Mbed 2 deprecated DORAv4

Dependencies:   mbed

main.cpp

Committer:
paologiorgio
Date:
2022-06-21
Revision:
3:b58e8c4438cd
Parent:
2:fcdd048a4a9e

File content as of revision 3:b58e8c4438cd:

#include "mbed.h"
#include <math.h>
#include <string.h>
#include <stdlib.h>

/*
TO-DO: i dati arrivano in DigitalIn e DigitalOut, anziché essere della classe Serial.
Al fine di poter immagazzinare i dati, associo a determinati livelli logici (1/0) dei caratteri,
riempio il buffer e ritrasmetto con i caratteri riconvertiti

comando per azionamento periferiche: SPARE

modifica sulla ricezione: devo ricevere solo se un certo comando è stato selezionato
*/

// ************* INFO *******************

//  ------                  ------------
// | MIMA | ---- DORA ---- | SPACE/CRAFT |
//  ------                  ------------

// testato con 26LS31 e 26LS32 + Arduino 

// ************ DEFINE ******************
// definisce dimensione pacchetto inviato da pc
// telecommand: 15 bit + 1 di controllo
#define PACKETSIZE 20           // lunghezza massima della stringa trasmissibile prima di interrupt
#define PACKET 15               // 15 bit, 1 di parità di controllo
#define PACKET_CHECKED 16       // COMMAND IDENTIFIER + TAG + PAYLOAD + PARITY CHECK
#define TELEMETRY_SIZE 16
#define PACKETDIM 13
#define IDENTIFIER 5
#define TAG 2
#define PAYLOAD 8
#define CMD_NUM 32
#define TLM_OPTION_1 912        // 57 * 16
#define TLM_OPTION_2 90608      // 5663 * 16
#define tb 7                    // bit sampling period
#define word 16
#define CHANNEL 2800
#define TLM_NUM 57


// ************ CN7+USB ******************
Serial SC(USBTX, USBRX);                // A4 TX, A6 RX - DATA OUT, DATA IN

// ************** CN10 *******************
Serial MIMA(PC_4, PC_5);
Serial MAX31865(PA_9, PC_0); //(?)
Serial ARDUINO(PB_6, PC_10);

// ************** TIMER *****************
Timer t;
float TIMEOUT = 10;
float tTimeStart;
float tTimeStop;
float tTimeRead;

// ******* L16 Actuatonix - Relay ********
PwmOut M1 (PA_6);                       // D12
PwmOut M2 (PA_8);                       // D7
DigitalOut Relay5V (PA_7);              // D11
DigitalOut Relay12V (PB_4);             // D5
DigitalOut Relay24V (PB_5);             // D4
DigitalOut Relay15_15_5V (PB_10);       // D6 | +15, -15, -5
float offset = 0.0f;

// **************** VARS *****************
volatile int nIndex;                        // indice per clear del buffer
char getPacket[PACKETSIZE];                 // buffer - pacchetto inviato di dimensione max PACKETSIZE
char PacketChecked[PACKET_CHECKED];         // lato Space/Craft
char TLM[TELEMETRY_SIZE];                   // telemetry format
char TLM_HSK[TLM_OPTION_1];                 // lato MIMA: CMD05 -> option 1 (ALL HSKP)
char TLM_HSK_SD[TLM_OPTION_2];              // lato MIMA: CMD05 -> option 2 (HSKP+SD)

volatile int LEN;                           // numero di bit da ricevere per ricezione corretta 
volatile int commandId;                     // CMDXX per telecomando
volatile int payloadDec;                    // trasformo il payload in decimale per comandi spare
volatile int sizeBuffer;                    // indice del buffer di ricezione
volatile unsigned char data;                // in arrivo da MIMA per telemetria
volatile int indexTemp;                     // indice del buffer di caratteri in arrivo da arduino/max31865
volatile char ch;

int base = 2;                               // base per l'esponenziale (conversione binary to decimal)
int CMD[CMD_NUM];                           // CMD in decimale
int TLM_ID[TLM_NUM];                        // TLM in decimale

volatile int tlmode_option_1;               // TLMODE: 57 words
volatile int tlmode_option_2;               // TLMODE: 5663 words (57 + 5606 scientific data word)
volatile int interferogram_option_1;        // TLMODE: 57 words
volatile int interferogram_option_2;        // TLMODE: 5663 words (57 + 5606 scientific data word)

volatile int ch1_errorDetected;
int ch1_intChecksum[word];                  
char ch1_checksumWord[word];                // checksum sul pacchetto elaborato
char ch1_checksumReceived[word];            // checksum ricevuto

char CH1_to_string[20];                     // *temperatura canale 1
char CH2_to_string[20];                     // *temperatura canale 2
char tempCH1[10];                           // temperatura canale 1
char tempCH2[10];                           // temperatura canale 2
volatile int indexJ = 0;                    // indice riempimento canale 1
volatile int indexT = 0;                    // indice riempimento canale 2
volatile float CH1, CH2;                    // valore in float (da stringa)
volatile int nRxCharCount;                  // indice riempimento buffer from:MAX31865
char caRxPacket[PACKETDIM];                 // buffer from:MAX31865
volatile int temperature_flag;              // flag per print su richiesta

volatile int ch2_errorDetected;             // flag: errore di trasmissione
int ch2_intChecksum[word];                  //     
char ch2_checksumWord[word];                // checksum sul pacchetto elaborato
char ch2_checksumReceived[word];            // checksum ricevuto

// ************** SETUP *******************
void CMD_REF();                             // crea la lista dei comandi
void TLM_ID_REF();                          // crea la lista delle telemetrie
void clearBuffer(char *arr, int arrLen);    // ripulisce il buffer di ricezione
void clearIntBuffer(int *y, int s);
void Checksum(char *a);                     // effettua checksum sui dati del CH1
void RxTelecommand();                       // riceve da Spacecraft
void TxTelecommand();                       // trasmette a MIMA
void RxTelemetry();                         // riceve da MIMA
void TxTelemetry();                         // trasmette a Spacecraft
void SpareCommand(int command);             // controllo L16, Relay, periferiche
void GetTemperature();
void ReadTemperature();
const char* MIMA_OPERATING_MODE(char *s);
int  BinToDec(int t, int dim, char *a);

// *********************************************************************


int main()
{
    // Setup per trasmissione seriale
    SC.baud(115200);
    MAX31865.baud(115200);
    MIMA.baud(9600);
                
    SC.printf("******* Test DORA Communication *******\r\n");
    
    // Flag per ricezione
    tlmode_option_1 = 1;
    tlmode_option_2 = 1;
    
    // Temperatura
    nRxCharCount = 0;
    clearBuffer(caRxPacket,PACKETDIM);  
    
    // Gestione interrupt seriale
    SC.attach(&RxTelecommand, Serial::RxIrq); // arriva telecomando da PC
    MAX31865.attach(&GetTemperature, Serial::RxIrq); // arriva dato da MAX31865 via Arduino
    
    // Ciclo principale
    while (true)
    {
        /* *********************************************************************
                         RICEZIONE TEMPERATURA DA MAX31865
        ********************************************************************* */   
        
        if ((commandId == 0) && (payloadDec == 32) && (temperature_flag == 1))
        {
            ReadTemperature();
            temperature_flag = 0;
        }
        
                
        /* *********************************************************************
                         RICEZIONE DI TELEMETRIE DA MIMA
        ********************************************************************* */

        sizeBuffer = 0; // reset 
        clearBuffer(TLM, sizeof(TLM)/sizeof(TLM[0]));
        clearBuffer(TLM_HSK, sizeof(TLM_HSK)/sizeof(TLM_HSK[0]));
        clearBuffer(TLM_HSK_SD, sizeof(TLM_HSK_SD)/sizeof(TLM_HSK_SD[0]));
        
        clearIntBuffer(ch1_intChecksum, sizeof(ch1_intChecksum)/sizeof(ch1_intChecksum[0]));
        clearIntBuffer(ch2_intChecksum, sizeof(ch2_intChecksum)/sizeof(ch2_intChecksum[0]));
        clearBuffer(ch1_checksumWord, sizeof(ch1_checksumWord)/sizeof(ch1_checksumWord[0]));
        clearBuffer(ch2_checksumWord, sizeof(ch2_checksumWord)/sizeof(ch2_checksumWord[0]));

        t.start();
        tTimeStart = t.read();  // in secondi 
        tTimeRead = tTimeStart;
        
        MIMA.attach(&RxTelemetry, Serial::RxIrq);   // entra in questa routine quando riceve un carattere dalla seriale del SERIAL
        
        if (commandId == 5) // TLMODE
        {
            if (tlmode_option_1 == 0)
            {
                while (sizeBuffer < TLM_OPTION_1 && ((tTimeRead - tTimeStart) < TIMEOUT))
                {
                    tTimeRead = t.read();
                }

                t.stop();

                if ((tTimeRead - tTimeStart) >= TIMEOUT)
                {
                    sizeBuffer = 0;
                    clearBuffer(TLM_HSK, TLM_OPTION_1);
                    //SC.printf("Timestamp: %f\n\r", tTimeRead);
                }
                else
                {
                    TxTelemetry();
                }
            }
            else if (tlmode_option_2 == 0)
            {
                while (sizeBuffer < TLM_OPTION_2 && ((tTimeRead - tTimeStart) < TIMEOUT))
                {
                    tTimeRead = t.read();
                }

                t.stop();

                if ((tTimeRead - tTimeStart) >= TIMEOUT)
                {
                    sizeBuffer = 0;
                    clearBuffer(TLM_HSK_SD, TLM_OPTION_1);
                    //SC.printf("Timestamp: %f\n\r", tTimeRead);
                }
                else
                {
                    Checksum(TLM_HSK_SD);
                    if (ch1_errorDetected == 0 && ch2_errorDetected == 0) // no checksum error flags
                    {
                        TxTelemetry();
                    }
                }
            }
        }
    }
}


// *********************************************************************


// ************** FUNCTIONS *******************
// init CMD
void CMD_REF()
{
    for (int i = 0; i < CMD_NUM; i++)
    {
        CMD[i] = i;
    }
}

// init TLM
void TLM_ID_REF()
{
    for (int i = 0; i < TLM_NUM; i++)
    {
        TLM_ID[i] = i;
    }
}

// clear
void clearBuffer(char *arr, int arrLen)
{
    for (nIndex = 0; nIndex < arrLen; nIndex++)
    {
        arr[nIndex] = '\0';
    }
}

// clear 
void clearIntBuffer(int *y, int s)
{
    for (nIndex = 0; nIndex < s; nIndex++)
    {
        y[nIndex] = '\0';
    }
}

// DORA riceve telecomando da SC
void RxTelecommand()
{
    CMD_REF();

    while (SC.readable()) 
    {
        clearBuffer(getPacket, sizeof(getPacket)/sizeof(getPacket[0])); 
        SC.gets(getPacket, sizeof(getPacket));  
        LEN = strlen(getPacket) - 2;    // calcola la sua lunghezza ignorando i tag \r\n
        ch = getPacket[0];

        if (LEN != PACKET)
        {
            SC.printf("> Bit number: %i is not equal to 15  // no tele-command\n\r", LEN);  // diagnostica  
        }
        else
        {
            for (int n = 0; n < LEN; n++)
            {
                PacketChecked[n] = getPacket[n];
            }

            // *** CONTROLLO DEI BIT - LSB: EVEN/ODD ***
            int ones = 0;
            int check = 0;
            while (check < PACKET)
            {
                if (getPacket[check] == '1')
                {
                    ones++;
                }

                check++;
            }

            char newItem;

            if (ones % 2 == 0)
            {
                newItem = '0';  // If the number of ones in[B0÷B14] bits is even (making the total number of ones even)
            }
            else
            {
                newItem = '1';  // If the number of ones in[B0÷B14] bits is odd (making the total number of ones even)
            }

            int nPacket = PACKET + 1;
            // shift elements 
            for (int i = nPacket - 1; i >= PACKET_CHECKED; i--)
            {
                PacketChecked[i] = PacketChecked[i - 1];
            }

            // insert LSB
            PacketChecked[PACKET_CHECKED - 1] = newItem;

            SC.printf("> Send: ");
            for (int z = 0; z < PACKET_CHECKED; z++)
            {
                SC.printf("%c", PacketChecked[z]);
            }

            SC.printf("\n\r");

            // ************DIAGNOSTICA ************
            // un telecommand è formato da 16 bit. i primi 5 sono identificativi,
            // poi ho due bit che mi specificano se i dati in arrivo sono una o più parole,
            // dopodiché ho un payload da 8 bit e per concludere ho LSB (parity bit)
            // MSB IIII TT PPPPPPPP PC
 
            /* ** COMMAND IDENTIFIER ** */
            int CMDIndex = 0;   // puntatore dell'identificativo
            commandId = 0;

            int B7 = PacketChecked[7];
            int B9 = PacketChecked[9];
            int B11 = PacketChecked[11];

            // trasformo l'identificatore in numero decimale intero
            commandId = BinToDec(CMDIndex, IDENTIFIER, PacketChecked);

            // scorro la lista di comandi disponibli e verifico se il comando trasmesso rientra
            // nella lista, altrimenti finisco in uno dei 3 SPARE
            int k = 0;
            int isElementPresent = 0;
            while (k < CMD_NUM)
            {
                if (commandId == CMD[k])
                {
                    isElementPresent = 1;
                    SC.printf("> Telcommand sent belgons to MIMA command list: CMD %i\n\r", k);

                    if (k == 2 || k == 15 || k == 30) // CMD02, CMD15, CMD30
                    {
                        SC.printf("> CMD %i : SPARE\n\r", k);
                    }
                    else if (k == 0 && PacketChecked[5] == '0' && PacketChecked[6] == '0') // CMD0 - spare
                    {
                        int counter = 7; // parto dal settimo bit
                        payloadDec = 0;  // inizializzazione del payload in formato digitale

                        payloadDec = BinToDec(counter, PACKET, PacketChecked);        

                        SpareCommand(payloadDec);
                        break;
                    }
                    else if (k == 1) // CMD01
                    {
                        SC.printf("> CMD %i, CODE: MIMA MODE\n\r", k);
                        
                        SC.printf("%s\n\r", MIMA_OPERATING_MODE(PacketChecked));
                        
                    }
                    else if (k == 3)
                    {
                        SC.printf("> CMD %i, CODE: LDth_On_Off - On/Off of Laser Diode thermal control loop\n\r", k);
                    }
                    else if (k == 4)
                    {
                        SC.printf("> CMD %i, CODE: IRth_On_Off - On/Off of IR sensor thermal control loop\n\r", k);
                    }
                    else if (k == 5)
                    {
                        int checkZerosIndex = 7;
                        while (checkZerosIndex < PACKET_CHECKED)
                        {
                            if (PacketChecked[checkZerosIndex] == '0')
                            {
                                tlmode_option_1 = 0;
                                checkZerosIndex++;
                            }
                            else
                            {
                                tlmode_option_1 = 1;
                                break;
                            }
                        }
                        
                        int checkOnesIndex = 7;
                        while (checkOnesIndex < PACKET_CHECKED)
                        {
                            if (PacketChecked[checkOnesIndex] == '1')
                            {
                                tlmode_option_2 = 0;
                                checkOnesIndex++;
                            }
                            else
                            {
                                tlmode_option_2 = 1;
                                break;
                            }
                        }
                    }
                    else if (k == 6)
                    {
                        int checkZerosIndex = 7;
                        while (checkZerosIndex < PACKET_CHECKED)
                        {
                            if (PacketChecked[checkZerosIndex] == '0')
                            {
                                interferogram_option_1 = 0;
                                checkZerosIndex++;
                            }
                            else
                            {
                                interferogram_option_1 = 1;
                                break;
                            }
                        }
                        
                        int checkOnesIndex = 7;
                        while (checkOnesIndex < PACKET_CHECKED)
                        {
                            if (PacketChecked[checkOnesIndex] == '1')
                            {
                                interferogram_option_2 = 0;
                                checkOnesIndex++;
                            }
                            else
                            {
                                interferogram_option_2 = 1;
                                break;
                            }
                        } 
                        
                        if (interferogram_option_1 == 0)
                        {
                            SC.printf("> CMD %i, START interferogram acquisition\n\r", k);
                        }
                        else if (interferogram_option_2 == 0)
                        {
                            SC.printf("> CMD %i, STOP interferogram acquisition\n\r", k);
                        }
                    }
                    else if (k == 7) // CMD07
                    {
                        // IR sensor thermal loop
                        if (B7 == '1')
                        {
                            SC.printf("> IR sensor thermal loop...\n\r");
                            SC.printf("IRT1 telemetry: feedback signal in the thermal control loop (default). IRT2 only for monitoring\n\r");
                        }
                        else
                        {
                            SC.printf("> IR sensor thermal loop...\n\r");
                            SC.printf("IRT2 telemetry: feedback signal in the thermal control. IRT1 only for monitoring\n\r");
                        }

                        // Laser Diode thermal loop
                        if (B9 == '1')
                        {
                            SC.printf("> Laser Diode thermal loop...\n\r");
                            SC.printf("LDT1 telemetry: feedback signal in the thermal control loop (default). LDT2 only for monitoring\n\r");
                        }
                        else
                        {
                            SC.printf("> Laser Diode thermal loop...\n\r");
                            SC.printf("LDT2 telemetry: feedback signal in the thermal control. LDT1 only for monitoring\n\r");

                        }

                        // BlackBody thermal loop
                        if (B11 == '1')
                        {
                            SC.printf("> BlackBody thermal loop...\n\r");
                            SC.printf("BBT1 telemetry: feedback signal in the thermal control loop (default). BBT2 only for monitoring\n\r");
                        }
                        else
                        {
                            SC.printf("> BlackBody thermal loop...\n\r");
                            SC.printf("BBT2 telemetry: feedback signal in the thermal control. BBT1 only for monitoring\n\r");
                        }
                    }
                    
                    else if ((k == 0) && (payloadDec == 32))
                    {
                        temperature_flag = 1;
                    }

                }
                
                k++;
            }

            if (isElementPresent == '0')
            {
                SC.printf("Telecommand sent doesn't exist\n\r");
            }

            // ***TAG ***
            int B5 = PacketChecked[5];
            int B6 = PacketChecked[6];

            if (B5 == '0' && B6 == '0')
            {
                // Single word telemetry
                SC.printf("Single word telemetry\n\r");
            }
            else if (B5 == '0' && B6 == '1')
            {
                // Multiple words telemetry (1st word)
                SC.printf("Multiple words telemetry (1st word)\n\r");
            }
            else if (B5 == '1' && B6 == '0')
            {
                // Multiple words telemetry (2nd word)
                SC.printf("Multiple words telemetry (2nd word)\n\r");
            }
            else
            {
                // Not used
                SC.printf("NOT USED\n\r");
            }

            // diagnostica: payload
            SC.printf("> Payload: ");
            for (int IndexPayload = 7; IndexPayload < PACKET; IndexPayload++)
            {
                SC.printf("%c", PacketChecked[IndexPayload]);
            }

            SC.printf("\n\r");  // per leggibilità

            //***********FINE DIAGNOSTICA PACCHETTO***********

        }
        
        TxTelecommand();
    }
}


/* ***************************************************************** */


// DORA trasmette telecomando a MIMA
void TxTelecommand()                                                                // Tx Telecommand
{
    for (int i = 0; i < PACKET_CHECKED + 1; i++)
    {
        MIMA.putc(PacketChecked[i]);
    }
}


/* ***************************************************************** */


// DORA riceve telemetria da MIMA
void RxTelemetry(void)                                                              // Rx Telemetry
{
    while((MIMA.readable()))
    {
        data = MIMA.getc(); // prendi carattere in arrivo
        
        if (tlmode_option_1 == 0)
        {
            TLM_HSK[sizeBuffer++] = data;
        } 
        else if (tlmode_option_2 == 0)
        {
            TLM_HSK_SD[sizeBuffer++] = data;
        }
        else 
        {
            TLM[sizeBuffer++] = data;
        }
            
    }
}


/* ***************************************************************** */


// DORA trasmette dati verso Space/craft
void TxTelemetry()                                                                  // Tx Telemetry
{
    if (tlmode_option_1 == 0)
    {
        SC.printf("\n\r> Receiving 57 words (all HSK) from MIMA... \n\r");
        
        for (int i = 0; i < TLM_OPTION_1; i++)
        {
             SC.putc(TLM_HSK[i]);
             ARDUINO.putc(TLM_HSK[i]);
        } 
        
        // parsing del pacchetto da 16 bit * 57 parole
        SC.printf("\n\r");
    }
    else if (tlmode_option_2 == 0)
    {
        SC.printf("\n\r> Receiving 5663 words (HSK + Scientific Data) from MIMA... \n\r");
        
        for (int i = 0; i < TLM_OPTION_2; i++)
        {
           
            SC.putc(TLM_HSK_SD[i]);
            ARDUINO.putc(TLM_HSK_SD[i]);
        }
        
        // parsing del pacchetto da 16 bit * 57 parole
        SC.printf("\n\r");
    }
    else 
    {
        SC.printf("\n\r> Receiving Telemetry from MIMA... \n\r");
        
        for (int i = 0; i < TLM_OPTION_2; i++)
        {
            SC.putc(TLM[i]);
            ARDUINO.putc(TLM[i]);
        }
        
        // parsing del pacchetto da 16 bit
        // TLM_parsing(TLM);
        SC.printf("\n\r");
    }
    
}


/* ***************************************************************** */


void TLM_parsing(char *tlm_buf) 
{
    // identificatore
    int tlm_identifier = BinToDec(0, IDENTIFIER, tlm_buf); 
    volatile int single_word = 0, first_word = 0, second_word = 0;
    
    if (tlm_buf[5] == '0' && tlm_buf[6] == '0')
    {
        // single word
        single_word = 1;
    }
    else if (tlm_buf[5] == '0' && tlm_buf[6] == '1')
    {
        // 1st word
        first_word = 1;
    }
    else if (tlm_buf[5] == '1' && tlm_buf[6] == '0')
    {
        // 2nd word
        second_word = 1;
    }
    else if (tlm_buf[5] == '1' && tlm_buf[6] == '1')
    {
        // not used
    }
    
    if (commandId == 1)
    {
        if ((tlm_identifier == 25) && (first_word == 1))
        {
            SC.printf("%s\n\r", MIMA_OPERATING_MODE(tlm_buf));
        }
    }
}


/* ***************************************************************** */

// integrità dei dati ricevuti da MIMA: Channel 1 - Channel 2
void Checksum(char *a)                                                              // Checksum
{
    volatile int temp, var, ai_int, aj_int, p = 0;
  
    for (int i = word; i < 2*word; i++) 
    {
        volatile int ch1_start = i+word;
        
        for (int j = ch1_start; j < CHANNEL*word; j+=word)
        {
            if (j == ch1_start) 
            {
                ai_int = a[i] - '0';    // '1'/'0' char -> int 1/0
                aj_int = a[j] - '0';    // '1'/'0' char -> int 1/0
                temp = ai_int ^ aj_int; // XOR
            } else
            {
                aj_int = a[j] - '0';
                temp = temp ^ aj_int;   
            }

        }
        ch1_intChecksum[p++] = temp; // vettore del checksum in int
    }
    
    for (int i = 0; i < word; i++) // trasformo in char
    {
        if (ch1_intChecksum[i] == 0)
        {
            ch1_checksumWord[i++] = '0';
        } 
        else if (ch1_intChecksum[i] == 1)
        {
            ch1_checksumWord[i++] = '1';
        }
    }
    
    // confronto tra checksum ricevuto e checksum elaborato
    volatile int t = 0;
    for (int i = (CHANNEL+1)*word; i < (CHANNEL+2)*word; i++) 
    {
        ch1_checksumReceived[t++] = TLM_HSK_SD[i];
    }
    
    ch1_errorDetected = 0;
    
    for (int i = 0; i < sizeof(ch1_checksumWord)/sizeof(ch1_checksumWord[0]); i++) 
    {
        if (ch1_checksumWord[i] != ch1_checksumReceived[i])
        {
            ch1_errorDetected = 1;
            SC.printf("\n\r> CH1 Channel Checksum ERROR detected: BIT n. %i\n\r", (i+1));
            break;
        }         
    }  
    
    
    /***** CHANNEL 2 *****/
    
    p = 0;
    int ch2_limit = (2*CHANNEL+4);
    for (int i = (CHANNEL+4)*word; i < ch2_limit*word; i++) 
    {
        volatile int ch2_start = i+word;
        
        for (int j = ch2_start; j < (ch2_limit+CHANNEL)*word; j+=word)
        {
            if (j == ch2_start) 
            {
                ai_int = a[i] - '0';    // '1'/'0' char -> int 1/0
                aj_int = a[j] - '0';    // '1'/'0' char -> int 1/0
                temp = ai_int ^ aj_int; // XOR
            } else
            {
                aj_int = a[j] - '0';
                temp = temp ^ aj_int;   
            }

        }
        ch2_intChecksum[p++] = temp; // vettore del checksum in int
    }
    
    for (int i = 0; i < word; i++) // trasformo in char
    {
        if (ch2_intChecksum[i] == 0)
        {
            ch2_checksumWord[i++] = '0';
        } 
        else if (ch1_intChecksum[i] == 1)
        {
            ch2_checksumWord[i++] = '1';
        }
    }
    
    // confronto tra checksum ricevuto e checksum elaborato
    t = 0;
    for (int i = (CHANNEL+4)*word; i < (2*CHANNEL+4)*word; i++) 
    {
        ch2_checksumReceived[t++] = TLM_HSK_SD[i];
    }
    
    ch2_errorDetected = 0; // flag
    
    for (int i = 0; i < sizeof(ch2_checksumWord)/sizeof(ch2_checksumWord[0]); i++) 
    {
        if (ch2_checksumWord[i] != ch2_checksumReceived[i])
        {
            ch2_errorDetected = 1;
            SC.printf("\n\r> CH2 Channel Checksum ERROR detected: BIT n. %i\n\r", (i+1));
            break;
        }         
    }     
}


/* ***************************************************************** */

// controllo dell'attuatore e dei relay
void SpareCommand(int command)                                                      // Spare command (Relay, L16)
{        
    if((command == 128) && (offset < 1.0f)) 
    { 
        offset += 0.2f; 
        M1.write(offset);
        M2.write(offset); 
        SC.printf("> Duty Cycle %.2f / estensione \n\r", offset);    
    } 
    else if((command == 64) && (offset > 0.0f)) 
    {
        offset -= 0.2f; 
        M1.write(offset);
        M2.write(offset); 
        SC.printf("> Duty Cycle %.2f / estensione \n\r", offset);  
    }
    else if (command == 1) 
    {
        Relay5V = 0;
        SC.printf("\r\nRelay 5V ON\r\n");       
    } 
    else if (command == 0) 
    {
        Relay5V = 1;
        SC.printf("\r\nRelay 5V OFF\r\n");
    } 
    else if (command == 3) 
    {
        Relay12V = 0;
        SC.printf("\r\nRelay 12V ON\r\n");           
    }  
    else if (command == 2) 
    {
        Relay12V = 1;
        SC.printf("\r\nRelay 12V OFF\r\n");
    } 
    else if (command == 7) 
    {
        Relay15_15_5V = 0;
        SC.printf("\r\nRelay +15V, -15V, -5V ON\r\n");     
    } 
    else if (command == 6) 
    {
        Relay15_15_5V = 1;
        SC.printf("\r\nRelay +15V, -15V, -5V OFF\r\n");
    } 
    else if (command == 15) 
    {
        Relay24V = 0;
        SC.printf("\r\nRelay 24V ON\r\n");        
    } 
    else if (command == 8) 
    {
        Relay24V = 1;
        SC.printf("\r\nRelay 24V OFF\r\n");   
    } 
    else if (command == 255) 
    {
        Relay5V = 1;
        Relay12V = 1;
        Relay15_15_5V = 1; // +15, -15, -5
        Relay24V = 1;
        offset = 0.0f;
            
        SC.printf("**** SHUTTING DOWN ALL RELAYS... ****\n\r");
        M1.write(offset);
        M2.write(offset); 
        SC.printf("> Duty Cycle %.2f / extension \n\r", offset);
    }
    else if ((command == 128) || (command == 64) && (Relay12V == 1))
    {
        offset = 0.0f;
        M1.write(offset);
        M2.write(offset); 
    }                   
}


/* ***************************************************************** */

// (t = indice da cui partire, dim = dimensione array, *a = array in input)
int BinToDec(int t, int dim, char *a)                                               // Binary to decimal conversion
{
    volatile int result = 0;

    while (t < dim)
    {
        if (a[t] == '1')
        {
            int raise = dim - 1 - t;
            result += pow((float) base, (float) raise);
        }
        else
        {
            result += 0;
        }
        t++;
    }
    return result;
}


/* ***************************************************************** */


// TEMPERATURA
void GetTemperature(void)                                                           // Get temperature from MAX31865-Arduino
{
    char cReadChar; 
    
    while((MAX31865.readable()))
    {
        cReadChar = MAX31865.getc();
        nRxCharCount++; 
        caRxPacket[nRxCharCount] = cReadChar;
    }
}


/* ***************************************************************** */


void ReadTemperature(void)                                                          // Read temperature float value 
{
    nRxCharCount = 0; // indice

    int y = 0, u = 0; // indici

    for (int i = 0; i < PACKETDIM; i++)
    {
        if (caRxPacket[i] == 'S')
        {
            indexJ = i + 1;

            while (indexJ < PACKETDIM)
            {
                if (caRxPacket[indexJ] == ';')
                {
                    break;
                }
                else
                {
                    tempCH1[y++] = caRxPacket[indexJ];
                }

                indexJ++;
            } // se trova ; esce dall'istruzione e salva il valore di uscita dell'indice

            indexT = indexJ + 1;

            while (indexT < PACKETDIM)
            {
                if (caRxPacket[indexT] == 'P')
                {
                    break;
                }
                else
                {
                    tempCH2[u++] = caRxPacket[indexT];
                }

                indexT++;
            }
            
            // trasforma il dato da sequenza di caratteri a numero float utile per analisi

            strcpy(CH1_to_string, tempCH1);
            CH1 = atof(CH1_to_string);

            strcpy(CH2_to_string, tempCH2);
            CH2 = atof(CH2_to_string);

            SC.printf("> TEMPERATURE - CH1: %4.8f[Celsius], CH2: %4.8f[Celsius]\n\r", CH1, CH2);

            break;
        }
    }

    wait_ms(150); // pausa per garantire sincronizzazione tra riempimento buffer e svuotamento
}


/* ***************************************************************** */             // MIMA OPERATING MODE


const char* MIMA_OPERATING_MODE(char *s)
{
    if (s[7] == '0' && s[8] == '0' && s[9] == '0' && s[10] == '1')
    {
        return "> Setting MIMA... Sleeping mode";
    }
    else if (s[7] == '0' && s[8] == '0' && s[9] == '1' && s[10] == '0')
    {
        return "> Setting MIMA... Awake mode";
    }
    else if (s[7] == '0' && s[8] == '0' && s[9] == '1' && s[10] == '1')
    {
        return "> Setting MIMA... Calibration mode";
    }
    else if (s[7] == '0' && s[8] == '1' && s[9] == '0' && s[10] == '0')
    {
        return "> Setting MIMA... Observation mode";
    }
    else if (s[7] == '0' && s[8] == '1' && s[9] == '0' && s[10] == '1') 
    {
        return "> Setting MIMA... Auto-test mode";
    }
    else if (s[7] == '0' && s[8] == '1' && s[9] == '1' && s[10] == '0')
    {
        return "> Setting MIMA... Full testing mode";
    }
    
    return "\0";
}


/* ***************************************************************** */