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 //############################################################################################