LoRaWAN demo application using grove peripherals generating Cayenne LPP

Dependencies:   lorawan1v1

radio chip selection

Radio chip driver is not included, because two options are available.
If you're using SX1272 or SX1276, then import sx127x driver into your program.
if you're using SX1261 or SX1262, then import sx126x driver into your program.
If you're using NAmote72 or Murata discovery, then you must import only sx127x driver.

Grove peripherals -> Cayenne demo

Read LoRaWAN-1.1 page for configuration instructions.

This project adds support for Murata discovery board, in addition to LoRa shields on NUCLEO boards.

Use with sx1272 shield with grove peripherals connected:

D8 D9: ButtonRX TXA3 A4: TempSense
D6 D7:SCL SDA : LEDA1 A2: Pot

Button

Sends two different payload types: short press (under 1 sec)
long press: held down > 1 sec.

serial console keys

115200bps, 8N1
Enter key not used
Keys '0' to '3': cayenne channel number
'0': pot (rotary sensor)
'1': temperature
'2': digital out
'3': analog out

DevEUI configuration

For use on networks which force you to use DevEUI defined by network, comment out HardwareIDtoDevEUI().
HardwareIDtoDevEUI() obtains DevEUI from the CPU unique hardware serial number. However, some networks may force you to use their DevEUI value.

SerialDisplay.cpp

Committer:
Wayne Roberts
Date:
2018-07-25
Revision:
11:09556b27dbce
Parent:
9:1a94f4a5e716

File content as of revision 11:09556b27dbce:

/*
 / _____)             _              | |
( (____  _____ ____ _| |_ _____  ____| |__
 \____ \| ___ |    (_   _) ___ |/ ___)  _ \
 _____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
    (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 "lorawan_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 */