LoRa_Node_STM32F103C8T6

Dependencies:   mbed mbed-STM32F103C8T6 OneWireCRC_LoRa_Node SX1276Lib_LoRa_Node

RFM95W.cpp

Committer:
lukas_formanek
Date:
2018-04-22
Revision:
2:8bd9ce0ae2df
Parent:
1:a54ff5e2c2f3
Child:
3:369546c57dc7

File content as of revision 2:8bd9ce0ae2df:

#include "RFM95W.h"

RFM95W rfm; // Globalna instancia

//--------------------------- Callback funkcie ---------------------------------
void TxDone(void){rfm.OnTxDone();};

void RxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ){rfm.OnRxDone(payload,size,rssi,snr);};

void TxTimeout(void){rfm.OnTxTimeout();};

void RxTimeout(void){rfm.OnRxTimeout();};

void RxError(void){rfm.OnRxError();};

void CadDone(bool channelActivityDetected){rfm.OnCadDone(channelActivityDetected);};
//------------------------------------------------------------------------------

RFM95W::RFM95W()
    : radio(NULL),
      indicationLed(LED_PIN),
      noise(NOISE_PIN)
{
    memset(receivedMessage, '\0', sizeof(receivedMessage));
    ledState = 0;
    timeOnAirSec = 0.3;
    indicationLed = 1;
    messageNumber = NODE_ID;
};

void RFM95W::OnLedTick()
{
    if(ledState<6) {
        indicationLed = !indicationLed;
    } else {
        ledState = 0;
        indicationLed = 1;
        ledTicker.detach();
    }
    ledState++;
}

void RFM95W::SendMessage()
{
    snprintf((char *)ack, 3, "%d%d%c",NODE_ID, sendBuffer[0]-'0', messageNumber);
    radio.Send( sendBuffer, 10 );       // poslem len 10 bajtov
}

void RFM95W::SendAck(uint8_t addr, uint8_t messageNumber)
{
    uint8_t ack[3];
    snprintf((char *)ack, sizeof(ack), "%d%d%c", addr, NODE_ID, messageNumber);
    PC.printf("Sending Ack : %s \r\n",ack);
    radio.Send(ack, 3);
};

float RFM95W::CalculateRandomTime()
{
    uint8_t number;
    while(number == 0) {number = rand() % 1200;}
    return (timeOnAirSec * (number / 200.0));
};

void RFM95W::OnCheckAck()
{
    if((receivedAck == false) && (sendCounter < MAX_RESENDS))
    {
        sendTicker.attach(callback(this,&RFM95W::OnSendAgain), CalculateRandomTime());
/*        NumberOfFailSends++;
        if(NumberOfFailSends >=3 )
        {
//            MessageAlter = !MessageAlter;           // ????????????????????????????????????????????????????????????????????????????????????????????????????????
           NumberOfFailSends = 0;
           sampleTicker.detach();
           sampleTicker.attach(&onSampleTick,15.0);          // kazdych 15s
        }
*/
    }
    ackTicker.detach();
};

void RFM95W::OnSendAgain()
{
    SendMessage();
    sendCounter++;
    sendTicker.detach();
};

void RFM95W::OnTxDone( void )
{
    radio.Sleep();
    receivedAck = false;
    ackTicker.attach(callback(this,&RFM95W::OnCheckAck),timeOnAirSec*3);
    radio.Rx(0);
};

void RFM95W::OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
{
    radio.Sleep();
//    debug("%d \r\n", payload[0]-'0');
    if(payload[0]-'0' == NODE_ID) {
        if( strncmp( ( const char* )payload, ( const char* )ack, 3 ) == 0 ) 
        {
            PC.printf("Received Ack : %s \r\n",ack);
            ledTicker.attach(callback(this,&RFM95W::OnLedTick), LED_BLIK_PERIOD);    
            indicationLed=0;
            messageNumber++;
            if(messageNumber>255)
                messageNumber = 0;
            radio.Rx(0); 
            return;
        }  
        // moje ID - adresa brany, konverzia na cislo     
        uint8_t MsgFrom = payload[1]-'0';           // konverzia na cislo
        SendAck(MsgFrom,payload[2]);
        PC.printf("MSG from : %d , message number received= %d \r\n",MsgFrom,payload[2]);
        if(payload[2] == messageNumbers[MsgFrom])
        {
            PC.printf("--------------------- Ta ista sprava -------------------- \r\n");
            radio.Rx(0);
            return;
        }
        messageNumbers[MsgFrom] = payload[2];
        
        payload[2] = 48;        // ASCII hodnota cisla 0
        PC.printf("Message number saved= %d \r\n",messageNumbers[MsgFrom]);
        snprintf((char *)receivedMessage, BUFF_SIZE, "%d|%d|%s|\r\n", rssi, snr, payload);

//        debug_if( DEBUG_MESSAGE, "> OnRxDone\n\r" );
  
        return;
    }
    radio.Rx(0);                  // som zakomentil :P
};

