1 // ******************************************************************************* 2 // Custom DPA Handler code example - Demonstrates using of custom FRC commands * 3 // ******************************************************************************* 4 // Copyright (c) MICRORISC s.r.o. 5 // 6 // File: $RCSfile: CustomDpaHandler-FRC.c,v $ 7 // Version: $Revision: 1.52 $ 8 // Date: $Date: 2022/02/25 09:41:25 $ 9 // 10 // Revision history: 11 // 2022/02/24 Release for DPA 4.17 12 // 2017/03/13 Release for DPA 3.00 13 // 2015/08/05 Release for DPA 2.20 14 // 2014/10/31 Release for DPA 2.10 15 // 2014/04/30 Release for DPA 2.00 16 // 17 // ******************************************************************************* 18 19 // Online DPA documentation https://doc.iqrf.org/DpaTechGuide/ 20 21 // Default IQRF include (modify the path according to your setup) 22 #include "IQRF.h" 23 24 // Default DPA header (modify the path according to your setup) 25 #include "DPA.h" 26 // Default Custom DPA Handler header (modify the path according to your setup) 27 #include "DPAcustomHandler.h" 28 29 //############################################################################################ 30 31 // Divides 16bit value by 255 32 void DivMod255( uns16 value ); 33 34 // Application implements 4 FCR commands 35 // 0x40 - bit command, result bit.0 == 1, result bit.1 == 1 when button is pressed, otherwise bit.1 == 0 36 // 0x41 - bit command, result bit.0 == 1, result bit.1 == 1 when LEDG is on, otherwise bit.1 == 0 37 // 0xC0 - byte command, result byte=VRN 38 // 0xC1 - shows how to return 16bit value even having its bytes equal 0. This command does not do sleeping, but UserData is used to specify which byte of 16bit value to return) 39 // 0xF0 - 2 bytes with temperature from getTemperature() call, 0x8000 is error, 0x7FFF instead of temperature value 0x0000 40 // 41 // FRC user data specify time to sleep after RFC data is collected, 0 means no sleeping 42 // Sleeping after FRC can be easily implemented using acknowledged broadcast FRC commands 43 44 // Must be the 1st defined function in the source code in order to be placed at the correct FLASH location! 45 //############################################################################################ 46 bit CustomDpaHandler() 47 //############################################################################################ 48 { 49 // Handler presence mark 50 clrwdt(); 51 52 // Go sleep on next Idle 53 static uns16 sleepTime; 54 55 // Detect DPA event to handle 56 switch ( GetDpaEvent() ) 57 { 58 // ------------------------------------------------- 59 case DpaEvent_Interrupt: 60 // Do an extra quick background interrupt work 61 // ! 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. 62 // ! 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. 63 // ! 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. 64 // ! Only global variables or local ones marked by static keyword can be used to allow reentrancy. 65 // ! Make sure race condition does not occur when accessing those variables at other places. 66 // ! 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. 67 // ! Do not call any OS functions except setINDFx(). 68 // ! Do not use any OS variables especially for writing access. 69 // ! 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. 70 71 DpaHandleReturnTRUE: 72 return TRUE; 73 74 // ------------------------------------------------- 75 case DpaEvent_Init: 76 // Do a one time initialization before main loop starts 77 78 // Enable LED during special system actions (discovery, FRC) 79 _systemLEDindication = TRUE; 80 break; 81 82 // ------------------------------------------------- 83 case DpaEvent_FrcResponseTime: 84 // Called to get FRC response time 85 86 switch ( DataOutBeforeResponseFRC[0] ) 87 { 88 case FRC_USER_BIT_FROM + 0: 89 case FRC_USER_BIT_FROM + 1: 90 case FRC_USER_BYTE_FROM + 0: 91 case FRC_USER_BYTE_FROM + 1: 92 responseFRCvalue = _FRC_RESPONSE_TIME_40_MS; 93 break; 94 } 95 break; 96 97 // ------------------------------------------------- 98 case DpaEvent_FrcValue: 99 // Called to get FRC value 100 uns16 FRC16bData @ DataOutBeforeResponseFRC; 101 sleepTime = FRC16bData; 102 103 switch ( _PCMD ) 104 { 105 // This example is sensitive to the bit FRCommand 0x40 106 case FRC_USER_BIT_FROM + 0: 107 // bit.1 is set only when button is pressed 108 if ( buttonPressed ) 109 responseFRCvalue.1 = 1; 110 break; 111 112 // This example is sensitive to the bit FRCommand 0x41 113 case FRC_USER_BIT_FROM + 1: 114 // bit.1 is set only when LEDG is on 115 if ( _LEDG == 1 ) 116 responseFRCvalue.1 = 1; 117 break; 118 119 // This example is sensitive to the byte FRCommand 0xF0 120 case FRC_USER_2BYTE_FROM: 121 // It returns 2 bytes from getTemperature() 122 123 // Temperature measurement error? 124 if ( getTemperature() == -128 ) 125 param3 = 0x8000; 126 127 // Is temperature 0? 128 if ( param3 == 0 ) 129 // Return 0x7FFF instead 130 param3 = 0x7FFF; 131 132 responseFRCvalue2B = param3; 133 break; 134 135 // This example is sensitive to the byte FRCommand 0xC0 136 case FRC_USER_BYTE_FROM + 0: 137 // Return node's VRN 138 responseFRCvalue = ntwVRN; 139 break; 140 141 // This example is sensitive to the byte FRCommand 0xC1 142 case FRC_USER_BYTE_FROM + 1: 143 { 144 // This FRC shows how to return 16 bit value keeping in mind that returned bytes must not be 0 145 // It converts 16 bit value into 255 radix and increments both quotient and reminder by 1 thus eliminating 0 146 // It means that the highest value that can be actually returned is 255 * 254 + 254 = 0xFE00 (hex) = 65024 (decimal) 147 // To compose the original 16b value just do: ( 1stByte - 1 ) + 255 * ( 2ndByte - 1 ) 148 149 static uns8 hiByte; 150 151 // Return 1st lower "byte" 152 if ( FRC16bData == 0 ) 153 { 154 // Example value to return is 0xABCD 155 DivMod255( 0xABCD ); 156 // Quotient /255 157 hiByte = param3.low8 + 1; 158 // Return reminder /255 159 responseFRCvalue = param4.low8 + 1; 160 } 161 else 162 // Return quotient 163 responseFRCvalue = hiByte; 164 165 // fall through to reset sleeping 166 } 167 168 default: 169 sleepTime = 0; 170 break; 171 } 172 173 break; 174 175 // ------------------------------------------------- 176 case DpaEvent_Idle: 177 // Do a quick background work when RF packet is not received 178 179 // Go sleep? 180 if ( sleepTime != 0 ) 181 { 182 // Prepare OS Sleep DPA Request 183 _PNUM = PNUM_OS; 184 _PCMD = CMD_OS_SLEEP; 185 // Time in 2.097s units 186 _DpaMessage.PerOSSleep_Request.Time = sleepTime; 187 sleepTime = 0; 188 // LEDG flash after wake up & pin wakeup 189 _DpaMessage.PerOSSleep_Request.Control = 0b1101; 190 _DpaDataLength = sizeof( _DpaMessage.PerOSSleep_Request ); 191 // Perform local DPA Request 192 DpaApiLocalRequest(); 193 } 194 break; 195 196 case DpaEvent_DpaRequest: 197 // Called to interpret DPA request for peripherals 198 // ------------------------------------------------- 199 // Peripheral enumeration 200 if ( IsDpaEnumPeripheralsRequest() ) 201 { 202 // We implement no user peripheral 203 _DpaMessage.EnumPeripheralsAnswer.HWPID |= 0x000F; 204 _DpaMessage.EnumPeripheralsAnswer.HWPIDver |= 0x0000; 205 goto DpaHandleReturnTRUE; 206 } 207 } 208 209 return FALSE; 210 } 211 212 //############################################################################################ 213 /* 214 * Divides 16bit value by 255 215 * Input: 216 * Dividend: value @ param3:16 217 * Output: 218 * Quotient: @ param3:16 219 * Remainder: @ param4.low8:8 220 * Assumes: param4:16 is adjacent to param3:16 221 * 222 * Based on http://www.piclist.com/techref/microchip/math/div/24by8-jah.htm 223 */ 224 void DivMod255( uns16 value @ param3 ) 225 //############################################################################################ 226 { 227 #asm 228 clrf param4 + 0 229 230 movlw 16; 231 movwf param4 + 1; 232 233 loop: 234 rlf value + 0, W; 235 rlf value + 1, f; 236 rlf param4 + 0, f; 237 rlf value + 0, f; 238 239 movlw 255; 240 subwf param4 + 0, f; 241 242 btfsc Carry; 243 bsf value + 0, 0; 244 245 btfss value + 0, 0; 246 addwf param4 + 0, f; 247 248 decfsz param4 + 1, f; 249 goto loop; 250 #endasm 251 } 252 253 //############################################################################################ 254 // 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) 255 #include "DPAcustomHandler.h" 256 //############################################################################################