Version FC

Dependencies:   DmTftLibrary eeprom SX1280Lib filesystem mbed

Fork of MSNV2-Terminal_V1-5 by Francis CHATAIN

Loracpp.txt

Committer:
FCH_31
Date:
2018-10-22
Revision:
41:5a436163dddf
Parent:
Lora.cpp@ 13:5414193da1de

File content as of revision 41:5a436163dddf:

/*
 * MISNet   
 *
 *  Lora:   Radio Management 
 *
 *  Created on: August 17, 2018       Author: Francis CHATAIN
 *
 */


// =====================================  Includes
#include "Lora.h"
#include "mbed.h"
#include "main.h"
#include "sx1280-hal.h"

// ==========================================================================  DEFINE
#define MODE_LORA         // Lora modulation 

#define TX_TIMEOUT_VALUE        100                         // ms   Number of tick size steps for tx timeout
#define RX_TIMEOUT_VALUE        100                         // ms   Number of tick size steps for rx timeout
#define RX_TIMEOUT_TICK_SIZE    RADIO_TICK_SIZE_1000_US     // Size of ticks (used for Tx and Rx timeout)
#define MODE_ADDR               0x8000 


// ==========================================================================  HW 
DigitalOut  F_CS        ( D6 )  ;     // MBED description of pin
DigitalOut  SD_CS       ( D8 )  ;     // MBED description of pin
DigitalOut  ANT_SW      ( A3 )  ;
DigitalOut  TxLed       ( A4 )  ;
DigitalOut  RxLed       ( A5 )  ;


// ==========================================================================  VARIABLES 
uint16_t    RxIrqMask ;       // Mask of IRQs to listen to in rx mode
uint16_t    TxIrqMask ;       // Mask of IRQs to listen to in tx mode


uint32_t    valueTimeTx      ; 
uint32_t    valueTimeLoop    ;

int         dataCounter     = 0 ;
uint8_t     oldFreq         ; 
uint8_t     oldBw           ; 
uint8_t     oldPwr          ; 
uint8_t     oldSf           ; 
uint8_t     oldTimer        ; 

// States of the application
typedef enum  { APP_LOWPOWER, APP_RX, APP_RX_TIMEOUT, APP_RX_ERROR, APP_TX, APP_TX_TIMEOUT, } AppStates_t ;
AppStates_t AppState = APP_LOWPOWER;        // Init State of the application

PacketStatus_t  PacketStatus        ;
int8_t          RssiValue    = 0    ;
int8_t          SnrValue     = 0    ;

ModulationParams_t          modulationParams;
PacketParams_t              PacketParams    ;        // Locals parameters and status for radio API
PacketStatus_t              packetStatus    ;        // NEED TO BE OPTIMIZED, COPY OF STUCTURE ALREADY EXISTING

uint32_t                    RF_FREQUENCY        ;   // HzNominal frequency
RadioLoRaBandwidths_t       LORA_BW             ;   /* 200; 400; 800; 1600 */
RadioLoRaSpreadingFactors_t LORA_SF             ;   /* SF5; SF6=; SF7; SF8 ; SF9; SF10; SF11 ; SF12 */
int8_t                      TX_OUTPUT_POWER     ;   /* Output power in dBm [-18..+13] dBm */ 
uint8_t                     BUFFER_SIZE_MAX     ;   /* Payload size max */
int16_t                     TIMER               ;   /* timer entre reemission en ms */
uint8_t                     BUFFER_SIZE_MIN     ;   /* Payload return size */


// ==========================================================================  Function  
void        initRadio              () ;
void        setRadioTx             () ;
void        setRadioRx             () ;
void        watchDogRxCRNoReceived () ; 



Timer       timerRadio       ;
Timeout     watchDogRx          ;
Timeout     watchDogTx          ;

void OnTxDone       ( void );               // Function to be executed on Radio Tx Done event
void OnRxDone       ( void );               // Function to be executed on Radio Rx Done event
void OnTxTimeout    ( void );               // Function executed on Radio Tx Timeout event
void OnRxTimeout    ( void );               // Function executed on Radio Rx Timeout event
void OnRxError      ( IrqErrorCode_t );     // Function executed on Radio Rx Error event

