more parts of adc fixed

adc
Ondřej Hruška 7 years ago
parent 835423099b
commit ddfbbeeb95
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 24
      comm/event_reports.c
  2. 2
      comm/event_reports.h
  3. 3
      comm/msg_responses.c
  4. 2
      tasks/task_main.c
  5. 116
      units/adc/_adc_core.c

@ -12,21 +12,26 @@ bool EventReport_Start(EventReport *report)
{ {
assert_param(report->timestamp != 0); assert_param(report->timestamp != 0);
TF_Msg msg; const uint8_t len_overhead = 1 /*callsign*/ + 1 /*type*/ + 8 /*timestamp u64*/;
TF_ClearMsg(&msg);
msg.len = (TF_LEN) (report->length + 1 /*callsign*/ + 1 /*type*/ + 8 /*checksum*/); TF_Msg msg = {
msg.type = MSG_UNIT_REPORT; .len = (TF_LEN) (report->length + len_overhead),
.type = MSG_UNIT_REPORT,
};
if (!TF_Send_Multipart(comm, &msg)) { if (!TF_Send_Multipart(comm, &msg)) {
dbg("!! Err sending event"); dbg("!! Err sending event");
return false; 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->unit->callsign);
pb_u8(&pb, report->type); pb_u8(&pb, report->type);
pb_u64(&pb, report->timestamp); pb_u64(&pb, report->timestamp);
assert_param(pb.ok); assert_param(pb.ok);
TF_Multipart_Payload(comm, evt_buf, 10); TF_Multipart_Payload(comm, evt_buf, len_overhead);
return true; return true;
} }
@ -36,6 +41,13 @@ void EventReport_Data(const uint8_t *buff, uint16_t len)
TF_Multipart_Payload(comm, buff, 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) void EventReport_End(void)
{ {
TF_Multipart_Close(comm); TF_Multipart_Close(comm);

@ -21,12 +21,14 @@ typedef struct event_report_ {
uint64_t timestamp; //!< Microsecond timestamp of the event, captured as close as possible to the IRQ uint64_t timestamp; //!< Microsecond timestamp of the event, captured as close as possible to the IRQ
uint16_t length; //!< Payload length uint16_t length; //!< Payload length
uint8_t *data; //!< Data if using the EventReport_Send() function, otherwise NULL and data is sent using EventReport_Data() 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; } EventReport;
bool EventReport_Send(EventReport *report); bool EventReport_Send(EventReport *report);
bool EventReport_Start(EventReport *report); bool EventReport_Start(EventReport *report);
void EventReport_Data(const uint8_t *buff, uint16_t len); void EventReport_Data(const uint8_t *buff, uint16_t len);
void EventReport_PB(PayloadBuilder *pb);
void EventReport_End(void); void EventReport_End(void);
#endif //GEX_F072_EVENT_REPORTS_H #endif //GEX_F072_EVENT_REPORTS_H

@ -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) void com_send_buf(TF_TYPE type, const uint8_t *buf, uint32_t len)
{ {
TF_Msg msg = { TF_Msg msg = {
.type = MSG_UNIT_REPORT, .type = type,
.data = buf, .data = buf,
.len = (TF_LEN) len, .len = (TF_LEN) len,
.type = type,
}; };
TF_Send(comm, &msg); // no listener TF_Send(comm, &msg); // no listener

@ -56,7 +56,7 @@ void TaskMain(void const * argument)
// Periodically check stacks for overrun // Periodically check stacks for overrun
stackmon_check_canaries(); stackmon_check_canaries();
// Periodically dump all stacks - for checking levels before critical (to reduce size if not needed) // 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; continue;
} }

@ -39,6 +39,75 @@ static void UADC_JobSendBlockChunk(Job *job)
priv->stream_serial++; 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) static void UADC_JobSendEndOfStreamMsg(Job *job)
{ {
Unit *unit = job->unit; Unit *unit = job->unit;
@ -93,17 +162,17 @@ void UADC_DMA_Handler(void *arg)
uint16_t end; uint16_t end;
if (ht) { if (ht) {
dbg("HT"); // dbg("HT");
end = (uint16_t) (priv->dma_buffer_itemcount / 2); end = (uint16_t) (priv->dma_buffer_itemcount / 2);
LL_DMA_ClearFlag_HT(priv->DMAx, priv->dma_chnum); LL_DMA_ClearFlag_HT(priv->DMAx, priv->dma_chnum);
} }
else { else {
dbg("TC"); // dbg("TC");
end = (uint16_t) priv->dma_buffer_itemcount; end = (uint16_t) priv->dma_buffer_itemcount;
LL_DMA_ClearFlag_TC(priv->DMAx, priv->dma_chnum); 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); assert_param(start <= end);
if (start != end) { if (start != end) {
@ -126,7 +195,7 @@ void UADC_DMA_Handler(void *arg)
scheduleJob(&j); scheduleJob(&j);
if (close) { if (close) {
dbg("End of capture"); // dbg("End of capture");
// If auto-arm enabled, we need to re-arm again. // If auto-arm enabled, we need to re-arm again.
// However, EOS irq is disabled during the capture. // However, EOS irq is disabled during the capture.
// We have to wait for the next EOS interrupt to occur. // 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); UADC_SwitchMode(unit, (priv->auto_rearm && m_trigd) ? ADC_OPMODE_REARM_PENDING : ADC_OPMODE_IDLE);
} }
} else { } else {
dbg("start==end, skip this irq"); // dbg("start==end, skip this irq");
} }
if (tc) { if (tc) {
@ -201,18 +270,18 @@ void UADC_ADC_EOS_Handler(void *arg)
if (i == priv->trigger_source) { if (i == priv->trigger_source) {
if (priv->opmode == ADC_OPMODE_ARMED) { if (priv->opmode == ADC_OPMODE_ARMED) {
dbg("Trig line level %d", (int)val); // dbg("Trig line level %d", (int)val);
bool trigd = false; bool trigd = false;
uint8_t edge_type = 0; uint8_t edge_type = 0;
if (priv->trig_prev_level < priv->trig_level && val >= priv->trig_level) { if (priv->trig_prev_level < priv->trig_level && val >= priv->trig_level) {
dbg("******** Rising edge"); // dbg("******** Rising edge");
// Rising edge // Rising edge
trigd = (bool) (priv->trig_edge & 0b01); trigd = (bool) (priv->trig_edge & 0b01);
edge_type = 1; edge_type = 1;
} }
else if (priv->trig_prev_level > priv->trig_level && val <= priv->trig_level) { else if (priv->trig_prev_level > priv->trig_level && val <= priv->trig_level) {
dbg("******** Falling edge"); // dbg("******** Falling edge");
// Falling edge // Falling edge
trigd = (bool) (priv->trig_edge & 0b10); trigd = (bool) (priv->trig_edge & 0b10);
edge_type = 2; edge_type = 2;
@ -246,7 +315,7 @@ void UADC_HandleTrigger(Unit *unit, uint8_t edge_type, uint64_t timestamp)
assert_param(priv); assert_param(priv);
if (priv->trig_holdoff != 0 && priv->trig_holdoff_remain > 0) { if (priv->trig_holdoff != 0 && priv->trig_holdoff_remain > 0) {
dbg("Trig discarded due to holdoff."); // dbg("Trig discarded due to holdoff.");
return; 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->trig_stream_remain = priv->trig_len;
priv->stream_serial = 0; 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); 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_frame_id = frame_id;
priv->stream_startpos = (uint16_t) DMA_POS(priv); priv->stream_startpos = (uint16_t) DMA_POS(priv);
priv->stream_serial = 0; priv->stream_serial = 0;
dbg("Start streaming."); // dbg("Start streaming.");
UADC_SwitchMode(unit, ADC_OPMODE_STREAM); UADC_SwitchMode(unit, ADC_OPMODE_STREAM);
} }
@ -302,7 +378,7 @@ void UADC_StopStream(Unit *unit)
struct priv *priv = unit->data; struct priv *priv = unit->data;
assert_param(priv); assert_param(priv);
dbg("Stop stream."); // dbg("Stop stream.");
UADC_ReportEndOfStream(unit); UADC_ReportEndOfStream(unit);
UADC_SwitchMode(unit, ADC_OPMODE_IDLE); 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)); assert_param((priv->opmode != ADC_OPMODE_UNINIT) || (new_mode == ADC_OPMODE_IDLE));
if (new_mode == ADC_OPMODE_UNINIT) { 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 // Stop the DMA, timer and disable ADC - this is called before tearing down the unit
LL_TIM_DisableCounter(priv->TIMx); 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)) { if (LL_ADC_IsEnabled(priv->ADCx)) {
// Cancel ongoing conversion // Cancel ongoing conversion
if (LL_ADC_REG_IsConversionOngoing(priv->ADCx)) { if (LL_ADC_REG_IsConversionOngoing(priv->ADCx)) {
dbg("Stopping ADC conv"); // dbg("Stopping ADC conv");
LL_ADC_REG_StopConversion(priv->ADCx); LL_ADC_REG_StopConversion(priv->ADCx);
hw_wait_while(LL_ADC_REG_IsStopConversionOngoing(priv->ADCx), 100); hw_wait_while(LL_ADC_REG_IsStopConversionOngoing(priv->ADCx), 100);
} }
LL_ADC_Disable(priv->ADCx); LL_ADC_Disable(priv->ADCx);
dbg("Disabling ADC"); // dbg("Disabling ADC");
hw_wait_while(LL_ADC_IsDisableOngoing(priv->ADCx), 100); 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_DisableChannel(priv->DMAx, priv->dma_chnum);
LL_DMA_DisableIT_HT(priv->DMAx, priv->dma_chnum); LL_DMA_DisableIT_HT(priv->DMAx, priv->dma_chnum);
LL_DMA_DisableIT_TC(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) { 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 // 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. // 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) { 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); assert_param(priv->opmode == ADC_OPMODE_IDLE || priv->opmode == ADC_OPMODE_REARM_PENDING);
// avoid firing immediately by the value jumping across the scale // 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_STREAM ||
new_mode == ADC_OPMODE_BLCAP) { 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); assert_param(priv->opmode == ADC_OPMODE_ARMED || priv->opmode == ADC_OPMODE_IDLE);
// during the capture, we disallow direct readout and averaging to reduce overhead // during the capture, we disallow direct readout and averaging to reduce overhead

Loading…
Cancel
Save