1 // ********************************************************************* 2 // Main Custom DPA Handler header * 3 // ********************************************************************* 4 // Copyright (c) MICRORISC s.r.o. 5 // 6 // File: $RCSfile: DPAcustomHandler.h,v $ 7 // Version: $Revision: 1.152 $ 8 // Date: $Date: 2022/08/01 15:03:29 $ 9 // 10 // Revision history: 11 // 2022/02/24 Release for DPA 4.17 12 // 2021/08/20 Release for DPA 4.16 13 // 2020/09/03 Release for DPA 4.15 14 // 2020/04/03 Release for DPA 4.14 15 // 2020/02/27 Release for DPA 4.13 16 // 2020/01/09 Release for DPA 4.12 17 // 2019/12/11 Release for DPA 4.11 18 // 2019/10/09 Release for DPA 4.10 19 // 2019/06/12 Release for DPA 4.03 20 // 2019/06/03 Release for DPA 4.02 21 // 2019/03/07 Release for DPA 4.01 22 // 2019/01/10 Release for DPA 4.00 23 // 2018/10/25 Release for DPA 3.03 24 // 2017/11/16 Release for DPA 3.02 25 // 2017/08/14 Release for DPA 3.01 26 // 2017/03/13 Release for DPA 3.00 27 // 2016/09/12 Release for DPA 2.28 28 // 2016/04/14 Release for DPA 2.27 29 // 2016/03/03 Release for DPA 2.26 30 // 2016/01/21 Release for DPA 2.25 31 // 2015/12/01 Release for DPA 2.24 32 // 2015/10/23 Release for DPA 2.23 33 // 2015/09/25 Release for DPA 2.22 34 // 2015/09/03 Release for DPA 2.21 35 // 2015/08/05 Release for DPA 2.20 36 // 2014/10/31 Release for DPA 2.10 37 // 2014/04/30 Release for DPA 2.00 38 // 2013/10/03 Release for DPA 1.00 39 // 40 // ********************************************************************* 41 42 // Online DPA documentation https://doc.iqrf.org/DpaTechGuide/ 43 // IQRF Standards documentation https://doc.iqrf.org/ 44 45 #ifndef _CUSTOM_DPA_HANDLER_ 46 #define _CUSTOM_DPA_HANDLER_ 47 48 //############################################################################################ 49 // 1st include 50 51 // Custom DPA Handler routine declaration 52 bit CustomDpaHandler(); 53 54 // Various DPA flags shared between DPA and Custom DPA Handler 55 uns8 DpaFlags @ usedBank4[0]; 56 57 // [C][N] TRUE if I2C timeout occurred at the last DpaApiI2C?() call 58 bit I2CwasTimeout @ DpaFlags.0; 59 // [N] Flag for the 1st DpaApiSleep 60 bit FirstDpaApiSleep @ DpaFlags.1; 61 62 #ifdef COORDINATOR_CUSTOM_HANDLER 63 // [C] TRUE if interface master is not connected (detected) 64 bit IFaceMasterNotConnected @ DpaFlags.2; 65 #endif 66 // [N] DPA by interface notification is sent also when there was a "reading" like DPA request 67 bit EnableIFaceNotificationOnRead @ DpaFlags.3; 68 // [N] TRUE when node was just bonded using default bonding procedure 69 bit NodeWasBonded @ DpaFlags.4; 70 // [N] When TRUE, then next call of DpaApiRfTxDpaPacket sends non-routed packet 71 bit NonroutedRfTxDpaPacket @ DpaFlags.7; 72 73 // [C] Ticks (decrementing) counter usable for timing in the coordinator's Customer DPA Handler 74 uns16 DpaTicks @ usedBank4[1]; 75 // [N] toutRF for LP mode, read from configuration memory after reset 76 uns8 LPtoutRF @ usedBank4[3]; 77 // DPA Request/Response HWPID 78 uns16 _HWPID @ usedBank4[4]; 79 // Identifies type of reset (stored at UserReg0 upon module reset). See Reset chapter at IQRF User's Guide for more information 80 uns8 ResetType @ usedBank4[6]; 81 // User DPA Values to return 82 uns8 UserDpaValue @ usedBank4[7]; 83 // Network depth of the DPA request/response, increases on bridging, decreases on back-bridging 84 uns8 NetDepth @ usedBank4[8]; 85 // TRUE when node was at DPA Service Mode after last boot 86 bit DSMactivated @ usedBank4[9].0; 87 // If set to TRUE, then LP RX mode in the main loop can be terminated by pin, see _RLPMAT 88 bit LpRxPinTerminate @ usedBank4[9].1; 89 // If set to TRUE, then [C] executes asynchronous DPA requests received from [N] 90 bit AsyncReqAtCoordinator @ usedBank4[9].2; 91 // RX filter used at the DPA main loop checkRF call 92 uns8 RxFilter @ usedBank4[11]; 93 // Countdown variable for button bonding before going to deep sleep 94 uns16 BondingSleepCountdown @ usedBank4[12]; 95 #define BONDING_SLEEP_COUNTDOWN_UNIT 290 96 // Non-zero pseudo-random value, read-only, updated on every Reset and Idle event, at [N] only. 97 uns16 Random @ usedBank4[14]; 98 // DPA value from the received packet or just to be sent to the interface. 99 uns8 DpaValue @ usedBank4[16]; 100 // If non-zero then timeout value for DpaApiI2C?() calls 101 uns8 I2Ctimeout @ usedBank4[17]; 102 103 // Macro to return an error from the peripheral handler. If the code size is not an issue this macro is the right choice. 104 #define DpaApiReturnPeripheralError(error) do { \ 105 DpaApiSetPeripheralError( error ); \ 106 return Carry; \ 107 } while( 0 ) 108 109 // DPA API functions, see documentation for details 110 #define DpaApiRfTxDpaPacket( dpaValue, netDepthAndFlags ) DpaApiEntry( dpaValue, netDepthAndFlags, DPA_API_RFTX_DPAPACKET ) 111 #define DpaApiReadConfigByte( index ) DpaApiEntry( index, param3.low8, DPA_API_READ_CONFIG_BYTE ) 112 #define DpaApiLocalRequest() DpaApiEntry( param2, param3.low8, DPA_API_LOCAL_REQUEST ) 113 #define DpaApiSetPeripheralError( error ) DpaApiEntry( error, param3.low8, DPA_API_SET_PERIPHERAL_ERROR ) 114 #define DpaApiSendToIFaceMaster( dpaValue, flags ) DpaApiEntry( dpaValue, flags, DPA_API_SEND_TO_IFACEMASTER ) 115 #define DpaApiSetRfDefaults() DpaApiEntry( param2, param3.low8, DPA_API_SET_RF_DEFAULTS ) 116 #define DpaApiLocalFrc( frcCommand, replyTxPower ) DpaApiEntry( frcCommand, replyTxPower, DPA_API_LOCAL_FRC ) 117 #define DpaApiCrc8( crc8, data ) DpaApiEntry( crc8, data, DPA_API_CRC8 ) 118 #define DpaApiAggregateFrc() DpaApiEntry( param2, param3.low8, DPA_API_AGGREGATE_FRC ) 119 #define DpaApiSetOTK() DpaApiEntry( param2, param3.low8, DPA_API_SET_OTK ) 120 #define DpaApiI2Cinit( frequency ) DpaApiEntry( frequency, param3.low8, DPA_API_I2C_INIT ) 121 #define DpaApiI2Cstart( address ) DpaApiEntry( address, param3.low8, DPA_API_I2C_START ) 122 #define DpaApiI2Cwrite( data ) DpaApiEntry( data, param3.low8, DPA_API_I2C_WRITE ) 123 #define DpaApiI2Cread( ack ) DpaApiEntry( ack, param3.low8, DPA_API_I2C_READ ) 124 #define DpaApiI2Cstop() DpaApiEntry( param2, param3.low8, DPA_API_I2C_STOP ) 125 #define DpaApiI2CwaitForACK( address ) DpaApiEntry( address, param3.low8, DPA_API_I2C_WAIT_FOR_ACK ) 126 #define DpaApiI2Cshutdown() DpaApiEntry( param2, param3.low8, DPA_API_I2C_SHUTDOWN ) 127 #define DpaApiI2CwaitForIdle() DpaApiEntry( param2, param3.low8, DPA_API_I2C_WAIT_FOR_IDLE ) 128 #define DpaApiSleep( wdtcon ) DpaApiEntry( wdtcon, param3.low8, DPA_API_SLEEP ) 129 #define DpaApiAfterSleep() DpaApiEntry( param2, param3.low8, DPA_API_AFTER_SLEEP ) 130 #define DpaApiRandom() DpaApiEntry( param2, param3.low8, DPA_API_RANDOM ) 131 132 #ifdef COORDINATOR_CUSTOM_HANDLER 133 #define DpaApiRfTxDpaPacketCoordinator() DpaApiEntry( param2, param3.low8, DPA_API_COORDINATOR_RFTX_DPAPACKET ) 134 #endif 135 136 #define DpaApiLocalFrc_StackSaver( frcCommand, replyTxPower ) \ 137 param2 = frcCommand; \ 138 param3.low8 = replyTxPower; \ 139 W = DPA_API_LOCAL_FRC; \ 140 #asm \ 141 DW __MOVLP( DPA_API_ADDRESS >> 8 ); \ 142 DW __CALL( DPA_API_ADDRESS ); \ 143 DW __MOVLP( CUSTOM_HANDLER_ADDRESS >> 8 ); \ 144 #endasm \ 145 146 #define I2CcomputeFrequency( I2Cfrequency) ( ( ( F_OSC ) / ( ( I2Cfrequency ) * 4 ) ) - 1 ) 147 148 // Wrapper routines to be called instead of DpaApi??? macros to decrease code size if more than ~2 calls are needed 149 void _DpaApiI2Cinit( uns8 frequency ); 150 void _DpaApiI2Cstart( uns8 address ); 151 void _DpaApiI2Cwrite( uns8 data ); 152 uns8 _DpaApiI2Cread( uns8 ack ); 153 void _DpaApiI2Cstop(); 154 void _DpaApiI2CwaitForACK( uns8 address ); 155 void _DpaApiI2Cshutdown(); 156 void _DpaApiI2CwaitForIdle(); 157 void _DpaApiSleep( uns8 wdtcon ); 158 void _DpaApiSleepFirst( uns8 wdtcon ); 159 void _DpaApiAfterSleep(); 160 uns8 _DpaApiRandom(); 161 void _DpaApiSetRfDefaults(); 162 163 // Helper "multi" function to decrease code size if used more times 164 void _DpaApiI2Cwrite0(); 165 void _DpaApiI2CwriteAndStop( uns8 data ); 166 uns8 _DpaApiI2CreadACK(); 167 uns8 _DpaApiI2CreadNACK(); 168 uns8 _DpaApiI2CreadNACKandStop(); 169 170 #ifdef COORDINATOR_CUSTOM_HANDLER 171 #undef DpaEvent_Interrupt 172 #undef DpaEvent_BeforeSleep 173 #undef DpaEvent_AfterSleep 174 #undef DpaEvent_FrcValue 175 #undef DpaEvent_FrcResponseTime 176 #else 177 #undef DpaEvent_ReceiveDpaResponse 178 #undef DpaEvent_IFaceReceive 179 #endif 180 181 // To detect overlapping code in case someone would put some code before this header by mistake 182 #pragma origin __APPLICATION_ADDRESS 183 #pragma updateBank 0 184 185 //############################################################################################ 186 // Main IQRF entry point jumps to the main DPA entry point 187 void APPLICATION() 188 //############################################################################################ 189 { 190 #asm 191 DW __MOVLP( MAIN_DPA_ADDRESS >> 8 ); 192 DW __GOTO( MAIN_DPA_ADDRESS ); 193 #endasm 194 195 #ifndef NO_CUSTOM_DPA_HANDLER 196 // Fake call to force CustomDpaHandler() compilation 197 CustomDpaHandler(); 198 #endif 199 200 // Fake call to force DpaApiEntry() compilation 201 DpaApiEntry( param2, param3.low8, W ); 202 } 203 204 //############################################################################################ 205 // Entry stub to the real DPA API entry 206 #pragma origin DPA_API_ADDRESS_ENTRY 207 uns8 DpaApiEntry( uns8 par1 @ param2, uns8 par2 @ param3.low8, uns8 apiIndex @ W ) 208 //############################################################################################ 209 { 210 #asm 211 DW __MOVLP( DPA_API_ADDRESS >> 8 ); 212 DW __CALL( DPA_API_ADDRESS ); 213 DW __MOVLP( DPA_API_ADDRESS_ENTRY >> 8 ); 214 #endasm 215 216 return W; 217 } 218 219 //############################################################################################ 220 #pragma origin DPA_API_ADDRESS_ENTRY + 0x08 221 222 //############################################################################################ 223 224 #ifndef NO_CUSTOM_DPA_HANDLER 225 // Next comes Custom DPA handler routine 226 #pragma origin CUSTOM_HANDLER_ADDRESS 227 #endif 228 229 #pragma updateBank 1 230 231 //############################################################################################ 232 #else // _CUSTOM_DPA_HANDLER_ 233 //############################################################################################ 234 // 2nd include 235 236 #ifndef NO_CUSTOM_DPA_HANDLER 237 238 // Library wrappers and helpers to decrease code size 239 //############################################################################################ 240 #pragma library 1 241 //############################################################################################ 242 uns8 _DpaApiUserBank_01( uns8 apiIndex @ W ) 243 //############################################################################################ 244 { 245 #pragma updateBank exit = UserBank_01 246 return DpaApiEntry( param2, param3.low8, apiIndex ); 247 } 248 //############################################################################################ 249 void _DpaApiI2Cinit( uns8 frequency @ W ) 250 //############################################################################################ 251 { 252 #pragma updateBank exit = UserBank_01 253 param2 = frequency; 254 _DpaApiUserBank_01( DPA_API_I2C_INIT ); 255 } 256 //############################################################################################ 257 void _DpaApiI2Cstart( uns8 address @ W ) 258 //############################################################################################ 259 { 260 #pragma updateBank exit = UserBank_01 261 param2 = address; 262 _DpaApiUserBank_01( DPA_API_I2C_START ); 263 } 264 //############################################################################################ 265 void _DpaApiI2Cwrite0() 266 //############################################################################################ 267 { 268 #pragma updateBank exit = UserBank_01 269 _DpaApiI2Cwrite( 0 ); 270 } 271 //############################################################################################ 272 void _DpaApiI2Cwrite( uns8 data @ W ) 273 //############################################################################################ 274 { 275 #pragma updateBank exit = UserBank_01 276 param2 = data; 277 _DpaApiUserBank_01( DPA_API_I2C_WRITE ); 278 } 279 //############################################################################################ 280 uns8 _DpaApiI2CreadNACKandStop() 281 //############################################################################################ 282 { 283 #pragma updateBank exit = UserBank_01 284 param2 = _DpaApiI2CreadNACK(); 285 _DpaApiI2Cstop(); /* Must not use param2 */ 286 return param2; 287 } 288 //############################################################################################ 289 uns8 _DpaApiI2CreadACK() 290 //############################################################################################ 291 { 292 #pragma updateBank exit = UserBank_01 293 return _DpaApiI2Cread( 1 ); 294 } 295 //############################################################################################ 296 uns8 _DpaApiI2CreadNACK() 297 //############################################################################################ 298 { 299 #pragma updateBank exit = UserBank_01 300 return _DpaApiI2Cread( 0 ); 301 } 302 //############################################################################################ 303 uns8 _DpaApiI2Cread( uns8 ack @ W ) 304 //############################################################################################ 305 { 306 #pragma updateBank exit = UserBank_01 307 param2 = ack; 308 return _DpaApiUserBank_01( DPA_API_I2C_READ ); 309 } 310 //############################################################################################ 311 void _DpaApiI2CwriteAndStop( uns8 data @ W ) 312 //############################################################################################ 313 { 314 #pragma updateBank exit = UserBank_01 315 _DpaApiI2Cwrite( data ); 316 _DpaApiI2Cstop(); 317 } 318 //############################################################################################ 319 void _DpaApiI2Cstop() 320 //############################################################################################ 321 { 322 #pragma updateBank exit = UserBank_01 323 _DpaApiUserBank_01( DPA_API_I2C_STOP ); 324 } 325 //############################################################################################ 326 void _DpaApiI2CwaitForACK( uns8 address @ W ) 327 //############################################################################################ 328 { 329 #pragma updateBank exit = UserBank_01 330 DpaApiI2CwaitForACK( address ); 331 } 332 //############################################################################################ 333 void _DpaApiI2Cshutdown() 334 //############################################################################################ 335 { 336 #pragma updateBank exit = UserBank_01 337 _DpaApiUserBank_01( DPA_API_I2C_SHUTDOWN ); 338 } 339 //############################################################################################ 340 void _DpaApiI2CwaitForIdle() 341 //############################################################################################ 342 { 343 #pragma updateBank exit = UserBank_01 344 _DpaApiUserBank_01( DPA_API_I2C_WAIT_FOR_IDLE ); 345 } 346 //############################################################################################ 347 void _DpaApiSleep( uns8 wdtcon @ W ) 348 //############################################################################################ 349 { 350 #pragma updateBank exit = UserBank_01 351 param2 = wdtcon; 352 _DpaApiUserBank_01( DPA_API_SLEEP ); 353 } 354 //############################################################################################ 355 void _DpaApiSleepFirst( uns8 wdtcon @ W ) 356 //############################################################################################ 357 { 358 #pragma updateBank exit = UserBank_01 359 FirstDpaApiSleep = TRUE; 360 _DpaApiSleep( wdtcon ); 361 } 362 //############################################################################################ 363 void _DpaApiAfterSleep() 364 //############################################################################################ 365 { 366 #pragma updateBank exit = UserBank_01 367 _DpaApiUserBank_01( DPA_API_AFTER_SLEEP ); 368 } 369 //############################################################################################ 370 uns8 _DpaApiRandom() 371 //############################################################################################ 372 { 373 #pragma updateBank exit = UserBank_01 374 return _DpaApiUserBank_01( DPA_API_RANDOM ); 375 } 376 //############################################################################################ 377 void _DpaApiSetRfDefaults() 378 //############################################################################################ 379 { 380 #pragma updateBank exit = UserBank_01 381 _DpaApiUserBank_01( DPA_API_SET_RF_DEFAULTS ); 382 } 383 //############################################################################################ 384 385 386 // Code bumper to detect too long code of Custom DPA handler + other routines 387 #pragma origin CUSTOM_HANDLER_ADDRESS_END 388 // To avoid adding some code after handler by mistake 389 #pragma origin __MAX_FLASH_ADDRESS 390 #endif 391 392 #endif // _CUSTOM_DPA_HANDLER_ 393 //############################################################################################