1 // **************************************************************************
    2 //   Custom DPA Handler code example - Using SPI MCU peripheral by OS calls *
    3 // **************************************************************************
    4 // Copyright (c) MICRORISC s.r.o.
    5 //
    6 // File:    $RCSfile: CustomDpaHandler-SPI.c,v $
    7 // Version: $Revision: 1.35 $
    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 //   2015/08/05  Release for DPA 2.20
   14 //   2014/10/31  Release for DPA 2.10
   15 //   2014/04/30  Release for DPA 2.00
   16 //
   17 // **************************************************************************
   18 
   19 // Online DPA documentation https://doc.iqrf.org/DpaTechGuide/
   20 
   21 // Default IQRF include (modify the path according to your setup)
   22 #include "IQRF.h"
   23 
   24 // Default DPA header (modify the path according to your setup)
   25 #include "DPA.h"
   26 // Default Custom DPA Handler header (modify the path according to your setup)
   27 #include "DPAcustomHandler.h"
   28 
   29 // This example shows how to connect custom peripheral with MCU SPI HW peripheral controlled by IQRF OS
   30 
   31 // Must be the 1st defined function in the source code in order to be placed at the correct FLASH location!
   32 //############################################################################################
   33 bit CustomDpaHandler()
   34 //############################################################################################
   35 {
   36   // Handler presence mark
   37   clrwdt();
   38 
   39   // Detect DPA event to handle (unused event handlers can be commented out or even deleted)
   40   switch ( GetDpaEvent() )
   41   {
   42     // -------------------------------------------------
   43     case DpaEvent_Interrupt:
   44       // Do an extra quick background interrupt work
   45       // ! 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.
   46       // ! 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.
   47       // ! 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.
   48       // ! Only global variables or local ones marked by static keyword can be used to allow reentrancy.
   49       // ! Make sure race condition does not occur when accessing those variables at other places.
   50       // ! 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.
   51       // ! Do not call any OS functions except setINDFx().
   52       // ! Do not use any OS variables especially for writing access.
   53       // ! 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.
   54 
   55 DpaHandleReturnTRUE:
   56       return TRUE;
   57 
   58       // -------------------------------------------------
   59     case DpaEvent_Idle:
   60       // Do a quick background work when RF packet is not received
   61 
   62       // Is there anything at SPI received?
   63       if ( !getStatusSPI() && _SPIRX )
   64       {
   65         if ( _SPICRCok )
   66         {
   67           stopSPI();
   68 
   69           // PeripheralRam[0] stores length of received data
   70           PeripheralRam[0] = SPIpacketLength;
   71 
   72           // Limit to max. length of Peripheral RAM
   73           if ( PeripheralRam[0] > sizeof( PeripheralRam ) - 1 )
   74             PeripheralRam[0] = sizeof( PeripheralRam ) - 1;
   75 
   76           // Store data to PeripheralRam[1...]
   77           copyMemoryBlock( bufferCOM, PeripheralRam + 1, PeripheralRam[0] );
   78 
   79           // Now data can be read by
   80           // 1. reading from Peripheral RAM
   81           // 2. by user peripheral _Pnum=PNUM_USER and _PCMD=1
   82         }
   83 
   84         startSPI( 0 );
   85       }
   86       break;
   87 
   88       // -------------------------------------------------
   89     case DpaEvent_Reset:
   90     {
   91       // Called after module is reset
   92       //goto DpaHandleReturnTRUE; // return TRUE only if you handle node bonding/unbonding
   93       static onlyOnce;
   94 
   95       if ( !onlyOnce )
   96       {
   97         onlyOnce = TRUE;
   98 
   99         // Enable SPI after reset
  100         enableSPI();
  101         bufferCOM[0] = 'R';
  102         bufferCOM[1] = 'e';
  103         bufferCOM[2] = 's';
  104         bufferCOM[3] = 'e';
  105         bufferCOM[4] = 't';
  106         startSPI( 5 );
  107       }
  108       break;
  109     }
  110 
  111     // -------------------------------------------------
  112     case DpaEvent_Init:
  113       // Do a one time initialization before main loop starts
  114 
  115       PeripheralRam[0] = 0;
  116       // SPI stays enabled after reset event
  117       bufferCOM[0] = 'I';
  118       bufferCOM[1] = 'n';
  119       bufferCOM[2] = 'i';
  120       bufferCOM[3] = 't';
  121       startSPI( 4 );
  122       break;
  123 
  124       // -------------------------------------------------
  125     case DpaEvent_DpaRequest:
  126       // Called to interpret DPA request for peripherals
  127       // -------------------------------------------------
  128       // Peripheral enumeration
  129       if ( IsDpaEnumPeripheralsRequest() )
  130       {
  131         _DpaMessage.EnumPeripheralsAnswer.UserPerNr |=  1;
  132         FlagUserPer( _DpaMessage.EnumPeripheralsAnswer.UserPer, PNUM_USER + 0 );
  133         _DpaMessage.EnumPeripheralsAnswer.HWPID |= 0x000F;
  134         _DpaMessage.EnumPeripheralsAnswer.HWPIDver |= 0;
  135 
  136         goto DpaHandleReturnTRUE;
  137       }
  138       // -------------------------------------------------
  139       // Get information about peripheral
  140       else if ( IsDpaPeripheralInfoRequest() )
  141       {
  142         if ( _PNUM == PNUM_USER + 0 )
  143         {
  144           _DpaMessage.PeripheralInfoAnswer.PerT = PERIPHERAL_TYPE_USER_AREA;
  145           _DpaMessage.PeripheralInfoAnswer.PerTE = PERIPHERAL_TYPE_EXTENDED_READ_WRITE;
  146           _DpaMessage.PeripheralInfoAnswer.Par1 = 0;
  147           _DpaMessage.PeripheralInfoAnswer.Par2 = 0;
  148           goto DpaHandleReturnTRUE;
  149         }
  150 
  151         break;
  152       }
  153       // -------------------------------------------------
  154       else
  155       {
  156         // Handle peripheral command
  157         if ( _PNUM == PNUM_USER + 0 )
  158         {
  159           switch ( _PCMD )
  160           {
  161             case 0:
  162               // Write one byte from PData to SPI
  163               if ( _DpaDataLength != 1 )
  164                 goto Error_FAIL;
  165 
  166               bufferCOM[0] = 'C';
  167               bufferCOM[1] = 'm';
  168               bufferCOM[2] = 'd';
  169               bufferCOM[3] = '=';
  170               bufferCOM[4] = _DpaMessage.Request.PData[0];
  171               // SPI is enabled from reset event
  172               startSPI( 5 );
  173               _DpaDataLength = 0;
  174               goto DpaHandleReturnTRUE;
  175 
  176             case 1:
  177               if ( _DpaDataLength != 0 )
  178                 goto Error_FAIL;
  179 
  180               // Read data originally read from SPI
  181               copyMemoryBlock( PeripheralRam + 1, _DpaMessage.Response.PData, _DpaDataLength = PeripheralRam[0] );
  182               goto DpaHandleReturnTRUE;
  183 
  184             default:;
  185               // For simplicity reasons we report only one type of error
  186 Error_FAIL:
  187               DpaApiReturnPeripheralError( ERROR_FAIL );
  188           }
  189         }
  190       }
  191 
  192       break;
  193   }
  194 
  195 DpaHandleReturnFALSE:
  196   return FALSE;
  197 }
  198 //############################################################################################
  199 // 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)
  200 #include "DPAcustomHandler.h"
  201 //############################################################################################