Space / Mbed 2 deprecated SC-MIMA-Protocol

Dependencies:   mbed

main.cpp

Committer:
paologiorgio
Date:
2022-06-01
Revision:
0:295db98f7ea0

File content as of revision 0:295db98f7ea0:

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

/*----------------------------
   ---------- INFO ----------- */

// DORA SETTING to-do-6 giugno !!!
// master-slave: slave MIMA comunica con DORA con collegamento UART (tx, rx, gnd)
// PC S/C sends packets to DORA -> MIMA (STM32) -> PC

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

/*----------------------------
   ---------- 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 IDENTIFIER 5
#define TAG 2
#define PAYLOAD 8
#define CMD_NUM 32 
#define OPTION_1 912 // 57*16
#define OPTION_2 90608 // 5663*16
#define tb 7 // bit sampling period

/*----------------------------
   ---------- INIT ----------- */
// comunicazioni seriali DORA

// PIN OCCUPATI: D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10

// ************** CN7 ********************
Serial SC(USBTX, USBRX);            // A4 TX, A6 RX - DATA OUT, DATA IN
DigitalOut GATE_WRITE_SC(PB_0);     // A3
DigitalOut GATE_READ_SC(PA_4);      // A2
DigitalOut DATA_CLOCK_OUT_SC(PA_1); // A1

// ************** CN10 *******************
Serial MIMA(PB_6, PA_10); // IN - OUT               // TX D1, RX D0 -> DATA_OUT, DATA_IN -> D0 e D1 non vanno bene! Risorse già occupate
// PA_8, PA_9, PC_1, PC_0, PA_10, PB_3 // RX, TX
DigitalOut GATE_WRITE_MIMA(PA_9);       // D8
DigitalOut GATE_READ_MIMA(PC_7);        // D9
DigitalOut DATA_CLOCK_OUT_MIMA(PB_6);   // D10

// DATA_OUT_CLOCK.write(0) -> wait_ms(7) -> DATA_OUT_CLOCK.write(0) -> wait_ms(7)

// informazioni circa il pacchetto trasmesso
volatile int nIndex;    // indice del pacchetto per lo "spacchettamento"
char getPacket[PACKETSIZE]; // buffer - pacchetto inviato di dimensione max PACKETSIZE
char PacketChecked[PACKET_CHECKED]; // lato Space/Craft
char TLM[OPTION_1]; // lato MIMA per check
char TLM_SD[OPTION_2]; // lato MIMA per check
char TLM_SC[OPTION_1]; // lato space/craft per check
char TLM_SD_SC[OPTION_2]; // lato space/craft per check

volatile int LEN;   // numero di bit da ricevere per ricezione corretta 
volatile int commandId;
volatile int size;
volatile unsigned char data;    // in arrivo da MIMA per telemetria

int base = 2;   // base per l'esponenziale (conversione binary to decimal)
int CMD[CMD_NUM];   // CMD in decimale
//const char *CODE[] = {};  // LISTA comandi 

volatile int option_1 = 0;   // default
volatile int option_2 = 0;

/*----------------------------
   ---------- SETUP ----------- */
void CMD_REF(void);
void init(void);
void RxTelecommand(void);
void TxTelecommand(void);
void RxTelemetry(void);
void TxTelemetry(void);

/*----------------------------
   ---------- MAIN ----------- */
int main()
{
    SC.baud(115200);
    MIMA.baud(115200);
    
    // Setup
    GATE_READ_MIMA = 1;
    GATE_WRITE_MIMA = 1;
    
    GATE_READ_SC = 1;
    GATE_WRITE_SC = 1;
    
    SC.printf("******* Starting... *******\n\r");

    // interrupt quando arriva stringa da PC (space/craft)
    SC.attach(&RxTelecommand, Serial::RxIrq);
    // interript quando invia stringa a MIMA
    MIMA.attach(&TxTelecommand, Serial::TxIrq);
    // interrupt quando riceve stringa da MIMA
    MIMA.attach(&RxTelemetry, Serial::RxIrq);
    // interrupt quando invia stringa a SC
    SC.attach(&TxTelemetry, Serial::TxIrq);

}



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



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

