]> rtime.felk.cvut.cz Git - arc.git/blob - arch/hc1x/hcs12d/drivers/Adc.c
Splitting of Adc to eQADC and Adc_560x......continued....now for all architectures...
[arc.git] / arch / hc1x / hcs12d / drivers / Adc.c
1 /* -------------------------------- Arctic Core ------------------------------\r
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com\r
3  *\r
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>\r
5  *\r
6  * This source code is free software; you can redistribute it and/or modify it\r
7  * under the terms of the GNU General Public License version 2 as published by the\r
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.\r
9  *\r
10  * This program is distributed in the hope that it will be useful, but\r
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
13  * for more details.\r
14  * -------------------------------- Arctic Core ------------------------------*/\r
15 \r
16 \r
17 #include <assert.h>\r
18 #include <stdlib.h>\r
19 #include "Mcu.h"\r
20 #include "Adc.h"\r
21 #include "Det.h"\r
22 #include "Os.h"\r
23 #include "isr.h"\r
24 #include "regs.h"\r
25 #include "arc.h"\r
26 #include "Adc_Internal.h"\r
27 \r
28 \r
29 // ATDCTL2\r
30 #define BM_ADPU 0x80\r
31 #define BM_AFFC 0x40\r
32 #define BM_AWAI 0x20\r
33 #define BM_ETRIGLE 0x10\r
34 #define BM_ETRIGP 0x08\r
35 #define BM_ETRIG_E 0x04\r
36 #define BM_ASCIE 0x02\r
37 #define BM_ASCIF 0x01\r
38 \r
39 // ATDCTL3\r
40 #define BM_S8C 0x40\r
41 #define BM_S4C 0x20\r
42 #define BM_S2C 0x10\r
43 #define BM_S1C 0x08\r
44 #define BM_FIFO 0x04\r
45 #define BM_FRZ1 0x02\r
46 #define BM_FRZ0 0x01\r
47 \r
48 // ATDCTL4\r
49 #define BM_SRES8 0x80\r
50 #define BM_SMP1 0x40\r
51 #define BM_SMP0 0x20\r
52 #define BM_PRS4 0x10\r
53 #define BM_PRS3 0x08\r
54 #define BM_PRS2 0x04\r
55 #define BM_PRS1 0x02\r
56 #define BM_PRS0 0x01\r
57 \r
58 // ATDCTL5\r
59 #define BM_DJM 0x80\r
60 #define BM_DSGN 0x40\r
61 #define BM_SCAN 0x20\r
62 #define BM_MULT 0x10\r
63 #define BM_CC 0x04\r
64 #define BM_CB 0x02\r
65 #define BM_CA 0x01\r
66 \r
67 \r
68 \r
69 /* Function prototypes. */\r
70 static void Adc_GroupConversionComplete (void);\r
71 \r
72 static Adc_StateType adcState = ADC_UNINIT;\r
73 \r
74 /* Pointer to configuration structure. */\r
75 static const Adc_ConfigType *AdcConfigPtr;\r
76 \r
77 \r
78 #if (ADC_DEINIT_API == STD_ON)\r
79 void Adc_DeInit ()\r
80 {\r
81         if (E_OK == Adc_CheckDeInit(adcState, AdcConfigPtr))\r
82         {\r
83             /* Clean internal status. */\r
84             AdcConfigPtr = (Adc_ConfigType *)NULL;\r
85             adcState = ADC_UNINIT;\r
86         }\r
87 }\r
88 #endif\r
89 \r
90 void Adc_Init (const Adc_ConfigType *ConfigPtr)\r
91 {\r
92   Adc_GroupType group;\r
93 \r
94   if (E_OK == Adc_CheckInit(adcState, ConfigPtr))\r
95   {\r
96     /* First of all, store the location of the configuration data. */\r
97     AdcConfigPtr = ConfigPtr;\r
98 \r
99     // Connect interrupt to correct isr\r
100         ISR_INSTALL_ISR2("ADC",Adc_GroupConversionComplete,IRQ_TYPE_ATD0,6,0);\r
101 \r
102 \r
103         ATD0CTL2   = BM_ADPU | BM_AFFC | BM_ASCIE;      /* power enable, Fast Flag Clear, irq enable*/\r
104     ATD0CTL3   = 0x03;  /* 8 conversions per sequence default, freeze enable */\r
105 \r
106     ATD0CTL4   = (ConfigPtr->hwConfigPtr->resolution << 7) |\r
107                      (ConfigPtr->hwConfigPtr->convTime << 5) |\r
108                       ConfigPtr->hwConfigPtr->adcPrescale;\r
109 \r
110     for (group = 0; group < ADC_NBR_OF_GROUPS; group++)\r
111     {\r
112       /* ADC307. */\r
113       ConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;\r
114     }\r
115 \r
116     /* Move on to INIT state. */\r
117     adcState = ADC_INIT;\r
118   }\r
119 }\r
120 \r
121 Std_ReturnType Adc_SetupResultBuffer (Adc_GroupType group, Adc_ValueGroupType *bufferPtr)\r
122 {\r
123   Std_ReturnType returnValue;\r
124 \r
125   /* Check for development errors. */\r
126   if (E_OK == Adc_CheckSetupResultBuffer (adcState, AdcConfigPtr, group))\r
127   {\r
128     AdcConfigPtr->groupConfigPtr[group].status->resultBufferPtr = bufferPtr;\r
129     returnValue = E_OK;\r
130   }\r
131   else\r
132   {\r
133     /* An error have been raised from Adc_CheckSetupResultBuffer(). */\r
134     returnValue = E_NOT_OK;\r
135   }\r
136 \r
137   return (returnValue);\r
138 }\r
139 \r
140 #if (ADC_READ_GROUP_API == STD_ON)\r
141 Std_ReturnType Adc_ReadGroup (Adc_GroupType group, Adc_ValueGroupType *dataBufferPtr)\r
142 {\r
143   Std_ReturnType returnValue;\r
144   Adc_ChannelType channel;\r
145 \r
146   if (E_OK == Adc_CheckReadGroup (adcState, AdcConfigPtr, group))\r
147   {\r
148     if ((ADC_CONV_MODE_CONTINUOUS == AdcConfigPtr->groupConfigPtr[group].conversionMode) &&\r
149          ((ADC_STREAM_COMPLETED    == AdcConfigPtr->groupConfigPtr[group].status->groupStatus) ||\r
150           (ADC_COMPLETED           == AdcConfigPtr->groupConfigPtr[group].status->groupStatus)))\r
151     {\r
152       /* ADC329, ADC331. */\r
153       AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;\r
154       returnValue = E_OK;\r
155     }\r
156     else if ((ADC_CONV_MODE_ONESHOT == AdcConfigPtr->groupConfigPtr[group].conversionMode) &&\r
157              (ADC_STREAM_COMPLETED  == AdcConfigPtr->groupConfigPtr[group].status->groupStatus))\r
158     {\r
159       /* ADC330. */\r
160       AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;\r
161 \r
162       returnValue = E_OK;\r
163     }\r
164     else\r
165     {\r
166       /* Keep status. */\r
167       returnValue = E_OK;\r
168     }\r
169 \r
170     if (E_OK == returnValue)\r
171     {\r
172       /* Copy the result to application buffer. */\r
173       for (channel = 0; channel < AdcConfigPtr->groupConfigPtr[group].numberOfChannels; channel++)\r
174       {\r
175         dataBufferPtr[channel] = AdcConfigPtr->groupConfigPtr[group].resultBuffer[channel];\r
176       }\r
177     }\r
178   }\r
179   else\r
180   {\r
181     /* An error have been raised from Adc_CheckReadGroup(). */\r
182     returnValue = E_NOT_OK;\r
183   }\r
184 \r
185   return (returnValue);\r
186 }\r
187 #endif\r
188 \r
189 static void Adc_GroupConversionComplete (void)\r
190 {\r
191   uint8 index;\r
192   Adc_GroupDefType *groupPtr = NULL;\r
193   /* Clear SCF flag. Not needed if AFFC is set but better to always do it  */\r
194   ATD0STAT0 = SCF;\r
195 \r
196   // Check which group is busy, only one is allowed to be busy at a time in a hw unit\r
197   for (index = 0; index < ADC_NBR_OF_GROUPS; index++)\r
198   {\r
199           if(AdcConfigPtr->groupConfigPtr[index].status->groupStatus == ADC_BUSY)\r
200           {\r
201                   groupPtr = (Adc_GroupDefType *)&AdcConfigPtr->groupConfigPtr[index];\r
202                   break;\r
203           }\r
204   }\r
205   if(groupPtr != NULL)\r
206   {\r
207           // Read hw buffer,\r
208           volatile uint16_t *ptr = &ATD0DR0;\r
209           for(index=0; index<groupPtr->numberOfChannels; index++)\r
210           {\r
211                   groupPtr->resultBuffer[index] = *(ptr + groupPtr->channelList[index]);\r
212           }\r
213 \r
214           /* Sample completed. */\r
215           groupPtr->status->groupStatus = ADC_STREAM_COMPLETED;\r
216 \r
217           /* Call notification if enabled. */\r
218         #if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)\r
219           if (groupPtr->status->notifictionEnable && groupPtr->groupCallback != NULL)\r
220           {\r
221                   groupPtr->groupCallback();\r
222           }\r
223         #endif\r
224   }\r
225 }\r
226 \r
227 #if (ADC_ENABLE_START_STOP_GROUP_API == STD_ON)\r
228 void Adc_StartGroupConversion (Adc_GroupType group)\r
229 {\r
230   /* Run development error check. */\r
231   if (E_OK == Adc_CheckStartGroupConversion (adcState, AdcConfigPtr, group))\r
232   {\r
233     /* Set single scan enable bit if this group is one shot. */\r
234     if (AdcConfigPtr->groupConfigPtr[group].conversionMode == ADC_CONV_MODE_ONESHOT)\r
235     {\r
236            /* Start next AD conversion. */\r
237            ATD0CTL5 = BM_DJM | BM_MULT; /* 10010000 Right Justified,unsigned */\r
238                                                                 /* No SCAN/MULT/AD0 start select */\r
239       /* Set group state to BUSY. */\r
240       AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;\r
241     }\r
242     else\r
243     {\r
244         // Continous mode\r
245            /* Start AD conversion. */\r
246            ATD0CTL5 = BM_DJM | BM_MULT | BM_SCAN; /* 10010000 Right Justified,unsigned */\r
247                                                                           /* SCAN/MULT/AD0 start select */\r
248        /* Set group state to BUSY. */\r
249        AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;\r
250     }\r
251   }\r
252 }\r
253 \r
254 void Adc_StopGroupConversion (Adc_GroupType group)\r
255 {\r
256   /* Run development error check. */\r
257   if (E_OK == Adc_CheckStopGroupConversion (adcState, AdcConfigPtr, group))\r
258   {\r
259            ATD0CTL3 = 0x03; /* Hard write to stop current conversion */\r
260   }\r
261   else\r
262   {\r
263         /* Error have been set within Adc_CheckStartGroupConversion(). */\r
264   }\r
265 }\r
266 #endif\r
267 \r
268 #if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)\r
269 void Adc_EnableGroupNotification (Adc_GroupType group)\r
270 {\r
271         Adc_EnableInternalGroupNotification(adcState, AdcConfigPtr, group);\r
272 }\r
273 \r
274 void Adc_DisableGroupNotification (Adc_GroupType group)\r
275 {\r
276         Adc_InternalDisableGroupNotification(adcState, AdcConfigPtr, group);\r
277 }\r
278 #endif\r
279 \r
280 Adc_StatusType Adc_GetGroupStatus (Adc_GroupType group)\r
281 {\r
282         return Adc_InternalGetGroupStatus(adcState, AdcConfigPtr, group);\r
283 }\r