Example #1
0
static void OnRxWindow2TimerEvent( TimerHandle_t xTimer )
{
    uint16_t symbTimeout = 5;   // DR_2, DR_1, DR_0
    uint32_t bandwidth = 0;   // LoRa 125 kHz

    TimerStop(&RxWindow2Timer);
    phyFlags.Bits.RxSlot = 2;

    if ( pLoRaDevice->ctrlFlags.Bits.ackRequested == 1 ) {
//        TimerSetValue(&AckTimeoutTimer,
//                ACK_TIMEOUT + randr(-ACK_TIMEOUT_RND, ACK_TIMEOUT_RND));
//        TimerStart (&AckTimeoutTimer);
    }

// For higher datarates, we increase the number of symbols generating a Rx Timeout
    if ( Rx2Dr >= DR_3 ) {   // DR_6, DR_5, DR_4, DR_3
        symbTimeout = 8;
    }
    if ( Rx2Dr == DR_6 ) {   // LoRa 250 kHz
        bandwidth = 1;
    }

    if ( pLoRaDevice->devClass != CLASS_C ) {
        LOG_TRACE("Open single Rx window 2 at %u ms (Channel : %u / DR: %u).",
                (uint32_t)(TimerGetCurrentTime() * portTICK_PERIOD_MS), Rx2ChannelFrequency, Rx2Dr);
        OpenReceptionWindow(Rx2ChannelFrequency, Rx2Dr, bandwidth, symbTimeout, false);
    } else {
        LOG_TRACE("Open continuous Rx window 2 at %u ms (Channel : %u / DR: %u).",
                (uint32_t)(TimerGetCurrentTime() * portTICK_PERIOD_MS), Rx2ChannelFrequency, Rx2Dr);
        OpenReceptionWindow(Rx2ChannelFrequency, Rx2Dr, bandwidth, symbTimeout, true);
    }
}
Example #2
0
static void OnRxWindow1TimerEvent( TimerHandle_t xTimer )
{
    uint16_t symbTimeout = 5;   // DR_2, DR_1, DR_0
    int8_t datarate = 0;
    uint32_t bandwidth = 0;   // LoRa 125 kHz

    TimerStop(&RxWindow1Timer);
    phyFlags.Bits.RxSlot = 1;

    datarate = pLoRaDevice->currDataRateIndex - Rx1DrOffset;
    if ( datarate < 0 ) {
        datarate = DR_0;
    }

// For higher datarates, we increase the number of symbols generating a Rx Timeout
    if ( datarate >= DR_3 ) {   // DR_6, DR_5, DR_4, DR_3
        symbTimeout = 8;
    }
    if ( datarate == DR_6 ) {   // LoRa 250 kHz
        bandwidth = 1;
    }
    LOG_TRACE("Open single Rx window 1 at %u ms (Channel : %u / DR: %u).",
            (uint32_t)(TimerGetCurrentTime() * portTICK_PERIOD_MS),
            Channels[pLoRaDevice->currChannelIndex].Frequency, datarate);
    OpenReceptionWindow(Channels[pLoRaDevice->currChannelIndex].Frequency, datarate, bandwidth,
            symbTimeout, false);
}
Example #3
0
static void OnRadioRxTimeout( void )
{
#if defined(LOG_LEVEL_TRACE)
    if ( phyFlags.Bits.RxSlot == 1 ) {
        LOG_TRACE("Receive window 1 timeout occurred at %u ms.",
                (uint32_t)(TimerGetCurrentTime() * portTICK_PERIOD_MS));
    } else if ( phyFlags.Bits.RxSlot == 2 ) {
        LOG_TRACE("Receive window 2 timeout occurred at %u ms.",
                (uint32_t)(TimerGetCurrentTime() * portTICK_PERIOD_MS));
    } else if ( phyFlags.Bits.RxSlot == 3 ) {
        LOG_TRACE("Time synchronized reception window timeout occurred.");
    }
#endif

    phyStatus = PHY_TIMEOUT;
    phyFlags.Bits.RxDone = 0;
}
Example #4
0
static void OnCadDone( bool channelActivityDetected )
{
#if defined(LOG_LEVEL_TRACE)
    uint64_t curTime = TimerGetCurrentTime();
#endif
    Radio.Sleep();
    if ( !channelActivityDetected ) {
        LOG_TRACE("Channel clear. Send packet now (%d%d)", *(((int*) (&curTime)) + 1), curTime);
//        Radio.Send(LoRaMacBuffer, LoRaMacBufferPktLen);
    }
}
Example #5
0
bool RegionCN470ATxConfig( TxConfigParams_t *txConfig, int8_t *txPower, TimerTime_t *txTimeOnAir )
{
    RadioModems_t modem;

    uint32_t frequency;
    uint16_t preambleLen;
    bool iqInverted;
    TimerTime_t curTime = TimerGetCurrentTime( );

    int8_t phyDr = DataratesCN470A[txConfig->Datarate];

    int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, Bands[TxChannels[txConfig->Channel].Band].TxMaxPower,
                                          txConfig->Datarate, ChannelsMask );
    uint32_t bandwidth = GetBandwidth( txConfig->Datarate );
    int8_t phyTxPower = 0;

    // Calculate physical TX power
    phyTxPower = RegionCommonComputeTxPower( txPowerLimited, txConfig->MaxEirp, txConfig->AntennaGain );

    if (txConfig->NodeWorkMode == NODE_MODE_REPEATER) {
        frequency = txConfig->RepeaterFrequency;
        preambleLen = PreambleLenthCN470A[txConfig->Datarate];
        iqInverted = true;
    } else {
        frequency = TxChannels[txConfig->Channel].Frequency;
        preambleLen = 8;
        iqInverted = false;
    }

    // Setup the radio frequency
    Radio.SetChannel( frequency);

    if ( txConfig->Datarate == DR_7 ) {
        // High Speed FSK channel
        modem = MODEM_FSK;
        Radio.SetTxConfig( modem, phyTxPower, 25e3, bandwidth, phyDr * 1e3, 0, 5, false, true, 0, 0, false, 3e3 );
    } else {
        modem = MODEM_LORA;
        Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, preambleLen, false, true, 0, 0, iqInverted, 3e3 );
    }
    // Setup maximum payload lenght of the radio driver
    Radio.SetMaxPayloadLength( modem, txConfig->PktLen );
    // Get the time-on-air of the next tx frame
    *txTimeOnAir = Radio.TimeOnAir( modem,  txConfig->PktLen );

    *txPower = txConfig->TxPower;

    DBG_LINKWAN("Tx, Band %d, Freq: %d,DR: %d, len: %d, duration %d, at %d\r\n",
                TxFreqBandNum, frequency, txConfig->Datarate, txConfig->PktLen, *txTimeOnAir, curTime);
    return true;
}
Example #6
0
static void OnRadioTxDone( void )
{
    TimerTime_t curTime = TimerGetCurrentTime();

    LOG_TRACE("Transmitted successfully (%u ms).", (uint32_t)(curTime * portTICK_PERIOD_MS));

// Update Band Time OFF
    Bands[Channels[pLoRaDevice->currChannelIndex].Band].LastTxDoneTime = curTime;
    if ( pLoRaDevice->dbgFlags.Bits.dutyCycleCtrlOff == 0 ) {
        Bands[Channels[pLoRaDevice->currChannelIndex].Band].TimeOff = TxTimeOnAir
                * Bands[Channels[pLoRaDevice->currChannelIndex].Band].DCycle - TxTimeOnAir;
    } else {
        Bands[Channels[pLoRaDevice->currChannelIndex].Band].TimeOff = 0;
    }
// Update Agregated Time OFF
    AggregatedLastTxDoneTime = curTime;
    AggregatedTimeOff = AggregatedTimeOff + (TxTimeOnAir * AggregatedDCycle - TxTimeOnAir);

    if ( phyFlags.Bits.TxType == LORAPHY_TXTYPE_ADVERTISING ) {
        /* Open advertising beacon reception window */

    } else if ( phyFlags.Bits.TxType == LORAPHY_TXTYPE_REGULAR
            && pLoRaDevice->dbgFlags.Bits.rxWindowsDisabled != 1 ) {
        TimerSetValue(&RxWindow1Timer, pLoRaDevice->rxWindow1Delay);
        TimerStart(&RxWindow1Timer);
        TimerSetValue(&RxWindow2Timer, pLoRaDevice->rxWindow2Delay);
        TimerStart(&RxWindow2Timer);
    } else {
        phyFlags.Bits.TxDone = 1;
    }

    /* Uplink message repetition is only valid for unconfirmed messages */
    if ( pLoRaDevice->ctrlFlags.Bits.ackPending == 0 ) {
        pLoRaDevice->nbRepCounter++;
    }
}
Example #7
0
bool RegionCN470ARxConfig( RxConfigParams_t *rxConfig, int8_t *datarate )
{
    RadioModems_t modem;
    int8_t dr = rxConfig->Datarate;
    uint8_t maxPayload = 0;
    int8_t phyDr = 0;
    uint32_t frequency = rxConfig->Frequency;

    TimerTime_t curTime = TimerGetCurrentTime( );
    bool iqInverted;

    if ( Radio.GetStatus( ) != RF_IDLE ) {
        return false;
    }

    if ( rxConfig->Window == 0 ) {
        // Apply window 1 frequency
        frequency = Channels[rxConfig->Channel].Frequency;
        // Apply the alternative RX 1 window frequency, if it is available
        if ( Channels[rxConfig->Channel].Rx1Frequency != 0 ) {
            frequency = Channels[rxConfig->Channel].Rx1Frequency;
        }
    }

    if (rxConfig->Window == 1) {
        if (get_lora_freq_type() == FREQ_TYPE_INTER) {
            frequency = 470300000 + (InterFreqRx2Chan[TxFreqBandNum]) * 200000;
        } else {
            frequency = 470300000 + (IntraFreqRx2Chan[TxFreqBandNum]) * 200000;
        }
    }

    // Read the physical datarate from the datarates table
    phyDr = DataratesCN470A[dr];

    if (rxConfig->NodeWorkMode == NODE_MODE_REPEATER) {
        frequency = rxConfig->RepeaterFrequency;
        iqInverted = false;
    } else {
        iqInverted = true;
    }

    Radio.SetChannel( frequency );

    // Radio configuration
    if ( dr == DR_7 ) {
        modem = MODEM_FSK;
        Radio.SetRxConfig( modem, 50e3, phyDr * 1e3, 0, 83.333e3, 5, rxConfig->WindowTimeout, false, 0, true, 0, 0, false,
                           rxConfig->RxContinuous );
    } else {
        modem = MODEM_LORA;
        Radio.SetRxConfig( modem, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0,
                           iqInverted, rxConfig->RxContinuous );
    }

    if ( rxConfig->RepeaterSupport == true ) {
        maxPayload = MaxPayloadOfDatarateRepeaterCN470A[dr];
    } else {
        maxPayload = MaxPayloadOfDatarateCN470A[dr];
    }
    Radio.SetMaxPayloadLength( modem, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );

    *datarate = (uint8_t) dr;
    rxConfig->Frequency = frequency;
    return true;
}
Example #8
0
/*
 * Set next transmission channel according to duty cycle boundries
 * unless it is a scheduled transmission on a specific channel (Class D)
 *
 * \return ERR_OK if a channel was set successfully
 */
