mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-10-01 01:26:06 -04:00
Merge remote-tracking branch 'upstream/master'
# Conflicts: # firmware/application/bitmap.hpp # firmware/application/receiver_model.cpp # firmware/application/receiver_model.hpp # firmware/application/touch.hpp # firmware/application/ui_setup.cpp # firmware/baseband/proc_ais.hpp # firmware/baseband/proc_ert.hpp # firmware/bootstrap/CMakeLists.txt # firmware/common/portapack_persistent_memory.cpp # firmware/common/portapack_persistent_memory.hpp
This commit is contained in:
commit
45a754645e
@ -29,7 +29,7 @@ enable_language(C CXX ASM)
|
||||
project(application)
|
||||
|
||||
# Compiler options here.
|
||||
set(USE_OPT "-Os --specs=nano.specs")
|
||||
set(USE_OPT "-Os -g --specs=nano.specs")
|
||||
|
||||
# C specific options here (added to USE_OPT).
|
||||
set(USE_COPT "-std=gnu99")
|
||||
@ -150,6 +150,7 @@ set(CPPSRC
|
||||
ui_audio.cpp
|
||||
ui_font_fixed_8x16.cpp
|
||||
ui_setup.cpp
|
||||
ui_touch_calibration.cpp
|
||||
ui_debug.cpp
|
||||
ui_baseband_stats_view.cpp
|
||||
ui_sd_card_status_view.cpp
|
||||
|
@ -4062,6 +4062,30 @@ ui_textentry.cpp.s:
|
||||
cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_textentry.cpp.s
|
||||
.PHONY : ui_textentry.cpp.s
|
||||
|
||||
ui_touch_calibration.obj: ui_touch_calibration.cpp.obj
|
||||
.PHONY : ui_touch_calibration.obj
|
||||
|
||||
# target to build an object file
|
||||
ui_touch_calibration.cpp.obj:
|
||||
cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_touch_calibration.cpp.obj
|
||||
.PHONY : ui_touch_calibration.cpp.obj
|
||||
|
||||
ui_touch_calibration.i: ui_touch_calibration.cpp.i
|
||||
.PHONY : ui_touch_calibration.i
|
||||
|
||||
# target to preprocess a source file
|
||||
ui_touch_calibration.cpp.i:
|
||||
cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_touch_calibration.cpp.i
|
||||
.PHONY : ui_touch_calibration.cpp.i
|
||||
|
||||
ui_touch_calibration.s: ui_touch_calibration.cpp.s
|
||||
.PHONY : ui_touch_calibration.s
|
||||
|
||||
# target to generate assembly for a file
|
||||
ui_touch_calibration.cpp.s:
|
||||
cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/ui_touch_calibration.cpp.s
|
||||
.PHONY : ui_touch_calibration.cpp.s
|
||||
|
||||
ui_xylos.obj: ui_xylos.cpp.obj
|
||||
.PHONY : ui_xylos.obj
|
||||
|
||||
@ -4588,6 +4612,9 @@ help:
|
||||
@echo "... ui_textentry.obj"
|
||||
@echo "... ui_textentry.i"
|
||||
@echo "... ui_textentry.s"
|
||||
@echo "... ui_touch_calibration.obj"
|
||||
@echo "... ui_touch_calibration.i"
|
||||
@echo "... ui_touch_calibration.s"
|
||||
@echo "... ui_xylos.obj"
|
||||
@echo "... ui_xylos.i"
|
||||
@echo "... ui_xylos.s"
|
||||
|
@ -25,6 +25,9 @@
|
||||
|
||||
#include "baseband_api.hpp"
|
||||
|
||||
#include "portapack.hpp"
|
||||
using namespace portapack;
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace ais {
|
||||
@ -291,6 +294,11 @@ AISAppView::AISAppView(NavigationView&) {
|
||||
add_children({ {
|
||||
&label_channel,
|
||||
&options_channel,
|
||||
&field_rf_amp,
|
||||
&field_lna,
|
||||
&field_vga,
|
||||
&rssi,
|
||||
&channel,
|
||||
&recent_entries_view,
|
||||
&recent_entry_detail_view,
|
||||
} });
|
||||
@ -304,7 +312,9 @@ AISAppView::AISAppView(NavigationView&) {
|
||||
sampling_rate,
|
||||
baseband_bandwidth,
|
||||
rf::Direction::Receive,
|
||||
false, 32, 32,
|
||||
receiver_model.rf_amp(),
|
||||
static_cast<int8_t>(receiver_model.lna()),
|
||||
static_cast<int8_t>(receiver_model.vga()),
|
||||
1,
|
||||
});
|
||||
|
||||
|
@ -24,6 +24,9 @@
|
||||
|
||||
#include "ui_widget.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "ui_receiver.hpp"
|
||||
#include "ui_rssi.hpp"
|
||||
#include "ui_channel.hpp"
|
||||
|
||||
#include "event_m0.hpp"
|
||||
|
||||
@ -177,6 +180,26 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
RFAmpField field_rf_amp {
|
||||
{ 13 * 8, 0 * 16 }
|
||||
};
|
||||
|
||||
LNAGainField field_lna {
|
||||
{ 15 * 8, 0 * 16 }
|
||||
};
|
||||
|
||||
VGAGainField field_vga {
|
||||
{ 18 * 8, 0 * 16 }
|
||||
};
|
||||
|
||||
RSSI rssi {
|
||||
{ 21 * 8, 0, 6 * 8, 4 },
|
||||
};
|
||||
|
||||
Channel channel {
|
||||
{ 21 * 8, 5, 6 * 8, 4 },
|
||||
};
|
||||
|
||||
MessageHandlerRegistration message_handler_packet {
|
||||
Message::ID::AISPacket,
|
||||
[this](Message* const p) {
|
||||
|
@ -119,7 +119,7 @@ AnalogAudioView::AnalogAudioView(
|
||||
};
|
||||
|
||||
const auto modulation = receiver_model.modulation();
|
||||
options_modulation.set_by_value(modulation);
|
||||
options_modulation.set_by_value(toUType(modulation));
|
||||
options_modulation.on_change = [this](size_t, OptionsField::value_t v) {
|
||||
this->on_modulation_changed(static_cast<ReceiverModel::Mode>(v));
|
||||
};
|
||||
@ -286,11 +286,8 @@ void AnalogAudioView::update_modulation(const ReceiverModel::Mode modulation) {
|
||||
baseband::run_image(image_tag);
|
||||
|
||||
const auto is_wideband_spectrum_mode = (modulation == ReceiverModel::Mode::SpectrumAnalysis);
|
||||
receiver_model.set_baseband_configuration({
|
||||
.mode = toUType(modulation),
|
||||
.sampling_rate = is_wideband_spectrum_mode ? 20000000U : 3072000U,
|
||||
.decimation_factor = 1,
|
||||
});
|
||||
receiver_model.set_modulation(modulation);
|
||||
receiver_model.set_sampling_rate(is_wideband_spectrum_mode ? 20000000 : 3072000);
|
||||
receiver_model.set_baseband_bandwidth(is_wideband_spectrum_mode ? 12000000 : 1750000);
|
||||
receiver_model.enable();
|
||||
|
||||
|
@ -99,6 +99,13 @@ void set_afsk_data(const uint32_t afsk_samples_per_bit, const uint32_t afsk_phas
|
||||
send_message(&message);
|
||||
}
|
||||
|
||||
void set_audiotx_data(const uint32_t bw) {
|
||||
const AudioTXConfigMessage message {
|
||||
bw
|
||||
};
|
||||
send_message(&message);
|
||||
}
|
||||
|
||||
void set_pwmrssi(int32_t avg, bool enabled) {
|
||||
const PWMRSSIConfigureMessage message {
|
||||
enabled,
|
||||
|
@ -53,6 +53,7 @@ struct WFMConfig {
|
||||
};
|
||||
|
||||
void set_ccir_data( const uint32_t samples_per_tone, const uint16_t tone_count);
|
||||
void set_audiotx_data(const uint32_t bw);
|
||||
void set_pwmrssi(int32_t avg, bool enabled);
|
||||
void set_afsk_data(const uint32_t afsk_samples_per_bit, const uint32_t afsk_phase_inc_mark, const uint32_t afsk_phase_inc_space,
|
||||
const uint8_t afsk_repeat, const uint32_t afsk_bw, const bool afsk_alt_format);
|
||||
|
@ -244,6 +244,98 @@ static constexpr Bitmap bitmap_sd_card_error {
|
||||
{ 16, 16 }, bitmap_sd_card_error_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_target_calibrate_data[] = {
|
||||
0x02, 0x00, 0x00, 0x40,
|
||||
0x07, 0x00, 0x00, 0xe0,
|
||||
0x0e, 0x00, 0x00, 0x70,
|
||||
0x1c, 0x00, 0x00, 0x38,
|
||||
|
||||
0x38, 0x00, 0x00, 0x1c,
|
||||
0x70, 0x00, 0x00, 0x0e,
|
||||
0xe0, 0x00, 0x00, 0x07,
|
||||
0xc0, 0x01, 0x80, 0x03,
|
||||
|
||||
0x80, 0x03, 0xc0, 0x01,
|
||||
0x00, 0x07, 0xe0, 0x00,
|
||||
0x00, 0x0e, 0x70, 0x00,
|
||||
0x00, 0x1c, 0x38, 0x00,
|
||||
|
||||
0x00, 0x38, 0x1c, 0x00,
|
||||
0x00, 0x30, 0x0c, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x30, 0x0c, 0x00,
|
||||
0x00, 0x38, 0x1c, 0x00,
|
||||
|
||||
0x00, 0x1c, 0x38, 0x00,
|
||||
0x00, 0x0e, 0x70, 0x00,
|
||||
0x00, 0x07, 0xe0, 0x00,
|
||||
0x80, 0x03, 0xc0, 0x01,
|
||||
|
||||
0xc0, 0x01, 0x80, 0x03,
|
||||
0xe0, 0x00, 0x00, 0x07,
|
||||
0x70, 0x00, 0x00, 0x0e,
|
||||
0x38, 0x00, 0x00, 0x1c,
|
||||
|
||||
0x1c, 0x00, 0x00, 0x38,
|
||||
0x0e, 0x00, 0x00, 0x70,
|
||||
0x07, 0x00, 0x00, 0xe0,
|
||||
0x02, 0x00, 0x00, 0x40,
|
||||
};
|
||||
|
||||
static constexpr Bitmap bitmap_target_calibrate {
|
||||
{ 32, 32 }, bitmap_target_calibrate_data
|
||||
};
|
||||
|
||||
static constexpr uint8_t bitmap_target_verify_data[] = {
|
||||
0x00, 0xe0, 0x07, 0x00,
|
||||
0x00, 0xfc, 0x3f, 0x00,
|
||||
0x00, 0x1f, 0xf8, 0x00,
|
||||
0xc0, 0x03, 0xc0, 0x03,
|
||||
|
||||
0xe0, 0x00, 0x00, 0x07,
|
||||
0x70, 0x00, 0x00, 0x0e,
|
||||
0x38, 0x00, 0x00, 0x1c,
|
||||
0x18, 0x00, 0x00, 0x18,
|
||||
|
||||
0x0c, 0x00, 0x00, 0x30,
|
||||
0x0c, 0x00, 0x00, 0x30,
|
||||
0x06, 0x00, 0x00, 0x60,
|
||||
0x06, 0x00, 0x00, 0x60,
|
||||
|
||||
0x06, 0x00, 0x00, 0x60,
|
||||
0x03, 0x80, 0x01, 0xc0,
|
||||
0x03, 0x80, 0x01, 0xc0,
|
||||
0x03, 0xe0, 0x07, 0xc0,
|
||||
|
||||
0x03, 0xe0, 0x07, 0xc0,
|
||||
0x03, 0x80, 0x01, 0xc0,
|
||||
0x03, 0x80, 0x01, 0xc0,
|
||||
0x06, 0x00, 0x00, 0x60,
|
||||
|
||||
0x06, 0x00, 0x00, 0x60,
|
||||
0x06, 0x00, 0x00, 0x60,
|
||||
0x0c, 0x00, 0x00, 0x30,
|
||||
0x0c, 0x00, 0x00, 0x30,
|
||||
|
||||
0x18, 0x00, 0x00, 0x18,
|
||||
0x38, 0x00, 0x00, 0x1c,
|
||||
0x70, 0x00, 0x00, 0x0e,
|
||||
0xe0, 0x00, 0x00, 0x07,
|
||||
|
||||
0xc0, 0x03, 0xc0, 0x03,
|
||||
0x00, 0x1f, 0xf8, 0x00,
|
||||
0x00, 0xfc, 0x3f, 0x00,
|
||||
0x00, 0xe0, 0x07, 0x00,
|
||||
};
|
||||
|
||||
static constexpr Bitmap bitmap_target_verify {
|
||||
{ 32, 32 }, bitmap_target_verify_data
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
#endif/*__BITMAP_HPP__*/
|
||||
|
@ -23,6 +23,9 @@
|
||||
|
||||
#include "baseband_api.hpp"
|
||||
|
||||
#include "portapack.hpp"
|
||||
using namespace portapack;
|
||||
|
||||
#include "manchester.hpp"
|
||||
|
||||
#include "crc.hpp"
|
||||
@ -124,6 +127,10 @@ ERTAppView::ERTAppView(NavigationView&) {
|
||||
baseband::run_image(portapack::spi_flash::image_tag_ert);
|
||||
|
||||
add_children({ {
|
||||
&field_rf_amp,
|
||||
&field_lna,
|
||||
&field_vga,
|
||||
&rssi,
|
||||
&recent_entries_view,
|
||||
} });
|
||||
|
||||
@ -132,7 +139,9 @@ ERTAppView::ERTAppView(NavigationView&) {
|
||||
sampling_rate,
|
||||
baseband_bandwidth,
|
||||
rf::Direction::Receive,
|
||||
false, 32, 32,
|
||||
receiver_model.rf_amp(),
|
||||
static_cast<int8_t>(receiver_model.lna()),
|
||||
static_cast<int8_t>(receiver_model.vga()),
|
||||
1,
|
||||
});
|
||||
|
||||
@ -149,12 +158,12 @@ ERTAppView::~ERTAppView() {
|
||||
}
|
||||
|
||||
void ERTAppView::focus() {
|
||||
recent_entries_view.focus();
|
||||
field_vga.focus();
|
||||
}
|
||||
|
||||
void ERTAppView::set_parent_rect(const Rect new_parent_rect) {
|
||||
View::set_parent_rect(new_parent_rect);
|
||||
recent_entries_view.set_parent_rect({ 0, 0, new_parent_rect.width(), new_parent_rect.height() });
|
||||
recent_entries_view.set_parent_rect({ 0, header_height, new_parent_rect.width(), new_parent_rect.height() - header_height });
|
||||
}
|
||||
|
||||
void ERTAppView::on_packet(const ert::Packet& packet) {
|
||||
|
@ -23,6 +23,9 @@
|
||||
#define __ERT_APP_H__
|
||||
|
||||
#include "ui_navigation.hpp"
|
||||
#include "ui_receiver.hpp"
|
||||
#include "ui_rssi.hpp"
|
||||
#include "ui_channel.hpp"
|
||||
|
||||
#include "event_m0.hpp"
|
||||
|
||||
@ -128,6 +131,24 @@ private:
|
||||
|
||||
ERTRecentEntriesView recent_entries_view { recent };
|
||||
|
||||
static constexpr auto header_height = 1 * 16;
|
||||
|
||||
RFAmpField field_rf_amp {
|
||||
{ 13 * 8, 0 * 16 }
|
||||
};
|
||||
|
||||
LNAGainField field_lna {
|
||||
{ 15 * 8, 0 * 16 }
|
||||
};
|
||||
|
||||
VGAGainField field_vga {
|
||||
{ 18 * 8, 0 * 16 }
|
||||
};
|
||||
|
||||
RSSI rssi {
|
||||
{ 21 * 8, 0, 6 * 8, 4 },
|
||||
};
|
||||
|
||||
MessageHandlerRegistration message_handler_packet {
|
||||
Message::ID::ERTPacket,
|
||||
[this](Message* const p) {
|
||||
|
@ -58,27 +58,18 @@ static volatile uint32_t touch_phase { 0 };
|
||||
* Noise will only occur when the panel is being touched. Not ideal, but
|
||||
* an acceptable improvement.
|
||||
*/
|
||||
static std::array<portapack::IO::TouchPinsConfig, 11> touch_pins_configs {
|
||||
static std::array<portapack::IO::TouchPinsConfig, 3> touch_pins_configs {
|
||||
/* State machine will pause here until touch is detected. */
|
||||
portapack::IO::TouchPinsConfig::WaitTouch,
|
||||
|
||||
portapack::IO::TouchPinsConfig::SensePressure,
|
||||
portapack::IO::TouchPinsConfig::SenseX,
|
||||
portapack::IO::TouchPinsConfig::SenseY,
|
||||
portapack::IO::TouchPinsConfig::SenseX,
|
||||
portapack::IO::TouchPinsConfig::SenseY,
|
||||
portapack::IO::TouchPinsConfig::SensePressure,
|
||||
portapack::IO::TouchPinsConfig::SenseX,
|
||||
portapack::IO::TouchPinsConfig::SenseY,
|
||||
portapack::IO::TouchPinsConfig::SenseX,
|
||||
portapack::IO::TouchPinsConfig::SenseY,
|
||||
};
|
||||
|
||||
static touch::Frame temp_frame;
|
||||
static touch::Frame touch_frame;
|
||||
|
||||
static uint32_t touch_debounce = 0;
|
||||
static uint32_t touch_debounce_mask = (1U << 1) - 1;
|
||||
static uint32_t touch_debounce_mask = (1U << 4) - 1;
|
||||
static bool touch_detected = false;
|
||||
static bool touch_cycle = false;
|
||||
|
||||
@ -87,20 +78,20 @@ static bool touch_update() {
|
||||
const auto current_phase = touch_pins_configs[touch_phase];
|
||||
|
||||
switch(current_phase) {
|
||||
case portapack::IO::TouchPinsConfig::WaitTouch:
|
||||
case portapack::IO::TouchPinsConfig::SensePressure:
|
||||
{
|
||||
/* Debounce touches. */
|
||||
const bool touch_raw = (samples.yp < touch::touch_threshold) && (samples.yn < touch::touch_threshold);
|
||||
const auto z1 = samples.xp - samples.xn;
|
||||
const auto z2 = samples.yp - samples.yn;
|
||||
const auto touch_raw = (z1 > touch::touch_threshold) || (z2 > touch::touch_threshold);
|
||||
touch_debounce = (touch_debounce << 1) | (touch_raw ? 1U : 0U);
|
||||
touch_detected = ((touch_debounce & touch_debounce_mask) == touch_debounce_mask);
|
||||
if( !touch_detected && !touch_cycle ) {
|
||||
temp_frame.pressure = { };
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case portapack::IO::TouchPinsConfig::SensePressure:
|
||||
} else {
|
||||
temp_frame.pressure += samples;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case portapack::IO::TouchPinsConfig::SenseX:
|
||||
|
@ -116,11 +116,21 @@ void ReceiverModel::set_vga(int32_t v_db) {
|
||||
}
|
||||
|
||||
uint32_t ReceiverModel::sampling_rate() const {
|
||||
return baseband_configuration.sampling_rate;
|
||||
return sampling_rate_;
|
||||
}
|
||||
|
||||
uint32_t ReceiverModel::modulation() const {
|
||||
return baseband_configuration.mode;
|
||||
void ReceiverModel::set_sampling_rate(uint32_t v) {
|
||||
sampling_rate_ = v;
|
||||
update_sampling_rate();
|
||||
}
|
||||
|
||||
ReceiverModel::Mode ReceiverModel::modulation() const {
|
||||
return mode_;
|
||||
}
|
||||
|
||||
void ReceiverModel::set_modulation(const Mode v) {
|
||||
mode_ = v;
|
||||
update_modulation();
|
||||
}
|
||||
|
||||
volume_t ReceiverModel::headphone_volume() const {
|
||||
@ -134,7 +144,7 @@ void ReceiverModel::set_headphone_volume(volume_t v) {
|
||||
|
||||
uint32_t ReceiverModel::baseband_oversampling() const {
|
||||
// TODO: Rename decimation_factor.
|
||||
return baseband_configuration.decimation_factor;
|
||||
return decimation_factor_;
|
||||
}
|
||||
|
||||
void ReceiverModel::enable() {
|
||||
@ -146,8 +156,8 @@ void ReceiverModel::enable() {
|
||||
update_lna();
|
||||
update_vga();
|
||||
update_baseband_bandwidth();
|
||||
update_baseband_configuration();
|
||||
update_modulation_configuration();
|
||||
update_sampling_rate();
|
||||
update_modulation();
|
||||
update_headphone_volume();
|
||||
}
|
||||
|
||||
@ -161,7 +171,7 @@ void ReceiverModel::disable() {
|
||||
}
|
||||
|
||||
int32_t ReceiverModel::tuning_offset() {
|
||||
if( (baseband_configuration.mode == 4) || (baseband_configuration.mode == 10) ) {
|
||||
if( (modulation() == Mode::SpectrumAnalysis) ) {
|
||||
return 0;
|
||||
} else {
|
||||
return -(sampling_rate() / 4);
|
||||
@ -192,33 +202,28 @@ void ReceiverModel::update_vga() {
|
||||
radio::set_vga_gain(vga_gain_db_);
|
||||
}
|
||||
|
||||
void ReceiverModel::set_baseband_configuration(const BasebandConfiguration config) {
|
||||
baseband_configuration = config;
|
||||
update_baseband_configuration();
|
||||
}
|
||||
|
||||
void ReceiverModel::set_am_configuration(const size_t n) {
|
||||
if( n < am_configs.size() ) {
|
||||
am_config_index = n;
|
||||
update_modulation_configuration();
|
||||
update_modulation();
|
||||
}
|
||||
}
|
||||
|
||||
void ReceiverModel::set_nbfm_configuration(const size_t n) {
|
||||
if( n < nbfm_configs.size() ) {
|
||||
nbfm_config_index = n;
|
||||
update_modulation_configuration();
|
||||
update_modulation();
|
||||
}
|
||||
}
|
||||
|
||||
void ReceiverModel::set_wfm_configuration(const size_t n) {
|
||||
if( n < wfm_configs.size() ) {
|
||||
wfm_config_index = n;
|
||||
update_modulation_configuration();
|
||||
update_modulation();
|
||||
}
|
||||
}
|
||||
|
||||
void ReceiverModel::update_baseband_configuration() {
|
||||
void ReceiverModel::update_sampling_rate() {
|
||||
// TODO: Move more low-level radio control stuff to M4. It'll enable tighter
|
||||
// synchronization for things like wideband (sweeping) spectrum analysis, and
|
||||
// protocols that need quick RX/TX turn-around.
|
||||
@ -236,8 +241,8 @@ void ReceiverModel::update_headphone_volume() {
|
||||
audio::headphone::set_volume(headphone_volume_);
|
||||
}
|
||||
|
||||
void ReceiverModel::update_modulation_configuration() {
|
||||
switch(static_cast<Mode>(modulation())) {
|
||||
void ReceiverModel::update_modulation() {
|
||||
switch(modulation()) {
|
||||
default:
|
||||
case Mode::AMAudio:
|
||||
update_am_configuration();
|
||||
|
@ -53,13 +53,11 @@ struct BasebandConfiguration {
|
||||
|
||||
class ReceiverModel {
|
||||
public:
|
||||
enum class Mode : int32_t {
|
||||
enum class Mode {
|
||||
AMAudio = 0,
|
||||
NarrowbandFMAudio = 1,
|
||||
WidebandFMAudio = 2,
|
||||
SpectrumAnalysis = 4,
|
||||
Capture = 7,
|
||||
CloseCall = 10,
|
||||
SpectrumAnalysis = 3,
|
||||
};
|
||||
|
||||
rf::Frequency tuning_frequency() const;
|
||||
@ -84,8 +82,10 @@ public:
|
||||
void set_vga(int32_t v_db);
|
||||
|
||||
uint32_t sampling_rate() const;
|
||||
void set_sampling_rate(uint32_t v);
|
||||
|
||||
uint32_t modulation() const;
|
||||
Mode modulation() const;
|
||||
void set_modulation(Mode v);
|
||||
|
||||
volume_t headphone_volume() const;
|
||||
void set_headphone_volume(volume_t v);
|
||||
@ -95,8 +95,6 @@ public:
|
||||
void enable();
|
||||
void disable();
|
||||
|
||||
void set_baseband_configuration(const BasebandConfiguration config);
|
||||
|
||||
size_t am_configuration() const;
|
||||
void set_am_configuration(const size_t n);
|
||||
|
||||
@ -114,11 +112,9 @@ private:
|
||||
int32_t lna_gain_db_ { 32 };
|
||||
uint32_t baseband_bandwidth_ { max2837::filter::bandwidth_minimum };
|
||||
int32_t vga_gain_db_ { 32 };
|
||||
BasebandConfiguration baseband_configuration {
|
||||
.mode = 1, /* TODO: Enum! */
|
||||
.sampling_rate = 3072000,
|
||||
.decimation_factor = 1,
|
||||
};
|
||||
Mode mode_ { Mode::NarrowbandFMAudio };
|
||||
uint32_t sampling_rate_ { 3072000 };
|
||||
size_t decimation_factor_ { 1 };
|
||||
size_t am_config_index = 0;
|
||||
size_t nbfm_config_index = 0;
|
||||
size_t wfm_config_index = 0;
|
||||
@ -132,10 +128,10 @@ private:
|
||||
void update_lna();
|
||||
void update_baseband_bandwidth();
|
||||
void update_vga();
|
||||
void update_baseband_configuration();
|
||||
void update_sampling_rate();
|
||||
void update_headphone_volume();
|
||||
|
||||
void update_modulation_configuration();
|
||||
void update_modulation();
|
||||
void update_am_configuration();
|
||||
void update_nbfm_configuration();
|
||||
void update_wfm_configuration();
|
||||
|
@ -21,15 +21,14 @@
|
||||
|
||||
#include "touch.hpp"
|
||||
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
using namespace portapack;
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace touch {
|
||||
|
||||
struct Metrics {
|
||||
const float x;
|
||||
const float y;
|
||||
const float r;
|
||||
};
|
||||
|
||||
static Metrics calculate_metrics(const Frame& frame) {
|
||||
Metrics calculate_metrics(const Frame& frame) {
|
||||
/* TODO: Yikes! M0 doesn't have floating point, so this code is
|
||||
* expensive! On the other hand, it seems to be working well (and
|
||||
* fast *enough*?), so maybe leave it alone at least for now.
|
||||
@ -38,14 +37,14 @@ static Metrics calculate_metrics(const Frame& frame) {
|
||||
const auto x_max = frame.x.xp;
|
||||
const auto x_min = frame.x.xn;
|
||||
const auto x_range = x_max - x_min;
|
||||
const auto x_position = (frame.x.yp + frame.x.yn) / 2;
|
||||
const float x_norm = float(x_position - x_min) / x_range;
|
||||
const float x_position = (frame.x.yp + frame.x.yn) * 0.5f;
|
||||
const float x_norm = (x_position - x_min) / x_range;
|
||||
|
||||
const auto y_max = frame.y.yn;
|
||||
const auto y_min = frame.y.yp;
|
||||
const auto y_range = y_max - y_min;
|
||||
const auto y_position = (frame.y.xp + frame.y.xn) / 2;
|
||||
const float y_norm = float(y_position - y_min) / y_range;
|
||||
const float y_position = (frame.y.xp + frame.y.xn) * 0.5f;
|
||||
const float y_norm = (y_position - y_min) / y_range;
|
||||
|
||||
const auto z_max = frame.pressure.yp;
|
||||
const auto z_min = frame.pressure.xn;
|
||||
@ -66,6 +65,28 @@ static Metrics calculate_metrics(const Frame& frame) {
|
||||
};
|
||||
}
|
||||
|
||||
ui::Point Calibration::translate(const DigitizerPoint& p) const {
|
||||
static constexpr range_t<int32_t> x_range { 0, 240 - 1 };
|
||||
static constexpr range_t<int32_t> y_range { 0, 320 - 1 };
|
||||
|
||||
const int32_t x = (a * p.x + b * p.y + c) / k;
|
||||
const int32_t y = (d * p.x + e * p.y + f) / k;
|
||||
const auto x_clipped = x_range.clip(x);
|
||||
const auto y_clipped = y_range.clip(y);
|
||||
return {
|
||||
static_cast<ui::Coord>(x_clipped),
|
||||
static_cast<ui::Coord>(y_clipped)
|
||||
};
|
||||
}
|
||||
|
||||
const Calibration default_calibration() {
|
||||
/* Values derived from one PortaPack H1 unit. */
|
||||
return {
|
||||
{ { { 256, 731 }, { 880, 432 }, { 568, 146 } } },
|
||||
{ { { 32, 48 }, { 208, 168 }, { 120, 288 } } }
|
||||
};
|
||||
};
|
||||
|
||||
void Manager::feed(const Frame& frame) {
|
||||
// touch_debounce.feed(touch_raw);
|
||||
const auto touch_raw = frame.touch;
|
||||
@ -81,10 +102,8 @@ void Manager::feed(const Frame& frame) {
|
||||
// TODO: Add touch pressure hysteresis?
|
||||
touch_pressure = (metrics.r < r_touch_threshold);
|
||||
if( touch_pressure ) {
|
||||
const float x = width_pixels * (metrics.x - calib_x_low) / calib_x_range;
|
||||
filter_x.feed(x);
|
||||
const float y = height_pixels * (calib_y_high - metrics.y) / calib_y_range;
|
||||
filter_y.feed(y);
|
||||
filter_x.feed(metrics.x * 1024);
|
||||
filter_y.feed(metrics.y * 1024);
|
||||
}
|
||||
} else {
|
||||
filter_x.reset();
|
||||
@ -116,4 +135,8 @@ void Manager::feed(const Frame& frame) {
|
||||
}
|
||||
}
|
||||
|
||||
ui::Point Manager::filtered_point() const {
|
||||
return persistent_memory::touch_calibration().translate({ filter_x.value(), filter_y.value() });
|
||||
}
|
||||
|
||||
} /* namespace touch */
|
||||
|
@ -38,7 +38,7 @@ using sample_t = uint16_t;
|
||||
|
||||
constexpr sample_t sample_max = 1023;
|
||||
|
||||
constexpr sample_t touch_threshold = sample_max * 0.5f;
|
||||
constexpr sample_t touch_threshold = sample_max / 5;
|
||||
|
||||
struct Samples {
|
||||
sample_t xp;
|
||||
@ -106,6 +106,51 @@ struct Frame {
|
||||
bool touch { false };
|
||||
};
|
||||
|
||||
struct Metrics {
|
||||
const float x;
|
||||
const float y;
|
||||
const float r;
|
||||
};
|
||||
|
||||
Metrics calculate_metrics(const Frame& frame);
|
||||
|
||||
struct DigitizerPoint {
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
};
|
||||
|
||||
struct Calibration {
|
||||
/* Touch screen calibration matrix, based on article by Carlos E. Vidales:
|
||||
* http://www.embedded.com/design/system-integration/4023968/How-To-Calibrate-Touch-Screens
|
||||
*/
|
||||
|
||||
constexpr Calibration(
|
||||
const std::array<DigitizerPoint, 3>& s,
|
||||
const std::array<ui::Point, 3>& d
|
||||
) : k { (s[0].x - s[2].x) * (s[1].y - s[2].y) - (s[1].x - s[2].x) * (s[0].y - s[2].y) },
|
||||
a { (d[0].x - d[2].x) * (s[1].y - s[2].y) - (d[1].x - d[2].x) * (s[0].y - s[2].y) },
|
||||
b { (s[0].x - s[2].x) * (d[1].x - d[2].x) - (d[0].x - d[2].x) * (s[1].x - s[2].x) },
|
||||
c { s[0].y * (s[2].x * d[1].x - s[1].x * d[2].x) + s[1].y * (s[0].x * d[2].x - s[2].x * d[0].x) + s[2].y * (s[1].x * d[0].x - s[0].x * d[1].x) },
|
||||
d { (d[0].y - d[2].y) * (s[1].y - s[2].y) - (d[1].y - d[2].y) * (s[0].y - s[2].y) },
|
||||
e { (s[0].x - s[2].x) * (d[1].y - d[2].y) - (d[0].y - d[2].y) * (s[1].x - s[2].x) },
|
||||
f { s[0].y * (s[2].x * d[1].y - s[1].x * d[2].y) + s[1].y * (s[0].x * d[2].y - s[2].x * d[0].y) + s[2].y * (s[1].x * d[0].y - s[0].x * d[1].y) }
|
||||
{
|
||||
}
|
||||
|
||||
ui::Point translate(const DigitizerPoint& p) const;
|
||||
|
||||
private:
|
||||
int32_t k;
|
||||
int32_t a;
|
||||
int32_t b;
|
||||
int32_t c;
|
||||
int32_t d;
|
||||
int32_t e;
|
||||
int32_t f;
|
||||
};
|
||||
|
||||
const Calibration default_calibration();
|
||||
|
||||
template<size_t N>
|
||||
class Filter {
|
||||
public:
|
||||
@ -173,20 +218,9 @@ private:
|
||||
TouchDetected,
|
||||
};
|
||||
|
||||
static constexpr uint32_t width_pixels = 240;
|
||||
static constexpr uint32_t height_pixels = 320;
|
||||
|
||||
static constexpr float r_touch_threshold = 0x1000;
|
||||
static constexpr size_t touch_count_threshold { 4 };
|
||||
static constexpr uint32_t touch_stable_bound { 4 };
|
||||
|
||||
static constexpr float calib_x_low = 0.15f;
|
||||
static constexpr float calib_x_high = 0.98f;
|
||||
static constexpr float calib_x_range = calib_x_high - calib_x_low;
|
||||
|
||||
static constexpr float calib_y_low = 0.04f;
|
||||
static constexpr float calib_y_high = 0.80f; //91
|
||||
static constexpr float calib_y_range = calib_y_high - calib_y_low;
|
||||
static constexpr float r_touch_threshold = 640;
|
||||
static constexpr size_t touch_count_threshold { 3 };
|
||||
static constexpr uint32_t touch_stable_bound { 8 };
|
||||
|
||||
// Ensure filter length is equal or less than touch_count_threshold,
|
||||
// or coordinates from the last touch will be in the initial averages.
|
||||
@ -202,12 +236,7 @@ private:
|
||||
&& filter_y.stable(touch_stable_bound);
|
||||
}
|
||||
|
||||
ui::Point filtered_point() const {
|
||||
return {
|
||||
static_cast<ui::Coord>(filter_x.value()),
|
||||
static_cast<ui::Coord>(filter_y.value())
|
||||
};
|
||||
}
|
||||
ui::Point filtered_point() const;
|
||||
|
||||
void touch_started() {
|
||||
fire_event(ui::TouchEvent::Type::Start);
|
||||
|
@ -181,7 +181,7 @@ TPMSAppView::TPMSAppView(NavigationView&) {
|
||||
sampling_rate,
|
||||
baseband_bandwidth,
|
||||
rf::Direction::Receive,
|
||||
false,
|
||||
receiver_model.rf_amp(),
|
||||
static_cast<int8_t>(receiver_model.lna()),
|
||||
static_cast<int8_t>(receiver_model.vga()),
|
||||
1,
|
||||
|
@ -119,7 +119,7 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr ui::Dim header_height = 2 * 16;
|
||||
static constexpr ui::Dim header_height = 1 * 16;
|
||||
|
||||
RSSI rssi {
|
||||
{ 21 * 8, 0, 6 * 8, 4 },
|
||||
|
@ -48,8 +48,21 @@ using namespace portapack;
|
||||
namespace ui {
|
||||
|
||||
void AboutView::on_show() {
|
||||
about_radio_config.tuning_frequency = 92200000; // 92.2MHz, change !
|
||||
radio::enable(about_radio_config);
|
||||
transmitter_model.set_tuning_frequency(92200000);
|
||||
transmitter_model.set_baseband_configuration({
|
||||
.mode = 0,
|
||||
.sampling_rate = 1536000,
|
||||
.decimation_factor = 1,
|
||||
});
|
||||
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();
|
||||
|
||||
baseband::set_audiotx_data(
|
||||
0
|
||||
);
|
||||
|
||||
//audio::headphone::set_volume(volume_t::decibel(0 - 99) + audio::headphone::volume_range().max);
|
||||
}
|
||||
@ -352,6 +365,8 @@ AboutView::AboutView(
|
||||
{
|
||||
uint8_t p, c;
|
||||
|
||||
baseband::run_image(portapack::spi_flash::image_tag_audio_tx);
|
||||
|
||||
add_children({ {
|
||||
&text_title,
|
||||
&text_firmware,
|
||||
@ -394,7 +409,8 @@ AboutView::AboutView(
|
||||
}
|
||||
|
||||
AboutView::~AboutView() {
|
||||
radio::disable();
|
||||
transmitter_model.disable();
|
||||
baseband::shutdown();
|
||||
}
|
||||
|
||||
void AboutView::focus() {
|
||||
|
@ -48,17 +48,6 @@ private:
|
||||
void draw_demoglyph(ui::Point p, char ch, ui::Color * pal);
|
||||
uint16_t debug_cnt = 0;
|
||||
|
||||
radio::Configuration about_radio_config = {
|
||||
0,
|
||||
1536000, // ?
|
||||
2500000, // ?
|
||||
rf::Direction::Transmit,
|
||||
true,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
};
|
||||
|
||||
typedef struct ymreg_t {
|
||||
uint8_t value;
|
||||
uint8_t cnt;
|
||||
@ -170,8 +159,6 @@ private:
|
||||
FIFODataMessage datamessage;
|
||||
const auto message = static_cast<const FIFOSignalMessage*>(p);
|
||||
if (message->signaltype == 1) {
|
||||
//debug_cnt++;
|
||||
//if (debug_cnt == 250) for(;;) {}
|
||||
this->render_audio();
|
||||
datamessage.data = ym_buffer;
|
||||
EventDispatcher::send_message(datamessage);
|
||||
|
@ -247,7 +247,6 @@ void LCRView::start_tx(const bool scan) {
|
||||
afsk_format = 0;
|
||||
}
|
||||
|
||||
|
||||
transmitter_model.set_tuning_frequency(portapack::persistent_memory::tuned_frequency());
|
||||
transmitter_model.set_baseband_configuration({
|
||||
.mode = 0,
|
||||
@ -281,7 +280,7 @@ LCRView::LCRView(NavigationView& nav) {
|
||||
|
||||
baseband::run_image(portapack::spi_flash::image_tag_afsk);
|
||||
|
||||
strcpy(rgsb, &scan_list[options_scanlist.selected_index()].addresses[0]);
|
||||
strcpy(rgsb, &scan_list[0].addresses[0]);
|
||||
|
||||
add_children({ {
|
||||
&text_recap,
|
||||
@ -298,6 +297,8 @@ LCRView::LCRView(NavigationView& nav) {
|
||||
&button_clear
|
||||
} });
|
||||
|
||||
options_scanlist.set_selected_index(0);
|
||||
|
||||
const auto button_setam_fn = [this, &nav](Button& button) {
|
||||
this->on_button_setam(nav, button);
|
||||
};
|
||||
|
@ -44,7 +44,7 @@ private:
|
||||
const char * addresses;
|
||||
};
|
||||
|
||||
scan_list_t scan_list[2] = {
|
||||
const scan_list_t scan_list[2] = {
|
||||
{ 36, &RGSB_list_Lille[0][0] },
|
||||
{ 23, &RGSB_list_Reims[0][0] }
|
||||
};
|
||||
@ -80,9 +80,8 @@ private:
|
||||
|
||||
tx_modes tx_mode = IDLE;
|
||||
bool abort_scan = false;
|
||||
uint8_t scan_count;
|
||||
uint8_t scan_count, scan_index;
|
||||
double scan_progress;
|
||||
unsigned int scan_index;
|
||||
char litteral[5][8] = { { 0 }, { 0 }, { 0 }, { 0 }, { 0 } };
|
||||
char rgsb[5] = { 0 };
|
||||
char lcr_message[512];
|
||||
@ -97,20 +96,6 @@ private:
|
||||
void on_txdone(int n);
|
||||
void on_button_setam(NavigationView& nav, Button& button);
|
||||
|
||||
radio::Configuration lcr_radio_config = {
|
||||
0,
|
||||
2280000,
|
||||
2500000, // ?
|
||||
rf::Direction::Transmit,
|
||||
true,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
};
|
||||
|
||||
// 2: 94 ?
|
||||
// 9: 85 ?
|
||||
|
||||
const Style style_val {
|
||||
.font = font::fixed_8x16,
|
||||
.background = Color::green(),
|
||||
|
@ -21,6 +21,8 @@
|
||||
|
||||
#include "ui_setup.hpp"
|
||||
|
||||
#include "ui_touch_calibration.hpp"
|
||||
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
#include "lpc43xx_cpp.hpp"
|
||||
using namespace lpc43xx;
|
||||
@ -32,6 +34,7 @@ using namespace portapack;
|
||||
#include "string_format.hpp"
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
#include "ui_font_fixed_8x16.hpp"
|
||||
#include "cpld_update.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
@ -172,18 +175,6 @@ void AntennaBiasSetupView::focus() {
|
||||
button_done.focus();
|
||||
}
|
||||
|
||||
void SetTouchCalibView::focus() {
|
||||
button_ok.focus();
|
||||
}
|
||||
|
||||
bool SetTouchCalibView::on_touch(const TouchEvent event) {
|
||||
if (event.type == ui::TouchEvent::Type::Start) {
|
||||
text_debugx.set(to_string_dec_uint(round(event.point.x), 4));
|
||||
text_debugy.set(to_string_dec_uint(round(event.point.y), 4));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
SetPlayDeadView::SetPlayDeadView(NavigationView& nav) {
|
||||
add_children({{
|
||||
&text_sequence,
|
||||
@ -445,7 +436,7 @@ SetupMenuView::SetupMenuView(NavigationView& nav) {
|
||||
{ "Date/Time", ui::Color::white(), [&nav](){ nav.push<SetDateTimeView>(); } },
|
||||
{ "Frequency correction", ui::Color::white(), [&nav](){ nav.push<SetFrequencyCorrectionView>(); } },
|
||||
{ "Antenna Bias Voltage", ui::Color::white(), [&nav](){ nav.push<AntennaBiasSetupView>(); } },
|
||||
{ "Touch screen", ui::Color::white(), [&nav](){ nav.push<NotImplementedView>(); } },
|
||||
{ "Touch screen", ui::Color::white(), [&nav](){ nav.push<TouchCalibrationView>(); } },
|
||||
{ "Play dead", ui::Color::red(), [&nav](){ nav.push<SetPlayDeadView>(); } }
|
||||
} });
|
||||
on_left = [&nav](){ nav.pop(); };
|
||||
|
206
firmware/application/ui_touch_calibration.cpp
Normal file
206
firmware/application/ui_touch_calibration.cpp
Normal file
@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "ui_touch_calibration.hpp"
|
||||
|
||||
#include "irq_controls.hpp"
|
||||
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
using namespace portapack;
|
||||
|
||||
namespace ui {
|
||||
|
||||
TouchCalibrationView::TouchCalibrationView(
|
||||
NavigationView& nav
|
||||
) : nav { nav },
|
||||
calibration { touch::default_calibration() }
|
||||
{
|
||||
add_children({ {
|
||||
&image_calibrate_0,
|
||||
&image_calibrate_1,
|
||||
&image_calibrate_2,
|
||||
&image_verify_0,
|
||||
&image_verify_1,
|
||||
&image_verify_2,
|
||||
&label_calibrate,
|
||||
&label_verify,
|
||||
&label_success,
|
||||
&label_failure,
|
||||
&button_cancel,
|
||||
&button_ok,
|
||||
} });
|
||||
|
||||
button_cancel.on_select = [this](Button&){ this->on_cancel(); };
|
||||
button_ok.on_select = [this](Button&){ this->on_ok(); };
|
||||
|
||||
set_phase(Phase::Calibrate0);
|
||||
}
|
||||
|
||||
void TouchCalibrationView::focus() {
|
||||
button_cancel.focus();
|
||||
}
|
||||
|
||||
void TouchCalibrationView::update_target() {
|
||||
const auto phase_calibrate = (phase == Phase::Calibrate0) || (phase == Phase::Calibrate1) || (phase == Phase::Calibrate2);
|
||||
const auto phase_verify = (phase == Phase::Verify0) || (phase == Phase::Verify1) || (phase == Phase::Verify2);
|
||||
|
||||
image_calibrate_0.hidden(phase != Phase::Calibrate0);
|
||||
image_calibrate_1.hidden(phase != Phase::Calibrate1);
|
||||
image_calibrate_2.hidden(phase != Phase::Calibrate2);
|
||||
|
||||
image_verify_0.hidden(phase != Phase::Verify0);
|
||||
image_verify_1.hidden(phase != Phase::Verify1);
|
||||
image_verify_2.hidden(phase != Phase::Verify2);
|
||||
|
||||
label_calibrate.hidden(!phase_calibrate);
|
||||
label_verify.hidden(!phase_verify);
|
||||
label_success.hidden(phase != Phase::Success);
|
||||
label_failure.hidden(phase != Phase::Failure);
|
||||
|
||||
button_ok.hidden((phase != Phase::Success) && (phase != Phase::Failure));
|
||||
|
||||
/* TODO: Such a hack to get around a poor repaint implementation! This "technique"
|
||||
* occurs in other places...
|
||||
*/
|
||||
set_dirty();
|
||||
}
|
||||
|
||||
void TouchCalibrationView::set_phase(const Phase value) {
|
||||
if( value != phase ) {
|
||||
phase = value;
|
||||
update_target();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t TouchCalibrationView::distance_squared(const Point& touch_point, const Image& target) {
|
||||
const auto target_point = target.screen_rect().center();
|
||||
const int32_t dx = target_point.x - touch_point.x;
|
||||
const int32_t dy = target_point.y - touch_point.y;
|
||||
const uint32_t dx2 = dx * dx;
|
||||
const uint32_t dy2 = dy * dy;
|
||||
return dx2 + dy2;
|
||||
}
|
||||
|
||||
void TouchCalibrationView::touch_complete() {
|
||||
auto next_phase = static_cast<Phase>(toUType(phase) + 1);
|
||||
|
||||
switch(phase) {
|
||||
case Phase::Calibrate0:
|
||||
case Phase::Verify0:
|
||||
digitizer_points[0] = average;
|
||||
break;
|
||||
|
||||
case Phase::Calibrate1:
|
||||
case Phase::Verify1:
|
||||
digitizer_points[1] = average;
|
||||
break;
|
||||
|
||||
case Phase::Calibrate2:
|
||||
case Phase::Verify2:
|
||||
digitizer_points[2] = average;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if( phase == Phase::Calibrate2 ) {
|
||||
const std::array<Point, 3> display_points { {
|
||||
image_calibrate_0.screen_rect().center(),
|
||||
image_calibrate_1.screen_rect().center(),
|
||||
image_calibrate_2.screen_rect().center(),
|
||||
} };
|
||||
|
||||
calibration = { digitizer_points, display_points };
|
||||
}
|
||||
|
||||
if( phase == Phase::Verify2 ) {
|
||||
const auto calibrated_0 = calibration.translate(digitizer_points[0]);
|
||||
const auto d_sq_0 = distance_squared(calibrated_0, image_verify_0);
|
||||
|
||||
const auto calibrated_1 = calibration.translate(digitizer_points[1]);
|
||||
const auto d_sq_1 = distance_squared(calibrated_1, image_verify_1);
|
||||
|
||||
const auto calibrated_2 = calibration.translate(digitizer_points[2]);
|
||||
const auto d_sq_2 = distance_squared(calibrated_2, image_verify_2);
|
||||
|
||||
if( (d_sq_0 < verify_d_sq_max) && (d_sq_1 < verify_d_sq_max) && (d_sq_2 < verify_d_sq_max) ) {
|
||||
next_phase = Phase::Success;
|
||||
} else {
|
||||
next_phase = Phase::Failure;
|
||||
}
|
||||
}
|
||||
|
||||
set_phase(next_phase);
|
||||
}
|
||||
|
||||
void TouchCalibrationView::on_ok() {
|
||||
if( phase == Phase::Success ) {
|
||||
persistent_memory::set_touch_calibration(calibration);
|
||||
nav.pop();
|
||||
}
|
||||
if( phase == Phase::Failure ) {
|
||||
set_phase(Phase::Calibrate0);
|
||||
}
|
||||
}
|
||||
|
||||
void TouchCalibrationView::on_cancel() {
|
||||
nav.pop();
|
||||
}
|
||||
|
||||
void TouchCalibrationView::on_frame_sync() {
|
||||
switch(phase) {
|
||||
case Phase::Calibrate0:
|
||||
case Phase::Calibrate1:
|
||||
case Phase::Calibrate2:
|
||||
case Phase::Verify0:
|
||||
case Phase::Verify1:
|
||||
case Phase::Verify2:
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
const auto frame = get_touch_frame();
|
||||
const auto metrics = touch::calculate_metrics(frame);
|
||||
const auto x = metrics.x * 1024;
|
||||
const auto y = metrics.y * 1024;
|
||||
|
||||
if( metrics.r < 640.0f ) {
|
||||
if( samples_count > 0 ) {
|
||||
average.x = ((average.x * 7) + x) / 8;
|
||||
average.y = ((average.y * 7) + y) / 8;
|
||||
} else {
|
||||
average.x = x;
|
||||
average.y = y;
|
||||
}
|
||||
|
||||
samples_count += 1;
|
||||
} else {
|
||||
if( samples_count >= samples_limit ) {
|
||||
touch_complete();
|
||||
}
|
||||
samples_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
158
firmware/application/ui_touch_calibration.hpp
Normal file
158
firmware/application/ui_touch_calibration.hpp
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __UI_TOUCH_CALIBRATION_HPP__
|
||||
#define __UI_TOUCH_CALIBRATION_HPP__
|
||||
|
||||
#include "ui_widget.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "touch.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
class TouchCalibrationView : public View {
|
||||
public:
|
||||
TouchCalibrationView(NavigationView& nav);
|
||||
|
||||
void focus() override;
|
||||
|
||||
private:
|
||||
enum class Phase {
|
||||
Init,
|
||||
Calibrate0,
|
||||
Calibrate1,
|
||||
Calibrate2,
|
||||
Verify0,
|
||||
Verify1,
|
||||
Verify2,
|
||||
Success,
|
||||
Failure,
|
||||
};
|
||||
|
||||
NavigationView& nav;
|
||||
Phase phase { Phase::Init };
|
||||
|
||||
void update_target();
|
||||
|
||||
void set_phase(const Phase value);
|
||||
|
||||
uint32_t distance_squared(const Point& touch_point, const Image& target);
|
||||
|
||||
void touch_complete();
|
||||
void on_ok();
|
||||
void on_cancel();
|
||||
|
||||
const uint32_t samples_limit { 40 };
|
||||
const uint32_t verify_d_sq_max = 10 * 10;
|
||||
|
||||
uint32_t samples_count { 0 };
|
||||
|
||||
touch::DigitizerPoint average;
|
||||
|
||||
std::array<touch::DigitizerPoint, 3> digitizer_points;
|
||||
|
||||
touch::Calibration calibration;
|
||||
|
||||
Image image_calibrate_0 {
|
||||
{ 32 - 16, 32 - 16, 32, 32 },
|
||||
&bitmap_target_calibrate,
|
||||
Color::white(),
|
||||
Color::black()
|
||||
};
|
||||
|
||||
Image image_calibrate_1 {
|
||||
{ 240 - 32 - 16, (320 - 16) / 2 - 16, 32, 32 },
|
||||
&bitmap_target_calibrate,
|
||||
Color::white(),
|
||||
Color::black()
|
||||
};
|
||||
|
||||
Image image_calibrate_2 {
|
||||
{ 240 / 2 - 16, (320 - 16) - 32 - 16, 32, 32 },
|
||||
&bitmap_target_calibrate,
|
||||
Color::white(),
|
||||
Color::black()
|
||||
};
|
||||
|
||||
Image image_verify_0 {
|
||||
{ 32 - 16, 32 - 16, 32, 32 },
|
||||
&bitmap_target_verify,
|
||||
Color::white(),
|
||||
Color::black()
|
||||
};
|
||||
|
||||
Image image_verify_1 {
|
||||
{ 240 - 32 - 16, (320 - 16) / 2 - 16, 32, 32 },
|
||||
&bitmap_target_verify,
|
||||
Color::white(),
|
||||
Color::black()
|
||||
};
|
||||
|
||||
Image image_verify_2 {
|
||||
{ 240 / 2 - 16, (320 - 16) - 32 - 16, 32, 32 },
|
||||
&bitmap_target_verify,
|
||||
Color::white(),
|
||||
Color::black()
|
||||
};
|
||||
|
||||
Text label_calibrate {
|
||||
{ 16, 5 * 16, 26 * 8, 1 * 16 },
|
||||
"Touch targets to calibrate"
|
||||
};
|
||||
|
||||
Text label_verify {
|
||||
{ 28, 5 * 16, 23 * 8, 1 * 16 },
|
||||
"Touch targets to verify"
|
||||
};
|
||||
|
||||
Text label_success {
|
||||
{ 32, 5 * 16, 22 * 8, 1 * 16 },
|
||||
"Apply new calibration?"
|
||||
};
|
||||
|
||||
Text label_failure {
|
||||
{ 16, 5 * 16, 26 * 8, 1 * 16 },
|
||||
"Calibration failed. Retry?"
|
||||
};
|
||||
|
||||
Button button_cancel {
|
||||
{ 40, 200, 64, 24 },
|
||||
"Cancel"
|
||||
};
|
||||
|
||||
Button button_ok {
|
||||
{ 136, 200, 64, 24 },
|
||||
"OK"
|
||||
};
|
||||
|
||||
void on_frame_sync();
|
||||
|
||||
MessageHandlerRegistration message_handler_frame_sync {
|
||||
Message::ID::DisplayFrameSync,
|
||||
[this](const Message* const) {
|
||||
this->on_frame_sync();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
#endif/*__UI_TOUCH_CALIBRATION_HPP__*/
|
@ -29,7 +29,7 @@ enable_language(C CXX ASM)
|
||||
project(baseband_shared)
|
||||
|
||||
# Compiler options here.
|
||||
set(USE_OPT "-O3 -falign-functions=16 -fno-math-errno --specs=nano.specs")
|
||||
set(USE_OPT "-O3 -g -falign-functions=16 -fno-math-errno --specs=nano.specs")
|
||||
|
||||
# C specific options here (added to USE_OPT).
|
||||
set(USE_COPT "-std=gnu99")
|
||||
@ -342,10 +342,10 @@ DeclareTargets(POOK ook)
|
||||
|
||||
### Audio transmit
|
||||
|
||||
#set(MODE_CPPSRC
|
||||
# proc_audiotx.cpp
|
||||
#)
|
||||
#DeclareTargets(PATX audio_tx)
|
||||
set(MODE_CPPSRC
|
||||
proc_audiotx.cpp
|
||||
)
|
||||
DeclareTargets(PATX audio_tx)
|
||||
|
||||
### AFSK
|
||||
|
||||
@ -361,13 +361,6 @@ DeclareTargets(PAFS afsk)
|
||||
#)
|
||||
#DeclareTargets(PEPR epar)
|
||||
|
||||
### Play audio
|
||||
|
||||
#set(MODE_CPPSRC
|
||||
# proc_playaudio.cpp
|
||||
#)
|
||||
#DeclareTargets(PPAU play_audio)
|
||||
|
||||
### Xylos
|
||||
|
||||
set(MODE_CPPSRC
|
||||
|
@ -119,8 +119,8 @@ void AFSKProcessor::execute(const buffer_c8_t& buffer) {
|
||||
}
|
||||
}
|
||||
|
||||
void AFSKProcessor::on_message(const Message* const p) {
|
||||
const auto message = *reinterpret_cast<const AFSKConfigureMessage*>(p);
|
||||
void AFSKProcessor::on_message(const Message* const msg) {
|
||||
const auto message = *reinterpret_cast<const AFSKConfigureMessage*>(msg);
|
||||
|
||||
if (message.id == Message::ID::AFSKConfigure) {
|
||||
afsk_samples_per_bit = message.samples_per_bit;
|
||||
|
@ -30,7 +30,7 @@ class AFSKProcessor : public BasebandProcessor {
|
||||
public:
|
||||
void execute(const buffer_c8_t& buffer) override;
|
||||
|
||||
void on_message(const Message* const p) override;
|
||||
void on_message(const Message* const msg) override;
|
||||
|
||||
private:
|
||||
bool configured = false;
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "baseband_processor.hpp"
|
||||
#include "baseband_thread.hpp"
|
||||
#include "rssi_thread.hpp"
|
||||
|
||||
#include "channel_decimator.hpp"
|
||||
#include "matched_filter.hpp"
|
||||
@ -51,6 +52,7 @@ private:
|
||||
static constexpr size_t baseband_fs = 2457600;
|
||||
|
||||
BasebandThread baseband_thread { baseband_fs, this, NORMALPRIO + 20, baseband::Direction::Receive };
|
||||
RSSIThread rssi_thread { NORMALPRIO + 10 };
|
||||
|
||||
std::array<complex16_t, 512> dst;
|
||||
const buffer_c16_t dst_buffer {
|
||||
|
@ -23,33 +23,69 @@
|
||||
#include "proc_audiotx.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
#include "sine_table.hpp"
|
||||
//#include "audio_output.hpp"
|
||||
#include "event_m4.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
void AudioTXProcessor::execute(const buffer_c8_t& buffer){
|
||||
|
||||
// This is called at 1536000/2048 = 750Hz
|
||||
|
||||
if (!configured) return;
|
||||
|
||||
ai = 0;
|
||||
for (size_t i = 0; i<buffer.count; i++) {
|
||||
sample = (sine_table_f32[(aphase & 0x03FF0000)>>18]*127); //(int8_t)lfsr(sample + i);
|
||||
|
||||
if (bc & 0x40)
|
||||
aphase += 60000;
|
||||
else
|
||||
aphase += 90000;
|
||||
//audio_fifo.out(&sample, 1);
|
||||
|
||||
//FM
|
||||
frq = sample * 1000;
|
||||
// Audio preview sample generation: 1536000/48000 = 32
|
||||
if (as >= 31) {
|
||||
as = 0;
|
||||
//audio_fifo.out(&sample, 1);
|
||||
//preview_audio_buffer.p[ai++] = sample << 8;
|
||||
|
||||
//if ((audio_fifo.len() < 1024) && (asked == false)) {
|
||||
// Ask application to fill up fifo
|
||||
sigmessage.signaltype = 1;
|
||||
shared_memory.application_queue.push(sigmessage);
|
||||
asked = true;
|
||||
//}
|
||||
} else {
|
||||
as++;
|
||||
}
|
||||
|
||||
|
||||
// FM
|
||||
frq = (int32_t)(sample) * 4 * 2000;
|
||||
|
||||
phase = (phase + frq);
|
||||
sphase = phase + (256<<16);
|
||||
sphase = phase + (256 << 16);
|
||||
|
||||
re = (sine_table_f32[(sphase & 0x03FF0000)>>18]*127);
|
||||
im = (sine_table_f32[(phase & 0x03FF0000)>>18]*127);
|
||||
|
||||
buffer.p[i] = {(int8_t)re,(int8_t)im};
|
||||
buffer.p[i] = { (int8_t)re, (int8_t)im };
|
||||
}
|
||||
|
||||
bc++;
|
||||
//AudioOutput::fill_audio_buffer(preview_audio_buffer, true);
|
||||
}
|
||||
|
||||
void AudioTXProcessor::on_message(const Message* const msg) {
|
||||
switch(msg->id) {
|
||||
case Message::ID::AudioTXConfig:
|
||||
//const auto message = static_cast<const AudioTXConfigMessage*>(msg);
|
||||
configured = true;
|
||||
break;
|
||||
|
||||
case Message::ID::FIFOData:
|
||||
//audio_fifo.in(static_cast<const FIFODataMessage*>(msg)->data, 1024);
|
||||
asked = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
@ -23,22 +23,39 @@
|
||||
#ifndef __PROC_AUDIOTX_H__
|
||||
#define __PROC_AUDIOTX_H__
|
||||
|
||||
#include "fifo.hpp"
|
||||
#include "baseband_processor.hpp"
|
||||
#include "baseband_thread.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class AudioTXProcessor : public BasebandProcessor {
|
||||
public:
|
||||
void execute(const buffer_c8_t& buffer) override;
|
||||
|
||||
void on_message(const Message* const msg) override;
|
||||
|
||||
private:
|
||||
bool configured = false;
|
||||
|
||||
//std::unique_ptr<int8_t[]> audio_fifo_data = std::make_unique<int8_t[]>(1UL << 11);
|
||||
//FIFO<int8_t> audio_fifo = { audio_fifo_data.get(), 11 }; // 43ms @ 48000Hz
|
||||
|
||||
uint8_t as = 0, ai;
|
||||
int8_t re, im;
|
||||
uint8_t s, as = 0, ai;
|
||||
uint8_t byte_pos = 0;
|
||||
uint8_t digit = 0;
|
||||
int8_t sample;
|
||||
|
||||
int16_t st;
|
||||
|
||||
bool asked = false;
|
||||
|
||||
//int16_t audio_data[64];
|
||||
/*const buffer_s16_t preview_audio_buffer {
|
||||
audio_data,
|
||||
sizeof(int16_t)*64
|
||||
};*/
|
||||
|
||||
FIFOSignalMessage sigmessage;
|
||||
|
||||
uint32_t aphase, phase, sphase;
|
||||
int32_t sample, frq, bc;
|
||||
int32_t frq;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "baseband_processor.hpp"
|
||||
#include "baseband_thread.hpp"
|
||||
#include "rssi_thread.hpp"
|
||||
|
||||
#include "channel_decimator.hpp"
|
||||
|
||||
@ -63,6 +64,7 @@ private:
|
||||
const float clock_recovery_rate = symbol_rate * 2;
|
||||
|
||||
BasebandThread baseband_thread { baseband_sampling_rate, this, NORMALPRIO + 20, baseband::Direction::Receive };
|
||||
RSSIThread rssi_thread { NORMALPRIO + 10 };
|
||||
|
||||
clock_recovery::ClockRecovery<clock_recovery::FixedErrorFilter> clock_recovery {
|
||||
clock_recovery_rate, symbol_rate, { 1.0f / 18.0f },
|
||||
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2016 Furrtek
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "proc_playaudio.hpp"
|
||||
#include "portapack_shared_memory.hpp"
|
||||
#include "sine_table.hpp"
|
||||
#include "audio_output.hpp"
|
||||
#include "event_m4.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
void PlayAudioProcessor::on_message(const Message* const msg) {
|
||||
if (msg->id == Message::ID::FIFOData) {
|
||||
const auto message = static_cast<const FIFODataMessage*>(msg);
|
||||
memcpy(&audio_fifo[fifo_put], message->data, 1024);
|
||||
fifo_put = (fifo_put + 1024) & 0x0FFF;
|
||||
asked = false;
|
||||
}
|
||||
}
|
||||
|
||||
void PlayAudioProcessor::execute(const buffer_c8_t& buffer){
|
||||
|
||||
// This is called at 1536000/2048 = 750Hz
|
||||
|
||||
ai = 0;
|
||||
for (size_t i = 0; i<buffer.count; i++) {
|
||||
// Audio preview sample generation: 1536000/48000 = 32
|
||||
if (as >= 31) {
|
||||
as = 0;
|
||||
sample = audio_fifo[fifo_get];
|
||||
preview_audio_buffer.p[ai++] = sample << 8;
|
||||
fifo_get = (fifo_get + 1) & 0x0FFF;
|
||||
if ((((fifo_put - fifo_get) & 0x0FFF) < 3072) && (asked == false)) {
|
||||
// Ask application to fill up fifo
|
||||
sigmessage.signaltype = 1;
|
||||
shared_memory.application_queue.push(sigmessage);
|
||||
asked = true;
|
||||
}
|
||||
} else {
|
||||
as++;
|
||||
}
|
||||
|
||||
sample = ((int8_t)audio_fifo[fifo_get] * 4);
|
||||
|
||||
//FM
|
||||
frq = sample * 2000;
|
||||
|
||||
phase = (phase + frq);
|
||||
sphase = phase + (256<<16);
|
||||
|
||||
re = (sine_table_f32[(sphase & 0x03FF0000)>>18]*127);
|
||||
im = (sine_table_f32[(phase & 0x03FF0000)>>18]*127);
|
||||
|
||||
buffer.p[i] = {(int8_t)re,(int8_t)im};
|
||||
}
|
||||
|
||||
//AudioOutput::fill_audio_buffer(preview_audio_buffer, true);
|
||||
}
|
||||
|
||||
int main() {
|
||||
EventDispatcher event_dispatcher { std::make_unique<PlayAudioProcessor>() };
|
||||
event_dispatcher.run();
|
||||
return 0;
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2016 Furrtek
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PROC_PLAYAUDIO_H__
|
||||
#define __PROC_PLAYAUDIO_H__
|
||||
|
||||
#include "baseband_processor.hpp"
|
||||
|
||||
class PlayAudioProcessor : public BasebandProcessor {
|
||||
public:
|
||||
void execute(const buffer_c8_t& buffer) override;
|
||||
void on_message(const Message* const msg) override;
|
||||
|
||||
private:
|
||||
int8_t audio_fifo[4096]; // Probably too much (=85ms @ 48000Hz)
|
||||
uint16_t fifo_put, fifo_get;
|
||||
uint8_t as = 0, ai;
|
||||
int8_t re, im;
|
||||
|
||||
int16_t st;
|
||||
|
||||
int16_t audio_data[64];
|
||||
|
||||
bool asked = false;
|
||||
|
||||
const buffer_s16_t preview_audio_buffer {
|
||||
audio_data,
|
||||
sizeof(int16_t)*64
|
||||
};
|
||||
|
||||
FIFOSignalMessage sigmessage;
|
||||
|
||||
uint32_t aphase, phase, sphase;
|
||||
int32_t sample, frq;
|
||||
};
|
||||
|
||||
#endif
|
@ -28,10 +28,6 @@
|
||||
#include <cstdint>
|
||||
|
||||
void RDSProcessor::execute(const buffer_c8_t& buffer) {
|
||||
uint32_t * rdsdata;
|
||||
|
||||
// TODO
|
||||
//rdsdata = (uint32_t *)shared_memory.radio_data;
|
||||
|
||||
for (size_t i = 0; i < buffer.count; i++) {
|
||||
|
||||
@ -96,6 +92,14 @@ void RDSProcessor::execute(const buffer_c8_t& buffer) {
|
||||
}
|
||||
}
|
||||
|
||||
void RDSProcessor::on_message(const Message* const msg) {
|
||||
if (msg->id == Message::ID::RDSConfigure) {
|
||||
//const auto message = *reinterpret_cast<const RDSConfigureMessage*>(p);
|
||||
rdsdata = (uint32_t*)shared_memory.tx_data;
|
||||
configured = true;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
EventDispatcher event_dispatcher { std::make_unique<RDSProcessor>() };
|
||||
event_dispatcher.run();
|
||||
|
@ -24,6 +24,7 @@
|
||||
#define __PROC_RDS_H__
|
||||
|
||||
#include "baseband_processor.hpp"
|
||||
#include "baseband_thread.hpp"
|
||||
|
||||
#define SAMPLES_PER_BIT 192
|
||||
#define FILTER_SIZE 576
|
||||
@ -33,7 +34,13 @@ class RDSProcessor : public BasebandProcessor {
|
||||
public:
|
||||
void execute(const buffer_c8_t& buffer) override;
|
||||
|
||||
void on_message(const Message* const msg) override;
|
||||
|
||||
private:
|
||||
uint32_t * rdsdata;
|
||||
|
||||
BasebandThread baseband_thread { 2280000, this, NORMALPRIO + 20, baseband::Direction::Transmit };
|
||||
|
||||
int8_t re, im;
|
||||
uint8_t mphase, s;
|
||||
uint32_t bit_pos;
|
||||
@ -50,6 +57,8 @@ private:
|
||||
int32_t sig, frq, frq_im, rdsc;
|
||||
int32_t k;
|
||||
|
||||
bool configured { false };
|
||||
|
||||
const int32_t waveform_biphase[576] = {
|
||||
165,167,168,168,167,166,163,160,
|
||||
157,152,147,141,134,126,118,109,
|
||||
|
@ -98,7 +98,7 @@ private:
|
||||
};
|
||||
|
||||
static constexpr float channel_rate_in = 307200.0f;
|
||||
static constexpr size_t channel_decimation = 8;
|
||||
static constexpr size_t channel_decimation = 2;
|
||||
static constexpr float channel_sample_rate = channel_rate_in / channel_decimation;
|
||||
OOKSlicerMagSquaredInt ook_slicer_5sps { channel_sample_rate / 8400 + 1};
|
||||
uint32_t slicer_history { 0 };
|
||||
|
@ -29,7 +29,7 @@ enable_language(C CXX ASM)
|
||||
project(bootstrap)
|
||||
|
||||
# Compiler options here.
|
||||
set(USE_OPT "-Os -falign-functions=16 -fno-math-errno --specs=nano.specs")
|
||||
set(USE_OPT "-Os -g -falign-functions=16 -fno-math-errno --specs=nano.specs")
|
||||
|
||||
# C specific options here (added to USE_OPT).
|
||||
set(USE_COPT "-std=gnu99")
|
||||
|
@ -71,9 +71,11 @@ public:
|
||||
AFSKConfigure = 23,
|
||||
PWMRSSIConfigure = 24,
|
||||
OOKConfigure = 25,
|
||||
RDSConfigure = 26,
|
||||
AudioTXConfig = 27,
|
||||
|
||||
FIFOSignal = 26,
|
||||
FIFOData = 27,
|
||||
FIFOSignal = 28,
|
||||
FIFOData = 29,
|
||||
MAX
|
||||
};
|
||||
|
||||
@ -516,6 +518,18 @@ public:
|
||||
const uint16_t tone_count;
|
||||
};
|
||||
|
||||
class RDSConfigureMessage : public Message {
|
||||
public:
|
||||
constexpr RDSConfigureMessage(
|
||||
const uint32_t length
|
||||
) : Message { ID::RDSConfigure },
|
||||
length(length)
|
||||
{
|
||||
}
|
||||
|
||||
const uint32_t length = 0;
|
||||
};
|
||||
|
||||
class RetuneMessage : public Message {
|
||||
public:
|
||||
constexpr RetuneMessage(
|
||||
@ -528,6 +542,18 @@ public:
|
||||
const int64_t freq = 0;
|
||||
};
|
||||
|
||||
class AudioTXConfigMessage : public Message {
|
||||
public:
|
||||
constexpr AudioTXConfigMessage(
|
||||
const uint32_t bw
|
||||
) : Message { ID::AudioTXConfig },
|
||||
bw(bw)
|
||||
{
|
||||
}
|
||||
|
||||
const uint32_t bw;
|
||||
};
|
||||
|
||||
class AFSKConfigureMessage : public Message {
|
||||
public:
|
||||
constexpr AFSKConfigureMessage(
|
||||
@ -576,6 +602,7 @@ public:
|
||||
const uint32_t pause_symbols;
|
||||
};
|
||||
|
||||
// TODO: use streaming buffer instead
|
||||
class FIFOSignalMessage : public Message {
|
||||
public:
|
||||
constexpr FIFOSignalMessage(
|
||||
@ -583,7 +610,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
const char signaltype = 0;
|
||||
char signaltype = 0;
|
||||
};
|
||||
|
||||
class FIFODataMessage : public Message {
|
||||
|
@ -36,7 +36,7 @@ using portapack::memory::map::backup_ram;
|
||||
namespace portapack {
|
||||
namespace persistent_memory {
|
||||
|
||||
constexpr rf::Frequency tuned_frequency_reset_value { 88000000 };
|
||||
constexpr rf::Frequency tuned_frequency_reset_value { 100000000 };
|
||||
|
||||
using ppb_range_t = range_t<ppb_t>;
|
||||
constexpr ppb_range_t ppb_range { -99000, 99000 };
|
||||
@ -57,9 +57,11 @@ constexpr int32_t afsk_bw_reset_value { 15 };
|
||||
|
||||
/* struct must pack the same way on M4 and M0 cores. */
|
||||
struct data_t {
|
||||
// General config
|
||||
int64_t tuned_frequency;
|
||||
int32_t correction_ppb;
|
||||
uint32_t touch_calibration_magic;
|
||||
touch::Calibration touch_calibration;
|
||||
|
||||
|
||||
// AFSK modem
|
||||
int32_t afsk_mark_freq;
|
||||
@ -99,6 +101,20 @@ void set_correction_ppb(const ppb_t new_value) {
|
||||
portapack::clock_manager.set_reference_ppb(clipped_value);
|
||||
}
|
||||
|
||||
static constexpr uint32_t touch_calibration_magic = 0x074af82f;
|
||||
|
||||
void set_touch_calibration(const touch::Calibration& new_value) {
|
||||
data->touch_calibration = new_value;
|
||||
data->touch_calibration_magic = touch_calibration_magic;
|
||||
}
|
||||
|
||||
const touch::Calibration& touch_calibration() {
|
||||
if( data->touch_calibration_magic != touch_calibration_magic ) {
|
||||
set_touch_calibration(touch::default_calibration());
|
||||
}
|
||||
return data->touch_calibration;
|
||||
}
|
||||
|
||||
int32_t afsk_mark_freq() {
|
||||
afsk_freq_range.reset_if_outside(data->afsk_mark_freq, afsk_mark_reset_value);
|
||||
return data->afsk_mark_freq;
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <cstdint>
|
||||
|
||||
#include "rf_path.hpp"
|
||||
#include "touch.hpp"
|
||||
|
||||
namespace portapack {
|
||||
namespace persistent_memory {
|
||||
@ -37,6 +38,9 @@ void set_tuned_frequency(const rf::Frequency new_value);
|
||||
ppb_t correction_ppb();
|
||||
void set_correction_ppb(const ppb_t new_value);
|
||||
|
||||
void set_touch_calibration(const touch::Calibration& new_value);
|
||||
const touch::Calibration& touch_calibration();
|
||||
|
||||
int32_t afsk_mark_freq();
|
||||
void set_afsk_mark(const int32_t new_value);
|
||||
|
||||
|
@ -75,7 +75,6 @@ constexpr image_tag_t image_tag_jammer { 'P', 'J', 'A', 'M' };
|
||||
constexpr image_tag_t image_tag_audio_tx { 'P', 'A', 'T', 'X' };
|
||||
constexpr image_tag_t image_tag_afsk { 'P', 'A', 'F', 'S' };
|
||||
constexpr image_tag_t image_tag_epar { 'P', 'E', 'P', 'R' };
|
||||
constexpr image_tag_t image_tag_play_audio { 'P', 'P', 'A', 'U' };
|
||||
constexpr image_tag_t image_tag_xylos { 'P', 'X', 'Y', 'L' };
|
||||
constexpr image_tag_t image_tag_rds { 'P', 'R', 'D', 'S' };
|
||||
constexpr image_tag_t image_tag_ook { 'P', 'O', 'O', 'K' };
|
||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user