Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of LoRaWAN-grove-cayenne by
Revision 0:62e456e60083, committed 2018-02-28
- Comitter:
- Wayne Roberts
- Date:
- Wed Feb 28 14:06:17 2018 -0800
- Child:
- 1:3c1d13a0489e
- Commit message:
- initial commit
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Commissioning.h Wed Feb 28 14:06:17 2018 -0800
@@ -0,0 +1,94 @@
+/*
+ / _____) _ | |
+( (____ _____ ____ _| |_ _____ ____| |__
+ \____ \| ___ | (_ _) ___ |/ ___) _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+ (C)2018 Semtech
+
+Description: End device commissioning parameters
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+*/
+#ifndef __LORA_COMMISSIONING_H__
+#define __LORA_COMMISSIONING_H__
+
+#define USE_BAND_915_HYBRID
+//#define USE_BAND_915
+//#define USE_BAND_ARIB_8CH
+//#define USE_BAND_868
+//#define USE_BAND_433
+//#define USE_BAND_470
+//#define USE_BAND_780
+
+
+#define ENABLE_VT100
+
+#ifdef ENABLE_VT100
+ #define ROW_MLME_IND (ROW_END+1)
+ #define ROW_MLME_CONF (ROW_END+2)
+ #define ROW_MCPS_IND (ROW_END+3)
+ #define ROW_MCPS_CONF (ROW_END+4)
+ #define ROW_MIC (ROW_END+5)
+#else
+ #define ROW_MIC 0
+#endif
+
+/*!
+ * Indicates if the end-device is to be connected to a private or public network
+ */
+#define LORAWAN_PUBLIC_NETWORK true
+
+/*!
+ * Mote device IEEE EUI (big endian)
+ *
+ * \remark In this application the value is automatically generated by calling
+ * BoardGetUniqueId function
+ */
+
+#define LORAWAN_DEVICE_EUI { 0x19,0x51,0x34,0x30,0x9E,0x30,0x6A,0x37 } // home net 000001
+//#define LORAWAN_DEVICE_EUI { 0x3e,0xbe,0x24,0xb1,0x6b,0x7b,0x9c,0xfc } // home net 6000ff
+/*!
+* Join IEEE EUI (big endian): undefine for ABP
+*/
+#define LORAWAN_JOIN_EUI { 0x64,0x7F,0xDA,0x80,0x00,0x00,0x01,0x2E }
+
+/*!
+* AES encryption/decryption cipher application key
+* 00112233445566778899aabbccddeeff */
+#define LORAWAN_ROOT_NWKKEY { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff }
+
+// d2fc83ea58cf0fbc973dbd07a7115486 lorawan-1.1 OTA only
+//#define LORAWAN_ROOT_APPKEY { 0xd2,0xfc,0x83,0xea,0x58,0xcf,0x0f,0xbc,0x97,0x3d,0xbd,0x07,0xa7,0x11,0x54,0x86 } // uncomment for lorawan1v1, or comment for lorawan1v0
+
+
+#ifndef LORAWAN_JOIN_EUI /* ABP mote: */
+ /*
+ * AppSkey: 09763a2d1c29831ea073b24d5d12f084
+ * FNwkSIntKey: 15aed1b53c90518e1c6170c12a315429
+ * SNwkSintKey: 37fe10c4c31a26f9d027180bc192567f 1v1 ABP
+ * NwkSEncKey: f765291c0b18720d9f62a13c4c01ef73 1v1 ABP
+ */
+ #define LORAWAN_FNwkSIntKey {0x15, 0xae, 0xd1, 0xb5, 0x3c, 0x90, 0x51, 0x8e, 0x1c, 0x61, 0x70, 0xc1, 0x2a, 0x31, 0x54, 0x29}
+ #define LORAWAN_APPSKEY {0x09, 0x76, 0x3a, 0x2d, 0x1c, 0x29, 0x83, 0x1e, 0xa0, 0x73, 0xb2, 0x4d, 0x5d, 0x12, 0xf0, 0x84}
+ //#define LORAWAN_SNwkSIntKey {0x37, 0xfe, 0x10, 0xc4, 0xc3, 0x1a, 0x26, 0xf9, 0xd0, 0x27, 0x18, 0x0b, 0xc1, 0x92, 0x56, 0x7f} // 1v1
+ //#define LORAWAN_NwkSEncKey {0xf7, 0x65, 0x29, 0x1c, 0x0b, 0x18, 0x72, 0x0d, 0x9f, 0x62, 0xa1, 0x3c, 0x4c, 0x01, 0xef, 0x73} // 1v1
+ #if defined(LORAWAN_SNwkSIntKey) && defined(LORAWAN_NwkSEncKey)
+ #define OPTNEG
+ #define LORAWAN_DEVICE_ADDRESS ( uint32_t )0x02000555 // 1v1 provisioned netid 000001
+ //#define LORAWAN_DEVICE_ADDRESS ( uint32_t )0xe3fc0555 // 1v1 provisioned netid 6000ff
+ #else
+ #undef OPTNEG
+ #define LORAWAN_DEVICE_ADDRESS ( uint32_t )0x02000aaa // 1v0 provisioned
+ #endif
+#else
+ #ifdef LORAWAN_ROOT_APPKEY
+ #define OPTNEG
+ #else
+ #undef OPTNEG
+ #endif
+#endif
+
+#endif // __LORA_COMMISSIONING_H__
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LoRaMacString.cpp Wed Feb 28 14:06:17 2018 -0800
@@ -0,0 +1,92 @@
+#include "LoRaMac.h"
+#include "LoRaMacString.h"
+
+void
+Mlme_to_string(Mlme_t mlme, char* dst)
+{
+ const char* ptr = NULL;
+
+ switch (mlme) {
+ case MLME_NONE: ptr = "NONE"; break;
+ case MLME_LINK_CHECK: ptr = "LINK_CHECK"; break;
+ case MLME_SWITCH_CLASS: ptr = "SWITCH_CLASS"; break;
+ case MLME_PING_SLOT_INFO: ptr = "PING_SLOT_INFO"; break;
+ case MLME_BEACON_TIMING: ptr = "BEACON_TIMING"; break;
+ case MLME_BEACON_ACQUISITION: ptr = "BEACON_ACQUISITION"; break;
+ case MLME_TIME_REQ: ptr = "TIME_REQ"; break;
+ case MLME_BEACON: ptr = "BEACON"; break;
+ case MLME_TXCW: ptr = "TXCW"; break;
+#ifdef LORAWAN_JOIN_EUI
+ case MLME_JOIN: ptr = "JOIN"; break;
+ case MLME_REJOIN_0: ptr = "REJOIN_0"; break;
+ case MLME_REJOIN_1: ptr = "REJOIN_1"; break;
+ case MLME_REJOIN_2: ptr = "REJOIN_2"; break;
+#endif
+ }
+
+ if (ptr != NULL)
+ strcpy(dst, ptr);
+}
+
+void
+LoRaMacEventInfoStatus_to_string(LoRaMacEventInfoStatus_t status, char* dst)
+{
+ const char* ptr = NULL;
+
+ switch (status) {
+
+ case LORAMAC_EVENT_INFO_STATUS_OK: ptr = "OK"; break;
+ case LORAMAC_EVENT_INFO_STATUS_INCR_FAIL: ptr = "INCR_FAIL"; break;
+ case LORAMAC_EVENT_INFO_STATUS_MLMEREQ: ptr = "MLMEREQ"; break;
+ case LORAMAC_EVENT_INFO_STATUS_UNKNOWN_MTYPE: ptr = "UNKNOWN_MTYPE"; break;
+ case LORAMAC_EVENT_INFO_STATUS_SENDING: ptr = "SENDING"; break;
+ case LORAMAC_EVENT_INFO_STATUS_MCPSREQ: ptr = "MCPSREQ"; break;
+ case LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT: ptr = "TX_TIMEOUT"; break;
+ case LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT: ptr = "RX2_TIMEOUT"; break;
+ case LORAMAC_EVENT_INFO_STATUS_RX2_ERROR: ptr = "RX2_ERROR"; break;
+#ifdef LORAWAN_JOIN_EUI
+ case LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL: ptr = "JOIN_FAIL"; break;
+ case LORAMAC_EVENT_INFO_STATUS_JOINNONCE: ptr = "JOINNONCE"; break;
+#endif
+ case LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED: ptr = "DOWNLINK_REPEATED"; break;
+ case LORAMAC_EVENT_INFO_STATUS_TX_DR_PAYLOAD_SIZE_ERROR: ptr = "TX_DR_PAYLOAD_SIZE_ERROR"; break;
+ case LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS: ptr = "DOWNLINK_TOO_MANY_FRAMES_LOSS"; break;
+ case LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL: ptr = "ADDRESS_FAIL"; break;
+ case LORAMAC_EVENT_INFO_STATUS_MIC_FAIL: ptr = "MIC_FAIL"; break;
+ case LORAMAC_EVENT_INFO_STATUS_MULTICAST_FAIL: ptr = "MULTICAST_FAIL"; break;
+ case LORAMAC_EVENT_INFO_STATUS_BEACON_LOCKED: ptr = "BEACON_LOCKED"; break;
+ case LORAMAC_EVENT_INFO_STATUS_BEACON_LOST: ptr = "BEACON_LOST"; break;
+ case LORAMAC_EVENT_INFO_STATUS_BEACON_NOT_FOUND: ptr = "BEACON_NOT_FOUND"; break;
+ case LORAMAC_EVENT_INFO_STATUS_NO_APPKEY: ptr = "NO_APPKEY"; break;
+ case LORAMAC_EVENT_INFO_BAD_RX_DELAY: ptr = "BAD_RX_DELAY"; break;
+ }
+
+ if (ptr != NULL)
+ strcpy(dst, ptr);
+}
+
+void
+LoRaMacStatus_to_string(LoRaMacStatus_t status, char* dst)
+{
+ const char* ptr = NULL;
+
+ switch (status) {
+ case LORAMAC_STATUS_OK: ptr = "OK"; break;
+ case LORAMAC_STATUS_IN_PROGRESS: ptr = "LORAMAC_STATUS_IN_PROGRESS"; break;
+ case LORAMAC_STATUS_BUSY_UPCONF: ptr = "BUSY_UPCONF"; break;
+ case LORAMAC_STATUS_SERVICE_UNKNOWN: ptr = "SERVICE_UNKNOWN"; break;
+ case LORAMAC_STATUS_PARAMETER_INVALID: ptr = "PARAMETER_INVALID"; break;
+ case LORAMAC_STATUS_FREQUENCY_INVALID: ptr = "FREQUENCY_INVALID"; break;
+ case LORAMAC_STATUS_DATARATE_INVALID: ptr = "DATARATE_INVALID"; break;
+ case LORAMAC_STATUS_FREQ_AND_DR_INVALID: ptr = "FREQ_AND_DR_INVALID"; break;
+#ifdef LORAWAN_JOIN_EUI
+ case LORAMAC_STATUS_NO_NETWORK_JOINED: ptr = "NO_NETWORK_JOINED"; break;
+#endif
+ case LORAMAC_STATUS_LENGTH_ERROR: ptr = "LENGTH_ERROR"; break;
+ case LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR: ptr = "MAC_CMD_LENGTH_ERROR"; break;
+ case LORAMAC_STATUS_DEVICE_OFF: ptr = "DEVICE_OFF"; break;
+ case LORAMAC_STATUS_EEPROM_FAIL: ptr = "EEPROM_FAIL"; break;
+ }
+ if (ptr != NULL)
+ strcpy(dst, ptr);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LoRaMacString.h Wed Feb 28 14:06:17 2018 -0800 @@ -0,0 +1,4 @@ + +void LoRaMacEventInfoStatus_to_string(LoRaMacEventInfoStatus_t status, char* dst); +void Mlme_to_string(Mlme_t mlme, char* dst); +void LoRaMacStatus_to_string(LoRaMacStatus_t status, char* dst);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SerialDisplay.cpp Wed Feb 28 14:06:17 2018 -0800
@@ -0,0 +1,518 @@
+/*
+ / _____) _ | |
+( (____ _____ ____ _| |_ _____ ____| |__
+ \____ \| ___ | (_ _) ___ |/ ___) _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+ (C)2015 Semtech
+
+Description: VT100 serial display management
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis and Gregory Cristian
+*/
+#include "board.h"
+
+#include "SerialDisplay.h"
+#include "LoRaMacString.h"
+
+#ifdef ENABLE_VT100
+VT100 vt( USBTX, USBRX );
+
+void SerialPrintCheckBox( bool activated, uint8_t color )
+{
+ if( activated == true )
+ {
+ vt.SetAttribute( VT100::ATTR_OFF, color, color );
+ }
+ else
+ {
+ vt.SetAttribute( VT100::ATTR_OFF );
+ }
+ vt.printf( " " );
+ vt.SetAttribute( VT100::ATTR_OFF );
+}
+
+#ifdef LORAWAN_JOIN_EUI
+void SerialDisplayUpdateActivationMode( bool otaa )
+{
+ vt.SetCursorPos( 4, 17 ); // TODO
+ SerialPrintCheckBox( otaa, VT100::WHITE );
+}
+
+void SerialDisplayUpdateEui( uint8_t line, const uint8_t *eui )
+{
+ vt.SetCursorPos( line, 27 );
+ for( uint8_t i = 0; i < 8; i++ )
+ {
+ vt.printf( "%02x ", eui[i] );
+ }
+ vt.SetCursorPos( line, 50 );
+ vt.printf( "]" );
+}
+#endif /* LORAWAN_JOIN_EUI */
+
+void SerialDisplayUpdateKey( uint8_t line, const uint8_t *key )
+{
+ vt.SetCursorPos( line, 29 );
+ for( uint8_t i = 0; i < 16; i++ )
+ {
+ vt.printf( "%02x ", key[i] );
+ }
+ vt.SetCursorPos( line, 76 );
+ vt.printf( "]" );
+}
+
+void SerialDisplayUpdateNwkId( uint8_t id )
+{
+ vt.SetCursorPos( ROW_NwkId, 27 );
+ vt.printf( "%03d", id );
+}
+
+void SerialDisplayUpdateDevAddr( uint32_t addr )
+{
+ vt.SetCursorPos( ROW_DevAddr, 27 );
+ vt.printf( "%02X %02X %02X %02X", ( addr >> 24 ) & 0xFF, ( addr >> 16 ) & 0xFF, ( addr >> 8 ) & 0xFF, addr & 0xFF );
+}
+
+void SerialDisplayUpdateFrameType( bool confirmed )
+{
+ vt.SetCursorPos( ROW_FrameType, 17 );
+ SerialPrintCheckBox( confirmed, VT100::WHITE );
+ vt.SetCursorPos( ROW_FrameType, 32 );
+ SerialPrintCheckBox( !confirmed, VT100::WHITE );
+}
+
+void SerialDisplayUpdateAdr( bool adr )
+{
+ vt.SetCursorPos( ROW_ADR, 27 );
+ if( adr == true )
+ {
+ vt.printf( " ON" );
+ }
+ else
+ {
+ vt.printf( "OFF" );
+ }
+}
+
+void SerialDisplayUpdateDutyCycle( bool dutyCycle )
+{
+ vt.SetCursorPos( ROW_DUTY, 27 );
+ if( dutyCycle == true )
+ {
+ vt.printf( " ON" );
+ }
+ else
+ {
+ vt.printf( "OFF" );
+ }
+}
+
+void SerialDisplayUpdatePublicNetwork( bool network )
+{
+ vt.SetCursorPos( ROW_PUBLIC, 17 );
+ SerialPrintCheckBox( network, VT100::WHITE );
+ vt.SetCursorPos( ROW_PUBLIC, 30 );
+ SerialPrintCheckBox( !network, VT100::WHITE );
+}
+
+#ifdef LORAWAN_JOIN_EUI
+void SerialDisplayUpdateNetworkIsJoined( bool state )
+{
+ vt.SetCursorPos( ROW_JOINED, 17 );
+ SerialPrintCheckBox( !state, VT100::RED );
+ vt.SetCursorPos( ROW_JOINED, 30 );
+ SerialPrintCheckBox( state, VT100::GREEN );
+}
+#endif /* LORAWAN_JOIN_EUI */
+
+/*void SerialDisplayUpdateLedState( uint8_t id, uint8_t state )
+{
+ switch( id )
+ {
+ case 1:
+ vt.SetCursorPos( 22, 17 );
+ SerialPrintCheckBox( state, VT100::RED );
+ break;
+ case 2:
+ vt.SetCursorPos( 22, 31 );
+ SerialPrintCheckBox( state, VT100::GREEN );
+ break;
+ case 3:
+ vt.SetCursorPos( 22, 45 );
+ SerialPrintCheckBox( state, VT100::BLUE );
+ break;
+ }
+}*/
+
+void SerialDisplayUpdateData( uint8_t line, const uint8_t *buffer, uint8_t size )
+{
+ if( size != 0 )
+ {
+ vt.SetCursorPos( line, 27 );
+ for( uint8_t i = 0; i < size; i++ )
+ {
+ vt.printf( "%02X ", buffer[i] );
+ if( ( ( i + 1 ) % 16 ) == 0 )
+ {
+ line++;
+ vt.SetCursorPos( line, 27 );
+ }
+ }
+ for( uint8_t i = size; i < 64; i++ )
+ {
+ vt.printf( "__ " );
+ if( ( ( i + 1 ) % 16 ) == 0 )
+ {
+ line++;
+ vt.SetCursorPos( line, 27 );
+ }
+ }
+ vt.SetCursorPos( line - 1, 74 );
+ vt.printf( "]" );
+ }
+ else
+ {
+ vt.SetCursorPos( line, 27 );
+ for( uint8_t i = 0; i < 64; i++ )
+ {
+ vt.printf( "__ " );
+ if( ( ( i + 1 ) % 16 ) == 0 )
+ {
+ line++;
+ vt.SetCursorPos( line, 27 );
+ }
+ }
+ vt.SetCursorPos( line - 1, 74 );
+ vt.printf( "]" );
+ }
+}
+
+void SerialDisplayUpdateUplinkAcked( bool state )
+{
+ vt.SetCursorPos( ROW_UPLINK_ACKED, 36 );
+ SerialPrintCheckBox( state, VT100::GREEN );
+}
+
+//void SerialDisplayUpdateUplink( bool acked, uint8_t datarate, uint32_t counter, uint8_t port, uint8_t *buffer, uint8_t bufferSize, LoRaMacEventInfoStatus_t s)
+void SerialDisplayUplink(uint8_t fport, const uint8_t* buffer, uint8_t bufferSize )
+{
+ vt.SetCursorPos( ROW_DOWNLINK_RSSI, 32 );
+ vt.printf( " ");
+ vt.SetCursorPos( ROW_DOWNLINK_SNR, 32 );
+ vt.printf( " ");
+
+ // Port
+ vt.SetCursorPos( ROW_UPLINK_PORT, 34 );
+ vt.printf( "%3u", fport );
+ // Data
+ SerialDisplayUpdateData( ROW_UPLINK_PAYLOAD, buffer, bufferSize );
+}
+
+void SerialDisplayMcpsConfirm( const McpsConfirm_t* mc)
+{
+ char str[48];
+ static uint8_t lastStrLen = 0;
+ // Acked
+ SerialDisplayUpdateUplinkAcked(mc->AckReceived);
+ LoRaMacEventInfoStatus_to_string(mc->Status, str);
+ vt.printf("] %s", str);
+ for (unsigned n = 0; n < lastStrLen; n++)
+ vt.putc(' ' );
+ lastStrLen = strlen(str);
+ // Datarate
+ vt.SetCursorPos( ROW_UPLINK_DR, 33 );
+ vt.printf( "DR%u", mc->Datarate);
+ // Counter
+ vt.SetCursorPos( ROW_UPLINK_FCNT, 27 );
+ vt.printf( "%10" PRIu32, mc->UpLinkCounter);
+}
+
+void SerialDisplayMcpsIndication()
+{
+}
+
+void SerialDisplayUpdateDonwlinkRxData( bool state )
+{
+ vt.SetCursorPos( ROW_DOWNLINK_SNR, 4 );
+ SerialPrintCheckBox( state, VT100::GREEN );
+}
+
+void SerialDisplayMcpsIndication(const McpsIndication_t* mi)
+{
+ int8_t Snr;
+
+ vt.SetCursorPos( ROW_DOWNLINK_RSSI, 32 );
+ vt.printf( "%5d", mi->Rssi );
+
+ if (mi->Snr & 0x80) { // The SNR sign bit is 1
+ // Invert and divide by 4
+ Snr = ( ( ~mi->Snr + 1 ) & 0xFF ) >> 2;
+ Snr = -Snr;
+ } else {
+ // Divide by 4
+ Snr = ( mi->Snr & 0xFF ) >> 2;
+ }
+ vt.SetCursorPos( ROW_DOWNLINK_SNR, 32 );
+ vt.printf( "%5d", Snr );
+
+ vt.SetCursorPos( ROW_DOWNLINK_FCNT, 27 );
+ vt.printf( "%10" PRIu32, mi->receivedFCntDown);
+
+ SerialDisplayUpdateDonwlinkRxData(mi->RxData);
+ vt.SetCursorPos( ROW_DOWNLINK_FPORT, 34 );
+ if (mi->RxData) {
+ vt.printf( "%3u", mi->Port);
+ SerialDisplayUpdateData( ROW_DOWNLINK_PAYLOAD, mi->Buffer, mi->BufferSize );
+ } else {
+ vt.printf(" ");
+ SerialDisplayUpdateData( ROW_DOWNLINK_PAYLOAD, NULL, 0 );
+ }
+ /*if (mcpsIndication->RxData) {
+ LoRaMacDownlinkStatus.Port = mcpsIndication->Port;
+ LoRaMacDownlinkStatus.Buffer = mcpsIndication->Buffer;
+ LoRaMacDownlinkStatus.BufferSize = mcpsIndication->BufferSize;
+ } else
+ LoRaMacDownlinkStatus.Buffer = NULL;*/
+}
+
+#if 0
+void SerialDisplayUpdateDownlink( int16_t rssi, int8_t snr, uint32_t counter, uint8_t port, uint8_t *buffer, uint8_t bufferSize )
+{
+ // Rx data
+ SerialDisplayUpdateDonwlinkRxData( buffer != NULL );
+ // RSSI
+ vt.SetCursorPos( ROW_DOWNLINK_RSSI, 32 );
+ vt.printf( "%5d", rssi );
+ // SNR
+ vt.SetCursorPos( ROW_DOWNLINK_SNR, 32 );
+ vt.printf( "%5d", snr );
+ // Counter
+ vt.SetCursorPos( ROW_DOWNLINK_FCNT, 27 );
+ vt.printf( "%10" PRIu32, counter );
+ if( buffer != NULL )
+ {
+ // Port
+ vt.SetCursorPos( ROW_DOWNLINK_FPORT, 34 );
+ vt.printf( "%3u", port );
+ // Data
+ SerialDisplayUpdateData( ROW_DOWNLINK_PAYLOAD, buffer, bufferSize );
+ }
+ else
+ {
+ // Port
+ vt.SetCursorPos( ROW_DOWNLINK_FPORT, 34 );
+ vt.printf( " " );
+ // Data
+ SerialDisplayUpdateData( ROW_DOWNLINK_PAYLOAD, NULL, 0 );
+ }
+}
+#endif /* if 0 */
+
+void SerialDisplayDrawFirstLine( void )
+{
+ vt.PutBoxDrawingChar( 'l' );
+ for( int8_t i = 0; i <= 77; i++ )
+ {
+ vt.PutBoxDrawingChar( 'q' );
+ }
+ vt.PutBoxDrawingChar( 'k' );
+ vt.printf( "\r\n" );
+}
+
+void SerialDisplayDrawTitle( const char* title )
+{
+ vt.PutBoxDrawingChar( 'x' );
+ vt.printf( "%s", title );
+ vt.PutBoxDrawingChar( 'x' );
+ vt.printf( "\r\n" );
+}
+void SerialDisplayDrawTopSeparator( void )
+{
+ vt.PutBoxDrawingChar( 't' );
+ for( int8_t i = 0; i <= 11; i++ )
+ {
+ vt.PutBoxDrawingChar( 'q' );
+ }
+ vt.PutBoxDrawingChar( 'w' );
+ for( int8_t i = 0; i <= 64; i++ )
+ {
+ vt.PutBoxDrawingChar( 'q' );
+ }
+ vt.PutBoxDrawingChar( 'u' );
+ vt.printf( "\r\n" );
+}
+
+void SerialDisplayDrawColSeparator( void )
+{
+ vt.PutBoxDrawingChar( 'x' );
+ for( int8_t i = 0; i <= 11; i++ )
+ {
+ vt.PutBoxDrawingChar( ' ' );
+ }
+ vt.PutBoxDrawingChar( 't' );
+ for( int8_t i = 0; i <= 64; i++ )
+ {
+ vt.PutBoxDrawingChar( 'q' );
+ }
+ vt.PutBoxDrawingChar( 'u' );
+ vt.printf( "\r\n" );
+}
+
+void SerialDisplayDrawSeparator( void )
+{
+ vt.PutBoxDrawingChar( 't' );
+ for( int8_t i = 0; i <= 11; i++ )
+ {
+ vt.PutBoxDrawingChar( 'q' );
+ }
+ vt.PutBoxDrawingChar( 'n' );
+ for( int8_t i = 0; i <= 64; i++ )
+ {
+ vt.PutBoxDrawingChar( 'q' );
+ }
+ vt.PutBoxDrawingChar( 'u' );
+ vt.printf( "\r\n" );
+}
+
+void SerialDisplayDrawLine( const char* firstCol, const char* secondCol )
+{
+ vt.PutBoxDrawingChar( 'x' );
+ vt.printf( "%s", firstCol );
+ vt.PutBoxDrawingChar( 'x' );
+ vt.printf( "%s", secondCol );
+ vt.PutBoxDrawingChar( 'x' );
+ vt.printf( "\r\n" );
+}
+
+void SerialDisplayDrawBottomLine( void )
+{
+ vt.PutBoxDrawingChar( 'm' );
+ for( int8_t i = 0; i <= 11; i++ )
+ {
+ vt.PutBoxDrawingChar( 'q' );
+ }
+ vt.PutBoxDrawingChar( 'v' );
+ for( int8_t i = 0; i <= 64; i++ )
+ {
+ vt.PutBoxDrawingChar( 'q' );
+ }
+ vt.PutBoxDrawingChar( 'j' );
+ vt.printf( "\r\n" );
+}
+
+void SerialDisplayInit( void )
+{
+ vt.ClearScreen( 2 );
+ vt.SetCursorMode( false );
+ vt.SetCursorPos( 0, 0 );
+
+ // "+-----------------------------------------------------------------------------+" );
+ SerialDisplayDrawFirstLine( );
+ // "¦ LoRaWAN Demonstration Application ¦" );
+ SerialDisplayDrawTitle( " LoRaWAN Demonstration Application " );
+ // "+------------+----------------------------------------------------------------¦" );
+ SerialDisplayDrawTopSeparator( );
+#ifdef LORAWAN_JOIN_EUI
+ // "¦ Activation ¦ [ ]Over The Air ¦" );
+ SerialDisplayDrawLine( " Activation ", " [ ]Over The Air " );
+ // "¦ ¦ DevEui [__ __ __ __ __ __ __ __] ¦" );
+ SerialDisplayDrawLine( " ", " DevEui [__ __ __ __ __ __ __ __] " );
+ // "¦ ¦ JoinEui [__ __ __ __ __ __ __ __] ¦" );
+ SerialDisplayDrawLine( " ", " JoinEui [__ __ __ __ __ __ __ __] " );
+ // "¦ ¦ NwkKey [__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __] ¦" );
+ SerialDisplayDrawLine( " ", " NwkKey [__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __] " );
+#ifdef OPTNEG
+ SerialDisplayDrawLine( " ", " AppKey [__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __] " );
+#endif
+ // "¦ +----------------------------------------------------------------¦" );
+ SerialDisplayDrawColSeparator( );
+#endif /* LORAWAN_JOIN_EUI */
+ // "¦ ¦ [x]Personalisation ¦" );
+ SerialDisplayDrawLine( " ", " [ ]Personalisation " );
+ // "¦ ¦ NwkId [___] ¦" );
+ SerialDisplayDrawLine( " ", " NwkId [___] " );
+ // "¦ ¦ DevAddr [__ __ __ __] ¦" );
+ SerialDisplayDrawLine( " ", " DevAddr [__ __ __ __] " );
+#ifdef OPTNEG
+ SerialDisplayDrawLine( " ", " FNwkSIntKey [__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __] ");
+ SerialDisplayDrawLine( " ", " SNwkSIntKey [__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __] ");
+ SerialDisplayDrawLine( " ", " NwkSEncKey [__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __] ");
+#else
+ // "¦ ¦ NwkSKey [__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __] ¦" );
+ SerialDisplayDrawLine( " ", " NwkSKey [__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __] ");
+#endif
+ // "¦ ¦ AppSKey [__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __] ¦" );
+ SerialDisplayDrawLine( " ", " AppSKey [__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __] ");
+ // "+------------+----------------------------------------------------------------¦" );
+ SerialDisplayDrawSeparator( );
+ // "¦ MAC params ¦ [ ]Confirmed / [ ]Unconfirmed ¦" );
+ SerialDisplayDrawLine( " MAC params ", " [ ]Confirmed / [ ]Unconfirmed " );
+ // "¦ ¦ ADR [ ] ¦" );
+ SerialDisplayDrawLine( " ", " ADR [ ] " );
+ // "¦ ¦ Duty cycle[ ] ¦" );
+ SerialDisplayDrawLine( " ", " Duty cycle[ ] " );
+ // "+------------+----------------------------------------------------------------¦" );
+ SerialDisplayDrawSeparator( );
+ // "¦ Network ¦ [ ]Public / [ ]Private ¦" );
+ SerialDisplayDrawLine( " Network ", " [ ]Public / [ ]Private " );
+#ifdef LORAWAN_JOIN_EUI
+ // "¦ ¦ [ ]Joining / [ ]Joined ¦" );
+ SerialDisplayDrawLine( " ", " [ ]Joining / [ ]Joined " );
+#endif /* LORAWAN_JOIN_EUI */
+ // "+------------+----------------------------------------------------------------¦" );
+ SerialDisplayDrawSeparator( );
+ // "¦ Uplink ¦ Acked [ ] ¦" );
+ SerialDisplayDrawLine( " Uplink ", " Acked [ ] " );
+ // "¦ ¦ Datarate [ ] ¦" );
+ SerialDisplayDrawLine( " ", " Datarate [ ] " );
+ // "¦ ¦ Counter [ ] ¦" );
+ SerialDisplayDrawLine( " ", " Counter [ ] " );
+ // "¦ ¦ Port [ ] ¦" );
+ SerialDisplayDrawLine( " ", " Port [ ] " );
+ // "¦ ¦ Data [__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ ¦" );
+ SerialDisplayDrawLine( " ", " Data [__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ " );
+ // "¦ ¦ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ ¦" );
+ SerialDisplayDrawLine( " ", " __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ " );
+ // "¦ ¦ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ ¦" );
+ SerialDisplayDrawLine( " ", " __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ " );
+ // "¦ ¦ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ ¦" );
+ SerialDisplayDrawLine( " ", " __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ " );
+ // "+------------+----------------------------------------------------------------¦" );
+ SerialDisplayDrawSeparator( );
+ // "¦ Downlink ¦ RSSI [ ] dBm ¦" );
+ SerialDisplayDrawLine( " Downlink ", " RSSI [ ] dBm " );
+ // "¦ [ ]Data ¦ SNR [ ] dB ¦" );
+ SerialDisplayDrawLine( " [ ]Data ", " SNR [ ] dB " );
+ // "¦ ¦ Counter [ ] ¦" );
+ // "¦ ¦ Counter [ ] ¦" );
+ SerialDisplayDrawLine( " ", " Counter [ ] " );
+ // "¦ ¦ Port [ ] ¦" );
+ SerialDisplayDrawLine( " ", " Port [ ] " );
+ // "¦ ¦ Data [__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ ¦" );
+ SerialDisplayDrawLine( " ", " Data [__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ " );
+ // "¦ ¦ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ ¦" );
+ SerialDisplayDrawLine( " ", " __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ " );
+ // "¦ ¦ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ ¦" );
+ SerialDisplayDrawLine( " ", " __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ " );
+ // "¦ ¦ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ ¦" );
+ SerialDisplayDrawLine( " ", " __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ " );
+ // "+------------+----------------------------------------------------------------+" );
+ SerialDisplayDrawBottomLine( );
+ vt.printf( "To refresh screen please hit 'r' key.\r\n" );
+}
+
+bool SerialDisplayReadable( void )
+{
+ return vt.Readable( );
+}
+
+uint8_t SerialDisplayGetChar( void )
+{
+ return vt.GetChar( );
+}
+
+#endif /* ENABLE_VT100 */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SerialDisplay.h Wed Feb 28 14:06:17 2018 -0800 @@ -0,0 +1,97 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: VT100 serial display management + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#ifndef __SERIAL_DISPLAY_H__ +#define __SERIAL_DISPLAY_H__ + +#include "vt100.h" +#include "LoRaMac.h" + +#ifdef ENABLE_VT100 + +#define ROW_START 5 +#ifdef LORAWAN_JOIN_EUI + #define ROW_DEVEUI ROW_START + #define ROW_JOINEUI (ROW_DEVEUI+1) + #define ROW_NWKKEY (ROW_JOINEUI+1) + #ifdef OPTNEG + #define ROW_APPKEY (ROW_JOINEUI+2) + #define ROW_NwkId (ROW_JOINEUI+5) + #else + #define ROW_NwkId (ROW_JOINEUI+4) + #endif +#else + #define ROW_NwkId ROW_START /* ABP */ +#endif /* LORAWAN_JOIN_EUI */ + +#define ROW_DevAddr (ROW_NwkId+1) +#define ROW_FNwkSIntKey (ROW_NwkId+2) +#ifdef OPTNEG + #define ROW_SNwkSIntKey (ROW_NwkId+3) + #define ROW_NwkSEncKey (ROW_NwkId+4) + #define ROW_AppSKey (ROW_NwkId+5) +#else + #define ROW_AppSKey (ROW_NwkId+3) +#endif + +#define ROW_FrameType (ROW_AppSKey+2) +#define ROW_ADR (ROW_AppSKey+3) +#define ROW_DUTY (ROW_AppSKey+4) +#define ROW_PUBLIC (ROW_AppSKey+6) +#ifdef LORAWAN_JOIN_EUI + #define ROW_JOINED (ROW_PUBLIC+1) + #define ROW_UPLINK_ACKED (ROW_PUBLIC+3) +#else + #define ROW_UPLINK_ACKED (ROW_PUBLIC+2) +#endif /* LORAWAN_JOIN_EUI */ + +#define ROW_UPLINK_DR (ROW_UPLINK_ACKED+1) +#define ROW_UPLINK_FCNT (ROW_UPLINK_DR+1) +#define ROW_UPLINK_PORT (ROW_UPLINK_DR+2) +#define ROW_UPLINK_PAYLOAD (ROW_UPLINK_DR+3) + +#define ROW_DOWNLINK_RSSI (ROW_UPLINK_PAYLOAD+5) +#define ROW_DOWNLINK_SNR (ROW_DOWNLINK_RSSI+1) +#define ROW_DOWNLINK_FCNT (ROW_DOWNLINK_SNR+1) +#define ROW_DOWNLINK_FPORT (ROW_DOWNLINK_FCNT+1) +#define ROW_DOWNLINK_PAYLOAD (ROW_DOWNLINK_FPORT+1) + +#define ROW_END (ROW_DOWNLINK_PAYLOAD+6) + +void SerialDisplayInit( void ); +void SerialDisplayUplink(uint8_t fport, const uint8_t* buffer, uint8_t bufferSize ); +void SerialDisplayMcpsConfirm( const McpsConfirm_t*); +void SerialDisplayMcpsIndication(const McpsIndication_t* mi); +void SerialDisplayPrintCheckBox( bool activated ); +#ifdef LORAWAN_JOIN_EUI +void SerialDisplayUpdateActivationMode( bool otaa ); +void SerialDisplayUpdateEui( uint8_t line, const uint8_t *eui ); +void SerialDisplayUpdateNetworkIsJoined( bool state ); +#endif /* LORAWAN_JOIN_EUI */ +void SerialDisplayUpdateKey( uint8_t line, const uint8_t *key ); +void SerialDisplayUpdateNwkId( uint8_t id ); +void SerialDisplayUpdateDevAddr( uint32_t addr ); +void SerialDisplayUpdateFrameType( bool confirmed ); +void SerialDisplayUpdateAdr( bool adr ); +void SerialDisplayUpdateDutyCycle( bool dutyCycle ); +void SerialDisplayUpdatePublicNetwork( bool network ); +void SerialDisplayUpdateData( const uint8_t *buffer ); +void SerialDisplayUpdateUplinkAcked( bool state ); +void SerialDisplayUpdateDonwlinkRxData( bool state ); +bool SerialDisplayReadable( void ); +uint8_t SerialDisplayGetChar( void ); +extern VT100 vt; +#endif /* ENABLE_VT100 */ + +#endif // __SERIAL_DISPLAY_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lorawan1v1.lib Wed Feb 28 14:06:17 2018 -0800 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/dudmuck/code/lorawan1v1/#62f7347b9e17
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_app.json Wed Feb 28 14:06:17 2018 -0800
@@ -0,0 +1,4 @@
+{
+ "macros": [ "MBEDTLS_CMAC_C" ]
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sensorDemoVT100.cpp Wed Feb 28 14:06:17 2018 -0800
@@ -0,0 +1,1238 @@
+/*
+ / _____) _ | |
+( (____ _____ ____ _| |_ _____ ____| |__
+ \____ \| ___ | (_ _) ___ |/ ___) _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+ (C)2018 Semtech
+
+Description: LoRaMac classB device implementation
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+*/
+
+#include "LoRaMac.h"
+#include "SerialDisplay.h"
+#include "LoRaMacString.h"
+#ifdef ENABLE_VT100
+
+/*!
+ * Defines the application data transmission duty cycle. 5s, value in [ms].
+ */
+#define APP_TX_DUTYCYCLE_us 8000000
+
+/*!
+ * Defines a random delay for application data transmission duty cycle. 1s,
+ * value in [ms].
+ */
+#define APP_TX_DUTYCYCLE_RND_us 2000000
+
+/*!
+ * Default datarate
+ */
+
+#if defined( USE_BAND_ARIB_8CH )
+ #define LORAWAN_DEFAULT_DATARATE DR_3
+#else
+ #define LORAWAN_DEFAULT_DATARATE DR_0
+#endif
+
+/*!
+ * LoRaWAN confirmed messages
+ */
+#define LORAWAN_CONFIRMED_MSG_ON true
+
+/*!
+ * LoRaWAN Adaptive Data Rate
+ *
+ * \remark Please note that when ADR is enabled the end-device should be static
+ */
+#define LORAWAN_ADR_ON 1
+
+#if defined( USE_BAND_868 )
+
+/*!
+ * LoRaWAN ETSI duty cycle control enable/disable
+ *
+ * \remark Please note that ETSI mandates duty cycled transmissions. Use only for test purposes
+ */
+#define LORAWAN_DUTYCYCLE_ON false
+
+#define USE_SEMTECH_DEFAULT_CHANNEL_LINEUP 1
+
+#if( USE_SEMTECH_DEFAULT_CHANNEL_LINEUP == 1 )
+
+#define LC4 { 867100000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
+#define LC5 { 867300000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
+#define LC6 { 867500000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
+#define LC7 { 867700000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
+#define LC8 { 867900000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
+#define LC9 { 868800000, { ( ( DR_7 << 4 ) | DR_7 ) }, 2 }
+#define LC10 { 868300000, { ( ( DR_6 << 4 ) | DR_6 ) }, 1 }
+
+#endif
+
+#endif
+
+/*!
+ * LoRaWAN application port
+ */
+#define LORAWAN_APP_PORT 2
+
+/*!
+ * User application data buffer size
+ */
+#define LORAWAN_APP_DATA_SIZE 3
+
+
+#ifdef LORAWAN_JOIN_EUI
+ static uint8_t DevEui[] = LORAWAN_DEVICE_EUI;
+ static const uint8_t JoinEui[] = LORAWAN_JOIN_EUI;
+ static const uint8_t NwkKey[] = LORAWAN_ROOT_NWKKEY;
+ #ifdef LORAWAN_ROOT_APPKEY
+ static const uint8_t AppKey[] = LORAWAN_ROOT_APPKEY;
+ #endif
+#else
+ static const uint8_t FNwkSIntKey[] = LORAWAN_FNwkSIntKey;
+ static const uint8_t AppSKey[] = LORAWAN_APPSKEY;
+ static const uint32_t DevAddr = LORAWAN_DEVICE_ADDRESS;
+ #if defined(LORAWAN_SNwkSIntKey) && defined(LORAWAN_NwkSEncKey)
+ static const uint8_t SNwkSIntKey[] = LORAWAN_SNwkSIntKey;
+ static const uint8_t NwkSEncKey[] = LORAWAN_NwkSEncKey;
+ #endif
+#endif
+
+/*!
+ * Application port
+ */
+static uint8_t AppPort = LORAWAN_APP_PORT;
+
+/*!
+ * User application data size
+ */
+static uint8_t gAppDataSize = LORAWAN_APP_DATA_SIZE;
+
+/*!
+ * User application data buffer size
+ */
+#define LORAWAN_APP_DATA_MAX_SIZE 64
+
+/*!
+ * User application data
+ */
+static uint8_t AppData[LORAWAN_APP_DATA_MAX_SIZE];
+
+/*!
+ * Indicates if the node is sending confirmed or unconfirmed messages
+ */
+static uint8_t gIsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
+
+/*!
+ * Timer to handle the application data transmission duty cycle
+ *
+ */
+LowPowerTimeout tx_timeout;
+
+/*!
+ * Indicates if a new packet can be sent
+ */
+static volatile struct {
+ uint8_t gmi : 1;
+ uint8_t gmc : 1;
+} flags;
+
+/*!
+ * Device states
+ */
+volatile enum eDevicState
+{
+ /* 0 */ DEVICE_STATE_INIT = 0,
+ /* 1 */ DEVICE_STATE_SEND,
+ /* 2 */ DEVICE_STATE_TRIGGER,
+ /* 3 */ DEVICE_STATE_SLEEP,
+#ifdef LORAWAN_JOIN_EUI
+ /* 4 */ DEVICE_STATE_JOIN,
+ /* 5 */ DEVICE_STATE_JOIN_OK
+#endif /* LORAWAN_JOIN_EUI */
+} DeviceState, WakeUpState;
+
+#if defined(TARGET_MOTE_L152RC) && !defined(TARGET_FF_ARDUINO)
+ #define TARGET_FF_ARDUINO
+#endif
+
+#if defined(TARGET_FF_ARDUINO)
+DigitalIn d8(D8);
+DigitalOut extLed(D15);
+#endif /* TARGET_FF_ARDUINO */
+
+#if defined(TARGET_FF_MORPHO) && !defined(TARGET_DISCO_L072CZ_LRWAN1)
+ #define JUMPER_ENABLE
+#endif /* */
+
+#ifdef JUMPER_ENABLE
+ #define TX_INTERVAL_US 15000000
+ DigitalOut jumper_out(PC_10);
+ InterruptIn jumper_in(PC_12);
+#endif /* JUMPER_ENABLE */
+
+uint8_t c_ch;
+us_timestamp_t buttonStartAt;
+#ifdef TARGET_DISCO_L072CZ_LRWAN1
+PwmOut pwm(PA_0);
+#elif defined(TARGET_FF_ARDUINO)
+PwmOut pwm(PB_11);
+#endif /* TARGET_DISCO_L072CZ_LRWAN1 */
+volatile int cayenne_ack_ch;
+
+/*!
+ * LoRaWAN compliance tests support data
+ */
+struct ComplianceTest_s
+{
+ bool Running;
+ uint8_t State;
+ bool IsTxConfirmed;
+ uint8_t AppPort;
+ uint8_t AppDataSize;
+ uint8_t *AppDataBuffer;
+ uint16_t DownLinkCounter;
+ bool LinkCheck;
+ uint8_t DemodMargin;
+ uint8_t NbGateways;
+}ComplianceTest;
+
+McpsIndication_t gmi;
+
+McpsConfirm_t gmc;
+
+#ifdef JUMPER_ENABLE
+void autoUplink()
+{
+ if (jumper_in.read() == 1) {
+ tx_timeout.attach_us(autoUplink, TX_INTERVAL_US);
+ }
+
+ c_ch = 0xff;
+ DeviceState = DEVICE_STATE_SEND;
+}
+
+void jumper_callback()
+{
+ tx_timeout.attach_us(autoUplink, TX_INTERVAL_US);
+}
+#endif /* JUMPER_ENABLE */
+
+static void
+clearIndications()
+{
+ vt.SetCursorPos(ROW_MCPS_CONF, 1);
+ vt.printf("\e[K");
+ vt.SetCursorPos(ROW_MCPS_IND, 1);
+ vt.printf("\e[K");
+ vt.SetCursorPos(ROW_MLME_IND, 1);
+ vt.printf("\e[K");
+ vt.SetCursorPos(ROW_MLME_CONF, 1);
+ vt.printf("\e[K");
+
+ vt.SetCursorPos(ROW_MIC+3, 1);
+ vt.printf("\e[K");
+}
+
+#define LPP_DIGITAL_INPUT 0 // 1 byte
+#define LPP_DIGITAL_OUTPUT 1 // 1 byte
+#define LPP_ANALOG_INPUT 2 // 2 bytes, 0.01 signed
+#define LPP_ANALOG_OUTPUT 3 // 2 bytes, 0.01 signed
+#define LPP_LUMINOSITY 101 // 2 bytes, 1 lux unsigned
+#define LPP_PRESENCE 102 // 1 byte, 1
+#define LPP_TEMPERATURE 103 // 2 bytes, 0.1°C signed
+#define LPP_RELATIVE_HUMIDITY 104 // 1 byte, 0.5% unsigned
+#define LPP_ACCELEROMETER 113 // 2 bytes per axis, 0.001G
+#define LPP_BAROMETRIC_PRESSURE 115 // 2 bytes 0.1 hPa Unsigned
+#define LPP_GYROMETER 134 // 2 bytes per axis, 0.01 °/s
+#define LPP_GPS 136 // 3 byte lon/lat 0.0001 °, 3 bytes alt 0.01m
+
+
+// Data ID + Data Type + Data Size
+#define LPP_DIGITAL_INPUT_SIZE 3
+#define LPP_DIGITAL_OUTPUT_SIZE 3
+#define LPP_ANALOG_INPUT_SIZE 4
+#define LPP_ANALOG_OUTPUT_SIZE 4
+#define LPP_LUMINOSITY_SIZE 4
+#define LPP_PRESENCE_SIZE 3
+#define LPP_TEMPERATURE_SIZE 4
+#define LPP_RELATIVE_HUMIDITY_SIZE 3
+#define LPP_ACCELEROMETER_SIZE 8
+#define LPP_BAROMETRIC_PRESSURE_SIZE 4
+#define LPP_GYROMETER_SIZE 8
+#define LPP_GPS_SIZE 11
+
+#define CAYENNE_CH_DOUT 2
+#define CAYENNE_CH_AOUT 3
+#define CAYENNE_CH_TEMP 0
+#define CAYENNE_CH_POT 1
+
+AnalogIn a1(A1);
+AnalogIn a3(A3);
+
+const unsigned R0 = 100000;
+const unsigned B = 4275;
+
+/*!
+ * \brief Prepares the payload of the frame
+ */
+static void PrepareTxFrame( uint8_t port )
+{
+ uint16_t u16, rot;
+ float t, f, R;
+
+ if (c_ch != 0xff) {
+ gAppDataSize = 0;
+ AppData[gAppDataSize++] = c_ch;
+ switch (c_ch) {
+ case CAYENNE_CH_TEMP:
+ AppData[gAppDataSize++] = LPP_TEMPERATURE;
+ u16 = a3.read_u16() >> 4;
+ R = 4096.0 / u16 - 1.0;
+ R = R0 * R;
+ t = 1.0/(log(R/R0)/B+1/298.15)-273.15;
+ u16 = t * 10; // 0.1C per bit
+ AppData[gAppDataSize++] = u16 >> 8;
+ AppData[gAppDataSize++] = u16;
+ break;
+ case CAYENNE_CH_POT:
+ AppData[gAppDataSize++] = LPP_ANALOG_INPUT;
+ u16 = a1.read_u16(); // pot (rotary angle)
+ f = u16 / 198.6; // scale 65535/3.3 to 0.01v per bit
+ rot = (uint16_t) f;
+ AppData[gAppDataSize++] = rot >> 8;
+ AppData[gAppDataSize++] = rot;
+ break;
+ case CAYENNE_CH_DOUT:
+ AppData[gAppDataSize++] = LPP_DIGITAL_OUTPUT;
+ AppData[gAppDataSize++] = extLed.read();
+ break;
+ case CAYENNE_CH_AOUT:
+ AppData[gAppDataSize++] = LPP_ANALOG_OUTPUT;
+ u16 = pwm.read() * 100;
+ AppData[gAppDataSize++] = u16 >> 8;
+ AppData[gAppDataSize++] = u16;
+ break;
+ }
+ return;
+ } else if (cayenne_ack_ch != -1) {
+ switch (cayenne_ack_ch) {
+ case CAYENNE_CH_DOUT:
+ AppData[gAppDataSize++] = LPP_DIGITAL_OUTPUT;
+ AppData[gAppDataSize++] = extLed.read();
+ break;
+ case CAYENNE_CH_AOUT:
+ AppData[gAppDataSize++] = LPP_ANALOG_OUTPUT;
+ u16 = pwm.read() * 100;
+ AppData[gAppDataSize++] = u16 >> 8;
+ AppData[gAppDataSize++] = u16;
+ break;
+ }
+ cayenne_ack_ch = -1;
+ }
+
+ while (d8.read() == 1) {
+ us_timestamp_t duration = LoRaMacReadTimer() - buttonStartAt;
+ if (duration > 1000000) {
+ gAppDataSize = 0;
+ AppData[gAppDataSize++] = CAYENNE_CH_DOUT;
+ AppData[gAppDataSize++] = LPP_DIGITAL_OUTPUT;
+ AppData[gAppDataSize++] = extLed.read();
+ return;
+ }
+ }
+
+ switch( port ) {
+ case LORAWAN_APP_PORT:
+ gAppDataSize = 0;
+ AppData[gAppDataSize++] = CAYENNE_CH_TEMP;
+ AppData[gAppDataSize++] = LPP_TEMPERATURE;
+ u16 = a3.read_u16() >> 4;
+ R = 4096.0 / u16 - 1.0;
+ R = R0 * R;
+ t = 1.0/(log(R/R0)/B+1/298.15)-273.15;
+ u16 = t * 10; // 0.1C per bit
+ AppData[gAppDataSize++] = u16 >> 8;
+ AppData[gAppDataSize++] = u16;
+ AppData[gAppDataSize++] = CAYENNE_CH_POT;
+ AppData[gAppDataSize++] = LPP_ANALOG_INPUT;
+ u16 = a1.read_u16(); // pot (rotary angle)
+ f = u16 / 198.6; // scale 65535/3.3 to 0.01v per bit
+ rot = (uint16_t) f;
+ AppData[gAppDataSize++] = rot >> 8;
+ AppData[gAppDataSize++] = rot;
+
+ AppData[gAppDataSize++] = CAYENNE_CH_DOUT;
+ AppData[gAppDataSize++] = LPP_DIGITAL_OUTPUT;
+ AppData[gAppDataSize++] = extLed.read();
+ break;
+ case 224:
+ if( ComplianceTest.LinkCheck == true ) {
+ ComplianceTest.LinkCheck = false;
+ gAppDataSize = 3;
+ AppData[0] = 5;
+ AppData[1] = ComplianceTest.DemodMargin;
+ AppData[2] = ComplianceTest.NbGateways;
+ ComplianceTest.State = 1;
+ } else {
+ switch( ComplianceTest.State ) {
+ case 4:
+ ComplianceTest.State = 1;
+ break;
+ case 1:
+ gAppDataSize = 2;
+ AppData[0] = ComplianceTest.DownLinkCounter >> 8;
+ AppData[1] = ComplianceTest.DownLinkCounter;
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/*!
+ * \brief Prepares the payload of the frame
+ *
+ * \retval [0: frame could be send, 1: error]
+ */
+static LoRaMacStatus_t SendFrame(bool IsTxConfirmed, uint8_t AppDataSize)
+{
+ LoRaMacStatus_t status;
+ char str[64];
+ McpsReq_t mcpsReq;
+ LoRaMacTxInfo_t txInfo;
+
+ if( LoRaMacQueryTxPossible( AppDataSize, &txInfo ) != LORAMAC_STATUS_OK )
+ {
+ // Send empty frame in order to flush MAC commands
+ mcpsReq.Type = MCPS_UNCONFIRMED;
+ mcpsReq.Req.fBuffer = NULL;
+ mcpsReq.Req.fBufferSize = 0;
+ mcpsReq.Req.Datarate = LORAWAN_DEFAULT_DATARATE;
+ }
+ else
+ {
+ SerialDisplayUpdateFrameType(IsTxConfirmed);
+ if( IsTxConfirmed == false )
+ {
+ mcpsReq.Type = MCPS_UNCONFIRMED;
+ mcpsReq.Req.fPort = AppPort;
+ mcpsReq.Req.fBuffer = AppData;
+ mcpsReq.Req.fBufferSize = AppDataSize;
+ mcpsReq.Req.Datarate = LORAWAN_DEFAULT_DATARATE;
+ }
+ else
+ {
+ mcpsReq.Type = MCPS_CONFIRMED;
+ mcpsReq.Req.fPort = AppPort;
+ mcpsReq.Req.fBuffer = AppData;
+ mcpsReq.Req.fBufferSize = AppDataSize;
+ mcpsReq.Req.NbTrials = 8;
+ mcpsReq.Req.Datarate = LORAWAN_DEFAULT_DATARATE;
+ }
+ }
+
+ clearIndications();
+ status = LoRaMacMcpsRequest( &mcpsReq );
+ if (status == LORAMAC_STATUS_OK) {
+ SerialDisplayUplink(mcpsReq.Req.fPort, AppData, mcpsReq.Req.fBufferSize);
+ vt.SetCursorPos( ROW_END, 1 );
+ vt.printf("sendFrame() OK %u\e[K", AppDataSize);
+ } else {
+ LoRaMacStatus_to_string(status, str);
+ vt.SetCursorPos( ROW_END, 1 );
+ vt.printf("sendFrame() %s rx%d\e[K", str, LoRaMacGetRxSlot());
+ }
+
+
+ return status;
+} // ..SendFrame()
+
+/*!
+ * \brief MCPS-Confirm event function
+ *
+ * \param [IN] mcpsConfirm - Pointer to the confirm structure,
+ * containing confirm attributes.
+ */
+static void McpsConfirm( const McpsConfirm_t *mcpsConfirm )
+{
+ char str[64];
+
+ vt.SetCursorPos( ROW_MCPS_CONF, 1);
+ vt.printf("McpsConfirm up:%uhz ", mcpsConfirm->UpLinkFreqHz);
+ LoRaMacEventInfoStatus_to_string(mcpsConfirm->Status, str);
+ if (mcpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK)
+ vt.printf("%s \e[K", str);
+ else
+ vt.printf("\e[31m%s\e[0m \e[K", str);
+
+ if (mcpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK)
+ {
+ switch( mcpsConfirm->McpsRequest )
+ {
+ case MCPS_UNCONFIRMED:
+ {
+ // Check Datarate
+ // Check TxPower
+ break;
+ }
+ case MCPS_CONFIRMED:
+ {
+ // Check Datarate
+ // Check TxPower
+ // Check AckReceived
+ // Check NbTrials
+ //LoRaMacUplinkStatus.Acked = mcpsConfirm->AckReceived;
+ break;
+ }
+ case MCPS_PROPRIETARY:
+ {
+ break;
+ }
+ default:
+ break;
+ }
+ } else {
+ /* fail */
+ }
+ memcpy(&gmc, mcpsConfirm, sizeof(McpsConfirm_t));
+ flags.gmc = true;
+
+ DeviceState = DEVICE_STATE_TRIGGER;
+} // ..McpsConfirm()
+
+
+/*!
+ * \brief MCPS-Indication event function
+ *
+ * \param [IN] mcpsIndication - Pointer to the indication structure,
+ * containing indication attributes.
+ */
+static void McpsIndication( const McpsIndication_t *mcpsIndication )
+{
+ char str[64];
+
+ memcpy(&gmi, mcpsIndication, sizeof(McpsIndication_t));
+ flags.gmi = true;
+
+ vt.SetCursorPos(ROW_MCPS_CONF, 1);
+ vt.printf("\e[K"); // clear stale mcpsconf if retrying
+
+ vt.SetCursorPos( ROW_MCPS_IND, 0);
+ vt.printf("McpsIndication rx%d ", mcpsIndication->RxSlot);
+ if (mcpsIndication->Status != LORAMAC_EVENT_INFO_STATUS_OK)
+ {
+ LoRaMacEventInfoStatus_to_string(mcpsIndication->Status, str);
+ vt.printf("\e[31m%s attempt%u\e[0m\e[K", str, mcpsIndication->attempt);
+ return;
+ }
+ vt.printf("OK \e[K");
+
+ switch( mcpsIndication->McpsIndication )
+ {
+ case MCPS_UNCONFIRMED:
+ {
+ break;
+ }
+ case MCPS_CONFIRMED:
+ {
+ /* ack sent by mac layer */
+ break;
+ }
+ case MCPS_PROPRIETARY:
+ {
+ break;
+ }
+ case MCPS_MULTICAST:
+ {
+ break;
+ }
+ default:
+ break;
+ }
+
+ // Check Multicast
+ // Check Port
+ // Check Datarate
+ // Check FramePending
+ // Check Buffer
+ // Check BufferSize
+ // Check Rssi
+ // Check Snr
+ // Check RxSlot
+
+
+ if( ComplianceTest.Running == true )
+ {
+ ComplianceTest.DownLinkCounter++;
+ }
+
+ if( mcpsIndication->RxData == true )
+ {
+ unsigned n;
+ for (n = 0; n < mcpsIndication->BufferSize; n += 4) {
+ uint16_t val = mcpsIndication->Buffer[n+1] << 8;
+ val += mcpsIndication->Buffer[n+2];
+ cayenne_ack_ch = mcpsIndication->Buffer[n];
+ switch (mcpsIndication->Buffer[n]) {
+ case CAYENNE_CH_DOUT:
+ extLed.write(val);
+ break;
+ case CAYENNE_CH_AOUT:
+ pwm.write(val / 100.0);
+ break;
+ default:
+ break;
+ }
+ }
+
+ switch( mcpsIndication->Port )
+ {
+ case 1: // The application LED can be controlled on port 1 or 2
+ case 2:
+ break;
+ case 224:
+ if( ComplianceTest.Running == false )
+ {
+ // Check compliance test enable command (i)
+ if( ( mcpsIndication->BufferSize == 4 ) &&
+ ( mcpsIndication->Buffer[0] == 0x01 ) &&
+ ( mcpsIndication->Buffer[1] == 0x01 ) &&
+ ( mcpsIndication->Buffer[2] == 0x01 ) &&
+ ( mcpsIndication->Buffer[3] == 0x01 ) )
+ {
+ gIsTxConfirmed = false;
+ AppPort = 224;
+ gAppDataSize = 2;
+ ComplianceTest.DownLinkCounter = 0;
+ ComplianceTest.LinkCheck = false;
+ ComplianceTest.DemodMargin = 0;
+ ComplianceTest.NbGateways = 0;
+ ComplianceTest.Running = true;
+ ComplianceTest.State = 1;
+
+ MibRequestConfirm_t mibReq;
+ mibReq.Type = MIB_ADR;
+ mibReq.Param.AdrEnable = true;
+ LoRaMacMibSetRequestConfirm( &mibReq );
+
+#if defined( USE_BAND_868 )
+ DutyCycleOn = false;
+#endif
+ }
+ }
+ else
+ {
+ ComplianceTest.State = mcpsIndication->Buffer[0];
+ switch( ComplianceTest.State )
+ {
+ case 0: // Check compliance test disable command (ii)
+ gIsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
+ AppPort = LORAWAN_APP_PORT;
+ gAppDataSize = LORAWAN_APP_DATA_SIZE;
+ ComplianceTest.DownLinkCounter = 0;
+ ComplianceTest.Running = false;
+
+ MibRequestConfirm_t mibReq;
+ mibReq.Type = MIB_ADR;
+ mibReq.Param.AdrEnable = LORAWAN_ADR_ON;
+ LoRaMacMibSetRequestConfirm( &mibReq );
+#if defined( USE_BAND_868 )
+ DutyCycleOn = LORAWAN_DUTYCYCLE_ON;
+#endif
+ break;
+ case 1: // (iii, iv)
+ gAppDataSize = 2;
+ break;
+ case 2: // Enable confirmed messages (v)
+ gIsTxConfirmed = true;
+ ComplianceTest.State = 1;
+ break;
+ case 3: // Disable confirmed messages (vi)
+ gIsTxConfirmed = false;
+ ComplianceTest.State = 1;
+ break;
+ case 4: // (vii)
+ gAppDataSize = mcpsIndication->BufferSize;
+
+ AppData[0] = 4;
+ for( uint8_t i = 1; i < gAppDataSize; i++ )
+ {
+ AppData[i] = mcpsIndication->Buffer[i] + 1;
+ }
+ break;
+ case 5: // (viii)
+ {
+ MlmeReq_t mlmeReq;
+ mlmeReq.Type = MLME_LINK_CHECK;
+ LoRaMacMlmeRequest( &mlmeReq );
+ }
+ break;
+ case 6: // (ix)
+ {
+#ifdef LORAWAN_JOIN_EUI
+ MlmeReq_t mlmeReq = {};
+
+ // Disable TestMode and revert back to normal operation
+ gIsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON;
+ AppPort = LORAWAN_APP_PORT;
+ gAppDataSize = LORAWAN_APP_DATA_SIZE;
+ ComplianceTest.DownLinkCounter = 0;
+ ComplianceTest.Running = false;
+
+ MibRequestConfirm_t mibReq;
+ mibReq.Type = MIB_ADR;
+ mibReq.Param.AdrEnable = LORAWAN_ADR_ON;
+ LoRaMacMibSetRequestConfirm( &mibReq );
+#if defined( USE_BAND_868 )
+ DutyCycleOn = LORAWAN_DUTYCYCLE_ON;
+#endif
+
+ mlmeReq.Type = MLME_JOIN;
+
+ mlmeReq.Req.Join.DevEui = DevEui;
+ mlmeReq.Req.Join.JoinEui = JoinEui;
+ mlmeReq.Req.Join.NwkKey = NwkKey;
+ #ifdef LORAWAN_ROOT_APPKEY
+ mlmeReq.Req.Join.AppKey = AppKey;
+ #endif /* LORAWAN_ROOT_APPKEY */
+
+ LoRaMacMlmeRequest( &mlmeReq );
+#endif /* LORAWAN_JOIN_EUI */
+ DeviceState = DEVICE_STATE_SLEEP;
+ }
+ break;
+ case 7: // Switch end device Class
+ {
+ MlmeReq_t mlmeReq;
+
+ mlmeReq.Type = MLME_SWITCH_CLASS;
+
+ // CLASS_A = 0, CLASS_B = 1, CLASS_C = 2
+ mlmeReq.Req.SwitchClass.Class = ( DeviceClass_t )mcpsIndication->Buffer[1];
+
+ LoRaMacMlmeRequest( &mlmeReq );
+
+ PrepareTxFrame( AppPort );
+ /*status =*/ SendFrame(gIsTxConfirmed, gAppDataSize);
+ }
+ break;
+ case 8: // Send PingSlotInfoReq
+ {
+ MlmeReq_t mlmeReq;
+
+ mlmeReq.Type = MLME_PING_SLOT_INFO;
+
+ mlmeReq.Req.PingSlotInfo.Value = mcpsIndication->Buffer[1];
+
+ LoRaMacMlmeRequest( &mlmeReq );
+ PrepareTxFrame( AppPort );
+ /*status =*/ SendFrame(gIsTxConfirmed, gAppDataSize);
+ }
+ break;
+ case 9: // Send BeaconTimingReq
+ {
+ MlmeReq_t mlmeReq;
+
+ mlmeReq.Type = MLME_BEACON_TIMING;
+
+ LoRaMacMlmeRequest( &mlmeReq );
+ PrepareTxFrame( AppPort );
+ /*status =*/ SendFrame(gIsTxConfirmed, gAppDataSize);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ }
+
+} // ..McpsIndication()
+
+#ifdef LORAWAN_JOIN_EUI
+void
+join(uint8_t tries)
+{
+ char str[64];
+ LoRaMacStatus_t status;
+ MlmeReq_t mlmeReq = { };
+
+ mlmeReq.Type = MLME_JOIN;
+
+ clearIndications();
+#ifdef LORAWAN_ROOT_APPKEY
+ mlmeReq.Req.Join.AppKey = AppKey;
+#endif
+ mlmeReq.Req.Join.DevEui = DevEui;
+ mlmeReq.Req.Join.JoinEui = JoinEui;
+ mlmeReq.Req.Join.NwkKey = NwkKey;
+ mlmeReq.Req.Join.NbTrials = tries;
+ status = LoRaMacMlmeRequest( &mlmeReq );
+ if (status != LORAMAC_STATUS_OK) {
+ LoRaMacStatus_to_string(status, str);
+ } else
+ extLed = 1;
+}
+#endif /* LORAWAN_JOIN_EUI */
+
+/*!
+ * \brief MLME-Confirm event function
+ *
+ * \param [IN] mlmeConfirm - Pointer to the confirm structure,
+ * containing confirm attributes.
+ */
+static void MlmeConfirm( const MlmeConfirm_t *mlmeConfirm )
+{
+ char str[64];
+ static uint8_t failCnt = 0;
+
+ vt.SetCursorPos(ROW_MLME_CONF, 1);
+ Mlme_to_string(mlmeConfirm->MlmeRequest, str);
+ vt.printf("MlmeConfirm %s ", str);
+ LoRaMacEventInfoStatus_to_string(mlmeConfirm->Status, str);
+ if (mlmeConfirm->Status != LORAMAC_EVENT_INFO_STATUS_OK)
+ vt.printf("\e[31m%s \e[0m \e[K", str);
+ else
+ vt.printf("%s \e[K", str);
+
+#if defined(LORAWAN_ROOT_APPKEY) && defined(LORAWAN_JOIN_EUI)
+ /* 1v1 joinNonce is incrementing non-volatile value */
+ if (mlmeConfirm->MlmeRequest == MLME_JOIN) {
+ vt.printf(" rxJoinNonce:%u vs %u",
+ mlmeConfirm->fields.join.rxJoinNonce,
+ mlmeConfirm->fields.join.myJoinNonce
+ );
+ }
+#endif /* LORAWAN_ROOT_APPKEY */
+
+ if (mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK)
+ {
+ failCnt = 0;
+ switch (mlmeConfirm->MlmeRequest)
+ {
+#ifdef LORAWAN_JOIN_EUI
+ case MLME_JOIN:
+ {
+ // Status is OK, node has joined the network
+ /* collect any mac cmds from server until expected channel mask */
+ extLed = 0;
+ DeviceState = DEVICE_STATE_JOIN_OK;
+ break;
+ }
+#endif /* LORAWAN_JOIN_EUI*/
+ case MLME_LINK_CHECK:
+ {
+ // Check DemodMargin
+ // Check NbGateways
+ if( ComplianceTest.Running == true )
+ {
+ ComplianceTest.LinkCheck = true;
+ ComplianceTest.DemodMargin = mlmeConfirm->fields.link.DemodMargin;
+ ComplianceTest.NbGateways = mlmeConfirm->fields.link.NbGateways;
+ }
+ break;
+ }
+ case MLME_TIME_REQ:
+ break;
+ default:
+ /* TODO: handle unknown MLME request */
+ DeviceState = DEVICE_STATE_SLEEP;
+ break;
+ }
+ }
+ else // not ok...
+ {
+ failCnt++;
+
+#ifdef LORAWAN_JOIN_EUI
+ if (failCnt > 5) {
+ join(1);
+ return;
+ }
+#endif
+
+ switch( mlmeConfirm->MlmeRequest )
+ {
+#ifdef LORAWAN_JOIN_EUI
+ case MLME_JOIN:
+ {
+ // Join failed, restart join procedure
+ break;
+ }
+#endif /* LORAWAN_JOIN_EUI */
+ case MLME_LINK_CHECK:
+ DeviceState = DEVICE_STATE_SLEEP;
+ break;
+#ifdef LORAWAN_JOIN_EUI
+ case MLME_REJOIN_0:
+ break;
+ case MLME_REJOIN_2:
+ break;
+ case MLME_TIME_REQ:
+ break;
+#endif /* LORAWAN_JOIN_EUI */
+ default:
+ DeviceState = DEVICE_STATE_SLEEP;
+ break;
+ }
+ }
+} // ..MlmeConfirm
+
+static void MlmeIndication( const MlmeIndication_t *MlmeIndication )
+{
+ char str[48];
+ MibRequestConfirm_t mibReq;
+
+ vt.SetCursorPos(ROW_MLME_IND, 1);
+ LoRaMacEventInfoStatus_to_string(MlmeIndication->Status, str);
+ Mlme_to_string(MlmeIndication->MlmeIndication, str);
+ vt.printf("MlmeIndication %s ", str);
+ if (MlmeIndication->Status != LORAMAC_EVENT_INFO_STATUS_OK)
+ vt.printf("\e[31m%s \e[0m \e[K", str);
+ else
+ vt.printf("%s \e[K", str);
+
+ switch( MlmeIndication->MlmeIndication )
+ {
+ case MLME_SWITCH_CLASS:
+ {
+ /* mac gave up on beacon */
+ mibReq.Type = MIB_DEVICE_CLASS;
+ mibReq.Param.Class = CLASS_A;
+ LoRaMacMibSetRequestConfirm( &mibReq );
+
+ // Switch to class A again
+ DeviceState = DEVICE_STATE_SLEEP; // class-B manual switch
+ break;
+ }
+ case MLME_BEACON:
+ {
+ LoRaMacEventInfoStatus_to_string(MlmeIndication->Status, str);
+ break;
+
+ }
+#ifdef LORAWAN_JOIN_EUI
+ case MLME_JOIN:
+ vt.printf("%uhz try%u", MlmeIndication->freqHz, MlmeIndication->JoinRequestTrials);
+ break;
+#endif /* !LORAWAN_JOIN_EUI */
+ default:
+ break;
+ }
+
+} // ..MlmeIndication()
+
+uint8_t periodicity;
+
+void SerialDisplayRefresh( void )
+{
+#ifdef LORAWAN_JOIN_EUI
+ MibRequestConfirm_t mibReq;
+#endif
+
+ SerialDisplayInit( );
+#ifdef LORAWAN_JOIN_EUI
+ SerialDisplayUpdateActivationMode(true);
+ SerialDisplayUpdateEui( ROW_DEVEUI, DevEui);
+ SerialDisplayUpdateEui( ROW_JOINEUI, JoinEui);
+ SerialDisplayUpdateKey( ROW_NWKKEY, NwkKey);
+
+ #ifdef LORAWAN_ROOT_APPKEY
+ SerialDisplayUpdateKey(ROW_APPKEY, AppKey);
+ #endif
+
+ mibReq.Type = MIB_NETWORK_JOINED;
+ LoRaMacMibGetRequestConfirm( &mibReq );
+ SerialDisplayUpdateNetworkIsJoined( mibReq.Param.IsNetworkJoined );
+#else
+ //SerialDisplayUpdateNwkId( LORAWAN_NETWORK_ID );
+ SerialDisplayUpdateDevAddr( DevAddr );
+ SerialDisplayUpdateKey( ROW_FNwkSIntKey, FNwkSIntKey);
+ SerialDisplayUpdateKey( ROW_AppSKey, AppSKey );
+ #if defined(LORAWAN_SNwkSIntKey) && defined(LORAWAN_NwkSEncKey)
+ SerialDisplayUpdateKey(ROW_NwkSEncKey, NwkSEncKey);
+ SerialDisplayUpdateKey(ROW_SNwkSIntKey, SNwkSIntKey);
+ #endif /* 1v1 ABP */
+
+ vt.SetCursorPos( ROW_END, 1 );
+ vt.printf("FCntUp:%08x", eeprom_read(EEPROM_FCNTUP));
+ vt.printf(" AFCntDown:%08x", get_fcntdwn(true));
+ vt.printf(" NFCntDown:%08x", get_fcntdwn(false));
+#endif
+
+
+ SerialDisplayUpdateAdr( LORAWAN_ADR_ON );
+#if defined( USE_BAND_868 )
+ SerialDisplayUpdateDutyCycle( LORAWAN_DUTYCYCLE_ON );
+#else
+ SerialDisplayUpdateDutyCycle( false );
+#endif
+ SerialDisplayUpdatePublicNetwork( LORAWAN_PUBLIC_NETWORK );
+
+ //SerialDisplayUpdateLedState( 3, AppLedStateOn );
+}
+
+void SerialRxProcess( void )
+{
+ LoRaMacStatus_t status;
+ MlmeReq_t mlmeReq;
+#ifndef LORAWAN_JOIN_EUI
+ static uint8_t icnt = 0;
+#endif
+
+ if( SerialDisplayReadable( ) == true ) {
+ char ch = SerialDisplayGetChar();
+#ifndef LORAWAN_JOIN_EUI
+ if (ch == 'I') {
+ if (++icnt == 3) {
+ vt.SetCursorPos( ROW_END, 1 );
+ vt.printf("reset-fcnts\e[K");
+ eeprom_clear(EEPROM_AFCNTDWN);
+ eeprom_clear(EEPROM_NFCNTDWN);
+ eeprom_clear(EEPROM_FCNTUP);
+ }
+ } else
+ icnt = 0;
+#endif /* !LORAWAN_JOIN_EUI */
+
+ if ( ch >= '0' && ch <= '9') {
+ c_ch = ch - '0';
+ DeviceState = DEVICE_STATE_SEND;
+ return;
+ }
+ switch( ch ) {
+ case 'R':
+ case 'r':
+ // Refresh Serial screen
+ SerialDisplayRefresh( );
+ break;
+ case 'L':
+ clearIndications();
+ mlmeReq.Type = MLME_LINK_CHECK;
+ status = LoRaMacMlmeRequest( &mlmeReq );
+ if (status == LORAMAC_STATUS_OK)
+ SendFrame(0, false);
+ break;
+#ifdef LORAWAN_JOIN_EUI
+ case 'j':
+ DeviceState = DEVICE_STATE_JOIN;
+ break;
+#endif
+ default:
+ break;
+ }
+ }
+}
+
+
+static const LoRaMacPrimitives_t LoRaMacPrimitives = {
+ McpsConfirm,
+ McpsIndication,
+ MlmeConfirm,
+ MlmeIndication
+};
+
+static const LoRaMacCallback_t LoRaMacCallbacks = {
+ BoardGetBatteryLevel,
+ NULL
+};
+
+/**
+ * Main application entry point.
+ */
+int main()
+{
+ MibRequestConfirm_t mibReq;
+
+ DeviceState = DEVICE_STATE_INIT;
+
+ if (sleep_manager_can_deep_sleep())
+ sleep_manager_lock_deep_sleep(); // prevent deep sleep
+
+#ifdef JUMPER_ENABLE
+ jumper_out = 1;
+ jumper_in.mode(PullDown);
+ jumper_in.rise(jumper_callback);
+#endif /* JUMPER_ENABLE */
+
+ while( 1 )
+ {
+ SerialRxProcess( );
+
+ if (flags.gmi) {
+ flags.gmi = false;
+ SerialDisplayMcpsIndication(&gmi);
+ }
+
+ if (flags.gmc) {
+ flags.gmc = false;
+ SerialDisplayMcpsConfirm(&gmc);
+ }
+
+ switch( DeviceState )
+ {
+ case DEVICE_STATE_INIT:
+ {
+ pwm.period(1.0 / 60);
+ cayenne_ack_ch = -1;
+ c_ch = 0xff;
+ d8.mode(PullDown);
+ if (LORAMAC_STATUS_OK != LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks )) {
+ return -1;
+ }
+
+ mibReq.Type = MIB_ADR;
+ mibReq.Param.AdrEnable = LORAWAN_ADR_ON;
+ LoRaMacMibSetRequestConfirm( &mibReq );
+
+ mibReq.Type = MIB_PUBLIC_NETWORK;
+ mibReq.Param.EnablePublicNetwork = LORAWAN_PUBLIC_NETWORK;
+ LoRaMacMibSetRequestConfirm( &mibReq );
+
+#if defined( USE_BAND_868 )
+ DutyCycleOn = LORAWAN_DUTYCYCLE_ON ;
+#if( USE_SEMTECH_DEFAULT_CHANNEL_LINEUP == 1 )
+ LoRaMacChannelAdd( 3, ( ChannelParams_t )LC4 );
+ LoRaMacChannelAdd( 4, ( ChannelParams_t )LC5 );
+ LoRaMacChannelAdd( 5, ( ChannelParams_t )LC6 );
+ LoRaMacChannelAdd( 6, ( ChannelParams_t )LC7 );
+ LoRaMacChannelAdd( 7, ( ChannelParams_t )LC8 );
+ LoRaMacChannelAdd( 8, ( ChannelParams_t )LC9 );
+ LoRaMacChannelAdd( 9, ( ChannelParams_t )LC10 );
+
+ mibReq.Type = MIB_RX2_CHANNEL;
+ mibReq.Param.Rx2Channel = ( Rx2ChannelParams_t ){ 869525000, DR_3 };
+ LoRaMacMibSetRequestConfirm( &mibReq );
+#endif
+
+#endif
+
+ SerialDisplayRefresh();
+#ifdef LORAWAN_JOIN_EUI
+
+ #ifndef SENETCO /* for senet, use network provided DevEUI */
+ // Initialize LoRaMac device unique ID
+ HardwareIDtoDevEUI(DevEui);
+ #ifdef LORAWAN_ROOT_APPKEY
+ // inverted DevEui provisioned as v1.1 on server (non-inv = lorawan1v0)
+ for (int i = 0; i < 8; i++)
+ DevEui[i] ^= 0xff;
+ #endif /* LORAWAN_ROOT_APPKEY */
+ #endif /* !SENETCO */
+ SerialDisplayUpdateEui( 5, DevEui );
+ DeviceState = DEVICE_STATE_JOIN;
+#else /* ABP... */
+
+ mibReq.Type = MIB_DEV_ADDR;
+ mibReq.Param.DevAddr = DevAddr;
+ LoRaMacMibSetRequestConfirm( &mibReq );
+ SerialDisplayUpdateDevAddr(DevAddr);
+
+ mibReq.Type = MIB_APP_SKEY;
+ mibReq.Param.key = AppSKey;
+ LoRaMacMibSetRequestConfirm( &mibReq );
+ SerialDisplayUpdateKey(ROW_AppSKey, AppSKey);
+
+ #if defined(LORAWAN_SNwkSIntKey) && defined(LORAWAN_NwkSEncKey)
+ /* lorawan 1v1 ABP */
+ mibReq.Type = MIB_NwkSEncKey;
+ mibReq.Param.NwkSEncKey = NwkSEncKey;
+ LoRaMacMibSetRequestConfirm( &mibReq );
+ SerialDisplayUpdateKey(ROW_NwkSEncKey, NwkSEncKey);
+
+ mibReq.Type = MIB_SNwkSIntKey;
+ mibReq.Param.SNwkSIntKey = SNwkSIntKey;
+ LoRaMacMibSetRequestConfirm( &mibReq );
+ SerialDisplayUpdateKey(ROW_SNwkSIntKey, SNwkSIntKey);
+
+ mibReq.Type = MIB_FNwkSIntKey;
+ mibReq.Param.key = FNwkSIntKey;
+ LoRaMacMibSetRequestConfirm( &mibReq );
+ SerialDisplayUpdateKey(ROW_FNwkSIntKey, mibReq.Param.key);
+ #else
+ /* lorawan 1v0 ABP */
+ mibReq.Type = MIB_NwkSKey;
+ mibReq.Param.key = FNwkSIntKey;
+ LoRaMacMibSetRequestConfirm( &mibReq );
+ SerialDisplayUpdateKey(ROW_FNwkSIntKey, mibReq.Param.key);
+ #endif
+
+ DeviceState = DEVICE_STATE_TRIGGER;
+#endif /* !LORAWAN_JOIN_EUI */
+ break;
+ }
+#ifdef LORAWAN_JOIN_EUI
+ case DEVICE_STATE_JOIN:
+ {
+ join(8);
+ DeviceState = DEVICE_STATE_SLEEP;
+ break;
+ }
+ case DEVICE_STATE_JOIN_OK:
+ MibRequestConfirm_t mibReq;
+ mibReq.Type = MIB_NETWORK_JOINED;
+ LoRaMacMibGetRequestConfirm( &mibReq );
+ SerialDisplayUpdateNetworkIsJoined( mibReq.Param.IsNetworkJoined );
+ mibReq.Type = MIB_DEV_ADDR;
+ LoRaMacMibGetRequestConfirm( &mibReq );
+ SerialDisplayUpdateDevAddr(mibReq.Param.DevAddr);
+ mibReq.Type = MIB_FNwkSIntKey;
+ LoRaMacMibGetRequestConfirm( &mibReq );
+ SerialDisplayUpdateKey( ROW_FNwkSIntKey, mibReq.Param.key );
+ mibReq.Type = MIB_APP_SKEY;
+ LoRaMacMibGetRequestConfirm( &mibReq );
+ SerialDisplayUpdateKey( ROW_AppSKey, mibReq.Param.key );
+
+ #ifdef LORAWAN_ROOT_APPKEY
+ mibReq.Type = MIB_SNwkSIntKey;
+ LoRaMacMibGetRequestConfirm( &mibReq );
+ SerialDisplayUpdateKey(ROW_SNwkSIntKey, mibReq.Param.key);
+ mibReq.Type = MIB_NwkSEncKey;
+ LoRaMacMibGetRequestConfirm( &mibReq );
+ SerialDisplayUpdateKey(ROW_NwkSEncKey, mibReq.Param.key);
+ #endif /* LORAWAN_ROOT_APPKEY */
+ DeviceState = DEVICE_STATE_TRIGGER;
+ break;
+#endif /* LORAWAN_JOIN_EUI */
+ case DEVICE_STATE_SEND:
+ SerialDisplayUpdateUplinkAcked( false );
+ SerialDisplayUpdateDonwlinkRxData( false );
+ PrepareTxFrame( AppPort );
+ /*status =*/ SendFrame(gIsTxConfirmed, gAppDataSize);
+ /* McpsConfirm or McpsIndication callback will continue */
+ DeviceState = DEVICE_STATE_SLEEP;
+ break;
+ case DEVICE_STATE_SLEEP:
+ {
+ // Wake up through events
+ sleep_manager_sleep_auto();
+ break;
+ }
+ case DEVICE_STATE_TRIGGER:
+ sleep_manager_sleep_auto();
+ if (d8.read() == 1) {
+ c_ch = 0xff;
+ DeviceState = DEVICE_STATE_SEND;
+ buttonStartAt = LoRaMacReadTimer();
+ }
+ break;
+ default:
+ DeviceState = DEVICE_STATE_INIT;
+ break;
+ } // ..switch( DeviceState )
+
+ } // ..while( 1 )
+}
+#endif /* ENABLE_VT100 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vt100.h Wed Feb 28 14:06:17 2018 -0800
@@ -0,0 +1,224 @@
+/*
+ / _____) _ | |
+( (____ _____ ____ _| |_ _____ ____| |__
+ \____ \| ___ | (_ _) ___ |/ ___) _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+ (C)2015 Semtech
+
+Description: VT100 terminal support class
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis and Gregory Cristian
+*/
+#ifndef __VT100_H__
+#define __VT100_H__
+
+#ifndef STRING_STACK_LIMIT
+#define STRING_STACK_LIMIT 120
+#endif
+
+#ifdef TARGET_MOTE_L152RC
+ #define VT100_BAUD 115200
+#elif defined(TARGET_DISCO_L072CZ_LRWAN1)
+ #define VT100_BAUD 38400 /* HSI? */
+#elif defined(TARGET_NUCLEO_L152RE)
+ #define VT100_BAUD 115200
+#elif defined(TARGET_NUCLEO_L073RZ)
+ #define VT100_BAUD 115200
+#else
+ #error find_usable_vt100_baudrate
+#endif
+
+/**
+ * Implements VT100 terminal commands support.
+ * Implments also the same behaviour has RawSerial class. The only difference
+ * is located in putc fucntion where writeable check is made befor sending the character.
+ */
+class VT100 : public SerialBase
+{
+public:
+ enum TextAttributes
+ {
+ ATTR_OFF = 0,
+ BOLD = 1,
+ USCORE = 4,
+ BLINK = 5,
+ REVERSE = 7,
+ BOLD_OFF = 21,
+ USCORE_OFF = 24,
+ BLINK_OFF = 25,
+ REVERSE_OFF = 27,
+ };
+
+ enum Colors
+ {
+ BLACK = 0,
+ RED = 1,
+ GREEN = 2,
+ BROWN = 3,
+ BLUE = 4,
+ MAGENTA = 5,
+ CYAN = 6,
+ WHITE = 7,
+ };
+
+ VT100( PinName tx, PinName rx ): SerialBase(tx, rx, VT100_BAUD)
+ {
+ // initializes terminal to "power-on" settings
+ // ESC c
+ this->printf( "\x1B\x63" );
+ }
+
+ void ClearScreen( uint8_t param )
+ {
+ // ESC [ Ps J
+ // 0 Clear screen from cursor down
+ // 1 Clear screen from cursor up
+ // 2 Clear entire screen
+ this->printf( "\x1B[%dJ", param );
+ }
+
+ void ClearLine( uint8_t param )
+ {
+ // ESC [ Ps K
+ // 0 Erase from the active position to the end of the line, inclusive (default)
+ // 1 Erase from the start of the screen to the active position, inclusive
+ // 2 Erase all of the line, inclusive
+ this->printf( "\x1B[%dK", param );
+ }
+
+ void SetAttribute( uint8_t attr )
+ {
+ // ESC [ Ps;...;Ps m
+ this->printf( "\x1B[%dm", attr );
+ }
+
+ void SetAttribute( uint8_t attr, uint8_t fgcolor, uint8_t bgcolor )
+ {
+ // ESC [ Ps;...;Ps m
+ this->printf( "\x1B[%d;%d;%dm", attr, fgcolor + 30, bgcolor + 40 );
+ }
+
+ void SetCursorMode( uint8_t visible )
+ {
+ if( visible == true )
+ {
+ // ESC [ ? 25 h
+ this->printf( "\x1B[?25h" );
+ }
+ else
+ {
+ // ESC [ ? 25 l
+ this->printf( "\x1B[?25l" );
+ }
+ }
+
+ void SetCursorPos( uint8_t line, uint8_t col )
+ {
+ // ESC [ Pl ; Pc H
+ this->printf( "\x1B[%d;%dH", line, col );
+ }
+
+ void PutStringAt( uint8_t line, uint8_t col, const char *s )
+ {
+ this->SetCursorPos( line, col );
+ this->printf( "%s", s );
+ }
+
+ void PutCharAt( uint8_t line, uint8_t col, uint8_t c )
+ {
+ this->SetCursorPos( line, col );
+ this->printf( "%c", c );
+ }
+
+ void PutHexAt( uint8_t line, uint8_t col, uint16_t n )
+ {
+ this->SetCursorPos( line, col );
+ this->printf( "%X", n );
+ }
+
+ void PutBoxDrawingChar( uint8_t c )
+ {
+ this->printf( "\x1B(0%c\x1b(B", c );
+ }
+
+ bool Readable( void )
+ {
+ return this->readable( );
+ }
+
+ uint8_t GetChar( void )
+ {
+ return this->getc( );
+ }
+
+ /*
+ * RawSerial class implmentation copy.
+ */
+ /** Read a char from the serial port
+ *
+ * @returns The char read from the serial port
+ */
+ int getc( )
+ {
+ return _base_getc( );
+ }
+
+ /** Write a char to the serial port
+ *
+ * @param c The char to write
+ *
+ * @returns The written char or -1 if an error occured
+ */
+ int putc( int c )
+ {
+ while( this->writeable( ) != 1 );
+ return _base_putc( c );
+ }
+
+ /** Write a string to the serial port
+ *
+ * @param str The string to write
+ *
+ * @returns 0 if the write succeeds, EOF for error
+ */
+ int puts( const char *str )
+ {
+ while( *str )
+ putc( *str++ );
+ return 0;
+ }
+
+ // Experimental support for printf in RawSerial. No Stream inheritance
+ // means we can't call printf() directly, so we use sprintf() instead.
+ // We only call malloc() for the sprintf() buffer if the buffer
+ // length is above a certain threshold, otherwise we use just the stack.
+ int printf( const char *format, ... )
+ {
+ std::va_list arg;
+ va_start( arg, format );
+ int len = vsnprintf( NULL, 0, format, arg );
+ if( len < STRING_STACK_LIMIT )
+ {
+ char temp[STRING_STACK_LIMIT];
+ vsprintf( temp, format, arg );
+ puts( temp );
+ }
+ else
+ {
+ char *temp = new char[len + 1];
+ vsprintf( temp, format, arg );
+ puts( temp );
+ delete[] temp;
+ }
+ va_end( arg );
+ return len;
+ }
+
+private:
+
+};
+
+#endif // __VT100_H__
