5.4. RFD Event Reporting of Open/Close of Reed Switch

5.4.1. Description

Implements an RFD application which sends the state of the attached reed switch whenever the switch opens or closes. Following data is reported.

  • On-chip Vcc sensor output (2 bytes)
  • State of the reed switch (1 byte): open(1), closed(2)

The RFD stays for the most part in deep sleep (micro sleeps in LPM3 and the radio sleeps in LPM2). Whenever the reed switch opens/closes, it interrupts the micro. The micro then debounces the switch after which the app sends the current state of the switch (open/close) to the gateway. The micro and radio go back to deep sleep after the message is sent and ack is received.

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

  • DEV_TYPE_RFD
  • RFD_APP_3
  • PLTFRM_ON_CHIP_VCC_SENSE_ENA
  • PLTFRM_REED_SWITCH_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))
  • 1 bytes (reed switch state (1 byte): open(1), closed(2))

The reed switch driver code is in pltfrm/src/reed_switch.c

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

5.4.2. Code

#ifdef DEV_TYPE_RFD

#ifdef RFD_APP_3

#if defined(PLTFRM_REED_SWITCH_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 <reed_switch.h>


#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_reedSwitchEvtCnt = 0;


void RFD_APP_buildSendSnsrUpdate(void)
{
   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
                    + REED_SWITCH_STATE_OUTPUT_SZ;
   UINT8_t evtPendFlag = 0x0;

   if (REED_SWITCH_checkPendingEvt(PLTFRM_REED_SWITCH_1_DEV_ID, &evtPendFlag) == PLTFRM_STS_SUCCESS)
   {
       if (evtPendFlag)
       {
           RFD_APP_reedSwitchEvtCnt ++;
       }
       else
       {
           SYS_globalEvtMsk1 |= SYS_GLOBAL_EVT_ENTER_LPM_REQUEST;
           return;
       }
   }
   else
   {
       SYS_fatal();
   }

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

   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;
       }

       {
           REED_SWITCH_state_t swState;
           if (REED_SWITCH_getState(PLTFRM_REED_SWITCH_1_DEV_ID, &swState) != PLTFRM_STS_SUCCESS)
               SYS_fatal();
           *buff_p = (UINT8_t)(swState);
           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_globalEvtMsk1 |= SYS_GLOBAL_EVT_ENTER_LPM_REQUEST;
       }
   }
}

void RFD_APP_wakeUpProc( )
{
   RFD_APP_buildSendSnsrUpdate();
}

void RFD_APP_nodeJoinDoneInd(void)
{
   // Enable interrupts from the reed switch
   if (REED_SWITCH_ena(PLTFRM_REED_SWITCH_1_DEV_ID) != PLTFRM_STS_SUCCESS)
   {
       SYS_fatal();
   }

   RFD_APP_wakeUpProc( );
}

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_globalEvtMsk1 |= SYS_GLOBAL_EVT_ENTER_LPM_REQUEST;
           }
           break;

      default:
           break;
   }

   return;
}

void RFD_APP_init(void)
{
   // The micro will only wake up whenever the reed switch opens or closes.
   SYS_SET_WAKEUP_INTERVAL(0);

   return;
}

#endif
#endif
#endif