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
 97// a cable delay
 98static const double MAX_DELAY_PS = 500000.;
 99
100class Ndigo6GAppSingle : public Ndigo6GApp {
101  private:
102    // last falling edge to compute the difference to
103    double lastFallingEdgeTs = 0;
104
105  public:
106    Ndigo6GAppSingle(int tdcChannelMask) : Ndigo6GApp(tdcChannelMask) {
107    }
108    virtual void ConfigureADC(ndigo6g12_configuration *config,
109                              int adc_threshold);
110    virtual double ProcessADCPacket(crono_packet *pkt);
111    virtual void ProcessTDCTimestamp(int tdcChannel, double timestamp) {}
112};
113
114
115
116// Implementation of the different sample applications
117class Ndigo6GAppDual : public Ndigo6GApp {
118  private:
119    DelayMeasurement delayMeasure;
120
121  public:
122    Ndigo6GAppDual(int tdcChannelMask) : Ndigo6GApp(tdcChannelMask) {
123        std::map<int, std::string> channelMap = {{0, "A"}, {3, "D"}};
124        AddTDCChannels(channelMap);
125        delayMeasure.Init(0, MAX_DELAY_PS, channelMap);
126    }
127    virtual void ConfigureADC(ndigo6g12_configuration *config,
128                              int adc_threshold);
129
130    virtual double ProcessADCPacket(crono_packet *pkt);
131
132    virtual void ProcessTDCTimestamp(int tdcChannel, double timestamp);
133    virtual void SetParamInfo(ndigo6g12_param_info *pi) {
134        Ndigo6GApp::SetParamInfo(pi);
135        // we have to wait for 3 TDC periods to make sure that the TDC data has
136        // arrived
137        delayMeasure.SetMaxWaitTime(pi->tdc_rollover_period * 3.5 *
138                                    pi->tdc_period);
139    }
140};
141
142class Ndigo6GAppQuad : public Ndigo6GApp {
143  private:
144    DelayMeasurement delayMeasure;
145
146  public:
147    Ndigo6GAppQuad(int tdcChannelMask) : Ndigo6GApp(tdcChannelMask) {
148
149        std::map<int, std::string> channelMap = {
150            {0, "A"}, {1, "B"}, {2, "C"}, {3, "D"}};
151        AddTDCChannels(channelMap);
152        delayMeasure.Init(0, MAX_DELAY_PS, channelMap);
153    }
154
155    virtual void ConfigureADC(ndigo6g12_configuration *config,
156                              int adc_threshold);
157
158    virtual  void SetParamInfo(ndigo6g12_param_info *pi) {
159        Ndigo6GApp::SetParamInfo( pi);
160        // we have to wait for 3 TDC periods to make sure that the TDC data has
161        // arrived
162        delayMeasure.SetMaxWaitTime(pi->tdc_rollover_period * 3.5 *
163                                    pi->packet_ts_period);
164    }
165
166    virtual double ProcessADCPacket(crono_packet *pkt);
167
168    virtual void ProcessTDCTimestamp(int tdcChannel, double timestamp);
169};
170
171class Ndigo6GAppAverager : public Ndigo6GApp {
172  private:
173    // last falling edge to compute the difference to
174    double lastFallingEdgeTs = 0;
175
176  public:
177    Ndigo6GAppAverager(int tdcChannelMask) : Ndigo6GApp(tdcChannelMask) {}
178    virtual void ConfigureADC(ndigo6g12_configuration *config,
179                              int adc_threshold);
180    virtual double ProcessADCPacket(crono_packet *pkt);
181};