Compare commits
83 Commits
v2.22-rc
...
gui-dispat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17bcc85e98 | ||
|
|
fd285b3364 | ||
|
|
9385758593 | ||
|
|
296aecab00 | ||
|
|
1396363eaa | ||
|
|
964d37a8e8 | ||
|
|
a80db0af5a | ||
|
|
627d8f8be1 | ||
|
|
86fed6bfbe | ||
|
|
bf00e1bc58 | ||
|
|
2196e76e22 | ||
|
|
6bb0b015c8 | ||
|
|
3627338b8d | ||
|
|
33e1a7756f | ||
|
|
886c956c3c | ||
|
|
1e2d9676c9 | ||
|
|
ea35b264ab | ||
|
|
2d8378c39d | ||
|
|
1a936b84f2 | ||
|
|
00711f6e4c | ||
|
|
bf962ce51f | ||
|
|
76902ee65f | ||
|
|
c85fa4affa | ||
|
|
3347bc6bde | ||
|
|
26bb81ce58 | ||
|
|
3a725aa3c1 | ||
|
|
d6c5b0214b | ||
|
|
7e13686276 | ||
|
|
63db049311 | ||
|
|
a9da730894 | ||
|
|
4d1cfcf2e6 | ||
|
|
5b86637e48 | ||
|
|
d3a193096e | ||
|
|
b38a5396f0 | ||
|
|
5120235e2e | ||
|
|
6002cc3270 | ||
|
|
553f5fd273 | ||
|
|
ae5b9e9717 | ||
|
|
3888bdc04a | ||
|
|
0ec45f29a4 | ||
|
|
5303d27f96 | ||
|
|
c308fe8cc2 | ||
|
|
9c7ad43a76 | ||
|
|
8c582e6cb0 | ||
|
|
4a8f483d30 | ||
|
|
b489601883 | ||
|
|
e56060ab4a | ||
|
|
c0a5e244b9 | ||
|
|
f99aed5785 | ||
|
|
64ccbd4334 | ||
|
|
0a5b84fea9 | ||
|
|
c2229f096b | ||
|
|
53bb8355f8 | ||
|
|
95160b7afd | ||
|
|
5754622fea | ||
|
|
2b0bd00603 | ||
|
|
20e085487e | ||
|
|
4cb47cf1a2 | ||
|
|
33439aaa22 | ||
|
|
6111b58e04 | ||
|
|
d6286b9e2b | ||
|
|
f69c37c4aa | ||
|
|
230e42b614 | ||
|
|
caedce0300 | ||
|
|
748ab1c354 | ||
|
|
33a2958203 | ||
|
|
8430a114fa | ||
|
|
9cc0a56057 | ||
|
|
db3d8a2de0 | ||
|
|
4460782dd4 | ||
|
|
d1e03c34be | ||
|
|
b493f4d0e1 | ||
|
|
fb48ff8b91 | ||
|
|
3f8f60f4c7 | ||
|
|
130e73c1fe | ||
|
|
26197f6ed7 | ||
|
|
d5035bb956 | ||
|
|
c0f1c35ba5 | ||
|
|
477fdc489c | ||
|
|
4f2fb2083d | ||
|
|
15ab87f3bc | ||
|
|
8b90666f30 | ||
|
|
c03e1842aa |
2
.github/workflows/docs.yml
vendored
2
.github/workflows/docs.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@v4
|
||||
|
||||
26
.github/workflows/push.yml
vendored
26
.github/workflows/push.yml
vendored
@@ -1,6 +1,16 @@
|
||||
name: CI
|
||||
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- dev
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- dev
|
||||
- main
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -21,7 +31,7 @@ jobs:
|
||||
- name: Install dependencies (python)
|
||||
run: python3 -m pip install bdflib
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
@@ -74,7 +84,7 @@ jobs:
|
||||
- name: Install dependencies (python)
|
||||
run: python3 -m pip install bdflib
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
@@ -121,7 +131,7 @@ jobs:
|
||||
- name: Install dependencies (apk)
|
||||
run: apk add --no-cache python3 py3-pip make git bash findutils gcc musl-dev
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
@@ -144,7 +154,7 @@ jobs:
|
||||
- name: Install dependencies (apk)
|
||||
run: apk add --no-cache make git diffutils findutils clang-extra-tools bash
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
@@ -161,7 +171,7 @@ jobs:
|
||||
- name: Install dependencies (apk)
|
||||
run: apk add --no-cache python3 py3-pip make git black
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
@@ -179,7 +189,7 @@ jobs:
|
||||
name: check_shell
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: shellcheck
|
||||
uses: reviewdog/action-shellcheck@v1
|
||||
with:
|
||||
@@ -198,7 +208,7 @@ jobs:
|
||||
- name: Install dependencies (apk)
|
||||
run: apk add --no-cache git
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ There is a static line on top which is presented on every sub-screen and reflect
|
||||
- T - git-related release **t**ag but version is not vXX.YY !
|
||||
- D - git-related **d**ev branch
|
||||
- B - git-related custom **b**ranch
|
||||
- E - git-related from d**e**tached commit
|
||||
- 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)
|
||||
|
||||
@@ -1,6 +1,36 @@
|
||||
# Version Changes
|
||||
|
||||
## V2.19
|
||||
|
||||
# V2.21
|
||||
|
||||
### Features & changes
|
||||
|
||||
- Bluetooth Low Energy support for PinecilV2
|
||||
- Large cleanup of translation files; and refactor of how we handle fonts for translations
|
||||
- Fixes for I2C corruption on PinecilV2
|
||||
- Option for using adjustable profiles on USB-PD or not
|
||||
- Cleanups and improvements to the generated [documents website](https://ralim.github.io/IronOS)
|
||||
|
||||
### PinecilV2 notes
|
||||
|
||||
For Pinecil V2 users blisp is currently my recommended CLI tool for updating the device. It is built for all main OS's automatically. This does not apply to V1 devices. If your iron came with a blue grip, its a V1 and update the same as always. If your device came with a green silicone grip its a V2 device.
|
||||
|
||||
Alternatively you can use Spagett1's PineFlash tool that should provide a GUI interface for PinecilV1 & PinecilV2.
|
||||
|
||||
For a small number of V2 Pinecil devices there appears to be an interference issue between the Bluetooth Low Energy and some devices; more information here. If this occurs to you, please let us know in the issue and rollback to 2.20 for now.
|
||||
|
||||
|
||||
# V2.20
|
||||
|
||||
- First "full" release for PinecilV2
|
||||
- Loots of documentation updates
|
||||
- Documentation is [now nicely readable as a site](https://ralim.github.io/IronOS/GettingStarted)
|
||||
- A fair collection of bugfixes for PinecilV2
|
||||
- Cold Junction Calibration was reworked and now occurs _at next boot_ to make it easier to perform when the device is cold
|
||||
|
||||
|
||||
# V2.19
|
||||
|
||||
- Bug-fix Infinite Boot Logo
|
||||
- Shutdown settings for MHP30
|
||||
- Accelerometer sensitivity for MHP30
|
||||
@@ -9,7 +39,9 @@
|
||||
- Updated translations
|
||||
- Improved documents, added features table
|
||||
|
||||
## V2.18
|
||||
|
||||
# V2.18
|
||||
|
||||
- Support for animated bootup logo's
|
||||
- Bootup logo's moved to their own IronOS-Meta repo
|
||||
- New Vietnamese translation (limited due to screen size)
|
||||
@@ -17,8 +49,11 @@
|
||||
- Updated translations
|
||||
- Better Instructions/documents
|
||||
|
||||
## V2.17
|
||||
### Big changes
|
||||
|
||||
# V2.17
|
||||
|
||||
### Features & changes
|
||||
|
||||
- Indicate status of VBus for modding Pinecil (debug menu)
|
||||
- Better hall effect sensor sensitivity adjustment (larger range with more steps)
|
||||
- Temperature increment will "round" to nearest multiple of increase amount
|
||||
@@ -32,7 +67,9 @@
|
||||
- Fixed automatic orientation for newer TS80P's with the SC7 accelerometer
|
||||
- User interface slight changes
|
||||
- New `metadata.zip` file to allow the Pine Updater to automatically fetch information on releases
|
||||
|
||||
### Notes
|
||||
|
||||
- VBus mod detection may not play well with all PPS chargers. If your iron reboots when you view this in the debug menu its not a fault. ([#1226](https://github.com/Ralim/IronOS/issues/1226))
|
||||
- `metadata.zip` is only designed for use by automatic software, ignore it for normal use
|
||||
- More details on Pinecil VBus mod coming via other channels.
|
||||
@@ -41,39 +78,38 @@
|
||||
- -> Release has been updated to build `e065be3` after one bug with the BMA223 was found.
|
||||
|
||||
|
||||
## V2.16
|
||||
# V2.16
|
||||
|
||||
* Overhaul of the Timer+ADC setup with help from @sandmanRO
|
||||
* Overhaul of the PID with help from @sandmanRO
|
||||
* Settings _should_ now upgrade in place to future versions, with resets only happening to new/changed settings
|
||||
* Shows error if tip runaway (failed temperature sensor) is detected
|
||||
* USB-PD now has a timeout, to allow forcing QC3 negotiation to start faster
|
||||
* QC3 Voltages are now adjustable to user desired setpoint
|
||||
* Added a small tolerance to allow "overvoltage" on QC3 above unit specifications.
|
||||
* * Please note: Doing this is entirely at your own risk!
|
||||
* New Advanced view that is much nicer to use and a very good daily driver option from @Mel-kior
|
||||
* OLED brightness and contrast thanks to @alvinhochun
|
||||
* Scrollbar is fixed so it doesnt jump around when menus are shown/hidden
|
||||
* Moved to `.dfu` files from `.bin` to make flashing commands easier
|
||||
* Every language had translation updates I believe
|
||||
* Romanian language added
|
||||
- Overhaul of the Timer+ADC setup with help from @sandmanRO
|
||||
- Overhaul of the PID with help from @sandmanRO
|
||||
- Settings _should_ now upgrade in place to future versions, with resets only happening to new/changed settings
|
||||
- Shows error if tip runaway (failed temperature sensor) is detected
|
||||
- USB-PD now has a timeout, to allow forcing QC3 negotiation to start faster
|
||||
- QC3 Voltages are now adjustable to user desired setpoint
|
||||
- Added a small tolerance to allow "overvoltage" on QC3 above unit specifications.
|
||||
- Please note: Doing this is entirely at your own risk!
|
||||
- New Advanced view that is much nicer to use and a very good daily driver option from @Mel-kior
|
||||
- OLED brightness and contrast thanks to @alvinhochun
|
||||
- Scrollbar is fixed so it doesnt jump around when menus are shown/hidden
|
||||
- Moved to `.dfu` files from `.bin` to make flashing commands easier
|
||||
- Every language had translation updates I believe
|
||||
- Romanian language added
|
||||
|
||||
|
||||
## V2.15
|
||||
# V2.15
|
||||
|
||||
### Features & changes
|
||||
|
||||
## Feature upgrades:
|
||||
- MHP30 support
|
||||
- Multi-lingual firmware combinations now exist for Pinecil
|
||||
- More fine grained voltage controlled options
|
||||
- USB-PD improvements (version one and two)
|
||||
- More configuration options for power pulse
|
||||
- All font / character encoding has been very reworked
|
||||
- More translation updates than one can count
|
||||
- More languages 😱
|
||||
|
||||
* MHP30 support
|
||||
* Multi-lingual firmware combinations now exist for Pinecil
|
||||
* More fine grained voltage controlled options
|
||||
* USB-PD improvements (version one and two)
|
||||
* More configuration options for power pulse
|
||||
* All font / character encoding has been very reworked
|
||||
* More translation updates than one can count
|
||||
* More languages 😱
|
||||
|
||||
### MHP30
|
||||
### MHP30 support
|
||||
|
||||
The MHP30 is a small reflow station from Miniware.
|
||||
Thanks to a massive amount of help from @g3gg0 this firmware brings the beginnings of support for this unit.
|
||||
@@ -84,7 +120,8 @@ Programs the same as any one Miniware unit using drag and drop.
|
||||
|
||||
The flood doors are now open for feature requests for this unit :)
|
||||
|
||||
## V2.14
|
||||
|
||||
# V2.14
|
||||
|
||||
- Fixing auto rotation bug in the LIS accelerometer in the TS80/TS80P
|
||||
- Adds support for two new accelerometers
|
||||
@@ -101,7 +138,8 @@ The flood doors are now open for feature requests for this unit :)
|
||||
- Cleanup the folder name of the source code #800
|
||||
- clang-format spec setup #801
|
||||
|
||||
## V2.13
|
||||
|
||||
# V2.13
|
||||
|
||||
- First _official_ Pinecil release
|
||||
- All of the wire for Pinecil releases added
|
||||
@@ -118,7 +156,8 @@ The flood doors are now open for feature requests for this unit :)
|
||||
- Fixed bug with accelerometer model on Pinecil
|
||||
- Rework of all of the temperature curves for better accuracy
|
||||
|
||||
## V2.12
|
||||
|
||||
# V2.12
|
||||
|
||||
- Only released as pre-release
|
||||
- [TS80P] Improvements to the PD negotiation to handle a few more adapters cleanly
|
||||
@@ -126,36 +165,42 @@ The flood doors are now open for feature requests for this unit :)
|
||||
- Clean up the menu (removed both enables and settings, so that you can turn things off easier)
|
||||
- Removing the very old single line menu style.
|
||||
|
||||
## V2.11
|
||||
|
||||
# V2.11
|
||||
|
||||
- First TS80P support
|
||||
- Added in a USB-PD driver stack for the FUSB302
|
||||
- Fixed some graphical glitches
|
||||
|
||||
## V2.10
|
||||
|
||||
# V2.10
|
||||
|
||||
- GUI polish (animations and scroll bars)
|
||||
- Power pulse to keep power supplies alive
|
||||
- Adjustable tip response gain
|
||||
|
||||
## V2.09
|
||||
|
||||
# V2.09
|
||||
|
||||
- Adjustable steps in temperature adjustment
|
||||
- Git hash now in build string
|
||||
- Adjustable language to set if US units are available or not
|
||||
- Some minor QC3 improvements
|
||||
|
||||
## V2.08
|
||||
|
||||
# V2.08
|
||||
|
||||
- Fixes auto start in sleep mode
|
||||
- Power limiters
|
||||
|
||||
## V2.07
|
||||
|
||||
# V2.07
|
||||
|
||||
- QC fixes
|
||||
- Cosmetic fixes for leading 0's
|
||||
|
||||
## V2.06
|
||||
|
||||
# V2.06
|
||||
|
||||
- Warning on settings reset
|
||||
- Temp temp re-write
|
||||
@@ -163,27 +208,33 @@ The flood doors are now open for feature requests for this unit :)
|
||||
- Hide some leading 0's
|
||||
- Menu timeouts
|
||||
|
||||
## V2.05
|
||||
|
||||
# V2.05
|
||||
|
||||
- Language updates
|
||||
|
||||
## V2.04
|
||||
|
||||
# V2.04
|
||||
|
||||
- GUI updates
|
||||
|
||||
## V2.03
|
||||
|
||||
# V2.03
|
||||
|
||||
- Support for new accelerometers
|
||||
|
||||
## V2.02
|
||||
|
||||
# V2.02
|
||||
|
||||
- Adds small font
|
||||
|
||||
## V2.01
|
||||
|
||||
# V2.01
|
||||
|
||||
- Newer settings menu
|
||||
|
||||
## V2.00
|
||||
|
||||
# V2.00
|
||||
|
||||
- Complete re-write of the low layer system to use the STM32 HAL for easier development
|
||||
- This allowed easier setup for the new ADC auto measuring system
|
||||
@@ -193,80 +244,96 @@ The flood doors are now open for feature requests for this unit :)
|
||||
- Added detailed screen views
|
||||
- Added smaller font for said screen views
|
||||
|
||||
## V1.17
|
||||
|
||||
# V1.17
|
||||
|
||||
- Added blinking cooldown display
|
||||
- Allowed smaller sleep timeout values
|
||||
- New font!
|
||||
- Automatic startup option
|
||||
|
||||
## V1.16
|
||||
|
||||
# V1.16
|
||||
|
||||
- Added automatic rotation support
|
||||
- Added power display graph
|
||||
|
||||
## V1.15
|
||||
|
||||
# V1.15
|
||||
|
||||
- Added support for a custom bootup logo to be programmed via the DFU bootloader
|
||||
|
||||
## V1.14
|
||||
|
||||
# V1.14
|
||||
|
||||
- Changed input voltage cutoff to be based on cell count rather than voltage
|
||||
|
||||
## V1.13
|
||||
|
||||
# V1.13
|
||||
|
||||
- Swapped buttons for menu to prevent accidentally changing first menu item
|
||||
- Added auto key repeat
|
||||
|
||||
## V1.12
|
||||
|
||||
# V1.12
|
||||
|
||||
- Increases sensitivity options to be 1\*9 with 0 off state
|
||||
- Fixes issue where going from COOL \*> soldering can leave screen off
|
||||
|
||||
## V1.11
|
||||
|
||||
# V1.11
|
||||
|
||||
- Boost mode
|
||||
- Change sensitivity options to be 1\*8
|
||||
|
||||
## V1.10
|
||||
|
||||
# V1.10
|
||||
|
||||
- Adds help text to settings
|
||||
- Improves settings for the display update rate
|
||||
|
||||
## V1.09
|
||||
|
||||
# V1.09
|
||||
|
||||
- Adds display modes, for slowing down or simplifying the display
|
||||
|
||||
## V1.08
|
||||
|
||||
# V1.08
|
||||
|
||||
- Fix settings menu not showing flip display
|
||||
|
||||
## V1.07
|
||||
|
||||
# V1.07
|
||||
|
||||
- Adds shutdown time to automatically shutdown the iron after inactivity
|
||||
|
||||
## V1.06
|
||||
|
||||
# V1.06
|
||||
|
||||
- Changes H and C when the iron is heating to the minidso chevron like images
|
||||
|
||||
## V1.05
|
||||
|
||||
# V1.05
|
||||
|
||||
- Adds ability to calibrate the input voltage measurement
|
||||
|
||||
## V1.04
|
||||
|
||||
# V1.04
|
||||
|
||||
- Increased accuracy of the temperature control
|
||||
- Improved PID response slightly
|
||||
- Allows temperature offset calibration
|
||||
- Nicer idle screen
|
||||
|
||||
## V1.03
|
||||
|
||||
# V1.03
|
||||
|
||||
- Improved Button handling
|
||||
- Ability to set motion sensitivity
|
||||
- DC voltmeter page shows input voltage
|
||||
|
||||
## V1.02
|
||||
|
||||
# V1.02
|
||||
|
||||
- Adds hold both buttons on IDLE to access the therometer mode
|
||||
- Changes the exit soldering mode to be holding both buttons (Like original firmware)
|
||||
|
||||
@@ -1,56 +1,79 @@
|
||||
# Startup Logos
|
||||
# Startup Logo / Animation
|
||||
|
||||
This firmware supports a user created bootup logo.
|
||||
By default, there is _not_ one included in the firmware. This means that once flashed they generally stay. If you want no logo again, you would have to flash a blank image to the bootup logo.
|
||||
When the device starts, you can have it optionally show either a static image or an animation. You can also set if these should stay on the screen or dismiss after some amount of time.
|
||||
These can be an elegant way to personalise your device or just mark it as your one at a meetup where there may be multiple.
|
||||
|
||||
All devices supported by IronOS support this logo, and follow a similar process for setting one up. Please read the below general information as well as any model specific notes.
|
||||
|
||||
Bootup logos are stored at the end of the flash storage in the Iron; next to the user settings. By locating them at the end of storage they are not erased during the normal firmware upgrade process. Once a logo is set it should stay (unless we need to change things in the main firmware); so to erase your logo you will also find that we generate an erase file. Alternatively your method of flashing _may_ support doing a full erase flash which will also work for this.
|
||||
|
||||
## Generating the Logo files
|
||||
|
||||
There are community logo's already converted and ready to use in [IronOS-Meta/releases](https://github.com/Ralim/IronOS-Meta/releases).
|
||||
Because logos are stored at a fixed location in the device's internal flash; we can use the same method to flash these as you would normal firmware.
|
||||
This does also mean that we need to convert the image/animation file into the format that IronOS understands.
|
||||
|
||||
IronOS uses a pre-processed file format to dramatically reduce the amount of space required to store the image; allowing for animations and saving space.
|
||||
|
||||
In the [IronOS-Meta](https://github.com/Ralim/IronOS-Meta) repository is a `python` script to convert images into this pre-processed file format.
|
||||
Additionally, memebers of the community have contributed back their logo images as well. We provide these pre-converted for all models and ready to use in [IronOS-Meta/releases](https://github.com/Ralim/IronOS-Meta/releases).
|
||||
Download the zip for Pinecil or Miniware and then install using the instructions in the Flashing section below.
|
||||
|
||||
If you want to make custom art then it needs to be converted with a Python script. The script and other needed files are in [IronOS-Meta](https://github.com/Ralim/IronOS-Meta/). Go to that folder, then it is easiest to select the green Code button (upper right), then Download Zip. This way you get all the files you need and some extras. You only need what is inside Boot Logos. Put your custom image inside the Boot Logos folder with all python script files already there.
|
||||
If you want to make custom art then it needs to be converted with the Python script.
|
||||
You can checkout the repository or use the download-as-zip button in the Github web interface to download the code.
|
||||
|
||||
The Python script converts an image passed into it on the command line into both a `.hex` file and a `.dfu` to be uploaded to the iron in DFU mode. The image can be in color and any size, but it will be resized and converted to 1-bit color. However, it looks best if you create a 96x16 image (Png or Bmp) in any image editor and color the pixels black & white manually.
|
||||
Inside the download code is a `Boot Logos` folder, inside here is the python script required for logo conversion.
|
||||
It is easiest if you copy your logo file to be converted into this folder too, in order to keep commands shorter.
|
||||
|
||||
The converter requires at least Python3 and Pillow apps. Follow online instructions for installing Python and Pillow.
|
||||
The image can be in color and any size, but it will be resized and converted to 1-bit color. However, it looks best if you create a 96x16 image (`png` or `bmp`) in any image editor and color the pixels black & white manually. The thresholding used for converting colour to B&W may not always work as well as one would hope.
|
||||
|
||||
For Windows, it is recommended to use Windows PowerShell instead of Command.
|
||||
Open Powershell (run as administrator), type python to install it, it will open microsoft store where you can install it free.
|
||||
Go back to Powershell and install Pillow. What works can vary, but this command may work:
|
||||
The converter requires at least Python3 and Pillow apps. Follow online instructions for installing Python and Pillow on your machine. Any reasonably recent version should work well.
|
||||
|
||||
python -m pip install Pillow
|
||||
or
|
||||
python3 -m pip install pillow
|
||||
When running the script on the Windows operating system; it is recommended to use `Powershell` rather than the old `Command Prompt`.
|
||||
|
||||
If the above does not work, see [this page](https://stackoverflow.com/a/20061019/6705343) on StackOverflow about installing Pillow.
|
||||
Now that Python and Pillow are successfuly installed, you can convert an image.
|
||||
For installing pillow; you can install it via your package manager (Debian and similar distros) or via pip. To install via pip the command should be `python -m pip install pillow`.
|
||||
|
||||
Go back to Powershell and type this command (change infile.png to the name of your image):
|
||||
In your shell you can now execute `python img2logo.py input.png out -m ${model}` to convert the file `input.png` and create output files in the folder `out`.
|
||||
The model should be replaced by one of the following options:
|
||||
|
||||
- `python img2logo.py infile.png out -m` for Miniware
|
||||
- `python img2logo.py infile.png out -p` for Pinecil
|
||||
- `miniware` for older Miniware Irons -> TS100, TS80, TS80P
|
||||
- `pinecilv1` for the Pinecil V1
|
||||
- `pinecilv2` for the Pinecil V2
|
||||
- `ts101` for the Miniware TS101 [^1]
|
||||
- `s60` for the Squire S60 [^1]
|
||||
- `mhp30` for the Miniware MHP30
|
||||
|
||||
Run `python img2logo.py --help` to see available options. Replace the word python with python3 if you have multiple versions of python installed.
|
||||
Different models are used for different flash locations for the image storage.
|
||||
This means that files are **not** interchangeable between devices. If you are flashing multiple devices you will need to create a different file for different models.
|
||||
|
||||
After processing its expected to have a `.hex` and `.dfu` file created to be used. Which one to use will depend on your device.
|
||||
|
||||
Note: make sure your image file is in the same folder as script files (img2logo.py, output_dfu.py, output_hex.py).
|
||||
|
||||
[^1] Note that these devices have larger resolution screens that the logo system supports right now. Fixes are coming for this soon, roughly scheduled for 2.23.
|
||||
|
||||
## Flashing the Logo
|
||||
|
||||
### Miniware (TS100/TS80/TS80P)
|
||||
### Upload via virtual disk (TS100,TS101,TS80,TS80P,S60,MHP30)
|
||||
|
||||
Upload the HEX file to the iron in DFU mode and, if the file's extension changes to .RDY, your custom splash screen should show up on startup.
|
||||
You perform this the same way as if you were flashing a new firmware, and all the existing notes around this apply.
|
||||
If you normally update your firmware by having your device show up as a flash drive this is the method for you.
|
||||
This applies to all Miniware + S60 devices running the stock DFU bootloader.
|
||||
|
||||
If you have flashed the `IronOS-dfu` alternative bootloader, you should use the `.dfu` files instead
|
||||
Place your device into update mode (usually by holding the B button when connecting your device to your pc via USB).
|
||||
Upload the `.hex` file you created earlier as if it was a firmware update. Do any normal tricks required for firmware flashing if any are required.
|
||||
Afterwards the firmware should indicate that it has worked (often by creating a `.rdy` file).
|
||||
|
||||
### Pinecil V1
|
||||
At this point unplug your iron and re-connect it to power to start normally and the logo should welcome you.
|
||||
|
||||
For Pinecil V1, we require using dfu-util to flash the logo art (Pinecil does not use hex).
|
||||
[Pine64 Updater](https://github.com/pine64/pine64_updater/releases) is the easiest way to load the Bootup logo onto Pinecil as it already includes the necessary DFU library. Connect Pinecil to a PC, and open the Updater the same as updating firmware.
|
||||
Select Custom > Browse to the DFU image file you just made > Update to install.
|
||||
### Upload via GUI flash tool (PinecilV1/V2)
|
||||
|
||||
The bootup logo is stored in a separate location than the IronOS firmware and you do not have to worry about it changing or breaking the IronOS.
|
||||
If you normally upload your firmware using a helper application, they should accept the files from the bootlogo the same as the normal firmware.
|
||||
Try the `.dfu` file first and then the `.hex`. If neither work then the application may not be updated to be able to handle boot logos. And you may need to use a different/newer tool.
|
||||
|
||||
You could also use dfu-util and use Command line to install it.
|
||||
### Upload via dfu-util (PinecilV1/IronOS-DFU)
|
||||
|
||||
- `dfu-util -D logo_file.dfu`
|
||||
For the PinecilV1 and for any devices that have been converted to use `IronOS-DFU` as the bootloader you can flash these via the `dfu-util` command line tool.
|
||||
For these flash as per usual using the `.dfu` file. Afterwards power cycle and the logo should show up.
|
||||
|
||||
### Upload via blisp (PinecilV2)
|
||||
|
||||
For the PinecilV2 we suggest `blisp` as the command line tool to use if you are not using a GUI tool. `blsip` has been updated to accept `.dfu` files as well as the `.bin` files it historically used. As such you use the `.dfu` file for the logo and flash as per normal otherwise and it will work and reboot at the end. It should show you your new logo after flashing.
|
||||
|
||||
@@ -22,9 +22,11 @@
|
||||
- [Startup Logo](../Documentation/Logo.md)
|
||||
- Hardware
|
||||
- [Hall Sensor (Pinecil)](../Documentation/HallSensor.md)
|
||||
- [Bluetooth (Pinecil V2)](../Documentation/Bluetooth.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)
|
||||
- [Changelog](../Documentation/History.md)
|
||||
|
||||
@@ -75,10 +75,23 @@ If the tip does not heat up, it is worth trying to reflash the firmware first in
|
||||
The main failure mode of the OLED display module is usually poor soldering on the OLED display cable to the main PCB.
|
||||
As this is soldered by hand generally, it's the most prone to failures.
|
||||
|
||||
If you have a poor connection or a floating pin, you can end up with a state where the screen works _sometimes_ and then freezes or only works on some power cycles. It might work on very old versions of IronOS but not the newest ones. You could try to reflow the pins for the OLED. On 96x16 screens, carefully peel it back from the adhesive and reflow the solder on the pins. If needed, replacement Oled screens are common and low cost.
|
||||
If you have a poor connection or a floating pin, you can end up with a state where the screen works _sometimes_ and then freezes or only works on some power cycles. It might work on very old versions of IronOS but not the newest ones. You could try to reflow the pins for the OLED. On 96x16 screens, carefully peel it back from the adhesive and reflow the solder on the pins.
|
||||
|
||||
As the OLED runs on an I2C bus, there are pull up resistors on the SDA and SCL pins. It is worth checking these as well, while they don't often fail, issues with these can cause _weird_ display issues.
|
||||
|
||||
If after all of the checks OLED is still blank, or screen works but pixels are barely visible, although soldering iron itself is working (i.e., you can safely check that it's turning on, heating up & melting solder successfully), then it means that _most likely_ OLED is dead. But it can be relatively easily replaced. Models like `TS100`, `TS80`, and `TS80P` share the same OLED screen which can be bought online and used for replacement. To do so:
|
||||
|
||||
- find & buy at electronics shop [of your choice] display with the following spec line:
|
||||
```OLED 0.69 inch / 14 pins / 96 x 16 pixels / **9616TSWC** / I2C IIC```
|
||||
|
||||
- disassemble your soldering iron;
|
||||
- desolder old OLED and solder back new one;
|
||||
- assemble your soldering iron back.
|
||||
|
||||
There are a few youtube videos how to do it like [this one for `TS100`](https://www.youtube.com/watch?v=HlWAY0oYPFI).
|
||||
|
||||
Unfortunately, this is a well-known issue of screens with OLED technology: sooner or later the brightness is starting to _"fade out"_ until complete off. Usually common recommendations to prolong its lifetime are: reduce brightness & reduce too often updates (i.e., disable animations). But your results may vary since there were reports when users couldn't see anything after turning on soldering irons which were just laying in a box for a few months after buying. And there are users with first `TS100` models not having any issues with display at all.
|
||||
|
||||
## Tip heats when not in heating mode
|
||||
|
||||
⚠️ DISCONNECT YOUR TIP ⚠️
|
||||
|
||||
36
Makefile
36
Makefile
@@ -79,16 +79,18 @@ help:
|
||||
list:
|
||||
@echo
|
||||
@echo "Supported top-level targets:"
|
||||
@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 " * 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 $(OUT_DIR) (set OUT env var to override: OUT=/path/to/dir make ...)"
|
||||
@echo " * docker-clean - delete created docker image for IronOS & its build cache objects (to free a lot of space)"
|
||||
@echo " * docker-clean-cache - delete build cache objects of IronOS docker image EXCEPT the image itself"
|
||||
@echo " * docker-clean-image - delete docker image for IronOS EXCEPT its build cache objects"
|
||||
@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 docker image & its build cache"
|
||||
@echo " * clean-full - delete generated files & dirs produced during builds INCLUDING docker image & its build cache"
|
||||
@echo ""
|
||||
@echo "NOTES on supported pass-trough targets:"
|
||||
@echo " * main Makefile is located in source/ directory and used to build the firmware itself;"
|
||||
@@ -123,10 +125,17 @@ docker-shell: docker-check $(DOCKER_DEPS)
|
||||
docker-build: docker-check $(DOCKER_DEPS)
|
||||
$(DOCKER_CMD) make build-all
|
||||
|
||||
# delete container
|
||||
docker-clean: docker-check
|
||||
# delete docker image
|
||||
docker-clean-image:
|
||||
-docker rmi ironos-builder:latest
|
||||
|
||||
# delete docker build cache objects
|
||||
docker-clean-cache:
|
||||
-docker system prune --filter label=ironos-builder:latest --force
|
||||
|
||||
# delete docker image & cache related to IronOS container
|
||||
docker-clean: docker-clean-image docker-clean-cache
|
||||
|
||||
# generate docs in site/ directory (DIR for -d is relative to mkdocs.yml file location, hence use default name/location site by setting up ../site)
|
||||
docs: $(MKDOCS_YML) Documentation/* Documentation/Flashing/* Documentation/images/*
|
||||
$(MKDOCS) build -f $(MKDOCS_YML) -d ../site
|
||||
@@ -222,7 +231,6 @@ ci: tests build-all build-multilang
|
||||
clean-build:
|
||||
$(MAKE) -C source/ clean-all
|
||||
rm -Rf site
|
||||
rm -Rf scripts/ci/artefacts
|
||||
rm -Rf $(OUT_DIR)
|
||||
|
||||
# global clean-up target
|
||||
@@ -230,7 +238,7 @@ clean-full: clean-build docker-clean
|
||||
|
||||
# phony targets
|
||||
.PHONY: help list
|
||||
.PHONY: docker-check docker-shell docker-build docker-clean
|
||||
.PHONY: docker-check docker-shell docker-build docker-clean-image docker-clean-cache docker-clean
|
||||
.PHONY: docs docs-deploy
|
||||
.PHONY: test-md test-sh test-py test-ccpp tests
|
||||
.PHONY: build-all build-multilang ci
|
||||
|
||||
@@ -1278,8 +1278,14 @@ def get_version_suffix(ver) -> str:
|
||||
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 (
|
||||
f"{subprocess.check_output(['git', 'rev-parse', '--symbolic-full-name', '--short', 'HEAD']).strip().decode('ascii')}"
|
||||
== "HEAD"
|
||||
):
|
||||
return "E" + "." + sha_id
|
||||
else:
|
||||
## - 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:
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration\ndone!"
|
||||
"message": "Калибрирането\nе завършено!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
"message": "Нулиране"
|
||||
@@ -13,267 +13,267 @@
|
||||
"message": "Настройките бяха\nнулирани!"
|
||||
},
|
||||
"NoAccelerometerMessage": {
|
||||
"message": "No accelerometer\ndetected!"
|
||||
"message": "Не е открит\nакселерометър!"
|
||||
},
|
||||
"NoPowerDeliveryMessage": {
|
||||
"message": "No USB-PD IC\ndetected!"
|
||||
"message": "Не е открито\nUSB-PD захранване!"
|
||||
},
|
||||
"LockingKeysString": {
|
||||
"message": "LOCKED"
|
||||
"message": "ЗАКЛЮЧ"
|
||||
},
|
||||
"UnlockingKeysString": {
|
||||
"message": "UNLOCKED"
|
||||
"message": "ОТКЛЮЧ"
|
||||
},
|
||||
"WarningKeysLockedString": {
|
||||
"message": "!LOCKED!"
|
||||
"message": "!ЗАКЛЮЧ!"
|
||||
},
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Thermal\nRunaway"
|
||||
"message": "Неконтролируемо\nпрегряване"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
"message": "!КС на човка!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
"message": "Преди рестартиране се уверете, че човка и дръжката са на стайна температурата!"
|
||||
},
|
||||
"CJCCalibrating": {
|
||||
"message": "calibrating\n"
|
||||
"message": "калибриране\n"
|
||||
},
|
||||
"SettingsResetWarning": {
|
||||
"message": "Сигурни ли сте, че искате да върнете фабричните настройки?"
|
||||
},
|
||||
"UVLOWarningString": {
|
||||
"message": "Ниско DC Напрежение"
|
||||
"message": "НИС.НАПР."
|
||||
},
|
||||
"UndervoltageString": {
|
||||
"message": "Ниско Напрежение\n"
|
||||
"message": "Ниско напрежение\n"
|
||||
},
|
||||
"InputVoltageString": {
|
||||
"message": "Входно V: \n"
|
||||
},
|
||||
"SleepingSimpleString": {
|
||||
"message": "Сън"
|
||||
"message": "Хъррр"
|
||||
},
|
||||
"SleepingAdvancedString": {
|
||||
"message": "Хър Хър Хър...\n"
|
||||
"message": "Сън...\n"
|
||||
},
|
||||
"SleepingTipAdvancedString": {
|
||||
"message": "Връх: \n"
|
||||
"message": "Човка:\n"
|
||||
},
|
||||
"OffString": {
|
||||
"message": "Изкл."
|
||||
},
|
||||
"ProfilePreheatString": {
|
||||
"message": "Preheat\n"
|
||||
"message": "Загряване\n"
|
||||
},
|
||||
"ProfileCooldownString": {
|
||||
"message": "Cooldown\n"
|
||||
"message": "Охлаждане\n"
|
||||
},
|
||||
"DeviceFailedValidationWarning": {
|
||||
"message": "Your device is most likely a counterfeit!"
|
||||
"message": "Вероятно, устройство е фалшификат!"
|
||||
},
|
||||
"TooHotToStartProfileWarning": {
|
||||
"message": "Too hot to\nstart profile"
|
||||
"message": "Твърде горещо за\nстартиране на профила"
|
||||
}
|
||||
},
|
||||
"characters": {
|
||||
"SettingRightChar": "R",
|
||||
"SettingLeftChar": "L",
|
||||
"SettingAutoChar": "A",
|
||||
"SettingOffChar": "O",
|
||||
"SettingSlowChar": "S",
|
||||
"SettingMediumChar": "M",
|
||||
"SettingFastChar": "F",
|
||||
"SettingRightChar": "Д",
|
||||
"SettingLeftChar": "Л",
|
||||
"SettingAutoChar": "А",
|
||||
"SettingOffChar": "И",
|
||||
"SettingSlowChar": "Н",
|
||||
"SettingMediumChar": "С",
|
||||
"SettingFastChar": "В",
|
||||
"SettingStartNoneChar": "И",
|
||||
"SettingStartSolderingChar": "Р",
|
||||
"SettingStartSolderingChar": "З",
|
||||
"SettingStartSleepChar": "С",
|
||||
"SettingStartSleepOffChar": "П",
|
||||
"SettingLockDisableChar": "D",
|
||||
"SettingLockBoostChar": "B",
|
||||
"SettingLockFullChar": "F"
|
||||
"SettingLockDisableChar": "И",
|
||||
"SettingLockBoostChar": "Т",
|
||||
"SettingLockFullChar": "П"
|
||||
},
|
||||
"menuGroups": {
|
||||
"PowerMenu": {
|
||||
"displayText": "Power\nsettings",
|
||||
"displayText": "Настройки на\nзахранването",
|
||||
"description": ""
|
||||
},
|
||||
"SolderingMenu": {
|
||||
"displayText": "Поялник\nНастройки",
|
||||
"displayText": "Настройки на\nзапояване",
|
||||
"description": ""
|
||||
},
|
||||
"PowerSavingMenu": {
|
||||
"displayText": "Режими\nНастройки",
|
||||
"displayText": "Авто\nизключване",
|
||||
"description": ""
|
||||
},
|
||||
"UIMenu": {
|
||||
"displayText": "Интерфейс\nНастройки",
|
||||
"displayText": "Интерфейс\n",
|
||||
"description": ""
|
||||
},
|
||||
"AdvancedMenu": {
|
||||
"displayText": "Разширени\nНастройки",
|
||||
"displayText": "Допълнителни\nнастройки",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"menuOptions": {
|
||||
"DCInCutoff": {
|
||||
"displayText": "Източник\nзахранване",
|
||||
"description": "Източник на захранване. Минимално напрежение. (DC 10V) (S 3,3V за клетка)"
|
||||
"displayText": "Гранично\nнапрежение",
|
||||
"description": "Минимално напрежение, за да не се изтощи батерията (DC 10V) (S 3,3V за клетка)"
|
||||
},
|
||||
"MinVolCell": {
|
||||
"displayText": "Minimum\nvoltage",
|
||||
"description": "Minimum allowed voltage per battery cell (3S: 3 - 3,7V | 4-6S: 2,4 - 3,7V)"
|
||||
"displayText": "Мин.\nнапрежение",
|
||||
"description": "Минимално допустимо напрежение на акумулаторна клетка (3S: 3 - 3,7V | 4-6S: 2,4 - 3,7V)"
|
||||
},
|
||||
"QCMaxVoltage": {
|
||||
"displayText": "Мощност на\nзахранване",
|
||||
"description": "Мощност на избраното захранване"
|
||||
"displayText": "Напреж.\nна QC",
|
||||
"description": "Максимална напрежение с QC захранвания"
|
||||
},
|
||||
"PDNegTimeout": {
|
||||
"displayText": "PD\ntimeout",
|
||||
"description": "PD negotiation timeout in 100ms steps for compatibility with some QC chargers"
|
||||
"displayText": "PD\nинтервал",
|
||||
"description": "PD интервал за договаряне на захранването на стъпки от 100 мс за съвместимост с някои QC захранвания (0=Изкл.)"
|
||||
},
|
||||
"PDVpdo": {
|
||||
"displayText": "PD\nVPDO",
|
||||
"description": "Enables PPS & EPR modes"
|
||||
"description": "Включи PPS & EPR"
|
||||
},
|
||||
"BoostTemperature": {
|
||||
"displayText": "Турбо\nтемп.",
|
||||
"description": "Температура за \"турбо\" режим"
|
||||
"description": "Температурата за \"турбо\" режим"
|
||||
},
|
||||
"AutoStart": {
|
||||
"displayText": "Автоматичен\nработен режим",
|
||||
"description": "Режим на поялника при включване на захранването. (И=Изключен | Р=Работен | С=Сън | П=Сън температура помещение)"
|
||||
"description": "Режим на поялника при включване на захранването (И=Изкл. | З=Запояване | С=Сън | П=Покой на стайна температурата)"
|
||||
},
|
||||
"TempChangeShortStep": {
|
||||
"displayText": "Промяна T\nбързо?",
|
||||
"description": "Промяна на температура при бързо натискане на бутон!"
|
||||
"displayText": "Промяна T\nбързо",
|
||||
"description": "Промяна на температурата при бързо натискане на бутон"
|
||||
},
|
||||
"TempChangeLongStep": {
|
||||
"displayText": "Промяна Т\nзадържане?",
|
||||
"description": "Промяна на температура при задържане на бутон!"
|
||||
"displayText": "Промяна Т\nзадържане",
|
||||
"description": "Промяна на температурата при задържане на бутон"
|
||||
},
|
||||
"LockingMode": {
|
||||
"displayText": "Allow locking\nbuttons",
|
||||
"description": "While soldering, hold down both buttons to toggle locking them (D=disable | B=boost mode only | F=full locking)"
|
||||
"displayText": "Бутони за\nзаключване",
|
||||
"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за движение",
|
||||
"description": "Усещане за движение (0=Изключено | 1=Слабо | ... | 9=Силно)"
|
||||
"displayText": "Чувствител.\nна движение",
|
||||
"description": "Чувствителност на движение на акселерометър (0=Изкл. | 1=Слабо | ... | 9=Силно)"
|
||||
},
|
||||
"SleepTemperature": {
|
||||
"displayText": "Темп.\nсън",
|
||||
"description": "Температура при режим \"сън\" (C)"
|
||||
"description": "Температурата при режим \"сън\""
|
||||
},
|
||||
"SleepTimeout": {
|
||||
"displayText": "Време\nсън",
|
||||
"description": "Включване в режим \"сън\" след: (Минути | Секунди)"
|
||||
"description": "Включване в режим \"сън\" (секунди | минути)"
|
||||
},
|
||||
"ShutdownTimeout": {
|
||||
"displayText": "Време\nизкл.",
|
||||
"description": "Изключване след (Минути)"
|
||||
"description": "Изключване след (минути)"
|
||||
},
|
||||
"HallEffSensitivity": {
|
||||
"displayText": "Hall sensor\nsensitivity",
|
||||
"description": "Sensitivity to magnets (0=Изключено | 1=Слабо | ... | 9=Силно)"
|
||||
"displayText": "Датчик\nна Хол",
|
||||
"description": "Чувствителност на сензора към магнитно поле (0=Изкл. | 1=Слабо | ... | 9=Силно)"
|
||||
},
|
||||
"TemperatureUnit": {
|
||||
"displayText": "Единици за\nтемпература",
|
||||
"description": "Единици за температура (C=Целзии | F=Фаренхайт)"
|
||||
"displayText": "Единици за\nтемпературата",
|
||||
"description": "Единици за температурата (C=Целзии | F=Фаренхайт)"
|
||||
},
|
||||
"DisplayRotation": {
|
||||
"displayText": "Ориентация\nна дисплея",
|
||||
"description": "Ориентация на дисплея (R=Дясна Ръка | L=Лява Ръка | A=Автоматично)"
|
||||
"description": "Ориентация на дисплея (Д=Дясна ръка | Л=Лява ръка | А=Авто)"
|
||||
},
|
||||
"CooldownBlink": {
|
||||
"displayText": "Мигай при\nтопъл поялник",
|
||||
"description": "След изключване от работен режим, индикатора за температура да мига докато човката на поялника все още е топла"
|
||||
"description": "След изключване от работен режим, индикатора за температурата да мига докато човката на поялника все още е топла"
|
||||
},
|
||||
"ScrollingSpeed": {
|
||||
"displayText": "Скорост\nна текста",
|
||||
"description": "Скорост на движение на този текст"
|
||||
"description": "Скорост на движение на този текст (Н=Ниска | B=Висока)"
|
||||
},
|
||||
"ReverseButtonTempChange": {
|
||||
"displayText": "Размяна\nбутони +-?",
|
||||
"description": "Обръщане на бутоните \"+\" и \"-\" за промяна на температурата на върха на поялника"
|
||||
"displayText": "Размяна\nбутони +/-",
|
||||
"description": "Обръщане на бутоните + и - за промяна на температурата на човка на поялника"
|
||||
},
|
||||
"AnimSpeed": {
|
||||
"displayText": "Anim.\nspeed",
|
||||
"description": "Pace of icon animations in menu (O=off | S=slow | M=medium | F=fast)"
|
||||
"displayText": "Скорост на\nанимацията",
|
||||
"description": "Скорост на анимация на иконата в главното меню (И=Изкл. | Н=Ниска | C=Средна | B=Висока)"
|
||||
},
|
||||
"AnimLoop": {
|
||||
"displayText": "Anim.\nloop",
|
||||
"description": "Loop icon animations in main menu"
|
||||
"displayText": "Анимац.\nцикъл",
|
||||
"description": "Зациклена анимация на иконите в главното меню"
|
||||
},
|
||||
"Brightness": {
|
||||
"displayText": "Screen\nbrightness",
|
||||
"description": "Adjust the OLED screen brightness"
|
||||
"displayText": "Яркост\nна екрана",
|
||||
"description": "Регулирайте яркостта на екрана"
|
||||
},
|
||||
"ColourInversion": {
|
||||
"displayText": "Invert\nscreen",
|
||||
"description": "Invert the OLED screen colors"
|
||||
"displayText": "Инвертиране\nна екрана",
|
||||
"description": "Инверсия на пикселите на екрана"
|
||||
},
|
||||
"LOGOTime": {
|
||||
"displayText": "Boot logo\nduration",
|
||||
"description": "Set boot logo duration (s=seconds)"
|
||||
"displayText": "Продължит.\nлогото",
|
||||
"description": "Продължителност на логото за стартиране (в секунди)"
|
||||
},
|
||||
"AdvancedIdle": {
|
||||
"displayText": "Детайлен\nекран в покой",
|
||||
"description": "Покажи детайлна информация със ситен шрифт на екрана в режим на покой."
|
||||
"description": "Покажи детайлна информация със ситен шрифт на екрана в режим на покой"
|
||||
},
|
||||
"AdvancedSoldering": {
|
||||
"displayText": "Детайлен\nработен екран",
|
||||
@@ -281,34 +281,34 @@
|
||||
},
|
||||
"BluetoothLE": {
|
||||
"displayText": "Bluetooth\n",
|
||||
"description": "Enables BLE"
|
||||
"description": "Включи BLE"
|
||||
},
|
||||
"PowerLimit": {
|
||||
"displayText": "Лимит на\nмощност",
|
||||
"description": "Максимална мощност на поялника (Watt)"
|
||||
"description": "Максимална мощност на поялника (вати)"
|
||||
},
|
||||
"CalibrateCJC": {
|
||||
"displayText": "Calibrate CJC\nat next boot",
|
||||
"description": "At next boot tip Cold Junction Compensation will be calibrated (not required if Delta T is < 5 C)"
|
||||
"displayText": "Калибриране\nна темп.",
|
||||
"description": "Калибриране на температурата (CJC) при следващо включване (не се изисква, ако разликата е по-малка от 5 °С)"
|
||||
},
|
||||
"VoltageCalibration": {
|
||||
"displayText": "Калибриране\nнапрежение?",
|
||||
"description": "Калибриране на входното напрежение. Задръжте бутонa за изход"
|
||||
"displayText": "Калибриране\nнапрежение",
|
||||
"description": "Калибриране на входното напрежение (задръжте бутонa за изход)"
|
||||
},
|
||||
"PowerPulsePower": {
|
||||
"displayText": "Захранващ\nимпулс",
|
||||
"description": "Поддържане на интензивност на захранващия импулс"
|
||||
"description": "Поддържане на интензивност на захранващия импулс (вати)"
|
||||
},
|
||||
"PowerPulseWait": {
|
||||
"displayText": "Power pulse\ndelay",
|
||||
"description": "Delay before keep-awake-pulse is triggered (x 2,5с)"
|
||||
"displayText": "Закъснение\nна импулса",
|
||||
"description": "Пауза между импулсите, които предпазват захранването от автоматично изключване (x 2,5 с)"
|
||||
},
|
||||
"PowerPulseDuration": {
|
||||
"displayText": "Power pulse\nduration",
|
||||
"description": "Keep-awake-pulse duration (x 250мс)"
|
||||
"displayText": "Продължит.\nна импулса",
|
||||
"description": "Дължината на импулса, който предпазва захранването от автоматично изключване (x 250 мс)"
|
||||
},
|
||||
"SettingsReset": {
|
||||
"displayText": "Фабрични\nнастройки?",
|
||||
"displayText": "Фабрични\nнастройки",
|
||||
"description": "Връщане на фабрични настройки"
|
||||
},
|
||||
"LanguageSwitch": {
|
||||
@@ -316,4 +316,4 @@
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"message": "Teplotní\nOchrana"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
"message": "!Zkrat na hrotu!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Před restartem se ujistěte, že hrot a držák mají pokojovou teplotu!"
|
||||
@@ -64,16 +64,16 @@
|
||||
"message": "Vyp"
|
||||
},
|
||||
"ProfilePreheatString": {
|
||||
"message": "Preheat\n"
|
||||
"message": "Předehřívání\n"
|
||||
},
|
||||
"ProfileCooldownString": {
|
||||
"message": "Cooldown\n"
|
||||
"message": "Zchlazování\n"
|
||||
},
|
||||
"DeviceFailedValidationWarning": {
|
||||
"message": "Vaše zařízení je s nejvyšší pravděpodobností padělek!"
|
||||
"message": "Vaše zařízení je pravěpodobně padělek!"
|
||||
},
|
||||
"TooHotToStartProfileWarning": {
|
||||
"message": "Too hot to\nstart profile"
|
||||
"message": "Teplota příliš vysoká pro start profilu"
|
||||
}
|
||||
},
|
||||
"characters": {
|
||||
@@ -156,60 +156,60 @@
|
||||
"description": "Při pájení podržte obě tlačítka pro jejich zamčení (Z=zakázáno | B=pouze v režimu boost | U=úplné zamčení)"
|
||||
},
|
||||
"ProfilePhases": {
|
||||
"displayText": "Profile\nPhases",
|
||||
"description": "Number of phases in profile mode"
|
||||
"displayText": "Profilové\nFáze",
|
||||
"description": "Počet fází v profilovém režimu"
|
||||
},
|
||||
"ProfilePreheatTemp": {
|
||||
"displayText": "Preheat\nTemp",
|
||||
"description": "Preheat to this temperature at the start of profile mode"
|
||||
"displayText": "Teplota\nPředehřátí",
|
||||
"description": "Teplota na kterou předehřát na začátku profilového režimu"
|
||||
},
|
||||
"ProfilePreheatSpeed": {
|
||||
"displayText": "Preheat\nSpeed",
|
||||
"description": "Preheat at this rate (degrees per second)"
|
||||
"displayText": "Rychlost\nPředehřívání",
|
||||
"description": "Rychlost předehřívání (stupně za sekundu)"
|
||||
},
|
||||
"ProfilePhase1Temp": {
|
||||
"displayText": "Phase 1\nTemp",
|
||||
"description": "Target temperature for the end of this phase"
|
||||
"displayText": "Teplota\nFáze 1",
|
||||
"description": "Cílová teplota na konci této fáze"
|
||||
},
|
||||
"ProfilePhase1Duration": {
|
||||
"displayText": "Phase 1\nDuration",
|
||||
"description": "Target duration of this phase (seconds)"
|
||||
"displayText": "Trvání\nFáze 1",
|
||||
"description": "Doba trvání této fáze (sekundy)"
|
||||
},
|
||||
"ProfilePhase2Temp": {
|
||||
"displayText": "Phase 2\nTemp",
|
||||
"displayText": "Teplota\nFáze 2",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase2Duration": {
|
||||
"displayText": "Phase 2\nDuration",
|
||||
"displayText": "Trvání\nFáze 2",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase3Temp": {
|
||||
"displayText": "Phase 3\nTemp",
|
||||
"displayText": "Teplota\nFáze 3",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase3Duration": {
|
||||
"displayText": "Phase 3\nDuration",
|
||||
"displayText": "Trvání\nFáze 3",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase4Temp": {
|
||||
"displayText": "Phase 4\nTemp",
|
||||
"displayText": "Teplota\nFáze 4",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase4Duration": {
|
||||
"displayText": "Phase 4\nDuration",
|
||||
"displayText": "Trvání\nFáze 4",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase5Temp": {
|
||||
"displayText": "Phase 5\nTemp",
|
||||
"displayText": "Teplota\nFáze 5",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase5Duration": {
|
||||
"displayText": "Phase 5\nDuration",
|
||||
"displayText": "Trvání\nFáze 5",
|
||||
"description": ""
|
||||
},
|
||||
"ProfileCooldownSpeed": {
|
||||
"displayText": "Cooldown\nSpeed",
|
||||
"description": "Cooldown at this rate at the end of profile mode (degrees per second)"
|
||||
"displayText": "Rychlost\nochlazování",
|
||||
"description": "Rychlost ochlazování na konci profilového režimu (stupně za sekundu)"
|
||||
},
|
||||
"MotionSensitivity": {
|
||||
"displayText": "Citlivost\nna pohyb",
|
||||
@@ -316,4 +316,4 @@
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"message": "Thermal\nRunaway"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
"message": "!Lötspitze\nkurzgeschlossen!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Vor dem Neustart bitte sicherstellen, dass Lötspitze & Gerät Raumtemperatur haben!"
|
||||
@@ -61,7 +61,7 @@
|
||||
"message": "Temp: \n"
|
||||
},
|
||||
"OffString": {
|
||||
"message": "Aus"
|
||||
"message": "aus"
|
||||
},
|
||||
"ProfilePreheatString": {
|
||||
"message": "Vorwärmen\n"
|
||||
@@ -145,15 +145,15 @@
|
||||
},
|
||||
"TempChangeShortStep": {
|
||||
"displayText": "Temp-Schritt\nDruck kurz",
|
||||
"description": "Schrittweite für Temperaturwechsel bei kurzem Tastendruck"
|
||||
"description": "Schrittweite für Temperaturänderung bei kurzem Tastendruck"
|
||||
},
|
||||
"TempChangeLongStep": {
|
||||
"displayText": "Temp-Schritt\nDruck lang",
|
||||
"description": "Schrittweite für Temperaturwechsel bei langem Tastendruck"
|
||||
"description": "Schrittweite für Temperaturänderung bei langem Tastendruck"
|
||||
},
|
||||
"LockingMode": {
|
||||
"displayText": "Tasten-\nsperre",
|
||||
"description": "Langes drücken beider Tasten im Lötmodus sperrt diese (A=aus | B=nur Boost | V=vollständig)"
|
||||
"description": "Langes Drücken beider Tasten im Lötmodus sperrt diese (A=aus | B=nur Boost | V=vollständig)"
|
||||
},
|
||||
"ProfilePhases": {
|
||||
"displayText": "Profile\nPhasen",
|
||||
@@ -173,7 +173,7 @@
|
||||
},
|
||||
"ProfilePhase1Duration": {
|
||||
"displayText": "Phase 1\nDauer",
|
||||
"description": "Zieldauer dieser Phase (Sekunden)"
|
||||
"description": "Dauer dieser Phase (Sekunden)"
|
||||
},
|
||||
"ProfilePhase2Temp": {
|
||||
"displayText": "Phase 2\nTemperatur",
|
||||
@@ -217,7 +217,7 @@
|
||||
},
|
||||
"SleepTemperature": {
|
||||
"displayText": "Ruhe-\ntemperatur",
|
||||
"description": "Ruhetemperatur der Spitze"
|
||||
"description": "Ruhetemperatur der Lötspitze"
|
||||
},
|
||||
"SleepTimeout": {
|
||||
"displayText": "Ruhever-\nzögerung",
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"message": "Temperatura\nfuori controllo"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
"message": "Punta in cortocircuito!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Prima di riavviare assicurati che la punta e l'impugnatura siano a temperatura ambiente!"
|
||||
|
||||
@@ -7,16 +7,16 @@
|
||||
"message": "Калибровка\nзавершена!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
"message": "Сброс OK"
|
||||
"message": "Готово!"
|
||||
},
|
||||
"SettingsResetMessage": {
|
||||
"message": "Настройки\nсброшены!"
|
||||
},
|
||||
"NoAccelerometerMessage": {
|
||||
"message": "Не определен\nакселерометр!"
|
||||
"message": "Акселерометр\nне обнаружен!"
|
||||
},
|
||||
"NoPowerDeliveryMessage": {
|
||||
"message": "USB-PD питание\nне обнаружено"
|
||||
"message": "Питание по USB-PD\nне обнаружено"
|
||||
},
|
||||
"LockingKeysString": {
|
||||
"message": "ЗАБЛОК"
|
||||
@@ -28,10 +28,10 @@
|
||||
"message": "!ЗАБЛОК!"
|
||||
},
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Неуправляемый\nРазогрев"
|
||||
"message": "Неуправляемый\nразогрев"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
"message": "!КЗ на жале!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Пожалуйста, убедитесь, что жало и корпус имеют комнатную температуру при следующей загрузке!"
|
||||
@@ -43,25 +43,25 @@
|
||||
"message": "Вы уверены, что хотите сбросить настройки к значениям по умолчанию?"
|
||||
},
|
||||
"UVLOWarningString": {
|
||||
"message": "НАПРЯЖ--"
|
||||
"message": "НИЗ.НАПР"
|
||||
},
|
||||
"UndervoltageString": {
|
||||
"message": "Низ. напряжение\n"
|
||||
},
|
||||
"InputVoltageString": {
|
||||
"message": "Питание В: \n"
|
||||
"message": "Питание(В):\n"
|
||||
},
|
||||
"SleepingSimpleString": {
|
||||
"message": "Zzzz"
|
||||
"message": "Хххррп"
|
||||
},
|
||||
"SleepingAdvancedString": {
|
||||
"message": "Ожидание...\n"
|
||||
"message": "Сон...\n"
|
||||
},
|
||||
"SleepingTipAdvancedString": {
|
||||
"message": "Жало: \n"
|
||||
},
|
||||
"OffString": {
|
||||
"message": "Вык"
|
||||
"message": "Выкл"
|
||||
},
|
||||
"ProfilePreheatString": {
|
||||
"message": "Преднагрев\n"
|
||||
@@ -70,7 +70,7 @@
|
||||
"message": "Остывание\n"
|
||||
},
|
||||
"DeviceFailedValidationWarning": {
|
||||
"message": "Вероятно, это устройство подделка!"
|
||||
"message": "Вероятно, это поддельное устройство!"
|
||||
},
|
||||
"TooHotToStartProfileWarning": {
|
||||
"message": "Слишком горячо для\nстарта профиля"
|
||||
@@ -84,9 +84,9 @@
|
||||
"SettingSlowChar": "М",
|
||||
"SettingMediumChar": "С",
|
||||
"SettingFastChar": "Б",
|
||||
"SettingStartNoneChar": "В",
|
||||
"SettingStartNoneChar": "О",
|
||||
"SettingStartSolderingChar": "П",
|
||||
"SettingStartSleepChar": "О",
|
||||
"SettingStartSleepChar": "С",
|
||||
"SettingStartSleepOffChar": "К",
|
||||
"SettingLockDisableChar": "О",
|
||||
"SettingLockBoostChar": "Т",
|
||||
@@ -94,166 +94,166 @@
|
||||
},
|
||||
"menuGroups": {
|
||||
"PowerMenu": {
|
||||
"displayText": "Параметры\nпитания",
|
||||
"displayText": "Настройки\nпитания",
|
||||
"description": ""
|
||||
},
|
||||
"SolderingMenu": {
|
||||
"displayText": "Параметры\nпайки",
|
||||
"displayText": "Настройки\nпайки",
|
||||
"description": ""
|
||||
},
|
||||
"PowerSavingMenu": {
|
||||
"displayText": "Режимы\nсна",
|
||||
"displayText": "Авто\nвыключение",
|
||||
"description": ""
|
||||
},
|
||||
"UIMenu": {
|
||||
"displayText": "Параметры\nинтерфейса",
|
||||
"displayText": "Интерфейс\n",
|
||||
"description": ""
|
||||
},
|
||||
"AdvancedMenu": {
|
||||
"displayText": "Дополнител.\nнастройки",
|
||||
"displayText": "Доп.\nнастройки",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"menuOptions": {
|
||||
"DCInCutoff": {
|
||||
"displayText": "Источник\nпитания",
|
||||
"description": "Источник питания. Устанавливает напряжение отсечки. (DC 10В) (S 3,3В на ячейку, без лимита мощности)"
|
||||
"displayText": "Предельное\nнапряжение",
|
||||
"description": "Установка минимально предельного напряжения от аккумулятора для предотвращения глубокого разряда (DC 10В | S 3,3В на ячейку, без ограничения мощности)"
|
||||
},
|
||||
"MinVolCell": {
|
||||
"displayText": "Мин.\nнапр.",
|
||||
"description": "Минимальное разрешенное напряжение на ячейку (3S: 3 - 3,7V | 4S-6S: 2,4 - 3,7V)"
|
||||
"displayText": "Мин.\nнапряжение",
|
||||
"description": "Минимально разрешённое напряжение на ячейку (3S: 3 - 3,7В | 4S-6S: 2,4 - 3,7В)"
|
||||
},
|
||||
"QCMaxVoltage": {
|
||||
"displayText": "Ограничение\nнапряжения QC",
|
||||
"description": "Максимальное напряжение для согласования с QC источником питания"
|
||||
"displayText": "Напр-е\nдля QC",
|
||||
"description": "Максимальное напряжение для согласования с источником питания по QC"
|
||||
},
|
||||
"PDNegTimeout": {
|
||||
"displayText": "PD\nтайм-аут",
|
||||
"description": "Power Delivery тайм-аут согласования с шагом 100 мс для совместимости с некоторыми быстрыми зарядными QC (0: отключено)"
|
||||
"displayText": "PD\nинтервал",
|
||||
"description": "Интервал согласования питания по Power Delivery с шагом 100 мс для совместимости с некоторыми источниками питания по QC (0=Откл.)"
|
||||
},
|
||||
"PDVpdo": {
|
||||
"displayText": "PD\nVPDO",
|
||||
"description": "Включает режимы PPS & EPR."
|
||||
"description": "Включить режимы PPS & EPR"
|
||||
},
|
||||
"BoostTemperature": {
|
||||
"displayText": "t° турбо\nрежима",
|
||||
"description": "Температура жала в турбо-режиме"
|
||||
},
|
||||
"AutoStart": {
|
||||
"displayText": "Авто\nстарт",
|
||||
"description": "Режим, в котором запускается паяльник при подаче питания (В=Выкл. | П=Пайка | О=Ожидание | К=Ожидание при комн. темп.)"
|
||||
"displayText": "Режим при\nвключении",
|
||||
"description": "Режим, в котором включается паяльник (О=Откл. | П=Пайка | С=Сон | К=Ожидание при комн. темп.)"
|
||||
},
|
||||
"TempChangeShortStep": {
|
||||
"displayText": "Шаг темп.\nкор. наж.",
|
||||
"displayText": "Шаг t° при\nкор.наж-ии",
|
||||
"description": "Шаг изменения температуры при коротком нажатии кнопок"
|
||||
},
|
||||
"TempChangeLongStep": {
|
||||
"displayText": "Шаг темп.\nдлин. наж.",
|
||||
"description": "Шаг изменения температуры при длинном нажатии кнопок"
|
||||
"displayText": "Шаг t° при\nдол.наж-ии",
|
||||
"description": "Шаг изменения температуры при долгом нажатии кнопок"
|
||||
},
|
||||
"LockingMode": {
|
||||
"displayText": "Разрешить\nблок. кнопок",
|
||||
"description": "При работе длинное нажатие обеих кнопок блокирует их (О=Отключено | Т=Только турбо | П=Полная блокировка)"
|
||||
"description": "Блокировать кнопки при их долгом нажатии в режиме пайки (О=Откл. | Т=Только турбо | П=Полная блокировка)"
|
||||
},
|
||||
"ProfilePhases": {
|
||||
"displayText": "Профиль\nЭтапы",
|
||||
"displayText": "Этапы\nпрофиля",
|
||||
"description": "Количество этапов в режиме профиля"
|
||||
},
|
||||
"ProfilePreheatTemp": {
|
||||
"displayText": "Преднагрев\nТемпература",
|
||||
"description": "Разогреть до этой температуры в начале режима профиля"
|
||||
"displayText": "Температура\nпреднагрева",
|
||||
"description": "Температура предварительного нагрева в начале режима термопрофиля"
|
||||
},
|
||||
"ProfilePreheatSpeed": {
|
||||
"displayText": "Преднагрев\nСкорость",
|
||||
"description": "Предварительный нагрев с этой скоростью (градусов в секунду)"
|
||||
"displayText": "Скорость\nпреднагрева",
|
||||
"description": "Скорость предварительного нагрева в начале режима термопрофиля (в градусах в секунду)"
|
||||
},
|
||||
"ProfilePhase1Temp": {
|
||||
"displayText": "Этап 1\nТемпература",
|
||||
"description": "Целевая температура в конце этого эатпа"
|
||||
"displayText": "Температура\n1-го этапа",
|
||||
"description": "Необходимая температура в конце 1-го этапа"
|
||||
},
|
||||
"ProfilePhase1Duration": {
|
||||
"displayText": "Этап 1\nДлительность",
|
||||
"description": "Целевая длительность этого этапа (секунды)"
|
||||
"displayText": "Длительность\n1-го этапа",
|
||||
"description": "Необходимая длительность 1-го этапа (в секундах)"
|
||||
},
|
||||
"ProfilePhase2Temp": {
|
||||
"displayText": "Этап 2\nТемпература",
|
||||
"displayText": "Температура\n2-го этапа",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase2Duration": {
|
||||
"displayText": "Этап 2\nДлительность",
|
||||
"displayText": "Длительность\n2-го этапа",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase3Temp": {
|
||||
"displayText": "Этап 3\nТемпература",
|
||||
"displayText": "Температура\n3-го этапа",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase3Duration": {
|
||||
"displayText": "Этап 3\nДлительность",
|
||||
"displayText": "Длительность\n3-го этапа",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase4Temp": {
|
||||
"displayText": "Этап 4\nТемпература",
|
||||
"displayText": "Температура\n4-го этапа",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase4Duration": {
|
||||
"displayText": "Этап 4\nДлительность",
|
||||
"displayText": "Длительность\n4-го этапа",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase5Temp": {
|
||||
"displayText": "Этап 5\nТемпература",
|
||||
"displayText": "Температура\n5-го этапа",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase5Duration": {
|
||||
"displayText": "Этап 5\nДлительность",
|
||||
"displayText": "Длительность\n5-го этапа",
|
||||
"description": ""
|
||||
},
|
||||
"ProfileCooldownSpeed": {
|
||||
"displayText": "Остывание\nСкорость",
|
||||
"description": "Остывать с такой скоростью в конце режима профиля (градусов в секунду)"
|
||||
"displayText": "Скорость\nостывания",
|
||||
"description": "Скорость остывания в конце режима термопрофиля (в градусах в секунду)"
|
||||
},
|
||||
"MotionSensitivity": {
|
||||
"displayText": "Чувствительн.\nакселерометра",
|
||||
"description": "Чувствительность акселерометра (0=Выкл. | 1=мин. | ... | 9=макс.)"
|
||||
"description": "Чувствительность акселерометра (0=Откл. | 1=мин. | ... | 9=макс.)"
|
||||
},
|
||||
"SleepTemperature": {
|
||||
"displayText": "Темп.\nожидания",
|
||||
"description": "Температура жала в режиме ожидания"
|
||||
"displayText": "t° при\nсне",
|
||||
"description": "Температура жала в режиме сна"
|
||||
},
|
||||
"SleepTimeout": {
|
||||
"displayText": "Таймаут\nожидания",
|
||||
"description": "Время до перехода в режим ожидания (Минуты | Секунды)"
|
||||
"displayText": "Интервал\nсна",
|
||||
"description": "Время до перехода в режим сна (секунды | минуты)"
|
||||
},
|
||||
"ShutdownTimeout": {
|
||||
"displayText": "Таймаут\nвыключения",
|
||||
"description": "Время до выключения паяльника (минуты)"
|
||||
"displayText": "Интервал\nотключ-я",
|
||||
"description": "Время до выключения паяльника (в минутах)"
|
||||
},
|
||||
"HallEffSensitivity": {
|
||||
"displayText": "Датчик\nХолла",
|
||||
"description": "Чувствительность датчика Холла к переходу в спящий режим (0=Выкл. | 1=мин. | ... | 9=макс.)"
|
||||
"description": "Чувствительность датчика Холла к магнитному полю (0=Откл. | 1=мин. | ... | 9=макс.)"
|
||||
},
|
||||
"TemperatureUnit": {
|
||||
"displayText": "Единицы\nтемпературы",
|
||||
"displayText": "Единицы\nизмерения",
|
||||
"description": "Единицы измерения температуры (C=°Цельcия | F=°Фаренгейта)"
|
||||
},
|
||||
"DisplayRotation": {
|
||||
"displayText": "Ориентация\nэкрана",
|
||||
"description": "Ориентация экрана (П=Правая рука | Л=Левая рука | А=Авто)"
|
||||
"displayText": "Поворот\nэкрана",
|
||||
"description": "Поворот экрана (П=Правша | Л=Левша | А=Авто)"
|
||||
},
|
||||
"CooldownBlink": {
|
||||
"displayText": "Мигание t°\nпри остывании",
|
||||
"description": "Мигать температурой на экране охлаждения, пока жало еще горячее"
|
||||
"description": "Мигать температурой на экране при остывании, пока жало ещё горячее"
|
||||
},
|
||||
"ScrollingSpeed": {
|
||||
"displayText": "Скорость\nтекста",
|
||||
"description": "Скорость прокрутки текста (М=Медленная | Б=Быстрая)"
|
||||
},
|
||||
"ReverseButtonTempChange": {
|
||||
"displayText": "Поменять\nкнопки+-",
|
||||
"displayText": "Поменять\nкнопки +/-",
|
||||
"description": "Поменять кнопки изменения температуры"
|
||||
},
|
||||
"AnimSpeed": {
|
||||
"displayText": "Скорость\nанимации",
|
||||
"description": "Скорость анимации иконок в главном меню (О=Отключено | М=Медленная| С=Средняя | Б=Быстрая)"
|
||||
"description": "Скорость анимации иконок в главном меню (О=Откл. | М=Медленная| С=Средняя | Б=Быстрая)"
|
||||
},
|
||||
"AnimLoop": {
|
||||
"displayText": "Зацикленная\nанимация",
|
||||
@@ -261,31 +261,31 @@
|
||||
},
|
||||
"Brightness": {
|
||||
"displayText": "Яркость\nэкрана",
|
||||
"description": "Настройки контраста/яркости OLED экрана"
|
||||
"description": "Уровень яркости пикселей на экране"
|
||||
},
|
||||
"ColourInversion": {
|
||||
"displayText": "Инверсия\nэкрана",
|
||||
"description": "Инвертировать цвета на OLED экране"
|
||||
"description": "Инвертировать пиксели на экране"
|
||||
},
|
||||
"LOGOTime": {
|
||||
"displayText": "Длительность\nпоказа логотипа",
|
||||
"displayText": "Длит-ть\nлоготипа",
|
||||
"description": "Длительность отображения логотипа (в секундах)"
|
||||
},
|
||||
"AdvancedIdle": {
|
||||
"displayText": "Подробный\nреж. ожидания",
|
||||
"description": "Отображать детальную информацию уменьшенным шрифтом на экране ожидания"
|
||||
"displayText": "Подробный\nэкран ожидания",
|
||||
"description": "Показывать дополнительную информацию на экране ожидания уменьшенным шрифтом"
|
||||
},
|
||||
"AdvancedSoldering": {
|
||||
"displayText": "Подробный\nэкран пайки",
|
||||
"description": "Показывать детальную информацию на экране пайки"
|
||||
"description": "Показывать дополнительную информацию на экране пайки уменьшенным шрифтом"
|
||||
},
|
||||
"BluetoothLE": {
|
||||
"displayText": "Bluetooth\n",
|
||||
"description": "Активирует BLE"
|
||||
"description": "Включить BLE"
|
||||
},
|
||||
"PowerLimit": {
|
||||
"displayText": "Предел\nмощности",
|
||||
"description": "Максимальная мощность, которую может использовать паяльник (Ватт)"
|
||||
"displayText": "Предел\nмощ-ти",
|
||||
"description": "Максимальная мощность, которую может использовать паяльник (в ваттах)"
|
||||
},
|
||||
"CalibrateCJC": {
|
||||
"displayText": "Калибровка\nтемпературы",
|
||||
@@ -296,20 +296,20 @@
|
||||
"description": "Калибровка входного напряжения (долгое нажатие для выхода)"
|
||||
},
|
||||
"PowerPulsePower": {
|
||||
"displayText": "Сила имп.\nпитания Вт",
|
||||
"description": "Сила импульса удерживающего от сна повербанк или другой источник питания"
|
||||
"displayText": "Сила имп.\nпитания",
|
||||
"description": "Сила импульса, удерживающего от автовыключения источник питания (в ваттах)"
|
||||
},
|
||||
"PowerPulseWait": {
|
||||
"displayText": "Пауза имп.\nпитания с",
|
||||
"description": "Пауза между импульсами удерживающими источник питания от сна (x 2,5с)"
|
||||
"displayText": "Пауза имп.\nпитания (К)",
|
||||
"description": "Коэффициент паузы между импульсами, удерживающими от автовыключения источник питания (К x 2,5 с)"
|
||||
},
|
||||
"PowerPulseDuration": {
|
||||
"displayText": "Длина имп.\nпитания мс",
|
||||
"description": "Длина импульса удерживающего от сна источник питания (x 250мс)"
|
||||
"displayText": "Длина имп.\nпитания (К)",
|
||||
"description": "Коэффициент длины импульса, удерживающего от автовыключения источник питания (К x 250 мс)"
|
||||
},
|
||||
"SettingsReset": {
|
||||
"displayText": "Сброс\nНастроек",
|
||||
"description": "Сброс настроек к значеням по умолчанию"
|
||||
"displayText": "Сброс\nнастроек",
|
||||
"description": "Сброс настроек к значениям по умолчанию"
|
||||
},
|
||||
"LanguageSwitch": {
|
||||
"displayText": "Язык:\n RU Русский",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration\ndone!"
|
||||
"message": "Kalibrácia\ndokončená!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
"message": "Reset OK"
|
||||
@@ -31,13 +31,13 @@
|
||||
"message": "Únik\nTepla"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
"message": "!Skrat hrotu!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
"message": "Pred reštartovaním sa uistite, že hrot a rúčka sú v izbovej teplote!"
|
||||
},
|
||||
"CJCCalibrating": {
|
||||
"message": "calibrating\n"
|
||||
"message": "kalibrovanie\n"
|
||||
},
|
||||
"SettingsResetWarning": {
|
||||
"message": "Naozaj chcete obnoviť továrenské nastavenia?"
|
||||
@@ -64,16 +64,16 @@
|
||||
"message": "Vyp"
|
||||
},
|
||||
"ProfilePreheatString": {
|
||||
"message": "Preheat\n"
|
||||
"message": "Predhrievanie\n"
|
||||
},
|
||||
"ProfileCooldownString": {
|
||||
"message": "Cooldown\n"
|
||||
"message": "Schladzovanie\n"
|
||||
},
|
||||
"DeviceFailedValidationWarning": {
|
||||
"message": "Vaše zariadenie je pravdepodobne falzifikát!"
|
||||
},
|
||||
"TooHotToStartProfileWarning": {
|
||||
"message": "Too hot to\nstart profile"
|
||||
"message": "Teplota príliš vysoká pre štart profilu"
|
||||
}
|
||||
},
|
||||
"characters": {
|
||||
@@ -133,7 +133,7 @@
|
||||
},
|
||||
"PDVpdo": {
|
||||
"displayText": "PD\nVPDO",
|
||||
"description": "Enables PPS & EPR modes"
|
||||
"description": "Zapína PPS & EPR režimy"
|
||||
},
|
||||
"BoostTemperature": {
|
||||
"displayText": "Boost\nteplota",
|
||||
@@ -156,60 +156,60 @@
|
||||
"description": "Zamknutie tlačidiel - dlhé stlačenie oboch naraz počas spájkovania (Z=Zakázať | B=Okrem boost | P=Plné zamknutie)"
|
||||
},
|
||||
"ProfilePhases": {
|
||||
"displayText": "Profile\nPhases",
|
||||
"description": "Number of phases in profile mode"
|
||||
"displayText": "Profilové\nFázy",
|
||||
"description": "Počet fáz v profilovóm režime"
|
||||
},
|
||||
"ProfilePreheatTemp": {
|
||||
"displayText": "Preheat\nTemp",
|
||||
"description": "Preheat to this temperature at the start of profile mode"
|
||||
"displayText": "Teplota\nPredhriatia",
|
||||
"description": "Teplota na ktorú sa má predohriať na začiatku profilového režimu"
|
||||
},
|
||||
"ProfilePreheatSpeed": {
|
||||
"displayText": "Preheat\nSpeed",
|
||||
"description": "Preheat at this rate (degrees per second)"
|
||||
"displayText": "Rýchlosť\nPredhriatia",
|
||||
"description": "Rýchlosť predhrievania (stupňe za sekundu)"
|
||||
},
|
||||
"ProfilePhase1Temp": {
|
||||
"displayText": "Phase 1\nTemp",
|
||||
"description": "Target temperature for the end of this phase"
|
||||
"displayText": "Teplota\nFáza 1",
|
||||
"description": "Cieľová teplota na konci tejto fázy"
|
||||
},
|
||||
"ProfilePhase1Duration": {
|
||||
"displayText": "Phase 1\nDuration",
|
||||
"description": "Target duration of this phase (seconds)"
|
||||
"displayText": "Trvanie\nFáza 1",
|
||||
"description": "Doba trvania tejto fázy (sekundy)"
|
||||
},
|
||||
"ProfilePhase2Temp": {
|
||||
"displayText": "Phase 2\nTemp",
|
||||
"displayText": "Teplota\nFáza 2",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase2Duration": {
|
||||
"displayText": "Phase 2\nDuration",
|
||||
"displayText": "Trvanie\nFáza 2",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase3Temp": {
|
||||
"displayText": "Phase 3\nTemp",
|
||||
"displayText": "Teplota\nFáza 3",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase3Duration": {
|
||||
"displayText": "Phase 3\nDuration",
|
||||
"displayText": "Trvanie\nFáza 3",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase4Temp": {
|
||||
"displayText": "Phase 4\nTemp",
|
||||
"displayText": "Teplota\nFáza 4",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase4Duration": {
|
||||
"displayText": "Phase 4\nDuration",
|
||||
"displayText": "Trvanie\nFáza 4",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase5Temp": {
|
||||
"displayText": "Phase 5\nTemp",
|
||||
"displayText": "Teplota\nFáza 5",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase5Duration": {
|
||||
"displayText": "Phase 5\nDuration",
|
||||
"displayText": "Trvanie\nFáza 4",
|
||||
"description": ""
|
||||
},
|
||||
"ProfileCooldownSpeed": {
|
||||
"displayText": "Cooldown\nSpeed",
|
||||
"description": "Cooldown at this rate at the end of profile mode (degrees per second)"
|
||||
"displayText": "Rýchlosť\nochladzovania",
|
||||
"description": "Rýchlosť ochladzovania na konci profilového režimu (stupne za sekundu)"
|
||||
},
|
||||
"MotionSensitivity": {
|
||||
"displayText": "Citlivosť\npohybu",
|
||||
@@ -281,15 +281,15 @@
|
||||
},
|
||||
"BluetoothLE": {
|
||||
"displayText": "Bluetooth\n",
|
||||
"description": "Enables BLE"
|
||||
"description": "Zapne BLE"
|
||||
},
|
||||
"PowerLimit": {
|
||||
"displayText": "Obmedzenie\nvýkonu",
|
||||
"description": "Obmedzenie výkonu podľa použitého zdroja (watt)"
|
||||
},
|
||||
"CalibrateCJC": {
|
||||
"displayText": "Calibrate CJC\nat next boot",
|
||||
"description": "At next boot tip Cold Junction Compensation will be calibrated (not required if Delta T is < 5°C)"
|
||||
"displayText": "Kalibrácia CJC\npri nasledujúcom štarte",
|
||||
"description": "Pri nasledujúcom štarte bude kalibrovaná kompenzácia studeného spoja (nie je potrebné ak Delta T je < 5°C)"
|
||||
},
|
||||
"VoltageCalibration": {
|
||||
"displayText": "Kalibrácia\nnap. napätia",
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
"tempUnitFahrenheit": false,
|
||||
"messagesWarn": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration\ndone!"
|
||||
"message": "Kalibrering\nfärdig!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
"message": "Reset OK"
|
||||
"message": "Återställning\nOK"
|
||||
},
|
||||
"SettingsResetMessage": {
|
||||
"message": "Inställningar\nåterställda"
|
||||
@@ -28,16 +28,16 @@
|
||||
"message": "!LÅST!"
|
||||
},
|
||||
"WarningThermalRunaway": {
|
||||
"message": "Thermal\nRunaway"
|
||||
"message": "Termisk\nFlykt"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
"message": "!Spets Kortsluten!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
"message": "Före omstart, säkerställ att spetsen och handtaget är i rumstemperatur!"
|
||||
},
|
||||
"CJCCalibrating": {
|
||||
"message": "calibrating\n"
|
||||
"message": "kalibrerar\n"
|
||||
},
|
||||
"SettingsResetWarning": {
|
||||
"message": "Är du säker på att du vill återställa inställningarna?"
|
||||
@@ -64,16 +64,16 @@
|
||||
"message": "Av"
|
||||
},
|
||||
"ProfilePreheatString": {
|
||||
"message": "Preheat\n"
|
||||
"message": "Förvärmning\n"
|
||||
},
|
||||
"ProfileCooldownString": {
|
||||
"message": "Cooldown\n"
|
||||
"message": "Nedkyldning\n"
|
||||
},
|
||||
"DeviceFailedValidationWarning": {
|
||||
"message": "Your device is most likely a counterfeit!"
|
||||
"message": "Din enhet är sannerligen oäkta!"
|
||||
},
|
||||
"TooHotToStartProfileWarning": {
|
||||
"message": "Too hot to\nstart profile"
|
||||
"message": "För varm för att\nstarta profilen!"
|
||||
}
|
||||
},
|
||||
"characters": {
|
||||
@@ -128,12 +128,12 @@
|
||||
"description": "Maximal QC-spänning enheten skall efterfråga"
|
||||
},
|
||||
"PDNegTimeout": {
|
||||
"displayText": "PD\ntimeout",
|
||||
"description": "PD negotiation timeout in 100ms steps for compatibility with some QC chargers"
|
||||
"displayText": "PD\npauser",
|
||||
"description": "PD förhandlings pauser i 100ms steg för kompatibilitet med vissa PD laddare"
|
||||
},
|
||||
"PDVpdo": {
|
||||
"displayText": "PD\nVPDO",
|
||||
"description": "Enables PPS & EPR modes"
|
||||
"description": "Slår på PPS & EPR lägen"
|
||||
},
|
||||
"BoostTemperature": {
|
||||
"displayText": "Turbo-\ntemp",
|
||||
@@ -156,60 +156,60 @@
|
||||
"description": "Vid lödning, håll nere bägge knappar för att slå på lås (A=Av | T=Bara turbo | F=Fullt lås)"
|
||||
},
|
||||
"ProfilePhases": {
|
||||
"displayText": "Profile\nPhases",
|
||||
"description": "Number of phases in profile mode"
|
||||
"displayText": "Profil-\nfaser",
|
||||
"description": "Antal faser i profil läge"
|
||||
},
|
||||
"ProfilePreheatTemp": {
|
||||
"displayText": "Preheat\nTemp",
|
||||
"description": "Preheat to this temperature at the start of profile mode"
|
||||
"displayText": "Förvärmnings-\ntemp",
|
||||
"description": "Förvärm till denna temperatur i början av provil läget"
|
||||
},
|
||||
"ProfilePreheatSpeed": {
|
||||
"displayText": "Preheat\nSpeed",
|
||||
"description": "Preheat at this rate (degrees per second)"
|
||||
"displayText": "Förvärmnings-\nhastighet",
|
||||
"description": "Förvärm enligt denna hastighet (grader per sekund)"
|
||||
},
|
||||
"ProfilePhase1Temp": {
|
||||
"displayText": "Phase 1\nTemp",
|
||||
"description": "Target temperature for the end of this phase"
|
||||
"displayText": "Fas 1\nTemp",
|
||||
"description": "Måltemperatur i slutet av denna fas"
|
||||
},
|
||||
"ProfilePhase1Duration": {
|
||||
"displayText": "Phase 1\nDuration",
|
||||
"description": "Target duration of this phase (seconds)"
|
||||
"displayText": "Fas 1\nTidslängd",
|
||||
"description": "Mållängd av denna fasen (sekunder)"
|
||||
},
|
||||
"ProfilePhase2Temp": {
|
||||
"displayText": "Phase 2\nTemp",
|
||||
"displayText": "Fas 2\nTemp",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase2Duration": {
|
||||
"displayText": "Phase 2\nDuration",
|
||||
"displayText": "Fas 2\nTidslängd",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase3Temp": {
|
||||
"displayText": "Phase 3\nTemp",
|
||||
"displayText": "Fas 3\nTemp",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase3Duration": {
|
||||
"displayText": "Phase 3\nDuration",
|
||||
"displayText": "Fas 3\nTidslängd",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase4Temp": {
|
||||
"displayText": "Phase 4\nTemp",
|
||||
"displayText": "Fas 4\nTemp",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase4Duration": {
|
||||
"displayText": "Phase 4\nDuration",
|
||||
"displayText": "Fas 4\nTidslängd",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase5Temp": {
|
||||
"displayText": "Phase 5\nTemp",
|
||||
"displayText": "Fas 5\nTemp",
|
||||
"description": ""
|
||||
},
|
||||
"ProfilePhase5Duration": {
|
||||
"displayText": "Phase 5\nDuration",
|
||||
"displayText": "Fas 5\nTidslängd",
|
||||
"description": ""
|
||||
},
|
||||
"ProfileCooldownSpeed": {
|
||||
"displayText": "Cooldown\nSpeed",
|
||||
"description": "Cooldown at this rate at the end of profile mode (degrees per second)"
|
||||
"displayText": "Nedkylnings-\nhastighet",
|
||||
"description": "Kyl ned i denna hastighet i slutet av profilen (grader per sekund)"
|
||||
},
|
||||
"MotionSensitivity": {
|
||||
"displayText": "Rörelse-\nkänslighet",
|
||||
@@ -260,16 +260,16 @@
|
||||
"description": "Loopa animationer i huvudmeny"
|
||||
},
|
||||
"Brightness": {
|
||||
"displayText": "Screen\nbrightness",
|
||||
"description": "Adjust the OLED screen brightness"
|
||||
"displayText": "Skärmens\nLjusstyrka",
|
||||
"description": "Justera OLED skärmens ljusstyrka"
|
||||
},
|
||||
"ColourInversion": {
|
||||
"displayText": "Invert\nscreen",
|
||||
"description": "Invert the OLED screen colors"
|
||||
"displayText": "Invertera\nskärm",
|
||||
"description": "Invertera OLED skärmens färger"
|
||||
},
|
||||
"LOGOTime": {
|
||||
"displayText": "Boot logo\nduration",
|
||||
"description": "Set boot logo duration (s=seconds)"
|
||||
"displayText": "Start logo\nTidslängd",
|
||||
"description": "Sätt uppstartslogotypens tidslängd (s=sekunder)"
|
||||
},
|
||||
"AdvancedIdle": {
|
||||
"displayText": "Detaljerad\nvid inaktiv",
|
||||
@@ -281,31 +281,31 @@
|
||||
},
|
||||
"BluetoothLE": {
|
||||
"displayText": "Bluetooth\n",
|
||||
"description": "Enables BLE"
|
||||
"description": "Tillåter BLE"
|
||||
},
|
||||
"PowerLimit": {
|
||||
"displayText": "Max-\neffekt",
|
||||
"description": "Maximal effekt som enheten kan använda (Watt)"
|
||||
},
|
||||
"CalibrateCJC": {
|
||||
"displayText": "Calibrate CJC\nat next boot",
|
||||
"description": "At next boot tip Cold Junction Compensation will be calibrated (not required if Delta T is < 5°C)"
|
||||
"displayText": "Kalibrera CJC\nnästa uppstart",
|
||||
"description": "Vid nästa uppstart kommer spets Cold Junction Compensation kalibreras (ej nödvändigt om Delta T är < 5°C)"
|
||||
},
|
||||
"VoltageCalibration": {
|
||||
"displayText": "Kalibrera\ninspänning?",
|
||||
"description": "Inspänningskalibrering. Knapparna justerar, håll inne för avslut"
|
||||
},
|
||||
"PowerPulsePower": {
|
||||
"displayText": "Power\npulse",
|
||||
"description": "Intensity of power of keep-awake-pulse (W=watt)"
|
||||
"displayText": "Effekt\npuls",
|
||||
"description": "Intensiteten av effekt för håll-vaken-puls (W=watt)"
|
||||
},
|
||||
"PowerPulseWait": {
|
||||
"displayText": "Power pulse\ndelay",
|
||||
"description": "Delay before keep-awake-pulse is triggered (x 2.5s)"
|
||||
"displayText": "Effekt puls\nfördröjning",
|
||||
"description": "Fördröjning innan håll-vaken-pulsen skickas (x 2.5s)"
|
||||
},
|
||||
"PowerPulseDuration": {
|
||||
"displayText": "Power pulse\nduration",
|
||||
"description": "Keep-awake-pulse duration (x 250ms)"
|
||||
"displayText": "Effekt puls\ntidsmängd",
|
||||
"description": "Håll-vaken-puls varaktighet (x 250ms)"
|
||||
},
|
||||
"SettingsReset": {
|
||||
"displayText": "Fabriks-\ninställ?",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"tempUnitFahrenheit": true,
|
||||
"messagesWarn": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration done!"
|
||||
"message": "校正完成!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
"message": "已重置!"
|
||||
@@ -31,13 +31,13 @@
|
||||
"message": "加热失控"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
"message": "!烙铁头短路!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
"message": "在重启前请确认烙铁头及本体已完全冷却!"
|
||||
},
|
||||
"CJCCalibrating": {
|
||||
"message": "calibrating"
|
||||
"message": "校正中"
|
||||
},
|
||||
"SettingsResetWarning": {
|
||||
"message": "你是否确定要将全部设定重置为默认值?"
|
||||
@@ -133,7 +133,7 @@
|
||||
},
|
||||
"PDVpdo": {
|
||||
"displayText": "PD VPDO",
|
||||
"description": "Enables PPS & EPR modes"
|
||||
"description": "启用PPS和EPR快充支持"
|
||||
},
|
||||
"BoostTemperature": {
|
||||
"displayText": "增热温度",
|
||||
@@ -280,8 +280,8 @@
|
||||
"description": "焊接模式画面以英语小字体显示详请"
|
||||
},
|
||||
"BluetoothLE": {
|
||||
"displayText": "Bluetooth",
|
||||
"description": "Enables BLE"
|
||||
"displayText": "蓝牙",
|
||||
"description": "启用蓝牙支持"
|
||||
},
|
||||
"PowerLimit": {
|
||||
"displayText": "功率限制",
|
||||
@@ -289,7 +289,7 @@
|
||||
},
|
||||
"CalibrateCJC": {
|
||||
"displayText": "校正CJC",
|
||||
"description": "At next boot tip Cold Junction Compensation will be calibrated (not required if Delta T is < 5 C)"
|
||||
"description": "在下次重启时校正烙铁头热电偶冷接点补偿值(CJC)(温差小于5摄氏度时无需校正)"
|
||||
},
|
||||
"VoltageCalibration": {
|
||||
"displayText": "输入电压校正?",
|
||||
@@ -316,4 +316,4 @@
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"tempUnitFahrenheit": true,
|
||||
"messagesWarn": {
|
||||
"CalibrationDone": {
|
||||
"message": "Calibration done!"
|
||||
"message": "校正完成!"
|
||||
},
|
||||
"ResetOKMessage": {
|
||||
"message": "已重設!"
|
||||
@@ -31,13 +31,13 @@
|
||||
"message": "加熱失控"
|
||||
},
|
||||
"WarningTipShorted": {
|
||||
"message": "!Tip Shorted!"
|
||||
"message": "!烙鐵頭短路!"
|
||||
},
|
||||
"SettingsCalibrationWarning": {
|
||||
"message": "Before rebooting, make sure tip & handle are at room temperature!"
|
||||
"message": "在重啟前請確認烙鐵頭及本體已完全冷卻!"
|
||||
},
|
||||
"CJCCalibrating": {
|
||||
"message": "calibrating"
|
||||
"message": "校正中"
|
||||
},
|
||||
"SettingsResetWarning": {
|
||||
"message": "你是否確定要將全部設定重設到預設值?"
|
||||
@@ -133,7 +133,7 @@
|
||||
},
|
||||
"PDVpdo": {
|
||||
"displayText": "PD VPDO",
|
||||
"description": "Enables PPS & EPR modes"
|
||||
"description": "開啟PPS及EPR支援"
|
||||
},
|
||||
"BoostTemperature": {
|
||||
"displayText": "增熱溫度",
|
||||
@@ -280,8 +280,8 @@
|
||||
"description": "於焊接模式畫面以英文小字型顯示詳細資料"
|
||||
},
|
||||
"BluetoothLE": {
|
||||
"displayText": "Bluetooth",
|
||||
"description": "Enables BLE"
|
||||
"displayText": "藍牙",
|
||||
"description": "開啟藍牙支援"
|
||||
},
|
||||
"PowerLimit": {
|
||||
"displayText": "功率限制",
|
||||
@@ -289,7 +289,7 @@
|
||||
},
|
||||
"CalibrateCJC": {
|
||||
"displayText": "校正CJC",
|
||||
"description": "At next boot tip Cold Junction Compensation will be calibrated (not required if Delta T is < 5 C)"
|
||||
"description": "在下次重啟時校正烙鐵頭熱電偶冷接點補償值(CJC)(溫差小於5攝氏度時無需校正)"
|
||||
},
|
||||
"VoltageCalibration": {
|
||||
"displayText": "輸入電壓校正?",
|
||||
@@ -316,4 +316,4 @@
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,12 +36,14 @@ nav:
|
||||
- Startup Logo: Logo.md
|
||||
- Hardware:
|
||||
- Hall Sensor (Pinecil): HallSensor.md
|
||||
- Bluetooth (Pinecil V2): Bluetooth.md
|
||||
- Hardware Notes: Hardware.md
|
||||
- Troubleshooting: Troubleshooting.md
|
||||
- Known Hardware Issues: HardwareIssues.md
|
||||
- Power sources: PowerSources.md
|
||||
- Translations: Translation.md
|
||||
- Development: Development.md
|
||||
- Changelog: History.md
|
||||
|
||||
# Plugins
|
||||
plugins:
|
||||
|
||||
@@ -14,14 +14,13 @@ WORKDIR /build/ironos
|
||||
## - 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_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 diffutils zip"
|
||||
ARG APK_DEV="musl-dev clang bash clang-extra-tools shellcheck"
|
||||
|
||||
# PIP packages to check & test Python code
|
||||
ARG PIP_PKGS='bdflib flake8'
|
||||
# PIP packages to check & test Python code, and generate docs
|
||||
ARG PIP_PKGS='bdflib flake8 pymdown-extensions mkdocs mkdocs-autolinks-plugin mkdocs-awesome-pages-plugin mkdocs-git-revision-date-plugin'
|
||||
|
||||
# Install system packages using alpine package manager
|
||||
RUN apk add --no-cache ${APK_COMPS} ${APK_PYTHON} ${APK_MISC} ${APK_DEV}
|
||||
@@ -32,4 +31,5 @@ RUN python3 -m pip install ${PIP_PKGS}
|
||||
# Git trust to avoid related warning
|
||||
RUN git config --global --add safe.directory /build/ironos
|
||||
|
||||
# Copy the whole source tree working dir into container
|
||||
COPY . /build/ironos
|
||||
|
||||
@@ -17,7 +17,7 @@ usage()
|
||||
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 -e "\tclean - delete created docker image for IronOS & its build cache objects\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"
|
||||
@@ -194,6 +194,7 @@ elif [ "${cmd}" = "build" ]; then
|
||||
docker_cmd="run --rm builder make build-all OUT=${OUT}"
|
||||
elif [ "${cmd}" = "clean" ]; then
|
||||
docker rmi ironos-builder:latest
|
||||
docker system prune --filter label=ironos-builder:latest --force
|
||||
exit "${?}"
|
||||
else
|
||||
usage
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
#include "BSP_Power.h"
|
||||
#include "BSP_QC.h"
|
||||
#include "Defines.h"
|
||||
#include "Types.h"
|
||||
#include "configuration.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* BSP.h -- Board Support
|
||||
*
|
||||
|
||||
@@ -19,9 +19,8 @@ void power_check();
|
||||
// Returns the tip resistance in x10 ohms, so 7.5 = 75; 14=140 etc
|
||||
uint8_t getTipResistanceX10();
|
||||
|
||||
uint8_t getTipThermalMass();
|
||||
uint8_t getTipInertia();
|
||||
|
||||
uint16_t getTipThermalMass();
|
||||
uint16_t getTipInertia();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -472,7 +472,7 @@ uint64_t getDeviceID() {
|
||||
|
||||
uint8_t preStartChecksDone() { return 1; }
|
||||
|
||||
uint8_t getTipThermalMass() { return TIP_THERMAL_MASS; }
|
||||
uint8_t getTipInertia() { return TIP_THERMAL_MASS; }
|
||||
uint16_t getTipThermalMass() { return TIP_THERMAL_MASS; }
|
||||
uint16_t getTipInertia() { return TIP_THERMAL_MASS; }
|
||||
|
||||
void showBootLogo(void) { BootLogo::handleShowingLogo((uint8_t *)FLASH_LOGOADDR); }
|
||||
|
||||
@@ -6,10 +6,12 @@
|
||||
*/
|
||||
#include "Setup.h"
|
||||
#include "TipThermoModel.h"
|
||||
#include "Types.h"
|
||||
#include "Utils.h"
|
||||
#include "configuration.h"
|
||||
extern uint16_t tipSenseResistancex10Ohms;
|
||||
uint32_t TipThermoModel::convertuVToDegC(uint32_t tipuVDelta) {
|
||||
|
||||
extern uint16_t tipSenseResistancex10Ohms;
|
||||
TemperatureType_t TipThermoModel::convertuVToDegC(uint32_t tipuVDelta) {
|
||||
// For the MHP30, we are mimicing the original code and using the resistor fitted to the base of the heater head,
|
||||
// this is measured at boot in pid task and in the disconnected tip check if tip is removed
|
||||
if (tipSenseResistancex10Ohms > 900 && tipSenseResistancex10Ohms <= 1100) {
|
||||
|
||||
@@ -396,7 +396,7 @@ bool isTipShorted() { return tipShorted; }
|
||||
#else
|
||||
bool isTipShorted() { return false; }
|
||||
#endif
|
||||
uint8_t getTipThermalMass() {
|
||||
uint16_t getTipThermalMass() {
|
||||
#ifdef TIP_RESISTANCE_SENSE_Pin
|
||||
if (lastTipResistance >= 80) {
|
||||
return TIP_THERMAL_MASS;
|
||||
@@ -406,7 +406,7 @@ uint8_t getTipThermalMass() {
|
||||
return TIP_THERMAL_MASS;
|
||||
#endif
|
||||
}
|
||||
uint8_t getTipInertia() {
|
||||
uint16_t getTipInertia() {
|
||||
#ifdef TIP_RESISTANCE_SENSE_Pin
|
||||
if (lastTipResistance >= 80) {
|
||||
return TIP_THERMAL_MASS;
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* FRToSI2C.cpp
|
||||
*
|
||||
* Created on: 14Apr.,2018
|
||||
* Author: Ralim
|
||||
*/
|
||||
#include "BSP.h"
|
||||
#include "Setup.h"
|
||||
#include <I2C_Wrapper.hpp>
|
||||
SemaphoreHandle_t FRToSI2C::I2CSemaphore = nullptr;
|
||||
StaticSemaphore_t FRToSI2C::xSemaphoreBuffer;
|
||||
|
||||
void FRToSI2C::CpltCallback() {
|
||||
hi2c1.State = HAL_I2C_STATE_READY; // Force state reset (even if tx error)
|
||||
if (I2CSemaphore) {
|
||||
xSemaphoreGiveFromISR(I2CSemaphore, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
bool FRToSI2C::Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) {
|
||||
|
||||
if (!lock())
|
||||
return false;
|
||||
if (HAL_I2C_Mem_Read(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, pData, Size, 500) != HAL_OK) {
|
||||
|
||||
I2C_Unstick();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
unlock();
|
||||
return true;
|
||||
}
|
||||
bool FRToSI2C::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) { return Mem_Write(address, reg, &data, 1); }
|
||||
|
||||
uint8_t FRToSI2C::I2C_RegisterRead(uint8_t add, uint8_t reg) {
|
||||
uint8_t tx_data[1];
|
||||
Mem_Read(add, reg, tx_data, 1);
|
||||
return tx_data[0];
|
||||
}
|
||||
bool FRToSI2C::Mem_Write(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size) {
|
||||
|
||||
if (!lock())
|
||||
return false;
|
||||
if (HAL_I2C_Mem_Write(&hi2c1, DevAddress, MemAddress, I2C_MEMADD_SIZE_8BIT, pData, Size, 500) != HAL_OK) {
|
||||
|
||||
I2C_Unstick();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FRToSI2C::Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size) {
|
||||
if (!lock())
|
||||
return false;
|
||||
if (HAL_I2C_Master_Transmit_IT(&hi2c1, DevAddress, pData, Size) != HAL_OK) {
|
||||
I2C_Unstick();
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FRToSI2C::probe(uint16_t DevAddress) {
|
||||
if (!lock())
|
||||
return false;
|
||||
uint8_t buffer[1];
|
||||
bool worked = HAL_I2C_Mem_Read(&hi2c1, DevAddress, 0x0F, I2C_MEMADD_SIZE_8BIT, buffer, 1, 1000) == HAL_OK;
|
||||
unlock();
|
||||
return worked;
|
||||
}
|
||||
|
||||
void FRToSI2C::I2C_Unstick() { unstick_I2C(); }
|
||||
|
||||
void FRToSI2C::unlock() { xSemaphoreGive(I2CSemaphore); }
|
||||
|
||||
bool FRToSI2C::lock() { return xSemaphoreTake(I2CSemaphore, (TickType_t)50) == pdTRUE; }
|
||||
|
||||
bool FRToSI2C::writeRegistersBulk(const uint8_t address, const I2C_REG *registers, const uint8_t registersLength) {
|
||||
for (int index = 0; index < registersLength; index++) {
|
||||
if (!I2C_RegisterWrite(address, registers[index].reg, registers[index].val)) {
|
||||
return false;
|
||||
}
|
||||
if (registers[index].pause_ms)
|
||||
delay_ms(registers[index].pause_ms);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -23,12 +23,6 @@ void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *hadc) {
|
||||
}
|
||||
}
|
||||
}
|
||||
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c __unused) { FRToSI2C::CpltCallback(); }
|
||||
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c __unused) { FRToSI2C::CpltCallback(); }
|
||||
void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c __unused) { FRToSI2C::CpltCallback(); }
|
||||
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c __unused) { FRToSI2C::CpltCallback(); }
|
||||
void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c __unused) { FRToSI2C::CpltCallback(); }
|
||||
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c __unused) { FRToSI2C::CpltCallback(); }
|
||||
|
||||
extern osThreadId POWTaskHandle;
|
||||
|
||||
|
||||
@@ -18,12 +18,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *hadc);
|
||||
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c);
|
||||
void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c);
|
||||
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c);
|
||||
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c);
|
||||
void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c);
|
||||
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c);
|
||||
|
||||
void HAL_GPIO_EXTI_Callback(uint16_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -13,10 +13,6 @@ ADC_HandleTypeDef hadc1;
|
||||
ADC_HandleTypeDef hadc2;
|
||||
DMA_HandleTypeDef hdma_adc1;
|
||||
|
||||
I2C_HandleTypeDef hi2c1;
|
||||
DMA_HandleTypeDef hdma_i2c1_rx;
|
||||
DMA_HandleTypeDef hdma_i2c1_tx;
|
||||
|
||||
IWDG_HandleTypeDef hiwdg;
|
||||
TIM_HandleTypeDef htimADC;
|
||||
TIM_HandleTypeDef htimTip;
|
||||
@@ -27,7 +23,6 @@ uint16_t ADCReadings[ADC_SAMPLES]; // Used to store the adc readings for the han
|
||||
// Functions
|
||||
static void SystemClock_Config(void);
|
||||
static void MX_ADC1_Init(void);
|
||||
static void MX_I2C1_Init(void);
|
||||
static void MX_IWDG_Init(void);
|
||||
static void MX_TIP_CONTROL_TIMER_Init(void);
|
||||
static void MX_ADC_CONTROL_TIMER_Init(void);
|
||||
@@ -45,9 +40,6 @@ void Setup_HAL() {
|
||||
|
||||
MX_GPIO_Init();
|
||||
MX_DMA_Init();
|
||||
#ifndef I2C_SOFT_BUS_1
|
||||
MX_I2C1_Init();
|
||||
#endif
|
||||
MX_ADC1_Init();
|
||||
MX_ADC2_Init();
|
||||
MX_TIP_CONTROL_TIMER_Init();
|
||||
@@ -277,20 +269,6 @@ static void MX_ADC2_Init(void) {
|
||||
;
|
||||
}
|
||||
}
|
||||
/* I2C1 init function */
|
||||
static void MX_I2C1_Init(void) {
|
||||
hi2c1.Instance = I2C1;
|
||||
hi2c1.Init.ClockSpeed = 75000;
|
||||
// OLED doesnt handle >100k when its asleep (off).
|
||||
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
|
||||
hi2c1.Init.OwnAddress1 = 0;
|
||||
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
|
||||
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
|
||||
hi2c1.Init.OwnAddress2 = 0;
|
||||
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
|
||||
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
|
||||
HAL_I2C_Init(&hi2c1);
|
||||
}
|
||||
|
||||
/* IWDG init function */
|
||||
static void MX_IWDG_Init(void) {
|
||||
|
||||
@@ -18,10 +18,6 @@ extern ADC_HandleTypeDef hadc1;
|
||||
extern ADC_HandleTypeDef hadc2;
|
||||
extern DMA_HandleTypeDef hdma_adc1;
|
||||
|
||||
extern DMA_HandleTypeDef hdma_i2c1_rx;
|
||||
extern DMA_HandleTypeDef hdma_i2c1_tx;
|
||||
extern I2C_HandleTypeDef hi2c1;
|
||||
|
||||
extern IWDG_HandleTypeDef hiwdg;
|
||||
|
||||
extern TIM_HandleTypeDef htimADC;
|
||||
|
||||
@@ -127,4 +127,4 @@ const int32_t uVtoDegC[] = {
|
||||
#endif
|
||||
const int uVtoDegCItems = sizeof(uVtoDegC) / (2 * sizeof(uVtoDegC[0]));
|
||||
|
||||
uint32_t TipThermoModel::convertuVToDegC(uint32_t tipuVDelta) { return Utils::InterpolateLookupTable(uVtoDegC, uVtoDegCItems, tipuVDelta); }
|
||||
TemperatureType_t TipThermoModel::convertuVToDegC(uint32_t tipuVDelta) { return Utils::InterpolateLookupTable(uVtoDegC, uVtoDegCItems, tipuVDelta); }
|
||||
|
||||
@@ -1,639 +1,5 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_i2c.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header file of I2C HAL module.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __STM32F1xx_HAL_I2C_H
|
||||
#define __STM32F1xx_HAL_I2C_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal_def.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup I2C
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/** @defgroup I2C_Exported_Types I2C Exported Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief I2C Configuration Structure definition
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t ClockSpeed; /*!< Specifies the clock frequency.
|
||||
This parameter must be set to a value lower than 400kHz */
|
||||
|
||||
uint32_t DutyCycle; /*!< Specifies the I2C fast mode duty cycle.
|
||||
This parameter can be a value of @ref I2C_duty_cycle_in_fast_mode */
|
||||
|
||||
uint32_t OwnAddress1; /*!< Specifies the first device own address.
|
||||
This parameter can be a 7-bit or 10-bit address. */
|
||||
|
||||
uint32_t AddressingMode; /*!< Specifies if 7-bit or 10-bit addressing mode is selected.
|
||||
This parameter can be a value of @ref I2C_addressing_mode */
|
||||
|
||||
uint32_t DualAddressMode; /*!< Specifies if dual addressing mode is selected.
|
||||
This parameter can be a value of @ref I2C_dual_addressing_mode */
|
||||
|
||||
uint32_t OwnAddress2; /*!< Specifies the second device own address if dual addressing mode is selected
|
||||
This parameter can be a 7-bit address. */
|
||||
|
||||
uint32_t GeneralCallMode; /*!< Specifies if general call mode is selected.
|
||||
This parameter can be a value of @ref I2C_general_call_addressing_mode */
|
||||
|
||||
uint32_t NoStretchMode; /*!< Specifies if nostretch mode is selected.
|
||||
This parameter can be a value of @ref I2C_nostretch_mode */
|
||||
|
||||
} I2C_InitTypeDef;
|
||||
|
||||
/**
|
||||
* @brief HAL State structure definition
|
||||
* @note HAL I2C State value coding follow below described bitmap :
|
||||
* b7-b6 Error information
|
||||
* 00 : No Error
|
||||
* 01 : Abort (Abort user request on going)
|
||||
* 10 : Timeout
|
||||
* 11 : Error
|
||||
* b5 IP initilisation status
|
||||
* 0 : Reset (IP not initialized)
|
||||
* 1 : Init done (IP initialized and ready to use. HAL I2C Init function called)
|
||||
* b4 (not used)
|
||||
* x : Should be set to 0
|
||||
* b3
|
||||
* 0 : Ready or Busy (No Listen mode ongoing)
|
||||
* 1 : Listen (IP in Address Listen Mode)
|
||||
* b2 Intrinsic process state
|
||||
* 0 : Ready
|
||||
* 1 : Busy (IP busy with some configuration or internal operations)
|
||||
* b1 Rx state
|
||||
* 0 : Ready (no Rx operation ongoing)
|
||||
* 1 : Busy (Rx operation ongoing)
|
||||
* b0 Tx state
|
||||
* 0 : Ready (no Tx operation ongoing)
|
||||
* 1 : Busy (Tx operation ongoing)
|
||||
*/
|
||||
typedef enum {
|
||||
HAL_I2C_STATE_RESET = 0x00U, /*!< Peripheral is not yet Initialized */
|
||||
HAL_I2C_STATE_READY = 0x20U, /*!< Peripheral Initialized and ready for use */
|
||||
HAL_I2C_STATE_BUSY = 0x24U, /*!< An internal process is ongoing */
|
||||
HAL_I2C_STATE_BUSY_TX = 0x21U, /*!< Data Transmission process is ongoing */
|
||||
HAL_I2C_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing */
|
||||
HAL_I2C_STATE_LISTEN = 0x28U, /*!< Address Listen Mode is ongoing */
|
||||
HAL_I2C_STATE_BUSY_TX_LISTEN = 0x29U, /*!< Address Listen Mode and Data Transmission
|
||||
process is ongoing */
|
||||
HAL_I2C_STATE_BUSY_RX_LISTEN = 0x2AU, /*!< Address Listen Mode and Data Reception
|
||||
process is ongoing */
|
||||
HAL_I2C_STATE_ABORT = 0x60U, /*!< Abort user request ongoing */
|
||||
HAL_I2C_STATE_TIMEOUT = 0xA0U, /*!< Timeout state */
|
||||
HAL_I2C_STATE_ERROR = 0xE0U /*!< Error */
|
||||
|
||||
} HAL_I2C_StateTypeDef;
|
||||
|
||||
/**
|
||||
* @brief HAL Mode structure definition
|
||||
* @note HAL I2C Mode value coding follow below described bitmap :
|
||||
* b7 (not used)
|
||||
* x : Should be set to 0
|
||||
* b6
|
||||
* 0 : None
|
||||
* 1 : Memory (HAL I2C communication is in Memory Mode)
|
||||
* b5
|
||||
* 0 : None
|
||||
* 1 : Slave (HAL I2C communication is in Slave Mode)
|
||||
* b4
|
||||
* 0 : None
|
||||
* 1 : Master (HAL I2C communication is in Master Mode)
|
||||
* b3-b2-b1-b0 (not used)
|
||||
* xxxx : Should be set to 0000
|
||||
*/
|
||||
typedef enum {
|
||||
HAL_I2C_MODE_NONE = 0x00U, /*!< No I2C communication on going */
|
||||
HAL_I2C_MODE_MASTER = 0x10U, /*!< I2C communication is in Master Mode */
|
||||
HAL_I2C_MODE_SLAVE = 0x20U, /*!< I2C communication is in Slave Mode */
|
||||
HAL_I2C_MODE_MEM = 0x40U /*!< I2C communication is in Memory Mode */
|
||||
|
||||
} HAL_I2C_ModeTypeDef;
|
||||
|
||||
/**
|
||||
* @brief I2C handle Structure definition
|
||||
*/
|
||||
typedef struct {
|
||||
I2C_TypeDef *Instance; /*!< I2C registers base address */
|
||||
|
||||
I2C_InitTypeDef Init; /*!< I2C communication parameters */
|
||||
|
||||
uint8_t *pBuffPtr; /*!< Pointer to I2C transfer buffer */
|
||||
|
||||
uint16_t XferSize; /*!< I2C transfer size */
|
||||
|
||||
__IO uint16_t XferCount; /*!< I2C transfer counter */
|
||||
|
||||
__IO uint32_t XferOptions; /*!< I2C transfer options */
|
||||
|
||||
__IO uint32_t PreviousState; /*!< I2C communication Previous state and mode
|
||||
context for internal usage */
|
||||
|
||||
DMA_HandleTypeDef *hdmatx; /*!< I2C Tx DMA handle parameters */
|
||||
|
||||
DMA_HandleTypeDef *hdmarx; /*!< I2C Rx DMA handle parameters */
|
||||
|
||||
HAL_LockTypeDef Lock; /*!< I2C locking object */
|
||||
|
||||
__IO HAL_I2C_StateTypeDef State; /*!< I2C communication state */
|
||||
|
||||
__IO HAL_I2C_ModeTypeDef Mode; /*!< I2C communication mode */
|
||||
|
||||
__IO uint32_t ErrorCode; /*!< I2C Error code */
|
||||
|
||||
__IO uint32_t Devaddress; /*!< I2C Target device address */
|
||||
|
||||
__IO uint32_t Memaddress; /*!< I2C Target memory address */
|
||||
|
||||
__IO uint32_t MemaddSize; /*!< I2C Target memory address size */
|
||||
|
||||
__IO uint32_t EventCount; /*!< I2C Event counter */
|
||||
|
||||
} I2C_HandleTypeDef;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/** @defgroup I2C_Exported_Constants I2C Exported Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup I2C_Error_Code I2C Error Code
|
||||
* @brief I2C Error Code
|
||||
* @{
|
||||
*/
|
||||
#define HAL_I2C_ERROR_NONE 0x00000000U /*!< No error */
|
||||
#define HAL_I2C_ERROR_BERR 0x00000001U /*!< BERR error */
|
||||
#define HAL_I2C_ERROR_ARLO 0x00000002U /*!< ARLO error */
|
||||
#define HAL_I2C_ERROR_AF 0x00000004U /*!< AF error */
|
||||
#define HAL_I2C_ERROR_OVR 0x00000008U /*!< OVR error */
|
||||
#define HAL_I2C_ERROR_DMA 0x00000010U /*!< DMA transfer error */
|
||||
#define HAL_I2C_ERROR_TIMEOUT 0x00000020U /*!< Timeout Error */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup I2C_duty_cycle_in_fast_mode I2C duty cycle in fast mode
|
||||
* @{
|
||||
*/
|
||||
#define I2C_DUTYCYCLE_2 0x00000000U
|
||||
#define I2C_DUTYCYCLE_16_9 I2C_CCR_DUTY
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup I2C_addressing_mode I2C addressing mode
|
||||
* @{
|
||||
*/
|
||||
#define I2C_ADDRESSINGMODE_7BIT 0x00004000U
|
||||
// #define I2C_ADDRESSINGMODE_10BIT (I2C_OAR1_ADDMODE | 0x00004000U)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup I2C_dual_addressing_mode I2C dual addressing mode
|
||||
* @{
|
||||
*/
|
||||
#define I2C_DUALADDRESS_DISABLE 0x00000000U
|
||||
#define I2C_DUALADDRESS_ENABLE I2C_OAR2_ENDUAL
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup I2C_general_call_addressing_mode I2C general call addressing mode
|
||||
* @{
|
||||
*/
|
||||
#define I2C_GENERALCALL_DISABLE 0x00000000U
|
||||
#define I2C_GENERALCALL_ENABLE I2C_CR1_ENGC
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup I2C_nostretch_mode I2C nostretch mode
|
||||
* @{
|
||||
*/
|
||||
#define I2C_NOSTRETCH_DISABLE 0x00000000U
|
||||
#define I2C_NOSTRETCH_ENABLE I2C_CR1_NOSTRETCH
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup I2C_Memory_Address_Size I2C Memory Address Size
|
||||
* @{
|
||||
*/
|
||||
#define I2C_MEMADD_SIZE_8BIT 0x00000001U
|
||||
#define I2C_MEMADD_SIZE_16BIT 0x00000010U
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup I2C_XferDirection_definition I2C XferDirection definition
|
||||
* @{
|
||||
*/
|
||||
#define I2C_DIRECTION_RECEIVE 0x00000000U
|
||||
#define I2C_DIRECTION_TRANSMIT 0x00000001U
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup I2C_XferOptions_definition I2C XferOptions definition
|
||||
* @{
|
||||
*/
|
||||
#define I2C_FIRST_FRAME 0x00000001U
|
||||
#define I2C_NEXT_FRAME 0x00000002U
|
||||
#define I2C_FIRST_AND_LAST_FRAME 0x00000004U
|
||||
#define I2C_LAST_FRAME 0x00000008U
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup I2C_Interrupt_configuration_definition I2C Interrupt configuration definition
|
||||
* @{
|
||||
*/
|
||||
#define I2C_IT_BUF I2C_CR2_ITBUFEN
|
||||
#define I2C_IT_EVT I2C_CR2_ITEVTEN
|
||||
#define I2C_IT_ERR I2C_CR2_ITERREN
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup I2C_Flag_definition I2C Flag definition
|
||||
* @{
|
||||
*/
|
||||
#define I2C_FLAG_SMBALERT 0x00018000U
|
||||
#define I2C_FLAG_TIMEOUT 0x00014000U
|
||||
#define I2C_FLAG_PECERR 0x00011000U
|
||||
#define I2C_FLAG_OVR 0x00010800U
|
||||
#define I2C_FLAG_AF 0x00010400U
|
||||
#define I2C_FLAG_ARLO 0x00010200U
|
||||
#define I2C_FLAG_BERR 0x00010100U
|
||||
#define I2C_FLAG_TXE 0x00010080U
|
||||
#define I2C_FLAG_RXNE 0x00010040U
|
||||
#define I2C_FLAG_STOPF 0x00010010U
|
||||
// #define I2C_FLAG_ADD10 0x00010008U
|
||||
#define I2C_FLAG_BTF 0x00010004U
|
||||
#define I2C_FLAG_ADDR 0x00010002U
|
||||
#define I2C_FLAG_SB 0x00010001U
|
||||
#define I2C_FLAG_DUALF 0x00100080U
|
||||
#define I2C_FLAG_SMBHOST 0x00100040U
|
||||
#define I2C_FLAG_SMBDEFAULT 0x00100020U
|
||||
#define I2C_FLAG_GENCALL 0x00100010U
|
||||
#define I2C_FLAG_TRA 0x00100004U
|
||||
#define I2C_FLAG_BUSY 0x00100002U
|
||||
#define I2C_FLAG_MSL 0x00100001U
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/** @defgroup I2C_Exported_Macros I2C Exported Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @brief Reset I2C handle state
|
||||
* @param __HANDLE__: specifies the I2C Handle.
|
||||
* This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral.
|
||||
* @retval None
|
||||
*/
|
||||
#define __HAL_I2C_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_I2C_STATE_RESET)
|
||||
|
||||
/** @brief Enable or disable the specified I2C interrupts.
|
||||
* @param __HANDLE__: specifies the I2C Handle.
|
||||
* This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral.
|
||||
* @param __INTERRUPT__: specifies the interrupt source to enable or disable.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg I2C_IT_BUF: Buffer interrupt enable
|
||||
* @arg I2C_IT_EVT: Event interrupt enable
|
||||
* @arg I2C_IT_ERR: Error interrupt enable
|
||||
* @retval None
|
||||
*/
|
||||
#define __HAL_I2C_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR2 |= (__INTERRUPT__))
|
||||
#define __HAL_I2C_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR2 &= (~(__INTERRUPT__)))
|
||||
|
||||
/** @brief Checks if the specified I2C interrupt source is enabled or disabled.
|
||||
* @param __HANDLE__: specifies the I2C Handle.
|
||||
* This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral.
|
||||
* @param __INTERRUPT__: specifies the I2C interrupt source to check.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg I2C_IT_BUF: Buffer interrupt enable
|
||||
* @arg I2C_IT_EVT: Event interrupt enable
|
||||
* @arg I2C_IT_ERR: Error interrupt enable
|
||||
* @retval The new state of __INTERRUPT__ (TRUE or FALSE).
|
||||
*/
|
||||
#define __HAL_I2C_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->CR2 & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET)
|
||||
|
||||
/** @brief Checks whether the specified I2C flag is set or not.
|
||||
* @param __HANDLE__: specifies the I2C Handle.
|
||||
* This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral.
|
||||
* @param __FLAG__: specifies the flag to check.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg I2C_FLAG_SMBALERT: SMBus Alert flag
|
||||
* @arg I2C_FLAG_TIMEOUT: Timeout or Tlow error flag
|
||||
* @arg I2C_FLAG_PECERR: PEC error in reception flag
|
||||
* @arg I2C_FLAG_OVR: Overrun/Underrun flag
|
||||
* @arg I2C_FLAG_AF: Acknowledge failure flag
|
||||
* @arg I2C_FLAG_ARLO: Arbitration lost flag
|
||||
* @arg I2C_FLAG_BERR: Bus error flag
|
||||
* @arg I2C_FLAG_TXE: Data register empty flag
|
||||
* @arg I2C_FLAG_RXNE: Data register not empty flag
|
||||
* @arg I2C_FLAG_STOPF: Stop detection flag
|
||||
* @arg I2C_FLAG_ADD10: 10-bit header sent flag
|
||||
* @arg I2C_FLAG_BTF: Byte transfer finished flag
|
||||
* @arg I2C_FLAG_ADDR: Address sent flag
|
||||
* Address matched flag
|
||||
* @arg I2C_FLAG_SB: Start bit flag
|
||||
* @arg I2C_FLAG_DUALF: Dual flag
|
||||
* @arg I2C_FLAG_SMBHOST: SMBus host header
|
||||
* @arg I2C_FLAG_SMBDEFAULT: SMBus default header
|
||||
* @arg I2C_FLAG_GENCALL: General call header flag
|
||||
* @arg I2C_FLAG_TRA: Transmitter/Receiver flag
|
||||
* @arg I2C_FLAG_BUSY: Bus busy flag
|
||||
* @arg I2C_FLAG_MSL: Master/Slave flag
|
||||
* @retval The new state of __FLAG__ (TRUE or FALSE).
|
||||
*/
|
||||
#define __HAL_I2C_GET_FLAG(__HANDLE__, __FLAG__) \
|
||||
((((uint8_t)((__FLAG__) >> 16U)) == 0x01U) ? ((((__HANDLE__)->Instance->SR1) & ((__FLAG__)&I2C_FLAG_MASK)) == ((__FLAG__)&I2C_FLAG_MASK)) \
|
||||
: ((((__HANDLE__)->Instance->SR2) & ((__FLAG__)&I2C_FLAG_MASK)) == ((__FLAG__)&I2C_FLAG_MASK)))
|
||||
|
||||
/** @brief Clears the I2C pending flags which are cleared by writing 0 in a specific bit.
|
||||
* @param __HANDLE__: specifies the I2C Handle.
|
||||
* This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral.
|
||||
* @param __FLAG__: specifies the flag to clear.
|
||||
* This parameter can be any combination of the following values:
|
||||
* @arg I2C_FLAG_SMBALERT: SMBus Alert flag
|
||||
* @arg I2C_FLAG_TIMEOUT: Timeout or Tlow error flag
|
||||
* @arg I2C_FLAG_PECERR: PEC error in reception flag
|
||||
* @arg I2C_FLAG_OVR: Overrun/Underrun flag (Slave mode)
|
||||
* @arg I2C_FLAG_AF: Acknowledge failure flag
|
||||
* @arg I2C_FLAG_ARLO: Arbitration lost flag (Master mode)
|
||||
* @arg I2C_FLAG_BERR: Bus error flag
|
||||
* @retval None
|
||||
*/
|
||||
#define __HAL_I2C_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->SR1 = ~((__FLAG__)&I2C_FLAG_MASK))
|
||||
|
||||
/** @brief Clears the I2C ADDR pending flag.
|
||||
* @param __HANDLE__: specifies the I2C Handle.
|
||||
* This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral.
|
||||
* @retval None
|
||||
*/
|
||||
#define __HAL_I2C_CLEAR_ADDRFLAG(__HANDLE__) \
|
||||
do { \
|
||||
__IO uint32_t tmpreg = 0x00U; \
|
||||
tmpreg = (__HANDLE__)->Instance->SR1; \
|
||||
tmpreg = (__HANDLE__)->Instance->SR2; \
|
||||
UNUSED(tmpreg); \
|
||||
} while (0U)
|
||||
|
||||
/** @brief Clears the I2C STOPF pending flag.
|
||||
* @param __HANDLE__: specifies the I2C Handle.
|
||||
* This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral.
|
||||
* @retval None
|
||||
*/
|
||||
#define __HAL_I2C_CLEAR_STOPFLAG(__HANDLE__) \
|
||||
do { \
|
||||
__IO uint32_t tmpreg = 0x00U; \
|
||||
tmpreg = (__HANDLE__)->Instance->SR1; \
|
||||
(__HANDLE__)->Instance->CR1 |= I2C_CR1_PE; \
|
||||
UNUSED(tmpreg); \
|
||||
} while (0U)
|
||||
|
||||
/** @brief Enable the I2C peripheral.
|
||||
* @param __HANDLE__: specifies the I2C Handle.
|
||||
* This parameter can be I2Cx where x: 1 or 2 to select the I2C peripheral.
|
||||
* @retval None
|
||||
*/
|
||||
#define __HAL_I2C_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 |= I2C_CR1_PE)
|
||||
|
||||
/** @brief Disable the I2C peripheral.
|
||||
* @param __HANDLE__: specifies the I2C Handle.
|
||||
* This parameter can be I2Cx where x: 1 or 2 to select the I2C peripheral.
|
||||
* @retval None
|
||||
*/
|
||||
#define __HAL_I2C_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 &= ~I2C_CR1_PE)
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup I2C_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup I2C_Exported_Functions_Group1
|
||||
* @{
|
||||
*/
|
||||
/* Initialization/de-initialization functions **********************************/
|
||||
HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c);
|
||||
HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c);
|
||||
void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c);
|
||||
void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup I2C_Exported_Functions_Group2
|
||||
* @{
|
||||
*/
|
||||
/* I/O operation functions *****************************************************/
|
||||
/******* Blocking mode: Polling */
|
||||
HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
|
||||
HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
|
||||
HAL_StatusTypeDef HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout);
|
||||
HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout);
|
||||
HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);
|
||||
HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);
|
||||
HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout);
|
||||
|
||||
/******* Non-Blocking mode: Interrupt */
|
||||
HAL_StatusTypeDef HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size);
|
||||
HAL_StatusTypeDef HAL_I2C_Master_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size);
|
||||
HAL_StatusTypeDef HAL_I2C_Slave_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size);
|
||||
HAL_StatusTypeDef HAL_I2C_Slave_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size);
|
||||
HAL_StatusTypeDef HAL_I2C_Mem_Write_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size);
|
||||
HAL_StatusTypeDef HAL_I2C_Mem_Read_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size);
|
||||
|
||||
HAL_StatusTypeDef HAL_I2C_Master_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions);
|
||||
HAL_StatusTypeDef HAL_I2C_Master_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions);
|
||||
HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions);
|
||||
HAL_StatusTypeDef HAL_I2C_Slave_Sequential_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions);
|
||||
HAL_StatusTypeDef HAL_I2C_Master_Abort_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress);
|
||||
HAL_StatusTypeDef HAL_I2C_EnableListen_IT(I2C_HandleTypeDef *hi2c);
|
||||
HAL_StatusTypeDef HAL_I2C_DisableListen_IT(I2C_HandleTypeDef *hi2c);
|
||||
|
||||
/******* Non-Blocking mode: DMA */
|
||||
HAL_StatusTypeDef HAL_I2C_Master_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size);
|
||||
HAL_StatusTypeDef HAL_I2C_Master_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size);
|
||||
HAL_StatusTypeDef HAL_I2C_Slave_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size);
|
||||
HAL_StatusTypeDef HAL_I2C_Slave_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size);
|
||||
HAL_StatusTypeDef HAL_I2C_Mem_Write_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size);
|
||||
HAL_StatusTypeDef HAL_I2C_Mem_Read_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size);
|
||||
|
||||
/******* I2C IRQHandler and Callbacks used in non blocking modes (Interrupt and DMA) */
|
||||
void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c);
|
||||
void HAL_I2C_ER_IRQHandler(I2C_HandleTypeDef *hi2c);
|
||||
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c);
|
||||
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c);
|
||||
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c);
|
||||
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c);
|
||||
void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode);
|
||||
void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c);
|
||||
void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c);
|
||||
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c);
|
||||
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c);
|
||||
void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup I2C_Exported_Functions_Group3
|
||||
* @{
|
||||
*/
|
||||
/* Peripheral State, Mode and Errors functions *********************************/
|
||||
HAL_I2C_StateTypeDef HAL_I2C_GetState(I2C_HandleTypeDef *hi2c);
|
||||
HAL_I2C_ModeTypeDef HAL_I2C_GetMode(I2C_HandleTypeDef *hi2c);
|
||||
uint32_t HAL_I2C_GetError(I2C_HandleTypeDef *hi2c);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/** @defgroup I2C_Private_Constants I2C Private Constants
|
||||
* @{
|
||||
*/
|
||||
#define I2C_FLAG_MASK 0x0000FFFFU
|
||||
#define I2C_MIN_PCLK_FREQ_STANDARD 2000000U /*!< 2 MHz */
|
||||
#define I2C_MIN_PCLK_FREQ_FAST 4000000U /*!< 4 MHz */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/** @defgroup I2C_Private_Macros I2C Private Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define I2C_MIN_PCLK_FREQ(__PCLK__, __SPEED__) (((__SPEED__) <= 100000U) ? ((__PCLK__) < I2C_MIN_PCLK_FREQ_STANDARD) : ((__PCLK__) < I2C_MIN_PCLK_FREQ_FAST))
|
||||
#define I2C_CCR_CALCULATION(__PCLK__, __SPEED__, __COEFF__) (((((__PCLK__)-1U) / ((__SPEED__) * (__COEFF__))) + 1U) & I2C_CCR_CCR)
|
||||
#define I2C_FREQRANGE(__PCLK__) ((__PCLK__) / 1000000U)
|
||||
#define I2C_RISE_TIME(__FREQRANGE__, __SPEED__) (((__SPEED__) <= 100000U) ? ((__FREQRANGE__) + 1U) : ((((__FREQRANGE__)*300U) / 1000U) + 1U))
|
||||
#define I2C_SPEED_STANDARD(__PCLK__, __SPEED__) ((I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 2U) < 4U) ? 4U : I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 2U))
|
||||
#define I2C_SPEED_FAST(__PCLK__, __SPEED__, __DUTYCYCLE__) \
|
||||
(((__DUTYCYCLE__) == I2C_DUTYCYCLE_2) ? I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 3U) : (I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 25U) | I2C_DUTYCYCLE_16_9))
|
||||
#define I2C_SPEED(__PCLK__, __SPEED__, __DUTYCYCLE__) \
|
||||
(((__SPEED__) <= 100000U) ? (I2C_SPEED_STANDARD((__PCLK__), (__SPEED__))) \
|
||||
: ((I2C_SPEED_FAST((__PCLK__), (__SPEED__), (__DUTYCYCLE__)) & I2C_CCR_CCR) == 0U) ? 1U \
|
||||
: ((I2C_SPEED_FAST((__PCLK__), (__SPEED__), (__DUTYCYCLE__))) | I2C_CCR_FS))
|
||||
|
||||
#define I2C_7BIT_ADD_WRITE(__ADDRESS__) ((uint8_t)((__ADDRESS__) & (~I2C_OAR1_ADD0)))
|
||||
#define I2C_7BIT_ADD_READ(__ADDRESS__) ((uint8_t)((__ADDRESS__) | I2C_OAR1_ADD0))
|
||||
|
||||
#define I2C_10BIT_ADDRESS(__ADDRESS__) ((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)(0x00FFU))))
|
||||
#define I2C_10BIT_HEADER_WRITE(__ADDRESS__) ((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)(0x0300U))) >> 7U) | (uint16_t)(0x00F0U))))
|
||||
#define I2C_10BIT_HEADER_READ(__ADDRESS__) ((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)(0x0300U))) >> 7U) | (uint16_t)(0x00F1U))))
|
||||
|
||||
#define I2C_MEM_ADD_MSB(__ADDRESS__) ((uint8_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)(0xFF00U))) >> 8U)))
|
||||
#define I2C_MEM_ADD_LSB(__ADDRESS__) ((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)(0x00FFU))))
|
||||
|
||||
/** @defgroup I2C_IS_RTC_Definitions I2C Private macros to check input parameters
|
||||
* @{
|
||||
*/
|
||||
#define IS_I2C_DUTY_CYCLE(CYCLE) (((CYCLE) == I2C_DUTYCYCLE_2) || ((CYCLE) == I2C_DUTYCYCLE_16_9))
|
||||
#define IS_I2C_ADDRESSING_MODE(ADDRESS) (((ADDRESS) == I2C_ADDRESSINGMODE_7BIT) || ((ADDRESS) == I2C_ADDRESSINGMODE_10BIT))
|
||||
#define IS_I2C_DUAL_ADDRESS(ADDRESS) (((ADDRESS) == I2C_DUALADDRESS_DISABLE) || ((ADDRESS) == I2C_DUALADDRESS_ENABLE))
|
||||
#define IS_I2C_GENERAL_CALL(CALL) (((CALL) == I2C_GENERALCALL_DISABLE) || ((CALL) == I2C_GENERALCALL_ENABLE))
|
||||
#define IS_I2C_NO_STRETCH(STRETCH) (((STRETCH) == I2C_NOSTRETCH_DISABLE) || ((STRETCH) == I2C_NOSTRETCH_ENABLE))
|
||||
#define IS_I2C_MEMADD_SIZE(SIZE) (((SIZE) == I2C_MEMADD_SIZE_8BIT) || ((SIZE) == I2C_MEMADD_SIZE_16BIT))
|
||||
#define IS_I2C_CLOCK_SPEED(SPEED) (((SPEED) > 0) && ((SPEED) <= 400000U))
|
||||
#define IS_I2C_OWN_ADDRESS1(ADDRESS1) (((ADDRESS1) & (uint32_t)(0xFFFFFC00U)) == 0U)
|
||||
#define IS_I2C_OWN_ADDRESS2(ADDRESS2) (((ADDRESS2) & (uint32_t)(0xFFFFFF01U)) == 0U)
|
||||
#define IS_I2C_TRANSFER_OPTIONS_REQUEST(REQUEST) (((REQUEST) == I2C_FIRST_FRAME) || ((REQUEST) == I2C_NEXT_FRAME) || ((REQUEST) == I2C_FIRST_AND_LAST_FRAME) || ((REQUEST) == I2C_LAST_FRAME))
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/** @defgroup I2C_Private_Functions I2C Private Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __STM32F1xx_HAL_I2C_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -86,7 +86,7 @@
|
||||
#define POWER_PULSE_DEFAULT 0
|
||||
#else
|
||||
#define POWER_PULSE_DEFAULT 5
|
||||
#endif /* TS100 */
|
||||
#endif /* TS100 */
|
||||
#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
|
||||
|
||||
@@ -172,6 +172,9 @@
|
||||
#define TIP_RESISTANCE 75 // x10 ohms, 7.5 typical for ts100 tips
|
||||
|
||||
#define POW_DC
|
||||
#define I2C_SOFT_BUS_1 1
|
||||
#define OLED_I2CBB1 1
|
||||
#define ACCEL_I2CBB1 1
|
||||
|
||||
#define TEMP_TMP36
|
||||
#endif /* TS100 */
|
||||
@@ -234,6 +237,9 @@
|
||||
#define POW_QC
|
||||
|
||||
#define TEMP_TMP36
|
||||
#define I2C_SOFT_BUS_1 1
|
||||
#define OLED_I2CBB1 1
|
||||
#define ACCEL_I2CBB1 1
|
||||
#endif /* TS80 */
|
||||
|
||||
#ifdef MODEL_TS80P
|
||||
@@ -248,6 +254,9 @@
|
||||
#define POW_QC 1
|
||||
#define TEMP_NTC
|
||||
#define I2C_SOFT_BUS_2 1
|
||||
#define I2C_SOFT_BUS_1 1
|
||||
#define OLED_I2CBB1 1
|
||||
#define ACCEL_I2CBB1 1
|
||||
#define SC7_ORI_FLIP
|
||||
#endif /* TS80P */
|
||||
|
||||
@@ -255,8 +264,8 @@
|
||||
#define FLASH_LOGOADDR (0x08000000 + (126 * 1024))
|
||||
#define SETTINGS_START_PAGE (0x08000000 + (127 * 1024))
|
||||
#else
|
||||
#define FLASH_LOGOADDR (0x08000000 + (62 * 1024))
|
||||
#define SETTINGS_START_PAGE (0x08000000 + (63 * 1024))
|
||||
#define FLASH_LOGOADDR (0x08000000 + (62 * 1024))
|
||||
#define SETTINGS_START_PAGE (0x08000000 + (63 * 1024))
|
||||
#endif /* TS101 */
|
||||
|
||||
#endif /* CONFIGURATION_H_ */
|
||||
|
||||
@@ -25,7 +25,4 @@ void preRToSInit() {
|
||||
#ifdef I2C_SOFT_BUS_1
|
||||
I2CBB1::init();
|
||||
#endif
|
||||
|
||||
/* Init the IPC objects */
|
||||
FRToSI2C::FRToSInit();
|
||||
}
|
||||
|
||||
@@ -81,55 +81,6 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc) {
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c) {
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
/**I2C1 GPIO Configuration
|
||||
PB6 ------> I2C1_SCL
|
||||
PB7 ------> I2C1_SDA
|
||||
*/
|
||||
GPIO_InitStruct.Pin = SCL_Pin | SDA_Pin;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
HAL_GPIO_Init(SCL_GPIO_Port, &GPIO_InitStruct);
|
||||
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_I2C1_CLK_ENABLE();
|
||||
/* I2C1 DMA Init */
|
||||
/* I2C1_RX Init */
|
||||
hdma_i2c1_rx.Instance = DMA1_Channel7;
|
||||
hdma_i2c1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
|
||||
hdma_i2c1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
hdma_i2c1_rx.Init.MemInc = DMA_MINC_ENABLE;
|
||||
hdma_i2c1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
|
||||
hdma_i2c1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
|
||||
hdma_i2c1_rx.Init.Mode = DMA_NORMAL;
|
||||
hdma_i2c1_rx.Init.Priority = DMA_PRIORITY_LOW;
|
||||
HAL_DMA_Init(&hdma_i2c1_rx);
|
||||
|
||||
__HAL_LINKDMA(hi2c, hdmarx, hdma_i2c1_rx);
|
||||
|
||||
/* I2C1_TX Init */
|
||||
hdma_i2c1_tx.Instance = DMA1_Channel6;
|
||||
hdma_i2c1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
|
||||
hdma_i2c1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
hdma_i2c1_tx.Init.MemInc = DMA_MINC_ENABLE;
|
||||
hdma_i2c1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
|
||||
hdma_i2c1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
|
||||
hdma_i2c1_tx.Init.Mode = DMA_NORMAL;
|
||||
hdma_i2c1_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
|
||||
HAL_DMA_Init(&hdma_i2c1_tx);
|
||||
|
||||
__HAL_LINKDMA(hi2c, hdmatx, hdma_i2c1_tx);
|
||||
|
||||
/* I2C1 interrupt Init */
|
||||
HAL_NVIC_SetPriority(I2C1_EV_IRQn, 15, 0);
|
||||
HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
|
||||
HAL_NVIC_SetPriority(I2C1_ER_IRQn, 15, 0);
|
||||
HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
|
||||
}
|
||||
|
||||
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim_base) {
|
||||
if (htim_base->Instance == TIM3) {
|
||||
/* Peripheral clock enable */
|
||||
|
||||
@@ -57,12 +57,12 @@ void TIM4_IRQHandler(void) {
|
||||
HAL_TIM_IRQHandler(handle);
|
||||
}
|
||||
|
||||
void I2C1_EV_IRQHandler(void) { HAL_I2C_EV_IRQHandler(&hi2c1); }
|
||||
void I2C1_ER_IRQHandler(void) { HAL_I2C_ER_IRQHandler(&hi2c1); }
|
||||
void I2C1_EV_IRQHandler(void) {}
|
||||
void I2C1_ER_IRQHandler(void) {}
|
||||
|
||||
void DMA1_Channel6_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_i2c1_tx); }
|
||||
void DMA1_Channel6_IRQHandler(void) {}
|
||||
|
||||
void DMA1_Channel7_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_i2c1_rx); }
|
||||
void DMA1_Channel7_IRQHandler(void) {}
|
||||
|
||||
void EXTI9_5_IRQHandler(void) {
|
||||
#ifdef INT_PD_Pin
|
||||
|
||||
@@ -97,7 +97,7 @@ 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; }
|
||||
uint16_t getTipThermalMass() { return TIP_THERMAL_MASS; }
|
||||
uint16_t getTipInertia() { return TIP_THERMAL_MASS; }
|
||||
|
||||
void showBootLogo(void) { BootLogo::handleShowingLogo((uint8_t *)FLASH_LOGOADDR); }
|
||||
|
||||
@@ -69,4 +69,4 @@ const int32_t uVtoDegC[] = {
|
||||
|
||||
const int uVtoDegCItems = sizeof(uVtoDegC) / (2 * sizeof(uVtoDegC[0]));
|
||||
|
||||
uint32_t TipThermoModel::convertuVToDegC(uint32_t tipuVDelta) { return Utils::InterpolateLookupTable(uVtoDegC, uVtoDegCItems, tipuVDelta); }
|
||||
TemperatureType_t TipThermoModel::convertuVToDegC(uint32_t tipuVDelta) { return Utils::InterpolateLookupTable(uVtoDegC, uVtoDegCItems, tipuVDelta); }
|
||||
|
||||
@@ -282,7 +282,7 @@ typedef union {
|
||||
*/
|
||||
#define __RV_CSR_SWAP(csr, val) \
|
||||
({ \
|
||||
register rv_csr_t __v = (unsigned long)(val); \
|
||||
volatile rv_csr_t __v = (unsigned long)(val); \
|
||||
__ASM volatile("csrrw %0, " STRINGIFY(csr) ", %1" : "=r"(__v) : "rK"(__v) : "memory"); \
|
||||
__v; \
|
||||
})
|
||||
@@ -297,7 +297,7 @@ typedef union {
|
||||
*/
|
||||
#define __RV_CSR_READ(csr) \
|
||||
({ \
|
||||
register rv_csr_t __v; \
|
||||
volatile rv_csr_t __v; \
|
||||
__ASM volatile("csrr %0, " STRINGIFY(csr) : "=r"(__v) : : "memory"); \
|
||||
__v; \
|
||||
})
|
||||
@@ -312,7 +312,7 @@ typedef union {
|
||||
*/
|
||||
#define __RV_CSR_WRITE(csr, val) \
|
||||
({ \
|
||||
register rv_csr_t __v = (rv_csr_t)(val); \
|
||||
volatile rv_csr_t __v = (rv_csr_t)(val); \
|
||||
__ASM volatile("csrw " STRINGIFY(csr) ", %0" : : "rK"(__v) : "memory"); \
|
||||
})
|
||||
|
||||
@@ -328,7 +328,7 @@ typedef union {
|
||||
*/
|
||||
#define __RV_CSR_READ_SET(csr, val) \
|
||||
({ \
|
||||
register rv_csr_t __v = (rv_csr_t)(val); \
|
||||
volatile rv_csr_t __v = (rv_csr_t)(val); \
|
||||
__ASM volatile("csrrs %0, " STRINGIFY(csr) ", %1" : "=r"(__v) : "rK"(__v) : "memory"); \
|
||||
__v; \
|
||||
})
|
||||
@@ -343,7 +343,7 @@ typedef union {
|
||||
*/
|
||||
#define __RV_CSR_SET(csr, val) \
|
||||
({ \
|
||||
register rv_csr_t __v = (rv_csr_t)(val); \
|
||||
volatile rv_csr_t __v = (rv_csr_t)(val); \
|
||||
__ASM volatile("csrs " STRINGIFY(csr) ", %0" : : "rK"(__v) : "memory"); \
|
||||
})
|
||||
|
||||
@@ -359,7 +359,7 @@ typedef union {
|
||||
*/
|
||||
#define __RV_CSR_READ_CLEAR(csr, val) \
|
||||
({ \
|
||||
register rv_csr_t __v = (rv_csr_t)(val); \
|
||||
volatile rv_csr_t __v = (rv_csr_t)(val); \
|
||||
__ASM volatile("csrrc %0, " STRINGIFY(csr) ", %1" : "=r"(__v) : "rK"(__v) : "memory"); \
|
||||
__v; \
|
||||
})
|
||||
@@ -374,7 +374,7 @@ typedef union {
|
||||
*/
|
||||
#define __RV_CSR_CLEAR(csr, val) \
|
||||
({ \
|
||||
register rv_csr_t __v = (rv_csr_t)(val); \
|
||||
volatile rv_csr_t __v = (rv_csr_t)(val); \
|
||||
__ASM volatile("csrc " STRINGIFY(csr) ", %0" : : "rK"(__v) : "memory"); \
|
||||
})
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
@@ -86,7 +86,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
|
||||
|
||||
@@ -145,12 +145,13 @@
|
||||
#define MIN_BOOST_TEMP_C 250 // The min settable temp for boost mode °C
|
||||
#define MIN_BOOST_TEMP_F 480 // The min settable temp for boost mode °F
|
||||
|
||||
#define POW_PD 1
|
||||
#define POW_PD_EXT 0
|
||||
#define POW_QC 1
|
||||
#define POW_DC 1
|
||||
#define POW_QC_20V 1
|
||||
#define ENABLE_QC2 1
|
||||
#define POW_PD 1
|
||||
#define POW_PD_EXT 0
|
||||
#define POW_QC 1
|
||||
#define POW_DC 1
|
||||
#define POW_QC_20V 1
|
||||
#define ENABLE_QC2 1
|
||||
#define MAG_SLEEP_SUPPORT 1
|
||||
#define TEMP_TMP36
|
||||
#define ACCEL_BMA
|
||||
#define ACCEL_SC7
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
// These control the period's of time used for the PWM
|
||||
const uint16_t powerPWM = 255;
|
||||
const uint8_t holdoffTicks = 25; // This is the tick delay before temp measure starts (i.e. time for op-amp recovery)
|
||||
const uint8_t tempMeasureTicks = 25;
|
||||
uint8_t holdoffTicks = 25; // This is the tick delay before temp measure starts (i.e. time for op-amp recovery)
|
||||
uint8_t tempMeasureTicks = 25;
|
||||
|
||||
uint16_t totalPWM = 255; // Total length of the cycle's ticks
|
||||
|
||||
@@ -160,18 +160,8 @@ uint8_t getTipResistanceX10() {
|
||||
return lastTipResistance;
|
||||
}
|
||||
|
||||
uint8_t getTipThermalMass() {
|
||||
if (lastTipResistance >= 80) {
|
||||
return TIP_THERMAL_MASS;
|
||||
}
|
||||
return 45;
|
||||
}
|
||||
uint8_t getTipInertia() {
|
||||
if (lastTipResistance >= 80) {
|
||||
return TIP_THERMAL_MASS;
|
||||
}
|
||||
return 10;
|
||||
}
|
||||
uint16_t getTipThermalMass() { return 120; }
|
||||
uint16_t getTipInertia() { return 750; }
|
||||
// We want to calculate lastTipResistance
|
||||
// If tip is connected, and the tip is cold and the tip is not being heated
|
||||
// We can use the GPIO to inject a small current into the tip and measure this
|
||||
@@ -180,7 +170,7 @@ uint8_t getTipInertia() {
|
||||
// Which is around 0.54mA this will induce:
|
||||
// 6 ohm tip -> 3.24mV (Real world ~= 3320)
|
||||
// 8 ohm tip -> 4.32mV (Real world ~= 4500)
|
||||
// Which is definitely measureable
|
||||
// Which is definitely measurable
|
||||
// Taking shortcuts here as we know we only really have to pick apart 6 and 8 ohm tips
|
||||
// These are reported as 60 and 75 respectively
|
||||
void performTipResistanceSampleReading() {
|
||||
|
||||
@@ -19,17 +19,17 @@ extern "C" {
|
||||
}
|
||||
void start_PWM_output(void);
|
||||
|
||||
#define ADC_Filter_Smooth 4
|
||||
#define ADC_Filter_Smooth 4 /* This basically smooths over one PWM cycle / set of readings */
|
||||
history<uint16_t, ADC_Filter_Smooth> ADC_Vin;
|
||||
history<uint16_t, ADC_Filter_Smooth> ADC_Temp;
|
||||
history<uint16_t, ADC_Filter_Smooth> ADC_Tip;
|
||||
volatile uint8_t ADCBurstCounter = 0;
|
||||
void adc_fifo_irq(void) {
|
||||
|
||||
// IRQ is called at the end of the 8 set readings, pop these from the FIFO and send to filters
|
||||
void adc_fifo_irq(void) {
|
||||
if (ADC_GetIntStatus(ADC_INT_FIFO_READY) == SET) {
|
||||
// Read out all entries in the fifo
|
||||
while (ADC_Get_FIFO_Count()) {
|
||||
ADCBurstCounter++;
|
||||
volatile uint32_t reading = ADC_Read_FIFO();
|
||||
uint32_t reading = ADC_Read_FIFO();
|
||||
// As per manual, 26 bit reading; lowest 16 are the ADC
|
||||
uint16_t sample = reading & 0xFFFF;
|
||||
uint8_t source = (reading >> 21) & 0b11111;
|
||||
@@ -43,23 +43,16 @@ void adc_fifo_irq(void) {
|
||||
case VIN_ADC_CHANNEL:
|
||||
ADC_Vin.update(sample);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ADCBurstCounter >= 8) {
|
||||
ADCBurstCounter = 0;
|
||||
start_PWM_output();
|
||||
|
||||
// unblock the PID controller thread
|
||||
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
if (pidTaskNotification) {
|
||||
vTaskNotifyGiveFromISR(pidTaskNotification, &xHigherPriorityTaskWoken);
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
// unblock the PID controller thread
|
||||
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
if (pidTaskNotification) {
|
||||
vTaskNotifyGiveFromISR(pidTaskNotification, &xHigherPriorityTaskWoken);
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,19 +60,21 @@ void adc_fifo_irq(void) {
|
||||
ADC_IntClr(ADC_INT_ALL);
|
||||
}
|
||||
|
||||
static bool fastPWM = false;
|
||||
static void switchToFastPWM(void);
|
||||
volatile bool inFastPWMMode = false;
|
||||
|
||||
volatile uint16_t PWMSafetyTimer = 0;
|
||||
volatile uint8_t pendingPWM = 0;
|
||||
volatile bool lastPeriodWasFast = false;
|
||||
static void switchToFastPWM(void);
|
||||
static void switchToSlowPWM(void);
|
||||
|
||||
volatile uint16_t PWMSafetyTimer = 0;
|
||||
volatile uint8_t pendingPWM = 0;
|
||||
volatile bool pendingNextPeriodIsFast = false;
|
||||
|
||||
void start_PWM_output(void) {
|
||||
|
||||
if (PWMSafetyTimer) {
|
||||
PWMSafetyTimer--;
|
||||
if (lastPeriodWasFast != fastPWM) {
|
||||
if (fastPWM) {
|
||||
if (pendingNextPeriodIsFast != inFastPWMMode) {
|
||||
if (pendingNextPeriodIsFast) {
|
||||
switchToFastPWM();
|
||||
} else {
|
||||
switchToSlowPWM();
|
||||
@@ -96,55 +91,87 @@ void start_PWM_output(void) {
|
||||
}
|
||||
} else {
|
||||
PWM_Channel_Disable(PWM_Channel);
|
||||
switchToFastPWM();
|
||||
}
|
||||
TIMER_Enable(TIMER_CH0);
|
||||
}
|
||||
|
||||
// Timer 0 is used to co-ordinate the ADC and the output PWM
|
||||
void timer0_comp0_callback(void) {
|
||||
TIMER_Disable(TIMER_CH0);
|
||||
ADC_Start();
|
||||
if (PWM_Channel_Is_Enabled(PWM_Channel)) {
|
||||
// So there appears to be a bug _somewhere_ where sometimes the comparator doesn't fire
|
||||
// Its not re-occurring with specific values, so suspect its a weird bug
|
||||
// For now, we just skip the cycle and throw away the ADC readings. Its a waste but
|
||||
// It stops stupid glitches in readings, i'd take slight instability from the time jump
|
||||
// Over the readings we get that are borked as the header is left on
|
||||
// <Ralim 2023/10/14>
|
||||
PWM_Channel_Disable(PWM_Channel);
|
||||
// MSG("ALERT PWM Glitch\r\n");
|
||||
// Triger the PID now instead
|
||||
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
if (pidTaskNotification) {
|
||||
vTaskNotifyGiveFromISR(pidTaskNotification, &xHigherPriorityTaskWoken);
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ADC_Start();
|
||||
}
|
||||
TIMER_ClearIntStatus(TIMER_CH0, TIMER_COMP_ID_0);
|
||||
}
|
||||
void timer0_comp1_callback(void) {
|
||||
// Trigged at end of output cycle; turn off the tip PWM
|
||||
PWM_Channel_Disable(PWM_Channel);
|
||||
TIMER_ClearIntStatus(TIMER_CH0, TIMER_COMP_ID_1);
|
||||
}
|
||||
void timer0_comp1_callback(void) { PWM_Channel_Disable(PWM_Channel); } // Trigged at end of output cycle; turn off the tip PWM
|
||||
|
||||
void timer0_comp2_callback(void) {
|
||||
// Triggered at end of timer cycle; re-start the tip driver
|
||||
start_PWM_output();
|
||||
TIMER_ClearIntStatus(TIMER_CH0, TIMER_COMP_ID_2);
|
||||
}
|
||||
void switchToFastPWM(void) {
|
||||
fastPWM = true;
|
||||
totalPWM = powerPWM + tempMeasureTicks + holdoffTicks;
|
||||
inFastPWMMode = true;
|
||||
holdoffTicks = 10;
|
||||
tempMeasureTicks = 10;
|
||||
totalPWM = powerPWM + tempMeasureTicks + holdoffTicks;
|
||||
TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_2, totalPWM);
|
||||
|
||||
// ~10Hz
|
||||
TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_0, powerPWM + holdoffTicks);
|
||||
// Set divider to 11
|
||||
|
||||
// Set divider to 10 ~= 10.5Hz
|
||||
uint32_t tmpVal = BL_RD_REG(TIMER_BASE, TIMER_TCDR);
|
||||
|
||||
tmpVal = BL_SET_REG_BITS_VAL(tmpVal, TIMER_TCDR2, 11);
|
||||
tmpVal = BL_SET_REG_BITS_VAL(tmpVal, TIMER_TCDR2, 10);
|
||||
|
||||
BL_WR_REG(TIMER_BASE, TIMER_TCDR, tmpVal);
|
||||
}
|
||||
|
||||
void switchToSlowPWM(void) {
|
||||
// 5Hz
|
||||
fastPWM = false;
|
||||
totalPWM = powerPWM + tempMeasureTicks / 2 + holdoffTicks / 2;
|
||||
inFastPWMMode = false;
|
||||
holdoffTicks = 5;
|
||||
tempMeasureTicks = 5;
|
||||
totalPWM = powerPWM + tempMeasureTicks + holdoffTicks;
|
||||
|
||||
TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_2, totalPWM);
|
||||
// Adjust ADC
|
||||
TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_0, powerPWM + (holdoffTicks / 2));
|
||||
TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_0, powerPWM + holdoffTicks);
|
||||
|
||||
// Set divider to 22
|
||||
// Set divider for ~ 5Hz
|
||||
|
||||
uint32_t tmpVal = BL_RD_REG(TIMER_BASE, TIMER_TCDR);
|
||||
|
||||
tmpVal = BL_SET_REG_BITS_VAL(tmpVal, TIMER_TCDR2, 22);
|
||||
tmpVal = BL_SET_REG_BITS_VAL(tmpVal, TIMER_TCDR2, 20);
|
||||
|
||||
BL_WR_REG(TIMER_BASE, TIMER_TCDR, tmpVal);
|
||||
}
|
||||
void setTipPWM(const uint8_t pulse, const bool shouldUseFastModePWM) {
|
||||
PWMSafetyTimer = 10; // This is decremented in the handler for PWM so that the tip pwm is
|
||||
// disabled if the PID task is not scheduled often enough.
|
||||
pendingPWM = pulse;
|
||||
fastPWM = shouldUseFastModePWM;
|
||||
pendingPWM = pulse;
|
||||
pendingNextPeriodIsFast = shouldUseFastModePWM;
|
||||
}
|
||||
extern osThreadId POWTaskHandle;
|
||||
|
||||
@@ -186,5 +213,6 @@ uint16_t getADCHandleTemp(uint8_t sample) { return ADC_Temp.average(); }
|
||||
|
||||
uint16_t getADCVin(uint8_t sample) { return ADC_Vin.average(); }
|
||||
|
||||
// Returns either average or instant value. When sample is set the samples from the injected ADC are copied to the filter and then the raw reading is returned
|
||||
// Returns the current raw tip reading after any cleanup filtering
|
||||
// For Pinecil V2 we dont do any rolling filtering other than just averaging all 4 readings in the adc snapshot
|
||||
uint16_t getTipRawTemp(uint8_t sample) { return ADC_Tip.average() >> 1; }
|
||||
|
||||
@@ -21,7 +21,6 @@ void timer0_comp1_callback(void);
|
||||
void timer0_comp2_callback(void);
|
||||
void adc_fifo_irq(void);
|
||||
void GPIO_IRQHandler(void);
|
||||
void switchToSlowPWM(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -102,7 +102,7 @@ void setup_adc(void) {
|
||||
|
||||
adc_cfg.clkDiv = ADC_CLK_DIV_4;
|
||||
adc_cfg.vref = ADC_VREF_3P2V;
|
||||
adc_cfg.resWidth = ADC_DATA_WIDTH_14_WITH_64_AVERAGE;
|
||||
adc_cfg.resWidth = ADC_DATA_WIDTH_14_WITH_16_AVERAGE;
|
||||
adc_cfg.inputMode = ADC_INPUT_SINGLE_END;
|
||||
adc_cfg.v18Sel = ADC_V18_SEL_1P72V;
|
||||
adc_cfg.v11Sel = ADC_V11_SEL_1P1V;
|
||||
@@ -111,7 +111,7 @@ void setup_adc(void) {
|
||||
adc_cfg.chopMode = ADC_CHOP_MOD_AZ_ON;
|
||||
adc_cfg.biasSel = ADC_BIAS_SEL_MAIN_BANDGAP;
|
||||
adc_cfg.vcm = ADC_PGA_VCM_1P6V;
|
||||
adc_cfg.offsetCalibEn = ENABLE;
|
||||
adc_cfg.offsetCalibEn = DISABLE;
|
||||
adc_cfg.offsetCalibVal = 0;
|
||||
|
||||
ADC_Disable();
|
||||
@@ -120,7 +120,7 @@ void setup_adc(void) {
|
||||
|
||||
ADC_Init(&adc_cfg);
|
||||
adc_fifo_cfg.dmaEn = DISABLE;
|
||||
adc_fifo_cfg.fifoThreshold = ADC_FIFO_THRESHOLD_8;
|
||||
adc_fifo_cfg.fifoThreshold = ADC_FIFO_THRESHOLD_8; // Triger FIFO when all 8 measurements are done
|
||||
ADC_FIFO_Cfg(&adc_fifo_cfg);
|
||||
ADC_MIC_Bias_Disable();
|
||||
ADC_Tsen_Disable();
|
||||
@@ -138,26 +138,29 @@ void setup_timer_scheduler() {
|
||||
TIMER_Disable(TIMER_CH0);
|
||||
|
||||
TIMER_CFG_Type cfg = {
|
||||
TIMER_CH0, // Channel
|
||||
TIMER_CLKSRC_32K, // Clock source
|
||||
TIMER_PRELOAD_TRIG_COMP0, // Trigger; reset after trigger 0
|
||||
TIMER_COUNT_PRELOAD, // Counter mode
|
||||
22, // Clock div
|
||||
(uint16_t)(powerPWM + holdoffTicks), // CH0 compare (adc)
|
||||
0, // CH1 compare (pwm out)
|
||||
0, // CH2 compare not used
|
||||
0, // Preload
|
||||
TIMER_CH0, // Channel
|
||||
TIMER_CLKSRC_32K, // Clock source
|
||||
TIMER_PRELOAD_TRIG_COMP2, // Trigger; reset after trigger 0
|
||||
TIMER_COUNT_PRELOAD, // Counter mode
|
||||
22, // Clock div
|
||||
(uint16_t)(powerPWM + holdoffTicks), // CH0 compare (adc)
|
||||
(uint16_t)(powerPWM), // CH1 compare (pwm out)
|
||||
(uint16_t)(powerPWM + holdoffTicks + tempMeasureTicks), // CH2 compare end of cycle
|
||||
0, // Preload
|
||||
};
|
||||
TIMER_Init(&cfg);
|
||||
|
||||
Timer_Int_Callback_Install(TIMER_CH0, TIMER_INT_COMP_0, timer0_comp0_callback);
|
||||
Timer_Int_Callback_Install(TIMER_CH0, TIMER_INT_COMP_1, timer0_comp1_callback);
|
||||
Timer_Int_Callback_Install(TIMER_CH0, TIMER_INT_COMP_2, timer0_comp2_callback);
|
||||
|
||||
TIMER_ClearIntStatus(TIMER_CH0, TIMER_COMP_ID_0);
|
||||
TIMER_ClearIntStatus(TIMER_CH0, TIMER_COMP_ID_1);
|
||||
TIMER_ClearIntStatus(TIMER_CH0, TIMER_COMP_ID_2);
|
||||
|
||||
TIMER_IntMask(TIMER_CH0, TIMER_INT_COMP_0, UNMASK);
|
||||
TIMER_IntMask(TIMER_CH0, TIMER_INT_COMP_1, UNMASK);
|
||||
TIMER_IntMask(TIMER_CH0, TIMER_INT_COMP_2, UNMASK);
|
||||
CPU_Interrupt_Enable(TIMER_CH0_IRQn);
|
||||
TIMER_Enable(TIMER_CH0);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ uint16_t getADCVin(uint8_t sample);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
void setupFUSBIRQ();
|
||||
extern const uint8_t holdoffTicks;
|
||||
extern const uint8_t tempMeasureTicks;
|
||||
void setupFUSBIRQ();
|
||||
extern uint8_t holdoffTicks;
|
||||
extern uint8_t tempMeasureTicks;
|
||||
#endif /* PINE_SETUP_H_ */
|
||||
|
||||
@@ -69,4 +69,4 @@ const int32_t uVtoDegC[] = {
|
||||
|
||||
const int uVtoDegCItems = sizeof(uVtoDegC) / (2 * sizeof(int32_t));
|
||||
|
||||
uint32_t TipThermoModel::convertuVToDegC(uint32_t tipuVDelta) { return Utils::InterpolateLookupTable(uVtoDegC, uVtoDegCItems, tipuVDelta); }
|
||||
TemperatureType_t TipThermoModel::convertuVToDegC(uint32_t tipuVDelta) { return Utils::InterpolateLookupTable(uVtoDegC, uVtoDegCItems, tipuVDelta); }
|
||||
|
||||
@@ -1,43 +1,44 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file bl702_pwm.h
|
||||
* @version V1.0
|
||||
* @date
|
||||
* @brief This file is the standard driver header file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT(c) 2020 Bouffalo Lab</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Bouffalo Lab nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
******************************************************************************
|
||||
* @file bl702_pwm.h
|
||||
* @version V1.0
|
||||
* @date
|
||||
* @brief This file is the standard driver header file
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT(c) 2020 Bouffalo Lab</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Bouffalo Lab nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#ifndef __BL702_PWM_H__
|
||||
#define __BL702_PWM_H__
|
||||
|
||||
#include "pwm_reg.h"
|
||||
#include "bl702_common.h"
|
||||
#include "pwm_reg.h"
|
||||
|
||||
|
||||
/** @addtogroup BL702_Peripheral_Driver
|
||||
* @{
|
||||
@@ -55,61 +56,60 @@
|
||||
* @brief PWM No. type definition
|
||||
*/
|
||||
typedef enum {
|
||||
PWM_CH0 = 0, /*!< PWM Channel 0 define */
|
||||
PWM_CH1, /*!< PWM Channel 1 define */
|
||||
PWM_CH2, /*!< PWM Channel 2 define */
|
||||
PWM_CH3, /*!< PWM Channel 3 define */
|
||||
PWM_CH4, /*!< PWM Channel 4 define */
|
||||
PWM_CH_MAX, /*!< */
|
||||
PWM_CH0 = 0, /*!< PWM Channel 0 define */
|
||||
PWM_CH1, /*!< PWM Channel 1 define */
|
||||
PWM_CH2, /*!< PWM Channel 2 define */
|
||||
PWM_CH3, /*!< PWM Channel 3 define */
|
||||
PWM_CH4, /*!< PWM Channel 4 define */
|
||||
PWM_CH_MAX, /*!< */
|
||||
} PWM_CH_ID_Type;
|
||||
|
||||
/**
|
||||
* @brief PWM Clock definition
|
||||
*/
|
||||
typedef enum {
|
||||
PWM_CLK_XCLK = 0, /*!< PWM Clock source :XTAL CLK */
|
||||
PWM_CLK_BCLK, /*!< PWM Clock source :Bus CLK */
|
||||
PWM_CLK_32K, /*!< PWM Clock source :32K CLK */
|
||||
PWM_CLK_XCLK = 0, /*!< PWM Clock source :XTAL CLK */
|
||||
PWM_CLK_BCLK, /*!< PWM Clock source :Bus CLK */
|
||||
PWM_CLK_32K, /*!< PWM Clock source :32K CLK */
|
||||
} PWM_Clk_Type;
|
||||
|
||||
/**
|
||||
* @brief PWM Stop Mode definition
|
||||
*/
|
||||
typedef enum {
|
||||
PWM_STOP_ABRUPT = 0, /*!< PWM stop abrupt select define */
|
||||
PWM_STOP_GRACEFUL, /*!< PWM stop graceful select define */
|
||||
PWM_STOP_ABRUPT = 0, /*!< PWM stop abrupt select define */
|
||||
PWM_STOP_GRACEFUL, /*!< PWM stop graceful select define */
|
||||
} PWM_Stop_Mode_Type;
|
||||
|
||||
/**
|
||||
* @brief PWM mode type def
|
||||
*/
|
||||
typedef enum {
|
||||
PWM_POL_NORMAL = 0, /*!< PWM normal polarity mode define */
|
||||
PWM_POL_INVERT, /*!< PWM invert polarity mode define */
|
||||
PWM_POL_NORMAL = 0, /*!< PWM normal polarity mode define */
|
||||
PWM_POL_INVERT, /*!< PWM invert polarity mode define */
|
||||
} PWM_Polarity_Type;
|
||||
|
||||
/**
|
||||
* @brief PWM interrupt type def
|
||||
*/
|
||||
typedef enum {
|
||||
PWM_INT_PULSE_CNT = 0, /*!< PWM Pulse count interrupt define */
|
||||
PWM_INT_ALL, /*!< */
|
||||
PWM_INT_PULSE_CNT = 0, /*!< PWM Pulse count interrupt define */
|
||||
PWM_INT_ALL, /*!< */
|
||||
} PWM_INT_Type;
|
||||
|
||||
/**
|
||||
* @brief PWM configuration structure type definition
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
PWM_CH_ID_Type ch; /*!< PWM channel */
|
||||
PWM_Clk_Type clk; /*!< PWM Clock */
|
||||
PWM_Stop_Mode_Type stopMode; /*!< PWM Stop Mode */
|
||||
PWM_Polarity_Type pol; /*!< PWM mode type */
|
||||
uint16_t clkDiv; /*!< PWM clkDiv num */
|
||||
uint16_t period; /*!< PWM period set */
|
||||
uint16_t threshold1; /*!< PWM threshold1 num */
|
||||
uint16_t threshold2; /*!< PWM threshold2 num */
|
||||
uint16_t intPulseCnt; /*!< PWM interrupt pulse count */
|
||||
typedef struct {
|
||||
PWM_CH_ID_Type ch; /*!< PWM channel */
|
||||
PWM_Clk_Type clk; /*!< PWM Clock */
|
||||
PWM_Stop_Mode_Type stopMode; /*!< PWM Stop Mode */
|
||||
PWM_Polarity_Type pol; /*!< PWM mode type */
|
||||
uint16_t clkDiv; /*!< PWM clkDiv num */
|
||||
uint16_t period; /*!< PWM period set */
|
||||
uint16_t threshold1; /*!< PWM threshold1 num */
|
||||
uint16_t threshold2; /*!< PWM threshold2 num */
|
||||
uint16_t intPulseCnt; /*!< PWM interrupt pulse count */
|
||||
} PWM_CH_CFG_Type;
|
||||
|
||||
/*@} end of group PWM_Public_Types */
|
||||
@@ -121,37 +121,27 @@ typedef struct
|
||||
/** @defgroup PWM_CH_ID_TYPE
|
||||
* @{
|
||||
*/
|
||||
#define IS_PWM_CH_ID_TYPE(type) (((type) == PWM_CH0) || \
|
||||
((type) == PWM_CH1) || \
|
||||
((type) == PWM_CH2) || \
|
||||
((type) == PWM_CH3) || \
|
||||
((type) == PWM_CH4) || \
|
||||
((type) == PWM_CH_MAX))
|
||||
#define IS_PWM_CH_ID_TYPE(type) (((type) == PWM_CH0) || ((type) == PWM_CH1) || ((type) == PWM_CH2) || ((type) == PWM_CH3) || ((type) == PWM_CH4) || ((type) == PWM_CH_MAX))
|
||||
|
||||
/** @defgroup PWM_CLK_TYPE
|
||||
* @{
|
||||
*/
|
||||
#define IS_PWM_CLK_TYPE(type) (((type) == PWM_CLK_XCLK) || \
|
||||
((type) == PWM_CLK_BCLK) || \
|
||||
((type) == PWM_CLK_32K))
|
||||
#define IS_PWM_CLK_TYPE(type) (((type) == PWM_CLK_XCLK) || ((type) == PWM_CLK_BCLK) || ((type) == PWM_CLK_32K))
|
||||
|
||||
/** @defgroup PWM_STOP_MODE_TYPE
|
||||
* @{
|
||||
*/
|
||||
#define IS_PWM_STOP_MODE_TYPE(type) (((type) == PWM_STOP_ABRUPT) || \
|
||||
((type) == PWM_STOP_GRACEFUL))
|
||||
#define IS_PWM_STOP_MODE_TYPE(type) (((type) == PWM_STOP_ABRUPT) || ((type) == PWM_STOP_GRACEFUL))
|
||||
|
||||
/** @defgroup PWM_POLARITY_TYPE
|
||||
* @{
|
||||
*/
|
||||
#define IS_PWM_POLARITY_TYPE(type) (((type) == PWM_POL_NORMAL) || \
|
||||
((type) == PWM_POL_INVERT))
|
||||
#define IS_PWM_POLARITY_TYPE(type) (((type) == PWM_POL_NORMAL) || ((type) == PWM_POL_INVERT))
|
||||
|
||||
/** @defgroup PWM_INT_TYPE
|
||||
* @{
|
||||
*/
|
||||
#define IS_PWM_INT_TYPE(type) (((type) == PWM_INT_PULSE_CNT) || \
|
||||
((type) == PWM_INT_ALL))
|
||||
#define IS_PWM_INT_TYPE(type) (((type) == PWM_INT_PULSE_CNT) || ((type) == PWM_INT_ALL))
|
||||
|
||||
/*@} end of group PWM_Public_Constants */
|
||||
|
||||
@@ -173,21 +163,21 @@ typedef struct
|
||||
void PWM_IRQHandler(void);
|
||||
#endif
|
||||
BL_Err_Type PWM_Channel_Init(PWM_CH_CFG_Type *chCfg);
|
||||
void PWM_Channel_Update(PWM_CH_ID_Type ch, uint16_t period, uint16_t threshold1, uint16_t threshold2);
|
||||
void PWM_Channel_Set_Div(PWM_CH_ID_Type ch, uint16_t div);
|
||||
void PWM_Channel_Set_Threshold1(PWM_CH_ID_Type ch, uint16_t threshold1);
|
||||
void PWM_Channel_Set_Threshold2(PWM_CH_ID_Type ch, uint16_t threshold2);
|
||||
void PWM_Channel_Set_Period(PWM_CH_ID_Type ch, uint16_t period);
|
||||
void PWM_Channel_Get(PWM_CH_ID_Type ch, uint16_t *period, uint16_t *threshold1, uint16_t *threshold2);
|
||||
void PWM_IntMask(PWM_CH_ID_Type ch, PWM_INT_Type intType, BL_Mask_Type intMask);
|
||||
void PWM_Channel_Enable(PWM_CH_ID_Type ch);
|
||||
void PWM_Channel_Disable(PWM_CH_ID_Type ch);
|
||||
void PWM_SW_Mode(PWM_CH_ID_Type ch, BL_Fun_Type enable);
|
||||
void PWM_SW_Force_Value(PWM_CH_ID_Type ch, uint8_t value);
|
||||
void PWM_Int_Callback_Install(PWM_CH_ID_Type ch, uint32_t intType, intCallback_Type *cbFun);
|
||||
void PWM_Channel_Update(PWM_CH_ID_Type ch, uint16_t period, uint16_t threshold1, uint16_t threshold2);
|
||||
void PWM_Channel_Set_Div(PWM_CH_ID_Type ch, uint16_t div);
|
||||
void PWM_Channel_Set_Threshold1(PWM_CH_ID_Type ch, uint16_t threshold1);
|
||||
void PWM_Channel_Set_Threshold2(PWM_CH_ID_Type ch, uint16_t threshold2);
|
||||
void PWM_Channel_Set_Period(PWM_CH_ID_Type ch, uint16_t period);
|
||||
void PWM_Channel_Get(PWM_CH_ID_Type ch, uint16_t *period, uint16_t *threshold1, uint16_t *threshold2);
|
||||
void PWM_IntMask(PWM_CH_ID_Type ch, PWM_INT_Type intType, BL_Mask_Type intMask);
|
||||
void PWM_Channel_Enable(PWM_CH_ID_Type ch);
|
||||
uint8_t PWM_Channel_Is_Enabled(PWM_CH_ID_Type ch);
|
||||
void PWM_Channel_Disable(PWM_CH_ID_Type ch);
|
||||
void PWM_SW_Mode(PWM_CH_ID_Type ch, BL_Fun_Type enable);
|
||||
void PWM_SW_Force_Value(PWM_CH_ID_Type ch, uint8_t value);
|
||||
void PWM_Int_Callback_Install(PWM_CH_ID_Type ch, uint32_t intType, intCallback_Type *cbFun);
|
||||
BL_Err_Type PWM_Smart_Configure(PWM_CH_ID_Type ch, uint32_t frequency, uint8_t dutyCycle);
|
||||
|
||||
|
||||
/*@} end of group PWM_Public_Functions */
|
||||
|
||||
/*@} end of group PWM */
|
||||
|
||||
@@ -354,7 +354,18 @@ void PWM_Channel_Enable(PWM_CH_ID_Type ch) {
|
||||
tmpVal = BL_RD_REG(PWMx, PWM_CONFIG);
|
||||
BL_WR_REG(PWMx, PWM_CONFIG, BL_CLR_REG_BIT(tmpVal, PWM_STOP_EN));
|
||||
}
|
||||
uint8_t PWM_Channel_Is_Enabled(PWM_CH_ID_Type ch) {
|
||||
uint32_t tmpVal;
|
||||
/* Get channel register */
|
||||
uint32_t PWMx = PWM_Get_Channel_Reg(ch);
|
||||
|
||||
/* Check the parameters */
|
||||
CHECK_PARAM(IS_PWM_CH_ID_TYPE(ch));
|
||||
|
||||
/* Config pwm clock to enable pwm */
|
||||
tmpVal = BL_RD_REG(PWMx, PWM_CONFIG);
|
||||
return BL_GET_REG_BITS_VAL(tmpVal, PWM_STOP_EN) == 0;
|
||||
}
|
||||
/****************************************************************************
|
||||
* @brief PWM disable
|
||||
*
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#endif
|
||||
|
||||
extern TickType_t lastMovementTime;
|
||||
extern OperatingMode currentMode;
|
||||
extern OperatingMode currentOperatingMode;
|
||||
|
||||
int ble_char_read_status_callback(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, u16_t len, u16_t offset) {
|
||||
if (attr == NULL || attr->uuid == NULL) {
|
||||
@@ -123,7 +123,7 @@ int ble_char_read_status_callback(struct bt_conn *conn, const struct bt_gatt_att
|
||||
break;
|
||||
case 13:
|
||||
// Operating mode
|
||||
temp = currentMode;
|
||||
temp = (uint32_t)currentOperatingMode;
|
||||
memcpy(buf, &temp, sizeof(temp));
|
||||
return sizeof(temp);
|
||||
break;
|
||||
@@ -162,7 +162,7 @@ int ble_char_read_bulk_value_callback(struct bt_conn *conn, const struct bt_gatt
|
||||
TipThermoModel::getTipMaxInC(), // 9 - max temp
|
||||
TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0), true), // 10 - Raw tip in μV
|
||||
abs(getRawHallEffect()), // 11 - hall sensor
|
||||
currentMode, // 12 - Operating mode
|
||||
(uint32_t)currentOperatingMode, // 12 - Operating mode
|
||||
x10WattHistory.average(), // 13 - Estimated Wattage *10
|
||||
};
|
||||
int lenToCopy = sizeof(bulkData) - offset;
|
||||
|
||||
@@ -152,6 +152,7 @@
|
||||
#define POW_QC_20V 1 // Supported features
|
||||
#define POW_EPR 1
|
||||
#define ENABLE_QC2 1
|
||||
#define MAG_SLEEP_SUPPORT 1
|
||||
#define DEVICE_HAS_VALIDATION_SUPPORT
|
||||
#define TEMP_NTC
|
||||
#define ACCEL_BMA
|
||||
@@ -160,11 +161,16 @@
|
||||
#define HALL_SI7210
|
||||
#define DEBUG_UART_OUTPUT
|
||||
#define HAS_POWER_DEBUG_MENU
|
||||
#define HARDWARE_MAX_WATTAGE_X10 750
|
||||
#define TIP_THERMAL_MASS 65 // X10 watts to raise 1 deg C in 1 second
|
||||
#define BLE_ENABLED
|
||||
#define NEEDS_VBUS_PROBE 0
|
||||
#define CANT_DIRECT_READ_SETTINGS
|
||||
#define HARDWARE_MAX_WATTAGE_X10 750
|
||||
#define BLE_ENABLED // We have a BLE stack
|
||||
#define NEEDS_VBUS_PROBE 0 // No vbus probe, its not connected in pcb
|
||||
#define CANT_DIRECT_READ_SETTINGS // We cant memcpy settings due to flash cache
|
||||
#define TIP_CONTROL_PID // We use PID rather than integrator
|
||||
#define TIP_PID_KP 45 // Reasonable compromise for most tips so far
|
||||
#define TIP_PID_KI 9 // About as high for stability across tips
|
||||
#define TIP_PID_KD 200 // Helps dampen smaller tips; ~= nothing for larger tips
|
||||
#define FILTER_DISPLAYED_TIP_TEMP 8 // Filtering for GUI display
|
||||
|
||||
#endif /* Pinecilv2 */
|
||||
|
||||
#define FLASH_PAGE_SIZE (1024) // Read pages
|
||||
|
||||
@@ -234,8 +234,8 @@ 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; }
|
||||
uint16_t getTipThermalMass() { return TIP_THERMAL_MASS; }
|
||||
uint16_t getTipInertia() { return TIP_THERMAL_INERTIA; }
|
||||
|
||||
void setBuzzer(bool on) {}
|
||||
|
||||
|
||||
@@ -8,4 +8,4 @@
|
||||
#include "Utils.h"
|
||||
#include "configuration.h"
|
||||
|
||||
uint32_t TipThermoModel::convertuVToDegC(uint32_t tipuVDelta) { return (tipuVDelta * 50) / 485; }
|
||||
TemperatureType_t TipThermoModel::convertuVToDegC(uint32_t tipuVDelta) { return (tipuVDelta * 50) / 485; }
|
||||
|
||||
@@ -5,14 +5,16 @@
|
||||
* Author: Ralim
|
||||
*/
|
||||
|
||||
#include "accelerometers_common.h"
|
||||
#include <BMA223.hpp>
|
||||
#include <array>
|
||||
|
||||
|
||||
bool BMA223::detect() {
|
||||
if (FRToSI2C::probe(BMA223_ADDRESS)) {
|
||||
if (ACCEL_I2C_CLASS::probe(BMA223_ADDRESS)) {
|
||||
// Read chip id to ensure its not an address collision
|
||||
uint8_t id = 0;
|
||||
if (FRToSI2C::Mem_Read(BMA223_ADDRESS, BMA223_BGW_CHIPID, &id, 1)) {
|
||||
if (ACCEL_I2C_CLASS::Mem_Read(BMA223_ADDRESS, BMA223_BGW_CHIPID, &id, 1)) {
|
||||
return id == 0b11111000;
|
||||
}
|
||||
}
|
||||
@@ -20,7 +22,7 @@ bool BMA223::detect() {
|
||||
return false;
|
||||
}
|
||||
|
||||
static const FRToSI2C::I2C_REG i2c_registers[] = {
|
||||
static const ACCEL_I2C_CLASS::I2C_REG i2c_registers[] = {
|
||||
//
|
||||
//
|
||||
{BMA223_PMU_RANGE, 0b00000011, 0}, // 2G range
|
||||
@@ -44,7 +46,7 @@ bool BMA223::initalize() {
|
||||
// Hysteresis is set to ~ 16 counts
|
||||
// Theta blocking is set to 0b10
|
||||
|
||||
return FRToSI2C::writeRegistersBulk(BMA223_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0]));
|
||||
return ACCEL_I2C_CLASS::writeRegistersBulk(BMA223_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0]));
|
||||
}
|
||||
|
||||
void BMA223::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) {
|
||||
@@ -52,7 +54,7 @@ void BMA223::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) {
|
||||
// And yet there are MSB and LSB registers _sigh_.
|
||||
uint8_t sensorData[6] = {0, 0, 0, 0, 0, 0};
|
||||
|
||||
if (FRToSI2C::Mem_Read(BMA223_ADDRESS, BMA223_ACCD_X_LSB, sensorData, 6) == false) {
|
||||
if (ACCEL_I2C_CLASS::Mem_Read(BMA223_ADDRESS, BMA223_ACCD_X_LSB, sensorData, 6) == false) {
|
||||
x = y = z = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#define CORE_DRIVERS_BMA223_HPP_
|
||||
#include "BMA223_defines.h"
|
||||
#include "BSP.h"
|
||||
#include "accelerometers_common.h"
|
||||
#include "I2C_Wrapper.hpp"
|
||||
|
||||
class BMA223 {
|
||||
@@ -17,7 +18,7 @@ public:
|
||||
static bool initalize();
|
||||
// 1 = rh, 2,=lh, 8=flat
|
||||
static Orientation getOrientation() {
|
||||
uint8_t val = FRToSI2C::I2C_RegisterRead(BMA223_ADDRESS, BMA223_INT_STATUS_3);
|
||||
uint8_t val = ACCEL_I2C_CLASS::I2C_RegisterRead(BMA223_ADDRESS, BMA223_INT_STATUS_3);
|
||||
val >>= 4; // we dont need high values
|
||||
val &= 0b11;
|
||||
if (val & 0b10) {
|
||||
|
||||
@@ -8,9 +8,10 @@
|
||||
#include <array>
|
||||
|
||||
#include "MMA8652FC.hpp"
|
||||
#include "accelerometers_common.h"
|
||||
#include "cmsis_os.h"
|
||||
|
||||
static const FRToSI2C::I2C_REG i2c_registers[] = {
|
||||
static const ACCEL_I2C_CLASS::I2C_REG i2c_registers[] = {
|
||||
{CTRL_REG2, 0, 0}, // Normal mode
|
||||
{CTRL_REG2, 0x40, 2}, // Reset all registers to POR values
|
||||
{FF_MT_CFG_REG, 0x78, 0}, // Enable motion detection for X, Y, Z axis, latch disabled
|
||||
@@ -26,11 +27,11 @@ static const FRToSI2C::I2C_REG i2c_registers[] = {
|
||||
{CTRL_REG1, 0x19, 0} // ODR=12 Hz, Active mode
|
||||
};
|
||||
|
||||
bool MMA8652FC::initalize() { return FRToSI2C::writeRegistersBulk(MMA8652FC_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); }
|
||||
bool MMA8652FC::initalize() { return ACCEL_I2C_CLASS::writeRegistersBulk(MMA8652FC_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); }
|
||||
|
||||
Orientation MMA8652FC::getOrientation() {
|
||||
// First read the PL_STATUS register
|
||||
uint8_t plStatus = FRToSI2C::I2C_RegisterRead(MMA8652FC_I2C_ADDRESS, PL_STATUS_REG);
|
||||
uint8_t plStatus = ACCEL_I2C_CLASS::I2C_RegisterRead(MMA8652FC_I2C_ADDRESS, PL_STATUS_REG);
|
||||
if ((plStatus & 0b10000000) == 0b10000000) {
|
||||
plStatus >>= 1; // We don't need the up/down bit
|
||||
plStatus &= 0x03; // mask to the two lower bits
|
||||
@@ -47,11 +48,11 @@ Orientation MMA8652FC::getOrientation() {
|
||||
void MMA8652FC::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) {
|
||||
std::array<int16_t, 3> sensorData;
|
||||
|
||||
FRToSI2C::Mem_Read(MMA8652FC_I2C_ADDRESS, OUT_X_MSB_REG, reinterpret_cast<uint8_t *>(sensorData.begin()), sensorData.size() * sizeof(int16_t));
|
||||
ACCEL_I2C_CLASS::Mem_Read(MMA8652FC_I2C_ADDRESS, OUT_X_MSB_REG, reinterpret_cast<uint8_t *>(sensorData.begin()), sensorData.size() * sizeof(int16_t));
|
||||
|
||||
x = static_cast<int16_t>(__builtin_bswap16(*reinterpret_cast<uint16_t *>(&sensorData[0])));
|
||||
y = static_cast<int16_t>(__builtin_bswap16(*reinterpret_cast<uint16_t *>(&sensorData[1])));
|
||||
z = static_cast<int16_t>(__builtin_bswap16(*reinterpret_cast<uint16_t *>(&sensorData[2])));
|
||||
}
|
||||
|
||||
bool MMA8652FC::detect() { return FRToSI2C::probe(MMA8652FC_I2C_ADDRESS); }
|
||||
bool MMA8652FC::detect() { return ACCEL_I2C_CLASS::probe(MMA8652FC_I2C_ADDRESS); }
|
||||
|
||||
@@ -6,11 +6,12 @@
|
||||
*/
|
||||
|
||||
#include "MSA301_defines.h"
|
||||
#include "accelerometers_common.h"
|
||||
#include <MSA301.h>
|
||||
#define MSA301_I2C_ADDRESS 0x26 << 1
|
||||
bool MSA301::detect() { return FRToSI2C::probe(MSA301_I2C_ADDRESS); }
|
||||
bool MSA301::detect() { return ACCEL_I2C_CLASS::probe(MSA301_I2C_ADDRESS); }
|
||||
|
||||
static const FRToSI2C::I2C_REG i2c_registers[] = {
|
||||
static const ACCEL_I2C_CLASS::I2C_REG i2c_registers[] = {
|
||||
//
|
||||
//
|
||||
{MSA301_REG_ODR, 0b00001000, 1}, // X/Y/Z enabled @ 250Hz
|
||||
@@ -21,11 +22,11 @@ static const FRToSI2C::I2C_REG i2c_registers[] = {
|
||||
|
||||
};
|
||||
|
||||
bool MSA301::initalize() { return FRToSI2C::writeRegistersBulk(MSA301_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); }
|
||||
bool MSA301::initalize() { return ACCEL_I2C_CLASS::writeRegistersBulk(MSA301_I2C_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0])); }
|
||||
|
||||
Orientation MSA301::getOrientation() {
|
||||
uint8_t temp = 0;
|
||||
FRToSI2C::Mem_Read(MSA301_I2C_ADDRESS, MSA301_REG_ORIENT_STATUS, &temp, 1);
|
||||
ACCEL_I2C_CLASS::Mem_Read(MSA301_I2C_ADDRESS, MSA301_REG_ORIENT_STATUS, &temp, 1);
|
||||
switch (temp) {
|
||||
case 112:
|
||||
return Orientation::ORIENTATION_LEFT_HAND;
|
||||
@@ -39,7 +40,7 @@ Orientation MSA301::getOrientation() {
|
||||
void MSA301::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) {
|
||||
uint8_t temp[6];
|
||||
// Bulk read all 6 regs
|
||||
FRToSI2C::Mem_Read(MSA301_I2C_ADDRESS, MSA301_REG_OUT_X_L, temp, 6);
|
||||
ACCEL_I2C_CLASS::Mem_Read(MSA301_I2C_ADDRESS, MSA301_REG_OUT_X_L, temp, 6);
|
||||
x = int16_t(((int16_t)temp[1]) << 8 | temp[0]) >> 2;
|
||||
y = int16_t(((int16_t)temp[3]) << 8 | temp[2]) >> 2;
|
||||
z = int16_t(((int16_t)temp[5]) << 8 | temp[4]) >> 2;
|
||||
|
||||
@@ -262,7 +262,8 @@ void OLED::maskScrollIndicatorOnOLED() {
|
||||
* If forward is true, this displays a forward navigation to the second framebuffer contents.
|
||||
* Otherwise a rewinding navigation animation is shown to the second framebuffer contents.
|
||||
*/
|
||||
void OLED::transitionSecondaryFramebuffer(bool forwardNavigation) {
|
||||
void OLED::transitionSecondaryFramebuffer(const bool forwardNavigation, const TickType_t viewEnterTime) {
|
||||
bool buttonsReleased = getButtonState() == BUTTON_NONE;
|
||||
uint8_t *stripBackPointers[4];
|
||||
stripBackPointers[0] = &secondFrameBuffer[FRAMEBUFFER_START + 0];
|
||||
stripBackPointers[1] = &secondFrameBuffer[FRAMEBUFFER_START + OLED_WIDTH];
|
||||
@@ -317,10 +318,14 @@ void OLED::transitionSecondaryFramebuffer(bool forwardNavigation) {
|
||||
|
||||
refresh(); // Now refresh to write out the contents to the new page
|
||||
vTaskDelayUntil(&startDraw, TICKS_100MS / 7);
|
||||
if (getButtonState() != BUTTON_NONE) {
|
||||
buttonsReleased |= getButtonState() == BUTTON_NONE;
|
||||
if (getButtonState() != BUTTON_NONE && buttonsReleased) {
|
||||
memcpy(screenBuffer + FRAMEBUFFER_START, secondFrameBuffer + FRAMEBUFFER_START, sizeof(screenBuffer) - FRAMEBUFFER_START);
|
||||
refresh(); // Now refresh to write out the contents to the new page
|
||||
return;
|
||||
}
|
||||
}
|
||||
refresh(); //
|
||||
}
|
||||
|
||||
void OLED::useSecondaryFramebuffer(bool useSecondary) {
|
||||
@@ -330,6 +335,7 @@ void OLED::useSecondaryFramebuffer(bool useSecondary) {
|
||||
setFramebuffer(screenBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This assumes that the current display output buffer has the current on screen contents
|
||||
* Then the secondary buffer has the "new" contents to be slid up onto the screen
|
||||
@@ -337,8 +343,9 @@ void OLED::useSecondaryFramebuffer(bool useSecondary) {
|
||||
*
|
||||
* **This function blocks until the transition has completed or user presses button**
|
||||
*/
|
||||
void OLED::transitionScrollDown() {
|
||||
TickType_t startDraw = xTaskGetTickCount();
|
||||
void OLED::transitionScrollDown(const TickType_t viewEnterTime) {
|
||||
TickType_t startDraw = xTaskGetTickCount();
|
||||
bool buttonsReleased = getButtonState() == BUTTON_NONE;
|
||||
|
||||
for (uint8_t heightPos = 0; heightPos < OLED_HEIGHT; heightPos++) {
|
||||
// For each line, we shuffle all bits up a row
|
||||
@@ -365,9 +372,9 @@ void OLED::transitionScrollDown() {
|
||||
// Finally on the bottom row; we shuffle it up ready
|
||||
secondFrameBuffer[fourthStripPos] >>= 1;
|
||||
#else
|
||||
// Move the MSB off the first strip, and pop MSB from second strip onto the first strip
|
||||
// Move the LSB off the first strip, and pop MSB from second strip onto the first strip
|
||||
screenBuffer[firstStripPos] = (screenBuffer[firstStripPos] >> 1) | ((screenBuffer[secondStripPos] & 0x01) << 7);
|
||||
// Now shuffle off the second strip MSB, and replace it with the MSB of the secondary buffer
|
||||
// Now shuffle off the second strip MSB, and replace it with the LSB of the secondary buffer
|
||||
screenBuffer[secondStripPos] = (screenBuffer[secondStripPos] >> 1) | ((secondFrameBuffer[firstStripPos] & 0x01) << 7);
|
||||
// Finally, do the shuffle on the second frame buffer
|
||||
secondFrameBuffer[firstStripPos] = (secondFrameBuffer[firstStripPos] >> 1) | ((secondFrameBuffer[secondStripPos] & 0x01) << 7);
|
||||
@@ -375,7 +382,62 @@ void OLED::transitionScrollDown() {
|
||||
secondFrameBuffer[secondStripPos] >>= 1;
|
||||
#endif /* OLED_128x32 */
|
||||
}
|
||||
if (getButtonState() != BUTTON_NONE) {
|
||||
buttonsReleased |= getButtonState() == BUTTON_NONE;
|
||||
if (getButtonState() != BUTTON_NONE && buttonsReleased) {
|
||||
// Exit early, but have to transition whole buffer
|
||||
memcpy(screenBuffer + FRAMEBUFFER_START, secondFrameBuffer + FRAMEBUFFER_START, sizeof(screenBuffer) - FRAMEBUFFER_START);
|
||||
refresh(); // Now refresh to write out the contents to the new page
|
||||
return;
|
||||
}
|
||||
refresh(); // Now refresh to write out the contents to the new page
|
||||
vTaskDelayUntil(&startDraw, TICKS_100MS / 7);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This assumes that the current display output buffer has the current on screen contents
|
||||
* Then the secondary buffer has the "new" contents to be slid down onto the screen
|
||||
* Sadly we cant use the hardware scroll as some devices with the 128x32 screens dont have the GRAM for holding both screens at once
|
||||
*
|
||||
* **This function blocks until the transition has completed or user presses button**
|
||||
*/
|
||||
void OLED::transitionScrollUp(const TickType_t viewEnterTime) {
|
||||
TickType_t startDraw = xTaskGetTickCount();
|
||||
bool buttonsReleased = getButtonState() == BUTTON_NONE;
|
||||
|
||||
for (uint8_t heightPos = 0; heightPos < OLED_HEIGHT; heightPos++) {
|
||||
// For each line, we shuffle all bits down a row
|
||||
for (uint8_t xPos = 0; xPos < OLED_WIDTH; xPos++) {
|
||||
const uint16_t firstStripPos = FRAMEBUFFER_START + xPos;
|
||||
const uint16_t secondStripPos = firstStripPos + OLED_WIDTH;
|
||||
#ifdef OLED_128x32
|
||||
// For 32 pixel high OLED's we have four strips to tailchain
|
||||
const uint16_t thirdStripPos = secondStripPos + OLED_WIDTH;
|
||||
const uint16_t fourthStripPos = thirdStripPos + OLED_WIDTH;
|
||||
// We are shffling LSB's off the end and pushing bits down
|
||||
screenBuffer[fourthStripPos] = (screenBuffer[fourthStripPos] << 1) | ((screenBuffer[thirdStripPos] & 0x80) >> 7);
|
||||
screenBuffer[thirdStripPos] = (screenBuffer[thirdStripPos] << 1) | ((screenBuffer[secondStripPos] & 0x80) >> 7);
|
||||
screenBuffer[secondStripPos] = (screenBuffer[secondStripPos] << 1) | ((screenBuffer[firstStripPos] & 0x80) >> 7);
|
||||
screenBuffer[firstStripPos] = (screenBuffer[firstStripPos] << 1) | ((secondFrameBuffer[fourthStripPos] & 0x80) >> 7);
|
||||
|
||||
secondFrameBuffer[fourthStripPos] = (secondFrameBuffer[fourthStripPos] << 1) | ((secondFrameBuffer[thirdStripPos] & 0x80) >> 7);
|
||||
secondFrameBuffer[thirdStripPos] = (secondFrameBuffer[thirdStripPos] << 1) | ((secondFrameBuffer[secondStripPos] & 0x80) >> 7);
|
||||
secondFrameBuffer[secondStripPos] = (secondFrameBuffer[secondStripPos] << 1) | ((secondFrameBuffer[firstStripPos] & 0x80) >> 7);
|
||||
// Finally on the bottom row; we shuffle it up ready
|
||||
secondFrameBuffer[firstStripPos] <<= 1;
|
||||
#else
|
||||
// We pop the LSB off the bottom row, and replace the MSB in that byte with the LSB of the row above
|
||||
screenBuffer[secondStripPos] = (screenBuffer[secondStripPos] << 1) | ((screenBuffer[firstStripPos] & 0x80) >> 7);
|
||||
// Move the LSB off the first strip, and pop MSB from second strip onto the first strip
|
||||
screenBuffer[firstStripPos] = (screenBuffer[firstStripPos] << 1) | ((secondFrameBuffer[secondStripPos] & 0x80) >> 7);
|
||||
|
||||
// Finally, do the shuffle on the second frame buffer
|
||||
secondFrameBuffer[secondStripPos] = (secondFrameBuffer[secondStripPos] << 1) | ((secondFrameBuffer[firstStripPos] & 0x80) >> 7);
|
||||
// Finally on the bottom row; we shuffle it up ready
|
||||
secondFrameBuffer[firstStripPos] <<= 1;
|
||||
#endif /* OLED_128x32 */
|
||||
}
|
||||
buttonsReleased |= getButtonState() == BUTTON_NONE;
|
||||
if (getButtonState() != BUTTON_NONE && buttonsReleased) {
|
||||
// Exit early, but have to transition whole buffer
|
||||
memcpy(screenBuffer + FRAMEBUFFER_START, secondFrameBuffer + FRAMEBUFFER_START, sizeof(screenBuffer) - FRAMEBUFFER_START);
|
||||
refresh(); // Now refresh to write out the contents to the new page
|
||||
@@ -428,14 +490,18 @@ void OLED::setRotation(bool leftHanded) {
|
||||
}
|
||||
|
||||
void OLED::setBrightness(uint8_t contrast) {
|
||||
OLED_Setup_Array[15].val = contrast;
|
||||
I2C_CLASS::writeRegistersBulk(DEVICEADDR_OLED, &OLED_Setup_Array[14], 2);
|
||||
if (OLED_Setup_Array[15].val != contrast) {
|
||||
OLED_Setup_Array[15].val = contrast;
|
||||
I2C_CLASS::writeRegistersBulk(DEVICEADDR_OLED, &OLED_Setup_Array[14], 2);
|
||||
}
|
||||
}
|
||||
|
||||
void OLED::setInverseDisplay(bool inverse) {
|
||||
uint8_t normalInverseCmd = inverse ? 0xA7 : 0xA6;
|
||||
OLED_Setup_Array[21].val = normalInverseCmd;
|
||||
I2C_CLASS::I2C_RegisterWrite(DEVICEADDR_OLED, 0x80, normalInverseCmd);
|
||||
if (OLED_Setup_Array[21].val != normalInverseCmd) {
|
||||
OLED_Setup_Array[21].val = normalInverseCmd;
|
||||
I2C_CLASS::I2C_RegisterWrite(DEVICEADDR_OLED, 0x80, normalInverseCmd);
|
||||
}
|
||||
}
|
||||
|
||||
// print a string to the current cursor location, len chars MAX
|
||||
|
||||
@@ -46,9 +46,9 @@ 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
|
||||
#define OLED_DIVIDER 0xD3
|
||||
|
||||
#else
|
||||
|
||||
@@ -59,14 +59,14 @@ extern "C" {
|
||||
#define OLED_GRAM_START_FLIP 0
|
||||
#define OLED_GRAM_END_FLIP 95
|
||||
|
||||
#define OLED_VCOM_LAYOUT 0x02
|
||||
#define OLED_SEGMENT_MAP 0xA0
|
||||
#define OLED_DIVIDER 0xD5
|
||||
#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 OLED_ON 0xAF
|
||||
#define OLED_OFF 0xAE
|
||||
|
||||
#define FRAMEBUFFER_START 17
|
||||
|
||||
@@ -78,7 +78,10 @@ enum class FontStyle {
|
||||
|
||||
class OLED {
|
||||
public:
|
||||
enum DisplayState : bool { OFF = false, ON = true };
|
||||
enum DisplayState : bool {
|
||||
OFF = false,
|
||||
ON = true
|
||||
};
|
||||
|
||||
static void initialize(); // Startup the I2C coms (brings screen out of reset etc)
|
||||
static bool isInitDone();
|
||||
@@ -117,10 +120,10 @@ public:
|
||||
static void setInverseDisplay(bool inverted);
|
||||
static int16_t getCursorX() { return cursor_x; }
|
||||
// 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);
|
||||
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);
|
||||
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;
|
||||
@@ -146,9 +149,10 @@ public:
|
||||
static void drawHeatSymbol(uint8_t state);
|
||||
static void drawScrollIndicator(uint8_t p, uint8_t h); // Draws a scrolling position indicator
|
||||
static void maskScrollIndicatorOnOLED();
|
||||
static void transitionSecondaryFramebuffer(bool forwardNavigation);
|
||||
static void transitionSecondaryFramebuffer(const bool forwardNavigation, const TickType_t viewEnterTime);
|
||||
static void useSecondaryFramebuffer(bool useSecondary);
|
||||
static void transitionScrollDown();
|
||||
static void transitionScrollDown(const TickType_t viewEnterTime);
|
||||
static void transitionScrollUp(const TickType_t viewEnterTime);
|
||||
|
||||
private:
|
||||
static bool checkDisplayBufferChecksum() {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "LIS2DH12_defines.hpp"
|
||||
#include "accelerometers_common.h"
|
||||
#include <SC7A20.hpp>
|
||||
#include <SC7A20_defines.h>
|
||||
#include <array>
|
||||
@@ -17,20 +18,20 @@ bool SC7A20::isInImitationMode;
|
||||
*/
|
||||
|
||||
bool SC7A20::detect() {
|
||||
if (FRToSI2C::probe(SC7A20_ADDRESS)) {
|
||||
if (ACCEL_I2C_CLASS::probe(SC7A20_ADDRESS)) {
|
||||
// Read chip id to ensure its not an address collision
|
||||
uint8_t id = 0;
|
||||
if (FRToSI2C::Mem_Read(SC7A20_ADDRESS, SC7A20_WHO_AMI_I, &id, 1)) {
|
||||
if (ACCEL_I2C_CLASS::Mem_Read(SC7A20_ADDRESS, SC7A20_WHO_AMI_I, &id, 1)) {
|
||||
if (id == SC7A20_WHO_AM_I_VALUE) {
|
||||
isInImitationMode = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (FRToSI2C::probe(SC7A20_ADDRESS2)) {
|
||||
if (ACCEL_I2C_CLASS::probe(SC7A20_ADDRESS2)) {
|
||||
// Read chip id to ensure its not an address collision
|
||||
uint8_t id = 0;
|
||||
if (FRToSI2C::Mem_Read(SC7A20_ADDRESS2, SC7A20_WHO_AMI_I, &id, 1)) {
|
||||
if (ACCEL_I2C_CLASS::Mem_Read(SC7A20_ADDRESS2, SC7A20_WHO_AMI_I, &id, 1)) {
|
||||
if (id == SC7A20_WHO_AM_I_VALUE) {
|
||||
isInImitationMode = true;
|
||||
return true;
|
||||
@@ -40,7 +41,7 @@ bool SC7A20::detect() {
|
||||
return false;
|
||||
}
|
||||
|
||||
static const FRToSI2C::I2C_REG i2c_registers[] = {
|
||||
static const ACCEL_I2C_CLASS::I2C_REG i2c_registers[] = {
|
||||
//
|
||||
//
|
||||
{SC7A20_CTRL_REG1, 0b01100111, 0}, // 200Hz, XYZ enabled
|
||||
@@ -59,19 +60,19 @@ static const FRToSI2C::I2C_REG i2c_registers[] = {
|
||||
|
||||
//
|
||||
};
|
||||
static const FRToSI2C::I2C_REG i2c_registers_alt[] = {{LIS_CTRL_REG1, 0b00110111, 0}, // 200Hz XYZ
|
||||
{LIS_CTRL_REG2, 0b00000000, 0}, //
|
||||
{LIS_CTRL_REG3, 0b01100000, 0}, // Setup interrupt pins
|
||||
{LIS_CTRL_REG4, 0b00001000, 0}, // Block update mode off, HR on
|
||||
{LIS_CTRL_REG5, 0b00000010, 0}, //
|
||||
{LIS_CTRL_REG6, 0b01100010, 0},
|
||||
// Basically setup the unit to run, and enable 4D orientation detection
|
||||
{LIS_INT2_CFG, 0b01111110, 0}, // setup for movement detection
|
||||
{LIS_INT2_THS, 0x28, 0}, //
|
||||
{LIS_INT2_DURATION, 64, 0}, //
|
||||
{LIS_INT1_CFG, 0b01111110, 0}, //
|
||||
{LIS_INT1_THS, 0x28, 0}, //
|
||||
{LIS_INT1_DURATION, 64, 0}};
|
||||
static const ACCEL_I2C_CLASS::I2C_REG i2c_registers_alt[] = {{LIS_CTRL_REG1, 0b00110111, 0}, // 200Hz XYZ
|
||||
{LIS_CTRL_REG2, 0b00000000, 0}, //
|
||||
{LIS_CTRL_REG3, 0b01100000, 0}, // Setup interrupt pins
|
||||
{LIS_CTRL_REG4, 0b00001000, 0}, // Block update mode off, HR on
|
||||
{LIS_CTRL_REG5, 0b00000010, 0}, //
|
||||
{LIS_CTRL_REG6, 0b01100010, 0},
|
||||
// Basically setup the unit to run, and enable 4D orientation detection
|
||||
{LIS_INT2_CFG, 0b01111110, 0}, // setup for movement detection
|
||||
{LIS_INT2_THS, 0x28, 0}, //
|
||||
{LIS_INT2_DURATION, 64, 0}, //
|
||||
{LIS_INT1_CFG, 0b01111110, 0}, //
|
||||
{LIS_INT1_THS, 0x28, 0}, //
|
||||
{LIS_INT1_DURATION, 64, 0}};
|
||||
|
||||
bool SC7A20::initalize() {
|
||||
// Setup acceleration readings
|
||||
@@ -83,9 +84,9 @@ bool SC7A20::initalize() {
|
||||
// Hysteresis is set to ~ 16 counts
|
||||
// Theta blocking is set to 0b10
|
||||
if (isInImitationMode) {
|
||||
return FRToSI2C::writeRegistersBulk(SC7A20_ADDRESS2, i2c_registers_alt, sizeof(i2c_registers_alt) / sizeof(i2c_registers_alt[0]));
|
||||
return ACCEL_I2C_CLASS::writeRegistersBulk(SC7A20_ADDRESS2, i2c_registers_alt, sizeof(i2c_registers_alt) / sizeof(i2c_registers_alt[0]));
|
||||
} else {
|
||||
return FRToSI2C::writeRegistersBulk(SC7A20_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0]));
|
||||
return ACCEL_I2C_CLASS::writeRegistersBulk(SC7A20_ADDRESS, i2c_registers, sizeof(i2c_registers) / sizeof(i2c_registers[0]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +94,7 @@ void SC7A20::getAxisReadings(int16_t &x, int16_t &y, int16_t &z) {
|
||||
// We can tell the accelerometer to output in LE mode which makes this simple
|
||||
uint16_t sensorData[3] = {0, 0, 0};
|
||||
|
||||
if (FRToSI2C::Mem_Read(isInImitationMode ? SC7A20_ADDRESS2 : SC7A20_ADDRESS, isInImitationMode ? SC7A20_OUT_X_L_ALT : SC7A20_OUT_X_L, (uint8_t *)sensorData, 6) == false) {
|
||||
if (ACCEL_I2C_CLASS::Mem_Read(isInImitationMode ? SC7A20_ADDRESS2 : SC7A20_ADDRESS, isInImitationMode ? SC7A20_OUT_X_L_ALT : SC7A20_OUT_X_L, (uint8_t *)sensorData, 6) == false) {
|
||||
x = y = z = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include "BSP.h"
|
||||
#include "I2C_Wrapper.hpp"
|
||||
#include "SC7A20_defines.h"
|
||||
#include "accelerometers_common.h"
|
||||
|
||||
|
||||
class SC7A20 {
|
||||
public:
|
||||
@@ -17,7 +19,7 @@ public:
|
||||
static bool initalize();
|
||||
// 1 = rh, 2,=lh, 8=flat
|
||||
static Orientation getOrientation() {
|
||||
uint8_t val = ((FRToSI2C::I2C_RegisterRead(isInImitationMode ? SC7A20_ADDRESS2 : SC7A20_ADDRESS, SC7A20_INT2_SOURCE) >> 2) - 1);
|
||||
uint8_t val = ((ACCEL_I2C_CLASS::I2C_RegisterRead(isInImitationMode ? SC7A20_ADDRESS2 : SC7A20_ADDRESS, SC7A20_INT2_SOURCE) >> 2) - 1);
|
||||
if (val == 1) {
|
||||
#ifdef SC7_ORI_FLIP
|
||||
return Orientation::ORIENTATION_RIGHT_HAND;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "I2C_Wrapper.hpp"
|
||||
#include "Si7210_defines.h"
|
||||
#include <Si7210.h>
|
||||
#ifdef MAG_SLEEP_SUPPORT
|
||||
bool Si7210::detect() { return FRToSI2C::wakePart(SI7210_ADDRESS); }
|
||||
|
||||
bool Si7210::init() {
|
||||
@@ -175,3 +176,4 @@ bool Si7210::set_high_range() {
|
||||
worked &= write_reg(SI7210_A5, 0, val);
|
||||
return worked;
|
||||
}
|
||||
#endif // MAG_SLEEP_SUPPORT
|
||||
@@ -7,7 +7,10 @@
|
||||
|
||||
#ifndef CORE_DRIVERS_SI7210_H_
|
||||
#define CORE_DRIVERS_SI7210_H_
|
||||
#include "configuration.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef MAG_SLEEP_SUPPORT
|
||||
class Si7210 {
|
||||
public:
|
||||
// Return true if present
|
||||
@@ -23,5 +26,5 @@ private:
|
||||
static bool get_field_strength(int16_t *field);
|
||||
static bool set_high_range();
|
||||
};
|
||||
|
||||
#endif // MAG_SLEEP_SUPPORT
|
||||
#endif /* CORE_DRIVERS_SI7210_H_ */
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "TipThermoModel.h"
|
||||
#include "BSP.h"
|
||||
#include "Settings.h"
|
||||
#include "Types.h"
|
||||
#include "Utils.h"
|
||||
#include "configuration.h"
|
||||
#include "main.hpp"
|
||||
@@ -54,45 +55,41 @@ uint32_t TipThermoModel::convertTipRawADCTouV(uint16_t rawADC, bool ski
|
||||
return valueuV;
|
||||
}
|
||||
|
||||
uint32_t TipThermoModel::convertTipRawADCToDegC(uint16_t rawADC) { return convertuVToDegC(convertTipRawADCTouV(rawADC)); }
|
||||
uint32_t TipThermoModel::convertTipRawADCToDegF(uint16_t rawADC) { return convertuVToDegF(convertTipRawADCTouV(rawADC)); }
|
||||
TemperatureType_t TipThermoModel::convertTipRawADCToDegC(uint16_t rawADC) { return convertuVToDegC(convertTipRawADCTouV(rawADC)); }
|
||||
TemperatureType_t TipThermoModel::convertTipRawADCToDegF(uint16_t rawADC) { return convertuVToDegF(convertTipRawADCTouV(rawADC)); }
|
||||
|
||||
uint32_t TipThermoModel::convertuVToDegF(uint32_t tipuVDelta) { return convertCtoF(convertuVToDegC(tipuVDelta)); }
|
||||
TemperatureType_t TipThermoModel::convertuVToDegF(uint32_t tipuVDelta) { return convertCtoF(convertuVToDegC(tipuVDelta)); }
|
||||
|
||||
uint32_t TipThermoModel::convertCtoF(uint32_t degC) {
|
||||
TemperatureType_t TipThermoModel::convertCtoF(TemperatureType_t degC) {
|
||||
//(Y °C × 9/5) + 32 =Y°F
|
||||
return (32 + ((degC * 9) / 5));
|
||||
}
|
||||
|
||||
uint32_t TipThermoModel::convertFtoC(uint32_t degF) {
|
||||
TemperatureType_t TipThermoModel::convertFtoC(TemperatureType_t degF) {
|
||||
//(Y°F − 32) × 5/9 = Y°C
|
||||
if (degF < 32) {
|
||||
return 0;
|
||||
}
|
||||
return ((degF - 32) * 5) / 9;
|
||||
}
|
||||
uint32_t TipThermoModel::getTipInC(bool sampleNow) {
|
||||
int32_t currentTipTempInC = TipThermoModel::convertTipRawADCToDegC(getTipRawTemp(sampleNow));
|
||||
TemperatureType_t TipThermoModel::getTipInC(bool sampleNow) {
|
||||
TemperatureType_t currentTipTempInC = TipThermoModel::convertTipRawADCToDegC(getTipRawTemp(sampleNow));
|
||||
currentTipTempInC += getHandleTemperature(sampleNow) / 10; // Add handle offset
|
||||
|
||||
// Power usage indicates that our tip temp is lower than our thermocouple temp.
|
||||
// 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) {
|
||||
return 0;
|
||||
}
|
||||
return currentTipTempInC;
|
||||
}
|
||||
|
||||
uint32_t TipThermoModel::getTipInF(bool sampleNow) {
|
||||
uint32_t currentTipTempInF = getTipInC(sampleNow);
|
||||
currentTipTempInF = convertCtoF(currentTipTempInF);
|
||||
TemperatureType_t TipThermoModel::getTipInF(bool sampleNow) {
|
||||
TemperatureType_t currentTipTempInF = getTipInC(sampleNow);
|
||||
currentTipTempInF = convertCtoF(currentTipTempInF);
|
||||
return currentTipTempInF;
|
||||
}
|
||||
|
||||
uint32_t TipThermoModel::getTipMaxInC() {
|
||||
uint32_t maximumTipTemp = TipThermoModel::convertTipRawADCToDegC(ADC_MAX_READING - 1);
|
||||
TemperatureType_t TipThermoModel::getTipMaxInC() {
|
||||
TemperatureType_t maximumTipTemp = TipThermoModel::convertTipRawADCToDegC(ADC_MAX_READING - 1);
|
||||
maximumTipTemp += getHandleTemperature(0) / 10; // Add handle offset
|
||||
return maximumTipTemp - 1;
|
||||
}
|
||||
|
||||
@@ -8,26 +8,27 @@
|
||||
#ifndef SRC_TIPTHERMOMODEL_H_
|
||||
#define SRC_TIPTHERMOMODEL_H_
|
||||
#include "BSP.h"
|
||||
#include "Types.h"
|
||||
#include "stdint.h"
|
||||
class TipThermoModel {
|
||||
public:
|
||||
// These are the main two functions
|
||||
static uint32_t getTipInC(bool sampleNow = false);
|
||||
static uint32_t getTipInF(bool sampleNow = false);
|
||||
static TemperatureType_t getTipInC(bool sampleNow = false);
|
||||
static TemperatureType_t getTipInF(bool sampleNow = false);
|
||||
|
||||
// Calculates the maximum temperature can can be read by the ADC range
|
||||
static uint32_t getTipMaxInC();
|
||||
static TemperatureType_t getTipMaxInC();
|
||||
|
||||
static uint32_t convertTipRawADCToDegC(uint16_t rawADC);
|
||||
static uint32_t convertTipRawADCToDegF(uint16_t rawADC);
|
||||
static TemperatureType_t convertTipRawADCToDegC(uint16_t rawADC);
|
||||
static TemperatureType_t convertTipRawADCToDegF(uint16_t rawADC);
|
||||
// Returns the uV of the tip reading before the op-amp compensating for pullups
|
||||
static uint32_t convertTipRawADCTouV(uint16_t rawADC, bool skipCalOffset = false);
|
||||
static uint32_t convertCtoF(uint32_t degC);
|
||||
static uint32_t convertFtoC(uint32_t degF);
|
||||
static uint32_t convertTipRawADCTouV(uint16_t rawADC, bool skipCalOffset = false);
|
||||
static TemperatureType_t convertCtoF(TemperatureType_t degC);
|
||||
static TemperatureType_t convertFtoC(TemperatureType_t degF);
|
||||
|
||||
private:
|
||||
static uint32_t convertuVToDegC(uint32_t tipuVDelta);
|
||||
static uint32_t convertuVToDegF(uint32_t tipuVDelta);
|
||||
static TemperatureType_t convertuVToDegC(uint32_t tipuVDelta);
|
||||
static TemperatureType_t convertuVToDegF(uint32_t tipuVDelta);
|
||||
};
|
||||
|
||||
#endif /* SRC_TIPTHERMOMODEL_H_ */
|
||||
|
||||
@@ -123,7 +123,8 @@ bool parseCapabilitiesArray(const uint8_t numCaps, uint8_t *bestIndex, uint16_t
|
||||
*bestIndex = 0xFF; // Mark unselected
|
||||
*bestVoltage = 5000; // Default 5V
|
||||
|
||||
uint8_t tipResistance = getTipResistanceX10();
|
||||
// Fudge of 0.5 ohms to round up a little to account for us always having off periods in PWM
|
||||
uint8_t tipResistance = getTipResistanceX10() + 5;
|
||||
#ifdef MODEL_HAS_DCDC
|
||||
// If this device has step down DC/DC inductor to smooth out current spikes
|
||||
// We can instead ignore resistance and go for max voltage we can accept; and rely on the DC/DC regulation to keep under current limit
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#ifndef CORE_DRIVERS_ACCELEROMTERS_COMMON_H_
|
||||
#define CORE_DRIVERS_ACCELEROMTERS_COMMON_H_
|
||||
|
||||
#include "configuration.h"
|
||||
#if defined(ACCEL_I2CBB2)
|
||||
#include "I2CBB2.hpp"
|
||||
#define ACCEL_I2C_CLASS I2CBB2
|
||||
|
||||
@@ -4,50 +4,21 @@
|
||||
#include "portmacro.h"
|
||||
#include <stdint.h>
|
||||
/**
|
||||
* A helper class for showing a full-screen scrolling message.
|
||||
* A helper for showing a full-screen scrolling message.
|
||||
*/
|
||||
class ScrollMessage {
|
||||
TickType_t messageStart = 0;
|
||||
int16_t lastOffset = -1;
|
||||
|
||||
/**
|
||||
* Calcualte the width in pixels of the message string, in the large
|
||||
* font and taking into account multi-byte chars.
|
||||
*
|
||||
* @param message The null-terminated message string.
|
||||
*/
|
||||
static uint16_t messageWidth(const char *message);
|
||||
|
||||
public:
|
||||
ScrollMessage() {}
|
||||
|
||||
/**
|
||||
* Resets this `ScrollMessage` instance to its initial state.
|
||||
*/
|
||||
void reset() {
|
||||
messageStart = 0;
|
||||
lastOffset = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this `ScrollMessage` instance is in its initial state.
|
||||
*/
|
||||
bool isReset() const { return messageStart == 0; }
|
||||
|
||||
/**
|
||||
* Draw and update the scroll message if needed.
|
||||
*
|
||||
* This function does not call `OLED::refresh()`. If this function
|
||||
* returns `true`, the caller shall call `OLED::refresh()` to draw the
|
||||
* modified framebuffer to the OLED screen.
|
||||
*
|
||||
* @param message The null-terminated message string. This must be the
|
||||
* same string as the previous call, unless this `ScrollMessage` instance
|
||||
* is in its initial state or `reset()` has been called.
|
||||
* @param currentTick The current tick as returned by `xTaskGetTickCount()`.
|
||||
* @return Whether the OLED framebuffer has been modified.
|
||||
*/
|
||||
bool drawUpdate(const char *message, TickType_t currentTick);
|
||||
};
|
||||
/**
|
||||
* Draw and update the scroll message if needed.
|
||||
*
|
||||
* This function does not call `OLED::refresh()`. If this function
|
||||
* returns `true`, the caller shall call `OLED::refresh()` to draw the
|
||||
* modified framebuffer to the OLED screen.
|
||||
*
|
||||
* @param message The null-terminated message string. This must be the
|
||||
* same string as the previous call, unless this `ScrollMessage` instance
|
||||
* is in its initial state or `reset()` has been called.
|
||||
* @param currentTick The current tick as returned by `xTaskGetTickCount()` offset to 0 at start of scrolling.
|
||||
*/
|
||||
void drawScrollingText(const char *message, TickType_t currentTickOffset);
|
||||
|
||||
#endif /* SCROLL_MESSAGE_HPP_ */
|
||||
|
||||
10
source/Core/Inc/Types.h
Normal file
10
source/Core/Inc/Types.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef TYPES_H_
|
||||
#define TYPES_H_
|
||||
#include <stddef.h>
|
||||
|
||||
// Used for temperature represented in C or x10C.
|
||||
//
|
||||
|
||||
typedef int32_t TemperatureType_t;
|
||||
|
||||
#endif
|
||||
@@ -2,10 +2,11 @@
|
||||
#define __MAIN_H
|
||||
#include "OLED.hpp"
|
||||
#include "Setup.h"
|
||||
#include "Types.h"
|
||||
#include <stdint.h>
|
||||
extern volatile uint32_t currentTempTargetDegC;
|
||||
extern bool settingsWereReset;
|
||||
extern bool usb_pd_available;
|
||||
extern volatile TemperatureType_t currentTempTargetDegC;
|
||||
extern bool settingsWereReset;
|
||||
extern bool usb_pd_available;
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@@ -23,7 +23,6 @@ const uint8_t wattHistoryFilter = 24; //
|
||||
extern expMovingAverage<uint32_t, wattHistoryFilter> x10WattHistory;
|
||||
|
||||
uint32_t availableW10(uint8_t sample);
|
||||
int32_t tempToX10Watts(int32_t rawTemp);
|
||||
void setTipX10Watts(int32_t mw);
|
||||
uint8_t X10WattsToPWM(int32_t milliWatts, uint8_t sample = 0);
|
||||
#endif /* POWER_HPP_ */
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
#define GUI_HPP_
|
||||
#include "BSP.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "Buttons.hpp"
|
||||
#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)
|
||||
@@ -36,8 +36,9 @@ typedef struct {
|
||||
uint8_t shortDescriptionSize;
|
||||
} menuitem;
|
||||
|
||||
void enterSettingsMenu();
|
||||
void warnUser(const char *warning, const TickType_t timeout);
|
||||
extern const menuitem rootSettingsMenu[];
|
||||
void enterSettingsMenu();
|
||||
bool warnUser(const char *warning, const ButtonState buttons);
|
||||
extern const menuitem rootSettingsMenu[];
|
||||
extern const menuitem *subSettingsMenus[];
|
||||
|
||||
#endif /* GUI_HPP_ */
|
||||
|
||||
@@ -28,19 +28,20 @@ static uint16_t str_display_len(const char *const str) {
|
||||
return count;
|
||||
}
|
||||
|
||||
uint16_t ScrollMessage::messageWidth(const char *message) { return FONT_12_WIDTH * str_display_len(message); }
|
||||
/**
|
||||
* Calculate the width in pixels of the message string, in the large
|
||||
* font and taking into account multi-byte chars.
|
||||
*
|
||||
* @param message The null-terminated message string.
|
||||
*/
|
||||
uint16_t messageWidth(const char *message) { return FONT_12_WIDTH * str_display_len(message); }
|
||||
|
||||
bool ScrollMessage::drawUpdate(const char *message, TickType_t currentTick) {
|
||||
bool lcdRefresh = false;
|
||||
void drawScrollingText(const char *message, TickType_t currentTickOffset) {
|
||||
|
||||
if (messageStart == 0) {
|
||||
messageStart = currentTick;
|
||||
lcdRefresh = true;
|
||||
}
|
||||
int16_t messageOffset;
|
||||
uint16_t msgWidth = messageWidth(message);
|
||||
if (msgWidth > OLED_WIDTH) {
|
||||
messageOffset = ((currentTick - messageStart) / (getSettingValue(SettingsOptions::DescriptionScrollSpeed) == 1 ? TICKS_100MS / 10 : (TICKS_100MS / 5)));
|
||||
messageOffset = (currentTickOffset / (getSettingValue(SettingsOptions::DescriptionScrollSpeed) == 1 ? TICKS_100MS / 10 : (TICKS_100MS / 5)));
|
||||
messageOffset %= msgWidth + OLED_WIDTH; // Roll around at the end
|
||||
if (messageOffset < OLED_WIDTH) {
|
||||
// Snap the message to the left edge.
|
||||
@@ -54,15 +55,7 @@ bool ScrollMessage::drawUpdate(const char *message, TickType_t currentTick) {
|
||||
messageOffset = (OLED_WIDTH - msgWidth) / 2 + msgWidth;
|
||||
}
|
||||
|
||||
if (lastOffset != messageOffset) {
|
||||
OLED::clearScreen();
|
||||
|
||||
//^ Rolling offset based on time
|
||||
OLED::setCursor((OLED_WIDTH - messageOffset), 0);
|
||||
OLED::print(message, FontStyle::LARGE);
|
||||
lastOffset = messageOffset;
|
||||
lcdRefresh = true;
|
||||
}
|
||||
|
||||
return lcdRefresh;
|
||||
//^ Rolling offset based on time
|
||||
OLED::setCursor((OLED_WIDTH - messageOffset), 0);
|
||||
OLED::print(message, FontStyle::LARGE);
|
||||
}
|
||||
|
||||
@@ -27,14 +27,6 @@ bool shouldBeUsingFastPWMMode(const uint8_t pwmTicks) {
|
||||
return lastPWMWasFast;
|
||||
}
|
||||
|
||||
int32_t tempToX10Watts(int32_t rawTemp) {
|
||||
// mass is in x10J/*C, rawC is raw per degree C
|
||||
// returns x10Watts needed to raise/lower a mass by rawTemp
|
||||
// degrees in one cycle.
|
||||
int32_t x10Watts = TIP_THERMAL_MASS * rawTemp;
|
||||
return x10Watts;
|
||||
}
|
||||
|
||||
void setTipX10Watts(int32_t mw) {
|
||||
int32_t outputPWMLevel = X10WattsToPWM(mw, 1);
|
||||
const bool shouldUseFastPWM = shouldBeUsingFastPWMMode(outputPWMLevel);
|
||||
|
||||
@@ -120,17 +120,12 @@ static bool showHallEffect(void);
|
||||
|
||||
#if defined(POW_DC) || defined(POW_QC)
|
||||
static void displayPowerMenu(void);
|
||||
static bool enterPowerMenu(void);
|
||||
#endif /* POW_DC or POW_QC */
|
||||
|
||||
static void displaySolderingMenu(void);
|
||||
static bool enterSolderingMenu(void);
|
||||
static void displayPowerSavingMenu(void);
|
||||
static bool enterPowerSavingMenu(void);
|
||||
static void displayUIMenu(void);
|
||||
static bool enterUIMenu(void);
|
||||
static void displayAdvancedMenu(void);
|
||||
static bool enterAdvancedMenu(void);
|
||||
|
||||
/*
|
||||
* Root Settings Menu
|
||||
@@ -216,16 +211,16 @@ const menuitem rootSettingsMenu[] {
|
||||
*/
|
||||
#if defined(POW_DC) || defined(POW_QC)
|
||||
/* Power */
|
||||
{0, enterPowerMenu, displayPowerMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0},
|
||||
{0, nullptr, displayPowerMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0},
|
||||
#endif
|
||||
/* Soldering */
|
||||
{0, enterSolderingMenu, displaySolderingMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0},
|
||||
{0, nullptr, displaySolderingMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0},
|
||||
/* Sleep Options Menu */
|
||||
{0, enterPowerSavingMenu, displayPowerSavingMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0},
|
||||
{0, nullptr, displayPowerSavingMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0},
|
||||
/* UI Menu */
|
||||
{0, enterUIMenu, displayUIMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0},
|
||||
{0, nullptr, displayUIMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0},
|
||||
/* Advanced Menu */
|
||||
{0, enterAdvancedMenu, displayAdvancedMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0},
|
||||
{0, nullptr, displayAdvancedMenu, nullptr, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0},
|
||||
/* Language Switch */
|
||||
{0, settings_setLanguageSwitch, settings_displayLanguageSwitch, settings_showLanguageSwitch, SettingsOptions::SettingsOptionsLength, SettingsItemIndex::NUM_ITEMS, 0},
|
||||
/* vvvv end of menu marker. DO NOT REMOVE vvvv */
|
||||
@@ -440,6 +435,12 @@ const menuitem advancedMenu[] = {
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
const menuitem *subSettingsMenus[] {
|
||||
#if defined(POW_DC) || defined(POW_QC) || defined(POW_PD)
|
||||
powerMenu,
|
||||
#endif
|
||||
solderingMenu, PowerSavingMenu, UIMenu, advancedMenu,
|
||||
};
|
||||
/* ^^^ !!!ENABLE CLANG-FORMAT back!!! ^^^ */
|
||||
|
||||
/**
|
||||
@@ -460,10 +461,9 @@ static void printShortDescription(SettingsItemIndex settingsItemIndex, uint16_t
|
||||
}
|
||||
|
||||
static int userConfirmation(const char *message) {
|
||||
ScrollMessage scrollMessage;
|
||||
|
||||
TickType_t tickStart = xTaskGetTickCount();
|
||||
for (;;) {
|
||||
bool lcdRefresh = scrollMessage.drawUpdate(message, xTaskGetTickCount());
|
||||
drawScrollingText(message, xTaskGetTickCount() - tickStart);
|
||||
|
||||
ButtonState buttons = getButtonState();
|
||||
switch (buttons) {
|
||||
@@ -481,10 +481,8 @@ static int userConfirmation(const char *message) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lcdRefresh) {
|
||||
OLED::refresh();
|
||||
osDelay(40);
|
||||
}
|
||||
OLED::refresh();
|
||||
osDelay(40);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -826,13 +824,13 @@ static void displayAnimationLoop(void) { OLED::drawCheckbox(getSettingValue(Sett
|
||||
|
||||
static void displayBrightnessLevel(void) {
|
||||
OLED::printNumber((getSettingValue(SettingsOptions::OLEDBrightness) / BRIGHTNESS_STEP + 1), 1, FontStyle::LARGE);
|
||||
// While not optimal to apply this here, it is _very_ convienient
|
||||
// While not optimal to apply this here, it is _very_ convenient
|
||||
OLED::setBrightness(getSettingValue(SettingsOptions::OLEDBrightness));
|
||||
}
|
||||
|
||||
static void displayInvertColor(void) {
|
||||
OLED::drawCheckbox(getSettingValue(SettingsOptions::OLEDInversion));
|
||||
// While not optimal to apply this here, it is _very_ convienient
|
||||
// While not optimal to apply this here, it is _very_ convenient
|
||||
OLED::setInverseDisplay(getSettingValue(SettingsOptions::OLEDInversion));
|
||||
}
|
||||
|
||||
@@ -942,7 +940,7 @@ static void displayPowerPulseDuration(void) { OLED::printNumber(getSettingValue(
|
||||
static bool setResetSettings(void) {
|
||||
if (userConfirmation(translatedString(Tr->SettingsResetWarning))) {
|
||||
resetSettings();
|
||||
warnUser(translatedString(Tr->ResetOKMessage), 3 * TICKS_SECOND);
|
||||
// warnUser(translatedString(Tr->ResetOKMessage), buttons); //TODO
|
||||
reboot();
|
||||
}
|
||||
return false;
|
||||
@@ -1026,214 +1024,3 @@ static bool enterAdvancedMenu(void) {
|
||||
gui_Menu(advancedMenu);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t gui_getMenuLength(const menuitem *menu) {
|
||||
uint8_t scrollContentSize = 0;
|
||||
for (uint8_t i = 0; menu[i].draw != nullptr; i++) {
|
||||
if (menu[i].isVisible == nullptr) {
|
||||
scrollContentSize += 1; // Always visible
|
||||
} else if (menu[i].isVisible()) {
|
||||
scrollContentSize += 1; // Selectively visible and chosen to show
|
||||
}
|
||||
}
|
||||
return scrollContentSize;
|
||||
}
|
||||
|
||||
void gui_Menu(const menuitem *menu) {
|
||||
// Draw the settings menu and provide iteration support etc
|
||||
|
||||
// This is used to detect whether a menu-exit transition should be played.
|
||||
static bool wasInGuiMenu;
|
||||
wasInGuiMenu = true;
|
||||
|
||||
enum class NavState {
|
||||
Idle,
|
||||
Entering,
|
||||
ScrollingDown,
|
||||
Exiting,
|
||||
};
|
||||
|
||||
uint8_t currentScreen = 0; // Current screen index in the menu struct
|
||||
uint8_t screensSkipped = 0; // Number of screens skipped due to being disabled
|
||||
TickType_t autoRepeatTimer = 0;
|
||||
TickType_t autoRepeatAcceleration = 0;
|
||||
bool earlyExit = false;
|
||||
bool lcdRefresh = true;
|
||||
|
||||
ButtonState lastButtonState = BUTTON_NONE;
|
||||
uint8_t scrollContentSize = gui_getMenuLength(menu);
|
||||
|
||||
bool scrollBlink = false;
|
||||
bool lastValue = false;
|
||||
NavState navState = NavState::Entering;
|
||||
|
||||
ScrollMessage scrollMessage;
|
||||
|
||||
while ((menu[currentScreen].draw != nullptr) && earlyExit == false) {
|
||||
bool valueChanged = false;
|
||||
// Handle menu transition:
|
||||
if (navState != NavState::Idle) {
|
||||
// Check if this menu item shall be skipped. If it shall be skipped,
|
||||
// `draw()` returns true. Draw on the secondary framebuffer as we want
|
||||
// to keep the primary framebuffer intact for the upcoming transition
|
||||
// animation.
|
||||
OLED::useSecondaryFramebuffer(true);
|
||||
if (menu[currentScreen].isVisible != nullptr) {
|
||||
if (!menu[currentScreen].isVisible()) {
|
||||
currentScreen++;
|
||||
screensSkipped++;
|
||||
OLED::useSecondaryFramebuffer(false);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
animOpenState = true;
|
||||
// The menu entering/exiting transition uses the secondary framebuffer,
|
||||
// but the scroll down transition does not.
|
||||
OLED::setCursor(0, 0);
|
||||
OLED::clearScreen();
|
||||
if (menu[currentScreen].shortDescriptionSize > 0) {
|
||||
printShortDescription(menu[currentScreen].shortDescriptionIndex, menu[currentScreen].shortDescriptionSize);
|
||||
}
|
||||
menu[currentScreen].draw();
|
||||
if (navState == NavState::ScrollingDown) {
|
||||
// Play the scroll down animation.
|
||||
OLED::maskScrollIndicatorOnOLED();
|
||||
OLED::transitionScrollDown();
|
||||
OLED::useSecondaryFramebuffer(false);
|
||||
} else {
|
||||
// The menu was drawn in a secondary framebuffer.
|
||||
// Now we play a transition from the pre-drawn primary
|
||||
// framebuffer to the new buffer.
|
||||
// The extra buffer is discarded at the end of the transition.
|
||||
OLED::useSecondaryFramebuffer(false);
|
||||
OLED::transitionSecondaryFramebuffer(navState == NavState::Entering);
|
||||
}
|
||||
animOpenState = false;
|
||||
navState = NavState::Idle;
|
||||
}
|
||||
|
||||
// If the user has hesitated for >=3 seconds, show the long text
|
||||
// Otherwise "draw" the option
|
||||
if ((xTaskGetTickCount() - lastButtonTime < (TICKS_SECOND * 3)) || menu[currentScreen].description == 0) {
|
||||
lcdRefresh = true;
|
||||
OLED::setCursor(0, 0);
|
||||
OLED::clearScreen();
|
||||
if (menu[currentScreen].shortDescriptionSize > 0) {
|
||||
printShortDescription(menu[currentScreen].shortDescriptionIndex, menu[currentScreen].shortDescriptionSize);
|
||||
}
|
||||
menu[currentScreen].draw();
|
||||
uint8_t indicatorHeight = OLED_HEIGHT / scrollContentSize;
|
||||
uint8_t position = OLED_HEIGHT * (currentScreen - screensSkipped) / scrollContentSize;
|
||||
if (lastValue) {
|
||||
scrollBlink = !scrollBlink;
|
||||
}
|
||||
if (!lastValue || !scrollBlink) {
|
||||
OLED::drawScrollIndicator(position, indicatorHeight);
|
||||
}
|
||||
} else {
|
||||
// Draw description
|
||||
const char *description = translatedString(Tr->SettingsDescriptions[menu[currentScreen].description - 1]);
|
||||
lcdRefresh |= scrollMessage.drawUpdate(description, xTaskGetTickCount());
|
||||
}
|
||||
|
||||
if (lcdRefresh) {
|
||||
OLED::refresh(); // update the LCD
|
||||
osDelay(40);
|
||||
lcdRefresh = false;
|
||||
}
|
||||
|
||||
ButtonState buttons = getButtonState();
|
||||
|
||||
if (buttons != lastButtonState) {
|
||||
autoRepeatAcceleration = 0;
|
||||
lastButtonState = buttons;
|
||||
}
|
||||
|
||||
auto callIncrementHandler = [&]() {
|
||||
wasInGuiMenu = false;
|
||||
valueChanged = true;
|
||||
bool res = false;
|
||||
if ((int)menu[currentScreen].autoSettingOption < (int)SettingsOptions::SettingsOptionsLength) {
|
||||
res = nextSettingValue(menu[currentScreen].autoSettingOption);
|
||||
} else if (menu[currentScreen].incrementHandler != nullptr) {
|
||||
res = menu[currentScreen].incrementHandler();
|
||||
} else {
|
||||
earlyExit = true;
|
||||
}
|
||||
if (wasInGuiMenu) {
|
||||
navState = NavState::Exiting;
|
||||
}
|
||||
wasInGuiMenu = true;
|
||||
return res;
|
||||
};
|
||||
|
||||
switch (buttons) {
|
||||
case BUTTON_BOTH:
|
||||
earlyExit = true; // will make us exit next loop
|
||||
scrollMessage.reset();
|
||||
break;
|
||||
case BUTTON_F_SHORT:
|
||||
// increment
|
||||
if (scrollMessage.isReset()) {
|
||||
lastValue = callIncrementHandler();
|
||||
} else {
|
||||
scrollMessage.reset();
|
||||
}
|
||||
break;
|
||||
case BUTTON_B_SHORT:
|
||||
if (scrollMessage.isReset()) {
|
||||
currentScreen++;
|
||||
navState = NavState::ScrollingDown;
|
||||
lastValue = false;
|
||||
} else {
|
||||
scrollMessage.reset();
|
||||
}
|
||||
break;
|
||||
case BUTTON_F_LONG:
|
||||
if (xTaskGetTickCount() + autoRepeatAcceleration > autoRepeatTimer + PRESS_ACCEL_INTERVAL_MAX) {
|
||||
if ((lastValue = callIncrementHandler())) {
|
||||
autoRepeatTimer = 1000;
|
||||
} else {
|
||||
autoRepeatTimer = 0;
|
||||
}
|
||||
autoRepeatTimer += xTaskGetTickCount();
|
||||
scrollMessage.reset();
|
||||
autoRepeatAcceleration += PRESS_ACCEL_STEP;
|
||||
}
|
||||
break;
|
||||
case BUTTON_B_LONG:
|
||||
if (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration > PRESS_ACCEL_INTERVAL_MAX) {
|
||||
currentScreen++;
|
||||
navState = NavState::ScrollingDown;
|
||||
autoRepeatTimer = xTaskGetTickCount();
|
||||
scrollMessage.reset();
|
||||
autoRepeatAcceleration += PRESS_ACCEL_STEP;
|
||||
}
|
||||
break;
|
||||
case BUTTON_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ((PRESS_ACCEL_INTERVAL_MAX - autoRepeatAcceleration) < PRESS_ACCEL_INTERVAL_MIN) {
|
||||
autoRepeatAcceleration = PRESS_ACCEL_INTERVAL_MAX - PRESS_ACCEL_INTERVAL_MIN;
|
||||
}
|
||||
|
||||
if ((xTaskGetTickCount() - lastButtonTime) > (TICKS_SECOND * 2 * 60)) {
|
||||
// If user has not pressed any buttons in 30 seconds, exit back a menu layer
|
||||
// This will trickle the user back to the main screen eventually
|
||||
earlyExit = true;
|
||||
scrollMessage.reset();
|
||||
}
|
||||
if (valueChanged) {
|
||||
// If user changed value, update the scroll content size
|
||||
scrollContentSize = gui_getMenuLength(menu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void enterSettingsMenu() {
|
||||
gui_Menu(rootSettingsMenu); // Call the root menu
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
40
source/Core/Threads/GUIRendering.md
Normal file
40
source/Core/Threads/GUIRendering.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# GUI Rendering
|
||||
|
||||
The GUI aims to be somewhat similar to immediate mode rendering, where the screen is re-rendered each sweep.
|
||||
This is due to a few aims:
|
||||
|
||||
1. Functions should try and contain their state to the context struct (helps keep state usage flatter)
|
||||
2. Allows external events to change the state
|
||||
3. Means state can be read/write over BLE or other external control interfaces
|
||||
|
||||
## Transitions
|
||||
|
||||
When changing the view to a new view it can be preferable to transition using an animation.
|
||||
The tooling provides for left, right and down animations at this point.
|
||||
The use of these gives a notion of "direction" when navigating the menu.
|
||||
|
||||
```
|
||||
┌───────────┐
|
||||
│ Debug Menu│
|
||||
└─────┬─────┘
|
||||
│
|
||||
│
|
||||
│
|
||||
┌──────────────┐ ┌────┴─────┐ ┌──────────────────┐ ┌─────────────────┐
|
||||
│Soldering Mode│ │ │ │ │ │ │
|
||||
│ OR ├───────────┤Home Menu ├───────────┤Settings Main Menu├───────────┤Settings sub menu│
|
||||
│Reflow Mode│ │ │ │ │ │ │
|
||||
└──────────────┘ └──────────┘ └──────────────────┘ └─────────┬───────┘
|
||||
│
|
||||
┌─────────┴───────┐
|
||||
│ │
|
||||
│Settings sub menu│
|
||||
│ │
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
The downside of supporting transitions is that for these to work, the code should render the screen _first_ then return the new state.
|
||||
This ensures there is a good working copy in the buffer before the transition changes the view.
|
||||
|
||||
The code that handles the dispatch will run a new render pass again to get the new buffer contents and then transition between the two for you.
|
||||
At the moment scrolling "Up" isn't implemented but the enumeration is there so that its implementation can follow.
|
||||
@@ -31,8 +31,159 @@ extern "C" {
|
||||
#include "pd.h"
|
||||
#endif
|
||||
// File local variables
|
||||
#define MOVEMENT_INACTIVITY_TIME (60 * configTICK_RATE_HZ)
|
||||
#define BUTTON_INACTIVITY_TIME (60 * configTICK_RATE_HZ)
|
||||
|
||||
extern bool heaterThermalRunaway;
|
||||
ButtonState buttonsAtDeviceBoot; // We record button state at startup, incase of jumping to debug modes
|
||||
OperatingMode currentOperatingMode = OperatingMode::InitialisationDone; // Current mode we are rendering
|
||||
guiContext context; // Context passed to functions to aid in state during render passes
|
||||
|
||||
OperatingMode handle_post_init_state();
|
||||
OperatingMode guiHandleDraw(void) {
|
||||
OLED::clearScreen(); // Clear ready for render pass
|
||||
// Read button state
|
||||
ButtonState buttons = getButtonState();
|
||||
// Enforce screen on if buttons pressed, movement, hot tip etc
|
||||
// if (buttons != BUTTON_NONE) {
|
||||
// OLED::setDisplayState(OLED::DisplayState::ON);
|
||||
// } else {
|
||||
// // Buttons are none; check if we can sleep display
|
||||
// uint32_t tipTemp = TipThermoModel::getTipInC();
|
||||
// if ((tipTemp < 50) && getSettingValue(SettingsOptions::Sensitivity)
|
||||
// && (((xTaskGetTickCount() - lastMovementTime) > MOVEMENT_INACTIVITY_TIME) && ((xTaskGetTickCount() - lastButtonTime) > BUTTON_INACTIVITY_TIME))) {
|
||||
// OLED::setDisplayState(OLED::DisplayState::OFF);
|
||||
// setStatusLED(LED_OFF);
|
||||
// } else {
|
||||
// OLED::setDisplayState(OLED::DisplayState::ON);
|
||||
// if (tipTemp > 55) {
|
||||
// setStatusLED(LED_COOLING_STILL_HOT);
|
||||
// } else {
|
||||
// setStatusLED(LED_STANDBY);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// Dispatch button state to gui mode
|
||||
OperatingMode newMode = currentOperatingMode;
|
||||
switch (currentOperatingMode) {
|
||||
case OperatingMode::StartupWarnings:
|
||||
newMode = showWarnings(buttons, &context);
|
||||
break;
|
||||
case OperatingMode::UsbPDDebug:
|
||||
#ifdef HAS_POWER_DEBUG_MENU
|
||||
newMode = showPDDebug(buttons, &context);
|
||||
break;
|
||||
#else
|
||||
newMode = OperatingMode::InitialisationDone;
|
||||
#endif
|
||||
case OperatingMode::StartupLogo:
|
||||
BootLogo::handleShowingLogo((uint8_t *)FLASH_LOGOADDR); // TODO needs refactor
|
||||
if (getSettingValue(SettingsOptions::AutoStartMode) == 1) {
|
||||
// jump directly to the autostart mode
|
||||
newMode = OperatingMode::Sleeping;
|
||||
} else if (getSettingValue(SettingsOptions::AutoStartMode) == 2) {
|
||||
newMode = OperatingMode::Hibernating;
|
||||
} else {
|
||||
newMode = OperatingMode::HomeScreen;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Fallthrough */
|
||||
case OperatingMode::HomeScreen:
|
||||
newMode = drawHomeScreen(buttons, &context);
|
||||
break;
|
||||
case OperatingMode::Soldering:
|
||||
newMode = gui_solderingMode(buttons, &context);
|
||||
break;
|
||||
case OperatingMode::SolderingProfile:
|
||||
newMode = gui_solderingProfileMode(buttons, &context);
|
||||
break;
|
||||
case OperatingMode::Sleeping:
|
||||
newMode = gui_SolderingSleepingMode(buttons, &context);
|
||||
break;
|
||||
case OperatingMode::TemperatureAdjust:
|
||||
newMode = gui_solderingTempAdjust(buttons, &context);
|
||||
break;
|
||||
case OperatingMode::DebugMenuReadout:
|
||||
newMode = showDebugMenu(buttons, &context);
|
||||
break;
|
||||
case OperatingMode::CJCCalibration:
|
||||
newMode = performCJCC(buttons, &context);
|
||||
break;
|
||||
case OperatingMode::SettingsMenu:
|
||||
newMode = gui_SettingsMenu(buttons, &context);
|
||||
break;
|
||||
case OperatingMode::InitialisationDone:
|
||||
newMode = handle_post_init_state();
|
||||
break;
|
||||
case OperatingMode::Hibernating:
|
||||
newMode = OperatingMode::HomeScreen;
|
||||
break;
|
||||
case OperatingMode::ThermalRunaway:
|
||||
newMode = OperatingMode::HomeScreen;
|
||||
break;
|
||||
};
|
||||
return newMode;
|
||||
}
|
||||
void guiRenderLoop(void) {
|
||||
OperatingMode newMode = guiHandleDraw(); // This does the screen drawing
|
||||
|
||||
// Post draw we handle any state transitions
|
||||
|
||||
if (newMode != currentOperatingMode) {
|
||||
context.viewEnterTime = xTaskGetTickCount();
|
||||
context.previousMode = currentOperatingMode;
|
||||
memset(&context.scratch_state, 0, sizeof(context.scratch_state));
|
||||
currentOperatingMode = newMode;
|
||||
}
|
||||
// If the transition marker is set, we need to make the next draw occur to the secondary buffer so we have something to transition to
|
||||
if (context.transitionMode != TransitionAnimation::None) {
|
||||
OLED::useSecondaryFramebuffer(true);
|
||||
// Now we need to fill the secondary buffer with the _next_ frame to transistion to
|
||||
guiHandleDraw();
|
||||
OLED::useSecondaryFramebuffer(false);
|
||||
// Now dispatch the transition
|
||||
switch (context.transitionMode) {
|
||||
case TransitionAnimation::Down:
|
||||
OLED::transitionScrollDown(context.viewEnterTime);
|
||||
break;
|
||||
case TransitionAnimation::Left:
|
||||
OLED::transitionSecondaryFramebuffer(false, context.viewEnterTime);
|
||||
break;
|
||||
case TransitionAnimation::Right:
|
||||
OLED::transitionSecondaryFramebuffer(true, context.viewEnterTime);
|
||||
break;
|
||||
case TransitionAnimation::Up:
|
||||
OLED::transitionScrollUp(context.viewEnterTime);
|
||||
|
||||
case TransitionAnimation::None:
|
||||
default:
|
||||
break; // Do nothing on unknown
|
||||
}
|
||||
|
||||
context.transitionMode = TransitionAnimation::None; // Clear transition flag
|
||||
}
|
||||
// Render done, draw it out
|
||||
OLED::refresh();
|
||||
}
|
||||
|
||||
OperatingMode handle_post_init_state() {
|
||||
#ifdef HAS_POWER_DEBUG_MENU
|
||||
#ifdef DEBUG_POWER_MENU_BUTTON_B
|
||||
if (buttonsAtDeviceBoot == BUTTON_B_LONG || buttonsAtDeviceBoot == BUTTON_B_SHORT) {
|
||||
#else
|
||||
if (buttonsAtDeviceBoot == BUTTON_F_LONG || buttonsAtDeviceBoot == BUTTON_F_SHORT) {
|
||||
#endif
|
||||
buttonsAtDeviceBoot = BUTTON_NONE;
|
||||
return OperatingMode::UsbPDDebug;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (getSettingValue(SettingsOptions::CalibrateCJC) > 0) {
|
||||
return OperatingMode::CJCCalibration;
|
||||
}
|
||||
|
||||
return OperatingMode::StartupLogo;
|
||||
}
|
||||
|
||||
/* StartGUITask function */
|
||||
void startGUITask(void const *argument) {
|
||||
@@ -46,43 +197,34 @@ void startGUITask(void const *argument) {
|
||||
bool buttonLockout = false;
|
||||
renderHomeScreenAssets();
|
||||
getTipRawTemp(1); // reset filter
|
||||
memset(&context, 0, sizeof(context));
|
||||
|
||||
OLED::setRotation(getSettingValue(SettingsOptions::OrientationMode) & 1);
|
||||
// If the front button is held down, on supported devices, show PD debugging metrics
|
||||
#ifdef HAS_POWER_DEBUG_MENU
|
||||
#ifdef DEBUG_POWER_MENU_BUTTON_B
|
||||
if (getButtonB()) {
|
||||
#else
|
||||
|
||||
// // If the boot logo is enabled with timeout and the autostart mode is enabled (but not set to sleep w/o heat), start heating during boot logo
|
||||
// if (getSettingValue(SettingsOptions::LOGOTime) > 0 && getSettingValue(SettingsOptions::LOGOTime) < 5 && getSettingValue(SettingsOptions::AutoStartMode) > 0
|
||||
// && getSettingValue(SettingsOptions::AutoStartMode) < 3) {
|
||||
// uint16_t sleepTempDegC;
|
||||
// if (getSettingValue(SettingsOptions::TemperatureInF)) {
|
||||
// sleepTempDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::SleepTemp));
|
||||
// } else {
|
||||
// sleepTempDegC = getSettingValue(SettingsOptions::SleepTemp);
|
||||
// }
|
||||
// // Only heat to sleep temperature (but no higher than 75°C for safety)
|
||||
// currentTempTargetDegC = min(sleepTempDegC, 75);
|
||||
// }
|
||||
// Read boot button state
|
||||
if (getButtonA()) {
|
||||
#endif
|
||||
showPDDebug();
|
||||
buttonsAtDeviceBoot = BUTTON_F_LONG;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (getSettingValue(SettingsOptions::CalibrateCJC) > 0) {
|
||||
performCJCC();
|
||||
if (getButtonB()) {
|
||||
buttonsAtDeviceBoot = BUTTON_B_LONG;
|
||||
}
|
||||
|
||||
// If the boot logo is enabled (but it times out) and the autostart mode is enabled (but not set to sleep w/o heat), start heating during boot logo
|
||||
if (getSettingValue(SettingsOptions::LOGOTime) > 0 && getSettingValue(SettingsOptions::LOGOTime) < 5 && getSettingValue(SettingsOptions::AutoStartMode) > 0
|
||||
&& getSettingValue(SettingsOptions::AutoStartMode) < 3) {
|
||||
uint16_t sleepTempDegC;
|
||||
if (getSettingValue(SettingsOptions::TemperatureInF)) {
|
||||
sleepTempDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::SleepTemp));
|
||||
} else {
|
||||
sleepTempDegC = getSettingValue(SettingsOptions::SleepTemp);
|
||||
}
|
||||
// Only heat to sleep temperature (but no higher than 75°C for safety)
|
||||
currentTempTargetDegC = min(sleepTempDegC, 75);
|
||||
TickType_t startRender = xTaskGetTickCount();
|
||||
for (;;) {
|
||||
guiRenderLoop();
|
||||
resetWatchdog();
|
||||
vTaskDelayUntil(&startRender, TICKS_100MS * 4 / 10); // Try and maintain 20-25fps ish update rate, way to fast but if we can its nice
|
||||
}
|
||||
|
||||
showBootLogo();
|
||||
showWarnings();
|
||||
if (getSettingValue(SettingsOptions::AutoStartMode)) {
|
||||
// jump directly to the autostart mode
|
||||
gui_solderingMode(getSettingValue(SettingsOptions::AutoStartMode) - 1);
|
||||
buttonLockout = true;
|
||||
}
|
||||
|
||||
drawHomeScreen(buttonLockout);
|
||||
}
|
||||
|
||||
@@ -1,39 +1,38 @@
|
||||
|
||||
|
||||
#include "OperatingModes.h"
|
||||
void performCJCC(void) {
|
||||
OperatingMode performCJCC(const ButtonState buttons, guiContext *cxt) {
|
||||
// Calibrate Cold Junction Compensation directly at boot, before internal components get warm.
|
||||
OLED::refresh();
|
||||
osDelay(50);
|
||||
if (!isTipDisconnected() && abs(int(TipThermoModel::getTipInC() - getHandleTemperature(0) / 10)) < 10) {
|
||||
uint16_t setoffset = 0;
|
||||
// Take 16 samples
|
||||
if (cxt->scratch_state.state1 < 16) {
|
||||
cxt->scratch_state.state3 += getTipRawTemp(1);
|
||||
OLED::setCursor(0, 0);
|
||||
OLED::print(translatedString(Tr->CJCCalibrating), FontStyle::SMALL);
|
||||
OLED::setCursor(0, 8);
|
||||
OLED::print(SmallSymbolDot, FontStyle::SMALL);
|
||||
for (uint8_t x = 0; x < (cxt->scratch_state.state1 / 4); x++) {
|
||||
OLED::print(SmallSymbolDot, FontStyle::SMALL);
|
||||
}
|
||||
|
||||
cxt->scratch_state.state1++;
|
||||
return OperatingMode::CJCCalibration;
|
||||
}
|
||||
|
||||
// If the thermo-couple at the end of the tip, and the handle are at
|
||||
// equilibrium, then the output should be zero, as there is no temperature
|
||||
// differential.
|
||||
while (setoffset == 0) {
|
||||
uint32_t offset = 0;
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
offset += getTipRawTemp(1);
|
||||
// cycle through the filter a fair bit to ensure we're stable.
|
||||
OLED::clearScreen();
|
||||
OLED::setCursor(0, 0);
|
||||
OLED::print(translatedString(Tr->CJCCalibrating), FontStyle::SMALL);
|
||||
OLED::setCursor(0, 8);
|
||||
OLED::print(SmallSymbolDot, FontStyle::SMALL);
|
||||
for (uint8_t x = 0; x < (i / 4); x++) {
|
||||
OLED::print(SmallSymbolDot, FontStyle::SMALL);
|
||||
}
|
||||
OLED::refresh();
|
||||
osDelay(100);
|
||||
}
|
||||
setoffset = TipThermoModel::convertTipRawADCTouV(offset / 16, true);
|
||||
|
||||
uint16_t setOffset = TipThermoModel::convertTipRawADCTouV(cxt->scratch_state.state3 / 16, true);
|
||||
setSettingValue(SettingsOptions::CalibrationOffset, setOffset);
|
||||
if (warnUser(translatedString(Tr->CJCCalibrationDone), buttons)) {
|
||||
// Preventing to repeat calibration at boot automatically (only one shot).
|
||||
setSettingValue(SettingsOptions::CalibrateCJC, 0);
|
||||
saveSettings();
|
||||
return OperatingMode::InitialisationDone;
|
||||
}
|
||||
setSettingValue(SettingsOptions::CalibrationOffset, setoffset);
|
||||
OLED::clearScreen();
|
||||
warnUser(translatedString(Tr->CalibrationDone), 3 * TICKS_SECOND);
|
||||
OLED::refresh();
|
||||
// Preventing to repeat calibration at boot automatically (only one shot).
|
||||
setSettingValue(SettingsOptions::CalibrateCJC, 0);
|
||||
saveSettings();
|
||||
return OperatingMode::CJCCalibration;
|
||||
}
|
||||
// Cant run calibration without the tip and for temps to be close
|
||||
return OperatingMode::InitialisationDone;
|
||||
}
|
||||
|
||||
@@ -1,111 +1,102 @@
|
||||
#include "OperatingModes.h"
|
||||
extern osThreadId GUITaskHandle;
|
||||
extern osThreadId MOVTaskHandle;
|
||||
extern osThreadId PIDTaskHandle;
|
||||
extern OperatingMode currentMode;
|
||||
extern osThreadId GUITaskHandle;
|
||||
extern osThreadId MOVTaskHandle;
|
||||
extern osThreadId PIDTaskHandle;
|
||||
|
||||
void showDebugMenu(void) {
|
||||
currentMode = OperatingMode::debug;
|
||||
uint8_t screen = 0;
|
||||
ButtonState b;
|
||||
for (;;) {
|
||||
OLED::clearScreen(); // Ensure the buffer starts clean
|
||||
OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left)
|
||||
OLED::print(SmallSymbolVersionNumber, FontStyle::SMALL); // Print version number
|
||||
OLED::setCursor(0, 8); // second line
|
||||
OLED::print(DebugMenu[screen], FontStyle::SMALL);
|
||||
switch (screen) {
|
||||
case 0: // Build Date
|
||||
break;
|
||||
case 1: // Device ID
|
||||
{
|
||||
uint64_t id = getDeviceID();
|
||||
OperatingMode showDebugMenu(const ButtonState buttons, guiContext *cxt) {
|
||||
OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left)
|
||||
OLED::print(SmallSymbolVersionNumber, FontStyle::SMALL); // Print version number
|
||||
OLED::setCursor(0, 8); // second line
|
||||
OLED::print(DebugMenu[cxt->scratch_state.state1], FontStyle::SMALL);
|
||||
switch (cxt->scratch_state.state1) {
|
||||
case 0: // Build Date
|
||||
break;
|
||||
case 1: // Device ID
|
||||
{
|
||||
uint64_t id = getDeviceID();
|
||||
#ifdef DEVICE_HAS_VALIDATION_CODE
|
||||
// If device has validation code; then we want to take over both lines of the screen
|
||||
OLED::clearScreen(); // Ensure the buffer starts clean
|
||||
OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left)
|
||||
OLED::print(DebugMenu[screen], FontStyle::SMALL);
|
||||
OLED::drawHex(getDeviceValidation(), FontStyle::SMALL, 8);
|
||||
OLED::setCursor(0, 8); // second line
|
||||
// If device has validation code; then we want to take over both lines of the screen
|
||||
OLED::clearScreen(); // Ensure the buffer starts clean
|
||||
OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left)
|
||||
OLED::print(DebugMenu[cxt->scratch_state.state1], FontStyle::SMALL);
|
||||
OLED::drawHex(getDeviceValidation(), FontStyle::SMALL, 8);
|
||||
OLED::setCursor(0, 8); // second line
|
||||
#endif
|
||||
OLED::drawHex((uint32_t)(id >> 32), FontStyle::SMALL, 8);
|
||||
OLED::drawHex((uint32_t)(id & 0xFFFFFFFF), FontStyle::SMALL, 8);
|
||||
} break;
|
||||
case 2: // ACC Type
|
||||
OLED::print(AccelTypeNames[(int)DetectedAccelerometerVersion], FontStyle::SMALL);
|
||||
break;
|
||||
case 3: // Power Negotiation Status
|
||||
OLED::print(PowerSourceNames[getPowerSourceNumber()], FontStyle::SMALL);
|
||||
break;
|
||||
case 4: // Input Voltage
|
||||
printVoltage();
|
||||
break;
|
||||
case 5: // Temp in °C
|
||||
OLED::printNumber(TipThermoModel::getTipInC(), 6, FontStyle::SMALL);
|
||||
break;
|
||||
case 6: // Handle Temp in °C
|
||||
OLED::printNumber(getHandleTemperature(0) / 10, 6, FontStyle::SMALL);
|
||||
OLED::print(SmallSymbolDot, FontStyle::SMALL);
|
||||
OLED::printNumber(getHandleTemperature(0) % 10, 1, FontStyle::SMALL);
|
||||
break;
|
||||
case 7: // Max Temp Limit in °C
|
||||
OLED::printNumber(TipThermoModel::getTipMaxInC(), 6, FontStyle::SMALL);
|
||||
break;
|
||||
case 8: // System Uptime
|
||||
OLED::printNumber(xTaskGetTickCount() / TICKS_100MS, 8, FontStyle::SMALL);
|
||||
break;
|
||||
case 9: // Movement Timestamp
|
||||
OLED::printNumber(lastMovementTime / TICKS_100MS, 8, FontStyle::SMALL);
|
||||
break;
|
||||
case 10: // Tip Resistance in Ω large to pad over so that we cover ID left overs
|
||||
OLED::printNumber(getTipResistanceX10() / 10, 6, FontStyle::SMALL);
|
||||
OLED::print(SmallSymbolDot, FontStyle::SMALL);
|
||||
OLED::printNumber(getTipResistanceX10() % 10, 1, FontStyle::SMALL);
|
||||
break;
|
||||
case 11: // Raw Tip in µV
|
||||
OLED::printNumber(TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0), true), 8, FontStyle::SMALL);
|
||||
break;
|
||||
case 12: // Tip Cold Junction Compensation Offset in µV
|
||||
OLED::printNumber(getSettingValue(SettingsOptions::CalibrationOffset), 8, FontStyle::SMALL);
|
||||
break;
|
||||
case 13: // High Water Mark for GUI
|
||||
OLED::printNumber(uxTaskGetStackHighWaterMark(GUITaskHandle), 8, FontStyle::SMALL);
|
||||
break;
|
||||
case 14: // High Water Mark for Movement Task
|
||||
OLED::printNumber(uxTaskGetStackHighWaterMark(MOVTaskHandle), 8, FontStyle::SMALL);
|
||||
break;
|
||||
case 15: // High Water Mark for PID Task
|
||||
OLED::printNumber(uxTaskGetStackHighWaterMark(PIDTaskHandle), 8, FontStyle::SMALL);
|
||||
break;
|
||||
break;
|
||||
OLED::drawHex((uint32_t)(id >> 32), FontStyle::SMALL, 8);
|
||||
OLED::drawHex((uint32_t)(id & 0xFFFFFFFF), FontStyle::SMALL, 8);
|
||||
} break;
|
||||
case 2: // ACC Type
|
||||
OLED::print(AccelTypeNames[(int)DetectedAccelerometerVersion], FontStyle::SMALL);
|
||||
break;
|
||||
case 3: // Power Negotiation Status
|
||||
OLED::print(PowerSourceNames[getPowerSourceNumber()], FontStyle::SMALL);
|
||||
break;
|
||||
case 4: // Input Voltage
|
||||
printVoltage();
|
||||
break;
|
||||
case 5: // Temp in °C
|
||||
OLED::printNumber(TipThermoModel::getTipInC(), 6, FontStyle::SMALL);
|
||||
break;
|
||||
case 6: // Handle Temp in °C
|
||||
OLED::printNumber(getHandleTemperature(0) / 10, 6, FontStyle::SMALL);
|
||||
OLED::print(SmallSymbolDot, FontStyle::SMALL);
|
||||
OLED::printNumber(getHandleTemperature(0) % 10, 1, FontStyle::SMALL);
|
||||
break;
|
||||
case 7: // Max Temp Limit in °C
|
||||
OLED::printNumber(TipThermoModel::getTipMaxInC(), 6, FontStyle::SMALL);
|
||||
break;
|
||||
case 8: // System Uptime
|
||||
OLED::printNumber(xTaskGetTickCount() / TICKS_100MS, 8, FontStyle::SMALL);
|
||||
break;
|
||||
case 9: // Movement Timestamp
|
||||
OLED::printNumber(lastMovementTime / TICKS_100MS, 8, FontStyle::SMALL);
|
||||
break;
|
||||
case 10: // Tip Resistance in Ω
|
||||
OLED::printNumber(getTipResistanceX10() / 10, 6, FontStyle::SMALL); // large to pad over so that we cover ID left overs
|
||||
OLED::print(SmallSymbolDot, FontStyle::SMALL);
|
||||
OLED::printNumber(getTipResistanceX10() % 10, 1, FontStyle::SMALL);
|
||||
break;
|
||||
case 11: // Raw Tip in µV
|
||||
OLED::printNumber(TipThermoModel::convertTipRawADCTouV(getTipRawTemp(0), true), 8, FontStyle::SMALL);
|
||||
break;
|
||||
case 12: // Tip Cold Junction Compensation Offset in µV
|
||||
OLED::printNumber(getSettingValue(SettingsOptions::CalibrationOffset), 8, FontStyle::SMALL);
|
||||
break;
|
||||
case 13: // High Water Mark for GUI
|
||||
OLED::printNumber(uxTaskGetStackHighWaterMark(GUITaskHandle), 8, FontStyle::SMALL);
|
||||
break;
|
||||
case 14: // High Water Mark for Movement Task
|
||||
OLED::printNumber(uxTaskGetStackHighWaterMark(MOVTaskHandle), 8, FontStyle::SMALL);
|
||||
break;
|
||||
case 15: // High Water Mark for PID Task
|
||||
OLED::printNumber(uxTaskGetStackHighWaterMark(PIDTaskHandle), 8, FontStyle::SMALL);
|
||||
break;
|
||||
break;
|
||||
#ifdef HALL_SENSOR
|
||||
case 16: // Raw Hall Effect Value
|
||||
{
|
||||
int16_t hallEffectStrength = getRawHallEffect();
|
||||
if (hallEffectStrength < 0) {
|
||||
hallEffectStrength = -hallEffectStrength;
|
||||
}
|
||||
OLED::printNumber(hallEffectStrength, 6, FontStyle::SMALL);
|
||||
} break;
|
||||
case 16: // Raw Hall Effect Value
|
||||
{
|
||||
int16_t hallEffectStrength = getRawHallEffect();
|
||||
if (hallEffectStrength < 0) {
|
||||
hallEffectStrength = -hallEffectStrength;
|
||||
}
|
||||
OLED::printNumber(hallEffectStrength, 6, FontStyle::SMALL);
|
||||
} break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
OLED::refresh();
|
||||
b = getButtonState();
|
||||
if (b == BUTTON_B_SHORT) {
|
||||
return;
|
||||
} else if (b == BUTTON_F_SHORT) {
|
||||
screen++;
|
||||
#ifdef HALL_SENSOR
|
||||
screen = screen % 17;
|
||||
#else
|
||||
screen = screen % 16;
|
||||
#endif
|
||||
}
|
||||
|
||||
GUIDelay();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (buttons == BUTTON_B_SHORT) {
|
||||
cxt->transitionMode = TransitionAnimation::Down;
|
||||
return OperatingMode::HomeScreen;
|
||||
} else if (buttons == BUTTON_F_SHORT) {
|
||||
cxt->scratch_state.state1++;
|
||||
#ifdef HALL_SENSOR
|
||||
cxt->scratch_state.state1 = cxt->scratch_state.state1 % 17;
|
||||
#else
|
||||
cxt->scratch_state.state1 = cxt->scratch_state.state1 % 16;
|
||||
#endif
|
||||
}
|
||||
return OperatingMode::DebugMenuReadout; // Stay in debug menu
|
||||
}
|
||||
|
||||
@@ -2,14 +2,10 @@
|
||||
#include "Buttons.hpp"
|
||||
#include "OperatingModes.h"
|
||||
|
||||
#define MOVEMENT_INACTIVITY_TIME (60 * configTICK_RATE_HZ)
|
||||
#define BUTTON_INACTIVITY_TIME (60 * configTICK_RATE_HZ)
|
||||
|
||||
uint8_t buttonAF[sizeof(buttonA)];
|
||||
uint8_t buttonBF[sizeof(buttonB)];
|
||||
uint8_t disconnectedTipF[sizeof(disconnectedTip)];
|
||||
extern OperatingMode currentMode;
|
||||
bool showExitMenuTransition = false;
|
||||
uint8_t buttonAF[sizeof(buttonA)];
|
||||
uint8_t buttonBF[sizeof(buttonB)];
|
||||
uint8_t disconnectedTipF[sizeof(disconnectedTip)];
|
||||
bool showExitMenuTransition = false;
|
||||
|
||||
void renderHomeScreenAssets(void) {
|
||||
|
||||
@@ -24,59 +20,50 @@ void renderHomeScreenAssets(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void handleButtons(bool *buttonLockout) {
|
||||
ButtonState buttons = getButtonState();
|
||||
if (buttons != BUTTON_NONE) {
|
||||
OLED::setDisplayState(OLED::DisplayState::ON);
|
||||
}
|
||||
if (buttons != BUTTON_NONE && *buttonLockout) {
|
||||
buttons = BUTTON_NONE;
|
||||
OperatingMode handleHomeButtons(const ButtonState buttons, guiContext *cxt) {
|
||||
if (buttons != BUTTON_NONE && cxt->scratch_state.state1 == 0) {
|
||||
return OperatingMode::HomeScreen; // Ignore button press
|
||||
} else {
|
||||
*buttonLockout = false;
|
||||
cxt->scratch_state.state1 = 1;
|
||||
}
|
||||
switch (buttons) {
|
||||
case BUTTON_NONE:
|
||||
// Do nothing
|
||||
break;
|
||||
case BUTTON_BOTH:
|
||||
// Not used yet
|
||||
// In multi-language this might be used to reset language on a long hold
|
||||
// or some such
|
||||
break;
|
||||
|
||||
case BUTTON_B_LONG:
|
||||
// Show the version information
|
||||
showDebugMenu();
|
||||
cxt->transitionMode = TransitionAnimation::Up;
|
||||
return OperatingMode::DebugMenuReadout;
|
||||
break;
|
||||
case BUTTON_F_LONG:
|
||||
#ifdef PROFILE_SUPPORT
|
||||
if (!isTipDisconnected()) {
|
||||
gui_solderingProfileMode(); // enter profile mode
|
||||
*buttonLockout = true;
|
||||
cxt->transitionMode = TransitionAnimation::Left;
|
||||
return OperatingMode::SolderingProfile;
|
||||
} else {
|
||||
return OperatingMode::HomeScreen;
|
||||
}
|
||||
#else
|
||||
gui_solderingTempAdjust();
|
||||
saveSettings();
|
||||
cxt->transitionMode = TransitionAnimation::Left;
|
||||
return OperatingMode::TemperatureAdjust;
|
||||
#endif
|
||||
break;
|
||||
case BUTTON_F_SHORT:
|
||||
if (!isTipDisconnected()) {
|
||||
gui_solderingMode(0); // enter soldering mode
|
||||
*buttonLockout = true;
|
||||
cxt->transitionMode = TransitionAnimation::Left;
|
||||
return OperatingMode::Soldering;
|
||||
}
|
||||
break;
|
||||
case BUTTON_B_SHORT:
|
||||
currentMode = OperatingMode::settings;
|
||||
enterSettingsMenu(); // enter the settings menu
|
||||
{
|
||||
OLED::useSecondaryFramebuffer(true);
|
||||
showExitMenuTransition = true;
|
||||
}
|
||||
*buttonLockout = true;
|
||||
cxt->transitionMode = TransitionAnimation::Right;
|
||||
return OperatingMode::SettingsMenu;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return OperatingMode::HomeScreen;
|
||||
}
|
||||
|
||||
void drawDetailedHomeScreen(uint32_t tipTemp) {
|
||||
@@ -181,55 +168,22 @@ void drawSimplifiedHomeScreen(uint32_t tipTemp) {
|
||||
}
|
||||
}
|
||||
}
|
||||
void drawHomeScreen(bool buttonLockout) {
|
||||
OperatingMode drawHomeScreen(const ButtonState buttons, guiContext *cxt) {
|
||||
|
||||
for (;;) {
|
||||
currentMode = OperatingMode::idle;
|
||||
handleButtons(&buttonLockout);
|
||||
currentTempTargetDegC = 0; // ensure tip is off
|
||||
getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0);
|
||||
uint32_t tipTemp = TipThermoModel::getTipInC();
|
||||
|
||||
currentTempTargetDegC = 0; // ensure tip is off
|
||||
getInputVoltageX10(getSettingValue(SettingsOptions::VoltageDiv), 0);
|
||||
uint32_t tipTemp = TipThermoModel::getTipInC();
|
||||
// Preemptively turn the display on. Turn it off if and only if
|
||||
// the tip temperature is below 50 degrees C *and* motion sleep
|
||||
// detection is enabled *and* there has been no activity (movement or
|
||||
// button presses) in a while.
|
||||
// This is zero cost really as state is only changed on display updates
|
||||
OLED::setDisplayState(OLED::DisplayState::ON);
|
||||
|
||||
if ((tipTemp < 50) && getSettingValue(SettingsOptions::Sensitivity)
|
||||
&& (((xTaskGetTickCount() - lastMovementTime) > MOVEMENT_INACTIVITY_TIME) && ((xTaskGetTickCount() - lastButtonTime) > BUTTON_INACTIVITY_TIME))) {
|
||||
OLED::setDisplayState(OLED::DisplayState::OFF);
|
||||
setStatusLED(LED_OFF);
|
||||
} else {
|
||||
OLED::setDisplayState(OLED::DisplayState::ON);
|
||||
if (tipTemp > 55) {
|
||||
setStatusLED(LED_COOLING_STILL_HOT);
|
||||
} else {
|
||||
setStatusLED(LED_STANDBY);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the lcd buffer
|
||||
OLED::clearScreen();
|
||||
if (OLED::getRotation()) {
|
||||
OLED::setCursor(50, 0);
|
||||
} else {
|
||||
OLED::setCursor(-1, 0);
|
||||
}
|
||||
if (getSettingValue(SettingsOptions::DetailedIDLE)) {
|
||||
drawDetailedHomeScreen(tipTemp);
|
||||
} else {
|
||||
drawSimplifiedHomeScreen(tipTemp);
|
||||
}
|
||||
|
||||
if (showExitMenuTransition) {
|
||||
OLED::useSecondaryFramebuffer(false);
|
||||
OLED::transitionSecondaryFramebuffer(false);
|
||||
showExitMenuTransition = false;
|
||||
} else {
|
||||
OLED::refresh();
|
||||
GUIDelay();
|
||||
}
|
||||
// Setup LCD Cursor location
|
||||
if (OLED::getRotation()) {
|
||||
OLED::setCursor(50, 0);
|
||||
} else {
|
||||
OLED::setCursor(-1, 0);
|
||||
}
|
||||
if (getSettingValue(SettingsOptions::DetailedIDLE)) {
|
||||
drawDetailedHomeScreen(tipTemp);
|
||||
} else {
|
||||
drawSimplifiedHomeScreen(tipTemp);
|
||||
}
|
||||
return handleHomeButtons(buttons, cxt);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,3 @@
|
||||
//
|
||||
|
||||
#include "OperatingModes.h"
|
||||
|
||||
// Global variables
|
||||
OperatingMode currentMode = OperatingMode::idle;
|
||||
@@ -10,6 +10,7 @@ extern "C" {
|
||||
#include "Settings.h"
|
||||
#include "TipThermoModel.h"
|
||||
#include "Translation.h"
|
||||
#include "Types.h"
|
||||
#include "cmsis_os.h"
|
||||
#include "configuration.h"
|
||||
#include "history.hpp"
|
||||
@@ -23,29 +24,64 @@ extern "C" {
|
||||
#include "pd.h"
|
||||
#endif
|
||||
|
||||
// Exposed modes
|
||||
enum OperatingMode {
|
||||
idle = 0,
|
||||
soldering = 1,
|
||||
boost = 2,
|
||||
sleeping = 3,
|
||||
settings = 4,
|
||||
debug = 5
|
||||
enum class OperatingMode {
|
||||
StartupLogo = 0, // Showing the startup logo
|
||||
CJCCalibration, // Cold Junction Calibration
|
||||
StartupWarnings, // Startup checks and warnings
|
||||
InitialisationDone, // Special state we use just before we to home screen at first startup. Allows jumping to extra startup states
|
||||
HomeScreen, // Home/Idle screen that is the main launchpad to other modes
|
||||
Soldering, // Main soldering operating mode
|
||||
SolderingProfile, // Soldering by following a profile, used for reflow for example
|
||||
Sleeping, // Sleep state holds iron at lower sleep temp
|
||||
Hibernating, // Like sleeping but keeps heater fully off until woken
|
||||
SettingsMenu, // Settings Menu
|
||||
DebugMenuReadout, // Debug metrics
|
||||
TemperatureAdjust, // Set point temperature adjustment
|
||||
UsbPDDebug, // USB PD debugging information
|
||||
ThermalRunaway, // Thermal Runaway warning state.
|
||||
};
|
||||
|
||||
enum class TransitionAnimation {
|
||||
None = 0,
|
||||
Right = 1,
|
||||
Left = 2,
|
||||
Down = 3,
|
||||
Up = 4,
|
||||
};
|
||||
|
||||
// Generic context struct used for gui functions to be able to retain state
|
||||
struct guiContext {
|
||||
TickType_t viewEnterTime; // Set to ticks when this view state was first entered
|
||||
OperatingMode previousMode;
|
||||
TransitionAnimation transitionMode;
|
||||
// Below is scratch state, this is retained over re-draws but blown away on state change
|
||||
struct scratch {
|
||||
uint16_t state1; // 16 bit state scratch
|
||||
uint16_t state2; // 16 bit state scratch
|
||||
uint32_t state3; // 32 bit state scratch
|
||||
uint32_t state4; // 32 bit state scratch
|
||||
uint16_t state5; // 16 bit state scratch
|
||||
uint16_t state6; // 16 bit state scratch
|
||||
|
||||
} scratch_state;
|
||||
};
|
||||
|
||||
// Main functions
|
||||
void performCJCC(void); // Used to calibrate the Cold Junction offset
|
||||
void gui_solderingTempAdjust(void); // For adjusting the setpoint temperature of the iron
|
||||
int gui_SolderingSleepingMode(bool stayOff, bool autoStarted); // Sleep mode
|
||||
void gui_solderingMode(uint8_t jumpToSleep); // Main mode for hot pointy tool
|
||||
void gui_solderingProfileMode(); // Profile mode for hot likely-not-so-pointy tool
|
||||
void showDebugMenu(void); // Debugging values
|
||||
void showPDDebug(void); // Debugging menu that shows PD adaptor info
|
||||
void showWarnings(void); // Shows user warnings if required
|
||||
void drawHomeScreen(bool buttonLockout) __attribute__((noreturn)); // IDLE / Home screen
|
||||
void renderHomeScreenAssets(void); // Called to act as start delay and used to render out flipped images for home screen graphics
|
||||
OperatingMode gui_SolderingSleepingMode(const ButtonState buttons, guiContext *cxt); // Sleep mode
|
||||
OperatingMode gui_solderingMode(const ButtonState buttons, guiContext *cxt); // Main mode for hot pointy tool
|
||||
OperatingMode gui_solderingTempAdjust(const ButtonState buttons, guiContext *cxt); // For adjusting the setpoint temperature of the iron
|
||||
OperatingMode drawHomeScreen(const ButtonState buttons, guiContext *cxt); // IDLE / Home screen
|
||||
OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt); //
|
||||
|
||||
OperatingMode gui_solderingProfileMode(const ButtonState buttons, guiContext *cxt); // Profile mode for hot likely-not-so-pointy tool
|
||||
OperatingMode performCJCC(const ButtonState buttons, guiContext *cxt); // Used to calibrate the Cold Junction offset
|
||||
OperatingMode showDebugMenu(const ButtonState buttons, guiContext *cxt); // Debugging values
|
||||
OperatingMode showPDDebug(const ButtonState buttons, guiContext *cxt); // Debugging menu that shows PD adaptor info
|
||||
OperatingMode showWarnings(const ButtonState buttons, guiContext *cxt); // Shows user warnings if required
|
||||
|
||||
// Common helpers
|
||||
int8_t getPowerSourceNumber(void); // Returns number ID of power source
|
||||
uint16_t getTipTemp(void); // Returns temperature of the tip in *C/*F (based on user settings)
|
||||
int8_t getPowerSourceNumber(void); // Returns number ID of power source
|
||||
void renderHomeScreenAssets(void); // Called to act as start delay and used to render out flipped images for home screen graphics
|
||||
|
||||
extern bool heaterThermalRunaway;
|
||||
#endif
|
||||
|
||||
233
source/Core/Threads/OperatingModes/SettingsMenu.cpp
Normal file
233
source/Core/Threads/OperatingModes/SettingsMenu.cpp
Normal file
@@ -0,0 +1,233 @@
|
||||
#include "OperatingModes.h"
|
||||
#include "ScrollMessage.hpp"
|
||||
|
||||
#define HELP_TEXT_TIMEOUT_TICKS (TICKS_SECOND * 3)
|
||||
/*
|
||||
* The settings menu is the most complex bit of GUI code we have
|
||||
* The menu consists of a two tier menu
|
||||
* Main menu -> Categories
|
||||
* Secondary menu -> Settings
|
||||
*
|
||||
* For each entry in the menu
|
||||
*/
|
||||
|
||||
/**
|
||||
* Prints two small lines (or one line for CJK) of short description for
|
||||
* setting items and prepares cursor after it.
|
||||
* @param settingsItemIndex Index of the setting item.
|
||||
* @param cursorCharPosition Custom cursor char position to set after printing
|
||||
* description.
|
||||
*/
|
||||
static void printShortDescription(SettingsItemIndex settingsItemIndex, uint16_t cursorCharPosition) {
|
||||
// print short description (default single line, explicit double line)
|
||||
uint8_t shortDescIndex = static_cast<uint8_t>(settingsItemIndex);
|
||||
OLED::printWholeScreen(translatedString(Tr->SettingsShortNames[shortDescIndex]));
|
||||
|
||||
// prepare cursor for value
|
||||
// make room for scroll indicator
|
||||
OLED::setCursor(cursorCharPosition * FONT_12_WIDTH - 2, 0);
|
||||
}
|
||||
|
||||
// Render a menu, based on the position given
|
||||
// This will either draw the menu item, or the help text depending on how long its been since button press
|
||||
void render_menu(const menuitem *item, guiContext *cxt) {
|
||||
|
||||
// If recent interaction or not help text draw the entry
|
||||
if ((xTaskGetTickCount() - lastButtonTime < HELP_TEXT_TIMEOUT_TICKS) || item->description == 0) {
|
||||
|
||||
if (item->shortDescriptionSize > 0) {
|
||||
printShortDescription(item->shortDescriptionIndex, item->shortDescriptionSize);
|
||||
}
|
||||
item->draw();
|
||||
} else {
|
||||
|
||||
uint16_t *isRenderingHelp = &(cxt->scratch_state.state6);
|
||||
*isRenderingHelp = 1;
|
||||
// Draw description
|
||||
const char *description = translatedString(Tr->SettingsDescriptions[item->description - 1]);
|
||||
drawScrollingText(description, xTaskGetTickCount() - lastButtonTime);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t getMenuLength(const menuitem *menu, const uint16_t stop) {
|
||||
// walk this menu to find the length
|
||||
uint16_t counter = 0;
|
||||
for (uint16_t pos = 0; pos < stop; pos++) {
|
||||
if (menu[pos].draw == nullptr) {
|
||||
return counter;
|
||||
}
|
||||
if (menu[pos].isVisible == nullptr || menu[pos].isVisible()) {
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
return counter;
|
||||
}
|
||||
|
||||
OperatingMode moveToNextEntry(guiContext *cxt) {
|
||||
uint16_t *mainEntry = &(cxt->scratch_state.state1);
|
||||
uint16_t *subEntry = &(cxt->scratch_state.state2);
|
||||
uint16_t *isRenderingHelp = &(cxt->scratch_state.state6);
|
||||
if (*isRenderingHelp) {
|
||||
*isRenderingHelp = 0;
|
||||
} else {
|
||||
// Scroll down
|
||||
// We can increment freely _once_
|
||||
cxt->transitionMode = TransitionAnimation::Down;
|
||||
if (*subEntry == 0) {
|
||||
(*mainEntry) += 1;
|
||||
if (rootSettingsMenu[*mainEntry].draw == nullptr) {
|
||||
// We are off the end of the menu now
|
||||
saveSettings();
|
||||
cxt->transitionMode = TransitionAnimation::Left;
|
||||
return OperatingMode::HomeScreen;
|
||||
}
|
||||
// Check if visible
|
||||
if (rootSettingsMenu[*mainEntry].isVisible != nullptr && !rootSettingsMenu[*mainEntry].isVisible()) {
|
||||
// We need to move on as this one isn't visible
|
||||
return moveToNextEntry(cxt);
|
||||
}
|
||||
} else {
|
||||
(*subEntry) += 1;
|
||||
|
||||
// If the new entry is null, we need to exit
|
||||
if (subSettingsMenus[*mainEntry][(*subEntry) - 1].draw == nullptr) {
|
||||
(*subEntry) = 0; // Reset back to the main menu
|
||||
cxt->transitionMode = TransitionAnimation::Left;
|
||||
// Have to break early to avoid the below check underflowing
|
||||
return OperatingMode::SettingsMenu;
|
||||
}
|
||||
// Check if visible
|
||||
if (subSettingsMenus[*mainEntry][(*subEntry) - 1].isVisible != nullptr && !subSettingsMenus[*mainEntry][(*subEntry) - 1].isVisible()) {
|
||||
// We need to move on as this one isn't visible
|
||||
return moveToNextEntry(cxt);
|
||||
}
|
||||
}
|
||||
}
|
||||
return OperatingMode::SettingsMenu;
|
||||
}
|
||||
|
||||
OperatingMode gui_SettingsMenu(const ButtonState buttons, guiContext *cxt) {
|
||||
// Render out the current settings menu
|
||||
// State 1 -> Root menu
|
||||
// State 2 -> Sub entry
|
||||
// Draw main entry if sub-entry is 0, otherwise draw sub-entry
|
||||
|
||||
uint16_t *mainEntry = &(cxt->scratch_state.state1);
|
||||
uint16_t *subEntry = &(cxt->scratch_state.state2);
|
||||
uint32_t *autoRepeatAcceleration = &(cxt->scratch_state.state3);
|
||||
uint32_t *autoRepeatTimer = &(cxt->scratch_state.state4);
|
||||
uint16_t *currentMenuLength = &(cxt->scratch_state.state5);
|
||||
uint16_t *isRenderingHelp = &(cxt->scratch_state.state6);
|
||||
|
||||
const menuitem *currentMenu;
|
||||
// Draw the currently on screen item
|
||||
uint16_t currentScreen;
|
||||
if (*subEntry == 0) {
|
||||
// Drawing main menu
|
||||
currentMenu = rootSettingsMenu;
|
||||
currentScreen = *mainEntry;
|
||||
} else {
|
||||
// Drawing sub menu
|
||||
currentMenu = subSettingsMenus[*mainEntry];
|
||||
currentScreen = (*subEntry) - 1;
|
||||
}
|
||||
render_menu(&(currentMenu[currentScreen]), cxt);
|
||||
|
||||
// Update the cached menu length if unknown
|
||||
if (*currentMenuLength == 0) {
|
||||
// We walk the current menu to find the length
|
||||
*currentMenuLength = getMenuLength(currentMenu, 64);
|
||||
}
|
||||
if (*isRenderingHelp == 0) {
|
||||
// Draw scroll
|
||||
uint16_t currentVirtualPosition = getMenuLength(currentMenu, currentScreen + 1) - 1;
|
||||
|
||||
uint8_t indicatorHeight = OLED_HEIGHT / *currentMenuLength;
|
||||
uint8_t position = (OLED_HEIGHT * currentVirtualPosition) / *currentMenuLength;
|
||||
// Draw if not last item
|
||||
if ((*currentMenuLength != currentVirtualPosition) || xTaskGetTickCount() % 1000 < 500) {
|
||||
OLED::drawScrollIndicator(position, indicatorHeight);
|
||||
}
|
||||
}
|
||||
// Now handle user button input
|
||||
|
||||
auto callIncrementHandler = [&]() {
|
||||
if ((int)currentMenu[currentScreen].autoSettingOption < (int)SettingsOptions::SettingsOptionsLength) {
|
||||
return nextSettingValue(currentMenu[currentScreen].autoSettingOption);
|
||||
} else if (currentMenu[currentScreen].incrementHandler != nullptr) {
|
||||
return currentMenu[currentScreen].incrementHandler();
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
//
|
||||
OperatingMode newMode = OperatingMode::SettingsMenu;
|
||||
switch (buttons) {
|
||||
case BUTTON_NONE:
|
||||
(*autoRepeatAcceleration) = 0; // reset acceleration
|
||||
(*autoRepeatTimer) = 0; // reset acceleration
|
||||
break;
|
||||
case BUTTON_BOTH:
|
||||
if (*subEntry == 0) {
|
||||
saveSettings();
|
||||
cxt->transitionMode = TransitionAnimation::Left;
|
||||
return OperatingMode::HomeScreen;
|
||||
} else {
|
||||
cxt->transitionMode = TransitionAnimation::Left;
|
||||
*subEntry = 0;
|
||||
return OperatingMode::SettingsMenu;
|
||||
}
|
||||
break;
|
||||
|
||||
case BUTTON_F_LONG:
|
||||
if (xTaskGetTickCount() + (*autoRepeatAcceleration) > (*autoRepeatTimer) + PRESS_ACCEL_INTERVAL_MAX) {
|
||||
if (callIncrementHandler()) {
|
||||
(*autoRepeatTimer) = TICKS_SECOND * 2;
|
||||
} else {
|
||||
(*autoRepeatTimer) = 0;
|
||||
}
|
||||
(*autoRepeatTimer) += xTaskGetTickCount();
|
||||
(*autoRepeatAcceleration) += PRESS_ACCEL_STEP;
|
||||
}
|
||||
break;
|
||||
case BUTTON_F_SHORT:
|
||||
// Increment setting
|
||||
if (*isRenderingHelp) {
|
||||
*isRenderingHelp = 0;
|
||||
} else {
|
||||
if (*subEntry == 0) {
|
||||
// In a root menu, if its null handler we enter the menu
|
||||
if (currentMenu[currentScreen].incrementHandler != nullptr) {
|
||||
currentMenu[currentScreen].incrementHandler();
|
||||
} else {
|
||||
(*subEntry) += 1;
|
||||
cxt->transitionMode = TransitionAnimation::Right;
|
||||
}
|
||||
} else {
|
||||
callIncrementHandler();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BUTTON_B_LONG:
|
||||
if (xTaskGetTickCount() + (*autoRepeatAcceleration) > (*autoRepeatTimer) + PRESS_ACCEL_INTERVAL_MAX) {
|
||||
(*autoRepeatTimer) = xTaskGetTickCount();
|
||||
(*autoRepeatAcceleration) += PRESS_ACCEL_STEP;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
/* Fall through*/
|
||||
case BUTTON_B_SHORT:
|
||||
// Increment menu item
|
||||
newMode = moveToNextEntry(cxt);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if ((PRESS_ACCEL_INTERVAL_MAX - (*autoRepeatAcceleration)) < PRESS_ACCEL_INTERVAL_MIN) {
|
||||
(*autoRepeatAcceleration) = PRESS_ACCEL_INTERVAL_MAX - PRESS_ACCEL_INTERVAL_MIN;
|
||||
}
|
||||
|
||||
// Otherwise we stay put for next render iteration
|
||||
return newMode;
|
||||
}
|
||||
@@ -1,56 +1,78 @@
|
||||
#include "HUB238.hpp"
|
||||
#include "OperatingModes.h"
|
||||
void showWarnings(void) {
|
||||
OperatingMode showWarnings(const ButtonState buttons, guiContext *cxt) {
|
||||
// Display alert if settings were reset
|
||||
if (settingsWereReset) {
|
||||
warnUser(translatedString(Tr->SettingsResetMessage), 10 * TICKS_SECOND);
|
||||
}
|
||||
#ifdef DEVICE_HAS_VALIDATION_SUPPORT
|
||||
if (getDeviceValidationStatus()) {
|
||||
// Warn user this device might be counterfeit
|
||||
warnUser(translatedString(Tr->DeviceFailedValidationWarning), 10 * TICKS_SECOND);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NO_WARN_MISSING
|
||||
// We also want to alert if accel or pd is not detected / not responding
|
||||
// In this case though, we dont want to nag the user _too_ much
|
||||
// So only show first 2 times
|
||||
while (DetectedAccelerometerVersion == AccelType::Scanning) {
|
||||
osDelay(5);
|
||||
resetWatchdog();
|
||||
}
|
||||
// Display alert if accelerometer is not detected
|
||||
if (DetectedAccelerometerVersion == AccelType::None) {
|
||||
if (getSettingValue(SettingsOptions::AccelMissingWarningCounter) < 2) {
|
||||
nextSettingValue(SettingsOptions::AccelMissingWarningCounter);
|
||||
saveSettings();
|
||||
warnUser(translatedString(Tr->NoAccelerometerMessage), 10 * TICKS_SECOND);
|
||||
switch (cxt->scratch_state.state1) {
|
||||
case 0: // Settings reset warning
|
||||
if (settingsWereReset) {
|
||||
if (warnUser(translatedString(Tr->SettingsResetMessage), buttons)) {
|
||||
settingsWereReset = false;
|
||||
cxt->scratch_state.state1 = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1: // Device validations
|
||||
#ifdef DEVICE_HAS_VALIDATION_SUPPORT
|
||||
if (getDeviceValidationStatus()) {
|
||||
// Warn user this device might be counterfeit
|
||||
if (warnUser(translatedString(Tr->DeviceFailedValidationWarning), buttons)) {
|
||||
cxt->scratch_state.state1 = 2;
|
||||
}
|
||||
}
|
||||
#else
|
||||
cxt->scratch_state.state1 = 2;
|
||||
#endif
|
||||
break;
|
||||
case 2: // Accelerometer detection
|
||||
if (DetectedAccelerometerVersion == AccelType::Scanning) {
|
||||
break;
|
||||
}
|
||||
// Display alert if accelerometer is not detected
|
||||
if (DetectedAccelerometerVersion == AccelType::None) {
|
||||
if (getSettingValue(SettingsOptions::AccelMissingWarningCounter) < 2) {
|
||||
nextSettingValue(SettingsOptions::AccelMissingWarningCounter);
|
||||
saveSettings();
|
||||
if (warnUser(translatedString(Tr->NoAccelerometerMessage), buttons)) {
|
||||
cxt->scratch_state.state1 = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
|
||||
#ifdef POW_PD
|
||||
// We expect pd to be present
|
||||
resetWatchdog();
|
||||
if (!USBPowerDelivery::fusbPresent()) {
|
||||
if (getSettingValue(SettingsOptions::PDMissingWarningCounter) < 2) {
|
||||
nextSettingValue(SettingsOptions::PDMissingWarningCounter);
|
||||
saveSettings();
|
||||
warnUser(translatedString(Tr->NoPowerDeliveryMessage), 10 * TICKS_SECOND);
|
||||
// We expect pd to be present
|
||||
if (!USBPowerDelivery::fusbPresent()) {
|
||||
if (getSettingValue(SettingsOptions::PDMissingWarningCounter) < 2) {
|
||||
nextSettingValue(SettingsOptions::PDMissingWarningCounter);
|
||||
saveSettings();
|
||||
if (warnUser(translatedString(Tr->NoPowerDeliveryMessage), buttons)) {
|
||||
cxt->scratch_state.state1 = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /*POW_PD*/
|
||||
#else
|
||||
#if POW_PD_EXT == 1
|
||||
if (!hub238_probe()) {
|
||||
if (getSettingValue(SettingsOptions::PDMissingWarningCounter) < 2) {
|
||||
nextSettingValue(SettingsOptions::PDMissingWarningCounter);
|
||||
saveSettings();
|
||||
warnUser(translatedString(Tr->NoPowerDeliveryMessage), 10 * TICKS_SECOND);
|
||||
if (!hub238_probe()) {
|
||||
if (getSettingValue(SettingsOptions::PDMissingWarningCounter) < 2) {
|
||||
nextSettingValue(SettingsOptions::PDMissingWarningCounter);
|
||||
saveSettings();
|
||||
if (warnUser(translatedString(Tr->NoPowerDeliveryMessage), buttons)) {
|
||||
cxt->scratch_state.state1 = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
cxt->scratch_state.state1 = 4;
|
||||
#endif /*POW_PD_EXT==1*/
|
||||
// If tip looks to be shorted, yell at user and dont auto dismiss
|
||||
if (isTipShorted()) {
|
||||
warnUser(translatedString(Tr->WarningTipShorted), portMAX_DELAY);
|
||||
#endif /*POW_PD*/
|
||||
|
||||
break;
|
||||
default:
|
||||
// We are off the end, warnings done
|
||||
return OperatingMode::InitialisationDone;
|
||||
}
|
||||
#endif /*NO_WARN_MISSING*/
|
||||
|
||||
return OperatingMode::StartupWarnings; // Stay in warnings
|
||||
}
|
||||
|
||||
@@ -1,64 +1,60 @@
|
||||
#include "OperatingModes.h"
|
||||
|
||||
extern OperatingMode currentMode;
|
||||
|
||||
int gui_SolderingSleepingMode(bool stayOff, bool autoStarted) {
|
||||
#ifndef NO_SLEEP_MODE
|
||||
OperatingMode gui_SolderingSleepingMode(const ButtonState buttons, guiContext *cxt) {
|
||||
#ifdef NO_SLEEP_MODE
|
||||
return OperatingMode::Soldering;
|
||||
#endif
|
||||
// Drop to sleep temperature and display until movement or button press
|
||||
currentMode = OperatingMode::sleeping;
|
||||
|
||||
for (;;) {
|
||||
// user moved or pressed a button, go back to soldering
|
||||
// If in the first two seconds we disable this to let accelerometer warm up
|
||||
// user moved or pressed a button, go back to soldering
|
||||
// If in the first two seconds we disable this to let accelerometer warm up
|
||||
|
||||
#ifdef POW_DC
|
||||
if (checkForUnderVoltage()) {
|
||||
// return non-zero on error
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (getSettingValue(SettingsOptions::TemperatureInF)) {
|
||||
currentTempTargetDegC = stayOff ? 0 : TipThermoModel::convertFtoC(min(getSettingValue(SettingsOptions::SleepTemp), getSettingValue(SettingsOptions::SolderingTemp)));
|
||||
} else {
|
||||
currentTempTargetDegC = stayOff ? 0 : min(getSettingValue(SettingsOptions::SleepTemp), getSettingValue(SettingsOptions::SolderingTemp));
|
||||
}
|
||||
|
||||
// draw the lcd
|
||||
uint16_t tipTemp = getTipTemp();
|
||||
|
||||
OLED::clearScreen();
|
||||
OLED::setCursor(0, 0);
|
||||
if (getSettingValue(SettingsOptions::DetailedSoldering)) {
|
||||
OLED::print(translatedString(Tr->SleepingAdvancedString), FontStyle::SMALL);
|
||||
OLED::setCursor(0, 8);
|
||||
OLED::print(translatedString(Tr->SleepingTipAdvancedString), FontStyle::SMALL);
|
||||
OLED::printNumber(tipTemp, 3, FontStyle::SMALL);
|
||||
OLED::printSymbolDeg(FontStyle::SMALL);
|
||||
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
|
||||
printVoltage();
|
||||
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
|
||||
} else {
|
||||
OLED::print(translatedString(Tr->SleepingSimpleString), FontStyle::LARGE);
|
||||
OLED::printNumber(tipTemp, 3, FontStyle::LARGE);
|
||||
OLED::printSymbolDeg(FontStyle::EXTRAS);
|
||||
}
|
||||
|
||||
OLED::refresh();
|
||||
GUIDelay();
|
||||
|
||||
if (!shouldBeSleeping(autoStarted)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (shouldShutdown()) {
|
||||
// shutdown
|
||||
currentTempTargetDegC = 0;
|
||||
// we want to exit soldering mode
|
||||
return 1;
|
||||
}
|
||||
if (checkForUnderVoltage()) {
|
||||
return OperatingMode::HomeScreen; // return non-zero on error
|
||||
}
|
||||
#endif
|
||||
if (getSettingValue(SettingsOptions::TemperatureInF)) {
|
||||
currentTempTargetDegC = TipThermoModel::convertFtoC(min(getSettingValue(SettingsOptions::SleepTemp), getSettingValue(SettingsOptions::SolderingTemp)));
|
||||
} else {
|
||||
currentTempTargetDegC = min(getSettingValue(SettingsOptions::SleepTemp), getSettingValue(SettingsOptions::SolderingTemp));
|
||||
}
|
||||
// draw the lcd
|
||||
uint16_t tipTemp = getSettingValue(SettingsOptions::TemperatureInF) ? TipThermoModel::getTipInF() : TipThermoModel::getTipInC();
|
||||
|
||||
return 0;
|
||||
OLED::clearScreen();
|
||||
OLED::setCursor(0, 0);
|
||||
if (getSettingValue(SettingsOptions::DetailedSoldering)) {
|
||||
OLED::print(translatedString(Tr->SleepingAdvancedString), FontStyle::SMALL);
|
||||
OLED::setCursor(0, 8);
|
||||
OLED::print(translatedString(Tr->SleepingTipAdvancedString), FontStyle::SMALL);
|
||||
OLED::printNumber(tipTemp, 3, FontStyle::SMALL);
|
||||
if (getSettingValue(SettingsOptions::TemperatureInF)) {
|
||||
OLED::print(SmallSymbolDegF, FontStyle::SMALL);
|
||||
} else {
|
||||
OLED::print(SmallSymbolDegC, FontStyle::SMALL);
|
||||
}
|
||||
|
||||
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
|
||||
printVoltage();
|
||||
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
|
||||
} else {
|
||||
OLED::print(translatedString(Tr->SleepingSimpleString), FontStyle::LARGE);
|
||||
OLED::printNumber(tipTemp, 3, FontStyle::LARGE);
|
||||
OLED::printSymbolDeg(FontStyle::EXTRAS);
|
||||
}
|
||||
|
||||
OLED::refresh();
|
||||
GUIDelay();
|
||||
|
||||
if (!shouldBeSleeping()) {
|
||||
return cxt->previousMode;
|
||||
}
|
||||
|
||||
if (shouldShutdown()) {
|
||||
// shutdown
|
||||
currentTempTargetDegC = 0;
|
||||
return OperatingMode::HomeScreen;
|
||||
}
|
||||
return OperatingMode::Sleeping;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,62 @@
|
||||
|
||||
#include "OperatingModes.h"
|
||||
#include "SolderingCommon.h"
|
||||
// State 1 = button locking
|
||||
// State 2 = boost mode
|
||||
// State 3 = buzzer timer
|
||||
|
||||
extern OperatingMode currentMode;
|
||||
|
||||
void gui_solderingMode(uint8_t jumpToSleep) {
|
||||
OperatingMode handleSolderingButtons(const ButtonState buttons, guiContext *cxt) {
|
||||
if (cxt->scratch_state.state1 == 1) {
|
||||
// Buttons are currently locked
|
||||
if (buttons == BUTTON_F_LONG) {
|
||||
if (getSettingValue(SettingsOptions::BoostTemp) && (getSettingValue(SettingsOptions::LockingMode) == 1)) {
|
||||
cxt->scratch_state.state2 = 1;
|
||||
}
|
||||
} else if (buttons == BUTTON_BOTH_LONG) {
|
||||
// Unlocking
|
||||
if (warnUser(translatedString(Tr->UnlockingKeysString), buttons)) {
|
||||
cxt->scratch_state.state1 = 0;
|
||||
}
|
||||
} else if (buttons != BUTTON_NONE) {
|
||||
// Do nothing and display a lock warning
|
||||
warnUser(translatedString(Tr->WarningKeysLockedString), buttons);
|
||||
}
|
||||
return OperatingMode::Soldering;
|
||||
}
|
||||
// otherwise we are unlocked
|
||||
switch (buttons) {
|
||||
case BUTTON_NONE:
|
||||
cxt->scratch_state.state2 = 0;
|
||||
break;
|
||||
case BUTTON_BOTH:
|
||||
/*Fall through*/
|
||||
case BUTTON_B_LONG:
|
||||
cxt->transitionMode = TransitionAnimation::Right;
|
||||
return OperatingMode::HomeScreen;
|
||||
case BUTTON_F_LONG:
|
||||
// if boost mode is enabled turn it on
|
||||
if (getSettingValue(SettingsOptions::BoostTemp)) {
|
||||
cxt->scratch_state.state2 = 1;
|
||||
}
|
||||
break;
|
||||
case BUTTON_F_SHORT:
|
||||
case BUTTON_B_SHORT:
|
||||
cxt->transitionMode = TransitionAnimation::Left;
|
||||
return OperatingMode::TemperatureAdjust;
|
||||
case BUTTON_BOTH_LONG:
|
||||
if (getSettingValue(SettingsOptions::LockingMode) != 0) {
|
||||
// Lock buttons
|
||||
if (warnUser(translatedString(Tr->LockingKeysString), buttons)) {
|
||||
cxt->scratch_state.state1 = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return OperatingMode::Soldering;
|
||||
}
|
||||
OperatingMode gui_solderingMode(const ButtonState buttons, guiContext *cxt) {
|
||||
/*
|
||||
* * Soldering (gui_solderingMode)
|
||||
* -> Main loop where we draw temp, and animations
|
||||
@@ -19,171 +71,106 @@ void gui_solderingMode(uint8_t jumpToSleep) {
|
||||
* --> Double button to exit
|
||||
* --> Long hold double button to toggle key lock
|
||||
*/
|
||||
bool boostModeOn = false;
|
||||
bool buttonsLocked = false;
|
||||
bool converged = false;
|
||||
currentMode = OperatingMode::soldering;
|
||||
|
||||
TickType_t buzzerEnd = 0;
|
||||
|
||||
if (jumpToSleep) {
|
||||
if (gui_SolderingSleepingMode(jumpToSleep == 2, true) == 1) {
|
||||
lastButtonTime = xTaskGetTickCount();
|
||||
return; // If the function returns non-0 then exit
|
||||
// Update the setpoints for the temperature
|
||||
if (cxt->scratch_state.state2) {
|
||||
if (getSettingValue(SettingsOptions::TemperatureInF)) {
|
||||
currentTempTargetDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::BoostTemp));
|
||||
} else {
|
||||
currentTempTargetDegC = (getSettingValue(SettingsOptions::BoostTemp));
|
||||
}
|
||||
} else {
|
||||
if (getSettingValue(SettingsOptions::TemperatureInF)) {
|
||||
currentTempTargetDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::SolderingTemp));
|
||||
} else {
|
||||
currentTempTargetDegC = (getSettingValue(SettingsOptions::SolderingTemp));
|
||||
}
|
||||
}
|
||||
for (;;) {
|
||||
ButtonState buttons = getButtonState();
|
||||
if (buttonsLocked && (getSettingValue(SettingsOptions::LockingMode) != 0)) { // If buttons locked
|
||||
switch (buttons) {
|
||||
case BUTTON_NONE:
|
||||
boostModeOn = false;
|
||||
break;
|
||||
case BUTTON_BOTH_LONG:
|
||||
// Unlock buttons
|
||||
buttonsLocked = false;
|
||||
warnUser(translatedString(Tr->UnlockingKeysString), TICKS_SECOND);
|
||||
break;
|
||||
case BUTTON_F_LONG:
|
||||
// if boost mode is enabled turn it on
|
||||
if (getSettingValue(SettingsOptions::BoostTemp) && (getSettingValue(SettingsOptions::LockingMode) == 1)) {
|
||||
boostModeOn = true;
|
||||
currentMode = OperatingMode::boost;
|
||||
}
|
||||
break;
|
||||
// fall through
|
||||
case BUTTON_BOTH:
|
||||
case BUTTON_B_LONG:
|
||||
case BUTTON_F_SHORT:
|
||||
case BUTTON_B_SHORT:
|
||||
// Do nothing and display a lock warning
|
||||
warnUser(translatedString(Tr->WarningKeysLockedString), TICKS_SECOND / 2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else { // Button not locked
|
||||
switch (buttons) {
|
||||
case BUTTON_NONE:
|
||||
// stay
|
||||
boostModeOn = false;
|
||||
currentMode = OperatingMode::soldering;
|
||||
break;
|
||||
case BUTTON_BOTH:
|
||||
case BUTTON_B_LONG:
|
||||
return; // exit on back long hold
|
||||
case BUTTON_F_LONG:
|
||||
// if boost mode is enabled turn it on
|
||||
if (getSettingValue(SettingsOptions::BoostTemp)) {
|
||||
boostModeOn = true;
|
||||
currentMode = OperatingMode::boost;
|
||||
}
|
||||
break;
|
||||
case BUTTON_F_SHORT:
|
||||
case BUTTON_B_SHORT: {
|
||||
uint16_t oldTemp = getSettingValue(SettingsOptions::SolderingTemp);
|
||||
gui_solderingTempAdjust(); // goto adjust temp mode
|
||||
if (oldTemp != getSettingValue(SettingsOptions::SolderingTemp)) {
|
||||
saveSettings(); // only save on change
|
||||
}
|
||||
} break;
|
||||
case BUTTON_BOTH_LONG:
|
||||
if (getSettingValue(SettingsOptions::LockingMode) != 0) {
|
||||
// Lock buttons
|
||||
buttonsLocked = true;
|
||||
warnUser(translatedString(Tr->LockingKeysString), TICKS_SECOND);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Update status
|
||||
int error = currentTempTargetDegC - TipThermoModel::getTipInC();
|
||||
if (error >= -10 && error <= 10) {
|
||||
// converged
|
||||
if (!cxt->scratch_state.state5) {
|
||||
setBuzzer(true);
|
||||
cxt->scratch_state.state3 = xTaskGetTickCount() + TICKS_SECOND / 3;
|
||||
cxt->scratch_state.state5 = true;
|
||||
}
|
||||
// else we update the screen information
|
||||
setStatusLED(LED_HOT);
|
||||
} else {
|
||||
setStatusLED(LED_HEATING);
|
||||
cxt->scratch_state.state5 = false;
|
||||
}
|
||||
if (cxt->scratch_state.state3 != 0 && xTaskGetTickCount() >= cxt->scratch_state.state3) {
|
||||
setBuzzer(false);
|
||||
}
|
||||
|
||||
OLED::clearScreen();
|
||||
// Draw in the screen details
|
||||
if (getSettingValue(SettingsOptions::DetailedSoldering)) {
|
||||
if (OLED::getRotation()) {
|
||||
OLED::setCursor(50, 0);
|
||||
} else {
|
||||
OLED::setCursor(-1, 0);
|
||||
}
|
||||
// Draw in the screen details
|
||||
if (getSettingValue(SettingsOptions::DetailedSoldering)) {
|
||||
if (OLED::getRotation()) {
|
||||
OLED::setCursor(50, 0);
|
||||
} else {
|
||||
OLED::setCursor(-1, 0);
|
||||
}
|
||||
|
||||
gui_drawTipTemp(true, FontStyle::LARGE);
|
||||
gui_drawTipTemp(true, FontStyle::LARGE);
|
||||
|
||||
#ifndef NO_SLEEP_MODE
|
||||
if (getSettingValue(SettingsOptions::Sensitivity) && getSettingValue(SettingsOptions::SleepTime)) {
|
||||
if (OLED::getRotation()) {
|
||||
OLED::setCursor(32, 0);
|
||||
} else {
|
||||
OLED::setCursor(47, 0);
|
||||
}
|
||||
printCountdownUntilSleep(getSleepTimeout());
|
||||
if (getSettingValue(SettingsOptions::Sensitivity) && getSettingValue(SettingsOptions::SleepTime)) {
|
||||
if (OLED::getRotation()) {
|
||||
OLED::setCursor(32, 0);
|
||||
} else {
|
||||
OLED::setCursor(47, 0);
|
||||
}
|
||||
printCountdownUntilSleep(getSleepTimeout());
|
||||
}
|
||||
#endif
|
||||
|
||||
if (boostModeOn) {
|
||||
if (OLED::getRotation()) {
|
||||
OLED::setCursor(38, 8);
|
||||
} else {
|
||||
OLED::setCursor(55, 8);
|
||||
}
|
||||
OLED::print(SmallSymbolPlus, FontStyle::SMALL);
|
||||
if (cxt->scratch_state.state2) { // Boost mode is on
|
||||
if (OLED::getRotation()) {
|
||||
OLED::setCursor(38, 8);
|
||||
} else {
|
||||
if (OLED::getRotation()) {
|
||||
OLED::setCursor(32, 8);
|
||||
} else {
|
||||
OLED::setCursor(47, 8);
|
||||
}
|
||||
OLED::print(PowerSourceNames[getPowerSourceNumber()], FontStyle::SMALL, 2);
|
||||
OLED::setCursor(55, 8);
|
||||
}
|
||||
|
||||
detailedPowerStatus();
|
||||
|
||||
OLED::print(SmallSymbolPlus, FontStyle::SMALL);
|
||||
} else {
|
||||
basicSolderingStatus(boostModeOn);
|
||||
}
|
||||
|
||||
OLED::refresh();
|
||||
// Update the setpoints for the temperature
|
||||
if (boostModeOn) {
|
||||
if (getSettingValue(SettingsOptions::TemperatureInF)) {
|
||||
currentTempTargetDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::BoostTemp));
|
||||
if (OLED::getRotation()) {
|
||||
OLED::setCursor(32, 8);
|
||||
} else {
|
||||
currentTempTargetDegC = (getSettingValue(SettingsOptions::BoostTemp));
|
||||
}
|
||||
} else {
|
||||
if (getSettingValue(SettingsOptions::TemperatureInF)) {
|
||||
currentTempTargetDegC = TipThermoModel::convertFtoC(getSettingValue(SettingsOptions::SolderingTemp));
|
||||
} else {
|
||||
currentTempTargetDegC = (getSettingValue(SettingsOptions::SolderingTemp));
|
||||
OLED::setCursor(47, 8);
|
||||
}
|
||||
OLED::print(PowerSourceNames[getPowerSourceNumber()], FontStyle::SMALL, 2);
|
||||
}
|
||||
|
||||
if (checkExitSoldering()) {
|
||||
setBuzzer(false);
|
||||
return;
|
||||
}
|
||||
detailedPowerStatus();
|
||||
|
||||
// Update status
|
||||
int error = currentTempTargetDegC - TipThermoModel::getTipInC();
|
||||
if (error >= -10 && error <= 10) {
|
||||
// converged
|
||||
if (!converged) {
|
||||
setBuzzer(true);
|
||||
buzzerEnd = xTaskGetTickCount() + TICKS_SECOND / 3;
|
||||
converged = true;
|
||||
}
|
||||
setStatusLED(LED_HOT);
|
||||
} else {
|
||||
setStatusLED(LED_HEATING);
|
||||
converged = false;
|
||||
}
|
||||
if (buzzerEnd != 0 && xTaskGetTickCount() >= buzzerEnd) {
|
||||
setBuzzer(false);
|
||||
}
|
||||
|
||||
// slow down ui update rate
|
||||
GUIDelay();
|
||||
} else {
|
||||
basicSolderingStatus(cxt->scratch_state.state2);
|
||||
}
|
||||
// Check if we should bail due to undervoltage for example
|
||||
if (checkExitSoldering()) {
|
||||
setBuzzer(false);
|
||||
cxt->transitionMode = TransitionAnimation::Right;
|
||||
return OperatingMode::HomeScreen;
|
||||
}
|
||||
#ifdef NO_SLEEP_MODE
|
||||
|
||||
if (shouldShutdown()) {
|
||||
// shutdown
|
||||
currentTempTargetDegC = 0;
|
||||
cxt->transitionMode = TransitionAnimation::Right;
|
||||
return OperatingMode::HomeScreen;
|
||||
}
|
||||
#endif
|
||||
if (shouldBeSleeping()) {
|
||||
return OperatingMode::Sleeping;
|
||||
}
|
||||
|
||||
if (heaterThermalRunaway) {
|
||||
currentTempTargetDegC = 0; // heater control off
|
||||
heaterThermalRunaway = false;
|
||||
cxt->transitionMode = TransitionAnimation::Right;
|
||||
return OperatingMode::ThermalRunaway;
|
||||
}
|
||||
return handleSolderingButtons(buttons, cxt);
|
||||
}
|
||||
|
||||
@@ -2,222 +2,212 @@
|
||||
#include "OperatingModes.h"
|
||||
#include "SolderingCommon.h"
|
||||
|
||||
extern OperatingMode currentMode;
|
||||
|
||||
void gui_solderingProfileMode() {
|
||||
OperatingMode gui_solderingProfileMode(const ButtonState buttons, guiContext *cxt) {
|
||||
/*
|
||||
* * Soldering (gui_solderingMode)
|
||||
* * Soldering
|
||||
* -> Main loop where we draw temp, and animations
|
||||
* PID control
|
||||
* --> Long hold back button to exit
|
||||
* --> Double button to exit
|
||||
*/
|
||||
currentMode = OperatingMode::soldering;
|
||||
|
||||
TickType_t buzzerEnd = 0;
|
||||
uint16_t tipTemp = 0;
|
||||
|
||||
bool waitForRelease = true;
|
||||
TickType_t phaseStartTime = xTaskGetTickCount();
|
||||
|
||||
uint16_t tipTemp = 0;
|
||||
uint8_t profilePhase = 0;
|
||||
|
||||
uint16_t phaseElapsedSeconds = 0;
|
||||
uint16_t phaseTotalSeconds = 0;
|
||||
uint16_t phaseStartTemp = 0;
|
||||
uint16_t phaseEndTemp = getSettingValue(SettingsOptions::ProfilePreheatTemp);
|
||||
// If this is during init, start at preheat
|
||||
if (cxt->scratch_state.state1 == 0) {
|
||||
cxt->scratch_state.state5 = getSettingValue(SettingsOptions::ProfilePreheatTemp);
|
||||
}
|
||||
uint16_t phaseTicksPerDegree = TICKS_SECOND / getSettingValue(SettingsOptions::ProfilePreheatSpeed);
|
||||
uint16_t profileCurrentTargetTemp = 0;
|
||||
|
||||
for (;;) {
|
||||
ButtonState buttons = getButtonState();
|
||||
if (buttons) {
|
||||
if (waitForRelease) {
|
||||
buttons = BUTTON_NONE;
|
||||
}
|
||||
} else {
|
||||
waitForRelease = false;
|
||||
}
|
||||
|
||||
switch (buttons) {
|
||||
case BUTTON_NONE:
|
||||
break;
|
||||
case BUTTON_BOTH:
|
||||
case BUTTON_B_LONG:
|
||||
return; // exit on back long hold
|
||||
case BUTTON_F_LONG:
|
||||
case BUTTON_F_SHORT:
|
||||
case BUTTON_B_SHORT:
|
||||
// Not used yet
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
tipTemp = getTipTemp();
|
||||
|
||||
// if start temp is unknown (preheat), we're setting it now
|
||||
if (phaseStartTemp == 0) {
|
||||
phaseStartTemp = tipTemp;
|
||||
// if this is hotter than the preheat temperature, we should fail
|
||||
if (phaseStartTemp >= 55) {
|
||||
warnUser(translatedString(Tr->TooHotToStartProfileWarning), 10 * TICKS_SECOND);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
phaseElapsedSeconds = (xTaskGetTickCount() - phaseStartTime) / TICKS_SECOND;
|
||||
|
||||
// have we finished this phase?
|
||||
if (phaseElapsedSeconds >= phaseTotalSeconds && tipTemp == phaseEndTemp) {
|
||||
profilePhase++;
|
||||
|
||||
phaseStartTemp = phaseEndTemp;
|
||||
phaseStartTime = xTaskGetTickCount();
|
||||
phaseElapsedSeconds = 0;
|
||||
|
||||
if (profilePhase > getSettingValue(SettingsOptions::ProfilePhases)) {
|
||||
// done with all phases, lets go to cooldown
|
||||
phaseTotalSeconds = 0;
|
||||
phaseEndTemp = 0;
|
||||
phaseTicksPerDegree = TICKS_SECOND / getSettingValue(SettingsOptions::ProfileCooldownSpeed);
|
||||
} else {
|
||||
// set up next phase
|
||||
switch (profilePhase) {
|
||||
case 1:
|
||||
phaseTotalSeconds = getSettingValue(SettingsOptions::ProfilePhase1Duration);
|
||||
phaseEndTemp = getSettingValue(SettingsOptions::ProfilePhase1Temp);
|
||||
break;
|
||||
case 2:
|
||||
phaseTotalSeconds = getSettingValue(SettingsOptions::ProfilePhase2Duration);
|
||||
phaseEndTemp = getSettingValue(SettingsOptions::ProfilePhase2Temp);
|
||||
break;
|
||||
case 3:
|
||||
phaseTotalSeconds = getSettingValue(SettingsOptions::ProfilePhase3Duration);
|
||||
phaseEndTemp = getSettingValue(SettingsOptions::ProfilePhase3Temp);
|
||||
break;
|
||||
case 4:
|
||||
phaseTotalSeconds = getSettingValue(SettingsOptions::ProfilePhase4Duration);
|
||||
phaseEndTemp = getSettingValue(SettingsOptions::ProfilePhase4Temp);
|
||||
break;
|
||||
case 5:
|
||||
phaseTotalSeconds = getSettingValue(SettingsOptions::ProfilePhase5Duration);
|
||||
phaseEndTemp = getSettingValue(SettingsOptions::ProfilePhase5Temp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (phaseStartTemp < phaseEndTemp) {
|
||||
phaseTicksPerDegree = (phaseTotalSeconds * TICKS_SECOND) / (phaseEndTemp - phaseStartTemp);
|
||||
} else {
|
||||
phaseTicksPerDegree = (phaseTotalSeconds * TICKS_SECOND) / (phaseStartTemp - phaseEndTemp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cooldown phase done?
|
||||
if (profilePhase > getSettingValue(SettingsOptions::ProfilePhases)) {
|
||||
if (TipThermoModel::getTipInC() < 55) {
|
||||
// we're done, let the buzzer beep too
|
||||
setStatusLED(LED_STANDBY);
|
||||
if (buzzerEnd == 0) {
|
||||
setBuzzer(true);
|
||||
buzzerEnd = xTaskGetTickCount() + TICKS_SECOND / 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// determine current target temp
|
||||
if (phaseStartTemp < phaseEndTemp) {
|
||||
if (profileCurrentTargetTemp < phaseEndTemp) {
|
||||
profileCurrentTargetTemp = phaseStartTemp + ((xTaskGetTickCount() - phaseStartTime) / phaseTicksPerDegree);
|
||||
}
|
||||
} else {
|
||||
if (profileCurrentTargetTemp > phaseEndTemp) {
|
||||
profileCurrentTargetTemp = phaseStartTemp - ((xTaskGetTickCount() - phaseStartTime) / phaseTicksPerDegree);
|
||||
}
|
||||
}
|
||||
|
||||
OLED::clearScreen();
|
||||
// Draw in the screen details
|
||||
if (getSettingValue(SettingsOptions::DetailedSoldering)) {
|
||||
// print temperature
|
||||
if (OLED::getRotation()) {
|
||||
OLED::setCursor(48, 0);
|
||||
} else {
|
||||
OLED::setCursor(0, 0);
|
||||
}
|
||||
|
||||
OLED::printNumber(tipTemp, 3, FontStyle::SMALL);
|
||||
OLED::print(SmallSymbolSlash, FontStyle::SMALL);
|
||||
OLED::printNumber(profileCurrentTargetTemp, 3, FontStyle::SMALL);
|
||||
OLED::printSymbolDeg(FontStyle::SMALL);
|
||||
|
||||
// print phase
|
||||
if (profilePhase > 0 && profilePhase <= getSettingValue(SettingsOptions::ProfilePhases)) {
|
||||
if (OLED::getRotation()) {
|
||||
OLED::setCursor(36, 0);
|
||||
} else {
|
||||
OLED::setCursor(55, 0);
|
||||
}
|
||||
OLED::printNumber(profilePhase, 1, FontStyle::SMALL);
|
||||
}
|
||||
|
||||
// print time progress / preheat / cooldown
|
||||
if (OLED::getRotation()) {
|
||||
OLED::setCursor(42, 8);
|
||||
} else {
|
||||
OLED::setCursor(0, 8);
|
||||
}
|
||||
|
||||
if (profilePhase == 0) {
|
||||
OLED::print(translatedString(Tr->ProfilePreheatString), FontStyle::SMALL);
|
||||
} else if (profilePhase > getSettingValue(SettingsOptions::ProfilePhases)) {
|
||||
OLED::print(translatedString(Tr->ProfileCooldownString), FontStyle::SMALL);
|
||||
} else {
|
||||
OLED::printNumber(phaseElapsedSeconds / 60, 1, FontStyle::SMALL);
|
||||
OLED::print(SmallSymbolColon, FontStyle::SMALL);
|
||||
OLED::printNumber(phaseElapsedSeconds % 60, 2, FontStyle::SMALL, false);
|
||||
|
||||
OLED::print(SmallSymbolSlash, FontStyle::SMALL);
|
||||
|
||||
// blink if we can't keep up with the time goal
|
||||
if (phaseElapsedSeconds < phaseTotalSeconds + 2 || (xTaskGetTickCount() / TICKS_SECOND) % 2 == 0) {
|
||||
OLED::printNumber(phaseTotalSeconds / 60, 1, FontStyle::SMALL);
|
||||
OLED::print(SmallSymbolColon, FontStyle::SMALL);
|
||||
OLED::printNumber(phaseTotalSeconds % 60, 2, FontStyle::SMALL, false);
|
||||
}
|
||||
}
|
||||
|
||||
detailedPowerStatus();
|
||||
|
||||
} else {
|
||||
basicSolderingStatus(false);
|
||||
}
|
||||
|
||||
OLED::refresh();
|
||||
// Update the setpoints for the temperature
|
||||
if (getSettingValue(SettingsOptions::TemperatureInF)) {
|
||||
currentTempTargetDegC = TipThermoModel::convertFtoC(profileCurrentTargetTemp);
|
||||
} else {
|
||||
currentTempTargetDegC = profileCurrentTargetTemp;
|
||||
}
|
||||
|
||||
if (checkExitSoldering() || (buzzerEnd != 0 && xTaskGetTickCount() >= buzzerEnd)) {
|
||||
setBuzzer(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update LED status
|
||||
if (profilePhase == 0) {
|
||||
setStatusLED(LED_HEATING);
|
||||
} else if (profilePhase > getSettingValue(SettingsOptions::ProfilePhases)) {
|
||||
setStatusLED(LED_COOLING_STILL_HOT);
|
||||
} else {
|
||||
setStatusLED(LED_HOT);
|
||||
}
|
||||
|
||||
// slow down ui update rate
|
||||
GUIDelay();
|
||||
switch (buttons) {
|
||||
case BUTTON_BOTH:
|
||||
case BUTTON_B_LONG:
|
||||
cxt->transitionMode = TransitionAnimation::Right;
|
||||
return OperatingMode::HomeScreen; // exit on back long hold
|
||||
case BUTTON_F_LONG:
|
||||
case BUTTON_F_SHORT:
|
||||
case BUTTON_B_SHORT:
|
||||
case BUTTON_NONE:
|
||||
// Not used yet
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (getSettingValue(SettingsOptions::TemperatureInF)) {
|
||||
tipTemp = TipThermoModel::getTipInF();
|
||||
} else {
|
||||
tipTemp = TipThermoModel::getTipInC();
|
||||
}
|
||||
// If time of entering is unknown; then we start now
|
||||
if (cxt->scratch_state.state3 == 0) {
|
||||
cxt->scratch_state.state3 = xTaskGetTickCount();
|
||||
}
|
||||
|
||||
// if start temp is unknown (preheat), we're setting it now
|
||||
if (cxt->scratch_state.state6 == 0) {
|
||||
cxt->scratch_state.state6 = tipTemp;
|
||||
// if this is hotter than the preheat temperature, we should fail
|
||||
if (cxt->scratch_state.state6 >= 55) {
|
||||
warnUser(translatedString(Tr->TooHotToStartProfileWarning), buttons);
|
||||
return OperatingMode::HomeScreen;
|
||||
}
|
||||
}
|
||||
uint16_t phaseElapsedSeconds = (xTaskGetTickCount() - cxt->scratch_state.state3) / TICKS_SECOND;
|
||||
|
||||
// have we finished this phase?
|
||||
if (phaseElapsedSeconds >= cxt->scratch_state.state2 && tipTemp == cxt->scratch_state.state5) {
|
||||
cxt->scratch_state.state1++;
|
||||
cxt->scratch_state.state6 = cxt->scratch_state.state5;
|
||||
cxt->scratch_state.state3 = xTaskGetTickCount();
|
||||
phaseElapsedSeconds = 0;
|
||||
if (cxt->scratch_state.state1 > getSettingValue(SettingsOptions::ProfilePhases)) {
|
||||
// done with all phases, lets go to cooldown
|
||||
cxt->scratch_state.state2 = 0;
|
||||
cxt->scratch_state.state5 = 0;
|
||||
phaseTicksPerDegree = TICKS_SECOND / getSettingValue(SettingsOptions::ProfileCooldownSpeed);
|
||||
} else {
|
||||
// set up next phase
|
||||
switch (cxt->scratch_state.state1) {
|
||||
case 1:
|
||||
cxt->scratch_state.state2 = getSettingValue(SettingsOptions::ProfilePhase1Duration);
|
||||
cxt->scratch_state.state5 = getSettingValue(SettingsOptions::ProfilePhase1Temp);
|
||||
break;
|
||||
case 2:
|
||||
cxt->scratch_state.state2 = getSettingValue(SettingsOptions::ProfilePhase2Duration);
|
||||
cxt->scratch_state.state5 = getSettingValue(SettingsOptions::ProfilePhase2Temp);
|
||||
break;
|
||||
case 3:
|
||||
cxt->scratch_state.state2 = getSettingValue(SettingsOptions::ProfilePhase3Duration);
|
||||
cxt->scratch_state.state5 = getSettingValue(SettingsOptions::ProfilePhase3Temp);
|
||||
break;
|
||||
case 4:
|
||||
cxt->scratch_state.state2 = getSettingValue(SettingsOptions::ProfilePhase4Duration);
|
||||
cxt->scratch_state.state5 = getSettingValue(SettingsOptions::ProfilePhase4Temp);
|
||||
break;
|
||||
case 5:
|
||||
cxt->scratch_state.state2 = getSettingValue(SettingsOptions::ProfilePhase5Duration);
|
||||
cxt->scratch_state.state5 = getSettingValue(SettingsOptions::ProfilePhase5Temp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (cxt->scratch_state.state6 < cxt->scratch_state.state5) {
|
||||
phaseTicksPerDegree = (cxt->scratch_state.state2 * TICKS_SECOND) / (cxt->scratch_state.state5 - cxt->scratch_state.state6);
|
||||
} else {
|
||||
phaseTicksPerDegree = (cxt->scratch_state.state2 * TICKS_SECOND) / (cxt->scratch_state.state6 - cxt->scratch_state.state5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cooldown phase done?
|
||||
if (cxt->scratch_state.state1 > getSettingValue(SettingsOptions::ProfilePhases)) {
|
||||
if (TipThermoModel::getTipInC() < 55) {
|
||||
// we're done, let the buzzer beep too
|
||||
setStatusLED(LED_STANDBY);
|
||||
if (cxt->scratch_state.state4 == 0) {
|
||||
setBuzzer(true);
|
||||
cxt->scratch_state.state4 = xTaskGetTickCount() + TICKS_SECOND / 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// determine current target temp
|
||||
if (cxt->scratch_state.state6 < cxt->scratch_state.state5) {
|
||||
if (profileCurrentTargetTemp < cxt->scratch_state.state5) {
|
||||
profileCurrentTargetTemp = cxt->scratch_state.state6 + ((xTaskGetTickCount() - cxt->viewEnterTime) / phaseTicksPerDegree);
|
||||
}
|
||||
} else {
|
||||
if (profileCurrentTargetTemp > cxt->scratch_state.state5) {
|
||||
profileCurrentTargetTemp = cxt->scratch_state.state6 - ((xTaskGetTickCount() - cxt->viewEnterTime) / phaseTicksPerDegree);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw in the screen details
|
||||
if (getSettingValue(SettingsOptions::DetailedSoldering)) {
|
||||
// print temperature
|
||||
if (OLED::getRotation()) {
|
||||
OLED::setCursor(48, 0);
|
||||
} else {
|
||||
OLED::setCursor(0, 0);
|
||||
}
|
||||
|
||||
OLED::printNumber(tipTemp, 3, FontStyle::SMALL);
|
||||
OLED::print(SmallSymbolSlash, FontStyle::SMALL);
|
||||
OLED::printNumber(profileCurrentTargetTemp, 3, FontStyle::SMALL);
|
||||
|
||||
if (getSettingValue(SettingsOptions::TemperatureInF)) {
|
||||
OLED::print(SmallSymbolDegF, FontStyle::SMALL);
|
||||
} else {
|
||||
OLED::print(SmallSymbolDegC, FontStyle::SMALL);
|
||||
}
|
||||
|
||||
// print phase
|
||||
if (cxt->scratch_state.state1 > 0 && cxt->scratch_state.state1 <= getSettingValue(SettingsOptions::ProfilePhases)) {
|
||||
if (OLED::getRotation()) {
|
||||
OLED::setCursor(36, 0);
|
||||
} else {
|
||||
OLED::setCursor(55, 0);
|
||||
}
|
||||
OLED::printNumber(cxt->scratch_state.state1, 1, FontStyle::SMALL);
|
||||
}
|
||||
|
||||
// print time progress / preheat / cooldown
|
||||
if (OLED::getRotation()) {
|
||||
OLED::setCursor(42, 8);
|
||||
} else {
|
||||
OLED::setCursor(0, 8);
|
||||
}
|
||||
|
||||
if (cxt->scratch_state.state1 == 0) {
|
||||
OLED::print(translatedString(Tr->ProfilePreheatString), FontStyle::SMALL);
|
||||
} else if (cxt->scratch_state.state1 > getSettingValue(SettingsOptions::ProfilePhases)) {
|
||||
OLED::print(translatedString(Tr->ProfileCooldownString), FontStyle::SMALL);
|
||||
} else {
|
||||
OLED::printNumber(phaseElapsedSeconds / 60, 1, FontStyle::SMALL);
|
||||
OLED::print(SmallSymbolColon, FontStyle::SMALL);
|
||||
OLED::printNumber(phaseElapsedSeconds % 60, 2, FontStyle::SMALL, false);
|
||||
|
||||
OLED::print(SmallSymbolSlash, FontStyle::SMALL);
|
||||
|
||||
// blink if we can't keep up with the time goal
|
||||
if (phaseElapsedSeconds < cxt->scratch_state.state2 + 2 || (xTaskGetTickCount() / TICKS_SECOND) % 2 == 0) {
|
||||
OLED::printNumber(cxt->scratch_state.state2 / 60, 1, FontStyle::SMALL);
|
||||
OLED::print(SmallSymbolColon, FontStyle::SMALL);
|
||||
OLED::printNumber(cxt->scratch_state.state2 % 60, 2, FontStyle::SMALL, false);
|
||||
}
|
||||
}
|
||||
|
||||
detailedPowerStatus();
|
||||
|
||||
} else {
|
||||
basicSolderingStatus(false);
|
||||
}
|
||||
|
||||
// Update the setpoints for the temperature
|
||||
if (getSettingValue(SettingsOptions::TemperatureInF)) {
|
||||
currentTempTargetDegC = TipThermoModel::convertFtoC(profileCurrentTargetTemp);
|
||||
} else {
|
||||
currentTempTargetDegC = profileCurrentTargetTemp;
|
||||
}
|
||||
|
||||
if (checkExitSoldering() || (cxt->scratch_state.state4 != 0 && xTaskGetTickCount() >= cxt->scratch_state.state4)) {
|
||||
setBuzzer(false);
|
||||
return OperatingMode::HomeScreen;
|
||||
}
|
||||
if (heaterThermalRunaway) {
|
||||
currentTempTargetDegC = 0; // heater control off
|
||||
heaterThermalRunaway = false;
|
||||
return OperatingMode::ThermalRunaway;
|
||||
}
|
||||
|
||||
// Update LED status
|
||||
if (cxt->scratch_state.state1 == 0) {
|
||||
setStatusLED(LED_HEATING);
|
||||
} else if (cxt->scratch_state.state1 > getSettingValue(SettingsOptions::ProfilePhases)) {
|
||||
setStatusLED(LED_COOLING_STILL_HOT);
|
||||
} else {
|
||||
setStatusLED(LED_HOT);
|
||||
}
|
||||
return OperatingMode::SolderingProfile;
|
||||
}
|
||||
|
||||
@@ -1,120 +1,104 @@
|
||||
#include "OperatingModes.h"
|
||||
void gui_solderingTempAdjust(void) {
|
||||
TickType_t lastChange = xTaskGetTickCount();
|
||||
currentTempTargetDegC = 0; // Turn off heater while adjusting temp
|
||||
TickType_t autoRepeatTimer = 0;
|
||||
uint8_t autoRepeatAcceleration = 0;
|
||||
#ifndef PROFILE_SUPPORT
|
||||
bool waitForRelease = false;
|
||||
ButtonState buttons = getButtonState();
|
||||
OperatingMode gui_solderingTempAdjust(const ButtonState buttonIn, guiContext *cxt) {
|
||||
|
||||
if (buttons != BUTTON_NONE) {
|
||||
// Temp adjust entered by long-pressing F button.
|
||||
waitForRelease = true;
|
||||
currentTempTargetDegC = 0; // Turn off heater while adjusting temp
|
||||
uint16_t *waitForRelease = &(cxt->scratch_state.state1);
|
||||
uint32_t *autoRepeatTimer = &(cxt->scratch_state.state3);
|
||||
uint16_t *autoRepeatAcceleration = &(cxt->scratch_state.state2);
|
||||
ButtonState buttons = buttonIn;
|
||||
if (*waitForRelease == 0) {
|
||||
// When we first enter we wait for the user to release buttons before enabling changes
|
||||
if (buttons != BUTTON_NONE) {
|
||||
buttons = BUTTON_NONE;
|
||||
} else {
|
||||
(*waitForRelease)++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
ButtonState buttons;
|
||||
#endif
|
||||
|
||||
for (;;) {
|
||||
OLED::setCursor(0, 0);
|
||||
OLED::clearScreen();
|
||||
buttons = getButtonState();
|
||||
if (buttons) {
|
||||
lastChange = xTaskGetTickCount();
|
||||
#ifndef PROFILE_SUPPORT
|
||||
if (waitForRelease) {
|
||||
buttons = BUTTON_NONE;
|
||||
}
|
||||
} else {
|
||||
waitForRelease = false;
|
||||
#endif
|
||||
}
|
||||
int16_t delta = 0;
|
||||
switch (buttons) {
|
||||
case BUTTON_NONE:
|
||||
// stay
|
||||
autoRepeatAcceleration = 0;
|
||||
break;
|
||||
case BUTTON_BOTH:
|
||||
// exit
|
||||
return;
|
||||
break;
|
||||
case BUTTON_B_LONG:
|
||||
if (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration > PRESS_ACCEL_INTERVAL_MAX) {
|
||||
delta = -getSettingValue(SettingsOptions::TempChangeLongStep);
|
||||
autoRepeatTimer = xTaskGetTickCount();
|
||||
autoRepeatAcceleration += PRESS_ACCEL_STEP;
|
||||
}
|
||||
break;
|
||||
case BUTTON_B_SHORT:
|
||||
delta = -getSettingValue(SettingsOptions::TempChangeShortStep);
|
||||
break;
|
||||
case BUTTON_F_LONG:
|
||||
if (xTaskGetTickCount() - autoRepeatTimer + autoRepeatAcceleration > PRESS_ACCEL_INTERVAL_MAX) {
|
||||
delta = getSettingValue(SettingsOptions::TempChangeLongStep);
|
||||
autoRepeatTimer = xTaskGetTickCount();
|
||||
autoRepeatAcceleration += PRESS_ACCEL_STEP;
|
||||
}
|
||||
break;
|
||||
case BUTTON_F_SHORT:
|
||||
delta = getSettingValue(SettingsOptions::TempChangeShortStep);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if ((PRESS_ACCEL_INTERVAL_MAX - autoRepeatAcceleration) < PRESS_ACCEL_INTERVAL_MIN) {
|
||||
autoRepeatAcceleration = PRESS_ACCEL_INTERVAL_MAX - PRESS_ACCEL_INTERVAL_MIN;
|
||||
}
|
||||
// If buttons are flipped; flip the delta
|
||||
if (getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled)) {
|
||||
delta = -delta;
|
||||
}
|
||||
if (delta != 0) {
|
||||
// constrain between the set temp limits, i.e. 10-450 C
|
||||
int16_t newTemp = getSettingValue(SettingsOptions::SolderingTemp);
|
||||
newTemp += delta;
|
||||
// Round to nearest increment of delta
|
||||
delta = abs(delta);
|
||||
newTemp = (newTemp / delta) * delta;
|
||||
OLED::setCursor(0, 0);
|
||||
|
||||
if (getSettingValue(SettingsOptions::TemperatureInF)) {
|
||||
if (newTemp > MAX_TEMP_F) {
|
||||
newTemp = MAX_TEMP_F;
|
||||
}
|
||||
if (newTemp < MIN_TEMP_F) {
|
||||
newTemp = MIN_TEMP_F;
|
||||
}
|
||||
} else {
|
||||
if (newTemp > MAX_TEMP_C) {
|
||||
newTemp = MAX_TEMP_C;
|
||||
}
|
||||
if (newTemp < MIN_TEMP_C) {
|
||||
newTemp = MIN_TEMP_C;
|
||||
}
|
||||
}
|
||||
setSettingValue(SettingsOptions::SolderingTemp, (uint16_t)newTemp);
|
||||
int16_t delta = 0;
|
||||
switch (buttons) {
|
||||
case BUTTON_NONE:
|
||||
// stay
|
||||
(*autoRepeatAcceleration) = 0;
|
||||
break;
|
||||
case BUTTON_BOTH:
|
||||
// exit
|
||||
cxt->transitionMode = TransitionAnimation::Right;
|
||||
return cxt->previousMode;
|
||||
case BUTTON_B_LONG:
|
||||
if (xTaskGetTickCount() - (*autoRepeatTimer) + (*autoRepeatAcceleration) > PRESS_ACCEL_INTERVAL_MAX) {
|
||||
delta = -getSettingValue(SettingsOptions::TempChangeLongStep);
|
||||
(*autoRepeatTimer) = xTaskGetTickCount();
|
||||
(*autoRepeatAcceleration) += PRESS_ACCEL_STEP;
|
||||
}
|
||||
if (xTaskGetTickCount() - lastChange > (TICKS_SECOND * 2)) {
|
||||
return; // exit if user just doesn't press anything for a bit
|
||||
break;
|
||||
case BUTTON_B_SHORT:
|
||||
delta = -getSettingValue(SettingsOptions::TempChangeShortStep);
|
||||
break;
|
||||
case BUTTON_F_LONG:
|
||||
if (xTaskGetTickCount() - (*autoRepeatTimer) + (*autoRepeatAcceleration) > PRESS_ACCEL_INTERVAL_MAX) {
|
||||
delta = getSettingValue(SettingsOptions::TempChangeLongStep);
|
||||
(*autoRepeatTimer) = xTaskGetTickCount();
|
||||
(*autoRepeatAcceleration) += PRESS_ACCEL_STEP;
|
||||
}
|
||||
|
||||
if (OLED::getRotation()) {
|
||||
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolPlus : LargeSymbolMinus, FontStyle::LARGE);
|
||||
} else {
|
||||
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolMinus : LargeSymbolPlus, FontStyle::LARGE);
|
||||
}
|
||||
|
||||
OLED::print(LargeSymbolSpace, FontStyle::LARGE);
|
||||
OLED::printNumber(getSettingValue(SettingsOptions::SolderingTemp), 3, FontStyle::LARGE);
|
||||
OLED::printSymbolDeg(FontStyle::EXTRAS);
|
||||
OLED::print(LargeSymbolSpace, FontStyle::LARGE);
|
||||
if (OLED::getRotation()) {
|
||||
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolMinus : LargeSymbolPlus, FontStyle::LARGE);
|
||||
} else {
|
||||
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolPlus : LargeSymbolMinus, FontStyle::LARGE);
|
||||
}
|
||||
OLED::refresh();
|
||||
GUIDelay();
|
||||
break;
|
||||
case BUTTON_F_SHORT:
|
||||
delta = getSettingValue(SettingsOptions::TempChangeShortStep);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if ((PRESS_ACCEL_INTERVAL_MAX - (*autoRepeatAcceleration)) < PRESS_ACCEL_INTERVAL_MIN) {
|
||||
(*autoRepeatAcceleration) = PRESS_ACCEL_INTERVAL_MAX - PRESS_ACCEL_INTERVAL_MIN;
|
||||
}
|
||||
// If buttons are flipped; flip the delta
|
||||
if (getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled)) {
|
||||
delta = -delta;
|
||||
}
|
||||
if (delta != 0) {
|
||||
// constrain between the set temp limits, i.e. 10-450 C
|
||||
int16_t newTemp = getSettingValue(SettingsOptions::SolderingTemp);
|
||||
newTemp += delta;
|
||||
// Round to nearest increment of delta
|
||||
delta = abs(delta);
|
||||
newTemp = (newTemp / delta) * delta;
|
||||
|
||||
if (getSettingValue(SettingsOptions::TemperatureInF)) {
|
||||
if (newTemp > MAX_TEMP_F) {
|
||||
newTemp = MAX_TEMP_F;
|
||||
} else if (newTemp < MIN_TEMP_F) {
|
||||
newTemp = MIN_TEMP_F;
|
||||
}
|
||||
} else {
|
||||
if (newTemp > MAX_TEMP_C) {
|
||||
newTemp = MAX_TEMP_C;
|
||||
} else if (newTemp < MIN_TEMP_C) {
|
||||
newTemp = MIN_TEMP_C;
|
||||
}
|
||||
}
|
||||
setSettingValue(SettingsOptions::SolderingTemp, (uint16_t)newTemp);
|
||||
}
|
||||
if (xTaskGetTickCount() - lastButtonTime > (TICKS_SECOND * 3)) {
|
||||
cxt->transitionMode = TransitionAnimation::Right;
|
||||
return cxt->previousMode; // exit if user just doesn't press anything for a bit
|
||||
}
|
||||
if (OLED::getRotation()) {
|
||||
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolPlus : LargeSymbolMinus, FontStyle::LARGE);
|
||||
} else {
|
||||
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolMinus : LargeSymbolPlus, FontStyle::LARGE);
|
||||
}
|
||||
|
||||
OLED::print(LargeSymbolSpace, FontStyle::LARGE);
|
||||
OLED::printNumber(getSettingValue(SettingsOptions::SolderingTemp), 3, FontStyle::LARGE);
|
||||
OLED::printSymbolDeg(FontStyle::EXTRAS);
|
||||
OLED::print(LargeSymbolSpace, FontStyle::LARGE);
|
||||
if (OLED::getRotation()) {
|
||||
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolMinus : LargeSymbolPlus, FontStyle::LARGE);
|
||||
} else {
|
||||
OLED::print(getSettingValue(SettingsOptions::ReverseButtonTempChangeEnabled) ? LargeSymbolPlus : LargeSymbolMinus, FontStyle::LARGE);
|
||||
}
|
||||
|
||||
return OperatingMode::TemperatureAdjust; // Stay in temp adjust
|
||||
}
|
||||
|
||||
@@ -2,93 +2,85 @@
|
||||
|
||||
#ifdef POW_PD
|
||||
#ifdef HAS_POWER_DEBUG_MENU
|
||||
void showPDDebug(void) {
|
||||
OperatingMode showPDDebug(const ButtonState buttons, guiContext *cxt) {
|
||||
// Print out the USB-PD state
|
||||
// Basically this is like the Debug menu, but instead we want to print out the PD status
|
||||
uint8_t screen = 0;
|
||||
ButtonState b;
|
||||
for (;;) {
|
||||
OLED::clearScreen(); // Ensure the buffer starts clean
|
||||
OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left)
|
||||
OLED::print(SmallSymbolPDDebug, FontStyle::SMALL); // Print Title
|
||||
OLED::setCursor(0, 8); // second line
|
||||
if (screen == 0) {
|
||||
// Print the PD state machine
|
||||
OLED::print(SmallSymbolState, FontStyle::SMALL);
|
||||
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
|
||||
OLED::printNumber(USBPowerDelivery::getStateNumber(), 2, FontStyle::SMALL, true);
|
||||
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
|
||||
// Also print vbus mod status
|
||||
if (USBPowerDelivery::fusbPresent()) {
|
||||
if (USBPowerDelivery::negotiationComplete() || (xTaskGetTickCount() > (TICKS_SECOND * 10))) {
|
||||
if (!USBPowerDelivery::isVBUSConnected()) {
|
||||
OLED::print(SmallSymbolNoVBus, FontStyle::SMALL);
|
||||
} else {
|
||||
OLED::print(SmallSymbolVBus, FontStyle::SMALL);
|
||||
}
|
||||
uint16_t *screen = &(cxt->scratch_state.state1);
|
||||
OLED::setCursor(0, 0); // Position the cursor at the 0,0 (top left)
|
||||
OLED::print(SmallSymbolPDDebug, FontStyle::SMALL); // Print Title
|
||||
OLED::setCursor(0, 8); // second line
|
||||
if ((*screen) == 0) {
|
||||
// Print the PD state machine
|
||||
OLED::print(SmallSymbolState, FontStyle::SMALL);
|
||||
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
|
||||
OLED::printNumber(USBPowerDelivery::getStateNumber(), 2, FontStyle::SMALL, true);
|
||||
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
|
||||
// Also print vbus mod status
|
||||
if (USBPowerDelivery::fusbPresent()) {
|
||||
if (USBPowerDelivery::negotiationComplete() || (xTaskGetTickCount() > (TICKS_SECOND * 10))) {
|
||||
if (!USBPowerDelivery::isVBUSConnected()) {
|
||||
OLED::print(SmallSymbolNoVBus, FontStyle::SMALL);
|
||||
} else {
|
||||
OLED::print(SmallSymbolVBus, FontStyle::SMALL);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Print out the Proposed power options one by one
|
||||
auto lastCaps = USBPowerDelivery::getLastSeenCapabilities();
|
||||
if (((*screen) - 1) < 11) {
|
||||
int voltage_mv = 0;
|
||||
int min_voltage = 0;
|
||||
int current_a_x100 = 0;
|
||||
int wattage = 0;
|
||||
|
||||
if ((lastCaps[(*screen) - 1] & PD_PDO_TYPE) == PD_PDO_TYPE_FIXED) {
|
||||
voltage_mv = PD_PDV2MV(PD_PDO_SRC_FIXED_VOLTAGE_GET(lastCaps[(*screen) - 1])); // voltage in mV units
|
||||
current_a_x100 = PD_PDO_SRC_FIXED_CURRENT_GET(lastCaps[(*screen) - 1]); // current in 10mA units
|
||||
} else if (((lastCaps[(*screen) - 1] & PD_PDO_TYPE) == PD_PDO_TYPE_AUGMENTED) && ((lastCaps[(*screen) - 1] & PD_APDO_TYPE) == PD_APDO_TYPE_AVS)) {
|
||||
voltage_mv = PD_PAV2MV(PD_APDO_AVS_MAX_VOLTAGE_GET(lastCaps[(*screen) - 1]));
|
||||
min_voltage = PD_PAV2MV(PD_APDO_PPS_MIN_VOLTAGE_GET(lastCaps[(*screen) - 1]));
|
||||
// Last value is wattage
|
||||
wattage = PD_APDO_AVS_MAX_POWER_GET(lastCaps[(*screen) - 1]);
|
||||
} else if (((lastCaps[(*screen) - 1] & PD_PDO_TYPE) == PD_PDO_TYPE_AUGMENTED) && ((lastCaps[(*screen) - 1] & PD_APDO_TYPE) == PD_APDO_TYPE_PPS)) {
|
||||
voltage_mv = PD_PAV2MV(PD_APDO_PPS_MAX_VOLTAGE_GET(lastCaps[(*screen) - 1]));
|
||||
min_voltage = PD_PAV2MV(PD_APDO_PPS_MIN_VOLTAGE_GET(lastCaps[(*screen) - 1]));
|
||||
current_a_x100 = PD_PAI2CA(PD_APDO_PPS_CURRENT_GET(lastCaps[(*screen) - 1])); // max current in 10mA units
|
||||
}
|
||||
// Skip not used entries
|
||||
if (voltage_mv == 0) {
|
||||
(*screen) += 1;
|
||||
} else {
|
||||
// print out this entry of the proposal
|
||||
OLED::printNumber(*screen, 2, FontStyle::SMALL, true); // print the entry number
|
||||
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
|
||||
if (min_voltage > 0) {
|
||||
OLED::printNumber(min_voltage / 1000, 2, FontStyle::SMALL, true); // print the voltage
|
||||
OLED::print(SmallSymbolMinus, FontStyle::SMALL);
|
||||
}
|
||||
OLED::printNumber(voltage_mv / 1000, 2, FontStyle::SMALL, true); // print the voltage
|
||||
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
|
||||
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
|
||||
if (wattage) {
|
||||
OLED::printNumber(wattage, 3, FontStyle::SMALL, true); // print the current in 0.1A res
|
||||
OLED::print(SmallSymbolWatts, FontStyle::SMALL);
|
||||
} else {
|
||||
OLED::printNumber(current_a_x100 / 100, 2, FontStyle::SMALL, true); // print the current in 0.1A res
|
||||
OLED::print(SmallSymbolDot, FontStyle::SMALL);
|
||||
OLED::printNumber(current_a_x100 % 100, 2, FontStyle::SMALL, false); // print the current in 0.1A res
|
||||
OLED::print(SmallSymbolAmps, FontStyle::SMALL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Print out the Proposed power options one by one
|
||||
auto lastCaps = USBPowerDelivery::getLastSeenCapabilities();
|
||||
if ((screen - 1) < 11) {
|
||||
int voltage_mv = 0;
|
||||
int min_voltage = 0;
|
||||
int current_a_x100 = 0;
|
||||
int wattage = 0;
|
||||
|
||||
if ((lastCaps[screen - 1] & PD_PDO_TYPE) == PD_PDO_TYPE_FIXED) {
|
||||
voltage_mv = PD_PDV2MV(PD_PDO_SRC_FIXED_VOLTAGE_GET(lastCaps[screen - 1])); // voltage in mV units
|
||||
current_a_x100 = PD_PDO_SRC_FIXED_CURRENT_GET(lastCaps[screen - 1]); // current in 10mA units
|
||||
} else if (((lastCaps[screen - 1] & PD_PDO_TYPE) == PD_PDO_TYPE_AUGMENTED) && ((lastCaps[screen - 1] & PD_APDO_TYPE) == PD_APDO_TYPE_AVS)) {
|
||||
voltage_mv = PD_PAV2MV(PD_APDO_AVS_MAX_VOLTAGE_GET(lastCaps[screen - 1]));
|
||||
min_voltage = PD_PAV2MV(PD_APDO_PPS_MIN_VOLTAGE_GET(lastCaps[screen - 1]));
|
||||
// Last value is wattage
|
||||
wattage = PD_APDO_AVS_MAX_POWER_GET(lastCaps[screen - 1]);
|
||||
} else if (((lastCaps[screen - 1] & PD_PDO_TYPE) == PD_PDO_TYPE_AUGMENTED) && ((lastCaps[screen - 1] & PD_APDO_TYPE) == PD_APDO_TYPE_PPS)) {
|
||||
voltage_mv = PD_PAV2MV(PD_APDO_PPS_MAX_VOLTAGE_GET(lastCaps[screen - 1]));
|
||||
min_voltage = PD_PAV2MV(PD_APDO_PPS_MIN_VOLTAGE_GET(lastCaps[screen - 1]));
|
||||
current_a_x100 = PD_PAI2CA(PD_APDO_PPS_CURRENT_GET(lastCaps[screen - 1])); // max current in 10mA units
|
||||
}
|
||||
// Skip not used entries
|
||||
if (voltage_mv == 0) {
|
||||
screen++;
|
||||
} else {
|
||||
// print out this entry of the proposal
|
||||
OLED::printNumber(screen, 2, FontStyle::SMALL, true); // print the entry number
|
||||
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
|
||||
if (min_voltage > 0) {
|
||||
OLED::printNumber(min_voltage / 1000, 2, FontStyle::SMALL, true); // print the voltage
|
||||
OLED::print(SmallSymbolMinus, FontStyle::SMALL);
|
||||
}
|
||||
OLED::printNumber(voltage_mv / 1000, 2, FontStyle::SMALL, true); // print the voltage
|
||||
OLED::print(SmallSymbolVolts, FontStyle::SMALL);
|
||||
OLED::print(SmallSymbolSpace, FontStyle::SMALL);
|
||||
if (wattage) {
|
||||
OLED::printNumber(wattage, 3, FontStyle::SMALL, true); // print the current in 0.1A res
|
||||
OLED::print(SmallSymbolWatts, FontStyle::SMALL);
|
||||
} else {
|
||||
OLED::printNumber(current_a_x100 / 100, 2, FontStyle::SMALL, true); // print the current in 0.1A res
|
||||
OLED::print(SmallSymbolDot, FontStyle::SMALL);
|
||||
OLED::printNumber(current_a_x100 % 100, 2, FontStyle::SMALL, false); // print the current in 0.1A res
|
||||
OLED::print(SmallSymbolAmps, FontStyle::SMALL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
screen = 0;
|
||||
}
|
||||
(*screen) = 0;
|
||||
}
|
||||
|
||||
OLED::refresh();
|
||||
b = getButtonState();
|
||||
if (b == BUTTON_B_SHORT) {
|
||||
return;
|
||||
} else if (b == BUTTON_F_SHORT) {
|
||||
screen++;
|
||||
}
|
||||
|
||||
GUIDelay();
|
||||
}
|
||||
if (buttons == BUTTON_B_SHORT) {
|
||||
return OperatingMode::InitialisationDone;
|
||||
} else if (buttons == BUTTON_F_SHORT) {
|
||||
(*screen) += 1;
|
||||
}
|
||||
return OperatingMode::UsbPDDebug;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "OperatingModes.h"
|
||||
#if POW_PD_EXT == 1
|
||||
#ifdef HAS_POWER_DEBUG_MENU
|
||||
void showPDDebug(void) {
|
||||
OperatingMode showPDDebug(const ButtonState buttons, guiContext *cxt) {
|
||||
// Print out the USB-PD state
|
||||
// Basically this is like the Debug menu, but instead we want to print out the PD status
|
||||
uint8_t screen = 0;
|
||||
@@ -44,13 +44,14 @@ void showPDDebug(void) {
|
||||
OLED::refresh();
|
||||
b = getButtonState();
|
||||
if (b == BUTTON_B_SHORT) {
|
||||
return;
|
||||
return OperatingMode::InitialisationDone;
|
||||
} else if (b == BUTTON_F_SHORT) {
|
||||
screen++;
|
||||
}
|
||||
|
||||
GUIDelay();
|
||||
}
|
||||
return OperatingMode::UsbPDDebug;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#include "OperatingModeUtilities.h"
|
||||
#include "OperatingModes.h"
|
||||
#include "SolderingCommon.h"
|
||||
#include "TipThermoModel.h"
|
||||
|
||||
void gui_drawTipTemp(bool symbol, const FontStyle font) {
|
||||
// Draw tip temp handling unit conversion & tolerance near setpoint
|
||||
uint16_t Temp = getTipTemp();
|
||||
TemperatureType_t Temp = getTipTemp();
|
||||
|
||||
OLED::printNumber(Temp, 3, font); // Draw the tip temp out
|
||||
if (symbol) {
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
#ifndef OPERATING_MODE_UTILITIES_H_
|
||||
#define OPERATING_MODE_UTILITIES_H_
|
||||
#include "Buttons.hpp"
|
||||
#include "OLED.hpp"
|
||||
#include <stdbool.h>
|
||||
|
||||
void GUIDelay(); //
|
||||
bool checkForUnderVoltage(void); //
|
||||
uint32_t getSleepTimeout(void); //
|
||||
bool shouldBeSleeping(bool inAutoStart); //
|
||||
bool shouldShutdown(void); //
|
||||
void gui_drawTipTemp(bool symbol, const FontStyle font); //
|
||||
void printVoltage(void); //
|
||||
void warnUser(const char *warning, const TickType_t timeout); //
|
||||
void gui_drawBatteryIcon(void); //
|
||||
bool checkForUnderVoltage(void); //
|
||||
uint16_t min(uint16_t a, uint16_t b); //
|
||||
void printCountdownUntilSleep(int sleepThres); //
|
||||
void GUIDelay(); //
|
||||
bool checkForUnderVoltage(void); //
|
||||
uint32_t getSleepTimeout(void); //
|
||||
bool shouldBeSleeping(); //
|
||||
bool shouldShutdown(void); //
|
||||
void gui_drawTipTemp(bool symbol, const FontStyle font); //
|
||||
void printVoltage(void); //
|
||||
bool warnUser(const char *warning, const ButtonState buttons); //
|
||||
void gui_drawBatteryIcon(void); //
|
||||
bool checkForUnderVoltage(void); //
|
||||
uint16_t min(uint16_t a, uint16_t b); //
|
||||
void printCountdownUntilSleep(int sleepThres); //
|
||||
#endif
|
||||
@@ -1,8 +1,9 @@
|
||||
#include "Buttons.hpp"
|
||||
#include "OperatingModeUtilities.h"
|
||||
void warnUser(const char *warning, const TickType_t timeout) {
|
||||
#include "OperatingModes.h"
|
||||
bool warnUser(const char *warning, const ButtonState buttons) {
|
||||
OLED::clearScreen();
|
||||
OLED::printWholeScreen(warning);
|
||||
OLED::refresh();
|
||||
waitForButtonPressOrTimeout(timeout);
|
||||
// TODO also timeout
|
||||
return buttons != BUTTON_NONE;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include "SolderingCommon.h"
|
||||
#include "OperatingModes.h"
|
||||
#include "configuration.h"
|
||||
#include "history.hpp"
|
||||
|
||||
extern bool heaterThermalRunaway;
|
||||
|
||||
@@ -104,30 +106,8 @@ bool checkExitSoldering(void) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef NO_SLEEP_MODE
|
||||
// No sleep mode, but still want shutdown timeout
|
||||
|
||||
if (shouldShutdown()) {
|
||||
// shutdown
|
||||
currentTempTargetDegC = 0;
|
||||
lastMovementTime = xTaskGetTickCount(); // We manually move the movement time to now such that shutdown timer is reset
|
||||
|
||||
return true; // we want to exit soldering mode
|
||||
}
|
||||
#endif
|
||||
if (shouldBeSleeping(false)) {
|
||||
if (gui_SolderingSleepingMode(false, false)) {
|
||||
return true; // If the function returns non-0 then exit
|
||||
}
|
||||
}
|
||||
|
||||
// If we have tripped thermal runaway, turn off heater and show warning
|
||||
if (heaterThermalRunaway) {
|
||||
currentTempTargetDegC = 0; // heater control off
|
||||
warnUser(translatedString(Tr->WarningThermalRunaway), 10 * TICKS_SECOND);
|
||||
heaterThermalRunaway = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -166,4 +146,14 @@ int8_t getPowerSourceNumber(void) {
|
||||
}
|
||||
|
||||
// Returns temperature of the tip in *C/*F (based on user settings)
|
||||
uint16_t getTipTemp(void) { return getSettingValue(SettingsOptions::TemperatureInF) ? TipThermoModel::getTipInF() : TipThermoModel::getTipInC(); }
|
||||
TemperatureType_t getTipTemp(void) {
|
||||
#ifdef FILTER_DISPLAYED_TIP_TEMP
|
||||
static history<TemperatureType_t, FILTER_DISPLAYED_TIP_TEMP> Filter_Temp;
|
||||
TemperatureType_t reading = getSettingValue(SettingsOptions::TemperatureInF) ? TipThermoModel::getTipInF() : TipThermoModel::getTipInC();
|
||||
Filter_Temp.update(reading);
|
||||
return Filter_Temp.average();
|
||||
|
||||
#else
|
||||
return getSettingValue(SettingsOptions::TemperatureInF) ? TipThermoModel::getTipInF() : TipThermoModel::getTipInC();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#ifndef SOLDERING_COMMON_H
|
||||
#define SOLDERING_COMMON_H
|
||||
#include <stdint.h>
|
||||
|
||||
void detailedPowerStatus();
|
||||
void basicSolderingStatus(bool boostModeOn);
|
||||
bool checkExitSoldering();
|
||||
void detailedPowerStatus();
|
||||
void basicSolderingStatus(bool boostModeOn);
|
||||
bool checkExitSoldering();
|
||||
uint16_t getTipTemp(void);
|
||||
|
||||
#endif //SOLDERING_COMMON_H
|
||||
#endif // SOLDERING_COMMON_H
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "OperatingModeUtilities.h"
|
||||
#include "configuration.h"
|
||||
#ifdef POW_DC
|
||||
extern volatile uint32_t currentTempTargetDegC;
|
||||
extern volatile TemperatureType_t currentTempTargetDegC;
|
||||
// returns true if undervoltage has occured
|
||||
bool checkForUnderVoltage(void) {
|
||||
if (!getIsPoweredByDCIN()) {
|
||||
|
||||
@@ -4,15 +4,13 @@
|
||||
TickType_t lastHallEffectSleepStart = 0;
|
||||
extern TickType_t lastMovementTime;
|
||||
|
||||
bool shouldBeSleeping(bool inAutoStart) {
|
||||
bool shouldBeSleeping() {
|
||||
#ifndef NO_SLEEP_MODE
|
||||
// Return true if the iron should be in sleep mode
|
||||
if (getSettingValue(SettingsOptions::Sensitivity) && getSettingValue(SettingsOptions::SleepTime)) {
|
||||
if (inAutoStart) {
|
||||
// In auto start we are asleep until movement
|
||||
if (lastMovementTime == 0 && lastButtonTime == 0) {
|
||||
return true;
|
||||
}
|
||||
// In auto start we are asleep until movement
|
||||
if (lastMovementTime == 0 && lastButtonTime == 0) {
|
||||
return true;
|
||||
}
|
||||
if (lastMovementTime > 0 || lastButtonTime > 0) {
|
||||
if (((xTaskGetTickCount() - lastMovementTime) > getSleepTimeout()) && ((xTaskGetTickCount() - lastButtonTime) > getSleepTimeout())) {
|
||||
|
||||
@@ -10,20 +10,21 @@
|
||||
#include "Settings.h"
|
||||
#include "TipThermoModel.h"
|
||||
#include "cmsis_os.h"
|
||||
#include "configuration.h"
|
||||
#include "history.hpp"
|
||||
#include "main.hpp"
|
||||
#include "power.hpp"
|
||||
#include "task.h"
|
||||
|
||||
static TickType_t powerPulseWaitUnit = 25 * TICKS_100MS; // 2.5 s
|
||||
static TickType_t powerPulseDurationUnit = (5 * TICKS_100MS) / 2; // 250 ms
|
||||
TaskHandle_t pidTaskNotification = NULL;
|
||||
volatile uint32_t currentTempTargetDegC = 0; // Current temperature target in C
|
||||
int32_t powerSupplyWattageLimit = 0;
|
||||
bool heaterThermalRunaway = false;
|
||||
static TickType_t powerPulseWaitUnit = 25 * TICKS_100MS; // 2.5 s
|
||||
static TickType_t powerPulseDurationUnit = (5 * TICKS_100MS) / 2; // 250 ms
|
||||
TaskHandle_t pidTaskNotification = NULL;
|
||||
volatile TemperatureType_t currentTempTargetDegC = 0; // Current temperature target in C
|
||||
int32_t powerSupplyWattageLimit = 0;
|
||||
bool heaterThermalRunaway = false;
|
||||
|
||||
static int32_t getPIDResultX10Watts(int32_t tError);
|
||||
static void detectThermalRunaway(const int16_t currentTipTempInC, const int tError);
|
||||
static int32_t getPIDResultX10Watts(TemperatureType_t set_point, TemperatureType_t current_value);
|
||||
static void detectThermalRunaway(const TemperatureType_t currentTipTempInC, const TemperatureType_t tError);
|
||||
static void setOutputx10WattsViaFilters(int32_t x10Watts);
|
||||
static int32_t getX10WattageLimits();
|
||||
|
||||
@@ -37,8 +38,8 @@ void startPIDTask(void const *argument __unused) {
|
||||
|
||||
currentTempTargetDegC = 0; // Force start with no output (off). If in sleep / soldering this will
|
||||
// be over-ridden rapidly
|
||||
pidTaskNotification = xTaskGetCurrentTaskHandle();
|
||||
uint32_t PIDTempTarget = 0;
|
||||
pidTaskNotification = xTaskGetCurrentTaskHandle();
|
||||
TemperatureType_t PIDTempTarget = 0;
|
||||
// Pre-seed the adc filters
|
||||
for (int i = 0; i < 32; i++) {
|
||||
ulTaskNotifyTake(pdTRUE, 5);
|
||||
@@ -58,22 +59,22 @@ void startPIDTask(void const *argument __unused) {
|
||||
// This is a call to block this thread until the ADC does its samples
|
||||
if (ulTaskNotifyTake(pdTRUE, TICKS_SECOND * 2)) {
|
||||
// Do the reading here to keep the temp calculations churning along
|
||||
uint32_t currentTipTempInC = TipThermoModel::getTipInC(true);
|
||||
PIDTempTarget = currentTempTargetDegC;
|
||||
TemperatureType_t currentTipTempInC = TipThermoModel::getTipInC(true);
|
||||
|
||||
PIDTempTarget = currentTempTargetDegC;
|
||||
if (PIDTempTarget > 0) {
|
||||
// Cap the max set point to 450C
|
||||
if (PIDTempTarget > (450)) {
|
||||
if (PIDTempTarget > 450) {
|
||||
// Maximum allowed output
|
||||
PIDTempTarget = (450);
|
||||
PIDTempTarget = 450;
|
||||
}
|
||||
// Safety check that not aiming higher than current tip can measure
|
||||
if (PIDTempTarget > TipThermoModel::getTipMaxInC()) {
|
||||
PIDTempTarget = TipThermoModel::getTipMaxInC();
|
||||
}
|
||||
int32_t tError = PIDTempTarget - currentTipTempInC;
|
||||
|
||||
detectThermalRunaway(currentTipTempInC, tError);
|
||||
x10WattsOut = getPIDResultX10Watts(tError);
|
||||
detectThermalRunaway(currentTipTempInC, PIDTempTarget - currentTipTempInC);
|
||||
x10WattsOut = getPIDResultX10Watts(PIDTempTarget, currentTipTempInC);
|
||||
} else {
|
||||
detectThermalRunaway(currentTipTempInC, 0);
|
||||
}
|
||||
@@ -88,7 +89,54 @@ void startPIDTask(void const *argument __unused) {
|
||||
}
|
||||
}
|
||||
|
||||
template <class T = int32_t> struct Integrator {
|
||||
#ifdef TIP_CONTROL_PID
|
||||
template <class T, T Kp, T Ki, T Kd, T integral_limit_scale> struct PID {
|
||||
T previous_error_term;
|
||||
T integration_running_sum;
|
||||
|
||||
T update(const T set_point, const T new_reading, const TickType_t interval_ms, const T max_output) {
|
||||
const T target_delta = set_point - new_reading;
|
||||
|
||||
// Proportional term
|
||||
const T kp_result = Kp * target_delta;
|
||||
|
||||
// Integral term as we use mixed sampling rates, we cant assume a constant sample interval
|
||||
// Thus we multiply this out by the interval time to ~= dv/dt
|
||||
// Then the shift by 1000 is ms -> Seconds
|
||||
|
||||
integration_running_sum += (target_delta * interval_ms * Ki) / 1000;
|
||||
|
||||
// We constrain integration_running_sum to limit windup
|
||||
// This is not overly required for most use cases but can prevent large overshoot in constrained implementations
|
||||
if (integration_running_sum > integral_limit_scale * max_output) {
|
||||
integration_running_sum = integral_limit_scale * max_output;
|
||||
} else if (integration_running_sum < -integral_limit_scale * max_output) {
|
||||
integration_running_sum = -integral_limit_scale * max_output;
|
||||
}
|
||||
// Calculate the integral term, we use a shift 100 to get precision in integral as we often need small amounts
|
||||
T ki_result = integration_running_sum / 100;
|
||||
|
||||
// Derivative term
|
||||
T derivative = (target_delta - previous_error_term);
|
||||
T kd_result = ((Kd * derivative) / (T)(interval_ms));
|
||||
|
||||
// Summation of the outputs
|
||||
T output = kp_result + ki_result + kd_result;
|
||||
|
||||
// Restrict to max / 0
|
||||
if (output > max_output)
|
||||
output = max_output;
|
||||
else if (output < 0)
|
||||
output = 0;
|
||||
|
||||
// Save target_delta to previous target_delta
|
||||
previous_error_term = target_delta;
|
||||
|
||||
return output;
|
||||
}
|
||||
};
|
||||
#else
|
||||
template <class T = TemperatureType_t> struct Integrator {
|
||||
T sum;
|
||||
|
||||
T update(const T val, const int32_t inertia, const int32_t gain, const int32_t rate, const int32_t limit) {
|
||||
@@ -99,11 +147,12 @@ template <class T = int32_t> struct Integrator {
|
||||
// Add the new value x integration interval ( 1 / rate)
|
||||
sum += (gain * val) / rate;
|
||||
|
||||
// limit the output
|
||||
if (sum > limit)
|
||||
// constrain the output between +- our max power output, this limits windup when doing the inital heatup or when solding something large
|
||||
if (sum > limit) {
|
||||
sum = limit;
|
||||
else if (sum < -limit)
|
||||
} else if (sum < -limit) {
|
||||
sum = -limit;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
@@ -112,15 +161,23 @@ template <class T = int32_t> struct Integrator {
|
||||
|
||||
T get(bool positiveOnly = true) const { return (positiveOnly) ? ((sum > 0) ? sum : 0) : sum; }
|
||||
};
|
||||
int32_t getPIDResultX10Watts(int32_t setpointDelta) {
|
||||
static TickType_t lastCall = 0;
|
||||
static Integrator<int32_t> powerStore = {0};
|
||||
#endif
|
||||
int32_t getPIDResultX10Watts(TemperatureType_t set_point, TemperatureType_t current_reading) {
|
||||
static TickType_t lastCall = 0;
|
||||
|
||||
const TickType_t rate = TICKS_SECOND / (xTaskGetTickCount() - lastCall);
|
||||
lastCall = xTaskGetTickCount();
|
||||
#ifdef TIP_CONTROL_PID
|
||||
static PID<TemperatureType_t, TIP_PID_KP, TIP_PID_KI, TIP_PID_KD, 5> pid = {0, 0};
|
||||
|
||||
const TickType_t interval = (xTaskGetTickCount() - lastCall);
|
||||
|
||||
#else
|
||||
static Integrator<TemperatureType_t> powerStore = {0};
|
||||
const TickType_t rate = TICKS_SECOND / (xTaskGetTickCount() - lastCall);
|
||||
#endif
|
||||
lastCall = xTaskGetTickCount();
|
||||
// Sandman note:
|
||||
// PID Challenge - we have a small thermal mass that we to want heat up as fast as possible but we don't
|
||||
// want to overshot excessively (if at all) the setpoint temperature. In the same time we have 'imprecise'
|
||||
// want to overshot excessively (if at all) the set point temperature. In the same time we have 'imprecise'
|
||||
// instant temperature measurements. The nature of temperature reading imprecision is not necessarily
|
||||
// related to the sensor (thermocouple) or DAQ system, that otherwise are fairly decent. The real issue is
|
||||
// the thermal inertia. We basically read the temperature in the window between two heating sessions when
|
||||
@@ -130,7 +187,7 @@ int32_t getPIDResultX10Watts(int32_t setpointDelta) {
|
||||
// negative side effects. As a result, we can only rely on the I term but with a twist. Instead of a simple
|
||||
// integrator we are going to use a self decaying integrator that acts more like a dual I term / P term
|
||||
// rather than a plain I term. Depending on the circumstances, like when the delta temperature is large,
|
||||
// it acts more like a P term whereas on closing to setpoint it acts increasingly closer to a plain I term.
|
||||
// it acts more like a P term whereas on closing to set point it acts increasingly closer to a plain I term.
|
||||
// So in a sense, we have a bit of both.
|
||||
// So there we go...
|
||||
|
||||
@@ -138,20 +195,22 @@ int32_t getPIDResultX10Watts(int32_t setpointDelta) {
|
||||
// delta temperature is in °C. The result is the power in X10 W needed to raise (or decrease!) the
|
||||
// tip temperature with (Delta Temperature ) °C in 1 second.
|
||||
// Note on powerStore. On update, if the value is provided in X10 (W) units then inertia shall be provided
|
||||
// in X10 (J / °C) units as well. Also, powerStore is updated with a gain of 2. Where this comes from: The actual
|
||||
// power CMOS is controlled by TIM3->CTR1 (that is software modulated - on/off - by TIM2-CTR4 interrupts). However,
|
||||
// TIM3->CTR1 is configured with a duty cycle of 50% so, in real, we get only 50% of the presumed power output
|
||||
// so we basically double the need (gain = 2) to get what we want.
|
||||
return powerStore.update(getTipThermalMass() * setpointDelta, // the required power
|
||||
getTipInertia(), // Inertia, smaller numbers increase dominance of the previous value
|
||||
2, // gain
|
||||
rate, // PID cycle frequency
|
||||
// in X10 (J / °C) units as well.
|
||||
|
||||
#ifdef TIP_CONTROL_PID
|
||||
return pid.update(set_point, current_reading, interval, getX10WattageLimits());
|
||||
#else
|
||||
return powerStore.update(((TemperatureType_t)getTipThermalMass()) * (set_point - current_reading), // the required power
|
||||
getTipInertia(), // Inertia, smaller numbers increase dominance of the previous value
|
||||
2, // gain
|
||||
rate, // PID cycle frequency
|
||||
getX10WattageLimits());
|
||||
#endif
|
||||
}
|
||||
|
||||
void detectThermalRunaway(const int16_t currentTipTempInC, const int tError) {
|
||||
static uint16_t tipTempCRunawayTemp = 0;
|
||||
static TickType_t runawaylastChangeTime = 0;
|
||||
void detectThermalRunaway(const TemperatureType_t currentTipTempInC, const TemperatureType_t tError) {
|
||||
static TemperatureType_t tipTempCRunawayTemp = 0;
|
||||
static TickType_t runawaylastChangeTime = 0;
|
||||
|
||||
// Check for thermal runaway, where it has been x seconds with negligible (y) temp rise
|
||||
// While trying to actively heat
|
||||
@@ -160,7 +219,7 @@ void detectThermalRunaway(const int16_t currentTipTempInC, const int tError) {
|
||||
if ((tError > THERMAL_RUNAWAY_TEMP_C)) {
|
||||
|
||||
// If we have heated up by more than 20C since last sample point, snapshot time and tip temp
|
||||
int16_t delta = (int16_t)currentTipTempInC - (int16_t)tipTempCRunawayTemp;
|
||||
TemperatureType_t delta = currentTipTempInC - tipTempCRunawayTemp;
|
||||
if (delta > THERMAL_RUNAWAY_TEMP_C) {
|
||||
// We have heated up more than the threshold, reset the timer
|
||||
tipTempCRunawayTemp = currentTipTempInC;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
TRANSLATION_DIR="../Translations"
|
||||
#TRANSLATION_SCRIPT="make_translation.py"
|
||||
@@ -91,14 +91,10 @@ while getopts "h:l:m:" option; do
|
||||
usage
|
||||
;;
|
||||
l)
|
||||
set -f
|
||||
IFS=' '
|
||||
largs=($OPTARG)
|
||||
IFS=' ' read -r -a largs <<< "${OPTARG}"
|
||||
;;
|
||||
m)
|
||||
set -f
|
||||
IFS=' '
|
||||
margs=($OPTARG)
|
||||
IFS=' ' read -r -a margs <<< "${OPTARG}"
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
@@ -124,7 +120,7 @@ if ((${#largs[@]})); then
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
if [ -z "$BUILD_LANGUAGES" ]; then
|
||||
if [ -z "${BUILD_LANGUAGES[*]}" ]; then
|
||||
echo " No custom languages selected."
|
||||
echo " Building: [ALL LANGUAGES]"
|
||||
BUILD_LANGUAGES+=("${AVAILABLE_LANGUAGES[@]}")
|
||||
@@ -137,11 +133,11 @@ echo " ${AVAILABLE_MODELS[*]}"
|
||||
echo -n "Requested models : "
|
||||
if ((${#margs[@]})); then
|
||||
for i in "${margs[@]}"; do
|
||||
|
||||
|
||||
if [[ "$i" != "Pinecil" ]] && [[ "$i" != "Pinecilv2" ]]; then # Dirty. Need to adapt the Build process to use upper cases only
|
||||
i=$(echo "${i}" | tr '[:lower:]' '[:upper:]')
|
||||
fi
|
||||
|
||||
|
||||
if isInArray "$i" "${AVAILABLE_MODELS[@]}"; then
|
||||
echo -n "$i "
|
||||
BUILD_MODELS+=("$i")
|
||||
@@ -152,7 +148,7 @@ if ((${#margs[@]})); then
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if [ -z "$BUILD_MODELS" ]; then
|
||||
if [ -z "${BUILD_MODELS[*]}" ]; then
|
||||
echo " No custom models selected."
|
||||
echo " Building: [ALL MODELS]"
|
||||
BUILD_MODELS+=("${AVAILABLE_MODELS[@]}")
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user