more parts of adc fixed

This commit is contained in:
2018-02-07 20:57:02 +01:00
parent 835423099b
commit ddfbbeeb95
5 changed files with 118 additions and 29 deletions
+96 -20
View File
@@ -39,6 +39,75 @@ static void UADC_JobSendBlockChunk(Job *job)
priv->stream_serial++;
}
static void UADC_JobSendTriggerCaptureHeader(Job *job)
{
Unit *unit = job->unit;
assert_param(unit);
struct priv *priv = unit->data;
assert_param(priv);
EventReport er = {
.unit = unit,
.type = EVT_CAPT_START,
.timestamp = job->timestamp,
.length = (priv->pretrig_len+1)*priv->nb_channels*sizeof(uint16_t) + 2 /*pretrig len*/ + 1 /*edge*/ + 1 /* seq */
};
uint16_t index_trigd = (uint16_t) job->data1;
uint8_t edge = (uint8_t) job->data2;
EventReport_Start(&er);
priv->stream_frame_id = er.sent_msg_id;
dbg("Sending TRIG HEADER with id %d (idx %d)", (int)er.sent_msg_id, (int)index_trigd);
{
// preamble
uint8_t buf[4];
PayloadBuilder pb = pb_start(buf, 4, NULL);
pb_u16(&pb, priv->pretrig_len);
pb_u8(&pb, edge);
pb_u8(&pb, priv->stream_serial++); // This is the serial counter for the first chunk
// (containing the pre-trigger, or empty if no pretrig configured)
EventReport_PB(&pb);
if (priv->pretrig_len > 0) {
// pretrig
uint16_t pretrig_remain = (uint16_t) ((priv->pretrig_len + 1) * priv->nb_channels); // +1 because we want pretrig 0 to exactly start with the triggering sample
assert_param(index_trigd <= priv->dma_buffer_itemcount);
// this is one past the last entry of the triggering capture group
if (pretrig_remain > index_trigd) {
// used items in the wrap-around part of the buffer
uint16_t items_from_end = pretrig_remain - index_trigd;
assert_param(priv->dma_buffer_itemcount - items_from_end >= index_trigd);
dbg("Pretrig wraparound part: start %d, len %d",
(int) (priv->dma_buffer_itemcount - items_from_end),
(int) items_from_end
);
EventReport_Data(
(uint8_t *) &priv->dma_buffer[priv->dma_buffer_itemcount -
items_from_end],
items_from_end * sizeof(uint16_t));
assert_param(items_from_end <= pretrig_remain);
pretrig_remain -= items_from_end;
}
dbg("Pretrig front part: start %d, len %d",
(int) (index_trigd - pretrig_remain),
(int) pretrig_remain
);
assert_param(pretrig_remain <= index_trigd);
EventReport_Data((uint8_t *) &priv->dma_buffer[index_trigd - pretrig_remain],
pretrig_remain * sizeof(uint16_t));
}
}
EventReport_End();
}
static void UADC_JobSendEndOfStreamMsg(Job *job)
{
Unit *unit = job->unit;
@@ -93,17 +162,17 @@ void UADC_DMA_Handler(void *arg)
uint16_t end;
if (ht) {
dbg("HT");
// dbg("HT");
end = (uint16_t) (priv->dma_buffer_itemcount / 2);
LL_DMA_ClearFlag_HT(priv->DMAx, priv->dma_chnum);
}
else {
dbg("TC");
// dbg("TC");
end = (uint16_t) priv->dma_buffer_itemcount;
LL_DMA_ClearFlag_TC(priv->DMAx, priv->dma_chnum);
}
dbg("start %d, end %d", (int)start, (int)end);
// dbg("start %d, end %d", (int)start, (int)end);
assert_param(start <= end);
if (start != end) {
@@ -126,7 +195,7 @@ void UADC_DMA_Handler(void *arg)
scheduleJob(&j);
if (close) {
dbg("End of capture");
// dbg("End of capture");
// If auto-arm enabled, we need to re-arm again.
// However, EOS irq is disabled during the capture.
// We have to wait for the next EOS interrupt to occur.
@@ -134,7 +203,7 @@ void UADC_DMA_Handler(void *arg)
UADC_SwitchMode(unit, (priv->auto_rearm && m_trigd) ? ADC_OPMODE_REARM_PENDING : ADC_OPMODE_IDLE);
}
} else {
dbg("start==end, skip this irq");
// dbg("start==end, skip this irq");
}
if (tc) {
@@ -201,18 +270,18 @@ void UADC_ADC_EOS_Handler(void *arg)
if (i == priv->trigger_source) {
if (priv->opmode == ADC_OPMODE_ARMED) {
dbg("Trig line level %d", (int)val);
// dbg("Trig line level %d", (int)val);
bool trigd = false;
uint8_t edge_type = 0;
if (priv->trig_prev_level < priv->trig_level && val >= priv->trig_level) {
dbg("******** Rising edge");
// dbg("******** Rising edge");
// Rising edge
trigd = (bool) (priv->trig_edge & 0b01);
edge_type = 1;
}
else if (priv->trig_prev_level > priv->trig_level && val <= priv->trig_level) {
dbg("******** Falling edge");
// dbg("******** Falling edge");
// Falling edge
trigd = (bool) (priv->trig_edge & 0b10);
edge_type = 2;
@@ -246,7 +315,7 @@ void UADC_HandleTrigger(Unit *unit, uint8_t edge_type, uint64_t timestamp)
assert_param(priv);
if (priv->trig_holdoff != 0 && priv->trig_holdoff_remain > 0) {
dbg("Trig discarded due to holdoff.");
// dbg("Trig discarded due to holdoff.");
return;
}
@@ -261,9 +330,16 @@ void UADC_HandleTrigger(Unit *unit, uint8_t edge_type, uint64_t timestamp)
priv->trig_stream_remain = priv->trig_len;
priv->stream_serial = 0;
// TODO Send pre-trigger
// dbg("Trigger condition hit, edge=%d, startpos %d", edge_type, (int)priv->stream_startpos);
dbg("Trigger condition hit, edge=%d, startpos %d", edge_type, (int)priv->stream_startpos);
Job j = {
.unit = unit,
.timestamp = timestamp,
.data1 = priv->stream_startpos,
.data2 = edge_type,
.cb = UADC_JobSendTriggerCaptureHeader
};
scheduleJob(&j);
UADC_SwitchMode(unit, ADC_OPMODE_TRIGD);
}
@@ -291,7 +367,7 @@ void UADC_StartStream(Unit *unit, TF_ID frame_id)
priv->stream_frame_id = frame_id;
priv->stream_startpos = (uint16_t) DMA_POS(priv);
priv->stream_serial = 0;
dbg("Start streaming.");
// dbg("Start streaming.");
UADC_SwitchMode(unit, ADC_OPMODE_STREAM);
}
@@ -302,7 +378,7 @@ void UADC_StopStream(Unit *unit)
struct priv *priv = unit->data;
assert_param(priv);
dbg("Stop stream.");
// dbg("Stop stream.");
UADC_ReportEndOfStream(unit);
UADC_SwitchMode(unit, ADC_OPMODE_IDLE);
}
@@ -336,7 +412,7 @@ void UADC_SwitchMode(Unit *unit, enum uadc_opmode new_mode)
assert_param((priv->opmode != ADC_OPMODE_UNINIT) || (new_mode == ADC_OPMODE_IDLE));
if (new_mode == ADC_OPMODE_UNINIT) {
dbg("ADC switch -> UNINIT");
// dbg("ADC switch -> UNINIT");
// Stop the DMA, timer and disable ADC - this is called before tearing down the unit
LL_TIM_DisableCounter(priv->TIMx);
@@ -344,23 +420,23 @@ void UADC_SwitchMode(Unit *unit, enum uadc_opmode new_mode)
if (LL_ADC_IsEnabled(priv->ADCx)) {
// Cancel ongoing conversion
if (LL_ADC_REG_IsConversionOngoing(priv->ADCx)) {
dbg("Stopping ADC conv");
// dbg("Stopping ADC conv");
LL_ADC_REG_StopConversion(priv->ADCx);
hw_wait_while(LL_ADC_REG_IsStopConversionOngoing(priv->ADCx), 100);
}
LL_ADC_Disable(priv->ADCx);
dbg("Disabling ADC");
// dbg("Disabling ADC");
hw_wait_while(LL_ADC_IsDisableOngoing(priv->ADCx), 100);
}
dbg("Disabling DMA");
// dbg("Disabling DMA");
LL_DMA_DisableChannel(priv->DMAx, priv->dma_chnum);
LL_DMA_DisableIT_HT(priv->DMAx, priv->dma_chnum);
LL_DMA_DisableIT_TC(priv->DMAx, priv->dma_chnum);
}
else if (new_mode == ADC_OPMODE_IDLE || new_mode == ADC_OPMODE_REARM_PENDING) {
dbg("ADC switch -> IDLE or IDLE/REARM_PENDING");
// dbg("ADC switch -> IDLE or IDLE/REARM_PENDING");
// IDLE and ARMED are identical with the exception that the trigger condition is not checked
// ARMED can be only entered from IDLE, thus we do the init only here.
@@ -382,7 +458,7 @@ void UADC_SwitchMode(Unit *unit, enum uadc_opmode new_mode)
}
}
else if (new_mode == ADC_OPMODE_ARMED) {
dbg("ADC switch -> ARMED");
// dbg("ADC switch -> ARMED");
assert_param(priv->opmode == ADC_OPMODE_IDLE || priv->opmode == ADC_OPMODE_REARM_PENDING);
// avoid firing immediately by the value jumping across the scale
@@ -392,7 +468,7 @@ void UADC_SwitchMode(Unit *unit, enum uadc_opmode new_mode)
new_mode == ADC_OPMODE_STREAM ||
new_mode == ADC_OPMODE_BLCAP) {
dbg("ADC switch -> TRIG'D / STREAM / BLOCK");
// dbg("ADC switch -> TRIG'D / STREAM / BLOCK");
assert_param(priv->opmode == ADC_OPMODE_ARMED || priv->opmode == ADC_OPMODE_IDLE);
// during the capture, we disallow direct readout and averaging to reduce overhead