test harness

Dependencies:   LoRaWAN-NAMote72-Application-Demo LoRaWAN-lib2 SX1272Lib lib_gps lib_mma8451q lib_mpl3115a2 mbed

Fork of LoRaWAN-NAMote72-Application-Demo by Semtech

app/LoRaApp.cpp

Committer:
billvs
Date:
2017-11-08
Revision:
16:3aa2e2bf34c3
Parent:
15:39a23f5affd1

File content as of revision 16:3aa2e2bf34c3:

/*
 / _____)             _              | |
( (____  _____ ____ _| |_ _____  ____| |__
 \____ \| ___ |    (_   _) ___ |/ ___)  _ \
 _____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
    (C)2015 Semtech

Description: User-defined applications such as GPS, Temp, Accelerometer, LED indications etc.
            Event based actions such as LED blink on Tx, LED toggle on downlink etc

License: Revised BSD License, see LICENSE.TXT file include in the project

Maintainer: Uttam Bhat
*/

#include "LoRaApp.h"

bool VerticalStatus = false;

/*!
 * Red LED timer event
 */
TimerLed RedLedTimer( Red );

/*!
 * Yellow LED timer event
 */
TimerLed YellowLedTimer( Yellow );

/*!
 * Green LED timer event
 */
TimerLed GreenLedTimer( Green );

Application::Application( uint8_t * memptr )
{
    BuffAddr = memptr;
    memset( BuffAddr, 0, LORAWAN_APP_DATA_MAX_SIZE );
    BuffPtr = 0;    
}

Application::~Application( )
{
}

void Application::ApplicationAppendData( uint8_t *pData, uint8_t len )
{
    if( ( BuffPtr + len ) <= LORAWAN_APP_DATA_SIZE )
    {
        memcpy( BuffAddr + BuffPtr, pData, len );
        BuffPtr += len;
    }
}

void Application::ApplicationPtrPos( uint8_t ptrPos )
{
    BuffPtr = ptrPos;
}

