1 // ************************************************************************** 2 // Custom DPA Handler code example - DPA Menu * 3 // ************************************************************************** 4 // Copyright (c) MICRORISC s.r.o. 5 // 6 // File: $RCSfile: CustomDpaHandler-DpaMenu.c,v $ 7 // Version: $Revision: 1.11 $ 8 // Date: $Date: 2023/11/03 16:32:29 $ 9 // 10 // Revision history: 11 // 2023/03/07 Release for DPA 4.30 12 // 13 // ********************************************************************* 14 15 // Online DPA documentation https://doc.iqrf.org/DpaTechGuide/ 16 17 // Default IQRF include (modify the path according to your setup) 18 #include "IQRF.h" 19 // Default DPA header (modify the path according to your setup) 20 #include "DPA.h" 21 // Default Custom DPA Handler header (modify the path according to your setup) 22 #include "DPAcustomHandler.h" 23 24 #if defined( TR7xD ) 25 #error This example is intended for TR7xG 26 #endif 27 28 #define _HWPID_ 0x0F0F 29 #define _HWPIDver_ 0x1234 30 31 // Executes DPA Menu User2 menu item 32 void User2Execute(); 33 34 // Must be the 1st defined function in the source code in order to be placed at the correct FLASH location! 35 //############################################################################################ 36 bit CustomDpaHandler() 37 //############################################################################################ 38 { 39 static bit startBeamingAtIdle; 40 static uns8 inStanbyCnt; 41 42 // Handler presence mark 43 clrwdt(); 44 45 // Detect DPA event to handle (unused event handlers can be commented out or even deleted) 46 switch ( GetDpaEvent() ) 47 { 48 // ------------------------------------------------- 49 case DpaEvent_Interrupt: 50 // Do an extra quick background interrupt work 51 // ! 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. 52 // ! 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. 53 // ! 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. 54 // ! Only global variables or local ones marked by static keyword can be used to allow reentrancy. 55 // ! Make sure race condition does not occur when accessing those variables at other places. 56 // ! 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. 57 // ! Do not call any OS functions except setINDFx(). 58 // ! Do not use any OS variables especially for writing access. 59 // ! 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. 60 // https://doc.iqrf.org/DpaTechGuide/pages/EventInterrupt.html 61 62 return Carry; 63 64 // ------------------------------------------------- 65 case DpaEvent_Idle: 66 // Do a quick background work when RF packet is not received 67 // https://doc.iqrf.org/DpaTechGuide/pages/idle.html 68 69 // Was beaming selected at the Online menu? 70 if ( startBeamingAtIdle ) 71 { 72 startBeamingAtIdle = FALSE; 73 // Simulate beaming (see CustomDpaHandler-SensorBeaming-Temperature.c for the real beaming code) 74 FirstDpaApiSleep = TRUE; 75 for ( ;; ) 76 { 77 DpaApiSleep( WDTCON_512ms ); 78 79 // Indicate beaming 80 setLEDG(); 81 waitMS( 20 ); 82 stopLEDG(); 83 84 DpaApiSleep( WDTCON_512ms ); 85 86 uns8 menuAndItem = DpaApiMenu( DMENU_Beaming, DMENU_Item_Implemented_User1Confirmed | DMENU_Item_Implemented_User2 ); 87 switch ( menuAndItem ) 88 { 89 case MakeDMenuAndItem( DMENU_Beaming, DMENU_Item_None ): 90 // No menu item was selected 91 break; 92 93 case MakeDMenuAndItem( DMENU_Beaming, DMENU_Item_User1 ): 94 // User1 always reports error 95 DpaApiMenuIndicateResult( FALSE ); 96 break; 97 98 case MakeDMenuAndItem( DMENU_Beaming, DMENU_Item_User2 ): 99 // User2 always reports OK 100 DpaApiMenuIndicateResult( TRUE ); 101 // And is executed 102 User2Execute(); 103 break; 104 105 case MakeDMenuAndItem( DMENU_Beaming, DMENU_Item_ConnectivityCheck ): 106 // Stop beaming sleeps 107 DpaApiAfterSleep(); 108 // Voluntary indication of the TestRange execution 109 pulsingLEDR(); 110 // Repeaters to test 111 clearBufferINFO(); 112 bufferINFO[0 / 8] = 0b1111.1110; // 1...7 113 // Do the test and result indication 114 DpaApiMenuIndicateResult( DpaApiLocalFrc( FRC_Ping, TX_POWER_MAX ) ); 115 // Continue regular beaming sleeps 116 FirstDpaApiSleep = TRUE; 117 break; 118 119 default: 120 // Stop beaming sleeps 121 DpaApiAfterSleep(); 122 // Execute other menu items 123 DpaApiMenuExecute( menuAndItem ); 124 // Continue regular beaming sleeps 125 FirstDpaApiSleep = TRUE; 126 break; 127 } 128 } 129 } 130 break; 131 132 // ------------------------------------------------- 133 case DpaEvent_Reset: 134 // Called after module is reset 135 // https://doc.iqrf.org/DpaTechGuide/pages/ResetEvent.html 136 137 { 138 static bit wasReset; 139 if ( !wasReset ) 140 { 141 wasReset = TRUE; 142 143 // To minimize the power consumption, no MCU pin must be left as a digital input without defined input level value. 144 // So, unused pins in given hardware should be set as outputs: 145 #if defined( TR72G ) // Symbols are generated by IQRF IDE according to the TR selection in a project 146 // TR pin C1 (MCU pin RA0): should be set as an output 147 LATA.0 = 0; // Low level 148 TRISA.0 = 0; // Output 149 150 // TR pin C2 (MCU pin RC2): should be set as an output 151 LATC.2 = 0; // Low level 152 TRISC.2 = 0; // Output 153 154 // TR pin C5 (MCU pins RA5, RB4 and RC6 connected in parallel): 155 // All MCU pins can be set as an input, but pin RB4 must be configured with internal pull-up (default activated). 156 TRISA.5 = 1; // Input 157 TRISB.4 = 1; // Input 158 TRISC.6 = 1; // Input 159 160 // TR pin C6 (MCU pin RC3): should be set as an output 161 LATC.3 = 0; // Low level 162 TRISC.3 = 0; // Output 163 164 // TR pin C7 (MCU pin RC4): should be set as an output 165 LATC.4 = 0; // Low level 166 TRISC.4 = 0; // Output 167 168 // TR pin C8 (MCU pins RC5 and RC7 connected in parallel): 169 // Only one MCU pin should be set as an output 170 LATC.5 = 0; // Low level 171 TRISC.5 = 0; // Output 172 TRISC.7 = 1; // Input 173 #elif defined( TR76G ) 174 // TR pin Q14 (MCU pin RA0): should be set as an output 175 LATA.0 = 0; // Low level 176 TRISA.0 = 0; // Output 177 178 // TR pin Q15 (MCU pin RC2): should be set as an output 179 LATC.2 = 0; // Low level 180 TRISC.2 = 0; // Output 181 182 // TR pin Q4 (MCU pin RC6): should be set as an output 183 LATC.6 = 0; // Low level 184 TRISC.6 = 0; // Output 185 186 // TR pin Q5 (MCU pin RC7): should be set as an output 187 LATC.7 = 0; // Low level 188 TRISC.7 = 0; // Output 189 190 // TR pin Q6 (MCU pin RC3): should be set as an output 191 LATC.3 = 0; // Low level 192 TRISC.3 = 0; // Output 193 194 // TR pin Q7 (MCU pin RC4): should be set as an output 195 LATC.4 = 0; // Low level 196 TRISC.4 = 0; // Output 197 198 // TR pin Q8 (MCU pin RC5): should be set as an output 199 LATC.5 = 0; // Low level 200 TRISC.5 = 0; // Output 201 202 // TR pin Q9 (MCU pin RA5): should be set as an output 203 LATA.5 = 0; // Low level 204 TRISA.5 = 0; // Output 205 206 // TR LED pins Q10 and Q11 (MCU pins RB7 and RA2) are set as outputs by OS. 207 // TR pin Q12 (MCU pin RB4) is set as an input with internal pull-up activated as default. 208 #else 209 #warning Low power consumption by treating unused pins is not implemented for the selected TR module 210 #endif 211 212 // Indicate startup 213 waitDelay( 20 ); 214 setLEDR(); 215 setLEDG(); 216 waitDelay( 50 ); 217 stopLEDR(); 218 stopLEDG(); 219 waitDelay( 50 ); 220 } 221 222 break; 223 } 224 225 // ------------------------------------------------- 226 case DpaEvent_MenuActivated: 227 // Called to customize DPA menu 228 // https://doc.iqrf.org/DpaTechGuide/pages/menuactivated.html 229 230 inStanbyCnt = 0; 231 232 switch ( userReg1 ) 233 { 234 case DMENU_Online: 235 // Customize Online DPA Menu 236 userReg1 = DMENU_Item_Implemented_Beaming | DMENU_Item_Implemented_User1Confirmed | DMENU_Item_Implemented_User2 | DMENU_Item_Unimplemented_UnbondFactorySettingsAndRestart; 237 goto DpaHandleReturnTRUE; 238 239 case DMENU_ReadyToBond: 240 // Customize ReadyToBond DPA Menu 241 userReg1 = DMENU_Item_Implemented_User1Confirmed | DMENU_Item_Implemented_User2 | DMENU_Item_Unimplemented_UnbondAndRestart; 242 243 // Was the BondingSleepCountdown just initiated? 244 if ( BondingSleepCountdown == 0 ) 245 // Set a few seconds timeout 246 BondingSleepCountdown = 10000 / BONDING_SLEEP_COUNTDOWN_UNIT; 247 goto DpaHandleReturnTRUE; 248 } 249 break; 250 251 // ------------------------------------------------- 252 case DpaEvent_MenuItemSelected: 253 // Called to indicate "OK" or "Error" for selected menu item 254 // https://doc.iqrf.org/DpaTechGuide/pages/menuitemselected.html 255 256 switch ( userReg1 ) 257 { 258 case MakeDMenuAndItem( DMENU_Online, DMENU_Item_Beaming ): 259 // Beaming is OK when the node is bonded, but not prebonded 260 if ( amIBonded() ) 261 { 262 startBeamingAtIdle = TRUE; 263 goto DpaHandleReturnTRUE; 264 } 265 266 break; 267 268 case MakeDMenuAndItem( DMENU_Online, DMENU_Item_User2 ): 269 case MakeDMenuAndItem( DMENU_ReadyToBond, DMENU_Item_User2 ): 270 // User2 always reports OK 271 goto DpaHandleReturnTRUE; 272 } 273 274 break; 275 276 // ------------------------------------------------- 277 case DpaEvent_MenuItemFinalize: 278 // Called to finalize menu item execution 279 // https://doc.iqrf.org/DpaTechGuide/pages/menuitemfinalize.html 280 281 switch ( GetDMenuItem( userReg1 ) ) 282 { 283 // Execute User2 menu item 284 case DMENU_Item_User2: 285 User2Execute(); 286 break; 287 } 288 break; 289 290 // ------------------------------------------------- 291 case DpaEvent_InStandby: 292 // Called to set WDT during Standby 293 // https://doc.iqrf.org/DpaTechGuide/pages/instandby.html 294 295 // Pulse LEDR or LEDG for 8 ms every 4 s in Standby 296 if ( inStanbyCnt.1 ) 297 _LEDR = 1; 298 else 299 _LEDG = 1; 300 301 if ( inStanbyCnt.0 ) 302 { 303 _LEDR = 0; 304 _LEDG = 0; 305 userReg1 = WDTCON_4s; 306 } 307 else 308 userReg1 = WDTCON_8ms; 309 310 inStanbyCnt++; 311 goto DpaHandleReturnTRUE; 312 313 // ------------------------------------------------- 314 case DpaEvent_DpaRequest: 315 // Called to interpret DPA request for peripherals 316 // https://doc.iqrf.org/DpaTechGuide/pages/EventDpaRequest.html 317 318 if ( IsDpaEnumPeripheralsRequest() ) 319 { 320 // ------------------------------------------------- 321 // Peripheral enumeration 322 // https://doc.iqrf.org/DpaTechGuide/pages/enumerate-peripherals.html 323 324 // We implement no user peripheral 325 _DpaMessage.EnumPeripheralsAnswer.HWPID |= _HWPID_; 326 _DpaMessage.EnumPeripheralsAnswer.HWPIDver |= _HWPIDver_; 327 328 DpaHandleReturnTRUE: 329 return TRUE; 330 } 331 } 332 333 return FALSE; 334 } 335 336 //############################################################################################ 337 void User2Execute() 338 //############################################################################################ 339 { 340 uns8 loop = 3; 341 do 342 { 343 waitMS( 200 ); 344 setLEDR(); 345 setLEDG(); 346 waitMS( 50 ); 347 stopLEDR(); 348 stopLEDG(); 349 clrwdt(); 350 } while ( --loop != 0 ); 351 } 352 353 //############################################################################################ 354 #pragma library 1 // Compile only used functions 355 // 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) 356 #include "DPAcustomHandler.h" 357 //############################################################################################