5.6. RFD Periodic Reporting of Ambient Light Intensity from TSL45315

5.6.1. Description

Implements an RFD application in which the following data is reported to the gateway every few seconds.

  • Light intensity in “Lux” from attached light sensor “TSL45315” (4 bytes)
  • On-chip Vcc sensor output (2 bytes)

When building an RFD executable which includes rfd_app_5.c, these macros need to enabled :-

  • DEV_TYPE_RFD
  • RFD_APP_5
  • PLTFRM_ON_CHIP_VCC_SENSE_ENA
  • PLTFRM_TSL45315_ENA

The data packet sent out by this app has the following format :-

  • 2 bytes (packet sequence number)
  • 1 byte (sensor bit mask with value 0x7)
  • 2 bytes (On-chip Vcc sensor output (unsigned 2 byte value))
  • 4 bytes (Light intensity in Lux)

The TSL45315 driver code is in pltfrm/src/tsl45315.c

To learn more about the sensors and the API, visit sections TSL45315 (AMS-TAOS) and On-Chip Voltage Sensor (TI MSP430).

5.6.2. Code

#ifdef DEV_TYPE_RFD
#ifdef RFD_APP_5
#if defined(PLTFRM_TSL45315_ENA) && defined(PLTFRM_ON_CHIP_VCC_SENSE_ENA)

#include <typedefs.h>
#include <system.h>
#include <pltfrm.h>
#include <util.h>
#include <mac_pib.h>
#include <adp.h>
#include <rfd_app.h>
#include <tsl45315.h>

RFD_APP_state_t RFD_APP_state = RFD_APP_STATE_CONVERSION_DONE;

#define RFD_APP_DATA_SEQ_NR_SZ   2
#define RFD_APP_DATA_SNSR_BIT_MSK_SZ   1

UINT16_t RFD_APP_pktSeqNr = 0;

// Stats
UINT16_t RFD_APP_dataTxReqCnt = 0;
UINT16_t RFD_APP_dataRxReqFailCnt = 0;
UINT16_t RFD_APP_cnfrmOkCnt = 0;
UINT16_t RFD_APP_cnfrmFlrCnt = 0;

UINT16_t RFD_APP_motionSenseCnt = 0;

void RFD_APP_buildSendSnsrUpdate(SINT32_t lux32)
{
   UINT8_t pktLen = ADP_ELEMENT_TYPE_LEN
                    + RFD_APP_DATA_SEQ_NR_SZ
                    + RFD_APP_DATA_SNSR_BIT_MSK_SZ
                    + PLTFRM_ON_CHIP_VCC_SENSOR_OUTPUT_LEN
                    + TSL45315_SENSOR_OUTPUT_VALUE_SZ;

   // seq-nr                            <2 bytes>
   // bit mask                          <1 byte / 2 bits valid (0 and 1)>
   // On chip Vcc sensor o/p            <2 bytes>
   // TSL45315 light o/p                <4 bytes>

   ADP_cntxt.txParams.bdHndl = SYS_allocMem(pktLen);
   if (SYS_BD_HNDL_IS_VALID(ADP_cntxt.txParams.bdHndl))
   {
       UINT8_t *buff_p = SYS_GET_BD_BUFF(ADP_cntxt.txParams.bdHndl);
       UINT8_t *flag_p, snsrFlag = 0x0;

       buff_p += ADP_ELEMENT_TYPE_LEN;

       RFD_APP_pktSeqNr ++;
       buff_p = UTIL_htons(buff_p, RFD_APP_pktSeqNr);

       flag_p = buff_p;
       buff_p ++;  // skip sensor flag field ...

       {
          UINT16_t vcc = 0;
          pltfrm_vccSenseInit( );
          vcc = pltfrm_vccSense();
          buff_p = UTIL_htons(buff_p, vcc);
          snsrFlag |= BIT0;
       }

       if (lux32 < 0)
       {
          if (TSL45315_getALSOutput(PLTFRM_TSL45315_1_DEV_ID, &lux32) != PLTFRM_STS_SUCCESS)
              SYS_fatal();
       }
       buff_p = UTIL_htonl(buff_p, lux32);
       snsrFlag |= BIT1;

       *flag_p = snsrFlag;

       ADP_cntxt.txParams.destShortAddr = LPWMN_COORD_MAC_SHORT_ADDR;

       RFD_APP_dataTxReqCnt ++;

       if (ADP_appPyldTxReq() != ADP_STS_SUCCESS)
       {
           RFD_APP_dataRxReqFailCnt ++;
           SYS_SET_WAKEUP_INTERVAL(RFD_APP_5_DFLT_WAKE_UP_INTERVAL_SECS);
           SYS_globalEvtMsk1 |= SYS_GLOBAL_EVT_ENTER_LPM_REQUEST;
       }
   }
}