RadioCallbacks_t callbacks  =  {
    &OnTxDone,        // txDone
    &OnRxDone,        // rxDone
    NULL,             // syncWordDone
    NULL,             // headerDone
    &OnTxTimeout,     // txTimeout
    &OnRxTimeout,     // rxTimeout
    &OnRxError,       // rxError
    NULL,             // rangingDone
    NULL,             // cadDone
};

//                    mosi, miso,   sclk,  nss,  busy , dio1 , dio2, dio3, rst , callbacks...
SX1280Hal Radio     ( D11 , D12 ,   D13 ,  D7 ,  D3   , D5   , NC  , NC  , A0  , &callbacks );



//===============================================================================================================================
void initLora (uint32_t rf,RadioLoRaBandwidths_t bw,RadioLoRaSpreadingFactors_t sf,int8_t pwr) 
//===============================================================================================================================
{
        // Default value initialisation 
    printf( "*** LORA ***  Lora Initialisation    \r\n");
    
    RxIrqMask = IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT;       // Mask of IRQs to listen to in rx mode
    TxIrqMask = IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT;       // Mask of IRQs to listen to in tx mode

    RF_FREQUENCY        =   rf              ;   // HzNominal frequency
    LORA_BW             =   bw              ;   /* 200; 400; 800; 1600 */
    LORA_SF             =   sf              ;   /* SF5; SF6=; SF7; SF8 ; SF9; SF10; SF11 ; SF12 */
    TX_OUTPUT_POWER     =   pwr             ;   /* Output power in dBm [-18..+13] dBm */ 
    BUFFER_SIZE_MAX     =   100             ;   /* Payload size max */
    BUFFER_SIZE_MIN     =   5               ;   /* Payload return size */
    TIMER               =   1000            ;   /* timer entre reemission en ms */ 
    
    
    
    Radio.Reset                 ()              ;  
    Radio.Init                  ()              ;
    initRadio                   ()              ;            
    Radio.SetRegulatorMode      ( USE_DCDC )    ;       // Can also be set in LDO mode but consume more power
    wait_ms                     ( 10 )          ;       // wait for on board DC/DC start-up time
    
    TxLed   = 0     ;
    RxLed   = 0     ;

}


