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