1
0
forked from me/IronOS

Compare commits

..

9 Commits

Author SHA1 Message Date
Ben V. Brown
7a0308dbf4 Generate layout structures 2023-06-29 20:53:22 +10:00
Ben V. Brown
c31fb5725b Fixing import loop 2023-06-29 20:26:00 +10:00
Ben V. Brown
7535a64bc7 Images 2023-06-29 18:51:40 +10:00
Ben V. Brown
b599dec278 Start on renderers 2023-06-29 18:46:34 +10:00
Ben V. Brown
3a05d695f8 More Font utils 2023-06-29 18:46:26 +10:00
Ben V. Brown
45639e5c23 Number Bounded draw 2023-06-29 18:46:19 +10:00
Ben V. Brown
da7dbd4b55 Move out FontStyle 2023-06-29 18:38:50 +10:00
Ben V. Brown
62fb6d5209 Starting to implement Elements 2023-06-28 23:14:09 +10:00
Ben V. Brown
d9350fdc73 Scratching out layout 2023-06-28 22:49:37 +10:00
49 changed files with 672 additions and 267 deletions

View File

@@ -37,4 +37,4 @@ jobs:
- run: git config user.name 'github-actions[bot]' && git config user.email 'github-actions[bot]@users.noreply.github.com' - run: git config user.name 'github-actions[bot]' && git config user.email 'github-actions[bot]@users.noreply.github.com'
- name: Publish docs - name: Publish docs
run: mkdocs gh-deploy -f scripts/IronOS-mkdocs.yml -d ../site run: mkdocs gh-deploy

View File

@@ -32,7 +32,7 @@ jobs:
- name: copy license text - name: copy license text
run: | run: |
cp LICENSE source/Hexfile/LICENSE cp LICENSE source/Hexfile/LICENSE
cp scripts/LICENSE_RELEASE.md source/Hexfile/LICENSE_RELEASE.md cp LICENSE_RELEASE.md source/Hexfile/LICENSE_RELEASE.md
- name: Archive ${{ matrix.model }} artifacts - name: Archive ${{ matrix.model }} artifacts
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
@@ -83,7 +83,7 @@ jobs:
- name: copy license text - name: copy license text
run: | run: |
cp LICENSE source/Hexfile/LICENSE cp LICENSE source/Hexfile/LICENSE
cp scripts/LICENSE_RELEASE.md source/Hexfile/LICENSE_RELEASE.md cp LICENSE_RELEASE.md source/Hexfile/LICENSE_RELEASE.md
- name: Archive ${{ matrix.model }} artifacts - name: Archive ${{ matrix.model }} artifacts
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3

1
.gitignore vendored
View File

@@ -178,3 +178,4 @@ CoreCompileInputs.cache
.vscode/settings.json .vscode/settings.json
source/compile_commands.json source/compile_commands.json
.idea/ .idea/
source/UI/layout_96x16.cpp

7
Bootup Logo/README.md Normal file
View File

