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