1 // ************************************************************************** 2 // Custom DPA Handler code example - User peripheral implementation - ADC * 3 // ************************************************************************** 4 // Copyright (c) MICRORISC s.r.o. 5 // 6 // File: $RCSfile: CustomDpaHandler-UserPeripheral-ADC.c,v $ 7 // Version: $Revision: 1.36 $ 8 // Date: $Date: 2022/02/25 09:41:25 $ 9 // 10 // Revision history: 11 // 2022/02/24 Release for DPA 4.17 12 // 2017/03/13 Release for DPA 3.00 13 // 2015/08/05 Release for DPA 2.20 14 // 2014/10/31 Release for DPA 2.10 15 // 2014/04/30 Release for DPA 2.00 16 // 17 // ********************************************************************* 18 19 // Online DPA documentation https://doc.iqrf.org/DpaTechGuide/ 20 21 // This example implements the user peripherals ADC 22 // PNUM = 0x20 and PCMD = 0 returns 2 bytes with 10b ADC result from pin C5 at PData 23 // PNUM = 0x21 and PCMD = 0 returns 2 bytes with 10b ADC result from pin C1 at PData 24 // Works with TR-72 having connected pins RA.5, RC.6 and RB.4 25 // At DDC-SE-01 allows to read: 26 // * Light intensity measurement using a photoresistor 27 // * Voltage measurement using a potentiometer 28 29 // Default IQRF include (modify the path according to your setup) 30 #include "IQRF.h" 31 32 // Default DPA header (modify the path according to your setup) 33 #include "DPA.h" 34 // Default Custom DPA Handler header (modify the path according to your setup) 35 #include "DPAcustomHandler.h" 36 37 // Must be the 1st defined function in the source code in order to be placed at the correct FLASH location! 38 //############################################################################################ 39 bit CustomDpaHandler() 40 //############################################################################################ 41 { 42 // Handler presence mark 43 clrwdt(); 44 45 // Detect DPA event to handle 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 61 DpaHandleReturnTRUE: 62 return TRUE; 63 64 // ------------------------------------------------- 65 case DpaEvent_Init: 66 // Do a one time initialization before main loop starts 67 68 // C5 as input 69 TRISA.5 = 1; 70 TRISC.6 = 1; 71 TRISB.4 = 1; 72 // C1 as input 73 TRISA.0 = 1; 74 75 break; 76 77 // ------------------------------------------------- 78 case DpaEvent_DpaRequest: 79 // Called to interpret DPA request for peripherals 80 // ------------------------------------------------- 81 // Peripheral enumeration 82 if ( IsDpaEnumPeripheralsRequest() ) 83 { 84 // We implement 1 user peripheral 85 _DpaMessage.EnumPeripheralsAnswer.UserPerNr |= 2; 86 FlagUserPer( _DpaMessage.EnumPeripheralsAnswer.UserPer, PNUM_USER + 0 ); 87 FlagUserPer( _DpaMessage.EnumPeripheralsAnswer.UserPer, PNUM_USER + 1 ); 88 _DpaMessage.EnumPeripheralsAnswer.HWPID |= 0x000F; 89 _DpaMessage.EnumPeripheralsAnswer.HWPIDver |= 0xabcd; 90 91 goto DpaHandleReturnTRUE; 92 } 93 // ------------------------------------------------- 94 // Get information about peripheral 95 else if ( IsDpaPeripheralInfoRequest() ) 96 { 97 if ( _PNUM == PNUM_USER + 0 || _PNUM == PNUM_USER + 1 ) 98 { 99 _DpaMessage.PeripheralInfoAnswer.PerT = PERIPHERAL_TYPE_ADC; 100 _DpaMessage.PeripheralInfoAnswer.PerTE = PERIPHERAL_TYPE_EXTENDED_READ; 101 goto DpaHandleReturnTRUE; 102 } 103 104 break; 105 } 106 // ------------------------------------------------- 107 else 108 { 109 // Handle peripheral command 110 if ( _PNUM == PNUM_USER + 0 || _PNUM == PNUM_USER + 1 ) 111 { 112 // Check command 113 if ( _PCMD != 0 ) 114 DpaApiReturnPeripheralError( ERROR_PCMD ); 115 116 // Check data length 117 if ( _DpaDataLength != 0 ) 118 DpaApiReturnPeripheralError( ERROR_DATA_LEN ); 119 120 #if defined( TR7xG ) 121 // Enable ADC 122 ADCMD = 0; 123 124 // Might not be needed if ADC registers are kept default 125 { 126 // Start reseting ADC registers from ADCON0 to ADPCH 127 // VREF- is connected to AVSS, VREF+ is connected to VDD 128 FSR0 = &ADCON0; 129 do 130 { 131 setINDF0( 0 ); 132 FSR0++; 133 // Stop reseting at 1st GPR register, ADPCH is the last implemented register before GPR 134 } while ( !FSR0L.5 ); 135 } 136 #endif 137 138 if ( _PNUM == PNUM_USER + 0 ) 139 { 140 #if defined( TR7xG ) 141 // ADC Positive Input Channel = ANA5 142 setADPCH( 0x05 ); 143 #else 144 // ADC setting (AN4 channel) 145 ADCON0 = 0b0.00100.01; 146 #endif 147 // ADC initialization (for more info see PIC datasheet) pin C5 (AN4-D/ANA5-G) as analog input 148 ANSELA.5 = 1; 149 } 150 else 151 { 152 #if defined( TR7xG ) 153 // ADC Positive Input Channel = ANA0 154 setADPCH( 0x00 ); 155 #else 156 // ADC setting (AN0 channel) 157 ADCON0 = 0b0.00000.01; 158 #endif 159 // ADC initialization (for more info see PIC datasheet) pin C1 (AN0-D/ANA0-G) as analog input 160 ANSELA.0 = 1; 161 } 162 163 #if defined( TR7xG ) 164 // ADC is enabled, ADGO is cleared upon completion, Clock supplied according to ADCLK register, right-justified 165 ADCON0 = 0b1000.0100; 166 // ADC Conversion Clock = FOSC/8 167 ADCLK = 8 / 2 - 1; 168 #else 169 // ADC result - right justified, Fosc/8 170 ADCON1 = 0b1001.0000; 171 #endif 172 173 // Short delay to stabilize 174 updateCRC16( W ); 175 // start ADC 176 _GO = 1; 177 // wait for ADC finish 178 while ( _GO ); 179 180 // 10b result is stored in ADRESH and ADRESL 181 _DpaMessage.Response.PData[0] = ADRESL; 182 _DpaMessage.Response.PData[1] = ADRESH & 0x03; 183 _DpaDataLength = sizeof( uns16 ); 184 185 goto DpaHandleReturnTRUE; 186 } 187 } 188 } 189 190 return FALSE; 191 } 192 //############################################################################################ 193 // 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) 194 #include "DPAcustomHandler.h" 195 //############################################################################################