Fixzed triggers and also missed TC/TH

adc^2
Ondřej Hruška 7 years ago
parent d6e73a5641
commit 85453afa44
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 103
      units/adc/_adc_core.c
  2. 2
      units/adc/_adc_init.c

@ -140,38 +140,17 @@ void UADC_ReportEndOfStream(Unit *unit)
scheduleJob(&j);
}
void UADC_DMA_Handler(void *arg)
static void handle_httc(Unit *unit, bool tc)
{
Unit *unit = arg;
assert_param(unit);
struct priv *priv = unit->data;
assert_param(priv);
if (priv->opmode == ADC_OPMODE_UNINIT) {
LL_DMA_ClearFlag_HT(priv->DMAx, priv->dma_chnum);
LL_DMA_ClearFlag_TC(priv->DMAx, priv->dma_chnum);
LL_DMA_ClearFlag_TE(priv->DMAx, priv->dma_chnum);
return;
}
const uint32_t isrsnapshot = priv->DMAx->ISR;
if (LL_DMA_IsActiveFlag_G(isrsnapshot, priv->dma_chnum)) {
const bool tc = LL_DMA_IsActiveFlag_TC(isrsnapshot, priv->dma_chnum);
const bool ht = LL_DMA_IsActiveFlag_HT(isrsnapshot, priv->dma_chnum);
const bool te = LL_DMA_IsActiveFlag_TE(isrsnapshot, priv->dma_chnum);
uint16_t start = priv->stream_startpos;
uint16_t end;
const bool ht = !tc;
// check what mode we're in
const bool m_trigd = priv->opmode == ADC_OPMODE_TRIGD;
const bool m_stream = priv->opmode == ADC_OPMODE_STREAM;
const bool m_fixcpt = priv->opmode == ADC_OPMODE_BLCAP;
if (m_trigd || m_stream || m_fixcpt) {
if (ht || tc) {
const uint16_t start = priv->stream_startpos;
uint16_t end;
if (ht) {
// dbg("HT");
end = (uint16_t) (priv->dma_buffer_itemcount / 2);
@ -183,10 +162,12 @@ void UADC_DMA_Handler(void *arg)
LL_DMA_ClearFlag_TC(priv->DMAx, priv->dma_chnum);
}
if (start > end) {
dbg("start %d, end %d", (int) start, (int) end);
if (ht == tc) {
// This shouldn't happen - looks like we missed the TC flag
dbg("!! %d -> %d", (int) start, (int) end);
// TODO we could try to catch up. for now, just take what is easy to grab and hope it doesnt matter
if (end == 64) start = 0;
}
assert_param(start <= end);
if (start != end) {
uint32_t sgcount = (end - start) / priv->nb_channels;
@ -232,6 +213,49 @@ void UADC_DMA_Handler(void *arg)
priv->stream_startpos = end;
}
}
void UADC_DMA_Handler(void *arg)
{
Unit *unit = arg;
assert_param(unit);
struct priv *priv = unit->data;
assert_param(priv);
if (priv->opmode == ADC_OPMODE_UNINIT) {
LL_DMA_ClearFlag_HT(priv->DMAx, priv->dma_chnum);
LL_DMA_ClearFlag_TC(priv->DMAx, priv->dma_chnum);
LL_DMA_ClearFlag_TE(priv->DMAx, priv->dma_chnum);
return;
}
const uint32_t isrsnapshot = priv->DMAx->ISR;
if (LL_DMA_IsActiveFlag_G(isrsnapshot, priv->dma_chnum)) {
const bool tc = LL_DMA_IsActiveFlag_TC(isrsnapshot, priv->dma_chnum);
const bool ht = LL_DMA_IsActiveFlag_HT(isrsnapshot, priv->dma_chnum);
const bool te = LL_DMA_IsActiveFlag_TE(isrsnapshot, priv->dma_chnum);
// check what mode we're in
const bool m_trigd = priv->opmode == ADC_OPMODE_TRIGD;
const bool m_stream = priv->opmode == ADC_OPMODE_STREAM;
const bool m_fixcpt = priv->opmode == ADC_OPMODE_BLCAP;
if (m_trigd || m_stream || m_fixcpt) {
if (ht || tc) {
if (ht && tc) {
uint16_t half = (uint16_t) (priv->dma_buffer_itemcount / 2);
if (priv->stream_startpos > half) {
handle_httc(unit, true);
handle_httc(unit, false);
} else {
handle_httc(unit, false);
handle_httc(unit, true);
}
} else {
handle_httc(unit, tc);
}
}
} else {
// This shouldn't happen, the interrupt should be disabled in this opmode
dbg("(!) not streaming, DMA IT should be disabled");
@ -259,13 +283,9 @@ void UADC_ADC_EOS_Handler(void *arg)
struct priv *priv = unit->data;
assert_param(priv);
const bool trig_ready4_rising = (priv->trig_prev_level < priv->trig_level) && (bool) (priv->trig_edge & 0b01);
const bool trig_ready4_falling = (priv->trig_prev_level > priv->trig_level) && (bool) (priv->trig_edge & 0b10);
const bool armed = (trig_ready4_rising && trig_ready4_falling) && priv->opmode == ADC_OPMODE_ARMED;
// Normally
uint64_t timestamp = 0;
if (armed) timestamp = PTIM_GetMicrotime();
if (priv->opmode == ADC_OPMODE_ARMED) timestamp = PTIM_GetMicrotime();
LL_ADC_ClearFlag_EOS(priv->ADCx);
if (priv->opmode == ADC_OPMODE_UNINIT) return;
@ -284,14 +304,12 @@ void UADC_ADC_EOS_Handler(void *arg)
int cnt = 0; // index of the sample within the group
const uint8_t trig_source = priv->trigger_source;
const bool can_average = priv->real_frequency_int < UADC_MAX_FREQ_FOR_AVERAGING;
const uint16_t *dma_buffer = priv->dma_buffer;
const uint32_t channels_mask = priv->extended_channels_mask;
for (uint8_t i = 0; i < 18; i++) {
if (channels_mask & (1 << i)) {
uint16_t val = dma_buffer[sample_pos+cnt];
uint16_t val = priv->dma_buffer[sample_pos+cnt];
cnt++;
if (can_average) {
@ -301,24 +319,27 @@ void UADC_ADC_EOS_Handler(void *arg)
}
priv->last_samples[i] = val;
}
}
if (priv->opmode == ADC_OPMODE_ARMED) {
uint16_t val = priv->last_samples[priv->trigger_source];
if (armed && i == trig_source) {
// dbg("Trig line level %d", (int)val);
if (trig_ready4_rising && val >= priv->trig_level) {
if ((priv->trig_prev_level < priv->trig_level) && val >= priv->trig_level && (bool) (priv->trig_edge & 0b01)) {
// dbg("******** Rising edge");
// Rising edge
UADC_HandleTrigger(unit, 1, timestamp);
}
else if (trig_ready4_falling && val <= priv->trig_level) {
else if ((priv->trig_prev_level > priv->trig_level) && val <= priv->trig_level && (bool) (priv->trig_edge & 0b10)) {
// dbg("******** Falling edge");
// Falling edge
UADC_HandleTrigger(unit, 2, timestamp);
}
priv->trig_prev_level = val;
}
}
}
// auto-rearm was waiting for the next sample
if (priv->opmode == ADC_OPMODE_REARM_PENDING) {
if (!priv->auto_rearm) {
// It looks like the flag was cleared by DISARM before we got a new sample.

@ -196,7 +196,7 @@ error_t UADC_init(Unit *unit)
priv->dma_buffer_itemcount*sizeof(uint16_t),
priv->nb_channels);
priv->dma_buffer = malloc_ck(priv->dma_buffer_itemcount * sizeof(uint16_t));
priv->dma_buffer = calloc_ck(priv->dma_buffer_itemcount, sizeof(uint16_t));
if (NULL == priv->dma_buffer) return E_OUT_OF_MEM;
assert_param(((uint32_t) priv->dma_buffer & 3) == 0); // must be aligned

Loading…
Cancel
Save