void RFM95W::OnTxTimeout( void )
{
    radio.Sleep();
    Init();
//    radio.Rx(0);
};

void RFM95W::OnRxTimeout( void )
{
    radio.Sleep();
    radio.Rx(0);
};

void RFM95W::OnRxError( void )
{
    radio.Sleep();
    PC.printf("Chyba prijatia ! \r\n");
    radio.Rx(0);
};

void RFM95W::OnCadDone( bool channelActivityDetected ){};

void RFM95W::SendValue(uint8_t addr, float value)
{
    snprintf((char *)sendBuffer, BUFF_SIZE, "%d%d%c|%.2f|",GATEWAY_ID, NODE_ID, messageNumber, value);
    sendCounter = 0;
    receivedAck = false;
    SendMessage();
};

void RFM95W::Init( void )
{
    PC.printf( "\n\n\r------- RFM95W GATEWAY -------\n\r" );
    // Initialize Radio driver
    radioEvents.TxDone = TxDone;
    radioEvents.RxDone = RxDone;
    radioEvents.RxError = RxError;
    radioEvents.TxTimeout = TxTimeout;
    radioEvents.RxTimeout = RxTimeout;
    radioEvents.CadDone = CadDone;
    radio.Init( &radioEvents );
    // verify the connection with the board
    while( radio.Read( REG_VERSION ) == 0x00  ) {
        PC.printf( "Radiovy modul nie je pripojeny!\n\r", NULL );
        wait(1);
    }

//    debug_if( ( DEBUG_MESSAGE & ( Radio.DetectBoardType( ) == SX1276MB1LAS ) ) , "\n\r        > TYP: RFM95W < \n\r" );
//    debug_if( ( DEBUG_MESSAGE & ( Radio.DetectBoardType( ) == SX1276MB1MAS ) ) , "\n\r        > TYP: RFM95W < \n\r" );
    radio.SetChannel( RF_FREQUENCY );
#if USE_MODEM_LORA == 1

//    debug_if( LORA_FHSS_ENABLED, "\n\r        > LORA FHSS Mod < \n\n\r");
//    debug_if( !LORA_FHSS_ENABLED, "\n\r        > LORA Mod < \n\n\r");
    PC.printf("\n\r        > LORA Mod <        \n\n\r");
    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, 2000000 );

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

#elif USE_MODEM_FSK == 1

    PC.printf("\n\r        > FSK Mod <        \n\n\r");
    radio.SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0,
                       FSK_DATARATE, 0,
                       FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON,
                       FSK_CRC_ENABLED, 0, 0, 0, 2000000 );

    radio.SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE,
                       0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH,
                       0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, FSK_CRC_ENABLED,
                       0, 0, false, true );

#else

#error "Nie je definovany typ modemu."

#endif
    // Konfiguracia pre moznost max. vysielacieho vykonu
    uint8_t paConfig;
    paConfig = radio.Read( REG_PACONFIG );
    paConfig |= RF_PACONFIG_PASELECT_PABOOST;
    radio.Write( REG_PACONFIG, paConfig );
      
    PC.printf("________Start aplikacie________\r\n" );
    timeOnAirSec = (radio.TimeOnAir( MODEM_LORA, 10)/1000.0);              // time on air v ms
    PC.printf( "\n\n\r------- Time on air : %f sec. -------\n\r", timeOnAirSec);
    indicationLed = 1;
    InitRandom();
    messageNumber = rand();
    for(uint16_t i = 0; i < MAX_DEVICES;i++)
        messageNumbers[i]=rand();
    radio.Rx(0);
};

void RFM95W::InitRandom()
{
    uint32_t seed;
    uint8_t loops = 3;
    for (int i=0; i<(32*loops); i++) {
        seed ^= noise.read_u16();
        if (seed & 1<31) { // shift left and wrap.
            seed <<= 1;
            seed |= 1;
        } else
            seed <<= 1;
    }
    srand(seed);
};