1 // *********************************************************************
    2 //   Custom DPA Handler - Beaming example                              *
    3 // *********************************************************************
    4 // Copyright (c) MICRORISC s.r.o.
    5 //
    6 // File:    $RCSfile: CustomDpaHandler-SensorBeaming.c,v $
    7 // Version: $Revision: 1.11 $
    8 // Date:    $Date: 2021/05/07 11:09:28 $
    9 //
   10 // Revision history:
   11 //   2020/09/03  Release for DPA 4.15
   12 //
   13 // *********************************************************************
   14 
   15 // Online DPA documentation https://doc.iqrf.org/DpaTechGuide/
   16 
   17 /*
   18 * This is public example of the beaming sensor code.
   19 * The actual beamed quantities' values are fake. Please see the code below.
   20 * After the button is pressed for a longer time the LEDR pulses and data are beamed. The device then goes to sleep.
   21 * The device wakes up by pressing the button which is indicated by LEDG pulse.
   22 */
   23 
   24 // Default IQRF include (modify the path according to your setup)
   25 #include "IQRF.h"
   26 
   27 // Default DPA header (modify the path according to your setup)
   28 #include "DPA.h"
   29 // Default Custom DPA Handler header (modify the path according to your setup)
   30 #include "DPAcustomHandler.h"
   31 // IQRF standards header (modify the path according to your setup)
   32 #include "standard/IQRFstandard.h"
   33 #include "standard/IQRF_HWPID.h"
   34 
   35 // This HWPID
   36 #define _HWPID_             0x123F
   37 
   38 // Define to return sensors in error
   39 //#define SENSOR_ERRORS
   40 
   41 // Must be the 1st defined function in the source code in order to be placed at the correct FLASH location!
   42 //############################################################################################
   43 bit CustomDpaHandler()
   44 //############################################################################################
   45 {
   46 #pragma updateBank default = UserBank_01
   47 
   48   // Handler presence mark
   49   clrwdt();
   50 
   51   // Detect DPA event to handle (unused event handlers can be commented out or even deleted)
   52   switch ( GetDpaEvent() )
   53   {
   54     // -------------------------------------------------
   55     case DpaEvent_Interrupt:
   56       // Do an extra quick background interrupt work
   57       return Carry;
   58 
   59       // -------------------------------------------------
   60     case DpaEvent_Idle:
   61       // Do a quick background work when RF packet is not received
   62 
   63     {
   64       // To detect long button press
   65       static uns8 buttonCnt;
   66 
   67       if ( !buttonPressed )
   68         buttonCnt = 0;
   69       else
   70       {
   71         // Note: when run at LP mode, than the press time must be adjusted for shorter counts that even depends on LPtoutRF value
   72         if ( ++buttonCnt == 0 )
   73         {
   74           // Indicate button was pressed for the longer time and then wait for its release
   75           setLEDR();
   76           do
   77           {
   78             clrwdt();
   79           } while ( buttonPressed );
   80           stopLEDR();
   81 
   82           // Prepare off-line sensor packet
   83 
   84           // No DPA Params used
   85           _DpaParams = 0;
   86 
   87           // Beaming is broadcast (could be unicast too)
   88           _NADR = BROADCAST_ADDRESS;
   89           _NADRhigh = 0;
   90 
   91           // Prepare sensor packet type and quantity data
   92 
   93           _PNUM = PNUM_STD_SENSORS;
   94           _PCMD = PCMD_STD_SENSORS_READ_TYPES_AND_FRC_VALUES | RESPONSE_FLAG;
   95           // HW profile ID
   96           _HWPID = _HWPID_;
   97 
   98           { // 1st sensor/quantity
   99             // Fake "living" temperature value = NodeAddress + [0-15]/16;
  100             _DpaMessage.Request.PData[0] = STD_SENSOR_TYPE_TEMPERATURE;
  101             shadowDef uns16 temperature @ ( &_DpaMessage.Request.PData[1] );
  102 #ifndef SENSOR_ERRORS
  103             temperature = (uns16)ntwADDR * 16;
  104             temperature |= ( Random.low8 & ( 16 - 1 ) );
  105             temperature |= 0x8000;
  106 #else
  107             temperature = FRC_STD_FRC_ERROR_VALUE;
  108 #endif
  109             // Length of the data inside DPA Request message
  110             _DpaDataLength = sizeof( uns8 ) + sizeof( uns16 );
  111           }
  112 
  113           { // Optional 2nd sensor/quantity
  114             // Fake "living" humidity value = NodeAddress + [0-1]/2;
  115             _DpaMessage.Request.PData[3] = STD_SENSOR_TYPE_HUMIDITY;
  116 #ifndef SENSOR_ERRORS
  117             _DpaMessage.Request.PData[4] = 4 + ( ntwADDR & 0x3F ) * 2;
  118             _DpaMessage.Request.PData[4] |= Random.high8 & 0x01;
  119 #else
  120             _DpaMessage.Request.PData[4] = FRC_STD_FRC_ERROR_VALUE;
  121 #endif
  122             // Length of the data inside DPA Request message
  123             _DpaDataLength += sizeof( uns8 ) + sizeof( uns8 );
  124           }
  125 
  126           { // Optional 3rd sensor/quantity
  127             // Fake CO2 value
  128             _DpaMessage.Request.PData[5] = STD_SENSOR_TYPE_CO2;
  129             shadowDef uns16 co2 @ ( &_DpaMessage.Request.PData[6] );
  130 #ifndef SENSOR_ERRORS
  131             co2 = 2345 + 4;
  132 #else
  133             co2 = FRC_STD_FRC_ERROR_VALUE;
  134 #endif
  135             // Length of the data inside DPA Request message
  136             _DpaDataLength += sizeof( uns8 ) + sizeof( uns16 );
  137           }
  138 
  139           { // Optional 4th sensor/quantity
  140             // Fake Binary30
  141             _DpaMessage.Request.PData[8] = STD_SENSOR_TYPE_BINARYDATA30;
  142             shadowDef uns32 bin30 @ ( &_DpaMessage.Request.PData[9] );
  143 #ifndef SENSOR_ERRORS
  144 #if !defined( __CC5XFREE__ ) // CC5X free edition does not support 32bit assignment
  145             bin30 = 0x3456789A + 4;
  146 #else
  147             bin30.low16 = ( 0x3456789A + 4 ) & 0xFfFf;
  148             bin30.high16 = ( 0x3456789A + 4 ) >> 16;
  149 #endif
  150 #else
  151 #if !defined( __CC5XFREE__ ) // CC5X free edition does not support 32bit assignment
  152             bin30 = FRC_STD_FRC_ERROR_VALUE;
  153 #else
  154             bin30.low16 = FRC_STD_FRC_ERROR_VALUE;
  155             bin30.high16 = 0;
  156 #endif
  157 #endif
  158             // Length of the data inside DPA Request message
  159             _DpaDataLength += sizeof( uns8 ) + sizeof( uns32 );
  160           }
  161 
  162           { // Optional 5th sensor/quantity
  163             // Fake Binary7
  164             _DpaMessage.Request.PData[13] = STD_SENSOR_TYPE_BINARYDATA7;
  165 #ifndef SENSOR_ERRORS
  166             _DpaMessage.Request.PData[14] = ( ntwADDR & 0x7F ) + 4;
  167 #else
  168             _DpaMessage.Request.PData[14] = FRC_STD_FRC_ERROR_VALUE;
  169 #endif
  170             // Length of the data inside DPA Request message
  171             _DpaDataLength += sizeof( uns8 ) + sizeof( uns8 );
  172           }
  173 
  174           // Do simplified LBT
  175           uns8 loop = 3;
  176           do
  177           {
  178             if ( !checkRF( DpaApiReadConfigByte( CFGIND_RXFILTER ) + 10 ) )
  179               break;
  180 
  181             // Do some wait (better to do a random time sleep)
  182             waitMS( 5 );
  183           } while ( --loop != 0 );
  184 
  185           // Force not routed packet to be sent from N by DPA API
  186           NonroutedRfTxDpaPacket = TRUE;
  187 
  188           // TX DPA message with zero DPA Value and asynchronous
  189           // Note: Use DpaValue = 0x01 to indicate asynchronous i.e. non-regular beaming
  190           DpaApiRfTxDpaPacket( 0 /*DpaValue*/, 0 );
  191 
  192           // Now go to endless sleep with a button wakeup
  193           _PNUM = PNUM_OS;
  194           _PCMD = CMD_OS_SLEEP;
  195           _DpaDataLength = sizeof( _DpaMessage.PerOSSleep_Request );
  196           // Wake up on PIN change, LEDG flash after wake up
  197           _DpaMessage.PerOSSleep_Request.Time = 0x0000;
  198           _DpaMessage.PerOSSleep_Request.Control = 0b101;
  199           // Perform local DPA Request
  200           DpaApiLocalRequest();
  201           }
  202         }
  203       }
  204     break;
  205 
  206     // -------------------------------------------------
  207     case DpaEvent_DpaRequest:
  208       // Called to interpret DPA request for peripherals
  209       if ( IsDpaEnumPeripheralsRequest() )
  210       {
  211         // -------------------------------------------------
  212         // Peripheral enumeration
  213         _DpaMessage.EnumPeripheralsAnswer.HWPID |= _HWPID_;
  214         _DpaMessage.EnumPeripheralsAnswer.HWPIDver |= 0;
  215 
  216 DpaHandleReturnTRUE:
  217         return TRUE;
  218     }
  219 
  220       break;
  221   }
  222 
  223 DpaHandleReturnFALSE:
  224   return FALSE;
  225 }
  226 
  227 //############################################################################################
  228 // 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)
  229 #include "DPAcustomHandler.h"
  230 //############################################################################################