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