1 // *********************************************************************
    2 //   Custom DPA Handler code example - Using TMR6 MCU timer            *
    3 // *********************************************************************
    4 // Copyright (c) MICRORISC s.r.o.
    5 //
    6 // File:    $RCSfile: CustomDpaHandler-Timer.c,v $
    7 // Version: $Revision: 1.43 $
    8 // Date:    $Date: 2022/02/25 09:41:25 $
    9 //
   10 // Revision history:
   11 //   2022/02/24  Release for DPA 4.17
   12 //   2017/03/13  Release for DPA 3.00
   13 //   2016/09/12  Release for DPA 2.28
   14 //   2015/08/05  Release for DPA 2.20
   15 //   2014/10/31  Release for DPA 2.10
   16 //   2014/04/30  Release for DPA 2.00
   17 //
   18 // *********************************************************************
   19 
   20 // Online DPA documentation https://doc.iqrf.org/DpaTechGuide/
   21 
   22 // Default IQRF include (modify the path according to your setup)
   23 #include "IQRF.h"
   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 // This example initializes TMR6 (at Reset or Init event) and uses it to pulse LED at Idle event.
   31 // TMR6 if driven by the internal PIC RC oscillator. See CustomDpaHandler-TimerCalibrated.c for a more precise timer implementation.
   32 // This example works only at STD mode, not at LP mode
   33 
   34 // If next symbol is defined then initialize timer at Reset event so it could be used already during Reset events (custom un/bonding)
   35 //#define   EARLY_INITIALIZATION
   36 
   37 // Must be the 1st defined function in the source code in order to be placed at the correct FLASH location!
   38 //############################################################################################
   39 bit CustomDpaHandler()
   40 //############################################################################################
   41 {
   42   // Handler presence mark
   43   clrwdt();
   44 
   45   // Place for local static variables used only within CustomDpaHandler() among more events
   46   static uns8 tmrCounter;
   47 
   48   // Detect DPA event to handle
   49   switch ( GetDpaEvent() )
   50   {
   51     // -------------------------------------------------
   52     case DpaEvent_Interrupt:
   53       // Do an extra quick background interrupt work
   54       // ! 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.
   55       // ! 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.
   56       // ! 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.
   57       // ! Only global variables or local ones marked by static keyword can be used to allow reentrancy.
   58       // ! Make sure race condition does not occur when accessing those variables at other places.
   59       // ! 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.
   60       // ! Do not call any OS functions except setINDFx().
   61       // ! Do not use any OS variables especially for writing access.
   62       // ! 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.
   63 
   64       //  If TMR6 interrupt occurred
   65       if ( TMR6IF )
   66       {
   67         // Unmask interrupt
   68         TMR6IF = 0;
   69         // Decrement count
   70         if ( tmrCounter != 0 )
   71           tmrCounter--;
   72       }
   73 
   74       return Carry;
   75 
   76       // -------------------------------------------------
   77     case DpaEvent_Idle:
   78       // Do a quick background work when RF packet is not received
   79 
   80       if ( tmrCounter == 0 )
   81       {
   82         // Pulse LEDR every 1.0 s
   83         tmrCounter = 1000 / 10;
   84         pulseLEDG();
   85       }
   86 
   87       break;
   88 
   89       // -------------------------------------------------
   90 #ifdef EARLY_INITIALIZATION
   91     case DpaEvent_Reset:
   92       // Called after module is reset
   93       // Could be called more times, but initialize Timer only once
   94       if ( !TMR6IE )
   95 #else
   96     // -------------------------------------------------
   97     case DpaEvent_Init:
   98       // Do a one time initialization before main loop starts
   99 #endif
  100     {
  101       // Setup TMR6 to generate ticks on the background (ticks every 10ms)
  102       _PR6 = 250 - 1;
  103       // Prescaler 16, Postscaler 10, 16 * 10 * 250 = 40000 = 4MHz * 10ms
  104 #if defined( TR7xG )
  105       TMR6MD = 0;
  106       T6CON = 0b1.100.1001;
  107       //  Timer2/4/6 Clock Select bits = FOSC/4
  108       T6CLKCON |= 0b0000.0001;
  109 #else
  110       T6CON = 0b0.1001.1.10;
  111 #endif
  112 
  113       TMR6IE = TRUE;
  114     }
  115     break;
  116 
  117     // -------------------------------------------------
  118     case DpaEvent_AfterSleep:
  119       // Called on wake-up from sleep
  120       TMR6IE = TRUE;
  121       _TMR6ON = TRUE;
  122       break;
  123 
  124       // -------------------------------------------------
  125     case DpaEvent_BeforeSleep:
  126       // Called before going to sleep   (the same handling as DpaEvent_DisableInterrupts event)
  127       // To minimize the power consumption, no MCU pin must be left as a digital input without defined input level value.
  128       //   So, unused pins in given hardware should be set as outputs:
  129                                 // Generated by IQRF IDE according to the TR selection in a project
  130 #if defined(TR72D) || defined(TR72G)
  131                                 // TR pin C1 (MCU pin RA0): should be set as an output
  132       LATA.0 = 0;                   // Low level
  133       TRISA.0 = 0;                  // Output
  134 
  135                                 // TR pin C2 (MCU pin RC2): should be set as an output
  136       LATC.2 = 0;                   // Low level
  137       TRISC.2 = 0;                  // Output
  138 
  139                                 // TR pin C5 (MCU pins RA5, RB4 and RC6 connected in parallel):
  140                                 //   All MCU pins can be set as an input, but pin RB4 must be configured with internal pull-up (default activated).
  141       TRISA.5 = 1;                  // Input
  142       TRISB.4 = 1;                  // Input
  143       TRISC.6 = 1;                  // Input
  144 
  145                                 // TR pin C6 (MCU pin RC3): should be set as an output
  146       LATC.3 = 0;                   // Low level
  147       TRISC.3 = 0;                  // Output
  148 
  149                                 // TR pin C7 (MCU pin RC4): should be set as an output
  150       LATC.4 = 0;                   // Low level
  151       TRISC.4 = 0;                  // Output
  152 
  153                                 // TR pin C8 (MCU pins RC5 and RC7 connected in parallel):
  154                                 //   Only one MCU pin should be set as an output
  155       LATC.5 = 0;                   // Low level
  156       TRISC.5 = 0;                  // Output
  157       TRISC.7 = 1;                  // Input
  158 
  159 #elif defined(TR76D) || defined(TR76G)
  160                                 // TR pin Q14 (MCU pin RA0): should be set as an output
  161       LATA.0 = 0;                   // Low level
  162       TRISA.0 = 0;                  // Output
  163 
  164                                 // TR pin Q15 (MCU pin RC2): should be set as an output
  165       LATC.2 = 0;                   // Low level
  166       TRISC.2 = 0;                  // Output
  167 
  168                                 // TR pin Q4 (MCU pin RC6): should be set as an output
  169       LATC.6 = 0;                   // Low level
  170       TRISC.6 = 0;                  // Output
  171 
  172                                 // TR pin Q5 (MCU pin RC7): should be set as an output
  173       LATC.7 = 0;                   // Low level
  174       TRISC.7 = 0;                  // Output
  175 
  176                                 // TR pin Q6 (MCU pin RC3): should be set as an output
  177       LATC.3 = 0;                   // Low level
  178       TRISC.3 = 0;                  // Output
  179 
  180                                 // TR pin Q7 (MCU pin RC4): should be set as an output
  181       LATC.4 = 0;                   // Low level
  182       TRISC.4 = 0;                  // Output
  183 
  184                                 // TR pin Q8 (MCU pin RC5): should be set as an output
  185       LATC.5 = 0;                   // Low level
  186       TRISC.5 = 0;                  // Output
  187 
  188                                 // TR pin Q9 (MCU pin RA5): should be set as an output
  189       LATA.5 = 0;                   // Low level
  190       TRISA.5 = 0;                  // Output
  191 
  192                                 // TR LED pins Q10 and Q11 (MCU pins RB7 and RA2) are set as outputs by OS.
  193                                 // TR pin Q12 (MCU pin RB4) is set as an input with internal pull-up activated as default.
  194 #else
  195       #warning Unsupported TR module selected.Modify the pin setting.
  196 #endif
  197         // -------------------------------------------------
  198     case DpaEvent_DisableInterrupts:
  199       // Called when device needs all hardware interrupts to be disabled (before Reset, Restart, LoadCode, Remove bond, and Run RFPGM)
  200       // Must not use TMR6 any more
  201       _TMR6ON = FALSE;
  202       TMR6IE = FALSE;
  203       break;
  204   }
  205 
  206   return FALSE;
  207 }
  208 //############################################################################################
  209 // 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)
  210 #include "DPAcustomHandler.h"
  211 //############################################################################################