1 /* Copyright (C) 2012-2013, 2015 Czech Technical University in Prague
5 * - Carlos Jenkins <carlos@jenkins.co.cr>
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.
14 * RPP driver implementation for ADC.
23 #include "os/portmacro.h"
25 // Binary semaphores for finish notifications
26 static xSemaphoreHandle sem[2][2];
29 xSemaphoreHandle mutex[2];
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);
40 mutex[adc] = xSemaphoreCreateMutex();
48 * ADC notification called by ADC conversion finished ISR.
50 * This procedure will just give semaphore.
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
60 void adcNotification(adcBASE_t *adc, uint32_t group)
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;
67 xSemaphoreGiveFromISR(sem[adc_idx][grp_idx], &xHigherPriorityTaskWoken);
68 portYIELD_FROM_ISR(xHigherPriorityTaskWoken); /* Cause context switch after return from interrupt */
73 uint32_t drv_adc_generic_read(adcBASE_t *adc, uint32_t group,
76 int adc_idx = (adc == adcREG1) ? 0 : 1;
77 int grp_idx = (group == adcGROUP1) ? 0 : 1;
79 /* Note: Thread safety of rpp_adc_update depends on this! */
80 xSemaphoreTake(mutex[adc_idx], portMAX_DELAY);
84 adcMidPointCalibration(adc);
87 adcEnableNotification(adc, group);
88 adcStartConversion(adc, group);
90 // Wait for conversion to complete
91 xSemaphoreTake(sem[adc_idx][grp_idx], portMAX_DELAY);
92 adcDisableNotification(adc, group);
95 uint32_t channels = adcGetData(adc, group, data);
97 // Check if memory overrun
98 if (adcIsFifoFull(adc, group) == ADC_FIFO_OVERFLOW)
99 // FIXME Should report somehow.
100 adcResetFiFo(adc, group);
102 xSemaphoreGive(mutex[adc_idx]);
107 #define MIN(a,b) ((a) < (b) ? (a) : (b))
109 int8_t port_adc_get(const struct port_desc *port, void *values, size_t size)
112 adcData_t data[ADC_MAX_CHANNELS];
113 int count = MIN(port->numchn, size/sizeof(uint16_t));
114 uint16_t *adcval = values;
116 assert(port->bpch == 16);
117 assert(size % sizeof(uint16_t) == 0);
119 drv_adc_generic_read(
125 for (i = 0; i < count; i++)
126 adcval[i] = data[i].value;