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}