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