Remove dead code (#2304)

* remove dead code, playdead

* removed Nuoptix

* remove ui_loadmodule

* removed modules.h

* removed replay_app

* removed handwrite

* removed numbers, script

* remove emu_cc1101

* removed noop, old pocsag

* removed unused abouts

* removed tone_search

* fix format

* forgot to remove

* removed unused py

* removed modules.h too
This commit is contained in:
Totoo 2024-10-15 22:14:33 +02:00 committed by GitHub
parent 1b3359b050
commit 66aa20161d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
35 changed files with 8 additions and 4342 deletions

View File

@ -191,7 +191,6 @@ set(CPPSRC
core_control.cpp
database.cpp
de_bruijn.cpp
#emu_cc1101.cpp
rfm69.cpp
event_m0.cpp
file_reader.cpp
@ -246,7 +245,6 @@ set(CPPSRC
hw/touch_adc.cpp
ui_baseband_stats_view.cpp
ui_navigation.cpp
ui_playdead.cpp
ui_record_view.cpp
ui_sd_card_status_view.cpp
ui/ui_alphanum.cpp
@ -270,28 +268,21 @@ set(CPPSRC
ui/ui_bmpview.cpp
apps/ais_app.cpp
apps/analog_audio_app.cpp
# apps/analog_tv_app.cpp
apps/ble_comm_app.cpp
apps/ble_rx_app.cpp
apps/ble_tx_app.cpp
apps/capture_app.cpp
apps/ert_app.cpp
# apps/gps_sim_app.cpp
# apps/lge_app.cpp
apps/pocsag_app.cpp
# apps/replay_app.cpp
apps/soundboard_app.cpp
# apps/tpms_app.cpp
apps/ui_about_simple.cpp
apps/ui_adsb_rx.cpp
# apps/ui_adsb_tx.cpp #moved to ext
apps/ui_aprs_rx.cpp
apps/ui_aprs_tx.cpp
apps/ui_battinfo.cpp
apps/ui_bht_tx.cpp
apps/ui_bmp_file_viewer.cpp
apps/ui_btle_rx.cpp
# apps/ui_coasterp.cpp
apps/ui_debug.cpp
apps/ui_debug_max17055.cpp
apps/ui_dfu_menu.cpp
@ -302,16 +293,10 @@ set(CPPSRC
apps/ui_freqman.cpp
apps/ui_fsk_rx.cpp
apps/ui_iq_trim.cpp
# apps/ui_jammer.cpp
# apps/ui_keyfob.cpp
# apps/ui_lcr.cpp
apps/ui_level.cpp
apps/ui_looking_glass_app.cpp
apps/ui_mictx.cpp
apps/ui_modemsetup.cpp
# apps/ui_morse.cpp
# apps/ui_nrf_rx.cpp
# apps/ui_nuoptix.cpp
apps/ui_playlist.cpp
apps/ui_pocsag_tx.cpp
apps/ui_rds.cpp
@ -325,16 +310,11 @@ set(CPPSRC
apps/ui_settings.cpp
apps/ui_siggen.cpp
apps/ui_sonde.cpp
# apps/ui_spectrum_painter_image.cpp
# apps/ui_spectrum_painter_text.cpp
# apps/ui_spectrum_painter.cpp
apps/ui_ss_viewer.cpp
# apps/ui_sstvtx.cpp #moved to ext
apps/ui_standalone_view.cpp
apps/ui_subghzd.cpp
# apps/ui_test.cpp
apps/ui_text_editor.cpp
apps/ui_tone_search.cpp
apps/ui_touch_calibration.cpp
apps/ui_touchtunes.cpp
apps/ui_view_wav.cpp
@ -345,14 +325,8 @@ set(CPPSRC
protocols/bht.cpp
protocols/dcs.cpp
protocols/encoders.cpp
# protocols/lcr.cpp
protocols/modems.cpp
protocols/rds.cpp
# ui_handwrite.cpp
# ui_loadmodule.cpp
# ui_numbers.cpp
# ui_replay_view.cpp
# ui_script.cpp
ui_sd_card_debug.cpp
config_mode.cpp
${CPLD_20150901_DATA_CPP}

View File

@ -1,224 +0,0 @@
/*
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
* Copyleft () 2022 NotPike
*
* 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 "replay_app.hpp"
#include "string_format.hpp"
#include "ui_fileman.hpp"
#include "io_file.hpp"
#include "io_convert.hpp"
#include "baseband_api.hpp"
#include "metadata_file.hpp"
#include "portapack.hpp"
#include "portapack_persistent_memory.hpp"
#include "utility.hpp"
using namespace portapack;
namespace fs = std::filesystem;
namespace ui {
void ReplayAppView::set_ready() {
ready_signal = true;
}
void ReplayAppView::on_file_changed(const fs::path& new_file_path) {
file_path = new_file_path;
File::Size file_size{};
{ // Get the size of the data file.
File data_file;
auto error = data_file.open(file_path);
if (error) {
file_error();
return;
}
file_size = data_file.size();
}
// Get original record frequency if available.
auto metadata_path = get_metadata_path(file_path);
auto metadata = read_metadata_file(metadata_path);
if (metadata) {
field_frequency.set_value(metadata->center_frequency);
sample_rate = metadata->sample_rate;
} else {
// TODO: This is interesting because it implies that the
// The capture will just be replayed at the freq set on the
// FrequencyField. Is that an intentional behavior?
sample_rate = 500000;
}
// UI Fixup.
text_sample_rate.set(unit_auto_scale(sample_rate, 3, 0) + "Hz");
progressbar.set_max(file_size);
text_filename.set(truncate(file_path.filename().string(), 12));
uint8_t sample_size = capture_file_sample_size(current()->path);
auto duration = ms_duration(file_size, sample_rate, sample_size);
text_duration.set(to_string_time_ms(duration));
button_play.focus();
}
void ReplayAppView::on_tx_progress(const uint32_t progress) {
progressbar.set_value(progress);
}
void ReplayAppView::focus() {
button_open.focus();
}
void ReplayAppView::file_error() {
nav_.display_modal("Error", "File read error.");
}
bool ReplayAppView::is_active() const {
return (bool)replay_thread;
}
void ReplayAppView::toggle() {
if (is_active()) {
stop(false);
} else {
start();
}
}
void ReplayAppView::start() {
stop(false);
std::unique_ptr<stream::Reader> reader;
auto p = std::make_unique<FileConvertReader>();
auto open_error = p->open(file_path);
if (open_error.is_valid()) {
file_error();
return; // Fixes TX bug if there's a file error
} else {
reader = std::move(p);
}
if (reader) {
button_play.set_bitmap(&bitmap_stop);
baseband::set_sample_rate(sample_rate, OversampleRate::x8);
replay_thread = std::make_unique<ReplayThread>(
std::move(reader),
read_size, buffer_count,
&ready_signal,
[](uint32_t return_code) {
ReplayThreadDoneMessage message{return_code};
EventDispatcher::send_message(message);
});
}
transmitter_model.set_sampling_rate(sample_rate * toUType(OversampleRate::x8));
transmitter_model.set_baseband_bandwidth(baseband_bandwidth);
transmitter_model.enable();
if (portapack::persistent_memory::stealth_mode()) {
DisplaySleepMessage message;
EventDispatcher::send_message(message);
}
}
void ReplayAppView::stop(const bool do_loop) {
if (is_active())
replay_thread.reset();
if (do_loop && check_loop.value()) {
start();
} else {
transmitter_model.disable();
button_play.set_bitmap(&bitmap_play);
}
ready_signal = false;
}
void ReplayAppView::handle_replay_thread_done(const uint32_t return_code) {
if (return_code == ReplayThread::END_OF_FILE) {
stop(true);
} else if (return_code == ReplayThread::READ_ERROR) {
stop(false);
file_error();
}
progressbar.set_value(0);
}
ReplayAppView::ReplayAppView(
NavigationView& nav)
: nav_(nav) {
baseband::run_image(portapack::spi_flash::image_tag_replay);
add_children({
&button_open,
&text_filename,
&text_sample_rate,
&text_duration,
&progressbar,
&field_frequency,
&tx_view, // now it handles previous rfgain, rfamp.
&check_loop,
&button_play,
&waterfall,
});
button_play.on_select = [this](ImageButton&) {
this->toggle();
};
button_open.on_select = [this, &nav](Button&) {
auto open_view = nav.push<FileLoadView>(".C*");
open_view->on_changed = [this](fs::path new_file_path) {
on_file_changed(new_file_path);
};
};
}
ReplayAppView::~ReplayAppView() {
transmitter_model.disable();
baseband::shutdown();
}
void ReplayAppView::on_hide() {
stop(false);
// TODO: Terrible kludge because widget system doesn't notify Waterfall that
// it's being shown or hidden.
waterfall.on_hide();
View::on_hide();
}
void ReplayAppView::set_parent_rect(const Rect new_parent_rect) {
View::set_parent_rect(new_parent_rect);
const ui::Rect waterfall_rect{0, header_height, new_parent_rect.width(), new_parent_rect.height() - header_height};
waterfall.set_parent_rect(waterfall_rect);
}
} /* namespace ui */

View File

@ -1,146 +0,0 @@
/*
* Copyright (C) 2016 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 __REPLAY_APP_HPP__
#define __REPLAY_APP_HPP__
#include "app_settings.hpp"
#include "radio_state.hpp"
#include "ui_widget.hpp"
#include "ui_navigation.hpp"
#include "ui_receiver.hpp"
#include "ui_freq_field.hpp"
#include "replay_thread.hpp"
#include "ui_spectrum.hpp"
#include "ui_transmitter.hpp"
#include <string>
#include <memory>
namespace ui {
class ReplayAppView : public View {
public:
ReplayAppView(NavigationView& nav);
~ReplayAppView();
void on_hide() override;
void set_parent_rect(const Rect new_parent_rect) override;
void focus() override;
std::string title() const override { return "Replay"; };
private:
NavigationView& nav_;
TxRadioState radio_state_{};
app_settings::SettingsManager settings_{
"tx_replay", app_settings::Mode::TX};
static constexpr ui::Dim header_height = 3 * 16;
uint32_t sample_rate = 0;
int32_t tx_gain{47};
bool rf_amp{true}; // aux private var to store temporal, Replay App rf_amp user selection.
static constexpr uint32_t baseband_bandwidth = 2500000;
const size_t read_size{16384};
const size_t buffer_count{3};
void on_file_changed(const std::filesystem::path& new_file_path);
void on_tx_progress(const uint32_t progress);
void toggle();
void start();
void stop(const bool do_loop);
bool is_active() const;
void set_ready();
void handle_replay_thread_done(const uint32_t return_code);
void file_error();
std::filesystem::path file_path{};
std::unique_ptr<ReplayThread> replay_thread{};
bool ready_signal{false};
Button button_open{
{0 * 8, 0 * 16, 10 * 8, 2 * 16},
"Open file"};
Text text_filename{
{11 * 8, 0 * 16, 12 * 8, 16},
"-"};
Text text_sample_rate{
{24 * 8, 0 * 16, 6 * 8, 16},
"-"};
Text text_duration{
{11 * 8, 1 * 16, 6 * 8, 16},
"-"};
ProgressBar progressbar{
{18 * 8, 1 * 16, 12 * 8, 16}};
TxFrequencyField field_frequency{
{0 * 8, 2 * 16},
nav_};
TransmitterView2 tx_view{
{11 * 8, 2 * 16},
/*short_ui*/ true};
Checkbox check_loop{
{21 * 8, 2 * 16},
4,
"Loop",
true};
ImageButton button_play{
{28 * 8, 2 * 16, 2 * 8, 1 * 16},
&bitmap_play,
Theme::getInstance()->fg_green->foreground,
Theme::getInstance()->fg_green->background};
spectrum::WaterfallView waterfall{};
MessageHandlerRegistration message_handler_replay_thread_error{
Message::ID::ReplayThreadDone,
[this](const Message* const p) {
const auto message = *reinterpret_cast<const ReplayThreadDoneMessage*>(p);
this->handle_replay_thread_done(message.return_code);
}};
MessageHandlerRegistration message_handler_fifo_signal{
Message::ID::RequestSignal,
[this](const Message* const p) {
const auto message = static_cast<const RequestSignalMessage*>(p);
if (message->signal == RequestSignalMessage::Signal::FillRequest) {
this->set_ready();
}
}};
MessageHandlerRegistration message_handler_tx_progress{
Message::ID::TXProgress,
[this](const Message* const p) {
const auto message = *reinterpret_cast<const TXProgressMessage*>(p);
this->on_tx_progress(message.progress);
}};
};
} /* namespace ui */
#endif /*__REPLAY_APP_HPP__*/

View File

@ -1,138 +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 "cpld_update.hpp"
#include "portapack.hpp"
#include "event_m0.hpp"
#include "ui_about.hpp"
#include "portapack_shared_memory.hpp"
#include "portapack_persistent_memory.hpp"
#include "lpc43xx_cpp.hpp"
#include <math.h>
#include <cstring>
using namespace lpc43xx;
using namespace portapack;
namespace ui {
// This is pretty much WaterfallView but in the opposite direction
CreditsWidget::CreditsWidget(
Rect parent_rect)
: Widget{parent_rect} {
}
void CreditsWidget::paint(Painter&) {
}
void CreditsWidget::on_show() {
clear();
const auto screen_r = screen_rect();
display.scroll_set_area(screen_r.top(), screen_r.bottom());
}
void CreditsWidget::on_hide() {
display.scroll_disable();
}
void CreditsWidget::new_row(
const std::array<Color, 240>& pixel_row) {
// Glitch be here (see comment in main.cpp)
const auto draw_y = display.scroll(-1);
display.draw_pixels(
{{0, draw_y - 1}, {240, 1}},
pixel_row);
}
void CreditsWidget::clear() {
display.fill_rectangle(
screen_rect(),
Theme::getInstance()->bg_darkest->background);
}
void AboutView::update() {
size_t i = 0;
std::array<Color, 240> pixel_row;
slow_down++;
if (slow_down % 3 < 2) return;
if (!timer) {
if (loop) {
credits_index = 0;
loop = false;
}
text = credits[credits_index].text;
timer = credits[credits_index].delay;
start_pos = credits[credits_index].start_pos;
if (timer < 0) {
timer = 240;
loop = true;
} else
timer += 16;
render_line = 0;
credits_index++;
} else
timer--;
if (render_line < 16) {
for (const auto c : text) {
const auto glyph = style().font.glyph(c);
const size_t start = (glyph.size().width() / 8) * render_line;
for (Dim c = 0; c < glyph.size().width(); c++) {
const auto pixel = glyph.pixels()[start + (c >> 3)] & (1U << (c & 0x7));
pixel_row[start_pos + i + c] = pixel ? Theme::getInstance()->bg_darkest->foreground : Theme::getInstance()->bg_darkest->background;
}
const auto advance = glyph.advance();
i += advance.x();
}
render_line++;
}
credits_display.new_row(pixel_row);
}
AboutView::AboutView(
NavigationView& nav) {
add_children({&credits_display,
&button_ok});
button_ok.on_select = [&nav](Button&) {
nav.pop();
};
}
void AboutView::focus() {
button_ok.focus();
}
} /* namespace ui */

View File

@ -1,119 +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 __UI_ABOUT_H__
#define __UI_ABOUT_H__
#include "ui_widget.hpp"
#include "ui_navigation.hpp"
#include <cstdint>
namespace ui {
class CreditsWidget : public Widget {
public:
CreditsWidget(Rect parent_rect);
void on_show() override;
void on_hide() override;
void paint(Painter&) override;
void new_row(const std::array<Color, 240>& pixel_row);
private:
void clear();
};
class AboutView : public View {
public:
AboutView(NavigationView& nav);
void focus() override;
std::string title() const override { return "About"; };
private:
void update();
uint8_t credits_index{0};
uint8_t render_line{0};
Coord start_pos{0};
uint8_t slow_down{0};
int32_t timer{0};
bool loop{false};
std::string text{};
typedef struct credits_t {
size_t start_pos;
std::string text;
int32_t delay;
} credits_t;
// TODO: Make this dinamically centered and parse \n as the delay value so it is easy to maintain
const credits_t credits[26] = {
// 012345678901234567890123456789
{60, "PortaPack Mayhem", 0},
{60, "PortaPack|HAVOC", 0},
{11 * 8, "Gurus J. Boone", 0},
{18 * 8, "M. Ossmann", 16},
{11 * 8, "HAVOC Furrtek", 16},
{7 * 8, "POCSAG rx T. Sailer", 0},
{18 * 8, "E. Oenal", 16},
{0 * 8, "Radiosonde infos F4GMU", 0},
{18 * 8, "RS1729", 16},
{4 * 8, "RDS waveform C. Jacquet", 16},
{7 * 8, "Xy. infos cLx", 16},
{2 * 8, "OOK scan trick Samy Kamkar", 16},
{7 * 8, "World map NASA", 16},
{0 * 8, "TouchTunes infos Notpike", 16},
{4 * 8, "Subaru infos Tom", 0},
{18 * 8, "Wimmenhove", 16},
{1 * 8, "GPS,TV,BTLE,NRF Shao", 24},
{6 * 8, "Thanks & donators", 16},
{1 * 8, "Rainer Matla Keld Norman", 0},
{1 * 8, " Giorgio C. DC1RDB", 0},
{1 * 8, " Sigmounte Waax", 0},
{1 * 8, " Windyoona Channels", 0},
{1 * 8, " F4GEV Pyr3x", 0},
{1 * 8, " HB3YOE", 24},
{11 * 8, "MMXVIII", -1}};
CreditsWidget credits_display{
{0, 16, 240, 240}};
Button button_ok{
{72, 272, 96, 24},
"OK"};
MessageHandlerRegistration message_handler_update{
Message::ID::DisplayFrameSync,
[this](const Message* const) {
this->update();
}};
};
} /* namespace ui */
#endif /*__UI_ABOUT_H__*/

View File

@ -1,413 +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 <ch.h>
#include "demofont.hpp"
#include "ymdata.hpp"
#include "cpld_update.hpp"
#include "portapack.hpp"
#include "audio.hpp"
#include "event_m0.hpp"
#include "ui_about.hpp"
#include "touch.hpp"
#include "sine_table.hpp"
#include "portapack_shared_memory.hpp"
#include "portapack_persistent_memory.hpp"
#include "lpc43xx_cpp.hpp"
#include <math.h>
#include <cstring>
using namespace lpc43xx;
using namespace portapack;
namespace ui {
void AboutView::on_show() {
transmitter_model.set_target_frequency(1337000000); // TODO: Change
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.enable();
baseband::set_audiotx_data(32, 50, false, 0);
// audio::headphone::set_volume(volume_t::decibel(0 - 99) + audio::headphone::volume_range().max);
}
void AboutView::render_video() {
uint8_t p, r, luma, chroma, cy;
ui::Color cc;
char ch;
float s;
// Send framebuffer to LCD. Gotta go fast !
display.render_box({30, 112}, {180, 72}, framebuffer);
// Clear framebuffer to black
memset(framebuffer, 0, 180 * 72 * sizeof(ui::Color));
// Drum hit palette animation
if (drum > 1) drum--;
// Render copper bars from Y buffer
for (p = 0; p < 72; p++) {
luma = copperbuffer[p] & 0x0F; // 0 is transparent
if (luma) {
chroma = copperbuffer[p] >> 4;
cc = ui::Color(std::min((coppercolor[chroma][0] / luma) * drum, 255), std::min((coppercolor[chroma][1] / luma) * drum, 255), std::min((coppercolor[chroma][2] / luma) * drum, 255));
for (r = 0; r < 180; r++)
framebuffer[(p * 180) + r] = cc;
}
}
// Scroll in/out state machine
if (anim_state == 0) {
// Scroll in
if (ofy < 8) {
ofy++;
anim_state = 0;
} else {
anim_state = 1;
}
if (ofx < (int16_t)(180 - (strlen(credits[credits_index].name) * 16) - 8)) {
ofx += 8;
anim_state = 0;
}
} else if (anim_state == 1) {
// Just wait
if (credits_timer == (30 * 3)) {
credits_timer = 0;
anim_state = 2;
} else {
credits_timer++;
}
} else {
// Scroll out
if (credits[credits_index].change == true) {
if (ofy > -24) {
ofy--;
anim_state = 2;
} else {
anim_state = 0;
}
} else {
anim_state = 0;
}
if (ofx < 180) {
ofx += 8;
anim_state = 2;
}
// Switch to next text
if (anim_state == 0) {
if (credits_index == 9)
credits_index = 0;
else
credits_index++;
ofx = -(strlen(credits[credits_index].name) * 16) - 16;
}
}
// Sine text ("role")
p = 0;
while ((ch = credits[credits_index].role[p])) {
draw_demoglyph({(ui::Coord)(8 + (p * 16)), (ui::Coord)(ofy + (sine_table_f32[((p * 16) + (phase >> 5)) & 0xFF] * 8))}, ch, paletteA);
p++;
}
// Scroll text (name)
p = 0;
while ((ch = credits[credits_index].name[p])) {
draw_demoglyph({(ui::Coord)(ofx + (p * 16)), 56}, ch, paletteB);
p++;
}
// Clear bars Y buffer
memset(copperbuffer, 0, 72);
// Render bars to Y buffer
for (p = 0; p < 5; p++) {
cy = copperbars[p];
for (r = 0; r < 16; r++)
copperbuffer[cy + r] = copperluma[r] + (p << 4);
}
// Animate bars positions
for (p = 0; p < 5; p++) {
s = sine_table_f32[((p * 32) + (phase / 24)) & 0xFF];
s += sine_table_f32[((p * 16) + (phase / 35)) & 0xFF];
copperbars[p] = 28 + (uint8_t)(s * 14);
}
phase += 128;
}
void AboutView::draw_demoglyph(ui::Point p, char ch, ui::Color* pal) {
uint8_t x, y, c, cl, cr;
uint16_t che;
int16_t lbx, il;
// Map ASCII to font bitmap
if ((ch >= 32) && (ch < 96))
che = char_map[ch - 32];
else
che = 0xFF;
if (che < 0xFF) {
che = (che * 128) + 48; // Start in bitmap
il = (180 * p.y) + p.x; // Start il framebuffer
for (y = 0; y < 16; y++) {
if (p.y + y >= 72) break; // Over bottom of framebuffer, abort
if (p.y + y >= 0) {
for (x = 0; x < 8; x++) {
c = demofont_bin[x + (y * 8) + che]; // Split byte in 2 4BPP pixels
cl = c >> 4;
cr = c & 0x0F;
lbx = p.x + (x * 2);
if (cl && (lbx < 180) && (lbx >= 0)) framebuffer[il] = pal[cl];
lbx++;
il++;
if (cr && (lbx < 180) && (lbx >= 0)) framebuffer[il] = pal[cr];
il++;
}
il += 180 - 16;
} else {
il += 180;
}
}
}
}
void AboutView::render_audio() {
uint8_t i, ymdata;
uint16_t ym_render_cnt;
// This is heavily inspired by MAME's ay8910.cpp and the YM2149's datasheet
// Render 1024 music samples
for (ym_render_cnt = 0; ym_render_cnt < 1024; ym_render_cnt++) {
// Update registers at 48000/960 = 50Hz
if (ym_sample_cnt == 0) {
// "Decompress" on the fly and update YM registers
for (i = 0; i < 14; i++) {
if (!ym_regs[i].cnt) {
// New run
ymdata = ymdata_bin[ym_regs[i].ptr++];
ym_regs[i].cnt = ymdata & 0x7F;
if (ymdata & 0x80) {
ym_regs[i].same = true;
ym_regs[i].value = ymdata_bin[ym_regs[i].ptr++];
} else {
ym_regs[i].same = false;
}
// Detect drum on channel B
if (i == 3)
if (ym_regs[3].value > 2) drum = 4;
}
if (ym_regs[i].same == false) {
ym_regs[i].value = ymdata_bin[ym_regs[i].ptr++];
if (i == 13) {
// Update envelope attributes
ym_env_att = (ym_regs[13].value & 4) ? 0x1F : 0x00;
if (!(ym_regs[13].value & 8)) {
ym_env_hold = 1;
ym_env_alt = ym_env_att;
} else {
ym_env_hold = ym_regs[13].value & 1;
ym_env_alt = ym_regs[13].value & 2;
}
// Reset envelope counter
ym_env_step = 0x1F;
ym_env_holding = 0;
ym_env_vol = (ym_env_step ^ ym_env_att);
}
}
ym_regs[i].cnt--;
}
ym_frame++;
}
// Square wave oscillators
// 2457600/16/48000 = 3.2, but 4 sounds better than 3...
for (i = 0; i < 3; i++) {
ym_osc_cnt[i] += 4;
if (ym_osc_cnt[i] >= (ym_regs[i * 2].value | ((ym_regs[(i * 2) + 1].value & 0x0f) << 8))) {
ym_osc_cnt[i] = 0;
ym_osc_out[i] ^= 1;
}
}
// Noise generator
ym_noise_cnt += 4;
if (ym_noise_cnt >= ((ym_regs[6].value & 0x1F) * 2)) {
ym_noise_cnt = 0;
ym_rng ^= (((ym_rng & 1) ^ ((ym_rng >> 3) & 1)) << 17);
ym_rng >>= 1;
}
// Mix tones and noise
for (i = 0; i < 3; i++)
ym_ch[i] = (ym_osc_out[i] | ((ym_regs[7].value >> i) & 1)) & ((ym_rng & 1) | ((ym_regs[7].value >> (i + 3)) & 1));
// Envelope generator
if (!ym_env_holding) {
ym_env_cnt += 8;
if (ym_env_cnt >= (ym_regs[11].value | (ym_regs[12].value << 8))) {
ym_env_cnt = 0;
ym_env_step--;
if (ym_env_step < 0) {
if (ym_env_hold) {
if (ym_env_alt)
ym_env_att ^= 0x1F;
ym_env_holding = 1;
ym_env_step = 0;
} else {
if (ym_env_alt && (ym_env_step & 0x20))
ym_env_att ^= 0x1F;
ym_env_step &= 0x1F;
}
}
}
}
ym_env_vol = (ym_env_step ^ ym_env_att);
ym_out = 0;
for (i = 0; i < 3; i++) {
if (ym_regs[i + 8].value & 0x10) {
// Envelope mode
ym_out += (ym_ch[i] ? ym_env_vol : 0);
} else {
// Fixed mode
ym_out += (ym_ch[i] ? (ym_regs[i + 8].value & 0x0F) : 0);
}
}
ym_buffer[ym_render_cnt] = (ym_out * 2) - 45;
if (ym_sample_cnt < 960) {
ym_sample_cnt++;
} else {
ym_sample_cnt = 0;
}
// Loop
if (ym_frame == ym_frames) ym_init();
}
}
void AboutView::update() {
if (framebuffer) {
// Update 1 out of 2 frames, 60Hz is very laggy
if (refresh_cnt & 1) render_video();
refresh_cnt++;
}
// Slowly increase volume to avoid jumpscare
if (headphone_vol < (70 << 2)) {
audio::headphone::set_volume(volume_t::decibel((headphone_vol / 4) - 99) + audio::headphone::volume_range().max);
headphone_vol++;
}
}
void AboutView::ym_init() {
uint8_t reg;
for (reg = 0; reg < 14; reg++) {
ym_regs[reg].cnt = 0;
// Pick up start pointers for each YM registers RLE blocks
ym_regs[reg].ptr = ((uint16_t)(ymdata_bin[(reg * 2) + 3]) << 8) + ymdata_bin[(reg * 2) + 2];
ym_regs[reg].same = false; // Useless ?
ym_regs[reg].value = 0; // Useless ?
}
ym_frame = 0;
}
AboutView::AboutView(
NavigationView& nav) {
uint8_t p, c;
baseband::run_image(portapack::spi_flash::image_tag_audio_tx);
add_children({{
&text_title,
&text_firmware,
&text_cpld_hackrf,
&text_cpld_hackrf_status,
&button_ok,
}});
if (cpld_hackrf_verify_eeprom()) {
text_cpld_hackrf_status.set(" OK");
} else {
text_cpld_hackrf_status.set("BAD");
}
// Politely ask for about 26kB
framebuffer = (ui::Color*)chHeapAlloc(0x0, 180 * 72 * sizeof(ui::Color));
if (framebuffer) {
memset(framebuffer, 0, 180 * 72 * sizeof(ui::Color));
// Copy original font palette
c = 0;
for (p = 0; p < 48; p += 3)
paletteA[c++] = ui::Color(demofont_bin[p], demofont_bin[p + 1], demofont_bin[p + 2]);
// Increase red in another one
c = 0;
for (p = 0; p < 48; p += 3)
paletteB[c++] = ui::Color(std::min(demofont_bin[p] + 64, 255), demofont_bin[p + 1], demofont_bin[p + 2]);
}
// Init YM synth
ym_frames = ((uint16_t)(ymdata_bin[1]) << 8) + ymdata_bin[0];
ym_init();
button_ok.on_select = [this, &nav](Button&) {
if (framebuffer) chHeapFree(framebuffer); // Do NOT forget this
nav.pop();
};
}
AboutView::~AboutView() {
transmitter_model.disable();
baseband::shutdown();
}
void AboutView::focus() {
button_ok.focus();
}
} /* namespace ui */

View File

@ -1,168 +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 __UI_ABOUT_H__
#define __UI_ABOUT_H__
#include "ui_widget.hpp"
#include "ui_menu.hpp"
#include "ui_navigation.hpp"
#include "transmitter_model.hpp"
#include "baseband_api.hpp"
#include <cstdint>
namespace ui {
class AboutView : public View {
public:
AboutView(NavigationView& nav);
~AboutView();
void on_show() override;
void focus() override;
private:
void ym_init();
void update();
void render_video();
void render_audio();
void draw_demoglyph(ui::Point p, char ch, ui::Color* pal);
uint16_t debug_cnt = 0;
typedef struct ymreg_t {
uint8_t value;
uint8_t cnt;
uint16_t ptr;
bool same;
} ymreg_t;
uint16_t headphone_vol = 5 << 2;
ymreg_t ym_regs[14];
uint16_t ym_frames;
uint16_t ym_frame;
uint8_t drum = 0;
uint16_t ym_osc_cnt[3];
uint32_t ym_rng = 1;
uint16_t ym_noise_cnt;
uint8_t ym_env_att, ym_env_hold, ym_env_alt, ym_env_holding, ym_env_vol;
int8_t ym_env_step;
uint16_t ym_env_cnt;
uint8_t ym_osc_out[3];
uint8_t ym_ch[3];
uint8_t ym_out;
uint16_t ym_sample_cnt = 0;
int8_t ym_buffer[1024];
uint8_t refresh_cnt;
ui::Color paletteA[16];
ui::Color paletteB[16];
ui::Color* framebuffer;
uint32_t phase = 0;
uint8_t copperbars[5] = {0};
uint8_t copperbuffer[72] = {0};
uint8_t anim_state = 0;
uint8_t credits_index = 0;
uint16_t credits_timer = 0;
int16_t ofx = -180, ofy = -24;
const uint8_t char_map[64] = {0xFF, 27, 46, 0xFF, 0xFF, 0xFF, 28, 45,
58, 59, 0xFF, 43, 40, 57, 26, 42,
29, 30, 31, 32, 33, 34, 35, 36,
37, 38, 41, 0xFF, 0xFF, 0xFF, 0xFF, 44,
0xFF, 0, 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
const uint8_t copperluma[16] = {8, 7, 6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6, 7, 8};
const uint8_t coppercolor[5][3] = {{255, 0, 0},
{0, 255, 0},
{0, 0, 255},
{255, 0, 255},
{255, 255, 0}};
typedef struct credits_t {
char role[12];
char name[12];
bool change;
} credits_t;
// 0123456789A 0123456789A
const credits_t credits[10] = {{"GURUS", "J. BOONE", false},
{"GURUS", "M. OSSMANN", true},
{"BUGS", "FURRTEK", true},
{"RDS WAVE", "C. JACQUET", true},
{"POCSAG RX", "T. SAILER", false},
{"POCSAG RX", "E. OENAL", true},
{"XYLOS DATA", "CLX", true},
{"GREETS TO", "SIGMOUNTE", false},
{"GREETS TO", "WINDYOONA", true},
{"THIS MUSIC", "BIG ALEC", true}};
Text text_title{
{100, 32, 40, 16},
"About",
};
Text text_firmware{
{0, 236, 240, 16},
"Version " VERSION_STRING,
};
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"};
MessageHandlerRegistration message_handler_update{
Message::ID::DisplayFrameSync,
[this](const Message* const) {
this->update();
}};
MessageHandlerRegistration message_handler_fifo_signal{
Message::ID::FIFOSignal,
[this](const Message* const p) {
const auto message = static_cast<const FIFOSignalMessage*>(p);
if (message->signaltype == 1) {
this->render_audio();
baseband::set_fifo_data(ym_buffer);
}
}};
};
} /* namespace ui */
#endif /*__UI_ABOUT_H__*/

View File

@ -1,288 +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 "ui_numbers.hpp"
#include "string_format.hpp"
#include "portapack.hpp"
#include "hackrf_hal.hpp"
#include "portapack_shared_memory.hpp"
#include <cstring>
#include <stdio.h>
using namespace portapack;
namespace ui {
// TODO: This app takes way too much space, find a way to shrink/simplify or make it an SD card module (loadable)
void NumbersStationView::focus() {
if (file_error)
nav_.display_modal("No voices", "No valid voices found in\nthe /numbers directory.", ABORT);
else
button_exit.focus();
}
NumbersStationView::~NumbersStationView() {
transmitter_model.disable();
baseband::shutdown();
}
NumbersStationView::wav_file_t* NumbersStationView::get_wav(uint32_t index) {
return &current_voice->available_wavs[index];
}
void NumbersStationView::prepare_audio() {
uint8_t code;
wav_file_t* wav_file;
if (sample_counter >= sample_length) {
if (segment == ANNOUNCE) {
if (!announce_loop) {
code_index = 0;
segment = MESSAGE;
} else {
wav_file = get_wav(11);
reader->open(current_voice->dir + file_names[wav_file->index].name + ".wav");
sample_length = wav_file->length;
announce_loop--;
}
}
if (segment == MESSAGE) {
if (code_index == 25) {
transmitter_model.disable();
return;
}
code = symfield_code.get_offset(code_index);
if (code >= 10) {
memset(audio_buffer, 0, 1024);
if (code == 10) {
pause = 11025; // p: 0.25s @ 44100Hz
} else if (code == 11) {
pause = 33075; // P: 0.75s @ 44100Hz
} else if (code == 12) {
transmitter_model.disable();
return;
}
} else {
wav_file = get_wav(code);
reader->open(current_voice->dir + file_names[code].name + ".wav");
sample_length = wav_file->length;
}
code_index++;
}
sample_counter = 0;
}
if (!pause) {
auto bytes_read = reader->read(audio_buffer, 1024).value();
// Unsigned to signed, pretty stupid :/
for (size_t n = 0; n < bytes_read; n++)
audio_buffer[n] -= 0x80;
for (size_t n = bytes_read; n < 1024; n++)
audio_buffer[n] = 0;
sample_counter += 1024;
} else {
if (pause >= 1024) {
pause -= 1024;
} else {
sample_counter = sample_length;
pause = 0;
}
}
baseband::set_fifo_data(audio_buffer);
}
void NumbersStationView::start_tx() {
// sample_length = sound_sizes[10]; // Announce
sample_counter = sample_length;
code_index = 0;
announce_loop = 2;
segment = ANNOUNCE;
prepare_audio();
transmitter_model.set_rf_amp(true);
transmitter_model.enable();
baseband::set_audiotx_data(
(1536000 / 44100) - 1, // TODO: Read wav file's samplerate
12000,
1,
false,
0);
}
void NumbersStationView::on_tick_second() {
armed_blink = not armed_blink;
if (armed_blink)
check_armed.set_style(Theme::getInstance()->fg_red);
else
check_armed.set_style(&style());
check_armed.set_dirty();
}
void NumbersStationView::on_voice_changed(size_t index) {
std::string code_list;
for (const auto& wavs : voices[index].available_wavs)
code_list += wavs.code;
symfield_code.set_symbol_list(code_list);
current_voice = &voices[index];
}
bool NumbersStationView::check_wav_validity(const std::string dir, const std::string file) {
if (reader->open("/numbers/" + dir + "/" + file)) {
// Check format (mono, 8 bits)
if ((reader->channels() == 1) && (reader->bits_per_sample() == 8))
return true;
else
return false;
} else
return false;
}
NumbersStationView::NumbersStationView(
NavigationView& nav)
: nav_(nav) {
std::vector<std::filesystem::path> directory_list;
using option_t = std::pair<std::string, int32_t>;
using options_t = std::vector<option_t>;
options_t voice_options;
voice_t temp_voice{};
bool valid;
uint32_t c;
// uint8_t y, m, d, dayofweek;
reader = std::make_unique<WAVFileReader>();
// Search for valid voice directories
directory_list = scan_root_directories("/numbers");
if (!directory_list.size()) {
file_error = true;
return;
}
for (const auto& dir : directory_list) {
c = 0;
for (const auto& file_name : file_names) {
valid = check_wav_validity(dir.string(), file_name.name + ".wav");
if ((!valid) && (file_name.required)) {
temp_voice.available_wavs.clear();
break; // Invalid required file means invalid voice
} else if (valid) {
temp_voice.available_wavs.push_back({file_name.code, c++, 0, 0}); // TODO: Needs length and samplerate
}
}
if (!temp_voice.available_wavs.empty()) {
// Voice can be used, are there accent files ?
c = 0;
for (const auto& file_name : file_names) {
valid = check_wav_validity(dir.string(), file_name.name + "a.wav");
if ((!valid) && (file_name.required)) {
c = 0;
break; // Invalid required file means accents can't be used
} else if (valid) {
c++;
}
}
temp_voice.accent = c ? true : false;
temp_voice.dir = dir.string();
voices.push_back(temp_voice);
}
}
if (voices.empty()) {
file_error = true;
return;
}
baseband::run_image(portapack::spi_flash::image_tag_audio_tx);
add_children({&labels,
&symfield_code,
&check_armed,
&options_voices,
&text_voice_flags,
//&button_tx_now,
&button_exit});
for (const auto& voice : voices)
voice_options.emplace_back(voice.dir.substr(0, 4), 0);
options_voices.set_options(voice_options);
options_voices.on_change = [this](size_t i, int32_t) {
this->on_voice_changed(i);
};
options_voices.set_selected_index(0);
check_armed.set_value(false);
check_armed.on_select = [this](Checkbox&, bool v) {
if (v) {
armed_blink = false;
signal_token_tick_second = rtc_time::signal_tick_second += [this]() {
this->on_tick_second();
};
} else {
check_armed.set_style(&style());
rtc_time::signal_tick_second -= signal_token_tick_second;
}
};
// DEBUG
symfield_code.set_offset(0, 10);
symfield_code.set_offset(1, 3);
symfield_code.set_offset(2, 4);
symfield_code.set_offset(3, 11);
symfield_code.set_offset(4, 6);
symfield_code.set_offset(5, 1);
symfield_code.set_offset(6, 9);
symfield_code.set_offset(7, 7);
symfield_code.set_offset(8, 8);
symfield_code.set_offset(9, 0);
symfield_code.set_offset(10, 12); // End
/*
dayofweek = rtc_time::current_day_of_week();
text_title.set(day_of_week[dayofweek]);
*/
button_exit.on_select = [&nav](Button&) {
nav.pop();
};
}
} /* namespace ui */

View File

@ -1,175 +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 __UI_NUMBERS_H__
#define __UI_NUMBERS_H__
#include "ui.hpp"
#include "ui_widget.hpp"
#include "ui_receiver.hpp"
#include "ui_navigation.hpp"
#include "rtc_time.hpp"
#include "clock_manager.hpp"
#include "baseband_api.hpp"
#include "utility.hpp"
#include "message.hpp"
#include "file.hpp"
#include "io_wave.hpp"
#include "radio_state.hpp"
namespace ui {
class NumbersStationView : public View {
public:
NumbersStationView(NavigationView& nav);
~NumbersStationView();
NumbersStationView(const NumbersStationView&) = delete;
NumbersStationView(NumbersStationView&&) = delete;
NumbersStationView& operator=(const NumbersStationView&) = delete;
NumbersStationView& operator=(NumbersStationView&&) = delete;
void focus() override;
std::string title() const override { return "Station"; };
private:
NavigationView& nav_;
TxRadioState radio_state_{
0 /* frequency */,
1750000 /* bandwidth */,
1536000 /* sampling rate */
};
// Sequencing state machine
enum segments {
IDLE = 0,
ANNOUNCE,
MESSAGE,
SIGNOFF
};
typedef struct {
char code;
uint32_t index;
uint32_t length;
uint32_t samplerate;
} wav_file_t;
struct voice_t {
std::string dir;
std::vector<wav_file_t> available_wavs;
bool accent;
};
std::vector<voice_t> voices{};
voice_t* current_voice{};
struct wav_file_list_t {
std::string name;
bool required;
char code;
};
const std::vector<wav_file_list_t> file_names = {
{"0", true, '0'},
{"1", true, '1'},
{"2", true, '2'},
{"3", true, '3'},
{"4", true, '4'},
{"5", true, '5'},
{"6", true, '6'},
{"7", true, '7'},
{"8", true, '8'},
{"9", true, '9'},
{"announce", false, 'A'}};
segments segment{IDLE};
bool armed{false};
bool file_error{false};
// const uint8_t month_table[12] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
// const char * day_of_week[7] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
std::unique_ptr<WAVFileReader> reader{};
uint8_t code_index{0}, announce_loop{0};
uint32_t sample_counter{0};
uint32_t sample_length{0};
int8_t audio_buffer[1024]{};
uint32_t pause{0};
bool armed_blink{false};
SignalToken signal_token_tick_second{};
wav_file_t* get_wav(uint32_t index);
bool check_wav_validity(const std::string dir, const std::string file);
void on_voice_changed(size_t index);
void on_tick_second();
void prepare_audio();
void start_tx();
Labels labels{
{{2 * 8, 5 * 8}, "Voice: Flags:", Theme::getInstance()->fg_light->foreground},
{{1 * 8, 8 * 8}, "Code:", Theme::getInstance()->fg_light->foreground}};
OptionsField options_voices{
{8 * 8, 1 * 8},
4,
{}};
Text text_voice_flags{
{19 * 8, 1 * 8, 2 * 8, 16},
""};
SymField symfield_code{
{1 * 8, 10 * 8},
25,
SymField::Type::Custom};
Checkbox check_armed{
{2 * 8, 13 * 16},
5,
"Armed"};
/*
Button button_tx_now {
{ 18 * 8, 13 * 16, 10 * 8, 32 },
"TX now"};
*/
Button button_exit{
{21 * 8, 16 * 16, 64, 32},
"Exit"};
MessageHandlerRegistration message_handler_fifo_signal{
Message::ID::RequestSignal,
[this](const Message* const p) {
const auto message = static_cast<const RequestSignalMessage*>(p);
if (message->signal == RequestSignalMessage::Signal::FillRequest) {
this->prepare_audio();
}
}};
};
} /* namespace ui */
#endif /*__UI_NUMBERS_H__*/

View File

@ -1,185 +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 "ui_nuoptix.hpp"
#include "ch.h"
#include "portapack.hpp"
#include "lfsr_random.hpp"
#include "string_format.hpp"
#include "portapack_shared_memory.hpp"
#include <cstring>
#include <vector>
using namespace portapack;
namespace ui {
void NuoptixView::focus() {
number_timecode.focus();
}
NuoptixView::~NuoptixView() {
transmitter_model.disable();
baseband::shutdown();
}
void NuoptixView::on_tx_progress(const uint32_t progress, const bool done) {
if (done)
transmit(false);
else
progressbar.set_value(progress);
}
void NuoptixView::transmit(bool setup) {
uint8_t mod, tone_code;
uint8_t c;
uint8_t dtmf_message[6];
rtc::RTC datetime;
if (!tx_mode) {
transmitter_model.disable();
return;
}
if (tx_mode == IMPROVISE)
timecode = lfsr_iterate(timecode) % 1999; // Could be 9999 but that would be one long audio track !
if (setup) {
progressbar.set_max(6 * 2);
if (tx_mode == IMPROVISE) {
// Seed from RTC
rtcGetTime(&RTCD1, &datetime);
timecode = datetime.day() + datetime.second();
} else {
timecode = number_timecode.value();
}
transmitter_model.set_rf_amp(true);
transmitter_model.enable();
dtmf_message[0] = '*'; // "Pre-tone for restart" method #1
dtmf_message[1] = 'A'; // "Restart" method #1
} else {
dtmf_message[0] = '#';
dtmf_message[1] = (timecode / 1000) % 10;
chThdSleepMilliseconds(92); // 141-49ms
number_timecode.set_value(timecode);
}
progressbar.set_value(0);
dtmf_message[2] = (timecode / 100) % 10;
dtmf_message[3] = (timecode / 10) % 10;
dtmf_message[4] = timecode % 10;
mod = 0;
for (c = 1; c < 5; c++)
if (dtmf_message[c] <= 9)
mod += dtmf_message[c];
mod = 10 - (mod % 10);
if (mod == 10) mod = 0; // Is this right ?
text_mod.set("Mod: " + to_string_dec_uint(mod));
dtmf_message[5] = mod;
for (c = 0; c < 6; c++) {
tone_code = dtmf_message[c];
if (tone_code == 'A')
tone_code = 10;
else if (tone_code == 'B')
tone_code = 11;
else if (tone_code == 'C')
tone_code = 12;
else if (tone_code == 'D')
tone_code = 13;
else if (tone_code == '#')
tone_code = 14;
else if (tone_code == '*')
tone_code = 15;
shared_memory.bb_data.tones_data.message[c * 2] = tone_code;
shared_memory.bb_data.tones_data.message[c * 2 + 1] = 0xFF; // Silence
}
for (c = 0; c < 16; c++) {
baseband::set_tone(c * 2, dtmf_deltas[c][0], NUOPTIX_TONE_LENGTH);
baseband::set_tone(c * 2 + 1, dtmf_deltas[c][1], NUOPTIX_TONE_LENGTH);
}
shared_memory.bb_data.tones_data.silence = NUOPTIX_TONE_LENGTH; // 49ms tone, 49ms space
audio::set_rate(audio::Rate::Hz_24000);
baseband::set_tones_config(transmitter_model.channel_bandwidth(), 0, 6 * 2, true, true);
timecode++;
}
NuoptixView::NuoptixView(
NavigationView& nav) {
baseband::run_image(portapack::spi_flash::image_tag_tones);
add_children({&number_timecode,
&text_timecode,
&text_mod,
&progressbar,
&tx_view});
number_timecode.set_value(1);
tx_view.on_edit_frequency = [this, &nav]() {
auto new_view = nav.push<FrequencyKeypadView>(transmitter_model.target_frequency());
new_view->on_changed = [this](rf::Frequency f) {
transmitter_model.set_target_frequency(f);
};
};
tx_view.on_start = [this]() {
tx_view.set_transmitting(true);
tx_mode = NORMAL;
transmit(true);
};
tx_view.on_stop = [this]() {
tx_view.set_transmitting(false);
tx_mode = IDLE;
};
/*button_impro.on_select = [this](Button&){
if (tx_mode == IMPROVISE) {
tx_mode = IDLE;
button_impro.set_text("IMPROVISE");
} else if (tx_mode == IDLE) {
tx_mode = IMPROVISE;
button_impro.set_text("STOP");
transmit(true);
}
};*/
}
} // namespace ui

View File

@ -1,109 +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 __UI_NUOPTIX_H__
#define __UI_NUOPTIX_H__
#include "ui.hpp"
#include "ui_widget.hpp"
#include "baseband_api.hpp"
#include "ui_navigation.hpp"
#include "ui_transmitter.hpp"
#include "rtc_time.hpp"
#include "tonesets.hpp"
#include "message.hpp"
#include "volume.hpp"
#include "audio.hpp"
#include "radio_state.hpp"
#define NUOPTIX_TONE_LENGTH ((TONES_SAMPLERATE * 0.049) - 1) // 49ms
namespace ui {
class NuoptixView : public View {
public:
NuoptixView(NavigationView& nav);
~NuoptixView();
void focus() override;
std::string title() const override { return "Nuoptix sync"; };
private:
enum tx_modes {
IDLE = 0,
NORMAL,
IMPROVISE
};
TxRadioState radio_state_{
0 /* frequency */,
1750000 /* bandwidth */,
1536000 /* sampling rate */
};
tx_modes tx_mode{IDLE};
void transmit(bool setup);
void on_tx_progress(const uint32_t progress, const bool done);
uint32_t timecode{0};
Text text_timecode{
{10 * 8, 2 * 16, 9 * 8, 16},
"Timecode:"};
NumberField number_timecode{
{13 * 8, 3 * 16},
4,
{1, 9999},
1,
'0'};
Text text_mod{
{10 * 8, 5 * 16, 6 * 8, 16},
"Mod: "};
ProgressBar progressbar{
{16, 14 * 16, 208, 16}};
/*Button button_impro {
{ 64, 184, 112, 40 },
"IMPROVISE"
};*/
TransmitterView tx_view{
16 * 16,
10000,
15};
MessageHandlerRegistration message_handler_tx_progress{
Message::ID::TXProgress,
[this](const Message* const p) {
const auto message = *reinterpret_cast<const TXProgressMessage*>(p);
this->on_tx_progress(message.progress, message.done);
}};
};
} /* namespace ui */
#endif /*__UI_NUOPTIX_H__*/

View File

@ -28,7 +28,6 @@
#include "file.hpp"
#include "file_reader.hpp"
#include "tone_key.hpp"
#include "replay_app.hpp"
#include "string_format.hpp"
#include "ui_fileman.hpp"
#include "io_file.hpp"

View File

@ -1,106 +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 "ui_script.hpp"
#include "portapack.hpp"
#include "event_m0.hpp"
#include <cstring>
using namespace portapack;
namespace ui {
void ScriptView::on_frequency_select() {
// button_edit_freq.focus();
}
void ScriptView::on_edit_freq(rf::Frequency f) {
(void)f;
// frequencies[menu_view.highlighted()].value = f;
setup_list();
}
void ScriptView::on_edit_desc(NavigationView& nav) {
(void)nav;
}
void ScriptView::on_delete() {
// frequencies.erase(frequencies.begin() + menu_view.highlighted());
setup_list();
}
void ScriptView::setup_list() {
// size_t n;
menu_view.clear();
/*for (n = 0; n < frequencies.size(); n++) {
menu_view.add_item({ freqman_item_string(frequencies[n]), Theme::getInstance()->bg_darkest->foreground, nullptr, [this](){ on_frequency_select(); } });
}*/
menu_view.set_parent_rect({0, 0, 240, 168});
menu_view.set_highlighted(menu_view.highlighted()); // Refresh
}
void ScriptView::focus() {
menu_view.focus();
}
ScriptView::ScriptView(
NavigationView& nav) {
add_children({&menu_view,
&text_edit,
&button_edit_freq,
&button_edit_desc,
&button_del,
&button_exit});
setup_list();
button_edit_freq.on_select = [this, &nav](Button&) {
/*auto new_view = nav.push<FrequencyKeypadView>(frequencies[menu_view.highlighted()].value);
new_view->on_changed = [this](rf::Frequency f) {
on_edit_freq(f);
};*/
};
button_edit_desc.on_select = [this, &nav](Button&) {
on_edit_desc(nav);
};
button_del.on_select = [this, &nav](Button&) {
nav.push<ModalMessageView>("Confirm", "Are you sure?", YESNO,
[this](bool choice) {
if (choice) {
on_delete();
}
});
};
button_exit.on_select = [this, &nav](Button&) {
nav.pop();
};
}
} // namespace ui

View File

@ -1,88 +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 "ui.hpp"
#include "ui_widget.hpp"
#include "ui_painter.hpp"
#include "ui_menu.hpp"
#include "ui_navigation.hpp"
#include "ui_receiver.hpp"
#include "ui_textentry.hpp"
#include "rtc_time.hpp"
namespace ui {
enum script_keyword {
STOP = 0,
WAIT_N,
WAIT_RTC,
IF,
LOOP,
END,
TX,
RX
};
struct script_line {
script_keyword keyword;
};
class ScriptView : public View {
public:
ScriptView(NavigationView& nav);
void focus() override;
std::string title() const override { return "Script editor"; };
private:
void on_frequency_select();
void on_edit_freq(rf::Frequency f);
void on_edit_desc(NavigationView& nav);
void on_delete();
void setup_list();
std::vector<script_line> script{};
MenuView menu_view{
{0, 0, 240, 168},
true};
Text text_edit{
{16, 194, 5 * 8, 16},
"Edit:"};
Button button_edit_freq{
{16, 194 + 16, 88, 32},
"Frequency"};
Button button_edit_desc{
{16, 194 + 16 + 34, 88, 32},
"Description"};
Button button_del{
{160, 192, 72, 64},
"Delete"};
Button button_exit{
{160, 264, 72, 32},
"Exit"};
};
} /* namespace ui */

View File

@ -1,54 +0,0 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2018 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 "ui_tone_search.hpp"
#include "baseband_api.hpp"
#include "string_format.hpp"
using namespace portapack;
namespace ui {
void ToneSearchView::focus() {
// field_frequency_min.focus();
}
ToneSearchView::~ToneSearchView() {
receiver_model.disable();
baseband::shutdown();
}
ToneSearchView::ToneSearchView(
NavigationView& nav)
: nav_(nav) {
// baseband::run_image(portapack::spi_flash::image_tag_wideband_spectrum);
add_children({
&labels,
&field_lna,
&field_vga,
&field_rf_amp,
});
}
} /* namespace ui */

View File

@ -1,68 +0,0 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2018 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 "receiver_model.hpp"
#include "ui_receiver.hpp"
namespace ui {
class ToneSearchView : public View {
public:
ToneSearchView(NavigationView& nav);
~ToneSearchView();
void focus() override;
std::string title() const override { return "Tone search"; };
private:
NavigationView& nav_;
Labels labels{
{{0 * 8, 0 * 8}, "LNA: VGA: AMP:", Theme::getInstance()->fg_light->foreground}};
LNAGainField field_lna{
{4 * 8, 0 * 16}};
VGAGainField field_vga{
{11 * 8, 0 * 16}};
RFAmpField field_rf_amp{
{18 * 8, 0 * 16}};
/*
MessageHandlerRegistration message_handler_frame_sync {
Message::ID::DisplayFrameSync,
[this](const Message* const) {
if( this->fifo ) {
ChannelSpectrum channel_spectrum;
while( fifo->out(channel_spectrum) ) {
this->on_channel_spectrum(channel_spectrum);
}
}
this->do_timers();
}
};*/
};
} /* namespace ui */

View File

@ -1,46 +0,0 @@
/*
* Copyright (C) 2017 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2017 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 "emu_cc1101.hpp"
namespace cc1101 {
void CC1101Emu::whitening_init() {
whitening_pn = 0x1FF;
}
// See TI app note DN509
uint8_t CC1101Emu::whiten_byte(uint8_t byte) {
uint_fast8_t new_bit;
byte ^= (whitening_pn & 0xFF);
for (size_t step = 0; step < 8; step++) {
new_bit = (whitening_pn & 1) ^ ((whitening_pn >> 5) & 1);
whitening_pn >>= 1;
whitening_pn |= (new_bit << 8);
}
return byte;
}
} /* namespace cc1101 */

View File

@ -96,7 +96,6 @@ Continuous (Fox-oring)
// Multimon-style stuff:
// TODO: DMR detector
// TODO: GSM channel detector
// TODO: Playdead amnesia and login
// TODO: Setup: Play dead by default ? Enable/disable ?
// Old or low-priority stuff:
@ -106,7 +105,6 @@ Continuous (Fox-oring)
// TODO: Check more OOK encoders
// BUG (fixed ?): No audio in about when shown second time
// TODO: Show MD5 mismatches for modules not found, etc...
// TODO: Module name/filename in modules.hpp to indicate requirement in case it's not found ui_loadmodule
// BUG: Description doesn't show up first time going to system>module info (UI drawn on top)
// TODO: Two players tic-tac-toe
// TODO: Analog TV pong game

View File

@ -1,344 +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 "ui_handwrite.hpp"
#include "portapack.hpp"
#include "hackrf_hal.hpp"
#include "portapack_shared_memory.hpp"
#include <algorithm>
using namespace portapack;
namespace ui {
void HandWriteView::paint(Painter& painter) {
_painter = &painter;
}
HandWriteView::HandWriteView(
NavigationView& nav,
std::string* str,
size_t max_length)
: TextEntryView(nav, str, max_length) {
size_t n;
// Handwriting alphabet definition here
handwriting = &handwriting_unistroke;
add_children({&button_case});
const auto button_fn = [this](Button& button) {
this->on_button(button);
};
n = 0;
for (auto& button : num_buttons) {
add_child(&button);
button.on_select = button_fn;
button.set_parent_rect({static_cast<Coord>(n * 24),
static_cast<Coord>(236),
24, 28});
const std::string label{
(char)(n + '0')};
button.set_text(label);
button.id = n + '0';
n++;
}
n = 0;
for (auto& button : special_buttons) {
add_child(&button);
button.on_select = button_fn;
button.set_parent_rect({static_cast<Coord>(50 + n * 24),
static_cast<Coord>(270),
24, 28});
const std::string label{
(char)(special_chars[n])};
button.set_text(label);
button.id = special_chars[n];
n++;
}
button_case.on_select = [this, &nav](Button&) {
if (_lowercase == true) {
_lowercase = false;
button_case.set_text("LC");
} else {
_lowercase = true;
button_case.set_text("UC");
}
};
button_ok.on_select = [this, &nav](Button&) {
if (on_changed)
on_changed(_str);
nav.pop();
};
update_text();
}
bool HandWriteView::on_touch(const TouchEvent event) {
if (event.type == ui::TouchEvent::Type::Start) {
stroke_index = 0;
move_wait = 3;
tracing = true;
}
if (event.type == ui::TouchEvent::Type::End) {
tracing = false;
guess_letter();
}
if (event.type == ui::TouchEvent::Type::Move) {
if (tracing)
current_pos = event.point;
}
return true;
}
void HandWriteView::clear_zone(const Color color, const bool flash) {
display.fill_rectangle(
{{0, 32}, {240, 216}},
color);
if (flash) {
flash_timer = 8;
} else {
// Draw grid
_painter->draw_rectangle(
{{0, 32}, {80, 216}},
Color::grey());
_painter->draw_rectangle(
{{80, 32}, {80, 216}},
Color::grey());
_painter->draw_rectangle(
{{160, 32}, {80, 216}},
Color::grey());
_painter->draw_rectangle(
{{0, 104}, {240, 72}},
Color::grey());
}
}
void HandWriteView::guess_letter() {
uint32_t symbol, match, count, stroke_idx, stroke_data;
Condition cond;
Direction dir;
bool matched;
// Letter guessing
if (stroke_index) {
for (symbol = 0; symbol < handwriting->letter_count; symbol++) {
count = handwriting->letter[symbol].count;
matched = false;
if (count) {
// We have a count match to do
if ((count == 1) && (stroke_index == 1)) matched = true;
if ((count == 2) && (stroke_index == 2)) matched = true;
if ((count == 3) && (stroke_index > 2)) matched = true;
} else {
matched = true;
}
if (matched) {
for (match = 0; match < 3; match++) {
cond = handwriting->letter[symbol].match[match].cond;
dir = handwriting->letter[symbol].match[match].dir;
if ((cond != cond_empty) && (dir != dir_empty)) {
if (cond == last) {
if (stroke_index)
stroke_idx = stroke_index - 1;
else
stroke_idx = 0;
} else if (cond == stroke_a)
stroke_idx = 0;
else if (cond == stroke_b)
stroke_idx = 1;
else if (cond == stroke_c)
stroke_idx = 2;
else
stroke_idx = 3;
if (stroke_idx >= stroke_index) break;
stroke_data = stroke_list[stroke_idx];
if ((dir & 0xF0) == 0xF0) {
if ((dir & 0x0F) != (stroke_data & 0x0F)) break;
} else if ((dir & 0x0F) == 0x0F) {
if ((dir & 0xF0) != (stroke_data & 0xF0)) break;
} else {
if (dir != (int32_t)stroke_data) break;
}
}
}
if (match == 3)
break;
else
matched = false;
}
}
if (matched) {
if (symbol) {
if (_lowercase)
char_add('a' + symbol - 1);
else
char_add('A' + symbol - 1);
clear_zone(Color::green(), true); // Green flash
} else {
if (_cursor_pos) {
char_delete();
clear_zone(Color::yellow(), true); // Yellow flash
} else {
clear_zone(Color::red(), true); // Red flash
}
}
} else {
clear_zone(Color::red(), true); // Red flash
}
} else {
// Short tap is space
char_add(' ');
clear_zone(Color::green(), true); // Green flash
}
update_text();
stroke_index = 0;
}
void HandWriteView::add_stroke(uint8_t dir) {
if (stroke_index < 8) {
stroke_list[stroke_index] = dir;
stroke_index++;
} else {
guess_letter();
}
}
void HandWriteView::sample_pen() {
int16_t diff_x, diff_y;
uint8_t dir, dir_ud, dir_lr, stroke_prev;
draw_cursor();
if (flash_timer) {
if (flash_timer == 1) clear_zone(Color::black(), false);
flash_timer--;
}
if (!(sample_skip & 1)) {
if (tracing) {
if (move_wait) {
move_wait--; // ~100ms delay to get rid of jitter from touch start
} else {
diff_x = current_pos.x() - last_pos.x();
diff_y = current_pos.y() - last_pos.y();
if (current_pos.y() <= 240) {
display.fill_rectangle(
{{current_pos.x(), current_pos.y()}, {4, 4}},
Color::grey());
}
dir = 0; // UL by default
if (abs(diff_x) > 7) {
if (diff_x > 0)
dir |= 0x01; // R
} else {
dir |= 0x02; // ?
}
if (abs(diff_y) > 7) {
if (diff_y > 0)
dir |= 0x10; // D
} else {
dir |= 0x20; // ?
}
// Need at least two identical directions to validate stroke
if ((dir & 0x11) == (dir_prev & 0x11))
dir_cnt++;
else
dir_cnt = 0;
dir_prev = dir;
if (dir_cnt > 1) {
dir_cnt = 0;
if (stroke_index) {
if ((stroke_list[stroke_index - 1] != dir) && (dir != 0x22)) {
// Register stroke if different from last one
dir_ud = (dir & 0xF0);
dir_lr = (dir & 0x0F);
stroke_prev = stroke_list[stroke_index - 1];
if (dir_ud == 0x20) {
// LR changed
if ((stroke_prev & 0x0F) != dir_lr) add_stroke(dir);
} else if (dir_lr == 0x02) {
// UD changed
if ((stroke_prev & 0xF0) != dir_ud) add_stroke(dir);
} else {
// Add direction
if (((stroke_prev & 0xF0) == 0x20) && (dir_ud != 0x20)) {
// Add UD
if ((stroke_prev & 0x0F) == dir_lr) {
// Replace totally
stroke_list[stroke_index - 1] = dir;
} else if (dir_lr == 0x02) {
// Merge UD
stroke_list[stroke_index - 1] = dir_ud | (stroke_prev & 0x0F);
} else {
add_stroke(dir);
}
} else if (((stroke_prev & 0x0F) == 0x02) && (dir_lr != 0x02)) {
// Add LR
if ((stroke_prev & 0xF0) == dir_ud) {
// Replace totally
stroke_list[stroke_index - 1] = dir;
} else if (dir_ud == 0x20) {
// Merge LR
stroke_list[stroke_index - 1] = dir_lr | (stroke_prev & 0xF0);
} else {
add_stroke(dir);
}
} else {
add_stroke(dir);
}
}
}
} else {
// Register first stroke
if (dir != 0x22) add_stroke(dir);
}
}
}
last_pos = current_pos;
}
}
sample_skip++;
}
void HandWriteView::on_show() {
clear_zone(Color::black(), false);
}
void HandWriteView::on_button(Button& button) {
char_add(button.id);
update_text();
}
} // namespace ui

View File

@ -1,88 +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 __UNISTROKE_H__
#define __UNISTROKE_H__
#include "ui.hpp"
#include "ui_widget.hpp"
#include "ui_painter.hpp"
#include "ui_textentry.hpp"
#include "unistroke.hpp"
namespace ui {
class HandWriteView : public TextEntryView {
public:
HandWriteView(NavigationView& nav, std::string* str, size_t max_length);
HandWriteView(const HandWriteView&) = delete;
HandWriteView(HandWriteView&&) = delete;
HandWriteView& operator=(const HandWriteView&) = delete;
HandWriteView& operator=(HandWriteView&&) = delete;
void paint(Painter& painter) override;
void on_show() override;
bool on_touch(const TouchEvent event) override;
private:
const char special_chars[5] = {'\'', '.', '?', '!', '='};
const HandWriting* handwriting{};
Painter* _painter{};
uint8_t dir_cnt{0};
uint8_t dir_prev{0};
uint8_t flash_timer{0};
bool tracing{false};
uint8_t stroke_index{0};
uint8_t sample_skip{0}, move_wait{0};
uint8_t stroke_list[8];
Point start_pos{}, current_pos{}, last_pos{};
bool _lowercase = false;
void sample_pen();
void add_stroke(uint8_t dir);
void guess_letter();
void clear_zone(const Color color, const bool flash);
void on_button(Button& button);
std::array<Button, 10> num_buttons{};
std::array<Button, 5> special_buttons{};
Button button_case{
{8, 270, 32, 28},
"UC"};
Button button_ok{
{190, 270, 40, 28},
"OK"};
MessageHandlerRegistration message_handler_sample{
Message::ID::DisplayFrameSync,
[this](const Message* const) {
this->sample_pen();
}};
};
} /* namespace ui */
#endif /*__UNISTROKE_H__*/

View File

@ -1,170 +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 "ui_loadmodule.hpp"
#include "ch.h"
#include "ff.h"
#include "event_m0.hpp"
#include "hackrf_gpio.hpp"
#include "portapack.hpp"
#include "portapack_shared_memory.hpp"
#include "hackrf_hal.hpp"
#include "string_format.hpp"
#include "ui_rds.hpp"
#include "ui_xylos.hpp"
#include "ui_epar.hpp"
#include "ui_lcr.hpp"
#include "analog_audio_app.hpp"
#include "ui_soundboard.hpp"
#include "ui_debug.hpp"
#include "ui_closecall.hpp"
#include "ui_audiotx.hpp"
#include "ui_jammer.hpp"
#include <cstring>
#include <stdio.h>
using namespace portapack;
namespace ui {
void LoadModuleView::focus() {
button_ok.focus();
}
void LoadModuleView::on_show() {
char md5_signature[16];
uint8_t c;
memcpy(md5_signature, (const void*)(0x10087FF0), 16);
for (c = 0; c < 16; c++) {
if (md5_signature[c] != _hash[c]) break;
}
// text_info.set(to_string_hex(*((unsigned int*)0x10087FF0), 8));
if (c == 16) {
text_info.set("Module already loaded :)");
_mod_loaded = true;
} else {
text_info.set("Loading module");
loadmodule();
}
}
int LoadModuleView::load_image() {
const char magic[6] = {'P', 'P', 'M', ' ', 0x02, 0x00};
UINT bw;
uint8_t i;
uint32_t cnt;
char md5sum[16];
FILINFO modinfo;
FIL modfile;
DIR rootdir;
FRESULT res;
// Scan SD card root directory for files with the right MD5 fingerprint at the right location
if (f_opendir(&rootdir, "/") == FR_OK) {
for (;;) {
res = f_readdir(&rootdir, &modinfo);
if (res != FR_OK || modinfo.fname[0] == 0) break; // Reached last file, abort
// Only care about files with .bin extension
if ((!(modinfo.fattrib & AM_DIR)) && (modinfo.fname[9] == 'B') && (modinfo.fname[10] == 'I') && (modinfo.fname[11] == 'N')) {
res = f_open(&modfile, modinfo.fname, FA_OPEN_EXISTING | FA_READ);
if (res != FR_OK) return 0;
// Magic bytes and version check
f_read(&modfile, &md5sum, 6, &bw);
for (i = 0; i < 6; i++)
if (md5sum[i] != magic[i]) break;
if (i == 6) {
f_lseek(&modfile, 26);
f_read(&modfile, &md5sum, 16, &bw);
for (i = 0; i < 16; i++)
if (md5sum[i] != _hash[i]) break;
// f_read can't read more than 512 bytes at a time ?
if (i == 16) {
f_lseek(&modfile, 512);
for (cnt = 0; cnt < 64; cnt++) {
if (f_read(&modfile, reinterpret_cast<void*>(portapack::memory::map::m4_code.base() + (cnt * 512)), 512, &bw)) return 0;
}
f_close(&modfile);
f_closedir(&rootdir);
LPC_RGU->RESET_CTRL[0] = (1 << 13);
return 1;
}
}
f_close(&modfile);
}
}
f_closedir(&rootdir);
}
return 0;
}
void LoadModuleView::loadmodule() {
// baseband::shutdown();
/*EventDispatcher::message_map().register_handler(Message::ID::ReadyForSwitch,
[this](Message* const p) {
(void)p;*/
if (load_image()) {
text_infob.set("Module loaded :)");
_mod_loaded = true;
} else {
text_info.set("Module not found :(");
_mod_loaded = false;
}
// }
//);
}
LoadModuleView::LoadModuleView(
NavigationView& nav,
const char* hash,
ViewID viewid) {
add_children({&text_info,
&text_infob,
&button_ok});
_hash = hash;
button_ok.on_select = [this, &nav, viewid](Button&) {
nav.pop();
if (_mod_loaded == true) {
if (viewid == AudioTX) nav.push<AudioTXView>();
if (viewid == Xylos) nav.push<XylosView>();
if (viewid == EPAR) nav.push<EPARView>();
if (viewid == LCR) nav.push<LCRView>();
if (viewid == SoundBoard) nav.push<SoundBoardView>();
if (viewid == AnalogAudio) nav.push<AnalogAudioView>();
if (viewid == RDS) nav.push<RDSView>();
if (viewid == CloseCall) nav.push<CloseCallView>();
if (viewid == Receiver) nav.push<ReceiverMenuView>();
if (viewid == Jammer) nav.push<JammerView>();
}
};
}
} /* namespace ui */

View File

@ -1,70 +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 "ui.hpp"
#include "ui_widget.hpp"
#include "ui_painter.hpp"
#include "ui_menu.hpp"
#include "ui_navigation.hpp"
#include "core_control.hpp"
namespace ui {
enum ViewID {
Receiver,
AudioTX,
CloseCall,
Xylos,
EPAR,
LCR,
SoundBoard,
AnalogAudio,
RDS,
Jammer
};
class LoadModuleView : public View {
public:
LoadModuleView(NavigationView& nav, const char* hash, ViewID viewid);
void loadmodule();
void on_show() override;
void focus() override;
private:
int load_image(void);
const char* _hash;
bool _mod_loaded = false;
Text text_info{
{8, 64, 224, 16},
"-"};
Text text_infob{
{8, 64 + 16, 224, 16},
"-"};
Button button_ok{
{88, 128, 64, 32},
"OK"};
};
} /* namespace ui */

View File

@ -24,8 +24,6 @@
#include "ui_navigation.hpp"
// #include "modules.h"
#include "bmp_modal_warning.hpp"
#include "bmp_splash.hpp"
#include "event_m0.hpp"
@ -35,12 +33,10 @@
#include "ui_about_simple.hpp"
#include "ui_adsb_rx.hpp"
// #include "ui_adsb_tx.hpp" //moved to ext
#include "ui_aprs_rx.hpp"
#include "ui_aprs_tx.hpp"
#include "ui_bht_tx.hpp"
#include "ui_btle_rx.hpp"
// #include "ui_coasterp.hpp" //moved to ext
#include "ui_debug.hpp"
#include "ui_encoders.hpp"
#include "ui_fileman.hpp"
@ -49,17 +45,10 @@
#include "ui_freqman.hpp"
#include "ui_fsk_rx.hpp"
#include "ui_iq_trim.hpp"
// #include "ui_jammer.hpp" //moved to ext
// #include "ui_keyfob.hpp" //moved to ext
// #include "ui_lcr.hpp"
#include "ui_level.hpp"
#include "ui_looking_glass_app.hpp"
#include "ui_mictx.hpp"
// #include "ui_morse.hpp" //moved to ext
// #include "ui_nrf_rx.hpp" //moved to ext
// #include "ui_numbers.hpp"
// #include "ui_nuoptix.hpp"
// #include "ui_playdead.hpp"
#include "ui_playlist.hpp"
#include "ui_pocsag_tx.hpp"
#include "ui_rds.hpp"
@ -72,12 +61,9 @@
#include "ui_settings.hpp"
#include "ui_siggen.hpp"
#include "ui_sonde.hpp"
// #include "ui_spectrum_painter.hpp" //moved to ext app
#include "ui_ss_viewer.hpp"
// #include "ui_sstvtx.hpp" //moved to ext
// #include "ui_test.hpp"
#include "ui_text_editor.hpp"
#include "ui_tone_search.hpp"
#include "ui_touchtunes.hpp"
#include "ui_view_wav.hpp"
#include "ui_weatherstation.hpp"
@ -88,18 +74,13 @@
#include "ais_app.hpp"
#include "analog_audio_app.hpp"
// #include "analog_tv_app.hpp" //moved to ext
// #include "ble_comm_app.hpp"
#include "ble_rx_app.hpp"
#include "ble_tx_app.hpp"
#include "capture_app.hpp"
#include "ert_app.hpp"
// #include "gps_sim_app.hpp" //moved to ext
// #include "lge_app.hpp" //moved to ext
#include "pocsag_app.hpp"
#include "replay_app.hpp"
#include "soundboard_app.hpp"
// #include "tpms_app.hpp" //moved to ext
#include "core_control.hpp"
#include "file.hpp"
@ -142,7 +123,6 @@ static NavigationView::AppMap generate_app_map(const NavigationView::AppList& ap
// TODO(u-foka): Check consistency of command names (where we add rx/tx postfix)
const NavigationView::AppList NavigationView::appList = {
/* HOME ******************************************************************/
//{"playdead", "Play dead", HOME, Color::red(), &bitmap_icon_playdead, new ViewFactory<PlayDeadView>()},
{nullptr, "Receive", HOME, Color::cyan(), &bitmap_icon_receivers, new ViewFactory<ReceiversMenuView>()},
{nullptr, "Transmit", HOME, Color::cyan(), &bitmap_icon_transmit, new ViewFactory<TransmittersMenuView>()},
{"capture", "Capture", HOME, Color::red(), &bitmap_icon_capture, new ViewFactory<CaptureAppView>()},
@ -154,13 +134,11 @@ const NavigationView::AppList NavigationView::appList = {
{nullptr, "Utilities", HOME, Color::cyan(), &bitmap_icon_utilities, new ViewFactory<UtilitiesMenuView>()},
{nullptr, "Settings", HOME, Color::cyan(), &bitmap_icon_setup, new ViewFactory<SettingsMenuView>()},
{nullptr, "Debug", HOME, Color::light_grey(), &bitmap_icon_debug, new ViewFactory<DebugMenuView>()},
//{"about", "About", HOME, Color::cyan(), nullptr, new ViewFactory<AboutView>()},
/* RX ********************************************************************/
{"adsbrx", "ADS-B", RX, Color::green(), &bitmap_icon_adsb, new ViewFactory<ADSBRxView>()},
{"ais", "AIS Boats", RX, Color::green(), &bitmap_icon_ais, new ViewFactory<AISAppView>()},
{"aprsrx", "APRS", RX, Color::green(), &bitmap_icon_aprs, new ViewFactory<APRSRXView>()},
{"audio", "Audio", RX, Color::green(), &bitmap_icon_speaker, new ViewFactory<AnalogAudioView>()},
//{"btle", "BTLE", RX, Color::yellow(), &bitmap_icon_btle, new ViewFactory<BTLERxView>()},
//{"blecomm", "BLE Comm", RX, ui::Color::orange(), &bitmap_icon_btle, new ViewFactory<BLECommView>()},
{"blerx", "BLE Rx", RX, Color::green(), &bitmap_icon_btle, new ViewFactory<BLERxView>()},
{"ert", "ERT Meter", RX, Color::green(), &bitmap_icon_ert, new ViewFactory<ERTAppView>()},
@ -169,10 +147,8 @@ const NavigationView::AppList NavigationView::appList = {
{"radiosonde", "Radiosnde", RX, Color::green(), &bitmap_icon_sonde, new ViewFactory<SondeView>()},
{"recon", "Recon", RX, Color::green(), &bitmap_icon_scanner, new ViewFactory<ReconView>()},
{"search", "Search", RX, Color::yellow(), &bitmap_icon_search, new ViewFactory<SearchView>()},
//{"tmps", "TPMS Cars", RX, Color::green(), &bitmap_icon_tpms, new ViewFactory<TPMSAppView>()},
{"subghzd", "SubGhzD", RX, Color::yellow(), &bitmap_icon_remote, new ViewFactory<SubGhzDView>()},
{"weather", "Weather", RX, Color::green(), &bitmap_icon_thermometer, new ViewFactory<WeatherView>()},
//{"fskrx", "FSK RX", RX, Color::yellow(), &bitmap_icon_remote, new ViewFactory<FskxRxMainView>()},
//{"dmr", "DMR", RX, Color::dark_grey(), &bitmap_icon_dmr, new ViewFactory<NotImplementedView>()},
//{"sigfox", "SIGFOX", RX, Color::dark_grey(), &bitmap_icon_fox, new ViewFactory<NotImplementedView>()},
//{"lora", "LoRa", RX, Color::dark_grey(), &bitmap_icon_lora, new ViewFactory<NotImplementedView>()},
@ -183,13 +159,10 @@ const NavigationView::AppList NavigationView::appList = {
{"aprstx", "APRS TX", TX, ui::Color::green(), &bitmap_icon_aprs, new ViewFactory<APRSTXView>()},
{"bht", "BHT Xy/EP", TX, ui::Color::green(), &bitmap_icon_bht, new ViewFactory<BHTView>()},
{"bletx", "BLE Tx", TX, ui::Color::green(), &bitmap_icon_btle, new ViewFactory<BLETxView>()},
//{"morse", "Morse", TX, ui::Color::green(), &bitmap_icon_morse, new ViewFactory<MorseView>()}, //moved to ext
//{"nuoptixdtmf", "Nuoptix DTMF", TX, ui::Color::green(), &bitmap_icon_nuoptix, new ViewFactory<NuoptixView>()},
{"ooktx", "OOK", TX, ui::Color::yellow(), &bitmap_icon_remote, new ViewFactory<EncodersView>()},
{"pocsagtx", "POCSAG TX", TX, ui::Color::green(), &bitmap_icon_pocsag, new ViewFactory<POCSAGTXView>()},
{"rdstx", "RDS", TX, ui::Color::green(), &bitmap_icon_rds, new ViewFactory<RDSView>()},
{"soundbrd", "Soundbrd", TX, ui::Color::green(), &bitmap_icon_soundboard, new ViewFactory<SoundBoardView>()},
//{"sstvtx", "SSTV", TX, ui::Color::green(), &bitmap_icon_sstv, new ViewFactory<SSTVTXView>()}, //moved to ext
{"touchtune", "TouchTune", TX, ui::Color::green(), &bitmap_icon_touchtunes, new ViewFactory<TouchTunesView>()},
/* UTILITIES *************************************************************/
{"antennalength", "Antenna Length", UTILITIES, Color::green(), &bitmap_icon_tools_antenna, new ViewFactory<WhipCalcView>()},
@ -200,7 +173,7 @@ const NavigationView::AppList NavigationView::appList = {
{nullptr, "SD Over USB", UTILITIES, Color::yellow(), &bitmap_icon_hackrf, new ViewFactory<SdOverUsbView>()},
{"signalgen", "Signal Gen", UTILITIES, Color::green(), &bitmap_icon_cwgen, new ViewFactory<SigGenView>()},
//{"testapp", "Test App", UTILITIES, Color::dark_grey(), nullptr, new ViewFactory<TestView>()},
//{"tonesearch", "Tone Search", UTILITIES, Color::dark_grey(), nullptr, new ViewFactory<ToneSearchView>()},
{"wavview", "Wav View", UTILITIES, Color::yellow(), &bitmap_icon_soundboard, new ViewFactory<ViewWavView>()},
// Dangerous apps.
{nullptr, "Flash Utility", UTILITIES, Color::red(), &bitmap_icon_temperature, new ViewFactory<FlashUtilityView>()},

View File

@ -1,82 +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 "ui_playdead.hpp"
#include "portapack_persistent_memory.hpp"
#include "string_format.hpp"
using namespace portapack;
namespace ui {
void PlayDeadView::focus() {
button_seq_entry.focus();
}
void PlayDeadView::paint(Painter& painter) {
if (persistent_memory::config_login()) {
// Blank the whole display
painter.fill_rectangle(
display.screen_rect(),
style().background);
}
}
PlayDeadView::PlayDeadView(NavigationView& nav) {
rtc::RTC datetime;
persistent_memory::set_playing_dead(0x5920C1DF); // Enable
add_children({
&text_playdead1,
&text_playdead2,
&text_playdead3,
&button_seq_entry,
});
// Seed from RTC
rtcGetTime(&RTCD1, &datetime);
text_playdead2.set("0x" + to_string_hex(lfsr_iterate(datetime.second()), 6) + "00");
text_playdead3.hidden(true);
button_seq_entry.on_dir = [this](Button&, KeyEvent key) {
sequence = (sequence << 3) | (static_cast<std::underlying_type<KeyEvent>::type>(key) + 1);
return true;
};
button_seq_entry.on_select = [this, &nav](Button&) {
if (sequence == persistent_memory::playdead_sequence()) {
persistent_memory::set_playing_dead(0x82175E23); // Disable
if (persistent_memory::config_login()) {
text_playdead3.hidden(false);
} else {
nav.pop();
nav.push<SystemMenuView>();
}
} else {
sequence = 0;
}
};
}
} /* namespace ui */

View File

@ -1,60 +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 __UI_PLAYDEAD_H__
#define __UI_PLAYDEAD_H__
#include "ui.hpp"
#include "ui_navigation.hpp"
namespace ui {
class PlayDeadView : public View {
public:
PlayDeadView(NavigationView& nav);
void focus() override;
void paint(Painter& painter) override;
private:
uint32_t sequence = 0;
Text text_playdead1{
{6 * 8, 7 * 16, 14 * 8, 16},
"\x46irmwa"
"re "
"er\x72o\x72"};
Text text_playdead2{
{6 * 8, 9 * 16, 16 * 8, 16},
""};
Text text_playdead3{
{6 * 8, 12 * 16, 16 * 8, 16},
"Please reset"};
Button button_seq_entry{
{240, 0, 1, 1},
""};
};
} /* namespace ui */
#endif /*__UI_PLAYDEAD_H__*/

View File

@ -424,13 +424,6 @@ set(MODE_CPPSRC
)
DeclareTargets(PNFM nfm_audio)
#### No op
#
#set(MODE_CPPSRC
# proc_noop.cpp
#)
#DeclareTargets(PNOP no_operation)
### OOK
set(MODE_CPPSRC
@ -438,12 +431,6 @@ set(MODE_CPPSRC
)
DeclareTargets(POOK ook)
#### POCSAG RX
#
#set(MODE_CPPSRC
# proc_pocsag.cpp
#)
#DeclareTargets(PPOC pocsag)
### POCSAG2 RX

View File

@ -1,38 +0,0 @@
/*
* Copyright (C) 2014 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_noop.hpp"
#include "event_m4.hpp"
#include <cstdint>
void NOOPProcessor::execute(const buffer_c8_t& buffer) {
for (size_t i = 0; i < buffer.count; i++) {
buffer.p[i] = {0, 0};
}
}
int main() {
EventDispatcher event_dispatcher{std::make_unique<NOOPProcessor>()};
event_dispatcher.run();
return 0;
}

View File

@ -1,38 +0,0 @@
/*
* Copyright (C) 2014 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_NOOP_H__
#define __PROC_NOOP_H__
#include "baseband_processor.hpp"
#include "baseband_thread.hpp"
class NOOPProcessor : public BasebandProcessor {
public:
void execute(const buffer_c8_t& buffer) override;
private:
/* NB: Threads should be the last members in the class definition. */
BasebandThread baseband_thread{1536000, this, baseband::Direction::Transmit};
};
#endif

View File

@ -1,539 +0,0 @@
/*
* Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu)
* Copyright (C) 2012-2014 Elias Oenal (multimon-ng@eliasoenal.com)
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
* Copyright (C) 2016 Kyle Reed
*
* 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_pocsag.hpp"
#include "dsp_iir_config.hpp"
#include "event_m4.hpp"
#include "audio_dma.hpp"
#include <algorithm>
#include <cmath>
#include <cstdint>
#include <cstddef>
void POCSAGProcessor::execute(const buffer_c8_t& buffer) {
if (!configured) return;
// Get 24kHz audio
const auto decim_0_out = decim_0.execute(buffer, dst_buffer);
const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer);
const auto channel_out = channel_filter.execute(decim_1_out, dst_buffer);
auto audio = demod.execute(channel_out, audio_buffer);
// If squelching, check for audio before smoothing because smoothing
// causes the squelch noise detection to fail. Likely because squelch
// looks for HF noise and smoothing is basically a lowpass filter.
// NB: Squelch in this processor is only for the the audio output.
// Squelching will likely drop data "noise" and break processing.
if (squelch_.enabled()) {
bool has_audio = squelch_.execute(audio);
squelch_history = (squelch_history << 1) | (has_audio ? 1 : 0);
}
smooth.Process(audio.p, audio.count);
processDemodulatedSamples(audio.p, 16);
extractFrames();
samples_processed += buffer.count;
if (samples_processed >= stat_update_threshold) {
send_stats();
samples_processed = 0;
}
// Clear the output before sending to audio chip.
// Only clear the audio buffer when there hasn't been any audio for a while.
if (squelch_.enabled() && squelch_history == 0) {
for (size_t i = 0; i < audio.count; ++i) {
audio.p[i] = 0.0;
}
}
audio_output.write(audio);
}
// ====================================================================
//
// ====================================================================
int POCSAGProcessor::OnDataWord(uint32_t word, int pos) {
packet.set(pos, word);
return 0;
}
// ====================================================================
//
// ====================================================================
int POCSAGProcessor::OnDataFrame(int len, int baud) {
if (len > 0) {
packet.set_bitrate(baud);
packet.set_flag(pocsag::PacketFlag::NORMAL);
packet.set_timestamp(Timestamp::now());
const POCSAGPacketMessage message(packet);
shared_memory.application_queue.push(message);
}
return 0;
}
void POCSAGProcessor::on_message(const Message* const message) {
switch (message->id) {
case Message::ID::POCSAGConfigure:
configure();
break;
case Message::ID::NBFMConfigure: {
auto config = reinterpret_cast<const NBFMConfigureMessage*>(message);
squelch_.set_threshold(config->squelch_level / 100.0);
break;
}
default:
break;
}
}
void POCSAGProcessor::configure() {
constexpr size_t decim_0_input_fs = baseband_fs;
constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0.decimation_factor;
constexpr size_t decim_1_input_fs = decim_0_output_fs;
constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1.decimation_factor;
constexpr size_t channel_filter_input_fs = decim_1_output_fs;
const size_t channel_filter_output_fs = channel_filter_input_fs / 2;
const size_t demod_input_fs = channel_filter_output_fs;
decim_0.configure(taps_11k0_decim_0.taps);
decim_1.configure(taps_11k0_decim_1.taps);
channel_filter.configure(taps_11k0_channel.taps, 2);
demod.configure(demod_input_fs, 4'500); // FSK +/- 4k5Hz.
// Smoothing should be roughly sample rate over max baud
// 24k / 3.2k = 7.5
smooth.SetSize(8);
// Don't have audio process the stream.
audio_output.configure(false);
// Set up the frame extraction, limits of baud
setFrameExtractParams(demod_input_fs, 4000, 300, 32);
// Mark the class as ready to accept data
configured = true;
}
void POCSAGProcessor::send_stats() const {
POCSAGStatsMessage message(m_fifo.codeword, m_numCode, m_gotSync, getRate());
shared_memory.application_queue.push(message);
}
// -----------------------------
// Frame extractraction methods
// -----------------------------
#define BAUD_STABLE (104)
#define MAX_CONSEC_SAME (32)
#define MAX_WITHOUT_SINGLE (64)
#define MAX_BAD_TRANS (10)
#define M_SYNC (0x7cd215d8)
#define M_NOTSYNC (0x832dea27)
#define M_IDLE (0x7a89c197)
// ====================================================================
//
// ====================================================================
inline int bitsDiff(unsigned long left, unsigned long right) {
unsigned long xord = left ^ right;
int count = 0;
for (int i = 0; i < 32; i++) {
if ((xord & 0x01) != 0) ++count;
xord = xord >> 1;
}
return (count);
}
// ====================================================================
//
// ====================================================================
void POCSAGProcessor::initFrameExtraction() {
m_averageSymbolLen_1024 = m_maxSymSamples_1024;
m_lastStableSymbolLen_1024 = m_minSymSamples_1024;
m_badTransitions = 0;
m_bitsStart = 0;
m_bitsEnd = 0;
m_inverted = false;
resetVals();
}
// ====================================================================
//
// ====================================================================
void POCSAGProcessor::resetVals() {
// Reset the parameters
// --------------------
m_goodTransitions = 0;
m_badTransitions = 0;
m_averageSymbolLen_1024 = m_maxSymSamples_1024;
m_shortestGoodTrans_1024 = m_maxSymSamples_1024;
m_valMid = 0;
// And reset the counts
// --------------------
m_lastTransPos_1024 = 0;
m_lastBitPos_1024 = 0;
m_lastSample = 0;
m_sampleNo = 0;
m_nextBitPos_1024 = m_maxSymSamples_1024;
m_nextBitPosInt = (long)m_nextBitPos_1024;
// Extraction
m_fifo.numBits = 0;
m_gotSync = false;
m_numCode = 0;
}
// ====================================================================
//
// ====================================================================
void POCSAGProcessor::setFrameExtractParams(long a_samplesPerSec, long a_maxBaud, long a_minBaud, long maxRunOfSameValue) {
m_samplesPerSec = a_samplesPerSec;
m_minSymSamples_1024 = (uint32_t)(1024.0f * (float)a_samplesPerSec / (float)a_maxBaud);
m_maxSymSamples_1024 = (uint32_t)(1024.0f * (float)a_samplesPerSec / (float)a_minBaud);
m_maxRunOfSameValue = maxRunOfSameValue;
m_shortestGoodTrans_1024 = m_maxSymSamples_1024;
m_averageSymbolLen_1024 = m_maxSymSamples_1024;
m_lastStableSymbolLen_1024 = m_minSymSamples_1024;
m_nextBitPos_1024 = m_averageSymbolLen_1024 / 2;
m_nextBitPosInt = m_nextBitPos_1024 >> 10;
initFrameExtraction();
}
// ====================================================================
//
// ====================================================================
int POCSAGProcessor::processDemodulatedSamples(float* sampleBuff, int noOfSamples) {
bool transition = false;
uint32_t samplePos_1024 = 0;
uint32_t len_1024 = 0;
// Loop through the block of data
// ------------------------------
for (int pos = 0; pos < noOfSamples; ++pos) {
m_sample = sampleBuff[pos];
m_valMid += (m_sample - m_valMid) / 1024.0f;
++m_sampleNo;
// Detect Transition
// -----------------
transition = !((m_lastSample < m_valMid) ^ (m_sample >= m_valMid)); // use XOR for speed
// If this is a transition
// -----------------------
if (transition) {
// Calculate samples since last trans
// ----------------------------------
int32_t fractional_1024 = (int32_t)(((m_sample - m_valMid) * 1024) / (m_sample - m_lastSample));
if (fractional_1024 < 0) {
fractional_1024 = -fractional_1024;
}
samplePos_1024 = (m_sampleNo << 10) - fractional_1024;
len_1024 = samplePos_1024 - m_lastTransPos_1024;
m_lastTransPos_1024 = samplePos_1024;
// If symbol is large enough to be valid
// -------------------------------------
if (len_1024 > m_minSymSamples_1024) {
// Check for shortest good transition
// ----------------------------------
if ((len_1024 < m_shortestGoodTrans_1024) &&
(m_goodTransitions < BAUD_STABLE)) // detect change of symbol size
{
int32_t fractionOfShortest_1024 = (len_1024 << 10) / m_shortestGoodTrans_1024;
// If currently at half the baud rate
// ----------------------------------
if ((fractionOfShortest_1024 > 410) && (fractionOfShortest_1024 < 614)) // 0.4 and 0.6
{
m_averageSymbolLen_1024 /= 2;
m_shortestGoodTrans_1024 = len_1024;
}
// If currently at the wrong baud rate
// -----------------------------------
else if (fractionOfShortest_1024 < 768) // 0.75
{
m_averageSymbolLen_1024 = len_1024;
m_shortestGoodTrans_1024 = len_1024;
m_goodTransitions = 0;
m_lastSingleBitPos_1024 = samplePos_1024 - len_1024;
}
}
// Calc the number of bits since events
// ------------------------------------
int32_t halfSymbol_1024 = m_averageSymbolLen_1024 / 2;
int bitsSinceLastTrans = max((uint32_t)1, (len_1024 + halfSymbol_1024) / m_averageSymbolLen_1024);
int bitsSinceLastSingle = (((m_sampleNo << 10) - m_lastSingleBitPos_1024) + halfSymbol_1024) / m_averageSymbolLen_1024;
// Check for single bit
// --------------------
if (bitsSinceLastTrans == 1) {
m_lastSingleBitPos_1024 = samplePos_1024;
}
// If too long since last transition
// ---------------------------------
if (bitsSinceLastTrans > MAX_CONSEC_SAME) {
resetVals();
}
// If too long sice last single bit
// --------------------------------
else if (bitsSinceLastSingle > MAX_WITHOUT_SINGLE) {
resetVals();
} else {
// If this is a good transition
// ----------------------------
int32_t offsetFromExtectedTransition_1024 = len_1024 - (bitsSinceLastTrans * m_averageSymbolLen_1024);
if (offsetFromExtectedTransition_1024 < 0) {
offsetFromExtectedTransition_1024 = -offsetFromExtectedTransition_1024;
}
if (offsetFromExtectedTransition_1024 < ((int32_t)m_averageSymbolLen_1024 / 4)) // Has to be within 1/4 of symbol to be good
{
++m_goodTransitions;
uint32_t bitsCount = min((uint32_t)BAUD_STABLE, m_goodTransitions);
uint32_t propFromPrevious = m_averageSymbolLen_1024 * bitsCount;
uint32_t propFromCurrent = (len_1024 / bitsSinceLastTrans);
m_averageSymbolLen_1024 = (propFromPrevious + propFromCurrent) / (bitsCount + 1);
m_badTransitions = 0;
// if ( len < m_shortestGoodTrans ){m_shortestGoodTrans = len;}
// Store the old symbol size
if (m_goodTransitions >= BAUD_STABLE) {
m_lastStableSymbolLen_1024 = m_averageSymbolLen_1024;
}
}
}
// Set the point of the last bit if not yet stable
// -----------------------------------------------
if ((m_goodTransitions < BAUD_STABLE) || (m_badTransitions > 0)) {
m_lastBitPos_1024 = samplePos_1024 - (m_averageSymbolLen_1024 / 2);
}
// Calculate the exact positiom of the next bit
// --------------------------------------------
int32_t thisPlusHalfsymbol_1024 = samplePos_1024 + (m_averageSymbolLen_1024 / 2);
int32_t lastPlusSymbol = m_lastBitPos_1024 + m_averageSymbolLen_1024;
m_nextBitPos_1024 = lastPlusSymbol + ((thisPlusHalfsymbol_1024 - lastPlusSymbol) / 16);
// Check for bad pos error
// -----------------------
if (m_nextBitPos_1024 < samplePos_1024) m_nextBitPos_1024 += m_averageSymbolLen_1024;
// Calculate integer sample after next bit
// ---------------------------------------
m_nextBitPosInt = (m_nextBitPos_1024 >> 10) + 1;
} // symbol is large enough to be valid
else {
// Bad transition, so reset the counts
// -----------------------------------
++m_badTransitions;
if (m_badTransitions > MAX_BAD_TRANS) {
resetVals();
}
}
} // end of if transition
// Reached the point of the next bit
// ---------------------------------
if (m_sampleNo >= m_nextBitPosInt) {
// Everything is good so extract a bit
// -----------------------------------
if (m_goodTransitions > 20) {
// Store value at the center of bit
// --------------------------------
storeBit();
}
// Check for long 1 or zero
// ------------------------
uint32_t bitsSinceLastTrans = ((m_sampleNo << 10) - m_lastTransPos_1024) / m_averageSymbolLen_1024;
if (bitsSinceLastTrans > m_maxRunOfSameValue) {
resetVals();
}
// Store the point of the last bit
// -------------------------------
m_lastBitPos_1024 = m_nextBitPos_1024;
// Calculate the exact point of the next bit
// -----------------------------------------
m_nextBitPos_1024 += m_averageSymbolLen_1024;
// Look for the bit after the next bit pos
// ---------------------------------------
m_nextBitPosInt = (m_nextBitPos_1024 >> 10) + 1;
} // Reached the point of the next bit
m_lastSample = m_sample;
} // Loop through the block of data
return getNoOfBits();
}
// ====================================================================
//
// ====================================================================
void POCSAGProcessor::storeBit() {
if (++m_bitsStart >= BIT_BUF_SIZE) {
m_bitsStart = 0;
}
// Calculate the bit value
float sample = (m_sample + m_lastSample) / 2;
// int32_t sample_1024 = m_sample_1024;
bool bit = sample > m_valMid;
// If buffer not full
if (m_bitsStart != m_bitsEnd) {
// Decide on output val
if (bit) {
m_bits[m_bitsStart] = 0;
} else {
m_bits[m_bitsStart] = 1;
}
}
// Throw away bits if the buffer is full
else {
if (--m_bitsStart <= -1) {
m_bitsStart = BIT_BUF_SIZE - 1;
}
}
}
// ====================================================================
//
// ====================================================================
int POCSAGProcessor::extractFrames() {
int msgCnt = 0;
// While there is unread data in the bits buffer
//----------------------------------------------
while (getNoOfBits() > 0) {
m_fifo.codeword = (m_fifo.codeword << 1) + getBit();
m_fifo.numBits++;
// If number of bits in fifo equals 32
//------------------------------------
if (m_fifo.numBits >= 32) {
// Not got sync
// ------------
if (!m_gotSync) {
if (bitsDiff(m_fifo.codeword, M_SYNC) <= 2) {
m_inverted = false;
m_gotSync = true;
m_numCode = -1;
m_fifo.numBits = 0;
} else if (bitsDiff(m_fifo.codeword, M_NOTSYNC) <= 2) {
m_inverted = true;
m_gotSync = true;
m_numCode = -1;
m_fifo.numBits = 0;
} else {
// Cause it to load one more bit
m_fifo.numBits = 31;
}
} // Not got sync
else {
// Increment the word count
// ------------------------
++m_numCode; // It got set to -1 when a sync was found, now count the 16 words
uint32_t val = m_inverted ? ~m_fifo.codeword : m_fifo.codeword;
OnDataWord(val, m_numCode);
// If at the end of a 16 word block
// --------------------------------
if (m_numCode >= 15) {
msgCnt += OnDataFrame(m_numCode + 1, (m_samplesPerSec << 10) / m_lastStableSymbolLen_1024);
m_gotSync = false;
m_numCode = -1;
}
m_fifo.numBits = 0;
}
} // If number of bits in fifo equals 32
} // While there is unread data in the bits buffer
return msgCnt;
} // extractFrames
// ====================================================================
//
// ====================================================================
short POCSAGProcessor::getBit() {
if (m_bitsEnd != m_bitsStart) {
if (++m_bitsEnd >= BIT_BUF_SIZE) {
m_bitsEnd = 0;
}
return m_bits[m_bitsEnd];
} else {
return -1;
}
}
// ====================================================================
//
// ====================================================================
int POCSAGProcessor::getNoOfBits() {
int bits = m_bitsEnd - m_bitsStart;
if (bits < 0) {
bits += BIT_BUF_SIZE;
}
return bits;
}
// ====================================================================
//
// ====================================================================
uint32_t POCSAGProcessor::getRate() const {
return ((m_samplesPerSec << 10) + 512) / m_lastStableSymbolLen_1024;
}
// ====================================================================
//
// ====================================================================
int main() {
audio::dma::init_audio_out();
EventDispatcher event_dispatcher{std::make_unique<POCSAGProcessor>()};
event_dispatcher.run();
return 0;
}

View File

@ -1,233 +0,0 @@
/*
* Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu)
* Copyright (C) 2012-2014 Elias Oenal (multimon-ng@eliasoenal.com)
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
* Copyright (C) 2023 Kyle Reed
*
* 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_POCSAG_H__
#define __PROC_POCSAG_H__
#include "baseband_processor.hpp"
#include "baseband_thread.hpp"
#include "rssi_thread.hpp"
#include "dsp_decimate.hpp"
#include "dsp_demodulate.hpp"
#include "pocsag_packet.hpp"
#include "pocsag.hpp"
#include "message.hpp"
#include "audio_output.hpp"
#include "portapack_shared_memory.hpp"
#include <cstdint>
#include <bitset>
using namespace std;
// Class used to smooth demodulated waveform prior to decoding
// -----------------------------------------------------------
template <class ValType, class CalcType>
class SmoothVals {
protected:
ValType* m_lastVals; // Previous N values
int m_size; // The size N
CalcType m_sumVal; // Running sum of lastVals
int m_pos; // Current position in last vals ring buffer
int m_count; //
public:
SmoothVals()
: m_lastVals(NULL), m_size(1), m_sumVal(0), m_pos(0), m_count(0) {
m_lastVals = new ValType[m_size];
}
// --------------------------------------------------
// --------------------------------------------------
virtual ~SmoothVals() {
delete[] m_lastVals;
}
SmoothVals(const SmoothVals<float, float>&) {
}
SmoothVals& operator=(const SmoothVals<float, float>&) {
return *this;
}
// --------------------------------------------------
// Set size of smoothing
// --------------------------------------------------
void SetSize(int size) {
m_size = std::max(size, 1);
m_pos = 0;
delete[] m_lastVals;
m_lastVals = new ValType[m_size];
m_sumVal = 0;
}
// --------------------------------------------------
// Get size of smoothing
// --------------------------------------------------
int Size() { return m_size; }
// --------------------------------------------------
// In place processing
// --------------------------------------------------
void Process(ValType* valBuff, int numVals) {
ValType tmpVal;
if (m_count > (1024 * 10)) {
// Recalculate the sum value occasionaly, stops accumulated errors when using float
m_count = 0;
m_sumVal = 0;
for (int i = 0; i < m_size; ++i) {
m_sumVal += (CalcType)m_lastVals[i];
}
}
// Use a rolling smoothed value while processing the buffer
for (int buffPos = 0; buffPos < numVals; ++buffPos) {
m_pos++;
if (m_pos >= m_size) {
m_pos = 0;
}
m_sumVal -= (CalcType)m_lastVals[m_pos]; // Subtract the oldest value
m_lastVals[m_pos] = valBuff[buffPos]; // Store the new value
m_sumVal += (CalcType)m_lastVals[m_pos]; // Add on the new value
tmpVal = (ValType)(m_sumVal / m_size); // Scale by number of values smoothed
valBuff[buffPos] = tmpVal;
}
m_count += numVals;
}
};
// --------------------------------------------------
// Class to process base band data to pocsag frames
// --------------------------------------------------
class POCSAGProcessor : public BasebandProcessor {
public:
void execute(const buffer_c8_t& buffer) override;
void on_message(const Message* const message) override;
int OnDataFrame(int len, int baud);
int OnDataWord(uint32_t word, int pos);
private:
static constexpr size_t baseband_fs = 3072000;
static constexpr uint8_t stat_update_interval = 10;
static constexpr uint32_t stat_update_threshold =
baseband_fs / stat_update_interval;
std::array<complex16_t, 512> dst{};
const buffer_c16_t dst_buffer{
dst.data(),
dst.size()};
std::array<float, 32> audio{};
const buffer_f32_t audio_buffer{
audio.data(),
audio.size()};
dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0{};
dsp::decimate::FIRC16xR16x32Decim8 decim_1{};
dsp::decimate::FIRAndDecimateComplex channel_filter{};
dsp::demodulate::FM demod{};
SmoothVals<float, float> smooth = {};
AudioOutput audio_output{};
bool configured = false;
pocsag::POCSAGPacket packet{};
uint32_t samples_processed = 0;
void configure();
void send_stats() const;
// ----------------------------------------
// Frame extractraction methods and members
// ----------------------------------------
void initFrameExtraction();
struct FIFOStruct {
unsigned long codeword;
int numBits;
};
#define BIT_BUF_SIZE (64)
void resetVals();
void setFrameExtractParams(long a_samplesPerSec, long a_maxBaud = 8000, long a_minBaud = 200, long maxRunOfSameValue = 32);
int processDemodulatedSamples(float* sampleBuff, int noOfSamples);
int extractFrames();
void storeBit();
short getBit();
int getNoOfBits();
uint32_t getRate() const;
uint32_t m_averageSymbolLen_1024{0};
uint32_t m_lastStableSymbolLen_1024{0};
uint32_t m_samplesPerSec{0};
uint32_t m_goodTransitions{0};
uint32_t m_badTransitions{0};
uint32_t m_sampleNo{0};
float m_sample{0};
float m_valMid{0.0f};
float m_lastSample{0.0f};
uint32_t m_lastTransPos_1024{0};
uint32_t m_lastSingleBitPos_1024{0};
uint32_t m_nextBitPosInt{0}; // Integer rounded up version to save on ops
uint32_t m_nextBitPos_1024{0};
uint32_t m_lastBitPos_1024{0};
uint32_t m_shortestGoodTrans_1024{0};
uint32_t m_minSymSamples_1024{0};
uint32_t m_maxSymSamples_1024{0};
uint32_t m_maxRunOfSameValue{0};
bitset<(size_t)BIT_BUF_SIZE> m_bits{0};
long m_bitsStart{0};
long m_bitsEnd{0};
FIFOStruct m_fifo{0, 0};
bool m_gotSync{false};
int m_numCode{0};
bool m_inverted{false};
FMSquelch squelch_{};
uint64_t squelch_history = 0;
/* NB: Threads should be the last members in the class definition. */
BasebandThread baseband_thread{baseband_fs, this, baseband::Direction::Receive};
RSSIThread rssi_thread{};
};
#endif /*__PROC_POCSAG_H__*/

View File

@ -1,111 +0,0 @@
/*
* Copyright (C) 2017 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2017 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 __EMU_CC1101_H__
#define __EMU_CC1101_H__
#include <cstdint>
#include <array>
#include "utility.hpp"
namespace cc1101 {
// Data rate (Bauds)
// Whitening: Everything except preamble and sync word, init value = 111111111
// Packet format: preamble, sync word, (opt) length, (opt) address, payload, (opt) CRC
// Preamble: 8*n bits of 10101010
// Sync word: 2 bytes (can be repeated twice)
// Length: 1 byte (address + payload)
// 2-FSK: 0=-dev, 1=+dev
// 4-FSK: 00=-1/3dev, 01=-dev, 10=1/3dev, 11=+dev (preamble and sync are in 2-FSK)
// OOK: PA on or off
// ASK: Power can be adjusted
// FEC: ?
class CC1101Emu {
public:
// CC1101Emu();
//~CC1101Emu();
enum packet_mode_t {
FIXED_LENGTH,
VARIABLE_LENGTH,
INFINITE_LENGTH
};
enum modulation_t {
TWO_FSK,
GFSK,
OOK,
FOUR_FSK,
MSK,
};
void set_sync_word(const uint16_t sync_word) {
sync_word_ = sync_word;
};
void set_address(const uint8_t address) {
address_ = address;
};
void set_packet_length(const uint8_t packet_length) {
packet_length_ = packet_length;
};
void set_data_config(const bool CRC, const bool manchester, const bool whitening) {
CRC_ = CRC;
manchester_ = manchester;
whitening_ = whitening;
};
void set_packet_mode(const packet_mode_t packet_mode) {
packet_mode_ = packet_mode;
};
void set_modulation(const modulation_t modulation) {
modulation_ = modulation;
}
void set_num_preamble(const uint8_t num_preamble) { // 2, 3, 4, 6, 8, 12, 16, or 24
num_preamble_ = num_preamble;
};
void set_deviation(const size_t deviation) {
deviation_ = deviation;
};
private:
uint16_t sync_word_{0xD391};
uint8_t address_{0x00};
uint8_t packet_length_{0};
bool CRC_{false};
bool manchester_{false};
bool whitening_{true};
packet_mode_t packet_mode_{VARIABLE_LENGTH};
modulation_t modulation_{TWO_FSK};
uint8_t num_preamble_{4};
size_t deviation_{4000};
uint16_t whitening_pn{0x1FF};
void whitening_init();
uint8_t whiten_byte(uint8_t byte);
};
} /* namespace cc1101 */
#endif /*__EMU_CC1101_H__*/

View File

@ -1,36 +0,0 @@
const char md5_baseband[16] = {
0xb8,
0x9e,
0x9b,
0x08,
0x44,
0x34,
0x04,
0x20,
0x0b,
0xbc,
0x60,
0x7e,
0x67,
0x88,
0x53,
0xf7,
};
const char md5_baseband_tx[16] = {
0xd5,
0xaf,
0x76,
0xd5,
0xa3,
0x32,
0x5d,
0x9a,
0x9d,
0x83,
0x46,
0x37,
0x02,
0x2d,
0xd0,
0x57,
};

View File

@ -184,10 +184,9 @@ struct data_t {
int32_t modem_baudrate;
int32_t modem_repeat;
// Play dead unlock (Used?)
uint32_t playdead_magic;
uint32_t playing_dead;
uint32_t playdead_sequence;
uint32_t UNUSED_2;
uint32_t UNUSED_3;
uint32_t UNUSED_4;
// UI Config
ui_config_t ui_config;
@ -269,11 +268,9 @@ struct data_t {
afsk_space_freq(afsk_space_reset_value),
modem_baudrate(modem_baudrate_reset_value),
modem_repeat(modem_repeat_reset_value),
playdead_magic(), // TODO: Unused?
playing_dead(), // TODO: Unused?
playdead_sequence(), // TODO: Unused?
UNUSED_2(0),
UNUSED_3(0),
UNUSED_4(0),
ui_config(),
pocsag_last_address(0), // TODO: A better default?
@ -1221,9 +1218,6 @@ bool debug_dump() {
pmem_dump_file.write_line("afsk_space_freq: " + to_string_dec_int(data->afsk_space_freq));
pmem_dump_file.write_line("modem_baudrate: " + to_string_dec_int(data->modem_baudrate));
pmem_dump_file.write_line("modem_repeat: " + to_string_dec_int(data->modem_repeat));
pmem_dump_file.write_line("playdead_magic: " + to_string_dec_uint(data->playdead_magic));
pmem_dump_file.write_line("playing_dead: " + to_string_dec_uint(data->playing_dead));
pmem_dump_file.write_line("playdead_sequence: " + to_string_dec_uint(data->playdead_sequence));
pmem_dump_file.write_line("pocsag_last_address: " + to_string_dec_uint(data->pocsag_last_address));
pmem_dump_file.write_line("pocsag_ignore_address: " + to_string_dec_uint(data->pocsag_ignore_address));
pmem_dump_file.write_line("tone_mix: " + to_string_dec_uint(data->tone_mix));

View File

@ -189,12 +189,6 @@ void set_modem_baudrate(const int32_t new_value);
uint8_t modem_repeat();
void set_modem_repeat(const uint32_t new_value);
uint32_t playing_dead();
void set_playing_dead(const uint32_t new_value);
uint32_t playdead_sequence();
void set_playdead_sequence(const uint32_t new_value);
bool stealth_mode();
void set_stealth_mode(const bool v);

View File

@ -1,117 +0,0 @@
#!/usr/bin/env python3
# Copyright (C) 2016 Furrtek
#
# 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.
#
import sys
import struct
import md5
usage_message = """
Baseband module package file generator
Usage: <command> <module_name> <module_name>...
"""
def read_image(path):
f = open(path, 'rb')
data = f.read()
f.close()
return data
def write_file(data, path):
f = open(path, 'wb')
f.write(data)
f.close()
if len(sys.argv) == 1:
print(usage_message)
sys.exit(-1)
data = bytearray()
h_data = bytearray()
name = bytearray()
info = bytearray()
description = bytearray()
data_default_byte = bytearray((0,))
sys.argv = sys.argv[1:]
# Format for module file:
# Magic (4), Version (2), Length (4), Name (16), MD5 (16), Description (214)
# 0x00 pad bytes (256)
# Module binary (padded to 32768-16)
# MD5 (16) again, so that module code can read it (dirty...)
for args in sys.argv:
m = md5.new()
data = read_image(args + '/build/' + args + '.bin')
data_r = data
# Magic bytes
info = 'PPM '
# Version
info += struct.pack('H', 2)
# Length
info += struct.pack('I', len(data))
# Module name
name = read_image(args + '/name')
if len(name) > 16:
name = name[0:15]
pad_size = 16 - len(name)
name += (data_default_byte * pad_size)
info += name
# Module MD5 footprint
m.update(data)
digest = m.digest()
pad_size = 16 - len(digest)
digest += (data_default_byte * pad_size)
info += digest
# Module description
description = read_image(args + '/description')
if len(description) > 214:
description = description[0:213]
pad_size = 214 - len(description)
description += (data_default_byte * pad_size)
info += description
# Header padding to fit in SD card sector
info += (data_default_byte * 256)
# Binary padding
data = info + data
pad_size = (32768 + 512 - 16) - len(data)
data += (data_default_byte * pad_size)
data += digest
write_file(data, args + '.bin')
# Add to modules.h
md5sum = ''
for byte in digest:
md5sum += '0x' + format(byte, '02x') + ','
h_data += 'const char md5_' + args.replace('-','_') + '[16] = {' + md5sum + '};\n'
# Update original binary with MD5 footprint
write_file(data[512:(32768+512)], args + '/build/' + args + '_inc.bin')
write_file(h_data, 'common/modules.h')