void Application::ApplicationCall( eAppType App )
{
    switch( App )
    {
        // Appends 8 Bytes (3 bytes longitude, 3 bytes latitude, 2 bytes altitude) to TX buffer
        case AppGps:
        {
            Gps.service( );

            uint16_t altitudeGps = atoi( Gps.NmeaGpsData.NmeaAltitude );

            if( ( BuffPtr + 8 ) <= LORAWAN_APP_DATA_SIZE )
            {               
                BuffAddr[BuffPtr++] = ( Gps.LatitudeBinary >> 16 ) & 0xFF;
                BuffAddr[BuffPtr++] = ( Gps.LatitudeBinary >> 8 ) & 0xFF;
                BuffAddr[BuffPtr++] = Gps.LatitudeBinary & 0xFF;
                BuffAddr[BuffPtr++] = ( Gps.LongitudeBinary >> 16 ) & 0xFF;
                BuffAddr[BuffPtr++] = ( Gps.LongitudeBinary >> 8 ) & 0xFF;
                BuffAddr[BuffPtr++] = Gps.LongitudeBinary & 0xFF;           
                BuffAddr[BuffPtr++] = ( altitudeGps >> 8 ) & 0xFF;
                BuffAddr[BuffPtr++] = altitudeGps & 0xFF;
            }
            break;
        }

        // Appends 1 Byte to TX buffer
        case AppPrsr:
        {               
            if( ( BuffPtr + 2 ) <= LORAWAN_APP_DATA_SIZE )
            {                
                volatile uint8_t stat;
                float val;

                Mpl3115a2.SetModeBarometer();
                Mpl3115a2.ToggleOneShot( );
                   
                stat = Mpl3115a2.read(STATUS_REG);       
                while( (stat & 0x04) != 0x04 ) {
                    wait(0.01);   
                    stat = Mpl3115a2.read(STATUS_REG);                  
                }

                val = Mpl3115a2.ReadBarometer()/100.0;
                
                BuffAddr[BuffPtr++] = ( ( uint16_t ) val >> 8 ) & 0xFF;
                BuffAddr[BuffPtr++] = ( ( uint16_t ) val ) & 0xFF;
                
            }
            break;
        }

        // Appends 1 Byte to TX buffer
        case AppTemp:
        {           
            Mpl3115a2.ReadTemperature( );
            if( ( BuffPtr + 1 ) <= LORAWAN_APP_DATA_SIZE )
            {
                BuffAddr[BuffPtr++] = ( int32_t )Mpl3115a2.Temperature;     // Signed degrees Celcius in half degree units. So, +/-63 °C                         
            }
            break;
        }       

        // Appends 1 Byte to TX buffer
        case AppBat:
        {  
            if( ( BuffPtr + 1 ) <= LORAWAN_APP_DATA_SIZE )
            {
#ifdef BAT_VAL_PERCENT
                uint16_t value;
                value = BoardGetBatteryLevel();
                BuffAddr[BuffPtr++] = ( value * 100 ) >> 8;  // Bat level in %
#else
                BuffAddr[BuffPtr++] = BoardGetBatteryLevel( );              // Per LoRaWAN spec; 0 = Charging; 1...254 = level, 255 = N/A
#endif                
            }
            break;
        }

        // Appends incremental values of 1 Byte each to TX buffer until Full
        case AppRamp:
        {
            int32_t i, j;

            // Populate Tx Buffer with increasing byte values starting from 0x00, 0x01, 0x02 ... 
            for( i = BuffPtr, j = 0; i < LORAWAN_APP_DATA_SIZE; i++ )
            {
                BuffAddr[i] = j++;
            }
            BuffPtr = LORAWAN_APP_DATA_SIZE;
            break;
        }

        // Appends 2 Bytes to TX buffer
        case AppAccl:
        {   
            uint8_t statusReg; 

            // Read the PS_STATUS register
            statusReg = Mma8451q.read_single( MMA8451_PL_STATUS );

            /* Display Orientation of NAMote on Serial Port */
            SerialAcclMetrDisplay( statusReg );

            // If Orientation of the Mote changed then let Green LED ON
            if( ( statusReg & 0x80 ) != 0 )
            {
                AppLed = 1;
                CtrlLED( Green, LED_ON );
            }

            // Read and populate device orientation in Tx Buffer
            if( ( BuffPtr + 2 ) <= LORAWAN_APP_DATA_SIZE )
            {
                if( statusReg & 0x40 )
                {
                    if( statusReg & 0x01 )
                    {
                        BuffAddr[BuffPtr++] = 0x66; // horizontal + faceup
                    }
                    else
                    {
                        BuffAddr[BuffPtr++] = 0x99; // horizontal + facedown
                    }

                    BuffAddr[BuffPtr++] = 0; // vertical = false
                }
                else
                {
                    BuffAddr[BuffPtr++] = 0; // horizontal = false
                    BuffAddr[BuffPtr++] = 0x11; // vertical = true
                }               
            }       
            
            break;
        }       

        case AppAcclSenet:
        {   
            uint8_t statusReg; 

            // Read the PS_STATUS register
            statusReg = Mma8451q.read_single( MMA8451_PL_STATUS );

            /* Display Orientation of NAMote on Serial Port */
            SerialAcclMetrDisplay( statusReg );

            // If Orientation of the Mote changed then populate Upper Nibble of 0th Byte of Tx Buffer                       
            if( ( statusReg & 0x40 ) != 0 )
            {   
                AppLed = 0;
                CtrlLED( Green, LED_OFF );
                BuffAddr[BuffPtr++] = 0; // horizontal
            }
            else
            {
                AppLed = 1;
                CtrlLED( Green, LED_ON );
                BuffAddr[BuffPtr++] = 10; // vertical
            }                       
            
            break;
        }

        case AppAcclSensor:
        {   
            uint8_t statusReg;
            int8_t regVal;
            int16_t axesData;

            // Read the PS_STATUS register
            statusReg = Mma8451q.read_single( MMA8451_PL_STATUS );

            /* Display Orientation of NAMote on Serial Port */
            SerialAcclMetrDisplay( statusReg );

            // If Orientation of the Mote changed then populate Upper Nibble of 0th Byte of Tx Buffer                       
            if( ( statusReg & 0x80 ) != 0 )
            {                   
                CtrlLED( Green, LED_ON );                
            }
            else
            {                
                CtrlLED( Green, LED_OFF );
            } 

            // Read and populate device orientation in Tx Buffer
            if( ( BuffPtr + 6 ) <= LORAWAN_APP_DATA_SIZE )
            {
                uint8_t addr;
                addr = MMA8451_OUT_X_MSB;

                // Read X-axis Data
                regVal = Mma8451q.read_single( addr++ );
                axesData = regVal << 8;
                regVal = Mma8451q.read_single( addr++ );
                axesData |= regVal;             
                BuffAddr[BuffPtr++] = ( axesData >> 10 ) & 0xFF; 
                BuffAddr[BuffPtr++] = ( axesData >> 2 ) & 0xFF; 

                // Read Y-axis Data
                regVal = Mma8451q.read_single( addr++ );
                axesData = regVal << 8;
                regVal = Mma8451q.read_single( addr++ );
                axesData |= regVal;             
                BuffAddr[BuffPtr++] = ( axesData >> 10 ) & 0xFF; 
                BuffAddr[BuffPtr++] = ( axesData >> 2 ) & 0xFF; 

                // Read Z-axis Data
                regVal = Mma8451q.read_single( addr++ );
                axesData = regVal << 8;
                regVal = Mma8451q.read_single( addr++ );
                axesData |= regVal;             
                BuffAddr[BuffPtr++] = ( axesData >> 10 ) & 0xFF; 
                BuffAddr[BuffPtr++] = ( axesData >> 2 ) & 0xFF; 
            }
            
            break;
        }

        case AppPushButton:
        {   
            uint16_t PushButtonCnt;
            uint8_t *p = (uint8_t *) &PushButtonCnt;

            PushButtonCnt = LoRaMacUplinkStatus.UplinkCounter;
                
            memcpy( &BuffAddr[BuffPtr], p, sizeof(uint16_t) );
            
            break;
        }

        default:
        {            
            break;
        }
    }
}

