Compare commits

...

45 Commits

Author SHA1 Message Date
gullradriel ecbb232d9c Merge pull request #864 from bernd-herzog/ssd_to_usb
Ssd to usb
2023-04-01 19:58:02 +02:00
gullradriel 0e59e61461 Merge pull request #865 from gullradriel/recon-fix
fixing range frequencies and index skipping
2023-04-01 19:57:31 +02:00
GullCode 7da322f926 fixing range frequencies and index skipping 2023-04-01 19:56:44 +02:00
Bernd Herzog 04392752d1 fixed spelling error 2023-04-01 19:38:38 +02:00
Bernd Herzog db5fcaba44 Merge remote-tracking branch 'origin/next' into ssd_to_usb 2023-04-01 19:24:53 +02:00
Bernd Herzog a8f0c8eac9 refactoring 2023-04-01 19:24:13 +02:00
Bernd Herzog 6fadd70c1d updated ui 2023-04-01 19:16:01 +02:00
Bernd Herzog 8d8d457da2 refactoring 2023-04-01 18:57:53 +02:00
Bernd Herzog 893df7272f refactoring 2023-04-01 18:36:57 +02:00
Bernd Herzog bb90fdc5fc Implemented write 2023-04-01 17:39:08 +02:00
Bernd Herzog 50859171f4 implemented msd read 2023-04-01 17:21:57 +02:00
Bernd Herzog fc1b676ce6 implemented rest of scsi stack 2023-03-31 22:34:55 +02:00
Bernd Herzog 776ac652a8 implemented scsi inquiry 2023-03-31 19:18:39 +02:00
gullradriel c9c438824d Merge pull request #860 from gullradriel/load-save-persistent-memory
Load save persistent memory
2023-03-31 18:25:10 +02:00
GullCode 95eb1e6d59 Loading pmem if enable before displaying splashscreen 2023-03-31 14:24:54 +02:00
GullCode 1f32367495 reset to original since loading is now taking place in navigation 2023-03-31 14:24:29 +02:00
GullCode 0ed5e6542e P.Mem settings menu entry 2023-03-31 14:06:22 +02:00
GullCode 7240d45a4f added on green sdcard load persistent settings 2023-03-31 14:05:49 +02:00
GullCode 17250304e0 indentation & added load & save persistent settings to sdcard 2023-03-31 14:05:33 +02:00
GullCode 835bc49999 Working pmem load flag checkbox 2023-03-30 17:40:17 +02:00
Bernd Herzog a6eb430830 integrated usb stack 2023-03-30 11:46:36 +02:00
Bernd Herzog 8dd68a0811 added copy of hackrf usb stack 2023-03-29 17:05:11 +02:00
Erwin Ried 9540776afd Merge pull request #855 from bernd-herzog/flash_utility
Add new App: flash utility
2023-03-28 15:41:43 +02:00
Bernd Herzog f5d4fce945 added flash utility 2023-03-28 14:39:00 +02:00
gullradriel 8840a6e894 Merge pull request #844 from bernd-herzog/reduce_image_size_lz4
Reduce image size lz4
2023-03-28 07:35:51 +02:00
gullradriel 7ef98f7741 Merge pull request #854 from gullradriel/converter-fix-disable
Fix to force converter icon to be displayed if enabled
2023-03-27 23:06:32 +02:00
GullCode b41be47c9d pesky and non consistent indentation is boring 2023-03-27 23:05:46 +02:00
GullCode 1e2bc703b8 Fix to force converter icon to be displayed if enabled 2023-03-27 23:03:09 +02:00
Bernd Herzog 9115eadd17 added lz4 to dockerfile 2023-03-27 16:22:20 +02:00
gullradriel 05429d3d15 Merge pull request #853 from gullradriel/up-down-convert
Up Down Converter (replacement/update of previous HamItUp function)
2023-03-27 15:39:04 +02:00
GullCode 30c1f9f594 Changed hamitup to converter icons and functions 2023-03-27 14:22:35 +02:00
GullCode f994f8d697 changing logic to take 'up' or 'down' in account 2023-03-27 14:22:07 +02:00
GullCode e045628dab Menu entry for Converter, cleanings of Radio menu 2023-03-27 14:16:03 +02:00
GullCode 17cdb34fea added set of functions for up/down/enable/disable converter 2023-03-27 14:15:28 +02:00
GullCode 9df0f6e9df updated bitmap icons for converter 2023-03-27 14:14:53 +02:00
GullCode 54e4b535cc converters icons 2023-03-27 14:14:11 +02:00
gullradriel d6555a7af0 Merge pull request #852 from gullradriel/recon-minor-update
Recon minor update
2023-03-26 21:06:16 +02:00
GullCode 30004a1c3c cosmetic, ui moves 2023-03-26 21:04:43 +02:00
GullCode 8d60da0a5a updated description of entry / input output file 2023-03-26 15:30:54 +02:00
GullCode 17f30b6f26 Added and fixed go to index 2023-03-26 15:11:27 +02:00
GullCode 3d13ee828e changed text index to button, adding set to index and on_encoder, global indentation 2023-03-24 23:44:16 +01:00
Bernd Herzog 7b4662fe4a fixed packing 2023-03-21 22:01:09 +01:00
Bernd Herzog 8fcedb017c fixed script 2023-03-21 21:31:59 +01:00
Bernd Herzog 7b3ab64930 fixed data packing 2023-03-21 21:27:32 +01:00
Bernd Herzog b856b047cc added compression of baseband images 2023-03-21 19:18:38 +01:00
53 changed files with 7286 additions and 3625 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ COPY ./ /havocsrc
#Fetch dependencies from APT
RUN apt-get update && \
apt-get install -y tar wget dfu-util cmake python bzip2 curl python3 python3-yaml && \
apt-get install -y tar wget dfu-util cmake python bzip2 lz4 curl python3 python3-yaml && \
apt-get -qy autoremove
#Install current pip from PyPa
+1 -1
View File
@@ -13,7 +13,7 @@ COPY ./ /havocsrc
# Fetch dependencies from APK
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
RUN apk update -U
RUN apk add --no-cache git tar wget cmake curl bzip2 make
RUN apk add --no-cache git tar wget cmake curl bzip2 lz4 make
RUN apk add --no-cache dfu-util ccache icu-data-full
RUN apk add --no-cache python3 py3-pip py3-yaml
RUN apk add --no-cache py3-pyyaml-env-tag
+1 -1
View File
@@ -11,7 +11,7 @@ WORKDIR /havoc/firmware
# Fetch dependencies from APT
RUN apt-get update && \
apt-get install -y git tar wget dfu-util cmake python3 ccache bzip2 curl && \
apt-get install -y git tar wget dfu-util cmake python3 ccache bzip2 liblz4-tool curl && \
apt-get -qy autoremove
#Install current pip from PyPa
+1 -1
View File
@@ -10,7 +10,7 @@ WORKDIR /havoc/firmware
# Fetch dependencies from APK
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
RUN apk update -U
RUN apk add --no-cache git tar wget cmake curl bzip2 make
RUN apk add --no-cache git tar wget cmake curl bzip2 lz4 make
RUN apk add --no-cache dfu-util ccache icu-data-full
RUN apk add --no-cache python3 py3-pip py3-yaml
RUN apk add --no-cache py3-pyyaml-env-tag
+1
View File
@@ -28,6 +28,7 @@ set(CHIBIOS_PORTAPACK ${PROJECT_SOURCE_DIR}/chibios-portapack)
set(EXTRACT_CPLD_DATA ${PROJECT_SOURCE_DIR}/tools/extract_cpld_data.py)
set(MAKE_SPI_IMAGE ${PROJECT_SOURCE_DIR}/tools/make_spi_image.py)
set(MAKE_IMAGE_CHUNK ${PROJECT_SOURCE_DIR}/tools/make_image_chunk.py)
set(LZ4 lz4)
set(FIRMWARE_NAME portapack-h1_h2-mayhem)
set(FIRMWARE_FILENAME ${FIRMWARE_NAME}.bin)
+6 -1
View File
@@ -234,6 +234,8 @@ set(CPPSRC
apps/ui_debug.cpp
apps/ui_encoders.cpp
apps/ui_fileman.cpp
apps/ui_flash_utility.cpp
apps/ui_sd_over_usb.cpp
apps/ui_freqman.cpp
apps/ui_jammer.cpp
apps/ui_keyfob.cpp
@@ -317,7 +319,10 @@ set(TCSRC)
set(TCPPSRC)
# List ASM source files here
set(ASMSRC ${PORTASM})
set(ASMSRC
${PORTASM}
lz4.S
)
set(INCDIR ${CMAKE_CURRENT_BINARY_DIR} ${COMMON} ${PORTINC} ${KERNINC} ${TESTINC}
${HALINC} ${PLATFORMINC} ${BOARDINC}
@@ -0,0 +1,89 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2023 Bernd Herzog
*
* 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_flash_utility.hpp"
#include "portapack_shared_memory.hpp"
namespace ui {
Thread* FlashUtilityView::thread { nullptr };
static constexpr size_t max_filename_length = 26;
FlashUtilityView::FlashUtilityView(NavigationView& nav) : nav_ (nav) {
add_children({
&labels,
&menu_view
});
menu_view.set_parent_rect({ 0, 3 * 8, 240, 33 * 8 });
for (const auto& entry : std::filesystem::directory_iterator(u"FIRMWARE", u"*.bin")) {
auto filename = entry.path().filename();
auto path = entry.path().native();
menu_view.add_item({
filename.string().substr(0, max_filename_length),
ui::Color::red(),
&bitmap_icon_temperature,
[this, path]() {
this->firmware_selected(path);
}
});
}
}
void FlashUtilityView::firmware_selected(std::filesystem::path::string_type path) {
nav_.push<ModalMessageView>(
"Warning!",
"This will replace your\ncurrent firmware.\n\nIf things go wrong you are\nrequired to flash manually\nwith dfu.",
YESNO,
[this, path](bool choice) {
if (choice) {
std::u16string full_path = std::u16string(u"FIRMWARE/") + path;
this->flash_firmware(full_path);
}
}
);
}
void FlashUtilityView::flash_firmware(std::filesystem::path::string_type path) {
ui::Painter painter;
painter.fill_rectangle(
{ 0, 0, portapack::display.width(), portapack::display.height() },
ui::Color::black()
);
painter.draw_string({ 12, 24 }, this->nav_.style(), "This will take 15 seconds.");
painter.draw_string({ 12, 64 }, this->nav_.style(), "Please wait while LEDs RX");
painter.draw_string({ 12, 84 }, this->nav_.style(), "and TX are flashing.");
painter.draw_string({ 12, 124 }, this->nav_.style(), "Then restart the device.");
std::memcpy(&shared_memory.bb_data.data[0], path.c_str(), (path.length() + 1) * 2);
m4_init(portapack::spi_flash::image_tag_flash_utility, portapack::memory::map::m4_code, false);
m0_halt();
}
void FlashUtilityView::focus() {
menu_view.focus();
}
} /* namespace ui */
@@ -0,0 +1,66 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2023 Bernd Herzog
*
* 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_FLSH_UITILTY_H__
#define __UI_FLSH_UITILTY_H__
#include "ui_widget.hpp"
#include "ui_navigation.hpp"
#include "string_format.hpp"
#include "ff.h"
#include "baseband_api.hpp"
#include "core_control.hpp"
#include <cstdint>
namespace ui {
class FlashUtilityView : public View {
public:
FlashUtilityView(NavigationView& nav);
void focus() override;
std::string title() const override { return "Flash Utility"; };
private:
NavigationView& nav_;
bool confirmed = false;
static Thread* thread;
Labels labels {
{ { 4, 4 }, "Select firmware to flash:", Color::white() }
};
MenuView menu_view {
{ 0, 2 * 8, 240, 26 * 8 },
true
};
void firmware_selected(std::filesystem::path::string_type path);
void flash_firmware(std::filesystem::path::string_type path);
};
} /* namespace ui */
#endif/*__UI_FLSH_UITILTY_H__*/
File diff suppressed because it is too large Load Diff
+319 -298
View File
@@ -42,367 +42,388 @@
namespace ui {
class ReconThread {
public:
ReconThread(freqman_db *database );
~ReconThread();
class ReconThread {
public:
ReconThread(freqman_db *database );
~ReconThread();
void set_recon(const bool v);
void set_freq_delete(const bool v);
bool is_recon();
void set_recon(const bool v);
void set_freq_delete(const bool v);
bool is_recon();
void set_lock_duration( const uint32_t v );
uint32_t get_lock_duration();
void set_lock_nb_match( const uint32_t v );
void set_match_mode( const uint32_t v );
uint32_t get_lock_nb_match();
void set_lock_duration( const uint32_t v );
uint32_t get_lock_duration();
void set_lock_nb_match( const uint32_t v );
void set_match_mode( const uint32_t v );
uint32_t get_lock_nb_match();
void set_freq_lock(const uint32_t v);
uint32_t is_freq_lock();
int64_t get_current_freq();
void set_freq_lock(const uint32_t v);
uint32_t is_freq_lock();
int64_t get_current_freq();
void set_stepper(const int64_t v);
void set_stepper(const int64_t v);
void set_index_stepper(const int64_t v);
void change_recon_direction();
bool get_recon_direction();
void set_recon_direction( const bool v);
void change_recon_direction();
bool get_recon_direction();
void set_recon_direction( const bool v);
void set_continuous(const bool v);
void set_continuous(const bool v);
void set_default_modulation( freqman_index_t index );
freqman_index_t get_current_modulation();
void set_default_bandwidth( freqman_index_t index );
freqman_index_t get_current_bandwidth();
void set_default_step( freqman_index_t index );
void set_freq_index( int16_t index );
int16_t get_freq_index();
void set_default_modulation( freqman_index_t index );
freqman_index_t get_current_modulation();
void set_default_bandwidth( freqman_index_t index );
freqman_index_t get_current_bandwidth();
void set_default_step( freqman_index_t index );
void set_freq_index( int16_t index );
int16_t get_freq_index();
void run();
void stop();
void run();
void stop();
ReconThread(const ReconThread&) = delete;
ReconThread(ReconThread&&) = delete;
ReconThread& operator=(const ReconThread&) = delete;
ReconThread& operator=(ReconThread&&) = delete;
ReconThread(const ReconThread&) = delete;
ReconThread(ReconThread&&) = delete;
ReconThread& operator=(const ReconThread&) = delete;
ReconThread& operator=(ReconThread&&) = delete;
private:
freqman_db &frequency_list_ ;
Thread* thread { nullptr };
int64_t freq = 0 ;
uint32_t step = 0 ;
freqman_index_t def_modulation = 0 ;
freqman_index_t def_bandwidth = 0 ;
freqman_index_t def_step = 0 ;
tone_index tone = 0 ;
freqman_entry last_entry = { } ;
int16_t frequency_index = 0 ;
private:
freqman_db &frequency_list_ ;
Thread* thread { nullptr };
int64_t freq = 0 ;
uint32_t step = 0 ;
freqman_index_t def_modulation = 0 ;
freqman_index_t def_bandwidth = 0 ;
freqman_index_t def_step = 0 ;
tone_index tone = 0 ;
freqman_entry last_entry = { } ;
int16_t frequency_index = 0 ;
bool _recon { true };
bool _freq_delete { false };
bool _fwd { true };
bool _continuous { true };
int64_t _stepper { 0 };
int32_t _freq_lock { 0 };
uint32_t _lock_duration { 50 };
uint32_t _lock_nb_match { 10 };
static msg_t static_fn(void* arg);
};
bool _recon { true };
bool _freq_delete { false };
bool _fwd { true };
bool _continuous { true };
bool entry_has_changed = false ;
int64_t _stepper { 0 };
int64_t _index_stepper { 0 };
int32_t _freq_lock { 0 };
uint32_t _lock_duration { 50 };
uint32_t _lock_nb_match { 10 };
static msg_t static_fn(void* arg);
};
class ReconView : public View {
public:
ReconView(NavigationView& nav);
~ReconView();
class ReconView : public View {
public:
ReconView(NavigationView& nav);
~ReconView();
void focus() override;
void focus() override;
void big_display_freq( int64_t f );
void big_display_freq( int64_t f );
const Style style_grey { // recon
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::grey(),
};
const Style style_grey { // recon
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::grey(),
};
const Style style_white { // recon
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::white(),
};
const Style style_white { // recon
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::white(),
};
const Style style_yellow { //Found signal
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::yellow(),
};
const Style style_yellow { //Found signal
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::yellow(),
};
const Style style_green { //Found signal
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::green(),
};
const Style style_green { //Found signal
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::green(),
};
const Style style_red { //erasing freq
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::red(),
};
const Style style_red { //erasing freq
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::red(),
};
const Style style_blue { // quick recon, wait == 0
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::blue(),
};
const Style style_blue { // quick recon, wait == 0
.font = font::fixed_8x16,
.background = Color::black(),
.foreground = Color::blue(),
};
std::string title() const override { return "Recon"; };
std::string title() const override { return "Recon"; };
//void set_parent_rect(const Rect new_parent_rect) override;
//void set_parent_rect(const Rect new_parent_rect) override;
private:
NavigationView& nav_;
private:
NavigationView& nav_;
void start_recon_thread();
size_t change_mode( freqman_index_t mod_type);
void show_max( bool refresh_display = false );
void recon_pause();
void recon_resume();
void user_pause();
void user_resume();
void frequency_file_load( bool stop_all_before = false);
void on_statistics_update(const ChannelStatistics& statistics);
void on_headphone_volume_changed(int32_t v);
void set_display_freq( int64_t freq );
void handle_retune( int64_t freq , uint32_t index );
bool check_sd_card();
void start_recon_thread();
size_t change_mode( freqman_index_t mod_type);
void show_max( bool refresh_display = false );
void recon_pause();
void recon_resume();
void user_pause();
void user_resume();
void frequency_file_load( bool stop_all_before = false);
void on_statistics_update(const ChannelStatistics& statistics);
void on_headphone_volume_changed(int32_t v);
void set_display_freq( int64_t freq );
void handle_retune( int64_t freq , uint32_t index );
bool check_sd_card();
void handle_coded_squelch(const uint32_t value);
jammer::jammer_range_t frequency_range { false, 0, 0 }; //perfect for manual recon task too...
int32_t squelch { 0 };
int32_t db { 0 };
int32_t timer { 0 };
int32_t wait { 5000 }; // in msec. if > 0 wait duration after a lock, if < 0 duration is set to 'wait' unless there is no more activity
uint32_t lock_wait { 500 }; // in msec. Represent the maximum amount of time we will wait for a lock to complete before switching to next
int32_t def_step { 0 };
freqman_db frequency_list = { };
uint32_t current_index { 0 };
bool userpause { false };
bool continuous_lock { false };
std::string input_file = { "RECON" };
std::string output_file = { "RECON_RESULTS" };
bool autosave = { true };
bool autostart = { true };
bool continuous = { true };
bool filedelete = { true };
bool load_freqs = { true };
bool load_ranges = { true };
bool load_hamradios = { true };
bool update_ranges = { true };
bool fwd = { true };
// maximum usable freq
long long int MAX_UFREQ = { 7200000000 };
uint32_t recon_lock_nb_match = { 10 };
uint32_t recon_lock_duration = { 50 };
uint32_t recon_match_mode = { 0 };
bool scanner_mode { false };
bool manual_mode { false };
bool sd_card_mounted = false ;
int32_t volume = 40 ;
jammer::jammer_range_t frequency_range { false, 0, 0 }; //perfect for manual recon task too...
int32_t squelch { 0 };
int32_t db { 0 };
int32_t timer { 0 };
int32_t wait { 5000 }; // in msec. if > 0 wait duration after a lock, if < 0 duration is set to 'wait' unless there is no more activity
uint32_t lock_wait { 500 }; // in msec. Represent the maximum amount of time we will wait for a lock to complete before switching to next
int32_t def_step { 0 };
freqman_db frequency_list = { };
uint32_t current_index { 0 };
bool userpause { false };
bool continuous_lock { false };
std::string input_file = { "RECON" };
std::string output_file = { "RECON_RESULTS" };
bool autosave = { true };
bool autostart = { true };
bool continuous = { true };
bool filedelete = { true };
bool load_freqs = { true };
bool load_ranges = { true };
bool load_hamradios = { true };
bool update_ranges = { true };
bool fwd = { true };
// maximum usable freq
long long int MAX_UFREQ = { 7200000000 };
uint32_t recon_lock_nb_match = { 10 };
uint32_t recon_lock_duration = { 50 };
uint32_t recon_match_mode = { 0 };
bool scanner_mode { false };
bool manual_mode { false };
bool sd_card_mounted = false ;
int32_t volume = 40 ;
Labels labels
{
{ { 0 * 8 , 0 * 16 }, "LNA: VGA: AMP: VOL: ", Color::light_grey() },
{ { 0 * 8 , 1 * 16 }, "BW: SQ: W,L: , ", Color::light_grey() },
{ { 3 * 8 , 10 * 16 }, "START END MANUAL", Color::light_grey() },
{ { 0 * 8 , (26 * 8) + 4 }, "MODE:", Color::light_grey() },
{ { 11 * 8 , (26 * 8) + 4 }, "STEP:", Color::light_grey() },
};
Labels labels
{
{ { 0 * 8 , 0 * 16 }, "LNA: VGA: AMP: VOL: ", Color::light_grey() },
{ { 0 * 8 , 1 * 16 }, "BW: SQ: W,L: , ", Color::light_grey() },
{ { 3 * 8 , 10 * 16 }, "START END MANUAL", Color::light_grey() },
{ { 0 * 8 , (26 * 8) + 4 }, "MODE:", Color::light_grey() },
{ { 11 * 8 , (26 * 8) + 4 }, "STEP:", Color::light_grey() },
};
LNAGainField field_lna {
{ 4 * 8, 0 * 16 }
};
LNAGainField field_lna {
{ 4 * 8, 0 * 16 }
};
VGAGainField field_vga {
{ 11 * 8, 0 * 16 }
};
VGAGainField field_vga {
{ 11 * 8, 0 * 16 }
};
RFAmpField field_rf_amp {
{ 18 * 8, 0 * 16 }
};
RFAmpField field_rf_amp {
{ 18 * 8, 0 * 16 }
};
NumberField field_volume {
{ 24 * 8, 0 * 16 },
2,
{ 0, 99 },
1,
' ',
};
NumberField field_volume {
{ 24 * 8, 0 * 16 },
2,
{ 0, 99 },
1,
' ',
};
OptionsField field_bw {
{ 3 * 8, 1 * 16 },
6,
{ }
};
OptionsField field_bw {
{ 3 * 8, 1 * 16 },
6,
{ }
};
NumberField field_squelch {
{ 12 * 8, 1 * 16 },
3,
{ -90, 20 },
1,
' ',
};
NumberField field_squelch {
{ 12 * 8, 1 * 16 },
3,
{ -90, 20 },
1,
' ',
};
NumberField field_wait {
{ 20 * 8, 1 * 16 },
5,
{ -9000, 9000 },
100,
' ',
};
NumberField field_wait {
{ 20 * 8, 1 * 16 },
5,
{ -9000, 9000 },
100,
' ',
};
NumberField field_lock_wait {
{ 26 * 8, 1 * 16 },
4,
{ 100 , 9000 },
100,
' ',
};
NumberField field_lock_wait {
{ 26 * 8, 1 * 16 },
4,
{ 100 , 9000 },
100,
' ',
};
RSSI rssi {
{ 0 * 16, 2 * 16, 240 - 4 * 8 , 16 },
};
RSSI rssi {
{ 0 * 16, 2 * 16, 240 - 5 * 8 - 1 , 16 },
};
Text text_cycle {
{ 0, 3 * 16, 3 * 8, 16 },
};
ButtonWithEncoder text_cycle {
{ 0, 3 * 16, 3 * 8, 16 },
""
};
Text text_max {
{ 3 * 8, 3 * 16, 20 * 8 , 16 },
};
Text text_max {
{ 3 * 8, 3 * 16, 20 * 8 , 16 },
};
Text desc_cycle {
{0, 4 * 16, 240 , 16 },
};
Text desc_cycle {
{0, 4 * 16, 240 , 16 },
};
/* BigFrequency big_display { //Show frequency in glamour
{ 4, 7 * 16 - 8 , 28 * 8, 52 },
0
}; */
/* BigFrequency big_display { //Show frequency in glamour
{ 4, 7 * 16 - 8 , 28 * 8, 52 },
0
}; */
Text big_display { //Show frequency in text mode
{ 0, 5 * 16 , 21 * 8, 16 },
};
Text big_display { //Show frequency in text mode
{ 0, 5 * 16 , 21 * 8, 16 },
};
Text freq_stats { //Show frequency stats in text mode
{ 0, 6 * 16 , 21 * 8, 16 },
};
Text freq_stats { //Show frequency stats in text mode
{ 0, 6 * 16 , 21 * 8, 16 },
};
Text text_timer { //Show frequency stats in text mode
{ 0, 7 * 16 , 21 * 8, 16 },
};
// TIMER: 9999
Text text_timer { //Show frequency stats in text mode
{ 0, 7 * 16 , 11 * 8, 16 },
};
Button button_recon_setup {
{ 240 - 4 * 8 , 2 * 16 , 4 * 8, 28 },
"OPT"
};
// T: Senn. 32.000k
Text text_ctcss {
{ 12 * 8 + 4, 7 * 16 , 14 * 8, 1 * 8 },
""
};
Button button_looking_glass {
{ 240 - 5 * 8 , 6 * 16 - 4 , 5 * 8, 28 },
"GLASS"
};
Button button_recon_setup {
{ 240 - 5 * 8 , 2 * 16 , 5 * 8, 28 },
"OPT"
};
Button button_scanner_mode {
{ 240 - 8 * 8 , 8 * 16 , 8 * 8, 28 },
"RECON"
};
Button button_looking_glass {
{ 240 - 5 * 8 , 5 * 16 , 5 * 8, 28 },
"GLASS"
};
Text file_name { //Show file used
{ 0 , 8 * 16 + 6 , 21 * 8, 16 },
};
// Button can be RECON or SCANNER
Button button_scanner_mode {
{ 240 - 7 * 8 , 8 * 16 , 7 * 8, 28 },
"RECON"
};
ButtonWithEncoder button_manual_start {
{ 0 * 8, 11 * 16, 11 * 8, 28 },
""
};
Text file_name { //Show file used
{ 0 , 8 * 16 + 6 , 240 - 7 * 8, 16 },
};
ButtonWithEncoder button_manual_end {
{ 12 * 8 - 6, 11 * 16, 11 * 8, 28 },
""
};
ButtonWithEncoder button_manual_start {
{ 0 * 8, 11 * 16, 11 * 8, 28 },
""
};
Button button_manual_recon {
{ 23 * 8 - 3, 11 * 16, 7 * 8 , 28 },
"SEARCH"
};
ButtonWithEncoder button_manual_end {
{ 12 * 8 - 6, 11 * 16, 11 * 8, 28 },
""
};
OptionsField field_mode {
{ 5 * 8, (26 * 8) + 4 },
6,
{
}
};
Button button_manual_recon {
{ 23 * 8 - 3, 11 * 16, 7 * 8 , 28 },
"SEARCH"
};
OptionsField step_mode {
{ 17 * 8, (26 * 8) + 4 },
12,
{
}
};
OptionsField field_mode {
{ 5 * 8, (26 * 8) + 4 },
6,
{
}
};
ButtonWithEncoder button_pause {
{ 0, (15 * 16) - 4, 72, 28 },
"PAUSE"
};
OptionsField step_mode {
{ 17 * 8, (26 * 8) + 4 },
12,
{
}
};
ButtonWithEncoder button_pause {
{ 0, (15 * 16) - 4, 72, 28 },
"PAUSE"
};
Button button_audio_app {
{ 84, (15 * 16) - 4, 72, 28 },
"AUDIO"
};
Button button_audio_app {
{ 84, (15 * 16) - 4, 72, 28 },
"AUDIO"
};
ButtonWithEncoder button_add {
{ 168, (15 * 16) - 4, 72, 28 },
"<STORE>"
};
ButtonWithEncoder button_add {
{ 168, (15 * 16) - 4, 72, 28 },
"<STORE>"
};
Button button_dir {
{ 0, (35 * 8) - 4, 34, 28 },
"FW>"
};
Button button_dir {
{ 0, (35 * 8) - 4, 34, 28 },
"FW>"
};
Button button_restart {
{ 38, (35 * 8) - 4, 34, 28 },
"RST"
};
Button button_restart {
{ 38, (35 * 8) - 4, 34, 28 },
"RST"
};
Button button_mic_app {
{ 84, (35 * 8) - 4, 72, 28 },
"MIC TX"
};
Button button_mic_app {
{ 84, (35 * 8) - 4, 72, 28 },
"MIC TX"
};
ButtonWithEncoder button_remove {
{ 168, (35 * 8) - 4, 72, 28 },
"<REMOVE>"
};
ButtonWithEncoder button_remove {
{ 168, (35 * 8) - 4, 72, 28 },
"<REMOVE>"
};
std::unique_ptr<ReconThread> recon_thread { };
std::unique_ptr<ReconThread> recon_thread { };
MessageHandlerRegistration message_handler_retune {
Message::ID::Retune,
[this](const Message* const p) {
const auto message = *reinterpret_cast<const RetuneMessage*>(p);
this->handle_retune(message.freq,message.range);
}
};
MessageHandlerRegistration message_handler_coded_squelch {
Message::ID::CodedSquelch,
[this](const Message* const p) {
const auto message = *reinterpret_cast<const CodedSquelchMessage*>(p);
this->handle_coded_squelch(message.value);
}
};
MessageHandlerRegistration message_handler_stats {
Message::ID::ChannelStatistics,
[this](const Message* const p) {
this->on_statistics_update(static_cast<const ChannelStatisticsMessage*>(p)->statistics);
}
};
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
};
MessageHandlerRegistration message_handler_retune {
Message::ID::Retune,
[this](const Message* const p) {
const auto message = *reinterpret_cast<const RetuneMessage*>(p);
this->handle_retune(message.freq,message.range);
}
};
MessageHandlerRegistration message_handler_stats {
Message::ID::ChannelStatistics,
[this](const Message* const p) {
this->on_statistics_update(static_cast<const ChannelStatisticsMessage*>(p)->statistics);
}
};
// app save settings
std::app_settings settings { };
std::app_settings::AppSettings app_settings { };
};
} /* namespace ui */
+232 -232
View File
@@ -34,268 +34,268 @@ using namespace portapack;
namespace ui {
bool ReconSetupLoadStrings( std::string source, std::string &input_file , std::string &output_file , uint32_t &recon_lock_duration , uint32_t &recon_lock_nb_match , int32_t &recon_squelch_level , uint32_t &recon_match_mode , int32_t &wait , uint32_t &lock_wait , int32_t &volume )
{
File settings_file;
size_t length, file_position = 0;
char * pos;
char * line_start;
char * line_end;
char file_data[257];
bool ReconSetupLoadStrings( std::string source, std::string &input_file , std::string &output_file , uint32_t &recon_lock_duration , uint32_t &recon_lock_nb_match , int32_t &recon_squelch_level , uint32_t &recon_match_mode , int32_t &wait , uint32_t &lock_wait , int32_t &volume )
{
File settings_file;
size_t length, file_position = 0;
char * pos;
char * line_start;
char * line_end;
char file_data[257];
uint32_t it = 0 ;
uint32_t nb_params = 9 ;
std::string params[ 9 ];
uint32_t it = 0 ;
uint32_t nb_params = 9 ;
std::string params[ 9 ];
bool check_sd_card = (sd_card::status() == sd_card::Status::Mounted) ? true : false ;
bool check_sd_card = (sd_card::status() == sd_card::Status::Mounted) ? true : false ;
if( check_sd_card )
{
auto result = settings_file.open( source );
if( !result.is_valid() )
{
while( it < nb_params )
{
// Read a 256 bytes block from file
settings_file.seek(file_position);
memset(file_data, 0, 257);
auto read_size = settings_file.read(file_data, 256);
if (read_size.is_error())
break ;
file_position += 256;
// Reset line_start to beginning of buffer
line_start = file_data;
pos=line_start;
while ((line_end = strstr(line_start, "\x0A"))) {
length = line_end - line_start - 1 ;
params[ it ] = string( pos , length );
it ++ ;
line_start = line_end + 1;
pos=line_start ;
if (line_start - file_data >= 256)
break;
if( it >= nb_params )
break ;
}
if (read_size.value() != 256)
break; // End of file
if( check_sd_card )
{
auto result = settings_file.open( source );
if( !result.is_valid() )
{
while( it < nb_params )
{
// Read a 256 bytes block from file
settings_file.seek(file_position);
memset(file_data, 0, 257);
auto read_size = settings_file.read(file_data, 256);
if (read_size.is_error())
break ;
file_position += 256;
// Reset line_start to beginning of buffer
line_start = file_data;
pos=line_start;
while ((line_end = strstr(line_start, "\x0A"))) {
length = line_end - line_start - 1 ;
params[ it ] = string( pos , length );
it ++ ;
line_start = line_end + 1;
pos=line_start ;
if (line_start - file_data >= 256)
break;
if( it >= nb_params )
break ;
}
if (read_size.value() != 256)
break; // End of file
// Restart at beginning of last incomplete line
file_position -= (file_data + 256 - line_start);
}
}
// Restart at beginning of last incomplete line
file_position -= (file_data + 256 - line_start);
}
}
}
}
if( it > 0 )
input_file = params[ 0 ];
else
input_file = "RECON" ;
if( it > 0 )
input_file = params[ 0 ];
else
input_file = "RECON" ;
if( it > 1 )
output_file= params[ 1 ];
else
output_file = "RECON_RESULTS" ;
if( it > 1 )
output_file= params[ 1 ];
else
output_file = "RECON_RESULTS" ;
if( it > 2 )
recon_lock_duration = strtoll( params[ 2 ].c_str() , nullptr , 10 );
else
recon_lock_duration = 50 ;
if( it > 2 )
recon_lock_duration = strtoll( params[ 2 ].c_str() , nullptr , 10 );
else
recon_lock_duration = 50 ;
if( it > 3 )
recon_lock_nb_match = strtoll( params[ 3 ].c_str() , nullptr , 10 );
else
recon_lock_nb_match = 10 ;
if( it > 3 )
recon_lock_nb_match = strtoll( params[ 3 ].c_str() , nullptr , 10 );
else
recon_lock_nb_match = 10 ;
if( it > 4 )
recon_squelch_level = strtoll( params[ 4 ].c_str() , nullptr , 10 );
else
recon_squelch_level = -14 ;
if( it > 4 )
recon_squelch_level = strtoll( params[ 4 ].c_str() , nullptr , 10 );
else
recon_squelch_level = -14 ;
if( it > 5 )
recon_match_mode = strtoll( params[ 5 ].c_str() , nullptr , 10 );
else
recon_match_mode = 0 ;
if( it > 5 )
recon_match_mode = strtoll( params[ 5 ].c_str() , nullptr , 10 );
else
recon_match_mode = 0 ;
if( it > 6 )
wait = strtoll( params[ 6 ].c_str() , nullptr , 10 );
else
wait = 5000 ;
if( it > 6 )
wait = strtoll( params[ 6 ].c_str() , nullptr , 10 );
else
wait = 5000 ;
if( it > 7 )
lock_wait = strtoll( params[ 7 ].c_str() , nullptr , 10 );
else
lock_wait = 1000 ;
if( it > 7 )
lock_wait = strtoll( params[ 7 ].c_str() , nullptr , 10 );
else
lock_wait = 1000 ;
if( it > 8 )
volume = strtoll( params[ 8 ].c_str() , nullptr , 10 );
else
volume = 40 ;
if( it > 8 )
volume = strtoll( params[ 8 ].c_str() , nullptr , 10 );
else
volume = 40 ;
if( it < nb_params )
{
/* bad number of params, signal defaults */
return false ;
}
return true ;
}
if( it < nb_params )
{
/* bad number of params, signal defaults */
return false ;
}
return true ;
}
bool ReconSetupSaveStrings( std::string dest, std::string input_file , std::string output_file , uint32_t recon_lock_duration , uint32_t recon_lock_nb_match , int32_t recon_squelch_level , uint32_t recon_match_mode , int32_t wait , uint32_t lock_wait , int32_t volume )
{
File settings_file;
bool ReconSetupSaveStrings( std::string dest, std::string input_file , std::string output_file , uint32_t recon_lock_duration , uint32_t recon_lock_nb_match , int32_t recon_squelch_level , uint32_t recon_match_mode , int32_t wait , uint32_t lock_wait , int32_t volume )
{
File settings_file;
auto result = settings_file.create( dest );
if( result.is_valid() )
return false ;
settings_file.write_line( input_file );
settings_file.write_line( output_file );
settings_file.write_line( to_string_dec_uint( recon_lock_duration ) );
settings_file.write_line( to_string_dec_uint( recon_lock_nb_match ) );
settings_file.write_line( to_string_dec_int( recon_squelch_level ) );
settings_file.write_line( to_string_dec_uint( recon_match_mode ) );
settings_file.write_line( to_string_dec_int( wait ) );
settings_file.write_line( to_string_dec_uint( lock_wait ) );
settings_file.write_line( to_string_dec_int( volume ) );
return true ;
}
auto result = settings_file.create( dest );
if( result.is_valid() )
return false ;
settings_file.write_line( input_file );
settings_file.write_line( output_file );
settings_file.write_line( to_string_dec_uint( recon_lock_duration ) );
settings_file.write_line( to_string_dec_uint( recon_lock_nb_match ) );
settings_file.write_line( to_string_dec_int( recon_squelch_level ) );
settings_file.write_line( to_string_dec_uint( recon_match_mode ) );
settings_file.write_line( to_string_dec_int( wait ) );
settings_file.write_line( to_string_dec_uint( lock_wait ) );
settings_file.write_line( to_string_dec_int( volume ) );
return true ;
}
ReconSetupViewMain::ReconSetupViewMain( NavigationView &nav , Rect parent_rect , std::string input_file , std::string output_file ) : View( parent_rect ) , _input_file { input_file } , _output_file { output_file }
{
hidden(true);
add_children({
&button_load_freqs,
&text_input_file,
&button_save_freqs,
&button_output_file,
&checkbox_autosave_freqs,
&checkbox_autostart_recon,
&checkbox_continuous,
&checkbox_clear_output
});
ReconSetupViewMain::ReconSetupViewMain( NavigationView &nav , Rect parent_rect , std::string input_file , std::string output_file ) : View( parent_rect ) , _input_file { input_file } , _output_file { output_file }
{
hidden(true);
add_children({
&button_load_freqs,
&text_input_file,
&button_save_freqs,
&button_output_file,
&checkbox_autosave_freqs,
&checkbox_autostart_recon,
&checkbox_continuous,
&checkbox_clear_output
});
checkbox_autosave_freqs.set_value( persistent_memory::recon_autosave_freqs() );
checkbox_autostart_recon.set_value( persistent_memory::recon_autostart_recon() );
checkbox_continuous.set_value( persistent_memory::recon_continuous() );
checkbox_clear_output.set_value( persistent_memory::recon_clear_output() );
checkbox_autosave_freqs.set_value( persistent_memory::recon_autosave_freqs() );
checkbox_autostart_recon.set_value( persistent_memory::recon_autostart_recon() );
checkbox_continuous.set_value( persistent_memory::recon_continuous() );
checkbox_clear_output.set_value( persistent_memory::recon_clear_output() );
text_input_file.set( _input_file );
button_output_file.set_text( _output_file );
text_input_file.set( _input_file );
button_output_file.set_text( _output_file );
button_load_freqs.on_select = [this, &nav](Button&) {
auto open_view = nav.push<FileLoadView>(".TXT");
open_view->on_changed = [this,&nav](std::filesystem::path new_file_path) {
std::string dir_filter = "FREQMAN/";
std::string str_file_path = new_file_path.string();
if (str_file_path.find(dir_filter) != string::npos) { // assert file from the FREQMAN folder
// get the filename without txt extension so we can use load_freqman_file fcn
_input_file = new_file_path.stem().string();
text_input_file.set( _input_file );
} else {
nav.display_modal("LOAD ERROR", "A valid file from\nFREQMAN directory is\nrequired.");
}
};
};
button_load_freqs.on_select = [this, &nav](Button&) {
auto open_view = nav.push<FileLoadView>(".TXT");
open_view->on_changed = [this,&nav](std::filesystem::path new_file_path) {
std::string dir_filter = "FREQMAN/";
std::string str_file_path = new_file_path.string();
if (str_file_path.find(dir_filter) != string::npos) { // assert file from the FREQMAN folder
// get the filename without txt extension so we can use load_freqman_file fcn
_input_file = new_file_path.stem().string();
text_input_file.set( _input_file );
} else {
nav.display_modal("LOAD ERROR", "A valid file from\nFREQMAN directory is\nrequired.");
}
};
};
button_save_freqs.on_select = [this, &nav](Button&) {
auto open_view = nav.push<FileLoadView>(".TXT");
open_view->on_changed = [this,&nav](std::filesystem::path new_file_path) {
std::string dir_filter = "FREQMAN/";
std::string str_file_path = new_file_path.string();
if (str_file_path.find(dir_filter) != string::npos) { // assert file from the FREQMAN folder
_output_file = new_file_path.stem().string();
button_output_file.set_text( _output_file );
} else {
nav.display_modal("LOAD ERROR", "A valid file from\nFREQMAN directory is\nrequired.");
}
};
};
button_save_freqs.on_select = [this, &nav](Button&) {
auto open_view = nav.push<FileLoadView>(".TXT");
open_view->on_changed = [this,&nav](std::filesystem::path new_file_path) {
std::string dir_filter = "FREQMAN/";
std::string str_file_path = new_file_path.string();
if (str_file_path.find(dir_filter) != string::npos) { // assert file from the FREQMAN folder
_output_file = new_file_path.stem().string();
button_output_file.set_text( _output_file );
} else {
nav.display_modal("LOAD ERROR", "A valid file from\nFREQMAN directory is\nrequired.");
}
};
};
button_output_file.on_select =[this, &nav](Button&) {
text_prompt( nav, _output_file , 28 ,
[this](std::string& buffer) {
_output_file = buffer ;
button_output_file.set_text( _output_file );
} );
};
};
button_output_file.on_select =[this, &nav](Button&) {
text_prompt( nav, _output_file , 28 ,
[this](std::string& buffer) {
_output_file = buffer ;
button_output_file.set_text( _output_file );
} );
};
};
void ReconSetupViewMain::Save( std::string &input_file , std::string &output_file ) {
persistent_memory::set_recon_autosave_freqs(checkbox_autosave_freqs.value());
persistent_memory::set_recon_autostart_recon(checkbox_autostart_recon.value());
persistent_memory::set_recon_continuous(checkbox_continuous.value());
persistent_memory::set_recon_clear_output(checkbox_clear_output.value());
input_file=_input_file ;
output_file=_output_file ;
};
void ReconSetupViewMore::Save( uint32_t &recon_lock_duration , uint32_t &recon_lock_nb_match , uint32_t &recon_match_mode ) {
persistent_memory::set_recon_load_freqs(checkbox_load_freqs.value());
persistent_memory::set_recon_load_ranges(checkbox_load_ranges.value());
persistent_memory::set_recon_load_hamradios(checkbox_load_hamradios.value());
persistent_memory::set_recon_update_ranges_when_recon(checkbox_update_ranges_when_recon.value());
recon_lock_duration = field_recon_lock_duration.value();
recon_lock_nb_match = field_recon_lock_nb_match.value();
recon_match_mode = field_recon_match_mode . selected_index_value() ;
};
void ReconSetupViewMain::Save( std::string &input_file , std::string &output_file ) {
persistent_memory::set_recon_autosave_freqs(checkbox_autosave_freqs.value());
persistent_memory::set_recon_autostart_recon(checkbox_autostart_recon.value());
persistent_memory::set_recon_continuous(checkbox_continuous.value());
persistent_memory::set_recon_clear_output(checkbox_clear_output.value());
input_file=_input_file ;
output_file=_output_file ;
};
void ReconSetupViewMore::Save( uint32_t &recon_lock_duration , uint32_t &recon_lock_nb_match , uint32_t &recon_match_mode ) {
persistent_memory::set_recon_load_freqs(checkbox_load_freqs.value());
persistent_memory::set_recon_load_ranges(checkbox_load_ranges.value());
persistent_memory::set_recon_load_hamradios(checkbox_load_hamradios.value());
persistent_memory::set_recon_update_ranges_when_recon(checkbox_update_ranges_when_recon.value());
recon_lock_duration = field_recon_lock_duration.value();
recon_lock_nb_match = field_recon_lock_nb_match.value();
recon_match_mode = field_recon_match_mode . selected_index_value() ;
};
void ReconSetupViewMain::focus() {
button_load_freqs.focus();
}
void ReconSetupViewMain::focus() {
button_load_freqs.focus();
}
ReconSetupViewMore::ReconSetupViewMore( NavigationView &nav , Rect parent_rect , uint32_t recon_lock_duration , uint32_t recon_lock_nb_match , uint32_t recon_match_mode ) : View( parent_rect ), _recon_lock_duration { recon_lock_duration } , _recon_lock_nb_match { recon_lock_nb_match } , _recon_match_mode { recon_match_mode }
{
(void)nav;
hidden(true);
ReconSetupViewMore::ReconSetupViewMore( NavigationView &nav , Rect parent_rect , uint32_t recon_lock_duration , uint32_t recon_lock_nb_match , uint32_t recon_match_mode ) : View( parent_rect ), _recon_lock_duration { recon_lock_duration } , _recon_lock_nb_match { recon_lock_nb_match } , _recon_match_mode { recon_match_mode }
{
(void)nav;
hidden(true);
add_children({
&checkbox_load_freqs,
&checkbox_load_ranges,
&checkbox_load_hamradios,
&checkbox_update_ranges_when_recon,
&text_recon_lock_duration,
&field_recon_lock_duration,
&text_recon_lock_nb,
&field_recon_lock_nb_match,
&field_recon_match_mode,
});
add_children({
&checkbox_load_freqs,
&checkbox_load_ranges,
&checkbox_load_hamradios,
&checkbox_update_ranges_when_recon,
&text_recon_lock_duration,
&field_recon_lock_duration,
&text_recon_lock_nb,
&field_recon_lock_nb_match,
&field_recon_match_mode,
});
checkbox_load_freqs.set_value( persistent_memory::recon_load_freqs() );
checkbox_load_ranges.set_value( persistent_memory::recon_load_ranges() );
checkbox_load_hamradios.set_value( persistent_memory::recon_load_hamradios() );
checkbox_update_ranges_when_recon.set_value( persistent_memory::recon_update_ranges_when_recon() );
field_recon_lock_duration.set_value( _recon_lock_duration );
field_recon_lock_nb_match.set_value( _recon_lock_nb_match );
field_recon_match_mode.set_by_value( _recon_match_mode );
};
checkbox_load_freqs.set_value( persistent_memory::recon_load_freqs() );
checkbox_load_ranges.set_value( persistent_memory::recon_load_ranges() );
checkbox_load_hamradios.set_value( persistent_memory::recon_load_hamradios() );
checkbox_update_ranges_when_recon.set_value( persistent_memory::recon_update_ranges_when_recon() );
field_recon_lock_duration.set_value( _recon_lock_duration );
field_recon_lock_nb_match.set_value( _recon_lock_nb_match );
field_recon_match_mode.set_by_value( _recon_match_mode );
};
void ReconSetupViewMore::focus() {
checkbox_load_freqs.focus();
}
void ReconSetupViewMore::focus() {
checkbox_load_freqs.focus();
}
void ReconSetupView::focus() {
viewMain.focus();
}
void ReconSetupView::focus() {
viewMain.focus();
}
ReconSetupView::ReconSetupView(
NavigationView& nav , std::string _input_file , std::string _output_file , uint32_t _recon_lock_duration , uint32_t _recon_lock_nb_match , uint32_t _recon_match_mode ) : nav_ { nav } , input_file { _input_file } , output_file { _output_file } , recon_lock_duration { _recon_lock_duration } , recon_lock_nb_match { _recon_lock_nb_match } , recon_match_mode { _recon_match_mode }
{
add_children({
&tab_view,
&viewMain,
&viewMore,
&button_save
});
ReconSetupView::ReconSetupView(
NavigationView& nav , std::string _input_file , std::string _output_file , uint32_t _recon_lock_duration , uint32_t _recon_lock_nb_match , uint32_t _recon_match_mode ) : nav_ { nav } , input_file { _input_file } , output_file { _output_file } , recon_lock_duration { _recon_lock_duration } , recon_lock_nb_match { _recon_lock_nb_match } , recon_match_mode { _recon_match_mode }
{
add_children({
&tab_view,
&viewMain,
&viewMore,
&button_save
});
button_save.on_select = [this,&nav](Button&) {
viewMain.Save( input_file , output_file );
viewMore.Save( recon_lock_duration , recon_lock_nb_match , recon_match_mode );
std::vector<std::string> messages ;
messages.push_back( input_file );
messages.push_back( output_file );
messages.push_back( to_string_dec_uint( recon_lock_duration ) );
messages.push_back( to_string_dec_uint( recon_lock_nb_match ) );
messages.push_back( to_string_dec_uint( recon_match_mode ) );
on_changed( messages );
nav.pop();
};
}
button_save.on_select = [this,&nav](Button&) {
viewMain.Save( input_file , output_file );
viewMore.Save( recon_lock_duration , recon_lock_nb_match , recon_match_mode );
std::vector<std::string> messages ;
messages.push_back( input_file );
messages.push_back( output_file );
messages.push_back( to_string_dec_uint( recon_lock_duration ) );
messages.push_back( to_string_dec_uint( recon_lock_nb_match ) );
messages.push_back( to_string_dec_uint( recon_match_mode ) );
on_changed( messages );
nav.pop();
};
}
} /* namespace ui */
+134 -134
View File
@@ -29,166 +29,166 @@
namespace ui {
bool ReconSetupLoadStrings( std::string source, std::string &input_file , std::string &output_file , uint32_t &recon_lock_duration , uint32_t &recon_lock_nb_match , int32_t &recon_squelch_level , uint32_t &recon_match_mode , int32_t &wait , uint32_t &lock_wait , int32_t &volume );
bool ReconSetupSaveStrings( std::string dest, const std::string input_file , const std::string output_file , const uint32_t recon_lock_duration , const uint32_t recon_lock_nb_match , int32_t recon_squelch_level , uint32_t recon_match_mode , int32_t wait , uint32_t lock_wait , int32_t volume );
bool ReconSetupLoadStrings( std::string source, std::string &input_file , std::string &output_file , uint32_t &recon_lock_duration , uint32_t &recon_lock_nb_match , int32_t &recon_squelch_level , uint32_t &recon_match_mode , int32_t &wait , uint32_t &lock_wait , int32_t &volume );
bool ReconSetupSaveStrings( std::string dest, const std::string input_file , const std::string output_file , const uint32_t recon_lock_duration , const uint32_t recon_lock_nb_match , int32_t recon_squelch_level , uint32_t recon_match_mode , int32_t wait , uint32_t lock_wait , int32_t volume );
class ReconSetupViewMain : public View {
public:
ReconSetupViewMain( NavigationView& nav, Rect parent_rect , std::string input_file , std::string output_file );
void Save( std::string &input_file , std::string &output_file );
void focus() override;
class ReconSetupViewMain : public View {
public:
ReconSetupViewMain( NavigationView& nav, Rect parent_rect , std::string input_file , std::string output_file );
void Save( std::string &input_file , std::string &output_file );
void focus() override;
private:
std::string _input_file = { "RECON" };
std::string _output_file = { "RECON_RESULTS" };
private:
std::string _input_file = { "RECON" };
std::string _output_file = { "RECON_RESULTS" };
Button button_load_freqs {
{ 1 * 8 , 12 , 18 * 8 , 22 },
"select input file"
};
Text text_input_file {
{ 1 * 8 , 4 + 2 * 16, 18 * 8, 22 },
"RECON"
};
Button button_load_freqs {
{ 1 * 8 , 12 , 18 * 8 , 22 },
"select input file"
};
Text text_input_file {
{ 1 * 8 , 4 + 2 * 16, 18 * 8, 22 },
"RECON"
};
Button button_save_freqs {
{ 1 * 8 , 4 * 16 - 8 , 18 * 8 , 22 },
"select output file"
};
Button button_output_file {
{ 1 * 8 , 5 * 16 - 2, 18 * 8, 22 },
"RECON_RESULTS"
};
Button button_save_freqs {
{ 1 * 8 , 4 * 16 - 8 , 18 * 8 , 22 },
"select output file"
};
Button button_output_file {
{ 1 * 8 , 5 * 16 - 2, 18 * 8, 22 },
"RECON_RESULTS"
};
Checkbox checkbox_autosave_freqs {
{ 1 * 8, 7 * 16 - 4 },
3,
"autosave freqs"
};
Checkbox checkbox_autosave_freqs {
{ 1 * 8, 7 * 16 - 4 },
3,
"autosave freqs"
};
Checkbox checkbox_autostart_recon {
{ 1 * 8, 9 * 16 - 4 },
3,
"autostart recon"
};
Checkbox checkbox_autostart_recon {
{ 1 * 8, 9 * 16 - 4 },
3,
"autostart recon"
};
Checkbox checkbox_continuous {
{ 1 * 8, 11 * 16 - 4 },
3,
"continuous"
};
Checkbox checkbox_clear_output {
{ 1 * 8, 13 * 16 - 4 },
3,
"clear output at start"
};
};
Checkbox checkbox_continuous {
{ 1 * 8, 11 * 16 - 4 },
3,
"continuous"
};
Checkbox checkbox_clear_output {
{ 1 * 8, 13 * 16 - 4 },
3,
"clear output at start"
};
};
class ReconSetupViewMore : public View {
public:
ReconSetupViewMore( NavigationView& nav, Rect parent_rect , const uint32_t _recon_lock_duration , const uint32_t _recon_lock_nb_match , const uint32_t _recon_match_mode );
class ReconSetupViewMore : public View {
public:
ReconSetupViewMore( NavigationView& nav, Rect parent_rect , const uint32_t _recon_lock_duration , const uint32_t _recon_lock_nb_match , const uint32_t _recon_match_mode );
void Save( uint32_t &recon_lock_duration , uint32_t &recon_lock_nb_match , uint32_t &recon_match_mode );
void Save( uint32_t &recon_lock_duration , uint32_t &recon_lock_nb_match , uint32_t &recon_match_mode );
void focus() override;
void focus() override;
private:
private:
const uint32_t _recon_lock_duration = 50 ;
const uint32_t _recon_lock_nb_match = 10 ;
const uint32_t _recon_match_mode = 0 ;
const uint32_t _recon_lock_duration = 50 ;
const uint32_t _recon_lock_nb_match = 10 ;
const uint32_t _recon_match_mode = 0 ;
Checkbox checkbox_load_freqs {
{ 1 * 8, 12 },
3,
"input: load freqs"
};
Checkbox checkbox_load_freqs {
{ 1 * 8, 12 },
3,
"input: load freqs"
};
Checkbox checkbox_load_ranges {
{ 1 * 8, 42 },
3,
"input: load ranges"
};
Checkbox checkbox_load_ranges {
{ 1 * 8, 42 },
3,
"input: load ranges"
};
Checkbox checkbox_load_hamradios {
{ 1 * 8, 72 },
3,
"input: load hamradios"
};
Checkbox checkbox_load_hamradios {
{ 1 * 8, 72 },
3,
"input: load hamradios"
};
Checkbox checkbox_update_ranges_when_recon {
{ 1 * 8, 102 },
3,
"auto update m-ranges"
};
Text text_recon_lock_duration {
{ 1 * 8 , 132 , 22 * 8 , 22 },
" ms (lock duration)"
};
NumberField field_recon_lock_duration {
{ 1 * 8, 132 }, // position X , Y
4, // number of displayed digits (even empty)
{ 50 , 990 }, // range of number
10, // rotary encoder increment
' ', // filling character
false // can loop
};
Text text_recon_lock_nb {
{ 1 * 8 , 162 , 25 * 8 , 22 },
" x (nb lock to match freq)"
};
NumberField field_recon_lock_nb_match {
{ 1 * 8, 162 },
4,
{ 1, 99 },
1,
' ',
false
};
OptionsField field_recon_match_mode {
{ 1 * 8, 192 },
20, // CONTINUOUS MATCH MODE / SPARSE TIMED MATCH MODE
{
{ "SQL MATCH: CONTINOUS" , 0 },
{ "SQL MATCH: SPARSE" , 1 }
}
};
};
Checkbox checkbox_update_ranges_when_recon {
{ 1 * 8, 102 },
3,
"auto update m-ranges"
};
Text text_recon_lock_duration {
{ 1 * 8 , 132 , 22 * 8 , 22 },
" ms (lock duration)"
};
NumberField field_recon_lock_duration {
{ 1 * 8, 132 }, // position X , Y
4, // number of displayed digits (even empty)
{ 50 , 990 }, // range of number
10, // rotary encoder increment
' ', // filling character
false // can loop
};
Text text_recon_lock_nb {
{ 1 * 8 , 162 , 25 * 8 , 22 },
" x (nb lock to match freq)"
};
NumberField field_recon_lock_nb_match {
{ 1 * 8, 162 },
4,
{ 1, 99 },
1,
' ',
false
};
OptionsField field_recon_match_mode {
{ 1 * 8, 192 },
20, // CONTINUOUS MATCH MODE / SPARSE TIMED MATCH MODE
{
{ "SQL MATCH: CONTINOUS" , 0 },
{ "SQL MATCH: SPARSE" , 1 }
}
};
};
class ReconSetupView : public View {
public:
ReconSetupView( NavigationView& nav , std::string _input_file , std::string _output_file , const uint32_t _recon_lock_duration , const uint32_t _recon_lock_nb_match , const uint32_t _recon_match_mode );
class ReconSetupView : public View {
public:
ReconSetupView( NavigationView& nav , std::string _input_file , std::string _output_file , const uint32_t _recon_lock_duration , const uint32_t _recon_lock_nb_match , const uint32_t _recon_match_mode );
std::function<void( std::vector<std::string> messages )> on_changed { };
std::function<void( std::vector<std::string> messages )> on_changed { };
void focus() override;
void focus() override;
std::string title() const override { return "Recon setup"; };
std::string title() const override { return "Recon setup"; };
private:
private:
NavigationView& nav_ ;
NavigationView& nav_ ;
std::string input_file = { "RECON" };
std::string output_file = { "RECON_RESULTS" };
uint32_t recon_lock_duration = 50 ;
uint32_t recon_lock_nb_match = 10 ;
uint32_t recon_match_mode = 0 ;
std::string input_file = { "RECON" };
std::string output_file = { "RECON_RESULTS" };
uint32_t recon_lock_duration = 50 ;
uint32_t recon_lock_nb_match = 10 ;
uint32_t recon_match_mode = 0 ;
Rect view_rect = { 0, 3 * 8, 240, 230 };
Rect view_rect = { 0, 3 * 8, 240, 230 };
ReconSetupViewMain viewMain{ nav_ , view_rect , input_file , output_file };
ReconSetupViewMore viewMore{ nav_ , view_rect , recon_lock_duration , recon_lock_nb_match , recon_match_mode };
ReconSetupViewMain viewMain{ nav_ , view_rect , input_file , output_file };
ReconSetupViewMore viewMore{ nav_ , view_rect , recon_lock_duration , recon_lock_nb_match , recon_match_mode };
TabView tab_view {
{ "Main", Color::cyan() , &viewMain },
{ "More", Color::green(), &viewMore }
};
Button button_save {
{ 9 * 8, 255, 14 * 8 , 40 },
"SAVE"
};
};
TabView tab_view {
{ "Main", Color::cyan() , &viewMain },
{ "More", Color::green(), &viewMore }
};
Button button_save {
{ 9 * 8, 255, 14 * 8 , 40 },
"SAVE"
};
};
} /* namespace ui */
@@ -0,0 +1,62 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2023 Bernd Herzog
*
* 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_sd_over_usb.hpp"
#include "portapack_shared_memory.hpp"
namespace ui {
SdOverUsbView::SdOverUsbView(NavigationView& nav) : nav_ (nav) {
add_children({
&labels,
&button_run
});
button_run.on_select = [this](Button&) {
ui::Painter painter;
painter.fill_rectangle(
{ 0, 0, portapack::display.width(), portapack::display.height() },
ui::Color::black()
);
painter.draw_bitmap(
{ portapack::display.width()/2-8, portapack::display.height()/2-8 },
bitmap_icon_hackrf,
ui::Color::yellow(),
ui::Color::black()
);
sdcDisconnect(&SDCD1);
sdcStop(&SDCD1);
portapack::shutdown(true);
m4_init(portapack::spi_flash::image_tag_usb_sd, portapack::memory::map::m4_code, false);
m0_halt();
/* will not return*/
};
}
void SdOverUsbView::focus() {
button_run.focus();
}
} /* namespace ui */
@@ -0,0 +1,64 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2023 Bernd Herzog
*
* 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_SD_OVER_USB_H__
#define __UI_SD_OVER_USB_H__
#include "ui_widget.hpp"
#include "ui_navigation.hpp"
#include "string_format.hpp"
#include "ff.h"
#include "baseband_api.hpp"
#include "core_control.hpp"
#include <cstdint>
namespace ui {
class SdOverUsbView : public View {
public:
SdOverUsbView(NavigationView& nav);
void focus() override;
std::string title() const override { return "Flash Utility"; };
private:
NavigationView& nav_;
Labels labels {
{ { 3 * 8, 2 * 16 }, "Click Run to start the", Color::white() },
{ { 3 * 8, 3 * 16 }, "USB Mass Storage Mode.", Color::white() },
{ { 3 * 8, 5 * 16 }, "It can take up to 20s", Color::white() },
{ { 3 * 8, 6 * 16 }, "for the drive to be", Color::white() },
{ { 3 * 8, 7 * 16 }, "available.", Color::white() },
};
Button button_run {
{ 9 * 8, 15 * 16, 12 * 8, 3 * 16 },
"Run"
};
};
} /* namespace ui */
#endif /*__UI_SD_OVER_USB_H__*/
+486 -337
View File
@@ -42,375 +42,524 @@ using namespace portapack;
namespace ui {
SetDateTimeView::SetDateTimeView(
NavigationView& nav
) {
button_save.on_select = [&nav, this](Button&){
const auto model = this->form_collect();
const rtc::RTC new_datetime {
model.year, model.month, model.day,
model.hour, model.minute, model.second
SetDateTimeView::SetDateTimeView(
NavigationView& nav
) {
button_save.on_select = [&nav, this](Button&){
const auto model = this->form_collect();
const rtc::RTC new_datetime {
model.year, model.month, model.day,
model.hour, model.minute, model.second
};
rtcSetTime(&RTCD1, &new_datetime);
nav.pop();
},
button_cancel.on_select = [&nav](Button&){
nav.pop();
},
add_children({
&labels,
&field_year,
&field_month,
&field_day,
&field_hour,
&field_minute,
&field_second,
&button_save,
&button_cancel,
});
rtc::RTC datetime;
rtcGetTime(&RTCD1, &datetime);
SetDateTimeModel model {
datetime.year(),
datetime.month(),
datetime.day(),
datetime.hour(),
datetime.minute(),
datetime.second()
};
rtcSetTime(&RTCD1, &new_datetime);
nav.pop();
},
button_cancel.on_select = [&nav](Button&){
nav.pop();
},
add_children({
&labels,
&field_year,
&field_month,
&field_day,
&field_hour,
&field_minute,
&field_second,
&button_save,
&button_cancel,
});
rtc::RTC datetime;
rtcGetTime(&RTCD1, &datetime);
SetDateTimeModel model {
datetime.year(),
datetime.month(),
datetime.day(),
datetime.hour(),
datetime.minute(),
datetime.second()
};
form_init(model);
}
void SetDateTimeView::focus() {
button_cancel.focus();
}
void SetDateTimeView::form_init(const SetDateTimeModel& model) {
field_year.set_value(model.year);
field_month.set_value(model.month);
field_day.set_value(model.day);
field_hour.set_value(model.hour);
field_minute.set_value(model.minute);
field_second.set_value(model.second);
}
SetDateTimeModel SetDateTimeView::form_collect() {
return {
.year = static_cast<uint16_t>(field_year.value()),
.month = static_cast<uint8_t>(field_month.value()),
.day = static_cast<uint8_t>(field_day.value()),
.hour = static_cast<uint8_t>(field_hour.value()),
.minute = static_cast<uint8_t>(field_minute.value()),
.second = static_cast<uint8_t>(field_second.value())
};
}
SetRadioView::SetRadioView(
NavigationView& nav
) {
button_cancel.on_select = [&nav](Button&){
nav.pop();
};
const auto reference = portapack::clock_manager.get_reference();
std::string source_name("---");
switch(reference.source) {
case ClockManager::ReferenceSource::Xtal: source_name = "HackRF"; break;
case ClockManager::ReferenceSource::PortaPack: source_name = "PortaPack"; break;
case ClockManager::ReferenceSource::External: source_name = "External"; break;
form_init(model);
}
value_source.set(source_name);
value_source_frequency.set(to_string_dec_uint(reference.frequency / 1000000, 2) + "." + to_string_dec_uint((reference.frequency % 1000000) / 100, 4, '0') + " MHz");
void SetDateTimeView::focus() {
button_cancel.focus();
}
label_source.set_style(&style_text);
value_source.set_style(&style_text);
value_source_frequency.set_style(&style_text);
void SetDateTimeView::form_init(const SetDateTimeModel& model) {
field_year.set_value(model.year);
field_month.set_value(model.month);
field_day.set_value(model.day);
field_hour.set_value(model.hour);
field_minute.set_value(model.minute);
field_second.set_value(model.second);
}
add_children({
&label_source,
&value_source,
&value_source_frequency,
});
SetDateTimeModel SetDateTimeView::form_collect() {
return {
.year = static_cast<uint16_t>(field_year.value()),
.month = static_cast<uint8_t>(field_month.value()),
.day = static_cast<uint8_t>(field_day.value()),
.hour = static_cast<uint8_t>(field_hour.value()),
.minute = static_cast<uint8_t>(field_minute.value()),
.second = static_cast<uint8_t>(field_second.value())
};
}
SetRadioView::SetRadioView(
NavigationView& nav
) {
button_cancel.on_select = [&nav](Button&){
nav.pop();
};
const auto reference = portapack::clock_manager.get_reference();
std::string source_name("---");
switch(reference.source) {
case ClockManager::ReferenceSource::Xtal: source_name = "HackRF"; break;
case ClockManager::ReferenceSource::PortaPack: source_name = "PortaPack"; break;
case ClockManager::ReferenceSource::External: source_name = "External"; break;
}
value_source.set(source_name);
value_source_frequency.set(to_string_dec_uint(reference.frequency / 1000000, 2) + "." + to_string_dec_uint((reference.frequency % 1000000) / 100, 4, '0') + " MHz");
label_source.set_style(&style_text);
value_source.set_style(&style_text);
value_source_frequency.set_style(&style_text);
if( reference.source == ClockManager::ReferenceSource::Xtal ) {
add_children({
&labels_correction,
&field_ppm,
});
&label_source,
&value_source,
&value_source_frequency,
});
if( reference.source == ClockManager::ReferenceSource::Xtal ) {
add_children({
&labels_correction,
&field_ppm,
});
}
add_children({
&check_clkout,
&field_clkout_freq,
&labels_clkout_khz,
&value_freq_step,
&labels_bias,
&check_bias,
&button_save,
&button_cancel
});
SetFrequencyCorrectionModel model {
static_cast<int8_t>(portapack::persistent_memory::correction_ppb() / 1000) , 0
};
form_init(model);
check_clkout.set_value(portapack::persistent_memory::clkout_enabled());
check_clkout.on_select = [this](Checkbox&, bool v) {
clock_manager.enable_clock_output(v);
portapack::persistent_memory::set_clkout_enabled(v);
StatusRefreshMessage message { };
EventDispatcher::send_message(message);
};
field_clkout_freq.set_value(portapack::persistent_memory::clkout_freq());
value_freq_step.set_style(&style_text);
field_clkout_freq.on_select = [this](NumberField&) {
freq_step_khz++;
if(freq_step_khz > 3) {
freq_step_khz = 0;
}
switch(freq_step_khz) {
case 0:
value_freq_step.set(" |");
break;
case 1:
value_freq_step.set(" | ");
break;
case 2:
value_freq_step.set(" | ");
break;
case 3:
value_freq_step.set("| ");
break;
}
field_clkout_freq.set_step(pow(10, freq_step_khz));
};
check_bias.set_value(portapack::get_antenna_bias());
check_bias.on_select = [this](Checkbox&, bool v) {
portapack::set_antenna_bias(v);
StatusRefreshMessage message { };
EventDispatcher::send_message(message);
};
button_save.on_select = [this, &nav](Button&){
const auto model = this->form_collect();
portapack::persistent_memory::set_correction_ppb(model.ppm * 1000);
portapack::persistent_memory::set_clkout_freq(model.freq);
clock_manager.enable_clock_output(portapack::persistent_memory::clkout_enabled());
nav.pop();
};
}
add_children({
&check_hamitup,
&button_hamitup_freq,
&check_clkout,
&field_clkout_freq,
&labels_clkout_khz,
&value_freq_step,
&labels_bias,
&check_bias,
&button_save,
&button_cancel
});
void SetRadioView::focus() {
button_save.focus();
}
SetFrequencyCorrectionModel model {
static_cast<int8_t>(portapack::persistent_memory::correction_ppb() / 1000) , 0
};
void SetRadioView::form_init(const SetFrequencyCorrectionModel& model) {
field_ppm.set_value(model.ppm);
}
form_init(model);
check_clkout.set_value(portapack::persistent_memory::clkout_enabled());
check_clkout.on_select = [this](Checkbox&, bool v) {
clock_manager.enable_clock_output(v);
portapack::persistent_memory::set_clkout_enabled(v);
StatusRefreshMessage message { };
EventDispatcher::send_message(message);
};
check_hamitup.set_value(portapack::persistent_memory::config_hamitup());
check_hamitup.on_select = [this](Checkbox&, bool v) {
portapack::persistent_memory::set_config_hamitup(v);
// Retune to take hamitup change in account
receiver_model.set_tuning_frequency( portapack::persistent_memory::tuned_frequency() );
//Refresh status bar with/out UP!
StatusRefreshMessage message { };
EventDispatcher::send_message(message);
};
button_hamitup_freq.set_text( to_string_short_freq( portapack::persistent_memory::config_hamitup_freq() ) + "MHz");
button_hamitup_freq.on_select = [this, &nav](Button& button) {
auto new_view = nav.push<FrequencyKeypadView>(portapack::persistent_memory::config_hamitup_freq() );
new_view->on_changed = [this, &button](rf::Frequency f) {
portapack::persistent_memory::set_config_hamitup_freq( f );
// Retune to take hamitup change in account
receiver_model.set_tuning_frequency( portapack::persistent_memory::tuned_frequency() );
button_hamitup_freq.set_text( "<" + to_string_short_freq( f ) + " MHz>" );
};
};
field_clkout_freq.set_value(portapack::persistent_memory::clkout_freq());
value_freq_step.set_style(&style_text);
field_clkout_freq.on_select = [this](NumberField&) {
freq_step_khz++;
if(freq_step_khz > 3) {
freq_step_khz = 0;
}
switch(freq_step_khz) {
case 0:
value_freq_step.set(" |");
break;
case 1:
value_freq_step.set(" | ");
break;
case 2:
value_freq_step.set(" | ");
break;
case 3:
value_freq_step.set("| ");
break;
}
field_clkout_freq.set_step(pow(10, freq_step_khz));
};
check_bias.set_value(portapack::get_antenna_bias());
check_bias.on_select = [this](Checkbox&, bool v) {
portapack::set_antenna_bias(v);
StatusRefreshMessage message { };
EventDispatcher::send_message(message);
};
button_save.on_select = [this, &nav](Button&){
const auto model = this->form_collect();
portapack::persistent_memory::set_correction_ppb(model.ppm * 1000);
portapack::persistent_memory::set_clkout_freq(model.freq);
clock_manager.enable_clock_output(portapack::persistent_memory::clkout_enabled());
nav.pop();
};
}
void SetRadioView::focus() {
button_save.focus();
}
void SetRadioView::form_init(const SetFrequencyCorrectionModel& model) {
field_ppm.set_value(model.ppm);
}
SetFrequencyCorrectionModel SetRadioView::form_collect() {
return {
.ppm = static_cast<int8_t>(field_ppm.value()),
.freq = static_cast<uint32_t>(field_clkout_freq.value()),
};
}
SetUIView::SetUIView(NavigationView& nav) {
add_children({
&checkbox_disable_touchscreen,
&checkbox_speaker,
&checkbox_bloff,
&options_bloff,
&checkbox_showsplash,
&checkbox_showclock,
&options_clockformat,
&checkbox_guireturnflag,
&button_save,
&button_cancel
});
checkbox_disable_touchscreen.set_value(persistent_memory::disable_touchscreen());
checkbox_speaker.set_value(persistent_memory::config_speaker());
checkbox_showsplash.set_value(persistent_memory::config_splash());
checkbox_showclock.set_value(!persistent_memory::hide_clock());
checkbox_guireturnflag.set_value(persistent_memory::show_gui_return_icon());
const auto backlight_config = persistent_memory::config_backlight_timer();
checkbox_bloff.set_value(backlight_config.timeout_enabled());
options_bloff.set_by_value(backlight_config.timeout_enum());
if (persistent_memory::clock_with_date()) {
options_clockformat.set_selected_index(1);
} else {
options_clockformat.set_selected_index(0);
SetFrequencyCorrectionModel SetRadioView::form_collect() {
return {
.ppm = static_cast<int8_t>(field_ppm.value()),
.freq = static_cast<uint32_t>(field_clkout_freq.value()),
};
}
button_save.on_select = [&nav, this](Button&) {
persistent_memory::set_config_backlight_timer({
(persistent_memory::backlight_timeout_t)options_bloff.selected_index_value(),
checkbox_bloff.value()
});
if (checkbox_showclock.value()){
if (options_clockformat.selected_index() == 1)
persistent_memory::set_clock_with_date(true);
else
persistent_memory::set_clock_with_date(false);
SetUIView::SetUIView(NavigationView& nav) {
add_children({
&checkbox_disable_touchscreen,
&checkbox_speaker,
&checkbox_bloff,
&options_bloff,
&checkbox_showsplash,
&checkbox_showclock,
&options_clockformat,
&checkbox_guireturnflag,
&button_save,
&button_cancel
});
checkbox_disable_touchscreen.set_value(persistent_memory::disable_touchscreen());
checkbox_speaker.set_value(persistent_memory::config_speaker());
checkbox_showsplash.set_value(persistent_memory::config_splash());
checkbox_showclock.set_value(!persistent_memory::hide_clock());
checkbox_guireturnflag.set_value(persistent_memory::show_gui_return_icon());
const auto backlight_config = persistent_memory::config_backlight_timer();
checkbox_bloff.set_value(backlight_config.timeout_enabled());
options_bloff.set_by_value(backlight_config.timeout_enum());
if (persistent_memory::clock_with_date()) {
options_clockformat.set_selected_index(1);
} else {
options_clockformat.set_selected_index(0);
}
if (checkbox_speaker.value()) audio::output::speaker_mute(); //Just mute audio if speaker is disabled
persistent_memory::set_config_speaker(checkbox_speaker.value()); //Store Speaker status
StatusRefreshMessage message { }; //Refresh status bar with/out speaker
EventDispatcher::send_message(message);
persistent_memory::set_config_splash(checkbox_showsplash.value());
persistent_memory::set_clock_hidden(!checkbox_showclock.value());
persistent_memory::set_gui_return_icon(checkbox_guireturnflag.value());
persistent_memory::set_disable_touchscreen(checkbox_disable_touchscreen.value());
nav.pop();
};
button_cancel.on_select = [&nav, this](Button&) {
nav.pop();
};
}
void SetUIView::focus() {
button_save.focus();
}
button_save.on_select = [&nav, this](Button&) {
persistent_memory::set_config_backlight_timer({
(persistent_memory::backlight_timeout_t)options_bloff.selected_index_value(),
checkbox_bloff.value()
});
if (checkbox_showclock.value()){
if (options_clockformat.selected_index() == 1)
persistent_memory::set_clock_with_date(true);
else
persistent_memory::set_clock_with_date(false);
}
if (checkbox_speaker.value()) audio::output::speaker_mute(); //Just mute audio if speaker is disabled
persistent_memory::set_config_speaker(checkbox_speaker.value()); //Store Speaker status
StatusRefreshMessage message { }; //Refresh status bar with/out speaker
EventDispatcher::send_message(message);
persistent_memory::set_config_splash(checkbox_showsplash.value());
persistent_memory::set_clock_hidden(!checkbox_showclock.value());
persistent_memory::set_gui_return_icon(checkbox_guireturnflag.value());
persistent_memory::set_disable_touchscreen(checkbox_disable_touchscreen.value());
nav.pop();
};
button_cancel.on_select = [&nav, this](Button&) {
nav.pop();
};
}
void SetUIView::focus() {
button_save.focus();
}
// ---------------------------------------------------------
// Appl. Settings
// ---------------------------------------------------------
SetAppSettingsView::SetAppSettingsView(NavigationView& nav) {
add_children({
&checkbox_load_app_settings,
&checkbox_save_app_settings,
&button_save,
&button_cancel
});
checkbox_load_app_settings.set_value(persistent_memory::load_app_settings());
checkbox_save_app_settings.set_value(persistent_memory::save_app_settings());
// ---------------------------------------------------------
// Appl. Settings
// ---------------------------------------------------------
SetAppSettingsView::SetAppSettingsView(NavigationView& nav) {
add_children({
&checkbox_load_app_settings,
&checkbox_save_app_settings,
&button_save,
&button_cancel
});
checkbox_load_app_settings.set_value(persistent_memory::load_app_settings());
checkbox_save_app_settings.set_value(persistent_memory::save_app_settings());
button_save.on_select = [&nav, this](Button&) {
persistent_memory::set_load_app_settings(checkbox_load_app_settings.value());
persistent_memory::set_save_app_settings(checkbox_save_app_settings.value());
nav.pop();
};
button_cancel.on_select = [&nav, this](Button&) {
nav.pop();
};
}
button_save.on_select = [&nav, this](Button&) {
persistent_memory::set_load_app_settings(checkbox_load_app_settings.value());
persistent_memory::set_save_app_settings(checkbox_save_app_settings.value());
nav.pop();
};
button_cancel.on_select = [&nav, this](Button&) {
nav.pop();
};
}
void SetAppSettingsView::focus() {
button_save.focus();
}
void SetAppSettingsView::focus() {
button_save.focus();
}
SetAudioView::SetAudioView(NavigationView& nav) {
add_children({
&labels,
&field_tone_mix,
&button_save,
&button_cancel
});
// ---------------------------------------------------------
// Converter Settings
// ---------------------------------------------------------
SetConverterSettingsView::SetConverterSettingsView(NavigationView& nav) {
add_children({
&check_show_converter,
&check_converter,
&converter_mode,
&button_converter_freq,
&button_save,
&button_cancel
});
field_tone_mix.set_value(persistent_memory::tone_mix());
button_save.on_select = [&nav, this](Button&) {
persistent_memory::set_tone_mix(field_tone_mix.value());
nav.pop();
};
check_show_converter.set_value(!portapack::persistent_memory::config_hide_converter());
check_show_converter.on_select = [this](Checkbox&, bool v) {
portapack::persistent_memory::set_config_hide_converter(!v);
if( !v )
{
check_converter.set_value(false);
}
// Retune to take converter change in account
receiver_model.set_tuning_frequency( portapack::persistent_memory::tuned_frequency() );
//Refresh status bar with/out converter
StatusRefreshMessage message { };
EventDispatcher::send_message(message);
};
button_cancel.on_select = [&nav, this](Button&) {
nav.pop();
};
}
check_converter.set_value(portapack::persistent_memory::config_converter());
check_converter.on_select = [this](Checkbox&, bool v) {
if( v )
{
check_show_converter.set_value(true);
portapack::persistent_memory::set_config_hide_converter(false);
}
portapack::persistent_memory::set_config_converter(v);
// Retune to take converter change in account
receiver_model.set_tuning_frequency( portapack::persistent_memory::tuned_frequency() );
//Refresh status bar with/out converter
StatusRefreshMessage message { };
EventDispatcher::send_message(message);
};
void SetAudioView::focus() {
button_save.focus();
}
converter_mode.set_by_value( portapack::persistent_memory::config_updown_converter() );
converter_mode.on_change = [this](size_t, OptionsField::value_t v) {
portapack::persistent_memory::set_config_updown_converter( v );
//Refresh status bar with icon up or down
StatusRefreshMessage message { };
EventDispatcher::send_message(message);
};
SetQRCodeView::SetQRCodeView(NavigationView& nav) {
add_children({
&checkbox_bigger_qr,
&button_save,
&button_cancel
});
button_converter_freq.set_text( to_string_short_freq( portapack::persistent_memory::config_converter_freq() ) + "MHz");
button_converter_freq.on_select = [this, &nav](Button& button) {
auto new_view = nav.push<FrequencyKeypadView>(portapack::persistent_memory::config_converter_freq() );
new_view->on_changed = [this, &button](rf::Frequency f) {
portapack::persistent_memory::set_config_converter_freq( f );
// Retune to take converter change in account
receiver_model.set_tuning_frequency( portapack::persistent_memory::tuned_frequency() );
button_converter_freq.set_text( "<" + to_string_short_freq( f ) + " MHz>" );
};
};
checkbox_bigger_qr.set_value(persistent_memory::show_bigger_qr_code());
button_save.on_select = [&nav, this](Button&) {
persistent_memory::set_show_bigger_qr_code(checkbox_bigger_qr.value());
nav.pop();
};
button_save.on_select = [&nav, this](Button&) {
nav.pop();
};
button_cancel.on_select = [&nav, this](Button&) {
nav.pop();
};
}
button_cancel.on_select = [&nav, this](Button&) {
nav.pop();
};
void SetConverterSettingsView::focus() {
button_save.focus();
}
}
// ---------------------------------------------------------
// Persistent Memory Settings
// ---------------------------------------------------------
SetPersistentMemoryView::SetPersistentMemoryView(NavigationView& nav) {
add_children({
&text_pmem_about,
&text_pmem_informations,
&text_pmem_status,
&check_load_mem_at_startup,
&button_save_mem_to_file,
&button_load_mem_from_file,
&button_return
});
void SetQRCodeView::focus() {
button_save.focus();
}
bool load_mem_at_startup = false ;
File pmem_flag_file_handle ;
std::string pmem_flag_file = "/SETTINGS/PMEM_FILEFLAG" ;
auto result = pmem_flag_file_handle.open(pmem_flag_file);
if(!result.is_valid())
{
load_mem_at_startup = true ;
}
check_load_mem_at_startup.set_value(load_mem_at_startup);
check_load_mem_at_startup.on_select = [this](Checkbox&, bool v) {
File pmem_flag_file_handle ;
std::string pmem_flag_file = "/SETTINGS/PMEM_FILEFLAG" ;
if( v )
{
auto result = pmem_flag_file_handle.open(pmem_flag_file);
if(result.is_valid())
{
auto result = pmem_flag_file_handle.create(pmem_flag_file); //third: create if it is not there
if( !result.is_valid() )
{
text_pmem_status.set("pmem flag file created");
}
else
{
text_pmem_status.set("!err. creating pmem flagfile!");
}
}
else
{
text_pmem_status.set("pmem flag already present");
}
}
else
{
auto result = delete_file( pmem_flag_file );
if( result != 0 )
{
text_pmem_status.set("!err. deleting pmem flagfile!");
}
else
{
text_pmem_status.set("pmem flag file deleted");
}
}
};
// ---------------------------------------------------------
// Settings main menu
// ---------------------------------------------------------
SettingsMenuView::SettingsMenuView(NavigationView& nav) {
if( portapack::persistent_memory::show_gui_return_icon() )
{
add_items( { { "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } } } );
}
add_items({
{ "Audio", ui::Color::dark_cyan(), &bitmap_icon_speaker, [&nav](){ nav.push<SetAudioView>(); } },
{ "Radio", ui::Color::dark_cyan(), &bitmap_icon_options_radio, [&nav](){ nav.push<SetRadioView>(); } },
{ "User Interface", ui::Color::dark_cyan(), &bitmap_icon_options_ui, [&nav](){ nav.push<SetUIView>(); } },
{ "Date/Time", ui::Color::dark_cyan(), &bitmap_icon_options_datetime, [&nav](){ nav.push<SetDateTimeView>(); } },
{ "Calibration", ui::Color::dark_cyan(), &bitmap_icon_options_touch, [&nav](){ nav.push<TouchCalibrationView>(); } },
{ "App Settings", ui::Color::dark_cyan(), &bitmap_icon_setup, [&nav](){ nav.push<SetAppSettingsView>(); } },
{ "QR Code", ui::Color::dark_cyan(), &bitmap_icon_qr_code, [&nav](){ nav.push<SetQRCodeView>(); } }
});
set_max_rows(2); // allow wider buttons
}
button_save_mem_to_file.on_select = [&nav, this](Button&) {
if( !portapack::persistent_memory::save_persistent_settings_to_file("SETTINGS/pmem_settings") )
{
text_pmem_status.set("!problem saving settings!");
}
else
{
text_pmem_status.set("settings saved");
}
};
button_load_mem_from_file.on_select = [&nav, this](Button&) {
if( !portapack::persistent_memory::load_persistent_settings_from_file("SETTINGS/pmem_settings") )
{
text_pmem_status.set("!problem loading settings!");
}
else
{
text_pmem_status.set("settings loaded");
//Refresh status bar with icon up or down
StatusRefreshMessage message { };
EventDispatcher::send_message(message);
}
};
button_return.on_select = [&nav, this](Button&) {
nav.pop();
};
}
void SetPersistentMemoryView::focus() {
button_return.focus();
}
//
// Audio settings
//
SetAudioView::SetAudioView(NavigationView& nav) {
add_children({
&labels,
&field_tone_mix,
&button_save,
&button_cancel
});
field_tone_mix.set_value(persistent_memory::tone_mix());
button_save.on_select = [&nav, this](Button&) {
persistent_memory::set_tone_mix(field_tone_mix.value());
nav.pop();
};
button_cancel.on_select = [&nav, this](Button&) {
nav.pop();
};
}
void SetAudioView::focus() {
button_save.focus();
}
SetQRCodeView::SetQRCodeView(NavigationView& nav) {
add_children({
&checkbox_bigger_qr,
&button_save,
&button_cancel
});
checkbox_bigger_qr.set_value(persistent_memory::show_bigger_qr_code());
button_save.on_select = [&nav, this](Button&) {
persistent_memory::set_show_bigger_qr_code(checkbox_bigger_qr.value());
nav.pop();
};
button_cancel.on_select = [&nav, this](Button&) {
nav.pop();
};
}
void SetQRCodeView::focus() {
button_save.focus();
}
// ---------------------------------------------------------
// Settings main menu
// ---------------------------------------------------------
SettingsMenuView::SettingsMenuView(NavigationView& nav) {
if( portapack::persistent_memory::show_gui_return_icon() )
{
add_items( { { "..", ui::Color::light_grey(),&bitmap_icon_previous, [&nav](){ nav.pop(); } } } );
}
add_items({
{ "Audio", ui::Color::dark_cyan(), &bitmap_icon_speaker, [&nav](){ nav.push<SetAudioView>(); } },
{ "Radio", ui::Color::dark_cyan(), &bitmap_icon_options_radio, [&nav](){ nav.push<SetRadioView>(); } },
{ "User Interface", ui::Color::dark_cyan(), &bitmap_icon_options_ui, [&nav](){ nav.push<SetUIView>(); } },
{ "Date/Time", ui::Color::dark_cyan(), &bitmap_icon_options_datetime, [&nav](){ nav.push<SetDateTimeView>(); } },
{ "Calibration", ui::Color::dark_cyan(), &bitmap_icon_options_touch, [&nav](){ nav.push<TouchCalibrationView>(); } },
{ "App Settings", ui::Color::dark_cyan(), &bitmap_icon_setup, [&nav](){ nav.push<SetAppSettingsView>(); } },
{ "Converter", ui::Color::dark_cyan(), &bitmap_icon_options_radio, [&nav](){ nav.push<SetConverterSettingsView>(); } },
{ "QR Code", ui::Color::dark_cyan(), &bitmap_icon_qr_code, [&nav](){ nav.push<SetQRCodeView>(); } },
{ "P.Memory Mgmt", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav](){ nav.push<SetPersistentMemoryView>(); } },
});
set_max_rows(2); // allow wider buttons
}
} /* namespace ui */
+95 -10
View File
@@ -198,16 +198,6 @@ private:
"Turn on bias voltage"
};
Checkbox check_hamitup {
{ 18, 14 * 16},
7,
"HamItUp"
};
Button button_hamitup_freq {
{ 240 - 15 * 8 , 14 * 16 , 15 * 8 , 24 },
"",
};
Button button_save {
{ 2 * 8, 16 * 16, 12 * 8, 32 },
"Save"
@@ -336,6 +326,53 @@ private:
};
};
class SetConverterSettingsView : public View {
public:
SetConverterSettingsView(NavigationView& nav);
void focus() override;
std::string title() const override { return "Converter"; };
private:
Checkbox check_show_converter {
{ 18, 4 * 16},
19,
"show/hide converter"
};
Checkbox check_converter {
{ 18, 6 * 16},
7,
"enable/disable converter"
};
OptionsField converter_mode {
{ 18 , 8 * 16 + 4 },
0,
{
{" + ",0}, // up converter
{" - ",1} // down converter
}
};
Button button_converter_freq {
{ 18 + 4 * 8 , 8 * 16 , 16 * 8 , 24 },
"",
};
Button button_save {
{ 2 * 8, 16 * 16, 12 * 8, 32 },
"Save"
};
Button button_cancel {
{ 16 * 8, 16 * 16, 12 * 8, 32 },
"Cancel",
};
};
class SetAudioView : public View {
public:
SetAudioView(NavigationView& nav);
@@ -395,6 +432,54 @@ private:
};
};
class SetPersistentMemoryView : public View {
public:
SetPersistentMemoryView(NavigationView& nav);
void focus() override;
std::string title() const override { return "P.Mem Mgmt"; };
private:
Text text_pmem_about {
{ 0, 1 * 16, 240 , 16 },
"PersistentMemory from/to SD"
};
Text text_pmem_informations {
{ 0, 2 * 16, 240 , 16 },
"use: when no/dead coin bat."
};
Text text_pmem_status {
{ 0, 3 * 16, 240 , 16 },
""
};
Checkbox check_load_mem_at_startup {
{ 18, 6 * 16},
19,
"load from sd at startup"
};
Button button_save_mem_to_file {
{ 0, 9 * 16, 240, 32 },
"save p.mem to sdcard"
};
Button button_load_mem_from_file {
{ 0, 12 * 16, 240, 32 },
"load p.mem from sdcard"
};
Button button_return {
{ 16 * 8, 16 * 16, 12 * 8, 32 },
"Return",
};
};
class SettingsMenuView : public BtnGridView {
public:
SettingsMenuView(NavigationView& nav);
+44 -22
View File
@@ -197,6 +197,28 @@ static constexpr Bitmap bitmap_icon_debug {
{ 16, 16 }, bitmap_icon_debug_data
};
static constexpr uint8_t bitmap_icon_downconvert_data[] = {
0x00, 0x00,
0x77, 0x77,
0x51, 0x51,
0x33, 0x53,
0x51, 0x51,
0x51, 0x77,
0x00, 0x80,
0x80, 0x01,
0x80, 0x01,
0x80, 0x01,
0x80, 0x01,
0xF8, 0x1F,
0xF0, 0x0F,
0xE0, 0x07,
0xC0, 0x03,
0x80, 0x01,
};
static constexpr Bitmap bitmap_icon_downconvert {
{ 16, 16 }, bitmap_icon_downconvert_data
};
static constexpr uint8_t bitmap_more_data[] = {
0x10,
0x10,
@@ -825,28 +847,6 @@ static constexpr Bitmap bitmap_icon_rename {
{ 16, 16 }, bitmap_icon_rename_data
};
static constexpr uint8_t bitmap_icon_hamitup_data[] = {
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x22, 0x47,
0x22, 0x49,
0x22, 0x49,
0x22, 0x47,
0x22, 0x01,
0x22, 0x01,
0x1C, 0x41,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
};
static constexpr Bitmap bitmap_icon_hamitup {
{ 16, 16 }, bitmap_icon_hamitup_data
};
static constexpr uint8_t bitmap_icon_lora_data[] = {
0xC0, 0x03,
0x30, 0x0C,
@@ -1023,6 +1023,28 @@ static constexpr Bitmap bitmap_icon_dmr {
{ 16, 16 }, bitmap_icon_dmr_data
};
static constexpr uint8_t bitmap_icon_upconvert_data[] = {
0x80, 0x01,
0xC0, 0x03,
0xE0, 0x07,
0xF0, 0x0F,
0xF8, 0x1F,
0x80, 0x01,
0x80, 0x01,
0x80, 0x01,
0x80, 0x01,
0x00, 0x00,
0x77, 0x77,
0x51, 0x51,
0x33, 0x53,
0x51, 0x51,
0x51, 0x77,
0x00, 0x80,
};
static constexpr Bitmap bitmap_icon_upconvert {
{ 16, 16 }, bitmap_icon_upconvert_data
};
static constexpr uint8_t bitmap_icon_clk_int_data[] = {
0x00,
0x00,
+9 -10
View File
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2023 Bernd Herzog
*
* This file is part of PortaPack.
*
@@ -28,22 +29,20 @@ using namespace lpc43xx;
#include "message.hpp"
#include "baseband_api.hpp"
#include "lz4.h"
#include <cstring>
/* TODO: OK, this is cool, but how do I put the M4 to sleep so I can switch to
* a different image? Other than asking the old image to sleep while the M0
* makes changes?
*
* I suppose I could force M4MEMMAP to an invalid memory reason which would
* cause an exception and effectively halt the M4. But that feels gross.
*/
void m4_init(const portapack::spi_flash::image_tag_t image_tag, const portapack::memory::region_t to, const bool full_reset) {
const portapack::spi_flash::chunk_t* chunk = reinterpret_cast<const portapack::spi_flash::chunk_t*>(portapack::spi_flash::images.base());
while(chunk->tag) {
if( chunk->tag == image_tag ) {
/* Initialize M4 code RAM */
std::memcpy(reinterpret_cast<void*>(to.base()), &chunk->data[0], chunk->length);
if(chunk->tag == image_tag) {
const void *src = &chunk->data[0];
void *dst = reinterpret_cast<void*>(to.base());
/* extract and initialize M4 code RAM */
unlz4_len(src, dst, chunk->compressed_data_size);
/* M4 core is assumed to be sleeping with interrupts off, so we can mess
* with its address space and RAM without concern.
+70
View File
@@ -0,0 +1,70 @@
/* source: https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/lz4-decompression-routine-for-cortex-m0-and-later */
.syntax unified
.cpu cortex-m0
.thumb
/* License: Public Domain - I cannot be held responsible for what it does or does not do if you use it, whether it's modified or not. */
/* Entry point = unlz4. On entry: r0 = source, r1 = destination. The first two bytes of the source must contain the length of the compressed data. */
.func unlz4
.global unlz4,unlz4_len
.type unlz4,%function
.type unlz4_len,%function
.thumb_func
unlz4: ldrh r2,[r0] /* get length of compressed data */
adds r0,r0,#2 /* advance source pointer */
.thumb_func
unlz4_len: push {r4-r6,lr} /* save r4, r5, r6 and return-address */
adds r5,r2,r0 /* point r5 to end of compressed data */
getToken: ldrb r6,[r0] /* get token */
adds r0,r0,#1 /* advance source pointer */
lsrs r4,r6,#4 /* get literal length, keep token in r6 */
beq getOffset /* jump forward if there are no literals */
bl getLength /* get length of literals */
movs r2,r0 /* point r2 to literals */
bl copyData /* copy literals (r2=src, r1=dst, r4=len) */
movs r0,r2 /* update source pointer */
getOffset: ldrb r3,[r0,#0] /* get match offset's low byte */
subs r2,r1,r3 /* subtract from destination; this will become the match position */
ldrb r3,[r0,#1] /* get match offset's high byte */
lsls r3,r3,#8 /* shift to high byte */
subs r2,r2,r3 /* subtract from match position */
adds r0,r0,#2 /* advance source pointer */
lsls r4,r6,#28 /* get rid of token's high 28 bits */
lsrs r4,r4,#28 /* move the 4 low bits back where they were */
bl getLength /* get length of match data */
adds r4,r4,#4 /* minimum match length is 4 bytes */
bl copyData /* copy match data (r2=src, r1=dst, r4=len) */
cmp r0,r5 /* check if we've reached the end of the compressed data */
blt getToken /* if not, go get the next token */
pop {r4-r6,pc} /* restore r4, r5 and r6, then return */
.thumb_func
getLength: cmp r4,#0x0f /* if length is 15, then more length info follows */
bne gotLength /* jump forward if we have the complete length */
getLengthLoop: ldrb r3,[r0] /* read another byte */
adds r0,r0,#1 /* advance source pointer */
adds r4,r4,r3 /* add byte to length */
cmp r3,#0xff /* check if end reached */
beq getLengthLoop /* if not, go round loop */
gotLength: bx lr /* return */
.thumb_func
copyData: rsbs r4,r4,#0 /* index = -length */
subs r2,r2,r4 /* point to end of source */
subs r1,r1,r4 /* point to end of destination */
copyDataLoop: ldrb r3,[r2,r4] /* read byte from source_end[-index] */
strb r3,[r1,r4] /* store byte in destination_end[-index] */
adds r4,r4,#1 /* increment index */
bne copyDataLoop /* keep going until index wraps to 0 */
bx lr /* return */
.size unlz4,.-unlz4
.endfunc
/* 42 narrow instructions = 84 bytes */
+36
View File
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2023 Bernd Herzog
*
* 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 __LZ4_H__
#define __LZ4_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern void unlz4_len(const void *aSource, void *aDestination, uint32_t aLength);
#ifdef __cplusplus
}
#endif
#endif /*__LZ4_H__*/
+5 -3
View File
@@ -515,11 +515,13 @@ bool init() {
return true;
}
void shutdown() {
void shutdown(const bool leave_screen_on) {
gpdma::controller.disable();
backlight()->off();
display.shutdown();
if (!leave_screen_on) {
backlight()->off();
display.shutdown();
}
radio::disable();
audio::shutdown();
+1 -1
View File
@@ -63,7 +63,7 @@ void set_antenna_bias(const bool v);
bool get_antenna_bias();
bool init();
void shutdown();
void shutdown(const bool leave_screen_on = false);
Backlight* backlight();
+11 -2
View File
@@ -170,8 +170,17 @@ void set_direction(const rf::Direction new_direction) {
bool set_tuning_frequency(const rf::Frequency frequency) {
rf::Frequency final_frequency = frequency ;
if( portapack::persistent_memory::config_hamitup() ) {
final_frequency = frequency + portapack::persistent_memory::config_hamitup_freq();
// if feature is enabled
if( portapack::persistent_memory::config_converter() ) {
//downconvert
if( portapack::persistent_memory::config_updown_converter() )
{
final_frequency = frequency - portapack::persistent_memory::config_converter_freq();
}
else //upconvert
{
final_frequency = frequency + portapack::persistent_memory::config_converter_freq();
}
}
const auto tuning_config = tuning::config::create(final_frequency);
if( tuning_config.is_valid() ) {
+60 -13
View File
@@ -70,6 +70,8 @@
#include "ui_playlist.hpp"
#include "ui_view_wav.hpp"
#include "ui_whipcalc.hpp"
#include "ui_flash_utility.hpp"
#include "ui_sd_over_usb.hpp"
//#include "acars_app.hpp"
#include "ais_app.hpp"
@@ -111,7 +113,7 @@ SystemStatusView::SystemStatusView(
&button_back,
&title,
&button_title,
&button_hamitup,
&button_converter,
&button_speaker,
&button_stealth,
//&button_textentry,
@@ -127,6 +129,24 @@ SystemStatusView::SystemStatusView(
else
button_speaker.hidden(true);
if( portapack::persistent_memory::config_hide_converter() )
{
button_converter.hidden(true);
}
else
{
button_converter.hidden(false);
if( portapack::persistent_memory::config_converter() )
{
button_converter.set_foreground(Color::red());
}
else
{
button_converter.set_foreground(Color::light_grey());
}
}
button_back.id = -1; // Special ID used by FocusManager
title.set_style(&style_systemstatus);
@@ -149,8 +169,8 @@ SystemStatusView::SystemStatusView(
this->on_title();
};
button_hamitup.on_select = [this](ImageButton&) {
this->on_hamitup();
button_converter.on_select = [this](ImageButton&) {
this->on_converter();
};
button_speaker.on_select = [this](ImageButton&) {
@@ -184,16 +204,33 @@ SystemStatusView::SystemStatusView(
}
void SystemStatusView::refresh() {
if( portapack::persistent_memory::config_hamitup() )
if( portapack::persistent_memory::config_hide_converter() )
{
button_hamitup.set_foreground(Color::red());
button_converter.hidden(true);
}
else
{
button_hamitup.set_foreground(Color::light_grey());
if( portapack::persistent_memory::config_updown_converter() )
{
button_converter.set_bitmap(&bitmap_icon_downconvert);
}
else
{
button_converter.set_bitmap(&bitmap_icon_upconvert);
}
button_converter.hidden(false);
if( portapack::persistent_memory::config_converter() )
{
button_converter.set_foreground(Color::red());
}
else
{
button_converter.set_foreground(Color::light_grey());
}
}
// Retune to take hamitup change in account
// Retune to take converter change in account
receiver_model.set_tuning_frequency( portapack::persistent_memory::tuned_frequency() );
transmitter_model.set_tuning_frequency( portapack::persistent_memory::tuned_frequency() );
if (!portapack::persistent_memory::config_speaker()) {
button_speaker.set_foreground(Color::light_grey());
@@ -257,16 +294,16 @@ void SystemStatusView::set_title(const std::string new_value) {
}
}
void SystemStatusView::on_hamitup() {
if(!portapack::persistent_memory::config_hamitup())
void SystemStatusView::on_converter() {
if(!portapack::persistent_memory::config_converter())
{
portapack::persistent_memory::set_config_hamitup( true );
button_hamitup.set_foreground(Color::red());
portapack::persistent_memory::set_config_converter( true );
button_converter.set_foreground(Color::red());
}
else
{
portapack::persistent_memory::set_config_hamitup( false );
button_hamitup.set_foreground(Color::light_grey());
portapack::persistent_memory::set_config_converter( false );
button_converter.set_foreground(Color::light_grey());
}
receiver_model.set_tuning_frequency( portapack::persistent_memory::tuned_frequency() ); // Retune
}
@@ -578,6 +615,8 @@ UtilitiesMenuView::UtilitiesMenuView(NavigationView& nav) {
{ "Antenna length", ui::Color::green(), &bitmap_icon_tools_antenna, [&nav](){ nav.push<WhipCalcView>(); } },
{ "Wipe SD card", ui::Color::red(), &bitmap_icon_tools_wipesd, [&nav](){ nav.push<WipeSDView>(); } },
{ "Flash Utility", ui::Color::red(), &bitmap_icon_temperature, [&nav](){ nav.push<FlashUtilityView>(); } },
{ "SD over USB", ui::Color::yellow(), &bitmap_icon_hackrf, [&nav](){ nav.push<SdOverUsbView>(); } },
});
set_max_rows(2); // allow wider buttons
}
@@ -684,6 +723,14 @@ SystemView::SystemView(
navigation_view.push<SystemMenuView>();
File pmem_flag_file_handle ;
std::string pmem_flag_file = "/SETTINGS/PMEM_FILEFLAG" ;
auto result = pmem_flag_file_handle.open(pmem_flag_file);
if(!result.is_valid())
{
portapack::persistent_memory::load_persistent_settings_from_file("SETTINGS/pmem_settings");
}
if (portapack::persistent_memory::config_splash())
{
navigation_view.push<BMPView>();
+3 -3
View File
@@ -147,9 +147,9 @@ namespace ui
Color::light_grey(),
Color::dark_grey()};
ImageButton button_hamitup{
ImageButton button_converter{
{17 * 8, 0, 2 * 8, 1 * 16},
&bitmap_icon_hamitup,
&bitmap_icon_upconvert,
Color::light_grey(),
Color::dark_grey()
};
@@ -194,7 +194,7 @@ namespace ui
SDCardStatusView sd_card_status_view{
{28 * 8, 0 * 16, 2 * 8, 1 * 16}};
void on_hamitup();
void on_converter();
void on_speaker();
void on_stealth();
void on_bias_tee();
+66 -7
View File
@@ -90,8 +90,6 @@ set(CSRC
${PORTSRC}
${KERNSRC}
${TESTSRC}
${HALSRC}
${PLATFORMSRC}
${BOARDSRC}
)
@@ -189,7 +187,7 @@ set(AOPT)
set(TOPT "-mthumb -DTHUMB")
# Define C warning options here
set(CWARN "-Wall -Wextra -Wstrict-prototypes")
set(CWARN "-Wall -Wextra")
# Define C++ warning options here
set(CPPWARN "-Wall -Wextra")
@@ -262,10 +260,11 @@ macro(DeclareTargets chunk_tag name)
project("baseband_${name}")
include(${RULESPATH}/rules.cmake)
add_executable(${PROJECT_NAME}.elf $<TARGET_OBJECTS:baseband_shared> ${MODE_CPPSRC})
add_executable(${PROJECT_NAME}.elf $<TARGET_OBJECTS:baseband_shared> ${MODE_CPPSRC} ${HALSRC} ${PLATFORMSRC})
set_target_properties(${PROJECT_NAME}.elf PROPERTIES LINK_DEPENDS ${LDSCRIPT})
add_definitions(${DEFS})
include_directories(. ${INCDIR})
target_compile_definitions(${PROJECT_NAME}.elf PUBLIC "-DBASEBAND_${name}")
include_directories(. ${INCDIR} ${MODE_INCDIR})
link_directories(${LLIBDIR})
target_link_libraries(${PROJECT_NAME}.elf ${LIBS})
target_link_libraries(${PROJECT_NAME}.elf -Wl,-Map=${PROJECT_NAME}.map)
@@ -273,7 +272,8 @@ macro(DeclareTargets chunk_tag name)
add_custom_command(
OUTPUT ${PROJECT_NAME}.bin ${PROJECT_NAME}.img
COMMAND ${CMAKE_OBJCOPY} -O binary ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin
COMMAND ${MAKE_IMAGE_CHUNK} ${PROJECT_NAME}.bin ${chunk_tag} ${PROJECT_NAME}.img
COMMAND ${LZ4} -f -9 ${PROJECT_NAME}.bin ${PROJECT_NAME}.lz4
COMMAND ${MAKE_IMAGE_CHUNK} ${PROJECT_NAME}.lz4 ${chunk_tag} ${PROJECT_NAME}.img
DEPENDS ${PROJECT_NAME}.elf ${MAKE_IMAGE_CHUNK}
VERBATIM
)
@@ -504,11 +504,70 @@ set(MODE_CPPSRC
)
DeclareTargets(PWFM wfm_audio)
### Flash Utility
include(${CHIBIOS_PORTAPACK}/os/various/fatfs_bindings/fatfs.cmake)
set(MODE_INCDIR ${FATFSINC})
set(MODE_CPPSRC
proc_flash_utility.cpp
w25q80bv.cpp
${FATFSSRC}
)
DeclareTargets(PFUT flash_utility)
### SD over USB
set(MODE_INCDIR
${HACKRF_PATH}/firmware
${HACKRF_PATH}/firmware/common
${HACKRF_PATH}/firmware/libopencm3/include
)
set(MODE_CPPSRC
sd_over_usb/proc_sd_over_usb.cpp
sd_over_usb/scsi.c
sd_over_usb/diskio.c
sd_over_usb/sd_over_usb.c
sd_over_usb/usb_descriptor.c
sd_over_usb/hackrf_core.c
${HACKRF_PATH}/firmware/common/usb.c
${HACKRF_PATH}/firmware/common/usb_queue.c
${HACKRF_PATH}/firmware/hackrf_usb/usb_device.c
${HACKRF_PATH}/firmware/hackrf_usb/usb_endpoint.c
${HACKRF_PATH}/firmware/common/usb_request.c
${HACKRF_PATH}/firmware/common/usb_standard_request.c
${HACKRF_PATH}/firmware/common/platform_detect.c
${HACKRF_PATH}/firmware/common/gpio_lpc.c
${HACKRF_PATH}/firmware/common/firmware_info.c
${HACKRF_PATH}/firmware/common/si5351c.c
${HACKRF_PATH}/firmware/common/i2c_bus.c
${HACKRF_PATH}/firmware/common/mixer.c
${HACKRF_PATH}/firmware/common/clkin.c
${HACKRF_PATH}/firmware/common/spi_bus.c
${HACKRF_PATH}/firmware/common/sgpio.c
${HACKRF_PATH}/firmware/common/rf_path.c
${HACKRF_PATH}/firmware/common/i2c_lpc.c
${HACKRF_PATH}/firmware/common/spi_ssp.c
${HACKRF_PATH}/firmware/common/rffc5071_spi.c
${HACKRF_PATH}/firmware/common/rffc5071.c
${HACKRF_PATH}/firmware/common/clkin.c
${HACKRF_PATH}/firmware/common/gpdma.c
${HACKRF_PATH}/firmware/libopencm3/lib/cm3/nvic.c
${HACKRF_PATH}/firmware/libopencm3/lib/cm3/sync.c
${HACKRF_PATH}/firmware/libopencm3/lib/lpc43xx/scu.c
${HACKRF_PATH}/firmware/libopencm3/lib/lpc43xx/timer.c
${HACKRF_PATH}/firmware/libopencm3/lib/lpc43xx/i2c.c
)
DeclareTargets(PUSB sd_over_usb)
### HackRF "factory" firmware
add_custom_command(
OUTPUT hackrf.img
COMMAND ${MAKE_IMAGE_CHUNK} ${HACKRF_FIRMWARE_BIN_IMAGE} HRF1 hackrf.img 98304
COMMAND ${LZ4} -f -9 ${HACKRF_FIRMWARE_BIN_IMAGE} hackrf.lz4
COMMAND ${MAKE_IMAGE_CHUNK} hackrf.lz4 HRF1 hackrf.img
DEPENDS ${HACKRF_FIRMWARE_BIN_FILENAME} ${MAKE_IMAGE_CHUNK}
VERBATIM
)
+6
View File
@@ -36,6 +36,7 @@ inline uint32_t get_free_stack_space(){
return stack_space_left;
}
/* Executes a breakpoint only when a debugger is attached. */
#define HALT_IF_DEBUGGING() \
do { \
if ((*(volatile uint32_t *)0xE000EDF0) & (1 << 0)) { \
@@ -43,4 +44,9 @@ inline uint32_t get_free_stack_space(){
} \
} while (0)
/* Stops execution until a debugger is attached. */
#define HALT_UNTIL_DEBUGGING() \
while (!((*(volatile uint32_t *)0xE000EDF0) & (1 << 0))) {} \
__asm__ __volatile__("bkpt 1")
#endif/*__DEBUG_H__*/
+4
View File
@@ -119,7 +119,11 @@
* @brief Enables the SDC subsystem.
*/
#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
#if defined(BASEBAND_flash_utility) || defined(BASEBAND_sd_over_usb)
#define HAL_USE_SDC TRUE
#else
#define HAL_USE_SDC FALSE
#endif /* BASEBAND_flash_utility */
#endif
/**
+116
View File
@@ -0,0 +1,116 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2023 Bernd Herzog
*
* 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 "hal.h"
#include "ff.h"
#include "w25q80bv.hpp"
#include "debug.hpp"
#include "portapack_shared_memory.hpp"
#define PAGE_LEN 256U
#define NUM_PAGES 4096U
void initialize_flash();
void erase_flash();
void initialize_sdcard();
void write_firmware(FIL *);
void write_page(size_t, uint8_t *, size_t);
int main() {
const TCHAR *filename = reinterpret_cast<const TCHAR *>(&shared_memory.bb_data.data[0]);
initialize_flash();
palSetPad(LED_PORT, LEDRX_PAD);
erase_flash();
initialize_sdcard();
FIL firmware_file;
if (f_open(&firmware_file, filename, FA_READ) != FR_OK) chDbgPanic("no file");
palSetPad(LED_PORT, LEDTX_PAD);
write_firmware(&firmware_file);
palClearPad(LED_PORT, LEDTX_PAD);
palClearPad(LED_PORT, LEDRX_PAD);
f_close(&firmware_file);
while(1)
__WFE();
return 0;
}
void initialize_flash() {
w25q80bv::disable_spifi();
w25q80bv::initialite_spi();
w25q80bv::setup();
w25q80bv::wait_for_device();
w25q80bv::wait_not_busy();
}
void erase_flash() {
w25q80bv::remove_write_protection();
w25q80bv::wait_not_busy();
w25q80bv::erase_chip();
w25q80bv::wait_not_busy();
}
void initialize_sdcard() {
static FATFS fs;
sdcStart(&SDCD1, nullptr);
if (sdcConnect(&SDCD1) == CH_FAILED) chDbgPanic("no sd card #1");
if (f_mount(&fs, reinterpret_cast<const TCHAR*>(_T("")), 1) != FR_OK) chDbgPanic("no sd card #2");
}
void write_firmware(FIL *firmware_file) {
uint8_t *data_buffer = &shared_memory.bb_data.data[0];
for (size_t page_index = 0; page_index < NUM_PAGES; page_index++) {
if (page_index % 32 == 0)
palTogglePad(LED_PORT, LEDTX_PAD);
size_t bytes_read;
if (f_read(firmware_file, data_buffer, PAGE_LEN, &bytes_read) != FR_OK) chDbgPanic("no data");
if (bytes_read > 0)
write_page(page_index, data_buffer, bytes_read);
if (bytes_read < PAGE_LEN)
return;
}
}
void write_page(size_t page_index, uint8_t *data_buffer, size_t data_length) {
w25q80bv::wait_not_busy();
w25q80bv::remove_write_protection();
w25q80bv::wait_not_busy();
w25q80bv::write(page_index, data_buffer, data_length);
w25q80bv::wait_not_busy();
}
+38
View File
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2023 Bernd Herzog
*
* 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 "diskio.h"
#include "ch.h"
#include "hal.h"
uint32_t get_capacity(void) {
return mmcsdGetCardCapacity(&SDCD1);
}
bool_t read_block(uint32_t startblk, uint8_t *buf, uint32_t n) {
return sdcRead(&SDCD1, startblk, buf, n);
}
bool_t write_block(uint32_t startblk, uint8_t *buf, uint32_t n) {
return sdcWrite(&SDCD1, startblk, buf, n);
}
+33
View File
@@ -0,0 +1,33 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2023 Bernd Herzog
*
* 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 __DISKIO_H__
#define __DISKIO_H__
#include <stdint.h>
#include <chtypes.h>
uint32_t get_capacity(void);
bool_t read_block(uint32_t startblk, uint8_t *buf, uint32_t n);
bool_t write_block(uint32_t startblk, uint8_t *buf, uint32_t n);
#endif /* __DISKIO_H__ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2023 Bernd Herzog
*
* 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 "hal.h"
extern "C" {
void start_usb(void);
void irq_usb(void);
void usb_transfer(void);
CH_IRQ_HANDLER(Vector60) {
irq_usb();
}
}
int main() {
sdcStart(&SDCD1, nullptr);
if (sdcConnect(&SDCD1) == CH_FAILED) chDbgPanic("no sd card #1");
start_usb();
while (true) {
usb_transfer();
}
return 0;
}
+274
View File
@@ -0,0 +1,274 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2023 Bernd Herzog
*
* 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 "scsi.h"
#include "diskio.h"
volatile bool usb_bulk_block_done = false;
void usb_bulk_block_cb(void* user_data, unsigned int bytes_transferred) {
usb_bulk_block_done = true;
(void)user_data;
(void)bytes_transferred;
}
void usb_send_bulk(void* const data, const uint32_t maximum_length) {
usb_bulk_block_done = false;
usb_transfer_schedule_block(
&usb_endpoint_bulk_in,
data,
maximum_length,
usb_bulk_block_cb,
NULL);
while (!usb_bulk_block_done);
}
void usb_receive_bulk(void* const data, const uint32_t maximum_length) {
usb_bulk_block_done = false;
usb_transfer_schedule_block(
&usb_endpoint_bulk_out,
data,
maximum_length,
usb_bulk_block_cb,
NULL);
while (!usb_bulk_block_done);
}
void usb_send_csw(msd_cbw_t *msd_cbw_data, uint8_t status) {
msd_csw_t csw = {
.signature = MSD_CSW_SIGNATURE,
.tag = msd_cbw_data->tag,
.data_residue = 0,
.status = status
};
memcpy(&usb_bulk_buffer[0], &csw, sizeof(msd_csw_t));
usb_send_bulk(&usb_bulk_buffer[0], sizeof(msd_csw_t));
}
uint8_t handle_inquiry(msd_cbw_t *msd_cbw_data) {
(void)msd_cbw_data;
scsi_inquiry_response_t ret = {
0x00, /* direct access block device */
0x80, /* removable */
0x00, //0x04, /* SPC-2 */
0x00, //0x02, /* response data format */
0x20, /* response has 0x20 + 4 bytes */
0x00,
0x00,
0x00,
"Mayhem",
"Portapack MSD",
{'v','1','.','6'}
};
memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_inquiry_response_t));
usb_send_bulk(&usb_bulk_buffer[0], sizeof(scsi_inquiry_response_t));
return 0;
}
uint8_t handle_inquiry_serial_number(msd_cbw_t *msd_cbw_data) {
(void)msd_cbw_data;
scsi_unit_serial_number_inquiry_response_t ret = {
.peripheral = 0x00,
.page_code = 0x80,
.reserved = 0,
.page_length = 0x08,
.serialNumber = "Mayhem"
};
memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_unit_serial_number_inquiry_response_t));
usb_send_bulk(&usb_bulk_buffer[0], sizeof(scsi_unit_serial_number_inquiry_response_t));
return 0;
}
uint8_t read_format_capacities(msd_cbw_t *msd_cbw_data) {
uint16_t len = msd_cbw_data->cmd_data[7] << 8 | msd_cbw_data->cmd_data[8];
if (len != 0) {
size_t num_blocks = get_capacity();
scsi_read_format_capacities_response_t ret = {
.header = {0, 0, 0, 1 * 8 /* num_entries * 8 */},
.blocknum = {((num_blocks) >> 24)& 0xff, ((num_blocks) >> 16)& 0xff, ((num_blocks) >> 8)& 0xff, num_blocks & 0xff},
.blocklen = {0b10 /* formated */, 0, (512) >> 8, 0},
};
memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_read_format_capacities_response_t));
usb_send_bulk(&usb_bulk_buffer[0], sizeof(scsi_read_format_capacities_response_t));
}
return 0;
}
uint8_t read_capacity10(msd_cbw_t *msd_cbw_data) {
(void)msd_cbw_data;
size_t num_blocks = get_capacity();
scsi_read_capacity10_response_t ret = {
.last_block_addr = cpu_to_be32(num_blocks - 1),
.block_size = cpu_to_be32(512)
};
memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_read_capacity10_response_t));
usb_send_bulk(&usb_bulk_buffer[0], sizeof(scsi_read_capacity10_response_t));
return 0;
}
uint8_t request_sense(msd_cbw_t *msd_cbw_data) {
(void)msd_cbw_data;
scsi_sense_response_t ret = {
.byte = { 0x70, 0, SCSI_SENSE_KEY_GOOD, 0,
0, 0, 0, 8,
0, 0 ,0 ,0,
SCSI_ASENSE_NO_ADDITIONAL_INFORMATION, SCSI_ASENSEQ_NO_QUALIFIER, 0, 0,
0, 0 }
};
memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_sense_response_t));
usb_send_bulk(&usb_bulk_buffer[0], sizeof(scsi_sense_response_t));
return 0;
}
uint8_t mode_sense6(msd_cbw_t *msd_cbw_data) {
(void)msd_cbw_data;
scsi_mode_sense6_response_t ret = {
.byte = {
sizeof(scsi_mode_sense6_response_t) - 1,
0,
0,
0 }
};
memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_mode_sense6_response_t));
usb_send_bulk(&usb_bulk_buffer[0], sizeof(scsi_mode_sense6_response_t));
return 0;
}
static data_request_t decode_data_request(const uint8_t *cmd) {
data_request_t req;
uint32_t lba;
uint16_t blk;
memcpy(&lba, &cmd[2], sizeof(lba));
memcpy(&blk, &cmd[7], sizeof(blk));
req.first_lba = be32_to_cpu(lba);
req.blk_cnt = be16_to_cpu(blk);
return req;
}
uint8_t data_read10(msd_cbw_t *msd_cbw_data) {
data_request_t req = decode_data_request(msd_cbw_data->cmd_data);
for (size_t block_index = 0; block_index < req.blk_cnt; block_index++) {
read_block(req.first_lba + block_index, &usb_bulk_buffer[0], 1 /* n blocks */);
usb_send_bulk(&usb_bulk_buffer[0], 512);
}
return 0;
}
uint8_t data_write10(msd_cbw_t *msd_cbw_data) {
data_request_t req = decode_data_request(msd_cbw_data->cmd_data);
for (size_t block_index = 0; block_index < req.blk_cnt; block_index++) {
usb_receive_bulk(&usb_bulk_buffer[0], 512);
write_block(req.first_lba + block_index, &usb_bulk_buffer[0], 1 /* n blocks */);
}
return 0;
}
void scsi_command(msd_cbw_t *msd_cbw_data) {
uint8_t status = 1;
switch (msd_cbw_data->cmd_data[0]) {
case SCSI_CMD_INQUIRY:
if ((msd_cbw_data->cmd_data[1] & 0b1) && msd_cbw_data->cmd_data[2] == 0x80) {
status = handle_inquiry_serial_number(msd_cbw_data);
}
else if ((msd_cbw_data->cmd_data[1] & 0b11) || msd_cbw_data->cmd_data[2] != 0) {
status = 1;
}
else {
status = handle_inquiry(msd_cbw_data);
}
break;
case SCSI_CMD_REQUEST_SENSE:
status = request_sense(msd_cbw_data);
break;
case SCSI_CMD_READ_CAPACITY_10:
status = read_capacity10(msd_cbw_data);
break;
case SCSI_CMD_READ_10:
status = data_read10(msd_cbw_data);
break;
case SCSI_CMD_WRITE_10:
status = data_write10(msd_cbw_data);
break;
case SCSI_CMD_TEST_UNIT_READY:
status = 0;
break;
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
status = 0;
break;
case SCSI_CMD_MODE_SENSE_6:
status = mode_sense6(msd_cbw_data);
break;
case SCSI_CMD_READ_FORMAT_CAPACITIES:
status = read_format_capacities(msd_cbw_data);
break;
case SCSI_CMD_VERIFY_10:
status = 0;
break;
}
usb_send_csw(msd_cbw_data, status);
}
+197
View File
@@ -0,0 +1,197 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2023 Bernd Herzog
*
* 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 __SCSI_H__
#define __SCSI_H__
#include <stddef.h>
#include <common/usb.h>
#include <common/usb_request.h>
#include <common/usb_standard_request.h>
#include <hackrf_usb/usb_device.h>
#include <hackrf_usb/usb_endpoint.h>
#include <libopencm3/lpc43xx/m4/nvic.h>
#include <libopencm3/lpc43xx/cgu.h>
#include "platform_detect.h"
#include "hackrf_core.h"
#include "usb_bulk_buffer.h"
#define MSD_CBW_SIGNATURE 0x43425355
#define MSD_CSW_SIGNATURE 0x53425355
#define SCSI_CMD_TEST_UNIT_READY 0x00
#define SCSI_CMD_REQUEST_SENSE 0x03
#define SCSI_CMD_INQUIRY 0x12
#define SCSI_CMD_MODE_SENSE_6 0x1A
#define SCSI_CMD_START_STOP_UNIT 0x1B
#define SCSI_CMD_SEND_DIAGNOSTIC 0x1D
#define SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E
#define SCSI_CMD_READ_CAPACITY_10 0x25
#define SCSI_CMD_READ_FORMAT_CAPACITIES 0x23
#define SCSI_CMD_READ_10 0x28
#define SCSI_CMD_WRITE_10 0x2A
#define SCSI_CMD_VERIFY_10 0x2F
#define SCSI_SENSE_KEY_GOOD 0x00
#define SCSI_SENSE_KEY_RECOVERED_ERROR 0x01
#define SCSI_SENSE_KEY_NOT_READY 0x02
#define SCSI_SENSE_KEY_MEDIUM_ERROR 0x03
#define SCSI_SENSE_KEY_HARDWARE_ERROR 0x04
#define SCSI_SENSE_KEY_ILLEGAL_REQUEST 0x05
#define SCSI_SENSE_KEY_UNIT_ATTENTION 0x06
#define SCSI_SENSE_KEY_DATA_PROTECT 0x07
#define SCSI_SENSE_KEY_BLANK_CHECK 0x08
#define SCSI_SENSE_KEY_VENDOR_SPECIFIC 0x09
#define SCSI_SENSE_KEY_COPY_ABORTED 0x0A
#define SCSI_SENSE_KEY_ABORTED_COMMAND 0x0B
#define SCSI_SENSE_KEY_VOLUME_OVERFLOW 0x0D
#define SCSI_SENSE_KEY_MISCOMPARE 0x0E
#define SCSI_ASENSE_NO_ADDITIONAL_INFORMATION 0x00
#define SCSI_ASENSE_LOGICAL_UNIT_NOT_READY 0x04
#define SCSI_ASENSE_INVALID_FIELD_IN_CDB 0x24
#define SCSI_ASENSE_NOT_READY_TO_READY_CHANGE 0x28
#define SCSI_ASENSE_WRITE_PROTECTED 0x27
#define SCSI_ASENSE_FORMAT_ERROR 0x31
#define SCSI_ASENSE_INVALID_COMMAND 0x20
#define SCSI_ASENSE_LBA_OUT_OF_RANGE 0x21
#define SCSI_ASENSE_MEDIUM_NOT_PRESENT 0x3A
#define SCSI_ASENSEQ_NO_QUALIFIER 0x00
#define SCSI_ASENSEQ_FORMAT_COMMAND_FAILED 0x01
#define SCSI_ASENSEQ_INIT_COMMAND_REQUIRED 0x02
#define SCSI_ASENSEQ_OPERATION_IN_PROGRESS 0x07
#define MSD_CBW_SIGNATURE 0x43425355
#define MSD_CSW_SIGNATURE 0x53425355
#define USB_TRANSFER_SIZE 0x2000
typedef struct {
uint32_t signature;
uint32_t tag;
uint32_t data_len;
uint8_t flags;
uint8_t lun;
uint8_t cmd_len;
uint8_t cmd_data[16];
} __attribute__((packed)) msd_cbw_t;
typedef struct {
uint8_t peripheral;
uint8_t removable;
uint8_t version;
uint8_t response_data_format;
uint8_t additional_length;
uint8_t sccstp;
uint8_t bqueetc;
uint8_t cmdque;
uint8_t vendorID[8];
uint8_t productID[16];
uint8_t productRev[4];
} scsi_inquiry_response_t;
typedef struct {
uint32_t signature;
uint32_t tag;
uint32_t data_residue;
uint8_t status;
} __attribute__((packed)) msd_csw_t;
typedef struct {
uint8_t header[4];
uint8_t blocknum[4];
uint8_t blocklen[4];
} scsi_read_format_capacities_response_t;
typedef struct {
uint32_t last_block_addr;
uint32_t block_size;
} scsi_read_capacity10_response_t;
typedef struct {
uint8_t byte[18];
} scsi_sense_response_t;
typedef struct {
uint8_t byte[4];
} scsi_mode_sense6_response_t;
typedef struct {
uint32_t first_lba;
uint16_t blk_cnt;
} data_request_t;
typedef struct {
uint8_t peripheral;
uint8_t page_code;
uint8_t reserved;
uint8_t page_length;
uint8_t serialNumber[8];
} scsi_unit_serial_number_inquiry_response_t;
static inline uint16_t bswap_16(const uint16_t x)
__attribute__ ((warn_unused_result))
__attribute__ ((const))
__attribute__ ((always_inline));
static inline uint16_t bswap_16(const uint16_t x) {
uint8_t tmp;
union { uint16_t x; uint8_t b[2]; } data;
data.x = x;
tmp = data.b[0];
data.b[0] = data.b[1];
data.b[1] = tmp;
return data.x;
}
static inline uint32_t bswap_32(const uint32_t x)
__attribute__ ((warn_unused_result))
__attribute__ ((const))
__attribute__ ((always_inline));
static inline uint32_t bswap_32(const uint32_t x) {
uint8_t tmp;
union { uint32_t x; uint8_t b[4]; } data;
data.x = x;
tmp = data.b[0];
data.b[0] = data.b[3];
data.b[3] = tmp;
tmp = data.b[1];
data.b[1] = data.b[2];
data.b[2] = tmp;
return data.x;
}
#define be16_to_cpu(x) bswap_16(x)
#define be32_to_cpu(x) bswap_32(x)
#define cpu_to_be16(x) bswap_16(x)
#define cpu_to_be32(x) bswap_32(x)
void scsi_command(msd_cbw_t *msd_cbw_data);
#endif /* __SCSI_H__ */
+132
View File
@@ -0,0 +1,132 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2023 Bernd Herzog
*
* 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 "sd_over_usb.h"
#include "scsi.h"
bool scsi_running = false;
usb_request_status_t report_max_lun(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{
if (stage == USB_TRANSFER_STAGE_SETUP) {
endpoint->buffer[0] = 0;
usb_transfer_schedule_block(
endpoint->in,
&endpoint->buffer,
1,
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out);
scsi_running = true;
}
return USB_REQUEST_STATUS_OK;
}
usb_request_status_t usb_class_request(usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) {
usb_request_status_t status = USB_REQUEST_STATUS_STALL;
volatile uint8_t request = endpoint->setup.request;
if (request == 0xFE)
return report_max_lun(endpoint, stage);
return status;
}
const usb_request_handlers_t usb_request_handlers = {
.standard = usb_standard_request,
.class = usb_class_request,
.vendor = 0,
.reserved = 0
};
void usb_configuration_changed(usb_device_t* const device) {
(void)device;
usb_endpoint_init(&usb_endpoint_bulk_in);
usb_endpoint_init(&usb_endpoint_bulk_out);
}
void start_usb(void) {
detect_hardware_platform();
pin_setup();
cpu_clock_init();
usb_set_configuration_changed_cb(usb_configuration_changed);
usb_peripheral_reset();
usb_device_init(0, &usb_device);
usb_queue_init(&usb_endpoint_control_out_queue);
usb_queue_init(&usb_endpoint_control_in_queue);
usb_queue_init(&usb_endpoint_bulk_out_queue);
usb_queue_init(&usb_endpoint_bulk_in_queue);
usb_endpoint_init(&usb_endpoint_control_out);
usb_endpoint_init(&usb_endpoint_control_in);
nvic_set_priority(NVIC_USB0_IRQ, 255);
usb_run(&usb_device);
}
void stop_usb(void) {
usb_peripheral_reset();
}
void irq_usb(void) {
usb0_isr();
}
volatile bool transfer_complete = false;
void scsi_bulk_transfer_complete(void* user_data, unsigned int bytes_transferred)
{
(void)user_data;
(void)bytes_transferred;
transfer_complete = true;
}
void usb_transfer(void) {
if (scsi_running) {
transfer_complete = false;
usb_transfer_schedule_block(
&usb_endpoint_bulk_out,
&usb_bulk_buffer[0x4000],
USB_TRANSFER_SIZE,
scsi_bulk_transfer_complete,
NULL);
while (!transfer_complete);
msd_cbw_t *msd_cbw_data = (msd_cbw_t *) &usb_bulk_buffer[0x4000];
if (msd_cbw_data->signature == MSD_CBW_SIGNATURE){
scsi_command(msd_cbw_data);
}
}
}
@@ -0,0 +1,43 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2023 Bernd Herzog
*
* 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 __USB_SD_OVER_USB_H__
#define __USB_SD_OVER_USB_H__
#include <stddef.h>
#include <common/usb.h>
#include <common/usb_request.h>
#include <common/usb_standard_request.h>
#include <hackrf_usb/usb_device.h>
#include <hackrf_usb/usb_endpoint.h>
#include <libopencm3/lpc43xx/m4/nvic.h>
#include <libopencm3/lpc43xx/cgu.h>
#include "platform_detect.h"
#include "hackrf_core.h"
#include "usb_bulk_buffer.h"
void start_usb(void);
void stop_usb(void);
void irq_usb(void);
void usb_transfer(void);
#endif /* __USB_SD_OVER_USB_H__ */
@@ -0,0 +1,39 @@
/*
* Copyright 2012-2022 Great Scott Gadgets <info@greatscottgadgets.com>
* Copyright 2012 Jared Boone
* Copyright 2013 Benjamin Vernoux
*
* This file is part of HackRF.
*
* 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 __USB_BULK_BUFFER_H__
#define __USB_BULK_BUFFER_H__
#include <stdbool.h>
#include <stdint.h>
#define USB_BULK_BUFFER_SIZE 0x8000
#define USB_BULK_BUFFER_MASK 0x7FFF
/* Address of usb_bulk_buffer is set in ldscripts. If you change the name of this
* variable, it won't be where it needs to be in the processor's address space,
* unless you also adjust the ldscripts.
*/
extern uint8_t usb_bulk_buffer[USB_BULK_BUFFER_SIZE];
#endif /*__USB_BULK_BUFFER_H__*/
@@ -0,0 +1,322 @@
/*
* Copyright 2012-2022 Great Scott Gadgets <info@greatscottgadgets.com>
* Copyright 2012 Jared Boone
*
* This file is part of HackRF.
*
* 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 <stdint.h>
#include "usb_type.h"
#include "usb_descriptor.h"
#define USB_VENDOR_ID (0x1D50)
#ifdef HACKRF_ONE
#define USB_PRODUCT_ID (0x6089)
#elif JAWBREAKER
#define USB_PRODUCT_ID (0x604B)
#elif RAD1O
#define USB_PRODUCT_ID (0xCC15)
#else
#define USB_PRODUCT_ID (0xFFFF)
#endif
#define USB_API_VERSION (0x0107)
#define USB_WORD(x) (x & 0xFF), ((x >> 8) & 0xFF)
#define USB_MAX_PACKET0 (64)
#define USB_MAX_PACKET_BULK_FS (64)
#define USB_MAX_PACKET_BULK_HS (512)
#define USB_BULK_IN_EP_ADDR (0x81)
#define USB_BULK_OUT_EP_ADDR (0x02)
#define USB_STRING_LANGID (0x0409)
uint8_t usb_descriptor_device[] = {
18, // bLength
USB_DESCRIPTOR_TYPE_DEVICE, // bDescriptorType
USB_WORD(0x0200), // bcdUSB
0x00, // bDeviceClass
0x00, // bDeviceSubClass
0x00, // bDeviceProtocol
USB_MAX_PACKET0, // bMaxPacketSize0
USB_WORD(USB_VENDOR_ID), // idVendor
USB_WORD(USB_PRODUCT_ID), // idProduct
USB_WORD(USB_API_VERSION), // bcdDevice
0x01, // iManufacturer
0x02, // iProduct
0x04, // iSerialNumber
0x01 // bNumConfigurations
};
uint8_t usb_descriptor_device_qualifier[] = {
10, // bLength
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, // bDescriptorType
USB_WORD(0x0200), // bcdUSB
0x00, // bDeviceClass
0x00, // bDeviceSubClass
0x00, // bDeviceProtocol
64, // bMaxPacketSize0
0x01, // bNumOtherSpeedConfigurations
0x00 // bReserved
};
uint8_t usb_descriptor_configuration_full_speed[] = {
9, // bLength
USB_DESCRIPTOR_TYPE_CONFIGURATION, // bDescriptorType
USB_WORD(32), // wTotalLength
0x01, // bNumInterfaces
0x01, // bConfigurationValue
0x00, // iConfiguration
0x80, // bmAttributes: USB-powered
250, // bMaxPower: 500mA
9, // bLength
USB_DESCRIPTOR_TYPE_INTERFACE, // bDescriptorType
0x00, // bInterfaceNumber
0x00, // bAlternateSetting
0x02, // bNumEndpoints
0x08, // bInterfaceClass: vendor-specific
0x06, // bInterfaceSubClass
0x50, // bInterfaceProtocol: vendor-specific
0x00, // iInterface
7, // bLength
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
USB_BULK_IN_EP_ADDR, // bEndpointAddress
0x02, // bmAttributes: BULK
USB_WORD(USB_MAX_PACKET_BULK_FS), // wMaxPacketSize
0x00, // bInterval: no NAK
7, // bLength
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
USB_BULK_OUT_EP_ADDR, // bEndpointAddress
0x02, // bmAttributes: BULK
USB_WORD(USB_MAX_PACKET_BULK_FS), // wMaxPacketSize
0x00, // bInterval: no NAK
0, // TERMINATOR
};
uint8_t usb_descriptor_configuration_high_speed[] = {
9, // bLength
USB_DESCRIPTOR_TYPE_CONFIGURATION, // bDescriptorType
USB_WORD(32), // wTotalLength
0x01, // bNumInterfaces
0x01, // bConfigurationValue
0x00, // iConfiguration
0x80, // bmAttributes: USB-powered
250, // bMaxPower: 500mA
9, // bLength
USB_DESCRIPTOR_TYPE_INTERFACE, // bDescriptorType
0x00, // bInterfaceNumber
0x00, // bAlternateSetting
0x02, // bNumEndpoints
0x08, // bInterfaceClass: vendor-specific
0x06, // bInterfaceSubClass
0x50, // bInterfaceProtocol: vendor-specific
0x00, // iInterface
7, // bLength
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
USB_BULK_IN_EP_ADDR, // bEndpointAddress
0x02, // bmAttributes: BULK
USB_WORD(USB_MAX_PACKET_BULK_HS), // wMaxPacketSize
0x00, // bInterval: no NAK
7, // bLength
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
USB_BULK_OUT_EP_ADDR, // bEndpointAddress
0x02, // bmAttributes: BULK
USB_WORD(USB_MAX_PACKET_BULK_HS), // wMaxPacketSize
0x00, // bInterval: no NAK
0, // TERMINATOR
};
uint8_t usb_descriptor_string_languages[] = {
0x04, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
USB_WORD(USB_STRING_LANGID), // wLANGID
};
// clang-format off
uint8_t usb_descriptor_string_manufacturer[] = {
40, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
'G', 0x00,
'r', 0x00,
'e', 0x00,
'a', 0x00,
't', 0x00,
' ', 0x00,
'S', 0x00,
'c', 0x00,
'o', 0x00,
't', 0x00,
't', 0x00,
' ', 0x00,
'G', 0x00,
'a', 0x00,
'd', 0x00,
'g', 0x00,
'e', 0x00,
't', 0x00,
's', 0x00,
};
uint8_t usb_descriptor_string_product[] = {
#ifdef HACKRF_ONE
43, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
'P', 0x00,
'o', 0x00,
'r', 0x00,
't', 0x00,
'a', 0x00,
'P', 0x00,
'a', 0x00,
'c', 0x00,
'k', 0x00,
' ', 0x00,
'M', 0x00,
'a', 0x00,
'y', 0x00,
'h', 0x00,
'e', 0x00,
'm', 0x00,
#elif JAWBREAKER
36, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
'H', 0x00,
'a', 0x00,
'c', 0x00,
'k', 0x00,
'R', 0x00,
'F', 0x00,
' ', 0x00,
'J', 0x00,
'a', 0x00,
'w', 0x00,
'b', 0x00,
'r', 0x00,
'e', 0x00,
'a', 0x00,
'k', 0x00,
'e', 0x00,
'r', 0x00,
#elif RAD1O
12, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
'r', 0x00,
'a', 0x00,
'd', 0x00,
'1', 0x00,
'o', 0x00,
#else
14, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
'H', 0x00,
'a', 0x00,
'c', 0x00,
'k', 0x00,
'R', 0x00,
'F', 0x00,
#endif
};
uint8_t usb_descriptor_string_config_description[] = {
24, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
'T', 0x00,
'r', 0x00,
'a', 0x00,
'n', 0x00,
's', 0x00,
'c', 0x00,
'e', 0x00,
'i', 0x00,
'v', 0x00,
'e', 0x00,
'r', 0x00,
};
#ifdef DFU_MODE
uint8_t usb_descriptor_string_serial_number[] = {
30, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
'R', 0x00,
'u', 0x00,
'n', 0x00,
'n', 0x00,
'i', 0x00,
'n', 0x00,
'g', 0x00,
'F', 0x00,
'r', 0x00,
'o', 0x00,
'm', 0x00,
'R', 0x00,
'A', 0x00,
'M', 0x00,
};
#else
uint8_t usb_descriptor_string_serial_number[USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN];
#endif
uint8_t* usb_descriptor_strings[] = {
usb_descriptor_string_languages,
usb_descriptor_string_manufacturer,
usb_descriptor_string_product,
usb_descriptor_string_config_description,
usb_descriptor_string_serial_number,
0, // TERMINATOR
};
uint8_t wcid_string_descriptor[] = {
18, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
'M', 0x00,
'S', 0x00,
'F', 0x00,
'T', 0x00,
'1', 0x00,
'0', 0x00,
'0', 0x00,
USB_WCID_VENDOR_REQ, // vendor request code for further descriptor
0x00
};
uint8_t wcid_feature_descriptor[] = {
0x28, 0x00, 0x00, 0x00, // bLength
USB_WORD(0x0100), // WCID version
USB_WORD(0x0004), // WICD descriptor index
0x01, // bNumSections
0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Reserved
0x00, // bInterfaceNumber
0x01, // Reserved
'W', 'I', 'N', 'U', 'S', 'B', 0x00,0x00, // Compatible ID, padded with zeros
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Sub-compatible ID
0x00,0x00,0x00,0x00,0x00,0x00 // Reserved
};
@@ -0,0 +1,42 @@
/*
* Copyright 2012-2022 Great Scott Gadgets <info@greatscottgadgets.com>
* Copyright 2012 Jared Boone
*
* This file is part of HackRF.
*
* 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 <stdint.h>
extern uint8_t usb_descriptor_device[];
extern uint8_t usb_descriptor_device_qualifier[];
extern uint8_t usb_descriptor_configuration_full_speed[];
extern uint8_t usb_descriptor_configuration_high_speed[];
extern uint8_t usb_descriptor_string_languages[];
extern uint8_t usb_descriptor_string_manufacturer[];
extern uint8_t usb_descriptor_string_product[];
#define USB_DESCRIPTOR_STRING_SERIAL_LEN 32
#define USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN \
(USB_DESCRIPTOR_STRING_SERIAL_LEN * 2 + 2) /* UTF-16LE */
extern uint8_t usb_descriptor_string_serial_number[];
extern uint8_t* usb_descriptor_strings[];
#define USB_WCID_VENDOR_REQ 0x19
extern uint8_t wcid_string_descriptor[];
extern uint8_t wcid_feature_descriptor[];
+165
View File
@@ -0,0 +1,165 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2023 Bernd Herzog
*
* 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 "w25q80bv.hpp"
#include "debug.hpp"
namespace w25q80bv {
void disable_spifi(){
RESET_CTRL1 = RESET_CTRL1_SPIFI_RST;
}
void initialite_spi(){
palSetPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
palOutputPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
const uint32_t clock_prescale_rate = 2;
const uint32_t serial_clock_rate = 2;
SSP_CR1(SSP0_BASE) = 0;
SSP_CPSR(SSP0_BASE) = clock_prescale_rate;
SSP_CR0(SSP0_BASE) = (serial_clock_rate << 8) | SSP_DATA_8BITS;
SSP_CR1(SSP0_BASE) = SSP_ENABLE;
}
void setup() {
/* Init SPIFI GPIO to Normal GPIO */
MMIO32(PIN_GROUP3 + PIN3) = (SCU_SSP_IO | SCU_CONF_FUNCTION2);
MMIO32(PIN_GROUP3 + PIN4) = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
MMIO32(PIN_GROUP3 + PIN5) = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
MMIO32(PIN_GROUP3 + PIN6) = (SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
MMIO32(PIN_GROUP3 + PIN7) = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
MMIO32(PIN_GROUP3 + PIN8) = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
/* configure SSP pins */
MMIO32(SCU_SSP0_CIPO) = (SCU_SSP_IO | SCU_CONF_FUNCTION5);
MMIO32(SCU_SSP0_COPI) = (SCU_SSP_IO | SCU_CONF_FUNCTION5);
MMIO32(SCU_SSP0_SCK) = (SCU_SSP_IO | SCU_CONF_FUNCTION2);
/* configure GPIO pins */
MMIO32(SCU_FLASH_HOLD) = SCU_GPIO_FAST;
MMIO32(SCU_FLASH_WP) = SCU_GPIO_FAST;
MMIO32(SCU_SSP0_CS) = (SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
//remove hardware write protection
/* drive CS, HOLD, and WP pins high */
palSetPad(W25Q80BV_HOLD_PORT, W25Q80BV_HOLD_PAD);
palSetPad(W25Q80BV_WP_PORT, W25Q80BV_WP_PAD);
/* Set GPIO pins as outputs. */
palOutputPad(W25Q80BV_HOLD_PORT, W25Q80BV_HOLD_PAD);
palOutputPad(W25Q80BV_WP_PORT, W25Q80BV_WP_PAD);
}
void wait_for_device() {
uint8_t device_id;
do {
device_id = get_device_id();
} while (device_id != W25Q80BV_DEVICE_ID_RES &&
device_id != W25Q16DV_DEVICE_ID_RES);
}
void wait_not_busy() {
while (get_status() & W25Q80BV_STATUS_BUSY) {HALT_IF_DEBUGGING();}
}
void remove_write_protection() {
uint8_t data[] = {W25Q80BV_WRITE_ENABLE};
palClearPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
for (size_t j = 0; j < 1; j++) {
data[j] = spi_ssp_transfer_word(data[j]);
}
palSetPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
while (!(get_status() & W25Q80BV_STATUS_WEL)) {HALT_IF_DEBUGGING();}
}
uint32_t spi_ssp_transfer_word(const uint32_t data) {
while ((SSP_SR(SSP0_BASE) & SSP_SR_TNF) == 0) {HALT_IF_DEBUGGING();}
SSP_DR(SSP0_BASE) = data;
while (SSP_SR(SSP0_BASE) & SSP_SR_BSY) {HALT_IF_DEBUGGING();}
while ((SSP_SR(SSP0_BASE) & SSP_SR_RNE) == 0) {HALT_IF_DEBUGGING();}
return SSP_DR(SSP0_BASE);
}
uint8_t get_status() {
uint8_t data[] = {W25Q80BV_READ_STATUS1, 0xFF};
palClearPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
for (size_t j = 0; j < 2; j++) {
data[j] = spi_ssp_transfer_word(data[j]);
}
palSetPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
return data[1];
}
uint8_t get_device_id() {
uint8_t data[] = {W25Q80BV_DEVICE_ID, 0xFF, 0xFF, 0xFF, 0xFF};
palClearPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
for (size_t j = 0; j < 5; j++) {
data[j] = spi_ssp_transfer_word(data[j]);
}
palSetPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
return data[4];
}
void erase_chip() {
uint8_t data[] = {W25Q80BV_CHIP_ERASE};
palClearPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
for (size_t j = 0; j < 1; j++) {
data[j] = spi_ssp_transfer_word(data[j]);
}
palSetPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
}
void write(size_t page_index, uint8_t *data_buffer, size_t length) {
size_t page_len = 256U;
size_t addr = page_index * page_len;
uint8_t header[] = {
W25Q80BV_PAGE_PROGRAM,
(uint8_t)((addr & 0xFF0000) >> 16),
(uint8_t)((addr & 0xFF00) >> 8),
(uint8_t)(addr & 0xFF)
};
palClearPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
for (size_t j = 0; j < 4; j++) {
header[j] = spi_ssp_transfer_word(header[j]);
}
for (size_t j = 0; j < length; j++) {
data_buffer[j] = spi_ssp_transfer_word(data_buffer[j]);
}
palSetPad(W25Q80BV_SELECT_PORT, W25Q80BV_SELECT_PAD);
}
}
+140
View File
@@ -0,0 +1,140 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2023 Bernd Herzog
*
* 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 __W25Q80BV_H__
#define __W25Q80BV_H__
#include "ch.h"
#include "hal.h"
#define RGU_BASE 0x40053000
#define RESET_CTRL1 MMIO32(RGU_BASE + 0x104)
#define RESET_CTRL1_SPIFI_RST_SHIFT (21)
#define RESET_CTRL1_SPIFI_RST (1 << RESET_CTRL1_SPIFI_RST_SHIFT)
#define W25Q80BV_WRITE_ENABLE 0x06
#define W25Q80BV_CHIP_ERASE 0xC7
#define W25Q80BV_DEVICE_ID 0xAB
#define W25Q80BV_PAGE_PROGRAM 0x02
#define PERIPH_BASE_APB0 0x40080000
#define SCU_BASE (PERIPH_BASE_APB0 + 0x06000)
#define MMIO32(addr) (*(volatile uint32_t *)(addr))
#define PIN_GROUP3 (SCU_BASE + 0x180)
#define PIN3 0x00C
#define PIN4 0x010
#define PIN5 0x014
#define PIN6 0x018
#define PIN7 0x01C
#define PIN8 0x020
#define BIT0 (1<<0)
#define BIT1 (1<<1)
#define BIT2 (1<<2)
#define BIT3 (1<<3)
#define BIT4 (1<<4)
#define BIT5 (1<<5)
#define BIT6 (1<<6)
#define BIT7 (1<<7)
#define BIT8 (1<<8)
#define SCU_CONF_EPUN_DIS_PULLUP (BIT4)
#define SCU_CONF_EHS_FAST (BIT5)
#define SCU_CONF_EZI_EN_IN_BUFFER (BIT6)
#define SCU_CONF_ZIF_DIS_IN_GLITCH_FILT (BIT7)
#define SCU_GPIO_FAST (SCU_CONF_EPUN_DIS_PULLUP | \
SCU_CONF_EHS_FAST | \
SCU_CONF_EZI_EN_IN_BUFFER | \
SCU_CONF_ZIF_DIS_IN_GLITCH_FILT)
#define SCU_SSP_IO SCU_GPIO_FAST
#define SCU_CONF_FUNCTION0 (0x0)
#define SCU_CONF_FUNCTION2 (0x2)
#define SCU_CONF_FUNCTION4 (0x4)
#define SCU_CONF_FUNCTION5 (0x5)
#define SCU_SSP0_CIPO (PIN_GROUP3 + PIN6)
#define SCU_SSP0_COPI (PIN_GROUP3 + PIN7)
#define SCU_SSP0_SCK (PIN_GROUP3 + PIN3)
#define SCU_SSP0_CS (PIN_GROUP3 + PIN8)
#define SCU_FLASH_HOLD (PIN_GROUP3 + PIN4)
#define SCU_FLASH_WP (PIN_GROUP3 + PIN5)
#define W25Q80BV_DEVICE_ID_RES 0x13 /* Expected device_id for W25Q80BV */
#define W25Q16DV_DEVICE_ID_RES 0x14 /* Expected device_id for W25Q16DV */
#define SSP_CR1(port) MMIO32(port + 0x004)
#define PERIPH_BASE_APB0 0x40080000
#define SSP0_BASE (PERIPH_BASE_APB0 + 0x03000)
#define SSP_CPSR(port) MMIO32(port + 0x010)
#define SSP_CR0(port) MMIO32(port + 0x000)
#define SSP_ENABLE BIT1
#define SSP_DATA_8BITS 0x7
#define palSetPad(port, pad) (LPC_GPIO->SET[(port)] = 1 << (pad))
#define palClearPad(port, pad) (LPC_GPIO->CLR[(port)] = 1 << (pad))
#define palOutputPad(port, pad) (LPC_GPIO->DIR[(port)] |= 1 << (pad))
#define palTogglePad(port, pad) (LPC_GPIO->NOT[(port)] |= 1 << (pad))
#define W25Q80BV_SELECT_PORT 5
#define W25Q80BV_SELECT_PAD 11
#define W25Q80BV_WP_PORT 1
#define W25Q80BV_WP_PAD 15
#define W25Q80BV_HOLD_PORT 1
#define W25Q80BV_HOLD_PAD 14
#define LED_PORT 2
#define LEDRX_PAD 2
#define LEDTX_PAD 8
#define W25Q80BV_STATUS_BUSY 0x01
#define W25Q80BV_STATUS_WEL 0x02
#define W25Q80BV_READ_STATUS1 0x05
#define W25Q80BV_READ_STATUS2 0x35
#define PERIPH_BASE_APB0 0x40080000
#define SSP0_BASE (PERIPH_BASE_APB0 + 0x03000)
#define SSP_DR(port) MMIO32(port + 0x008)
#define SSP_SR(port) MMIO32(port + 0x00C)
#define SSP_SR_TNF BIT1
#define SSP_SR_RNE BIT2
#define SSP_SR_BSY BIT4
namespace w25q80bv {
void disable_spifi();
uint8_t get_status();
void wait_for_device();
void wait_not_busy();
uint32_t spi_ssp_transfer_word(const uint32_t data);
void initialite_spi();
void setup();
void remove_write_protection();
uint8_t get_device_id();
void erase_chip();
void write(size_t page_index, uint8_t *data_buffer, size_t length);
}
#endif/*__W25Q80BV_H__*/
@@ -25,8 +25,10 @@ MEMORY
{
flash (rx) : org = 0x00000000, len = 32752 /* Local SRAM @ 0x10080000 */
ram (rwx) : org = 0x10000000, len = 96k /* Local SRAM @ 0x10000000 */
ram_usb (rwx) : org = 0x20008000, len = 32K
}
usb_bulk_buffer = ORIGIN(ram_usb);
__ram_start__ = ORIGIN(ram);
__ram_size__ = LENGTH(ram);
__ram_end__ = __ram_start__ + __ram_size__;
File diff suppressed because it is too large Load Diff
+153 -143
View File
@@ -36,183 +36,193 @@ using namespace modems;
using namespace serializer;
namespace portapack {
namespace persistent_memory {
enum backlight_timeout_t {
Timeout5Sec = 0,
Timeout15Sec = 1,
Timeout30Sec = 2,
Timeout60Sec = 3,
Timeout180Sec = 4,
Timeout300Sec = 5,
Timeout600Sec = 6,
Timeout3600Sec = 7,
};
namespace persistent_memory {
struct backlight_config_t {
public:
backlight_config_t() :
_timeout_enum(backlight_timeout_t::Timeout600Sec),
_timeout_enabled(false)
{
}
enum backlight_timeout_t {
Timeout5Sec = 0,
Timeout15Sec = 1,
Timeout30Sec = 2,
Timeout60Sec = 3,
Timeout180Sec = 4,
Timeout300Sec = 5,
Timeout600Sec = 6,
Timeout3600Sec = 7,
};
backlight_config_t(
backlight_timeout_t timeout_enum,
bool timeout_enabled
) :
_timeout_enum(timeout_enum),
_timeout_enabled(timeout_enabled)
{
}
struct backlight_config_t {
public:
backlight_config_t() :
_timeout_enum(backlight_timeout_t::Timeout600Sec),
_timeout_enabled(false)
{
}
bool timeout_enabled() const {
return _timeout_enabled;
}
backlight_config_t(
backlight_timeout_t timeout_enum,
bool timeout_enabled
) :
_timeout_enum(timeout_enum),
_timeout_enabled(timeout_enabled)
{
}
backlight_timeout_t timeout_enum() const {
return _timeout_enum;
}
bool timeout_enabled() const {
return _timeout_enabled;
}
uint32_t timeout_seconds() const {
switch(timeout_enum()) {
case Timeout5Sec: return 5;
case Timeout15Sec: return 15;
case Timeout30Sec: return 30;
case Timeout60Sec: return 60;
case Timeout180Sec: return 180;
case Timeout300Sec: return 300;
default:
case Timeout600Sec: return 600;
case Timeout3600Sec: return 3600;
}
}
backlight_timeout_t timeout_enum() const {
return _timeout_enum;
}
private:
backlight_timeout_t _timeout_enum;
bool _timeout_enabled;
};
uint32_t timeout_seconds() const {
switch(timeout_enum()) {
case Timeout5Sec: return 5;
case Timeout15Sec: return 15;
case Timeout30Sec: return 30;
case Timeout60Sec: return 60;
case Timeout180Sec: return 180;
case Timeout300Sec: return 300;
default:
case Timeout600Sec: return 600;
case Timeout3600Sec: return 3600;
}
}
namespace cache {
private:
backlight_timeout_t _timeout_enum;
bool _timeout_enabled;
};
/* Set values in cache to sensible defaults. */
void defaults();
namespace cache {
/* Load cached settings from values in persistent RAM, replacing with defaults
* if persistent RAM contents appear to be invalid. */
void init();
/* Set values in cache to sensible defaults. */
void defaults();
/* Calculate a check value for cached settings, and copy the check value and
* settings into persistent RAM. Intended to be called periodically to update
* persistent settings with current settings. */
void persist();
/* Load cached settings from values in persistent RAM, replacing with defaults
* if persistent RAM contents appear to be invalid. */
void init();
} /* namespace cache */
/* Calculate a check value for cached settings, and copy the check value and
* settings into persistent RAM. Intended to be called periodically to update
* persistent settings with current settings. */
void persist();
using ppb_t = int32_t;
} /* namespace cache */
rf::Frequency tuned_frequency();
void set_tuned_frequency(const rf::Frequency new_value);
using ppb_t = int32_t;
ppb_t correction_ppb();
void set_correction_ppb(const ppb_t new_value);
rf::Frequency tuned_frequency();
void set_tuned_frequency(const rf::Frequency new_value);
void set_touch_calibration(const touch::Calibration& new_value);
const touch::Calibration& touch_calibration();
ppb_t correction_ppb();
void set_correction_ppb(const ppb_t new_value);
serial_format_t serial_format();
void set_serial_format(const serial_format_t new_value);
void set_touch_calibration(const touch::Calibration& new_value);
const touch::Calibration& touch_calibration();
int32_t tone_mix();
void set_tone_mix(const int32_t new_value);
serial_format_t serial_format();
void set_serial_format(const serial_format_t new_value);
int32_t afsk_mark_freq();
void set_afsk_mark(const int32_t new_value);
int32_t tone_mix();
void set_tone_mix(const int32_t new_value);
int32_t afsk_space_freq();
void set_afsk_space(const int32_t new_value);
int32_t afsk_mark_freq();
void set_afsk_mark(const int32_t new_value);
int32_t modem_baudrate();
void set_modem_baudrate(const int32_t new_value);
int32_t afsk_space_freq();
void set_afsk_space(const int32_t new_value);
uint8_t modem_repeat();
void set_modem_repeat(const uint32_t new_value);
int32_t modem_baudrate();
void set_modem_baudrate(const int32_t new_value);
uint32_t playing_dead();
void set_playing_dead(const uint32_t new_value);
uint8_t modem_repeat();
void set_modem_repeat(const uint32_t new_value);
uint32_t playdead_sequence();
void set_playdead_sequence(const uint32_t new_value);
uint32_t playing_dead();
void set_playing_dead(const uint32_t new_value);
bool stealth_mode();
void set_stealth_mode(const bool v);
uint32_t playdead_sequence();
void set_playdead_sequence(const uint32_t new_value);
uint8_t config_cpld();
void set_config_cpld(uint8_t i);
bool stealth_mode();
void set_stealth_mode(const bool v);
bool config_splash();
bool config_hamitup();
int64_t config_hamitup_freq();
bool show_gui_return_icon();
bool load_app_settings();
bool save_app_settings();
bool show_bigger_qr_code();
bool hide_clock();
bool clock_with_date();
bool config_login();
bool config_speaker();
backlight_config_t config_backlight_timer();
bool disable_touchscreen();
uint8_t config_cpld();
void set_config_cpld(uint8_t i);
void set_gui_return_icon(bool v);
void set_load_app_settings(bool v);
void set_save_app_settings(bool v);
void set_show_bigger_qr_code(bool v);
void set_config_splash(bool v);
void set_config_hamitup(bool v);
void set_config_hamitup_freq(const int64_t v );
void set_clock_hidden(bool v);
void set_clock_with_date(bool v);
void set_config_login(bool v);
void set_config_speaker(bool v);
void set_config_backlight_timer(const backlight_config_t& new_value);
void set_disable_touchscreen(bool v);
bool config_splash();
bool config_hide_converter();
bool config_converter();
bool config_updown_converter();
int64_t config_converter_freq();
bool show_gui_return_icon();
bool load_app_settings();
bool save_app_settings();
bool show_bigger_qr_code();
bool hide_clock();
bool clock_with_date();
bool config_login();
bool config_speaker();
backlight_config_t config_backlight_timer();
bool disable_touchscreen();
//uint8_t ui_config_textentry();
//void set_config_textentry(uint8_t new_value);
void set_gui_return_icon(bool v);
void set_load_app_settings(bool v);
void set_save_app_settings(bool v);
void set_show_bigger_qr_code(bool v);
void set_config_splash(bool v);
void set_config_hide_converter(bool v);
void set_config_converter(bool v);
void set_config_updown_converter(const bool v);
void set_config_converter_freq(const int64_t v );
void set_clock_hidden(bool v);
void set_clock_with_date(bool v);
void set_config_login(bool v);
void set_config_speaker(bool v);
void set_config_backlight_timer(const backlight_config_t& new_value);
void set_disable_touchscreen(bool v);
uint32_t pocsag_last_address();
void set_pocsag_last_address(uint32_t address);
//uint8_t ui_config_textentry();
//void set_config_textentry(uint8_t new_value);
uint32_t pocsag_ignore_address();
void set_pocsag_ignore_address(uint32_t address);
uint32_t pocsag_last_address();
void set_pocsag_last_address(uint32_t address);
bool clkout_enabled();
void set_clkout_enabled(bool v);
uint32_t clkout_freq();
void set_clkout_freq(uint32_t freq);
uint32_t pocsag_ignore_address();
void set_pocsag_ignore_address(uint32_t address);
/* Recon app */
bool recon_autosave_freqs();
bool recon_autostart_recon();
bool recon_continuous();
bool recon_clear_output();
bool recon_load_freqs();
bool recon_load_ranges();
bool recon_update_ranges_when_recon();
bool recon_load_hamradios();
bool recon_match_mode();
void set_recon_autosave_freqs(const bool v);
void set_recon_autostart_recon(const bool v);
void set_recon_continuous(const bool v);
void set_recon_clear_output(const bool v);
void set_recon_load_freqs(const bool v);
void set_recon_load_ranges(const bool v);
void set_recon_update_ranges_when_recon(const bool v);
void set_recon_load_hamradios(const bool v );
void set_recon_match_mode( const bool v );
bool clkout_enabled();
void set_clkout_enabled(bool v);
uint32_t clkout_freq();
void set_clkout_freq(uint32_t freq);
/* Recon app */
bool recon_autosave_freqs();
bool recon_autostart_recon();
bool recon_continuous();
bool recon_clear_output();
bool recon_load_freqs();
bool recon_load_ranges();
bool recon_update_ranges_when_recon();
bool recon_load_hamradios();
bool recon_match_mode();
void set_recon_autosave_freqs(const bool v);
void set_recon_autostart_recon(const bool v);
void set_recon_continuous(const bool v);
void set_recon_clear_output(const bool v);
void set_recon_load_freqs(const bool v);
void set_recon_load_ranges(const bool v);
void set_recon_update_ranges_when_recon(const bool v);
void set_recon_load_hamradios(const bool v );
void set_recon_match_mode( const bool v );
// sd persisting settings
int save_persistent_settings_to_file( std::string filename );
int load_persistent_settings_from_file( std::string filename );
} /* namespace persistent_memory */
} /* namespace persistent_memory */
} /* namespace portapack */
#endif/*__PORTAPACK_PERSISTENT_MEMORY_H__*/
+3
View File
@@ -106,6 +106,8 @@ constexpr image_tag_t image_tag_gps { 'P', 'G', 'P', 'S' };
constexpr image_tag_t image_tag_siggen { 'P', 'S', 'I', 'G' };
constexpr image_tag_t image_tag_sstv_tx { 'P', 'S', 'T', 'X' };
constexpr image_tag_t image_tag_tones { 'P', 'T', 'O', 'N' };
constexpr image_tag_t image_tag_flash_utility { 'P', 'F', 'U', 'T' };
constexpr image_tag_t image_tag_usb_sd { 'P', 'U', 'S', 'B' };
constexpr image_tag_t image_tag_noop { 'P', 'N', 'O', 'P' };
@@ -114,6 +116,7 @@ constexpr image_tag_t image_tag_hackrf { 'H', 'R', 'F', '1' };
struct chunk_t {
const image_tag_t tag;
const uint32_t length;
const uint32_t compressed_data_size;
const uint8_t data[];
const chunk_t* next() const {
Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

+22 -17
View File
@@ -27,7 +27,7 @@ import struct
usage_message = """
PortaPack image chunk writer
Usage: <command> <input_binary> <four-characer tag> <output_tagged_binary> [<chunk max size>]
Usage: <command> <input_binary> <four-characer tag> <output_tagged_binary>
"""
def read_image(path):
@@ -41,17 +41,33 @@ def write_image(data, path):
f.write(data)
f.close()
input_image_max_length = 32768
if len(sys.argv) in (4, 5):
if len(sys.argv) == 4:
input_image = read_image(sys.argv[1])
input_image = bytearray(input_image)
tag = tuple(map(ord, sys.argv[2]))
output_path = sys.argv[3]
if len(sys.argv) == 5:
input_image_max_length = int(sys.argv[4])
if input_image[4] & 8 == 8:
input_image = input_image[15:]
else:
input_image = input_image[7:]
if (len(input_image) & 3) != 0:
for i in range(4 - (len(input_image) & 3)):
input_image.append(0)
output_image = bytearray()
output_image += struct.pack('<4BI', tag[0], tag[1], tag[2], tag[3], len(input_image) - 4)
output_image += input_image
write_image(output_image, output_path)
elif len(sys.argv) == 2:
input_image = bytearray()
null_image = bytearray()
tag = (0, 0, 0, 0)
output_path = sys.argv[1]
null_image += struct.pack('<4BI', tag[0], tag[1], tag[2], tag[3], 0)
write_image(null_image, output_path)
else:
print(usage_message)
sys.exit(-1)
@@ -59,14 +75,3 @@ else:
if len(tag) != 4:
print(usage_message)
sys.exit(-2)
if len(input_image) > input_image_max_length:
raise RuntimeError('image size of %d exceeds device size of %d bytes' % (len(input_image), input_image_max_length))
if (len(input_image) & 3) != 0:
raise RuntimeError('image size of %d is not multiple of four' % (len(input_image,)))
output_image = bytearray()
output_image += struct.pack('<4BI', tag[0], tag[1], tag[2], tag[3], len(input_image))
output_image += input_image
write_image(output_image, output_path)
Binary file not shown.
Binary file not shown.