]> rtime.felk.cvut.cz Git - arc.git/blob - arch/hc1x/hcs12d/drivers/Adc.c
1b7b7946b9a61725e6a0a4f3ed83f76408af2713
[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 \r
27 \r
28 // ATDCTL2\r
29 #define BM_ADPU 0x80\r
30 #define BM_AFFC 0x40\r
31 #define BM_AWAI 0x20\r
32 #define BM_ETRIGLE 0x10\r
33 #define BM_ETRIGP 0x08\r
34 #define BM_ETRIG_E 0x04\r
35 #define BM_ASCIE 0x02\r
36 #define BM_ASCIF 0x01\r
37 \r
38 // ATDCTL3\r
39 #define BM_S8C 0x40\r
40 #define BM_S4C 0x20\r
41 #define BM_S2C 0x10\r
42 #define BM_S1C 0x08\r
43 #define BM_FIFO 0x04\r
44 #define BM_FRZ1 0x02\r
45 #define BM_FRZ0 0x01\r
46 \r
47 // ATDCTL4\r
48 #define BM_SRES8 0x80\r
49 #define BM_SMP1 0x40\r
50 #define BM_SMP0 0x20\r
51 #define BM_PRS4 0x10\r
52 #define BM_PRS3 0x08\r
53 #define BM_PRS2 0x04\r
54 #define BM_PRS1 0x02\r
55 #define BM_PRS0 0x01\r
56 \r
57 // ATDCTL5\r
58 #define BM_DJM 0x80\r
59 #define BM_DSGN 0x40\r
60 #define BM_SCAN 0x20\r
61 #define BM_MULT 0x10\r
62 #define BM_CC 0x04\r
63 #define BM_CB 0x02\r
64 #define BM_CA 0x01\r
65 \r
66 typedef enum\r
67 {\r
68   ADC_UNINIT,\r
69   ADC_INIT,\r
70 }Adc_StateType;\r
71 \r
72 /* Function prototypes. */\r
73 \r
74 /* Development error checking. */\r
75 static Std_ReturnType Adc_CheckReadGroup (Adc_GroupType group);\r
76 static Std_ReturnType Adc_CheckStartGroupConversion (Adc_GroupType group);\r
77 static Std_ReturnType Adc_CheckInit (const Adc_ConfigType *ConfigPtr);\r
78 static Std_ReturnType Adc_CheckSetupResultBuffer (Adc_GroupType group);\r
79 \r
80 static void Adc_GroupConversionComplete (void);\r
81 \r
82 static Adc_StateType adcState = ADC_UNINIT;\r
83 \r
84 /* Pointer to configuration structure. */\r
85 static const Adc_ConfigType *AdcConfigPtr;\r
86 \r
87 #if (ADC_DEINIT_API == STD_ON)\r
88 Std_ReturnType Adc_DeInit (const Adc_ConfigType *ConfigPtr)\r
89 {\r
90 \r
91   return (E_OK);\r
92 }\r
93 #endif\r
94 \r
95 Std_ReturnType Adc_Init (const Adc_ConfigType *ConfigPtr)\r
96 {\r
97   Std_ReturnType returnValue;\r
98   Adc_GroupType group;\r
99 \r
100   if (E_OK == Adc_CheckInit(ConfigPtr))\r
101   {\r
102     /* First of all, store the location of the configuration data. */\r
103     AdcConfigPtr = ConfigPtr;\r
104 \r
105     // Connect interrupt to correct isr\r
106         ISR_INSTALL_ISR2("ADC",Adc_GroupConversionComplete,IRQ_TYPE_ATD0,6,0);\r
107 \r
108 \r
109         ATD0CTL2   = BM_ADPU | BM_AFFC | BM_ASCIE;      /* power enable, Fast Flag Clear, irq enable*/\r
110     ATD0CTL3   = 0x00;  /* 8 conversions per sequence default */\r
111 \r
112     ATD0CTL4   = (ConfigPtr->hwConfigPtr->resolution << 7) |\r
113                      (ConfigPtr->hwConfigPtr->convTime << 5) |\r
114                       ConfigPtr->hwConfigPtr->adcPrescale;\r
115 \r
116     for (group = ADC_GROUP0; group < ADC_NBR_OF_GROUPS; group++)\r
117     {\r
118       /* ADC307. */\r
119       ConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;\r
120     }\r
121 \r
122     /* Move on to INIT state. */\r
123     adcState = ADC_INIT;\r
124     returnValue = E_OK;\r
125   }\r
126   else\r
127   {\r
128     returnValue = E_NOT_OK;\r
129   }\r
130 \r
131   return (returnValue);\r
132 }\r
133 \r
134 Std_ReturnType Adc_SetupResultBuffer (Adc_GroupType group, Adc_ValueGroupType *bufferPtr)\r
135 {\r
136   Std_ReturnType returnValue;\r
137 \r
138   /* Check for development errors. */\r
139   if (E_OK == Adc_CheckSetupResultBuffer (group))\r
140   {\r
141     AdcConfigPtr->groupConfigPtr[group].status->resultBufferPtr = bufferPtr;\r
142     returnValue = E_OK;\r
143   }\r
144   else\r
145   {\r
146     /* An error have been raised from Adc_CheckSetupResultBuffer(). */\r
147     returnValue = E_NOT_OK;\r
148   }\r
149 \r
150   return (returnValue);\r
151 }\r
152 \r
153 #if (ADC_READ_GROUP_API == STD_ON)\r
154 Std_ReturnType Adc_ReadGroup (Adc_GroupType group, Adc_ValueGroupType *dataBufferPtr)\r
155 {\r
156   Std_ReturnType returnValue;\r
157   Adc_ChannelType channel;\r
158 \r
159   if (E_OK == Adc_CheckReadGroup (group))\r
160   {\r
161     if ((ADC_CONV_MODE_CONTINUOUS == AdcConfigPtr->groupConfigPtr[group].conversionMode) &&\r
162          ((ADC_STREAM_COMPLETED    == AdcConfigPtr->groupConfigPtr[group].status->groupStatus) ||\r
163           (ADC_COMPLETED           == AdcConfigPtr->groupConfigPtr[group].status->groupStatus)))\r
164     {\r
165       /* ADC329, ADC331. */\r
166       AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;\r
167       returnValue = E_OK;\r
168     }\r
169     else if ((ADC_CONV_MODE_ONESHOT == AdcConfigPtr->groupConfigPtr[group].conversionMode) &&\r
170              (ADC_STREAM_COMPLETED  == AdcConfigPtr->groupConfigPtr[group].status->groupStatus))\r
171     {\r
172       /* ADC330. */\r
173       AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;\r
174 \r
175       returnValue = E_OK;\r
176     }\r
177     else\r
178     {\r
179       /* Keep status. */\r
180       returnValue = E_OK;\r
181     }\r
182 \r
183     if (E_OK == returnValue)\r
184     {\r
185       /* Copy the result to application buffer. */\r
186       for (channel = 0; channel < AdcConfigPtr->groupConfigPtr[group].numberOfChannels; channel++)\r
187       {\r
188         dataBufferPtr[channel] = AdcConfigPtr->groupConfigPtr[group].resultBuffer[channel];\r
189       }\r
190     }\r
191   }\r
192   else\r
193   {\r
194     /* An error have been raised from Adc_CheckReadGroup(). */\r
195     returnValue = E_NOT_OK;\r
196   }\r
197 \r
198   return (returnValue);\r
199 }\r
200 #endif\r
201 \r
202 Adc_StatusType Adc_GetGroupStatus (Adc_GroupType group)\r
203 {\r
204   Adc_StatusType returnValue;\r
205   if ((ADC_INIT == adcState) && (AdcConfigPtr != NULL))\r
206   {\r
207     /* Adc initilised, OK to move on... */\r
208     returnValue = AdcConfigPtr->groupConfigPtr[group].status->groupStatus;\r
209   }\r
210   else\r
211   {\r
212     returnValue = ADC_IDLE;\r
213 #if ( ADC_DEV_ERROR_DETECT == STD_ON )\r
214     Det_ReportError(MODULE_ID_ADC,0,ADC_GETGROUPSTATUS_ID, ADC_E_UNINIT );\r
215 #endif\r
216     }\r
217 \r
218   return (returnValue);\r
219 }\r
220 \r
221 static void Adc_GroupConversionComplete (void)\r
222 {\r
223   uint8 index;\r
224   Adc_GroupDefType *groupPtr = NULL;\r
225   /* Clear SCF flag. Not needed if AFFC is set but better to always do it  */\r
226   ATD0STAT0 = SCF;\r
227 \r
228   // Check which group is busy, only one is allowed to be busy at a time in a hw unit\r
229   for (index = ADC_GROUP0; index < ADC_NBR_OF_GROUPS; index++)\r
230   {\r
231           if(AdcConfigPtr->groupConfigPtr[index].status->groupStatus == ADC_BUSY)\r
232           {\r
233                   groupPtr = (Adc_GroupDefType *)&AdcConfigPtr->groupConfigPtr[index];\r
234                   break;\r
235           }\r
236   }\r
237   if(groupPtr != NULL)\r
238   {\r
239           // Read hw buffer,\r
240           volatile uint16_t *ptr = &ATD0DR0;\r
241           for(index=0; index<groupPtr->numberOfChannels; index++)\r
242           {\r
243                   groupPtr->resultBuffer[index] = *(ptr + groupPtr->channelList[index]);\r
244           }\r
245 \r
246           /* Sample completed. */\r
247           groupPtr->status->groupStatus = ADC_STREAM_COMPLETED;\r
248 \r
249           /* Call notification if enabled. */\r
250         #if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)\r
251           if (groupPtr->status->notifictionEnable && groupPtr->groupCallback != NULL)\r
252           {\r
253                   groupPtr->groupCallback();\r
254           }\r
255         #endif\r
256   }\r
257 }\r
258 \r
259 #if (ADC_ENABLE_START_STOP_GROUP_API == STD_ON)\r
260 void Adc_StartGroupConversion (Adc_GroupType group)\r
261 {\r
262   /* Run development error check. */\r
263   if (E_OK == Adc_CheckStartGroupConversion (group))\r
264   {\r
265     /* Set single scan enable bit if this group is one shot. */\r
266     if (AdcConfigPtr->groupConfigPtr[group].conversionMode == ADC_CONV_MODE_ONESHOT)\r
267     {\r
268            /* Start next AD conversion. */\r
269            ATD0CTL5 = BM_DJM | BM_MULT; /* 10010000 Right Justified,unsigned */\r
270                                                                 /* No SCAN/MULT/AD0 start select */\r
271       /* Set group state to BUSY. */\r
272       AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;\r
273     }\r
274     else\r
275     {\r
276         // Continous mode\r
277            /* Start AD conversion. */\r
278            ATD0CTL5 = BM_DJM | BM_MULT | BM_SCAN; /* 10010000 Right Justified,unsigned */\r
279                                                                           /* SCAN/MULT/AD0 start select */\r
280        /* Set group state to BUSY. */\r
281        AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;\r
282     }\r
283   }\r
284 }\r
285 #endif\r
286 \r
287 #if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)\r
288 void Adc_EnableGroupNotification (Adc_GroupType group)\r
289 {\r
290         AdcConfigPtr->groupConfigPtr[group].status->notifictionEnable = 1;\r
291 }\r
292 \r
293 void Adc_DisableGroupNotification (Adc_GroupType group)\r
294 {\r
295         AdcConfigPtr->groupConfigPtr[group].status->notifictionEnable = 0;\r
296 }\r
297 #endif\r
298 \r
299 \r
300 /* Development error checking functions. */\r
301 #if (ADC_READ_GROUP_API == STD_ON)\r
302 static Std_ReturnType Adc_CheckReadGroup (Adc_GroupType group)\r
303 {\r
304   Std_ReturnType returnValue;\r
305 \r
306 #if ( ADC_DEV_ERROR_DETECT == STD_ON )\r
307 \r
308   if (ADC_UNINIT == adcState)\r
309   {\r
310     /* ADC296. */\r
311     returnValue = E_NOT_OK;\r
312     Det_ReportError(MODULE_ID_ADC,0,ADC_READGROUP_ID ,ADC_E_UNINIT );\r
313   }\r
314   else if ((group < ADC_GROUP0) || (group >= ADC_NBR_OF_GROUPS))\r
315   {\r
316     /* ADC152. */\r
317     returnValue = E_NOT_OK;\r
318     Det_ReportError(MODULE_ID_ADC,0,ADC_READGROUP_ID ,ADC_E_PARAM_GROUP );\r
319   }\r
320   else if (ADC_IDLE == AdcConfigPtr->groupConfigPtr[group].status->groupStatus)\r
321   {\r
322     /* ADC388. */\r
323     returnValue = E_NOT_OK;\r
324     Det_ReportError(MODULE_ID_ADC,0,ADC_READGROUP_ID ,ADC_E_IDLE );\r
325   }\r
326   else\r
327   {\r
328     /* Nothing strange. Go on... */\r
329     returnValue = E_OK;\r
330   }\r
331 #else\r
332   returnValue = E_OK;\r
333 #endif\r
334   return (returnValue);\r
335 }\r
336 #endif\r
337 \r
338 #if (ADC_ENABLE_START_STOP_GROUP_API == STD_ON)\r
339 static Std_ReturnType Adc_CheckStartGroupConversion (Adc_GroupType group)\r
340 {\r
341   Std_ReturnType returnValue;\r
342 #if ( ADC_DEV_ERROR_DETECT == STD_ON )\r
343   if (!(ADC_INIT == adcState))\r
344   {\r
345     /* ADC not initialised, ADC294. */\r
346     Det_ReportError(MODULE_ID_ADC,0,ADC_STARTGROUPCONVERSION_ID, ADC_E_UNINIT );\r
347     returnValue = E_NOT_OK;\r
348   }\r
349   else  if (!((group >= 0) && (group < ADC_NBR_OF_GROUPS)))\r
350   {\r
351     /* Wrong group ID, ADC125 */\r
352     Det_ReportError(MODULE_ID_ADC,0,ADC_STARTGROUPCONVERSION_ID, ADC_E_PARAM_GROUP );\r
353     returnValue = E_NOT_OK;\r
354   }\r
355   else if (!(ADC_TRIGG_SRC_SW == AdcConfigPtr->groupConfigPtr[group].triggerSrc))\r
356   {\r
357     /* Wrong trig source, ADC133. */\r
358     Det_ReportError(MODULE_ID_ADC,0,ADC_STARTGROUPCONVERSION_ID, ADC_E_WRONG_TRIGG_SRC);\r
359     returnValue = E_NOT_OK;\r
360   }\r
361   else if (!((ADC_IDLE             == AdcConfigPtr->groupConfigPtr[group].status->groupStatus) ||\r
362              (ADC_STREAM_COMPLETED == AdcConfigPtr->groupConfigPtr[group].status->groupStatus)))\r
363   {\r
364     /* Group status not OK, ADC351, ADC428 */\r
365     Det_ReportError(MODULE_ID_ADC,0,ADC_STARTGROUPCONVERSION_ID, ADC_E_BUSY );\r
366 \r
367     returnValue = E_NOT_OK;\r
368   }\r
369   else\r
370   {\r
371     returnValue = E_OK;\r
372   }\r
373 #else\r
374   returnValue = E_OK;\r
375 #endif\r
376   return (returnValue);\r
377 }\r
378 #endif\r
379 \r
380 static Std_ReturnType Adc_CheckInit (const Adc_ConfigType *ConfigPtr)\r
381 {\r
382   Std_ReturnType returnValue;\r
383 \r
384 #if ( ADC_DEV_ERROR_DETECT == STD_ON )\r
385   if (!(ADC_UNINIT == adcState))\r
386   {\r
387     /* Oops, already initialised. */\r
388     Det_ReportError(MODULE_ID_ADC,0,ADC_INIT_ID, ADC_E_ALREADY_INITIALIZED );\r
389     returnValue = E_NOT_OK;\r
390   }\r
391   else if (ConfigPtr == NULL)\r
392   {\r
393     /* Wrong config! */\r
394     Det_ReportError(MODULE_ID_ADC,0,ADC_INIT_ID, ADC_E_PARAM_CONFIG );\r
395     returnValue = E_NOT_OK;\r
396   }\r
397   else\r
398   {\r
399     /* Looks good!! */\r
400     returnValue = E_OK;\r
401   }\r
402 #else\r
403     returnValue = E_OK;\r
404 #endif\r
405   return (returnValue);\r
406 }\r
407 \r
408 static Std_ReturnType Adc_CheckSetupResultBuffer (Adc_GroupType group)\r
409 {\r
410   Std_ReturnType returnValue;\r
411 \r
412 #if ( ADC_DEV_ERROR_DETECT == STD_ON )\r
413   if (ADC_UNINIT == adcState)\r
414   {\r
415     /* Driver not initialised. */\r
416     Det_ReportError(MODULE_ID_ADC,0,ADC_SETUPRESULTBUFFER_ID,ADC_E_UNINIT );\r
417     returnValue = E_NOT_OK;\r
418   }\r
419   else if (group < ADC_NBR_OF_GROUPS)\r
420   {\r
421     /* ADC423 */\r
422     Det_ReportError(MODULE_ID_ADC,0,ADC_SETUPRESULTBUFFER_ID,ADC_E_PARAM_GROUP );\r
423     returnValue = E_NOT_OK;\r
424   }\r
425   else\r
426   {\r
427     /* Looks good!! */\r
428     returnValue = E_OK;\r
429   }\r
430 #else\r
431   returnValue = E_OK;\r
432 #endif\r
433   return (returnValue);\r
434 }\r
435 \r
436 \r