mirror of
https://github.com/scottbez1/smartknob.git
synced 2025-09-26 23:09:27 +08:00
Fab automation (#2)
- Use KiKit for fab automation - Add splitflap scripts for exporting pcb pdfs, and switch to splitflap script for 3d rendering (for consistency with fab automation) - Added support in 3d rendering scripts for soldermask & silkscreen colors, option to skip virtual components - Added silkscreen to base and screen pcbs for commit and date info
This commit is contained in:
parent
8957d8b28e
commit
56feeb484c
57
.github/workflows/electronics.yml
vendored
57
.github/workflows/electronics.yml
vendored
@ -14,13 +14,62 @@ jobs:
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set up outputs directory
|
||||
run: mkdir -p electronics/build
|
||||
run: mkdir -p electronics/build/outputs
|
||||
|
||||
- name: Install dependencies
|
||||
run: ./electronics/scripts/dependencies.sh
|
||||
|
||||
- name: Export JLCPCB fabrication files [view_base]
|
||||
run: |
|
||||
./electronics/scripts/export_jlcpcb.py electronics/view_base/view_base.kicad_pcb
|
||||
cp -r electronics/build/view_base-jlc electronics/build/outputs
|
||||
|
||||
- name: Export PCB overview PDF [view_base]
|
||||
run: |
|
||||
./electronics/scripts/generate_pdf.py electronics/view_base/view_base.kicad_pcb
|
||||
cp electronics/build/view_base-pcb-packet.pdf electronics/build/outputs
|
||||
env:
|
||||
PYTHONUNBUFFERED: 1
|
||||
|
||||
- name: Render PCB 3D [view_base]
|
||||
run: |
|
||||
./electronics/scripts/export_3d.py electronics/view_base/view_base.kicad_pcb --suffix front --width 1280 --height 1280 --skip-virtual --color-soldermask 0.95 0.95 0.95 --color-silk 0.1 0.1 0.1 transform z+ z+
|
||||
cp electronics/build/view_base-front-3d.png electronics/build/outputs
|
||||
./scripts/annotate_image.sh electronics/build/outputs/view_base-front-3d.png
|
||||
./electronics/scripts/export_3d.py electronics/view_base/view_base.kicad_pcb --suffix back --width 1280 --height 1280 --skip-virtual --color-soldermask 0.95 0.95 0.95 --color-silk 0.1 0.1 0.1 transform z+ z+ ry+ ry+ ry+ ry+ ry+ ry+ ry+ ry+ ry+ ry+ ry+ ry+ ry+ ry+ ry+ ry+ ry+ ry+
|
||||
cp electronics/build/view_base-back-3d.png electronics/build/outputs
|
||||
./scripts/annotate_image.sh electronics/build/outputs/view_base-back-3d.png
|
||||
env:
|
||||
PYTHONUNBUFFERED: 1
|
||||
|
||||
- name: Export JLCPCB fabrication files [view_screen]
|
||||
run: |
|
||||
./electronics/scripts/export_jlcpcb.py electronics/view_screen/view_screen.kicad_pcb
|
||||
cp -r electronics/build/view_screen-jlc electronics/build/outputs
|
||||
|
||||
- name: Export PCB overview PDF [view_screen]
|
||||
run: |
|
||||
./electronics/scripts/generate_pdf.py electronics/view_screen/view_screen.kicad_pcb
|
||||
cp electronics/build/view_screen-pcb-packet.pdf electronics/build/outputs
|
||||
env:
|
||||
PYTHONUNBUFFERED: 1
|
||||
|
||||
- name: Render PCB 3D [view_screen]
|
||||
run: |
|
||||
./electronics/scripts/export_3d.py electronics/view_screen/view_screen.kicad_pcb --suffix front --width 1280 --height 1280 --skip-virtual --color-soldermask 0.95 0.95 0.95 --color-silk 0.1 0.1 0.1 transform z+ z+
|
||||
cp electronics/build/view_screen-front-3d.png electronics/build/outputs
|
||||
./scripts/annotate_image.sh electronics/build/outputs/view_screen-front-3d.png
|
||||
./electronics/scripts/export_3d.py electronics/view_screen/view_screen.kicad_pcb --suffix back --width 1280 --height 1280 --skip-virtual --color-soldermask 0.95 0.95 0.95 --color-silk 0.1 0.1 0.1 transform z+ z+ ry+ ry+ ry+ ry+ ry+ ry+ ry+ ry+ ry+ ry+ ry+ ry+ ry+ ry+ ry+ ry+ ry+ ry+
|
||||
cp electronics/build/view_screen-back-3d.png electronics/build/outputs
|
||||
./scripts/annotate_image.sh electronics/build/outputs/view_screen-back-3d.png
|
||||
env:
|
||||
PYTHONUNBUFFERED: 1
|
||||
|
||||
- name: Export artifacts (KiBot) [view_base]
|
||||
uses: INTI-CMNB/KiBot@fb6d637c17fbba2daf005a9a7972e4c02c1c997c
|
||||
with:
|
||||
config: electronics/view_base/view_base.kibot.yml
|
||||
dir: electronics/build
|
||||
dir: electronics/build/outputs
|
||||
schema: 'electronics/view_base/view_base.sch'
|
||||
board: 'electronics/view_base/view_base.kicad_pcb'
|
||||
|
||||
@ -28,7 +77,7 @@ jobs:
|
||||
uses: INTI-CMNB/KiBot@fb6d637c17fbba2daf005a9a7972e4c02c1c997c
|
||||
with:
|
||||
config: electronics/view_screen/view_screen.kibot.yml
|
||||
dir: electronics/build
|
||||
dir: electronics/build/outputs
|
||||
schema: 'electronics/view_screen/view_screen.sch'
|
||||
board: 'electronics/view_screen/view_screen.kicad_pcb'
|
||||
|
||||
@ -51,5 +100,5 @@ jobs:
|
||||
- name: Sync artifacts to S3
|
||||
if: github.event_name == 'push' && github.repository_owner == 'scottbez1'
|
||||
run: |
|
||||
aws s3 sync electronics/build s3://smartknob-artifacts/${GITHUB_REF#refs/heads/}/electronics --delete --cache-control max-age=0,no-cache
|
||||
aws s3 sync electronics/build/outputs s3://smartknob-artifacts/${GITHUB_REF#refs/heads/}/electronics --delete --cache-control max-age=0,no-cache
|
||||
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -27,3 +27,5 @@ build/
|
||||
!.vscode/extensions.json
|
||||
!.vscode/*.code-snippets
|
||||
|
||||
__pycache__
|
||||
|
||||
|
23
README.md
23
README.md
@ -13,11 +13,11 @@ Premium SmartKnob experience. Under active development. Untested & unproven.
|
||||
|
||||
#### Base PCB
|
||||
|
||||
<a href="https://smartknob-artifacts.s3.us-west-1.amazonaws.com/master/electronics/view_base-3D_top.png">
|
||||
<img src="https://smartknob-artifacts.s3.us-west-1.amazonaws.com/master/electronics/view_base-3D_top.png" width="300" />
|
||||
<a href="https://smartknob-artifacts.s3.us-west-1.amazonaws.com/master/electronics/view_base-front-3d.png">
|
||||
<img src="https://smartknob-artifacts.s3.us-west-1.amazonaws.com/master/electronics/view_base-front-3d.png" width="300" />
|
||||
</a>
|
||||
<a href="https://smartknob-artifacts.s3.us-west-1.amazonaws.com/master/electronics/view_base-3D_bottom.png">
|
||||
<img src="https://smartknob-artifacts.s3.us-west-1.amazonaws.com/master/electronics/view_base-3D_bottom.png" width="300" />
|
||||
<a href="https://smartknob-artifacts.s3.us-west-1.amazonaws.com/master/electronics/view_base-back-3d.png">
|
||||
<img src="https://smartknob-artifacts.s3.us-west-1.amazonaws.com/master/electronics/view_base-back-3d.png" width="300" />
|
||||
</a>
|
||||
|
||||
|
||||
@ -25,13 +25,17 @@ Premium SmartKnob experience. Under active development. Untested & unproven.
|
||||
|
||||
[Interactive BOM](https://smartknob-artifacts.s3.us-west-1.amazonaws.com/master/electronics/view_base-ibom.html)
|
||||
|
||||
[PCB Packet](https://smartknob-artifacts.s3.us-west-1.amazonaws.com/master/electronics/view_base-pcb-packet.pdf)
|
||||
|
||||
[Gerbers](https://smartknob-artifacts.s3.us-west-1.amazonaws.com/master/electronics/view_base-jlc/gerbers.zip)
|
||||
|
||||
#### Screen PCB
|
||||
|
||||
<a href="https://smartknob-artifacts.s3.us-west-1.amazonaws.com/master/electronics/view_screen-3D_top.png">
|
||||
<img src="https://smartknob-artifacts.s3.us-west-1.amazonaws.com/master/electronics/view_screen-3D_top.png" width="300" />
|
||||
<a href="https://smartknob-artifacts.s3.us-west-1.amazonaws.com/master/electronics/view_screen-front-3d.png">
|
||||
<img src="https://smartknob-artifacts.s3.us-west-1.amazonaws.com/master/electronics/view_screen-front-3d.png" width="300" />
|
||||
</a>
|
||||
<a href="https://smartknob-artifacts.s3.us-west-1.amazonaws.com/master/electronics/view_screen-3D_bottom.png">
|
||||
<img src="https://smartknob-artifacts.s3.us-west-1.amazonaws.com/master/electronics/view_screen-3D_bottom.png" width="300" />
|
||||
<a href="https://smartknob-artifacts.s3.us-west-1.amazonaws.com/master/electronics/view_screen-back-3d.png">
|
||||
<img src="https://smartknob-artifacts.s3.us-west-1.amazonaws.com/master/electronics/view_screen-back-3d.png" width="300" />
|
||||
</a>
|
||||
|
||||
|
||||
@ -39,6 +43,9 @@ Premium SmartKnob experience. Under active development. Untested & unproven.
|
||||
|
||||
[Interactive BOM](https://smartknob-artifacts.s3.us-west-1.amazonaws.com/master/electronics/view_screen-ibom.html)
|
||||
|
||||
[PCB Packet](https://smartknob-artifacts.s3.us-west-1.amazonaws.com/master/electronics/view_screen-pcb-packet.pdf)
|
||||
|
||||
[Gerbers](https://smartknob-artifacts.s3.us-west-1.amazonaws.com/master/electronics/view_screen-jlc/gerbers.zip)
|
||||
|
||||
### SmartKnob Handheld
|
||||
An exploration of a small handheld form-factor. Under active development.
|
||||
|
0
__init__.py
Normal file
0
__init__.py
Normal file
0
electronics/scripts/__init__.py
Normal file
0
electronics/scripts/__init__.py
Normal file
87
electronics/scripts/config/eeschema
Normal file
87
electronics/scripts/config/eeschema
Normal file
@ -0,0 +1,87 @@
|
||||
SchematicFramePos_x=89
|
||||
SchematicFramePos_y=38
|
||||
SchematicFrameSize_x=1125
|
||||
SchematicFrameSize_y=739
|
||||
SchematicFrameMaximized=0
|
||||
SchematicFrameAutoSaveInterval=600
|
||||
SchematicFramePerspective=layout2|name=MainToolbar;caption=;state=139644;dir=1;layer=6;row=0;pos=0;prop=100000;bestw=1016;besth=36;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=OptToolbar;caption=;state=139596;dir=4;layer=3;row=0;pos=0;prop=100000;bestw=36;besth=212;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=ToolsToolbar;caption=;state=139596;dir=2;layer=1;row=0;pos=0;prop=100000;bestw=36;besth=688;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=DrawFrame;caption=;state=1020;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=387;besth=181;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=MsgPanel;caption=;state=131452;dir=3;layer=6;row=0;pos=0;prop=100000;bestw=400;besth=34;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|dock_size(1,6,0)=36|dock_size(4,3,0)=36|dock_size(2,1,0)=36|dock_size(5,0,0)=337|dock_size(3,6,0)=34|
|
||||
SchematicFrameMostRecentlyUsedPath=
|
||||
SchematicFrameUnits=1
|
||||
SchematicFrameShowGrid=1
|
||||
SchematicFrame_LastGridSize=5
|
||||
SchematicFrameFirstRunShown=0
|
||||
SchematicFrameDevelMaxUndoItems=0
|
||||
SchematicFrameGalDisplayOptionsGridStyle=0
|
||||
SchematicFrameGalDisplayOptionsGridLineWidth=1
|
||||
SchematicFrameGalDisplayOptionsGridMaxDensity=10
|
||||
SchematicFrameGalDisplayOptionsGridAxesEnabled=0
|
||||
SchematicFrameGalDisplayOptionsCursorFullscreen=0
|
||||
SchematicFrameGalDisplayOptionsForceDisplayCursor=1
|
||||
ShowPageLimits=1
|
||||
Units=1
|
||||
PrintMonochrome=1
|
||||
PrintSheetReferenceAndTitleBlock=1
|
||||
RepeatStepX=0
|
||||
RepeatStepY=100
|
||||
RepeatLabelIncrement=1
|
||||
ShowIllegalSymbolLibDialog=1
|
||||
ShowSheetFileNameCaseSensitivityDlg=1
|
||||
DefaultBusWidth=12
|
||||
DefaultWireWidth=6
|
||||
DefaultJunctionSize=40
|
||||
ShowHiddenPins=0
|
||||
HorizVertLinesOnly=1
|
||||
AutoplaceFields=1
|
||||
AutoplaceJustify=1
|
||||
AutoplaceAlign=0
|
||||
FootprintPreview=0
|
||||
SimCmdLine=
|
||||
LastFindReplaceFlags=1
|
||||
LastFindString=
|
||||
LastReplaceString=
|
||||
FieldNames=(templatefields)
|
||||
canvas_type=2
|
||||
Color4DWireEx=rgb(0, 132, 0)
|
||||
Color4DBusEx=rgb(0, 0, 132)
|
||||
Color4DConnEx=rgb(0, 132, 0)
|
||||
Color4DLLabelEx=rgb(0, 0, 0)
|
||||
Color4DHLabelEx=rgb(132, 132, 0)
|
||||
Color4DGLabelEx=rgb(132, 0, 0)
|
||||
Color4DPinNumEx=rgb(132, 0, 0)
|
||||
Color4DPinNameEx=rgb(0, 132, 132)
|
||||
Color4DFieldEx=rgb(132, 0, 132)
|
||||
Color4DReferenceEx=rgb(0, 132, 132)
|
||||
Color4DValueEx=rgb(0, 132, 132)
|
||||
Color4DNoteEx=rgb(0, 0, 194)
|
||||
Color4DBodyEx=rgb(132, 0, 0)
|
||||
Color4DBodyBgEx=rgb(255, 255, 194)
|
||||
Color4DNetNameEx=rgb(132, 132, 132)
|
||||
Color4DPinEx=rgb(132, 0, 0)
|
||||
Color4DSheetEx=rgb(132, 0, 132)
|
||||
Color4DSheetFileNameEx=rgb(132, 132, 0)
|
||||
Color4DSheetNameEx=rgb(0, 132, 132)
|
||||
Color4DSheetLabelEx=rgb(132, 132, 0)
|
||||
Color4DNoConnectEx=rgb(0, 0, 132)
|
||||
Color4DErcWEx=rgba(0, 132, 0, 0.800)
|
||||
Color4DErcEEx=rgba(132, 0, 0, 0.800)
|
||||
Color4DGridEx=rgb(132, 132, 132)
|
||||
Color4DBgCanvasEx=rgb(255, 255, 255)
|
||||
Color4DCursorEx=rgb(0, 0, 0)
|
||||
Color4DBrightenedEx=rgb(255, 0, 255)
|
||||
Color4DHiddenEx=rgb(194, 194, 194)
|
||||
Color4DWorksheetEx=rgb(132, 0, 0)
|
||||
file1=
|
||||
file2=
|
||||
file3=
|
||||
file4=
|
||||
file5=
|
||||
file6=
|
||||
file7=
|
||||
file8=
|
||||
file9=
|
||||
PlotModeColor=1
|
||||
PlotFrameRef=1
|
||||
PlotFormat=3
|
||||
PlotHPGLOrg=0
|
||||
PlotHPGLPaperSize=0
|
||||
PlotHPGLPenSize=0.4826
|
556
electronics/scripts/config/pcbnew
Normal file
556
electronics/scripts/config/pcbnew
Normal file
@ -0,0 +1,556 @@
|
||||
Color4DPCBLayer_F.Cu=rgb(132, 0, 0)
|
||||
Color4DPCBLayer_In1.Cu=rgb(194, 194, 0)
|
||||
Color4DPCBLayer_In2.Cu=rgb(194, 0, 194)
|
||||
Color4DPCBLayer_In3.Cu=rgb(194, 0, 0)
|
||||
Color4DPCBLayer_In4.Cu=rgb(0, 132, 132)
|
||||
Color4DPCBLayer_In5.Cu=rgb(0, 132, 0)
|
||||
Color4DPCBLayer_In6.Cu=rgb(0, 0, 132)
|
||||
Color4DPCBLayer_In7.Cu=rgb(132, 132, 132)
|
||||
Color4DPCBLayer_In8.Cu=rgb(132, 0, 132)
|
||||
Color4DPCBLayer_In9.Cu=rgb(194, 194, 194)
|
||||
Color4DPCBLayer_In10.Cu=rgb(132, 0, 132)
|
||||
Color4DPCBLayer_In11.Cu=rgb(132, 0, 0)
|
||||
Color4DPCBLayer_In12.Cu=rgb(132, 132, 0)
|
||||
Color4DPCBLayer_In13.Cu=rgb(194, 194, 194)
|
||||
Color4DPCBLayer_In14.Cu=rgb(0, 0, 132)
|
||||
Color4DPCBLayer_In15.Cu=rgb(0, 132, 0)
|
||||
Color4DPCBLayer_In16.Cu=rgb(132, 0, 0)
|
||||
Color4DPCBLayer_In17.Cu=rgb(194, 194, 0)
|
||||
Color4DPCBLayer_In18.Cu=rgb(194, 0, 194)
|
||||
Color4DPCBLayer_In19.Cu=rgb(194, 0, 0)
|
||||
Color4DPCBLayer_In20.Cu=rgb(0, 132, 132)
|
||||
Color4DPCBLayer_In21.Cu=rgb(0, 132, 0)
|
||||
Color4DPCBLayer_In22.Cu=rgb(0, 0, 132)
|
||||
Color4DPCBLayer_In23.Cu=rgb(132, 132, 132)
|
||||
Color4DPCBLayer_In24.Cu=rgb(132, 0, 132)
|
||||
Color4DPCBLayer_In25.Cu=rgb(194, 194, 194)
|
||||
Color4DPCBLayer_In26.Cu=rgb(132, 0, 132)
|
||||
Color4DPCBLayer_In27.Cu=rgb(132, 0, 0)
|
||||
Color4DPCBLayer_In28.Cu=rgb(132, 132, 0)
|
||||
Color4DPCBLayer_In29.Cu=rgb(194, 194, 194)
|
||||
Color4DPCBLayer_In30.Cu=rgb(0, 0, 132)
|
||||
Color4DPCBLayer_B.Cu=rgba(0, 132, 0, 0.439)
|
||||
Color4DPCBLayer_B.Adhes=rgb(0, 0, 132)
|
||||
Color4DPCBLayer_F.Adhes=rgb(132, 0, 132)
|
||||
Color4DPCBLayer_B.Paste=rgb(0, 194, 194)
|
||||
Color4DPCBLayer_F.Paste=rgb(132, 0, 0)
|
||||
Color4DPCBLayer_B.SilkS=rgb(132, 0, 132)
|
||||
Color4DPCBLayer_F.SilkS=rgb(0, 132, 132)
|
||||
Color4DPCBLayer_B.Mask=rgb(132, 132, 0)
|
||||
Color4DPCBLayer_F.Mask=rgb(132, 0, 132)
|
||||
Color4DPCBLayer_Dwgs.User=rgb(194, 194, 194)
|
||||
Color4DPCBLayer_Cmts.User=rgb(0, 0, 132)
|
||||
Color4DPCBLayer_Eco1.User=rgb(0, 132, 0)
|
||||
Color4DPCBLayer_Eco2.User=rgb(194, 194, 0)
|
||||
Color4DPCBLayer_Edge.Cuts=rgb(194, 194, 0)
|
||||
Color4DPCBLayer_Margin=rgb(194, 0, 194)
|
||||
Color4DPCBLayer_B.CrtYd=rgb(132, 132, 132)
|
||||
Color4DPCBLayer_F.CrtYd=rgb(194, 194, 194)
|
||||
Color4DPCBLayer_B.Fab=rgb(0, 0, 132)
|
||||
Color4DPCBLayer_F.Fab=rgb(132, 132, 132)
|
||||
Color4DTxtFrontEx=rgb(194, 194, 194)
|
||||
Color4DTxtBackEx=rgb(0, 0, 132)
|
||||
Color4DTxtInvisEx=rgb(132, 132, 132)
|
||||
Color4DPadBackEx=rgb(0, 132, 0)
|
||||
Color4DAnchorEx=rgb(0, 0, 132)
|
||||
Color4DPadFrontEx=rgb(132, 0, 0)
|
||||
Color4DPadThruHoleEx=rgb(194, 194, 0)
|
||||
Color4DNonPlatedEx=rgb(194, 194, 0)
|
||||
Color4DPCBBackground=rgb(0, 0, 0)
|
||||
Color4DPCBCursor=rgb(255, 255, 255)
|
||||
Color4DAuxItems=rgb(255, 255, 255)
|
||||
Color4DWorksheet=rgb(72, 0, 0)
|
||||
Color4DGrid=rgb(132, 132, 132)
|
||||
Color4DViaThruEx=rgb(194, 194, 194)
|
||||
Color4DViaBBlindEx=rgb(132, 132, 0)
|
||||
Color4DViaMicroEx=rgb(0, 132, 132)
|
||||
Color4DRatsEx=rgb(255, 255, 255)
|
||||
Color4DNoNetPadMarker=rgb(0, 0, 132)
|
||||
LegacyAutoDeleteOldTrack=1
|
||||
LegacyUse45DegreeTracks=1
|
||||
LegacyUseTwoSegmentTracks=1
|
||||
Use45DegreeGraphicSegments=0
|
||||
MagneticPads=2
|
||||
MagneticTracks=1
|
||||
EditActionChangesTrackWidth=0
|
||||
DragSelects=1
|
||||
PcbFramePos_x=72
|
||||
PcbFramePos_y=27
|
||||
PcbFrameSize_x=2488
|
||||
PcbFrameSize_y=1413
|
||||
PcbFrameMaximized=1
|
||||
PcbFrameAutoSaveInterval=600
|
||||
PcbFramePerspective=layout2|name=MainToolbar;caption=;state=139644;dir=1;layer=6;row=0;pos=0;prop=100000;bestw=956;besth=38;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=AuxToolbar;caption=;state=139644;dir=1;layer=4;row=0;pos=0;prop=100000;bestw=995;besth=38;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=MsgPanel;caption=;state=131452;dir=3;layer=6;row=0;pos=0;prop=100000;bestw=400;besth=34;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=OptToolbar;caption=;state=139596;dir=4;layer=3;row=0;pos=0;prop=100000;bestw=36;besth=597;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=MicrowaveToolbar;caption=;state=139598;dir=2;layer=1;row=0;pos=0;prop=100000;bestw=36;besth=187;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=ToolsToolbar;caption=;state=139596;dir=2;layer=2;row=0;pos=0;prop=100000;bestw=36;besth=708;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=LayersManager;caption=Layers Manager;state=1532;dir=2;layer=3;row=0;pos=0;prop=100000;bestw=198;besth=32;minw=198;minh=32;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=198;floath=32|name=DrawFrame;caption=;state=1022;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=387;besth=181;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=DrawFrameGal;caption=;state=1020;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=1112;besth=731;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|dock_size(1,6,0)=38|dock_size(1,4,0)=38|dock_size(3,6,0)=34|dock_size(4,3,0)=36|dock_size(2,2,0)=36|dock_size(2,3,0)=198|dock_size(5,0,0)=389|
|
||||
PcbFrameMostRecentlyUsedPath=
|
||||
PcbFrameShowGrid=1
|
||||
PcbFrameGridColor=rgb(132, 132, 132)
|
||||
PcbFrame_LastGridSize=2
|
||||
PcbFrameFirstRunShown=1
|
||||
PcbFrameDevelMaxUndoItems=0
|
||||
PcbFrameGalDisplayOptionsOpenGLAntialiasingMode=0
|
||||
PcbFrameGalDisplayOptionsGridStyle=0
|
||||
PcbFrameGalDisplayOptionsGridLineWidth=1
|
||||
PcbFrameGalDisplayOptionsGridMaxDensity=10
|
||||
PcbFrameGalDisplayOptionsGridAxesEnabled=0
|
||||
PcbFrameGalDisplayOptionsCursorFullscreen=0
|
||||
PcbFrameGalDisplayOptionsForceDisplayCursor=0
|
||||
PcbFramePcbUserGrid_X=0.254
|
||||
PcbFramePcbUserGrid_Y=0.254
|
||||
PcbFramePcbUserGrid_Unit=1
|
||||
PcbFrameDiPadFi=1
|
||||
PcbFrameDiViaFi=1
|
||||
PcbFrameDiPadNu=1
|
||||
PcbFrameDiModEd=1
|
||||
PcbFrameDiModTx=1
|
||||
PcbFrameFastGrid1=0
|
||||
PcbFrameFastGrid2=0
|
||||
Units=1
|
||||
DisplayPolarCoords=0
|
||||
ShowNetNamesMode=3
|
||||
DisplayTrackFilled=1
|
||||
TrackDisplayClearance=2
|
||||
PadFill=1
|
||||
ViaFill=1
|
||||
PadAffG=1
|
||||
PadSNum=1
|
||||
ModAffC=1
|
||||
ModAffT=1
|
||||
PcbAffT=1
|
||||
PcbShowZonesMode=0
|
||||
RotationAngle=900
|
||||
MaxLnkS=3
|
||||
PlotLineWidth_mm=0.1
|
||||
ShowMicrowaveTools=0
|
||||
ShowLayerManagerTools=1
|
||||
ShowPageLimits=0
|
||||
canvas_type=1
|
||||
pcbnew.InteractiveRouter.Mode=1
|
||||
pcbnew.InteractiveRouter.OptimizerEffort=1
|
||||
pcbnew.InteractiveRouter.RemoveLoops=1
|
||||
pcbnew.InteractiveRouter.SmartPads=1
|
||||
pcbnew.InteractiveRouter.ShoveVias=1
|
||||
pcbnew.InteractiveRouter.StartDiagonal=0
|
||||
pcbnew.InteractiveRouter.ShoveTimeLimit=1000
|
||||
pcbnew.InteractiveRouter.ShoveIterationLimit=250
|
||||
pcbnew.InteractiveRouter.WalkaroundIterationLimit=50
|
||||
pcbnew.InteractiveRouter.JumpOverObstacles=0
|
||||
pcbnew.InteractiveRouter.SmoothDraggedSegments=1
|
||||
pcbnew.InteractiveRouter.CanViolateDRC=0
|
||||
pcbnew.InteractiveRouter.SuggestFinish=0
|
||||
pcbnew.InteractiveRouter.FreeAngleMode=0
|
||||
pcbnew.InteractiveRouter.InlineDragEnabled=0
|
||||
MousewheelPAN=0
|
||||
ZoomNoCenter=0
|
||||
AutoPAN=1
|
||||
file1=
|
||||
file2=
|
||||
file3=
|
||||
file4=
|
||||
file5=
|
||||
file6=
|
||||
file7=
|
||||
file8=
|
||||
file9=
|
||||
PcbFrameCursorShape=0
|
||||
PcbFrameMaxUndoItems=0
|
||||
ViaHoleDisplayMode=1
|
||||
ColorPCBLayer_F.Cu=Red 2
|
||||
ColorPCBLayer_In1.Cu=Yellow 3
|
||||
ColorPCBLayer_In2.Cu=Magenta 3
|
||||
ColorPCBLayer_In3.Cu=Red 3
|
||||
ColorPCBLayer_In4.Cu=Cyan 2
|
||||
ColorPCBLayer_In5.Cu=Green 2
|
||||
ColorPCBLayer_In6.Cu=Blue 2
|
||||
ColorPCBLayer_In7.Cu=Gray 2
|
||||
ColorPCBLayer_In8.Cu=Magenta 2
|
||||
ColorPCBLayer_In9.Cu=Gray 3
|
||||
ColorPCBLayer_In10.Cu=Magenta 2
|
||||
ColorPCBLayer_In11.Cu=Red 2
|
||||
ColorPCBLayer_In12.Cu=Brown 2
|
||||
ColorPCBLayer_In13.Cu=Gray 3
|
||||
ColorPCBLayer_In14.Cu=Blue 2
|
||||
ColorPCBLayer_In15.Cu=Green 2
|
||||
ColorPCBLayer_In16.Cu=Red 2
|
||||
ColorPCBLayer_In17.Cu=Yellow 3
|
||||
ColorPCBLayer_In18.Cu=Magenta 3
|
||||
ColorPCBLayer_In19.Cu=Red 3
|
||||
ColorPCBLayer_In20.Cu=Cyan 2
|
||||
ColorPCBLayer_In21.Cu=Green 2
|
||||
ColorPCBLayer_In22.Cu=Blue 2
|
||||
ColorPCBLayer_In23.Cu=Gray 2
|
||||
ColorPCBLayer_In24.Cu=Magenta 2
|
||||
ColorPCBLayer_In25.Cu=Gray 3
|
||||
ColorPCBLayer_In26.Cu=Magenta 2
|
||||
ColorPCBLayer_In27.Cu=Red 2
|
||||
ColorPCBLayer_In28.Cu=Brown 2
|
||||
ColorPCBLayer_In29.Cu=Gray 3
|
||||
ColorPCBLayer_In30.Cu=Blue 2
|
||||
ColorPCBLayer_B.Cu=Green 2
|
||||
ColorPCBLayer_B.Adhes=Blue 2
|
||||
ColorPCBLayer_F.Adhes=Magenta 2
|
||||
ColorPCBLayer_B.Paste=Cyan 3
|
||||
ColorPCBLayer_F.Paste=Red 2
|
||||
ColorPCBLayer_B.SilkS=Magenta 2
|
||||
ColorPCBLayer_F.SilkS=Cyan 2
|
||||
ColorPCBLayer_B.Mask=Brown 2
|
||||
ColorPCBLayer_F.Mask=Magenta 2
|
||||
ColorPCBLayer_Dwgs.User=Gray 3
|
||||
ColorPCBLayer_Cmts.User=Blue 2
|
||||
ColorPCBLayer_Eco1.User=Green 2
|
||||
ColorPCBLayer_Eco2.User=Yellow 3
|
||||
ColorPCBLayer_Edge.Cuts=Yellow 3
|
||||
ColorPCBLayer_Margin=Magenta 3
|
||||
ColorPCBLayer_B.CrtYd=Yellow 3
|
||||
ColorPCBLayer_F.CrtYd=Gray 2
|
||||
ColorPCBLayer_B.Fab=Red 2
|
||||
ColorPCBLayer_F.Fab=Yellow 3
|
||||
ColorTxtFrontEx=Gray 3
|
||||
ColorTxtBackEx=Blue 2
|
||||
ColorTxtInvisEx=Gray 2
|
||||
ColorAnchorEx=Blue 2
|
||||
ColorPadBackEx=Green 2
|
||||
ColorPadFrontEx=Red 2
|
||||
ColorViaThruEx=Gray 3
|
||||
ColorViaBBlindEx=Brown 2
|
||||
ColorViaMicroEx=Cyan 2
|
||||
ColorNonPlatedEx=Yellow 3
|
||||
ColorRatsEx=White
|
||||
ShowMRa=1
|
||||
TwoSegT=1
|
||||
SegmPcb45Only=1
|
||||
PcbMagPadOpt=1
|
||||
PcbMagTrackOpt=1
|
||||
MiddleButtonPAN=1
|
||||
MiddleBtnPANLimited=0
|
||||
FootprintWizardPos_x=384
|
||||
FootprintWizardPos_y=514
|
||||
FootprintWizardSize_x=2272
|
||||
FootprintWizardSize_y=1000
|
||||
FootprintWizardMaximized=0
|
||||
FootprintWizardPerspective=layout2|name=m_mainToolBar;caption=;state=139632;dir=1;layer=10;row=0;pos=0;prop=100000;bestw=393;besth=36;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=m_parametersPanel;caption=;state=508;dir=4;layer=0;row=0;pos=0;prop=100000;bestw=20;besth=20;minw=360;minh=180;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=m_buildMessageBox;caption=;state=508;dir=4;layer=0;row=0;pos=1;prop=100000;bestw=104;besth=73;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=DrawFrame;caption=;state=256;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=382;besth=63;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=MsgPanel;caption=;state=131388;dir=3;layer=1;row=0;pos=0;prop=100000;bestw=400;besth=68;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|dock_size(1,10,0)=36|dock_size(4,0,0)=513|dock_size(5,0,0)=300|dock_size(3,1,0)=68|
|
||||
FootprintWizardMostRecentlyUsedPath=
|
||||
FootprintWizardShowGrid=1
|
||||
FootprintWizardGridColor=rgb(132, 132, 132)
|
||||
FootprintWizard_LastGridSize=0
|
||||
FootprintWizardFirstRunShown=0
|
||||
FootprintWizardDevelMaxUndoItems=0
|
||||
FootprintWizardGalDisplayOptionsOpenGLAntialiasingMode=0
|
||||
FootprintWizardGalDisplayOptionsGridStyle=0
|
||||
FootprintWizardGalDisplayOptionsGridLineWidth=0.5
|
||||
FootprintWizardGalDisplayOptionsGridMaxDensity=10
|
||||
FootprintWizardGalDisplayOptionsGridAxesEnabled=0
|
||||
FootprintWizardGalDisplayOptionsCursorFullscreen=0
|
||||
FootprintWizardGalDisplayOptionsForceDisplayCursor=0
|
||||
Fpwizard_auiPerspective=layout2|name=m_mainToolBar;caption=;state=139632;dir=1;layer=10;row=0;pos=0;prop=100000;bestw=393;besth=36;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=m_parametersPanel;caption=;state=508;dir=4;layer=0;row=0;pos=0;prop=100000;bestw=20;besth=20;minw=360;minh=180;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=m_buildMessageBox;caption=;state=508;dir=4;layer=0;row=0;pos=1;prop=100000;bestw=104;besth=73;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=DrawFrame;caption=;state=256;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=382;besth=63;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=MsgPanel;caption=;state=131388;dir=3;layer=1;row=0;pos=0;prop=100000;bestw=400;besth=68;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|dock_size(1,10,0)=36|dock_size(4,0,0)=513|dock_size(5,0,0)=300|dock_size(3,1,0)=68|
|
||||
ModEditColor4DPCBLayer_F.Cu=rgb(132, 0, 0)
|
||||
ModEditColor4DPCBLayer_In1.Cu=rgb(194, 194, 0)
|
||||
ModEditColor4DPCBLayer_In2.Cu=rgb(194, 0, 194)
|
||||
ModEditColor4DPCBLayer_In3.Cu=rgb(194, 0, 0)
|
||||
ModEditColor4DPCBLayer_In4.Cu=rgb(0, 132, 132)
|
||||
ModEditColor4DPCBLayer_In5.Cu=rgb(0, 132, 0)
|
||||
ModEditColor4DPCBLayer_In6.Cu=rgb(0, 0, 132)
|
||||
ModEditColor4DPCBLayer_In7.Cu=rgb(132, 132, 132)
|
||||
ModEditColor4DPCBLayer_In8.Cu=rgb(132, 0, 132)
|
||||
ModEditColor4DPCBLayer_In9.Cu=rgb(194, 194, 194)
|
||||
ModEditColor4DPCBLayer_In10.Cu=rgb(132, 0, 132)
|
||||
ModEditColor4DPCBLayer_In11.Cu=rgb(132, 0, 0)
|
||||
ModEditColor4DPCBLayer_In12.Cu=rgb(132, 132, 0)
|
||||
ModEditColor4DPCBLayer_In13.Cu=rgb(194, 194, 194)
|
||||
ModEditColor4DPCBLayer_In14.Cu=rgb(0, 0, 132)
|
||||
ModEditColor4DPCBLayer_In15.Cu=rgb(0, 132, 0)
|
||||
ModEditColor4DPCBLayer_In16.Cu=rgb(132, 0, 0)
|
||||
ModEditColor4DPCBLayer_In17.Cu=rgb(194, 194, 0)
|
||||
ModEditColor4DPCBLayer_In18.Cu=rgb(194, 0, 194)
|
||||
ModEditColor4DPCBLayer_In19.Cu=rgb(194, 0, 0)
|
||||
ModEditColor4DPCBLayer_In20.Cu=rgb(0, 132, 132)
|
||||
ModEditColor4DPCBLayer_In21.Cu=rgb(0, 132, 0)
|
||||
ModEditColor4DPCBLayer_In22.Cu=rgb(0, 0, 132)
|
||||
ModEditColor4DPCBLayer_In23.Cu=rgb(132, 132, 132)
|
||||
ModEditColor4DPCBLayer_In24.Cu=rgb(132, 0, 132)
|
||||
ModEditColor4DPCBLayer_In25.Cu=rgb(194, 194, 194)
|
||||
ModEditColor4DPCBLayer_In26.Cu=rgb(132, 0, 132)
|
||||
ModEditColor4DPCBLayer_In27.Cu=rgb(132, 0, 0)
|
||||
ModEditColor4DPCBLayer_In28.Cu=rgb(132, 132, 0)
|
||||
ModEditColor4DPCBLayer_In29.Cu=rgb(194, 194, 194)
|
||||
ModEditColor4DPCBLayer_In30.Cu=rgb(0, 0, 132)
|
||||
ModEditColor4DPCBLayer_B.Cu=rgb(0, 132, 0)
|
||||
ModEditColor4DPCBLayer_B.Adhes=rgb(0, 0, 132)
|
||||
ModEditColor4DPCBLayer_F.Adhes=rgb(132, 0, 132)
|
||||
ModEditColor4DPCBLayer_B.Paste=rgb(0, 194, 194)
|
||||
ModEditColor4DPCBLayer_F.Paste=rgb(132, 0, 0)
|
||||
ModEditColor4DPCBLayer_B.SilkS=rgb(132, 0, 132)
|
||||
ModEditColor4DPCBLayer_F.SilkS=rgb(0, 132, 132)
|
||||
ModEditColor4DPCBLayer_B.Mask=rgb(132, 132, 0)
|
||||
ModEditColor4DPCBLayer_F.Mask=rgb(132, 0, 132)
|
||||
ModEditColor4DPCBLayer_Dwgs.User=rgb(194, 194, 194)
|
||||
ModEditColor4DPCBLayer_Cmts.User=rgb(0, 0, 132)
|
||||
ModEditColor4DPCBLayer_Eco1.User=rgb(0, 132, 0)
|
||||
ModEditColor4DPCBLayer_Eco2.User=rgb(194, 194, 0)
|
||||
ModEditColor4DPCBLayer_Edge.Cuts=rgb(194, 194, 0)
|
||||
ModEditColor4DPCBLayer_Margin=rgb(194, 0, 194)
|
||||
ModEditColor4DPCBLayer_B.CrtYd=rgb(132, 132, 132)
|
||||
ModEditColor4DPCBLayer_F.CrtYd=rgb(194, 194, 194)
|
||||
ModEditColor4DPCBLayer_B.Fab=rgb(0, 0, 132)
|
||||
ModEditColor4DPCBLayer_F.Fab=rgb(132, 132, 132)
|
||||
ModEditColor4DTxtFrontEx=rgb(194, 194, 194)
|
||||
ModEditColor4DTxtBackEx=rgb(0, 0, 132)
|
||||
ModEditColor4DTxtInvisEx=rgb(132, 132, 132)
|
||||
ModEditColor4DPadBackEx=rgb(0, 132, 0)
|
||||
ModEditColor4DAnchorEx=rgb(0, 0, 132)
|
||||
ModEditColor4DPadFrontEx=rgb(132, 0, 0)
|
||||
ModEditColor4DPadThruHoleEx=rgb(194, 194, 0)
|
||||
ModEditColor4DNonPlatedEx=rgb(194, 194, 0)
|
||||
ModEditColor4DPCBBackground=rgb(0, 0, 0)
|
||||
ModEditColor4DPCBCursor=rgb(255, 255, 255)
|
||||
ModEditColor4DAuxItems=rgb(255, 255, 255)
|
||||
ModEditColor4DWorksheet=rgb(72, 0, 0)
|
||||
ModEditColor4DGrid=rgb(132, 132, 132)
|
||||
ModEditFramePos_x=72
|
||||
ModEditFramePos_y=27
|
||||
ModEditFrameSize_x=1848
|
||||
ModEditFrameSize_y=1053
|
||||
ModEditFrameMaximized=1
|
||||
ModEditFramePerspective=layout2|name=MainToolbar;caption=;state=139644;dir=1;layer=6;row=0;pos=0;prop=100000;bestw=982;besth=38;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=MsgPanel;caption=;state=131452;dir=3;layer=6;row=0;pos=0;prop=100000;bestw=400;besth=34;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=OptToolbar;caption=;state=139596;dir=4;layer=3;row=0;pos=0;prop=100000;bestw=36;besth=366;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=Footprints;caption=Libraries;state=2044;dir=4;layer=1;row=0;pos=0;prop=100000;bestw=552;besth=-1;minw=250;minh=400;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=ToolsToolbar;caption=;state=139596;dir=2;layer=1;row=0;pos=0;prop=100000;bestw=36;besth=418;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=LayersManager;caption=Layers Manager;state=1532;dir=2;layer=3;row=0;pos=0;prop=100000;bestw=188;besth=32;minw=188;minh=32;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=188;floath=32|name=DrawFrame;caption=;state=1022;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=387;besth=144;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=DrawFrameGal;caption=;state=1020;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=1112;besth=731;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|dock_size(1,6,0)=38|dock_size(3,6,0)=34|dock_size(4,3,0)=36|dock_size(4,1,0)=554|dock_size(2,1,0)=36|dock_size(2,3,0)=188|dock_size(5,0,0)=554|
|
||||
ModEditFrameMostRecentlyUsedPath=
|
||||
ModEditFrameShowGrid=1
|
||||
ModEditFrameGridColor=rgb(132, 132, 132)
|
||||
ModEditFrame_LastGridSize=16
|
||||
ModEditFrameFirstRunShown=0
|
||||
ModEditFrameDevelMaxUndoItems=0
|
||||
ModEditFrameGalDisplayOptionsOpenGLAntialiasingMode=0
|
||||
ModEditFrameGalDisplayOptionsGridStyle=0
|
||||
ModEditFrameGalDisplayOptionsGridLineWidth=0.5
|
||||
ModEditFrameGalDisplayOptionsGridMaxDensity=10
|
||||
ModEditFrameGalDisplayOptionsGridAxesEnabled=1
|
||||
ModEditFrameGalDisplayOptionsCursorFullscreen=0
|
||||
ModEditFrameGalDisplayOptionsForceDisplayCursor=0
|
||||
ModEditFramePcbUserGrid_X=0.254
|
||||
ModEditFramePcbUserGrid_Y=0.254
|
||||
ModEditFramePcbUserGrid_Unit=1
|
||||
ModEditFrameDiPadFi=1
|
||||
ModEditFrameDiViaFi=1
|
||||
ModEditFrameDiPadNu=1
|
||||
ModEditFrameDiModEd=1
|
||||
ModEditFrameDiModTx=1
|
||||
ModEditFrameFastGrid1=0
|
||||
ModEditFrameFastGrid2=0
|
||||
FpEditorUnits=1
|
||||
FpEditorDisplayPolarCoords=0
|
||||
FpEditorPadDisplayMode=1
|
||||
FpEditorGraphicLinesDisplayMode=1
|
||||
FpEditorTextsDisplayMode=1
|
||||
FpEditorTextsRefDefaultText=REF**
|
||||
FpEditorGrlineWidth=0.15
|
||||
FpEditorTextsDefaultSizeH=1
|
||||
FpEditorTextsDefaultSizeV=1
|
||||
FpEditorTextsDefaultThickness=0.15
|
||||
FpEditorRefDefaultText=REF**
|
||||
FpEditorRefDefaultVisibility=1
|
||||
FpEditorRefDefaultLayer=37
|
||||
FpEditorValueDefaultText=
|
||||
FpEditorValueDefaultVisibility=1
|
||||
FpEditorValueDefaultLayer=49
|
||||
ModViewFramePos_x=72
|
||||
ModViewFramePos_y=27
|
||||
ModViewFrameSize_x=2488
|
||||
ModViewFrameSize_y=1413
|
||||
ModViewFrameMaximized=1
|
||||
ModViewFramePerspective=layout2|name=MainToolbar;caption=;state=139644;dir=1;layer=6;row=0;pos=0;prop=100000;bestw=779;besth=38;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=MsgPanel;caption=;state=131452;dir=3;layer=6;row=0;pos=0;prop=100000;bestw=400;besth=34;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=Libraries;caption=;state=1020;dir=4;layer=2;row=0;pos=0;prop=100000;bestw=200;besth=-1;minw=100;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=Footprints;caption=;state=1020;dir=4;layer=1;row=0;pos=0;prop=100000;bestw=300;besth=-1;minw=100;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=DrawFrame;caption=;state=1022;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=387;besth=144;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=DrawFrameGal;caption=;state=1020;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=1835;besth=1040;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|dock_size(1,6,0)=38|dock_size(3,6,0)=34|dock_size(4,2,0)=202|dock_size(4,1,0)=302|dock_size(5,0,0)=389|
|
||||
ModViewFrameMostRecentlyUsedPath=
|
||||
ModViewFrameShowGrid=1
|
||||
ModViewFrameGridColor=rgb(132, 132, 132)
|
||||
ModViewFrame_LastGridSize=1
|
||||
ModViewFrameFirstRunShown=0
|
||||
ModViewFrameDevelMaxUndoItems=0
|
||||
ModViewFrameGalDisplayOptionsOpenGLAntialiasingMode=0
|
||||
ModViewFrameGalDisplayOptionsGridStyle=0
|
||||
ModViewFrameGalDisplayOptionsGridLineWidth=0.5
|
||||
ModViewFrameGalDisplayOptionsGridMaxDensity=10
|
||||
ModViewFrameGalDisplayOptionsGridAxesEnabled=1
|
||||
ModViewFrameGalDisplayOptionsCursorFullscreen=0
|
||||
ModViewFrameGalDisplayOptionsForceDisplayCursor=0
|
||||
import_last_path=
|
||||
FpWizardListWidth=588
|
||||
FpWizardListHeight=482
|
||||
Viewer3DFrameNamePos_x=72
|
||||
Viewer3DFrameNamePos_y=27
|
||||
Viewer3DFrameNameSize_x=2488
|
||||
Viewer3DFrameNameSize_y=1413
|
||||
Viewer3DFrameNameMaximized=1
|
||||
Viewer3DFrameNamePerspective=layout2|name=MainToolbar;caption=;state=139644;dir=1;layer=6;row=0;pos=0;prop=100000;bestw=735;besth=36;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|name=DrawFrame;caption=;state=1020;dir=5;layer=0;row=0;pos=0;prop=100000;bestw=20;besth=20;minw=-1;minh=-1;maxw=-1;maxh=-1;floatx=-1;floaty=-1;floatw=-1;floath=-1|dock_size(1,6,0)=36|dock_size(5,0,0)=22|
|
||||
Viewer3DFrameNameMostRecentlyUsedPath=
|
||||
BgColor_Red=0.4
|
||||
BgColor_Green=0.4
|
||||
BgColor_Blue=0.5
|
||||
BgColor_Red_Top=0.8
|
||||
BgColor_Green_Top=0.8
|
||||
BgColor_Blue_Top=0.9
|
||||
SMaskColor_Red=0.0784314
|
||||
SMaskColor_Green=0.2
|
||||
SMaskColor_Blue=0.141176
|
||||
SPasteColor_Red=0.501961
|
||||
SPasteColor_Green=0.501961
|
||||
SPasteColor_Blue=0.501961
|
||||
SilkColor_Red=0.9
|
||||
SilkColor_Green=0.9
|
||||
SilkColor_Blue=0.9
|
||||
CopperColor_Red=0.7
|
||||
CopperColor_Green=0.612157
|
||||
CopperColor_Blue=0
|
||||
BoardBodyColor_Red=0.2
|
||||
BoardBodyColor_Green=0.168627
|
||||
BoardBodyColor_Blue=0.0862745
|
||||
ShowRealisticMode=1
|
||||
MousewheelPAN3D=0
|
||||
RenderEngine=0
|
||||
Render_Material=0
|
||||
Render_OGL_ShowCopperThickness=1
|
||||
Render_OGL_ShowModelBoudingBoxes=0
|
||||
Render_RAY_Shadows=1
|
||||
Render_RAY_Backfloor=1
|
||||
Render_RAY_Refractions=1
|
||||
Render_RAY_Reflections=1
|
||||
Render_RAY_PostProcess=1
|
||||
Render_RAY_AntiAliasing=1
|
||||
Render_RAY_ProceduralTextures=1
|
||||
ShowAxis=1
|
||||
ShowGrid3D=0
|
||||
ShowFootprints_Normal=1
|
||||
ShowFootprints_Insert=1
|
||||
ShowFootprints_Virtual=1
|
||||
ShowZones=1
|
||||
ShowAdhesiveLayers=1
|
||||
ShowSilkScreenLayers=1
|
||||
ShowSolderMasLayers=1
|
||||
ShowSolderPasteLayers=1
|
||||
ShowCommentsLayers=1
|
||||
ShowEcoLayers=1
|
||||
ShowBoardBody=1
|
||||
SilentMode=0
|
||||
NetlistDeleteSinglePadNets=1
|
||||
NetlistReportFilterMsg=15
|
||||
TestMissingCourtyard=0
|
||||
TestFootprintCourtyard=0
|
||||
RefillZonesBeforeDrc=0
|
||||
Zone_Ouline_Hatch_Opt=2
|
||||
Zone_Filter_Opt=Net-*
|
||||
Zone_Clearance=20
|
||||
Zone_Thickness=10
|
||||
Zone_TH_Gap=20
|
||||
Zone_TH_Copper_Width=39.37007874015748
|
||||
PcbIconScale=-1
|
||||
PrintModuleScale=3
|
||||
PrintMonochrome=1
|
||||
ModEditColor4DPCBLayer_Rescue=rgb(132, 0, 0)
|
||||
ActionPluginButtons=
|
||||
ModEditFrameUnits=1
|
||||
FpEditorSilkLineWidth=0.15
|
||||
FpEditorSilkTextSizeH=1
|
||||
FpEditorSilkTextSizeV=1
|
||||
FpEditorSilkTextThickness=0.15
|
||||
FpEditorSilkTextItalic=0
|
||||
FpEditorCopperLineWidth=0.12
|
||||
FpEditorCopperTextSizeV=1.5
|
||||
FpEditorCopperTextSizeH=1.5
|
||||
FpEditorCopperTextThickness=0.3
|
||||
FpEditorCopperTextItalic=0
|
||||
FpEditorEdgeCutLineWidth=0.12
|
||||
FpEditorCourtyardLineWidth=0.12
|
||||
FpEditorOthersLineWidth=0.12
|
||||
FpEditorOthersTextSizeV=1
|
||||
FpEditorOthersTextSizeH=1
|
||||
FpEditorOthersTextSizeThickness=0.15
|
||||
FpEditorOthersTextItalic=0
|
||||
ModeditLibWidth=552
|
||||
NetlistUpdateFootprints=1
|
||||
NetlistDeleteShortingTracks=0
|
||||
NetlistDeleteExtraFootprints=1
|
||||
FootprintTextShownColumns=0 1 2 3 4 5 6
|
||||
DrcTrackToZoneTest=0
|
||||
ModViewFrameUnits=1
|
||||
ModViewFrameModalPcbUserGrid_X=0.254
|
||||
ModViewFrameModalPcbUserGrid_Y=0.254
|
||||
ModViewFrameModalPcbUserGrid_Unit=1
|
||||
ModViewFrameModalDiPadFi=1
|
||||
ModViewFrameModalDiViaFi=1
|
||||
ModViewFrameModalDiPadNu=1
|
||||
ModViewFrameModalDiModEd=1
|
||||
ModViewFrameModalDiModTx=1
|
||||
ModViewFrameModalFastGrid1=0
|
||||
ModViewFrameModalFastGrid2=0
|
||||
ModViewFrameAutoZoom=1
|
||||
ModViewFrameZoom=17.1134
|
||||
Color4DPCBLayer_Rescue=rgb(132, 0, 0)
|
||||
MagneticGraphics=1
|
||||
PcbFrameUnits=1
|
||||
PrintScale=1
|
||||
PrintPageFrame=1
|
||||
PlotLayer_0=1
|
||||
PlotLayer_1=0
|
||||
PlotLayer_2=0
|
||||
PlotLayer_3=0
|
||||
PlotLayer_4=0
|
||||
PlotLayer_5=0
|
||||
PlotLayer_6=0
|
||||
PlotLayer_7=0
|
||||
PlotLayer_8=0
|
||||
PlotLayer_9=0
|
||||
PlotLayer_10=0
|
||||
PlotLayer_11=0
|
||||
PlotLayer_12=0
|
||||
PlotLayer_13=0
|
||||
PlotLayer_14=0
|
||||
PlotLayer_15=0
|
||||
PlotLayer_16=0
|
||||
PlotLayer_17=0
|
||||
PlotLayer_18=0
|
||||
PlotLayer_19=0
|
||||
PlotLayer_20=0
|
||||
PlotLayer_21=0
|
||||
PlotLayer_22=0
|
||||
PlotLayer_23=0
|
||||
PlotLayer_24=0
|
||||
PlotLayer_25=0
|
||||
PlotLayer_26=0
|
||||
PlotLayer_27=0
|
||||
PlotLayer_28=0
|
||||
PlotLayer_29=0
|
||||
PlotLayer_30=0
|
||||
PlotLayer_31=1
|
||||
PlotLayer_32=0
|
||||
PlotLayer_33=0
|
||||
PlotLayer_34=1
|
||||
PlotLayer_35=1
|
||||
PlotLayer_36=1
|
||||
PlotLayer_37=1
|
||||
PlotLayer_38=1
|
||||
PlotLayer_39=1
|
||||
PlotLayer_40=0
|
||||
PlotLayer_41=0
|
||||
PlotLayer_42=0
|
||||
PlotLayer_43=0
|
||||
PlotLayer_44=1
|
||||
PlotLayer_45=0
|
||||
PlotLayer_46=0
|
||||
PlotLayer_47=0
|
||||
PlotLayer_48=0
|
||||
PlotLayer_49=0
|
||||
PlotLayer_50=0
|
||||
PrintPadsDrillOpt=2
|
||||
PrintSinglePage=0
|
||||
PlotXFineScaleAdj=1
|
||||
PlotYFineScaleAdj=1
|
||||
CheckZonesBeforePlotting=1
|
||||
PSPlotFineWidthAdj=0
|
||||
DrillZerosFormat=0
|
||||
DrillMirrorYOpt=0
|
||||
DrillMergePTHNPTH=0
|
||||
DrillMinHeader=0
|
||||
DrillUnit=1
|
||||
DrillMapFileType=1
|
||||
DrillFileType=0
|
||||
OvalHolesRouteMode=1
|
||||
PlaceFileUnits=1
|
||||
PlaceFileOpts=0
|
||||
PlaceFileFormat=1
|
||||
LibFootprintTextShownColumns=0 1 2 3 4 5 6
|
96
electronics/scripts/config/policy.xml
Normal file
96
electronics/scripts/config/policy.xml
Normal file
@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE policymap [
|
||||
<!ELEMENT policymap (policy)+>
|
||||
<!ATTLIST policymap xmlns CDATA #FIXED ''>
|
||||
<!ELEMENT policy EMPTY>
|
||||
<!ATTLIST policy xmlns CDATA #FIXED '' domain NMTOKEN #REQUIRED
|
||||
name NMTOKEN #IMPLIED pattern CDATA #IMPLIED rights NMTOKEN #IMPLIED
|
||||
stealth NMTOKEN #IMPLIED value CDATA #IMPLIED>
|
||||
]>
|
||||
<!--
|
||||
Configure ImageMagick policies.
|
||||
|
||||
Domains include system, delegate, coder, filter, path, or resource.
|
||||
|
||||
Rights include none, read, write, execute and all. Use | to combine them,
|
||||
for example: "read | write" to permit read from, or write to, a path.
|
||||
|
||||
Use a glob expression as a pattern.
|
||||
|
||||
Suppose we do not want users to process MPEG video images:
|
||||
|
||||
<policy domain="delegate" rights="none" pattern="mpeg:decode" />
|
||||
|
||||
Here we do not want users reading images from HTTP:
|
||||
|
||||
<policy domain="coder" rights="none" pattern="HTTP" />
|
||||
|
||||
The /repository file system is restricted to read only. We use a glob
|
||||
expression to match all paths that start with /repository:
|
||||
|
||||
<policy domain="path" rights="read" pattern="/repository/*" />
|
||||
|
||||
Lets prevent users from executing any image filters:
|
||||
|
||||
<policy domain="filter" rights="none" pattern="*" />
|
||||
|
||||
Any large image is cached to disk rather than memory:
|
||||
|
||||
<policy domain="resource" name="area" value="1GP"/>
|
||||
|
||||
Define arguments for the memory, map, area, width, height and disk resources
|
||||
with SI prefixes (.e.g 100MB). In addition, resource policies are maximums
|
||||
for each instance of ImageMagick (e.g. policy memory limit 1GB, -limit 2GB
|
||||
exceeds policy maximum so memory limit is 1GB).
|
||||
|
||||
Rules are processed in order. Here we want to restrict ImageMagick to only
|
||||
read or write a small subset of proven web-safe image types:
|
||||
|
||||
<policy domain="delegate" rights="none" pattern="*" />
|
||||
<policy domain="filter" rights="none" pattern="*" />
|
||||
<policy domain="coder" rights="none" pattern="*" />
|
||||
<policy domain="coder" rights="read|write" pattern="{GIF,JPEG,PNG,WEBP}" />
|
||||
-->
|
||||
<policymap>
|
||||
<!-- <policy domain="system" name="shred" value="2"/> -->
|
||||
<!-- <policy domain="system" name="precision" value="6"/> -->
|
||||
<!-- <policy domain="system" name="memory-map" value="anonymous"/> -->
|
||||
<!-- <policy domain="system" name="max-memory-request" value="256MiB"/> -->
|
||||
<!-- <policy domain="resource" name="temporary-path" value="/tmp"/> -->
|
||||
<policy domain="resource" name="memory" value="256MiB"/>
|
||||
<policy domain="resource" name="map" value="512MiB"/>
|
||||
<policy domain="resource" name="width" value="16KP"/>
|
||||
<policy domain="resource" name="height" value="16KP"/>
|
||||
<!-- <policy domain="resource" name="list-length" value="128"/> -->
|
||||
<policy domain="resource" name="area" value="128MB"/>
|
||||
<policy domain="resource" name="disk" value="1GiB"/>
|
||||
<!-- <policy domain="resource" name="file" value="768"/> -->
|
||||
<!-- <policy domain="resource" name="thread" value="4"/> -->
|
||||
<!-- <policy domain="resource" name="throttle" value="0"/> -->
|
||||
<!-- <policy domain="resource" name="time" value="3600"/> -->
|
||||
<!-- <policy domain="coder" rights="none" pattern="MVG" /> -->
|
||||
<!-- <policy domain="module" rights="none" pattern="{PS,PDF,XPS}" /> -->
|
||||
<!-- <policy domain="delegate" rights="none" pattern="HTTPS" /> -->
|
||||
<!-- <policy domain="path" rights="none" pattern="@*" /> -->
|
||||
<!-- <policy domain="cache" name="memory-map" value="anonymous"/> -->
|
||||
<!-- <policy domain="cache" name="synchronize" value="True"/> -->
|
||||
<!-- <policy domain="cache" name="shared-secret" value="passphrase" stealth="true"/> -->
|
||||
<!-- <policy domain="system" name="pixel-cache-memory" value="anonymous"/> -->
|
||||
<!-- <policy domain="system" name="shred" value="2"/> -->
|
||||
<!-- <policy domain="system" name="precision" value="6"/> -->
|
||||
<!-- not needed due to the need to use explicitly by mvg: -->
|
||||
<!-- <policy domain="delegate" rights="none" pattern="MVG" /> -->
|
||||
<!-- use curl -->
|
||||
<policy domain="delegate" rights="none" pattern="URL" />
|
||||
<policy domain="delegate" rights="none" pattern="HTTPS" />
|
||||
<policy domain="delegate" rights="none" pattern="HTTP" />
|
||||
<!-- in order to avoid to get image with password text -->
|
||||
<policy domain="path" rights="none" pattern="@*"/>
|
||||
<!-- disable ghostscript format types -->
|
||||
<policy domain="coder" rights="none" pattern="PS" />
|
||||
<policy domain="coder" rights="none" pattern="PS2" />
|
||||
<policy domain="coder" rights="none" pattern="PS3" />
|
||||
<policy domain="coder" rights="none" pattern="EPS" />
|
||||
<policy domain="coder" rights="read|write" pattern="PDF" />
|
||||
<policy domain="coder" rights="none" pattern="XPS" />
|
||||
</policymap>
|
28
electronics/scripts/dependencies.sh
Executable file
28
electronics/scripts/dependencies.sh
Executable file
@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
if [[ -z "${GITHUB_WORKFLOW}" ]]; then
|
||||
>&2 echo "Aborting! This script is meant to be run in CI (Github Actions) only. It may modify/damage your system configuration if run outside of CI."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -v
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
|
||||
sudo add-apt-repository --yes ppa:kicad/kicad-5.1-releases
|
||||
sudo apt-get update -qq
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y kicad inkscape poppler-utils xdotool recordmydesktop python3-dev python3-pip
|
||||
|
||||
# KiKit is installed via pinned git revision to get "new" CLI with support for V-Cuts layer specification. TODO: switch to release version once landed.
|
||||
sudo python3 -m pip install psutil kikit==1.0.2 xvfbwrapper
|
||||
|
||||
mkdir -p ~/.config/kicad
|
||||
cp /usr/share/kicad/template/fp-lib-table ~/.config/kicad/
|
||||
cp /usr/share/kicad/template/sym-lib-table ~/.config/kicad/
|
||||
|
||||
cp "$DIR/config/eeschema" ~/.config/kicad/
|
||||
cp "$DIR/config/pcbnew" ~/.config/kicad/
|
||||
|
||||
# Install ImageMagick policy that allows PDF conversion (safe in CI because we control all inputs/outputs)
|
||||
sudo cp "$DIR/config/policy.xml" /etc/ImageMagick-6/policy.xml
|
192
electronics/scripts/export_3d.py
Executable file
192
electronics/scripts/export_3d.py
Executable file
@ -0,0 +1,192 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright 2015-2021 Scott Bezek and the splitflap contributors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import psutil
|
||||
import sys
|
||||
import time
|
||||
|
||||
electronics_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
repo_root = os.path.dirname(electronics_root)
|
||||
sys.path.append(repo_root)
|
||||
|
||||
from util import file_util
|
||||
from export_util import (
|
||||
patch_config,
|
||||
PopenContext,
|
||||
versioned_file,
|
||||
xdotool,
|
||||
wait_for_window,
|
||||
recorded_xvfb,
|
||||
)
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
RENDER_TIMEOUT = 10 * 60
|
||||
|
||||
|
||||
def _wait_for_pcbnew_idle():
|
||||
start = time.time()
|
||||
while time.time() < start + RENDER_TIMEOUT:
|
||||
for proc in psutil.process_iter():
|
||||
if proc.name() == 'pcbnew':
|
||||
cpu = proc.cpu_percent(interval=1)
|
||||
print(f'CPU={cpu}', flush=True)
|
||||
if cpu < 5:
|
||||
print('Render took %d seconds' % (time.time() - start))
|
||||
return
|
||||
time.sleep(1)
|
||||
raise RuntimeError('Timeout waiting for pcbnew to go idle')
|
||||
|
||||
|
||||
def _zoom_in():
|
||||
xdotool([
|
||||
'click',
|
||||
'4',
|
||||
])
|
||||
time.sleep(0.2)
|
||||
|
||||
|
||||
def _invoke_view_option(index):
|
||||
command = ['key', 'alt+v'] + ['Down']*index + ['Return']
|
||||
xdotool(command)
|
||||
time.sleep(2)
|
||||
|
||||
|
||||
_transforms = {
|
||||
'z+': ('Zoom in', _zoom_in),
|
||||
'rx+': ('Rotate X Clockwise', lambda: _invoke_view_option(4)),
|
||||
'rx-': ('Rotate X Counterclockwise', lambda: _invoke_view_option(5)),
|
||||
'ry+': ('Rotate Y Clockwise', lambda: _invoke_view_option(6)),
|
||||
'ry-': ('Rotate Y Counterclockwise', lambda: _invoke_view_option(7)),
|
||||
'rz+': ('Rotate Z Clockwise', lambda: _invoke_view_option(8)),
|
||||
'rz-': ('Rotate Z Counterclockwise', lambda: _invoke_view_option(9)),
|
||||
'ml': ('Move left', lambda: _invoke_view_option(10)),
|
||||
'mr': ('Move right', lambda: _invoke_view_option(11)),
|
||||
'mu': ('Move up', lambda: _invoke_view_option(12)),
|
||||
'md': ('Move down', lambda: _invoke_view_option(13)),
|
||||
}
|
||||
|
||||
|
||||
def _pcbnew_export_3d(output_file, width, height, transforms):
|
||||
if os.path.exists(output_file):
|
||||
os.remove(output_file)
|
||||
|
||||
wait_for_window('pcbnew', 'Pcbnew ', additional_commands=['windowfocus'])
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
logger.info('Open 3d viewer')
|
||||
xdotool(['key', 'alt+3'])
|
||||
|
||||
wait_for_window('3D Viewer', '3D Viewer', additional_commands=['windowfocus'])
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
# Maximize window
|
||||
xdotool(['search', '--name', '3D Viewer', 'windowmove', '0', '0'])
|
||||
xdotool(['search', '--name', '3D Viewer', 'windowsize', str(width), str(height)])
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
for transform in transforms:
|
||||
description, func = _transforms[transform]
|
||||
logger.info(description)
|
||||
func()
|
||||
|
||||
logger.info('Wait for rendering...')
|
||||
|
||||
_wait_for_pcbnew_idle()
|
||||
|
||||
time.sleep(5)
|
||||
|
||||
logger.info('Export current view')
|
||||
xdotool([
|
||||
'key',
|
||||
'alt+f',
|
||||
'Return',
|
||||
])
|
||||
|
||||
logger.info('Enter build output filename')
|
||||
xdotool([
|
||||
'key',
|
||||
'ctrl+a',
|
||||
])
|
||||
xdotool(['type', output_file])
|
||||
|
||||
logger.info('Save')
|
||||
xdotool(['key', 'Return'])
|
||||
|
||||
logger.info('Wait before shutdown')
|
||||
time.sleep(2)
|
||||
|
||||
|
||||
def export_3d(filename, suffix, width, height, transforms, raytrace, virtual, color_soldermask, color_silk):
|
||||
pcb_file = os.path.abspath(filename)
|
||||
output_dir = os.path.join(electronics_root, 'build')
|
||||
file_util.mkdir_p(output_dir)
|
||||
|
||||
screencast_output_file = os.path.join(output_dir, 'export_3d_screencast.ogv')
|
||||
|
||||
name, _ = os.path.splitext(os.path.basename(pcb_file))
|
||||
if suffix:
|
||||
name = name + '-' + suffix
|
||||
output_file = os.path.join(output_dir, f'{name}-3d.png')
|
||||
|
||||
settings = {
|
||||
'canvas_type': '1',
|
||||
'SMaskColor_Red': str(color_soldermask[0]),
|
||||
'SMaskColor_Green': str(color_soldermask[1]),
|
||||
'SMaskColor_Blue': str(color_soldermask[2]),
|
||||
'SilkColor_Red': str(color_silk[0]),
|
||||
'SilkColor_Green': str(color_silk[1]),
|
||||
'SilkColor_Blue': str(color_silk[2]),
|
||||
'RenderEngine': '1' if raytrace else '0',
|
||||
'ShowFootprints_Virtual': '1' if virtual else '0',
|
||||
'Render_RAY_ProceduralTextures': '0',
|
||||
}
|
||||
with patch_config(os.path.expanduser('~/.config/kicad/pcbnew'), settings):
|
||||
with versioned_file(pcb_file):
|
||||
with recorded_xvfb(screencast_output_file, width=width, height=height, colordepth=24):
|
||||
with PopenContext(['pcbnew', pcb_file], close_fds=True) as pcbnew_proc:
|
||||
_pcbnew_export_3d(output_file, width, height, transforms)
|
||||
pcbnew_proc.terminate()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('pcb')
|
||||
parser.add_argument('--suffix', default='')
|
||||
parser.add_argument('--width', type=int, default=2560)
|
||||
parser.add_argument('--height', type=int, default=1440)
|
||||
parser.add_argument('--skip-raytrace', action='store_true')
|
||||
parser.add_argument('--skip-virtual', action='store_true', help='Don\'t render virtual footprints')
|
||||
parser.add_argument('--color-soldermask', type=float, nargs=3, help='Soldermask color as 3 floats from 0-1', default=[0.1, 0.1, 0.1])
|
||||
parser.add_argument('--color-silk', type=float, nargs=3, help='Silkscreen color as 3 floats from 0-1', default=[0.9, 0.9, 0.9])
|
||||
|
||||
# Use subparsers to for an optional nargs="*" choices argument (workaround for https://bugs.python.org/issue9625)
|
||||
subparsers = parser.add_subparsers(dest='which')
|
||||
transform_parser = subparsers.add_parser('transform', help='Apply one or more transforms before capturing image')
|
||||
transform_parser.add_argument('transform', nargs='+', choices=list(_transforms.keys()))
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
transforms = args.transform if args.which == 'transform' else []
|
||||
|
||||
export_3d(args.pcb, args.suffix, args.width, args.height, transforms, not args.skip_raytrace, not args.skip_virtual, args.color_soldermask, args.color_silk)
|
70
electronics/scripts/export_jlcpcb.py
Executable file
70
electronics/scripts/export_jlcpcb.py
Executable file
@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright 2021 Scott Bezek and the splitflap contributors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
electronics_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
repo_root = os.path.dirname(electronics_root)
|
||||
sys.path.append(repo_root)
|
||||
|
||||
from util import file_util
|
||||
from export_util import (
|
||||
versioned_file,
|
||||
)
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def export_jlcpcb(pcb, schematic, alt_fields):
|
||||
pcb_file = os.path.abspath(pcb)
|
||||
|
||||
output_dir = os.path.join(electronics_root, 'build', os.path.splitext(os.path.basename(pcb_file))[0] + '-jlc')
|
||||
file_util.mkdir_p(output_dir)
|
||||
|
||||
with versioned_file(pcb_file):
|
||||
command = [
|
||||
'kikit',
|
||||
'fab',
|
||||
'jlcpcb',
|
||||
]
|
||||
if schematic is not None:
|
||||
schematic_file = os.path.abspath(schematic)
|
||||
command += [
|
||||
'--assembly',
|
||||
'--schematic',
|
||||
schematic_file,
|
||||
'--field',
|
||||
]
|
||||
command.append(','.join(alt_fields + ['LCSC']))
|
||||
command += [
|
||||
pcb_file,
|
||||
output_dir,
|
||||
]
|
||||
subprocess.check_call(command)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('pcb')
|
||||
parser.add_argument('--assembly-schematic')
|
||||
parser.add_argument('--alt-fields', nargs='+')
|
||||
args = parser.parse_args()
|
||||
export_jlcpcb(args.pcb, args.assembly_schematic, args.alt_fields)
|
138
electronics/scripts/export_util.py
Normal file
138
electronics/scripts/export_util.py
Normal file
@ -0,0 +1,138 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright 2015-2016 Scott Bezek and the splitflap contributors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
from contextlib import contextmanager
|
||||
|
||||
electronics_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
repo_root = os.path.dirname(electronics_root)
|
||||
sys.path.append(repo_root)
|
||||
|
||||
from xvfbwrapper import Xvfb
|
||||
from util import file_util, rev_info
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class PopenContext(subprocess.Popen):
|
||||
def __enter__(self):
|
||||
return self
|
||||
def __exit__(self, type, value, traceback):
|
||||
if self.stdout:
|
||||
self.stdout.close()
|
||||
if self.stderr:
|
||||
self.stderr.close()
|
||||
if self.stdin:
|
||||
self.stdin.close()
|
||||
if type:
|
||||
self.terminate()
|
||||
# Wait for the process to terminate, to avoid zombies.
|
||||
self.wait()
|
||||
|
||||
def xdotool(command):
|
||||
return subprocess.check_output(['xdotool'] + command)
|
||||
|
||||
def wait_for_window(name, window_regex, additional_commands=None, timeout=10):
|
||||
if additional_commands is not None:
|
||||
commands = additional_commands
|
||||
else:
|
||||
commands = []
|
||||
|
||||
DELAY = 0.5
|
||||
logger.info('Waiting for %s window...', name)
|
||||
for i in range(int(timeout/DELAY)):
|
||||
try:
|
||||
xdotool(['search', '--name', window_regex] + commands)
|
||||
logger.info('Found %s window', name)
|
||||
return
|
||||
except subprocess.CalledProcessError:
|
||||
pass
|
||||
time.sleep(DELAY)
|
||||
raise RuntimeError('Timed out waiting for %s window' % name)
|
||||
|
||||
@contextmanager
|
||||
def recorded_xvfb(video_filename, **xvfb_args):
|
||||
with Xvfb(**xvfb_args):
|
||||
with PopenContext([
|
||||
'recordmydesktop',
|
||||
'--no-sound',
|
||||
'--no-frame',
|
||||
'--on-the-fly-encoding',
|
||||
'-o', video_filename], close_fds=True) as screencast_proc:
|
||||
yield
|
||||
screencast_proc.terminate()
|
||||
|
||||
|
||||
def get_versioned_contents(filename):
|
||||
with open(filename, 'r') as f:
|
||||
original_contents = f.read()
|
||||
date = rev_info.git_date()
|
||||
date_long = rev_info.git_date(short=False)
|
||||
rev = rev_info.git_short_rev()
|
||||
logger.info('Replacing placeholders with %s and %s' % (date, rev))
|
||||
return original_contents, original_contents \
|
||||
.replace('Date ""', 'Date "%s"' % date_long) \
|
||||
.replace('DATE: YYYY-MM-DD TIME TZ', 'DATE: %s' % date_long) \
|
||||
.replace('DATE: YYYY-MM-DD', 'DATE: %s' % date) \
|
||||
.replace('Rev ""', 'Rev "%s"' % rev) \
|
||||
.replace('COMMIT: deadbeef', 'COMMIT: %s' % rev)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def versioned_file(filename):
|
||||
original_contents, versioned_contents = get_versioned_contents(filename)
|
||||
with open(filename, 'w') as temp_schematic:
|
||||
logger.debug('Writing to %s', filename)
|
||||
temp_schematic.write(versioned_contents)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
with open(filename, 'w') as temp_schematic:
|
||||
logger.debug('Restoring %s', filename)
|
||||
temp_schematic.write(original_contents)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def patch_config(filename, replacements):
|
||||
if not os.path.exists(filename):
|
||||
yield
|
||||
return
|
||||
|
||||
with open(filename, 'r') as f:
|
||||
original_contents = f.read()
|
||||
|
||||
new_contents = original_contents
|
||||
for (key, value) in replacements.items():
|
||||
pattern = '^' + re.escape(key) + '=(.*)$'
|
||||
new_contents = re.sub(pattern, key + '=' + value, new_contents, flags=re.MULTILINE)
|
||||
|
||||
with open(filename, 'w') as f:
|
||||
logger.debug('Writing to %s', filename)
|
||||
f.write(new_contents)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
with open(filename, 'w') as f:
|
||||
logger.debug('Restoring %s', filename)
|
||||
f.write(original_contents)
|
||||
|
80
electronics/scripts/generate_pdf.py
Executable file
80
electronics/scripts/generate_pdf.py
Executable file
@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright 2015-2021 Scott Bezek and the splitflap contributors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import pcbnew
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
import pcb_util
|
||||
|
||||
electronics_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def run(pcb_file):
|
||||
output_directory = os.path.join(electronics_root, 'build')
|
||||
temp_dir = os.path.join(output_directory, 'temp_pdfs')
|
||||
shutil.rmtree(temp_dir, ignore_errors=True)
|
||||
try:
|
||||
os.makedirs(temp_dir)
|
||||
plot_to_directory(pcb_file, output_directory, temp_dir)
|
||||
finally:
|
||||
shutil.rmtree(temp_dir, ignore_errors=True)
|
||||
|
||||
|
||||
def plot_to_directory(pcb_file, output_directory, temp_dir):
|
||||
board_name = os.path.splitext(os.path.basename(pcb_file))[0]
|
||||
|
||||
with pcb_util.get_plotter(pcb_file, temp_dir) as plotter:
|
||||
plotter.plot_options.SetDrillMarksType(pcbnew.PCB_PLOT_PARAMS.NO_DRILL_SHAPE)
|
||||
plotter.plot_options.SetExcludeEdgeLayer(False)
|
||||
|
||||
LayerDef = namedtuple('LayerDef', ['layer', 'mirror'])
|
||||
layers = [
|
||||
LayerDef(pcbnew.F_Cu, False),
|
||||
LayerDef(pcbnew.B_Cu, True),
|
||||
LayerDef(pcbnew.F_SilkS, False),
|
||||
LayerDef(pcbnew.B_SilkS, True),
|
||||
LayerDef(pcbnew.F_Mask, False),
|
||||
LayerDef(pcbnew.B_Mask, True),
|
||||
LayerDef(pcbnew.F_Paste, False),
|
||||
]
|
||||
|
||||
pdfs = []
|
||||
for layer in layers:
|
||||
plotter.plot_options.SetMirror(layer.mirror)
|
||||
output_filename = plotter.plot(layer.layer, pcbnew.PLOT_FORMAT_PDF)
|
||||
pdfs.append(output_filename)
|
||||
|
||||
_, map_file = plotter.plot_drill()
|
||||
pdfs.append(map_file)
|
||||
|
||||
output_pdf_filename = os.path.join(output_directory, '%s-pcb-packet.pdf' % (board_name,))
|
||||
|
||||
command = ['pdfunite'] + pdfs + [output_pdf_filename]
|
||||
subprocess.check_call(command)
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser('Generate a pdf of the PCB')
|
||||
parser.add_argument('pcb_file')
|
||||
args = parser.parse_args()
|
||||
run(args.pcb_file)
|
||||
|
112
electronics/scripts/pcb_util.py
Normal file
112
electronics/scripts/pcb_util.py
Normal file
@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright 2015-2021 Scott Bezek and the splitflap contributors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import pcbnew
|
||||
import tempfile
|
||||
|
||||
from contextlib import contextmanager
|
||||
|
||||
from export_util import (
|
||||
get_versioned_contents
|
||||
)
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@contextmanager
|
||||
def versioned_board(filename):
|
||||
_, versioned_contents = get_versioned_contents(filename)
|
||||
with tempfile.NamedTemporaryFile(suffix='.kicad_pcb', mode='w') as temp_pcb:
|
||||
logger.debug('Writing to %s', temp_pcb.name)
|
||||
temp_pcb.write(versioned_contents)
|
||||
temp_pcb.flush()
|
||||
|
||||
logger.debug('Load board')
|
||||
board = pcbnew.LoadBoard(temp_pcb.name)
|
||||
yield board
|
||||
|
||||
@contextmanager
|
||||
def get_plotter(pcb_filename, build_directory):
|
||||
with versioned_board(pcb_filename) as board:
|
||||
yield Plotter(board, build_directory)
|
||||
|
||||
|
||||
class Plotter(object):
|
||||
def __init__(self, board, build_directory):
|
||||
self.board = board
|
||||
self.build_directory = build_directory
|
||||
self.plot_controller = pcbnew.PLOT_CONTROLLER(board)
|
||||
self.plot_options = self.plot_controller.GetPlotOptions()
|
||||
self.plot_options.SetOutputDirectory(build_directory)
|
||||
|
||||
self.plot_options.SetPlotFrameRef(False)
|
||||
self.plot_options.SetLineWidth(pcbnew.FromMM(0.35))
|
||||
self.plot_options.SetScale(1)
|
||||
self.plot_options.SetUseAuxOrigin(True)
|
||||
self.plot_options.SetMirror(False)
|
||||
self.plot_options.SetExcludeEdgeLayer(True)
|
||||
|
||||
def plot(self, layer, plot_format):
|
||||
layer_name = self.board.GetLayerName(layer)
|
||||
logger.info('Plotting layer %s (kicad layer=%r)', layer_name, layer)
|
||||
self.plot_controller.SetLayer(layer)
|
||||
self.plot_controller.OpenPlotfile(layer_name, plot_format , 'Plot')
|
||||
output_filename = self.plot_controller.GetPlotFileName()
|
||||
self.plot_controller.PlotLayer()
|
||||
self.plot_controller.ClosePlot()
|
||||
return output_filename
|
||||
|
||||
def plot_drill(self):
|
||||
board_name = os.path.splitext(os.path.basename(self.board.GetFileName()))[0]
|
||||
logger.info('Plotting drill file')
|
||||
drill_writer = pcbnew.EXCELLON_WRITER(self.board)
|
||||
drill_writer.SetMapFileFormat(pcbnew.PLOT_FORMAT_PDF)
|
||||
|
||||
mirror = False
|
||||
minimalHeader = False
|
||||
offset = pcbnew.wxPoint(0, 0)
|
||||
merge_npth = True
|
||||
drill_writer.SetOptions(mirror, minimalHeader, offset, merge_npth)
|
||||
|
||||
metric_format = True
|
||||
drill_writer.SetFormat(metric_format)
|
||||
|
||||
generate_drill = True
|
||||
generate_map = True
|
||||
drill_writer.CreateDrillandMapFilesSet(self.build_directory, generate_drill, generate_map)
|
||||
|
||||
drill_file_name = os.path.join(
|
||||
self.build_directory,
|
||||
'%s.drl' % (board_name,)
|
||||
)
|
||||
|
||||
map_file_name = os.path.join(
|
||||
self.build_directory,
|
||||
'%s-drl_map.pdf' % (board_name,)
|
||||
)
|
||||
return drill_file_name, map_file_name
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Test pcb util')
|
||||
parser.add_argument('input_file', help='Input .kicad_pcb file')
|
||||
args = parser.parse_args()
|
||||
with versioned_board(args.input_file) as board:
|
||||
logger.info('Loaded %s', board.GetFileName())
|
||||
for module in board.GetModules():
|
||||
logger.info('Module %s: %s', module.GetReference(), module.GetValue())
|
@ -8,6 +8,32 @@ preflight:
|
||||
update_xml: true
|
||||
|
||||
outputs:
|
||||
# - name: pdf
|
||||
# type: pdf_pcb_print
|
||||
# dir: pdf
|
||||
# options:
|
||||
# separated: true
|
||||
# layers:
|
||||
# - 'F.Cu'
|
||||
# - 'B.Cu'
|
||||
# - 'F.Paste'
|
||||
# - 'B.Paste'
|
||||
# - 'F.SilkS'
|
||||
# - 'B.SilkS'
|
||||
# - 'Edge.Cuts'
|
||||
|
||||
# - name: gerber
|
||||
# type: gerber
|
||||
# dir: gerber
|
||||
# layers:
|
||||
# - 'F.Cu'
|
||||
# - 'B.Cu'
|
||||
# - 'F.Paste'
|
||||
# - 'B.Paste'
|
||||
# - 'F.SilkS'
|
||||
# - 'B.SilkS'
|
||||
# - 'Edge.Cuts'
|
||||
|
||||
- name: ibom
|
||||
comment: 'Interactive BOM'
|
||||
type: ibom
|
||||
@ -19,24 +45,24 @@ outputs:
|
||||
- name: schematic
|
||||
type: pdf_sch_print
|
||||
|
||||
- name: 3d
|
||||
type: render_3d
|
||||
options:
|
||||
no_virtual: true
|
||||
view: 'top'
|
||||
silk: '#111111'
|
||||
solder_mask: '#ffffff'
|
||||
board: '#C3BA9B'
|
||||
copper: '#99967F'
|
||||
zoom: 4
|
||||
orthographic: true
|
||||
ray_tracing: true
|
||||
height: 1920
|
||||
width: 1920
|
||||
# - name: 3d
|
||||
# type: render_3d
|
||||
# options:
|
||||
# no_virtual: true
|
||||
# view: 'top'
|
||||
# silk: '#111111'
|
||||
# solder_mask: '#ffffff'
|
||||
# board: '#C3BA9B'
|
||||
# copper: '#99967F'
|
||||
# zoom: 4
|
||||
# orthographic: true
|
||||
# ray_tracing: true
|
||||
# height: 1920
|
||||
# width: 1920
|
||||
|
||||
- name: 3d_back
|
||||
type: render_3d
|
||||
extends: 3d
|
||||
options:
|
||||
view: 'bottom'
|
||||
zoom: 3
|
||||
# - name: 3d_back
|
||||
# type: render_3d
|
||||
# extends: 3d
|
||||
# options:
|
||||
# view: 'bottom'
|
||||
# zoom: 3
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -19,24 +19,24 @@ outputs:
|
||||
- name: schematic
|
||||
type: pdf_sch_print
|
||||
|
||||
- name: 3d
|
||||
type: render_3d
|
||||
options:
|
||||
no_virtual: true
|
||||
view: 'top'
|
||||
silk: '#111111'
|
||||
solder_mask: '#ffffff'
|
||||
board: '#C3BA9B'
|
||||
copper: '#99967F'
|
||||
orthographic: true
|
||||
ray_tracing: true
|
||||
height: 1920
|
||||
width: 1920
|
||||
zoom: 3
|
||||
# - name: 3d
|
||||
# type: render_3d
|
||||
# options:
|
||||
# no_virtual: true
|
||||
# view: 'top'
|
||||
# silk: '#111111'
|
||||
# solder_mask: '#ffffff'
|
||||
# board: '#C3BA9B'
|
||||
# copper: '#99967F'
|
||||
# orthographic: true
|
||||
# ray_tracing: true
|
||||
# height: 1920
|
||||
# width: 1920
|
||||
# zoom: 4
|
||||
|
||||
- name: 3d_back
|
||||
type: render_3d
|
||||
extends: 3d
|
||||
options:
|
||||
view: 'bottom'
|
||||
zoom: 3
|
||||
# - name: 3d_back
|
||||
# type: render_3d
|
||||
# extends: 3d
|
||||
# options:
|
||||
# view: 'bottom'
|
||||
# zoom: 3
|
||||
|
File diff suppressed because it is too large
Load Diff
BIN
scripts/RobotoMono-Bold.ttf
Normal file
BIN
scripts/RobotoMono-Bold.ttf
Normal file
Binary file not shown.
16
scripts/annotate_image.sh
Executable file
16
scripts/annotate_image.sh
Executable file
@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
|
||||
FONT="$DIR/RobotoMono-Bold.ttf"
|
||||
|
||||
# Make sure font exists
|
||||
ls "$FONT"
|
||||
|
||||
set -v
|
||||
|
||||
LABEL="`date --rfc-3339=seconds`\n`git rev-parse --short HEAD`"
|
||||
convert -background black -fill white -pointsize 12 -font "$FONT" -size 300x36 label:"$LABEL" -bordercolor black -border 3 $1 +swap -append $1
|
||||
|
0
util/__init__.py
Normal file
0
util/__init__.py
Normal file
14
util/file_util.py
Normal file
14
util/file_util.py
Normal file
@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import errno
|
||||
import os
|
||||
|
||||
def mkdir_p(path):
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except OSError as exc: # Python >2.5
|
||||
if exc.errno == errno.EEXIST and os.path.isdir(path):
|
||||
pass
|
||||
else:
|
||||
raise
|
||||
|
32
util/rev_info.py
Normal file
32
util/rev_info.py
Normal file
@ -0,0 +1,32 @@
|
||||
import datetime
|
||||
import subprocess
|
||||
|
||||
def git_short_rev():
|
||||
try:
|
||||
return subprocess.check_output([
|
||||
'git',
|
||||
'rev-parse',
|
||||
'--short',
|
||||
'HEAD',
|
||||
]).decode('utf-8').strip()
|
||||
except Exception:
|
||||
raise RuntimeError("Could not read git revision. Make sure you have git installed and you're working with a git clone of the repository.")
|
||||
|
||||
def current_date():
|
||||
return datetime.date.today().strftime('%Y-%m-%d')
|
||||
|
||||
def git_date(short=True):
|
||||
try:
|
||||
iso = subprocess.check_output([
|
||||
'git',
|
||||
'log',
|
||||
'-1',
|
||||
'--format=%ci',
|
||||
'HEAD',
|
||||
]).decode('utf-8').strip()
|
||||
if short:
|
||||
return iso.split(' ')[0]
|
||||
else:
|
||||
return iso
|
||||
except Exception:
|
||||
raise RuntimeError("Could not read git commit date. Make sure you have git installed and you're working with a git clone of the repository.")
|
Loading…
Reference in New Issue
Block a user