5.2 ndigo6g12_app.h

  1#pragma once
  2#include "delay.h"
  3#include "ndigo6g12_interface.h"
  4#include <map>
  5#include <string>
  6#include <vector>
  7
  8// Base class for Ndigo6G applications
  9// contains common code for packet processing
 10class Ndigo6GApp {
 11  protected:
 12    const int PRECURSOR = 1;
 13    // contains the timing parameters of the current mode like sample period
 14    ndigo6g12_param_info *pi;
 15    int adcThreshold;
 16    int tdcChannelMask;
 17    // convenience method for adding the TDC channels to the channel map
 18    void AddTDCChannels(std::map<int, std::string> &channelMap) {
 19        for (int i = 0; i < 4; i++) {
 20            if (tdcChannelMask & (1 << i)) {
 21                channelMap[4 + i] = (char)'E' + (char)i;
 22            }
 23        }
 24    }
 25
 26  public:
 27    Ndigo6GApp(int tdcChannelMask) { this->tdcChannelMask = tdcChannelMask; }
 28
 29    // configure the Ndigo6G with the appropiate mode and triggers
 30    virtual void ConfigureADC(ndigo6g12_configuration *config,
 31                              int adcThreshold) = 0;
 32
 33    virtual void ConfigureTDC(ndigo6g12_configuration *config);
 34
 35    // react to an ADC incoming packet
 36    virtual double ProcessADCPacket(crono_packet *pkt) = 0;
 37
 38    // set the parameters after configuration was successful
 39    virtual void SetParamInfo(ndigo6g12_param_info *pi) { this->pi = pi; }
 40
 41    // called by the main loop on a TDC packet arrival
 42    virtual void ProcessTDCPacket(crono_packet *pkt);
 43
 44    // react to an incoming TDC packet, called by default implementation of
 45    // ProcessTDCPacket
 46    virtual void ProcessTDCTimestamp(int tdcChannel, double timestamp) {
 47        printf("TDC event on channel %d timestamp: %.3f ns\n", tdcChannel,
 48               timestamp / 1000.0);
 49    };
 50
 51    // helper method to find the timestamp of the current packet
 52    double ComputePacketTimestamp(volatile crono_packet *pkt) {
 53        // calculate packet timestamp in picoseconds
 54        // the precursor time is constant in the modes, but the amount of
 55        // samples is different (32/16/8 for 1/2/4)
 56        double packet_ts =
 57            pkt->timestamp * pi->packet_ts_period - PRECURSOR * 5e3 ;
 58        return packet_ts;
 59    }
 60
 61    // Computes the falling edge in the given data, returns the absolute ps
 62    // value, and -1 if threshold was not passed in the packet.
 63    double ComputeFallingEdge(crono_packet *pkt) {
 64        // packet length is number of 64-bit words of data
 65        double packetTs = ComputePacketTimestamp(pkt);
 66        // 4 ADC samples are stored in each 64-bit chunk of packet data
 67        uint32_t sampleCount = (pkt->length * 4);
 68
 69        // ADC data is a signed 16-bit integer
 70        int16_t *adc_data = (int16_t *)(pkt->data);
 71
 72        // find first falling edge in ADC data
 73        for (uint32_t i = 0; i < (sampleCount - 1); i++) {
 74            if (adc_data[i] >= adcThreshold && adc_data[i + 1] < adcThreshold) {
 75                // calculate threshold crossing relative to start of packet
 76                double feOffset = i;
 77                // linear interpolation of trigger threshold crossing
 78                feOffset += (double)(adc_data[i] - adcThreshold) /
 79                            (adc_data[i] - adc_data[i + 1]);
 80                // convert to picoseconds
 81                feOffset *= pi->sample_period;
 82
 83                // calculate timestamp of threshold crossing in picoseconds
 84                double fallingEdgeTs = packetTs + feOffset;
 85                // adjust for ADC pipeline delay
 86                fallingEdgeTs -= pi->adc_sample_delay;
 87
 88                return fallingEdgeTs;
 89            }
 90        }
 91        return -1;
 92    }
 93
 94
 95};
 96// maximum distance of two pulses, so that they are considered to be a cable delay
 97static const double MAX_DELAY_PS = 500000.;
 98
 99class Ndigo6GAppSingle : public Ndigo6GApp {
100  private:
101    // last falling edge to compute the difference to
102    double lastFallingEdgeTs = 0;
103
104  public:
105    Ndigo6GAppSingle(int tdcChannelMask) : Ndigo6GApp(tdcChannelMask) {
106    }
107    virtual void ConfigureADC(ndigo6g12_configuration *config,
108                              int adc_threshold);
109    virtual double ProcessADCPacket(crono_packet *pkt);
110    virtual void ProcessTDCTimestamp(int tdcChannel, double timestamp) {}
111};
112
113
114
115// Implementation of the different sample applications
116class Ndigo6GAppDual : public Ndigo6GApp {
117  private:
118    DelayMeasurement delayMeasure;
119
120  public:
121    Ndigo6GAppDual(int tdcChannelMask) : Ndigo6GApp(tdcChannelMask) {
122        std::map<int, std::string> channelMap = {{0, "A"}, {3, "D"}};
123        AddTDCChannels(channelMap);
124        delayMeasure.Init(0, MAX_DELAY_PS, channelMap);
125    }
126    virtual void ConfigureADC(ndigo6g12_configuration *config,
127                              int adc_threshold);
128
129    virtual double ProcessADCPacket(crono_packet *pkt);
130
131    virtual void ProcessTDCTimestamp(int tdcChannel, double timestamp);
132    virtual void SetParamInfo(ndigo6g12_param_info *pi) {
133        Ndigo6GApp::SetParamInfo(pi);
134        // we have to wait for 3 TDC periods to make sure that the TDC data has
135        // arrived
136        delayMeasure.SetMaxWaitTime(pi->tdc_rollover_period * 3.5 *
137                                    pi->tdc_period);
138    }
139};
140
141class Ndigo6GAppQuad : public Ndigo6GApp {
142  private:
143    DelayMeasurement delayMeasure;
144
145  public:
146    Ndigo6GAppQuad(int tdcChannelMask) : Ndigo6GApp(tdcChannelMask) {
147
148        std::map<int, std::string> channelMap = {
149            {0, "A"}, {1, "B"}, {2, "C"}, {3, "D"}};
150        AddTDCChannels(channelMap);
151        delayMeasure.Init(0, MAX_DELAY_PS, channelMap);
152    }
153
154    virtual void ConfigureADC(ndigo6g12_configuration *config,
155                              int adc_threshold);
156
157    virtual  void SetParamInfo(ndigo6g12_param_info *pi) {
158        Ndigo6GApp::SetParamInfo( pi);
159        // we have to wait for 3 TDC periods to make sure that the TDC data has
160        // arrived
161        delayMeasure.SetMaxWaitTime(pi->tdc_rollover_period * 3.5 *
162                                    pi->packet_ts_period);
163    }
164
165    virtual double ProcessADCPacket(crono_packet *pkt);
166
167    virtual void ProcessTDCTimestamp(int tdcChannel, double timestamp);
168};
169
170class Ndigo6GAppAverager : public Ndigo6GApp {
171  private:
172    // last falling edge to compute the difference to
173    double lastFallingEdgeTs = 0;
174
175  public:
176    Ndigo6GAppAverager(int tdcChannelMask) : Ndigo6GApp(tdcChannelMask) {}
177    virtual void ConfigureADC(ndigo6g12_configuration *config,
178                              int adc_threshold);
179    virtual double ProcessADCPacket(crono_packet *pkt);
180};