1 // ************************************************************************************************ 2 // Custom DPA Handler code example - Shows custom (un)bonding and factory settings using button * 3 // ************************************************************************************************ 4 // Copyright (c) MICRORISC s.r.o. 5 // 6 // File: $RCSfile: CustomDpaHandler-Bonding.c,v $ 7 // Version: $Revision: 1.53 $ 8 // Date: $Date: 2022/02/25 09:41:25 $ 9 // 10 // Revision history: 11 // 2022/02/24 Release for DPA 4.17 12 // 2021/08/20 Release for DPA 4.16 13 // 2019/12/11 Release for DPA 4.11 14 // 2019/10/09 Release for DPA 4.10 15 // 2019/06/03 Release for DPA 4.02 16 // 2019/01/10 Release for DPA 4.00 17 // 2018/10/25 Release for DPA 3.03 18 // 2017/08/14 Release for DPA 3.01 19 // 2017/03/13 Release for DPA 3.00 20 // 2015/08/05 Release for DPA 2.20 21 // 22 // ********************************************************************* 23 24 // Online DPA documentation https://doc.iqrf.org/DpaTechGuide/ 25 26 // Default IQRF include (modify the path according to your setup) 27 #include "IQRF.h" 28 29 // Default DPA header (modify the path according to your setup) 30 #include "DPA.h" 31 // Default Custom DPA Handler header (modify the path according to your setup) 32 #include "DPAcustomHandler.h" 33 34 // This code illustrates bonding using a button connected to the custom pin. 35 // Except going to sleep the code behaves the same way as the standard bonding procedure. 36 // Please see https://www.iqrf.org/DpaTechGuide/index.html?page=device-startup.html and the following chapters. 37 // ! Please note, that the overlapping networks support by SmartConnect DPA command https://doc.iqrf.org/DpaTechGuide/pages/smart-connect.html will not work with this example 38 39 // Define to just reassign a bonding button with the button behavior implemented inside DPA 40 // #define USE_DpaEvent_BondingButton 41 42 // Custom bonding button. Change to the pin and an active level of your choice. 43 //#define IsButton ( !PORTA.5 ) 44 #define IsButton buttonPressed 45 46 // Returns TRUE when button is released shortly after LEDG goes out 47 bit ButtonAfterGreen(); 48 // Same as above but with leading gap 49 bit ButtonAfterGreenWithGap(); 50 // RedLED on for 1s 51 void LEDR1s(); 52 53 // Must be the 1st defined function in the source code in order to be placed at the correct FLASH location! 54 //############################################################################################ 55 bit CustomDpaHandler() 56 //############################################################################################ 57 { 58 // Handler presence mark 59 clrwdt(); 60 61 // Detect DPA event to handle 62 switch ( GetDpaEvent() ) 63 { 64 // ------------------------------------------------- 65 case DpaEvent_Interrupt: 66 // Do an extra quick background interrupt work 67 // ! 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. 68 // ! 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. 69 // ! 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. 70 // ! Only global variables or local ones marked by static keyword can be used to allow reentrancy. 71 // ! Make sure race condition does not occur when accessing those variables at other places. 72 // ! 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. 73 // ! Do not call any OS functions except setINDFx(). 74 // ! Do not use any OS variables especially for writing access. 75 // ! 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. 76 return Carry; 77 78 #ifdef USE_DpaEvent_BondingButton 79 // ------------------------------------------------- 80 case DpaEvent_BondingButton: 81 // Called to allow a bonding button customization 82 83 userReg1.0 = 0; 84 if ( IsButton ) 85 userReg1.0 = 1; 86 87 return TRUE; 88 #else 89 // ------------------------------------------------- 90 case DpaEvent_Reset: 91 // Called after module is reset 92 93 // Handle (un)bonding 94 if ( !amIBonded() ) 95 { 96 // ------------------------------------------------- 97 // Not bonded 98 99 // Very 1st bonding attempt and well released button after 2.5 s gap and LEDG? 100 if ( ButtonAfterGreenWithGap() ) 101 // Factory settings! 102 goto _factoryAndRemoveBond; 103 104 // If and while node is not bonded 105 for ( ;; ) 106 { 107 // If button is not pressed, be ready to be SmartConnected 108 while ( !IsButton ) 109 { 110 // Do and wait for an indication 111 pulseLEDR(); 112 waitMS( 6 ); 113 // Make sure to use LP mode 114 setRFmode( _WPE | _RX_LP | _TX_LP ); 115 116 // Set sometimes a new service channel for SmartConnect, otherwise the last one 117 static uns8 lastServiceChannel; 118 static uns8 channelCnt; 119 // Time to set a new service channel? 120 if ( ( channelCnt & 0x03 ) == 0 ) 121 // Set a new service channel 122 lastServiceChannel = 0; 123 // Next "timer" 124 channelCnt++; 125 126 // Set the SmartConnect service channel 127 setServiceChannel( lastServiceChannel ); 128 // Save last service channel used 129 lastServiceChannel = param2 + 1; 130 131 // Try SmartConnect 132 _checkRFcfg_PQT = TRUE; 133 toutRF = 6; 134 // Use more strict RF RX filter for SmartConnect only 135 checkRF( RxFilter + 4 ); 136 RFRXpacket(); 137 // Restore original RF RX filter 138 checkRF( RxFilter ); 139 // Process SmartConnect packet, if received 140 answerSystemPacket(); 141 // Restore RF settings (and make sure Spirit1 is not locked) 142 wasRFICrestarted(); 143 DpaApiSetRfDefaults(); 144 // SmartConnect success? 145 if ( amIBonded() ) 146 goto _NodeWasBonded; 147 } 148 149 // Bonding by button indication 150 pulseLEDR(); 151 // Traditional bonding using 3 service channels 152 _3CHTX = TRUE; 153 // Bonded? 154 if ( bondRequestAdvanced() ) 155 { 156 _NodeWasBonded: 157 // Indicate bonding for 0.5 s 158 setLEDG(); 159 waitDelay( 50 ); 160 stopLEDG(); 161 // Exit the loop 162 break; 163 } 164 } 165 } 166 else 167 { 168 // ------------------------------------------------- 169 // Bonded 170 171 // If the button is pressed for 2s (Green LED is on during this time) and then released within 0.5s, then un-bond the node (indicated by 1s Red LED) 172 if ( ButtonAfterGreen() ) 173 { 174 // Red LED for 1s 175 LEDR1s(); 176 // Remove bond + implicit restart 177 _DpaDataLength = 0; 178 _PNUM = PNUM_NODE; 179 _PCMD = CMD_NODE_REMOVE_BOND; 180 // Perform local DPA Request 181 DpaApiLocalRequest(); 182 // Unreachable code because of restart 183 } 184 185 // Now wait if the button is still pressed for about 2.5 s and if again released after green LED do factory settings and remove bond 186 if ( ButtonAfterGreenWithGap() ) 187 { 188 _factoryAndRemoveBond: 189 // Red LED for 1s 190 LEDR1s(); 191 // Factory settings + remove bond + implicit restart 192 _DpaDataLength = 0; 193 _PNUM = PNUM_OS; 194 _PCMD = CMD_OS_FACTORY_SETTINGS; 195 // Perform local DPA Request 196 DpaApiLocalRequest(); 197 // Unreachable code because of restart 198 } 199 } 200 201 return TRUE; 202 #endif 203 } 204 205 return FALSE; 206 } 207 208 //############################################################################################ 209 void LEDR1s() 210 //############################################################################################ 211 { 212 setLEDR(); 213 waitDelay( 100 ); 214 stopLEDR(); 215 } 216 217 //############################################################################################ 218 bit ButtonAfterGreen() 219 //############################################################################################ 220 { 221 // Returns TRUE when button is released shortly after LEDG goes out 222 223 // Time for Green LED on 224 startDelay( 200 ); 225 // Green LED on 226 setLEDG(); 227 do 228 { 229 // If button not pressed 230 if ( !IsButton ) 231 { 232 // Switch off Green LED 233 stopLEDG(); 234 // And return FALSE 235 return FALSE; 236 } 237 // Is button still pressed while Green LED is on? 238 } while ( isDelay() ); 239 240 // Switch off Green LED 241 stopLEDG(); 242 // Set testing delay 243 startDelay( 50 ); 244 do 245 { 246 // If the button is released within the delay 247 if ( !IsButton ) 248 // Return TRUE 249 return TRUE; 250 } while ( isDelay() ); 251 // Otherwise return FALSE 252 return FALSE; 253 } 254 255 //############################################################################################ 256 bit ButtonAfterGreenWithGap() 257 //############################################################################################ 258 { 259 // Is button pressed for 2.55s ? 260 startDelay( 255 ); 261 while ( IsButton && isDelay() ); 262 // If not the next call will return FALSE, otherwise will test for button release after Green LED goes off 263 return ButtonAfterGreen(); 264 } 265 266 //############################################################################################ 267 // 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) 268 #include "DPAcustomHandler.h" 269 //############################################################################################