42 Commits

Author SHA1 Message Date
Dave
58875cd1b6 Update for CircuitPython 10.x support 2026-01-10 15:40:24 -06:00
XtramCZ
04eeacac09 Small improvements (#195)
* fixed crashes on one-line scripts, auto .dd

* Delete button

* Additional crash fix

* Disable read-only

---------

Co-authored-by: Dave <dbisu@users.noreply.github.com>
2026-01-10 12:17:16 -06:00
IDoNotHaveAUsernam3
c3184a5390 Fix "The next four lines" to replace four with five (#338) 2026-01-10 12:01:10 -06:00
Tzur Soffer
fb55875e3c Variable and expression bugfixes (#325)
* Fix evaluating with Booleans

* replaced re with a function (this feature of re is not supported on circutpython)

* Fixed internalVar in expression + allows for +=, *=, etc in variable math

* Removed added +=, *=, etc operations as they are not in the official language

Removed added +=, *=, etc operations as they are not in the official language. I added them in a previous commit and removed them in this one.

* Fix duplicate lines
2026-01-10 12:00:15 -06:00
Linusx
986c919616 Update webapp.py / web ui (#144)
* Update webapp.py

PS: Font will work on most devices (preinstalled), else it doesn't really matter

* Update webapp.py
2026-01-10 11:57:08 -06:00
Dave
10bc8b9489 Moved pin definitions into pins.py to help support different board form factors 2026-01-10 11:11:19 -06:00
ooqe
5ac23fdaf0 Fix syntax error in await runScript call (#336) 2025-11-25 16:53:40 -06:00
Cheesy
d730a804e0 Adds Keystroke Reflection Exfoliation (#335)
* Adds Hak5's Keystroke Reflection Exfoliation

Adds a way to read in caps, scroll, and num lock so that you can export information from the attack into a loot.bin. Has some caveats on how it works

* Fixed programing status bug
2025-11-16 19:15:54 -06:00
Dave
ca88c6c159 Fix which issue templates are available (#329)
Co-authored-by: Dave <dbisu>
2025-03-14 22:16:04 -05:00
Tzur Soffer
ab753989d5 add internal variables (#321)
* add internal variables

* remove extra spacing
2025-02-01 20:28:15 -06:00
Tzur Soffer
522e640c26 While loops and conditional statements (#316)
* added math to variables as well as the ability to use them in DELAY and PRINT/PRINTLN

* add comparisons

* fix typo

* Added While loops and Conditional statements

* If and While loops working
2025-01-26 17:26:45 -06:00
Tzur Soffer
e61d232b46 Variable MATH (#304)
* added math to variables as well as the ability to use them in DELAY and PRINT/PRINTLN

* add comparisons

* fix typo
2025-01-23 19:58:59 -06:00
Dave
6f9cbc3d80 Change link to new PicoDuckyBuilder script (#315)
Co-authored-by: Dave <dbisu>
2025-01-16 19:09:27 -06:00
Dave
fda4617e33 Fix build script to find the correct keyboard_ lines (#311)
Co-authored-by: Dave <dbisu>
2025-01-15 21:01:30 -06:00
Tzur Soffer
90a76bcada remove power key due to keyboard layout issues (#310) 2025-01-15 20:56:12 -06:00
Tzur Soffer
8b9822151f Added duckyScript 3.0 functionality (#300)
* Added HOLD and RELEASE

* Update removed unnecessary heldKeys var

* Fixed HOLD being released after key press

* added REM_BLOCK, STRING Block, and STRINGLN Block

* LED + INJECT_MOD

* add define

* added all randoms

* added stop, restart, reset

* bugfixes and cleanup

* added missing keys
2025-01-03 14:40:40 -06:00
Dave
2dea346723 Fix bug importing keyboard layouts (#302) 2024-12-29 13:48:06 -06:00
Dave
8b11882c52 Pico2 support (#299)
* Add support for Pico2/2W boards

* Update documentation to include Pico2/2W

* update language support
2024-12-21 12:00:23 -06:00
Dave
8bcd2aa456 Add bundle script 2024-12-20 23:41:27 -06:00
Tony
f1636c3e45 Add functions, while loops, and vars support (#264)
* Add functions, while loops, and vars support

* Add back REPEAT

* Add support for nested WHILE loops in function

---------

Co-authored-by: Tony Le <tonyle@coxautoinc.com>
2024-09-21 12:18:16 -05:00
Dave
5dd0783886 Add debugging instructions 2024-03-12 19:54:10 -05:00
William
3caf2ceb98 added new wait_for_button_press functionality (#234) 2024-02-13 20:16:43 -06:00
Dave
70eb2cd8b0 Add link to defcon31-ducky project 2024-01-16 19:18:05 -06:00
Piotr Ginał
0113b0e004 Fix typo (#197) 2023-09-17 15:59:29 -05:00
Dave
74ef11770b Clarify getting latest release 2023-06-24 13:07:19 -05:00
Dave
a7992c2fb3 Update installation instructions 2023-06-24 12:58:58 -05:00
Dave
49e81125c1 Updated issue template 2023-06-24 10:01:39 -05:00
Antoine Meloche
221e796449 DOC: typo fix in README.md (#172)
DuckScript -> DuckyScript
2023-04-17 18:22:01 -05:00
LoneWolf
e12c0bf892 Add files via upload (#150) 2023-03-26 14:10:20 -05:00
Dave
5ea13cf7c2 Fix formatting for secrets.py 2023-03-17 19:40:57 -05:00
Dave
a5cbb0cb34 Update README instructions to include setting up AP info in secrets.py 2023-03-17 19:18:32 -05:00
Dave
ce00d8ddc9 fix language support (#140) 2023-02-19 13:58:20 -06:00
Dave
b99ddf37e5 Pico W Support (#137)
* Refactor code to support Pico W board

* Updates for Pico W support

* Update based on changes in CircuitPython v8.0.0 beta 6

* Updated bundle download to 8.x, fixed a few typos

* Updating documentation for web interface

* Update support for CircuitPython 8.0.0, fix many bugs

* Document multiple payload options

* Update copyright dates

* Fixed typo
2023-02-18 16:21:53 -06:00
Oussamaosman02
99900ed5d5 Updating installation tool repo and user (#129) 2023-01-16 10:57:58 -06:00
Christoph Mantsch
164ecff72a Update links for payloads and DuckyScript reference (#116) 2022-11-21 21:03:25 -06:00
Dave
97e926bda0 Updating issue templates 2022-10-29 21:13:14 -05:00
Dave
4c0db1a0e1 Update issue templates 2022-10-29 21:09:16 -05:00
Dave
d4957e2e95 Doc updates (#104)
* Update instructions to include copying boot.py

* Clean up instructions

* Fix formatting
2022-09-26 20:59:21 -05:00
Dave
6516c8bbe4 Add reset instructions (#99) 2022-09-19 18:11:26 -05:00
Dave
3a7411e55e Change button monitoring and LED to async tasks (#98) 2022-09-18 11:36:22 -05:00
Dave
e51a769cdd Fix library includes and GPIO names (#93) 2022-09-03 08:34:07 -05:00
Dave
f02c061543 Add button to run scripts (#92) 2022-08-28 22:56:16 -05:00
31 changed files with 1587 additions and 3512 deletions

1
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1 @@
blank_issues_enabled: false

29
.github/ISSUE_TEMPLATE/not-working.md vendored Normal file
View File

@@ -0,0 +1,29 @@
---
name: Not Working
about: Create a report if something is not working correctly
title: ''
labels: ''
assignees: ''
---
**Describe the issue**
A clear and concise description of the symptoms
**To Reproduce**
Steps to reproduce the behavior:
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Debug info**
If possible, include debug serial data.
On Windows, use PuTTY, connect to the debug serial port (commonly COM3, but could vary)
On Linux, use minicom (minicom -b 115200 -o -D /dev/ttyACM0, where ttyACM0 corresponds to your device)
**Additional context**
Add any other context about the problem here.

6
DEBUG.md Normal file
View File

@@ -0,0 +1,6 @@
# Instructions on how to collect debug logs
* On Windows, use [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html) to connect to the debug serial port (commonly COM3, but could vary on your machine).
* On Linux, use minicom (minicom -b 115200 -o -D /dev/ttyACM0, where ttyACM0 corresponds to your device).
* On Ubuntu: `sudo apt install minicom`

165
README.md
View File

@@ -16,48 +16,156 @@
<br /> <br />
## Install ## Quick Start Guide
Install and have your USB Rubber Ducky working in less than 5 minutes. Install and have your USB Rubber Ducky working in less than 5 minutes.
1. Download [CircuitPython for the Raspberry Pi Pico](https://circuitpython.org/board/raspberry_pi_pico/). *Updated to 7.0.0 1. Download the latest release from the [Releases](https://github.com/dbisu/pico-ducky/releases) page.
2. Plug the device into a USB port while holding the boot button. It will show up as a removable media device named `RPI-RP2`. 2. Plug the device into a USB port while holding the boot button. It will show up as a removable media device named RPI-RP2.
3. Copy the downloaded `.uf2` file to the root of the Pico (`RPI-RP2`). The device will reboot and after a second or so, it will reconnect as `CIRCUITPY`. 3. Install CircutlPython on the Pico or Pico W
4. Download `adafruit-circuitpython-bundle-7.x-mpy-YYYYMMDD.zip` [here](https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases/latest) and extract it outside the device. If using a Pico board:
5. Navigate to `lib` in the recently extracted folder and copy `adafruit_hid` to the `lib` folder in your Raspberry Pi Pico. Copy the adafruit-circuitpython-raspberry_pi_pico-en_US-10.0.3.uf2 file to the root of the Pico (RPI-RP2). The device will reboot and after a second or so, it will reconnect as CIRCUITPY.
6. Click [here](https://raw.githubusercontent.com/dbisu/pico-ducky/main/duckyinpython.py), press CTRL + S and save the file as `code.py` in the root of the Raspberry Pi Pico, overwriting the previous file. If using a Pico W board:
7. Find a script [here](https://github.com/hak5darren/USB-Rubber-Ducky/wiki/Payloads) or [create your own one using Ducky Script](https://github.com/hak5darren/USB-Rubber-Ducky/wiki/Duckyscript) and save it as `payload.dd` in the Pico. Copy the adafruit-circuitpython-raspberry_pi_pico_w-en_US-10.0.3.uf2 file to the root of the Pico (RPI-RP2). The device will reboot and after a second or so, it will reconnect as CIRCUITPY.
8. Be careful, if your device isn't in [setup mode](#setup-mode), the device will reboot and after half a second, the script will run. If using a Pico 2 board:
### Setup mode Copy the adafruit-circuitpython-raspberry_pi_pico2-en_US-10.0.3.uf2 file to the root of the Pico (RPI-RP2). The device will reboot and after a second or so, it will reconnect as CIRCUITPY.
If using a Pico 2W board:
Copy the adafruit-circuitpython-raspberry_pi_pico2_w-en_US-10.0.3.uf2 file to the root of the Pico (RPI-RP2). The device will reboot and after a second or so, it will reconnect as CIRCUITPY.
4. Copy the lib folder to the root of the CIRCUITPY
5. Copy *.py to the root of the CIRCUITPY
6. Follow the instructions in README.md to enter setup mode
7. Copy your payload as payload.dd to the root of the CIRCUITPY
8. Unplug the device from the USB port and remove the setup jumper.
Enjoy your Pico-Ducky.
## Setup mode
To edit the payload, enter setup mode by connecting the pin 1 (`GP0`) to pin 3 (`GND`), this will stop the pico-ducky from injecting the payload in your own machine. To edit the payload, enter setup mode by connecting the pin 1 (`GP0`) to pin 3 (`GND`), this will stop the pico-ducky from injecting the payload in your own machine.
The easiest way to so is by using a jumper wire between those pins as seen bellow. The easiest way to do so is by using a jumper wire between those pins as seen bellow.
![Setup mode with a jumper](images/setup-mode.png) ![Setup mode with a jumper](images/setup-mode.png)
### USB enable/disable mode ## USB enable/disable mode
If you need the pico-ducky to not show up as a USB mass storage device for stealth, follow these instructions. If you need the pico-ducky to not show up as a USB mass storage device for stealth, follow these instructions.
Enter setup mode. - Enter setup mode.
Copy boot.py to the root of the pico-ducky. - Copy your payload script to the pico-ducky.
Copy your payload script to the pico-ducky. - Disconnect the pico from your host PC.
Disconnect the pico from your host PC. - Connect a jumper wire between pin 18 (`GND`) and pin 20 (`GPIO15`).
Connect a jumper wire between pin 18 (`GND`) and pin 20 (`GPIO15`).
This will prevent the pico-ducky from showing up as a USB drive when plugged into the target computer. This will prevent the pico-ducky from showing up as a USB drive when plugged into the target computer.
Remove the jumper and reconnect to your PC to reprogram. - Remove the jumper and reconnect to your PC to reprogram.
The default mode is USB mass storage enabled.
Pico: The default mode is USB mass storage enabled.
Pico W: The default mode is USB mass storage **disabled**
![USB enable/disable mode](images/usb-boot-mode.png) ![USB enable/disable mode](images/usb-boot-mode.png)
### Changing Keyboard Layouts
-----
# Full Install Instructions
Install and have your USB Rubber Ducky working in less than 5 minutes.
1. Clone the repo to get a local copy of the files. `git clone https://github.com/dbisu/pico-ducky.git`
2. Download [CircuitPython for the Raspberry Pi Pico](https://circuitpython.org/board/raspberry_pi_pico/). *Updated to 10.0.3
Download [CircuitPython for the Raspberry Pi Pico W](https://circuitpython.org/board/raspberry_pi_pico_w/). *Updated to 10.0.3
Download [CircuitPython for the Raspberry Pi Pico 2](https://circuitpython.org/board/raspberry_pi_pico2/). *Updated to 10.0.3
Download [CircuitPython for the Raspberry Pi Pico 2W](https://circuitpython.org/board/raspberry_pi_pico2_w/). *Updated to 10.0.3
3. Plug the device into a USB port while holding the boot button. It will show up as a removable media device named `RPI-RP2`.
4. Copy the downloaded `.uf2` file to the root of the Pico (`RPI-RP2`). The device will reboot and after a second or so, it will reconnect as `CIRCUITPY`.
5. Download `adafruit-circuitpython-bundle-10.x-mpy-YYYYMMDD.zip` [here](https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases/latest) and extract it outside the device.
6. Navigate to `lib` in the recently extracted folder and copy `adafruit_hid` to the `lib` folder on your Raspberry Pi Pico.
7. Copy `adafruit_debouncer.mpy` and `adafruit_ticks.mpy` to the `lib` folder on your Raspberry Pi Pico.
8. Copy `asyncio` to the `lib` folder on your Pico.
9. Copy `adafruit_wsgi` to the `lib` folder on your Pico.
10. Copy `boot.py` from your clone to the root of your Pico.
11. Copy `duckyinpython.py`, `code.py`, `pins.py`, `webapp.py`, `wsgiserver.py` to the root folder of the Pico.
12. *For Pico W Only* Create the file `secrets.py` in the root of the Pico W. This contains the AP name and password to be created by the Pico W.
`secrets = { 'ssid' : "BadAPName", 'password' : "badpassword" }`
13. Find a script [here](https://github.com/hak5/usbrubberducky-payloads) or [create your own one using Ducky Script](https://docs.hak5.org/hak5-usb-rubber-ducky/ducky-script-basics/hello-world) and save it as `payload.dd` in the Pico. Currently, pico-ducky only supports DuckyScript 1.0, and some of 3.0.
14. Be careful, if your device isn't in [setup mode](#setup-mode), the device will reboot and after half a second, the script will run.
15. **Please note:** by default Pico W will not show as a USB drive
### Pico W Web Service
The Pico W AP defaults to ip address `192.168.4.1`. You should be able to find the webservice at `http://192.168.4.1:80`
The following endpoints are available on the webservice:
```
/
/new
/ducky
/edit/<filename>
/write/<filename>
/run/<filename>
```
API endpoints
```
/api/run/<filenumber>
```
## Setup mode
To edit the payload, enter setup mode by connecting the pin 1 (`GP0`) to pin 3 (`GND`), this will stop the pico-ducky from injecting the payload in your own machine.
The easiest way to do so is by using a jumper wire between those pins as seen bellow.
![Setup mode with a jumper](images/setup-mode.png)
## USB enable/disable mode
If you need the pico-ducky to not show up as a USB mass storage device for stealth, follow these instructions.
- Enter setup mode.
- Copy your payload script to the pico-ducky.
- Disconnect the pico from your host PC.
- Connect a jumper wire between pin 18 (`GND`) and pin 20 (`GPIO15`).
This will prevent the pico-ducky from showing up as a USB drive when plugged into the target computer.
- Remove the jumper and reconnect to your PC to reprogram.
Pico: The default mode is USB mass storage enabled.
Pico W: The default mode is USB mass storage **disabled**
![USB enable/disable mode](images/usb-boot-mode.png)
## Multiple payloads
Multiple payloads can be stored on the Pico and Pico W.
To select a payload, ground one of these pins:
- GP4 - payload.dd
- GP5 - payload2.dd
- GP10 - payload3.dd
- GP11 - payload4.dd
## Changing Keyboard Layouts
Copied from [Neradoc/Circuitpython_Keyboard_Layouts](https://github.com/Neradoc/Circuitpython_Keyboard_Layouts/blob/main/PICODUCKY.md) Copied from [Neradoc/Circuitpython_Keyboard_Layouts](https://github.com/Neradoc/Circuitpython_Keyboard_Layouts/blob/main/PICODUCKY.md)
@@ -129,14 +237,18 @@ keycode_win_de.mpy
## Useful links and resources ## Useful links and resources
### How to recover your Pico if it becomes corrupted or doesn't boot.
[Reset Instructions](RESET.md)
### Installation Tool ### Installation Tool
[raspberrypi5621](https://github.com/raspberrypi5621) Created a tool to convert a blank RPi Pico to a ducky. [ryo-yamada](https://github.com/ryo-yamada) Created a tool to convert a blank RPi Pico to a ducky.
You can find the tool [here](https://github.com/raspberrypi5621/pyducky) You can find the tool [here](https://github.com/ryo-yamada/PicoDuckyBuilder)
### Docs ### Docs
[CircuitPython](https://circuitpython.readthedocs.io/en/6.3.x/README.html) [CircuitPython](https://docs.circuitpython.org/en/latest/README.html)
[CircuitPython HID](https://learn.adafruit.com/circuitpython-essentials/circuitpython-hid-keyboard-and-mouse) [CircuitPython HID](https://learn.adafruit.com/circuitpython-essentials/circuitpython-hid-keyboard-and-mouse)
@@ -149,3 +261,8 @@ You can find the tool [here](https://github.com/raspberrypi5621/pyducky)
[USB Rubber Ducky playlist by **Hak5**](https://www.youtube.com/playlist?list=PLW5y1tjAOzI0YaJslcjcI4zKI366tMBYk) [USB Rubber Ducky playlist by **Hak5**](https://www.youtube.com/playlist?list=PLW5y1tjAOzI0YaJslcjcI4zKI366tMBYk)
[CircuitPython tutorial on the Raspberry Pi Pico by **DroneBot Workshop**](https://www.youtube.com/watch?v=07vG-_CcDG0) [CircuitPython tutorial on the Raspberry Pi Pico by **DroneBot Workshop**](https://www.youtube.com/watch?v=07vG-_CcDG0)
## Related Projects
[Defcon31-ducky](https://github.com/iot-pwn/defcon31-ducky)

7
RESET.md Normal file
View File

@@ -0,0 +1,7 @@
# Instructions on how to reset a Raspberry Pi Pico
Follow these instructions if your Pico ends up in an odd state
1. Download the reset firmware from [flash_nuke.uf2](https://datasheets.raspberrypi.com/soft/flash_nuke.uf2)
2. While holding the BOOTSEL button on the Pico, plug in the USB cable to your computer.
3. When the RPI-RP2 drive shows up on your computer, copy the flash_nuke.uf2 file to the Pico
4. After the device reboots, follow the Install instructions [here](https://github.com/dbisu/pico-ducky/blob/main/README.md)

View File

@@ -1,209 +0,0 @@
%TF.GenerationSoftware,KiCad,Pcbnew,6.0.1-79c1e3a40b~116~ubuntu20.04.1*%
%TF.CreationDate,2022-02-10T07:45:31-06:00*%
%TF.ProjectId,pico-ducky,7069636f-2d64-4756-936b-792e6b696361,rev?*%
%TF.SameCoordinates,Original*%
%TF.FileFunction,Copper,L2,Bot*%
%TF.FilePolarity,Positive*%
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW 6.0.1-79c1e3a40b~116~ubuntu20.04.1) date 2022-02-10 07:45:31*
%MOMM*%
%LPD*%
G01*
G04 APERTURE LIST*
%TA.AperFunction,ComponentPad*%
%ADD10C,1.320800*%
%TD*%
%TA.AperFunction,ComponentPad*%
%ADD11C,1.752600*%
%TD*%
%TA.AperFunction,ComponentPad*%
%ADD12R,1.700000X1.700000*%
%TD*%
%TA.AperFunction,ComponentPad*%
%ADD13O,1.700000X1.700000*%
%TD*%
%TA.AperFunction,ComponentPad*%
%ADD14R,1.308000X1.308000*%
%TD*%
%TA.AperFunction,ComponentPad*%
%ADD15C,1.308000*%
%TD*%
G04 APERTURE END LIST*
D10*
%TO.P,SW3,1,1*%
%TO.N,Net-(J1-Pad6)*%
X105400000Y-71800000D03*
%TO.P,SW3,2,2*%
%TO.N,Net-(J1-Pad7)*%
X105400000Y-73800001D03*
%TO.P,SW3,3,3*%
%TO.N,Net-(J1-Pad8)*%
X105400000Y-75800000D03*
%TO.P,SW3,4,4*%
%TO.N,Net-(J1-Pad13)*%
X105400000Y-77800001D03*
%TO.P,SW3,5,5*%
%TO.N,Net-(J1-Pad14)*%
X105400000Y-79799999D03*
%TO.P,SW3,6,6*%
%TO.N,Net-(J1-Pad15)*%
X105400000Y-81800000D03*
D11*
%TO.P,SW3,7*%
%TO.N,N/C*%
X105400000Y-69700000D03*
%TO.P,SW3,8*%
X105400000Y-83900000D03*
%TD*%
D12*
%TO.P,J2,1,Pin_1*%
%TO.N,unconnected-(J2-Pad1)*%
X131000000Y-53400000D03*
D13*
%TO.P,J2,2,Pin_2*%
%TO.N,unconnected-(J2-Pad2)*%
X131000000Y-55940000D03*
%TO.P,J2,3,Pin_3*%
%TO.N,unconnected-(J2-Pad3)*%
X131000000Y-58480000D03*
%TO.P,J2,4,Pin_4*%
%TO.N,unconnected-(J2-Pad4)*%
X131000000Y-61020000D03*
%TO.P,J2,5,Pin_5*%
%TO.N,unconnected-(J2-Pad5)*%
X131000000Y-63560000D03*
%TO.P,J2,6,Pin_6*%
%TO.N,unconnected-(J2-Pad6)*%
X131000000Y-66100000D03*
%TO.P,J2,7,Pin_7*%
%TO.N,unconnected-(J2-Pad7)*%
X131000000Y-68640000D03*
%TO.P,J2,8,Pin_8*%
%TO.N,unconnected-(J2-Pad8)*%
X131000000Y-71180000D03*
%TO.P,J2,9,Pin_9*%
%TO.N,unconnected-(J2-Pad9)*%
X131000000Y-73720000D03*
%TO.P,J2,10,Pin_10*%
%TO.N,unconnected-(J2-Pad10)*%
X131000000Y-76260000D03*
%TO.P,J2,11,Pin_11*%
%TO.N,unconnected-(J2-Pad11)*%
X131000000Y-78800000D03*
%TO.P,J2,12,Pin_12*%
%TO.N,unconnected-(J2-Pad12)*%
X131000000Y-81340000D03*
%TO.P,J2,13,Pin_13*%
%TO.N,unconnected-(J2-Pad13)*%
X131000000Y-83880000D03*
%TO.P,J2,14,Pin_14*%
%TO.N,unconnected-(J2-Pad14)*%
X131000000Y-86420000D03*
%TO.P,J2,15,Pin_15*%
%TO.N,unconnected-(J2-Pad15)*%
X131000000Y-88960000D03*
%TO.P,J2,16,Pin_16*%
%TO.N,unconnected-(J2-Pad16)*%
X131000000Y-91500000D03*
%TO.P,J2,17,Pin_17*%
%TO.N,unconnected-(J2-Pad17)*%
X131000000Y-94040000D03*
%TO.P,J2,18,Pin_18*%
%TO.N,unconnected-(J2-Pad18)*%
X131000000Y-96580000D03*
%TO.P,J2,19,Pin_19*%
%TO.N,unconnected-(J2-Pad19)*%
X131000000Y-99120000D03*
%TO.P,J2,20,Pin_20*%
%TO.N,unconnected-(J2-Pad20)*%
X131000000Y-101660000D03*
%TD*%
D14*
%TO.P,S1,1*%
%TO.N,Net-(J1-Pad18)*%
X105200000Y-98000000D03*
D15*
%TO.P,S1,2*%
%TO.N,unconnected-(S1-Pad2)*%
X105200000Y-95460000D03*
%TO.P,S1,3*%
%TO.N,Net-(J1-Pad20)*%
X105200000Y-100540000D03*
%TD*%
D12*
%TO.P,J1,1,Pin_1*%
%TO.N,Net-(J1-Pad1)*%
X112950000Y-53205000D03*
D13*
%TO.P,J1,2,Pin_2*%
%TO.N,unconnected-(J1-Pad2)*%
X112950000Y-55745000D03*
%TO.P,J1,3,Pin_3*%
%TO.N,Net-(J1-Pad3)*%
X112950000Y-58285000D03*
%TO.P,J1,4,Pin_4*%
%TO.N,unconnected-(J1-Pad4)*%
X112950000Y-60825000D03*
%TO.P,J1,5,Pin_5*%
%TO.N,unconnected-(J1-Pad5)*%
X112950000Y-63365000D03*
%TO.P,J1,6,Pin_6*%
%TO.N,Net-(J1-Pad6)*%
X112950000Y-65905000D03*
%TO.P,J1,7,Pin_7*%
%TO.N,Net-(J1-Pad7)*%
X112950000Y-68445000D03*
%TO.P,J1,8,Pin_8*%
%TO.N,Net-(J1-Pad8)*%
X112950000Y-70985000D03*
%TO.P,J1,9,Pin_9*%
%TO.N,unconnected-(J1-Pad9)*%
X112950000Y-73525000D03*
%TO.P,J1,10,Pin_10*%
%TO.N,unconnected-(J1-Pad10)*%
X112950000Y-76065000D03*
%TO.P,J1,11,Pin_11*%
%TO.N,unconnected-(J1-Pad11)*%
X112950000Y-78605000D03*
%TO.P,J1,12,Pin_12*%
%TO.N,unconnected-(J1-Pad12)*%
X112950000Y-81145000D03*
%TO.P,J1,13,Pin_13*%
%TO.N,Net-(J1-Pad13)*%
X112950000Y-83685000D03*
%TO.P,J1,14,Pin_14*%
%TO.N,Net-(J1-Pad14)*%
X112950000Y-86225000D03*
%TO.P,J1,15,Pin_15*%
%TO.N,Net-(J1-Pad15)*%
X112950000Y-88765000D03*
%TO.P,J1,16,Pin_16*%
%TO.N,unconnected-(J1-Pad16)*%
X112950000Y-91305000D03*
%TO.P,J1,17,Pin_17*%
%TO.N,unconnected-(J1-Pad17)*%
X112950000Y-93845000D03*
%TO.P,J1,18,Pin_18*%
%TO.N,Net-(J1-Pad18)*%
X112950000Y-96385000D03*
%TO.P,J1,19,Pin_19*%
%TO.N,unconnected-(J1-Pad19)*%
X112950000Y-98925000D03*
%TO.P,J1,20,Pin_20*%
%TO.N,Net-(J1-Pad20)*%
X112950000Y-101465000D03*
%TD*%
D14*
%TO.P,S2,1*%
%TO.N,Net-(J1-Pad3)*%
X105700000Y-56740000D03*
D15*
%TO.P,S2,2*%
%TO.N,Net-(J1-Pad1)*%
X105700000Y-54200000D03*
%TO.P,S2,3*%
%TO.N,unconnected-(S2-Pad3)*%
X105700000Y-59280000D03*
%TD*%
M02*

View File

@@ -1,110 +0,0 @@
%TF.GenerationSoftware,KiCad,Pcbnew,6.0.1-79c1e3a40b~116~ubuntu20.04.1*%
%TF.CreationDate,2022-02-10T07:45:33-06:00*%
%TF.ProjectId,pico-ducky,7069636f-2d64-4756-936b-792e6b696361,rev?*%
%TF.SameCoordinates,Original*%
%TF.FileFunction,Soldermask,Bot*%
%TF.FilePolarity,Negative*%
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW 6.0.1-79c1e3a40b~116~ubuntu20.04.1) date 2022-02-10 07:45:33*
%MOMM*%
%LPD*%
G01*
G04 APERTURE LIST*
%ADD10C,1.320800*%
%ADD11C,1.752600*%
%ADD12R,1.700000X1.700000*%
%ADD13O,1.700000X1.700000*%
%ADD14R,1.308000X1.308000*%
%ADD15C,1.308000*%
%ADD16C,3.200000*%
G04 APERTURE END LIST*
D10*
%TO.C,SW3*%
X105400000Y-71800000D03*
X105400000Y-73800001D03*
X105400000Y-75800000D03*
X105400000Y-77800001D03*
X105400000Y-79799999D03*
X105400000Y-81800000D03*
D11*
X105400000Y-69700000D03*
X105400000Y-83900000D03*
%TD*%
D12*
%TO.C,J2*%
X131000000Y-53400000D03*
D13*
X131000000Y-55940000D03*
X131000000Y-58480000D03*
X131000000Y-61020000D03*
X131000000Y-63560000D03*
X131000000Y-66100000D03*
X131000000Y-68640000D03*
X131000000Y-71180000D03*
X131000000Y-73720000D03*
X131000000Y-76260000D03*
X131000000Y-78800000D03*
X131000000Y-81340000D03*
X131000000Y-83880000D03*
X131000000Y-86420000D03*
X131000000Y-88960000D03*
X131000000Y-91500000D03*
X131000000Y-94040000D03*
X131000000Y-96580000D03*
X131000000Y-99120000D03*
X131000000Y-101660000D03*
%TD*%
D14*
%TO.C,S1*%
X105200000Y-98000000D03*
D15*
X105200000Y-95460000D03*
X105200000Y-100540000D03*
%TD*%
D16*
%TO.C,REF\u002A\u002A*%
X105500000Y-46600000D03*
%TD*%
D12*
%TO.C,J1*%
X112950000Y-53205000D03*
D13*
X112950000Y-55745000D03*
X112950000Y-58285000D03*
X112950000Y-60825000D03*
X112950000Y-63365000D03*
X112950000Y-65905000D03*
X112950000Y-68445000D03*
X112950000Y-70985000D03*
X112950000Y-73525000D03*
X112950000Y-76065000D03*
X112950000Y-78605000D03*
X112950000Y-81145000D03*
X112950000Y-83685000D03*
X112950000Y-86225000D03*
X112950000Y-88765000D03*
X112950000Y-91305000D03*
X112950000Y-93845000D03*
X112950000Y-96385000D03*
X112950000Y-98925000D03*
X112950000Y-101465000D03*
%TD*%
D14*
%TO.C,S2*%
X105700000Y-56740000D03*
D15*
X105700000Y-54200000D03*
X105700000Y-59280000D03*
%TD*%
D16*
%TO.C,REF\u002A\u002A*%
X135400000Y-46700000D03*
%TD*%
%TO.C,REF\u002A\u002A*%
X135500000Y-107300000D03*
%TD*%
%TO.C,REF\u002A\u002A*%
X105800000Y-107400000D03*
%TD*%
M02*

View File

@@ -1,15 +0,0 @@
%TF.GenerationSoftware,KiCad,Pcbnew,6.0.1-79c1e3a40b~116~ubuntu20.04.1*%
%TF.CreationDate,2022-02-10T07:45:32-06:00*%
%TF.ProjectId,pico-ducky,7069636f-2d64-4756-936b-792e6b696361,rev?*%
%TF.SameCoordinates,Original*%
%TF.FileFunction,Paste,Bot*%
%TF.FilePolarity,Positive*%
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW 6.0.1-79c1e3a40b~116~ubuntu20.04.1) date 2022-02-10 07:45:32*
%MOMM*%
%LPD*%
G01*
G04 APERTURE LIST*
G04 APERTURE END LIST*
M02*

View File

@@ -1,15 +0,0 @@
%TF.GenerationSoftware,KiCad,Pcbnew,6.0.1-79c1e3a40b~116~ubuntu20.04.1*%
%TF.CreationDate,2022-02-10T07:45:32-06:00*%
%TF.ProjectId,pico-ducky,7069636f-2d64-4756-936b-792e6b696361,rev?*%
%TF.SameCoordinates,Original*%
%TF.FileFunction,Legend,Bot*%
%TF.FilePolarity,Positive*%
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW 6.0.1-79c1e3a40b~116~ubuntu20.04.1) date 2022-02-10 07:45:32*
%MOMM*%
%LPD*%
G01*
G04 APERTURE LIST*
G04 APERTURE END LIST*
M02*

View File

@@ -1,26 +0,0 @@
%TF.GenerationSoftware,KiCad,Pcbnew,6.0.1-79c1e3a40b~116~ubuntu20.04.1*%
%TF.CreationDate,2022-02-10T07:45:33-06:00*%
%TF.ProjectId,pico-ducky,7069636f-2d64-4756-936b-792e6b696361,rev?*%
%TF.SameCoordinates,Original*%
%TF.FileFunction,Profile,NP*%
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW 6.0.1-79c1e3a40b~116~ubuntu20.04.1) date 2022-02-10 07:45:33*
%MOMM*%
%LPD*%
G01*
G04 APERTURE LIST*
%TA.AperFunction,Profile*%
%ADD10C,0.100000*%
%TD*%
G04 APERTURE END LIST*
D10*
X102120000Y-43060000D02*
X139030000Y-43060000D01*
X139030000Y-43060000D02*
X139030000Y-111080000D01*
X139030000Y-111080000D02*
X102120000Y-111080000D01*
X102120000Y-111080000D02*
X102120000Y-43060000D01*
M02*

View File

@@ -1,264 +0,0 @@
%TF.GenerationSoftware,KiCad,Pcbnew,6.0.1-79c1e3a40b~116~ubuntu20.04.1*%
%TF.CreationDate,2022-02-10T07:45:31-06:00*%
%TF.ProjectId,pico-ducky,7069636f-2d64-4756-936b-792e6b696361,rev?*%
%TF.SameCoordinates,Original*%
%TF.FileFunction,Copper,L1,Top*%
%TF.FilePolarity,Positive*%
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW 6.0.1-79c1e3a40b~116~ubuntu20.04.1) date 2022-02-10 07:45:31*
%MOMM*%
%LPD*%
G01*
G04 APERTURE LIST*
%TA.AperFunction,ComponentPad*%
%ADD10C,1.320800*%
%TD*%
%TA.AperFunction,ComponentPad*%
%ADD11C,1.752600*%
%TD*%
%TA.AperFunction,ComponentPad*%
%ADD12R,1.700000X1.700000*%
%TD*%
%TA.AperFunction,ComponentPad*%
%ADD13O,1.700000X1.700000*%
%TD*%
%TA.AperFunction,ComponentPad*%
%ADD14R,1.308000X1.308000*%
%TD*%
%TA.AperFunction,ComponentPad*%
%ADD15C,1.308000*%
%TD*%
%TA.AperFunction,Conductor*%
%ADD16C,0.250000*%
%TD*%
G04 APERTURE END LIST*
D10*
%TO.P,SW3,1,1*%
%TO.N,Net-(J1-Pad6)*%
X105400000Y-71800000D03*
%TO.P,SW3,2,2*%
%TO.N,Net-(J1-Pad7)*%
X105400000Y-73800001D03*
%TO.P,SW3,3,3*%
%TO.N,Net-(J1-Pad8)*%
X105400000Y-75800000D03*
%TO.P,SW3,4,4*%
%TO.N,Net-(J1-Pad13)*%
X105400000Y-77800001D03*
%TO.P,SW3,5,5*%
%TO.N,Net-(J1-Pad14)*%
X105400000Y-79799999D03*
%TO.P,SW3,6,6*%
%TO.N,Net-(J1-Pad15)*%
X105400000Y-81800000D03*
D11*
%TO.P,SW3,7*%
%TO.N,N/C*%
X105400000Y-69700000D03*
%TO.P,SW3,8*%
X105400000Y-83900000D03*
%TD*%
D12*
%TO.P,J2,1,Pin_1*%
%TO.N,unconnected-(J2-Pad1)*%
X131000000Y-53400000D03*
D13*
%TO.P,J2,2,Pin_2*%
%TO.N,unconnected-(J2-Pad2)*%
X131000000Y-55940000D03*
%TO.P,J2,3,Pin_3*%
%TO.N,unconnected-(J2-Pad3)*%
X131000000Y-58480000D03*
%TO.P,J2,4,Pin_4*%
%TO.N,unconnected-(J2-Pad4)*%
X131000000Y-61020000D03*
%TO.P,J2,5,Pin_5*%
%TO.N,unconnected-(J2-Pad5)*%
X131000000Y-63560000D03*
%TO.P,J2,6,Pin_6*%
%TO.N,unconnected-(J2-Pad6)*%
X131000000Y-66100000D03*
%TO.P,J2,7,Pin_7*%
%TO.N,unconnected-(J2-Pad7)*%
X131000000Y-68640000D03*
%TO.P,J2,8,Pin_8*%
%TO.N,unconnected-(J2-Pad8)*%
X131000000Y-71180000D03*
%TO.P,J2,9,Pin_9*%
%TO.N,unconnected-(J2-Pad9)*%
X131000000Y-73720000D03*
%TO.P,J2,10,Pin_10*%
%TO.N,unconnected-(J2-Pad10)*%
X131000000Y-76260000D03*
%TO.P,J2,11,Pin_11*%
%TO.N,unconnected-(J2-Pad11)*%
X131000000Y-78800000D03*
%TO.P,J2,12,Pin_12*%
%TO.N,unconnected-(J2-Pad12)*%
X131000000Y-81340000D03*
%TO.P,J2,13,Pin_13*%
%TO.N,unconnected-(J2-Pad13)*%
X131000000Y-83880000D03*
%TO.P,J2,14,Pin_14*%
%TO.N,unconnected-(J2-Pad14)*%
X131000000Y-86420000D03*
%TO.P,J2,15,Pin_15*%
%TO.N,unconnected-(J2-Pad15)*%
X131000000Y-88960000D03*
%TO.P,J2,16,Pin_16*%
%TO.N,unconnected-(J2-Pad16)*%
X131000000Y-91500000D03*
%TO.P,J2,17,Pin_17*%
%TO.N,unconnected-(J2-Pad17)*%
X131000000Y-94040000D03*
%TO.P,J2,18,Pin_18*%
%TO.N,unconnected-(J2-Pad18)*%
X131000000Y-96580000D03*
%TO.P,J2,19,Pin_19*%
%TO.N,unconnected-(J2-Pad19)*%
X131000000Y-99120000D03*
%TO.P,J2,20,Pin_20*%
%TO.N,unconnected-(J2-Pad20)*%
X131000000Y-101660000D03*
%TD*%
D14*
%TO.P,S1,1*%
%TO.N,Net-(J1-Pad18)*%
X105200000Y-98000000D03*
D15*
%TO.P,S1,2*%
%TO.N,unconnected-(S1-Pad2)*%
X105200000Y-95460000D03*
%TO.P,S1,3*%
%TO.N,Net-(J1-Pad20)*%
X105200000Y-100540000D03*
%TD*%
D12*
%TO.P,J1,1,Pin_1*%
%TO.N,Net-(J1-Pad1)*%
X112950000Y-53205000D03*
D13*
%TO.P,J1,2,Pin_2*%
%TO.N,unconnected-(J1-Pad2)*%
X112950000Y-55745000D03*
%TO.P,J1,3,Pin_3*%
%TO.N,Net-(J1-Pad3)*%
X112950000Y-58285000D03*
%TO.P,J1,4,Pin_4*%
%TO.N,unconnected-(J1-Pad4)*%
X112950000Y-60825000D03*
%TO.P,J1,5,Pin_5*%
%TO.N,unconnected-(J1-Pad5)*%
X112950000Y-63365000D03*
%TO.P,J1,6,Pin_6*%
%TO.N,Net-(J1-Pad6)*%
X112950000Y-65905000D03*
%TO.P,J1,7,Pin_7*%
%TO.N,Net-(J1-Pad7)*%
X112950000Y-68445000D03*
%TO.P,J1,8,Pin_8*%
%TO.N,Net-(J1-Pad8)*%
X112950000Y-70985000D03*
%TO.P,J1,9,Pin_9*%
%TO.N,unconnected-(J1-Pad9)*%
X112950000Y-73525000D03*
%TO.P,J1,10,Pin_10*%
%TO.N,unconnected-(J1-Pad10)*%
X112950000Y-76065000D03*
%TO.P,J1,11,Pin_11*%
%TO.N,unconnected-(J1-Pad11)*%
X112950000Y-78605000D03*
%TO.P,J1,12,Pin_12*%
%TO.N,unconnected-(J1-Pad12)*%
X112950000Y-81145000D03*
%TO.P,J1,13,Pin_13*%
%TO.N,Net-(J1-Pad13)*%
X112950000Y-83685000D03*
%TO.P,J1,14,Pin_14*%
%TO.N,Net-(J1-Pad14)*%
X112950000Y-86225000D03*
%TO.P,J1,15,Pin_15*%
%TO.N,Net-(J1-Pad15)*%
X112950000Y-88765000D03*
%TO.P,J1,16,Pin_16*%
%TO.N,unconnected-(J1-Pad16)*%
X112950000Y-91305000D03*
%TO.P,J1,17,Pin_17*%
%TO.N,unconnected-(J1-Pad17)*%
X112950000Y-93845000D03*
%TO.P,J1,18,Pin_18*%
%TO.N,Net-(J1-Pad18)*%
X112950000Y-96385000D03*
%TO.P,J1,19,Pin_19*%
%TO.N,unconnected-(J1-Pad19)*%
X112950000Y-98925000D03*
%TO.P,J1,20,Pin_20*%
%TO.N,Net-(J1-Pad20)*%
X112950000Y-101465000D03*
%TD*%
D14*
%TO.P,S2,1*%
%TO.N,Net-(J1-Pad3)*%
X105700000Y-56740000D03*
D15*
%TO.P,S2,2*%
%TO.N,Net-(J1-Pad1)*%
X105700000Y-54200000D03*
%TO.P,S2,3*%
%TO.N,unconnected-(S2-Pad3)*%
X105700000Y-59280000D03*
%TD*%
D16*
%TO.N,Net-(J1-Pad3)*%
X105700000Y-56740000D02*
X111405000Y-56740000D01*
X111405000Y-56740000D02*
X112950000Y-58285000D01*
%TO.N,Net-(J1-Pad6)*%
X111295000Y-65905000D02*
X112950000Y-65905000D01*
X105400000Y-71800000D02*
X111295000Y-65905000D01*
%TO.N,Net-(J1-Pad7)*%
X107594999Y-73800001D02*
X112950000Y-68445000D01*
X105400000Y-73800001D02*
X107594999Y-73800001D01*
%TO.N,Net-(J1-Pad14)*%
X105400000Y-79799999D02*
X106524999Y-79799999D01*
X106524999Y-79799999D02*
X112950000Y-86225000D01*
%TO.N,Net-(J1-Pad15)*%
X112365000Y-88765000D02*
X112950000Y-88765000D01*
X105400000Y-81800000D02*
X112365000Y-88765000D01*
%TO.N,Net-(J1-Pad18)*%
X111335000Y-98000000D02*
X112950000Y-96385000D01*
X105200000Y-98000000D02*
X111335000Y-98000000D01*
%TO.N,Net-(J1-Pad20)*%
X105200000Y-100540000D02*
X112025000Y-100540000D01*
X112025000Y-100540000D02*
X112950000Y-101465000D01*
%TO.N,Net-(J1-Pad8)*%
X105400000Y-75800000D02*
X108135000Y-75800000D01*
X108135000Y-75800000D02*
X112950000Y-70985000D01*
%TO.N,Net-(J1-Pad13)*%
X107065001Y-77800001D02*
X112950000Y-83685000D01*
X105400000Y-77800001D02*
X107065001Y-77800001D01*
%TO.N,Net-(J1-Pad1)*%
X106695000Y-53205000D02*
X105700000Y-54200000D01*
X112950000Y-53205000D02*
X106695000Y-53205000D01*
%TD*%
M02*

View File

@@ -1,110 +0,0 @@
%TF.GenerationSoftware,KiCad,Pcbnew,6.0.1-79c1e3a40b~116~ubuntu20.04.1*%
%TF.CreationDate,2022-02-10T07:45:33-06:00*%
%TF.ProjectId,pico-ducky,7069636f-2d64-4756-936b-792e6b696361,rev?*%
%TF.SameCoordinates,Original*%
%TF.FileFunction,Soldermask,Top*%
%TF.FilePolarity,Negative*%
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW 6.0.1-79c1e3a40b~116~ubuntu20.04.1) date 2022-02-10 07:45:33*
%MOMM*%
%LPD*%
G01*
G04 APERTURE LIST*
%ADD10C,1.320800*%
%ADD11C,1.752600*%
%ADD12R,1.700000X1.700000*%
%ADD13O,1.700000X1.700000*%
%ADD14R,1.308000X1.308000*%
%ADD15C,1.308000*%
%ADD16C,3.200000*%
G04 APERTURE END LIST*
D10*
%TO.C,SW3*%
X105400000Y-71800000D03*
X105400000Y-73800001D03*
X105400000Y-75800000D03*
X105400000Y-77800001D03*
X105400000Y-79799999D03*
X105400000Y-81800000D03*
D11*
X105400000Y-69700000D03*
X105400000Y-83900000D03*
%TD*%
D12*
%TO.C,J2*%
X131000000Y-53400000D03*
D13*
X131000000Y-55940000D03*
X131000000Y-58480000D03*
X131000000Y-61020000D03*
X131000000Y-63560000D03*
X131000000Y-66100000D03*
X131000000Y-68640000D03*
X131000000Y-71180000D03*
X131000000Y-73720000D03*
X131000000Y-76260000D03*
X131000000Y-78800000D03*
X131000000Y-81340000D03*
X131000000Y-83880000D03*
X131000000Y-86420000D03*
X131000000Y-88960000D03*
X131000000Y-91500000D03*
X131000000Y-94040000D03*
X131000000Y-96580000D03*
X131000000Y-99120000D03*
X131000000Y-101660000D03*
%TD*%
D14*
%TO.C,S1*%
X105200000Y-98000000D03*
D15*
X105200000Y-95460000D03*
X105200000Y-100540000D03*
%TD*%
D16*
%TO.C,REF\u002A\u002A*%
X105500000Y-46600000D03*
%TD*%
D12*
%TO.C,J1*%
X112950000Y-53205000D03*
D13*
X112950000Y-55745000D03*
X112950000Y-58285000D03*
X112950000Y-60825000D03*
X112950000Y-63365000D03*
X112950000Y-65905000D03*
X112950000Y-68445000D03*
X112950000Y-70985000D03*
X112950000Y-73525000D03*
X112950000Y-76065000D03*
X112950000Y-78605000D03*
X112950000Y-81145000D03*
X112950000Y-83685000D03*
X112950000Y-86225000D03*
X112950000Y-88765000D03*
X112950000Y-91305000D03*
X112950000Y-93845000D03*
X112950000Y-96385000D03*
X112950000Y-98925000D03*
X112950000Y-101465000D03*
%TD*%
D14*
%TO.C,S2*%
X105700000Y-56740000D03*
D15*
X105700000Y-54200000D03*
X105700000Y-59280000D03*
%TD*%
D16*
%TO.C,REF\u002A\u002A*%
X135400000Y-46700000D03*
%TD*%
%TO.C,REF\u002A\u002A*%
X135500000Y-107300000D03*
%TD*%
%TO.C,REF\u002A\u002A*%
X105800000Y-107400000D03*
%TD*%
M02*

View File

@@ -1,15 +0,0 @@
%TF.GenerationSoftware,KiCad,Pcbnew,6.0.1-79c1e3a40b~116~ubuntu20.04.1*%
%TF.CreationDate,2022-02-10T07:45:31-06:00*%
%TF.ProjectId,pico-ducky,7069636f-2d64-4756-936b-792e6b696361,rev?*%
%TF.SameCoordinates,Original*%
%TF.FileFunction,Paste,Top*%
%TF.FilePolarity,Positive*%
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW 6.0.1-79c1e3a40b~116~ubuntu20.04.1) date 2022-02-10 07:45:31*
%MOMM*%
%LPD*%
G01*
G04 APERTURE LIST*
G04 APERTURE END LIST*
M02*

View File

@@ -1,188 +0,0 @@
%TF.GenerationSoftware,KiCad,Pcbnew,6.0.1-79c1e3a40b~116~ubuntu20.04.1*%
%TF.CreationDate,2022-02-10T07:45:32-06:00*%
%TF.ProjectId,pico-ducky,7069636f-2d64-4756-936b-792e6b696361,rev?*%
%TF.SameCoordinates,Original*%
%TF.FileFunction,Legend,Top*%
%TF.FilePolarity,Positive*%
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW 6.0.1-79c1e3a40b~116~ubuntu20.04.1) date 2022-02-10 07:45:32*
%MOMM*%
%LPD*%
G01*
G04 APERTURE LIST*
%ADD10C,0.150000*%
%ADD11C,0.120000*%
%ADD12C,0.127000*%
%ADD13C,0.200000*%
G04 APERTURE END LIST*
D10*
%TO.C,J2*%
X130666666Y-50082380D02*
X130666666Y-50796666D01*
X130619047Y-50939523D01*
X130523809Y-51034761D01*
X130380952Y-51082380D01*
X130285714Y-51082380D01*
X131095238Y-50177619D02*
X131142857Y-50130000D01*
X131238095Y-50082380D01*
X131476190Y-50082380D01*
X131571428Y-50130000D01*
X131619047Y-50177619D01*
X131666666Y-50272857D01*
X131666666Y-50368095D01*
X131619047Y-50510952D01*
X131047619Y-51082380D01*
X131666666Y-51082380D01*
%TO.C,S1*%
X108239761Y-96936904D02*
X108287380Y-96794047D01*
X108287380Y-96555952D01*
X108239761Y-96460714D01*
X108192142Y-96413095D01*
X108096904Y-96365476D01*
X108001666Y-96365476D01*
X107906428Y-96413095D01*
X107858809Y-96460714D01*
X107811190Y-96555952D01*
X107763571Y-96746428D01*
X107715952Y-96841666D01*
X107668333Y-96889285D01*
X107573095Y-96936904D01*
X107477857Y-96936904D01*
X107382619Y-96889285D01*
X107335000Y-96841666D01*
X107287380Y-96746428D01*
X107287380Y-96508333D01*
X107335000Y-96365476D01*
X108287380Y-95413095D02*
X108287380Y-95984523D01*
X108287380Y-95698809D02*
X107287380Y-95698809D01*
X107430238Y-95794047D01*
X107525476Y-95889285D01*
X107573095Y-95984523D01*
%TO.C,J1*%
X112616666Y-49887380D02*
X112616666Y-50601666D01*
X112569047Y-50744523D01*
X112473809Y-50839761D01*
X112330952Y-50887380D01*
X112235714Y-50887380D01*
X113616666Y-50887380D02*
X113045238Y-50887380D01*
X113330952Y-50887380D02*
X113330952Y-49887380D01*
X113235714Y-50030238D01*
X113140476Y-50125476D01*
X113045238Y-50173095D01*
%TO.C,S2*%
X108739761Y-55676904D02*
X108787380Y-55534047D01*
X108787380Y-55295952D01*
X108739761Y-55200714D01*
X108692142Y-55153095D01*
X108596904Y-55105476D01*
X108501666Y-55105476D01*
X108406428Y-55153095D01*
X108358809Y-55200714D01*
X108311190Y-55295952D01*
X108263571Y-55486428D01*
X108215952Y-55581666D01*
X108168333Y-55629285D01*
X108073095Y-55676904D01*
X107977857Y-55676904D01*
X107882619Y-55629285D01*
X107835000Y-55581666D01*
X107787380Y-55486428D01*
X107787380Y-55248333D01*
X107835000Y-55105476D01*
X107882619Y-54724523D02*
X107835000Y-54676904D01*
X107787380Y-54581666D01*
X107787380Y-54343571D01*
X107835000Y-54248333D01*
X107882619Y-54200714D01*
X107977857Y-54153095D01*
X108073095Y-54153095D01*
X108215952Y-54200714D01*
X108787380Y-54772142D01*
X108787380Y-54153095D01*
D11*
%TO.C,SW3*%
X103126700Y-84229500D02*
X103126700Y-78933600D01*
X106563274Y-69370500D02*
X107673300Y-69370500D01*
X103126700Y-76673000D02*
X103126700Y-69370500D01*
X107673300Y-84229500D02*
X106563274Y-84229500D01*
X107673300Y-69370500D02*
X107673300Y-84229500D01*
X103126700Y-69370500D02*
X104236726Y-69370500D01*
X104236726Y-84229500D02*
X103126700Y-84229500D01*
%TO.C,J2*%
X132330000Y-54670000D02*
X132330000Y-102990000D01*
X129670000Y-102990000D02*
X132330000Y-102990000D01*
X129670000Y-54670000D02*
X132330000Y-54670000D01*
X132330000Y-52070000D02*
X132330000Y-53400000D01*
X129670000Y-54670000D02*
X129670000Y-102990000D01*
X131000000Y-52070000D02*
X132330000Y-52070000D01*
D12*
%TO.C,S1*%
X106450000Y-103000000D02*
X106450000Y-93000000D01*
X103950000Y-93000000D02*
X103950000Y-103000000D01*
X103950000Y-103000000D02*
X106450000Y-103000000D01*
X106450000Y-93000000D02*
X103950000Y-93000000D01*
D13*
X103450000Y-98000000D02*
G75*
G03*
X103450000Y-98000000I-100000J0D01*
G01*
D11*
%TO.C,J1*%
X111620000Y-102795000D02*
X114280000Y-102795000D01*
X111620000Y-54475000D02*
X114280000Y-54475000D01*
X114280000Y-51875000D02*
X114280000Y-53205000D01*
X112950000Y-51875000D02*
X114280000Y-51875000D01*
X111620000Y-54475000D02*
X111620000Y-102795000D01*
X114280000Y-54475000D02*
X114280000Y-102795000D01*
D12*
%TO.C,S2*%
X104450000Y-61740000D02*
X106950000Y-61740000D01*
X104450000Y-51740000D02*
X104450000Y-61740000D01*
X106950000Y-61740000D02*
X106950000Y-51740000D01*
X106950000Y-51740000D02*
X104450000Y-51740000D01*
D13*
X103950000Y-56740000D02*
G75*
G03*
X103950000Y-56740000I-100000J0D01*
G01*
%TD*%
M02*

View File

@@ -1,20 +0,0 @@
M48
; DRILL file {KiCad 6.0.1-79c1e3a40b~116~ubuntu20.04.1} date Thu 10 Feb 2022 07:45:38 AM CST
; FORMAT={-:-/ absolute / inch / decimal}
; #@! TF.CreationDate,2022-02-10T07:45:38-06:00
; #@! TF.GenerationSoftware,Kicad,Pcbnew,6.0.1-79c1e3a40b~116~ubuntu20.04.1
; #@! TF.FileFunction,NonPlated,1,2,NPTH
FMAT,2
INCH
; #@! TA.AperFunction,NonPlated,NPTH,ComponentDrill
T1C0.1260
%
G90
G05
T1
X4.1535Y-1.8346
X4.1654Y-4.2283
X5.3307Y-1.8386
X5.3346Y-4.2244
T0
M30

View File

@@ -1,79 +0,0 @@
M48
; DRILL file {KiCad 6.0.1-79c1e3a40b~116~ubuntu20.04.1} date Thu 10 Feb 2022 07:45:38 AM CST
; FORMAT={-:-/ absolute / inch / decimal}
; #@! TF.CreationDate,2022-02-10T07:45:38-06:00
; #@! TF.GenerationSoftware,Kicad,Pcbnew,6.0.1-79c1e3a40b~116~ubuntu20.04.1
; #@! TF.FileFunction,Plated,1,2,PTH
FMAT,2
INCH
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
T1C0.0315
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
T2C0.0320
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
T3C0.0394
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
T4C0.0490
%
G90
G05
T1
X4.1417Y-3.7583
X4.1417Y-3.8583
X4.1417Y-3.9583
X4.1614Y-2.1339
X4.1614Y-2.2339
X4.1614Y-2.3339
T2
X4.1496Y-2.8268
X4.1496Y-2.9055
X4.1496Y-2.9843
X4.1496Y-3.063
X4.1496Y-3.1417
X4.1496Y-3.2205
T3
X4.4469Y-2.0947
X4.4469Y-2.1947
X4.4469Y-2.2947
X4.4469Y-2.3947
X4.4469Y-2.4947
X4.4469Y-2.5947
X4.4469Y-2.6947
X4.4469Y-2.7947
X4.4469Y-2.8947
X4.4469Y-2.9947
X4.4469Y-3.0947
X4.4469Y-3.1947
X4.4469Y-3.2947
X4.4469Y-3.3947
X4.4469Y-3.4947
X4.4469Y-3.5947
X4.4469Y-3.6947
X4.4469Y-3.7947
X4.4469Y-3.8947
X4.4469Y-3.9947
X5.1575Y-2.1024
X5.1575Y-2.2024
X5.1575Y-2.3024
X5.1575Y-2.4024
X5.1575Y-2.5024
X5.1575Y-2.6024
X5.1575Y-2.7024
X5.1575Y-2.8024
X5.1575Y-2.9024
X5.1575Y-3.0024
X5.1575Y-3.1024
X5.1575Y-3.2024
X5.1575Y-3.3024
X5.1575Y-3.4024
X5.1575Y-3.5024
X5.1575Y-3.6024
X5.1575Y-3.7024
X5.1575Y-3.8024
X5.1575Y-3.9024
X5.1575Y-4.0024
T4
X4.1496Y-2.7441
X4.1496Y-3.3031
T0
M30

View File

@@ -1,125 +0,0 @@
{
"Header": {
"GenerationSoftware": {
"Vendor": "KiCad",
"Application": "Pcbnew",
"Version": "6.0.1-79c1e3a40b~116~ubuntu20.04.1"
},
"CreationDate": "2022-02-10T07:45:34-06:00"
},
"GeneralSpecs": {
"ProjectId": {
"Name": "pico-ducky",
"GUID": "7069636f-2d64-4756-936b-792e6b696361",
"Revision": "rev?"
},
"Size": {
"X": 37.01,
"Y": 68.12
},
"LayerNumber": 2,
"BoardThickness": 1.6,
"Finish": "None"
},
"DesignRules": [
{
"Layers": "Outer",
"PadToPad": 0.0,
"PadToTrack": 0.0,
"TrackToTrack": 0.2,
"MinLineWidth": 0.25
}
],
"FilesAttributes": [
{
"Path": "pico-ducky-F_Cu.gbr",
"FileFunction": "Copper,L1,Top",
"FilePolarity": "Positive"
},
{
"Path": "pico-ducky-B_Cu.gbr",
"FileFunction": "Copper,L2,Bot",
"FilePolarity": "Positive"
},
{
"Path": "pico-ducky-F_Paste.gbr",
"FileFunction": "SolderPaste,Top",
"FilePolarity": "Positive"
},
{
"Path": "pico-ducky-B_Paste.gbr",
"FileFunction": "SolderPaste,Bot",
"FilePolarity": "Positive"
},
{
"Path": "pico-ducky-F_Silkscreen.gbr",
"FileFunction": "Legend,Top",
"FilePolarity": "Positive"
},
{
"Path": "pico-ducky-B_Silkscreen.gbr",
"FileFunction": "Legend,Bot",
"FilePolarity": "Positive"
},
{
"Path": "pico-ducky-F_Mask.gbr",
"FileFunction": "SolderMask,Top",
"FilePolarity": "Negative"
},
{
"Path": "pico-ducky-B_Mask.gbr",
"FileFunction": "SolderMask,Bot",
"FilePolarity": "Negative"
},
{
"Path": "pico-ducky-Edge_Cuts.gbr",
"FileFunction": "Profile",
"FilePolarity": "Positive"
}
],
"MaterialStackup": [
{
"Type": "Legend",
"Name": "Top Silk Screen"
},
{
"Type": "SolderPaste",
"Name": "Top Solder Paste"
},
{
"Type": "SolderMask",
"Thickness": 0.01,
"Name": "Top Solder Mask"
},
{
"Type": "Copper",
"Thickness": 0.035,
"Name": "F.Cu"
},
{
"Type": "Dielectric",
"Thickness": 1.51,
"Material": "FR4",
"Name": "F.Cu/B.Cu",
"Notes": "Type: dielectric layer 1 (from F.Cu to B.Cu)"
},
{
"Type": "Copper",
"Thickness": 0.035,
"Name": "B.Cu"
},
{
"Type": "SolderMask",
"Thickness": 0.01,
"Name": "Bottom Solder Mask"
},
{
"Type": "SolderPaste",
"Name": "Bottom Solder Paste"
},
{
"Type": "Legend",
"Name": "Bottom Silk Screen"
}
]
}

View File

@@ -1,578 +0,0 @@
(kicad_pcb (version 20211014) (generator pcbnew)
(general
(thickness 1.6)
)
(paper "A4")
(layers
(0 "F.Cu" signal)
(31 "B.Cu" signal)
(32 "B.Adhes" user "B.Adhesive")
(33 "F.Adhes" user "F.Adhesive")
(34 "B.Paste" user)
(35 "F.Paste" user)
(36 "B.SilkS" user "B.Silkscreen")
(37 "F.SilkS" user "F.Silkscreen")
(38 "B.Mask" user)
(39 "F.Mask" user)
(40 "Dwgs.User" user "User.Drawings")
(41 "Cmts.User" user "User.Comments")
(42 "Eco1.User" user "User.Eco1")
(43 "Eco2.User" user "User.Eco2")
(44 "Edge.Cuts" user)
(45 "Margin" user)
(46 "B.CrtYd" user "B.Courtyard")
(47 "F.CrtYd" user "F.Courtyard")
(48 "B.Fab" user)
(49 "F.Fab" user)
(50 "User.1" user)
(51 "User.2" user)
(52 "User.3" user)
(53 "User.4" user)
(54 "User.5" user)
(55 "User.6" user)
(56 "User.7" user)
(57 "User.8" user)
(58 "User.9" user)
)
(setup
(stackup
(layer "F.SilkS" (type "Top Silk Screen"))
(layer "F.Paste" (type "Top Solder Paste"))
(layer "F.Mask" (type "Top Solder Mask") (thickness 0.01))
(layer "F.Cu" (type "copper") (thickness 0.035))
(layer "dielectric 1" (type "core") (thickness 1.51) (material "FR4") (epsilon_r 4.5) (loss_tangent 0.02))
(layer "B.Cu" (type "copper") (thickness 0.035))
(layer "B.Mask" (type "Bottom Solder Mask") (thickness 0.01))
(layer "B.Paste" (type "Bottom Solder Paste"))
(layer "B.SilkS" (type "Bottom Silk Screen"))
(copper_finish "None")
(dielectric_constraints no)
)
(pad_to_mask_clearance 0)
(pcbplotparams
(layerselection 0x00010fc_ffffffff)
(disableapertmacros false)
(usegerberextensions false)
(usegerberattributes true)
(usegerberadvancedattributes true)
(creategerberjobfile true)
(svguseinch false)
(svgprecision 6)
(excludeedgelayer true)
(plotframeref false)
(viasonmask false)
(mode 1)
(useauxorigin false)
(hpglpennumber 1)
(hpglpenspeed 20)
(hpglpendiameter 15.000000)
(dxfpolygonmode true)
(dxfimperialunits true)
(dxfusepcbnewfont true)
(psnegative false)
(psa4output false)
(plotreference true)
(plotvalue true)
(plotinvisibletext false)
(sketchpadsonfab false)
(subtractmaskfromsilk false)
(outputformat 1)
(mirror false)
(drillshape 0)
(scaleselection 1)
(outputdirectory "cad/")
)
)
(net 0 "")
(net 1 "unconnected-(J1-Pad2)")
(net 2 "unconnected-(J1-Pad4)")
(net 3 "unconnected-(J1-Pad5)")
(net 4 "unconnected-(J1-Pad9)")
(net 5 "unconnected-(J1-Pad10)")
(net 6 "unconnected-(J1-Pad11)")
(net 7 "unconnected-(J1-Pad12)")
(net 8 "unconnected-(J1-Pad16)")
(net 9 "unconnected-(J1-Pad17)")
(net 10 "unconnected-(J1-Pad19)")
(net 11 "unconnected-(J2-Pad1)")
(net 12 "unconnected-(J2-Pad2)")
(net 13 "unconnected-(J2-Pad3)")
(net 14 "unconnected-(J2-Pad4)")
(net 15 "unconnected-(J2-Pad5)")
(net 16 "unconnected-(J2-Pad6)")
(net 17 "unconnected-(J2-Pad7)")
(net 18 "unconnected-(J2-Pad8)")
(net 19 "unconnected-(J2-Pad9)")
(net 20 "unconnected-(J2-Pad10)")
(net 21 "unconnected-(J2-Pad11)")
(net 22 "unconnected-(J2-Pad12)")
(net 23 "unconnected-(J2-Pad13)")
(net 24 "unconnected-(J2-Pad14)")
(net 25 "unconnected-(J2-Pad15)")
(net 26 "unconnected-(J2-Pad16)")
(net 27 "unconnected-(J2-Pad17)")
(net 28 "unconnected-(J2-Pad18)")
(net 29 "unconnected-(J2-Pad19)")
(net 30 "unconnected-(J2-Pad20)")
(net 31 "Net-(J1-Pad3)")
(net 32 "Net-(J1-Pad6)")
(net 33 "Net-(J1-Pad7)")
(net 34 "Net-(J1-Pad14)")
(net 35 "Net-(J1-Pad15)")
(net 36 "Net-(J1-Pad18)")
(net 37 "Net-(J1-Pad20)")
(net 38 "Net-(J1-Pad8)")
(net 39 "Net-(J1-Pad13)")
(net 40 "Net-(J1-Pad1)")
(net 41 "unconnected-(S1-Pad2)")
(net 42 "unconnected-(S2-Pad3)")
(footprint "Connector_PinSocket_2.54mm:PinSocket_1x20_P2.54mm_Vertical" (layer "F.Cu")
(tedit 5A19A41E) (tstamp 31e895e5-7b36-4827-b794-b5b947f2801b)
(at 131 53.4)
(descr "Through hole straight socket strip, 1x20, 2.54mm pitch, single row (from Kicad 4.0.7), script generated")
(tags "Through hole socket strip THT 1x20 2.54mm single row")
(property "Sheetfile" "pico-ducky.kicad_sch")
(property "Sheetname" "")
(path "/60ef5d45-ab54-4614-8417-f29731f193e9")
(attr through_hole)
(fp_text reference "J2" (at 0 -2.77) (layer "F.SilkS")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 13666891-0874-46d5-8b1f-5f8a3d2e3667)
)
(fp_text value "Conn_01x20_Female" (at 0 51.03) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 826e5a92-f4a7-481c-a810-e691fb4242fa)
)
(fp_text user "${REFERENCE}" (at 0 24.13 90) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp faaede8c-2aeb-4f9f-951c-9e98aefd8353)
)
(fp_line (start 1.33 1.27) (end 1.33 49.59) (layer "F.SilkS") (width 0.12) (tstamp 73d985f0-c578-40ca-ab9b-537d56fc30c2))
(fp_line (start -1.33 49.59) (end 1.33 49.59) (layer "F.SilkS") (width 0.12) (tstamp 8edc9dab-270b-46ce-86c7-43d2ea9d2561))
(fp_line (start -1.33 1.27) (end 1.33 1.27) (layer "F.SilkS") (width 0.12) (tstamp 906e14b4-a894-4fb8-92ce-dc27c4d28378))
(fp_line (start 1.33 -1.33) (end 1.33 0) (layer "F.SilkS") (width 0.12) (tstamp a9c07e71-f8a5-403b-8e00-562e3cd133e0))
(fp_line (start -1.33 1.27) (end -1.33 49.59) (layer "F.SilkS") (width 0.12) (tstamp ac998646-16d3-4146-971c-4cb50e1f3fdb))
(fp_line (start 0 -1.33) (end 1.33 -1.33) (layer "F.SilkS") (width 0.12) (tstamp b55ffde1-3db6-44e1-8a25-d5de2cc37fea))
(fp_line (start 1.75 50) (end -1.8 50) (layer "F.CrtYd") (width 0.05) (tstamp 2622f595-7ff0-453e-9b78-19125b1110e8))
(fp_line (start -1.8 -1.8) (end 1.75 -1.8) (layer "F.CrtYd") (width 0.05) (tstamp 7bb67499-9a91-41e1-afe8-7eef34869d71))
(fp_line (start -1.8 50) (end -1.8 -1.8) (layer "F.CrtYd") (width 0.05) (tstamp 7bfd21eb-4ee9-42ce-8900-a93d825953d0))
(fp_line (start 1.75 -1.8) (end 1.75 50) (layer "F.CrtYd") (width 0.05) (tstamp 900716a9-2103-4663-a7b4-094a39ecb871))
(fp_line (start 1.27 49.53) (end -1.27 49.53) (layer "F.Fab") (width 0.1) (tstamp 071715f0-4a79-4e1a-8718-9cffdd92cf95))
(fp_line (start 1.27 -0.635) (end 1.27 49.53) (layer "F.Fab") (width 0.1) (tstamp 18f447e2-259c-4c3c-b887-9d9c6df88167))
(fp_line (start -1.27 49.53) (end -1.27 -1.27) (layer "F.Fab") (width 0.1) (tstamp 2e306457-a203-45bd-8828-39a6fc7884b5))
(fp_line (start -1.27 -1.27) (end 0.635 -1.27) (layer "F.Fab") (width 0.1) (tstamp 46aecb8d-9ecb-45b1-85b3-c48114c449a4))
(fp_line (start 0.635 -1.27) (end 1.27 -0.635) (layer "F.Fab") (width 0.1) (tstamp c587cddf-70f7-45f9-a743-257eda0ecb2b))
(pad "1" thru_hole rect locked (at 0 0) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 11 "unconnected-(J2-Pad1)") (pinfunction "Pin_1") (pintype "passive") (tstamp 133696af-8bcb-4f2a-918a-966f6f31bafd))
(pad "2" thru_hole oval locked (at 0 2.54) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 12 "unconnected-(J2-Pad2)") (pinfunction "Pin_2") (pintype "passive") (tstamp 9b86eb10-9f20-4c99-95e9-2380fe3f9b14))
(pad "3" thru_hole oval locked (at 0 5.08) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 13 "unconnected-(J2-Pad3)") (pinfunction "Pin_3") (pintype "passive") (tstamp 1dd65e06-1b19-42b2-9e48-aa593ac50db3))
(pad "4" thru_hole oval locked (at 0 7.62) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 14 "unconnected-(J2-Pad4)") (pinfunction "Pin_4") (pintype "passive") (tstamp 9a2a4879-e6b7-4350-b86b-5104d34e2a80))
(pad "5" thru_hole oval locked (at 0 10.16) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 15 "unconnected-(J2-Pad5)") (pinfunction "Pin_5") (pintype "passive") (tstamp a49a4d82-48bd-42b8-95c9-1c983664fc79))
(pad "6" thru_hole oval locked (at 0 12.7) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 16 "unconnected-(J2-Pad6)") (pinfunction "Pin_6") (pintype "passive") (tstamp 1d44b2aa-9869-4de8-b803-3ac1829b85dc))
(pad "7" thru_hole oval locked (at 0 15.24) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 17 "unconnected-(J2-Pad7)") (pinfunction "Pin_7") (pintype "passive") (tstamp fd35caac-7fa3-4ae4-adc7-7771f7f34b82))
(pad "8" thru_hole oval locked (at 0 17.78) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 18 "unconnected-(J2-Pad8)") (pinfunction "Pin_8") (pintype "passive") (tstamp a23fda0c-76b9-4947-9d26-721683d9824c))
(pad "9" thru_hole oval locked (at 0 20.32) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 19 "unconnected-(J2-Pad9)") (pinfunction "Pin_9") (pintype "passive") (tstamp 3634acc5-1d40-409a-b593-f224d9318583))
(pad "10" thru_hole oval locked (at 0 22.86) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 20 "unconnected-(J2-Pad10)") (pinfunction "Pin_10") (pintype "passive") (tstamp f5b3ac78-e150-4b32-bc84-9d75c87fb341))
(pad "11" thru_hole oval locked (at 0 25.4) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 21 "unconnected-(J2-Pad11)") (pinfunction "Pin_11") (pintype "passive") (tstamp 2f21e29d-624e-4cb4-9a3c-1a75369755aa))
(pad "12" thru_hole oval locked (at 0 27.94) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 22 "unconnected-(J2-Pad12)") (pinfunction "Pin_12") (pintype "passive") (tstamp 95ec8c15-617f-40e1-a3f7-7e9eb27d7908))
(pad "13" thru_hole oval locked (at 0 30.48) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 23 "unconnected-(J2-Pad13)") (pinfunction "Pin_13") (pintype "passive") (tstamp 325a060a-bb55-4a28-b469-3ff109457870))
(pad "14" thru_hole oval locked (at 0 33.02) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 24 "unconnected-(J2-Pad14)") (pinfunction "Pin_14") (pintype "passive") (tstamp d0064f4c-eaa8-4fc1-8c95-5edfe18ce9e5))
(pad "15" thru_hole oval locked (at 0 35.56) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 25 "unconnected-(J2-Pad15)") (pinfunction "Pin_15") (pintype "passive") (tstamp 4a7017bb-a698-433b-a0be-587786fcc0bb))
(pad "16" thru_hole oval locked (at 0 38.1) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 26 "unconnected-(J2-Pad16)") (pinfunction "Pin_16") (pintype "passive") (tstamp 6d65a827-125f-4e46-bf64-3cc60fd414e5))
(pad "17" thru_hole oval locked (at 0 40.64) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 27 "unconnected-(J2-Pad17)") (pinfunction "Pin_17") (pintype "passive") (tstamp 08522cb4-e044-4d86-a062-8eb79a22f851))
(pad "18" thru_hole oval locked (at 0 43.18) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 28 "unconnected-(J2-Pad18)") (pinfunction "Pin_18") (pintype "passive") (tstamp 66fc6b30-d33c-405d-9170-5e4e3b401c64))
(pad "19" thru_hole oval locked (at 0 45.72) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 29 "unconnected-(J2-Pad19)") (pinfunction "Pin_19") (pintype "passive") (tstamp 8f9a72c7-905a-4381-80e3-5385498e2e49))
(pad "20" thru_hole oval locked (at 0 48.26) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 30 "unconnected-(J2-Pad20)") (pinfunction "Pin_20") (pintype "passive") (tstamp 1b2eb90f-4916-4496-934c-ebfaf59fd7d2))
(model "${KICAD6_3DMODEL_DIR}/Connector_PinSocket_2.54mm.3dshapes/PinSocket_1x20_P2.54mm_Vertical.wrl"
(offset (xyz 0 0 0))
(scale (xyz 1 1 1))
(rotate (xyz 0 0 0))
)
)
(footprint "MSS-102545-14A-D:SW_MSS-102545-14A-D" (layer "F.Cu")
(tedit 61F6FABF) (tstamp 477892a1-722e-4cda-bb6c-fcdb8ba5f93e)
(at 105.2 98 -90)
(property "MANUFACTURER" "CUI Devices")
(property "MAXIMUM_PACKAGE_HEIGHT" "6.5 mm")
(property "PARTREV" "1.0")
(property "STANDARD" "Manufacturer Recommendations")
(property "Sheetfile" "pico-ducky.kicad_sch")
(property "Sheetname" "")
(path "/6d421685-6187-4a3c-8570-78b8305b32fe")
(attr through_hole)
(fp_text reference "S1" (at -1.825 -2.635 90) (layer "F.SilkS")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 560d05a7-84e4-403a-80d1-f287a4032b8a)
)
(fp_text value "MSS-102545-14A-D" (at 7.065 2.635 90) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 2a4111b7-8149-4814-9344-3b8119cd75e4)
)
(fp_line (start 5 -1.25) (end -5 -1.25) (layer "F.SilkS") (width 0.127) (tstamp 66ca01b3-51ff-4294-9b77-4492e98f6aec))
(fp_line (start -5 1.25) (end 5 1.25) (layer "F.SilkS") (width 0.127) (tstamp 9f969b13-1795-4747-8326-93bdc304ed56))
(fp_line (start 5 1.25) (end 5 -1.25) (layer "F.SilkS") (width 0.127) (tstamp b9d4de74-d246-495d-8b63-12ab2133d6d6))
(fp_line (start -5 -1.25) (end -5 1.25) (layer "F.SilkS") (width 0.127) (tstamp fb0bf2a0-d317-42f7-b022-b5e05481f6be))
(fp_circle (center 0 1.85) (end 0.1 1.85) (layer "F.SilkS") (width 0.2) (fill none) (tstamp 0fb27e11-fde6-4a25-adbb-e9684771b369))
(fp_line (start 5.25 -1.5) (end -5.25 -1.5) (layer "F.CrtYd") (width 0.05) (tstamp 0e32af77-726b-4e11-9f99-2e2484ba9e9b))
(fp_line (start -5.25 1.5) (end 5.25 1.5) (layer "F.CrtYd") (width 0.05) (tstamp 152cd84e-bbed-4df5-a866-d1ab977b0966))
(fp_line (start 5.25 1.5) (end 5.25 -1.5) (layer "F.CrtYd") (width 0.05) (tstamp 2ee28fa9-d785-45a1-9a1b-1be02ad8cd0b))
(fp_line (start -5.25 -1.5) (end -5.25 1.5) (layer "F.CrtYd") (width 0.05) (tstamp 8a427111-6480-4b0c-b097-d8b6a0ee1819))
(fp_line (start -5 -1.25) (end -5 1.25) (layer "F.Fab") (width 0.127) (tstamp 022502e0-e724-4b75-bc35-3c5984dbeb76))
(fp_line (start 5 1.25) (end 5 -1.25) (layer "F.Fab") (width 0.127) (tstamp 2eea20e6-112c-411a-b615-885ae773135a))
(fp_line (start 5 -1.25) (end -5 -1.25) (layer "F.Fab") (width 0.127) (tstamp 49fec31e-3712-4229-8142-b191d90a97d0))
(fp_line (start -5 1.25) (end 5 1.25) (layer "F.Fab") (width 0.127) (tstamp d655bb0a-cbf9-4908-ad60-7024ff468fbd))
(fp_circle (center 0 1.85) (end 0.1 1.85) (layer "F.Fab") (width 0.2) (fill none) (tstamp 08ec951f-e7eb-41cf-9589-697107a98e88))
(pad "1" thru_hole rect locked (at 0 0 270) (size 1.308 1.308) (drill 0.8) (layers *.Cu *.Mask)
(net 36 "Net-(J1-Pad18)") (pintype "passive") (tstamp 56d2bc5d-fd72-4542-ab0f-053a5fd60efa))
(pad "2" thru_hole circle locked (at -2.54 0 270) (size 1.308 1.308) (drill 0.8) (layers *.Cu *.Mask)
(net 41 "unconnected-(S1-Pad2)") (pintype "passive") (tstamp 09bbea88-8bd7-48ec-baae-1b4a9a11a40e))
(pad "3" thru_hole circle locked (at 2.54 0 270) (size 1.308 1.308) (drill 0.8) (layers *.Cu *.Mask)
(net 37 "Net-(J1-Pad20)") (pintype "passive") (tstamp 41c18011-40db-4384-9ba4-c0158d0d9d6a))
)
(footprint "SK-14D01-G6:SK-14D01-G 6" (layer "F.Cu")
(tedit 620516C0) (tstamp 8174b4de-74b1-48db-ab8e-c8432251095b)
(at 105.4 71.8 -90)
(property "Sheetfile" "pico-ducky.kicad_sch")
(property "Sheetname" "")
(path "/7c48a97b-1931-421f-af9d-e88a00997ace")
(attr through_hole)
(fp_text reference "SW3" (at 5 -2.1463 90) (layer "F.SilkS") hide
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 7edc9030-db7b-43ac-a1b3-b87eeacb4c2d)
)
(fp_text value "SK-14D01-G_6" (at 5 -2.1463 90) (layer "F.SilkS") hide
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 08a7c925-7fae-4530-b0c9-120e185cb318)
)
(fp_text user "*" (at -1 -0.635 90) (layer "F.SilkS") hide
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 03c52831-5dc5-43c5-a442-8d23643b46fb)
)
(fp_text user "*" (at -1 -0.635 90) (layer "F.SilkS") hide
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 0b21a65d-d20b-411e-920a-75c343ac5136)
)
(fp_text user "Copyright 2021 Accelerated Designs. All rights reserved." (at 0 0 90) (layer "Cmts.User") hide
(effects (font (size 0.127 0.127) (thickness 0.002)))
(tstamp fe8d9267-7834-48d6-a191-c8724b2ee78d)
)
(fp_text user "*" (at -1 0.635 90) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 3cd1bda0-18db-417d-b581-a0c50623df68)
)
(fp_text user "*" (at -1 0.635 90) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp d57dcfee-5058-4fc2-a68b-05f9a48f685b)
)
(fp_line (start 12.4295 2.2733) (end 7.1336 2.2733) (layer "F.SilkS") (width 0.12) (tstamp 1a1ab354-5f85-45f9-938c-9f6c4c8c3ea2))
(fp_line (start -2.4295 -1.163274) (end -2.4295 -2.2733) (layer "F.SilkS") (width 0.12) (tstamp 2d210a96-f81f-42a9-8bf4-1b43c11086f3))
(fp_line (start 4.873 2.2733) (end -2.4295 2.2733) (layer "F.SilkS") (width 0.12) (tstamp 4c8eb964-bdf4-44de-90e9-e2ab82dd5313))
(fp_line (start 12.4295 -2.2733) (end 12.4295 -1.163274) (layer "F.SilkS") (width 0.12) (tstamp 7aed3a71-054b-4aaa-9c0a-030523c32827))
(fp_line (start -2.4295 -2.2733) (end 12.4295 -2.2733) (layer "F.SilkS") (width 0.12) (tstamp 9bb20359-0f8b-45bc-9d38-6626ed3a939d))
(fp_line (start -2.4295 2.2733) (end -2.4295 1.163274) (layer "F.SilkS") (width 0.12) (tstamp aa14c3bd-4acc-4908-9d28-228585a22a9d))
(fp_line (start 12.4295 1.163274) (end 12.4295 2.2733) (layer "F.SilkS") (width 0.12) (tstamp e857610b-4434-4144-b04e-43c1ebdc5ceb))
(fp_line (start 7.2606 8.3947) (end 7.2606 2.4003) (layer "F.CrtYd") (width 0.05) (tstamp 0f54db53-a272-4955-88fb-d7ab00657bb0))
(fp_line (start -2.5565 -1.1303) (end -3.2303 -1.1303) (layer "F.CrtYd") (width 0.05) (tstamp 2d6db888-4e40-41c8-b701-07170fc894bc))
(fp_line (start 13.2303 -1.1303) (end 12.5565 -1.1303) (layer "F.CrtYd") (width 0.05) (tstamp 31e08896-1992-4725-96d9-9d2728bca7a3))
(fp_line (start -2.5565 1.1303) (end -2.5565 2.4003) (layer "F.CrtYd") (width 0.05) (tstamp 3aaee4c4-dbf7-49a5-a620-9465d8cc3ae7))
(fp_line (start -3.2303 1.1303) (end -2.5565 1.1303) (layer "F.CrtYd") (width 0.05) (tstamp 5528bcad-2950-4673-90eb-c37e6952c475))
(fp_line (start 13.2303 1.1303) (end 13.2303 -1.1303) (layer "F.CrtYd") (width 0.05) (tstamp 6441b183-b8f2-458f-a23d-60e2b1f66dd6))
(fp_line (start -2.5565 -2.4003) (end -2.5565 -1.1303) (layer "F.CrtYd") (width 0.05) (tstamp 66043bca-a260-4915-9fce-8a51d324c687))
(fp_line (start -3.2303 -1.1303) (end -3.2303 1.1303) (layer "F.CrtYd") (width 0.05) (tstamp 7bbf981c-a063-4e30-8911-e4228e1c0743))
(fp_line (start 7.2606 2.4003) (end 12.5565 2.4003) (layer "F.CrtYd") (width 0.05) (tstamp 80094b70-85ab-4ff6-934b-60d5ee65023a))
(fp_line (start 12.5565 -2.4003) (end -2.5565 -2.4003) (layer "F.CrtYd") (width 0.05) (tstamp 852dabbf-de45-4470-8176-59d37a754407))
(fp_line (start 4.746 8.3947) (end 7.2606 8.3947) (layer "F.CrtYd") (width 0.05) (tstamp 922058ca-d09a-45fd-8394-05f3e2c1e03a))
(fp_line (start 4.746 2.4003) (end 4.746 8.3947) (layer "F.CrtYd") (width 0.05) (tstamp 97fe9c60-586f-4895-8504-4d3729f5f81a))
(fp_line (start 12.5565 -1.1303) (end 12.5565 -2.4003) (layer "F.CrtYd") (width 0.05) (tstamp b5352a33-563a-4ffe-a231-2e68fb54afa3))
(fp_line (start -2.5565 2.4003) (end 4.746 2.4003) (layer "F.CrtYd") (width 0.05) (tstamp bdc7face-9f7c-4701-80bb-4cc144448db1))
(fp_line (start 12.5565 1.1303) (end 13.2303 1.1303) (layer "F.CrtYd") (width 0.05) (tstamp bfc0aadc-38cf-466e-a642-68fdc3138c78))
(fp_line (start 12.5565 2.4003) (end 12.5565 1.1303) (layer "F.CrtYd") (width 0.05) (tstamp d4a1d3c4-b315-4bec-9220-d12a9eab51e0))
(fp_line (start 5 2.1463) (end 5 8.1407) (layer "F.Fab") (width 0.1) (tstamp 29e78086-2175-405e-9ba3-c48766d2f50c))
(fp_line (start 12.3025 -2.1463) (end 12.3025 2.1463) (layer "F.Fab") (width 0.1) (tstamp 666713b0-70f4-42df-8761-f65bc212d03b))
(fp_line (start -2.3025 -2.1463) (end 12.3025 -2.1463) (layer "F.Fab") (width 0.1) (tstamp 6c2e273e-743c-4f1e-a647-4171f8122550))
(fp_line (start 12.3025 2.1463) (end -2.3025 2.1463) (layer "F.Fab") (width 0.1) (tstamp 7dc880bc-e7eb-4cce-8d8c-0b65a9dd788e))
(fp_line (start -2.3025 2.1463) (end -2.3025 -2.1463) (layer "F.Fab") (width 0.1) (tstamp 9157f4ae-0244-4ff1-9f73-3cb4cbb5f280))
(fp_line (start 5 8.1407) (end 7.0066 8.1407) (layer "F.Fab") (width 0.1) (tstamp 94a873dc-af67-4ef9-8159-1f7c93eeb3d7))
(fp_line (start 7.0066 2.1463) (end 7.0066 8.1407) (layer "F.Fab") (width 0.1) (tstamp a1823eb2-fb0d-4ed8-8b96-04184ac3a9d5))
(pad "1" thru_hole circle (at 0 0 270) (size 1.3208 1.3208) (drill 0.8128) (layers *.Cu *.Mask)
(net 32 "Net-(J1-Pad6)") (pinfunction "1") (pintype "unspecified") (tstamp 704d6d51-bb34-4cbf-83d8-841e208048d8))
(pad "2" thru_hole circle (at 2.000001 0 270) (size 1.3208 1.3208) (drill 0.8128) (layers *.Cu *.Mask)
(net 33 "Net-(J1-Pad7)") (pinfunction "2") (pintype "unspecified") (tstamp 0eaa98f0-9565-4637-ace3-42a5231b07f7))
(pad "3" thru_hole circle (at 4 0 270) (size 1.3208 1.3208) (drill 0.8128) (layers *.Cu *.Mask)
(net 38 "Net-(J1-Pad8)") (pinfunction "3") (pintype "unspecified") (tstamp 181abe7a-f941-42b6-bd46-aaa3131f90fb))
(pad "4" thru_hole circle (at 6.000001 0 270) (size 1.3208 1.3208) (drill 0.8128) (layers *.Cu *.Mask)
(net 39 "Net-(J1-Pad13)") (pinfunction "4") (pintype "unspecified") (tstamp ce83728b-bebd-48c2-8734-b6a50d837931))
(pad "5" thru_hole circle (at 7.999999 0 270) (size 1.3208 1.3208) (drill 0.8128) (layers *.Cu *.Mask)
(net 34 "Net-(J1-Pad14)") (pinfunction "5") (pintype "unspecified") (tstamp c41b3c8b-634e-435a-b582-96b83bbd4032))
(pad "6" thru_hole circle (at 10 0 270) (size 1.3208 1.3208) (drill 0.8128) (layers *.Cu *.Mask)
(net 35 "Net-(J1-Pad15)") (pinfunction "6") (pintype "unspecified") (tstamp 9340c285-5767-42d5-8b6d-63fe2a40ddf3))
(pad "7" thru_hole circle (at -2.1 0 270) (size 1.7526 1.7526) (drill 1.2446) (layers *.Cu *.Mask) (tstamp 1831fb37-1c5d-42c4-b898-151be6fca9dc))
(pad "8" thru_hole circle (at 12.1 0 270) (size 1.7526 1.7526) (drill 1.2446) (layers *.Cu *.Mask) (tstamp 0f22151c-f260-4674-b486-4710a2c42a55))
)
(footprint "MountingHole:MountingHole_3.2mm_M3" (layer "F.Cu")
(tedit 56D1B4CB) (tstamp 981ff4de-0330-4757-b746-0cb983df5e7c)
(at 105.5 46.6)
(descr "Mounting Hole 3.2mm, no annular, M3")
(tags "mounting hole 3.2mm no annular m3")
(attr exclude_from_pos_files exclude_from_bom)
(fp_text reference "REF**" (at 0 -4.2) (layer "F.SilkS") hide
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 9505be36-b21c-4db8-9484-dd0861395d26)
)
(fp_text value "MountingHole_3.2mm_M3" (at 0 4.2) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 49d97c73-e37a-4154-9d0a-88037e40cc11)
)
(fp_text user "${REFERENCE}" (at 0.3 0) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 7943ed8c-e760-4ace-9c5f-baf5589fae39)
)
(fp_circle (center 0 0) (end 3.2 0) (layer "Cmts.User") (width 0.15) (fill none) (tstamp 59e09498-d26e-4ba7-b47d-fece2ea7c274))
(fp_circle (center 0 0) (end 3.45 0) (layer "F.CrtYd") (width 0.05) (fill none) (tstamp ea4f0afc-785b-40cf-8ef1-cbe20404c18b))
(pad "" np_thru_hole circle (at 0 0) (size 3.2 3.2) (drill 3.2) (layers *.Cu *.Mask) (tstamp fead07ab-5a70-40db-ada8-c72dcc827bfc))
)
(footprint "Connector_PinSocket_2.54mm:PinSocket_1x20_P2.54mm_Vertical" (layer "F.Cu")
(tedit 5A19A41E) (tstamp a0db2c5f-7239-49ae-ba47-437c621e7ff8)
(at 112.95 53.205)
(descr "Through hole straight socket strip, 1x20, 2.54mm pitch, single row (from Kicad 4.0.7), script generated")
(tags "Through hole socket strip THT 1x20 2.54mm single row")
(property "Sheetfile" "pico-ducky.kicad_sch")
(property "Sheetname" "")
(path "/5493e8cd-8323-4518-b41a-1736b1fae7d0")
(attr through_hole)
(fp_text reference "J1" (at 0 -2.77) (layer "F.SilkS")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 5e597a99-b966-40ca-93cf-60af0be59632)
)
(fp_text value "Conn_01x20_Female" (at 0 51.03) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 62785fc4-216d-4983-9ac2-0f8d21d68772)
)
(fp_text user "${REFERENCE}" (at 0 24.13 90) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 76011dd7-642b-438a-bb90-b324383a7851)
)
(fp_line (start -1.33 49.59) (end 1.33 49.59) (layer "F.SilkS") (width 0.12) (tstamp 016969ab-09a8-471c-ace6-1bdaa379b509))
(fp_line (start -1.33 1.27) (end 1.33 1.27) (layer "F.SilkS") (width 0.12) (tstamp 05f453e1-e6ac-4725-ac6f-c737cb237871))
(fp_line (start 1.33 -1.33) (end 1.33 0) (layer "F.SilkS") (width 0.12) (tstamp d539fbf6-d474-41de-bda0-19ba022ca66a))
(fp_line (start 0 -1.33) (end 1.33 -1.33) (layer "F.SilkS") (width 0.12) (tstamp df232253-71d7-4d83-a4f3-12da054a77bd))
(fp_line (start -1.33 1.27) (end -1.33 49.59) (layer "F.SilkS") (width 0.12) (tstamp ec54d593-d947-40d5-9ce4-01090f07d42f))
(fp_line (start 1.33 1.27) (end 1.33 49.59) (layer "F.SilkS") (width 0.12) (tstamp f12847bd-98ae-41f9-b585-95021b3ae723))
(fp_line (start -1.8 50) (end -1.8 -1.8) (layer "F.CrtYd") (width 0.05) (tstamp 070365ef-242a-4d41-bc0a-b8ed9b91feca))
(fp_line (start -1.8 -1.8) (end 1.75 -1.8) (layer "F.CrtYd") (width 0.05) (tstamp 40950b1d-ca89-4396-b2fc-a613e266e57c))
(fp_line (start 1.75 -1.8) (end 1.75 50) (layer "F.CrtYd") (width 0.05) (tstamp be6525b4-e91c-443a-b608-161699ca5e45))
(fp_line (start 1.75 50) (end -1.8 50) (layer "F.CrtYd") (width 0.05) (tstamp daf121ec-2c00-4e96-96aa-2bc6f7a0fed5))
(fp_line (start -1.27 49.53) (end -1.27 -1.27) (layer "F.Fab") (width 0.1) (tstamp 181a4764-a462-4b4f-82ec-35df94857db0))
(fp_line (start 1.27 49.53) (end -1.27 49.53) (layer "F.Fab") (width 0.1) (tstamp 44d072f9-64e1-459e-80d1-c82fa5b6cb3e))
(fp_line (start 0.635 -1.27) (end 1.27 -0.635) (layer "F.Fab") (width 0.1) (tstamp 790e6361-4226-4a79-a7b2-5b2ee8aee9e8))
(fp_line (start 1.27 -0.635) (end 1.27 49.53) (layer "F.Fab") (width 0.1) (tstamp ec1f1e1b-be42-4866-9a6b-b89e6e88f2c5))
(fp_line (start -1.27 -1.27) (end 0.635 -1.27) (layer "F.Fab") (width 0.1) (tstamp f891c330-6d8a-4428-9e37-e8db48c0cba9))
(pad "1" thru_hole rect locked (at 0 0) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 40 "Net-(J1-Pad1)") (pinfunction "Pin_1") (pintype "passive") (tstamp feb0929e-d283-4515-ba6d-4fb6ed542932))
(pad "2" thru_hole oval locked (at 0 2.54) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 1 "unconnected-(J1-Pad2)") (pinfunction "Pin_2") (pintype "passive") (tstamp 3febc2fd-da92-4b4c-94c6-7e9024943f53))
(pad "3" thru_hole oval locked (at 0 5.08) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 31 "Net-(J1-Pad3)") (pinfunction "Pin_3") (pintype "passive") (tstamp 2a4b2c44-d6a9-4780-82b0-ca745511a184))
(pad "4" thru_hole oval locked (at 0 7.62) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 2 "unconnected-(J1-Pad4)") (pinfunction "Pin_4") (pintype "passive") (tstamp 629d43c1-9248-4504-bcc8-0325e1994502))
(pad "5" thru_hole oval locked (at 0 10.16) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 3 "unconnected-(J1-Pad5)") (pinfunction "Pin_5") (pintype "passive") (tstamp 71c421cf-b82d-4b3a-b6f7-ad75b4b97b86))
(pad "6" thru_hole oval locked (at 0 12.7) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 32 "Net-(J1-Pad6)") (pinfunction "Pin_6") (pintype "passive") (tstamp 121a20b0-ed40-482c-8ad3-5ff84667baa9))
(pad "7" thru_hole oval locked (at 0 15.24) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 33 "Net-(J1-Pad7)") (pinfunction "Pin_7") (pintype "passive") (tstamp 39dfcc95-5a6d-4987-a05e-ce056d625d10))
(pad "8" thru_hole oval locked (at 0 17.78) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 38 "Net-(J1-Pad8)") (pinfunction "Pin_8") (pintype "passive") (tstamp b0896365-9965-4303-b601-ab1270a33206))
(pad "9" thru_hole oval locked (at 0 20.32) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 4 "unconnected-(J1-Pad9)") (pinfunction "Pin_9") (pintype "passive") (tstamp fcb90f38-f221-4e19-8961-a534ced69fbc))
(pad "10" thru_hole oval locked (at 0 22.86) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 5 "unconnected-(J1-Pad10)") (pinfunction "Pin_10") (pintype "passive") (tstamp c54eec57-39ef-41e4-bbaf-4eee6a3ff4b2))
(pad "11" thru_hole oval locked (at 0 25.4) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 6 "unconnected-(J1-Pad11)") (pinfunction "Pin_11") (pintype "passive") (tstamp 1576d8d0-12c8-4054-834f-2c4176251961))
(pad "12" thru_hole oval locked (at 0 27.94) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 7 "unconnected-(J1-Pad12)") (pinfunction "Pin_12") (pintype "passive") (tstamp 02eee15d-cf8f-4967-9a10-3f1e76e39294))
(pad "13" thru_hole oval locked (at 0 30.48) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 39 "Net-(J1-Pad13)") (pinfunction "Pin_13") (pintype "passive") (tstamp a96926a0-932a-4907-aecc-0b46506674fc))
(pad "14" thru_hole oval locked (at 0 33.02) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 34 "Net-(J1-Pad14)") (pinfunction "Pin_14") (pintype "passive") (tstamp 97550abf-a4e2-491b-8c4b-fc5bcb83e111))
(pad "15" thru_hole oval locked (at 0 35.56) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 35 "Net-(J1-Pad15)") (pinfunction "Pin_15") (pintype "passive") (tstamp c85a30cd-7820-4060-a4c2-50ec142d23a1))
(pad "16" thru_hole oval locked (at 0 38.1) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 8 "unconnected-(J1-Pad16)") (pinfunction "Pin_16") (pintype "passive") (tstamp f68d080c-0841-4795-a272-fd003222b937))
(pad "17" thru_hole oval locked (at 0 40.64) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 9 "unconnected-(J1-Pad17)") (pinfunction "Pin_17") (pintype "passive") (tstamp bd8df187-444b-4819-a289-8ba5ff2e46b6))
(pad "18" thru_hole oval locked (at 0 43.18) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 36 "Net-(J1-Pad18)") (pinfunction "Pin_18") (pintype "passive") (tstamp c39baa4e-3aa1-4edc-bd10-b789a33040d0))
(pad "19" thru_hole oval locked (at 0 45.72) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 10 "unconnected-(J1-Pad19)") (pinfunction "Pin_19") (pintype "passive") (tstamp f5435e42-c1ee-4a96-ab1d-cf405c5546eb))
(pad "20" thru_hole oval locked (at 0 48.26) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)
(net 37 "Net-(J1-Pad20)") (pinfunction "Pin_20") (pintype "passive") (tstamp b65f6395-d469-4afb-9d3b-bc71d62896fd))
(model "${KICAD6_3DMODEL_DIR}/Connector_PinSocket_2.54mm.3dshapes/PinSocket_1x20_P2.54mm_Vertical.wrl"
(offset (xyz 0 0 0))
(scale (xyz 1 1 1))
(rotate (xyz 0 0 0))
)
)
(footprint "MSS-102545-14A-D:SW_MSS-102545-14A-D" (layer "F.Cu")
(tedit 61F6FABF) (tstamp ae77c3c8-1144-468e-ad5b-a0b4090735bd)
(at 105.7 56.74 -90)
(property "MANUFACTURER" "CUI Devices")
(property "MAXIMUM_PACKAGE_HEIGHT" "6.5 mm")
(property "PARTREV" "1.0")
(property "STANDARD" "Manufacturer Recommendations")
(property "Sheetfile" "pico-ducky.kicad_sch")
(property "Sheetname" "")
(path "/100847e3-630c-4c13-ba45-180e92370805")
(attr through_hole)
(fp_text reference "S2" (at -1.825 -2.635 90) (layer "F.SilkS")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 49a65079-57a9-46fc-8711-1d7f2cab8dbf)
)
(fp_text value "MSS-102545-14A-D" (at 7.065 2.635 90) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 87ba184f-bff5-4989-8217-6af375cc3dd8)
)
(fp_line (start 5 1.25) (end 5 -1.25) (layer "F.SilkS") (width 0.127) (tstamp 25c663ff-96b6-4263-a06e-d1829409cf73))
(fp_line (start -5 1.25) (end 5 1.25) (layer "F.SilkS") (width 0.127) (tstamp 34ce7009-187e-4541-a14e-708b3a2903d9))
(fp_line (start 5 -1.25) (end -5 -1.25) (layer "F.SilkS") (width 0.127) (tstamp 637e9edf-ffed-49a2-8408-fa110c9a4c79))
(fp_line (start -5 -1.25) (end -5 1.25) (layer "F.SilkS") (width 0.127) (tstamp b456cffc-d9d7-4c91-91f2-36ec9a65dd1b))
(fp_circle (center 0 1.85) (end 0.1 1.85) (layer "F.SilkS") (width 0.2) (fill none) (tstamp aa8663be-9516-4b07-84d2-4c4d668b8596))
(fp_line (start -5.25 1.5) (end 5.25 1.5) (layer "F.CrtYd") (width 0.05) (tstamp 291935ec-f8ff-41f0-8717-e68b8af7b8c1))
(fp_line (start 5.25 -1.5) (end -5.25 -1.5) (layer "F.CrtYd") (width 0.05) (tstamp 35fb7c56-dc85-43f7-b954-81b8040a8500))
(fp_line (start 5.25 1.5) (end 5.25 -1.5) (layer "F.CrtYd") (width 0.05) (tstamp 4e677390-a246-4ca0-954c-746e0870f88f))
(fp_line (start -5.25 -1.5) (end -5.25 1.5) (layer "F.CrtYd") (width 0.05) (tstamp 73ee7e03-97a8-4121-b568-c25f3934a935))
(fp_line (start 5 -1.25) (end -5 -1.25) (layer "F.Fab") (width 0.127) (tstamp 1a22eb2d-f625-4371-a918-ff1b97dc8219))
(fp_line (start 5 1.25) (end 5 -1.25) (layer "F.Fab") (width 0.127) (tstamp 6ff9bb63-d6fd-4e32-bb60-7ac65509c2e9))
(fp_line (start -5 1.25) (end 5 1.25) (layer "F.Fab") (width 0.127) (tstamp d767f2ff-12ec-4778-96cb-3fdd7a473d60))
(fp_line (start -5 -1.25) (end -5 1.25) (layer "F.Fab") (width 0.127) (tstamp f674b8e7-203d-419e-988a-58e0f9ae4fad))
(fp_circle (center 0 1.85) (end 0.1 1.85) (layer "F.Fab") (width 0.2) (fill none) (tstamp dfcef016-1bf5-4158-8a79-72d38a522877))
(pad "1" thru_hole rect locked (at 0 0 270) (size 1.308 1.308) (drill 0.8) (layers *.Cu *.Mask)
(net 31 "Net-(J1-Pad3)") (pintype "passive") (tstamp 9fdca5c2-1fbd-4774-a9c3-8795a40c206d))
(pad "2" thru_hole circle locked (at -2.54 0 270) (size 1.308 1.308) (drill 0.8) (layers *.Cu *.Mask)
(net 40 "Net-(J1-Pad1)") (pintype "passive") (tstamp a0d52767-051a-423c-a600-928281f27952))
(pad "3" thru_hole circle locked (at 2.54 0 270) (size 1.308 1.308) (drill 0.8) (layers *.Cu *.Mask)
(net 42 "unconnected-(S2-Pad3)") (pintype "passive") (tstamp 178ae27e-edb9-4ffb-bd13-c0a6dd659606))
)
(footprint "MountingHole:MountingHole_3.2mm_M3" (layer "F.Cu")
(tedit 56D1B4CB) (tstamp caa42d03-8d73-4d57-b233-e69949da956a)
(at 135.4 46.7)
(descr "Mounting Hole 3.2mm, no annular, M3")
(tags "mounting hole 3.2mm no annular m3")
(attr exclude_from_pos_files exclude_from_bom)
(fp_text reference "REF**" (at 0 -4.2) (layer "F.SilkS") hide
(effects (font (size 1 1) (thickness 0.15)))
(tstamp c76d4423-ef1b-4a6f-8176-33d65f2877bb)
)
(fp_text value "MountingHole_3.2mm_M3" (at 0 4.2) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp f7667b23-296e-4362-a7e3-949632c8954b)
)
(fp_text user "${REFERENCE}" (at 0.3 0) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp b873bc5d-a9af-4bd9-afcb-87ce4d417120)
)
(fp_circle (center 0 0) (end 3.2 0) (layer "Cmts.User") (width 0.15) (fill none) (tstamp 03c7f780-fc1b-487a-b30d-567d6c09fdc8))
(fp_circle (center 0 0) (end 3.45 0) (layer "F.CrtYd") (width 0.05) (fill none) (tstamp c04386e0-b49e-4fff-b380-675af13a62cb))
(pad "" np_thru_hole circle (at 0 0) (size 3.2 3.2) (drill 3.2) (layers *.Cu *.Mask) (tstamp 700e8b73-5976-423f-a3f3-ab3d9f3e9760))
)
(footprint "MountingHole:MountingHole_3.2mm_M3" (layer "F.Cu")
(tedit 56D1B4CB) (tstamp e5659af8-1b07-414b-b4ba-77ce52c44317)
(at 135.5 107.3)
(descr "Mounting Hole 3.2mm, no annular, M3")
(tags "mounting hole 3.2mm no annular m3")
(attr exclude_from_pos_files exclude_from_bom)
(fp_text reference "REF**" (at 0 -4.2) (layer "F.SilkS") hide
(effects (font (size 1 1) (thickness 0.15)))
(tstamp b9bb0e73-161a-4d06-b6eb-a9f66d8a95f5)
)
(fp_text value "MountingHole_3.2mm_M3" (at 0 4.2) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 4107d40a-e5df-4255-aacc-13f9928e090c)
)
(fp_text user "${REFERENCE}" (at 0.3 0) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 0fdc6f30-77bc-4e9b-8665-c8aa9acf5bf9)
)
(fp_circle (center 0 0) (end 3.2 0) (layer "Cmts.User") (width 0.15) (fill none) (tstamp 0ae82096-0994-4fb0-9a2a-d4ac4804abac))
(fp_circle (center 0 0) (end 3.45 0) (layer "F.CrtYd") (width 0.05) (fill none) (tstamp e0f06b5c-de63-4833-a591-ca9e19217a35))
(pad "" np_thru_hole circle (at 0 0) (size 3.2 3.2) (drill 3.2) (layers *.Cu *.Mask) (tstamp b4300db7-1220-431a-b7c3-2edbdf8fa6fc))
)
(footprint "MountingHole:MountingHole_3.2mm_M3" (layer "F.Cu")
(tedit 56D1B4CB) (tstamp ee0468cc-9675-4b75-be39-8b2679523f9a)
(at 105.8 107.4)
(descr "Mounting Hole 3.2mm, no annular, M3")
(tags "mounting hole 3.2mm no annular m3")
(attr exclude_from_pos_files exclude_from_bom)
(fp_text reference "REF**" (at 0 -4.2) (layer "F.SilkS") hide
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 8195a7cf-4576-44dd-9e0e-ee048fdb93dd)
)
(fp_text value "MountingHole_3.2mm_M3" (at 0 4.2) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp e7bb7815-0d52-4bb8-b29a-8cf960bd2905)
)
(fp_text user "${REFERENCE}" (at 0.3 0) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp d2d7bea6-0c22-495f-8666-323b30e03150)
)
(fp_circle (center 0 0) (end 3.2 0) (layer "Cmts.User") (width 0.15) (fill none) (tstamp 0f324b67-75ef-407f-8dbc-3c1fc5c2abba))
(fp_circle (center 0 0) (end 3.45 0) (layer "F.CrtYd") (width 0.05) (fill none) (tstamp 1c68b844-c861-46b7-b734-0242168a4220))
(pad "" np_thru_hole circle (at 0 0) (size 3.2 3.2) (drill 3.2) (layers *.Cu *.Mask) (tstamp 79e31048-072a-4a40-a625-26bb0b5f046b))
)
(gr_rect (start 102.12 43.06) (end 139.03 111.08) (layer "Edge.Cuts") (width 0.1) (fill none) (tstamp dbfb14d7-1f97-4dd2-9004-1d129d3b4221))
(segment (start 105.7 56.74) (end 111.405 56.74) (width 0.25) (layer "F.Cu") (net 31) (tstamp 04ad2464-115f-4e51-85ef-62527f6f730f))
(segment (start 111.405 56.74) (end 112.95 58.285) (width 0.25) (layer "F.Cu") (net 31) (tstamp 107eba14-98d9-4afc-9bd1-f9918704065d))
(segment (start 111.295 65.905) (end 112.95 65.905) (width 0.25) (layer "F.Cu") (net 32) (tstamp 50adc7ba-3b83-472b-8dfc-b74684357a6c))
(segment (start 105.4 71.8) (end 111.295 65.905) (width 0.25) (layer "F.Cu") (net 32) (tstamp ed8e419c-3e02-45bc-a398-dfef73bb479d))
(segment (start 107.594999 73.800001) (end 112.95 68.445) (width 0.25) (layer "F.Cu") (net 33) (tstamp 0e5e24d7-3dc5-4e1e-8769-7c7ae1c9e8a6))
(segment (start 105.4 73.800001) (end 107.594999 73.800001) (width 0.25) (layer "F.Cu") (net 33) (tstamp 586ef98a-572a-4c28-8086-49f602b4ce1a))
(segment (start 105.4 79.799999) (end 106.524999 79.799999) (width 0.25) (layer "F.Cu") (net 34) (tstamp 083b2527-e405-49bd-a309-2cdb85cd9a7a))
(segment (start 106.524999 79.799999) (end 112.95 86.225) (width 0.25) (layer "F.Cu") (net 34) (tstamp a4b2ea54-8955-488f-827f-865f41cd460f))
(segment (start 112.365 88.765) (end 112.95 88.765) (width 0.25) (layer "F.Cu") (net 35) (tstamp 550980db-668a-4cd5-b944-6f8f90a64b92))
(segment (start 105.4 81.8) (end 112.365 88.765) (width 0.25) (layer "F.Cu") (net 35) (tstamp 8cb3cc65-5125-4b26-8805-a87acd967839))
(segment (start 111.335 98) (end 112.95 96.385) (width 0.25) (layer "F.Cu") (net 36) (tstamp b11de678-5a1b-4645-977e-d01fbb62650b))
(segment (start 105.2 98) (end 111.335 98) (width 0.25) (layer "F.Cu") (net 36) (tstamp c49e1f14-c2a8-457b-b542-3379c6ba9356))
(segment (start 105.2 100.54) (end 112.025 100.54) (width 0.25) (layer "F.Cu") (net 37) (tstamp 6a66fc9e-c892-4458-921d-87615fa3a44a))
(segment (start 112.025 100.54) (end 112.95 101.465) (width 0.25) (layer "F.Cu") (net 37) (tstamp 9f9df658-76f9-4492-a345-d51805669b23))
(segment (start 105.4 75.8) (end 108.135 75.8) (width 0.25) (layer "F.Cu") (net 38) (tstamp 4aba0570-361a-43a1-8475-4e31d3442aa1))
(segment (start 108.135 75.8) (end 112.95 70.985) (width 0.25) (layer "F.Cu") (net 38) (tstamp ac902824-adcb-4fe8-b2b9-74384e4a02b2))
(segment (start 107.065001 77.800001) (end 112.95 83.685) (width 0.25) (layer "F.Cu") (net 39) (tstamp 14a5d740-983d-4a64-b3ba-76fb523ba838))
(segment (start 105.4 77.800001) (end 107.065001 77.800001) (width 0.25) (layer "F.Cu") (net 39) (tstamp bcf37e83-ac07-479a-9d97-44519b68796f))
(segment (start 106.695 53.205) (end 105.7 54.2) (width 0.25) (layer "F.Cu") (net 40) (tstamp 5c706984-8543-460e-8fea-862f0cc5a54d))
(segment (start 112.95 53.205) (end 106.695 53.205) (width 0.25) (layer "F.Cu") (net 40) (tstamp d6bd5cd5-1aab-4e14-a87e-6b0202d3c68c))
)

