Skip to content
This repository has been archived by the owner on Jun 25, 2020. It is now read-only.

Commit

Permalink
Using new CPLD data (fixes spectrum mirroring)
Browse files Browse the repository at this point in the history
Scanner bugfix for wide ranges
Added squelch parameter for NFM receiver
Adjustment to Vumeter widget rendering
  • Loading branch information
furrtek authored and furrtek committed Jun 11, 2017
1 parent 042d271 commit e2f0a03
Show file tree
Hide file tree
Showing 13 changed files with 105 additions and 54 deletions.
2 changes: 1 addition & 1 deletion firmware/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ set(CHIBIOS_PORTAPACK ${PROJECT_SOURCE_DIR}/chibios-portapack)
set(HACKRF_FIRMWARE_FILENAME hackrf_one_usb.dfu)
set(HACKRF_FIRMWARE_IMAGE ${PROJECT_SOURCE_DIR}/${HACKRF_FIRMWARE_FILENAME})

set(HACKRF_CPLD_SVF_FILENAME hackrf_cpld_default.svf)
set(HACKRF_CPLD_SVF_FILENAME hackrf_cpld_portapack.svf)
set(HACKRF_CPLD_SVF_PATH ${PROJECT_SOURCE_DIR}/${HACKRF_CPLD_SVF_FILENAME})

set(EXTRACT_CPLD_DATA ${PROJECT_SOURCE_DIR}/tools/extract_cpld_data.py)
Expand Down
7 changes: 7 additions & 0 deletions firmware/application/analog_audio_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 *******************************************************/
Expand Down
13 changes: 13 additions & 0 deletions firmware/application/analog_audio_app.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,19 @@ class NBFMOptionsView : public View {
{ "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 {
Expand Down
5 changes: 3 additions & 2 deletions firmware/application/baseband_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,16 @@ 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,
channel,
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);
Expand Down
2 changes: 1 addition & 1 deletion firmware/application/baseband_api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
11 changes: 10 additions & 1 deletion firmware/application/receiver_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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 {
Expand Down
4 changes: 4 additions & 0 deletions firmware/application/receiver_model.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ class ReceiverModel {

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();
Expand Down Expand Up @@ -99,6 +102,7 @@ class ReceiverModel {
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();

Expand Down
83 changes: 48 additions & 35 deletions firmware/application/ui_scanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
}
}

Expand Down Expand Up @@ -157,70 +165,73 @@ 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();
slice_counter = 0;
}
receiver_model.set_tuning_frequency(slices[slice_counter].center_frequency);
} else {
// Unique slice
do_detection();
}

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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) {
Expand Down
16 changes: 10 additions & 6 deletions firmware/application/ui_scanner.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ class ScannerView : public View {
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 };
Expand All @@ -123,7 +126,7 @@ class ScannerView : public View {
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 };
Expand All @@ -135,6 +138,7 @@ class ScannerView : public View {
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 },
Expand All @@ -149,7 +153,7 @@ class ScannerView : public View {
{ { 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() }
};

Expand Down Expand Up @@ -188,12 +192,12 @@ class ScannerView : public View {

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 },
Expand All @@ -203,11 +207,11 @@ class ScannerView : public View {
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 },
Expand Down
3 changes: 1 addition & 2 deletions firmware/baseband/proc_nfm_audio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,7 @@ void NarrowbandFMAudio::configure(const NBFMConfigureMessage& message) {
channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs;
channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs;
channel_spectrum.set_decimation_factor(std::floor(channel_filter_output_fs / (channel_filter_pass_f + channel_filter_stop_f)));
// TODO: Configurable squelch threshold
audio_output.configure(message.audio_hpf_config, message.audio_deemph_config, 0.8f);
audio_output.configure(message.audio_hpf_config, message.audio_deemph_config, (float)message.squelch_level / 100.0);

synth_acc = 0;

Expand Down
2 changes: 0 additions & 2 deletions firmware/baseband/proc_wideband_spectrum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@

#include "event_m4.hpp"

#include "dsp_fft.hpp"

#include <cstdint>
#include <cstddef>

Expand Down
7 changes: 5 additions & 2 deletions firmware/common/message.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,15 +356,17 @@ class NBFMConfigureMessage : public Message {
const size_t channel_decimation,
const size_t deviation,
const iir_biquad_config_t audio_hpf_config,
const iir_biquad_config_t audio_deemph_config
const iir_biquad_config_t audio_deemph_config,
const uint8_t squelch_level
) : Message { ID::NBFMConfigure },
decim_0_filter(decim_0_filter),
decim_1_filter(decim_1_filter),
channel_filter(channel_filter),
channel_decimation { channel_decimation },
deviation { deviation },
audio_hpf_config(audio_hpf_config),
audio_deemph_config(audio_deemph_config)
audio_deemph_config(audio_deemph_config),
squelch_level(squelch_level)
{
}

Expand All @@ -375,6 +377,7 @@ class NBFMConfigureMessage : public Message {
const size_t deviation;
const iir_biquad_config_t audio_hpf_config;
const iir_biquad_config_t audio_deemph_config;
const uint8_t squelch_level;
};

class WFMConfigureMessage : public Message {
Expand Down
4 changes: 2 additions & 2 deletions firmware/common/ui_widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1461,7 +1461,7 @@ VuMeter::VuMeter(
show_max_ { show_max }
{
//set_focusable(false);
LED_height = parent_rect.size().height() / LEDs;
LED_height = std::max(1UL, parent_rect.size().height() / LEDs);
split = 256 / LEDs;
}

Expand Down Expand Up @@ -1507,7 +1507,7 @@ void VuMeter::paint(Painter& painter) {
else
color = lit ? Color::green() : Color::dark_green();

painter.fill_rectangle({ pos.x(), pos.y() + (Coord)(bar * LED_height), width, (Coord)LED_height - 2 }, color);
painter.fill_rectangle({ pos.x(), pos.y() + (Coord)(bar * (LED_height + 1)), width, (Coord)LED_height }, color);
}
prev_value = value_;
}
Expand Down

0 comments on commit e2f0a03

Please sign in to comment.