1 // *********************************************************************
    2 //   Custom DPA Handler - FRC  aggregation example                     *
    3 // *********************************************************************
    4 // Copyright (c) MICRORISC s.r.o.
    5 //
    6 // File:    $RCSfile: CustomDpaHandler-FrcAggregation.c,v $
    7 // Version: $Revision: 1.20 $
    8 // Date:    $Date: 2022/02/25 09:41:25 $
    9 //
   10 // Revision history:
   11 //   2022/02/24  Release for DPA 4.17
   12 //   2021/08/20  Release for DPA 4.16
   13 //
   14 // *********************************************************************
   15 
   16 // Online DPA documentation https://doc.iqrf.org/DpaTechGuide/
   17 
   18 /*
   19 * This example shows how to aggregate FRC values in the discovered Node from other Nodes.
   20 * The example handles custom FRC 1 byte command FRC_USER_BYTE_FROM (0xC0) and
   21 * returns FRC values from 0x82 to 0x84 for Nodes #2 to #4 respectively.
   22 * When trying this example, please make sure Nodes #2 to #4 are bonded to the network, but switched off.
   23 * Also this example must be loaded into another but discovered Node, e.g. to the Node #1.
   24 *
   25 * See advance example CustomDpaHandler-BeamingAggregation.c for the beamed IQRF Standard Sensor data aggregation.
   26 
   27 * Important: The feature "FRC Aggregation" must be set from MICRORISC (i.e. the TR transceiver manufacturer) otherwise the aggregation will not work.
   28 */
   29 
   30 // Default IQRF include (modify the path according to your setup)
   31 #include "IQRF.h"
   32 
   33 // Default DPA header (modify the path according to your setup)
   34 #include "DPA.h"
   35 // Default Custom DPA Handler header (modify the path according to your setup)
   36 #include "DPAcustomHandler.h"
   37 
   38 // Must be the 1st defined function in the source code in order to be placed at the correct FLASH location!
   39 //############################################################################################
   40 bit CustomDpaHandler()
   41 //############################################################################################
   42 {
   43 #pragma updateBank default = UserBank_01
   44 
   45   // Handler presence mark
   46   clrwdt();
   47 
   48   // Detect DPA event to handle (unused event handlers can be commented out or even deleted)
   49   switch ( GetDpaEvent() )
   50   {
   51     // -------------------------------------------------
   52     case DpaEvent_Interrupt:
   53       // Do an extra quick background interrupt work
   54       return Carry;
   55 
   56       // -------------------------------------------------
   57     case DpaEvent_FrcValue:
   58       // Called to get FRC value
   59 
   60       // Is this the 1 Byte FRC command we handle?
   61       if ( PCMD == FRC_USER_BYTE_FROM )
   62       {
   63         // Clear the FRC aggregation buffer
   64         clearBufferINFO();
   65         // Set the pointer to the beginning of the aggregation buffer
   66         setFSR0( _FSR_INFO );
   67         // Move pointer to the place for the 1st addressed node
   68         FSR0 += sizeof( uns8 );
   69         // Variable for the "Node" loop
   70         uns8 node = 0;
   71         do {
   72           // Check whether the current node was addressed by FRC.
   73           addressBitmap( ++node );
   74           // Prepare the pointer to beginning of the bitmap of FRC addressed Nodes
   75 #if &bufferRF[0] != &AddressedNodesBeforeResponseFRC[0]
   76           setFSR1( _FSR_RF );   // Optimize
   77 #else
   78           FSR1 = &AddressedNodesBeforeResponseFRC[0];
   79 #endif
   80           // Move the pointer to the bitmap byte, where the bit for the checked node is
   81           FSR1L += bitmapByteIndex; // Note: FSR0L will not overflow
   82           // Is Node addressed by the FRC command? (i.e. is the bit set?)
   83 
   84           // IQRF OS bit indicating selective FRC (bit.0 at the 1st byte behind AddressedNodesBeforeResponseFRC)
   85           bit isSelectiveFrc @ AddressedNodesBeforeResponseFRC[sizeof( AddressedNodesBeforeResponseFRC )].0;
   86           // W = bitmap byte
   87           W = *FSR1;
   88           if ( !isSelectiveFrc )  // Note: must not modify W
   89             W = 0xFF; // Not selective FRC => all nodes are selected
   90           // Is Nodes selected?
   91           if ( ( W & bitmapBitMask ) != 0 )
   92           {
   93             // Is the addressed node one of the Nodes (2-4) we handle in this example?
   94             // If so, store its (fake) aggregated FRC value (0x82-0x84) into the aggregation buffer(INFO).
   95             // Normally the formerly obtained and currently aggregated FRC data will be stored in the (external) memory.
   96             switch ( node )
   97             {
   98               case 2:
   99                 setINDF0( 0x82 );
  100                 break;
  101 
  102               case 3:
  103                 setINDF0( 0x83 );
  104                 break;
  105 
  106               case 4:
  107                 setINDF0( 0x84 );
  108                 break;
  109             }
  110 
  111             // Move pointer to the next FRC value byte in the aggregation buffer
  112             FSR0 += sizeof( uns8 );
  113           }
  114           // Loop until
  115         } while (
  116           // Aggregation buffer is not full/over
  117           FSR0L < ( &bufferINFO[sizeof( bufferINFO )] & 0xFF ) &&
  118           // and not all node addresses were checked
  119           node != MAX_ADDRESS );
  120 
  121         // Start FRC value aggregation.
  122         // Important:
  123         //  This node must be discovered and the feature "FRC Aggregation" must be set from MICRORISC (i.e. the TR transceiver manufacturer)
  124         //  otherwise the aggregation will not work.
  125         DpaApiAggregateFrc();
  126       }
  127       break;
  128 
  129       // -------------------------------------------------
  130     case DpaEvent_FrcResponseTime:
  131       // Called to get FRC response time
  132 
  133       if ( DataOutBeforeResponseFRC[0] == FRC_USER_BYTE_FROM )
  134         responseFRCvalue = _FRC_RESPONSE_TIME_40_MS;
  135 
  136       break;
  137 
  138       // -------------------------------------------------
  139     case DpaEvent_DpaRequest:
  140       // Called to interpret DPA request for peripherals
  141       if ( IsDpaEnumPeripheralsRequest() )
  142       {
  143         // -------------------------------------------------
  144         // Peripheral enumeration
  145         _DpaMessage.EnumPeripheralsAnswer.HWPID |= 0x456F;
  146         return TRUE;
  147       }
  148 
  149       break;
  150   }
  151 
  152   return FALSE;
  153 }
  154 
  155 //############################################################################################
  156 // 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)
  157 #include "DPAcustomHandler.h"
  158 //############################################################################################