View File

@@ -1,75 +0,0 @@
{
"board": {
"active_layer": 0,
"active_layer_preset": "All Layers",
"auto_track_width": true,
"hidden_nets": [],
"high_contrast_mode": 0,
"net_color_mode": 1,
"opacity": {
"pads": 1.0,
"tracks": 1.0,
"vias": 1.0,
"zones": 0.6
},
"ratsnest_display_mode": 0,
"selection_filter": {
"dimensions": true,
"footprints": true,
"graphics": true,
"keepouts": true,
"lockedItems": true,
"otherItems": true,
"pads": true,
"text": true,
"tracks": true,
"vias": true,
"zones": true
},
"visible_items": [
0,
1,
2,
3,
4,
5,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
32,
33,
34,
35,
36
],
"visible_layers": "fffffff_ffffffff",
"zone_display_mode": 0
},
"meta": {
"filename": "pico-ducky.kicad_prl",
"version": 3
},
"project": {
"files": []
}
}

View File

@@ -1,433 +0,0 @@
{
"board": {
"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": 0.762,
"height": 1.524,
"width": 1.524
},
"silk_line_width": 0.15,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.15,
"silk_text_upright": false,
"zones": {
"45_degree_only": false,
"min_clearance": 0.508
}
},
"diff_pair_dimensions": [
{
"gap": 0.0,
"via_gap": 0.0,
"width": 0.0
}
],
"drc_exclusions": [],
"meta": {
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"copper_edge_clearance": "error",
"courtyards_overlap": "error",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint_type_mismatch": "error",
"hole_clearance": "error",
"hole_near_hole": "error",
"invalid_outline": "error",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "error",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_over_copper": "warning",
"silk_overlap": "warning",
"skew_out_of_range": "error",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_dangling": "warning",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zone_has_empty_net": "error",
"zones_intersect": "error"
},
"rules": {
"allow_blind_buried_vias": false,
"allow_microvias": false,
"max_error": 0.005,
"min_clearance": 0.0,
"min_copper_edge_clearance": 0.0,
"min_hole_clearance": 0.25,
"min_hole_to_hole": 0.25,
"min_microvia_diameter": 0.19999999999999998,
"min_microvia_drill": 0.09999999999999999,
"min_silk_clearance": 0.0,
"min_through_hole_diameter": 0.3,
"min_track_width": 0.19999999999999998,
"min_via_annular_width": 0.049999999999999996,
"min_via_diameter": 0.39999999999999997,
"solder_mask_clearance": 0.0,
"solder_mask_min_width": 0.0,
"use_height_for_length_calcs": true
},
"track_widths": [
0.0
],
"via_dimensions": [
{
"diameter": 0.0,
"drill": 0.0
}
],
"zones_allow_external_fillets": false,
"zones_use_no_outline": true
},
"layer_presets": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_entry_needed": "error",
"bus_label_syntax": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"extra_units": "error",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"lib_symbol_issues": "warning",
"multiple_net_names": "warning",
"net_not_bus_member": "warning",
"no_connect_connected": "warning",
"no_connect_dangling": "warning",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "warning",
"power_pin_not_driven": "error",
"similar_labels": "warning",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "pico-ducky.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12.0,
"clearance": 0.2,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.25,
"via_diameter": 0.8,
"via_drill": 0.4,
"wire_width": 6.0
}
],
"meta": {
"version": 2
},
"net_colors": null
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"specctra_dsn": "",
"step": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"annotate_start_num": 0,
"drawing": {
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"field_names": [],
"intersheets_ref_own_page": false,
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
"intersheets_ref_suffix": "",
"junction_size_choice": 3,
"label_size_ratio": 0.375,
"pin_symbol_size": 25.0,
"text_offset_ratio": 0.15
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "",
"ngspice": {
"fix_include_paths": true,
"fix_passive_vals": false,
"meta": {
"version": 0
},
"model_mode": 0,
"workbook_filename": ""
},
"page_layout_descr_file": "",
"plot_directory": "",
"spice_adjust_passive_values": false,
"spice_external_command": "spice \"%I\"",
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"9538e4ed-27e6-4c37-b989-9859dc0d49e8",
""
]
],
"text_variables": {}
}

