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