some small adc fixes (impreoving[D[D trigger)
This commit is contained in:
+30
-16
@@ -31,11 +31,11 @@ void UADC_DMA_Handler(void *arg)
|
||||
const bool te = LL_DMA_IsActiveFlag_TE(isrsnapshot, priv->dma_chnum);
|
||||
|
||||
// check what mode we're in
|
||||
const bool m_trig = priv->opmode == ADC_OPMODE_TRIGD;
|
||||
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_FIXCAPT;
|
||||
|
||||
if (m_trig || m_stream || m_fixcpt) {
|
||||
if (m_trigd || m_stream || m_fixcpt) {
|
||||
if (ht || tc) {
|
||||
const uint16_t start = priv->stream_startpos;
|
||||
uint16_t end;
|
||||
@@ -57,7 +57,7 @@ void UADC_DMA_Handler(void *arg)
|
||||
if (start != end) {
|
||||
uint32_t sgcount = (end - start) / priv->nb_channels;
|
||||
|
||||
if (m_trig || m_fixcpt) {
|
||||
if (m_trigd || m_fixcpt) {
|
||||
sgcount = MIN(priv->trig_stream_remain, sgcount);
|
||||
priv->trig_stream_remain -= sgcount;
|
||||
}
|
||||
@@ -67,14 +67,16 @@ void UADC_DMA_Handler(void *arg)
|
||||
|
||||
// TODO send the data together with remaining count (used to detect end of transmission)
|
||||
|
||||
if (m_trig || m_fixcpt) {
|
||||
if (m_trigd || m_fixcpt) { // Trig'd or Block capture - check for the max count condition
|
||||
if (priv->trig_stream_remain == 0) {
|
||||
dbg("End of capture");
|
||||
UADC_ReportEndOfStream(unit);
|
||||
UADC_SwitchMode(unit, ADC_OPMODE_IDLE);
|
||||
if (priv->auto_rearm && m_trig) {
|
||||
UADC_SwitchMode(unit, ADC_OPMODE_ARMED);
|
||||
}
|
||||
|
||||
// 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.
|
||||
// TODO verify if keeping the EOS irq enabled during capture has significant performance penalty. If not, we can leave it enabled.
|
||||
UADC_SwitchMode(unit, (priv->auto_rearm && m_trigd) ? ADC_OPMODE_REARM_PENDING : ADC_OPMODE_IDLE);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -143,8 +145,8 @@ void UADC_ADC_EOS_Handler(void *arg)
|
||||
|
||||
priv->last_samples[i] = val;
|
||||
|
||||
if (priv->opmode == ADC_OPMODE_ARMED) {
|
||||
if (i == priv->trigger_source) {
|
||||
if (i == priv->trigger_source) {
|
||||
if (priv->opmode == ADC_OPMODE_ARMED) {
|
||||
dbg("Trig line level %d", (int)val);
|
||||
|
||||
bool trigd = false;
|
||||
@@ -165,9 +167,19 @@ void UADC_ADC_EOS_Handler(void *arg)
|
||||
if (trigd) {
|
||||
UADC_HandleTrigger(unit, edge_type, timestamp);
|
||||
}
|
||||
|
||||
priv->trig_prev_level = val;
|
||||
}
|
||||
else 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.
|
||||
// Let's just switch to IDLE
|
||||
UADC_SwitchMode(unit, ADC_OPMODE_IDLE);
|
||||
} else {
|
||||
// Re-arming for a new trigger
|
||||
UADC_SwitchMode(unit, ADC_OPMODE_ARMED);
|
||||
}
|
||||
}
|
||||
|
||||
priv->trig_prev_level = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -290,8 +302,8 @@ void UADC_SwitchMode(Unit *unit, enum uadc_opmode new_mode)
|
||||
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) {
|
||||
dbg("ADC switch -> IDLE");
|
||||
else if (new_mode == ADC_OPMODE_IDLE || new_mode == ADC_OPMODE_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.
|
||||
|
||||
@@ -314,8 +326,10 @@ void UADC_SwitchMode(Unit *unit, enum uadc_opmode new_mode)
|
||||
}
|
||||
else if (new_mode == ADC_OPMODE_ARMED) {
|
||||
dbg("ADC switch -> ARMED");
|
||||
assert_param(priv->opmode == ADC_OPMODE_IDLE);
|
||||
// there's nothing else to do here
|
||||
assert_param(priv->opmode == ADC_OPMODE_IDLE || priv->opmode == ADC_OPMODE_REARM_PENDING);
|
||||
|
||||
// avoid firing immediately by the value jumping across the scale
|
||||
priv->trig_prev_level = priv->last_samples[priv->trigger_source];
|
||||
}
|
||||
else if (new_mode == ADC_OPMODE_TRIGD ||
|
||||
new_mode == ADC_OPMODE_STREAM ||
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
|
||||
enum uadc_opmode {
|
||||
ADC_OPMODE_UNINIT, //!< Not yet switched to any mode
|
||||
ADC_OPMODE_IDLE, //!< Idle, each sample overwrites the previous. Allows immediate value readout and averaging.
|
||||
ADC_OPMODE_IDLE, //!< Idle. Allows immediate value readout and averaging.
|
||||
ADC_OPMODE_REARM_PENDING, //!< Idle, waiting for the next sample to re-arm (auto trigger).
|
||||
ADC_OPMODE_ARMED, //!< Armed for a trigger. Direct access and averaging are disabled.
|
||||
ADC_OPMODE_TRIGD, //!< Triggered, sending pre-trigger and streaming captured data.
|
||||
ADC_OPMODE_FIXCAPT,//!< Capture of fixed length without a trigger
|
||||
|
||||
+65
-33
@@ -109,16 +109,20 @@ static error_t UADC_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P
|
||||
*/
|
||||
case CMD_SETUP_TRIGGER:
|
||||
dbg("> Setup trigger");
|
||||
if (priv->opmode != ADC_OPMODE_IDLE && priv->opmode != ADC_OPMODE_ARMED) return E_BUSY;
|
||||
if (priv->opmode != ADC_OPMODE_IDLE &&
|
||||
priv->opmode != ADC_OPMODE_ARMED &&
|
||||
priv->opmode != ADC_OPMODE_REARM_PENDING) {
|
||||
return E_BUSY;
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t source = pp_u8(pp);
|
||||
uint16_t level = pp_u16(pp);
|
||||
uint8_t edge = pp_u8(pp); // TODO test falling edge and dual edge
|
||||
uint16_t pretrig = pp_u16(pp); // TODO test pre-trigger ...
|
||||
uint32_t count = pp_u32(pp);
|
||||
uint16_t holdoff = pp_u16(pp); // TODO test hold-off ...
|
||||
bool auto_rearm = pp_bool(pp);
|
||||
const uint8_t source = pp_u8(pp);
|
||||
const uint16_t level = pp_u16(pp);
|
||||
const uint8_t edge = pp_u8(pp);
|
||||
const uint16_t pretrig = pp_u16(pp); // TODO test pre-trigger ...
|
||||
const uint32_t count = pp_u32(pp);
|
||||
const uint16_t holdoff = pp_u16(pp);
|
||||
const bool auto_rearm = pp_bool(pp);
|
||||
|
||||
if (source > 17) {
|
||||
com_respond_str(MSG_ERROR, frame_id, "Invalid trig source");
|
||||
@@ -141,7 +145,7 @@ static error_t UADC_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P
|
||||
}
|
||||
|
||||
// XXX the max size may be too much
|
||||
uint16_t max_pretrig = (priv->dma_buffer_itemcount / priv->nb_channels);
|
||||
const uint16_t max_pretrig = (priv->dma_buffer_itemcount / priv->nb_channels);
|
||||
if (pretrig > max_pretrig) {
|
||||
com_respond_snprintf(frame_id, MSG_ERROR,
|
||||
"Pretrig too large (max %d)", (int) max_pretrig);
|
||||
@@ -164,17 +168,28 @@ static error_t UADC_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P
|
||||
*/
|
||||
case CMD_ARM:
|
||||
dbg("> Arm");
|
||||
if(priv->opmode != ADC_OPMODE_IDLE) return E_BUSY;
|
||||
uint8_t sticky = pp_u8(pp);
|
||||
|
||||
if (priv->trig_len == 0) {
|
||||
com_respond_str(MSG_ERROR, frame_id, "Trigger not configured.");
|
||||
return E_FAILURE;
|
||||
if(priv->opmode == ADC_OPMODE_ARMED || priv->opmode == ADC_OPMODE_REARM_PENDING) {
|
||||
// We are armed or will re-arm promptly, act like the call succeeded
|
||||
// The auto flag is set regardless
|
||||
} else {
|
||||
if (priv->opmode != ADC_OPMODE_IDLE) {
|
||||
return E_BUSY; // capture in progress
|
||||
}
|
||||
|
||||
if (priv->trig_len == 0) {
|
||||
com_respond_str(MSG_ERROR, frame_id, "Trigger not configured.");
|
||||
return E_FAILURE;
|
||||
}
|
||||
|
||||
UADC_SwitchMode(unit, ADC_OPMODE_ARMED);
|
||||
}
|
||||
|
||||
// avoid firing immediately by the value jumping across the scale
|
||||
priv->trig_prev_level = priv->last_samples[priv->trigger_source];
|
||||
if (sticky != 255) {
|
||||
priv->auto_rearm = (bool)sticky;
|
||||
}
|
||||
|
||||
UADC_SwitchMode(unit, ADC_OPMODE_ARMED);
|
||||
return E_SUCCESS;
|
||||
|
||||
/**
|
||||
@@ -182,13 +197,21 @@ static error_t UADC_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P
|
||||
* Switches to idle.
|
||||
*/
|
||||
case CMD_DISARM:
|
||||
// TODO test
|
||||
dbg("> Disarm");
|
||||
|
||||
priv->auto_rearm = false;
|
||||
|
||||
if(priv->opmode == ADC_OPMODE_IDLE) {
|
||||
return E_SUCCESS; // already idle, success - no work to do
|
||||
}
|
||||
|
||||
// capture in progress
|
||||
if(priv->opmode != ADC_OPMODE_ARMED) return E_BUSY;
|
||||
if (priv->opmode != ADC_OPMODE_ARMED &&
|
||||
priv->opmode != ADC_OPMODE_REARM_PENDING) {
|
||||
// Capture in progress, we already cleared auto rearm, so we're done for now
|
||||
// auto_rearm is checked in the EOS isr and if cleared, does not re-arm.
|
||||
return E_SUCCESS;
|
||||
}
|
||||
|
||||
UADC_SwitchMode(unit, ADC_OPMODE_IDLE);
|
||||
return E_SUCCESS;
|
||||
@@ -197,15 +220,18 @@ static error_t UADC_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P
|
||||
* Abort any ongoing capture and dis-arm.
|
||||
*/
|
||||
case CMD_ABORT:;
|
||||
// TODO test
|
||||
dbg("> Abort capture");
|
||||
enum uadc_opmode old_opmode = priv->opmode;
|
||||
UADC_SwitchMode(unit, ADC_OPMODE_IDLE);
|
||||
{
|
||||
enum uadc_opmode old_opmode = priv->opmode;
|
||||
|
||||
if (old_opmode == ADC_OPMODE_FIXCAPT ||
|
||||
old_opmode == ADC_OPMODE_STREAM ||
|
||||
old_opmode == ADC_OPMODE_TRIGD) {
|
||||
UADC_ReportEndOfStream(unit);
|
||||
priv->auto_rearm = false;
|
||||
UADC_SwitchMode(unit, ADC_OPMODE_IDLE);
|
||||
|
||||
if (old_opmode == ADC_OPMODE_FIXCAPT ||
|
||||
old_opmode == ADC_OPMODE_STREAM ||
|
||||
old_opmode == ADC_OPMODE_TRIGD) {
|
||||
UADC_ReportEndOfStream(unit);
|
||||
}
|
||||
}
|
||||
return E_SUCCESS;
|
||||
|
||||
@@ -214,13 +240,17 @@ static error_t UADC_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P
|
||||
* The reported edge will be 0b11, here meaning "manual trigger"
|
||||
*/
|
||||
case CMD_FORCE_TRIGGER:
|
||||
// TODO test
|
||||
dbg("> Force trigger");
|
||||
if(priv->opmode == ADC_OPMODE_IDLE) {
|
||||
com_respond_str(MSG_ERROR, frame_id, "Not armed");
|
||||
// This is similar to block capture, but includes the pre-trig buffer and has fixed size based on trigger config
|
||||
// FORCE is useful for checking if the trigger is set up correctly
|
||||
if (priv->opmode != ADC_OPMODE_ARMED &&
|
||||
priv->opmode != ADC_OPMODE_IDLE &&
|
||||
priv->opmode != ADC_OPMODE_REARM_PENDING) return E_BUSY;
|
||||
|
||||
if (priv->trig_len == 0) {
|
||||
com_respond_str(MSG_ERROR, frame_id, "Trigger not configured.");
|
||||
return E_FAILURE;
|
||||
}
|
||||
if(priv->opmode != ADC_OPMODE_ARMED) return E_BUSY;
|
||||
|
||||
UADC_HandleTrigger(unit, 0b11, PTIM_GetMicrotime());
|
||||
return E_SUCCESS;
|
||||
@@ -234,7 +264,8 @@ static error_t UADC_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P
|
||||
case CMD_BLOCK_CAPTURE:
|
||||
// TODO test
|
||||
dbg("> Block cpt");
|
||||
if(priv->opmode != ADC_OPMODE_ARMED &&
|
||||
if (priv->opmode != ADC_OPMODE_ARMED &&
|
||||
priv->opmode != ADC_OPMODE_REARM_PENDING &&
|
||||
priv->opmode != ADC_OPMODE_IDLE) return E_BUSY;
|
||||
|
||||
uint32_t count = pp_u32(pp);
|
||||
@@ -249,8 +280,9 @@ static error_t UADC_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P
|
||||
case CMD_STREAM_START:
|
||||
// TODO test
|
||||
dbg("> Stream ON");
|
||||
if(priv->opmode != ADC_OPMODE_ARMED &&
|
||||
priv->opmode != ADC_OPMODE_IDLE) return E_BUSY;
|
||||
if (priv->opmode != ADC_OPMODE_ARMED &&
|
||||
priv->opmode != ADC_OPMODE_REARM_PENDING &&
|
||||
priv->opmode != ADC_OPMODE_IDLE) return E_BUSY;
|
||||
|
||||
UADC_StartStream(unit, frame_id);
|
||||
return E_SUCCESS;
|
||||
@@ -261,7 +293,7 @@ static error_t UADC_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P
|
||||
case CMD_STREAM_STOP:
|
||||
// TODO test
|
||||
dbg("> Stream OFF");
|
||||
if(priv->opmode != ADC_OPMODE_STREAM) {
|
||||
if (priv->opmode != ADC_OPMODE_STREAM) {
|
||||
com_respond_str(MSG_ERROR, frame_id, "Not streaming");
|
||||
return E_FAILURE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user