File diff suppressed because it is too large Load Diff

48
boot.py
View File

@@ -1,16 +1,58 @@
# License : GPLv2.0
# copyright (c) 2023 Dave Bailey
# Author: Dave Bailey (dbisu, @daveisu)
# Pico and Pico W board support
from board import * from board import *
import board
import digitalio import digitalio
import storage import storage
import os
noStorageStatus = False def is_exfil_enabled(payload_path="payload.dd"):
try:
with open(payload_path, "r") as f:
for line in f:
if "$_EXFIL_MODE_ENABLED" in line and "TRUE" in line.upper():
return True
except OSError:
pass
return False
exfil_enabled = is_exfil_enabled()
loot_exists = "loot.bin" in os.listdir("/")
noStorage = False
noStoragePin = digitalio.DigitalInOut(GP15) noStoragePin = digitalio.DigitalInOut(GP15)
noStoragePin.switch_to_input(pull=digitalio.Pull.UP) noStoragePin.switch_to_input(pull=digitalio.Pull.UP)
noStorageStatus = not noStoragePin.value noStorageStatus = noStoragePin.value
if(noStorageStatus == True): # If GP15 is not connected, it will default to being pulled high (True)
# If GP is connected to GND, it will be low (False)
# Pico:
# GP15 not connected == USB visible
# GP15 connected to GND == USB not visible
# Pico W:
# GP15 not connected == USB NOT visible
# GP15 connected to GND == USB visible
if exfil_enabled:
if not loot_exists:
storage.disable_usb_drive()
if(board.board_id == 'raspberry_pi_pico' or board.board_id == 'raspberry_pi_pico2'):
# On Pi Pico, default to USB visible
noStorage = not noStorageStatus
elif(board.board_id == 'raspberry_pi_pico_w' or board.board_id == 'raspberry_pi_pico2_w'):
# on Pi Pico W, default to USB hidden by default
# so webapp can access storage
noStorage = noStorageStatus
if(noStorage == True):
# don't show USB drive to host PC # don't show USB drive to host PC
storage.disable_usb_drive() storage.disable_usb_drive()
print("Disabling USB drive") print("Disabling USB drive")
else: else:
# normal boot # normal boot
print("USB drive enabled") print("USB drive enabled")