static void OnRedLedTimerEvent( void )
{
    TimerStop( &RedLedTimer.LedTimer );

    if( RedLed == LED_OFF )
    {
        RedLed = LED_ON;
    }
    else
    {
        RedLed = LED_OFF;
    }
}

static void OnYellowLedTimerEvent( void )
{
    TimerStop( &YellowLedTimer.LedTimer );

    if( YellowLed == LED_OFF )
    {
        YellowLed = LED_ON;
    }
    else
    {
        YellowLed = LED_OFF;
    }
}

static void OnGreenLedTimerEvent( void )
{
    TimerStop( &GreenLedTimer.LedTimer );

    if( GreenLed == LED_OFF )
    {
        GreenLed = LED_ON;
    }
    else
    {
        GreenLed = LED_OFF;
    }
}

TimerLed::TimerLed( eLedType led )
{
    switch( led )
    {
        case Red:
        {
            TimerInit( &LedTimer, OnRedLedTimerEvent );
            break;
        }

        case Yellow:
        {
            TimerInit( &LedTimer, OnYellowLedTimerEvent );
            break;
        }

        case Green:
        {
            TimerInit( &LedTimer, OnGreenLedTimerEvent );
            break;
        }
    }
    
}
        
TimerLed::~TimerLed( )
{
}

void BlinkLED( eLedType led, uint32_t time )
{
    switch( led )
    {
        case Red:
        {
            TimerSetValue( &RedLedTimer.LedTimer, time );
            TimerStart( &RedLedTimer.LedTimer );
            RedLed = LED_ON;
            break;
        }

        case Yellow:
        {
            TimerSetValue( &YellowLedTimer.LedTimer, time );
            TimerStart( &YellowLedTimer.LedTimer );
            YellowLed = LED_ON;
            break;
        }

        case Green:
        {
            TimerSetValue( &GreenLedTimer.LedTimer, time );
            TimerStart( &GreenLedTimer.LedTimer );
            GreenLed = LED_ON;
            break;
        }
    }
}

void ToggleLED( eLedType led )
{
    switch( led )
    {
        case Red:
        {
            if( RedLed == LED_OFF )
            {
                RedLed = LED_ON;
            }
            else
            {
                RedLed = LED_OFF;
            }
            break;
        }

        case Yellow:
        {
            if( YellowLed == LED_OFF )
            {
                YellowLed = LED_ON;
            }
            else
            {
                YellowLed = LED_OFF;
            }
            break;
        }

        case Green:
        {
            if( GreenLed == LED_OFF )
            {
                GreenLed = LED_ON;
            }
            else
            {
                GreenLed = LED_OFF;
            }
            break;
        }
    }
}   

void CtrlLED( eLedType led, uint8_t state )
{
    switch( led )
    {
        case Red:
        {
            RedLed = state;
            break;
        }

        case Yellow:
        {
            YellowLed = state;
            break;
        }

        case Green:
        {
            GreenLed = state;
            break;
        }

        case Usr:
        {
            if( state )
            {
                UsrLed = LED_ON;
            }
            else
            {
                UsrLed = LED_OFF;
            }
            break;
        }
    }
}

void CheckOrientation( void )
{
    uint8_t statusReg; 
    
    // Read the PS_STATUS register
    statusReg = Mma8451q.read_single( MMA8451_PL_STATUS );

     // If Orientation of the Mote changed then populate Upper Nibble of 0th Byte of Tx Buffer                       
    if( ( statusReg & 0x40 ) != 0 )
    {           
        CtrlLED( Green, LED_OFF );
        VerticalStatus = false; // horizontal
    }
    else
    {        
        CtrlLED( Green, LED_ON );
        VerticalStatus = true; // vertical
    }       
}