mQ Branch for NA mote testing

Dependencies:   LoRaWAN-lib SX1272Lib-mQ lib_gps lib_mma8451q lib_mpl3115a2 mbed

Fork of LoRaWAN-NAMote72-Application-Demo by Semtech

app/LoRaApp.cpp

Committer:
Benedict_Tizzano
Date:
2018-03-30
Revision:
19:e136bd75eabd
Parent:
18:18408c3c2d0c

File content as of revision 19:e136bd75eabd:

/*
 / _____)             _              | |
( (____  _____ ____ _| |_ _____  ____| |__
 \____ \| ___ |    (_   _) ___ |/ ___)  _ \
 _____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
    (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 )
{
    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 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 )
            {
                BuffAddr[BuffPtr++] = BoardGetBatteryLevel( );              // Per LoRaWAN spec; 0 = Charging; 1...254 = level, 255 = N/A
            }
            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 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;
        }
        default:
        {
            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;
        }
        default:
        {
            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;
        }
        default:
        {
            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
    }
}