Added tabs to BHT TX and Jammer

Updated firmware binary
This commit is contained in:
furrtek 2017-08-12 00:27:05 +01:00
commit e5fef6bb89
25 changed files with 751 additions and 646 deletions

View File

@ -13,12 +13,10 @@ notifications:
# TODO: The "build_number.1" in this URL is almost certainly wrong, but correct value not available from Travis?
- "Firmware download : https://portapack-h1-builds.s3.amazonaws.com/%{repository_slug}/%{build_number}/%{build_number}.1/build/firmware/portapack-h1-firmware-%{commit}.tar.bz2"
before_script:
- wget https://developer.arm.com/-/media/Files/downloads/gnu-rm/6-2017q2/gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2 -O /tmp/gcc-arm.tar.bz2
- tar -xf /tmp/gcc-arm.tar.bz2
- export PATH=$PWD/gcc-arm-none-eabi-6-2017-q2-update/bin:$PATH
- export CC="arm-none-eabi-gcc"
- export CXX="arm-none-eabi-g++"
before_install:
- sudo add-apt-repository ppa:team-gcc-arm-embedded/ppa -y
- sudo apt-get update -q
- sudo apt-get install gcc-arm-embedded -y
script:
# TODO: Introduce top-level Makefile, this is lame.
@ -29,14 +27,6 @@ script:
- popd
addons:
apt:
packages:
- lib32bz2-1.0
- lib32ncurses5
- lib32z1
- cmake
sources:
- kalakris-cmake
artifacts:
paths:
- $(ls build/firmware/portapack-h1-havoc-*.tar.bz2 | tr "\n" ":")

View File

