src/lmic/lmic_eu868.c
///
/// \brief change the TX channel given the desired tx time.
///
/// \param [in] now is the time at which we want to transmit. In fact, it's always
///     the current time.
///
/// \returns the actual time at which we can transmit. \c LMIC.txChnl is set to the
///     selected channel.
///
/// \details
///     We scan all the channels, creating a mask of all enabled channels that are
///     feasible at the earliest possible time. We then randomly choose one from
///     that, updating the shuffle mask.
///
///     One sublety is that we have to cope with an artifact of the shuffler.
///     It will zero out bits for candidates that are real candidates, but
///     not in the time window, and not consider them as early as it should.
///     So we keep a mask of all feasible channels, and make sure that they
///     remain set in the shuffle mask if appropriate.
///
\brief change the TX channel given the desired tx time.
\param [in] now is the time at which we want to transmit. In fact, it's always
the current time.

\returns the actual time at which we can transmit. \c LMIC.txChnl is set to the
selected channel.

\details
We scan all the channels, creating a mask of all enabled channels that are
feasible at the earliest possible time. We then randomly choose one from
that, updating the shuffle mask.

One sublety is that we have to cope with an artifact of the shuffler.
It will zero out bits for candidates that are real candidates, but
not in the time window, and not consider them as early as it should.
So we keep a mask of all feasible channels, and make sure that they
remain set in the shuffle mask if appropriate.
\ brief change the TX channel given the desired tx time . \ param [ in ] now is the time at which we want to transmit . In fact it ' s always the current time . \ returns the actual time at which we can transmit . \ c LMIC . txChnl is set to the selected channel . \ details We scan all the channels creating a mask of all enabled channels that are feasible at the earliest possible time . We then randomly choose one from that updating the shuffle mask . One sublety is that we have to cope with an artifact of the shuffler . It will zero out bits for candidates that are real candidates but not in the time window and not consider them as early as it should . So we keep a mask of all feasible channels and make sure that they remain set in the shuffle mask if appropriate .
ostime_t LMICeu868_nextTx(ostime_t now) {
        ostime_t mintime = now + sec2osticks(28800);
        u2_t availMap;
        u2_t feasibleMap;
        u1_t bandMap;
        bandMap = 0;
        for (u1_t chnl = 0; chnl < MAX_CHANNELS; ++chnl) {
                u2_t chnlBit = 1 << chnl;
                if (LMIC.channelMap < chnlBit)
                        break;
                if ((LMIC.channelMap & chnlBit) == 0)
                        continue;
                if ((LMIC.channelDrMap[chnl] & (1 << (LMIC.datarate & 0xF))) == 0)
                        continue;
                u1_t const band = LMIC.channelFreq[chnl] & 0x3;
                u1_t const thisBandBit = 1 << band;
                if ((bandMap & thisBandBit) != 0)
                        continue;
                bandMap |= thisBandBit;
                if ((s4_t)(mintime - LMIC.bands[band].avail) > 0)
                        mintime = LMIC.bands[band].avail;
        }
        availMap = 0;
        feasibleMap = 0;
        for (u1_t chnl = 0; chnl < MAX_CHANNELS; ++chnl) {
                u2_t chnlBit = 1 << chnl;
                if (LMIC.channelMap < chnlBit)
                        break;
                if ((LMIC.channelMap & chnlBit) == 0)
                        continue;
                if ((LMIC.channelDrMap[chnl] & (1 << (LMIC.datarate & 0xF))) == 0)
                        continue;
                feasibleMap |= chnlBit;
                u1_t const band = LMIC.channelFreq[chnl] & 0x3;
                if ((s4_t)(LMIC.bands[band].avail - mintime) > 0)
                        continue;
                availMap |= chnlBit;
        }
        u2_t saveShuffleMap = LMIC.channelShuffleMap;
        int candidateCh = LMIC_findNextChannel(&LMIC.channelShuffleMap, &availMap, 1, LMIC.txChnl == 0xFF ? -1 : LMIC.txChnl);
        LMIC.channelShuffleMap |= saveShuffleMap & feasibleMap & ~availMap;
        if (candidateCh >= 0) {
                LMIC.txChnl = candidateCh;
        }
        return mintime;
}
ostime_t LMICeu868_nextTx ( ostime_t now ) { ostime_t mintime = now + sec2osticks ( 28800 ) ; u2_t availMap ; u2_t feasibleMap ; u1_t bandMap ; bandMap = 0 ; for ( u1_t chnl = 0 ; chnl < MAX_CHANNELS ; ++ chnl ) { u2_t chnlBit = 1 << chnl ; if ( LMIC . channelMap < chnlBit ) break ; if ( ( LMIC . channelMap & chnlBit ) == 0 ) continue ; if ( ( LMIC . channelDrMap [ chnl ] & ( 1 << ( LMIC . datarate & 0xF ) ) ) == 0 ) continue ; u1_t const band = LMIC . channelFreq [ chnl ] & 0x3 ; u1_t const thisBandBit = 1 << band ; if ( ( bandMap & thisBandBit ) != 0 ) continue ; bandMap |= thisBandBit ; if ( ( s4_t ) ( mintime - LMIC . bands [ band ] . avail ) > 0 ) mintime = LMIC . bands [ band ] . avail ; } availMap = 0 ; feasibleMap = 0 ; for ( u1_t chnl = 0 ; chnl < MAX_CHANNELS ; ++ chnl ) { u2_t chnlBit = 1 << chnl ; if ( LMIC . channelMap < chnlBit ) break ; if ( ( LMIC . channelMap & chnlBit ) == 0 ) continue ; if ( ( LMIC . channelDrMap [ chnl ] & ( 1 << ( LMIC . datarate & 0xF ) ) ) == 0 ) continue ; feasibleMap |= chnlBit ; u1_t const band = LMIC . channelFreq [ chnl ] & 0x3 ; if ( ( s4_t ) ( LMIC . bands [ band ] . avail - mintime ) > 0 ) continue ; availMap |= chnlBit ; } u2_t saveShuffleMap = LMIC . channelShuffleMap ; int candidateCh = LMIC_findNextChannel ( & LMIC . channelShuffleMap , & availMap , 1 , LMIC . txChnl == 0xFF ? -1 : LMIC . txChnl ) ; LMIC . channelShuffleMap |= saveShuffleMap & feasibleMap & ~ availMap ; if ( candidateCh >= 0 ) { LMIC . txChnl = candidateCh ; } return mintime ; }
\brief change the TX channel given the desired tx time.
\ brief change the TX channel given the desired tx time .
/*8h*/ // set mintime to the earliest time of all enabled channels // (can't just look at bands); and for a given channel, we // can't tell if we're ready till we've checked all possible // avail times. // none at any higher numbers? // not enabled? // not feasible? // already considered? // consider this band. // enabled, not considered, feasible: adjust the min time. // make a mask of candidates available for use // none at any higher numbers? // not enabled? // not feasible? // This channel is feasible. But might not be available. // not available yet? // ok: this is a candidate. // find the next available chennel. // restore bits in the shuffleMap that were on, but might have reset // if availMap was used to refresh shuffleMap. These are channels that // are feasble but not yet candidates due to band saturation // update the channel; otherwise we'll just use the // most recent one.