From ddfbbeeb955fc0513bb08eec1445f05dbe98f643 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Wed, 7 Feb 2018 20:57:02 +0100 Subject: [PATCH] more parts of adc fixed --- comm/event_reports.c | 24 ++++++--- comm/event_reports.h | 2 + comm/msg_responses.c | 3 +- tasks/task_main.c | 2 +- units/adc/_adc_core.c | 116 ++++++++++++++++++++++++++++++++++-------- 5 files changed, 118 insertions(+), 29 deletions(-) diff --git a/comm/event_reports.c b/comm/event_reports.c index 15c423a..45136bf 100644 --- a/comm/event_reports.c +++ b/comm/event_reports.c @@ -12,21 +12,26 @@ bool EventReport_Start(EventReport *report) { assert_param(report->timestamp != 0); - TF_Msg msg; - TF_ClearMsg(&msg); - msg.len = (TF_LEN) (report->length + 1 /*callsign*/ + 1 /*type*/ + 8 /*checksum*/); - msg.type = MSG_UNIT_REPORT; + const uint8_t len_overhead = 1 /*callsign*/ + 1 /*type*/ + 8 /*timestamp u64*/; + + TF_Msg msg = { + .len = (TF_LEN) (report->length + len_overhead), + .type = MSG_UNIT_REPORT, + }; + if (!TF_Send_Multipart(comm, &msg)) { dbg("!! Err sending event"); return false; } - PayloadBuilder pb = pb_start(evt_buf, 10, NULL); + report->sent_msg_id = msg.frame_id; + + PayloadBuilder pb = pb_start(evt_buf, len_overhead, NULL); pb_u8(&pb, report->unit->callsign); pb_u8(&pb, report->type); pb_u64(&pb, report->timestamp); assert_param(pb.ok); - TF_Multipart_Payload(comm, evt_buf, 10); + TF_Multipart_Payload(comm, evt_buf, len_overhead); return true; } @@ -36,6 +41,13 @@ void EventReport_Data(const uint8_t *buff, uint16_t len) TF_Multipart_Payload(comm, buff, len); } +void EventReport_PB(PayloadBuilder *pb) +{ + uint32_t len; + uint8_t *buf = pb_close(pb, &len); + TF_Multipart_Payload(comm, buf, len); +} + void EventReport_End(void) { TF_Multipart_Close(comm); diff --git a/comm/event_reports.h b/comm/event_reports.h index 56223ca..05f57c1 100644 --- a/comm/event_reports.h +++ b/comm/event_reports.h @@ -21,12 +21,14 @@ typedef struct event_report_ { uint64_t timestamp; //!< Microsecond timestamp of the event, captured as close as possible to the IRQ uint16_t length; //!< Payload length uint8_t *data; //!< Data if using the EventReport_Send() function, otherwise NULL and data is sent using EventReport_Data() + TF_ID sent_msg_id; } EventReport; bool EventReport_Send(EventReport *report); bool EventReport_Start(EventReport *report); void EventReport_Data(const uint8_t *buff, uint16_t len); +void EventReport_PB(PayloadBuilder *pb); void EventReport_End(void); #endif //GEX_F072_EVENT_REPORTS_H diff --git a/comm/msg_responses.c b/comm/msg_responses.c index d1887dd..312aa9b 100644 --- a/comm/msg_responses.c +++ b/comm/msg_responses.c @@ -57,10 +57,9 @@ void com_send_pb(TF_TYPE type, PayloadBuilder *pb) void com_send_buf(TF_TYPE type, const uint8_t *buf, uint32_t len) { TF_Msg msg = { - .type = MSG_UNIT_REPORT, + .type = type, .data = buf, .len = (TF_LEN) len, - .type = type, }; TF_Send(comm, &msg); // no listener diff --git a/tasks/task_main.c b/tasks/task_main.c index b7e8600..51d5f75 100644 --- a/tasks/task_main.c +++ b/tasks/task_main.c @@ -56,7 +56,7 @@ void TaskMain(void const * argument) // Periodically check stacks for overrun stackmon_check_canaries(); // Periodically dump all stacks - for checking levels before critical (to reduce size if not needed) - if ((cnt%75)==0) stackmon_dump(); + if ((cnt%150)==0) stackmon_dump(); continue; } diff --git a/units/adc/_adc_core.c b/units/adc/_adc_core.c index c092f2e..586b55a 100644 --- a/units/adc/_adc_core.c +++ b/units/adc/_adc_core.c @@ -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