forked from M-Labs/kirdy
Compare commits
280 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 26f12dbf77 | |||
| 388e6725ef | |||
| f4c761c5ca | |||
| e560d8f1eb | |||
| 0437c6e76e | |||
| bad21806f8 | |||
| cb2bc505c9 | |||
| 4f19d2c2be | |||
| e8d3858fc9 | |||
| 9bec56ed6c | |||
| 51b82e0447 | |||
| 31e108a4b5 | |||
| 253f4410ee | |||
| bd72c382b0 | |||
| a512614de5 | |||
| 76f7875e3a | |||
| 0d64d62fb0 | |||
| 0aeffdbf7b | |||
| 89a1270c02 | |||
| c2e78e6f17 | |||
| 86e6d3764e | |||
| 1111967a7b | |||
| 1896e2534b | |||
| 6d4b1b0574 | |||
| 0b5fda2cd9 | |||
| b763350a8b | |||
| 838592c812 | |||
| e632cbbfdd | |||
| 27bf573010 | |||
| c267c30b89 | |||
| c5826876a6 | |||
| 6782cda790 | |||
| 2fe2ef531b | |||
| f2ad06ecae | |||
| 5166bb7ba8 | |||
| 9c611fc861 | |||
| 51913f2e2f | |||
| c86d67b15c | |||
| 3d2294a90c | |||
| 3ba8b99084 | |||
| af73ac8127 | |||
| c214e4182d | |||
| fb69ae3306 | |||
| 8c8ed12522 | |||
| 572e2dbc5d | |||
| 82c46e04d0 | |||
| 28f8c3c497 | |||
| 47bf166ecb | |||
| 1dcac25574 | |||
| 3f9a4bf140 | |||
| 201148fb21 | |||
| a90031dd6c | |||
| 7b52072617 | |||
| c241d34434 | |||
| 20c3d42dd7 | |||
| aae89256c3 | |||
| 3344e7ab19 | |||
| a76b8de994 | |||
| 3410a271fd | |||
| 8f38acd0f2 | |||
| b95b9dcefa | |||
| 5e6a4c0646 | |||
| ec5bf1d6b6 | |||
| 3737c2ed59 | |||
| 4cd328d98c | |||
| af95de0f16 | |||
| db2f76771a | |||
| 6f87cba9a6 | |||
| 80d94270a2 | |||
| 456691f79f | |||
| 0f3db7fec5 | |||
| 9002ca6992 | |||
| 92f6b83b16 | |||
| da50f372d9 | |||
| 57bfd6d83c | |||
| dacf9f0fa5 | |||
| bfd8c0e43a | |||
| dc97f42bd0 | |||
| 3813b79623 | |||
| 83a764889c | |||
| c09da0db98 | |||
| d5a620c76b | |||
| d1660c6090 | |||
| f35546b070 | |||
| 0dceb8c3c6 | |||
| 266110ba14 | |||
| e8aaf5f66b | |||
| 70fed23c51 | |||
| b8241d1f27 | |||
| ded7dd7694 | |||
| 7fa4330797 | |||
| 7be35fe7f0 | |||
| c5efc6ca57 | |||
| b330f45260 | |||
| 554f292cab | |||
| f303ab639a | |||
| ba30575406 | |||
| bfdb1f5066 | |||
| 5b35f32a42 | |||
| 2df22d5dcb | |||
| b73eacd234 | |||
| 4a06a7579f | |||
| 9524601cb6 | |||
| 4116962175 | |||
| 0e087c6992 | |||
| 6b250aa1fd | |||
| de80aedafc | |||
| 31a97bdeb4 | |||
| 784b8a357b | |||
| ceb003e07e | |||
| 10873f4791 | |||
| e160316bfc | |||
| 0a992c1dc8 | |||
| ae74455f94 | |||
| 6bccbceb81 | |||
| eaebdb390d | |||
| 489333c43d | |||
| 4288d465c9 | |||
| 09863353cd | |||
| 6d107d55cf | |||
| d435dc06d8 | |||
| 898358f4e6 | |||
| a13c6fa86c | |||
| b1a1173075 | |||
| af68b0e90a | |||
| f8abfd4300 | |||
| 7d41edef20 | |||
| 607da8a822 | |||
| 7f06fc06fd | |||
| 67f9e65df8 | |||
| 7d2e14ef2f | |||
| e525a3f354 | |||
| 8431e9f43d | |||
| e9d5f4598a | |||
| 1867935047 | |||
| 99cf17f7e4 | |||
| 048245f674 | |||
| 0a01d299bc | |||
| dbbd438e92 | |||
| 3ad7c417f6 | |||
| c06491a8b2 | |||
| 0380c8d30b | |||
| ed5cda6364 | |||
| 61624b0bd6 | |||
| 1480305c16 | |||
| 74c465d16f | |||
| 574abc2c2f | |||
| a9dbff8250 | |||
| 8cd3f70721 | |||
| b7231f48ff | |||
| 7f6a385e1d | |||
| eff8adc184 | |||
| a579e5c5d5 | |||
| 65b757ac3c | |||
| 911d9a7bc9 | |||
| 111d9a4226 | |||
| a3885c365e | |||
| a58b0954ec | |||
| 92c6cf12d4 | |||
| ef2410f441 | |||
| adfa4f5fa3 | |||
| df939eb9a3 | |||
| 3aca712e1d | |||
| 4526536a48 | |||
| f488786e1c | |||
| 3528d8a68f | |||
| 46393bacdb | |||
| 6fc800e562 | |||
| 76477065be | |||
| b1fa0e51c8 | |||
| 9f82fa58f4 | |||
| 19341672a9 | |||
| 86a9fb039e | |||
| a2bb390ae2 | |||
| 18dd0a7963 | |||
| d1cc677668 | |||
| c09ccc29cd | |||
| c4135f6ac3 | |||
| 6ee45b4814 | |||
| a8787430b1 | |||
| ed785b7c85 | |||
| 30ab228b4b | |||
| 88cca12a60 | |||
| 8139ebdc1b | |||
| 5f83b73011 | |||
| 0642640da7 | |||
| 6dd1bf9301 | |||
| d2efc02b6a | |||
| 89d415194d | |||
| 09b3765877 | |||
| 7a76325288 | |||
| ffa5f4e8ff | |||
| e9a396f001 | |||
| 412f5ec58b | |||
| e29898f8f8 | |||
| 60a79d1780 | |||
| b0edd3dba2 | |||
| 4c331dd319 | |||
| 6b05b2d851 | |||
| f22ab430b8 | |||
| 4cd650367d | |||
| de262b849d | |||
| 4132bfacd3 | |||
| 6096711d2c | |||
| 3d3d6f5cb5 | |||
| 172c3e1dfc | |||
| ee0ed8ebe7 | |||
| 771f2813f7 | |||
| 4e0d14def2 | |||
| f6677d874c | |||
| d391e3a1fb | |||
| edd30e94a0 | |||
| ad731c2f15 | |||
| 9d8a553669 | |||
| e22f424531 | |||
| 6af0f992d5 | |||
| f50505feaf | |||
| 9ae867cd88 | |||
| 85b50bf824 | |||
| 07ea733b34 | |||
| 5bea3f0e5f | |||
| af283b17ac | |||
| c3022e9db1 | |||
| c02181c80c | |||
| 095fe8ea69 | |||
| a0b67cdb09 | |||
| 381f25f036 | |||
| c768bdc93a | |||
| 0d12c902fc | |||
| 3cfdee917a | |||
| 5f582be143 | |||
| 2f7ca2a706 | |||
| ff3d9b790a | |||
| bc7bf9a6e7 | |||
| ca110962f7 | |||
| d0f226ce03 | |||
| f49fd08c69 | |||
| ccaf728c75 | |||
| 3ac287ace2 | |||
| cdf900a5b6 | |||
| af8d361b95 | |||
| e355e83d28 | |||
| 285fc9b5d6 | |||
| 8c612fc0c9 | |||
| 42cd55645c | |||
| d190b8b192 | |||
| 74325a3cee | |||
| 709eae8566 | |||
| d3e3451d37 | |||
| 33ff0c3678 | |||
| 33d9cb45c4 | |||
| 8ae27725c6 | |||
| 20fc6d6fac | |||
| 654964831a | |||
| 27c7b5929e | |||
| e48f1979f0 | |||
| 59f2385ecf | |||
| d4e074cbd4 | |||
| 277796d2a4 | |||
| be8bf0a8b6 | |||
| b1123047c7 | |||
| 707fac0775 | |||
| a99dde8b38 | |||
| d1f7a20c15 | |||
| 58a8b15c40 | |||
| 590ba8171c | |||
| 0807f66b3c | |||
| 2953d4edde | |||
| f2c026ffdd | |||
| c7d36bc8d5 | |||
| 784fc03957 | |||
| 6cc2bc32c5 | |||
| 23ee568ea7 | |||
| d3f3608136 | |||
| 4cf7b7fdf9 | |||
| 0179e7641a | |||
| f6767b147b | |||
| 475fe28604 | |||
| 764a203dd8 | |||
| f2b419f8d0 |
@@ -1,12 +0,0 @@
|
||||
[target.thumbv7em-none-eabihf]
|
||||
runner = "gdb -q -x openocd.gdb"
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Tlink.x",
|
||||
]
|
||||
|
||||
[build]
|
||||
# Pick ONE of these compilation targets
|
||||
# target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+
|
||||
# target = "thumbv7m-none-eabi" # Cortex-M3
|
||||
# target = "thumbv7em-none-eabi" # Cortex-M4 and Cortex-M7 (no FPU)
|
||||
target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU)
|
||||
8
.cargo/config.toml
Normal file
8
.cargo/config.toml
Normal file
@@ -0,0 +1,8 @@
|
||||
[target.thumbv7em-none-eabihf]
|
||||
runner = "gdb -q -x openocd.gdb"
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Tlink.x",
|
||||
]
|
||||
|
||||
[build]
|
||||
target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU)
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,4 +1,4 @@
|
||||
target/
|
||||
result
|
||||
|
||||
*.pyc
|
||||
*.jdebug*
|
||||
|
||||
60
BSD.md
Normal file
60
BSD.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# Building Rust embedded firmware on BSD
|
||||
|
||||
Using the Rust stable compiler from the BSD ports is mostly a matter of removing the arbitrary limitations that have been built into the Rust toolchain.
|
||||
|
||||
Get rid of the "nightly toolchain" check in cargo-xbuild:
|
||||
```
|
||||
diff --git a/src/lib.rs b/src/lib.rs
|
||||
index 204ad8f..9c61e39 100644
|
||||
--- a/src/lib.rs
|
||||
+++ b/src/lib.rs
|
||||
@@ -157,28 +157,11 @@ pub fn build(args: Args, command_name: &str, crate_config: Option<Config>) -> Re
|
||||
})
|
||||
})?;
|
||||
|
||||
- // We can't build sysroot with stable or beta due to unstable features
|
||||
let sysroot = rustc::sysroot(verbose)?;
|
||||
- let src = match meta.channel {
|
||||
- Channel::Dev => rustc::Src::from_env().ok_or(anyhow!(
|
||||
+ let src = rustc::Src::from_env().ok_or(anyhow!(
|
||||
"The XARGO_RUST_SRC env variable must be set and point to the \
|
||||
- Rust source directory when working with the 'dev' channel",
|
||||
- ))?,
|
||||
- Channel::Nightly => {
|
||||
- if let Some(src) = rustc::Src::from_env() {
|
||||
- src
|
||||
- } else {
|
||||
- sysroot.src()?
|
||||
- }
|
||||
- }
|
||||
- Channel::Stable | Channel::Beta => {
|
||||
- bail!(
|
||||
- "The sysroot can't be built for the {:?} channel. \
|
||||
- Switch to nightly.",
|
||||
- meta.channel
|
||||
- );
|
||||
- }
|
||||
- };
|
||||
+ Rust source directory",
|
||||
+ ))?;
|
||||
|
||||
let cmode = if let Some(triple) = args.target() {
|
||||
if triple == meta.host {
|
||||
```
|
||||
|
||||
Run ``cargo install --path .`` to install the modified cargo-xbuild
|
||||
|
||||
Get a copy of the Rust sources that corresponds to the installed compiler binary, and set up the environment accordingly:
|
||||
```
|
||||
> rustc --version
|
||||
rustc 1.72.1 (d5c2e9c34 2023-09-13) (built from a source tarball)
|
||||
> git clone --depth=1 --recurse-submodules --shallow-submodules https://github.com/rust-lang/rust --branch 1.72.1
|
||||
> export XARGO_RUST_SRC=`pwd`/rust/library
|
||||
```
|
||||
|
||||
Disable other arbitrary checks in the Rust compiler:
|
||||
```
|
||||
> export RUSTC_BOOTSTRAP=1
|
||||
```
|
||||
|
||||
And you can now simply run ``cargo xbuild`` to build the firmware.
|
||||
782
Cargo.lock
generated
782
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
24
Cargo.toml
24
Cargo.toml
@@ -15,23 +15,29 @@ default-target = "thumbv7em-none-eabihf"
|
||||
|
||||
[dependencies]
|
||||
panic-halt = "0.2.0"
|
||||
cortex-m = "0.7.6"
|
||||
cortex-m-rt = { version = "0.7.1", features = ["device"] }
|
||||
cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] }
|
||||
cortex-m-rt = { version = "0.7.3", features = ["device"] }
|
||||
cortex-m-semihosting = "0.5.0"
|
||||
log = "0.4.17"
|
||||
bare-metal = "1"
|
||||
nb = "1"
|
||||
cortex-m-log = { version = "0.7.0", features = ["log-integration", "semihosting"] }
|
||||
stm32f4xx-hal = { version = "0.13.2", features = ["rt", "stm32f407", "usb_fs"] }
|
||||
stm32-eth = { version = "0.3.0", features = ["stm32f407"] }
|
||||
smoltcp = { version = "0.8.0", default-features = false, features = ["proto-ipv4", "socket-tcp", "log", "medium-ethernet"] }
|
||||
stm32f4xx-hal = { version = "0.20.0", features = ["stm32f407", "otg-fs", "usb_fs"] }
|
||||
stm32-eth = { version = "0.6.0", features = ["stm32f407", "smoltcp-phy", "smoltcp"] }
|
||||
ieee802_3_miim = "0.8.0"
|
||||
smoltcp = { version = "0.11.0", default-features = false, features = ["proto-ipv4", "socket-tcp", "medium-ethernet", "iface-neighbor-cache-count-16"] }
|
||||
uom = { version = "0.30", default-features = false, features = ["autoconvert", "si", "f32", "use_serde"] }
|
||||
num-traits = { version = "0.2.15", default-features = false, features = ["libm"] }
|
||||
usb-device = "0.2.9"
|
||||
usbd-serial = "0.1.1"
|
||||
usb-device = "0.3.2"
|
||||
usbd-serial = "0.2.1"
|
||||
fugit = "0.3.6"
|
||||
rtt-target = { version = "0.3.1", features = ["cortex-m"] }
|
||||
|
||||
|
||||
miniconf = "0.9.0"
|
||||
serde = { version = "1.0.158", features = ["derive"], default-features = false }
|
||||
sfkv = "0.1"
|
||||
bit_field = "0.10"
|
||||
crc = "3.0.1"
|
||||
byteorder = { version = "1", default-features = false }
|
||||
[features]
|
||||
semihosting = ["cortex-m-log/semihosting"]
|
||||
RTT = []
|
||||
|
||||
85
README.md
Normal file
85
README.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# Testing Firmware for the Sinara 1550 Kirdy
|
||||
|
||||
- This repo is for testing only. Not intended for production use.
|
||||
|
||||
## Building
|
||||
|
||||
### Reproducible build with Nix
|
||||
|
||||
kirdy firmware is packaged using the [Nix](https://nixos.org) Flakes system. Install Nix 2.4+ and enable flakes by adding ``experimental-features = nix-command flakes`` to ``nix.conf`` (e.g. ``~/.config/nix/nix.conf``).
|
||||
|
||||
Once you have Flakes enabled, you can use ``nix build`` to build the firmware.
|
||||
|
||||
### Development environment
|
||||
|
||||
Clone this repository and with Nix Flakes enabled, use the following commands:
|
||||
|
||||
```shell
|
||||
nix develop
|
||||
cargo build
|
||||
```
|
||||
|
||||
The resulting ELF file will be located under `target/thumbv7em-none-eabihf/release/kirdy`.
|
||||
|
||||
Alternatively, you can install the Rust toolchain without Nix using rustup; see the Rust manifest file pulled in `flake.nix` to determine which Rust version to use.
|
||||
|
||||
For building on FreeBSD or OpenBSD, see BSD.md.
|
||||
|
||||
## Debugging
|
||||
|
||||
Connect SWDIO/SWCLK/RST/GND to a programmer such as ST-Link v2.1. Run OpenOCD:
|
||||
```shell
|
||||
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg
|
||||
```
|
||||
|
||||
You may need to power up the programmer before powering the device.
|
||||
Leave OpenOCD running. Run the GNU debugger:
|
||||
```shell
|
||||
gdb target/thumbv7em-none-eabihf/release/kirdy
|
||||
|
||||
(gdb) source openocd.gdb
|
||||
```
|
||||
|
||||
## Flashing
|
||||
If the firmware to be flashed involves an update on the flash settings, it is required to erase the flash settings before flashing the new firmware to avoid unexpected hardware behavior. There are several options for flashing kirdy. DFU requires only a USB-C cable or RJ45 cable, whereas OpenOCD needs a JTAG/SWD adapter.
|
||||
|
||||
### dfu-util on Linux
|
||||
* Install the DFU USB tool (dfu-util).
|
||||
* Convert firmware from ELF to BIN: `arm-none-eabi-objcopy -O binary kirdy kirdy.bin` (you can skip this step if using the BIN from Hydra)
|
||||
* Put STM32 into DFU Mode. You can either
|
||||
* Connect to the USB Type C cable to kirdy next to the RJ45 Jack. After that, add BOOT0 jumper to kirdy near programming headers and then cycle board power to put it in DFU mode. OR
|
||||
* Plug in RJ45 cable, which connect to a network that is accessible by your computer and send the corresponding dfu json command via TCP Socket to kirdy. Please see the python test script for the command.
|
||||
* Push firmware to flash: `dfu-util -a 0 -s 0x08000000:leave -D kirdy.bin`
|
||||
* If you plugged in the BOOT0 jumper, you will need to
|
||||
1. Remove BOOT0 jumper
|
||||
2. Cycle power to leave DFU update mode
|
||||
* If you plugged in the RJ45 cable, the MCU would start its application code automatically. No power cycle is needed.
|
||||
|
||||
### st.com DfuSe tool on Windows
|
||||
On a Windows machine install [st.com](https://st.com) DfuSe USB device firmware upgrade (DFU) software. [link](https://www.st.com/en/development-tools/stsw-stm32080.html).
|
||||
- add jumper to kirdy across 2-pin jumper adjacent to JTAG connector
|
||||
- cycle board power to put it in DFU update mode
|
||||
- connect USB Type C to PC
|
||||
- use st.com software to upload firmware
|
||||
- remove jumper
|
||||
- cycle power to leave DFU update mode
|
||||
|
||||
### OpenOCD
|
||||
```shell
|
||||
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg -c "program target/thumbv7em-none-eabihf/debug/kirdy verify reset; exit"
|
||||
```
|
||||
|
||||
## Erasing Flash Settings
|
||||
The flash settings are stored in the last flash sector(ID: 11) of bank 0 of stm32f405. You can erase it with JTAG/SWD adapter or by putting the device in Dfu mode. You may find it useful if you have set network settings incorrectly.
|
||||
|
||||
With JTAG/SWD adapter connected, issue the following command:
|
||||
|
||||
```shell
|
||||
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg -c "flash init; init; halt; flash erase_sector 0 11 last; reset; exit"
|
||||
```
|
||||
|
||||
With STM32 in DFU Mode, connect the USB Type C cable and then issue the following command:
|
||||
|
||||
```
|
||||
dfu-util -a 0 -s 0x080E0000:leave -D erase_flash_settings.bin
|
||||
```
|
||||
5
build.rs
5
build.rs
@@ -1,7 +1,4 @@
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::{env, fs::File, io::Write, path::PathBuf};
|
||||
|
||||
fn main() {
|
||||
// Put the linker script somewhere the linker can find it
|
||||
|
||||
56
docs/thermostat.md
Normal file
56
docs/thermostat.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# Thermostat
|
||||
Kirdy incorporates a single channel thermostat circuitry like Sinara-hw [Thermostat](https://github.com/sinara-hw/Thermostat) with improved noise. It can deliver more than 9W of cooling/heating power with better than +-1mK temperature stability.
|
||||
|
||||
## Power Input
|
||||
If you use Kirdy with a PoE (IEEE 802.3af Class 3) PSE, Kirdy may experience power failure due to power limit. If you need more power on Thermostat, you can plug in additional Power supply on the 12V power Jack(Recommend: 12V 2A). Although the TEC Driver has a very high 165 degree thermal shutdown threshold, it is highly recommended to provide active cooling to the TEC Driving Circuitry.
|
||||
|
||||
## Control Mode
|
||||
Like Sinara-hw [Thermostat](https://github.com/sinara-hw/Thermostat), they both share the same control mode and algorithm, namely constant Current Control Mode
|
||||
|
||||
### Constant Current Control Mode
|
||||
You can drive a constant current to the load. The end user to connect an external control loop. If end user wants to use it with an external control loop, it is recommended to retrieve reports via the ActiveReportMode instead of polling status report for better consistency and higher maximum update rate.
|
||||
|
||||
### PID Control Mode
|
||||
Thermostat uses the [PID algorithm](https://hackmd.io/IACbwcOTSt6Adj3_F9bKuw) derived by Quartiq. The included Pid Autotune Algorithm can already achieve the specified +-1mK stability.
|
||||
|
||||
During autotuning, Theremstat drives a user-specified step current into the load to calculate the pid parameters. Improper usage can damage the connected device.
|
||||
|
||||
#### Important Notes
|
||||
1. Configure all the protection mechanisms correctly before running the pid autotune algorithm.
|
||||
2. Supervise the PID autotune process.
|
||||
3. PID Autotune algorithm sometimes can produce unstable PID parameters. Do evaluate the PID performance after autotune is completed
|
||||
4. For best performance, you should do the autotune with Kirdy installed in the environment that it is gonna be used.
|
||||
5. If you are using the GUI, you need to set a high enough polling rate for PID autotune to function correctly.
|
||||
|
||||
#### Usage Guide
|
||||
|
||||
You can run pid autotune via the standalone auto
|
||||
|
||||
1. Target Temperature
|
||||
- Set it to the intended operating temperature for the connected device to operate in. You can still change temperature setpoint afterwards.
|
||||
2. Test Current
|
||||
- Set it to the maximum recommended operating current specified on the TEC/Resistive load.
|
||||
3. Update Rate
|
||||
- This can be set by configuring the filter settings in the Temperature ADC. High Update Rate can yield faster loop response with temperature regulation noise as the trade-off. Higher update rate can be useful if the load is actively cooled.
|
||||
4. Temperature Swing
|
||||
- Lower value can damp the control loop response.
|
||||
5. Lookback Period
|
||||
- Larger value can damp the control loop response. Do note that the larger lookback period also increases the autotune completion time.
|
||||
|
||||
You can give your system a try with the following parameters.
|
||||
1. Target Temperature: (User-Specified)
|
||||
2. Test Current: (User-Specified)
|
||||
3. Update Rate: 16.67Hz (Sinc5Sinc1 Filter with 50Hz and 60Hz Rejection)
|
||||
4. Temperature Swing: 0 Degree
|
||||
5. Lookback Period: 5s
|
||||
|
||||
Once autotune is successful, you can improve its stability by increasing the lookback period.
|
||||
|
||||
#### Troubleshooting
|
||||
If you obtain unstable PID parameters,
|
||||
1. Check if the polling rate is close to the PID update rate. If not, increase the polling rate
|
||||
2. Increase the lookback period and try again.
|
||||
|
||||
If the autotune does not finish running or faikls, you should
|
||||
1. Check if the thermostat has a hard time heating or cooling the connected device to the targe temperature. If yes, you should consider adjust the target temperature accordingly.
|
||||
2. Check if the polling rate is close to the PID update rate. If not, increase the polling rate.
|
||||
BIN
erase_flash_settings.bin
Normal file
BIN
erase_flash_settings.bin
Normal file
Binary file not shown.
14
flake.lock
generated
14
flake.lock
generated
@@ -3,11 +3,11 @@
|
||||
"mozilla-overlay": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1664789696,
|
||||
"narHash": "sha256-UGWJHQShiwLCr4/DysMVFrYdYYHcOqAOVsWNUu+l6YU=",
|
||||
"lastModified": 1704373101,
|
||||
"narHash": "sha256-+gi59LRWRQmwROrmE1E2b3mtocwueCQqZ60CwLG+gbg=",
|
||||
"owner": "mozilla",
|
||||
"repo": "nixpkgs-mozilla",
|
||||
"rev": "80627b282705101e7b38e19ca6e8df105031b072",
|
||||
"rev": "9b11a87c0cc54e308fa83aac5b4ee1816d5418a2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -18,16 +18,16 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1666164185,
|
||||
"narHash": "sha256-5v+YB4ijeUfg5LCz9ck4gIpCPhIS+qn02OyPJO48bCE=",
|
||||
"lastModified": 1713725259,
|
||||
"narHash": "sha256-9ZR/Rbx5/Z/JZf5ehVNMoz/s5xjpP0a22tL6qNvLt5E=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "c5203abb1329f7ea084c04acda330ca75d5b9fb5",
|
||||
"rev": "a5e4bbcb4780c63c79c87d29ea409abf097de3f7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-22.05",
|
||||
"ref": "nixos-23.11",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
|
||||
46
flake.nix
46
flake.nix
@@ -1,15 +1,15 @@
|
||||
{
|
||||
description = "Firmware for kirdy";
|
||||
|
||||
inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-22.05;
|
||||
inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-23.11;
|
||||
inputs.mozilla-overlay = { url = github:mozilla/nixpkgs-mozilla; flake = false; };
|
||||
|
||||
outputs = { self, nixpkgs, mozilla-overlay }:
|
||||
let
|
||||
pkgs = import nixpkgs { system = "x86_64-linux"; overlays = [ (import mozilla-overlay) ]; };
|
||||
rustManifest = pkgs.fetchurl {
|
||||
url = "https://static.rust-lang.org/dist/2022-09-22/channel-rust-stable.toml";
|
||||
sha256 = "f257a7de2f284f025238964ca2c1865c704be4156e1909d6393d92b796005055";
|
||||
url = "https://static.rust-lang.org/dist/2024-03-21/channel-rust-nightly.toml";
|
||||
sha256 = "1c7db6ab80d20682b5cc5bda7360c63311d7188c0c082902d3790820527cd4e0";
|
||||
};
|
||||
|
||||
targets = [
|
||||
@@ -22,7 +22,7 @@
|
||||
inherit targets;
|
||||
extensions = ["rust-src"];
|
||||
};
|
||||
rust = rustChannelOfTargets "stable" null targets;
|
||||
rust = rustChannelOfTargets "nightly" null targets;
|
||||
rustPlatform = pkgs.recurseIntoAttrs (pkgs.makeRustPlatform {
|
||||
rustc = rust;
|
||||
cargo = rust;
|
||||
@@ -51,6 +51,34 @@
|
||||
'';
|
||||
|
||||
dontFixup = true;
|
||||
auditable = false;
|
||||
};
|
||||
|
||||
pglive = pkgs.python3Packages.buildPythonPackage rec {
|
||||
pname = "pglive";
|
||||
version = "0.7.2";
|
||||
format = "pyproject";
|
||||
src = pkgs.fetchPypi {
|
||||
inherit pname version;
|
||||
hash = "sha256-jqj8X6H1N5mJQ4OrY5ANqRB0YJByqg/bNneEALWmH1A=";
|
||||
};
|
||||
buildInputs = [ pkgs.python3Packages.poetry-core ];
|
||||
propagatedBuildInputs = with pkgs.python3Packages; [ pyqtgraph numpy ];
|
||||
};
|
||||
|
||||
kirdy_gui = pkgs.python3Packages.buildPythonPackage {
|
||||
pname = "kirdy_gui";
|
||||
version = "0.0.0";
|
||||
format = "pyproject";
|
||||
src = "${self}/pykirdy";
|
||||
|
||||
nativeBuildInputs = [ pkgs.qt6.wrapQtAppsHook ];
|
||||
propagatedBuildInputs = [ pkgs.qt6.qtbase ] ++ (with pkgs.python3Packages; [ pyqtgraph pyqt6 qasync pglive aenum sipyco]);
|
||||
|
||||
dontWrapQtApps = true;
|
||||
postFixup = ''
|
||||
wrapQtApp "$out/bin/tec_qt"
|
||||
'';
|
||||
};
|
||||
in {
|
||||
packages.x86_64-linux = {
|
||||
@@ -64,16 +92,14 @@
|
||||
devShell.x86_64-linux = pkgs.mkShell {
|
||||
name = "kirdy-dev-shell";
|
||||
buildInputs = with pkgs; [
|
||||
rustPlatform.rust.rustc
|
||||
rustPlatform.rust.cargo
|
||||
openocd dfu-util glibc
|
||||
rust openocd dfu-util glibc
|
||||
] ++ (with python3Packages; [
|
||||
numpy matplotlib pyqtgraph
|
||||
numpy matplotlib pyqtgraph setuptools pyqt6 qasync pglive aenum sipyco
|
||||
]);
|
||||
shellHook=
|
||||
''
|
||||
export QT_PLUGIN_PATH=${pkgs.qt5.qtbase}/${pkgs.qt5.qtbase.dev.qtPluginPrefix}
|
||||
export QML2_IMPORT_PATH=${pkgs.qt5.qtbase}/${pkgs.qt5.qtbase.dev.qtQmlPrefix}
|
||||
export QT_PLUGIN_PATH=${pkgs.qt6.qtbase}/${pkgs.qt6.qtbase.dev.qtPluginPrefix}
|
||||
export QML2_IMPORT_PATH=${pkgs.qt6.qtbase}/${pkgs.qt6.qtbase.dev.qtQmlPrefix}
|
||||
'';
|
||||
};
|
||||
defaultPackage.x86_64-linux = kirdy;
|
||||
|
||||
6
memory.x
6
memory.x
@@ -2,9 +2,8 @@
|
||||
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K
|
||||
/* reserved for config data */
|
||||
CONFIG (rx) : ORIGIN = 0x8100000, LENGTH = 16K
|
||||
/* The last flash sector is reserved for config */
|
||||
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 896K
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 112K - 4
|
||||
/* reserved for DFU trigger message */
|
||||
DFU_MSG (wrx) : ORIGIN = 0x2001BFFC, LENGTH = 4
|
||||
@@ -14,6 +13,5 @@ MEMORY
|
||||
}
|
||||
|
||||
_flash_start = ORIGIN(FLASH);
|
||||
_config_start = ORIGIN(CONFIG);
|
||||
_dfu_msg = ORIGIN(DFU_MSG);
|
||||
_stack_start = ORIGIN(CCMRAM) + LENGTH(CCMRAM);
|
||||
|
||||
137
pykirdy/asyncio_exmaple.py
Normal file
137
pykirdy/asyncio_exmaple.py
Normal file
@@ -0,0 +1,137 @@
|
||||
from pprint import pp
|
||||
from driver.kirdy import Kirdy, FilterConfig
|
||||
import signal
|
||||
import time
|
||||
import asyncio
|
||||
|
||||
async def enter_dfu_mode(kirdy: Kirdy):
|
||||
"""
|
||||
Enter Device Firmware Upgrade(Dfu) mode
|
||||
Please refer to README.md for firmware update instructions.
|
||||
"""
|
||||
await kirdy.device.dfu()
|
||||
|
||||
async def active_report(kirdy: Kirdy):
|
||||
"""
|
||||
Configure Kirdy to actively report status to connected socket
|
||||
Press Ctrl + C to exit active report mode
|
||||
"""
|
||||
async for data in kirdy.report_mode():
|
||||
pp(data)
|
||||
|
||||
async def device_cfg(kirdy: Kirdy):
|
||||
"""
|
||||
Configure Kirdy's network and board specific transconductance settings.
|
||||
These configs are saved to flash immediately after command is processed.
|
||||
"""
|
||||
# Kirdy rev0_3's gain and transconductance varies between boards to maximize the
|
||||
# PD current range resolution.
|
||||
await kirdy.device.set_pd_mon_fin_gain(1.0)
|
||||
await kirdy.device.set_pd_mon_transconductance(1/1000.0)
|
||||
|
||||
# Network Settings will be updated on next reboot.
|
||||
await kirdy.device.set_ip_settings(
|
||||
addr="192.168.1.128",
|
||||
port=1337,
|
||||
prefix_len=24,
|
||||
gateway="192.168.1.1"
|
||||
)
|
||||
# Hard reset Kirdy.
|
||||
await kirdy.device.hard_reset()
|
||||
|
||||
async def ld_thermostat_cfg(kirdy: Kirdy):
|
||||
"""
|
||||
Control and config laser diode and thermostat parameters.
|
||||
"""
|
||||
# Load the laser diode and thermostat settings from flash memory.
|
||||
await kirdy.device.restore_settings_from_flash()
|
||||
|
||||
# Power off the laser diode & thermostat and clear any asserted alarm
|
||||
await kirdy.laser.set_power_on(False)
|
||||
await kirdy.laser.clear_alarm()
|
||||
await kirdy.thermostat.set_power_on(False)
|
||||
await kirdy.thermostat.clear_alarm()
|
||||
|
||||
# Set the laser diode terminals not to be shorted
|
||||
await kirdy.laser.set_ld_terms_short(False)
|
||||
|
||||
# Do not power up the laser & thermostat during initial startup
|
||||
await kirdy.laser.set_default_pwr_on(False)
|
||||
await kirdy.thermostat.set_default_pwr_on(False)
|
||||
|
||||
await kirdy.laser.set_i(0)
|
||||
|
||||
# Configure the laser diode output power limit and photodiode parameters
|
||||
# Exceeding the power limit triggers overpower protection alarm.
|
||||
# The laser diode power will be cut off upon alarm assertion while the thermostat power remains unchanged.
|
||||
await kirdy.laser.set_ld_pwr_limit(0.0)
|
||||
await kirdy.laser.set_pd_mon_dark_current(0.0)
|
||||
await kirdy.laser.set_pd_mon_responsitivity(0.0)
|
||||
|
||||
# Configure the thermostat NTC thermistor parameters.
|
||||
await kirdy.thermostat.set_sh_r0(10.0 * 1000)
|
||||
await kirdy.thermostat.set_sh_t0(25)
|
||||
await kirdy.thermostat.set_sh_beta(3900)
|
||||
|
||||
# Configure the thermostat TEC settings.
|
||||
# The actual output current is limited by value set below.
|
||||
await kirdy.thermostat.set_tec_max_cooling_i(1.0)
|
||||
await kirdy.thermostat.set_tec_max_heating_i(1.0)
|
||||
await kirdy.thermostat.set_tec_max_v(4.0)
|
||||
|
||||
# Configure the thermostat temperature monitor limits.
|
||||
# Exceeding the temperature limits trigger over temperature protection alarm.
|
||||
# Both laser diode and thermostat power will be cut off upon alarm assertion.
|
||||
await kirdy.thermostat.set_temp_mon_upper_limit(70)
|
||||
await kirdy.thermostat.set_temp_mon_lower_limit(0)
|
||||
|
||||
# Configure the thermostat ADC Filter Setting / PID Update Rate / Report Rate.
|
||||
# The ADC sampling rate determines the report and pid update rate.
|
||||
# The chosen filter and sampling rate affects the noise of the readings.
|
||||
# For details, please refer to the AD7172 datasheet.
|
||||
await kirdy.thermostat.config_temp_adc_filter(FilterConfig.Sinc5Sinc1With50hz60HzRejection.f16sps)
|
||||
|
||||
# Configure the thermostat PID parameters.
|
||||
# You can configure the PID parameter by the included autotune script.
|
||||
# You should configure the filter sampling rate first before applying pid parameters.
|
||||
await kirdy.thermostat.set_temperature_setpoint(25)
|
||||
await kirdy.thermostat.set_pid_kp(0.15668282198105507)
|
||||
await kirdy.thermostat.set_pid_ki(0.0001281321)
|
||||
await kirdy.thermostat.set_pid_kd(13.82367)
|
||||
await kirdy.thermostat.set_pid_output_max(1.0)
|
||||
await kirdy.thermostat.set_pid_output_min(-1.0)
|
||||
|
||||
# Configure thermostat to run in PID control mode
|
||||
await kirdy.thermostat.set_pid_control_mode()
|
||||
|
||||
# When control mode is switched from PID to constant current(CC) control mode,
|
||||
# thermostat keeps its instantaneous output current unchanged.
|
||||
# Thermostat output current should only be set if it is in CC control mode
|
||||
# or the value set will be overwritten by PID output.
|
||||
await kirdy.thermostat.set_constant_current_control_mode()
|
||||
await kirdy.thermostat.set_tec_i_out(0.0)
|
||||
|
||||
# Save the current settings to flash memory
|
||||
await kirdy.device.save_current_settings_to_flash()
|
||||
|
||||
# Power on the laser diode and thermostat
|
||||
await kirdy.laser.set_power_on(True)
|
||||
await kirdy.thermostat.set_power_on(True)
|
||||
|
||||
pp(await kirdy.device.get_settings_summary())
|
||||
pp(await kirdy.device.get_status_report())
|
||||
|
||||
async def main():
|
||||
kirdy = Kirdy()
|
||||
kirdy.start_session(host='192.168.1.128', port=1337)
|
||||
await kirdy.wait_until_connected()
|
||||
|
||||
await ld_thermostat_cfg(kirdy)
|
||||
# await active_report(kirdy)
|
||||
# await device_cfg(kirdy)
|
||||
# await enter_dfu_mode(kirdy)
|
||||
|
||||
await kirdy.end_session()
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
981
pykirdy/driver/kirdy.py
Normal file
981
pykirdy/driver/kirdy.py
Normal file
@@ -0,0 +1,981 @@
|
||||
import types
|
||||
import socket
|
||||
import json
|
||||
import logging
|
||||
import time
|
||||
from threading import Thread
|
||||
from aenum import StrEnum, NoAlias
|
||||
import queue
|
||||
import asyncio
|
||||
|
||||
class _dt(StrEnum):
|
||||
ip_settings = "ip_settings"
|
||||
temp_adc_filter = "temp_adc_filter"
|
||||
f32 = "data_f32"
|
||||
bool = "data_bool"
|
||||
none = "None"
|
||||
|
||||
class State(StrEnum):
|
||||
disconnected = "disconnected"
|
||||
connected = "connected"
|
||||
|
||||
class CmdList:
|
||||
class device(StrEnum, settings=NoAlias):
|
||||
_target = "device_cmd"
|
||||
SetIPSettings = _dt.ip_settings
|
||||
SetPdFinGain = _dt.f32
|
||||
SetPdTransconductance = _dt.f32
|
||||
SetActiveReportMode = _dt.bool
|
||||
GetHwRev = _dt.none
|
||||
GetStatusReport = _dt.none
|
||||
GetSettingsSummary = _dt.none
|
||||
Dfu = _dt.none
|
||||
SaveFlashSettings = _dt.none
|
||||
LoadFlashSettings = _dt.none
|
||||
HardReset = _dt.none
|
||||
|
||||
class ld(StrEnum, settings=NoAlias):
|
||||
_target = "laser_diode_cmd"
|
||||
SetDefaultPowerOn = _dt.bool
|
||||
PowerUp = _dt.none
|
||||
PowerDown = _dt.none
|
||||
LdTermsShort = _dt.none
|
||||
LdTermsOpen = _dt.none
|
||||
SetI = _dt.f32
|
||||
SetPdResponsitivity = _dt.f32
|
||||
SetPdDarkCurrent = _dt.f32
|
||||
ApplyPdParams = _dt.none
|
||||
SetLdPwrLimit = _dt.f32
|
||||
ClearAlarm = _dt.none
|
||||
|
||||
class thermostat(StrEnum, settings=NoAlias):
|
||||
_target = "thermostat_cmd"
|
||||
SetDefaultPowerOn = _dt.bool,
|
||||
PowerUp = _dt.f32,
|
||||
PowerDown = _dt.f32,
|
||||
SetTecMaxV = _dt.f32,
|
||||
SetTecMaxIPos = _dt.f32,
|
||||
SetTecMaxINeg = _dt.f32,
|
||||
SetTecIOut = _dt.f32,
|
||||
SetTemperatureSetpoint = _dt.f32,
|
||||
SetPidEngage = _dt.none,
|
||||
SetPidDisEngage = _dt.none,
|
||||
SetPidKp = _dt.f32,
|
||||
SetPidKi = _dt.f32,
|
||||
SetPidKd = _dt.f32,
|
||||
SetPidOutMin = _dt.f32,
|
||||
SetPidOutMax = _dt.f32,
|
||||
ConfigTempAdcFilter = _dt.temp_adc_filter,
|
||||
GetPollInterval = _dt.none,
|
||||
SetTempMonUpperLimit = _dt.f32,
|
||||
SetTempMonLowerLimit = _dt.f32,
|
||||
ClearAlarm = _dt.none,
|
||||
SetShT0 = _dt.f32,
|
||||
SetShR0 = _dt.f32,
|
||||
SetShBeta = _dt.f32,
|
||||
|
||||
class FilterConfig:
|
||||
class Sinc5Sinc1With50hz60HzRejection(StrEnum):
|
||||
f27sps = "F27SPS"
|
||||
f21sps = "F21SPS"
|
||||
f20sps = "F20SPS"
|
||||
f16sps = "F16SPS"
|
||||
_odr_type = "sinc5sinc1postfilter"
|
||||
|
||||
def _filter_type(self):
|
||||
return "Sinc5Sinc1With50hz60HzRejection"
|
||||
|
||||
@classmethod
|
||||
def get_list_of_settings(cls):
|
||||
ret = []
|
||||
for e in cls:
|
||||
if e not in [cls._odr_type]:
|
||||
ret.append(e)
|
||||
return ret
|
||||
|
||||
class Sinc5Sinc1(StrEnum):
|
||||
f31250_0sps = "F31250_0SPS"
|
||||
f15625_0sps = "F15625_0SPS"
|
||||
f10417_0sps = "F10417_0SPS"
|
||||
f5208_0sps = "F5208_0SPS"
|
||||
f2597_0sps = "F2597_0SPS"
|
||||
f1007_0sps = "F1007_0SPS"
|
||||
f503_8sps = "F503_8SPS"
|
||||
f381_0sps = "F381_0SPS"
|
||||
f200_3sps = "F200_3SPS"
|
||||
f100_2sps = "F100_2SPS"
|
||||
f59_52sps = "F59_52SPS"
|
||||
f49_68sps = "F49_68SPS"
|
||||
f20_01sps = "F20_01SPS"
|
||||
f16_63sps = "F16_63SPS"
|
||||
f10_0sps = "F10_0SPS"
|
||||
f5_0sps = "F5_0SPS"
|
||||
f2_5sps = "F2_5SPS"
|
||||
f1_25sps = "F1_25SPS"
|
||||
_odr_type = "sinc5sinc1odr"
|
||||
|
||||
def _filter_type(self):
|
||||
return "Sinc5Sinc1"
|
||||
|
||||
@classmethod
|
||||
def get_list_of_settings(cls):
|
||||
ret = []
|
||||
for e in cls:
|
||||
if e not in [cls._odr_type]:
|
||||
ret.append(e)
|
||||
return ret
|
||||
|
||||
class Sinc3(StrEnum):
|
||||
f31250_0sps = "F31250_0SPS"
|
||||
f15625_0sps = "F15625_0SPS"
|
||||
f10417_0sps = "F10417_0SPS"
|
||||
f5208_0sps = "F5208_0SPS"
|
||||
f2597_0sps = "F2597_0SPS"
|
||||
f1007_0sps = "F1007_0SPS"
|
||||
f503_8sps = "F503_8SPS"
|
||||
f381_0sps = "F381_0SPS"
|
||||
f200_3sps = "F200_3SPS"
|
||||
f100_2sps = "F100_2SPS"
|
||||
f59_52sps = "F59_52SPS"
|
||||
f49_68sps = "F49_68SPS"
|
||||
f20_01sps = "F20_01SPS"
|
||||
f16_63sps = "F16_63SPS"
|
||||
f10_0sps = "F10_0SPS"
|
||||
f5_0sps = "F5_0SPS"
|
||||
f2_5sps = "F2_5SPS"
|
||||
f1_25sps = "F1_25SPS"
|
||||
_odr_type = "sinc3odr"
|
||||
|
||||
def _filter_type(self):
|
||||
return "Sinc3"
|
||||
|
||||
@classmethod
|
||||
def get_list_of_settings(cls):
|
||||
ret = []
|
||||
for e in cls:
|
||||
if e not in [cls._odr_type]:
|
||||
ret.append(e)
|
||||
return ret
|
||||
|
||||
class Sinc3WithFineODR():
|
||||
upper_limit = 31250
|
||||
lower_limit = 1.907465
|
||||
_odr_type = "sinc3fineodr"
|
||||
|
||||
def __init__(self, rate):
|
||||
assert rate >= self.lower_limit and rate <= self.upper_limit
|
||||
self.rate = float(rate)
|
||||
|
||||
def _filter_type(self):
|
||||
return "Sinc3WithFineODR"
|
||||
|
||||
class InvalidDataType(Exception):
|
||||
pass
|
||||
|
||||
class InvalidCmd(Exception):
|
||||
pass
|
||||
|
||||
class Device:
|
||||
def __init__(self, send_cmd_handler, send_raw_cmd_handler):
|
||||
self._cmd = CmdList.device
|
||||
self._send_cmd = send_cmd_handler
|
||||
self._send_raw_cmd = send_raw_cmd_handler
|
||||
|
||||
async def set_ip_settings(self, addr="192.168.1.128", port=1337, prefix_len=24, gateway="192.168.1.1"):
|
||||
"""
|
||||
Upon command execution, the ip settings are saved into flash and are effective upon next reboot.
|
||||
"""
|
||||
try:
|
||||
socket.inet_aton(addr)
|
||||
socket.inet_aton(gateway)
|
||||
except OSError:
|
||||
raise InvalidDataType
|
||||
|
||||
addr = addr.split(".")
|
||||
gateway = gateway.split(".")
|
||||
|
||||
if not(isinstance(port, int) and isinstance(prefix_len, int)):
|
||||
raise InvalidDataType
|
||||
|
||||
return await self._send_raw_cmd(
|
||||
{
|
||||
"device_cmd": "SetIPSettings",
|
||||
"ip_settings": {
|
||||
"addr": [int(x) for x in addr],
|
||||
"port": port,
|
||||
"prefix_len": prefix_len,
|
||||
"gateway": [int(x) for x in gateway],
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
async def set_active_report_mode(self, on):
|
||||
"""
|
||||
Set active report to be on. If it is on, Kirdy will send status report
|
||||
to the client socket according to the temperature polling rate set.
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetActiveReportMode, on)
|
||||
|
||||
async def set_pd_mon_fin_gain(self, gain):
|
||||
"""
|
||||
Configure the photodiode monitor final analog front-end stage gain.
|
||||
- gain: unitless
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetPdFinGain, gain)
|
||||
|
||||
async def set_pd_mon_transconductance(self, transconductance):
|
||||
"""
|
||||
Configure the photodiode monitor transconductance value.
|
||||
- transconductance: 1/Ohm
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetPdTransconductance, transconductance)
|
||||
|
||||
async def get_hw_rev(self):
|
||||
"""
|
||||
Get hardware revision of the connected Kirdy
|
||||
|
||||
{
|
||||
'msg_type': 'HwRev',
|
||||
'hw_rev': {
|
||||
'major': 0,
|
||||
'minor': 3
|
||||
}
|
||||
}
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.GetHwRev, msg_type="HwRev")
|
||||
|
||||
async def get_status_report(self, sig=None):
|
||||
"""
|
||||
Get status of all peripherals in a json object.
|
||||
|
||||
{
|
||||
'ts': 227657, # Relative Timestamp (ms)
|
||||
'msg_type': 'Report' # Indicate it is a 'Report' json object
|
||||
'laser': {
|
||||
'pwr_on': False, # Laser Power is On (True/False)
|
||||
'pwr_excursion': False, # Was Laser experienced an Overpowered Condition? (True/False)
|
||||
'ld_i_set': 0.0, # Laser Diode Output Current (A)
|
||||
'pd_i': 2.0000002e-06, # Internal Photodiode Monitor current (A)
|
||||
'pd_pwr': None, # Power Readings from Internal Photodiode (W). Return None if pd_mon parameter(s) are not defined.
|
||||
'term_50ohm': 'On' # Is the Low Frequency Modulation Input's Impedance 50 Ohm? ("On"/"Off")
|
||||
},
|
||||
'thermostat': {
|
||||
'pwr_on': False, # Tec Power is On (True/False)
|
||||
'pid_engaged': False, # Is Pid_Engaged. If False, it is in Constant Current Mode (True/False)
|
||||
'temp_mon_status': { # Temperature Monitor:
|
||||
'status': 'Off', # "Off": Power is Off
|
||||
# "ConstantCurrentMode": Thermostat is regulated in CC mode
|
||||
# "PidStartUp": PID Regulation is not stable
|
||||
# "PidStable": PID Regulation is stable and the temperature is within +-1mK to the setpoint
|
||||
# "OverTempAlarm": Overtemperature Alarm is triggered
|
||||
'over_temp_alarm': False # Was Laser Diode experienced an Overtemperature condition (True/False)
|
||||
},
|
||||
'temperature': 25.03344, # Temperature Readings (Degree Celsius)
|
||||
'i_set': 0.0, # Tec Current Set by User/PID Controller(A)
|
||||
'tec_i': 0.0024998188, # Tec Current Readings (A)
|
||||
'tec_v': -0.00399971 # Tec Voltage Readings (V)
|
||||
}
|
||||
}
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.GetStatusReport, msg_type="Report", sig=sig)
|
||||
|
||||
async def get_settings_summary(self, sig=None):
|
||||
"""
|
||||
Get the current settings of laser and thermostat in a json object.
|
||||
|
||||
{
|
||||
'msg_type': 'Settings', # Indicate it is a 'Settings' json object
|
||||
'laser': {
|
||||
'default_pwr_on': False, # Power On Laser Diode at Startup
|
||||
'ld_drive_current': { # Laser Diode Output Current (A)
|
||||
'value': 0.0, # Value Set
|
||||
'max': 0.3 # Max Value Settable
|
||||
},
|
||||
'pd_mon_params': { # Photodiode Parameters
|
||||
'transconductance': 0.000115258765 # Board Specific Transconductance (1/ohm)
|
||||
'responsitivity': 0.0141, # Responsitivity (A/W)
|
||||
'i_dark': 0.0 # Max Value Settable (A)
|
||||
},
|
||||
'ld_pwr_limit': { # Laser Diode Power Limit (W)
|
||||
'value': 0.00975, # Value Set
|
||||
'max': 0.023321507 # Max Value Settable
|
||||
},
|
||||
'ld_terms_short: False, # Is Laser Diode Terminals short? (True/False)
|
||||
},
|
||||
'thermostat': {
|
||||
'default_pwr_on': True, # Power on Thermostat at Startup
|
||||
'pid_engaged': True, # True: PID Control Mode | False Constant Current Mode
|
||||
'temperature_setpoint': 25.0, # Temperature Setpoint (Degree Celsius)
|
||||
'tec_settings': {
|
||||
'i_set': { # Current TEC Current Set by PID Controller/User (A)
|
||||
'value': 0.04330516, # Value Set
|
||||
'max': 3.0 # Max Value Settable
|
||||
},
|
||||
'max_v': { # Max Voltage Across Tec Terminals (V)
|
||||
'value': 4.00000000, # Value Set
|
||||
'max': 4.3 # Max Value Settable
|
||||
},
|
||||
'max_i_pos': { # Max Cooling Current Across Tec Terminals (A)
|
||||
'value': 0.99628574, # Value Set
|
||||
'max': 3.0 # Max Value Settable
|
||||
},
|
||||
'max_i_neg': { # Max Heating Current Across Tec Terminals (A)
|
||||
'value': 0.99628574, # Value Set
|
||||
'max': 3.0 # Max Value Settable
|
||||
}
|
||||
},
|
||||
'pid_params': { # PID Controller Parameters
|
||||
'kp': 0.15668282, # Proportional Gain
|
||||
'ki': 0.0021359625, # Integral Gain
|
||||
'kd': 0.8292545, # Derivative Gain
|
||||
'output_min': -1.0, # Minimum Current Output (A)
|
||||
'output_max': 1.0 # Maximum Current Output (A)
|
||||
},
|
||||
'temp_adc_settings': { # Temperature ADC Settings (Please read AD7172-2 Documentation)
|
||||
'filter_type': 'Sinc5Sinc1With50hz60HzRejection', # Filter Types
|
||||
'sinc5sinc1odr': None, # (Unused)
|
||||
'sinc3odr': None, # (Unused)
|
||||
'sinc5sinc1postfilter': None, # (Unused)
|
||||
'sinc3fineodr': None, # (Unused)
|
||||
'rate': 16.67 # ADC Sampling Rate (Hz)
|
||||
},
|
||||
'temp_mon_settings': { # Temperature Monitor Settings
|
||||
'upper_limit': 40.0, # Temperature Upper Limit (Degree Celsius)
|
||||
'lower_limit': 10.0 # Temperature Lower Limit (Degree Celsius)
|
||||
},
|
||||
'thermistor_params': { # Thermistor Steinhart-Hart equation parameters
|
||||
't0': 25.0, # t0: Degree Celsius
|
||||
'r0': 10000.0, # r0: Ohm
|
||||
'b': 3900.0 # b: (unitless)
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.GetSettingsSummary, msg_type="Settings", sig=sig)
|
||||
|
||||
async def dfu(self):
|
||||
"""
|
||||
Hard reset and put the connected Kirdy into the Dfu mode for firmware update.
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.Dfu)
|
||||
|
||||
async def save_current_settings_to_flash(self):
|
||||
"""
|
||||
Save the current laser diode and thermostat configurations into flash.
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SaveFlashSettings)
|
||||
|
||||
async def restore_settings_from_flash(self):
|
||||
"""
|
||||
Restore the laser diode and thermostat settings from flash.
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.LoadFlashSettings)
|
||||
|
||||
async def hard_reset(self):
|
||||
"""
|
||||
Hard Reset Kirdy. The socket connection will be closed by Kirdy.
|
||||
Laser diode power and Tec power will be turned off.
|
||||
Kirdy will send out a json({'msg_type': 'HardReset'}) to all sockets before hard reset take place.
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.HardReset)
|
||||
|
||||
class Laser:
|
||||
def __init__(self, send_cmd_handler):
|
||||
self._cmd = CmdList.ld
|
||||
self._send_cmd = send_cmd_handler
|
||||
|
||||
async def set_power_on(self, on):
|
||||
"""
|
||||
Power Up or Power Down laser diode. Powering up the Laser Diode resets the pwr_excursion status
|
||||
- on (True/False)
|
||||
"""
|
||||
if on:
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.PowerUp, None)
|
||||
else:
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.PowerDown, None)
|
||||
|
||||
async def set_default_pwr_on(self, on):
|
||||
"""
|
||||
Set whether laser diode is powered up at Startup.
|
||||
- on (True/False)
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetDefaultPowerOn, on)
|
||||
|
||||
async def set_ld_terms_short(self, short):
|
||||
"""
|
||||
Open/Short laser diode terminals.
|
||||
- on (True/False)
|
||||
"""
|
||||
if short:
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.LdTermsShort, None)
|
||||
else:
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.LdTermsOpen, None)
|
||||
|
||||
async def set_i(self, i):
|
||||
"""
|
||||
Set laser diode output current: Max(0, Min(i_set, 300mA)).
|
||||
- i: A
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetI, i)
|
||||
|
||||
async def set_pd_mon_responsitivity(self, responsitivity):
|
||||
"""
|
||||
Configure the photodiode monitor responsitivity parameter.
|
||||
The value is only effective if ApplyPdParams cmd is issued.
|
||||
- responsitivity: A/W
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetPdResponsitivity, responsitivity)
|
||||
|
||||
async def set_pd_mon_dark_current(self, dark_current):
|
||||
"""
|
||||
Configure the photodiode monitor dark current parameter.
|
||||
The value is only effective if ApplyPdParams cmd is issued.
|
||||
- dark_current: A
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetPdDarkCurrent, dark_current)
|
||||
|
||||
async def apply_pd_params(self):
|
||||
"""
|
||||
Evaluate and apply photodiode monitor parameters that are set with SetPdDarkCurrent and SetPdResponsitivity cmd.
|
||||
After Kirdy receives the cmd, it will check if the current power limit is within the newly calculated
|
||||
power limit range. If it is out of range, the photodiode monitor parameters remains unchanged and Kirdy
|
||||
sends out a "InvalidSettings" message along with an error message.
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.ApplyPdParams)
|
||||
|
||||
async def set_ld_pwr_limit(self, pwr_limit):
|
||||
"""
|
||||
Set the power limit for the power excursion monitor.
|
||||
If the power limit settings is out of range, power limit remains unchanged and Kirdy
|
||||
sends out a "InvalidSettings" message along with an error message.
|
||||
|
||||
If the calculated power with the params of pd_mon > pwr_limit,
|
||||
overpower protection is triggered.
|
||||
- pwr_limit: W
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetLdPwrLimit, pwr_limit)
|
||||
|
||||
async def clear_alarm(self):
|
||||
"""
|
||||
Clear the power excursion monitor alarm.
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.ClearAlarm)
|
||||
|
||||
class Thermostat:
|
||||
def __init__(self, send_cmd_handler, send_raw_cmd_handler):
|
||||
self._cmd = CmdList.thermostat
|
||||
self._send_cmd = send_cmd_handler
|
||||
self._send_raw_cmd = send_raw_cmd_handler
|
||||
|
||||
async def set_power_on(self, on):
|
||||
"""
|
||||
Power up or power down thermostat.
|
||||
- Powering up the thermostat resets the pwr_excursion status
|
||||
"""
|
||||
if on:
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.PowerUp, None)
|
||||
else:
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.PowerDown, None)
|
||||
|
||||
async def set_default_pwr_on(self, on):
|
||||
"""
|
||||
Set whether thermostat is powered up at Startup.
|
||||
- on: (True/False)
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetDefaultPowerOn, on)
|
||||
|
||||
async def set_tec_max_v(self, max_v):
|
||||
"""
|
||||
Set Tec Maximum Voltage Across the TEC Terminals.
|
||||
- max_v: V
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetTecMaxV, max_v)
|
||||
|
||||
async def set_tec_max_cooling_i(self, max_i_pos):
|
||||
"""
|
||||
Set Tec maximum cooling current (Settable Range: 0.0 - 3.0)
|
||||
- max_i_pos: A
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetTecMaxIPos, max_i_pos)
|
||||
|
||||
async def set_tec_max_heating_i(self, max_i_neg):
|
||||
"""
|
||||
Set Tec maximum heating current (Settable Range: 0.0 - 3.0)
|
||||
- max_i_neg: A
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetTecMaxINeg, max_i_neg)
|
||||
|
||||
async def set_tec_i_out(self, i_out):
|
||||
"""
|
||||
Set Tec Output Current (Settable Range: 0.0 - 3.0)
|
||||
This cmd is only effective in constant current control mode
|
||||
or your newly set value will be overwritten by PID Controller Output
|
||||
- i_out: A
|
||||
"""
|
||||
if isinstance(i_out, float):
|
||||
return await self._send_raw_cmd({"tec_set_i": i_out})
|
||||
elif isinstance(i_out, int):
|
||||
return await self._send_raw_cmd({"tec_set_i": float(i_out)})
|
||||
else:
|
||||
raise InvalidDataType
|
||||
|
||||
async def set_constant_current_control_mode(self):
|
||||
"""
|
||||
Disable PID Controller and output current can be controlled with set_tec_i_out() cmd.
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetPidDisEngage, None)
|
||||
|
||||
async def set_temperature_setpoint(self, temperature):
|
||||
"""
|
||||
Set Temperature Setpoint for PID Controller. This parameter is not active in constant current control mode
|
||||
- temperature: Degree Celsius
|
||||
"""
|
||||
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetTemperatureSetpoint, temperature)
|
||||
|
||||
async def set_pid_control_mode(self):
|
||||
"""
|
||||
Enable PID Controller. Its PID Update Interval is controlled by the Temperature ADC polling rate.
|
||||
Please refer to config_temp_adc_filter for the possible polling rate options
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetPidEngage, None)
|
||||
|
||||
async def set_pid_kp(self, kp):
|
||||
"""
|
||||
Set Kp parameter for PID Controller
|
||||
kp: (unitless)
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetPidKp, kp)
|
||||
|
||||
async def set_pid_ki(self, ki):
|
||||
"""
|
||||
Set Ki parameter for PID Controller
|
||||
ki: (unitless)
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetPidKi, ki)
|
||||
|
||||
async def set_pid_kd(self, kd):
|
||||
"""
|
||||
Set Kd parameter for PID Controller
|
||||
kd: (unitless)
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetPidKd, kd)
|
||||
|
||||
async def set_pid_output_max(self, out_max):
|
||||
"""
|
||||
Set max output limit at the PID Output
|
||||
- out_max: A
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetPidOutMax, out_max)
|
||||
|
||||
async def set_pid_output_min(self, out_min):
|
||||
"""
|
||||
Set min output limit at the PID Output
|
||||
- out_min: A
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetPidOutMin, out_min)
|
||||
|
||||
async def set_temp_mon_upper_limit(self, upper_limit):
|
||||
"""
|
||||
Set Temperature Monitor Upper Limit Threshold. Exceeding the limit for too long
|
||||
will force the TEC Controller, PID Controller and Laser Diode Power to Shutdown
|
||||
- upper_limit: Degree Celsius
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetTempMonUpperLimit, upper_limit)
|
||||
|
||||
async def set_temp_mon_lower_limit(self, lower_limit):
|
||||
"""
|
||||
Set Temperature Monitor Lower Limit Threshold. Exceeding the limit for too long
|
||||
will force the TEC Controller, PID Controller and Laser Diode Power to Shutdown
|
||||
- lower_limit: Degree Celsius
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetTempMonLowerLimit, lower_limit)
|
||||
|
||||
async def clear_alarm(self):
|
||||
"""
|
||||
Clear the temperature monitor alarm
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.ClearAlarm)
|
||||
|
||||
async def set_sh_t0(self, t0):
|
||||
"""
|
||||
Set t0 Steinhart-Hart parameter for the laser diode NTC
|
||||
- t0: Degree Celsius
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetShT0, t0)
|
||||
|
||||
async def set_sh_r0(self, r0):
|
||||
"""
|
||||
Set r0 Steinhart-Hart parameter for the laser diode NTC
|
||||
- r0: Ohm
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetShR0, r0)
|
||||
|
||||
async def set_sh_beta(self, beta):
|
||||
"""
|
||||
Set beta Steinhart-Hart parameter for the laser diode NTC
|
||||
- beta: (unitless)
|
||||
"""
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.SetShBeta, beta)
|
||||
|
||||
async def config_temp_adc_filter(self, filter_config):
|
||||
"""
|
||||
Configure the temperature adc filter type and sampling rate.
|
||||
Please refer to AD7172 datasheet for the usage of various types of filter.
|
||||
The actual temperature polling rate is bottlenecked by the processing speed of the MCU and
|
||||
performs differently under different kinds of workload. Please verify the polling rate with
|
||||
the timestamp.
|
||||
"""
|
||||
cmd = {}
|
||||
cmd[self._cmd._target] = self._cmd.ConfigTempAdcFilter.name
|
||||
if hasattr(filter_config, 'rate'):
|
||||
cmd[self._cmd.ConfigTempAdcFilter] = {
|
||||
"filter_type": filter_config._filter_type(),
|
||||
filter_config._odr_type: filter_config.rate,
|
||||
}
|
||||
else:
|
||||
cmd[self._cmd.ConfigTempAdcFilter] = {
|
||||
"filter_type": filter_config._filter_type(),
|
||||
filter_config._odr_type: filter_config,
|
||||
}
|
||||
|
||||
return await self._send_raw_cmd(cmd)
|
||||
|
||||
async def get_poll_interval(self):
|
||||
return await self._send_cmd(self._cmd._target, self._cmd.GetPollInterval, msg_type="Interval")
|
||||
|
||||
class Kirdy:
|
||||
def __init__(self):
|
||||
self.device = Device(self._send_cmd, self._send_raw_cmd)
|
||||
self.laser = Laser(self._send_cmd)
|
||||
self.thermostat = Thermostat(self._send_cmd, self._send_raw_cmd)
|
||||
self.hw_rev = None
|
||||
|
||||
self._task_queue, self._int_msg_queue, self._report_queue = None, None, None
|
||||
self._timeout = 5.0
|
||||
self._writer, self._reader = None, None
|
||||
self._event_loop = None
|
||||
|
||||
self._msg_queue_get_report = False
|
||||
self._report_mode_on = False
|
||||
self._state = State.disconnected
|
||||
|
||||
self.read_response_task, self.handler_task = None, None
|
||||
self._lock = asyncio.Lock()
|
||||
|
||||
# PyQt Signal
|
||||
self._report_sig = None # Dict
|
||||
self._connected_sig = None # Bool
|
||||
self._err_msg_sig = None # Str
|
||||
|
||||
self.connected_event = None
|
||||
|
||||
def get_hw_rev(self):
|
||||
return self.hw_rev
|
||||
|
||||
def set_report_sig(self, sig):
|
||||
"""
|
||||
Connect a PyQt Signal to the active report output(dict). This should be configured before the session is started.
|
||||
"""
|
||||
self._report_sig = sig
|
||||
|
||||
def set_connected_sig(self, sig):
|
||||
"""
|
||||
Connect a PyQt Signal to connection status(bool)
|
||||
- True: Connection is established
|
||||
- False: Connection is dropped
|
||||
"""
|
||||
self._connected_sig = sig
|
||||
|
||||
def set_err_msg_sig(self, sig):
|
||||
"""
|
||||
Emit a error message to a PyQt Signal(str) when a cmd fails to execute
|
||||
"""
|
||||
self._err_msg_sig = sig
|
||||
|
||||
def start_session(self, host='192.168.1.128', port=1337):
|
||||
"""
|
||||
Start Kirdy Connection Session.
|
||||
In case of disconnection, all the queued tasks are cleared and the handler task retries TCP connection indefinitely.
|
||||
- host: Kirdy's IP Address
|
||||
- port: Kirdy's Port Number
|
||||
"""
|
||||
self._host, self._ctrl_port = host, port
|
||||
if self._event_loop is None:
|
||||
try:
|
||||
self._event_loop = asyncio.get_running_loop()
|
||||
except:
|
||||
self._event_loop = asyncio.new_event_loop()
|
||||
self._event_loop.run_forever()
|
||||
self.connected_event = asyncio.Event()
|
||||
self.handler_task = asyncio.create_task(self._handler())
|
||||
|
||||
async def end_session(self, block=False):
|
||||
"""
|
||||
Stop Kirdy's TCP connection and its associated thread.
|
||||
"""
|
||||
if self._event_loop is not None:
|
||||
if block:
|
||||
await self._task_queue.join()
|
||||
|
||||
if self.read_response_task is not None:
|
||||
self.read_response_task.cancel()
|
||||
await self.read_response_task
|
||||
self.read_response_task = None
|
||||
|
||||
if self.handler_task is not None:
|
||||
self.handler_task.cancel()
|
||||
await self.handler_task
|
||||
self.handler_task = None
|
||||
|
||||
self._writer = None
|
||||
|
||||
if self._connected_sig is not None:
|
||||
self._connected_sig.emit(False)
|
||||
|
||||
def connecting(self):
|
||||
"""
|
||||
Return True if client is connecting
|
||||
"""
|
||||
return self._state == State.disconnected and self.read_response_task is not None
|
||||
|
||||
def connected(self):
|
||||
"""
|
||||
Returns True if client is connected.
|
||||
"""
|
||||
return self._writer is not None
|
||||
|
||||
async def wait_until_connected(self):
|
||||
if not(self.connected()):
|
||||
await self.connected_event.wait()
|
||||
|
||||
async def report_mode(self):
|
||||
"""
|
||||
Enable and retrieve active report from Kirdy
|
||||
"""
|
||||
if self.connected():
|
||||
self._report_mode_on = True
|
||||
await self.device.set_active_report_mode(True)
|
||||
report = None
|
||||
|
||||
while self._report_mode_on:
|
||||
report = await self._report_queue.get()
|
||||
if not(isinstance(report, dict)):
|
||||
self.stop_active_report()
|
||||
else:
|
||||
yield report
|
||||
|
||||
if isinstance(report, dict):
|
||||
await self.device.set_active_report_mode(False)
|
||||
else:
|
||||
raise ConnectionError
|
||||
|
||||
def stop_report_mode(self):
|
||||
self._report_mode_on = False
|
||||
|
||||
def task_dispatcher(self, awaitable_fn):
|
||||
"""
|
||||
Enqueue a task to be handled by the handler.
|
||||
"""
|
||||
if self.connected():
|
||||
try:
|
||||
self._task_queue.put_nowait(lambda: awaitable_fn)
|
||||
return True
|
||||
except asyncio.queues.QueueFull:
|
||||
return False
|
||||
else:
|
||||
raise ConnectionError
|
||||
|
||||
async def _sock_disconnection_handling(self):
|
||||
# Reader needn't be closed
|
||||
try:
|
||||
self._writer.close()
|
||||
await self._writer.wait_closed()
|
||||
except:
|
||||
# In Hard Reset/DFU cmd, Kirdy may close its socket first
|
||||
pass
|
||||
self._reader = None
|
||||
self._writer = None
|
||||
|
||||
for i in range(self._report_queue.maxsize):
|
||||
if self._report_queue.full():
|
||||
self._report_queue.get_nowait()
|
||||
self._report_queue.put_nowait(None)
|
||||
|
||||
if self._connected_sig is not None:
|
||||
self._connected_sig.emit(False)
|
||||
|
||||
async def _handler(self):
|
||||
try:
|
||||
self._state = State.disconnected
|
||||
first_con = True
|
||||
task = None
|
||||
while True:
|
||||
if self._state == State.disconnected:
|
||||
try:
|
||||
self.hw_rev = None
|
||||
await self.__coninit(self._timeout)
|
||||
self.read_response_task = asyncio.create_task(self._read_response_handler())
|
||||
task = None
|
||||
logging.info("Connected to %s:%d", self._host, self._ctrl_port)
|
||||
|
||||
hw_rev = await self.device.get_hw_rev()
|
||||
self.hw_rev = hw_rev["hw_rev"]
|
||||
|
||||
if self._connected_sig is not None:
|
||||
self._connected_sig.emit(True)
|
||||
self.connected_event.set()
|
||||
|
||||
# State Transition
|
||||
self._state = State.connected
|
||||
except (OSError, TimeoutError):
|
||||
if first_con:
|
||||
first_con = False
|
||||
logging.warning("Cannot connect to %s:%d. Retrying in the background.", self._host, self._ctrl_port)
|
||||
await asyncio.sleep(5.0)
|
||||
|
||||
elif self._state == State.connected:
|
||||
try:
|
||||
task = await self._task_queue.get()
|
||||
if isinstance(task, Exception):
|
||||
raise task
|
||||
await task()
|
||||
self._task_queue.task_done()
|
||||
|
||||
except (TimeoutError, ConnectionResetError, ConnectionError):
|
||||
logging.warning("Connection to Kirdy is dropped.")
|
||||
first_con = True
|
||||
self.read_response_task.cancel()
|
||||
|
||||
# State Transition
|
||||
self._state = State.disconnected
|
||||
await self._sock_disconnection_handling()
|
||||
except asyncio.exceptions.CancelledError:
|
||||
pass
|
||||
except:
|
||||
logging.warning("Handler experienced an error.", exc_info=True)
|
||||
await self._sock_disconnection_handling()
|
||||
|
||||
async def _read_response_handler(self):
|
||||
try:
|
||||
while True:
|
||||
if self._report_mode_on:
|
||||
response = await asyncio.wait_for(self._read_response(), self._timeout)
|
||||
else:
|
||||
response = await self._read_response()
|
||||
|
||||
if response["msg_type"] == 'HardReset':
|
||||
logging.warn("Kirdy is being hard reset.")
|
||||
raise asyncio.exceptions.CancelledError
|
||||
if response["msg_type"] == 'Dfu':
|
||||
logging.warn("Kirdy enters Dfu Mode.")
|
||||
asyncio.create_task(self.end_session())
|
||||
if response["msg_type"] == 'ConnectionClose':
|
||||
logging.warn("Kirdy runs out of TCP sockets and closes this connected socket.")
|
||||
asyncio.create_task(self.end_session())
|
||||
if response["msg_type"] == 'Report' and not self._msg_queue_get_report:
|
||||
if self._report_sig is None:
|
||||
self._report_queue.put_nowait_overwrite(response)
|
||||
else:
|
||||
self._report_sig.emit(response)
|
||||
else:
|
||||
if self._msg_queue_get_report:
|
||||
self._msg_queue_get_report = False
|
||||
self._int_msg_queue.put_nowait_overwrite(response)
|
||||
except asyncio.exceptions.CancelledError:
|
||||
pass
|
||||
except (TimeoutError, ConnectionResetError, ConnectionError) as exec:
|
||||
self._task_queue.put_nowait_overwrite(exec)
|
||||
self._int_msg_queue.put_nowait_overwrite(exec)
|
||||
except Exception as exec:
|
||||
logging.warn("Read Response Handler experienced an error. Exiting.", exc_info=True)
|
||||
self._task_queue.put_nowait_overwrite(exec)
|
||||
self._int_msg_queue.put_nowait_overwrite(exec)
|
||||
if self._report_mode_on:
|
||||
self._report_mode_on = False
|
||||
self._report_queue.put_nowait_overwrite(TimeoutError)
|
||||
|
||||
async def _stop_handler(self):
|
||||
for task in asyncio.all_tasks():
|
||||
task.cancel()
|
||||
await asyncio.gather(*asyncio.all_tasks(), loop=self._event_loop)
|
||||
|
||||
async def __coninit(self, timeout):
|
||||
def _put_nowait_overwrite(self, item):
|
||||
if self.full():
|
||||
self.get_nowait()
|
||||
self.put_nowait(item)
|
||||
asyncio.Queue.put_nowait_overwrite = _put_nowait_overwrite
|
||||
|
||||
if self._task_queue is not None:
|
||||
while not(self._task_queue.empty()):
|
||||
task = self._task_queue.get_nowait()
|
||||
if isinstance(task, types.FunctionType):
|
||||
task().close()
|
||||
else:
|
||||
self._task_queue = asyncio.Queue(maxsize=16)
|
||||
self._int_msg_queue = asyncio.Queue(maxsize=4)
|
||||
self._report_queue = asyncio.Queue(maxsize=16)
|
||||
|
||||
self._reader, self._writer = await asyncio.wait_for(asyncio.open_connection(self._host, self._ctrl_port), timeout)
|
||||
writer_sock = self._writer.get_extra_info("socket")
|
||||
writer_sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||||
|
||||
async def _read_response(self):
|
||||
raw_response = b''
|
||||
while len(raw_response) == 0:
|
||||
# Ignore 0 size packet
|
||||
raw_response = await self._reader.readuntil()
|
||||
response = raw_response.decode('utf-8', errors='ignore').split("\n")
|
||||
return json.loads(response[0])
|
||||
|
||||
def _response_handling(self, msg, msg_type, sig=None):
|
||||
if msg["msg_type"] in ["InvalidCmd", "InvalidDatatype"]:
|
||||
raise InvalidCmd
|
||||
elif msg["msg_type"] == msg_type:
|
||||
if sig is not None:
|
||||
sig.emit(msg)
|
||||
else:
|
||||
logging.warn(f"Commands fail to execute. {msg['msg_type']}:{msg['msg']}")
|
||||
if self._err_msg_sig is not None and msg['msg'] is not None:
|
||||
self._err_msg_sig.emit(msg['msg'])
|
||||
return msg
|
||||
|
||||
async def _send_raw_cmd(self, cmd, msg_type="Acknowledge", sig=None):
|
||||
if self.connected():
|
||||
async with self._lock:
|
||||
self._writer.write(bytes(json.dumps(cmd), "UTF-8"))
|
||||
await self._writer.drain()
|
||||
msg = await asyncio.wait_for(self._int_msg_queue.get(), self._timeout)
|
||||
return self._response_handling(msg, msg_type, sig)
|
||||
else:
|
||||
raise ConnectionError
|
||||
|
||||
async def _send_cmd(self, target, cmd, data=None, msg_type="Acknowledge", sig=None):
|
||||
cmd_dict = {}
|
||||
cmd_dict[target] = cmd.name
|
||||
|
||||
if cmd == _dt.f32:
|
||||
if isinstance(data, float):
|
||||
cmd_dict[cmd] = data
|
||||
elif isinstance(data, int):
|
||||
cmd_dict[cmd] = float(data)
|
||||
elif cmd == _dt.bool:
|
||||
if isinstance(data, bool):
|
||||
cmd_dict[cmd] = data
|
||||
else:
|
||||
raise InvalidDataType
|
||||
elif cmd == "None":
|
||||
pass
|
||||
|
||||
if msg_type == 'Report':
|
||||
self._msg_queue_get_report = True
|
||||
|
||||
async with self._lock:
|
||||
self._writer.write(bytes(json.dumps(cmd_dict), "UTF-8"))
|
||||
await self._writer.drain()
|
||||
|
||||
msg = await asyncio.wait_for(self._int_msg_queue.get(), self._timeout)
|
||||
if isinstance(msg, Exception):
|
||||
raise msg
|
||||
return self._response_handling(msg, msg_type, sig)
|
||||
1192
pykirdy/kirdy_qt.py
Normal file
1192
pykirdy/kirdy_qt.py
Normal file
File diff suppressed because it is too large
Load Diff
358
pykirdy/pid_autotune.py
Normal file
358
pykirdy/pid_autotune.py
Normal file
@@ -0,0 +1,358 @@
|
||||
import math
|
||||
import logging
|
||||
from collections import deque, namedtuple
|
||||
from enum import Enum
|
||||
import socket
|
||||
import json
|
||||
import time
|
||||
import signal
|
||||
from driver.kirdy import Kirdy, FilterConfig
|
||||
import asyncio
|
||||
from sipyco.asyncio_tools import SignalHandler
|
||||
|
||||
# Based on hirshmann pid-autotune libiary
|
||||
# See https://github.com/hirschmann/pid-autotune
|
||||
# Which is in turn based on a fork of Arduino PID AutoTune Library
|
||||
# See https://github.com/t0mpr1c3/Arduino-PID-AutoTune-Library
|
||||
|
||||
|
||||
class PIDAutotuneState(Enum):
|
||||
STATE_OFF = 'off'
|
||||
STATE_RELAY_STEP_UP = 'relay step up'
|
||||
STATE_RELAY_STEP_DOWN = 'relay step down'
|
||||
STATE_SUCCEEDED = 'succeeded'
|
||||
STATE_FAILED = 'failed'
|
||||
STATE_READY = 'ready'
|
||||
|
||||
|
||||
class PIDAutotune:
|
||||
PIDParams = namedtuple('PIDParams', ['Kp', 'Ki', 'Kd'])
|
||||
|
||||
PEAK_AMPLITUDE_TOLERANCE = 0.05
|
||||
|
||||
_tuning_rules = {
|
||||
"ziegler-nichols": [0.6, 1.2, 0.075],
|
||||
"tyreus-luyben": [0.4545, 0.2066, 0.07214],
|
||||
"ciancone-marlin": [0.303, 0.1364, 0.0481],
|
||||
"pessen-integral": [0.7, 1.75, 0.105],
|
||||
"some-overshoot": [0.333, 0.667, 0.111],
|
||||
"no-overshoot": [0.2, 0.4, 0.0667]
|
||||
}
|
||||
|
||||
def __init__(self, setpoint, out_step=10, lookback=60,
|
||||
noiseband=0.5, sampletime=1.2):
|
||||
if setpoint is None:
|
||||
raise ValueError('setpoint must be specified')
|
||||
|
||||
self._inputs = deque(maxlen=round(lookback / sampletime))
|
||||
self._sampletime = sampletime
|
||||
self._setpoint = setpoint
|
||||
self._outputstep = out_step
|
||||
self._noiseband = noiseband
|
||||
self._out_min = -out_step
|
||||
self._out_max = out_step
|
||||
self._state = PIDAutotuneState.STATE_OFF
|
||||
self._peak_timestamps = deque(maxlen=5)
|
||||
self._peaks = deque(maxlen=5)
|
||||
self._output = 0
|
||||
self._last_run_timestamp = 0
|
||||
self._peak_type = 0
|
||||
self._peak_count = 0
|
||||
self._initial_output = 0
|
||||
self._induced_amplitude = 0
|
||||
self._Ku = 0
|
||||
self._Pu = 0
|
||||
|
||||
def setParam(self, target, step, noiseband, sampletime, lookback):
|
||||
self._setpoint = target
|
||||
self._outputstep = step
|
||||
self._out_max = step
|
||||
self._out_min = -step
|
||||
self._noiseband = noiseband
|
||||
self._inputs = deque(maxlen=round(lookback / sampletime))
|
||||
self._sampletime = sampletime
|
||||
|
||||
def setReady(self):
|
||||
self._state = PIDAutotuneState.STATE_READY
|
||||
self._peak_count = 0
|
||||
|
||||
def setOff(self):
|
||||
self._state = PIDAutotuneState.STATE_OFF
|
||||
|
||||
def setFailed(self):
|
||||
self._state = PIDAutotuneState.STATE_FAILED
|
||||
self._peak_count = 30
|
||||
|
||||
def state(self):
|
||||
"""Get the current state."""
|
||||
return self._state
|
||||
|
||||
def output(self):
|
||||
"""Get the last output value."""
|
||||
return self._output
|
||||
|
||||
def tuning_rules(self):
|
||||
"""Get a list of all available tuning rules."""
|
||||
return self._tuning_rules.keys()
|
||||
|
||||
def get_tec_pid (self):
|
||||
divisors = self._tuning_rules["tyreus-luyben"]
|
||||
kp = self._Ku * divisors[0]
|
||||
ki = divisors[1] * self._Ku / self._Pu / (1 / self._sampletime)
|
||||
kd = divisors[2] * self._Ku * self._Pu * (1 / self._sampletime)
|
||||
return kp, ki, kd
|
||||
|
||||
def get_pid_parameters(self, tuning_rule='ziegler-nichols'):
|
||||
"""Get PID parameters.
|
||||
|
||||
Args:
|
||||
tuning_rule (str): Sets the rule which should be used to calculate
|
||||
the parameters.
|
||||
"""
|
||||
divisors = self._tuning_rules[tuning_rule]
|
||||
kp = self._Ku * divisors[0]
|
||||
ki = divisors[1] * self._Ku / self._Pu / (1 / self._sampletime)
|
||||
kd = divisors[2] * self._Ku * self._Pu * (1 / self._sampletime)
|
||||
return PIDAutotune.PIDParams(kp, ki, kd)
|
||||
|
||||
def run(self, input_val, time_input):
|
||||
"""To autotune a system, this method must be called periodically.
|
||||
|
||||
Args:
|
||||
input_val (float): The temperature input value.
|
||||
time_input (float): Current time in seconds.
|
||||
|
||||
Returns:
|
||||
`true` if tuning is finished, otherwise `false`.
|
||||
"""
|
||||
now = time_input * 1000
|
||||
|
||||
if (self._state == PIDAutotuneState.STATE_OFF
|
||||
or self._state == PIDAutotuneState.STATE_SUCCEEDED
|
||||
or self._state == PIDAutotuneState.STATE_FAILED
|
||||
or self._state == PIDAutotuneState.STATE_READY):
|
||||
self._state = PIDAutotuneState.STATE_RELAY_STEP_UP
|
||||
|
||||
self._last_run_timestamp = now
|
||||
|
||||
# check input and change relay state if necessary
|
||||
if (self._state == PIDAutotuneState.STATE_RELAY_STEP_UP
|
||||
and input_val > self._setpoint + self._noiseband):
|
||||
self._state = PIDAutotuneState.STATE_RELAY_STEP_DOWN
|
||||
logging.debug('switched state: {0}'.format(self._state))
|
||||
logging.debug('input: {0}'.format(input_val))
|
||||
elif (self._state == PIDAutotuneState.STATE_RELAY_STEP_DOWN
|
||||
and input_val < self._setpoint - self._noiseband):
|
||||
self._state = PIDAutotuneState.STATE_RELAY_STEP_UP
|
||||
logging.debug('switched state: {0}'.format(self._state))
|
||||
logging.debug('input: {0}'.format(input_val))
|
||||
|
||||
# set output
|
||||
if (self._state == PIDAutotuneState.STATE_RELAY_STEP_UP):
|
||||
self._output = self._initial_output - self._outputstep
|
||||
elif self._state == PIDAutotuneState.STATE_RELAY_STEP_DOWN:
|
||||
self._output = self._initial_output + self._outputstep
|
||||
|
||||
# respect output limits
|
||||
self._output = min(self._output, self._out_max)
|
||||
self._output = max(self._output, self._out_min)
|
||||
|
||||
# identify peaks
|
||||
is_max = True
|
||||
is_min = True
|
||||
|
||||
for val in self._inputs:
|
||||
is_max = is_max and (input_val >= val)
|
||||
is_min = is_min and (input_val <= val)
|
||||
|
||||
self._inputs.append(input_val)
|
||||
|
||||
# we don't trust the maxes or mins until the input array is full
|
||||
if len(self._inputs) < self._inputs.maxlen:
|
||||
return False
|
||||
|
||||
# increment peak count and record peak time for maxima and minima
|
||||
inflection = False
|
||||
|
||||
# peak types:
|
||||
# -1: minimum
|
||||
# +1: maximum
|
||||
if is_max:
|
||||
if self._peak_type == -1:
|
||||
inflection = True
|
||||
self._peak_type = 1
|
||||
elif is_min:
|
||||
if self._peak_type == 1:
|
||||
inflection = True
|
||||
self._peak_type = -1
|
||||
|
||||
# update peak times and values
|
||||
if inflection:
|
||||
self._peak_count += 1
|
||||
self._peaks.append(input_val)
|
||||
self._peak_timestamps.append(now)
|
||||
logging.debug('found peak: {0}'.format(input_val))
|
||||
logging.debug('peak count: {0}'.format(self._peak_count))
|
||||
|
||||
# check for convergence of induced oscillation
|
||||
# convergence of amplitude assessed on last 4 peaks (1.5 cycles)
|
||||
self._induced_amplitude = 0
|
||||
|
||||
if inflection and (self._peak_count > 4):
|
||||
abs_max = self._peaks[-2]
|
||||
abs_min = self._peaks[-2]
|
||||
for i in range(0, len(self._peaks) - 2):
|
||||
self._induced_amplitude += abs(self._peaks[i]
|
||||
- self._peaks[i+1])
|
||||
abs_max = max(self._peaks[i], abs_max)
|
||||
abs_min = min(self._peaks[i], abs_min)
|
||||
|
||||
self._induced_amplitude /= 6.0
|
||||
|
||||
# check convergence criterion for amplitude of induced oscillation
|
||||
amplitude_dev = ((0.5 * (abs_max - abs_min)
|
||||
- self._induced_amplitude)
|
||||
/ self._induced_amplitude)
|
||||
|
||||
logging.debug('amplitude: {0}'.format(self._induced_amplitude))
|
||||
logging.debug('amplitude deviation: {0}'.format(amplitude_dev))
|
||||
|
||||
if amplitude_dev < PIDAutotune.PEAK_AMPLITUDE_TOLERANCE:
|
||||
self._state = PIDAutotuneState.STATE_SUCCEEDED
|
||||
|
||||
# if the autotune has not already converged
|
||||
# terminate after 10 cycles
|
||||
if self._peak_count >= 20:
|
||||
self._output = 0
|
||||
self._state = PIDAutotuneState.STATE_FAILED
|
||||
return True
|
||||
|
||||
if self._state == PIDAutotuneState.STATE_SUCCEEDED:
|
||||
self._output = 0
|
||||
logging.debug('peak finding successful')
|
||||
|
||||
# calculate ultimate gain
|
||||
self._Ku = 4.0 * self._outputstep / \
|
||||
(self._induced_amplitude * math.pi)
|
||||
print('Ku: {0}'.format(self._Ku))
|
||||
|
||||
# calculate ultimate period in seconds
|
||||
period1 = self._peak_timestamps[3] - self._peak_timestamps[1]
|
||||
period2 = self._peak_timestamps[4] - self._peak_timestamps[2]
|
||||
self._Pu = 0.5 * (period1 + period2) / 1000.0
|
||||
print('Pu: {0}'.format(self._Pu))
|
||||
|
||||
for rule in self._tuning_rules:
|
||||
params = self.get_pid_parameters(rule)
|
||||
print('rule: {0}'.format(rule))
|
||||
print('Kp: {0}'.format(params.Kp))
|
||||
print('Ki: {0}'.format(params.Ki))
|
||||
print('Kd: {0}'.format(params.Kd))
|
||||
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
async def main():
|
||||
"""
|
||||
PID AutoTune Tools for Kirdy
|
||||
The obtained temperature works best at the target temperature specified.
|
||||
Before running PID AutoTune, please
|
||||
1. Secure the laser diode onto the LD adapter and copper heat sink
|
||||
2. Make sure Kirdy has warmed up and reached thermal equilibrium state
|
||||
|
||||
In case of PID Autotune Failure, you can
|
||||
1. Run the PID Autotune again
|
||||
2. Or increase the lookback period
|
||||
3. Or increase the sampling rate
|
||||
"""
|
||||
|
||||
# Target temperature of the autotune routine, celsius
|
||||
target_temperature = 20
|
||||
# Value by which output will be increased/decreased from zero, amps
|
||||
output_step = 1
|
||||
# Reference period for local minima/maxima, seconds
|
||||
lookback = 2.0
|
||||
# Determines by how much the input value must
|
||||
# overshoot/undershoot the setpoint, celsius
|
||||
noiseband = 2.0
|
||||
|
||||
kirdy = Kirdy()
|
||||
kirdy.start_session(host='192.168.1.126', port=1337)
|
||||
|
||||
await kirdy.wait_until_connected()
|
||||
|
||||
while not(kirdy.connected()):
|
||||
pass
|
||||
|
||||
await kirdy.laser.set_power_on(False)
|
||||
await kirdy.laser.set_i(0)
|
||||
|
||||
await kirdy.thermostat.set_power_on(False)
|
||||
await kirdy.thermostat.set_constant_current_control_mode()
|
||||
await kirdy.thermostat.set_tec_i_out(0)
|
||||
await kirdy.thermostat.clear_alarm()
|
||||
|
||||
|
||||
signal_handler = SignalHandler()
|
||||
signal_handler.setup()
|
||||
async def sig_handling():
|
||||
await signal_handler.wait_terminate()
|
||||
tuner.setFailed()
|
||||
asyncio.create_task(sig_handling())
|
||||
|
||||
await kirdy.device.set_active_report_mode(False)
|
||||
|
||||
# Configure the Thermistor Parameters
|
||||
await kirdy.thermostat.set_sh_beta(3950)
|
||||
await kirdy.thermostat.set_sh_r0(10.0 * 1000)
|
||||
await kirdy.thermostat.set_sh_t0(25)
|
||||
|
||||
# Set a large enough temperature range so that it won't trigger overtemperature protection
|
||||
await kirdy.thermostat.set_temp_mon_upper_limit(target_temperature + 20)
|
||||
await kirdy.thermostat.set_temp_mon_lower_limit(target_temperature - 20)
|
||||
|
||||
await kirdy.thermostat.set_tec_max_cooling_i(output_step)
|
||||
await kirdy.thermostat.set_tec_max_heating_i(output_step)
|
||||
|
||||
# The Polling Rate of Temperature Adc is equal to the PID Update Interval
|
||||
await kirdy.thermostat.config_temp_adc_filter(FilterConfig.Sinc5Sinc1With50hz60HzRejection.f16sps)
|
||||
settings = await kirdy.device.get_settings_summary()
|
||||
sampling_rate = settings["thermostat"]["temp_adc_settings"]["rate"]
|
||||
|
||||
print("Settings: {0}".format(settings))
|
||||
|
||||
tuner = PIDAutotune(target_temperature, output_step,
|
||||
lookback, noiseband, 1/sampling_rate)
|
||||
|
||||
await kirdy.thermostat.set_power_on(True)
|
||||
|
||||
while True:
|
||||
status_report = await kirdy.device.get_status_report()
|
||||
|
||||
temperature = status_report["thermostat"]["temperature"]
|
||||
ts = status_report['ts']
|
||||
print("Ts: {0} Current Temperature: {1} degree".format(ts, temperature))
|
||||
|
||||
if (tuner.run(temperature, ts / 1000.0)):
|
||||
print(tuner._state)
|
||||
break
|
||||
|
||||
tuner_out = tuner.output()
|
||||
await kirdy.thermostat.set_tec_i_out(float(tuner_out))
|
||||
|
||||
await kirdy.thermostat.set_tec_i_out(0)
|
||||
await kirdy.thermostat.set_power_on(False)
|
||||
|
||||
if tuner.state() == PIDAutotuneState.STATE_SUCCEEDED:
|
||||
pid_params = tuner.get_pid_parameters(tuning_rule="tyreus-luyben")
|
||||
await kirdy.thermostat.set_pid_kp(pid_params.Kp)
|
||||
await kirdy.thermostat.set_pid_ki(pid_params.Ki)
|
||||
await kirdy.thermostat.set_pid_kd(pid_params.Kd)
|
||||
await kirdy.thermostat.set_pid_output_max(1.0)
|
||||
await kirdy.thermostat.set_pid_output_min(1.0)
|
||||
|
||||
await kirdy.end_session()
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
210
pykirdy/ui/config_adc_filter_form.ui
Normal file
210
pykirdy/ui/config_adc_filter_form.ui
Normal file
@@ -0,0 +1,210 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Cfg_Adc_Filter_Form</class>
|
||||
<widget class="QDialog" name="Cfg_Adc_Filter_Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>786</width>
|
||||
<height>303</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Config Temperature ADC Filter</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="verticalLayoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>20</y>
|
||||
<width>731</width>
|
||||
<height>251</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="3,4,4">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Value</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Readings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="filter_type_layout" stretch="3,4,4">
|
||||
<item>
|
||||
<widget class="QLabel" name="filter_type_lbl">
|
||||
<property name="text">
|
||||
<string>Filter Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="filter_type_cbox">
|
||||
<property name="editable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="filter_type_reading_lbl">
|
||||
<property name="text">
|
||||
<string>Sinc5Sinc1With50hz60HzRejection</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="filter_sampling_rate_layout" stretch="3,4,4,4">
|
||||
<item>
|
||||
<widget class="QLabel" name="filter_sampling_rate_lbl">
|
||||
<property name="text">
|
||||
<string>Filter Sampling Rate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="filter_sampling_rate_cbox"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="fine_filter_sampling_rate_spinbox">
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>16.670000000000002</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="filter_sampling_rate_reading_lbl">
|
||||
<property name="text">
|
||||
<string>F16SPS</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="recorded_sampling_rate_layout" stretch="3,4,4">
|
||||
<item>
|
||||
<widget class="QLabel" name="recorded_sampling_rate_lbl">
|
||||
<property name="text">
|
||||
<string>Recorded Sampling Rate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="recorded_sampling_rate_reading_lbl">
|
||||
<property name="text">
|
||||
<string>16.67</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="apply_btn_layout" stretch="3,2,3,2">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="apply_btn">
|
||||
<property name="text">
|
||||
<string>Apply</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="close_btn">
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>close_btn</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>Cfg_Adc_Filter_Form</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>677</x>
|
||||
<y>246</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>392</x>
|
||||
<y>151</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
488
pykirdy/ui/config_pd_mon_form.ui
Normal file
488
pykirdy/ui/config_pd_mon_form.ui
Normal file
@@ -0,0 +1,488 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Cfg_Pd_Mon_Form</class>
|
||||
<widget class="QDialog" name="Cfg_Pd_Mon_Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>500</width>
|
||||
<height>520</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>500</width>
|
||||
<height>520</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>500</width>
|
||||
<height>520</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>config_pd_mon_form</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="verticalLayoutWidget_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>481</width>
|
||||
<height>500</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="cfg_pd_mon_form_layout" stretch="0,2,2,2,2,2,1">
|
||||
<item>
|
||||
<widget class="QLabel" name="title_lbl">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>22</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Configure Photodiode Monitor</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="pwr_off_layout" stretch="5,4">
|
||||
<property name="spacing">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SizeConstraint::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="pwr_off_lbl">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>14</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string> Step 1: Turn off Laser Power</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pwr_off_btn">
|
||||
<property name="text">
|
||||
<string>Power Off</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="rst_ld_pwr_limit_layout" stretch="5,4">
|
||||
<item>
|
||||
<widget class="QLabel" name="rst_ld_pwr_limit_lbl">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>14</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string> Step 2: Reset Ld Pwr Limit to 0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="rst_ld_pwr_limit_btn">
|
||||
<property name="text">
|
||||
<string>Reset Ld Pwr Limit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="cfg_pd_params_layout">
|
||||
<item>
|
||||
<widget class="QLabel" name="cfg_pd_params_lbl">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>14</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string> Step 3: Configure Photodiode Parameters</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="5,2,2">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string> Value</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Reading</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="cfg_responsitivity_layout" stretch="5,2,2">
|
||||
<item>
|
||||
<widget class="QLabel" name="cfg_responsitivity_lbl">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Responsitivity: </string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="cfg_responsitivity_spinbox">
|
||||
<property name="suffix">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="cfg_responsitivity_reading">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0.0000</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="cfg_dark_current_layout" stretch="5,2,2">
|
||||
<item>
|
||||
<widget class="QLabel" name="cfg_dark_current_lbl">
|
||||
<property name="text">
|
||||
<string>Dark Current: </string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="cfg_dark_current_spinbox">
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="cfg_dark_current_reading">
|
||||
<property name="text">
|
||||
<string>0.0000</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="apply_pd_params_layout" stretch="5,4">
|
||||
<property name="spacing">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="apply_pd_params_btn">
|
||||
<property name="text">
|
||||
<string>Apply</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="cfg_pwr_limit_layout">
|
||||
<item>
|
||||
<widget class="QLabel" name="cfg_pd_pwr_limit_lbl">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>14</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string> Step 4: Configure Laser Diode Power Limit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="5,2,2">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string> Value</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Reading</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="pwr_limit_layout" stretch="5,2,2">
|
||||
<item>
|
||||
<widget class="QLabel" name="cfg_pwr_limit_lbl">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Power Limit:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="cfg_pwr_limit_spinbox">
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.001000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="cfg_pwr_limit_reading">
|
||||
<property name="text">
|
||||
<string>0.0000</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="settable_pwr_range_layout" stretch="5,4">
|
||||
<property name="spacing">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="settable_pwr_range_lbl">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Settable Power Range:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="settable_pwr_range_display_lbl">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>28</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>( Power Range )</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="apply_pwr_limit_layout" stretch="2,3,4">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="apply_pwr_limit_max_btn">
|
||||
<property name="text">
|
||||
<string>Apply Max</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="apply_pwr_limit_btn">
|
||||
<property name="text">
|
||||
<string>Apply</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="pwr_on_layout" stretch="5,4">
|
||||
<property name="spacing">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="pwr_on_lbl">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>14</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string> Step 5: Turn On Laser Power</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pwr_on_btn">
|
||||
<property name="text">
|
||||
<string>Clear Alarm and Power On</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="close_btn_layout" stretch="5,4">
|
||||
<property name="spacing">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="close_btn">
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>close_btn</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>Cfg_Pd_Mon_Form</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>141</x>
|
||||
<y>456</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>281</x>
|
||||
<y>355</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
376
pykirdy/ui/conn_settings_form.ui
Normal file
376
pykirdy/ui/conn_settings_form.ui
Normal file
@@ -0,0 +1,376 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Conn_Settings_Form</class>
|
||||
<widget class="QDialog" name="Conn_Settings_Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>415</width>
|
||||
<height>145</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>415</width>
|
||||
<height>145</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>415</width>
|
||||
<height>145</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Connection Settings</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="horizontalLayoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>10</y>
|
||||
<width>371</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="ip_addr_layout">
|
||||
<item>
|
||||
<widget class="QLabel" name="ip_addr_label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>IP Address:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="addr_in_0">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>192</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="dot_0_label">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
<bold>false</bold>
|
||||
<kerning>true</kerning>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="addr_in_1">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>168</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="dot_1_label">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
<bold>false</bold>
|
||||
<kerning>true</kerning>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="addr_in_2">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>1</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="dot_2_label">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
<bold>false</bold>
|
||||
<kerning>true</kerning>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="addr_in_3">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>128</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="horizontalLayoutWidget_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>50</y>
|
||||
<width>371</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="port_layout" stretch="3,0,6">
|
||||
<item>
|
||||
<widget class="QLabel" name="port_no_label">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>97</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Port:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="port_in">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>1337</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="port_layout_spacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Preferred</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="horizontalLayoutWidget_4">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>90</y>
|
||||
<width>371</width>
|
||||
<height>47</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="buttons_layout">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="connect_btn">
|
||||
<property name="text">
|
||||
<string>Connect</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cancel_btn">
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>addr_in_0</tabstop>
|
||||
<tabstop>addr_in_1</tabstop>
|
||||
<tabstop>addr_in_2</tabstop>
|
||||
<tabstop>addr_in_3</tabstop>
|
||||
<tabstop>port_in</tabstop>
|
||||
<tabstop>connect_btn</tabstop>
|
||||
<tabstop>cancel_btn</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>cancel_btn</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>Conn_Settings_Form</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>340</x>
|
||||
<y>140</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>364</x>
|
||||
<y>96</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>connect_btn</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>Conn_Settings_Form</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>258</x>
|
||||
<y>147</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>237</x>
|
||||
<y>99</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
696
pykirdy/ui/kirdy_qt.ui
Normal file
696
pykirdy/ui/kirdy_qt.ui
Normal file
@@ -0,0 +1,696 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1280</width>
|
||||
<height>720</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>1280</width>
|
||||
<height>720</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>3840</width>
|
||||
<height>2160</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Kirdy Control Panel</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset theme="application-x-executable"/>
|
||||
</property>
|
||||
<widget class="QWidget" name="main_widget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="main_layout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SizeConstraint::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="ctrl_vertical_layout" stretch="1,1,10,1,1,1,10,1">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SizeConstraint::SetMaximumSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="ld_section_label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>14</pointsize>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string> Laser Diode</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ParameterTree" name="ld_status" native="true">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>57</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ParameterTree" name="ld_tree" native="true">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="ld_btns_layout">
|
||||
<property name="spacing">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="ld_pwr_on_btn">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>POWER ON</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="ld_pwr_off_btn">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>POWER OFF</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="ld_clear_alarm_btn">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>CLEAR ALARM</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="tec_section_label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>14</pointsize>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string> Thermostat</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ParameterTree" name="tec_status" native="true">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>57</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ParameterTree" name="tec_tree" native="true">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="tec_btns_layout">
|
||||
<property name="spacing">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="tec_pwr_on_btn">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>POWER ON</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="tec_pwr_off_btn">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>POWER OFF</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="tec_clear_alarm_btn">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>CLEAR ALARM</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="graphgroup">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SizeConstraint::SetNoConstraint</enum>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="LivePlotWidget" name="tec_temp_graph" native="true">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="LivePlotWidget" name="tec_i_graph" native="true">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="LivePlotWidget" name="pd_mon_pwr_graph" native="true">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="LivePlotWidget" name="ld_i_set_graph" native="true">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="bottom_settings_group">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Shape::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Shadow::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="settings_layout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="connect_btn">
|
||||
<property name="text">
|
||||
<string>Connect</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="status_lbl">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>480</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>480</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>50</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Disconnected</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="plot_settings">
|
||||
<property name="toolTip">
|
||||
<string>Plot Settings</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>📉</string>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::ToolButtonPopupMode::InstantPopup</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="limits_warning">
|
||||
<property name="toolTipDuration">
|
||||
<number>1000000000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="background_task_lbl">
|
||||
<property name="text">
|
||||
<string>Ready.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QtWaitingSpinner" name="loading_spinner" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="polling_rate_lbl">
|
||||
<property name="text">
|
||||
<string>Polling Rate (Hz): </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="report_group" native="true">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="polling_rate_spinbox">
|
||||
<property name="maximum">
|
||||
<double>1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>20.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="polling_rate_apply_btn">
|
||||
<property name="text">
|
||||
<string>Apply</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menuBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1280</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuKirdy">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Kirdy</string>
|
||||
</property>
|
||||
<addaction name="menu_action_about_kirdy"/>
|
||||
<addaction name="menu_action_update_net_settings"/>
|
||||
<addaction name="menu_action_save"/>
|
||||
<addaction name="menu_action_load"/>
|
||||
<addaction name="menu_action_dfu_mode"/>
|
||||
<addaction name="menu_action_hard_reset"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuAbout">
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>About</string>
|
||||
</property>
|
||||
<addaction name="menu_action_about_gui"/>
|
||||
</widget>
|
||||
<addaction name="menuKirdy"/>
|
||||
<addaction name="menuAbout"/>
|
||||
</widget>
|
||||
<action name="actionReset">
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Reset the Kirdy</string>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::MenuRole::NoRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEnter_DFU_Mode">
|
||||
<property name="text">
|
||||
<string>Enter DFU Mode</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Reset kirdy and enter USB device firmware update (DFU) mode</string>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::MenuRole::NoRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionNetwork_Settings">
|
||||
<property name="text">
|
||||
<string>Network Settings</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Configure IPv4 address, netmask length, and optional default gateway</string>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::MenuRole::NoRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAbout_Kirdy">
|
||||
<property name="text">
|
||||
<string>About Kirdy</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show Kirdy hardware revision, and settings related to i</string>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::MenuRole::NoRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionLoad_all_configs">
|
||||
<property name="text">
|
||||
<string>Load all channel configs from flash</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Restore configuration for all channels from flash</string>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::MenuRole::NoRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSave_all_configs">
|
||||
<property name="text">
|
||||
<string>Save all channel configs to flash</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Save configuration for all channels to flash</string>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::MenuRole::NoRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionConnection_Settings">
|
||||
<property name="text">
|
||||
<string>Connect</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="menu_action_update_net_settings">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Update Network Settings</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="menu_action_dfu_mode">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enter DFU Mode</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="menu_action_save">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save Settings to Flash</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="menu_action_hard_reset">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Hard Reset</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="menu_action_connect">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Connect</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="menu_action_disconnect">
|
||||
<property name="text">
|
||||
<string>Disconnect</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="menu_action_about_gui">
|
||||
<property name="text">
|
||||
<string>About GUI</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action">
|
||||
<property name="text">
|
||||
<string>test</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="menu_action_about_kirdy">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>About Kirdy</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="menu_action_load">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Load Settings from Flash</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ParameterTree</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>pyqtgraph.parametertree</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>LivePlotWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>pglive.sources.live_plot_widget</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QtWaitingSpinner</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>waitingspinnerwidget</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
6
pykirdy/ui/mainwindow.qss
Normal file
6
pykirdy/ui/mainwindow.qss
Normal file
@@ -0,0 +1,6 @@
|
||||
QPushButton:disabled { color: gray }
|
||||
ParameterTree:disabled { color: gray }
|
||||
QToolButton:disabled { color: gray }
|
||||
QDoubleSpinBox:disabled { color: gray }
|
||||
QCheckBox:disabled { color: gray }
|
||||
QMenu:disabled { color: gray }
|
||||
131
pykirdy/ui/ui_config_adc_filter_form.py
Normal file
131
pykirdy/ui/ui_config_adc_filter_form.py
Normal file
@@ -0,0 +1,131 @@
|
||||
# Form implementation generated from reading ui file 'config_adc_filter_form.ui'
|
||||
#
|
||||
# Created by: PyQt6 UI code generator 6.6.0
|
||||
#
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
from PyQt6 import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
class Ui_Cfg_Adc_Filter_Form(object):
|
||||
def setupUi(self, Cfg_Adc_Filter_Form):
|
||||
Cfg_Adc_Filter_Form.setObjectName("Cfg_Adc_Filter_Form")
|
||||
Cfg_Adc_Filter_Form.resize(786, 303)
|
||||
self.verticalLayoutWidget = QtWidgets.QWidget(parent=Cfg_Adc_Filter_Form)
|
||||
self.verticalLayoutWidget.setGeometry(QtCore.QRect(20, 20, 731, 251))
|
||||
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
|
||||
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||
self.horizontalLayout.addItem(spacerItem)
|
||||
self.label_4 = QtWidgets.QLabel(parent=self.verticalLayoutWidget)
|
||||
self.label_4.setObjectName("label_4")
|
||||
self.horizontalLayout.addWidget(self.label_4)
|
||||
self.label_5 = QtWidgets.QLabel(parent=self.verticalLayoutWidget)
|
||||
self.label_5.setObjectName("label_5")
|
||||
self.horizontalLayout.addWidget(self.label_5)
|
||||
self.horizontalLayout.setStretch(0, 3)
|
||||
self.horizontalLayout.setStretch(1, 4)
|
||||
self.horizontalLayout.setStretch(2, 4)
|
||||
self.verticalLayout.addLayout(self.horizontalLayout)
|
||||
self.filter_type_layout = QtWidgets.QHBoxLayout()
|
||||
self.filter_type_layout.setObjectName("filter_type_layout")
|
||||
self.filter_type_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget)
|
||||
self.filter_type_lbl.setObjectName("filter_type_lbl")
|
||||
self.filter_type_layout.addWidget(self.filter_type_lbl)
|
||||
self.filter_type_cbox = QtWidgets.QComboBox(parent=self.verticalLayoutWidget)
|
||||
self.filter_type_cbox.setEditable(False)
|
||||
self.filter_type_cbox.setObjectName("filter_type_cbox")
|
||||
self.filter_type_layout.addWidget(self.filter_type_cbox)
|
||||
self.filter_type_reading_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget)
|
||||
self.filter_type_reading_lbl.setObjectName("filter_type_reading_lbl")
|
||||
self.filter_type_layout.addWidget(self.filter_type_reading_lbl)
|
||||
self.filter_type_layout.setStretch(0, 3)
|
||||
self.filter_type_layout.setStretch(1, 4)
|
||||
self.filter_type_layout.setStretch(2, 4)
|
||||
self.verticalLayout.addLayout(self.filter_type_layout)
|
||||
self.filter_sampling_rate_layout = QtWidgets.QHBoxLayout()
|
||||
self.filter_sampling_rate_layout.setObjectName("filter_sampling_rate_layout")
|
||||
self.filter_sampling_rate_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget)
|
||||
self.filter_sampling_rate_lbl.setObjectName("filter_sampling_rate_lbl")
|
||||
self.filter_sampling_rate_layout.addWidget(self.filter_sampling_rate_lbl)
|
||||
self.filter_sampling_rate_cbox = QtWidgets.QComboBox(parent=self.verticalLayoutWidget)
|
||||
self.filter_sampling_rate_cbox.setObjectName("filter_sampling_rate_cbox")
|
||||
self.filter_sampling_rate_layout.addWidget(self.filter_sampling_rate_cbox)
|
||||
self.fine_filter_sampling_rate_spinbox = QtWidgets.QDoubleSpinBox(parent=self.verticalLayoutWidget)
|
||||
self.fine_filter_sampling_rate_spinbox.setMaximum(1000.0)
|
||||
self.fine_filter_sampling_rate_spinbox.setProperty("value", 16.67)
|
||||
self.fine_filter_sampling_rate_spinbox.setObjectName("fine_filter_sampling_rate_spinbox")
|
||||
self.filter_sampling_rate_layout.addWidget(self.fine_filter_sampling_rate_spinbox)
|
||||
self.filter_sampling_rate_reading_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget)
|
||||
self.filter_sampling_rate_reading_lbl.setObjectName("filter_sampling_rate_reading_lbl")
|
||||
self.filter_sampling_rate_layout.addWidget(self.filter_sampling_rate_reading_lbl)
|
||||
self.filter_sampling_rate_layout.setStretch(0, 3)
|
||||
self.filter_sampling_rate_layout.setStretch(1, 4)
|
||||
self.filter_sampling_rate_layout.setStretch(2, 4)
|
||||
self.filter_sampling_rate_layout.setStretch(3, 4)
|
||||
self.verticalLayout.addLayout(self.filter_sampling_rate_layout)
|
||||
self.recorded_sampling_rate_layout = QtWidgets.QHBoxLayout()
|
||||
self.recorded_sampling_rate_layout.setObjectName("recorded_sampling_rate_layout")
|
||||
self.recorded_sampling_rate_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget)
|
||||
self.recorded_sampling_rate_lbl.setObjectName("recorded_sampling_rate_lbl")
|
||||
self.recorded_sampling_rate_layout.addWidget(self.recorded_sampling_rate_lbl)
|
||||
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||
self.recorded_sampling_rate_layout.addItem(spacerItem1)
|
||||
self.recorded_sampling_rate_reading_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget)
|
||||
self.recorded_sampling_rate_reading_lbl.setObjectName("recorded_sampling_rate_reading_lbl")
|
||||
self.recorded_sampling_rate_layout.addWidget(self.recorded_sampling_rate_reading_lbl)
|
||||
self.recorded_sampling_rate_layout.setStretch(0, 3)
|
||||
self.recorded_sampling_rate_layout.setStretch(1, 4)
|
||||
self.recorded_sampling_rate_layout.setStretch(2, 4)
|
||||
self.verticalLayout.addLayout(self.recorded_sampling_rate_layout)
|
||||
self.apply_btn_layout = QtWidgets.QHBoxLayout()
|
||||
self.apply_btn_layout.setObjectName("apply_btn_layout")
|
||||
spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||
self.apply_btn_layout.addItem(spacerItem2)
|
||||
self.apply_btn = QtWidgets.QPushButton(parent=self.verticalLayoutWidget)
|
||||
self.apply_btn.setObjectName("apply_btn")
|
||||
self.apply_btn_layout.addWidget(self.apply_btn)
|
||||
spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||
self.apply_btn_layout.addItem(spacerItem3)
|
||||
self.close_btn = QtWidgets.QPushButton(parent=self.verticalLayoutWidget)
|
||||
self.close_btn.setObjectName("close_btn")
|
||||
self.apply_btn_layout.addWidget(self.close_btn)
|
||||
self.apply_btn_layout.setStretch(0, 3)
|
||||
self.apply_btn_layout.setStretch(1, 2)
|
||||
self.apply_btn_layout.setStretch(2, 3)
|
||||
self.apply_btn_layout.setStretch(3, 2)
|
||||
self.verticalLayout.addLayout(self.apply_btn_layout)
|
||||
|
||||
self.retranslateUi(Cfg_Adc_Filter_Form)
|
||||
self.close_btn.clicked.connect(Cfg_Adc_Filter_Form.accept) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(Cfg_Adc_Filter_Form)
|
||||
|
||||
def retranslateUi(self, Cfg_Adc_Filter_Form):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
Cfg_Adc_Filter_Form.setWindowTitle(_translate("Cfg_Adc_Filter_Form", "Config Temperature ADC Filter"))
|
||||
self.label_4.setText(_translate("Cfg_Adc_Filter_Form", "Value"))
|
||||
self.label_5.setText(_translate("Cfg_Adc_Filter_Form", "Readings"))
|
||||
self.filter_type_lbl.setText(_translate("Cfg_Adc_Filter_Form", "Filter Type"))
|
||||
self.filter_type_reading_lbl.setText(_translate("Cfg_Adc_Filter_Form", "Sinc5Sinc1With50hz60HzRejection"))
|
||||
self.filter_sampling_rate_lbl.setText(_translate("Cfg_Adc_Filter_Form", "Filter Sampling Rate"))
|
||||
self.filter_sampling_rate_reading_lbl.setText(_translate("Cfg_Adc_Filter_Form", "F16SPS"))
|
||||
self.recorded_sampling_rate_lbl.setText(_translate("Cfg_Adc_Filter_Form", "Recorded Sampling Rate"))
|
||||
self.recorded_sampling_rate_reading_lbl.setText(_translate("Cfg_Adc_Filter_Form", "16.67"))
|
||||
self.apply_btn.setText(_translate("Cfg_Adc_Filter_Form", "Apply"))
|
||||
self.close_btn.setText(_translate("Cfg_Adc_Filter_Form", "Close"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
Cfg_Adc_Filter_Form = QtWidgets.QDialog()
|
||||
ui = Ui_Cfg_Adc_Filter_Form()
|
||||
ui.setupUi(Cfg_Adc_Filter_Form)
|
||||
Cfg_Adc_Filter_Form.show()
|
||||
sys.exit(app.exec())
|
||||
295
pykirdy/ui/ui_config_pd_mon_form.py
Normal file
295
pykirdy/ui/ui_config_pd_mon_form.py
Normal file
@@ -0,0 +1,295 @@
|
||||
# Form implementation generated from reading ui file 'config_pd_mon_form.ui'
|
||||
#
|
||||
# Created by: PyQt6 UI code generator 6.6.0
|
||||
#
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
from PyQt6 import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
class Ui_Cfg_Pd_Mon_Form(object):
|
||||
def setupUi(self, Cfg_Pd_Mon_Form):
|
||||
Cfg_Pd_Mon_Form.setObjectName("Cfg_Pd_Mon_Form")
|
||||
Cfg_Pd_Mon_Form.resize(500, 520)
|
||||
Cfg_Pd_Mon_Form.setMinimumSize(QtCore.QSize(500, 520))
|
||||
Cfg_Pd_Mon_Form.setMaximumSize(QtCore.QSize(500, 520))
|
||||
self.verticalLayoutWidget_2 = QtWidgets.QWidget(parent=Cfg_Pd_Mon_Form)
|
||||
self.verticalLayoutWidget_2.setGeometry(QtCore.QRect(10, 10, 481, 500))
|
||||
self.verticalLayoutWidget_2.setObjectName("verticalLayoutWidget_2")
|
||||
self.cfg_pd_mon_form_layout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget_2)
|
||||
self.cfg_pd_mon_form_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.cfg_pd_mon_form_layout.setObjectName("cfg_pd_mon_form_layout")
|
||||
self.title_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(22)
|
||||
self.title_lbl.setFont(font)
|
||||
self.title_lbl.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.title_lbl.setObjectName("title_lbl")
|
||||
self.cfg_pd_mon_form_layout.addWidget(self.title_lbl)
|
||||
self.pwr_off_layout = QtWidgets.QHBoxLayout()
|
||||
self.pwr_off_layout.setSizeConstraint(QtWidgets.QLayout.SizeConstraint.SetDefaultConstraint)
|
||||
self.pwr_off_layout.setSpacing(12)
|
||||
self.pwr_off_layout.setObjectName("pwr_off_layout")
|
||||
self.pwr_off_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(14)
|
||||
self.pwr_off_lbl.setFont(font)
|
||||
self.pwr_off_lbl.setObjectName("pwr_off_lbl")
|
||||
self.pwr_off_layout.addWidget(self.pwr_off_lbl)
|
||||
self.pwr_off_btn = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_2)
|
||||
self.pwr_off_btn.setObjectName("pwr_off_btn")
|
||||
self.pwr_off_layout.addWidget(self.pwr_off_btn)
|
||||
self.pwr_off_layout.setStretch(0, 5)
|
||||
self.pwr_off_layout.setStretch(1, 4)
|
||||
self.cfg_pd_mon_form_layout.addLayout(self.pwr_off_layout)
|
||||
self.rst_ld_pwr_limit_layout = QtWidgets.QHBoxLayout()
|
||||
self.rst_ld_pwr_limit_layout.setObjectName("rst_ld_pwr_limit_layout")
|
||||
self.rst_ld_pwr_limit_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(14)
|
||||
self.rst_ld_pwr_limit_lbl.setFont(font)
|
||||
self.rst_ld_pwr_limit_lbl.setObjectName("rst_ld_pwr_limit_lbl")
|
||||
self.rst_ld_pwr_limit_layout.addWidget(self.rst_ld_pwr_limit_lbl)
|
||||
self.rst_ld_pwr_limit_btn = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_2)
|
||||
self.rst_ld_pwr_limit_btn.setObjectName("rst_ld_pwr_limit_btn")
|
||||
self.rst_ld_pwr_limit_layout.addWidget(self.rst_ld_pwr_limit_btn)
|
||||
self.rst_ld_pwr_limit_layout.setStretch(0, 5)
|
||||
self.rst_ld_pwr_limit_layout.setStretch(1, 4)
|
||||
self.cfg_pd_mon_form_layout.addLayout(self.rst_ld_pwr_limit_layout)
|
||||
self.cfg_pd_params_layout = QtWidgets.QVBoxLayout()
|
||||
self.cfg_pd_params_layout.setObjectName("cfg_pd_params_layout")
|
||||
self.cfg_pd_params_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(14)
|
||||
self.cfg_pd_params_lbl.setFont(font)
|
||||
self.cfg_pd_params_lbl.setObjectName("cfg_pd_params_lbl")
|
||||
self.cfg_pd_params_layout.addWidget(self.cfg_pd_params_lbl)
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||
self.horizontalLayout.addItem(spacerItem)
|
||||
self.label_2 = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.horizontalLayout.addWidget(self.label_2)
|
||||
self.label = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
|
||||
self.label.setObjectName("label")
|
||||
self.horizontalLayout.addWidget(self.label)
|
||||
self.horizontalLayout.setStretch(0, 5)
|
||||
self.horizontalLayout.setStretch(1, 2)
|
||||
self.horizontalLayout.setStretch(2, 2)
|
||||
self.cfg_pd_params_layout.addLayout(self.horizontalLayout)
|
||||
self.cfg_responsitivity_layout = QtWidgets.QHBoxLayout()
|
||||
self.cfg_responsitivity_layout.setObjectName("cfg_responsitivity_layout")
|
||||
self.cfg_responsitivity_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.cfg_responsitivity_lbl.sizePolicy().hasHeightForWidth())
|
||||
self.cfg_responsitivity_lbl.setSizePolicy(sizePolicy)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(12)
|
||||
self.cfg_responsitivity_lbl.setFont(font)
|
||||
self.cfg_responsitivity_lbl.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
|
||||
self.cfg_responsitivity_lbl.setObjectName("cfg_responsitivity_lbl")
|
||||
self.cfg_responsitivity_layout.addWidget(self.cfg_responsitivity_lbl)
|
||||
self.cfg_responsitivity_spinbox = QtWidgets.QDoubleSpinBox(parent=self.verticalLayoutWidget_2)
|
||||
self.cfg_responsitivity_spinbox.setSuffix("")
|
||||
self.cfg_responsitivity_spinbox.setDecimals(4)
|
||||
self.cfg_responsitivity_spinbox.setMaximum(1000.0)
|
||||
self.cfg_responsitivity_spinbox.setSingleStep(0.001)
|
||||
self.cfg_responsitivity_spinbox.setObjectName("cfg_responsitivity_spinbox")
|
||||
self.cfg_responsitivity_layout.addWidget(self.cfg_responsitivity_spinbox)
|
||||
self.cfg_responsitivity_reading = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.cfg_responsitivity_reading.sizePolicy().hasHeightForWidth())
|
||||
self.cfg_responsitivity_reading.setSizePolicy(sizePolicy)
|
||||
self.cfg_responsitivity_reading.setObjectName("cfg_responsitivity_reading")
|
||||
self.cfg_responsitivity_layout.addWidget(self.cfg_responsitivity_reading)
|
||||
self.cfg_responsitivity_layout.setStretch(0, 5)
|
||||
self.cfg_responsitivity_layout.setStretch(1, 2)
|
||||
self.cfg_responsitivity_layout.setStretch(2, 2)
|
||||
self.cfg_pd_params_layout.addLayout(self.cfg_responsitivity_layout)
|
||||
self.cfg_dark_current_layout = QtWidgets.QHBoxLayout()
|
||||
self.cfg_dark_current_layout.setObjectName("cfg_dark_current_layout")
|
||||
self.cfg_dark_current_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
|
||||
self.cfg_dark_current_lbl.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
|
||||
self.cfg_dark_current_lbl.setObjectName("cfg_dark_current_lbl")
|
||||
self.cfg_dark_current_layout.addWidget(self.cfg_dark_current_lbl)
|
||||
self.cfg_dark_current_spinbox = QtWidgets.QDoubleSpinBox(parent=self.verticalLayoutWidget_2)
|
||||
self.cfg_dark_current_spinbox.setDecimals(4)
|
||||
self.cfg_dark_current_spinbox.setSingleStep(0.001)
|
||||
self.cfg_dark_current_spinbox.setObjectName("cfg_dark_current_spinbox")
|
||||
self.cfg_dark_current_layout.addWidget(self.cfg_dark_current_spinbox)
|
||||
self.cfg_dark_current_reading = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
|
||||
self.cfg_dark_current_reading.setObjectName("cfg_dark_current_reading")
|
||||
self.cfg_dark_current_layout.addWidget(self.cfg_dark_current_reading)
|
||||
self.cfg_dark_current_layout.setStretch(0, 5)
|
||||
self.cfg_dark_current_layout.setStretch(1, 2)
|
||||
self.cfg_dark_current_layout.setStretch(2, 2)
|
||||
self.cfg_pd_params_layout.addLayout(self.cfg_dark_current_layout)
|
||||
self.apply_pd_params_layout = QtWidgets.QHBoxLayout()
|
||||
self.apply_pd_params_layout.setSpacing(12)
|
||||
self.apply_pd_params_layout.setObjectName("apply_pd_params_layout")
|
||||
spacerItem1 = QtWidgets.QSpacerItem(10, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||
self.apply_pd_params_layout.addItem(spacerItem1)
|
||||
self.apply_pd_params_btn = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_2)
|
||||
self.apply_pd_params_btn.setObjectName("apply_pd_params_btn")
|
||||
self.apply_pd_params_layout.addWidget(self.apply_pd_params_btn)
|
||||
self.apply_pd_params_layout.setStretch(0, 5)
|
||||
self.apply_pd_params_layout.setStretch(1, 4)
|
||||
self.cfg_pd_params_layout.addLayout(self.apply_pd_params_layout)
|
||||
self.cfg_pd_mon_form_layout.addLayout(self.cfg_pd_params_layout)
|
||||
self.cfg_pwr_limit_layout = QtWidgets.QVBoxLayout()
|
||||
self.cfg_pwr_limit_layout.setObjectName("cfg_pwr_limit_layout")
|
||||
self.cfg_pd_pwr_limit_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(14)
|
||||
self.cfg_pd_pwr_limit_lbl.setFont(font)
|
||||
self.cfg_pd_pwr_limit_lbl.setObjectName("cfg_pd_pwr_limit_lbl")
|
||||
self.cfg_pwr_limit_layout.addWidget(self.cfg_pd_pwr_limit_lbl)
|
||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||
spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||
self.horizontalLayout_2.addItem(spacerItem2)
|
||||
self.label_3 = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
|
||||
self.label_3.setObjectName("label_3")
|
||||
self.horizontalLayout_2.addWidget(self.label_3)
|
||||
self.label_4 = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
|
||||
self.label_4.setObjectName("label_4")
|
||||
self.horizontalLayout_2.addWidget(self.label_4)
|
||||
self.horizontalLayout_2.setStretch(0, 5)
|
||||
self.horizontalLayout_2.setStretch(1, 2)
|
||||
self.horizontalLayout_2.setStretch(2, 2)
|
||||
self.cfg_pwr_limit_layout.addLayout(self.horizontalLayout_2)
|
||||
self.pwr_limit_layout = QtWidgets.QHBoxLayout()
|
||||
self.pwr_limit_layout.setObjectName("pwr_limit_layout")
|
||||
self.cfg_pwr_limit_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(12)
|
||||
self.cfg_pwr_limit_lbl.setFont(font)
|
||||
self.cfg_pwr_limit_lbl.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
|
||||
self.cfg_pwr_limit_lbl.setObjectName("cfg_pwr_limit_lbl")
|
||||
self.pwr_limit_layout.addWidget(self.cfg_pwr_limit_lbl)
|
||||
self.cfg_pwr_limit_spinbox = QtWidgets.QDoubleSpinBox(parent=self.verticalLayoutWidget_2)
|
||||
self.cfg_pwr_limit_spinbox.setDecimals(4)
|
||||
self.cfg_pwr_limit_spinbox.setSingleStep(0.001)
|
||||
self.cfg_pwr_limit_spinbox.setObjectName("cfg_pwr_limit_spinbox")
|
||||
self.pwr_limit_layout.addWidget(self.cfg_pwr_limit_spinbox)
|
||||
self.cfg_pwr_limit_reading = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
|
||||
self.cfg_pwr_limit_reading.setObjectName("cfg_pwr_limit_reading")
|
||||
self.pwr_limit_layout.addWidget(self.cfg_pwr_limit_reading)
|
||||
self.pwr_limit_layout.setStretch(0, 5)
|
||||
self.pwr_limit_layout.setStretch(1, 2)
|
||||
self.pwr_limit_layout.setStretch(2, 2)
|
||||
self.cfg_pwr_limit_layout.addLayout(self.pwr_limit_layout)
|
||||
self.settable_pwr_range_layout = QtWidgets.QHBoxLayout()
|
||||
self.settable_pwr_range_layout.setSpacing(12)
|
||||
self.settable_pwr_range_layout.setObjectName("settable_pwr_range_layout")
|
||||
self.settable_pwr_range_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(12)
|
||||
self.settable_pwr_range_lbl.setFont(font)
|
||||
self.settable_pwr_range_lbl.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
|
||||
self.settable_pwr_range_lbl.setObjectName("settable_pwr_range_lbl")
|
||||
self.settable_pwr_range_layout.addWidget(self.settable_pwr_range_lbl)
|
||||
self.settable_pwr_range_display_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
|
||||
self.settable_pwr_range_display_lbl.setMinimumSize(QtCore.QSize(0, 28))
|
||||
self.settable_pwr_range_display_lbl.setObjectName("settable_pwr_range_display_lbl")
|
||||
self.settable_pwr_range_layout.addWidget(self.settable_pwr_range_display_lbl)
|
||||
self.settable_pwr_range_layout.setStretch(0, 5)
|
||||
self.settable_pwr_range_layout.setStretch(1, 4)
|
||||
self.cfg_pwr_limit_layout.addLayout(self.settable_pwr_range_layout)
|
||||
self.apply_pwr_limit_layout = QtWidgets.QHBoxLayout()
|
||||
self.apply_pwr_limit_layout.setObjectName("apply_pwr_limit_layout")
|
||||
spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||
self.apply_pwr_limit_layout.addItem(spacerItem3)
|
||||
self.apply_pwr_limit_max_btn = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_2)
|
||||
self.apply_pwr_limit_max_btn.setObjectName("apply_pwr_limit_max_btn")
|
||||
self.apply_pwr_limit_layout.addWidget(self.apply_pwr_limit_max_btn)
|
||||
self.apply_pwr_limit_btn = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_2)
|
||||
self.apply_pwr_limit_btn.setObjectName("apply_pwr_limit_btn")
|
||||
self.apply_pwr_limit_layout.addWidget(self.apply_pwr_limit_btn)
|
||||
self.apply_pwr_limit_layout.setStretch(0, 2)
|
||||
self.apply_pwr_limit_layout.setStretch(1, 3)
|
||||
self.apply_pwr_limit_layout.setStretch(2, 4)
|
||||
self.cfg_pwr_limit_layout.addLayout(self.apply_pwr_limit_layout)
|
||||
self.cfg_pd_mon_form_layout.addLayout(self.cfg_pwr_limit_layout)
|
||||
self.pwr_on_layout = QtWidgets.QHBoxLayout()
|
||||
self.pwr_on_layout.setSpacing(12)
|
||||
self.pwr_on_layout.setObjectName("pwr_on_layout")
|
||||
self.pwr_on_lbl = QtWidgets.QLabel(parent=self.verticalLayoutWidget_2)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(14)
|
||||
self.pwr_on_lbl.setFont(font)
|
||||
self.pwr_on_lbl.setObjectName("pwr_on_lbl")
|
||||
self.pwr_on_layout.addWidget(self.pwr_on_lbl)
|
||||
self.pwr_on_btn = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_2)
|
||||
self.pwr_on_btn.setObjectName("pwr_on_btn")
|
||||
self.pwr_on_layout.addWidget(self.pwr_on_btn)
|
||||
self.pwr_on_layout.setStretch(0, 5)
|
||||
self.pwr_on_layout.setStretch(1, 4)
|
||||
self.cfg_pd_mon_form_layout.addLayout(self.pwr_on_layout)
|
||||
self.close_btn_layout = QtWidgets.QHBoxLayout()
|
||||
self.close_btn_layout.setSpacing(12)
|
||||
self.close_btn_layout.setObjectName("close_btn_layout")
|
||||
spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||
self.close_btn_layout.addItem(spacerItem4)
|
||||
self.close_btn = QtWidgets.QPushButton(parent=self.verticalLayoutWidget_2)
|
||||
self.close_btn.setObjectName("close_btn")
|
||||
self.close_btn_layout.addWidget(self.close_btn)
|
||||
self.close_btn_layout.setStretch(0, 5)
|
||||
self.close_btn_layout.setStretch(1, 4)
|
||||
self.cfg_pd_mon_form_layout.addLayout(self.close_btn_layout)
|
||||
self.cfg_pd_mon_form_layout.setStretch(1, 2)
|
||||
self.cfg_pd_mon_form_layout.setStretch(2, 2)
|
||||
self.cfg_pd_mon_form_layout.setStretch(3, 2)
|
||||
self.cfg_pd_mon_form_layout.setStretch(4, 2)
|
||||
self.cfg_pd_mon_form_layout.setStretch(5, 2)
|
||||
self.cfg_pd_mon_form_layout.setStretch(6, 1)
|
||||
|
||||
self.retranslateUi(Cfg_Pd_Mon_Form)
|
||||
self.close_btn.clicked.connect(Cfg_Pd_Mon_Form.accept) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(Cfg_Pd_Mon_Form)
|
||||
|
||||
def retranslateUi(self, Cfg_Pd_Mon_Form):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
Cfg_Pd_Mon_Form.setWindowTitle(_translate("Cfg_Pd_Mon_Form", "config_pd_mon_form"))
|
||||
self.title_lbl.setText(_translate("Cfg_Pd_Mon_Form", "Configure Photodiode Monitor"))
|
||||
self.pwr_off_lbl.setText(_translate("Cfg_Pd_Mon_Form", " Step 1: Turn off Laser Power"))
|
||||
self.pwr_off_btn.setText(_translate("Cfg_Pd_Mon_Form", "Power Off"))
|
||||
self.rst_ld_pwr_limit_lbl.setText(_translate("Cfg_Pd_Mon_Form", " Step 2: Reset Ld Pwr Limit to 0"))
|
||||
self.rst_ld_pwr_limit_btn.setText(_translate("Cfg_Pd_Mon_Form", "Reset Ld Pwr Limit"))
|
||||
self.cfg_pd_params_lbl.setText(_translate("Cfg_Pd_Mon_Form", " Step 3: Configure Photodiode Parameters"))
|
||||
self.label_2.setText(_translate("Cfg_Pd_Mon_Form", " Value"))
|
||||
self.label.setText(_translate("Cfg_Pd_Mon_Form", "Reading"))
|
||||
self.cfg_responsitivity_lbl.setText(_translate("Cfg_Pd_Mon_Form", "Responsitivity: "))
|
||||
self.cfg_responsitivity_reading.setText(_translate("Cfg_Pd_Mon_Form", "0.0000"))
|
||||
self.cfg_dark_current_lbl.setText(_translate("Cfg_Pd_Mon_Form", "Dark Current: "))
|
||||
self.cfg_dark_current_reading.setText(_translate("Cfg_Pd_Mon_Form", "0.0000"))
|
||||
self.apply_pd_params_btn.setText(_translate("Cfg_Pd_Mon_Form", "Apply"))
|
||||
self.cfg_pd_pwr_limit_lbl.setText(_translate("Cfg_Pd_Mon_Form", " Step 4: Configure Laser Diode Power Limit"))
|
||||
self.label_3.setText(_translate("Cfg_Pd_Mon_Form", " Value"))
|
||||
self.label_4.setText(_translate("Cfg_Pd_Mon_Form", "Reading"))
|
||||
self.cfg_pwr_limit_lbl.setText(_translate("Cfg_Pd_Mon_Form", "Power Limit:"))
|
||||
self.cfg_pwr_limit_reading.setText(_translate("Cfg_Pd_Mon_Form", "0.0000"))
|
||||
self.settable_pwr_range_lbl.setText(_translate("Cfg_Pd_Mon_Form", "Settable Power Range:"))
|
||||
self.settable_pwr_range_display_lbl.setText(_translate("Cfg_Pd_Mon_Form", "( Power Range )"))
|
||||
self.apply_pwr_limit_max_btn.setText(_translate("Cfg_Pd_Mon_Form", "Apply Max"))
|
||||
self.apply_pwr_limit_btn.setText(_translate("Cfg_Pd_Mon_Form", "Apply"))
|
||||
self.pwr_on_lbl.setText(_translate("Cfg_Pd_Mon_Form", " Step 5: Turn On Laser Power"))
|
||||
self.pwr_on_btn.setText(_translate("Cfg_Pd_Mon_Form", "Clear Alarm and Power On"))
|
||||
self.close_btn.setText(_translate("Cfg_Pd_Mon_Form", "Close"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
Cfg_Pd_Mon_Form = QtWidgets.QDialog()
|
||||
ui = Ui_Cfg_Pd_Mon_Form()
|
||||
ui.setupUi(Cfg_Pd_Mon_Form)
|
||||
Cfg_Pd_Mon_Form.show()
|
||||
sys.exit(app.exec())
|
||||
161
pykirdy/ui/ui_conn_settings_form.py
Normal file
161
pykirdy/ui/ui_conn_settings_form.py
Normal file
@@ -0,0 +1,161 @@
|
||||
# Form implementation generated from reading ui file 'conn_settings_form.ui'
|
||||
#
|
||||
# Created by: PyQt6 UI code generator 6.6.0
|
||||
#
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
from PyQt6 import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
class Ui_Conn_Settings_Form(object):
|
||||
def setupUi(self, Conn_Settings_Form):
|
||||
Conn_Settings_Form.setObjectName("Conn_Settings_Form")
|
||||
Conn_Settings_Form.resize(415, 145)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Fixed, QtWidgets.QSizePolicy.Policy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(Conn_Settings_Form.sizePolicy().hasHeightForWidth())
|
||||
Conn_Settings_Form.setSizePolicy(sizePolicy)
|
||||
Conn_Settings_Form.setMinimumSize(QtCore.QSize(415, 145))
|
||||
Conn_Settings_Form.setMaximumSize(QtCore.QSize(415, 145))
|
||||
self.horizontalLayoutWidget = QtWidgets.QWidget(parent=Conn_Settings_Form)
|
||||
self.horizontalLayoutWidget.setGeometry(QtCore.QRect(20, 10, 371, 41))
|
||||
self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
|
||||
self.ip_addr_layout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
|
||||
self.ip_addr_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.ip_addr_layout.setObjectName("ip_addr_layout")
|
||||
self.ip_addr_label = QtWidgets.QLabel(parent=self.horizontalLayoutWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.ip_addr_label.sizePolicy().hasHeightForWidth())
|
||||
self.ip_addr_label.setSizePolicy(sizePolicy)
|
||||
self.ip_addr_label.setMaximumSize(QtCore.QSize(120, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(12)
|
||||
self.ip_addr_label.setFont(font)
|
||||
self.ip_addr_label.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight)
|
||||
self.ip_addr_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
|
||||
self.ip_addr_label.setObjectName("ip_addr_label")
|
||||
self.ip_addr_layout.addWidget(self.ip_addr_label)
|
||||
self.addr_in_0 = QtWidgets.QLineEdit(parent=self.horizontalLayoutWidget)
|
||||
self.addr_in_0.setMaximumSize(QtCore.QSize(50, 16777215))
|
||||
self.addr_in_0.setMaxLength(3)
|
||||
self.addr_in_0.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.addr_in_0.setObjectName("addr_in_0")
|
||||
self.ip_addr_layout.addWidget(self.addr_in_0)
|
||||
self.dot_0_label = QtWidgets.QLabel(parent=self.horizontalLayoutWidget)
|
||||
self.dot_0_label.setMaximumSize(QtCore.QSize(10, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(12)
|
||||
font.setBold(False)
|
||||
font.setKerning(True)
|
||||
self.dot_0_label.setFont(font)
|
||||
self.dot_0_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.dot_0_label.setObjectName("dot_0_label")
|
||||
self.ip_addr_layout.addWidget(self.dot_0_label)
|
||||
self.addr_in_1 = QtWidgets.QLineEdit(parent=self.horizontalLayoutWidget)
|
||||
self.addr_in_1.setMaximumSize(QtCore.QSize(50, 16777215))
|
||||
self.addr_in_1.setMaxLength(3)
|
||||
self.addr_in_1.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.addr_in_1.setObjectName("addr_in_1")
|
||||
self.ip_addr_layout.addWidget(self.addr_in_1)
|
||||
self.dot_1_label = QtWidgets.QLabel(parent=self.horizontalLayoutWidget)
|
||||
self.dot_1_label.setMaximumSize(QtCore.QSize(10, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(12)
|
||||
font.setBold(False)
|
||||
font.setKerning(True)
|
||||
self.dot_1_label.setFont(font)
|
||||
self.dot_1_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.dot_1_label.setObjectName("dot_1_label")
|
||||
self.ip_addr_layout.addWidget(self.dot_1_label)
|
||||
self.addr_in_2 = QtWidgets.QLineEdit(parent=self.horizontalLayoutWidget)
|
||||
self.addr_in_2.setMaximumSize(QtCore.QSize(50, 16777215))
|
||||
self.addr_in_2.setMaxLength(3)
|
||||
self.addr_in_2.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.addr_in_2.setObjectName("addr_in_2")
|
||||
self.ip_addr_layout.addWidget(self.addr_in_2)
|
||||
self.dot_2_label = QtWidgets.QLabel(parent=self.horizontalLayoutWidget)
|
||||
self.dot_2_label.setMaximumSize(QtCore.QSize(10, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(12)
|
||||
font.setBold(False)
|
||||
font.setKerning(True)
|
||||
self.dot_2_label.setFont(font)
|
||||
self.dot_2_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.dot_2_label.setObjectName("dot_2_label")
|
||||
self.ip_addr_layout.addWidget(self.dot_2_label)
|
||||
self.addr_in_3 = QtWidgets.QLineEdit(parent=self.horizontalLayoutWidget)
|
||||
self.addr_in_3.setMaximumSize(QtCore.QSize(50, 16777215))
|
||||
self.addr_in_3.setMaxLength(3)
|
||||
self.addr_in_3.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.addr_in_3.setObjectName("addr_in_3")
|
||||
self.ip_addr_layout.addWidget(self.addr_in_3)
|
||||
self.horizontalLayoutWidget_2 = QtWidgets.QWidget(parent=Conn_Settings_Form)
|
||||
self.horizontalLayoutWidget_2.setGeometry(QtCore.QRect(20, 50, 371, 41))
|
||||
self.horizontalLayoutWidget_2.setObjectName("horizontalLayoutWidget_2")
|
||||
self.port_layout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_2)
|
||||
self.port_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.port_layout.setObjectName("port_layout")
|
||||
self.port_no_label = QtWidgets.QLabel(parent=self.horizontalLayoutWidget_2)
|
||||
self.port_no_label.setMaximumSize(QtCore.QSize(97, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(12)
|
||||
self.port_no_label.setFont(font)
|
||||
self.port_no_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
|
||||
self.port_no_label.setObjectName("port_no_label")
|
||||
self.port_layout.addWidget(self.port_no_label)
|
||||
self.port_in = QtWidgets.QLineEdit(parent=self.horizontalLayoutWidget_2)
|
||||
self.port_in.setMaximumSize(QtCore.QSize(50, 16777215))
|
||||
self.port_in.setMaxLength(5)
|
||||
self.port_in.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.port_in.setObjectName("port_in")
|
||||
self.port_layout.addWidget(self.port_in)
|
||||
spacerItem = QtWidgets.QSpacerItem(50, 20, QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||
self.port_layout.addItem(spacerItem)
|
||||
self.port_layout.setStretch(0, 3)
|
||||
self.port_layout.setStretch(2, 6)
|
||||
self.horizontalLayoutWidget_4 = QtWidgets.QWidget(parent=Conn_Settings_Form)
|
||||
self.horizontalLayoutWidget_4.setGeometry(QtCore.QRect(20, 90, 371, 47))
|
||||
self.horizontalLayoutWidget_4.setObjectName("horizontalLayoutWidget_4")
|
||||
self.buttons_layout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_4)
|
||||
self.buttons_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.buttons_layout.setObjectName("buttons_layout")
|
||||
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||
self.buttons_layout.addItem(spacerItem1)
|
||||
self.connect_btn = QtWidgets.QPushButton(parent=self.horizontalLayoutWidget_4)
|
||||
self.connect_btn.setObjectName("connect_btn")
|
||||
self.buttons_layout.addWidget(self.connect_btn)
|
||||
self.cancel_btn = QtWidgets.QPushButton(parent=self.horizontalLayoutWidget_4)
|
||||
self.cancel_btn.setObjectName("cancel_btn")
|
||||
self.buttons_layout.addWidget(self.cancel_btn)
|
||||
|
||||
self.retranslateUi(Conn_Settings_Form)
|
||||
self.cancel_btn.clicked.connect(Conn_Settings_Form.reject) # type: ignore
|
||||
self.connect_btn.clicked.connect(Conn_Settings_Form.accept) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(Conn_Settings_Form)
|
||||
Conn_Settings_Form.setTabOrder(self.addr_in_0, self.addr_in_1)
|
||||
Conn_Settings_Form.setTabOrder(self.addr_in_1, self.addr_in_2)
|
||||
Conn_Settings_Form.setTabOrder(self.addr_in_2, self.addr_in_3)
|
||||
Conn_Settings_Form.setTabOrder(self.addr_in_3, self.port_in)
|
||||
Conn_Settings_Form.setTabOrder(self.port_in, self.connect_btn)
|
||||
Conn_Settings_Form.setTabOrder(self.connect_btn, self.cancel_btn)
|
||||
|
||||
def retranslateUi(self, Conn_Settings_Form):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
Conn_Settings_Form.setWindowTitle(_translate("Conn_Settings_Form", "Connection Settings"))
|
||||
self.ip_addr_label.setText(_translate("Conn_Settings_Form", "IP Address:"))
|
||||
self.addr_in_0.setText(_translate("Conn_Settings_Form", "192"))
|
||||
self.dot_0_label.setText(_translate("Conn_Settings_Form", "."))
|
||||
self.addr_in_1.setText(_translate("Conn_Settings_Form", "168"))
|
||||
self.dot_1_label.setText(_translate("Conn_Settings_Form", "."))
|
||||
self.addr_in_2.setText(_translate("Conn_Settings_Form", "1"))
|
||||
self.dot_2_label.setText(_translate("Conn_Settings_Form", "."))
|
||||
self.addr_in_3.setText(_translate("Conn_Settings_Form", "128"))
|
||||
self.port_no_label.setText(_translate("Conn_Settings_Form", "Port:"))
|
||||
self.port_in.setText(_translate("Conn_Settings_Form", "1337"))
|
||||
self.connect_btn.setText(_translate("Conn_Settings_Form", "Connect"))
|
||||
self.cancel_btn.setText(_translate("Conn_Settings_Form", "Cancel"))
|
||||
264
pykirdy/ui/ui_update_network_settings_form.py
Normal file
264
pykirdy/ui/ui_update_network_settings_form.py
Normal file
@@ -0,0 +1,264 @@
|
||||
# Form implementation generated from reading ui file 'update_network_settings_form.ui'
|
||||
#
|
||||
# Created by: PyQt6 UI code generator 6.6.0
|
||||
#
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
from PyQt6 import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
class Ui_Update_Network_Settings_Form(object):
|
||||
def setupUi(self, Update_Network_Settings_Form):
|
||||
Update_Network_Settings_Form.setObjectName("Update_Network_Settings_Form")
|
||||
Update_Network_Settings_Form.resize(415, 180)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(Update_Network_Settings_Form.sizePolicy().hasHeightForWidth())
|
||||
Update_Network_Settings_Form.setSizePolicy(sizePolicy)
|
||||
Update_Network_Settings_Form.setMinimumSize(QtCore.QSize(415, 180))
|
||||
Update_Network_Settings_Form.setMaximumSize(QtCore.QSize(415, 180))
|
||||
self.horizontalLayoutWidget = QtWidgets.QWidget(parent=Update_Network_Settings_Form)
|
||||
self.horizontalLayoutWidget.setGeometry(QtCore.QRect(20, 10, 371, 41))
|
||||
self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
|
||||
self.ip_addr_layout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
|
||||
self.ip_addr_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.ip_addr_layout.setObjectName("ip_addr_layout")
|
||||
self.ip_addr_label = QtWidgets.QLabel(parent=self.horizontalLayoutWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.ip_addr_label.sizePolicy().hasHeightForWidth())
|
||||
self.ip_addr_label.setSizePolicy(sizePolicy)
|
||||
self.ip_addr_label.setMaximumSize(QtCore.QSize(120, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(12)
|
||||
self.ip_addr_label.setFont(font)
|
||||
self.ip_addr_label.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight)
|
||||
self.ip_addr_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
|
||||
self.ip_addr_label.setObjectName("ip_addr_label")
|
||||
self.ip_addr_layout.addWidget(self.ip_addr_label)
|
||||
self.addr_in_0 = QtWidgets.QLineEdit(parent=self.horizontalLayoutWidget)
|
||||
self.addr_in_0.setMaximumSize(QtCore.QSize(50, 16777215))
|
||||
self.addr_in_0.setMaxLength(3)
|
||||
self.addr_in_0.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.addr_in_0.setObjectName("addr_in_0")
|
||||
self.ip_addr_layout.addWidget(self.addr_in_0)
|
||||
self.dot_0_lbl = QtWidgets.QLabel(parent=self.horizontalLayoutWidget)
|
||||
self.dot_0_lbl.setMaximumSize(QtCore.QSize(10, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(12)
|
||||
font.setBold(False)
|
||||
font.setKerning(True)
|
||||
self.dot_0_lbl.setFont(font)
|
||||
self.dot_0_lbl.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.dot_0_lbl.setObjectName("dot_0_lbl")
|
||||
self.ip_addr_layout.addWidget(self.dot_0_lbl)
|
||||
self.addr_in_1 = QtWidgets.QLineEdit(parent=self.horizontalLayoutWidget)
|
||||
self.addr_in_1.setMaximumSize(QtCore.QSize(50, 16777215))
|
||||
self.addr_in_1.setMaxLength(3)
|
||||
self.addr_in_1.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.addr_in_1.setObjectName("addr_in_1")
|
||||
self.ip_addr_layout.addWidget(self.addr_in_1)
|
||||
self.dot_1_lbl = QtWidgets.QLabel(parent=self.horizontalLayoutWidget)
|
||||
self.dot_1_lbl.setMaximumSize(QtCore.QSize(10, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(12)
|
||||
font.setBold(False)
|
||||
font.setKerning(True)
|
||||
self.dot_1_lbl.setFont(font)
|
||||
self.dot_1_lbl.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.dot_1_lbl.setObjectName("dot_1_lbl")
|
||||
self.ip_addr_layout.addWidget(self.dot_1_lbl)
|
||||
self.addr_in_2 = QtWidgets.QLineEdit(parent=self.horizontalLayoutWidget)
|
||||
self.addr_in_2.setMaximumSize(QtCore.QSize(50, 16777215))
|
||||
self.addr_in_2.setMaxLength(3)
|
||||
self.addr_in_2.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.addr_in_2.setObjectName("addr_in_2")
|
||||
self.ip_addr_layout.addWidget(self.addr_in_2)
|
||||
self.dot_2_lbl = QtWidgets.QLabel(parent=self.horizontalLayoutWidget)
|
||||
self.dot_2_lbl.setMaximumSize(QtCore.QSize(10, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(12)
|
||||
font.setBold(False)
|
||||
font.setKerning(True)
|
||||
self.dot_2_lbl.setFont(font)
|
||||
self.dot_2_lbl.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.dot_2_lbl.setObjectName("dot_2_lbl")
|
||||
self.ip_addr_layout.addWidget(self.dot_2_lbl)
|
||||
self.addr_in_3 = QtWidgets.QLineEdit(parent=self.horizontalLayoutWidget)
|
||||
self.addr_in_3.setMaximumSize(QtCore.QSize(50, 16777215))
|
||||
self.addr_in_3.setMaxLength(3)
|
||||
self.addr_in_3.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.addr_in_3.setObjectName("addr_in_3")
|
||||
self.ip_addr_layout.addWidget(self.addr_in_3)
|
||||
self.horizontalLayoutWidget_4 = QtWidgets.QWidget(parent=Update_Network_Settings_Form)
|
||||
self.horizontalLayoutWidget_4.setGeometry(QtCore.QRect(20, 130, 371, 47))
|
||||
self.horizontalLayoutWidget_4.setObjectName("horizontalLayoutWidget_4")
|
||||
self.buttons_layout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_4)
|
||||
self.buttons_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.buttons_layout.setObjectName("buttons_layout")
|
||||
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||
self.buttons_layout.addItem(spacerItem)
|
||||
self.update_btn = QtWidgets.QPushButton(parent=self.horizontalLayoutWidget_4)
|
||||
self.update_btn.setObjectName("update_btn")
|
||||
self.buttons_layout.addWidget(self.update_btn)
|
||||
self.cancel_btn = QtWidgets.QPushButton(parent=self.horizontalLayoutWidget_4)
|
||||
self.cancel_btn.setObjectName("cancel_btn")
|
||||
self.buttons_layout.addWidget(self.cancel_btn)
|
||||
self.horizontalLayoutWidget_3 = QtWidgets.QWidget(parent=Update_Network_Settings_Form)
|
||||
self.horizontalLayoutWidget_3.setGeometry(QtCore.QRect(20, 90, 371, 41))
|
||||
self.horizontalLayoutWidget_3.setObjectName("horizontalLayoutWidget_3")
|
||||
self.port_layout_2 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_3)
|
||||
self.port_layout_2.setContentsMargins(0, 0, 0, 0)
|
||||
self.port_layout_2.setSpacing(6)
|
||||
self.port_layout_2.setObjectName("port_layout_2")
|
||||
self.prefix_len_lbl = QtWidgets.QLabel(parent=self.horizontalLayoutWidget_3)
|
||||
self.prefix_len_lbl.setMaximumSize(QtCore.QSize(98, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(12)
|
||||
self.prefix_len_lbl.setFont(font)
|
||||
self.prefix_len_lbl.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
|
||||
self.prefix_len_lbl.setObjectName("prefix_len_lbl")
|
||||
self.port_layout_2.addWidget(self.prefix_len_lbl)
|
||||
self.prefix_len_in = QtWidgets.QLineEdit(parent=self.horizontalLayoutWidget_3)
|
||||
self.prefix_len_in.setMaximumSize(QtCore.QSize(50, 16777215))
|
||||
self.prefix_len_in.setMaxLength(2)
|
||||
self.prefix_len_in.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.prefix_len_in.setObjectName("prefix_len_in")
|
||||
self.port_layout_2.addWidget(self.prefix_len_in)
|
||||
self.port_no_lbl = QtWidgets.QLabel(parent=self.horizontalLayoutWidget_3)
|
||||
self.port_no_lbl.setMinimumSize(QtCore.QSize(82, 0))
|
||||
self.port_no_lbl.setMaximumSize(QtCore.QSize(50, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(12)
|
||||
self.port_no_lbl.setFont(font)
|
||||
self.port_no_lbl.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
|
||||
self.port_no_lbl.setObjectName("port_no_lbl")
|
||||
self.port_layout_2.addWidget(self.port_no_lbl)
|
||||
self.port_in = QtWidgets.QLineEdit(parent=self.horizontalLayoutWidget_3)
|
||||
self.port_in.setMaximumSize(QtCore.QSize(50, 16777215))
|
||||
self.port_in.setMaxLength(5)
|
||||
self.port_in.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.port_in.setObjectName("port_in")
|
||||
self.port_layout_2.addWidget(self.port_in)
|
||||
spacerItem1 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||
self.port_layout_2.addItem(spacerItem1)
|
||||
self.horizontalLayoutWidget_5 = QtWidgets.QWidget(parent=Update_Network_Settings_Form)
|
||||
self.horizontalLayoutWidget_5.setGeometry(QtCore.QRect(20, 50, 371, 41))
|
||||
self.horizontalLayoutWidget_5.setObjectName("horizontalLayoutWidget_5")
|
||||
self.gateway_layout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_5)
|
||||
self.gateway_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.gateway_layout.setObjectName("gateway_layout")
|
||||
self.gateway_lbl = QtWidgets.QLabel(parent=self.horizontalLayoutWidget_5)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.gateway_lbl.sizePolicy().hasHeightForWidth())
|
||||
self.gateway_lbl.setSizePolicy(sizePolicy)
|
||||
self.gateway_lbl.setMaximumSize(QtCore.QSize(120, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(12)
|
||||
self.gateway_lbl.setFont(font)
|
||||
self.gateway_lbl.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight)
|
||||
self.gateway_lbl.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
|
||||
self.gateway_lbl.setObjectName("gateway_lbl")
|
||||
self.gateway_layout.addWidget(self.gateway_lbl)
|
||||
self.gateway_in_0 = QtWidgets.QLineEdit(parent=self.horizontalLayoutWidget_5)
|
||||
self.gateway_in_0.setMaximumSize(QtCore.QSize(50, 16777215))
|
||||
self.gateway_in_0.setMaxLength(3)
|
||||
self.gateway_in_0.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.gateway_in_0.setObjectName("gateway_in_0")
|
||||
self.gateway_layout.addWidget(self.gateway_in_0)
|
||||
self.dot_0_lbl_2 = QtWidgets.QLabel(parent=self.horizontalLayoutWidget_5)
|
||||
self.dot_0_lbl_2.setMaximumSize(QtCore.QSize(10, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(12)
|
||||
font.setBold(False)
|
||||
font.setKerning(True)
|
||||
self.dot_0_lbl_2.setFont(font)
|
||||
self.dot_0_lbl_2.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.dot_0_lbl_2.setObjectName("dot_0_lbl_2")
|
||||
self.gateway_layout.addWidget(self.dot_0_lbl_2)
|
||||
self.gateway_in_1 = QtWidgets.QLineEdit(parent=self.horizontalLayoutWidget_5)
|
||||
self.gateway_in_1.setMaximumSize(QtCore.QSize(50, 16777215))
|
||||
self.gateway_in_1.setMaxLength(3)
|
||||
self.gateway_in_1.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.gateway_in_1.setObjectName("gateway_in_1")
|
||||
self.gateway_layout.addWidget(self.gateway_in_1)
|
||||
self.dot_1_lbl_2 = QtWidgets.QLabel(parent=self.horizontalLayoutWidget_5)
|
||||
self.dot_1_lbl_2.setMaximumSize(QtCore.QSize(10, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(12)
|
||||
font.setBold(False)
|
||||
font.setKerning(True)
|
||||
self.dot_1_lbl_2.setFont(font)
|
||||
self.dot_1_lbl_2.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.dot_1_lbl_2.setObjectName("dot_1_lbl_2")
|
||||
self.gateway_layout.addWidget(self.dot_1_lbl_2)
|
||||
self.gateway_in_2 = QtWidgets.QLineEdit(parent=self.horizontalLayoutWidget_5)
|
||||
self.gateway_in_2.setMaximumSize(QtCore.QSize(50, 16777215))
|
||||
self.gateway_in_2.setMaxLength(3)
|
||||
self.gateway_in_2.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.gateway_in_2.setObjectName("gateway_in_2")
|
||||
self.gateway_layout.addWidget(self.gateway_in_2)
|
||||
self.dot_2_lbl_2 = QtWidgets.QLabel(parent=self.horizontalLayoutWidget_5)
|
||||
self.dot_2_lbl_2.setMaximumSize(QtCore.QSize(10, 16777215))
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(12)
|
||||
font.setBold(False)
|
||||
font.setKerning(True)
|
||||
self.dot_2_lbl_2.setFont(font)
|
||||
self.dot_2_lbl_2.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.dot_2_lbl_2.setObjectName("dot_2_lbl_2")
|
||||
self.gateway_layout.addWidget(self.dot_2_lbl_2)
|
||||
self.gateway_in_3 = QtWidgets.QLineEdit(parent=self.horizontalLayoutWidget_5)
|
||||
self.gateway_in_3.setMaximumSize(QtCore.QSize(50, 16777215))
|
||||
self.gateway_in_3.setMaxLength(3)
|
||||
self.gateway_in_3.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
self.gateway_in_3.setObjectName("gateway_in_3")
|
||||
self.gateway_layout.addWidget(self.gateway_in_3)
|
||||
|
||||
self.retranslateUi(Update_Network_Settings_Form)
|
||||
self.cancel_btn.clicked.connect(Update_Network_Settings_Form.reject) # type: ignore
|
||||
self.update_btn.clicked.connect(Update_Network_Settings_Form.accept) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(Update_Network_Settings_Form)
|
||||
Update_Network_Settings_Form.setTabOrder(self.addr_in_0, self.addr_in_1)
|
||||
Update_Network_Settings_Form.setTabOrder(self.addr_in_1, self.addr_in_2)
|
||||
Update_Network_Settings_Form.setTabOrder(self.addr_in_2, self.addr_in_3)
|
||||
Update_Network_Settings_Form.setTabOrder(self.addr_in_3, self.gateway_in_0)
|
||||
Update_Network_Settings_Form.setTabOrder(self.gateway_in_0, self.gateway_in_1)
|
||||
Update_Network_Settings_Form.setTabOrder(self.gateway_in_1, self.gateway_in_2)
|
||||
Update_Network_Settings_Form.setTabOrder(self.gateway_in_2, self.gateway_in_3)
|
||||
Update_Network_Settings_Form.setTabOrder(self.gateway_in_3, self.prefix_len_in)
|
||||
Update_Network_Settings_Form.setTabOrder(self.prefix_len_in, self.port_in)
|
||||
Update_Network_Settings_Form.setTabOrder(self.port_in, self.update_btn)
|
||||
Update_Network_Settings_Form.setTabOrder(self.update_btn, self.cancel_btn)
|
||||
|
||||
def retranslateUi(self, Update_Network_Settings_Form):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
Update_Network_Settings_Form.setWindowTitle(_translate("Update_Network_Settings_Form", "Update Network Settings"))
|
||||
self.ip_addr_label.setText(_translate("Update_Network_Settings_Form", "IP Address:"))
|
||||
self.addr_in_0.setText(_translate("Update_Network_Settings_Form", "192"))
|
||||
self.dot_0_lbl.setText(_translate("Update_Network_Settings_Form", "."))
|
||||
self.addr_in_1.setText(_translate("Update_Network_Settings_Form", "168"))
|
||||
self.dot_1_lbl.setText(_translate("Update_Network_Settings_Form", "."))
|
||||
self.addr_in_2.setText(_translate("Update_Network_Settings_Form", "1"))
|
||||
self.dot_2_lbl.setText(_translate("Update_Network_Settings_Form", "."))
|
||||
self.addr_in_3.setText(_translate("Update_Network_Settings_Form", "128"))
|
||||
self.update_btn.setText(_translate("Update_Network_Settings_Form", "Update"))
|
||||
self.cancel_btn.setText(_translate("Update_Network_Settings_Form", "Cancel"))
|
||||
self.prefix_len_lbl.setText(_translate("Update_Network_Settings_Form", "Prefix Length:"))
|
||||
self.prefix_len_in.setText(_translate("Update_Network_Settings_Form", "24"))
|
||||
self.port_no_lbl.setText(_translate("Update_Network_Settings_Form", "Port:"))
|
||||
self.port_in.setText(_translate("Update_Network_Settings_Form", "1337"))
|
||||
self.gateway_lbl.setText(_translate("Update_Network_Settings_Form", "Gateway:"))
|
||||
self.gateway_in_0.setText(_translate("Update_Network_Settings_Form", "192"))
|
||||
self.dot_0_lbl_2.setText(_translate("Update_Network_Settings_Form", "."))
|
||||
self.gateway_in_1.setText(_translate("Update_Network_Settings_Form", "168"))
|
||||
self.dot_1_lbl_2.setText(_translate("Update_Network_Settings_Form", "."))
|
||||
self.gateway_in_2.setText(_translate("Update_Network_Settings_Form", "1"))
|
||||
self.dot_2_lbl_2.setText(_translate("Update_Network_Settings_Form", "."))
|
||||
self.gateway_in_3.setText(_translate("Update_Network_Settings_Form", "1"))
|
||||
614
pykirdy/ui/update_network_settings_form.ui
Normal file
614
pykirdy/ui/update_network_settings_form.ui
Normal file
@@ -0,0 +1,614 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Update_Network_Settings_Form</class>
|
||||
<widget class="QDialog" name="Update_Network_Settings_Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>415</width>
|
||||
<height>180</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>415</width>
|
||||
<height>180</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>415</width>
|
||||
<height>180</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Update Network Settings</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="horizontalLayoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>10</y>
|
||||
<width>371</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="ip_addr_layout">
|
||||
<item>
|
||||
<widget class="QLabel" name="ip_addr_label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>IP Address:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="addr_in_0">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>192</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="dot_0_lbl">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
<bold>false</bold>
|
||||
<kerning>true</kerning>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="addr_in_1">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>168</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="dot_1_lbl">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
<bold>false</bold>
|
||||
<kerning>true</kerning>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="addr_in_2">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>1</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="dot_2_lbl">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
<bold>false</bold>
|
||||
<kerning>true</kerning>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="addr_in_3">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>128</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="horizontalLayoutWidget_4">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>130</y>
|
||||
<width>371</width>
|
||||
<height>47</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="buttons_layout">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="update_btn">
|
||||
<property name="text">
|
||||
<string>Update</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cancel_btn">
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="horizontalLayoutWidget_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>90</y>
|
||||
<width>371</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="port_layout_2" stretch="0,0,0,0,0">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="prefix_len_lbl">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>98</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Prefix Length:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="prefix_len_in">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>24</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="port_no_lbl">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>82</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Port:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="port_in">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>1337</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="horizontalLayoutWidget_5">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>50</y>
|
||||
<width>371</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="gateway_layout">
|
||||
<item>
|
||||
<widget class="QLabel" name="gateway_lbl">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Gateway:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="gateway_in_0">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>192</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="dot_0_lbl_2">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
<bold>false</bold>
|
||||
<kerning>true</kerning>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="gateway_in_1">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>168</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="dot_1_lbl_2">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
<bold>false</bold>
|
||||
<kerning>true</kerning>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="gateway_in_2">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>1</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="dot_2_lbl_2">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
<bold>false</bold>
|
||||
<kerning>true</kerning>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="gateway_in_3">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>1</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>addr_in_0</tabstop>
|
||||
<tabstop>addr_in_1</tabstop>
|
||||
<tabstop>addr_in_2</tabstop>
|
||||
<tabstop>addr_in_3</tabstop>
|
||||
<tabstop>gateway_in_0</tabstop>
|
||||
<tabstop>gateway_in_1</tabstop>
|
||||
<tabstop>gateway_in_2</tabstop>
|
||||
<tabstop>gateway_in_3</tabstop>
|
||||
<tabstop>prefix_len_in</tabstop>
|
||||
<tabstop>port_in</tabstop>
|
||||
<tabstop>update_btn</tabstop>
|
||||
<tabstop>cancel_btn</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>cancel_btn</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>Update_Network_Settings_Form</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>340</x>
|
||||
<y>140</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>364</x>
|
||||
<y>96</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>update_btn</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>Update_Network_Settings_Form</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>258</x>
|
||||
<y>147</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>237</x>
|
||||
<y>99</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
194
pykirdy/waitingspinnerwidget.py
Normal file
194
pykirdy/waitingspinnerwidget.py
Normal file
@@ -0,0 +1,194 @@
|
||||
"""
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2012-2014 Alexander Turkin
|
||||
Copyright (c) 2014 William Hallatt
|
||||
Copyright (c) 2015 Jacob Dawid
|
||||
Copyright (c) 2016 Luca Weiss
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
"""
|
||||
|
||||
import math
|
||||
|
||||
from PyQt6.QtCore import *
|
||||
from PyQt6.QtGui import *
|
||||
from PyQt6.QtWidgets import *
|
||||
|
||||
|
||||
class QtWaitingSpinner(QWidget):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
# WAS IN initialize()
|
||||
self._color = QColor(Qt.GlobalColor.black)
|
||||
self._roundness = 100.0
|
||||
self._minimumTrailOpacity = 3.14159265358979323846
|
||||
self._trailFadePercentage = 80.0
|
||||
self._revolutionsPerSecond = 1.57079632679489661923
|
||||
self._numberOfLines = 20
|
||||
self._lineLength = 5
|
||||
self._lineWidth = 2
|
||||
self._innerRadius = 5
|
||||
self._currentCounter = 0
|
||||
|
||||
self._timer = QTimer(self)
|
||||
self._timer.timeout.connect(self.rotate)
|
||||
self.updateSize()
|
||||
self.updateTimer()
|
||||
# END initialize()
|
||||
|
||||
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
||||
|
||||
def paintEvent(self, QPaintEvent):
|
||||
painter = QPainter(self)
|
||||
painter.fillRect(self.rect(), Qt.GlobalColor.transparent)
|
||||
painter.setRenderHint(QPainter.RenderHint.Antialiasing, True)
|
||||
|
||||
if self._currentCounter >= self._numberOfLines:
|
||||
self._currentCounter = 0
|
||||
|
||||
painter.setPen(Qt.PenStyle.NoPen)
|
||||
for i in range(0, self._numberOfLines):
|
||||
painter.save()
|
||||
painter.translate(self._innerRadius + self._lineLength, self._innerRadius + self._lineLength)
|
||||
rotateAngle = float(360 * i) / float(self._numberOfLines)
|
||||
painter.rotate(rotateAngle)
|
||||
painter.translate(self._innerRadius, 0)
|
||||
distance = self.lineCountDistanceFromPrimary(i, self._currentCounter, self._numberOfLines)
|
||||
color = self.currentLineColor(distance, self._numberOfLines, self._trailFadePercentage,
|
||||
self._minimumTrailOpacity, self._color)
|
||||
painter.setBrush(color)
|
||||
painter.drawRoundedRect(QRect(0, int(-self._lineWidth / 2), self._lineLength, self._lineWidth), self._roundness,
|
||||
self._roundness, Qt.SizeMode.RelativeSize)
|
||||
painter.restore()
|
||||
|
||||
def start(self):
|
||||
if not self._timer.isActive():
|
||||
self._timer.start()
|
||||
self._currentCounter = 0
|
||||
|
||||
def stop(self):
|
||||
if self._timer.isActive():
|
||||
self._timer.stop()
|
||||
self._currentCounter = 0
|
||||
|
||||
def setNumberOfLines(self, lines):
|
||||
self._numberOfLines = lines
|
||||
self._currentCounter = 0
|
||||
self.updateTimer()
|
||||
|
||||
def setLineLength(self, length):
|
||||
self._lineLength = length
|
||||
self.updateSize()
|
||||
|
||||
def setLineWidth(self, width):
|
||||
self._lineWidth = width
|
||||
self.updateSize()
|
||||
|
||||
def setInnerRadius(self, radius):
|
||||
self._innerRadius = radius
|
||||
self.updateSize()
|
||||
|
||||
def color(self):
|
||||
return self._color
|
||||
|
||||
def roundness(self):
|
||||
return self._roundness
|
||||
|
||||
def minimumTrailOpacity(self):
|
||||
return self._minimumTrailOpacity
|
||||
|
||||
def trailFadePercentage(self):
|
||||
return self._trailFadePercentage
|
||||
|
||||
def revolutionsPersSecond(self):
|
||||
return self._revolutionsPerSecond
|
||||
|
||||
def numberOfLines(self):
|
||||
return self._numberOfLines
|
||||
|
||||
def lineLength(self):
|
||||
return self._lineLength
|
||||
|
||||
def lineWidth(self):
|
||||
return self._lineWidth
|
||||
|
||||
def innerRadius(self):
|
||||
return self._innerRadius
|
||||
|
||||
def setRoundness(self, roundness):
|
||||
self._roundness = max(0.0, min(100.0, roundness))
|
||||
|
||||
def setColor(self, color=Qt.GlobalColor.black):
|
||||
self._color = QColor(color)
|
||||
|
||||
def setRevolutionsPerSecond(self, revolutionsPerSecond):
|
||||
self._revolutionsPerSecond = revolutionsPerSecond
|
||||
self.updateTimer()
|
||||
|
||||
def setTrailFadePercentage(self, trail):
|
||||
self._trailFadePercentage = trail
|
||||
|
||||
def setMinimumTrailOpacity(self, minimumTrailOpacity):
|
||||
self._minimumTrailOpacity = minimumTrailOpacity
|
||||
|
||||
def rotate(self):
|
||||
self._currentCounter += 1
|
||||
if self._currentCounter >= self._numberOfLines:
|
||||
self._currentCounter = 0
|
||||
self.update()
|
||||
|
||||
def updateSize(self):
|
||||
self.size = (self._innerRadius + self._lineLength) * 2
|
||||
self.setFixedSize(self.size, self.size)
|
||||
|
||||
def updateTimer(self):
|
||||
self._timer.setInterval(int(1000 / (self._numberOfLines * self._revolutionsPerSecond)))
|
||||
|
||||
def lineCountDistanceFromPrimary(self, current, primary, totalNrOfLines):
|
||||
distance = primary - current
|
||||
if distance < 0:
|
||||
distance += totalNrOfLines
|
||||
return distance
|
||||
|
||||
def currentLineColor(self, countDistance, totalNrOfLines, trailFadePerc, minOpacity, colorinput):
|
||||
color = QColor(colorinput)
|
||||
if countDistance == 0:
|
||||
return color
|
||||
minAlphaF = minOpacity / 100.0
|
||||
distanceThreshold = int(math.ceil((totalNrOfLines - 1) * trailFadePerc / 100.0))
|
||||
if countDistance > distanceThreshold:
|
||||
color.setAlphaF(minAlphaF)
|
||||
else:
|
||||
alphaDiff = color.alphaF() - minAlphaF
|
||||
gradient = alphaDiff / float(distanceThreshold + 1)
|
||||
resultAlpha = color.alphaF() - gradient * countDistance
|
||||
# If alpha is out of bounds, clip it.
|
||||
resultAlpha = min(1.0, max(0.0, resultAlpha))
|
||||
color.setAlphaF(resultAlpha)
|
||||
return color
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = QApplication([])
|
||||
waiting_spinner = QtWaitingSpinner()
|
||||
waiting_spinner.show()
|
||||
waiting_spinner.start()
|
||||
app.exec()
|
||||
64
rustfmt.toml
Normal file
64
rustfmt.toml
Normal file
@@ -0,0 +1,64 @@
|
||||
max_width = 120
|
||||
hard_tabs = false
|
||||
tab_spaces = 4
|
||||
newline_style = "Auto"
|
||||
use_small_heuristics = "Default"
|
||||
indent_style = "Block"
|
||||
wrap_comments = false
|
||||
format_code_in_doc_comments = false
|
||||
comment_width = 100
|
||||
normalize_comments = false
|
||||
normalize_doc_attributes = false
|
||||
format_strings = true
|
||||
format_macro_matchers = true
|
||||
format_macro_bodies = true
|
||||
empty_item_single_line = true
|
||||
struct_lit_single_line = true
|
||||
fn_single_line = false
|
||||
where_single_line = true
|
||||
imports_indent = "Visual"
|
||||
imports_layout = "Mixed"
|
||||
imports_granularity="Crate"
|
||||
group_imports = "StdExternalCrate"
|
||||
reorder_imports = true
|
||||
reorder_modules = true
|
||||
reorder_impl_items = false
|
||||
type_punctuation_density = "Wide"
|
||||
space_before_colon = false
|
||||
space_after_colon = true
|
||||
spaces_around_ranges = false
|
||||
binop_separator = "Front"
|
||||
remove_nested_parens = true
|
||||
combine_control_expr = true
|
||||
overflow_delimited_expr = false
|
||||
struct_field_align_threshold = 0
|
||||
enum_discrim_align_threshold = 0
|
||||
match_arm_blocks = true
|
||||
match_arm_leading_pipes = "Never"
|
||||
force_multiline_blocks = false
|
||||
fn_params_layout = "Tall"
|
||||
brace_style = "SameLineWhere"
|
||||
control_brace_style = "AlwaysSameLine"
|
||||
trailing_semicolon = true
|
||||
trailing_comma = "Vertical"
|
||||
match_block_trailing_comma = false
|
||||
blank_lines_upper_bound = 1
|
||||
blank_lines_lower_bound = 0
|
||||
edition = "2018"
|
||||
version = "Two"
|
||||
inline_attribute_width = 0
|
||||
merge_derives = true
|
||||
use_try_shorthand = false
|
||||
use_field_init_shorthand = false
|
||||
force_explicit_abi = true
|
||||
condense_wildcard_suffixes = false
|
||||
color = "Auto"
|
||||
unstable_features = false
|
||||
disable_all_formatting = false
|
||||
skip_children = false
|
||||
hide_parse_errors = false
|
||||
error_on_line_overflow = false
|
||||
error_on_unformatted = false
|
||||
ignore = []
|
||||
emit_mode = "Files"
|
||||
make_backup = false
|
||||
@@ -1,20 +1,30 @@
|
||||
use super::{gpio, sys_timer, usb};
|
||||
use crate::laser_diode::current_sources::*;
|
||||
use fugit::ExtU32;
|
||||
use log::info;
|
||||
use stm32f4xx_hal::{
|
||||
pac::{CorePeripherals, Peripherals},
|
||||
rcc::RccExt,
|
||||
time::MegaHertz,
|
||||
watchdog::IndependentWatchdog,
|
||||
};
|
||||
use log::{debug, info};
|
||||
use stm32f4xx_hal::{pac::{CorePeripherals, Peripherals},
|
||||
rcc::RccExt,
|
||||
time::MegaHertz,
|
||||
timer::TimerExt,
|
||||
watchdog::IndependentWatchdog};
|
||||
use uom::si::{electric_current::{ampere, milliampere},
|
||||
f32::ElectricCurrent};
|
||||
|
||||
use super::{gpio, sys_timer, usb};
|
||||
use crate::{device::{flash_store::{self, FlashStore},
|
||||
hw_rev::HWRev},
|
||||
laser_diode::{laser_diode::LdDrive, ld_ctrl::*},
|
||||
net::net::{IpSettings, ServerHandle},
|
||||
thermostat::{max1968::MAX1968, thermostat::Thermostat},
|
||||
DeviceSettings};
|
||||
|
||||
#[cfg(not(feature = "semihosting"))]
|
||||
const WATCHDOG_PERIOD: u32 = 1000;
|
||||
const WATCHDOG_PERIOD: u32 = 4000;
|
||||
#[cfg(feature = "semihosting")]
|
||||
const WATCHDOG_PERIOD: u32 = 30000;
|
||||
|
||||
pub fn bootup(mut core_perif: CorePeripherals, perif: Peripherals) -> IndependentWatchdog {
|
||||
pub fn bootup(
|
||||
mut core_perif: CorePeripherals,
|
||||
perif: Peripherals,
|
||||
) -> (IndependentWatchdog, FlashStore, HWRev, LdDrive, Thermostat) {
|
||||
core_perif.SCB.enable_icache();
|
||||
core_perif.SCB.enable_dcache(&mut core_perif.CPUID);
|
||||
|
||||
@@ -25,42 +35,90 @@ pub fn bootup(mut core_perif: CorePeripherals, perif: Peripherals) -> Independen
|
||||
.use_hse(MegaHertz::from_raw(8).convert())
|
||||
.sysclk(MegaHertz::from_raw(168).convert())
|
||||
.hclk(MegaHertz::from_raw(168).convert())
|
||||
.pclk1(MegaHertz::from_raw(32).convert())
|
||||
.pclk2(MegaHertz::from_raw(64).convert())
|
||||
.pclk1(MegaHertz::from_raw(42).convert())
|
||||
.pclk2(MegaHertz::from_raw(84).convert())
|
||||
.freeze();
|
||||
|
||||
sys_timer::setup(core_perif.SYST, clocks);
|
||||
|
||||
let (_eth_pins, usb, current_source_phy) = gpio::setup(
|
||||
clocks,
|
||||
perif.GPIOA,
|
||||
perif.GPIOB,
|
||||
perif.GPIOC,
|
||||
perif.GPIOD,
|
||||
perif.GPIOG,
|
||||
perif.SPI2,
|
||||
perif.OTG_FS_GLOBAL,
|
||||
perif.OTG_FS_DEVICE,
|
||||
perif.OTG_FS_PWRCLK,
|
||||
);
|
||||
let (mut hw_rev, eth_pins, eth_mgmt_pins, usb, current_source_phy, ad7172_phy, max1968_phy, pd_mon_phy) =
|
||||
gpio::setup(
|
||||
clocks,
|
||||
perif.TIM4,
|
||||
perif.GPIOA,
|
||||
perif.GPIOB,
|
||||
perif.GPIOC,
|
||||
perif.GPIOD,
|
||||
perif.GPIOE,
|
||||
perif.SPI1,
|
||||
perif.SPI2,
|
||||
perif.SPI3,
|
||||
perif.OTG_FS_GLOBAL,
|
||||
perif.OTG_FS_DEVICE,
|
||||
perif.OTG_FS_PWRCLK,
|
||||
);
|
||||
|
||||
usb::State::setup(usb);
|
||||
|
||||
let mut laser = CurrentSource {
|
||||
phy: current_source_phy,
|
||||
setting: CurrentSourceSettings {
|
||||
output_current: 0.0,
|
||||
},
|
||||
};
|
||||
debug!("Setting up TEC");
|
||||
let tec_driver = MAX1968::new(max1968_phy, perif.ADC1, perif.ADC2, perif.DMA2);
|
||||
let mut thermostat = Thermostat::new(tec_driver, ad7172_phy);
|
||||
thermostat.setup();
|
||||
thermostat.calibrate_dac_value();
|
||||
thermostat.set_i(ElectricCurrent::new::<ampere>(0.0));
|
||||
|
||||
debug!("Setting up Laser Driver");
|
||||
let current_source = LdCtrl::new(current_source_phy);
|
||||
let mut laser = LdDrive::new(current_source, perif.ADC3, perif.TIM2.counter(&clocks), pd_mon_phy);
|
||||
laser.setup();
|
||||
laser.set_current(0.1).unwrap();
|
||||
laser.ld_open();
|
||||
laser.ld_set_i(ElectricCurrent::new::<ampere>(0.0));
|
||||
laser.set_pd_i_limit(ElectricCurrent::new::<milliampere>(2.5));
|
||||
laser.set_pd_mon_calibrated_vdda(thermostat.get_calibrated_vdda());
|
||||
|
||||
debug!("Setting up Internal Flash Driver");
|
||||
let flash_store = flash_store::store(perif.FLASH);
|
||||
|
||||
let mut ip_settings: IpSettings = IpSettings::default();
|
||||
let device_settings: DeviceSettings;
|
||||
match flash_store.read_value("Device") {
|
||||
Ok(Some(config)) => {
|
||||
device_settings = config;
|
||||
ip_settings = device_settings.ip_settings;
|
||||
debug!("Found Device Settings");
|
||||
}
|
||||
Ok(None) => {
|
||||
debug!("Flash does not have IP Settings");
|
||||
}
|
||||
Err(e) => {
|
||||
debug!("Cannot Store Flash: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
debug!("Setting up ETH");
|
||||
let mac_addr = hw_rev.get_mac_address();
|
||||
let ethernet_parts_in = stm32_eth::PartsIn {
|
||||
dma: perif.ETHERNET_DMA,
|
||||
mac: perif.ETHERNET_MAC,
|
||||
mmc: perif.ETHERNET_MMC,
|
||||
ptp: perif.ETHERNET_PTP,
|
||||
};
|
||||
ServerHandle::new(
|
||||
eth_pins,
|
||||
eth_mgmt_pins,
|
||||
ethernet_parts_in,
|
||||
clocks,
|
||||
perif.TIM5.counter(&clocks),
|
||||
mac_addr,
|
||||
ip_settings,
|
||||
);
|
||||
|
||||
debug!("Setting Watchdog");
|
||||
let mut wd = IndependentWatchdog::new(perif.IWDG);
|
||||
wd.start(WATCHDOG_PERIOD.millis());
|
||||
wd.feed();
|
||||
|
||||
info!("Kirdy setup complete");
|
||||
|
||||
wd
|
||||
(wd, flash_store, hw_rev, laser, thermostat)
|
||||
}
|
||||
|
||||
47
src/device/dfu.rs
Normal file
47
src/device/dfu.rs
Normal file
@@ -0,0 +1,47 @@
|
||||
use core::arch::asm;
|
||||
|
||||
use cortex_m_rt::pre_init;
|
||||
use stm32f4xx_hal::pac::{RCC, SYSCFG};
|
||||
|
||||
const DFU_TRIG_MSG: u32 = 0xDECAFBAD;
|
||||
|
||||
extern "C" {
|
||||
// This symbol comes from memory.x
|
||||
static mut _dfu_msg: u32;
|
||||
}
|
||||
|
||||
pub unsafe fn set_dfu_trigger() {
|
||||
_dfu_msg = DFU_TRIG_MSG;
|
||||
}
|
||||
|
||||
/// Called by reset handler in lib.rs immediately after reset.
|
||||
/// This function should not be called outside of reset handler as
|
||||
/// bootloader expects MCU to be in reset state when called.
|
||||
#[cfg(target_arch = "arm")]
|
||||
#[pre_init]
|
||||
unsafe fn __pre_init() {
|
||||
if _dfu_msg == DFU_TRIG_MSG {
|
||||
_dfu_msg = 0x00000000;
|
||||
|
||||
// Enable system config controller clock
|
||||
let rcc = &*RCC::ptr();
|
||||
rcc.apb2enr.modify(|_, w| w.syscfgen().set_bit());
|
||||
|
||||
// Bypass BOOT pins and remap bootloader to 0x00000000
|
||||
let syscfg = &*SYSCFG::ptr();
|
||||
syscfg.memrm.write(|w| w.mem_mode().bits(0b01));
|
||||
|
||||
// Impose instruction and memory barriers
|
||||
cortex_m::asm::isb();
|
||||
cortex_m::asm::dsb();
|
||||
|
||||
asm!(
|
||||
// Set stack pointer to bootloader location
|
||||
"LDR R0, =0x1FFF0000",
|
||||
"LDR SP,[R0, #0]",
|
||||
// Jump to bootloader
|
||||
"LDR R0,[R0, #4]",
|
||||
"BX R0",
|
||||
);
|
||||
}
|
||||
}
|
||||
58
src/device/flash_store.rs
Normal file
58
src/device/flash_store.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
use log::error;
|
||||
use sfkv::{Store, StoreBackend};
|
||||
use stm32f4xx_hal::{flash::{Error, FlashExt},
|
||||
pac::FLASH};
|
||||
|
||||
// Last flash sector is used to avoid overwriting the code in flash.
|
||||
pub const FLASH_SECTOR: u8 = 11;
|
||||
pub const FLASH_SECTOR_11_OFFSET: u32 = 0xE0000;
|
||||
|
||||
/// Only 16 KiB out of 128KiB in the Sector is used to save RAM
|
||||
pub const RESERVED_MEMORY: usize = 0x4000;
|
||||
static mut BACKUP_SPACE: [u8; RESERVED_MEMORY] = [0; RESERVED_MEMORY];
|
||||
|
||||
pub struct FlashBackend {
|
||||
flash: FLASH,
|
||||
}
|
||||
|
||||
fn get_offset() -> usize {
|
||||
FLASH_SECTOR_11_OFFSET as usize
|
||||
}
|
||||
|
||||
impl StoreBackend for FlashBackend {
|
||||
type Data = [u8];
|
||||
|
||||
fn data(&self) -> &Self::Data {
|
||||
&self.flash.read()[get_offset()..(get_offset() + RESERVED_MEMORY)]
|
||||
}
|
||||
|
||||
type Error = Error;
|
||||
fn erase(&mut self) -> Result<(), Self::Error> {
|
||||
self.flash.unlocked().erase(FLASH_SECTOR)
|
||||
}
|
||||
|
||||
fn program(&mut self, offset: usize, payload: &[u8]) -> Result<(), Self::Error> {
|
||||
self.flash.unlocked().program(get_offset() + offset, payload.iter())
|
||||
}
|
||||
|
||||
fn backup_space(&self) -> &'static mut [u8] {
|
||||
unsafe { BACKUP_SPACE.as_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
pub type FlashStore = Store<FlashBackend>;
|
||||
|
||||
pub fn store(flash: FLASH) -> FlashStore {
|
||||
let backend = FlashBackend { flash };
|
||||
let mut store = FlashStore::new(backend);
|
||||
|
||||
match store.get_bytes_used() {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
error!("corrupt store, erasing. error: {:?}", e);
|
||||
let _ = store.erase().map_err(|e| error!("flash erase failed: {:?}", e));
|
||||
}
|
||||
}
|
||||
|
||||
store
|
||||
}
|
||||
@@ -1,48 +1,71 @@
|
||||
use crate::laser_diode::current_sources::*;
|
||||
use fugit::RateExtU32;
|
||||
use stm32_eth::EthPins;
|
||||
use stm32f4xx_hal::{
|
||||
gpio::{gpioa::*, gpiob::*, gpioc::*, gpiog::*, GpioExt, Input},
|
||||
otg_fs::USB,
|
||||
pac::{GPIOA, GPIOB, GPIOC, GPIOD, GPIOG, OTG_FS_DEVICE, OTG_FS_GLOBAL, OTG_FS_PWRCLK, SPI2},
|
||||
rcc::Clocks,
|
||||
spi,
|
||||
spi::{NoMiso, Spi},
|
||||
};
|
||||
use stm32f4xx_hal::{gpio::{alt::otg_fs::{Dm, Dp},
|
||||
gpioa::*,
|
||||
gpiob::*,
|
||||
gpioc::*,
|
||||
GpioExt, Input, Speed},
|
||||
otg_fs::USB,
|
||||
pac::{GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, OTG_FS_DEVICE, OTG_FS_GLOBAL, OTG_FS_PWRCLK, SPI1, SPI2,
|
||||
SPI3, TIM4},
|
||||
rcc::Clocks,
|
||||
spi::{NoMiso, Spi},
|
||||
timer::{pwm::PwmExt, Channel1, Channel2, Channel3}};
|
||||
|
||||
pub type EthernetPins =
|
||||
EthPins<PA1<Input>, PA7<Input>, PB11<Input>, PG13<Input>, PB13<Input>, PC4<Input>, PC5<Input>>;
|
||||
use crate::{device::hw_rev::{HWRev, HwRevPins},
|
||||
laser_diode::{ld_ctrl::{self, LdCtrlPhy},
|
||||
ld_pwr_exc_protector::LdPwrExcProtectorPhy,
|
||||
max5719},
|
||||
net::net::EthernetMgmtPins,
|
||||
thermostat::{ad5680, ad7172,
|
||||
max1968::{self, MAX1968Phy, MAX1968PinSet, PWM_FREQ_KHZ}}};
|
||||
|
||||
pub type EthernetPins = EthPins<PA1<Input>, PA7<Input>, PB11<Input>, PB12<Input>, PB13<Input>, PC4<Input>, PC5<Input>>;
|
||||
|
||||
pub fn setup(
|
||||
clocks: Clocks,
|
||||
tim4: TIM4,
|
||||
gpioa: GPIOA,
|
||||
gpiob: GPIOB,
|
||||
gpioc: GPIOC,
|
||||
gpiod: GPIOD,
|
||||
gpiog: GPIOG,
|
||||
gpioe: GPIOE,
|
||||
spi1: SPI1,
|
||||
spi2: SPI2,
|
||||
spi3: SPI3,
|
||||
otg_fs_global: OTG_FS_GLOBAL,
|
||||
otg_fs_device: OTG_FS_DEVICE,
|
||||
otg_fs_pwrclk: OTG_FS_PWRCLK,
|
||||
) -> (
|
||||
HWRev,
|
||||
EthernetPins,
|
||||
EthernetMgmtPins,
|
||||
USB,
|
||||
CurrentSourcePhyConstruct<CurrentSourcePhyCh0>,
|
||||
// photo_diode_phy,
|
||||
// thermostat_phy
|
||||
LdCtrlPhy<ld_ctrl::Channel0>,
|
||||
ad7172::AdcPhy,
|
||||
MAX1968Phy<max1968::Channel0>,
|
||||
LdPwrExcProtectorPhy,
|
||||
) {
|
||||
let gpioa = gpioa.split();
|
||||
let gpiob = gpiob.split();
|
||||
let gpioc = gpioc.split();
|
||||
let gpiod = gpiod.split();
|
||||
let gpiog = gpiog.split();
|
||||
let gpioe = gpioe.split();
|
||||
|
||||
let mut hw_rev = HWRev::detect_hw_rev(HwRevPins {
|
||||
h0: gpioe.pe8.into_input(),
|
||||
h1: gpioe.pe9.into_input(),
|
||||
h2: gpioe.pe10.into_input(),
|
||||
h3: gpioe.pe11.into_input(),
|
||||
});
|
||||
|
||||
hw_rev.startup_delay_before_gpio_init();
|
||||
|
||||
let usb = USB {
|
||||
usb_global: otg_fs_global,
|
||||
usb_device: otg_fs_device,
|
||||
usb_pwrclk: otg_fs_pwrclk,
|
||||
pin_dm: gpioa.pa11.into_alternate(),
|
||||
pin_dp: gpioa.pa12.into_alternate(),
|
||||
pin_dm: Dm::PA11(gpioa.pa11.into_alternate()),
|
||||
pin_dp: Dp::PA12(gpioa.pa12.into_alternate()),
|
||||
hclk: clocks.hclk(),
|
||||
};
|
||||
|
||||
@@ -50,32 +73,92 @@ pub fn setup(
|
||||
ref_clk: gpioa.pa1,
|
||||
crs: gpioa.pa7,
|
||||
tx_en: gpiob.pb11,
|
||||
tx_d0: gpiog.pg13,
|
||||
tx_d0: gpiob.pb12,
|
||||
tx_d1: gpiob.pb13,
|
||||
rx_d0: gpioc.pc4,
|
||||
rx_d1: gpioc.pc5,
|
||||
};
|
||||
|
||||
let current_source_phy = CurrentSourcePhyConstruct {
|
||||
max5719_spi: Spi::new(
|
||||
spi2,
|
||||
(
|
||||
gpiob.pb10.into_alternate(),
|
||||
NoMiso {},
|
||||
gpiob.pb15.into_alternate(),
|
||||
let mut eth_mgmt_pins = EthernetMgmtPins {
|
||||
mdio: gpioa.pa2.into_alternate::<11>(),
|
||||
mdc: gpioc.pc1.into_alternate::<11>(),
|
||||
};
|
||||
eth_mgmt_pins.mdio.set_speed(Speed::VeryHigh);
|
||||
eth_mgmt_pins.mdc.set_speed(Speed::VeryHigh);
|
||||
|
||||
let current_source_phy = LdCtrlPhy {
|
||||
dac: max5719::Dac::new(
|
||||
Spi::new(
|
||||
spi2,
|
||||
(gpiob.pb10.into_alternate(), NoMiso::new(), gpiob.pb15.into_alternate()),
|
||||
max5719::SPI_MODE,
|
||||
max5719::SPI_CLOCK_MHZ.convert(),
|
||||
&clocks,
|
||||
),
|
||||
spi::Mode {
|
||||
polarity: spi::Polarity::IdleLow,
|
||||
phase: spi::Phase::CaptureOnFirstTransition,
|
||||
},
|
||||
10_u32.MHz(),
|
||||
&clocks,
|
||||
gpiod.pd8.into_push_pull_output(),
|
||||
gpiob.pb14.into_push_pull_output(),
|
||||
),
|
||||
max5719_load: gpiob.pb14.into_push_pull_output(),
|
||||
max5719_cs: gpiod.pd8.into_push_pull_output(),
|
||||
current_source_ldo_en: gpiod.pd9.into_push_pull_output(),
|
||||
current_source_short: gpioa.pa4.into_push_pull_output(),
|
||||
current_source_short_pin: gpioa.pa4.into_push_pull_output(),
|
||||
termination_status_pin: gpiod.pd7.internal_pull_up(true),
|
||||
};
|
||||
|
||||
(eth_pins, usb, current_source_phy)
|
||||
let pd_mon_phy = LdPwrExcProtectorPhy {
|
||||
_pd_mon_ch0: gpioa.pa3.into_analog(),
|
||||
pwr_en_ch0: gpiod.pd9.into_push_pull_output(),
|
||||
};
|
||||
|
||||
let pwm_chs = (
|
||||
Channel1::new(gpiob.pb6),
|
||||
Channel2::new(gpiob.pb7),
|
||||
Channel3::new(gpiob.pb8),
|
||||
);
|
||||
let (max_i_neg0, max_v0, max_i_pos0) = tim4.pwm_hz(pwm_chs, PWM_FREQ_KHZ.convert(), &clocks).split();
|
||||
|
||||
let max1968_phy = MAX1968Phy::new(MAX1968PinSet {
|
||||
dac: ad5680::Dac::new(
|
||||
Spi::new(
|
||||
spi1,
|
||||
(gpiob.pb3.into_alternate(), NoMiso::new(), gpiob.pb5.into_alternate()),
|
||||
ad5680::SPI_MODE,
|
||||
ad5680::SPI_CLOCK_MHZ.convert(),
|
||||
&clocks,
|
||||
),
|
||||
gpiob.pb4.into_push_pull_output(),
|
||||
),
|
||||
shdn: gpioa.pa5.into_push_pull_output(),
|
||||
vref_pin: gpioa.pa6.into_analog(),
|
||||
itec_pin: gpiob.pb1.into_analog(),
|
||||
dac_feedback_pin: gpioc.pc0.into_analog(),
|
||||
vtec_pin: gpiob.pb0.into_analog(),
|
||||
max_v: max_v0,
|
||||
max_i_pos: max_i_pos0,
|
||||
max_i_neg: max_i_neg0,
|
||||
});
|
||||
|
||||
let ad7172_phy = ad7172::Adc::new(
|
||||
Spi::new(
|
||||
spi3,
|
||||
(
|
||||
gpioc.pc10.into_alternate(),
|
||||
gpioc.pc11.into_alternate(),
|
||||
gpioc.pc12.into_alternate(),
|
||||
),
|
||||
ad7172::SPI_MODE,
|
||||
ad7172::SPI_CLOCK_MHZ.convert(),
|
||||
&clocks,
|
||||
),
|
||||
gpioa.pa15.into_push_pull_output(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
(
|
||||
hw_rev,
|
||||
eth_pins,
|
||||
eth_mgmt_pins,
|
||||
usb,
|
||||
current_source_phy,
|
||||
ad7172_phy,
|
||||
max1968_phy,
|
||||
pd_mon_phy,
|
||||
)
|
||||
}
|
||||
|
||||
68
src/device/hw_rev.rs
Normal file
68
src/device/hw_rev.rs
Normal file
@@ -0,0 +1,68 @@
|
||||
use crc::{Crc, CRC_24_BLE};
|
||||
use miniconf::Tree;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use stm32f4xx_hal::{gpio::{Input, PE10, PE11, PE8, PE9},
|
||||
signature};
|
||||
|
||||
use crate::device::sys_timer::sleep;
|
||||
|
||||
pub struct HwRevPins {
|
||||
pub h0: PE8<Input>,
|
||||
pub h1: PE9<Input>,
|
||||
pub h2: PE10<Input>,
|
||||
pub h3: PE11<Input>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Copy, Clone, Debug, Tree)]
|
||||
pub struct HWRev {
|
||||
pub major: u8,
|
||||
pub minor: u8,
|
||||
}
|
||||
|
||||
impl HWRev {
|
||||
pub fn detect_hw_rev(hwrev_pins: HwRevPins) -> Self {
|
||||
let (h0, h1, h2, h3) = (
|
||||
hwrev_pins.h0.is_high(),
|
||||
hwrev_pins.h1.is_high(),
|
||||
hwrev_pins.h2.is_high(),
|
||||
hwrev_pins.h3.is_high(),
|
||||
);
|
||||
match (h0, h1, h2, h3) {
|
||||
(true, true, true, true) => HWRev { major: 0, minor: 3 },
|
||||
(_, _, _, _) => HWRev { major: 0, minor: 0 },
|
||||
}
|
||||
}
|
||||
|
||||
/// On Rev0_3, during power up, digital power rails are stabilized way before analog power rails
|
||||
/// This causes improper initialization on any peripherals requiring calibrations
|
||||
/// See Issue #32 on Kirdy Hw Repo
|
||||
pub fn startup_delay_before_gpio_init(&mut self) {
|
||||
if self.major == 0 && self.minor == 3 {
|
||||
sleep(5000);
|
||||
}
|
||||
}
|
||||
|
||||
/// On Rev0_3, it lacks pre-allocated Mac Addresses accessible on PCB.
|
||||
/// This functions generate a random Mac Address with 96bit unique UUID inside STM32
|
||||
/// See Issue #36 on Kirdy Hw Repo
|
||||
pub fn get_mac_address(&mut self) -> [u8; 6] {
|
||||
if self.major == 0 && self.minor == 3 {
|
||||
let uid = signature::Uid::get();
|
||||
let mut uid_data: [u8; 12] = [0; 12];
|
||||
uid_data[0] = uid.x() as u8;
|
||||
uid_data[1] = (uid.x() >> 8) as u8;
|
||||
uid_data[2] = uid.y() as u8;
|
||||
uid_data[3] = (uid.y() >> 8) as u8;
|
||||
uid_data[4..11].clone_from_slice(uid.lot_num().as_bytes());
|
||||
|
||||
let crc: Crc<u32> = Crc::<u32>::new(&CRC_24_BLE);
|
||||
let mut digest = crc.digest();
|
||||
digest.update(&uid_data);
|
||||
let crc24 = digest.finalize();
|
||||
|
||||
[0x02, 0xE0, 0xD5, (crc24 >> 16) as u8, (crc24 >> 8) as u8, (crc24 as u8)]
|
||||
} else {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,13 +3,15 @@ pub fn init_log() {
|
||||
use super::usb;
|
||||
static USB_LOGGER: usb::Logger = usb::Logger;
|
||||
let _ = log::set_logger(&USB_LOGGER);
|
||||
log::set_max_level(log::LevelFilter::Debug);
|
||||
// log::set_max_level(log::LevelFilter::Debug);
|
||||
log::set_max_level(log::LevelFilter::Trace);
|
||||
}
|
||||
|
||||
#[cfg(feature = "RTT")]
|
||||
pub fn init_log() {
|
||||
use super::rtt_logger;
|
||||
use rtt_target::rtt_init_print;
|
||||
|
||||
use super::rtt_logger;
|
||||
static RTT_LOGGER: rtt_logger::Logger = rtt_logger::Logger;
|
||||
rtt_init_print!();
|
||||
let _ = log::set_logger(&RTT_LOGGER);
|
||||
@@ -18,8 +20,8 @@ pub fn init_log() {
|
||||
|
||||
#[cfg(feature = "semihosting")]
|
||||
pub fn init_log() {
|
||||
use cortex_m_log::log::{init, Logger};
|
||||
use cortex_m_log::printer::semihosting::{hio::HStdout, InterruptOk};
|
||||
use cortex_m_log::{log::{init, Logger},
|
||||
printer::semihosting::{hio::HStdout, InterruptOk}};
|
||||
use log::LevelFilter;
|
||||
static mut LOGGER: Option<Logger<InterruptOk<HStdout>>> = None;
|
||||
let logger = Logger {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
pub mod boot;
|
||||
pub mod dfu;
|
||||
pub mod flash_store;
|
||||
pub mod gpio;
|
||||
pub mod hw_rev;
|
||||
pub mod log_setup;
|
||||
pub mod rtt_logger;
|
||||
pub mod sys_timer;
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use core::cell::RefCell;
|
||||
use core::ops::Deref;
|
||||
use cortex_m::interrupt::Mutex;
|
||||
use cortex_m::peripheral::syst::SystClkSource;
|
||||
use core::{cell::RefCell, ops::Deref};
|
||||
|
||||
use cortex_m::{interrupt::Mutex, peripheral::syst::SystClkSource};
|
||||
use cortex_m_rt::exception;
|
||||
use stm32f4xx_hal::{pac::SYST, rcc::Clocks};
|
||||
use stm32f4xx_hal::{pac::{SYST, Peripherals}, rcc::Clocks};
|
||||
|
||||
/// Rate in Hz
|
||||
const TIMER_RATE: u32 = 1000;
|
||||
@@ -11,9 +10,13 @@ const TIMER_RATE: u32 = 1000;
|
||||
const TIMER_DELTA: u32 = 1000 / TIMER_RATE;
|
||||
/// Elapsed time in milliseconds
|
||||
static TIMER_MS: Mutex<RefCell<u32>> = Mutex::new(RefCell::new(0));
|
||||
static mut US_COUNT: u32 = 168;
|
||||
|
||||
/// Setup SysTick exception
|
||||
pub fn setup(mut syst: SYST, clocks: Clocks) {
|
||||
unsafe {
|
||||
US_COUNT = clocks.hclk().to_MHz()
|
||||
}
|
||||
syst.set_clock_source(SystClkSource::Core);
|
||||
syst.set_reload(clocks.hclk().to_Hz() / TIMER_RATE - 1);
|
||||
syst.enable_counter();
|
||||
@@ -33,6 +36,15 @@ pub fn now() -> u32 {
|
||||
cortex_m::interrupt::free(|cs| *TIMER_MS.borrow(cs).borrow().deref())
|
||||
}
|
||||
|
||||
/// Obtain current time in milliseconds + microseconds
|
||||
pub fn now_precise() -> (u32, u32) {
|
||||
let ms = now();
|
||||
unsafe {
|
||||
let us = (Peripherals::steal().STK.load.read().bits() - Peripherals::steal().STK.val.read().bits()) / US_COUNT;
|
||||
(ms, us)
|
||||
}
|
||||
}
|
||||
|
||||
/// block for `amount` milliseconds
|
||||
pub fn sleep(amount: u32) {
|
||||
if amount == 0 {
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
use core::{
|
||||
fmt::{self, Write},
|
||||
mem::MaybeUninit,
|
||||
};
|
||||
use core::{fmt::{self, Write},
|
||||
mem::MaybeUninit};
|
||||
|
||||
use cortex_m::interrupt::free;
|
||||
use log::{Log, Metadata, Record};
|
||||
use stm32f4xx_hal::{
|
||||
otg_fs::{UsbBus as Bus, USB},
|
||||
pac::{interrupt, Interrupt, NVIC},
|
||||
};
|
||||
use usb_device::{
|
||||
class_prelude::UsbBusAllocator,
|
||||
prelude::{UsbDevice, UsbDeviceBuilder, UsbVidPid},
|
||||
};
|
||||
use stm32f4xx_hal::{otg_fs::{UsbBus as Bus, USB},
|
||||
pac::{interrupt, Interrupt, NVIC}};
|
||||
use usb_device::{class_prelude::UsbBusAllocator,
|
||||
descriptor::lang_id,
|
||||
device::StringDescriptors,
|
||||
prelude::{UsbDevice, UsbDeviceBuilder, UsbVidPid}};
|
||||
use usbd_serial::SerialPort;
|
||||
|
||||
static mut EP_MEMORY: [u32; 1024] = [0; 1024];
|
||||
@@ -27,16 +24,20 @@ pub struct State {
|
||||
|
||||
impl State {
|
||||
pub fn setup(usb: USB) {
|
||||
unsafe { BUS.write(Bus::new(usb, &mut EP_MEMORY)) };
|
||||
unsafe { BUS.write(Bus::new(usb, EP_MEMORY.as_mut())) };
|
||||
|
||||
let str_descriptor = StringDescriptors::new(lang_id::LangID::EN)
|
||||
.manufacturer("M-Labs")
|
||||
.product("Kirdy");
|
||||
|
||||
let bus = unsafe { BUS.assume_init_ref() };
|
||||
let serial = SerialPort::new(bus);
|
||||
let dev = UsbDeviceBuilder::new(bus, UsbVidPid(0x16c0, 0x27dd))
|
||||
.manufacturer("M-Labs")
|
||||
.product("thermostat")
|
||||
.device_release(0x20)
|
||||
.self_powered(true)
|
||||
.device_class(usbd_serial::USB_CLASS_CDC)
|
||||
.strings(&[str_descriptor])
|
||||
.unwrap()
|
||||
.build();
|
||||
|
||||
free(|_| unsafe {
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
use stm32f4xx_hal::{
|
||||
gpio::{gpioa::*, gpiob::*, gpiod::*, Alternate, Output, PushPull, PD9},
|
||||
hal::{blocking::spi::Write, digital::v2::OutputPin},
|
||||
pac::SPI2,
|
||||
spi::{NoMiso, Spi, TransferModeNormal},
|
||||
};
|
||||
|
||||
use crate::device::sys_timer::sleep;
|
||||
pub trait CurrentSourcePhy {
|
||||
type CurrentSourceLdoEn: OutputPin;
|
||||
type CurrentSourceShort: OutputPin;
|
||||
type Max5719Load: OutputPin;
|
||||
type Max5719Cs: OutputPin;
|
||||
type Max5719Spi: Write<u8>;
|
||||
}
|
||||
|
||||
pub struct CurrentSourcePhyConstruct<C: CurrentSourcePhy> {
|
||||
pub max5719_spi: C::Max5719Spi,
|
||||
pub max5719_load: C::Max5719Load,
|
||||
pub max5719_cs: C::Max5719Cs,
|
||||
pub current_source_ldo_en: C::CurrentSourceLdoEn,
|
||||
pub current_source_short: C::CurrentSourceShort,
|
||||
}
|
||||
pub struct CurrentSourceSettings {
|
||||
pub output_current: f32,
|
||||
}
|
||||
pub struct CurrentSource<C: CurrentSourcePhy> {
|
||||
pub phy: CurrentSourcePhyConstruct<C>,
|
||||
pub setting: CurrentSourceSettings,
|
||||
}
|
||||
|
||||
pub struct CurrentSourcePhyCh0;
|
||||
|
||||
impl CurrentSourcePhy for CurrentSourcePhyCh0 {
|
||||
type CurrentSourceLdoEn = PD9<Output<PushPull>>;
|
||||
type CurrentSourceShort = PA4<Output<PushPull>>;
|
||||
type Max5719Load = PB14<Output<PushPull>>;
|
||||
type Max5719Cs = PD8<Output<PushPull>>;
|
||||
type Max5719Spi =
|
||||
Spi<SPI2, (PB10<Alternate<5>>, NoMiso, PB15<Alternate<5>>), TransferModeNormal>;
|
||||
}
|
||||
|
||||
impl<C: CurrentSourcePhy> CurrentSource<C> {
|
||||
pub fn setup(&mut self) {
|
||||
let _ = self.phy.max5719_load.set_high();
|
||||
let _ = self.phy.max5719_cs.set_high();
|
||||
let _ = self.phy.current_source_ldo_en.set_high();
|
||||
sleep(10_u32);
|
||||
let _ = self.phy.current_source_short.set_high();
|
||||
sleep(10_u32);
|
||||
}
|
||||
|
||||
pub fn set_current(
|
||||
&mut self,
|
||||
current: f32,
|
||||
) -> Result<(), <<C as CurrentSourcePhy>::Max5719Spi as Write<u8>>::Error> {
|
||||
let _ = self.phy.max5719_load.set_high();
|
||||
let _ = self.phy.max5719_cs.set_low();
|
||||
self.setting.output_current = current * 10.0 / 0.75;
|
||||
let word = (((self.setting.output_current / 4.096) * 1048576.0) as u32) << 4;
|
||||
let mut buf = [
|
||||
((word >> 16) & 0xFF) as u8,
|
||||
((word >> 8) & 0xFF) as u8,
|
||||
((word >> 0) & 0xFF) as u8,
|
||||
];
|
||||
self.phy.max5719_spi.write(&mut buf)?;
|
||||
let _ = self.phy.max5719_cs.set_high();
|
||||
let _ = self.phy.max5719_load.set_low();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
311
src/laser_diode/laser_diode.rs
Normal file
311
src/laser_diode/laser_diode.rs
Normal file
@@ -0,0 +1,311 @@
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use log::info;
|
||||
use miniconf::Tree;
|
||||
use num_traits::Zero;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use stm32f4xx_hal::{pac::{ADC3, TIM2},
|
||||
timer::CounterUs};
|
||||
use uom::si::{electric_current::{ampere, milliampere},
|
||||
f32::{ElectricCurrent, ElectricPotential, ElectricalConductance, ElectricalResistance, Power},
|
||||
power::milliwatt};
|
||||
|
||||
use crate::{device::sys_timer::sleep,
|
||||
laser_diode::{ld_ctrl::{Impedance50Ohm, LdCtrl},
|
||||
ld_current_out_ctrl_timer::LdCurrentOutCtrlTimer,
|
||||
ld_pwr_exc_protector::{self, LdPwrExcProtector},
|
||||
pd_mon_params}};
|
||||
|
||||
impl Settings {
|
||||
pub const LD_CURRENT_MAX: ElectricCurrent = ElectricCurrent {
|
||||
dimension: PhantomData,
|
||||
units: PhantomData,
|
||||
value: 0.3,
|
||||
};
|
||||
pub const DAC_OUT_V_MAX: ElectricPotential = ElectricPotential {
|
||||
dimension: PhantomData,
|
||||
units: PhantomData,
|
||||
value: 4.096,
|
||||
};
|
||||
|
||||
const LD_DRIVE_TRANSIMPEDANCE: ElectricalResistance = ElectricalResistance {
|
||||
dimension: PhantomData,
|
||||
units: PhantomData,
|
||||
value: 10.0 / 0.75,
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Clone, Copy, Debug, Tree)]
|
||||
struct Settings {
|
||||
pwr_on: bool,
|
||||
default_pwr_on: bool,
|
||||
ld_drive_current: ElectricCurrent,
|
||||
pd_mon_params: pd_mon_params::Parameters,
|
||||
ld_pwr_limit: Power,
|
||||
ld_terms_short: bool,
|
||||
incoming_pd_mon_params: pd_mon_params::Parameters,
|
||||
}
|
||||
|
||||
impl Default for Settings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
pwr_on: false,
|
||||
default_pwr_on: false,
|
||||
ld_drive_current: ElectricCurrent::new::<milliampere>(0.0),
|
||||
pd_mon_params: pd_mon_params::Parameters::default(),
|
||||
incoming_pd_mon_params: pd_mon_params::Parameters::default(),
|
||||
ld_pwr_limit: Power::new::<milliwatt>(0.0),
|
||||
ld_terms_short: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Copy, Clone, Debug, Tree)]
|
||||
pub struct StatusReport {
|
||||
pwr_on: bool,
|
||||
pwr_excursion: bool,
|
||||
ld_i_set: ElectricCurrent,
|
||||
pd_i: ElectricCurrent,
|
||||
pd_pwr: Power,
|
||||
term_50ohm: Impedance50Ohm,
|
||||
}
|
||||
|
||||
pub struct LdDrive {
|
||||
ctrl: LdCtrl,
|
||||
settings: Settings,
|
||||
}
|
||||
|
||||
impl LdDrive {
|
||||
pub fn new(
|
||||
current_source: LdCtrl,
|
||||
pins_adc: ADC3,
|
||||
tim2: CounterUs<TIM2>,
|
||||
phy: ld_pwr_exc_protector::LdPwrExcProtectorPhy,
|
||||
) -> Self {
|
||||
LdPwrExcProtector::setup(pins_adc, phy);
|
||||
LdCurrentOutCtrlTimer::setup(tim2);
|
||||
|
||||
LdDrive {
|
||||
ctrl: current_source,
|
||||
settings: Settings::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setup(&mut self) {
|
||||
LdPwrExcProtector::pwr_off();
|
||||
self.ctrl.set_i(
|
||||
ElectricCurrent::new::<milliampere>(0.0),
|
||||
Settings::LD_DRIVE_TRANSIMPEDANCE,
|
||||
Settings::DAC_OUT_V_MAX,
|
||||
);
|
||||
LdCurrentOutCtrlTimer::reset();
|
||||
self.ld_short();
|
||||
}
|
||||
|
||||
pub fn ld_short(&mut self) {
|
||||
self.ctrl.ld_short_enable();
|
||||
self.settings.ld_terms_short = true;
|
||||
}
|
||||
|
||||
pub fn ld_open(&mut self) {
|
||||
self.ctrl.ld_short_disable();
|
||||
self.settings.ld_terms_short = false;
|
||||
}
|
||||
|
||||
pub fn power_up(&mut self) {
|
||||
let prev_i_set = self.settings.ld_drive_current;
|
||||
LdCurrentOutCtrlTimer::reset();
|
||||
let _ = self.ctrl.set_i(
|
||||
ElectricCurrent::new::<milliampere>(0.0),
|
||||
Settings::LD_DRIVE_TRANSIMPEDANCE,
|
||||
Settings::DAC_OUT_V_MAX,
|
||||
);
|
||||
// Wait for the DAC to reset its voltage back to 0V
|
||||
sleep(35);
|
||||
LdPwrExcProtector::pwr_on | ||||