-/* Copyright (C) 2012-2013 Czech Technical University in Prague
+/* Copyright (C) 2012-2013, 2015 Czech Technical University in Prague
*
* Authors:
* - Michal Horn
*/
-#include "drv/adc.h"
+#include "drv/drv.h"
+#include "drv/port.h"
+#include "os/portmacro.h"
-// Binary semaphore for ADC1 GRP1 conversion (AIN)
-xSemaphoreHandle adcSemaphore_ADC1GRP1;
-// Binary semaphore for ADC2 GRP1 conversion (HOUT-IFBK)
-xSemaphoreHandle adcSemaphore_ADC2GRP1;
+// Binary semaphores for finish notifications
+static xSemaphoreHandle sem[2][2];
-// Mutex for AIN read control
-xSemaphoreHandle adcMutex_ADC;
-// Mutex for HOUTIFBK control
-xSemaphoreHandle adcMutex_HOUTIFBK;
+// Mutex for two ADCs
+xSemaphoreHandle mutex[2];
void drv_adc_init()
{
- // Create semaphores
- vSemaphoreCreateBinary(adcSemaphore_ADC1GRP1);
- xSemaphoreTake(adcSemaphore_ADC1GRP1, 0);
- vSemaphoreCreateBinary(adcSemaphore_ADC2GRP1);
- xSemaphoreTake(adcSemaphore_ADC2GRP1, 0);
-
- adcMutex_ADC = xSemaphoreCreateMutex();
- adcMutex_HOUTIFBK = xSemaphoreCreateMutex();
-
- // Low level init
- adcInit();
+ int adc, grp;
+
+ for (adc = 0; adc < 2; adc++) {
+ for (grp = 0; grp < 2; grp++) {
+ vSemaphoreCreateBinary(sem[adc][grp]);
+ xSemaphoreTake(sem[adc][grp], 0);
+ }
+ mutex[adc] = xSemaphoreCreateMutex();
+ }
+ // Low level init
+ adcInit();
}
*/
void adcNotification(adcBASE_t *adc, uint32_t group)
{
- if(adcIsConversionComplete(adc, group) == ADC_CONVERSION_IS_FINISHED) {
-
- // ADC1
- if(adc == adcREG1) {
- switch(group) {
- case adcGROUP0:
- // Group0 is unused on RPP
- break;
- case adcGROUP1:
- // According to FreeRTOS documentation second parameter is
- // optional (and can be set to NULL) from FreeRTOS
- // V7.3.0. We are using 7.0.2. I confirmed this in the
- // source code: src/os/queue.c line 821. - Carlos
- {
- signed portBASE_TYPE dummy;
- xSemaphoreGiveFromISR(adcSemaphore_ADC1GRP1, &dummy);
- }
- break;
- default:
- // Group2 is unused on RPP
- break;
- }
- // ADC2
- } else {
- switch(group) {
- case adcGROUP0:
- // Group0 is unused on RPP
- break;
- case adcGROUP1:
- {
- signed portBASE_TYPE dummy;
- xSemaphoreGiveFromISR(adcSemaphore_ADC2GRP1, &dummy);
- }
- break;
- default:
- // Group2 is unused on RPP
- break;
- }
- }
- }
+ if (adcIsConversionComplete(adc, group) == ADC_CONVERSION_IS_FINISHED) {
+ int adc_idx = (adc == adcREG1) ? 0 : 1;
+ int grp_idx = (group == adcGROUP1) ? 0 : 1;
+ portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
+
+ xSemaphoreGiveFromISR(sem[adc_idx][grp_idx], &xHigherPriorityTaskWoken);
+ portYIELD_FROM_ISR(xHigherPriorityTaskWoken); /* Cause context switch after return from interrupt */
+ }
}
uint32_t drv_adc_generic_read(adcBASE_t *adc, uint32_t group,
- xSemaphoreHandle adcSemaphore, adcData_t* data)
+ adcData_t *data)
{
- // Calibrate
- adcCalibration(adc);
- adcMidPointCalibration(adc);
+ int adc_idx = (adc == adcREG1) ? 0 : 1;
+ int grp_idx = (group == adcGROUP1) ? 0 : 1;
- // Start conversion
- adcEnableNotification(adc, group);
- adcStartConversion(adc, group);
+ /* Note: Thread safety of rpp_adc_update depends on this! */
+ xSemaphoreTake(mutex[adc_idx], portMAX_DELAY);
- // Wait for conversion to complete
- xSemaphoreTake(adcSemaphore, portMAX_DELAY);
- adcDisableNotification(adc, group);
+ // Calibrate
+ adcCalibration(adc);
+ adcMidPointCalibration(adc);
- // Get data
- uint32_t channels = adcGetData(adc, group, data);
+ // Start conversion
+ adcEnableNotification(adc, group);
+ adcStartConversion(adc, group);
- // Check if memory overrun
- if(adcIsFifoFull(adc, group) == ADC_FIFO_OVERFLOW) {
- // FIXME Should report somehow.
- adcResetFiFo(adc, group);
- }
+ // Wait for conversion to complete
+ xSemaphoreTake(sem[adc_idx][grp_idx], portMAX_DELAY);
+ adcDisableNotification(adc, group);
- return channels;
-}
+ // Get data
+ uint32_t channels = adcGetData(adc, group, data);
+ // Check if memory overrun
+ if (adcIsFifoFull(adc, group) == ADC_FIFO_OVERFLOW)
+ // FIXME Should report somehow.
+ adcResetFiFo(adc, group);
-uint32_t drv_adc_read_adc(adcData_t* data)
-{
- xSemaphoreTake(adcMutex_ADC, portMAX_DELAY);
- uint32_t result = drv_adc_generic_read(
- adcREG1,
- adcGROUP1,
- adcSemaphore_ADC1GRP1,
- data
- );
- xSemaphoreGive(adcMutex_ADC);
- return result;
+ xSemaphoreGive(mutex[adc_idx]);
+
+ return channels;
}
-uint32_t drv_adc_read_houtifbk(adcData_t* data)
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+int8_t port_adc_get(const struct port_desc *port, void *values, size_t size)
{
- xSemaphoreTake(adcMutex_HOUTIFBK, portMAX_DELAY);
- uint32_t result = drv_adc_generic_read(
- adcREG2,
- adcGROUP1,
- adcSemaphore_ADC2GRP1,
- data
- );
- xSemaphoreGive(adcMutex_HOUTIFBK);
- return result;
-}
+ uint32_t i;
+ adcData_t data[ADC_MAX_CHANNELS];
+ int count = MIN(port->numchn, size/sizeof(uint16_t));
+ uint16_t *adcval = values;
-uint32_t adc_get_port_val(uint32_t* config, uint32_t num_channels,
- uint32_t* values) {
- uint32_t i;
- adcBASE_t* adcReg = (adcBASE_t *)config[0];
- uint32_t adcGroup = config[1];
- uint32_t adcSemaphore = config[2];
- adcData_t data[ADC_MAX_CHANNELS];
-
- drv_adc_generic_read(
- adcReg,
- adcGroup,
- (adcSemaphore == 1) ? adcSemaphore_ADC1GRP1 : adcSemaphore_ADC2GRP1,
+ assert(port->bpch == 16);
+ assert(size % sizeof(uint16_t) == 0);
+
+ drv_adc_generic_read(
+ port->cfg.adc.reg,
+ port->cfg.adc.group,
data
- );
+ );
- for (i = 0; i < num_channels; i++) {
- values[i] = data[i].value;
- values[i+num_channels] = data[i].id;
- }
+ for (i = 0; i < count; i++)
+ adcval[i] = data[i].value;
- return 0;
+ return 0;
}
-