]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blob - rpp/src/drv/adc.c
Make the RPP layer thread safe
[pes-rpp/rpp-lib.git] / rpp / src / drv / adc.c
1 /* Copyright (C) 2012-2013, 2015 Czech Technical University in Prague
2  *
3  * Authors:
4  *     - Michal Horn
5  *     - Carlos Jenkins <carlos@jenkins.co.cr>
6  *
7  * This document contains proprietary information belonging to Czech
8  * Technical University in Prague. Passing on and copying of this
9  * document, and communication of its contents is not permitted
10  * without prior written authorization.
11  *
12  * File : adc.c
13  * Abstract:
14  *     RPP driver implementation for ADC.
15  *
16  * References:
17  *     ti_drv_adc.c
18  */
19
20
21 #include "drv/drv.h"
22 #include "drv/port.h"
23 #include "os/portmacro.h"
24
25 // Binary semaphores for finish notifications
26 static xSemaphoreHandle sem[2][2];
27
28 // Mutex for two ADCs
29 xSemaphoreHandle mutex[2];
30
31 void drv_adc_init()
32 {
33         int adc, grp;
34
35         for (adc = 0; adc < 2; adc++) {
36                 for (grp = 0; grp < 2; grp++) {
37                         vSemaphoreCreateBinary(sem[adc][grp]);
38                         xSemaphoreTake(sem[adc][grp], 0);
39                 }
40                 mutex[adc] = xSemaphoreCreateMutex();
41         }
42         // Low level init
43         adcInit();
44 }
45
46
47 /**
48  * ADC notification called by ADC conversion finished ISR.
49  *
50  * This procedure will just give semaphore.
51  *
52  *   @param[in] adc Pointer to ADC module:
53  *              - adcREG1: ADC1 module pointer
54  *              - adcREG2: ADC2 module pointer
55  *   @param[in] group Hardware group of ADC module:
56  *              - adcGROUP0: ADC event group
57  *              - adcGROUP1: ADC group 1
58  *              - adcGROUP2: ADC group 2
59  */
60 void adcNotification(adcBASE_t *adc, uint32_t group)
61 {
62         if (adcIsConversionComplete(adc, group) == ADC_CONVERSION_IS_FINISHED) {
63                 int adc_idx = (adc == adcREG1) ? 0 : 1;
64                 int grp_idx = (group == adcGROUP1) ? 0 : 1;
65                 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
66
67                 xSemaphoreGiveFromISR(sem[adc_idx][grp_idx], &xHigherPriorityTaskWoken);
68                 portYIELD_FROM_ISR(xHigherPriorityTaskWoken); /* Cause context switch after return from interrupt */
69         }
70 }
71
72
73 uint32_t drv_adc_generic_read(adcBASE_t *adc, uint32_t group,
74                                                           adcData_t *data)
75 {
76         int adc_idx = (adc == adcREG1) ? 0 : 1;
77         int grp_idx = (group == adcGROUP1) ? 0 : 1;
78
79         /* Note: Thread safety of rpp_adc_update depends on this! */
80         xSemaphoreTake(mutex[adc_idx], portMAX_DELAY);
81
82         // Calibrate
83         adcCalibration(adc);
84         adcMidPointCalibration(adc);
85
86         // Start conversion
87         adcEnableNotification(adc, group);
88         adcStartConversion(adc, group);
89
90         // Wait for conversion to complete
91         xSemaphoreTake(sem[adc_idx][grp_idx], portMAX_DELAY);
92         adcDisableNotification(adc, group);
93
94         // Get data
95         uint32_t channels = adcGetData(adc, group, data);
96
97         // Check if memory overrun
98         if (adcIsFifoFull(adc, group) == ADC_FIFO_OVERFLOW)
99                 // FIXME Should report somehow.
100                 adcResetFiFo(adc, group);
101
102         xSemaphoreGive(mutex[adc_idx]);
103
104         return channels;
105 }
106
107 #define MIN(a,b) ((a) < (b) ? (a) : (b))
108
109 int8_t port_adc_get(const struct port_desc *port, void *values, size_t size)
110 {
111         uint32_t i;
112         adcData_t data[ADC_MAX_CHANNELS];
113         int count = MIN(port->numchn, size/sizeof(uint16_t));
114         uint16_t *adcval = values;
115
116         assert(port->bpch == 16);
117         assert(size % sizeof(uint16_t) == 0);
118
119         drv_adc_generic_read(
120                 port->cfg.adc.reg,
121                 port->cfg.adc.group,
122                 data
123                 );
124
125         for (i = 0; i < count; i++)
126                 adcval[i] = data[i].value;
127
128         return 0;
129 }