Using new CPLD data (fixes spectrum mirroring)

Scanner bugfix for wide ranges
Added squelch parameter for NFM receiver
Adjustment to Vumeter widget rendering
This commit is contained in:
furrtek 2017-06-11 09:50:29 +01:00
parent 042d271a9f
commit e2f0a03460
13 changed files with 105 additions and 54 deletions

View file

@ -66,12 +66,19 @@ NBFMOptionsView::NBFMOptionsView(
add_children({
&label_config,
&options_config,
&text_squelch,
&field_squelch
});
options_config.set_selected_index(receiver_model.nbfm_configuration());
options_config.on_change = [this](size_t n, OptionsField::value_t) {
receiver_model.set_nbfm_configuration(n);
};
field_squelch.set_value(receiver_model.squelch_level());
field_squelch.on_change = [this](int32_t v) {
receiver_model.set_squelch_level(v);
};
}
/* AnalogAudioView *******************************************************/

View file

@ -78,6 +78,19 @@ private:
{ "16k ", 0 },
}
};
Text text_squelch {
{ 9 * 8, 0 * 16, 7 * 8, 1 * 16 },
"SQ /100"
};
NumberField field_squelch {
{ 12 * 8, 0 * 16 },
3,
{ 0, 100 },
1,
' ',
};
};
class AnalogAudioView : public View {

View file

@ -52,7 +52,7 @@ void AMConfig::apply() const {
audio::set_rate(audio::Rate::Hz_12000);
}
void NBFMConfig::apply() const {
void NBFMConfig::apply(const uint8_t squelch_level) const {
const NBFMConfigureMessage message {
decim_0,
decim_1,
@ -60,7 +60,8 @@ void NBFMConfig::apply() const {
2,
deviation,
audio_24k_hpf_300hz_config,
audio_24k_deemph_300_6_config
audio_24k_deemph_300_6_config,
squelch_level
};
send_message(&message);
audio::set_rate(audio::Rate::Hz_24000);

View file

@ -48,7 +48,7 @@ struct NBFMConfig {
const fir_taps_real<32> channel;
const size_t deviation;
void apply() const;
void apply(const uint8_t squelch_level) const;
};
struct WFMConfig {

View file

@ -153,6 +153,15 @@ void ReceiverModel::set_headphone_volume(volume_t v) {
update_headphone_volume();
}
uint8_t ReceiverModel::squelch_level() const {
return squelch_level_;
}
void ReceiverModel::set_squelch_level(uint8_t v) {
squelch_level_ = v;
update_modulation();
}
void ReceiverModel::enable() {
enabled_ = true;
radio::set_direction(rf::Direction::Receive);
@ -286,7 +295,7 @@ size_t ReceiverModel::nbfm_configuration() const {
}
void ReceiverModel::update_nbfm_configuration() {
nbfm_configs[nbfm_config_index].apply();
nbfm_configs[nbfm_config_index].apply(squelch_level_);
}
size_t ReceiverModel::wfm_configuration() const {

View file

@ -71,6 +71,9 @@ public:
volume_t headphone_volume() const;
void set_headphone_volume(volume_t v);
uint8_t squelch_level() const;
void set_squelch_level(uint8_t v);
void enable();
void disable();
@ -99,6 +102,7 @@ private:
size_t nbfm_config_index = 0;
size_t wfm_config_index = 0;
volume_t headphone_volume_ { -43.0_dB };
uint8_t squelch_level_ { 80 };
int32_t tuning_offset();

View file

@ -66,6 +66,14 @@ void ScannerView::do_detection() {
rtc::RTC datetime;
std::string str_approx, str_timestamp;
// Display spectrum
bin_skip_acc = 0;
pixel_index = 0;
display.draw_pixels(
{ { 0, 88 }, { (Dim)spectrum_row.size(), 1 } },
spectrum_row
);
mean_power = mean_acc / (SCAN_BIN_NB_NO_DC * slices_nb);
mean_acc = 0;
@ -79,8 +87,8 @@ void ScannerView::do_detection() {
if ((power >= mean_power + power_threshold) && (power > power_max)) {
power_max = power;
bin_max_pixel = slices[slice].max_index;
bin_max = bin_max_pixel + (slice * SCAN_BIN_NB);
bin_max = slices[slice].max_index + (slice * SCAN_BIN_NB);
bin_max_pixel = bin_max / slices_nb;
}
}
@ -157,63 +165,65 @@ void ScannerView::do_detection() {
scan_counter++;
// Refresh red tick
portapack::display.fill_rectangle({last_pos, 90, 1, 6}, Color::black());
portapack::display.fill_rectangle({last_tick_pos, 90, 1, 6}, Color::black());
if (bin_max > -1) {
if (bin_max_pixel < 120)
bin_max_pixel += 2;
//if (bin_max_pixel < 120)
// bin_max_pixel += 2;
//else
// bin_max_pixel -= 0;
last_pos = (ui::Coord)bin_max_pixel;
portapack::display.fill_rectangle({last_pos, 90, 1, 6}, Color::red());
last_tick_pos = (Coord)bin_max_pixel;
portapack::display.fill_rectangle({last_tick_pos, 90, 1, 6}, Color::red());
}
}
void ScannerView::add_spectrum_pixel(Color color) {
// Is avoiding floats really needed ?
bin_skip_acc += bin_skip_frac;
if (bin_skip_acc < 0x10000)
return;
bin_skip_acc -= 0x10000;
if (pixel_index < 240)
spectrum_row[pixel_index++] = color;
}
void ScannerView::on_channel_spectrum(const ChannelSpectrum& spectrum) {
uint8_t power_max = 0;
int16_t bin_max = 0;
uint8_t max_power = 0;
int16_t max_bin = 0;
uint8_t power;
size_t bin;
std::array<Color, 240> pixel_row;
baseband::spectrum_streaming_stop();
// Draw spectrum line
// Add pixels to spectrum row, and find max power for this slice
// Leftmost and rightmost 2 bins are ignored
// Center 12 bins are ignored
// 256-2-2-12 = 240 bins used
for (bin = 0; bin < 120; bin++) {
const auto pixel_color = spectrum_rgb3_lut[spectrum.db[134 + bin]]; // 134~253 in 0~119
pixel_row[bin] = pixel_color;
}
for (bin = 120; bin < 240; bin++) {
const auto pixel_color = spectrum_rgb3_lut[spectrum.db[bin - 118]]; // 2~121 in 120~239
pixel_row[bin] = pixel_color;
}
display.draw_pixels(
{ { 0, 88 + slice_counter * 2 }, { pixel_row.size(), 1 } },
pixel_row
);
// Find max power for this slice
for (bin = 0 ; bin < 120; bin++) {
add_spectrum_pixel(spectrum_rgb3_lut[spectrum.db[134 + bin]]); // 134~253 goes in 0~119
power = spectrum.db[134 + bin];
mean_acc += power;
if (power > power_max) {
power_max = power;
bin_max = bin - 2;
if (power > max_power) {
max_power = power;
max_bin = bin - 2; // To check
}
}
for (bin = 120; bin < 240; bin++) {
add_spectrum_pixel(spectrum_rgb3_lut[spectrum.db[bin - 118]]); // 2~121 goes in 120~239
power = spectrum.db[bin - 118];
mean_acc += power;
if (power > power_max) {
power_max = power;
bin_max = bin + 2;
if (power > max_power) {
max_power = power;
max_bin = bin + 2; // To check
}
}
slices[slice_counter].max_power = power_max;
slices[slice_counter].max_index = bin_max;
slices[slice_counter].max_power = max_power;
slices[slice_counter].max_index = max_bin;
// Slice update
if (slices_nb > 1) {
// Slice sequence
slice_counter++;
if (slice_counter >= slices_nb) {
do_detection();
@ -221,6 +231,7 @@ void ScannerView::on_channel_spectrum(const ChannelSpectrum& spectrum) {
}
receiver_model.set_tuning_frequency(slices[slice_counter].center_frequency);
} else {
// Unique slice
do_detection();
}
@ -272,6 +283,8 @@ void ScannerView::on_range_changed() {
slices_nb = 1;
text_slices.set(" 1");
}
bin_skip_frac = 0x10000 / slices_nb;
slice_counter = 0;
}
@ -353,7 +366,7 @@ ScannerView::ScannerView(
&recent_entries_view
});
baseband::set_spectrum(SCAN_SLICE_WIDTH, 32);
baseband::set_spectrum(SCAN_SLICE_WIDTH, 31);
recent_entries_view.set_parent_rect({ 0, 28 * 8, 240, 12 * 8 });
recent_entries_view.on_select = [this, &nav](const ScannerRecentEntry& entry) {

View file

@ -112,6 +112,9 @@ private:
int16_t index;
} slices[32];
uint32_t bin_skip_acc { 0 }, bin_skip_frac { };
uint32_t pixel_index { 0 };
std::array<Color, 240> spectrum_row { 0 };
ChannelSpectrumFIFO* fifo { nullptr };
rf::Frequency f_min { 0 }, f_max { 0 };
uint8_t detect_timer { 0 }, release_timer { 0 }, timing_div { 0 };
@ -123,7 +126,7 @@ private:
uint8_t slices_nb { 0 };
uint8_t slice_counter { 0 };
int16_t last_bin { 0 };
Coord last_pos { 0 };
Coord last_tick_pos { 0 };
rf::Frequency scan_span { 0 }, resolved_frequency { 0 };
uint16_t locked_bin { 0 };
uint8_t scan_counter { 0 };
@ -135,6 +138,7 @@ private:
void on_lna_changed(int32_t v_db);
void on_vga_changed(int32_t v_db);
void do_timers();
void add_spectrum_pixel(Color color);
const RecentEntriesColumns columns { {
{ "Frequency", 9 },
@ -149,7 +153,7 @@ private:
{ { 1 * 8, 4 * 8 }, "Trig: /255 Mean: /255", Color::light_grey() },
{ { 1 * 8, 6 * 8 }, "Slices: /32 Rate: Hz", Color::light_grey() },
{ { 6 * 8, 10 * 8 }, "Timer Status", Color::light_grey() },
{ { 1 * 8, 25 * 8 }, "Accuracy: +/-4.9kHz", Color::light_grey() },
{ { 1 * 8, 25 * 8 }, "Accuracy +/-4.9kHz", Color::light_grey() },
{ { 26 * 8, 25 * 8 }, "MHz", Color::light_grey() }
};
@ -188,12 +192,12 @@ private:
VuMeter vu_max {
{ 1 * 8, 11 * 8 - 4, 3 * 8, 48 },
16,
18,
false
};
ProgressBar progress_timers {
{ 6 * 8, 12 * 8, 5 * 8, 16 }
{ 6 * 8, 12 * 8, 6 * 8, 16 }
};
Text text_infos {
{ 13 * 8, 12 * 8, 15 * 8, 16 },
@ -203,11 +207,11 @@ private:
Checkbox check_snap {
{ 6 * 8, 15 * 8 },
7,
"Adjust:",
"Snap to:",
true
};
OptionsField options_snap {
{ 15 * 8, 15 * 8 },
{ 17 * 8, 15 * 8 },
7,
{
{ "25kHz ", 25000 },