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