1 // *********************************************************************
    2 //   Custom DPA Handler code example - Local FRC                       *
    3 // *********************************************************************
    4 // Copyright (c) MICRORISC s.r.o.
    5 //
    6 // File:    $RCSfile: CustomDpaHandler-LocalFRC.c,v $
    7 // Version: $Revision: 1.9 $
    8 // Date:    $Date: 2021/04/26 15:13:50 $
    9 //
   10 // Revision history:
   11 //   2020/09/03  Release for DPA 4.15
   12 //
   13 // *********************************************************************
   14 
   15 // Online DPA documentation https://doc.iqrf.org/DpaTechGuide/
   16 
   17 // Default IQRF include (modify the path according to your setup)
   18 #include "IQRF.h"
   19 
   20 // Default DPA header (modify the path according to your setup)
   21 #include "DPA.h"
   22 // Default Custom DPA Handler header (modify the path according to your setup)
   23 #include "DPAcustomHandler.h"
   24 
   25 //############################################################################################
   26 
   27 // This minimalistic example implements both Local FRC Controller and Actuator.
   28 
   29 // When a IQRF button is pressed, the controller sends Local FRC command to switch on/off LEDR at [Ns]1-5 (actuators). LEDG at the Controller indicates on/off status.
   30 // Actuators i.e. [Ns] which received Local FRC command from the Controller must have Local FRC enabled in their configuration.
   31 // Actuators use DpaEvent_VerifyLocalFrc to allow only FRC_AcknowledgedBroadcastBits and FRC_MemoryRead[Plus1] FRCs with embedded DPA Request with PNUM_LEDR. Also only Local FRC Controllers with odd address are allowed to control the Actuator.
   32 
   33 
   34 // Choose local FRC command to be used:
   35 
   36 // This (1 byte) FRC command executes embedded DPA Request immediately. DPA Request must be processed within 40 ms and maximum 63 [Ns] can be addressed.
   37 //#define   LOCAL_FRC_CMD     FRC_MemoryReadPlus1
   38 // This (2 bit) FRC command executes embedded DPA Request after the whole FRC process is finished (delay might be noticed). Maximum 239 [Ns] can be addressed. DPA Request execution time is not limited.
   39 #define   LOCAL_FRC_CMD   FRC_AcknowledgedBroadcastBits
   40 
   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   // Detect DPA event to handle (unused event handlers can be commented out or even deleted)
   51   switch ( GetDpaEvent() )
   52   {
   53     // -------------------------------------------------
   54     case DpaEvent_Interrupt:
   55       // Do an extra quick background interrupt work
   56       return Carry;
   57 
   58       // -------------------------------------------------
   59     case DpaEvent_Idle:
   60       // Do a quick background work when RF packet is not received
   61 
   62     { // ###### Local FRC Controller part ######
   63       static bit wasButtonPressed;
   64 
   65       // If the button is pressed, send appropriate Local FRC command to switch on/off the actuator
   66       if ( buttonPressed )
   67       {
   68         if ( !wasButtonPressed )
   69         {
   70           // Selected [Ns] bitmap for Local FRC. In this example it is hard-coded. In real application it might be read from EEPROM.
   71           clearBufferINFO();
   72           // [Ns] 1-5
   73           bufferINFO[0] = 0b111110;
   74 
   75           // Prepare DPA Request. In this example it is hard-coded. In real application it might be read from EEPROM.
   76           // W = PCMD
   77           static bit offOrOn;
   78           offOrOn = !offOrOn;
   79           if ( offOrOn )
   80           {
   81             setLEDG();
   82             W = CMD_LED_SET_ON;
   83           }
   84           else
   85           {
   86             stopLEDG();
   87             W = CMD_LED_SET_OFF;
   88           }
   89 
   90           // FRC User data structure varies according the actual FRC command used
   91 #if LOCAL_FRC_CMD == FRC_AcknowledgedBroadcastBits
   92           // PCMD
   93           DataInSendFRC[2] = W;
   94           // Total DPA Request length
   95           DataInSendFRC[0] = 5;
   96           // PNUM
   97           DataInSendFRC[1] = PNUM_LEDR;
   98           // HWPID
   99           DataInSendFRC[3] = HWPID_DoNotCheck & 0xFF;
  100           DataInSendFRC[4] = HWPID_DoNotCheck >> 8;
  101 #elif LOCAL_FRC_CMD == FRC_MemoryReadPlus1 || LOCAL_FRC_CMD == FRC_MemoryRead
  102           // PCMD
  103           DataInSendFRC[3] = W;
  104           // Memory address
  105           DataInSendFRC[0] = ( (uns16)&_DpaMessage.Response.PData[0] ) & 0xFF;
  106           DataInSendFRC[1] = ( (uns16)&_DpaMessage.Response.PData[0] ) >> 8;
  107           // PNUM
  108           DataInSendFRC[2] = PNUM_LEDR;
  109           // DPA Request data length
  110           DataInSendFRC[4] = 0;
  111 #else
  112 #error Unimplemented FRC Command
  113 #endif
  114 
  115           // Do local FRC
  116           // If some addressed Nodes except me did not answer, keep LEDG pulsing to indicate it
  117           if ( DpaApiLocalFrc( LOCAL_FRC_CMD, RFpower ) + 1 != param2 )
  118             pulsingLEDG();
  119           // Note: workaround to resolve the missing internal reset of the _localFRC variable at IQRF OS 4.04D
  120           _localFRC = FALSE;
  121         }
  122 
  123         wasButtonPressed = TRUE;
  124       }
  125       else
  126         wasButtonPressed = FALSE;
  127 
  128       break;
  129     }
  130 
  131     // -------------------------------------------------
  132     case DpaEvent_VerifyLocalFrc:
  133       // Called to verify local FRC command
  134 
  135       // ###### Local FRC Actuator part ######
  136       // Allow only certain FRC commands, DPA Requests and Local FRC Controller addresses
  137 
  138       // Ignore Local FRC send from even [Ns] Controllers
  139       if ( !TX.0 )
  140         break;
  141 
  142       // Allow only certain FRC commands and DPA Request peripherals (LEDR) to work with
  143       switch ( _PCMD )
  144       {
  145         case FRC_AcknowledgedBroadcastBits:
  146           if ( DataOutBeforeResponseFRC[1] == PNUM_LEDR )
  147             goto DpaHandleReturnTRUE;
  148           break;
  149 
  150         case FRC_MemoryRead:
  151         case FRC_MemoryReadPlus1:
  152           if ( DataOutBeforeResponseFRC[2] == PNUM_LEDR )
  153             goto DpaHandleReturnTRUE;
  154           break;
  155       }
  156 
  157       break;
  158 
  159       // -------------------------------------------------
  160     case DpaEvent_DpaRequest:
  161       // Called to interpret DPA request for peripherals
  162       if ( IsDpaEnumPeripheralsRequest() )
  163       {
  164         // -------------------------------------------------
  165         // Peripheral enumeration
  166         _DpaMessage.EnumPeripheralsAnswer.HWPID = 0xF5CF;
  167 
  168 DpaHandleReturnTRUE:
  169         return TRUE;
  170       }
  171 
  172       break;
  173   }
  174 
  175 DpaHandleReturnFALSE:
  176   return FALSE;
  177 }
  178 
  179 //############################################################################################
  180 // 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)
  181 #include "DPAcustomHandler.h"
  182 //############################################################################################