mirror of
				https://github.com/manuelbl/ttn-esp32.git
				synced 2025-10-31 02:30:35 +01:00 
			
		
		
		
	Latest LMIC code from https://github.com/mcci-catena/arduino-lmic
This commit is contained in:
		| @ -123,15 +123,7 @@ | ||||
| //#define DISABLE_MCMD_PING_SET // set ping freq, automatically disabled by DISABLE_PING | ||||
| //#define DISABLE_MCMD_BCNI_ANS // next beacon start, automatically disabled by DISABLE_BEACON | ||||
|  | ||||
| // In LoRaWAN, a gateway applies I/Q inversion on TX, and nodes do the | ||||
| // same on RX. This ensures that gateways can talk to nodes and vice | ||||
| // versa, but gateways will not hear other gateways and nodes will not | ||||
| // hear other nodes. By defining this macro in lmic_project_config.h, | ||||
| // this inversion is disabled and this node can hear other nodes. If | ||||
| // two nodes both have this macro set, they can talk to each other | ||||
| // (but they can no longer hear gateways). This should probably only | ||||
| // be used when debugging and/or when talking to the radio directly | ||||
| // (e.g. like in the "raw" example). | ||||
| // DEPRECATED(tmm@mcci.com); replaced by LMIC.noRXIQinversion (dynamic). Don't define this. | ||||
| //#define DISABLE_INVERT_IQ_ON_RX | ||||
|  | ||||
| // This allows choosing between multiple included AES implementations. | ||||
| @ -178,4 +170,24 @@ | ||||
| # define LMIC_ENABLE_DeviceTimeReq 0 | ||||
| #endif | ||||
|  | ||||
| // LMIC_ENABLE_user_events | ||||
| // Enable/disable support for programmable callbacks for events, rx, and tx. | ||||
| // This is always defined, and non-zero to enable.  Default is enabled. | ||||
| #if !defined(LMIC_ENABLE_user_events) | ||||
| # define LMIC_ENABLE_user_events 1 | ||||
| #endif | ||||
|  | ||||
| // LMIC_ENABLE_onEvent | ||||
| // Enable/disable support for out-call to user-supplied `onEvent()` function. | ||||
| // This is always defined, and non-zero to enable. Default is enabled. | ||||
| #if !defined(LMIC_ENABLE_onEvent) | ||||
| # define LMIC_ENABLE_onEvent 1 | ||||
| #endif | ||||
|  | ||||
| // LMIC_ENABLE_long_messages | ||||
| // LMIC certification requires that this be enabled. | ||||
| #if !defined(LMIC_ENABLE_long_messages) | ||||
| # define LMIC_ENABLE_long_messages 1        /* PARAM */ | ||||
| #endif | ||||
|  | ||||
| #endif // _lmic_config_h_ | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /* | ||||
|  * Copyright (c) 2014-2016 IBM Corporation. | ||||
|  * Copyright (c) 2016, 2018 MCCI Corporation. | ||||
|  * Copyright (c) 2016, 2018-2019 MCCI Corporation. | ||||
|  * All rights reserved. | ||||
|  * | ||||
|  *  Redistribution and use in source and binary forms, with or without | ||||
| @ -33,10 +33,17 @@ | ||||
| # include "oslmic_types.h" | ||||
| #endif | ||||
|  | ||||
| #ifndef _lmic_env_h_ | ||||
| # include "lmic_env.h" | ||||
| #endif | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C"{ | ||||
| #endif | ||||
|  | ||||
| // The type of an optional user-defined failure handler routine | ||||
| typedef void LMIC_ABI_STD hal_failure_handler_t(const char* const file, const uint16_t line); | ||||
|  | ||||
| /* | ||||
|  * initialize hardware (IO, SPI, TIMER, IRQ). | ||||
|  * This API is deprecated as it uses the const global lmic_pins, | ||||
| @ -87,6 +94,11 @@ void hal_disableIRQs (void); | ||||
|  */ | ||||
| void hal_enableIRQs (void); | ||||
|  | ||||
| /* | ||||
|  * return CPU interrupt nesting count | ||||
|  */ | ||||
| uint8_t hal_getIrqLevel (void); | ||||
|  | ||||
| /* | ||||
|  * put system and CPU in low-power mode, sleep until interrupt. | ||||
|  */ | ||||
| @ -116,6 +128,12 @@ u1_t hal_checkTimer (u4_t targettime); | ||||
|  */ | ||||
| void hal_failed (const char *file, u2_t line); | ||||
|  | ||||
| /* | ||||
|  * set a custom hal failure handler routine. The default behaviour, defined in | ||||
|  * hal_failed(), is to halt by looping infintely. | ||||
|  */ | ||||
| void hal_set_failure_handler(const hal_failure_handler_t* const); | ||||
|  | ||||
| /* | ||||
|  * get the calibration value for radio_rssi | ||||
|  */ | ||||
|  | ||||
							
								
								
									
										633
									
								
								src/lmic/lmic.c
									
									
									
									
									
								
							
							
						
						
									
										633
									
								
								src/lmic/lmic.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										227
									
								
								src/lmic/lmic.h
									
									
									
									
									
								
							
							
						
						
									
										227
									
								
								src/lmic/lmic.h
									
									
									
									
									
								
							| @ -105,7 +105,7 @@ extern "C"{ | ||||
| #define ARDUINO_LMIC_VERSION_CALC(major, minor, patch, local)	\ | ||||
| 	(((major) << 24u) | ((minor) << 16u) | ((patch) << 8u) | (local)) | ||||
|  | ||||
| #define	ARDUINO_LMIC_VERSION	ARDUINO_LMIC_VERSION_CALC(2, 3, 2, 0)	/* v2.3.2 */ | ||||
| #define	ARDUINO_LMIC_VERSION	ARDUINO_LMIC_VERSION_CALC(2, 3, 2, 50)	/* v2.3.2.50 */ | ||||
|  | ||||
| #define	ARDUINO_LMIC_VERSION_GET_MAJOR(v)	\ | ||||
| 	(((v) >> 24u) & 0xFFu) | ||||
| @ -122,14 +122,17 @@ extern "C"{ | ||||
| //! Only For Antenna Tuning Tests ! | ||||
| //#define CFG_TxContinuousMode 1 | ||||
|  | ||||
| enum { MAX_FRAME_LEN      =  64 };   //!< Library cap on max frame length | ||||
| // since this was annouunced as the API variable, we keep it. But it's not used, | ||||
| // MAX_LEN_FRAME is what the code uses. | ||||
| enum { MAX_FRAME_LEN      =  MAX_LEN_FRAME };   //!< Library cap on max frame length | ||||
|  | ||||
| enum { TXCONF_ATTEMPTS    =   8 };   //!< Transmit attempts for confirmed frames | ||||
| enum { MAX_MISSED_BCNS    =  20 };   // threshold for triggering rejoin requests | ||||
| enum { MAX_RXSYMS         = 100 };   // stop tracking beacon beyond this | ||||
|  | ||||
| enum { LINK_CHECK_CONT    =  12 ,    // continue with this after reported dead link | ||||
|        LINK_CHECK_DEAD    =  24 ,    // after this UP frames and no response from NWK assume link is dead | ||||
|        LINK_CHECK_INIT    = -12 ,    // UP frame count until we inc datarate | ||||
| enum { LINK_CHECK_CONT    =  0  ,    // continue with this after reported dead link | ||||
|        LINK_CHECK_DEAD    =  32 ,    // after this UP frames and no response to ack from NWK assume link is dead (ADR_ACK_DELAY) | ||||
|        LINK_CHECK_INIT    = -64 ,    // UP frame count until we ask for ack (ADR_ACK_LIMIT) | ||||
|        LINK_CHECK_OFF     =-128 };   // link check disabled | ||||
|  | ||||
| enum { TIME_RESYNC        = 6*128 }; // secs | ||||
| @ -153,12 +156,23 @@ struct band_t { | ||||
| }; | ||||
| TYPEDEF_xref2band_t; //!< \internal | ||||
|  | ||||
| struct lmic_saved_adr_state_s { | ||||
|     u4_t        channelFreq[MAX_CHANNELS]; | ||||
|     u2_t        channelMap; | ||||
| }; | ||||
|  | ||||
| #elif CFG_LMIC_US_like  // US915 spectrum ================================================= | ||||
|  | ||||
| enum { MAX_XCHANNELS = 2 };      // extra channels in RAM, channels 0-71 are immutable | ||||
|  | ||||
| struct lmic_saved_adr_state_s { | ||||
|     u2_t        channelMap[(72+MAX_XCHANNELS+15)/16];  // enabled bits | ||||
| }; | ||||
|  | ||||
| #endif // ========================================================================== | ||||
|  | ||||
| typedef struct lmic_saved_adr_state_s   lmic_saved_adr_state_t; | ||||
|  | ||||
| // Keep in sync with evdefs.hpp::drChange | ||||
| enum { DRCHG_SET, DRCHG_NOJACC, DRCHG_NOACK, DRCHG_NOADRACK, DRCHG_NWKCMD }; | ||||
| enum { KEEP_TXPOW = -128 }; | ||||
| @ -189,14 +203,14 @@ enum { BCN_NONE    = 0x00,   //!< No beacon received | ||||
| //! Information about the last and previous beacons. | ||||
| struct bcninfo_t { | ||||
|     ostime_t txtime;  //!< Time when the beacon was sent | ||||
|     u4_t     time;    //!< GPS time in seconds of last beacon (received or surrogate) | ||||
|     s4_t     lat;     //!< Lat field of last beacon (valid only if BCN_FULL set) | ||||
|     s4_t     lon;     //!< Lon field of last beacon (valid only if BCN_FULL set) | ||||
|     s1_t     rssi;    //!< Adjusted RSSI value of last received beacon | ||||
|     s1_t     snr;     //!< Scaled SNR value of last received beacon | ||||
|     u1_t     flags;   //!< Last beacon reception and tracking states. See BCN_* values. | ||||
|     u4_t     time;    //!< GPS time in seconds of last beacon (received or surrogate) | ||||
|     // | ||||
|     u1_t     info;    //!< Info field of last beacon (valid only if BCN_FULL set) | ||||
|     s4_t     lat;     //!< Lat field of last beacon (valid only if BCN_FULL set) | ||||
|     s4_t     lon;     //!< Lon field of last beacon (valid only if BCN_FULL set) | ||||
| }; | ||||
| #endif // !DISABLE_BEACONS | ||||
|  | ||||
| @ -235,7 +249,7 @@ enum _ev_t { EV_SCAN_TIMEOUT=1, EV_BEACON_FOUND, | ||||
|              EV_JOINED, EV_RFU1, EV_JOIN_FAILED, EV_REJOIN_FAILED, | ||||
|              EV_TXCOMPLETE, EV_LOST_TSYNC, EV_RESET, | ||||
|              EV_RXCOMPLETE, EV_LINK_DEAD, EV_LINK_ALIVE, EV_SCAN_FOUND, | ||||
|              EV_TXSTART }; | ||||
|              EV_TXSTART, EV_TXCANCELED, EV_RXSTART, EV_JOIN_TXCOMPLETE }; | ||||
| typedef enum _ev_t ev_t; | ||||
|  | ||||
| enum { | ||||
| @ -243,6 +257,12 @@ enum { | ||||
|         MAX_CLOCK_ERROR = 65536, | ||||
| }; | ||||
|  | ||||
| // callbacks for client alerts. | ||||
| // types and functions are always defined, to reduce #ifs in example code and libraries. | ||||
| typedef void LMIC_ABI_STD lmic_rxmessage_cb_t(void *pUserData, uint8_t port, const uint8_t *pMessage, size_t nMessage); | ||||
| typedef void LMIC_ABI_STD lmic_txmessage_cb_t(void *pUserData, int fSuccess); | ||||
| typedef void LMIC_ABI_STD lmic_event_cb_t(void *pUserData, ev_t e); | ||||
|  | ||||
| // network time request callback function | ||||
| // defined unconditionally, because APIs and types can't change based on config. | ||||
| // This is called when a time-request succeeds or when we get a downlink | ||||
| @ -272,26 +292,108 @@ enum lmic_request_time_state_e { | ||||
|  | ||||
| typedef u1_t lmic_request_time_state_t; | ||||
|  | ||||
| /* | ||||
|  | ||||
| Structure:  lmic_client_data_t | ||||
|  | ||||
| Function: | ||||
|         Holds LMIC client data that must live through LMIC_reset(). | ||||
|  | ||||
| Description: | ||||
|         There are a variety of client registration linkage items that | ||||
|         must live through LMIC_reset(), because LMIC_reset() is called | ||||
|         at frame rollover time.  We group them together into a structure | ||||
|         to make copies easy. | ||||
|  | ||||
| */ | ||||
|  | ||||
| //! abstract type for collection of client data that survives LMIC_reset(). | ||||
| typedef struct lmic_client_data_s lmic_client_data_t; | ||||
|  | ||||
| //! contents of lmic_client_data_t | ||||
| struct lmic_client_data_s { | ||||
|  | ||||
|     /* pointer-width things come first */ | ||||
| #if LMIC_ENABLE_DeviceTimeReq | ||||
|     lmic_request_network_time_cb_t *pNetworkTimeCb; //! call-back routine for network time | ||||
|     void        *pNetworkTimeUserData;              //! call-back data for network time. | ||||
| #endif | ||||
|  | ||||
| #if LMIC_ENABLE_user_events | ||||
|     lmic_event_cb_t     *eventCb;           //! user-supplied callback function for events. | ||||
|     void                *eventUserData;     //! data for eventCb | ||||
|     lmic_rxmessage_cb_t *rxMessageCb;       //! user-supplied message-received callback | ||||
|     void                *rxMessageUserData; //! data for rxMessageCb | ||||
|     lmic_txmessage_cb_t *txMessageCb;       //! transmit-complete message handler; reset on each tx complete. | ||||
|     void                *txMessageUserData; //! data for txMessageCb. | ||||
| #endif // LMIC_ENABLE_user_events | ||||
|  | ||||
|     /* next we have things that are (u)int32_t */ | ||||
|     /* none at the moment */ | ||||
|  | ||||
|     /* next we have things that are (u)int16_t */ | ||||
|  | ||||
|     u2_t        clockError;                 //! Inaccuracy in the clock. CLOCK_ERROR_MAX represents +/-100% error | ||||
|  | ||||
|     /* finally, things that are (u)int8_t */ | ||||
|     /* none at the moment */ | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  | ||||
| Structure:  lmic_t | ||||
|  | ||||
| Function: | ||||
|         Provides the instance data for the LMIC. | ||||
|  | ||||
| */ | ||||
|  | ||||
| struct lmic_t { | ||||
|     // client setup data, survives LMIC_reset(). | ||||
|     lmic_client_data_t  client; | ||||
|  | ||||
|     // the OS job object. pointer alignment. | ||||
|     osjob_t     osjob; | ||||
|  | ||||
| #if !defined(DISABLE_BEACONS) | ||||
|     bcninfo_t   bcninfo;      // Last received beacon info | ||||
| #endif | ||||
|  | ||||
| #if !defined(DISABLE_PING) | ||||
|     rxsched_t   ping;         // pingable setup | ||||
| #endif | ||||
|  | ||||
|     /* (u)int32_t things */ | ||||
|  | ||||
|     // Radio settings TX/RX (also accessed by HAL) | ||||
|     ostime_t    txend; | ||||
|     ostime_t    rxtime; | ||||
|  | ||||
|     // LBT info | ||||
|     ostime_t    lbt_ticks;      // ticks to listen | ||||
|     s1_t        lbt_dbmax;      // max permissible dB on our channel (eg -80) | ||||
|  | ||||
|     u4_t        freq; | ||||
|     s1_t        rssi; | ||||
|     s1_t        snr;            // LMIC.snr is SNR times 4 | ||||
|     rps_t       rps; | ||||
|     u1_t        rxsyms; | ||||
|     u1_t        dndr; | ||||
|     s1_t        txpow;     // dBm | ||||
|  | ||||
|     osjob_t     osjob; | ||||
|     ostime_t    globalDutyAvail; // time device can send again | ||||
|  | ||||
|     // Channel scheduling | ||||
|     u4_t        netid;        // current network id (~0 - none) | ||||
|     devaddr_t   devaddr; | ||||
|     u4_t        seqnoDn;      // device level down stream seqno | ||||
|     u4_t        seqnoUp; | ||||
|     u4_t        dn2Freq; | ||||
|  | ||||
| #if !defined(DISABLE_BEACONS) | ||||
|     ostime_t    bcnRxtime; | ||||
| #endif | ||||
|  | ||||
| #if LMIC_ENABLE_DeviceTimeReq | ||||
|     // put here for alignment, to reduce RAM use. | ||||
|     ostime_t    localDeviceTime;    // the LMIC.txend value for last DeviceTimeAns | ||||
|     lmic_gpstime_t netDeviceTime;   // the netDeviceTime for lastDeviceTimeAns | ||||
|                                     // zero ==> not valid. | ||||
| #endif // LMIC_ENABLE_DeviceTimeReq | ||||
|  | ||||
|     // Channel scheduling -- very much private | ||||
| #if CFG_LMIC_EU_like | ||||
|     band_t      bands[MAX_BANDS]; | ||||
|     u4_t        channelFreq[MAX_CHANNELS]; | ||||
| @ -304,45 +406,46 @@ struct lmic_t { | ||||
|     u2_t        activeChannels125khz; | ||||
|     u2_t        activeChannels500khz; | ||||
| #endif | ||||
|  | ||||
|     /* (u)int16_t things */ | ||||
|  | ||||
|     rps_t       rps;            // radio parameter selections: SF, BW, CodingRate, NoCrc, implicit hdr | ||||
|     u2_t        opmode;         // engineUpdate() operating mode flags | ||||
|     u2_t        devNonce;       // last generated nonce | ||||
|  | ||||
| #if !defined(DISABLE_BEACONS) | ||||
|     s2_t        drift;          // last measured drift | ||||
|     s2_t        lastDriftDiff; | ||||
|     s2_t        maxDriftDiff; | ||||
| #endif | ||||
|  | ||||
|     /* (u)int8_t things */ | ||||
|     s1_t        rssi; | ||||
|     s1_t        snr;            // LMIC.snr is SNR times 4 | ||||
|     u1_t        rxsyms; | ||||
|     u1_t        dndr; | ||||
|     s1_t        txpow;          // transmit dBm (administrative) | ||||
|     s1_t        radio_txpow;    // the radio driver's copy of txpow, limited by adrTxPow. | ||||
|     s1_t        lbt_dbmax;      // max permissible dB on our channel (eg -80) | ||||
|  | ||||
|     u1_t        txChnl;          // channel for next TX | ||||
|     u1_t        globalDutyRate;  // max rate: 1/2^k | ||||
|     ostime_t    globalDutyAvail; // time device can send again | ||||
|  | ||||
|     u4_t        netid;        // current network id (~0 - none) | ||||
|     u2_t        opmode; | ||||
|     u1_t        upRepeat;     // configured up repeat | ||||
|     s1_t        adrTxPow;     // ADR adjusted TX power | ||||
|     u1_t        datarate;     // current data rate | ||||
|     u1_t        errcr;        // error coding rate (used for TX only) | ||||
|     u1_t        rejoinCnt;    // adjustment for rejoin datarate | ||||
| #if !defined(DISABLE_BEACONS) | ||||
|     s2_t        drift;        // last measured drift | ||||
|     s2_t        lastDriftDiff; | ||||
|     s2_t        maxDriftDiff; | ||||
| #endif | ||||
|  | ||||
|     u2_t        clockError; // Inaccuracy in the clock. CLOCK_ERROR_MAX | ||||
|                             // represents +/-100% error | ||||
|     bit_t       initBandplanAfterReset; // cleared by LMIC_reset(), set by first join. See issue #244 | ||||
|  | ||||
|     u1_t        pendTxPort; | ||||
|     u1_t        pendTxConf;   // confirmed data | ||||
|     u1_t        pendTxLen;    // +0x80 = confirmed | ||||
|     u1_t        pendTxData[MAX_LEN_PAYLOAD]; | ||||
|  | ||||
|     u2_t        devNonce;     // last generated nonce | ||||
|     u1_t        nwkKey[16];   // network session key | ||||
|     u1_t        artKey[16];   // application router session key | ||||
|     devaddr_t   devaddr; | ||||
|     u4_t        seqnoDn;      // device level down stream seqno | ||||
|     u4_t        seqnoUp; | ||||
| #if LMIC_ENABLE_DeviceTimeReq | ||||
|     // put here for alignment, to reduce RAM use. | ||||
|     ostime_t    localDeviceTime;    // the LMIC.txend value for last DeviceTimeAns | ||||
|     lmic_gpstime_t netDeviceTime;   // the netDeviceTime for lastDeviceTimeAns | ||||
|                                     // zero ==> not valid. | ||||
|     lmic_request_network_time_cb_t *pNetworkTimeCb;	// call-back routine | ||||
|     void        *pNetworkTimeUserData; // call-back data | ||||
| #endif // LMIC_ENABLE_DeviceTimeReq | ||||
|  | ||||
|     u1_t        dnConf;       // dn frame confirm pending: LORA::FCT_ACK or 0 | ||||
|     s1_t        adrAckReq;    // counter until we reset data rate (0=off) | ||||
| @ -376,7 +479,6 @@ struct lmic_t { | ||||
|  | ||||
|     // 2nd RX window (after up stream) | ||||
|     u1_t        dn2Dr; | ||||
|     u4_t        dn2Freq; | ||||
| #if !defined(DISABLE_MCMD_DN2P_SET) | ||||
|     u1_t        dn2Ans;       // 0=no answer pend, 0x80+ACKs | ||||
| #endif | ||||
| @ -389,10 +491,6 @@ struct lmic_t { | ||||
| #if !defined(DISABLE_MCMD_PING_SET) && !defined(DISABLE_PING) | ||||
|     u1_t        pingSetAns;   // answer set cmd and ACK bits | ||||
| #endif | ||||
| #if !defined(DISABLE_PING) | ||||
|     rxsched_t   ping;         // pingable setup | ||||
| #endif | ||||
|  | ||||
|     // Public part of MAC state | ||||
|     u1_t        txCnt; | ||||
|     u1_t        txrxFlags;  // transaction flags (TX-RX combo) | ||||
| @ -403,11 +501,10 @@ struct lmic_t { | ||||
| #if !defined(DISABLE_BEACONS) | ||||
|     u1_t        bcnChnl; | ||||
|     u1_t        bcnRxsyms;    // | ||||
|     ostime_t    bcnRxtime; | ||||
|     bcninfo_t   bcninfo;      // Last received beacon info | ||||
| #endif | ||||
|  | ||||
|     u1_t        noRXIQinversion; | ||||
|     u1_t        saveIrqFlags;   // last LoRa IRQ flags | ||||
| }; | ||||
|  | ||||
| //! \var struct lmic_t LMIC | ||||
| @ -418,16 +515,19 @@ DECLARE_LMIC; //!< \internal | ||||
| #define DR_RANGE_MAP(drlo,drhi) (((u2_t)0xFFFF<<(drlo)) & ((u2_t)0xFFFF>>(15-(drhi)))) | ||||
| bit_t LMIC_setupBand (u1_t bandidx, s1_t txpow, u2_t txcap); | ||||
| bit_t LMIC_setupChannel (u1_t channel, u4_t freq, u2_t drmap, s1_t band); | ||||
| void  LMIC_disableChannel (u1_t channel); | ||||
| void  LMIC_enableSubBand(u1_t band); | ||||
| void  LMIC_enableChannel(u1_t channel); | ||||
| void  LMIC_disableSubBand(u1_t band); | ||||
| void  LMIC_selectSubBand(u1_t band); | ||||
| bit_t LMIC_disableChannel (u1_t channel); | ||||
| bit_t LMIC_enableSubBand(u1_t band); | ||||
| bit_t LMIC_enableChannel(u1_t channel); | ||||
| bit_t LMIC_disableSubBand(u1_t band); | ||||
| bit_t LMIC_selectSubBand(u1_t band); | ||||
|  | ||||
| void  LMIC_setDrTxpow   (dr_t dr, s1_t txpow);  // set default/start DR/txpow | ||||
| void  LMIC_setAdrMode   (bit_t enabled);        // set ADR mode (if mobile turn off) | ||||
|  | ||||
| #if !defined(DISABLE_JOIN) | ||||
| bit_t LMIC_startJoining (void); | ||||
| void  LMIC_tryRejoin    (void); | ||||
| void  LMIC_unjoin       (void); | ||||
| #endif | ||||
|  | ||||
| void  LMIC_shutdown     (void); | ||||
| @ -436,6 +536,7 @@ void  LMIC_reset        (void); | ||||
| void  LMIC_clrTxData    (void); | ||||
| void  LMIC_setTxData    (void); | ||||
| int   LMIC_setTxData2   (u1_t port, xref2u1_t data, u1_t dlen, u1_t confirmed); | ||||
| int   LMIC_sendWithCallback(u1_t port, xref2u1_t data, u1_t dlen, u1_t confirmed, lmic_txmessage_cb_t *pCb, void *pUserData); | ||||
| void  LMIC_sendAlive    (void); | ||||
|  | ||||
| #if !defined(DISABLE_BEACONS) | ||||
| @ -447,9 +548,6 @@ void  LMIC_disableTracking (void); | ||||
| void  LMIC_stopPingable  (void); | ||||
| void  LMIC_setPingable   (u1_t intvExp); | ||||
| #endif | ||||
| #if !defined(DISABLE_JOIN) | ||||
| void  LMIC_tryRejoin     (void); | ||||
| #endif | ||||
|  | ||||
| void LMIC_setSession (u4_t netid, devaddr_t devaddr, xref2u1_t nwkKey, xref2u1_t artKey); | ||||
| void LMIC_setLinkCheckMode (bit_t enabled); | ||||
| @ -462,11 +560,26 @@ void LMIC_getSessionKeys (u4_t *netid, devaddr_t *devaddr, xref2u1_t nwkKey, xre | ||||
| void LMIC_requestNetworkTime(lmic_request_network_time_cb_t *pCallbackfn, void *pUserData); | ||||
| int LMIC_getNetworkTimeReference(lmic_time_reference_t *pReference); | ||||
|  | ||||
| int LMIC_registerRxMessageCb(lmic_rxmessage_cb_t *pRxMessageCb, void *pUserData); | ||||
| int LMIC_registerEventCb(lmic_event_cb_t *pEventCb, void *pUserData); | ||||
|  | ||||
| // APIs for client half of compliance. | ||||
| typedef u1_t lmic_compliance_rx_action_t; | ||||
|  | ||||
| enum lmic_compliance_rx_action_e { | ||||
|     LMIC_COMPLIANCE_RX_ACTION_PROCESS = 0,  // process this message normally | ||||
|     LMIC_COMPLIANCE_RX_ACTION_START,        // enter compliance mode, discard this message | ||||
|     LMIC_COMPLIANCE_RX_ACTION_IGNORE,       // continue in compliance mode, discard this message | ||||
|     LMIC_COMPLIANCE_RX_ACTION_END           // exit compliance mode, discard this message | ||||
| }; | ||||
|  | ||||
| lmic_compliance_rx_action_t LMIC_complianceRxMessage(u1_t port, const u1_t *pMessage, size_t nMessage); | ||||
|  | ||||
| // Declare onEvent() function, to make sure any definition will have the | ||||
| // C conventions, even when in a C++ file. | ||||
| #if LMIC_ENABLE_onEvent | ||||
| DECL_ON_LMIC_EVENT; | ||||
|  | ||||
|  | ||||
| #endif /* LMIC_ENABLE_onEvent */ | ||||
|  | ||||
| // Special APIs - for development or testing | ||||
| // !!!See implementation for caveats!!! | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /* | ||||
| * Copyright (c) 2014-2016 IBM Corporation. | ||||
| * Copyright (c) 2017 MCCI Corporation. | ||||
| * Copyright (c) 2017, 2019 MCCI Corporation. | ||||
| * All rights reserved. | ||||
| * | ||||
| *  Redistribution and use in source and binary forms, with or without | ||||
| @ -138,7 +138,7 @@ int8_t LMICas923_pow2dBm(uint8_t mcmd_ladr_p1) { | ||||
| 			(mcmd_ladr_p1&MCMD_LADR_POW_MASK)>>MCMD_LADR_POW_SHIFT | ||||
| 			); | ||||
| 			 | ||||
| 	return adj; | ||||
| 	return LMICas923_getMaxEIRP(LMIC.txParam) + adj; | ||||
| } | ||||
|  | ||||
| // only used in this module, but used by variant macro dr2hsym(). | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /* | ||||
| * Copyright (c) 2014-2016 IBM Corporation. | ||||
| * Copyright (c) 2017 MCCI Corporation. | ||||
| * Copyright (c) 2017, 2019 MCCI Corporation. | ||||
| * All rights reserved. | ||||
| * | ||||
| *  Redistribution and use in source and binary forms, with or without | ||||
| @ -109,9 +109,11 @@ bit_t LMIC_setupChannel(u1_t chidx, u4_t freq, u2_t drmap, s1_t band) { | ||||
|         return 0; // all channels are hardwired. | ||||
| } | ||||
|  | ||||
| void LMIC_disableChannel(u1_t channel) { | ||||
| bit_t LMIC_disableChannel(u1_t channel) { | ||||
|         bit_t result = 0; | ||||
|         if (channel < 72) { | ||||
|                 if (ENABLED_CHANNEL(channel)) { | ||||
|                         result = 1; | ||||
|                         if (IS_CHANNEL_125khz(channel)) | ||||
|                                 LMIC.activeChannels125khz--; | ||||
|                         else if (IS_CHANNEL_500khz(channel)) | ||||
| @ -119,11 +121,14 @@ void LMIC_disableChannel(u1_t channel) { | ||||
|                 } | ||||
|                 LMIC.channelMap[channel >> 4] &= ~(1 << (channel & 0xF)); | ||||
|         } | ||||
|         return result; | ||||
| } | ||||
|  | ||||
| void LMIC_enableChannel(u1_t channel) { | ||||
| bit_t LMIC_enableChannel(u1_t channel) { | ||||
|         bit_t result = 0; | ||||
|         if (channel < 72) { | ||||
|                 if (!ENABLED_CHANNEL(channel)) { | ||||
|                         result = 1; | ||||
|                         if (IS_CHANNEL_125khz(channel)) | ||||
|                                 LMIC.activeChannels125khz++; | ||||
|                         else if (IS_CHANNEL_500khz(channel)) | ||||
| @ -131,42 +136,52 @@ void LMIC_enableChannel(u1_t channel) { | ||||
|                 } | ||||
|                 LMIC.channelMap[channel >> 4] |= (1 << (channel & 0xF)); | ||||
|         } | ||||
|         return result; | ||||
| } | ||||
|  | ||||
| void  LMIC_enableSubBand(u1_t band) { | ||||
| bit_t LMIC_enableSubBand(u1_t band) { | ||||
|         ASSERT(band < 8); | ||||
|         u1_t start = band * 8; | ||||
|         u1_t end = start + 8; | ||||
|         bit_t result = 0; | ||||
|  | ||||
|         // enable all eight 125 kHz channels in this subband | ||||
|         for (int channel = start; channel < end; ++channel) | ||||
|                 LMIC_enableChannel(channel); | ||||
|                 result |= LMIC_enableChannel(channel); | ||||
|  | ||||
|         // there's a single 500 kHz channel associated with | ||||
|         // each group of 8 125 kHz channels. Enable it, too. | ||||
|         LMIC_enableChannel(64 + band); | ||||
|         result |= LMIC_enableChannel(64 + band); | ||||
|         return result; | ||||
| } | ||||
| void  LMIC_disableSubBand(u1_t band) { | ||||
|  | ||||
| bit_t LMIC_disableSubBand(u1_t band) { | ||||
|         ASSERT(band < 8); | ||||
|         u1_t start = band * 8; | ||||
|         u1_t end = start + 8; | ||||
|         bit_t result = 0; | ||||
|  | ||||
|         // disable all eight 125 kHz channels in this subband | ||||
|         for (int channel = start; channel < end; ++channel) | ||||
|                 LMIC_disableChannel(channel); | ||||
|                 result |= LMIC_disableChannel(channel); | ||||
|  | ||||
|         // there's a single 500 kHz channel associated with | ||||
|         // each group of 8 125 kHz channels. Disable it, too. | ||||
|         LMIC_disableChannel(64 + band); | ||||
|         result |= LMIC_disableChannel(64 + band); | ||||
|         return result; | ||||
| } | ||||
| void  LMIC_selectSubBand(u1_t band) { | ||||
|  | ||||
| bit_t LMIC_selectSubBand(u1_t band) { | ||||
|         bit_t result = 0; | ||||
|  | ||||
|         ASSERT(band < 8); | ||||
|         for (int b = 0; b<8; ++b) { | ||||
|                 if (band == b) | ||||
|                         LMIC_enableSubBand(b); | ||||
|                         result |= LMIC_enableSubBand(b); | ||||
|                 else | ||||
|                         LMIC_disableSubBand(b); | ||||
|                         result |= LMIC_disableSubBand(b); | ||||
|         } | ||||
|         return result; | ||||
| } | ||||
|  | ||||
| void LMICau921_updateTx(ostime_t txbeg) { | ||||
| @ -213,6 +228,13 @@ void LMICau921_setRx1Params(void) { | ||||
|         LMIC.rps = dndr2rps(LMIC.dndr); | ||||
| } | ||||
|  | ||||
| void LMICau921_initJoinLoop(void) { | ||||
|         LMICuslike_initJoinLoop(); | ||||
|  | ||||
|         // initialize the adrTxPower. | ||||
|         LMIC.adrTxPow = 30; // dBm | ||||
|  | ||||
| } | ||||
|  | ||||
| // | ||||
| // END: AU921 related stuff | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /* | ||||
| * Copyright (c) 2014-2016 IBM Corporation. | ||||
| * Copyright (c) 2017 MCCI Corporation. | ||||
| * Copyright (c) 2017, 2019 MCCI Corporation. | ||||
| * All rights reserved. | ||||
| * | ||||
| *  Redistribution and use in source and binary forms, with or without | ||||
| @ -104,6 +104,10 @@ | ||||
| # error "LMICbandplan_setBcnRxParams() not defined by bandplan" | ||||
| #endif | ||||
|  | ||||
| #if !defined(LMICbandplan_canMapChannels) | ||||
| # error "LMICbandplan_canMapChannels() not defined by bandplan" | ||||
| #endif | ||||
|  | ||||
| #if !defined(LMICbandplan_mapChannels) | ||||
| # error "LMICbandplan_mapChannels() not defined by bandplan" | ||||
| #endif | ||||
| @ -143,6 +147,15 @@ | ||||
| #if !defined(LMICbandplan_init) | ||||
| # error "LMICbandplan_init() not defined by bandplan" | ||||
| #endif | ||||
|  | ||||
| #if !defined(LMICbandplan_saveAdrState) | ||||
| # error "LMICbandplan_saveAdrState() not defined by bandplan" | ||||
| #endif | ||||
|  | ||||
| #if !defined(LMICbandplan_compareAdrState) | ||||
| # error "LMICbandplan_compareAdrState() not defined by bandplan" | ||||
| #endif | ||||
|  | ||||
| // | ||||
| // Things common to lmic.c code | ||||
| // | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /* | ||||
| * Copyright (c) 2014-2016 IBM Corporation. | ||||
| * Copyright (c) 2017 MCCI Corporation. | ||||
| * Copyright (c) 2017, 2019 MCCI Corporation. | ||||
| * All rights reserved. | ||||
| * | ||||
| *  Redistribution and use in source and binary forms, with or without | ||||
| @ -26,8 +26,8 @@ | ||||
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| */ | ||||
|  | ||||
| #ifndef _lmic_as923_h_ | ||||
| # define _lmic_as923_h_ | ||||
| #ifndef _lmic_bandplan_as923_h_ | ||||
| # define _lmic_bandplan_as923_h_ | ||||
|  | ||||
| #ifndef _lmic_eu_like_h_ | ||||
| # include "lmic_eu_like.h" | ||||
| @ -112,4 +112,4 @@ void LMICas923_updateTx(ostime_t txbeg); | ||||
| ostime_t LMICas923_nextJoinTime(ostime_t now); | ||||
| #define LMICbandplan_nextJoinTime(now)     LMICas923_nextJoinTime(now) | ||||
|  | ||||
| #endif // _lmic_as923_h_ | ||||
| #endif // _lmic_bandplan_as923_h_ | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /* | ||||
| * Copyright (c) 2014-2016 IBM Corporation. | ||||
| * Copyright (c) 2017 MCCI Corporation. | ||||
| * Copyright (c) 2017, 2019 MCCI Corporation. | ||||
| * All rights reserved. | ||||
| * | ||||
| *  Redistribution and use in source and binary forms, with or without | ||||
| @ -26,12 +26,12 @@ | ||||
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| */ | ||||
|  | ||||
| #ifndef _lmic_au921_h_ | ||||
| # define _lmic_au921_h_ | ||||
| #ifndef _lmic_bandplan_au921_h_ | ||||
| # define _lmic_bandplan_au921_h_ | ||||
|  | ||||
| // preconditions for lmic_us_like.h | ||||
| #define LMICuslike_getFirst500kHzDR()   (AU921_DR_SF8C) | ||||
|  | ||||
| #define LMICuslike_getFirst500kHzDR()   (LORAWAN_DR6) | ||||
| #define	LMICuslike_getJoin125kHzDR()	(LORAWAN_DR2) | ||||
|  | ||||
| #ifndef _lmic_us_like_h_ | ||||
| # include "lmic_us_like.h" | ||||
| @ -46,7 +46,10 @@ ostime_t LMICau921_dr2hsym(uint8_t dr); | ||||
| #define dr2hsym(dr) LMICau921_dr2hsym(dr) | ||||
|  | ||||
|  | ||||
| #define LMICbandplan_getInitialDrJoin() (EU868_DR_SF7) | ||||
| #define LMICbandplan_getInitialDrJoin() (LORAWAN_DR2) | ||||
|  | ||||
| void LMICau921_initJoinLoop(void); | ||||
| #define LMICbandplan_initJoinLoop()     LMICau921_initJoinLoop() | ||||
|  | ||||
| void LMICau921_setBcnRxParams(void); | ||||
| #define LMICbandplan_setBcnRxParams() LMICau921_setBcnRxParams() | ||||
| @ -60,4 +63,4 @@ void LMICau921_setRx1Params(void); | ||||
| void LMICau921_updateTx(ostime_t txbeg); | ||||
| #define LMICbandplan_updateTx(txbeg)    LMICau921_updateTx(txbeg) | ||||
|  | ||||
| #endif // _lmic_au921_h_ | ||||
| #endif // _lmic_bandplan_au921_h_ | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /* | ||||
| * Copyright (c) 2014-2016 IBM Corporation. | ||||
| * Copyright (c) 2017 MCCI Corporation. | ||||
| * Copyright (c) 2017, 2019 MCCI Corporation. | ||||
| * All rights reserved. | ||||
| * | ||||
| *  Redistribution and use in source and binary forms, with or without | ||||
| @ -89,4 +89,7 @@ void LMICeu868_initDefaultChannels(bit_t join); | ||||
| ostime_t LMICeu868_nextJoinTime(ostime_t now); | ||||
| #define LMICbandplan_nextJoinTime(now)     LMICeu868_nextJoinTime(now) | ||||
|  | ||||
| void LMICeu868_setRx1Params(void); | ||||
| #define LMICbandplan_setRx1Params()     LMICeu868_setRx1Params() | ||||
|  | ||||
| #endif // _lmic_eu868_h_ | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /* | ||||
| * Copyright (c) 2014-2016 IBM Corporation. | ||||
| * Copyright (c) 2017 MCCI Corporation. | ||||
| * Copyright (c) 2017, 2019 MCCI Corporation. | ||||
| * All rights reserved. | ||||
| * | ||||
| *  Redistribution and use in source and binary forms, with or without | ||||
| @ -26,8 +26,8 @@ | ||||
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| */ | ||||
|  | ||||
| #ifndef _lmic_in866_h_ | ||||
| # define _lmic_in866_h_ | ||||
| #ifndef _lmic_bandplan_in866_h_ | ||||
| # define _lmic_bandplan_in866_h_ | ||||
|  | ||||
| #ifndef _lmic_eu_like_h_ | ||||
| # include "lmic_eu_like.h" | ||||
| @ -82,4 +82,7 @@ ostime_t LMICin866_nextJoinState(void); | ||||
| void LMICin866_initDefaultChannels(bit_t join); | ||||
| #define LMICbandplan_initDefaultChannels(join)  LMICin866_initDefaultChannels(join) | ||||
|  | ||||
| #endif // _lmic_in866_h_ | ||||
| void LMICin866_setRx1Params(void); | ||||
| #define LMICbandplan_setRx1Params()     LMICin866_setRx1Params() | ||||
|  | ||||
| #endif // _lmic_bandplan_in866_h_ | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /* | ||||
| * Copyright (c) 2014-2016 IBM Corporation. | ||||
| * Copyright (c) 2017 MCCI Corporation. | ||||
| * Copyright (c) 2017, 2019 MCCI Corporation. | ||||
| * All rights reserved. | ||||
| * | ||||
| *  Redistribution and use in source and binary forms, with or without | ||||
| @ -26,11 +26,12 @@ | ||||
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| */ | ||||
|  | ||||
| #ifndef _lmic_us915_h_ | ||||
| # define _lmic_us915_h_ | ||||
| #ifndef _lmic_bandplan_us915_h_ | ||||
| # define _lmic_bandplan_us915_h_ | ||||
|  | ||||
| // preconditions for lmic_us_like.h | ||||
| #define LMICuslike_getFirst500kHzDR()   (US915_DR_SF8C) | ||||
| #define LMICuslike_getFirst500kHzDR()   (LORAWAN_DR4) | ||||
| #define LMICuslike_getJoin125kHzDR()    (LORAWAN_DR0) | ||||
|  | ||||
| #ifndef _lmic_us_like_h_ | ||||
| # include "lmic_us_like.h" | ||||
| @ -45,7 +46,7 @@ ostime_t LMICus915_dr2hsym(uint8_t dr); | ||||
| #define dr2hsym(dr) LMICus915_dr2hsym(dr) | ||||
|  | ||||
|  | ||||
| #define LMICbandplan_getInitialDrJoin() (US915_DR_SF7) | ||||
| #define LMICbandplan_getInitialDrJoin() (LORAWAN_DR0) | ||||
|  | ||||
| void LMICus915_setBcnRxParams(void); | ||||
| #define LMICbandplan_setBcnRxParams() LMICus915_setBcnRxParams() | ||||
| @ -53,10 +54,13 @@ void LMICus915_setBcnRxParams(void); | ||||
| u4_t LMICus915_convFreq(xref2cu1_t ptr); | ||||
| #define LMICbandplan_convFreq(ptr)      LMICus915_convFreq(ptr) | ||||
|  | ||||
| void LMICus915_initJoinLoop(void); | ||||
| #define LMICbandplan_initJoinLoop()     LMICus915_initJoinLoop() | ||||
|  | ||||
| void LMICus915_setRx1Params(void); | ||||
| #define LMICbandplan_setRx1Params()     LMICus915_setRx1Params() | ||||
|  | ||||
| void LMICus915_updateTx(ostime_t txbeg); | ||||
| #define LMICbandplan_updateTx(txbeg)    LMICus915_updateTx(txbeg) | ||||
|  | ||||
| #endif // _lmic_us915_h_ | ||||
| #endif // _lmic_bandplan_us915_h_ | ||||
|  | ||||
| @ -214,4 +214,38 @@ Returns: | ||||
| # endif | ||||
| #endif | ||||
|  | ||||
| /* | ||||
|  | ||||
| Macro:	LMIC_DECLARE_FUNCTION_WEAK() | ||||
|  | ||||
| Function: | ||||
| 	Declare an external function as a weak reference. | ||||
|  | ||||
| Definition: | ||||
| 	#define LMIC_DECLARE_FUNCTION_WEAK(ReturnType, FunctionName, Params) ... | ||||
|  | ||||
| Description: | ||||
| 	This macro generates a weak reference to the specified function. | ||||
|  | ||||
| Example: | ||||
| 	LMIC_DECLARE_FUNCTION_WEAK(void, onEvent, (ev_t e)); | ||||
|  | ||||
| 	This saya that onEvent is a weak external reference. When calling | ||||
| 	onEvent, you must always first check whether it's supplied: | ||||
|  | ||||
| 	if (onEvent != NULL) | ||||
| 		onEvent(e); | ||||
|  | ||||
| Returns: | ||||
| 	This macro expands to a declaration, without a trailing semicolon. | ||||
|  | ||||
| Notes: | ||||
| 	This form allows for compilers that use _Pragma(weak, name) instead | ||||
| 	of inline attributes. | ||||
|  | ||||
| */ | ||||
|  | ||||
| #define LMIC_DECLARE_FUNCTION_WEAK(a_ReturnType, a_FunctionName, a_Params)	\ | ||||
| 	a_ReturnType __attribute__((__weak__)) a_FunctionName a_Params | ||||
|  | ||||
| #endif /* _lmic_env_h_ */ | ||||
| @ -1,6 +1,6 @@ | ||||
| /* | ||||
| * Copyright (c) 2014-2016 IBM Corporation. | ||||
| * Copyright (c) 2017 MCCI Corporation. | ||||
| * Copyright (c) 2017, 2019 MCCI Corporation. | ||||
| * All rights reserved. | ||||
| * | ||||
| *  Redistribution and use in source and binary forms, with or without | ||||
| @ -59,7 +59,7 @@ uint8_t LMICeu868_maxFrameLen(uint8_t dr) { | ||||
| } | ||||
|  | ||||
| static CONST_TABLE(s1_t, TXPOWLEVELS)[] = { | ||||
|         20, 14, 11, 8, 5, 2, 0,0, 0,0,0,0, 0,0,0,0 | ||||
|         16, 14, 12, 10, 8, 6, 4, 2, 0,0,0,0, 0,0,0,0 | ||||
| }; | ||||
|  | ||||
| int8_t LMICeu868_pow2dBm(uint8_t mcmd_ladr_p1) { | ||||
| @ -221,6 +221,28 @@ LMICeu868_txDoneFSK(ostime_t delay, osjobcb_t func) { | ||||
|         os_setTimedCallback(&LMIC.osjob, LMIC.rxtime - RX_RAMPUP, func); | ||||
| } | ||||
|  | ||||
| // set the Rx1 dndr, rps. | ||||
| void LMICeu868_setRx1Params(void) { | ||||
|     u1_t const txdr = LMIC.dndr; | ||||
|     s1_t drOffset; | ||||
|     s1_t candidateDr; | ||||
|  | ||||
|     if ( LMIC.rx1DrOffset <= 5) | ||||
|         drOffset = (s1_t) LMIC.rx1DrOffset; | ||||
|     else | ||||
|         // make a reasonable assumption for unspecified value. | ||||
|         drOffset = 5; | ||||
|  | ||||
|     candidateDr = (s1_t) txdr - drOffset; | ||||
|     if (candidateDr < LORAWAN_DR0) | ||||
|             candidateDr = 0; | ||||
|     else if (candidateDr > LORAWAN_DR7) | ||||
|             candidateDr = LORAWAN_DR7; | ||||
|  | ||||
|     LMIC.dndr = (u1_t) candidateDr; | ||||
|     LMIC.rps = dndr2rps(LMIC.dndr); | ||||
| } | ||||
|  | ||||
| void | ||||
| LMICeu868_initJoinLoop(void) { | ||||
|         LMICeulike_initJoinLoop(NUM_DEFAULT_CHANNELS, /* adr dBm */ EU868_TX_EIRP_MAX_DBM); | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /* | ||||
| * Copyright (c) 2014-2016 IBM Corporation. | ||||
| * Copyright (c) 2017 MCCI Corporation. | ||||
| * Copyright (c) 2017, 2019 MCCI Corporation. | ||||
| * All rights reserved. | ||||
| * | ||||
| *  Redistribution and use in source and binary forms, with or without | ||||
| @ -32,37 +32,47 @@ | ||||
|  | ||||
| #if CFG_LMIC_EU_like | ||||
|  | ||||
| void  LMIC_enableSubBand(u1_t band) { | ||||
| bit_t LMIC_enableSubBand(u1_t band) { | ||||
|         LMIC_API_PARAMETER(band); | ||||
|         return 0; | ||||
| } | ||||
|  | ||||
| void  LMIC_disableSubBand(u1_t band) { | ||||
| bit_t LMIC_disableSubBand(u1_t band) { | ||||
|         LMIC_API_PARAMETER(band); | ||||
|         return 0; | ||||
| } | ||||
|  | ||||
| void LMIC_disableChannel(u1_t channel) { | ||||
| bit_t LMIC_disableChannel(u1_t channel) { | ||||
|         u2_t old_chmap = LMIC.channelMap; | ||||
|         LMIC.channelFreq[channel] = 0; | ||||
|         LMIC.channelDrMap[channel] = 0; | ||||
|         LMIC.channelMap &= ~(1 << channel); | ||||
|         LMIC.channelMap = old_chmap & ~(1 << channel); | ||||
|         return LMIC.channelMap != old_chmap; | ||||
| } | ||||
|  | ||||
| // this is a no-op provided for compatibilty | ||||
| void LMIC_enableChannel(u1_t channel) { | ||||
| bit_t LMIC_enableChannel(u1_t channel) { | ||||
|         LMIC_API_PARAMETER(channel); | ||||
|         return 0; | ||||
| } | ||||
|  | ||||
| u1_t LMICeulike_mapChannels(u1_t chpage, u2_t chmap) { | ||||
|         // Bad page, disable all channel, enable non-existent | ||||
| bit_t LMICeulike_canMapChannels(u1_t chpage, u2_t chmap) { | ||||
|         if (chpage != 0 || chmap == 0 || (chmap & ~LMIC.channelMap) != 0) | ||||
|                 return 0;  // illegal input | ||||
|         for (u1_t chnl = 0; chnl<MAX_CHANNELS; chnl++) { | ||||
|                 if ((chmap & (1 << chnl)) != 0 && LMIC.channelFreq[chnl] == 0) | ||||
|                         chmap &= ~(1 << chnl); // ignore - channel is not defined | ||||
|                         return 0; // fail - channel is not defined | ||||
|         } | ||||
|         LMIC.channelMap = chmap; | ||||
|         return 1; | ||||
| } | ||||
|  | ||||
| // assumes that LMICeulike_canMapChannels passed. Return true if something changed. | ||||
| bit_t LMICeulike_mapChannels(u1_t chpage, u2_t chmap) { | ||||
|         u2_t const old_chmap = LMIC.channelMap; | ||||
|         LMIC.channelMap = chmap; | ||||
|         return old_chmap != chmap; | ||||
| } | ||||
|  | ||||
| #if !defined(DISABLE_JOIN) | ||||
| void LMICeulike_initJoinLoop(uint8_t nDefaultChannels, s1_t adrTxPow) { | ||||
| #if CFG_TxContinuousMode | ||||
| @ -159,4 +169,19 @@ ostime_t LMICeulike_nextJoinState(uint8_t nDefaultChannels) { | ||||
| } | ||||
| #endif // !DISABLE_JOIN | ||||
|  | ||||
| void LMICeulike_saveAdrState(lmic_saved_adr_state_t *pStateBuffer) { | ||||
|         memcpy( | ||||
|                 pStateBuffer->channelFreq, | ||||
|                 LMIC.channelFreq, | ||||
|                 sizeof(LMIC.channelFreq) | ||||
|         ); | ||||
|         pStateBuffer->channelMap = LMIC.channelMap; | ||||
| } | ||||
|  | ||||
| bit_t LMICeulike_compareAdrState(const lmic_saved_adr_state_t *pStateBuffer) { | ||||
|         if (memcmp(pStateBuffer->channelFreq, LMIC.channelFreq, sizeof(LMIC.channelFreq)) != 0) | ||||
|                 return 1; | ||||
|         return pStateBuffer->channelMap != LMIC.channelMap; | ||||
| } | ||||
|  | ||||
| #endif // CFG_LMIC_EU_like | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /* | ||||
| * Copyright (c) 2014-2016 IBM Corporation. | ||||
| * Copyright (c) 2017 MCCI Corporation. | ||||
| * Copyright (c) 2017, 2019 MCCI Corporation. | ||||
| * All rights reserved. | ||||
| * | ||||
| *  Redistribution and use in source and binary forms, with or without | ||||
| @ -74,14 +74,14 @@ enum { BAND_MILLI = 0, BAND_CENTI = 1, BAND_DECI = 2, BAND_AUX = 3 }; | ||||
| #define LMICbandplan_setSessionInitDefaultChannels()    \ | ||||
|         do { LMICbandplan_initDefaultChannels(/* normal, not join */ 0); } while (0) | ||||
|  | ||||
| u1_t LMICeulike_mapChannels(u1_t chpage, u2_t chmap); | ||||
| bit_t LMICeulike_canMapChannels(u1_t chpage, u2_t chmap); | ||||
| #define LMICbandplan_canMapChannels(c, m)  LMICeulike_canMapChannels(c, m) | ||||
|  | ||||
| bit_t LMICeulike_mapChannels(u1_t chpage, u2_t chmap); | ||||
| #define LMICbandplan_mapChannels(c, m)  LMICeulike_mapChannels(c, m) | ||||
|  | ||||
| void LMICeulike_initJoinLoop(u1_t nDefaultChannels, s1_t adrTxPow); | ||||
|  | ||||
| #define LMICbandplan_setRx1Params() \ | ||||
|         do { /*LMIC.freq/rps remain unchanged*/ } while (0) | ||||
|  | ||||
| void LMICeulike_updateTx(ostime_t txbeg); | ||||
| #define LMICbandplan_updateTx(t)        LMICeulike_updateTx(t) | ||||
|  | ||||
| @ -95,4 +95,10 @@ static inline ostime_t LMICeulike_nextJoinTime(ostime_t now) { | ||||
| #define LMICbandplan_init()     \ | ||||
|         do { /* nothing */ } while (0) | ||||
|  | ||||
| void LMICeulike_saveAdrState(lmic_saved_adr_state_t *pStateBuffer); | ||||
| #define LMICbandplan_saveAdrState(pState) LMICeulike_saveAdrState(pState) | ||||
|  | ||||
| bit_t LMICeulike_compareAdrState(const lmic_saved_adr_state_t *pStateBuffer); | ||||
| #define LMICbandplan_compareAdrState(pState) LMICeulike_compareAdrState(pState) | ||||
|  | ||||
| #endif // _lmic_eu_like_h_ | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /* | ||||
| * Copyright (c) 2014-2016 IBM Corporation. | ||||
| * Copyright (c) 2017 MCCI Corporation. | ||||
| * Copyright (c) 2017, 2019 MCCI Corporation. | ||||
| * All rights reserved. | ||||
| * | ||||
| *  Redistribution and use in source and binary forms, with or without | ||||
| @ -59,7 +59,7 @@ uint8_t LMICin866_maxFrameLen(uint8_t dr) { | ||||
| } | ||||
|  | ||||
| static CONST_TABLE(s1_t, TXPOWLEVELS)[] = { | ||||
|         20, 14, 11, 8, 5, 2, 0,0, 0,0,0,0, 0,0,0,0 | ||||
|         30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10, 0, 0,0,0,0 | ||||
| }; | ||||
|  | ||||
| int8_t LMICin866_pow2dBm(uint8_t mcmd_ladr_p1) { | ||||
| @ -195,6 +195,27 @@ LMICin866_txDoneFSK(ostime_t delay, osjobcb_t func) { | ||||
|         os_setTimedCallback(&LMIC.osjob, LMIC.rxtime - RX_RAMPUP, func); | ||||
| } | ||||
|  | ||||
| // set the Rx1 dndr, rps. | ||||
| void LMICin866_setRx1Params(void) { | ||||
|     u1_t const txdr = LMIC.dndr; | ||||
|     s1_t drOffset; | ||||
|     s1_t candidateDr; | ||||
|  | ||||
|     if ( LMIC.rx1DrOffset <= 5) | ||||
|         drOffset = (s1_t) LMIC.rx1DrOffset; | ||||
|     else | ||||
|         drOffset = 5 - (s1_t) LMIC.rx1DrOffset; | ||||
|  | ||||
|     candidateDr = (s1_t) txdr - drOffset; | ||||
|     if (candidateDr < LORAWAN_DR0) | ||||
|             candidateDr = 0; | ||||
|     else if (candidateDr > LORAWAN_DR5) | ||||
|             candidateDr = LORAWAN_DR5; | ||||
|  | ||||
|     LMIC.dndr = (u1_t) candidateDr; | ||||
|     LMIC.rps = dndr2rps(LMIC.dndr); | ||||
| } | ||||
|  | ||||
| void | ||||
| LMICin866_initJoinLoop(void) { | ||||
|         LMICeulike_initJoinLoop(NUM_DEFAULT_CHANNELS, /* adr dBm */ IN866_TX_EIRP_MAX_DBM); | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /* | ||||
| * Copyright (c) 2014-2016 IBM Corporation. | ||||
| * Copyright (c) 2017 MCCI Corporation. | ||||
| * Copyright (c) 2017, 2019 MCCI Corporation. | ||||
| * All rights reserved. | ||||
| * | ||||
| *  Redistribution and use in source and binary forms, with or without | ||||
| @ -98,9 +98,11 @@ bit_t LMIC_setupChannel(u1_t chidx, u4_t freq, u2_t drmap, s1_t band) { | ||||
|         return 1; | ||||
| } | ||||
|  | ||||
| void LMIC_disableChannel(u1_t channel) { | ||||
| bit_t LMIC_disableChannel(u1_t channel) { | ||||
|         bit_t result = 0; | ||||
|         if (channel < 72 + MAX_XCHANNELS) { | ||||
|                 if (ENABLED_CHANNEL(channel)) { | ||||
|                         result = 1; | ||||
|                         if (IS_CHANNEL_125khz(channel)) | ||||
|                                 LMIC.activeChannels125khz--; | ||||
|                         else if (IS_CHANNEL_500khz(channel)) | ||||
| @ -108,11 +110,14 @@ void LMIC_disableChannel(u1_t channel) { | ||||
|                 } | ||||
|                 LMIC.channelMap[channel >> 4] &= ~(1 << (channel & 0xF)); | ||||
|         } | ||||
|         return result; | ||||
| } | ||||
|  | ||||
| void LMIC_enableChannel(u1_t channel) { | ||||
| bit_t LMIC_enableChannel(u1_t channel) { | ||||
|         bit_t result = 0; | ||||
|         if (channel < 72 + MAX_XCHANNELS) { | ||||
|                 if (!ENABLED_CHANNEL(channel)) { | ||||
|                         result = 1; | ||||
|                         if (IS_CHANNEL_125khz(channel)) | ||||
|                                 LMIC.activeChannels125khz++; | ||||
|                         else if (IS_CHANNEL_500khz(channel)) | ||||
| @ -120,42 +125,52 @@ void LMIC_enableChannel(u1_t channel) { | ||||
|                 } | ||||
|                 LMIC.channelMap[channel >> 4] |= (1 << (channel & 0xF)); | ||||
|         } | ||||
|         return result; | ||||
| } | ||||
|  | ||||
| void  LMIC_enableSubBand(u1_t band) { | ||||
| bit_t  LMIC_enableSubBand(u1_t band) { | ||||
|         ASSERT(band < 8); | ||||
|         u1_t start = band * 8; | ||||
|         u1_t end = start + 8; | ||||
|         bit_t result = 0; | ||||
|  | ||||
|         // enable all eight 125 kHz channels in this subband | ||||
|         for (int channel = start; channel < end; ++channel) | ||||
|                 LMIC_enableChannel(channel); | ||||
|                 result |= LMIC_enableChannel(channel); | ||||
|  | ||||
|         // there's a single 500 kHz channel associated with | ||||
|         // each group of 8 125 kHz channels. Enable it, too. | ||||
|         LMIC_enableChannel(64 + band); | ||||
|         result |= LMIC_enableChannel(64 + band); | ||||
|         return result; | ||||
| } | ||||
| void  LMIC_disableSubBand(u1_t band) { | ||||
|  | ||||
| bit_t  LMIC_disableSubBand(u1_t band) { | ||||
|         ASSERT(band < 8); | ||||
|         u1_t start = band * 8; | ||||
|         u1_t end = start + 8; | ||||
|         bit_t result = 0; | ||||
|  | ||||
|         // disable all eight 125 kHz channels in this subband | ||||
|         for (int channel = start; channel < end; ++channel) | ||||
|                 LMIC_disableChannel(channel); | ||||
|                 result |= LMIC_disableChannel(channel); | ||||
|  | ||||
|         // there's a single 500 kHz channel associated with | ||||
|         // each group of 8 125 kHz channels. Disable it, too. | ||||
|         LMIC_disableChannel(64 + band); | ||||
|         result |= LMIC_disableChannel(64 + band); | ||||
|         return result; | ||||
| } | ||||
| void  LMIC_selectSubBand(u1_t band) { | ||||
|  | ||||
| bit_t  LMIC_selectSubBand(u1_t band) { | ||||
|         bit_t result = 0; | ||||
|  | ||||
|         ASSERT(band < 8); | ||||
|         for (int b = 0; b<8; ++b) { | ||||
|                 if (band == b) | ||||
|                         LMIC_enableSubBand(b); | ||||
|                         result |= LMIC_enableSubBand(b); | ||||
|                 else | ||||
|                         LMIC_disableSubBand(b); | ||||
|                         result |= LMIC_disableSubBand(b); | ||||
|         } | ||||
|         return result; | ||||
| } | ||||
|  | ||||
| void LMICus915_updateTx(ostime_t txbeg) { | ||||
| @ -193,16 +208,31 @@ void LMICus915_setBcnRxParams(void) { | ||||
| } | ||||
| #endif // !DISABLE_BEACONS | ||||
|  | ||||
| // TODO(tmm@mcci.com): parmeterize for US-like | ||||
| // set the Rx1 dndr, rps. | ||||
| void LMICus915_setRx1Params(void) { | ||||
|     u1_t const txdr = LMIC.dndr; | ||||
|     u1_t candidateDr; | ||||
|     LMIC.freq = US915_500kHz_DNFBASE + (LMIC.txChnl & 0x7) * US915_500kHz_DNFSTEP; | ||||
|     if( /* TX datarate */LMIC.dndr < US915_DR_SF8C ) | ||||
|         LMIC.dndr += US915_DR_SF10CR - US915_DR_SF10; | ||||
|     else if( LMIC.dndr == US915_DR_SF8C ) | ||||
|         LMIC.dndr = US915_DR_SF7CR; | ||||
|     if ( /* TX datarate */txdr < LORAWAN_DR4) | ||||
|             candidateDr = txdr + 10 - LMIC.rx1DrOffset; | ||||
|     else | ||||
|             candidateDr = LORAWAN_DR13 - LMIC.rx1DrOffset; | ||||
|  | ||||
|     if (candidateDr < LORAWAN_DR8) | ||||
|             candidateDr = LORAWAN_DR8; | ||||
|     else if (candidateDr > LORAWAN_DR13) | ||||
|             candidateDr = LORAWAN_DR13; | ||||
|  | ||||
|     LMIC.dndr = candidateDr; | ||||
|     LMIC.rps = dndr2rps(LMIC.dndr); | ||||
| } | ||||
|  | ||||
| void LMICus915_initJoinLoop(void) { | ||||
|     LMICuslike_initJoinLoop(); | ||||
|  | ||||
|     // initialize the adrTxPower. | ||||
|     LMIC.adrTxPow = 20; // dBm | ||||
| } | ||||
|  | ||||
| // | ||||
| // END: US915 related stuff | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /* | ||||
| * Copyright (c) 2014-2016 IBM Corporation. | ||||
| * Copyright (c) 2017 MCCI Corporation. | ||||
| * Copyright (c) 2017, 2019 MCCI Corporation. | ||||
| * All rights reserved. | ||||
| * | ||||
| *  Redistribution and use in source and binary forms, with or without | ||||
| @ -91,7 +91,46 @@ void LMICuslike_initDefaultChannels(bit_t fJoin) { | ||||
|         LMIC.activeChannels500khz = 8; | ||||
| } | ||||
|  | ||||
| u1_t LMICuslike_mapChannels(u1_t chpage, u2_t chmap) { | ||||
| // verify that a given setting is permitted | ||||
| bit_t LMICuslike_canMapChannels(u1_t chpage, u2_t chmap) { | ||||
| 	/* | ||||
| 	|| MCMD_LADR_CHP_125ON and MCMD_LADR_CHP_125OFF are special. The | ||||
| 	|| channel map appllies to 500kHz (ch 64..71) and in addition | ||||
| 	|| all channels 0..63 are turned off or on.  MCMC_LADR_CHP_BANK | ||||
| 	|| is also special, in that it enables subbands. | ||||
| 	*/ | ||||
| 	if (chpage < MCMD_LADR_CHP_USLIKE_SPECIAL) { | ||||
| 		if (chmap == 0) | ||||
| 			return 0; | ||||
|  | ||||
| 		// operate on channels 0..15, 16..31, 32..47, 48..63, 64..71 | ||||
| 		if (chpage == (64 >> 4)) { | ||||
| 			if (chmap & 0xFF00) { | ||||
| 				// those are reserved bits, fail. | ||||
| 				return 0; | ||||
| 			} | ||||
| 		} | ||||
| 	} else if (chpage == MCMD_LADR_CHP_BANK) { | ||||
| 		if (chmap == 0 || (chmap & 0xFF00) != 0) { | ||||
| 			// no bits set, or reserved bitsset , fail. | ||||
| 			return 0; | ||||
| 		} | ||||
| 	} else if (chpage == MCMD_LADR_CHP_125ON || chpage == MCMD_LADR_CHP_125OFF) { | ||||
|                 u1_t const en125 = chpage == MCMD_LADR_CHP_125ON; | ||||
|  | ||||
| 		// if disabling all 125kHz chans, must have at least one 500kHz chan | ||||
| 		// don't allow reserved bits to be set in chmap. | ||||
| 		if ((! en125 && chmap == 0) || (chmap & 0xFF00) != 0) | ||||
| 			return 0; | ||||
| 	} else { | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	// if we get here, it looks legal. | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| bit_t LMICuslike_mapChannels(u1_t chpage, u2_t chmap) { | ||||
| 	/* | ||||
| 	|| MCMD_LADR_CHP_125ON and MCMD_LADR_CHP_125OFF are special. The | ||||
| 	|| channel map appllies to 500kHz (ch 64..71) and in addition | ||||
| @ -99,61 +138,53 @@ u1_t LMICuslike_mapChannels(u1_t chpage, u2_t chmap) { | ||||
| 	|| is also special, in that it enables subbands. | ||||
| 	*/ | ||||
| 	u1_t base, top; | ||||
| 	bit_t result = 0; | ||||
|  | ||||
| 	if (chpage == MCMD_LADR_CHP_BANK) { | ||||
| 		// each bit enables a bank of channels | ||||
| 		for (u1_t subband = 0; subband < 8; ++subband, chmap >>= 1) { | ||||
| 			if (chmap & 1) { | ||||
| 				result |= LMIC_enableSubBand(subband); | ||||
| 			} else { | ||||
| 				result |= LMIC_disableSubBand(subband); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return result; | ||||
| 	} | ||||
|  | ||||
| 	if (chpage < MCMD_LADR_CHP_USLIKE_SPECIAL) { | ||||
| 		// operate on channels 0..15, 16..31, 32..47, 48..63 | ||||
| 		base = chpage << 4; | ||||
| 		top = base + 16; | ||||
| 		if (base == 64) { | ||||
| 			if (chmap & 0xFF00) { | ||||
| 				// those are reserved bits, fail. | ||||
| 				return 0; | ||||
| 			} | ||||
| 			top = 72; | ||||
| 		} | ||||
| 	} else if (chpage == MCMD_LADR_CHP_BANK) { | ||||
| 		if (chmap & 0xFF00) { | ||||
| 			// those are resreved bits, fail. | ||||
| 			return 0; | ||||
| 		} | ||||
| 		// each bit enables a bank of channels | ||||
| 		for (u1_t subband = 0; subband < 8; ++subband, chmap >>= 1) { | ||||
| 			if (chmap & 1) { | ||||
| 				LMIC_enableSubBand(subband); | ||||
| 			} else { | ||||
| 				LMIC_disableSubBand(subband); | ||||
| 			} | ||||
|  | ||||
| 		// don't change any channels below | ||||
| 		base = top = 0; | ||||
| 		} | ||||
| 	} else if (chpage == MCMD_LADR_CHP_125ON || chpage == MCMD_LADR_CHP_125OFF) { | ||||
| 	} else /* if (chpage == MCMD_LADR_CHP_125ON || chpage == MCMD_LADR_CHP_125OFF) */ { | ||||
|                 u1_t const en125 = chpage == MCMD_LADR_CHP_125ON; | ||||
|  | ||||
| 		// enable or disable all 125kHz channels | ||||
| 		for (u1_t chnl = 0; chnl < 64; ++chnl) { | ||||
| 			if (en125) | ||||
| 				LMIC_enableChannel(chnl); | ||||
| 				result |= LMIC_enableChannel(chnl); | ||||
| 			else | ||||
| 				LMIC_disableChannel(chnl); | ||||
| 				result |= LMIC_disableChannel(chnl); | ||||
| 		} | ||||
|  | ||||
| 		// then apply mask to top 8 channels. | ||||
| 		base = 64; | ||||
| 		top = 72; | ||||
| 	} else { | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	// apply chmap to channels in [base..top-1]. | ||||
| 	// Use enable/disable channel to keep activeChannel counts in sync. | ||||
| 	for (u1_t chnl = base; chnl < top; ++chnl, chmap >>= 1) { | ||||
| 		if (chmap & 0x0001) | ||||
| 			LMIC_enableChannel(chnl); | ||||
| 			result |= LMIC_enableChannel(chnl); | ||||
| 		else | ||||
| 			LMIC_disableChannel(chnl); | ||||
| 			result |= LMIC_disableChannel(chnl); | ||||
|         } | ||||
|         return 1; | ||||
|         return result; | ||||
| } | ||||
|  | ||||
| // US does not have duty cycling - return now as earliest TX time | ||||
| @ -183,18 +214,13 @@ void LMICuslike_initJoinLoop(void) { | ||||
|         // starting point. | ||||
|         setNextChannel(0, 64, LMIC.activeChannels125khz); | ||||
|  | ||||
|         // initialize the adrTxPower. | ||||
|         // TODO(tmm@mcci.com): is this right for all US-like regions | ||||
|         LMIC.adrTxPow = 20; // dBm | ||||
|         ASSERT((LMIC.opmode & OP_NEXTCHNL) == 0); | ||||
|  | ||||
|         // make sure LMIC.txend is valid. | ||||
|         LMIC.txend = os_getTime(); | ||||
|         ASSERT((LMIC.opmode & OP_NEXTCHNL) == 0); | ||||
|  | ||||
|         // make sure the datarate is set to DR0 per LoRaWAN regional reqts V1.0.2, | ||||
|         // section 2.2.2 | ||||
|         // TODO(tmm@mcci.com): parameterize this for US-like | ||||
|         LMICcore_setDrJoin(DRCHG_SET, LORAWAN_DR0); | ||||
|         // make sure the datarate is set to DR2 per LoRaWAN regional reqts V1.0.2, | ||||
|         // section 2.*.2 | ||||
|         LMICcore_setDrJoin(DRCHG_SET, LMICbandplan_getInitialDrJoin()); | ||||
|  | ||||
|         // TODO(tmm@mcci.com) need to implement the transmit randomization and | ||||
|         // duty cycle restrictions from LoRaWAN V1.0.2 section 7. | ||||
| @ -233,7 +259,7 @@ ostime_t LMICuslike_nextJoinState(void) { | ||||
|                 setNextChannel(0, 64, LMIC.activeChannels125khz); | ||||
|  | ||||
|                 // TODO(tmm@mcci.com) parameterize | ||||
|                 s1_t dr = LORAWAN_DR0; | ||||
|                 s1_t dr = LMICuslike_getJoin125kHzDR(); | ||||
|                 if ((++LMIC.txCnt & 0x7) == 0) { | ||||
|                         failed = 1; // All DR exhausted - signal failed | ||||
|                 } | ||||
| @ -260,4 +286,16 @@ ostime_t LMICuslike_nextJoinState(void) { | ||||
| } | ||||
| #endif | ||||
|  | ||||
| void LMICuslike_saveAdrState(lmic_saved_adr_state_t *pStateBuffer) { | ||||
|         memcpy( | ||||
|                 pStateBuffer->channelMap, | ||||
|                 LMIC.channelMap, | ||||
|                 sizeof(LMIC.channelMap) | ||||
|         ); | ||||
| } | ||||
|  | ||||
| bit_t LMICuslike_compareAdrState(const lmic_saved_adr_state_t *pStateBuffer) { | ||||
|         return memcmp(pStateBuffer->channelMap, LMIC.channelMap, sizeof(LMIC.channelMap)) != 0; | ||||
| } | ||||
|  | ||||
| #endif // CFG_LMIC_US_like | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /* | ||||
| * Copyright (c) 2014-2016 IBM Corporation. | ||||
| * Copyright (c) 2017 MCCI Corporation. | ||||
| * Copyright (c) 2017, 2019 MCCI Corporation. | ||||
| * All rights reserved. | ||||
| * | ||||
| *  Redistribution and use in source and binary forms, with or without | ||||
| @ -43,6 +43,9 @@ | ||||
| #define IS_CHANNEL_500khz(c) (c>=64 && c<72) | ||||
| #define ENABLED_CHANNEL(chnl) ((LMIC.channelMap[(chnl >> 4)] & (1<<(chnl & 0x0F))) != 0) | ||||
|  | ||||
| // library functions: called from bandplan | ||||
| void LMICuslike_initJoinLoop(void); | ||||
|  | ||||
| // provide the isValidBeacon1 function -- int for bool. | ||||
| static inline int | ||||
| LMICuslike_isValidBeacon1(const uint8_t *d) { | ||||
| @ -77,24 +80,30 @@ void LMICuslike_initDefaultChannels(bit_t fJoin); | ||||
| #define LMICbandplan_setSessionInitDefaultChannels()    \ | ||||
|         do { /* nothing */} while (0) | ||||
|  | ||||
| u1_t LMICuslike_mapChannels(u1_t chpage, u2_t chmap); | ||||
| bit_t LMICuslike_canMapChannels(u1_t chpage, u2_t chmap); | ||||
| #define LMICbandplan_canMapChannels(chpage, chmap) LMICuslike_canMapChannels(chpage, chmap) | ||||
|  | ||||
| bit_t LMICuslike_mapChannels(u1_t chpage, u2_t chmap); | ||||
| #define LMICbandplan_mapChannels(chpage, chmap) LMICuslike_mapChannels(chpage, chmap) | ||||
|  | ||||
| ostime_t LMICuslike_nextTx(ostime_t now); | ||||
| #define LMICbandplan_nextTx(now)        LMICuslike_nextTx(now) | ||||
|  | ||||
| void LMICuslike_initJoinLoop(void); | ||||
| #define LMICbandplan_initJoinLoop()     LMICuslike_initJoinLoop() | ||||
|  | ||||
| ostime_t LMICuslike_nextJoinState(void); | ||||
| #define LMICbandplan_nextJoinState()    LMICuslike_nextJoinState(); | ||||
|  | ||||
| static inline ostime_t LMICeulike_nextJoinTime(ostime_t now) { | ||||
| static inline ostime_t LMICuslike_nextJoinTime(ostime_t now) { | ||||
|         return now; | ||||
| } | ||||
| #define LMICbandplan_nextJoinTime(now)     LMICeulike_nextJoinTime(now) | ||||
| #define LMICbandplan_nextJoinTime(now)     LMICuslike_nextJoinTime(now) | ||||
|  | ||||
| #define LMICbandplan_init()     \ | ||||
|         do { /* nothing */ } while (0) | ||||
|  | ||||
| void LMICuslike_saveAdrState(lmic_saved_adr_state_t *pStateBuffer); | ||||
| #define LMICbandplan_saveAdrState(pState) LMICuslike_saveAdrState(pState) | ||||
|  | ||||
| bit_t LMICuslike_compareAdrState(const lmic_saved_adr_state_t *pStateBuffer); | ||||
| #define LMICbandplan_compareAdrState(pState) LMICuslike_compareAdrState(pState) | ||||
|  | ||||
| #endif // _lmic_us_like_h_ | ||||
|  | ||||
| @ -44,7 +44,14 @@ typedef u1_t cr_t; | ||||
| typedef u1_t sf_t; | ||||
| typedef u1_t bw_t; | ||||
| typedef u1_t dr_t; | ||||
|  | ||||
| // Radio parameter set (encodes SF/BW/CR/IH/NOCRC) | ||||
| // 2..0:    Spreading factor | ||||
| // 4..3:    bandwidth: 0 == 125kHz, 1 == 250 kHz, 2 == 500 kHz. 3 == reserved. | ||||
| // 6..5:    coding rate: 0 == 4/5, 1 == 4/6, 2 == 4/7, 3 == 4/8 | ||||
| // 7:       nocrc: 0 == with crc, 1 == without crc | ||||
| // 15..8:   Implicit header control: 0 ==> none, 1..0xFF ==> length in bytes. | ||||
|  | ||||
| typedef u2_t rps_t; | ||||
| TYPEDEF_xref2rps_t; | ||||
|  | ||||
| @ -52,7 +59,7 @@ enum { ILLEGAL_RPS = 0xFF }; | ||||
|  | ||||
| // Global maximum frame length | ||||
| enum { STD_PREAMBLE_LEN  =  8 }; | ||||
| enum { MAX_LEN_FRAME     = 64 }; | ||||
| enum { MAX_LEN_FRAME     =  LMIC_ENABLE_long_messages ? 255 : 64 }; | ||||
| enum { LEN_DEVNONCE      =  2 }; | ||||
| enum { LEN_ARTNONCE      =  3 }; | ||||
| enum { LEN_NETID         =  3 }; | ||||
| @ -414,7 +421,6 @@ enum { | ||||
|     HDR_FTYPE_DADN   = 0x60,  // data (unconfirmed) dn | ||||
|     HDR_FTYPE_DCUP   = 0x80,  // data confirmed up | ||||
|     HDR_FTYPE_DCDN   = 0xA0,  // data confirmed dn | ||||
|     HDR_FTYPE_REJOIN = 0xC0,  // rejoin for roaming | ||||
|     HDR_FTYPE_PROP   = 0xE0 | ||||
| }; | ||||
| enum { | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /* | ||||
|  * Copyright (c) 2014-2016 IBM Corporation. | ||||
|  * Copyright (c) 2016-2017 MCCI Corporation. | ||||
|  * Copyright (c) 2016-2017, 2019 MCCI Corporation. | ||||
|  * All rights reserved. | ||||
|  * | ||||
|  *  Redistribution and use in source and binary forms, with or without | ||||
| @ -68,13 +68,15 @@ static int unlinkjob (osjob_t** pnext, osjob_t* job) { | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static osjob_t** getJobQueue(osjob_t* job) { | ||||
|     return os_jobIsTimed(job) ? &OS.scheduledjobs : &OS.runnablejobs; | ||||
| } | ||||
|  | ||||
| // clear scheduled job | ||||
| void os_clearCallback (osjob_t* job) { | ||||
|     hal_disableIRQs(); | ||||
|  | ||||
|     // if it's not in the scheduled jobs, look in the runnable... | ||||
|     if (! unlinkjob(&OS.scheduledjobs, job)) | ||||
|         unlinkjob(&OS.runnablejobs, job); | ||||
|     unlinkjob(getJobQueue(job), job); | ||||
|  | ||||
|     hal_enableIRQs(); | ||||
| } | ||||
| @ -83,11 +85,15 @@ void os_clearCallback (osjob_t* job) { | ||||
| void os_setCallback (osjob_t* job, osjobcb_t cb) { | ||||
|     osjob_t** pnext; | ||||
|     hal_disableIRQs(); | ||||
|  | ||||
|     // remove if job was already queued | ||||
|     unlinkjob(&OS.runnablejobs, job); | ||||
|     // fill-in job | ||||
|     job->func = cb; | ||||
|     unlinkjob(getJobQueue(job), job); | ||||
|  | ||||
|     // fill-in job. Ascending memory order is write-queue friendly | ||||
|     job->next = NULL; | ||||
|     job->deadline = 0; | ||||
|     job->func = cb; | ||||
|  | ||||
|     // add to end of run queue | ||||
|     for(pnext=&OS.runnablejobs; *pnext; pnext=&((*pnext)->next)); | ||||
|     *pnext = job; | ||||
| @ -97,13 +103,21 @@ void os_setCallback (osjob_t* job, osjobcb_t cb) { | ||||
| // schedule timed job | ||||
| void os_setTimedCallback (osjob_t* job, ostime_t time, osjobcb_t cb) { | ||||
|     osjob_t** pnext; | ||||
|  | ||||
|     // special case time 0 -- it will be one tick late. | ||||
|     if (time == 0) | ||||
|         time = 1; | ||||
|  | ||||
|     hal_disableIRQs(); | ||||
|  | ||||
|     // remove if job was already queued | ||||
|     unlinkjob(&OS.scheduledjobs, job); | ||||
|     unlinkjob(getJobQueue(job), job); | ||||
|  | ||||
|     // fill-in job | ||||
|     job->next = NULL; | ||||
|     job->deadline = time; | ||||
|     job->func = cb; | ||||
|     job->next = NULL; | ||||
|  | ||||
|     // insert into schedule | ||||
|     for(pnext=&OS.scheduledjobs; *pnext; pnext=&((*pnext)->next)) { | ||||
|         if((*pnext)->deadline - time > 0) { // (cmp diff, not abs!) | ||||
| @ -141,3 +155,13 @@ void os_runloop_once() { | ||||
|         j->func(j); | ||||
|     } | ||||
| } | ||||
|  | ||||
| // return true if there are any jobs scheduled within time ticks from now. | ||||
| // return false if any jobs scheduled are at least time ticks in the future. | ||||
| bit_t os_queryTimeCriticalJobs(ostime_t time) { | ||||
|     if (OS.scheduledjobs && | ||||
|         OS.scheduledjobs->deadline - os_getTime() < time) | ||||
|         return 1; | ||||
|     else | ||||
|         return 0; | ||||
| } | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /* | ||||
|  * Copyright (c) 2014-2016 IBM Corporation. | ||||
|  * Copyright (c) 2018 MCCI Corporation | ||||
|  * Copyright (c) 2018, 2019 MCCI Corporation | ||||
|  * All rights reserved. | ||||
|  * | ||||
|  *  Redistribution and use in source and binary forms, with or without | ||||
| @ -84,8 +84,7 @@ typedef              u1_t* xref2u1_t; | ||||
|  | ||||
| #define SIZEOFEXPR(x) sizeof(x) | ||||
|  | ||||
| #define ON_LMIC_EVENT(ev)  onEvent(ev) | ||||
| #define DECL_ON_LMIC_EVENT void onEvent(ev_t e) | ||||
| #define DECL_ON_LMIC_EVENT LMIC_DECLARE_FUNCTION_WEAK(void, onEvent, (ev_t e)) | ||||
|  | ||||
| extern u4_t AESAUX[]; | ||||
| extern u4_t AESKEY[]; | ||||
| @ -149,7 +148,13 @@ void radio_monitor_rssi(ostime_t n, oslmic_radio_rssi_t *pRssi); | ||||
|  | ||||
|  | ||||
| struct osjob_t;  // fwd decl. | ||||
| typedef void (*osjobcb_t) (struct osjob_t*); | ||||
|  | ||||
| //! the function type for osjob_t callbacks | ||||
| typedef void (osjobcbfn_t)(struct osjob_t*); | ||||
|  | ||||
| //! the pointer-to-function for osjob_t callbacks | ||||
| typedef osjobcbfn_t *osjobcb_t; | ||||
|  | ||||
| struct osjob_t { | ||||
|     struct osjob_t* next; | ||||
|     ostime_t deadline; | ||||
| @ -157,6 +162,11 @@ struct osjob_t { | ||||
| }; | ||||
| TYPEDEF_xref2osjob_t; | ||||
|  | ||||
| //! determine whether a job is timed or immediate. os_setTimedCallback() | ||||
| // must treat incoming == 0 as being 1 instead. | ||||
| static inline int os_jobIsTimed(xref2osjob_t job) { | ||||
|     return (job->deadline != 0); | ||||
| } | ||||
|  | ||||
| #ifndef HAS_os_calls | ||||
|  | ||||
| @ -190,6 +200,10 @@ void os_radio (u1_t mode); | ||||
| #ifndef os_getBattLevel | ||||
| u1_t os_getBattLevel (void); | ||||
| #endif | ||||
| #ifndef os_queryTimeCriticalJobs | ||||
| //! Return non-zero if any jobs are scheduled between now and now+time. | ||||
| bit_t os_queryTimeCriticalJobs(ostime_t time); | ||||
| #endif | ||||
|  | ||||
| #ifndef os_rlsbf4 | ||||
| //! Read 32-bit quantity from given pointer in little endian byte order. | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| /* | ||||
|  * Copyright (c) 2014-2016 IBM Corporation. | ||||
|  * Copyright (c) 2016-2018 MCCI Corporation. | ||||
|  * Copyright (c) 2016-2019 MCCI Corporation. | ||||
|  * All rights reserved. | ||||
|  * | ||||
|  *  Redistribution and use in source and binary forms, with or without | ||||
| @ -188,6 +188,12 @@ | ||||
|  | ||||
| #define SX1276_MC1_IMPLICIT_HEADER_MODE_ON    0x01 | ||||
|  | ||||
| #ifdef CFG_sx1276_radio | ||||
| # define SX127X_MC1_IMPLICIT_HEADER_MODE_ON	SX1276_MC1_IMPLICIT_HEADER_MODE_ON | ||||
| #else | ||||
| # define SX127X_MC1_IMPLICIT_HEADER_MODE_ON	SX1272_MC1_IMPLICIT_HEADER_MODE_ON | ||||
| #endif | ||||
|  | ||||
| // sx1276 RegModemConfig2 | ||||
| #define SX1276_MC2_RX_PAYLOAD_CRCON        0x04 | ||||
|  | ||||
| @ -264,7 +270,7 @@ | ||||
| #define MAP_DIO0_LORA_TXDONE   0x40  // 01------ | ||||
| #define MAP_DIO1_LORA_RXTOUT   0x00  // --00---- | ||||
| #define MAP_DIO1_LORA_NOP      0x30  // --11---- | ||||
| #define MAP_DIO2_LORA_NOP      0xC0  // ----11-- | ||||
| #define MAP_DIO2_LORA_NOP      0x0C  // ----11-- | ||||
|  | ||||
| #define MAP_DIO0_FSK_READY     0x00  // 00------ (packet sent / payload ready) | ||||
| #define MAP_DIO1_FSK_NOP       0x30  // --11---- | ||||
| @ -445,7 +451,7 @@ static void configChannel () { | ||||
| static void configPower () { | ||||
| #ifdef CFG_sx1276_radio | ||||
|     // PA_BOOST output is assumed but not 20 dBm. | ||||
|     s1_t pw = (s1_t)LMIC.txpow; | ||||
|     s1_t pw = (s1_t)LMIC.radio_txpow; | ||||
|     if(pw > 17) { | ||||
|         pw = 17; | ||||
|     } else if(pw < 2) { | ||||
| @ -461,7 +467,7 @@ static void configPower () { | ||||
|  | ||||
| #elif CFG_sx1272_radio | ||||
|     // set PA config (2-17 dBm using PA_BOOST) | ||||
|     s1_t pw = (s1_t)LMIC.txpow; | ||||
|     s1_t pw = (s1_t)LMIC.radio_txpow; | ||||
|     if(pw > 17) { | ||||
|         pw = 17; | ||||
|     } else if(pw < 2) { | ||||
| @ -634,8 +640,8 @@ static void rxlora (u1_t rxmode) { | ||||
|     // set LNA gain | ||||
|     writeReg(RegLna, LNA_RX_GAIN); | ||||
|     // set max payload size | ||||
|     writeReg(LORARegPayloadMaxLength, 64); | ||||
| #if !defined(DISABLE_INVERT_IQ_ON_RX) | ||||
|     writeReg(LORARegPayloadMaxLength, MAX_LEN_FRAME); | ||||
| #if !defined(DISABLE_INVERT_IQ_ON_RX) /* DEPRECATED(tmm@mcci.com); #250. remove test, always include code in V3 */ | ||||
|     // use inverted I/Q signal (prevent mote-to-mote communication) | ||||
|  | ||||
|     // XXX: use flag to switch on/off inversion | ||||
| @ -660,6 +666,9 @@ static void rxlora (u1_t rxmode) { | ||||
|     // enable antenna switch for RX | ||||
|     hal_pin_rxtx(0); | ||||
|  | ||||
|     writeReg(LORARegFifoAddrPtr, 0); | ||||
|     writeReg(LORARegFifoRxBaseAddr, 0); | ||||
|  | ||||
|     // now instruct the radio to receive | ||||
|     if (rxmode == RXMODE_SINGLE) { // single rx | ||||
|         hal_waitUntil(LMIC.rxtime); // busy wait until exact rx time | ||||
| @ -958,6 +967,7 @@ void radio_irq_handler_v2 (u1_t dio, ostime_t now) { | ||||
| #endif | ||||
|     if( (readReg(RegOpMode) & OPMODE_LORA) != 0) { // LORA modem | ||||
|         u1_t flags = readReg(LORARegIrqFlags); | ||||
| 	LMIC.saveIrqFlags = flags; | ||||
|         LMIC_X_DEBUG_PRINTF("IRQ=%02x\n", flags); | ||||
|         if( flags & IRQ_LORA_TXDONE_MASK ) { | ||||
|             // save exact tx time | ||||
| @ -969,7 +979,7 @@ void radio_irq_handler_v2 (u1_t dio, ostime_t now) { | ||||
|             } | ||||
|             LMIC.rxtime = now; | ||||
|             // read the PDU and inform the MAC that we received something | ||||
|             LMIC.dataLen = (readReg(LORARegModemConfig1) & SX1272_MC1_IMPLICIT_HEADER_MODE_ON) ? | ||||
|             LMIC.dataLen = (readReg(LORARegModemConfig1) & SX127X_MC1_IMPLICIT_HEADER_MODE_ON) ? | ||||
|                 readReg(LORARegPayloadLength) : readReg(LORARegRxNbBytes); | ||||
|             // set FIFO read address pointer | ||||
|             writeReg(LORARegFifoAddrPtr, readReg(LORARegFifoRxCurrentAddr)); | ||||
|  | ||||
		Reference in New Issue
	
	Block a user