//===============================================================================================================================
void sendMessageLora () {
//===============================================================================================================================
    uint8_t         Buffer          [BUFFER_SIZE_MAX]       ;           // Buffer
    char            frameMISNET     [BUFFER_SIZE_MAX]       ;           // Misnet Frame
    uint8_t         *pointer                                ;
    char            *ptr_int                                ;
    
    
    dataCounter = dataCounter + 1 ;
    memset  ( &Buffer       , 0x00, BUFFER_SIZE_MAX );
    memset  ( &frameMISNET  , 0x00, BUFFER_SIZE_MAX );
    
 
    uint16_t    clearPart           =   0x0     ; 
    
    uint32_t    servicePayload      =   0x0     ; 
    //char        serviceMessage[16]              ;     // TRACES
     
    uint8_t     SFT                 =   0       ;
    uint8_t     DFT                 =   0       ;
    uint8_t     FDL                 =   8       ;
    uint8_t     BL                  =   7       ;
    uint8_t     DMI                 =   66      ;
    uint16_t    RCA                 =   0xBEEF & 0x7FFF ;
    uint32_t    MIC                 =   0xCAFECAFE  & 0xFFFFFFFF  ;
 

    clearPart   =  MODE_ADDR | ( ID_TERMINAL << 6 ) |  ID_GATEWAY ; 
    printf( "*** LORA ***  CLEAR PART= %8X \r\n ", clearPart);

    servicePayload =  (uint32_t)( (SFT & 0x03)  << 30) | 
                      (uint32_t)( (DFT & 0x03)  << 28) | 
                      (uint32_t)( (FDL & 0x3F)  << 22) | 
                      (uint32_t)( (BL  & 0x07)  << 19) | 
                      (uint32_t)( (DMI & 0xFF)  << 11) | 
                      (RCA & 0x7FF)                   ;
                      
    //sprintf (serviceMessage, "%08X%08X", servicePayload, MIC) ;    // traces 
    //printf( "*** LORA ***  SERVICE Payload = %08X \r\n ", servicePayload);
    //printf( "*** LORA ***  SERVICE MIC     = %08X \r\n ", MIC);
    
    // CLEAR PART + Indianess correction 
    pointer = (uint8_t*) &clearPart ;       for (int i = 0, j=1 ; i<2 ; i++, j--)  frameMISNET[j]   = pointer[i] ;
       
    // SERVICE + Indianess correction 
    pointer = (uint8_t*) &servicePayload ;  for (int i=0, j=3 ; i<4 ; i++, j--)    frameMISNET[2+i] = pointer[j] ;
    pointer = (uint8_t*) &MIC ;             for (int i=0, j=3 ; i<4 ; i++, j--)    frameMISNET[6+i] = pointer[j] ;
  
    printf( "*** LORA ***  START Buffer  "); for (int i = 0 ; i<10 ; i++)  printf ("%02X,", frameMISNET[i] ) ; printf( "\n") ; 

    
    int n = sprintf (frameMISNET, "%1c%1c",  ID_TERMINAL, ID_GATEWAY);
   
    pointer = (uint8_t*) &dataCounter  ; for (int i = 0 ; i<4 ; i++)  frameMISNET[2+i] = pointer[i] ;
                                                                 //(int32*)&frameMISNET[2]=(int32*)&ptr_int; // -> aton OR ntoa                                                                                                                         

    printf( "*** LORA ***  TX SEND   %05d  ", dataCounter);
       for (int i = 0 ; i<10 ; i++)  printf ("%d,", frameMISNET[i] ) ; printf( "\n") ; 
       
    
    // Send SF, BW, COUNTER, POWER, FREQ, TIMETX, TIMELOOP, RSSIVALUE
    frameMISNET[6] = LORA_SF            ; 
    ptr_int = (char*) &LORA_BW          ; 
    frameMISNET[7]= ptr_int[1]          ;   
    frameMISNET[8]= ptr_int[0]          ;
    frameMISNET[9] = TX_OUTPUT_POWER    ; 
    ptr_int = (char*) &RF_FREQUENCY     ; for (int i = 0 ; i<4 ; i++)  frameMISNET[10+i] = ptr_int[i] ; 
    ptr_int = (char*) &valueTimeTx      ; for (int i = 0 ; i<4 ; i++)  frameMISNET[14+i] = ptr_int[i] ;   //printf( "*** LORA ***  TimeTx   %d  %d  ", valueTimeTx, valueTimeLoop);  //delay temps Tx   
    ptr_int = (char*) &valueTimeLoop    ; for (int i = 0 ; i<4 ; i++)  frameMISNET[18+i] = ptr_int[i] ;   //delay temps Loop  
    frameMISNET[22] = RssiValue ; 
    
    memcpy                      ( Buffer    , frameMISNET   , 23    );
    
    valueTimeTx   =  0 ; 
    valueTimeLoop =  0 ; 
    timerRadio.reset        ()  ;    // Record tile for close loop
    timerRadio.start        ()  ; 
    setRadioTx              ()  ; 
    TxLed           =       1   ;
    PacketParams.Params.LoRa.PayloadLength          =   23         ;
    Radio.SetPacketParams                           ( &PacketParams )           ;
    Radio.SendPayload       ( Buffer    , 23,( TickTime_t ) {RX_TIMEOUT_TICK_SIZE, TX_TIMEOUT_VALUE} );
    TxLed           =       0   ;

    //printf( "*** LORA ***  ARM watchDogRxRxRxRx  \r\n" );
    watchDogRx.attach (&watchDogRxCRNoReceived, 1.0);     // Arm watchDogRx  if the response is not received in less 500 ms =>  force retry   
}
//===============================================================================================================================


