125 lines
4.5 KiB
C++
125 lines
4.5 KiB
C++
// Copyright (2019-2023) Paul Scherrer Institute
|
|
|
|
#include "JFConversionFixedPoint.h"
|
|
#include "../common/RawToConvertedGeometry.h"
|
|
|
|
#define FIXED_PRECISION 14
|
|
|
|
JFConversionFixedPoint::JFConversionFixedPoint() {
|
|
gain_g0 = (int32_t *) std::aligned_alloc(64, RAW_MODULE_SIZE * sizeof(int32_t));
|
|
gain_g1 = (int32_t *) std::aligned_alloc(64, RAW_MODULE_SIZE * sizeof(int32_t));
|
|
gain_g2 = (int32_t *) std::aligned_alloc(64, RAW_MODULE_SIZE * sizeof(int32_t));
|
|
pedestal_g0 = (uint16_t *) std::aligned_alloc(64, RAW_MODULE_SIZE * sizeof(uint16_t));
|
|
pedestal_g1 = (uint16_t *) std::aligned_alloc(64, RAW_MODULE_SIZE * sizeof(uint16_t));
|
|
pedestal_g2 = (uint16_t *) std::aligned_alloc(64, RAW_MODULE_SIZE * sizeof(uint16_t));
|
|
}
|
|
|
|
JFConversionFixedPoint::~JFConversionFixedPoint() {
|
|
std::free(gain_g0);
|
|
std::free(gain_g1);
|
|
std::free(gain_g2);
|
|
std::free(pedestal_g0);
|
|
std::free(pedestal_g1);
|
|
std::free(pedestal_g2);
|
|
}
|
|
|
|
inline int32_t one_over_gain_energy(double gain_factor, double energy) {
|
|
double tmp = gain_factor * energy;
|
|
if (!std::isfinite(tmp) || (tmp == 0.0))
|
|
return INT16_MIN;
|
|
else
|
|
return std::lround((1 << FIXED_PRECISION) / (gain_factor * energy));
|
|
}
|
|
|
|
void JFConversionFixedPoint::Setup(const JFModuleGainCalibration &gain_calibration,
|
|
const JFModulePedestal &in_pedestal_g0,
|
|
const JFModulePedestal &in_pedestal_g1,
|
|
const JFModulePedestal &in_pedestal_g2,
|
|
double energy) {
|
|
auto &gain_arr = gain_calibration.GetGainCalibration();
|
|
memcpy(pedestal_g0, in_pedestal_g0.GetPedestal(), RAW_MODULE_SIZE * sizeof(uint16_t));
|
|
memcpy(pedestal_g1, in_pedestal_g1.GetPedestal(), RAW_MODULE_SIZE * sizeof(uint16_t));
|
|
memcpy(pedestal_g2, in_pedestal_g2.GetPedestal(), RAW_MODULE_SIZE * sizeof(uint16_t));
|
|
|
|
for (int i = 0; i < RAW_MODULE_SIZE; i++) {
|
|
gain_g0[i] = one_over_gain_energy(gain_arr[i], energy);
|
|
gain_g1[i] = one_over_gain_energy(gain_arr[i + RAW_MODULE_SIZE], energy);
|
|
gain_g2[i] = one_over_gain_energy(gain_arr[i + 2 * RAW_MODULE_SIZE], energy);
|
|
}
|
|
}
|
|
|
|
inline int32_t jf_round(int32_t in) {
|
|
const int32_t half = (1L << (FIXED_PRECISION-1));
|
|
|
|
if (in <= INT16_MIN * (1L << FIXED_PRECISION))
|
|
return INT16_MIN * (1L << FIXED_PRECISION);
|
|
else if (in >= INT16_MAX * (1L << FIXED_PRECISION))
|
|
return INT16_MAX * (1L << FIXED_PRECISION);
|
|
else if (in > 0)
|
|
return in + half;
|
|
else
|
|
return in - half;
|
|
}
|
|
|
|
void JFConversionFixedPoint::ConvertModule(int16_t *__restrict dest, const uint16_t *source) {
|
|
auto gain_g0_aligned = std::assume_aligned<64>(gain_g0);
|
|
auto gain_g1_aligned = std::assume_aligned<64>(gain_g1);
|
|
auto gain_g2_aligned = std::assume_aligned<64>(gain_g2);
|
|
auto pedestal_g0_aligned = std::assume_aligned<64>(pedestal_g0);
|
|
auto pedestal_g1_aligned = std::assume_aligned<64>(pedestal_g1);
|
|
auto pedestal_g2_aligned = std::assume_aligned<64>(pedestal_g2);
|
|
|
|
#pragma ivdep
|
|
for (int i = 0; i < RAW_MODULE_SIZE; i++) {
|
|
uint16_t gainbits = source[i] & 0xc000;
|
|
int32_t adc = source[i] & 0x3fff;
|
|
|
|
dest[i] = static_cast<int16_t>(jf_round((adc - pedestal_g0_aligned[i]) * gain_g0_aligned[i])
|
|
/ (1L << FIXED_PRECISION));
|
|
|
|
int16_t val_1 = jf_round((adc - pedestal_g1_aligned[i]) * gain_g1_aligned[i])
|
|
/ (1L << FIXED_PRECISION);
|
|
|
|
int16_t val_2 = jf_round((adc - pedestal_g2_aligned[i]) * gain_g2_aligned[i])
|
|
/ (1L << FIXED_PRECISION);
|
|
|
|
if (gainbits == 0x4000)
|
|
dest[i] = val_1;
|
|
|
|
if (gainbits == 0xc000)
|
|
dest[i] = val_2;
|
|
|
|
if (gainbits == 0x8000)
|
|
dest[i] = INT16_MIN;
|
|
|
|
if (source[i] == 0xffff)
|
|
dest[i] = INT16_MIN;
|
|
|
|
if (source[i] == 0x4000)
|
|
dest[i] = INT16_MIN;
|
|
|
|
if (source[i] == 0xc000)
|
|
dest[i] = INT16_MAX;
|
|
}
|
|
}
|
|
|
|
JFConversionFixedPoint::JFConversionFixedPoint(JFConversionFixedPoint &&other) noexcept {
|
|
gain_g0 = other.gain_g0;
|
|
other.gain_g0 = nullptr;
|
|
|
|
gain_g1 = other.gain_g1;
|
|
other.gain_g1 = nullptr;
|
|
|
|
gain_g2 = other.gain_g2;
|
|
other.gain_g2 = nullptr;
|
|
|
|
pedestal_g0 = other.pedestal_g0;
|
|
other.pedestal_g0 = nullptr;
|
|
|
|
pedestal_g1 = other.pedestal_g1;
|
|
other.pedestal_g1 = nullptr;
|
|
|
|
pedestal_g2 = other.pedestal_g2;
|
|
other.pedestal_g2 = nullptr;
|
|
}
|