]> rtime.felk.cvut.cz Git - arc.git/blob - arch/hc1x/hcs12d/drivers/Adc.c
a8e95da61b571637c0dfa6ca6a082c4b7d3e7f0a
[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 Std_ReturnType Adc_DeInit (const Adc_ConfigType *ConfigPtr)\r
80 {\r
81         if (E_OK == Adc_CheckDeInit(adcState, ConfigPtr))\r
82         {\r
83             /* Clean internal status. */\r
84             AdcConfigPtr = (Adc_ConfigType *)NULL;\r
85             adcState = ADC_UNINIT;\r
86         }\r
87 \r
88          return (E_OK);\r
89 }\r
90 #endif\r
91 \r
92 Std_ReturnType Adc_Init (const Adc_ConfigType *ConfigPtr)\r
93 {\r
94   Std_ReturnType returnValue;\r
95   Adc_GroupType group;\r
96 \r
97   if (E_OK == Adc_CheckInit(adcState, ConfigPtr))\r
98   {\r
99     /* First of all, store the location of the configuration data. */\r
100     AdcConfigPtr = ConfigPtr;\r
101 \r
102     // Connect interrupt to correct isr\r
103         ISR_INSTALL_ISR2("ADC",Adc_GroupConversionComplete,IRQ_TYPE_ATD0,6,0);\r
104 \r
105 \r
106         ATD0CTL2   = BM_ADPU | BM_AFFC | BM_ASCIE;      /* power enable, Fast Flag Clear, irq enable*/\r
107     ATD0CTL3   = 0x03;  /* 8 conversions per sequence default, freeze enable */\r
108 \r
109     ATD0CTL4   = (ConfigPtr->hwConfigPtr->resolution << 7) |\r
110                      (ConfigPtr->hwConfigPtr->convTime << 5) |\r
111                       ConfigPtr->hwConfigPtr->adcPrescale;\r
112 \r
113     for (group = 0; group < ADC_NBR_OF_GROUPS; group++)\r
114     {\r
115       /* ADC307. */\r
116       ConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;\r
117     }\r
118 \r
119     /* Move on to INIT state. */\r
120     adcState = ADC_INIT;\r
121     returnValue = E_OK;\r
122   }\r
123   else\r
124   {\r
125     returnValue = E_NOT_OK;\r
126   }\r
127 \r
128   return (returnValue);\r
129 }\r
130 \r
131 Std_ReturnType Adc_SetupResultBuffer (Adc_GroupType group, Adc_ValueGroupType *bufferPtr)\r
132 {\r
133   Std_ReturnType returnValue;\r
134 \r
135   /* Check for development errors. */\r
136   if (E_OK == Adc_CheckSetupResultBuffer (AdcConfigPtr, group))\r
137   {\r
138     AdcConfigPtr->groupConfigPtr[group].status->resultBufferPtr = bufferPtr;\r
139     returnValue = E_OK;\r
140   }\r
141   else\r
142   {\r
143     /* An error have been raised from Adc_CheckSetupResultBuffer(). */\r
144     returnValue = E_NOT_OK;\r
145   }\r
146 \r
147   return (returnValue);\r
148 }\r
149 \r
150 #if (ADC_READ_GROUP_API == STD_ON)\r
151 Std_ReturnType Adc_ReadGroup (Adc_GroupType group, Adc_ValueGroupType *dataBufferPtr)\r
152 {\r
153   Std_ReturnType returnValue;\r
154   Adc_ChannelType channel;\r
155 \r
156   if (E_OK == Adc_CheckReadGroup (adcState, AdcConfigPtr, group))\r
157   {\r
158     if ((ADC_CONV_MODE_CONTINUOUS == AdcConfigPtr->groupConfigPtr[group].conversionMode) &&\r
159          ((ADC_STREAM_COMPLETED    == AdcConfigPtr->groupConfigPtr[group].status->groupStatus) ||\r
160           (ADC_COMPLETED           == AdcConfigPtr->groupConfigPtr[group].status->groupStatus)))\r
161     {\r
162       /* ADC329, ADC331. */\r
163       AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;\r
164       returnValue = E_OK;\r
165     }\r
166     else if ((ADC_CONV_MODE_ONESHOT == AdcConfigPtr->groupConfigPtr[group].conversionMode) &&\r
167              (ADC_STREAM_COMPLETED  == AdcConfigPtr->groupConfigPtr[group].status->groupStatus))\r
168     {\r
169       /* ADC330. */\r
170       AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;\r
171 \r
172       returnValue = E_OK;\r
173     }\r
174     else\r
175     {\r
176       /* Keep status. */\r
177       returnValue = E_OK;\r
178     }\r
179 \r
180     if (E_OK == returnValue)\r
181     {\r
182       /* Copy the result to application buffer. */\r
183       for (channel = 0; channel < AdcConfigPtr->groupConfigPtr[group].numberOfChannels; channel++)\r
184       {\r
185         dataBufferPtr[channel] = AdcConfigPtr->groupConfigPtr[group].resultBuffer[channel];\r
186       }\r
187     }\r
188   }\r
189   else\r
190   {\r
191     /* An error have been raised from Adc_CheckReadGroup(). */\r
192     returnValue = E_NOT_OK;\r
193   }\r
194 \r
195   return (returnValue);\r
196 }\r
197 #endif\r
198 \r
199 static void Adc_GroupConversionComplete (void)\r
200 {\r
201   uint8 index;\r
202   Adc_GroupDefType *groupPtr = NULL;\r
203   /* Clear SCF flag. Not needed if AFFC is set but better to always do it  */\r
204   ATD0STAT0 = SCF;\r
205 \r
206   // Check which group is busy, only one is allowed to be busy at a time in a hw unit\r
207   for (index = 0; index < ADC_NBR_OF_GROUPS; index++)\r
208   {\r
209           if(AdcConfigPtr->groupConfigPtr[index].status->groupStatus == ADC_BUSY)\r
210           {\r
211                   groupPtr = (Adc_GroupDefType *)&AdcConfigPtr->groupConfigPtr[index];\r
212                   break;\r
213           }\r
214   }\r
215   if(groupPtr != NULL)\r
216   {\r
217           // Read hw buffer,\r
218           volatile uint16_t *ptr = &ATD0DR0;\r
219           for(index=0; index<groupPtr->numberOfChannels; index++)\r
220           {\r
221                   groupPtr->resultBuffer[index] = *(ptr + groupPtr->channelList[index]);\r
222           }\r
223 \r
224           /* Sample completed. */\r
225           groupPtr->status->groupStatus = ADC_STREAM_COMPLETED;\r
226 \r
227           /* Call notification if enabled. */\r
228         #if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)\r
229           if (groupPtr->status->notifictionEnable && groupPtr->groupCallback != NULL)\r
230           {\r
231                   groupPtr->groupCallback();\r
232           }\r
233         #endif\r
234   }\r
235 }\r
236 \r
237 #if (ADC_ENABLE_START_STOP_GROUP_API == STD_ON)\r
238 void Adc_StartGroupConversion (Adc_GroupType group)\r
239 {\r
240   /* Run development error check. */\r
241   if (E_OK == Adc_CheckStartGroupConversion (adcState, AdcConfigPtr, group))\r
242   {\r
243     /* Set single scan enable bit if this group is one shot. */\r
244     if (AdcConfigPtr->groupConfigPtr[group].conversionMode == ADC_CONV_MODE_ONESHOT)\r
245     {\r
246            /* Start next AD conversion. */\r
247            ATD0CTL5 = BM_DJM | BM_MULT; /* 10010000 Right Justified,unsigned */\r
248                                                                 /* No SCAN/MULT/AD0 start select */\r
249       /* Set group state to BUSY. */\r
250       AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;\r
251     }\r
252     else\r
253     {\r
254         // Continous mode\r
255            /* Start AD conversion. */\r
256            ATD0CTL5 = BM_DJM | BM_MULT | BM_SCAN; /* 10010000 Right Justified,unsigned */\r
257                                                                           /* SCAN/MULT/AD0 start select */\r
258        /* Set group state to BUSY. */\r
259        AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;\r
260     }\r
261   }\r
262 }\r
263 \r
264 void Adc_StopGroupConversion (Adc_GroupType group)\r
265 {\r
266   /* Run development error check. */\r
267   if (E_OK == Adc_CheckStopGroupConversion (adcState, AdcConfigPtr, group))\r
268   {\r
269            ATD0CTL3 = 0x03; /* Hard write to stop current conversion */\r
270   }\r
271   else\r
272   {\r
273         /* Error have been set within Adc_CheckStartGroupConversion(). */\r
274   }\r
275 }\r
276 #endif\r
277 \r
278 #if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)\r
279 void Adc_EnableGroupNotification (Adc_GroupType group)\r
280 {\r
281         Adc_EnableInternalGroupNotification(adcState, AdcConfigPtr, group);\r
282 }\r
283 \r
284 void Adc_DisableGroupNotification (Adc_GroupType group)\r
285 {\r
286         Adc_InternalDisableGroupNotification(adcState, AdcConfigPtr, group);\r
287 }\r
288 #endif\r
289 \r
290 Adc_StatusType Adc_GetGroupStatus (Adc_GroupType group)\r
291 {\r
292         return Adc_InternalGetGroupStatus(adcState, AdcConfigPtr, group);\r
293 }\r