mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-12-28 16:59:47 -05:00
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:
parent
790ec34ac0
commit
bebec9ccf7
@ -23,6 +23,7 @@
|
||||
// Color bitmaps generated with:
|
||||
// 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: RDS doesn't stop baseband when stopping tx ?
|
||||
//BUG: Check AFSK transmit end, skips last bits ?
|
||||
|
@ -76,6 +76,7 @@ void generate_frame_emergency(uint8_t * const adsb_frame, const uint32_t ICAO_ad
|
||||
ADSB_generate_CRC(adsb_frame);
|
||||
}
|
||||
|
||||
/*
|
||||
void generate_frame_pos(uint8_t * const adsb_frame, const uint32_t ICAO_address, const uint32_t altitude,
|
||||
const float latitude, const float longitude) {
|
||||
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));
|
||||
//delta_lon = 360.0 / (NL(rlat) - time_parity);
|
||||
//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)];
|
||||
}*/
|
||||
}
|
||||
// int xz and yz, then:
|
||||
// xz >>= 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[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) {
|
||||
uint8_t adsb_crc[14]; // Temp buffer
|
||||
uint8_t b, c, s, bitn;
|
||||
const uint32_t crc_poly = 0x1205FFF;
|
||||
|
||||
in_frame[11] = 0x00; // Clear CRC
|
||||
// Clear CRC
|
||||
in_frame[11] = 0x00;
|
||||
in_frame[12] = 0x00;
|
||||
in_frame[13] = 0x00;
|
||||
|
||||
@ -140,7 +143,6 @@ void ADSB_generate_CRC(uint8_t * const in_frame) {
|
||||
|
||||
// Insert CRC in frame
|
||||
memcpy(&in_frame[11], &adsb_crc[11], 3);
|
||||
|
||||
}
|
||||
|
||||
} /* namespace adsb */
|
||||
|
@ -33,8 +33,8 @@ namespace adsb {
|
||||
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_pos(uint8_t * const adsb_frame, const uint32_t ICAO_address, const uint32_t altitude,
|
||||
const float latitude, const float longitude);
|
||||
//void generate_frame_pos(uint8_t * const adsb_frame, const uint32_t ICAO_address, const uint32_t altitude,
|
||||
// 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 ADSB_generate_CRC(uint8_t * const in_message);
|
||||
|
@ -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];
|
||||
|
||||
l = std::min(l, 31L);
|
||||
to_string_hex_internal(p, n, l - 1);
|
||||
p[l] = 0;
|
||||
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) {
|
||||
return to_string_dec_uint(value.year(), 4, '0') + "/" +
|
||||
to_string_dec_uint(value.month(), 2, '0') + "/" +
|
||||
|
@ -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_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_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);
|
||||
|
||||
|
@ -38,7 +38,8 @@ using namespace portapack;
|
||||
namespace ui {
|
||||
|
||||
void ADSBTxView::focus() {
|
||||
sym_icao.focus();
|
||||
//sym_icao.focus();
|
||||
tx_view.focus();
|
||||
}
|
||||
|
||||
ADSBTxView::~ADSBTxView() {
|
||||
@ -59,21 +60,15 @@ void ADSBTxView::generate_frame() {
|
||||
|
||||
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++) {
|
||||
if ((adsb_frame[c >> 3] << (c & 7)) & 0x80)
|
||||
adsb_bin[c] = 0xFF;
|
||||
adsb_bin[c] = 1;
|
||||
}
|
||||
|
||||
// Display for debug
|
||||
str_debug = "";
|
||||
for (c = 0; c < 7; c++)
|
||||
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);
|
||||
// Display in hex for debug
|
||||
text_frame_a.set(to_string_hex_array(&adsb_frame[0], 7));
|
||||
text_frame_b.set(to_string_hex_array(&adsb_frame[7], 7));
|
||||
|
||||
button_callsign.set_text(callsign);
|
||||
}
|
||||
@ -81,25 +76,25 @@ void ADSBTxView::generate_frame() {
|
||||
bool ADSBTxView::start_tx() {
|
||||
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);
|
||||
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
|
||||
}
|
||||
|
||||
void ADSBTxView::on_txdone(const int n) {
|
||||
void ADSBTxView::on_txdone(const bool v) {
|
||||
//size_t sr;
|
||||
|
||||
if (n == 200) {
|
||||
if (v) {
|
||||
transmitter_model.disable();
|
||||
tx_view.set_transmitting(false);
|
||||
//progress.set_value(0);
|
||||
} else {
|
||||
//progress.set_value(n);
|
||||
|
@ -61,7 +61,7 @@ private:
|
||||
bool start_tx();
|
||||
void generate_frame();
|
||||
void generate_frame_pos();
|
||||
void on_txdone(const int n);
|
||||
void on_txdone(const bool v);
|
||||
|
||||
const Style style_val {
|
||||
.font = font::fixed_8x16,
|
||||
@ -166,7 +166,7 @@ private:
|
||||
Message::ID::TXDone,
|
||||
[this](const Message* const p) {
|
||||
const auto message = *reinterpret_cast<const TXDoneMessage*>(p);
|
||||
this->on_txdone(message.progress);
|
||||
this->on_txdone(message.done);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -34,6 +34,8 @@ using namespace portapack;
|
||||
|
||||
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() {
|
||||
if (file_error)
|
||||
nav_.display_modal("No voices", "No valid voices found in\nthe /numbers directory.", ABORT, nullptr);
|
||||
@ -46,29 +48,34 @@ NumbersStationView::~NumbersStationView() {
|
||||
baseband::shutdown();
|
||||
}
|
||||
|
||||
void NumbersStationView::on_tuning_frequency_changed(rf::Frequency f) {
|
||||
transmitter_model.set_tuning_frequency(f);
|
||||
NumbersStationView::wav_file_t * NumbersStationView::get_wav(uint32_t index) {
|
||||
return ¤t_voice->available_wavs[index];
|
||||
}
|
||||
|
||||
void NumbersStationView::prepare_audio() {
|
||||
uint8_t code;
|
||||
wav_file_t * wav_file;
|
||||
|
||||
/*if (sample_counter >= sample_duration) {
|
||||
if (sample_counter >= sample_length) {
|
||||
if (segment == ANNOUNCE) {
|
||||
if (!announce_loop) {
|
||||
code_index = 0;
|
||||
segment = MESSAGE;
|
||||
} else {
|
||||
reader->open("/numbers/announce.wav");
|
||||
sample_duration = sound_sizes[10];
|
||||
wav_file = get_wav(11);
|
||||
reader->open(current_voice->dir + file_names[wav_file->index].name + ".wav");
|
||||
sample_length = wav_file->length;
|
||||
announce_loop--;
|
||||
}
|
||||
}
|
||||
|
||||
if (segment == MESSAGE) {
|
||||
code = symfield_code.get_sym(code_index);
|
||||
|
||||
if (code_index == 25)
|
||||
if (code_index == 25) {
|
||||
transmitter_model.disable();
|
||||
return;
|
||||
}
|
||||
|
||||
code = symfield_code.get_sym(code_index);
|
||||
|
||||
if (code >= 10) {
|
||||
memset(audio_buffer, 0, 1024);
|
||||
@ -78,10 +85,12 @@ void NumbersStationView::prepare_audio() {
|
||||
pause = 33075; // P: 0.75s @ 44100Hz
|
||||
} else if (code == 12) {
|
||||
transmitter_model.disable();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
reader->open("/numbers/" + file_names[code] + ".wav");
|
||||
sample_duration = sound_sizes[code];
|
||||
wav_file = get_wav(code);
|
||||
reader->open(current_voice->dir + file_names[code].name + ".wav");
|
||||
sample_length = wav_file->length;
|
||||
}
|
||||
code_index++;
|
||||
}
|
||||
@ -102,17 +111,17 @@ void NumbersStationView::prepare_audio() {
|
||||
if (pause >= 1024) {
|
||||
pause -= 1024;
|
||||
} else {
|
||||
sample_counter = sample_duration;
|
||||
sample_counter = sample_length;
|
||||
pause = 0;
|
||||
}
|
||||
}
|
||||
|
||||
baseband::set_fifo_data(audio_buffer);*/
|
||||
baseband::set_fifo_data(audio_buffer);
|
||||
}
|
||||
|
||||
void NumbersStationView::start_tx() {
|
||||
//sample_duration = sound_sizes[10]; // Announce
|
||||
sample_counter = sample_duration;
|
||||
//sample_length = sound_sizes[10]; // Announce
|
||||
sample_counter = sample_length;
|
||||
|
||||
code_index = 0;
|
||||
announce_loop = 2;
|
||||
@ -126,7 +135,7 @@ void NumbersStationView::start_tx() {
|
||||
transmitter_model.enable();
|
||||
|
||||
baseband::set_audiotx_data(
|
||||
(1536000 / 44100) - 1,
|
||||
(1536000 / 44100) - 1, // TODO: Read wav file's samplerate
|
||||
12000,
|
||||
1,
|
||||
false,
|
||||
@ -135,28 +144,37 @@ void NumbersStationView::start_tx() {
|
||||
}
|
||||
|
||||
void NumbersStationView::on_tick_second() {
|
||||
if (check_armed.value()) {
|
||||
armed_blink = not armed_blink;
|
||||
|
||||
if (armed_blink)
|
||||
check_armed.set_style(&style_red);
|
||||
else
|
||||
check_armed.set_style(&style());
|
||||
|
||||
check_armed.set_dirty();
|
||||
}
|
||||
armed_blink = not armed_blink;
|
||||
|
||||
if (armed_blink)
|
||||
check_armed.set_style(&style_red);
|
||||
else
|
||||
check_armed.set_style(&style());
|
||||
|
||||
check_armed.set_dirty();
|
||||
}
|
||||
|
||||
void NumbersStationView::on_voice_changed(size_t index) {
|
||||
std::string flags_string = "";
|
||||
std::string code_list = "";
|
||||
|
||||
if (voices[index].accent) {
|
||||
flags_string = "^";
|
||||
}
|
||||
if (voices[index].announce) {
|
||||
flags_string += "A";
|
||||
}
|
||||
text_voice_flags.set(flags_string);
|
||||
for (const auto& wavs : voices[index].available_wavs)
|
||||
code_list += wavs.code;
|
||||
|
||||
for (uint32_t c = 0; c < 25; c++)
|
||||
symfield_code.set_symbol_list(c, code_list);
|
||||
|
||||
current_voice = &voices[index];
|
||||
}
|
||||
|
||||
bool NumbersStationView::check_wav_validity(const std::string dir, const std::string file) {
|
||||
if (reader->open("/numbers/" + dir + "/" + file)) {
|
||||
// Check format (mono, 8 bits)
|
||||
if ((reader->channels() == 1) && (reader->bits_per_sample() == 8))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
NumbersStationView::NumbersStationView(
|
||||
@ -167,8 +185,9 @@ NumbersStationView::NumbersStationView(
|
||||
using option_t = std::pair<std::string, int32_t>;
|
||||
using options_t = std::vector<option_t>;
|
||||
options_t voice_options;
|
||||
uint32_t c, i, ia;
|
||||
voice_t temp_voice { };
|
||||
bool valid;
|
||||
uint32_t c;
|
||||
//uint8_t y, m, d, dayofweek;
|
||||
|
||||
reader = std::make_unique<WAVFileReader>();
|
||||
@ -179,42 +198,39 @@ NumbersStationView::NumbersStationView(
|
||||
file_error = true;
|
||||
return;
|
||||
}
|
||||
// This is awfully repetitive
|
||||
|
||||
for (const auto& dir : directory_list) {
|
||||
i = 0;
|
||||
c = 0;
|
||||
for (const auto& file_name : file_names) {
|
||||
valid = false;
|
||||
if (reader->open("/numbers/" + dir.string() + "/" + file_name + ".wav")) {
|
||||
// Check format (mono, 8 bits)
|
||||
if ((reader->channels() == 1) && (reader->bits_per_sample() == 8))
|
||||
valid = true;
|
||||
valid = check_wav_validity(dir.string(), file_name.name + ".wav");
|
||||
if ((!valid) && (file_name.required)) {
|
||||
temp_voice.available_wavs.clear();
|
||||
break; // Invalid required file means invalid voice
|
||||
} 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 (i) {
|
||||
// Voice ok, are there accent files ?
|
||||
ia = 0;
|
||||
if (!temp_voice.available_wavs.empty()) {
|
||||
// Voice can be used, are there accent files ?
|
||||
c = 0;
|
||||
for (const auto& file_name : file_names) {
|
||||
valid = false;
|
||||
if (reader->open("/numbers/" + dir.string() + "/" + file_name + "a.wav")) {
|
||||
// Check format (mono, 8 bits)
|
||||
if ((reader->channels() == 1) && (reader->bits_per_sample() == 8))
|
||||
valid = true;
|
||||
valid = check_wav_validity(dir.string(), file_name.name + "a.wav");
|
||||
if ((!valid) && (file_name.required)) {
|
||||
c = 0;
|
||||
break; // Invalid required file means accents can't be used
|
||||
} 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;
|
||||
return;
|
||||
}
|
||||
@ -254,9 +270,6 @@ NumbersStationView::NumbersStationView(
|
||||
}
|
||||
};
|
||||
|
||||
for (c = 0; c < 25; c++)
|
||||
symfield_code.set_symbol_list(c, "0123456789pPE");
|
||||
|
||||
// DEBUG
|
||||
symfield_code.set_sym(0, 10);
|
||||
symfield_code.set_sym(1, 3);
|
||||
|
@ -42,6 +42,11 @@ class NumbersStationView : public View {
|
||||
public:
|
||||
NumbersStationView(NavigationView& nav);
|
||||
~NumbersStationView();
|
||||
|
||||
NumbersStationView(const NumbersStationView&) = delete;
|
||||
NumbersStationView(NumbersStationView&&) = delete;
|
||||
NumbersStationView& operator=(const NumbersStationView&) = delete;
|
||||
NumbersStationView& operator=(NumbersStationView&&) = delete;
|
||||
|
||||
void focus() override;
|
||||
|
||||
@ -64,60 +69,66 @@ private:
|
||||
.foreground = Color::red()
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
char code;
|
||||
uint32_t index;
|
||||
uint32_t length;
|
||||
uint32_t samplerate;
|
||||
} wav_file_t;
|
||||
|
||||
struct voice_t {
|
||||
std::string dir;
|
||||
std::vector<wav_file_t> available_wavs;
|
||||
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 };
|
||||
bool armed { 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 char * day_of_week[7] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
|
||||
|
||||
std::unique_ptr<WAVFileReader> reader { };
|
||||
|
||||
uint8_t code_index, announce_loop;
|
||||
uint32_t sample_counter;
|
||||
uint32_t sample_duration;
|
||||
int8_t audio_buffer[1024];
|
||||
uint32_t pause = 0;
|
||||
uint8_t code_index { 0 }, announce_loop { 0 };
|
||||
uint32_t sample_counter { 0 };
|
||||
uint32_t sample_length { 0 };
|
||||
int8_t audio_buffer[1024] { };
|
||||
uint32_t pause { 0 };
|
||||
bool armed_blink { false };
|
||||
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_tick_second();
|
||||
void on_tuning_frequency_changed(rf::Frequency f);
|
||||
void on_tick_second();
|
||||
void prepare_audio();
|
||||
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 {
|
||||
{ { 2 * 8, 5 * 8 }, "Voice: Flags:", Color::light_grey() },
|
||||
{ { 1 * 8, 8 * 8 }, "Code:", Color::light_grey() }
|
||||
|
@ -29,57 +29,67 @@
|
||||
|
||||
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;
|
||||
|
||||
for (size_t i = 0; i < buffer.count; i++) {
|
||||
|
||||
// Synthesis at 2M
|
||||
/*if (preamble == true) {
|
||||
if (bit_pos >= 16) {
|
||||
bit_pos = 0;
|
||||
preamble = false;
|
||||
bit_part = 0;
|
||||
} else {
|
||||
cur_bit = (preamble_parts << bit_pos) >> 15;
|
||||
bit_pos++;
|
||||
}
|
||||
}*/
|
||||
//if (preamble == false) {
|
||||
if (!bit_part) {
|
||||
if (bit_pos >= 112) {
|
||||
// Stop
|
||||
message.progress = 200;
|
||||
shared_memory.application_queue.push(message);
|
||||
configured = false;
|
||||
cur_bit = 0;
|
||||
} else {
|
||||
cur_bit = 0; //shared_memory.tx_data[bit_pos];
|
||||
bit_pos++;
|
||||
bit_part = 1;
|
||||
if (!sample) {
|
||||
sample = 3;
|
||||
|
||||
if (active) {
|
||||
if (preamble) {
|
||||
if (bit_pos >= 16) {
|
||||
preamble = false;
|
||||
bit_pos = 0;
|
||||
} else {
|
||||
cur_bit = (preamble_parts << bit_pos) >> 15;
|
||||
bit_pos++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!preamble) {
|
||||
if (bit_pos >= 112) {
|
||||
active = false; // Stop
|
||||
cur_bit = 0;
|
||||
} else {
|
||||
cur_bit = shared_memory.bb_data.data[bit_pos];
|
||||
bit_pos++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bit_part = 0;
|
||||
cur_bit ^= 1;
|
||||
//cur_bit = 0;
|
||||
if (bit_pos == 8192) { // ?
|
||||
configured = false;
|
||||
message.done = true;
|
||||
shared_memory.application_queue.push(message);
|
||||
}
|
||||
bit_pos++;
|
||||
}
|
||||
//}
|
||||
} else
|
||||
sample--;
|
||||
|
||||
// 8D48: 10001101 01001000
|
||||
// 1001010110100110 0110010110010101
|
||||
if (sample == 1)
|
||||
cur_bit ^= 1; // Invert
|
||||
|
||||
delta = tone_sample * fm_delta;
|
||||
tone_sample += 128;
|
||||
|
||||
if (cur_bit) {
|
||||
phase = (phase + 0x1FE00); // What ?
|
||||
sphase = phase + (64 << 18);
|
||||
phase += delta;
|
||||
sphase = phase + (64 << 24);
|
||||
|
||||
re = (sine_table_i8[(sphase & 0x03FC0000) >> 18]);
|
||||
im = (sine_table_i8[(phase & 0x03FC0000) >> 18]);
|
||||
re = (sine_table_i8[(sphase & 0xFF000000U) >> 24]);
|
||||
im = (sine_table_i8[(phase & 0xFF000000U) >> 24]);
|
||||
} else {
|
||||
re = 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);
|
||||
|
||||
if (message.id == Message::ID::ADSBConfigure) {
|
||||
bit_part = 0;
|
||||
bit_pos = 0;
|
||||
sample = 0;
|
||||
cur_bit = 0;
|
||||
preamble = true;
|
||||
active = true;
|
||||
configured = true;
|
||||
|
||||
fm_delta = 50000 * (0xFFFFFFULL / 4000000); // Fixed bw for now
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include "baseband_processor.hpp"
|
||||
#include "baseband_thread.hpp"
|
||||
|
||||
#define TEST_F2D(f) (uint32_t)((f) * ((1ULL << 32) / 4000000))
|
||||
|
||||
class ADSBTXProcessor : public BasebandProcessor {
|
||||
public:
|
||||
void execute(const buffer_c8_t& buffer) override;
|
||||
@ -35,18 +37,20 @@ public:
|
||||
private:
|
||||
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;
|
||||
uint8_t bit_part;
|
||||
bool preamble;
|
||||
int8_t re, im;
|
||||
uint16_t bit_pos = 0;
|
||||
uint8_t cur_bit = 0;
|
||||
uint32_t phase, sphase;
|
||||
int32_t sig, frq;
|
||||
bool preamble { }, active { };
|
||||
uint16_t bit_pos { 0 };
|
||||
uint8_t cur_bit { 0 };
|
||||
uint32_t sample { 0 };
|
||||
uint32_t tone_phase { 0 };
|
||||
uint32_t fm_delta { 0 };
|
||||
uint32_t phase { 0 }, sphase { 0 };
|
||||
int32_t tone_sample { 0 }, delta { 0 };
|
||||
int8_t re { }, im { };
|
||||
|
||||
TXDoneMessage message;
|
||||
TXDoneMessage message { };
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user