diff --git a/.gitignore b/.gitignore index 57ace6f..a13c3d2 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ sdkconfig sdkconfig.old dev_keys.txt ttn-esp32 +.vscode/ diff --git a/src/aes/lmic_aes.c b/src/aes/lmic_aes.c index 40eb516..2a5bca3 100755 --- a/src/aes/lmic_aes.c +++ b/src/aes/lmic_aes.c @@ -262,9 +262,6 @@ u4_t os_aes (u1_t mode, xref2u1_t buf, u2_t len) { u4_t a0, a1, a2, a3; u4_t t0, t1, t2, t3; u4_t *ki, *ke; - // ttn-esp32 change: prevent error 'x' may be used uninitialized in this function - a0 = a1 = a2 = a3 = 0; - t0 = t1 = 0; // load input block if( (mode & AES_CTR) || ((mode & AES_MIC) && (mode & AES_MICNOAUX)==0) ) { // load CTR block or first MIC block diff --git a/src/aes/other.c b/src/aes/other.c old mode 100644 new mode 100755 diff --git a/src/hal/hal_esp32.cpp b/src/hal/hal_esp32.cpp index 74b63e5..901ef9b 100755 --- a/src/hal/hal_esp32.cpp +++ b/src/hal/hal_esp32.cpp @@ -130,6 +130,17 @@ s1_t hal_getRssiCal (void) return lmic_pins.rssi_cal; } +ostime_t hal_setModuleActive (bit_t val) +{ + return 0; +} + +bit_t hal_queryUsingTcxo(void) +{ + return false; +} + + // ----------------------------------------------------------------------------- // SPI @@ -152,12 +163,12 @@ void HAL_ESP32::spiInit() ESP_LOGI(TAG, "SPI initialized"); } -void hal_spi_write(u1_t cmd, const u1_t *buf, int len) +void hal_spi_write(u1_t cmd, const u1_t *buf, size_t len) { ttn_hal.spiWrite(cmd, buf, len); } -void HAL_ESP32::spiWrite(uint8_t cmd, const uint8_t *buf, int len) +void HAL_ESP32::spiWrite(uint8_t cmd, const uint8_t *buf, size_t len) { memset(&spiTransaction, 0, sizeof(spiTransaction)); spiTransaction.addr = cmd; @@ -167,12 +178,12 @@ void HAL_ESP32::spiWrite(uint8_t cmd, const uint8_t *buf, int len) ESP_ERROR_CHECK(err); } -void hal_spi_read(u1_t cmd, u1_t *buf, int len) +void hal_spi_read(u1_t cmd, u1_t *buf, size_t len) { ttn_hal.spiRead(cmd, buf, len); } -void HAL_ESP32::spiRead(uint8_t cmd, uint8_t *buf, int len) +void HAL_ESP32::spiRead(uint8_t cmd, uint8_t *buf, size_t len) { memset(buf, 0, len); memset(&spiTransaction, 0, sizeof(spiTransaction)); diff --git a/src/hal/hal_esp32.h b/src/hal/hal_esp32.h index 3dd5ad2..5a7a3c6 100644 --- a/src/hal/hal_esp32.h +++ b/src/hal/hal_esp32.h @@ -63,8 +63,8 @@ public: void initCriticalSection(); void enterCriticalSection(); void leaveCriticalSection(); - void spiWrite(uint8_t cmd, const uint8_t *buf, int len); - void spiRead(uint8_t cmd, uint8_t *buf, int len); + void spiWrite(uint8_t cmd, const uint8_t *buf, size_t len); + void spiRead(uint8_t cmd, uint8_t *buf, size_t len); uint8_t checkTimer(uint32_t time); void sleep(); void waitUntil(uint32_t time); diff --git a/src/lmic/config.h b/src/lmic/config.h index 1750907..253fd0a 100755 --- a/src/lmic/config.h +++ b/src/lmic/config.h @@ -171,4 +171,11 @@ # endif // defined(LMIC_DISABLE_DR_LEGACY) #endif // LMIC_DR_LEGACY +// LMIC_ENABLE_DeviceTimeReq +// enable support for MCMD_DeviceTimeReq and MCMD_DeviceTimeAns +// this is always defined, and non-zero to enable it. +#if !defined(LMIC_ENABLE_DeviceTimeReq) +# define LMIC_ENABLE_DeviceTimeReq 0 +#endif + #endif // _lmic_config_h_ diff --git a/src/lmic/hal.h b/src/lmic/hal.h index dab1f67..5b610f4 100755 --- a/src/lmic/hal.h +++ b/src/lmic/hal.h @@ -26,8 +26,12 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _hal_hpp_ -#define _hal_hpp_ +#ifndef _lmic_hal_h_ +#define _lmic_hal_h_ + +#ifndef _oslmic_types_h_ +# include "oslmic_types.h" +#endif #ifdef __cplusplus extern "C"{ @@ -35,21 +39,20 @@ extern "C"{ /* * initialize hardware (IO, SPI, TIMER, IRQ). + * This API is deprecated as it uses the const global lmic_pins, + * which the platform can't control or change. */ void hal_init (void); /* - * initialize hardware, passing in platform-specific context + * Initialize hardware, passing in platform-specific context + * The pointer is to a HalPinmap_t. */ void hal_init_ex (const void *pContext); /* - * drive radio NSS pin (0=low, 1=high). - */ -void hal_pin_nss (u1_t val); - -/* - * drive radio RX/TX pins (0=rx, 1=tx). + * drive radio RX/TX pins (0=rx, 1=tx). Actual polarity + * is determined by the value of HalPinmap_t::rxtx_rx_active. */ void hal_pin_rxtx (u1_t val); @@ -58,29 +61,19 @@ void hal_pin_rxtx (u1_t val); */ void hal_pin_rst (u1_t val); -// BEGIN ttn-esp32 change -// use higher level SPI functions /* * Perform SPI write transaction with radio chip * - write the command byte 'cmd' * - write 'len' bytes out of 'buf' */ -void hal_spi_write(u1_t cmd, const u1_t* buf, int len); +void hal_spi_write(u1_t cmd, const u1_t* buf, size_t len); /* * Perform SPI read transaction with radio chip * - write the command byte 'cmd' * - read 'len' bytes into 'buf' */ -void hal_spi_read(u1_t cmd, u1_t* buf, int len); - -/* - * perform 8-bit SPI transaction with radio. - * - write given byte 'outval' - * - read byte and return value - */ -//u1_t hal_spi (u1_t outval); -// END ttn-esp32 change +void hal_spi_read(u1_t cmd, u1_t* buf, size_t len); /* * disable all CPU interrupts. @@ -128,8 +121,18 @@ void hal_failed (const char *file, u2_t line); */ s1_t hal_getRssiCal (void); +/* + * control the radio state + * - if val == 0, turn tcxo off and otherwise prepare for sleep + * - if val == 1, turn tcxo on and otherwise prep for activity + * - return the number of ticks that we need to wait + */ +ostime_t hal_setModuleActive (bit_t val); + +bit_t hal_queryUsingTcxo(void); + #ifdef __cplusplus } // extern "C" #endif -#endif // _hal_hpp_ +#endif // _lmic_hal_h_ diff --git a/src/lmic/lmic.c b/src/lmic/lmic.c old mode 100644 new mode 100755 index 9f11d56..a7f253c --- a/src/lmic/lmic.c +++ b/src/lmic/lmic.c @@ -713,6 +713,38 @@ scan_mac_cmds( oidx += 2; continue; } /* end case */ + case MCMD_DeviceTimeAns: { +#if LMIC_ENABLE_DeviceTimeReq + // don't process a spurious downlink. + if ( LMIC.txDeviceTimeReqState == lmic_RequestTimeState_rx ) { + // remember that it's time to notify the client. + LMIC.txDeviceTimeReqState = lmic_RequestTimeState_success; + + // the network time is linked to the time of the last TX. + LMIC.localDeviceTime = LMIC.txend; + + // save the network time. + // The first 4 bytes contain the seconds since the GPS epoch + // (i.e January the 6th 1980 at 00:00:00 UTC). + // Note: as per the LoRaWAN specs, the octet order for all + // multi-octet fields is little endian + // Note: the casts are necessary, because opts is an array of + // single byte values, and they might overflow when shifted + LMIC.netDeviceTime = ( (lmic_gpstime_t) opts[oidx + 1] ) | + (((lmic_gpstime_t) opts[oidx + 2]) << 8) | + (((lmic_gpstime_t) opts[oidx + 3]) << 16) | + (((lmic_gpstime_t) opts[oidx + 4]) << 24); + + // The 5th byte contains the fractional seconds in 2^-8 second steps + LMIC.netDeviceTimeFrac = opts[oidx + 5]; +#if LMIC_DEBUG_LEVEL > 0 + LMIC_DEBUG_PRINTF("%"LMIC_PRId_ostime_t": MAC command DeviceTimeAns received: seconds_since_gps_epoch=%"PRIu32", fractional_seconds=%d\n", os_getTime(), LMIC.netDeviceTime, LMIC.netDeviceTimeFrac); +#endif + } +#endif // LMIC_ENABLE_DeviceTimeReq + oidx += 6; + continue; + } /* end case */ } /* end switch */ /* unrecognized mac commands fall out of switch to here */ EV(specCond, ERR, (e_.reason = EV::specCond_t::BAD_MAC_CMD, @@ -1139,7 +1171,8 @@ static bit_t processJoinAccept (void) { LMIC.datarate = AS923_DR_SF10; #endif } - LMIC.opmode &= ~(OP_JOINING|OP_TRACK|OP_REJOIN|OP_TXRXPEND|OP_PINGINI) | OP_NEXTCHNL; + LMIC.opmode &= ~(OP_JOINING|OP_TRACK|OP_REJOIN|OP_TXRXPEND|OP_PINGINI); + LMIC.opmode |= OP_NEXTCHNL; LMIC.txCnt = 0; stateJustJoined(); LMIC.dn2Dr = LMIC.frame[OFF_JA_DLSET] & 0x0F; @@ -1328,6 +1361,13 @@ static void buildDataFrame (void) { LMIC.txParamSetupAns = 0; } #endif +#if LMIC_ENABLE_DeviceTimeReq + if ( LMIC.txDeviceTimeReqState == lmic_RequestTimeState_tx ) { + LMIC.frame[end+0] = MCMD_DeviceTimeReq; + end += 1; + LMIC.txDeviceTimeReqState = lmic_RequestTimeState_rx; + } +#endif // LMIC_ENABLE_DeviceTimeReq ASSERT(end <= OFF_DAT_OPTS+16); u1_t flen = end + (txdata ? 5+dlen : 4); @@ -1587,6 +1627,24 @@ static bit_t processDnData (void) { LMIC.dataBeg = LMIC.dataLen = 0; txcomplete: LMIC.opmode &= ~(OP_TXDATA|OP_TXRXPEND); + +#if LMIC_ENABLE_DeviceTimeReq + lmic_request_time_state_t const requestTimeState = LMIC.txDeviceTimeReqState; + if ( requestTimeState != lmic_RequestTimeState_idle ) { + lmic_request_network_time_cb_t * const pNetworkTimeCb = LMIC.pNetworkTimeCb; + int flagSuccess = (LMIC.txDeviceTimeReqState == lmic_RequestTimeState_success); + LMIC.txDeviceTimeReqState = lmic_RequestTimeState_idle; + if (pNetworkTimeCb != NULL) { + // reset the callback, so that the user's routine + // can post another request if desired. + LMIC.pNetworkTimeCb = NULL; + + // call the user's notification routine. + (*pNetworkTimeCb)(LMIC.pNetworkTimeUserData, flagSuccess); + } + } +#endif // LMIC_ENABLE_DeviceTimeReq + if( (LMIC.txrxFlags & (TXRX_DNW1|TXRX_DNW2|TXRX_PING)) != 0 && (LMIC.opmode & OP_LINKDEAD) != 0 ) { LMIC.opmode &= ~OP_LINKDEAD; reportEvent(EV_LINK_ALIVE); @@ -1728,12 +1786,11 @@ static void engineUpdate (void) { #endif // !DISABLE_JOIN ostime_t now = os_getTime(); - ostime_t rxtime = 0; ostime_t txbeg = 0; - // ttn-esp32: suppress unused variable - LMIC_UNREFERENCED_VARIABLE(rxtime); #if !defined(DISABLE_BEACONS) + ostime_t rxtime = 0; + if( (LMIC.opmode & OP_TRACK) != 0 ) { // We are tracking a beacon ASSERT( now + RX_RAMPUP - LMIC.bcnRxtime <= 0 ); @@ -1929,6 +1986,11 @@ void LMIC_reset (void) { DO_DEVDB(LMIC.ping.dr, pingDr); DO_DEVDB(LMIC.ping.intvExp, pingIntvExp); #endif // !DISABLE_PING +#if LMIC_ENABLE_DeviceTimeReq + LMIC.txDeviceTimeReqState = lmic_RequestTimeState_idle; + LMIC.netDeviceTime = 0; // the "invalid" time. + LMIC.netDeviceTimeFrac = 0; +#endif // LMIC_ENABLE_DeviceTimeReq } @@ -1970,7 +2032,6 @@ int LMIC_setTxData2 (u1_t port, xref2u1_t data, u1_t dlen, u1_t confirmed) { return 0; } - // Send a payload-less message to signal device is alive void LMIC_sendAlive (void) { LMIC.opmode |= OP_POLL; @@ -2068,3 +2129,36 @@ void LMIC_getSessionKeys (u4_t *netid, devaddr_t *devaddr, xref2u1_t nwkKey, xre memcpy(artKey, LMIC.artKey, sizeof(LMIC.artKey)); memcpy(nwkKey, LMIC.nwkKey, sizeof(LMIC.nwkKey)); } + +// \brief post an asynchronous request for the network time. +void LMIC_requestNetworkTime(lmic_request_network_time_cb_t *pCallbackfn, void *pUserData) { +#if LMIC_ENABLE_DeviceTimeReq + if (LMIC.txDeviceTimeReqState == lmic_RequestTimeState_idle) { + LMIC.txDeviceTimeReqState = lmic_RequestTimeState_tx; + LMIC.pNetworkTimeCb = pCallbackfn; + LMIC.pNetworkTimeUserData = pUserData; + return; + } +#endif // LMIC_ENABLE_DeviceTimeReq + // if no device time support, or if not in proper state, + // report a failure. + if (pCallbackfn != NULL) + (*pCallbackfn)(pUserData, /* false */ 0); +} + +// \brief return local/remote time pair (if valid, and DeviceTimeReq enabled), +// return true for success, false for error. We adjust the sampled OS time +// back in time to the nearest second boundary. +int LMIC_getNetworkTimeReference(lmic_time_reference_t *pReference) { +#if LMIC_ENABLE_DeviceTimeReq + if (pReference != NULL && // valid parameter, and + LMIC.netDeviceTime != 0) { // ... we have a reasonable answer. + const ostime_t tAdjust = LMIC.netDeviceTimeFrac * ms2osticks(1000) / 256; + + pReference->tLocal = LMIC.localDeviceTime - tAdjust; + pReference->tNetwork = LMIC.netDeviceTime; + return 1; + } +#endif // LMIC_ENABLE_DeviceTimeReq + return 0; +} diff --git a/src/lmic/lmic.h b/src/lmic/lmic.h old mode 100644 new mode 100755 index fa27d96..331d5a3 --- a/src/lmic/lmic.h +++ b/src/lmic/lmic.h @@ -1,7 +1,7 @@ /* * Copyright (c) 2014-2016 IBM Corporation. * Copyright (c) 2016 Matthijs Kooijman. - * 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 @@ -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, 2, 2, 0) +#define ARDUINO_LMIC_VERSION ARDUINO_LMIC_VERSION_CALC(2, 3, 2, 0) /* v2.3.2 */ #define ARDUINO_LMIC_VERSION_GET_MAJOR(v) \ (((v) >> 24u) & 0xFFu) @@ -243,6 +243,35 @@ enum { MAX_CLOCK_ERROR = 65536, }; +// 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 +// without time request, "completing" the pending time request. +typedef void LMIC_ABI_STD lmic_request_network_time_cb_t(void *pUserData, int flagSuccess); + +// how the network represents time. +typedef u4_t lmic_gpstime_t; + +// rather than deal with 1/256 second tick, we adjust ostime back +// (as it's high res) to match tNetwork. +typedef struct lmic_time_reference_s lmic_time_reference_t; + +struct lmic_time_reference_s { + // our best idea of when we sent the uplink (end of packet). + ostime_t tLocal; + // the network's best idea of when we sent the uplink. + lmic_gpstime_t tNetwork; +}; + +enum lmic_request_time_state_e { + lmic_RequestTimeState_idle = 0, // we're not doing anything + lmic_RequestTimeState_tx, // we want to tx a time request on next uplink + lmic_RequestTimeState_rx, // we have tx'ed, next downlink completes. + lmic_RequestTimeState_success // we sucessfully got time. +}; + +typedef u1_t lmic_request_time_state_t; + struct lmic_t { // Radio settings TX/RX (also accessed by HAL) ostime_t txend; @@ -306,6 +335,14 @@ struct lmic_t { 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) @@ -329,6 +366,10 @@ struct lmic_t { bit_t txParamSetupAns; // transmit setup answer pending. u1_t txParam; // the saved TX param byte. #endif +#if LMIC_ENABLE_DeviceTimeReq + lmic_request_time_state_t txDeviceTimeReqState; // current state, initially idle. + u1_t netDeviceTimeFrac; // updated on any DeviceTimeAns. +#endif // rx1DrOffset is the offset from uplink to downlink datarate u1_t rx1DrOffset; // captured from join. zero by default. @@ -368,6 +409,7 @@ struct lmic_t { u1_t noRXIQinversion; }; + //! \var struct lmic_t LMIC //! The state of LMIC MAC layer is encapsulated in this variable. DECLARE_LMIC; //!< \internal @@ -417,6 +459,9 @@ u4_t LMIC_getSeqnoUp (void); u4_t LMIC_setSeqnoUp (u4_t); void LMIC_getSessionKeys (u4_t *netid, devaddr_t *devaddr, xref2u1_t nwkKey, xref2u1_t artKey); +void LMIC_requestNetworkTime(lmic_request_network_time_cb_t *pCallbackfn, void *pUserData); +int LMIC_getNetworkTimeReference(lmic_time_reference_t *pReference); + // Declare onEvent() function, to make sure any definition will have the // C conventions, even when in a C++ file. DECL_ON_LMIC_EVENT; diff --git a/src/lmic/lmic_as923.c b/src/lmic/lmic_as923.c old mode 100644 new mode 100755 diff --git a/src/lmic/lmic_au921.c b/src/lmic/lmic_au921.c old mode 100644 new mode 100755 diff --git a/src/lmic/lmic_config_preconditions.h b/src/lmic/lmic_config_preconditions.h old mode 100644 new mode 100755 index 6f5bbcc..49be1d5 --- a/src/lmic/lmic_config_preconditions.h +++ b/src/lmic/lmic_config_preconditions.h @@ -114,6 +114,12 @@ Revision history: // following values. These are in order of the sections in the manual. Not all of the // below are supported yet. // +// CFG_as923jp is treated as a special case of CFG_as923, so it's not included in +// the below. +// +// TODO(tmm@mcci.com) consider moving this block to a central file as it's not +// user-editable. +// # define CFG_LMIC_REGION_MASK \ ((defined(CFG_eu868) << LMIC_REGION_eu868) | \ (defined(CFG_us915) << LMIC_REGION_us915) | \ @@ -127,6 +133,8 @@ Revision history: 0) // the selected region. +// TODO(tmm@mcci.com) consider moving this block to a central file as it's not +// user-editable. #if defined(CFG_eu868) # define CFG_region LMIC_REGION_eu868 #elif defined(CFG_us915) @@ -139,6 +147,10 @@ Revision history: # define CFG_region LMIC_REGION_au921 #elif defined(CFG_cn490) # define CFG_region LMIC_REGION_cn490 +#elif defined(CFG_as923jp) +# define CFG_as923 1 /* CFG_as923jp implies CFG_as923 */ +# define CFG_region LMIC_REGION_as923 +# define LMIC_COUNTRY_CODE LMIC_COUNTRY_CODE_JP #elif defined(CFG_as923) # define CFG_region LMIC_REGION_as923 #elif defined(CFG_kr921) @@ -149,7 +161,11 @@ Revision history: # define CFG_region 0 #endif -// finally the mask of` US-like and EU-like regions +// a bitmask of EU-like regions -- these are regions which have up to 16 +// channels indidually programmable via downloink. +// +// TODO(tmm@mcci.com) consider moving this block to a central file as it's not +// user-editable. #define CFG_LMIC_EU_like_MASK ( \ (1 << LMIC_REGION_eu868) | \ /* (1 << LMIC_REGION_us915) | */ \ @@ -162,6 +178,12 @@ Revision history: (1 << LMIC_REGION_in866) | \ 0) +// a bitmask of` US-like regions -- these are regions with 64 fixed 125 kHz channels +// overlaid by 8 500 kHz channels. The channel frequencies can't be changed, but +// subsets of channels can be selected via masks. +// +// TODO(tmm@mcci.com) consider moving this block to a central file as it's not +// user-editable. #define CFG_LMIC_US_like_MASK ( \ /* (1 << LMIC_REGION_eu868) | */ \ (1 << LMIC_REGION_us915) | \ @@ -174,9 +196,12 @@ Revision history: /* (1 << LMIC_REGION_in866) | */ \ 0) +// +// booleans that are true if the configured region is EU-like or US-like. +// TODO(tmm@mcci.com) consider moving this block to a central file as it's not +// user-editable. +// #define CFG_LMIC_EU_like (!!(CFG_LMIC_REGION_MASK & CFG_LMIC_EU_like_MASK)) #define CFG_LMIC_US_like (!!(CFG_LMIC_REGION_MASK & CFG_LMIC_US_like_MASK)) - - #endif /* _LMIC_CONFIG_PRECONDITIONS_H_ */ diff --git a/src/lmic/lmic_env.h b/src/lmic/lmic_env.h new file mode 100755 index 0000000..4610fb3 --- /dev/null +++ b/src/lmic/lmic_env.h @@ -0,0 +1,217 @@ +/* + +Module: lmic_env.h + +Function: + Sets up macros etc. to make things a little easier for portabilty + +Copyright notice and license info: + See LICENSE file accompanying this project. + +Author: + Terry Moore, MCCI Corporation November 2018 + +Description: + This file is an adaptation of MCCI's standard IOCTL framework. + We duplicate a bit of functionality that we might get from other + libraries, so that the LMIC library can continue to stand alone. + +*/ + +#ifndef _lmic_env_h_ /* prevent multiple includes */ +#define _lmic_env_h_ + +/* + +Macro: LMIC_C_ASSERT() + +Function: + Declaration-like macro that will cause a compile error if arg is FALSE. + +Definition: + LMIC_C_ASSERT( + BOOL fErrorIfFalse + ); + +Description: + This macro, if used where an external reference declarataion is + permitted, will either compile cleanly, or will cause a compilation + error. The results of using this macro where a declaration is not + permitted are unspecified. + + This is different from #if !(fErrorIfFalse) / #error in that the + expression is evaluated by the compiler rather than by the pre- + processor. Therefore things like sizeof() can be used. + +Returns: + No explicit result -- either compiles cleanly or causes a compile + error. + +*/ + +#ifndef LMIC_C_ASSERT +# define LMIC_C_ASSERT(e) \ + void LMIC_C_ASSERT__(int LMIC_C_ASSERT_x[(e) ? 1: -1]) +#endif + +/****************************************************************************\ +| +| Define the begin/end declaration tags for C++ co-existance +| +\****************************************************************************/ + +#ifdef __cplusplus +# define LMIC_BEGIN_DECLS extern "C" { +# define LMIC_END_DECLS } +#else +# define LMIC_BEGIN_DECLS /* nothing */ +# define LMIC_END_DECLS /* nothing */ +#endif + +//---------------------------------------------------------------------------- +// Annotations to avoid various "unused" warnings. These must appear as a +// statement in the function body; the macro annotates the variable to quiet +// compiler warnings. The way this is done is compiler-specific, and so these +// definitions are fall-backs, which might be overridden. +// +// Although these are all similar, we don't want extra macro expansions, +// so we define each one explicitly rather than relying on a common macro. +//---------------------------------------------------------------------------- + +// signal that a parameter is intentionally unused. +#ifndef LMIC_UNREFERENCED_PARAMETER +# define LMIC_UNREFERENCED_PARAMETER(v) do { (void) (v); } while (0) +#endif + +// an API parameter is a parameter that is required by an API definition, but +// happens to be unreferenced in this implementation. This is a stronger +// assertion than LMIC_UNREFERENCED_PARAMETER(): this parameter is here +// becuase of an API contract, but we have no use for it in this function. +#ifndef LMIC_API_PARAMETER +# define LMIC_API_PARAMETER(v) do { (void) (v); } while (0) +#endif + +// an intentionally-unreferenced variable. +#ifndef LMIC_UNREFERENCED_VARIABLE +# define LMIC_UNREFERENCED_VARIABLE(v) do { (void) (v); } while (0) +#endif + +// we have three (!) debug levels (LMIC_DEBUG_LEVEL > 0, LMIC_DEBUG_LEVEL > 1, +// and LMIC_X_DEBUG_LEVEL > 0. In each case we might have parameters or +// or varables that are only refereneced at the target debug level. + +// Parameter referenced only if debugging at level > 0. +#ifndef LMIC_DEBUG1_PARAMETER +# if LMIC_DEBUG_LEVEL > 0 +# define LMIC_DEBUG1_PARAMETER(v) do { ; } while (0) +# else +# define LMIC_DEBUG1_PARAMETER(v) do { (void) (v); } while (0) +# endif +#endif + +// variable referenced only if debugging at level > 0 +#ifndef LMIC_DEBUG1_VARIABLE +# if LMIC_DEBUG_LEVEL > 0 +# define LMIC_DEBUG1_VARIABLE(v) do { ; } while (0) +# else +# define LMIC_DEBUG1_VARIABLE(v) do { (void) (v); } while (0) +# endif +#endif + +// parameter referenced only if debugging at level > 1 +#ifndef LMIC_DEBUG2_PARAMETER +# if LMIC_DEBUG_LEVEL > 1 +# define LMIC_DEBUG2_PARAMETER(v) do { ; } while (0) +# else +# define LMIC_DEBUG2_PARAMETER(v) do { (void) (v); } while (0) +# endif +#endif + +// variable referenced only if debugging at level > 1 +#ifndef LMIC_DEBUG2_VARIABLE +# if LMIC_DEBUG_LEVEL > 1 +# define LMIC_DEBUG2_VARIABLE(v) do { ; } while (0) +# else +# define LMIC_DEBUG2_VARIABLE(v) do { (void) (v); } while (0) +# endif +#endif + +// parameter referenced only if LMIC_X_DEBUG_LEVEL > 0 +#ifndef LMIC_X_DEBUG_PARAMETER +# if LMIC_X_DEBUG_LEVEL > 0 +# define LMIC_X_DEBUG_PARAMETER(v) do { ; } while (0) +# else +# define LMIC_X_DEBUG_PARAMETER(v) do { (void) (v); } while (0) +# endif +#endif + +// variable referenced only if LMIC_X_DEBUG_LEVEL > 0 +#ifndef LMIC_X_DEBUG_VARIABLE +# if LMIC_X_DEBUG_LEVEL > 0 +# define LMIC_X_DEBUG_VARIABLE(v) do { ; } while (0) +# else +# define LMIC_X_DEBUG_VARIABLE(v) do { (void) (v); } while (0) +# endif +#endif + +// parameter referenced only if EV() macro is enabled (which it never is) +// TODO(tmm@mcci.com) take out the EV() framework as it reuqires C++, and +// this code is really C-99 to its bones. +#ifndef LMIC_EV_PARAMETER +# define LMIC_EV_PARAMETER(v) do { (void) (v); } while (0) +#endif + +// variable referenced only if EV() macro is defined. +#ifndef LMIC_EV_VARIABLE +# define LMIC_EV_VARIABLE(v) do { (void) (v); } while (0) +#endif + + /* + +Macro: LMIC_ABI_STD + +Index: Macro: LMIC_ABI_VARARGS + +Function: + Annotation macros to force a particular binary calling sequence. + +Definition: + #define LMIC_ABI_STD compiler-specific + #define LMIC_ABI_VARARGS compiler-specific + +Description: + These macros are used when declaring a function type, and indicate + that a particular calling sequence is to be used. They are normally + used between the type portion of the function declaration and the + name of the function. For example: + + typedef void LMIC_ABI_STD myCallBack_t(void); + + It's important to use this in libraries on platforms with multiple + calling sequences, because different components can be compiled with + different defaults. + +Returns: + Not applicable. + +*/ + +/* ABI marker for normal (fixed parameter count) functions -- used for function types */ +#ifndef LMIC_ABI_STD +# ifdef _MSC_VER +# define LMIC_ABI_STD __stdcall +# else +# define LMIC_ABI_STD /* nothing */ +# endif +#endif + +/* ABI marker for VARARG functions -- used for function types */ +#ifndef LMIC_ABI_VARARGS +# ifdef _MSC_VER +# define LMIC_ABI_VARARGS __cdecl +# else +# define LMIC_ABI_VARARGS /* nothing */ +# endif +#endif + +#endif /* _lmic_env_h_ */ \ No newline at end of file diff --git a/src/lmic/lmic_eu_like.c b/src/lmic/lmic_eu_like.c old mode 100644 new mode 100755 diff --git a/src/lmic/lmic_in866.c b/src/lmic/lmic_in866.c old mode 100644 new mode 100755 diff --git a/src/lmic/lmic_us915.c b/src/lmic/lmic_us915.c old mode 100644 new mode 100755 diff --git a/src/lmic/lmic_us_like.c b/src/lmic/lmic_us_like.c old mode 100644 new mode 100755 diff --git a/src/lmic/lmic_util.h b/src/lmic/lmic_util.h index d99217d..7e1b3c8 100755 --- a/src/lmic/lmic_util.h +++ b/src/lmic/lmic_util.h @@ -9,7 +9,7 @@ Copyright & License: See accompanying LICENSE file. Author: - Terry Moore, MCCI September 2019 + Terry Moore, MCCI September 2018 */ diff --git a/src/lmic/lorabase.h b/src/lmic/lorabase.h old mode 100644 new mode 100755 index a4e570f..656ea2c --- a/src/lmic/lorabase.h +++ b/src/lmic/lorabase.h @@ -449,6 +449,7 @@ enum { MCMD_RXTimingSetupAns = 0x08, // : - MCMD_TxParamSetupAns = 0x09, // : - MCMD_DIChannelAns = 0x0A, // : u1: [7-2]:RFU 1:exists 0:OK + MCMD_DeviceTimeReq = 0x0D, // Class B MCMD_PING_IND = 0x10, // - pingability indic : u1: 7=RFU, 6-4:interval, 3-0:datarate @@ -468,6 +469,7 @@ enum { MCMD_RXTimingSetupReq = 0x08, // : u1: [7-4]:RFU [3-0]: Delay 1-15s (0 => 1) MCMD_TxParamSetupReq = 0x09, // : u1: [7-6]:RFU [5:4]: dl dwell/ul dwell [3:0] max EIRP MCMD_DIChannelReq = 0x0A, // : u1: channel, u3: frequency + MCMD_DeviceTimeAns = 0x0D, // Class B MCMD_PING_SET = 0x11, // set ping freq : u3: freq diff --git a/src/lmic/oslmic.c b/src/lmic/oslmic.c old mode 100644 new mode 100755 diff --git a/src/lmic/oslmic.h b/src/lmic/oslmic.h old mode 100644 new mode 100755 index b4f10d1..7710c1d --- a/src/lmic/oslmic.h +++ b/src/lmic/oslmic.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2014-2016 IBM Corporation. + * Copyright (c) 2018 MCCI Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,29 +30,22 @@ #ifndef _oslmic_h_ #define _oslmic_h_ -// Dependencies required for the LoRa MAC in C to run. +// Dependencies required for the LMIC to run. // These settings can be adapted to the underlying system. -// You should not, however, change the lmic.[hc] +// You should not, however, change the lmic merely for porting purposes.[hc] #include "config.h" -#include -#ifdef __cplusplus -extern "C"{ +#ifndef _lmic_env_h_ +# include "lmic_env.h" #endif -//================================================================================ -//================================================================================ -// Target platform as C library -typedef uint8_t bit_t; -typedef uint8_t u1_t; -typedef int8_t s1_t; -typedef uint16_t u2_t; -typedef int16_t s2_t; -typedef uint32_t u4_t; -typedef int32_t s4_t; -typedef unsigned int uint; -typedef const char* str_t; +#ifndef _oslmic_types_h_ +# include "oslmic_types.h" +#endif + +LMIC_BEGIN_DECLS + #include #include "hal.h" @@ -73,7 +67,6 @@ typedef struct rxsched_t rxsched_t; typedef struct bcninfo_t bcninfo_t; typedef const u1_t* xref2cu1_t; typedef u1_t* xref2u1_t; -typedef s4_t ostime_t; // int32_t == s4_t is long on some platforms; and someday // we will want 64-bit ostime_t. So, we will use a macro for the @@ -91,105 +84,6 @@ typedef s4_t ostime_t; #define SIZEOFEXPR(x) sizeof(x) -//---------------------------------------------------------------------------- -// Annotations to avoid various "unused" warnings. These must appear as a -// statement in the function body; the macro annotates the variable to quiet -// compiler warnings. The way this is done is compiler-specific, and so these -// definitions are fall-backs, which might be overridden. -// -// Although these are all similar, we don't want extra macro expansions, -// so we define each one explicitly rather than relying on a common macro. -//---------------------------------------------------------------------------- - -// signal that a parameter is intentionally unused. -#ifndef LMIC_UNREFERENCED_PARAMETER -# define LMIC_UNREFERENCED_PARAMETER(v) do { (void) (v); } while (0) -#endif - -// an API parameter is a parameter that is required by an API definition, but -// happens to be unreferenced in this implementation. This is a stronger -// assertion than LMIC_UNREFERENCED_PARAMETER(): this parameter is here -// becuase of an API contract, but we have no use for it in this function. -#ifndef LMIC_API_PARAMETER -# define LMIC_API_PARAMETER(v) do { (void) (v); } while (0) -#endif - -// an intentionally-unreferenced variable. -#ifndef LMIC_UNREFERENCED_VARIABLE -# define LMIC_UNREFERENCED_VARIABLE(v) do { (void) (v); } while (0) -#endif - -// we have three (!) debug levels (LMIC_DEBUG_LEVEL > 0, LMIC_DEBUG_LEVEL > 1, -// and LMIC_X_DEBUG_LEVEL > 0. In each case we might have parameters or -// or varables that are only refereneced at the target debug level. - -// Parameter referenced only if debugging at level > 0. -#ifndef LMIC_DEBUG1_PARAMETER -# if LMIC_DEBUG_LEVEL > 0 -# define LMIC_DEBUG1_PARAMETER(v) do { ; } while (0) -# else -# define LMIC_DEBUG1_PARAMETER(v) do { (void) (v); } while (0) -# endif -#endif - -// variable referenced only if debugging at level > 0 -#ifndef LMIC_DEBUG1_VARIABLE -# if LMIC_DEBUG_LEVEL > 0 -# define LMIC_DEBUG1_VARIABLE(v) do { ; } while (0) -# else -# define LMIC_DEBUG1_VARIABLE(v) do { (void) (v); } while (0) -# endif -#endif - -// parameter referenced only if debugging at level > 1 -#ifndef LMIC_DEBUG2_PARAMETER -# if LMIC_DEBUG_LEVEL > 1 -# define LMIC_DEBUG2_PARAMETER(v) do { ; } while (0) -# else -# define LMIC_DEBUG2_PARAMETER(v) do { (void) (v); } while (0) -# endif -#endif - -// variable referenced only if debugging at level > 1 -#ifndef LMIC_DEBUG2_VARIABLE -# if LMIC_DEBUG_LEVEL > 1 -# define LMIC_DEBUG2_VARIABLE(v) do { ; } while (0) -# else -# define LMIC_DEBUG2_VARIABLE(v) do { (void) (v); } while (0) -# endif -#endif - -// parameter referenced only if LMIC_X_DEBUG_LEVEL > 0 -#ifndef LMIC_X_DEBUG_PARAMETER -# if LMIC_X_DEBUG_LEVEL > 0 -# define LMIC_X_DEBUG_PARAMETER(v) do { ; } while (0) -# else -# define LMIC_X_DEBUG_PARAMETER(v) do { (void) (v); } while (0) -# endif -#endif - -// variable referenced only if LMIC_X_DEBUG_LEVEL > 0 -#ifndef LMIC_X_DEBUG_VARIABLE -# if LMIC_X_DEBUG_LEVEL > 0 -# define LMIC_X_DEBUG_VARIABLE(v) do { ; } while (0) -# else -# define LMIC_X_DEBUG_VARIABLE(v) do { (void) (v); } while (0) -# endif -#endif - -// parameter referenced only if EV() macro is enabled (which it never is) -// TODO(tmm@mcci.com) take out the EV() framework as it reuqires C++, and -// this code is really C-99 to its bones. -#ifndef LMIC_EV_PARAMETER -# define LMIC_EV_PARAMETER(v) do { (void) (v); } while (0) -#endif - -// variable referenced only if EV() macro is defined. -#ifndef LMIC_EV_VARIABLE -# define LMIC_EV_VARIABLE(v) do { (void) (v); } while (0) -#endif - - #define ON_LMIC_EVENT(ev) onEvent(ev) #define DECL_ON_LMIC_EVENT void onEvent(ev_t e) @@ -416,8 +310,6 @@ extern xref2u1_t AESaux; u4_t os_aes (u1_t mode, xref2u1_t buf, u2_t len); #endif -#ifdef __cplusplus -} // extern "C" -#endif +LMIC_END_DECLS #endif // _oslmic_h_ diff --git a/src/lmic/oslmic_types.h b/src/lmic/oslmic_types.h new file mode 100755 index 0000000..d790a37 --- /dev/null +++ b/src/lmic/oslmic_types.h @@ -0,0 +1,47 @@ +/* + +Module: oslmic_types.h + +Function: + Basic types from oslmic.h, shared by all layers. + +Copyright & License: + See accompanying LICENSE file. + +Author: + Terry Moore, MCCI November 2018 + (based on oslmic.h from IBM). + +*/ + +#ifndef _oslmic_types_h_ +# define _oslmic_types_h_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +//================================================================================ +//================================================================================ +// Target platform as C library +typedef uint8_t bit_t; +typedef uint8_t u1_t; +typedef int8_t s1_t; +typedef uint16_t u2_t; +typedef int16_t s2_t; +typedef uint32_t u4_t; +typedef int32_t s4_t; +typedef unsigned int uint; +typedef const char* str_t; + +// the HAL needs to give us ticks, so it ought to know the right type. +typedef s4_t ostime_t; + +#ifdef __cplusplus +} +#endif + +/* end of oslmic_types.h */ +#endif /* _oslmic_types_h_ */ diff --git a/src/lmic/radio.c b/src/lmic/radio.c old mode 100644 new mode 100755 index 8f943ac..5320a1c --- a/src/lmic/radio.c +++ b/src/lmic/radio.c @@ -135,13 +135,22 @@ // #define RegAgcThresh2 0x45 // common // #define RegAgcThresh3 0x46 // common // #define RegPllHop 0x4B // common -#define RegPaDac 0x4D // common // #define RegTcxo 0x58 // common // #define RegPll 0x5C // common // #define RegPllLowPn 0x5E // common // #define RegFormerTemp 0x6C // common // #define RegBitRateFrac 0x70 // common +#if defined(CFG_sx1276_radio) +#define RegTcxo 0x4B // common +#define RegPaDac 0x4D // common +#elif defined(CFG_sx1272_radio) +#define RegTcxo 0x58 // common +#define RegPaDac 0x5A // common +#endif + +#define RegTcxo_TcxoInputOn (1u << 4) + // ---------------------------------------- // spread factors and mode for RegModemConfig2 #define SX1272_MC2_FSK 0x00 @@ -290,58 +299,41 @@ static u1_t randbuf[16]; static void writeReg (u1_t addr, u1_t data ) { - // ttn-esp32 change: higher level SPI interface hal_spi_write(addr | 0x80, &data, 1); - /* - hal_pin_nss(0); - hal_spi(addr | 0x80); - hal_spi(data); - hal_pin_nss(1); - */ } static u1_t readReg (u1_t addr) { - // ttn-esp32 change: higher level SPI interface u1_t buf[1]; hal_spi_read(addr & 0x7f, buf, 1); return buf[0]; - /* - hal_pin_nss(0); - hal_spi(addr & 0x7F); - u1_t val = hal_spi(0x00); - hal_pin_nss(1); - return val; - */ } static void writeBuf (u1_t addr, xref2u1_t buf, u1_t len) { - // ttn-esp32 change: higher level SPI interface hal_spi_write(addr | 0x80, buf, len); - /* - hal_pin_nss(0); - hal_spi(addr | 0x80); - for (u1_t i=0; i