mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2025-07-11 03:08:32 +00:00
Added a bunch of notes about Radiosonde RX (help !)
This commit is contained in:
parent
d3222c27ca
commit
f00125879d
@ -53,14 +53,14 @@ SondeView::SondeView(NavigationView& nav) {
|
|||||||
field_frequency.set_value(receiver_model.tuning_frequency());
|
field_frequency.set_value(receiver_model.tuning_frequency());
|
||||||
field_frequency.set_step(receiver_model.frequency_step());
|
field_frequency.set_step(receiver_model.frequency_step());
|
||||||
field_frequency.on_change = [this](rf::Frequency f) {
|
field_frequency.on_change = [this](rf::Frequency f) {
|
||||||
receiver_model.set_tuning_frequency(f);
|
set_target_frequency(f);
|
||||||
field_frequency.set_value(f);
|
field_frequency.set_value(f);
|
||||||
};
|
};
|
||||||
field_frequency.on_edit = [this, &nav]() {
|
field_frequency.on_edit = [this, &nav]() {
|
||||||
// TODO: Provide separate modal method/scheme?
|
// TODO: Provide separate modal method/scheme?
|
||||||
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
|
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
|
||||||
new_view->on_changed = [this](rf::Frequency f) {
|
new_view->on_changed = [this](rf::Frequency f) {
|
||||||
receiver_model.set_tuning_frequency(f);
|
set_target_frequency(f);
|
||||||
field_frequency.set_value(f);
|
field_frequency.set_value(f);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -74,6 +74,8 @@ SondeView::SondeView(NavigationView& nav) {
|
|||||||
static_cast<int8_t>(receiver_model.lna()),
|
static_cast<int8_t>(receiver_model.lna()),
|
||||||
static_cast<int8_t>(receiver_model.vga()),
|
static_cast<int8_t>(receiver_model.vga()),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
set_target_frequency(402000000);
|
||||||
|
|
||||||
/*logger = std::make_unique<SondeLogger>();
|
/*logger = std::make_unique<SondeLogger>();
|
||||||
if( logger ) {
|
if( logger ) {
|
||||||
@ -90,8 +92,15 @@ void SondeView::focus() {
|
|||||||
field_vga.focus();
|
field_vga.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SondeView::on_packet(const sonde::Packet& packet) {
|
void SondeView::on_packet(const baseband::Packet& packet) {
|
||||||
text_debug.set("Got frame !");
|
std::string bin_string;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 30; i++) {
|
||||||
|
bin_string += to_string_dec_uint(packet[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
text_debug.set(bin_string);
|
||||||
|
|
||||||
/*if( logger ) {
|
/*if( logger ) {
|
||||||
logger->on_packet(packet);
|
logger->on_packet(packet);
|
||||||
}*/
|
}*/
|
||||||
@ -100,4 +109,13 @@ void SondeView::on_packet(const sonde::Packet& packet) {
|
|||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SondeView::set_target_frequency(const uint32_t new_value) {
|
||||||
|
target_frequency_ = new_value;
|
||||||
|
radio::set_tuning_frequency(tuning_frequency());
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SondeView::tuning_frequency() const {
|
||||||
|
return target_frequency_ - (sampling_rate / 4);
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui */
|
||||||
|
@ -67,6 +67,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
//std::unique_ptr<SondeLogger> logger { };
|
//std::unique_ptr<SondeLogger> logger { };
|
||||||
|
uint32_t target_frequency_ { };
|
||||||
|
|
||||||
FrequencyField field_frequency {
|
FrequencyField field_frequency {
|
||||||
{ 0 * 8, 0 * 8 },
|
{ 0 * 8, 0 * 8 },
|
||||||
@ -96,12 +97,16 @@ private:
|
|||||||
Message::ID::SondePacket,
|
Message::ID::SondePacket,
|
||||||
[this](Message* const p) {
|
[this](Message* const p) {
|
||||||
const auto message = static_cast<const SondePacketMessage*>(p);
|
const auto message = static_cast<const SondePacketMessage*>(p);
|
||||||
const sonde::Packet packet { message->type, message->packet };
|
//const sonde::Packet packet { message->type, message->packet };
|
||||||
this->on_packet(packet);
|
//this->on_packet(packet);
|
||||||
|
this->on_packet(message->packet);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void on_packet(const sonde::Packet& packet);
|
//void on_packet(const sonde::Packet& packet);
|
||||||
|
void on_packet(const baseband::Packet& packet);
|
||||||
|
void set_target_frequency(const uint32_t new_value);
|
||||||
|
uint32_t tuning_frequency() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui */
|
||||||
|
@ -28,22 +28,23 @@
|
|||||||
#include "event_m4.hpp"
|
#include "event_m4.hpp"
|
||||||
|
|
||||||
SondeProcessor::SondeProcessor() {
|
SondeProcessor::SondeProcessor() {
|
||||||
decim_0.configure(taps_200k_decim_0.taps, 33554432);
|
decim_0.configure(taps_11k0_decim_0.taps, 33554432);
|
||||||
decim_1.configure(taps_200k_decim_1.taps, 131072);
|
decim_1.configure(taps_11k0_decim_1.taps, 131072);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SondeProcessor::execute(const buffer_c8_t& buffer) {
|
void SondeProcessor::execute(const buffer_c8_t& buffer) {
|
||||||
/* 2.4576MHz, 2048 samples */
|
/* 2.4576MHz, 2048 samples */
|
||||||
|
|
||||||
const auto decim_0_out = decim_0.execute(buffer, dst_buffer);
|
const auto decim_0_out = decim_0.execute(buffer, dst_buffer);
|
||||||
const auto decimator_out = decim_1.execute(decim_0_out, dst_buffer);
|
const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer);
|
||||||
|
const auto decimator_out = decim_1_out;
|
||||||
|
|
||||||
/* 307.2kHz, 256 samples */
|
/* 38.4kHz, 32 samples */
|
||||||
feed_channel_stats(decimator_out);
|
feed_channel_stats(decimator_out);
|
||||||
|
|
||||||
for(size_t i=0; i<decimator_out.count; i++) {
|
for(size_t i=0; i<decimator_out.count; i++) {
|
||||||
if( mf_38k4_1t_19k2.execute_once(decimator_out.p[i]) ) {
|
if( mf.execute_once(decimator_out.p[i]) ) {
|
||||||
clock_recovery_fsk_19k2(mf_38k4_1t_19k2.get_output());
|
clock_recovery_fsk_4800(mf.get_output());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,13 +20,61 @@
|
|||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Notes to self (or others, welcome !):
|
||||||
|
* Sharebrained wrote in matched_filter.hpp that taps should be those of a complex low-pass filter combined with a complex sinusoid, so
|
||||||
|
* that the filter shifts the spectrum where we want (signal of interest around 0Hz).
|
||||||
|
*
|
||||||
|
* In this baseband processor, after decim_0 and decim_1, the signal ends up being sampled at 38400Hz (2457600 / 8 / 8)
|
||||||
|
* Since the applied shift in ui_sonde.cpp is -fs/4 = -2457600/4 = -614400Hz to avoid the DC spike, the FSK signal ends up being
|
||||||
|
* shifted by 614400 / 8 / 8 = 9600Hz. So decim_1_out should look like this:
|
||||||
|
*
|
||||||
|
* _______________|__/'\__________
|
||||||
|
* -C A B C
|
||||||
|
*
|
||||||
|
* A is the DC spike at 0Hz
|
||||||
|
* B is the FSK signal shifted right at 9600Hz
|
||||||
|
* C is the bandwidth edge at 19200Hz
|
||||||
|
*
|
||||||
|
* Taps should be computed to shift the whole spectrum by -9600Hz ("left") so that it looks like this:
|
||||||
|
*
|
||||||
|
* ______________/'\______________
|
||||||
|
* -C D C
|
||||||
|
*
|
||||||
|
* A should have been filtered off ?
|
||||||
|
* D is B around 0Hz now
|
||||||
|
*
|
||||||
|
* Then the clock_recovery function should be happy :)
|
||||||
|
*
|
||||||
|
* Mathworks.com says:
|
||||||
|
* In the case of a single-rate FIR design, we simply multiply each set of coefficients by (aka 'heterodyne with') a complex exponential.
|
||||||
|
*
|
||||||
|
* Can SciPy's remez function be used for this ? See tools/firtest.py
|
||||||
|
* GnuRadio's firdes only outputs an odd number of taps
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Looking at the AIS baseband processor:
|
||||||
|
*
|
||||||
|
* Copied everything necessary to get decim_1_out (so same 8 * 8 = 64 decimation factor)
|
||||||
|
* The samplerate is also the same (2457600)
|
||||||
|
* After the matching filter, the data is decimated by 2 so the final samplerate for clock_recovery is 38400 / 2 = 19200Hz.
|
||||||
|
* Like here, the shift used is fs/4, so decim_1_out should be looking similar.
|
||||||
|
* The AIS signal deviates by 2400 (4800Hz signal width), the symbol rate is 9600.
|
||||||
|
*
|
||||||
|
* The matched filter's input samplerate is 38400Hz, to get a 9600Hz shift it must use 4 taps ?
|
||||||
|
* To obtain unity gain, the sinusoid length must be / by the number of taps ?
|
||||||
|
*
|
||||||
|
* See ais_baseband.hpp
|
||||||
|
*
|
||||||
|
* */
|
||||||
|
|
||||||
#ifndef __PROC_SONDE_H__
|
#ifndef __PROC_SONDE_H__
|
||||||
#define __PROC_SONDE_H__
|
#define __PROC_SONDE_H__
|
||||||
|
|
||||||
#include "baseband_processor.hpp"
|
#include "baseband_processor.hpp"
|
||||||
#include "baseband_thread.hpp"
|
#include "baseband_thread.hpp"
|
||||||
#include "rssi_thread.hpp"
|
#include "rssi_thread.hpp"
|
||||||
#include "proc_tpms.hpp"
|
#include "proc_ais.hpp"
|
||||||
|
|
||||||
#include "channel_decimator.hpp"
|
#include "channel_decimator.hpp"
|
||||||
#include "matched_filter.hpp"
|
#include "matched_filter.hpp"
|
||||||
@ -36,8 +84,6 @@
|
|||||||
#include "packet_builder.hpp"
|
#include "packet_builder.hpp"
|
||||||
#include "baseband_packet.hpp"
|
#include "baseband_packet.hpp"
|
||||||
|
|
||||||
#include "ook.hpp"
|
|
||||||
|
|
||||||
#include "message.hpp"
|
#include "message.hpp"
|
||||||
#include "portapack_shared_memory.hpp"
|
#include "portapack_shared_memory.hpp"
|
||||||
|
|
||||||
@ -63,13 +109,13 @@ private:
|
|||||||
dst.size()
|
dst.size()
|
||||||
};
|
};
|
||||||
|
|
||||||
dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0 { };
|
dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0 { };
|
||||||
dsp::decimate::FIRC16xR16x16Decim2 decim_1 { };
|
dsp::decimate::FIRC16xR16x32Decim8 decim_1 { };
|
||||||
|
dsp::matched_filter::MatchedFilter mf { baseband::ais::square_taps_38k4_1t_p, 2 };
|
||||||
|
|
||||||
dsp::matched_filter::MatchedFilter mf_38k4_1t_19k2 { rect_taps_307k2_38k4_1t_19k2_p, 8 };
|
// AIS: 19200, 9600
|
||||||
|
clock_recovery::ClockRecovery<clock_recovery::FixedErrorFilter> clock_recovery_fsk_4800 {
|
||||||
clock_recovery::ClockRecovery<clock_recovery::FixedErrorFilter> clock_recovery_fsk_19k2 {
|
19200, 4800, { 0.0555f },
|
||||||
38400, 19200, { 0.0555f },
|
|
||||||
[this](const float raw_symbol) {
|
[this](const float raw_symbol) {
|
||||||
const uint_fast8_t sliced_symbol = (raw_symbol >= 0.0f) ? 1 : 0;
|
const uint_fast8_t sliced_symbol = (raw_symbol >= 0.0f) ? 1 : 0;
|
||||||
this->packet_builder_fsk_4800_M10.execute(sliced_symbol);
|
this->packet_builder_fsk_4800_M10.execute(sliced_symbol);
|
||||||
@ -78,7 +124,7 @@ private:
|
|||||||
PacketBuilder<BitPattern, NeverMatch, FixedLength> packet_builder_fsk_4800_M10 {
|
PacketBuilder<BitPattern, NeverMatch, FixedLength> packet_builder_fsk_4800_M10 {
|
||||||
{ 0b11001100110011001010011001001100, 32, 1 },
|
{ 0b11001100110011001010011001001100, 32, 1 },
|
||||||
{ },
|
{ },
|
||||||
{ 102 * 8 },
|
{ 50 }, // { 102 * 8 },
|
||||||
[this](const baseband::Packet& packet) {
|
[this](const baseband::Packet& packet) {
|
||||||
const SondePacketMessage message { sonde::Packet::Type::M10, packet };
|
const SondePacketMessage message { sonde::Packet::Type::M10, packet };
|
||||||
shared_memory.application_queue.push(message);
|
shared_memory.application_queue.push(message);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user