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