1 // ********************************************************************* 2 // Custom DPA Handler code example - Local FRC Controller * 3 // ********************************************************************* 4 // Copyright (c) MICRORISC s.r.o. 5 // 6 // File: $RCSfile: CustomDpaHandler-LocalFRC-Controller.c,v $ 7 // Version: $Revision: 1.19 $ 8 // Date: $Date: 2024/05/31 09:29:22 $ 9 // 10 // Revision history: 11 // 2022/02/24 Release for DPA 4.17 12 // 2020/09/03 Release for DPA 4.15 13 // 14 // ********************************************************************* 15 16 // Online DPA documentation https://doc.iqrf.org/DpaTechGuide/ 17 18 // Default IQRF include (modify the path according to your setup) 19 #include "IQRF.h" 20 21 // Default DPA header (modify the path according to your setup) 22 #include "DPA.h" 23 // Default Custom DPA Handler header (modify the path according to your setup) 24 #include "DPAcustomHandler.h" 25 // IQRF standards header (modify the path according to your setup) 26 #include "Standard\IQRFstandard.h" 27 28 //############################################################################################ 29 30 // This example implements configurable Local FRC Controller 31 32 // When a IQRF button is pressed, the controller sends Local FRC command to switch on/off configurable FRC commands to the selected [Ns] 33 34 // Structure with the controller settings stored at EEPROM from address 0 35 typedef struct 36 { 37 // Selected nodes (actuators) 38 uns8 Nodes[sizeof( _DpaMessage.PerFrcSendSelective_Request.SelectedNodes )]; 39 // RF power used 40 uns8 RfPower; 41 // Number of retries if all Ns do not respond 42 uns8 Retries; 43 // Auto power-off time [10 ms] (0 => no auto power-off) 44 uns16 PowerOffTime; 45 // Local FRC command used 46 uns8 FrcCommand; 47 // ON and OFF user data for the FRC command, 1st byte is the total data length including the length byte 48 uns8 OnOffData[0]; 49 } TLocalFrcCtrl; 50 51 //############################################################################################ 52 53 #pragma cdata[ __EESTART + PERIPHERAL_EEPROM_START ] = \ 54 /* uns8 Nodes[sizeof( _DpaMessage.PerFrcSendSelective_Request.SelectedNodes )]; */ \ 55 /* example: only N#1 is selected */ \ 56 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 59 /* uns8 RfPower; */ \ 60 1, \ 61 /* uns8 Retries; */ \ 62 1, \ 63 /* uns16 PowerOffTime; */ \ 64 ( 10 * (uns16)100 ) & 0xFF, ( 10 * (uns16)100 ) >> 8 /* example: 10 s */ 65 66 // Light (DALI) Example using FRC_STD_LIGHT_LDI_SEND 67 #if 0 68 #pragma cdata[ __EESTART + PERIPHERAL_EEPROM_START + offsetof( TLocalFrcCtrl, FrcCommand )] = \ 69 /* uns8 FrcCommand; */ \ 70 FRC_STD_LIGHT_LDI_SEND, \ 71 /* uns8 OnOffData[2 * ( sizeof( uns8 ) + sizeof( _DpaMessage.PerFrcSendSelective_Request.UserData ) )]; */ \ 72 /* ON */ 5, PNUM_STD_LIGHT, 0xFF, 0x05, 0, \ 73 /* OFF */ 5, PNUM_STD_LIGHT, 0xFF, 0x00, 0 74 #endif 75 76 // LEDR Example using FRC_AcknowledgedBroadcastBits 77 #if 1 78 #pragma cdata[ __EESTART + PERIPHERAL_EEPROM_START + offsetof( TLocalFrcCtrl, FrcCommand )] = \ 79 /* uns8 FrcCommand; */ \ 80 FRC_AcknowledgedBroadcastBits, \ 81 /* uns8 OnOffData[2 * ( sizeof( uns8 ) + sizeof( _DpaMessage.PerFrcSendSelective_Request.UserData ) )]; */ \ 82 /* ON */ 6, 5, PNUM_LEDR, CMD_LED_SET_ON, HWPID_DoNotCheck & 0xFF, HWPID_DoNotCheck >> 8, \ 83 /* OFF */ 6, 5, PNUM_LEDR, CMD_LED_SET_OFF, HWPID_DoNotCheck & 0xFF, HWPID_DoNotCheck >> 8 84 #endif 85 86 //############################################################################################ 87 88 // The FRC settings stored in the bufferINFo after read from the EEPROM 89 shadowDef TLocalFrcCtrl LocalFrcCtrl @ bufferINFO; 90 91 // Calculates the structure field address in the EEPROM 92 #define LocalFrcCtrlEeAddr( field ) ( offsetof( TLocalFrcCtrl, field ) + PERIPHERAL_EEPROM_START ) 93 94 // Must be the 1st defined function in the source code in order to be placed at the correct FLASH location! 95 //############################################################################################ 96 bit CustomDpaHandler() 97 //############################################################################################ 98 { 99 // Handler presence mark 100 clrwdt(); 101 102 // Detect DPA event to handle (unused event handlers can be commented out or even deleted) 103 switch ( GetDpaEvent() ) 104 { 105 // ------------------------------------------------- 106 case DpaEvent_Interrupt: 107 // Do an extra quick background interrupt work 108 return Carry; 109 110 // ------------------------------------------------- 111 case DpaEvent_Idle: 112 // Do a quick background work when RF packet is not received 113 { 114 // On/Off actuator state 115 static bit offOrOn; 116 // On start time from captureTicks() 117 static uns16 timerStart; 118 // Auto power-off time in ticks, zero if no timer is running 119 static uns16 timerValue; 120 121 // Check the auto power-off timer if it is running 122 if ( timerValue != 0 ) 123 { 124 // Timer is over? 125 captureTicks(); 126 param3 -= timerStart; 127 if ( param3 > timerValue ) 128 { 129 // Yes, switch off the actuator 130 offOrOn = FALSE; 131 goto _sendLocalFrc; 132 } 133 } 134 135 // If the button is pressed for some time, send appropriate Local FRC command to switch on/off the actuator 136 static uns8 buttonCnt; 137 if ( buttonPressed ) 138 { 139 // Button was longer pressed? 140 #define BUTTON_CNT 8 141 if ( buttonCnt < BUTTON_CNT && ++buttonCnt == BUTTON_CNT ) 142 { 143 // Toggle actuator's state 144 offOrOn = !offOrOn; 145 146 _sendLocalFrc: 147 // Read the FRC structure up to the FRC user data 148 eeReadData( LocalFrcCtrlEeAddr( Nodes ), offsetof( TLocalFrcCtrl, OnOffData ) ); 149 // Read retries counter 150 uns8 retries = LocalFrcCtrl.Retries; 151 // Read timer value 152 timerValue = LocalFrcCtrl.PowerOffTime; 153 // Do local FRC 154 do 155 { 156 // Indicated LED and get the FRC user data address in the EEPROM according the ON or OFF state 157 if ( offOrOn ) 158 { 159 setLEDG(); 160 // Store timer's start time 161 captureTicks(); 162 timerStart = param3; 163 // FRC-On user data offset 164 W = LocalFrcCtrlEeAddr( OnOffData ) + sizeof( uns8 ); 165 } 166 else 167 { 168 stopLEDG(); 169 // No auto power-off timer when switched off 170 timerValue = 0; 171 // FRC-Off user data offset 172 W = eeReadByte( LocalFrcCtrlEeAddr( OnOffData ) ) + LocalFrcCtrlEeAddr( OnOffData ) + sizeof( uns8 ); 173 } 174 175 // Read the FRC user data 176 eeReadData( W, sizeof( _DpaMessage.PerFrcSendSelective_Request.UserData ) ); 177 setFSR0( _FSR_INFO ); 178 // And copy the FRC user data to the FRC data structure 179 copyMemoryBlock( FSR0, DataInSendFRC, sizeof( _DpaMessage.PerFrcSendSelective_Request.UserData ) ); 180 181 // Read the starting rest the FRC structure up to the FRC user data 182 eeReadData( LocalFrcCtrlEeAddr( Nodes ), offsetof( TLocalFrcCtrl, OnOffData ) ); 183 184 // Set configured RF power 185 setRFpower( LocalFrcCtrl.RfPower ); 186 // Now call the local FRC and exit "retry loop" if all nodes answered 187 if ( DpaApiLocalFrc( LocalFrcCtrl.FrcCommand, LocalFrcCtrl.RfPower ) == param2 ) 188 break; 189 190 // More retries? Indicate it. 191 pulseLEDR(); 192 // Just for sure... 193 clrwdt(); 194 } while ( --retries != (uns8)-1 ); 195 196 // Note: workaround to resolve the missing internal reset of the _localFRC variable at IQRF OS 4.04D 197 _localFRC = FALSE; 198 199 // Restore original configured RF power 200 DpaApiSetRfDefaults(); 201 } 202 } 203 else 204 // Button is not pressed 205 buttonCnt = 0; 206 207 break; 208 } 209 210 // ------------------------------------------------- 211 case DpaEvent_DpaRequest: 212 // Called to interpret DPA request for peripherals 213 if ( IsDpaEnumPeripheralsRequest() ) 214 { 215 // ------------------------------------------------- 216 // Peripheral enumeration 217 _DpaMessage.EnumPeripheralsAnswer.HWPID |= 0xF2CF; 218 219 DpaHandleReturnTRUE: 220 return TRUE; 221 } 222 223 break; 224 } 225 226 DpaHandleReturnFALSE: 227 return FALSE; 228 } 229 230 //############################################################################################ 231 // 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) 232 #include "DPAcustomHandler.h" 233 //############################################################################################