Compare commits
57 Commits
epr-pineci
...
v2.22-rc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
524d121fcb | ||
|
|
97c0fee358 | ||
|
|
17b39de903 | ||
|
|
3f880d9e26 | ||
|
|
4533c2f497 | ||
|
|
c120af398a | ||
|
|
2d7abc274a | ||
|
|
80c4b58976 | ||
|
|
a7df1cc5be | ||
|
|
584b3826c3 | ||
|
|
c4fd383694 | ||
|
|
bd9c63f55d | ||
|
|
45f89f8f9c | ||
|
|
f61376a404 | ||
|
|
703a32f68a | ||
|
|
e0f373a88a | ||
|
|
05d0ef66ef | ||
|
|
6d18e860f8 | ||
|
|
344068d480 | ||
|
|
13e1c24152 | ||
|
|
7254b78404 | ||
|
|
55d36c98f1 | ||
|
|
65ac2e25a6 | ||
|
|
ea1906e499 | ||
|
|
9a3fef92c3 | ||
|
|
118fa09ce7 | ||
|
|
6ba2a5c259 | ||
|
|
0f6c1b686e | ||
|
|
f83ebc8c81 | ||
|
|
65dd3e879c | ||
|
|
52dd27cc07 | ||
|
|
8ac43645b7 | ||
|
|
1c9d3940ca | ||
|
|
297a4dffa5 | ||
|
|
93a18e5076 | ||
|
|
bfbdf8c941 | ||
|
|
b00d26cb9c | ||
|
|
78a4cfecfe | ||
|
|
c7574c4d0c | ||
|
|
1d820acbee | ||
|
|
d95af7d1a0 | ||
|
|
ca79638a74 | ||
|
|
4649df6914 | ||
|
|
cd7696b66f | ||
|
|
552b582bcb | ||
|
|
311dbeac6f | ||
|
|
6ff7bec4a4 | ||
|
|
b80716e2a7 | ||
|
|
7b57cc981f | ||
|
|
f72bc969ac | ||
|
|
0be83598f1 | ||
|
|
88f62941ec | ||
|
|
cbde61edb4 | ||
|
|
8c17a085f1 | ||
|
|
3a8eb3c511 | ||
|
|
f81257562d | ||
|
|
5d96470e45 |
94
.github/workflows/push.yml
vendored
94
.github/workflows/push.yml
vendored
@@ -3,6 +3,8 @@ name: CI
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-20.04
|
||||
container:
|
||||
@@ -26,13 +28,14 @@ jobs:
|
||||
- name: Git ownership exception
|
||||
run: git config --global --add safe.directory /__w/IronOS/IronOS && git config --global safe.directory "$GITHUB_WORKSPACE"
|
||||
|
||||
- name: build ${{ matrix.model }}
|
||||
- name: Git meta info
|
||||
run: echo "GITHUB_CI_PR_SHA=${{github.event.pull_request.head.sha}}" >> "${GITHUB_ENV}"
|
||||
|
||||
- name: Build ${{ matrix.model }}
|
||||
run: cd source && ./build.sh -m ${{ matrix.model }}
|
||||
|
||||
- name: copy license text
|
||||
run: |
|
||||
cp LICENSE source/Hexfile/LICENSE
|
||||
cp scripts/LICENSE_RELEASE.md source/Hexfile/LICENSE_RELEASE.md
|
||||
- name: Copy license files
|
||||
run: cp LICENSE scripts/LICENSE_RELEASE.md source/Hexfile/
|
||||
|
||||
- name: Archive ${{ matrix.model }} artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
@@ -47,7 +50,7 @@ jobs:
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Generate json index file
|
||||
run: cd source && python3 metadata.py ${{ matrix.model }}.json
|
||||
run: ./source/metadata.py ${{ matrix.model }}.json
|
||||
|
||||
- name: Archive ${{ matrix.model }} index file
|
||||
uses: actions/upload-artifact@v3
|
||||
@@ -55,6 +58,7 @@ jobs:
|
||||
name: metadata
|
||||
path: source/Hexfile/${{ matrix.model }}.json
|
||||
|
||||
|
||||
build_multi-lang:
|
||||
runs-on: ubuntu-20.04
|
||||
container:
|
||||
@@ -77,13 +81,14 @@ jobs:
|
||||
- name: Git ownership exception
|
||||
run: git config --global --add safe.directory /__w/IronOS/IronOS && git config --global safe.directory "$GITHUB_WORKSPACE"
|
||||
|
||||
- name: build ${{ matrix.model }}
|
||||
run: cd source && make -j$(nproc) model="${{ matrix.model }}" firmware-multi_compressed_European firmware-multi_compressed_Bulgarian+Russian+Serbian+Ukrainian firmware-multi_Chinese+Japanese
|
||||
- name: Git meta info
|
||||
run: echo "GITHUB_CI_PR_SHA=${{github.event.pull_request.head.sha}}" >> "${GITHUB_ENV}"
|
||||
|
||||
- name: copy license text
|
||||
run: |
|
||||
cp LICENSE source/Hexfile/LICENSE
|
||||
cp scripts/LICENSE_RELEASE.md source/Hexfile/LICENSE_RELEASE.md
|
||||
- name: Build ${{ matrix.model }}
|
||||
run: make -C source/ -j$(nproc) model="${{ matrix.model }}" firmware-multi_compressed_European firmware-multi_compressed_Bulgarian+Russian+Serbian+Ukrainian firmware-multi_Chinese+Japanese
|
||||
|
||||
- name: Copy license files
|
||||
run: cp LICENSE scripts/LICENSE_RELEASE.md source/Hexfile/
|
||||
|
||||
- name: Archive ${{ matrix.model }} artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
@@ -98,7 +103,7 @@ jobs:
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Generate json index file
|
||||
run: cd source && python3 metadata.py ${{ matrix.model }}_multi-lang.json
|
||||
run: ./source/metadata.py ${{ matrix.model }}_multi-lang.json
|
||||
|
||||
- name: Archive ${{ matrix.model }} index file
|
||||
uses: actions/upload-artifact@v3
|
||||
@@ -106,60 +111,72 @@ jobs:
|
||||
name: metadata
|
||||
path: source/Hexfile/${{ matrix.model }}_multi-lang.json
|
||||
|
||||
|
||||
tests:
|
||||
runs-on: ubuntu-20.04
|
||||
container:
|
||||
image: alpine:3.16
|
||||
|
||||
steps:
|
||||
- name: deps
|
||||
- name: Install dependencies (apk)
|
||||
run: apk add --no-cache python3 py3-pip make git bash findutils gcc musl-dev
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: install black
|
||||
- name: Install dependencies (python)
|
||||
run: python3 -m pip install bdflib
|
||||
|
||||
- name: Run python tests
|
||||
run: cd Translations && chmod +x make_translation_test.py && ./make_translation_test.py
|
||||
run: ./Translations/make_translation_test.py
|
||||
|
||||
- name: Run BriefLZ tests
|
||||
run: |
|
||||
cd source
|
||||
make Objects/host/brieflz/libbrieflz.so
|
||||
cd ../Translations
|
||||
chmod +x brieflz_test.py
|
||||
./brieflz_test.py
|
||||
run: make -C source/ Objects/host/brieflz/libbrieflz.so && ./Translations/brieflz_test.py
|
||||
|
||||
check_formatting:
|
||||
|
||||
check_c-cpp:
|
||||
runs-on: ubuntu-20.04
|
||||
container:
|
||||
image: alpine:3.16
|
||||
|
||||
steps:
|
||||
- name: deps
|
||||
- name: Install dependencies (apk)
|
||||
run: apk add --no-cache make git diffutils findutils clang-extra-tools bash
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Check format style with clang-format
|
||||
run: make clean check-style
|
||||
|
||||
|
||||
check_python:
|
||||
runs-on: ubuntu-20.04
|
||||
container:
|
||||
image: alpine:3.16
|
||||
|
||||
steps:
|
||||
- name: Install dependencies (apk)
|
||||
run: apk add --no-cache python3 py3-pip make git black
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: install black
|
||||
- name: Install dependencies (python)
|
||||
run: python3 -m pip install bdflib flake8
|
||||
|
||||
- name: Check formatting with clang-format
|
||||
run: cd source && make clean && make check-style
|
||||
|
||||
- name: Check python formatting with black
|
||||
run: black --check Translations
|
||||
|
||||
- name: Check python with flake8
|
||||
run: flake8 Translations
|
||||
|
||||
shellcheck:
|
||||
name: runner / shellcheck
|
||||
|
||||
check_shell:
|
||||
name: check_shell
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -170,3 +187,20 @@ jobs:
|
||||
reporter: github-pr-review # Change reporter.
|
||||
exclude: "./.git/*" # Optional.
|
||||
check_all_files_with_shebangs: "false" # Optional.
|
||||
|
||||
|
||||
check_readme:
|
||||
runs-on: ubuntu-20.04
|
||||
container:
|
||||
image: alpine:3.16
|
||||
|
||||
steps:
|
||||
- name: Install dependencies (apk)
|
||||
run: apk add --no-cache git
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Check autogenerated Documentation/README.md
|
||||
run: /bin/sh ./scripts/deploy.sh docs_readme
|
||||
|
||||
81
.gitignore
vendored
81
.gitignore
vendored
@@ -1,3 +1,5 @@
|
||||
#### Generic ####
|
||||
|
||||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
@@ -5,6 +7,7 @@
|
||||
*.elf
|
||||
*.d
|
||||
*.DS_Store
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
@@ -31,33 +34,22 @@
|
||||
# Debug files
|
||||
*.dSYM/
|
||||
*.su
|
||||
source/.metadata/*
|
||||
|
||||
TS100/KiCad/TS100.bak
|
||||
Logo GUI/TS100 Logo Editor/TS100 Logo Editor/obj/
|
||||
Logo GUI/TS100 Logo Editor/TS100 Logo Editor/bin/
|
||||
*.cache
|
||||
Translation Editor/.vscode/
|
||||
Translation Editor/__pycache__/
|
||||
# Custom scripts & misc. files
|
||||
*.pyc
|
||||
*.lst
|
||||
*.mk
|
||||
*.list
|
||||
source/Hexfile/
|
||||
source/Objects/
|
||||
|
||||
ci/artefacts/
|
||||
ci/secrets/unencrypted/
|
||||
codeship.aes
|
||||
.vscode/settings.json
|
||||
|
||||
# Auto generated files
|
||||
source/Core/Inc/unit.h
|
||||
source/Core/Gen/
|
||||
*.cache
|
||||
codeship.aes
|
||||
CoreCompileInputs.cache
|
||||
|
||||
# IDE configs
|
||||
.vs/*
|
||||
.settings/*
|
||||
..cproject.swp
|
||||
.cproject.swp
|
||||
|
||||
# Visual Studios
|
||||
.vscode/*
|
||||
@@ -65,6 +57,7 @@ source/Core/Gen/
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
.vscode/settings.json
|
||||
|
||||
# Eclipse
|
||||
.metadata
|
||||
@@ -120,11 +113,24 @@ local.properties
|
||||
.scala_dependencies
|
||||
.worksheet
|
||||
|
||||
# Jetbrains
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
|
||||
# source code tagging systems (GNU Global, ctags, cscope)
|
||||
GPATH
|
||||
GRTAGS
|
||||
GTAGS
|
||||
*tags
|
||||
*tags/
|
||||
.*tags
|
||||
.*tags/
|
||||
cscope.*
|
||||
cscope/
|
||||
.cscope/
|
||||
|
||||
|
||||
#### Jetbrains: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm ####
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
@@ -174,7 +180,38 @@ fabric.properties
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
CoreCompileInputs.cache
|
||||
.vscode/settings.json
|
||||
|
||||
#### IronOS project specific files ####
|
||||
|
||||
# Binaries
|
||||
source/Hexfile/
|
||||
source/Objects/
|
||||
BUILDS/
|
||||
|
||||
# Autogenerated
|
||||
source/Core/Gen/
|
||||
source/Core/Inc/unit.h
|
||||
|
||||
# Deploy
|
||||
scripts/ci/artefacts/
|
||||
scripts/ci/secrets/unencrypted/
|
||||
|
||||
# Generated static local docs
|
||||
site/
|
||||
|
||||
# Translations
|
||||
Translations/__pycache__/
|
||||
Translation Editor/__pycache__/
|
||||
Translation Editor/.vscode/
|
||||
|
||||
# misc.
|
||||
source/compile_commands.json
|
||||
.idea/
|
||||
source/.metadata/*
|
||||
|
||||
# TS100 related
|
||||
TS100/KiCad/TS100.bak
|
||||
Logo GUI/TS100 Logo Editor/TS100 Logo Editor/obj/
|
||||
Logo GUI/TS100 Logo Editor/TS100 Logo Editor/bin/
|
||||
|
||||
# Tests/linters/sanitizers
|
||||
source/check-style.log
|
||||
|
||||
99
Documentation/Bluetooth.md
Normal file
99
Documentation/Bluetooth.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# Bluetooth Low Energy
|
||||
|
||||
The Pinecilv2 has hardware support for Bluetooth Low Energy (BLE). This protocol allows reading and writing of parameters to the Pinecil during runtime.
|
||||
|
||||
The BLE interface advertises three services, these provide access to live telemetry as well as the ability to read/write settings.
|
||||
These are outlined in more detail below.
|
||||
|
||||
Pinecil devices advertise themselves on BLE as `Pinecil-XXXXXXX`.
|
||||
They also include the UUID `9eae1000-9d0d-48c5-AA55-33e27f9bc533` in the advertisement packet to allow for filtering.
|
||||
|
||||
Unless otherwise noted, all data is sent and received as Little-Endian.
|
||||
|
||||
As of the time of writing this, notifications are not fully implemented so data will need to be polled. Notification/Indication support will come when there is time to implement it.
|
||||
|
||||
## Using the BLE Interface
|
||||
|
||||
It is advised to follow the below points when first implementing a BLE integration. Of course once the integration is working feel free to deviate from these. These are just _suggested_ ideas to help kickstart.
|
||||
|
||||
1. When filtering for devices, its preferable to filter by the UUID `9eae1000-9d0d-48c5-AA55-33e27f9bc533`, rather than by the device name if possible.
|
||||
2. Upon first collection check if the three expected services exist; if they don't the user may have selected an incorrect device.
|
||||
3. It's best to read the live bulk endpoint over the live service when its easy to do so (one read vs ~15).
|
||||
1. However if you are just updating one or two line items it may be more efficient to just read these on the live service.
|
||||
2. Feel free to test both and decide.
|
||||
4. When reading settings from the device; the association of number <-> setting is fixed, but you may see settings you don't yet know about, make sure you can handle these.
|
||||
5. You probably don't want to show unknown setting's to the user though.
|
||||
6. Read the device firmware revision and ensure you can decode it. If BLE is revised it may be essential for handling versions cleanly.
|
||||
7. It's advisable to keep an eye on the IronOS repository or at least setup the Github watch for release notifications.
|
||||
1. Future releases may revise some BLE aspects or add new settings for example.
|
||||
|
||||
## Services
|
||||
|
||||
Below is a description of each service. Note that the exact settings are not listed for brevity; it's best to refer to [the uuid lists](https://github.com/Ralim/IronOS/blob/dev/source/Core/BSP/Pinecilv2/ble_characteristics.h) and the [handlers](https://github.com/Ralim/IronOS/blob/dev/source/Core/BSP/Pinecilv2/ble_handlers.cpp) alongside this.
|
||||
|
||||
### Live
|
||||
|
||||
`UUID: d85ef000-168e-4a71-AA55-33e27f9bc533`
|
||||
|
||||
The live services has one characteristic per reading. The readings (in order) are:
|
||||
When implementing these; the ones that are not obvious are generally found in the debugging menu. Values are encoded as an unsigned 32 bit number for all results.
|
||||
|
||||
1. Live temperature (In C)
|
||||
2. Live set point
|
||||
3. DC input voltage
|
||||
4. Handle temperature (In C)
|
||||
5. Power level
|
||||
6. Power source
|
||||
7. Tip resistance
|
||||
8. uptime
|
||||
9. Time of last movement
|
||||
10. Maximum temperature settable
|
||||
11. Raw tip reading
|
||||
12. Hall sensor
|
||||
13. Operating mode
|
||||
14. Estimated wattage
|
||||
|
||||
### Settings
|
||||
|
||||
`UUID: f6d80000-5a10-4eba-AA55-33e27f9bc533`
|
||||
|
||||
The settings service has two special entries; for saving and resetting settings.
|
||||
Otherwise all settings are enumerated using UUID's of the format : `f6d7ZZZZ-5a10-4eba-AA55-33e27f9bc533))` where `ZZZZ` is the setting number as matched from [Settings.h](https://github.com/Ralim/IronOS/blob/dev/source/Core/Inc/Settings.h#L16).
|
||||
|
||||
All data is read and written in fixed unsigned 16 bit numbers.
|
||||
|
||||
#### Settings save
|
||||
|
||||
To save the settings write a `0x0001` to `f6d7FFFF-5a10-4eba-AA55-33e27f9bc533`.
|
||||
Its advised to not save settings on each change but instead to give the user a save button _or_ save after a timeout. This is just to reduce write cycles on the internal flash.
|
||||
|
||||
#### Settings reset
|
||||
|
||||
To reset all settings to defaults; write a `0x0001` to `f6d7FFFE-5a10-4eba-AA55-33e27f9bc533`.
|
||||
This will reset settings immediately.
|
||||
|
||||
### Bulk
|
||||
|
||||
`UUID: 9eae1000-9d0d-48c5-AA55-33e27f9bc533`
|
||||
|
||||
The bulk endpoint is where extra data is located with varying read sizes.
|
||||
|
||||
#### Live data
|
||||
|
||||
The bulk live data endpoint provides all of the data provided in the live endpoint, as one large single-read binary blob. This is designed for applications that are showing large amounts of data as this is more efficient for reading.
|
||||
|
||||
#### Accelerometer Name
|
||||
|
||||
_Not yet implemented_
|
||||
|
||||
#### Build ID
|
||||
|
||||
This encodes the current build ID to allow viewing and handling when the BLE format changes.
|
||||
|
||||
#### Device Serial Number
|
||||
|
||||
This is generally the device CPU serial number. For most devices this can be used as an ID. On PinecilV2 its the MAC address.
|
||||
|
||||
#### Device Unique ID
|
||||
|
||||
This is only relevant on the PinecilV2. This is a random ID that is burned in at the factory. This is used by the online authenticity checker tool.
|
||||
@@ -9,9 +9,42 @@ This menu is meant to be simple, so it has no fancy GUI animations.
|
||||
|
||||
## Menu items
|
||||
|
||||
Items are shown in the menu on a single line, so they use short codes and appear in this order:
|
||||
Items are shown in the menu on a single line, so they use short codes.
|
||||
|
||||
### Version
|
||||
|
||||
There is a static line on top which is presented on every sub-screen and reflects exact version of firmware. Version line on top has the following format - `vX.YYN.[ZZZZZZZZ]`:
|
||||
|
||||
- X: major version
|
||||
- Y: minor version
|
||||
- N: build type:
|
||||
- R - git-related **r**elease tag vXX.YY
|
||||
- T - git-related release **t**ag but version is not vXX.YY !
|
||||
- D - git-related **d**ev branch
|
||||
- B - git-related custom **b**ranch
|
||||
- G - neither above but **g**it-related
|
||||
- C - build from github **C**I during _pull request_
|
||||
- H - build outside of a git tree (i.e. release tarball or **h**omebrew customization without git)
|
||||
- S - something **s**pecial[^ERR]
|
||||
- V - something **v**ery special[^ERR]
|
||||
[^ERR]: `S` and `V` are reserved letters for cases when source of firmware is having very unique origin & configuration
|
||||
- Z: short commit ID hash with 8 digits generated automatically from git (for git-related build types only)
|
||||
|
||||
I.e.:
|
||||
- `v2.22H` means firmware built locally from tarball with release version of `2.22`
|
||||
- `v2.22D.1A2B3C4D` means firmware with development version of `2.22` from git `dev` branch & with commit ID `1A2B3C4D` (so it can be traced for debug purposes)
|
||||
- `v2.22R.5E6F7G8H` means firmware with official release version of `2.22` and it's properly tagged with `v2.22` git tag & with commit ID `5E6F7G8H`'
|
||||
|
||||
---
|
||||
|
||||
**Additional scroll-able items appear in this order**:
|
||||
|
||||
### Date
|
||||
|
||||
- This is a date of firmware compilation and it has the following format: `DD-MM-YY` (i.e., `01-07-23` means it has been built in July, 1st, 2023)
|
||||
|
||||
### ID
|
||||
|
||||
- This is used by Irons that have an ID and serial number to help check if the iron is authentic. All Pinecil V1 show the same ID number as this is the number programmed into the MCU.
|
||||
- The new Pinecil V2 released Aug. 2, 2022 now uses MCU BL706, which enables generating a unique ID/Serial number to every iron. This can be used to verify your [Pinecil authenticity here](https://pinecil.pine64.org/).
|
||||
|
||||
@@ -52,7 +85,6 @@ This is the handle temperature or more accurately the reading of the Cold Juncti
|
||||
This is used for CJC of the tip temperature.
|
||||
> If CHan is extremely high, this indicates the temperature sensor isn't reading correctly ([see Troubleshooting](https://ralim.github.io/IronOS/Troubleshooting/))
|
||||
|
||||
|
||||
### Max C
|
||||
|
||||
This indicates the max temperature in °C that the system estimates it can measure the tip reliably to.
|
||||
@@ -106,6 +138,7 @@ Pressing (`+`) cycles through elements, and (`-`) or unplugging will exit the me
|
||||
The first page shows the PD negotiation stage number; which can be used for diagnosing if PD is not working. Once negotiation is complete; use (`+`) button to advance to other screens which show the different proposals advertised for voltage and current (State 12 means all is good with the PD charger).
|
||||
|
||||
#### Below is a method for user modification to convert some early models of Pinecil V1 to safely support 24V on the DC5525 barrel.
|
||||
|
||||
⚠️ Warning: do this at your own risk, read everything in this document, and go to the [Pine64 community chat](https://wiki.pine64.org/wiki/Pinecil#Community_links) if you desire advice. An incorrect cut of the trace could render the Pinecil non-working.
|
||||
|
||||
Background: a simple user modification to the PCB on _some models_ of original V1 allows it to safely use DC barrel 24V by cutting a trace line to the Vbus which held it back to 21V. You can check whether your Pinecil V1 needs the update or can benefit from it by using a hidden trick in the PD debug menu.
|
||||
|
||||
@@ -133,7 +133,7 @@ On Windows follow the instructions on the official documentation to install 'Win
|
||||
3. Build the firmware for Pinecil V2:
|
||||
|
||||
```sh
|
||||
cd source/source
|
||||
cd source/
|
||||
./build.sh -l EN -m Pinecilv2
|
||||
```
|
||||
|
||||
|
||||
@@ -1,8 +1,62 @@
|
||||
## Notes on the various supported hardware
|
||||
|
||||
|
||||
### TS100
|
||||
|
||||
TS100\* is a neat soldering iron:
|
||||
|
||||
- can run from 9-25V DC;
|
||||
- provides a power range that is determined by the input voltage;
|
||||
- voltages below 12V don't overly work well for any substantial mass;
|
||||
- the default firmware can be found [here](https://www.minidso.com/forum.php?mod=viewthread&tid=892&extra=page%3D1).
|
||||
|
||||

|
||||
|
||||
|
||||
### TS80
|
||||
|
||||
TS80\* is a successor to TS100:
|
||||
|
||||
- uses _Quick Charge 3.0_ / _QC3_ capable charger only (18W max);
|
||||
- doesn't support PD as it is not designed on the hardware level;
|
||||
- the default firmware can be found [here](https://www.minidso.com/forum.php?mod=viewthread&tid=3208&extra=page%3D1).
|
||||
|
||||

|
||||
|
||||
|
||||
### TS80P
|
||||
|
||||
TS80P\* is a successor to TS80:
|
||||
|
||||
- supports _Quick Charge 3.0_ (_QC3_: 9V/3A, 18W max);
|
||||
- supports _Power Delivery_ (_PD_: 9V/3A & 12V/3A, 30W max)\*\*;
|
||||
- the default firmware can be found [here](https://www.minidso.com/forum.php?mod=viewthread&tid=4085&extra=page%3D1).
|
||||
|
||||
\*\*: use valid PD device that supports 12V/3A as power source to get full 30W potential, otherwise the iron will fall back to 9V/18W power mode.
|
||||
|
||||

|
||||
|
||||
|
||||
### MHP30
|
||||
|
||||
- Accelerometer is the MSA301, this is mounted roughly in the middle of the unit
|
||||
- USB-PD is using the FUSB302
|
||||
- The hardware I2C bus on PB6/7 is used for the MSA301 and FUSB302
|
||||
- The OLED is the same SSD1306 as everything else, but it’s on a bit-banged bus
|
||||
MHP30 is a **M**ini **H**ot **P**late:
|
||||
|
||||
- accelerometer is the MSA301, this is mounted roughly in the middle of the unit;
|
||||
- USB-PD is using the FUSB302;
|
||||
- the hardware I2C bus on PB6/7 is used for the MSA301 and FUSB302;
|
||||
- the OLED is the same SSD1306 as everything else, but it’s on a bit-banged bus.
|
||||
|
||||
|
||||
### Pinecil
|
||||
|
||||
Pincecil\*:
|
||||
|
||||
- first model of soldering iron from PINE64;
|
||||
- the default firmware can be found [here](https://files.pine64.org/os/Pinecil/Pinecil_firmware_20201115.zip).
|
||||
|
||||

|
||||
|
||||
|
||||
\*: Please note: these soldering irons do *NOT* contain DC/DC converters. This means that your power at the tip is a function of the supplied voltage. Just because the iron "supports" running at a wide range of voltages, you should always use a voltage near the upper limit where possible. It is highly recommended to use a PD adapter where possible as this allows the iron to _know_ the limitations of your supply. The marked irons can only turn the tip on and off in software, this means that they can't control the maximum power drawn from the supply. This is why when using PD the iron may select a lower voltage than your power supplies maximum. This is to prevent your power supply failing from over current. For more information about power management underhood, please, [see the related documentation section](https://ralim.github.io/IronOS/Power/).
|
||||
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ The resistance of the tip is a fixed constant in ohms (Ω):
|
||||
This means the power delivered to the soldering tip is proportional to the voltage squared.
|
||||
Therefore the Pinecil and TS100 perform poorly when run off 12V power supplies and may issue a `Thermal Runaway` message (weak power supply).
|
||||
|
||||
|
||||
|
||||
#### Use an [Ohm calculator](https://www.rapidtables.com/calc/electric/power-calculator.html#dc) to quickly derive watts.
|
||||
|
||||
| Type | Volts| / | Tip Ω | = | Amps | * | Volts | = | Watts |
|
||||
@@ -44,3 +46,8 @@ To measure the tip temperature in the iron, the iron has a small op-amp connecte
|
||||
Once the output is turned off (via the FET), the system has a recovery time as the tip capacitance discharges and the op-amp exits saturation. After this delay period, the MCU's ADC (analog-to-digital converter) samples the output of the op-amp 8 times quickly and then sets a flag to turn the PWM output back on.
|
||||
This enforces a small dead time in the output signal while this occurs, so there is a balance between sampling the temperature often to maintain a stable tip temperature control and sampling less often to increase the maximum power deliverable to the tip ([see Complexity of measurement](https://ralim.github.io/IronOS/Temperature/#complexity-of-measurement)).
|
||||
|
||||
|
||||
|
||||
## Power sources
|
||||
|
||||
Supported by IronOS hardware may use different power sources (chargers/powerbanks/battery packs) with different standards & protocols (QC/PD/etc). For more information collected by the community on that, please, [see the related documentation section](https://ralim.github.io/IronOS/PowerSources/).
|
||||
|
||||
80
Documentation/PowerSources.md
Normal file
80
Documentation/PowerSources.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# Power sources
|
||||
|
||||
Supported by IronOS hardware may use different power sources (chargers/powerbanks/battery packs) with different standards & protocols (QC/PD/etc). This document contains information collected by the community with tested power sources.
|
||||
|
||||
This is not ads but first hands-on experience results from real users since some chargers/powerbanks regardless labels on the box may not fully support what's declared!
|
||||
|
||||
|
||||
## QC(3)
|
||||
|
||||
|
||||
### Compatible Devices (QuickCharge for TS80/P)
|
||||
|
||||
The following table is the list of compatible device and remarks when powering up the TS80 through it for both stock firmware from MiniDso and IronOS. The list of devices below are primarily taken from [#349](https://github.com/Ralim/ts100/issues/349#issuecomment-449559806)
|
||||
|
||||
| Device Name | Stock FW | IronOS FW |
|
||||
|-------------|:--------:|:---------:|
|
||||
| Anker PowerCore II Slim 10000 Powerbank | Not Working | Good |
|
||||
| [Aukey 26.5/30 Ah Powerbank (PB-Y3)](https://www.aukey.com/products/30000mah-power-bank-with-quick-charge-3-0/) | OK\*\* (15sec t/o) | OK\*\* (15sec t/o) |
|
||||
| Aukey QC3 Charger | Good | Only 5V |
|
||||
| [Aukey QC3 Charging Station (PA-T11)](https://www.aukey.com/products/6-port-charging-station-with-quick-charge-3-0-pa-t11/) | Good | Good |
|
||||
| Besiter 20000mah QC3 | Not Working | Only 5V |
|
||||
| BlitzWolf BW-P5 | Not Working\* | Unknown |
|
||||
| BlitzWolf BW-PF2 | OK\*\* (10sec t/o) | OK\*\* (10sec t/o) |
|
||||
| BlitzWolf BW-PL3 | Low Voltage | OK |
|
||||
| BlitzWolf BW-PL4 | Unknown | Not Working |
|
||||
| BlitzWolf BW-S6 | Unknown | OK |
|
||||
| Charmast 20800 mAh QC 3.0 | Low Voltage\* | Good |
|
||||
| Clas Ohlson Powerbank USB-C 10050 mAh, Clas Ohlson | Unknown | OK\*\* |
|
||||
| [Cygnett 20,000mAh USB-C](https://www.cygnett.com/products/20-000mah-usb-c-power-bank-in-black)| Not Working | Good |
|
||||
| [HAME H13D](https://www.amazon.com/dp/B07GWMFW82) 10000mAh PD/QC3.0 Power Bank | OK\*\* (30sec t/o) | OK\*\* (30sec t/o?) |
|
||||
| HIPER 10000 mAh 18W PD+QC3.0 (MPX10000) | Low Voltage | OK\*\* (30sec t/o) |
|
||||
| [iMuto Portable Charger 30000mAh](https://www.amazon.com/gp/product/B01MXCMGB8/ref=ppx_yo_dt_b_asin_title_o05_s00) | Low Voltage | Good |
|
||||
| ISDT BG-8S | Good | Good |
|
||||
| [iVoler Quick Charge 3.0 USB C 30W 2-Port USB](https://www.amazon.de/dp/B077P8ZZB8/) | Good | Good |
|
||||
| [imuto X6L Pro 30000 mah](https://www.amazon.com/dp/B01MXCMGB8) | Not Working | Bad |
|
||||
| Interstep 10000 mAh 18W PD+QC3.0+FCP+AFC (MPX10000) | Good | OK\*\* (30sec t/o) |
|
||||
| Jackery Black 420 | Low Voltage | Good |
|
||||
| Kogan Premium 80W 5 Port USB Charger| Low Voltage | Good |
|
||||
| Nokia AD-18WE | Unknown | OK |
|
||||
| [Omars 2000mAh USB-C PD+QC3.0 (OMPB20KBUPLT / OMPB20KPLT)](https://www.amazon.com/dp/B07CMLVR6C) | OK\*\* (20sec t/o) | Unknown |
|
||||
| Polaroid PS100 Powerbank (https://polaroid.com/products/ps100) | Good | Good |
|
||||
| Xiaomi 10000mAh Mi Power Bank Pro (PLM03ZM) | Good | Unknown |
|
||||
| Xiaomi 10000mAh Mi Power Bank 2i (PLM09ZM) | Good | Good |
|
||||
| Xiaomi 20000mAh Mi Power Bank 3 (PLM07ZM) | Unknown | Good Type A, Bad Type C |
|
||||
| [ZeroLemon ToughJuice](https://www.amazon.com/dp/B01CZR3LT2/) 30000mAh PD/QC2.0 Power Bank | OK\*\* (20sec t/o) | OK\*\* (20sec t/o?) |
|
||||
| [URUAV XT-60 to USB module](https://www.banggood.com/URUAV-XT-60-to-USB-Charger-Converter-Support-3S-6S-LiPo-Battery-10_5V-32V-Input-3V-20V-Output-45W-Max-Fast-Charging-Adapter-For-RC-Racing-Drone-p-1475876.html) | Unknown | Good |
|
||||
|
||||
|
||||
\* Need further tests on newer firmware
|
||||
|
||||
\*\* Most Power Banks shut down if current draw drops below 50mA, assuming that charging is complete and avoiding overcharging. Custom firmware is designed to avoid this until it enters Zzzz mode.
|
||||
|
||||
|
||||
### DIY QC3.0
|
||||
|
||||
You may also build your own QC3.0 power source that requires this little [thing](https://www.tindie.com/products/soubitos/qualcomm-qc2-3-diy-8-32vin-36-12vout-3a-max/) and have at least 3S lithium packs or any input voltage from 8 to 32V.
|
||||
|
||||
You can also go for an [alternate module](https://www.banggood.com/DC-Buck-Module-12V24V-to-QC3_0-Single-USB-Mobile-Charging-Board-p-1310585.html) which has at least one good review of it.
|
||||
|
||||
**DISCLAIMER:** _**We do not hold any responsibility for accidents that happen when building your own QC3.0 power source!!!**_
|
||||
|
||||
|
||||
## PD
|
||||
|
||||
The following additional table is the list of devices compatible with hardware which requires Power Delivery support (>= 30W). Devices from the list have been successfully tested & used with TS80P in PD mode. Please, keep in mind that:
|
||||
|
||||
- PD can be provided only through usb-c <-> usb-c cable;
|
||||
- not only a charger but a cable itself should be capable to carry higher wattages.
|
||||
|
||||
|
||||
### Compatible Devices (PowerDelivery for TS80P)
|
||||
|
||||
| Device Name | IronOS FW |
|
||||
|-------------|:---------:|
|
||||
| Traver Charger QC09 (45W max)\* | OK |
|
||||
| Xiaomi AD65GEU Mi 65W Fast Charger with GaN Tech (AD65GEU, 65W max) | OK |
|
||||
|
||||
\* Comes as an _option_ for extra price in the package with TS80P from [official store](https://aliexpress.com/item/4000764937427.html) or from [NovelLife store separately](https://aliexpress.com/item/4001316262433.html) on AliExpress.
|
||||
|
||||
Please, DO NOT BUY cheap "fast chargers with QC/PD support" for a few dollars online (i.e., less than ~10$): if you check reviews, then you see that they are phonies - even if you get lucky, you probably get 5V/1A max from them.
|
||||
30
Documentation/README.md
Normal file
30
Documentation/README.md
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
<!-- THIS FILE IS AUTOGENERATED by "scripts/deploy.sh docs_readme" based on nav section in scripts/IronOS-mkdocs.yml config -->
|
||||
<!-- THIS FILE IS NOT SUPPOSED TO BE EDITED MANUALLY -->
|
||||
|
||||
#### This is autogenerated README for brief navigation through github over official documentation for IronOS project
|
||||
#### This documentation is also available [here online](https://ralim.github.io/IronOS)
|
||||
|
||||
- [Home](../Documentation/index.md)
|
||||
- [Getting Started](../Documentation/GettingStarted.md)
|
||||
- Flashing the firmware
|
||||
- [MHP30](../Documentation/Flashing/MHP30.md)
|
||||
- [Pinecil V1](../Documentation/Flashing/Pinecil%20V1.md)
|
||||
- [Pinecil V2](../Documentation/Flashing/Pinecil%20V2.md)
|
||||
- [TS80(P)](../Documentation/Flashing/TS80(P).md)
|
||||
- [TS100](../Documentation/Flashing/TS100.md)
|
||||
- Operation
|
||||
- [Main Menu](../Documentation/Menu.md)
|
||||
- [Settings](../Documentation/Settings.md)
|
||||
- [Debug Menu](../Documentation/DebugMenu.md)
|
||||
- [Power](../Documentation/Power.md)
|
||||
- [Temperature](../Documentation/Temperature.md)
|
||||
- [Startup Logo](../Documentation/Logo.md)
|
||||
- Hardware
|
||||
- [Hall Sensor (Pinecil)](../Documentation/HallSensor.md)
|
||||
- [Hardware Notes](../Documentation/Hardware.md)
|
||||
- [Troubleshooting](../Documentation/Troubleshooting.md)
|
||||
- [Known Hardware Issues](../Documentation/HardwareIssues.md)
|
||||
- [Power sources](../Documentation/PowerSources.md)
|
||||
- [Translations](../Documentation/Translation.md)
|
||||
- [Development](../Documentation/Development.md)
|
||||
@@ -14,6 +14,18 @@ But it is helpful to do some basic diagnostics first just in case the issue is e
|
||||
The **VAST** majority of issues are poor soldering or cold solder joints.
|
||||
If you can open up your iron, give it a good look at all the connection points, and use another iron to reflow any suspicious ones, this can fix most issues.
|
||||
|
||||
## Tip Shorted warning
|
||||
|
||||
If you are powering up a device that supports tip resistance detection (TS101 and Pinecilv2 as of present), the firmware checks the readings of the raw tip resistance and sorts these into three "bins". `8 ohm tips`, `6.2 ohm tips` and `tip-shorted`. The tip resistance is used when negotiating USB-PD and in thermal calculations.
|
||||
The `tip-shorted` option is selected if your tip is measured to be abnormally small. This could indicate a failed driver mosfet or a failed tip.
|
||||
|
||||
When this warning is shown; heating will be disabled to protect from damage. As trying to heat a shorted tip can damage the iron itself.
|
||||
|
||||
It is best to take out your tip and manually measure and verify the tip's resistance. It should be 6-8 ohms (depending on tip type). When measuring resistances this small some multimeters can struggle. If you have access to a current limited bench power supply, you can try doing a 4 wire measurement by measuring the voltage drop on the tip while applying a known current. `(R=V/I)`.
|
||||
|
||||
If the tip measures correctly you may have a damaged driver mosfet; it would be ideal to open your iron and test the mosfet is operating correctly.
|
||||
If after both of these checks everything looks as expected, feel free to open a discussion on IronOS to talk about the issue (Or for Pinecil the community chat can be a much faster response).
|
||||
|
||||
## High tip temp reading when the tip is cool
|
||||
|
||||
If you are finding the tip is reading high; the first fields to check in the Debug menu are `RTip` and `CHan`.
|
||||
|
||||
@@ -8,7 +8,7 @@ For soldering irons that are designed to be powered by batteries (TS100 & Pineci
|
||||
|
||||
Currently **31** languages are supported. When downloading the firmware for your soldering iron, take note of the language code in the file name.
|
||||
|
||||
This project is considered feature complete for use as a soldering iron, _so please suggest any feature improvements you would like!_
|
||||
This project is considered stable & feature complete for everyday use with a supported device, _so please suggest any feature improvements you would like!_
|
||||
|
||||
_This firmware does **NOT** support the USB port while running for changing settings. This is done through the onscreen menu only. Logos are edited on a computer and flashed like firmware._
|
||||
|
||||
@@ -39,6 +39,12 @@ For notes on installation for your device, please refer to the flashing guide fo
|
||||
- [TS80 / TS80P](https://ralim.github.io/IronOS/Flashing/TS80%28P%29/)
|
||||
- [TS100](https://ralim.github.io/IronOS/Flashing/TS100)
|
||||
|
||||
But the _generic_ [TL;DR](https://www.merriam-webster.com/dictionary/TL%3BDR) is to:
|
||||
|
||||
- [download firmware from here](https://github.com/Ralim/IronOS/releases) for the correct model with suitable language support;
|
||||
- put a device into DFU/bootloader mode (usually by keep holding A/+/front button while connecting a device to power source to power device on);
|
||||
- flash the firmware by drag-n-drop the firmware file using a file manager of your OS **or** using a separate flashing tool.
|
||||
|
||||
## Key Features
|
||||
|
||||
- PID style iron temperature control
|
||||
@@ -70,3 +76,25 @@ When on the main screen and having the tip plugged in, the unit shows a pair of
|
||||
- Holding down the button near the USB end will show the _[debug menu](https://ralim.github.io/IronOS/DebugMenu/)._ In _soldering mode_ this ends the heating.
|
||||
|
||||
Operation details are over in the [Menu information.](https://ralim.github.io/IronOS/Menu/)
|
||||
|
||||
## Feedback
|
||||
|
||||
If you would like to:
|
||||
|
||||
- report any issue related to IronOS
|
||||
- request a feature
|
||||
- provide some suggestion
|
||||
|
||||
then you can [fill this form](https://github.com/Ralim/IronOS/issues/new/choose) using github account\*.
|
||||
|
||||
And if you would like to:
|
||||
|
||||
- ask more generic question about IronOS/supported hardware/something you're curious about/etc.
|
||||
- reach out community to chat with
|
||||
- share your soldering & DIY skills
|
||||
- share some interesting finding
|
||||
- share useful related hardware/software with others
|
||||
|
||||
or _anything_ like that, then you can use forum-like [Discussions here](https://github.com/Ralim/IronOS/discussions).
|
||||
|
||||
\*: You may need to create it first if you don't have one - it's free of charge.
|
||||
|
||||
3
Env.yml
3
Env.yml
@@ -9,5 +9,4 @@ services:
|
||||
dockerfile: scripts/IronOS.Dockerfile
|
||||
command: /bin/sh
|
||||
volumes:
|
||||
- ./scripts/ci:/build/ci:Z
|
||||
- ./:/build/source:Z
|
||||
- ./:/build/ironos:Z
|
||||
|
||||
178
Makefile
178
Makefile
@@ -19,8 +19,6 @@ 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
|
||||
|
||||
@@ -29,6 +27,14 @@ ifndef MKDOCS
|
||||
MKDOCS:=mkdocs
|
||||
endif
|
||||
|
||||
# build output related directories
|
||||
ifdef OUT
|
||||
OUT_DIR=$(OUT)
|
||||
else
|
||||
OUT_DIR=$(CURDIR)/BUILDS
|
||||
endif
|
||||
OUT_HEX=$(CURDIR)/source/Hexfile
|
||||
|
||||
|
||||
### global static variables
|
||||
|
||||
@@ -45,62 +51,80 @@ DOCKER_CMD=$(DOCKER_BIN) -f $(DOCKER_YML) run --rm builder
|
||||
# MkDocs config
|
||||
MKDOCS_YML=$(CURDIR)/scripts/IronOS-mkdocs.yml
|
||||
|
||||
# supported models
|
||||
MODELS=TS100 TS80 TS80P Pinecil MHP30 Pinecilv2 S60 TS101 # target names & dir names
|
||||
MODELS_ML=Pinecil Pinecilv2 # target names
|
||||
MODELS_MULTILANG=Pinecil_multi-lang Pinecilv2_multi-lang # dir names
|
||||
|
||||
# zip command (to pack artifacts)
|
||||
ZIP=zip -q -j -r
|
||||
|
||||
|
||||
### targets
|
||||
|
||||
# default target to show help
|
||||
help:
|
||||
@echo
|
||||
@echo "Welcome!\nThis is $(INFO)"
|
||||
@echo "Welcome!"
|
||||
@echo "This 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 " * download, configure & start docker container"
|
||||
@echo " * compile builds of IronOS firmware for all supported models inside that container"
|
||||
@echo " * 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
|
||||
@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 " * help - shows short basic help"
|
||||
@echo " * list - this output"
|
||||
@echo " * docker-shell - start docker container with shell inside to work on IronOS with all tools needed"
|
||||
@echo " * docker-build - compile builds of IronOS for supported models inside docker container and place them to \"scripts/ci/artefacts/\""
|
||||
@echo " * docker-clean - delete created docker container (but not pre-downloaded data for it)"
|
||||
@echo " * docs - generate \"site\"/ directory with documentation in a form of static html files using ReadTheDocs framework and $(MKDOCS_YML) local config file"
|
||||
@echo " * docs-deploy - generate & deploy docs online to gh-pages branch of current github repo"
|
||||
@echo " * tests - run set of checks, linters & tests (equivalent of github CI IronOS project settings for push trigger)"
|
||||
@echo " * clean-build - delete generated files & dirs produced during builds EXCEPT generated docker container image"
|
||||
@echo " * clean-full - delete generated files & dirs produced during builds INCLUDING generated docker container image"
|
||||
@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 " * main Makefile is located in source/ directory and used to build the firmware itself;"
|
||||
@echo " * this top-level Makefile supports to call targets from source/Makefile;"
|
||||
@echo " * 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 " $$ 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 " * LANG_ID: $(shell echo "`ls Translations/ | grep -e "^translation_.*.json$$" | sed -e 's,^translation_,,g; s,\.json$$,,g; ' | tr '\n' ' '`")"
|
||||
@echo " * MODEL_ID: $(MODELS)"
|
||||
@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
|
||||
@echo " $$ 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' ' '`"
|
||||
# detect availability of docker
|
||||
docker-check:
|
||||
ifeq ($(DOCKER_BIN),)
|
||||
@echo "ERROR: Can't find docker-compose nor docker tool. Please, install docker and try again"
|
||||
@exit 1
|
||||
else
|
||||
@true
|
||||
endif
|
||||
|
||||
# former start_dev.sh
|
||||
docker-shell: $(DOCKER_DEPS)
|
||||
docker-shell: docker-check $(DOCKER_DEPS)
|
||||
$(DOCKER_CMD)
|
||||
|
||||
# former build.sh
|
||||
docker-build: $(DOCKER_DEPS)
|
||||
$(DOCKER_CMD) /bin/bash /build/ci/buildAll.sh
|
||||
docker-build: docker-check $(DOCKER_DEPS)
|
||||
$(DOCKER_CMD) make build-all
|
||||
|
||||
# delete container
|
||||
docker-clean:
|
||||
docker-clean: docker-check
|
||||
-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)
|
||||
@@ -111,15 +135,103 @@ docs: $(MKDOCS_YML) Documentation/* Documentation/Flashing/* Documentation/im
|
||||
docs-deploy: $(MKDOCS_YML) Documentation/* Documentation/Flashing/* Documentation/images/*
|
||||
$(MKDOCS) gh-deploy -f $(MKDOCS_YML) -d ../site
|
||||
|
||||
# routine check for autogenerated Documentation/README.md
|
||||
test-md:
|
||||
@echo ""
|
||||
@echo "---- Checking REAMDE.md... ----"
|
||||
@echo ""
|
||||
@/bin/sh ./scripts/deploy.sh docs_readme
|
||||
|
||||
# shell style & linter check (github CI version of shellcheck is more recent than alpine one so the latter may not catch some policies)
|
||||
test-sh:
|
||||
@echo ""
|
||||
@echo "---- Checking shell scripts... ----"
|
||||
@echo ""
|
||||
@for f in `find ./scripts -type f -iname "*.sh" ! -name "flash_ts100_linux.sh"` ; do shellcheck "$${f}"; done;
|
||||
|
||||
# python-related tests & checks
|
||||
test-py:
|
||||
@echo ""
|
||||
@echo "---- Checking python code... ----"
|
||||
@echo ""
|
||||
flake8 Translations
|
||||
black --check Translations
|
||||
@$(MAKE) -C source/ Objects/host/brieflz/libbrieflz.so
|
||||
./Translations/brieflz_test.py
|
||||
./Translations/make_translation_test.py
|
||||
|
||||
# clang-format check for C/C++ code style
|
||||
test-ccpp:
|
||||
@echo ""
|
||||
@echo "---- Checking C/C++ code... ----"
|
||||
@echo ""
|
||||
$(MAKE) -C source/ clean check-style
|
||||
|
||||
# meta target for tests & checks based on .github/workflows/push
|
||||
tests: test-md test-sh test-py test-ccpp
|
||||
@echo ""
|
||||
@echo "All tests & checks have been completed successfully."
|
||||
@echo ""
|
||||
|
||||
# former scripts/ci/buildAll.sh - all in one to build all firmware & place the produced binaries into one output directory
|
||||
build-all:
|
||||
@mkdir -p $(OUT_DIR)
|
||||
@chmod 0777 $(OUT_DIR)
|
||||
cd source && bash ./build.sh
|
||||
@echo "All Firmware built"
|
||||
@for model in $(MODELS); do \
|
||||
mkdir -p $(OUT_DIR)/$${model} ; \
|
||||
cp -r $(OUT_HEX)/$${model}_*.bin $(OUT_DIR)/$${model}/ ; \
|
||||
cp -r $(OUT_HEX)/$${model}_*.hex $(OUT_DIR)/$${model}/ ; \
|
||||
cp -r $(OUT_HEX)/$${model}_*.dfu $(OUT_DIR)/$${model}/ ; \
|
||||
done;
|
||||
@echo "Resulting output directory: $(OUT_DIR)"
|
||||
|
||||
# target to build multilang supported builds for Pinecil & PinecilV2
|
||||
build-multilang:
|
||||
@for modelml in $(MODELS_ML); do \
|
||||
$(MAKE) -C source/ -j2 model=$${modelml} firmware-multi_compressed_European firmware-multi_compressed_Bulgarian+Russian+Serbian+Ukrainian firmware-multi_Chinese+Japanese ; \
|
||||
mkdir -p $(OUT_DIR)/$${modelml}_multi-lang ; \
|
||||
cp $(OUT_HEX)/$${modelml}_multi_*.bin $(OUT_DIR)/$${modelml}_multi-lang ; \
|
||||
cp $(OUT_HEX)/$${modelml}_multi_*.hex $(OUT_DIR)/$${modelml}_multi-lang ; \
|
||||
cp $(OUT_HEX)/$${modelml}_multi_*.dfu $(OUT_DIR)/$${modelml}_multi-lang ; \
|
||||
done;
|
||||
@echo "Resulting output directory: $(OUT_DIR)"
|
||||
|
||||
# target to reproduce zips according to github CI settings; artifacts will be in $(OUT_DIR)/CI/*.zip
|
||||
ci: tests build-all build-multilang
|
||||
@mkdir -p $(OUT_DIR)/metadata;
|
||||
@for m in $(MODELS) $(MODELS_MULTILANG); do \
|
||||
cp LICENSE scripts/LICENSE_RELEASE.md $(OUT_DIR)/$${m}/ ; \
|
||||
$(ZIP) $(OUT_DIR)/$${m}.zip $(OUT_DIR)/$${m} ; \
|
||||
./source/metadata.py $${m}.json $${m}; \
|
||||
cp $(OUT_HEX)/$${m}.json $(OUT_DIR)/metadata; \
|
||||
done;
|
||||
@$(ZIP) $(OUT_DIR)/metadata.zip $(OUT_DIR)/metadata
|
||||
@mkdir -p $(OUT_DIR)/CI
|
||||
@mv $(OUT_DIR)/*.zip $(OUT_DIR)/CI
|
||||
@chmod 0777 $(OUT_DIR)/CI
|
||||
@chmod 0666 $(OUT_DIR)/CI/*.zip
|
||||
@echo "Resulting artifacts directory: $(OUT_DIR)/CI"
|
||||
|
||||
# pass-through target for Makefile inside source/ dir
|
||||
%:
|
||||
make -C source/ $@
|
||||
$(MAKE) -C source/ $@
|
||||
|
||||
# global clean-up target
|
||||
clean-full: docker-clean
|
||||
make -C source/ clean-all
|
||||
# global clean-up target for produced/generated files inside tree
|
||||
clean-build:
|
||||
$(MAKE) -C source/ clean-all
|
||||
rm -Rf site
|
||||
rm -Rf scripts/ci/artefacts
|
||||
rm -Rf $(OUT_DIR)
|
||||
|
||||
.PHONY: docker-shell docker-build docker-clean docs clean-full
|
||||
# global clean-up target
|
||||
clean-full: clean-build docker-clean
|
||||
|
||||
# phony targets
|
||||
.PHONY: help list
|
||||
.PHONY: docker-check docker-shell docker-build docker-clean
|
||||
.PHONY: docs docs-deploy
|
||||
.PHONY: test-md test-sh test-py test-ccpp tests
|
||||
.PHONY: build-all build-multilang ci
|
||||
.PHONY: clean-build clean-full
|
||||
|
||||
30
README.md
30
README.md
@@ -21,18 +21,28 @@ This project is considered feature complete for use as a soldering iron, _so ple
|
||||
|
||||
_This firmware does **NOT** support the USB port while running for changing settings. This is done through the onscreen menu only. Logos are edited on a computer and flashed like firmware._
|
||||
|
||||
| Device | DC | QC | PD | EPR | BLE | Battery | Recommended |
|
||||
| :--------: | :-: | :-: | :-: | :-: | :-: | :-----: | :---------: |
|
||||
| MHP30 | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ✔️ |
|
||||
| Pinecil V1 | ✔️ | ✔️ | ✔️ | ❌ | ❌ | ✔️ | ✔️ |
|
||||
| Pinecil V2 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
|
||||
| TS80P | ❌ | ✔️ | ✔️ | ❌ | ❌ | ✔️ | ✔️ |
|
||||
| TS100 | ✔️ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌* |
|
||||
| TS80 | ❌ | ✔️ | ❌ | ❌ | ❌ | ✔️ | ❌** |
|
||||
| Device | DC | QC | PD | EPR | BLE | Tip Sense | Recommended Purchase | Notes |
|
||||
| :------------: | :-: | :-: | :-: | :-: | :-: | :-----: | :------------------: | :-------------------------------------------:|
|
||||
| Miniware MHP30 | ❌ | ❌ | ✔️ | ❌ | ❌ | ✔️ | ✔️ | |
|
||||
| Pinecil V1 | ✔️ | ✔️ | ✔️ | ❌ | ❌ | ❌ | ❌ * | |
|
||||
| Pinecil V2 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | |
|
||||
| Miniware TS101 | ✔️ | ❌ | ✔️ | ✔️ | ❌ | ✔️ | ✔️ | Full OLED resolution not yet supported. |
|
||||
| Sequre S60 | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ✔️ | Full OLED resolution not yet supported. |
|
||||
| Miniware TS80P | ❌ | ✔️ | ✔️ | ❌ | ❌ | N/A | ✔️ | |
|
||||
| Miniware TS100 | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌** | |
|
||||
| Miniware TS80 | ❌ | ✔️ | ❌ | ❌ | ❌ | N/A | ❌*** | |
|
||||
|
||||
\*Please note that Miniware started shipping TS100's using cloned STM32 Chips. While these do work with IronOS, their DFU bootloader works terribly, and it is hard to get it to successfully flash larger firmware images like IronOS without timing out. This is the main reason why the TS100 is **_no longer recommended_**.
|
||||
_Tip Sense_ refers to the device being able to choose between the 'usual' TS100 or Hakko T12 style tips and Pine64's custom shorter tips which have lower resistance and allow for more power. This is N/A for TS80/TS80P as there is only one model of tip for them.
|
||||
|
||||
\**TS80 is replaced by TS80P. Production ramped down a long time ago and it's just existing stock clearing the system. It's marked not recommended being optimistic that people might pause and buy the far superior TS80P instead. This is the main reason why the TS80 is **_no longer recommended_**.
|
||||
_Recommended Purchase_ is only referring to if you are buying a **new** device. Of course all the devices listed are supported and will work excellently for years to come.
|
||||
|
||||
The TS101 and S60 feature a higher resolution OLED than other devices. Work is ongoing to support this fully, for now a cropped view is usable.
|
||||
|
||||
\*PinecilV1 stopped being manufactured a long time ago now, all models for sale online are generally clones (or old stock). Vendors are trying to sell these for more than Pine64 sells the V2 for now. Thus the V1 is **_no longer recommended_**.
|
||||
|
||||
\**Please note that Miniware started shipping TS100's using cloned STM32 Chips. While these do work with IronOS, their DFU bootloader works terribly, and it is hard to get it to successfully flash larger firmware images like IronOS without timing out. This is the main reason why the TS100 is **_no longer recommended_**.
|
||||
|
||||
\**\*TS80 is replaced by TS80P. Production ramped down a long time ago and it's just existing stock clearing the system. It's marked not recommended being optimistic that people might pause and buy the far superior TS80P instead. This is the main reason why the TS80 is **_no longer recommended_**.
|
||||
|
||||
## Getting Started
|
||||
|
||||
|
||||
0
Translations/brieflz.py
Normal file → Executable file
0
Translations/brieflz.py
Normal file → Executable file
0
Translations/brieflz_test.py
Normal file → Executable file
0
Translations/brieflz_test.py
Normal file → Executable file
@@ -1263,6 +1263,57 @@ def get_translation_sanity_checks_text(defs: dict) -> str:
|
||||
return sanity_checks_text
|
||||
|
||||
|
||||
def get_version_suffix(ver) -> str:
|
||||
# Check env var from push.yml first:
|
||||
# - if it's pull request then use vX.YY + C.ID for version line as in *C*I with proper tag instead of merge tag for detached tree
|
||||
if os.environ.get("GITHUB_CI_PR_SHA", "") != "":
|
||||
return "C" + "." + os.environ["GITHUB_CI_PR_SHA"][:8].upper()
|
||||
# - no github PR SHA ID, hence keep checking
|
||||
|
||||
suffix = str("")
|
||||
|
||||
try:
|
||||
# Use commands _hoping_ they won't be too new for one environments nor deprecated for another ones:
|
||||
## - get commit id; --short=8 - the shorted hash with 8 digits (increase/decrease if needed!)
|
||||
sha_id = f"{subprocess.check_output(['git', 'rev-parse', '--short=8', 'HEAD']).strip().decode('ascii').upper()}"
|
||||
## - if the exact commit relates to tag, then this command should return one-line tag name:
|
||||
tag = f"{subprocess.check_output(['git', 'tag', '--points-at', '%s' % sha_id]).strip().decode('ascii')}"
|
||||
## - get short "traditional" branch name (as in `git branch` for that one with asterisk):
|
||||
branch = f"{subprocess.check_output(['git', 'symbolic-ref', '--short', 'HEAD']).strip().decode('ascii')}"
|
||||
if tag and "" != tag:
|
||||
# _Speculate_ on tag that it's Release...
|
||||
if ver == tag:
|
||||
# ... but only if double-check for tag is matched
|
||||
suffix = "R"
|
||||
else:
|
||||
# ... otherwise it's tagged but not a release version!
|
||||
suffix = "T"
|
||||
elif branch and "" != branch:
|
||||
# _Hardcoded_ current main development branch...
|
||||
if "dev" == branch:
|
||||
suffix = "D"
|
||||
# ... or some other branch
|
||||
else:
|
||||
suffix = "B"
|
||||
else:
|
||||
# Something else but from Git
|
||||
suffix = "G"
|
||||
# Attach SHA commit to ID a build since it's from git anyway
|
||||
suffix += "." + sha_id
|
||||
except subprocess.CalledProcessError:
|
||||
# No git tree so _probably_ Homebrew build from source
|
||||
suffix = "H"
|
||||
except OSError:
|
||||
# Something _special_?
|
||||
suffix = "S"
|
||||
|
||||
if "" == suffix:
|
||||
# Something _very_ special!
|
||||
suffix = "V"
|
||||
|
||||
return suffix
|
||||
|
||||
|
||||
def read_version() -> str:
|
||||
with open(HERE.parent / "source" / "version.h") as version_file:
|
||||
for line in version_file:
|
||||
@@ -1270,11 +1321,7 @@ def read_version() -> str:
|
||||
matches = re.findall(r"\"(.+?)\"", line)
|
||||
if matches:
|
||||
version = matches[0]
|
||||
try:
|
||||
version += f".{subprocess.check_output(['git', 'rev-parse', '--short=7', 'HEAD']).strip().decode('ascii').upper()}"
|
||||
# --short=7: the shorted hash with 7 digits. Increase/decrease if needed!
|
||||
except OSError:
|
||||
version += " git"
|
||||
version += get_version_suffix(version)
|
||||
return version
|
||||
|
||||
|
||||
|
||||
0
Translations/objcopy.py
Normal file → Executable file
0
Translations/objcopy.py
Normal file → Executable file
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Беларуская",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Каліброўка\nзроблена!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Некантралюемае\nразаграванне"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Пераканайцеся, што пры наступнай загрузцы наканечнік і ручка маюць пакаёвую тэмпературу!"
|
||||
},
|
||||
@@ -313,4 +316,4 @@
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Български",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration\ndone!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Thermal\nRunaway"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
},
|
||||
@@ -313,4 +316,4 @@
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Český",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Kalibrace\ndokončena!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Teplotní\nOchrana"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Před restartem se ujistěte, že hrot a držák mají pokojovou teplotu!"
|
||||
},
|
||||
@@ -313,4 +316,4 @@
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Dansk",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration\ndone!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Thermal\nRunaway"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Deutsch",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Erfolgreich\nkalibriert!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Thermal\nRunaway"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Vor dem Neustart bitte sicherstellen, dass Lötspitze & Gerät Raumtemperatur haben!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Greek",
|
||||
"tempUnitFahrenheit": true,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Βαθμονόμηση\nολοκληρώθηκε!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Θερμική\nΦυγή"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Πριν την επανεκκίνηση, βεβαιωθείτε ότι η μύτη και η συσκ. είναι σε θερμ. δωματίου!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "English",
|
||||
"tempUnitFahrenheit": true,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration\ndone!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Thermal\nRunaway"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Castellano",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "¡Calibracion\nlista!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Térmico\nFuera de control"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "¡Antes de reiniciar, asegúrese de que la punta y el mango estén a temperatura ambiente!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Suomi",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration\ndone!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Thermal\nRunaway"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Français",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Étalonnage\nterminé!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Emballement\nthermique"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Avant de redémarrer, assurez-vous que la panne et la poignée sont à température ambiante !"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Hrvatski",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Kalibracija\ndovršena!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Neispravan\ngrijač"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Prije restarta provjerite da su vrh i ručka na sobnoj temperaturi!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Magyar",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Kalibráció\nkész!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Kontrollálatlan\nhőmérséklet!"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Újraindítás előtt a hegy és az eszköz legyen szobahőmérsékletű!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Italiano",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibrazione\ncompletata!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Temperatura\nfuori controllo"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Prima di riavviare assicurati che la punta e l'impugnatura siano a temperatura ambiente!"
|
||||
},
|
||||
@@ -162,7 +165,7 @@
|
||||
},
|
||||
"ProfilePreheatSpeed": {
|
||||
"displayText": "Velocità\npreriscaldamento",
|
||||
"description": "Imposta la velocità di preriscaldamento [gradi al secondo]"
|
||||
"description": "Imposta la velocità di preriscaldamento [°C/s]"
|
||||
},
|
||||
"ProfilePhase1Temp": {
|
||||
"displayText": "Temperatura\nfase 1",
|
||||
@@ -206,7 +209,7 @@
|
||||
},
|
||||
"ProfileCooldownSpeed": {
|
||||
"displayText": "Velocità\nraffreddamento",
|
||||
"description": "Imposta la velocità di raffreddamento al termine del profilo di riscaldamento [gradi al secondo]"
|
||||
"description": "Imposta la velocità di raffreddamento al termine del profilo di riscaldamento [°C/s]"
|
||||
},
|
||||
"MotionSensitivity": {
|
||||
"displayText": "Sensibilità\nal movimento",
|
||||
|
||||
5
Translations/translation_JA_JP.json
Executable file → Normal file
5
Translations/translation_JA_JP.json
Executable file → Normal file
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "日本語",
|
||||
"tempUnitFahrenheit": true,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration done!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "過熱"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Lietuvių",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration\ndone!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Perkaitimo\npavojus"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Norsk bokmål",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration\ndone!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Termisk\nrømling"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Nederlands",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration\ndone!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Verwarming\nOncontroleerbaar"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Vlaams",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration\ndone!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Thermal\nRunaway"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Polski",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Kalibracja\nwykonana!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Ucieczka\ntermiczna"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Upewnij się, że końcówka i uchwyt mają temperaturę pokojową podczas następnego rozruchu!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Português",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibração\nefetuada!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Thermal\nRunaway"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Antes de reiniciar certifique-se que o ferro está à temperatura ambiente!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Română",
|
||||
"tempUnitFahrenheit": true,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration\ndone!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Încălzire\nEşuată"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Înainte de repornire, asiguraţi-vă că vârful şi mânerul sunt la temperatura camerei!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Русский",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Калибровка\nзавершена!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Неуправляемый\nРазогрев"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Пожалуйста, убедитесь, что жало и корпус имеют комнатную температуру при следующей загрузке!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Slovenčina",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration\ndone!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Únik\nTepla"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Slovenščina",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration\ndone!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Thermal\nRunaway"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Српски",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration\ndone!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Thermal\nRunaway"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Srpski",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration\ndone!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Thermal\nRunaway"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Svenska",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration\ndone!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Thermal\nRunaway"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Türkçe",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration\ndone!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Thermal\nRunaway"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Українська",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "КХС\nвідкалібровано!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Некерований\nрозігрів"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Під час наступного завантаження переконайтеся, що жало і ручка мають кімнатну температуру!"
|
||||
},
|
||||
@@ -61,16 +64,16 @@
|
||||
"message": "Вимк"
|
||||
},
|
||||
"ProfilePreheatString": {
|
||||
"message": "Preheat\n"
|
||||
"message": "Попередній\nрозігрів"
|
||||
},
|
||||
"ProfileCooldownString": {
|
||||
"message": "Cooldown\n"
|
||||
"message": "Охолодження\n"
|
||||
},
|
||||
"DeviceFailedValidationWarning": {
|
||||
"message": "Вірогідно ваш пристрій підробний!"
|
||||
},
|
||||
"TooHotToStartProfileWarning": {
|
||||
"message": "Too hot to\nstart profile"
|
||||
"message": "Занадто гараче для\nзміни профілів"
|
||||
}
|
||||
},
|
||||
"characters": {
|
||||
@@ -153,60 +156,60 @@
|
||||
"description": "Під час пайки тривале натискання обох кнопок заблокує їх (В=Вимк | Т=Тільки турбо | П=Повне)"
|
||||
},
|
||||
"ProfilePhases": {
|
||||
"displayText": "Profile\nPhases",
|
||||
"description": "Number of phases in profile mode"
|
||||
"displayText": "Етапи\nпрофілів",
|
||||
"description": "Кількість етапів в режимі профілів"
|
||||
},
|
||||
"ProfilePreheatTemp": {
|
||||
"displayText": "Preheat\nTemp",
|
||||
"description": "Preheat to this temperature at the start of profile mode"
|
||||
"displayText": "Температура\nПоп.Розігріву",
|
||||
"description": "Попередньо розігріти до цієї температури на початку режимку профілів"
|
||||
},
|
||||
"ProfilePreheatSpeed": {
|
||||
"displayText": "Preheat\nSpeed",
|
||||
"description": "Preheat at this rate (degrees per second)"
|
||||
"displayText": "Швидкість\nПоп.Розігріву",
|
||||
"description": "Розігрівати з такою швидкістю (градусів в секунду)"
|
||||
},
|
||||
"ProfilePhase1Temp": {
|
||||
"displayText": "Phase 1\nTemp",
|
||||
"description": "Target temperature for the end of this phase"
|
||||
"displayText": "Етап 1\nТемпература",
|
||||
"description": "Температура в кінці цього етапу"
|
||||
},
|
||||
"ProfilePhase1Duration": {
|
||||
"displayText": "Phase 1\nDuration",
|
||||
"description": "Target duration of this phase (seconds)"
|
||||
"displayText": "Етап 1\nТривалість",
|
||||
"description": "Тривалість цього етапу (секунд)"
|
||||
},
|
||||
"ProfilePhase2Temp": {
|
||||
"displayText": "Phase 2\nTemp",
|
||||
"displayText": "Етап 2\nТемпература",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase2Duration": {
|
||||
"displayText": "Phase 2\nDuration",
|
||||
"displayText": "Етап 2\nТривалість",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase3Temp": {
|
||||
"displayText": "Phase 3\nTemp",
|
||||
"displayText": "Етап 3\nТемпература",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase3Duration": {
|
||||
"displayText": "Phase 3\nDuration",
|
||||
"displayText": "Етап 3\nТривалість",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase4Temp": {
|
||||
"displayText": "Phase 4\nTemp",
|
||||
"displayText": "Етап 4\nТемпература",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase4Duration": {
|
||||
"displayText": "Phase 4\nDuration",
|
||||
"displayText": "Етап 4\nТривалість",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase5Temp": {
|
||||
"displayText": "Phase 5\nTemp",
|
||||
"displayText": "Етап 5\nТемпература",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase5Duration": {
|
||||
"displayText": "Phase 5\nDuration",
|
||||
"displayText": "Етап 5\nТривалість",
|
||||
"description": ""
|
||||
},
|
||||
"ProfileCooldownSpeed": {
|
||||
"displayText": "Cooldown\nSpeed",
|
||||
"description": "Cooldown at this rate at the end of profile mode (degrees per second)"
|
||||
"displayText": "Швидкість\nОхолодження",
|
||||
"description": "Швидкість охолодження в кінці режиму профілів (градусів в секунду)"
|
||||
},
|
||||
"MotionSensitivity": {
|
||||
"displayText": "Чутливість\nсенсору руху",
|
||||
@@ -278,7 +281,7 @@
|
||||
},
|
||||
"BluetoothLE": {
|
||||
"displayText": "Bluetooth\n",
|
||||
"description": "Enables BLE"
|
||||
"description": "Увімкнути BLE"
|
||||
},
|
||||
"PowerLimit": {
|
||||
"displayText": "Макс.\nпотуж.",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "Tieng Viet",
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration\ndone!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Nhiet\nTat gia nhiet"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "廣東話 (香港)",
|
||||
"tempUnitFahrenheit": true,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration done!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "加熱失控"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "简体中文",
|
||||
"tempUnitFahrenheit": true,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration done!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "加热失控"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
},
|
||||
@@ -313,4 +316,4 @@
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
"languageLocalName": "正體中文",
|
||||
"tempUnitFahrenheit": true,
|
||||
"messagesWarn": {
|
||||
"CJCCalibrationDone": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration done!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
@@ -30,6 +30,9 @@
|
||||
"WarningThermalRunaway": {
|
||||
"message": "加熱失控"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
},
|
||||
@@ -313,4 +316,4 @@
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"messagesWarn": [{
|
||||
"id": "CJCCalibrationDone",
|
||||
"description": "Confirmation message indicating CJC calibration is complete."
|
||||
"id": "CalibrationDone",
|
||||
"description": "Confirmation message indicating calibration is complete."
|
||||
},
|
||||
{
|
||||
"id": "ResetOKMessage",
|
||||
@@ -17,7 +17,9 @@
|
||||
},
|
||||
{
|
||||
"id": "NoPowerDeliveryMessage",
|
||||
"include": ["POW_PD"],
|
||||
"include": [
|
||||
"POW_PD"
|
||||
],
|
||||
"description": "The IC required for USB-PD could not be communicated with. This is an error warning that USB-PD WILL NOT FUNCTION. Generally indicative of either a hardware or software issues."
|
||||
},
|
||||
{
|
||||
@@ -35,7 +37,12 @@
|
||||
{
|
||||
"id": "WarningThermalRunaway",
|
||||
"description": "Warning text shown when the software has disabled the heater as a safety precaution as the temperature reading didn't react as expected."
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"id": "WarningTipShorted",
|
||||
"description": "Warning text shown when the software has detected that the users tip is likely shorted."
|
||||
},
|
||||
{
|
||||
"id": "SettingsCalibrationWarning",
|
||||
"description": "Confirmation message shown before performing an offset calibration. Should warn the user to make sure tip and handle are at the same temperature."
|
||||
},
|
||||
@@ -50,50 +57,66 @@
|
||||
{
|
||||
"id": "UVLOWarningString",
|
||||
"maxLen": 8,
|
||||
"include": ["POW_DC"],
|
||||
"include": [
|
||||
"POW_DC"
|
||||
],
|
||||
"description": "Warning text shown when the unit turns off due to undervoltage in simple mode."
|
||||
},
|
||||
{
|
||||
"id": "UndervoltageString",
|
||||
"maxLen": 15,
|
||||
"include": ["POW_DC"],
|
||||
"include": [
|
||||
"POW_DC"
|
||||
],
|
||||
"description": "Warning text shown when the unit turns off due to undervoltage in advanced mode."
|
||||
},
|
||||
{
|
||||
"id": "InputVoltageString",
|
||||
"maxLen": 11,
|
||||
"note": "Preferably end with a space",
|
||||
"include": ["POW_DC"],
|
||||
"include": [
|
||||
"POW_DC"
|
||||
],
|
||||
"description": "Prefix text for 'Input Voltage' shown before showing the input voltage reading."
|
||||
},
|
||||
{
|
||||
"id": "ProfilePreheatString",
|
||||
"maxLen": 9,
|
||||
"include": ["PROFILE_SUPPORT"],
|
||||
"include": [
|
||||
"PROFILE_SUPPORT"
|
||||
],
|
||||
"description": "Shown in profile mode while preheating"
|
||||
},
|
||||
{
|
||||
"id": "ProfileCooldownString",
|
||||
"maxLen": 9,
|
||||
"include": ["PROFILE_SUPPORT"],
|
||||
"include": [
|
||||
"PROFILE_SUPPORT"
|
||||
],
|
||||
"description": "Shown in profile mode while cooling down"
|
||||
},
|
||||
{
|
||||
"id": "SleepingSimpleString",
|
||||
"maxLen": 4,
|
||||
"exclude": ["NO_SLEEP_MODE"],
|
||||
"exclude": [
|
||||
"NO_SLEEP_MODE"
|
||||
],
|
||||
"description": "The text shown to indicate the unit is in sleep mode when the advanced view is NOT on."
|
||||
},
|
||||
{
|
||||
"id": "SleepingAdvancedString",
|
||||
"maxLen": 15,
|
||||
"exclude": ["NO_SLEEP_MODE"],
|
||||
"exclude": [
|
||||
"NO_SLEEP_MODE"
|
||||
],
|
||||
"description": "The text shown to indicate the unit is in sleep mode when the advanced view is turned on."
|
||||
},
|
||||
{
|
||||
"id": "SleepingTipAdvancedString",
|
||||
"maxLen": 6,
|
||||
"exclude": ["NO_SLEEP_MODE"],
|
||||
"exclude": [
|
||||
"NO_SLEEP_MODE"
|
||||
],
|
||||
"description": "The prefix text shown before tip temperature when the unit is sleeping with advanced view on."
|
||||
},
|
||||
{
|
||||
@@ -109,11 +132,14 @@
|
||||
{
|
||||
"id": "TooHotToStartProfileWarning",
|
||||
"default": "Too hot to\nstart profile",
|
||||
"include": ["PROFILE_SUPPORT"],
|
||||
"include": [
|
||||
"PROFILE_SUPPORT"
|
||||
],
|
||||
"description": "Shown when profile mode is started while the device is too hot."
|
||||
}
|
||||
],
|
||||
"characters": [{
|
||||
"characters": [
|
||||
{
|
||||
"id": "SettingRightChar",
|
||||
"len": 1,
|
||||
"description": "Shown for fixed Right-handed display rotation."
|
||||
@@ -187,11 +213,15 @@
|
||||
"description": "Shown when the locking mode is set to lock all buttons."
|
||||
}
|
||||
],
|
||||
"menuGroups": [{
|
||||
"menuGroups": [
|
||||
{
|
||||
"id": "PowerMenu",
|
||||
"maxLen": 5,
|
||||
"maxLen2": 11,
|
||||
"include": ["POW_DC", "POW_QC"],
|
||||
"include": [
|
||||
"POW_DC",
|
||||
"POW_QC"
|
||||
],
|
||||
"description": "Menu for settings related to power. Main settings to do with the input voltage."
|
||||
},
|
||||
{
|
||||
@@ -219,39 +249,50 @@
|
||||
"description": "Advanced settings. Misc catchall for settings that don't fit anywhere else or settings that require some thought before use."
|
||||
}
|
||||
],
|
||||
"menuOptions": [{
|
||||
"menuOptions": [
|
||||
{
|
||||
"id": "DCInCutoff",
|
||||
"maxLen": 5,
|
||||
"maxLen2": 11,
|
||||
"include": ["POW_DC"],
|
||||
"include": [
|
||||
"POW_DC"
|
||||
],
|
||||
"description": "When the device is powered by a battery, this adjusts the low voltage threshold for when the unit should turn off the heater to protect the battery."
|
||||
},
|
||||
{
|
||||
"id": "MinVolCell",
|
||||
"maxLen": 4,
|
||||
"maxLen2": 9,
|
||||
"include": ["POW_DC"],
|
||||
"include": [
|
||||
"POW_DC"
|
||||
],
|
||||
"description": "When powered by a battery, this adjusts the minimum voltage per cell before shutdown. (This is multiplied by the cell count.)"
|
||||
},
|
||||
{
|
||||
"id": "QCMaxVoltage",
|
||||
"maxLen": 8,
|
||||
"maxLen2": 15,
|
||||
"include": ["POW_QC"],
|
||||
"include": [
|
||||
"POW_QC"
|
||||
],
|
||||
"description": "This adjusts the maximum voltage the QC negotiation will adjust to. Does NOT affect USB-PD. Should be set safely based on the current rating of your power supply."
|
||||
},
|
||||
{
|
||||
"id": "PDNegTimeout",
|
||||
"maxLen": 8,
|
||||
"maxLen2": 15,
|
||||
"include": ["POW_PD"],
|
||||
"include": [
|
||||
"POW_PD"
|
||||
],
|
||||
"description": "How long until firmware stops trying to negotiate for USB-PD and tries QC instead. Longer times may help dodgy / old PD adapters, faster times move onto PD quickly. Units of 100ms. Recommended to keep small values."
|
||||
},
|
||||
{
|
||||
"id": "PDVpdo",
|
||||
"maxLen": 7,
|
||||
"maxLen2": 15,
|
||||
"include": ["POW_PD"],
|
||||
"include": [
|
||||
"POW_PD"
|
||||
],
|
||||
"description": "Enabled PPS & EPR modes."
|
||||
},
|
||||
{
|
||||
@@ -288,98 +329,126 @@
|
||||
"id": "ProfilePhases",
|
||||
"maxLen": 6,
|
||||
"maxLen2": 13,
|
||||
"include": ["PROFILE_SUPPORT"],
|
||||
"include": [
|
||||
"PROFILE_SUPPORT"
|
||||
],
|
||||
"description": "set the number of phases for profile mode."
|
||||
},
|
||||
{
|
||||
"id": "ProfilePreheatTemp",
|
||||
"maxLen": 4,
|
||||
"maxLen2": 9,
|
||||
"include": ["PROFILE_SUPPORT"],
|
||||
"include": [
|
||||
"PROFILE_SUPPORT"
|
||||
],
|
||||
"description": "Preheat to this temperature at the start of profile mode."
|
||||
},
|
||||
{
|
||||
"id": "ProfilePreheatSpeed",
|
||||
"maxLen": 5,
|
||||
"maxLen2": 11,
|
||||
"include": ["PROFILE_SUPPORT"],
|
||||
"include": [
|
||||
"PROFILE_SUPPORT"
|
||||
],
|
||||
"description": "How fast the temperature is allowed to rise during the preheat phase at the start of profile mode."
|
||||
},
|
||||
{
|
||||
"id": "ProfilePhase1Temp",
|
||||
"maxLen": 4,
|
||||
"maxLen2": 9,
|
||||
"include": ["PROFILE_SUPPORT"],
|
||||
"include": [
|
||||
"PROFILE_SUPPORT"
|
||||
],
|
||||
"description": "Target temperature for the end of phase 1 of profile mode."
|
||||
},
|
||||
{
|
||||
"id": "ProfilePhase1Duration",
|
||||
"maxLen": 4,
|
||||
"maxLen2": 9,
|
||||
"include": ["PROFILE_SUPPORT"],
|
||||
"include": [
|
||||
"PROFILE_SUPPORT"
|
||||
],
|
||||
"description": "Duration of phase 1 of profile mode. The phase might actually take longer if it takes longer to reach the target temperature."
|
||||
},
|
||||
{
|
||||
"id": "ProfilePhase2Temp",
|
||||
"maxLen": 4,
|
||||
"maxLen2": 9,
|
||||
"include": ["PROFILE_SUPPORT"],
|
||||
"include": [
|
||||
"PROFILE_SUPPORT"
|
||||
],
|
||||
"description": "Target temperature for the end of phase 2 of profile mode."
|
||||
},
|
||||
{
|
||||
"id": "ProfilePhase2Duration",
|
||||
"maxLen": 4,
|
||||
"maxLen2": 9,
|
||||
"include": ["PROFILE_SUPPORT"],
|
||||
"include": [
|
||||
"PROFILE_SUPPORT"
|
||||
],
|
||||
"description": "Duration of phase 2 of profile mode. The phase might actually take longer if it takes longer to reach the target temperature."
|
||||
},
|
||||
{
|
||||
"id": "ProfilePhase3Temp",
|
||||
"maxLen": 4,
|
||||
"maxLen2": 9,
|
||||
"include": ["PROFILE_SUPPORT"],
|
||||
"include": [
|
||||
"PROFILE_SUPPORT"
|
||||
],
|
||||
"description": "Target temperature for the end of phase 3 of profile mode."
|
||||
},
|
||||
{
|
||||
"id": "ProfilePhase3Duration",
|
||||
"maxLen": 4,
|
||||
"maxLen2": 9,
|
||||
"include": ["PROFILE_SUPPORT"],
|
||||
"include": [
|
||||
"PROFILE_SUPPORT"
|
||||
],
|
||||
"description": "Duration of phase 3 of profile mode. The phase might actually take longer if it takes longer to reach the target temperature."
|
||||
},
|
||||
{
|
||||
"id": "ProfilePhase4Temp",
|
||||
"maxLen": 4,
|
||||
"maxLen2": 9,
|
||||
"include": ["PROFILE_SUPPORT"],
|
||||
"include": [
|
||||
"PROFILE_SUPPORT"
|
||||
],
|
||||
"description": "Target temperature for the end of phase 5 of profile mode."
|
||||
},
|
||||
{
|
||||
"id": "ProfilePhase4Duration",
|
||||
"maxLen": 4,
|
||||
"maxLen2": 9,
|
||||
"include": ["PROFILE_SUPPORT"],
|
||||
"include": [
|
||||
"PROFILE_SUPPORT"
|
||||
],
|
||||
"description": "Duration of phase 5 of profile mode. The phase might actually take longer if it takes longer to reach the target temperature."
|
||||
},
|
||||
{
|
||||
"id": "ProfilePhase5Temp",
|
||||
"maxLen": 4,
|
||||
"maxLen2": 9,
|
||||
"include": ["PROFILE_SUPPORT"],
|
||||
"include": [
|
||||
"PROFILE_SUPPORT"
|
||||
],
|
||||
"description": "Target temperature for the end of phase 5 of profile mode."
|
||||
},
|
||||
{
|
||||
"id": "ProfilePhase5Duration",
|
||||
"maxLen": 4,
|
||||
"maxLen2": 9,
|
||||
"include": ["PROFILE_SUPPORT"],
|
||||
"include": [
|
||||
"PROFILE_SUPPORT"
|
||||
],
|
||||
"description": "Duration of phase 5 of profile mode. The phase might actually take longer if it takes longer to reach the target temperature."
|
||||
},
|
||||
{
|
||||
"id": "ProfileCooldownSpeed",
|
||||
"maxLen": 5,
|
||||
"maxLen2": 11,
|
||||
"include": ["PROFILE_SUPPORT"],
|
||||
"include": [
|
||||
"PROFILE_SUPPORT"
|
||||
],
|
||||
"description": "How fast the temperature is allowed to drop during the cooldown phase at the end of profile mode."
|
||||
},
|
||||
{
|
||||
@@ -392,14 +461,18 @@
|
||||
"id": "SleepTemperature",
|
||||
"maxLen": 4,
|
||||
"maxLen2": 9,
|
||||
"exclude": ["NO_SLEEP_MODE"],
|
||||
"exclude": [
|
||||
"NO_SLEEP_MODE"
|
||||
],
|
||||
"description": "Temperature the device will drop down to while asleep. Typically around halfway between off and soldering temperature."
|
||||
},
|
||||
{
|
||||
"id": "SleepTimeout",
|
||||
"maxLen": 4,
|
||||
"maxLen2": 9,
|
||||
"exclude": ["NO_SLEEP_MODE"],
|
||||
"exclude": [
|
||||
"NO_SLEEP_MODE"
|
||||
],
|
||||
"description": "How long of a period without movement / button-pressing is required before the device drops down to the sleep temperature."
|
||||
},
|
||||
{
|
||||
@@ -412,7 +485,9 @@
|
||||
"id": "HallEffSensitivity",
|
||||
"maxLen": 6,
|
||||
"maxLen2": 13,
|
||||
"include": ["HALL_SENSOR"],
|
||||
"include": [
|
||||
"HALL_SENSOR"
|
||||
],
|
||||
"description": "If the unit has a hall effect sensor (Pinecil), this adjusts how sensitive it is at detecting a magnet to put the device into sleep mode."
|
||||
},
|
||||
{
|
||||
@@ -425,7 +500,9 @@
|
||||
"id": "DisplayRotation",
|
||||
"maxLen": 6,
|
||||
"maxLen2": 13,
|
||||
"exclude": ["NO_DISPLAY_ROTATE"],
|
||||
"exclude": [
|
||||
"NO_DISPLAY_ROTATE"
|
||||
],
|
||||
"description": "If the display should rotate automatically or if it should be fixed for left- or right-handed mode."
|
||||
},
|
||||
{
|
||||
@@ -492,7 +569,9 @@
|
||||
"id": "BluetoothLE",
|
||||
"maxLen": 7,
|
||||
"maxLen2": 15,
|
||||
"include": ["BLE_ENABLED"],
|
||||
"include": [
|
||||
"BLE_ENABLED"
|
||||
],
|
||||
"description": "Should BLE be enabled at boot time."
|
||||
},
|
||||
{
|
||||
@@ -544,4 +623,4 @@
|
||||
"description": "Changes the device language on multi-lingual builds."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -3,19 +3,21 @@ site_name: IronOS
|
||||
site_url: https://ralim.github.io/IronOS/
|
||||
site_description: "IronOS Open Source Soldering Iron firmware for Miniware and Pinecil"
|
||||
|
||||
# repo config
|
||||
# Repo config
|
||||
repo_url: https://github.com/ralim/IronOS/
|
||||
|
||||
# Dir & location config
|
||||
docs_dir: ../Documentation
|
||||
edit_uri: edit/dev/Documentation/
|
||||
|
||||
# Theme and config
|
||||
theme:
|
||||
theme:
|
||||
name: readthedocs
|
||||
highlightsjs: true
|
||||
hljs_languages:
|
||||
- yaml
|
||||
|
||||
# Navigation structure
|
||||
nav:
|
||||
- Home: index.md
|
||||
- Getting Started: GettingStarted.md
|
||||
@@ -37,9 +39,10 @@ nav:
|
||||
- Hardware Notes: Hardware.md
|
||||
- Troubleshooting: Troubleshooting.md
|
||||
- Known Hardware Issues: HardwareIssues.md
|
||||
- Power sources: PowerSources.md
|
||||
- Translations: Translation.md
|
||||
- Development: Development.md
|
||||
|
||||
|
||||
# Plugins
|
||||
plugins:
|
||||
- search
|
||||
@@ -47,7 +50,6 @@ plugins:
|
||||
- awesome-pages
|
||||
- git-revision-date
|
||||
|
||||
|
||||
# Markdown Extensions
|
||||
markdown_extensions:
|
||||
- attr_list
|
||||
|
||||
@@ -1,29 +1,35 @@
|
||||
# Default Reference Distro for development env & deploy:
|
||||
# * Alpine Linux, version 3.16 *
|
||||
FROM alpine:3.16
|
||||
LABEL maintainer="Ben V. Brown <ralim@ralimtek.com>"
|
||||
|
||||
WORKDIR /build
|
||||
# Installing the two compilers, python3, python3 pip, clang format
|
||||
# Compilders ->gcc-* newlib-*
|
||||
# Python3 -> py*
|
||||
# Misc -> findutils make git
|
||||
# musl-dev is required for the multi lang firmwares
|
||||
# clang is required for clang-format (for dev)
|
||||
# Default current dir when container starts
|
||||
WORKDIR /build/ironos
|
||||
|
||||
# Installing the two compilers (ARM & RISCV), python3 & pip, clang tools, etc.:
|
||||
## - compilers: gcc-*, newlib-*
|
||||
## - python3: py*, black (required to check Python code formatting)
|
||||
## - misc: findutils, make, git, diffutils, zip
|
||||
## - musl-dev (required for the multi lang firmwares)
|
||||
## - clang (required for clang-format to check C++ code formatting)
|
||||
## - shellcheck (to check sh scripts)
|
||||
|
||||
ARG APK_COMPS="gcc-riscv-none-elf gcc-arm-none-eabi newlib-riscv-none-elf \
|
||||
newlib-arm-none-eabi"
|
||||
ARG APK_PYTHON="python3 py3-pip black"
|
||||
ARG APK_MISC="findutils make git"
|
||||
ARG APK_DEV="musl-dev clang bash clang-extra-tools"
|
||||
ARG APK_MISC="findutils make git diffutils zip"
|
||||
ARG APK_DEV="musl-dev clang bash clang-extra-tools shellcheck"
|
||||
|
||||
# PIP packages
|
||||
ARG PIP_PKGS='bdflib'
|
||||
# PIP packages to check & test Python code
|
||||
ARG PIP_PKGS='bdflib flake8'
|
||||
|
||||
# Install system packages using alpine package manager
|
||||
RUN apk add --no-cache ${APK_COMPS} ${APK_PYTHON} ${APK_MISC} ${APK_DEV}
|
||||
|
||||
# Install Python3 packages
|
||||
|
||||
# Install Python3 packages as modules using pip
|
||||
RUN python3 -m pip install ${PIP_PKGS}
|
||||
# Git trust
|
||||
RUN git config --global --add safe.directory /build/source
|
||||
|
||||
COPY . /build/source
|
||||
COPY ./scripts/ci /build/ci
|
||||
# Git trust to avoid related warning
|
||||
RUN git config --global --add safe.directory /build/ironos
|
||||
|
||||
COPY . /build/ironos
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
set -u
|
||||
|
||||
mkdir -p /build/ci/artefacts
|
||||
|
||||
# Build STM code
|
||||
cd /build/source/source/
|
||||
bash ./build.sh || exit 1
|
||||
echo "All Firmware built"
|
||||
# Copy out all the final resulting files we would like to store for the next op
|
||||
cp -r /build/source/source/Hexfile/*.hex /build/ci/artefacts/
|
||||
cp -r /build/source/source/Hexfile/*.bin /build/ci/artefacts/
|
||||
@@ -1 +0,0 @@
|
||||
8312c4c91799885f222f663fc81f9a31 gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2
|
||||
@@ -1 +0,0 @@
|
||||
add5b6a9b12987d0e72f55a4d2cd0f3b nuclei_riscv_newlibc_prebuilt_linux64_2020.08.tar.bz2
|
||||
@@ -3,24 +3,140 @@
|
||||
# little helper for docker deployment to:
|
||||
# - start development environment for IronOS ("shell" sub-command)
|
||||
# - generate full set of builds ("build" sub-command)
|
||||
# - probably doing some other routines (check source briefly before running undocumented commands!)
|
||||
|
||||
#set -x
|
||||
#set -e
|
||||
|
||||
### helper functions
|
||||
|
||||
# brief help (some supported commands may be missing!)
|
||||
usage()
|
||||
{
|
||||
echo -e "\nUsage: ${0} [CMD]\n"
|
||||
echo "CMD:"
|
||||
echo "CMD (docker related):"
|
||||
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 "CMD (helper routines):"
|
||||
echo -e "\tdocs_readme - generate & OVERWRITE(!) README.md inside Documentation/ based on nav section from mkdocs.yml if it changed\n"
|
||||
echo -e "\tcheck_style_file SRC - run code style checks based on clang-format & custom parsers for source code file SRC\n"
|
||||
echo -e "\tcheck_style_log - run clang-format using source/Makefile and generate gcc-compatible error log in source/check-style.log\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"
|
||||
}
|
||||
|
||||
# Documentation/README.md automagical generation routine
|
||||
docs_readme()
|
||||
{
|
||||
# WARNING: ON RUN Documentaion/README.md MAY BE OVERWRITTEN WITHOUT ANY WARNINGS / CONFIRMATIONS !!!
|
||||
# Returns:
|
||||
## 0 to the environment & silence - if there are no any changes in README.md nor updates in mkdocs.yml
|
||||
## 1 to the environment (as error) & note message - if the update of README.md in repo is required
|
||||
yml="scripts/IronOS-mkdocs.yml"
|
||||
md_old="Documentation/README.md"
|
||||
md_new="Documentation/README"
|
||||
# ^^^^ hardcoded paths relative to IronOS/ to make this func very trivial
|
||||
# file overwritten section looks out of style but hoping to make shellcheck happy
|
||||
cat << EOF > "${md_new}"
|
||||
|
||||
<!-- THIS FILE IS AUTOGENERATED by "scripts/deploy.sh docs_readme" based on nav section in ${yml} config -->
|
||||
<!-- THIS FILE IS NOT SUPPOSED TO BE EDITED MANUALLY -->
|
||||
|
||||
#### This is autogenerated README for brief navigation through github over official documentation for IronOS project
|
||||
#### This documentation is also available [here online](https://ralim.github.io/IronOS)
|
||||
|
||||
EOF
|
||||
# it probably will become unexplainable in a few months but so far it works:
|
||||
sed '1,/^nav/d; /^ *$/,$d; s,- ,- [,; s,: ,](../Documentation/,; s,.md,.md),; s,:$,],; s,/Pinecil ,/Pinecil%20,; /^ - \[.*\]$/ s,\[,,; s,]$,,' "${yml}" >> "${md_new}"
|
||||
ret=0
|
||||
if [ -z "$(diff -q "${md_old}" "${md_new}")" ]; then
|
||||
rm "${md_new}"
|
||||
ret=0
|
||||
else
|
||||
mv "${md_new}" "${md_old}"
|
||||
echo ""
|
||||
echo "${yml} seems to be updated..."
|
||||
echo "... while ${md_old} is out-of-date!"
|
||||
echo ""
|
||||
echo "Please, update ${md_old} in your local working copy by command:"
|
||||
echo ""
|
||||
echo " $ ./scripts/deploy.sh docs_readme"
|
||||
echo ""
|
||||
echo "And then commit & push changes to update ${md_old} in the repo:"
|
||||
echo ""
|
||||
echo " $ git commit ${md_old} -m \"${md_old}: update autogenerated file\" && git push"
|
||||
echo ""
|
||||
ret=1
|
||||
fi;
|
||||
return "${ret}"
|
||||
}
|
||||
|
||||
# Helper function to check code style using clang-format & grep/sed custom parsers:
|
||||
# - basic logic moved from source/Makefile : `check-style` target for better maintainance since a lot of sh script involved;
|
||||
# - output goes in gcc-like error compatible format for IDEs/editors.
|
||||
check_style_file()
|
||||
{
|
||||
ret=0
|
||||
src="${1}"
|
||||
test ! -f "${src}" && echo "ERROR!!! Provided file ${src} is not available to check/read!!!" && exit 1
|
||||
# count lines using diff between beauty-fied file & original file to detect format issue
|
||||
var="$(clang-format "$src" | diff "$src" - | wc -l)"
|
||||
if [ "${var}" -ne 0 ]; then
|
||||
# show full log error or, if LIST=anything provided, then show only filename of interest (implemented for debug purposes mainly)
|
||||
if [ -z "${LIST}" ]; then
|
||||
# sed is here only for pretty logging
|
||||
clang-format "${src}" | diff "${src}" - | sed 's/^---/-------------------------------------------------------------------------------/; s/^< /--- /; s/^> /+++ /; /^[0-9].*/ s/[acd,].*$/ERROR1/; /^[0-9].*/ s,^,\n\n\n\n'"${src}"':,; /ERROR1$/ s,ERROR1$,:1: error: clang-format code style mismatch:,; '
|
||||
else
|
||||
echo "${src}"
|
||||
fi;
|
||||
ret=1
|
||||
fi;
|
||||
# - clang-format has neat option for { } in condition blocks but it's available only since version 15:
|
||||
# * https://clang.llvm.org/docs/ClangFormatStyleOptions.html#insertbraces
|
||||
# - since reference env is alpine 3.16 with clang-format 13, implement custom parser to do the similar thing here with grep:
|
||||
# it used to trace missing { and } for if/else/do/while/for BUT IT'S VERY SPECULATIVE, very-very hacky & dirty.
|
||||
# - if file is problematic but filename only requested make final grep in pipe silent ... UPD: make code messy but shellcheck happy
|
||||
if [ -z "${LIST}" ]; then
|
||||
grep -H -n -e "^ .*if .*)$" -e "^ .*else$" -e "^ .* do$" -e "^ .*while .*)$" -e "^ .*for .*)$" "${src}" | grep -v -e "^.*//" -e "^.*:.*: .*if ((.*[^)])$" | sed 's,^,\n\n,; s,: ,:1: error: probably missing { or } for conditional or loop block:\n>>>,;' | grep -e "^.*$"
|
||||
else
|
||||
grep -H -n -e "^ .*if .*)$" -e "^ .*else$" -e "^ .* do$" -e "^ .*while .*)$" -e "^ .*for .*)$" "${src}" | grep -v -e "^.*//" -e "^.*:.*: .*if ((.*[^)])$" | sed 's,^,\n\n,; s,: ,:1: error: probably missing { or } for conditional or loop block:\n>>>,;' | grep -q -e "^.*$"
|
||||
fi;
|
||||
if [ "${?}" -ne 1 ]; then
|
||||
# ... and only print the filename
|
||||
test -z "${LIST}" || echo "${src}"
|
||||
ret=1;
|
||||
fi;
|
||||
return "${ret}"
|
||||
}
|
||||
|
||||
# check_style routine for those who too lazy to do it everytime manually
|
||||
check_style_log()
|
||||
{
|
||||
log="source/check-style.log"
|
||||
make -C source check-style 2>&1 | tee "${log}"
|
||||
chmod 0666 "${log}"
|
||||
sed -i -e 's,\r,,g' "${log}"
|
||||
return 0
|
||||
}
|
||||
|
||||
### main
|
||||
|
||||
docker_conf="Env.yml"
|
||||
|
||||
# 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}"
|
||||
|
||||
# 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)
|
||||
|
||||
@@ -42,6 +158,29 @@ if [ -n "${docker_tool}" ] && [ -z "${docker_bin}" ]; then
|
||||
docker_bin="${docker_tool} compose"
|
||||
fi;
|
||||
|
||||
# give function argument a name
|
||||
|
||||
cmd="${1}"
|
||||
|
||||
# if only README.md for Documentation update is required then run it & exit
|
||||
|
||||
if [ "docs_readme" = "${cmd}" ]; then
|
||||
docs_readme
|
||||
exit "${?}"
|
||||
fi;
|
||||
|
||||
if [ "check_style_file" = "${cmd}" ]; then
|
||||
check_style_file "${2}"
|
||||
exit "${?}"
|
||||
fi;
|
||||
|
||||
if [ "check_style_log" = "${cmd}" ]; then
|
||||
check_style_log
|
||||
exit "${?}"
|
||||
fi;
|
||||
|
||||
# if docker is not presented in any way show warning & exit
|
||||
|
||||
if [ -z "${docker_bin}" ]; then
|
||||
echo "ERROR: Can't find docker-compose nor docker tool. Please, install docker and try again."
|
||||
exit 1
|
||||
@@ -49,11 +188,10 @@ 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"
|
||||
docker_cmd="run --rm builder make build-all OUT=${OUT}"
|
||||
elif [ "${cmd}" = "clean" ]; then
|
||||
docker rmi ironos-builder:latest
|
||||
exit "${?}"
|
||||
@@ -62,20 +200,6 @@ else
|
||||
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
|
||||
@@ -87,4 +211,3 @@ echo -e "\t* type \"${0} clean\" to delete created container (but not cached dat
|
||||
echo -e "\n====>>>> ${docker_bin} ${docker_file} ${docker_cmd}\n"
|
||||
eval "${docker_bin} ${docker_file} ${docker_cmd}"
|
||||
exit "${?}"
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AllowShortEnumsOnASingleLine: false ### <<< Keeps enums as is
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
|
||||
@@ -101,6 +101,11 @@ void setBuzzer(bool on);
|
||||
// For example, on the MHP30 this is used to figure out the resistance of the hotplate
|
||||
uint8_t preStartChecks();
|
||||
uint8_t preStartChecksDone();
|
||||
|
||||
// Check if the tip or output mosfet is shorted (if possible)
|
||||
bool isTipShorted();
|
||||
// Show the boot logo
|
||||
void showBootLogo(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// BSP mapping functions
|
||||
|
||||
#include "BSP.h"
|
||||
#include "BootLogo.h"
|
||||
#include "I2C_Wrapper.hpp"
|
||||
#include "Pins.h"
|
||||
#include "Setup.h"
|
||||
@@ -472,4 +473,6 @@ uint64_t getDeviceID() {
|
||||
uint8_t preStartChecksDone() { return 1; }
|
||||
|
||||
uint8_t getTipThermalMass() { return TIP_THERMAL_MASS; }
|
||||
uint8_t getTipInertia() { return TIP_THERMAL_MASS; }
|
||||
uint8_t getTipInertia() { return TIP_THERMAL_MASS; }
|
||||
|
||||
void showBootLogo(void) { BootLogo::handleShowingLogo((uint8_t *)FLASH_LOGOADDR); }
|
||||
|
||||
@@ -18,4 +18,5 @@ void power_check() {
|
||||
|
||||
bool getIsPoweredByDCIN() { return false; }
|
||||
|
||||
uint8_t getTipResistanceX10() { return TIP_RESISTANCE; }
|
||||
uint8_t getTipResistanceX10() { return TIP_RESISTANCE; }
|
||||
bool isTipShorted() { return false; }
|
||||
@@ -47,9 +47,9 @@ void Setup_HAL() {
|
||||
MX_IWDG_Init();
|
||||
HAL_ADC_Start(&hadc2);
|
||||
HAL_ADCEx_MultiModeStart_DMA(&hadc1, ADCReadings,
|
||||
(ADC_SAMPLES * ADC_CHANNELS)); // start DMA of normal readings
|
||||
// HAL_ADCEx_InjectedStart(&hadc1); // enable injected readings
|
||||
// HAL_ADCEx_InjectedStart(&hadc2); // enable injected readings
|
||||
(ADC_SAMPLES * ADC_CHANNELS)); // start DMA of normal readings
|
||||
// HAL_ADCEx_InjectedStart(&hadc1); // enable injected readings
|
||||
// HAL_ADCEx_InjectedStart(&hadc2); // enable injected readings
|
||||
}
|
||||
|
||||
// channel 0 -> temperature sensor, 1-> VIN, 2-> tip
|
||||
@@ -154,8 +154,9 @@ static void MX_ADC1_Init(void) {
|
||||
|
||||
SET_BIT(hadc1.Instance->CR1, (ADC_CR1_EOSIE)); // Enable end of Normal
|
||||
// Run ADC internal calibration
|
||||
while (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK)
|
||||
while (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/* ADC2 init function */
|
||||
@@ -191,8 +192,9 @@ static void MX_ADC2_Init(void) {
|
||||
HAL_ADC_ConfigChannel(&hadc2, &sConfig);
|
||||
|
||||
// Run ADC internal calibration
|
||||
while (HAL_ADCEx_Calibration_Start(&hadc2) != HAL_OK)
|
||||
while (HAL_ADCEx_Calibration_Start(&hadc2) != HAL_OK) {
|
||||
;
|
||||
}
|
||||
}
|
||||
/* I2C1 init function */
|
||||
static void MX_I2C1_Init(void) {
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
* How many seconds/minutes we wait until going to sleep/shutdown.
|
||||
* Values -> SLEEP_TIME * 10; i.e. 5*10 = 50 Seconds!
|
||||
*/
|
||||
#define SLEEP_TIME 5 // x10 Seconds
|
||||
#define SHUTDOWN_TIME 10 // Minutes
|
||||
#define SLEEP_TIME 5 // x10 Seconds
|
||||
#define SHUTDOWN_TIME 0 // Minutes -- Default shutdown to being off
|
||||
|
||||
/**
|
||||
* Auto start off for safety.
|
||||
@@ -164,13 +164,13 @@
|
||||
#define HARDWARE_MAX_WATTAGE_X10 650
|
||||
#define TIP_THERMAL_MASS 65 // TODO, needs refinement
|
||||
#define TIP_RESISTANCE 60 // x10 ohms, ~6 typical
|
||||
#endif /* MHP30 */
|
||||
#endif /* MHP30 */
|
||||
|
||||
#ifdef ACCEL_EXITS_ON_MOVEMENT
|
||||
#define NO_SLEEP_MODE
|
||||
#endif
|
||||
|
||||
#define FLASH_LOGOADDR (0x08000000 + (62 * 1024))
|
||||
#define FLASH_LOGOADDR (0x08000000 + (126 * 1024))
|
||||
#define SETTINGS_START_PAGE (0x08000000 + (127 * 1024))
|
||||
|
||||
#endif /* CONFIGURATION_H_ */
|
||||
|
||||
@@ -30,9 +30,9 @@ void flash_save_buffer(const uint8_t *buffer, const uint16_t length) {
|
||||
HAL_FLASH_Unlock();
|
||||
for (uint16_t i = 0; i < (length / 2); i++) {
|
||||
resetWatchdog();
|
||||
HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, SETTINGS_START_PAGE+ (i*sizeof(uint16_t)), data[i]);
|
||||
HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, SETTINGS_START_PAGE + (i * sizeof(uint16_t)), data[i]);
|
||||
}
|
||||
HAL_FLASH_Lock();
|
||||
}
|
||||
|
||||
void flash_read_buffer(uint8_t *buffer, const uint16_t length) { memcpy(buffer, (uint8_t*)SETTINGS_START_PAGE, length); }
|
||||
void flash_read_buffer(uint8_t *buffer, const uint16_t length) { memcpy(buffer, (uint8_t *)SETTINGS_START_PAGE, length); }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// BSP mapping functions
|
||||
|
||||
#include "BSP.h"
|
||||
#include "BootLogo.h"
|
||||
#include "I2C_Wrapper.hpp"
|
||||
#include "Pins.h"
|
||||
#include "Setup.h"
|
||||
@@ -284,6 +285,7 @@ void performTipResistanceSampleReading() {
|
||||
|
||||
tipResistanceReadingSlot++;
|
||||
}
|
||||
bool tipShorted = false;
|
||||
void FinishMeasureTipResistance() {
|
||||
|
||||
// Otherwise we now have the 4 samples;
|
||||
@@ -303,6 +305,8 @@ void FinishMeasureTipResistance() {
|
||||
// return; // Change nothing as probably disconnected tip
|
||||
tipResistanceReadingSlot = lastTipResistance = 0;
|
||||
return;
|
||||
} else if (reading < 200) {
|
||||
tipShorted = true;
|
||||
} else if (reading < 800) {
|
||||
newRes = 62;
|
||||
} else {
|
||||
@@ -372,7 +376,7 @@ uint64_t getDeviceID() {
|
||||
|
||||
uint8_t preStartChecksDone() {
|
||||
#ifdef TIP_RESISTANCE_SENSE_Pin
|
||||
return (lastTipResistance == 0 || tipResistanceReadingSlot < numTipResistanceReadings || tipMeasurementOccuring) ? 0 : 1;
|
||||
return (lastTipResistance == 0 || tipResistanceReadingSlot < numTipResistanceReadings || tipMeasurementOccuring || tipShorted) ? 0 : 1;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
@@ -387,7 +391,11 @@ uint8_t getTipResistanceX10() {
|
||||
return TIP_RESISTANCE;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef TIP_RESISTANCE_SENSE_Pin
|
||||
bool isTipShorted() { return tipShorted; }
|
||||
#else
|
||||
bool isTipShorted() { return false; }
|
||||
#endif
|
||||
uint8_t getTipThermalMass() {
|
||||
#ifdef TIP_RESISTANCE_SENSE_Pin
|
||||
if (lastTipResistance >= 80) {
|
||||
@@ -407,4 +415,6 @@ uint8_t getTipInertia() {
|
||||
#else
|
||||
return TIP_THERMAL_MASS;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void showBootLogo(void) { BootLogo::handleShowingLogo((uint8_t *)FLASH_LOGOADDR); }
|
||||
|
||||
@@ -229,8 +229,9 @@ static void MX_ADC1_Init(void) {
|
||||
HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
|
||||
SET_BIT(hadc1.Instance->CR1, (ADC_CR1_JEOCIE)); // Enable end of injected conv irq
|
||||
// Run ADC internal calibration
|
||||
while (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK)
|
||||
while (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/* ADC2 init function */
|
||||
@@ -272,8 +273,9 @@ static void MX_ADC2_Init(void) {
|
||||
HAL_ADCEx_InjectedConfigChannel(&hadc2, &sConfigInjected);
|
||||
|
||||
// Run ADC internal calibration
|
||||
while (HAL_ADCEx_Calibration_Start(&hadc2) != HAL_OK)
|
||||
while (HAL_ADCEx_Calibration_Start(&hadc2) != HAL_OK) {
|
||||
;
|
||||
}
|
||||
}
|
||||
/* I2C1 init function */
|
||||
static void MX_I2C1_Init(void) {
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include "stm32f1xx_hal.h"
|
||||
#include "string.h"
|
||||
|
||||
|
||||
void flash_save_buffer(const uint8_t *buffer, const uint16_t length) {
|
||||
FLASH_EraseInitTypeDef pEraseInit;
|
||||
pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
|
||||
|
||||
@@ -208,9 +208,7 @@ static void prvTaskExitError(void) {
|
||||
// therefore not output an 'unreachable code' warning for code that appears
|
||||
// after it. */
|
||||
// }
|
||||
for(;;){
|
||||
|
||||
}
|
||||
for (;;) {}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "configuration.h"
|
||||
#include <I2C_Wrapper.hpp>
|
||||
|
||||
|
||||
void preRToSInit() {
|
||||
/* Reset of all peripherals, Initializes the Flash interface and the Systick.
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// BSP mapping functions
|
||||
|
||||
#include "BSP.h"
|
||||
#include "BootLogo.h"
|
||||
#include "I2C_Wrapper.hpp"
|
||||
#include "IRQ.h"
|
||||
#include "Pins.h"
|
||||
@@ -93,8 +94,10 @@ uint8_t preStartChecks() { return 1; }
|
||||
uint64_t getDeviceID() { return dbg_id_get(); }
|
||||
|
||||
uint8_t getTipResistanceX10() { return TIP_RESISTANCE; }
|
||||
|
||||
bool isTipShorted() { return false; }
|
||||
uint8_t preStartChecksDone() { return 1; }
|
||||
|
||||
uint8_t getTipThermalMass() { return TIP_THERMAL_MASS; }
|
||||
uint8_t getTipInertia() { return TIP_THERMAL_MASS; }
|
||||
uint8_t getTipInertia() { return TIP_THERMAL_MASS; }
|
||||
|
||||
void showBootLogo(void) { BootLogo::handleShowingLogo((uint8_t *)FLASH_LOGOADDR); }
|
||||
|
||||
@@ -23,13 +23,13 @@ void log_system_state(int32_t PWMWattsx10) {
|
||||
// Tip_Temp_C,Handle_Temp_C,Output_Power_Wattx10,PWM,Tip_Raw\r\n
|
||||
// 3+1+3+1+3+1+3+1+5+2 = 23, so sizing at 32 for now
|
||||
|
||||
outputLength = snprintf(uartOutputBuffer, uartOutputBufferLength, "%lu,%u,%li,%u,%lu\r\n", //
|
||||
TipThermoModel::getTipInC(false), // Tip temp in C
|
||||
getHandleTemperature(0), // Handle temp in C X10
|
||||
PWMWattsx10, // Output Wattage
|
||||
pendingPWM, // PWM
|
||||
TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0), true) // Tip temp in uV
|
||||
);
|
||||
outputLength = snprintf(uartOutputBuffer, uartOutputBufferLength, "%lu,%u,%li,%u,%lu\r\n",
|
||||
TipThermoModel::getTipInC(false), // Tip temp in C
|
||||
getHandleTemperature(0), // Handle temp in C X10
|
||||
PWMWattsx10, // Output Wattage
|
||||
pendingPWM, // PWM
|
||||
TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0), true) // Tip temp in uV
|
||||
);
|
||||
|
||||
// Now print this out the uart via IRQ (DMA cant be used as oled has it)
|
||||
currentOutputPos = 0;
|
||||
|
||||
@@ -40,18 +40,19 @@ enum class i2c_step {
|
||||
Wait_stop, // Wait for stop to send and we are done
|
||||
Done, // Finished
|
||||
Error_occured, // Error occured on the bus
|
||||
|
||||
};
|
||||
|
||||
struct i2c_state {
|
||||
i2c_step currentStep;
|
||||
bool isMemoryWrite;
|
||||
bool wakePart;
|
||||
uint8_t deviceAddress;
|
||||
uint8_t memoryAddress;
|
||||
uint8_t * buffer;
|
||||
uint8_t *buffer;
|
||||
uint16_t numberOfBytes;
|
||||
dma_parameter_struct dma_init_struct;
|
||||
};
|
||||
|
||||
i2c_state currentState;
|
||||
|
||||
void perform_i2c_step() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// BSP mapping functions
|
||||
|
||||
#include "BSP.h"
|
||||
#include "BootLogo.h"
|
||||
#include "I2C_Wrapper.hpp"
|
||||
#include "IRQ.h"
|
||||
#include "Pins.h"
|
||||
@@ -10,6 +11,7 @@
|
||||
#include "Utils.h"
|
||||
#include "configuration.h"
|
||||
#include "crc32.h"
|
||||
#include "hal_flash.h"
|
||||
#include "history.hpp"
|
||||
#include "main.hpp"
|
||||
|
||||
@@ -187,7 +189,7 @@ void performTipResistanceSampleReading() {
|
||||
gpio_write(TIP_RESISTANCE_SENSE, tipResistanceReadingSlot == 0);
|
||||
tipResistanceReadingSlot++;
|
||||
}
|
||||
|
||||
bool tipShorted = false;
|
||||
void FinishMeasureTipResistance() {
|
||||
|
||||
// Otherwise we now have the 4 samples;
|
||||
@@ -206,6 +208,8 @@ void FinishMeasureTipResistance() {
|
||||
uint8_t newRes = 0;
|
||||
if (reading > 8000) {
|
||||
// return; // Change nothing as probably disconnected tip
|
||||
} else if (reading < 500) {
|
||||
tipShorted = true;
|
||||
} else if (reading < 4000) {
|
||||
newRes = 62;
|
||||
} else {
|
||||
@@ -215,8 +219,8 @@ void FinishMeasureTipResistance() {
|
||||
}
|
||||
volatile bool tipMeasurementOccuring = true;
|
||||
volatile TickType_t nextTipMeasurement = 100;
|
||||
|
||||
void performTipMeasurementStep() {
|
||||
bool isTipShorted() { return tipShorted; }
|
||||
void performTipMeasurementStep() {
|
||||
|
||||
// Wait 100ms for settle time
|
||||
if (xTaskGetTickCount() < (nextTipMeasurement)) {
|
||||
@@ -238,7 +242,8 @@ uint8_t preStartChecks() {
|
||||
performTipMeasurementStep();
|
||||
return preStartChecksDone();
|
||||
}
|
||||
uint8_t preStartChecksDone() { return (lastTipResistance == 0 || tipResistanceReadingSlot < numTipResistanceReadings || tipMeasurementOccuring) ? 0 : 1; }
|
||||
// If we are still measuring the tip; or tip is shorted; prevent heating
|
||||
uint8_t preStartChecksDone() { return (lastTipResistance == 0 || tipResistanceReadingSlot < numTipResistanceReadings || tipMeasurementOccuring || tipShorted) ? 0 : 1; }
|
||||
|
||||
// Return hardware unique ID if possible
|
||||
uint64_t getDeviceID() {
|
||||
@@ -278,4 +283,11 @@ uint8_t getDeviceValidationStatus() {
|
||||
uint32_t programmedHash = EF_Ctrl_Get_Key_Slot_w1();
|
||||
uint32_t computedHash = gethash();
|
||||
return programmedHash == computedHash ? 0 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
void showBootLogo(void) {
|
||||
uint8_t scratch[1024];
|
||||
flash_read(FLASH_LOGOADDR - 0x23000000, scratch, 1024);
|
||||
|
||||
BootLogo::handleShowingLogo(scratch);
|
||||
}
|
||||
|
||||
@@ -40,8 +40,9 @@ bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t read_address, uint8_t *p_b
|
||||
i2cCfg.data = p_buffer;
|
||||
i2cCfg.subAddrSize = 1; // one byte address
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
err = I2C_MasterReceiveBlocking(I2C0_ID, &i2cCfg);
|
||||
taskENTER_CRITICAL();
|
||||
/* --------------- */
|
||||
err = I2C_MasterReceiveBlocking(I2C0_ID, &i2cCfg);
|
||||
taskEXIT_CRITICAL();
|
||||
bool res = err == SUCCESS;
|
||||
if (!res) {
|
||||
@@ -63,8 +64,10 @@ bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *p_bu
|
||||
i2cCfg.dataSize = number_of_byte;
|
||||
i2cCfg.data = p_buffer;
|
||||
i2cCfg.subAddrSize = 1; // one byte address
|
||||
taskENTER_CRITICAL();
|
||||
err = I2C_MasterSendBlocking(I2C0_ID, &i2cCfg);
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
/* --------------- */
|
||||
err = I2C_MasterSendBlocking(I2C0_ID, &i2cCfg);
|
||||
taskEXIT_CRITICAL();
|
||||
bool res = err == SUCCESS;
|
||||
if (!res) {
|
||||
|
||||
@@ -80,21 +80,20 @@
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 0 )
|
||||
#error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0
|
||||
#error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0
|
||||
#endif
|
||||
|
||||
/* Block sizes must not get too small. */
|
||||
#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
|
||||
#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
|
||||
|
||||
/* Assumes 8bit bytes! */
|
||||
#define heapBITS_PER_BYTE ( ( size_t ) 8 )
|
||||
#define heapBITS_PER_BYTE ( ( size_t ) 8 )
|
||||
|
||||
/* Define the linked list structure. This is used to link free blocks in order
|
||||
* of their memory address. */
|
||||
typedef struct A_BLOCK_LINK
|
||||
{
|
||||
struct A_BLOCK_LINK * pxNextFreeBlock; /*<< The next free block in the list. */
|
||||
size_t xBlockSize; /*<< The size of the free block. */
|
||||
typedef struct A_BLOCK_LINK {
|
||||
struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */
|
||||
size_t xBlockSize; /*<< The size of the free block. */
|
||||
} BlockLink_t;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
@@ -105,7 +104,7 @@ typedef struct A_BLOCK_LINK
|
||||
* the block in front it and/or the block behind it if the memory blocks are
|
||||
* adjacent to each other.
|
||||
*/
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert );
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
@@ -114,14 +113,14 @@ static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert );
|
||||
static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( portBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK );
|
||||
|
||||
/* Create a couple of list links to mark the start and end of the list. */
|
||||
static BlockLink_t xStart, * pxEnd = NULL;
|
||||
static BlockLink_t xStart, *pxEnd = NULL;
|
||||
|
||||
/* Keeps track of the number of calls to allocate and free memory as well as the
|
||||
* number of free bytes remaining, but says nothing about fragmentation. */
|
||||
static size_t xFreeBytesRemaining = 0U;
|
||||
static size_t xFreeBytesRemaining = 0U;
|
||||
static size_t xMinimumEverFreeBytesRemaining = 0U;
|
||||
static size_t xNumberOfSuccessfulAllocations = 0;
|
||||
static size_t xNumberOfSuccessfulFrees = 0;
|
||||
static size_t xNumberOfSuccessfulFrees = 0;
|
||||
|
||||
/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize
|
||||
* member of an BlockLink_t structure is set then the block belongs to the
|
||||
@@ -131,420 +130,354 @@ static size_t xBlockAllocatedBit = 0;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void * pvPortMalloc( size_t xWantedSize )
|
||||
{
|
||||
BlockLink_t * pxBlock, * pxPreviousBlock, * pxNewBlockLink;
|
||||
void * pvReturn = NULL;
|
||||
void *pvPortMalloc( size_t xWantedSize ) {
|
||||
BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
|
||||
void *pvReturn = NULL;
|
||||
|
||||
/* The heap must be initialised before the first call to
|
||||
* prvPortMalloc(). */
|
||||
configASSERT( pxEnd );
|
||||
/* The heap must be initialised before the first call to
|
||||
* prvPortMalloc(). */
|
||||
configASSERT( pxEnd );
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* Check the requested block size is not so large that the top bit is
|
||||
* set. The top bit of the block size member of the BlockLink_t structure
|
||||
* is used to determine who owns the block - the application or the
|
||||
* kernel, so it must be free. */
|
||||
if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
|
||||
{
|
||||
/* The wanted size is increased so it can contain a BlockLink_t
|
||||
* structure in addition to the requested amount of bytes. */
|
||||
if( xWantedSize > 0 )
|
||||
{
|
||||
xWantedSize += xHeapStructSize;
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* Check the requested block size is not so large that the top bit is
|
||||
* set. The top bit of the block size member of the BlockLink_t structure
|
||||
* is used to determine who owns the block - the application or the
|
||||
* kernel, so it must be free. */
|
||||
if ( ( xWantedSize & xBlockAllocatedBit ) == 0 ) {
|
||||
/* The wanted size is increased so it can contain a BlockLink_t
|
||||
* structure in addition to the requested amount of bytes. */
|
||||
if ( xWantedSize > 0 ) {
|
||||
xWantedSize += xHeapStructSize;
|
||||
|
||||
/* Ensure that blocks are always aligned to the required number
|
||||
* of bytes. */
|
||||
if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )
|
||||
{
|
||||
/* Byte alignment required. */
|
||||
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
|
||||
{
|
||||
/* Traverse the list from the start (lowest address) block until
|
||||
* one of adequate size is found. */
|
||||
pxPreviousBlock = &xStart;
|
||||
pxBlock = xStart.pxNextFreeBlock;
|
||||
|
||||
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
|
||||
{
|
||||
pxPreviousBlock = pxBlock;
|
||||
pxBlock = pxBlock->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the end marker was reached then a block of adequate size
|
||||
* was not found. */
|
||||
if( pxBlock != pxEnd )
|
||||
{
|
||||
/* Return the memory space pointed to - jumping over the
|
||||
* BlockLink_t structure at its start. */
|
||||
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
|
||||
|
||||
/* This block is being returned for use so must be taken out
|
||||
* of the list of free blocks. */
|
||||
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||
|
||||
/* If the block is larger than required it can be split into
|
||||
* two. */
|
||||
if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
|
||||
{
|
||||
/* This block is to be split into two. Create a new
|
||||
* block following the number of bytes requested. The void
|
||||
* cast is used to prevent byte alignment warnings from the
|
||||
* compiler. */
|
||||
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
|
||||
|
||||
/* Calculate the sizes of two blocks split from the
|
||||
* single block. */
|
||||
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
||||
pxBlock->xBlockSize = xWantedSize;
|
||||
|
||||
/* Insert the new block into the list of free blocks. */
|
||||
prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||
|
||||
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
|
||||
{
|
||||
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* The block is being returned - it is allocated and owned
|
||||
* by the application and has no "next" block. */
|
||||
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
||||
pxBlock->pxNextFreeBlock = NULL;
|
||||
xNumberOfSuccessfulAllocations++;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
/* Ensure that blocks are always aligned to the required number
|
||||
* of bytes. */
|
||||
if ( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 ) {
|
||||
/* Byte alignment required. */
|
||||
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
traceMALLOC( pvReturn, xWantedSize );
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
|
||||
#if ( configUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
{
|
||||
if( pvReturn == NULL )
|
||||
{
|
||||
extern void vApplicationMallocFailedHook( void );
|
||||
vApplicationMallocFailedHook();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif /* if ( configUSE_MALLOC_FAILED_HOOK == 1 ) */
|
||||
|
||||
return pvReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFree( void * pv )
|
||||
{
|
||||
uint8_t * puc = ( uint8_t * ) pv;
|
||||
BlockLink_t * pxLink;
|
||||
|
||||
if( pv != NULL )
|
||||
{
|
||||
/* The memory being freed will have an BlockLink_t structure immediately
|
||||
* before it. */
|
||||
puc -= xHeapStructSize;
|
||||
|
||||
/* This casting is to keep the compiler from issuing warnings. */
|
||||
pxLink = ( void * ) puc;
|
||||
|
||||
/* Check the block is actually allocated. */
|
||||
configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
|
||||
configASSERT( pxLink->pxNextFreeBlock == NULL );
|
||||
|
||||
if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
|
||||
{
|
||||
if( pxLink->pxNextFreeBlock == NULL )
|
||||
{
|
||||
/* The block is being returned to the heap - it is no longer
|
||||
* allocated. */
|
||||
pxLink->xBlockSize &= ~xBlockAllocatedBit;
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* Add this block to the list of free blocks. */
|
||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||
traceFREE( pv, pxLink->xBlockSize );
|
||||
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||
xNumberOfSuccessfulFrees++;
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetFreeHeapSize( void )
|
||||
{
|
||||
return xFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetMinimumEverFreeHeapSize( void )
|
||||
{
|
||||
return xMinimumEverFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert )
|
||||
{
|
||||
BlockLink_t * pxIterator;
|
||||
uint8_t * puc;
|
||||
|
||||
/* Iterate through the list until a block is found that has a higher address
|
||||
* than the block being inserted. */
|
||||
for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
/* Nothing to do here, just iterate to the right position. */
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted after
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxIterator;
|
||||
|
||||
if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
|
||||
{
|
||||
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
|
||||
pxBlockToInsert = pxIterator;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted before
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxBlockToInsert;
|
||||
if ( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) {
|
||||
/* Traverse the list from the start (lowest address) block until
|
||||
* one of adequate size is found. */
|
||||
pxPreviousBlock = &xStart;
|
||||
pxBlock = xStart.pxNextFreeBlock;
|
||||
|
||||
if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
if( pxIterator->pxNextFreeBlock != pxEnd )
|
||||
{
|
||||
/* Form one big block from the two blocks. */
|
||||
pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
|
||||
while ( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ) {
|
||||
pxPreviousBlock = pxBlock;
|
||||
pxBlock = pxBlock->pxNextFreeBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxEnd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the block being inserted plugged a gab, so was merged with the block
|
||||
* before and the block after, then it's pxNextFreeBlock pointer will have
|
||||
* already been set, and should not be set here as that would make it point
|
||||
* to itself. */
|
||||
if( pxIterator != pxBlockToInsert )
|
||||
{
|
||||
pxIterator->pxNextFreeBlock = pxBlockToInsert;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the end marker was reached then a block of adequate size
|
||||
* was not found. */
|
||||
if ( pxBlock != pxEnd ) {
|
||||
/* Return the memory space pointed to - jumping over the
|
||||
* BlockLink_t structure at its start. */
|
||||
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
|
||||
|
||||
/* This block is being returned for use so must be taken out
|
||||
* of the list of free blocks. */
|
||||
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||
|
||||
/* If the block is larger than required it can be split into
|
||||
* two. */
|
||||
if ( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) {
|
||||
/* This block is to be split into two. Create a new
|
||||
* block following the number of bytes requested. The void
|
||||
* cast is used to prevent byte alignment warnings from the
|
||||
* compiler. */
|
||||
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
|
||||
|
||||
/* Calculate the sizes of two blocks split from the
|
||||
* single block. */
|
||||
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
||||
pxBlock->xBlockSize = xWantedSize;
|
||||
|
||||
/* Insert the new block into the list of free blocks. */
|
||||
prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||
|
||||
if ( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) {
|
||||
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* The block is being returned - it is allocated and owned
|
||||
* by the application and has no "next" block. */
|
||||
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
||||
pxBlock->pxNextFreeBlock = NULL;
|
||||
xNumberOfSuccessfulAllocations++;
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
traceMALLOC( pvReturn, xWantedSize );
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
|
||||
#if ( configUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
{
|
||||
if ( pvReturn == NULL ) {
|
||||
extern void vApplicationMallocFailedHook( void );
|
||||
vApplicationMallocFailedHook();
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif /* if ( configUSE_MALLOC_FAILED_HOOK == 1 ) */
|
||||
|
||||
return pvReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions )
|
||||
{
|
||||
BlockLink_t * pxFirstFreeBlockInRegion = NULL, * pxPreviousFreeBlock;
|
||||
size_t xAlignedHeap;
|
||||
size_t xTotalRegionSize, xTotalHeapSize = 0;
|
||||
BaseType_t xDefinedRegions = 0;
|
||||
size_t xAddress;
|
||||
const HeapRegion_t * pxHeapRegion;
|
||||
void vPortFree( void *pv ) {
|
||||
uint8_t *puc = ( uint8_t * ) pv;
|
||||
BlockLink_t *pxLink;
|
||||
|
||||
/* Can only call once! */
|
||||
configASSERT( pxEnd == NULL );
|
||||
if ( pv != NULL ) {
|
||||
/* The memory being freed will have an BlockLink_t structure immediately
|
||||
* before it. */
|
||||
puc -= xHeapStructSize;
|
||||
|
||||
/* This casting is to keep the compiler from issuing warnings. */
|
||||
pxLink = ( void * ) puc;
|
||||
|
||||
/* Check the block is actually allocated. */
|
||||
configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
|
||||
configASSERT( pxLink->pxNextFreeBlock == NULL );
|
||||
|
||||
if ( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) {
|
||||
if ( pxLink->pxNextFreeBlock == NULL ) {
|
||||
/* The block is being returned to the heap - it is no longer
|
||||
* allocated. */
|
||||
pxLink->xBlockSize &= ~xBlockAllocatedBit;
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* Add this block to the list of free blocks. */
|
||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||
traceFREE( pv, pxLink->xBlockSize );
|
||||
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||
xNumberOfSuccessfulFrees++;
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetFreeHeapSize( void ) { return xFreeBytesRemaining; }
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetMinimumEverFreeHeapSize( void ) { return xMinimumEverFreeBytesRemaining; }
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ) {
|
||||
BlockLink_t *pxIterator;
|
||||
uint8_t *puc;
|
||||
|
||||
/* Iterate through the list until a block is found that has a higher address
|
||||
* than the block being inserted. */
|
||||
for ( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock ) {
|
||||
/* Nothing to do here, just iterate to the right position. */
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted after
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxIterator;
|
||||
|
||||
if ( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert ) {
|
||||
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
|
||||
pxBlockToInsert = pxIterator;
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted before
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxBlockToInsert;
|
||||
|
||||
if ( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock ) {
|
||||
if ( pxIterator->pxNextFreeBlock != pxEnd ) {
|
||||
/* Form one big block from the two blocks. */
|
||||
pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
|
||||
} else {
|
||||
pxBlockToInsert->pxNextFreeBlock = pxEnd;
|
||||
}
|
||||
} else {
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the block being inserted plugged a gab, so was merged with the block
|
||||
* before and the block after, then it's pxNextFreeBlock pointer will have
|
||||
* already been set, and should not be set here as that would make it point
|
||||
* to itself. */
|
||||
if ( pxIterator != pxBlockToInsert ) {
|
||||
pxIterator->pxNextFreeBlock = pxBlockToInsert;
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) {
|
||||
BlockLink_t *pxFirstFreeBlockInRegion = NULL, *pxPreviousFreeBlock;
|
||||
size_t xAlignedHeap;
|
||||
size_t xTotalRegionSize, xTotalHeapSize = 0;
|
||||
BaseType_t xDefinedRegions = 0;
|
||||
size_t xAddress;
|
||||
const HeapRegion_t *pxHeapRegion;
|
||||
|
||||
/* Can only call once! */
|
||||
configASSERT( pxEnd == NULL );
|
||||
|
||||
pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] );
|
||||
|
||||
while ( pxHeapRegion->xSizeInBytes > 0 ) {
|
||||
xTotalRegionSize = pxHeapRegion->xSizeInBytes;
|
||||
|
||||
/* Ensure the heap region starts on a correctly aligned boundary. */
|
||||
xAddress = ( size_t ) pxHeapRegion->pucStartAddress;
|
||||
|
||||
if ( ( xAddress & portBYTE_ALIGNMENT_MASK ) != 0 ) {
|
||||
xAddress += ( portBYTE_ALIGNMENT - 1 );
|
||||
xAddress &= ~portBYTE_ALIGNMENT_MASK;
|
||||
|
||||
/* Adjust the size for the bytes lost to alignment. */
|
||||
xTotalRegionSize -= xAddress - ( size_t ) pxHeapRegion->pucStartAddress;
|
||||
}
|
||||
|
||||
xAlignedHeap = xAddress;
|
||||
|
||||
/* Set xStart if it has not already been set. */
|
||||
if ( xDefinedRegions == 0 ) {
|
||||
/* xStart is used to hold a pointer to the first item in the list of
|
||||
* free blocks. The void cast is used to prevent compiler warnings. */
|
||||
xStart.pxNextFreeBlock = ( BlockLink_t * ) xAlignedHeap;
|
||||
xStart.xBlockSize = ( size_t ) 0;
|
||||
} else {
|
||||
/* Should only get here if one region has already been added to the
|
||||
* heap. */
|
||||
configASSERT( pxEnd != NULL );
|
||||
|
||||
/* Check blocks are passed in with increasing start addresses. */
|
||||
configASSERT( xAddress > ( size_t ) pxEnd );
|
||||
}
|
||||
|
||||
/* Remember the location of the end marker in the previous region, if
|
||||
* any. */
|
||||
pxPreviousFreeBlock = pxEnd;
|
||||
|
||||
/* pxEnd is used to mark the end of the list of free blocks and is
|
||||
* inserted at the end of the region space. */
|
||||
xAddress = xAlignedHeap + xTotalRegionSize;
|
||||
xAddress -= xHeapStructSize;
|
||||
xAddress &= ~portBYTE_ALIGNMENT_MASK;
|
||||
|
||||
pxEnd = ( BlockLink_t * ) xAddress;
|
||||
pxEnd->xBlockSize = 0;
|
||||
pxEnd->pxNextFreeBlock = NULL;
|
||||
|
||||
/* To start with there is a single free block in this region that is
|
||||
* sized to take up the entire heap region minus the space taken by the
|
||||
* free block structure. */
|
||||
pxFirstFreeBlockInRegion = ( BlockLink_t * ) xAlignedHeap;
|
||||
pxFirstFreeBlockInRegion->xBlockSize = xAddress - ( size_t ) pxFirstFreeBlockInRegion;
|
||||
pxFirstFreeBlockInRegion->pxNextFreeBlock = pxEnd;
|
||||
|
||||
/* If this is not the first region that makes up the entire heap space
|
||||
* then link the previous region to this region. */
|
||||
if ( pxPreviousFreeBlock != NULL ) {
|
||||
pxPreviousFreeBlock->pxNextFreeBlock = pxFirstFreeBlockInRegion;
|
||||
}
|
||||
|
||||
xTotalHeapSize += pxFirstFreeBlockInRegion->xBlockSize;
|
||||
|
||||
/* Move onto the next HeapRegion_t structure. */
|
||||
xDefinedRegions++;
|
||||
pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] );
|
||||
}
|
||||
|
||||
while( pxHeapRegion->xSizeInBytes > 0 )
|
||||
{
|
||||
xTotalRegionSize = pxHeapRegion->xSizeInBytes;
|
||||
xMinimumEverFreeBytesRemaining = xTotalHeapSize;
|
||||
xFreeBytesRemaining = xTotalHeapSize;
|
||||
|
||||
/* Ensure the heap region starts on a correctly aligned boundary. */
|
||||
xAddress = ( size_t ) pxHeapRegion->pucStartAddress;
|
||||
/* Check something was actually defined before it is accessed. */
|
||||
configASSERT( xTotalHeapSize );
|
||||
|
||||
if( ( xAddress & portBYTE_ALIGNMENT_MASK ) != 0 )
|
||||
{
|
||||
xAddress += ( portBYTE_ALIGNMENT - 1 );
|
||||
xAddress &= ~portBYTE_ALIGNMENT_MASK;
|
||||
|
||||
/* Adjust the size for the bytes lost to alignment. */
|
||||
xTotalRegionSize -= xAddress - ( size_t ) pxHeapRegion->pucStartAddress;
|
||||
}
|
||||
|
||||
xAlignedHeap = xAddress;
|
||||
|
||||
/* Set xStart if it has not already been set. */
|
||||
if( xDefinedRegions == 0 )
|
||||
{
|
||||
/* xStart is used to hold a pointer to the first item in the list of
|
||||
* free blocks. The void cast is used to prevent compiler warnings. */
|
||||
xStart.pxNextFreeBlock = ( BlockLink_t * ) xAlignedHeap;
|
||||
xStart.xBlockSize = ( size_t ) 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Should only get here if one region has already been added to the
|
||||
* heap. */
|
||||
configASSERT( pxEnd != NULL );
|
||||
|
||||
/* Check blocks are passed in with increasing start addresses. */
|
||||
configASSERT( xAddress > ( size_t ) pxEnd );
|
||||
}
|
||||
|
||||
/* Remember the location of the end marker in the previous region, if
|
||||
* any. */
|
||||
pxPreviousFreeBlock = pxEnd;
|
||||
|
||||
/* pxEnd is used to mark the end of the list of free blocks and is
|
||||
* inserted at the end of the region space. */
|
||||
xAddress = xAlignedHeap + xTotalRegionSize;
|
||||
xAddress -= xHeapStructSize;
|
||||
xAddress &= ~portBYTE_ALIGNMENT_MASK;
|
||||
pxEnd = ( BlockLink_t * ) xAddress;
|
||||
pxEnd->xBlockSize = 0;
|
||||
pxEnd->pxNextFreeBlock = NULL;
|
||||
|
||||
/* To start with there is a single free block in this region that is
|
||||
* sized to take up the entire heap region minus the space taken by the
|
||||
* free block structure. */
|
||||
pxFirstFreeBlockInRegion = ( BlockLink_t * ) xAlignedHeap;
|
||||
pxFirstFreeBlockInRegion->xBlockSize = xAddress - ( size_t ) pxFirstFreeBlockInRegion;
|
||||
pxFirstFreeBlockInRegion->pxNextFreeBlock = pxEnd;
|
||||
|
||||
/* If this is not the first region that makes up the entire heap space
|
||||
* then link the previous region to this region. */
|
||||
if( pxPreviousFreeBlock != NULL )
|
||||
{
|
||||
pxPreviousFreeBlock->pxNextFreeBlock = pxFirstFreeBlockInRegion;
|
||||
}
|
||||
|
||||
xTotalHeapSize += pxFirstFreeBlockInRegion->xBlockSize;
|
||||
|
||||
/* Move onto the next HeapRegion_t structure. */
|
||||
xDefinedRegions++;
|
||||
pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] );
|
||||
}
|
||||
|
||||
xMinimumEverFreeBytesRemaining = xTotalHeapSize;
|
||||
xFreeBytesRemaining = xTotalHeapSize;
|
||||
|
||||
/* Check something was actually defined before it is accessed. */
|
||||
configASSERT( xTotalHeapSize );
|
||||
|
||||
/* Work out the position of the top bit in a size_t variable. */
|
||||
xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 );
|
||||
/* Work out the position of the top bit in a size_t variable. */
|
||||
xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortGetHeapStats( HeapStats_t * pxHeapStats )
|
||||
{
|
||||
BlockLink_t * pxBlock;
|
||||
size_t xBlocks = 0, xMaxSize = 0, xMinSize = portMAX_DELAY; /* portMAX_DELAY used as a portable way of getting the maximum value. */
|
||||
void vPortGetHeapStats( HeapStats_t *pxHeapStats ) {
|
||||
BlockLink_t *pxBlock;
|
||||
size_t xBlocks = 0, xMaxSize = 0, xMinSize = portMAX_DELAY; /* portMAX_DELAY used as a portable way of getting the maximum value. */
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
pxBlock = xStart.pxNextFreeBlock;
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
pxBlock = xStart.pxNextFreeBlock;
|
||||
|
||||
/* pxBlock will be NULL if the heap has not been initialised. The heap
|
||||
* is initialised automatically when the first allocation is made. */
|
||||
if( pxBlock != NULL )
|
||||
{
|
||||
do
|
||||
{
|
||||
/* Increment the number of blocks and record the largest block seen
|
||||
* so far. */
|
||||
xBlocks++;
|
||||
/* pxBlock will be NULL if the heap has not been initialised. The heap
|
||||
* is initialised automatically when the first allocation is made. */
|
||||
if ( pxBlock != NULL ) {
|
||||
do {
|
||||
/* Increment the number of blocks and record the largest block seen
|
||||
* so far. */
|
||||
xBlocks++;
|
||||
|
||||
if( pxBlock->xBlockSize > xMaxSize )
|
||||
{
|
||||
xMaxSize = pxBlock->xBlockSize;
|
||||
}
|
||||
|
||||
/* Heap five will have a zero sized block at the end of each
|
||||
* each region - the block is only used to link to the next
|
||||
* heap region so it not a real block. */
|
||||
if( pxBlock->xBlockSize != 0 )
|
||||
{
|
||||
if( pxBlock->xBlockSize < xMinSize )
|
||||
{
|
||||
xMinSize = pxBlock->xBlockSize;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move to the next block in the chain until the last block is
|
||||
* reached. */
|
||||
pxBlock = pxBlock->pxNextFreeBlock;
|
||||
} while( pxBlock != pxEnd );
|
||||
if ( pxBlock->xBlockSize > xMaxSize ) {
|
||||
xMaxSize = pxBlock->xBlockSize;
|
||||
}
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
|
||||
pxHeapStats->xSizeOfLargestFreeBlockInBytes = xMaxSize;
|
||||
pxHeapStats->xSizeOfSmallestFreeBlockInBytes = xMinSize;
|
||||
pxHeapStats->xNumberOfFreeBlocks = xBlocks;
|
||||
/* Heap five will have a zero sized block at the end of each
|
||||
* each region - the block is only used to link to the next
|
||||
* heap region so it not a real block. */
|
||||
if ( pxBlock->xBlockSize != 0 ) {
|
||||
if ( pxBlock->xBlockSize < xMinSize ) {
|
||||
xMinSize = pxBlock->xBlockSize;
|
||||
}
|
||||
}
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
pxHeapStats->xAvailableHeapSpaceInBytes = xFreeBytesRemaining;
|
||||
pxHeapStats->xNumberOfSuccessfulAllocations = xNumberOfSuccessfulAllocations;
|
||||
pxHeapStats->xNumberOfSuccessfulFrees = xNumberOfSuccessfulFrees;
|
||||
pxHeapStats->xMinimumEverFreeBytesRemaining = xMinimumEverFreeBytesRemaining;
|
||||
/* Move to the next block in the chain until the last block is
|
||||
* reached. */
|
||||
pxBlock = pxBlock->pxNextFreeBlock;
|
||||
} while ( pxBlock != pxEnd );
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
|
||||
pxHeapStats->xSizeOfLargestFreeBlockInBytes = xMaxSize;
|
||||
pxHeapStats->xSizeOfSmallestFreeBlockInBytes = xMinSize;
|
||||
pxHeapStats->xNumberOfFreeBlocks = xBlocks;
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
pxHeapStats->xAvailableHeapSpaceInBytes = xFreeBytesRemaining;
|
||||
pxHeapStats->xNumberOfSuccessfulAllocations = xNumberOfSuccessfulAllocations;
|
||||
pxHeapStats->xNumberOfSuccessfulFrees = xNumberOfSuccessfulFrees;
|
||||
pxHeapStats->xMinimumEverFreeBytesRemaining = xMinimumEverFreeBytesRemaining;
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
|
||||
@@ -19,15 +19,13 @@ uint16_t ADCReadings[ADC_NORM_SAMPLES]; // room for 32 lots of the pair of readi
|
||||
|
||||
// Heap
|
||||
|
||||
extern uint8_t __HeapBase;
|
||||
extern uint8_t __HeapLimit; // @suppress("Type cannot be resolved")
|
||||
const uint32_t _heap_size = ((&__HeapLimit) - (&__HeapBase));
|
||||
extern uint8_t _heap_start;
|
||||
extern uint8_t _heap_size; // @suppress("Type cannot be resolved")
|
||||
static HeapRegion_t xHeapRegions[] = {
|
||||
{&__HeapBase, (unsigned int)_heap_size},
|
||||
{&_heap_start, (unsigned int)&_heap_size},
|
||||
{NULL, 0}, /* Terminates the array. */
|
||||
{NULL, 0} /* Terminates the array. */
|
||||
};
|
||||
|
||||
// Functions
|
||||
|
||||
void setup_timer_scheduler(void);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
*
|
||||
*/
|
||||
#include "bflb_platform.h"
|
||||
#include "drv_mmheap.h"
|
||||
#include "hal_common.h"
|
||||
#include "hal_flash.h"
|
||||
#include "hal_mtimer.h"
|
||||
@@ -32,8 +33,11 @@ extern uint32_t __HeapLimit;
|
||||
|
||||
static uint8_t uart_dbg_disable = 0;
|
||||
|
||||
// struct heap_info mmheap_root;
|
||||
struct heap_info mmheap_root;
|
||||
|
||||
static struct heap_region system_mmheap[] = {
|
||||
{NULL, 0}, {NULL, 0}, /* Terminates the array. */
|
||||
};
|
||||
__WEAK__ void board_init(void) {}
|
||||
|
||||
__WEAK__ enum uart_index_type board_get_debug_uart_index(void) { return 0; }
|
||||
@@ -88,14 +92,14 @@ void bflb_platform_init(uint32_t baudrate) {
|
||||
}
|
||||
static bool initialized = false;
|
||||
if (!initialized) {
|
||||
// system_mmheap[0].addr = (uint8_t *)&__HeapBase;
|
||||
// system_mmheap[0].mem_size = ((size_t)&__HeapLimit - (size_t)&__HeapBase);
|
||||
system_mmheap[0].addr = (uint8_t *)&__HeapBase;
|
||||
system_mmheap[0].mem_size = ((size_t)&__HeapLimit - (size_t)&__HeapBase);
|
||||
|
||||
// if (system_mmheap[0].mem_size > 0) {
|
||||
// mmheap_init(&mmheap_root, system_mmheap);
|
||||
// }
|
||||
if (system_mmheap[0].mem_size > 0) {
|
||||
mmheap_init(&mmheap_root, system_mmheap);
|
||||
}
|
||||
|
||||
// MSG("dynamic memory init success,heap size = %d Kbyte \r\n", system_mmheap[0].mem_size / 1024);
|
||||
MSG("dynamic memory init success,heap size = %d Kbyte \r\n", system_mmheap[0].mem_size / 1024);
|
||||
initialized = 1;
|
||||
if (ret != SUCCESS) {
|
||||
MSG("flash init fail!!!\r\n");
|
||||
|
||||
@@ -17,17 +17,18 @@ OUTPUT_ARCH( "riscv" )
|
||||
/* configure the entry point */
|
||||
ENTRY(_enter)
|
||||
|
||||
StackSize = 0x800; /* 2KB */
|
||||
|
||||
__EM_SIZE = DEFINED(ble_controller_init) ? 8K : 0K;
|
||||
StackSize = 0x1000; /* 4KB */
|
||||
__EM_SIZE =8K;
|
||||
|
||||
MEMORY
|
||||
{
|
||||
xip_memory (rx) : ORIGIN = 0x23000000, LENGTH = 1022K
|
||||
xip_memory (rx) : ORIGIN = 0x23000000, LENGTH = 1008K /*1024 - 8K header - 4K*2 for settings and logo*/
|
||||
itcm_memory (rx) : ORIGIN = 0x22014000, LENGTH = 12K
|
||||
dtcm_memory (rx) : ORIGIN = 0x42017000, LENGTH = 4K
|
||||
ram_memory (!rx) : ORIGIN = 0x42018000, LENGTH = 96K
|
||||
hbn_memory (rx) : ORIGIN = 0x40010000, LENGTH = 0xE00 /* hbn ram 4K used 3.5K*/
|
||||
dtcm_memory (rx) : ORIGIN = 0x42014000, LENGTH = 8K
|
||||
ram_memory (!rx) : ORIGIN = 0x42016000, LENGTH = 72K
|
||||
rsvd_memory (!rx) : ORIGIN = 0x42028000, LENGTH = 1K
|
||||
ram2_memory (!rx) : ORIGIN = 0x42028400, LENGTH = (31K - __EM_SIZE)
|
||||
hbn_memory (rx) : ORIGIN = 0x40010000, LENGTH = 0xE00 /* hbn ram 4K used 3.5K*/
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
@@ -91,13 +92,12 @@ SECTIONS
|
||||
. = ALIGN(4);
|
||||
__text_code_end__ = .;
|
||||
} > xip_memory
|
||||
.preinit_array :
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
} >xip_memory AT>xip_memory
|
||||
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
@@ -105,7 +105,6 @@ SECTIONS
|
||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
} >xip_memory AT>xip_memory
|
||||
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
@@ -113,7 +112,6 @@ SECTIONS
|
||||
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
} >xip_memory AT>xip_memory
|
||||
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
@@ -137,7 +135,6 @@ SECTIONS
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
} >xip_memory AT>xip_memory
|
||||
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
@@ -146,13 +143,11 @@ SECTIONS
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
} >xip_memory AT>xip_memory
|
||||
|
||||
.lalign :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _data_lma = . );
|
||||
} >xip_memory AT>xip_memory
|
||||
|
||||
. = ALIGN(4);
|
||||
__itcm_load_addr = .;
|
||||
|
||||
@@ -182,7 +177,7 @@ SECTIONS
|
||||
__tcm_code_end__ = .;
|
||||
} > itcm_memory
|
||||
|
||||
__hbn_load_addr = __itcm_load_addr + SIZEOF(.itcm_region);
|
||||
__hbn_load_addr = __itcm_load_addr + SIZEOF(.itcm_region);
|
||||
|
||||
.hbn_ram_region : AT (__hbn_load_addr)
|
||||
{
|
||||
@@ -208,8 +203,6 @@ SECTIONS
|
||||
. = ALIGN(4);
|
||||
__tcm_data_end__ = .;
|
||||
} > dtcm_memory
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* .stack_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
@@ -226,7 +219,6 @@ SECTIONS
|
||||
__StackTop = ORIGIN(dtcm_memory) + LENGTH(dtcm_memory);
|
||||
PROVIDE( __freertos_irq_stack_top = __StackTop);
|
||||
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __tcm_data_end__, "region RAM overflowed with stack")
|
||||
/*************************************************************************/
|
||||
@@ -326,5 +318,7 @@ SECTIONS
|
||||
|
||||
ASSERT((__HeapLimit - __HeapBase ) >= __heap_min_size, "heap size is too short.")
|
||||
|
||||
PROVIDE( _heap_start = ORIGIN(ram2_memory) );
|
||||
PROVIDE( _heap_size = LENGTH(ram2_memory) );
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,421 @@
|
||||
/**
|
||||
* @file drv_mmheap.c
|
||||
* @brief
|
||||
*
|
||||
* Copyright (c) 2021 Bouffalolab team
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "drv_mmheap.h"
|
||||
|
||||
#define MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT 8
|
||||
#define MEM_MANAGE_BITS_PER_BYTE 8
|
||||
#define MEM_MANAGE_MEM_STRUCT_SIZE mmheap_align_up(sizeof(struct heap_node), MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT)
|
||||
#define MEM_MANAGE_MINUM_MEM_SIZE (MEM_MANAGE_MEM_STRUCT_SIZE << 1)
|
||||
#define MEM_MANAGE_ALLOCA_LABAL ((size_t)((size_t)1 << (sizeof(size_t) * MEM_MANAGE_BITS_PER_BYTE - 1)))
|
||||
|
||||
static inline size_t mmheap_align_down(size_t data, size_t align_byte)
|
||||
{
|
||||
return data & ~(align_byte - 1);
|
||||
}
|
||||
|
||||
static inline size_t mmheap_align_up(size_t data, size_t align_byte)
|
||||
{
|
||||
return (data + align_byte - 1) & ~(align_byte - 1);
|
||||
}
|
||||
|
||||
static inline struct heap_node *mmheap_addr_sub(const void *addr)
|
||||
{
|
||||
return (struct heap_node *)((const uint8_t *)addr - MEM_MANAGE_MEM_STRUCT_SIZE);
|
||||
}
|
||||
|
||||
static inline void *mmheap_addr_add(const struct heap_node *mem_node)
|
||||
{
|
||||
return (void *)((const uint8_t *)mem_node + MEM_MANAGE_MEM_STRUCT_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mmheap_insert_node_to_freelist
|
||||
*
|
||||
* @param pRoot
|
||||
* @param pNode
|
||||
*/
|
||||
static inline void mmheap_insert_node_to_freelist(struct heap_info *pRoot, struct heap_node *pNode)
|
||||
{
|
||||
struct heap_node *pPriv_Node;
|
||||
struct heap_node *pNext_Node;
|
||||
/*Find the node with an address similar to pNode*/
|
||||
for (pPriv_Node = pRoot->pStart; pPriv_Node->next_node < pNode; pPriv_Node = pPriv_Node->next_node) {
|
||||
}
|
||||
|
||||
pNext_Node = pPriv_Node->next_node;
|
||||
/*Try to merge the pNode with the previous block*/
|
||||
if ((uint8_t *)mmheap_addr_add(pPriv_Node) + pPriv_Node->mem_size == (uint8_t *)pNode) {
|
||||
if (pPriv_Node != pRoot->pStart) { /*can merge if not start block*/
|
||||
pPriv_Node->mem_size += MEM_MANAGE_MEM_STRUCT_SIZE + pNode->mem_size;
|
||||
pNode = pPriv_Node;
|
||||
} else {
|
||||
/*The latter is not merged if it is a Start block to avoid wasting memory*/
|
||||
pRoot->pStart->next_node = pNode;
|
||||
}
|
||||
} else {
|
||||
/*Insert directly into the free single-chain table when merging is not possible*/
|
||||
pPriv_Node->next_node = pNode;
|
||||
}
|
||||
/*Try to merge the pNode with the next block*/
|
||||
if ((uint8_t *)mmheap_addr_add(pNode) + pNode->mem_size == (uint8_t *)pNext_Node) {
|
||||
if (pNext_Node != pRoot->pEnd) {
|
||||
pNode->mem_size += MEM_MANAGE_MEM_STRUCT_SIZE + pNext_Node->mem_size;
|
||||
pNode->next_node = pNext_Node->next_node;
|
||||
} else {
|
||||
pNode->next_node = pRoot->pEnd;
|
||||
}
|
||||
} else {
|
||||
/*Insert directly into the free single-chain table when merging is not possible*/
|
||||
pNode->next_node = pNext_Node;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mmheap_get_state
|
||||
*
|
||||
* @param pRoot
|
||||
* @param pState
|
||||
*/
|
||||
void mmheap_get_state(struct heap_info *pRoot, struct heap_state *pState)
|
||||
{
|
||||
MMHEAP_ASSERT(pRoot->pStart != NULL);
|
||||
MMHEAP_ASSERT(pRoot->pEnd != NULL);
|
||||
pState->max_node_size = pRoot->pStart->next_node->mem_size;
|
||||
pState->min_node_size = pRoot->pStart->next_node->mem_size;
|
||||
pState->remain_size = 0;
|
||||
pState->free_node_num = 0;
|
||||
MMHEAP_LOCK();
|
||||
for (struct heap_node *pNode = pRoot->pStart->next_node; pNode->next_node != NULL; pNode = pNode->next_node) {
|
||||
pState->remain_size += pNode->mem_size;
|
||||
pState->free_node_num++;
|
||||
if (pNode->mem_size > pState->max_node_size)
|
||||
pState->max_node_size = pNode->mem_size;
|
||||
if (pNode->mem_size < pState->min_node_size)
|
||||
pState->min_node_size = pNode->mem_size;
|
||||
}
|
||||
MMHEAP_UNLOCK();
|
||||
}
|
||||
/**
|
||||
* @brief mmheap_align_alloc
|
||||
*
|
||||
* @param pRoot
|
||||
* @param align_size
|
||||
* @param want_size
|
||||
* @return void*
|
||||
*/
|
||||
void *mmheap_align_alloc(struct heap_info *pRoot, size_t align_size, size_t want_size)
|
||||
{
|
||||
void *pReturn = NULL;
|
||||
struct heap_node *pPriv_Node, *pNow_Node;
|
||||
|
||||
MMHEAP_ASSERT(pRoot->pStart != NULL);
|
||||
MMHEAP_ASSERT(pRoot->pEnd != NULL);
|
||||
|
||||
if (want_size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((want_size & MEM_MANAGE_ALLOCA_LABAL) != 0) {
|
||||
MMHEAP_MALLOC_FAIL();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (align_size & (align_size - 1)) {
|
||||
MMHEAP_MALLOC_FAIL();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MMHEAP_LOCK();
|
||||
if (want_size < MEM_MANAGE_MINUM_MEM_SIZE)
|
||||
want_size = MEM_MANAGE_MINUM_MEM_SIZE;
|
||||
if (align_size < MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT)
|
||||
align_size = MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT;
|
||||
|
||||
want_size = mmheap_align_up(want_size, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);
|
||||
|
||||
pPriv_Node = pRoot->pStart;
|
||||
pNow_Node = pRoot->pStart->next_node;
|
||||
|
||||
while (pNow_Node->next_node != NULL) {
|
||||
if (pNow_Node->mem_size >= want_size + MEM_MANAGE_MEM_STRUCT_SIZE) {
|
||||
size_t use_align_size;
|
||||
size_t new_size;
|
||||
pReturn = (void *)mmheap_align_up((size_t)mmheap_addr_add(pNow_Node), align_size); /*Calculate the aligned address*/
|
||||
use_align_size = (uint8_t *)pReturn - (uint8_t *)mmheap_addr_add(pNow_Node); /*Calculate the memory consumed by the alignment*/
|
||||
if (use_align_size != 0) { /*if Memory misalignment*/
|
||||
if (use_align_size < MEM_MANAGE_MINUM_MEM_SIZE + MEM_MANAGE_MEM_STRUCT_SIZE) { /*The unaligned value is too small*/
|
||||
pReturn = (void *)mmheap_align_up(
|
||||
(size_t)mmheap_addr_add(pNow_Node) + MEM_MANAGE_MINUM_MEM_SIZE + MEM_MANAGE_MEM_STRUCT_SIZE, align_size);
|
||||
use_align_size = (uint8_t *)pReturn - (uint8_t *)mmheap_addr_add(pNow_Node);
|
||||
}
|
||||
if (use_align_size <= pNow_Node->mem_size) {
|
||||
new_size = pNow_Node->mem_size - use_align_size; /*Calculate the remaining memory size by removing the memory consumed by alignment*/
|
||||
if (new_size >= want_size) { /*Meet the conditions for distribution*/
|
||||
struct heap_node *pNew_Node = mmheap_addr_sub(pReturn);
|
||||
pNow_Node->mem_size -= new_size + MEM_MANAGE_MEM_STRUCT_SIZE; /*Split Node*/
|
||||
pNew_Node->mem_size = new_size; /*The new node is also not in the free chain and does not need to be discharged from the free chain*/
|
||||
pNew_Node->next_node = NULL;
|
||||
pNow_Node = pNew_Node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else { /*Memory is directly aligned*/
|
||||
pPriv_Node->next_node = pNow_Node->next_node;
|
||||
pNow_Node->next_node = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pPriv_Node = pNow_Node;
|
||||
pNow_Node = pNow_Node->next_node;
|
||||
}
|
||||
|
||||
if (pNow_Node == pRoot->pEnd) {
|
||||
MMHEAP_UNLOCK();
|
||||
MMHEAP_MALLOC_FAIL();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pNow_Node->mem_size >= MEM_MANAGE_MINUM_MEM_SIZE + MEM_MANAGE_MEM_STRUCT_SIZE + want_size) { /*Node memory is still available*/
|
||||
struct heap_node *pNew_Node = (struct heap_node *)((uint8_t *)mmheap_addr_add(pNow_Node) + want_size); /*Calculate the address of the node that will be moved into the free chain table*/
|
||||
pNew_Node->mem_size = pNow_Node->mem_size - want_size - MEM_MANAGE_MEM_STRUCT_SIZE;
|
||||
pNew_Node->next_node = NULL;
|
||||
pNow_Node->mem_size = want_size;
|
||||
mmheap_insert_node_to_freelist(pRoot, pNew_Node);
|
||||
}
|
||||
pNow_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL;
|
||||
MMHEAP_UNLOCK();
|
||||
return pReturn;
|
||||
}
|
||||
/**
|
||||
* @brief mmheap_alloc
|
||||
*
|
||||
* @param pRoot
|
||||
* @param want_size
|
||||
* @return void*
|
||||
*/
|
||||
void *mmheap_alloc(struct heap_info *pRoot, size_t want_size)
|
||||
{
|
||||
return mmheap_align_alloc(pRoot, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT, want_size);
|
||||
}
|
||||
/**
|
||||
* @brief mmheap_realloc
|
||||
*
|
||||
* @param pRoot
|
||||
* @param src_addr
|
||||
* @param want_size
|
||||
* @return void*
|
||||
*/
|
||||
void *mmheap_realloc(struct heap_info *pRoot, void *src_addr, size_t want_size)
|
||||
{
|
||||
void *pReturn = NULL;
|
||||
struct heap_node *pNext_Node, *pPriv_Node;
|
||||
struct heap_node *pSrc_Node;
|
||||
MMHEAP_ASSERT(pRoot->pStart != NULL);
|
||||
MMHEAP_ASSERT(pRoot->pEnd != NULL);
|
||||
if (src_addr == NULL) {
|
||||
return mmheap_align_alloc(pRoot, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT, want_size);
|
||||
}
|
||||
if (want_size == 0) {
|
||||
mmheap_free(pRoot, src_addr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MMHEAP_LOCK();
|
||||
if ((want_size & MEM_MANAGE_ALLOCA_LABAL) != 0) {
|
||||
MMHEAP_UNLOCK();
|
||||
MMHEAP_MALLOC_FAIL();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pSrc_Node = mmheap_addr_sub(src_addr);
|
||||
|
||||
if ((pSrc_Node->mem_size & MEM_MANAGE_ALLOCA_LABAL) == 0) {
|
||||
MMHEAP_UNLOCK();
|
||||
MMHEAP_ASSERT((pSrc_Node->mem_size & MEM_MANAGE_ALLOCA_LABAL) != 0);
|
||||
MMHEAP_MALLOC_FAIL();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pSrc_Node->mem_size &= ~MEM_MANAGE_ALLOCA_LABAL;
|
||||
if (pSrc_Node->mem_size >= want_size) {
|
||||
pSrc_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL;
|
||||
pReturn = src_addr;
|
||||
MMHEAP_UNLOCK();
|
||||
return pReturn;
|
||||
}
|
||||
/*Start looking in the free list for blocks similar to this block*/
|
||||
for (pPriv_Node = pRoot->pStart; pPriv_Node->next_node < pSrc_Node; pPriv_Node = pPriv_Node->next_node) {
|
||||
}
|
||||
pNext_Node = pPriv_Node->next_node;
|
||||
|
||||
if (pNext_Node != pRoot->pEnd &&
|
||||
((uint8_t *)src_addr + pSrc_Node->mem_size == (uint8_t *)pNext_Node) &&
|
||||
(pSrc_Node->mem_size + pNext_Node->mem_size + MEM_MANAGE_MEM_STRUCT_SIZE >= want_size)) {
|
||||
/*Meet next node non-end, memory contiguous, enough memory left*/
|
||||
pReturn = src_addr;
|
||||
pPriv_Node->next_node = pNext_Node->next_node;
|
||||
pSrc_Node->mem_size += MEM_MANAGE_MEM_STRUCT_SIZE + pNext_Node->mem_size;
|
||||
want_size = mmheap_align_up(want_size, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);
|
||||
if (pSrc_Node->mem_size >= MEM_MANAGE_MINUM_MEM_SIZE + MEM_MANAGE_MEM_STRUCT_SIZE + want_size) { /*Removing the remaining space allocated is enough to open new blocks*/
|
||||
struct heap_node *pNew_Node = (struct heap_node *)((uint8_t *)mmheap_addr_add(pSrc_Node) + want_size);
|
||||
pNew_Node->next_node = NULL;
|
||||
pNew_Node->mem_size = pSrc_Node->mem_size - want_size - MEM_MANAGE_MEM_STRUCT_SIZE;
|
||||
pSrc_Node->mem_size = want_size;
|
||||
mmheap_insert_node_to_freelist(pRoot, pNew_Node);
|
||||
}
|
||||
pSrc_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL;
|
||||
MMHEAP_UNLOCK();
|
||||
} else {
|
||||
MMHEAP_UNLOCK();
|
||||
pReturn = mmheap_align_alloc(pRoot, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT, want_size);
|
||||
if (pReturn == NULL) {
|
||||
pSrc_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL;
|
||||
MMHEAP_MALLOC_FAIL();
|
||||
return NULL;
|
||||
}
|
||||
MMHEAP_LOCK();
|
||||
memcpy(pReturn, src_addr, pSrc_Node->mem_size);
|
||||
pSrc_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL;
|
||||
MMHEAP_UNLOCK();
|
||||
mmheap_free(pRoot, src_addr);
|
||||
}
|
||||
return pReturn;
|
||||
}
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param pRoot
|
||||
* @param num
|
||||
* @param size
|
||||
* @return void*
|
||||
*/
|
||||
void *mmheap_calloc(struct heap_info *pRoot, size_t num, size_t size)
|
||||
{
|
||||
void *pReturn = NULL;
|
||||
|
||||
pReturn = (void *)mmheap_alloc(pRoot, size * num);
|
||||
|
||||
if (pReturn) {
|
||||
memset(pReturn, 0, num * size);
|
||||
}
|
||||
|
||||
return pReturn;
|
||||
}
|
||||
/**
|
||||
* @brief mmheap_free
|
||||
*
|
||||
* @param pRoot
|
||||
* @param addr
|
||||
*/
|
||||
void mmheap_free(struct heap_info *pRoot, void *addr)
|
||||
{
|
||||
struct heap_node *pFree_Node;
|
||||
MMHEAP_ASSERT(pRoot->pStart != NULL);
|
||||
MMHEAP_ASSERT(pRoot->pEnd != NULL);
|
||||
MMHEAP_LOCK();
|
||||
if (addr == NULL) {
|
||||
MMHEAP_UNLOCK();
|
||||
return;
|
||||
}
|
||||
pFree_Node = mmheap_addr_sub(addr);
|
||||
|
||||
if ((pFree_Node->mem_size & MEM_MANAGE_ALLOCA_LABAL) == 0) {
|
||||
MMHEAP_UNLOCK();
|
||||
MMHEAP_ASSERT((pFree_Node->mem_size & MEM_MANAGE_ALLOCA_LABAL) != 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pFree_Node->next_node != NULL) {
|
||||
MMHEAP_UNLOCK();
|
||||
MMHEAP_ASSERT(pFree_Node->next_node == NULL);
|
||||
return;
|
||||
}
|
||||
pFree_Node->mem_size &= ~MEM_MANAGE_ALLOCA_LABAL;
|
||||
mmheap_insert_node_to_freelist(pRoot, pFree_Node);
|
||||
MMHEAP_UNLOCK();
|
||||
}
|
||||
/**
|
||||
* @brief mmheap_init
|
||||
*
|
||||
* @param pRoot
|
||||
* @param pRegion
|
||||
*/
|
||||
void mmheap_init(struct heap_info *pRoot, const struct heap_region *pRegion)
|
||||
{
|
||||
struct heap_node *align_addr;
|
||||
size_t align_size;
|
||||
struct heap_node *pPriv_node = NULL;
|
||||
|
||||
pRoot->total_size = 0;
|
||||
pRoot->pEnd = NULL;
|
||||
pRoot->pStart = NULL;
|
||||
|
||||
for (; pRegion->addr != NULL; pRegion++) {
|
||||
align_addr = (struct heap_node *)mmheap_align_up((size_t)pRegion->addr, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT); /*Calculate the aligned address*/
|
||||
if ((uint8_t *)align_addr > pRegion->mem_size + (uint8_t *)pRegion->addr) /*Alignment consumes more memory than the memory area*/
|
||||
continue;
|
||||
align_size = pRegion->mem_size - ((uint8_t *)align_addr - (uint8_t *)pRegion->addr); /*Calculate the size of memory left after alignment*/
|
||||
if (align_size < MEM_MANAGE_MINUM_MEM_SIZE + MEM_MANAGE_MEM_STRUCT_SIZE) /*if Aligning the remaining memory is too small*/
|
||||
continue;
|
||||
align_size -= MEM_MANAGE_MEM_STRUCT_SIZE; /*Find the size of the memory block after removing the table header*/
|
||||
align_addr->mem_size = align_size;
|
||||
align_addr->next_node = NULL;
|
||||
if (pRoot->pStart == NULL) {
|
||||
pRoot->pStart = align_addr; /*set current addr for start*/
|
||||
if (align_size >= MEM_MANAGE_MINUM_MEM_SIZE + MEM_MANAGE_MEM_STRUCT_SIZE) { /*If the remaining blocks are large enough*/
|
||||
align_size -= MEM_MANAGE_MEM_STRUCT_SIZE; /*Remove the next block of table headers remaining memory size*/
|
||||
align_addr = (struct heap_node *)((uint8_t *)pRoot->pStart + MEM_MANAGE_MEM_STRUCT_SIZE); //the next block addr
|
||||
align_addr->mem_size = align_size;
|
||||
align_addr->next_node = NULL;
|
||||
pRoot->pStart->mem_size = 0;
|
||||
pRoot->pStart->next_node = align_addr;
|
||||
pRoot->total_size = align_addr->mem_size;
|
||||
} else { /*The memory is too small, and the address of the current memory block is recorded as start*/
|
||||
pRoot->total_size = 0;
|
||||
pRoot->pStart->mem_size = 0;
|
||||
}
|
||||
} else {
|
||||
pPriv_node->next_node = align_addr;
|
||||
pRoot->total_size += align_size;
|
||||
}
|
||||
pPriv_node = align_addr;
|
||||
}
|
||||
//At this point, pPriv_node is the last block, then place the end of the table at the end of the block, find the address to place the end block, end block is only convenient for traversal, so as small as possible, assigned to MEM_MANAGE_MEM_STRUCT_SIZE
|
||||
align_addr = (struct heap_node *)mmheap_align_down(
|
||||
(size_t)mmheap_addr_add(pPriv_node) + pPriv_node->mem_size - MEM_MANAGE_MEM_STRUCT_SIZE, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);
|
||||
align_size = (uint8_t *)align_addr - (uint8_t *)mmheap_addr_add(pPriv_node); /*Find the remaining size of the previous block after the end block is allocated*/
|
||||
if (align_size >= MEM_MANAGE_MINUM_MEM_SIZE) {
|
||||
pRoot->total_size -= pPriv_node->mem_size - align_size; /*Removing memory consumed by allocating end blocks*/
|
||||
pRoot->pEnd = align_addr; /*Update the address at the end of the list*/
|
||||
pPriv_node->next_node = align_addr;
|
||||
pPriv_node->mem_size = align_size;
|
||||
align_addr->next_node = NULL;
|
||||
align_addr->mem_size = 0; /*The end block is not involved in memory allocation, so a direct 0 is sufficient*/
|
||||
} else { /*The last block is too small, directly as the end block*/
|
||||
pRoot->pEnd = pPriv_node;
|
||||
pRoot->total_size -= pPriv_node->mem_size;
|
||||
}
|
||||
MMHEAP_ASSERT(pRoot->pStart != NULL);
|
||||
MMHEAP_ASSERT(pRoot->pEnd != NULL);
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/**
|
||||
* @file drv_mmheap.h
|
||||
* @brief
|
||||
*
|
||||
* Copyright (c) 2021 Bouffalolab team
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
*/
|
||||
#ifndef __DRV_MMHEAP_H
|
||||
#define __DRV_MMHEAP_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef MMHEAP_LOCK
|
||||
#define MMHEAP_LOCK()
|
||||
#endif
|
||||
|
||||
#ifndef MMHEAP_UNLOCK
|
||||
#define MMHEAP_UNLOCK()
|
||||
#endif
|
||||
|
||||
#ifndef MMHEAP_ASSERT
|
||||
#define MMHEAP_ASSERT(A) \
|
||||
if (!(A)) \
|
||||
printf("mmheap malloc error:drv_mmheap,%d\r\n", __LINE__)
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef MMHEAP_MALLOC_FAIL
|
||||
#define MMHEAP_MALLOC_FAIL() printf("mmheap malloc fail:drv_mmheap,%d\r\n", __LINE__)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct heap_region {
|
||||
void *addr;
|
||||
size_t mem_size;
|
||||
};
|
||||
|
||||
struct heap_node {
|
||||
struct heap_node *next_node;
|
||||
size_t mem_size;
|
||||
};
|
||||
|
||||
struct heap_info {
|
||||
struct heap_node *pStart;
|
||||
struct heap_node *pEnd;
|
||||
size_t total_size;
|
||||
};
|
||||
|
||||
struct heap_state {
|
||||
size_t remain_size;
|
||||
size_t free_node_num;
|
||||
size_t max_node_size;
|
||||
size_t min_node_size;
|
||||
};
|
||||
|
||||
void mmheap_init(struct heap_info *pRoot, const struct heap_region *pRigon);
|
||||
/**
|
||||
* @brief Alloc start address aligned memory from the heap.
|
||||
* Alloc aligned address and specified size memory from the heap.
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] pRoot heap info.
|
||||
* @param[in] align_size address align mask of the memory.
|
||||
* @param[in] want_size size of the memory.
|
||||
*
|
||||
* @return the pointer to the allocated memory.
|
||||
*/
|
||||
void *mmheap_align_alloc(struct heap_info *pRoot, size_t align_size, size_t want_size);
|
||||
/**
|
||||
* @brief Alloc memory.
|
||||
* Allocate size bytes and returns a pointer to the allocated memory.
|
||||
*
|
||||
* @attention size should no bigger than MMHEAP_BLK_SIZE_MAX.
|
||||
*
|
||||
* @param[in] pRoot heap info.
|
||||
* @param[in] want_size size of the memory.
|
||||
*
|
||||
* @return the pointer to the allocated memory.
|
||||
*/
|
||||
void *mmheap_alloc(struct heap_info *pRoot, size_t want_size);
|
||||
/**
|
||||
* @brief Realloc memory from the heap.
|
||||
* Change the size of the memory block pointed to by ptr to size bytes.
|
||||
*
|
||||
* @attention
|
||||
* <ul>
|
||||
* <li> if ptr is NULL, then the call is equivalent to mmheap_alloc(size), for all values of size.
|
||||
* <li> if ptr is if size is equal to zero, and ptr is not NULL, then the call is equivalent to mmheap_free(ptr).
|
||||
* </ul>
|
||||
*
|
||||
* @param[in] pRoot heap info.
|
||||
* @param[in] src_addr old pointer to the memory space.
|
||||
* @param[in] want_size new size of the memory space.
|
||||
*
|
||||
* @return the new pointer to the allocated memory.
|
||||
*/
|
||||
void *mmheap_realloc(struct heap_info *pRoot, void *src_addr, size_t want_size);
|
||||
/**
|
||||
* @brief Cealloc memory from the heap.
|
||||
* Change the size of the memory block pointed to by ptr to size bytes.
|
||||
*
|
||||
* @attention
|
||||
* <ul>
|
||||
* <li> if ptr is NULL, then the call is equivalent to mmheap_alloc(size), for all values of size.
|
||||
* <li> if ptr is if size is equal to zero, and ptr is not NULL, then the call is equivalent to mmheap_free(ptr).
|
||||
* </ul>
|
||||
*
|
||||
* @param[in] pRoot heap info.
|
||||
* @param[in] num size number.
|
||||
* @param[in] size new size of the memory space.
|
||||
*
|
||||
* @return the new pointer to the allocated memory.
|
||||
*/
|
||||
void *mmheap_calloc(struct heap_info *pRoot, size_t num, size_t size);
|
||||
/**
|
||||
* @brief Free the memory.
|
||||
* Free the memory space pointed to by ptr, which must have been returned by a previous call to mmheap_alloc(), mmheap_aligned_alloc(), or mmheap_realloc().
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* @param[in] pRoot heap info.
|
||||
* @param[in] addr pointer to the memory.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void mmheap_free(struct heap_info *pRoot, void *addr);
|
||||
/**
|
||||
* @brief get mmheap state
|
||||
*
|
||||
* @param pRoot heap info.
|
||||
* @param pState heap state
|
||||
*/
|
||||
void mmheap_get_state(struct heap_info *pRoot, struct heap_state *pState);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,70 +1,61 @@
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <FreeRTOS.h>
|
||||
#include "bflb_platform.h"
|
||||
#include <task.h>
|
||||
#include "ble.h"
|
||||
#include "BSP.h"
|
||||
#include "bflb_platform.h"
|
||||
#include "bl702_glb.h"
|
||||
#include "ble_characteristics.h"
|
||||
#include "ble_peripheral.h"
|
||||
#include "bluetooth.h"
|
||||
#include "conn.h"
|
||||
#include "gatt.h"
|
||||
#include "hci_core.h"
|
||||
#include "uuid.h"
|
||||
#include "ble_peripheral.h"
|
||||
#include "log.h"
|
||||
#include "bl702_glb.h"
|
||||
#include "ble_characteristics.h"
|
||||
#include "hal_clock.h"
|
||||
#include "ble.h"
|
||||
#include "hci_core.h"
|
||||
#include "log.h"
|
||||
#include "uuid.h"
|
||||
#include <FreeRTOS.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <task.h>
|
||||
|
||||
void ble_stack_start(void) {
|
||||
MSG("BLE Starting\n");
|
||||
GLB_Set_EM_Sel(GLB_EM_8KB);
|
||||
ble_controller_init(configMAX_PRIORITIES - 1);
|
||||
|
||||
// Initialize BLE Host stack
|
||||
hci_driver_init();
|
||||
|
||||
|
||||
void ble_stack_start(void)
|
||||
{
|
||||
MSG("BLE Starting\n");
|
||||
GLB_Set_EM_Sel(GLB_EM_8KB);
|
||||
ble_controller_init(configMAX_PRIORITIES - 1);
|
||||
|
||||
// // Initialize BLE Host stack
|
||||
hci_driver_init();
|
||||
|
||||
bt_enable(bt_enable_cb);
|
||||
MSG("BLE Starting...Done\n");
|
||||
bt_enable(bt_enable_cb);
|
||||
MSG("BLE Starting...Done\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
|
||||
application must provide an implementation of vApplicationGetTimerTaskMemory()
|
||||
to provide the memory that is used by the Timer service task. */
|
||||
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize)
|
||||
{
|
||||
/* If the buffers to be provided to the Timer task are declared inside this
|
||||
function then they must be declared static - otherwise they will be allocated on
|
||||
the stack and so not exists after this function exits. */
|
||||
static StaticTask_t xTimerTaskTCB;
|
||||
static StackType_t uxTimerTaskStack[configTIMER_TASK_STACK_DEPTH];
|
||||
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize) {
|
||||
/* If the buffers to be provided to the Timer task are declared inside this
|
||||
function then they must be declared static - otherwise they will be allocated on
|
||||
the stack and so not exists after this function exits. */
|
||||
static StaticTask_t xTimerTaskTCB;
|
||||
static StackType_t uxTimerTaskStack[configTIMER_TASK_STACK_DEPTH];
|
||||
|
||||
/* Pass out a pointer to the StaticTask_t structure in which the Timer
|
||||
task's state will be stored. */
|
||||
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
|
||||
/* Pass out a pointer to the StaticTask_t structure in which the Timer
|
||||
task's state will be stored. */
|
||||
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
|
||||
|
||||
/* Pass out the array that will be used as the Timer task's stack. */
|
||||
*ppxTimerTaskStackBuffer = uxTimerTaskStack;
|
||||
/* Pass out the array that will be used as the Timer task's stack. */
|
||||
*ppxTimerTaskStackBuffer = uxTimerTaskStack;
|
||||
|
||||
/* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
|
||||
Note that, as the array is necessarily of type StackType_t,
|
||||
configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */
|
||||
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
|
||||
/* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
|
||||
Note that, as the array is necessarily of type StackType_t,
|
||||
configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */
|
||||
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
|
||||
}
|
||||
|
||||
void vApplicationMallocFailedHook(void) {
|
||||
MSG("vApplicationMallocFailedHook\r\n");
|
||||
|
||||
|
||||
void vApplicationMallocFailedHook(void)
|
||||
{
|
||||
MSG("vApplicationMallocFailedHook\r\n");
|
||||
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
while (1) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,8 +113,9 @@ int ble_char_read_status_callback(struct bt_conn *conn, const struct bt_gatt_att
|
||||
// hall sensor
|
||||
{
|
||||
int16_t hallEffectStrength = getRawHallEffect();
|
||||
if (hallEffectStrength < 0)
|
||||
if (hallEffectStrength < 0) {
|
||||
hallEffectStrength = -hallEffectStrength;
|
||||
}
|
||||
temp = hallEffectStrength;
|
||||
memcpy(buf, &temp, sizeof(temp));
|
||||
return sizeof(temp);
|
||||
|
||||
@@ -258,7 +258,9 @@ static struct bt_gatt_attr ble_attrs_declaration[] = {
|
||||
NAME
|
||||
get_attr
|
||||
*/
|
||||
struct bt_gatt_attr *get_attr(u8_t index) { return &ble_attrs_declaration[index]; }
|
||||
struct bt_gatt_attr *get_attr(u8_t index) {
|
||||
return &ble_attrs_declaration[index];
|
||||
}
|
||||
|
||||
static struct bt_gatt_service ble_tp_server = BT_GATT_SERVICE(ble_attrs_declaration);
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ NOTES
|
||||
#ifndef _BLE_TP_SVC_H_
|
||||
#define _BLE_TP_SVC_H_
|
||||
|
||||
#include "types.h"
|
||||
#include "ble_config.h"
|
||||
|
||||
// read value handle offset 2
|
||||
|
||||
@@ -63,10 +63,10 @@
|
||||
* OLED Brightness
|
||||
*
|
||||
*/
|
||||
#define MIN_BRIGHTNESS 1 // Min OLED brightness selectable
|
||||
#define MAX_BRIGHTNESS 101 // Max OLED brightness selectable
|
||||
#define BRIGHTNESS_STEP 25 // OLED brightness increment
|
||||
#define DEFAULT_BRIGHTNESS 26 // default OLED brightness
|
||||
#define MIN_BRIGHTNESS 1 // Min OLED brightness selectable
|
||||
#define MAX_BRIGHTNESS 101 // Max OLED brightness selectable
|
||||
#define BRIGHTNESS_STEP 25 // OLED brightness increment
|
||||
#define DEFAULT_BRIGHTNESS 26 // default OLED brightness
|
||||
|
||||
/**
|
||||
* Temp change settings
|
||||
@@ -87,7 +87,7 @@
|
||||
#define POWER_PULSE_DEFAULT 0
|
||||
#else
|
||||
#define POWER_PULSE_DEFAULT 5
|
||||
#endif /* Pinecil */
|
||||
#endif /* Pinecil */
|
||||
#define POWER_PULSE_WAIT_DEFAULT 4 // Default rate of the power pulse: 4*2500 = 10000 ms = 10 s
|
||||
#define POWER_PULSE_DURATION_DEFAULT 1 // Default duration of the power pulse: 1*250 = 250 ms
|
||||
|
||||
@@ -167,8 +167,10 @@
|
||||
#define CANT_DIRECT_READ_SETTINGS
|
||||
#endif /* Pinecilv2 */
|
||||
|
||||
#define FLASH_LOGOADDR (0x23000000 + (1022 * 1024))
|
||||
#define FLASH_PAGE_SIZE (1024)
|
||||
#define FLASH_PAGE_SIZE (1024) // Read pages
|
||||
// Erase is 4 or 8 k size, so we pad these apart for now
|
||||
// If we ever get low on flash, will need better solution
|
||||
#define FLASH_LOGOADDR (0x23000000 + (1016 * FLASH_PAGE_SIZE))
|
||||
#define SETTINGS_START_PAGE (1023 * FLASH_PAGE_SIZE) // Hal auto offsets base addr
|
||||
|
||||
#endif /* CONFIGURATION_H_ */
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// BSP mapping functions
|
||||
|
||||
#include "BSP.h"
|
||||
#include "BootLogo.h"
|
||||
#include "HUB238.hpp"
|
||||
#include "I2C_Wrapper.hpp"
|
||||
#include "Pins.h"
|
||||
@@ -208,7 +209,7 @@ bool isTipDisconnected() {
|
||||
|
||||
void setStatusLED(const enum StatusLED state) {}
|
||||
uint8_t preStartChecks() {
|
||||
if (!hub238_has_run_selection()) {
|
||||
if (!hub238_has_run_selection() && (xTaskGetTickCount() < TICKS_SECOND * 5)) {
|
||||
return 0;
|
||||
}
|
||||
// We check if we are in a "Limited" mode; where we have to run the PWM really fast
|
||||
@@ -230,10 +231,12 @@ uint64_t getDeviceID() {
|
||||
}
|
||||
|
||||
uint8_t getTipResistanceX10() { return TIP_RESISTANCE; }
|
||||
|
||||
bool isTipShorted() { return false; }
|
||||
uint8_t preStartChecksDone() { return 1; }
|
||||
|
||||
uint8_t getTipThermalMass() { return TIP_THERMAL_MASS; }
|
||||
uint8_t getTipInertia() { return TIP_THERMAL_INERTIA; }
|
||||
|
||||
void setBuzzer(bool on) {}
|
||||
void setBuzzer(bool on) {}
|
||||
|
||||
void showBootLogo(void) { BootLogo::handleShowingLogo((uint8_t *)FLASH_LOGOADDR); }
|
||||
|
||||
@@ -206,8 +206,9 @@ static void MX_ADC1_Init(void) {
|
||||
HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
|
||||
SET_BIT(hadc1.Instance->CR1, (ADC_CR1_JEOCIE)); // Enable end of injected conv irq
|
||||
// Run ADC internal calibration
|
||||
while (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK)
|
||||
while (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/* ADC2 init function */
|
||||
@@ -244,8 +245,9 @@ static void MX_ADC2_Init(void) {
|
||||
HAL_ADCEx_InjectedConfigChannel(&hadc2, &sConfigInjected);
|
||||
|
||||
// Run ADC internal calibration
|
||||
while (HAL_ADCEx_Calibration_Start(&hadc2) != HAL_OK)
|
||||
while (HAL_ADCEx_Calibration_Start(&hadc2) != HAL_OK) {
|
||||
;
|
||||
}
|
||||
}
|
||||
/* I2C1 init function */
|
||||
static void MX_I2C1_Init(void) {
|
||||
|
||||
@@ -30,10 +30,9 @@ void flash_save_buffer(const uint8_t *buffer, const uint16_t length) {
|
||||
HAL_FLASH_Unlock();
|
||||
for (uint16_t i = 0; i < (length / 2); i++) {
|
||||
resetWatchdog();
|
||||
HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, SETTINGS_START_PAGE+ (i*sizeof(uint16_t)), data[i]);
|
||||
HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, SETTINGS_START_PAGE + (i * sizeof(uint16_t)), data[i]);
|
||||
}
|
||||
HAL_FLASH_Lock();
|
||||
|
||||
}
|
||||
|
||||
void flash_read_buffer(uint8_t *buffer, const uint16_t length) { memcpy(buffer, (uint8_t*)SETTINGS_START_PAGE, length); }
|
||||
void flash_read_buffer(uint8_t *buffer, const uint16_t length) { memcpy(buffer, (uint8_t *)SETTINGS_START_PAGE, length); }
|
||||
|
||||
@@ -208,40 +208,38 @@ static void prvTaskExitError(void) {
|
||||
// therefore not output an 'unreachable code' warning for code that appears
|
||||
// after it. */
|
||||
// }
|
||||
for(;;){
|
||||
|
||||
}
|
||||
for (;;) {}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortSVCHandler(void) {
|
||||
__asm volatile(" ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */
|
||||
" ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
|
||||
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
|
||||
" ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
|
||||
" msr psp, r0 \n" /* Restore the task stack pointer. */
|
||||
" isb \n"
|
||||
" mov r0, #0 \n"
|
||||
" msr basepri, r0 \n"
|
||||
" orr r14, #0xd \n"
|
||||
" bx r14 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n");
|
||||
__asm volatile(" ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */
|
||||
" ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
|
||||
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
|
||||
" ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
|
||||
" msr psp, r0 \n" /* Restore the task stack pointer. */
|
||||
" isb \n"
|
||||
" mov r0, #0 \n"
|
||||
" msr basepri, r0 \n"
|
||||
" orr r14, #0xd \n"
|
||||
" bx r14 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n");
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvPortStartFirstTask(void) {
|
||||
__asm volatile(" ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n"
|
||||
" ldr r0, [r0] \n"
|
||||
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
|
||||
" cpsie i \n" /* Globally enable interrupts. */
|
||||
" cpsie f \n"
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc 0 \n" /* System call to start first task. */
|
||||
" nop \n");
|
||||
__asm volatile(" ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n"
|
||||
" ldr r0, [r0] \n"
|
||||
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
|
||||
" cpsie i \n" /* Globally enable interrupts. */
|
||||
" cpsie f \n"
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc 0 \n" /* System call to start first task. */
|
||||
" nop \n");
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
@@ -215,6 +215,6 @@ uint8_t hub238_source_currentX100() {
|
||||
temp &= 0b1111;
|
||||
return pdo_slot_to_currentx100(temp);
|
||||
}
|
||||
return 10;//Failsafe to 0.1 amp
|
||||
return 10; // Failsafe to 0.1 amp
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -25,41 +25,43 @@ uint8_t OLED::displayOffset;
|
||||
uint8_t OLED::screenBuffer[16 + (OLED_WIDTH * (OLED_HEIGHT / 8)) + 10]; // The data buffer
|
||||
uint8_t OLED::secondFrameBuffer[16 + (OLED_WIDTH * (OLED_HEIGHT / 8)) + 10];
|
||||
uint32_t OLED::displayChecksum;
|
||||
/*Setup params for the OLED screen*/
|
||||
/*http://www.displayfuture.com/Display/datasheet/controller/SSD1307.pdf*/
|
||||
/*All commands are prefixed with 0x80*/
|
||||
/*Data packets are prefixed with 0x40*/
|
||||
/*
|
||||
* Setup params for the OLED screen
|
||||
* http://www.displayfuture.com/Display/datasheet/controller/SSD1307.pdf
|
||||
* All commands are prefixed with 0x80
|
||||
* Data packets are prefixed with 0x40
|
||||
*/
|
||||
I2C_CLASS::I2C_REG OLED_Setup_Array[] = {
|
||||
/**/
|
||||
{0x80, 0xAE, 0}, /*Display off*/
|
||||
{0x80, OLED_DIVIDER, 0}, /*Set display clock divide ratio / osc freq*/
|
||||
{0x80, 0x52, 0}, /*Divide ratios*/
|
||||
{0x80, 0xA8, 0}, /*Set Multiplex Ratio*/
|
||||
{0x80, OLED_HEIGHT - 1, 0}, /*Multiplex ratio adjusts how far down the matrix it scans*/
|
||||
{0x80, 0xC0, 0}, /*Set COM Scan direction*/
|
||||
{0x80, 0xD3, 0}, /*Set vertical Display offset*/
|
||||
{0x80, 0x00, 0}, /*0 Offset*/
|
||||
{0x80, 0x40, 0}, /*Set Display start line to 0*/
|
||||
{0x80, OLED_OFF, 0}, /* Display off */
|
||||
{0x80, OLED_DIVIDER, 0}, /* Set display clock divide ratio / osc freq */
|
||||
{0x80, 0x52, 0}, /* Divide ratios */
|
||||
{0x80, 0xA8, 0}, /* Set Multiplex Ratio */
|
||||
{0x80, OLED_HEIGHT - 1, 0}, /* Multiplex ratio adjusts how far down the matrix it scans */
|
||||
{0x80, 0xC0, 0}, /* Set COM Scan direction */
|
||||
{0x80, 0xD3, 0}, /* Set vertical Display offset */
|
||||
{0x80, 0x00, 0}, /* 0 Offset */
|
||||
{0x80, 0x40, 0}, /* Set Display start line to 0 */
|
||||
#ifdef OLED_SEGMENT_MAP_REVERSED
|
||||
{0x80, 0xA1, 0}, /*Set Segment remap to normal*/
|
||||
{0x80, 0xA1, 0}, /* Set Segment remap to normal */
|
||||
#else
|
||||
{0x80, 0xA0, 0}, /*Set Segment remap to normal*/
|
||||
{0x80, 0xA0, 0}, /* Set Segment remap to normal */
|
||||
#endif
|
||||
{0x80, 0x8D, 0}, /*Charge Pump*/
|
||||
{0x80, 0x14, 0}, /*Charge Pump settings*/
|
||||
{0x80, 0xDA, 0}, /*Set VCOM Pins hardware config*/
|
||||
{0x80, OLED_VCOM_LAYOUT, 0}, /*Combination 0x2 or 0x12 depending on OLED model*/
|
||||
{0x80, 0x81, 0}, /*Brightness*/
|
||||
{0x80, 0x00, 0}, /*^0*/
|
||||
{0x80, 0xD9, 0}, /*Set pre-charge period*/
|
||||
{0x80, 0xF1, 0}, /*Pre charge period*/
|
||||
{0x80, 0xDB, 0}, /*Adjust VCOMH regulator ouput*/
|
||||
{0x80, 0x30, 0}, /*VCOM level*/
|
||||
{0x80, 0xA4, 0}, /*Enable the display GDDR*/
|
||||
{0x80, 0XA6, 0}, /*Normal display*/
|
||||
{0x80, 0x20, 0}, /*Memory Mode*/
|
||||
{0x80, 0x00, 0}, /*Wrap memory*/
|
||||
{0x80, 0xAF, 0}, /*Display on*/
|
||||
{0x80, 0x8D, 0}, /* Charge Pump */
|
||||
{0x80, 0x14, 0}, /* Charge Pump settings */
|
||||
{0x80, 0xDA, 0}, /* Set VCOM Pins hardware config */
|
||||
{0x80, OLED_VCOM_LAYOUT, 0}, /* Combination 0x2 or 0x12 depending on OLED model */
|
||||
{0x80, 0x81, 0}, /* Brightness */
|
||||
{0x80, 0x00, 0}, /* ^0 */
|
||||
{0x80, 0xD9, 0}, /* Set pre-charge period */
|
||||
{0x80, 0xF1, 0}, /* Pre charge period */
|
||||
{0x80, 0xDB, 0}, /* Adjust VCOMH regulator ouput */
|
||||
{0x80, 0x30, 0}, /* VCOM level */
|
||||
{0x80, 0xA4, 0}, /* Enable the display GDDR */
|
||||
{0x80, 0xA6, 0}, /* Normal display */
|
||||
{0x80, 0x20, 0}, /* Memory Mode */
|
||||
{0x80, 0x00, 0}, /* Wrap memory */
|
||||
{0x80, OLED_ON, 0}, /* Display on */
|
||||
};
|
||||
// Setup based on the SSD1307 and modified for the SSD1306
|
||||
|
||||
@@ -115,6 +117,7 @@ static uint16_t lerp(uint16_t a, uint16_t b, uint16_t t) { return a + t * (b - a
|
||||
void OLED::initialize() {
|
||||
cursor_x = cursor_y = 0;
|
||||
inLeftHandedMode = false;
|
||||
|
||||
#ifdef OLED_128x32
|
||||
stripPointers[0] = &screenBuffer[FRAMEBUFFER_START];
|
||||
stripPointers[1] = &screenBuffer[FRAMEBUFFER_START + OLED_WIDTH];
|
||||
@@ -124,7 +127,8 @@ void OLED::initialize() {
|
||||
#else
|
||||
stripPointers[0] = &screenBuffer[FRAMEBUFFER_START];
|
||||
stripPointers[1] = &screenBuffer[FRAMEBUFFER_START + OLED_WIDTH];
|
||||
#endif
|
||||
|
||||
#endif /* OLED_128x32 */
|
||||
displayOffset = 0;
|
||||
memcpy(&screenBuffer[0], &REFRESH_COMMANDS[0], sizeof(REFRESH_COMMANDS));
|
||||
memcpy(&secondFrameBuffer[0], &REFRESH_COMMANDS[0], sizeof(REFRESH_COMMANDS));
|
||||
@@ -140,6 +144,7 @@ void OLED::initialize() {
|
||||
setDisplayState(DisplayState::ON);
|
||||
initDone = true;
|
||||
}
|
||||
|
||||
void OLED::setFramebuffer(uint8_t *buffer) {
|
||||
stripPointers[0] = &buffer[FRAMEBUFFER_START];
|
||||
stripPointers[1] = &buffer[FRAMEBUFFER_START + OLED_WIDTH];
|
||||
@@ -147,7 +152,7 @@ void OLED::setFramebuffer(uint8_t *buffer) {
|
||||
#ifdef OLED_128x32
|
||||
stripPointers[2] = &buffer[FRAMEBUFFER_START + (2 * OLED_WIDTH)];
|
||||
stripPointers[3] = &buffer[FRAMEBUFFER_START + (3 * OLED_WIDTH)];
|
||||
#endif
|
||||
#endif /* OLED_128x32 */
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -156,7 +161,6 @@ void OLED::setFramebuffer(uint8_t *buffer) {
|
||||
* Precursor is the command char that is used to select the table.
|
||||
*/
|
||||
void OLED::drawChar(const uint16_t charCode, const FontStyle fontStyle) {
|
||||
|
||||
const uint8_t *currentFont;
|
||||
static uint8_t fontWidth, fontHeight;
|
||||
uint16_t index;
|
||||
@@ -243,7 +247,7 @@ void OLED::maskScrollIndicatorOnOLED() {
|
||||
#ifdef OLED_128x32
|
||||
0x00,
|
||||
0x00,
|
||||
#endif
|
||||
#endif /* OLED_128x32 */
|
||||
// Clears two 8px strips
|
||||
0x00,
|
||||
0x00,
|
||||
@@ -266,7 +270,7 @@ void OLED::transitionSecondaryFramebuffer(bool forwardNavigation) {
|
||||
#ifdef OLED_128x32
|
||||
stripBackPointers[2] = &secondFrameBuffer[OLED_WIDTH * 2];
|
||||
stripBackPointers[3] = &secondFrameBuffer[OLED_WIDTH * 3];
|
||||
#endif
|
||||
#endif /* OLED_128x32 */
|
||||
|
||||
TickType_t totalDuration = TICKS_100MS * 5; // 500ms
|
||||
TickType_t duration = 0;
|
||||
@@ -297,17 +301,19 @@ void OLED::transitionSecondaryFramebuffer(bool forwardNavigation) {
|
||||
|
||||
memmove(&stripPointers[0][oldStart], &stripPointers[0][oldPrevious], OLED_WIDTH - progress);
|
||||
memmove(&stripPointers[1][oldStart], &stripPointers[1][oldPrevious], OLED_WIDTH - progress);
|
||||
|
||||
#ifdef OLED_128x32
|
||||
memmove(&stripPointers[2][oldStart], &stripPointers[2][oldPrevious], OLED_WIDTH - progress);
|
||||
memmove(&stripPointers[3][oldStart], &stripPointers[3][oldPrevious], OLED_WIDTH - progress);
|
||||
#endif
|
||||
#endif /* OLED_128x32 */
|
||||
|
||||
memmove(&stripPointers[0][newStart], &stripBackPointers[0][newEnd], progress);
|
||||
memmove(&stripPointers[1][newStart], &stripBackPointers[1][newEnd], progress);
|
||||
|
||||
#ifdef OLED_128x32
|
||||
memmove(&stripPointers[2][newStart], &stripBackPointers[2][newEnd], progress);
|
||||
memmove(&stripPointers[3][newStart], &stripBackPointers[3][newEnd], progress);
|
||||
#endif
|
||||
#endif /* OLED_128x32 */
|
||||
|
||||
refresh(); // Now refresh to write out the contents to the new page
|
||||
vTaskDelayUntil(&startDraw, TICKS_100MS / 7);
|
||||
@@ -367,7 +373,7 @@ void OLED::transitionScrollDown() {
|
||||
secondFrameBuffer[firstStripPos] = (secondFrameBuffer[firstStripPos] >> 1) | ((secondFrameBuffer[secondStripPos] & 0x01) << 7);
|
||||
// Finally on the bottom row; we shuffle it up ready
|
||||
secondFrameBuffer[secondStripPos] >>= 1;
|
||||
#endif
|
||||
#endif /* OLED_128x32 */
|
||||
}
|
||||
if (getButtonState() != BUTTON_NONE) {
|
||||
// Exit early, but have to transition whole buffer
|
||||
@@ -383,7 +389,7 @@ void OLED::transitionScrollDown() {
|
||||
void OLED::setRotation(bool leftHanded) {
|
||||
#ifdef OLED_FLIP
|
||||
leftHanded = !leftHanded;
|
||||
#endif
|
||||
#endif /* OLED_FLIP */
|
||||
if (inLeftHandedMode == leftHanded) {
|
||||
return;
|
||||
}
|
||||
@@ -399,7 +405,7 @@ void OLED::setRotation(bool leftHanded) {
|
||||
} else {
|
||||
OLED_Setup_Array[9].val = 0xA0;
|
||||
}
|
||||
#endif
|
||||
#endif /* OLED_SEGMENT_MAP_REVERSED */
|
||||
// send command struct again with changes
|
||||
if (leftHanded) {
|
||||
OLED_Setup_Array[5].val = 0xC8; // c1?
|
||||
@@ -475,6 +481,23 @@ void OLED::printWholeScreen(const char *string) {
|
||||
}
|
||||
}
|
||||
|
||||
// Print *F or *C - in font style of Small, Large (by default) or Extra based on input arg
|
||||
void OLED::printSymbolDeg(const FontStyle fontStyle) {
|
||||
switch (fontStyle) {
|
||||
case FontStyle::EXTRAS:
|
||||
// Picks *F or *C in ExtraFontChars[] from Font.h
|
||||
OLED::drawSymbol(getSettingValue(SettingsOptions::TemperatureInF) ? 0 : 1);
|
||||
break;
|
||||
case FontStyle::LARGE:
|
||||
OLED::print(getSettingValue(SettingsOptions::TemperatureInF) ? LargeSymbolDegF : LargeSymbolDegC, fontStyle);
|
||||
break;
|
||||
case FontStyle::SMALL:
|
||||
default:
|
||||
OLED::print(getSettingValue(SettingsOptions::TemperatureInF) ? SmallSymbolDegF : SmallSymbolDegC, fontStyle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline void stripLeaderZeros(char *buffer, uint8_t places) {
|
||||
// Removing the leading zero's by swapping them to SymbolSpace
|
||||
// Stop 1 short so that we dont blank entire number if its zero
|
||||
@@ -486,6 +509,7 @@ inline void stripLeaderZeros(char *buffer, uint8_t places) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OLED::drawHex(uint32_t x, FontStyle fontStyle, uint8_t digits) {
|
||||
// print number to hex
|
||||
for (uint_fast8_t i = 0; i < digits; i++) {
|
||||
@@ -493,6 +517,7 @@ void OLED::drawHex(uint32_t x, FontStyle fontStyle, uint8_t digits) {
|
||||
drawChar(value + 2, fontStyle);
|
||||
}
|
||||
}
|
||||
|
||||
// maximum places is 5
|
||||
void OLED::printNumber(uint16_t number, uint8_t places, FontStyle fontStyle, bool noLeaderZeros) {
|
||||
char buffer[7] = {0};
|
||||
@@ -522,8 +547,9 @@ void OLED::printNumber(uint16_t number, uint8_t places, FontStyle fontStyle, boo
|
||||
}
|
||||
|
||||
buffer[0] = 2 + number % 10;
|
||||
if (noLeaderZeros)
|
||||
if (noLeaderZeros) {
|
||||
stripLeaderZeros(buffer, places);
|
||||
}
|
||||
print(buffer, fontStyle);
|
||||
}
|
||||
|
||||
@@ -549,10 +575,12 @@ void OLED::drawSymbol(uint8_t symbolID) {
|
||||
// Draw an area, but y must be aligned on 0/8 offset
|
||||
void OLED::drawArea(int16_t x, int8_t y, uint8_t wide, uint8_t height, const uint8_t *ptr) {
|
||||
// Splat this from x->x+wide in two strides
|
||||
if (x <= -wide)
|
||||
if (x <= -wide) {
|
||||
return; // cutoffleft
|
||||
if (x > 96)
|
||||
}
|
||||
if (x > 96) {
|
||||
return; // cutoff right
|
||||
}
|
||||
|
||||
uint8_t visibleStart = 0;
|
||||
uint8_t visibleEnd = wide;
|
||||
@@ -584,10 +612,12 @@ void OLED::drawArea(int16_t x, int8_t y, uint8_t wide, uint8_t height, const uin
|
||||
// For data which has octets swapped in a 16-bit word.
|
||||
void OLED::drawAreaSwapped(int16_t x, int8_t y, uint8_t wide, uint8_t height, const uint8_t *ptr) {
|
||||
// Splat this from x->x+wide in two strides
|
||||
if (x <= -wide)
|
||||
if (x <= -wide) {
|
||||
return; // cutoffleft
|
||||
if (x > 96)
|
||||
}
|
||||
if (x > 96) {
|
||||
return; // cutoff right
|
||||
}
|
||||
|
||||
uint8_t visibleStart = 0;
|
||||
uint8_t visibleEnd = wide;
|
||||
@@ -618,10 +648,12 @@ void OLED::drawAreaSwapped(int16_t x, int8_t y, uint8_t wide, uint8_t height, co
|
||||
|
||||
void OLED::fillArea(int16_t x, int8_t y, uint8_t wide, uint8_t height, const uint8_t value) {
|
||||
// Splat this from x->x+wide in two strides
|
||||
if (x <= -wide)
|
||||
if (x <= -wide) {
|
||||
return; // cutoffleft
|
||||
if (x > 96)
|
||||
}
|
||||
if (x > 96) {
|
||||
return; // cutoff right
|
||||
}
|
||||
|
||||
uint8_t visibleStart = 0;
|
||||
uint8_t visibleEnd = wide;
|
||||
@@ -657,30 +689,37 @@ void OLED::drawFilledRect(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, bool c
|
||||
uint8_t mask = 0xFF;
|
||||
if (y0) {
|
||||
mask = mask << (y0 % 8);
|
||||
for (uint8_t col = x0; col < x1; col++)
|
||||
if (clear)
|
||||
for (uint8_t col = x0; col < x1; col++) {
|
||||
if (clear) {
|
||||
stripPointers[0][(y0 / 8) * 96 + col] &= ~mask;
|
||||
else
|
||||
} else {
|
||||
stripPointers[0][(y0 / 8) * 96 + col] |= mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Next loop down the line the total number of solids
|
||||
if (y0 / 8 != y1 / 8)
|
||||
for (uint8_t col = x0; col < x1; col++)
|
||||
if (y0 / 8 != y1 / 8) {
|
||||
for (uint8_t col = x0; col < x1; col++) {
|
||||
for (uint8_t r = (y0 / 8); r < (y1 / 8); r++) {
|
||||
// This gives us the row index r
|
||||
if (clear)
|
||||
if (clear) {
|
||||
stripPointers[0][(r * 96) + col] = 0;
|
||||
else
|
||||
} else {
|
||||
stripPointers[0][(r * 96) + col] = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finally draw the tail
|
||||
mask = ~(mask << (y1 % 8));
|
||||
for (uint8_t col = x0; col < x1; col++)
|
||||
if (clear)
|
||||
for (uint8_t col = x0; col < x1; col++) {
|
||||
if (clear) {
|
||||
stripPointers[0][(y1 / 8) * 96 + col] &= ~mask;
|
||||
else
|
||||
} else {
|
||||
stripPointers[0][(y1 / 8) * 96 + col] |= mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OLED::drawHeatSymbol(uint8_t state) {
|
||||
|
||||
@@ -36,7 +36,9 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#define DEVICEADDR_OLED (0x3c << 1)
|
||||
|
||||
#ifdef OLED_128x32
|
||||
|
||||
#define OLED_WIDTH 128
|
||||
#define OLED_HEIGHT 32
|
||||
#define OLED_GRAM_START 0x00 // Should be 0x00 when we have full width
|
||||
@@ -44,22 +46,28 @@ extern "C" {
|
||||
#define OLED_GRAM_START_FLIP 0
|
||||
#define OLED_GRAM_END_FLIP 0x7F
|
||||
|
||||
#define OLED_VCOM_LAYOUT 0x12
|
||||
#define OLED_VCOM_LAYOUT 0x12
|
||||
#define OLED_SEGMENT_MAP_REVERSED
|
||||
#define OLED_DIVIDER 0xD3
|
||||
#else
|
||||
#define OLED_WIDTH 96
|
||||
#define OLED_HEIGHT 16
|
||||
#define OLED_VCOM_LAYOUT 0x02
|
||||
#define OLED_DIVIDER 0xD3
|
||||
|
||||
#else
|
||||
|
||||
#define OLED_WIDTH 96
|
||||
#define OLED_HEIGHT 16
|
||||
#define OLED_GRAM_START 0x20
|
||||
#define OLED_GRAM_END 0x7F
|
||||
#define OLED_GRAM_START_FLIP 0
|
||||
#define OLED_GRAM_END_FLIP 95
|
||||
#define OLED_DIVIDER 0xD5
|
||||
#define OLED_SEGMENT_MAP 0xA0
|
||||
|
||||
#endif
|
||||
#define OLED_VCOM_LAYOUT 0x02
|
||||
#define OLED_SEGMENT_MAP 0xA0
|
||||
#define OLED_DIVIDER 0xD5
|
||||
|
||||
#endif /* OLED_128x32 */
|
||||
|
||||
#define OLED_ON 0xAF
|
||||
#define OLED_OFF 0xAE
|
||||
|
||||
#define FRAMEBUFFER_START 17
|
||||
|
||||
enum class FontStyle {
|
||||
@@ -88,27 +96,31 @@ public:
|
||||
static void setDisplayState(DisplayState state) {
|
||||
if (state != displayState) {
|
||||
displayState = state;
|
||||
screenBuffer[1] = (state == ON) ? 0xAF : 0xAE;
|
||||
screenBuffer[1] = (state == ON) ? OLED_ON : OLED_OFF;
|
||||
// Dump the screen state change out _now_
|
||||
I2C_CLASS::Transmit(DEVICEADDR_OLED, screenBuffer, FRAMEBUFFER_START - 1);
|
||||
osDelay(TICKS_10MS);
|
||||
}
|
||||
}
|
||||
|
||||
static void setRotation(bool leftHanded); // Set the rotation for the screen
|
||||
// Set the rotation for the screen
|
||||
static void setRotation(bool leftHanded);
|
||||
// Get the current rotation of the LCD
|
||||
static bool getRotation() {
|
||||
#ifdef OLED_FLIP
|
||||
return !inLeftHandedMode;
|
||||
#else
|
||||
return inLeftHandedMode;
|
||||
#endif
|
||||
#endif /* OLED_FLIP */
|
||||
}
|
||||
static void setBrightness(uint8_t contrast);
|
||||
static void setInverseDisplay(bool inverted);
|
||||
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
|
||||
// Draw a string to the current location, with selected font; optionally - with MAX length only
|
||||
static void print(const char *string, FontStyle fontStyle, uint8_t length = 255);
|
||||
static void printWholeScreen(const char *string);
|
||||
// Print *F or *C - in font style of Small, Large (by default) or Extra based on input arg
|
||||
static void printSymbolDeg(FontStyle fontStyle = FontStyle::LARGE);
|
||||
// Set the cursor location by pixels
|
||||
static void setCursor(int16_t x, int16_t y) {
|
||||
cursor_x = x;
|
||||
|
||||
@@ -44,10 +44,11 @@ uint32_t TipThermoModel::convertTipRawADCTouV(uint16_t rawADC, bool ski
|
||||
|
||||
if (getSettingValue(SettingsOptions::CalibrationOffset) && skipCalOffset == false) {
|
||||
// Remove uV tipOffset
|
||||
if (valueuV > getSettingValue(SettingsOptions::CalibrationOffset))
|
||||
if (valueuV > getSettingValue(SettingsOptions::CalibrationOffset)) {
|
||||
valueuV -= getSettingValue(SettingsOptions::CalibrationOffset);
|
||||
else
|
||||
} else {
|
||||
valueuV = 0;
|
||||
}
|
||||
}
|
||||
lastuv = valueuV;
|
||||
return valueuV;
|
||||
@@ -78,8 +79,9 @@ uint32_t TipThermoModel::getTipInC(bool sampleNow) {
|
||||
// I found a number that doesn't unbalance the existing PID, causing overshoot.
|
||||
// This could be tuned in concert with PID parameters...
|
||||
|
||||
if (currentTipTempInC < 0)
|
||||
if (currentTipTempInC < 0) {
|
||||
return 0;
|
||||
}
|
||||
return currentTipTempInC;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ void USBPowerDelivery::IRQOccured() { pe.IRQOccured(); }
|
||||
bool USBPowerDelivery::negotiationHasWorked() { return pe.pdHasNegotiated(); }
|
||||
uint8_t USBPowerDelivery::getStateNumber() { return pe.currentStateCode(true); }
|
||||
void USBPowerDelivery::step() {
|
||||
while (pe.thread()) {}
|
||||
while (pe.thread()) {}
|
||||
}
|
||||
|
||||
void USBPowerDelivery::PPSTimerCallback() { pe.TimersCallback(); }
|
||||
@@ -93,18 +93,22 @@ uint32_t *USBPowerDelivery::getLastSeenCapabilities() { return lastCapabilities;
|
||||
static unsigned int sqrtI(unsigned long sqrtArg) {
|
||||
unsigned int answer, x;
|
||||
unsigned long temp;
|
||||
if (sqrtArg == 0)
|
||||
if (sqrtArg == 0) {
|
||||
return 0; // undefined result
|
||||
if (sqrtArg == 1)
|
||||
return 1; // identity
|
||||
}
|
||||
if (sqrtArg == 1) {
|
||||
return 1; // identity
|
||||
}
|
||||
answer = 0; // integer square root
|
||||
for (x = 0x8000; x > 0; x = x >> 1) { // 16 bit shift
|
||||
answer |= x; // possible bit in root
|
||||
temp = answer * answer; //
|
||||
if (temp == sqrtArg)
|
||||
if (temp == sqrtArg) {
|
||||
break; // exact, found it
|
||||
if (temp > sqrtArg)
|
||||
}
|
||||
if (temp > sqrtArg) {
|
||||
answer ^= x; // too large, reverse bit
|
||||
}
|
||||
}
|
||||
return answer; // approximate root
|
||||
}
|
||||
@@ -225,7 +229,6 @@ bool EPREvaluateCapabilityFunc(const epr_pd_msg *capabilities, pd_msg *request)
|
||||
request->hdr = PD_MSGTYPE_EPR_REQUEST | PD_NUMOBJ(2);
|
||||
request->obj[1] = lastCapabilities[bestIndex]; // Copy PDO into slot 2
|
||||
|
||||
|
||||
if (bestIsAVS) {
|
||||
request->obj[0] = PD_RDO_PROG_CURRENT_SET(PD_CA2PAI(bestIndexCurrent)) | PD_RDO_PROG_VOLTAGE_SET(PD_MV2APS(bestIndexVoltage));
|
||||
} else if (bestIsPPS) {
|
||||
|
||||
@@ -86,6 +86,12 @@ typedef enum {
|
||||
ZERO = 3, // Power on only (No heat Mode)
|
||||
} autoStartMode_t;
|
||||
|
||||
typedef enum {
|
||||
RIGHT = 0, // Right-hand screen orientation
|
||||
LEFT = 1, // Left-hand screen orientation
|
||||
AUTO = 2, // Automatic screen orientation based on accel.data if presented
|
||||
} orientationMode_t;
|
||||
|
||||
// Settings wide operations
|
||||
void saveSettings();
|
||||
bool loadSettings();
|
||||
|
||||
@@ -107,7 +107,7 @@ enum class SettingsItemIndex : uint8_t {
|
||||
};
|
||||
|
||||
struct TranslationIndexTable {
|
||||
uint16_t CJCCalibrationDone;
|
||||
uint16_t CalibrationDone;
|
||||
uint16_t ResetOKMessage;
|
||||
uint16_t SettingsResetMessage;
|
||||
uint16_t NoAccelerometerMessage;
|
||||
@@ -116,6 +116,7 @@ struct TranslationIndexTable {
|
||||
uint16_t UnlockingKeysString;
|
||||
uint16_t WarningKeysLockedString;
|
||||
uint16_t WarningThermalRunaway;
|
||||
uint16_t WarningTipShorted;
|
||||
|
||||
uint16_t SettingsCalibrationWarning;
|
||||
uint16_t CJCCalibrating;
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
#ifndef GUI_HPP_
|
||||
#define GUI_HPP_
|
||||
#include "BSP.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "Settings.h"
|
||||
#include "Translation.h"
|
||||
|
||||
|
||||
#define PRESS_ACCEL_STEP (TICKS_100MS / 3)
|
||||
#define PRESS_ACCEL_INTERVAL_MIN TICKS_100MS
|
||||
#define PRESS_ACCEL_INTERVAL_MAX (TICKS_100MS * 3)
|
||||
@@ -35,7 +37,7 @@ typedef struct {
|
||||
} menuitem;
|
||||
|
||||
void enterSettingsMenu();
|
||||
void warnUser(const char *warning, const int timeout);
|
||||
void warnUser(const char *warning, const TickType_t timeout);
|
||||
extern const menuitem rootSettingsMenu[];
|
||||
|
||||
#endif /* GUI_HPP_ */
|
||||
|
||||
@@ -20,8 +20,7 @@ void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackTyp
|
||||
/* place for user code */
|
||||
}
|
||||
|
||||
void vApplicationStackOverflowHook( TaskHandle_t xTask,
|
||||
char * pcTaskName ) {
|
||||
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) {
|
||||
(void)xTask;
|
||||
(void)pcTaskName;
|
||||
|
||||
|
||||
@@ -11,29 +11,34 @@
|
||||
#include "cmsis_os.h"
|
||||
#include "configuration.h"
|
||||
#include "stdint.h"
|
||||
|
||||
enum QCState {
|
||||
NOT_STARTED = 0, // Have not checked
|
||||
QC_3 = 1,
|
||||
QC_2 = 2,
|
||||
NO_QC = 3,
|
||||
|
||||
};
|
||||
|
||||
void QC_Seek9V() {
|
||||
QC_DNegZero_Six();
|
||||
QC_DPlusThree_Three();
|
||||
}
|
||||
|
||||
void QC_Seek12V() {
|
||||
QC_DNegZero_Six();
|
||||
QC_DPlusZero_Six();
|
||||
}
|
||||
|
||||
void QC_Seek20V() {
|
||||
QC_DNegThree_Three();
|
||||
QC_DPlusThree_Three();
|
||||
}
|
||||
|
||||
void QC_SeekContMode() {
|
||||
QC_DNegThree_Three();
|
||||
QC_DPlusZero_Six();
|
||||
}
|
||||
|
||||
void QC_SeekContPlus() {
|
||||
QC_SeekContMode();
|
||||
osDelay(30);
|
||||
@@ -41,6 +46,7 @@ void QC_SeekContPlus() {
|
||||
osDelay(10);
|
||||
QC_SeekContMode();
|
||||
}
|
||||
|
||||
void QC_SeekContNeg() {
|
||||
QC_SeekContMode();
|
||||
osDelay(30);
|
||||
@@ -48,17 +54,21 @@ void QC_SeekContNeg() {
|
||||
osDelay(10);
|
||||
QC_SeekContMode();
|
||||
}
|
||||
|
||||
QCState QCMode = QCState::NOT_STARTED;
|
||||
uint8_t QCTries = 0;
|
||||
void seekQC(int16_t Vx10, uint16_t divisor) {
|
||||
if (QCMode == QCState::NOT_STARTED)
|
||||
if (QCMode == QCState::NOT_STARTED) {
|
||||
startQC(divisor);
|
||||
}
|
||||
|
||||
if (Vx10 < 40) // Bail out if less than 4V
|
||||
if (Vx10 < 40) { // Bail out if less than 4V
|
||||
return;
|
||||
}
|
||||
|
||||
if (xTaskGetTickCount() < TICKS_SECOND)
|
||||
if (xTaskGetTickCount() < TICKS_SECOND) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Seek the QC to the Voltage given if this adapter supports continuous mode
|
||||
// try and step towards the wanted value
|
||||
@@ -87,8 +97,9 @@ void seekQC(int16_t Vx10, uint16_t divisor) {
|
||||
// Re-measure
|
||||
/* Disabled due to nothing to test and code space of around 1k*/
|
||||
steps = vStart - getInputVoltageX10(divisor, 0);
|
||||
if (steps < 0)
|
||||
if (steps < 0) {
|
||||
steps = -steps;
|
||||
}
|
||||
if (steps > 4) {
|
||||
// No continuous mode, so QC2
|
||||
QCMode = QCState::QC_2;
|
||||
@@ -104,8 +115,9 @@ void seekQC(int16_t Vx10, uint16_t divisor) {
|
||||
QC_Seek9V();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* ENABLE_QC2 */
|
||||
}
|
||||
|
||||
// Must be called after FreeRToS Starts
|
||||
void startQC(uint16_t divisor) {
|
||||
// Pre check that the input could be >5V already, and if so, dont both
|
||||
@@ -143,7 +155,9 @@ void startQC(uint16_t divisor) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QC_DM_No_PullDown();
|
||||
|
||||
if (enteredQC) {
|
||||
// We have a QC capable charger
|
||||
QC_Seek9V();
|
||||
@@ -161,7 +175,6 @@ void startQC(uint16_t divisor) {
|
||||
}
|
||||
QCMode = QCState::NOT_STARTED;
|
||||
QCTries++;
|
||||
|
||||
} else {
|
||||
// no QC
|
||||
QCTries++;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user