1 // *********************************************************************
    2 //   Custom DPA Handler code template                                  *
    3 // *********************************************************************
    4 // Copyright (c) MICRORISC s.r.o.
    5 //
    6 // File:    $RCSfile: CustomDpaHandler-ButtonReconnect.c,v $
    7 // Version: $Revision: 1.1 $
    8 // Date:    $Date: 2026/05/14 19:57:58 $
    9 //
   10 // Revision history:
   11 //   2025/05/30  Release for DPA 4.33
   12 //
   13 // *********************************************************************
   14 
   15 // This example uses the CLC to connect pin RA0 to RB4.Therefore, a button connected to RA0 behaves like a standard DPA button connected to RB4.
   16 // Note that RB4 is an open-drain digital output with a weak pull-up resistor, which allows the CLC to function properly.
   17 // Therefore (open-drain + pull-up), pressing the original button connected to RB4 will not cause a short circuit when the new button connected to RA0 is not pressed.
   18 
   19 // Default IQRF include (modify the path according to your setup)
   20 #include "IQRF.h"
   21 
   22 // Default DPA header (modify the path according to your setup)
   23 #include "DPA.h"
   24 // Default Custom DPA Handler header (modify the path according to your setup)
   25 #include "DPAcustomHandler.h"
   26 
   27 //############################################################################################
   28 // https://doc.iqrf.org/DpaTechGuide/pages/custom-dpa-handler.html
   29 bit CustomDpaHandler()
   30 //############################################################################################
   31 {
   32   // Handler presence mark
   33   clrwdt();
   34 
   35   // Detect DPA event to handle (unused event handlers can be commented out or even deleted)
   36   switch ( GetDpaEvent() )
   37   {
   38     // -------------------------------------------------
   39     case DpaEvent_Interrupt:
   40       // Do an extra quick background interrupt work
   41       // ! 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.
   42       // ! 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.
   43       // ! 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.
   44       // ! Only global variables or local ones marked by static keyword can be used to allow reentrancy.
   45       // ! Make sure race condition does not occur when accessing those variables at other places.
   46       // ! 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.
   47       // ! Do not call any OS functions except setINDFx().
   48       // ! Do not use any OS variables especially for writing access.
   49       // ! 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.
   50       // https://doc.iqrf.org/DpaTechGuide/pages/EventInterrupt.html
   51       return Carry;
   52 
   53       // -------------------------------------------------
   54     case DpaEvent_Reset:
   55       // Called after module is reset
   56       // https://doc.iqrf.org/DpaTechGuide/pages/ResetEvent.html
   57     {
   58       static bit wasReset;
   59       if ( !wasReset )
   60       {
   61         wasReset = TRUE;
   62 
   63         // CLC4 connects RA0-input to RB4-output
   64 
   65         // Enable CLC4
   66         CLC4MD = 0;
   67 
   68         // RB4 is open drain
   69         ODCONB.4 = 0;
   70         // Pull-up at RB4
   71         WPUB.4 = 0;
   72         // Pull-up at RA0
   73         WPUA.0 = 1;
   74         // RB4 is digital output
   75         TRISB.4 = 0;
   76         // RA0 is digital input
   77         TRISA.0 = 1;
   78 
   79         // LC4G1POL not_inverted; LC4G2POL not_inverted; LC4G3POL not_inverted; LC4G4POL not_inverted; LC4POL not_inverted;
   80         CLC4POL = 0x00;
   81         // LC4D1S CLCIN0 (CLCIN0PPS);
   82         CLC4SEL0 = 0x00;
   83         // LC4D2S CLCIN0 (CLCIN0PPS);
   84         CLC4SEL1 = 0x00;
   85         // LC4D3S CLCIN0 (CLCIN0PPS);
   86         CLC4SEL2 = 0x00;
   87         // LC4D4S CLCIN0 (CLCIN0PPS);
   88         CLC4SEL3 = 0x00;
   89         // LC4G1D3N disabled; LC4G1D2N disabled; LC4G1D4N disabled; LC4G1D1T enabled; LC4G1D3T disabled; LC4G1D2T disabled; LC4G1D4T disabled; LC4G1D1N disabled;
   90         CLC4GLS0 = 0x02;
   91         // LC4G2D2N disabled; LC4G2D1N disabled; LC4G2D4N disabled; LC4G2D3N disabled; LC4G2D2T disabled; LC4G2D1T enabled; LC4G2D4T disabled; LC4G2D3T disabled;
   92         CLC4GLS1 = 0x02;
   93         // LC4G3D1N disabled; LC4G3D2N disabled; LC4G3D3N disabled; LC4G3D4N disabled; LC4G3D1T enabled; LC4G3D2T disabled; LC4G3D3T disabled; LC4G3D4T disabled;
   94         CLC4GLS2 = 0x02;
   95         // LC4G4D1N disabled; LC4G4D2N disabled; LC4G4D3N disabled; LC4G4D4N disabled; LC4G4D1T enabled; LC4G4D2T disabled; LC4G4D3T disabled; LC4G4D4T disabled;
   96         CLC4GLS3 = 0x02;
   97         // LC4EN enabled; INTN disabled; INTP disabled; MODE 4-input AND;
   98         CLC4CON = 0x82;
   99 
  100         unlockPPS();
  101         // CLCIN0 = RA0
  102         CLCIN0PPS = 0b00.000.000;
  103         // CLC4OUT = RB4
  104         RB4PPS = 0x04;
  105         lockPPS();
  106       }
  107       break;
  108     }
  109 
  110     // -------------------------------------------------
  111     case DpaEvent_DpaRequest:
  112       // Called to interpret DPA request for peripherals
  113       // https://doc.iqrf.org/DpaTechGuide/pages/EventDpaRequest.html
  114       if ( IsDpaEnumPeripheralsRequest() )
  115       {
  116         // -------------------------------------------------
  117         // Peripheral enumeration
  118         // https://doc.iqrf.org/DpaTechGuide/pages/enumerate-peripherals.html
  119 
  120         _DpaMessage.EnumPeripheralsAnswer.HWPID |= 0xB00F;
  121         _DpaMessage.EnumPeripheralsAnswer.HWPIDver |= 0;
  122 
  123         return TRUE;
  124       }
  125 
  126       break;
  127   }
  128 
  129   return FALSE;
  130 }
  131 
  132 //############################################################################################
  133 // 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)
  134 #include "DPAcustomHandler.h"
  135 //############################################################################################