]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blob - rpp/src/drv/adc.c
Fixed some minor and other mayor bugs. Changes simulation to static memory to avoid...
[pes-rpp/rpp-lib.git] / rpp / src / drv / adc.c
1 /* Copyright (C) 2012-2013 Czech Technical University in Prague
2  *
3  * Authors:
4  *     - Michal Horn
5  *     - Carlos Jenkins <carlos@jenkins.co.cr>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  * File : adc.c
21  * Abstract:
22  *     RPP driver implementation for ADC.
23  *
24  * References:
25  *     ti_drv_adc.c
26  */
27
28
29 #include "drv/adc.h"
30
31 // Binary semaphore for ADC1 GRP1 conversion (AIN)
32 xSemaphoreHandle adcSemaphore_ADC1GRP1;
33 // Binary semaphore for ADC2 GRP1 conversion (HOUT-IFBK)
34 xSemaphoreHandle adcSemaphore_ADC2GRP1;
35
36 // Mutex for AIN read control
37 xSemaphoreHandle adcMutex_AIN;
38 // Mutex for HOUTIFBK control
39 xSemaphoreHandle adcMutex_HOUTIFBK;
40
41 void drv_adc_init()
42 {
43     // Create semaphores
44     vSemaphoreCreateBinary(adcSemaphore_ADC1GRP1);
45     xSemaphoreTake(adcSemaphore_ADC1GRP1, 0);
46     vSemaphoreCreateBinary(adcSemaphore_ADC2GRP1);
47     xSemaphoreTake(adcSemaphore_ADC2GRP1, 0);
48
49     adcMutex_AIN       = xSemaphoreCreateMutex();
50     adcMutex_HOUTIFBK  = xSemaphoreCreateMutex();
51
52     // Low level init
53     adcInit();
54 }
55
56
57 /**
58  * ADC notification called by ADC conversion finished ISR.
59  *
60  * This procedure will just give semaphore.
61  *
62  *   @param[in] adc Pointer to ADC module:
63  *              - adcREG1: ADC1 module pointer
64  *              - adcREG2: ADC2 module pointer
65  *   @param[in] group Hardware group of ADC module:
66  *              - adcGROUP0: ADC event group
67  *              - adcGROUP1: ADC group 1
68  *              - adcGROUP2: ADC group 2
69  */
70 void adcNotification(adcBASE_t *adc, uint32_t group)
71 {
72     if(adcIsConversionComplete(adc, group) == ADC_CONVERSION_IS_FINISHED) {
73
74         // ADC1
75         if(adc == adcREG1) {
76             switch(group) {
77                 case adcGROUP0:
78                     // Group0 is unused on RPP
79                     break;
80                 case adcGROUP1:
81                     // According to FreeRTOS documentation second parameter is
82                     // optional (and can be set to NULL) from FreeRTOS
83                     // V7.3.0. We are using 7.0.2. I confirmed this in the
84                     // source code: src/os/queue.c line 821. - Carlos
85                     {
86                         signed portBASE_TYPE dummy;
87                         xSemaphoreGiveFromISR(adcSemaphore_ADC1GRP1, &dummy);
88                     }
89                     break;
90                 default:
91                     // Group2 is unused on RPP
92                     break;
93             }
94         // ADC2
95         } else {
96             switch(group) {
97                 case adcGROUP0:
98                     // Group0 is unused on RPP
99                     break;
100                 case adcGROUP1:
101                     {
102                         signed portBASE_TYPE dummy;
103                         xSemaphoreGiveFromISR(adcSemaphore_ADC2GRP1, &dummy);
104                     }
105                     break;
106                 default:
107                     // Group2 is unused on RPP
108                     break;
109             }
110         }
111     }
112 }
113
114
115 uint32_t drv_adc_generic_read(adcBASE_t *adc, uint32_t group,
116                                xSemaphoreHandle adcSemaphore, adcData_t* data)
117 {
118     // Calibrate
119     adcCalibration(adc);
120     adcMidPointCalibration(adc);
121
122     // Start conversion
123     adcEnableNotification(adc, group);
124     adcStartConversion(adc, group);
125
126     // Wait for conversion to complete
127     xSemaphoreTake(adcSemaphore, portMAX_DELAY);
128     adcDisableNotification(adc, group);
129
130     // Get data
131     uint32_t channels = adcGetData(adc, group, data);
132
133     // Check if memory overrun
134     if(adcIsFifoFull(adc, group) == ADC_FIFO_OVERFLOW) {
135         // FIXME Should report somehow.
136         adcResetFiFo(adc, group);
137     }
138
139     return channels;
140 }
141
142
143 uint32_t drv_adc_read_ain(adcData_t* data)
144 {
145     xSemaphoreTake(adcMutex_AIN, portMAX_DELAY);
146     uint32_t result = drv_adc_generic_read(
147                                 adcREG1,
148                                 adcGROUP1,
149                                 adcSemaphore_ADC1GRP1,
150                                 data
151                             );
152     xSemaphoreGive(adcMutex_AIN);
153     return result;
154 }
155
156 uint32_t drv_adc_read_houtifbk(adcData_t* data)
157 {
158     xSemaphoreTake(adcMutex_HOUTIFBK, portMAX_DELAY);
159     uint32_t result = drv_adc_generic_read(
160                                 adcREG2,
161                                 adcGROUP1,
162                                 adcSemaphore_ADC2GRP1,
163                                 data
164                             );
165     xSemaphoreGive(adcMutex_HOUTIFBK);
166     return result;
167 }
168
169 // FIXME make it work again
170 uint32_t adc_get_port_val(uint32_t* config, uint32_t num_channels,
171                            uint32_t* values) {
172     /*
173     uint32_t i;
174     adcBASE_t* adcReg = (adcBASE_t *)config[0];
175     uint32_t adcGroup = config[1];
176
177     adcData.adc_data = adc_data_origin;
178     adcData.ch_count = num_channels;
179     if (read_adc(adcReg, adcGroup) == 1)
180         return 1;
181
182     for (i = 0; i < num_channels; i++) {
183         values[i] = adcData.adc_data[i].value;
184         values[i+num_channels] = adcData.adc_data[i].id;
185     }
186     adcData.adc_data = NULL;
187     */
188     return 0;
189 }
190