More ADS-B TX experimentation

Lots of junk added in Numbers Station regarding voice files
Removed warnings caused by unfinished ADS-B function
This commit is contained in:
furrtek 2017-05-01 10:42:09 +01:00
parent 790ec34ac0
commit bebec9ccf7
12 changed files with 224 additions and 172 deletions

View File

@ -23,6 +23,7 @@
// Color bitmaps generated with: // Color bitmaps generated with:
// Gimp image > indexed colors (16), then "xxd -i *.bmp" // Gimp image > indexed colors (16), then "xxd -i *.bmp"
//TODO: Waveform widget as FFT view in scanner
//BUG: Replay freezes when SD card not present //BUG: Replay freezes when SD card not present
//BUG: RDS doesn't stop baseband when stopping tx ? //BUG: RDS doesn't stop baseband when stopping tx ?
//BUG: Check AFSK transmit end, skips last bits ? //BUG: Check AFSK transmit end, skips last bits ?

View File

@ -76,6 +76,7 @@ void generate_frame_emergency(uint8_t * const adsb_frame, const uint32_t ICAO_ad
ADSB_generate_CRC(adsb_frame); ADSB_generate_CRC(adsb_frame);
} }
/*
void generate_frame_pos(uint8_t * const adsb_frame, const uint32_t ICAO_address, const uint32_t altitude, void generate_frame_pos(uint8_t * const adsb_frame, const uint32_t ICAO_address, const uint32_t altitude,
const float latitude, const float longitude) { const float latitude, const float longitude) {
uint8_t c, time_parity; uint8_t c, time_parity;
@ -103,9 +104,9 @@ void generate_frame_pos(uint8_t * const adsb_frame, const uint32_t ICAO_address,
//rlat = delta_lat * ((yz / 524288.0) + int(lat / delta_lat)); //rlat = delta_lat * ((yz / 524288.0) + int(lat / delta_lat));
//delta_lon = 360.0 / (NL(rlat) - time_parity); //delta_lon = 360.0 / (NL(rlat) - time_parity);
//xz = 524288.0 * (mod(lon, delta_lon) / delta_lon); // Round to int ! //xz = 524288.0 * (mod(lon, delta_lon) / delta_lon); // Round to int !
/*if (time_parity) { if (time_parity) {
A = sign(rlat0)[NL(rlat0) - NL(rlat1)]; A = sign(rlat0)[NL(rlat0) - NL(rlat1)];
}*/ }
// int xz and yz, then: // int xz and yz, then:
// xz >>= 2; // xz >>= 2;
// yz >>= 2; // yz >>= 2;
@ -115,13 +116,15 @@ void generate_frame_pos(uint8_t * const adsb_frame, const uint32_t ICAO_address,
adsb_frame[5] = ((altitude_coded & 0x7F0) >> 3) | 1; adsb_frame[5] = ((altitude_coded & 0x7F0) >> 3) | 1;
adsb_frame[6] = ((altitude_coded & 0x00F) << 4) | (LAT >> 15); // Then 0, even/odd, and the 2 LAT-CPR MSBs adsb_frame[6] = ((altitude_coded & 0x00F) << 4) | (LAT >> 15); // Then 0, even/odd, and the 2 LAT-CPR MSBs
} }
*/
void ADSB_generate_CRC(uint8_t * const in_frame) { void ADSB_generate_CRC(uint8_t * const in_frame) {
uint8_t adsb_crc[14]; // Temp buffer uint8_t adsb_crc[14]; // Temp buffer
uint8_t b, c, s, bitn; uint8_t b, c, s, bitn;
const uint32_t crc_poly = 0x1205FFF; const uint32_t crc_poly = 0x1205FFF;
in_frame[11] = 0x00; // Clear CRC // Clear CRC
in_frame[11] = 0x00;
in_frame[12] = 0x00; in_frame[12] = 0x00;
in_frame[13] = 0x00; in_frame[13] = 0x00;
@ -140,7 +143,6 @@ void ADSB_generate_CRC(uint8_t * const in_frame) {
// Insert CRC in frame // Insert CRC in frame
memcpy(&in_frame[11], &adsb_crc[11], 3); memcpy(&in_frame[11], &adsb_crc[11], 3);
} }
} /* namespace adsb */ } /* namespace adsb */

