1 // **********************************************************************************
    2 //   Custom DPA Handler code example - Nodes polling                                *
    3 // **********************************************************************************
    4 // Copyright (c) IQRF Tech s.r.o.
    5 //
    6 // File:    $RCSfile: CustomDpaHandler-Coordinator-PollNodes.c,v $
    7 // Version: $Revision: 1.16 $
    8 // Date:    $Date: 2017/08/31 08:32:32 $
    9 //
   10 // Revision history:
   11 //   2017/03/13  Release for DPA 3.00
   12 //   2015/08/05  Release for DPA 2.20
   13 //   2014/10/31  Release for DPA 2.10
   14 //
   15 // **********************************************************************************
   16 
   17 // Online DPA documentation http://www.iqrf.org/DpaTechGuide/
   18 
   19 // Default IQRF include (modify the path according to your setup)
   20 #include "IQRF.h"
   21 
   22 // Implement Custom DPA Handler for Coordinator
   23 #define COORDINATOR_CUSTOM_HANDLER
   24 
   25 // Default DPA header (modify the path according to your setup)
   26 #include "DPA.h"
   27 // Default Custom DPA Handler header (modify the path according to your setup)
   28 #include "DPAcustomHandler.h"
   29 
   30 // Application periodically sends a request to every node and then it reports a received response to its interface master
   31 // If PeripehralRam[0].0 is set to 1, polling is disabled
   32 
   33 // The example will not work at demo DPA version because demo DPA does not support the following Custom DPA Handler events: DpaEvent_Interrupt, DpaEvent_BeforeSleep, DpaEvent_AfterSleep, DpaEvent_Reset, DpaEvent_DisableInterrupts, DpaEvent_ReceiveDpaResponse, DpaEvent_IFaceReceive, DpaEvent_ReceiveDpaRequest, DpaEvent_BeforeSendingDpaResponse
   34 
   35 // Machine states
   36 typedef enum
   37 {
   38   // Send request to the node
   39   state_SendRequest,
   40   // Wait for the response from node
   41   state_WaitResponse,
   42 } TState;
   43 
   44 // Must be the 1st defined function in the source code in order to be placed at the correct FLASH location!
   45 //############################################################################################
   46 bit CustomDpaHandler()
   47 //############################################################################################
   48 {
   49   // Handler presence mark
   50   clrwdt();
   51 
   52   // Currently polled node
   53   static uns8 nodeAddr;
   54   // Machine state
   55   static uns8 state;
   56 
   57   // Detect DPA event to handle
   58   switch ( GetDpaEvent() )
   59   {
   60     // -------------------------------------------------
   61     case DpaEvent_Init:
   62       // Do a one time initialization work before main loop starts
   63 
   64       // Next node address will be 1
   65       nodeAddr = MAX_ADDRESS;
   66       // Next state is to send request to the next nodeAddr
   67       state = state_SendRequest;
   68 
   69       // Give GSM GW time to start SPI master
   70       waitDelay( 100 );
   71 
   72       break;
   73 
   74       // -------------------------------------------------
   75     case DpaEvent_Idle:
   76       // Do a quick background work when RF packet is not received
   77 
   78       // What state is the application at?
   79       switch ( state )
   80       {
   81         // Send request to the node
   82         case state_SendRequest:
   83           // If bit 0 of PeripheralRam[0] is set, nodes are not polled
   84           if ( !PeripheralRam[0].0 )
   85           {
   86             // Store previous node address
   87             uns8 oldAddr = nodeAddr;
   88             for ( ;; )
   89             {
   90               // Generate next address, handle overflow
   91               if ( ++nodeAddr == ( MAX_ADDRESS + 1 ) )
   92                 nodeAddr = 1;
   93 
   94               // Is the node address bonded to the network?
   95               if ( isBondedNode( nodeAddr ) )
   96               {
   97                 // Next state is to wait for the response
   98                 state = state_WaitResponse;
   99 
  100                 // Send request to the node
  101                 _NADR = nodeAddr;
  102                 _NADRhigh = 0;
  103                 // Use OS peripheral
  104                 _PNUM = PNUM_OS;
  105                 // Read OS
  106                 _PCMD = CMD_OS_READ;
  107                 // Any HWPID
  108                 _HWPID = HWPID_DoNotCheck;
  109                 // This DPA request has no data
  110                 _DpaDataLength = 0;
  111                 // Send the DPA request
  112                 uns16 hopsBack = DpaApiRfTxDpaPacketCoordinator();
  113 
  114                 // Indicate DPA Request
  115                 pulseLEDG();
  116 
  117                 // Disable interrupts to prevent background change of DpaTicks variable
  118                 GIE = FALSE;
  119                 // Compute total number of hops C>N + N>C + 2
  120                 DpaTicks = (uns16)RTHOPS + hopsBack + 2;
  121                 // Response returns 11 bytes, so it will have the same slot length as request
  122                 DpaTicks *= RTTSLOT;
  123                 // Add extra 0.5s to the timeout
  124                 DpaTicks += 500 / 10;
  125                 // Enable interrupts again
  126                 GIE = TRUE;
  127                 // Exit the loop
  128                 break;
  129               }
  130 
  131               // If the loop is back, then there is no bonded node
  132               if ( nodeAddr == oldAddr )
  133               {
  134                 // Wait for a response that will not happen
  135                 state = state_WaitResponse;
  136                 // and after approx. 10s try to find bonded node again
  137                 GIE = FALSE;
  138                 DpaTicks = 1024;
  139                 GIE = TRUE;
  140                 // Exit the loop
  141                 break;
  142               }
  143             }
  144           }
  145           break;
  146 
  147         case state_WaitResponse:
  148           // Timeout occurred?
  149           if ( DpaTicks.15 != 0 )
  150             // Yes, request the next node
  151             state = state_SendRequest;
  152           break;
  153       }
  154       break;
  155 
  156       // -------------------------------------------------
  157     case DpaEvent_ReceiveDpaResponse:
  158       // Called after DPA response was received at coordinator
  159 
  160       // Is it a response from the requested node sent by me?
  161       if ( _NADR == nodeAddr && _PNUM == PNUM_OS && _PCMD == ( CMD_OS_READ | RESPONSE_FLAG ) && NetDepth == 1 )
  162       {
  163         // Response received indication
  164         pulseLEDR();
  165         // Yes, forward the result to the interface master, DPA value is 0
  166         DpaApiSendToIFaceMaster( 0, 0 );
  167         state = state_SendRequest;
  168         // Request was handled.
  169         return TRUE;
  170       }
  171       break;
  172 
  173       // -------------------------------------------------
  174     case DpaEvent_DpaRequest:
  175       // Called to interpret DPA request for peripherals
  176       // -------------------------------------------------
  177       // Peripheral enumeration
  178       if ( IsDpaEnumPeripheralsRequest() )
  179       {
  180         _DpaMessage.EnumPeripheralsAnswer.HWPID = 0x000F;
  181         _DpaMessage.EnumPeripheralsAnswer.HWPIDver = 0xABCD;
  182         return TRUE;
  183       }
  184 
  185       break;
  186   }
  187 
  188   return FALSE;
  189 }
  190 
  191 //############################################################################################
  192 // Default Custom DPA Handler header; 2nd include to implement Code bumper to detect too long code of the Custom DPA Handler (modify the path according to your setup) 
  193 #include "DPAcustomHandler.h"
  194 //############################################################################################