// inizializzazione pacchetto TBC
void init(void)
{
    // reset pacchetto
    nIndex = 0;
    for (nIndex = 0; nIndex < PACKETSIZE; nIndex++)
    {
        getPacket[nIndex] = '\0';
    }
}

// DORA riceve telecomando da MIMA
void RxTelecommand(void)
{
    init(); // clear the buffer
    CMD_REF();  // carica vettore dei comandi

    while (SC.readable())   // finché sulla porta USB arrivano dati, esegui
    {
        SC.gets(getPacket, sizeof(getPacket));  // leggi la stringa in ingresso
        LEN = strlen(getPacket) - 2;    // calcola la sua lunghezza ignorando i tag \r\n

        if (LEN != PACKET)
        {
            // controlla se la stringa ricevuta è consona (16 bit)
            SC.printf("> Bit number: %i is not equal to 15 - ERROR\n\r", LEN);  // diagnostica        
        }
        else
        {
            for (int n = 0; n < LEN; n++)
            {
                PacketChecked[n] = getPacket[n];    // riempi il nuovo array
            }

            // ***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;
            // trasformo l'identificatore in numero
            while (CMDIndex < IDENTIFIER)
            {
                if (PacketChecked[CMDIndex] == '1')
                {
                    int raise = IDENTIFIER - 1 - CMDIndex;
                    commandId += pow((float) base, (float) raise);
                }
                else
                {
                    commandId += 0;
                }

                CMDIndex++;
            }

            // 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);
                    break;

                }

                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");
            }

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

            SC.printf("\n\r");
            int B7 = PacketChecked[7];
            int B9 = PacketChecked[9];
            int B11 = PacketChecked[11];

            // ******************************
            // ********CHECK CMD01 *********
            // ******************************
            if (PacketChecked[11] == '0' &&
                PacketChecked[12] == '0' &&
                PacketChecked[13] == '0' &&
                PacketChecked[14] == '1')
            {
                SC.printf("> Setting MIMA... Sleeping mode\n\r");
            }
            else if (PacketChecked[11] == '0' &&
                PacketChecked[12] == '0' &&
                PacketChecked[13] == '1' &&
                PacketChecked[14] == '0')
            {
                SC.printf("> Setting MIMA... Awake mode\n\r");
            }
            else if (PacketChecked[11] == '0' &&
                PacketChecked[12] == '0' &&
                PacketChecked[13] == '1' &&
                PacketChecked[14] == '1')
            {
                SC.printf("> Setting MIMA... Calibration mode\n\r");
            }
            else if (PacketChecked[11] == '0' &&
                PacketChecked[12] == '1' &&
                PacketChecked[13] == '0' &&
                PacketChecked[14] == '0')
            {
                SC.printf("> Setting MIMA... Observation mode\n\r");
            }
            else if (PacketChecked[11] == '0' &&
                PacketChecked[12] == '1' &&
                PacketChecked[13] == '0' &&
                PacketChecked[14] == '1')
            {
                SC.printf("> Setting MIMA... Auto-test mode\n\r");
            }
            else if (PacketChecked[11] == '0' &&
                PacketChecked[12] == '1' &&
                PacketChecked[13] == '1' &&
                PacketChecked[14] == '0')
            {
                SC.printf("> Setting MIMA... Full testing mode\n\r");
            }

            // 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");
            }

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

}   

