Compare commits
No commits in common. "online" and "main" have entirely different histories.
BIN
HW/timer_button/3D/Tlacitko_top.SLDPRT
Normal file
BIN
HW/timer_button/3D/Tlacitko_top.SLDPRT
Normal file
Binary file not shown.
BIN
HW/timer_button/3D/Tlacitko_top.STL
Normal file
BIN
HW/timer_button/3D/Tlacitko_top.STL
Normal file
Binary file not shown.
4442
HW/timer_button/bom/ibom.html
Normal file
4442
HW/timer_button/bom/ibom.html
Normal file
File diff suppressed because one or more lines are too long
92107
HW/timer_button/fp-info-cache
Normal file
92107
HW/timer_button/fp-info-cache
Normal file
File diff suppressed because it is too large
Load Diff
29
HW/timer_button/production/bom.csv
Normal file
29
HW/timer_button/production/bom.csv
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
Designator,Footprint,Quantity,Value,LCSC Part #
|
||||||
|
BZ1,Buzzer_12x9.5RM7.6,1,Buzzer,
|
||||||
|
"C1, C10, C11, C12, C17, C2, C4, C5, C6, C7, C8, C9",0805,12,100n,
|
||||||
|
"C13, C14",0805,2,1u,
|
||||||
|
"C15, C16",0805,2,12p,
|
||||||
|
C3,0805,1,10n,
|
||||||
|
D1,WSON-6-1EP_3x3mm_P0.95mm,1,TPD3E001DRSR,
|
||||||
|
"D10, D11, D12, D3, D4, D5, D6, D7, D8, D9",LED_WS2812B_PLCC4_5.0x5.0mm_P3.2mm,10,WS2812B,
|
||||||
|
D2,1206,1,LED,
|
||||||
|
J1,USB_C_Receptacle_HRO_TYPE-C-31-M-12,1,USB_C_Receptacle_USB2.0_16P,
|
||||||
|
J2,PinHeader_1x02_P2.54mm_Vertical,1,Conn_01x02,
|
||||||
|
"J3, J8, J9",PinHeader_1x03_P2.54mm_Vertical,3,Conn_01x03,
|
||||||
|
J4,PinHeader_1x06_P2.54mm_Vertical,1,Conn_01x06,
|
||||||
|
"J5, J6",PinHeader_1x04_P2.54mm_Vertical,2,Conn_01x04,
|
||||||
|
J7,PinHeader_2x05_P2.54mm_Vertical,1,Conn_02x05_Odd_Even,
|
||||||
|
JP1,SolderJumper-2_P1.3mm_Open_RoundedPad1.0x1.5mm,1,Jumper_2_Open,
|
||||||
|
"Q1, Q3",SOT-23,2,BSS123T-HF,
|
||||||
|
Q2,TSOP-6_1.65x3.05mm_P0.95mm,1,PMN30XPEAX,
|
||||||
|
"R1, R7",0805,2,5k1,
|
||||||
|
"R10, R11, R12, R13, R15, R2, R4, R8",0805,8,10k,
|
||||||
|
R14,0805,1,560R,
|
||||||
|
"R3, R9",0805,2,1k,
|
||||||
|
"R5, R6",0805,2,27R,
|
||||||
|
SW1,SW_Cherry_MX_1.00u_PCB,1,SW_Push,
|
||||||
|
"SW2, SW3",SW_SPST_TL3342,2,SW_Push,
|
||||||
|
U1,QFN-56-1EP_7x7mm_P0.4mm_EP3.2x3.2mm,1,RP2040,
|
||||||
|
U2,SOIC-8_5.23x5.23mm_P1.27mm,1,W25Q128JVS,
|
||||||
|
U3,SOT-23-5_HandSoldering,1,SP6205EM5-L-3-3,
|
||||||
|
Y1,Crystal_SMD_5032-2Pin_5.0x3.2mm,1,12MHz,
|
|
66
HW/timer_button/production/designators.csv
Normal file
66
HW/timer_button/production/designators.csv
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
BZ1:1
|
||||||
|
C1:1
|
||||||
|
C10:1
|
||||||
|
C11:1
|
||||||
|
C12:1
|
||||||
|
C13:1
|
||||||
|
C14:1
|
||||||
|
C15:1
|
||||||
|
C16:1
|
||||||
|
C17:1
|
||||||
|
C2:1
|
||||||
|
C3:1
|
||||||
|
C4:1
|
||||||
|
C5:1
|
||||||
|
C6:1
|
||||||
|
C7:1
|
||||||
|
C8:1
|
||||||
|
C9:1
|
||||||
|
D1:1
|
||||||
|
D10:1
|
||||||
|
D11:1
|
||||||
|
D12:1
|
||||||
|
D2:1
|
||||||
|
D3:1
|
||||||
|
D4:1
|
||||||
|
D5:1
|
||||||
|
D6:1
|
||||||
|
D7:1
|
||||||
|
D8:1
|
||||||
|
D9:1
|
||||||
|
J1:1
|
||||||
|
J2:1
|
||||||
|
J3:1
|
||||||
|
J4:1
|
||||||
|
J5:1
|
||||||
|
J6:1
|
||||||
|
J7:1
|
||||||
|
J8:1
|
||||||
|
J9:1
|
||||||
|
JP1:1
|
||||||
|
Q1:1
|
||||||
|
Q2:1
|
||||||
|
Q3:1
|
||||||
|
R1:1
|
||||||
|
R10:1
|
||||||
|
R11:1
|
||||||
|
R12:1
|
||||||
|
R13:1
|
||||||
|
R14:1
|
||||||
|
R15:1
|
||||||
|
R2:1
|
||||||
|
R3:1
|
||||||
|
R4:1
|
||||||
|
R5:1
|
||||||
|
R6:1
|
||||||
|
R7:1
|
||||||
|
R8:1
|
||||||
|
R9:1
|
||||||
|
REF**:1
|
||||||
|
SW1:1
|
||||||
|
SW2:1
|
||||||
|
SW3:1
|
||||||
|
U1:1
|
||||||
|
U2:1
|
||||||
|
U3:1
|
||||||
|
Y1:1
|
|
BIN
HW/timer_button/production/gerber.zip
Normal file
BIN
HW/timer_button/production/gerber.zip
Normal file
Binary file not shown.
353
HW/timer_button/production/netlist.ipc
Normal file
353
HW/timer_button/production/netlist.ipc
Normal file
@ -0,0 +1,353 @@
|
|||||||
|
P CODE 00
|
||||||
|
P UNITS CUST 0
|
||||||
|
P arrayDim N
|
||||||
|
317GND VIA MD0157PA00X+052283Y-035827X0315Y0000R000S3
|
||||||
|
317GND VIA MD0157PA00X+053701Y-035827X0315Y0000R000S3
|
||||||
|
317GND VIA MD0157PA00X+057323Y-029921X0315Y0000R000S3
|
||||||
|
317GND VIA MD0157PA00X+053307Y-034409X0315Y0000R000S3
|
||||||
|
317GND VIA MD0157PA00X+054252Y-033622X0315Y0000R000S3
|
||||||
|
317+1V1 VIA MD0157PA00X+056929Y-033701X0315Y0000R000S3
|
||||||
|
317GND VIA MD0157PA00X+054882Y-044173X0315Y0000R000S3
|
||||||
|
317GND VIA MD0157PA00X+055433Y-043071X0315Y0000R000S3
|
||||||
|
317GND VIA MD0157PA00X+061181Y-028425X0315Y0000R000S3
|
||||||
|
317NET-(D2-A) VIA MD0157PA00X+053189Y-037165X0315Y0000R000S3
|
||||||
|
317NET-(D2-A) VIA MD0157PA00X+050945Y-036772X0315Y0000R000S3
|
||||||
|
317VCC VIA MD0157PA00X+061496Y-037083X0315Y0000R000S3
|
||||||
|
317/RST VIA MD0157PA00X+061969Y-036142X0315Y0000R000S3
|
||||||
|
317/RST VIA MD0157PA00X+060295Y-041142X0315Y0000R000S3
|
||||||
|
317+BATT VIA MD0157PA00X+055433Y-046530X0315Y0000R000S3
|
||||||
|
317/BUZZ VIA MD0157PA00X+062205Y-042520X0315Y0000R000S3
|
||||||
|
317/NEOPIXEL VIA MD0157PA00X+062598Y-042205X0315Y0000R000S3
|
||||||
|
317/NEOPIXEL VIA MD0157PA00X+060020Y-048957X0315Y0000R000S3
|
||||||
|
317/TX VIA MD0157PA00X+066772Y-036540X0315Y0000R000S3
|
||||||
|
317/RX VIA MD0157PA00X+066494Y-036262X0315Y0000R000S3
|
||||||
|
317/NEOPIXEL VIA MD0157PA00X+066260Y-035933X0315Y0000R000S3
|
||||||
|
317/BUZZ VIA MD0157PA00X+065938Y-035706X0315Y0000R000S3
|
||||||
|
317/SDA VIA MD0157PA00X+065660Y-035428X0315Y0000R000S3
|
||||||
|
317/SCL VIA MD0157PA00X+065382Y-035149X0315Y0000R000S3
|
||||||
|
317NET-(D8-DOUT) VIA MD0157PA00X+063848Y-029490X0315Y0000R000S3
|
||||||
|
317/CHRG VIA MD0157PA00X+051260Y-042520X0315Y0000R000S3
|
||||||
|
317NET-(D10-DOUT) VIA MD0157PA00X+070080Y-041182X0315Y0000R000S3
|
||||||
|
317NET-(D10-DOUT) VIA MD0157PA00X+068456Y-041433X0315Y0000R000S3
|
||||||
|
317NET-(D10-DIN) VIA MD0157PA00X+067879Y-035476X0315Y0000R000S3
|
||||||
|
317NET-(D10-DIN) VIA MD0157PA00X+067795Y-033622X0315Y0000R000S3
|
||||||
|
317NET-(D8-DOUT) VIA MD0157PA00X+060079Y-028425X0315Y0000R000S3
|
||||||
|
317NET-(D7-DOUT) VIA MD0157PA00X+058031Y-029055X0315Y0000R000S3
|
||||||
|
317NET-(D7-DOUT) VIA MD0157PA00X+058094Y-029780X0315Y0000R000S3
|
||||||
|
317NET-(D5-DOUT) VIA MD0157PA00X+047638Y-038504X0315Y0000R000S3
|
||||||
|
317NET-(D5-DOUT) VIA MD0157PA00X+049632Y-037346X0315Y0000R000S3
|
||||||
|
317NET-(D4-DOUT) VIA MD0157PA00X+050709Y-045197X0315Y0000R000S3
|
||||||
|
317NET-(D4-DOUT) VIA MD0157PA00X+050235Y-043244X0315Y0000R000S3
|
||||||
|
317/BOOT VIA MD0157PA00X+052480Y-035118X0315Y0000R000S3
|
||||||
|
317NET-(C16-PAD1) VIA MD0157PA00X+063071Y-034961X0315Y0000R000S3
|
||||||
|
317NET-(U1-XIN) VIA MD0157PA00X+063071Y-033465X0315Y0000R000S3
|
||||||
|
317VCC VIA MD0157PA00X+054252Y-032677X0315Y0000R000S3
|
||||||
|
317T-(U1-QSPI_SS) VIA MD0157PA00X+054488Y-030157X0315Y0000R000S3
|
||||||
|
317T-(U1-QSPI_SS) VIA MD0157PA00X+055669Y-030157X0315Y0000R000S3
|
||||||
|
317-(U1-QSPI_SD1) VIA MD0157PA00X+054961Y-030433X0315Y0000R000S3
|
||||||
|
317-(U1-QSPI_SD1) VIA MD0157PA00X+055948Y-030436X0315Y0000R000S3
|
||||||
|
317GND VIA MD0157PA00X+049741Y-038789X0315Y0000R000S3
|
||||||
|
317+5V VIA MD0157PA00X+049909Y-038433X0315Y0000R000S3
|
||||||
|
317NET-(D1-IO2) VIA MD0157PA00X+050000Y-039134X0315Y0000R000S3
|
||||||
|
317NET-(D1-IO1) VIA MD0157PA00X+050000Y-039606X0315Y0000R000S3
|
||||||
|
317VCC VIA MD0157PA00X+058031Y-032913X0315Y0000R000S3
|
||||||
|
317VCC VIA MD0157PA00X+057323Y-034316X0315Y0000R000S3
|
||||||
|
317+1V1 VIA MD0157PA00X+056378Y-032874X0315Y0000R000S3
|
||||||
|
317+1V1 VIA MD0157PA00X+055748Y-034316X0315Y0000R000S3
|
||||||
|
317VCC VIA MD0157PA00X+059372Y-031804X0315Y0000R000S3
|
||||||
|
317VCC VIA MD0157PA00X+058189Y-031811X0315Y0000R000S3
|
||||||
|
317NET-(J9-PIN_3) VIA MD0157PA00X+053251Y-036641X0315Y0000R000S3
|
||||||
|
317NET-(J9-PIN_2) VIA MD0157PA00X+053622Y-036772X0315Y0000R000S3
|
||||||
|
317/V_BATT VIA MD0157PA00X+054882Y-038110X0315Y0000R000S3
|
||||||
|
317/V_BATT VIA MD0157PA00X+054862Y-037480X0315Y0000R000S3
|
||||||
|
317VCC VIA MD0157PA00X+061102Y-038268X0315Y0000R000S3
|
||||||
|
317NET-(J8-PIN_2) VIA MD0157PA00X+059802Y-036648X0315Y0000R000S3
|
||||||
|
317NET-(J8-PIN_3) VIA MD0157PA00X+059409Y-036614X0315Y0000R000S3
|
||||||
|
317/CHRG VIA MD0157PA00X+059329Y-037049X0315Y0000R000S3
|
||||||
|
317VCC VIA MD0157PA00X+059449Y-033701X0315Y0000R000S3
|
||||||
|
317/CS VIA MD0157PA00X+061890Y-038268X0315Y0000R000S3
|
||||||
|
317/CS VIA MD0157PA00X+061890Y-036929X0315Y0000R000S3
|
||||||
|
317/MISO VIA MD0157PA00X+062283Y-038268X0315Y0000R000S3
|
||||||
|
317/MISO VIA MD0157PA00X+062283Y-036929X0315Y0000R000S3
|
||||||
|
317GND VIA MD0394PA00X+059055Y-032756X0787Y0000R000S3
|
||||||
|
317/RST VIA MD0157PA00X+061614Y-033391X0315Y0000R000S3
|
||||||
|
317/SWDIO VIA MD0157PA00X+060945Y-033268X0315Y0000R000S3
|
||||||
|
317/SWCLK VIA MD0157PA00X+061339Y-033110X0315Y0000R000S3
|
||||||
|
317VCC VIA MD0157PA00X+061890Y-034316X0315Y0000R000S3
|
||||||
|
317+1V1 VIA MD0157PA00X+060000Y-032992X0315Y0000R000S3
|
||||||
|
367N/C REF** D1260UA00X+062992Y-045669X1260Y0000R000S3
|
||||||
|
327GND C1 -1 A02X+058553Y-038189X0463Y0571R000S1
|
||||||
|
327ET-(U1-GPIO24) C1 -2 A02X+059370Y-038189X0463Y0571R000S1
|
||||||
|
327/RST SW3 -1 A02X+060295Y-041142X0669Y0394R180S1
|
||||||
|
327/RST SW3 -1 A02X+057815Y-041142X0669Y0394R180S1
|
||||||
|
327GND SW3 -2 A02X+057815Y-042638X0669Y0394R180S1
|
||||||
|
327GND SW3 -2 A02X+060295Y-042638X0669Y0394R180S1
|
||||||
|
327/BOOT SW2 -1 A02X+051443Y-033414X0669Y0394R315S1
|
||||||
|
327/BOOT SW2 -1 A02X+053197Y-031660X0669Y0394R315S1
|
||||||
|
327GND SW2 -2 A02X+052139Y-030602X0669Y0394R315S1
|
||||||
|
327GND SW2 -2 A02X+050385Y-032356X0669Y0394R315S1
|
||||||
|
327NET-(U1-XIN) Y1 -1 A01X+063071Y-033504X0787Y0945R090S2
|
||||||
|
327NET-(C16-PAD1) Y1 -2 A01X+063071Y-034961X0787Y0945R090S2
|
||||||
|
327+BATT U3 -1 A02X+056122Y-045748X0614Y0256R270S1
|
||||||
|
327GND U3 -2 A02X+055748Y-045748X0614Y0256R270S1
|
||||||
|
327+BATT U3 -3 A02X+055374Y-045748X0614Y0256R270S1
|
||||||
|
327NET-(U3-NC) U3 -4 A02X+055374Y-044685X0614Y0256R270S1
|
||||||
|
327VCC U3 -5 A02X+056122Y-044685X0614Y0256R270S1
|
||||||
|
327T-(U1-QSPI_SS) U2 -1 A02X+054289Y-029213X0630Y0236R090S1
|
||||||
|
327-(U1-QSPI_SD1) U2 -2 A02X+054789Y-029213X0630Y0236R090S1
|
||||||
|
327-(U1-QSPI_SD2) U2 -3 A02X+055289Y-029213X0630Y0236R090S1
|
||||||
|
327GND U2 -4 A02X+055789Y-029213X0630Y0236R090S1
|
||||||
|
327-(U1-QSPI_SD0) U2 -5 A02X+055789Y-032047X0630Y0236R090S1
|
||||||
|
327(U1-QSPI_SCLK) U2 -6 A02X+055289Y-032047X0630Y0236R090S1
|
||||||
|
327-(U1-QSPI_SD3) U2 -7 A02X+054789Y-032047X0630Y0236R090S1
|
||||||
|
327VCC U2 -8 A02X+054289Y-032047X0630Y0236R090S1
|
||||||
|
327VCC U1 -1 A02X+058031Y-031403X0344Y0079R090S1
|
||||||
|
327/TX U1 -2 A02X+058189Y-031403X0344Y0079R090S1
|
||||||
|
327/RX U1 -3 A02X+058346Y-031403X0344Y0079R090S1
|
||||||
|
327/NEOPIXEL U1 -4 A02X+058504Y-031403X0344Y0079R090S1
|
||||||
|
327/BUZZ U1 -5 A02X+058661Y-031403X0344Y0079R090S1
|
||||||
|
327/SDA U1 -6 A02X+058819Y-031403X0344Y0079R090S1
|
||||||
|
327/SCL U1 -7 A02X+058976Y-031403X0344Y0079R090S1
|
||||||
|
327ET-(J7-PIN_10) U1 -8 A02X+059134Y-031403X0344Y0079R090S1
|
||||||
|
327NET-(J7-PIN_8) U1 -9 A02X+059291Y-031403X0344Y0079R090S1
|
||||||
|
327VCC U1 -10 A02X+059449Y-031403X0344Y0079R090S1
|
||||||
|
327NET-(J7-PIN_6) U1 -11 A02X+059606Y-031403X0344Y0079R090S1
|
||||||
|
327NET-(J7-PIN_4) U1 -12 A02X+059764Y-031403X0344Y0079R090S1
|
||||||
|
327NET-(J7-PIN_2) U1 -13 A02X+059921Y-031403X0344Y0079R090S1
|
||||||
|
327NET-(J7-PIN_1) U1 -14 A02X+060079Y-031403X0344Y0079R090S1
|
||||||
|
327NET-(J7-PIN_3) U1 -15 A02X+060408Y-031732X0079Y0344R090S1
|
||||||
|
327NET-(J7-PIN_5) U1 -16 A02X+060408Y-031890X0079Y0344R090S1
|
||||||
|
327NET-(J7-PIN_7) U1 -17 A02X+060408Y-032047X0079Y0344R090S1
|
||||||
|
327NET-(J7-PIN_9) U1 -18 A02X+060408Y-032205X0079Y0344R090S1
|
||||||
|
327GND U1 -19 A02X+060408Y-032362X0079Y0344R090S1
|
||||||
|
327NET-(U1-XIN) U1 -20 A02X+060408Y-032520X0079Y0344R090S1
|
||||||
|
327NET-(U1-XOUT) U1 -21 A02X+060408Y-032677X0079Y0344R090S1
|
||||||
|
327VCC U1 -22 A02X+060408Y-032835X0079Y0344R090S1
|
||||||
|
327+1V1 U1 -23 A02X+060408Y-032992X0079Y0344R090S1
|
||||||
|
327/SWCLK U1 -24 A02X+060408Y-033150X0079Y0344R090S1
|
||||||
|
327/SWDIO U1 -25 A02X+060408Y-033307X0079Y0344R090S1
|
||||||
|
327/RST U1 -26 A02X+060408Y-033465X0079Y0344R090S1
|
||||||
|
327/MISO U1 -27 A02X+060408Y-033622X0079Y0344R090S1
|
||||||
|
327/CS U1 -28 A02X+060408Y-033780X0079Y0344R090S1
|
||||||
|
327/CLK U1 -29 A02X+060079Y-034109X0344Y0079R090S1
|
||||||
|
327/MOSI U1 -30 A02X+059921Y-034109X0344Y0079R090S1
|
||||||
|
327NET-(J8-PIN_1) U1 -31 A02X+059764Y-034109X0344Y0079R090S1
|
||||||
|
327NET-(J8-PIN_2) U1 -32 A02X+059606Y-034109X0344Y0079R090S1
|
||||||
|
327VCC U1 -33 A02X+059449Y-034109X0344Y0079R090S1
|
||||||
|
327NET-(J8-PIN_3) U1 -34 A02X+059291Y-034109X0344Y0079R090S1
|
||||||
|
327/CHRG U1 -35 A02X+059134Y-034109X0344Y0079R090S1
|
||||||
|
327ET-(U1-GPIO24) U1 -36 A02X+058976Y-034109X0344Y0079R090S1
|
||||||
|
327NET-(D2-A) U1 -37 A02X+058819Y-034109X0344Y0079R090S1
|
||||||
|
327/V_BATT U1 -38 A02X+058661Y-034109X0344Y0079R090S1
|
||||||
|
327NET-(J9-PIN_1) U1 -39 A02X+058504Y-034109X0344Y0079R090S1
|
||||||
|
327NET-(J9-PIN_2) U1 -40 A02X+058346Y-034109X0344Y0079R090S1
|
||||||
|
327NET-(J9-PIN_3) U1 -41 A02X+058189Y-034109X0344Y0079R090S1
|
||||||
|
327VCC U1 -42 A02X+058031Y-034109X0344Y0079R090S1
|
||||||
|
327VCC U1 -43 A02X+057702Y-033780X0079Y0344R090S1
|
||||||
|
327VCC U1 -44 A02X+057702Y-033622X0079Y0344R090S1
|
||||||
|
327+1V1 U1 -45 A02X+057702Y-033465X0079Y0344R090S1
|
||||||
|
327/DN U1 -46 A02X+057702Y-033307X0079Y0344R090S1
|
||||||
|
327/DP U1 -47 A02X+057702Y-033150X0079Y0344R090S1
|
||||||
|
327VCC U1 -48 A02X+057702Y-032992X0079Y0344R090S1
|
||||||
|
327VCC U1 -49 A02X+057702Y-032835X0079Y0344R090S1
|
||||||
|
327+1V1 U1 -50 A02X+057702Y-032677X0079Y0344R090S1
|
||||||
|
327-(U1-QSPI_SD3) U1 -51 A02X+057702Y-032520X0079Y0344R090S1
|
||||||
|
327(U1-QSPI_SCLK) U1 -52 A02X+057702Y-032362X0079Y0344R090S1
|
||||||
|
327-(U1-QSPI_SD0) U1 -53 A02X+057702Y-032205X0079Y0344R090S1
|
||||||
|
327-(U1-QSPI_SD2) U1 -54 A02X+057702Y-032047X0079Y0344R090S1
|
||||||
|
327-(U1-QSPI_SD1) U1 -55 A02X+057702Y-031890X0079Y0344R090S1
|
||||||
|
327T-(U1-QSPI_SS) U1 -56 A02X+057702Y-031732X0079Y0344R090S1
|
||||||
|
327GND U1 -57 A02X+059055Y-032756X1260Y1260R090S1
|
||||||
|
367N/C SW1 D1575UA00X+059055Y-039370X1575Y0000R000S0
|
||||||
|
367N/C SW1 D0669UA00X+057055Y-039370X0669Y0000R000S0
|
||||||
|
367N/C SW1 D0669UA00X+061055Y-039370X0669Y0000R000S0
|
||||||
|
317ET-(U1-GPIO24) SW1 -1 D0591PA00X+060055Y-037370X0866Y0000R000S0
|
||||||
|
317GND SW1 -2 D0591PA00X+057555Y-038370X0866Y0000R000S0
|
||||||
|
327/BUZZ R15 -1 A02X+058425Y-044646X0472Y0551R000S1
|
||||||
|
327GND R15 -2 A02X+059213Y-044646X0472Y0551R000S1
|
||||||
|
327NET-(D2-K) R14 -1 A02X+049055Y-036772X0472Y0551R180S1
|
||||||
|
327GND R14 -2 A02X+048268Y-036772X0472Y0551R180S1
|
||||||
|
327VCC R13 -1 A02X+061102Y-038268X0472Y0551R180S1
|
||||||
|
327ET-(U1-GPIO24) R13 -2 A02X+060315Y-038268X0472Y0551R180S1
|
||||||
|
327NET-(Q1-D) R12 -1 A02X+051496Y-041890X0472Y0551R000S1
|
||||||
|
327+5V R12 -2 A02X+052283Y-041890X0472Y0551R000S1
|
||||||
|
327/CHRG R11 -1 A02X+049134Y-042598X0472Y0551R270S1
|
||||||
|
327GND R11 -2 A02X+049134Y-041811X0472Y0551R270S1
|
||||||
|
327/V_BATT R10 -1 A02X+053465Y-044094X0472Y0551R000S1
|
||||||
|
327GND R10 -2 A02X+054252Y-044094X0472Y0551R000S1
|
||||||
|
327/BOOT R9 -1 A01X+054173Y-035118X0472Y0551R270S2
|
||||||
|
327T-(U1-QSPI_SS) R9 -2 A01X+054173Y-034331X0472Y0551R270S2
|
||||||
|
327T-(U1-QSPI_SS) R8 -1 A01X+055039Y-033465X0472Y0551R270S2
|
||||||
|
327VCC R8 -2 A01X+055039Y-032677X0472Y0551R270S2
|
||||||
|
327GND R7 -1 A02X+051732Y-037402X0472Y0551R090S1
|
||||||
|
327NET-(J1-CC2) R7 -2 A02X+051732Y-038189X0472Y0551R090S1
|
||||||
|
327/DP R6 -1 A02X+052756Y-038898X0472Y0551R180S1
|
||||||
|
327NET-(D1-IO2) R6 -2 A02X+051969Y-038898X0472Y0551R180S1
|
||||||
|
327NET-(D1-IO1) R5 -1 A02X+051969Y-039685X0472Y0551R000S1
|
||||||
|
327/DN R5 -2 A02X+052756Y-039685X0472Y0551R000S1
|
||||||
|
327/RST R4 -2 A01X+061811Y-033465X0472Y0551R090S2
|
||||||
|
327VCC R4 -1 A01X+061811Y-032677X0472Y0551R090S2
|
||||||
|
327NET-(C16-PAD1) R3 -1 A02X+062520Y-033937X0472Y0551R270S1
|
||||||
|
327NET-(U1-XOUT) R3 -2 A02X+062520Y-033150X0472Y0551R270S1
|
||||||
|
327+BATT R2 -1 A02X+051969Y-044094X0472Y0551R000S1
|
||||||
|
327/V_BATT R2 -2 A02X+052756Y-044094X0472Y0551R000S1
|
||||||
|
327GND R1 -1 A02X+051732Y-041181X0472Y0551R270S1
|
||||||
|
327NET-(J1-CC1) R1 -2 A02X+051732Y-040394X0472Y0551R270S1
|
||||||
|
327/BUZZ Q3 -1 A02X+058898Y-046181X0581Y0236R000S1
|
||||||
|
327GND Q3 -2 A02X+058898Y-045433X0581Y0236R000S1
|
||||||
|
327NET-(BZ1--) Q3 -3 A02X+059636Y-045807X0581Y0236R000S1
|
||||||
|
327+BATT Q2 -1 A02X+051843Y-043346X0276Y0201R000S1
|
||||||
|
327+BATT Q2 -2 A02X+051843Y-042972X0276Y0201R000S1
|
||||||
|
327NET-(Q1-D) Q2 -3 A02X+051843Y-042598X0276Y0201R000S1
|
||||||
|
327+5V Q2 -4 A02X+052756Y-042598X0276Y0201R000S1
|
||||||
|
327+BATT Q2 -5 A02X+052756Y-042972X0276Y0201R000S1
|
||||||
|
327+BATT Q2 -6 A02X+052756Y-043346X0276Y0201R000S1
|
||||||
|
327/CHRG Q1 -1 A02X+049970Y-042579X0581Y0236R000S1
|
||||||
|
327GND Q1 -2 A02X+049970Y-041831X0581Y0236R000S1
|
||||||
|
327NET-(Q1-D) Q1 -3 A02X+050709Y-042205X0581Y0236R000S1
|
||||||
|
327+5V JP1 -1 A02X+053543Y-042736X0394Y0197R090S1
|
||||||
|
327+BATT JP1 -2 A02X+053543Y-043248X0394Y0197R090S1
|
||||||
|
317NET-(J9-PIN_1) J9 -1 D0394PA00X+054094Y-037352X0669Y0669R000S0
|
||||||
|
317NET-(J9-PIN_2) J9 -2 D0394PA00X+054094Y-038352X0669Y0669R000S0
|
||||||
|
317NET-(J9-PIN_3) J9 -3 D0394PA00X+054094Y-039352X0669Y0669R000S0
|
||||||
|
317NET-(J8-PIN_1) J8 -1 D0394PA00X+055591Y-039323X0669Y0669R180S0
|
||||||
|
317NET-(J8-PIN_2) J8 -2 D0394PA00X+055591Y-038323X0669Y0669R180S0
|
||||||
|
317NET-(J8-PIN_3) J8 -3 D0394PA00X+055591Y-037323X0669Y0669R180S0
|
||||||
|
317NET-(J7-PIN_1) J7 -1 D0394PA00X+069299Y-038898X0669Y0669R090S0
|
||||||
|
317NET-(J7-PIN_2) J7 -2 D0394PA00X+069299Y-039898X0669Y0669R090S0
|
||||||
|
317NET-(J7-PIN_3) J7 -3 D0394PA00X+068299Y-038898X0669Y0669R090S0
|
||||||
|
317NET-(J7-PIN_4) J7 -4 D0394PA00X+068299Y-039898X0669Y0669R090S0
|
||||||
|
317NET-(J7-PIN_5) J7 -5 D0394PA00X+067299Y-038898X0669Y0669R090S0
|
||||||
|
317NET-(J7-PIN_6) J7 -6 D0394PA00X+067299Y-039898X0669Y0669R090S0
|
||||||
|
317NET-(J7-PIN_7) J7 -7 D0394PA00X+066299Y-038898X0669Y0669R090S0
|
||||||
|
317NET-(J7-PIN_8) J7 -8 D0394PA00X+066299Y-039898X0669Y0669R090S0
|
||||||
|
317NET-(J7-PIN_9) J7 -9 D0394PA00X+065299Y-038898X0669Y0669R090S0
|
||||||
|
317ET-(J7-PIN_10) J7 -10 D0394PA00X+065299Y-039898X0669Y0669R090S0
|
||||||
|
317VCC J6 -1 D0394PA00X+066535Y-041417X0669Y0669R000S0
|
||||||
|
317/RX J6 -2 D0394PA00X+066535Y-042417X0669Y0669R000S0
|
||||||
|
317/TX J6 -3 D0394PA00X+066535Y-043417X0669Y0669R000S0
|
||||||
|
317GND J6 -4 D0394PA00X+066535Y-044417X0669Y0669R000S0
|
||||||
|
317GND J5 -4 D0394PA00X+065118Y-044417X0669Y0669R000S0
|
||||||
|
317/SDA J5 -3 D0394PA00X+065118Y-043417X0669Y0669R000S0
|
||||||
|
317/SCL J5 -2 D0394PA00X+065118Y-042417X0669Y0669R000S0
|
||||||
|
317VCC J5 -1 D0394PA00X+065118Y-041417X0669Y0669R000S0
|
||||||
|
317VCC J4 -1 D0394PA00X+063701Y-036811X0669Y0669R000S0
|
||||||
|
317/MOSI J4 -2 D0394PA00X+063701Y-037811X0669Y0669R000S0
|
||||||
|
317/CLK J4 -3 D0394PA00X+063701Y-038811X0669Y0669R000S0
|
||||||
|
317/CS J4 -4 D0394PA00X+063701Y-039811X0669Y0669R000S0
|
||||||
|
317/MISO J4 -5 D0394PA00X+063701Y-040811X0669Y0669R000S0
|
||||||
|
317GND J4 -6 D0394PA00X+063701Y-041811X0669Y0669R000S0
|
||||||
|
317/SWCLK J3 -1 D0394PA00X+063278Y-029370X0669Y0669R090S0
|
||||||
|
317GND J3 -2 D0394PA00X+062278Y-029370X0669Y0669R090S0
|
||||||
|
317/SWDIO J3 -3 D0394PA00X+061278Y-029370X0669Y0669R090S0
|
||||||
|
317+BATT J2 -1 D0394PA00X+052701Y-044961X0669Y0669R270S0
|
||||||
|
317GND J2 -2 D0394PA00X+053701Y-044961X0669Y0669R270S0
|
||||||
|
367N/C J1 D0256UA00X+050236Y-038232X0256Y0000R270S0
|
||||||
|
367N/C J1 D0256UA00X+050236Y-040508X0256Y0000R270S0
|
||||||
|
327GND J1 -A1 A02X+050805Y-040650X0236Y0571R270S1
|
||||||
|
327+5V J1 -A4 A02X+050805Y-040335X0236Y0571R270S1
|
||||||
|
327NET-(J1-CC1) J1 -A5 A02X+050805Y-039862X0118Y0571R270S1
|
||||||
|
327NET-(D1-IO2) J1 -A6 A02X+050805Y-039469X0118Y0571R270S1
|
||||||
|
327NET-(D1-IO1) J1 -A7 A02X+050805Y-039272X0118Y0571R270S1
|
||||||
|
327J1-SBU1-PADA8) J1 -A8 A02X+050805Y-038878X0118Y0571R270S1
|
||||||
|
327+5V J1 -A9 A02X+050805Y-038406X0236Y0571R270S1
|
||||||
|
327GND J1 -A12 A02X+050805Y-038091X0236Y0571R270S1
|
||||||
|
327GND J1 -B1 A02X+050805Y-038091X0236Y0571R270S1
|
||||||
|
327+5V J1 -B4 A02X+050805Y-038406X0236Y0571R270S1
|
||||||
|
327NET-(J1-CC2) J1 -B5 A02X+050805Y-038681X0118Y0571R270S1
|
||||||
|
327NET-(D1-IO2) J1 -B6 A02X+050805Y-039075X0118Y0571R270S1
|
||||||
|
327NET-(D1-IO1) J1 -B7 A02X+050805Y-039665X0118Y0571R270S1
|
||||||
|
327J1-SBU2-PADB8) J1 -B8 A02X+050805Y-040059X0118Y0571R270S1
|
||||||
|
327+5V J1 -B9 A02X+050805Y-040335X0236Y0571R270S1
|
||||||
|
327GND J1 -B12 A02X+050805Y-040650X0236Y0571R270S1
|
||||||
|
317GND J1 -S1 D0236PA00X+048799Y-041071X0394Y0630R270S0
|
||||||
|
317GND J1 -S1 D0236PA00X+050445Y-041071X0394Y0827R270S0
|
||||||
|
317GND J1 -S1 D0236PA00X+050445Y-037669X0394Y0827R270S0
|
||||||
|
317GND J1 -S1 D0236PA00X+048799Y-037669X0394Y0630R270S0
|
||||||
|
327+BATT D12 -1 A01X+063909Y-047691X0591Y0354R324S2
|
||||||
|
327D12-DOUT-PAD2) D12 -2 A01X+064672Y-048742X0591Y0354R324S2
|
||||||
|
327GND D12 -3 A01X+066233Y-047608X0591Y0354R324S2
|
||||||
|
327NET-(D11-DOUT) D12 -4 A01X+065469Y-046557X0591Y0354R324S2
|
||||||
|
327+BATT D11 -1 A01X+067860Y-043268X0591Y0354R288S2
|
||||||
|
327NET-(D11-DOUT) D11 -2 A01X+069095Y-043669X0591Y0354R288S2
|
||||||
|
327GND D11 -3 A01X+069691Y-041835X0591Y0354R288S2
|
||||||
|
327NET-(D10-DOUT) D11 -4 A01X+068456Y-041433X0591Y0354R288S2
|
||||||
|
327+BATT D10 -1 A01X+068476Y-037311X0591Y0354R252S2
|
||||||
|
327NET-(D10-DOUT) D10 -2 A01X+069711Y-036910X0591Y0354R252S2
|
||||||
|
327GND D10 -3 A01X+069115Y-035075X0591Y0354R252S2
|
||||||
|
327NET-(D10-DIN) D10 -4 A01X+067879Y-035476X0591Y0354R252S2
|
||||||
|
327+BATT D9 -1 A01X+065477Y-032191X0591Y0354R216S2
|
||||||
|
327NET-(D10-DIN) D9 -2 A01X+066241Y-031140X0591Y0354R216S2
|
||||||
|
327GND D9 -3 A01X+064680Y-030006X0591Y0354R216S2
|
||||||
|
327NET-(D8-DOUT) D9 -4 A01X+063917Y-031057X0591Y0354R216S2
|
||||||
|
327+BATT D8 -1 A01X+060024Y-029780X0591Y0354R180S2
|
||||||
|
327NET-(D8-DOUT) D8 -2 A01X+060024Y-028480X0591Y0354R180S2
|
||||||
|
327GND D8 -3 A01X+058094Y-028480X0591Y0354R180S2
|
||||||
|
327NET-(D7-DOUT) D8 -4 A01X+058094Y-029780X0591Y0354R180S2
|
||||||
|
327+BATT D7 -1 A01X+054190Y-031049X0591Y0354R144S2
|
||||||
|
327NET-(D7-DOUT) D7 -2 A01X+053426Y-029998X0591Y0354R144S2
|
||||||
|
327GND D7 -3 A01X+051865Y-031132X0591Y0354R144S2
|
||||||
|
327NET-(D6-DOUT) D7 -4 A01X+052629Y-032183X0591Y0354R144S2
|
||||||
|
327+BATT D6 -1 A01X+050235Y-035484X0591Y0354R108S2
|
||||||
|
327NET-(D6-DOUT) D6 -2 A01X+048999Y-035083X0591Y0354R108S2
|
||||||
|
327GND D6 -3 A01X+048403Y-036917X0591Y0354R108S2
|
||||||
|
327NET-(D5-DOUT) D6 -4 A01X+049639Y-037319X0591Y0354R108S2
|
||||||
|
327+BATT D5 -1 A01X+049639Y-041409X0591Y0354R072S2
|
||||||
|
327NET-(D5-DOUT) D5 -2 A01X+048403Y-041811X0591Y0354R072S2
|
||||||
|
327GND D5 -3 A01X+048999Y-043646X0591Y0354R072S2
|
||||||
|
327NET-(D4-DOUT) D5 -4 A01X+050235Y-043244X0591Y0354R072S2
|
||||||
|
327+BATT D4 -1 A01X+052645Y-046530X0591Y0354R036S2
|
||||||
|
327NET-(D4-DOUT) D4 -2 A01X+051881Y-047581X0591Y0354R036S2
|
||||||
|
327GND D4 -3 A01X+053442Y-048715X0591Y0354R036S2
|
||||||
|
327NET-(D3-DOUT) D4 -4 A01X+054205Y-047663X0591Y0354R036S2
|
||||||
|
327+BATT D3 -1 A01X+058091Y-048957X0591Y0354R000S2
|
||||||
|
327NET-(D3-DOUT) D3 -2 A01X+058091Y-050256X0591Y0354R000S2
|
||||||
|
327GND D3 -3 A01X+060020Y-050256X0591Y0354R000S2
|
||||||
|
327/NEOPIXEL D3 -4 A01X+060020Y-048957X0591Y0354R000S2
|
||||||
|
327NET-(D2-A) D2 -2 A02X+050945Y-036772X0492Y0689R000S1
|
||||||
|
327NET-(D2-K) D2 -1 A02X+049843Y-036772X0492Y0689R000S1
|
||||||
|
327NET-(D1-IO1) D1 -1 A01X+049504Y-039557X0248Y0177R180S2
|
||||||
|
327NET-(D1-IO2) D1 -2 A01X+049504Y-039183X0248Y0177R180S2
|
||||||
|
327GND D1 -3 A01X+049504Y-038809X0248Y0177R180S2
|
||||||
|
327-(D1-IO3-PAD4) D1 -4 A01X+048449Y-038809X0248Y0177R180S2
|
||||||
|
327+5V D1 -5 A01X+048449Y-039183X0248Y0177R180S2
|
||||||
|
327N/C D1 -6 A01X+048449Y-039557X0248Y0177R180S2
|
||||||
|
327N/C D1 -7 A01X+049134Y-039390X0315Y0413R180S2
|
||||||
|
327N/C D1 -7 A01X+048819Y-038976X0315Y0413R180S2
|
||||||
|
327N/C D1 -7 A01X+048819Y-039390X0315Y0413R180S2
|
||||||
|
327N/C D1 -7 A01X+049134Y-038976X0315Y0413R180S2
|
||||||
|
327GND C17 -2 A01X+054252Y-033479X0463Y0571R090S2
|
||||||
|
327VCC C17 -1 A01X+054252Y-032662X0463Y0571R090S2
|
||||||
|
327NET-(C16-PAD1) C16 -1 A01X+064252Y-035290X0463Y0571R270S2
|
||||||
|
327GND C16 -2 A01X+064252Y-034473X0463Y0571R270S2
|
||||||
|
327NET-(U1-XIN) C15 -1 A01X+064252Y-032977X0463Y0571R090S2
|
||||||
|
327GND C15 -2 A01X+064252Y-033794X0463Y0571R090S2
|
||||||
|
327GND C14 -1 A01X+058110Y-035133X0463Y0571R270S2
|
||||||
|
327VCC C14 -2 A01X+058110Y-034316X0463Y0571R270S2
|
||||||
|
327GND C13 -1 A01X+054961Y-035133X0463Y0571R270S2
|
||||||
|
327+1V1 C13 -2 A01X+054961Y-034316X0463Y0571R270S2
|
||||||
|
327GND C12 -1 A01X+057323Y-035133X0463Y0571R270S2
|
||||||
|
327VCC C12 -2 A01X+057323Y-034316X0463Y0571R270S2
|
||||||
|
327GND C11 -1 A01X+056535Y-035133X0463Y0571R270S2
|
||||||
|
327VCC C11 -2 A01X+056535Y-034316X0463Y0571R270S2
|
||||||
|
327GND C10 -1 A01X+058583Y-032613X0463Y0571R270S2
|
||||||
|
327VCC C10 -2 A01X+058583Y-031796X0463Y0571R270S2
|
||||||
|
327GND C9 -1 A01X+061102Y-035133X0463Y0571R270S2
|
||||||
|
327+1V1 C9 -2 A01X+061102Y-034316X0463Y0571R270S2
|
||||||
|
327GND C8 -1 A01X+055748Y-035133X0463Y0571R270S2
|
||||||
|
327+1V1 C8 -2 A01X+055748Y-034316X0463Y0571R270S2
|
||||||
|
327GND C7 -1 A01X+059449Y-035133X0463Y0571R270S2
|
||||||
|
327VCC C7 -2 A01X+059449Y-034316X0463Y0571R270S2
|
||||||
|
327GND C6 -1 A01X+061890Y-035133X0463Y0571R270S2
|
||||||
|
327VCC C6 -2 A01X+061890Y-034316X0463Y0571R270S2
|
||||||
|
327VCC C5 -2 A01X+059370Y-031796X0463Y0571R270S2
|
||||||
|
327GND C5 -1 A01X+059370Y-032613X0463Y0571R270S2
|
||||||
|
327VCC C4 -1 A02X+056220Y-043873X0463Y0571R270S1
|
||||||
|
327GND C4 -2 A02X+056220Y-043056X0463Y0571R270S1
|
||||||
|
327NET-(U3-NC) C3 -1 A02X+055433Y-043873X0463Y0571R270S1
|
||||||
|
327GND C3 -2 A02X+055433Y-043056X0463Y0571R270S1
|
||||||
|
327+BATT C2 -1 A02X+054646Y-045827X0463Y0571R270S1
|
||||||
|
327GND C2 -2 A02X+054646Y-045010X0463Y0571R270S1
|
||||||
|
317VCC BZ1 -1 D0394PA00X+057559Y-045827X0787Y0787R000S0
|
||||||
|
317NET-(BZ1--) BZ1 -2 D0394PA00X+060551Y-045827X0787Y0000R000S0
|
||||||
|
999
|
65
HW/timer_button/production/positions.csv
Normal file
65
HW/timer_button/production/positions.csv
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
Designator,Mid X,Mid Y,Rotation,Layer
|
||||||
|
BZ1,146.2,-116.4,0.0,top
|
||||||
|
C1,149.7625,-97.0,0.0,bottom
|
||||||
|
C10,148.8,-81.8,90.0,top
|
||||||
|
C11,143.6,-88.2,90.0,top
|
||||||
|
C12,145.6,-88.2,90.0,top
|
||||||
|
C13,139.6,-88.2,90.0,top
|
||||||
|
C14,147.6,-88.2,90.0,top
|
||||||
|
C15,163.2,-84.8,270.0,top
|
||||||
|
C16,163.2,-88.6,90.0,top
|
||||||
|
C17,137.8,-84.0,270.0,top
|
||||||
|
C2,138.8,-115.3625,90.0,bottom
|
||||||
|
C3,140.8,-110.4,90.0,bottom
|
||||||
|
C4,142.8,-110.4,90.0,bottom
|
||||||
|
C5,150.8,-81.8,90.0,top
|
||||||
|
C6,157.2,-88.2,90.0,top
|
||||||
|
C7,151.0,-88.2,90.0,top
|
||||||
|
C8,141.6,-88.2,90.0,top
|
||||||
|
C9,155.2,-88.2,90.0,top
|
||||||
|
D1,124.4,-99.525,180.0,top
|
||||||
|
D10,174.74,-91.93,108.0,top
|
||||||
|
D11,174.69,-108.08,72.0,top
|
||||||
|
D12,165.28,-121.03,36.0,top
|
||||||
|
D2,128.0,-93.4,0.0,bottom
|
||||||
|
D3,150.0,-126.0,0.0,top
|
||||||
|
D4,134.73,-120.96,324.0,top
|
||||||
|
D5,125.27,-108.02,288.0,top
|
||||||
|
D6,125.27,-91.95,252.0,top
|
||||||
|
D7,134.69,-78.97,216.0,top
|
||||||
|
D8,150.01,-73.99,180.0,top
|
||||||
|
D9,165.3,-78.99,144.0,top
|
||||||
|
J1,125.0,-100.0,90.0,bottom
|
||||||
|
J2,133.86,-114.2,90.0,top
|
||||||
|
J3,160.725,-74.6,270.0,top
|
||||||
|
J4,161.8,-93.5,0.0,top
|
||||||
|
J5,165.4,-105.2,0.0,top
|
||||||
|
J6,169.0,-105.2,0.0,top
|
||||||
|
J7,176.02,-98.8,270.0,top
|
||||||
|
J8,141.2,-99.88,180.0,top
|
||||||
|
J9,137.4,-94.875,0.0,top
|
||||||
|
Q1,127.8625,-107.2,0.0,bottom
|
||||||
|
Q2,132.84,-109.15,0.0,bottom
|
||||||
|
Q3,150.5375,-116.35,0.0,bottom
|
||||||
|
R1,131.4,-103.6,90.0,bottom
|
||||||
|
R10,136.8,-112.0,0.0,bottom
|
||||||
|
R11,124.8,-107.2,90.0,bottom
|
||||||
|
R12,131.8,-106.4,0.0,bottom
|
||||||
|
R13,154.2,-97.2,180.0,bottom
|
||||||
|
R14,123.6,-93.4,180.0,bottom
|
||||||
|
R15,149.4,-113.4,0.0,bottom
|
||||||
|
R2,133.0,-112.0,0.0,bottom
|
||||||
|
R3,158.8,-85.2,90.0,bottom
|
||||||
|
R4,157.0,-84.0,270.0,top
|
||||||
|
R5,133.0,-100.8,0.0,bottom
|
||||||
|
R6,133.0,-98.8,180.0,bottom
|
||||||
|
R7,131.4,-96.0,270.0,bottom
|
||||||
|
R8,139.8,-84.0,90.0,top
|
||||||
|
R9,137.6,-88.2,90.0,top
|
||||||
|
SW1,152.54,-94.92,0.0,top
|
||||||
|
SW2,131.55,-81.3,45.0,bottom
|
||||||
|
SW3,150.0,-106.4,180.0,bottom
|
||||||
|
U1,150.0,-83.2,270.0,bottom
|
||||||
|
U2,139.8,-77.8,270.0,bottom
|
||||||
|
U3,141.6,-114.85,90.0,bottom
|
||||||
|
Y1,160.2,-86.95,270.0,top
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
19300
HW/timer_button/timer_button.kicad_pcb
Normal file
19300
HW/timer_button/timer_button.kicad_pcb
Normal file
File diff suppressed because it is too large
Load Diff
77
HW/timer_button/timer_button.kicad_prl
Normal file
77
HW/timer_button/timer_button.kicad_prl
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
{
|
||||||
|
"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": 0.6,
|
||||||
|
"pads": 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": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
8,
|
||||||
|
9,
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
19,
|
||||||
|
20,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
23,
|
||||||
|
24,
|
||||||
|
25,
|
||||||
|
26,
|
||||||
|
27,
|
||||||
|
28,
|
||||||
|
29,
|
||||||
|
30,
|
||||||
|
32,
|
||||||
|
33,
|
||||||
|
34,
|
||||||
|
35,
|
||||||
|
36,
|
||||||
|
39,
|
||||||
|
40
|
||||||
|
],
|
||||||
|
"visible_layers": "ffffdff_ffffffff",
|
||||||
|
"zone_display_mode": 0
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"filename": "timer_button.kicad_prl",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"project": {
|
||||||
|
"files": []
|
||||||
|
}
|
||||||
|
}
|
492
HW/timer_button/timer_button.kicad_pro
Normal file
492
HW/timer_button/timer_button.kicad_pro
Normal file
@ -0,0 +1,492 @@
|
|||||||
|
{
|
||||||
|
"board": {
|
||||||
|
"3dviewports": [],
|
||||||
|
"design_settings": {
|
||||||
|
"defaults": {
|
||||||
|
"board_outline_line_width": 0.09999999999999999,
|
||||||
|
"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.15,
|
||||||
|
"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": 3.2,
|
||||||
|
"height": 3.2,
|
||||||
|
"width": 3.2
|
||||||
|
},
|
||||||
|
"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": {
|
||||||
|
"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",
|
||||||
|
"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_type_mismatch": "ignore",
|
||||||
|
"hole_clearance": "error",
|
||||||
|
"hole_near_hole": "error",
|
||||||
|
"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",
|
||||||
|
"missing_courtyard": "ignore",
|
||||||
|
"missing_footprint": "warning",
|
||||||
|
"net_conflict": "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_thickness": "warning",
|
||||||
|
"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",
|
||||||
|
"zones_intersect": "error"
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"max_error": 0.005,
|
||||||
|
"min_clearance": 0.0,
|
||||||
|
"min_connection": 0.0,
|
||||||
|
"min_copper_edge_clearance": 0.0,
|
||||||
|
"min_hole_clearance": 0.25,
|
||||||
|
"min_hole_to_hole": 0.25,
|
||||||
|
"min_microvia_diameter": 0.19999999999999998,
|
||||||
|
"min_microvia_drill": 0.09999999999999999,
|
||||||
|
"min_resolved_spokes": 2,
|
||||||
|
"min_silk_clearance": 0.0,
|
||||||
|
"min_text_height": 0.7999999999999999,
|
||||||
|
"min_text_thickness": 0.08,
|
||||||
|
"min_through_hole_diameter": 0.3,
|
||||||
|
"min_track_width": 0.0,
|
||||||
|
"min_via_annular_width": 0.09999999999999999,
|
||||||
|
"min_via_diameter": 0.5,
|
||||||
|
"solder_mask_clearance": 0.0,
|
||||||
|
"solder_mask_min_width": 0.0,
|
||||||
|
"solder_mask_to_copper_clearance": 0.0,
|
||||||
|
"use_height_for_length_calcs": true
|
||||||
|
},
|
||||||
|
"teardrop_options": [
|
||||||
|
{
|
||||||
|
"td_allow_use_two_tracks": true,
|
||||||
|
"td_curve_segcount": 5,
|
||||||
|
"td_on_pad_in_zone": false,
|
||||||
|
"td_onpadsmd": true,
|
||||||
|
"td_onroundshapesonly": false,
|
||||||
|
"td_ontrackend": false,
|
||||||
|
"td_onviapad": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"teardrop_parameters": [
|
||||||
|
{
|
||||||
|
"td_curve_segcount": 0,
|
||||||
|
"td_height_ratio": 1.0,
|
||||||
|
"td_length_ratio": 0.5,
|
||||||
|
"td_maxheight": 2.0,
|
||||||
|
"td_maxlen": 1.0,
|
||||||
|
"td_target_name": "td_round_shape",
|
||||||
|
"td_width_to_size_filter_ratio": 0.9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"td_curve_segcount": 0,
|
||||||
|
"td_height_ratio": 1.0,
|
||||||
|
"td_length_ratio": 0.5,
|
||||||
|
"td_maxheight": 2.0,
|
||||||
|
"td_maxlen": 1.0,
|
||||||
|
"td_target_name": "td_rect_shape",
|
||||||
|
"td_width_to_size_filter_ratio": 0.9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"td_curve_segcount": 0,
|
||||||
|
"td_height_ratio": 1.0,
|
||||||
|
"td_length_ratio": 0.5,
|
||||||
|
"td_maxheight": 2.0,
|
||||||
|
"td_maxlen": 1.0,
|
||||||
|
"td_target_name": "td_track_end",
|
||||||
|
"td_width_to_size_filter_ratio": 0.9
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"track_widths": [
|
||||||
|
0.0,
|
||||||
|
0.2,
|
||||||
|
0.4
|
||||||
|
],
|
||||||
|
"via_dimensions": [
|
||||||
|
{
|
||||||
|
"diameter": 0.0,
|
||||||
|
"drill": 0.0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"zones_allow_external_fillets": false
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"conflicting_netclasses": "error",
|
||||||
|
"different_unit_footprint": "error",
|
||||||
|
"different_unit_net": "error",
|
||||||
|
"duplicate_reference": "error",
|
||||||
|
"duplicate_sheet_names": "error",
|
||||||
|
"endpoint_off_grid": "warning",
|
||||||
|
"extra_units": "error",
|
||||||
|
"global_label_dangling": "warning",
|
||||||
|
"hier_label_mismatch": "error",
|
||||||
|
"label_dangling": "error",
|
||||||
|
"lib_symbol_issues": "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",
|
||||||
|
"similar_labels": "warning",
|
||||||
|
"simulation_model_issue": "ignore",
|
||||||
|
"unannotated": "error",
|
||||||
|
"unit_value_mismatch": "error",
|
||||||
|
"unresolved_variable": "error",
|
||||||
|
"wire_dangling": "error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"libraries": {
|
||||||
|
"pinned_footprint_libs": [],
|
||||||
|
"pinned_symbol_libs": []
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"filename": "timer_button.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.25,
|
||||||
|
"via_diameter": 0.8,
|
||||||
|
"via_drill": 0.4,
|
||||||
|
"wire_width": 6
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"net_colors": null,
|
||||||
|
"netclass_assignments": null,
|
||||||
|
"netclass_patterns": []
|
||||||
|
},
|
||||||
|
"pcbnew": {
|
||||||
|
"last_paths": {
|
||||||
|
"gencad": "",
|
||||||
|
"idf": "",
|
||||||
|
"netlist": "",
|
||||||
|
"specctra_dsn": "",
|
||||||
|
"step": "",
|
||||||
|
"vrml": ""
|
||||||
|
},
|
||||||
|
"page_layout_descr_file": ""
|
||||||
|
},
|
||||||
|
"schematic": {
|
||||||
|
"annotate_start_num": 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,
|
||||||
|
"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": "",
|
||||||
|
"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_voltages": false,
|
||||||
|
"subpart_first_id": 65,
|
||||||
|
"subpart_id_separator": 0
|
||||||
|
},
|
||||||
|
"sheets": [
|
||||||
|
[
|
||||||
|
"4c88d864-5558-4972-998d-a249c51e3544",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"text_variables": {}
|
||||||
|
}
|
6221
HW/timer_button/timer_button.kicad_sch
Normal file
6221
HW/timer_button/timer_button.kicad_sch
Normal file
File diff suppressed because it is too large
Load Diff
1
POC_in_rust/.gitignore
vendored
1
POC_in_rust/.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
target
|
|
@ -1,21 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "POC_in_rust"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2024"
|
|
||||||
|
|
||||||
[profile.release]
|
|
||||||
opt-level="s"
|
|
||||||
lto="fat"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
async-tungstenite = {version="0.29.1", features=["tokio-rustls-webpki-roots"]}
|
|
||||||
chrono = "0.4.41"
|
|
||||||
env_logger = "0.11.8"
|
|
||||||
iced = {"git"= "https://github.com/iced-rs/iced.git", "features"=["tokio", "auto-detect-theme", "fira-sans", "tiny-skia", "sipper"]}
|
|
||||||
lazy_static = "1.5.0"
|
|
||||||
nusb = "0.1.13"
|
|
||||||
reqwest = { version = "0.12.15", features = ["json"] }
|
|
||||||
rustls = {version = "0.23.27", features = ["std", "prefer-post-quantum", "tls12", "logging"]}
|
|
||||||
serde = {version = "1.0.219", features=["derive"]}
|
|
||||||
serde_json = "1.0.140"
|
|
||||||
tokio = {version = "1.45.0", features=["time", "fs", "io-util", "macros"]}
|
|
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"DURATION": 600,
|
|
||||||
"STATION_ID": 2,
|
|
||||||
"HOST": "https://beta.alkator.cz",
|
|
||||||
"WSS_HOST": "wss://beta.alkator.cz"
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
|
|
||||||
use std::time::{Instant, SystemTime};
|
|
||||||
use serde::{Serialize, Serializer, Deserialize, Deserializer, de::Error};
|
|
||||||
|
|
||||||
pub fn serialize<S>(instant: &Instant, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
let system_now = SystemTime::now();
|
|
||||||
let instant_now = Instant::now();
|
|
||||||
let approx = system_now - (instant_now - *instant);
|
|
||||||
approx.serialize(serializer)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Instant, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
let de = SystemTime::deserialize(deserializer)?;
|
|
||||||
let system_now = SystemTime::now();
|
|
||||||
let instant_now = Instant::now();
|
|
||||||
let duration = system_now.duration_since(de).map_err(Error::custom)?;
|
|
||||||
let approx = instant_now - duration;
|
|
||||||
Ok(approx)
|
|
||||||
}
|
|
@ -1,66 +0,0 @@
|
|||||||
use iced::task::{Never, Sipper, sipper};
|
|
||||||
use tokio::time::sleep;
|
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
use nusb::{transfer::{ RequestBuffer, TransferError }, Interface};
|
|
||||||
|
|
||||||
static USB_VENDOR: u16 = 0xffff;
|
|
||||||
static USB_PRODUCT: u16 = 0x0035;
|
|
||||||
|
|
||||||
|
|
||||||
fn get_interface() -> Option<Interface> {
|
|
||||||
let dev = nusb::list_devices().ok()?.find(|dev| dev.vendor_id() == USB_VENDOR && dev.product_id() == USB_PRODUCT)?;
|
|
||||||
let device = dev.open().ok()?;
|
|
||||||
device.detach_and_claim_interface(0).ok()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pub fn connect() -> impl Sipper<Never, Event> {
|
|
||||||
sipper(async |mut output|{
|
|
||||||
loop {
|
|
||||||
let interface = loop {
|
|
||||||
if let Some(interface) = get_interface(){
|
|
||||||
break interface;
|
|
||||||
}
|
|
||||||
sleep(Duration::new(0, 100)).await;
|
|
||||||
};
|
|
||||||
output.send(Event::Connected).await;
|
|
||||||
let mut card_id = 0;
|
|
||||||
loop {
|
|
||||||
let buf = RequestBuffer::new(8);
|
|
||||||
let data = interface.interrupt_in(0x81, buf).await;
|
|
||||||
match data.status {
|
|
||||||
Err(TransferError::Disconnected) => {
|
|
||||||
output.send(Event::Disconnected).await;
|
|
||||||
break;
|
|
||||||
},
|
|
||||||
Ok(()) => {
|
|
||||||
let code = data.data[2];
|
|
||||||
match code {
|
|
||||||
40 => {
|
|
||||||
output.send(Event::ReadedCardId(card_id)).await;
|
|
||||||
card_id = 0;
|
|
||||||
},
|
|
||||||
0 => (),
|
|
||||||
x @ 30..=38 => {
|
|
||||||
card_id *= 10;
|
|
||||||
card_id += x as usize - 29;
|
|
||||||
},
|
|
||||||
39 => {
|
|
||||||
card_id *= 10;
|
|
||||||
},
|
|
||||||
_ => panic!(),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => todo!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum Event{
|
|
||||||
Disconnected,
|
|
||||||
Connected,
|
|
||||||
ReadedCardId(usize),
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
use std::fs::File;
|
|
||||||
use std::io::BufReader;
|
|
||||||
use std::error::Error;
|
|
||||||
use std::path::Path;
|
|
||||||
use serde::{Deserialize};
|
|
||||||
use lazy_static::lazy_static;
|
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct Config {
|
|
||||||
pub DURATION: u64,
|
|
||||||
pub STATION_ID: usize,
|
|
||||||
pub HOST: String,
|
|
||||||
pub WSS_HOST: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_config_from_file<P: AsRef<Path>>(path: P) -> Result<Config, Box<dyn Error>> {
|
|
||||||
// Open the file in read-only mode with buffer.
|
|
||||||
let file = File::open(path)?;
|
|
||||||
let reader = BufReader::new(file);
|
|
||||||
|
|
||||||
// Read the JSON contents of the file as an instance of `User`.
|
|
||||||
let config = serde_json::from_reader(reader)?;
|
|
||||||
|
|
||||||
// Return the `User`.
|
|
||||||
Ok(config)
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
pub static ref CONFIG: Config = read_config_from_file("config.json").unwrap();
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
use iced::futures;
|
|
||||||
use iced::task::{Never, Sipper, sipper};
|
|
||||||
|
|
||||||
use futures::stream::StreamExt;
|
|
||||||
|
|
||||||
use async_tungstenite::tungstenite;
|
|
||||||
use crate::config::CONFIG;
|
|
||||||
|
|
||||||
pub fn connect() -> impl Sipper<Never, Event> {
|
|
||||||
sipper(async |mut output| {
|
|
||||||
let endpoint_addr: String = CONFIG.WSS_HOST.clone() + "/api/live/racers";
|
|
||||||
loop {
|
|
||||||
|
|
||||||
let mut websocket =
|
|
||||||
match async_tungstenite::tokio::connect_async(endpoint_addr.as_str()).await
|
|
||||||
{
|
|
||||||
Ok((websocket, _)) => {
|
|
||||||
websocket.fuse()
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
tokio::time::sleep(tokio::time::Duration::from_secs(1))
|
|
||||||
.await;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
println!("Websocket Connected!");
|
|
||||||
loop {
|
|
||||||
futures::select! {
|
|
||||||
received = websocket.select_next_some() => {
|
|
||||||
match received {
|
|
||||||
Ok(tungstenite::Message::Text(message)) => {
|
|
||||||
output.send(Event::MessageReceived(String::from(message.as_str()))).await;
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
println!("Websocket Disconnected!");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Ok(_) => {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum Event {
|
|
||||||
MessageReceived(String),
|
|
||||||
}
|
|
@ -1,203 +0,0 @@
|
|||||||
use iced::time::{self, Duration, Instant, milliseconds};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::fmt::{Formatter, Error as fmtError};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use iced::widget::{center, column, row, text};
|
|
||||||
use iced::{Element, Subscription, Theme, Center, Task};
|
|
||||||
use tokio::fs::File;
|
|
||||||
use tokio::io::AsyncWriteExt;
|
|
||||||
use std::fs::read_to_string;
|
|
||||||
use reqwest::Client;
|
|
||||||
use chrono::{DateTime, Local};
|
|
||||||
use iced::futures::join;
|
|
||||||
|
|
||||||
|
|
||||||
mod card_reader;
|
|
||||||
mod approx_time;
|
|
||||||
mod config;
|
|
||||||
mod db_update;
|
|
||||||
use config::CONFIG;
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
struct RacerTime{
|
|
||||||
#[serde(with = "approx_time")]
|
|
||||||
time: Instant,
|
|
||||||
racer: Racer,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
struct State{
|
|
||||||
racers: Vec<RacerTime>,
|
|
||||||
db: HashMap<usize, Racer>,
|
|
||||||
#[serde(with = "approx_time")]
|
|
||||||
time: Instant,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for State {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
racers: vec![],
|
|
||||||
db: Default::default(),
|
|
||||||
time: Instant::now(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn dump_state(json: String) -> Result<(), tokio::io::Error> {
|
|
||||||
let mut file = File::create("state.json").await?;
|
|
||||||
file.write_all(json.as_bytes()).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
|
||||||
struct RegisterRacer{
|
|
||||||
card_id: usize,
|
|
||||||
time: String,
|
|
||||||
station_id: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Eq, PartialEq)]
|
|
||||||
struct Racer{
|
|
||||||
starting_number: usize,
|
|
||||||
card_id: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Message{
|
|
||||||
CardReader(card_reader::Event),
|
|
||||||
RacerRecieved(db_update::Event),
|
|
||||||
Tick(Instant),
|
|
||||||
Nothing,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Debug for Message {
|
|
||||||
// Required method
|
|
||||||
fn fmt(&self, _f: &mut Formatter<'_>) -> Result<(), fmtError>{
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn station_register(card_id: usize, time: DateTime::<Local>) -> Result<(), reqwest::Error>{
|
|
||||||
let register_racer = RegisterRacer{
|
|
||||||
card_id: card_id,
|
|
||||||
station_id: CONFIG.STATION_ID,
|
|
||||||
time: format!("{}", time.format("%d.%m.%Y %H:%M:%S.%6f")),
|
|
||||||
};
|
|
||||||
Client::new()
|
|
||||||
.post(CONFIG.HOST.clone() + "/api/station/register")
|
|
||||||
.json(®ister_racer)
|
|
||||||
.send()
|
|
||||||
.await?;
|
|
||||||
// Result can be error (400 and so on), whatever for now
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn register_and_dump(card_id: usize, datetime: DateTime<Local>, json: String) -> (Result<(), tokio::io::Error>, Result<(), reqwest::Error>){
|
|
||||||
return join!(dump_state(json), station_register(card_id, datetime))
|
|
||||||
}
|
|
||||||
|
|
||||||
impl State{
|
|
||||||
fn update(&mut self, message: Message) -> Task<Message>{
|
|
||||||
match message {
|
|
||||||
Message::RacerRecieved(event) => {
|
|
||||||
match event {
|
|
||||||
db_update::Event::MessageReceived(s) => {
|
|
||||||
let racer: Racer = serde_json::from_str(s.as_str()).unwrap();
|
|
||||||
let old_racer = self.db.insert(racer.card_id, racer.clone());
|
|
||||||
if old_racer != Some(racer){
|
|
||||||
let json = serde_json::to_string(self).unwrap();
|
|
||||||
Task::perform(dump_state(json), |_| Message::Nothing)
|
|
||||||
}else{
|
|
||||||
Task::none()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Message::Tick(time) => {
|
|
||||||
self.time = time;
|
|
||||||
Task::none()
|
|
||||||
},
|
|
||||||
Message::Nothing => Task::none(),
|
|
||||||
Message::CardReader(card_reader::Event::ReadedCardId(card_id)) => {
|
|
||||||
let time = Instant::now();
|
|
||||||
let datetime = Local::now();
|
|
||||||
if let Some(racer) = self.db.get(&card_id){
|
|
||||||
if !self.racers.iter().any(|rt| rt.racer.starting_number == racer.starting_number){
|
|
||||||
let racer_time = RacerTime{time, racer: racer.clone()};
|
|
||||||
self.racers.push(racer_time);
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
println!("Racer {} not found in db!", card_id)
|
|
||||||
}
|
|
||||||
let json = serde_json::to_string(self).unwrap();
|
|
||||||
Task::perform(register_and_dump(card_id, datetime, json), |_| Message::Nothing)
|
|
||||||
},
|
|
||||||
Message::CardReader(card_reader::Event::Connected) => {
|
|
||||||
println!("Card Reader Connected!");
|
|
||||||
Task::none()
|
|
||||||
},
|
|
||||||
Message::CardReader(card_reader::Event::Disconnected) => {
|
|
||||||
println!("Card Reader Disconnected!");
|
|
||||||
Task::none()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn view(&self) -> Element<Message> {
|
|
||||||
let mut content = column![
|
|
||||||
row![
|
|
||||||
text("Číslo závodníka").width(120).align_x(Center).align_y(Center), text("čas").size(20).width(120).align_x(Center).align_y(Center)
|
|
||||||
],
|
|
||||||
];
|
|
||||||
for racer_time in &self.racers {
|
|
||||||
const MINUTE: u64 = 60;
|
|
||||||
|
|
||||||
|
|
||||||
let time = self.time - racer_time.time;
|
|
||||||
let duration = Duration::new(CONFIG.DURATION, 0);
|
|
||||||
let (duration, negative) = if duration < time {
|
|
||||||
(time - duration, true)
|
|
||||||
} else {
|
|
||||||
(duration - time, false)
|
|
||||||
};
|
|
||||||
let seconds = duration.as_secs();
|
|
||||||
|
|
||||||
if negative && seconds >= 10 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
let duration = text!(
|
|
||||||
"{}{:0>2}:{:0>2}.{:0>2}",
|
|
||||||
if negative {"-"} else {""},
|
|
||||||
seconds / MINUTE,
|
|
||||||
seconds % MINUTE,
|
|
||||||
duration.subsec_millis() / 10,
|
|
||||||
).size(20).width(120).align_x(Center).align_y(Center);
|
|
||||||
content = content.push(
|
|
||||||
row![
|
|
||||||
text(racer_time.racer.starting_number.to_string()).size(20).width(120).align_x(Center).align_y(Center), duration
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
center(content).into()
|
|
||||||
}
|
|
||||||
fn subscription(&self) -> Subscription<Message> {
|
|
||||||
Subscription::batch(vec![
|
|
||||||
time::every(milliseconds(10)).map(Message::Tick),
|
|
||||||
Subscription::run(card_reader::connect).map(Message::CardReader),
|
|
||||||
Subscription::run(db_update::connect).map(Message::RacerRecieved)
|
|
||||||
])
|
|
||||||
}
|
|
||||||
fn theme(&self) -> Theme {
|
|
||||||
Theme::Dark
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
|
||||||
let init_state = || -> State {read_to_string("state.json").ok().map(|s| serde_json::from_str(&s).ok()).flatten().unwrap_or_else(||Default::default())} ;
|
|
||||||
env_logger::init();
|
|
||||||
rustls::crypto::aws_lc_rs::default_provider().install_default().unwrap();
|
|
||||||
iced::application(init_state, State::update, State::view)
|
|
||||||
.subscription(State::subscription)
|
|
||||||
.theme(State::theme)
|
|
||||||
.run()
|
|
||||||
}
|
|
100
SW/PC/Alkator.json
Normal file
100
SW/PC/Alkator.json
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"1": {
|
||||||
|
"name": "Michal_Dolezal",
|
||||||
|
"time": 59686.214496,
|
||||||
|
"laps": 3,
|
||||||
|
"lap_time": {
|
||||||
|
"0": 1570.6283019999973,
|
||||||
|
"1": 1714.182087000001,
|
||||||
|
"2": 1446.9299450000035
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"name": "David_Hubalek",
|
||||||
|
"time": 61285.385381,
|
||||||
|
"laps": 3,
|
||||||
|
"lap_time": {
|
||||||
|
"0": 1378.498722999997,
|
||||||
|
"1": 1902.1900959999984,
|
||||||
|
"2": 2436.201885000002
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"9": {
|
||||||
|
"name": "Lucie_Ponocna",
|
||||||
|
"time": 60148.765882,
|
||||||
|
"laps": 3,
|
||||||
|
"lap_time": {
|
||||||
|
"0": 1481.6570529999954,
|
||||||
|
"1": 1371.9764339999965,
|
||||||
|
"2": 1392.5671650000004
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"8": {
|
||||||
|
"name": "Jan_Cada",
|
||||||
|
"time": 60218.945151,
|
||||||
|
"laps": 3,
|
||||||
|
"lap_time": {
|
||||||
|
"0": 1293.8216450000036,
|
||||||
|
"1": 1341.646053000004,
|
||||||
|
"2": 1402.6441269999996
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"10": {
|
||||||
|
"name": "Jenda",
|
||||||
|
"time": 61880.872883,
|
||||||
|
"laps": 3,
|
||||||
|
"lap_time": {
|
||||||
|
"0": 1365.9300070000027,
|
||||||
|
"1": 1959.2283549999993,
|
||||||
|
"2": 1957.2417010000063
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"name": "Vojta_Flekr",
|
||||||
|
"time": 61567.55196,
|
||||||
|
"laps": 3,
|
||||||
|
"lap_time": {
|
||||||
|
"0": 1447.2361820000006,
|
||||||
|
"1": 1654.6209919999965,
|
||||||
|
"2": 1696.5821589999978
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"7": {
|
||||||
|
"name": "Lukas_Bouchal",
|
||||||
|
"time": 61356.658114,
|
||||||
|
"laps": 3,
|
||||||
|
"lap_time": {
|
||||||
|
"0": 1456.207137999998,
|
||||||
|
"1": 1405.8979709999985,
|
||||||
|
"2": 1365.8517150000043
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"3": {
|
||||||
|
"name": "Adam_Krejsa",
|
||||||
|
"time": 61475.209162,
|
||||||
|
"laps": 3,
|
||||||
|
"lap_time": {
|
||||||
|
"0": 1313.4791200000036,
|
||||||
|
"1": 1358.869869999995,
|
||||||
|
"2": 1402.3635040000008
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"6": {
|
||||||
|
"name": "David_Bedrnicek",
|
||||||
|
"time": 62894.44809,
|
||||||
|
"laps": 3,
|
||||||
|
"lap_time": {
|
||||||
|
"0": 1480.398721999998,
|
||||||
|
"1": 1721.0690019999965,
|
||||||
|
"2": 1939.8222899999964
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"11": {
|
||||||
|
"name": "Nacelnik",
|
||||||
|
"time": 64679.27699,
|
||||||
|
"laps": 1,
|
||||||
|
"lap_time": {
|
||||||
|
"0": 2533.054164000001
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
SW/PC/Alkator_count_results.py
Normal file
32
SW/PC/Alkator_count_results.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Created on Sat Oct 21 17:19:11 2023
|
||||||
|
|
||||||
|
@author: angoosh
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
FILE = './Alkator.json'
|
||||||
|
|
||||||
|
data_dict = ''
|
||||||
|
results = {}
|
||||||
|
|
||||||
|
with open(FILE,'r') as f:
|
||||||
|
file_content = f.read()
|
||||||
|
data_dict = json.loads(file_content)
|
||||||
|
|
||||||
|
for id in data_dict:
|
||||||
|
laps = int(data_dict[id]['laps'])
|
||||||
|
time = 0
|
||||||
|
for i in range(0,laps):
|
||||||
|
time += float(data_dict[id]['lap_time'][str(i)])
|
||||||
|
time = (time - (600*laps)) / 60
|
||||||
|
print(data_dict[id]['name'],time)
|
||||||
|
data_dict[id]['total_time'] = time
|
||||||
|
results[data_dict[id]['name']] = time
|
||||||
|
|
||||||
|
print(results)
|
||||||
|
dict(sorted(results.items(), key=lambda item: item[0]))
|
||||||
|
print(results)
|
1
SW/PC/Stopwatch/log.json
Normal file
1
SW/PC/Stopwatch/log.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
[]
|
@ -7,7 +7,7 @@ import json
|
|||||||
|
|
||||||
gi.require_version('Gtk', '4.0')
|
gi.require_version('Gtk', '4.0')
|
||||||
from queue import Queue
|
from queue import Queue
|
||||||
from gi.repository import Gtk, Gio, Gdk, GLib
|
from gi.repository import Gtk, Gio, Gdk
|
||||||
from requests.adapters import HTTPAdapter, Retry
|
from requests.adapters import HTTPAdapter, Retry
|
||||||
from usbcardreader import UsbCardReader
|
from usbcardreader import UsbCardReader
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ def callbackOnCard(card_id):
|
|||||||
if card_id in db:
|
if card_id in db:
|
||||||
if card_id not in activeCards:
|
if card_id not in activeCards:
|
||||||
activeCards.append(card_id)
|
activeCards.append(card_id)
|
||||||
GLib.idle_add(win.arb, db[card_id])
|
win.arb(db[card_id])
|
||||||
print('Card is active now')
|
print('Card is active now')
|
||||||
else:
|
else:
|
||||||
print('Card is already active')
|
print('Card is already active')
|
||||||
@ -140,16 +140,16 @@ class GridRow():
|
|||||||
else:
|
else:
|
||||||
mins, secs = divmod(t, 60)
|
mins, secs = divmod(t, 60)
|
||||||
timer = '{:02d}:{:02d}'.format(mins, secs)
|
timer = '{:02d}:{:02d}'.format(mins, secs)
|
||||||
GLib.idle_add(self.runb.set_label, timer)
|
self.runb.set_label(timer)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
t -= 1
|
t -= 1
|
||||||
if t == 10:
|
if t == 10:
|
||||||
if self.grid.get_name() == "lightgrid":
|
if self.grid.get_name() == "lightgrid":
|
||||||
GLib.idle_add(self.grid.set_name, "lredgrid")
|
self.grid.set_name("lredgrid")
|
||||||
else:
|
else:
|
||||||
GLib.idle_add(self.grid.set_name, "dredgrid")
|
self.grid.set_name("dredgrid")
|
||||||
|
|
||||||
GLib.idle_add(GridWindow.remRow, self.parent)
|
GridWindow.remRow(self.parent)
|
||||||
|
|
||||||
class GridWindow(Gtk.ApplicationWindow):
|
class GridWindow(Gtk.ApplicationWindow):
|
||||||
def __init__(self, **kargs):
|
def __init__(self, **kargs):
|
4
SW/PC/Stopwatch/people.json
Normal file
4
SW/PC/Stopwatch/people.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"1": 3619716179,
|
||||||
|
"2": 3620062547
|
||||||
|
}
|
51
SW/PC/Stopwatch/rfid_read.py
Normal file
51
SW/PC/Stopwatch/rfid_read.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import usb.core
|
||||||
|
import usb.util
|
||||||
|
import time
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
|
||||||
|
USB_IF = 0 # Interface
|
||||||
|
USB_TIMEOUT = 5 # Timeout in MS
|
||||||
|
USB_VENDOR = 0xffff # Vendor-ID:
|
||||||
|
USB_PRODUCT = 0x0035 # Product-ID
|
||||||
|
|
||||||
|
# Find the HID device by vender/product ID
|
||||||
|
dev = usb.core.find(idVendor=USB_VENDOR, idProduct=USB_PRODUCT)
|
||||||
|
|
||||||
|
# Get and store the endpoint
|
||||||
|
endpoint = dev[0][(0,0)][0]
|
||||||
|
|
||||||
|
if dev.is_kernel_driver_active(USB_IF) is True:
|
||||||
|
dev.detach_kernel_driver(USB_IF)
|
||||||
|
|
||||||
|
# Claim the device
|
||||||
|
usb.util.claim_interface(dev, USB_IF)
|
||||||
|
|
||||||
|
receivedNumber = 0
|
||||||
|
while True:
|
||||||
|
control = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Read a character from the device
|
||||||
|
control = dev.read(endpoint.bEndpointAddress, endpoint.wMaxPacketSize, USB_TIMEOUT)
|
||||||
|
# Here you have to analyze what's coming in.
|
||||||
|
# In my case you had to check the first byte (command)
|
||||||
|
if (control[2] != 40) & (control[2] != 0):
|
||||||
|
# Convert ascii to a number, there's probably better ways to do so.
|
||||||
|
receivedDigit = control[2] - 29
|
||||||
|
|
||||||
|
if receivedDigit == 10:
|
||||||
|
receivedDigit = 0
|
||||||
|
|
||||||
|
# Append the digit to the number
|
||||||
|
receivedNumber = 10 * receivedNumber + receivedDigit
|
||||||
|
|
||||||
|
# Check if the received character is CRLF
|
||||||
|
if (( control[0] == 0 )) & (( control[2] == 40 )) & (( not receivedNumber == 0 )):
|
||||||
|
print('cardNumber:', receivedNumber)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
exit()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
time.sleep(0.001) # Let CTRL+C actually exit
|
0
run.sh → SW/PC/Stopwatch/run.sh
Normal file → Executable file
0
run.sh → SW/PC/Stopwatch/run.sh
Normal file → Executable file
110
SW/PC/Stopwatch/start_finish_stopwatch.py
Normal file
110
SW/PC/Stopwatch/start_finish_stopwatch.py
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
import threading
|
||||||
|
import time
|
||||||
|
import usb.core
|
||||||
|
import usb.util
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
DEBUG = False
|
||||||
|
|
||||||
|
if DEBUG == True:
|
||||||
|
index = 2
|
||||||
|
else:
|
||||||
|
index = 1
|
||||||
|
activeCards = []
|
||||||
|
|
||||||
|
TIME = 600
|
||||||
|
|
||||||
|
USB_IF = 0 # Interface
|
||||||
|
USB_TIMEOUT = 5 # Timeout in ms
|
||||||
|
USB_VENDOR = 0xffff # Vendor-ID:
|
||||||
|
USB_PRODUCT = 0x0035 # Product-ID
|
||||||
|
|
||||||
|
with open('people.json', 'r') as f:
|
||||||
|
db = json.load(f)
|
||||||
|
|
||||||
|
try:
|
||||||
|
times = {}
|
||||||
|
with open('times.json', 'r') as f:
|
||||||
|
times_json = json.load(f)
|
||||||
|
for i in times_json:
|
||||||
|
times[i] = {}
|
||||||
|
times[i]['start'] = datetime.datetime.strptime(times_json[i]['start'],"%d/%m/%Y, %H:%M:%S")
|
||||||
|
try:
|
||||||
|
times[i]['end'] = datetime.datetime.strptime(times_json[i]['end'],"%d/%m/%Y, %H:%M:%S")
|
||||||
|
times[i]['duration'] = times[i]['end'] - times[i]['start']
|
||||||
|
except:
|
||||||
|
print(i, "Not finished yet")
|
||||||
|
print(times)
|
||||||
|
except Exception as e: print(e)
|
||||||
|
#except:
|
||||||
|
# times = {}
|
||||||
|
# times_json = {}
|
||||||
|
|
||||||
|
class UsbCardReader():
|
||||||
|
def __init__(self, **kargs):
|
||||||
|
# Find the HID device by vendor/product ID
|
||||||
|
self.dev = usb.core.find(idVendor=USB_VENDOR, idProduct=USB_PRODUCT)
|
||||||
|
# Get and store the endpoint
|
||||||
|
self.endpoint = self.dev[0][(0,0)][0]
|
||||||
|
if self.dev.is_kernel_driver_active(USB_IF) is True:
|
||||||
|
self.dev.detach_kernel_driver(USB_IF)
|
||||||
|
# Claim the device
|
||||||
|
usb.util.claim_interface(self.dev, USB_IF)
|
||||||
|
self.receivedNumber = 0
|
||||||
|
|
||||||
|
cardread=threading.Thread(target=self.read)
|
||||||
|
cardread.start()
|
||||||
|
|
||||||
|
def read(self):
|
||||||
|
global activeCards, db, times, times_json
|
||||||
|
|
||||||
|
print("Waiting for card")
|
||||||
|
receivedNumber = 0
|
||||||
|
|
||||||
|
while True:
|
||||||
|
control = None
|
||||||
|
try:
|
||||||
|
control = self.dev.read(self.endpoint.bEndpointAddress, self.endpoint.wMaxPacketSize, USB_TIMEOUT)
|
||||||
|
if (control[2] != 40) & (control[2] != 0):
|
||||||
|
receivedDigit = control[2] - 29
|
||||||
|
if receivedDigit == 10:
|
||||||
|
receivedDigit = 0
|
||||||
|
receivedNumber = 10 * receivedNumber + receivedDigit
|
||||||
|
|
||||||
|
if (( control[0] == 0 )) & (( control[2] == 40 )) & (( not receivedNumber == 0 )):
|
||||||
|
try:
|
||||||
|
with open('people.json', 'r') as f:
|
||||||
|
db = json.load(f)
|
||||||
|
for i in db:
|
||||||
|
if db[i] == receivedNumber:
|
||||||
|
print("Runner:", i)
|
||||||
|
print(db)
|
||||||
|
runner_found = False
|
||||||
|
for j in times:
|
||||||
|
if j == i:
|
||||||
|
runner_found = True
|
||||||
|
times[j]['end'] = datetime.datetime.now()
|
||||||
|
times[j]['duration'] = times[j]['end'] - times[j]['start']
|
||||||
|
times_json[j]['end'] = times[j]['end'].strftime("%d/%m/%Y, %H:%M:%S")
|
||||||
|
times_json[j]['duration'] = str(times[j]['duration'])
|
||||||
|
if runner_found == False:
|
||||||
|
times[i] = {}
|
||||||
|
times[i]['start'] = datetime.datetime.now()
|
||||||
|
times_json[i] = {}
|
||||||
|
times_json[i]['start'] = times[i]['start'].strftime("%d/%m/%Y, %H:%M:%S")
|
||||||
|
with open("times.json", 'w') as f:
|
||||||
|
f.write(json.dumps(times_json, indent = 4))
|
||||||
|
print(times)
|
||||||
|
except Exception as e: print(e)
|
||||||
|
receivedNumber = 0
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
exit()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
time.sleep(0.001)
|
||||||
|
|
||||||
|
UsbCardReader()
|
20
SW/PC/Stopwatch/style.css
Normal file
20
SW/PC/Stopwatch/style.css
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#lightgrid {
|
||||||
|
background-color: #F0F0F0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#darkgrid {
|
||||||
|
background-color: #D0D0D0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lredgrid {
|
||||||
|
background-color: #FF8888;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dredgrid {
|
||||||
|
background-color: #FF6666;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gridlabel {
|
||||||
|
font-size: 16pt;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
12
SW/PC/Stopwatch/times.json
Normal file
12
SW/PC/Stopwatch/times.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"1": {
|
||||||
|
"start": "25/02/2025, 18:06:16",
|
||||||
|
"end": "25/02/2025, 18:06:31",
|
||||||
|
"duration": "0:00:14.553644"
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"start": "25/02/2025, 18:15:08",
|
||||||
|
"end": "25/02/2025, 18:15:27",
|
||||||
|
"duration": "0:00:19.543765"
|
||||||
|
}
|
||||||
|
}
|
84
SW/PC/Stopwatch/zapis_zavodniku.py
Normal file
84
SW/PC/Stopwatch/zapis_zavodniku.py
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import time
|
||||||
|
import usb.core
|
||||||
|
import usb.util
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
import threading
|
||||||
|
|
||||||
|
USB_IF = 0 # Interface
|
||||||
|
USB_TIMEOUT = 5 # Timeout in ms
|
||||||
|
USB_VENDOR = 0xffff # Vendor-ID:
|
||||||
|
USB_PRODUCT = 0x0035 # Product-ID
|
||||||
|
|
||||||
|
activeCards = {}
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open('people.json', 'r') as f:
|
||||||
|
activeCards = json.load(f)
|
||||||
|
except:
|
||||||
|
print("No people.json found")
|
||||||
|
|
||||||
|
class UsbCardReader():
|
||||||
|
def __init__(self, **kargs):
|
||||||
|
# Find the HID device by vendor/product ID
|
||||||
|
self.dev = usb.core.find(idVendor=USB_VENDOR, idProduct=USB_PRODUCT)
|
||||||
|
# Get and store the endpoint
|
||||||
|
self.endpoint = self.dev[0][(0,0)][0]
|
||||||
|
if self.dev.is_kernel_driver_active(USB_IF) is True:
|
||||||
|
self.dev.detach_kernel_driver(USB_IF)
|
||||||
|
# Claim the device
|
||||||
|
usb.util.claim_interface(self.dev, USB_IF)
|
||||||
|
self.receivedNumber = 0
|
||||||
|
|
||||||
|
def read(self):
|
||||||
|
global activeCards
|
||||||
|
|
||||||
|
print("Priloz kartu")
|
||||||
|
|
||||||
|
while True:
|
||||||
|
control = None
|
||||||
|
try:
|
||||||
|
control = self.dev.read(self.endpoint.bEndpointAddress, self.endpoint.wMaxPacketSize, USB_TIMEOUT)
|
||||||
|
if (control[2] != 40) & (control[2] != 0):
|
||||||
|
receivedDigit = control[2] - 29
|
||||||
|
if receivedDigit == 10:
|
||||||
|
receivedDigit = 0
|
||||||
|
self.receivedNumber = 10 * self.receivedNumber + receivedDigit
|
||||||
|
|
||||||
|
if (( control[0] == 0 )) & (( control[2] == 40 )) & (( not self.receivedNumber == 0 )):
|
||||||
|
try:
|
||||||
|
cardPresent = False
|
||||||
|
for i in activeCards:
|
||||||
|
if activeCards[i] == self.receivedNumber:
|
||||||
|
cardPresent = True
|
||||||
|
break
|
||||||
|
if cardPresent == False:
|
||||||
|
assign=threading.Thread(target=self.assign)
|
||||||
|
assign.start()
|
||||||
|
else:
|
||||||
|
print("Naramek jiz zaregistrovan")
|
||||||
|
self.receivedNumber = 0
|
||||||
|
print("Priloz kartu")
|
||||||
|
except Exception as e: print(e)
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
exit()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
time.sleep(0.001)
|
||||||
|
|
||||||
|
def assign(self):
|
||||||
|
global activeCards
|
||||||
|
|
||||||
|
n = input("Cislo zavodnika: ")
|
||||||
|
activeCards[str(n)] = self.receivedNumber
|
||||||
|
with open('people.json', 'w') as f:
|
||||||
|
f.write(json.dumps(activeCards, indent = 4))
|
||||||
|
self.receivedNumber = 0
|
||||||
|
print("Ulozeno, priloz kartu")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
reader = UsbCardReader()
|
||||||
|
print("Zapis zavodniku ready")
|
||||||
|
reader.read()
|
100
SW/PC/main.py
Executable file
100
SW/PC/main.py
Executable file
@ -0,0 +1,100 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
import serial
|
||||||
|
import json
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
JSON_PATH = './Alkator.json'
|
||||||
|
|
||||||
|
data_dict = ''
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(JSON_PATH, 'r') as file:
|
||||||
|
file_content = file.read()
|
||||||
|
data_dict = json.loads(file_content)
|
||||||
|
print('json_exists')
|
||||||
|
except:
|
||||||
|
data_dict = {}
|
||||||
|
|
||||||
|
def get_seconds():
|
||||||
|
current_time = datetime.now()
|
||||||
|
hours = current_time.hour
|
||||||
|
mins = current_time.minute
|
||||||
|
secs = current_time.second
|
||||||
|
us = current_time.microsecond
|
||||||
|
seconds = hours*3600 + mins*60 + secs
|
||||||
|
seconds = float(str(seconds) + '.' + str(us))
|
||||||
|
return seconds
|
||||||
|
|
||||||
|
def read(ser):
|
||||||
|
while True:
|
||||||
|
mes = ser.read_until(b'\r')
|
||||||
|
if b'Reading ntag' in mes:
|
||||||
|
print('reading')
|
||||||
|
if b'Data' in mes:
|
||||||
|
data = mes.decode('utf-8')
|
||||||
|
data = data[6:].replace('\x00', '').replace('\r', '').split(' ')
|
||||||
|
print('data read done')
|
||||||
|
try:
|
||||||
|
lap_secs = get_seconds() - data_dict[data[0]]['time']
|
||||||
|
print(lap_secs)
|
||||||
|
lap = data_dict[data[0]]['laps']
|
||||||
|
try:
|
||||||
|
data_dict[data[0]]['lap_time'][lap] = lap_secs
|
||||||
|
except:
|
||||||
|
data_dict[data[0]]['lap_time'] = {lap: lap_secs}
|
||||||
|
lap += 1
|
||||||
|
data_dict[data[0]]['laps'] = lap
|
||||||
|
data_dict[data[0]]['time'] = get_seconds()
|
||||||
|
|
||||||
|
except:
|
||||||
|
data_dict[data[0]] = {'name': data[1]}
|
||||||
|
data_dict[data[0]]['time'] = get_seconds()
|
||||||
|
data_dict[data[0]]['laps'] = 0
|
||||||
|
|
||||||
|
data_json = json.dumps(data_dict, indent=4)
|
||||||
|
print(data_json)
|
||||||
|
with open(JSON_PATH, 'w') as file:
|
||||||
|
file.write(data_json)
|
||||||
|
|
||||||
|
def write(ser):
|
||||||
|
while True:
|
||||||
|
data = input('ID:')
|
||||||
|
data = data + '\r'
|
||||||
|
ser.write(data.encode())
|
||||||
|
while True:
|
||||||
|
mes = ser.read_until(b'\r')
|
||||||
|
if b'Waiting' in mes:
|
||||||
|
print('Waiting for card')
|
||||||
|
if b'Erasing' in mes:
|
||||||
|
print('Erasing card')
|
||||||
|
if b'Writing' in mes:
|
||||||
|
print('Writing data to card')
|
||||||
|
if b'done' in mes:
|
||||||
|
print('Write done')
|
||||||
|
break
|
||||||
|
|
||||||
|
def main():
|
||||||
|
s = serial.Serial(port="/dev/ttyACM3", parity=serial.PARITY_EVEN, stopbits=serial.STOPBITS_ONE, timeout=1)
|
||||||
|
s.flush()
|
||||||
|
|
||||||
|
rw = input('Read or Write tags? [R/w]')
|
||||||
|
rw = rw.lower()
|
||||||
|
|
||||||
|
if rw == 'w':
|
||||||
|
s.write('w\r'.encode())
|
||||||
|
write(s)
|
||||||
|
elif rw == 'r':
|
||||||
|
s.write('r\r'.encode())
|
||||||
|
read(s)
|
||||||
|
elif rw == '':
|
||||||
|
s.write('r\r'.encode())
|
||||||
|
read(s)
|
||||||
|
else:
|
||||||
|
print('Invalid option')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
163
SW/RPi_Pico_Button/main.py
Normal file
163
SW/RPi_Pico_Button/main.py
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
import neopixel
|
||||||
|
import time
|
||||||
|
import sys
|
||||||
|
import select
|
||||||
|
from machine import Pin, SPI
|
||||||
|
|
||||||
|
#neopixel
|
||||||
|
ws_pin = 2
|
||||||
|
led_num = 10
|
||||||
|
BRIGHTNESS = 0.2 # Adjust the brightness (0.0 - 1.0)
|
||||||
|
|
||||||
|
led_strip = neopixel.NeoPixel(Pin(ws_pin), led_num)
|
||||||
|
|
||||||
|
push_button = Pin(24, Pin.IN, Pin.PULL_UP)
|
||||||
|
buzzer = Pin(3, Pin.OUT)
|
||||||
|
led = Pin(25, Pin.OUT)
|
||||||
|
|
||||||
|
pushbutton_pressed = 0
|
||||||
|
blink_interrupted = 0
|
||||||
|
|
||||||
|
def set_neopixel_brightness(color):
|
||||||
|
r, g, b = color
|
||||||
|
r = int(r * BRIGHTNESS)
|
||||||
|
g = int(g * BRIGHTNESS)
|
||||||
|
b = int(b * BRIGHTNESS)
|
||||||
|
return (r, g, b)
|
||||||
|
|
||||||
|
def set_neopixel_color(r,g,b):
|
||||||
|
color = (r,g,b)
|
||||||
|
color = set_neopixel_brightness(color)
|
||||||
|
led_strip.fill(color)
|
||||||
|
led_strip.write()
|
||||||
|
|
||||||
|
set_neopixel_color(0,0,0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def loop_neopixel():
|
||||||
|
# Display red
|
||||||
|
color = (255, 0, 0) # Red color
|
||||||
|
color = set_neopixel_brightness(color)
|
||||||
|
led_strip.fill(color)
|
||||||
|
led_strip.write()
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
# Display green
|
||||||
|
color = (0, 255, 0) # Green color
|
||||||
|
color = set_neopixel_brightness(color)
|
||||||
|
led_strip.fill(color)
|
||||||
|
led_strip.write()
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
# Display blue
|
||||||
|
color = (0, 0, 255) # Blue color
|
||||||
|
color = set_neopixel_brightness(color)
|
||||||
|
led_strip.fill(color)
|
||||||
|
led_strip.write()
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
neopix_loop_dot_pos = 0
|
||||||
|
def neopixel_loop_dot():
|
||||||
|
global neopix_loop_dot_pos
|
||||||
|
color = (255, 0, 0)
|
||||||
|
black = (0, 0, 0)
|
||||||
|
|
||||||
|
color = set_neopixel_brightness(color)
|
||||||
|
led_strip[neopix_loop_dot_pos] = black
|
||||||
|
neopix_loop_dot_pos += 1
|
||||||
|
if neopix_loop_dot_pos > 9:
|
||||||
|
neopix_loop_dot_pos = 0
|
||||||
|
led_strip[neopix_loop_dot_pos] = color
|
||||||
|
led_strip.write()
|
||||||
|
time.sleep(0.2)
|
||||||
|
|
||||||
|
def lightup_led(index, color):
|
||||||
|
led_strip[index] = color
|
||||||
|
led_strip.write()
|
||||||
|
|
||||||
|
def blink_and_beep(times):
|
||||||
|
global pushbutton_pressed, blink_interrupted
|
||||||
|
|
||||||
|
blink_delay = 0.2
|
||||||
|
|
||||||
|
#insert beep
|
||||||
|
buzzer.value(1)
|
||||||
|
for i in range(0, times):
|
||||||
|
set_neopixel_color(255, 0, 0)
|
||||||
|
buzzer.value(0)
|
||||||
|
time.sleep(blink_delay)
|
||||||
|
set_neopixel_color(0, 0, 0)
|
||||||
|
buzzer.value(1)
|
||||||
|
time.sleep(blink_delay)
|
||||||
|
if pushbutton_pressed == 1:
|
||||||
|
pushbutton_pressed = 0
|
||||||
|
blink_interrupted = 1
|
||||||
|
i = times
|
||||||
|
buzzer.value(0)
|
||||||
|
return
|
||||||
|
buzzer.value(0)
|
||||||
|
|
||||||
|
ten_min_timer = 0
|
||||||
|
ten_min_timer_led_index = 11
|
||||||
|
def count_10_min():
|
||||||
|
global ten_min_timer, ten_min_timer_led_index, pushbutton_pressed, blink_interrupted
|
||||||
|
|
||||||
|
red = (255, 0, 0)
|
||||||
|
red = set_neopixel_brightness(red)
|
||||||
|
green = (0, 255, 0)
|
||||||
|
green = set_neopixel_brightness(green)
|
||||||
|
|
||||||
|
if ten_min_timer_led_index == 11:
|
||||||
|
return
|
||||||
|
|
||||||
|
if (ten_min_timer % 60) == 0:
|
||||||
|
if ten_min_timer_led_index == 10:
|
||||||
|
pushbutton_pressed = 0
|
||||||
|
blink_and_beep(15)
|
||||||
|
if blink_interrupted == 1:
|
||||||
|
blink_interrupted = 0
|
||||||
|
return
|
||||||
|
ten_min_timer_led_index = 11
|
||||||
|
led_strip[0] = green
|
||||||
|
led_strip[2] = green
|
||||||
|
led_strip[4] = green
|
||||||
|
led_strip[6] = green
|
||||||
|
led_strip[8] = green
|
||||||
|
led_strip.write()
|
||||||
|
return
|
||||||
|
lightup_led(ten_min_timer_led_index, red)
|
||||||
|
ten_min_timer_led_index += 1
|
||||||
|
|
||||||
|
ten_min_timer += 1
|
||||||
|
|
||||||
|
def button_callback(push_button):
|
||||||
|
global ten_min_timer, ten_min_timer_led_index, pushbutton_pressed
|
||||||
|
pushbutton_pressed = 1
|
||||||
|
ten_min_timer = 0
|
||||||
|
ten_min_timer_led_index = 0
|
||||||
|
set_neopixel_color(0,0,0)
|
||||||
|
count_10_min()
|
||||||
|
|
||||||
|
set_neopixel_color(0,0,0)
|
||||||
|
push_button.irq(trigger=Pin.IRQ_FALLING, handler=button_callback)
|
||||||
|
|
||||||
|
green = (0, 255, 0)
|
||||||
|
green = set_neopixel_brightness(green)
|
||||||
|
led_strip[0] = green
|
||||||
|
led_strip[2] = green
|
||||||
|
led_strip[4] = green
|
||||||
|
led_strip[6] = green
|
||||||
|
led_strip[8] = green
|
||||||
|
led_strip.write()
|
||||||
|
|
||||||
|
led_state = False
|
||||||
|
while True:
|
||||||
|
count_10_min()
|
||||||
|
time.sleep(1)
|
||||||
|
if led_state:
|
||||||
|
led.low()
|
||||||
|
led_state = False
|
||||||
|
else:
|
||||||
|
led.high()
|
||||||
|
led_state = True
|
408
SW/RPi_Pico_Reader/NFC_PN532.py
Normal file
408
SW/RPi_Pico_Reader/NFC_PN532.py
Normal file
@ -0,0 +1,408 @@
|
|||||||
|
# @Author: carlosgilgonzalez
|
||||||
|
# @Date: 2019-10-15T16:13:47+01:00
|
||||||
|
# @Last modified by: carlosgilgonzalez
|
||||||
|
# @Last modified time: 2019-10-15T16:56:27+01:00
|
||||||
|
|
||||||
|
|
||||||
|
# Original work:
|
||||||
|
# Adafruit PN532 NFC/RFID control library.
|
||||||
|
# Author: Tony DiCola
|
||||||
|
|
||||||
|
# Partial Port to Micropython:
|
||||||
|
# Micropython PN532 NFC/RFID control library.
|
||||||
|
# Author: Carlos Gil Gonzalez
|
||||||
|
"""
|
||||||
|
Micropython PN532 NFC/RFID control library (SPI)
|
||||||
|
https://github.com/Carglglz/NFC_PN532_SPI
|
||||||
|
"""
|
||||||
|
|
||||||
|
import time
|
||||||
|
from machine import Pin
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
# __version__ = "0.0.0-auto.0"
|
||||||
|
# __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PN532.git"
|
||||||
|
|
||||||
|
# pylint: disable=bad-whitespace
|
||||||
|
_PREAMBLE = const(0x00)
|
||||||
|
_STARTCODE1 = const(0x00)
|
||||||
|
_STARTCODE2 = const(0xFF)
|
||||||
|
_POSTAMBLE = const(0x00)
|
||||||
|
|
||||||
|
_HOSTTOPN532 = const(0xD4)
|
||||||
|
_PN532TOHOST = const(0xD5)
|
||||||
|
|
||||||
|
# PN532 Commands
|
||||||
|
_COMMAND_DIAGNOSE = const(0x00)
|
||||||
|
_COMMAND_GETFIRMWAREVERSION = const(0x02)
|
||||||
|
_COMMAND_GETGENERALSTATUS = const(0x04)
|
||||||
|
_COMMAND_SETSERIALBAUDRATE = const(0x10)
|
||||||
|
_COMMAND_SETPARAMETERS = const(0x12)
|
||||||
|
_COMMAND_SAMCONFIGURATION = const(0x14)
|
||||||
|
|
||||||
|
_COMMAND_INLISTPASSIVETARGET = const(0x4A)
|
||||||
|
|
||||||
|
_COMMAND_INDATAEXCHANGE = const(0x40)
|
||||||
|
_COMMAND_INCOMMUNICATETHRU = const(0x42)
|
||||||
|
|
||||||
|
|
||||||
|
_RESPONSE_INDATAEXCHANGE = const(0x41)
|
||||||
|
_RESPONSE_INLISTPASSIVETARGET = const(0x4B)
|
||||||
|
|
||||||
|
_WAKEUP = const(0x55)
|
||||||
|
|
||||||
|
_MIFARE_ISO14443A = const(0x00)
|
||||||
|
|
||||||
|
# Mifare Commands
|
||||||
|
MIFARE_CMD_AUTH_A = const(0x60)
|
||||||
|
MIFARE_CMD_AUTH_B = const(0x61)
|
||||||
|
MIFARE_CMD_READ = const(0x30)
|
||||||
|
MIFARE_CMD_WRITE = const(0xA0)
|
||||||
|
MIFARE_ULTRALIGHT_CMD_WRITE = const(0xA2)
|
||||||
|
|
||||||
|
# Known keys
|
||||||
|
KEY_DEFAULT_B = bytes([0xFF]*6)
|
||||||
|
|
||||||
|
|
||||||
|
_ACK = b'\x00\x00\xFF\x00\xFF\x00'
|
||||||
|
_FRAME_START = b'\x00\x00\xFF'
|
||||||
|
# pylint: enable=bad-whitespace
|
||||||
|
_SPI_STATREAD = const(0x02)
|
||||||
|
_SPI_DATAWRITE = const(0x01)
|
||||||
|
_SPI_DATAREAD = const(0x03)
|
||||||
|
_SPI_READY = const(0x01)
|
||||||
|
|
||||||
|
|
||||||
|
def _reset(pin):
|
||||||
|
"""Perform a hardware reset toggle"""
|
||||||
|
pin.init(Pin.OUT)
|
||||||
|
pin.value(True)
|
||||||
|
time.sleep(0.1)
|
||||||
|
pin.value(False)
|
||||||
|
time.sleep(0.5)
|
||||||
|
pin.value(True)
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
|
||||||
|
class BusyError(Exception):
|
||||||
|
"""Base class for exceptions in this module."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def reverse_bit(num):
|
||||||
|
"""Turn an LSB byte to an MSB byte, and vice versa. Used for SPI as
|
||||||
|
it is LSB for the PN532, but 99% of SPI implementations are MSB only!"""
|
||||||
|
result = 0
|
||||||
|
for _ in range(8):
|
||||||
|
result <<= 1
|
||||||
|
result += (num & 1)
|
||||||
|
num >>= 1
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class PN532:
|
||||||
|
"""Driver for the PN532 connected over SPI. Pass in a hardware or bitbang
|
||||||
|
SPI device & chip select digitalInOut pin. Optional IRQ pin (not used),
|
||||||
|
reset pin and debugging output."""
|
||||||
|
|
||||||
|
def __init__(self, spi, cs_pin, irq=None, reset=None, debug=False):
|
||||||
|
"""Create an instance of the PN532 class using SPI"""
|
||||||
|
self.debug = debug
|
||||||
|
self._irq = irq
|
||||||
|
self.CSB = cs_pin
|
||||||
|
self._spi = spi
|
||||||
|
self.CSB.on()
|
||||||
|
if reset:
|
||||||
|
if debug:
|
||||||
|
print("Resetting")
|
||||||
|
_reset(reset)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self._wakeup()
|
||||||
|
# self.get_firmware_version() # first time often fails, try 2ce
|
||||||
|
return
|
||||||
|
except (BusyError, RuntimeError):
|
||||||
|
pass
|
||||||
|
# self.get_firmware_version()
|
||||||
|
|
||||||
|
def _wakeup(self):
|
||||||
|
"""Send any special commands/data to wake up PN532"""
|
||||||
|
time.sleep(1)
|
||||||
|
self.CSB.off()
|
||||||
|
time.sleep_ms(2)
|
||||||
|
self._spi.write(bytearray([0x00]))
|
||||||
|
time.sleep_ms(2)
|
||||||
|
self.CSB.on() # pylint: disable=no-member
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
def _wait_ready(self, timeout=1000):
|
||||||
|
"""Poll PN532 if status byte is ready, up to `timeout` milliseconds"""
|
||||||
|
status_query = bytearray([reverse_bit(_SPI_STATREAD), 0])
|
||||||
|
status = bytearray([0, 0])
|
||||||
|
timestamp = time.ticks_ms()
|
||||||
|
while time.ticks_diff(time.ticks_ms(), timestamp) < timeout:
|
||||||
|
time.sleep(0.02) # required
|
||||||
|
self.CSB.off()
|
||||||
|
time.sleep_ms(2)
|
||||||
|
self._spi.write_readinto(status_query, status)
|
||||||
|
time.sleep_ms(2)
|
||||||
|
self.CSB.on()
|
||||||
|
if reverse_bit(status[1]) == 0x01: # LSB data is read in MSB
|
||||||
|
return True # Not busy anymore!
|
||||||
|
else:
|
||||||
|
time.sleep(0.01) # pause a bit till we ask again
|
||||||
|
# Timed out!
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _read_data(self, count):
|
||||||
|
"""Read a specified count of bytes from the PN532."""
|
||||||
|
# Build a read request frame.
|
||||||
|
frame = bytearray(count+1)
|
||||||
|
# Add the SPI data read signal byte, but LSB'ify it
|
||||||
|
frame[0] = reverse_bit(_SPI_DATAREAD)
|
||||||
|
time.sleep(0.02) # required
|
||||||
|
self.CSB.off()
|
||||||
|
time.sleep_ms(2)
|
||||||
|
self._spi.write_readinto(frame, frame)
|
||||||
|
time.sleep_ms(2)
|
||||||
|
self.CSB.on()
|
||||||
|
for i, val in enumerate(frame):
|
||||||
|
frame[i] = reverse_bit(val) # turn LSB data to MSB
|
||||||
|
if self.debug:
|
||||||
|
print("DEBUG: _read_data: ", [hex(i) for i in frame[1:]])
|
||||||
|
return frame[1:] # don't return the status byte
|
||||||
|
|
||||||
|
def _write_data(self, framebytes):
|
||||||
|
"""Write a specified count of bytes to the PN532"""
|
||||||
|
# start by making a frame with data write in front,
|
||||||
|
# then rest of bytes, and LSBify it
|
||||||
|
rev_frame = [reverse_bit(x)
|
||||||
|
for x in bytes([_SPI_DATAWRITE]) + framebytes]
|
||||||
|
if self.debug:
|
||||||
|
print("DEBUG: _write_data: ", [hex(i) for i in rev_frame])
|
||||||
|
time.sleep(0.02) # required
|
||||||
|
self.CSB.off()
|
||||||
|
time.sleep_ms(2)
|
||||||
|
self._spi.write(bytes(rev_frame)) # pylint: disable=no-member
|
||||||
|
time.sleep_ms(2)
|
||||||
|
self.CSB.on()
|
||||||
|
|
||||||
|
def _write_frame(self, data):
|
||||||
|
"""Write a frame to the PN532 with the specified data bytearray."""
|
||||||
|
assert data is not None and 1 < len(
|
||||||
|
data) < 255, 'Data must be array of 1 to 255 bytes.'
|
||||||
|
# Build frame to send as:
|
||||||
|
# - Preamble (0x00)
|
||||||
|
# - Start code (0x00, 0xFF)
|
||||||
|
# - Command length (1 byte)
|
||||||
|
# - Command length checksum
|
||||||
|
# - Command bytes
|
||||||
|
# - Checksum
|
||||||
|
# - Postamble (0x00)
|
||||||
|
length = len(data)
|
||||||
|
frame = bytearray(length+8)
|
||||||
|
frame[0] = _PREAMBLE
|
||||||
|
frame[1] = _STARTCODE1
|
||||||
|
frame[2] = _STARTCODE2
|
||||||
|
checksum = sum(frame[0:3])
|
||||||
|
frame[3] = length & 0xFF
|
||||||
|
frame[4] = (~length + 1) & 0xFF
|
||||||
|
frame[5:-2] = data
|
||||||
|
checksum += sum(data)
|
||||||
|
frame[-2] = ~checksum & 0xFF
|
||||||
|
frame[-1] = _POSTAMBLE
|
||||||
|
# Send frame.
|
||||||
|
if self.debug:
|
||||||
|
print('DEBUG: _write_frame: ', [hex(i) for i in frame])
|
||||||
|
self._write_data(bytes(frame))
|
||||||
|
|
||||||
|
def _read_frame(self, length):
|
||||||
|
"""Read a response frame from the PN532 of at most length bytes in size.
|
||||||
|
Returns the data inside the frame if found, otherwise raises an exception
|
||||||
|
if there is an error parsing the frame. Note that less than length bytes
|
||||||
|
might be returned!
|
||||||
|
"""
|
||||||
|
# Read frame with expected length of data.
|
||||||
|
response = self._read_data(length+8)
|
||||||
|
if self.debug:
|
||||||
|
print('DEBUG: _read_frame:', [hex(i) for i in response])
|
||||||
|
|
||||||
|
# Swallow all the 0x00 values that preceed 0xFF.
|
||||||
|
offset = 0
|
||||||
|
while response[offset] == 0x00:
|
||||||
|
offset += 1
|
||||||
|
if offset >= len(response):
|
||||||
|
raise RuntimeError(
|
||||||
|
'Response frame preamble does not contain 0x00FF!')
|
||||||
|
if response[offset] != 0xFF:
|
||||||
|
raise RuntimeError(
|
||||||
|
'Response frame preamble does not contain 0x00FF!')
|
||||||
|
offset += 1
|
||||||
|
if offset >= len(response):
|
||||||
|
raise RuntimeError('Response contains no data!')
|
||||||
|
# Check length & length checksum match.
|
||||||
|
frame_len = response[offset]
|
||||||
|
if (frame_len + response[offset+1]) & 0xFF != 0:
|
||||||
|
raise RuntimeError(
|
||||||
|
'Response length checksum did not match length!')
|
||||||
|
# Check frame checksum value matches bytes.
|
||||||
|
checksum = sum(response[offset+2:offset+2+frame_len+1]) & 0xFF
|
||||||
|
if checksum != 0:
|
||||||
|
raise RuntimeError(
|
||||||
|
'Response checksum did not match expected value: ', checksum)
|
||||||
|
# Return frame data.
|
||||||
|
return response[offset+2:offset+2+frame_len]
|
||||||
|
|
||||||
|
def call_function(self, command, response_length=0, params=[], timeout=1000): # pylint: disable=dangerous-default-value
|
||||||
|
"""Send specified command to the PN532 and expect up to response_length
|
||||||
|
bytes back in a response. Note that less than the expected bytes might
|
||||||
|
be returned! Params can optionally specify an array of bytes to send as
|
||||||
|
parameters to the function call. Will wait up to timeout seconds
|
||||||
|
for a response and return a bytearray of response bytes, or None if no
|
||||||
|
response is available within the timeout.
|
||||||
|
"""
|
||||||
|
# Build frame data with command and parameters.
|
||||||
|
data = bytearray(2+len(params))
|
||||||
|
data[0] = _HOSTTOPN532
|
||||||
|
data[1] = command & 0xFF
|
||||||
|
for i, val in enumerate(params):
|
||||||
|
data[2+i] = val
|
||||||
|
# Send frame and wait for response.
|
||||||
|
try:
|
||||||
|
self._write_frame(data)
|
||||||
|
except OSError:
|
||||||
|
self._wakeup()
|
||||||
|
return None
|
||||||
|
if not self._wait_ready(timeout):
|
||||||
|
if(self.debug):
|
||||||
|
print('DEBUG: _wait_ready timed out waiting for ACK')
|
||||||
|
return None
|
||||||
|
# Verify ACK response and wait to be ready for function response.
|
||||||
|
if not _ACK == self._read_data(len(_ACK)):
|
||||||
|
raise RuntimeError('Did not receive expected ACK from PN532!')
|
||||||
|
if not self._wait_ready(timeout):
|
||||||
|
if(self.debug):
|
||||||
|
print('DEBUG: _wait_ready timed out waiting for response')
|
||||||
|
return None
|
||||||
|
# Read response bytes.
|
||||||
|
response = self._read_frame(response_length+2)
|
||||||
|
if(self.debug):
|
||||||
|
print('DEBUG: call_function response:', [hex(i) for i in response])
|
||||||
|
# Check that response is for the called function.
|
||||||
|
if not (response[0] == _PN532TOHOST and response[1] == (command+1)):
|
||||||
|
raise RuntimeError('Received unexpected command response!')
|
||||||
|
# Return response data.
|
||||||
|
return response[2:]
|
||||||
|
|
||||||
|
def get_firmware_version(self):
|
||||||
|
"""Call PN532 GetFirmwareVersion function and return a tuple with the IC,
|
||||||
|
Ver, Rev, and Support values.
|
||||||
|
"""
|
||||||
|
response = self.call_function(
|
||||||
|
_COMMAND_GETFIRMWAREVERSION, 4, timeout=500)
|
||||||
|
if response is None:
|
||||||
|
raise RuntimeError('Failed to detect the PN532')
|
||||||
|
return tuple(response)
|
||||||
|
|
||||||
|
def SAM_configuration(self): # pylint: disable=invalid-name
|
||||||
|
"""Configure the PN532 to read MiFare cards."""
|
||||||
|
# Send SAM configuration command with configuration for:
|
||||||
|
# - 0x01, normal mode
|
||||||
|
# - 0x14, timeout 50ms * 20 = 1 second
|
||||||
|
# - 0x01, use IRQ pin
|
||||||
|
# Note that no other verification is necessary as call_function will
|
||||||
|
# check the command was executed as expected.
|
||||||
|
self.call_function(_COMMAND_SAMCONFIGURATION,
|
||||||
|
params=[0x01, 0x14, 0x01])
|
||||||
|
|
||||||
|
def read_passive_target(self, card_baud=_MIFARE_ISO14443A, timeout=1000):
|
||||||
|
"""Wait for a MiFare card to be available and return its UID when found.
|
||||||
|
Will wait up to timeout seconds and return None if no card is found,
|
||||||
|
otherwise a bytearray with the UID of the found card is returned.
|
||||||
|
"""
|
||||||
|
# Send passive read command for 1 card. Expect at most a 7 byte UUID.
|
||||||
|
try:
|
||||||
|
response = self.call_function(_COMMAND_INLISTPASSIVETARGET,
|
||||||
|
params=[0x01, card_baud],
|
||||||
|
response_length=19,
|
||||||
|
timeout=timeout)
|
||||||
|
except BusyError:
|
||||||
|
return None # no card found!
|
||||||
|
# If no response is available return None to indicate no card is present.
|
||||||
|
if response is None:
|
||||||
|
return None
|
||||||
|
# Check only 1 card with up to a 7 byte UID is present.
|
||||||
|
if response[0] != 0x01:
|
||||||
|
raise RuntimeError('More than one card detected!')
|
||||||
|
if response[5] > 7:
|
||||||
|
raise RuntimeError('Found card with unexpectedly long UID!')
|
||||||
|
# Return UID of card.
|
||||||
|
return response[6:6+response[5]]
|
||||||
|
|
||||||
|
def ntag2xx_write_block(self, block_number, data):
|
||||||
|
"""Write a block of data to the card. Block number should be the block
|
||||||
|
to write and data should be a byte array of length 4 with the data to
|
||||||
|
write. If the data is successfully written then True is returned,
|
||||||
|
otherwise False is returned.
|
||||||
|
"""
|
||||||
|
assert data is not None and len(
|
||||||
|
data) == 4, 'Data must be an array of 4 bytes!'
|
||||||
|
# Build parameters for InDataExchange command to do NTAG203 classic write.
|
||||||
|
params = bytearray(3+len(data))
|
||||||
|
params[0] = 0x01 # Max card numbers
|
||||||
|
params[1] = MIFARE_ULTRALIGHT_CMD_WRITE
|
||||||
|
params[2] = block_number & 0xFF
|
||||||
|
params[3:] = data
|
||||||
|
# Send InDataExchange request.
|
||||||
|
response = self.call_function(_COMMAND_INDATAEXCHANGE,
|
||||||
|
params=params,
|
||||||
|
response_length=1)
|
||||||
|
return response[0] == 0x00
|
||||||
|
|
||||||
|
def ntag2xx_read_block(self, block_number):
|
||||||
|
"""Read a block of data from the card. Block number should be the block
|
||||||
|
to read. If the block is successfully read a bytearray of length 16 with
|
||||||
|
data starting at the specified block will be returned. If the block is
|
||||||
|
not read then None will be returned.
|
||||||
|
"""
|
||||||
|
return self.mifare_classic_read_block(block_number)[0:4] # only 4 bytes per page
|
||||||
|
|
||||||
|
def mifare_classic_read_block(self, block_number):
|
||||||
|
"""Read a block of data from the card. Block number should be the block
|
||||||
|
to read. If the block is successfully read a bytearray of length 16 with
|
||||||
|
data starting at the specified block will be returned. If the block is
|
||||||
|
not read then None will be returned.
|
||||||
|
"""
|
||||||
|
# Send InDataExchange request to read block of MiFare data.
|
||||||
|
response = self.call_function(_COMMAND_INDATAEXCHANGE,
|
||||||
|
params=[0x01, MIFARE_CMD_READ,
|
||||||
|
block_number & 0xFF],
|
||||||
|
response_length=17)
|
||||||
|
# Check first response is 0x00 to show success.
|
||||||
|
if response[0] != 0x00:
|
||||||
|
return None
|
||||||
|
# Return first 4 bytes since 16 bytes are always returned.
|
||||||
|
return response[1:]
|
||||||
|
|
||||||
|
def mifare_classic_authenticate_block(self, uid, block_number, key_number=MIFARE_CMD_AUTH_B, key=KEY_DEFAULT_B): # pylint: disable=invalid-name
|
||||||
|
"""Authenticate specified block number for a MiFare classic card. Uid
|
||||||
|
should be a byte array with the UID of the card, block number should be
|
||||||
|
the block to authenticate, key number should be the key type (like
|
||||||
|
MIFARE_CMD_AUTH_A or MIFARE_CMD_AUTH_B), and key should be a byte array
|
||||||
|
with the key data. Returns True if the block was authenticated, or False
|
||||||
|
if not authenticated.
|
||||||
|
"""
|
||||||
|
# Build parameters for InDataExchange command to authenticate MiFare card.
|
||||||
|
uidlen = len(uid)
|
||||||
|
keylen = len(key)
|
||||||
|
params = bytearray(3 + uidlen + keylen)
|
||||||
|
params[0] = 0x01 # Max card numbers
|
||||||
|
params[1] = key_number & 0xFF
|
||||||
|
params[2] = block_number & 0xFF
|
||||||
|
params[3 : 3 + keylen] = key
|
||||||
|
params[3 + keylen :] = uid
|
||||||
|
# Send InDataExchange request and verify response is 0x00.
|
||||||
|
response = self.call_function(
|
||||||
|
_COMMAND_INDATAEXCHANGE, params=params, response_length=1
|
||||||
|
)
|
||||||
|
return response[0] == 0x00
|
214
SW/RPi_Pico_Reader/main.py
Normal file
214
SW/RPi_Pico_Reader/main.py
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
import NFC_PN532 as nfc
|
||||||
|
import neopixel
|
||||||
|
import time
|
||||||
|
import sys
|
||||||
|
import select
|
||||||
|
from machine import Pin, SPI
|
||||||
|
|
||||||
|
#neopixel
|
||||||
|
ws_pin = 0
|
||||||
|
led_num = 8
|
||||||
|
BRIGHTNESS = 0.2 # Adjust the brightness (0.0 - 1.0)
|
||||||
|
|
||||||
|
led_strip = neopixel.NeoPixel(Pin(ws_pin), led_num)
|
||||||
|
|
||||||
|
def set_neopixel_brightness(color):
|
||||||
|
r, g, b = color
|
||||||
|
r = int(r * BRIGHTNESS)
|
||||||
|
g = int(g * BRIGHTNESS)
|
||||||
|
b = int(b * BRIGHTNESS)
|
||||||
|
return (r, g, b)
|
||||||
|
|
||||||
|
def set_neopixel_color(r,g,b):
|
||||||
|
color = (r,g,b)
|
||||||
|
color = set_neopixel_brightness(color)
|
||||||
|
led_strip.fill(color)
|
||||||
|
led_strip.write()
|
||||||
|
|
||||||
|
set_neopixel_color(0,0,0)
|
||||||
|
|
||||||
|
# SPI
|
||||||
|
spi_dev = SPI(0, baudrate=1000000)
|
||||||
|
cs = Pin(17, Pin.OUT)
|
||||||
|
cs.on()
|
||||||
|
|
||||||
|
# SENSOR INIT
|
||||||
|
pn532 = nfc.PN532(spi_dev,cs)
|
||||||
|
ic, ver, rev, support = pn532.get_firmware_version()
|
||||||
|
#print('Found PN532 with firmware version: {0}.{1}'.format(ver, rev))
|
||||||
|
|
||||||
|
# Configure PN532 to communicate with MiFare cards
|
||||||
|
pn532.SAM_configuration()
|
||||||
|
|
||||||
|
# FUNCTION TO READ NFC
|
||||||
|
def read_nfc(dev, tmot):
|
||||||
|
"""Accepts a device and a timeout in millisecs """
|
||||||
|
print('Reading...')
|
||||||
|
uid = dev.read_passive_target(timeout=tmot)
|
||||||
|
if uid is None:
|
||||||
|
print('CARD NOT FOUND')
|
||||||
|
else:
|
||||||
|
numbers = [i for i in uid]
|
||||||
|
string_ID = '{}-{}-{}-{}'.format(*numbers)
|
||||||
|
print('Found card with UID:', [hex(i) for i in uid])
|
||||||
|
print('Number_id: {}'.format(string_ID))
|
||||||
|
|
||||||
|
def loop_neopixel():
|
||||||
|
# Display red
|
||||||
|
color = (255, 0, 0) # Red color
|
||||||
|
color = set_neopixel_brightness(color)
|
||||||
|
led_strip.fill(color)
|
||||||
|
led_strip.write()
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
# Display green
|
||||||
|
color = (0, 255, 0) # Green color
|
||||||
|
color = set_neopixel_brightness(color)
|
||||||
|
led_strip.fill(color)
|
||||||
|
led_strip.write()
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
# Display blue
|
||||||
|
color = (0, 0, 255) # Blue color
|
||||||
|
color = set_neopixel_brightness(color)
|
||||||
|
led_strip.fill(color)
|
||||||
|
led_strip.write()
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
def read_nfc_loop():
|
||||||
|
sys.stdout.write('Waiting for RFID/NFC card to read!\r')
|
||||||
|
set_neopixel_color(255,0,0)
|
||||||
|
while True:
|
||||||
|
# Check if a card is available to read
|
||||||
|
uid = pn532.read_passive_target(timeout=0.5)
|
||||||
|
# Try again if no card is available.
|
||||||
|
if uid is not None:
|
||||||
|
break
|
||||||
|
|
||||||
|
set_neopixel_color(255,255,0)
|
||||||
|
|
||||||
|
ntag_string = 'Data: '
|
||||||
|
sys.stdout.write('Reading ntag \r')
|
||||||
|
|
||||||
|
leds_on = 0
|
||||||
|
for page in range(20,40):
|
||||||
|
try:
|
||||||
|
ntag2xx_page = pn532.ntag2xx_read_block(page)
|
||||||
|
if (page % 2) == 0:
|
||||||
|
if page == 0:
|
||||||
|
pass
|
||||||
|
elif page == 2:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
led_strip[leds_on] = (0,0,255)
|
||||||
|
leds_on += 1
|
||||||
|
if leds_on > 7:
|
||||||
|
leds_on = 7
|
||||||
|
led_strip.write()
|
||||||
|
|
||||||
|
if ntag2xx_page is not None:
|
||||||
|
for char in ntag2xx_page:
|
||||||
|
ntag_string += chr(char)
|
||||||
|
else:
|
||||||
|
sys.stdout.write('Error reading card\r')
|
||||||
|
return 1
|
||||||
|
except:
|
||||||
|
sys.stdout.write('Error reading card\r')
|
||||||
|
return 1
|
||||||
|
|
||||||
|
set_neopixel_color(0,255,0)
|
||||||
|
sys.stdout.write(ntag_string + '\r')
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
#print('PAGE ',page,': ',[chr(x) for x in ntag2xx_page])
|
||||||
|
|
||||||
|
def write_nfc_loop(data):
|
||||||
|
content = data.encode('utf-8')
|
||||||
|
length = len(content)
|
||||||
|
pages = int(length / 4)
|
||||||
|
if (length % 4) != 0:
|
||||||
|
pages += 1
|
||||||
|
|
||||||
|
sys.stdout.write("Waiting for RFID/NFC card to write to!\r")
|
||||||
|
set_neopixel_color(255,0,0)
|
||||||
|
while True:
|
||||||
|
# Check if a card is available to read
|
||||||
|
uid = pn532.read_passive_target(timeout=0.5)
|
||||||
|
# Try again if no card is available.
|
||||||
|
if uid is not None:
|
||||||
|
break
|
||||||
|
|
||||||
|
set_neopixel_color(255,255,0)
|
||||||
|
|
||||||
|
sys.stdout.write('Erasing card\r')
|
||||||
|
for page in range(20,41):
|
||||||
|
content_erase = b'\x00\x00\x00\x00'
|
||||||
|
pn532.ntag2xx_write_block(page, content_erase)
|
||||||
|
|
||||||
|
sys.stdout.write('Writing card\r')
|
||||||
|
for page in range(20,20 + pages):
|
||||||
|
content_slice = bytearray(4)
|
||||||
|
for i in range(0,4):
|
||||||
|
try:
|
||||||
|
content_slice[i] = (content[i + 4 * (page - 20)])
|
||||||
|
except:
|
||||||
|
content_slice[i] = 0
|
||||||
|
#content_slice.append(content[i + 4 * (page - 20)])
|
||||||
|
print(content_slice)
|
||||||
|
pn532.ntag2xx_write_block(page, content_slice)
|
||||||
|
|
||||||
|
sys.stdout.write('Write done\r')
|
||||||
|
set_neopixel_color(0,255,0)
|
||||||
|
|
||||||
|
def loop():
|
||||||
|
poll_results = poll_obj.poll(1)
|
||||||
|
if poll_results:
|
||||||
|
rw = sys.stdin.readline().strip()
|
||||||
|
sys.stdout.write("received data: " + rw + "\r")
|
||||||
|
rw = rw.lower()
|
||||||
|
if rw == 'w':
|
||||||
|
while True:
|
||||||
|
sys.stdout.write('ID: \r')
|
||||||
|
poll_results = poll_obj.poll(1)
|
||||||
|
data = sys.stdin.readline().strip()
|
||||||
|
write_nfc_loop(data)
|
||||||
|
elif rw == 'r':
|
||||||
|
while True:
|
||||||
|
ret = read_nfc_loop()
|
||||||
|
if ret == 255:
|
||||||
|
set_neopixel_color(0,0,255)
|
||||||
|
rw = None
|
||||||
|
return 1
|
||||||
|
elif rw == '':
|
||||||
|
while True:
|
||||||
|
ret = read_nfc_loop()
|
||||||
|
if ret == 255:
|
||||||
|
set_neopixel_color(0,0,255)
|
||||||
|
rw = None
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
sys.stdout.write('Invalid option\r')
|
||||||
|
|
||||||
|
poll_obj = select.poll()
|
||||||
|
poll_obj.register(sys.stdin, select.POLLIN)
|
||||||
|
|
||||||
|
set_neopixel_color(0,0,255)
|
||||||
|
|
||||||
|
|
||||||
|
while True:
|
||||||
|
poll_results = poll_obj.poll(1)
|
||||||
|
if poll_results:
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
ret = loop()
|
||||||
|
if ret == 1:
|
||||||
|
poll_results = None
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
set_neopixel_color(0,0,255)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
#except:
|
||||||
|
# set_neopixel_color(0,0,0)
|
11
Vysledky.txt
Normal file
11
Vysledky.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
Jan_Cada 37.30186375000012
|
||||||
|
Adam_Krejsa 37.911874899999994
|
||||||
|
Lukas_Bouchal 40.46594706666668
|
||||||
|
Lucie_Ponocna 40.77001086666654
|
||||||
|
Michal_Dolezal 48.86233890000003
|
||||||
|
Vojta_Flekr 49.97398888333325
|
||||||
|
David_Bedrnicek 55.68816689999985
|
||||||
|
David_Hubalek 65.28151173333329
|
||||||
|
Jenda 78.040001050000136
|
||||||
|
|
||||||
|
Nacelnik 31.216666667
|
1
log.json
1
log.json
@ -1 +0,0 @@
|
|||||||
[{"url": "https://beta.alkator.cz/api/card/register", "json": {"racer_id": 60, "starting_number": 2, "card_id": 1364550814, "time": "10.05.2025 17:40:13.486403"}}, {"url": "https://beta.alkator.cz/api/station/register", "json": {"card_id": 1364550814, "time": "10.05.2025 17:42:45.425016", "station_id": 1}}]
|
|
Loading…
x
Reference in New Issue
Block a user