static uint8_t SetNextChannel( void )
{
    uint8_t i = 0;
    uint8_t j = 0;
    uint8_t k = 0;
    uint8_t nbEnabledChannels = 0;
    uint8_t enabledChannels[LORA_MAX_NB_CHANNELS];
    TimerTime_t curTime = TimerGetCurrentTime();

    memset1(enabledChannels, 0, LORA_MAX_NB_CHANNELS);

// Update Aggregated duty cycle
    if ( AggregatedTimeOff < (curTime - AggregatedLastTxDoneTime) ) {
        AggregatedTimeOff = 0;
    }

// Update bands Time OFF
    TimerTime_t minTime = (TimerTime_t)(-1);
    for ( i = 0; i < LORA_MAX_NB_BANDS; i++ ) {
        if ( pLoRaDevice->dbgFlags.Bits.dutyCycleCtrlOff == 0 ) {
            if ( Bands[i].TimeOff < (curTime - Bands[i].LastTxDoneTime) ) {
                Bands[i].TimeOff = 0;
            }
            if ( Bands[i].TimeOff != 0 ) {
                minTime = MIN(Bands[i].TimeOff, minTime);
            }
        } else {
            minTime = 0;
            Bands[i].TimeOff = 0;
        }
    }

// Search how many channels are enabled
    for ( i = 0, k = 0; i < LORA_MAX_NB_CHANNELS; i += 16, k++ ) {
        for ( j = 0; j < 16; j++ ) {
            if ( (pLoRaDevice->channelsMask[k] & (1 << j)) != 0 ) {
                if ( Channels[i + j].Frequency == 0 ) {   // Check if the channel is enabled
                    continue;
                }
                if ( ((Channels[i + j].DrRange.Fields.Min <= pLoRaDevice->currChannelIndex)
                        && (pLoRaDevice->currDataRateIndex <= Channels[i + j].DrRange.Fields.Max))
                        == false ) {   // Check if the current channel selection supports the given datarate
                    continue;
                }
                if ( Bands[Channels[i + j].Band].TimeOff > 0 ) {   // Check if the band is available for transmission
                    continue;
                }
                if ( AggregatedTimeOff > 0 ) {   // Check if there is time available for transmission
                    continue;
                }
                enabledChannels[nbEnabledChannels++] = i + j;
            }
        }
    }
    if ( nbEnabledChannels > 0 ) {
        pLoRaDevice->currChannelIndex = enabledChannels[randr(0, nbEnabledChannels - 1)];
        return 0;
    }

    return ERR_OK;
}
Example #9
0
/*!
 * Check tx message queue to see if any messages are pending.
 *
 * \retvalue    ERR_OK          Transmission started successfully.
 *              ERR_NOTAVAIL    No channel available.
 *              ERR_VALUE       Invalid tx type selected.
 *              ERR_DISABLED    Device was remotely disable (MaxDCycle setting).
 *              ERR_RXEMPTY     Message queue is empty.
 */