@ -34,7 +34,9 @@ namespace audio {
namespace {
constexpr i2s::ConfigTX i2s0_config_tx {
// "Master": I2S peripheral generates SCK/WS, transmits to audio codec.
constexpr i2s::ConfigTX i2s0_config_tx_master_base_clk {
.dao = i2s::DAO {
.wordwidth = i2s::WordWidth::Bits16,
.mono = 0,
@ -56,9 +58,10 @@ constexpr i2s::ConfigTX i2s0_config_tx {
.four_pin = 0,
.mclk_out_en = 1,
},
.sck_in_sel = 1,
};
constexpr i2s::ConfigRX i2s0_config_rx {
constexpr i2s::ConfigRX i2s0_config_rx_four_wire {
.dai = i2s::DAI {
.wordwidth = i2s::WordWidth::Bits16,
.mono = 0,
@ -75,10 +78,38 @@ constexpr i2s::ConfigRX i2s0_config_rx {
.bitrate = 7,
},
.rxmode = i2s::Mode {
.clksel = i2s::ClockSelect::BaseAudioClkOrExternalMCLK,
.clksel = i2s::ClockSelect::FractionalDivider,
.four_pin = 1,
.mclk_out_en = 0,
},
.sck_in_sel = 0,
};
// "Slave": I2S controlled by external SCK/WS, received from audio codec.
constexpr i2s::ConfigTX i2s0_config_tx_slave_base_clk {
.dao = i2s::DAO {
.wordwidth = i2s::WordWidth::Bits16,
.mono = 0,
.stop = 1,
.reset = 0,
.ws_sel = 1,
.ws_halfperiod = 0x0f,
.mute = 1,
},
.txrate = i2s::MCLKRate {
.x_divider = 0,
.y_divider = 0,
},
.txbitrate = i2s::BitRate {
.bitrate = 0,
},
.txmode = i2s::Mode {
.clksel = i2s::ClockSelect::FractionalDivider,
.four_pin = 0,
.mclk_out_en = 1,
},
.sck_in_sel = 1,
};
constexpr i2s::ConfigDMA i2s0_config_dma {
@ -171,17 +202,18 @@ size_t reg_bits() {
} /* namespace debug */
void init(audio::Codec* const codec) {
audio_codec = codec;
clock_manager.start_audio_pll();
audio_codec->init();
// Configure I2S before activating codec interface.
i2s::i2s0::configure(
i2s0_config_tx,
i2s0_config_rx,
i2s0_config_tx_master_base_clk,
i2s0_config_rx_four_wire,
i2s0_config_dma
);
audio_codec = codec;
audio_codec->init();
// Set pin mode, since it's likely GPIO (as left after CPLD JTAG interactions).
portapack::pin_i2s0_rx_sda.mode(3);
}

View File

@ -551,6 +551,28 @@ static constexpr Bitmap bitmap_more {
{ 8, 8 }, bitmap_more_data
};
static constexpr uint8_t bitmap_icon_transmit_data[] = {
0xC0, 0x10,
0x00, 0x21,
0x1C, 0x22,
0x63, 0x42,
0x5D, 0x44,
0xA2, 0x44,
0xAA, 0x44,
0xAA, 0x44,
0x5D, 0x44,
0x6B, 0x42,
0x1C, 0x22,
0x1C, 0x21,
0xDD, 0x10,
0x3E, 0x08,
0x2A, 0x04,
0x2A, 0x03,
};
static constexpr Bitmap bitmap_icon_transmit {
{ 16, 16 }, bitmap_icon_transmit_data
};
static constexpr uint8_t bitmap_icon_freqman_data[] = {
0x00, 0x00,
0x0E, 0x00,
@ -1034,22 +1056,22 @@ static constexpr uint8_t bitmap_tab_edge_data[] = {
0x03,
0x07,
0x07,
0x07,
0x0F,
0x0F,
0x0F,
0x1F,
0x1F,
0x1F,
0x1F,
0x3F,
0x3F,
0x3F,
0x7F,
0x7F,
0x7F,
0xFF,
0xFF,
0x07,
0x0F,
0x0F,
0x0F,
0x1F,
0x1F,
0x1F,
0x1F,
0x3F,
0x3F,
0x3F,
0x7F,
0x7F,
0x7F,
0xFF,
0xFF,
};
static constexpr Bitmap bitmap_tab_edge {
{ 8, 24 }, bitmap_tab_edge_data

View File

@ -132,11 +132,7 @@ AboutView::AboutView(
NavigationView& nav
)
{
add_children({
&text_cpld_hackrf,
&text_cpld_hackrf_status,
&button_ok,
});
add_child(&button_ok);
for (auto& text : text_line) {
text.set("");
@ -148,12 +144,6 @@ AboutView::AboutView(
add_child(&text);
}
if( hackrf::cpld::verify_eeprom() ) {
text_cpld_hackrf_status.set(" OK");
} else {
text_cpld_hackrf_status.set("BAD");
}
button_ok.on_select = [&nav](Button&){
nav.pop();
};

View File

@ -106,16 +106,6 @@ private:
std::array<Text, 10> text_line { };
Text text_cpld_hackrf {
{ 0, 252, 11*8, 16 },
"HackRF CPLD",
};
Text text_cpld_hackrf_status {
{ 240 - 3*8, 252, 3*8, 16 },
"???"
};
Button button_ok {
{ 72, 272, 96, 24 },
"OK"

View File

@ -33,7 +33,7 @@ using namespace portapack;
namespace ui {
void BHTView::focus() {
relay_states[0].focus();
tx_view.focus();
}
BHTView::~BHTView() {
@ -41,34 +41,15 @@ BHTView::~BHTView() {
baseband::shutdown();
}
void BHTView::generate_message() {
if (tx_mode == SINGLE) {
text_message.set(
gen_message_xy(header_code_a.value(), header_code_b.value(), city_code_xy.value(), family_code_xy.value(),
checkbox_wcsubfamily.value(), subfamily_code.value(), checkbox_wcid.value(), receiver_code.value(),
relay_states[0].selected_index(), relay_states[1].selected_index(),
relay_states[2].selected_index(), relay_states[3].selected_index())
);
/*} else {
text_message.set(
gen_message_ep(city_code_ep.value(), family_code_ep.selected_index_value(),
relay_states[0].selected_index(), relay_states[1].selected_index())
);*/
} else if (tx_mode == SEQUENCE) {
text_message.set(
gen_message_xy(sequence_matin[seq_index].code)
);
}
}
void BHTView::start_tx() {
uint8_t c;
generate_message();
view_xylos.generate_message();
view_EPAR.generate_message();
if (tx_mode == SINGLE)
if (view_xylos.tx_mode == XylosView::tx_modes::SINGLE)
progressbar.set_max(20);
else if (tx_mode == SEQUENCE)
else if (view_xylos.tx_mode == XylosView::tx_modes::SEQUENCE)
progressbar.set_max(20 * XY_SEQ_COUNT);
transmitter_model.set_sampling_rate(1536000);
@ -85,155 +66,166 @@ void BHTView::start_tx() {
void BHTView::on_tx_progress(const int progress, const bool done) {
uint8_t c;
uint8_t rs;
if (tx_mode == SINGLE) {
if (view_xylos.tx_mode == XylosView::tx_modes::SINGLE) {
if (done) {
transmitter_model.disable();
progressbar.set_value(0);
if (!checkbox_cligno.value()) {
tx_mode = IDLE;
view_xylos.tx_mode = XylosView::tx_modes::IDLE;
tx_view.set_transmitting(false);
} else {
chThdSleepMilliseconds(tempo_cligno.value() * 1000); // Dirty :(
chThdSleepMilliseconds(field_tempo.value() * 1000); // Dirty :(
// Invert first relay's state
rs = relay_states[0].selected_index();
if (rs > 0) relay_states[0].set_selected_index(rs ^ 3);
view_EPAR.flip_relays();
view_xylos.flip_relays();
start_tx();
}
} else {
progressbar.set_value(progress);
}
} else if (tx_mode == SEQUENCE) {
} else if (view_xylos.tx_mode == XylosView::tx_modes::SEQUENCE) {
if (done) {
transmitter_model.disable();
if (seq_index < (XY_SEQ_COUNT - 1)) {
for (c = 0; c < sequence_matin[seq_index].delay; c++)
if (view_xylos.seq_index < (XY_SEQ_COUNT - 1)) {
for (c = 0; c < view_xylos.sequence_matin[view_xylos.seq_index].delay; c++)
chThdSleepMilliseconds(1000);
seq_index++;
view_xylos.seq_index++;
start_tx();
} else {
progressbar.set_value(0);
tx_mode = IDLE;
view_xylos.tx_mode = XylosView::tx_modes::IDLE;
tx_view.set_transmitting(false);
}
} else {
progressbar.set_value((seq_index * 20) + progress);
progressbar.set_value((view_xylos.seq_index * 20) + progress);
}
}
}
BHTView::BHTView(NavigationView& nav) {
void EPARView::flip_relays() {
// Invert first relay's state
relay_states[0].set_selected_index(relay_states[0].selected_index() ^ 1);
}
void EPARView::generate_message() {
//text_message.set(
gen_message_ep(field_city.value(), field_group.selected_index_value(),
relay_states[0].selected_index(), relay_states[1].selected_index());
//);
}
EPARView::EPARView() {
size_t n;
baseband::run_image(portapack::spi_flash::image_tag_tones);
//baseband::run_image(portapack::spi_flash::image_tag_encoders);
hidden(true);
//baseband::run_image(portapack::spi_flash::image_tag_ook);
add_children({
&labels,
&options_mode,
&header_code_a,
&header_code_b,
&city_code_xy,
&family_code_xy,
&subfamily_code,
&checkbox_wcsubfamily,
&receiver_code,
&checkbox_wcid,
&progressbar,
&text_message,
&checkbox_cligno,
&tempo_cligno,
&button_seq,
&tx_view
&field_city,
&field_group,
&button_scan
});
field_city.set_value(220);
field_group.set_selected_index(2);
options_mode.set_selected_index(0); // Start up in Xy mode
header_code_a.set_value(0);
header_code_b.set_value(0);
city_code_xy.set_value(10);
//city_code_ep.set_value(220);
family_code_xy.set_value(1);
//family_code_ep.set_selected_index(2);
subfamily_code.set_value(1);
receiver_code.set_value(1);
tempo_cligno.set_value(0);
field_city.on_change = [this](int32_t) { generate_message(); };
field_group.on_change = [this](size_t, int32_t) { generate_message(); };
/* options_mode.on_change = [this](size_t mode, OptionsField::value_t) {
_mode = mode;
if (_mode) {
// EP layout
remove_children({
&header_code_a,
&header_code_b,
&checkbox_speaker,
&bmp_speaker,
&city_code_xy,
&family_code_xy,
&subfamily_code,
&checkbox_wcsubfamily,
&receiver_code,
&checkbox_wcid,
&relay_states[2],
&relay_states[3]
});
add_children({
&city_code_ep,
&family_code_ep
});
set_dirty();
} else {
// Xy layout
remove_children({
&city_code_ep,
&family_code_ep
});
add_children({
&header_code_a,
&header_code_b,
&checkbox_speaker,
&bmp_speaker,
&city_code_xy,
&family_code_xy,
&subfamily_code,
&checkbox_wcsubfamily,
&receiver_code,
&checkbox_wcid,
&relay_states[2],
&relay_states[3]
});
set_dirty();
};
generate_message();
};*/
const auto relay_state_fn = [this](size_t, OptionsField::value_t) {
this->generate_message();
};
header_code_a.on_change = [this](int32_t) { generate_message(); };
header_code_b.on_change = [this](int32_t) { generate_message(); };
city_code_xy.on_change = [this](int32_t) { generate_message(); };
family_code_xy.on_change = [this](int32_t) { generate_message(); };
subfamily_code.on_change = [this](int32_t) { generate_message(); };
receiver_code.on_change = [this](int32_t) { generate_message(); };
n = 0;
for (auto& relay_state : relay_states) {
relay_state.on_change = relay_state_fn;
relay_state.set_parent_rect({
static_cast<Coord>(90 + (n * 36)),
80,
24, 24
});
relay_state.set_options(relay_options);
add_child(&relay_state);
n++;
}
}
void EPARView::focus() {
field_city.focus();
}
void XylosView::flip_relays() {
size_t rs;
// Invert first relay's state
rs = relay_states[0].selected_index();
if (rs > 0) relay_states[0].set_selected_index(rs ^ 3);
}
void XylosView::generate_message() {
if (tx_mode == SINGLE) {
//text_message.set(
gen_message_xy(field_header_a.value(), field_header_b.value(), field_city.value(), field_family.value(),
checkbox_wcsubfamily.value(), field_subfamily.value(), checkbox_wcid.value(), field_receiver.value(),
relay_states[0].selected_index(), relay_states[1].selected_index(),
relay_states[2].selected_index(), relay_states[3].selected_index());
//);
} else if (tx_mode == SEQUENCE) {
//text_message.set(
gen_message_xy(sequence_matin[seq_index].code);
//);
}
}
XylosView::XylosView() {
size_t n;
hidden(true);
//baseband::run_image(portapack::spi_flash::image_tag_tones);
add_children({
&labels,
&field_header_a,
&field_header_b,
&field_city,
&field_family,
&field_subfamily,
&checkbox_wcsubfamily,
&field_receiver,
&checkbox_wcid,
&button_seq,
});
field_header_a.set_value(0);
field_header_b.set_value(0);
field_city.set_value(10);
field_family.set_value(1);
field_subfamily.set_value(1);
field_receiver.set_value(1);
field_header_a.on_change = [this](int32_t) { generate_message(); };
field_header_b.on_change = [this](int32_t) { generate_message(); };
field_city.on_change = [this](int32_t) { generate_message(); };
field_family.on_change = [this](int32_t) { generate_message(); };
field_subfamily.on_change = [this](int32_t) { generate_message(); };
field_receiver.on_change = [this](int32_t) { generate_message(); };
checkbox_wcsubfamily.on_select = [this](Checkbox&, bool v) {
if (v)
subfamily_code.set_focusable(false);
else
subfamily_code.set_focusable(true);
field_subfamily.set_focusable(!v);
generate_message();
};
checkbox_wcid.on_select = [this](Checkbox&, bool v) {
if (v)
receiver_code.set_focusable(false);
else
receiver_code.set_focusable(true);
field_receiver.set_focusable(!v);
generate_message();
};
@ -248,16 +240,41 @@ BHTView::BHTView(NavigationView& nav) {
for (auto& relay_state : relay_states) {
relay_state.on_change = relay_state_fn;
relay_state.set_parent_rect({
static_cast<Coord>(4 + (n * 36)),
150,
static_cast<Coord>(54 + (n * 36)),
134,
24, 24
});
relay_state.set_options(relay_options);
add_child(&relay_state);
n++;
}
}
void XylosView::focus() {
field_city.focus();
}
BHTView::BHTView(NavigationView& nav) {
Rect view_rect = { 0, 3 * 8, 240, 192 };
generate_message();
baseband::run_image(portapack::spi_flash::image_tag_tones);
add_children({
&tab_view,
&labels,
&view_xylos,
&view_EPAR,
&checkbox_cligno,
&field_tempo,
&progressbar,
&text_message,
&tx_view
});
view_xylos.set_parent_rect(view_rect);
view_EPAR.set_parent_rect(view_rect);
field_tempo.set_value(0);
tx_view.on_edit_frequency = [this, &nav]() {
auto new_view = nav.push<FrequencyKeypadView>(receiver_model.tuning_frequency());
@ -266,18 +283,18 @@ BHTView::BHTView(NavigationView& nav) {
};
};
button_seq.on_select = [this, &nav](Button&) {
/*button_seq.on_select = [this, &nav](Button&) {
if (tx_mode == IDLE) {
seq_index = 0;
tx_mode = SEQUENCE;
tx_view.set_transmitting(true);
start_tx();
}
};
};*/
tx_view.on_start = [this]() {
if (tx_mode == IDLE) {
tx_mode = SINGLE;
if (view_xylos.tx_mode == XylosView::tx_modes::IDLE) {
view_xylos.tx_mode = XylosView::tx_modes::SINGLE;
tx_view.set_transmitting(true);
start_tx();
}
@ -286,7 +303,7 @@ BHTView::BHTView(NavigationView& nav) {
tx_view.on_stop = [this]() {
transmitter_model.disable();
tx_view.set_transmitting(false);
tx_mode = IDLE;
view_xylos.tx_mode = XylosView::tx_modes::IDLE;
};
}

View File

@ -22,6 +22,7 @@
#include "ui.hpp"
#include "ui_widget.hpp"
#include "ui_tabview.hpp"
#include "ui_navigation.hpp"
#include "ui_transmitter.hpp"
#include "ui_font_fixed_8x16.hpp"
@ -37,23 +38,30 @@
namespace ui {
class BHTView : public View {
class XylosView : public View {
public:
BHTView(NavigationView& nav);
~BHTView();
XylosView();
void focus() override;
std::string title() const override { return "BHT transmit"; };
private:
void flip_relays();
void generate_message();
enum tx_modes {
IDLE = 0,
SINGLE,
SEQUENCE
};
tx_modes tx_mode = IDLE;
uint32_t seq_index { 0 };
struct sequence_t {
const std::string code;
const uint32_t delay;
};
const sequence_t sequence_matin[XY_SEQ_COUNT] = {
{ "0000189000B1002B0000", 19 }, // 18:9:0:00 R1=OFF (1)
{ "0000189200B2110B0000", 16 }, // 18:9:2:00 R1=ON (4)
@ -70,124 +78,71 @@ private:
{ "0000181AAAB1000B0000", 17 }, // 18:1:A:AA
{ "0000189400B0100B0000", 17 } // 18:9:4:00 R2=OFF (8)
};
enum tx_modes {
IDLE = 0,
SINGLE,
SEQUENCE
};
tx_modes tx_mode = IDLE;
void generate_message();
void on_tx_progress(const int progress, const bool done);
void start_tx();
const Style style_val {
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::green(),
};
const Style style_cancel {
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::red(),
};
const Style style_grey {
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::grey(),
};
private:
Labels labels {
{ { 8 * 8, 3 * 8 }, "Header:", Color::light_grey() },
{ { 4 * 8, 5 * 8 }, "Code ville:", Color::light_grey() },
{ { 7 * 8, 7 * 8 }, "Famille:", Color::light_grey() },
{ { 2 * 8, 9 * 8 + 2 }, "Sous-famille:", Color::light_grey() },
{ { 2 * 8, 13 * 8 }, "ID recepteur:", Color::light_grey() },
{ { 1 * 8, 16 * 8 }, "Relais:", Color::light_grey() },
{ { 27 * 8 + 4, 19 * 8 + 4 }, "s.", Color::light_grey() }
{ { 8 * 8, 1 * 8 }, "Header:", Color::light_grey() },
{ { 4 * 8, 3 * 8 }, "Code ville:", Color::light_grey() },
{ { 7 * 8, 5 * 8 }, "Famille:", Color::light_grey() },
{ { 2 * 8, 7 * 8 + 2 }, "Sous-famille:", Color::light_grey() },
{ { 2 * 8, 11 * 8 }, "ID recepteur:", Color::light_grey() },
{ { 2 * 8, 14 * 8 }, "Relais:", Color::light_grey() }
};
OptionsField options_mode {
{ 10 * 8, 4 },
10,
{
{ "Mode Xy.", 0 },
{ "Mode EP.", 1 }
}
NumberField field_header_a {
{ 16 * 8, 1 * 8 },
2,
{ 0, 99 },
1,
'0'
};
NumberField field_header_b {
{ 18 * 8, 1 * 8 },
2,
{ 0, 99 },
1,
'0'
};
NumberField header_code_a {
NumberField field_city {
{ 16 * 8, 3 * 8 },
2,
{ 0, 99 },
1,
'0'
};
NumberField header_code_b {
{ 18 * 8, 3 * 8 },
2,
{ 0, 99 },
1,
'0'
};
NumberField city_code_xy {
{ 16 * 8, 5 * 8 },
2,
{ 0, 99 },
1,
' '
};
/*NumberField city_code_ep {
{ 16 * 8, 5 * 8 },
3,
{ 0, 255 },
1,
' '
};*/
NumberField family_code_xy {
{ 16 * 8, 7 * 8 },
NumberField field_family {
{ 16 * 8, 5 * 8 },
1,
{ 0, 9 },
1,
' '
};
/*OptionsField family_code_ep {
{ 16 * 8, 7 * 8 },
2,
{
{ "A ", 2 }, // See receiver PCB
{ "B ", 1 },
{ "C ", 0 },
{ "TP", 3 }
}
};*/
NumberField subfamily_code {
{ 16 * 8, 9 * 8 + 2 },
NumberField field_subfamily {
{ 16 * 8, 7 * 8 + 2 },
1,
{ 0, 9 },
1,
' '
};
Checkbox checkbox_wcsubfamily {
{ 20 * 8, 8 * 8 + 6 },
{ 20 * 8, 6 * 8 + 6 },
6,
"Toutes"
};
NumberField receiver_code {
{ 16 * 8, 13 * 8 },
NumberField field_receiver {
{ 16 * 8, 11 * 8 },
2,
{ 0, 99 },
1,
'0'
};
Checkbox checkbox_wcid {
{ 20 * 8, 12 * 8 + 4 },
{ 20 * 8, 10 * 8 + 4 },
4,
"Tous"
};
@ -200,30 +155,104 @@ private:
{ &bitmap_bulb_on, 2 }
};
ProgressBar progressbar {
{ 3 * 8, 12 * 16, 20 * 8, 16 },
Button button_seq {
{ 24 * 8, 1 * 8, 40, 32 },
"Seq"
};
Text text_message {
{ 3 * 8, 13 * 16, 20 * 8, 16 },
""
};
class EPARView : public View {
public:
EPARView();
void focus() override;
void flip_relays();
void generate_message();
private:
Labels labels {
{ { 4 * 8, 1 * 8 }, "Code ville:", Color::light_grey() },
{ { 8 * 8, 3 * 8 }, "Groupe:", Color::light_grey() },
{ { 8 * 8, 7 * 8 }, "Relais:", Color::light_grey() }
};
Checkbox checkbox_cligno {
{ 18 * 8 + 4, 19 * 8 },
NumberField field_city {
{ 16 * 8, 1 * 8 },
3,
"Alt"
};
NumberField tempo_cligno {
{ 25 * 8 + 4, 19 * 8 + 4 },
2,
{ 1, 99 },
{ 0, 255 },
1,
' '
};
Button button_seq {
{ 24 * 8, 13 * 16, 40, 32 },
"Seq"
OptionsField field_group {
{ 16 * 8, 3 * 8 },
2,
{
{ "A ", 2 }, // See receiver PCB
{ "B ", 1 },
{ "C ", 0 },
{ "TP", 3 }
}
};
std::array<ImageOptionsField, 2> relay_states { };
ImageOptionsField::options_t relay_options = {
{ &bitmap_bulb_off, 0 },
{ &bitmap_bulb_on, 1 }
};
Button button_scan {
{ 22 * 8, 1 * 8, 56, 32 },
"Scan"
};
};
class BHTView : public View {
public:
BHTView(NavigationView& nav);
~BHTView();
void focus() override;
std::string title() const override { return "BHT transmit"; };
private:
void on_tx_progress(const int progress, const bool done);
void start_tx();
XylosView view_xylos { };
EPARView view_EPAR { };
TabView tab_view {
{ "Xylos", Color::cyan(), &view_xylos },
{ "EPAR", Color::green(), &view_EPAR }
};
Labels labels {
{ { 29 * 8, 14 * 16 + 4 }, "s", Color::light_grey() }
};
ProgressBar progressbar {
{ 1 * 8, 14 * 16, 20 * 8, 16 },
};
Text text_message {
{ 1 * 8, 15 * 16, 20 * 8, 16 },
""
};
Checkbox checkbox_cligno {
{ 22 * 8, 14 * 16 },
1,
"~"
};
NumberField field_tempo {
{ 27 * 8, 14 * 16 + 4 },
2,
{ 1, 99 },
1,
' '
};
TransmitterView tx_view {

View File

@ -173,9 +173,9 @@ void RegistersWidget::paint(Painter& painter) {
void RegistersWidget::draw_legend(const Coord left, Painter& painter) {
const auto pos = screen_pos();
for(int i=0; i<config.registers_count; i+=config.registers_per_row()) {
for(size_t i=0; i<config.registers_count; i+=config.registers_per_row()) {
const Point offset {
left, (i / config.registers_per_row()) * row_height
left, static_cast<int>((i / config.registers_per_row()) * row_height)
};
const auto text = to_string_hex(i, config.legend_length());
@ -193,10 +193,10 @@ void RegistersWidget::draw_values(
) {
const auto pos = screen_pos();
for(int i=0; i<config.registers_count; i++) {
for(size_t i=0; i<config.registers_count; i++) {
const Point offset = {
left + config.legend_width() + 8 + (i % config.registers_per_row()) * (config.value_width() + 8),
(i / config.registers_per_row()) * row_height
static_cast<int>(left + config.legend_width() + 8 + (i % config.registers_per_row()) * (config.value_width() + 8)),
static_cast<int>((i / config.registers_per_row()) * row_height)
};
const auto value = reader(i);

View File

@ -130,42 +130,42 @@ private:
};
struct RegistersWidgetConfig {
int registers_count;
int register_bits;
size_t registers_count;
size_t register_bits;
constexpr int legend_length() const {
constexpr size_t legend_length() const {
return (registers_count >= 0x10) ? 2 : 1;
}
constexpr int legend_width() const {
constexpr size_t legend_width() const {
return legend_length() * 8;
}
constexpr int value_length() const {
constexpr size_t value_length() const {
return (register_bits + 3) / 4;
}
constexpr int value_width() const {
constexpr size_t value_width() const {
return value_length() * 8;
}
constexpr int registers_per_row() const {
constexpr size_t registers_per_row() const {
return (value_length() >= 3) ? 4 : 8;
}
constexpr int registers_row_length() const {
constexpr size_t registers_row_length() const {
return (registers_per_row() * (value_length() + 1)) - 1;
}
constexpr int registers_row_width() const {
constexpr size_t registers_row_width() const {
return registers_row_length() * 8;
}
constexpr int row_width() const {
constexpr size_t row_width() const {
return legend_width() + 8 + registers_row_width();
}
constexpr int rows() const {
constexpr size_t rows() const {
return registers_count / registers_per_row();
}
};
@ -185,7 +185,7 @@ private:
const RegistersWidgetConfig config;
const std::function<uint32_t(const size_t register_number)> reader;
static constexpr int row_height = 16;
static constexpr size_t row_height = 16;
void draw_legend(const Coord left, Painter& painter);
void draw_values(const Coord left, Painter& painter);

View File

@ -33,28 +33,95 @@
#include <stdio.h>
using namespace portapack;
using namespace jammer;
namespace ui {
void JammerView::focus() {
options_preset.focus();
void RangeView::focus() {
check_enabled.focus();
}
extern constexpr jammer_range_t RangeView::range_presets[];
extern constexpr Style RangeView::style_info;
RangeView::RangeView(NavigationView& nav) {
hidden(true);
add_children({
&labels,
&check_enabled,
&options_preset,
&button_min,
&button_max,
&text_info
});
check_enabled.set_value(false);
check_enabled.on_select = [this](Checkbox&, bool v) {
frequency_range.enabled = v;
};
button_min.on_select = [this, &nav](Button& button) {
rf::Frequency * value_ptr;
value_ptr = &frequency_range.min;
auto new_view = nav.push<FrequencyKeypadView>(*value_ptr);
new_view->on_changed = [this, value_ptr, &button](rf::Frequency f) {
*value_ptr = f;
update_button(button, f);
update_range();
};
//update_button(button, f);
};
button_max.on_select = [this, &nav](Button& button) {
rf::Frequency * value_ptr;
value_ptr = &frequency_range.max;
auto new_view = nav.push<FrequencyKeypadView>(*value_ptr);
new_view->on_changed = [this, value_ptr, &button](rf::Frequency f) {
*value_ptr = f;
update_button(button, f);
update_range();
};
//update_button(button, f);
};
text_info.set_style(&style_info);
options_preset.set_selected_index(8); // ISM 868
options_preset.on_change = [this](size_t, OptionsField::value_t v) {
frequency_range.min = range_presets[v].min;
frequency_range.max = range_presets[v].max;
check_enabled.set_value(true);
update_button(button_min, frequency_range.min);
update_button(button_max, frequency_range.max);
update_range();
};
}
JammerView::~JammerView() {
transmitter_model.disable();
baseband::shutdown();
}
void JammerView::update_range(const uint32_t n) {
void RangeView::update_button(Button& button, rf::Frequency f) {
std::string label;
auto f_mhz = to_string_dec_int(f / 1000000, 4);
auto f_hz100 = to_string_dec_int((f / 1000) % 1000, 3, '0');
label = f_mhz + "." + f_hz100 + "M";
button.set_text(label);
}
void RangeView::update_range() {
std::string label;
jammer_range_t * range_ptr;
rf::Frequency center, bw_khz;
range_ptr = &frequency_range[n];
center = (range_ptr->min + range_ptr->max) / 2;
bw_khz = abs(range_ptr->max - range_ptr->min) / 1000;
center = (frequency_range.min + frequency_range.max) / 2;
bw_khz = abs(frequency_range.max - frequency_range.min) / 1000;
label = "C:" + to_string_short_freq(center) + "M W:";
@ -68,24 +135,16 @@ void JammerView::update_range(const uint32_t n) {
while (label.length() < 23)
label += " ";
texts_info[n].set(label);
text_info.set(label);
}
void JammerView::update_button(const uint32_t id) {
std::string label;
rf::Frequency f;
if (id & 1)
f = frequency_range[id / 2].max;
else
f = frequency_range[id / 2].min;
auto f_mhz = to_string_dec_int(f / 1000000, 4);
auto f_hz100 = to_string_dec_int((f / 1000) % 1000, 3, '0');
void JammerView::focus() {
tab_view.focus();
}
label = f_mhz + "." + f_hz100 + "M";
buttons_freq[id].set_text(label);
JammerView::~JammerView() {
transmitter_model.disable();
baseband::shutdown();
}
void JammerView::on_retune(const rf::Frequency freq, const uint32_t range) {
@ -95,9 +154,11 @@ void JammerView::on_retune(const rf::Frequency freq, const uint32_t range) {
}
}
JammerView::JammerView(NavigationView& nav) {
size_t n;
JammerView::JammerView(
NavigationView& nav
) : nav_ { nav }
{
Rect view_rect = { 0, 3 * 8, 240, 80 };
baseband::run_image(portapack::spi_flash::image_tag_jammer);
static constexpr Style style_val {
@ -112,107 +173,28 @@ JammerView::JammerView(NavigationView& nav) {
.foreground = Color::red(),
};
static constexpr Style style_info {
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::grey(),
};
JammerChannel * jammer_channels = (JammerChannel*)shared_memory.bb_data.data;
add_children({
&tab_view,
&view_range_a,
&view_range_b,
&view_range_c,
&labels,
&options_type,
&text_range_number,
&text_range_total,
&options_speed,
&options_preset,
&options_hop,
&button_transmit
});
const auto button_freq_fn = [this, &nav](Button& button) {
rf::Frequency * value_ptr;
uint32_t id = button.id;
if (id & 1)
value_ptr = &frequency_range[id >> 1].max;
else
value_ptr = &frequency_range[id >> 1].min;
auto new_view = nav.push<FrequencyKeypadView>(*value_ptr);
new_view->on_changed = [this, value_ptr, id](rf::Frequency f) {
*value_ptr = f;
update_button(id);
update_range(id >> 1);
};
update_button(id);
};
const auto checkbox_fn = [this](Checkbox& checkbox, bool v) {
frequency_range[checkbox.id].enabled = v;
};
n = 0;
for (auto& button : buttons_freq) {
button.on_select = button_freq_fn;
button.set_parent_rect({
static_cast<Coord>(13 * 8),
static_cast<Coord>(76 + ((n >> 1) * 58) + (20 * (n & 1))),
96, 20
});
button.id = n;
add_child(&button);
n++;
}
n = 0;
for (auto& checkbox : checkboxes) {
checkbox.on_select = checkbox_fn;
checkbox.set_parent_rect({
static_cast<Coord>(8),
static_cast<Coord>(86 + (n * 58)),
24, 24
});
checkbox.id = n;
checkbox.set_text("Range " + to_string_dec_uint(n + 1));
add_child(&checkbox);
n++;
}
n = 0;
for (auto& text : texts_info) {
text.set_parent_rect({
static_cast<Coord>(3 * 8),
static_cast<Coord>(116 + (n * 58)),
25 * 8, 16
});
text.set_style(&style_info);
add_child(&text);
n++;
}
options_preset.on_change = [this](size_t, OptionsField::value_t v) {
const jammer_range_t * preset_ptr;
uint32_t c;
for (c = 0; c < 3; c++) {
preset_ptr = &range_presets[v][c];
frequency_range[c].min = preset_ptr->min;
frequency_range[c].max = preset_ptr->max;
checkboxes[c].set_value(preset_ptr->enabled);
update_button(c * 2);
update_button(c * 2 + 1);
update_range(c);
}
};
view_range_a.set_parent_rect(view_rect);
view_range_b.set_parent_rect(view_rect);
view_range_c.set_parent_rect(view_rect);
options_type.set_selected_index(2); // Sweep
options_speed.set_selected_index(3); // 10kHz
options_preset.set_selected_index(8); // ISM 868
options_hop.set_selected_index(1); // 50ms
button_transmit.set_style(&style_val);
@ -239,14 +221,14 @@ JammerView::JammerView(NavigationView& nav) {
// Convert ranges min/max to center/bw
for (size_t r = 0; r < 3; r++) {
if (frequency_range[r].enabled) {
range_bw = abs(frequency_range[r].max - frequency_range[r].min);
if (range_views[r]->frequency_range.enabled) {
range_bw = abs(range_views[r]->frequency_range.max - range_views[r]->frequency_range.min);
// Sort
if (frequency_range[r].min < frequency_range[r].max)
start_freq = frequency_range[r].min;
if (range_views[r]->frequency_range.min < range_views[r]->frequency_range.max)
start_freq = range_views[r]->frequency_range.min;
else
start_freq = frequency_range[r].max;
start_freq = range_views[r]->frequency_range.max;
if (range_bw >= JAMMER_CH_WIDTH) {
num_channels = 0;

View File

@ -24,12 +24,162 @@
#include "ui_widget.hpp"
#include "ui_font_fixed_8x16.hpp"
#include "ui_navigation.hpp"
#include "ui_tabview.hpp"
#include "transmitter_model.hpp"
#include "message.hpp"
#include "jammer.hpp"
using namespace jammer;
namespace ui {
class RangeView : public View {
public:
RangeView(NavigationView& nav);
void focus() override;
jammer_range_t frequency_range { };
private:
void update_button(Button& button, rf::Frequency f);
void update_range();
static constexpr Style style_info {
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::grey(),
};
static constexpr jammer_range_t range_presets[] = {
// GSM900 Orange
{ true, 935000000, 945000000 }, // BW:10M
// GSM1800 Orange
{ false, 1808000000, 1832000000 }, // BW:24M
// GSM900 SFR
{ true, 950000000, 960000000 }, // BW:10M
// GSM1800 SFR
{ false, 1832000000, 1853000000 }, // BW:21M
// GSM900 Bouygues
{ true, 925000000, 935000000 }, // BW:10M
// GSM1800 Bouygues
{ false, 1858000000, 1880000000 }, // BW:22M
// GSM900 Free
{ true, 945000000, 950000000 }, // BW:5M
// GSM-R
{ true, 921000000, 925000000 }, // BW:4M
// DECT
{ true, 1880000000, 1900000000 }, // BW: 20MHz
// PMV AFSK
{ true, 162930000, 162970000 }, // BW: 40kHz
// ISM 433
{ true, 433050000, 434790000 }, // Center: 433.92MHz BW: 0.2%
// ISM 868
{ true, 868000000, 868200000 }, // Center: 868.2MHz BW: 40kHz
// GPS L1
{ true, 1575420000 - 500000, 1575420000 + 500000 }, // BW: 1MHz
// GPS L2
{ false, 1227600000 - 1000000, 1227600000 + 1000000 }, // BW: 2MHz
// WLAN 2.4G CH1
{ true, 2412000000 - 11000000, 2412000000 + 11000000}, // BW: 22MHz
// WLAN 2.4G CH2
{ true, 2417000000 - 11000000, 2417000000 + 11000000}, // BW: 22MHz
// WLAN 2.4G CH3
{ true, 2422000000 - 11000000, 2422000000 + 11000000}, // BW: 22MHz
// WLAN 2.4G CH4
{ true, 2427000000 - 11000000, 2427000000 + 11000000}, // BW: 22MHz
// WLAN 2.4G CH5
{ true, 2432000000 - 11000000, 2432000000 + 11000000}, // BW: 22MHz
// WLAN 2.4G CH6
{ true, 2437000000 - 11000000, 2437000000 + 11000000}, // BW: 22MHz
// WLAN 2.4G CH7
{ true, 2442000000 - 11000000, 2442000000 + 11000000}, // BW: 22MHz
// WLAN 2.4G CH8
{ true, 2447000000 - 11000000, 2447000000 + 11000000}, // BW: 22MHz
// WLAN 2.4G CH9
{ true, 2452000000 - 11000000, 2452000000 + 11000000}, // BW: 22MHz
// WLAN 2.4G CH10
{ true, 2457000000 - 11000000, 2457000000 + 11000000}, // BW: 22MHz
// WLAN 2.4G CH11
{ true, 2462000000 - 11000000, 2462000000 + 11000000}, // BW: 22MHz
// WLAN 2.4G CH12
{ true, 2467000000 - 11000000, 2467000000 + 11000000}, // BW: 22MHz
// WLAN 2.4G CH13
{ true, 2472000000 - 11000000, 2472000000 + 11000000}, // BW: 22MHz
};
Labels labels {
{ { 2 * 8, 5 * 8 }, "Preset:", Color::light_grey() },
{ { 5 * 8, 9 * 8 }, "Start:", Color::light_grey() },
{ { 6 * 8, 13 * 8 }, "Stop:", Color::light_grey() },
};
Checkbox check_enabled {
{ 44, 1 * 8 },
12,
"Enable range",
false
};
OptionsField options_preset {
{ 9 * 8, 5 * 8 },
19,
{
{ "GSM900 Orange FR", 0 },
{ "GSM1800 Orange FR", 1 },
{ "GSM900 SFR FR", 2 },
{ "GSM1800 SFR FR", 3 },
{ "GSM900 Bouygues FR", 4 },
{ "GSM1800 Bouygues FR", 5 },
{ "GSM Free FR ", 6 },
{ "GSM-R FR ", 7 },
{ "DECT ", 8 },
{ "Optifib ", 9 },
{ "ISM 433 ", 10 },
{ "ISM 868 ", 11 },
{ "GPS L1 ", 12 },
{ "GPS L2 ", 13 },
{ "WLAN 2.4G CH1 ", 14 },
{ "WLAN 2.4G CH2 ", 15 },
{ "WLAN 2.4G CH3 ", 16 },
{ "WLAN 2.4G CH4 ", 17 },
{ "WLAN 2.4G CH5 ", 18 },
{ "WLAN 2.4G CH6 ", 19 },
{ "WLAN 2.4G CH7 ", 20 },
{ "WLAN 2.4G CH8 ", 21 },
{ "WLAN 2.4G CH9 ", 22 },
{ "WLAN 2.4G CH10 ", 23 },
{ "WLAN 2.4G CH11 ", 24 },
{ "WLAN 2.4G CH12 ", 25 },
{ "WLAN 2.4G CH13 ", 26 }
}
};
Button button_min {
{ 13 * 8, 4 * 16, 120, 28 },
""
};
Button button_max {
{ 13 * 8, 6 * 16, 120, 28 },
""
};
Text text_info {
{ 3 * 8, 8 * 16, 25 * 8, 16 },
""
};
};
class JammerView : public View {
public:
JammerView(NavigationView& nav);
@ -38,137 +188,34 @@ public:
void focus() override;
std::string title() const override { return "Jammer"; };
private:
typedef struct jammer_range {
bool enabled;
rf::Frequency min;
rf::Frequency max;
} jammer_range_t;
jammer_range_t frequency_range[3];
NavigationView& nav_;
void update_range(const uint32_t n);
void update_button(const uint32_t n);
void on_retune(const rf::Frequency freq, const uint32_t range);
const jammer_range_t range_presets[23][3] = {
// Orange
{{ true, 935000000, 945000000 }, // GSM 900 BW:10M
{ false, 1808000000, 1832000000 }, // GSM 1800 BW:24M
{ false, 0, 0 }},
// SFR
{{ true, 950000000, 960000000 }, // GSM 900 BW:10M
{ false, 1832000000, 1853000000 }, // GSM 1800 BW:21M
{ false, 0, 0 }},
// Bouygues
{{ true, 925000000, 935000000 }, // GSM 900 BW:10M
{ false, 1858000000, 1880000000 }, // GSM 1800 BW:22M
{ false, 0, 0 }},
// Free
{{ true, 945000000, 950000000 }, // GSM 900 BW:5M
{ false, 0, 0 },
{ false, 0, 0 }},
// GSM-R
{{ true, 921000000, 925000000 }, // GSM 900 BW:4M
{ false, 0, 0 },
{ false, 0, 0 }},
// DECT
{{ true, 1880000000, 1900000000 }, // BW: 20MHz
{ false, 0, 0 },
{ false, 0, 0 }},
// PMV AFSK
{{ true, 162930000, 162970000 }, // BW: 40kHz
{ false, 0, 0 },
{ false, 0, 0 }},
// ISM 433
{{ true, 433050000, 434790000 }, // Center: 433.92MHz BW: 0.2%
{ false, 0, 0 },
{ false, 0, 0 }},
// ISM 868
{{ true, 868000000, 868200000 }, // Center: 868.2MHz BW: 40kHz
{ false, 0, 0 },
{ false, 0, 0 }},
// GPS L1 & L2
{{ true, 1575420000 - 500000, 1575420000 + 500000 }, // BW: 1MHz
{ false, 1227600000 - 1000000, 1227600000 + 1000000 }, // BW: 2MHz
{ false, 0, 0 }},
// WLAN 2.4G CH1
{{ true, 2412000000 - 11000000, 2412000000 + 11000000}, // BW: 22MHz
{ false, 0, 0 },
{ false, 0, 0 }},
// WLAN 2.4G CH2
{{ true, 2417000000 - 11000000, 2417000000 + 11000000}, // BW: 22MHz
{ false, 0, 0 },
{ false, 0, 0 }},
// WLAN 2.4G CH3
{{ true, 2422000000 - 11000000, 2422000000 + 11000000}, // BW: 22MHz
{ false, 0, 0 },
{ false, 0, 0 }},
// WLAN 2.4G CH4
{{ true, 2427000000 - 11000000, 2427000000 + 11000000}, // BW: 22MHz
{ false, 0, 0 },
{ false, 0, 0 }},
// WLAN 2.4G CH5
{{ true, 2432000000 - 11000000, 2432000000 + 11000000}, // BW: 22MHz
{ false, 0, 0 },
{ false, 0, 0 }},
// WLAN 2.4G CH6
{{ true, 2437000000 - 11000000, 2437000000 + 11000000}, // BW: 22MHz
{ false, 0, 0 },
{ false, 0, 0 }},
// WLAN 2.4G CH7
{{ true, 2442000000 - 11000000, 2442000000 + 11000000}, // BW: 22MHz
{ false, 0, 0 },
{ false, 0, 0 }},
// WLAN 2.4G CH8
{{ true, 2447000000 - 11000000, 2447000000 + 11000000}, // BW: 22MHz
{ false, 0, 0 },
{ false, 0, 0 }},
// WLAN 2.4G CH9
{{ true, 2452000000 - 11000000, 2452000000 + 11000000}, // BW: 22MHz
{ false, 0, 0 },
{ false, 0, 0 }},
// WLAN 2.4G CH10
{{ true, 2457000000 - 11000000, 2457000000 + 11000000}, // BW: 22MHz
{ false, 0, 0 },
{ false, 0, 0 }},
// WLAN 2.4G CH11
{{ true, 2462000000 - 11000000, 2462000000 + 11000000}, // BW: 22MHz
{ false, 0, 0 },
{ false, 0, 0 }},
// WLAN 2.4G CH12
{{ true, 2467000000 - 11000000, 2467000000 + 11000000}, // BW: 22MHz
{ false, 0, 0 },
{ false, 0, 0 }},
// WLAN 2.4G CH13
{{ true, 2472000000 - 11000000, 2472000000 + 11000000}, // BW: 22MHz
{ false, 0, 0 },
{ false, 0, 0 }},
};
bool jamming { false };
RangeView view_range_a { nav_ };
RangeView view_range_b { nav_ };
RangeView view_range_c { nav_ };
std::array<RangeView*, 3> range_views { &view_range_a, &view_range_b, &view_range_c };
TabView tab_view {
{ "Range 1", Color::white(), range_views[0] },
{ "Range 2", Color::white(), range_views[1] },
{ "Range 3", Color::white(), range_views[2] },
};
Labels labels {
{ { 3 * 8, 4 }, "Type:", Color::light_grey() },
{ { 2 * 8, 20 }, "Speed:", Color::light_grey() },
{ { 1 * 8, 36 }, "Preset:", Color::light_grey() },
{ { 5 * 8, 52 }, "Hop:", Color::light_grey() }
{ { 3 * 8, 12 * 16 }, "Type:", Color::light_grey() },
{ { 2 * 8, 13 * 16 }, "Speed:", Color::light_grey() },
{ { 5 * 8, 14 * 16 }, "Hop:", Color::light_grey() }
};
OptionsField options_type {
{ 9 * 8, 4 },
{ 9 * 8, 12 * 16 },
5,
{
{ "FSK ", 0 },
@ -178,16 +225,16 @@ private:
};
Text text_range_number {
{ 18 * 8, 4, 2 * 8, 16 },
{ 18 * 8, 12 * 16, 2 * 8, 16 },
"--"
};
Text text_range_total {
{ 20 * 8, 4, 3 * 8, 16 },
{ 20 * 8, 12 * 16, 3 * 8, 16 },
"/--"
};
OptionsField options_speed {
{ 9 * 8, 20 },
{ 9 * 8, 13 * 16 },
6,
{
{ "10Hz ", 10 },
@ -198,38 +245,8 @@ private:
}
};
OptionsField options_preset {
{ 9 * 8, 36 },
16,
{
{ "GSM Orange FR ", 0 },
{ "GSM SFR FR ", 1 },
{ "GSM Bouygues FR", 2 },
{ "GSM Free FR ", 3 },
{ "GSM-R FR ", 4 },
{ "DECT ", 5 },
{ "Optifib ", 6 },
{ "ISM 433 ", 7 },
{ "ISM 868 ", 8 },
{ "GPS ", 9 },
{ "WLAN 2.4G CH1 ", 10 },
{ "WLAN 2.4G CH2 ", 11 },
{ "WLAN 2.4G CH3 ", 12 },
{ "WLAN 2.4G CH4 ", 13 },
{ "WLAN 2.4G CH5 ", 14 },
{ "WLAN 2.4G CH6 ", 15 },
{ "WLAN 2.4G CH7 ", 16 },
{ "WLAN 2.4G CH8 ", 17 },
{ "WLAN 2.4G CH9 ", 18 },
{ "WLAN 2.4G CH10 ", 19 },
{ "WLAN 2.4G CH11 ", 20 },
{ "WLAN 2.4G CH12 ", 21 },
{ "WLAN 2.4G CH13 ", 22 }
}
};
OptionsField options_hop {
{ 9 * 8, 52 },
{ 9 * 8, 14 * 16 },
5,
{
{ "10ms ", 1 },
@ -241,10 +258,6 @@ private:
{ "10s ", 1000 }
}
};
std::array<Checkbox, 3> checkboxes { };
std::array<Button, 6> buttons_freq { };
std::array<Text, 3> texts_info { };
Button button_transmit {
{ 1 * 8, 16 * 16, 80, 48 },

View File

@ -349,7 +349,7 @@ SystemMenuView::SystemMenuView(NavigationView& nav) {
add_items({
{ "Play dead", ui::Color::red(), &bitmap_icon_playdead, [&nav](){ nav.push<PlayDeadView>(); } },
{ "Receivers", ui::Color::cyan(), &bitmap_icon_receivers, [&nav](){ nav.push<ReceiversMenuView>(); } },
{ "Transmitters", ui::Color::green(), nullptr, [&nav](){ nav.push<TransmittersMenuView>(); } },
{ "Transmitters", ui::Color::green(), &bitmap_icon_transmit, [&nav](){ nav.push<TransmittersMenuView>(); } },
{ "Capture", ui::Color::blue(), &bitmap_icon_capture, [&nav](){ nav.push<CaptureAppView>(); } },
{ "Replay", ui::Color::grey(), &bitmap_icon_replay, [&nav](){ nav.push<ReplayAppView>(); } },
{ "Scanner/search", ui::Color::orange(), &bitmap_icon_closecall, [&nav](){ nav.push<ScannerView>(); } },

View File

@ -566,8 +566,8 @@ buffer_c16_t DecimateBy2CIC3::execute(
uint32_t t1 = _iq0;
uint32_t t2 = _iq1;
const uint32_t taps = 0x00000003;
auto s = src.p;
auto d = dst.p;
void* s = src.p;
void* d = dst.p;
const auto d_end = &dst.p[src.count / 2];
while(d < d_end) {
uint32_t i = __SXTH(t1, 0); /* 1: I0 */
@ -665,21 +665,21 @@ buffer_c16_t FIRAndDecimateComplex::execute(
const auto output_sampling_rate = src.sampling_rate / decimation_factor_;
const size_t output_samples = src.count / decimation_factor_;
sample_t* dst_p = dst.p;
void* dst_p = dst.p;
const buffer_c16_t result { dst.p, output_samples, output_sampling_rate };
const sample_t* src_p = src.p;
const void* src_p = src.p;
size_t outer_count = output_samples;
while(outer_count > 0) {
/* Put new samples into delay buffer */
auto z_new_p = &samples_[taps_count_ - decimation_factor_];
void* z_new_p = &samples_[taps_count_ - decimation_factor_];
for(size_t i=0; i<decimation_factor_; i++) {
*__SIMD32(z_new_p)++ = *__SIMD32(src_p)++;
}
size_t loop_count = taps_count_ / 8;
auto t_p = &taps_reversed_[0];
auto z_p = &samples_[0];
void* t_p = &taps_reversed_[0];
void* z_p = &samples_[0];
int64_t t_real = 0;
int64_t t_imag = 0;
@ -741,8 +741,8 @@ buffer_c16_t FIRAndDecimateComplex::execute(
const size_t unroll_factor = 4;
size_t shift_count = (taps_count_ - decimation_factor_) / unroll_factor;
sample_t* t = &samples_[0];
const sample_t* s = &samples_[decimation_factor_];
void* t = &samples_[0];
const void* s = &samples_[decimation_factor_];
while(shift_count > 0) {
*__SIMD32(t)++ = *__SIMD32(s)++;
@ -754,7 +754,7 @@ buffer_c16_t FIRAndDecimateComplex::execute(
shift_count = (taps_count_ - decimation_factor_) % unroll_factor;
while(shift_count > 0) {
*(t++) = *(s++);
*__SIMD32(t)++ = *__SIMD32(s)++;
shift_count--;
}

View File

@ -34,7 +34,7 @@ buffer_f32_t AM::execute(
const buffer_c16_t& src,
const buffer_f32_t& dst
) {
const auto src_p = src.p;
const void* src_p = src.p;
const auto src_end = &src.p[src.count];
auto dst_p = dst.p;
while(src_p < src_end) {
@ -90,7 +90,7 @@ buffer_f32_t FM::execute(
) {
auto z = z_;
const auto src_p = src.p;
const void* src_p = src.p;
const auto src_end = &src.p[src.count];
auto dst_p = dst.p;
while(src_p < src_end) {
@ -113,9 +113,9 @@ buffer_s16_t FM::execute(
) {
auto z = z_;
const auto src_p = src.p;
const void* src_p = src.p;
const auto src_end = &src.p[src.count];
auto dst_p = dst.p;
void* dst_p = dst.p;
while(src_p < src_end) {
const auto s0 = *__SIMD32(src_p)++;
const auto s1 = *__SIMD32(src_p)++;

View File

@ -41,6 +41,19 @@ extern "C" {
* @brief Product name title=UM10503 Chapter title=LPC43xx Configuration Registers (CREG) Modification date=1/28/2014 Major revision=1 Minor revision=8
*/
typedef struct {
__IO uint32_t ETHMODE : 3;
uint32_t RESERVED0 : 1;
__IO uint32_t CTOUTCTRL : 1;
uint32_t RESERVED1 : 7;
__IO uint32_t I2S0_TX_SCK_IN_SEL : 1;
__IO uint32_t I2S0_RX_SCK_IN_SEL : 1;
__IO uint32_t I2S1_TX_SCK_IN_SEL : 1;
__IO uint32_t I2S1_RX_SCK_IN_SEL : 1;
__IO uint32_t EMC_CLK_SEL : 1;
uint32_t RESERVED2 : 15;
} LPC_CREG_CREG6_Type;
typedef struct {
uint32_t RESERVED0;
__IO uint32_t CREG0;
@ -52,7 +65,7 @@ typedef struct {
__IO uint32_t FLASHCFGA;
__IO uint32_t FLASHCFGB;
__IO uint32_t ETBCFG;
__IO uint32_t CREG6;
LPC_CREG_CREG6_Type CREG6;
__IO uint32_t M4TXEVENT;
uint32_t RESERVED3[51];
__I uint32_t CHIPID;

View File

@ -29,7 +29,7 @@ using namespace portapack;
namespace asahi_kasei {
namespace ak4951 {
void AK4951::configure_digital_interface() {
void AK4951::configure_digital_interface_i2s() {
// Configure for external slave mode.
map.r.mode_control_1.DIF = 0b11; // I2S compatible
map.r.mode_control_1.BCKO = 0; // BICK = 32fs
@ -38,22 +38,28 @@ void AK4951::configure_digital_interface() {
map.r.mode_control_2.CM = 0b00; // MCKI = 256fs
map.r.mode_control_2.FS = 0b1011; // fs = 48kHz
update(Register::ModeControl2);
}
// map.r.mode_control_3.DVOLC = 1; // Control L/R channels with DVL (LchDigitalVolumeControl)
// update(Register::ModeControl3);
void AK4951::configure_digital_interface_external_slave() {
map.r.power_management_2.MS = 0; // Slave mode
map.r.power_management_2.PMPLL = 0; // EXT mode
update(Register::PowerManagement2);
}
void AK4951::configure_digital_interface_external_master() {
map.r.power_management_2.MS = 1; // Master mode
map.r.power_management_2.PMPLL = 0; // EXT mode
update(Register::PowerManagement2);
}
void AK4951::init() {
reset();
// Write dummy address to "release" the reset.
write(0x00, 0x00);
configure_digital_interface();
configure_digital_interface_i2s();
configure_digital_interface_external_slave();
map.r.power_management_1.PMVCM = 1;
update(Register::PowerManagement1);

View File

@ -864,7 +864,9 @@ private:
Line,
};
void configure_digital_interface();
void configure_digital_interface_i2s();
void configure_digital_interface_external_slave();
void configure_digital_interface_external_master();
void set_digtal_volume_control(const reg_t value);
void set_dac_power(const bool enable);
void set_headphone_power(const bool enable);

View File

@ -138,6 +138,7 @@ struct ConfigTX {
uint32_t txrate;
uint32_t txbitrate;
uint32_t txmode;
uint32_t sck_in_sel;
};
struct ConfigRX {
@ -145,6 +146,7 @@ struct ConfigRX {
uint32_t rxrate;
uint32_t rxbitrate;
uint32_t rxmode;
uint32_t sck_in_sel;
};
struct ConfigDMA {
@ -161,21 +163,13 @@ public:
) {
reset();
/* I2S operates in master mode, use PLL0AUDIO as MCLK source for TX. */
/* NOTE: Documentation of CREG6 is quite confusing. Refer to "I2S clocking and
* pin connections" and other I2S diagrams for more clarity.
*/
if( &p() == LPC_I2S0 ) {
LPC_CREG->CREG6 |=
(1U << 12)
| (1U << 13)
;
LPC_CREG->CREG6.I2S0_TX_SCK_IN_SEL = config_tx.sck_in_sel;
LPC_CREG->CREG6.I2S0_RX_SCK_IN_SEL = config_rx.sck_in_sel;
}
if( &p() == LPC_I2S1 ) {
LPC_CREG->CREG6 |=
(1U << 14)
| (1U << 15)
;
LPC_CREG->CREG6.I2S1_TX_SCK_IN_SEL = config_tx.sck_in_sel;
LPC_CREG->CREG6.I2S1_RX_SCK_IN_SEL = config_rx.sck_in_sel;
}
p().DAO = config_tx.dao;

View File

@ -28,6 +28,12 @@
namespace jammer {
typedef struct jammer_range {
bool enabled;
int64_t min;
int64_t max;
} jammer_range_t;
enum JammerType : uint32_t {
TYPE_FSK = 0,
TYPE_TONE = 1,

View File

@ -78,7 +78,7 @@ constexpr Pin pins[] = {
[P2_11] = { 2, 11, { .mode=0, .pd=1, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* RX_AMP/P49: U12.V1(I), U14.V3(I) */
[P2_12] = { 2, 12, { .mode=0, .pd=0, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* !RX_AMP_PWR/P52: 10K PU, Q1.G(I), power to U13 (RX amp) */
[P2_13] = { 2, 13, { .mode=0, .pd=0, .pu=0, .fast=0, .input=1, .ifilt=1 } }, /* P2_13: PortaPack P2_13/DIR */
[P3_0] = { 3, 0, { .mode=2, .pd=0, .pu=1, .fast=0, .input=0, .ifilt=1 } }, /* I2S0_TX_SCK: PortaPack I2S0_TX_SCK(I) */
[P3_0] = { 3, 0, { .mode=2, .pd=0, .pu=1, .fast=0, .input=1, .ifilt=1 } }, /* I2S0_TX_SCK: PortaPack I2S0_TX_SCK(I) */
[P3_1] = { 3, 1, { .mode=0, .pd=0, .pu=1, .fast=0, .input=1, .ifilt=1 } }, /* I2S0_RX_WS: PortaPack I2S0_TX_WS(I). Input enabled to fold back into RX. */
[P3_2] = { 3, 2, { .mode=0, .pd=0, .pu=1, .fast=0, .input=0, .ifilt=1 } }, /* I2S0_RX_SDA: PortaPack I2S0_TX_SDA(I) */
//[P3_3] = { 3, 3, { .mode=3, .pd=1, .pu=0, .fast=1, .input=1, .ifilt=0 } }, /* SPIFI_SCK: W25Q80BV.CLK(I), enable input buffer for timing feedback */

View File

@ -108,7 +108,7 @@ Optional<Reading> Packet::reading_ook_8k4_schrader() const {
* Those bits assumed to be 0b0100", which may not be entirely true...
*/
constexpr uint8_t first_nibble = 0x4;
const auto system_id = (first_nibble << 20) | reader_.read(0, 20);
// const auto system_id = (first_nibble << 20) | reader_.read(0, 20);
const auto id = reader_.read(20, 32);
const auto value_0 = reader_.read(52, 8);
const auto value_1 = reader_.read(60, 8);

View File

@ -25,6 +25,30 @@
namespace wolfson {
namespace wm8731 {
void WM8731::configure_interface_i2s_slave() {
write(DigitalAudioInterfaceFormat {
.format = 2,
.iwl = 0,
.lrp = 0,
.lrswap = 0,
.ms = 0,
.bclkinv = 0,
.reserved0 = 0,
});
}
void WM8731::configure_interface_i2s_master() {
write(DigitalAudioInterfaceFormat {
.format = 2,
.iwl = 0,
.lrp = 0,
.lrswap = 0,
.ms = 1,
.bclkinv = 0,
.reserved0 = 0,
});
}
void WM8731::init() {
reset();
@ -49,15 +73,7 @@ void WM8731::init() {
// .reserved0 = 0,
// });
write(DigitalAudioInterfaceFormat {
.format = 2,
.iwl = 0,
.lrp = 0,
.lrswap = 0,
.ms = 0,
.bclkinv = 0,
.reserved0 = 0,
});
configure_interface_i2s_slave();
write(DigitalAudioPathControl {
.adchpd = 0,

View File

@ -375,6 +375,9 @@ private:
RegisterMap map { default_after_reset };
volume_t headphone_volume = -60.0_dB;
void configure_interface_i2s_slave();
void configure_interface_i2s_master();
bool write(const Register reg);
bool write(const address_t reg_address, const reg_t value);

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 B

Binary file not shown.