kopia lustrzana https://github.com/sh123/esp32_loraprs
Porównaj commity
13 Commity
Autor | SHA1 | Data |
---|---|---|
![]() |
c09422dab9 | |
![]() |
f0d7caa6f2 | |
![]() |
12c194b919 | |
![]() |
f48def5cab | |
![]() |
5ca3bf0e9e | |
![]() |
8a6427f088 | |
![]() |
e78e0e8513 | |
![]() |
cf99eb014d | |
![]() |
b89a13680e | |
![]() |
0a43429b1c | |
![]() |
2083f946d9 | |
![]() |
3e90abd47f | |
![]() |
127ccbe072 |
|
@ -4,4 +4,3 @@
|
||||||
*.sch-bak
|
*.sch-bak
|
||||||
*.kicad_pcb-bak
|
*.kicad_pcb-bak
|
||||||
fp-info-cache
|
fp-info-cache
|
||||||
*-cache.lib
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# ESP32 LoRa APRS Modem
|
# ESP32 LoRa APRS Modem
|
||||||

|

|
||||||
|
|
||||||
This project is amateur radio ESP32 based LoRa **KISS Bluetooth/BLE/USB/TCPIP** modem + LoRa **APRS-IS RX/TX iGate** server over WiFI + LoRa **APRS digipeater** + **Codec2 DV modem** (with Codec2 Talkie Android application).
|
This project is amateur radio ESP32 based LoRa/FSK **KISS Bluetooth/BLE/USB/TCPIP** modem + LoRa **APRS-IS RX/TX iGate** server over WiFI + LoRa/FSK **APRS digipeater** + **Codec2 DV modem** (with Codec2 Talkie Android application).
|
||||||
|
|
||||||
⚠ **To configure sketch modify default parameters in config.h file.**
|
⚠ **To configure sketch modify default parameters in config.h file.**
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
- `antenna_base` - base for rubber duck antenna, to be printed with PETG filament.
|
- `antenna_base` - base for rubber duck antenna, to be printed with PETG filament.
|
||||||
- `antenna_cover` - cover for rubber duck antenna, to printed with TPU filament.
|
- `antenna_cover` - cover for rubber duck antenna, to printed with TPU filament.
|
||||||
|
|
||||||
👉 Rubber duck antenna spiral widing was done with 1.3mm copper wire on 8mm aluminium scaffolding tube.
|
👉 Rubber duck antenna spiral widing was done with 1.3mm copper wire on 8mm aluminium scaffolding tube, ~8 turns with 6mm step
|
||||||
|
|
||||||
**Tracker case**:
|
**Tracker case**:
|
||||||
- `aprs_tracker_e22_base` - base for tracker case without battery compartment.
|
- `aprs_tracker_e22_base` - base for tracker case without battery compartment.
|
||||||
|
|
|
@ -0,0 +1,352 @@
|
||||||
|
EESchema-LIBRARY Version 2.4
|
||||||
|
#encoding utf-8
|
||||||
|
#
|
||||||
|
# Connector_Conn_01x03_Female
|
||||||
|
#
|
||||||
|
DEF Connector_Conn_01x03_Female J 0 40 Y N 1 F N
|
||||||
|
F0 "J" 0 200 50 H V C CNN
|
||||||
|
F1 "Connector_Conn_01x03_Female" 0 -200 50 H V C CNN
|
||||||
|
F2 "" 0 0 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
$FPLIST
|
||||||
|
Connector*:*_1x??_*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
A 0 -100 20 901 -901 1 1 6 N 0 -80 0 -120
|
||||||
|
A 0 0 20 901 -901 1 1 6 N 0 20 0 -20
|
||||||
|
A 0 100 20 901 -901 1 1 6 N 0 120 0 80
|
||||||
|
P 2 1 1 6 -50 -100 -20 -100 N
|
||||||
|
P 2 1 1 6 -50 0 -20 0 N
|
||||||
|
P 2 1 1 6 -50 100 -20 100 N
|
||||||
|
X Pin_1 1 -200 100 150 R 50 50 1 1 P
|
||||||
|
X Pin_2 2 -200 0 150 R 50 50 1 1 P
|
||||||
|
X Pin_3 3 -200 -100 150 R 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Connector_Conn_01x10_Female
|
||||||
|
#
|
||||||
|
DEF Connector_Conn_01x10_Female J 0 40 Y N 1 F N
|
||||||
|
F0 "J" 0 500 50 H V C CNN
|
||||||
|
F1 "Connector_Conn_01x10_Female" 0 -600 50 H V C CNN
|
||||||
|
F2 "" 0 0 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
$FPLIST
|
||||||
|
Connector*:*_1x??_*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
A 0 -500 20 901 -901 1 1 6 N 0 -480 0 -520
|
||||||
|
A 0 -400 20 901 -901 1 1 6 N 0 -380 0 -420
|
||||||
|
A 0 -300 20 901 -901 1 1 6 N 0 -280 0 -320
|
||||||
|
A 0 -200 20 901 -901 1 1 6 N 0 -180 0 -220
|
||||||
|
A 0 -100 20 901 -901 1 1 6 N 0 -80 0 -120
|
||||||
|
A 0 0 20 901 -901 1 1 6 N 0 20 0 -20
|
||||||
|
A 0 100 20 901 -901 1 1 6 N 0 120 0 80
|
||||||
|
A 0 200 20 901 -901 1 1 6 N 0 220 0 180
|
||||||
|
A 0 300 20 901 -901 1 1 6 N 0 320 0 280
|
||||||
|
A 0 400 20 901 -901 1 1 6 N 0 420 0 380
|
||||||
|
P 2 1 1 6 -50 -500 -20 -500 N
|
||||||
|
P 2 1 1 6 -50 -400 -20 -400 N
|
||||||
|
P 2 1 1 6 -50 -300 -20 -300 N
|
||||||
|
P 2 1 1 6 -50 -200 -20 -200 N
|
||||||
|
P 2 1 1 6 -50 -100 -20 -100 N
|
||||||
|
P 2 1 1 6 -50 0 -20 0 N
|
||||||
|
P 2 1 1 6 -50 100 -20 100 N
|
||||||
|
P 2 1 1 6 -50 200 -20 200 N
|
||||||
|
P 2 1 1 6 -50 300 -20 300 N
|
||||||
|
P 2 1 1 6 -50 400 -20 400 N
|
||||||
|
X Pin_1 1 -200 400 150 R 50 50 1 1 P
|
||||||
|
X Pin_10 10 -200 -500 150 R 50 50 1 1 P
|
||||||
|
X Pin_2 2 -200 300 150 R 50 50 1 1 P
|
||||||
|
X Pin_3 3 -200 200 150 R 50 50 1 1 P
|
||||||
|
X Pin_4 4 -200 100 150 R 50 50 1 1 P
|
||||||
|
X Pin_5 5 -200 0 150 R 50 50 1 1 P
|
||||||
|
X Pin_6 6 -200 -100 150 R 50 50 1 1 P
|
||||||
|
X Pin_7 7 -200 -200 150 R 50 50 1 1 P
|
||||||
|
X Pin_8 8 -200 -300 150 R 50 50 1 1 P
|
||||||
|
X Pin_9 9 -200 -400 150 R 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Connector_Conn_01x12_Female
|
||||||
|
#
|
||||||
|
DEF Connector_Conn_01x12_Female J 0 40 Y N 1 F N
|
||||||
|
F0 "J" 0 600 50 H V C CNN
|
||||||
|
F1 "Connector_Conn_01x12_Female" 0 -700 50 H V C CNN
|
||||||
|
F2 "" 0 0 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
$FPLIST
|
||||||
|
Connector*:*_1x??_*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
A 0 -600 20 901 -901 1 1 6 N 0 -580 0 -620
|
||||||
|
A 0 -500 20 901 -901 1 1 6 N 0 -480 0 -520
|
||||||
|
A 0 -400 20 901 -901 1 1 6 N 0 -380 0 -420
|
||||||
|
A 0 -300 20 901 -901 1 1 6 N 0 -280 0 -320
|
||||||
|
A 0 -200 20 901 -901 1 1 6 N 0 -180 0 -220
|
||||||
|
A 0 -100 20 901 -901 1 1 6 N 0 -80 0 -120
|
||||||
|
A 0 0 20 901 -901 1 1 6 N 0 20 0 -20
|
||||||
|
A 0 100 20 901 -901 1 1 6 N 0 120 0 80
|
||||||
|
A 0 200 20 901 -901 1 1 6 N 0 220 0 180
|
||||||
|
A 0 300 20 901 -901 1 1 6 N 0 320 0 280
|
||||||
|
A 0 400 20 901 -901 1 1 6 N 0 420 0 380
|
||||||
|
A 0 500 20 901 -901 1 1 6 N 0 520 0 480
|
||||||
|
P 2 1 1 6 -50 -600 -20 -600 N
|
||||||
|
P 2 1 1 6 -50 -500 -20 -500 N
|
||||||
|
P 2 1 1 6 -50 -400 -20 -400 N
|
||||||
|
P 2 1 1 6 -50 -300 -20 -300 N
|
||||||
|
P 2 1 1 6 -50 -200 -20 -200 N
|
||||||
|
P 2 1 1 6 -50 -100 -20 -100 N
|
||||||
|
P 2 1 1 6 -50 0 -20 0 N
|
||||||
|
P 2 1 1 6 -50 100 -20 100 N
|
||||||
|
P 2 1 1 6 -50 200 -20 200 N
|
||||||
|
P 2 1 1 6 -50 300 -20 300 N
|
||||||
|
P 2 1 1 6 -50 400 -20 400 N
|
||||||
|
P 2 1 1 6 -50 500 -20 500 N
|
||||||
|
X Pin_1 1 -200 500 150 R 50 50 1 1 P
|
||||||
|
X Pin_10 10 -200 -400 150 R 50 50 1 1 P
|
||||||
|
X Pin_11 11 -200 -500 150 R 50 50 1 1 P
|
||||||
|
X Pin_12 12 -200 -600 150 R 50 50 1 1 P
|
||||||
|
X Pin_2 2 -200 400 150 R 50 50 1 1 P
|
||||||
|
X Pin_3 3 -200 300 150 R 50 50 1 1 P
|
||||||
|
X Pin_4 4 -200 200 150 R 50 50 1 1 P
|
||||||
|
X Pin_5 5 -200 100 150 R 50 50 1 1 P
|
||||||
|
X Pin_6 6 -200 0 150 R 50 50 1 1 P
|
||||||
|
X Pin_7 7 -200 -100 150 R 50 50 1 1 P
|
||||||
|
X Pin_8 8 -200 -200 150 R 50 50 1 1 P
|
||||||
|
X Pin_9 9 -200 -300 150 R 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Connector_Conn_Coaxial
|
||||||
|
#
|
||||||
|
DEF Connector_Conn_Coaxial J 0 40 Y N 1 F N
|
||||||
|
F0 "J" 10 120 50 H V C CNN
|
||||||
|
F1 "Connector_Conn_Coaxial" 115 0 50 V V C CNN
|
||||||
|
F2 "" 0 0 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
$FPLIST
|
||||||
|
*BNC*
|
||||||
|
*SMA*
|
||||||
|
*SMB*
|
||||||
|
*SMC*
|
||||||
|
*Cinch*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
A -2 0 71 1636 0 0 1 10 N -70 20 70 0
|
||||||
|
A -1 0 71 0 -1638 0 1 10 N 70 0 -70 -20
|
||||||
|
C 0 0 20 0 1 8 N
|
||||||
|
P 2 0 1 0 -100 0 -20 0 N
|
||||||
|
P 2 0 1 0 0 -100 0 -70 N
|
||||||
|
X In 1 -200 0 100 R 50 50 1 1 P
|
||||||
|
X Ext 2 0 -200 100 U 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Device_C
|
||||||
|
#
|
||||||
|
DEF Device_C C 0 10 N Y 1 F N
|
||||||
|
F0 "C" 25 100 50 H V L CNN
|
||||||
|
F1 "Device_C" 25 -100 50 H V L CNN
|
||||||
|
F2 "" 38 -150 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
$FPLIST
|
||||||
|
C_*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
P 2 0 1 20 -80 -30 80 -30 N
|
||||||
|
P 2 0 1 20 -80 30 80 30 N
|
||||||
|
X ~ 1 0 150 110 D 50 50 1 1 P
|
||||||
|
X ~ 2 0 -150 110 U 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Device_CP1
|
||||||
|
#
|
||||||
|
DEF Device_CP1 C 0 10 N N 1 F N
|
||||||
|
F0 "C" 25 100 50 H V L CNN
|
||||||
|
F1 "Device_CP1" 25 -100 50 H V L CNN
|
||||||
|
F2 "" 0 0 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
$FPLIST
|
||||||
|
CP_*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
A 0 -150 128 1287 513 0 1 20 N -80 -50 80 -50
|
||||||
|
P 2 0 1 20 -80 30 80 30 N
|
||||||
|
P 2 0 1 0 -70 90 -30 90 N
|
||||||
|
P 2 0 1 0 -50 70 -50 110 N
|
||||||
|
X ~ 1 0 150 110 D 50 50 1 1 P
|
||||||
|
X ~ 2 0 -150 130 U 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Jumper_SolderJumper_2_Open
|
||||||
|
#
|
||||||
|
DEF Jumper_SolderJumper_2_Open JP 0 0 Y N 1 F N
|
||||||
|
F0 "JP" 0 80 50 H V C CNN
|
||||||
|
F1 "Jumper_SolderJumper_2_Open" 0 -100 50 H V C CNN
|
||||||
|
F2 "" 0 0 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
$FPLIST
|
||||||
|
SolderJumper*Open*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
A -10 0 40 901 -901 0 1 0 N -10 40 -10 -40
|
||||||
|
A -10 0 40 901 -901 0 1 0 F -10 40 -10 -40
|
||||||
|
A 10 0 40 -899 899 0 1 0 N 10 -40 10 40
|
||||||
|
A 10 0 40 -899 899 0 1 0 F 10 -40 10 40
|
||||||
|
P 2 0 1 0 -10 40 -10 -40 N
|
||||||
|
P 2 0 1 0 10 40 10 -40 N
|
||||||
|
X A 1 -150 0 100 R 50 50 1 1 P
|
||||||
|
X B 2 150 0 100 L 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Jumper_SolderJumper_3_Open
|
||||||
|
#
|
||||||
|
DEF Jumper_SolderJumper_3_Open JP 0 0 Y N 1 F N
|
||||||
|
F0 "JP" -100 -100 50 H V C CNN
|
||||||
|
F1 "Jumper_SolderJumper_3_Open" 0 110 50 H V C CNN
|
||||||
|
F2 "" 0 0 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
$FPLIST
|
||||||
|
SolderJumper*Open*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
A -40 0 40 901 -901 0 1 0 N -40 40 -40 -40
|
||||||
|
A -40 0 40 901 -901 0 1 0 F -40 40 -40 -40
|
||||||
|
A 40 0 40 -899 899 0 1 0 N 40 -40 40 40
|
||||||
|
A 40 0 40 -899 899 0 1 0 F 40 -40 40 40
|
||||||
|
S -20 40 20 -40 0 1 0 F
|
||||||
|
P 2 0 1 0 -100 0 -80 0 N
|
||||||
|
P 2 0 1 0 -40 40 -40 -40 N
|
||||||
|
P 2 0 1 0 0 -50 0 -40 N
|
||||||
|
P 2 0 1 0 40 40 40 -40 N
|
||||||
|
P 2 0 1 0 100 0 80 0 N
|
||||||
|
X A 1 -200 0 100 R 50 50 1 1 P
|
||||||
|
X C 2 0 -150 100 U 50 50 1 1 I
|
||||||
|
X B 3 200 0 100 L 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# RF_Module_Ai-Thinker-Ra-01
|
||||||
|
#
|
||||||
|
DEF RF_Module_Ai-Thinker-Ra-01 U 0 40 Y Y 1 F N
|
||||||
|
F0 "U" 100 700 50 H V C CNN
|
||||||
|
F1 "RF_Module_Ai-Thinker-Ra-01" 400 -550 50 H V C CNN
|
||||||
|
F2 "RF_Module:Ai-Thinker-Ra-01-LoRa" 1000 -400 50 H I C CNN
|
||||||
|
F3 "" 100 700 50 H I C CNN
|
||||||
|
$FPLIST
|
||||||
|
Ai?Thinker?Ra?01*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
S -300 600 300 -500 0 1 10 f
|
||||||
|
X Ant 1 -500 500 200 R 50 50 1 1 I
|
||||||
|
X DIO4 10 500 0 200 L 50 50 1 1 B
|
||||||
|
X DIO5 11 500 -100 200 L 50 50 1 1 B
|
||||||
|
X SCK 12 -500 0 200 R 50 50 1 1 B
|
||||||
|
X MISO 13 -500 -100 200 R 50 50 1 1 O
|
||||||
|
X MOSI 14 -500 -200 200 R 50 50 1 1 I
|
||||||
|
X ~SS 15 -500 100 200 R 50 50 1 1 I
|
||||||
|
X Gnd 16 0 -700 200 U 50 50 1 1 P N
|
||||||
|
X Gnd 2 0 -700 200 U 50 50 1 1 W
|
||||||
|
X 3v3 3 0 800 200 D 50 50 1 1 W
|
||||||
|
X ~Reset 4 -500 300 200 R 50 50 1 1 I
|
||||||
|
X DIO0 5 500 400 200 L 50 50 1 1 B
|
||||||
|
X DIO1 6 500 300 200 L 50 50 1 1 B
|
||||||
|
X DIO2 7 500 200 200 L 50 50 1 1 B
|
||||||
|
X DIO3 8 500 100 200 L 50 50 1 1 B
|
||||||
|
X Gnd 9 0 -700 200 U 50 50 1 1 P N
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# lora_tracker_E22-400M30S
|
||||||
|
#
|
||||||
|
DEF lora_tracker_E22-400M30S U 0 40 Y Y 1 L N
|
||||||
|
F0 "U" -800 1300 85 H V L BNN
|
||||||
|
F1 "lora_tracker_E22-400M30S" 0 0 50 H I C CNN
|
||||||
|
F2 "" 0 0 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
DRAW
|
||||||
|
T 0 0 500 85 0 1 0 E22-400M30S Normal 0 C C
|
||||||
|
P 2 1 0 0 -800 -1200 800 -1200 N
|
||||||
|
P 2 1 0 0 -800 1200 -800 -1200 N
|
||||||
|
P 2 1 0 0 800 -1200 800 1200 N
|
||||||
|
P 2 1 0 0 800 1200 -800 1200 N
|
||||||
|
X GND@1 1 -1000 1100 200 R 0 50 1 0 B
|
||||||
|
X VCC@2 10 -1000 -900 200 R 0 50 1 0 B
|
||||||
|
X GND@6 11 -1000 -1100 200 R 0 50 1 0 B
|
||||||
|
X GND@7 12 1000 -1100 200 L 0 50 1 0 B
|
||||||
|
X DIO1 13 1000 -900 200 L 0 50 1 0 B
|
||||||
|
X BUSY 14 1000 -700 200 L 0 50 1 0 B
|
||||||
|
X NRST 15 1000 -500 200 L 0 50 1 0 B
|
||||||
|
X MISO 16 1000 -300 200 L 0 50 1 0 B
|
||||||
|
X MOSI 17 1000 -100 200 L 0 50 1 0 B
|
||||||
|
X SCK 18 1000 100 200 L 0 50 1 0 B
|
||||||
|
X NSS 19 1000 300 200 L 0 50 1 0 B
|
||||||
|
X GND@2 2 -1000 900 200 R 0 50 1 0 B
|
||||||
|
X GND@8 20 1000 700 200 L 0 50 1 0 B
|
||||||
|
X ANT 21 1000 900 200 L 0 50 1 0 B
|
||||||
|
X GND@9 22 1000 1100 200 L 0 50 1 0 B
|
||||||
|
X GND@3 3 -1000 700 200 R 0 50 1 0 B
|
||||||
|
X GND@4 4 -1000 300 200 R 0 50 1 0 B
|
||||||
|
X GND@5 5 -1000 100 200 R 0 50 1 0 B
|
||||||
|
X RXEN 6 -1000 -100 200 R 0 50 1 0 B
|
||||||
|
X TXEN 7 -1000 -300 200 R 0 50 1 0 B
|
||||||
|
X DIO2 8 -1000 -500 200 R 0 50 1 0 B
|
||||||
|
X VCC@1 9 -1000 -700 200 R 0 50 1 0 B
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# lora_tracker_ESP32
|
||||||
|
#
|
||||||
|
DEF lora_tracker_ESP32 U 0 40 Y Y 1 F N
|
||||||
|
F0 "U" 50 150 50 H V C CNN
|
||||||
|
F1 "lora_tracker_ESP32" 50 50 50 H V C CNN
|
||||||
|
F2 "" 50 150 50 H I C CNN
|
||||||
|
F3 "" 50 150 50 H I C CNN
|
||||||
|
DRAW
|
||||||
|
S -300 0 450 -2000 0 1 0 N
|
||||||
|
X +3V3 1 -400 -100 100 R 50 50 1 1 I
|
||||||
|
X GPIO26 10 -400 -1000 100 R 50 50 1 1 I
|
||||||
|
X GPIO27 11 -400 -1100 100 R 50 50 1 1 I
|
||||||
|
X GPIO14 12 -400 -1200 100 R 50 50 1 1 I
|
||||||
|
X GPIO12 13 -400 -1300 100 R 50 50 1 1 I
|
||||||
|
X GND 14 -400 -1400 100 R 50 50 1 1 I
|
||||||
|
X GPIO13 15 -400 -1500 100 R 50 50 1 1 I
|
||||||
|
X GPIO9 16 -400 -1600 100 R 50 50 1 1 I
|
||||||
|
X GPIO10 17 -400 -1700 100 R 50 50 1 1 I
|
||||||
|
X GPIO11 18 -400 -1800 100 R 50 50 1 1 I
|
||||||
|
X VIN 19 -400 -1900 100 R 50 50 1 1 I
|
||||||
|
X EN 2 -400 -200 100 R 50 50 1 1 I
|
||||||
|
X GPIO6 20 550 -1900 100 L 50 50 1 1 I
|
||||||
|
X GPIO7 21 550 -1800 100 L 50 50 1 1 I
|
||||||
|
X GPIO8 22 550 -1700 100 L 50 50 1 1 I
|
||||||
|
X GPIO15 23 550 -1600 100 L 50 50 1 1 I
|
||||||
|
X GPIO2 24 550 -1500 100 L 50 50 1 1 I
|
||||||
|
X GPIO0 25 550 -1400 100 L 50 50 1 1 I
|
||||||
|
X GPIO4 26 550 -1300 100 L 50 50 1 1 I
|
||||||
|
X GPIO16 27 550 -1200 100 L 50 50 1 1 I
|
||||||
|
X GPIO17 28 550 -1100 100 L 50 50 1 1 I
|
||||||
|
X GPIO5 29 550 -1000 100 L 50 50 1 1 I
|
||||||
|
X GPIO36 3 -400 -300 100 R 50 50 1 1 I
|
||||||
|
X GPIO18 30 550 -900 100 L 50 50 1 1 I
|
||||||
|
X GPIO19 31 550 -800 100 L 50 50 1 1 I
|
||||||
|
X GND 32 550 -700 100 L 50 50 1 1 I
|
||||||
|
X GPIO21 33 550 -600 100 L 50 50 1 1 I
|
||||||
|
X GPIO3 34 550 -500 100 L 50 50 1 1 I
|
||||||
|
X GPIO1 35 550 -400 100 L 50 50 1 1 I
|
||||||
|
X GPIO22 36 550 -300 100 L 50 50 1 1 I
|
||||||
|
X GPIO23 37 550 -200 100 L 50 50 1 1 I
|
||||||
|
X GND 38 550 -100 100 L 50 50 1 1 I
|
||||||
|
X GPIO39 4 -400 -400 100 R 50 50 1 1 I
|
||||||
|
X GPIO34 5 -400 -500 100 R 50 50 1 1 I
|
||||||
|
X GPIO35 6 -400 -600 100 R 50 50 1 1 I
|
||||||
|
X GPIO32 7 -400 -700 100 R 50 50 1 1 I
|
||||||
|
X GPIO33 8 -400 -800 100 R 50 50 1 1 I
|
||||||
|
X GPIO25 9 -400 -900 100 R 50 50 1 1 I
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
#End Library
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,75 @@
|
||||||
|
{
|
||||||
|
"board": {
|
||||||
|
"active_layer": 0,
|
||||||
|
"active_layer_preset": "All Layers",
|
||||||
|
"auto_track_width": true,
|
||||||
|
"hidden_nets": [],
|
||||||
|
"high_contrast_mode": 0,
|
||||||
|
"net_color_mode": 1,
|
||||||
|
"opacity": {
|
||||||
|
"pads": 1.0,
|
||||||
|
"tracks": 1.0,
|
||||||
|
"vias": 1.0,
|
||||||
|
"zones": 0.6
|
||||||
|
},
|
||||||
|
"ratsnest_display_mode": 0,
|
||||||
|
"selection_filter": {
|
||||||
|
"dimensions": true,
|
||||||
|
"footprints": true,
|
||||||
|
"graphics": true,
|
||||||
|
"keepouts": true,
|
||||||
|
"lockedItems": true,
|
||||||
|
"otherItems": true,
|
||||||
|
"pads": true,
|
||||||
|
"text": true,
|
||||||
|
"tracks": true,
|
||||||
|
"vias": true,
|
||||||
|
"zones": true
|
||||||
|
},
|
||||||
|
"visible_items": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
8,
|
||||||
|
9,
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
19,
|
||||||
|
20,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
23,
|
||||||
|
24,
|
||||||
|
25,
|
||||||
|
26,
|
||||||
|
27,
|
||||||
|
28,
|
||||||
|
29,
|
||||||
|
30,
|
||||||
|
32,
|
||||||
|
33,
|
||||||
|
34,
|
||||||
|
35,
|
||||||
|
36
|
||||||
|
],
|
||||||
|
"visible_layers": "fffffff_ffffffff",
|
||||||
|
"zone_display_mode": 0
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"filename": "lora_tracker.kicad_prl",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"project": {
|
||||||
|
"files": []
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,419 @@
|
||||||
|
{
|
||||||
|
"board": {
|
||||||
|
"design_settings": {
|
||||||
|
"defaults": {
|
||||||
|
"board_outline_line_width": 0.15,
|
||||||
|
"copper_line_width": 0.19999999999999998,
|
||||||
|
"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.049999999999999996,
|
||||||
|
"dimension_precision": 4,
|
||||||
|
"dimension_units": 3,
|
||||||
|
"dimensions": {
|
||||||
|
"arrow_length": 1270000,
|
||||||
|
"extension_offset": 500000,
|
||||||
|
"keep_text_aligned": true,
|
||||||
|
"suppress_zeroes": false,
|
||||||
|
"text_position": 0,
|
||||||
|
"units_format": 1
|
||||||
|
},
|
||||||
|
"fab_line_width": 0.09999999999999999,
|
||||||
|
"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.09999999999999999,
|
||||||
|
"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.762,
|
||||||
|
"height": 1.524,
|
||||||
|
"width": 1.524
|
||||||
|
},
|
||||||
|
"silk_line_width": 0.15,
|
||||||
|
"silk_text_italic": false,
|
||||||
|
"silk_text_size_h": 1.0,
|
||||||
|
"silk_text_size_v": 1.0,
|
||||||
|
"silk_text_thickness": 0.15,
|
||||||
|
"silk_text_upright": false,
|
||||||
|
"zones": {
|
||||||
|
"45_degree_only": false,
|
||||||
|
"min_clearance": 0.508
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"diff_pair_dimensions": [],
|
||||||
|
"drc_exclusions": [],
|
||||||
|
"meta": {
|
||||||
|
"filename": "board_design_settings.json",
|
||||||
|
"version": 2
|
||||||
|
},
|
||||||
|
"rule_severities": {
|
||||||
|
"annular_width": "error",
|
||||||
|
"clearance": "error",
|
||||||
|
"copper_edge_clearance": "error",
|
||||||
|
"courtyards_overlap": "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_type_mismatch": "error",
|
||||||
|
"hole_clearance": "error",
|
||||||
|
"hole_near_hole": "error",
|
||||||
|
"invalid_outline": "error",
|
||||||
|
"item_on_disabled_layer": "error",
|
||||||
|
"items_not_allowed": "error",
|
||||||
|
"length_out_of_range": "error",
|
||||||
|
"malformed_courtyard": "error",
|
||||||
|
"microvia_drill_out_of_range": "error",
|
||||||
|
"missing_courtyard": "ignore",
|
||||||
|
"missing_footprint": "warning",
|
||||||
|
"net_conflict": "warning",
|
||||||
|
"npth_inside_courtyard": "ignore",
|
||||||
|
"padstack": "error",
|
||||||
|
"pth_inside_courtyard": "ignore",
|
||||||
|
"shorting_items": "error",
|
||||||
|
"silk_over_copper": "warning",
|
||||||
|
"silk_overlap": "warning",
|
||||||
|
"skew_out_of_range": "error",
|
||||||
|
"through_hole_pad_without_hole": "error",
|
||||||
|
"too_many_vias": "error",
|
||||||
|
"track_dangling": "warning",
|
||||||
|
"track_width": "error",
|
||||||
|
"tracks_crossing": "error",
|
||||||
|
"unconnected_items": "error",
|
||||||
|
"unresolved_variable": "error",
|
||||||
|
"via_dangling": "warning",
|
||||||
|
"zone_has_empty_net": "error",
|
||||||
|
"zones_intersect": "error"
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"allow_blind_buried_vias": false,
|
||||||
|
"allow_microvias": false,
|
||||||
|
"max_error": 0.005,
|
||||||
|
"min_clearance": 0.0,
|
||||||
|
"min_copper_edge_clearance": 0.09999999999999999,
|
||||||
|
"min_hole_clearance": 0.25,
|
||||||
|
"min_hole_to_hole": 0.25,
|
||||||
|
"min_microvia_diameter": 0.19999999999999998,
|
||||||
|
"min_microvia_drill": 0.09999999999999999,
|
||||||
|
"min_silk_clearance": 0.0,
|
||||||
|
"min_through_hole_diameter": 0.3,
|
||||||
|
"min_track_width": 0.19999999999999998,
|
||||||
|
"min_via_annular_width": 0.049999999999999996,
|
||||||
|
"min_via_diameter": 0.39999999999999997,
|
||||||
|
"use_height_for_length_calcs": true
|
||||||
|
},
|
||||||
|
"track_widths": [],
|
||||||
|
"via_dimensions": [],
|
||||||
|
"zones_allow_external_fillets": false,
|
||||||
|
"zones_use_no_outline": true
|
||||||
|
},
|
||||||
|
"layer_presets": []
|
||||||
|
},
|
||||||
|
"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_label_syntax": "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",
|
||||||
|
"extra_units": "error",
|
||||||
|
"global_label_dangling": "warning",
|
||||||
|
"hier_label_mismatch": "error",
|
||||||
|
"label_dangling": "error",
|
||||||
|
"lib_symbol_issues": "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",
|
||||||
|
"similar_labels": "warning",
|
||||||
|
"unannotated": "error",
|
||||||
|
"unit_value_mismatch": "error",
|
||||||
|
"unresolved_variable": "error",
|
||||||
|
"wire_dangling": "error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"libraries": {
|
||||||
|
"pinned_footprint_libs": [],
|
||||||
|
"pinned_symbol_libs": []
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"filename": "lora_tracker.kicad_pro",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
"net_settings": {
|
||||||
|
"classes": [
|
||||||
|
{
|
||||||
|
"bus_width": 12.0,
|
||||||
|
"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.25,
|
||||||
|
"via_diameter": 0.8,
|
||||||
|
"via_drill": 0.4,
|
||||||
|
"wire_width": 6.0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"version": 2
|
||||||
|
},
|
||||||
|
"net_colors": null
|
||||||
|
},
|
||||||
|
"pcbnew": {
|
||||||
|
"last_paths": {
|
||||||
|
"gencad": "",
|
||||||
|
"idf": "",
|
||||||
|
"netlist": "",
|
||||||
|
"specctra_dsn": "",
|
||||||
|
"step": "",
|
||||||
|
"vrml": ""
|
||||||
|
},
|
||||||
|
"page_layout_descr_file": ""
|
||||||
|
},
|
||||||
|
"schematic": {
|
||||||
|
"annotate_start_num": 0,
|
||||||
|
"drawing": {
|
||||||
|
"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.25,
|
||||||
|
"pin_symbol_size": 0.0,
|
||||||
|
"text_offset_ratio": 0.08
|
||||||
|
},
|
||||||
|
"legacy_lib_dir": "",
|
||||||
|
"legacy_lib_list": [],
|
||||||
|
"meta": {
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
"net_format_name": "Pcbnew",
|
||||||
|
"ngspice": {
|
||||||
|
"fix_include_paths": true,
|
||||||
|
"fix_passive_vals": false,
|
||||||
|
"meta": {
|
||||||
|
"version": 0
|
||||||
|
},
|
||||||
|
"model_mode": 0,
|
||||||
|
"workbook_filename": ""
|
||||||
|
},
|
||||||
|
"page_layout_descr_file": "",
|
||||||
|
"plot_directory": "",
|
||||||
|
"spice_adjust_passive_values": false,
|
||||||
|
"spice_external_command": "spice \"%I\"",
|
||||||
|
"subpart_first_id": 65,
|
||||||
|
"subpart_id_separator": 0
|
||||||
|
},
|
||||||
|
"sheets": [
|
||||||
|
[
|
||||||
|
"2d4f79a6-5cd6-46ec-8c40-a841159b019b",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"text_variables": {}
|
||||||
|
}
|
Plik diff jest za duży
Load Diff
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,75 @@
|
||||||
|
{
|
||||||
|
"board": {
|
||||||
|
"active_layer": 0,
|
||||||
|
"active_layer_preset": "All Layers",
|
||||||
|
"auto_track_width": true,
|
||||||
|
"hidden_nets": [],
|
||||||
|
"high_contrast_mode": 0,
|
||||||
|
"net_color_mode": 1,
|
||||||
|
"opacity": {
|
||||||
|
"pads": 1.0,
|
||||||
|
"tracks": 1.0,
|
||||||
|
"vias": 1.0,
|
||||||
|
"zones": 0.6
|
||||||
|
},
|
||||||
|
"ratsnest_display_mode": 0,
|
||||||
|
"selection_filter": {
|
||||||
|
"dimensions": true,
|
||||||
|
"footprints": true,
|
||||||
|
"graphics": true,
|
||||||
|
"keepouts": true,
|
||||||
|
"lockedItems": true,
|
||||||
|
"otherItems": true,
|
||||||
|
"pads": true,
|
||||||
|
"text": true,
|
||||||
|
"tracks": true,
|
||||||
|
"vias": true,
|
||||||
|
"zones": true
|
||||||
|
},
|
||||||
|
"visible_items": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
8,
|
||||||
|
9,
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
19,
|
||||||
|
20,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
23,
|
||||||
|
24,
|
||||||
|
25,
|
||||||
|
26,
|
||||||
|
27,
|
||||||
|
28,
|
||||||
|
29,
|
||||||
|
30,
|
||||||
|
32,
|
||||||
|
33,
|
||||||
|
34,
|
||||||
|
35,
|
||||||
|
36
|
||||||
|
],
|
||||||
|
"visible_layers": "fffffff_ffffffff",
|
||||||
|
"zone_display_mode": 0
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"filename": "lora_tracker_wide.kicad_prl",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"project": {
|
||||||
|
"files": []
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,182 @@
|
||||||
|
{
|
||||||
|
"board": {
|
||||||
|
"design_settings": {
|
||||||
|
"defaults": {
|
||||||
|
"board_outline_line_width": 0.15,
|
||||||
|
"copper_line_width": 0.19999999999999998,
|
||||||
|
"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.049999999999999996,
|
||||||
|
"dimension_precision": 4,
|
||||||
|
"dimension_units": 3,
|
||||||
|
"dimensions": {
|
||||||
|
"arrow_length": 1270000,
|
||||||
|
"extension_offset": 500000,
|
||||||
|
"keep_text_aligned": true,
|
||||||
|
"suppress_zeroes": false,
|
||||||
|
"text_position": 0,
|
||||||
|
"units_format": 1
|
||||||
|
},
|
||||||
|
"fab_line_width": 0.09999999999999999,
|
||||||
|
"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.09999999999999999,
|
||||||
|
"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.762,
|
||||||
|
"height": 1.524,
|
||||||
|
"width": 1.524
|
||||||
|
},
|
||||||
|
"silk_line_width": 0.15,
|
||||||
|
"silk_text_italic": false,
|
||||||
|
"silk_text_size_h": 1.0,
|
||||||
|
"silk_text_size_v": 1.0,
|
||||||
|
"silk_text_thickness": 0.15,
|
||||||
|
"silk_text_upright": false,
|
||||||
|
"zones": {
|
||||||
|
"45_degree_only": false,
|
||||||
|
"min_clearance": 0.508
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"diff_pair_dimensions": [],
|
||||||
|
"drc_exclusions": [],
|
||||||
|
"meta": {
|
||||||
|
"filename": "board_design_settings.json",
|
||||||
|
"version": 2
|
||||||
|
},
|
||||||
|
"rule_severities": {
|
||||||
|
"annular_width": "error",
|
||||||
|
"clearance": "error",
|
||||||
|
"copper_edge_clearance": "error",
|
||||||
|
"courtyards_overlap": "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_type_mismatch": "error",
|
||||||
|
"hole_clearance": "error",
|
||||||
|
"hole_near_hole": "error",
|
||||||
|
"invalid_outline": "error",
|
||||||
|
"item_on_disabled_layer": "error",
|
||||||
|
"items_not_allowed": "error",
|
||||||
|
"length_out_of_range": "error",
|
||||||
|
"malformed_courtyard": "error",
|
||||||
|
"microvia_drill_out_of_range": "error",
|
||||||
|
"missing_courtyard": "ignore",
|
||||||
|
"missing_footprint": "warning",
|
||||||
|
"net_conflict": "warning",
|
||||||
|
"npth_inside_courtyard": "ignore",
|
||||||
|
"padstack": "error",
|
||||||
|
"pth_inside_courtyard": "ignore",
|
||||||
|
"shorting_items": "error",
|
||||||
|
"silk_over_copper": "warning",
|
||||||
|
"silk_overlap": "warning",
|
||||||
|
"skew_out_of_range": "error",
|
||||||
|
"through_hole_pad_without_hole": "error",
|
||||||
|
"too_many_vias": "error",
|
||||||
|
"track_dangling": "warning",
|
||||||
|
"track_width": "error",
|
||||||
|
"tracks_crossing": "error",
|
||||||
|
"unconnected_items": "error",
|
||||||
|
"unresolved_variable": "error",
|
||||||
|
"via_dangling": "warning",
|
||||||
|
"zone_has_empty_net": "error",
|
||||||
|
"zones_intersect": "error"
|
||||||
|
},
|
||||||
|
"rule_severitieslegacy_courtyards_overlap": true,
|
||||||
|
"rule_severitieslegacy_no_courtyard_defined": false,
|
||||||
|
"rules": {
|
||||||
|
"allow_blind_buried_vias": false,
|
||||||
|
"allow_microvias": false,
|
||||||
|
"max_error": 0.005,
|
||||||
|
"min_clearance": 0.0,
|
||||||
|
"min_copper_edge_clearance": 0.09999999999999999,
|
||||||
|
"min_hole_clearance": 0.25,
|
||||||
|
"min_hole_to_hole": 0.25,
|
||||||
|
"min_microvia_diameter": 0.19999999999999998,
|
||||||
|
"min_microvia_drill": 0.09999999999999999,
|
||||||
|
"min_silk_clearance": 0.0,
|
||||||
|
"min_through_hole_diameter": 0.3,
|
||||||
|
"min_track_width": 0.19999999999999998,
|
||||||
|
"min_via_annular_width": 0.049999999999999996,
|
||||||
|
"min_via_diameter": 0.39999999999999997,
|
||||||
|
"use_height_for_length_calcs": true
|
||||||
|
},
|
||||||
|
"track_widths": [],
|
||||||
|
"via_dimensions": [],
|
||||||
|
"zones_allow_external_fillets": false,
|
||||||
|
"zones_use_no_outline": true
|
||||||
|
},
|
||||||
|
"layer_presets": []
|
||||||
|
},
|
||||||
|
"boards": [],
|
||||||
|
"cvpcb": {
|
||||||
|
"equivalence_files": []
|
||||||
|
},
|
||||||
|
"libraries": {
|
||||||
|
"pinned_footprint_libs": [],
|
||||||
|
"pinned_symbol_libs": []
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"filename": "lora_tracker_wide.kicad_pro",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
"net_settings": {
|
||||||
|
"classes": [
|
||||||
|
{
|
||||||
|
"bus_width": 12.0,
|
||||||
|
"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.25,
|
||||||
|
"via_diameter": 0.8,
|
||||||
|
"via_drill": 0.4,
|
||||||
|
"wire_width": 6.0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"version": 2
|
||||||
|
},
|
||||||
|
"net_colors": null
|
||||||
|
},
|
||||||
|
"pcbnew": {
|
||||||
|
"last_paths": {
|
||||||
|
"gencad": "",
|
||||||
|
"idf": "",
|
||||||
|
"netlist": "lora_tracker_wide.net",
|
||||||
|
"specctra_dsn": "",
|
||||||
|
"step": "",
|
||||||
|
"vrml": ""
|
||||||
|
},
|
||||||
|
"page_layout_descr_file": ""
|
||||||
|
},
|
||||||
|
"schematic": {
|
||||||
|
"drawing": {
|
||||||
|
"label_size_ratio": 0.25,
|
||||||
|
"pin_symbol_size": 0,
|
||||||
|
"text_offset_ratio": 0.08
|
||||||
|
},
|
||||||
|
"legacy_lib_dir": "",
|
||||||
|
"legacy_lib_list": []
|
||||||
|
},
|
||||||
|
"sheets": [],
|
||||||
|
"text_variables": {}
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
(sym_lib_table
|
(sym_lib_table
|
||||||
(lib (name lora_tracker)(type Legacy)(uri ${KIPRJMOD}/lora_tracker.lib)(options "")(descr ""))
|
(lib (name "lora_tracker")(type "Legacy")(uri "${KIPRJMOD}/lora_tracker.lib")(options "")(descr ""))
|
||||||
|
(lib (name "lora_tracker-rescue")(type "Legacy")(uri "${KIPRJMOD}/lora_tracker-rescue.lib")(options "")(descr ""))
|
||||||
)
|
)
|
||||||
|
|
|
@ -59,18 +59,30 @@
|
||||||
#define CFG_LORA_USE_CAD true // set to true to utilize carrier detection
|
#define CFG_LORA_USE_CAD true // set to true to utilize carrier detection
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// LoRa protocol default parameters (they need to match between devices!!!)
|
// modulation
|
||||||
|
#define CFG_MOD_TYPE_LORA 0
|
||||||
|
#define CFG_MOD_TYPE_FSK 1
|
||||||
|
#define CFG_MOD_TYPE CFG_MOD_TYPE_LORA
|
||||||
|
|
||||||
|
// general radio parameters
|
||||||
#define CFG_LORA_FREQ_RX 433.775e6 // RX frequency in MHz
|
#define CFG_LORA_FREQ_RX 433.775e6 // RX frequency in MHz
|
||||||
#define CFG_LORA_FREQ_TX 433.775e6 // TX frequency in MHz
|
#define CFG_LORA_FREQ_TX 433.775e6 // TX frequency in MHz
|
||||||
|
#define CFG_LORA_PWR 20 // output power in dBm
|
||||||
|
|
||||||
|
// LoRa protocol default parameters (they need to match between devices!!!)
|
||||||
#define CFG_LORA_BW 125e3 // bandwidth (from 7.8 kHz up to 500 kHz)
|
#define CFG_LORA_BW 125e3 // bandwidth (from 7.8 kHz up to 500 kHz)
|
||||||
#define CFG_LORA_SF 12 // spreading factor (6 - 12), 6 requires implicit header mode
|
#define CFG_LORA_SF 12 // spreading factor (6 - 12), 6 requires implicit header mode
|
||||||
#define CFG_LORA_CR 7 // coding rate (5 - 8)
|
#define CFG_LORA_CR 7 // coding rate (5 - 8)
|
||||||
#define CFG_LORA_CRC 1 // 0 - disabled, 1 - 1 byte, 2 - 2 bytes
|
#define CFG_LORA_CRC 1 // 0 - disabled, 1 - 1 byte, 2 - 2 bytes
|
||||||
#define CFG_LORA_EXPLICIT true // header mode, true - explicit, false - implicit
|
#define CFG_LORA_EXPLICIT true // header mode, true - explicit, false - implicit
|
||||||
#define CFG_LORA_SYNC 0x12 // sync word (0x12 - private used by other trackers, 0x34 - public used by LoRaWAN)
|
#define CFG_LORA_SYNC 0x12 // sync word (0x12 - private used by other trackers, 0x34 - public used by LoRaWAN)
|
||||||
#define CFG_LORA_PWR 20 // output power in dBm
|
|
||||||
#define CFG_LORA_PREAMBLE 8 // preamble length from 6 to 65535
|
#define CFG_LORA_PREAMBLE 8 // preamble length from 6 to 65535
|
||||||
|
|
||||||
|
// fsk modem default parameters (they need to match between devices!!!)
|
||||||
|
#define CFG_FSK_BIT_RATE 4.8 // bit rate in Kbps from 0.6 to 300.0
|
||||||
|
#define CFG_FSK_FREQ_DEV 1.2 // frequency deviation in kHz from 0.6 to 200.0
|
||||||
|
#define CFG_FSK_RX_BW 9.7 // rx bandwidth in kHz !!discrete!! from 4.8 to 467.0
|
||||||
|
|
||||||
// WiFi client and AP options
|
// WiFi client and AP options
|
||||||
#define CFG_WIFI_ENABLE_AP false // run as wifi access point (for CFG_KISS_TCP_IP mode)
|
#define CFG_WIFI_ENABLE_AP false // run as wifi access point (for CFG_KISS_TCP_IP mode)
|
||||||
#define CFG_WIFI_SSID "<ssid>" // connect to SSID or run as this SSID in AP mode
|
#define CFG_WIFI_SSID "<ssid>" // connect to SSID or run as this SSID in AP mode
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <DebugLog.h>
|
#include <DebugLog.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#define CIRCULAR_BUFFER_INT_SAFE
|
#define CIRCULAR_BUFFER_INT_SAFE
|
||||||
#include <CircularBuffer.h>
|
#include <CircularBuffer.h>
|
||||||
|
@ -13,6 +14,7 @@ namespace Kiss {
|
||||||
class Processor {
|
class Processor {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// Enum to represent special KISS markers
|
||||||
enum Marker {
|
enum Marker {
|
||||||
Fend = 0xc0,
|
Fend = 0xc0,
|
||||||
Fesc = 0xdb,
|
Fesc = 0xdb,
|
||||||
|
@ -20,6 +22,7 @@ protected:
|
||||||
Tfesc = 0xdd
|
Tfesc = 0xdd
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Enum to represent the state of the processor
|
||||||
enum State {
|
enum State {
|
||||||
GetStart = 0,
|
GetStart = 0,
|
||||||
GetEnd,
|
GetEnd,
|
||||||
|
@ -30,6 +33,7 @@ protected:
|
||||||
Escape
|
Escape
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Enum to represent KISS commands
|
||||||
enum Cmd {
|
enum Cmd {
|
||||||
Data = 0x00,
|
Data = 0x00,
|
||||||
TxDelay = 0x01,
|
TxDelay = 0x01,
|
||||||
|
@ -43,6 +47,7 @@ protected:
|
||||||
NoCmd = 0x80
|
NoCmd = 0x80
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Enum to represent the type of data being processed
|
||||||
enum DataType {
|
enum DataType {
|
||||||
Raw = 0,
|
Raw = 0,
|
||||||
Control,
|
Control,
|
||||||
|
@ -50,56 +55,69 @@ protected:
|
||||||
None = 0x80
|
None = 0x80
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int CfgSerialToRigQueueSize = 4096;
|
// Compile-time constants for configuration
|
||||||
static const int CfgRigToSerialQueueSize = 4096;
|
static constexpr int CfgToSerialDelayMs = 10;
|
||||||
|
static constexpr int CfgSerialToRigQueueSize = 4096;
|
||||||
|
static constexpr int CfgRigToSerialQueueSize = 4096;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Processor();
|
Processor();
|
||||||
|
virtual ~Processor() = default; // Add virtual destructor
|
||||||
|
|
||||||
|
// Sends data from rig to serial with a specific command
|
||||||
void sendRigToSerial(Cmd cmd, const byte *packet, int packetLength);
|
void sendRigToSerial(Cmd cmd, const byte *packet, int packetLength);
|
||||||
|
|
||||||
|
// Queues data for transmission from rig to serial
|
||||||
void queueRigToSerial(Cmd cmd, const byte *packet, int packetLength);
|
void queueRigToSerial(Cmd cmd, const byte *packet, int packetLength);
|
||||||
|
|
||||||
|
// Queues data for transmission from serial to rig
|
||||||
void queueSerialToRig(Cmd cmd, const byte *packet, int packetLength);
|
void queueSerialToRig(Cmd cmd, const byte *packet, int packetLength);
|
||||||
|
|
||||||
|
// Processes queued data for transmission from rig to serial
|
||||||
bool processRigToSerial();
|
bool processRigToSerial();
|
||||||
|
|
||||||
|
// Processes queued data for transmission from serial to rig
|
||||||
bool processSerialToRig();
|
bool processSerialToRig();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// Virtual methods to be implemented by derived classes
|
||||||
virtual bool onRigTxBegin() = 0;
|
virtual bool onRigTxBegin() = 0;
|
||||||
virtual void onRigTx(byte b) = 0;
|
virtual void onRigTx(byte b) = 0;
|
||||||
virtual void onRigTxEnd() = 0;
|
virtual void onRigTxEnd() = 0;
|
||||||
virtual void onRigPacket(void *packet, int packetLength) = 0;
|
virtual void onRigPacket(void *packet, int packetLength) = 0;
|
||||||
|
|
||||||
virtual void onSerialTx(byte b) = 0;
|
virtual void onSerialTx(byte b) = 0;
|
||||||
virtual bool onSerialRxHasData() = 0;
|
virtual bool onSerialRxHasData() = 0;
|
||||||
virtual bool onSerialRx(byte *b) = 0;
|
virtual bool onSerialRx(byte *b) = 0;
|
||||||
|
|
||||||
virtual void onControlCommand(Cmd cmd, byte value) = 0;
|
virtual void onControlCommand(Cmd cmd, byte value) = 0;
|
||||||
virtual void onRadioControlCommand(const std::vector<byte> &command) = 0;
|
virtual void onRadioControlCommand(const std::vector<byte> &command) = 0;
|
||||||
virtual void onRebootCommand() = 0;
|
virtual void onRebootCommand() = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Processes a received byte
|
||||||
bool receiveByte(byte rxByte);
|
bool receiveByte(byte rxByte);
|
||||||
bool receiveByteRaw(byte rxByte);
|
bool receiveByteRaw(byte rxByte);
|
||||||
bool receiveByteKiss(byte rxByte);
|
bool receiveByteKiss(byte rxByte);
|
||||||
|
|
||||||
|
// Processes data and commands
|
||||||
void processData(byte rxByte);
|
void processData(byte rxByte);
|
||||||
bool processCommand(byte rxByte);
|
bool processCommand(byte rxByte);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool disableKiss_;
|
bool disableKiss_; // Flag to disable KISS mode
|
||||||
bool usePrefix3_;
|
bool usePrefix3_; // Flag to use a 3-byte prefix
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isRawIdle_;
|
bool isRawIdle_; // Indicates if raw mode is idle
|
||||||
State state_;
|
State state_; // Current state of the processor
|
||||||
DataType dataType_;
|
DataType dataType_;// Current data type being processed
|
||||||
std::vector<byte> cmdBuffer_;
|
std::vector<byte> cmdBuffer_; // Buffer for commands
|
||||||
|
|
||||||
|
// Circular buffers for data queues
|
||||||
CircularBuffer<uint8_t, CfgSerialToRigQueueSize> serialToRigQueue_;
|
CircularBuffer<uint8_t, CfgSerialToRigQueueSize> serialToRigQueue_;
|
||||||
CircularBuffer<uint8_t, CfgRigToSerialQueueSize> rigToSerialQueue_;
|
CircularBuffer<uint8_t, CfgRigToSerialQueueSize> rigToSerialQueue_;
|
||||||
CircularBuffer<uint8_t, CfgRigToSerialQueueSize> rigToSerialQueueIndex_;
|
CircularBuffer<uint8_t, CfgRigToSerialQueueSize> rigToSerialQueueIndex_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // Kiss
|
} // Kiss
|
||||||
|
|
||||||
#endif // KISS_PROCESSOR_H
|
#endif // KISS_PROCESSOR_H
|
||||||
|
|
|
@ -11,18 +11,28 @@ struct Config
|
||||||
DebugLogLevel LogLevel; // log level
|
DebugLogLevel LogLevel; // log level
|
||||||
bool IsClientMode; // false - server mode, true - client mode (disables wifi and aprsis)
|
bool IsClientMode; // false - server mode, true - client mode (disables wifi and aprsis)
|
||||||
|
|
||||||
// lora protocol parameters
|
// modulation type
|
||||||
|
int ModType; // 0 - lora, 1 - fsk
|
||||||
|
|
||||||
|
// general radio parameters
|
||||||
long LoraFreqRx; // lora RX frequency, e.g. 433.775e6
|
long LoraFreqRx; // lora RX frequency, e.g. 433.775e6
|
||||||
long LoraFreqTx; // lora TX frequency, e.g. 433.775e6
|
long LoraFreqTx; // lora TX frequency, e.g. 433.775e6
|
||||||
|
int LoraPower; // lora power level in dbm, 20
|
||||||
|
|
||||||
|
// lora protocol parameters
|
||||||
long LoraBw; // lora bandwidth, e.g. 125e3
|
long LoraBw; // lora bandwidth, e.g. 125e3
|
||||||
int LoraSf; // lora spreading factor, e.g. 12
|
int LoraSf; // lora spreading factor, e.g. 12
|
||||||
int LoraCodingRate; // lora coding rate, e.g. 7
|
int LoraCodingRate; // lora coding rate, e.g. 7
|
||||||
int LoraPower; // lora power level in dbm, 20
|
|
||||||
int LoraSync; // lora sync word/packet id, 0x34
|
int LoraSync; // lora sync word/packet id, 0x34
|
||||||
int LoraCrc; // lora crc mode, 0 - disabled, 1 - 1 byte, 2 - 2 bytes
|
int LoraCrc; // lora crc mode, 0 - disabled, 1 - 1 byte, 2 - 2 bytes
|
||||||
bool LoraExplicit; // lora header mode, true - explicit, false - implicit
|
bool LoraExplicit; // lora header mode, true - explicit, false - implicit
|
||||||
int LoraPreamble; // lora preamble length from 6 to 65535
|
int LoraPreamble; // lora preamble length from 6 to 65535
|
||||||
|
|
||||||
|
// fsk modulation parameters
|
||||||
|
float FskBitRate; // fsk bit rate, 0.6 - 300.0 Kbps
|
||||||
|
float FskFreqDev; // fsk frequency deviation 0.6 - 200 kHz
|
||||||
|
float FskRxBw; // fsk rx bandwidth, discrete from 4.8 to 467 kHz
|
||||||
|
|
||||||
// lora hardware pinouts and isr
|
// lora hardware pinouts and isr
|
||||||
byte LoraPinSs; // lora ss pin
|
byte LoraPinSs; // lora ss pin
|
||||||
byte LoraPinRst; // lora rst pin
|
byte LoraPinRst; // lora rst pin
|
||||||
|
|
|
@ -39,9 +39,11 @@ private:
|
||||||
|
|
||||||
void setupWifi(const String &wifiName, const String &wifiKey);
|
void setupWifi(const String &wifiName, const String &wifiKey);
|
||||||
void setupRig(long freq, long bw, int sf, int cr, int pwr, int sync, int crcBytes, bool isExplicit);
|
void setupRig(long freq, long bw, int sf, int cr, int pwr, int sync, int crcBytes, bool isExplicit);
|
||||||
void setFreq(long freq) const;
|
void setupRigFsk(long freq, float bitRate, float freqDev, float rxBw, int pwr);
|
||||||
void setupBt(const String &btName);
|
void setupBt(const String &btName);
|
||||||
|
|
||||||
|
void setFreq(long freq) const;
|
||||||
|
|
||||||
void reconnectWifi() const;
|
void reconnectWifi() const;
|
||||||
bool reconnectAprsis();
|
bool reconnectAprsis();
|
||||||
void attachKissNetworkClient();
|
void attachKissNetworkClient();
|
||||||
|
@ -50,9 +52,14 @@ private:
|
||||||
|
|
||||||
void onRigTaskRxPacket();
|
void onRigTaskRxPacket();
|
||||||
void onRigTaskTxPacket();
|
void onRigTaskTxPacket();
|
||||||
|
void onRigTaskStartRx();
|
||||||
|
void onRigTaskStartTx();
|
||||||
static void rigTask(void *self);
|
static void rigTask(void *self);
|
||||||
static ICACHE_RAM_ATTR void onRigIsrRxPacket();
|
static ICACHE_RAM_ATTR void onRigIsrRxPacket();
|
||||||
|
|
||||||
|
void startRx();
|
||||||
|
static bool startRxTimer(void *param);
|
||||||
|
|
||||||
void onAprsisDataAvailable();
|
void onAprsisDataAvailable();
|
||||||
|
|
||||||
void sendSignalReportEvent(int rssi, float snr);
|
void sendSignalReportEvent(int rssi, float snr);
|
||||||
|
@ -104,13 +111,18 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct SetHardware {
|
struct SetHardware {
|
||||||
uint32_t freq;
|
uint32_t freqRx;
|
||||||
|
uint32_t freqTx;
|
||||||
|
uint8_t modType;
|
||||||
|
int16_t pwr;
|
||||||
uint32_t bw;
|
uint32_t bw;
|
||||||
uint16_t sf;
|
uint16_t sf;
|
||||||
uint16_t cr;
|
uint16_t cr;
|
||||||
uint16_t pwr;
|
|
||||||
uint16_t sync;
|
uint16_t sync;
|
||||||
uint8_t crc;
|
uint8_t crc;
|
||||||
|
uint32_t fskBitRate;
|
||||||
|
uint32_t fskFreqDev;
|
||||||
|
uint32_t fskRxBw;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct SignalReport {
|
struct SignalReport {
|
||||||
|
@ -123,7 +135,7 @@ private:
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const String CfgLoraprsVersion = "LoRAPRS 1.0.13";
|
const String CfgLoraprsVersion = "LoRAPRS 1.0.16";
|
||||||
|
|
||||||
// processor config
|
// processor config
|
||||||
const int CfgConnRetryMs = 500; // connection retry delay, e.g. wifi
|
const int CfgConnRetryMs = 500; // connection retry delay, e.g. wifi
|
||||||
|
@ -143,7 +155,9 @@ private:
|
||||||
// radio task commands
|
// radio task commands
|
||||||
enum RadioTaskBits {
|
enum RadioTaskBits {
|
||||||
Receive = 0x01,
|
Receive = 0x01,
|
||||||
Transmit = 0x02
|
Transmit = 0x02,
|
||||||
|
StartReceive = 0x04,
|
||||||
|
StartTransmit = 0x10
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -162,6 +176,7 @@ private:
|
||||||
|
|
||||||
// peripherals, radio
|
// peripherals, radio
|
||||||
static TaskHandle_t rigTaskHandle_;
|
static TaskHandle_t rigTaskHandle_;
|
||||||
|
Timer<1> startRxTimer_;
|
||||||
static volatile bool rigIsRxActive_;
|
static volatile bool rigIsRxActive_;
|
||||||
static volatile bool rigIsRxIsrEnabled_;
|
static volatile bool rigIsRxIsrEnabled_;
|
||||||
bool rigIsImplicitMode_;
|
bool rigIsImplicitMode_;
|
||||||
|
|
|
@ -134,7 +134,7 @@ bool Processor::processRigToSerial()
|
||||||
onRigPacket(&buf, rxPacketSize);
|
onRigPacket(&buf, rxPacketSize);
|
||||||
|
|
||||||
isProcessed = true;
|
isProcessed = true;
|
||||||
yield();
|
if (!rigToSerialQueueIndex_.isEmpty()) delay(CfgToSerialDelayMs);
|
||||||
}
|
}
|
||||||
return isProcessed;
|
return isProcessed;
|
||||||
}
|
}
|
||||||
|
@ -280,11 +280,19 @@ bool Processor::receiveByteKiss(byte rxByte)
|
||||||
break;
|
break;
|
||||||
case State::Escape:
|
case State::Escape:
|
||||||
if (rxByte == Marker::Tfend) {
|
if (rxByte == Marker::Tfend) {
|
||||||
onRigTx((byte)Marker::Fend);
|
if (dataType_ == DataType::Raw) {
|
||||||
|
onRigTx((byte)Marker::Fend);
|
||||||
|
} else if (dataType_ == DataType::Control) {
|
||||||
|
cmdBuffer_.push_back((byte)Marker::Fend);
|
||||||
|
}
|
||||||
state_ = State::GetData;
|
state_ = State::GetData;
|
||||||
}
|
}
|
||||||
else if (rxByte == Marker::Tfesc) {
|
else if (rxByte == Marker::Tfesc) {
|
||||||
onRigTx((byte)Marker::Fesc);
|
if (dataType_ == DataType::Raw) {
|
||||||
|
onRigTx((byte)Marker::Fesc);
|
||||||
|
} else if (dataType_ == DataType::Control) {
|
||||||
|
cmdBuffer_.push_back((byte)Marker::Fesc);
|
||||||
|
}
|
||||||
state_ = State::GetData;
|
state_ = State::GetData;
|
||||||
}
|
}
|
||||||
else if (rxByte != Marker::Fend) {
|
else if (rxByte != Marker::Fend) {
|
||||||
|
|
|
@ -61,9 +61,14 @@ void Service::setup(const Config &conf)
|
||||||
}
|
}
|
||||||
aprsLoginCommand_ += String("\n");
|
aprsLoginCommand_ += String("\n");
|
||||||
|
|
||||||
// peripherals, LoRa
|
// radio module, FSK/LoRa
|
||||||
setupRig(config_.LoraFreqRx, config_.LoraBw, config_.LoraSf,
|
if (config_.ModType == CFG_MOD_TYPE_FSK) {
|
||||||
config_.LoraCodingRate, config_.LoraPower, config_.LoraSync, config_.LoraCrc, config_.LoraExplicit);
|
setupRigFsk(config_.LoraFreqRx, config_.FskBitRate, config_.FskFreqDev, config_.FskRxBw, config_.LoraPower);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setupRig(config_.LoraFreqRx, config_.LoraBw, config_.LoraSf,
|
||||||
|
config_.LoraCodingRate, config_.LoraPower, config_.LoraSync, config_.LoraCrc, config_.LoraExplicit);
|
||||||
|
}
|
||||||
|
|
||||||
// start radio task
|
// start radio task
|
||||||
xTaskCreate(rigTask, "rigTask", 4096, this, 5, &rigTaskHandle_);
|
xTaskCreate(rigTask, "rigTask", 4096, this, 5, &rigTaskHandle_);
|
||||||
|
@ -251,7 +256,7 @@ void Service::setupRig(long loraFreq, long bw, int sf, int cr, int pwr, int sync
|
||||||
#pragma message("Using SX127X")
|
#pragma message("Using SX127X")
|
||||||
LOG_INFO("Using SX127X module");
|
LOG_INFO("Using SX127X module");
|
||||||
if (isIsrInstalled_) rig_->clearDio0Action();
|
if (isIsrInstalled_) rig_->clearDio0Action();
|
||||||
rig_->setDio0Action(onRigIsrRxPacket);
|
rig_->setDio0Action(onRigIsrRxPacket, RISING);
|
||||||
isIsrInstalled_ = true;
|
isIsrInstalled_ = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -269,6 +274,43 @@ void Service::setupRig(long loraFreq, long bw, int sf, int cr, int pwr, int sync
|
||||||
LOG_INFO("LoRa initialized");
|
LOG_INFO("LoRa initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Service::setupRigFsk(long freq, float bitRate, float freqDev, float rxBw, int pwr)
|
||||||
|
{
|
||||||
|
LOG_INFO("Initializing FSK");
|
||||||
|
LOG_INFO("Frequency:", freq, "Hz");
|
||||||
|
LOG_INFO("Bit rate:", bitRate, "kbps");
|
||||||
|
LOG_INFO("Deviation:", freqDev, "kHz");
|
||||||
|
LOG_INFO("Bandwidth:", rxBw, "kHz");
|
||||||
|
LOG_INFO("Power:", pwr, "dBm");
|
||||||
|
rig_ = std::make_shared<MODULE_NAME>(new Module(config_.LoraPinSs, config_.LoraPinA, config_.LoraPinRst, config_.LoraPinB));
|
||||||
|
int state = rig_->beginFSK((float)freq / 1e6, bitRate, freqDev, rxBw, pwr);
|
||||||
|
if (state != RADIOLIB_ERR_NONE) {
|
||||||
|
LOG_ERROR("Radio start error:", state);
|
||||||
|
}
|
||||||
|
rig_->disableAddressFiltering();
|
||||||
|
#ifdef USE_SX126X
|
||||||
|
#pragma message("Using SX126X")
|
||||||
|
LOG_INFO("Using SX126X module");
|
||||||
|
rig_->setRfSwitchPins(config_.LoraPinSwitchRx, config_.LoraPinSwitchTx);
|
||||||
|
if (isIsrInstalled_) rig_->clearDio1Action();
|
||||||
|
rig_->setDio1Action(onRigIsrRxPacket);
|
||||||
|
isIsrInstalled_ = true;
|
||||||
|
#else
|
||||||
|
#pragma message("Using SX127X")
|
||||||
|
LOG_INFO("Using SX127X module");
|
||||||
|
if (isIsrInstalled_) rig_->clearDio0Action();
|
||||||
|
rig_->setDio0Action(onRigIsrRxPacket, RISING);
|
||||||
|
isIsrInstalled_ = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
state = rig_->startReceive();
|
||||||
|
if (state != RADIOLIB_ERR_NONE) {
|
||||||
|
LOG_ERROR("Receive start error:", state);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("FSK initialized");
|
||||||
|
}
|
||||||
|
|
||||||
void Service::setupBt(const String &btName)
|
void Service::setupBt(const String &btName)
|
||||||
{
|
{
|
||||||
String btType = config_.BtEnableBle ? "BLE" : "BT";
|
String btType = config_.BtEnableBle ? "BLE" : "BT";
|
||||||
|
@ -325,6 +367,7 @@ void Service::loop()
|
||||||
if (config_.TlmEnable) {
|
if (config_.TlmEnable) {
|
||||||
telemetryTimer_.tick();
|
telemetryTimer_.tick();
|
||||||
}
|
}
|
||||||
|
startRxTimer_.tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
ICACHE_RAM_ATTR void Service::onRigIsrRxPacket() {
|
ICACHE_RAM_ATTR void Service::onRigIsrRxPacket() {
|
||||||
|
@ -346,9 +389,30 @@ void Service::rigTask(void *self) {
|
||||||
else if (commandBits & RadioTaskBits::Transmit) {
|
else if (commandBits & RadioTaskBits::Transmit) {
|
||||||
static_cast<Service*>(self)->onRigTaskTxPacket();
|
static_cast<Service*>(self)->onRigTaskTxPacket();
|
||||||
}
|
}
|
||||||
|
if (commandBits & RadioTaskBits::StartReceive) {
|
||||||
|
static_cast<Service*>(self)->onRigTaskStartRx();
|
||||||
|
}
|
||||||
|
else if (commandBits & RadioTaskBits::StartTransmit) {
|
||||||
|
static_cast<Service*>(self)->onRigTaskStartTx();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Service::onRigTaskStartRx() {
|
||||||
|
LOG_TRACE("onRigTaskStartRx");
|
||||||
|
if (config_.PttEnable) {
|
||||||
|
digitalWrite(config_.PttPin, LOW);
|
||||||
|
}
|
||||||
|
if (isHalfDuplex()) {
|
||||||
|
setFreq(config_.LoraFreqRx);
|
||||||
|
}
|
||||||
|
int state = rig_->startReceive();
|
||||||
|
if (state != RADIOLIB_ERR_NONE) {
|
||||||
|
LOG_ERROR("Start receive error: ", state);
|
||||||
|
}
|
||||||
|
rigIsRxIsrEnabled_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
void Service::onRigTaskRxPacket() {
|
void Service::onRigTaskRxPacket() {
|
||||||
int packetSize = rig_->getPacketLength();
|
int packetSize = rig_->getPacketLength();
|
||||||
LOG_TRACE("onRigTaskRxPacket", packetSize);
|
LOG_TRACE("onRigTaskRxPacket", packetSize);
|
||||||
|
@ -369,15 +433,21 @@ void Service::onRigTaskRxPacket() {
|
||||||
rigIsRxActive_ = false;
|
rigIsRxActive_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Service::onRigTaskTxPacket() {
|
void Service::onRigTaskStartTx() {
|
||||||
rigIsRxIsrEnabled_ = false;
|
LOG_TRACE("onRigTaskStartTx");
|
||||||
if (isHalfDuplex()) {
|
if (rigIsRxIsrEnabled_) {
|
||||||
setFreq(config_.LoraFreqTx);
|
rigIsRxIsrEnabled_ = false;
|
||||||
}
|
if (isHalfDuplex()) {
|
||||||
if (config_.PttEnable) {
|
setFreq(config_.LoraFreqTx);
|
||||||
digitalWrite(config_.PttPin, HIGH);
|
}
|
||||||
|
if (config_.PttEnable) {
|
||||||
|
digitalWrite(config_.PttPin, HIGH);
|
||||||
|
}
|
||||||
delay(config_.PttTxDelayMs);
|
delay(config_.PttTxDelayMs);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Service::onRigTaskTxPacket() {
|
||||||
while (rigTxQueueIndex_.size() > 0) {
|
while (rigTxQueueIndex_.size() > 0) {
|
||||||
int txPacketSize = rigTxQueueIndex_.shift();
|
int txPacketSize = rigTxQueueIndex_.shift();
|
||||||
LOG_TRACE("onRigTaskTxPacket", txPacketSize);
|
LOG_TRACE("onRigTaskTxPacket", txPacketSize);
|
||||||
|
@ -393,18 +463,7 @@ void Service::onRigTaskTxPacket() {
|
||||||
}
|
}
|
||||||
vTaskDelay(1);
|
vTaskDelay(1);
|
||||||
}
|
}
|
||||||
if (config_.PttEnable) {
|
startRxTimer_.in(config_.PttTxTailMs, &startRxTimer);
|
||||||
delay(config_.PttTxTailMs);
|
|
||||||
digitalWrite(config_.PttPin, LOW);
|
|
||||||
}
|
|
||||||
if (isHalfDuplex()) {
|
|
||||||
setFreq(config_.LoraFreqRx);
|
|
||||||
}
|
|
||||||
int state = rig_->startReceive();
|
|
||||||
if (state != RADIOLIB_ERR_NONE) {
|
|
||||||
LOG_ERROR("Start receive error: ", state);
|
|
||||||
}
|
|
||||||
rigIsRxIsrEnabled_ = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Service::sendPeriodicBeacon()
|
void Service::sendPeriodicBeacon()
|
||||||
|
@ -486,6 +545,16 @@ bool Service::sendModemTelemetryTimer(void *param)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Service::startRxTimer(void *param)
|
||||||
|
{
|
||||||
|
static_cast<Service*>(param)->startRx();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Service::startRx() {
|
||||||
|
xTaskNotify(rigTaskHandle_, RadioTaskBits::StartReceive, eSetBits);
|
||||||
|
}
|
||||||
|
|
||||||
void Service::sendModemTelemetry()
|
void Service::sendModemTelemetry()
|
||||||
{
|
{
|
||||||
float batVoltage = 2 * analogRead(config_.TlmBatMonPin) * (3.3 / 4096.0) + config_.TlmBatMonCal;
|
float batVoltage = 2 * analogRead(config_.TlmBatMonPin) * (3.3 / 4096.0) + config_.TlmBatMonCal;
|
||||||
|
@ -549,10 +618,6 @@ void Service::performFrequencyCorrection() {
|
||||||
|
|
||||||
void Service::setFreq(long loraFreq) const {
|
void Service::setFreq(long loraFreq) const {
|
||||||
rig_->setFrequency((float)loraFreq / 1e6);
|
rig_->setFrequency((float)loraFreq / 1e6);
|
||||||
int state = rig_->startReceive();
|
|
||||||
if (state != RADIOLIB_ERR_NONE) {
|
|
||||||
LOG_ERROR("Start receive error:", state);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Service::processIncomingRawPacketAsServer(const byte *packet, int packetLength) {
|
void Service::processIncomingRawPacketAsServer(const byte *packet, int packetLength) {
|
||||||
|
@ -608,6 +673,8 @@ void Service::processIncomingRawPacketAsServer(const byte *packet, int packetLen
|
||||||
bool Service::onRigTxBegin()
|
bool Service::onRigTxBegin()
|
||||||
{
|
{
|
||||||
LOG_TRACE("onRigTxBegin");
|
LOG_TRACE("onRigTxBegin");
|
||||||
|
startRxTimer_.cancel();
|
||||||
|
xTaskNotify(rigTaskHandle_, RadioTaskBits::StartTransmit, eSetBits);
|
||||||
rigCurrentTxPacketSize_ = 0;
|
rigCurrentTxPacketSize_ = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -739,21 +806,29 @@ void Service::onRadioControlCommand(const std::vector<byte> &rawCommand) {
|
||||||
if (config_.KissEnableExtensions && rawCommand.size() == sizeof(SetHardware)) {
|
if (config_.KissEnableExtensions && rawCommand.size() == sizeof(SetHardware)) {
|
||||||
LOG_INFO("Setting new radio parameters");
|
LOG_INFO("Setting new radio parameters");
|
||||||
const struct SetHardware * setHardware = reinterpret_cast<const struct SetHardware*>(rawCommand.data());
|
const struct SetHardware * setHardware = reinterpret_cast<const struct SetHardware*>(rawCommand.data());
|
||||||
|
|
||||||
// TODO, add support for split set hardware
|
config_.LoraFreqRx = be32toh(setHardware->freqRx);
|
||||||
config_.LoraFreqRx = be32toh(setHardware->freq);
|
config_.LoraFreqTx = be32toh(setHardware->freqTx);
|
||||||
config_.LoraFreqTx = be32toh(setHardware->freq);
|
config_.ModType = setHardware->modType;
|
||||||
config_.LoraBw = be32toh(setHardware->bw);
|
config_.LoraBw = be32toh(setHardware->bw);
|
||||||
config_.LoraSf = be16toh(setHardware->sf);
|
config_.LoraSf = be16toh(setHardware->sf);
|
||||||
config_.LoraCodingRate = be16toh(setHardware->cr);
|
config_.LoraCodingRate = be16toh(setHardware->cr);
|
||||||
config_.LoraPower = be16toh(setHardware->pwr);
|
config_.LoraPower = (int16_t)be16toh(setHardware->pwr);
|
||||||
config_.LoraSync = be16toh(setHardware->sync);
|
config_.LoraSync = be16toh(setHardware->sync);
|
||||||
|
config_.FskBitRate = (float)be32toh(setHardware->fskBitRate) / 1e3;
|
||||||
|
config_.FskFreqDev = (float)be32toh(setHardware->fskFreqDev) / 1e3;
|
||||||
|
config_.FskRxBw = (float)be32toh(setHardware->fskRxBw) / 1e3;
|
||||||
int crcType = setHardware->crc ? config_.LoraCrc : 0;
|
int crcType = setHardware->crc ? config_.LoraCrc : 0;
|
||||||
|
|
||||||
setupRig(config_.LoraFreqRx, config_.LoraBw, config_.LoraSf,
|
if (config_.ModType == CFG_MOD_TYPE_FSK) {
|
||||||
config_.LoraCodingRate, config_.LoraPower, config_.LoraSync, crcType, config_.LoraExplicit);
|
setupRigFsk(config_.LoraFreqRx, config_.FskBitRate, config_.FskFreqDev, config_.FskRxBw, config_.LoraPower);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setupRig(config_.LoraFreqRx, config_.LoraBw, config_.LoraSf,
|
||||||
|
config_.LoraCodingRate, config_.LoraPower, config_.LoraSync, crcType, config_.LoraExplicit);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG_ERROR("Radio control command of wrong size");
|
LOG_ERROR("Radio control command of wrong size", rawCommand.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
16
src/main.cpp
16
src/main.cpp
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
#include "loraprs_service.h"
|
#include "loraprs_service.h"
|
||||||
|
|
||||||
const int CfgPollDelayMs = 20; // main loop delay
|
const int CfgPollDelayMs = 10; // main loop delay
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize config from config.h options.
|
* Initialize config from config.h options.
|
||||||
|
@ -31,18 +31,28 @@ void initializeConfig(LoraPrs::Config &cfg) {
|
||||||
// client/server mode switch
|
// client/server mode switch
|
||||||
cfg.IsClientMode = CFG_IS_CLIENT_MODE;
|
cfg.IsClientMode = CFG_IS_CLIENT_MODE;
|
||||||
|
|
||||||
// lora parameters, must match on devices
|
// modulation
|
||||||
|
cfg.ModType = CFG_MOD_TYPE;
|
||||||
|
|
||||||
|
// generic module parameters
|
||||||
cfg.LoraFreqRx = CFG_LORA_FREQ_RX;
|
cfg.LoraFreqRx = CFG_LORA_FREQ_RX;
|
||||||
cfg.LoraFreqTx = CFG_LORA_FREQ_TX;
|
cfg.LoraFreqTx = CFG_LORA_FREQ_TX;
|
||||||
|
cfg.LoraPower = CFG_LORA_PWR;
|
||||||
|
|
||||||
|
// lora parameters, must match on devices
|
||||||
cfg.LoraBw = CFG_LORA_BW;
|
cfg.LoraBw = CFG_LORA_BW;
|
||||||
cfg.LoraSf = CFG_LORA_SF;
|
cfg.LoraSf = CFG_LORA_SF;
|
||||||
cfg.LoraCodingRate = CFG_LORA_CR;
|
cfg.LoraCodingRate = CFG_LORA_CR;
|
||||||
cfg.LoraSync = CFG_LORA_SYNC;
|
cfg.LoraSync = CFG_LORA_SYNC;
|
||||||
cfg.LoraCrc = CFG_LORA_CRC; // set to 0 to disable
|
cfg.LoraCrc = CFG_LORA_CRC; // set to 0 to disable
|
||||||
cfg.LoraExplicit = CFG_LORA_EXPLICIT;
|
cfg.LoraExplicit = CFG_LORA_EXPLICIT;
|
||||||
cfg.LoraPower = CFG_LORA_PWR;
|
|
||||||
cfg.LoraPreamble = CFG_LORA_PREAMBLE;
|
cfg.LoraPreamble = CFG_LORA_PREAMBLE;
|
||||||
|
|
||||||
|
// fsk parameters
|
||||||
|
cfg.FskBitRate = CFG_FSK_BIT_RATE;
|
||||||
|
cfg.FskFreqDev = CFG_FSK_FREQ_DEV;
|
||||||
|
cfg.FskRxBw = CFG_FSK_RX_BW;
|
||||||
|
|
||||||
// lora pinouts
|
// lora pinouts
|
||||||
cfg.LoraPinSs = CFG_LORA_PIN_SS;
|
cfg.LoraPinSs = CFG_LORA_PIN_SS;
|
||||||
cfg.LoraPinRst = CFG_LORA_PIN_RST;
|
cfg.LoraPinRst = CFG_LORA_PIN_RST;
|
||||||
|
|
Ładowanie…
Reference in New Issue