Compare commits

...

17 Commits

Author SHA1 Message Date
summermorningdream 2a78c543a1 revert adding ccache tool (#2153) 2024-05-18 17:33:07 +08:00
Totoo 53b59a8a22 Fix for compile under docker (#2147) 2024-05-12 15:18:14 +02:00
Bernd Herzog 100bea644c Version independent external apps (standalone apps) (#2145)
This pull requests adds a new type of external app to the firmware: The standalone app.

Pros:

Will work after an upgrade.
Size of image is only limited by shared heap size of M0 (application) (64kb total).
Cons:

No full access to all functions in the main firmware. One well defined (and versioned) API handles all communication.
The Pacman app was converted to be the first the the new kind.
2024-05-12 14:55:11 +02:00
summermorningdream fe71592b68 revert submodule downgrade caused my my mistake (#2146) 2024-05-12 18:36:01 +08:00
Erwin Ried 4a96feb829 Adding some missing font 2024-05-12 01:00:55 +02:00
Totoo e666eb1797 MsgDblReg fix (#2144) 2024-05-11 10:52:35 +02:00
gullradriel 963c6e5238 Revert "Updated HackRF revision (#2122)" (#2142)
This reverts commit fac71677d4.
2024-05-08 18:32:38 +12:00
jLynx fac71677d4 Updated HackRF revision (#2122)
* WIP getting name from board
* Updated labels
2024-05-08 08:26:05 +02:00
summermorningdream 075b23b291 add bool type print (#2136) 2024-05-08 08:23:47 +02:00
Mark Thompson 3628576d60 Removed some blank lines (#2140) 2024-05-07 15:41:58 +02:00
Erwin Ried a3b71d0e3d Changing all links to grabify (#2139)
Note: If you are worried about grabify, one of our Mayhem maestros cooked up Grabify. Just using general stats to spruce up layout and discussions.
2024-05-05 09:54:25 +02:00
sommermorgentraum 0ea8453e8a tune output order (#2132) 2024-04-30 08:07:39 -05:00
sommermorgentraum 1ffedace7b replace_my_ide_s_default_comment (#2131) 2024-04-30 08:08:21 +02:00
Mark Thompson e43f7a7980 Change flashing message to match LED behavior (#2130) 2024-04-29 22:29:46 +02:00
Totoo f6a2d21624 support for battery if any + TPMS app to ext (#2129)
* batt initial
* batt widgets
* settings modify
* batt info screen
* ability to hide icon
* battView
* redo tmps
* hide curr + charge if no data
* fix flashing
2024-04-29 17:38:27 +02:00
sommermorgentraum f572b00391 add real gcc ver chk (#2118) 2024-04-29 17:36:30 +02:00
Totoo d74fd527e2 TPMS to ext app (#2128)
* initial

* fix
2024-04-29 13:30:21 +02:00
94 changed files with 2115 additions and 790 deletions
+7 -6
View File
@@ -72,12 +72,13 @@ set(HACKRF_CPLD_XSVF_PATH ${HACKRF_PATH}/firmware/cpld/sgpio_if/${HACKRF_CPLD_XS
set(HACKRF_FIRMWARE_DFU_IMAGE ${hackrf_usb_BINARY_DIR}/${HACKRF_FIRMWARE_DFU_FILENAME})
set(HACKRF_FIRMWARE_BIN_IMAGE ${hackrf_usb_BINARY_DIR}/${HACKRF_FIRMWARE_BIN_FILENAME})
find_program(CCACHE "ccache")
if(CCACHE)
set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE})
set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE})
set(ENV{CCACHE_SLOPPINESS} pch_defines,time_macros)
endif(CCACHE)
# this seems causing some issues (ref. in discord discussions), so temporarily disabled, until figure out the pros and cons and bugs of this tool.
#find_program(CCACHE "ccache")
#if(CCACHE)
# set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE})
# set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE})
# set(ENV{CCACHE_SLOPPINESS} pch_defines,time_macros)
#endif(CCACHE)
enable_testing()
add_subdirectory(firmware)
+5 -3
View File
@@ -10,7 +10,7 @@ This is a fork of the [Havoc](https://github.com/furrtek/portapack-havoc/) firmw
[<img src="https://raw.githubusercontent.com/wiki/portapack-mayhem/mayhem-firmware/img/hw_overview_h2_front.png" height="400">](https://github.com/portapack-mayhem/mayhem-firmware/wiki/Hardware-overview) [<img src="https://raw.githubusercontent.com/wiki/portapack-mayhem/mayhem-firmware/img/hw_overview_h2_inside.png" height="400">](https://github.com/portapack-mayhem/mayhem-firmware/wiki/Hardware-overview#portapack-internals)
*[PortaPack H2+HackRF+battery](https://s.click.aliexpress.com/e/_DmU7GQX) (clone) with a custom [3d printed case](https://github.com/portapack-mayhem/mayhem-firmware/wiki/H2-Enclosure)*
*[PortaPack H2+HackRF+battery](https://grabify.link/7T28JP) (clone) with a custom [3d printed case](https://github.com/portapack-mayhem/mayhem-firmware/wiki/H2-Enclosure)*
# What is this?
@@ -26,9 +26,11 @@ This repository expands upon the previous work by many people and aims to consta
## What to buy?
:heavy_check_mark: A recommended one is this [PortaPack H2](https://s.click.aliexpress.com/e/_DmU7GQX), that includes everything you need with the plastic case "inspired" on [this](https://github.com/portapack-mayhem/mayhem-firmware/wiki/H2-Enclosure).
:heavy_check_mark: A recommended one is this [PortaPack H2](https://grabify.link/7T28JP), that includes everything you need with the plastic case "inspired" on [this](https://github.com/portapack-mayhem/mayhem-firmware/wiki/H2-Enclosure).
:heavy_check_mark: Our friends at OpenSourceSDRLab give away five units every three months in our discord (check the badge on top) of their [PortaPack H2](https://www.aliexpress.com/item/4000247041639.html?gatewayAdapt=4itemAdapt), you can support them too by ordering.
:heavy_check_mark: Some individuals lean towards the [H2 with a metal enclosure](https://grabify.link/HTDXG5), but its advantages remain debated. Share your insights on our [wiki](https://github.com/portapack-mayhem/mayhem-firmware/wiki/Hardware-overview).
:heavy_check_mark: Our friends at OpenSourceSDRLab give away five units every three months in our discord (check the badge on top) of their [PortaPack H2](https://grabify.link/LG0OUY), you can support them too by ordering.
: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:
+4 -2
View File
@@ -50,6 +50,7 @@ endif()
add_subdirectory(application)
add_subdirectory(baseband)
add_subdirectory(standalone)
add_subdirectory(test)
# NOTE: Dependencies break if the .bin files aren't included in DEPENDS. WTF, CMake?
@@ -88,7 +89,7 @@ add_custom_target(
program-external-apps
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${PROJECT_SOURCE_DIR}/tools/copy_external_apps.sh
DEPENDS program
DEPENDS program standalone_apps
)
add_custom_command(
@@ -100,8 +101,9 @@ add_custom_command(
COMMAND cp ${FIRMWARE_FILENAME} firmware_tar/FIRMWARE/portapack-mayhem_${VERSION_NOHASH}.bin
COMMAND mkdir -p firmware_tar/APPS
COMMAND cp application/*.ppma firmware_tar/APPS
COMMAND cp standalone/*/*.ppmp firmware_tar/APPS
COMMAND cd firmware_tar && tar -cvaf ../${PPFW_FILENAME} *
DEPENDS firmware ${FIRMWARE_FILENAME}
DEPENDS firmware ${FIRMWARE_FILENAME} standalone_apps
# Dont use VERBATIM here as it prevents usage of globbing (*)
# There shouldnt be any funny business in the filenames above :)
)
+4 -2
View File
@@ -177,6 +177,7 @@ set(CPPSRC
${COMMON}/utility.cpp
${COMMON}/wm8731.cpp
${COMMON}/ads1110.cpp
${COMMON}/battery.cpp
${COMMON}/performance_counter.cpp
${COMMON}/bmpfile.cpp
app_settings.cpp
@@ -277,13 +278,13 @@ set(CPPSRC
apps/pocsag_app.cpp
# apps/replay_app.cpp
apps/soundboard_app.cpp
apps/tpms_app.cpp
apps/tpms_app.cpp
# apps/tpms_app.cpp
apps/ui_about_simple.cpp
apps/ui_adsb_rx.cpp
apps/ui_adsb_tx.cpp
apps/ui_aprs_rx.cpp
apps/ui_aprs_tx.cpp
apps/ui_battinfo.cpp
apps/ui_bht_tx.cpp
apps/ui_bmp_file_viewer.cpp
apps/ui_btle_rx.cpp
@@ -324,6 +325,7 @@ set(CPPSRC
# apps/ui_spectrum_painter.cpp
apps/ui_ss_viewer.cpp
apps/ui_sstvtx.cpp
apps/ui_standalone_view.cpp
apps/ui_subghzd.cpp
# apps/ui_test.cpp
apps/ui_text_editor.cpp
@@ -5,11 +5,9 @@ namespace ui {
// TODO: Generate this automatically from github
// Information: a line starting with a '#' will be yellow coloured
const std::string authors_list[] = {
" ",
"# * List of contributors * ",
" ",
"#Mayhem:",
" ",
"eried,euquiq,gregoryfenton",
"johnelder,jwetzell,nnemanjan00",
"N0vaPixel,klockee,gullradriel",
@@ -27,7 +25,6 @@ const std::string authors_list[] = {
"Netro,HTotoo",
" ",
"#Havoc:",
" ",
"furrtek,mrmookie,NotPike",
"mjwaxios,ImDroided,Giorgiofox",
"F4GEV,z4ziggy,xmycroftx",
@@ -37,11 +34,9 @@ const std::string authors_list[] = {
"brianlechthaler,ZeroChaos-...",
" ",
"#PortaPack:",
" ",
"jboone,argilo",
" ",
"#HackRF:",
" ",
"mossmann,dominicgs,bvernoux",
"bgamari,schneider42,miek",
"willcode,hessu,Sec42",
@@ -86,8 +81,8 @@ AboutView::AboutView(NavigationView& nav) {
void AboutView::focus() {
menu_view.focus();
// put focus on first text line
menu_view.set_highlighted(1);
// put focus on last text line to make it more obvious that list is scrollable
menu_view.set_highlighted(10);
}
} /* namespace ui */
@@ -15,7 +15,7 @@ class AboutView : public View {
private:
MenuView menu_view{
{0, 0, 240, 240},
{0, 0, 240, 264},
true};
Button button_ok{
+124
View File
@@ -0,0 +1,124 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "ui_battinfo.hpp"
#include "event_m0.hpp"
#include "portapack.hpp"
#include <cstring>
using namespace portapack;
namespace ui {
bool BattinfoView::needRun = true;
void BattinfoView::focus() {
button_exit.focus();
}
// called each 1/60th of second, so 6 = 100ms
void BattinfoView::on_timer() {
if (++timer_counter == timer_period) {
timer_counter = 0;
update_result();
}
}
void BattinfoView::update_result() {
if (!battery::BatteryManagement::isDetected()) {
// todo show no batt management
text_percent.set("UNKNOWN");
text_voltage.set("UNKNOWN");
text_current.set("-");
text_charge.set("-");
return;
}
bool uichg = false;
battery::BatteryManagement::getBatteryInfo(percent, voltage, current, isCharging);
// update text fields
if (percent <= 100)
text_percent.set(to_string_dec_uint(percent) + " %");
else
text_percent.set("UNKNOWN");
if (voltage > 1) {
text_voltage.set(to_string_decimal(voltage / 1000.0, 3) + " V");
} else {
text_voltage.set("UNKNOWN");
}
if (current != 0) {
if (labels_opt.hidden()) uichg = true;
labels_opt.hidden(false);
text_current.hidden(false);
text_charge.hidden(false);
text_current.set(to_string_dec_int(current) + " mA");
text_charge.set(isCharging ? "charge" : "discharge");
labels_opt.hidden(false);
} else {
if (!labels_opt.hidden()) uichg = true;
labels_opt.hidden(true);
text_current.hidden(true);
text_charge.hidden(true);
}
if (uichg) set_dirty();
// to update status bar too, send message in behalf of batt manager
BatteryStateMessage msg{percent, isCharging, voltage};
EventDispatcher::send_message(msg);
}
BattinfoView::BattinfoView(NavigationView& nav)
: nav_{nav} {
add_children({&labels,
&labels_opt,
&text_percent,
&text_voltage,
&text_current,
&text_charge,
&button_exit});
button_exit.on_select = [this, &nav](Button&) {
nav.pop();
};
update_result();
needRun = true;
thread = chThdCreateFromHeap(NULL, 512, NORMALPRIO + 10, BattinfoView::static_fn, this);
}
msg_t BattinfoView::static_fn(void* arg) {
auto obj = static_cast<BattinfoView*>(arg);
while (needRun) {
chThdSleepMilliseconds(16);
obj->on_timer();
}
return 0;
}
BattinfoView::~BattinfoView() {
needRun = false;
if (thread) {
chThdTerminate(thread);
chThdWait(thread);
thread = nullptr;
}
}
} // namespace ui
+86
View File
@@ -0,0 +1,86 @@
/*
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef __UI_BATTINFO_H__
#define __UI_BATTINFO_H__
#include "ui.hpp"
#include "ui_widget.hpp"
#include "ui_navigation.hpp"
#include "string_format.hpp"
namespace ui {
class BattinfoView : public View {
public:
~BattinfoView();
BattinfoView(NavigationView& nav);
BattinfoView(const BattinfoView&) = delete;
BattinfoView(BattinfoView&&) = delete;
BattinfoView& operator=(const BattinfoView&) = delete;
BattinfoView& operator=(BattinfoView&&) = delete;
void focus() override;
std::string title() const override { return "Battery"; };
private:
void update_result();
void on_timer();
NavigationView& nav_;
uint16_t timer_period = 60;
uint16_t timer_counter = 0;
uint8_t percent = 0;
uint16_t voltage = 0;
int32_t current = 0;
bool isCharging = false;
Labels labels{
{{2 * 8, 1 * 16}, "Percent:", Color::light_grey()},
{{2 * 8, 2 * 16}, "Voltage:", Color::light_grey()}};
Labels labels_opt{
{{2 * 8, 3 * 16}, "Current:", Color::light_grey()},
{{2 * 8, 4 * 16}, "Charge:", Color::light_grey()}};
Text text_percent{
{13 * 8, 1 * 16, 10 * 16, 16},
"-"};
Text text_voltage{
{13 * 8, 2 * 16, 10 * 16, 16},
"-"};
Text text_current{
{13 * 8, 3 * 16, 10 * 16, 16},
"-"};
Text text_charge{
{13 * 8, 4 * 16, 10 * 16, 16},
"-"};
Button button_exit{
{72, 17 * 16, 96, 32},
"Back"};
static msg_t static_fn(void* arg);
static bool needRun;
Thread* thread{nullptr};
};
} /* namespace ui */
#endif /*__UI_BATTINFO__*/
+4 -4
View File
@@ -42,7 +42,7 @@ DfuMenu::DfuMenu(NavigationView& nav)
&text_info_line_9,
&text_info_line_10});
if (portapack::battery_ads1110.isDetected()) {
if (battery::BatteryManagement::isDetected()) {
add_child(&voltage_label);
add_child(&text_info_line_11);
}
@@ -53,7 +53,7 @@ void DfuMenu::paint(Painter& painter) {
size_t m0_fragmented_free_space = 0;
const auto m0_fragments = chHeapStatus(NULL, &m0_fragmented_free_space);
auto lines = (portapack::battery_ads1110.isDetected() ? 11 : 10) + 2;
auto lines = (battery::BatteryManagement::isDetected() ? 11 : 10) + 2;
text_info_line_1.set(to_string_dec_uint(chCoreStatus(), 6));
text_info_line_2.set(to_string_dec_uint(m0_fragmented_free_space, 6));
@@ -65,8 +65,8 @@ void DfuMenu::paint(Painter& painter) {
text_info_line_8.set(to_string_dec_uint(shared_memory.m4_performance_counter, 6));
text_info_line_9.set(to_string_dec_uint(shared_memory.m4_buffer_missed, 6));
text_info_line_10.set(to_string_dec_uint(chTimeNow() / 1000, 6));
if (portapack::battery_ads1110.isDetected()) {
text_info_line_11.set(to_string_decimal_padding(portapack::battery_ads1110.readVoltage(), 3, 6));
if (battery::BatteryManagement::isDetected()) {
text_info_line_11.set(to_string_decimal_padding((float)battery::BatteryManagement::getVoltage() / 1000.0, 3, 6));
}
constexpr auto margin = 5;
@@ -163,8 +163,8 @@ bool FlashUtilityView::flash_firmware(std::filesystem::path::string_type path) {
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, 64}, this->nav_.style(), "Please wait while LED RX");
painter.draw_string({12, 84}, this->nav_.style(), "is on and TX is flashing.");
painter.draw_string({12, 124}, this->nav_.style(), "Device will then restart.");
std::memcpy(&shared_memory.bb_data.data[0], path.c_str(), (path.length() + 1) * 2);
+16
View File
@@ -329,6 +329,10 @@ SetUIView::SetUIView(NavigationView& nav) {
if (audio::speaker_disable_supported()) {
add_child(&toggle_speaker);
}
if (battery::BatteryManagement::isDetected()) {
add_child(&toggle_battery_icon);
add_child(&toggle_battery_text);
}
checkbox_disable_touchscreen.set_value(pmem::disable_touchscreen());
checkbox_showsplash.set_value(pmem::config_splash());
@@ -355,6 +359,8 @@ SetUIView::SetUIView(NavigationView& nav) {
toggle_speaker.set_value(!pmem::ui_hide_speaker());
toggle_mute.set_value(!pmem::ui_hide_mute());
toggle_fake_brightness.set_value(!pmem::ui_hide_fake_brightness());
toggle_battery_icon.set_value(!pmem::ui_hide_battery_icon());
toggle_battery_text.set_value(!pmem::ui_hide_numeric_battery());
toggle_sd_card.set_value(!pmem::ui_hide_sd_card());
button_save.on_select = [&nav, this](Button&) {
@@ -382,6 +388,8 @@ SetUIView::SetUIView(NavigationView& nav) {
pmem::set_ui_hide_speaker(!toggle_speaker.value());
pmem::set_ui_hide_mute(!toggle_mute.value());
pmem::set_ui_hide_fake_brightness(!toggle_fake_brightness.value());
pmem::set_ui_hide_battery_icon(!toggle_battery_icon.value());
pmem::set_ui_hide_numeric_battery(!toggle_battery_text.value());
pmem::set_ui_hide_sd_card(!toggle_sd_card.value());
send_system_refresh();
@@ -807,6 +815,7 @@ SetMenuColorView::SetMenuColorView(NavigationView& nav) {
&field_green_level,
&field_blue_level,
&button_save,
&button_reset,
&button_cancel});
button_sample.set_focusable(false);
@@ -824,6 +833,13 @@ SetMenuColorView::SetMenuColorView(NavigationView& nav) {
field_green_level.on_change = color_changed_fn;
field_blue_level.on_change = color_changed_fn;
button_reset.on_select = [&nav, this](Button&) {
field_red_level.set_value(127);
field_green_level.set_value(127);
field_blue_level.set_value(127);
set_dirty();
};
button_save.on_select = [&nav, this](Button&) {
Color c = Color(field_red_level.value(), field_green_level.value(), field_blue_level.value());
pmem::set_menu_color(c);
+21 -8
View File
@@ -323,37 +323,45 @@ class SetUIView : public View {
};
ImageToggle toggle_camera{
{6 * 8, 14 * 16 + 2, 16, 16},
{2 * 8, 14 * 16 + 2, 16, 16},
&bitmap_icon_camera};
ImageToggle toggle_sleep{
{8 * 8, 14 * 16 + 2, 16, 16},
{4 * 8, 14 * 16 + 2, 16, 16},
&bitmap_icon_sleep};
ImageToggle toggle_stealth{
{10 * 8, 14 * 16 + 2, 16, 16},
{6 * 8, 14 * 16 + 2, 16, 16},
&bitmap_icon_stealth};
ImageToggle toggle_converter{
{12 * 8, 14 * 16 + 2, 16, 16},
{8 * 8, 14 * 16 + 2, 16, 16},
&bitmap_icon_upconvert};
ImageToggle toggle_bias_tee{
{14 * 8, 14 * 16 + 2, 16, 16},
{10 * 8, 14 * 16 + 2, 16, 16},
&bitmap_icon_biast_off};
ImageToggle toggle_clock{
{16 * 8, 14 * 16 + 2, 8, 16},
{12 * 8, 14 * 16 + 2, 8, 16},
&bitmap_icon_clk_ext};
ImageToggle toggle_mute{
{17 * 8, 14 * 16 + 2, 16, 16},
{13 * 8, 14 * 16 + 2, 16, 16},
&bitmap_icon_speaker_and_headphones_mute};
ImageToggle toggle_speaker{
{19 * 8, 14 * 16 + 2, 16, 16},
{15 * 8, 14 * 16 + 2, 16, 16},
&bitmap_icon_speaker_mute};
ImageToggle toggle_battery_icon{
{17 * 8, 14 * 16 + 2, 16, 16},
&bitmap_icon_batt_icon};
ImageToggle toggle_battery_text{
{19 * 8, 14 * 16 + 2, 16, 16},
&bitmap_icon_batt_text};
ImageToggle toggle_fake_brightness{
{21 * 8, 14 * 16 + 2, 16, 16},
&bitmap_icon_brightness};
@@ -789,6 +797,11 @@ class SetMenuColorView : public View {
' ',
};
Button button_reset{
{2 * 8, 13 * 16, 12 * 8, 32},
"Reset",
};
Button button_save{
{2 * 8, 16 * 16, 12 * 8, 32},
"Save"};
@@ -0,0 +1,82 @@
/*
* 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_standalone_view.hpp"
#include "irq_controls.hpp"
namespace ui {
void create_thread(int32_t (*fn)(void*), void* arg, size_t stack_size, int priority) {
// TODO: collect memory on terminate, once this is used
chThdCreateFromHeap(NULL, stack_size, priority, fn, arg);
}
void fill_rectangle(int x, int y, int width, int height, uint16_t color) {
ui::Painter painter;
painter.fill_rectangle({x, y, width, height}, ui::Color(color));
}
void* alloc(size_t size) {
void* p = chHeapAlloc(0x0, size);
if (p == nullptr)
chDbgPanic("Out of Memory");
return p;
}
uint64_t get_switches_state_ulong() {
return get_switches_state().to_ulong();
}
standalone_application_api_t api = {
/* .malloc = */ &alloc,
/* .calloc = */ &calloc,
/* .realloc = */ &realloc,
/* .free = */ &chHeapFree,
/* .create_thread = */ &create_thread,
/* .fill_rectangle = */ &fill_rectangle,
/* .swizzled_switches = */ &swizzled_switches,
/* .get_switches_state = */ &get_switches_state_ulong,
};
StandaloneView::StandaloneView(NavigationView& nav, std::unique_ptr<uint8_t[]> app_image)
: nav_(nav), _app_image(std::move(app_image)) {
get_application_information()->initialize(api);
add_children({&dummy});
}
void StandaloneView::focus() {
dummy.focus();
}
void StandaloneView::paint(Painter& painter) {
(void)painter;
}
void StandaloneView::frame_sync() {
// skip first refresh
if (!initialized) {
initialized = true;
} else {
get_application_information()->on_event(1);
}
}
} // namespace ui
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2023 Bernd Herzog
* Copyright (C) 2024 Bernd Herzog
*
* This file is part of PortaPack.
*
@@ -19,22 +19,24 @@
* Boston, MA 02110-1301, USA.
*/
#ifndef __UI_PACMAN_H__
#define __UI_PACMAN_H__
#ifndef __UI_STANDALONE_VIEW_H__
#define __UI_STANDALONE_VIEW_H__
#include "ui_navigation.hpp"
#include "event_m0.hpp"
#include "message.hpp"
#include "standalone_app.hpp"
namespace ui::external_app::pacman {
namespace ui {
class PacmanView : public View {
class StandaloneView : public View {
public:
PacmanView(NavigationView& nav);
StandaloneView(NavigationView& nav, std::unique_ptr<uint8_t[]> app_image);
virtual ~StandaloneView() override { get_application_information()->shutdown(); }
void focus() override;
std::string title() const override { return "Pac-Man"; };
std::string title() const override { return (const char*)get_application_information()->app_name; };
void paint(Painter& painter) override;
void frame_sync();
@@ -42,6 +44,10 @@ class PacmanView : public View {
private:
bool initialized = false;
NavigationView& nav_;
std::unique_ptr<uint8_t[]> _app_image;
standalone_application_information_t* get_application_information() const {
return reinterpret_cast<standalone_application_information_t*>(_app_image.get());
}
Button dummy{
{240, 0, 0, 0},
@@ -54,6 +60,6 @@ class PacmanView : public View {
}};
};
} // namespace ui::external_app::pacman
} // namespace ui
#endif /*__UI_PACMAN_H__*/
#endif /*__UI_STANDALONE_VIEW_H__*/
+76
View File
@@ -2447,6 +2447,82 @@ static constexpr Bitmap bitmap_icon_camera{
{16, 16},
bitmap_icon_camera_data};
static constexpr uint8_t bitmap_icon_batt_icon_data[] = {
0xC0,
0x03,
0xC0,
0x03,
0xF0,
0x0F,
0x10,
0x08,
0x10,
0x08,
0x10,
0x08,
0x10,
0x08,
0x10,
0x08,
0xF0,
0x0F,
0xF0,
0x0F,
0xF0,
0x0F,
0xF0,
0x0F,
0xF0,
0x0F,
0xF0,
0x0F,
0xF0,
0x0F,
0x00,
0x00,
};
static constexpr Bitmap bitmap_icon_batt_icon{
{16, 16},
bitmap_icon_batt_icon_data};
static constexpr uint8_t bitmap_icon_batt_text_data[] = {
0x00,
0x00,
0x30,
0x06,
0x48,
0x09,
0x48,
0x09,
0x70,
0x0E,
0x40,
0x08,
0x30,
0x06,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x48,
0x00,
0x20,
0x00,
0x10,
0x00,
0x48,
0x00,
0x00,
0x00,
};
static constexpr Bitmap bitmap_icon_batt_text{
{16, 16},
bitmap_icon_batt_text_data};
static constexpr uint8_t bitmap_icon_tools_wipesd_data[] = {
0xF0,
0x3F,
+5 -5
View File
@@ -1,9 +1,5 @@
set(EXTCPPSRC
#pacman
external/pacman/main.cpp
external/pacman/ui_pacman.cpp
#tetris
external/tetris/main.cpp
external/tetris/ui_tetris.cpp
@@ -80,10 +76,13 @@ set(EXTCPPSRC
#wardrivemap
external/wardrivemap/main.cpp
external/wardrivemap/ui_wardrivemap.cpp
#tpmsrx
external/tpmsrx/main.cpp
external/tpmsrx/tpms_app.cpp
)
set(EXTAPPLIST
pacman
afsk_rx
calculator
font_viewer
@@ -102,4 +101,5 @@ set(EXTAPPLIST
foxhunt_rx
audio_test
wardrivemap
tpmsrx
)
+7 -7
View File
@@ -23,7 +23,6 @@ MEMORY
* Also need to consider processor memory map - reading 0xADxxxxxx generates a fault which may be better than unexpected behavior.
* External app address ranges below must match those in python file "external_app_info.py".
*/
ram_external_app_pacman (rwx) : org = 0xADB00000, len = 32k
ram_external_app_afsk_rx (rwx) : org = 0xADB10000, len = 32k
ram_external_app_calculator (rwx) : org = 0xADB20000, len = 32k
ram_external_app_font_viewer(rwx) : org = 0xADB30000, len = 32k
@@ -42,16 +41,11 @@ MEMORY
ram_external_app_foxhunt_rx(rwx) : org = 0xADC00000, len = 32k
ram_external_app_audio_test(rwx) : org = 0xADC10000, len = 32k
ram_external_app_wardrivemap(rwx) : org = 0xADC20000, len = 32k
ram_external_app_tpmsrx(rwx) : org = 0xADC30000, len = 32k
}
SECTIONS
{
.external_app_pacman : ALIGN(4) SUBALIGN(4)
{
KEEP(*(.external_app.app_pacman.application_information));
*(*ui*external_app*pacman*);
} > ram_external_app_pacman
.external_app_afsk_rx : ALIGN(4) SUBALIGN(4)
{
KEEP(*(.external_app.app_afsk_rx.application_information));
@@ -160,4 +154,10 @@ SECTIONS
*(*ui*external_app*wardrivemap*);
} > ram_external_app_wardrivemap
.external_app_tpmsrx : ALIGN(4) SUBALIGN(4)
{
KEEP(*(.external_app.app_tpmsrx.application_information));
*(*ui*external_app*tpmsrx*);
} > ram_external_app_tpmsrx
}
-65
View File
@@ -1,65 +0,0 @@
#include "ui_pacman.hpp"
#include "irq_controls.hpp"
namespace ui::external_app::pacman {
#pragma GCC diagnostic push
// external code, so ignore warnings
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wreturn-type"
#pragma GCC diagnostic ignored "-Weffc++"
#include "playfield.hpp"
#pragma GCC diagnostic pop
PacmanView::PacmanView(NavigationView& nav)
: nav_(nav) {
add_children({&dummy});
}
void PacmanView::focus() {
dummy.focus();
}
void PacmanView::paint(Painter& painter) {
(void)painter;
static Playfield _game;
static bool wait_for_button_release{false};
if (!initialized) {
initialized = true;
_game.Init();
}
auto switches_raw = swizzled_switches() & ((1 << (int)Switch::Right) | (1 << (int)Switch::Left) | (1 << (int)Switch::Down) | (1 << (int)Switch::Up) | (1 << (int)Switch::Sel) | (1 << (int)Switch::Dfu));
auto switches_debounced = get_switches_state().to_ulong();
// For the Select (Start/Pause) button, wait for release to avoid repeat
uint8_t buttons_to_wait_for = (1 << (int)Switch::Sel);
if (wait_for_button_release) {
if ((switches_debounced & buttons_to_wait_for) == 0)
wait_for_button_release = false;
switches_debounced &= ~buttons_to_wait_for;
} else {
if (switches_debounced & buttons_to_wait_for)
wait_for_button_release = true;
}
// For the directional buttons, use the raw inputs for fastest response time
but_RIGHT = (switches_raw & (1 << (int)Switch::Right)) != 0;
but_LEFT = (switches_raw & (1 << (int)Switch::Left)) != 0;
but_DOWN = (switches_raw & (1 << (int)Switch::Down)) != 0;
but_UP = (switches_raw & (1 << (int)Switch::Up)) != 0;
// For the pause button, use the debounced input to avoid glitches, and OR in the value to make sure that we don't clear it before it's seen
but_A |= (switches_debounced & (1 << (int)Switch::Sel)) != 0;
_game.Step();
}
void PacmanView::frame_sync() {
set_dirty();
}
} // namespace ui::external_app::pacman
@@ -1,82 +1,82 @@
/*
* 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.hpp"
#include "ui_pacman.hpp"
#include "ui_navigation.hpp"
#include "external_app.hpp"
namespace ui::external_app::pacman {
void initialize_app(ui::NavigationView& nav) {
nav.push<PacmanView>();
}
} // namespace ui::external_app::pacman
extern "C" {
__attribute__((section(".external_app.app_pacman.application_information"), used)) application_information_t _application_information_pacman = {
/*.memory_location = */ (uint8_t*)0x00000000, // will be filled at compile time
/*.externalAppEntry = */ ui::external_app::pacman::initialize_app,
/*.header_version = */ CURRENT_HEADER_VERSION,
/*.app_version = */ VERSION_MD5,
/*.app_name = */ "Pac-Man",
/*.bitmap_data = */ {
0x00,
0x00,
0x00,
0x00,
0xC0,
0x07,
0xE0,
0x0F,
0xF0,
0x1F,
0xF8,
0x07,
0xF8,
0x01,
0x78,
0x00,
0xF8,
0x01,
0xF8,
0x07,
0xF0,
0x1F,
0xE0,
0x0F,
0xC0,
0x07,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
},
/*.icon_color = */ ui::Color::yellow().v,
/*.menu_location = */ app_location_t::UTILITIES,
/*.m4_app_tag = portapack::spi_flash::image_tag_none */ {0, 0, 0, 0},
/*.m4_app_offset = */ 0x00000000, // will be filled at compile time
};
}
/*
* Copyright (C) 2024 Mark Thompson
*
* 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 "tpms_app.hpp"
#include "ui_navigation.hpp"
#include "external_app.hpp"
namespace ui::external_app::tpmsrx {
void initialize_app(ui::NavigationView& nav) {
nav.push<TPMSAppView>();
}
} // namespace ui::external_app::tpmsrx
extern "C" {
__attribute__((section(".external_app.app_tpmsrx.application_information"), used)) application_information_t _application_information_tpmsrx = {
/*.memory_location = */ (uint8_t*)0x00000000, // will be filled at compile time
/*.externalAppEntry = */ ui::external_app::tpmsrx::initialize_app,
/*.header_version = */ CURRENT_HEADER_VERSION,
/*.app_version = */ VERSION_MD5,
/*.app_name = */ "TPMS RX",
/*.bitmap_data = */ {
0xC0,
0x03,
0xF0,
0x0F,
0x18,
0x18,
0xEC,
0x37,
0x36,
0x6D,
0x3A,
0x59,
0x4B,
0xD5,
0x8B,
0xD3,
0xCB,
0xD1,
0xAB,
0xD2,
0x9A,
0x5C,
0xB6,
0x6C,
0xEC,
0x37,
0x18,
0x18,
0xF0,
0x0F,
0xC0,
0x03,
},
/*.icon_color = */ ui::Color::green().v,
/*.menu_location = */ app_location_t::RX,
/*.m4_app_tag = portapack::spi_flash::image_tag_tpms */ {'P', 'T', 'P', 'M'},
/*.m4_app_offset = */ 0x00000000, // will be filled at compile time
};
}
@@ -34,15 +34,15 @@ using namespace portapack;
namespace pmem = portapack::persistent_memory;
namespace tpms {
namespace ui::external_app::tpmsrx {
namespace format {
std::string type(Reading::Type type) {
std::string type(tpms::Reading::Type type) {
return to_string_dec_uint(toUType(type), 2);
}
std::string id(TransponderID id) {
std::string id(tpms::TransponderID id) {
return to_string_hex(id.value(), 8);
}
@@ -54,17 +54,17 @@ std::string temperature(Temperature temperature) {
return to_string_dec_int(units_fahr ? temperature.fahrenheit() : temperature.celsius(), 3);
}
std::string flags(Flags flags) {
std::string flags(tpms::Flags flags) {
return to_string_hex(flags, 2);
}
static std::string signal_type(SignalType signal_type) {
static std::string signal_type(tpms::SignalType signal_type) {
switch (signal_type) {
case SignalType::FSK_19k2_Schrader:
case tpms::SignalType::FSK_19k2_Schrader:
return "FSK 38400 19200 Schrader";
case SignalType::OOK_8k192_Schrader:
case tpms::SignalType::OOK_8k192_Schrader:
return "OOK - 8192 Schrader";
case SignalType::OOK_8k4_Schrader:
case tpms::SignalType::OOK_8k4_Schrader:
return "OOK - 8400 Schrader";
default:
return "- - - -";
@@ -73,15 +73,13 @@ static std::string signal_type(SignalType signal_type) {
} /* namespace format */
} /* namespace tpms */
void TPMSLogger::on_packet(const tpms::Packet& packet, const uint32_t target_frequency) {
const auto hex_formatted = packet.symbols_formatted();
// TODO: function doesn't take uint64_t, so when >= 1<<32, weirdness will ensue!
const auto target_frequency_str = to_string_dec_uint(target_frequency, 10);
std::string entry = target_frequency_str + " " + tpms::format::signal_type(packet.signal_type()) + " " + hex_formatted.data + "/" + hex_formatted.errors;
std::string entry = target_frequency_str + " " + ui::external_app::tpmsrx::format::signal_type(packet.signal_type()) + " " + hex_formatted.data + "/" + hex_formatted.errors;
log_file.write_entry(packet.received_at(), entry);
}
@@ -101,52 +99,9 @@ void TPMSRecentEntry::update(const tpms::Reading& reading) {
}
}
namespace ui {
template <>
void RecentEntriesTable<TPMSRecentEntries>::draw(
const Entry& entry,
const Rect& target_rect,
Painter& painter,
const Style& style) {
std::string line = tpms::format::type(entry.type) + " " + tpms::format::id(entry.id);
if (entry.last_pressure.is_valid()) {
line += " " + tpms::format::pressure(entry.last_pressure.value());
} else {
line +=
" "
" ";
}
if (entry.last_temperature.is_valid()) {
line += " " + tpms::format::temperature(entry.last_temperature.value());
} else {
line +=
" "
" ";
}
if (entry.received_count > 999) {
line += " +++";
} else {
line += " " + to_string_dec_uint(entry.received_count, 3);
}
if (entry.last_flags.is_valid()) {
line += " " + tpms::format::flags(entry.last_flags.value());
} else {
line +=
" "
" ";
}
line.resize(target_rect.width() / 8, ' ');
painter.draw_string(target_rect.location(), style, line);
}
TPMSAppView::TPMSAppView(NavigationView&) {
baseband::run_image(portapack::spi_flash::image_tag_tpms);
// baseband::run_image(portapack::spi_flash::image_tag_tpms);
baseband::run_prepared_image(portapack::memory::map::m4_code.base());
add_children({&rssi,
&field_volume,
@@ -167,16 +122,16 @@ TPMSAppView::TPMSAppView(NavigationView&) {
options_band.set_by_value(receiver_model.target_frequency());
options_pressure.on_change = [this](size_t, int32_t i) {
tpms::format::units_psi = (bool)i;
format::units_psi = (bool)i;
update_view();
};
options_pressure.set_selected_index(tpms::format::units_psi, true);
options_pressure.set_selected_index(format::units_psi, true);
options_temperature.on_change = [this](size_t, int32_t i) {
tpms::format::units_fahr = (bool)i;
format::units_fahr = (bool)i;
update_view();
};
options_temperature.set_selected_index(tpms::format::units_fahr, true);
options_temperature.set_selected_index(format::units_fahr, true);
logger = std::make_unique<TPMSLogger>();
if (logger) {
@@ -234,4 +189,50 @@ void TPMSAppView::on_show_list() {
recent_entries_view.focus();
}
} /* namespace ui */
} // namespace ui::external_app::tpmsrx
namespace ui {
template <>
void RecentEntriesTable<ui::external_app::tpmsrx::TPMSRecentEntries>::draw(
const Entry& entry,
const Rect& target_rect,
Painter& painter,
const Style& style) {
std::string line = ui::external_app::tpmsrx::format::type(entry.type) + " " + ui::external_app::tpmsrx::format::id(entry.id);
if (entry.last_pressure.is_valid()) {
line += " " + ui::external_app::tpmsrx::format::pressure(entry.last_pressure.value());
} else {
line +=
" "
" ";
}
if (entry.last_temperature.is_valid()) {
line += " " + ui::external_app::tpmsrx::format::temperature(entry.last_temperature.value());
} else {
line +=
" "
" ";
}
if (entry.received_count > 999) {
line += " +++";
} else {
line += " " + to_string_dec_uint(entry.received_count, 3);
}
if (entry.last_flags.is_valid()) {
line += " " + ui::external_app::tpmsrx::format::flags(entry.last_flags.value());
} else {
line +=
" "
" ";
}
line.resize(target_rect.width() / 8, ' ');
painter.draw_string(target_rect.location(), style, line);
}
} // namespace ui
@@ -38,7 +38,7 @@
#include "tpms_packet.hpp"
namespace tpms {
namespace ui::external_app::tpmsrx {
namespace format {
@@ -47,12 +47,6 @@ static bool units_fahr{false};
} /* namespace format */
} /* namespace tpms */
namespace std {
} /* namespace std */
struct TPMSRecentEntry {
using Key = std::pair<tpms::Reading::Type, tpms::TransponderID>;
@@ -94,8 +88,6 @@ class TPMSLogger {
LogFile log_file{};
};
namespace ui {
using TPMSRecentEntriesView = RecentEntriesView<TPMSRecentEntries>;
class TPMSAppView : public View {
@@ -115,16 +107,18 @@ class TPMSAppView : public View {
private:
RxRadioState radio_state_{
314950000 /* frequency*/,
314950000 /* frequency*/
,
1750000 /* bandwidth */,
2457600 /* sampling rate */};
2457600 /* sampling rate */
};
app_settings::SettingsManager settings_{
"rx_tpms",
app_settings::Mode::RX,
{
{"units_psi"sv, &tpms::format::units_psi},
{"units_fahr"sv, &tpms::format::units_fahr},
{"units_psi"sv, &format::units_psi},
{"units_fahr"sv, &format::units_fahr},
}};
MessageHandlerRegistration message_handler_packet{
@@ -198,6 +192,6 @@ class TPMSAppView : public View {
void update_view();
};
} /* namespace ui */
} // namespace ui::external_app::tpmsrx
#endif /*__TPMS_APP_H__*/
+1 -2
View File
@@ -85,7 +85,6 @@ ClockManager clock_manager{
WM8731 audio_codec_wm8731{i2c0, 0x1a};
AK4951 audio_codec_ak4951{i2c0, 0x12};
ads1110::ADS1110 battery_ads1110{i2c0, 0x48};
ReceiverModel receiver_model;
TransmitterModel transmitter_model;
@@ -587,7 +586,7 @@ init_status_t init() {
chThdSleepMilliseconds(10);
audio::init(portapack_audio_codec());
battery_ads1110.init();
battery::BatteryManagement::init();
if (lcd_fast_setup)
draw_splash_screen_icon(4, ui::bitmap_icon_speaker);
+1 -1
View File
@@ -38,6 +38,7 @@
#include "radio.hpp"
#include "clock_manager.hpp"
#include "temperature_logger.hpp"
#include "battery.hpp"
/* TODO: This would be better as a class to add
* guardrails on setting properties. */
@@ -63,7 +64,6 @@ extern portapack::USBSerial usb_serial;
extern si5351::Si5351 clock_generator;
extern ClockManager clock_manager;
extern ads1110::ADS1110 battery_ads1110;
extern ReceiverModel receiver_model;
extern TransmitterModel transmitter_model;
-1
View File
@@ -1,5 +1,4 @@
#include "ui_bmpview.hpp"
#include "usb_serial_asyncmsg.hpp"
#include "portapack.hpp"
bool BMPViewer::load_bmp(const std::filesystem::path& file) {
@@ -2,6 +2,7 @@
#include "sd_card.hpp"
#include "file_path.hpp"
#include "ui_standalone_view.hpp"
namespace ui {
@@ -10,8 +11,10 @@ namespace ui {
// iterates over all ppma-s, and if it is runnable on the current system, it'll call the callback, and pass info.
/* static */ void ExternalItemsMenuLoader::load_all_external_items_callback(std::function<void(AppInfoConsole&)> callback) {
if (!callback) return;
if (sd_card::status() != sd_card::Status::Mounted)
return;
for (const auto& entry : std::filesystem::directory_iterator(apps_dir, u"*.ppma")) {
auto filePath = apps_dir / entry.path();
File app;
@@ -43,6 +46,37 @@ namespace ui {
.appLocation = application_information.menu_location};
callback(info);
}
for (const auto& entry : std::filesystem::directory_iterator(apps_dir, u"*.ppmp")) {
auto filePath = apps_dir / entry.path();
File app;
auto openError = app.open(filePath);
if (openError)
continue;
standalone_application_information_t application_information = {};
auto readResult = app.read(&application_information, sizeof(standalone_application_information_t));
if (!readResult)
continue;
if (application_information.header_version < CURRENT_STANDALONE_APPLICATION_API_VERSION)
continue;
// here the app is startable and good.
std::string appshortname = filePath.filename().string();
if (appshortname.size() >= 5 && appshortname.substr(appshortname.size() - 5) == ".ppmp") {
// Remove the ".ppmp" suffix
appshortname = appshortname.substr(0, appshortname.size() - 5);
}
AppInfoConsole info{
.appCallName = appshortname.c_str(),
.appFriendlyName = reinterpret_cast<char*>(&application_information.app_name[0]),
.appLocation = application_information.menu_location};
callback(info);
}
}
/* static */ std::vector<GridItem> ExternalItemsMenuLoader::load_external_items(app_location_t app_location, NavigationView& nav) {
@@ -103,6 +137,44 @@ namespace ui {
external_apps.push_back(gridItem);
}
for (const auto& entry : std::filesystem::directory_iterator(apps_dir, u"*.ppmp")) {
auto filePath = apps_dir / entry.path();
File app;
auto openError = app.open(filePath);
if (openError)
continue;
standalone_application_information_t application_information = {};
auto readResult = app.read(&application_information, sizeof(standalone_application_information_t));
if (!readResult)
continue;
if (application_information.menu_location != app_location)
continue;
if (application_information.header_version > CURRENT_STANDALONE_APPLICATION_API_VERSION)
continue;
GridItem gridItem = {};
gridItem.text = reinterpret_cast<char*>(&application_information.app_name[0]);
gridItem.color = Color((uint16_t)application_information.icon_color);
auto dyn_bmp = DynamicBitmap<16, 16>{application_information.bitmap_data};
gridItem.bitmap = dyn_bmp.bitmap();
bitmaps.push_back(std::move(dyn_bmp));
gridItem.on_select = [&nav, app_location, filePath]() {
if (!run_standalone_app(nav, filePath)) {
nav.display_modal("Error", "The .ppmp file in your " + apps_dir.string() + "\nfolder can't be read. Please\nupdate your SD Card content.");
}
};
external_apps.push_back(gridItem);
}
return external_apps;
}
@@ -187,4 +259,39 @@ namespace ui {
return true;
}
/* static */ bool ExternalItemsMenuLoader::run_standalone_app(ui::NavigationView& nav, std::filesystem::path filePath) {
File app;
auto openError = app.open(filePath);
if (openError)
return false;
auto app_image = std::make_unique<uint8_t[]>(app.size());
// read file in 512 byte chunks
for (size_t file_read_index = 0; file_read_index < app.size(); file_read_index += std::filesystem::max_file_block_size) {
auto bytes_to_read = std::filesystem::max_file_block_size;
if (file_read_index + std::filesystem::max_file_block_size > app.size())
bytes_to_read = app.size() - file_read_index;
auto readResult = app.read(&app_image[file_read_index], bytes_to_read);
if (!readResult)
return false;
if (readResult.value() < std::filesystem::max_file_block_size)
break;
}
for (size_t file_read_index = 0; file_read_index < app.size() / 4; file_read_index++) {
uint32_t* ptr = reinterpret_cast<uint32_t*>(&app_image[file_read_index * 4]);
if (*ptr >= 0xADB10000 && *ptr < (0xADB10000 + 64 * 1024)) {
*ptr = *ptr - 0xADB10000 + (uint32_t)app_image.get();
}
}
nav.push<StandaloneView>(std::move(app_image));
return true;
}
} // namespace ui
@@ -26,6 +26,7 @@
#include "ui.hpp"
#include "ui_navigation.hpp"
#include "external_app.hpp"
#include "standalone_app.hpp"
#include "file.hpp"
@@ -57,6 +58,7 @@ class ExternalItemsMenuLoader {
static std::vector<GridItem> load_external_items(app_location_t, NavigationView&);
ExternalItemsMenuLoader() = delete;
static bool run_external_app(ui::NavigationView&, std::filesystem::path);
static bool run_standalone_app(ui::NavigationView&, std::filesystem::path);
static void load_all_external_items_callback(std::function<void(AppInfoConsole&)> callback);
private:
+48 -9
View File
@@ -84,6 +84,7 @@
#include "ui_weatherstation.hpp"
#include "ui_subghzd.hpp"
#include "ui_whipcalc.hpp"
#include "ui_battinfo.hpp"
#include "ui_external_items_menu_loader.hpp"
// #include "acars_app.hpp"
@@ -100,7 +101,7 @@
#include "pocsag_app.hpp"
#include "replay_app.hpp"
#include "soundboard_app.hpp"
#include "tpms_app.hpp"
// #include "tpms_app.hpp" //moved to ext
#include "core_control.hpp"
#include "file.hpp"
@@ -171,9 +172,9 @@ const NavigationView::AppList NavigationView::appList = {
{"radiosonde", "Radiosnde", RX, Color::green(), &bitmap_icon_sonde, new ViewFactory<SondeView>()},
{"recon", "Recon", RX, Color::green(), &bitmap_icon_scanner, new ViewFactory<ReconView>()},
{"search", "Search", RX, Color::yellow(), &bitmap_icon_search, new ViewFactory<SearchView>()},
{"tmps", "TPMS Cars", RX, Color::green(), &bitmap_icon_tpms, new ViewFactory<TPMSAppView>()},
{"weather", "Weather", RX, Color::green(), &bitmap_icon_thermometer, new ViewFactory<WeatherView>()},
//{"tmps", "TPMS Cars", RX, Color::green(), &bitmap_icon_tpms, new ViewFactory<TPMSAppView>()},
{"subghzd", "SubGhzD", RX, Color::yellow(), &bitmap_icon_remote, new ViewFactory<SubGhzDView>()},
{"weather", "Weather", RX, Color::green(), &bitmap_icon_thermometer, new ViewFactory<WeatherView>()},
//{"fskrx", "FSK RX", RX, Color::yellow(), &bitmap_icon_remote, new ViewFactory<FskxRxMainView>()},
//{"dmr", "DMR", RX, Color::dark_grey(), &bitmap_icon_dmr, new ViewFactory<NotImplementedView>()},
//{"sigfox", "SIGFOX", RX, Color::dark_grey(), &bitmap_icon_fox, new ViewFactory<NotImplementedView>()},
@@ -334,6 +335,9 @@ SystemStatusView::SystemStatusView(
refresh();
};
battery_icon.on_select = [this]() { on_battery_details(); };
battery_text.on_select = [this]() { on_battery_details(); };
button_fake_brightness.on_select = [this](ImageButton&) {
set_dirty();
pmem::toggle_fake_brightness_level();
@@ -370,6 +374,26 @@ SystemStatusView::SystemStatusView(
refresh();
}
// when battery icon / text is clicked
void SystemStatusView::on_battery_details() {
if (!nav_.is_valid()) return;
if (batt_info_up) return;
batt_info_up = true;
nav_.push<BattinfoView>();
nav_.set_on_pop([this]() {
batt_info_up = false;
});
}
void SystemStatusView::on_battery_data(const BatteryStateMessage* msg) {
if (!pmem::ui_hide_numeric_battery()) {
battery_text.set_battery(msg->percent, msg->on_charger);
}
if (!pmem::ui_hide_battery_icon()) {
battery_icon.set_battery(msg->percent, msg->on_charger);
};
}
void SystemStatusView::refresh() {
// NB: Order of insertion is the display order Left->Right.
// TODO: Might be better to support hide and only add once.
@@ -386,8 +410,20 @@ void SystemStatusView::refresh() {
if (audio::speaker_disable_supported() && !pmem::ui_hide_speaker()) status_icons.add(&toggle_speaker);
if (!pmem::ui_hide_fake_brightness()) status_icons.add(&button_fake_brightness);
if (battery::BatteryManagement::isDetected()) {
uint8_t percent = battery::BatteryManagement::getPercent();
if (!pmem::ui_hide_battery_icon()) {
status_icons.add(&battery_icon);
battery_text.set_battery(percent, false); // got an on select, that may pop up the details of the battery.
};
if (!pmem::ui_hide_numeric_battery()) {
status_icons.add(&battery_text);
battery_text.set_battery(percent, false);
}
}
if (!pmem::ui_hide_sd_card()) status_icons.add(&sd_card_status_view);
status_icons.update_layout();
// Clock status
@@ -667,8 +703,9 @@ void NavigationView::display_modal(
const std::string& title,
const std::string& message,
modal_t type,
std::function<void(bool)> on_choice) {
push<ModalMessageView>(title, message, type, on_choice);
std::function<void(bool)> on_choice,
bool compact) {
push<ModalMessageView>(title, message, type, on_choice, compact);
}
void NavigationView::free_view() {
@@ -997,11 +1034,13 @@ ModalMessageView::ModalMessageView(
const std::string& title,
const std::string& message,
modal_t type,
std::function<void(bool)> on_choice)
std::function<void(bool)> on_choice,
bool compact)
: title_{title},
message_{message},
type_{type},
on_choice_{on_choice} {
on_choice_{on_choice},
compact{compact} {
if (type == INFO) {
add_child(&button_ok);
button_ok.on_select = [this, &nav](Button&) {
@@ -1034,13 +1073,13 @@ ModalMessageView::ModalMessageView(
}
void ModalMessageView::paint(Painter& painter) {
portapack::display.drawBMP({100, 48}, modal_warning_bmp, false);
if (!compact) portapack::display.drawBMP({100, 48}, modal_warning_bmp, false);
// Break lines.
auto lines = split_string(message_, '\n');
for (size_t i = 0; i < lines.size(); ++i) {
painter.draw_string(
{1 * 8, (Coord)(120 + (i * 16))},
{1 * 8, (Coord)(((compact) ? 8 * 3 : 120) + (i * 16))},
style(),
lines[i]);
}
+18 -3
View File
@@ -120,7 +120,8 @@ class NavigationView : public View {
const std::string& title,
const std::string& message,
modal_t type,
std::function<void(bool)> on_choice = nullptr);
std::function<void(bool)> on_choice = nullptr,
bool compact = false);
void focus() override;
@@ -191,7 +192,7 @@ class SystemStatusView : public View {
private:
static constexpr auto default_title = "";
bool batt_info_up = false; // to prevent show multiple batt info dialog
NavigationView& nav_;
Rectangle backdrop{
@@ -278,6 +279,9 @@ class SystemStatusView : public View {
SDCardStatusView sd_card_status_view{
{0, 0 * 16, 2 * 8, 1 * 16}};
BatteryTextField battery_text{{0, 0, 2 * 8, 1 * 16}, 102};
BatteryIcon battery_icon{{0, 0, 10, 1 * 16}, 102};
void on_converter();
void on_bias_tee();
void on_camera();
@@ -285,6 +289,8 @@ class SystemStatusView : public View {
void refresh();
void on_clk();
void rtc_battery_workaround();
void on_battery_data(const BatteryStateMessage* msg);
void on_battery_details();
MessageHandlerRegistration message_handler_refresh{
Message::ID::StatusRefresh,
@@ -292,6 +298,13 @@ class SystemStatusView : public View {
(void)p;
this->refresh();
}};
MessageHandlerRegistration message_handler_battery{
Message::ID::BatteryStateData,
[this](const Message* const p) {
const auto message = static_cast<const BatteryStateMessage*>(p);
this->on_battery_data(message);
}};
};
class InformationView : public View {
@@ -418,7 +431,8 @@ class ModalMessageView : public View {
const std::string& title,
const std::string& message,
modal_t type,
std::function<void(bool)> on_choice);
std::function<void(bool)> on_choice,
bool compact = false);
void paint(Painter& painter) override;
void focus() override;
@@ -430,6 +444,7 @@ class ModalMessageView : public View {
const std::string message_;
const modal_t type_;
const std::function<void(bool)> on_choice_;
const bool compact;
Button button_ok{
{10 * 8, 14 * 16, 10 * 8, 48},
@@ -132,3 +132,13 @@ void UsbSerialAsyncmsg::asyncmsg(const char* data) {
}
chprintf((BaseSequentialStream*)&SUSBD1, "%s\r\n", data);
}
/// bool
template <>
// usage: UsbSerialAsyncmsg::asyncmsg(true);
void UsbSerialAsyncmsg::asyncmsg<bool>(const bool& data) {
if (!portapack::async_tx_enabled) {
return;
}
chprintf((BaseSequentialStream*)&SUSBD1, "%s\r\n", data ? "true" : "false");
}
+9 -6
View File
@@ -498,12 +498,6 @@ set(MODE_CPPSRC
)
DeclareTargets(PTON tones)
### TPMS
set(MODE_CPPSRC
proc_tpms.cpp
)
DeclareTargets(PTPM tpms)
### Wideband Spectrum
@@ -651,6 +645,15 @@ set(MODE_CPPSRC
)
DeclareTargets(PABP audio_beep)
### TPMS
set(MODE_CPPSRC
proc_tpms.cpp
)
DeclareTargets(PTPM tpms)
### HackRF "factory" firmware
add_custom_command(
+14 -11
View File
@@ -24,10 +24,11 @@
#include <algorithm>
#include <cstdint>
namespace battery {
namespace ads1110 {
constexpr float BATTERY_MIN_VOLTAGE = 3.0;
constexpr float BATTERY_MAX_VOLTAGE = 4.0;
constexpr uint16_t BATTERY_MIN_VOLTAGE = 3000;
constexpr uint16_t BATTERY_MAX_VOLTAGE = 4000;
void ADS1110::init() {
if (!detected_) {
@@ -50,6 +51,7 @@ bool ADS1110::detect() {
return true;
}
}
detected_ = false;
return false;
}
@@ -57,7 +59,8 @@ bool ADS1110::write(const uint8_t value) {
return bus.transmit(bus_address, &value, 1);
}
float ADS1110::readVoltage() {
// returns the batt voltage in mV
uint16_t ADS1110::readVoltage() {
// Read the conversion result
uint8_t data[3];
if (!bus.receive(bus_address, data, 3)) {
@@ -67,7 +70,7 @@ float ADS1110::readVoltage() {
uint16_t raw = (static_cast<uint16_t>(data[0]) << 8) | data[1];
// Calculate the voltage based on the output code
float voltage = 0.0f;
int16_t voltage = 0;
float minCode = 0;
float pga = 0.0f;
@@ -110,21 +113,21 @@ float ADS1110::readVoltage() {
}
// 2.048 is the reference voltage & 2.0 is to make up for the voltage divider
voltage = raw / (-1.0 * minCode) * pga * 2.048 * 2.0;
return voltage;
voltage = (int16_t)(raw / (-1.0 * minCode) * pga * 2.048 * 2.0 * 1000.0); // v to mV
if (voltage < 0) voltage *= -1; // should not happen in this build, but prevent it
return (uint16_t)voltage;
}
void ADS1110::getBatteryInfo(float& batteryPercentage, float& voltage) {
void ADS1110::getBatteryInfo(uint8_t& batteryPercentage, uint16_t& voltage) {
voltage = readVoltage();
// Calculate the remaining battery percentage
batteryPercentage = (voltage - BATTERY_MIN_VOLTAGE) /
(BATTERY_MAX_VOLTAGE - BATTERY_MIN_VOLTAGE) * 100.0;
batteryPercentage = (float)(voltage - BATTERY_MIN_VOLTAGE) / (float)(BATTERY_MAX_VOLTAGE - BATTERY_MIN_VOLTAGE) * 100.0;
// Limit the values to the valid range
batteryPercentage = std::clamp(batteryPercentage, 0.0f, 100.0f);
batteryPercentage = (batteryPercentage > 100) ? 100 : batteryPercentage;
// ToDo: if its > 4, then 100%, if < 3 then 0%
}
} /* namespace ads1110 */
} // namespace battery
+5 -6
View File
@@ -27,11 +27,10 @@
#include <string>
#include "i2c_pp.hpp"
namespace battery {
namespace ads1110 {
using address_t = uint8_t;
using reg_t = uint16_t;
class ADS1110 {
public:
@@ -39,10 +38,11 @@ class ADS1110 {
: bus(bus), bus_address(bus_address), detected_(false) {}
void init();
bool detect();
bool isDetected() const { return detected_; }
float readVoltage();
void getBatteryInfo(float& batteryPercentage, float& voltage);
uint16_t readVoltage();
void getBatteryInfo(uint8_t& batteryPercentage, uint16_t& voltage);
private:
I2C& bus;
@@ -50,9 +50,8 @@ class ADS1110 {
bool detected_;
bool write(const uint8_t value);
bool detect();
};
} /* namespace ads1110 */
} // namespace battery
#endif /* __ADS1110_H__ */
+111
View File
@@ -0,0 +1,111 @@
#include "battery.hpp"
#include "event_m0.hpp"
#include "portapack.hpp"
#include "ads1110.hpp"
// uncomment if you want to emulate batt management system
// #define USE_BATT_EMULATOR
extern I2C portapack::i2c0;
namespace battery {
constexpr uint32_t BATTERY_UPDATE_INTERVAL = 30000;
BatteryManagement::BatteryModules BatteryManagement::detected_ = BatteryManagement::BATT_NONE;
ads1110::ADS1110 battery_ads1110{portapack::i2c0, 0x48};
Thread* BatteryManagement::thread = nullptr;
void BatteryManagement::init() {
// try to detect supported modules
detected_ = BATT_NONE;
if (battery_ads1110.detect()) {
battery_ads1110.init();
detected_ = BATT_ADS1110;
}
// add new supported module detect + init here
#ifdef USE_BATT_EMULATOR
if (detected_ == BATT_NONE) {
detected_ = BATT_EMULATOR;
}
#endif
if (detected_ != BATT_NONE) {
// sets timer to query and broadcats this info
create_thread();
}
}
// sets the values, it the currend module supports it.
bool BatteryManagement::getBatteryInfo(uint8_t& batteryPercentage, uint16_t& voltage, int32_t& current, bool& isCharging) {
if (detected_ == BATT_NONE) return false;
if (detected_ == BATT_ADS1110) {
battery_ads1110.getBatteryInfo(batteryPercentage, voltage);
return true;
}
// add new module query here
#ifdef USE_BATT_EMULATOR
if (detected_ == BATT_EMULATOR) {
batteryPercentage += 5; // %
if (batteryPercentage > 100) batteryPercentage = 0;
voltage = rand() % 1000 + 3000; // mV
current = rand() % 150; // mA
isCharging = rand() % 2;
return true;
}
#endif
(void)isCharging; // keep the compiler calm
(void)current;
return false;
}
uint8_t BatteryManagement::getPercent() {
if (detected_ == BATT_NONE) return 102;
uint8_t batteryPercentage = 0;
bool isCharging = false;
uint16_t voltage = 0;
int32_t current = 0;
getBatteryInfo(batteryPercentage, voltage, current, isCharging);
return batteryPercentage;
}
uint16_t BatteryManagement::getVoltage() {
if (detected_ == BATT_NONE) return 0;
if (detected_ == BATT_NONE) return 102;
uint8_t batteryPercentage = 0;
bool isCharging = false;
uint16_t voltage = 0;
int32_t current = 0;
getBatteryInfo(batteryPercentage, voltage, current, isCharging);
return voltage;
}
msg_t BatteryManagement::timer_fn(void* arg) {
(void)arg;
if (!detected_) return 0;
uint8_t batteryPercentage = 102;
bool isCharging = false;
uint16_t voltage = 0;
int32_t current = 0;
chThdSleepMilliseconds(1000); // wait ui for fully load
while (1) {
if (BatteryManagement::getBatteryInfo(batteryPercentage, voltage, current, isCharging)) {
// send local message
BatteryStateMessage msg{batteryPercentage, isCharging, voltage};
EventDispatcher::send_message(msg);
}
chThdSleepMilliseconds(BATTERY_UPDATE_INTERVAL);
}
return 0;
}
void BatteryManagement::create_thread() {
thread = chThdCreateFromHeap(NULL, 512, NORMALPRIO, BatteryManagement::timer_fn, nullptr);
}
} // namespace battery
+50
View File
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2024 HTotoo.
*
* 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 __BATTERY_H__
#define __BATTERY_H__
#include <cstdint>
#include "ch.h"
namespace battery {
class BatteryManagement {
public:
enum BatteryModules {
BATT_NONE = 0,
BATT_ADS1110 = 1,
BATT_EMULATOR = 254
};
static void init();
static bool isDetected() { return detected_ != BATT_NONE; }
static bool getBatteryInfo(uint8_t& batteryPercentage, uint16_t& voltage, int32_t& current, bool& isCharging);
static uint16_t getVoltage();
static uint8_t getPercent();
private:
static void create_thread();
static msg_t timer_fn(void* arg);
static Thread* thread;
static BatteryModules detected_; // if there is any batt management system
};
}; // namespace battery
#endif
+1 -8
View File
@@ -25,20 +25,13 @@
#include "ch.h"
#include "ui_navigation.hpp"
#include "spi_image.hpp"
#include "standalone_app.hpp"
#define CURRENT_HEADER_VERSION 0x00000002
#define MIN_HEADER_VERSION_FOR_CHECKSUM 0x00000002
typedef void (*externalAppEntry_t)(ui::NavigationView& nav);
enum app_location_t : uint32_t {
UTILITIES = 0,
RX,
TX,
DEBUG,
HOME
};
struct application_information_t {
uint8_t* memory_location;
externalAppEntry_t externalAppEntry;
+17
View File
@@ -123,6 +123,7 @@ class Message {
EnvironmentData = 65,
AudioBeep = 66,
PocsagTosend = 67,
BatteryStateData = 68,
MAX
};
@@ -1409,4 +1410,20 @@ class PocsagTosendMessage : public Message {
uint64_t addr = 0;
};
class BatteryStateMessage : public Message {
public:
constexpr BatteryStateMessage(
uint8_t percent,
bool on_charger,
uint16_t voltage)
: Message{ID::BatteryStateData},
percent{percent},
on_charger{on_charger},
voltage{voltage} {
}
uint8_t percent = 0;
bool on_charger = false;
uint16_t voltage = 0; // mV
};
#endif /*__MESSAGE_H__*/
@@ -132,8 +132,8 @@ struct ui_config2_t {
bool hide_mute : 1;
bool hide_fake_brightness : 1;
bool UNUSED_1 : 1;
bool UNUSED_2 : 1;
bool hide_numeric_battery : 1;
bool hide_battery_icon : 1;
bool UNUSED_3 : 1;
bool UNUSED_4 : 1;
bool UNUSED_5 : 1;
@@ -423,6 +423,7 @@ void defaults() {
set_encoder_dial_sensitivity(DIAL_SENSITIVITY_NORMAL);
set_config_speaker_disable(true); // Disable AK4951 speaker by default (in case of OpenSourceSDRLab H2)
set_menu_color(Color::grey());
set_ui_hide_numeric_battery(true); // hide the numeric battery by default - no space to display it
// Default values for recon app.
set_recon_autosave_freqs(false);
@@ -954,6 +955,13 @@ bool ui_hide_fake_brightness() {
return data->ui_config2.hide_fake_brightness;
}
bool ui_hide_numeric_battery() {
return data->ui_config2.hide_numeric_battery;
}
bool ui_hide_battery_icon() {
return data->ui_config2.hide_battery_icon;
}
void set_ui_hide_speaker(bool v) {
data->ui_config2.hide_speaker = v;
}
@@ -986,6 +994,12 @@ void set_ui_hide_sd_card(bool v) {
void set_ui_hide_fake_brightness(bool v) {
data->ui_config2.hide_fake_brightness = v;
}
void set_ui_hide_numeric_battery(bool v) {
data->ui_config2.hide_numeric_battery = v;
}
void set_ui_hide_battery_icon(bool v) {
data->ui_config2.hide_battery_icon = v;
}
/* Converter */
bool config_converter() {
@@ -1248,6 +1262,8 @@ bool debug_dump() {
pmem_dump_file.write_line("ui_config2 hide_sd_card: " + to_string_dec_uint(data->ui_config2.hide_sd_card));
pmem_dump_file.write_line("ui_config2 hide_mute: " + to_string_dec_uint(data->ui_config2.hide_mute));
pmem_dump_file.write_line("ui_config2 hide_fake_brightness: " + to_string_dec_uint(data->ui_config2.hide_fake_brightness));
pmem_dump_file.write_line("ui_config2 hide_battery_icon: " + to_string_dec_uint(data->ui_config2.hide_battery_icon));
pmem_dump_file.write_line("ui_config2 hide_numeric_battery: " + to_string_dec_uint(data->ui_config2.hide_numeric_battery));
// misc_config bits
pmem_dump_file.write_line("misc_config config_audio_mute: " + to_string_dec_int(config_audio_mute()));
@@ -335,6 +335,8 @@ bool ui_hide_sleep();
bool ui_hide_bias_tee();
bool ui_hide_clock();
bool ui_hide_fake_brightness();
bool ui_hide_numeric_battery();
bool ui_hide_battery_icon();
bool ui_hide_sd_card();
void set_ui_hide_speaker(bool v);
void set_ui_hide_mute(bool v);
@@ -345,6 +347,8 @@ void set_ui_hide_sleep(bool v);
void set_ui_hide_bias_tee(bool v);
void set_ui_hide_clock(bool v);
void set_ui_hide_fake_brightness(bool v);
void set_ui_hide_numeric_battery(bool v);
void set_ui_hide_battery_icon(bool v);
void set_ui_hide_sd_card(bool v);
// sd persisting settings
+74
View File
@@ -0,0 +1,74 @@
/*
* 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.
*/
#ifndef __UI_STANDALONE_APP_H__
#define __UI_STANDALONE_APP_H__
#include <cerrno>
#include <cstdint>
#include <stddef.h>
#define CURRENT_STANDALONE_APPLICATION_API_VERSION 1
struct standalone_application_api_t {
void* (*malloc)(size_t size);
void* (*calloc)(size_t num, size_t size);
void* (*realloc)(void* p, size_t size);
void (*free)(void* p);
void (*create_thread)(int32_t (*fn)(void*), void* arg, size_t stack_size, int priority);
void (*fill_rectangle)(int x, int y, int width, int height, uint16_t color);
uint8_t (*swizzled_switches)();
uint64_t (*get_switches_state)();
// HOW TO extend this interface:
// to keep everything backward compatible: add new fields at the end
// and increment CURRENT_STANDALONE_APPLICATION_API_VERSION
};
enum app_location_t : uint32_t {
UTILITIES = 0,
RX,
TX,
DEBUG,
HOME
};
struct standalone_application_information_t {
uint32_t header_version;
uint8_t app_name[16];
uint8_t bitmap_data[32];
uint32_t icon_color;
app_location_t menu_location;
/// @brief gets called once at application start
void (*initialize)(const standalone_application_api_t& api);
/// @brief gets called when an event occurs
/// @param events bitfield of events
/// @note events are defined in firmware/application/event_m0.hpp
void (*on_event)(const uint32_t& events);
/// @brief gets called once at application shutdown
void (*shutdown)();
};
#endif /*__UI_STANDALONE_APP_H__*/
+129
View File
@@ -2044,6 +2044,135 @@ bool TextField::on_touch(TouchEvent event) {
return false;
}
/* BatteryIcon *************************************************************/
BatteryIcon::BatteryIcon(Rect parent_rect, uint8_t percent)
: Widget(parent_rect) {
this->set_battery(percent, false);
set_focusable(true);
}
void BatteryIcon::getAccessibilityText(std::string& result) {
result = to_string_dec_uint(percent_) + "%";
}
void BatteryIcon::getWidgetName(std::string& result) {
result = "Battery percent";
}
void BatteryIcon::set_battery(uint8_t percentage, bool charge) {
if (charge == charge_ && percent_ == percentage) return;
percent_ = percentage;
charge_ = charge;
set_dirty();
}
bool BatteryIcon::on_key(KeyEvent key) {
if (key == KeyEvent::Select && on_select) {
on_select();
return true;
}
return false;
}
bool BatteryIcon::on_touch(TouchEvent event) {
if (event.type == TouchEvent::Type::Start) {
focus();
return true;
}
if (event.type == TouchEvent::Type::End && on_select) {
on_select();
return true;
}
return false;
}
void BatteryIcon::paint(Painter& painter) {
ui::Rect rect = screen_rect(); // 10, 1 * 16
painter.fill_rectangle(rect, has_focus() || highlighted() ? Color::light_grey() : Color::dark_grey()); // clear
ui::Color battColor = (charge_) ? Color::cyan() : Color::green();
// batt body:
painter.draw_vline({rect.left() + 1, rect.top() + 2}, rect.height() - 4, battColor);
painter.draw_vline({rect.right() - 2, rect.top() + 2}, rect.height() - 4, battColor);
painter.draw_hline({rect.left() + 1, rect.top() + 2}, rect.width() - 2, battColor);
painter.draw_hline({rect.left() + 1, rect.bottom() - 2}, rect.width() - 2, battColor);
// batt cap:
painter.draw_hline({rect.left() + 3, rect.top() + 1}, rect.width() - 6, battColor);
painter.draw_hline({rect.left() + 3, 0}, rect.width() - 6, battColor);
if (percent_ > 100) { // error / unk
painter.draw_string({rect.left() + 2, rect.top() + 3}, font::fixed_5x8, Color::white(), Color::dark_grey(), "?");
return;
}
int8_t ppx = (rect.bottom() - 3) - (rect.top() + 2); // 11px max height to draw bars
int8_t ptd = (int8_t)((static_cast<float>(percent_) / 100.0f) * (float)ppx + 0.5); // pixels to draw
int8_t pp = ppx - ptd; // pixels to start from
if (percent_ >= 70)
battColor = Color::green();
else if (percent_ >= 40)
battColor = Color::orange();
else
battColor = Color::red();
// fill the bars
for (int y = pp; y < ppx; y++) {
painter.draw_hline({rect.left() + 2, rect.top() + 3 + y}, rect.width() - 4, battColor);
}
}
/* BatteryTextField *************************************************************/
BatteryTextField::BatteryTextField(Rect parent_rect, uint8_t percent)
: Widget(parent_rect) {
this->set_battery(percent, false);
set_focusable(true);
}
void BatteryTextField::paint(Painter& painter) {
Color bg = has_focus() || highlighted() ? Color::light_grey() : Color::dark_grey();
ui::Rect rect = screen_rect(); // 2 * 8, 1 * 16
painter.fill_rectangle(rect, bg); // clear
std::string txt_batt = percent_ <= 100 ? to_string_dec_uint(percent_) : "UNK";
int xdelta = 0;
if (txt_batt.length() == 1)
xdelta = 5;
else if (txt_batt.length() == 2)
xdelta = 2;
painter.draw_string({rect.left() + xdelta, rect.top()}, font::fixed_5x8, Color::white(), bg, txt_batt);
painter.draw_string({rect.left(), rect.top() + 8}, font::fixed_5x8, Color::white(), bg, (charge_) ? "+%" : " %");
}
void BatteryTextField::getAccessibilityText(std::string& result) {
result = to_string_dec_uint(percent_) + "%";
}
void BatteryTextField::getWidgetName(std::string& result) {
result = "Battery percent";
}
void BatteryTextField::set_battery(uint8_t percentage, bool charge) {
if (charge == charge_ && percent_ == percentage) return;
charge_ = charge;
percent_ = percentage;
set_dirty();
}
bool BatteryTextField::on_key(KeyEvent key) {
if (key == KeyEvent::Select && on_select) {
on_select();
return true;
}
return false;
}
bool BatteryTextField::on_touch(TouchEvent event) {
if (event.type == TouchEvent::Type::Start) {
focus();
return true;
}
if (event.type == TouchEvent::Type::End && on_select) {
on_select();
return true;
}
return false;
}
/* NumberField ***********************************************************/
NumberField::NumberField(
+48
View File
@@ -33,6 +33,8 @@
#include "portapack.hpp"
#include "utility.hpp"
#include "ui/ui_font_fixed_5x8.hpp"
#include <functional>
#include <memory>
#include <string>
@@ -781,6 +783,52 @@ class TextField : public Text {
using Text::set;
};
class BatteryTextField : public Widget {
public:
std::function<void()> on_select{};
BatteryTextField(Rect parent_rect, uint8_t percent);
void paint(Painter& painter) override;
void set_battery(uint8_t percentage, bool charge);
void set_text(std::string_view value);
bool on_key(KeyEvent key) override;
bool on_touch(TouchEvent event) override;
void getAccessibilityText(std::string& result) override;
void getWidgetName(std::string& result) override;
private:
uint8_t percent_{102};
bool charge_{false};
static constexpr Style style{
.font = font::fixed_5x8,
.background = Color::dark_grey(),
.foreground = Color::white(),
};
};
class BatteryIcon : public Widget {
public:
std::function<void()> on_select{};
BatteryIcon(Rect parent_rect, uint8_t percent);
void paint(Painter& painter) override;
void set_battery(uint8_t percentage, bool charge);
bool on_key(KeyEvent key) override;
bool on_touch(TouchEvent event) override;
void getAccessibilityText(std::string& result) override;
void getWidgetName(std::string& result) override;
private:
uint8_t percent_{102};
bool charge_{false};
};
class NumberField : public Widget {
public:
std::function<void(NumberField&)> on_select{};
Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

+11
View File
@@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 3.5)
project(standalone_apps)
add_subdirectory(pacman)
add_custom_target(
standalone_apps
DEPENDS pacman_app
)
+233
View File
@@ -0,0 +1,233 @@
#
# 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.
#
##############################################################################
# Build global options
# NOTE: Can be overridden externally.
#
enable_language(C CXX ASM)
include(CheckCXXCompilerFlag)
project(pacman_app)
# Compiler options here.
set(USE_OPT "-Os -g --specs=nano.specs")
# C specific options here (added to USE_OPT).
set(USE_COPT "-std=gnu99")
# C++ specific options here (added to USE_OPT).
check_cxx_compiler_flag("-std=c++20" cpp20_supported)
if(cpp20_supported)
set(USE_CPPOPT "-std=c++20")
else()
set(USE_CPPOPT "-std=c++17")
endif()
set(USE_CPPOPT "${USE_CPPOPT} -fno-rtti -fno-exceptions -Weffc++ -Wuninitialized -fno-use-cxa-atexit")
# Enable this if you want the linker to remove unused code and data
set(USE_LINK_GC yes)
# Linker extra options here.
set(USE_LDOPT)
# Enable this if you want link time optimizations (LTO) - this flag affects chibios only
set(USE_LTO no)
# If enabled, this option allows to compile the application in THUMB mode.
set(USE_THUMB yes)
# Enable this if you want to see the full log while compiling.
set(USE_VERBOSE_COMPILE no)
#
# Build global options
##############################################################################
##############################################################################
# Architecture or project specific options
#
# Enables the use of FPU on Cortex-M4 (no, softfp, hard).
set(USE_FPU no)
#
# Architecture or project specific options
##############################################################################
##############################################################################
# Project, sources and paths
#
# Define linker script file here
set(LDSCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/external.ld)
# C sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
FILE(GLOB_RECURSE Sources_C ${CMAKE_CURRENT_LIST_DIR}/*.c)
set(CSRC
${Sources_C}
)
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
FILE(GLOB_RECURSE Sources_CPP ${CMAKE_CURRENT_LIST_DIR}/*.cpp)
set(CPPSRC
${Sources_CPP}
)
# C sources to be compiled in ARM mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
set(ACSRC)
# C++ sources to be compiled in ARM mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
set(ACPPSRC)
# C sources to be compiled in THUMB mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
set(TCSRC)
# C sources to be compiled in THUMB mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
set(TCPPSRC)
# List ASM source files here
set(ASMSRC)
set(INCDIR
${CMAKE_CURRENT_SOURCE_DIR}
${COMMON}
${COMMON}/../application
${COMMON}/../application/hw
)
#
# Project, sources and paths
##############################################################################
##############################################################################
# Compiler settings
#
# TODO: Entertain using MCU=cortex-m0.small-multiply for LPC43xx M0 core.
# However, on GCC-ARM-Embedded 4.9 2015q2, it seems to produce non-functional
# binaries.
set(MCU cortex-m0)
# ARM-specific options here
set(AOPT)
# THUMB-specific options here
set(TOPT "-mthumb -DTHUMB")
# Define C warning options here
set(CWARN "-Wall -Wextra -Wstrict-prototypes")
# Define C++ warning options here
set(CPPWARN "-Wall -Wextra -Wno-psabi")
#
# Compiler settings
##############################################################################
##############################################################################
# Start of default section
#
# List all default C defines here, like -D_DEBUG=1
# TODO: Switch -DCRT0_INIT_DATA depending on load from RAM or SPIFI?
# NOTE: _RANDOM_TCC to kill a GCC 4.9.3 error with std::max argument types
set(DDEFS "-DLPC43XX -DLPC43XX_M0 -D__NEWLIB__ -DHACKRF_ONE -DTOOLCHAIN_GCC -DTOOLCHAIN_GCC_ARM -D_RANDOM_TCC=0")
# List all default ASM defines here, like -D_DEBUG=1
set(DADEFS)
# List all default directories to look for include files here
set(DINCDIR)
# List the default directory to look for the libraries here
set(DLIBDIR)
# List all default libraries here
set(DLIBS)
#
# End of default section
##############################################################################
##############################################################################
# Start of user section
#
# List all user C define here, like -D_DEBUG=1
set(UDEFS)
# Define ASM defines here
set(UADEFS)
# List all user directories here
set(UINCDIR)
# List the user directory to look for the libraries here
set(ULIBDIR)
# List all user libraries here
set(ULIBS)
#
# End of user defines
##############################################################################
set(RULESPATH ${CHIBIOS}/os/ports/GCC/ARMCMx)
include(${RULESPATH}/rules.cmake)
##############################################################################
add_executable(${PROJECT_NAME}.elf ${CSRC} ${CPPSRC} ${ASMSRC})
set_target_properties(${PROJECT_NAME}.elf PROPERTIES LINK_DEPENDS ${LDSCRIPT})
add_definitions(${DEFS})
include_directories(. ${INCDIR})
link_directories(${LLIBDIR})
target_link_libraries(${PROJECT_NAME}.elf -Wl,-Map=${PROJECT_NAME}.map)
# redirect std lib memory allocations
target_link_libraries(${PROJECT_NAME}.elf "-Wl,-wrap,_malloc_r")
target_link_libraries(${PROJECT_NAME}.elf "-Wl,-wrap,_free_r")
add_custom_command(
OUTPUT ${PROJECT_NAME}.ppmp
COMMAND ${CMAKE_OBJCOPY} -v -O binary ${PROJECT_NAME}.elf ${PROJECT_NAME}.ppmp
DEPENDS ${PROJECT_NAME}.elf
)
add_custom_target(
${PROJECT_NAME}
DEPENDS ${PROJECT_NAME}.ppmp
)
@@ -17,6 +17,7 @@
/* MIT license, all text above must be included in any redistribution. */
// #include "ili9328.h"
#include "standalone_app.hpp"
typedef uint16_t ushort;
@@ -46,16 +47,15 @@ uint16_t _paletteW[] =
};
void drawIndexedmap(uint8_t* indexmap, int16_t x, uint16_t y) {
ui::Painter painter;
byte i = 0;
word color = (word)_paletteW[indexmap[0]];
uint16_t color = (uint16_t)_paletteW[indexmap[0]];
for (byte tmpY = 0; tmpY < 8; tmpY++) {
byte width = 1;
for (byte tmpX = 0; tmpX < 8; tmpX++) {
word next_color = (word)_paletteW[indexmap[++i]];
uint16_t next_color = (uint16_t)_paletteW[indexmap[++i]];
if ((color != next_color && width >= 1) || tmpX == 7) {
painter.draw_hline({x + tmpX - width + 1, y + tmpY}, width, ui::Color(color));
_api->fill_rectangle(x + tmpX - width + 1, y + tmpY, width, 1, color);
// painter.draw_hline({x + tmpX - width + 1, y + tmpY}, width, ui::Color(color));
color = next_color;
width = 0;
+118
View File
@@ -0,0 +1,118 @@
/*
Copyright (C) 2024 Bernd Herzog
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
MEMORY
{
ram : org = 0xADB10000, len = 64k /* DO NOT CHANGE the address. We make the image relocateable on load. It needs to be 0xADB10000 */
}
__ram_start__ = ORIGIN(ram);
__ram_size__ = LENGTH(ram);
__ram_end__ = __ram_start__ + __ram_size__;
SECTIONS
{
. = 0;
_text = .;
startup : ALIGN(16) SUBALIGN(16)
{
KEEP(*(.standalone_application_information));
} > ram
constructors : ALIGN(4) SUBALIGN(4)
{
PROVIDE(__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE(__init_array_end = .);
} > ram
destructors : ALIGN(4) SUBALIGN(4)
{
PROVIDE(__fini_array_start = .);
KEEP(*(.fini_array))
KEEP(*(SORT(.fini_array.*)))
PROVIDE(__fini_array_end = .);
} > ram
.text : ALIGN(16) SUBALIGN(16)
{
*(.text.startup.*)
*(.text)
*(.text.*)
*(.rodata)
*(.rodata.*)
*(.glue_7t)
*(.glue_7)
*(.gcc*)
} > ram
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > ram
.ARM.exidx : {
PROVIDE(__exidx_start = .);
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
PROVIDE(__exidx_end = .);
} > ram
.eh_frame_hdr :
{
*(.eh_frame_hdr)
} > ram
.eh_frame : ONLY_IF_RO
{
*(.eh_frame)
} > ram
.textalign : ONLY_IF_RO
{
. = ALIGN(8);
} > ram
.bss ALIGN(4) : ALIGN(4)
{
. = ALIGN(4);
PROVIDE(_bss_start = .);
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(4);
PROVIDE(_bss_end = .);
} > ram
. = ALIGN(4);
_etext = .;
_textdata = _etext;
.data ALIGN(4) : AT (_textdata)
{
. = ALIGN(4);
PROVIDE(_data = .);
*(.data)
*(.data.*)
*(.ramtext)
. = ALIGN(4);
PROVIDE(_edata = .);
} > ram
}
PROVIDE(end = .);
_end = .;
+101
View File
@@ -0,0 +1,101 @@
/*
* 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 "standalone_app.hpp"
#include "pacman.hpp"
#include <memory>
const standalone_application_api_t* _api;
extern "C" {
__attribute__((section(".standalone_application_information"), used)) standalone_application_information_t _standalone_application_information = {
/*.header_version = */ CURRENT_STANDALONE_APPLICATION_API_VERSION,
/*.app_name = */ "Pac-Man",
/*.bitmap_data = */ {
0x00,
0x00,
0x00,
0x00,
0xC0,
0x07,
0xE0,
0x0F,
0xF0,
0x1F,
0xF8,
0x07,
0xF8,
0x01,
0x78,
0x00,
0xF8,
0x01,
0xF8,
0x07,
0xF0,
0x1F,
0xE0,
0x0F,
0xC0,
0x07,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
},
/*.icon_color = 16 bit: 5R 6G 5B*/ 0x0000FFE0,
/*.menu_location = */ app_location_t::UTILITIES,
/*.initialize_app = */ initialize,
/*.on_event = */ on_event,
/*.shutdown = */ shutdown,
};
}
/* Implementing abort() eliminates requirement for _getpid(), _kill(), _exit(). */
extern "C" void abort() {
while (true);
}
// replace memory allocations to use heap from chibios
extern "C" void* malloc(size_t size) {
return _api->malloc(size);
}
extern "C" void* calloc(size_t num, size_t size) {
return _api->calloc(num, size);
}
extern "C" void* realloc(void* p, size_t size) {
return _api->realloc(p, size);
}
extern "C" void free(void* p) {
_api->free(p);
}
// redirect std lib memory allocations (sprintf, etc.)
extern "C" void* __wrap__malloc_r(size_t size) {
return _api->malloc(size);
}
extern "C" void __wrap__free_r(void* p) {
_api->free(p);
}
+80
View File
@@ -0,0 +1,80 @@
/*
* 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 <memory>
#include "pacman.hpp"
#include "irq_controls.hpp"
#pragma GCC diagnostic push
// external code, so ignore warnings
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wreturn-type"
#pragma GCC diagnostic ignored "-Weffc++"
#include "playfield.hpp"
#pragma GCC diagnostic pop
std::unique_ptr<Playfield> _playfield;
void initialize(const standalone_application_api_t& api) {
_api = &api;
}
void on_event(const uint32_t& events) {
static bool wait_for_button_release{false};
if (!_playfield) {
_playfield = std::make_unique<Playfield>();
_playfield->Init();
}
if (events & 1) {
auto switches_raw = _api->swizzled_switches() & ((1 << (int)Switch::Right) | (1 << (int)Switch::Left) | (1 << (int)Switch::Down) | (1 << (int)Switch::Up) | (1 << (int)Switch::Sel) | (1 << (int)Switch::Dfu));
auto switches_debounced = _api->get_switches_state();
// For the Select (Start/Pause) button, wait for release to avoid repeat
uint8_t buttons_to_wait_for = (1 << (int)Switch::Sel);
if (wait_for_button_release) {
if ((switches_debounced & buttons_to_wait_for) == 0)
wait_for_button_release = false;
switches_debounced &= ~buttons_to_wait_for;
} else {
if (switches_debounced & buttons_to_wait_for)
wait_for_button_release = true;
}
// For the directional buttons, use the raw inputs for fastest response time
but_RIGHT = (switches_raw & (1 << (int)Switch::Right)) != 0;
but_LEFT = (switches_raw & (1 << (int)Switch::Left)) != 0;
but_DOWN = (switches_raw & (1 << (int)Switch::Down)) != 0;
but_UP = (switches_raw & (1 << (int)Switch::Up)) != 0;
// For the pause button, use the debounced input to avoid glitches, and OR in the value to make sure that we don't clear it before it's seen
but_A |= (switches_debounced & (1 << (int)Switch::Sel)) != 0;
_playfield->Step();
}
}
void shutdown() {
_playfield.reset();
}
+33
View File
@@ -0,0 +1,33 @@
/*
* 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 __PACMAN_H__
#define __PACMAN_H__
#include "standalone_app.hpp"
void initialize(const standalone_application_api_t& api);
void on_event(const uint32_t& events);
void shutdown();
extern const standalone_application_api_t* _api;
#endif /*__PACMAN_H__*/
@@ -1,4 +1,6 @@
#include <cstring>
/******************************************************************************/
/* MAIN GAME VARIABLES */
/******************************************************************************/
@@ -1,3 +1,27 @@
#!/usr/bin/env python3
#
# Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
# Copyleft (ɔ) 2024 zxkmm with the GPL license
#
# 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.
#
from PIL import Image
import numpy as np
@@ -0,0 +1,61 @@
#!/usr/bin/env python3
#
# Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
# Copyleft (ɔ) 2024 zxkmm with the GPL license
#
# 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.
#
import subprocess
import sys
if_succeed = False
def get_gcc_version(elf_file):
global if_succeed
output = subprocess.check_output(['readelf', '-p', '.comment', elf_file])
output = output.decode('utf-8')
lines = output.split('\n')
for line in lines:
if 'GCC:' in line:
version_info = line.split('GCC:')[1].strip()
if_succeed = True
return version_info
if not if_succeed: # didn't use try except here cuz don't need to break compile if this is bad result anyway
return None
if __name__ == "__main__":
if len(sys.argv) != 2:
current_dir = subprocess.check_output(['pwd'])
print(f"current dir: {current_dir}")
print("usage python check_gcc_version_from_elf.py xxx.elf")
sys.exit(1)
elf_file = sys.argv[1]
version_info = get_gcc_version(elf_file)
if version_info is not None:
print(f"real gcc version readed from elf: {version_info}")
else:
print("something went wrong when checking gcc version don't worry tho, it's not deadly issue. skip.")
+1
View File
@@ -44,6 +44,7 @@ do
echo "Copying external applications to" $mountpoint
mkdir -p $mountpoint/APPS
cp application/*.ppma $mountpoint/APPS
cp standalone/*/*.ppmp $mountpoint/APPS
echo "Unmounting" $mountpoint
umount $mountpoint
+90 -32
View File
@@ -3,6 +3,7 @@
#
# Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
# Copyright (C) 2024 Mark Thompson
# Copyleft (ɔ) 2024 zxkmm with the GPL license
#
# This file is part of PortaPack.
#
@@ -23,9 +24,11 @@
#
import sys
import os
from external_app_info import maximum_application_size
from external_app_info import external_apps_address_start
from external_app_info import external_apps_address_end
import subprocess
usage_message = """
PortaPack SPI flash image generator
@@ -34,65 +37,120 @@ Usage: <command> <application_path> <baseband_path> <output_path>
Where paths refer to the .bin files for each component project.
"""
def read_image(path):
f = open(path, 'rb')
data = f.read()
f.close()
return data
f = open(path, 'rb')
data = f.read()
f.close()
return data
def write_image(data, path):
f = open(path, 'wb')
f.write(data)
f.close()
f = open(path, 'wb')
f.write(data)
f.close()
def get_gcc_version_from_elf(elf_file):
succeed = False
output = subprocess.check_output(['readelf', '-p', '.comment', elf_file])
output = output.decode('utf-8')
lines = output.split('\n')
for line in lines:
if 'GCC:' in line:
version_info = line.split('GCC:')[1].strip()
succeed = True
return version_info
if not succeed: # didn't use try except here cuz don't need to break compile if this is bad result anyway
return None
def get_gcc_version_from_elf_files_in_giving_path_or_filename_s_path(path):
elf_files = []
if os.path.isdir(path):
elf_files = [os.path.join(path, f) for f in os.listdir(path) if f.endswith(".elf")]
elif os.path.isfile(path):
elf_files = [os.path.join(os.path.dirname(path), f) for f in os.listdir(os.path.dirname(path)) if
f.endswith(".elf")]
else:
print(
"gave path or filename is not valid") # didn't use except nor exit here cuz don't need to break compile if this is bad result anyway
gcc_versions = []
for elf_file in elf_files:
version_info = get_gcc_version_from_elf(elf_file)
if version_info is not None:
extract_elf_file_name = os.path.basename(elf_file)
gcc_versions.append("gcc version of " + extract_elf_file_name + " is " + version_info)
return gcc_versions
if len(sys.argv) != 4:
print(usage_message)
sys.exit(-1)
print(usage_message)
sys.exit(-1)
application_image = read_image(sys.argv[1])
baseband_image = read_image(sys.argv[2])
output_path = sys.argv[3]
print("\ncheck gcc versions from all elf target\n")
application_gcc_versions = get_gcc_version_from_elf_files_in_giving_path_or_filename_s_path(sys.argv[1])
baseband_gcc_versions = get_gcc_version_from_elf_files_in_giving_path_or_filename_s_path(sys.argv[2])
for itap in application_gcc_versions:
print(itap)
for itbb in baseband_gcc_versions:
print(itbb)
print("\n")
spi_size = 1048576
images = (
{
'name': 'application',
'data': application_image,
'size': len(application_image),
},
{
'name': 'baseband',
'data': baseband_image,
'size': len(baseband_image),
},
{
'name': 'application',
'data': application_image,
'size': len(application_image),
},
{
'name': 'baseband',
'data': baseband_image,
'size': len(baseband_image),
},
)
spi_image = bytearray()
spi_image_default_byte = bytearray((255,))
for image in images:
if len(image['data']) > image['size']:
raise RuntimeError('data for image "%(name)s" is longer than 0x%(size)x bytes 0x%(sz)x' % {'name':image['name'], 'size':image['size'], 'sz':len(image['data'])})
pad_size = image['size'] - len(image['data'])
padded_data = image['data'] + (spi_image_default_byte * pad_size)
spi_image += padded_data
if len(image['data']) > image['size']:
raise RuntimeError(
'data for image "%(name)s" is longer than 0x%(size)x bytes 0x%(sz)x' % {'name': image['name'],
'size': image['size'],
'sz': len(image['data'])})
pad_size = image['size'] - len(image['data'])
padded_data = image['data'] + (spi_image_default_byte * pad_size)
spi_image += padded_data
if len(spi_image) > spi_size - 4:
raise RuntimeError('SPI flash image size of %d exceeds device size of %d bytes' % (len(spi_image) + 4, spi_size))
raise RuntimeError('SPI flash image size of %d exceeds device size of %d bytes' % (len(spi_image) + 4, spi_size))
pad_size = spi_size - 4 - len(spi_image)
for i in range(pad_size):
spi_image += spi_image_default_byte
spi_image += spi_image_default_byte
# quick "add up the words" checksum, and check for possible references to code in external apps
checksum = 0
for i in range(0, len(spi_image), 4):
snippet = spi_image[i:i+4]
val = int.from_bytes(snippet, byteorder='little')
checksum += val
if (val >= external_apps_address_start) and (val < external_apps_address_end) and ((val & 0xFFFF) < maximum_application_size):
print ("WARNING: Possible external code address", hex(val), "at offset", hex(i), "in", sys.argv[3])
snippet = spi_image[i:i + 4]
val = int.from_bytes(snippet, byteorder='little')
checksum += val
if (val >= external_apps_address_start) and (val < external_apps_address_end) and (
(val & 0xFFFF) < maximum_application_size):
print("WARNING: Possible external code address", hex(val), "at offset", hex(i), "in", sys.argv[3])
final_checksum = 0
checksum = (final_checksum - checksum) & 0xFFFFFFFF
@@ -102,4 +160,4 @@ spi_image += checksum.to_bytes(4, 'little')
write_image(spi_image, output_path)
percent_remaining = round(1000 * pad_size / spi_size) / 10;
print ("Space remaining in flash ROM:", pad_size, "bytes (", percent_remaining, "%)")
print("Space remaining in flash ROM:", pad_size, "bytes (", percent_remaining, "%)")
+1 -1
Submodule hackrf updated: f5dd48a5bc...22c9ff10f9
@@ -0,0 +1 @@
Version 1.00 April 11, 2014, initial release
Binary file not shown.
@@ -0,0 +1 @@
This font was created using FontCreator 6.0 from High-Logic.com
@@ -0,0 +1 @@
Copyright (c) 2021 by Bung Letter. All rights reserved.
Binary file not shown.
@@ -0,0 +1 @@
Macromedia Fontographer 4.1 Gong! Normal
@@ -0,0 +1 @@
Copyright \251 2002, m klein fonteria. All rights reserved.
@@ -0,0 +1 @@
Copyright \251 2002, m klein fonteria. All rights reserved.
@@ -1 +0,0 @@
These fonts are for free and can be use for commercial and non-commercial purposes. These aren't professionally made--only beta test. Let me know if there are problems with spaces and kernings.
-93
View File
@@ -1,93 +0,0 @@
Copyright 2017 The Sedgwick Ave Project Authors (https://github.com/googlefonts/sedgwickave)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1 @@
Schwarzenegger Condensed:Version 1.10
@@ -0,0 +1 @@
Schwarzenegger:Version 1.10
@@ -0,0 +1 @@
This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is available with a FAQ at: http://scripts.sil.org/OFL
@@ -0,0 +1 @@
This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is available with a FAQ at: http://scripts.sil.org/OFL
@@ -0,0 +1 @@
:Smoke Weed normal
@@ -0,0 +1 @@
Free for personal use only. Please visit www.mawns.com for a commercial license.
Binary file not shown.
@@ -0,0 +1 @@
Copyright (c) M Klein 10-04
@@ -0,0 +1,56 @@
import os
import re
from fontTools.ttLib import TTFont
def get_longest_copyright(font):
decodable_copyrights = []
for name in font['name'].names:
try:
decoded_string = name.string.decode('utf-8')
if decoded_string:
decodable_copyrights.append(decoded_string)
except UnicodeDecodeError:
pass
if decodable_copyrights:
return max(decodable_copyrights, key=len)
else:
return None
def read_copyright_info(font_file):
try:
font = TTFont(font_file)
copyright_info = get_longest_copyright(font)
#decode copyright info, it has a lot of \x00, replace all those for nothing
if copyright_info:
return re.sub(r'\x00', '', copyright_info)
else:
print(f"Could not find any copyright info in {font_file}")
return None
except Exception as e:
print(f"Error reading copyright info from {font_file}: {e}")
return None
def write_license_file(font_file, copyright_info):
try:
base_name, ext = os.path.splitext(font_file)
license_file = f"{base_name}-info.txt"
with open(license_file, 'w') as f:
f.write(copyright_info)
print(f"License file written: {license_file}")
except Exception as e:
print(f"Error writing license file for {font_file}: {e}")
def main():
folder_path = os.path.dirname(__file__)
for filename in os.listdir(folder_path):
if filename.endswith('.ttf') or filename.endswith('.otf'):
font_file = os.path.join(folder_path, filename)
copyright_info = read_copyright_info(font_file)
if copyright_info:
write_license_file(font_file, copyright_info)
if __name__ == "__main__":
main()
@@ -0,0 +1 @@
Copyright (c) 2011 by wickhop. All rights reserved.
@@ -1 +0,0 @@
,dannybernecker,dannys-mbp.speedport_w_724v_typ_a_05011603_00_007,16.12.2015 04:43,file:///Users/dannybernecker/Library/Application%20Support/LibreOffice/4;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

@@ -1,94 +0,0 @@
Copyright (c) <2006>, <Punkto Design> (<http://charaktertypen.com | info@charaktertypen.com>),
with Reserved Font Name <„Beatstreet“>.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1 @@
Beatstreet is a trademark of Danny Bernecker.
@@ -0,0 +1 @@
If you would like to help support Larabie Fonts please consider making a donation. It costs a lot to keep the site running and free from irritating pop-up or banner ads. Any amount is appreciated and goes right back into making maintaining the site and developing more free fonts. Visit www.larabiefonts.com for details.
@@ -0,0 +1 @@
JohnGauthier: Fresh Marker: 2015
@@ -0,0 +1 @@
Ver 2 Gomarice Font 2005/08/02
-93
View File
@@ -1,93 +0,0 @@
Copyright (c) <2006>, <Punkto Design, D. Bernecker> (<http://charaktertypen.com | info@charaktertypen.com>), with Reserved Font Name <„Tagster“>.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
-143
View File
@@ -1,143 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=shift_jis">
<TITLE>LARABIE FONTS &ldquo;README</TITLE>
<META NAME="GENERATOR" CONTENT="StarOffice 8 (Win32)">
<META NAME="AUTHOR" CONTENT="Rina Larabie">
<META NAME="CREATED" CONTENT="20061130;11580000">
<META NAME="CHANGEDBY" CONTENT="Rina Larabie">
<META NAME="CHANGED" CONTENT="20061207;15120000">
<STYLE>
<!--
@page { size: 8.5in 11in; margin-right: 1.25in; margin-top: 1in; margin-bottom: 1in }
P { margin-bottom: 0.08in; direction: ltr; color: #000000; widows: 2; orphans: 2 }
P.western { font-family: "Times New Roman", serif; font-size: 12pt; so-language: en-US }
P.cjk { font-family: "Times New Roman", serif; font-size: 12pt }
P.ctl { font-family: "Times New Roman", serif; font-size: 12pt; so-language: ar-SA }
H3 { margin-top: 0.19in; margin-bottom: 0.19in; direction: ltr; color: #000000; widows: 2; orphans: 2; page-break-after: auto }
H3.western { font-size: 13pt; so-language: en-US }
H3.cjk { font-family: "Times New Roman", serif; font-size: 13pt }
H3.ctl { font-family: "Times New Roman", serif; font-size: 13pt; so-language: ar-SA }
A:link { color: #0000ff }
-->
</STYLE>
</HEAD>
<BODY LANG="en-US" TEXT="#000000" LINK="#0000ff" DIR="LTR">
<H3 CLASS="western" STYLE="margin-top: 0in"><FONT FACE="Tahoma, sans-serif">LARABIE
FONTS FREEWARE FONTS EULA (End User License Agreement) and SOFTWARE
INCLUSION AGREEMENT</FONT></H3>
<P CLASS="western" STYLE="margin-bottom: 0in"><B><FONT FACE="Tahoma, sans-serif">LARABIE
FONTS FREEWARE FONTS EULA</FONT></B></P>
<P CLASS="western" STYLE="margin-bottom: 0in"><BR>
</P>
<P CLASS="western" STYLE="margin-bottom: 0in"><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">Larabie
Fonts Freeware Fonts in TrueType format are free to use for personal
and commercial purposes. No payment is necessary to use Larabie Fonts
Freeware Fonts for personal or commercial use. If you wish to include
Larabie Fonts Freeware Fonts in software see SOFTWARE INCLUSION
AGREEMENT below. </FONT></FONT>
</P>
<P CLASS="western" STYLE="margin-bottom: 0in"><BR>
</P>
<P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Tahoma, sans-serif"><FONT SIZE=2><B>USAGE</B></FONT></FONT></P>
<P CLASS="western" STYLE="margin-bottom: 0in"><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">You
can offer individual Larabie Fonts Freeware Fonts for download on a
website but do not combine fonts into a single archive or alter them
in any way. We appreciate inclusion of the font name and trademark or
site URL in the credits or documentation but it is not mandatory. </FONT></FONT>
</P>
<P CLASS="western" STYLE="margin-bottom: 0in"><BR>
</P>
<P CLASS="western" STYLE="margin-bottom: 0in"><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">Some
Larabie Fonts Freeware Fonts may have enhanced and/or expanded
families available for sale at </FONT></FONT><FONT COLOR="#0000ff"><U><A HREF="http://www.typodermic.com/"><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">www.typodermic.com</FONT></FONT></A></U></FONT><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">.</FONT></FONT></P>
<P CLASS="western" STYLE="margin-bottom: 0in"><BR>
</P>
<P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Tahoma, sans-serif"><FONT SIZE=2><B>PAYMENT</B></FONT></FONT></P>
<P CLASS="western" STYLE="margin-bottom: 0in"><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">Payment
is not required for the use of Larabie Fonts Freeware Fonts unless
they are intended to be <I>included</I> with software. More details
follow.</FONT></FONT></P>
<P CLASS="western" STYLE="margin-bottom: 0in"><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">Donations
to Larabie Fonts are welcome via check or electronic payment via
Paypal. We can accept any amount in US dollars, Canadian dollars, GBP
or euros. If you require an invoice for your donation, please refer
to </FONT></FONT><FONT COLOR="#0000ff"><U><A HREF="http://www.larabiefonts.com/donation.html"><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">www.larabiefonts.com/donation.html</FONT></FONT></A></U></FONT><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">
for instructions. </FONT></FONT>
</P>
<P CLASS="western" STYLE="margin-bottom: 0in"><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">Donations
can include CDs, magazines, t-shirts, a sample of your merchandise or
anything featuring Larabie Fonts. Mailing information is available at
the link above.</FONT></FONT></P>
<P CLASS="western" STYLE="margin-bottom: 0in"><BR>
</P>
<P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Tahoma, sans-serif"><FONT SIZE=2><B>SUPPORT</B></FONT></FONT></P>
<P CLASS="western" STYLE="margin-bottom: 0in"><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">Font
installation help is available at </FONT></FONT><FONT COLOR="#0000ff"><U><A HREF="http://www.myfonts.com/support"><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">www.myfonts.com/support</FONT></FONT></A></U></FONT><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">.
If you experience problems with any Larabie Font, please visit
</FONT></FONT><FONT COLOR="#0000ff"><U><A HREF="http://www.larabiefonts.com/"><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">www.larabiefonts.com</FONT></FONT></A></U></FONT><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">
to verify you have the latest version. If you download Larabie Fonts
Freeware Fonts from other websites you may get older versions that
have spacing issues, incomplete character sets or technical problems.
</FONT></FONT>
</P>
<P CLASS="western" STYLE="margin-bottom: 0in"><BR>
</P>
<P CLASS="western" STYLE="margin-bottom: 0in"><B><FONT FACE="Tahoma, sans-serif">SOFTWARE
INCLUSION AGREEMENT </FONT></B>
</P>
<P CLASS="western" STYLE="margin-bottom: 0in"><BR>
</P>
<P CLASS="western" STYLE="margin-bottom: 0in"><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">The
Larabie Fonts SOFTWARE PRODUCT is protected by copyright laws and
International copyright treaties, as well as other intellectual
property laws and treaties. The SOFTWARE PRODUCT is licensed, not
sold.</FONT></FONT></P>
<P CLASS="western" STYLE="margin-bottom: 0in"><BR>
</P>
<P CLASS="western" STYLE="margin-bottom: 0in"><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">1.
GRANT OF LICENSE. This document grants you the following rights:</FONT></FONT></P>
<P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Tahoma, sans-serif"><FONT SIZE=2>-
Installation and Use. You may install and use an unlimited number of
copies of the SOFTWARE PRODUCT. You may copy and distribute unlimited
copies of the SOFTWARE PRODUCT as you receive them, in any medium,
provided that you publish on each copy an appropriate copyright
notice. Keep intact all the notices that refer to this License and
give any other recipients of the fonts a copy of this License along
with the fonts.</FONT></FONT></P>
<P CLASS="western" STYLE="margin-bottom: 0in"><BR>
</P>
<P CLASS="western" STYLE="margin-bottom: 0in"><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">2.
LIMITED WARRANTY NO WARRANTIES. Larabie Fonts expressly disclaims any
warranty for the SOFTWARE PRODUCT. The SOFTWARE PRODUCT and any
related documentation is provided &quot;as is&quot; without warranty
of any kind, either express or implied, including, without
limitation, the implied warranties or merchantability, fitness for a
particular purpose, or non-infringement. The entire risk arising out
of use or performance of the SOFTWARE PRODUCT remains with you.</FONT></FONT></P>
<P CLASS="western" STYLE="margin-bottom: 0in"><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">NO
LIABILITY FOR CONSEQUENTIAL DAMAGES. In no event shall Ray Larabie or
Larabie Fonts be liable for any damages whatsoever (including,
without limitation, damages for loss of business profits, business
interruption, loss of business information, or any other pecuniary
loss) arising out of the use of or inability to use this product,
even if Larabie Fonts has been advised of the possibility of such
damages.</FONT></FONT></P>
<P CLASS="western" STYLE="margin-bottom: 0in"><BR>
</P>
<P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Tahoma, sans-serif"><FONT SIZE=2>3.
MISCELLANEOUS</FONT></FONT></P>
<P CLASS="western" STYLE="margin-bottom: 0in"><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">Should
you have any questions concerning this document or you desire to
contact Larabie Fonts for any reason, please email
</FONT></FONT><FONT COLOR="#0000ff"><U><A HREF="http://www.larabiefonts.com/email.html"><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">www.larabiefonts.com/email.html</FONT></FONT></A></U></FONT><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">.</FONT></FONT></P>
<P CLASS="western" STYLE="margin-bottom: 0in"><BR>
</P>
<P CLASS="western" STYLE="margin-bottom: 0in"><FONT SIZE=2><FONT FACE="Tahoma, sans-serif">4.
GOVERNING LAW</FONT></FONT></P>
<P CLASS="western" STYLE="margin-bottom: 0in"><FONT FACE="Tahoma, sans-serif"><FONT SIZE=2>This
agreement is governed by the laws of Canada and the province of
British Columbia.</FONT></FONT></P>
</BODY>
</HTML>
@@ -0,0 +1 @@
Copyright (c) 2007 by Punkto Deisgn. All rights reserved.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 723 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 721 KiB