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