View File

@ -33,8 +33,8 @@ namespace adsb {
void make_frame_mode_s(uint8_t * const adsb_frame, const uint32_t ICAO_address); void make_frame_mode_s(uint8_t * const adsb_frame, const uint32_t ICAO_address);
void generate_frame_id(uint8_t * const adsb_frame, const uint32_t ICAO_address, std::string & callsign); void generate_frame_id(uint8_t * const adsb_frame, const uint32_t ICAO_address, std::string & callsign);
void generate_frame_pos(uint8_t * const adsb_frame, const uint32_t ICAO_address, const uint32_t altitude, //void generate_frame_pos(uint8_t * const adsb_frame, const uint32_t ICAO_address, const uint32_t altitude,
const float latitude, const float longitude); // const float latitude, const float longitude);
void generate_frame_emergency(uint8_t * const adsb_frame, const uint32_t ICAO_address, const uint8_t code); void generate_frame_emergency(uint8_t * const adsb_frame, const uint32_t ICAO_address, const uint8_t code);
void ADSB_generate_CRC(uint8_t * const in_message); void ADSB_generate_CRC(uint8_t * const in_message);

View File

@ -127,13 +127,25 @@ static void to_string_hex_internal(char* p, const uint64_t n, const int32_t l) {
} }
} }
std::string to_string_hex(const uint64_t n, const int32_t l) { std::string to_string_hex(const uint64_t n, int32_t l) {
char p[32]; char p[32];
l = std::min(l, 31L);
to_string_hex_internal(p, n, l - 1); to_string_hex_internal(p, n, l - 1);
p[l] = 0; p[l] = 0;
return p; return p;
} }
std::string to_string_hex_array(uint8_t * const array, const int32_t l) {
std::string str_return = "";
uint8_t bytes;
for (bytes = 0; bytes < l; bytes++)
str_return += to_string_hex(array[bytes], 2);
return str_return;
}
std::string to_string_datetime(const rtc::RTC& value) { std::string to_string_datetime(const rtc::RTC& value) {
return to_string_dec_uint(value.year(), 4, '0') + "/" + return to_string_dec_uint(value.year(), 4, '0') + "/" +
to_string_dec_uint(value.month(), 2, '0') + "/" + to_string_dec_uint(value.month(), 2, '0') + "/" +

View File

@ -34,6 +34,7 @@ std::string to_string_bin(const uint32_t n, const uint8_t l = 0);
std::string to_string_dec_uint(const uint32_t n, const int32_t l = 0, const char fill = 0); std::string to_string_dec_uint(const uint32_t n, const int32_t l = 0, const char fill = 0);
std::string to_string_dec_int(const int32_t n, const int32_t l = 0, const char fill = 0); std::string to_string_dec_int(const int32_t n, const int32_t l = 0, const char fill = 0);
std::string to_string_hex(const uint64_t n, const int32_t l = 0); std::string to_string_hex(const uint64_t n, const int32_t l = 0);
std::string to_string_hex_array(uint8_t * const array, const int32_t l = 0);
std::string to_string_short_freq(const uint64_t f, const int32_t l = 4); std::string to_string_short_freq(const uint64_t f, const int32_t l = 4);

View File

@ -38,7 +38,8 @@ using namespace portapack;
namespace ui { namespace ui {
void ADSBTxView::focus() { void ADSBTxView::focus() {
sym_icao.focus(); //sym_icao.focus();
tx_view.focus();
} }
ADSBTxView::~ADSBTxView() { ADSBTxView::~ADSBTxView() {
@ -59,21 +60,15 @@ void ADSBTxView::generate_frame() {
memset(adsb_bin, 0, 112); memset(adsb_bin, 0, 112);
// Convert to binary (1 bit per byte, faster for baseband code) // Convert to binary (1 byte per bit, faster for baseband code)
for (c = 0; c < 112; c++) { for (c = 0; c < 112; c++) {
if ((adsb_frame[c >> 3] << (c & 7)) & 0x80) if ((adsb_frame[c >> 3] << (c & 7)) & 0x80)
adsb_bin[c] = 0xFF; adsb_bin[c] = 1;
} }
// Display for debug // Display in hex for debug
str_debug = ""; text_frame_a.set(to_string_hex_array(&adsb_frame[0], 7));
for (c = 0; c < 7; c++) text_frame_b.set(to_string_hex_array(&adsb_frame[7], 7));
str_debug += to_string_hex(adsb_frame[c], 2);
text_frame_a.set(str_debug);
str_debug = "";
for (c = 0; c < 7; c++)
str_debug += to_string_hex(adsb_frame[c + 7], 2);
text_frame_b.set(str_debug);
button_callsign.set_text(callsign); button_callsign.set_text(callsign);
} }
@ -81,25 +76,25 @@ void ADSBTxView::generate_frame() {
bool ADSBTxView::start_tx() { bool ADSBTxView::start_tx() {
generate_frame(); generate_frame();
transmitter_model.set_tuning_frequency(434000000); // FOR TESTING - DEBUG
transmitter_model.set_sampling_rate(2000000U);
transmitter_model.set_rf_amp(true);
transmitter_model.set_lna(40);
transmitter_model.set_vga(40);
transmitter_model.set_baseband_bandwidth(1750000);
transmitter_model.enable();
memcpy(shared_memory.bb_data.data, adsb_bin, 112); memcpy(shared_memory.bb_data.data, adsb_bin, 112);
baseband::set_adsb(); baseband::set_adsb();
transmitter_model.set_tuning_frequency(434000000); // FOR TESTING - DEBUG
transmitter_model.set_sampling_rate(4000000U);
transmitter_model.set_rf_amp(true);
transmitter_model.set_vga(40);
transmitter_model.set_baseband_bandwidth(2500000);
transmitter_model.enable();
return false; // DEBUG return false; // DEBUG
} }
void ADSBTxView::on_txdone(const int n) { void ADSBTxView::on_txdone(const bool v) {
//size_t sr; //size_t sr;
if (n == 200) { if (v) {
transmitter_model.disable(); transmitter_model.disable();
tx_view.set_transmitting(false);
//progress.set_value(0); //progress.set_value(0);
} else { } else {
//progress.set_value(n); //progress.set_value(n);

View File

@ -61,7 +61,7 @@ private:
bool start_tx(); bool start_tx();
void generate_frame(); void generate_frame();
void generate_frame_pos(); void generate_frame_pos();
void on_txdone(const int n); void on_txdone(const bool v);
const Style style_val { const Style style_val {
.font = font::fixed_8x16, .font = font::fixed_8x16,
@ -166,7 +166,7 @@ private:
Message::ID::TXDone, Message::ID::TXDone,
[this](const Message* const p) { [this](const Message* const p) {
const auto message = *reinterpret_cast<const TXDoneMessage*>(p); const auto message = *reinterpret_cast<const TXDoneMessage*>(p);
this->on_txdone(message.progress); this->on_txdone(message.done);
} }
}; };
}; };

View File

@ -34,6 +34,8 @@ using namespace portapack;
namespace ui { namespace ui {
// TODO: This app takes way too much space, find a way to shrink/simplify or make it an SD card module (loadable)
void NumbersStationView::focus() { void NumbersStationView::focus() {
if (file_error) if (file_error)
nav_.display_modal("No voices", "No valid voices found in\nthe /numbers directory.", ABORT, nullptr); nav_.display_modal("No voices", "No valid voices found in\nthe /numbers directory.", ABORT, nullptr);
@ -46,29 +48,34 @@ NumbersStationView::~NumbersStationView() {
baseband::shutdown(); baseband::shutdown();
} }
void NumbersStationView::on_tuning_frequency_changed(rf::Frequency f) { NumbersStationView::wav_file_t * NumbersStationView::get_wav(uint32_t index) {
transmitter_model.set_tuning_frequency(f); return &current_voice->available_wavs[index];
} }
void NumbersStationView::prepare_audio() { void NumbersStationView::prepare_audio() {
uint8_t code; uint8_t code;
wav_file_t * wav_file;
/*if (sample_counter >= sample_duration) { if (sample_counter >= sample_length) {
if (segment == ANNOUNCE) { if (segment == ANNOUNCE) {
if (!announce_loop) { if (!announce_loop) {
code_index = 0;
segment = MESSAGE; segment = MESSAGE;
} else { } else {
reader->open("/numbers/announce.wav"); wav_file = get_wav(11);
sample_duration = sound_sizes[10]; reader->open(current_voice->dir + file_names[wav_file->index].name + ".wav");
sample_length = wav_file->length;
announce_loop--; announce_loop--;
} }
} }
if (segment == MESSAGE) { if (segment == MESSAGE) {
code = symfield_code.get_sym(code_index); if (code_index == 25) {
if (code_index == 25)
transmitter_model.disable(); transmitter_model.disable();
return;
}
code = symfield_code.get_sym(code_index);
if (code >= 10) { if (code >= 10) {
memset(audio_buffer, 0, 1024); memset(audio_buffer, 0, 1024);
@ -78,10 +85,12 @@ void NumbersStationView::prepare_audio() {
pause = 33075; // P: 0.75s @ 44100Hz pause = 33075; // P: 0.75s @ 44100Hz
} else if (code == 12) { } else if (code == 12) {
transmitter_model.disable(); transmitter_model.disable();
return;
} }
} else { } else {
reader->open("/numbers/" + file_names[code] + ".wav"); wav_file = get_wav(code);
sample_duration = sound_sizes[code]; reader->open(current_voice->dir + file_names[code].name + ".wav");
sample_length = wav_file->length;
} }
code_index++; code_index++;
} }
@ -102,17 +111,17 @@ void NumbersStationView::prepare_audio() {
if (pause >= 1024) { if (pause >= 1024) {
pause -= 1024; pause -= 1024;
} else { } else {
sample_counter = sample_duration; sample_counter = sample_length;
pause = 0; pause = 0;
} }
} }
baseband::set_fifo_data(audio_buffer);*/ baseband::set_fifo_data(audio_buffer);
} }
void NumbersStationView::start_tx() { void NumbersStationView::start_tx() {
//sample_duration = sound_sizes[10]; // Announce //sample_length = sound_sizes[10]; // Announce
sample_counter = sample_duration; sample_counter = sample_length;
code_index = 0; code_index = 0;
announce_loop = 2; announce_loop = 2;
@ -126,7 +135,7 @@ void NumbersStationView::start_tx() {
transmitter_model.enable(); transmitter_model.enable();
baseband::set_audiotx_data( baseband::set_audiotx_data(
(1536000 / 44100) - 1, (1536000 / 44100) - 1, // TODO: Read wav file's samplerate
12000, 12000,
1, 1,
false, false,
@ -135,7 +144,6 @@ void NumbersStationView::start_tx() {
} }
void NumbersStationView::on_tick_second() { void NumbersStationView::on_tick_second() {
if (check_armed.value()) {
armed_blink = not armed_blink; armed_blink = not armed_blink;
if (armed_blink) if (armed_blink)
@ -145,18 +153,28 @@ void NumbersStationView::on_tick_second() {
check_armed.set_dirty(); check_armed.set_dirty();
} }
}
void NumbersStationView::on_voice_changed(size_t index) { void NumbersStationView::on_voice_changed(size_t index) {
std::string flags_string = ""; std::string code_list = "";
if (voices[index].accent) { for (const auto& wavs : voices[index].available_wavs)
flags_string = "^"; code_list += wavs.code;
for (uint32_t c = 0; c < 25; c++)
symfield_code.set_symbol_list(c, code_list);
current_voice = &voices[index];
} }
if (voices[index].announce) {
flags_string += "A"; bool NumbersStationView::check_wav_validity(const std::string dir, const std::string file) {
} if (reader->open("/numbers/" + dir + "/" + file)) {
text_voice_flags.set(flags_string); // Check format (mono, 8 bits)
if ((reader->channels() == 1) && (reader->bits_per_sample() == 8))
return true;
else
return false;
} else
return false;
} }
NumbersStationView::NumbersStationView( NumbersStationView::NumbersStationView(
@ -167,8 +185,9 @@ NumbersStationView::NumbersStationView(
using option_t = std::pair<std::string, int32_t>; using option_t = std::pair<std::string, int32_t>;
using options_t = std::vector<option_t>; using options_t = std::vector<option_t>;
options_t voice_options; options_t voice_options;
uint32_t c, i, ia; voice_t temp_voice { };
bool valid; bool valid;
uint32_t c;
//uint8_t y, m, d, dayofweek; //uint8_t y, m, d, dayofweek;
reader = std::make_unique<WAVFileReader>(); reader = std::make_unique<WAVFileReader>();
@ -179,42 +198,39 @@ NumbersStationView::NumbersStationView(
file_error = true; file_error = true;
return; return;
} }
// This is awfully repetitive
for (const auto& dir : directory_list) { for (const auto& dir : directory_list) {
i = 0; c = 0;
for (const auto& file_name : file_names) { for (const auto& file_name : file_names) {
valid = false; valid = check_wav_validity(dir.string(), file_name.name + ".wav");
if (reader->open("/numbers/" + dir.string() + "/" + file_name + ".wav")) { if ((!valid) && (file_name.required)) {
// Check format (mono, 8 bits) temp_voice.available_wavs.clear();
if ((reader->channels() == 1) && (reader->bits_per_sample() == 8)) break; // Invalid required file means invalid voice
valid = true; } else if (valid) {
temp_voice.available_wavs.push_back({ file_name.code, c++, 0, 0 }); // TODO: Needs length and samplerate
} }
if (!valid) {
if (i < 10)
i = 0; // Missingno, invalid voice
break;
} }
i++; if (!temp_voice.available_wavs.empty()) {
} // Voice can be used, are there accent files ?
if (i) { c = 0;
// Voice ok, are there accent files ?
ia = 0;
for (const auto& file_name : file_names) { for (const auto& file_name : file_names) {
valid = false; valid = check_wav_validity(dir.string(), file_name.name + "a.wav");
if (reader->open("/numbers/" + dir.string() + "/" + file_name + "a.wav")) { if ((!valid) && (file_name.required)) {
// Check format (mono, 8 bits) c = 0;
if ((reader->channels() == 1) && (reader->bits_per_sample() == 8)) break; // Invalid required file means accents can't be used
valid = true; } else if (valid) {
c++;
} }
if (!valid)
break;
ia++;
} }
voices.push_back({ dir.string(), (ia >= 10), (i == 11) }); temp_voice.accent = c ? true : false;
temp_voice.dir = dir.string();
voices.push_back(temp_voice);
} }
} }
if (!voices.size()) {
if (voices.empty()) {
file_error = true; file_error = true;
return; return;
} }
@ -254,9 +270,6 @@ NumbersStationView::NumbersStationView(
} }
}; };
for (c = 0; c < 25; c++)
symfield_code.set_symbol_list(c, "0123456789pPE");
// DEBUG // DEBUG
symfield_code.set_sym(0, 10); symfield_code.set_sym(0, 10);
symfield_code.set_sym(1, 3); symfield_code.set_sym(1, 3);

View File

@ -43,6 +43,11 @@ public:
NumbersStationView(NavigationView& nav); NumbersStationView(NavigationView& nav);
~NumbersStationView(); ~NumbersStationView();
NumbersStationView(const NumbersStationView&) = delete;
NumbersStationView(NumbersStationView&&) = delete;
NumbersStationView& operator=(const NumbersStationView&) = delete;
NumbersStationView& operator=(NumbersStationView&&) = delete;
void focus() override; void focus() override;
std::string title() const override { return "Numbers station"; }; std::string title() const override { return "Numbers station"; };
@ -64,60 +69,66 @@ private:
.foreground = Color::red() .foreground = Color::red()
}; };
typedef struct {
char code;
uint32_t index;
uint32_t length;
uint32_t samplerate;
} wav_file_t;
struct voice_t { struct voice_t {
std::string dir; std::string dir;
std::vector<wav_file_t> available_wavs;
bool accent; bool accent;
bool announce; };
std::vector<voice_t> voices { };
voice_t * current_voice { };
struct wav_file_list_t {
std::string name;
bool required;
char code;
};
const std::vector<wav_file_list_t> file_names = {
{ "0", true, '0' },
{ "1", true, '1' },
{ "2", true, '2' },
{ "3", true, '3' },
{ "4", true, '4' },
{ "5", true, '5' },
{ "6", true, '6' },
{ "7", true, '7' },
{ "8", true, '8' },
{ "9", true, '9' },
{ "announce", false, 'A' }
}; };
segments segment { IDLE }; segments segment { IDLE };
bool armed { false }; bool armed { false };
bool file_error { false }; bool file_error { false };
std::vector<voice_t> voices;
const std::vector<std::string> file_names = {
{ "0" },
{ "1" },
{ "2" },
{ "3" },
{ "4" },
{ "5" },
{ "6" },
{ "7" },
{ "8" },
{ "9" },
{ "announce" }
};
// const uint8_t month_table[12] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 }; // const uint8_t month_table[12] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
// const char * day_of_week[7] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" }; // const char * day_of_week[7] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
std::unique_ptr<WAVFileReader> reader { }; std::unique_ptr<WAVFileReader> reader { };
uint8_t code_index, announce_loop; uint8_t code_index { 0 }, announce_loop { 0 };
uint32_t sample_counter; uint32_t sample_counter { 0 };
uint32_t sample_duration; uint32_t sample_length { 0 };
int8_t audio_buffer[1024]; int8_t audio_buffer[1024] { };
uint32_t pause = 0; uint32_t pause { 0 };
bool armed_blink { false }; bool armed_blink { false };
SignalToken signal_token_tick_second { }; SignalToken signal_token_tick_second { };
wav_file_t * get_wav(uint32_t index);
bool check_wav_validity(const std::string dir, const std::string file);
void on_voice_changed(size_t index); void on_voice_changed(size_t index);
void on_tick_second(); void on_tick_second();
void on_tuning_frequency_changed(rf::Frequency f);
void prepare_audio(); void prepare_audio();
void start_tx(); void start_tx();
// Schedule: save on sd card
// For each day of the week, max 8 messages ?
// For each message: Normal, accent. Can chose accent on first or last digit
// Prelude with number of repeats
// Message 1 with number of repeats
// Interlude ?
// Message 2 with number of repeats
// End
// Frequency list and sequence
Labels labels { Labels labels {
{ { 2 * 8, 5 * 8 }, "Voice: Flags:", Color::light_grey() }, { { 2 * 8, 5 * 8 }, "Voice: Flags:", Color::light_grey() },
{ { 1 * 8, 8 * 8 }, "Code:", Color::light_grey() } { { 1 * 8, 8 * 8 }, "Code:", Color::light_grey() }

View File

@ -29,57 +29,67 @@
void ADSBTXProcessor::execute(const buffer_c8_t& buffer) { void ADSBTXProcessor::execute(const buffer_c8_t& buffer) {
// This is called at 2M/2048 = 977Hz // This is called at 4M/2048 = 1953Hz
// One pulse = 500ns = 2 samples
// One bit = 2 pulses = 1us = 4 samples
if (!configured) return; if (!configured) return;
for (size_t i = 0; i < buffer.count; i++) { for (size_t i = 0; i < buffer.count; i++) {
// Synthesis at 2M if (!sample) {
/*if (preamble == true) { sample = 3;
if (active) {
if (preamble) {
if (bit_pos >= 16) { if (bit_pos >= 16) {
bit_pos = 0;
preamble = false; preamble = false;
bit_part = 0; bit_pos = 0;
} else { } else {
cur_bit = (preamble_parts << bit_pos) >> 15; cur_bit = (preamble_parts << bit_pos) >> 15;
bit_pos++; bit_pos++;
} }
}*/ }
//if (preamble == false) {
if (!bit_part) { if (!preamble) {
if (bit_pos >= 112) { if (bit_pos >= 112) {
// Stop active = false; // Stop
message.progress = 200;
shared_memory.application_queue.push(message);
configured = false;
cur_bit = 0; cur_bit = 0;
} else { } else {
cur_bit = 0; //shared_memory.tx_data[bit_pos]; cur_bit = shared_memory.bb_data.data[bit_pos];
bit_pos++; bit_pos++;
bit_part = 1; }
} }
} else { } else {
bit_part = 0; //cur_bit = 0;
cur_bit ^= 1; if (bit_pos == 8192) { // ?
configured = false;
message.done = true;
shared_memory.application_queue.push(message);
} }
//} bit_pos++;
}
} else
sample--;
// 8D48: 10001101 01001000 if (sample == 1)
// 1001010110100110 0110010110010101 cur_bit ^= 1; // Invert
delta = tone_sample * fm_delta;
tone_sample += 128;
if (cur_bit) { if (cur_bit) {
phase = (phase + 0x1FE00); // What ? phase += delta;
sphase = phase + (64 << 18); sphase = phase + (64 << 24);
re = (sine_table_i8[(sphase & 0x03FC0000) >> 18]); re = (sine_table_i8[(sphase & 0xFF000000U) >> 24]);
im = (sine_table_i8[(phase & 0x03FC0000) >> 18]); im = (sine_table_i8[(phase & 0xFF000000U) >> 24]);
} else { } else {
re = 0; re = 0;
im = 0; im = 0;
} }
buffer.p[i] = {(int8_t)re, (int8_t)im}; buffer.p[i] = {re, im};
} }
} }
@ -87,11 +97,14 @@ void ADSBTXProcessor::on_message(const Message* const p) {
const auto message = *reinterpret_cast<const ADSBConfigureMessage*>(p); const auto message = *reinterpret_cast<const ADSBConfigureMessage*>(p);
if (message.id == Message::ID::ADSBConfigure) { if (message.id == Message::ID::ADSBConfigure) {
bit_part = 0;
bit_pos = 0; bit_pos = 0;
sample = 0;
cur_bit = 0; cur_bit = 0;
preamble = true; preamble = true;
active = true;
configured = true; configured = true;
fm_delta = 50000 * (0xFFFFFFULL / 4000000); // Fixed bw for now
} }
} }

View File

@ -26,6 +26,8 @@
#include "baseband_processor.hpp" #include "baseband_processor.hpp"
#include "baseband_thread.hpp" #include "baseband_thread.hpp"
#define TEST_F2D(f) (uint32_t)((f) * ((1ULL << 32) / 4000000))
class ADSBTXProcessor : public BasebandProcessor { class ADSBTXProcessor : public BasebandProcessor {
public: public:
void execute(const buffer_c8_t& buffer) override; void execute(const buffer_c8_t& buffer) override;
@ -35,18 +37,20 @@ public:
private: private:
bool configured = false; bool configured = false;
BasebandThread baseband_thread { 2000000, this, NORMALPRIO + 20, baseband::Direction::Transmit }; // 2280000 BasebandThread baseband_thread { 4000000, this, NORMALPRIO + 20, baseband::Direction::Transmit };
const uint16_t preamble_parts = 0b1010000101000000; const uint16_t preamble_parts = 0b1010000101000000;
uint8_t bit_part; bool preamble { }, active { };
bool preamble; uint16_t bit_pos { 0 };
int8_t re, im; uint8_t cur_bit { 0 };
uint16_t bit_pos = 0; uint32_t sample { 0 };
uint8_t cur_bit = 0; uint32_t tone_phase { 0 };
uint32_t phase, sphase; uint32_t fm_delta { 0 };
int32_t sig, frq; uint32_t phase { 0 }, sphase { 0 };
int32_t tone_sample { 0 }, delta { 0 };
int8_t re { }, im { };
TXDoneMessage message; TXDoneMessage message { };
}; };
#endif #endif

Binary file not shown.