1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * o Redistributions of source code must retain the above copyright notice, this list
9  *   of conditions and the following disclaimer.
10  *
11  * o Redistributions in binary form must reproduce the above copyright notice, this
12  *   list of conditions and the following disclaimer in the documentation and/or
13  *   other materials provided with the distribution.
14  *
15  * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
16  *   contributors may be used to endorse or promote products derived from this
17  *   software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "adc_imx6sx.h"
32 
33 /*******************************************************************************
34  * Code
35  ******************************************************************************/
36 
37 /*FUNCTION**********************************************************************
38  *
39  * Function Name : ADC_Init
40  * Description   : Initialize ADC to reset state and initialize with initialize
41  *                 structure.
42  *
43  *END**************************************************************************/
ADC_Init(ADC_Type * base,const adc_init_config_t * initConfig)44 void ADC_Init(ADC_Type* base, const adc_init_config_t* initConfig)
45 {
46     assert(initConfig);
47 
48     /* Reset ADC register to its default value. */
49     ADC_Deinit(base);
50 
51     /* Set hardware average function and number. */
52     if (initConfig->averageNumber != adcAvgNumNone)
53     {
54         ADC_GC_REG(base) |= ADC_GC_AVGE_MASK;
55         ADC_CFG_REG(base) |= ADC_CFG_AVGS(initConfig->averageNumber);
56     }
57 
58     /* Set resolution mode. */
59     ADC_CFG_REG(base) |= ADC_CFG_MODE(initConfig->resolutionMode);
60 
61     /* Set clock source. */
62     ADC_SetClockSource(base, initConfig->clockSource, initConfig->divideRatio);
63 }
64 
65 /*FUNCTION**********************************************************************
66  *
67  * Function Name : ADC_Deinit
68  * Description   : This function reset ADC module register content to its
69  *                 default value.
70  *
71  *END**************************************************************************/
ADC_Deinit(ADC_Type * base)72 void ADC_Deinit(ADC_Type* base)
73 {
74     /* Reset ADC Module Register content to default value */
75     ADC_HC0_REG(base) = ADC_HC0_ADCH_MASK;
76     ADC_HC1_REG(base) = ADC_HC1_ADCH_MASK;
77     ADC_R0_REG(base)  = 0x0;
78     ADC_R1_REG(base)  = 0x0;
79     ADC_CFG_REG(base) = ADC_CFG_ADSTS(2);
80     ADC_GC_REG(base)  = 0x0;
81     ADC_GS_REG(base)  = ADC_GS_CALF_MASK | ADC_GS_AWKST_MASK;
82     ADC_CV_REG(base)  = 0x0;
83     ADC_OFS_REG(base) = 0x0;
84     ADC_CAL_REG(base) = 0x0;
85 }
86 
87 /*FUNCTION**********************************************************************
88  *
89  * Function Name : ADC_SetConvertResultOverwrite
90  * Description   : Enable or disable ADC overwrite conversion result register.
91  *
92  *END**************************************************************************/
ADC_SetConvertResultOverwrite(ADC_Type * base,bool enable)93 void ADC_SetConvertResultOverwrite(ADC_Type* base, bool enable)
94 {
95     if(enable)
96         ADC_CFG_REG(base) |= ADC_CFG_OVWREN_MASK;
97     else
98         ADC_CFG_REG(base) &= ~ADC_CFG_OVWREN_MASK;
99 }
100 
101 /*FUNCTION**********************************************************************
102  *
103  * Function Name : ADC_SetConvertTrigMode
104  * Description   : This function is used to set conversion trigger mode.
105  *
106  *END**************************************************************************/
ADC_SetConvertTrigMode(ADC_Type * base,uint8_t mode)107 void ADC_SetConvertTrigMode(ADC_Type* base, uint8_t mode)
108 {
109     assert(mode <= adcHardwareTrigger);
110 
111     if(mode == adcHardwareTrigger)
112         ADC_CFG_REG(base) |= ADC_CFG_ADTRG_MASK;
113     else
114         ADC_CFG_REG(base) &= ~ADC_CFG_ADTRG_MASK;
115 }
116 
117 /*FUNCTION**********************************************************************
118  *
119  * Function Name : ADC_SetConvertSpeed
120  * Description   : This function is used to set conversion speed mode.
121  *
122  *END**************************************************************************/
ADC_SetConvertSpeed(ADC_Type * base,uint8_t mode)123 void ADC_SetConvertSpeed(ADC_Type* base, uint8_t mode)
124 {
125     assert(mode <= adcHighSpeed);
126 
127     if(mode == adcHighSpeed)
128         ADC_CFG_REG(base) |= ADC_CFG_ADHSC_MASK;
129     else
130         ADC_CFG_REG(base) &= ~ADC_CFG_ADHSC_MASK;
131 }
132 
133 /*FUNCTION**********************************************************************
134  *
135  * Function Name : ADC_SetSampleTimeDuration
136  * Description   : This function is used to set sample time duration.
137  *
138  *END**************************************************************************/
ADC_SetSampleTimeDuration(ADC_Type * base,uint8_t duration)139 void ADC_SetSampleTimeDuration(ADC_Type* base, uint8_t duration)
140 {
141     assert(duration <= adcSamplePeriodClock24);
142 
143     switch(duration)
144     {
145         case adcSamplePeriodClock2:
146             ADC_CFG_REG(base) &= ~ADC_CFG_ADLSMP_MASK;
147             ADC_CFG_REG(base) = (ADC_CFG_REG(base) & (~ADC_CFG_ADSTS_MASK)) |
148                                 ADC_CFG_ADSTS(0U);
149             break;
150 
151         case adcSamplePeriodClock4:
152             ADC_CFG_REG(base) &= ~ADC_CFG_ADLSMP_MASK;
153             ADC_CFG_REG(base) = (ADC_CFG_REG(base) & (~ADC_CFG_ADSTS_MASK)) |
154                                 ADC_CFG_ADSTS(1U);
155             break;
156 
157         case adcSamplePeriodClock6:
158             ADC_CFG_REG(base) &= ~ADC_CFG_ADLSMP_MASK;
159             ADC_CFG_REG(base) = (ADC_CFG_REG(base) & (~ADC_CFG_ADSTS_MASK)) |
160                                 ADC_CFG_ADSTS(2U);
161             break;
162 
163         case adcSamplePeriodClock8:
164             ADC_CFG_REG(base) &= ~ADC_CFG_ADLSMP_MASK;
165             ADC_CFG_REG(base) = (ADC_CFG_REG(base) & (~ADC_CFG_ADSTS_MASK)) |
166                                 ADC_CFG_ADSTS(3U);
167             break;
168 
169         case adcSamplePeriodClock12:
170             ADC_CFG_REG(base) |= ADC_CFG_ADLSMP_MASK;
171             ADC_CFG_REG(base) = (ADC_CFG_REG(base) & (~ADC_CFG_ADSTS_MASK)) |
172                                 ADC_CFG_ADSTS(0U);
173             break;
174 
175         case adcSamplePeriodClock16:
176             ADC_CFG_REG(base) |= ADC_CFG_ADLSMP_MASK;
177             ADC_CFG_REG(base) = (ADC_CFG_REG(base) & (~ADC_CFG_ADSTS_MASK)) |
178                                 ADC_CFG_ADSTS(1U);
179             break;
180 
181         case adcSamplePeriodClock20:
182             ADC_CFG_REG(base) |= ADC_CFG_ADLSMP_MASK;
183             ADC_CFG_REG(base) = (ADC_CFG_REG(base) & (~ADC_CFG_ADSTS_MASK)) |
184                                 ADC_CFG_ADSTS(2U);
185             break;
186 
187         case adcSamplePeriodClock24:
188             ADC_CFG_REG(base) |= ADC_CFG_ADLSMP_MASK;
189             ADC_CFG_REG(base) = (ADC_CFG_REG(base) & (~ADC_CFG_ADSTS_MASK)) |
190                                 ADC_CFG_ADSTS(3U);
191             break;
192     }
193 }
194 
195 /*FUNCTION**********************************************************************
196  *
197  * Function Name : ADC_SetPowerMode
198  * Description   : This function is used to set power mode.
199  *
200  *END**************************************************************************/
ADC_SetPowerMode(ADC_Type * base,uint8_t powerMode)201 void ADC_SetPowerMode(ADC_Type* base, uint8_t powerMode)
202 {
203     assert(powerMode <= adcLowPowerMode);
204 
205     if(powerMode == adcLowPowerMode)
206         ADC_CFG_REG(base) |= ADC_CFG_ADLPC_MASK;
207     else
208         ADC_CFG_REG(base) &= ~ADC_CFG_ADLPC_MASK;
209 }
210 
211 /*FUNCTION**********************************************************************
212  *
213  * Function Name : ADC_SetClockSource
214  * Description   : This function is used to set ADC clock source.
215  *
216  *END**************************************************************************/
ADC_SetClockSource(ADC_Type * base,uint8_t source,uint8_t div)217 void ADC_SetClockSource(ADC_Type* base, uint8_t source, uint8_t div)
218 {
219     assert(source <= adcAsynClock);
220     assert(div <= adcInputClockDiv8);
221 
222     ADC_CFG_REG(base) = (ADC_CFG_REG(base) & (~ADC_CFG_ADIV_MASK)) |
223                         ADC_CFG_ADIV(div);
224     ADC_CFG_REG(base) = (ADC_CFG_REG(base) & (~ADC_CFG_ADICLK_MASK)) |
225                         ADC_CFG_ADICLK(source);
226 }
227 
228 /*FUNCTION**********************************************************************
229  *
230  * Function Name : ADC_SetAsynClockOutput
231  * Description   : This function is used to enable asynchronous clock source output
232  *                 regardless of the state of ADC.
233  *
234  *END**************************************************************************/
ADC_SetAsynClockOutput(ADC_Type * base,bool enable)235 void ADC_SetAsynClockOutput(ADC_Type* base, bool enable)
236 {
237     if(enable)
238         ADC_GC_REG(base) |= ADC_GC_ADACKEN_MASK;
239     else
240         ADC_GC_REG(base) &= ~ADC_GC_ADACKEN_MASK;
241 }
242 
243 /*FUNCTION**********************************************************************
244  *
245  * Function Name : ADC_SetCalibration
246  * Description   : Enable or disable calibration function.
247  *
248  *END**************************************************************************/
ADC_SetCalibration(ADC_Type * base,bool enable)249 void ADC_SetCalibration(ADC_Type* base, bool enable)
250 {
251     if(enable)
252         ADC_GC_REG(base) |= ADC_GC_CAL_MASK;
253     else
254         ADC_GC_REG(base) &= ~ADC_GC_CAL_MASK;
255 }
256 
257 /*FUNCTION**********************************************************************
258  *
259  * Function Name : ADC_SetConvertCmd
260  * Description   : Enable continuous conversion and start a conversion on target channel.
261  *        This function is only used for software trigger mode. If configured as
262  *        hardware trigger mode, this function just enable continuous conversion
263  *        and not start the conversion.
264  *
265  *END**************************************************************************/
ADC_SetConvertCmd(ADC_Type * base,uint8_t channel,bool enable)266 void ADC_SetConvertCmd(ADC_Type* base, uint8_t channel, bool enable)
267 {
268     uint8_t triggerMode;
269 
270     /* Enable continuous conversion. */
271     if(enable)
272     {
273         ADC_GC_REG(base) |= ADC_GC_ADCO_MASK;
274         /* Start the conversion. */
275         triggerMode = ADC_GetConvertTrigMode(base);
276         if(triggerMode == adcSoftwareTrigger)
277             ADC_HC0_REG(base) = (ADC_HC0_REG(base) & (~ADC_HC0_ADCH_MASK)) |
278                                 ADC_HC0_ADCH(channel);
279         else /* Just set the channel. */
280             ADC_HC1_REG(base) = (ADC_HC1_REG(base) & (~ADC_HC1_ADCH_MASK)) |
281                                 ADC_HC1_ADCH(channel);
282     }
283     else
284         ADC_GC_REG(base) &= ~ADC_GC_ADCO_MASK;
285 }
286 
287 /*FUNCTION**********************************************************************
288  *
289  * Function Name : ADC_TriggerSingleConvert
290  * Description   : Enable single conversion and trigger single time conversion
291  *                 on target imput channel. If configured as hardware trigger
292  *                 mode, this function just set input channel and not start a
293  *                 conversion.
294  *
295  *END**************************************************************************/
ADC_TriggerSingleConvert(ADC_Type * base,uint8_t channel)296 void ADC_TriggerSingleConvert(ADC_Type* base, uint8_t channel)
297 {
298     uint8_t triggerMode;
299 
300     /* Enable single conversion. */
301     ADC_GC_REG(base) &= ~ADC_GC_ADCO_MASK;
302     /* Start the conversion. */
303     triggerMode = ADC_GetConvertTrigMode(base);
304     if(triggerMode == adcSoftwareTrigger)
305         ADC_HC0_REG(base) = (ADC_HC0_REG(base) & (~ADC_HC0_ADCH_MASK)) |
306                             ADC_HC0_ADCH(channel);
307     else /* Just set the channel. */
308         ADC_HC1_REG(base) = (ADC_HC1_REG(base) & (~ADC_HC1_ADCH_MASK)) |
309                             ADC_HC1_ADCH(channel);
310 }
311 
312 /*FUNCTION**********************************************************************
313  *
314  * Function Name : ADC_SetAverageNum
315  * Description   : This function is used to enable hardware aaverage function
316  *                 and set hardware average number. If avgNum is equal to
317  *                 adcAvgNumNone, it means disable hardware average function.
318  *
319  *END**************************************************************************/
ADC_SetAverageNum(ADC_Type * base,uint8_t avgNum)320 void ADC_SetAverageNum(ADC_Type* base, uint8_t avgNum)
321 {
322     assert(avgNum <= adcAvgNumNone);
323 
324     if(avgNum != adcAvgNumNone)
325     {
326         /* Enable hardware average function. */
327         ADC_GC_REG(base) |= ADC_GC_AVGE_MASK;
328         /* Set hardware average number. */
329         ADC_CFG_REG(base) = (ADC_CFG_REG(base) & (~ADC_CFG_AVGS_MASK)) |
330                             ADC_CFG_AVGS(avgNum);
331     }
332     else
333     {
334         /* Disable hardware average function. */
335         ADC_GC_REG(base) &= ~ADC_GC_AVGE_MASK;
336     }
337 }
338 
339 /*FUNCTION**********************************************************************
340  *
341  * Function Name : ADC_StopConvert
342  * Description   : This function is used to stop all conversions.
343  *
344  *END**************************************************************************/
ADC_StopConvert(ADC_Type * base)345 void ADC_StopConvert(ADC_Type* base)
346 {
347     uint8_t triggerMode;
348 
349     triggerMode = ADC_GetConvertTrigMode(base);
350     /* According trigger mode to set specific register. */
351     if(triggerMode == adcSoftwareTrigger)
352         ADC_HC0_REG(base) |= ADC_HC0_ADCH_MASK;
353     else
354         ADC_HC1_REG(base) |= ADC_HC1_ADCH_MASK;
355 }
356 
357 /*FUNCTION**********************************************************************
358  *
359  * Function Name : ADC_GetConvertResult
360  * Description   : This function is used to get conversion result.
361  *
362  *END**************************************************************************/
ADC_GetConvertResult(ADC_Type * base)363 uint16_t ADC_GetConvertResult(ADC_Type* base)
364 {
365     uint8_t triggerMode;
366 
367     triggerMode = ADC_GetConvertTrigMode(base);
368     if(triggerMode == adcSoftwareTrigger)
369         return (uint16_t)((ADC_R0_REG(base) & ADC_R0_D_MASK) >> ADC_R0_D_SHIFT);
370     else
371         return (uint16_t)((ADC_R1_REG(base) & ADC_R1_D_MASK) >> ADC_R1_D_SHIFT);
372 }
373 
374 /*FUNCTION**********************************************************************
375  *
376  * Function Name : ADC_SetCmpMode
377  * Description   : This function is used to enable compare function
378  *                 and set comparer mode.
379  *
380  *END**************************************************************************/
ADC_SetCmpMode(ADC_Type * base,uint8_t cmpMode,uint16_t cmpVal1,uint16_t cmpVal2)381 void ADC_SetCmpMode(ADC_Type* base, uint8_t cmpMode, uint16_t cmpVal1, uint16_t cmpVal2)
382 {
383     assert(cmpMode <= adcCmpModeDisable);
384 
385     switch(cmpMode)
386     {
387         case adcCmpModeLessThanCmpVal1:
388             ADC_GC_REG(base) |= ADC_GC_ACFE_MASK;
389             ADC_GC_REG(base) &= ~(ADC_GC_ACFGT_MASK | ADC_GC_ACREN_MASK);
390             ADC_CV_REG(base) = (ADC_CV_REG(base) & (~ADC_CV_CV1_MASK)) | ADC_CV_CV1(cmpVal1);
391             break;
392 
393         case adcCmpModeGreaterThanCmpVal1:
394             ADC_GC_REG(base) |= ADC_GC_ACFE_MASK;
395             ADC_GC_REG(base) = (ADC_GC_REG(base) | ADC_GC_ACFGT_MASK) & (~ADC_GC_ACREN_MASK);
396             ADC_CV_REG(base) = (ADC_CV_REG(base) & (~ADC_CV_CV1_MASK)) | ADC_CV_CV1(cmpVal1);
397             break;
398 
399         case adcCmpModeOutRangNotInclusive:
400             ADC_GC_REG(base) |= ADC_GC_ACFE_MASK;
401             ADC_GC_REG(base) = (ADC_GC_REG(base) | ADC_GC_ACREN_MASK) & (~ADC_GC_ACFGT_MASK);
402             if(cmpVal1 <= cmpVal2)
403             {
404                 ADC_CV_REG(base) = (ADC_CV_REG(base) & (~ADC_CV_CV1_MASK)) | ADC_CV_CV1(cmpVal1);
405                 ADC_CV_REG(base) = (ADC_CV_REG(base) & (~ADC_CV_CV2_MASK)) | ADC_CV_CV2(cmpVal2);
406             }
407             break;
408 
409         case adcCmpModeInRangNotInclusive:
410             ADC_GC_REG(base) |= ADC_GC_ACFE_MASK;
411             ADC_GC_REG(base) = (ADC_GC_REG(base) | ADC_GC_ACREN_MASK) & (~ADC_GC_ACFGT_MASK);
412             if(cmpVal1 > cmpVal2)
413             {
414                 ADC_CV_REG(base) = (ADC_CV_REG(base) & (~ADC_CV_CV1_MASK)) | ADC_CV_CV1(cmpVal1);
415                 ADC_CV_REG(base) = (ADC_CV_REG(base) & (~ADC_CV_CV2_MASK)) | ADC_CV_CV2(cmpVal2);
416             }
417             break;
418 
419         case adcCmpModeInRangInclusive:
420             ADC_GC_REG(base) |= ADC_GC_ACFE_MASK;
421             ADC_GC_REG(base) |= ADC_GC_ACREN_MASK | ADC_GC_ACFGT_MASK;
422             if(cmpVal1 <= cmpVal2)
423             {
424                 ADC_CV_REG(base) = (ADC_CV_REG(base) & (~ADC_CV_CV1_MASK)) | ADC_CV_CV1(cmpVal1);
425                 ADC_CV_REG(base) = (ADC_CV_REG(base) & (~ADC_CV_CV2_MASK)) | ADC_CV_CV2(cmpVal2);
426             }
427             break;
428 
429         case adcCmpModeOutRangInclusive:
430             ADC_GC_REG(base) |= ADC_GC_ACFE_MASK;
431             ADC_GC_REG(base) |= ADC_GC_ACREN_MASK | ADC_GC_ACFGT_MASK;
432             if(cmpVal1 > cmpVal2)
433             {
434                 ADC_CV_REG(base) = (ADC_CV_REG(base) & (~ADC_CV_CV1_MASK)) | ADC_CV_CV1(cmpVal1);
435                 ADC_CV_REG(base) = (ADC_CV_REG(base) & (~ADC_CV_CV2_MASK)) | ADC_CV_CV2(cmpVal2);
436             }
437             break;
438 
439         case adcCmpModeDisable:
440             ADC_GC_REG(base) &= ~ADC_GC_ACFE_MASK;
441             break;
442     }
443 }
444 
445 /*FUNCTION**********************************************************************
446  *
447  * Function Name : ADC_SetCorrectionMode
448  * Description   : This function is used to set offset correct mode.
449  *
450  *END**************************************************************************/
ADC_SetCorrectionMode(ADC_Type * base,bool correctMode)451 void ADC_SetCorrectionMode(ADC_Type* base, bool correctMode)
452 {
453     if(correctMode)
454         ADC_OFS_REG(base) |= ADC_OFS_SIGN_MASK;
455     else
456         ADC_OFS_REG(base) &= ~ADC_OFS_SIGN_MASK;
457 }
458 
459 /*FUNCTION**********************************************************************
460  *
461  * Function Name : ADC_SetIntCmd
462  * Description   : Enables or disables ADC conversion complete interrupt request.
463  *
464  *END**************************************************************************/
ADC_SetIntCmd(ADC_Type * base,bool enable)465 void ADC_SetIntCmd(ADC_Type* base, bool enable)
466 {
467     uint8_t triggerMode;
468 
469     triggerMode = ADC_GetConvertTrigMode(base);
470     if(triggerMode == adcSoftwareTrigger)
471     {
472         if(enable)
473             ADC_HC0_REG(base) |= ADC_HC0_AIEN_MASK;
474         else
475             ADC_HC0_REG(base) &= ~ADC_HC0_AIEN_MASK;
476     }
477     else
478     {
479         if(enable)
480             ADC_HC1_REG(base) |= ADC_HC1_AIEN_MASK;
481         else
482             ADC_HC1_REG(base) &= ~ADC_HC1_AIEN_MASK;
483     }
484 }
485 
486 /*FUNCTION**********************************************************************
487  *
488  * Function Name : ADC_IsConvertComplete
489  * Description   : This function is used to get ADC conversion complete status.
490  *
491  *END**************************************************************************/
ADC_IsConvertComplete(ADC_Type * base)492 bool ADC_IsConvertComplete(ADC_Type* base)
493 {
494     uint8_t triggerMode;
495 
496     triggerMode = ADC_GetConvertTrigMode(base);
497     if(triggerMode == adcSoftwareTrigger)
498         return (bool)((ADC_HS_REG(base) & ADC_HS_COCO0_MASK) >> ADC_HS_COCO0_SHIFT);
499     else
500         return (bool)((ADC_HS_REG(base) & ADC_HS_COCO1_MASK) >> ADC_HS_COCO1_SHIFT);
501 }
502 
503 /*FUNCTION**********************************************************************
504  *
505  * Function Name : ADC_SetDmaCmd
506  * Description   : Enable or disable DMA request.
507  *
508  *END**************************************************************************/
ADC_SetDmaCmd(ADC_Type * base,bool enable)509 void ADC_SetDmaCmd(ADC_Type* base, bool enable)
510 {
511     if (enable)
512         ADC_GC_REG(base) |= ADC_GC_DMAEN_MASK;
513     else
514         ADC_GC_REG(base) &= ~ADC_GC_DMAEN_MASK;
515 }
516 
517 /*******************************************************************************
518  * EOF
519  ******************************************************************************/
520