LoRa_Node_STM32F103C8T6

Dependencies:   mbed mbed-STM32F103C8T6 OneWireCRC_LoRa_Node SX1276Lib_LoRa_Node

RFM95W.cpp

Committer:
lukas_formanek
Date:
2018-04-30
Revision:
6:531b8dccca06
Parent:
5:6e899f5db65e
Child:
7:1aa5c96a8b9f

File content as of revision 6:531b8dccca06:

#include "RFM95W.h"

RFM95W rfm;

//--------------------------- 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;
    sendCounter = 0;
    receivedAck = false;
};

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

void RFM95W::SendMessage()
{
    snprintf((char *)ack, 3, "%c%c%c",NODE_ID, sendBuffer[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), "%c%c%c", addr, NODE_ID, messageNumber);
    PC.printf("Sending Ack : %s \r\n",ack);
    radio.Send(ack, 3);
};

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

void RFM95W::OnCheckAck()
{
    if((receivedAck == false) && (sendCounter < MAX_RESENDS))
        sendTicker.attach(this,&RFM95W::OnSendAgain, CalculateRandomTime());
    else if((receivedAck == false) && (sendCounter >= MAX_RESENDS)) {
        PC.printf("Message number : %d \r\n", messageNumber);
        messageNumber++;
        if(messageNumber>255)
            messageNumber = 0;
    }
    ackTicker.detach();
};

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

void RFM95W::OnTxDone( void )
{
    radio.Sleep();
    if(sendingAck)
        sendingAck = false;
    else {
        receivedAck = false;
        ackTicker.attach(this,&RFM95W::OnCheckAck,timeOnAirSec*3);
    }
    radio.Rx(0);
    PC.printf("on Tx done...\r\n");
};

void RFM95W::OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
{
    radio.Sleep();
    if(payload[0] == NODE_ID) {
        ledTicker.attach(this,&RFM95W::OnLedTick, LED_BLIK_PERIOD);
        if((size == 3) && (strncmp( ( const char* )payload, ( const char* )ack, 3 ) == 0) ) {
            receivedAck = true;
            PC.printf("Received Ack : %s \r\n",ack);
            messageNumber++;
            if(messageNumber>255)
                messageNumber = 0;
            radio.Rx(0);
            return;
        }
        sendingAck = true;
        uint8_t MsgFrom = payload[1];           // konverzia na cislo
        SendAck(MsgFrom,payload[2]);
        PC.printf("MSG from : %c , 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
        memmove(payload, payload+4, size - 4 + 1);
        PC.printf("Upraveny payload : %s\r\n",payload);
        snprintf((char *)receivedMessage, BUFF_SIZE, "%s", payload);
        ProcessReceivedMessage();
        return;
    }
    radio.Rx(0);                  // som zakomentil :P
};

void RFM95W::ProcessReceivedMessage()
{
        int time = atoi((const char*)receivedMessage);
        thermometer.StopPeriodicMeassure();
        thermometer.StartPeriodicMeassure(time);
        PC.printf("Skonvertovane cislo : %d \r\n",time);
};

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

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, "%c%c%c|%.2f|",addr, 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);
    }
    radio.SetChannel( RF_FREQUENCY );
#if USE_MODEM_LORA == 1
    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() % 256;
    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) {
            seed <<= 1;
            seed |= 1;
        } else
            seed <<= 1;
    }
    srand(seed);
};