// Time out si pas de message de CR recu
void        watchDogRxCRNoReceived ()  { 
    printf( "*** LORA ***  watchDogRxNoReceive NO RESPONSE    \r\n");    
}   // Force new emission 




//===============================================================================================================================
void initRadio () {
//===============================================================================================================================
    F_CS   = 1  ;
    SD_CS  = 1  ;
    ANT_SW = 1  ;
    
    // SET MODULATION
    modulationParams.PacketType                     =   PACKET_TYPE_LORA        ;
    modulationParams.Params.LoRa.CodingRate         =   LORA_CR_4_5             ;
    modulationParams.Params.LoRa.Bandwidth          =   LORA_BW_0200            ; 
    modulationParams.Params.LoRa.SpreadingFactor    =   LORA_SF7                ; 
    // SET PACKET PARAM
    PacketParams.PacketType                         =   PACKET_TYPE_LORA        ;
    PacketParams.Params.LoRa.PreambleLength         =   0x08                    ;
    PacketParams.Params.LoRa.HeaderType             =   LORA_PACKET_VARIABLE_LENGTH;
    PacketParams.Params.LoRa.PayloadLength          =   BUFFER_SIZE_MAX         ;
    PacketParams.Params.LoRa.Crc                    =   LORA_CRC_ON             ;
    PacketParams.Params.LoRa.InvertIQ               =   LORA_IQ_INVERTED        ;
    // RADIO
    Radio.SetStandby                                ( STDBY_RC  )               ;
    Radio.SetPacketType                             ( modulationParams.PacketType );
    Radio.SetModulationParams                       ( &modulationParams )       ;
    Radio.SetPacketParams                           ( &PacketParams )           ;   
    Radio.SetBufferBaseAddresses                    ( 0x00, 0x00 );
    Radio.SetTxParams                               ( TX_OUTPUT_POWER, RADIO_RAMP_20_US )       ;
    Radio.SetRx                                     ( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, RX_TIMEOUT_VALUE } )   ;
    //AppState                    =                   APP_LOWPOWER;
}
//===============================================================================================================================



//===============================================================================================================================
void setRadioTx () {
//=============================================================================================================================== 
    RxLed  = 0  ;
    TxLed  = 0  ;
    F_CS   = 1  ;
    SD_CS  = 1  ;
    ANT_SW = 1  ;

    // SET MODULATION
    modulationParams.PacketType                     =   PACKET_TYPE_LORA        ;
    modulationParams.Params.LoRa.CodingRate         =   LORA_CR_4_5             ;
    modulationParams.Params.LoRa.Bandwidth          =   LORA_BW    ; 
    modulationParams.Params.LoRa.SpreadingFactor    =   LORA_SF    ; 

    // SET PACKET PARAM
    PacketParams.PacketType                         =   PACKET_TYPE_LORA        ;
    PacketParams.Params.LoRa.PreambleLength         =   0x08                    ;
    PacketParams.Params.LoRa.HeaderType             =   LORA_PACKET_VARIABLE_LENGTH;
    PacketParams.Params.LoRa.PayloadLength          =   BUFFER_SIZE_MAX         ;
    PacketParams.Params.LoRa.Crc                    =   LORA_CRC_ON             ;
    PacketParams.Params.LoRa.InvertIQ               =   LORA_IQ_INVERTED        ;

    // RADIO
    Radio.SetStandby                                ( STDBY_RC  )               ;
    Radio.SetPacketType                             ( modulationParams.PacketType );
    Radio.SetModulationParams                       ( &modulationParams )       ;
    Radio.SetPacketParams                           ( &PacketParams )           ;
    Radio.SetRfFrequency                            ( RF_FREQUENCY )            ;
    Radio.SetBufferBaseAddresses                    ( 0x00, 0x00 );
    Radio.SetTxParams                               ( TX_OUTPUT_POWER, RADIO_RAMP_20_US )       ;
    Radio.SetDioIrqParams                           ( TxIrqMask , TxIrqMask , IRQ_RADIO_NONE, IRQ_RADIO_NONE );
    Radio.SetRx                                     ( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, RX_TIMEOUT_VALUE } )   ;

    //AppState                    =                   APP_LOWPOWER;
 
 }


