1 // ***********************************************************************************
    2 //   Custom DPA Handler code example - User peripheral implementation - i2c          *
    3 // ***********************************************************************************
    4 // Copyright (c) MICRORISC s.r.o.
    5 //
    6 // File:    $RCSfile: CustomDpaHandler-UserPeripheral-i2c.c,v $
    7 // Version: $Revision: 1.23 $
    8 // Date:    $Date: 2021/08/18 20:43:06 $
    9 //
   10 // Revision history:
   11 //   2021/08/18  Release for DPA 4.16
   12 //   2020/01/02  Release for DPA 4.11
   13 //   2017/03/13  Release for DPA 3.00
   14 //   2015/12/01  Release for DPA 2.24
   15 //   2015/08/05  Release for DPA 2.20
   16 //
   17 // *********************************************************************
   18 
   19 // Online DPA documentation https://doc.iqrf.org/DpaTechGuide/
   20 
   21 // This example implements the user peripheral reading from MCP9802 at DDC-SE-01
   22 // PNUM = 0x20 and PCMD = 0 returns 2 bytes with result read from MCP9802
   23 // Based on example DDC-SE-01-i2c.c
   24 
   25 // Default IQRF include (modify the path according to your setup)
   26 #include "IQRF.h"
   27 
   28 // Default DPA header (modify the path according to your setup)
   29 #include "DPA.h"
   30 // Default Custom DPA Handler header (modify the path according to your setup)
   31 #include "DPAcustomHandler.h"
   32 
   33 //############################################################################################
   34 
   35 // I2C SCL frequency [Hz]
   36 #define I2Cfrequency        50000
   37 
   38 #define I2C_ADR             0b10010110
   39 #define PWR_SENSOR_TRIS     TRISC.7
   40 #define PWR_SENSOR_IO       LATC.7
   41 
   42 // Must be the 1st defined function in the source code in order to be placed at the correct FLASH location!
   43 //############################################################################################
   44 bit CustomDpaHandler()
   45 //############################################################################################
   46 {
   47   // Handler presence mark
   48   clrwdt();
   49 
   50   // Detect DPA event to handle
   51   switch ( GetDpaEvent() )
   52   {
   53     // -------------------------------------------------
   54     case DpaEvent_Interrupt:
   55       // Do an extra quick background interrupt work
   56       // ! 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.
   57       // ! 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.
   58       // ! 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.
   59       // ! Only global variables or local ones marked by static keyword can be used to allow reentrancy.
   60       // ! Make sure race condition does not occur when accessing those variables at other places.
   61       // ! 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.
   62       // ! Do not call any OS functions except setINDFx().
   63       // ! Do not use any OS variables especially for writing access.
   64       // ! 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.
   65 
   66 DpaHandleReturnTRUE:
   67       return TRUE;
   68 
   69       // -------------------------------------------------
   70     case DpaEvent_Init:
   71       // Do a one time initialization before main loop starts
   72     case DpaEvent_AfterSleep:
   73       // Called after woken up after sleep
   74 
   75       PORTC = 0x80;                       // port
   76 
   77       PWR_SENSOR_TRIS = 0;                // sensor power as output (SIM C8)
   78       TRISC.5 = 1;                        // shared with SIM C8
   79 
   80       TRISA.5 = 1;                        // sensor ALERT as input (SIM C5)
   81       TRISB.4 = 1;                        // shared with SIM C5
   82       TRISC.6 = 1;                        // shared with SIM C5
   83       DpaApiI2Cinit( I2CcomputeFrequency( I2Cfrequency ) );
   84 
   85       break;
   86 
   87       // -------------------------------------------------
   88     case DpaEvent_BeforeSleep:
   89       // Called before going to sleep
   90 
   91       DpaApiI2Cshutdown();
   92       break;
   93 
   94       // -------------------------------------------------
   95     case DpaEvent_DpaRequest:
   96       // Called to interpret DPA request for peripherals
   97       // -------------------------------------------------
   98       // Peripheral enumeration
   99       if ( IsDpaEnumPeripheralsRequest() )
  100       {
  101         // We implement 1 user peripheral
  102         _DpaMessage.EnumPeripheralsAnswer.UserPerNr = 1;
  103         FlagUserPer( _DpaMessage.EnumPeripheralsAnswer.UserPer, PNUM_USER + 0 );
  104         _DpaMessage.EnumPeripheralsAnswer.HWPID = 0x000F;
  105         _DpaMessage.EnumPeripheralsAnswer.HWPIDver = 0xAbCd;
  106 
  107         goto DpaHandleReturnTRUE;
  108       }
  109       // -------------------------------------------------
  110       // Get information about peripheral
  111       else if ( IsDpaPeripheralInfoRequest() )
  112       {
  113         if ( _PNUM == PNUM_USER + 0 )
  114         {
  115           _DpaMessage.PeripheralInfoAnswer.PerT = PERIPHERAL_TYPE_USER_AREA;
  116           _DpaMessage.PeripheralInfoAnswer.PerTE = PERIPHERAL_TYPE_EXTENDED_READ;
  117           goto DpaHandleReturnTRUE;
  118         }
  119 
  120         break;
  121       }
  122       // -------------------------------------------------
  123       else
  124       {
  125         // Handle peripheral command
  126         if ( _PNUM == PNUM_USER + 0 )
  127         {
  128           // Check command
  129           switch ( _PCMD )
  130           {
  131             case 0:
  132               // -------------------------------------------------
  133               // Read temperature
  134               if ( _DpaDataLength != 0 )
  135                 DpaApiReturnPeripheralError( ERROR_DATA_LEN );
  136 
  137               _DpaApiI2Cstart( I2C_ADR );                 // MCP9802 address
  138               _DpaApiI2Cwrite( 0x01 );                    // pointer: 1 = configuration register
  139               _DpaApiI2Cwrite( 0x60 );                    // configuration: 12-bit ADC
  140               _DpaApiI2Cstop();
  141 
  142               _DpaApiI2Cstart( I2C_ADR );                 // MCP9802 address
  143               _DpaApiI2Cwrite( 0 );                       // pointer: 0 = temperature
  144               _DpaApiI2Cstop();
  145 
  146               _DpaApiI2Cstart( I2C_ADR | 1 );             // MCP9802 address + read
  147               uns16 temperature  @ _DpaMessage.Response.PData;
  148               temperature.high8 = _DpaApiI2Cread( TRUE );  // store the result
  149               temperature.low8 = _DpaApiI2Cread( FALSE );
  150               _DpaApiI2Cstop();
  151 
  152               _DpaDataLength = sizeof( temperature );
  153               goto DpaHandleReturnTRUE;
  154 
  155             default:
  156               // -------------------------------------------------
  157               // Invalid command
  158               DpaApiReturnPeripheralError( ERROR_PCMD );
  159           }
  160         }
  161       }
  162   }
  163 
  164   return FALSE;
  165 }
  166 
  167 //############################################################################################
  168 // 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)
  169 #include "DPAcustomHandler.h"
  170 //############################################################################################