View File

@@ -0,0 +1,126 @@
import os
import shutil
import re
import sys
import zipfile
languages = [ "MAC_FR",
"US_DVO",
"WIN_BR",
"WIN_CZ",
"WIN_CZ1",
"WIN_DA",
"WIN_DE",
"WIN_ES",
"WIN_FR",
"WIN_HU",
"WIN_IT",
"WIN_PO",
"WIN_SW",
"WIN_TR",
"WIN_UK" ]
supported_boards = ["raspberry_pi_pico",
"raspberry_pi_pico_w",
"raspberry_pi_pico2",
"raspberry_pi_pico2_w"]
files_to_bundle = ["boot.py",
"code.py",
"duckyinpython.py",
"pins.py",
"wsgiserver.py",
"webapp.py",
"secrets.py",
"payload.dd",
"payload2.dd",
"payload3.dd",
"payload4.dd",
"INSTALL.txt"]
dirs_to_bundle = ["lib"]
def bundle_files_to_zip(source_dir, destination_dir, file_list, target_file, replacement_dict, version):
"""
Bundles files from a source directory into a new directory with a unique name.
Args:
source_dir: Path to the source directory containing the files.
destination_dir: Path to the destination directory where bundles will be created.
file_list: List of filenames to be included in the bundle.
target_file: Filename of the file to be modified.
replacement_dict: Dictionary containing key-value pairs for text replacements.
Returns:
None
"""
if not os.path.exists(destination_dir):
os.makedirs(destination_dir)
# Generate a unique bundle name (e.g., using a timestamp)
bundle_name = f"pico-ducky-{version}-{destination_dir}.zip"
bundle_path = os.path.join(destination_dir, bundle_name)
# Create a temporary directory for the bundle contents
temp_dir = os.path.join(destination_dir, "temp_bundle")
os.makedirs(temp_dir)
for filename in file_list:
source_file = os.path.join(source_dir, filename)
destination_file = os.path.join(temp_dir, filename)
if filename == target_file:
with open(source_file, 'r') as f:
file_content = f.read()
for key, value in replacement_dict.items():
file_content = re.sub(key, value, file_content)
with open(destination_file, 'w') as f:
f.write(file_content)
else:
shutil.copy2(source_file, destination_file)
for dir in dirs_to_bundle:
shutil.copytree(os.path.join(source_dir,dir),os.path.join(temp_dir,dir))
#find uf2 files for supported boards
for root, dirs, files in os.walk(source_dir):
for file in files:
for board in supported_boards:
if '-'+board+'-' in file:
source_file = os.path.join(source_dir, file)
destination_file = os.path.join(temp_dir, file)
shutil.copy2(source_file, destination_file)
# Create the ZIP archive
with zipfile.ZipFile(bundle_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
for root, _, files in os.walk(temp_dir):
for file in files:
file_path = os.path.join(root, file)
archive_path = os.path.relpath(file_path, temp_dir)
zipf.write(file_path, archive_path)
# Remove the temporary directory
shutil.rmtree(temp_dir)
def main(argv):
version = argv[0]
for dest_dir in languages:
source_directory = "US"
target_file_to_modify = "duckyinpython.py"
replacements = {
"#from keyboard_layout_win_LANG": "from keyboard_layout_"+dest_dir.lower(),
"#from keycode_win_LANG": "from keycode_"+dest_dir.lower(),
"from adafruit_hid.keyboard_": "#from adafruit_hid.keyboard_",
"from adafruit_hid.keycode": "#from adafruit_hid.keycode"
}
bundle_files_to_zip(source_directory, dest_dir, files_to_bundle,
target_file_to_modify, replacements, version)
if __name__ == "__main__":
main(sys.argv[1:])

88
code.py Normal file
View File

@@ -0,0 +1,88 @@
# License : GPLv2.0
# copyright (c) 2023 Dave Bailey
# Author: Dave Bailey (dbisu, @daveisu)
# Pico and Pico W board support
import supervisor
import os
import pwmio
import time
import digitalio
from board import *
import board
from duckyinpython import *
if(board.board_id == 'raspberry_pi_pico_w' or board.board_id == 'raspberry_pi_pico2_w'):
import wifi
from webapp import *
# sleep at the start to allow the device to be recognized by the host computer
time.sleep(.5)
def startWiFi():
import ipaddress
# Get wifi details and more from a secrets.py file
try:
from secrets import secrets
except ImportError:
print("WiFi secrets are kept in secrets.py, please add them there!")
raise
print("Connect wifi")
#wifi.radio.connect(secrets['ssid'],secrets['password'])
wifi.radio.start_ap(secrets['ssid'],secrets['password'])
HOST = repr(wifi.radio.ipv4_address_ap)
PORT = 80 # Port to listen on
print(HOST,PORT)
# turn off automatically reloading when files are written to the pico
#supervisor.disable_autoreload()
supervisor.runtime.autoreload = False
if(board.board_id == 'raspberry_pi_pico' or board.board_id == 'raspberry_pi_pico2'):
led = pwmio.PWMOut(board.LED, frequency=5000, duty_cycle=0)
elif(board.board_id == 'raspberry_pi_pico_w' or board.board_id == 'raspberry_pi_pico2_w'):
led = digitalio.DigitalInOut(board.LED)
led.switch_to_output()
async def run_payload_on_startup():
progStatus = False
progStatus = getProgrammingStatus()
print("progStatus", progStatus)
if(progStatus == False):
print("Finding payload")
if "loot.bin" in os.listdir("/"):
print("loot.bin exists, skipping payload execution.")
else:
payload = selectPayload()
await asyncio.sleep(0.1)
print("Running")
await runScript(payload)
else:
print("Done")
led_state = False
async def main_loop():
global led,button1
button_task = asyncio.create_task(monitor_buttons(button1))
payload_task = asyncio.create_task(run_payload_on_startup())
led_task = asyncio.create_task(monitor_led_changes())
if(board.board_id == 'raspberry_pi_pico_w' or board.board_id == 'raspberry_pi_pico2_w'):
pico_led_task = asyncio.create_task(blink_pico_w_led(led))
print("Starting Wifi")
startWiFi()
print("Starting Web Service")
webservice_task = asyncio.create_task(startWebService())
await asyncio.gather(pico_led_task, button_task, webservice_task, payload_task, led_task)
else:
pico_led_task = asyncio.create_task(blink_pico_led(led))
await asyncio.gather(pico_led_task, button_task, payload_task, led_task )
asyncio.run(main_loop())

View File

@@ -1,9 +1,24 @@
# License : GPLv2.0 # License : GPLv2.0
# copyright (c) 2021 Dave Bailey # copyright (c) 2023 Dave Bailey
# Author: Dave Bailey (dbisu, @daveisu) # Author: Dave Bailey (dbisu, @daveisu)
#
# TODO: ADD support for the following:
# Add jitter
# Add LED functionality
import re
import time
import random
import digitalio
from digitalio import DigitalInOut, Pull
from adafruit_debouncer import Debouncer
import board
from board import *
import asyncio
import usb_hid import usb_hid
from adafruit_hid.keyboard import Keyboard from adafruit_hid.keyboard import Keyboard
from adafruit_hid.consumer_control import ConsumerControl
from adafruit_hid.consumer_control_code import ConsumerControlCode
from pins import *
# comment out these lines for non_US keyboards # comment out these lines for non_US keyboards
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS as KeyboardLayout from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS as KeyboardLayout
@@ -11,38 +26,40 @@ from adafruit_hid.keycode import Keycode
# uncomment these lines for non_US keyboards # uncomment these lines for non_US keyboards
# replace LANG with appropriate language # replace LANG with appropriate language
#from keyboard_layout_win_LANG import KeyboardLayout #from keyboard_layout_win_LANG import KeyboardLayout as KeyboardLayout
#from keycode_win_LANG import Keycode #from keycode_win_LANG import Keycode
import supervisor def _capsOn():
return kbd.led_on(Keyboard.LED_CAPS_LOCK)
import time def _numOn():
import digitalio return kbd.led_on(Keyboard.LED_NUM_LOCK)
from board import *
import pwmio
led = pwmio.PWMOut(LED, frequency=5000, duty_cycle=0) def _scrollOn():
return kbd.led_on(Keyboard.LED_SCROLL_LOCK)
def led_pwm_up(led): def pressLock(key):
for i in range(100): kbd.press(key)
# PWM LED up and down kbd.release(key)
if i < 50:
led.duty_cycle = int(i * 2 * 65535 / 100) # Up
time.sleep(0.01)
def led_pwm_down(led):
for i in range(100):
# PWM LED up and down
if i >= 50:
led.duty_cycle = 65535 - int((i - 50) * 2 * 65535 / 100) # Down
time.sleep(0.01)
# led = digitalio.DigitalInOut(LED) def SaveKeyboardLedState():
# led.direction = digitalio.Direction.OUTPUT variables["$_INITIAL_SCROLLLOCK"] = _scrollOn()
variables["$_INITIAL_NUMLOCK"] = _numOn()
variables ["$_INITIAL_CAPSLOCK"] = _capsOn()
duckyCommands = {
'WINDOWS': Keycode.WINDOWS, 'GUI': Keycode.GUI, def RestoreKeyboardLedState():
'APP': Keycode.APPLICATION, 'MENU': Keycode.APPLICATION, 'SHIFT': Keycode.SHIFT, if(variables["$_INITIAL_CAPSLOCK"] != _capsOn()):
'ALT': Keycode.ALT, 'CONTROL': Keycode.CONTROL, 'CTRL': Keycode.CONTROL, pressLock(Keycode.CAPS_LOCK)
if(variables["$_INITIAL_NUMLOCK"] != _numOn()):
pressLock(Keycode.NUM_LOCK)
if(variables["$_INITIAL_SCROLLLOCK"] != _scrollOn()):
pressLock(Keycode.SCROLL_LOCK)
duckyKeys = {
'WINDOWS': Keycode.GUI, 'RWINDOWS': Keycode.RIGHT_GUI, 'GUI': Keycode.GUI, 'RGUI': Keycode.RIGHT_GUI, 'COMMAND': Keycode.GUI, 'RCOMMAND': Keycode.RIGHT_GUI,
'APP': Keycode.APPLICATION, 'MENU': Keycode.APPLICATION, 'SHIFT': Keycode.SHIFT, 'RSHIFT': Keycode.RIGHT_SHIFT,
'ALT': Keycode.ALT, 'RALT': Keycode.RIGHT_ALT, 'OPTION': Keycode.ALT, 'ROPTION': Keycode.RIGHT_ALT, 'CONTROL': Keycode.CONTROL, 'CTRL': Keycode.CONTROL, 'RCTRL': Keycode.RIGHT_CONTROL,
'DOWNARROW': Keycode.DOWN_ARROW, 'DOWN': Keycode.DOWN_ARROW, 'LEFTARROW': Keycode.LEFT_ARROW, 'DOWNARROW': Keycode.DOWN_ARROW, 'DOWN': Keycode.DOWN_ARROW, 'LEFTARROW': Keycode.LEFT_ARROW,
'LEFT': Keycode.LEFT_ARROW, 'RIGHTARROW': Keycode.RIGHT_ARROW, 'RIGHT': Keycode.RIGHT_ARROW, 'LEFT': Keycode.LEFT_ARROW, 'RIGHTARROW': Keycode.RIGHT_ARROW, 'RIGHT': Keycode.RIGHT_ARROW,
'UPARROW': Keycode.UP_ARROW, 'UP': Keycode.UP_ARROW, 'BREAK': Keycode.PAUSE, 'UPARROW': Keycode.UP_ARROW, 'UP': Keycode.UP_ARROW, 'BREAK': Keycode.PAUSE,
@@ -60,48 +77,255 @@ duckyCommands = {
'Z': Keycode.Z, 'F1': Keycode.F1, 'F2': Keycode.F2, 'F3': Keycode.F3, 'Z': Keycode.Z, 'F1': Keycode.F1, 'F2': Keycode.F2, 'F3': Keycode.F3,
'F4': Keycode.F4, 'F5': Keycode.F5, 'F6': Keycode.F6, 'F7': Keycode.F7, 'F4': Keycode.F4, 'F5': Keycode.F5, 'F6': Keycode.F6, 'F7': Keycode.F7,
'F8': Keycode.F8, 'F9': Keycode.F9, 'F10': Keycode.F10, 'F11': Keycode.F11, 'F8': Keycode.F8, 'F9': Keycode.F9, 'F10': Keycode.F10, 'F11': Keycode.F11,
'F12': Keycode.F12, 'F12': Keycode.F12, 'F13': Keycode.F13, 'F14': Keycode.F14, 'F15': Keycode.F15,
'F16': Keycode.F16, 'F17': Keycode.F17, 'F18': Keycode.F18, 'F19': Keycode.F19,
'F20': Keycode.F20, 'F21': Keycode.F21, 'F22': Keycode.F22, 'F23': Keycode.F23,
'F24': Keycode.F24
} }
duckyConsumerKeys = {
'MK_VOLUP': ConsumerControlCode.VOLUME_INCREMENT, 'MK_VOLDOWN': ConsumerControlCode.VOLUME_DECREMENT, 'MK_MUTE': ConsumerControlCode.MUTE,
'MK_NEXT': ConsumerControlCode.SCAN_NEXT_TRACK, 'MK_PREV': ConsumerControlCode.SCAN_PREVIOUS_TRACK,
'MK_PP': ConsumerControlCode.PLAY_PAUSE, 'MK_STOP': ConsumerControlCode.STOP
}
variables = {"$_RANDOM_MIN": 0, "$_RANDOM_MAX": 65535,"$_EXFIL_MODE_ENABLED": False,"$_EXFIL_LEDS_ENABLED": False,"$_INITIAL_SCROLLLOCK": False, "$_INITIAL_NUMLOCK": False, "$_INITIAL_CAPSLOCK": False}
internalVariables = {"$_CAPSLOCK_ON": _capsOn, "$_NUMLOCK_ON": _numOn, "$_SCROLLLOCK_ON": _scrollOn}
defines = {}
functions = {}
letters = "abcdefghijklmnopqrstuvwxyz"
numbers = "0123456789"
specialChars = "!@#$%^&*()"
class IF:
def __init__(self, condition, codeIter):
self.condition = condition
self.codeIter = list(codeIter)
self.lastIfResult = None
def _exitIf(self):
_depth = 0
for line in self.codeIter:
line = self.codeIter.pop(0)
line = line.strip()
if line.upper().startswith("END_IF"):
_depth -= 1
elif line.upper().startswith("IF"):
_depth += 1
if _depth < 0:
print("No else, exiting" + str(list(self.codeIter)))
break
return(self.codeIter)
def runIf(self):
if isinstance(self.condition, str):
self.lastIfResult = evaluateExpression(self.condition)
elif isinstance(self.condition, bool):
self.lastIfResult = self.condition
else:
raise ValueError("Invalid condition type")
# print(f"condition {self.condition} result is {self.lastIfResult} since \"$VAR\" is {variables["$VAR"]}, code is {self.codeIter}")
depth = 0
for line in self.codeIter:
line = self.codeIter.pop(0)
line = line.strip()
if line == "":
continue
# print(line)
if line.startswith("IF"):
depth += 1
elif line.startswith("END_IF"):
if depth == 0:
return(self.codeIter, -1)
depth -=1
elif line.startswith("ELSE") and depth == 0:
# print(f"ELSE LINE {line}, lastIfResult: {self.lastIfResult}")
if self.lastIfResult is False:
line = line[4:].strip() # Remove 'ELSE' and strip whitespace
if line.startswith("IF"):
nestedCondition = _getIfCondition(line)
# print(f"nested IF {nestedCondition}")
self.codeIter, self.lastIfResult = IF(nestedCondition, self.codeIter).runIf()
if self.lastIfResult == -1 or self.lastIfResult == True:
# print(f"self.lastIfResult {self.lastIfResult}")
return(self.codeIter, True)
else:
return IF(True, self.codeIter).runIf() #< Regular ELSE block
else:
self._exitIf()
break
# Process regular lines
elif self.lastIfResult:
# print(f"running line {line}")
self.codeIter = list(parseLine(line, self.codeIter))
# print("end of if")
return(self.codeIter, self.lastIfResult)
def _getIfCondition(line):
return str(line)[2:-4].strip()
def _isCodeBlock(line):
line = line.upper().strip()
if line.startswith("IF") or line.startswith("WHILE"):
return True
return False
def _getCodeBlock(linesIter):
"""Returns the code block starting at the given line."""
code = []
depth = 1
for line in linesIter:
line = line.strip()
if line.upper().startswith("END_"):
depth -= 1
elif _isCodeBlock(line):
depth += 1
if depth <= 0:
break
code.append(line)
return code
def replaceBooleans(text): #< fix capitalization mistakes in true and false (for evaluating with booleans)
# Replace any letter-by-letter match for "true" with the proper "True"
text = re.sub(r'[Tt][Rr][Uu][Ee]', 'True', text)
# Replace any letter-by-letter match for "false" with the proper "False"
text = re.sub(r'[Ff][Aa][Ll][Ss][Ee]', 'False', text)
return text
def evaluateExpression(expression):
"""Evaluates an expression with variables and returns the result."""
expression = replaceVariables(expression)
expression = replaceBooleans(expression) #< Cant use re due its limitation in circutpython
print(expression)
expression = expression.replace("^", "**") #< Replace ^ with ** for exponentiation
expression = expression.replace("&&", "and")
expression = expression.replace("||", "or")
expression = expression.replace("TRUE", "True")
expression = expression.replace("FALSE", "False")
return eval(expression, {}, variables)
def deepcopy(List):
return(List[:])
def convertLine(line): def convertLine(line):
newline = [] commands = []
# print(line) # print(line)
# loop on each key - the filter removes empty values # loop on each key - the filter removes empty values
for key in filter(None, line.split(" ")): for key in filter(None, line.split(" ")):
key = key.upper() key = key.upper()
# find the keycode for the command in the list # find the keycode for the command in the list
command_keycode = duckyCommands.get(key, None) command_keycode = duckyKeys.get(key, None)
command_consumer_keycode = duckyConsumerKeys.get(key, None)
if command_keycode is not None: if command_keycode is not None:
# if it exists in the list, use it # if it exists in the list, use it
newline.append(command_keycode) commands.append(command_keycode)
elif command_consumer_keycode is not None:
# if it exists in the list, use it
commands.append(1000+command_consumer_keycode)
elif hasattr(Keycode, key): elif hasattr(Keycode, key):
# if it's in the Keycode module, use it (allows any valid keycode) # if it's in the Keycode module, use it (allows any valid keycode)
newline.append(getattr(Keycode, key)) commands.append(getattr(Keycode, key))
else: else:
# if it's not a known key name, show the error for diagnosis # if it's not a known key name, show the error for diagnosis
print(f"Unknown key: <{key}>") print(f"Unknown key: <{key}>")
# print(newline) # print(commands)
return newline return commands
def runScriptLine(line): def runScriptLine(line):
for k in line: keys = convertLine(line)
kbd.press(k) for k in keys:
kbd.release_all() if k > 1000:
consumerControl.press(int(k-1000))
else:
kbd.press(k)
for k in reversed(keys):
if k > 1000:
consumerControl.release()
else:
kbd.release(k)
def sendString(line): def sendString(line):
layout.write(line) layout.write(line)
def parseLine(line): def replaceVariables(line):
global defaultDelay for var in variables:
if(line[0:3] == "REM"): line = line.replace(var, str(variables[var]))
# ignore ducky script comments for var in internalVariables:
line = line.replace(var, str(internalVariables[var]()))
return line
def replaceDefines(line):
for define, value in defines.items():
line = line.replace(define, value)
return line
async def parseLine(line, script_lines):
global defaultDelay, variables, functions, defines
line = line.strip()
line = line.replace("$_RANDOM_INT", str(random.randint(int(variables.get("$_RANDOM_MIN", 0)), int(variables.get("$_RANDOM_MAX", 65535)))))
line = replaceDefines(line)
if line[:10] == "INJECT_MOD":
line = line[11:]
elif line.startswith("REM_BLOCK"):
while line.startswith("END_REM") == False:
line = next(script_lines).strip()
# print(line)
elif(line[0:3] == "REM"):
pass pass
elif line.startswith("HOLD"):
# HOLD command to press and hold a key
key = line[5:].strip().upper()
commandKeycode = duckyKeys.get(key, None)
if commandKeycode:
kbd.press(commandKeycode)
else:
print(f"Unknown key to HOLD: <{key}>")
elif line.startswith("RELEASE"):
# RELEASE command to release a held key
key = line[8:].strip().upper()
commandKeycode = duckyKeys.get(key, None)
if commandKeycode:
kbd.release(commandKeycode)
else:
print(f"Unknown key to RELEASE: <{key}>")
elif(line[0:5] == "DELAY"): elif(line[0:5] == "DELAY"):
line = replaceVariables(line)
time.sleep(float(line[6:])/1000) time.sleep(float(line[6:])/1000)
elif line == "STRINGLN": #< stringLN block
line = next(script_lines).strip()
line = replaceVariables(line)
while line.startswith("END_STRINGLN") == False:
sendString(line)
kbd.press(Keycode.ENTER)
kbd.release(Keycode.ENTER)
line = next(script_lines).strip()
line = replaceVariables(line)
line = replaceDefines(line)
elif(line[0:8] == "STRINGLN"):
sendString(replaceVariables(line[9:]))
kbd.press(Keycode.ENTER)
kbd.release(Keycode.ENTER)
elif line == "STRING": #< string block
line = next(script_lines).strip()
line = replaceVariables(line)
while line.startswith("END_STRING") == False:
sendString(line)
line = next(script_lines).strip()
line = replaceVariables(line)
line = replaceDefines(line)
elif(line[0:6] == "STRING"): elif(line[0:6] == "STRING"):
sendString(line[7:]) sendString(replaceVariables(line[7:]))
elif(line[0:5] == "PRINT"): elif(line[0:5] == "PRINT"):
print("[SCRIPT]: " + line[6:]) line = replaceVariables(line[6:])
print("[SCRIPT]: " + line)
elif(line[0:6] == "IMPORT"): elif(line[0:6] == "IMPORT"):
runScript(line[7:]) runScript(line[7:])
elif(line[0:13] == "DEFAULT_DELAY"): elif(line[0:13] == "DEFAULT_DELAY"):
@@ -113,74 +337,187 @@ def parseLine(line):
led.value = False led.value = False
else: else:
led.value = True led.value = True
elif(line[0:3] == "LED"):
if(led.value == True):
led.value = False
else:
led.value = True
elif(line[:7] == "LED_OFF"):
led.value = False
elif(line[:5] == "LED_R"):
led.value = True
elif(line[:5] == "LED_G"):
led.value = True
elif(line[0:21] == "WAIT_FOR_BUTTON_PRESS"):
button_pressed = False
# NOTE: we don't use assincio in this case because we want to block code execution
while not button_pressed:
button1.update()
button1Pushed = button1.fell
button1Released = button1.rose
button1Held = not button1.value
if(button1Pushed):
print("Button 1 pushed")
button_pressed = True
elif line.startswith("VAR"):
match = re.match(r"VAR\s+\$(\w+)\s*=\s*(.+)", line)
if match:
varName = f"${match.group(1)}"
value = evaluateExpression(match.group(2))
variables[varName] = value
else:
raise SyntaxError(f"Invalid variable declaration: {line}")
elif line.startswith("$"):
match = re.match(r"\$(\w+)\s*=\s*(.+)", line)
if match:
varName = f"${match.group(1)}"
expression = match.group(2)
value = evaluateExpression(expression)
variables[varName] = value
else:
raise SyntaxError(f"Invalid variable update, declare variable first: {line}")
elif line.startswith("DEFINE"):
defineLocation = line.find(" ")
valueLocation = line.find(" ", defineLocation + 1)
defineName = line[defineLocation+1:valueLocation]
defineValue = line[valueLocation+1:]
defines[defineName] = defineValue
elif line.startswith("FUNCTION"):
# print("ENTER FUNCTION")
func_name = line.split()[1]
functions[func_name] = []
line = next(script_lines).strip()
while line != "END_FUNCTION":
functions[func_name].append(line)
line = next(script_lines).strip()
elif line.startswith("WHILE"):
# print("ENTER WHILE LOOP")
condition = line[5:].strip()
loopCode = list(_getCodeBlock(script_lines))
while evaluateExpression(condition) == True:
currentIterCode = deepcopy(loopCode)
# print(loopCode)
while currentIterCode:
loopLine = currentIterCode.pop(0)
currentIterCode = list(parseLine(loopLine, iter(currentIterCode))) #< very inefficient, should be replaced later.
elif line.upper().startswith("IF"):
script_lines, ret = IF(_getIfCondition(line), script_lines).runIf()
print(f"IF returned {ret} code")
elif line.upper().startswith("END_IF"):
pass
elif line == "RANDOM_LOWERCASE_LETTER":
sendString(random.choice(letters))
elif line == "RANDOM_UPPERCASE_LETTER":
sendString(random.choice(letters.upper()))
elif line == "RANDOM_LETTER":
sendString(random.choice(letters + letters.upper()))
elif line == "RANDOM_NUMBER":
sendString(random.choice(numbers))
elif line == "RANDOM_SPECIAL":
sendString(random.choice(specialChars))
elif line == "RANDOM_CHAR":
sendString(random.choice(letters + letters.upper() + numbers + specialChars))
elif line == "VID_RANDOM" or line == "PID_RANDOM":
for _ in range(4):
sendString(random.choice("0123456789ABCDEF"))
elif line == "MAN_RANDOM" or line == "PROD_RANDOM":
for _ in range(12):
sendString(random.choice(letters + letters.upper() + numbers))
elif line == "SERIAL_RANDOM":
for _ in range(12):
sendString(random.choice(letters + letters.upper() + numbers + specialChars))
elif line == "RESET":
kbd.release_all()
elif line == "SAVE_HOST_KEYBOARD_LOCK_STATE":
SaveKeyboardLedState()
elif line == "RESTORE_HOST_KEYBOARD_LOCK_STATE":
RestoreKeyboardLedState()
elif line == "WAIT_FOR_SCROLL_CHANGE":
last_scroll_state = _scrollOn()
while True:
current_scroll_state = _scrollOn()
if current_scroll_state != last_scroll_state:
break
await asyncio.sleep(0.01)
elif line in functions:
updated_lines = []
inside_while_block = False
for func_line in functions[line]:
if func_line.startswith("WHILE"):
inside_while_block = True # Start skipping lines
updated_lines.append(func_line)
elif func_line.startswith("END_WHILE"):
inside_while_block = False # Stop skipping lines
updated_lines.append(func_line)
parseLine(updated_lines[0], iter(updated_lines))
updated_lines = [] # Clear updated_lines after parsing
elif inside_while_block:
updated_lines.append(func_line)
elif not (func_line.startswith("END_WHILE") or func_line.startswith("WHILE")):
parseLine(func_line, iter(functions[line]))
else: else:
newScriptLine = convertLine(line) runScriptLine(line)
runScriptLine(newScriptLine)
return(script_lines)
kbd = Keyboard(usb_hid.devices) kbd = Keyboard(usb_hid.devices)
consumerControl = ConsumerControl(usb_hid.devices)
layout = KeyboardLayout(kbd) layout = KeyboardLayout(kbd)
# turn off automatically reloading when files are written to the pico
supervisor.disable_autoreload()
# sleep at the start to allow the device to be recognized by the host computer
time.sleep(.5)
led_pwm_up(led)
def getProgrammingStatus(): def getProgrammingStatus():
# check GP0 for setup mode
# see setup mode for instructions # see setup mode for instructions
progStatusPin = digitalio.DigitalInOut(GP0)
progStatusPin.switch_to_input(pull=digitalio.Pull.UP)
progStatus = not progStatusPin.value progStatus = not progStatusPin.value
return(progStatus) return(progStatus)
defaultDelay = 0 defaultDelay = 0
def runScript(file): async def runScript(file):
global defaultDelay global defaultDelay
duckyScriptPath = file duckyScriptPath = file
restart = True
try: try:
f = open(duckyScriptPath,"r",encoding='utf-8') while restart:
previousLine = "" restart = False
for line in f: with open(duckyScriptPath, "r", encoding='utf-8') as f:
line = line.rstrip() script_lines = iter(f.readlines())
if(line[0:6] == "REPEAT"): previousLine = ""
for i in range(int(line[7:])): for line in script_lines:
#repeat the last command print(f"runScript: {line}")
parseLine(previousLine) if(line[0:6] == "REPEAT"):
time.sleep(float(defaultDelay)/1000) for i in range(int(line[7:])):
else: #repeat the last command
parseLine(line) parseLine(previousLine, script_lines)
previousLine = line time.sleep(float(defaultDelay) / 1000)
time.sleep(float(defaultDelay)/1000) elif line.startswith("RESTART_PAYLOAD"):
restart = True
break
elif line.startswith("STOP_PAYLOAD"):
restart = False
break
else:
await parseLine(line, script_lines)
previousLine = line
time.sleep(float(defaultDelay) / 1000)
except OSError as e: except OSError as e:
print("Unable to open file ", file) print("Unable to open file", file)
def selectPayload(): def selectPayload():
global payload1Pin, payload2Pin, payload3Pin, payload4Pin
payload = "payload.dd" payload = "payload.dd"
# check switch status # check switch status
# payload1 = GPIO4 to GND
# payload2 = GPIO5 to GND
# payload3 = GPIO10 to GND
# payload4 = GPIO11 to GND
payload1Pin = digitalio.DigitalInOut(GP4)
payload1Pin.switch_to_input(pull=digitalio.Pull.UP)
payload1State = not payload1Pin.value payload1State = not payload1Pin.value
payload2Pin = digitalio.DigitalInOut(GP5)
payload2Pin.switch_to_input(pull=digitalio.Pull.UP)
payload2State = not payload2Pin.value payload2State = not payload2Pin.value
payload3Pin = digitalio.DigitalInOut(GP10)
payload3Pin.switch_to_input(pull=digitalio.Pull.UP)
payload3State = not payload3Pin.value payload3State = not payload3Pin.value
payload4Pin = digitalio.DigitalInOut(GP11)
payload4Pin.switch_to_input(pull=digitalio.Pull.UP)
payload4State = not payload4Pin.value payload4State = not payload4Pin.value
if(payload1State == True): if(payload1State == True):
payload = "payload.dd" payload = "payload.dd"
@@ -198,28 +535,132 @@ def selectPayload():
# default to payload1 # default to payload1
payload = "payload.dd" payload = "payload.dd"
return payload return payload
progStatus = False async def blink_led(led):
progStatus = getProgrammingStatus() print("Blink")
if(board.board_id == 'raspberry_pi_pico' or board.board_id == 'raspberry_pi_pico2'):
blink_pico_led(led)
elif(board.board_id == 'raspberry_pi_pico_w' or board.board_id == 'raspberry_pi_pico2_w'):
blink_pico_w_led(led)
if(progStatus == False):
# not in setup mode, inject the payload
payload = selectPayload()
print("Running ", payload)
runScript(payload)
print("Done") async def blink_pico_led(led):
else: print("starting blink_pico_led")
print("Update your payload") led_state = False
while True:
if(variables.get("$_EXFIL_LEDS_ENABLED")):
led.duty_cycle = 65535
else:
if led_state:
#led_pwm_up(led)
#print("led up")
for i in range(100):
# PWM LED up and down
if i < 50:
led.duty_cycle = int(i * 2 * 65535 / 100) # Up
await asyncio.sleep(0.01)
led_state = False
else:
#led_pwm_down(led)
#print("led down")
for i in range(100):
# PWM LED up and down
if i >= 50:
led.duty_cycle = 65535 - int((i - 50) * 2 * 65535 / 100) # Down
await asyncio.sleep(0.01)
led_state = True
await asyncio.sleep(0)
async def blink_pico_w_led(led):
print("starting blink_pico_w_led")
led_state = False
while True:
if(variables.get("$_EXFIL_LEDS_ENABLED")):
led.value = 1
else:
if led_state:
#print("led on")
led.value = 1
await asyncio.sleep(0.5)
led_state = False
else:
#print("led off")
led.value = 0
await asyncio.sleep(0.5)
led_state = True
await asyncio.sleep(0.5)
async def monitor_buttons(button1):
global inBlinkeyMode, inMenu, enableRandomBeep, enableSirenMode,pixel
print("starting monitor_buttons")
button1Down = False
while True:
button1.update()
button1Pushed = button1.fell
button1Released = button1.rose
button1Held = not button1.value
if(button1Pushed):
print("Button 1 pushed")
button1Down = True
if(button1Released):
print("Button 1 released")
if(button1Down):
print("push and released")
if(button1Released):
if(button1Down):
# Run selected payload
payload = selectPayload()
print("Running ", payload)
await runScript(payload)
print("Done")
button1Down = False
await asyncio.sleep(0)
async def monitor_led_changes():
print("starting monitor_led_changes")
while True:
if variables.get("$_EXFIL_MODE_ENABLED"):
try:
bit_list = []
last_caps_state = _capsOn()
last_num_state = _numOn()
last_scroll_state = _scrollOn()
with open("loot.bin", "ab") as file:
while variables.get("$_EXFIL_MODE_ENABLED"):
caps_state = _capsOn()
num_state = _numOn()
scroll_state = _scrollOn()
if caps_state != last_caps_state:
bit_list.append(0)
last_caps_state = caps_state
elif num_state != last_num_state:
bit_list.append(1)
last_num_state = num_state
if len(bit_list) == 8:
byte = 0
for b in bit_list:
byte = (byte << 1) | b
file.write(bytes([byte]))
bit_list = []
if scroll_state != last_scroll_state:
variables["$_EXFIL_LEDS_ENABLED"] = False
break
await asyncio.sleep(0.001)
except Exception as e:
print(f"Error occurred: {e}")
await asyncio.sleep(0.0)
led_state = False
while True:
if led_state:
led_pwm_up(led)
led_state = False
else:
led_pwm_down(led)
led_state = True

13
examples/functions.dd Normal file
View File

@@ -0,0 +1,13 @@
REM Example Function
FUNCTION COUNTDOWN()
REM The next four lines open Notepad in Windows and type "Hello World!"
GUI r
DELAY 1000
STRING notepad
ENTER
DELAY 2000
STRING Hello World!
ENTER
END_FUNCTION
COUNTDOWN()

7
examples/while_loops.dd Normal file
View File

@@ -0,0 +1,7 @@
VAR $TIME = 3
WHILE ($TIME > 0)
STRING .
DELAY 500
STRING While Looop!!
ENTER
END_WHILE

View File

@@ -1,6 +1,6 @@
REM The next four lines open Notepad in Windows and type "Hello World!" REM The next five lines open Notepad in Windows and type "Hello World!"
GUI r GUI r
STRING notepad STRING notepad
ENTER ENTER
DELAY 250 DELAY 250
STRING Hello World! STRING Hello World!

29
pins.py Normal file
View File

@@ -0,0 +1,29 @@
import digitalio
from digitalio import DigitalInOut, Pull
from board import *
from adafruit_debouncer import Debouncer
#init button
button1_pin = DigitalInOut(GP22) # defaults to input
button1_pin.pull = Pull.UP # turn on internal pull-up resistor
button1 = Debouncer(button1_pin)
# payload1 = GPIO4 to GND
# payload2 = GPIO5 to GND
# payload3 = GPIO10 to GND
# payload4 = GPIO11 to GND
#init payload selection switch
payload1Pin = digitalio.DigitalInOut(GP4)
payload1Pin.switch_to_input(pull=digitalio.Pull.UP)
payload2Pin = digitalio.DigitalInOut(GP5)
payload2Pin.switch_to_input(pull=digitalio.Pull.UP)
payload3Pin = digitalio.DigitalInOut(GP10)
payload3Pin.switch_to_input(pull=digitalio.Pull.UP)
payload4Pin = digitalio.DigitalInOut(GP11)
payload4Pin.switch_to_input(pull=digitalio.Pull.UP)
# check GP0 for setup mode
progStatusPin = digitalio.DigitalInOut(GP0)
progStatusPin.switch_to_input(pull=digitalio.Pull.UP)

263
webapp.py Normal file
View File

@@ -0,0 +1,263 @@
# License : GPLv2.0
# copyright (c) 2023 Dave Bailey
# Author: Dave Bailey (dbisu, @daveisu)
# FeatherS2 board support
import socketpool
import time
import os
import storage
import wsgiserver as server
from adafruit_wsgi.wsgi_app import WSGIApp
import wifi
from duckyinpython import *
payload_html = """<html>
<head>
<title>Pico W Ducky</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>button{{margin:0.2em}}html{{font-family:'Open Sans', sans-serif;margin:2%}}table{{width:30%;max-width:20vh;margin-bottom:1em;border-collapse:collapse}}</style>
</head>
<body>
<h1>Pico W Ducky</h1>
<table border="1"><tr><th>Payload</th><th>Actions</th></tr>{}</table><br>
<a href="/new"><button>New Script</button></a>
</body>
</html>
"""
edit_html = """<!DOCTYPE html>
<html>
<head>
<title>Script Editor</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>button{{margin-top:1em}}.main{{font-family:'Open Sans', sans-serif;margin:2%}}textarea{{width:100%;max-width:80vh;margin-bottom:1em;height:50vh}}</style>
</head>
<body>
<form action="/write/{}" method="POST">
<textarea rows="5" name="scriptData">{}</textarea><br/>
<input type="submit" value="submit"/>
</form>
<br>
<a href="/ducky"><button>Home</button></a>
</body>
</html>
"""
new_html = """<!DOCTYPE html>
<html>
<head>
<title>New Script</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>button{margin-top:1em}.main{font-family:'Open Sans', sans-serif;margin:2%}textarea{width:100%;max-width:80vh;margin-bottom:1em}#ducky-input{height:50vh}</style>
</head>
<body>
<div class="main">
<form action="/new" method="POST">
<p>New Script:</p>
<textarea rows="1" name="scriptName" placeholder="script name"></textarea><br>
<textarea id="ducky-input" rows="5" name="scriptData" placeholder="script"></textarea>
<br><input type="submit" value="Submit"/>
</form>
<a href="/ducky"><button>Go Back</button></a>
</div>
</body>
</html>
"""
response_html = """<!DOCTYPE html>
<html>
<head>
<title>Pico W Ducky</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>button{{margin-top:1em}}body{{font-family:'Open Sans', sans-serif;margin:2%}}</style>
</head>
<body>
<h1>Pico W Ducky</h1>
{}
<br><a href="/ducky"><button>Home</button></a>
</body>
</html>
"""
newrow_html = "<tr><td>{}</td><td><a href='/edit/{}'>Edit</a> / <a href='/delete/{}'>Delete</a> / <a href='/run/{}'>Run</a></tr>"
def setPayload(payload_number):
if(payload_number == 1):
payload = "payload.dd"
else:
payload = "payload"+str(payload_number)+".dd"
return(payload)
def ducky_main(request):
print("Ducky main")
payloads = []
rows = ""
files = os.listdir()
#print(files)
for f in files:
if ('.dd' in f) == True:
payloads.append(f)
newrow = newrow_html.format(f,f,f,f)
#print(newrow)
rows = rows + newrow
response = payload_html.format(rows)
return(response)
_hexdig = '0123456789ABCDEFabcdef'
_hextobyte = None
def cleanup_text(string):
"""unquote('abc%20def') -> b'abc def'."""
global _hextobyte
if not string:
return b''
if isinstance(string, str):
string = string.encode('utf-8')
bits = string.split(b'%')
if len(bits) == 1:
return string
res = [bits[0]]
append = res.append
if _hextobyte is None:
_hextobyte = {(a + b).encode(): bytes([int(a + b, 16)])
for a in _hexdig for b in _hexdig}
for item in bits[1:]:
try:
append(_hextobyte[item[:2]])
append(item[2:])
except KeyError:
append(b'%')
append(item)
return b''.join(res).decode().replace('+',' ')
web_app = WSGIApp()
@web_app.route("/ducky")
def duck_main(request):
response = ducky_main(request)
return("200 OK", [('Content-Type', 'text/html')], response)
@web_app.route("/edit/<filename>")
def edit(request, filename):
print("Editing ", filename)
f = open(filename,"r",encoding='utf-8')
textbuffer = ''
for line in f:
textbuffer = textbuffer + line
f.close()
response = edit_html.format(filename,textbuffer)
#print(response)
return("200 OK",[('Content-Type', 'text/html')], response)
@web_app.route("/write/<filename>",methods=["POST"])
def write_script(request, filename):
data = request.body.getvalue()
fields = data.split("&")
form_data = {}
for field in fields:
key,value = field.split('=')
form_data[key] = value
#print(form_data)
storage.remount("/",readonly=False)
f = open(filename,"w",encoding='utf-8')
textbuffer = form_data['scriptData']
textbuffer = cleanup_text(textbuffer)
#print(textbuffer)
for line in textbuffer.splitlines():
f.write(line + '\n')
f.close()
storage.remount("/",readonly=True)
response = response_html.format("Wrote script " + filename)
return("200 OK",[('Content-Type', 'text/html')], response)
@web_app.route("/new",methods=['GET','POST'])
def write_new_script(request):
response = ''
if(request.method == 'GET'):
response = new_html
else:
data = request.body.getvalue()
fields = data.split("&")
form_data = {}
for field in fields:
key,value = field.split('=')
form_data[key] = value
#print(form_data)
filename = form_data['scriptName']
if ".dd" not in filename:
filename = filename + ".dd"
textbuffer = form_data['scriptData']
textbuffer = cleanup_text(textbuffer)
storage.remount("/",readonly=False)
f = open(filename,"w",encoding='utf-8')
for line in textbuffer.splitlines():
f.write(line + '\n')
f.close()
storage.remount("/",readonly=True)
response = response_html.format("Wrote script " + filename)
return("200 OK",[('Content-Type', 'text/html')], response)
@web_app.route("/delete/<filename>")
def delete(request, filename):
print("Deleting ", filename)
storage.remount("/",readonly=False)
os.remove(filename)
response = response_html.format("Deleted script " + filename)
storage.remount("/",readonly=True)
return("200 OK",[('Content-Type', 'text/html')], response)
@web_app.route("/run/<filename>")
def run_script(request, filename):
print("run_script ", filename)
response = response_html.format("Running script " + filename)
#print(response)
runScript(filename)
return("200 OK",[('Content-Type', 'text/html')], response)
@web_app.route("/")
def index(request):
response = ducky_main(request)
return("200 OK", [('Content-Type', 'text/html')], response)
@web_app.route("/api/run/<filenumber>")
def run_script(request, filenumber):
filename = setPayload(int(filenumber))
print("run_script ", filenumber)
response = response_html.format("Running script " + filename)
#print(response)
runScript(filename)
return("200 OK",[('Content-Type', 'text/html')], response)
async def startWebService():
HOST = repr(wifi.radio.ipv4_address_ap)
PORT = 80 # Port to listen on
print(HOST,PORT)
wsgiServer = server.WSGIServer(PORT, application=web_app)
print(f"open this IP in your browser: http://{HOST}:{PORT}/")
# Start the server
wsgiServer.start()
while True:
wsgiServer.update_poll()
await asyncio.sleep(0)

286
wsgiserver.py Executable file
View File

@@ -0,0 +1,286 @@
# SPDX-FileCopyrightText: Copyright (c) 2019 Matt Costi for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""
`adafruit_esp32spi_wsgiserver`
================================================================================
A simple WSGI (Web Server Gateway Interface) server that interfaces with the ESP32 over SPI.
Opens a specified port on the ESP32 to listen for incoming HTTP Requests and
Accepts an Application object that must be callable, which gets called
whenever a new HTTP Request has been received.
The Application MUST accept 2 ordered parameters:
1. environ object (incoming request data)
2. start_response function. Must be called before the Application
callable returns, in order to set the response status and headers.
The Application MUST return a single string in a list,
which is the response data
Requires update_poll being called in the applications main event loop.
For more details about Python WSGI see:
https://www.python.org/dev/peps/pep-0333/
* Author(s): Matt Costi
"""
# pylint: disable=no-name-in-module
import io
import gc
from micropython import const
import socketpool
import wifi
class BadRequestError(Exception):
"""Raised when the client sends an unexpected empty line"""
pass
_BUFFER_SIZE = 32
buffer = bytearray(_BUFFER_SIZE)
def readline(socketin):
"""
Implement readline() for native wifi using recv_into
"""
data_string = b""
while True:
try:
num = socketin.recv_into(buffer, 1)
data_string += str(buffer, 'utf8')[:num]
if num == 0:
return data_string
if data_string[-2:] == b"\r\n":
return data_string[:-2]
except OSError as ex:
# if ex.errno == 9: # [Errno 9] EBADF
# return None
if ex.errno == 11: # [Errno 11] EAGAIN
continue
raise
def read(socketin,length = -1):
total = 0
data_string = b""
try:
if length > 0:
while total < length:
reste = length - total
num = socketin.recv_into(buffer, min(_BUFFER_SIZE, reste))
#
if num == 0:
# timeout
# raise OSError(110)
return data_string
#
data_string += buffer[:num]
total = total + num
return data_string
else:
while True:
num = socketin.recv_into(buffer, 1)
data_string += str(buffer, 'utf8')[:num]
if num == 0:
return data_string
except OSError as ex:
if ex.errno == 11: # [Errno 11] EAGAIN
return data_string
raise
def parse_headers(sock):
"""
Parses the header portion of an HTTP request/response from the socket.
Expects first line of HTTP request/response to have been read already
return: header dictionary
rtype: Dict
"""
headers = {}
while True:
line = readline(sock)
if not line or line == b"\r\n":
break
#print("**line: ", line)
title, content = line.split(b': ', 1)
if title and content:
title = str(title.lower(), 'utf-8')
content = str(content, 'utf-8')
headers[title] = content
return headers
pool = socketpool.SocketPool(wifi.radio)
NO_SOCK_AVAIL = const(255)
# pylint: disable=invalid-name
class WSGIServer:
"""
A simple server that implements the WSGI interface
"""
def __init__(self, port=80, debug=False, application=None):
self.application = application
self.port = port
self._server_sock = None
self._client_sock = None
self._debug = debug
self._response_status = None
self._response_headers = []
def start(self):
"""
starts the server and begins listening for incoming connections.
Call update_poll in the main loop for the application callable to be
invoked on receiving an incoming request.
"""
self._server_sock = pool.socket(pool.AF_INET,pool.SOCK_STREAM)
HOST = repr(wifi.radio.ipv4_address_ap)
self._server_sock.bind((repr(wifi.radio.ipv4_address_ap), self.port))
self._server_sock.listen(1)
# if self._debug:
# ip = _the_interface.pretty_ip(_the_interface.ip_address)
# print("Server available at {0}:{1}".format(ip, self.port))
# print(
# "Sever status: ",
# _the_interface.get_server_state(self._server_sock.socknum),
# )
def pretty_ip(self):
return f"http://{wifi.radio.ipv4_address_ap}:{self.port}"
def update_poll(self):
"""
Call this method inside your main event loop to get the server
check for new incoming client requests. When a request comes in,
the application callable will be invoked.
"""
self.client_available()
if self._client_sock:
try:
environ = self._get_environ(self._client_sock)
result = self.application(environ, self._start_response)
self.finish_response(result)
except BadRequestError:
self._start_response("400 Bad Request", [])
self.finish_response([])
def finish_response(self, result):
"""
Called after the application callbile returns result data to respond with.
Creates the HTTP Response payload from the response_headers and results data,
and sends it back to client.
:param string result: the data string to send back in the response to the client.
"""
try:
response = "HTTP/1.1 {0}\r\n".format(self._response_status)
for header in self._response_headers:
response += "{0}: {1}\r\n".format(*header)
response += "\r\n"
self._client_sock.send(response.encode("utf-8"))
for data in result:
if isinstance(data, str):
data = data.encode("utf-8")
elif not isinstance(data, bytes):
data = str(data).encode("utf-8")
bytes_sent = 0
while bytes_sent < len(data):
try:
bytes_sent += self._client_sock.send(data[bytes_sent:])
except OSError as ex:
if ex.errno != 11: # [Errno 11] EAGAIN
raise
gc.collect()
except OSError as ex:
if ex.errno != 104: # [Errno 104] ECONNRESET
raise
finally:
#print("closing")
self._client_sock.close()
self._client_sock = None
def client_available(self):
"""
returns a client socket connection if available.
Otherwise, returns None
:return: the client
:rtype: Socket
"""
sock = None
if not self._server_sock:
print("Server has not been started, cannot check for clients!")
elif not self._client_sock:
self._server_sock.setblocking(False)
try:
self._client_sock, addr = self._server_sock.accept()
except OSError as ex:
if ex.errno != 11: # [Errno 11] EAGAIN
raise
return None
def _start_response(self, status, response_headers):
"""
The application callable will be given this method as the second param
This is to be called before the application callable returns, to signify
the response can be started with the given status and headers.
:param string status: a status string including the code and reason. ex: "200 OK"
:param list response_headers: a list of tuples to represent the headers.
ex ("header-name", "header value")
"""
self._response_status = status
self._response_headers = [("Server", "esp32WSGIServer")] + response_headers
def _get_environ(self, client):
"""
The application callable will be given the resulting environ dictionary.
It contains metadata about the incoming request and the request body ("wsgi.input")
:param Socket client: socket to read the request from
"""
env = {}
line = readline(client).decode("utf-8")
try:
(method, path, ver) = line.rstrip("\r\n").split(None, 2)
except ValueError:
raise BadRequestError("Unknown request from client.")
env["wsgi.version"] = (1, 0)
env["wsgi.url_scheme"] = "http"
env["wsgi.multithread"] = False
env["wsgi.multiprocess"] = False
env["wsgi.run_once"] = False
env["REQUEST_METHOD"] = method
env["SCRIPT_NAME"] = ""
env["SERVER_NAME"] = str(wifi.radio.ipv4_address_ap)
env["SERVER_PROTOCOL"] = ver
env["SERVER_PORT"] = self.port
if path.find("?") >= 0:
env["PATH_INFO"] = path.split("?")[0]
env["QUERY_STRING"] = path.split("?")[1]
else:
env["PATH_INFO"] = path
headers = parse_headers(client)
if "content-type" in headers:
env["CONTENT_TYPE"] = headers.get("content-type")
if "content-length" in headers:
env["CONTENT_LENGTH"] = headers.get("content-length")
body = read(client, int(env["CONTENT_LENGTH"]))
env["wsgi.input"] = io.StringIO(body)
else:
body = read(client)
env["wsgi.input"] = io.StringIO(body)
for name, value in headers.items():
key = "HTTP_" + name.replace("-", "_").upper()
if key in env:
value = "{0},{1}".format(env[key], value)
env[key] = value
return env