//===============================================================================================================================
void setRadioRx () {
//===============================================================================================================================
    RxLed  = 0  ;
    TxLed  = 0  ;   
    
    F_CS   = 1  ;
    SD_CS  = 1  ;
    ANT_SW = 1  ;
    
    // SET MODULATION
    modulationParams.PacketType                     =   PACKET_TYPE_LORA        ;
    modulationParams.Params.LoRa.CodingRate         =   LORA_CR_4_5             ;
    modulationParams.Params.LoRa.Bandwidth          =   LORA_BW_0200            ; 
    modulationParams.Params.LoRa.SpreadingFactor    =   LORA_SF7                ; 

    // SET PACKET PARAM
    PacketParams.PacketType                         =   PACKET_TYPE_LORA        ;
    PacketParams.Params.LoRa.PreambleLength         =   0x08                    ;
    PacketParams.Params.LoRa.HeaderType             =   LORA_PACKET_VARIABLE_LENGTH;
    PacketParams.Params.LoRa.PayloadLength          =   BUFFER_SIZE_MIN         ;
    PacketParams.Params.LoRa.Crc                    =   LORA_CRC_ON             ;
    PacketParams.Params.LoRa.InvertIQ               =   LORA_IQ_INVERTED        ;

    // RADIO
    Radio.SetStandby                                ( STDBY_RC  )               ;
    Radio.SetPacketType                             ( modulationParams.PacketType );
    Radio.SetModulationParams                       ( &modulationParams )       ;
    Radio.SetPacketParams                           ( &PacketParams )           ;
    Radio.SetRfFrequency                            ( RF_FREQUENCY + 440000UL)            ;

    Radio.SetBufferBaseAddresses                    ( 0x00, 0x00 );
    Radio.SetDioIrqParams                           ( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE )    ;
    Radio.SetRx                                     ( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, 0x00000000 } )   ;
//    Radio.SetRx                                     ( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, RX_TIMEOUT_VALUE } )   ;
}
//===============================================================================================================================




// ============================================================================ RADIO CALLBACK
void OnTxDone       ( void ) {
//==============================================================================
    valueTimeTx = timerRadio.read_ms () ; 
    printf( "*** LORA ***  OnTxDone \r\n" );
    TxLed   = 0 ;
    setRadioRx () ; 
}
//==============================================================================



