satdump/plugins/jpss_support/jpss/instruments/atms/atms_reader.cpp
2024-05-09 01:16:08 +02:00

218 lines
No EOL
8.4 KiB
C++

#include "atms_reader.h"
#include "common/ccsds/ccsds_time.h"
#include "common/repack.h"
namespace jpss
{
namespace atms
{
ATMSReader::ATMSReader()
{
for (int i = 0; i < 22; i++)
{
channels[i].resize(96);
channels_cc[i].resize(4);
channels_wc[i].resize(4);
}
lines = 0;
scan_pos = -1;
}
ATMSReader::~ATMSReader()
{
for (int i = 0; i < 22; i++)
channels[i].clear();
}
void ATMSReader::work(ccsds::CCSDSPacket &packet)
{
// Filter out bad packets
if (packet.payload.size() < 56)
return;
// Is there a sync signal?
int scan_synch = packet.payload[10] >> 7;
// If there is, trigger a new scanline
if (scan_synch == 1)
{
calib_data[lines]["calibration_pkt"] = last_calib_pkt;
calib_data[lines]["engineering_pkt"] = last_eng_pkt;
calib_data[lines]["hotcal_pkt"] = last_hot_pkt;
lines++;
timestamps.push_back(ccsds::parseCCSDSTimeFull(packet, -4383));
scan_pos = 0;
for (int i = 0; i < 22; i++)
{
channels[i].resize((lines + 1) * 96);
channels_cc[i].resize((lines + 1) * 4);
channels_wc[i].resize((lines + 1) * 4);
}
}
int16_t beam_angle = 0;
((uint8_t *)&beam_angle)[1] = packet.payload[8 + 0];
((uint8_t *)&beam_angle)[0] = packet.payload[8 + 1];
// Safeguard
if (scan_pos < 96 && scan_pos >= 0)
{
for (int i = 0; i < 22; i++) // Decode all channels
channels[i][(lines * 96) + 95 - scan_pos] = (packet.payload[12 + i * 2] << 8 | packet.payload[13 + i * 2]);
calib_data[lines]["beam_pos_sc"][95 - scan_pos] = beam_angle;
}
else if (scan_pos - 96 < 4 && scan_pos - 96 >= 0)
{
for (int i = 0; i < 22; i++) // Decode all channels
channels_cc[i][(lines * 4) + (scan_pos - 96)] = (packet.payload[12 + i * 2] << 8 | packet.payload[13 + i * 2]);
calib_data[lines]["beam_pos_cc"][scan_pos - 96] = beam_angle;
}
else if (scan_pos - 96 - 4 < 4 && scan_pos - 96 - 4 >= 0)
{
for (int i = 0; i < 22; i++) // Decode all channels
channels_wc[i][(lines * 4) + (scan_pos - 96 - 4)] = (packet.payload[12 + i * 2] << 8 | packet.payload[13 + i * 2]);
calib_data[lines]["beam_pos_wc"][scan_pos - 96 - 4] = beam_angle;
}
scan_pos++;
}
inline double parse_pam_gamma0(uint16_t word) { return 2300.0 + 0.006 * word; }
inline double parse_4w_2w_r0(uint16_t word) { return 1900.0 + 0.003 * word; }
inline double parse_4w_2w_alpha(uint16_t word) { return 0.002 + 5e-8 * word; }
inline double parse_4w_2w_delta(uint16_t word) { return 5e-5 * word; }
inline double parse_4w_prt_beta(uint16_t word) { return 6e-5 * word - 2.0; }
inline double parse_calibration_target_offset(uint16_t word) { return -7.5e-6 * word; }
inline double parse_cold_calibration_offset(uint16_t word) { return 1.5e-5 * word; }
inline double parse_quadratic_coefficient(uint16_t word) { return 2.6e-5 * word - 0.850; }
inline double parse_alignement(uint16_t word) { return 2.0e-5 * word - 0.655; }
inline double parse_2w_prt_a(uint16_t word) { return 3.0e-6 * word; }
inline double parse_rc(uint16_t word) { return 0.0003 * word; }
inline double parse_muxresti(uint16_t word) { return 1900.0 + 0.003 * word; }
void ATMSReader::work_calib(ccsds::CCSDSPacket &packet)
{
// Filter out bad packets
if (packet.payload.size() < 438)
return;
// Parse calibration packet
ATMSCalibPkt calib_pkt;
uint16_t words[215];
repackBytesTo16bits(&packet.payload[8], 430, words);
calib_pkt.pamKav = parse_pam_gamma0(words[0]);
calib_pkt.pamWg = parse_pam_gamma0(words[1]);
for (int i = 0; i < NUM_PRT_KAV; i++)
{
calib_pkt.prtCoeffKav[i][0] = parse_4w_2w_r0(words[2 + 4 * i + 0]);
calib_pkt.prtCoeffKav[i][1] = parse_4w_2w_alpha(words[2 + 4 * i + 1]);
calib_pkt.prtCoeffKav[i][2] = parse_4w_2w_delta(words[2 + 4 * i + 2]);
calib_pkt.prtCoeffKav[i][3] = parse_4w_prt_beta(words[2 + 4 * i + 3]);
}
for (int i = 0; i < NUM_PRT_WG; i++)
{
calib_pkt.prtCoeffWg[i][0] = parse_4w_2w_r0(words[34 + 4 * i + 0]);
calib_pkt.prtCoeffWg[i][1] = parse_4w_2w_alpha(words[34 + 4 * i + 1]);
calib_pkt.prtCoeffWg[i][2] = parse_4w_2w_delta(words[34 + 4 * i + 2]);
calib_pkt.prtCoeffWg[i][3] = parse_4w_prt_beta(words[34 + 4 * i + 3]);
}
for (int i = 0; i < NUM_ATMS_BANDS; i++)
calib_pkt.warmBias[i] = parse_calibration_target_offset(words[62 + i]);
for (int i = 0; i < NUM_ATMS_BANDS; i++)
calib_pkt.coldBias[i] = parse_cold_calibration_offset(words[67 + i]);
for (int i = 0; i < 22; i++)
calib_pkt.quadraticCoeffs[i] = parse_quadratic_coefficient(words[72 + i]);
// Beam alignement - Skipped
for (int i = 0; i < NUM_PRT_COEFFS; i++)
{
calib_pkt.prtCoeffShelf[i][0] = parse_4w_2w_r0(words[139 + 4 * i + 0]);
calib_pkt.prtCoeffShelf[i][1] = parse_4w_2w_alpha(words[139 + 4 * i + 1]);
calib_pkt.prtCoeffShelf[i][2] = parse_4w_2w_delta(words[139 + 4 * i + 2]);
calib_pkt.prtCoeffShelf[i][3] = parse_rc(words[139 + 4 * i + 3]);
}
for (int i = 0; i < NUM_PRT_COEFF_2WIRE / 2; i++)
{
calib_pkt.prtCoeff2Wire[i * 2 + 0] = parse_4w_2w_r0(words[155 + 2 * i + 0]);
calib_pkt.prtCoeff2Wire[i * 2 + 1] = parse_2w_prt_a(words[155 + 2 * i + 1]);
}
for (int i = 0; i < NUM_HOUSE_KEEPING; i++)
{
calib_pkt.houseKeeping[i] = parse_muxresti(words[211 + i]);
}
calib_pkt.valid = true;
last_calib_pkt = calib_pkt;
}
void ATMSReader::work_eng(ccsds::CCSDSPacket &packet)
{
// Filter out bad packets
if (packet.payload.size() < 156)
return;
ATMSHealtStatusPkt eng_pkt;
uint16_t words[74];
repackBytesTo16bits(&packet.payload[8], 148, words);
for (int i = 0; i < NUM_HS_VARS; i++)
eng_pkt.data[i] = words[i];
eng_pkt.valid = true;
last_eng_pkt = eng_pkt;
}
void ATMSReader::work_hotcal(ccsds::CCSDSPacket &packet)
{
// Filter out bad packets
if (packet.payload.size() < 42)
return;
ATMSHotCalTempPkt hot_pkt;
uint16_t words[17];
repackBytesTo16bits(&packet.payload[8], 34, words);
for (int i = 0; i < NUM_PRT_KAV; i++)
hot_pkt.kavPrt[i] = words[i];
hot_pkt.kavPamCounts = words[8];
for (int i = 0; i < NUM_PRT_WG; i++)
hot_pkt.wqPrt[i] = words[9 + i];
hot_pkt.wgPamCounts = words[16];
hot_pkt.valid = true;
last_hot_pkt = hot_pkt;
}
image::Image ATMSReader::getChannel(int channel)
{
return image::Image(channels[channel].data(), 16, 96, lines, 1);
}
nlohmann::json ATMSReader::getCalib()
{
for (int i = 0; i < lines; i++)
for (int c = 0; c < 22; c++)
for (int z = 0; z < 4; z++)
calib_data[i]["cold_counts"][c][z] = channels_cc[c][i * 4 + z];
for (int i = 0; i < lines; i++)
for (int c = 0; c < 22; c++)
for (int z = 0; z < 4; z++)
calib_data[i]["warm_counts"][c][z] = channels_wc[c][i * 4 + z];
return calib_data;
}
} // namespace atms
} // namespace jpss