@@ -0,0 +1,7 @@
# Bootup logo's
IronOS supports both a bootup logo _AND_ bootup animations.
However, they are no longer included in this repo.
[Please read the docs](https://ralim.github.io/IronOS/Logo/)

View File

Before

Width:  |  Height:  |  Size: 630 B

After

Width:  |  Height:  |  Size: 630 B

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -9,13 +9,13 @@ WORKDIR /build
# musl-dev is required for the multi lang firmwares # musl-dev is required for the multi lang firmwares
# clang is required for clang-format (for dev) # clang is required for clang-format (for dev)
ARG APK_COMPS="gcc-riscv-none-elf gcc-arm-none-eabi newlib-riscv-none-elf \ ARG APK_COMPS="gcc-riscv-none-elf gcc-arm-none-eabi newlib-riscv-none-elf \
newlib-arm-none-eabi" newlib-arm-none-eabi"
ARG APK_PYTHON="python3 py3-pip black" ARG APK_PYTHON="python3 py3-pip black"
ARG APK_MISC="findutils make git" ARG APK_MISC="findutils make git"
ARG APK_DEV="musl-dev clang bash clang-extra-tools" ARG APK_DEV="musl-dev clang bash clang-extra-tools"
# PIP packages # PIP packages
ARG PIP_PKGS='bdflib' ARG PIP_PKGS='bdflib pyyaml'
RUN apk add --no-cache ${APK_COMPS} ${APK_PYTHON} ${APK_MISC} ${APK_DEV} RUN apk add --no-cache ${APK_COMPS} ${APK_PYTHON} ${APK_MISC} ${APK_DEV}
@@ -26,4 +26,4 @@ RUN python3 -m pip install ${PIP_PKGS}
RUN git config --global --add safe.directory /build/source RUN git config --global --add safe.directory /build/source
COPY . /build/source COPY . /build/source
COPY ./scripts/ci /build/ci COPY ./ci /build/ci

View File

@@ -125,7 +125,7 @@ On Windows follow the instructions on the official documentation to install 'Win
```sh ```sh
cd IronOS cd IronOS
./scripts/deploy.sh ./start_dev.sh
``` ```
This script will build a Docker image and run a container with the necessary tools to build the firmware. This script will build a Docker image and run a container with the necessary tools to build the firmware.

View File

@@ -55,7 +55,7 @@ sgr1ff1n (Shane) commented in [issue 11](https://github.com/Ralim/IronOS/issues/
While in the past there were reports of unreliable upgrades, the consensus in [issue 11](https://github.com/Ralim/IronOS/issues/11) is that things work mostly as expected in Linux. While in the past there were reports of unreliable upgrades, the consensus in [issue 11](https://github.com/Ralim/IronOS/issues/11) is that things work mostly as expected in Linux.
@awigen has contributed a script [flash_ts100_linux.sh](https://raw.githubusercontent.com/Ralim/IronOS/dev/scripts/flash_ts100_linux.sh) that works on Ubuntu 16.04 as well as other distros. @awigen has contributed a script [flash_ts100_linux.sh](https://raw.githubusercontent.com/Ralim/IronOS/master/Flashing/flash_ts100_linux.sh) that works on Ubuntu 16.04 as well as other distros.
If you want to do it manually (or if the script does not work for some reason) the general procedure is the same as for Windows, the differences are in the way to mount the unit and copy the firmware. If you want to do it manually (or if the script does not work for some reason) the general procedure is the same as for Windows, the differences are in the way to mount the unit and copy the firmware.
Remember that after flashing, the firmware filename will have changed to end in `.RDY` or `.ERR` or `.NOT` and only `.RDY` means the flashing was successful! Remember that after flashing, the firmware filename will have changed to end in `.RDY` or `.ERR` or `.NOT` and only `.RDY` means the flashing was successful!

View File

@@ -55,7 +55,7 @@ sgr1ff1n (Shane) commented in [issue 11](https://github.com/Ralim/IronOS/issues/
While in the past there were reports of unreliable upgrades, the consensus in [issue 11](https://github.com/Ralim/IronOS/issues/11) is that things work mostly as expected in Linux. While in the past there were reports of unreliable upgrades, the consensus in [issue 11](https://github.com/Ralim/IronOS/issues/11) is that things work mostly as expected in Linux.
@awigen has contributed a script [flash_ts100_linux.sh](https://raw.githubusercontent.com/Ralim/IronOS/dev/scripts/flash_ts100_linux.sh) that works on Ubuntu 16.04 as well as other distros. @awigen has contributed a script [flash_ts100_linux.sh](https://raw.githubusercontent.com/Ralim/IronOS/master/Flashing/flash_ts100_linux.sh) that works on Ubuntu 16.04 as well as other distros.
If you want to do it manually (or if the script does not work for some reason) the general procedure is the same as for Windows, the differences are in the way to mount the unit and copy the firmware. If you want to do it manually (or if the script does not work for some reason) the general procedure is the same as for Windows, the differences are in the way to mount the unit and copy the firmware.
Remember that after flashing, the firmware filename will have changed to end in `.RDY` or `.ERR` or `.NOT` and only `.RDY` means the flashing was successful! Remember that after flashing, the firmware filename will have changed to end in `.RDY` or `.ERR` or `.NOT` and only `.RDY` means the flashing was successful!

125
Makefile
View File

@@ -1,125 +0,0 @@
#!/usr/bin/env make
INFO:=top-level Makefile for IronOS - Soldering Iron Open Source Firmware Project.
### global adjustable variables
# command for "docker compose" from DOCKER env. var.
ifdef DOCKER
DOCKER_BIN:=$(DOCKER)
else
DOCKER_BIN:=
endif
# detect availability of docker
ifndef DOCKER_BIN
DOCKER_COMPOSE:=$(shell command -v docker-compose 2>/dev/null)
DOCKER_TOOL:=$(shell command -v docker 2>/dev/null)
ifdef DOCKER_COMPOSE
DOCKER_BIN:=$(DOCKER_COMPOSE)
else ifdef DOCKER_TOOL
DOCKER_BIN:=$(DOCKER_TOOL) compose
else
$(error ERROR: Can't find docker-compose nor docker tool. Please, install docker and try again)
endif # DOCKER_* checks
endif # DOCKER_BIN
# command for python-based mkdocs tool
ifndef MKDOCS
MKDOCS:=mkdocs
endif
### global static variables
# docker-related files
DOCKER_YML=$(CURDIR)/Env.yml
DOCKER_FILE=$(CURDIR)/scripts/IronOS.Dockerfile
# docker dependencies
DOCKER_DEPS=$(DOCKER_YML) $(DOCKER_FILE)
# compose docker-compose command
DOCKER_CMD=$(DOCKER_BIN) -f $(DOCKER_YML) run --rm builder
# MkDocs config
MKDOCS_YML=$(CURDIR)/scripts/IronOS-mkdocs.yml
### targets
# default target to show help
help:
@echo
@echo "Welcome!\nThis is $(INFO)"
@echo "To read more about supported commands (aka \"targets\"), type \"make list\"."
@echo "But if you're impatient then just type \"make docker-build\" - it will:"
@echo "\t * download, configure & start docker container"
@echo "\t * compile builds of IronOS firmware for all supported models inside that container"
@echo "\t * export generated binaries to \"scripts/ci/artefacts/\" local directory"
@echo "Patches are welcome. Happy Hacking!"
@echo
# target to list supported targets with additional info
list:
@echo ""
@echo "Supported top-level targets:"
@echo "\t * help - shows short basic help"
@echo "\t * list - this output"
@echo "\t * docker-shell - start docker container with shell inside to work on IronOS with all tools needed"
@echo "\t * docker-build - compile builds of IronOS for supported models inside docker container and place them to \"scripts/ci/artefacts/\""
@echo "\t * docker-clean - delete created docker container (but not pre-downloaded data for it)"
@echo "\t * docs - generate \"site\"/ directory with documentation in a form of static html files using ReadTheDocs framework and $(MKDOCS_YML) local config file"
@echo "\t * docs-deploy - generate & deploy docs online to gh-pages branch of current github repo"
@echo "\t * clean-full - delete files & directories generated by all the targets above "
@echo ""
@echo "NOTES on supported pass-trough targets:"
@echo "\t * main Makefile is located in source/ directory and used to build the firmware itself;"
@echo "\t * this top-level Makefile supports to call targets from source/Makefile;"
@echo "\t * if you set up development environment right on your host, then to build firmware locally, you can just type right from here:"
@echo
@echo "\t> make firmware-LANG_ID model=MODEL_ID"
@echo
@echo "Full list of current supported IDs:"
@echo "\t * LANG_ID: BE BG CS DA DE EL EN ES FI FR HR HU IT JA_JP LT NB NL_BE NL PL PT RO RU SK SL SR_CYRL SR_LATN SV TR UK VI YUE_HK ZH_CN ZH_TW"
@echo "\t * MODEL_ID: TS100 TS101 TS80 TS80P MHP30 Pinecil Pinecilv2 S60"
@echo
@echo "For example, to make a local build of IronOS firmware for TS100 with English language, just type:"
@echo "\n\t> make firmware-EN model=TS100"
@echo
# bash one-liner to generate langs for "make list":
# echo "`ls Translations/ | grep -e "^translation_.*.json$" | sed -e 's,^translation_,,g; s,\.json$,,g; ' | tr '\n' ' '`"
# former start_dev.sh
docker-shell: $(DOCKER_DEPS)
$(DOCKER_CMD)
# former build.sh
docker-build: $(DOCKER_DEPS)
$(DOCKER_CMD) /bin/bash /build/ci/buildAll.sh
# delete container
docker-clean:
-docker rmi ironos-builder:latest
# generate docs in site/ directory (DIR for -d is relative to mkdocs.yml file location, hence use default name/location site by setting up ../site)
docs: $(MKDOCS_YML) Documentation/* Documentation/Flashing/* Documentation/images/*
$(MKDOCS) build -f $(MKDOCS_YML) -d ../site
# deploy docs to gh-pages branch of current repo automagically using ReadTheDocs framework
docs-deploy: $(MKDOCS_YML) Documentation/* Documentation/Flashing/* Documentation/images/*
$(MKDOCS) gh-deploy -f $(MKDOCS_YML) -d ../site
# pass-through target for Makefile inside source/ dir
%:
make -C source/ $@
# global clean-up target
clean-full: docker-clean
make -C source/ clean-all
rm -Rf site
rm -Rf scripts/ci/artefacts
.PHONY: docker-shell docker-build docker-clean docs clean-full

View File

@@ -67,15 +67,9 @@ For notes on installation for your device, please refer to the flashing guide fo
- Boost mode lets you temporarily change the temperature when soldering (i.e. raise the temperature for short periods) - Boost mode lets you temporarily change the temperature when soldering (i.e. raise the temperature for short periods)
- (TS100/Pinecil) Battery charge level indicator if power source set to a lipo cell count - (TS100/Pinecil) Battery charge level indicator if power source set to a lipo cell count
- (TS80/TS80P/Pinecil) Power bank operating voltage is displayed - (TS80/TS80P/Pinecil) Power bank operating voltage is displayed
- [Custom boot up logo support](https://ralim.github.io/IronOS/Logo/)[^bootlogo] - [Custom boot up logo support](https://ralim.github.io/IronOS/Logo/)
- Automatic LCD rotation based on the orientation - Automatic LCD rotation based on the orientation
[^bootlogo]: **BOOTUP LOGO NOTICE**:
IronOS supports both a bootup logo _AND_ bootup animations.
However, _**they are no longer included in this repo**_.
**Please, [read the docs](https://ralim.github.io/IronOS/Logo/) for more information**.
## Menu System ## Menu System
This new firmware uses a new menu system to allow access to the settings on the device. This new firmware uses a new menu system to allow access to the settings on the device.

View File

@@ -282,7 +282,7 @@
}, },
"PowerLimit": { "PowerLimit": {
"displayText": "Leistungs-\nmaximum", "displayText": "Leistungs-\nmaximum",
"description": "Durchschnittliche maximal zulässige Leistungsaufnahme des Lötkolbens (W=Watt)" "description": "Maximal zulässige Leistungsaufnahme des Lötkolbens (W=Watt)"
}, },
"CalibrateCJC": { "CalibrateCJC": {
"displayText": "Temperatur\nkalibrieren", "displayText": "Temperatur\nkalibrieren",

View File

@@ -282,7 +282,7 @@
}, },
"PowerLimit": { "PowerLimit": {
"displayText": "Power\nlimit", "displayText": "Power\nlimit",
"description": "Average maximum power the iron can use (W=watt)" "description": "Maximum power the iron can use (W=watt)"
}, },
"CalibrateCJC": { "CalibrateCJC": {
"displayText": "Calibrate CJC\nat next boot", "displayText": "Calibrate CJC\nat next boot",

View File

@@ -282,7 +282,7 @@
}, },
"PowerLimit": { "PowerLimit": {
"displayText": "Power\nlimit", "displayText": "Power\nlimit",
"description": "Average maximum power the iron can use (W=watt)" "description": "Maximum power the iron can use (W=watt)"
}, },
"CalibrateCJC": { "CalibrateCJC": {
"displayText": "Calibrate CJC\nat next boot", "displayText": "Calibrate CJC\nat next boot",

View File

@@ -282,7 +282,7 @@
}, },
"PowerLimit": { "PowerLimit": {
"displayText": "Power\nlimit", "displayText": "Power\nlimit",
"description": "Average maximum power the iron can use (W=watt)" "description": "Maximum power the iron can use (W=watt)"
}, },
"CalibrateCJC": { "CalibrateCJC": {
"displayText": "Calibrate CJC\nat next boot", "displayText": "Calibrate CJC\nat next boot",

View File

@@ -282,7 +282,7 @@
}, },
"PowerLimit": { "PowerLimit": {
"displayText": "Power\nlimit", "displayText": "Power\nlimit",
"description": "Average maximum power the iron can use (W=watt)" "description": "Maximum power the iron can use (W=watt)"
}, },
"CalibrateCJC": { "CalibrateCJC": {
"displayText": "Calibrate CJC\nat next boot", "displayText": "Calibrate CJC\nat next boot",

2
build.sh Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
docker-compose run --rm builder /bin/bash /build/ci/buildAll.sh

View File

@@ -6,8 +6,7 @@ services:
tty: true tty: true
build: build:
context: . context: .
dockerfile: scripts/IronOS.Dockerfile
command: /bin/sh command: /bin/sh
volumes: volumes:
- ./scripts/ci:/build/ci:Z - ./ci:/build/ci:Z
- ./:/build/source:Z - ./:/build/source:Z

View File

@@ -6,7 +6,7 @@ site_description: "IronOS Open Source Soldering Iron firmware for Miniware and P
# repo config # repo config
repo_url: https://github.com/ralim/IronOS/ repo_url: https://github.com/ralim/IronOS/
docs_dir: ../Documentation docs_dir: Documentation
edit_uri: edit/dev/Documentation/ edit_uri: edit/dev/Documentation/
# Theme and config # Theme and config

View File

@@ -1,90 +0,0 @@
#!/usr/bin/env bash
# little helper for docker deployment to:
# - start development environment for IronOS ("shell" sub-command)
# - generate full set of builds ("build" sub-command)
#set -x
#set -e
usage()
{
echo -e "\nUsage: ${0} [CMD]\n"
echo "CMD:"
echo -e "\tshell - start docker container with shell inside to work on IronOS with all tools needed"
echo -e "\tbuild - compile builds of IronOS inside docker container for supported hardware"
echo -e "\tclean - delete created docker container (but not pre-downloaded data for it)\n"
echo -e "STORAGE NOTICE: for \"shell\" and \"build\" commands extra files will be downloaded so make sure that you have ~5GB of free space.\n"
}
### main
docker_conf="Env.yml"
# allow providing custom path to docker tool using DOCKER_BIN external env. var.
# (compose sub-command must be included, i.e. DOCKER_BIN="/usr/local/bin/docker compose" ./deploy.sh)
if [ -z "${DOCKER_BIN}" ]; then
docker_bin=""
else
docker_bin="${DOCKER_BIN}"
fi;
# detect availability of docker
docker_compose="$(command -v docker-compose)"
if [ -n "${docker_compose}" ] && [ -z "${docker_bin}" ]; then
docker_bin="${docker_compose}"
fi;
docker_tool="$(command -v docker)"
if [ -n "${docker_tool}" ] && [ -z "${docker_bin}" ]; then
docker_bin="${docker_tool} compose"
fi;
if [ -z "${docker_bin}" ]; then
echo "ERROR: Can't find docker-compose nor docker tool. Please, install docker and try again."
exit 1
fi;
# construct command to run
cmd="${1}"
if [ -z "${cmd}" ] || [ "${cmd}" = "shell" ]; then
docker_cmd="run --rm builder"
elif [ "${cmd}" = "build" ]; then
docker_cmd="run --rm builder /bin/bash /build/ci/buildAll.sh"
elif [ "${cmd}" = "clean" ]; then
docker rmi ironos-builder:latest
exit "${?}"
else
usage
exit 1
fi;
# get absolute location of project root dir to make docker happy with config(s)
# (successfully tested on relatively POSIX-compliant Dash shell)
# this script
script_file="/deploy.sh"
# IronOS/scripts/deploy.sh
script_path="${PWD}"/"${0}"
# IronOS/scripts/
script_dir=${script_path%"${script_file}"}
# IronOS/
root_dir="${script_dir}/.."
# IronOS/Env.yml
docker_file="-f ${root_dir}/${docker_conf}"
# change dir to project root dir & run constructed command
cd "${root_dir}" || exit 1
echo -e "\n====>>>> Firing up & starting container..."
if [ "${cmd}" = "shell" ]; then
echo -e "\t* type \"exit\" to end the session when done;"
fi;
echo -e "\t* type \"${0} clean\" to delete created container (but not cached data)"
echo -e "\n====>>>> ${docker_bin} ${docker_file} ${docker_cmd}\n"
eval "${docker_bin} ${docker_file} ${docker_cmd}"
exit "${?}"

View File

@@ -33,7 +33,7 @@
#define SOFT_I2C_DELAY() \ #define SOFT_I2C_DELAY() \
{ \ { \
for (int xx = 0; xx < 15; xx++) { \ for (int xx = 0; xx < 10; xx++) { \
asm("nop"); \ asm("nop"); \
} \ } \
} }

View File

@@ -136,8 +136,7 @@
#define POWER_LIMIT_STEPS 5 // #define POWER_LIMIT_STEPS 5 //
#define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_PINECIL // Uses TS100 resistors #define OP_AMP_GAIN_STAGE OP_AMP_GAIN_STAGE_PINECIL // Uses TS100 resistors
#define TEMP_uV_LOOKUP_HAKKO // Use Hakko lookup table #define TEMP_uV_LOOKUP_HAKKO // Use Hakko lookup table
#define USB_PD_VMAX 24 // Maximum voltage for PD to negotiate #define USB_PD_VMAX 20 // Maximum voltage for PD to negotiate
#define POW_EPR 1 // EPR mode is tentatively enabled
#define PID_TIM_HZ (8) // Tick rate of the PID loop #define PID_TIM_HZ (8) // Tick rate of the PID loop
#define MAX_TEMP_C 450 // Max soldering temp selectable °C #define MAX_TEMP_C 450 // Max soldering temp selectable °C
#define MAX_TEMP_F 850 // Max soldering temp selectable °F #define MAX_TEMP_F 850 // Max soldering temp selectable °F

View File

@@ -32,7 +32,7 @@ uint32_t OLED::displayChecksum;
I2C_CLASS::I2C_REG OLED_Setup_Array[] = { I2C_CLASS::I2C_REG OLED_Setup_Array[] = {
/**/ /**/
{0x80, 0xAE, 0}, /*Display off*/ {0x80, 0xAE, 0}, /*Display off*/
{0x80, OLED_DIVIDER, 0}, /*Set display clock divide ratio / osc freq*/ {0x80, 0xD3, 0}, /*Set display clock divide ratio / osc freq*/
{0x80, 0x52, 0}, /*Divide ratios*/ {0x80, 0x52, 0}, /*Divide ratios*/
{0x80, 0xA8, 0}, /*Set Multiplex Ratio*/ {0x80, 0xA8, 0}, /*Set Multiplex Ratio*/
{0x80, OLED_HEIGHT - 1, 0}, /*Multiplex ratio adjusts how far down the matrix it scans*/ {0x80, OLED_HEIGHT - 1, 0}, /*Multiplex ratio adjusts how far down the matrix it scans*/
@@ -90,7 +90,7 @@ const uint8_t REFRESH_COMMANDS[17] = {
0x80, 0x80,
0x00, // A 0x00, // A
0x80, 0x80,
(OLED_HEIGHT / 8) - 1, // B (OLED_HEIGHT / 8), // B
// Start of data // Start of data
0x40, 0x40,
@@ -127,7 +127,6 @@ void OLED::initialize() {
#endif #endif
displayOffset = 0; displayOffset = 0;
memcpy(&screenBuffer[0], &REFRESH_COMMANDS[0], sizeof(REFRESH_COMMANDS)); memcpy(&screenBuffer[0], &REFRESH_COMMANDS[0], sizeof(REFRESH_COMMANDS));
memcpy(&secondFrameBuffer[0], &REFRESH_COMMANDS[0], sizeof(REFRESH_COMMANDS));
// Set the display to be ON once the settings block is sent and send the // Set the display to be ON once the settings block is sent and send the
// initialisation data to the OLED. // initialisation data to the OLED.
@@ -170,6 +169,7 @@ void OLED::drawChar(const uint16_t charCode, const FontStyle fontStyle) {
case FontStyle::SMALL: case FontStyle::SMALL:
case FontStyle::LARGE: case FontStyle::LARGE:
default: default:
// TODO handle 4 lines
if (charCode == '\x01' && cursor_y == 0) { // 0x01 is used as new line char if (charCode == '\x01' && cursor_y == 0) { // 0x01 is used as new line char
setCursor(0, 8); setCursor(0, 8);
return; return;
@@ -272,7 +272,7 @@ void OLED::transitionSecondaryFramebuffer(bool forwardNavigation) {
TickType_t duration = 0; TickType_t duration = 0;
TickType_t start = xTaskGetTickCount(); TickType_t start = xTaskGetTickCount();
uint8_t offset = 0; uint8_t offset = 0;
TickType_t startDraw = xTaskGetTickCount();
while (duration <= totalDuration) { while (duration <= totalDuration) {
duration = xTaskGetTickCount() - start; duration = xTaskGetTickCount() - start;
uint16_t progress = ((duration * 100) / totalDuration); // Percentage of the period we are through for animation uint16_t progress = ((duration * 100) / totalDuration); // Percentage of the period we are through for animation
@@ -309,8 +309,9 @@ void OLED::transitionSecondaryFramebuffer(bool forwardNavigation) {
memmove(&stripPointers[3][newStart], &stripBackPointers[3][newEnd], progress); memmove(&stripPointers[3][newStart], &stripBackPointers[3][newEnd], progress);
#endif #endif
TickType_t start = xTaskGetTickCount();
refresh(); // Now refresh to write out the contents to the new page refresh(); // Now refresh to write out the contents to the new page
vTaskDelayUntil(&startDraw, TICKS_100MS / 7); vTaskDelayUntil(&start, TICKS_100MS / 7);
if (getButtonState() != BUTTON_NONE) { if (getButtonState() != BUTTON_NONE) {
return; return;
} }
@@ -332,7 +333,6 @@ void OLED::useSecondaryFramebuffer(bool useSecondary) {
* **This function blocks until the transition has completed or user presses button** * **This function blocks until the transition has completed or user presses button**
*/ */
void OLED::transitionScrollDown() { void OLED::transitionScrollDown() {
TickType_t startDraw = xTaskGetTickCount();
for (uint8_t heightPos = 0; heightPos < OLED_HEIGHT; heightPos++) { for (uint8_t heightPos = 0; heightPos < OLED_HEIGHT; heightPos++) {
// For each line, we shuffle all bits up a row // For each line, we shuffle all bits up a row
@@ -375,8 +375,9 @@ void OLED::transitionScrollDown() {
refresh(); // Now refresh to write out the contents to the new page refresh(); // Now refresh to write out the contents to the new page
return; return;
} }
TickType_t start = xTaskGetTickCount();
refresh(); // Now refresh to write out the contents to the new page refresh(); // Now refresh to write out the contents to the new page
vTaskDelayUntil(&startDraw, TICKS_100MS / 7); vTaskDelayUntil(&start, TICKS_100MS / 7);
} }
} }
@@ -431,6 +432,57 @@ void OLED::setInverseDisplay(bool inverse) {
OLED_Setup_Array[21].val = normalInverseCmd; OLED_Setup_Array[21].val = normalInverseCmd;
I2C_CLASS::I2C_RegisterWrite(DEVICEADDR_OLED, 0x80, normalInverseCmd); I2C_CLASS::I2C_RegisterWrite(DEVICEADDR_OLED, 0x80, normalInverseCmd);
} }
void OLED::printBounded(const char *str, const uint8_t x, const uint8_t y, const uint8_t w, const uint8_t h, FontStyle fontStyle) {
setCursor(x, y);
const uint8_t *next = reinterpret_cast<const uint8_t *>(str);
// Determine font size by newline magic marker
if (fontStyle == FontStyle::FROM_TEXT) {
fontStyle = FontStyle::SMALL;
if (next[0] == 0x01) {
fontStyle = FontStyle::LARGE;
next++;
}
} else if (fontStyle == FontStyle::FROM_HEIGHT) {
if (h > get_fontstyle_height(FontStyle::SMALL)) {
fontStyle = FontStyle::LARGE;
} else {
fontStyle = FontStyle::SMALL;
}
}
// Now we walk and print
while (next[0]) {
uint16_t index;
if (next[0] <= 0xF0) {
index = next[0];
next++;
} else {
if (!next[1]) {
return;
}
index = (next[0] - 0xF0) * 0xFF - 15 + next[1];
next += 2;
}
if (index > 0x01) {
// Not a newline or terminator
// Need to make sure we clip
if (cursor_x >= (x + w)) {
// About to write out of bounds, wrap
if (fontStyle == FontStyle::SMALL) {
cursor_y += 8;
} else {
cursor_y += 16;
}
}
if (cursor_y >= y + h) {
// Clipping off bottom, yeet
return;
}
}
drawChar(index, fontStyle);
}
}
// print a string to the current cursor location, len chars MAX // print a string to the current cursor location, len chars MAX
void OLED::print(const char *const str, FontStyle fontStyle, uint8_t len) { void OLED::print(const char *const str, FontStyle fontStyle, uint8_t len) {
@@ -493,6 +545,25 @@ void OLED::drawHex(uint32_t x, FontStyle fontStyle, uint8_t digits) {
drawChar(value + 2, fontStyle); drawChar(value + 2, fontStyle);
} }
} }
void OLED::printNumberBounded(const uint16_t num, bool noLeaderZeros, const uint8_t x, const uint8_t y, const uint8_t w, const uint8_t h) {
// Print the number to the screen, bounded by the given dimension
FontStyle fontStyle = get_fontstyle_fromHeight(h);
uint8_t places = w / get_fontstyle_width(fontStyle);
if (places > 5)
places = 5;
char buffer[7] = {0, 0, 0, 0, 0, 0, 0};
uint16_t number = num;
for (int i = places; i >= 0; i--) {
buffer[i] = 2 /*Skew past null and newline*/ + number % 10;
number /= 10;
}
if (noLeaderZeros)
stripLeaderZeros(buffer, places);
printBounded(buffer, x, y, w, h, FontStyle::FROM_HEIGHT);
}
// maximum places is 5 // maximum places is 5
void OLED::printNumber(uint16_t number, uint8_t places, FontStyle fontStyle, bool noLeaderZeros) { void OLED::printNumber(uint16_t number, uint8_t places, FontStyle fontStyle, bool noLeaderZeros) {
char buffer[7] = {0}; char buffer[7] = {0};

View File

@@ -10,6 +10,7 @@
#ifndef OLED_HPP_ #ifndef OLED_HPP_
#define OLED_HPP_ #define OLED_HPP_
#include "Font.h" #include "Font.h"
#include "FontUtils.h"
#include "cmsis_os.h" #include "cmsis_os.h"
#include "configuration.h" #include "configuration.h"
#include <BSP.h> #include <BSP.h>
@@ -46,7 +47,6 @@ extern "C" {
#define OLED_VCOM_LAYOUT 0x12 #define OLED_VCOM_LAYOUT 0x12
#define OLED_SEGMENT_MAP_REVERSED #define OLED_SEGMENT_MAP_REVERSED
#define OLED_DIVIDER 0xD3
#else #else
#define OLED_WIDTH 96 #define OLED_WIDTH 96
#define OLED_HEIGHT 16 #define OLED_HEIGHT 16
@@ -56,18 +56,12 @@ extern "C" {
#define OLED_GRAM_END 0x7F #define OLED_GRAM_END 0x7F
#define OLED_GRAM_START_FLIP 0 #define OLED_GRAM_START_FLIP 0
#define OLED_GRAM_END_FLIP 95 #define OLED_GRAM_END_FLIP 95
#define OLED_DIVIDER 0xD5
#define OLED_SEGMENT_MAP 0xA0 #define OLED_SEGMENT_MAP 0xA0
#endif #endif
#define FRAMEBUFFER_START 17 #define FRAMEBUFFER_START 17
enum class FontStyle {
SMALL,
LARGE,
EXTRAS,
};
class OLED { class OLED {
public: public:
enum DisplayState : bool { OFF = false, ON = true }; enum DisplayState : bool { OFF = false, ON = true };
@@ -107,8 +101,13 @@ public:
static void setBrightness(uint8_t contrast); static void setBrightness(uint8_t contrast);
static void setInverseDisplay(bool inverted); static void setInverseDisplay(bool inverted);
static int16_t getCursorX() { return cursor_x; } static int16_t getCursorX() { return cursor_x; }
static void print(const char *string, FontStyle fontStyle, uint8_t length = 255); // Draw a string to the current location, with selected font; optionally - with MAX length only
static void printWholeScreen(const char *string); static void printBounded(const char *str, const uint8_t x, const uint8_t y, const uint8_t w, const uint8_t h, FontStyle fontStyle = FontStyle::FROM_TEXT);
static void printNumberBounded(const uint16_t num, bool noLeaderZeros, const uint8_t x, const uint8_t y, const uint8_t w, const uint8_t h);
static void print(const char *string, FontStyle fontStyle,
uint8_t length = 255); // Draw a string to the current location, with selected font; optionally - with MAX length only
static void printWholeScreen(const char *string);
// Set the cursor location by pixels // Set the cursor location by pixels
static void setCursor(int16_t x, int16_t y) { static void setCursor(int16_t x, int16_t y) {
cursor_x = x; cursor_x = x;

View File

@@ -119,7 +119,8 @@ bool parseCapabilitiesArray(const uint8_t numCaps, uint8_t *bestIndex, uint16_t
*bestIndex = 0xFF; // Mark unselected *bestIndex = 0xFF; // Mark unselected
*bestVoltage = 5000; // Default 5V *bestVoltage = 5000; // Default 5V
uint8_t tipResistance = getTipResistanceX10(); // Fudge of 0.5 ohms to round up a little to account for us always having off periods in PWM
uint8_t tipResistance = getTipResistanceX10() + 5;
#ifdef MODEL_HAS_DCDC #ifdef MODEL_HAS_DCDC
// If this device has step down DC/DC inductor to smooth out current spikes // If this device has step down DC/DC inductor to smooth out current spikes
// We can instead ignore resistance and go for max voltage we can accept; and rely on the DC/DC regulation to keep under current limit // We can instead ignore resistance and go for max voltage we can accept; and rely on the DC/DC regulation to keep under current limit
@@ -286,9 +287,7 @@ bool pdbs_dpm_evaluate_capability(const pd_msg *capabilities, pd_msg *request) {
// We dont do usb // We dont do usb
// request->obj[0] |= PD_RDO_USB_COMMS; // request->obj[0] |= PD_RDO_USB_COMMS;
#ifdef POW_EPR #ifdef POW_EPR
if (USBPowerDelivery::isVBUSConnected() == false ) { request->obj[0] |= PD_RDO_EPR_CAPABLE;
request->obj[0] |= PD_RDO_EPR_CAPABLE;
}
#endif #endif
/* Update requested voltage */ /* Update requested voltage */

View File

@@ -0,0 +1,13 @@
#pragma once
#include <stdint.h>
enum class FontStyle {
SMALL,
LARGE,
EXTRAS,
FROM_TEXT, // Magically pick from the text
FROM_HEIGHT, // Pick font to best fill the height
};
constexpr uint8_t get_fontstyle_height(const FontStyle font);
constexpr uint8_t get_fontstyle_width(const FontStyle font);
constexpr FontStyle get_fontstyle_fromHeight(const uint8_t height);

View File

@@ -0,0 +1,14 @@
#include "FontUtils.h"
constexpr uint8_t get_fontstyle_height(const FontStyle font) {
if (font == FontStyle::SMALL)
return 8;
return 16;
}
constexpr uint8_t get_fontstyle_width(const FontStyle font) {
if (font == FontStyle::SMALL)
return 6;
return 12;
}
constexpr FontStyle get_fontstyle_fromHeight(const uint8_t height) { return (height <= 8) ? FontStyle::SMALL : FontStyle::LARGE; }

View File

@@ -171,6 +171,7 @@ SOURCE_DRIVERS_DIR = ./Core/Drivers
INC_PD_DRIVERS_DIR = ./Core/Drivers/usb-pd/include INC_PD_DRIVERS_DIR = ./Core/Drivers/usb-pd/include
PD_DRIVER_TESTS_DIR = ./Core/Drivers/usb-pd/tests PD_DRIVER_TESTS_DIR = ./Core/Drivers/usb-pd/tests
PD_DRIVER_DIR = ./Core/Drivers/usb-pd PD_DRIVER_DIR = ./Core/Drivers/usb-pd
UI_DIR = ./UI
# Find-all's used for formatting; have to exclude external modules # Find-all's used for formatting; have to exclude external modules
@@ -419,6 +420,7 @@ INCLUDES = -I$(APP_INC_DIR) \
-I$(FRTOS_INC_DIR) \ -I$(FRTOS_INC_DIR) \
-I$(DRIVER_INC_DIR) \ -I$(DRIVER_INC_DIR) \
-I$(BSP_INC_DIR) \ -I$(BSP_INC_DIR) \
-I$(UI_DIR) \
-I$(THREADS_INC_DIR) \ -I$(THREADS_INC_DIR) \
-I$(THREADS_OP_MODES_INC_DIR) \ -I$(THREADS_OP_MODES_INC_DIR) \
-I$(THREADS_OP_MODES_TOOLS_INC_DIR) \ -I$(THREADS_OP_MODES_TOOLS_INC_DIR) \
@@ -433,6 +435,7 @@ EXCLUDED_DIRS := -path $(PINECILV2_VENDOR_BSP_ES8388_DIR) \
-o -path $(PINECILV2_VENDOR_BSP_USB_DIR) \ -o -path $(PINECILV2_VENDOR_BSP_USB_DIR) \
SOURCE := $(shell find $(SOURCE_THREADS_DIR) -type f -name '*.c') \ SOURCE := $(shell find $(SOURCE_THREADS_DIR) -type f -name '*.c') \
$(shell find $(UI_DIR) -type f -name '*.c') \
$(shell find $(SOURCE_CORE_DIR) -type f -name '*.c') \ $(shell find $(SOURCE_CORE_DIR) -type f -name '*.c') \
$(shell find $(SOURCE_DRIVERS_DIR) -type f -name '*.c') \ $(shell find $(SOURCE_DRIVERS_DIR) -type f -name '*.c') \
$(shell find $(DEVICE_BSP_DIR) -type d \( $(EXCLUDED_DIRS) \) -prune -false -o -type f -name '*.c')\ $(shell find $(DEVICE_BSP_DIR) -type d \( $(EXCLUDED_DIRS) \) -prune -false -o -type f -name '*.c')\
@@ -441,6 +444,7 @@ $(SOURCE_BRIEFLZ_DIR)/depack.c
# We exclude the USB-PD stack tests $(PD_DRIVER_TESTS_DIR) # We exclude the USB-PD stack tests $(PD_DRIVER_TESTS_DIR)
SOURCE_CPP := $(shell find $(SOURCE_THREADS_DIR) -type f -name '*.cpp') \ SOURCE_CPP := $(shell find $(SOURCE_THREADS_DIR) -type f -name '*.cpp') \
$(shell find $(SOURCE_CORE_DIR) -type f -name '*.cpp') \ $(shell find $(SOURCE_CORE_DIR) -type f -name '*.cpp') \
$(shell find $(UI_DIR) -type f -name '*.cpp') \
$(shell find $(SOURCE_DRIVERS_DIR) -path $(PD_DRIVER_TESTS_DIR) -prune -false -o -type f -name '*.cpp') \ $(shell find $(SOURCE_DRIVERS_DIR) -path $(PD_DRIVER_TESTS_DIR) -prune -false -o -type f -name '*.cpp') \
$(shell find $(DEVICE_BSP_DIR) -type d \( $(EXCLUDED_DIRS) \) -prune -false -o -type f -name '*.cpp') \ $(shell find $(DEVICE_BSP_DIR) -type d \( $(EXCLUDED_DIRS) \) -prune -false -o -type f -name '*.cpp') \
$(shell find $(SOURCE_MIDDLEWARES_DIR) -type f -name '*.cpp') $(shell find $(SOURCE_MIDDLEWARES_DIR) -type f -name '*.cpp')

8
source/UI/UI.cpp Normal file
View File

@@ -0,0 +1,8 @@
#include "UI.h"
#include "OLED.hpp"
void ui_render_screen(screenLayout_t *screen, ScreenContext_t *context) {
// Walk the struct associated to the screen, calling render for each element of the screen
// Then start OLED refresh
OLED::refresh();
}

16
source/UI/UI.h Normal file
View File

@@ -0,0 +1,16 @@
#pragma once
#include "UI_Layouts.h"
#include <stdint.h>
typedef union {
int32_t i32;
void *ptr;
} screen_arg_t;
typedef struct {
screen_arg_t args[4];
} ScreenContext_t;
//
void ui_render_screen(screenLayout_t *screen, ScreenContext_t *context);
void ui_render_element(const ElementTypes_t element, const ElementSettings_t *settings, screen_arg_t *args);

77
source/UI/UI_Elements.cpp Normal file
View File

@@ -0,0 +1,77 @@
#include "UI_Elements.h"
#include "FontUtils.h"
#include "OLED.hpp"
#include "UI.h"
void render_Text(const ElementSettings_t *settings, screen_arg_t *args);
void render_Number(const ElementSettings_t *settings, screen_arg_t *args);
void render_Image(const ElementSettings_t *settings, screen_arg_t *args);
void render_PowerSource(const ElementSettings_t *settings, screen_arg_t *args);
void render_Temperature(const ElementSettings_t *settings, screen_arg_t *args);
void render_InputVoltage(const ElementSettings_t *settings, screen_arg_t *args);
void render_ScrollBar(const ElementSettings_t *settings, screen_arg_t *args);
void render_CheckBox(const ElementSettings_t *settings, screen_arg_t *args);
void render_TextScroller(const ElementSettings_t *settings, screen_arg_t *args);
void ui_render_element(const ElementTypes_t element, const ElementSettings_t *settings, screen_arg_t *args) {
switch (element) {
case ElementTypes_t::Text:
render_Text(settings, args);
break;
case ElementTypes_t::Number:
render_Number(settings, args);
break;
case ElementTypes_t::Image:
render_Image(settings, args);
break;
case ElementTypes_t::PowerSource:
render_PowerSource(settings, args);
break;
case ElementTypes_t::Temperature:
render_Temperature(settings, args);
break;
case ElementTypes_t::InputVoltage:
render_InputVoltage(settings, args);
break;
case ElementTypes_t::ScrollBar:
render_ScrollBar(settings, args);
break;
case ElementTypes_t::CheckBox:
render_CheckBox(settings, args);
break;
case ElementTypes_t::TextScroller:
render_TextScroller(settings, args);
break;
}
}
void render_Text(const ElementSettings_t *settings, screen_arg_t *args) {
// Draw text clipped into bounds
// Args shall be a pointer to an encoded string
OLED::printBounded((const char *)args->ptr, settings->position.x, settings->position.y, settings->size.w, settings->size.h);
}
void render_Number(const ElementSettings_t *settings, screen_arg_t *args) {
// Arg is an int32 of the number to display
OLED::printNumberBounded(args->i32, true, settings->position.x, settings->position.y, settings->size.w, settings->size.h);
}
void render_Image(const ElementSettings_t *settings, screen_arg_t *args) {
// arg is a pointer to the raw image data to display
OLED::drawArea(settings->position.x, settings->position.y, settings->size.w, settings->size.h, (uint8_t *)args->ptr);
}
void render_PowerSource(const ElementSettings_t *settings, screen_arg_t *args) {
//
}
void render_Temperature(const ElementSettings_t *settings, screen_arg_t *args) {
//
}
void render_InputVoltage(const ElementSettings_t *settings, screen_arg_t *args) {
//
}
void render_ScrollBar(const ElementSettings_t *settings, screen_arg_t *args) {
//
}
void render_CheckBox(const ElementSettings_t *settings, screen_arg_t *args) {
//
}
void render_TextScroller(const ElementSettings_t *settings, screen_arg_t *args) {
//
}

26
source/UI/UI_Elements.h Normal file
View File

@@ -0,0 +1,26 @@
#pragma once
#include <stdint.h>
typedef enum {
Text, // Basic text splat, using re-encoded strings
Number, // Draws numbers using best size for the height (always one line)
Image, // Pre-rendered bitmap that can be memcpy'ed in
PowerSource, // Draws a battery icon, or text for voltage, or DC power plug
Temperature, // Draws the number with temperature symbol following (height picks font)
InputVoltage, // Draws the number with V following and also 1 dp(height picks font)
ScrollBar, // Draws a vertical scrollbar, number sets percentage 0-100
CheckBox, // Draws checkbox, ticked = number!=0
TextScroller, // Renders text, scrolling with time
} ElementTypes_t;
typedef struct {
struct {
uint8_t x;
uint8_t y;
} position;
struct {
uint8_t w;
uint8_t h;
} size;
} ElementSettings_t;

26
source/UI/UI_Layouts.h Normal file
View File

@@ -0,0 +1,26 @@
#pragma once
#include "UI_Elements.h"
typedef enum {
SimplifiedHome, // Basic home
SimplifiedHomeWarning, // Home with temp warning
DetailedHome, // Detailed home view
DetailedHomeWarning, // Home with temp warning
DebugView, // Debugging metrics
settingsCategory, // Settings category with icon
SettingsEntryBool, // Tickbox setting
SettingsEntry3Number, // Settings adjust with 3 number digits
SettingsEntry2Number, // Settings adjust with 2 number digits
SettingsEntry1Number, // Settings adjust with 2 number digits
SettingsEntry1Text, // Setting with single text char for state
ScrollingText, // Scrolling large text (warnings, help text)
SolderingMode, // Basic soldering mode
DetailedSolderingMode, // Detailed soldering mode
NumberAdjust, // Number adjust of number with <> either side
} screenLayout_t;
typedef struct {
struct {
ElementTypes_t elementType;
ElementSettings_t elementSettings;
} elements[5];
} ScreenLayoutRecord_t;

15
source/UI/UI_Screens.h Normal file
View File

@@ -0,0 +1,15 @@
#pragma once
#include "UI_Layouts.h"
typedef void (*render_prep_fn)();
typedef void (*tick_fn)();
typedef void (*button_handler_fn)();
typedef struct {
// on_enter
// on_exit
tick_fn tick;
render_prep_fn render_prepare;
screenLayout_t layout; // Render layout used
button_handler_fn handle_button;
} Screen_t;

78
source/UI/generate_ui.py Executable file
View File

@@ -0,0 +1,78 @@
#!/usr/bin/env python3
"""
Read in the yaml config files in this folder
For each config file, generate a cpp file defining each layout
"""
import yaml
from string import Template
def element_to_str(element) -> str:
template = Template(
"""
{
.elementType = ElementTypes_t::$type,
.elementSettings={
.position ={
.x=$x,
.y=$y,
},
.size ={
.w=$w,
.h=$h,
}
},
},
"""
)
return template.substitute(
x=element["position"]["x"],
y=element["position"]["y"],
w=element["size"]["w"],
h=element["size"]["h"],
type=element["type"],
)
def layout_to_str(layout):
inner_elements = "".join(element_to_str(x) for x in layout["elements"])
template = Template(
"""{
.elements =
{
$elements
},
},
"""
)
return template.substitute(elements=inner_elements)
def layouts_to_cpp(layout_file_path, output_file_path):
with open(layout_file_path, "r") as file:
with open(output_file_path, "w") as output:
layout_defs = yaml.safe_load(file)
header = """
#include "UI.h"
#include "UI_Elements.h"
const ScreenLayoutRecord_t screenLayouts[] = {
"""
output.write(header)
for layout_name in layout_defs["layouts"]:
layout = layout_defs["layouts"][layout_name]
# Now we convert this layout into a structure definition
element_entry = layout_to_str(layout)
output.write(element_entry)
footer = """
};
"""
output.write(footer)
layouts_to_cpp("layout_96x16.yaml", "layout_96x16.cpp")

270
source/UI/layout_96x16.yaml Normal file
View File

@@ -0,0 +1,270 @@
layouts:
SimplifiedHome:
mirrorOnRotate: true
elements:
- type: Image
position:
x: 0
y: 0
size:
w: 42
h: 16
- type: Image
position:
x: 0
y: 0
size:
w: 42
h: 16
- type: PowerSource
position:
x: 84
y: 0
size:
w: 12
h: 16
simplifiedHomeWarning:
mirrorOnRotate: true
elements:
- type: Text
position:
x: 0
y: 0
size:
w: 42
h: 16
- type: Image
position:
x: 0
y: 0
size:
w: 42
h: 16
- type: PowerSource
position:
x: 84
y: 0
size:
w: 12
h: 16
detailedHome:
elements:
- type: Temperature
position:
x: 0
y: 0
size:
w: 48
h: 16
- type: Temperature
position:
x: 48
y: 0
size:
w: 32
h: 8
- type: InputVoltage
position:
x: 48
y: 0
size:
w: 32
h: 8
detailedHomeWarning:
elements:
- type: Temperature
position:
x: 0
y: 0
size:
w: 48
h: 16
- type: InputVoltage
position:
x: 48
y: 0
size:
w: 32
h: 8
SebugMenu:
elements:
- type: Text
position:
x: 0
y: 0
size:
w: 96
h: 8
- type: Text
position:
x: 0
y: 8
size:
w: 48
h: 8
- type: Number
position:
x: 48
y: 8
size:
w: 48
h: 8
SettingsCategory:
elements:
- type: Text
position:
x: 0
y: 0
size:
w: 78
h: 16
- type: Image
position:
x: 79
y: 0
size:
w: 16
h: 16
- type: ScrollBar
position:
x: 95
y: 0
size:
w: 1
h: 16
SettingsEntryBool:
elements:
- type: Text
position:
x: 0
y: 0
size:
w: 78
h: 16
- type: CheckBox
position:
x: 79
y: 0
size:
w: 16
h: 16
- type: ScrollBar
position:
x: 95
y: 0
size:
w: 1
h: 16
SettingsEntry3Number:
elements:
- type: Text
position:
x: 0
y: 0
size:
w: 78
h: 16
- type: Number
position:
x: 79
y: 0
size:
w: 36
h: 16
- type: ScrollBar
position:
x: 95
y: 0
size:
w: 1
h: 16
SettingsEntry2Number:
elements:
- type: Text
position:
x: 0
y: 0
size:
w: 78
h: 16
- type: Number
position:
x: 79
y: 0
size:
w: 36
h: 16
- type: ScrollBar
position:
x: 95
y: 0
size:
w: 1
h: 16
SettingsEntry1Number:
elements:
- type: Text
position:
x: 0
y: 0
size:
w: 78
h: 16
- type: Number
position:
x: 79
y: 0
size:
w: 36
h: 16
- type: ScrollBar
position:
x: 95
y: 0
size:
w: 1
h: 16
SettingsEntry1Text:
elements:
- type: Text
position:
x: 0
y: 0
size:
w: 78
h: 16
- type: Number
position:
x: 79
y: 0
size:
w: 36
h: 16
- type: ScrollBar
position:
x: 95
y: 0
size:
w: 1
h: 16
ScrollingText:
elements:
- type: TextScroller
position:
x: 0
y: 0
size:
w: 96
h: 16
# SolderingMode:
# elements:
# DetailedSolderingMode:
# elements:
# NumberAdjust:
# elements:

2
start_dev.sh Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
docker-compose run --rm builder