mirror of
https://github.com/SatDump/SatDump
synced 2026-08-13 17:47:30 -04:00
Semi-temp-fix for 32-APSK in DVB-S2!
This commit is contained in:
parent
0b55ce440a
commit
6ac88342b2
5 changed files with 373 additions and 21 deletions
|
|
@ -121,6 +121,30 @@ namespace dvbs2
|
|||
cfg.g1 = 2.84;
|
||||
cfg.g2 = 5.27;
|
||||
}
|
||||
else if (modcod == 25)
|
||||
{
|
||||
cfg.coderate = dvbs2::C4_5;
|
||||
cfg.g1 = 2.72;
|
||||
cfg.g2 = 4.87;
|
||||
}
|
||||
else if (modcod == 26)
|
||||
{
|
||||
cfg.coderate = dvbs2::C5_6;
|
||||
cfg.g1 = 2.64;
|
||||
cfg.g2 = 4.64;
|
||||
}
|
||||
else if (modcod == 27)
|
||||
{
|
||||
cfg.coderate = dvbs2::C8_9;
|
||||
cfg.g1 = 2.54;
|
||||
cfg.g2 = 4.33;
|
||||
}
|
||||
else if (modcod == 28)
|
||||
{
|
||||
cfg.coderate = dvbs2::C9_10;
|
||||
cfg.g1 = 2.53;
|
||||
cfg.g2 = 4.30;
|
||||
}
|
||||
}
|
||||
else
|
||||
throw std::runtime_error("MODCOD not (yet?) supported!");
|
||||
|
|
|
|||
|
|
@ -67,8 +67,8 @@ namespace dsp
|
|||
const_states = 16;
|
||||
const_bits = 4;
|
||||
const_amp = 100;
|
||||
const_sca = 1; // 0.5;
|
||||
const_prescale = 0.53;
|
||||
const_sca = 1; // 0.5;
|
||||
const_prescale = 0.53;
|
||||
|
||||
constellation = new complex_t[const_states];
|
||||
|
||||
|
|
@ -104,8 +104,8 @@ namespace dsp
|
|||
const_states = 32;
|
||||
const_bits = 5;
|
||||
const_amp = 100;
|
||||
const_sca = 0.5;
|
||||
const_prescale = 0.5;
|
||||
const_sca = 1; // 0.5;
|
||||
const_prescale = 0.54;
|
||||
|
||||
constellation = new complex_t[const_states];
|
||||
|
||||
|
|
@ -314,29 +314,36 @@ namespace dsp
|
|||
|
||||
void constellation_t::demod_soft_lut(complex_t sample, int8_t *bits, float *phase_error)
|
||||
{
|
||||
int x = (sample.real / 1.5) * lut_resolution + lut_resolution / 2;
|
||||
if (const_bits != 5)
|
||||
{
|
||||
int x = (sample.real / 1.5) * lut_resolution + lut_resolution / 2;
|
||||
#if 1
|
||||
if (x < 0)
|
||||
x = 0;
|
||||
if (x >= lut_resolution)
|
||||
x = lut_resolution - 1;
|
||||
if (x < 0)
|
||||
x = 0;
|
||||
if (x >= lut_resolution)
|
||||
x = lut_resolution - 1;
|
||||
#endif
|
||||
|
||||
int y = (sample.imag / 1.5) * lut_resolution + lut_resolution / 2;
|
||||
int y = (sample.imag / 1.5) * lut_resolution + lut_resolution / 2;
|
||||
#if 1
|
||||
if (y < 0)
|
||||
y = 0;
|
||||
if (y >= lut_resolution)
|
||||
y = lut_resolution - 1;
|
||||
if (y < 0)
|
||||
y = 0;
|
||||
if (y >= lut_resolution)
|
||||
y = lut_resolution - 1;
|
||||
#endif
|
||||
|
||||
SoftResult &v = lut[x][y];
|
||||
SoftResult &v = lut[x][y];
|
||||
|
||||
if (bits != nullptr)
|
||||
for (int i = 0; i < const_bits; i++)
|
||||
bits[i] = v.bits[i];
|
||||
if (bits != nullptr)
|
||||
for (int i = 0; i < const_bits; i++)
|
||||
bits[i] = v.bits[i];
|
||||
|
||||
if (phase_error != nullptr)
|
||||
*phase_error = v.phase_error;
|
||||
if (phase_error != nullptr)
|
||||
*phase_error = v.phase_error;
|
||||
}
|
||||
else
|
||||
{
|
||||
demod_soft_calc(sample, bits, phase_error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +1,2 @@
|
|||
add_subdirectory(proj_test)
|
||||
add_subdirectory(proj_test)
|
||||
add_subdirectory(dvbs2_mod)
|
||||
9
tools/dvbs2_mod/CMakeLists.txt
Normal file
9
tools/dvbs2_mod/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
cmake_minimum_required (VERSION 3.0.0)
|
||||
|
||||
file(GLOB_RECURSE SatDump_testing_CPPS *.cpp)
|
||||
|
||||
add_executable(dvbs2_mod ${SatDump_testing_CPPS})
|
||||
target_include_directories(dvbs2_mod PUBLIC src-testing src-core)
|
||||
|
||||
# Link against the core
|
||||
target_link_libraries (dvbs2_mod PUBLIC satdump_core)
|
||||
311
tools/dvbs2_mod/main.cpp
Normal file
311
tools/dvbs2_mod/main.cpp
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
/**********************************************************************
|
||||
* This file is used for testing random stuff without running the
|
||||
* whole of SatDump, which comes in handy for debugging individual
|
||||
* elements before putting them all together in modules...
|
||||
*
|
||||
* If you are an user, ignore this file which will not be built by
|
||||
* default, and if you're a developper in need of doing stuff here...
|
||||
* Go ahead!
|
||||
*
|
||||
* Don't judge the code you might see in there! :)
|
||||
**********************************************************************/
|
||||
|
||||
#include "logger.h"
|
||||
#include <fstream>
|
||||
|
||||
#include "common/codings/dvb-s2/bbframe_descramble.h"
|
||||
#include "common/codings/dvb-s2/bbframe_bch.h"
|
||||
#include "common/codings/dvb-s2/bbframe_ldpc.h"
|
||||
#include "common/codings/dvb-s2/s2_deinterleaver.h"
|
||||
#include "common/dsp/constellation.h"
|
||||
#include "common/codings/dvb-s2/s2_scrambling.h"
|
||||
#include "modules/demod/dvbs2/s2_defs.h"
|
||||
#include "common/codings/dvb-s2/modcod_to_cfg.h"
|
||||
|
||||
#include "common/dsp/rational_resampler.h"
|
||||
#include "common/dsp/firdes.h"
|
||||
#include "common/dsp/file_sink.h"
|
||||
|
||||
#include "common/cli_utils.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
unsigned char crc_tab[256];
|
||||
|
||||
#define CRC_POLY 0xAB
|
||||
// Reversed
|
||||
#define CRC_POLYR 0xD5
|
||||
|
||||
void build_crc8_table(void)
|
||||
{
|
||||
int r, crc;
|
||||
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
r = i;
|
||||
crc = 0;
|
||||
for (int j = 7; j >= 0; j--)
|
||||
{
|
||||
if ((r & (1 << j) ? 1 : 0) ^ ((crc & 0x80) ? 1 : 0))
|
||||
{
|
||||
crc = (crc << 1) ^ CRC_POLYR;
|
||||
}
|
||||
else
|
||||
{
|
||||
crc <<= 1;
|
||||
}
|
||||
}
|
||||
crc_tab[i] = crc;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* MSB is sent first
|
||||
*
|
||||
* The polynomial has been reversed
|
||||
*/
|
||||
int add_crc8_bits(unsigned char *in, int length)
|
||||
{
|
||||
int crc = 0;
|
||||
int b;
|
||||
|
||||
for (int n = 0; n < length; n++)
|
||||
{
|
||||
b = ((in[n / 8] >> (7 - (n % 8))) & 1) ^ (crc & 0x01);
|
||||
crc >>= 1;
|
||||
if (b)
|
||||
{
|
||||
crc ^= CRC_POLY;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t crc2 = 0;
|
||||
for (int i = 0; i < 8; i++)
|
||||
crc2 = crc2 << 1 | ((crc >> i) & 1);
|
||||
|
||||
return crc2;
|
||||
}
|
||||
}
|
||||
|
||||
#include "common/codings/dvb-s2/bbframe_ts_parser.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
initLogger();
|
||||
build_crc8_table();
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
logger->error(std::string(argv[0]) + " input.ts output.f32 --modcod 11 --baseband_format f32 --rrc_alpha 0.25 [--shortframes] [--pilots]");
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////
|
||||
std::string ts_input_path = argv[1];
|
||||
std::string baseband_output_path = argv[2];
|
||||
|
||||
// Parse flags
|
||||
nlohmann::json parameters = parse_common_flags(argc - 3, &argv[3]);
|
||||
|
||||
int modulator_modcod = parameters["modcod"].get<int>();
|
||||
bool modulator_shortframes = parameters.contains("shortframes") ? parameters["shortframes"].get<bool>() : false;
|
||||
bool modulator_pilots = parameters.contains("pilots") ? parameters["pilots"].get<bool>() : false;
|
||||
float modulator_rrc_alpha = parameters["rrc_alpha"].get<float>();
|
||||
std::string baseband_format = parameters["baseband_format"].get<std::string>();
|
||||
/////////////
|
||||
|
||||
// File stuff
|
||||
// std::ofstream bbframes_test("bbframe_test.bin");
|
||||
std::ifstream ts_input(ts_input_path);
|
||||
|
||||
// Get CFG
|
||||
auto cfg = dvbs2::get_dvbs2_cfg(modulator_modcod, modulator_shortframes, modulator_pilots);
|
||||
|
||||
dvbs2::BBFrameDescrambler bbframe_scra(cfg.framesize, cfg.coderate);
|
||||
dvbs2::BBFrameBCH bbframe_bch(cfg.framesize, cfg.coderate);
|
||||
dvbs2::BBFrameLDPC bbframe_ldpc(cfg.framesize, cfg.coderate);
|
||||
dvbs2::S2Deinterleaver interleaver(cfg.constellation, cfg.framesize, cfg.coderate);
|
||||
dsp::constellation_t constellation_slots(cfg.constel_obj_type, cfg.g1, cfg.g2);
|
||||
dvbs2::S2Scrambling s2_scrambling;
|
||||
|
||||
// Bunch of variables
|
||||
int plframe_slots = cfg.frame_slot_count;
|
||||
int final_frm_size = cfg.framesize == dvbs2::FECFRAME_NORMAL ? 64800 : 16200;
|
||||
int final_frm_size_bytes = final_frm_size / 8;
|
||||
int bb_size = bbframe_bch.dataSize();
|
||||
int bb_bytes = bb_size / 8;
|
||||
int bb_data_size = bb_size - 10 * 8;
|
||||
int bb_data_size_bytes = bb_data_size / 8;
|
||||
|
||||
logger->warn("PL Slots : {:d}", plframe_slots);
|
||||
|
||||
// Main BB frame buffer
|
||||
uint8_t bbframe_raw[final_frm_size_bytes];
|
||||
|
||||
// Interleaving stuff
|
||||
uint8_t frame_bits_buf[final_frm_size];
|
||||
uint8_t frame_bits_buf_interleaved[final_frm_size];
|
||||
|
||||
// Modulator stuff
|
||||
int pls_code = modulator_modcod << 2 | modulator_shortframes << 1 | modulator_pilots;
|
||||
dvbs2::s2_sof sof;
|
||||
dvbs2::s2_plscodes pls;
|
||||
// complex_t *modulated_frame; //[(plframe_slots + 1) * 90];
|
||||
|
||||
// TS Stuff
|
||||
int ts_bytes_remaining = 0;
|
||||
int current_ts_offset = 0;
|
||||
uint8_t current_ts[188];
|
||||
uint8_t ts_crc = 0;
|
||||
|
||||
// DSP To do pulse-shaping and saving to disk
|
||||
std::shared_ptr<dsp::stream<complex_t>> input_dsp_stream = std::make_shared<dsp::stream<complex_t>>();
|
||||
// modulated_frame = input_dsp_stream->writeBuf;
|
||||
|
||||
dsp::CCRationalResamplerBlock resampler_blk(input_dsp_stream, 2, 1, dsp::firdes::root_raised_cosine(1, 2, 1, 0.25, 31));
|
||||
std::shared_ptr<dsp::FileSinkBlock> file_sink_blk = std::make_shared<dsp::FileSinkBlock>(resampler_blk.output_stream);
|
||||
|
||||
resampler_blk.start();
|
||||
file_sink_blk->start();
|
||||
file_sink_blk->set_output_sample_type(dsp::basebandTypeFromString(baseband_format));
|
||||
file_sink_blk->start_recording(baseband_output_path, 2e6, 0, true);
|
||||
|
||||
while (!ts_input.eof())
|
||||
{
|
||||
// Reset
|
||||
memset(bbframe_raw, 0, final_frm_size_bytes);
|
||||
|
||||
// Encoder BBFrame
|
||||
{
|
||||
// MAPTYPE
|
||||
uint8_t ts_gs = 0b11;
|
||||
uint8_t sis_mis = 0b1;
|
||||
uint8_t ccm_acm = 0b1;
|
||||
uint8_t issyi = 0b0;
|
||||
uint8_t npd = 0b0;
|
||||
uint8_t ro = 0b11;
|
||||
|
||||
if (modulator_rrc_alpha == 0.35)
|
||||
ro = 0b00;
|
||||
else if (modulator_rrc_alpha == 0.25)
|
||||
ro = 0b01;
|
||||
else if (modulator_rrc_alpha == 0.20)
|
||||
ro = 0b10;
|
||||
|
||||
bbframe_raw[0] = ts_gs << 6 | sis_mis << 5 | ccm_acm << 4 | issyi << 3 | npd << 2 | ro;
|
||||
bbframe_raw[1] = 0x00; // RESERVED since ISI not set
|
||||
|
||||
// UPL
|
||||
uint16_t user_pkt_length = 188 * 8; // TS
|
||||
|
||||
bbframe_raw[2] = user_pkt_length >> 8;
|
||||
bbframe_raw[3] = user_pkt_length & 0xFF;
|
||||
|
||||
// DFL
|
||||
uint16_t bb_pkt_length = bb_data_size;
|
||||
|
||||
bbframe_raw[4] = bb_pkt_length >> 8;
|
||||
bbframe_raw[5] = bb_pkt_length & 0xFF;
|
||||
|
||||
// SYNC
|
||||
bbframe_raw[6] = 0x47; // TS
|
||||
|
||||
// Now, we put the TS in and set SYNCD
|
||||
uint8_t b;
|
||||
for (int i = 0; i < bb_data_size_bytes; i++)
|
||||
{
|
||||
if (ts_bytes_remaining == 0) // Read a new TS if required
|
||||
{
|
||||
ts_input.read((char *)current_ts, 188);
|
||||
ts_bytes_remaining = 188;
|
||||
}
|
||||
|
||||
if (ts_bytes_remaining == 188)
|
||||
{
|
||||
if (current_ts[0] != 0x47)
|
||||
logger->error("TS Input error, sync not 0x47!");
|
||||
|
||||
current_ts[0] = ts_crc;
|
||||
|
||||
b = ts_crc;
|
||||
ts_crc = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
b = current_ts[188 - ts_bytes_remaining];
|
||||
ts_crc = crc_tab[b ^ ts_crc];
|
||||
}
|
||||
|
||||
bbframe_raw[10 + i] = current_ts[188 - ts_bytes_remaining--];
|
||||
}
|
||||
|
||||
uint16_t syncd = current_ts_offset * 8;
|
||||
bbframe_raw[7] = syncd >> 8;
|
||||
bbframe_raw[8] = syncd & 0xFF;
|
||||
|
||||
if (ts_bytes_remaining == 0)
|
||||
current_ts_offset = 0;
|
||||
else
|
||||
current_ts_offset = ts_bytes_remaining;
|
||||
|
||||
// Compute CRC
|
||||
bbframe_raw[9] = add_crc8_bits(bbframe_raw, 72);
|
||||
}
|
||||
|
||||
// Scrambling
|
||||
bbframe_scra.work(bbframe_raw);
|
||||
|
||||
// BCH Encoder
|
||||
bbframe_bch.encode(bbframe_raw);
|
||||
|
||||
// LDPC Encoder
|
||||
bbframe_ldpc.encode(bbframe_raw);
|
||||
|
||||
// Convert the frame to bits
|
||||
for (int i = 0; i < final_frm_size; i++)
|
||||
frame_bits_buf[i] = (bbframe_raw[i / 8] >> (7 - (i % 8))) & 1;
|
||||
|
||||
// Interleave
|
||||
interleaver.interleave(frame_bits_buf, frame_bits_buf_interleaved);
|
||||
|
||||
// Insert PL Header stuff
|
||||
for (int i = 0; i < 26; i++)
|
||||
input_dsp_stream->writeBuf[i] = sof.symbols[i];
|
||||
|
||||
for (int i = 26; i < 90; i++)
|
||||
input_dsp_stream->writeBuf[i] = pls.symbols[pls_code][i - 26];
|
||||
|
||||
// Now, time to modulate slots
|
||||
int sym_pos = 0;
|
||||
s2_scrambling.reset();
|
||||
for (int slot = 0; slot < plframe_slots; slot++)
|
||||
{
|
||||
complex_t *slotp = &input_dsp_stream->writeBuf[(slot + 1) * 90];
|
||||
|
||||
for (int i = 0; i < 90; i++)
|
||||
{
|
||||
uint8_t const_bits = 0;
|
||||
for (int i = 0; i < constellation_slots.getBitsCnt(); i++)
|
||||
const_bits = const_bits << 1 | !frame_bits_buf_interleaved[sym_pos++];
|
||||
|
||||
complex_t symbol = constellation_slots.mod(const_bits);
|
||||
|
||||
if (cfg.constellation == dvbs2::MOD_QPSK)
|
||||
slotp[i] = s2_scrambling.scramble(symbol) * 1.35;
|
||||
else
|
||||
slotp[i] = s2_scrambling.scramble(symbol);
|
||||
}
|
||||
}
|
||||
|
||||
// Scale samples down, so they fit in "1"
|
||||
for (int i = 0; i < (plframe_slots + 1) * 90; i++)
|
||||
input_dsp_stream->writeBuf[i] *= 0.7;
|
||||
|
||||
// bbframes_test.write((char *)input_dsp_stream->writeBuf, (plframe_slots + 1) * 90 * sizeof(complex_t));
|
||||
input_dsp_stream->swap((plframe_slots + 1) * 90);
|
||||
}
|
||||
|
||||
resampler_blk.stop();
|
||||
file_sink_blk->stop_recording();
|
||||
file_sink_blk->stop();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue