5.6 ndigo6g12_adc_averager.cpp
¶
1#include <stdio.h>
2#include "ndigo6g12_app.h"
3
4const int AVERAGING_COUNT = 16;
5
6double Ndigo6GAppAverager::ProcessADCPacket(crono_packet* pkt) {
7
8 // calculate packet timestamp in picoseconds
9 // not adjusted for ADC-data precursor
10 double packet_ts = pkt->timestamp * pi->packet_ts_period;
11
12 printf("\nPacket timestamp: %.3f ns\n", (packet_ts / 1000.0));
13
14 // packet length is number of 64-bit words of data
15 // the first two 64-bit packet data words are additional header
16 // information
17 uint32_t data_offset = 2;
18 // only the first currently carries valid information
19 uint64_t averaging_header0 = *(pkt->data);
20
21 // if bit is set, less than the requested number of iterations have been
22 // performed before writing the packet due to possible data overflow on
23 // the next iteration
24 bool stopped_due_to_overflow = (averaging_header0 >> 32) & 0x1;
25
26 // if bit is set, the averaged data contains saturated or overflowed
27 // samples does NOT indicate that the input signal has not exceeded the
28 // ADC range
29 bool averaging_overflow = (averaging_header0 >> 32) & 0x2;
30
31 // number of iterations; may be less than requested
32 int iterations_performed = (averaging_header0 & 0xffffff);
33
34 // 2 averaged ADC samples are stored in each 64-bit chunk of packet data
35 uint32_t sample_count = ((pkt->length - data_offset) * 2);
36
37 // ADC data is a signed 32-bit integer
38 int32_t* adc_data = (int32_t*)(pkt->data + data_offset);
39
40 // find first falling edge in averaging data
41 for (uint32_t i = 0; i < sample_count - 1; i++) {
42 if (adc_data[i] >= 0 && adc_data[i + 1] < 0) {
43 // calculate threshold crossing relative to start of packet
44 double fe_offset = i;
45 // linear interpolation of trigger threshold crossing
46 fe_offset +=
47 (double)(adc_data[i] - 0) / (adc_data[i] - adc_data[i + 1]);
48 // calculate timestamp of threshold crossing in picoseconds
49 fe_offset *= pi->sample_period;
50
51 printf("Falling edge event - offset to packet start: %.3f ns\n",
52 (fe_offset / 1000.0));
53 break;
54 }
55 }
56 return packet_ts;
57}
58
59void Ndigo6GAppAverager::ConfigureADC(ndigo6g12_configuration* config,
60 int adcThreshold) {
61 // adcThreshold not used here, 0 is used as threshold for the data
62 config->adc_mode = NDIGO6G12_ADC_MODE_A;
63
64 // ADC sample value range -32768 .. 32767
65 // averaging data saturates at +/- 2^21 - 1
66 config->output_mode = NDIGO6G12_OUTPUT_MODE_SIGNED32;
67
68 // enable ADC channel A and trigger on the falling edge of TRG input
69 // shift baseline of analog inputs to +350 mV
70 config->analog_offsets[0] = NDIGO6G12_DC_OFFSET_N_NIM * -1;
71
72 // trigger on falling edge of TRG input
73 config->trigger[NDIGO6G12_TRIGGER_TRG].edge = true;
74 config->trigger[NDIGO6G12_TRIGGER_TRG].rising = false;
75
76 // set trigger level on TRG input to -350 mV
77 config->tdc_trigger_offsets[4] = NDIGO6G12_DC_OFFSET_N_NIM;
78
79 // enable channel
80 config->trigger_block[0].enabled = true;
81 // multiples of 32 ADC samples (5 ns recording time)
82 config->trigger_block[0].length = 32764;
83
84 // select TRG as trigger source of the channel
85 config->trigger_block[0].sources = NDIGO6G12_TRIGGER_SOURCE_TRG;
86
87 // configuration of the Averaging features
88 // number of events that are averaged/summed
89 config->average_configuration.iterations = AVERAGING_COUNT;
90
91 // saturate averaging data instead of overflow
92 config->average_configuration.use_saturation = true;
93
94 // don't stop averaging if next iteration could lead to sample data overflow
95 config->average_configuration.stop_on_overflow = false;
96}