//void OnRxDone       ( void )                          { AppState = APP_RX         ;   }
//==============================================================================
void OnRxDone       ( void ) {
//==============================================================================
    uint8_t Buffer1 [BUFFER_SIZE_MAX+1];                  // Buffer Radio
    uint8_t BufferSize = BUFFER_SIZE_MAX ;          // Size of the buffer
 
    RxLed               =   1   ;  // Show the reception 

    printf( "*** LORA ***  RX DONE \r\n" );
    valueTimeLoop = timerRadio.read_ms ()   ; 
    timerRadio.stop       ()  ; 
    watchDogRx.detach     ()  ;      
    //printf( "*** LORA ***  DISARM watchDogRx  \r\n" );

    Radio.GetPacketStatus(&packetStatus)    ; 
    RssiValue = packetStatus.LoRa.RssiPkt   ; 
    
    memset              ( &Buffer1 , 0x00, BUFFER_SIZE_MAX );
    Radio.GetPayload    ( Buffer1, &BufferSize, BUFFER_SIZE_MAX );
    
    RxLed               =   0   ;  // Show the reception 
    
    Buffer1[7] = 0 ; 

    printf  ( "*** LORA *** RX DONE =>  %s \r\n", Buffer1 );   wait(1) ; // flush serial 
     
    // Extract value 
    
    switch (Buffer1[2]) {
        case '1': RF_FREQUENCY    =   2400000000UL ; break ; 
        case '2': RF_FREQUENCY    =   2400680000UL ; break ; 
        case '3': RF_FREQUENCY    =   2423840000UL ; break ; 
        case '4': RF_FREQUENCY    =   2424520000UL ; break ; 
        case '5': RF_FREQUENCY    =   2448840000UL ; break ; 
        case '6': RF_FREQUENCY    =   2449520000UL ; break ; 
        case '7': RF_FREQUENCY    =   2473840000UL ; break ; 
        case '8': RF_FREQUENCY    =   2474520000UL ; break ; 
    }  
                
    switch (Buffer1[3]) {
        case '1': LORA_BW           =   LORA_BW_0200     ;   break ; 
        case '2': LORA_BW           =   LORA_BW_0400     ;   break ; 
        case '3': LORA_BW           =   LORA_BW_0800     ;   break ; 
        case '4': LORA_BW           =   LORA_BW_1600    ;   break ; 
    }  
               
    switch (Buffer1[4]) {
       case '1': TX_OUTPUT_POWER    =   -18         ;   break   ; 
       case '2': TX_OUTPUT_POWER    =   0           ;   break   ; 
       case '3': TX_OUTPUT_POWER    =   8           ;   break   ; 
       case '4': TX_OUTPUT_POWER    =   10          ;   break   ; 
       case '5': TX_OUTPUT_POWER    =   13          ;   break   ; 
    }  
                               
    switch (Buffer1[5]) {
       case '1': LORA_SF            =   LORA_SF5       ;   break     ; 
       case '2': LORA_SF            =   LORA_SF6       ;   break     ; 
       case '3': LORA_SF            =   LORA_SF7       ;   break     ; 
       case '4': LORA_SF            =   LORA_SF8       ;   break     ; 
       case '5': LORA_SF            =   LORA_SF9       ;   break     ; 
       case '6': LORA_SF            =   LORA_SF10      ;   break     ; 
       case '7': LORA_SF            =   LORA_SF12      ;   break     ; 
    }  

   int OLD_TIMER = TIMER ; 
   
   switch (Buffer1[6]) {
        case '1': TIMER      =   50     ;   break     ; 
        case '2': TIMER      =   75     ;   break     ; 
        case '3': TIMER      =   125    ;   break     ; 
        case '4': TIMER      =   250    ;   break     ; 
        case '5': TIMER      =   500    ;   break     ; 
        case '6': TIMER      =   1000   ;   break     ; 
        case '7': TIMER      =   2000   ;   break     ; 
     }    

    RxLed               =   0             ;

    if (oldFreq != Buffer1[2] || oldBw   != Buffer1[3] || oldPwr  != Buffer1[4] || oldSf   != Buffer1[5] || oldTimer   != Buffer1[6] ) {
            oldFreq = Buffer1[2] ;
            oldBw   = Buffer1[3] ;
            oldPwr  = Buffer1[4] ;
            oldSf   = Buffer1[5] ; 
            oldTimer = Buffer1[6] ;
            //printf  ( "*** LORA *** Reset Radio \r\n" );
            //app.updateDisplay   ( LORA_SF, LORA_BW, TX_OUTPUT_POWER, BUFFER_SIZE_MAX, RF_FREQUENCY, TIMER ) ; 
    }   
    
    if (OLD_TIMER != TIMER) {
        //wakeUpTerminal.detach   ();
        //wakeUpTerminal.attach   (&wakeUpTerminalFunction, (float) TIMER/1000);
    }
}
//==============================================================================

void OnTxTimeout    ( void )                        { AppState = APP_TX_TIMEOUT ;}
void OnRxTimeout    ( void )                        { AppState = APP_RX_TIMEOUT ; }
void OnRxError      ( IrqErrorCode_t errorCode )    { AppState = APP_RX_ERROR   ; }
void OnRangingDone  ( IrqRangingCode_t val )        {  }
void OnCadDone      ( bool channelActivityDetected ){  }