diff --git a/units/adc/_adc_init.c b/units/adc/_adc_init.c index 5f2d9e4..6ce4b31 100644 --- a/units/adc/_adc_init.c +++ b/units/adc/_adc_init.c @@ -30,7 +30,8 @@ error_t UADC_preInit(Unit *unit) priv->enable_tsense = false; priv->enable_vref = false; priv->sample_time = 0b010; // 13.5c - priv->frequency = 4; //1000 + priv->frequency = 1000; + priv->buffer_size = 512; return E_SUCCESS; } @@ -160,6 +161,7 @@ error_t UADC_init(Unit *unit) LL_TIM_SetAutoReload(priv->TIMx, count - 1); LL_TIM_EnableARRPreload(priv->TIMx); LL_TIM_EnableUpdateEvent(priv->TIMx); + LL_TIM_SetTriggerOutput(priv->TIMx, LL_TIM_TRGO_UPDATE); LL_TIM_GenerateEvent_UPDATE(priv->TIMx); // load the prescaller value } @@ -195,9 +197,9 @@ error_t UADC_init(Unit *unit) // --------------------- CONFIGURE DMA ------------------------------- dbg("Setting up DMA"); { - // The length must be a 2*multiple of the number of channels - // this is a horrible way to do it but will work - uint16_t itemcount = (uint16_t) (priv->nb_channels * (uint16_t) (UADC_DMA_MAX_BUF_LEN / (2 * priv->nb_channels))); + // The length must be a 2*multiple of the number of channels, in bytes + uint16_t itemcount = (uint16_t) ((priv->nb_channels) * (uint16_t) (priv->buffer_size / (2 * priv->nb_channels))); + if (itemcount % 2 == 1) itemcount -= priv->nb_channels; priv->dma_buffer_size = (uint16_t) (itemcount * 2); dbg("DMA item count is %d (%d bytes)", itemcount, priv->dma_buffer_size); @@ -236,6 +238,7 @@ error_t UADC_init(Unit *unit) dbg("ADC inited, starting the timer ..."); // FIXME - temporary demo - counter start... + LL_ADC_REG_StartConversion(priv->ADCx); // the first conversion must be started manually LL_TIM_EnableCounter(priv->TIMx); return E_SUCCESS; @@ -254,7 +257,7 @@ void UADC_deInit(Unit *unit) LL_ADC_CommonDeInit(priv->ADCx_Common); LL_TIM_DeInit(priv->TIMx); - irqd_detach(priv->DMAx, UADC_DMA_Handler); + irqd_detach(priv->DMA_CHx, UADC_DMA_Handler); LL_DMA_DeInit(priv->DMAx, priv->dma_chnum); free_ck(priv->dma_buffer); diff --git a/units/adc/_adc_internal.h b/units/adc/_adc_internal.h index 319f218..e3d0cdf 100644 --- a/units/adc/_adc_internal.h +++ b/units/adc/_adc_internal.h @@ -19,6 +19,7 @@ struct priv { bool enable_vref; //!< append a signal from the internal voltage reference uint8_t sample_time; //!< 0-7 (corresponds to 1.5-239.5 cycles) - time for the sampling capacitor to charge uint32_t frequency; //!< Timer frequency in Hz. Note: not all frequencies can be achieved accurately + uint16_t buffer_size; //!< Buffer size in bytes (count 2 bytes per channel per measurement) - faster sampling freq needs bigger buffer // TODO averaging (maybe a separate component?) // TODO threshold watchdog with hysteresis (maybe a separate component?) diff --git a/units/adc/_adc_settings.c b/units/adc/_adc_settings.c index e35ec86..e44b457 100644 --- a/units/adc/_adc_settings.c +++ b/units/adc/_adc_settings.c @@ -21,6 +21,10 @@ void UADC_loadBinary(Unit *unit, PayloadParser *pp) priv->enable_vref = pp_bool(pp); priv->sample_time = pp_u8(pp); priv->frequency = pp_u32(pp); + + if (version >= 1) { + priv->buffer_size = pp_u16(pp); + } } /** Write to a binary buffer for storing in Flash */ @@ -28,13 +32,14 @@ void UADC_writeBinary(Unit *unit, PayloadBuilder *pb) { struct priv *priv = unit->data; - pb_u8(pb, 0); // version + pb_u8(pb, 1); // version pb_u16(pb, priv->channels); pb_bool(pb, priv->enable_tsense); pb_bool(pb, priv->enable_vref); pb_u8(pb, priv->sample_time); pb_u32(pb, priv->frequency); + pb_u16(pb, priv->buffer_size); } // ------------------------------------------------------------------------ @@ -61,6 +66,9 @@ error_t UADC_loadIni(Unit *unit, const char *key, const char *value) else if (streq(key, "frequency")) { priv->frequency = (uint32_t) avr_atoi(value); } + else if (streq(key, "buffer_size")) { + priv->buffer_size = (uint16_t) avr_atoi(value); + } else { return E_BAD_KEY; } @@ -89,5 +97,11 @@ void UADC_writeIni(Unit *unit, IniWriter *iw) iw_comment(iw, "Sampling frequency (Hz)"); iw_entry(iw, "frequency", "%d", (int)priv->frequency); + + iw_comment(iw, "Sample buffer size (bytes, 2 per channels per sample)"); + iw_comment(iw, "- a report is sent when 1/2 of the circular buffer is filled"); + iw_comment(iw, "- the buffer is shared by all channels"); + iw_comment(iw, "- insufficient buffer size can lead to data loss"); + iw_entry(iw, "buffer_size", "%d", (int)priv->buffer_size); }