static uint8_t CheckTx( void )
{
    LoRaPhy_ChannelParams_t channel;
    uint8_t flags;
    uint8_t TxDataBuffer[LORAPHY_BUFFER_SIZE];

    if ( GetTxMsg(TxDataBuffer, sizeof(TxDataBuffer)) == ERR_OK ) {
#if 0
        if ( SetNextChannel() != ERR_OK ) {
            return ERR_NOTAVAIL;
        }
#endif
        flags = LORAPHY_BUF_FLAGS(TxDataBuffer);
        channel = Channels[pLoRaDevice->currChannelIndex];

        if ( flags & LORAPHY_PACKET_FLAGS_JOIN_REQ ) {
            pLoRaDevice->rxWindow1Delay = JoinAcceptDelay1 - RADIO_WAKEUP_TIME;
            pLoRaDevice->rxWindow2Delay = JoinAcceptDelay2 - RADIO_WAKEUP_TIME;
        } else {
            pLoRaDevice->rxWindow1Delay = ReceiveDelay1 - RADIO_WAKEUP_TIME;
            pLoRaDevice->rxWindow2Delay = ReceiveDelay2 - RADIO_WAKEUP_TIME;
        }

        Radio.SetChannel(channel.Frequency);
        Radio.SetMaxPayloadLength(MODEM_LORA, LORAPHY_BUF_SIZE(TxDataBuffer));

        if ( pLoRaDevice->currDataRateIndex == DR_7 ) {   // High Speed FSK channel
            Radio.SetTxConfig(MODEM_FSK, TxPowers[pLoRaDevice->currTxPowerIndex], 25e3, 0,
                    Datarates[pLoRaDevice->currDataRateIndex] * 1e3, 0, 5, false, true, 0, 0, false,
                    TX_TIMEOUT);
            TxTimeOnAir = Radio.TimeOnAir(MODEM_FSK, LORAPHY_BUF_SIZE(TxDataBuffer));
        } else if ( pLoRaDevice->currDataRateIndex == DR_6 ) {   // High speed LoRa channel
            Radio.SetTxConfig(MODEM_LORA, TxPowers[pLoRaDevice->currTxPowerIndex], 0, 1,
                    Datarates[pLoRaDevice->currDataRateIndex], 1, 8, false, true, 0, 0, false,
                    TX_TIMEOUT);
            TxTimeOnAir = Radio.TimeOnAir(MODEM_LORA, LORAPHY_BUF_SIZE(TxDataBuffer));
        } else {   // Normal LoRa channel
            Radio.SetTxConfig(MODEM_LORA, TxPowers[pLoRaDevice->currTxPowerIndex], 0, 0,
                    Datarates[pLoRaDevice->currDataRateIndex], 1, 8, false, true, 0, 0, false,
                    TX_TIMEOUT);
            TxTimeOnAir = Radio.TimeOnAir(MODEM_LORA, LORAPHY_BUF_SIZE(TxDataBuffer));
        }

        if ( MaxDCycle == 255 ) {
            return ERR_DISABLED;
        }
        if ( MaxDCycle == 0 ) {
            AggregatedTimeOff = 0;
        }

        if ( MAX(Bands[channel.Band].TimeOff, AggregatedTimeOff) > (TimerGetCurrentTime()) ) {
            // Schedule transmission
            LOG_TRACE("Send in %d ticks on channel %d (DR: %u).",
                    MAX(Bands[channel.Band].TimeOff, AggregatedTimeOff), channel.Frequency,
                    pLoRaDevice->currDataRateIndex);
            vTaskDelay(
                    MAX(Bands[channel.Band].TimeOff, AggregatedTimeOff)
                            / MAX(Bands[channel.Band].TimeOff, AggregatedTimeOff));
        } else {
            // Send now
            LOG_TRACE("Sending at %u ms on channel %d (DR: %u).",
                    (uint32_t)(TimerGetCurrentTime() * portTICK_PERIOD_MS), channel.Frequency,
                    pLoRaDevice->currDataRateIndex);
            Radio.Send(LORAPHY_BUF_PAYLOAD_START(TxDataBuffer), LORAPHY_BUF_SIZE(TxDataBuffer));
//            LOG_DEBUG("Send data on channel with frequency %u Hz", channel.Frequency);
        }

        if ( (flags & LORAPHY_PACKET_FLAGS_FRM_MASK) == LORAPHY_PACKET_FLAGS_FRM_ADVERTISING ) {
            phyFlags.Bits.TxType = LORAPHY_TXTYPE_ADVERTISING;
        } else if ( (flags & LORAPHY_PACKET_FLAGS_FRM_MASK) == LORAPHY_PACKET_FLAGS_FRM_REGULAR ) {
            phyFlags.Bits.TxType = LORAPHY_TXTYPE_REGULAR;
        } else if ( (flags & LORAPHY_PACKET_FLAGS_FRM_MASK)
                == LORAPHY_PACKET_FLAGS_FRM_MULTICAST ) {
            phyFlags.Bits.TxType = LORAPHY_TXTYPE_MULTICAST;
        } else {
            return ERR_VALUE;
        }

        return ERR_OK;
    }
    return ERR_NOTAVAIL; /* no data to send? */
}