1 // *********************************************************************
    2 //   Custom DPA Handler code template                                  *
    3 // *********************************************************************
    4 // Copyright (c) MICRORISC s.r.o.
    5 //
    6 // File:    $RCSfile: CustomDpaHandler-TwoButtons.c,v $
    7 // Version: $Revision: 1.2 $
    8 // Date:    $Date: 2026/05/22 14:48:54 $
    9 //
   10 // Revision history:
   11 //   2025/05/30  Release for DPA 4.33
   12 //
   13 // *********************************************************************
   14 
   15 /*
   16 This example shows how to operate a second button, in addition to the default DPA button connected to RB4.
   17 The second button can be connected to any GPIO. In this example, RA0 was chosen.
   18 Both the RB4 and the RA0 are digital inputs with weak pull-up activated. This is the default setting for RB4.
   19 The buttons can operate in three different modes. See the MODE_DPA_... symbols below.
   20 The MODE symbol controls the conditional compilation of the custom DPA handler for the selected mode.
   21 The following simple circuit is needed for the buttons to work in any of the three modes.
   22 
   23                RB4         RA0
   24                 #           #
   25                 |           |
   26                 |   Diode   |
   27                 |           |
   28                 o---->|-----o
   29                 |           |
   30                 |           |
   31  Default      | o         | o  Second
   32  DPA Button |=|>        |=|>   Button
   33               | o         | o
   34                 |           |
   35                 |           |
   36                ===         ===
   37                GND         GND
   38 */
   39 
   40 // Both buttons open the same default DPA Menu
   41 #define MODE_DPA_MENUS 0
   42 // Both buttons open the DPA Menu, but they differ. DPA Menu opened by the default RB4 button does not contain menu items including StandBy and after.
   43 #define MODE_DPA_MENUS_DIFERENTIATED 1
   44 // Second button does not open DPA Menu, but controls Green LED.
   45 #define MODE_SEPARATED 2
   46 
   47 // The actual mode
   48 #define MODE MODE_SEPARATED
   49 
   50 //############################################################################################
   51 
   52 // Default IQRF include (modify the path according to your setup)
   53 #include "IQRF.h"
   54 
   55 // Default DPA header (modify the path according to your setup)
   56 #include "DPA.h"
   57 // Default Custom DPA Handler header (modify the path according to your setup)
   58 #include "DPAcustomHandler.h"
   59 
   60 // Second button definition
   61 #define BTN2_TRIS TRISA.0
   62 #define BTN2_PORT PORTA.0
   63 #define BTN2_WPU  WPUA.0
   64 
   65 //############################################################################################
   66 // https://doc.iqrf.org/DpaTechGuide/pages/custom-dpa-handler.html
   67 bit CustomDpaHandler()
   68 //############################################################################################
   69 {
   70   // Handler presence mark
   71   clrwdt();
   72 
   73   // Detect DPA event to handle (unused event handlers can be commented out or even deleted)
   74   switch ( GetDpaEvent() )
   75   {
   76     // -------------------------------------------------
   77     case DpaEvent_Interrupt:
   78       // Do an extra quick background interrupt work
   79       // ! The time spent handling this event is critical.If there is no interrupt to handle return immediately otherwise keep the code as fast as possible.
   80       // ! Make sure the event is the 1st case in the main switch statement at the handler routine.This ensures that the event is handled as the 1st one.
   81       // ! It is desirable that this event is handled with immediate return even if it is not used by the custom handler because the Interrupt event is raised on every MCU interrupt and the “empty” return handler ensures the shortest possible interrupt routine response time.
   82       // ! Only global variables or local ones marked by static keyword can be used to allow reentrancy.
   83       // ! Make sure race condition does not occur when accessing those variables at other places.
   84       // ! Make sure( inspect.lst file generated by C compiler ) compiler does not create any hidden temporary local variable( occurs when using division, multiplication or bit shifts ) at the event handler code.The name of such variable is usually Cnumbercnt.
   85       // ! Do not call any OS functions except setINDFx().
   86       // ! Do not use any OS variables especially for writing access.
   87       // ! All above rules apply also to any other function being called from the event handler code, although calling any function from Interrupt event is not recommended because of additional MCU stack usage.
   88       // https://doc.iqrf.org/DpaTechGuide/pages/EventInterrupt.html
   89       return Carry;
   90 
   91 
   92       // -------------------------------------------------
   93     case DpaEvent_Idle:
   94       // Do a quick background work when RF packet is not received
   95       // https://doc.iqrf.org/DpaTechGuide/pages/idle.html
   96 
   97 #if MODE == MODE_SEPARATED
   98       _LEDG = !BTN2_PORT;
   99 #endif
  100       break;
  101 
  102       // -------------------------------------------------
  103     case DpaEvent_MenuActivated:
  104       // Called to customize DPA menu
  105       // https://doc.iqrf.org/DpaTechGuide/pages/menuactivated.html
  106 
  107 #if MODE == MODE_SEPARATED
  108 
  109       // 2nd button pressed?
  110       if ( !BTN2_PORT )
  111         _DpaMessage.PerNodeGetDpaMenuInfo_Response.FlagsExt = DMENU_Ext_DoNotOpen;
  112 
  113 #elif MODE == MODE_DPA_MENUS_DIFERENTIATED
  114 
  115       // 2nd button pressed?
  116       if ( !BTN2_PORT )
  117         // Open default DPA Menu
  118         break;
  119 
  120       // Standard DPA button pressed => modify DPA Menu content
  121       userReg1 = DMENU_Item_Unimplemented_Standby | DMENU_Item_Unimplemented_UnbondAndRestart | DMENU_Item_Unimplemented_UnbondFactorySettingsAndRestart;
  122       _DpaMessage.PerNodeGetDpaMenuInfo_Response.FlagsExt = DMENU_Ext_Item_Unimplemented_Reset;
  123       return TRUE;
  124 
  125 #else // MODE == MODE_DPA_MENUS
  126       // Both buttons open the same default DPA Menu
  127 #endif
  128       break;
  129 
  130       // -------------------------------------------------
  131     case DpaEvent_Reset:
  132       // Called after module is reset
  133       // https://doc.iqrf.org/DpaTechGuide/pages/ResetEvent.html
  134     {
  135       static bit wasReset;
  136       // Setup GPIO for the 2nd button?
  137       if ( !wasReset )
  138       {
  139         wasReset = TRUE;
  140         // Pull-up to 2nd button
  141         BTN2_WPU = 1;
  142         // 2nd button is at input
  143         BTN2_TRIS = 1;
  144       }
  145       break;
  146     }
  147 
  148     // -------------------------------------------------
  149     case DpaEvent_DpaRequest:
  150       // Called to interpret DPA request for peripherals
  151       // https://doc.iqrf.org/DpaTechGuide/pages/EventDpaRequest.html
  152       if ( IsDpaEnumPeripheralsRequest() )
  153       {
  154         // -------------------------------------------------
  155         // Peripheral enumeration
  156         // https://doc.iqrf.org/DpaTechGuide/pages/enumerate-peripherals.html
  157 
  158         _DpaMessage.EnumPeripheralsAnswer.HWPID |= 0xBB0F;
  159         _DpaMessage.EnumPeripheralsAnswer.HWPIDver |= 0;
  160         return TRUE;
  161       }
  162 
  163       break;
  164   }
  165 
  166   return FALSE;
  167 }
  168 
  169 //############################################################################################
  170 // 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)
  171 #include "DPAcustomHandler.h"
  172 //############################################################################################