// DORA trasmette telecomando a MIMA
void TxTelecommand(void)
{

    while (MIMA.writeable())
    {
        GATE_WRITE_MIMA = 0;
        
        DATA_CLOCK_OUT_MIMA = 1;
        wait_ms(7);
            
        for (int i = 0; i < PACKET_CHECKED + 1; i++)
        {
            DATA_CLOCK_OUT_MIMA = 0;
            // The data are read on the falling-edge of the DATA_CLOCK_OUT signal
            MIMA.putc(PacketChecked[i]);
            wait_ms(7);
            DATA_CLOCK_OUT_MIMA = 1;
            wait_ms(7);
        }
    }
    
    GATE_WRITE_MIMA = 1;
    
}

// DORA riceve telemetrie/telemetrie+scientific data da MIMA
void RxTelemetry(void)
{
    while (MIMA.readable()) // finché la seriale sul MIMA manda caratteri
    {
        GATE_READ_MIMA = 0;
        
        // check del payload per scelta del buffer
        // 00000000 -> Option 1: transfer all Housekeeping and Status telemetries (from TLM00 to TLM56)
        // 11111111 -> Option 2: transfer telemetries and scientific data packets (from TLM00 to TLM5662)

        int j = 7;
        while (j < PACKET_CHECKED)
        {
            if (PacketChecked[j] == '0')
            {
                j++;
            }
            else
            {
                option_1 = 1;
                break;
            }
        }

        int k = 7;
        while (k < PACKET_CHECKED)
        {
            if (PacketChecked[k] == '1')
            {
                k++;
            }
            else
            {
                option_2 = 1;
                break;
            }
        }

        if (commandId == 5) // TLMODE
        {
            if (option_1 == 0)
            {
                size = 0;   // reset 

                TLM[0] = '\0';
                SC.printf("Receiving 57 words...\n\r");

                while (size < OPTION_1)
                {
                    DATA_CLOCK_OUT_MIMA = 1;
                    wait_ms(tb/2);
                    DATA_CLOCK_OUT_MIMA = 0;
                    data = MIMA.getc(); // prendi carattere in arrivo
                    TLM[size] = data;
                    size++;
                    wait_ms(tb/2);
                    
                    if ((size+1) == OPTION_1)
                    {
                        SC.printf("%s", TLM);
                        size = 0;
                        break;
                    }
                }
            }
            else if (option_2 == 0)
            {
                size = 0;

                TLM_SD[0] = '\0';
                SC.printf("Receiving 5663 words...\n\r");

                while (size < OPTION_2)
                {
                    DATA_CLOCK_OUT_MIMA = 1;
                    wait_ms(tb/2);
                    DATA_CLOCK_OUT_MIMA = 0;
                    data = MIMA.getc();
                    TLM_SD[size] = data;
                    size++;
                    wait_ms(tb/2);
                    
                    
                    if ((size+1) == OPTION_2)
                    {
                        SC.printf("%s", TLM_SD);
                        size = 0;
                        break;
                    }
                }

            }
        }
        
    GATE_READ_MIMA = 1;
    
    }
}


// DORA trasmette dati verso Space/craft
void TxTelemetry(void)
{
    while(SC.writeable())
    {
        GATE_WRITE_SC = 0;
        
        DATA_CLOCK_OUT_SC = 1;
        wait_ms(tb/2);
        
        // The data are read on the falling-edge of the DATA_CLOCK_OUT signal
        if (option_1 == 0) 
        {
            for (int i = 0; i < OPTION_1; i++) 
            {
                DATA_CLOCK_OUT_SC = 0;
                SC.putc(TLM[i]);
                wait_ms(tb/2);
                DATA_CLOCK_OUT_SC = 1;
                wait_ms(tb/2);
            }
        } else if (option_2 == 0) 
        {
            for (int i = 0; i < OPTION_2; i++) 
            {
                DATA_CLOCK_OUT_SC = 0;
                SC.putc(TLM_SD[i]);
                wait_ms(tb/2);
                DATA_CLOCK_OUT_SC = 1;
                wait_ms(tb/2);
            }
        }
        
        GATE_WRITE_SC = 1;
    }
    
}