void RFD_APP_TSL45315_intTmoHndlr(void)
{
   // No need to do anything here. The purpose of the timer interrupt
   // is to wake up the micro. After waking up, RFD_APP_wakeUpProc( )
   // will be called.
   return;
}

void RFD_APP_wakeUpProc( )
{
   if (RFD_APP_state == RFD_APP_STATE_WAIT_CONVERSION)
   {
       RFD_APP_buildSendSnsrUpdate(-1);
       RFD_APP_state = RFD_APP_STATE_CONVERSION_DONE;
   }
   else
   {
       SINT32_t lux32;
       UINT16_t tmoVal;
       PLTFRM_sts_t sts;

       sts = TSL45315_startALSConv(PLTFRM_TSL45315_1_DEV_ID,
                                   &lux32,
                                   &tmoVal);
       if ((sts != PLTFRM_STS_SUCCESS) && (sts != PLTFRM_STS_OPN_IN_PROGRESS))
       {
           SYS_fatal();
       }
       else
       {
           if (sts == PLTFRM_STS_OPN_IN_PROGRESS)
           {
               if (PLTFRM_startTimerA1(0, tmoVal, RFD_APP_TSL45315_intTmoHndlr) != PLTFRM_STS_SUCCESS)
               {
                   SYS_fatal();
               }
               else
               {
                   SYS_globalEvtMsk1 |= SYS_GLOBAL_EVT_ENTER_LPM_REQUEST;
                   RFD_APP_state = RFD_APP_STATE_WAIT_CONVERSION;
                   SYS_SET_WAKEUP_INTERVAL(0);
               }
           }
           else
           {
               RFD_APP_buildSendSnsrUpdate(lux32);
               RFD_APP_state = RFD_APP_STATE_CONVERSION_DONE;
           }
       }
   }

   return;
}

void RFD_APP_nodeJoinDoneInd(void)
{
   SYS_SET_WAKEUP_INTERVAL(RFD_APP_5_DFLT_WAKE_UP_INTERVAL_SECS);
   SYS_globalEvtMsk1 |= SYS_GLOBAL_EVT_ENTER_LPM_REQUEST;
   RFD_APP_state = RFD_APP_STATE_CONVERSION_DONE;
   return;
}

void RFD_APP_prepareToEnterLPM(void)
{
   // Interrupts are disabled globally at this point.
   // The MSP430 will go into deep sleep mode on returning
   // from this function.
   return;
}

void RFD_APP_wakeUpTimerExpEvt(void)
{
   return;
}

void APP_procGPIOEvt()
{
   return;
}

void RFD_APP_evtHndlr(UINT16_t globalEvtId, void *params_p)
{
   switch (globalEvtId)
   {
      case SYS_GLOBAL_EVT_ADP_DATA_CONFIRM:
           {
              ADP_dataCnfrmParams_s *dcParams_p = (ADP_dataCnfrmParams_s *)params_p;
              if (dcParams_p->sts == ADP_STS_SUCCESS)
              {
                  RFD_APP_cnfrmOkCnt ++;
              }
              else
              {
                  RFD_APP_cnfrmFlrCnt ++;
              }
              SYS_SET_WAKEUP_INTERVAL(RFD_APP_5_DFLT_WAKE_UP_INTERVAL_SECS);
              SYS_globalEvtMsk1 |= SYS_GLOBAL_EVT_ENTER_LPM_REQUEST;
           }
           break;

      default:
           break;
   }

   return;
}

void RFD_APP_init(void)
{
   SYS_SET_WAKEUP_INTERVAL(RFD_APP_5_DFLT_WAKE_UP_INTERVAL_SECS);

   return;
}

#endif
#endif
#endif