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