mirror of
https://github.com/Djeeberjr/fw-anwesenheit.git
synced 2026-05-01 02:59:09 +00:00
Compare commits
31 Commits
v1.0
...
59d87eb199
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59d87eb199 | ||
|
|
630fc4aaf9 | ||
| 21480cef4f | |||
|
|
fabb14de86 | ||
|
|
6a2d448f86 | ||
|
|
fc7bd8b089 | ||
|
|
3117c55b1c | ||
|
|
593d98df74 | ||
|
|
fa6d1f024c | ||
|
|
36dc52f464 | ||
|
|
6831d7776c | ||
| a015d6b983 | |||
|
|
1ae5250449 | ||
|
|
2f502e908e | ||
|
|
5950279dc4 | ||
| fe6540ca3d | |||
|
|
161ebf9bd2 | ||
|
|
c1b54920ff | ||
|
|
5a2beb1fb3 | ||
|
|
d5c20bf348 | ||
|
|
49027fed99 | ||
|
|
4dda9548d3 | ||
|
|
46e207bd2a | ||
|
|
8cb118e0ee | ||
|
|
9b4df77112 | ||
| 23bb1126a6 | |||
| a97e9c8080 | |||
| 4b39529a65 | |||
| c91d2f070f | |||
| 2e6094ea11 | |||
| 43e964b5a0 |
14
.cargo/config.toml
Normal file
14
.cargo/config.toml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[target.riscv32imac-unknown-none-elf]
|
||||||
|
runner = "espflash flash --monitor --chip esp32c6"
|
||||||
|
|
||||||
|
[build]
|
||||||
|
rustflags = [
|
||||||
|
# Required to obtain backtraces (e.g. when using the "esp-backtrace" crate.)
|
||||||
|
# NOTE: May negatively impact performance of produced code
|
||||||
|
"-C", "force-frame-pointers",
|
||||||
|
]
|
||||||
|
|
||||||
|
target = "riscv32imac-unknown-none-elf"
|
||||||
|
|
||||||
|
[unstable]
|
||||||
|
build-std = ["alloc", "core"]
|
||||||
Binary file not shown.
Binary file not shown.
BIN
3d_print/LWL.3mf
BIN
3d_print/LWL.3mf
Binary file not shown.
Binary file not shown.
2404
Cargo.lock
generated
2404
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
93
Cargo.toml
93
Cargo.toml
@@ -3,24 +3,81 @@ name = "fw-anwesenheit"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[features]
|
[[bin]]
|
||||||
default = []
|
name = "fw-anwesenheit"
|
||||||
mock_pi = [] # Enable mocking of the rpi hardware
|
path = "./src/main.rs"
|
||||||
|
test = false
|
||||||
|
doctest = false
|
||||||
|
bench = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
chrono = { version = "0.4.40", features = ["serde"] }
|
esp-bootloader-esp-idf = "0.1.0"
|
||||||
gpio = "0.4.1"
|
embassy-net = { version = "0.7.0", features = [
|
||||||
regex = "1.11.1"
|
"dhcpv4",
|
||||||
serde = { version = "1.0.219", features = ["derive"] }
|
"medium-ethernet",
|
||||||
serde_json = "1.0.140"
|
"tcp",
|
||||||
rocket = { version = "0.5.1", features = ["json"] }
|
"udp",
|
||||||
tokio = { version = "1.44.2", features = ["full"] }
|
] }
|
||||||
rust-embed = "8.7.0"
|
embedded-hal = "=1.0.0"
|
||||||
log = "0.4.27"
|
embedded-io = "0.6.1"
|
||||||
simplelog = "0.12.2"
|
embedded-io-async = "0.6.1"
|
||||||
rppal = { version = "0.22.1", features = ["hal"] }
|
esp-alloc = "0.8.0"
|
||||||
smart-leds = "0.3"
|
esp-hal = { version = "1.0.0-beta.1", features = ["esp32c6", "unstable"] }
|
||||||
ws2812-spi = "0.3"
|
smoltcp = { version = "0.12.0", default-features = false, features = [
|
||||||
rgb = "0.8.50"
|
"medium-ethernet",
|
||||||
anyhow = "1.0.98"
|
"multicast",
|
||||||
|
"proto-dhcpv4",
|
||||||
|
"proto-dns",
|
||||||
|
"proto-ipv4",
|
||||||
|
"socket-dns",
|
||||||
|
"socket-icmp",
|
||||||
|
"socket-raw",
|
||||||
|
"socket-tcp",
|
||||||
|
"socket-udp",
|
||||||
|
] }
|
||||||
|
# for more networking protocol support see https://crates.io/crates/edge-net
|
||||||
|
bleps = { git = "https://github.com/bjoernQ/bleps", package = "bleps", rev = "a5148d8ae679e021b78f53fd33afb8bb35d0b62e", features = [
|
||||||
|
"async",
|
||||||
|
"macros",
|
||||||
|
] }
|
||||||
|
critical-section = "1.2.0"
|
||||||
|
embassy-executor = { version = "0.7.0", features = ["nightly"] }
|
||||||
|
embassy-time = { version = "0.4.0", features = ["generic-queue-8"] }
|
||||||
|
esp-hal-embassy = { version = "0.9.0", features = ["esp32c6"] }
|
||||||
|
esp-wifi = { version = "0.15.0", features = [
|
||||||
|
"wifi",
|
||||||
|
"builtin-scheduler",
|
||||||
|
"esp-alloc",
|
||||||
|
"esp32c6",
|
||||||
|
"log-04",
|
||||||
|
] }
|
||||||
|
heapless = { version = "0.8.0", default-features = false }
|
||||||
|
static_cell = { version = "2.1.0", features = ["nightly"] }
|
||||||
|
esp-println = { version = "0.15.0", features = ["esp32c6", "log-04"] }
|
||||||
|
log = { version = "0.4" }
|
||||||
|
edge-dhcp = { version = "0.6.0", features = ["log"] }
|
||||||
|
edge-nal = "0.5.0"
|
||||||
|
edge-nal-embassy = { version = "0.6.0", features = ["log"] }
|
||||||
|
picoserve = { version = "0.16.0", features = ["embassy", "log"] }
|
||||||
|
embassy-sync = { version = "0.7.0", features = ["log"] }
|
||||||
|
ds3231 = { version = "0.3.0", features = ["async", "temperature_f32"] }
|
||||||
|
chrono = { version = "0.4.41", default-features = false }
|
||||||
|
dir-embed = "0.3.0"
|
||||||
|
embedded-sdmmc-dev = "0.8.2"
|
||||||
|
esp-hal-smartled = { git = "https://github.com/esp-rs/esp-hal-community.git", package = "esp-hal-smartled", branch = "main", features = ["esp32c6"]}
|
||||||
|
smart-leds = "0.4.0"
|
||||||
|
serde = { version = "1.0.219", default-features = false, features = ["derive", "alloc"] }
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
# Rust debug is too slow.
|
||||||
|
# For debug builds always builds with some optimization
|
||||||
|
opt-level = "s"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
codegen-units = 1 # LLVM can perform better optimizations using a single thread
|
||||||
|
debug = 2
|
||||||
|
debug-assertions = false
|
||||||
|
incremental = false
|
||||||
|
lto = 'fat'
|
||||||
|
opt-level = 's'
|
||||||
|
overflow-checks = false
|
||||||
|
|||||||
61
Makefile
61
Makefile
@@ -1,61 +0,0 @@
|
|||||||
PACKAGE_NAME := fwa
|
|
||||||
VERSION := 1.0
|
|
||||||
ARCH := armhf
|
|
||||||
BUILD_DIR := build
|
|
||||||
DEB_DIR := $(BUILD_DIR)/$(PACKAGE_NAME)-$(VERSION)
|
|
||||||
BIN_DIR := $(DEB_DIR)/usr/local/bin
|
|
||||||
SERVICE_DIR := $(DEB_DIR)/lib/systemd/system
|
|
||||||
CONFIG_DIR := $(DEB_DIR)/etc
|
|
||||||
PM3_DIR := $(DEB_DIR)/usr/share/pm3
|
|
||||||
|
|
||||||
.PHONY: all build clean package prepare_package
|
|
||||||
|
|
||||||
all: package
|
|
||||||
|
|
||||||
build: $(BUILD_DIR)/fwa
|
|
||||||
|
|
||||||
$(BUILD_DIR)/fwa: web/dist
|
|
||||||
cross build --release --target arm-unknown-linux-gnueabihf
|
|
||||||
cp ./target/arm-unknown-linux-gnueabihf/release/fw-anwesenheit $@
|
|
||||||
|
|
||||||
prepare_package: $(DEB_DIR)/DEBIAN $(BIN_DIR)/fwa
|
|
||||||
mkdir -p $(SERVICE_DIR)
|
|
||||||
cp ./service/fwa.service $(SERVICE_DIR)/
|
|
||||||
cp ./service/fwa-fail.service $(SERVICE_DIR)/
|
|
||||||
|
|
||||||
mkdir -p $(CONFIG_DIR)
|
|
||||||
cp ./service/fwa.env $(CONFIG_DIR)/
|
|
||||||
|
|
||||||
mkdir -p $(PM3_DIR)
|
|
||||||
cp -r ./pre-compiled/* $(PM3_DIR)/
|
|
||||||
|
|
||||||
mkdir -p $(DEB_DIR)/var/lib/fwa/
|
|
||||||
|
|
||||||
$(BIN_DIR)/fwa: $(BUILD_DIR)/fwa
|
|
||||||
mkdir -p $(BIN_DIR)
|
|
||||||
cp $< $@
|
|
||||||
|
|
||||||
|
|
||||||
$(DEB_DIR)/DEBIAN:
|
|
||||||
mkdir -p $(DEB_DIR)/DEBIAN
|
|
||||||
echo "Package: $(PACKAGE_NAME)" > $(DEB_DIR)/DEBIAN/control
|
|
||||||
echo "Version: $(VERSION)" >> $(DEB_DIR)/DEBIAN/control
|
|
||||||
echo "Section: utils" >> $(DEB_DIR)/DEBIAN/control
|
|
||||||
echo "Priority: optional" >> $(DEB_DIR)/DEBIAN/control
|
|
||||||
echo "Architecture: $(ARCH)" >> $(DEB_DIR)/DEBIAN/control
|
|
||||||
echo "Depends: libc6 (>= 2.28)" >> $(DEB_DIR)/DEBIAN/control
|
|
||||||
echo "Maintainer: Niklas Kapelle <niklas@kapelle.org>" >> $(DEB_DIR)/DEBIAN/control
|
|
||||||
echo "Description: Feuerwehr anwesenheit" >> $(DEB_DIR)/DEBIAN/control
|
|
||||||
|
|
||||||
echo "/etc/fwa.env" > $(DEB_DIR)/DEBIAN/conffiles
|
|
||||||
|
|
||||||
web/dist:
|
|
||||||
(cd web && npm run build)
|
|
||||||
|
|
||||||
package: prepare_package
|
|
||||||
dpkg-deb --build $(DEB_DIR)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
cargo clean
|
|
||||||
rm -rf web/dist
|
|
||||||
rm -rf $(BUILD_DIR)
|
|
||||||
66
build.rs
Normal file
66
build.rs
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
use std::env;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
linker_be_nice();
|
||||||
|
// make sure linkall.x is the last linker script (otherwise might cause problems with flip-link)
|
||||||
|
println!("cargo:rustc-link-arg=-Tlinkall.x");
|
||||||
|
save_build_time();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn save_build_time() {
|
||||||
|
let out_dir = env::var("OUT_DIR").unwrap();
|
||||||
|
let dest_path = Path::new(&out_dir).join("build_time.rs");
|
||||||
|
let system_time = std::time::SystemTime::now();
|
||||||
|
let unix_time = system_time
|
||||||
|
.duration_since(std::time::UNIX_EPOCH)
|
||||||
|
.unwrap()
|
||||||
|
.as_secs();
|
||||||
|
println!("cargo:rustc-env=BUILD_TIME={}", unix_time);
|
||||||
|
let content = format!(
|
||||||
|
"/// compile time as UNIX-Timestamp (seconds since 1970-01-01)
|
||||||
|
pub const BUILD_UNIX_TIME: u64 = {};",
|
||||||
|
unix_time
|
||||||
|
);
|
||||||
|
let mut f = File::create(dest_path).unwrap();
|
||||||
|
f.write_all(content.as_bytes()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn linker_be_nice() {
|
||||||
|
let args: Vec<String> = std::env::args().collect();
|
||||||
|
if args.len() > 1 {
|
||||||
|
let kind = &args[1];
|
||||||
|
let what = &args[2];
|
||||||
|
|
||||||
|
match kind.as_str() {
|
||||||
|
"undefined-symbol" => match what.as_str() {
|
||||||
|
"_defmt_timestamp" => {
|
||||||
|
eprintln!();
|
||||||
|
eprintln!(
|
||||||
|
"💡 `defmt` not found - make sure `defmt.x` is added as a linker script and you have included `use defmt_rtt as _;`"
|
||||||
|
);
|
||||||
|
eprintln!();
|
||||||
|
}
|
||||||
|
"_stack_start" => {
|
||||||
|
eprintln!();
|
||||||
|
eprintln!("💡 Is the linker script `linkall.x` missing?");
|
||||||
|
eprintln!();
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
|
// we don't have anything helpful for "missing-lib" yet
|
||||||
|
_ => {
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"cargo:rustc-link-arg=--error-handling-script={}",
|
||||||
|
std::env::current_exe().unwrap().display()
|
||||||
|
);
|
||||||
|
}
|
||||||
24
buzzer.py
24
buzzer.py
@@ -1,24 +0,0 @@
|
|||||||
import RPi.GPIO as GPIO
|
|
||||||
import time
|
|
||||||
|
|
||||||
BUZZER_PIN = 26
|
|
||||||
|
|
||||||
def beep(frequency, duration):
|
|
||||||
pwm = GPIO.PWM(BUZZER_PIN, frequency)
|
|
||||||
pwm.start(50) # 50 % duty cycle
|
|
||||||
time.sleep(duration)
|
|
||||||
pwm.stop()
|
|
||||||
|
|
||||||
def main():
|
|
||||||
GPIO.setmode(GPIO.BCM)
|
|
||||||
GPIO.setup(BUZZER_PIN, GPIO.OUT)
|
|
||||||
|
|
||||||
try:
|
|
||||||
beep(523, 0.3) # C5
|
|
||||||
beep(659, 0.3) # E5
|
|
||||||
beep(784, 0.3) # G5
|
|
||||||
finally:
|
|
||||||
GPIO.cleanup()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 13 KiB |
@@ -1,34 +0,0 @@
|
|||||||
@startuml
|
|
||||||
actor user
|
|
||||||
|
|
||||||
|
|
||||||
main -> pm3 :start
|
|
||||||
loop
|
|
||||||
pm3 -> pm3 : look for HITAG
|
|
||||||
end
|
|
||||||
|
|
||||||
user -> pm3 :show HITAG
|
|
||||||
|
|
||||||
pm3 -> parser : parse ID
|
|
||||||
parser -> pm3 : return ID
|
|
||||||
|
|
||||||
pm3 --> main : send ID
|
|
||||||
|
|
||||||
loop
|
|
||||||
main -> main : look for IDs
|
|
||||||
end
|
|
||||||
|
|
||||||
main -> idstore : send ID
|
|
||||||
idstore -> System : ask for day
|
|
||||||
alt
|
|
||||||
System -> idstore : return attendence_day
|
|
||||||
else
|
|
||||||
create collections attendence_day
|
|
||||||
idstore -> attendence_day : create new attendence_day
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
idstore -> attendence_day : add ID
|
|
||||||
attendence_day -> system : save json
|
|
||||||
|
|
||||||
@enduml
|
|
||||||
105757
pcb/fp-info-cache
Normal file
105757
pcb/fp-info-cache
Normal file
File diff suppressed because it is too large
Load Diff
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-15_233643.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-15_233643.zip
Normal file
Binary file not shown.
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-15_234143.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-15_234143.zip
Normal file
Binary file not shown.
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-15_234647.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-15_234647.zip
Normal file
Binary file not shown.
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-15_235651.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-15_235651.zip
Normal file
Binary file not shown.
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-16_000203.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-16_000203.zip
Normal file
Binary file not shown.
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-16_001607.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-16_001607.zip
Normal file
Binary file not shown.
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-16_002317.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-16_002317.zip
Normal file
Binary file not shown.
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-19_173350.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-19_173350.zip
Normal file
Binary file not shown.
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-19_180034.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-19_180034.zip
Normal file
Binary file not shown.
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-21_164706.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-21_164706.zip
Normal file
Binary file not shown.
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-21_171858.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-21_171858.zip
Normal file
Binary file not shown.
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-21_180710.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-21_180710.zip
Normal file
Binary file not shown.
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-21_182538.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-21_182538.zip
Normal file
Binary file not shown.
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-21_190146.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-21_190146.zip
Normal file
Binary file not shown.
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-22_202808.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-22_202808.zip
Normal file
Binary file not shown.
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-22_203420.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-22_203420.zip
Normal file
Binary file not shown.
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-22_204627.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-22_204627.zip
Normal file
Binary file not shown.
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-22_211436.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-22_211436.zip
Normal file
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
0
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,125 @@
|
|||||||
|
{
|
||||||
|
"board": {
|
||||||
|
"active_layer": 0,
|
||||||
|
"active_layer_preset": "",
|
||||||
|
"auto_track_width": false,
|
||||||
|
"hidden_netclasses": [],
|
||||||
|
"hidden_nets": [],
|
||||||
|
"high_contrast_mode": 0,
|
||||||
|
"net_color_mode": 1,
|
||||||
|
"opacity": {
|
||||||
|
"images": 1.0,
|
||||||
|
"pads": 1.0,
|
||||||
|
"shapes": 1.0,
|
||||||
|
"tracks": 1.0,
|
||||||
|
"vias": 1.0,
|
||||||
|
"zones": 1.0
|
||||||
|
},
|
||||||
|
"selection_filter": {
|
||||||
|
"dimensions": true,
|
||||||
|
"footprints": true,
|
||||||
|
"graphics": true,
|
||||||
|
"keepouts": true,
|
||||||
|
"lockedItems": false,
|
||||||
|
"otherItems": true,
|
||||||
|
"pads": true,
|
||||||
|
"text": true,
|
||||||
|
"tracks": true,
|
||||||
|
"vias": true,
|
||||||
|
"zones": true
|
||||||
|
},
|
||||||
|
"visible_items": [
|
||||||
|
12
|
||||||
|
],
|
||||||
|
"visible_layers": "fffffff_ffffffff",
|
||||||
|
"zone_display_mode": 0
|
||||||
|
},
|
||||||
|
"git": {
|
||||||
|
"repo_password": "",
|
||||||
|
"repo_type": "",
|
||||||
|
"repo_username": "",
|
||||||
|
"ssh_key": ""
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"filename": "fw-anwesenheit.kicad_prl",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"net_inspector_panel": {
|
||||||
|
"col_hidden": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
],
|
||||||
|
"col_order": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9,
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13
|
||||||
|
],
|
||||||
|
"col_widths": [
|
||||||
|
162,
|
||||||
|
147,
|
||||||
|
91,
|
||||||
|
72,
|
||||||
|
91,
|
||||||
|
100,
|
||||||
|
91,
|
||||||
|
76,
|
||||||
|
91,
|
||||||
|
91,
|
||||||
|
91,
|
||||||
|
91,
|
||||||
|
91,
|
||||||
|
91
|
||||||
|
],
|
||||||
|
"custom_group_rules": [],
|
||||||
|
"expanded_rows": [],
|
||||||
|
"filter_by_net_name": true,
|
||||||
|
"filter_by_netclass": true,
|
||||||
|
"filter_text": "",
|
||||||
|
"group_by_constraint": false,
|
||||||
|
"group_by_netclass": false,
|
||||||
|
"show_unconnected_nets": false,
|
||||||
|
"show_zero_pad_nets": false,
|
||||||
|
"sort_ascending": true,
|
||||||
|
"sorting_column": 0
|
||||||
|
},
|
||||||
|
"open_jobsets": [],
|
||||||
|
"project": {
|
||||||
|
"files": []
|
||||||
|
},
|
||||||
|
"schematic": {
|
||||||
|
"selection_filter": {
|
||||||
|
"graphics": true,
|
||||||
|
"images": true,
|
||||||
|
"labels": true,
|
||||||
|
"lockedItems": false,
|
||||||
|
"otherItems": true,
|
||||||
|
"pins": true,
|
||||||
|
"symbols": true,
|
||||||
|
"text": true,
|
||||||
|
"wires": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,630 @@
|
|||||||
|
{
|
||||||
|
"board": {
|
||||||
|
"3dviewports": [],
|
||||||
|
"design_settings": {
|
||||||
|
"defaults": {
|
||||||
|
"apply_defaults_to_fp_fields": false,
|
||||||
|
"apply_defaults_to_fp_shapes": false,
|
||||||
|
"apply_defaults_to_fp_text": false,
|
||||||
|
"board_outline_line_width": 0.05,
|
||||||
|
"copper_line_width": 0.2,
|
||||||
|
"copper_text_italic": false,
|
||||||
|
"copper_text_size_h": 1.5,
|
||||||
|
"copper_text_size_v": 1.5,
|
||||||
|
"copper_text_thickness": 0.3,
|
||||||
|
"copper_text_upright": false,
|
||||||
|
"courtyard_line_width": 0.05,
|
||||||
|
"dimension_precision": 4,
|
||||||
|
"dimension_units": 3,
|
||||||
|
"dimensions": {
|
||||||
|
"arrow_length": 1270000,
|
||||||
|
"extension_offset": 500000,
|
||||||
|
"keep_text_aligned": true,
|
||||||
|
"suppress_zeroes": true,
|
||||||
|
"text_position": 0,
|
||||||
|
"units_format": 0
|
||||||
|
},
|
||||||
|
"fab_line_width": 0.1,
|
||||||
|
"fab_text_italic": false,
|
||||||
|
"fab_text_size_h": 1.0,
|
||||||
|
"fab_text_size_v": 1.0,
|
||||||
|
"fab_text_thickness": 0.15,
|
||||||
|
"fab_text_upright": false,
|
||||||
|
"other_line_width": 0.1,
|
||||||
|
"other_text_italic": false,
|
||||||
|
"other_text_size_h": 1.0,
|
||||||
|
"other_text_size_v": 1.0,
|
||||||
|
"other_text_thickness": 0.15,
|
||||||
|
"other_text_upright": false,
|
||||||
|
"pads": {
|
||||||
|
"drill": 0.0,
|
||||||
|
"height": 1.7,
|
||||||
|
"width": 1.7
|
||||||
|
},
|
||||||
|
"silk_line_width": 0.1,
|
||||||
|
"silk_text_italic": false,
|
||||||
|
"silk_text_size_h": 1.0,
|
||||||
|
"silk_text_size_v": 1.0,
|
||||||
|
"silk_text_thickness": 0.1,
|
||||||
|
"silk_text_upright": false,
|
||||||
|
"zones": {
|
||||||
|
"min_clearance": 0.5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"diff_pair_dimensions": [
|
||||||
|
{
|
||||||
|
"gap": 0.0,
|
||||||
|
"via_gap": 0.0,
|
||||||
|
"width": 0.0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"drc_exclusions": [],
|
||||||
|
"meta": {
|
||||||
|
"version": 2
|
||||||
|
},
|
||||||
|
"rule_severities": {
|
||||||
|
"annular_width": "error",
|
||||||
|
"clearance": "error",
|
||||||
|
"connection_width": "warning",
|
||||||
|
"copper_edge_clearance": "error",
|
||||||
|
"copper_sliver": "warning",
|
||||||
|
"courtyards_overlap": "error",
|
||||||
|
"creepage": "error",
|
||||||
|
"diff_pair_gap_out_of_range": "error",
|
||||||
|
"diff_pair_uncoupled_length_too_long": "error",
|
||||||
|
"drill_out_of_range": "error",
|
||||||
|
"duplicate_footprints": "warning",
|
||||||
|
"extra_footprint": "warning",
|
||||||
|
"footprint": "error",
|
||||||
|
"footprint_filters_mismatch": "ignore",
|
||||||
|
"footprint_symbol_mismatch": "warning",
|
||||||
|
"footprint_type_mismatch": "ignore",
|
||||||
|
"hole_clearance": "error",
|
||||||
|
"hole_near_hole": "error",
|
||||||
|
"hole_to_hole": "error",
|
||||||
|
"holes_co_located": "warning",
|
||||||
|
"invalid_outline": "error",
|
||||||
|
"isolated_copper": "warning",
|
||||||
|
"item_on_disabled_layer": "error",
|
||||||
|
"items_not_allowed": "error",
|
||||||
|
"length_out_of_range": "error",
|
||||||
|
"lib_footprint_issues": "warning",
|
||||||
|
"lib_footprint_mismatch": "warning",
|
||||||
|
"malformed_courtyard": "error",
|
||||||
|
"microvia_drill_out_of_range": "error",
|
||||||
|
"mirrored_text_on_front_layer": "warning",
|
||||||
|
"missing_courtyard": "ignore",
|
||||||
|
"missing_footprint": "warning",
|
||||||
|
"net_conflict": "warning",
|
||||||
|
"nonmirrored_text_on_back_layer": "warning",
|
||||||
|
"npth_inside_courtyard": "ignore",
|
||||||
|
"padstack": "warning",
|
||||||
|
"pth_inside_courtyard": "ignore",
|
||||||
|
"shorting_items": "error",
|
||||||
|
"silk_edge_clearance": "warning",
|
||||||
|
"silk_over_copper": "warning",
|
||||||
|
"silk_overlap": "warning",
|
||||||
|
"skew_out_of_range": "error",
|
||||||
|
"solder_mask_bridge": "error",
|
||||||
|
"starved_thermal": "error",
|
||||||
|
"text_height": "warning",
|
||||||
|
"text_on_edge_cuts": "error",
|
||||||
|
"text_thickness": "warning",
|
||||||
|
"through_hole_pad_without_hole": "error",
|
||||||
|
"too_many_vias": "error",
|
||||||
|
"track_angle": "error",
|
||||||
|
"track_dangling": "warning",
|
||||||
|
"track_segment_length": "error",
|
||||||
|
"track_width": "error",
|
||||||
|
"tracks_crossing": "error",
|
||||||
|
"unconnected_items": "error",
|
||||||
|
"unresolved_variable": "error",
|
||||||
|
"via_dangling": "warning",
|
||||||
|
"zones_intersect": "error"
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"max_error": 0.005,
|
||||||
|
"min_clearance": 0.2,
|
||||||
|
"min_connection": 0.0,
|
||||||
|
"min_copper_edge_clearance": 0.5,
|
||||||
|
"min_groove_width": 0.0,
|
||||||
|
"min_hole_clearance": 0.25,
|
||||||
|
"min_hole_to_hole": 0.2,
|
||||||
|
"min_microvia_diameter": 0.2,
|
||||||
|
"min_microvia_drill": 0.1,
|
||||||
|
"min_resolved_spokes": 2,
|
||||||
|
"min_silk_clearance": 0.0,
|
||||||
|
"min_text_height": 0.8,
|
||||||
|
"min_text_thickness": 0.08,
|
||||||
|
"min_through_hole_diameter": 0.1,
|
||||||
|
"min_track_width": 0.1,
|
||||||
|
"min_via_annular_width": 0.1,
|
||||||
|
"min_via_diameter": 0.3,
|
||||||
|
"solder_mask_to_copper_clearance": 0.0,
|
||||||
|
"use_height_for_length_calcs": true
|
||||||
|
},
|
||||||
|
"teardrop_options": [
|
||||||
|
{
|
||||||
|
"td_onpadsmd": true,
|
||||||
|
"td_onroundshapesonly": false,
|
||||||
|
"td_ontrackend": false,
|
||||||
|
"td_onviapad": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"teardrop_parameters": [
|
||||||
|
{
|
||||||
|
"td_allow_use_two_tracks": true,
|
||||||
|
"td_curve_segcount": 0,
|
||||||
|
"td_height_ratio": 1.0,
|
||||||
|
"td_length_ratio": 0.5,
|
||||||
|
"td_maxheight": 2.0,
|
||||||
|
"td_maxlen": 1.0,
|
||||||
|
"td_on_pad_in_zone": false,
|
||||||
|
"td_target_name": "td_round_shape",
|
||||||
|
"td_width_to_size_filter_ratio": 0.9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"td_allow_use_two_tracks": true,
|
||||||
|
"td_curve_segcount": 0,
|
||||||
|
"td_height_ratio": 1.0,
|
||||||
|
"td_length_ratio": 0.5,
|
||||||
|
"td_maxheight": 2.0,
|
||||||
|
"td_maxlen": 1.0,
|
||||||
|
"td_on_pad_in_zone": false,
|
||||||
|
"td_target_name": "td_rect_shape",
|
||||||
|
"td_width_to_size_filter_ratio": 0.9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"td_allow_use_two_tracks": true,
|
||||||
|
"td_curve_segcount": 0,
|
||||||
|
"td_height_ratio": 1.0,
|
||||||
|
"td_length_ratio": 0.5,
|
||||||
|
"td_maxheight": 2.0,
|
||||||
|
"td_maxlen": 1.0,
|
||||||
|
"td_on_pad_in_zone": false,
|
||||||
|
"td_target_name": "td_track_end",
|
||||||
|
"td_width_to_size_filter_ratio": 0.9
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"track_widths": [
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"tuning_pattern_settings": {
|
||||||
|
"diff_pair_defaults": {
|
||||||
|
"corner_radius_percentage": 80,
|
||||||
|
"corner_style": 1,
|
||||||
|
"max_amplitude": 1.0,
|
||||||
|
"min_amplitude": 0.2,
|
||||||
|
"single_sided": false,
|
||||||
|
"spacing": 1.0
|
||||||
|
},
|
||||||
|
"diff_pair_skew_defaults": {
|
||||||
|
"corner_radius_percentage": 80,
|
||||||
|
"corner_style": 1,
|
||||||
|
"max_amplitude": 1.0,
|
||||||
|
"min_amplitude": 0.2,
|
||||||
|
"single_sided": false,
|
||||||
|
"spacing": 0.6
|
||||||
|
},
|
||||||
|
"single_track_defaults": {
|
||||||
|
"corner_radius_percentage": 80,
|
||||||
|
"corner_style": 1,
|
||||||
|
"max_amplitude": 1.0,
|
||||||
|
"min_amplitude": 0.2,
|
||||||
|
"single_sided": false,
|
||||||
|
"spacing": 0.6
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"via_dimensions": [
|
||||||
|
{
|
||||||
|
"diameter": 0.0,
|
||||||
|
"drill": 0.0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"zones_allow_external_fillets": false
|
||||||
|
},
|
||||||
|
"ipc2581": {
|
||||||
|
"dist": "",
|
||||||
|
"distpn": "",
|
||||||
|
"internal_id": "",
|
||||||
|
"mfg": "",
|
||||||
|
"mpn": ""
|
||||||
|
},
|
||||||
|
"layer_pairs": [],
|
||||||
|
"layer_presets": [],
|
||||||
|
"viewports": []
|
||||||
|
},
|
||||||
|
"boards": [],
|
||||||
|
"cvpcb": {
|
||||||
|
"equivalence_files": []
|
||||||
|
},
|
||||||
|
"erc": {
|
||||||
|
"erc_exclusions": [],
|
||||||
|
"meta": {
|
||||||
|
"version": 0
|
||||||
|
},
|
||||||
|
"pin_map": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"rule_severities": {
|
||||||
|
"bus_definition_conflict": "error",
|
||||||
|
"bus_entry_needed": "error",
|
||||||
|
"bus_to_bus_conflict": "error",
|
||||||
|
"bus_to_net_conflict": "error",
|
||||||
|
"different_unit_footprint": "error",
|
||||||
|
"different_unit_net": "error",
|
||||||
|
"duplicate_reference": "error",
|
||||||
|
"duplicate_sheet_names": "error",
|
||||||
|
"endpoint_off_grid": "warning",
|
||||||
|
"extra_units": "error",
|
||||||
|
"footprint_filter": "ignore",
|
||||||
|
"footprint_link_issues": "warning",
|
||||||
|
"four_way_junction": "ignore",
|
||||||
|
"global_label_dangling": "warning",
|
||||||
|
"hier_label_mismatch": "error",
|
||||||
|
"label_dangling": "error",
|
||||||
|
"label_multiple_wires": "warning",
|
||||||
|
"lib_symbol_issues": "warning",
|
||||||
|
"lib_symbol_mismatch": "warning",
|
||||||
|
"missing_bidi_pin": "warning",
|
||||||
|
"missing_input_pin": "warning",
|
||||||
|
"missing_power_pin": "error",
|
||||||
|
"missing_unit": "warning",
|
||||||
|
"multiple_net_names": "warning",
|
||||||
|
"net_not_bus_member": "warning",
|
||||||
|
"no_connect_connected": "warning",
|
||||||
|
"no_connect_dangling": "warning",
|
||||||
|
"pin_not_connected": "error",
|
||||||
|
"pin_not_driven": "error",
|
||||||
|
"pin_to_pin": "warning",
|
||||||
|
"power_pin_not_driven": "error",
|
||||||
|
"same_local_global_label": "warning",
|
||||||
|
"similar_label_and_power": "warning",
|
||||||
|
"similar_labels": "warning",
|
||||||
|
"similar_power": "warning",
|
||||||
|
"simulation_model_issue": "ignore",
|
||||||
|
"single_global_label": "ignore",
|
||||||
|
"unannotated": "error",
|
||||||
|
"unconnected_wire_endpoint": "warning",
|
||||||
|
"unit_value_mismatch": "error",
|
||||||
|
"unresolved_variable": "error",
|
||||||
|
"wire_dangling": "error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"libraries": {
|
||||||
|
"pinned_footprint_libs": [],
|
||||||
|
"pinned_symbol_libs": []
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"filename": "fw-anwesenheit.kicad_pro",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
"net_settings": {
|
||||||
|
"classes": [
|
||||||
|
{
|
||||||
|
"bus_width": 12,
|
||||||
|
"clearance": 0.2,
|
||||||
|
"diff_pair_gap": 0.25,
|
||||||
|
"diff_pair_via_gap": 0.25,
|
||||||
|
"diff_pair_width": 0.2,
|
||||||
|
"line_style": 0,
|
||||||
|
"microvia_diameter": 0.3,
|
||||||
|
"microvia_drill": 0.1,
|
||||||
|
"name": "Default",
|
||||||
|
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"track_width": 0.2,
|
||||||
|
"via_diameter": 0.6,
|
||||||
|
"via_drill": 0.3,
|
||||||
|
"wire_width": 6
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"net_colors": null,
|
||||||
|
"netclass_assignments": null,
|
||||||
|
"netclass_patterns": []
|
||||||
|
},
|
||||||
|
"pcbnew": {
|
||||||
|
"last_paths": {
|
||||||
|
"gencad": "",
|
||||||
|
"idf": "",
|
||||||
|
"netlist": "",
|
||||||
|
"plot": "production/",
|
||||||
|
"pos_files": "",
|
||||||
|
"specctra_dsn": "",
|
||||||
|
"step": "",
|
||||||
|
"svg": "",
|
||||||
|
"vrml": ""
|
||||||
|
},
|
||||||
|
"page_layout_descr_file": ""
|
||||||
|
},
|
||||||
|
"schematic": {
|
||||||
|
"annotate_start_num": 0,
|
||||||
|
"bom_export_filename": "${PROJECTNAME}.csv",
|
||||||
|
"bom_fmt_presets": [],
|
||||||
|
"bom_fmt_settings": {
|
||||||
|
"field_delimiter": ",",
|
||||||
|
"keep_line_breaks": false,
|
||||||
|
"keep_tabs": false,
|
||||||
|
"name": "CSV",
|
||||||
|
"ref_delimiter": ",",
|
||||||
|
"ref_range_delimiter": "",
|
||||||
|
"string_delimiter": "\""
|
||||||
|
},
|
||||||
|
"bom_presets": [],
|
||||||
|
"bom_settings": {
|
||||||
|
"exclude_dnp": false,
|
||||||
|
"fields_ordered": [
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Reference",
|
||||||
|
"name": "Reference",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Qty",
|
||||||
|
"name": "${QUANTITY}",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": true,
|
||||||
|
"label": "Value",
|
||||||
|
"name": "Value",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": true,
|
||||||
|
"label": "DNP",
|
||||||
|
"name": "${DNP}",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": true,
|
||||||
|
"label": "Exclude from BOM",
|
||||||
|
"name": "${EXCLUDE_FROM_BOM}",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": true,
|
||||||
|
"label": "Exclude from Board",
|
||||||
|
"name": "${EXCLUDE_FROM_BOARD}",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": true,
|
||||||
|
"label": "Footprint",
|
||||||
|
"name": "Footprint",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Datasheet",
|
||||||
|
"name": "Datasheet",
|
||||||
|
"show": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filter_string": "",
|
||||||
|
"group_symbols": true,
|
||||||
|
"include_excluded_from_bom": true,
|
||||||
|
"name": "Default Editing",
|
||||||
|
"sort_asc": true,
|
||||||
|
"sort_field": "Referenz"
|
||||||
|
},
|
||||||
|
"connection_grid_size": 50.0,
|
||||||
|
"drawing": {
|
||||||
|
"dashed_lines_dash_length_ratio": 12.0,
|
||||||
|
"dashed_lines_gap_length_ratio": 3.0,
|
||||||
|
"default_line_thickness": 6.0,
|
||||||
|
"default_text_size": 50.0,
|
||||||
|
"field_names": [],
|
||||||
|
"intersheets_ref_own_page": false,
|
||||||
|
"intersheets_ref_prefix": "",
|
||||||
|
"intersheets_ref_short": false,
|
||||||
|
"intersheets_ref_show": false,
|
||||||
|
"intersheets_ref_suffix": "",
|
||||||
|
"junction_size_choice": 3,
|
||||||
|
"label_size_ratio": 0.375,
|
||||||
|
"operating_point_overlay_i_precision": 3,
|
||||||
|
"operating_point_overlay_i_range": "~A",
|
||||||
|
"operating_point_overlay_v_precision": 3,
|
||||||
|
"operating_point_overlay_v_range": "~V",
|
||||||
|
"overbar_offset_ratio": 1.23,
|
||||||
|
"pin_symbol_size": 25.0,
|
||||||
|
"text_offset_ratio": 0.15
|
||||||
|
},
|
||||||
|
"legacy_lib_dir": "",
|
||||||
|
"legacy_lib_list": [],
|
||||||
|
"meta": {
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
"net_format_name": "",
|
||||||
|
"page_layout_descr_file": "",
|
||||||
|
"plot_directory": "",
|
||||||
|
"space_save_all_events": true,
|
||||||
|
"spice_current_sheet_as_root": false,
|
||||||
|
"spice_external_command": "spice \"%I\"",
|
||||||
|
"spice_model_current_sheet_as_root": true,
|
||||||
|
"spice_save_all_currents": false,
|
||||||
|
"spice_save_all_dissipations": false,
|
||||||
|
"spice_save_all_voltages": false,
|
||||||
|
"subpart_first_id": 65,
|
||||||
|
"subpart_id_separator": 0
|
||||||
|
},
|
||||||
|
"sheets": [
|
||||||
|
[
|
||||||
|
"ccbf1fda-befd-42da-bcb2-5d3829184012",
|
||||||
|
"Root"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"text_variables": {}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-22_225609.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-22_225609.zip
Normal file
Binary file not shown.
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-23_143548.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-23_143548.zip
Normal file
Binary file not shown.
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-23_144128.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-23_144128.zip
Normal file
Binary file not shown.
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-23_145320.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-23_145320.zip
Normal file
Binary file not shown.
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-23_145958.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-23_145958.zip
Normal file
Binary file not shown.
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-23_150841.zip
Normal file
BIN
pcb/fw-anwesenheit-backups/fw-anwesenheit-2025-08-23_150841.zip
Normal file
Binary file not shown.
25828
pcb/fw-anwesenheit.kicad_pcb
Normal file
25828
pcb/fw-anwesenheit.kicad_pcb
Normal file
File diff suppressed because it is too large
Load Diff
143
pcb/fw-anwesenheit.kicad_prl
Normal file
143
pcb/fw-anwesenheit.kicad_prl
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
{
|
||||||
|
"board": {
|
||||||
|
"active_layer": 5,
|
||||||
|
"active_layer_preset": "",
|
||||||
|
"auto_track_width": true,
|
||||||
|
"hidden_netclasses": [],
|
||||||
|
"hidden_nets": [],
|
||||||
|
"high_contrast_mode": 0,
|
||||||
|
"net_color_mode": 1,
|
||||||
|
"opacity": {
|
||||||
|
"images": 0.6,
|
||||||
|
"pads": 1.0,
|
||||||
|
"shapes": 1.0,
|
||||||
|
"tracks": 1.0,
|
||||||
|
"vias": 1.0,
|
||||||
|
"zones": 0.6
|
||||||
|
},
|
||||||
|
"selection_filter": {
|
||||||
|
"dimensions": true,
|
||||||
|
"footprints": true,
|
||||||
|
"graphics": true,
|
||||||
|
"keepouts": true,
|
||||||
|
"lockedItems": false,
|
||||||
|
"otherItems": true,
|
||||||
|
"pads": true,
|
||||||
|
"text": true,
|
||||||
|
"tracks": true,
|
||||||
|
"vias": true,
|
||||||
|
"zones": true
|
||||||
|
},
|
||||||
|
"visible_items": [
|
||||||
|
"vias",
|
||||||
|
"footprint_text",
|
||||||
|
"footprint_anchors",
|
||||||
|
"ratsnest",
|
||||||
|
"grid",
|
||||||
|
"footprints_front",
|
||||||
|
"footprints_back",
|
||||||
|
"footprint_values",
|
||||||
|
"footprint_references",
|
||||||
|
"tracks",
|
||||||
|
"drc_errors",
|
||||||
|
"drawing_sheet",
|
||||||
|
"bitmaps",
|
||||||
|
"pads",
|
||||||
|
"zones",
|
||||||
|
"drc_warnings",
|
||||||
|
"drc_exclusions",
|
||||||
|
"locked_item_shadows",
|
||||||
|
"conflict_shadows",
|
||||||
|
"shapes"
|
||||||
|
],
|
||||||
|
"visible_layers": "ffffffff_ffffffff_ffffffff_fdff502a",
|
||||||
|
"zone_display_mode": 0
|
||||||
|
},
|
||||||
|
"git": {
|
||||||
|
"repo_type": "",
|
||||||
|
"repo_username": "",
|
||||||
|
"ssh_key": ""
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"filename": "fw-anwesenheit.kicad_prl",
|
||||||
|
"version": 5
|
||||||
|
},
|
||||||
|
"net_inspector_panel": {
|
||||||
|
"col_hidden": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
],
|
||||||
|
"col_order": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9,
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13
|
||||||
|
],
|
||||||
|
"col_widths": [
|
||||||
|
162,
|
||||||
|
147,
|
||||||
|
91,
|
||||||
|
72,
|
||||||
|
91,
|
||||||
|
100,
|
||||||
|
91,
|
||||||
|
76,
|
||||||
|
91,
|
||||||
|
91,
|
||||||
|
91,
|
||||||
|
91,
|
||||||
|
91,
|
||||||
|
91
|
||||||
|
],
|
||||||
|
"custom_group_rules": [],
|
||||||
|
"expanded_rows": [],
|
||||||
|
"filter_by_net_name": true,
|
||||||
|
"filter_by_netclass": true,
|
||||||
|
"filter_text": "",
|
||||||
|
"group_by_constraint": false,
|
||||||
|
"group_by_netclass": false,
|
||||||
|
"show_unconnected_nets": false,
|
||||||
|
"show_zero_pad_nets": false,
|
||||||
|
"sort_ascending": true,
|
||||||
|
"sorting_column": 0
|
||||||
|
},
|
||||||
|
"open_jobsets": [],
|
||||||
|
"project": {
|
||||||
|
"files": []
|
||||||
|
},
|
||||||
|
"schematic": {
|
||||||
|
"selection_filter": {
|
||||||
|
"graphics": true,
|
||||||
|
"images": true,
|
||||||
|
"labels": true,
|
||||||
|
"lockedItems": false,
|
||||||
|
"otherItems": true,
|
||||||
|
"pins": true,
|
||||||
|
"symbols": true,
|
||||||
|
"text": true,
|
||||||
|
"wires": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
632
pcb/fw-anwesenheit.kicad_pro
Normal file
632
pcb/fw-anwesenheit.kicad_pro
Normal file
@@ -0,0 +1,632 @@
|
|||||||
|
{
|
||||||
|
"board": {
|
||||||
|
"3dviewports": [],
|
||||||
|
"design_settings": {
|
||||||
|
"defaults": {
|
||||||
|
"apply_defaults_to_fp_fields": false,
|
||||||
|
"apply_defaults_to_fp_shapes": false,
|
||||||
|
"apply_defaults_to_fp_text": false,
|
||||||
|
"board_outline_line_width": 0.05,
|
||||||
|
"copper_line_width": 0.2,
|
||||||
|
"copper_text_italic": false,
|
||||||
|
"copper_text_size_h": 1.5,
|
||||||
|
"copper_text_size_v": 1.5,
|
||||||
|
"copper_text_thickness": 0.3,
|
||||||
|
"copper_text_upright": false,
|
||||||
|
"courtyard_line_width": 0.05,
|
||||||
|
"dimension_precision": 4,
|
||||||
|
"dimension_units": 3,
|
||||||
|
"dimensions": {
|
||||||
|
"arrow_length": 1270000,
|
||||||
|
"extension_offset": 500000,
|
||||||
|
"keep_text_aligned": true,
|
||||||
|
"suppress_zeroes": true,
|
||||||
|
"text_position": 0,
|
||||||
|
"units_format": 0
|
||||||
|
},
|
||||||
|
"fab_line_width": 0.1,
|
||||||
|
"fab_text_italic": false,
|
||||||
|
"fab_text_size_h": 1.0,
|
||||||
|
"fab_text_size_v": 1.0,
|
||||||
|
"fab_text_thickness": 0.15,
|
||||||
|
"fab_text_upright": false,
|
||||||
|
"other_line_width": 0.1,
|
||||||
|
"other_text_italic": false,
|
||||||
|
"other_text_size_h": 1.0,
|
||||||
|
"other_text_size_v": 1.0,
|
||||||
|
"other_text_thickness": 0.15,
|
||||||
|
"other_text_upright": false,
|
||||||
|
"pads": {
|
||||||
|
"drill": 0.0,
|
||||||
|
"height": 1.7,
|
||||||
|
"width": 1.7
|
||||||
|
},
|
||||||
|
"silk_line_width": 0.1,
|
||||||
|
"silk_text_italic": false,
|
||||||
|
"silk_text_size_h": 1.0,
|
||||||
|
"silk_text_size_v": 1.0,
|
||||||
|
"silk_text_thickness": 0.1,
|
||||||
|
"silk_text_upright": false,
|
||||||
|
"zones": {
|
||||||
|
"min_clearance": 0.5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"diff_pair_dimensions": [
|
||||||
|
{
|
||||||
|
"gap": 0.0,
|
||||||
|
"via_gap": 0.0,
|
||||||
|
"width": 0.0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"drc_exclusions": [],
|
||||||
|
"meta": {
|
||||||
|
"version": 2
|
||||||
|
},
|
||||||
|
"rule_severities": {
|
||||||
|
"annular_width": "error",
|
||||||
|
"clearance": "error",
|
||||||
|
"connection_width": "warning",
|
||||||
|
"copper_edge_clearance": "error",
|
||||||
|
"copper_sliver": "warning",
|
||||||
|
"courtyards_overlap": "error",
|
||||||
|
"creepage": "error",
|
||||||
|
"diff_pair_gap_out_of_range": "error",
|
||||||
|
"diff_pair_uncoupled_length_too_long": "error",
|
||||||
|
"drill_out_of_range": "error",
|
||||||
|
"duplicate_footprints": "warning",
|
||||||
|
"extra_footprint": "warning",
|
||||||
|
"footprint": "error",
|
||||||
|
"footprint_filters_mismatch": "ignore",
|
||||||
|
"footprint_symbol_mismatch": "warning",
|
||||||
|
"footprint_type_mismatch": "ignore",
|
||||||
|
"hole_clearance": "error",
|
||||||
|
"hole_near_hole": "error",
|
||||||
|
"hole_to_hole": "error",
|
||||||
|
"holes_co_located": "warning",
|
||||||
|
"invalid_outline": "error",
|
||||||
|
"isolated_copper": "warning",
|
||||||
|
"item_on_disabled_layer": "error",
|
||||||
|
"items_not_allowed": "error",
|
||||||
|
"length_out_of_range": "error",
|
||||||
|
"lib_footprint_issues": "warning",
|
||||||
|
"lib_footprint_mismatch": "warning",
|
||||||
|
"malformed_courtyard": "error",
|
||||||
|
"microvia_drill_out_of_range": "error",
|
||||||
|
"mirrored_text_on_front_layer": "warning",
|
||||||
|
"missing_courtyard": "ignore",
|
||||||
|
"missing_footprint": "warning",
|
||||||
|
"net_conflict": "warning",
|
||||||
|
"nonmirrored_text_on_back_layer": "warning",
|
||||||
|
"npth_inside_courtyard": "ignore",
|
||||||
|
"padstack": "warning",
|
||||||
|
"pth_inside_courtyard": "ignore",
|
||||||
|
"shorting_items": "error",
|
||||||
|
"silk_edge_clearance": "warning",
|
||||||
|
"silk_over_copper": "warning",
|
||||||
|
"silk_overlap": "warning",
|
||||||
|
"skew_out_of_range": "error",
|
||||||
|
"solder_mask_bridge": "error",
|
||||||
|
"starved_thermal": "error",
|
||||||
|
"text_height": "warning",
|
||||||
|
"text_on_edge_cuts": "error",
|
||||||
|
"text_thickness": "warning",
|
||||||
|
"through_hole_pad_without_hole": "error",
|
||||||
|
"too_many_vias": "error",
|
||||||
|
"track_angle": "error",
|
||||||
|
"track_dangling": "warning",
|
||||||
|
"track_segment_length": "error",
|
||||||
|
"track_width": "error",
|
||||||
|
"tracks_crossing": "error",
|
||||||
|
"unconnected_items": "error",
|
||||||
|
"unresolved_variable": "error",
|
||||||
|
"via_dangling": "warning",
|
||||||
|
"zones_intersect": "error"
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"max_error": 0.005,
|
||||||
|
"min_clearance": 0.2,
|
||||||
|
"min_connection": 0.0,
|
||||||
|
"min_copper_edge_clearance": 0.5,
|
||||||
|
"min_groove_width": 0.0,
|
||||||
|
"min_hole_clearance": 0.25,
|
||||||
|
"min_hole_to_hole": 0.2,
|
||||||
|
"min_microvia_diameter": 0.2,
|
||||||
|
"min_microvia_drill": 0.1,
|
||||||
|
"min_resolved_spokes": 2,
|
||||||
|
"min_silk_clearance": 0.0,
|
||||||
|
"min_text_height": 0.8,
|
||||||
|
"min_text_thickness": 0.08,
|
||||||
|
"min_through_hole_diameter": 0.1,
|
||||||
|
"min_track_width": 0.1,
|
||||||
|
"min_via_annular_width": 0.1,
|
||||||
|
"min_via_diameter": 0.3,
|
||||||
|
"solder_mask_to_copper_clearance": 0.0,
|
||||||
|
"use_height_for_length_calcs": true
|
||||||
|
},
|
||||||
|
"teardrop_options": [
|
||||||
|
{
|
||||||
|
"td_onpthpad": true,
|
||||||
|
"td_onroundshapesonly": false,
|
||||||
|
"td_onsmdpad": true,
|
||||||
|
"td_ontrackend": false,
|
||||||
|
"td_onvia": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"teardrop_parameters": [
|
||||||
|
{
|
||||||
|
"td_allow_use_two_tracks": true,
|
||||||
|
"td_curve_segcount": 0,
|
||||||
|
"td_height_ratio": 1.0,
|
||||||
|
"td_length_ratio": 0.5,
|
||||||
|
"td_maxheight": 2.0,
|
||||||
|
"td_maxlen": 1.0,
|
||||||
|
"td_on_pad_in_zone": false,
|
||||||
|
"td_target_name": "td_round_shape",
|
||||||
|
"td_width_to_size_filter_ratio": 0.9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"td_allow_use_two_tracks": true,
|
||||||
|
"td_curve_segcount": 0,
|
||||||
|
"td_height_ratio": 1.0,
|
||||||
|
"td_length_ratio": 0.5,
|
||||||
|
"td_maxheight": 2.0,
|
||||||
|
"td_maxlen": 1.0,
|
||||||
|
"td_on_pad_in_zone": false,
|
||||||
|
"td_target_name": "td_rect_shape",
|
||||||
|
"td_width_to_size_filter_ratio": 0.9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"td_allow_use_two_tracks": true,
|
||||||
|
"td_curve_segcount": 0,
|
||||||
|
"td_height_ratio": 1.0,
|
||||||
|
"td_length_ratio": 0.5,
|
||||||
|
"td_maxheight": 2.0,
|
||||||
|
"td_maxlen": 1.0,
|
||||||
|
"td_on_pad_in_zone": false,
|
||||||
|
"td_target_name": "td_track_end",
|
||||||
|
"td_width_to_size_filter_ratio": 0.9
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"track_widths": [
|
||||||
|
0.0
|
||||||
|
],
|
||||||
|
"tuning_pattern_settings": {
|
||||||
|
"diff_pair_defaults": {
|
||||||
|
"corner_radius_percentage": 80,
|
||||||
|
"corner_style": 1,
|
||||||
|
"max_amplitude": 1.0,
|
||||||
|
"min_amplitude": 0.2,
|
||||||
|
"single_sided": false,
|
||||||
|
"spacing": 1.0
|
||||||
|
},
|
||||||
|
"diff_pair_skew_defaults": {
|
||||||
|
"corner_radius_percentage": 80,
|
||||||
|
"corner_style": 1,
|
||||||
|
"max_amplitude": 1.0,
|
||||||
|
"min_amplitude": 0.2,
|
||||||
|
"single_sided": false,
|
||||||
|
"spacing": 0.6
|
||||||
|
},
|
||||||
|
"single_track_defaults": {
|
||||||
|
"corner_radius_percentage": 80,
|
||||||
|
"corner_style": 1,
|
||||||
|
"max_amplitude": 1.0,
|
||||||
|
"min_amplitude": 0.2,
|
||||||
|
"single_sided": false,
|
||||||
|
"spacing": 0.6
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"via_dimensions": [
|
||||||
|
{
|
||||||
|
"diameter": 0.0,
|
||||||
|
"drill": 0.0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"zones_allow_external_fillets": false
|
||||||
|
},
|
||||||
|
"ipc2581": {
|
||||||
|
"dist": "",
|
||||||
|
"distpn": "",
|
||||||
|
"internal_id": "",
|
||||||
|
"mfg": "",
|
||||||
|
"mpn": ""
|
||||||
|
},
|
||||||
|
"layer_pairs": [],
|
||||||
|
"layer_presets": [],
|
||||||
|
"viewports": []
|
||||||
|
},
|
||||||
|
"boards": [],
|
||||||
|
"cvpcb": {
|
||||||
|
"equivalence_files": []
|
||||||
|
},
|
||||||
|
"erc": {
|
||||||
|
"erc_exclusions": [],
|
||||||
|
"meta": {
|
||||||
|
"version": 0
|
||||||
|
},
|
||||||
|
"pin_map": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"rule_severities": {
|
||||||
|
"bus_definition_conflict": "error",
|
||||||
|
"bus_entry_needed": "error",
|
||||||
|
"bus_to_bus_conflict": "error",
|
||||||
|
"bus_to_net_conflict": "error",
|
||||||
|
"different_unit_footprint": "error",
|
||||||
|
"different_unit_net": "error",
|
||||||
|
"duplicate_reference": "error",
|
||||||
|
"duplicate_sheet_names": "error",
|
||||||
|
"endpoint_off_grid": "warning",
|
||||||
|
"extra_units": "error",
|
||||||
|
"footprint_filter": "ignore",
|
||||||
|
"footprint_link_issues": "warning",
|
||||||
|
"four_way_junction": "ignore",
|
||||||
|
"global_label_dangling": "warning",
|
||||||
|
"hier_label_mismatch": "error",
|
||||||
|
"label_dangling": "error",
|
||||||
|
"label_multiple_wires": "warning",
|
||||||
|
"lib_symbol_issues": "warning",
|
||||||
|
"lib_symbol_mismatch": "warning",
|
||||||
|
"missing_bidi_pin": "warning",
|
||||||
|
"missing_input_pin": "warning",
|
||||||
|
"missing_power_pin": "error",
|
||||||
|
"missing_unit": "warning",
|
||||||
|
"multiple_net_names": "warning",
|
||||||
|
"net_not_bus_member": "warning",
|
||||||
|
"no_connect_connected": "warning",
|
||||||
|
"no_connect_dangling": "warning",
|
||||||
|
"pin_not_connected": "error",
|
||||||
|
"pin_not_driven": "error",
|
||||||
|
"pin_to_pin": "warning",
|
||||||
|
"power_pin_not_driven": "error",
|
||||||
|
"same_local_global_label": "warning",
|
||||||
|
"similar_label_and_power": "warning",
|
||||||
|
"similar_labels": "warning",
|
||||||
|
"similar_power": "warning",
|
||||||
|
"simulation_model_issue": "ignore",
|
||||||
|
"single_global_label": "ignore",
|
||||||
|
"unannotated": "error",
|
||||||
|
"unconnected_wire_endpoint": "warning",
|
||||||
|
"unit_value_mismatch": "error",
|
||||||
|
"unresolved_variable": "error",
|
||||||
|
"wire_dangling": "error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"libraries": {
|
||||||
|
"pinned_footprint_libs": [],
|
||||||
|
"pinned_symbol_libs": []
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"filename": "fw-anwesenheit.kicad_pro",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"net_settings": {
|
||||||
|
"classes": [
|
||||||
|
{
|
||||||
|
"bus_width": 12,
|
||||||
|
"clearance": 0.2,
|
||||||
|
"diff_pair_gap": 0.25,
|
||||||
|
"diff_pair_via_gap": 0.25,
|
||||||
|
"diff_pair_width": 0.2,
|
||||||
|
"line_style": 0,
|
||||||
|
"microvia_diameter": 0.3,
|
||||||
|
"microvia_drill": 0.1,
|
||||||
|
"name": "Default",
|
||||||
|
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"priority": 2147483647,
|
||||||
|
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"track_width": 0.2,
|
||||||
|
"via_diameter": 0.6,
|
||||||
|
"via_drill": 0.3,
|
||||||
|
"wire_width": 6
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"version": 4
|
||||||
|
},
|
||||||
|
"net_colors": null,
|
||||||
|
"netclass_assignments": null,
|
||||||
|
"netclass_patterns": []
|
||||||
|
},
|
||||||
|
"pcbnew": {
|
||||||
|
"last_paths": {
|
||||||
|
"gencad": "",
|
||||||
|
"idf": "",
|
||||||
|
"netlist": "",
|
||||||
|
"plot": "production/",
|
||||||
|
"pos_files": "",
|
||||||
|
"specctra_dsn": "",
|
||||||
|
"step": "",
|
||||||
|
"svg": "",
|
||||||
|
"vrml": ""
|
||||||
|
},
|
||||||
|
"page_layout_descr_file": ""
|
||||||
|
},
|
||||||
|
"schematic": {
|
||||||
|
"annotate_start_num": 0,
|
||||||
|
"bom_export_filename": "${PROJECTNAME}.csv",
|
||||||
|
"bom_fmt_presets": [],
|
||||||
|
"bom_fmt_settings": {
|
||||||
|
"field_delimiter": ",",
|
||||||
|
"keep_line_breaks": false,
|
||||||
|
"keep_tabs": false,
|
||||||
|
"name": "CSV",
|
||||||
|
"ref_delimiter": ",",
|
||||||
|
"ref_range_delimiter": "",
|
||||||
|
"string_delimiter": "\""
|
||||||
|
},
|
||||||
|
"bom_presets": [],
|
||||||
|
"bom_settings": {
|
||||||
|
"exclude_dnp": false,
|
||||||
|
"fields_ordered": [
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Reference",
|
||||||
|
"name": "Reference",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Qty",
|
||||||
|
"name": "${QUANTITY}",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": true,
|
||||||
|
"label": "Value",
|
||||||
|
"name": "Value",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": true,
|
||||||
|
"label": "DNP",
|
||||||
|
"name": "${DNP}",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": true,
|
||||||
|
"label": "Exclude from BOM",
|
||||||
|
"name": "${EXCLUDE_FROM_BOM}",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": true,
|
||||||
|
"label": "Exclude from Board",
|
||||||
|
"name": "${EXCLUDE_FROM_BOARD}",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": true,
|
||||||
|
"label": "Footprint",
|
||||||
|
"name": "Footprint",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Datasheet",
|
||||||
|
"name": "Datasheet",
|
||||||
|
"show": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filter_string": "",
|
||||||
|
"group_symbols": true,
|
||||||
|
"include_excluded_from_bom": true,
|
||||||
|
"name": "Default Editing",
|
||||||
|
"sort_asc": true,
|
||||||
|
"sort_field": "Referenz"
|
||||||
|
},
|
||||||
|
"connection_grid_size": 50.0,
|
||||||
|
"drawing": {
|
||||||
|
"dashed_lines_dash_length_ratio": 12.0,
|
||||||
|
"dashed_lines_gap_length_ratio": 3.0,
|
||||||
|
"default_line_thickness": 6.0,
|
||||||
|
"default_text_size": 50.0,
|
||||||
|
"field_names": [],
|
||||||
|
"intersheets_ref_own_page": false,
|
||||||
|
"intersheets_ref_prefix": "",
|
||||||
|
"intersheets_ref_short": false,
|
||||||
|
"intersheets_ref_show": false,
|
||||||
|
"intersheets_ref_suffix": "",
|
||||||
|
"junction_size_choice": 3,
|
||||||
|
"label_size_ratio": 0.375,
|
||||||
|
"operating_point_overlay_i_precision": 3,
|
||||||
|
"operating_point_overlay_i_range": "~A",
|
||||||
|
"operating_point_overlay_v_precision": 3,
|
||||||
|
"operating_point_overlay_v_range": "~V",
|
||||||
|
"overbar_offset_ratio": 1.23,
|
||||||
|
"pin_symbol_size": 25.0,
|
||||||
|
"text_offset_ratio": 0.15
|
||||||
|
},
|
||||||
|
"legacy_lib_dir": "",
|
||||||
|
"legacy_lib_list": [],
|
||||||
|
"meta": {
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
"net_format_name": "",
|
||||||
|
"page_layout_descr_file": "",
|
||||||
|
"plot_directory": "",
|
||||||
|
"space_save_all_events": true,
|
||||||
|
"spice_current_sheet_as_root": false,
|
||||||
|
"spice_external_command": "spice \"%I\"",
|
||||||
|
"spice_model_current_sheet_as_root": true,
|
||||||
|
"spice_save_all_currents": false,
|
||||||
|
"spice_save_all_dissipations": false,
|
||||||
|
"spice_save_all_voltages": false,
|
||||||
|
"subpart_first_id": 65,
|
||||||
|
"subpart_id_separator": 0
|
||||||
|
},
|
||||||
|
"sheets": [
|
||||||
|
[
|
||||||
|
"ccbf1fda-befd-42da-bcb2-5d3829184012",
|
||||||
|
"Root"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"text_variables": {}
|
||||||
|
}
|
||||||
11937
pcb/fw-anwesenheit.kicad_sch
Normal file
11937
pcb/fw-anwesenheit.kicad_sch
Normal file
File diff suppressed because it is too large
Load Diff
BIN
pcb/production.zip
Normal file
BIN
pcb/production.zip
Normal file
Binary file not shown.
6969
pcb/production/fw-anwesenheit-B_Cu.gbl
Normal file
6969
pcb/production/fw-anwesenheit-B_Cu.gbl
Normal file
File diff suppressed because it is too large
Load Diff
92
pcb/production/fw-anwesenheit-B_Mask.gbs
Normal file
92
pcb/production/fw-anwesenheit-B_Mask.gbs
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,9.0.3*
|
||||||
|
G04 #@! TF.CreationDate,2025-08-23T15:15:08+02:00*
|
||||||
|
G04 #@! TF.ProjectId,fw-anwesenheit,66772d61-6e77-4657-9365-6e686569742e,rev?*
|
||||||
|
G04 #@! TF.SameCoordinates,Original*
|
||||||
|
G04 #@! TF.FileFunction,Soldermask,Bot*
|
||||||
|
G04 #@! TF.FilePolarity,Negative*
|
||||||
|
%FSLAX46Y46*%
|
||||||
|
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
|
||||||
|
G04 Created by KiCad (PCBNEW 9.0.3) date 2025-08-23 15:15:08*
|
||||||
|
%MOMM*%
|
||||||
|
%LPD*%
|
||||||
|
G01*
|
||||||
|
G04 APERTURE LIST*
|
||||||
|
G04 Aperture macros list*
|
||||||
|
%AMRoundRect*
|
||||||
|
0 Rectangle with rounded corners*
|
||||||
|
0 $1 Rounding radius*
|
||||||
|
0 $2 $3 $4 $5 $6 $7 $8 $9 X,Y pos of 4 corners*
|
||||||
|
0 Add a 4 corners polygon primitive as box body*
|
||||||
|
4,1,4,$2,$3,$4,$5,$6,$7,$8,$9,$2,$3,0*
|
||||||
|
0 Add four circle primitives for the rounded corners*
|
||||||
|
1,1,$1+$1,$2,$3*
|
||||||
|
1,1,$1+$1,$4,$5*
|
||||||
|
1,1,$1+$1,$6,$7*
|
||||||
|
1,1,$1+$1,$8,$9*
|
||||||
|
0 Add four rect primitives between the rounded corners*
|
||||||
|
20,1,$1+$1,$2,$3,$4,$5,0*
|
||||||
|
20,1,$1+$1,$4,$5,$6,$7,0*
|
||||||
|
20,1,$1+$1,$6,$7,$8,$9,0*
|
||||||
|
20,1,$1+$1,$8,$9,$2,$3,0*%
|
||||||
|
G04 Aperture macros list end*
|
||||||
|
%ADD10R,1.350000X1.350000*%
|
||||||
|
%ADD11C,1.350000*%
|
||||||
|
%ADD12C,2.304000*%
|
||||||
|
%ADD13RoundRect,0.102000X-1.050000X1.050000X-1.050000X-1.050000X1.050000X-1.050000X1.050000X1.050000X0*%
|
||||||
|
%ADD14C,1.000000*%
|
||||||
|
%ADD15C,1.500000*%
|
||||||
|
%ADD16R,1.600000X2.000000*%
|
||||||
|
%ADD17O,1.600000X2.000000*%
|
||||||
|
%ADD18R,1.700000X1.700000*%
|
||||||
|
%ADD19C,1.700000*%
|
||||||
|
G04 APERTURE END LIST*
|
||||||
|
D10*
|
||||||
|
X89916000Y-118888000D03*
|
||||||
|
D11*
|
||||||
|
X89916000Y-120888000D03*
|
||||||
|
D12*
|
||||||
|
X89500000Y-59520000D03*
|
||||||
|
D13*
|
||||||
|
X89500000Y-62060000D03*
|
||||||
|
D12*
|
||||||
|
X104740000Y-87460000D03*
|
||||||
|
X104740000Y-84920000D03*
|
||||||
|
X89500000Y-87460000D03*
|
||||||
|
D13*
|
||||||
|
X89500000Y-92540000D03*
|
||||||
|
D12*
|
||||||
|
X104740000Y-90000000D03*
|
||||||
|
D13*
|
||||||
|
X104740000Y-92540000D03*
|
||||||
|
D12*
|
||||||
|
X104740000Y-82380000D03*
|
||||||
|
X89500000Y-90000000D03*
|
||||||
|
D14*
|
||||||
|
X125750000Y-83600000D03*
|
||||||
|
X117750000Y-83600000D03*
|
||||||
|
D15*
|
||||||
|
X107500000Y-90000000D03*
|
||||||
|
X111000000Y-90000000D03*
|
||||||
|
X128500000Y-90000000D03*
|
||||||
|
D16*
|
||||||
|
X113411000Y-103378000D03*
|
||||||
|
D17*
|
||||||
|
X92911000Y-103378000D03*
|
||||||
|
D15*
|
||||||
|
X125000000Y-90000000D03*
|
||||||
|
D18*
|
||||||
|
X120010000Y-127000000D03*
|
||||||
|
D19*
|
||||||
|
X122550000Y-127000000D03*
|
||||||
|
D15*
|
||||||
|
X114500000Y-90000000D03*
|
||||||
|
D18*
|
||||||
|
X83185000Y-110490000D03*
|
||||||
|
D19*
|
||||||
|
X83185000Y-113030000D03*
|
||||||
|
X83185000Y-115570000D03*
|
||||||
|
X83185000Y-118110000D03*
|
||||||
|
D15*
|
||||||
|
X121500000Y-90000000D03*
|
||||||
|
X118000000Y-90000000D03*
|
||||||
|
M02*
|
||||||
27
pcb/production/fw-anwesenheit-B_Paste.gbp
Normal file
27
pcb/production/fw-anwesenheit-B_Paste.gbp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,9.0.3*
|
||||||
|
G04 #@! TF.CreationDate,2025-08-23T15:15:08+02:00*
|
||||||
|
G04 #@! TF.ProjectId,fw-anwesenheit,66772d61-6e77-4657-9365-6e686569742e,rev?*
|
||||||
|
G04 #@! TF.SameCoordinates,Original*
|
||||||
|
G04 #@! TF.FileFunction,Paste,Bot*
|
||||||
|
G04 #@! TF.FilePolarity,Positive*
|
||||||
|
%FSLAX46Y46*%
|
||||||
|
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
|
||||||
|
G04 Created by KiCad (PCBNEW 9.0.3) date 2025-08-23 15:15:08*
|
||||||
|
%MOMM*%
|
||||||
|
%LPD*%
|
||||||
|
G01*
|
||||||
|
G04 APERTURE LIST*
|
||||||
|
%ADD10R,1.700000X1.700000*%
|
||||||
|
%ADD11C,1.700000*%
|
||||||
|
G04 APERTURE END LIST*
|
||||||
|
D10*
|
||||||
|
X120010000Y-127000000D03*
|
||||||
|
D11*
|
||||||
|
X122550000Y-127000000D03*
|
||||||
|
D10*
|
||||||
|
X83185000Y-110490000D03*
|
||||||
|
D11*
|
||||||
|
X83185000Y-113030000D03*
|
||||||
|
X83185000Y-115570000D03*
|
||||||
|
X83185000Y-118110000D03*
|
||||||
|
M02*
|
||||||
2765
pcb/production/fw-anwesenheit-B_Silkscreen.gbo
Normal file
2765
pcb/production/fw-anwesenheit-B_Silkscreen.gbo
Normal file
File diff suppressed because it is too large
Load Diff
96
pcb/production/fw-anwesenheit-Edge_Cuts.gm1
Normal file
96
pcb/production/fw-anwesenheit-Edge_Cuts.gm1
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,9.0.3*
|
||||||
|
G04 #@! TF.CreationDate,2025-08-23T15:15:08+02:00*
|
||||||
|
G04 #@! TF.ProjectId,fw-anwesenheit,66772d61-6e77-4657-9365-6e686569742e,rev?*
|
||||||
|
G04 #@! TF.SameCoordinates,Original*
|
||||||
|
G04 #@! TF.FileFunction,Profile,NP*
|
||||||
|
%FSLAX46Y46*%
|
||||||
|
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
|
||||||
|
G04 Created by KiCad (PCBNEW 9.0.3) date 2025-08-23 15:15:08*
|
||||||
|
%MOMM*%
|
||||||
|
%LPD*%
|
||||||
|
G01*
|
||||||
|
G04 APERTURE LIST*
|
||||||
|
G04 #@! TA.AperFunction,Profile*
|
||||||
|
%ADD10C,1.025000*%
|
||||||
|
G04 #@! TD*
|
||||||
|
G04 #@! TA.AperFunction,Profile*
|
||||||
|
%ADD11C,0.050000*%
|
||||||
|
G04 #@! TD*
|
||||||
|
G04 #@! TA.AperFunction,Profile*
|
||||||
|
%ADD12C,0.010000*%
|
||||||
|
G04 #@! TD*
|
||||||
|
G04 APERTURE END LIST*
|
||||||
|
D10*
|
||||||
|
X85512500Y-123500000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X84487500Y-123500000I-512500J0D01*
|
||||||
|
G01*
|
||||||
|
X84487500Y-123500000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X85512500Y-123500000I512500J0D01*
|
||||||
|
G01*
|
||||||
|
X85512500Y-85000000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X84487500Y-85000000I-512500J0D01*
|
||||||
|
G01*
|
||||||
|
X84487500Y-85000000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X85512500Y-85000000I512500J0D01*
|
||||||
|
G01*
|
||||||
|
D11*
|
||||||
|
X81045000Y-79502000D02*
|
||||||
|
X131045000Y-79502000D01*
|
||||||
|
X131045000Y-129502000D01*
|
||||||
|
X81045000Y-129502000D01*
|
||||||
|
X81045000Y-79502000D01*
|
||||||
|
D10*
|
||||||
|
X127512500Y-123500000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X126487500Y-123500000I-512500J0D01*
|
||||||
|
G01*
|
||||||
|
X126487500Y-123500000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X127512500Y-123500000I512500J0D01*
|
||||||
|
G01*
|
||||||
|
X109512500Y-85000000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X108487500Y-85000000I-512500J0D01*
|
||||||
|
G01*
|
||||||
|
X108487500Y-85000000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X109512500Y-85000000I512500J0D01*
|
||||||
|
G01*
|
||||||
|
D12*
|
||||||
|
X117400000Y-83100000D02*
|
||||||
|
X118100000Y-83100000D01*
|
||||||
|
X118100000Y-84100000D02*
|
||||||
|
X117400000Y-84100000D01*
|
||||||
|
X116900000Y-83600000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X117400000Y-83100000I500000J0D01*
|
||||||
|
G01*
|
||||||
|
X117400000Y-84100000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X116900000Y-83600000I0J500000D01*
|
||||||
|
G01*
|
||||||
|
X118100000Y-83100000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X118600000Y-83600000I0J-500000D01*
|
||||||
|
G01*
|
||||||
|
X118600000Y-83600000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X118100000Y-84100000I-500000J0D01*
|
||||||
|
G01*
|
||||||
|
M02*
|
||||||
7162
pcb/production/fw-anwesenheit-F_Cu.gtl
Normal file
7162
pcb/production/fw-anwesenheit-F_Cu.gtl
Normal file
File diff suppressed because it is too large
Load Diff
288
pcb/production/fw-anwesenheit-F_Mask.gts
Normal file
288
pcb/production/fw-anwesenheit-F_Mask.gts
Normal file
@@ -0,0 +1,288 @@
|
|||||||
|
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,9.0.3*
|
||||||
|
G04 #@! TF.CreationDate,2025-08-23T15:15:08+02:00*
|
||||||
|
G04 #@! TF.ProjectId,fw-anwesenheit,66772d61-6e77-4657-9365-6e686569742e,rev?*
|
||||||
|
G04 #@! TF.SameCoordinates,Original*
|
||||||
|
G04 #@! TF.FileFunction,Soldermask,Top*
|
||||||
|
G04 #@! TF.FilePolarity,Negative*
|
||||||
|
%FSLAX46Y46*%
|
||||||
|
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
|
||||||
|
G04 Created by KiCad (PCBNEW 9.0.3) date 2025-08-23 15:15:08*
|
||||||
|
%MOMM*%
|
||||||
|
%LPD*%
|
||||||
|
G01*
|
||||||
|
G04 APERTURE LIST*
|
||||||
|
G04 Aperture macros list*
|
||||||
|
%AMRoundRect*
|
||||||
|
0 Rectangle with rounded corners*
|
||||||
|
0 $1 Rounding radius*
|
||||||
|
0 $2 $3 $4 $5 $6 $7 $8 $9 X,Y pos of 4 corners*
|
||||||
|
0 Add a 4 corners polygon primitive as box body*
|
||||||
|
4,1,4,$2,$3,$4,$5,$6,$7,$8,$9,$2,$3,0*
|
||||||
|
0 Add four circle primitives for the rounded corners*
|
||||||
|
1,1,$1+$1,$2,$3*
|
||||||
|
1,1,$1+$1,$4,$5*
|
||||||
|
1,1,$1+$1,$6,$7*
|
||||||
|
1,1,$1+$1,$8,$9*
|
||||||
|
0 Add four rect primitives between the rounded corners*
|
||||||
|
20,1,$1+$1,$2,$3,$4,$5,0*
|
||||||
|
20,1,$1+$1,$4,$5,$6,$7,0*
|
||||||
|
20,1,$1+$1,$6,$7,$8,$9,0*
|
||||||
|
20,1,$1+$1,$8,$9,$2,$3,0*%
|
||||||
|
%AMOutline5P*
|
||||||
|
0 Free polygon, 5 corners , with rotation*
|
||||||
|
0 The origin of the aperture is its center*
|
||||||
|
0 number of corners: always 5*
|
||||||
|
0 $1 to $10 corner X, Y*
|
||||||
|
0 $11 Rotation angle, in degrees counterclockwise*
|
||||||
|
0 create outline with 5 corners*
|
||||||
|
4,1,5,$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$1,$2,$11*%
|
||||||
|
%AMOutline6P*
|
||||||
|
0 Free polygon, 6 corners , with rotation*
|
||||||
|
0 The origin of the aperture is its center*
|
||||||
|
0 number of corners: always 6*
|
||||||
|
0 $1 to $12 corner X, Y*
|
||||||
|
0 $13 Rotation angle, in degrees counterclockwise*
|
||||||
|
0 create outline with 6 corners*
|
||||||
|
4,1,6,$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$1,$2,$13*%
|
||||||
|
%AMOutline7P*
|
||||||
|
0 Free polygon, 7 corners , with rotation*
|
||||||
|
0 The origin of the aperture is its center*
|
||||||
|
0 number of corners: always 7*
|
||||||
|
0 $1 to $14 corner X, Y*
|
||||||
|
0 $15 Rotation angle, in degrees counterclockwise*
|
||||||
|
0 create outline with 7 corners*
|
||||||
|
4,1,7,$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$1,$2,$15*%
|
||||||
|
%AMOutline8P*
|
||||||
|
0 Free polygon, 8 corners , with rotation*
|
||||||
|
0 The origin of the aperture is its center*
|
||||||
|
0 number of corners: always 8*
|
||||||
|
0 $1 to $16 corner X, Y*
|
||||||
|
0 $17 Rotation angle, in degrees counterclockwise*
|
||||||
|
0 create outline with 8 corners*
|
||||||
|
4,1,8,$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$1,$2,$17*%
|
||||||
|
%AMFreePoly0*
|
||||||
|
4,1,6,1.000000,0.000000,0.500000,-0.750000,-0.500000,-0.750000,-0.500000,0.750000,0.500000,0.750000,1.000000,0.000000,1.000000,0.000000,$1*%
|
||||||
|
%AMFreePoly1*
|
||||||
|
4,1,6,0.500000,-0.750000,-0.650000,-0.750000,-0.150000,0.000000,-0.650000,0.750000,0.500000,0.750000,0.500000,-0.750000,0.500000,-0.750000,$1*%
|
||||||
|
G04 Aperture macros list end*
|
||||||
|
%ADD10RoundRect,0.225000X0.225000X0.250000X-0.225000X0.250000X-0.225000X-0.250000X0.225000X-0.250000X0*%
|
||||||
|
%ADD11Outline5P,-1.250000X0.510000X-0.910000X0.850000X1.250000X0.850000X1.250000X-0.850000X-1.250000X-0.850000X0.000000*%
|
||||||
|
%ADD12RoundRect,0.170000X-1.080000X-0.680000X1.080000X-0.680000X1.080000X0.680000X-1.080000X0.680000X0*%
|
||||||
|
%ADD13RoundRect,0.250000X-1.000000X-0.600000X1.000000X-0.600000X1.000000X0.600000X-1.000000X0.600000X0*%
|
||||||
|
%ADD14RoundRect,0.525400X0.900400X0.525400X-0.900400X0.525400X-0.900400X-0.525400X0.900400X-0.525400X0*%
|
||||||
|
%ADD15RoundRect,0.300400X0.300400X-1.000400X0.300400X1.000400X-0.300400X1.000400X-0.300400X-1.000400X0*%
|
||||||
|
%ADD16C,1.700000*%
|
||||||
|
%ADD17C,1.500000*%
|
||||||
|
%ADD18RoundRect,0.218750X0.256250X-0.218750X0.256250X0.218750X-0.256250X0.218750X-0.256250X-0.218750X0*%
|
||||||
|
%ADD19RoundRect,0.237500X0.237500X-0.250000X0.237500X0.250000X-0.237500X0.250000X-0.237500X-0.250000X0*%
|
||||||
|
%ADD20RoundRect,0.237500X-0.237500X0.250000X-0.237500X-0.250000X0.237500X-0.250000X0.237500X0.250000X0*%
|
||||||
|
%ADD21RoundRect,0.225000X-0.225000X-0.250000X0.225000X-0.250000X0.225000X0.250000X-0.225000X0.250000X0*%
|
||||||
|
%ADD22RoundRect,0.150000X-0.875000X-0.150000X0.875000X-0.150000X0.875000X0.150000X-0.875000X0.150000X0*%
|
||||||
|
%ADD23R,1.350000X1.350000*%
|
||||||
|
%ADD24C,1.350000*%
|
||||||
|
%ADD25FreePoly0,0.000000*%
|
||||||
|
%ADD26FreePoly1,0.000000*%
|
||||||
|
%ADD27C,2.304000*%
|
||||||
|
%ADD28RoundRect,0.102000X-1.050000X1.050000X-1.050000X-1.050000X1.050000X-1.050000X1.050000X1.050000X0*%
|
||||||
|
%ADD29RoundRect,0.237500X0.250000X0.237500X-0.250000X0.237500X-0.250000X-0.237500X0.250000X-0.237500X0*%
|
||||||
|
%ADD30RoundRect,0.102000X-0.635000X-0.279400X0.635000X-0.279400X0.635000X0.279400X-0.635000X0.279400X0*%
|
||||||
|
%ADD31RoundRect,0.237500X-0.250000X-0.237500X0.250000X-0.237500X0.250000X0.237500X-0.250000X0.237500X0*%
|
||||||
|
%ADD32RoundRect,0.225000X0.250000X-0.225000X0.250000X0.225000X-0.250000X0.225000X-0.250000X-0.225000X0*%
|
||||||
|
%ADD33C,1.000000*%
|
||||||
|
%ADD34RoundRect,0.102000X0.350000X0.950000X-0.350000X0.950000X-0.350000X-0.950000X0.350000X-0.950000X0*%
|
||||||
|
%ADD35RoundRect,0.102000X0.850000X0.900000X-0.850000X0.900000X-0.850000X-0.900000X0.850000X-0.900000X0*%
|
||||||
|
%ADD36RoundRect,0.102000X0.700000X1.300000X-0.700000X1.300000X-0.700000X-1.300000X0.700000X-1.300000X0*%
|
||||||
|
%ADD37RoundRect,0.225000X-0.250000X0.225000X-0.250000X-0.225000X0.250000X-0.225000X0.250000X0.225000X0*%
|
||||||
|
%ADD38R,1.600000X2.000000*%
|
||||||
|
%ADD39O,1.600000X2.000000*%
|
||||||
|
G04 APERTURE END LIST*
|
||||||
|
G36*
|
||||||
|
X117483000Y-126250000D02*
|
||||||
|
G01*
|
||||||
|
X119933000Y-126250000D01*
|
||||||
|
X119933000Y-127750000D01*
|
||||||
|
X117483000Y-127750000D01*
|
||||||
|
X117483000Y-126250000D01*
|
||||||
|
G37*
|
||||||
|
D10*
|
||||||
|
X123775000Y-97500000D03*
|
||||||
|
X122225000Y-97500000D03*
|
||||||
|
D11*
|
||||||
|
X128778000Y-111252000D03*
|
||||||
|
D12*
|
||||||
|
X128778000Y-113792000D03*
|
||||||
|
D13*
|
||||||
|
X128778000Y-116332000D03*
|
||||||
|
D14*
|
||||||
|
X113821600Y-126598500D03*
|
||||||
|
X113821600Y-124058500D03*
|
||||||
|
X113821600Y-121518500D03*
|
||||||
|
X113821600Y-118978500D03*
|
||||||
|
X113821600Y-116438500D03*
|
||||||
|
X113821600Y-113898500D03*
|
||||||
|
X113821600Y-111358500D03*
|
||||||
|
X97656600Y-111358500D03*
|
||||||
|
X97656600Y-113898500D03*
|
||||||
|
X97656600Y-116438500D03*
|
||||||
|
X97656600Y-118978500D03*
|
||||||
|
X97656600Y-121518500D03*
|
||||||
|
X97656600Y-124058500D03*
|
||||||
|
X97656600Y-126598500D03*
|
||||||
|
D15*
|
||||||
|
X107548000Y-113446800D03*
|
||||||
|
X105008000Y-113446800D03*
|
||||||
|
D16*
|
||||||
|
X107040000Y-127620000D03*
|
||||||
|
X104500000Y-127620000D03*
|
||||||
|
X107040000Y-125080000D03*
|
||||||
|
X104500000Y-125080000D03*
|
||||||
|
X107040000Y-122540000D03*
|
||||||
|
X104500000Y-122540000D03*
|
||||||
|
X107040000Y-120000000D03*
|
||||||
|
X104592600Y-120056800D03*
|
||||||
|
D17*
|
||||||
|
X83000000Y-127500000D03*
|
||||||
|
D18*
|
||||||
|
X83500000Y-93787500D03*
|
||||||
|
X83500000Y-92212500D03*
|
||||||
|
D19*
|
||||||
|
X120000000Y-102412500D03*
|
||||||
|
X120000000Y-100587500D03*
|
||||||
|
X122000000Y-102412500D03*
|
||||||
|
X122000000Y-100587500D03*
|
||||||
|
D20*
|
||||||
|
X90000000Y-109087500D03*
|
||||||
|
X90000000Y-110912500D03*
|
||||||
|
D21*
|
||||||
|
X95618000Y-98552000D03*
|
||||||
|
X97168000Y-98552000D03*
|
||||||
|
D17*
|
||||||
|
X84000000Y-103500000D03*
|
||||||
|
D22*
|
||||||
|
X99871000Y-97282000D03*
|
||||||
|
X99871000Y-98552000D03*
|
||||||
|
X99871000Y-99822000D03*
|
||||||
|
X99871000Y-101092000D03*
|
||||||
|
X99871000Y-102362000D03*
|
||||||
|
X99871000Y-103632000D03*
|
||||||
|
X99871000Y-104902000D03*
|
||||||
|
X99871000Y-106172000D03*
|
||||||
|
X109171000Y-106172000D03*
|
||||||
|
X109171000Y-104902000D03*
|
||||||
|
X109171000Y-103632000D03*
|
||||||
|
X109171000Y-102362000D03*
|
||||||
|
X109171000Y-101092000D03*
|
||||||
|
X109171000Y-99822000D03*
|
||||||
|
X109171000Y-98552000D03*
|
||||||
|
X109171000Y-97282000D03*
|
||||||
|
D23*
|
||||||
|
X89916000Y-118888000D03*
|
||||||
|
D24*
|
||||||
|
X89916000Y-120888000D03*
|
||||||
|
D19*
|
||||||
|
X116000000Y-102412500D03*
|
||||||
|
X116000000Y-100587500D03*
|
||||||
|
D17*
|
||||||
|
X86175000Y-118373000D03*
|
||||||
|
D25*
|
||||||
|
X117983000Y-127000000D03*
|
||||||
|
D26*
|
||||||
|
X119433000Y-127000000D03*
|
||||||
|
D27*
|
||||||
|
X89500000Y-59520000D03*
|
||||||
|
D28*
|
||||||
|
X89500000Y-62060000D03*
|
||||||
|
D27*
|
||||||
|
X104740000Y-87460000D03*
|
||||||
|
X104740000Y-84920000D03*
|
||||||
|
X89500000Y-87460000D03*
|
||||||
|
D28*
|
||||||
|
X89500000Y-92540000D03*
|
||||||
|
D27*
|
||||||
|
X104740000Y-90000000D03*
|
||||||
|
D28*
|
||||||
|
X104740000Y-92540000D03*
|
||||||
|
D27*
|
||||||
|
X104740000Y-82380000D03*
|
||||||
|
X89500000Y-90000000D03*
|
||||||
|
D29*
|
||||||
|
X90412500Y-97000000D03*
|
||||||
|
X88587500Y-97000000D03*
|
||||||
|
X90412500Y-99000000D03*
|
||||||
|
X88587500Y-99000000D03*
|
||||||
|
D30*
|
||||||
|
X117704600Y-113560200D03*
|
||||||
|
X117704600Y-114500000D03*
|
||||||
|
X117704600Y-115439800D03*
|
||||||
|
X120295400Y-115439800D03*
|
||||||
|
X120295400Y-113560200D03*
|
||||||
|
D21*
|
||||||
|
X118225000Y-111000000D03*
|
||||||
|
X119775000Y-111000000D03*
|
||||||
|
D20*
|
||||||
|
X86000000Y-92087500D03*
|
||||||
|
X86000000Y-93912500D03*
|
||||||
|
D31*
|
||||||
|
X123087500Y-111000000D03*
|
||||||
|
X124912500Y-111000000D03*
|
||||||
|
D19*
|
||||||
|
X124000000Y-102412500D03*
|
||||||
|
X124000000Y-100587500D03*
|
||||||
|
D17*
|
||||||
|
X84000000Y-100500000D03*
|
||||||
|
X86500000Y-127500000D03*
|
||||||
|
X90000000Y-127500000D03*
|
||||||
|
D19*
|
||||||
|
X128000000Y-102500000D03*
|
||||||
|
X128000000Y-100675000D03*
|
||||||
|
D17*
|
||||||
|
X124500000Y-108500000D03*
|
||||||
|
D19*
|
||||||
|
X118000000Y-102412500D03*
|
||||||
|
X118000000Y-100587500D03*
|
||||||
|
D32*
|
||||||
|
X125984000Y-115583000D03*
|
||||||
|
X125984000Y-114033000D03*
|
||||||
|
D19*
|
||||||
|
X122500000Y-120912500D03*
|
||||||
|
X122500000Y-119087500D03*
|
||||||
|
D20*
|
||||||
|
X90000000Y-113087500D03*
|
||||||
|
X90000000Y-114912500D03*
|
||||||
|
D17*
|
||||||
|
X84000000Y-97500000D03*
|
||||||
|
D33*
|
||||||
|
X125750000Y-83600000D03*
|
||||||
|
X117750000Y-83600000D03*
|
||||||
|
D34*
|
||||||
|
X118550000Y-94650000D03*
|
||||||
|
X119650000Y-94650000D03*
|
||||||
|
X120750000Y-94650000D03*
|
||||||
|
X121850000Y-94650000D03*
|
||||||
|
X122950000Y-94650000D03*
|
||||||
|
X124050000Y-94650000D03*
|
||||||
|
X125150000Y-94650000D03*
|
||||||
|
X126250000Y-94650000D03*
|
||||||
|
X127350000Y-94650000D03*
|
||||||
|
D35*
|
||||||
|
X128900000Y-93600000D03*
|
||||||
|
X113400000Y-93600000D03*
|
||||||
|
D36*
|
||||||
|
X128650000Y-84000000D03*
|
||||||
|
X112950000Y-84000000D03*
|
||||||
|
D19*
|
||||||
|
X126000000Y-102412500D03*
|
||||||
|
X126000000Y-100587500D03*
|
||||||
|
D17*
|
||||||
|
X86175000Y-115373000D03*
|
||||||
|
D19*
|
||||||
|
X120000000Y-120927500D03*
|
||||||
|
X120000000Y-119102500D03*
|
||||||
|
D37*
|
||||||
|
X94500000Y-124225000D03*
|
||||||
|
X94500000Y-125775000D03*
|
||||||
|
D38*
|
||||||
|
X113411000Y-103378000D03*
|
||||||
|
D39*
|
||||||
|
X92911000Y-103378000D03*
|
||||||
|
M02*
|
||||||
215
pcb/production/fw-anwesenheit-F_Paste.gtp
Normal file
215
pcb/production/fw-anwesenheit-F_Paste.gtp
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,9.0.3*
|
||||||
|
G04 #@! TF.CreationDate,2025-08-23T15:15:08+02:00*
|
||||||
|
G04 #@! TF.ProjectId,fw-anwesenheit,66772d61-6e77-4657-9365-6e686569742e,rev?*
|
||||||
|
G04 #@! TF.SameCoordinates,Original*
|
||||||
|
G04 #@! TF.FileFunction,Paste,Top*
|
||||||
|
G04 #@! TF.FilePolarity,Positive*
|
||||||
|
%FSLAX46Y46*%
|
||||||
|
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
|
||||||
|
G04 Created by KiCad (PCBNEW 9.0.3) date 2025-08-23 15:15:08*
|
||||||
|
%MOMM*%
|
||||||
|
%LPD*%
|
||||||
|
G01*
|
||||||
|
G04 APERTURE LIST*
|
||||||
|
G04 Aperture macros list*
|
||||||
|
%AMRoundRect*
|
||||||
|
0 Rectangle with rounded corners*
|
||||||
|
0 $1 Rounding radius*
|
||||||
|
0 $2 $3 $4 $5 $6 $7 $8 $9 X,Y pos of 4 corners*
|
||||||
|
0 Add a 4 corners polygon primitive as box body*
|
||||||
|
4,1,4,$2,$3,$4,$5,$6,$7,$8,$9,$2,$3,0*
|
||||||
|
0 Add four circle primitives for the rounded corners*
|
||||||
|
1,1,$1+$1,$2,$3*
|
||||||
|
1,1,$1+$1,$4,$5*
|
||||||
|
1,1,$1+$1,$6,$7*
|
||||||
|
1,1,$1+$1,$8,$9*
|
||||||
|
0 Add four rect primitives between the rounded corners*
|
||||||
|
20,1,$1+$1,$2,$3,$4,$5,0*
|
||||||
|
20,1,$1+$1,$4,$5,$6,$7,0*
|
||||||
|
20,1,$1+$1,$6,$7,$8,$9,0*
|
||||||
|
20,1,$1+$1,$8,$9,$2,$3,0*%
|
||||||
|
%AMOutline5P*
|
||||||
|
0 Free polygon, 5 corners , with rotation*
|
||||||
|
0 The origin of the aperture is its center*
|
||||||
|
0 number of corners: always 5*
|
||||||
|
0 $1 to $10 corner X, Y*
|
||||||
|
0 $11 Rotation angle, in degrees counterclockwise*
|
||||||
|
0 create outline with 5 corners*
|
||||||
|
4,1,5,$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$1,$2,$11*%
|
||||||
|
%AMOutline6P*
|
||||||
|
0 Free polygon, 6 corners , with rotation*
|
||||||
|
0 The origin of the aperture is its center*
|
||||||
|
0 number of corners: always 6*
|
||||||
|
0 $1 to $12 corner X, Y*
|
||||||
|
0 $13 Rotation angle, in degrees counterclockwise*
|
||||||
|
0 create outline with 6 corners*
|
||||||
|
4,1,6,$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$1,$2,$13*%
|
||||||
|
%AMOutline7P*
|
||||||
|
0 Free polygon, 7 corners , with rotation*
|
||||||
|
0 The origin of the aperture is its center*
|
||||||
|
0 number of corners: always 7*
|
||||||
|
0 $1 to $14 corner X, Y*
|
||||||
|
0 $15 Rotation angle, in degrees counterclockwise*
|
||||||
|
0 create outline with 7 corners*
|
||||||
|
4,1,7,$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$1,$2,$15*%
|
||||||
|
%AMOutline8P*
|
||||||
|
0 Free polygon, 8 corners , with rotation*
|
||||||
|
0 The origin of the aperture is its center*
|
||||||
|
0 number of corners: always 8*
|
||||||
|
0 $1 to $16 corner X, Y*
|
||||||
|
0 $17 Rotation angle, in degrees counterclockwise*
|
||||||
|
0 create outline with 8 corners*
|
||||||
|
4,1,8,$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$1,$2,$17*%
|
||||||
|
G04 Aperture macros list end*
|
||||||
|
%ADD10RoundRect,0.225000X0.225000X0.250000X-0.225000X0.250000X-0.225000X-0.250000X0.225000X-0.250000X0*%
|
||||||
|
%ADD11Outline5P,-1.250000X0.510000X-0.910000X0.850000X1.250000X0.850000X1.250000X-0.850000X-1.250000X-0.850000X0.000000*%
|
||||||
|
%ADD12RoundRect,0.170000X-1.080000X-0.680000X1.080000X-0.680000X1.080000X0.680000X-1.080000X0.680000X0*%
|
||||||
|
%ADD13RoundRect,0.250000X-1.000000X-0.600000X1.000000X-0.600000X1.000000X0.600000X-1.000000X0.600000X0*%
|
||||||
|
%ADD14RoundRect,0.500000X0.875000X0.500000X-0.875000X0.500000X-0.875000X-0.500000X0.875000X-0.500000X0*%
|
||||||
|
%ADD15RoundRect,0.275000X0.275000X-0.975000X0.275000X0.975000X-0.275000X0.975000X-0.275000X-0.975000X0*%
|
||||||
|
%ADD16C,1.700000*%
|
||||||
|
%ADD17RoundRect,0.218750X0.256250X-0.218750X0.256250X0.218750X-0.256250X0.218750X-0.256250X-0.218750X0*%
|
||||||
|
%ADD18RoundRect,0.237500X0.237500X-0.250000X0.237500X0.250000X-0.237500X0.250000X-0.237500X-0.250000X0*%
|
||||||
|
%ADD19RoundRect,0.237500X-0.237500X0.250000X-0.237500X-0.250000X0.237500X-0.250000X0.237500X0.250000X0*%
|
||||||
|
%ADD20RoundRect,0.225000X-0.225000X-0.250000X0.225000X-0.250000X0.225000X0.250000X-0.225000X0.250000X0*%
|
||||||
|
%ADD21RoundRect,0.150000X-0.875000X-0.150000X0.875000X-0.150000X0.875000X0.150000X-0.875000X0.150000X0*%
|
||||||
|
%ADD22RoundRect,0.237500X0.250000X0.237500X-0.250000X0.237500X-0.250000X-0.237500X0.250000X-0.237500X0*%
|
||||||
|
%ADD23R,1.270000X0.558800*%
|
||||||
|
%ADD24RoundRect,0.237500X-0.250000X-0.237500X0.250000X-0.237500X0.250000X0.237500X-0.250000X0.237500X0*%
|
||||||
|
%ADD25RoundRect,0.225000X0.250000X-0.225000X0.250000X0.225000X-0.250000X0.225000X-0.250000X-0.225000X0*%
|
||||||
|
%ADD26R,0.700000X1.900000*%
|
||||||
|
%ADD27R,1.700000X1.800000*%
|
||||||
|
%ADD28R,1.400000X2.600000*%
|
||||||
|
%ADD29RoundRect,0.225000X-0.250000X0.225000X-0.250000X-0.225000X0.250000X-0.225000X0.250000X0.225000X0*%
|
||||||
|
G04 APERTURE END LIST*
|
||||||
|
D10*
|
||||||
|
X123775000Y-97500000D03*
|
||||||
|
X122225000Y-97500000D03*
|
||||||
|
D11*
|
||||||
|
X128778000Y-111252000D03*
|
||||||
|
D12*
|
||||||
|
X128778000Y-113792000D03*
|
||||||
|
D13*
|
||||||
|
X128778000Y-116332000D03*
|
||||||
|
D14*
|
||||||
|
X113821600Y-126598500D03*
|
||||||
|
X113821600Y-124058500D03*
|
||||||
|
X113821600Y-121518500D03*
|
||||||
|
X113821600Y-118978500D03*
|
||||||
|
X113821600Y-116438500D03*
|
||||||
|
X113821600Y-113898500D03*
|
||||||
|
X113821600Y-111358500D03*
|
||||||
|
X97656600Y-111358500D03*
|
||||||
|
X97656600Y-113898500D03*
|
||||||
|
X97656600Y-116438500D03*
|
||||||
|
X97656600Y-118978500D03*
|
||||||
|
X97656600Y-121518500D03*
|
||||||
|
X97656600Y-124058500D03*
|
||||||
|
X97656600Y-126598500D03*
|
||||||
|
D15*
|
||||||
|
X107548000Y-113446800D03*
|
||||||
|
X105008000Y-113446800D03*
|
||||||
|
D16*
|
||||||
|
X107040000Y-127620000D03*
|
||||||
|
X104500000Y-127620000D03*
|
||||||
|
X107040000Y-125080000D03*
|
||||||
|
X104500000Y-125080000D03*
|
||||||
|
X107040000Y-122540000D03*
|
||||||
|
X104500000Y-122540000D03*
|
||||||
|
X107040000Y-120000000D03*
|
||||||
|
X104592600Y-120056800D03*
|
||||||
|
D17*
|
||||||
|
X83500000Y-93787500D03*
|
||||||
|
X83500000Y-92212500D03*
|
||||||
|
D18*
|
||||||
|
X120000000Y-102412500D03*
|
||||||
|
X120000000Y-100587500D03*
|
||||||
|
X122000000Y-102412500D03*
|
||||||
|
X122000000Y-100587500D03*
|
||||||
|
D19*
|
||||||
|
X90000000Y-109087500D03*
|
||||||
|
X90000000Y-110912500D03*
|
||||||
|
D20*
|
||||||
|
X95618000Y-98552000D03*
|
||||||
|
X97168000Y-98552000D03*
|
||||||
|
D21*
|
||||||
|
X99871000Y-97282000D03*
|
||||||
|
X99871000Y-98552000D03*
|
||||||
|
X99871000Y-99822000D03*
|
||||||
|
X99871000Y-101092000D03*
|
||||||
|
X99871000Y-102362000D03*
|
||||||
|
X99871000Y-103632000D03*
|
||||||
|
X99871000Y-104902000D03*
|
||||||
|
X99871000Y-106172000D03*
|
||||||
|
X109171000Y-106172000D03*
|
||||||
|
X109171000Y-104902000D03*
|
||||||
|
X109171000Y-103632000D03*
|
||||||
|
X109171000Y-102362000D03*
|
||||||
|
X109171000Y-101092000D03*
|
||||||
|
X109171000Y-99822000D03*
|
||||||
|
X109171000Y-98552000D03*
|
||||||
|
X109171000Y-97282000D03*
|
||||||
|
D18*
|
||||||
|
X116000000Y-102412500D03*
|
||||||
|
X116000000Y-100587500D03*
|
||||||
|
D22*
|
||||||
|
X90412500Y-97000000D03*
|
||||||
|
X88587500Y-97000000D03*
|
||||||
|
X90412500Y-99000000D03*
|
||||||
|
X88587500Y-99000000D03*
|
||||||
|
D23*
|
||||||
|
X117704600Y-113560200D03*
|
||||||
|
X117704600Y-114500000D03*
|
||||||
|
X117704600Y-115439800D03*
|
||||||
|
X120295400Y-115439800D03*
|
||||||
|
X120295400Y-113560200D03*
|
||||||
|
D20*
|
||||||
|
X118225000Y-111000000D03*
|
||||||
|
X119775000Y-111000000D03*
|
||||||
|
D19*
|
||||||
|
X86000000Y-92087500D03*
|
||||||
|
X86000000Y-93912500D03*
|
||||||
|
D24*
|
||||||
|
X123087500Y-111000000D03*
|
||||||
|
X124912500Y-111000000D03*
|
||||||
|
D18*
|
||||||
|
X124000000Y-102412500D03*
|
||||||
|
X124000000Y-100587500D03*
|
||||||
|
X128000000Y-102500000D03*
|
||||||
|
X128000000Y-100675000D03*
|
||||||
|
X118000000Y-102412500D03*
|
||||||
|
X118000000Y-100587500D03*
|
||||||
|
D25*
|
||||||
|
X125984000Y-115583000D03*
|
||||||
|
X125984000Y-114033000D03*
|
||||||
|
D18*
|
||||||
|
X122500000Y-120912500D03*
|
||||||
|
X122500000Y-119087500D03*
|
||||||
|
D19*
|
||||||
|
X90000000Y-113087500D03*
|
||||||
|
X90000000Y-114912500D03*
|
||||||
|
D26*
|
||||||
|
X118550000Y-94650000D03*
|
||||||
|
X119650000Y-94650000D03*
|
||||||
|
X120750000Y-94650000D03*
|
||||||
|
X121850000Y-94650000D03*
|
||||||
|
X122950000Y-94650000D03*
|
||||||
|
X124050000Y-94650000D03*
|
||||||
|
X125150000Y-94650000D03*
|
||||||
|
X126250000Y-94650000D03*
|
||||||
|
X127350000Y-94650000D03*
|
||||||
|
D27*
|
||||||
|
X128900000Y-93600000D03*
|
||||||
|
X113400000Y-93600000D03*
|
||||||
|
D28*
|
||||||
|
X128650000Y-84000000D03*
|
||||||
|
X112950000Y-84000000D03*
|
||||||
|
D18*
|
||||||
|
X126000000Y-102412500D03*
|
||||||
|
X126000000Y-100587500D03*
|
||||||
|
X120000000Y-120927500D03*
|
||||||
|
X120000000Y-119102500D03*
|
||||||
|
D29*
|
||||||
|
X94500000Y-124225000D03*
|
||||||
|
X94500000Y-125775000D03*
|
||||||
|
M02*
|
||||||
1963
pcb/production/fw-anwesenheit-F_Silkscreen.gto
Normal file
1963
pcb/production/fw-anwesenheit-F_Silkscreen.gto
Normal file
File diff suppressed because it is too large
Load Diff
4667
pcb/production/fw-anwesenheit-In1_Cu.g1
Normal file
4667
pcb/production/fw-anwesenheit-In1_Cu.g1
Normal file
File diff suppressed because it is too large
Load Diff
9045
pcb/production/fw-anwesenheit-In2_Cu.g2
Normal file
9045
pcb/production/fw-anwesenheit-In2_Cu.g2
Normal file
File diff suppressed because it is too large
Load Diff
4766
pcb/production/fw-anwesenheit-In3_Cu.g3
Normal file
4766
pcb/production/fw-anwesenheit-In3_Cu.g3
Normal file
File diff suppressed because it is too large
Load Diff
4667
pcb/production/fw-anwesenheit-In4_Cu.g4
Normal file
4667
pcb/production/fw-anwesenheit-In4_Cu.g4
Normal file
File diff suppressed because it is too large
Load Diff
996
pcb/production/fw-anwesenheit-NPTH-drl_map.gbr
Normal file
996
pcb/production/fw-anwesenheit-NPTH-drl_map.gbr
Normal file
@@ -0,0 +1,996 @@
|
|||||||
|
%TF.GenerationSoftware,KiCad,Pcbnew,9.0.3*%
|
||||||
|
%TF.CreationDate,2025-08-23T15:15:25+02:00*%
|
||||||
|
%TF.ProjectId,fw-anwesenheit,66772d61-6e77-4657-9365-6e686569742e,rev?*%
|
||||||
|
%TF.SameCoordinates,Original*%
|
||||||
|
%TF.FileFunction,Drillmap*%
|
||||||
|
%TF.FilePolarity,Positive*%
|
||||||
|
%FSLAX45Y45*%
|
||||||
|
G04 Gerber Fmt 4.5, Leading zero omitted, Abs format (unit mm)*
|
||||||
|
G04 Created by KiCad (PCBNEW 9.0.3) date 2025-08-23 15:15:25*
|
||||||
|
%MOMM*%
|
||||||
|
%LPD*%
|
||||||
|
G01*
|
||||||
|
G04 APERTURE LIST*
|
||||||
|
%ADD10C,1.025000*%
|
||||||
|
%ADD11C,0.050000*%
|
||||||
|
%ADD12C,0.010000*%
|
||||||
|
%ADD13C,0.200000*%
|
||||||
|
%ADD14C,0.100000*%
|
||||||
|
G04 APERTURE END LIST*
|
||||||
|
D10*
|
||||||
|
X8551250Y-12350000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X8448750Y-12350000I-51250J0D01*
|
||||||
|
G01*
|
||||||
|
X8448750Y-12350000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X8551250Y-12350000I51250J0D01*
|
||||||
|
G01*
|
||||||
|
X8551250Y-8500000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X8448750Y-8500000I-51250J0D01*
|
||||||
|
G01*
|
||||||
|
X8448750Y-8500000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X8551250Y-8500000I51250J0D01*
|
||||||
|
G01*
|
||||||
|
D11*
|
||||||
|
X8104500Y-7950200D02*
|
||||||
|
X13104500Y-7950200D01*
|
||||||
|
X13104500Y-12950200D01*
|
||||||
|
X8104500Y-12950200D01*
|
||||||
|
X8104500Y-7950200D01*
|
||||||
|
D10*
|
||||||
|
X12751250Y-12350000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X12648750Y-12350000I-51250J0D01*
|
||||||
|
G01*
|
||||||
|
X12648750Y-12350000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X12751250Y-12350000I51250J0D01*
|
||||||
|
G01*
|
||||||
|
X10951250Y-8500000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X10848750Y-8500000I-51250J0D01*
|
||||||
|
G01*
|
||||||
|
X10848750Y-8500000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X10951250Y-8500000I51250J0D01*
|
||||||
|
G01*
|
||||||
|
D12*
|
||||||
|
X11740000Y-8310000D02*
|
||||||
|
X11810000Y-8310000D01*
|
||||||
|
X11810000Y-8410000D02*
|
||||||
|
X11740000Y-8410000D01*
|
||||||
|
X11690000Y-8360000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X11740000Y-8310000I50000J0D01*
|
||||||
|
G01*
|
||||||
|
X11740000Y-8410000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X11690000Y-8360000I0J50000D01*
|
||||||
|
G01*
|
||||||
|
X11810000Y-8310000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X11860000Y-8360000I0J-50000D01*
|
||||||
|
G01*
|
||||||
|
X11860000Y-8360000D02*
|
||||||
|
G75*
|
||||||
|
G02*
|
||||||
|
X11810000Y-8410000I-50000J0D01*
|
||||||
|
G01*
|
||||||
|
D13*
|
||||||
|
D14*
|
||||||
|
X11725000Y-8310000D02*
|
||||||
|
X11825000Y-8410000D01*
|
||||||
|
X11825000Y-8310000D02*
|
||||||
|
X11725000Y-8410000D01*
|
||||||
|
X12525000Y-8310000D02*
|
||||||
|
X12625000Y-8410000D01*
|
||||||
|
X12625000Y-8310000D02*
|
||||||
|
X12525000Y-8410000D01*
|
||||||
|
D13*
|
||||||
|
X8362777Y-13264184D02*
|
||||||
|
X8362777Y-13064184D01*
|
||||||
|
X8362777Y-13064184D02*
|
||||||
|
X8410396Y-13064184D01*
|
||||||
|
X8410396Y-13064184D02*
|
||||||
|
X8438967Y-13073708D01*
|
||||||
|
X8438967Y-13073708D02*
|
||||||
|
X8458015Y-13092755D01*
|
||||||
|
X8458015Y-13092755D02*
|
||||||
|
X8467539Y-13111803D01*
|
||||||
|
X8467539Y-13111803D02*
|
||||||
|
X8477063Y-13149898D01*
|
||||||
|
X8477063Y-13149898D02*
|
||||||
|
X8477063Y-13178469D01*
|
||||||
|
X8477063Y-13178469D02*
|
||||||
|
X8467539Y-13216565D01*
|
||||||
|
X8467539Y-13216565D02*
|
||||||
|
X8458015Y-13235612D01*
|
||||||
|
X8458015Y-13235612D02*
|
||||||
|
X8438967Y-13254660D01*
|
||||||
|
X8438967Y-13254660D02*
|
||||||
|
X8410396Y-13264184D01*
|
||||||
|
X8410396Y-13264184D02*
|
||||||
|
X8362777Y-13264184D01*
|
||||||
|
X8562777Y-13264184D02*
|
||||||
|
X8562777Y-13130850D01*
|
||||||
|
X8562777Y-13168946D02*
|
||||||
|
X8572301Y-13149898D01*
|
||||||
|
X8572301Y-13149898D02*
|
||||||
|
X8581824Y-13140374D01*
|
||||||
|
X8581824Y-13140374D02*
|
||||||
|
X8600872Y-13130850D01*
|
||||||
|
X8600872Y-13130850D02*
|
||||||
|
X8619920Y-13130850D01*
|
||||||
|
X8686586Y-13264184D02*
|
||||||
|
X8686586Y-13130850D01*
|
||||||
|
X8686586Y-13064184D02*
|
||||||
|
X8677063Y-13073708D01*
|
||||||
|
X8677063Y-13073708D02*
|
||||||
|
X8686586Y-13083231D01*
|
||||||
|
X8686586Y-13083231D02*
|
||||||
|
X8696110Y-13073708D01*
|
||||||
|
X8696110Y-13073708D02*
|
||||||
|
X8686586Y-13064184D01*
|
||||||
|
X8686586Y-13064184D02*
|
||||||
|
X8686586Y-13083231D01*
|
||||||
|
X8810396Y-13264184D02*
|
||||||
|
X8791348Y-13254660D01*
|
||||||
|
X8791348Y-13254660D02*
|
||||||
|
X8781824Y-13235612D01*
|
||||||
|
X8781824Y-13235612D02*
|
||||||
|
X8781824Y-13064184D01*
|
||||||
|
X8915158Y-13264184D02*
|
||||||
|
X8896110Y-13254660D01*
|
||||||
|
X8896110Y-13254660D02*
|
||||||
|
X8886586Y-13235612D01*
|
||||||
|
X8886586Y-13235612D02*
|
||||||
|
X8886586Y-13064184D01*
|
||||||
|
X9143729Y-13264184D02*
|
||||||
|
X9143729Y-13064184D01*
|
||||||
|
X9143729Y-13064184D02*
|
||||||
|
X9210396Y-13207041D01*
|
||||||
|
X9210396Y-13207041D02*
|
||||||
|
X9277063Y-13064184D01*
|
||||||
|
X9277063Y-13064184D02*
|
||||||
|
X9277063Y-13264184D01*
|
||||||
|
X9458015Y-13264184D02*
|
||||||
|
X9458015Y-13159422D01*
|
||||||
|
X9458015Y-13159422D02*
|
||||||
|
X9448491Y-13140374D01*
|
||||||
|
X9448491Y-13140374D02*
|
||||||
|
X9429444Y-13130850D01*
|
||||||
|
X9429444Y-13130850D02*
|
||||||
|
X9391348Y-13130850D01*
|
||||||
|
X9391348Y-13130850D02*
|
||||||
|
X9372301Y-13140374D01*
|
||||||
|
X9458015Y-13254660D02*
|
||||||
|
X9438967Y-13264184D01*
|
||||||
|
X9438967Y-13264184D02*
|
||||||
|
X9391348Y-13264184D01*
|
||||||
|
X9391348Y-13264184D02*
|
||||||
|
X9372301Y-13254660D01*
|
||||||
|
X9372301Y-13254660D02*
|
||||||
|
X9362777Y-13235612D01*
|
||||||
|
X9362777Y-13235612D02*
|
||||||
|
X9362777Y-13216565D01*
|
||||||
|
X9362777Y-13216565D02*
|
||||||
|
X9372301Y-13197517D01*
|
||||||
|
X9372301Y-13197517D02*
|
||||||
|
X9391348Y-13187993D01*
|
||||||
|
X9391348Y-13187993D02*
|
||||||
|
X9438967Y-13187993D01*
|
||||||
|
X9438967Y-13187993D02*
|
||||||
|
X9458015Y-13178469D01*
|
||||||
|
X9553253Y-13130850D02*
|
||||||
|
X9553253Y-13330850D01*
|
||||||
|
X9553253Y-13140374D02*
|
||||||
|
X9572301Y-13130850D01*
|
||||||
|
X9572301Y-13130850D02*
|
||||||
|
X9610396Y-13130850D01*
|
||||||
|
X9610396Y-13130850D02*
|
||||||
|
X9629444Y-13140374D01*
|
||||||
|
X9629444Y-13140374D02*
|
||||||
|
X9638967Y-13149898D01*
|
||||||
|
X9638967Y-13149898D02*
|
||||||
|
X9648491Y-13168946D01*
|
||||||
|
X9648491Y-13168946D02*
|
||||||
|
X9648491Y-13226088D01*
|
||||||
|
X9648491Y-13226088D02*
|
||||||
|
X9638967Y-13245136D01*
|
||||||
|
X9638967Y-13245136D02*
|
||||||
|
X9629444Y-13254660D01*
|
||||||
|
X9629444Y-13254660D02*
|
||||||
|
X9610396Y-13264184D01*
|
||||||
|
X9610396Y-13264184D02*
|
||||||
|
X9572301Y-13264184D01*
|
||||||
|
X9572301Y-13264184D02*
|
||||||
|
X9553253Y-13254660D01*
|
||||||
|
X9734205Y-13245136D02*
|
||||||
|
X9743729Y-13254660D01*
|
||||||
|
X9743729Y-13254660D02*
|
||||||
|
X9734205Y-13264184D01*
|
||||||
|
X9734205Y-13264184D02*
|
||||||
|
X9724682Y-13254660D01*
|
||||||
|
X9724682Y-13254660D02*
|
||||||
|
X9734205Y-13245136D01*
|
||||||
|
X9734205Y-13245136D02*
|
||||||
|
X9734205Y-13264184D01*
|
||||||
|
X9734205Y-13140374D02*
|
||||||
|
X9743729Y-13149898D01*
|
||||||
|
X9743729Y-13149898D02*
|
||||||
|
X9734205Y-13159422D01*
|
||||||
|
X9734205Y-13159422D02*
|
||||||
|
X9724682Y-13149898D01*
|
||||||
|
X9724682Y-13149898D02*
|
||||||
|
X9734205Y-13140374D01*
|
||||||
|
X9734205Y-13140374D02*
|
||||||
|
X9734205Y-13159422D01*
|
||||||
|
D14*
|
||||||
|
X8002000Y-13542700D02*
|
||||||
|
X8102000Y-13642700D01*
|
||||||
|
X8102000Y-13542700D02*
|
||||||
|
X8002000Y-13642700D01*
|
||||||
|
D13*
|
||||||
|
X8467539Y-13684184D02*
|
||||||
|
X8353253Y-13684184D01*
|
||||||
|
X8410396Y-13684184D02*
|
||||||
|
X8410396Y-13484184D01*
|
||||||
|
X8410396Y-13484184D02*
|
||||||
|
X8391348Y-13512755D01*
|
||||||
|
X8391348Y-13512755D02*
|
||||||
|
X8372301Y-13531803D01*
|
||||||
|
X8372301Y-13531803D02*
|
||||||
|
X8353253Y-13541327D01*
|
||||||
|
X8553253Y-13665136D02*
|
||||||
|
X8562777Y-13674660D01*
|
||||||
|
X8562777Y-13674660D02*
|
||||||
|
X8553253Y-13684184D01*
|
||||||
|
X8553253Y-13684184D02*
|
||||||
|
X8543729Y-13674660D01*
|
||||||
|
X8543729Y-13674660D02*
|
||||||
|
X8553253Y-13665136D01*
|
||||||
|
X8553253Y-13665136D02*
|
||||||
|
X8553253Y-13684184D01*
|
||||||
|
X8686586Y-13484184D02*
|
||||||
|
X8705634Y-13484184D01*
|
||||||
|
X8705634Y-13484184D02*
|
||||||
|
X8724682Y-13493708D01*
|
||||||
|
X8724682Y-13493708D02*
|
||||||
|
X8734205Y-13503231D01*
|
||||||
|
X8734205Y-13503231D02*
|
||||||
|
X8743729Y-13522279D01*
|
||||||
|
X8743729Y-13522279D02*
|
||||||
|
X8753253Y-13560374D01*
|
||||||
|
X8753253Y-13560374D02*
|
||||||
|
X8753253Y-13607993D01*
|
||||||
|
X8753253Y-13607993D02*
|
||||||
|
X8743729Y-13646088D01*
|
||||||
|
X8743729Y-13646088D02*
|
||||||
|
X8734205Y-13665136D01*
|
||||||
|
X8734205Y-13665136D02*
|
||||||
|
X8724682Y-13674660D01*
|
||||||
|
X8724682Y-13674660D02*
|
||||||
|
X8705634Y-13684184D01*
|
||||||
|
X8705634Y-13684184D02*
|
||||||
|
X8686586Y-13684184D01*
|
||||||
|
X8686586Y-13684184D02*
|
||||||
|
X8667539Y-13674660D01*
|
||||||
|
X8667539Y-13674660D02*
|
||||||
|
X8658015Y-13665136D01*
|
||||||
|
X8658015Y-13665136D02*
|
||||||
|
X8648491Y-13646088D01*
|
||||||
|
X8648491Y-13646088D02*
|
||||||
|
X8638967Y-13607993D01*
|
||||||
|
X8638967Y-13607993D02*
|
||||||
|
X8638967Y-13560374D01*
|
||||||
|
X8638967Y-13560374D02*
|
||||||
|
X8648491Y-13522279D01*
|
||||||
|
X8648491Y-13522279D02*
|
||||||
|
X8658015Y-13503231D01*
|
||||||
|
X8658015Y-13503231D02*
|
||||||
|
X8667539Y-13493708D01*
|
||||||
|
X8667539Y-13493708D02*
|
||||||
|
X8686586Y-13484184D01*
|
||||||
|
X8877063Y-13484184D02*
|
||||||
|
X8896110Y-13484184D01*
|
||||||
|
X8896110Y-13484184D02*
|
||||||
|
X8915158Y-13493708D01*
|
||||||
|
X8915158Y-13493708D02*
|
||||||
|
X8924682Y-13503231D01*
|
||||||
|
X8924682Y-13503231D02*
|
||||||
|
X8934205Y-13522279D01*
|
||||||
|
X8934205Y-13522279D02*
|
||||||
|
X8943729Y-13560374D01*
|
||||||
|
X8943729Y-13560374D02*
|
||||||
|
X8943729Y-13607993D01*
|
||||||
|
X8943729Y-13607993D02*
|
||||||
|
X8934205Y-13646088D01*
|
||||||
|
X8934205Y-13646088D02*
|
||||||
|
X8924682Y-13665136D01*
|
||||||
|
X8924682Y-13665136D02*
|
||||||
|
X8915158Y-13674660D01*
|
||||||
|
X8915158Y-13674660D02*
|
||||||
|
X8896110Y-13684184D01*
|
||||||
|
X8896110Y-13684184D02*
|
||||||
|
X8877063Y-13684184D01*
|
||||||
|
X8877063Y-13684184D02*
|
||||||
|
X8858015Y-13674660D01*
|
||||||
|
X8858015Y-13674660D02*
|
||||||
|
X8848491Y-13665136D01*
|
||||||
|
X8848491Y-13665136D02*
|
||||||
|
X8838967Y-13646088D01*
|
||||||
|
X8838967Y-13646088D02*
|
||||||
|
X8829444Y-13607993D01*
|
||||||
|
X8829444Y-13607993D02*
|
||||||
|
X8829444Y-13560374D01*
|
||||||
|
X8829444Y-13560374D02*
|
||||||
|
X8838967Y-13522279D01*
|
||||||
|
X8838967Y-13522279D02*
|
||||||
|
X8848491Y-13503231D01*
|
||||||
|
X8848491Y-13503231D02*
|
||||||
|
X8858015Y-13493708D01*
|
||||||
|
X8858015Y-13493708D02*
|
||||||
|
X8877063Y-13484184D01*
|
||||||
|
X9067539Y-13484184D02*
|
||||||
|
X9086586Y-13484184D01*
|
||||||
|
X9086586Y-13484184D02*
|
||||||
|
X9105634Y-13493708D01*
|
||||||
|
X9105634Y-13493708D02*
|
||||||
|
X9115158Y-13503231D01*
|
||||||
|
X9115158Y-13503231D02*
|
||||||
|
X9124682Y-13522279D01*
|
||||||
|
X9124682Y-13522279D02*
|
||||||
|
X9134205Y-13560374D01*
|
||||||
|
X9134205Y-13560374D02*
|
||||||
|
X9134205Y-13607993D01*
|
||||||
|
X9134205Y-13607993D02*
|
||||||
|
X9124682Y-13646088D01*
|
||||||
|
X9124682Y-13646088D02*
|
||||||
|
X9115158Y-13665136D01*
|
||||||
|
X9115158Y-13665136D02*
|
||||||
|
X9105634Y-13674660D01*
|
||||||
|
X9105634Y-13674660D02*
|
||||||
|
X9086586Y-13684184D01*
|
||||||
|
X9086586Y-13684184D02*
|
||||||
|
X9067539Y-13684184D01*
|
||||||
|
X9067539Y-13684184D02*
|
||||||
|
X9048491Y-13674660D01*
|
||||||
|
X9048491Y-13674660D02*
|
||||||
|
X9038967Y-13665136D01*
|
||||||
|
X9038967Y-13665136D02*
|
||||||
|
X9029444Y-13646088D01*
|
||||||
|
X9029444Y-13646088D02*
|
||||||
|
X9019920Y-13607993D01*
|
||||||
|
X9019920Y-13607993D02*
|
||||||
|
X9019920Y-13560374D01*
|
||||||
|
X9019920Y-13560374D02*
|
||||||
|
X9029444Y-13522279D01*
|
||||||
|
X9029444Y-13522279D02*
|
||||||
|
X9038967Y-13503231D01*
|
||||||
|
X9038967Y-13503231D02*
|
||||||
|
X9048491Y-13493708D01*
|
||||||
|
X9048491Y-13493708D02*
|
||||||
|
X9067539Y-13484184D01*
|
||||||
|
X9219920Y-13684184D02*
|
||||||
|
X9219920Y-13550850D01*
|
||||||
|
X9219920Y-13569898D02*
|
||||||
|
X9229444Y-13560374D01*
|
||||||
|
X9229444Y-13560374D02*
|
||||||
|
X9248491Y-13550850D01*
|
||||||
|
X9248491Y-13550850D02*
|
||||||
|
X9277063Y-13550850D01*
|
||||||
|
X9277063Y-13550850D02*
|
||||||
|
X9296110Y-13560374D01*
|
||||||
|
X9296110Y-13560374D02*
|
||||||
|
X9305634Y-13579422D01*
|
||||||
|
X9305634Y-13579422D02*
|
||||||
|
X9305634Y-13684184D01*
|
||||||
|
X9305634Y-13579422D02*
|
||||||
|
X9315158Y-13560374D01*
|
||||||
|
X9315158Y-13560374D02*
|
||||||
|
X9334205Y-13550850D01*
|
||||||
|
X9334205Y-13550850D02*
|
||||||
|
X9362777Y-13550850D01*
|
||||||
|
X9362777Y-13550850D02*
|
||||||
|
X9381825Y-13560374D01*
|
||||||
|
X9381825Y-13560374D02*
|
||||||
|
X9391348Y-13579422D01*
|
||||||
|
X9391348Y-13579422D02*
|
||||||
|
X9391348Y-13684184D01*
|
||||||
|
X9486586Y-13684184D02*
|
||||||
|
X9486586Y-13550850D01*
|
||||||
|
X9486586Y-13569898D02*
|
||||||
|
X9496110Y-13560374D01*
|
||||||
|
X9496110Y-13560374D02*
|
||||||
|
X9515158Y-13550850D01*
|
||||||
|
X9515158Y-13550850D02*
|
||||||
|
X9543729Y-13550850D01*
|
||||||
|
X9543729Y-13550850D02*
|
||||||
|
X9562777Y-13560374D01*
|
||||||
|
X9562777Y-13560374D02*
|
||||||
|
X9572301Y-13579422D01*
|
||||||
|
X9572301Y-13579422D02*
|
||||||
|
X9572301Y-13684184D01*
|
||||||
|
X9572301Y-13579422D02*
|
||||||
|
X9581825Y-13560374D01*
|
||||||
|
X9581825Y-13560374D02*
|
||||||
|
X9600872Y-13550850D01*
|
||||||
|
X9600872Y-13550850D02*
|
||||||
|
X9629444Y-13550850D01*
|
||||||
|
X9629444Y-13550850D02*
|
||||||
|
X9648491Y-13560374D01*
|
||||||
|
X9648491Y-13560374D02*
|
||||||
|
X9658015Y-13579422D01*
|
||||||
|
X9658015Y-13579422D02*
|
||||||
|
X9658015Y-13684184D01*
|
||||||
|
X10048491Y-13474660D02*
|
||||||
|
X9877063Y-13731803D01*
|
||||||
|
X10305634Y-13484184D02*
|
||||||
|
X10324682Y-13484184D01*
|
||||||
|
X10324682Y-13484184D02*
|
||||||
|
X10343729Y-13493708D01*
|
||||||
|
X10343729Y-13493708D02*
|
||||||
|
X10353253Y-13503231D01*
|
||||||
|
X10353253Y-13503231D02*
|
||||||
|
X10362777Y-13522279D01*
|
||||||
|
X10362777Y-13522279D02*
|
||||||
|
X10372301Y-13560374D01*
|
||||||
|
X10372301Y-13560374D02*
|
||||||
|
X10372301Y-13607993D01*
|
||||||
|
X10372301Y-13607993D02*
|
||||||
|
X10362777Y-13646088D01*
|
||||||
|
X10362777Y-13646088D02*
|
||||||
|
X10353253Y-13665136D01*
|
||||||
|
X10353253Y-13665136D02*
|
||||||
|
X10343729Y-13674660D01*
|
||||||
|
X10343729Y-13674660D02*
|
||||||
|
X10324682Y-13684184D01*
|
||||||
|
X10324682Y-13684184D02*
|
||||||
|
X10305634Y-13684184D01*
|
||||||
|
X10305634Y-13684184D02*
|
||||||
|
X10286587Y-13674660D01*
|
||||||
|
X10286587Y-13674660D02*
|
||||||
|
X10277063Y-13665136D01*
|
||||||
|
X10277063Y-13665136D02*
|
||||||
|
X10267539Y-13646088D01*
|
||||||
|
X10267539Y-13646088D02*
|
||||||
|
X10258015Y-13607993D01*
|
||||||
|
X10258015Y-13607993D02*
|
||||||
|
X10258015Y-13560374D01*
|
||||||
|
X10258015Y-13560374D02*
|
||||||
|
X10267539Y-13522279D01*
|
||||||
|
X10267539Y-13522279D02*
|
||||||
|
X10277063Y-13503231D01*
|
||||||
|
X10277063Y-13503231D02*
|
||||||
|
X10286587Y-13493708D01*
|
||||||
|
X10286587Y-13493708D02*
|
||||||
|
X10305634Y-13484184D01*
|
||||||
|
X10458015Y-13665136D02*
|
||||||
|
X10467539Y-13674660D01*
|
||||||
|
X10467539Y-13674660D02*
|
||||||
|
X10458015Y-13684184D01*
|
||||||
|
X10458015Y-13684184D02*
|
||||||
|
X10448491Y-13674660D01*
|
||||||
|
X10448491Y-13674660D02*
|
||||||
|
X10458015Y-13665136D01*
|
||||||
|
X10458015Y-13665136D02*
|
||||||
|
X10458015Y-13684184D01*
|
||||||
|
X10591348Y-13484184D02*
|
||||||
|
X10610396Y-13484184D01*
|
||||||
|
X10610396Y-13484184D02*
|
||||||
|
X10629444Y-13493708D01*
|
||||||
|
X10629444Y-13493708D02*
|
||||||
|
X10638968Y-13503231D01*
|
||||||
|
X10638968Y-13503231D02*
|
||||||
|
X10648491Y-13522279D01*
|
||||||
|
X10648491Y-13522279D02*
|
||||||
|
X10658015Y-13560374D01*
|
||||||
|
X10658015Y-13560374D02*
|
||||||
|
X10658015Y-13607993D01*
|
||||||
|
X10658015Y-13607993D02*
|
||||||
|
X10648491Y-13646088D01*
|
||||||
|
X10648491Y-13646088D02*
|
||||||
|
X10638968Y-13665136D01*
|
||||||
|
X10638968Y-13665136D02*
|
||||||
|
X10629444Y-13674660D01*
|
||||||
|
X10629444Y-13674660D02*
|
||||||
|
X10610396Y-13684184D01*
|
||||||
|
X10610396Y-13684184D02*
|
||||||
|
X10591348Y-13684184D01*
|
||||||
|
X10591348Y-13684184D02*
|
||||||
|
X10572301Y-13674660D01*
|
||||||
|
X10572301Y-13674660D02*
|
||||||
|
X10562777Y-13665136D01*
|
||||||
|
X10562777Y-13665136D02*
|
||||||
|
X10553253Y-13646088D01*
|
||||||
|
X10553253Y-13646088D02*
|
||||||
|
X10543729Y-13607993D01*
|
||||||
|
X10543729Y-13607993D02*
|
||||||
|
X10543729Y-13560374D01*
|
||||||
|
X10543729Y-13560374D02*
|
||||||
|
X10553253Y-13522279D01*
|
||||||
|
X10553253Y-13522279D02*
|
||||||
|
X10562777Y-13503231D01*
|
||||||
|
X10562777Y-13503231D02*
|
||||||
|
X10572301Y-13493708D01*
|
||||||
|
X10572301Y-13493708D02*
|
||||||
|
X10591348Y-13484184D01*
|
||||||
|
X10724682Y-13484184D02*
|
||||||
|
X10848491Y-13484184D01*
|
||||||
|
X10848491Y-13484184D02*
|
||||||
|
X10781825Y-13560374D01*
|
||||||
|
X10781825Y-13560374D02*
|
||||||
|
X10810396Y-13560374D01*
|
||||||
|
X10810396Y-13560374D02*
|
||||||
|
X10829444Y-13569898D01*
|
||||||
|
X10829444Y-13569898D02*
|
||||||
|
X10838968Y-13579422D01*
|
||||||
|
X10838968Y-13579422D02*
|
||||||
|
X10848491Y-13598469D01*
|
||||||
|
X10848491Y-13598469D02*
|
||||||
|
X10848491Y-13646088D01*
|
||||||
|
X10848491Y-13646088D02*
|
||||||
|
X10838968Y-13665136D01*
|
||||||
|
X10838968Y-13665136D02*
|
||||||
|
X10829444Y-13674660D01*
|
||||||
|
X10829444Y-13674660D02*
|
||||||
|
X10810396Y-13684184D01*
|
||||||
|
X10810396Y-13684184D02*
|
||||||
|
X10753253Y-13684184D01*
|
||||||
|
X10753253Y-13684184D02*
|
||||||
|
X10734206Y-13674660D01*
|
||||||
|
X10734206Y-13674660D02*
|
||||||
|
X10724682Y-13665136D01*
|
||||||
|
X10943729Y-13684184D02*
|
||||||
|
X10981825Y-13684184D01*
|
||||||
|
X10981825Y-13684184D02*
|
||||||
|
X11000872Y-13674660D01*
|
||||||
|
X11000872Y-13674660D02*
|
||||||
|
X11010396Y-13665136D01*
|
||||||
|
X11010396Y-13665136D02*
|
||||||
|
X11029444Y-13636565D01*
|
||||||
|
X11029444Y-13636565D02*
|
||||||
|
X11038968Y-13598469D01*
|
||||||
|
X11038968Y-13598469D02*
|
||||||
|
X11038968Y-13522279D01*
|
||||||
|
X11038968Y-13522279D02*
|
||||||
|
X11029444Y-13503231D01*
|
||||||
|
X11029444Y-13503231D02*
|
||||||
|
X11019920Y-13493708D01*
|
||||||
|
X11019920Y-13493708D02*
|
||||||
|
X11000872Y-13484184D01*
|
||||||
|
X11000872Y-13484184D02*
|
||||||
|
X10962777Y-13484184D01*
|
||||||
|
X10962777Y-13484184D02*
|
||||||
|
X10943729Y-13493708D01*
|
||||||
|
X10943729Y-13493708D02*
|
||||||
|
X10934206Y-13503231D01*
|
||||||
|
X10934206Y-13503231D02*
|
||||||
|
X10924682Y-13522279D01*
|
||||||
|
X10924682Y-13522279D02*
|
||||||
|
X10924682Y-13569898D01*
|
||||||
|
X10924682Y-13569898D02*
|
||||||
|
X10934206Y-13588946D01*
|
||||||
|
X10934206Y-13588946D02*
|
||||||
|
X10943729Y-13598469D01*
|
||||||
|
X10943729Y-13598469D02*
|
||||||
|
X10962777Y-13607993D01*
|
||||||
|
X10962777Y-13607993D02*
|
||||||
|
X11000872Y-13607993D01*
|
||||||
|
X11000872Y-13607993D02*
|
||||||
|
X11019920Y-13598469D01*
|
||||||
|
X11019920Y-13598469D02*
|
||||||
|
X11029444Y-13588946D01*
|
||||||
|
X11029444Y-13588946D02*
|
||||||
|
X11038968Y-13569898D01*
|
||||||
|
X11210396Y-13550850D02*
|
||||||
|
X11210396Y-13684184D01*
|
||||||
|
X11162777Y-13474660D02*
|
||||||
|
X11115158Y-13617517D01*
|
||||||
|
X11115158Y-13617517D02*
|
||||||
|
X11238967Y-13617517D01*
|
||||||
|
X11305634Y-13484184D02*
|
||||||
|
X11305634Y-13522279D01*
|
||||||
|
X11381825Y-13484184D02*
|
||||||
|
X11381825Y-13522279D01*
|
||||||
|
X11677063Y-13760374D02*
|
||||||
|
X11667539Y-13750850D01*
|
||||||
|
X11667539Y-13750850D02*
|
||||||
|
X11648491Y-13722279D01*
|
||||||
|
X11648491Y-13722279D02*
|
||||||
|
X11638968Y-13703231D01*
|
||||||
|
X11638968Y-13703231D02*
|
||||||
|
X11629444Y-13674660D01*
|
||||||
|
X11629444Y-13674660D02*
|
||||||
|
X11619920Y-13627041D01*
|
||||||
|
X11619920Y-13627041D02*
|
||||||
|
X11619920Y-13588946D01*
|
||||||
|
X11619920Y-13588946D02*
|
||||||
|
X11629444Y-13541327D01*
|
||||||
|
X11629444Y-13541327D02*
|
||||||
|
X11638968Y-13512755D01*
|
||||||
|
X11638968Y-13512755D02*
|
||||||
|
X11648491Y-13493708D01*
|
||||||
|
X11648491Y-13493708D02*
|
||||||
|
X11667539Y-13465136D01*
|
||||||
|
X11667539Y-13465136D02*
|
||||||
|
X11677063Y-13455612D01*
|
||||||
|
X11743729Y-13503231D02*
|
||||||
|
X11753253Y-13493708D01*
|
||||||
|
X11753253Y-13493708D02*
|
||||||
|
X11772301Y-13484184D01*
|
||||||
|
X11772301Y-13484184D02*
|
||||||
|
X11819920Y-13484184D01*
|
||||||
|
X11819920Y-13484184D02*
|
||||||
|
X11838968Y-13493708D01*
|
||||||
|
X11838968Y-13493708D02*
|
||||||
|
X11848491Y-13503231D01*
|
||||||
|
X11848491Y-13503231D02*
|
||||||
|
X11858015Y-13522279D01*
|
||||||
|
X11858015Y-13522279D02*
|
||||||
|
X11858015Y-13541327D01*
|
||||||
|
X11858015Y-13541327D02*
|
||||||
|
X11848491Y-13569898D01*
|
||||||
|
X11848491Y-13569898D02*
|
||||||
|
X11734206Y-13684184D01*
|
||||||
|
X11734206Y-13684184D02*
|
||||||
|
X11858015Y-13684184D01*
|
||||||
|
X12096110Y-13684184D02*
|
||||||
|
X12096110Y-13484184D01*
|
||||||
|
X12181825Y-13684184D02*
|
||||||
|
X12181825Y-13579422D01*
|
||||||
|
X12181825Y-13579422D02*
|
||||||
|
X12172301Y-13560374D01*
|
||||||
|
X12172301Y-13560374D02*
|
||||||
|
X12153253Y-13550850D01*
|
||||||
|
X12153253Y-13550850D02*
|
||||||
|
X12124682Y-13550850D01*
|
||||||
|
X12124682Y-13550850D02*
|
||||||
|
X12105634Y-13560374D01*
|
||||||
|
X12105634Y-13560374D02*
|
||||||
|
X12096110Y-13569898D01*
|
||||||
|
X12305634Y-13684184D02*
|
||||||
|
X12286587Y-13674660D01*
|
||||||
|
X12286587Y-13674660D02*
|
||||||
|
X12277063Y-13665136D01*
|
||||||
|
X12277063Y-13665136D02*
|
||||||
|
X12267539Y-13646088D01*
|
||||||
|
X12267539Y-13646088D02*
|
||||||
|
X12267539Y-13588946D01*
|
||||||
|
X12267539Y-13588946D02*
|
||||||
|
X12277063Y-13569898D01*
|
||||||
|
X12277063Y-13569898D02*
|
||||||
|
X12286587Y-13560374D01*
|
||||||
|
X12286587Y-13560374D02*
|
||||||
|
X12305634Y-13550850D01*
|
||||||
|
X12305634Y-13550850D02*
|
||||||
|
X12334206Y-13550850D01*
|
||||||
|
X12334206Y-13550850D02*
|
||||||
|
X12353253Y-13560374D01*
|
||||||
|
X12353253Y-13560374D02*
|
||||||
|
X12362777Y-13569898D01*
|
||||||
|
X12362777Y-13569898D02*
|
||||||
|
X12372301Y-13588946D01*
|
||||||
|
X12372301Y-13588946D02*
|
||||||
|
X12372301Y-13646088D01*
|
||||||
|
X12372301Y-13646088D02*
|
||||||
|
X12362777Y-13665136D01*
|
||||||
|
X12362777Y-13665136D02*
|
||||||
|
X12353253Y-13674660D01*
|
||||||
|
X12353253Y-13674660D02*
|
||||||
|
X12334206Y-13684184D01*
|
||||||
|
X12334206Y-13684184D02*
|
||||||
|
X12305634Y-13684184D01*
|
||||||
|
X12486587Y-13684184D02*
|
||||||
|
X12467539Y-13674660D01*
|
||||||
|
X12467539Y-13674660D02*
|
||||||
|
X12458015Y-13655612D01*
|
||||||
|
X12458015Y-13655612D02*
|
||||||
|
X12458015Y-13484184D01*
|
||||||
|
X12638968Y-13674660D02*
|
||||||
|
X12619920Y-13684184D01*
|
||||||
|
X12619920Y-13684184D02*
|
||||||
|
X12581825Y-13684184D01*
|
||||||
|
X12581825Y-13684184D02*
|
||||||
|
X12562777Y-13674660D01*
|
||||||
|
X12562777Y-13674660D02*
|
||||||
|
X12553253Y-13655612D01*
|
||||||
|
X12553253Y-13655612D02*
|
||||||
|
X12553253Y-13579422D01*
|
||||||
|
X12553253Y-13579422D02*
|
||||||
|
X12562777Y-13560374D01*
|
||||||
|
X12562777Y-13560374D02*
|
||||||
|
X12581825Y-13550850D01*
|
||||||
|
X12581825Y-13550850D02*
|
||||||
|
X12619920Y-13550850D01*
|
||||||
|
X12619920Y-13550850D02*
|
||||||
|
X12638968Y-13560374D01*
|
||||||
|
X12638968Y-13560374D02*
|
||||||
|
X12648491Y-13579422D01*
|
||||||
|
X12648491Y-13579422D02*
|
||||||
|
X12648491Y-13598469D01*
|
||||||
|
X12648491Y-13598469D02*
|
||||||
|
X12553253Y-13617517D01*
|
||||||
|
X12724682Y-13674660D02*
|
||||||
|
X12743730Y-13684184D01*
|
||||||
|
X12743730Y-13684184D02*
|
||||||
|
X12781825Y-13684184D01*
|
||||||
|
X12781825Y-13684184D02*
|
||||||
|
X12800872Y-13674660D01*
|
||||||
|
X12800872Y-13674660D02*
|
||||||
|
X12810396Y-13655612D01*
|
||||||
|
X12810396Y-13655612D02*
|
||||||
|
X12810396Y-13646088D01*
|
||||||
|
X12810396Y-13646088D02*
|
||||||
|
X12800872Y-13627041D01*
|
||||||
|
X12800872Y-13627041D02*
|
||||||
|
X12781825Y-13617517D01*
|
||||||
|
X12781825Y-13617517D02*
|
||||||
|
X12753253Y-13617517D01*
|
||||||
|
X12753253Y-13617517D02*
|
||||||
|
X12734206Y-13607993D01*
|
||||||
|
X12734206Y-13607993D02*
|
||||||
|
X12724682Y-13588946D01*
|
||||||
|
X12724682Y-13588946D02*
|
||||||
|
X12724682Y-13579422D01*
|
||||||
|
X12724682Y-13579422D02*
|
||||||
|
X12734206Y-13560374D01*
|
||||||
|
X12734206Y-13560374D02*
|
||||||
|
X12753253Y-13550850D01*
|
||||||
|
X12753253Y-13550850D02*
|
||||||
|
X12781825Y-13550850D01*
|
||||||
|
X12781825Y-13550850D02*
|
||||||
|
X12800872Y-13560374D01*
|
||||||
|
X12877063Y-13760374D02*
|
||||||
|
X12886587Y-13750850D01*
|
||||||
|
X12886587Y-13750850D02*
|
||||||
|
X12905634Y-13722279D01*
|
||||||
|
X12905634Y-13722279D02*
|
||||||
|
X12915158Y-13703231D01*
|
||||||
|
X12915158Y-13703231D02*
|
||||||
|
X12924682Y-13674660D01*
|
||||||
|
X12924682Y-13674660D02*
|
||||||
|
X12934206Y-13627041D01*
|
||||||
|
X12934206Y-13627041D02*
|
||||||
|
X12934206Y-13588946D01*
|
||||||
|
X12934206Y-13588946D02*
|
||||||
|
X12924682Y-13541327D01*
|
||||||
|
X12924682Y-13541327D02*
|
||||||
|
X12915158Y-13512755D01*
|
||||||
|
X12915158Y-13512755D02*
|
||||||
|
X12905634Y-13493708D01*
|
||||||
|
X12905634Y-13493708D02*
|
||||||
|
X12886587Y-13465136D01*
|
||||||
|
X12886587Y-13465136D02*
|
||||||
|
X12877063Y-13455612D01*
|
||||||
|
X13238968Y-13760374D02*
|
||||||
|
X13229444Y-13750850D01*
|
||||||
|
X13229444Y-13750850D02*
|
||||||
|
X13210396Y-13722279D01*
|
||||||
|
X13210396Y-13722279D02*
|
||||||
|
X13200872Y-13703231D01*
|
||||||
|
X13200872Y-13703231D02*
|
||||||
|
X13191349Y-13674660D01*
|
||||||
|
X13191349Y-13674660D02*
|
||||||
|
X13181825Y-13627041D01*
|
||||||
|
X13181825Y-13627041D02*
|
||||||
|
X13181825Y-13588946D01*
|
||||||
|
X13181825Y-13588946D02*
|
||||||
|
X13191349Y-13541327D01*
|
||||||
|
X13191349Y-13541327D02*
|
||||||
|
X13200872Y-13512755D01*
|
||||||
|
X13200872Y-13512755D02*
|
||||||
|
X13210396Y-13493708D01*
|
||||||
|
X13210396Y-13493708D02*
|
||||||
|
X13229444Y-13465136D01*
|
||||||
|
X13229444Y-13465136D02*
|
||||||
|
X13238968Y-13455612D01*
|
||||||
|
X13315158Y-13550850D02*
|
||||||
|
X13315158Y-13684184D01*
|
||||||
|
X13315158Y-13569898D02*
|
||||||
|
X13324682Y-13560374D01*
|
||||||
|
X13324682Y-13560374D02*
|
||||||
|
X13343730Y-13550850D01*
|
||||||
|
X13343730Y-13550850D02*
|
||||||
|
X13372301Y-13550850D01*
|
||||||
|
X13372301Y-13550850D02*
|
||||||
|
X13391349Y-13560374D01*
|
||||||
|
X13391349Y-13560374D02*
|
||||||
|
X13400872Y-13579422D01*
|
||||||
|
X13400872Y-13579422D02*
|
||||||
|
X13400872Y-13684184D01*
|
||||||
|
X13524682Y-13684184D02*
|
||||||
|
X13505634Y-13674660D01*
|
||||||
|
X13505634Y-13674660D02*
|
||||||
|
X13496111Y-13665136D01*
|
||||||
|
X13496111Y-13665136D02*
|
||||||
|
X13486587Y-13646088D01*
|
||||||
|
X13486587Y-13646088D02*
|
||||||
|
X13486587Y-13588946D01*
|
||||||
|
X13486587Y-13588946D02*
|
||||||
|
X13496111Y-13569898D01*
|
||||||
|
X13496111Y-13569898D02*
|
||||||
|
X13505634Y-13560374D01*
|
||||||
|
X13505634Y-13560374D02*
|
||||||
|
X13524682Y-13550850D01*
|
||||||
|
X13524682Y-13550850D02*
|
||||||
|
X13553253Y-13550850D01*
|
||||||
|
X13553253Y-13550850D02*
|
||||||
|
X13572301Y-13560374D01*
|
||||||
|
X13572301Y-13560374D02*
|
||||||
|
X13581825Y-13569898D01*
|
||||||
|
X13581825Y-13569898D02*
|
||||||
|
X13591349Y-13588946D01*
|
||||||
|
X13591349Y-13588946D02*
|
||||||
|
X13591349Y-13646088D01*
|
||||||
|
X13591349Y-13646088D02*
|
||||||
|
X13581825Y-13665136D01*
|
||||||
|
X13581825Y-13665136D02*
|
||||||
|
X13572301Y-13674660D01*
|
||||||
|
X13572301Y-13674660D02*
|
||||||
|
X13553253Y-13684184D01*
|
||||||
|
X13553253Y-13684184D02*
|
||||||
|
X13524682Y-13684184D01*
|
||||||
|
X13648492Y-13550850D02*
|
||||||
|
X13724682Y-13550850D01*
|
||||||
|
X13677063Y-13484184D02*
|
||||||
|
X13677063Y-13655612D01*
|
||||||
|
X13677063Y-13655612D02*
|
||||||
|
X13686587Y-13674660D01*
|
||||||
|
X13686587Y-13674660D02*
|
||||||
|
X13705634Y-13684184D01*
|
||||||
|
X13705634Y-13684184D02*
|
||||||
|
X13724682Y-13684184D01*
|
||||||
|
X13943730Y-13550850D02*
|
||||||
|
X13943730Y-13750850D01*
|
||||||
|
X13943730Y-13560374D02*
|
||||||
|
X13962777Y-13550850D01*
|
||||||
|
X13962777Y-13550850D02*
|
||||||
|
X14000873Y-13550850D01*
|
||||||
|
X14000873Y-13550850D02*
|
||||||
|
X14019920Y-13560374D01*
|
||||||
|
X14019920Y-13560374D02*
|
||||||
|
X14029444Y-13569898D01*
|
||||||
|
X14029444Y-13569898D02*
|
||||||
|
X14038968Y-13588946D01*
|
||||||
|
X14038968Y-13588946D02*
|
||||||
|
X14038968Y-13646088D01*
|
||||||
|
X14038968Y-13646088D02*
|
||||||
|
X14029444Y-13665136D01*
|
||||||
|
X14029444Y-13665136D02*
|
||||||
|
X14019920Y-13674660D01*
|
||||||
|
X14019920Y-13674660D02*
|
||||||
|
X14000873Y-13684184D01*
|
||||||
|
X14000873Y-13684184D02*
|
||||||
|
X13962777Y-13684184D01*
|
||||||
|
X13962777Y-13684184D02*
|
||||||
|
X13943730Y-13674660D01*
|
||||||
|
X14153253Y-13684184D02*
|
||||||
|
X14134206Y-13674660D01*
|
||||||
|
X14134206Y-13674660D02*
|
||||||
|
X14124682Y-13655612D01*
|
||||||
|
X14124682Y-13655612D02*
|
||||||
|
X14124682Y-13484184D01*
|
||||||
|
X14315158Y-13684184D02*
|
||||||
|
X14315158Y-13579422D01*
|
||||||
|
X14315158Y-13579422D02*
|
||||||
|
X14305634Y-13560374D01*
|
||||||
|
X14305634Y-13560374D02*
|
||||||
|
X14286587Y-13550850D01*
|
||||||
|
X14286587Y-13550850D02*
|
||||||
|
X14248492Y-13550850D01*
|
||||||
|
X14248492Y-13550850D02*
|
||||||
|
X14229444Y-13560374D01*
|
||||||
|
X14315158Y-13674660D02*
|
||||||
|
X14296111Y-13684184D01*
|
||||||
|
X14296111Y-13684184D02*
|
||||||
|
X14248492Y-13684184D01*
|
||||||
|
X14248492Y-13684184D02*
|
||||||
|
X14229444Y-13674660D01*
|
||||||
|
X14229444Y-13674660D02*
|
||||||
|
X14219920Y-13655612D01*
|
||||||
|
X14219920Y-13655612D02*
|
||||||
|
X14219920Y-13636565D01*
|
||||||
|
X14219920Y-13636565D02*
|
||||||
|
X14229444Y-13617517D01*
|
||||||
|
X14229444Y-13617517D02*
|
||||||
|
X14248492Y-13607993D01*
|
||||||
|
X14248492Y-13607993D02*
|
||||||
|
X14296111Y-13607993D01*
|
||||||
|
X14296111Y-13607993D02*
|
||||||
|
X14315158Y-13598469D01*
|
||||||
|
X14381825Y-13550850D02*
|
||||||
|
X14458015Y-13550850D01*
|
||||||
|
X14410396Y-13484184D02*
|
||||||
|
X14410396Y-13655612D01*
|
||||||
|
X14410396Y-13655612D02*
|
||||||
|
X14419920Y-13674660D01*
|
||||||
|
X14419920Y-13674660D02*
|
||||||
|
X14438968Y-13684184D01*
|
||||||
|
X14438968Y-13684184D02*
|
||||||
|
X14458015Y-13684184D01*
|
||||||
|
X14600873Y-13674660D02*
|
||||||
|
X14581825Y-13684184D01*
|
||||||
|
X14581825Y-13684184D02*
|
||||||
|
X14543730Y-13684184D01*
|
||||||
|
X14543730Y-13684184D02*
|
||||||
|
X14524682Y-13674660D01*
|
||||||
|
X14524682Y-13674660D02*
|
||||||
|
X14515158Y-13655612D01*
|
||||||
|
X14515158Y-13655612D02*
|
||||||
|
X14515158Y-13579422D01*
|
||||||
|
X14515158Y-13579422D02*
|
||||||
|
X14524682Y-13560374D01*
|
||||||
|
X14524682Y-13560374D02*
|
||||||
|
X14543730Y-13550850D01*
|
||||||
|
X14543730Y-13550850D02*
|
||||||
|
X14581825Y-13550850D01*
|
||||||
|
X14581825Y-13550850D02*
|
||||||
|
X14600873Y-13560374D01*
|
||||||
|
X14600873Y-13560374D02*
|
||||||
|
X14610396Y-13579422D01*
|
||||||
|
X14610396Y-13579422D02*
|
||||||
|
X14610396Y-13598469D01*
|
||||||
|
X14610396Y-13598469D02*
|
||||||
|
X14515158Y-13617517D01*
|
||||||
|
X14781825Y-13684184D02*
|
||||||
|
X14781825Y-13484184D01*
|
||||||
|
X14781825Y-13674660D02*
|
||||||
|
X14762777Y-13684184D01*
|
||||||
|
X14762777Y-13684184D02*
|
||||||
|
X14724682Y-13684184D01*
|
||||||
|
X14724682Y-13684184D02*
|
||||||
|
X14705634Y-13674660D01*
|
||||||
|
X14705634Y-13674660D02*
|
||||||
|
X14696111Y-13665136D01*
|
||||||
|
X14696111Y-13665136D02*
|
||||||
|
X14686587Y-13646088D01*
|
||||||
|
X14686587Y-13646088D02*
|
||||||
|
X14686587Y-13588946D01*
|
||||||
|
X14686587Y-13588946D02*
|
||||||
|
X14696111Y-13569898D01*
|
||||||
|
X14696111Y-13569898D02*
|
||||||
|
X14705634Y-13560374D01*
|
||||||
|
X14705634Y-13560374D02*
|
||||||
|
X14724682Y-13550850D01*
|
||||||
|
X14724682Y-13550850D02*
|
||||||
|
X14762777Y-13550850D01*
|
||||||
|
X14762777Y-13550850D02*
|
||||||
|
X14781825Y-13560374D01*
|
||||||
|
X14858015Y-13760374D02*
|
||||||
|
X14867539Y-13750850D01*
|
||||||
|
X14867539Y-13750850D02*
|
||||||
|
X14886587Y-13722279D01*
|
||||||
|
X14886587Y-13722279D02*
|
||||||
|
X14896111Y-13703231D01*
|
||||||
|
X14896111Y-13703231D02*
|
||||||
|
X14905634Y-13674660D01*
|
||||||
|
X14905634Y-13674660D02*
|
||||||
|
X14915158Y-13627041D01*
|
||||||
|
X14915158Y-13627041D02*
|
||||||
|
X14915158Y-13588946D01*
|
||||||
|
X14915158Y-13588946D02*
|
||||||
|
X14905634Y-13541327D01*
|
||||||
|
X14905634Y-13541327D02*
|
||||||
|
X14896111Y-13512755D01*
|
||||||
|
X14896111Y-13512755D02*
|
||||||
|
X14886587Y-13493708D01*
|
||||||
|
X14886587Y-13493708D02*
|
||||||
|
X14867539Y-13465136D01*
|
||||||
|
X14867539Y-13465136D02*
|
||||||
|
X14858015Y-13455612D01*
|
||||||
|
M02*
|
||||||
17
pcb/production/fw-anwesenheit-NPTH.drl
Normal file
17
pcb/production/fw-anwesenheit-NPTH.drl
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
M48
|
||||||
|
; DRILL file {KiCad 9.0.3} date 2025-08-23T15:15:25+0200
|
||||||
|
; FORMAT={-:-/ absolute / metric / decimal}
|
||||||
|
; #@! TF.CreationDate,2025-08-23T15:15:25+02:00
|
||||||
|
; #@! TF.GenerationSoftware,Kicad,Pcbnew,9.0.3
|
||||||
|
; #@! TF.FileFunction,NonPlated,1,6,NPTH
|
||||||
|
FMAT,2
|
||||||
|
METRIC
|
||||||
|
; #@! TA.AperFunction,NonPlated,NPTH,ComponentDrill
|
||||||
|
T1C1.000
|
||||||
|
%
|
||||||
|
G90
|
||||||
|
G05
|
||||||
|
T1
|
||||||
|
X117.75Y-83.6
|
||||||
|
X125.75Y-83.6
|
||||||
|
M30
|
||||||
3487
pcb/production/fw-anwesenheit-PTH-drl_map.gbr
Normal file
3487
pcb/production/fw-anwesenheit-PTH-drl_map.gbr
Normal file
File diff suppressed because it is too large
Load Diff
244
pcb/production/fw-anwesenheit-PTH.drl
Normal file
244
pcb/production/fw-anwesenheit-PTH.drl
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
M48
|
||||||
|
; DRILL file {KiCad 9.0.3} date 2025-08-23T15:15:25+0200
|
||||||
|
; FORMAT={-:-/ absolute / metric / decimal}
|
||||||
|
; #@! TF.CreationDate,2025-08-23T15:15:25+02:00
|
||||||
|
; #@! TF.GenerationSoftware,Kicad,Pcbnew,9.0.3
|
||||||
|
; #@! TF.FileFunction,Plated,1,6,PTH
|
||||||
|
FMAT,2
|
||||||
|
METRIC
|
||||||
|
; #@! TA.AperFunction,Plated,PTH,ViaDrill
|
||||||
|
T1C0.200
|
||||||
|
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
|
||||||
|
T2C0.800
|
||||||
|
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
|
||||||
|
T3C0.850
|
||||||
|
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
|
||||||
|
T4C1.400
|
||||||
|
%
|
||||||
|
G90
|
||||||
|
G05
|
||||||
|
T1
|
||||||
|
X82.677Y-80.645
|
||||||
|
X83.185Y-110.49
|
||||||
|
X83.5Y-92.212
|
||||||
|
X83.95Y-112.96
|
||||||
|
X84.328Y-126.873
|
||||||
|
X84.582Y-116.967
|
||||||
|
X84.709Y-80.645
|
||||||
|
X85.979Y-97.79
|
||||||
|
X86.487Y-99.822
|
||||||
|
X86.741Y-80.645
|
||||||
|
X87.505Y-126.494
|
||||||
|
X88.011Y-117.475
|
||||||
|
X88.519Y-103.124
|
||||||
|
X88.773Y-80.645
|
||||||
|
X90.0Y-109.087
|
||||||
|
X90.0Y-114.912
|
||||||
|
X90.412Y-97.0
|
||||||
|
X90.412Y-99.0
|
||||||
|
X90.805Y-80.645
|
||||||
|
X91.694Y-127.889
|
||||||
|
X92.583Y-119.888
|
||||||
|
X92.71Y-98.044
|
||||||
|
X92.837Y-80.645
|
||||||
|
X94.488Y-124.206
|
||||||
|
X94.488Y-125.73
|
||||||
|
X94.869Y-80.645
|
||||||
|
X94.869Y-128.397
|
||||||
|
X95.25Y-113.157
|
||||||
|
X95.377Y-118.364
|
||||||
|
X95.618Y-98.552
|
||||||
|
X95.885Y-101.092
|
||||||
|
X96.774Y-120.904
|
||||||
|
X96.774Y-121.539
|
||||||
|
X96.774Y-122.174
|
||||||
|
X96.774Y-123.444
|
||||||
|
X96.774Y-124.079
|
||||||
|
X96.774Y-124.714
|
||||||
|
X96.901Y-80.645
|
||||||
|
X96.901Y-128.397
|
||||||
|
X96.926Y-126.086
|
||||||
|
X96.926Y-126.644
|
||||||
|
X96.926Y-127.203
|
||||||
|
X97.168Y-98.552
|
||||||
|
X97.663Y-114.046
|
||||||
|
X97.663Y-116.332
|
||||||
|
X97.663Y-120.904
|
||||||
|
X97.663Y-121.539
|
||||||
|
X97.663Y-122.174
|
||||||
|
X97.663Y-123.444
|
||||||
|
X97.663Y-124.079
|
||||||
|
X97.663Y-124.714
|
||||||
|
X97.688Y-126.086
|
||||||
|
X97.688Y-126.644
|
||||||
|
X97.688Y-127.203
|
||||||
|
X98.044Y-102.362
|
||||||
|
X98.044Y-103.632
|
||||||
|
X98.044Y-104.902
|
||||||
|
X98.044Y-106.172
|
||||||
|
X98.552Y-94.361
|
||||||
|
X98.552Y-120.904
|
||||||
|
X98.552Y-121.539
|
||||||
|
X98.552Y-122.174
|
||||||
|
X98.552Y-123.444
|
||||||
|
X98.552Y-124.079
|
||||||
|
X98.552Y-124.714
|
||||||
|
X98.603Y-126.086
|
||||||
|
X98.603Y-126.644
|
||||||
|
X98.603Y-127.203
|
||||||
|
X98.933Y-80.645
|
||||||
|
X98.933Y-128.397
|
||||||
|
X100.965Y-80.645
|
||||||
|
X100.965Y-128.397
|
||||||
|
X102.489Y-98.552
|
||||||
|
X102.616Y-94.361
|
||||||
|
X102.743Y-123.317
|
||||||
|
X102.997Y-80.645
|
||||||
|
X102.997Y-128.397
|
||||||
|
X103.886Y-107.95
|
||||||
|
X104.267Y-119.761
|
||||||
|
X104.267Y-120.396
|
||||||
|
X104.521Y-125.095
|
||||||
|
X104.648Y-97.663
|
||||||
|
X104.902Y-119.761
|
||||||
|
X104.902Y-120.396
|
||||||
|
X105.029Y-80.645
|
||||||
|
X105.029Y-112.522
|
||||||
|
X105.029Y-113.411
|
||||||
|
X105.475Y-105.0
|
||||||
|
X107.061Y-80.645
|
||||||
|
X107.315Y-112.903
|
||||||
|
X107.315Y-113.665
|
||||||
|
X107.315Y-114.3
|
||||||
|
X107.442Y-107.95
|
||||||
|
X107.823Y-112.903
|
||||||
|
X107.823Y-113.665
|
||||||
|
X107.823Y-114.3
|
||||||
|
X108.839Y-120.396
|
||||||
|
X108.966Y-98.552
|
||||||
|
X108.966Y-112.014
|
||||||
|
X109.093Y-80.645
|
||||||
|
X109.093Y-128.397
|
||||||
|
X109.22Y-97.282
|
||||||
|
X109.791Y-110.68
|
||||||
|
X110.109Y-123.571
|
||||||
|
X110.49Y-115.189
|
||||||
|
X110.744Y-101.092
|
||||||
|
X110.744Y-102.362
|
||||||
|
X110.744Y-103.632
|
||||||
|
X110.744Y-104.902
|
||||||
|
X110.744Y-106.172
|
||||||
|
X110.871Y-123.571
|
||||||
|
X111.125Y-80.645
|
||||||
|
X111.125Y-128.397
|
||||||
|
X111.379Y-107.95
|
||||||
|
X112.903Y-83.947
|
||||||
|
X112.903Y-118.491
|
||||||
|
X113.157Y-80.645
|
||||||
|
X113.157Y-128.397
|
||||||
|
X113.411Y-93.853
|
||||||
|
X113.792Y-126.746
|
||||||
|
X113.822Y-116.438
|
||||||
|
X115.189Y-80.645
|
||||||
|
X115.189Y-128.397
|
||||||
|
X115.443Y-91.821
|
||||||
|
X115.951Y-117.094
|
||||||
|
X116.0Y-102.412
|
||||||
|
X116.078Y-118.491
|
||||||
|
X116.332Y-125.984
|
||||||
|
X116.459Y-125.476
|
||||||
|
X116.967Y-125.349
|
||||||
|
X117.221Y-80.645
|
||||||
|
X117.221Y-128.397
|
||||||
|
X117.475Y-116.84
|
||||||
|
X117.705Y-113.56
|
||||||
|
X117.705Y-115.443
|
||||||
|
X117.729Y-123.571
|
||||||
|
X118.0Y-102.412
|
||||||
|
X118.237Y-110.998
|
||||||
|
X118.364Y-123.571
|
||||||
|
X118.491Y-99.06
|
||||||
|
X118.55Y-94.65
|
||||||
|
X119.253Y-80.645
|
||||||
|
X119.253Y-128.397
|
||||||
|
X119.634Y-126.492
|
||||||
|
X119.634Y-127.0
|
||||||
|
X119.634Y-127.508
|
||||||
|
X119.65Y-94.65
|
||||||
|
X119.761Y-92.329
|
||||||
|
X119.761Y-110.998
|
||||||
|
X120.0Y-102.412
|
||||||
|
X120.0Y-121.0
|
||||||
|
X120.015Y-99.441
|
||||||
|
X120.015Y-119.253
|
||||||
|
X120.294Y-113.589
|
||||||
|
X120.75Y-94.65
|
||||||
|
X121.285Y-80.645
|
||||||
|
X121.285Y-128.397
|
||||||
|
X121.92Y-94.234
|
||||||
|
X121.92Y-95.123
|
||||||
|
X122.0Y-100.587
|
||||||
|
X122.0Y-102.412
|
||||||
|
X122.047Y-99.06
|
||||||
|
X122.174Y-97.536
|
||||||
|
X122.174Y-126.619
|
||||||
|
X122.174Y-127.381
|
||||||
|
X122.301Y-111.887
|
||||||
|
X122.301Y-115.697
|
||||||
|
X122.5Y-119.087
|
||||||
|
X122.5Y-120.912
|
||||||
|
X122.53Y-126.949
|
||||||
|
X122.936Y-94.65
|
||||||
|
X122.936Y-126.619
|
||||||
|
X122.936Y-127.381
|
||||||
|
X123.317Y-80.645
|
||||||
|
X123.317Y-128.397
|
||||||
|
X123.825Y-97.536
|
||||||
|
X124.0Y-102.412
|
||||||
|
X124.079Y-94.234
|
||||||
|
X124.079Y-94.996
|
||||||
|
X125.15Y-94.65
|
||||||
|
X125.349Y-80.645
|
||||||
|
X125.349Y-128.397
|
||||||
|
X125.73Y-92.837
|
||||||
|
X125.984Y-114.046
|
||||||
|
X125.984Y-115.57
|
||||||
|
X126.0Y-102.412
|
||||||
|
X126.25Y-94.65
|
||||||
|
X126.873Y-97.536
|
||||||
|
X127.35Y-94.65
|
||||||
|
X127.381Y-80.645
|
||||||
|
X127.381Y-128.397
|
||||||
|
X128.0Y-102.5
|
||||||
|
X128.219Y-113.284
|
||||||
|
X128.219Y-114.198
|
||||||
|
X128.27Y-115.824
|
||||||
|
X128.27Y-116.713
|
||||||
|
X128.651Y-83.947
|
||||||
|
X128.905Y-93.599
|
||||||
|
X128.981Y-113.741
|
||||||
|
X129.0Y-116.27
|
||||||
|
X129.413Y-80.645
|
||||||
|
X129.413Y-128.397
|
||||||
|
X129.642Y-113.335
|
||||||
|
X129.642Y-114.249
|
||||||
|
X129.794Y-115.824
|
||||||
|
X129.794Y-116.713
|
||||||
|
T2
|
||||||
|
X89.916Y-118.888
|
||||||
|
X89.916Y-120.888
|
||||||
|
T3
|
||||||
|
X92.911Y-103.378
|
||||||
|
X113.411Y-103.378
|
||||||
|
T4
|
||||||
|
X89.5Y-59.52
|
||||||
|
X89.5Y-62.06
|
||||||
|
X89.5Y-87.46
|
||||||
|
X89.5Y-90.0
|
||||||
|
X89.5Y-92.54
|
||||||
|
X104.74Y-82.38
|
||||||
|
X104.74Y-84.92
|
||||||
|
X104.74Y-87.46
|
||||||
|
X104.74Y-90.0
|
||||||
|
X104.74Y-92.54
|
||||||
|
M30
|
||||||
23
pm3_mock.sh
23
pm3_mock.sh
@@ -1,23 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
generate_random_hex() {
|
|
||||||
openssl rand -hex 4 | tr '[:lower:]' '[:upper:]'
|
|
||||||
}
|
|
||||||
|
|
||||||
output_hotspot_id() {
|
|
||||||
echo "[+] UID.... C1532B57"
|
|
||||||
}
|
|
||||||
|
|
||||||
trap 'output_hotspot_id' SIGUSR1
|
|
||||||
|
|
||||||
echo "Proxmark 3 mock script"
|
|
||||||
echo "Outputs a random ID every 1 to 5 seconds"
|
|
||||||
|
|
||||||
while true; do
|
|
||||||
random_id=$(generate_random_hex)
|
|
||||||
echo "[+] UID.... $random_id"
|
|
||||||
if (( RANDOM % 2 == 0 )); then
|
|
||||||
echo "[+] UID.... $random_id"
|
|
||||||
fi
|
|
||||||
sleep "$((RANDOM % 5 + 1))"
|
|
||||||
done
|
|
||||||
Binary file not shown.
Binary file not shown.
550
pre-compiled/pm3
550
pre-compiled/pm3
@@ -1,550 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Usage: run option -h to get help
|
|
||||||
|
|
||||||
# BT auto detection
|
|
||||||
# Shall we look for white HC-06-USB dongle ?
|
|
||||||
FINDBTDONGLE=true
|
|
||||||
# Shall we look for rfcomm interface ?
|
|
||||||
FINDBTRFCOMM=true
|
|
||||||
# Shall we look for registered BT device ? (Linux only)
|
|
||||||
FINDBTDIRECT=true
|
|
||||||
|
|
||||||
PM3PATH=$(dirname "$0")
|
|
||||||
EVALENV=""
|
|
||||||
FULLIMAGE="fullimage.elf"
|
|
||||||
BOOTIMAGE="bootrom.elf"
|
|
||||||
|
|
||||||
#Skip check if --list is used
|
|
||||||
if [ ! "$1" == "--list" ]; then
|
|
||||||
# try pm3 dirs in current repo workdir
|
|
||||||
if [ -d "$PM3PATH/client/" ]; then
|
|
||||||
if [ -x "$PM3PATH/client/proxmark3" ]; then
|
|
||||||
CLIENT="$PM3PATH/client/proxmark3"
|
|
||||||
elif [ -x "$PM3PATH/client/build/proxmark3" ]; then
|
|
||||||
CLIENT="$PM3PATH/client/build/proxmark3"
|
|
||||||
else
|
|
||||||
echo >&2 "[!!] In devel workdir but no executable found, did you compile it?"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
# try install dir
|
|
||||||
elif [ -x "$PM3PATH/proxmark3" ]; then
|
|
||||||
CLIENT="$PM3PATH/proxmark3"
|
|
||||||
else
|
|
||||||
# hope it's installed somehow, still not sure where fw images and pm3.py are...
|
|
||||||
CLIENT="proxmark3"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# LeakSanitizer suppressions
|
|
||||||
if [ -e .lsan_suppressions ]; then
|
|
||||||
EVALENV+=" LSAN_OPTIONS=suppressions=.lsan_suppressions"
|
|
||||||
fi
|
|
||||||
if [ "$EVALENV" != "" ]; then
|
|
||||||
EVALENV="export $EVALENV"
|
|
||||||
fi
|
|
||||||
PM3LIST=()
|
|
||||||
SHOWLIST=false
|
|
||||||
|
|
||||||
function get_pm3_list_Linux {
|
|
||||||
N=$1
|
|
||||||
PM3LIST=()
|
|
||||||
if [ ! -c "/dev/tty0" ]; then
|
|
||||||
echo >&2 "[!!] Script cannot access /dev/ttyXXX files, insufficient privileges"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
for DEV in $(find /dev/ttyACM* 2>/dev/null); do
|
|
||||||
if command -v udevadm >/dev/null; then
|
|
||||||
# WSL1 detection
|
|
||||||
if udevadm info -q property -n "$DEV" | grep -q "ID_VENDOR=proxmark.org"; then
|
|
||||||
PM3LIST+=("$DEV")
|
|
||||||
if [ ${#PM3LIST[*]} -ge "$N" ]; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
# WSL2 with usbipd detection - doesn't report same things as WSL1
|
|
||||||
if grep -q "proxmark.org" "/sys/class/tty/${DEV#/dev/}/../../../manufacturer" 2>/dev/null; then
|
|
||||||
if echo "${PM3LIST[*]}" | grep -qv "${DEV}"; then
|
|
||||||
PM3LIST+=("$DEV")
|
|
||||||
if [ ${#PM3LIST[*]} -ge "$N" ]; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if $FINDBTDONGLE; then
|
|
||||||
# check if the HC-06-USB white dongle is present (still, that doesn't tell us if it's paired with a Proxmark3...)
|
|
||||||
for DEV in $(find /dev/ttyUSB* 2>/dev/null); do
|
|
||||||
if command -v udevadm >/dev/null; then
|
|
||||||
if udevadm info -q property -n "$DEV" | grep -q "ID_MODEL=CP2104_USB_to_UART_Bridge_Controller"; then
|
|
||||||
PM3LIST+=("$DEV")
|
|
||||||
if [ ${#PM3LIST[*]} -ge "$N" ]; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
if grep -q "DRIVER=cp210x" "/sys/class/tty/${DEV#/dev/}/../../uevent" 2>/dev/null; then
|
|
||||||
PM3LIST+=("$DEV")
|
|
||||||
if [ ${#PM3LIST[*]} -ge "$N" ]; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
if $FINDBTRFCOMM; then
|
|
||||||
# check if the MAC of a Proxmark3 was bound to a local rfcomm interface
|
|
||||||
# (on OSes without deprecated rfcomm and hcitool, the loop will be simply skipped)
|
|
||||||
for DEVMAC in $(rfcomm -a 2>/dev/null | grep " 20:19:0[45]" | sed 's/^\(.*\): \([0-9:]*\) .*/\1@\2/'); do
|
|
||||||
DEV=${DEVMAC/@*/}
|
|
||||||
MAC=${DEVMAC/*@/}
|
|
||||||
# check which are Proxmark3 and, side-effect, if they're actually present
|
|
||||||
if hcitool name "$MAC" | grep -q "PM3"; then
|
|
||||||
PM3LIST+=("/dev/$DEV")
|
|
||||||
if [ ${#PM3LIST[*]} -ge "$N" ]; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
if $FINDBTDIRECT; then
|
|
||||||
# check if the MAC of a Proxmark3 was registered in the known devices
|
|
||||||
for MAC in $(dbus-send --system --print-reply --type=method_call --dest='org.bluez' '/' org.freedesktop.DBus.ObjectManager.GetManagedObjects 2>/dev/null|\
|
|
||||||
awk '/"Address"/{getline;gsub(/"/,"",$3);a=$3}/Name/{getline;if (/PM3_RDV4/ || /Proxmark3 SE/) print a}'); do
|
|
||||||
PM3LIST+=("bt:$MAC")
|
|
||||||
done
|
|
||||||
# we don't probe the device so there is no guarantee the device is actually present
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_pm3_list_macOS {
|
|
||||||
N=$1
|
|
||||||
PM3LIST=()
|
|
||||||
for DEV in $(ioreg -r -c "IOUSBHostDevice" -l | awk -F '"' '
|
|
||||||
$2=="USB Vendor Name"{b=($4=="proxmark.org")}
|
|
||||||
b==1 && $2=="IODialinDevice"{print $4}'); do
|
|
||||||
PM3LIST+=("$DEV")
|
|
||||||
if [ ${#PM3LIST[*]} -ge "$N" ]; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_pm3_list_Windows {
|
|
||||||
N=$1
|
|
||||||
PM3LIST=()
|
|
||||||
|
|
||||||
# Normal SERIAL PORTS (COM)
|
|
||||||
for DEV in $(wmic /locale:ms_409 path Win32_SerialPort Where "PNPDeviceID LIKE '%VID_9AC4&PID_4B8F%' Or PNPDeviceID LIKE '%VID_2D2D&PID_504D%'" Get DeviceID 2>/dev/null | awk -b '/^COM/{print $1}'); do
|
|
||||||
DEV=${DEV/ */}
|
|
||||||
#prevent soft bricking when using pm3-flash-all on an outdated bootloader
|
|
||||||
if [ $(basename -- "$0") = "pm3-flash-all" ]; then
|
|
||||||
line=$(wmic /locale:ms_409 path Win32_SerialPort Where "DeviceID='$DEV'" Get PNPDeviceID 2>/dev/null | awk -b '/^USB/{print $1}');
|
|
||||||
if [[ ! $line =~ ^"USB\VID_9AC4&PID_4B8F\ICEMAN" ]]; then
|
|
||||||
echo -e "\033[0;31m[!] Using pm3-flash-all on an oudated bootloader, use pm3-flash-bootrom first!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
PM3LIST+=("$DEV")
|
|
||||||
if [ ${#PM3LIST[*]} -ge "$N" ]; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
#BT direct SERIAL PORTS (COM)
|
|
||||||
if $FINDBTRFCOMM; then
|
|
||||||
for DEV in $(wmic /locale:ms_409 path Win32_PnPEntity Where "Caption LIKE '%Bluetooth%(COM%'" Get Name 2> /dev/null | awk -b 'match($0,/(COM[0-9]+)/,m){print m[1]}'); do
|
|
||||||
DEV=${DEV/ */}
|
|
||||||
PM3LIST+=("$DEV")
|
|
||||||
if [ ${#PM3LIST[*]} -ge "$N" ]; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
#white BT dongle SERIAL PORTS (COM)
|
|
||||||
if $FINDBTDONGLE; then
|
|
||||||
for DEV in $(wmic /locale:ms_409 path Win32_SerialPort Where "PNPDeviceID LIKE '%VID_10C4&PID_EA60%'" Get DeviceID 2>/dev/null | awk -b '/^COM/{print $1}'); do
|
|
||||||
DEV=${DEV/ */}
|
|
||||||
PM3LIST+=("$DEV")
|
|
||||||
if [ ${#PM3LIST[*]} -ge "$N" ]; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_pm3_list_WSL {
|
|
||||||
N=$1
|
|
||||||
PM3LIST=()
|
|
||||||
|
|
||||||
# Normal SERIAL PORTS (COM)
|
|
||||||
for DEV in $($PSHEXE -command "Get-CimInstance -ClassName Win32_serialport | Where-Object {\$_.PNPDeviceID -like '*VID_9AC4&PID_4B8F*' -or \$_.PNPDeviceID -like '*VID_2D2D&PID_504D*'} | Select -expandproperty DeviceID" 2>/dev/null); do
|
|
||||||
DEV=$(echo $DEV | tr -dc '[:print:]')
|
|
||||||
_comport=$DEV
|
|
||||||
DEV=$(echo $DEV | sed -nr 's#^COM([0-9]+)\b#/dev/ttyS\1#p')
|
|
||||||
# ttyS counterpart takes some more time to appear
|
|
||||||
if [ -e "$DEV" ]; then
|
|
||||||
|
|
||||||
#prevent soft bricking when using pm3-flash-all on an outdated bootloader
|
|
||||||
if [ $(basename -- "$0") = "pm3-flash-all" ]; then
|
|
||||||
line=$($PSHEXE -command "Get-CimInstance -ClassName Win32_serialport | Where-Object {\$_.DeviceID -eq '$_comport'} | Select -expandproperty PNPDeviceID" 2>/dev/null | tr -dc '[:print:]');
|
|
||||||
if [[ ! $line =~ ^"USB\VID_9AC4&PID_4B8F\ICEMAN" ]]; then
|
|
||||||
echo -e "\033[0;31m[!] Using pm3-flash-all on an oudated bootloader, use pm3-flash-bootrom first!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
PM3LIST+=("$DEV")
|
|
||||||
if [ ! -w "$DEV" ]; then
|
|
||||||
echo "[!] Let's give users read/write access to $DEV"
|
|
||||||
sudo chmod 666 "$DEV"
|
|
||||||
fi
|
|
||||||
if [ ${#PM3LIST[*]} -ge "$N" ]; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
#BT direct SERIAL PORTS (COM)
|
|
||||||
if $FINDBTRFCOMM; then
|
|
||||||
for DEV in $($PSHEXE -command "Get-CimInstance -ClassName Win32_PnPEntity | Where-Object Caption -like 'Standard Serial over Bluetooth link (COM*' | Select Name" 2> /dev/null | sed -nr 's#.*\bCOM([0-9]+)\b.*#/dev/ttyS\1#p'); do
|
|
||||||
# ttyS counterpart takes some more time to appear
|
|
||||||
if [ -e "$DEV" ]; then
|
|
||||||
PM3LIST+=("$DEV")
|
|
||||||
if [ ! -w "$DEV" ]; then
|
|
||||||
echo "[!] Let's give users read/write access to $DEV"
|
|
||||||
sudo chmod 666 "$DEV"
|
|
||||||
fi
|
|
||||||
if [ ${#PM3LIST[*]} -ge "$N" ]; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
#white BT dongle SERIAL PORTS (COM)
|
|
||||||
if $FINDBTDONGLE; then
|
|
||||||
for DEV in $($PSHEXE -command "Get-CimInstance -ClassName Win32_serialport | Where-Object PNPDeviceID -like '*VID_10C4&PID_EA60*' | Select DeviceID" 2>/dev/null | sed -nr 's#^COM([0-9]+)\b#/dev/ttyS\1#p'); do
|
|
||||||
# ttyS counterpart takes some more time to appear
|
|
||||||
if [ -e "$DEV" ]; then
|
|
||||||
PM3LIST+=("$DEV")
|
|
||||||
if [ ! -w "$DEV" ]; then
|
|
||||||
echo "[!] Let's give users read/write access to $DEV"
|
|
||||||
sudo chmod 666 "$DEV"
|
|
||||||
fi
|
|
||||||
if [ ${#PM3LIST[*]} -ge "$N" ]; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
SCRIPT=$(basename -- "$0")
|
|
||||||
|
|
||||||
if [ "$SCRIPT" = "pm3" ]; then
|
|
||||||
CMD() { eval "$EVALENV"; $CLIENT "$@"; }
|
|
||||||
HELP() {
|
|
||||||
cat << EOF
|
|
||||||
|
|
||||||
Quick helper script for proxmark3 client when working with a Proxmark3 device
|
|
||||||
|
|
||||||
Description:
|
|
||||||
The usage is the same as for the proxmark3 client, with the following differences:
|
|
||||||
* the correct port name will be automatically guessed;
|
|
||||||
* the script will wait for a Proxmark3 to be connected (same as option -w of the client).
|
|
||||||
You can also specify a first option -n N to access the Nth Proxmark3 connected.
|
|
||||||
To see a list of available ports, use --list.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
$SCRIPT [-n <N>] [<any other proxmark3 client option>]
|
|
||||||
$SCRIPT [--list] [-h|--help] [-hh|--helpclient]
|
|
||||||
$SCRIPT [-o|--offline]
|
|
||||||
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
-h/--help this help
|
|
||||||
-hh/--helpclient proxmark3 client help (the script will forward these options)
|
|
||||||
--list list all detected com ports
|
|
||||||
-n <N> connect device referred to the N:th number on the --list output
|
|
||||||
-o/--offline shortcut to use directly the proxmark3 client without guessing ports
|
|
||||||
|
|
||||||
Samples:
|
|
||||||
./$SCRIPT -- Auto detect/ select com port in the following order BT, USB/CDC, BT DONGLE
|
|
||||||
./$SCRIPT -p /dev/ttyACM0 -- connect to port /dev/ttyACM0
|
|
||||||
./$SCRIPT -n 2 -- use second item from the --list output
|
|
||||||
./$SCRIPT -c 'lf search' -i -- run command and stay in client once completed
|
|
||||||
|
|
||||||
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
elif [ "$SCRIPT" = "pm3-flash" ]; then
|
|
||||||
FINDBTDONGLE=false
|
|
||||||
FINDBTRFCOMM=false
|
|
||||||
FINDBTDIRECT=false
|
|
||||||
CMD() {
|
|
||||||
ARGS=("--port" "$1" "--flash")
|
|
||||||
shift;
|
|
||||||
while [ "$1" != "" ]; do
|
|
||||||
if [ "$1" == "-b" ]; then
|
|
||||||
ARGS+=("--unlock-bootloader")
|
|
||||||
elif [ "$1" == "--force" ]; then
|
|
||||||
ARGS+=("--force")
|
|
||||||
else
|
|
||||||
ARGS+=("--image" "$1")
|
|
||||||
fi
|
|
||||||
shift;
|
|
||||||
done
|
|
||||||
$CLIENT "${ARGS[@]}";
|
|
||||||
}
|
|
||||||
HELP() {
|
|
||||||
cat << EOF
|
|
||||||
Quick helper script for flashing a Proxmark3 device via USB
|
|
||||||
|
|
||||||
Description:
|
|
||||||
The usage is similar to the old proxmark3-flasher binary, except that the correct port name will be automatically guessed.
|
|
||||||
You can also specify a first option -n N to access the Nth Proxmark3 connected on USB.
|
|
||||||
If this doesn't work, you'll have to use manually the proxmark3 client, see "$CLIENT -h".
|
|
||||||
To see a list of available ports, use --list.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
$SCRIPT [-n <N>] [-b] image.elf [image.elf...]
|
|
||||||
$SCRIPT --list
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-b Enable flashing of bootloader area (DANGEROUS)
|
|
||||||
|
|
||||||
Example:
|
|
||||||
$SCRIPT -b bootrom.elf fullimage.elf
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
elif [ "$SCRIPT" = "pm3-flash-all" ]; then
|
|
||||||
FINDBTDONGLE=false
|
|
||||||
FINDBTRFCOMM=false
|
|
||||||
FINDBTDIRECT=false
|
|
||||||
|
|
||||||
|
|
||||||
CMD() {
|
|
||||||
ARGS=("--port" "$1" "--flash" "--unlock-bootloader" "--image" "$BOOTIMAGE" "--image" "$FULLIMAGE")
|
|
||||||
shift;
|
|
||||||
while [ "$1" != "" ]; do
|
|
||||||
if [ "$1" == "--force" ]; then
|
|
||||||
ARGS+=("--force")
|
|
||||||
fi
|
|
||||||
shift;
|
|
||||||
done
|
|
||||||
$CLIENT "${ARGS[@]}";
|
|
||||||
}
|
|
||||||
HELP() {
|
|
||||||
cat << EOF
|
|
||||||
Quick helper script for flashing a Proxmark3 device via USB
|
|
||||||
|
|
||||||
Description:
|
|
||||||
The correct port name will be automatically guessed and the stock bootloader and firmware image will be flashed.
|
|
||||||
You can also specify a first option -n N to access the Nth Proxmark3 connected on USB.
|
|
||||||
If this doesn't work, you'll have to use manually the proxmark3 client, see "$CLIENT -h".
|
|
||||||
To see a list of available ports, use --list.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
$SCRIPT [-n <N>]
|
|
||||||
$SCRIPT --list
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
elif [ "$SCRIPT" = "pm3-flash-fullimage" ]; then
|
|
||||||
FINDBTDONGLE=false
|
|
||||||
FINDBTRFCOMM=false
|
|
||||||
FINDBTDIRECT=false
|
|
||||||
CMD() {
|
|
||||||
ARGS=("--port" "$1" "--flash" "--image" "$FULLIMAGE")
|
|
||||||
shift;
|
|
||||||
while [ "$1" != "" ]; do
|
|
||||||
if [ "$1" == "--force" ]; then
|
|
||||||
ARGS+=("--force")
|
|
||||||
fi
|
|
||||||
shift;
|
|
||||||
done
|
|
||||||
$CLIENT "${ARGS[@]}";
|
|
||||||
}
|
|
||||||
HELP() {
|
|
||||||
cat << EOF
|
|
||||||
Quick helper script for flashing a Proxmark3 device via USB
|
|
||||||
|
|
||||||
Description:
|
|
||||||
The correct port name will be automatically guessed and the stock firmware image will be flashed.
|
|
||||||
You can also specify a first option -n N to access the Nth Proxmark3 connected on USB.
|
|
||||||
If this doesn't work, you'll have to use manually the proxmark3 client, see "$CLIENT -h".
|
|
||||||
To see a list of available ports, use --list.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
$SCRIPT [-n <N>]
|
|
||||||
$SCRIPT --list
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
elif [ "$SCRIPT" = "pm3-flash-bootrom" ]; then
|
|
||||||
FINDBTDONGLE=false
|
|
||||||
FINDBTRFCOMM=false
|
|
||||||
FINDBTDIRECT=false
|
|
||||||
CMD() {
|
|
||||||
ARGS=("--port" "$1" "--flash" "--unlock-bootloader" "--image" "$BOOTIMAGE")
|
|
||||||
shift;
|
|
||||||
while [ "$1" != "" ]; do
|
|
||||||
if [ "$1" == "--force" ]; then
|
|
||||||
ARGS+=("--force")
|
|
||||||
fi
|
|
||||||
shift;
|
|
||||||
done
|
|
||||||
$CLIENT "${ARGS[@]}";
|
|
||||||
}
|
|
||||||
HELP() {
|
|
||||||
cat << EOF
|
|
||||||
Quick helper script for flashing a Proxmark3 device via USB
|
|
||||||
|
|
||||||
Description:
|
|
||||||
The correct port name will be automatically guessed and the stock bootloader will be flashed.
|
|
||||||
You can also specify a first option -n N to access the Nth Proxmark3 connected on USB.
|
|
||||||
If this doesn't work, you'll have to use manually the proxmark3 client, see "$CLIENT -h".
|
|
||||||
To see a list of available ports, use --list.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
$SCRIPT [-n <N>]
|
|
||||||
$SCRIPT --list
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
else
|
|
||||||
echo >&2 "[!!] Script ran under unknown name, abort: $SCRIPT"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# priority to the help options
|
|
||||||
for ARG; do
|
|
||||||
if [ "$ARG" == "-h" ] || [ "$ARG" == "--help" ]; then
|
|
||||||
HELP
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
if [ "$ARG" == "-hh" ] || [ "$ARG" == "--helpclient" ]; then
|
|
||||||
CMD "-h"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# if offline, bypass the script and forward all other args
|
|
||||||
for ARG; do
|
|
||||||
shift
|
|
||||||
if [ "$ARG" == "-o" ] || [ "$ARG" == "--offline" ]; then
|
|
||||||
CMD "$@"
|
|
||||||
exit $?
|
|
||||||
fi
|
|
||||||
set -- "$@" "$ARG"
|
|
||||||
done
|
|
||||||
|
|
||||||
# if a port is already provided, let's just run the command as such
|
|
||||||
for ARG; do
|
|
||||||
shift
|
|
||||||
if [ "$ARG" == "-p" ]; then
|
|
||||||
CMD "$@"
|
|
||||||
exit $?
|
|
||||||
fi
|
|
||||||
set -- "$@" "$ARG"
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ "$1" == "--list" ]; then
|
|
||||||
shift
|
|
||||||
if [ "$1" != "" ]; then
|
|
||||||
echo >&2 "[!!] Option --list must be used alone"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
SHOWLIST=true
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Number of the Proxmark3 we're interested in
|
|
||||||
N=1
|
|
||||||
if [ "$1" == "-n" ]; then
|
|
||||||
shift
|
|
||||||
if [ "$1" -ge 1 ] && [ "$1" -lt 10 ]; then
|
|
||||||
N=$1
|
|
||||||
shift
|
|
||||||
else
|
|
||||||
echo >&2 "[!!] Option -n requires a number between 1 and 9, got \"$1\""
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
HOSTOS=$(uname | awk '{print toupper($0)}')
|
|
||||||
if [ "$HOSTOS" = "LINUX" ]; then
|
|
||||||
# Detect when running under WSL1 (but exclude WSL2)
|
|
||||||
if uname -a | grep -qi Microsoft && uname -a | grep -qvi WSL2; then
|
|
||||||
# First try finding it using the PATH environment variable
|
|
||||||
PSHEXE=$(command -v powershell.exe 2>/dev/null)
|
|
||||||
|
|
||||||
# If it fails (such as if WSLENV is not set), try using the default installation path
|
|
||||||
if [ -z "$PSHEXE" ]; then
|
|
||||||
PSHEXE=/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Finally test if PowerShell is working
|
|
||||||
if ! "$PSHEXE" exit >/dev/null 2>&1; then
|
|
||||||
echo >&2 "[!!] Cannot run powershell.exe, are you sure your WSL is authorized to run Windows processes? (cf WSL interop flag)"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
GETPM3LIST=get_pm3_list_WSL
|
|
||||||
else
|
|
||||||
GETPM3LIST=get_pm3_list_Linux
|
|
||||||
fi
|
|
||||||
elif [ "$HOSTOS" = "DARWIN" ]; then
|
|
||||||
GETPM3LIST=get_pm3_list_macOS
|
|
||||||
elif [[ "$HOSTOS" =~ MINGW(32|64)_NT* ]]; then
|
|
||||||
GETPM3LIST=get_pm3_list_Windows
|
|
||||||
else
|
|
||||||
echo >&2 "[!!] Host OS not recognized, abort: $HOSTOS"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if $SHOWLIST; then
|
|
||||||
# Probe for up to 9 devs
|
|
||||||
$GETPM3LIST 9
|
|
||||||
if [ ${#PM3LIST} -lt 1 ]; then
|
|
||||||
echo >&2 "[!!] No port found"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
n=1
|
|
||||||
for DEV in "${PM3LIST[@]}"
|
|
||||||
do
|
|
||||||
echo "$n: $DEV"
|
|
||||||
n=$((n+1))
|
|
||||||
done
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Wait till we get at least N Proxmark3 devices
|
|
||||||
$GETPM3LIST "$N"
|
|
||||||
if [ ${#PM3LIST} -lt "$N" ]; then
|
|
||||||
echo >&2 "[=] Waiting for Proxmark3 to appear..."
|
|
||||||
fi
|
|
||||||
while true; do
|
|
||||||
if [ ${#PM3LIST[*]} -ge "$N" ]; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
sleep .1
|
|
||||||
$GETPM3LIST "$N"
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ ${#PM3LIST} -lt "$N" ]; then
|
|
||||||
HELP() {
|
|
||||||
cat << EOF
|
|
||||||
[!!] No port found, abort
|
|
||||||
|
|
||||||
[?] Hint: try '$SCRIPT --list' to see list of available ports, and use the -n command like below
|
|
||||||
[?] $SCRIPT [-n <N>]
|
|
||||||
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
HELP
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
CMD "${PM3LIST[$((N-1))]}" "$@"
|
|
||||||
exit $?
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
PM3PATH=$(dirname "$0")
|
|
||||||
. "$PM3PATH/pm3"
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
PM3PATH=$(dirname "$0")
|
|
||||||
. "$PM3PATH/pm3"
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
PM3PATH=$(dirname "$0")
|
|
||||||
. "$PM3PATH/pm3"
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
PM3PATH=$(dirname "$0")
|
|
||||||
. "$PM3PATH/pm3"
|
|
||||||
Binary file not shown.
4
rust-toolchain.toml
Normal file
4
rust-toolchain.toml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[toolchain]
|
||||||
|
channel = "nightly"
|
||||||
|
components = ["rust-src"]
|
||||||
|
targets = ["riscv32imac-unknown-none-elf"]
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=Failure state for fwa.service
|
|
||||||
Requires=local-fs.target
|
|
||||||
After=local-fs.target
|
|
||||||
StartLimitIntervalSec=500
|
|
||||||
StartLimitBurst=5
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
ExecStart=/usr/local/bin/fwa --error
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=5
|
|
||||||
User=root
|
|
||||||
Group=root
|
|
||||||
WorkingDirectory=/var/lib/fwa
|
|
||||||
EnvironmentFile=/etc/fwa.env
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
PM3_BIN=/usr/share/pm3/pm3
|
|
||||||
LOG_LEVEL=warn
|
|
||||||
HOTSPOT_IDS=578B5DF2;c1532b57
|
|
||||||
HOTSPOT_SSID=fwa
|
|
||||||
HOTSPOT_PW=a9LG2kUVrsRRVUo1
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=Feuerwehr Anwesenheit Service
|
|
||||||
Requires=local-fs.target
|
|
||||||
After=local-fs.target
|
|
||||||
StartLimitIntervalSec=500
|
|
||||||
StartLimitBurst=5
|
|
||||||
OnFailure= fwa-fail.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
ExecStart=/usr/local/bin/fwa
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=5
|
|
||||||
User=root
|
|
||||||
Group=root
|
|
||||||
WorkingDirectory=/var/lib/fwa
|
|
||||||
EnvironmentFile=/etc/fwa.env
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
3
src/drivers.rs
Normal file
3
src/drivers.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
pub mod nfc_reader;
|
||||||
|
pub mod rtc;
|
||||||
|
pub mod buzzer;
|
||||||
0
src/drivers/buzzer.rs
Normal file
0
src/drivers/buzzer.rs
Normal file
9
src/drivers/fram.rs
Normal file
9
src/drivers/fram.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
const DEVICE_TYPE_CODE: u8 = 0b10100000;
|
||||||
|
|
||||||
|
const DEVICE_ADDRESS_CODE: u8 = 0b000000; // 3 bits for device address | default A0 = 0 A1 = 0 A2 = 0
|
||||||
|
|
||||||
|
const WRITE_CODE: u8 = 0b00000000; // 0 for write
|
||||||
|
const READ_CODE: u8 = 0b00000001; // 1 for read
|
||||||
|
|
||||||
|
const DEVICE_ADDRESS_WRITE: u8 = DEVICE_TYPE_CODE | DEVICE_ADDRESS_CODE | WRITE_CODE; // I2C address write for FRAM
|
||||||
|
const DEVICE_ADDRESS_READ: u8 = DEVICE_TYPE_CODE | DEVICE_ADDRESS_CODE | READ_CODE; // I2C address read for FRAM
|
||||||
28
src/drivers/nfc_reader.rs
Normal file
28
src/drivers/nfc_reader.rs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
use embassy_time::{Duration, Timer};
|
||||||
|
use esp_hal::{Async, uart::Uart};
|
||||||
|
use log::{debug, info};
|
||||||
|
|
||||||
|
use crate::TallyPublisher;
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
pub async fn rfid_reader_task(mut uart_device: Uart<'static, Async>, chan: TallyPublisher) {
|
||||||
|
let mut uart_buffer = [0u8; 64];
|
||||||
|
|
||||||
|
loop {
|
||||||
|
debug!("Looking for NFC...");
|
||||||
|
match uart_device.read_async(&mut uart_buffer).await {
|
||||||
|
Ok(n) => {
|
||||||
|
let mut hex_str = heapless::String::<64>::new();
|
||||||
|
for byte in &uart_buffer[..n] {
|
||||||
|
core::fmt::Write::write_fmt(&mut hex_str, format_args!("{:02X} ", byte)).ok();
|
||||||
|
}
|
||||||
|
info!("Read {n} bytes from UART: {hex_str}");
|
||||||
|
chan.publish([1, 0, 2, 5, 0, 8, 12, 15]).await;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("Error reading from UART: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Timer::after(Duration::from_millis(200)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
96
src/drivers/rtc.rs
Normal file
96
src/drivers/rtc.rs
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
use ds3231::{
|
||||||
|
Config, DS3231, DS3231Error, InterruptControl, Oscillator, SquareWaveFrequency,
|
||||||
|
TimeRepresentation,
|
||||||
|
};
|
||||||
|
use esp_hal::{
|
||||||
|
Async,
|
||||||
|
i2c::{self, master::I2c},
|
||||||
|
};
|
||||||
|
use log::{debug, error, info};
|
||||||
|
|
||||||
|
use crate::{FEEDBACK_STATE, drivers, feedback};
|
||||||
|
use chrono::{TimeZone, Utc};
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/build_time.rs"));
|
||||||
|
|
||||||
|
const RTC_ADDRESS: u8 = 0x68;
|
||||||
|
|
||||||
|
pub struct RTCClock {
|
||||||
|
dev: DS3231<I2c<'static, Async>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RTCClock {
|
||||||
|
pub async fn new(i2c: i2c::master::I2c<'static, Async>) -> Self {
|
||||||
|
debug!("configuring rtc...");
|
||||||
|
let rtc = drivers::rtc::rtc_config(i2c).await;
|
||||||
|
debug!("rtc up");
|
||||||
|
|
||||||
|
RTCClock { dev: rtc }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_time(&mut self) -> u64 {
|
||||||
|
match self.dev.datetime().await {
|
||||||
|
Ok(datetime) => {
|
||||||
|
let utc_time = datetime.and_utc().timestamp() as u64;
|
||||||
|
utc_time
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
FEEDBACK_STATE.signal(feedback::FeedbackState::Error);
|
||||||
|
error!("Failed to read RTC datetime: {:?}", e);
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn rtc_config(i2c: I2c<'static, Async>) -> DS3231<I2c<'static, Async>> {
|
||||||
|
let mut rtc: DS3231<I2c<'static, Async>> = DS3231::new(i2c, RTC_ADDRESS);
|
||||||
|
let naive_dt = Utc
|
||||||
|
.timestamp_opt(BUILD_UNIX_TIME as i64, 0)
|
||||||
|
.single()
|
||||||
|
.unwrap()
|
||||||
|
.naive_utc();
|
||||||
|
|
||||||
|
let rtc_config = Config {
|
||||||
|
time_representation: TimeRepresentation::TwentyFourHour,
|
||||||
|
square_wave_frequency: SquareWaveFrequency::Hz1,
|
||||||
|
interrupt_control: InterruptControl::Interrupt, // Enable interrupt mode
|
||||||
|
battery_backed_square_wave: false,
|
||||||
|
oscillator_enable: Oscillator::Disabled,
|
||||||
|
};
|
||||||
|
|
||||||
|
match rtc.configure(&rtc_config).await {
|
||||||
|
Ok(_) => info!("DS3231 configured successfully"),
|
||||||
|
Err(e) => {
|
||||||
|
info!("Failed to configure DS3231: {:?}", e);
|
||||||
|
panic!("DS3231 configuration failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc.set_datetime(&naive_dt).await.unwrap_or_else(|e| {
|
||||||
|
FEEDBACK_STATE.signal(feedback::FeedbackState::Error);
|
||||||
|
error!("Failed to set RTC datetime: {:?}", e);
|
||||||
|
});
|
||||||
|
info!("RTC datetime set to: {}", naive_dt);
|
||||||
|
|
||||||
|
match rtc.status().await {
|
||||||
|
Ok(mut status) => {
|
||||||
|
status.set_alarm1_flag(false);
|
||||||
|
status.set_alarm2_flag(false);
|
||||||
|
match rtc.set_status(status).await {
|
||||||
|
Ok(_) => info!("Alarm flags cleared"),
|
||||||
|
Err(e) => info!("Failed to clear alarm flags: {:?}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => info!("Failed to read status: {:?}", e),
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn read_rtc_time<'a>(
|
||||||
|
rtc: &'a mut DS3231<I2c<'static, Async>>,
|
||||||
|
) -> Result<u64, DS3231Error<esp_hal::i2c::master::Error>> {
|
||||||
|
let timestamp_result = rtc.datetime().await?;
|
||||||
|
Ok(timestamp_result.and_utc().timestamp() as u64)
|
||||||
|
}
|
||||||
348
src/feedback.rs
348
src/feedback.rs
@@ -1,181 +1,187 @@
|
|||||||
use anyhow::Result;
|
use embassy_time::{Delay, Duration, Timer};
|
||||||
use log::error;
|
use esp_hal::{delay, gpio::Output, peripherals, rmt::ConstChannelAccess};
|
||||||
use rgb::RGB8;
|
use esp_hal_smartled::SmartLedsAdapterAsync;
|
||||||
use smart_leds::colors::{GREEN, RED};
|
use log::{debug, error, info};
|
||||||
use std::time::Duration;
|
use init::hardware;
|
||||||
use tokio::{join, time::sleep};
|
use smart_leds::colors::{BLACK, GREEN, RED, YELLOW};
|
||||||
|
use smart_leds::{brightness, colors::BLUE};
|
||||||
|
use smart_leds::SmartLedsWriteAsync;
|
||||||
|
|
||||||
use crate::hardware::{Buzzer, StatusLed};
|
use crate::{FEEDBACK_STATE, init};
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_pi"))]
|
#[derive(Copy, Clone, Debug)]
|
||||||
use crate::{hardware::GPIOBuzzer, hardware::SpiLed};
|
pub enum FeedbackState {
|
||||||
|
Ack,
|
||||||
#[cfg(feature = "mock_pi")]
|
Nak,
|
||||||
use crate::hardware::{MockBuzzer, MockLed};
|
Error,
|
||||||
|
Startup,
|
||||||
const LED_BLINK_DURATION: Duration = Duration::from_secs(1);
|
WIFI,
|
||||||
|
Idle,
|
||||||
pub enum DeviceStatus {
|
|
||||||
NotReady,
|
|
||||||
Ready,
|
|
||||||
HotspotEnabled,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeviceStatus {
|
const LED_LEVEL: u8 = 255;
|
||||||
pub fn color(&self) -> RGB8 {
|
|
||||||
match self {
|
|
||||||
Self::NotReady => RGB8::new(0, 0, 0),
|
|
||||||
Self::Ready => RGB8::new(0, 50, 0),
|
|
||||||
Self::HotspotEnabled => RGB8::new(0, 0, 50),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub struct Feedback<B: Buzzer, L: StatusLed> {
|
|
||||||
device_status: DeviceStatus,
|
|
||||||
buzzer: B,
|
|
||||||
led: L,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<B: Buzzer, L: StatusLed> Feedback<B, L> {
|
#[embassy_executor::task]
|
||||||
pub async fn success(&mut self) {
|
pub async fn feedback_task(mut led: SmartLedsAdapterAsync<ConstChannelAccess<esp_hal::rmt::Tx, 0>, { init::hardware::LED_BUFFER_SIZE }>, buzzer: peripherals::GPIO21<'static>) {
|
||||||
let buzzer_handle = Self::beep_ack(&mut self.buzzer);
|
debug!("Starting feedback task");
|
||||||
let led_handle = Self::flash_led_for_duration(&mut self.led, GREEN, LED_BLINK_DURATION);
|
let mut buzzer = init::hardware::setup_buzzer(buzzer);
|
||||||
let (buzzer_result, _) = join!(buzzer_handle, led_handle);
|
loop {
|
||||||
|
let feedback_state = FEEDBACK_STATE.wait().await;
|
||||||
buzzer_result.unwrap_or_else(|err| {
|
match feedback_state {
|
||||||
error!("Failed to buzz: {err}");
|
FeedbackState::Ack => {
|
||||||
});
|
led.write(brightness([GREEN; init::hardware::NUM_LEDS].into_iter(), LED_LEVEL)).await.unwrap();
|
||||||
|
buzzer.set_high();
|
||||||
let _ = self.led_to_status();
|
Timer::after(Duration::from_millis(100)).await;
|
||||||
}
|
buzzer.set_low();
|
||||||
|
Timer::after(Duration::from_millis(50)).await;
|
||||||
pub async fn failure(&mut self) {
|
}
|
||||||
let buzzer_handle = Self::beep_nak(&mut self.buzzer);
|
FeedbackState::Nak => {
|
||||||
let led_handle = Self::flash_led_for_duration(&mut self.led, RED, LED_BLINK_DURATION);
|
led.write(brightness([YELLOW; init::hardware::NUM_LEDS].into_iter(), LED_LEVEL)).await.unwrap();
|
||||||
|
buzzer.set_high();
|
||||||
let (buzzer_result, _) = join!(buzzer_handle, led_handle);
|
Timer::after(Duration::from_millis(100)).await;
|
||||||
|
buzzer.set_low();
|
||||||
buzzer_result.unwrap_or_else(|err| {
|
Timer::after(Duration::from_millis(100)).await;
|
||||||
error!("Failed to buzz: {err}");
|
buzzer.set_high();
|
||||||
});
|
Timer::after(Duration::from_millis(100)).await;
|
||||||
|
buzzer.set_low();
|
||||||
let _ = self.led_to_status();
|
led.write(brightness([BLACK; init::hardware::NUM_LEDS].into_iter(), LED_LEVEL)).await.unwrap();
|
||||||
}
|
}
|
||||||
|
FeedbackState::Error => {
|
||||||
pub async fn activate_error_state(&mut self) -> Result<()> {
|
led.write(brightness([RED; init::hardware::NUM_LEDS].into_iter(), LED_LEVEL)).await.unwrap();
|
||||||
self.led.turn_on(RED)?;
|
buzzer.set_high();
|
||||||
Self::beep_nak(&mut self.buzzer).await?;
|
Timer::after(Duration::from_millis(500)).await;
|
||||||
Ok(())
|
buzzer.set_low();
|
||||||
}
|
Timer::after(Duration::from_millis(500)).await;
|
||||||
|
buzzer.set_high();
|
||||||
pub async fn startup(&mut self){
|
Timer::after(Duration::from_millis(500)).await;
|
||||||
self.device_status = DeviceStatus::Ready;
|
buzzer.set_low();
|
||||||
|
}
|
||||||
let led_handle = Self::flash_led_for_duration(&mut self.led, GREEN, Duration::from_secs(1));
|
FeedbackState::Startup => {
|
||||||
let buzzer_handle = Self::beep_startup(&mut self.buzzer);
|
led.write(brightness([GREEN; init::hardware::NUM_LEDS].into_iter(), LED_LEVEL)).await.unwrap();
|
||||||
|
buzzer.set_high();
|
||||||
let (buzzer_result, led_result) = join!(buzzer_handle, led_handle);
|
Timer::after(Duration::from_millis(10)).await;
|
||||||
|
buzzer.set_low();
|
||||||
buzzer_result.unwrap_or_else(|err| {
|
Timer::after(Duration::from_millis(10)).await;
|
||||||
error!("Failed to buzz: {err}");
|
buzzer.set_high();
|
||||||
});
|
Timer::after(Duration::from_millis(10)).await;
|
||||||
|
buzzer.set_low();
|
||||||
led_result.unwrap_or_else(|err| {
|
Timer::after(Duration::from_millis(50)).await;
|
||||||
error!("Failed to blink led: {err}");
|
buzzer.set_high();
|
||||||
});
|
Timer::after(Duration::from_millis(100)).await;
|
||||||
|
buzzer.set_low();
|
||||||
let _ = self.led_to_status();
|
led.write(brightness([BLACK; init::hardware::NUM_LEDS].into_iter(), LED_LEVEL)).await.unwrap();
|
||||||
}
|
}
|
||||||
|
FeedbackState::WIFI => {
|
||||||
pub fn set_device_status(&mut self, status: DeviceStatus){
|
led.write(brightness([BLUE; init::hardware::NUM_LEDS].into_iter(), LED_LEVEL)).await.unwrap();
|
||||||
self.device_status = status;
|
}
|
||||||
let _ = self.led_to_status();
|
FeedbackState::Idle => {
|
||||||
}
|
// Do nothing
|
||||||
|
}
|
||||||
fn led_to_status(&mut self) -> Result<()> {
|
};
|
||||||
self.led.turn_on(self.device_status.color())
|
debug!("Feedback state: {:?}", feedback_state);
|
||||||
}
|
|
||||||
|
|
||||||
async fn flash_led_for_duration(led: &mut L, color: RGB8, duration: Duration) -> Result<()> {
|
|
||||||
led.turn_on(color)?;
|
|
||||||
|
|
||||||
sleep(duration).await;
|
|
||||||
|
|
||||||
led.turn_off()?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn beep_ack(buzzer: &mut B) -> Result<()> {
|
|
||||||
buzzer
|
|
||||||
.modulated_tone(1200.0, Duration::from_millis(100))
|
|
||||||
.await?;
|
|
||||||
sleep(Duration::from_millis(10)).await;
|
|
||||||
buzzer
|
|
||||||
.modulated_tone(2000.0, Duration::from_millis(50))
|
|
||||||
.await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn beep_nak(buzzer: &mut B) -> Result<()> {
|
|
||||||
buzzer
|
|
||||||
.modulated_tone(600.0, Duration::from_millis(150))
|
|
||||||
.await?;
|
|
||||||
sleep(Duration::from_millis(100)).await;
|
|
||||||
buzzer
|
|
||||||
.modulated_tone(600.0, Duration::from_millis(150))
|
|
||||||
.await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn beep_startup(buzzer: &mut B) -> Result<()> {
|
|
||||||
buzzer
|
|
||||||
.modulated_tone(523.0, Duration::from_millis(150))
|
|
||||||
.await?;
|
|
||||||
buzzer
|
|
||||||
.modulated_tone(659.0, Duration::from_millis(150))
|
|
||||||
.await?;
|
|
||||||
buzzer
|
|
||||||
.modulated_tone(784.0, Duration::from_millis(150))
|
|
||||||
.await?;
|
|
||||||
buzzer
|
|
||||||
.modulated_tone(1046.0, Duration::from_millis(200))
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
sleep(Duration::from_millis(100)).await;
|
|
||||||
|
|
||||||
buzzer
|
|
||||||
.modulated_tone(784.0, Duration::from_millis(100))
|
|
||||||
.await?;
|
|
||||||
buzzer
|
|
||||||
.modulated_tone(880.0, Duration::from_millis(200))
|
|
||||||
.await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "mock_pi")]
|
|
||||||
pub type FeedbackImpl = Feedback<MockBuzzer, MockLed>;
|
|
||||||
#[cfg(not(feature = "mock_pi"))]
|
|
||||||
pub type FeedbackImpl = Feedback<GPIOBuzzer, SpiLed>;
|
|
||||||
|
|
||||||
impl FeedbackImpl {
|
// async fn beep_ack() {
|
||||||
pub fn new() -> Result<Self> {
|
// buzzer.set_high();
|
||||||
#[cfg(feature = "mock_pi")]
|
// buzzer.set_low();
|
||||||
{
|
// //Timer::after(Duration::from_millis(100)).await;
|
||||||
Ok(Feedback {
|
// }
|
||||||
device_status: DeviceStatus::NotReady,
|
|
||||||
buzzer: MockBuzzer {},
|
/* pub async fn failure(&mut self) {
|
||||||
led: MockLed {},
|
let buzzer_handle = Self::beep_nak(&mut self.buzzer);
|
||||||
})
|
let led_handle = Self::flash_led_for_duration(&mut self.led, RED, LED_BLINK_DURATION);
|
||||||
}
|
|
||||||
#[cfg(not(feature = "mock_pi"))]
|
let (buzzer_result, _) = join!(buzzer_handle, led_handle);
|
||||||
{
|
|
||||||
Ok(Feedback {
|
buzzer_result.unwrap_or_else(|err| { error!("Failed to buzz: {err}");
|
||||||
device_status: DeviceStatus::NotReady,
|
});
|
||||||
buzzer: GPIOBuzzer::new_default()?,
|
|
||||||
led: SpiLed::new()?,
|
let _ = self.led_to_status();
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn activate_error_state(&mut self) -> Result<()> {
|
||||||
|
self.led.turn_on(RED)?;
|
||||||
|
Self::beep_nak(&mut self.buzzer).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn startup(&mut self){
|
||||||
|
self.device_status = DeviceStatus::Ready;
|
||||||
|
|
||||||
|
let led_handle = Self::flash_led_for_duration(&mut self.led, GREEN, Duration::from_secs(1));
|
||||||
|
let buzzer_handle = Self::beep_startup(&mut self.buzzer);
|
||||||
|
|
||||||
|
let (buzzer_result, led_result) = join!(buzzer_handle, led_handle);
|
||||||
|
|
||||||
|
buzzer_result.unwrap_or_else(|err| {
|
||||||
|
error!("Failed to buzz: {err}");
|
||||||
|
});
|
||||||
|
|
||||||
|
led_result.unwrap_or_else(|err| {
|
||||||
|
error!("Failed to blink led: {err}");
|
||||||
|
});
|
||||||
|
|
||||||
|
let _ = self.led_to_status();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async fn flash_led_for_duration(led: &mut L, color: RGB8, duration: Duration) -> Result<()> {
|
||||||
|
led.turn_on(color)?;
|
||||||
|
|
||||||
|
sleep(duration).await;
|
||||||
|
|
||||||
|
led.turn_off()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn beep_ack(buzzer: &mut B) -> Result<()> {
|
||||||
|
buzzer
|
||||||
|
.modulated_tone(1200.0, Duration::from_millis(100))
|
||||||
|
.await?;
|
||||||
|
sleep(Duration::from_millis(10)).await;
|
||||||
|
buzzer
|
||||||
|
.modulated_tone(2000.0, Duration::from_millis(50))
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn beep_nak(buzzer: &mut B) -> Result<()> {
|
||||||
|
buzzer
|
||||||
|
.modulated_tone(600.0, Duration::from_millis(150))
|
||||||
|
.await?;
|
||||||
|
sleep(Duration::from_millis(100)).await;
|
||||||
|
buzzer
|
||||||
|
.modulated_tone(600.0, Duration::from_millis(150))
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn beep_startup(buzzer: &mut B) -> Result<()> {
|
||||||
|
buzzer
|
||||||
|
.modulated_tone(523.0, Duration::from_millis(150))
|
||||||
|
.await?;
|
||||||
|
buzzer
|
||||||
|
.modulated_tone(659.0, Duration::from_millis(150))
|
||||||
|
.await?;
|
||||||
|
buzzer
|
||||||
|
.modulated_tone(784.0, Duration::from_millis(150))
|
||||||
|
.await?;
|
||||||
|
buzzer
|
||||||
|
.modulated_tone(1046.0, Duration::from_millis(200))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
sleep(Duration::from_millis(100)).await;
|
||||||
|
|
||||||
|
buzzer
|
||||||
|
.modulated_tone(784.0, Duration::from_millis(100))
|
||||||
|
.await?;
|
||||||
|
buzzer
|
||||||
|
.modulated_tone(880.0, Duration::from_millis(200))
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
use anyhow::Result;
|
|
||||||
use rppal::pwm::{Channel, Polarity, Pwm};
|
|
||||||
use std::time::Duration;
|
|
||||||
use tokio::time::sleep;
|
|
||||||
|
|
||||||
use crate::hardware::Buzzer;
|
|
||||||
|
|
||||||
const DEFAULT_PWM_CHANNEL_BUZZER: Channel = Channel::Pwm0; //PWM0 = GPIO18/Physical pin 12
|
|
||||||
|
|
||||||
pub struct GPIOBuzzer {
|
|
||||||
pwm: Pwm,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GPIOBuzzer {
|
|
||||||
pub fn new_from_channel(channel: Channel) -> Result<Self, rppal::pwm::Error> {
|
|
||||||
// Enable with dummy values; we'll set frequency/duty in the tone method
|
|
||||||
let duty_cycle: f64 = 0.5;
|
|
||||||
let pwm = Pwm::with_frequency(channel, 1000.0, duty_cycle, Polarity::Normal, true)?;
|
|
||||||
pwm.disable()?;
|
|
||||||
|
|
||||||
Ok(GPIOBuzzer { pwm })
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_default() -> Result<Self, rppal::pwm::Error> {
|
|
||||||
Self::new_from_channel(DEFAULT_PWM_CHANNEL_BUZZER)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Buzzer for GPIOBuzzer {
|
|
||||||
async fn modulated_tone(&mut self, frequency_hz: f64, duration: Duration) -> Result<()> {
|
|
||||||
self.pwm.set_frequency(frequency_hz, 0.5)?; // 50% duty cycle (square wave)
|
|
||||||
self.pwm.enable()?;
|
|
||||||
sleep(duration).await;
|
|
||||||
self.pwm.disable()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
use anyhow::{Result, anyhow};
|
|
||||||
use log::{trace, warn};
|
|
||||||
use std::env;
|
|
||||||
use tokio::process::Command;
|
|
||||||
|
|
||||||
use crate::hardware::Hotspot;
|
|
||||||
|
|
||||||
const SSID: &str = "fwa";
|
|
||||||
const CON_NAME: &str = "fwa-hotspot";
|
|
||||||
const PASSWORD: &str = "a9LG2kUVrsRRVUo1";
|
|
||||||
const IPV4_ADDRES: &str = "192.168.4.1/24";
|
|
||||||
|
|
||||||
/// NetworkManager Hotspot
|
|
||||||
pub struct NMHotspot {
|
|
||||||
ssid: String,
|
|
||||||
con_name: String,
|
|
||||||
password: String,
|
|
||||||
ipv4: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NMHotspot {
|
|
||||||
pub fn new_from_env() -> Result<Self> {
|
|
||||||
let ssid = env::var("HOTSPOT_SSID").unwrap_or(SSID.to_owned());
|
|
||||||
let password = env::var("HOTSPOT_PW").unwrap_or_else(|_| {
|
|
||||||
warn!("HOTSPOT_PW not set. Using default password");
|
|
||||||
PASSWORD.to_owned()
|
|
||||||
});
|
|
||||||
|
|
||||||
if password.len() < 8 {
|
|
||||||
return Err(anyhow!("Hotspot password to short"));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(NMHotspot {
|
|
||||||
ssid,
|
|
||||||
con_name: CON_NAME.to_owned(),
|
|
||||||
password,
|
|
||||||
ipv4: IPV4_ADDRES.to_owned(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn create_hotspot(&self) -> Result<()> {
|
|
||||||
let cmd = Command::new("nmcli")
|
|
||||||
.args(["device", "wifi", "hotspot"])
|
|
||||||
.arg("con-name")
|
|
||||||
.arg(&self.con_name)
|
|
||||||
.arg("ssid")
|
|
||||||
.arg(&self.ssid)
|
|
||||||
.arg("password")
|
|
||||||
.arg(&self.password)
|
|
||||||
.output()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
trace!("nmcli (std): {}", String::from_utf8_lossy(&cmd.stdout));
|
|
||||||
trace!("nmcli (err): {}", String::from_utf8_lossy(&cmd.stderr));
|
|
||||||
|
|
||||||
if !cmd.status.success() {
|
|
||||||
return Err(anyhow!("nmcli command had non-zero exit code"));
|
|
||||||
}
|
|
||||||
|
|
||||||
let cmd = Command::new("nmcli")
|
|
||||||
.arg("connection")
|
|
||||||
.arg("modify")
|
|
||||||
.arg(&self.con_name)
|
|
||||||
.arg("ipv4.method")
|
|
||||||
.arg("shared")
|
|
||||||
.arg("ipv4.addresses")
|
|
||||||
.arg(&self.ipv4)
|
|
||||||
.output()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
if !cmd.status.success() {
|
|
||||||
return Err(anyhow!("nmcli command had non-zero exit code"));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks if the connection already exists
|
|
||||||
async fn exists(&self) -> Result<bool> {
|
|
||||||
let cmd = Command::new("nmcli")
|
|
||||||
.args(["connection", "show"])
|
|
||||||
.arg(&self.con_name)
|
|
||||||
.output()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
trace!("nmcli (std): {}", String::from_utf8_lossy(&cmd.stdout));
|
|
||||||
trace!("nmcli (err): {}", String::from_utf8_lossy(&cmd.stderr));
|
|
||||||
|
|
||||||
Ok(cmd.status.success())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Hotspot for NMHotspot {
|
|
||||||
async fn enable_hotspot(&self) -> Result<()> {
|
|
||||||
if !self.exists().await? {
|
|
||||||
self.create_hotspot().await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let cmd = Command::new("nmcli")
|
|
||||||
.args(["connection", "up"])
|
|
||||||
.arg(&self.con_name)
|
|
||||||
.output()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
trace!("nmcli (std): {}", String::from_utf8_lossy(&cmd.stdout));
|
|
||||||
trace!("nmcli (err): {}", String::from_utf8_lossy(&cmd.stderr));
|
|
||||||
|
|
||||||
if !cmd.status.success() {
|
|
||||||
return Err(anyhow!("nmcli command had non-zero exit code"));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn disable_hotspot(&self) -> Result<()> {
|
|
||||||
let cmd = Command::new("nmcli")
|
|
||||||
.args(["connection", "down"])
|
|
||||||
.arg(&self.con_name)
|
|
||||||
.output()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
trace!("nmcli (std): {}", String::from_utf8_lossy(&cmd.stdout));
|
|
||||||
trace!("nmcli (err): {}", String::from_utf8_lossy(&cmd.stderr));
|
|
||||||
|
|
||||||
if !cmd.status.success() {
|
|
||||||
return Err(anyhow!("nmcli command had non-zero exit code"));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
use anyhow::Result;
|
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
mod gpio_buzzer;
|
|
||||||
mod hotspot;
|
|
||||||
mod mock;
|
|
||||||
mod spi_led;
|
|
||||||
|
|
||||||
pub use gpio_buzzer::GPIOBuzzer;
|
|
||||||
pub use mock::{MockBuzzer, MockHotspot, MockLed};
|
|
||||||
pub use spi_led::SpiLed;
|
|
||||||
|
|
||||||
pub trait StatusLed {
|
|
||||||
fn turn_off(&mut self) -> Result<()>;
|
|
||||||
|
|
||||||
fn turn_on(&mut self, color: rgb::RGB8) -> Result<()>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Buzzer {
|
|
||||||
fn modulated_tone(
|
|
||||||
&mut self,
|
|
||||||
frequency_hz: f64,
|
|
||||||
duration: Duration,
|
|
||||||
) -> impl Future<Output = Result<()>> + std::marker::Send;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Hotspot {
|
|
||||||
fn enable_hotspot(&self) -> impl std::future::Future<Output = Result<()>> + std::marker::Send;
|
|
||||||
|
|
||||||
fn disable_hotspot(&self) -> impl std::future::Future<Output = Result<()>> + std::marker::Send;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a struct to manage the hotspot
|
|
||||||
/// Respects the `mock_pi` flag.
|
|
||||||
pub fn create_hotspot() -> Result<impl Hotspot> {
|
|
||||||
#[cfg(feature = "mock_pi")]
|
|
||||||
{
|
|
||||||
Ok(mock::MockHotspot {})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "mock_pi"))]
|
|
||||||
{
|
|
||||||
hotspot::NMHotspot::new_from_env()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
use anyhow::Result;
|
|
||||||
use rppal::spi::{Bus, Mode, SlaveSelect, Spi};
|
|
||||||
use smart_leds::SmartLedsWrite;
|
|
||||||
use ws2812_spi::Ws2812;
|
|
||||||
|
|
||||||
use crate::hardware::StatusLed;
|
|
||||||
|
|
||||||
const SPI_CLOCK_SPEED: u32 = 3_800_000;
|
|
||||||
|
|
||||||
pub struct SpiLed {
|
|
||||||
controller: Ws2812<Spi>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SpiLed {
|
|
||||||
pub fn new() -> Result<Self, rppal::spi::Error> {
|
|
||||||
let spi = Spi::new(Bus::Spi0, SlaveSelect::Ss0, SPI_CLOCK_SPEED, Mode::Mode0)?;
|
|
||||||
let controller = Ws2812::new(spi);
|
|
||||||
Ok(SpiLed { controller })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl StatusLed for SpiLed {
|
|
||||||
fn turn_off(&mut self) -> Result<()> {
|
|
||||||
self.controller
|
|
||||||
.write(vec![rgb::RGB8::new(0, 0, 0)].into_iter())?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn turn_on(&mut self, color: rgb::RGB8) -> Result<()> {
|
|
||||||
self.controller.write(vec![color].into_iter())?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
3
src/init.rs
Normal file
3
src/init.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
pub mod hardware;
|
||||||
|
pub mod network;
|
||||||
|
pub mod wifi;
|
||||||
215
src/init/hardware.rs
Normal file
215
src/init/hardware.rs
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_net::Stack;
|
||||||
|
use embassy_time::{Duration, Timer};
|
||||||
|
use embedded_sdmmc_dev::SdCard;
|
||||||
|
use esp_hal::i2c::master::Config;
|
||||||
|
use esp_hal::peripherals::{
|
||||||
|
self, GPIO0, GPIO1, GPIO2, GPIO10, GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22,
|
||||||
|
GPIO23, I2C0, RMT, SPI2, UART1,
|
||||||
|
};
|
||||||
|
use esp_hal::rmt::{ConstChannelAccess, Rmt, Tx};
|
||||||
|
use esp_hal::spi::{
|
||||||
|
Mode,
|
||||||
|
master::{Config as Spi_config, Spi},
|
||||||
|
};
|
||||||
|
|
||||||
|
use esp_hal::time::Rate;
|
||||||
|
use esp_hal::timer::timg::TimerGroup;
|
||||||
|
use esp_hal::{
|
||||||
|
Async,
|
||||||
|
clock::CpuClock,
|
||||||
|
gpio::{Output, OutputConfig},
|
||||||
|
i2c::master::I2c,
|
||||||
|
timer::systimer::SystemTimer,
|
||||||
|
uart::Uart,
|
||||||
|
};
|
||||||
|
|
||||||
|
use esp_hal_smartled::{SmartLedsAdapterAsync, buffer_size_async};
|
||||||
|
|
||||||
|
use smart_leds::colors::{BLUE, GREEN, RED};
|
||||||
|
use smart_leds::{
|
||||||
|
RGB8, SmartLedsWriteAsync, brightness, gamma,
|
||||||
|
hsv::{Hsv, hsv2rgb},
|
||||||
|
};
|
||||||
|
|
||||||
|
use esp_println::logger::init_logger;
|
||||||
|
use log::{debug, error};
|
||||||
|
|
||||||
|
use crate::init::network;
|
||||||
|
use crate::init::wifi;
|
||||||
|
|
||||||
|
/*************************************************
|
||||||
|
* GPIO Pinout Xiao Esp32c6
|
||||||
|
*
|
||||||
|
* D0 -> GPIO0 -> SD DECT
|
||||||
|
* D1 -> GPIO1 -> Level Shifter A0 -> LED
|
||||||
|
* D2 -> GPIO2 -> SPI/CS
|
||||||
|
* D3 -> GPIO21 -> Buzzer
|
||||||
|
* D4 -> GPIO22 -> I2C/SDA
|
||||||
|
* D5 -> GPIO23 -> I2C/SCL
|
||||||
|
* D6 -> GPIO16 -> UART/TX
|
||||||
|
* D7 -> GPIO17 -> UART/RX -> Level Shifter A1 -> NFC Reader
|
||||||
|
* D8 -> GPIO19 -> SPI/SCLK
|
||||||
|
* D9 -> GPIO20 -> SPI/MISO
|
||||||
|
* D10 -> GPIO10 -> SPI/MOSI
|
||||||
|
*
|
||||||
|
*************************************************/
|
||||||
|
|
||||||
|
pub const NUM_LEDS: usize = 66;
|
||||||
|
pub const LED_BUFFER_SIZE: usize = NUM_LEDS * 25;
|
||||||
|
|
||||||
|
#[panic_handler]
|
||||||
|
fn panic(info: &core::panic::PanicInfo) -> ! {
|
||||||
|
loop {
|
||||||
|
error!("PANIC: {info}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_bootloader_esp_idf::esp_app_desc!();
|
||||||
|
|
||||||
|
pub async fn hardware_init(
|
||||||
|
spawner: &mut Spawner,
|
||||||
|
) -> (
|
||||||
|
Uart<'static, Async>,
|
||||||
|
Stack<'static>,
|
||||||
|
I2c<'static, Async>,
|
||||||
|
SmartLedsAdapterAsync<ConstChannelAccess<esp_hal::rmt::Tx, 0>, LED_BUFFER_SIZE>,
|
||||||
|
GPIO21<'static>,
|
||||||
|
) {
|
||||||
|
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
|
||||||
|
let peripherals = esp_hal::init(config);
|
||||||
|
|
||||||
|
esp_alloc::heap_allocator!(size: 72 * 1024);
|
||||||
|
|
||||||
|
let timer0 = SystemTimer::new(peripherals.SYSTIMER);
|
||||||
|
esp_hal_embassy::init(timer0.alarm0);
|
||||||
|
|
||||||
|
init_logger(log::LevelFilter::Debug);
|
||||||
|
|
||||||
|
let timer1 = TimerGroup::new(peripherals.TIMG0);
|
||||||
|
let mut rng = esp_hal::rng::Rng::new(peripherals.RNG);
|
||||||
|
let network_seed = (rng.random() as u64) << 32 | rng.random() as u64;
|
||||||
|
|
||||||
|
wifi::set_antenna_mode(peripherals.GPIO3, peripherals.GPIO14).await;
|
||||||
|
let interfaces = wifi::setup_wifi(timer1.timer0, rng, peripherals.WIFI, spawner);
|
||||||
|
let stack = network::setup_network(network_seed, interfaces.ap, spawner);
|
||||||
|
|
||||||
|
Timer::after(Duration::from_millis(1)).await;
|
||||||
|
init_lvl_shifter(peripherals.GPIO0);
|
||||||
|
|
||||||
|
let uart_device = setup_uart(peripherals.UART1, peripherals.GPIO16, peripherals.GPIO17);
|
||||||
|
|
||||||
|
let i2c_device = setup_i2c(peripherals.I2C0, peripherals.GPIO22, peripherals.GPIO23);
|
||||||
|
|
||||||
|
let spi_device = setup_spi(
|
||||||
|
peripherals.SPI2,
|
||||||
|
peripherals.GPIO19,
|
||||||
|
peripherals.GPIO20,
|
||||||
|
peripherals.GPIO18,
|
||||||
|
peripherals.GPIO2,
|
||||||
|
);
|
||||||
|
|
||||||
|
let sd_card = setup_sdcard(spi_device);
|
||||||
|
|
||||||
|
let buzzer_gpio = peripherals.GPIO21;
|
||||||
|
|
||||||
|
Timer::after(Duration::from_millis(500)).await;
|
||||||
|
|
||||||
|
let led = setup_led(peripherals.RMT, peripherals.GPIO1);
|
||||||
|
|
||||||
|
debug!("hardware init done");
|
||||||
|
|
||||||
|
(uart_device, stack, i2c_device, led, buzzer_gpio)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the level shifter for the NFC reader and LED (output-enable (OE) input is low, all outputs are placed in the high-impedance (Hi-Z) state)
|
||||||
|
fn init_lvl_shifter(oe_pin: GPIO0<'static>) {
|
||||||
|
let mut oe_lvl_shifter =
|
||||||
|
Output::new(oe_pin, esp_hal::gpio::Level::Low, OutputConfig::default().with_drive_mode(esp_hal::gpio::DriveMode::PushPull).with_drive_strength(esp_hal::gpio::DriveStrength::_10mA));
|
||||||
|
oe_lvl_shifter.set_high();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_uart(
|
||||||
|
uart1: UART1<'static>,
|
||||||
|
uart_tx: GPIO16<'static>,
|
||||||
|
uart_rx: GPIO17<'static>,
|
||||||
|
) -> Uart<'static, Async> {
|
||||||
|
let uard_device = Uart::new(uart1, esp_hal::uart::Config::default().with_baudrate(9600));
|
||||||
|
|
||||||
|
match uard_device {
|
||||||
|
Ok(block) => block.with_rx(uart_rx).with_tx(uart_tx).into_async(),
|
||||||
|
Err(e) => {
|
||||||
|
error!("Failed to initialize UART: {e}");
|
||||||
|
panic!(); //TODO panic!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_i2c(
|
||||||
|
i2c0: I2C0<'static>,
|
||||||
|
sda: GPIO22<'static>,
|
||||||
|
scl: GPIO23<'static>,
|
||||||
|
) -> I2c<'static, Async> {
|
||||||
|
debug!("init I2C");
|
||||||
|
let config = Config::default().with_frequency(Rate::from_khz(400));
|
||||||
|
let i2c = match I2c::new(i2c0, config) {
|
||||||
|
Ok(i2c) => i2c.with_sda(sda).with_scl(scl).into_async(),
|
||||||
|
Err(e) => {
|
||||||
|
error!("Failed to initialize I2C: {:?}", e);
|
||||||
|
panic!(); //TODO panic!
|
||||||
|
}
|
||||||
|
};
|
||||||
|
i2c
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_spi(
|
||||||
|
spi2: SPI2<'static>,
|
||||||
|
sck: GPIO19<'static>,
|
||||||
|
miso: GPIO20<'static>,
|
||||||
|
mosi: GPIO18<'static>,
|
||||||
|
cs: GPIO2<'static>,
|
||||||
|
) -> Spi<'static, Async> {
|
||||||
|
let spi = match Spi::new(spi2, Spi_config::default()) {
|
||||||
|
Ok(spi) => spi
|
||||||
|
.with_sck(sck)
|
||||||
|
.with_miso(miso)
|
||||||
|
.with_mosi(mosi)
|
||||||
|
.with_cs(cs)
|
||||||
|
.into_async(),
|
||||||
|
Err(e) => panic!("Failed to initialize SPI: {:?}", e),
|
||||||
|
};
|
||||||
|
spi
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_sdcard(spi_device: Spi<'static, Async>) {
|
||||||
|
//let sdcard = SdCard::new(spi_device as embedded_hal::spi::SpiDevice(), delayer)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setup_buzzer(buzzer_gpio: GPIO21<'static>) -> Output<'static> {
|
||||||
|
let config = esp_hal::gpio::OutputConfig::default()
|
||||||
|
.with_drive_strength(esp_hal::gpio::DriveStrength::_40mA);
|
||||||
|
let buzzer = Output::new(buzzer_gpio, esp_hal::gpio::Level::Low, config);
|
||||||
|
|
||||||
|
buzzer
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_led(
|
||||||
|
rmt: RMT<'static>,
|
||||||
|
led_gpio: GPIO1<'static>,
|
||||||
|
) -> SmartLedsAdapterAsync<ConstChannelAccess<esp_hal::rmt::Tx, 0>, LED_BUFFER_SIZE> {
|
||||||
|
debug!("setup led");
|
||||||
|
let rmt: Rmt<'_, esp_hal::Async> = {
|
||||||
|
let frequency: Rate = Rate::from_mhz(80);
|
||||||
|
Rmt::new(rmt, frequency)
|
||||||
|
}
|
||||||
|
.expect("Failed to initialize RMT")
|
||||||
|
.into_async();
|
||||||
|
|
||||||
|
let rmt_channel = rmt.channel0;
|
||||||
|
let rmt_buffer = [0_u32; buffer_size_async(NUM_LEDS)];
|
||||||
|
|
||||||
|
let led: SmartLedsAdapterAsync<_, LED_BUFFER_SIZE> =
|
||||||
|
SmartLedsAdapterAsync::new(rmt_channel, led_gpio, rmt_buffer);
|
||||||
|
|
||||||
|
led
|
||||||
|
}
|
||||||
72
src/init/network.rs
Normal file
72
src/init/network.rs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
use core::{net::Ipv4Addr, str::FromStr};
|
||||||
|
|
||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_net::{Ipv4Cidr, Runner, Stack, StackResources, StaticConfigV4};
|
||||||
|
use embassy_time::{Duration, Timer};
|
||||||
|
use esp_wifi::wifi::WifiDevice;
|
||||||
|
use static_cell::make_static;
|
||||||
|
|
||||||
|
|
||||||
|
pub fn setup_network<'a>(seed: u64, wifi: WifiDevice<'static>, spawner: &mut Spawner) -> Stack<'a> {
|
||||||
|
let gw_ip_addr_str = "192.168.2.1";
|
||||||
|
let gw_ip_addr = Ipv4Addr::from_str(gw_ip_addr_str).expect("failed to parse gateway ip");
|
||||||
|
let config = embassy_net::Config::ipv4_static(StaticConfigV4 {
|
||||||
|
address: Ipv4Cidr::new(gw_ip_addr, 24),
|
||||||
|
gateway: Some(gw_ip_addr),
|
||||||
|
dns_servers: Default::default(),
|
||||||
|
});
|
||||||
|
|
||||||
|
let (stack, runner) =
|
||||||
|
embassy_net::new(wifi, config, make_static!(StackResources::<3>::new()), seed);
|
||||||
|
|
||||||
|
spawner.must_spawn(net_task(runner));
|
||||||
|
spawner.must_spawn(run_dhcp(stack, gw_ip_addr_str));
|
||||||
|
|
||||||
|
stack
|
||||||
|
}
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
async fn run_dhcp(stack: Stack<'static>, gw_ip_addr: &'static str) {
|
||||||
|
use core::net::{Ipv4Addr, SocketAddrV4};
|
||||||
|
|
||||||
|
use edge_dhcp::{
|
||||||
|
io::{self, DEFAULT_SERVER_PORT},
|
||||||
|
server::{Server, ServerOptions},
|
||||||
|
};
|
||||||
|
use edge_nal::UdpBind;
|
||||||
|
use edge_nal_embassy::{Udp, UdpBuffers};
|
||||||
|
|
||||||
|
let ip = Ipv4Addr::from_str(gw_ip_addr).expect("dhcp task failed to parse gw ip");
|
||||||
|
|
||||||
|
let mut buf = [0u8; 1500];
|
||||||
|
|
||||||
|
let mut gw_buf = [Ipv4Addr::UNSPECIFIED];
|
||||||
|
|
||||||
|
let buffers = UdpBuffers::<3, 1024, 1024, 10>::new();
|
||||||
|
let unbound_socket = Udp::new(stack, &buffers);
|
||||||
|
let mut bound_socket = unbound_socket
|
||||||
|
.bind(core::net::SocketAddr::V4(SocketAddrV4::new(
|
||||||
|
Ipv4Addr::UNSPECIFIED,
|
||||||
|
DEFAULT_SERVER_PORT,
|
||||||
|
)))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
_ = io::server::run(
|
||||||
|
&mut Server::<_, 64>::new_with_et(ip),
|
||||||
|
&ServerOptions::new(ip, Some(&mut gw_buf)),
|
||||||
|
&mut bound_socket,
|
||||||
|
&mut buf,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.inspect_err(|e| log::warn!("DHCP server error: {e:?}"));
|
||||||
|
Timer::after(Duration::from_millis(500)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
async fn net_task(mut runner: Runner<'static, WifiDevice<'static>>) {
|
||||||
|
runner.run().await;
|
||||||
|
}
|
||||||
|
|
||||||
56
src/init/wifi.rs
Normal file
56
src/init/wifi.rs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_time::{Duration, Timer};
|
||||||
|
use esp_hal::gpio::{Output, OutputConfig};
|
||||||
|
use esp_hal::peripherals::{GPIO3, GPIO14, WIFI};
|
||||||
|
use esp_wifi::wifi::{AccessPointConfiguration, Configuration, WifiController, WifiEvent, WifiState};
|
||||||
|
use esp_wifi::{EspWifiRngSource, EspWifiTimerSource, wifi::Interfaces};
|
||||||
|
use static_cell::make_static;
|
||||||
|
|
||||||
|
pub async fn set_antenna_mode(gpio3: GPIO3<'static>, gpio14: GPIO14<'static>) {
|
||||||
|
let mut rf_switch = Output::new(gpio3, esp_hal::gpio::Level::Low, OutputConfig::default());
|
||||||
|
|
||||||
|
rf_switch.set_low();
|
||||||
|
|
||||||
|
Timer::after_millis(150).await;
|
||||||
|
|
||||||
|
let mut antenna_mode = Output::new(gpio14, esp_hal::gpio::Level::Low, OutputConfig::default());
|
||||||
|
|
||||||
|
antenna_mode.set_low();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setup_wifi<'d: 'static>(
|
||||||
|
timer: impl EspWifiTimerSource + 'd,
|
||||||
|
rng: impl EspWifiRngSource + 'd,
|
||||||
|
wifi: WIFI<'static>,
|
||||||
|
spawner: &mut Spawner,
|
||||||
|
) -> Interfaces<'d> {
|
||||||
|
let esp_wifi_ctrl = make_static!(esp_wifi::init(timer, rng).unwrap());
|
||||||
|
|
||||||
|
let (controller, interfaces) = esp_wifi::wifi::new(esp_wifi_ctrl, wifi).unwrap();
|
||||||
|
|
||||||
|
spawner.must_spawn(connection(controller));
|
||||||
|
|
||||||
|
interfaces
|
||||||
|
}
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
async fn connection(mut controller: WifiController<'static>) {
|
||||||
|
loop {
|
||||||
|
match esp_wifi::wifi::wifi_state() {
|
||||||
|
WifiState::ApStarted => {
|
||||||
|
// wait until we're no longer connected
|
||||||
|
controller.wait_for_event(WifiEvent::ApStop).await;
|
||||||
|
Timer::after(Duration::from_millis(5000)).await
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
if !matches!(controller.is_started(), Ok(true)) {
|
||||||
|
let client_config = Configuration::AccessPoint(AccessPointConfiguration {
|
||||||
|
ssid: "esp-wifi".try_into().unwrap(),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
controller.set_configuration(&client_config).unwrap();
|
||||||
|
controller.start_async().await.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/lib.rs
Normal file
1
src/lib.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#![no_std]
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
use std::env;
|
|
||||||
|
|
||||||
use log::LevelFilter;
|
|
||||||
use simplelog::{ConfigBuilder, SimpleLogger};
|
|
||||||
|
|
||||||
pub fn setup_logger() {
|
|
||||||
let log_level = env::var("LOG_LEVEL")
|
|
||||||
.ok()
|
|
||||||
.and_then(|level| level.parse::<LevelFilter>().ok())
|
|
||||||
.unwrap_or({
|
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
LevelFilter::Debug
|
|
||||||
} else {
|
|
||||||
LevelFilter::Warn
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let config = ConfigBuilder::new()
|
|
||||||
.set_target_level(LevelFilter::Off)
|
|
||||||
.set_location_level(LevelFilter::Off)
|
|
||||||
.set_thread_level(LevelFilter::Off)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let _ = SimpleLogger::init(log_level, config);
|
|
||||||
}
|
|
||||||
244
src/main.rs
244
src/main.rs
@@ -1,192 +1,90 @@
|
|||||||
#![allow(dead_code)]
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
#![feature(impl_trait_in_assoc_type)]
|
||||||
|
|
||||||
use anyhow::Result;
|
use embassy_executor::Spawner;
|
||||||
use feedback::{Feedback, FeedbackImpl};
|
use embassy_net::Stack;
|
||||||
use log::{error, info, warn};
|
use embassy_sync::{
|
||||||
use std::{
|
blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}, channel::Channel, pubsub::{
|
||||||
env::{self, args},
|
PubSubChannel, Publisher,
|
||||||
sync::Arc,
|
WaitResult::{Lagged, Message},
|
||||||
time::Duration,
|
}, signal::Signal
|
||||||
};
|
};
|
||||||
use tally_id::TallyID;
|
use embassy_time::{Duration, Timer};
|
||||||
use tokio::{
|
use log::{debug, info};
|
||||||
fs,
|
use static_cell::make_static;
|
||||||
signal::unix::{SignalKind, signal},
|
|
||||||
sync::{
|
|
||||||
Mutex,
|
|
||||||
broadcast::{self, Receiver, Sender},
|
|
||||||
},
|
|
||||||
try_join,
|
|
||||||
};
|
|
||||||
use webserver::start_webserver;
|
|
||||||
|
|
||||||
use crate::{hardware::{create_hotspot, Hotspot}, pm3::run_pm3, store::IDStore, webserver::{spawn_idle_watcher, ActivityNotifier}};
|
use crate::{store::TallyID, webserver::start_webserver};
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
mod drivers;
|
||||||
mod feedback;
|
mod feedback;
|
||||||
mod hardware;
|
mod init;
|
||||||
mod pm3;
|
|
||||||
mod logger;
|
|
||||||
mod tally_id;
|
|
||||||
mod webserver;
|
|
||||||
mod store;
|
mod store;
|
||||||
|
mod webserver;
|
||||||
|
|
||||||
const STORE_PATH: &str = "./data.json";
|
static FEEDBACK_STATE: Signal<CriticalSectionRawMutex, feedback::FeedbackState> = Signal::new();
|
||||||
|
|
||||||
async fn run_webserver<H>(
|
type TallyChannel = PubSubChannel<NoopRawMutex, TallyID, 8, 2, 1>;
|
||||||
store: Arc<Mutex<IDStore>>,
|
type TallyPublisher = Publisher<'static, NoopRawMutex, TallyID, 8, 2, 1>;
|
||||||
id_channel: Sender<String>,
|
|
||||||
hotspot: Arc<Mutex<H>>,
|
|
||||||
user_feedback: Arc<Mutex<FeedbackImpl>>,
|
|
||||||
) -> Result<()>
|
|
||||||
where
|
|
||||||
H: Hotspot + Send + Sync + 'static,
|
|
||||||
{
|
|
||||||
let activity_channel = spawn_idle_watcher(Duration::from_secs(60 * 30), move || {
|
|
||||||
info!("No activity on webserver. Disabling hotspot");
|
|
||||||
let cloned_hotspot = hotspot.clone();
|
|
||||||
let cloned_user_feedback = user_feedback.clone();
|
|
||||||
tokio::spawn(async move {
|
|
||||||
let _ = cloned_hotspot.lock().await.disable_hotspot().await;
|
|
||||||
cloned_user_feedback
|
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.set_device_status(feedback::DeviceStatus::Ready);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
let notifier = ActivityNotifier {
|
#[esp_hal_embassy::main]
|
||||||
sender: activity_channel,
|
async fn main(mut spawner: Spawner) {
|
||||||
};
|
let (uart_device, stack, _i2c, _led, buzzer_gpio) =
|
||||||
|
init::hardware::hardware_init(&mut spawner).await;
|
||||||
|
|
||||||
start_webserver(store, id_channel, notifier).await?;
|
wait_for_stack_up(stack).await;
|
||||||
|
|
||||||
Ok(())
|
info!("Starting up...");
|
||||||
}
|
|
||||||
|
|
||||||
async fn load_or_create_store() -> Result<IDStore> {
|
let chan: &'static mut TallyChannel = make_static!(PubSubChannel::new());
|
||||||
if fs::try_exists(STORE_PATH).await? {
|
|
||||||
info!("Loading data from file");
|
//start_webserver(&mut spawner, stack);
|
||||||
IDStore::new_from_json(STORE_PATH).await
|
|
||||||
} else {
|
let publisher = chan.publisher().unwrap();
|
||||||
info!("No data file found. Creating empty one.");
|
|
||||||
Ok(IDStore::new())
|
let mut rtc = drivers::rtc::RTCClock::new(_i2c).await;
|
||||||
|
|
||||||
|
/****************************** Spawning tasks ***********************************/
|
||||||
|
debug!("spawing NFC reader task...");
|
||||||
|
spawner.must_spawn(drivers::nfc_reader::rfid_reader_task(
|
||||||
|
uart_device,
|
||||||
|
publisher,
|
||||||
|
));
|
||||||
|
|
||||||
|
debug!("spawing feedback task..");
|
||||||
|
spawner.must_spawn(feedback::feedback_task(_led, buzzer_gpio));
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
let mut sub = chan.subscriber().unwrap();
|
||||||
|
|
||||||
|
debug!("everything spawned");
|
||||||
|
FEEDBACK_STATE.signal(feedback::FeedbackState::Startup);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
rtc.get_time().await;
|
||||||
|
info!("Current RTC time: {}", rtc.get_time().await);
|
||||||
|
Timer::after(Duration::from_millis(1000)).await;
|
||||||
|
|
||||||
|
// let wait_result = sub.next_message().await;
|
||||||
|
// match wait_result {
|
||||||
|
// Lagged(_) => debug!("Lagged"),
|
||||||
|
// Message(msg) => debug!("Got message: {msg:?}"),
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_hotspot_enable_ids() -> Vec<TallyID> {
|
async fn wait_for_stack_up(stack: Stack<'static>) {
|
||||||
let hotspot_ids: Vec<TallyID> = env::var("HOTSPOT_IDS")
|
loop {
|
||||||
.map(|ids| ids.split(";").map(|id| TallyID(id.to_owned())).collect())
|
if stack.is_link_up() {
|
||||||
.unwrap_or_default();
|
break;
|
||||||
|
|
||||||
if hotspot_ids.is_empty() {
|
|
||||||
warn!(
|
|
||||||
"HOTSPOT_IDS is not set or empty. You will not be able to activate the hotspot via a tally!"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
hotspot_ids
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn handle_ids_loop(
|
|
||||||
mut id_channel: Receiver<String>,
|
|
||||||
hotspot_enable_ids: Vec<TallyID>,
|
|
||||||
id_store: Arc<Mutex<IDStore>>,
|
|
||||||
hotspot: Arc<Mutex<impl Hotspot>>,
|
|
||||||
user_feedback: Arc<Mutex<FeedbackImpl>>,
|
|
||||||
) -> Result<()> {
|
|
||||||
while let Ok(tally_id_string) = id_channel.recv().await {
|
|
||||||
let tally_id = TallyID(tally_id_string);
|
|
||||||
|
|
||||||
if hotspot_enable_ids.contains(&tally_id) {
|
|
||||||
info!("Enableing hotspot");
|
|
||||||
let hotspot_enable_result = hotspot.lock().await.enable_hotspot().await;
|
|
||||||
|
|
||||||
match hotspot_enable_result {
|
|
||||||
Ok(_) => {
|
|
||||||
user_feedback
|
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.set_device_status(feedback::DeviceStatus::HotspotEnabled);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error!("Hotspot: {e}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Should the ID be added anyway or ignored ?
|
|
||||||
}
|
}
|
||||||
|
Timer::after(Duration::from_millis(500)).await;
|
||||||
if id_store.lock().await.add_id(tally_id) {
|
if stack.is_config_up() {
|
||||||
info!("Added new id to current day");
|
break;
|
||||||
|
|
||||||
user_feedback.lock().await.success().await;
|
|
||||||
|
|
||||||
if let Err(e) = id_store.lock().await.export_json(STORE_PATH).await {
|
|
||||||
error!("Failed to save id store to file: {e}");
|
|
||||||
user_feedback.lock().await.failure().await;
|
|
||||||
// TODO: How to handle a failure to save ?
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Timer::after(Duration::from_millis(500)).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn enter_error_state(feedback: Arc<Mutex<FeedbackImpl>>, hotspot: Arc<Mutex<impl Hotspot>>) {
|
|
||||||
let _ = feedback.lock().await.activate_error_state().await;
|
|
||||||
let _ = hotspot.lock().await.enable_hotspot().await;
|
|
||||||
|
|
||||||
let mut sigterm = signal(SignalKind::terminate()).unwrap();
|
|
||||||
sigterm.recv().await;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::main]
|
|
||||||
async fn main() -> Result<()> {
|
|
||||||
logger::setup_logger();
|
|
||||||
|
|
||||||
info!("Starting application");
|
|
||||||
|
|
||||||
let user_feedback = Arc::new(Mutex::new(Feedback::new()?));
|
|
||||||
let hotspot = Arc::new(Mutex::new(create_hotspot()?));
|
|
||||||
|
|
||||||
let error_flag_set = args().any(|e| e == "--error" || e == "-e");
|
|
||||||
if error_flag_set {
|
|
||||||
error!("Error flag set. Entering error state");
|
|
||||||
enter_error_state(user_feedback.clone(), hotspot).await;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let store: Arc<Mutex<IDStore>> = Arc::new(Mutex::new(load_or_create_store().await?));
|
|
||||||
let hotspot_enable_ids = get_hotspot_enable_ids();
|
|
||||||
|
|
||||||
let (tx, rx) = broadcast::channel::<String>(32);
|
|
||||||
let sse_tx = tx.clone();
|
|
||||||
|
|
||||||
let pm3_handle = run_pm3(tx);
|
|
||||||
|
|
||||||
user_feedback.lock().await.startup().await;
|
|
||||||
|
|
||||||
let loop_handle = handle_ids_loop(
|
|
||||||
rx,
|
|
||||||
hotspot_enable_ids,
|
|
||||||
store.clone(),
|
|
||||||
hotspot.clone(),
|
|
||||||
user_feedback.clone(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let webserver_handle = run_webserver(
|
|
||||||
store.clone(),
|
|
||||||
sse_tx,
|
|
||||||
hotspot.clone(),
|
|
||||||
user_feedback.clone(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let run_result = try_join!(pm3_handle, loop_handle, webserver_handle);
|
|
||||||
|
|
||||||
if let Err(e) = run_result {
|
|
||||||
error!("Failed to run application: {e}");
|
|
||||||
return Err(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
mod runner;
|
|
||||||
mod parser;
|
|
||||||
|
|
||||||
pub use runner::run_pm3;
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
use regex::Regex;
|
|
||||||
|
|
||||||
/// Parses the output of PM3 finds the read IDs
|
|
||||||
/// Example input: `[+] UID.... 3112B710`
|
|
||||||
pub fn parse_line(line: &str) -> Option<String> {
|
|
||||||
let regex = Regex::new(r"(?m)^\[\+\] UID.... (.*)$").unwrap();
|
|
||||||
let result = regex.captures(line);
|
|
||||||
|
|
||||||
result.map(|c| c.get(1).unwrap().as_str().to_owned())
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
use anyhow::{Result, anyhow};
|
|
||||||
use log::{debug, info, trace, warn};
|
|
||||||
use std::env;
|
|
||||||
use std::process::Stdio;
|
|
||||||
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
|
|
||||||
use tokio::process::Command;
|
|
||||||
use tokio::select;
|
|
||||||
use tokio::signal::unix::{SignalKind, signal};
|
|
||||||
use tokio::sync::broadcast;
|
|
||||||
|
|
||||||
/// Runs the pm3 binary and monitors it's output
|
|
||||||
/// The pm3 binary is ether set in the env var PM3_BIN or found in the path
|
|
||||||
/// The ouput is parsed and send via the `tx` channel
|
|
||||||
pub async fn run_pm3(tx: broadcast::Sender<String>) -> Result<()> {
|
|
||||||
kill_orphans().await;
|
|
||||||
|
|
||||||
let pm3_path = match env::var("PM3_BIN") {
|
|
||||||
Ok(path) => path,
|
|
||||||
Err(_) => {
|
|
||||||
info!("PM3_BIN not set. Using default value");
|
|
||||||
"pm3".to_owned()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut cmd = Command::new("stdbuf")
|
|
||||||
.arg("-oL")
|
|
||||||
.arg(pm3_path)
|
|
||||||
.arg("-c")
|
|
||||||
.arg("lf hitag reader -@")
|
|
||||||
.stdout(Stdio::piped())
|
|
||||||
.stderr(Stdio::null())
|
|
||||||
.stdin(Stdio::piped())
|
|
||||||
.spawn()?;
|
|
||||||
|
|
||||||
let stdout = cmd.stdout.take().ok_or(anyhow!("Failed to get stdout"))?;
|
|
||||||
let mut stdin = cmd.stdin.take().ok_or(anyhow!("Failed to get stdin"))?;
|
|
||||||
|
|
||||||
let mut reader = BufReader::new(stdout).lines();
|
|
||||||
|
|
||||||
let mut sigterm = signal(SignalKind::terminate())?;
|
|
||||||
|
|
||||||
let child_handle = tokio::spawn(async move {
|
|
||||||
let mut last_id: String = "".to_owned();
|
|
||||||
while let Some(line) = reader.next_line().await.unwrap_or(None) {
|
|
||||||
trace!("PM3: {line}");
|
|
||||||
if let Some(uid) = super::parser::parse_line(&line) {
|
|
||||||
if last_id == uid {
|
|
||||||
let _ = tx.send(uid.clone());
|
|
||||||
}
|
|
||||||
last_id = uid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
select! {
|
|
||||||
_ = child_handle => {}
|
|
||||||
_ = sigterm.recv() => {
|
|
||||||
debug!("Graceful shutdown of PM3");
|
|
||||||
let _ = stdin.write_all(b"\n").await;
|
|
||||||
let _ = stdin.flush().await;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let status = cmd.wait().await?;
|
|
||||||
|
|
||||||
// We use the exit code here because status.success() is false if the child was terminated by a
|
|
||||||
// signal
|
|
||||||
let code = status.code().unwrap_or(0);
|
|
||||||
|
|
||||||
if code == 0 {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(anyhow!("PM3 exited with a non-zero exit code: {code}"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Kills any open pm3 instances
|
|
||||||
/// Also funny name. hehehe.
|
|
||||||
async fn kill_orphans() {
|
|
||||||
let kill_result = Command::new("pkill")
|
|
||||||
.arg("-KILL")
|
|
||||||
.arg("-x")
|
|
||||||
.arg("proxmark3")
|
|
||||||
.output()
|
|
||||||
.await;
|
|
||||||
|
|
||||||
match kill_result {
|
|
||||||
Ok(_) => {
|
|
||||||
debug!("Successfully killed orphaned pm3 instances");
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
warn!("Failed to kill pm3 orphans: {e} Continuing anyway");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +1,23 @@
|
|||||||
use crate::tally_id::TallyID;
|
use super::TallyID;
|
||||||
use serde::{Deserialize, Serialize};
|
use alloc::collections::BTreeMap;
|
||||||
use std::collections::HashMap;
|
use alloc::string::String;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Clone)]
|
#[derive(Clone, Serialize)]
|
||||||
pub struct Name {
|
pub struct Name {
|
||||||
pub first: String,
|
pub first: String,
|
||||||
pub last: String,
|
pub last: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Clone)]
|
#[derive(Clone, Serialize)]
|
||||||
pub struct IDMapping {
|
pub struct IDMapping {
|
||||||
id_map: HashMap<TallyID, Name>,
|
id_map: BTreeMap<TallyID, Name>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IDMapping {
|
impl IDMapping {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
IDMapping {
|
IDMapping {
|
||||||
id_map: HashMap::new(),
|
id_map: BTreeMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,49 +29,3 @@ impl IDMapping {
|
|||||||
self.id_map.insert(id, name);
|
self.id_map.insert(id, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn basic() {
|
|
||||||
let mut map = IDMapping::new();
|
|
||||||
let id1 = TallyID("A2Fb44".to_owned());
|
|
||||||
let name1 = Name {
|
|
||||||
first: "Max".to_owned(),
|
|
||||||
last: "Mustermann".to_owned(),
|
|
||||||
};
|
|
||||||
|
|
||||||
map.add_mapping(id1.clone(), name1.clone());
|
|
||||||
|
|
||||||
let res = map.map(&id1);
|
|
||||||
|
|
||||||
assert_eq!(res, Some(&name1));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn multiple() {
|
|
||||||
let mut map = IDMapping::new();
|
|
||||||
let id1 = TallyID("A2Fb44".to_owned());
|
|
||||||
let name1 = Name {
|
|
||||||
first: "Max".to_owned(),
|
|
||||||
last: "Mustermann".to_owned(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let id2 = TallyID("7D3DF5B5".to_owned());
|
|
||||||
let name2 = Name {
|
|
||||||
first: "First".to_owned(),
|
|
||||||
last: "Last".to_owned(),
|
|
||||||
};
|
|
||||||
|
|
||||||
map.add_mapping(id1.clone(), name1.clone());
|
|
||||||
map.add_mapping(id2.clone(), name2.clone());
|
|
||||||
|
|
||||||
let res = map.map(&id1);
|
|
||||||
assert_eq!(res, Some(&name1));
|
|
||||||
|
|
||||||
let res = map.map(&id2);
|
|
||||||
assert_eq!(res, Some(&name2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,123 +1,19 @@
|
|||||||
use anyhow::{Result, anyhow};
|
use super::Date;
|
||||||
use serde::{Deserialize, Serialize};
|
use super::IDMapping;
|
||||||
use std::collections::{HashMap, HashSet};
|
use super::TallyID;
|
||||||
use tokio::fs;
|
use alloc::collections::BTreeMap;
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
use crate::{store::IDMapping, tally_id::TallyID};
|
#[derive(Clone)]
|
||||||
|
|
||||||
/// Represents a single day that IDs can attend
|
|
||||||
#[derive(Deserialize, Serialize)]
|
|
||||||
pub struct AttendanceDay {
|
pub struct AttendanceDay {
|
||||||
date: String,
|
date: Date,
|
||||||
ids: Vec<TallyID>,
|
ids: Vec<TallyID>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stores all the days
|
|
||||||
#[derive(Deserialize, Serialize)]
|
|
||||||
pub struct IDStore {
|
|
||||||
days: HashMap<String, AttendanceDay>,
|
|
||||||
pub mapping: IDMapping,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IDStore {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
IDStore {
|
|
||||||
days: HashMap::new(),
|
|
||||||
mapping: IDMapping::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creats a new `IDStore` from a json file
|
|
||||||
pub async fn new_from_json(filepath: &str) -> Result<Self> {
|
|
||||||
let read_string = fs::read_to_string(filepath).await?;
|
|
||||||
Ok(serde_json::from_str(&read_string)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add a new id for the current day
|
|
||||||
/// Returns false if ID is already present at the current day.
|
|
||||||
pub fn add_id(&mut self, id: TallyID) -> bool {
|
|
||||||
self.get_current_day().add_id(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the `AttendanceDay` of the current day
|
|
||||||
/// Creates a new if not exists
|
|
||||||
pub fn get_current_day(&mut self) -> &mut AttendanceDay {
|
|
||||||
let current_day = get_day_str();
|
|
||||||
|
|
||||||
if self.days.contains_key(¤t_day) {
|
|
||||||
return self.days.get_mut(¤t_day).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
self.days.insert(
|
|
||||||
current_day.clone(),
|
|
||||||
AttendanceDay::new(¤t_day.clone()),
|
|
||||||
);
|
|
||||||
|
|
||||||
self.days.get_mut(¤t_day.clone()).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Writes the store to a json file
|
|
||||||
pub async fn export_json(&self, filepath: &str) -> Result<()> {
|
|
||||||
fs::write(filepath, serde_json::to_string(&self)?).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Export the store to a csv file.
|
|
||||||
/// With days in the rows and IDs in the collum.
|
|
||||||
pub fn export_csv(&self) -> Result<String> {
|
|
||||||
let mut csv = String::new();
|
|
||||||
let seperator = ";";
|
|
||||||
let mut user_ids: HashSet<TallyID> = HashSet::new();
|
|
||||||
|
|
||||||
for day in self.days.values() {
|
|
||||||
for id in day.ids.iter() {
|
|
||||||
user_ids.insert(id.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut user_ids: Vec<TallyID> = user_ids.into_iter().collect();
|
|
||||||
user_ids.sort();
|
|
||||||
|
|
||||||
let mut days: Vec<String> = self.days.keys().cloned().collect();
|
|
||||||
days.sort();
|
|
||||||
|
|
||||||
let header = days.join(seperator);
|
|
||||||
csv.push_str(&format!(
|
|
||||||
"ID{seperator}Nachname{seperator}Vorname{seperator}{header}\n"
|
|
||||||
));
|
|
||||||
|
|
||||||
for user_id in user_ids.iter() {
|
|
||||||
let id = &user_id.0.to_string();
|
|
||||||
let name = self.mapping.map(user_id);
|
|
||||||
|
|
||||||
let firstname = name.map(|e| e.first.clone()).unwrap_or("".to_owned());
|
|
||||||
let lastname = name.map(|e| e.last.clone()).unwrap_or("".to_owned());
|
|
||||||
|
|
||||||
csv.push_str(&format!("{id}{seperator}{lastname}{seperator}{firstname}"));
|
|
||||||
for day in days.iter() {
|
|
||||||
let was_there: bool = self
|
|
||||||
.days
|
|
||||||
.get(day)
|
|
||||||
.ok_or(anyhow!("Failed to access day"))?
|
|
||||||
.ids
|
|
||||||
.contains(user_id);
|
|
||||||
|
|
||||||
if was_there {
|
|
||||||
csv.push_str(&format!("{seperator}x"));
|
|
||||||
} else {
|
|
||||||
csv.push_str(seperator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
csv.push('\n');
|
|
||||||
}
|
|
||||||
Ok(csv)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AttendanceDay {
|
impl AttendanceDay {
|
||||||
fn new(day: &str) -> Self {
|
fn new(date: Date) -> Self {
|
||||||
Self {
|
Self {
|
||||||
date: day.to_owned(),
|
date,
|
||||||
ids: Vec::new(),
|
ids: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,7 +29,43 @@ impl AttendanceDay {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_day_str() -> String {
|
#[derive(Clone)]
|
||||||
let now = chrono::offset::Local::now();
|
pub struct IDStore {
|
||||||
now.format("%Y-%m-%d").to_string()
|
pub days: BTreeMap<Date, AttendanceDay>,
|
||||||
|
pub mapping: IDMapping,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IDStore {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
IDStore {
|
||||||
|
days: BTreeMap::new(),
|
||||||
|
mapping: IDMapping::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_from_storage() -> Self {
|
||||||
|
// TODO: implement
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a new id for the current day
|
||||||
|
/// Returns false if ID is already present at the current day.
|
||||||
|
pub fn add_id(&mut self, id: TallyID) -> bool {
|
||||||
|
self.get_current_day().add_id(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the `AttendanceDay` of the current day
|
||||||
|
/// Creates a new if not exists
|
||||||
|
pub fn get_current_day(&mut self) -> &mut AttendanceDay {
|
||||||
|
let current_day: Date = 1;
|
||||||
|
|
||||||
|
if self.days.contains_key(¤t_day) {
|
||||||
|
return self.days.get_mut(¤t_day).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.days
|
||||||
|
.insert(current_day, AttendanceDay::new(current_day));
|
||||||
|
|
||||||
|
self.days.get_mut(¤t_day.clone()).unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user