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