mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-09-15 02:52:58 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d94afe364b | |||
| 2e4db3dd27 | |||
| 97d3edbde7 | |||
| 4c18b80e42 | |||
| 01034af077 | |||
| 57ce978bab | |||
| 854ac514cb | |||
| b47a5fe0c8 | |||
| af362600ef |
+2
-1
@@ -1 +1,2 @@
|
||||
build
|
||||
*
|
||||
!firmware/tools/docker-entrypoint.sh
|
||||
@@ -30,7 +30,7 @@ This repository expands upon the previous work by many people and aims to consta
|
||||
|
||||
:heavy_check_mark: A recommended one is this [PortaPack H2](https://www.ebay.com/itm/116382397447), that includes everything you need with the plastic case "inspired" on [this](https://github.com/portapack-mayhem/mayhem-firmware/wiki/3d-printed-enclosure).
|
||||
|
||||
:heavy_check_mark: Some individuals lean towards the [H2 with a metal enclosure](https://share.hackrf.app/LZPBH9), but its advantages remain debated. Share your insights on our [wiki](https://github.com/portapack-mayhem/mayhem-firmware/wiki/Hardware-overview).
|
||||
:heavy_check_mark: Some individuals lean towards the [H2 with a metal enclosure](https://share.hackrf.app/9FJFJE), but its advantages remain debated. Share your insights on our [wiki](https://github.com/portapack-mayhem/mayhem-firmware/wiki/Hardware-overview).
|
||||
|
||||
:warning: Be cautious , *ask* the seller about compatibility with the latest releases. Look out for the description of the item, if they provide the firmware files for an older version or they have custom setup instructions, this means it might be **NOT compatible**, for example:
|
||||
|
||||
|
||||
Executable
+83
@@ -0,0 +1,83 @@
|
||||
#!/bin/bash
|
||||
|
||||
#################################################
|
||||
# This script aids building mayhem inside docker
|
||||
#
|
||||
# Basic usage:
|
||||
# - Build dev container: ./dockerize.sh build
|
||||
# - Build mayhem: ./dockerize.sh
|
||||
#
|
||||
# The image will be automatically build if it
|
||||
# does not exist, but if the dockerfile changes
|
||||
# it need to be rebuilt manually.
|
||||
#
|
||||
# Advanced parameters:
|
||||
# - Get a shell inside the build image to
|
||||
# inspect problems: ./dockerize.sh shell
|
||||
# - Give additional parameters to the container:
|
||||
# ./dockerize.sh -j10
|
||||
# ./dockerize.sh ninja -j10
|
||||
# - Use a different dockerfile:
|
||||
# ./dockerize.sh build dockerfile-other
|
||||
# - Use a different cpu architecture:
|
||||
# ./dockerize.sh build dockerfile-nogit-arm arm64
|
||||
#
|
||||
# Environment variables:
|
||||
# - It is possible to override the default image
|
||||
# name that is being used to build and run the
|
||||
# build container using an environment variable.
|
||||
# The default is 'portapack-dev'
|
||||
# Override by setting the following environment
|
||||
# variable: MAYHEM_DEV_DOCKER_IMAGE
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (C) 2024 u-foka
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
set -e # exit immediatelly on any failure
|
||||
|
||||
DIR="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
|
||||
|
||||
IMAGE="${MAYHEM_DEV_DOCKER_IMAGE:-portapack-dev}"
|
||||
|
||||
build_image() {
|
||||
DOCKERFILE=${1:-dockerfile-nogit}
|
||||
PLATFORM=${2:-amd64}
|
||||
docker build --platform "linux/${PLATFORM}" -t "${IMAGE}" -f "${DOCKERFILE}" .
|
||||
}
|
||||
|
||||
start_docker() {
|
||||
if [ -z "$(docker images -q ${IMAGE} 2> /dev/null)" ]; then
|
||||
build_image
|
||||
fi
|
||||
|
||||
exec docker run -v "${DIR}:/havoc" -u "$(id -u):$(id -g)" -ti --rm "${IMAGE}" "$@"
|
||||
}
|
||||
|
||||
if [ "$1" = 'shell' ]; then # open a shell into the container
|
||||
start_docker "bash -li"
|
||||
elif [ "$1" = 'build' ]; then # build the default (or specified) target with ninja
|
||||
shift # remove the first item from $@ as we consumed it, we can then pass the rest on to make
|
||||
build_image "$@"
|
||||
exit $?
|
||||
fi
|
||||
|
||||
start_docker "$@"
|
||||
@@ -55,22 +55,24 @@ CaptureAppView::CaptureAppView(NavigationView& nav)
|
||||
this->field_frequency.set_step(v);
|
||||
};
|
||||
|
||||
option_format.set_selected_index(0); // Default to C16
|
||||
option_format.set_selected_index(file_format);
|
||||
option_format.on_change = [this](size_t, uint32_t file_type) {
|
||||
file_format = file_type;
|
||||
record_view.set_file_type((RecordView::FileType)file_type);
|
||||
};
|
||||
|
||||
check_trim.set_value(trim);
|
||||
check_trim.on_select = [this](Checkbox&, bool v) {
|
||||
trim = v;
|
||||
record_view.set_auto_trim(v);
|
||||
};
|
||||
|
||||
freqman_set_bandwidth_option(SPEC_MODULATION, option_bandwidth);
|
||||
option_bandwidth.on_change = [this](size_t, uint32_t bandwidth) {
|
||||
option_bandwidth.on_change = [this](size_t, uint32_t new_capture_rate) {
|
||||
/* Nyquist would imply a sample rate of 2x bandwidth, but because the ADC
|
||||
* provides 2 values (I,Q), the sample_rate is equal to bandwidth here. */
|
||||
auto sample_rate = bandwidth;
|
||||
|
||||
/* base_rate (bandwidth) is used for FFT calculation and display LCD, and also in recording writing SD Card rate. */
|
||||
/* capture_rate (bandwidth) is used for FFT calculation and display LCD, and also in recording writing SD Card rate. */
|
||||
/* ex. sampling_rate values, 4Mhz, when recording 500 kHz (BW) and fs 8 Mhz, when selected 1 Mhz BW ... */
|
||||
/* ex. recording 500kHz BW to .C16 file, base_rate clock 500kHz x2(I,Q) x 2 bytes (int signed) =2MB/sec rate SD Card. */
|
||||
|
||||
@@ -78,7 +80,7 @@ CaptureAppView::CaptureAppView(NavigationView& nav)
|
||||
|
||||
// record_view determines the correct oversampling to apply and returns the actual sample rate.
|
||||
// NB: record_view is what actually updates proc_capture baseband settings.
|
||||
auto actual_sample_rate = record_view.set_sampling_rate(sample_rate);
|
||||
auto actual_sample_rate = record_view.set_sampling_rate(new_capture_rate);
|
||||
|
||||
// Update the radio model with the actual sampling rate.
|
||||
receiver_model.set_sampling_rate(actual_sample_rate);
|
||||
@@ -88,19 +90,19 @@ CaptureAppView::CaptureAppView(NavigationView& nav)
|
||||
receiver_model.set_baseband_bandwidth(anti_alias_filter_bandwidth);
|
||||
|
||||
// Automatically switch default capture format to C8 when bandwidth setting is increased to >=1.5MHz anb back to C16 for <=1,25Mhz
|
||||
if ((bandwidth >= 1500000) && (previous_bandwidth < 1500000)) {
|
||||
if ((new_capture_rate >= 1500000) && (capture_rate < 1500000)) {
|
||||
option_format.set_selected_index(1); // Default C8 format for REC, 1500K ... 5500k
|
||||
}
|
||||
if ((bandwidth <= 1250000) && (previous_bandwidth > 1250000)) {
|
||||
if ((new_capture_rate <= 1250000) && (capture_rate > 1250000)) {
|
||||
option_format.set_selected_index(0); // Default C16 format for REC , 12k5 ... 1250K
|
||||
}
|
||||
previous_bandwidth = bandwidth;
|
||||
capture_rate = new_capture_rate;
|
||||
|
||||
waterfall.start();
|
||||
};
|
||||
|
||||
receiver_model.enable();
|
||||
option_bandwidth.set_by_value(500000);
|
||||
option_bandwidth.set_by_value(capture_rate);
|
||||
|
||||
record_view.on_error = [&nav](std::string message) {
|
||||
nav.display_modal("Error", message);
|
||||
|
||||
@@ -48,12 +48,21 @@ class CaptureAppView : public View {
|
||||
|
||||
private:
|
||||
static constexpr ui::Dim header_height = 3 * 16;
|
||||
uint32_t previous_bandwidth{500000};
|
||||
|
||||
uint32_t capture_rate{500000};
|
||||
uint32_t file_format{0};
|
||||
bool trim{false};
|
||||
|
||||
NavigationView& nav_;
|
||||
RxRadioState radio_state_{ReceiverModel::Mode::Capture};
|
||||
app_settings::SettingsManager settings_{
|
||||
"rx_capture", app_settings::Mode::RX};
|
||||
"rx_capture",
|
||||
app_settings::Mode::RX,
|
||||
{
|
||||
{"capture_rate"sv, &capture_rate},
|
||||
{"file_format"sv, &file_format},
|
||||
{"trim"sv, &trim},
|
||||
}};
|
||||
|
||||
Labels labels{
|
||||
{{0 * 8, 1 * 16}, "Rate:", Theme::getInstance()->fg_light->foreground},
|
||||
|
||||
@@ -92,6 +92,9 @@ void ExternalModuleView::on_tick_second() {
|
||||
case app_location_t::TX:
|
||||
btnText += " (TX)";
|
||||
break;
|
||||
case app_location_t::SETTINGS:
|
||||
btnText += " (Settings)";
|
||||
break;
|
||||
case app_location_t::DEBUG:
|
||||
btnText += " (Debug)";
|
||||
break;
|
||||
|
||||
@@ -53,6 +53,8 @@ namespace fs = std::filesystem;
|
||||
#include "i2cdevmanager.hpp"
|
||||
#include "i2cdev_max17055.hpp"
|
||||
|
||||
#include "file_reader.hpp"
|
||||
|
||||
extern ui::SystemView* system_view_ptr;
|
||||
|
||||
namespace pmem = portapack::persistent_memory;
|
||||
@@ -705,11 +707,28 @@ SetEncoderDialView::SetEncoderDialView(NavigationView& nav) {
|
||||
&field_encoder_dial_sensitivity,
|
||||
&field_encoder_rate_multiplier,
|
||||
&button_save,
|
||||
&button_cancel});
|
||||
&button_cancel,
|
||||
&button_dial_sensitivity_plus,
|
||||
&button_dial_sensitivity_minus,
|
||||
&button_rate_multiplier_plus,
|
||||
&button_rate_multiplier_minus});
|
||||
|
||||
field_encoder_dial_sensitivity.set_by_value(pmem::encoder_dial_sensitivity());
|
||||
field_encoder_rate_multiplier.set_value(pmem::encoder_rate_multiplier());
|
||||
|
||||
button_dial_sensitivity_plus.on_select = [this](Button&) {
|
||||
field_encoder_dial_sensitivity.on_encoder(1);
|
||||
};
|
||||
button_dial_sensitivity_minus.on_select = [this](Button&) {
|
||||
field_encoder_dial_sensitivity.on_encoder(-1);
|
||||
};
|
||||
button_rate_multiplier_plus.on_select = [this](Button&) {
|
||||
field_encoder_rate_multiplier.on_encoder(1);
|
||||
};
|
||||
button_rate_multiplier_minus.on_select = [this](Button&) {
|
||||
field_encoder_rate_multiplier.on_encoder(-1);
|
||||
};
|
||||
|
||||
button_save.on_select = [&nav, this](Button&) {
|
||||
pmem::set_encoder_dial_sensitivity(field_encoder_dial_sensitivity.selected_index_value());
|
||||
pmem::set_encoder_rate_multiplier(field_encoder_rate_multiplier.value());
|
||||
@@ -975,67 +994,6 @@ void SetMenuColorView::focus() {
|
||||
button_save.focus();
|
||||
}
|
||||
|
||||
/* SetAutoStartView ************************************/
|
||||
|
||||
SetAutostartView::SetAutostartView(NavigationView& nav) {
|
||||
add_children({&labels,
|
||||
&button_save,
|
||||
&button_cancel,
|
||||
&button_reset,
|
||||
&options});
|
||||
|
||||
button_save.on_select = [&nav, this](Button&) {
|
||||
autostart_app = "";
|
||||
if (selected != 0) {
|
||||
auto it = full_app_list.find(selected);
|
||||
if (it != full_app_list.end())
|
||||
autostart_app = it->second;
|
||||
}
|
||||
nav.pop();
|
||||
};
|
||||
|
||||
button_cancel.on_select = [&nav, this](Button&) {
|
||||
nav.pop();
|
||||
};
|
||||
|
||||
button_reset.on_select = [this](Button&) {
|
||||
selected = 0;
|
||||
options.set_selected_index(0);
|
||||
autostart_app = "";
|
||||
};
|
||||
|
||||
// options
|
||||
i = 0;
|
||||
OptionsField::option_t o{"-none-", i};
|
||||
opts.emplace_back(o);
|
||||
for (auto& app : NavigationView::appList) {
|
||||
if (app.id == nullptr) continue;
|
||||
i++;
|
||||
o = {app.displayName, i};
|
||||
opts.emplace_back(o);
|
||||
full_app_list.emplace(i, app.id);
|
||||
if (autostart_app == app.id) selected = i;
|
||||
}
|
||||
ExternalItemsMenuLoader::load_all_external_items_callback([this](ui::AppInfoConsole& app) {
|
||||
if (app.appCallName == nullptr) return;
|
||||
i++;
|
||||
OptionsField::option_t o = {app.appFriendlyName, i};
|
||||
opts.emplace_back(o);
|
||||
full_app_list.emplace(i, app.appCallName);
|
||||
if (autostart_app == app.appCallName) selected = i;
|
||||
});
|
||||
|
||||
options.set_options(opts);
|
||||
options.on_change = [this](size_t, OptionsField::value_t v) {
|
||||
selected = v;
|
||||
};
|
||||
options.set_selected_index(selected);
|
||||
}
|
||||
|
||||
void SetAutostartView::focus() {
|
||||
options.focus();
|
||||
}
|
||||
|
||||
/* SetThemeView ************************************/
|
||||
|
||||
SetThemeView::SetThemeView(NavigationView& nav) {
|
||||
@@ -1117,9 +1075,12 @@ SettingsMenuView::SettingsMenuView(NavigationView& nav)
|
||||
}
|
||||
|
||||
void SettingsMenuView::on_populate() {
|
||||
if (pmem::show_gui_return_icon()) {
|
||||
const bool return_icon = pmem::show_gui_return_icon();
|
||||
|
||||
if (return_icon) {
|
||||
add_items({{"..", ui::Color::light_grey(), &bitmap_icon_previous, [this]() { nav_.pop(); }}});
|
||||
}
|
||||
|
||||
add_items({
|
||||
{"App Settings", ui::Color::dark_cyan(), &bitmap_icon_notepad, [this]() { nav_.push<AppSettingsView>(); }},
|
||||
{"Audio", ui::Color::dark_cyan(), &bitmap_icon_speaker, [this]() { nav_.push<SetAudioView>(); }},
|
||||
@@ -1138,9 +1099,11 @@ void SettingsMenuView::on_populate() {
|
||||
{"Display", ui::Color::dark_cyan(), &bitmap_icon_brightness, [this]() { nav_.push<SetDisplayView>(); }},
|
||||
{"Menu Color", ui::Color::dark_cyan(), &bitmap_icon_brightness, [this]() { nav_.push<SetMenuColorView>(); }},
|
||||
{"Theme", ui::Color::dark_cyan(), &bitmap_icon_setup, [this]() { nav_.push<SetThemeView>(); }},
|
||||
{"Autostart", ui::Color::dark_cyan(), &bitmap_icon_setup, [this]() { nav_.push<SetAutostartView>(); }},
|
||||
});
|
||||
|
||||
if (battery::BatteryManagement::isDetected()) add_item({"Battery", ui::Color::dark_cyan(), &bitmap_icon_batt_icon, [this]() { nav_.push<SetBatteryView>(); }});
|
||||
|
||||
add_external_items(nav_, app_location_t::SETTINGS, *this, return_icon ? 1 : 0);
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
@@ -611,6 +611,22 @@ class SetEncoderDialView : public View {
|
||||
1,
|
||||
' '};
|
||||
|
||||
Button button_dial_sensitivity_plus{
|
||||
{20 * 8, 4 * 16, 16, 16},
|
||||
"+"};
|
||||
|
||||
Button button_dial_sensitivity_minus{
|
||||
{20 * 8, 6 * 16, 16, 16},
|
||||
"-"};
|
||||
|
||||
Button button_rate_multiplier_plus{
|
||||
{20 * 8, 11 * 16, 16, 16},
|
||||
"+"};
|
||||
|
||||
Button button_rate_multiplier_minus{
|
||||
{20 * 8, 13 * 16, 16, 16},
|
||||
"-"};
|
||||
|
||||
Button button_save{
|
||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||
"Save"};
|
||||
@@ -888,47 +904,6 @@ class SetMenuColorView : public View {
|
||||
};
|
||||
};
|
||||
|
||||
class SetAutostartView : public View {
|
||||
public:
|
||||
SetAutostartView(NavigationView& nav);
|
||||
|
||||
void focus() override;
|
||||
|
||||
std::string title() const override { return "Autostart"; };
|
||||
|
||||
private:
|
||||
int32_t i = 0;
|
||||
std::string autostart_app{""};
|
||||
OptionsField::options_t opts{};
|
||||
std::map<int32_t, std::string> full_app_list{}; // looking table
|
||||
int32_t selected = 0;
|
||||
SettingsStore nav_setting{
|
||||
"nav"sv,
|
||||
{{"autostart_app"sv, &autostart_app}}};
|
||||
Labels labels{
|
||||
{{1 * 8, 1 * 16}, "Select app to start on boot", Theme::getInstance()->fg_light->foreground},
|
||||
{{2 * 8, 2 * 16}, "(an SD Card is required)", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
Button button_save{
|
||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||
"Save"};
|
||||
|
||||
OptionsField options{
|
||||
{0 * 8, 4 * 16},
|
||||
screen_width / 8,
|
||||
{},
|
||||
true};
|
||||
|
||||
Button button_cancel{
|
||||
{16 * 8, 16 * 16, 12 * 8, 32},
|
||||
"Cancel",
|
||||
};
|
||||
|
||||
Button button_reset{
|
||||
{2 * 8, 6 * 16, screen_width - 4 * 8, 32},
|
||||
"Reset"};
|
||||
};
|
||||
|
||||
class SetThemeView : public View {
|
||||
public:
|
||||
SetThemeView(NavigationView& nav);
|
||||
@@ -1012,6 +987,7 @@ class SettingsMenuView : public BtnGridView {
|
||||
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
|
||||
void on_populate() override;
|
||||
};
|
||||
|
||||
|
||||
@@ -2531,6 +2531,44 @@ static constexpr Bitmap bitmap_icon_batt_icon{
|
||||
{16, 16},
|
||||
bitmap_icon_batt_icon_data};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_temperature_data[] = {
|
||||
0x00,
|
||||
0x01,
|
||||
0x80,
|
||||
0x01,
|
||||
0x80,
|
||||
0x05,
|
||||
0xC0,
|
||||
0x0D,
|
||||
0x40,
|
||||
0x0D,
|
||||
0xD0,
|
||||
0x1F,
|
||||
0x70,
|
||||
0x15,
|
||||
0xB0,
|
||||
0x1A,
|
||||
0x58,
|
||||
0x35,
|
||||
0xB8,
|
||||
0x3A,
|
||||
0x58,
|
||||
0x34,
|
||||
0x28,
|
||||
0x28,
|
||||
0x18,
|
||||
0x30,
|
||||
0x30,
|
||||
0x18,
|
||||
0x60,
|
||||
0x0C,
|
||||
0xC0,
|
||||
0x07,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_temperature{
|
||||
{16, 16},
|
||||
bitmap_icon_temperature_data};
|
||||
|
||||
static constexpr uint8_t bitmap_tab_edge_data[] = {
|
||||
0x00,
|
||||
0x01,
|
||||
@@ -4789,6 +4827,44 @@ static constexpr Bitmap bitmap_icon_ais{
|
||||
{16, 16},
|
||||
bitmap_icon_ais_data};
|
||||
|
||||
static constexpr uint8_t bitmap_temperature_data[] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x20,
|
||||
0x00,
|
||||
0x70,
|
||||
0x3E,
|
||||
0x88,
|
||||
0x00,
|
||||
0x88,
|
||||
0x00,
|
||||
0x88,
|
||||
0x3E,
|
||||
0x88,
|
||||
0x00,
|
||||
0x88,
|
||||
0x00,
|
||||
0x88,
|
||||
0x3E,
|
||||
0x88,
|
||||
0x00,
|
||||
0x04,
|
||||
0x01,
|
||||
0x74,
|
||||
0x01,
|
||||
0x04,
|
||||
0x01,
|
||||
0x88,
|
||||
0x00,
|
||||
0x70,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
};
|
||||
static constexpr Bitmap bitmap_temperature{
|
||||
{16, 16},
|
||||
bitmap_temperature_data};
|
||||
|
||||
static constexpr uint8_t bitmap_titlebar_image_data[] = {
|
||||
0x00,
|
||||
0x00,
|
||||
@@ -5701,6 +5777,44 @@ static constexpr Bitmap bitmap_icon_options_datetime{
|
||||
{16, 16},
|
||||
bitmap_icon_options_datetime_data};
|
||||
|
||||
static constexpr uint8_t bitmap_icon_tune_fork_data[] = {
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x22,
|
||||
0x44,
|
||||
0x21,
|
||||
0x84,
|
||||
0x2D,
|
||||
0xB4,
|
||||
0x25,
|
||||
0xA4,
|
||||
0x25,
|
||||
0xA4,
|
||||
0x2D,
|
||||
0xB4,
|
||||
0x61,
|
||||
0x86,
|
||||
0xC2,
|
||||
0x43,
|
||||
0x80,
|
||||
0x01,
|
||||
0x80,
|
||||
0x01,
|
||||
0x80,
|
||||
0x01,
|
||||
0x80,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
};
|
||||
static constexpr Bitmap bitmap_icon_tune_fork{
|
||||
{16, 16},
|
||||
bitmap_icon_tune_fork_data};
|
||||
|
||||
static constexpr uint8_t bitmap_target_verify_data[] = {
|
||||
0x00,
|
||||
0xE0,
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.hpp"
|
||||
#include "ui_app_manager.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "external_app.hpp"
|
||||
|
||||
namespace ui::external_app::app_manager {
|
||||
void initialize_app(ui::NavigationView& nav) {
|
||||
nav.push<AppManagerView>();
|
||||
}
|
||||
} // namespace ui::external_app::app_manager
|
||||
|
||||
extern "C" {
|
||||
|
||||
__attribute__((section(".external_app.app_app_manager.application_information"), used)) application_information_t _application_information_app_manager = {
|
||||
/*.memory_location = */ (uint8_t*)0x00000000,
|
||||
/*.externalAppEntry = */ ui::external_app::app_manager::initialize_app,
|
||||
/*.header_version = */ CURRENT_HEADER_VERSION,
|
||||
/*.app_version = */ VERSION_MD5,
|
||||
|
||||
/*.app_name = */ "AppManager",
|
||||
/*.bitmap_data = */ {
|
||||
0xE0,
|
||||
0x00,
|
||||
0x10,
|
||||
0x01,
|
||||
0x10,
|
||||
0x01,
|
||||
0x1F,
|
||||
0x1F,
|
||||
0x01,
|
||||
0x10,
|
||||
0x01,
|
||||
0x10,
|
||||
0x01,
|
||||
0x10,
|
||||
0x01,
|
||||
0x70,
|
||||
0x01,
|
||||
0x80,
|
||||
0x01,
|
||||
0x80,
|
||||
0x01,
|
||||
0x80,
|
||||
0x01,
|
||||
0x70,
|
||||
0xE1,
|
||||
0x10,
|
||||
0x11,
|
||||
0x11,
|
||||
0x11,
|
||||
0x11,
|
||||
0x1F,
|
||||
0x1F,
|
||||
|
||||
},
|
||||
/*.icon_color = */ ui::Color::cyan().v,
|
||||
/*.menu_location = */ app_location_t::SETTINGS,
|
||||
/*.desired_menu_position = */ -1,
|
||||
|
||||
/*.m4_app_tag = portapack::spi_flash::image_tag_none */ {0, 0, 0, 0},
|
||||
/*.m4_app_offset = */ 0x00000000, // will be filled at compile time
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* copyleft spammingdramaqueen
|
||||
*
|
||||
* 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_app_manager.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "ui_external_items_menu_loader.hpp"
|
||||
|
||||
#include "file.hpp"
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
#include "string_format.hpp"
|
||||
|
||||
#include "file_reader.hpp"
|
||||
|
||||
using namespace portapack;
|
||||
|
||||
namespace ui::external_app::app_manager {
|
||||
|
||||
/* AppManagerView **************************************/
|
||||
/* | inner apps | external apps |
|
||||
* ------------------------------
|
||||
* | id | appCallName |
|
||||
* | displayName|appFriendlyName|
|
||||
*/
|
||||
AppManagerView::AppManagerView(NavigationView& nav)
|
||||
: nav_{nav} {
|
||||
add_children({&labels,
|
||||
&menu_view,
|
||||
&text_app_info,
|
||||
&button_hide_unhide,
|
||||
&button_clean_hide,
|
||||
&button_set_cancel_autostart,
|
||||
&button_clean_autostart});
|
||||
|
||||
menu_view.set_parent_rect({0, 2 * 8, screen_width, 24 * 8});
|
||||
|
||||
menu_view.on_highlight = [this]() {
|
||||
if (menu_view.highlighted_index() >= app_list_index) {
|
||||
text_app_info.set("");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string info;
|
||||
auto app_name = get_app_info(menu_view.highlighted_index(), true);
|
||||
auto app_id = get_app_info(menu_view.highlighted_index(), false);
|
||||
|
||||
info += "Hidden:";
|
||||
|
||||
if (is_blacklisted(app_name)) {
|
||||
info += "Yes ";
|
||||
} else {
|
||||
info += "No ";
|
||||
}
|
||||
|
||||
info += "Autostart:";
|
||||
if (is_autostart_app(app_id)) {
|
||||
info += "Yes";
|
||||
} else {
|
||||
info += "No";
|
||||
}
|
||||
|
||||
if (info.empty()) {
|
||||
info = "Highlight an app";
|
||||
}
|
||||
|
||||
text_app_info.set(info);
|
||||
};
|
||||
|
||||
button_hide_unhide.on_select = [this](Button&) {
|
||||
hide_unhide_app();
|
||||
refresh_list();
|
||||
};
|
||||
|
||||
button_clean_hide.on_select = [this](Button&) {
|
||||
clean_blacklist();
|
||||
refresh_list();
|
||||
};
|
||||
|
||||
button_set_cancel_autostart.on_select = [this](Button&) {
|
||||
set_unset_autostart_app();
|
||||
refresh_list();
|
||||
};
|
||||
|
||||
button_clean_autostart.on_select = [this](Button&) {
|
||||
unset_auto_start();
|
||||
refresh_list();
|
||||
};
|
||||
|
||||
refresh_list();
|
||||
}
|
||||
|
||||
void AppManagerView::refresh_list() {
|
||||
auto previous_cursor_index = menu_view.highlighted_index();
|
||||
app_list_index = 0;
|
||||
menu_view.clear();
|
||||
|
||||
size_t index = 0;
|
||||
|
||||
auto padding = [](const std::string& str) {
|
||||
return str.length() < 25 ? std::string(25 - str.length(), ' ') + '' : "";
|
||||
// that weird char is a icon in portapack's font base that looks like a switch, which i use to indicate the auto start
|
||||
};
|
||||
|
||||
for (auto& app : NavigationView::appList) {
|
||||
if (app.id == nullptr) continue;
|
||||
|
||||
app_list_index++;
|
||||
|
||||
menu_view.add_item({app.displayName + std::string(is_autostart_app(app.id) ? padding(app.displayName) : ""),
|
||||
app.iconColor,
|
||||
app.icon,
|
||||
[this, app_id = std::string(app.id)](KeyEvent) {
|
||||
button_hide_unhide.focus();
|
||||
}});
|
||||
}
|
||||
|
||||
ExternalItemsMenuLoader::load_all_external_items_callback([this, &index, &padding](ui::AppInfoConsole& app) {
|
||||
if (app.appCallName == nullptr) return;
|
||||
|
||||
app_list_index++;
|
||||
|
||||
menu_view.add_item({app.appFriendlyName + std::string(is_autostart_app(app.appCallName) ? padding(app.appFriendlyName) : ""),
|
||||
ui::Color::light_grey(),
|
||||
&bitmap_icon_sdcard,
|
||||
[this, app_id = std::string(app.appCallName)](KeyEvent) {
|
||||
button_hide_unhide.focus();
|
||||
}});
|
||||
});
|
||||
|
||||
menu_view.set_highlighted(previous_cursor_index);
|
||||
}
|
||||
|
||||
void AppManagerView::focus() {
|
||||
menu_view.focus();
|
||||
}
|
||||
|
||||
void AppManagerView::hide_app() {
|
||||
std::vector<std::string> blacklist;
|
||||
get_blacklist(blacklist);
|
||||
|
||||
blacklist.push_back(get_app_info(menu_view.highlighted_index(), true));
|
||||
write_blacklist(blacklist);
|
||||
}
|
||||
|
||||
void AppManagerView::unhide_app() {
|
||||
std::vector<std::string> blacklist;
|
||||
get_blacklist(blacklist);
|
||||
blacklist.erase(std::remove(blacklist.begin(), blacklist.end(), get_app_info(menu_view.highlighted_index(), true)), blacklist.end());
|
||||
write_blacklist(blacklist);
|
||||
}
|
||||
|
||||
void AppManagerView::hide_unhide_app() {
|
||||
if (is_blacklisted(get_app_info(menu_view.highlighted_index(), true)))
|
||||
unhide_app();
|
||||
else
|
||||
hide_app();
|
||||
}
|
||||
|
||||
void AppManagerView::get_blacklist(std::vector<std::string>& blacklist) {
|
||||
File f;
|
||||
|
||||
auto error = f.open(u"SETTINGS/blacklist");
|
||||
if (error)
|
||||
return;
|
||||
|
||||
auto reader = FileLineReader(f);
|
||||
for (const auto& line : reader) {
|
||||
if (line.length() == 0 || line[0] == '#')
|
||||
continue;
|
||||
|
||||
blacklist.push_back(trim(line));
|
||||
}
|
||||
}
|
||||
|
||||
void AppManagerView::write_blacklist(const std::vector<std::string>& blacklist) {
|
||||
File f;
|
||||
auto error = f.create(u"SETTINGS/blacklist");
|
||||
if (error)
|
||||
return;
|
||||
|
||||
for (const auto& app_name : blacklist) {
|
||||
auto line = app_name + "\n";
|
||||
f.write(line.c_str(), line.length());
|
||||
}
|
||||
}
|
||||
|
||||
void AppManagerView::clean_blacklist() {
|
||||
std::vector<std::string> blacklist = {};
|
||||
write_blacklist(blacklist);
|
||||
}
|
||||
|
||||
bool AppManagerView::is_blacklisted(const std::string& app_name) {
|
||||
std::vector<std::string> blacklist;
|
||||
get_blacklist(blacklist);
|
||||
return std::find(blacklist.begin(), blacklist.end(), app_name) != blacklist.end();
|
||||
}
|
||||
|
||||
void AppManagerView::set_auto_start() {
|
||||
auto app_index = menu_view.highlighted_index();
|
||||
if (app_index >= app_list_index) return;
|
||||
|
||||
auto id_aka_app_call_name = get_app_info(app_index, false);
|
||||
|
||||
autostart_app = id_aka_app_call_name;
|
||||
|
||||
refresh_list();
|
||||
}
|
||||
|
||||
void AppManagerView::unset_auto_start() {
|
||||
autostart_app = "";
|
||||
refresh_list();
|
||||
}
|
||||
|
||||
void AppManagerView::set_unset_autostart_app() {
|
||||
auto app_index = menu_view.highlighted_index();
|
||||
if (app_index >= app_list_index) return;
|
||||
|
||||
auto id_aka_friendly_name = get_app_info(app_index, false);
|
||||
|
||||
if (is_autostart_app(id_aka_friendly_name))
|
||||
unset_auto_start();
|
||||
else
|
||||
set_auto_start();
|
||||
}
|
||||
|
||||
bool AppManagerView::is_autostart_app(const char* id_aka_friendly_name) {
|
||||
return autostart_app == std::string(id_aka_friendly_name);
|
||||
}
|
||||
|
||||
bool AppManagerView::is_autostart_app(const std::string& id_aka_friendly_name) {
|
||||
return autostart_app == id_aka_friendly_name;
|
||||
}
|
||||
|
||||
std::string AppManagerView::get_app_info(uint16_t index, bool is_display_name) {
|
||||
size_t current_index = 0;
|
||||
std::string result;
|
||||
|
||||
for (auto& app : NavigationView::appList) {
|
||||
if (app.id == nullptr) continue;
|
||||
if (current_index == index) {
|
||||
return is_display_name ? std::string(app.displayName) : std::string(app.id);
|
||||
}
|
||||
current_index++;
|
||||
}
|
||||
|
||||
ExternalItemsMenuLoader::load_all_external_items_callback([¤t_index, &index, &result, &is_display_name](ui::AppInfoConsole& app) {
|
||||
if (app.appCallName == nullptr) return;
|
||||
if (current_index == index) {
|
||||
result = is_display_name ? app.appFriendlyName : app.appCallName;
|
||||
}
|
||||
current_index++;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace ui::external_app::app_manager
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* copyleft spammingdramaqueen
|
||||
*
|
||||
* 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_APP_MANAGER_H__
|
||||
#define __UI_APP_MANAGER_H__
|
||||
|
||||
#include "ui_navigation.hpp"
|
||||
|
||||
namespace ui::external_app::app_manager {
|
||||
|
||||
class AppManagerView : public View {
|
||||
public:
|
||||
AppManagerView(NavigationView& nav);
|
||||
std::string title() const override { return "AppMan"; };
|
||||
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
std::string autostart_app{""};
|
||||
SettingsStore nav_setting{
|
||||
"nav"sv,
|
||||
{{"autostart_app"sv, &autostart_app}}};
|
||||
|
||||
void focus() override;
|
||||
void refresh_list();
|
||||
uint16_t app_list_index{0};
|
||||
|
||||
Labels labels{
|
||||
{{0 * 8, 0 * 16}, "App list:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
MenuView menu_view{};
|
||||
|
||||
Text text_app_info{
|
||||
{0, 27 * 8, screen_width, 16},
|
||||
"Highlight an app"};
|
||||
|
||||
Button button_hide_unhide{
|
||||
{0, 29 * 8, screen_width / 2 - 1, 32},
|
||||
"Hide/Show"};
|
||||
|
||||
Button button_clean_hide{
|
||||
{screen_width / 2 + 2, 29 * 8, screen_width / 2 - 2, 32},
|
||||
"Clean Hidden"};
|
||||
|
||||
Button button_set_cancel_autostart{
|
||||
{0, screen_height - 32 - 16, screen_width / 2 - 1, 32},
|
||||
"Set Autostart"};
|
||||
|
||||
Button button_clean_autostart{
|
||||
{screen_width / 2 + 2, screen_height - 32 - 16, screen_width / 2 - 2, 32},
|
||||
"Del Autostart"};
|
||||
|
||||
std::string get_app_info(uint16_t index, bool is_display_name);
|
||||
void get_blacklist(std::vector<std::string>& blacklist);
|
||||
void write_blacklist(const std::vector<std::string>& blacklist);
|
||||
bool is_blacklisted(const std::string& app_display_name);
|
||||
void hide_app();
|
||||
void unhide_app();
|
||||
void hide_unhide_app();
|
||||
void clean_blacklist();
|
||||
bool is_autostart_app(const std::string& display_name);
|
||||
void set_auto_start();
|
||||
void unset_auto_start();
|
||||
void set_unset_autostart_app();
|
||||
bool is_autostart_app(const char* id_aka_app_call_name);
|
||||
};
|
||||
|
||||
} // namespace ui::external_app::app_manager
|
||||
|
||||
#endif // __UI_APP_MANAGER_H__
|
||||
+6
-1
@@ -146,6 +146,10 @@ set(EXTCPPSRC
|
||||
#metronome
|
||||
external/metronome/main.cpp
|
||||
external/metronome/ui_metronome.cpp
|
||||
|
||||
#app_manager
|
||||
external/app_manager/main.cpp
|
||||
external/app_manager/ui_app_manager.cpp
|
||||
)
|
||||
|
||||
set(EXTAPPLIST
|
||||
@@ -184,4 +188,5 @@ set(EXTAPPLIST
|
||||
fmradio
|
||||
tuner
|
||||
metronome
|
||||
)
|
||||
app_manager
|
||||
)
|
||||
+7
@@ -58,6 +58,7 @@ MEMORY
|
||||
ram_external_app_fmradio(rwx) : org = 0xADD10000, len = 32k
|
||||
ram_external_app_tuner(rwx) : org = 0xADD20000, len = 32k
|
||||
ram_external_app_metronome(rwx) : org = 0xADD30000, len = 32k
|
||||
ram_external_app_app_manager(rwx) : org = 0xADD40000, len = 32k
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
@@ -272,4 +273,10 @@ SECTIONS
|
||||
KEEP(*(.external_app.app_metronome.application_information));
|
||||
*(*ui*external_app*metronome*);
|
||||
} > ram_external_app_metronome
|
||||
|
||||
.external_app_app_manager : ALIGN(4) SUBALIGN(4)
|
||||
{
|
||||
KEEP(*(.external_app.app_app_manager.application_information));
|
||||
*(*ui*external_app*app_manager*);
|
||||
} > ram_external_app_app_manager
|
||||
}
|
||||
|
||||
@@ -38,17 +38,31 @@ BtnGridView::BtnGridView(
|
||||
set_parent_rect(new_parent_rect);
|
||||
set_focusable(true);
|
||||
|
||||
signal_token_tick_second = rtc_time::signal_tick_second += [this]() {
|
||||
this->on_tick_second();
|
||||
button_pgup.set_focusable(false);
|
||||
button_pgup.on_select = [this](Button&) {
|
||||
if (arrow_up_enabled) {
|
||||
if (((int64_t)highlighted_item - displayed_max) > 0)
|
||||
set_highlighted(highlighted_item - displayed_max);
|
||||
else
|
||||
set_highlighted(0);
|
||||
}
|
||||
};
|
||||
|
||||
add_child(&arrow_more);
|
||||
arrow_more.set_focusable(false);
|
||||
arrow_more.set_foreground(Theme::getInstance()->bg_darkest->background);
|
||||
button_pgdown.set_focusable(false);
|
||||
button_pgdown.on_select = [this](Button&) {
|
||||
if (arrow_down_enabled) {
|
||||
set_highlighted(highlighted_item + displayed_max);
|
||||
}
|
||||
};
|
||||
|
||||
button_pgup.set_style(Theme::getInstance()->bg_darkest_small);
|
||||
button_pgdown.set_style(Theme::getInstance()->bg_darkest_small);
|
||||
|
||||
add_child(&button_pgup);
|
||||
add_child(&button_pgdown);
|
||||
}
|
||||
|
||||
BtnGridView::~BtnGridView() {
|
||||
rtc_time::signal_tick_second -= signal_token_tick_second;
|
||||
}
|
||||
|
||||
void BtnGridView::set_max_rows(int rows) {
|
||||
@@ -63,7 +77,10 @@ void BtnGridView::set_parent_rect(const Rect new_parent_rect) {
|
||||
View::set_parent_rect(new_parent_rect);
|
||||
|
||||
displayed_max = (parent_rect().size().height() / button_h);
|
||||
arrow_more.set_parent_rect({228, (Coord)(displayed_max * button_h), 8, 8});
|
||||
|
||||
button_pgup.set_parent_rect({0, (Coord)(displayed_max * button_h), 120, 16});
|
||||
button_pgdown.set_parent_rect({120, (Coord)(displayed_max * button_h), 120, 16});
|
||||
|
||||
displayed_max *= rows_;
|
||||
|
||||
// Delete any existing buttons.
|
||||
@@ -84,28 +101,40 @@ void BtnGridView::set_parent_rect(const Rect new_parent_rect) {
|
||||
|
||||
menu_item_views.push_back(std::move(item));
|
||||
}
|
||||
|
||||
update_items();
|
||||
}
|
||||
|
||||
void BtnGridView::set_arrow_enabled(bool enabled) {
|
||||
void BtnGridView::set_arrow_up_enabled(bool enabled) {
|
||||
if (!show_arrows)
|
||||
return;
|
||||
if (enabled) {
|
||||
add_child(&arrow_more);
|
||||
} else {
|
||||
remove_child(&arrow_more);
|
||||
if (!arrow_up_enabled) {
|
||||
arrow_up_enabled = true;
|
||||
button_pgup.set_text("PAGE UP");
|
||||
}
|
||||
} else if (!enabled) {
|
||||
if (arrow_up_enabled) {
|
||||
arrow_up_enabled = false;
|
||||
button_pgup.set_text(" ");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void BtnGridView::on_tick_second() {
|
||||
if (more && blink)
|
||||
arrow_more.set_foreground(Theme::getInstance()->bg_darkest->foreground);
|
||||
else
|
||||
arrow_more.set_foreground(Theme::getInstance()->bg_darkest->background);
|
||||
|
||||
blink = !blink;
|
||||
|
||||
arrow_more.set_dirty();
|
||||
}
|
||||
void BtnGridView::set_arrow_down_enabled(bool enabled) {
|
||||
if (!show_arrows)
|
||||
return;
|
||||
if (enabled) {
|
||||
if (!arrow_down_enabled) {
|
||||
arrow_down_enabled = true;
|
||||
button_pgdown.set_text("PAGE DOWN");
|
||||
}
|
||||
} else if (!enabled) {
|
||||
if (arrow_down_enabled) {
|
||||
arrow_down_enabled = false;
|
||||
button_pgdown.set_text(" ");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void BtnGridView::clear() {
|
||||
// clear vector and release memory, not using swap since it's causing capture to glitch/fault
|
||||
@@ -153,15 +182,23 @@ void BtnGridView::insert_item(const GridItem& new_item, size_t position, bool in
|
||||
}
|
||||
}
|
||||
|
||||
void BtnGridView::show_hide_arrows() {
|
||||
if (highlighted_item == 0) {
|
||||
set_arrow_up_enabled(false);
|
||||
} else {
|
||||
set_arrow_up_enabled(true);
|
||||
}
|
||||
if (highlighted_item == (menu_items.size() - 1)) {
|
||||
set_arrow_down_enabled(false);
|
||||
} else {
|
||||
set_arrow_down_enabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void BtnGridView::update_items() {
|
||||
size_t i = 0;
|
||||
Color bg_color = portapack::persistent_memory::menu_color();
|
||||
|
||||
if ((menu_items.size()) > (displayed_max + offset)) {
|
||||
more = true;
|
||||
blink = true;
|
||||
} else
|
||||
more = false;
|
||||
Color bg_color = portapack::persistent_memory::menu_color();
|
||||
|
||||
for (auto& item : menu_item_views) {
|
||||
if ((i + offset) >= menu_items.size()) {
|
||||
@@ -189,14 +226,19 @@ NewButton* BtnGridView::item_view(size_t index) const {
|
||||
return menu_item_views[index].get();
|
||||
}
|
||||
|
||||
void BtnGridView::show_arrows_enabled(bool enabled) {
|
||||
show_arrows = enabled;
|
||||
}
|
||||
|
||||
bool BtnGridView::set_highlighted(int32_t new_value) {
|
||||
int32_t item_count = (int32_t)menu_items.size();
|
||||
|
||||
if (new_value < 0)
|
||||
return false;
|
||||
|
||||
if (new_value >= item_count)
|
||||
if (new_value >= item_count) {
|
||||
new_value = item_count - 1;
|
||||
}
|
||||
|
||||
if (((uint32_t)new_value > offset) && ((new_value - offset) >= displayed_max)) {
|
||||
// Shift BtnGridView up
|
||||
@@ -222,6 +264,8 @@ bool BtnGridView::set_highlighted(int32_t new_value) {
|
||||
if (visible())
|
||||
item_view(highlighted_item - offset)->focus();
|
||||
|
||||
show_hide_arrows();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -235,21 +279,22 @@ void BtnGridView::on_focus() {
|
||||
|
||||
void BtnGridView::on_blur() {
|
||||
#if 0
|
||||
if (!keep_highlight)
|
||||
item_view(highlighted_item - offset)->unhighlight();
|
||||
if (!keep_highlight)
|
||||
item_view(highlighted_item - offset)->unhighlight();
|
||||
#endif
|
||||
}
|
||||
|
||||
void BtnGridView::on_show() {
|
||||
on_populate();
|
||||
|
||||
View::on_show();
|
||||
set_highlighted(highlighted_item);
|
||||
}
|
||||
|
||||
void BtnGridView::on_hide() {
|
||||
View::on_hide();
|
||||
|
||||
clear();
|
||||
set_arrow_up_enabled(false);
|
||||
set_arrow_down_enabled(false);
|
||||
}
|
||||
|
||||
bool BtnGridView::on_key(const KeyEvent key) {
|
||||
|
||||
@@ -68,11 +68,18 @@ class BtnGridView : public View {
|
||||
|
||||
NewButton* item_view(size_t index) const;
|
||||
|
||||
bool show_arrows{true}; // flag used to hide arrows in main menu
|
||||
void show_arrows_enabled(bool enabled);
|
||||
|
||||
bool set_highlighted(int32_t new_value);
|
||||
uint32_t highlighted_index();
|
||||
|
||||
void set_parent_rect(const Rect new_parent_rect) override;
|
||||
void set_arrow_enabled(bool enabled);
|
||||
bool arrow_up_enabled{false};
|
||||
bool arrow_down_enabled{false};
|
||||
void set_arrow_up_enabled(bool enabled);
|
||||
void set_arrow_down_enabled(bool enabled);
|
||||
void show_hide_arrows();
|
||||
void on_focus() override;
|
||||
void on_blur() override;
|
||||
void on_show() override;
|
||||
@@ -88,24 +95,21 @@ class BtnGridView : public View {
|
||||
|
||||
private:
|
||||
int rows_{3};
|
||||
void on_tick_second();
|
||||
|
||||
bool keep_highlight{false};
|
||||
|
||||
SignalToken signal_token_tick_second{};
|
||||
std::vector<GridItem> menu_items{};
|
||||
std::vector<std::unique_ptr<NewButton>> menu_item_views{};
|
||||
|
||||
Image arrow_more{
|
||||
{228, 320 - 8, 8, 8},
|
||||
&bitmap_more,
|
||||
Theme::getInstance()->bg_darkest->foreground,
|
||||
Theme::getInstance()->bg_darkest->background};
|
||||
Button button_pgup{
|
||||
{0, 324, 120, 16},
|
||||
" "};
|
||||
|
||||
Button button_pgdown{
|
||||
{121, 324, 119, 16},
|
||||
" "};
|
||||
|
||||
int button_w = 240 / rows_;
|
||||
static constexpr int button_h = 48;
|
||||
bool blink = false;
|
||||
bool more = false;
|
||||
size_t displayed_max{0};
|
||||
size_t highlighted_item{0};
|
||||
size_t offset{0};
|
||||
|
||||
@@ -760,7 +760,7 @@ void NavigationView::handle_autostart() {
|
||||
|
||||
/* Helpers **************************************************************/
|
||||
|
||||
static void add_apps(NavigationView& nav, BtnGridView& grid, app_location_t loc) {
|
||||
void add_apps(NavigationView& nav, BtnGridView& grid, app_location_t loc) {
|
||||
for (auto& app : NavigationView::appList) {
|
||||
if (app.menuLocation == loc) {
|
||||
grid.add_item({app.displayName, app.iconColor, app.icon,
|
||||
@@ -825,9 +825,7 @@ void ReceiversMenuView::on_populate() {
|
||||
if (return_icon) {
|
||||
add_item({"..", Theme::getInstance()->fg_light->foreground, &bitmap_icon_previous, [this]() { nav_.pop(); }});
|
||||
}
|
||||
|
||||
add_apps(nav_, *this, RX);
|
||||
|
||||
add_external_items(nav_, app_location_t::RX, *this, return_icon ? 1 : 0);
|
||||
}
|
||||
|
||||
@@ -841,9 +839,7 @@ void TransmittersMenuView::on_populate() {
|
||||
if (return_icon) {
|
||||
add_items({{"..", Theme::getInstance()->fg_light->foreground, &bitmap_icon_previous, [this]() { nav_.pop(); }}});
|
||||
}
|
||||
|
||||
add_apps(nav_, *this, TX);
|
||||
|
||||
add_external_items(nav_, app_location_t::TX, *this, return_icon ? 1 : 0);
|
||||
}
|
||||
|
||||
@@ -859,9 +855,7 @@ void UtilitiesMenuView::on_populate() {
|
||||
if (return_icon) {
|
||||
add_items({{"..", Theme::getInstance()->fg_light->foreground, &bitmap_icon_previous, [this]() { nav_.pop(); }}});
|
||||
}
|
||||
|
||||
add_apps(nav_, *this, UTILITIES);
|
||||
|
||||
add_external_items(nav_, app_location_t::UTILITIES, *this, return_icon ? 1 : 0);
|
||||
}
|
||||
|
||||
@@ -882,7 +876,7 @@ void SystemMenuView::hackrf_mode(NavigationView& nav) {
|
||||
SystemMenuView::SystemMenuView(NavigationView& nav)
|
||||
: nav_(nav) {
|
||||
set_max_rows(2); // allow wider buttons
|
||||
set_arrow_enabled(false);
|
||||
show_arrows_enabled(false);
|
||||
}
|
||||
|
||||
void SystemMenuView::on_populate() {
|
||||
|
||||
@@ -59,6 +59,10 @@ using namespace sd_card;
|
||||
|
||||
namespace ui {
|
||||
|
||||
void add_apps(NavigationView& nav, BtnGridView& grid, app_location_t loc);
|
||||
void add_external_items(NavigationView& nav, app_location_t location, BtnGridView& grid, uint8_t error_tile_pos);
|
||||
bool verify_sdcard_format();
|
||||
|
||||
enum modal_t {
|
||||
INFO = 0,
|
||||
YESNO,
|
||||
|
||||
@@ -170,6 +170,81 @@ temp_humid Packet::get_temp_humid() const {
|
||||
result.humid = 0;
|
||||
result.temp = 0;
|
||||
|
||||
if (type_ == Type::Meteomodem_M10) {
|
||||
// https://github.com/projecthorus/radiosonde_auto_rx/blob/master/demod/mod/m10mod.c
|
||||
// temp:
|
||||
uint16_t ADC_Ti_raw = (reader_bi_m.read(0x49 * 8, 8) << 8) | reader_bi_m.read(0x48 * 8, 8) << 8; // int.temp.diode, ref: 4095->1.5V
|
||||
if (ADC_Ti_raw != 0) {
|
||||
// internal
|
||||
float vti, ti;
|
||||
// INCH1A (temp.diode), slau144
|
||||
vti = ADC_Ti_raw / 4095.0 * 1.5; // V_REF+ = 1.5V, no calibration
|
||||
ti = (vti - 0.986) / 0.00355; // 0.986/0.00355=277.75, 1.5/4095/0.00355=0.1032
|
||||
result.temp = ti;
|
||||
}
|
||||
// NTC - Thermistor Shibaura PB5 - 41E
|
||||
float p0 = 1.07303516e-03,
|
||||
p1 = 2.41296733e-04,
|
||||
p2 = 2.26744154e-06,
|
||||
p3 = 6.52855181e-08;
|
||||
// T/K = 1/( p0 + p1*ln(R) + p2*ln(R)^2 + p3*ln(R)^3 )
|
||||
|
||||
// range/scale 0, 1, 2: // M10-pcb
|
||||
float Rs_T[3] = {12.1e3, 36.5e3, 475.0e3}; // bias/series
|
||||
float Rp[3] = {1e20, 330.0e3, 2000.0e3}; // parallel, Rp[0]=inf
|
||||
|
||||
uint8_t scT; // {0,1,2}, range/scale voltage divider
|
||||
uint16_t ADC_RT; // ADC12 P6.7(A7) , adr_0377h,adr_0376h
|
||||
// uint16_t Tcal[2]; // adr_1000h[scT*4]
|
||||
|
||||
float adc_max = 4095.0; // ADC12
|
||||
float x, R;
|
||||
float T = 0; // T/Kelvin
|
||||
|
||||
scT = reader_bi_m.read(0x3E * 8, 8); // adr_0455h
|
||||
ADC_RT = (reader_bi_m.read(0x40 * 8, 8) << 8) | reader_bi_m.read(0x3F * 8, 8);
|
||||
if (ADC_RT != 0) {
|
||||
ADC_RT -= 0xA000;
|
||||
// Tcal[0] = (reader_bi_m.read(0x42 * 8, 8) << 8) | reader_bi_m.read(0x41 * 8, 8);
|
||||
// Tcal[1] = (reader_bi_m.read(0x44 * 8, 8) << 8) | reader_bi_m.read(0x43 * 8, 8);
|
||||
|
||||
x = (adc_max - ADC_RT) / ADC_RT; // (Vcc-Vout)/Vout
|
||||
if (scT < 3)
|
||||
R = Rs_T[scT] / (x - Rs_T[scT] / Rp[scT]);
|
||||
else
|
||||
R = -1;
|
||||
|
||||
if (R > 0) T = 1 / (p0 + p1 * log(R) + p2 * log(R) * log(R) + p3 * log(R) * log(R) * log(R));
|
||||
result.temp = T - 273.15;
|
||||
}
|
||||
|
||||
// humidity:
|
||||
// get count rh:
|
||||
float TBCCR1 = (reader_bi_m.read(0x35 * 8, 8) | (reader_bi_m.read(0x36 * 8, 8) << 8) | (reader_bi_m.read(0x37 * 8, 8) << 16)) / 1000.0;
|
||||
// get count 55:
|
||||
float TBCREF = (reader_bi_m.read(0x32 * 8, 8) | (reader_bi_m.read(0x33 * 8, 8) << 8) | (reader_bi_m.read(0x34 * 8, 8) << 16)) / 1000.0;
|
||||
if (TBCREF != 0) {
|
||||
float cRHc55 = TBCCR1 / TBCREF; //;get_count_RH(gpx) / get_count_55(gpx); // CalRef 55%RH , T=20C ?
|
||||
// get_Tntc2: --unused.
|
||||
// float Rs = 22.1e3; // P5.6=Vcc
|
||||
// float R25 = 2.2e3;
|
||||
// float b = 3650.0; // B/Kelvin
|
||||
// float T25 = 25.0 + 273.15; // T0=25C, R0=R25=5k
|
||||
// -> Steinhart-Hart coefficients (polyfit):
|
||||
|
||||
// cRHc55_RH:
|
||||
// float TH = get_Tntc2(gpx); --unused
|
||||
float rh = (cRHc55 - 0.8955) / 0.002; // UPSI linear transfer function
|
||||
// temperature compensation
|
||||
float T0 = 0.0, T1 = -30.0; // T/C
|
||||
if (result.temp < T0) rh += T0 - result.temp / 5.5; // approx/empirical
|
||||
if (result.temp < T1) rh *= 1.0 + (T1 - result.temp) / 75.0; // approx/empirical
|
||||
if (rh < 0.0) rh = 0.0;
|
||||
if (rh > 100.0) rh = 100.0;
|
||||
result.humid = rh;
|
||||
}
|
||||
}
|
||||
|
||||
if (type_ == Type::Vaisala_RS41_SG && crc_ok_RS41()) // Only process if packet is healthy
|
||||
{
|
||||
// memset(calfrchk, 0, 51); // is this necessary ? only if the sondeID changes (new sonde)
|
||||
|
||||
@@ -71,7 +71,8 @@ enum app_location_t : uint32_t {
|
||||
RX,
|
||||
TX,
|
||||
DEBUG,
|
||||
HOME
|
||||
HOME,
|
||||
SETTINGS
|
||||
};
|
||||
|
||||
struct standalone_application_information_t {
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# Copyright (C) 2024 u-foka
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
set -e # exit immediatelly on any failure
|
||||
|
||||
build_make() {
|
||||
|
||||
@@ -0,0 +1,561 @@
|
||||
M48
|
||||
METRIC,LZ,000.000
|
||||
;FILE_FORMAT=3:3
|
||||
;TYPE=PLATED
|
||||
;Layer: PTH_Through
|
||||
;EasyEDA v6.5.46, 2025-01-01 16:01:39
|
||||
;1acd7fc2553046b79c71bda98b4923fc,10
|
||||
;Gerber Generator version 0.2
|
||||
;Holesize 1 = 0.300 mm
|
||||
T01C0.300
|
||||
;Holesize 2 = 0.400 mm
|
||||
T02C0.400
|
||||
;Holesize 3 = 0.500 mm
|
||||
T03C0.500
|
||||
;Holesize 4 = 0.700 mm
|
||||
T04C0.700
|
||||
;Holesize 5 = 0.712 mm
|
||||
T05C0.712
|
||||
;Holesize 6 = 0.800 mm
|
||||
T06C0.800
|
||||
;Holesize 7 = 1.000 mm
|
||||
T07C1.000
|
||||
;Holesize 8 = 1.450 mm
|
||||
T08C1.450
|
||||
;Holesize 9 = 1.501 mm
|
||||
T09C1.501
|
||||
;Holesize 10 = 1.600 mm
|
||||
T10C1.600
|
||||
;Holesize 11 = 3.200 mm
|
||||
T11C3.200
|
||||
;Holesize 12 = 3.300 mm
|
||||
T12C3.300
|
||||
;Holesize 13 = 4.000 mm
|
||||
T13C4.000
|
||||
%
|
||||
G05
|
||||
G90
|
||||
T01
|
||||
X033262Y064570
|
||||
T02
|
||||
X033746Y068890
|
||||
X033746Y067630
|
||||
X032496Y068890
|
||||
X032496Y067640
|
||||
X000503Y006140
|
||||
X002078Y005493
|
||||
X-001046Y005505
|
||||
X-001757Y003880
|
||||
X002700Y003931
|
||||
X-001046Y002407
|
||||
X000503Y001746
|
||||
X002065Y002394
|
||||
X112492Y006204
|
||||
X114067Y005556
|
||||
X110942Y005569
|
||||
X110231Y003943
|
||||
X114689Y003994
|
||||
X110942Y002470
|
||||
X112492Y001810
|
||||
X114054Y002457
|
||||
X112454Y073311
|
||||
X114028Y072663
|
||||
X110904Y072676
|
||||
X110193Y071050
|
||||
X114651Y071101
|
||||
X110904Y069577
|
||||
X112454Y068917
|
||||
X114016Y069564
|
||||
X000363Y073082
|
||||
X001938Y072434
|
||||
X-001186Y072447
|
||||
X-001897Y070822
|
||||
X002561Y070872
|
||||
X-001186Y069348
|
||||
X000363Y068688
|
||||
X001926Y069336
|
||||
X043182Y073180
|
||||
X057290Y063879
|
||||
X055639Y063879
|
||||
X054115Y063879
|
||||
X023541Y056040
|
||||
X-000716Y008989
|
||||
X040694Y054339
|
||||
X039184Y054339
|
||||
X037684Y054339
|
||||
X036194Y054339
|
||||
X034684Y054339
|
||||
X033184Y054339
|
||||
X031694Y054339
|
||||
X030184Y054339
|
||||
X028684Y054339
|
||||
X040694Y057659
|
||||
X039184Y057659
|
||||
X037684Y057659
|
||||
X036194Y057659
|
||||
X034684Y057659
|
||||
X033184Y057659
|
||||
X031694Y057659
|
||||
X030184Y057659
|
||||
X028684Y057659
|
||||
X027194Y057659
|
||||
X025684Y057659
|
||||
X024184Y057659
|
||||
X-002604Y045352
|
||||
X003264Y054799
|
||||
X000826Y052072
|
||||
X001374Y051759
|
||||
X001394Y052349
|
||||
X001394Y052349
|
||||
X003674Y050949
|
||||
X004474Y050949
|
||||
X004474Y051819
|
||||
X003674Y051819
|
||||
X000794Y053369
|
||||
X000804Y054169
|
||||
X115384Y012549
|
||||
X115384Y014149
|
||||
X115384Y015569
|
||||
X091384Y022329
|
||||
X092884Y022329
|
||||
X094384Y022329
|
||||
X095884Y022329
|
||||
X097384Y022329
|
||||
X082084Y026189
|
||||
X082084Y027159
|
||||
X086521Y016440
|
||||
X076134Y058229
|
||||
X069384Y058229
|
||||
X068854Y056279
|
||||
X059895Y043988
|
||||
X081972Y056970
|
||||
X070944Y056949
|
||||
X060837Y043271
|
||||
X078771Y056139
|
||||
X071254Y056139
|
||||
X065404Y066959
|
||||
X022844Y069129
|
||||
X022854Y070029
|
||||
X024785Y069289
|
||||
X041284Y063829
|
||||
X041284Y064749
|
||||
X017594Y069039
|
||||
X016784Y069039
|
||||
X021954Y060729
|
||||
X022604Y061599
|
||||
X033484Y062559
|
||||
X032884Y063169
|
||||
X022684Y048469
|
||||
X022684Y049489
|
||||
X022684Y050469
|
||||
X019781Y050798
|
||||
X020551Y051588
|
||||
X019071Y049998
|
||||
X053284Y073469
|
||||
X051784Y073469
|
||||
X054784Y073469
|
||||
X044284Y073469
|
||||
X056284Y073469
|
||||
X050284Y073469
|
||||
X048784Y073469
|
||||
X057784Y073469
|
||||
X021882Y074350
|
||||
X023382Y074350
|
||||
X064450Y066340
|
||||
X047962Y071820
|
||||
X028462Y067260
|
||||
X029172Y066460
|
||||
X033902Y071829
|
||||
X039922Y069890
|
||||
X039929Y061954
|
||||
X047970Y065068
|
||||
X023182Y068229
|
||||
X009236Y057012
|
||||
X022652Y071790
|
||||
X009622Y065100
|
||||
X035742Y072490
|
||||
X009572Y059860
|
||||
X043912Y060994
|
||||
X045552Y067320
|
||||
X046412Y066020
|
||||
X047212Y041900
|
||||
X047212Y068570
|
||||
X044692Y069849
|
||||
X040972Y069849
|
||||
X040992Y067830
|
||||
X025171Y026068
|
||||
X031191Y031448
|
||||
X030271Y030328
|
||||
X024261Y025278
|
||||
X033391Y025758
|
||||
X033401Y024428
|
||||
X031911Y025798
|
||||
X033391Y027298
|
||||
X032081Y032348
|
||||
X049684Y011368
|
||||
X048184Y011358
|
||||
X046684Y011348
|
||||
X045184Y011358
|
||||
X043684Y011348
|
||||
X115384Y016969
|
||||
X115384Y018169
|
||||
X115364Y019329
|
||||
X115384Y020659
|
||||
X115214Y008229
|
||||
X115204Y006729
|
||||
X109384Y001239
|
||||
X107884Y001249
|
||||
X106384Y001259
|
||||
X104884Y001249
|
||||
X103384Y001249
|
||||
X101884Y001239
|
||||
X100384Y001229
|
||||
X098884Y001239
|
||||
X097384Y001239
|
||||
X095884Y001229
|
||||
X094384Y001229
|
||||
X092884Y001229
|
||||
X091384Y001229
|
||||
X089884Y001229
|
||||
X088384Y001229
|
||||
X086884Y001219
|
||||
X000785Y007999
|
||||
X002284Y006879
|
||||
X003484Y005729
|
||||
X-002596Y008829
|
||||
X-002616Y010329
|
||||
X-002616Y011829
|
||||
X-002616Y013329
|
||||
X-002616Y014829
|
||||
X-002616Y016329
|
||||
X-000816Y065529
|
||||
X-002316Y065529
|
||||
X076084Y073484
|
||||
X073272Y073460
|
||||
X071284Y073475
|
||||
X068284Y073484
|
||||
X074584Y020369
|
||||
X074584Y021658
|
||||
X074584Y022719
|
||||
X081484Y044478
|
||||
X074365Y029879
|
||||
X072535Y029828
|
||||
X070635Y029808
|
||||
X077555Y039659
|
||||
X069335Y039858
|
||||
X074145Y039309
|
||||
X074145Y040279
|
||||
X074345Y033929
|
||||
X074335Y035788
|
||||
X072555Y035769
|
||||
X072545Y033948
|
||||
X070655Y033938
|
||||
X070685Y035769
|
||||
X098884Y022329
|
||||
X100384Y022329
|
||||
X101884Y022329
|
||||
X103384Y022329
|
||||
X104884Y022329
|
||||
X066784Y020168
|
||||
X066784Y021048
|
||||
X066784Y021959
|
||||
X066784Y022808
|
||||
X072121Y024198
|
||||
X072121Y025078
|
||||
X083535Y045249
|
||||
X079544Y049619
|
||||
X115384Y022329
|
||||
X113884Y022329
|
||||
X112384Y022329
|
||||
X110884Y022329
|
||||
X109384Y022329
|
||||
X107884Y022329
|
||||
X106384Y022329
|
||||
X001584Y065529
|
||||
X003284Y065529
|
||||
X004984Y065529
|
||||
X006384Y067929
|
||||
X006384Y066729
|
||||
X006384Y065529
|
||||
X-002316Y067029
|
||||
X-000816Y067029
|
||||
X001385Y067429
|
||||
X003184Y068429
|
||||
X004184Y070029
|
||||
X004385Y071629
|
||||
X-002616Y032829
|
||||
X-002616Y031329
|
||||
X-002616Y029829
|
||||
X-002616Y028329
|
||||
X-002616Y026829
|
||||
X-002616Y025329
|
||||
X-002616Y023829
|
||||
X-002616Y022329
|
||||
X-002616Y020829
|
||||
X-002616Y019329
|
||||
X-002616Y017829
|
||||
X-002516Y007529
|
||||
X-002516Y006229
|
||||
X004684Y004629
|
||||
X005584Y003629
|
||||
X006484Y002729
|
||||
X007385Y001829
|
||||
X002884Y000829
|
||||
X004385Y000829
|
||||
X005884Y000829
|
||||
X007385Y000829
|
||||
X008884Y000829
|
||||
X010385Y000829
|
||||
X011884Y000829
|
||||
X013385Y000829
|
||||
X014884Y000829
|
||||
X016384Y000829
|
||||
X017884Y000829
|
||||
X019384Y000829
|
||||
X020884Y000829
|
||||
X022384Y000829
|
||||
X023884Y000829
|
||||
X025384Y000829
|
||||
X026884Y000829
|
||||
X028384Y000829
|
||||
X029884Y000829
|
||||
X031384Y000829
|
||||
X032884Y000829
|
||||
X034384Y000829
|
||||
X035884Y000829
|
||||
X037384Y000829
|
||||
X038884Y000829
|
||||
X040384Y000829
|
||||
X041884Y000829
|
||||
X043384Y000829
|
||||
X044884Y000829
|
||||
X046384Y000829
|
||||
X047884Y000829
|
||||
X049384Y000829
|
||||
X050884Y000829
|
||||
X052384Y000829
|
||||
X053884Y000829
|
||||
X055384Y000829
|
||||
X056884Y000829
|
||||
X058384Y000829
|
||||
X059884Y000829
|
||||
X061384Y000829
|
||||
X062884Y000829
|
||||
X064384Y000829
|
||||
X065884Y000829
|
||||
X067384Y000829
|
||||
X068891Y000829
|
||||
X070391Y000829
|
||||
X071891Y000829
|
||||
X073391Y000829
|
||||
X074891Y000829
|
||||
X076431Y000828
|
||||
X078002Y000840
|
||||
X079384Y001229
|
||||
X080884Y001229
|
||||
X082384Y001229
|
||||
X083884Y001229
|
||||
X085384Y001229
|
||||
X004382Y074350
|
||||
X005882Y074350
|
||||
X007382Y074350
|
||||
X008882Y074350
|
||||
X014382Y074350
|
||||
X015882Y074350
|
||||
X017382Y074350
|
||||
X020382Y074350
|
||||
X018882Y074350
|
||||
X024882Y074350
|
||||
X026462Y074330
|
||||
X027922Y074320
|
||||
X029162Y074340
|
||||
X030882Y074350
|
||||
X032382Y074350
|
||||
X033882Y074350
|
||||
X035382Y074350
|
||||
X036882Y074350
|
||||
X038382Y074350
|
||||
X039882Y074350
|
||||
X041382Y074350
|
||||
X045784Y073469
|
||||
X047284Y073469
|
||||
X059284Y073469
|
||||
X060784Y073475
|
||||
X062284Y073475
|
||||
X063784Y073475
|
||||
X065284Y073475
|
||||
X066784Y073475
|
||||
X078602Y073510
|
||||
X081184Y073475
|
||||
X082684Y073475
|
||||
X084484Y073475
|
||||
X085984Y073475
|
||||
X087484Y073475
|
||||
X088984Y073475
|
||||
X090484Y073475
|
||||
X091984Y073475
|
||||
X093484Y073475
|
||||
X094984Y073475
|
||||
X096484Y073475
|
||||
X097984Y073475
|
||||
X099484Y073475
|
||||
X100984Y073475
|
||||
X102484Y073475
|
||||
X103984Y073475
|
||||
X105484Y073475
|
||||
X106984Y073475
|
||||
X108484Y073475
|
||||
X027601Y019268
|
||||
X023813Y020081
|
||||
X028890Y022249
|
||||
X026321Y021528
|
||||
X017452Y004818
|
||||
X085852Y017350
|
||||
X077648Y008828
|
||||
X034983Y005683
|
||||
X076673Y015173
|
||||
X033983Y015173
|
||||
X068663Y007623
|
||||
X068663Y004453
|
||||
X063595Y015808
|
||||
X036533Y015813
|
||||
X063015Y016538
|
||||
X031443Y015303
|
||||
X062135Y007909
|
||||
X032333Y005783
|
||||
X061270Y008433
|
||||
X014703Y005623
|
||||
X060676Y014433
|
||||
X014723Y014433
|
||||
X059741Y013778
|
||||
X012013Y014393
|
||||
X-001718Y058110
|
||||
X061644Y042569
|
||||
X057445Y030168
|
||||
X047615Y039378
|
||||
X058814Y044899
|
||||
X057445Y027618
|
||||
X047615Y040929
|
||||
X069195Y046318
|
||||
X077135Y046328
|
||||
X076515Y047028
|
||||
X068495Y047039
|
||||
X075865Y047689
|
||||
X067745Y047689
|
||||
X075155Y048389
|
||||
X067165Y048389
|
||||
X004574Y045538
|
||||
X078065Y045868
|
||||
X047924Y031737
|
||||
X047879Y021582
|
||||
X047893Y024121
|
||||
X047895Y029199
|
||||
X047897Y026660
|
||||
X060794Y051359
|
||||
X058555Y024128
|
||||
X068304Y052019
|
||||
X059624Y052679
|
||||
X058264Y053329
|
||||
X098233Y060306
|
||||
X098221Y061405
|
||||
X098225Y062489
|
||||
X092008Y060306
|
||||
X058359Y021582
|
||||
X091955Y061388
|
||||
X091955Y062489
|
||||
X063594Y055499
|
||||
X060064Y054079
|
||||
X072164Y054799
|
||||
X083563Y029081
|
||||
X083532Y018290
|
||||
X073148Y024448
|
||||
X048131Y018289
|
||||
X091127Y059240
|
||||
X078791Y019948
|
||||
X021611Y040768
|
||||
X040324Y031329
|
||||
X040344Y029829
|
||||
X040344Y028329
|
||||
X040384Y026729
|
||||
X040384Y025109
|
||||
X-002616Y034329
|
||||
X-002616Y035829
|
||||
X-002616Y037829
|
||||
X-002616Y039329
|
||||
X020884Y059739
|
||||
X019984Y058749
|
||||
X019024Y057729
|
||||
X025085Y062139
|
||||
X024894Y060729
|
||||
X023884Y059619
|
||||
X022634Y058629
|
||||
X021484Y057629
|
||||
X090962Y015440
|
||||
X090962Y018290
|
||||
X096042Y010710
|
||||
X093452Y015640
|
||||
X-002514Y051122
|
||||
X-002594Y046042
|
||||
X-002704Y050362
|
||||
X004296Y056722
|
||||
X-001114Y048042
|
||||
T03
|
||||
X014774Y046069
|
||||
X069914Y059240
|
||||
X086375Y059240
|
||||
X004011Y018968
|
||||
X014804Y064082
|
||||
X021274Y018289
|
||||
X101122Y005440
|
||||
X090962Y006600
|
||||
X099862Y006600
|
||||
X089632Y005459
|
||||
T04
|
||||
X082571Y008808
|
||||
T05
|
||||
X013029Y015788G85X013034Y015788
|
||||
X015569Y015788G85X015574Y015788
|
||||
T06
|
||||
X052422Y070860G85X052382Y070860
|
||||
X054962Y070860G85X054922Y070860
|
||||
X049882Y070860G85X049842Y070860
|
||||
X052441Y003918G85X052401Y003918
|
||||
X054981Y003918G85X054941Y003918
|
||||
X049901Y003918G85X049861Y003918
|
||||
X009484Y045729
|
||||
T07
|
||||
X069822Y069930G85X069822Y069930
|
||||
X069822Y067390G85X069822Y067390
|
||||
X077442Y069930G85X077442Y069930
|
||||
X079982Y067390G85X079982Y067390
|
||||
X077442Y067390G85X077442Y067390
|
||||
X074902Y067390G85X074902Y067390
|
||||
X079982Y069930G85X079982Y069930
|
||||
X074902Y069930G85X074902Y069930
|
||||
X072362Y067390G85X072362Y067390
|
||||
X072362Y069930G85X072362Y069930
|
||||
T08
|
||||
X011293Y043946G85X011289Y043949
|
||||
X021263Y053732G85X021259Y053736
|
||||
X024204Y044129G85X024201Y044133
|
||||
X014050Y021431G85X014047Y021435
|
||||
X016546Y036471G85X016543Y036475
|
||||
X024021Y031218G85X024017Y031221
|
||||
X032767Y029853G85X032764Y029856
|
||||
T09
|
||||
X-001239Y059722G85X-001234Y059722
|
||||
X005873Y059722G85X005878Y059722
|
||||
T10
|
||||
X014473Y040765
|
||||
X020837Y034402
|
||||
T11
|
||||
X007048Y048190
|
||||
T12
|
||||
X000539Y003918G85X000544Y003918
|
||||
X112527Y003981G85X112532Y003981
|
||||
X112489Y071088G85X112494Y071088
|
||||
X000399Y070860G85X000404Y070860
|
||||
T13
|
||||
X028261Y048190
|
||||
X028261Y026977
|
||||
M30
|
||||
@@ -0,0 +1,515 @@
|
||||
M48
|
||||
METRIC,LZ,000.000
|
||||
;FILE_FORMAT=3:3
|
||||
;TYPE=PLATED
|
||||
;Layer: PTH_Through_Via
|
||||
;EasyEDA v6.5.46, 2025-01-01 16:01:39
|
||||
;1acd7fc2553046b79c71bda98b4923fc,10
|
||||
;Gerber Generator version 0.2
|
||||
;Holesize 1 = 0.300 mm
|
||||
T01C0.300
|
||||
;Holesize 2 = 0.400 mm
|
||||
T02C0.400
|
||||
;Holesize 3 = 0.500 mm
|
||||
T03C0.500
|
||||
;Holesize 4 = 0.700 mm
|
||||
T04C0.700
|
||||
;Holesize 5 = 0.800 mm
|
||||
T05C0.800
|
||||
;Holesize 6 = 1.600 mm
|
||||
T06C1.600
|
||||
;Holesize 7 = 3.200 mm
|
||||
T07C3.200
|
||||
;Holesize 8 = 4.000 mm
|
||||
T08C4.000
|
||||
%
|
||||
G05
|
||||
G90
|
||||
T01
|
||||
X033262Y064570
|
||||
T02
|
||||
X033746Y068890
|
||||
X033746Y067630
|
||||
X032496Y068890
|
||||
X032496Y067640
|
||||
X000503Y006140
|
||||
X002078Y005493
|
||||
X-001046Y005505
|
||||
X-001757Y003880
|
||||
X002700Y003931
|
||||
X-001046Y002407
|
||||
X000503Y001746
|
||||
X002065Y002394
|
||||
X112492Y006204
|
||||
X114067Y005556
|
||||
X110942Y005569
|
||||
X110231Y003943
|
||||
X114689Y003994
|
||||
X110942Y002470
|
||||
X112492Y001810
|
||||
X114054Y002457
|
||||
X112454Y073311
|
||||
X114028Y072663
|
||||
X110904Y072676
|
||||
X110193Y071050
|
||||
X114651Y071101
|
||||
X110904Y069577
|
||||
X112454Y068917
|
||||
X114016Y069564
|
||||
X000363Y073082
|
||||
X001938Y072434
|
||||
X-001186Y072447
|
||||
X-001897Y070822
|
||||
X002561Y070872
|
||||
X-001186Y069348
|
||||
X000363Y068688
|
||||
X001926Y069336
|
||||
X043182Y073180
|
||||
X057290Y063879
|
||||
X055639Y063879
|
||||
X054115Y063879
|
||||
X023541Y056040
|
||||
X-000716Y008989
|
||||
X040694Y054339
|
||||
X039184Y054339
|
||||
X037684Y054339
|
||||
X036194Y054339
|
||||
X034684Y054339
|
||||
X033184Y054339
|
||||
X031694Y054339
|
||||
X030184Y054339
|
||||
X028684Y054339
|
||||
X040694Y057659
|
||||
X039184Y057659
|
||||
X037684Y057659
|
||||
X036194Y057659
|
||||
X034684Y057659
|
||||
X033184Y057659
|
||||
X031694Y057659
|
||||
X030184Y057659
|
||||
X028684Y057659
|
||||
X027194Y057659
|
||||
X025684Y057659
|
||||
X024184Y057659
|
||||
X-002604Y045352
|
||||
X003264Y054799
|
||||
X000826Y052072
|
||||
X001374Y051759
|
||||
X001394Y052349
|
||||
X001394Y052349
|
||||
X003674Y050949
|
||||
X004474Y050949
|
||||
X004474Y051819
|
||||
X003674Y051819
|
||||
X000794Y053369
|
||||
X000804Y054169
|
||||
X115384Y012549
|
||||
X115384Y014149
|
||||
X115384Y015569
|
||||
X091384Y022329
|
||||
X092884Y022329
|
||||
X094384Y022329
|
||||
X095884Y022329
|
||||
X097384Y022329
|
||||
X082084Y026189
|
||||
X082084Y027159
|
||||
X086521Y016440
|
||||
X076134Y058229
|
||||
X069384Y058229
|
||||
X068854Y056279
|
||||
X059895Y043988
|
||||
X081972Y056970
|
||||
X070944Y056949
|
||||
X060837Y043271
|
||||
X078771Y056139
|
||||
X071254Y056139
|
||||
X065404Y066959
|
||||
X022844Y069129
|
||||
X022854Y070029
|
||||
X024785Y069289
|
||||
X041284Y063829
|
||||
X041284Y064749
|
||||
X017594Y069039
|
||||
X016784Y069039
|
||||
X021954Y060729
|
||||
X022604Y061599
|
||||
X033484Y062559
|
||||
X032884Y063169
|
||||
X022684Y048469
|
||||
X022684Y049489
|
||||
X022684Y050469
|
||||
X019781Y050798
|
||||
X020551Y051588
|
||||
X019071Y049998
|
||||
X053284Y073469
|
||||
X051784Y073469
|
||||
X054784Y073469
|
||||
X044284Y073469
|
||||
X056284Y073469
|
||||
X050284Y073469
|
||||
X048784Y073469
|
||||
X057784Y073469
|
||||
X021882Y074350
|
||||
X023382Y074350
|
||||
X064450Y066340
|
||||
X047962Y071820
|
||||
X028462Y067260
|
||||
X029172Y066460
|
||||
X033902Y071829
|
||||
X039922Y069890
|
||||
X039929Y061954
|
||||
X047970Y065068
|
||||
X023182Y068229
|
||||
X009236Y057012
|
||||
X022652Y071790
|
||||
X009622Y065100
|
||||
X035742Y072490
|
||||
X009572Y059860
|
||||
X043912Y060994
|
||||
X045552Y067320
|
||||
X046412Y066020
|
||||
X047212Y041900
|
||||
X047212Y068570
|
||||
X044692Y069849
|
||||
X040972Y069849
|
||||
X040992Y067830
|
||||
X025171Y026068
|
||||
X031191Y031448
|
||||
X030271Y030328
|
||||
X024261Y025278
|
||||
X033391Y025758
|
||||
X033401Y024428
|
||||
X031911Y025798
|
||||
X033391Y027298
|
||||
X032081Y032348
|
||||
X049684Y011368
|
||||
X048184Y011358
|
||||
X046684Y011348
|
||||
X045184Y011358
|
||||
X043684Y011348
|
||||
X115384Y016969
|
||||
X115384Y018169
|
||||
X115364Y019329
|
||||
X115384Y020659
|
||||
X115214Y008229
|
||||
X115204Y006729
|
||||
X109384Y001239
|
||||
X107884Y001249
|
||||
X106384Y001259
|
||||
X104884Y001249
|
||||
X103384Y001249
|
||||
X101884Y001239
|
||||
X100384Y001229
|
||||
X098884Y001239
|
||||
X097384Y001239
|
||||
X095884Y001229
|
||||
X094384Y001229
|
||||
X092884Y001229
|
||||
X091384Y001229
|
||||
X089884Y001229
|
||||
X088384Y001229
|
||||
X086884Y001219
|
||||
X000785Y007999
|
||||
X002284Y006879
|
||||
X003484Y005729
|
||||
X-002596Y008829
|
||||
X-002616Y010329
|
||||
X-002616Y011829
|
||||
X-002616Y013329
|
||||
X-002616Y014829
|
||||
X-002616Y016329
|
||||
X-000816Y065529
|
||||
X-002316Y065529
|
||||
X076084Y073484
|
||||
X073272Y073460
|
||||
X071284Y073475
|
||||
X068284Y073484
|
||||
X074584Y020369
|
||||
X074584Y021658
|
||||
X074584Y022719
|
||||
X081484Y044478
|
||||
X074365Y029879
|
||||
X072535Y029828
|
||||
X070635Y029808
|
||||
X077555Y039659
|
||||
X069335Y039858
|
||||
X074145Y039309
|
||||
X074145Y040279
|
||||
X074345Y033929
|
||||
X074335Y035788
|
||||
X072555Y035769
|
||||
X072545Y033948
|
||||
X070655Y033938
|
||||
X070685Y035769
|
||||
X098884Y022329
|
||||
X100384Y022329
|
||||
X101884Y022329
|
||||
X103384Y022329
|
||||
X104884Y022329
|
||||
X066784Y020168
|
||||
X066784Y021048
|
||||
X066784Y021959
|
||||
X066784Y022808
|
||||
X072121Y024198
|
||||
X072121Y025078
|
||||
X083535Y045249
|
||||
X079544Y049619
|
||||
X115384Y022329
|
||||
X113884Y022329
|
||||
X112384Y022329
|
||||
X110884Y022329
|
||||
X109384Y022329
|
||||
X107884Y022329
|
||||
X106384Y022329
|
||||
X001584Y065529
|
||||
X003284Y065529
|
||||
X004984Y065529
|
||||
X006384Y067929
|
||||
X006384Y066729
|
||||
X006384Y065529
|
||||
X-002316Y067029
|
||||
X-000816Y067029
|
||||
X001385Y067429
|
||||
X003184Y068429
|
||||
X004184Y070029
|
||||
X004385Y071629
|
||||
X-002616Y032829
|
||||
X-002616Y031329
|
||||
X-002616Y029829
|
||||
X-002616Y028329
|
||||
X-002616Y026829
|
||||
X-002616Y025329
|
||||
X-002616Y023829
|
||||
X-002616Y022329
|
||||
X-002616Y020829
|
||||
X-002616Y019329
|
||||
X-002616Y017829
|
||||
X-002516Y007529
|
||||
X-002516Y006229
|
||||
X004684Y004629
|
||||
X005584Y003629
|
||||
X006484Y002729
|
||||
X007385Y001829
|
||||
X002884Y000829
|
||||
X004385Y000829
|
||||
X005884Y000829
|
||||
X007385Y000829
|
||||
X008884Y000829
|
||||
X010385Y000829
|
||||
X011884Y000829
|
||||
X013385Y000829
|
||||
X014884Y000829
|
||||
X016384Y000829
|
||||
X017884Y000829
|
||||
X019384Y000829
|
||||
X020884Y000829
|
||||
X022384Y000829
|
||||
X023884Y000829
|
||||
X025384Y000829
|
||||
X026884Y000829
|
||||
X028384Y000829
|
||||
X029884Y000829
|
||||
X031384Y000829
|
||||
X032884Y000829
|
||||
X034384Y000829
|
||||
X035884Y000829
|
||||
X037384Y000829
|
||||
X038884Y000829
|
||||
X040384Y000829
|
||||
X041884Y000829
|
||||
X043384Y000829
|
||||
X044884Y000829
|
||||
X046384Y000829
|
||||
X047884Y000829
|
||||
X049384Y000829
|
||||
X050884Y000829
|
||||
X052384Y000829
|
||||
X053884Y000829
|
||||
X055384Y000829
|
||||
X056884Y000829
|
||||
X058384Y000829
|
||||
X059884Y000829
|
||||
X061384Y000829
|
||||
X062884Y000829
|
||||
X064384Y000829
|
||||
X065884Y000829
|
||||
X067384Y000829
|
||||
X068891Y000829
|
||||
X070391Y000829
|
||||
X071891Y000829
|
||||
X073391Y000829
|
||||
X074891Y000829
|
||||
X076431Y000828
|
||||
X078002Y000840
|
||||
X079384Y001229
|
||||
X080884Y001229
|
||||
X082384Y001229
|
||||
X083884Y001229
|
||||
X085384Y001229
|
||||
X004382Y074350
|
||||
X005882Y074350
|
||||
X007382Y074350
|
||||
X008882Y074350
|
||||
X014382Y074350
|
||||
X015882Y074350
|
||||
X017382Y074350
|
||||
X020382Y074350
|
||||
X018882Y074350
|
||||
X024882Y074350
|
||||
X026462Y074330
|
||||
X027922Y074320
|
||||
X029162Y074340
|
||||
X030882Y074350
|
||||
X032382Y074350
|
||||
X033882Y074350
|
||||
X035382Y074350
|
||||
X036882Y074350
|
||||
X038382Y074350
|
||||
X039882Y074350
|
||||
X041382Y074350
|
||||
X045784Y073469
|
||||
X047284Y073469
|
||||
X059284Y073469
|
||||
X060784Y073475
|
||||
X062284Y073475
|
||||
X063784Y073475
|
||||
X065284Y073475
|
||||
X066784Y073475
|
||||
X078602Y073510
|
||||
X081184Y073475
|
||||
X082684Y073475
|
||||
X084484Y073475
|
||||
X085984Y073475
|
||||
X087484Y073475
|
||||
X088984Y073475
|
||||
X090484Y073475
|
||||
X091984Y073475
|
||||
X093484Y073475
|
||||
X094984Y073475
|
||||
X096484Y073475
|
||||
X097984Y073475
|
||||
X099484Y073475
|
||||
X100984Y073475
|
||||
X102484Y073475
|
||||
X103984Y073475
|
||||
X105484Y073475
|
||||
X106984Y073475
|
||||
X108484Y073475
|
||||
X027601Y019268
|
||||
X023813Y020081
|
||||
X028890Y022249
|
||||
X026321Y021528
|
||||
X017452Y004818
|
||||
X085852Y017350
|
||||
X077648Y008828
|
||||
X034983Y005683
|
||||
X076673Y015173
|
||||
X033983Y015173
|
||||
X068663Y007623
|
||||
X068663Y004453
|
||||
X063595Y015808
|
||||
X036533Y015813
|
||||
X063015Y016538
|
||||
X031443Y015303
|
||||
X062135Y007909
|
||||
X032333Y005783
|
||||
X061270Y008433
|
||||
X014703Y005623
|
||||
X060676Y014433
|
||||
X014723Y014433
|
||||
X059741Y013778
|
||||
X012013Y014393
|
||||
X-001718Y058110
|
||||
X061644Y042569
|
||||
X057445Y030168
|
||||
X047615Y039378
|
||||
X058814Y044899
|
||||
X057445Y027618
|
||||
X047615Y040929
|
||||
X069195Y046318
|
||||
X077135Y046328
|
||||
X076515Y047028
|
||||
X068495Y047039
|
||||
X075865Y047689
|
||||
X067745Y047689
|
||||
X075155Y048389
|
||||
X067165Y048389
|
||||
X004574Y045538
|
||||
X078065Y045868
|
||||
X047924Y031737
|
||||
X047879Y021582
|
||||
X047893Y024121
|
||||
X047895Y029199
|
||||
X047897Y026660
|
||||
X060794Y051359
|
||||
X058555Y024128
|
||||
X068304Y052019
|
||||
X059624Y052679
|
||||
X058264Y053329
|
||||
X098233Y060306
|
||||
X098221Y061405
|
||||
X098225Y062489
|
||||
X092008Y060306
|
||||
X058359Y021582
|
||||
X091955Y061388
|
||||
X091955Y062489
|
||||
X063594Y055499
|
||||
X060064Y054079
|
||||
X072164Y054799
|
||||
X083563Y029081
|
||||
X083532Y018290
|
||||
X073148Y024448
|
||||
X048131Y018289
|
||||
X091127Y059240
|
||||
X078791Y019948
|
||||
X021611Y040768
|
||||
X040324Y031329
|
||||
X040344Y029829
|
||||
X040344Y028329
|
||||
X040384Y026729
|
||||
X040384Y025109
|
||||
X-002616Y034329
|
||||
X-002616Y035829
|
||||
X-002616Y037829
|
||||
X-002616Y039329
|
||||
X020884Y059739
|
||||
X019984Y058749
|
||||
X019024Y057729
|
||||
X025085Y062139
|
||||
X024894Y060729
|
||||
X023884Y059619
|
||||
X022634Y058629
|
||||
X021484Y057629
|
||||
X090962Y015440
|
||||
X090962Y018290
|
||||
X096042Y010710
|
||||
X093452Y015640
|
||||
X-002514Y051122
|
||||
X-002594Y046042
|
||||
X-002704Y050362
|
||||
X004296Y056722
|
||||
X-001114Y048042
|
||||
T03
|
||||
X014774Y046069
|
||||
X069914Y059240
|
||||
X086375Y059240
|
||||
X004011Y018968
|
||||
X014804Y064082
|
||||
X021274Y018289
|
||||
X101122Y005440
|
||||
X090962Y006600
|
||||
X099862Y006600
|
||||
X089632Y005459
|
||||
T04
|
||||
X082571Y008808
|
||||
T05
|
||||
X009484Y045729
|
||||
T06
|
||||
X014473Y040765
|
||||
X020837Y034402
|
||||
T07
|
||||
X007048Y048190
|
||||
T08
|
||||
X028261Y048190
|
||||
X028261Y026977
|
||||
M30
|
||||
@@ -0,0 +1,114 @@
|
||||
G04 Layer: BoardOutlineLayer*
|
||||
G04 EasyEDA v6.5.46, 2025-01-01 16:01:39*
|
||||
G04 1acd7fc2553046b79c71bda98b4923fc,10*
|
||||
G04 Gerber Generator version 0.2*
|
||||
G04 Scale: 100 percent, Rotated: No, Reflected: No *
|
||||
G04 Dimensions in millimeters *
|
||||
G04 leading zeros omitted , absolute positions ,4 integer and 5 decimal *
|
||||
%FSLAX45Y45*%
|
||||
%MOMM*%
|
||||
|
||||
%ADD10C,0.2540*%
|
||||
D10*
|
||||
X9285762Y5161592D02*
|
||||
G01*
|
||||
X11467622Y5161592D01*
|
||||
G75*
|
||||
G01*
|
||||
X11490437Y6366413D02*
|
||||
G03*
|
||||
X11490435Y6365811I-114999J-10D01*
|
||||
G75*
|
||||
G01*
|
||||
X3958438Y6366413D02*
|
||||
G03*
|
||||
X3958436Y6365811I-114999J-10D01*
|
||||
G75*
|
||||
G01*
|
||||
X11489939Y1123414D02*
|
||||
G03*
|
||||
X11489937Y1122812I-114999J-10D01*
|
||||
G75*
|
||||
G01*
|
||||
X11122802Y6341742D02*
|
||||
G03*
|
||||
X11122801Y6341376I-70000J11D01*
|
||||
G75*
|
||||
G01*
|
||||
X11120262Y5539102D02*
|
||||
G03*
|
||||
X11120261Y5538736I-70000J11D01*
|
||||
G75*
|
||||
G01*
|
||||
X3958438Y1124415D02*
|
||||
G03*
|
||||
X3958436Y1123813I-114999J-10D01*
|
||||
G75*
|
||||
G01*
|
||||
X9285762Y5161591D02*
|
||||
G03*
|
||||
X9119393Y5006651I-4000J-162495D01*
|
||||
G75*
|
||||
G01*
|
||||
X11467621Y5161591D02*
|
||||
G03*
|
||||
X11617482Y5315261I-7768J157484D01*
|
||||
G75*
|
||||
G01*
|
||||
X9119393Y2454272D02*
|
||||
G03*
|
||||
X9259094Y2326002I137678J9736D01*
|
||||
G75*
|
||||
G01*
|
||||
X11627643Y2179953D02*
|
||||
G03*
|
||||
X11486672Y2326004I-142230J3776D01*
|
||||
G75*
|
||||
G01*
|
||||
X11294904Y2D02*
|
||||
G03*
|
||||
X11627644Y328931I-18455J351430D01*
|
||||
G75*
|
||||
G01*
|
||||
X-346707Y320040D02*
|
||||
G03*
|
||||
X2Y-1I337962J18303D01*
|
||||
G75*
|
||||
G01*
|
||||
X-11431Y7518226D02*
|
||||
G03*
|
||||
X-346708Y7186754I-19125J-315954D01*
|
||||
G75*
|
||||
G01*
|
||||
X11617482Y7196922D02*
|
||||
G03*
|
||||
X11310144Y7518229I-289029J31179D01*
|
||||
X-11432Y7518227D02*
|
||||
G01*
|
||||
X11310142Y7518227D01*
|
||||
X11617482Y5315259D02*
|
||||
G01*
|
||||
X11617482Y7196922D01*
|
||||
X9119392Y2454272D02*
|
||||
G01*
|
||||
X9119392Y5006649D01*
|
||||
X9259092Y2326002D02*
|
||||
G01*
|
||||
X11486672Y2326002D01*
|
||||
X11627642Y328929D02*
|
||||
G01*
|
||||
X11627642Y2179952D01*
|
||||
X0Y0D02*
|
||||
G01*
|
||||
X11294902Y0D01*
|
||||
X-346707Y320037D02*
|
||||
G01*
|
||||
X-346707Y7186752D01*
|
||||
G75*
|
||||
G01*
|
||||
X11294902Y3D02*
|
||||
G03*
|
||||
X11627642Y328933I-18454J351430D01*
|
||||
|
||||
%LPD*%
|
||||
M02*
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
||||
G04 Layer: BottomPasteMaskLayer*
|
||||
G04 EasyEDA v6.5.46, 2025-01-01 16:01:39*
|
||||
G04 1acd7fc2553046b79c71bda98b4923fc,10*
|
||||
G04 Gerber Generator version 0.2*
|
||||
G04 Scale: 100 percent, Rotated: No, Reflected: No *
|
||||
G04 Dimensions in millimeters *
|
||||
G04 leading zeros omitted , absolute positions ,4 integer and 5 decimal *
|
||||
%FSLAX45Y45*%
|
||||
%MOMM*%
|
||||
|
||||
%AMMACRO1*21,1,$1,$2,0,0,$3*%
|
||||
%ADD10MACRO1,5X2.3X135.0000*%
|
||||
%ADD11MACRO1,5X2.3X-10.0001*%
|
||||
|
||||
%LPD*%
|
||||
D10*
|
||||
G01*
|
||||
X209293Y4568317D03*
|
||||
D11*
|
||||
G01*
|
||||
X32306Y3442335D03*
|
||||
M02*
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,106 @@
|
||||
G04 Layer: BottomSolderMaskLayer*
|
||||
G04 EasyEDA v6.5.46, 2025-01-01 16:01:39*
|
||||
G04 1acd7fc2553046b79c71bda98b4923fc,10*
|
||||
G04 Gerber Generator version 0.2*
|
||||
G04 Scale: 100 percent, Rotated: No, Reflected: No *
|
||||
G04 Dimensions in millimeters *
|
||||
G04 leading zeros omitted , absolute positions ,4 integer and 5 decimal *
|
||||
%FSLAX45Y45*%
|
||||
%MOMM*%
|
||||
|
||||
%AMMACRO1*4,1,8,-0.8085,-0.8382,-0.8382,-0.8085,-0.8382,0.8084,-0.8085,0.8382,0.8084,0.8382,0.8382,0.8084,0.8382,-0.8085,0.8084,-0.8382,-0.8085,-0.8382,0*%
|
||||
%AMMACRO2*4,1,8,0.9335,-2.6317,-2.6317,0.9335,-2.6317,0.9756,-0.9756,2.6317,-0.9335,2.6317,2.6317,-0.9335,2.6317,-0.9756,0.9756,-2.6317,0.9335,-2.6317,0*%
|
||||
%AMMACRO3*4,1,8,2.2742,-1.6203,-2.6912,-0.7448,-2.7154,-0.7103,-2.3087,1.5962,-2.2742,1.6203,2.6912,0.7448,2.7154,0.7103,2.3087,-1.5962,2.2742,-1.6203,0*%
|
||||
%ADD10C,1.6766*%
|
||||
%ADD11C,1.6764*%
|
||||
%ADD12MACRO1*%
|
||||
%ADD13C,1.6016*%
|
||||
%ADD14C,5.4016*%
|
||||
%ADD15C,1.8016*%
|
||||
%ADD17C,1.7016*%
|
||||
%ADD18MACRO2*%
|
||||
%ADD19MACRO3*%
|
||||
%ADD20C,2.4016*%
|
||||
|
||||
%LPD*%
|
||||
D10*
|
||||
G01*
|
||||
X6982152Y6992950D03*
|
||||
G01*
|
||||
X6982152Y6738950D03*
|
||||
G01*
|
||||
X7744152Y6992950D03*
|
||||
D11*
|
||||
G01*
|
||||
X7998152Y6738950D03*
|
||||
G01*
|
||||
X7744152Y6738950D03*
|
||||
G01*
|
||||
X7490152Y6738950D03*
|
||||
D12*
|
||||
G01*
|
||||
X7998152Y6992950D03*
|
||||
D11*
|
||||
G01*
|
||||
X7490152Y6992950D03*
|
||||
G01*
|
||||
X7236152Y6738950D03*
|
||||
G01*
|
||||
X7236152Y6992950D03*
|
||||
D13*
|
||||
G01*
|
||||
X-123675Y5972175D03*
|
||||
G01*
|
||||
X587524Y5972175D03*
|
||||
D14*
|
||||
G01*
|
||||
X54124Y391795D03*
|
||||
G01*
|
||||
X11252984Y398145D03*
|
||||
G01*
|
||||
X11249174Y7108825D03*
|
||||
G01*
|
||||
X40154Y7085964D03*
|
||||
D15*
|
||||
G01*
|
||||
X5240169Y7085964D03*
|
||||
D17*
|
||||
G01*
|
||||
X5494169Y7085964D03*
|
||||
G01*
|
||||
X4986169Y7085964D03*
|
||||
D11*
|
||||
G01*
|
||||
X1303195Y1578787D03*
|
||||
G01*
|
||||
X1557195Y1578787D03*
|
||||
D15*
|
||||
G01*
|
||||
X5242125Y391795D03*
|
||||
D17*
|
||||
G01*
|
||||
X5496125Y391795D03*
|
||||
G01*
|
||||
X4988125Y391795D03*
|
||||
D18*
|
||||
G01*
|
||||
X209292Y4568315D03*
|
||||
D19*
|
||||
G01*
|
||||
X32304Y3442333D03*
|
||||
D20*
|
||||
G01*
|
||||
X1129078Y4394733D03*
|
||||
G01*
|
||||
X2126104Y5373370D03*
|
||||
G01*
|
||||
X2420236Y4413122D03*
|
||||
G01*
|
||||
X1404846Y2143302D03*
|
||||
G01*
|
||||
X1654451Y3647312D03*
|
||||
G01*
|
||||
X2401872Y3121939D03*
|
||||
G01*
|
||||
X3276546Y2985465D03*
|
||||
M02*
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
Portapack H4 is an add-on for the HackRF Software Defined Radio (SDR) platform.
|
||||
|
||||
The improvements of H4:
|
||||
1.GPIO port! The H4M adds a GPIO port so users can make their own add-ons for the H4M, just like the flipper.
|
||||
2.Advanced battery management IC (battery %, voltage, current/draw, etc...)
|
||||
3.Single power on/off switch.
|
||||
4.When powered off, the battery will no longer phantom drain.
|
||||
5.flat design, going back to the iPod style click wheel. (so no more broken buttons and encoders!)
|
||||
6.Improved charge speeds.
|
||||
7.Built in mic (and mic switch between internal and external).
|
||||
8.Matte screen.
|
||||
Reference in New Issue
Block a user