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