├── LICENSE
├── README.md
├── case
├── grumpy_case_build123d.py
├── grumpy_case_cadquery.py
├── grumpy_case_choc.py
├── grumpy_case_lp.py
├── grumpy_lp.FCStd
└── grumpy_lp_choc.FCStd
├── firmware
└── QMK
│ ├── grumpy
│ ├── config.h
│ ├── halconf.h
│ ├── info.json
│ ├── keymaps
│ │ ├── default
│ │ │ └── keymap.c
│ │ └── vial
│ │ │ ├── config.h
│ │ │ ├── keymap.c
│ │ │ ├── rules.mk
│ │ │ └── vial.json
│ ├── mcuconf.h
│ └── rules.mk
│ ├── grumpy_MX_vial.uf2
│ ├── grumpy_chocV1
│ ├── config.h
│ ├── halconf.h
│ ├── info.json
│ ├── keymaps
│ │ ├── default
│ │ │ └── keymap.c
│ │ └── vial
│ │ │ ├── config.h
│ │ │ ├── keymap.c
│ │ │ ├── rules.mk
│ │ │ └── vial.json
│ ├── mcuconf.h
│ └── rules.mk
│ └── grumpy_chocV1_vial.uf2
├── grumpy_ch552t
├── fp-info-cache
├── fp-lib-table
├── grumpy_ch522t.kicad_pcb
├── grumpy_ch522t.kicad_prl
├── grumpy_ch522t.kicad_pro
└── grumpy_ch522t.kicad_sch
├── grumpy_choc
├── fp-info-cache
├── fp-lib-table
├── grumpy_choc.kicad_pcb
├── grumpy_choc.kicad_prl
├── grumpy_choc.kicad_pro
├── grumpy_choc.kicad_sch
└── sym-lib-table
├── grumpy_xiao
├── grumpy.kicad_pcb
├── grumpy.kicad_prl
├── grumpy.kicad_pro
└── grumpy.kicad_sch
├── img
├── choc_v1_alu.jpg
├── grumpies.jpg
├── grumpy.png
└── grumpy_mjf.png
└── prod
├── ChocV1 low profile
├── case_choc
│ ├── grumpy case threads drawing.pdf
│ ├── grumpy_lp_choc_bottom.step
│ └── grumpy_lp_choc_top.step
└── grumpy_chocV1_GERBER_20250107.zip
├── MX ChocV2 low profile
├── case_chocV2
│ ├── grumpy_lp.step
│ ├── grumpy_lp.stl
│ ├── grumpy_lp_bottom.step
│ └── grumpy_lp_bottom.stl
└── grumpy_chocV2_GERBER_20240611.zip
└── MX Xiao
├── case_mx
└── grumpy.stl
└── grumpy_mx_GERBER_20230724.zip
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2023 weteor
2 |
3 | CERN Open Hardware Licence Version 2 - Permissive
4 |
5 | Preamble
6 |
7 | CERN has developed this licence to promote collaboration among
8 | hardware designers and to provide a legal tool which supports the
9 | freedom to use, study, modify, share and distribute hardware designs
10 | and products based on those designs. Version 2 of the CERN Open
11 | Hardware Licence comes in three variants: this licence, CERN-OHL-P
12 | (permissive); and two reciprocal licences: CERN-OHL-W (weakly
13 | reciprocal) and CERN-OHL-S (strongly reciprocal).
14 |
15 | The CERN-OHL-P is copyright CERN 2020. Anyone is welcome to use it, in
16 | unmodified form only.
17 |
18 | Use of this Licence does not imply any endorsement by CERN of any
19 | Licensor or their designs nor does it imply any involvement by CERN in
20 | their development.
21 |
22 |
23 | 1 Definitions
24 |
25 | 1.1 'Licence' means this CERN-OHL-P.
26 |
27 | 1.2 'Source' means information such as design materials or digital
28 | code which can be applied to Make or test a Product or to
29 | prepare a Product for use, Conveyance or sale, regardless of its
30 | medium or how it is expressed. It may include Notices.
31 |
32 | 1.3 'Covered Source' means Source that is explicitly made available
33 | under this Licence.
34 |
35 | 1.4 'Product' means any device, component, work or physical object,
36 | whether in finished or intermediate form, arising from the use,
37 | application or processing of Covered Source.
38 |
39 | 1.5 'Make' means to create or configure something, whether by
40 | manufacture, assembly, compiling, loading or applying Covered
41 | Source or another Product or otherwise.
42 |
43 | 1.6 'Notice' means copyright, acknowledgement and trademark notices,
44 | references to the location of any Notices, modification notices
45 | (subsection 3.3(b)) and all notices that refer to this Licence
46 | and to the disclaimer of warranties that are included in the
47 | Covered Source.
48 |
49 | 1.7 'Licensee' or 'You' means any person exercising rights under
50 | this Licence.
51 |
52 | 1.8 'Licensor' means a person who creates Source or modifies Covered
53 | Source and subsequently Conveys the resulting Covered Source
54 | under the terms and conditions of this Licence. A person may be
55 | a Licensee and a Licensor at the same time.
56 |
57 | 1.9 'Convey' means to communicate to the public or distribute.
58 |
59 |
60 | 2 Applicability
61 |
62 | 2.1 This Licence governs the use, copying, modification, Conveying
63 | of Covered Source and Products, and the Making of Products. By
64 | exercising any right granted under this Licence, You irrevocably
65 | accept these terms and conditions.
66 |
67 | 2.2 This Licence is granted by the Licensor directly to You, and
68 | shall apply worldwide and without limitation in time.
69 |
70 | 2.3 You shall not attempt to restrict by contract or otherwise the
71 | rights granted under this Licence to other Licensees.
72 |
73 | 2.4 This Licence is not intended to restrict fair use, fair dealing,
74 | or any other similar right.
75 |
76 |
77 | 3 Copying, Modifying and Conveying Covered Source
78 |
79 | 3.1 You may copy and Convey verbatim copies of Covered Source, in
80 | any medium, provided You retain all Notices.
81 |
82 | 3.2 You may modify Covered Source, other than Notices.
83 |
84 | You may only delete Notices if they are no longer applicable to
85 | the corresponding Covered Source as modified by You and You may
86 | add additional Notices applicable to Your modifications.
87 |
88 | 3.3 You may Convey modified Covered Source (with the effect that You
89 | shall also become a Licensor) provided that You:
90 |
91 | a) retain Notices as required in subsection 3.2; and
92 |
93 | b) add a Notice to the modified Covered Source stating that You
94 | have modified it, with the date and brief description of how
95 | You have modified it.
96 |
97 | 3.4 You may Convey Covered Source or modified Covered Source under
98 | licence terms which differ from the terms of this Licence
99 | provided that You:
100 |
101 | a) comply at all times with subsection 3.3; and
102 |
103 | b) provide a copy of this Licence to anyone to whom You
104 | Convey Covered Source or modified Covered Source.
105 |
106 |
107 | 4 Making and Conveying Products
108 |
109 | You may Make Products, and/or Convey them, provided that You ensure
110 | that the recipient of the Product has access to any Notices applicable
111 | to the Product.
112 |
113 |
114 | 5 DISCLAIMER AND LIABILITY
115 |
116 | 5.1 DISCLAIMER OF WARRANTY -- The Covered Source and any Products
117 | are provided 'as is' and any express or implied warranties,
118 | including, but not limited to, implied warranties of
119 | merchantability, of satisfactory quality, non-infringement of
120 | third party rights, and fitness for a particular purpose or use
121 | are disclaimed in respect of any Source or Product to the
122 | maximum extent permitted by law. The Licensor makes no
123 | representation that any Source or Product does not or will not
124 | infringe any patent, copyright, trade secret or other
125 | proprietary right. The entire risk as to the use, quality, and
126 | performance of any Source or Product shall be with You and not
127 | the Licensor. This disclaimer of warranty is an essential part
128 | of this Licence and a condition for the grant of any rights
129 | granted under this Licence.
130 |
131 | 5.2 EXCLUSION AND LIMITATION OF LIABILITY -- The Licensor shall, to
132 | the maximum extent permitted by law, have no liability for
133 | direct, indirect, special, incidental, consequential, exemplary,
134 | punitive or other damages of any character including, without
135 | limitation, procurement of substitute goods or services, loss of
136 | use, data or profits, or business interruption, however caused
137 | and on any theory of contract, warranty, tort (including
138 | negligence), product liability or otherwise, arising in any way
139 | in relation to the Covered Source, modified Covered Source
140 | and/or the Making or Conveyance of a Product, even if advised of
141 | the possibility of such damages, and You shall hold the
142 | Licensor(s) free and harmless from any liability, costs,
143 | damages, fees and expenses, including claims by third parties,
144 | in relation to such use.
145 |
146 |
147 | 6 Patents
148 |
149 | 6.1 Subject to the terms and conditions of this Licence, each
150 | Licensor hereby grants to You a perpetual, worldwide,
151 | non-exclusive, no-charge, royalty-free, irrevocable (except as
152 | stated in this section 6, or where terminated by the Licensor
153 | for cause) patent licence to Make, have Made, use, offer to
154 | sell, sell, import, and otherwise transfer the Covered Source
155 | and Products, where such licence applies only to those patent
156 | claims licensable by such Licensor that are necessarily
157 | infringed by exercising rights under the Covered Source as
158 | Conveyed by that Licensor.
159 |
160 | 6.2 If You institute patent litigation against any entity (including
161 | a cross-claim or counterclaim in a lawsuit) alleging that the
162 | Covered Source or a Product constitutes direct or contributory
163 | patent infringement, or You seek any declaration that a patent
164 | licensed to You under this Licence is invalid or unenforceable
165 | then any rights granted to You under this Licence shall
166 | terminate as of the date such process is initiated.
167 |
168 |
169 | 7 General
170 |
171 | 7.1 If any provisions of this Licence are or subsequently become
172 | invalid or unenforceable for any reason, the remaining
173 | provisions shall remain effective.
174 |
175 | 7.2 You shall not use any of the name (including acronyms and
176 | abbreviations), image, or logo by which the Licensor or CERN is
177 | known, except where needed to comply with section 3, or where
178 | the use is otherwise allowed by law. Any such permitted use
179 | shall be factual and shall not be made so as to suggest any kind
180 | of endorsement or implication of involvement by the Licensor or
181 | its personnel.
182 |
183 | 7.3 CERN may publish updated versions and variants of this Licence
184 | which it considers to be in the spirit of this version, but may
185 | differ in detail to address new problems or concerns. New
186 | versions will be published with a unique version number and a
187 | variant identifier specifying the variant. If the Licensor has
188 | specified that a given variant applies to the Covered Source
189 | without specifying a version, You may treat that Covered Source
190 | as being released under any version of the CERN-OHL with that
191 | variant. If no variant is specified, the Covered Source shall be
192 | treated as being released under CERN-OHL-S. The Licensor may
193 | also specify that the Covered Source is subject to a specific
194 | version of the CERN-OHL or any later version in which case You
195 | may apply this or any later version of CERN-OHL with the same
196 | variant identifier published by CERN.
197 |
198 | 7.4 This Licence shall not be enforceable except by a Licensor
199 | acting as such, and third party beneficiary rights are
200 | specifically excluded.
201 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### grumpy
2 |
3 | 28 key (3-row) angled unibody keyboard with col stagger
4 |
5 |
6 |
7 | ## Features
8 |
9 | ###### MX Xiao-Version:
10 |
11 | - spacing: MX
12 | - case: open bottom (3dp)
13 | - Hotswap sockets (MX)
14 | - Seeed Xiao Controller
15 | - RP2040 (w/ QMK, Vial)
16 | - BLE (w/ZMK)
17 | - SAMD21 (should work, don't have one to test)
18 | - gerber and case files are supplied (kicad files, stl as well as cadquery files)
19 | - completely open source, permissive license ([CERN-OHL-P](https://cern-ohl.web.cern.ch/home))
20 |
21 | ###### MX/ChocV2 CH552T-Version:
22 |
23 | - spacing: MX
24 | - case: top w/ bottom plate (top and bottom 3dp)
25 | - Hotswap sockets (MX and Choc V1/V2)
26 | - CH552T Controller (w/ FAK firmware)
27 | - gerber and case files are supplied (kicad files, stl as well as cadquery files)
28 | - completely open source, permissive license ([CERN-OHL-P](https://cern-ohl.web.cern.ch/home))
29 |
30 | ###### ChocV1 Xiao-Version:
31 |
32 | - spacing: choc
33 | - case: top w/ bottom plate (top 3dp/cnc, bottom 3dp)
34 | - Hotswap sockets (Choc V1)
35 | - Seeed Xiao Controller
36 | - RP2040 (w/ QMK, Vial)
37 | - BLE (w/ZMK)
38 | - SAMD21 (should work, don't have one to test)
39 | - gerber and case files are supplied (kicad files, stl as well as cadquery files)
40 | - completely open source, permissive license ([CERN-OHL-P](https://cern-ohl.web.cern.ch/home))
41 |
42 | ## Want one?
43 |
44 | All production files you need to build your own board can be found [here](./prod/).
45 |
46 | The case has no bottom and ends right below the HS Sockets. You may either use it as is, but preferably use some 2-3mm self-adhesive neopren on the whole pcb. The case will be hard to print on a FDM Printer, so maybe use a service to print it in resin or nylon.
47 |
48 | Apart from the pcb and optionally a case you need:
49 |
50 | ###### Xiao-Version
51 |
52 | - 28 hotswap sockets
53 | - 28 diodes (1N4148 int SOT-123)
54 | - 28 of your favourite switches
55 | - 1 Controller
56 |
57 | ###### CH552T-Version:
58 |
59 | - 28 hotswap sockets
60 | - 28 diodes (1N4148 int SOT-123)
61 | - 28 of your favourite switches
62 | - 1x CH552T (TSSOP-20)
63 | - 1x USBLC6-2SC6 (SOT-23-6)
64 | - 1x 10kOhm resistor (SMD 0603)
65 | - 2x 5.1kOhm resistors (SMD 0603)
66 | - 2x 100nF capacitors (SMD 0603)
67 | - 1x USB Connector C-Type, 12 pin/16pin, mid-mount (1.6mm)
68 |
69 | ### firmware
70 |
71 | ###### Xiao-Version:
72 |
73 | firmware configs for qmk and vial can be found in the [firmware folder](./firmware).
74 |
75 | The first time the pcb is plugged in, the bootloader will provide a drive to upload the firmware file.
76 |
77 | ###### CH552T-Version:
78 |
79 | firmware config for FAK can be found [here](https://github.com/weteor/fak-config/tree/main/keyboards/grumpy). Please also see [FAK-Firmware site](https://github.com/semickolon/fak) for more information
80 |
81 | Bootloader should be available on first plugins until firmware is written. After that either use the firmware BOOT to go into bootloader, or hold the boot button on the pcb pressed while pluggin in the usb cable.
82 |
83 | ## the rest
84 |
85 | Everything in this repository is free to use however you might see fit. If you want to support me and my projects, please consider linking back to this repository if you build/change/use anything.
86 |
87 | If you would like to send me a tip, you could do it [here](https://ko-fi.com/weteor) (Please don't feel like you have to).
88 |
89 | ## more pictures
90 |
91 | 
92 | 
93 |
--------------------------------------------------------------------------------
/case/grumpy_case_build123d.py:
--------------------------------------------------------------------------------
1 | from build123d import *
2 |
3 | import cadquery as cq
4 | import cadquery.selectors as cqs
5 | from cadquery import NearestToPointSelector, exporters as exp
6 |
7 | # CONSTANTS
8 | spacing = 19.05 # MX-Spacing
9 | holeSize = 14 # Platehole size
10 | pcbThickness = 1.6 # PCB Thickness
11 | hsThickness = 1.85 # HS Socket Thickness below PCB
12 | hsSafety = 1 # extra space to hide HS Sockets
13 |
14 | # CASE PARAMETERS
15 | keySafety = 0.5 # extra space between keycap and case
16 | spaceAbovePCB = 0.25 # space between PCB and Plate.
17 | plateHeight = 5 - spaceAbovePCB # heigth of plate
18 | colStagger = 0.25 * spacing # stagger between cols
19 |
20 |
21 | heightAbovePlate = 8.5 # height of case rim measured from plate
22 | heightBelowPlate = pcbThickness+hsThickness+hsSafety # height of rim hiding pcb and Sockets
23 |
24 | overallHeight = heightAbovePlate+heightBelowPlate+plateHeight
25 |
26 | outerRad = 5 # radius of outer edge fillets
27 | outerRadSmall = 1.5 # radius of other outline fillets
28 |
29 | wallWidth = 7.5 # Wall Width (in effect only left and right)
30 | lWallWidth = 3 # min Wallthickness for keys outside of case body
31 |
32 | rectOffset = 0.125*19.05-colStagger/2 # rectangular case body y offset
33 | rectHeight = 3*spacing+2*lWallWidth+colStagger # rectangular case y height
34 |
35 |
36 | caseWidth = 10 *spacing + 2*wallWidth # absolute case width
37 | caseHeight = 3*spacing + 2*wallWidth + 3*colStagger # absolute case height
38 |
39 | handAngle = 14 # degrees of rotation for each hand
40 |
41 | centerInset = 2 #how much lower the inner cutout should be
42 |
43 | def getRowPos(rowOffset=0):
44 | """ returns x y coordinate tuple for each right hand switch of the selected row
45 |
46 | :param rowOffset: row number counted from the top
47 | :return list of coordinate tuples
48 | """
49 |
50 | topSwitchY = caseHeight/2-wallWidth-spacing/2-rowOffset*spacing
51 |
52 |
53 | points = [
54 | ( 1.5 * spacing, topSwitchY - 2 * colStagger ),
55 | ( 2.5 * spacing, topSwitchY - 1 * colStagger ),
56 | ( 3.5 * spacing, topSwitchY - 2 * colStagger ),
57 | ]
58 | if (rowOffset > 0):
59 | # points.append(( 4.5 * spacing, topSwitchY - 3.5 * colStagger ) )
60 | points.append(( 4.5 * spacing, topSwitchY - 4 * colStagger ) )
61 |
62 | if (rowOffset < 2):
63 | points.append(( 0.5 * spacing, topSwitchY - 4 * colStagger ))
64 |
65 |
66 |
67 | return points
68 |
69 | def getSwitchPositions(keys=True):
70 | """ collects all positions for the first three rows
71 |
72 | :param keys: if true returns alphakey positions, if false returns thumbkeyposition
73 | :return list of coordinate tuples
74 | """
75 | if keys:
76 | return getRowPos(0) + getRowPos(1) + getRowPos(2)
77 | else:
78 | return [( 0.25 * spacing, caseHeight/2-wallWidth-spacing/2-2*spacing - 4 * colStagger )]
79 |
80 | def getAlphaKeyPos():
81 | return getSwitchPositions(True)
82 |
83 | def getThumbKeyPos():
84 | return getSwitchPositions(False)
85 |
86 | def getAllKeyPos():
87 | return getAlphaKeyPos() + getThumbKeyPos()
88 |
89 | def getInnerEdges(object):
90 | obj = ( object.edges()
91 | .filter_by(Axis.Z)
92 | .filter_by(
93 | lambda v: v.center().X > 2 and v.center().X < (caseWidth/2-20))
94 | )
95 | return obj;
96 |
97 |
98 | ## ------------------------------------------------------------------------------
99 |
100 | with BuildSketch() as SketchOutline:
101 | # outline shapes for alpha and thumbs
102 | with Locations(getAlphaKeyPos()):
103 | Rectangle(spacing+2*lWallWidth, spacing+2*lWallWidth)
104 | with Locations(getThumbKeyPos()):
105 | Rectangle(spacing*1.5+2*lWallWidth, spacing+2*lWallWidth)
106 | with Locations((caseWidth/4-7+5,-8)):
107 | Rectangle(caseWidth/2+10, 2*spacing+2*wallWidth+2.5+10, rotation=-handAngle)
108 | with Locations((-21.2,5)):
109 | Rectangle(40-lWallWidth, 46.9, mode=Mode.SUBTRACT)
110 |
111 | with BuildSketch() as CaseOutline:
112 | with Locations((4.33,0,0)):
113 | add(SketchOutline.sketch, rotation=handAngle)
114 | with Locations((-20,0)):
115 | Rectangle(40,caseHeight*2, mode=Mode.SUBTRACT)
116 |
117 | with BuildSketch() as CaseOutlineFilletOuter:
118 | add(CaseOutline.sketch)
119 | fillet(CaseOutlineFilletOuter.edges().sort_by(Axis.X)[-1].vertices(), outerRad)
120 |
121 | with BuildSketch() as KeyCutout:
122 | with Locations(getAlphaKeyPos()):
123 | Rectangle(spacing+keySafety, spacing+keySafety)
124 | with Locations(getThumbKeyPos()):
125 | Rectangle(1.5*spacing+keySafety, spacing+keySafety)
126 | fillet(KeyCutout.vertices().sort_by(Axis.X)[4:], 1)
127 | fillet(KeyCutout.vertices().group_by(Axis.X)[0].sort_by(Axis.Y)[0], 1)
128 | fillet(KeyCutout.vertices().group_by(Axis.X)[2].sort_by(Axis.Y)[0], 1)
129 |
130 | with BuildSketch() as USBCutoutOuter:
131 | Rectangle(13,7)
132 | fillet(USBCutoutOuter.vertices(), 2.5)
133 |
134 | with BuildSketch() as USBCutoutInner:
135 | Rectangle(10,5)
136 | fillet(USBCutoutInner.vertices(), 1.5)
137 |
138 | with BuildSketch() as USBCutoutOuterStraight:
139 | with Locations((0,-1.5)):
140 | Rectangle(12.5,10.5)
141 | fillet(USBCutoutOuterStraight.vertices().group_by(Axis.Y)[-1], 2.5)
142 | ## ------------------------------------------------------------------------------
143 |
144 | with BuildPart() as FullCase:
145 |
146 | # Build Case Bottom below Plate
147 | with BuildPart() as Bottom:
148 | add(CaseOutlineFilletOuter.sketch)
149 | extrude(amount=heightBelowPlate)
150 | # select faces that should not be offset = open faces
151 | remFaces = Bottom.faces().sort_by(Axis.Z)[0]
152 | remFaces += Bottom.faces().sort_by(Axis.Z)[-1]
153 | remFaces += Bottom.faces().sort_by(Axis.X)[:5].sort_by(Axis.Y)[-4:]
154 | # create shell
155 | offset(amount=-lWallWidth, openings=remFaces, kind=Kind.INTERSECTION)
156 | fillet(getInnerEdges(Bottom), outerRadSmall)
157 |
158 | # Build Plate part
159 | with BuildPart(Plane(origin=(0,0,heightBelowPlate))) as Plate:
160 | add(CaseOutlineFilletOuter.sketch)
161 | extrude(amount=plateHeight)
162 | fillet(getInnerEdges(Plate), outerRadSmall)
163 | # work plane for further operations
164 | wPlane = Plane(origin=(4.33,0,heightBelowPlate)).rotated((0,0,handAngle))
165 | # add cutouts for switch clips
166 | with BuildSketch(wPlane) :
167 | with Locations(getAllKeyPos()):
168 | Rectangle(5,holeSize+2)
169 | extrude(amount=plateHeight-1.5, mode=Mode.SUBTRACT)
170 | # add switch cutout
171 | with BuildSketch(wPlane) :
172 | with Locations(getAllKeyPos()):
173 | Rectangle(holeSize,holeSize)
174 | extrude(amount=plateHeight, mode=Mode.SUBTRACT)
175 |
176 | # Build Top part
177 | with BuildPart(Plane(origin=(0,0,heightBelowPlate+plateHeight))) as Top:
178 | add(CaseOutlineFilletOuter.sketch)
179 | extrude(amount=heightAbovePlate)
180 | fillet(getInnerEdges(Top), outerRadSmall)
181 | # work plane for further operations
182 | wPlane = Plane(origin=(4.33,0,heightBelowPlate+plateHeight)).rotated((0,0,handAngle))
183 | # add keycap cutout
184 | with BuildSketch(wPlane) :
185 | add(KeyCutout.sketch)
186 | extrude(amount=heightAbovePlate, mode=Mode.SUBTRACT)
187 | # lower center cutout
188 | extrude(Top.faces().filter_by(Axis.Z).group_by(Axis.Z)[-1].sort_by(Axis.X)[0],
189 | amount=-centerInset, mode=Mode.SUBTRACT)
190 | show_object(Bottom)
191 | show_object(Plate)
192 | show_object(Top)
193 |
194 | mirror(FullCase.part, about=Plane.YZ)
195 |
196 | # add fillets on mirrored edges
197 | fillet(FullCase.edges()
198 | .filter_by(Axis.Z)
199 | .filter_by(
200 | lambda v: (v.center().X < 0.05 and v.center().X > -0.05) and
201 | ((v.center().Y < 0 and v.center().Y > -25) or v.center().Y > 7)), 1)
202 | # add top groove
203 | groove_wire = FullCase.faces().filter_by(Axis.Z).group_by(Axis.Z)[-2][0].outer_wire() #wires().sort_by(SortBy.LENGTH)[-1]
204 | groove_wire = groove_wire.rotate(Axis.Z, 180).translate((0,33,centerInset))
205 | extrude(Face(groove_wire), amount=-2, mode=Mode.SUBTRACT)
206 |
207 | # fillet top groove edges
208 | groove_fil_edges = FullCase.edges(Select.LAST).group_by(Axis.Y)[-1].sort_by(Axis.X)[1:-1]
209 | fillet(groove_fil_edges, outerRadSmall)
210 |
211 | # outline Chamfer
212 | main_top_face = FullCase.faces().filter_by(Axis.Z).group_by(Axis.Z)[-1].sort_by(Axis.X)[0]
213 | chamfer(main_top_face.outer_wire().edges(), 1)
214 | chamfer(main_top_face.inner_wires().edges(), 0.5)
215 |
216 | inset_face = FullCase.faces().filter_by(Axis.Z).group_by(Axis.Z)[-2].sort_by(Axis.Y)[0]
217 | chamfer(inset_face.edges(), 0.5)
218 |
219 | bottom_face = FullCase.faces().filter_by(Axis.Z).group_by(Axis.Z)[0][0]
220 | chamfer(bottom_face.outer_wire().edges(), 0.7)
221 |
222 | # usb cutout
223 | usb_face = FullCase.faces().filter_by(Axis.Y).group_by(Axis.Y)[-1].sort_by(SortBy.LENGTH)[-1]
224 | usb_plane = Plane(usb_face).shift_origin((usb_face.center().X,usb_face.center().Y,heightBelowPlate))
225 | with BuildSketch(usb_plane):
226 | add(USBCutoutInner.sketch)
227 | extrude(amount=-5, mode=Mode.SUBTRACT)
228 |
229 | with BuildSketch(usb_plane):
230 | add(USBCutoutOuterStraight.sketch, rotation=180)
231 | extrude(amount=-1, mode=Mode.SUBTRACT)
232 |
233 | inner_usb_edges = FullCase.faces(Select.LAST).filter_by(Axis.Y).sort_by(Axis.Y)[0].inner_wires().edges()
234 | outer_usb_edges = FullCase.edges(Select.LAST).group_by(Axis.Y)[-1].sort_by(Axis.X)[1:-1]
235 |
236 | chamfer(inner_usb_edges, 0.75)
237 | chamfer(outer_usb_edges, 0.75)
238 |
239 | show_object(FullCase, name="full" )
--------------------------------------------------------------------------------
/case/grumpy_case_cadquery.py:
--------------------------------------------------------------------------------
1 | import cadquery as cq
2 | import cadquery.selectors as cqs
3 | from cadquery import NearestToPointSelector, exporters as exp
4 |
5 | # CONSTANTS
6 | spacing = 19.05 # MX-Spacing
7 | holeSize = 14 # Platehole size
8 | pcbThickness = 1.6 # PCB Thickness
9 | hsThickness = 1.85 # HS Socket Thickness below PCB
10 | hsSafety = 1 # extra space to hide HS Sockets
11 |
12 | # CASE PARAMETERS
13 | keySafety = 0.5 # extra space between keycap and case
14 | spaceAbovePCB = 0.25 # space between PCB and Plate.
15 | plateHeight = 5 - spaceAbovePCB # heigth of plate
16 | colStagger = 0.25 * spacing # stagger between cols
17 |
18 |
19 | heightAbovePlate = 8.5 # height of case rim measured from plate
20 | heightBelowPlate = pcbThickness+hsThickness+hsSafety # height of rim hiding pcb and Sockets
21 |
22 | overallHeight = heightAbovePlate+heightBelowPlate+plateHeight
23 |
24 | outerRad = 5 # radius of outer edge fillets
25 | outerRadSmall = 1.5 # radius of other outline fillets
26 |
27 | wallWidth = 7.5 # Wall Width (in effect only left and right)
28 | lWallWidth = 3 # min Wallthickness for keys outside of case body
29 |
30 | rectOffset = 0.125*19.05-colStagger/2 # rectangular case body y offset
31 | rectHeight = 3*spacing+2*lWallWidth+colStagger # rectangular case y height
32 |
33 |
34 | caseWidth = 10 *spacing + 2*wallWidth # absolute case width
35 | caseHeight = 3*spacing + 2*wallWidth + 3*colStagger # absolute case height
36 |
37 | handAngle = 14 # degrees of rotation for each hand
38 |
39 | centerInset = 2 #how much lower the inner cutout should be
40 |
41 | ## ------------------------------------------------------------------------------
42 |
43 | def getRowPos(rowOffset=0):
44 | """ returns x y coordinate tuple for each right hand switch of the selected row
45 |
46 | :param rowOffset: row number counted from the top
47 | :return list of coordinate tuples
48 | """
49 |
50 | topSwitchY = caseHeight/2-wallWidth-spacing/2-rowOffset*spacing
51 |
52 |
53 | points = [
54 | ( 1.5 * spacing, topSwitchY - 2 * colStagger ),
55 | ( 2.5 * spacing, topSwitchY - 1 * colStagger ),
56 | ( 3.5 * spacing, topSwitchY - 2 * colStagger ),
57 | ]
58 | if (rowOffset > 0):
59 | # points.append(( 4.5 * spacing, topSwitchY - 3.5 * colStagger ) )
60 | points.append(( 4.5 * spacing, topSwitchY - 4 * colStagger ) )
61 |
62 | if (rowOffset < 2):
63 | points.append(( 0.5 * spacing, topSwitchY - 4 * colStagger ))
64 |
65 |
66 |
67 | return points
68 |
69 | def getSwitchPositions(keys=True):
70 | """ collects all positions for the first three rows
71 |
72 | :param keys: if true returns alphakey positions, if false returns thumbkeyposition
73 | :return list of coordinate tuples
74 | """
75 | if keys:
76 | return getRowPos(0) + getRowPos(1) + getRowPos(2)
77 | else:
78 | return [( 0.25 * spacing, caseHeight/2-wallWidth-spacing/2-2*spacing - 4 * colStagger )]
79 |
80 | def getAlphaKeyPos():
81 | return getSwitchPositions(True)
82 |
83 | def getThumbKeyPos():
84 | return getSwitchPositions(False)
85 |
86 | def getAllKeyPos():
87 | return getAlphaKeyPos() + getThumbKeyPos()
88 |
89 | ## ------------------------------------------------------------------------------
90 |
91 | # CADQUERY EXTENSIONS
92 |
93 | def _rotateAndClean(self, inverseCut = False):
94 | if inverseCut:
95 | cutDir = -1
96 | else:
97 | cutDir = 1
98 |
99 | obj = (
100 | self.rotate((0,0,0),(0,0,1),handAngle)
101 | .translate((4.33,0,0))
102 | .moveTo(-20,0)
103 | .rect(40,caseHeight*2)
104 | .cutBlind(cutDir * overallHeight)
105 | )
106 | return obj
107 |
108 |
109 | def _filletOuterEdges(self):
110 | # fillet outmost edges
111 | obj = (
112 | self.edges("|Z")
113 | .edges(cqs.BoxSelector( (caseWidth/2, caseHeight, 0), (caseWidth, -caseHeight, overallHeight) ))
114 | .fillet(outerRad)
115 | )
116 | return obj
117 |
118 |
119 | def _filletInnerEdges(self):
120 | # fillet inner edges
121 | obj = (
122 | self.edges("|Z")
123 | .edges(cqs.BoxSelector( (2, caseHeight, 0), (caseWidth/2-20, -caseHeight, overallHeight) ))
124 | .fillet(outerRadSmall)
125 | )
126 | return obj
127 |
128 |
129 | def _caseShape(self, height, filletOuter=True, filletInner=True):
130 | obj = (
131 | self.placeSketch(so)
132 | .extrude(height)
133 | .rotateAndClean()
134 | )
135 | if filletOuter:
136 | obj = obj.filletOuterEdges()
137 |
138 | if filletInner:
139 | # fillet inner edges
140 | obj = obj.filletInnerEdges()
141 | return obj
142 |
143 | cq.Workplane.filletOuterEdges = _filletOuterEdges # selects the ">X" edges and fillets them
144 | cq.Workplane.filletInnerEdges = _filletInnerEdges # selects all edges except ">X" and X<0 and fillets them
145 | cq.Workplane.rotateAndClean = _rotateAndClean # rotates and translates the object by hand spacing and angle
146 | cq.Workplane.caseShape = _caseShape # creates the base Case outline with given height and optional inner and outer fillet
147 |
148 | ## ------------------------------------------------------------------------------
149 |
150 | # SKETCH FOR OUTLINE WITHOUT FILLETS
151 | so = (
152 | cq.Sketch()
153 | # create outline shape for all keys w/ min. wall widht
154 | .push(getAlphaKeyPos())
155 | .rect(spacing+2*lWallWidth, spacing+2*lWallWidth)
156 | .reset()
157 | .push(getThumbKeyPos())
158 | .rect(spacing*1.5+2*lWallWidth,spacing+2*lWallWidth)
159 | .reset()
160 | # add rectangular outline to key shape
161 | .push([(caseWidth/4-7+5,-8)])
162 | .rect(caseWidth/2+10, 2*spacing+2*wallWidth+2.5+10, angle=-handAngle)
163 | # readd middle cutout
164 | .push([(-21.2,5)])
165 | .rect(40-lWallWidth, 46.9, mode='s')
166 | .clean()
167 | )
168 |
169 |
170 | # SKETCH FOR SWITCH CUTOUTS IN TOP PART
171 | si = (
172 | cq.Sketch()
173 | # create shape for all keys w/ keysafety added
174 | .push(getAlphaKeyPos())
175 | .rect(spacing+keySafety, spacing+keySafety)
176 | .reset()
177 | .push(getThumbKeyPos())
178 | .rect(spacing*1.5+keySafety, spacing+keySafety)
179 | .clean()
180 | # fillet all edges except the leftmost, which will later be on the mirror plane
181 | .reset()
182 | .vertices(cqs.BoxSelector( (2, caseHeight/2, 10), (caseWidth/2+2, -caseHeight/2, -10) ))
183 | .fillet(1)
184 | .reset()
185 | .vertices(cqs.BoxSelector( (-2, 0, -1), (2, -caseHeight, 1) ))
186 | .fillet(1)
187 | )
188 |
189 | # SKETCH FOR INNER USB CUTOUT
190 | su = (cq.Sketch()
191 | .rect(10,5)
192 | .reset()
193 | .vertices()
194 | .fillet(1.5)
195 | )
196 | # SKETCH FOR OUTER USB CUTOUT
197 | suo = (cq.Sketch()
198 | .rect(13,7)
199 | .reset()
200 | .vertices()
201 | .fillet(2.5)
202 | )
203 |
204 | # SKETCH FOR OUTER USB CUTOUT w/ STRAIGHT BOTTOM
205 | suo_down = (cq.Sketch()
206 | .push([(0,-1.5)])
207 | .rect(12.5,10.5)
208 | .reset()
209 | .vertices(">Y")
210 | .fillet(2.5)
211 | )
212 |
213 | ## ------------------------------------------------------------------------------
214 |
215 | # BOTTOM
216 | bottom = (
217 | cq.Workplane("XY")
218 | .caseShape(heightBelowPlate, filletInner=False)
219 | # hollow out bottom, so only the rim remains
220 | .faces(cqs.SumSelector(cqs.StringSyntaxSelector("Z or Z").workplane().transformed(offset=(4.33,0,-1.5),rotate=(0,0,handAngle))
232 | .pushPoints(getAllKeyPos())
233 | .rect(5,holeSize+2)
234 | .cutBlind(-plateHeight)
235 | # add switch cutouts
236 | .faces(">Z").workplane().transformed(rotate=(0,0,handAngle))
237 | .pushPoints(getAllKeyPos())
238 | .rect(holeSize,holeSize)
239 | .cutBlind(-overallHeight)
240 | )
241 |
242 | # TOP
243 | top = (
244 | cq.Workplane("XY", origin=(0,0,heightBelowPlate+plateHeight))
245 | .caseShape(heightAbovePlate)
246 | .faces(">Z").workplane().transformed(offset=(4.33,0,0),rotate=(0,0,handAngle))
247 | # remove keycutout
248 | .placeSketch(si)
249 | .cutBlind(-heightAbovePlate)
250 | # lower middle cutout
251 | .faces(">Z")
252 | .faces(cqs.NearestToPointSelector((0,-20, overallHeight))).wires().toPending()
253 | .cutBlind(-centerInset)
254 | )
255 |
256 | # MERGE ALL PARTS
257 | half = (
258 | bottom.union(plate.union(top))
259 | )
260 |
261 | # CREATE FULL CASE
262 | full = (
263 | half.mirror("YZ",union=True)
264 | # fillet on X=0
265 | .edges("|Z")
266 | .edges(cqs.BoxSelector( (-1, caseHeight, heightBelowPlate+plateHeight+1), (1, -caseHeight*2, overallHeight) ))
267 | .fillet(1)
268 | # add top groove
269 | .faces(cqs.NearestToPointSelector((0,-10, overallHeight))).wires().translate((0,42+0.1*lWallWidth, centerInset)).item(1).rotateAboutCenter((0,0,1), 180).toPending()
270 | .cutBlind(-2)
271 | # round bottom near thumbs
272 | .edges("|Z")
273 | .edges(cqs.NearestToPointSelector((0,-20,0)))
274 | .fillet(2)
275 | # round groove
276 | .edges("|Z")
277 | .edges(cqs.NearestToPointSelector((0,15,overallHeight)))
278 | .fillet(0.5)
279 | .faces("|Y")
280 | .edges(cqs.BoxSelector( (-20, 10, overallHeight-centerInset), (20, 120, overallHeight) ))
281 | .fillet(outerRadSmall)
282 | # add chamfer to outline
283 | .faces(">Z")
284 | .faces(cqs.NearestToPointSelector((0,caseHeight/2, overallHeight)))
285 | .wires().item(0)
286 | .chamfer(1)
287 | # add chamfer to keycutout
288 | .faces(">Z")
289 | .faces(cqs.NearestToPointSelector((0,caseHeight/2, overallHeight)))
290 | .wires().item(1)
291 | .chamfer(0.5)
292 | # add chamfer to middle cutout
293 | .faces("|Z")
294 | .faces(cqs.NearestToPointSelector((0,-10, overallHeight-centerInset)))
295 | .wires().item(0)
296 | .chamfer(0.5)
297 | .faces(cqs.NearestToPointSelector((0,-10, overallHeight-centerInset)))
298 | .wires().item(1)
299 | .chamfer(0.5 )
300 | # add chamfer to bottom rim
301 | .faces(" 0):
67 | points.append(( 4.5 * spacing_x, topSwitchY - 3.5 * colStagger ) )
68 | # points.append(( 4.5 * spacing, topSwitchY - 4 * colStagger ) )
69 |
70 | if (rowOffset < 2):
71 | points.append(( 0.5 * spacing_x, topSwitchY - 4 * colStagger ))
72 | return points
73 |
74 | def getSwitchPositions(keys=True):
75 | """ collects all positions for the first three rows
76 |
77 | :param keys: if true returns alphakey positions, if false returns thumbkeyposition
78 | :return list of coordinate tuples
79 | """
80 | if keys:
81 | return getRowPos(0) + getRowPos(1) + getRowPos(2)
82 | else:
83 | return [( 0.25 * spacing_x, caseHeight/2-wallWidth-spacing_y/2-2*spacing_y - 4 * colStagger )]
84 |
85 | def getAlphaKeyPos():
86 | return getSwitchPositions(True)
87 |
88 | def getThumbKeyPos():
89 | return getSwitchPositions(False)
90 |
91 | def getAllKeyPos():
92 | return getAlphaKeyPos() + getThumbKeyPos()
93 |
94 | def getAllKeyPosMir():
95 | switchPos = list(map(lambda pnt: (-1*pnt[0], pnt[1]), getAlphaKeyPos() + getThumbKeyPos()))
96 | return switchPos
97 |
98 | def getInnerEdges(object):
99 | obj = ( object.edges()
100 | .filter_by(Axis.Z)
101 | .filter_by(
102 | lambda v: v.center().X > 2 and v.center().X < (caseWidth/2-20))
103 | )
104 | return obj;
105 |
106 | # %%
107 | ## ------------------------------------------------------------------------------
108 |
109 | with BuildSketch() as SketchOutline:
110 | # outline shapes for alpha and thumbs
111 | with Locations(getAlphaKeyPos()):
112 | Rectangle(spacing_x+2*lWallWidth, spacing_y+2*lWallWidth)
113 | with Locations(getThumbKeyPos()):
114 | Rectangle(spacing_x*1.5+2*lWallWidth, spacing_y+2*lWallWidth)
115 | with Locations((caseWidth/4-7+5,-8)):
116 | Rectangle(caseWidth/2+10, 2*spacing_y+2*wallWidth+2.5+10, rotation=-handAngle)
117 | with Locations((-21.5,7.3)):
118 | Rectangle(40-lWallWidth, 46.9, mode=Mode.SUBTRACT)
119 |
120 | with BuildSketch() as CaseOutline:
121 | with Locations((part_x_offset,0,0)):
122 | add(SketchOutline.sketch, rotation=handAngle)
123 | with Locations((-20,0)):
124 | Rectangle(40,caseHeight*2, mode=Mode.SUBTRACT)
125 |
126 | with BuildSketch() as CaseOutlineFilletOuter:
127 | add(CaseOutline.sketch)
128 | fillet(CaseOutlineFilletOuter.edges().sort_by(Axis.X)[-1].vertices(), outerRad)
129 |
130 | with BuildSketch() as KeyCutout:
131 | with Locations(getAlphaKeyPos()):
132 | Rectangle(spacing_x+keySafety, spacing_y+keySafety)
133 | with Locations(getThumbKeyPos()):
134 | Rectangle(1.5*spacing_x+keySafety, spacing_y+keySafety)
135 | fillet(KeyCutout.vertices().sort_by(Axis.X)[4:], 1)
136 | fillet(KeyCutout.vertices().group_by(Axis.X)[0].sort_by(Axis.Y)[0], 1)
137 | fillet(KeyCutout.vertices().group_by(Axis.X)[2].sort_by(Axis.Y)[0], 1)
138 |
139 | with BuildSketch() as USBCutoutInner:
140 | Rectangle(11.5,6.5+usbStraightExtra)
141 | fillet(USBCutoutInner.vertices(), 1.5)
142 |
143 | with BuildSketch() as USBCutoutOuter:
144 | with Locations((0,-1.5)):
145 | Rectangle(12.5,10.5)
146 | fillet(USBCutoutOuter.vertices().group_by(Axis.Y)[-1], 2)
147 |
148 | with BuildSketch() as BottomKeyCutout:
149 | with Locations([(-5.5,0), (5.5,0)]):
150 | Circle(1.25)
151 | with Locations((0,0)):
152 | Circle(2)
153 | with Locations([(1.3-0.5, -5-0.5,9+1)]):
154 | Rectangle(8.6,6.5)
155 | with Locations([(-5-1.3+0.5,-3.7)]):
156 | Rectangle(8.6,5.5)
157 | with Locations((-5-1.3+1.25+2/2,-2)):
158 | Rectangle(7.6+2.5+2,4)
159 |
160 | with BuildSketch(Plane.XY.rotated((0,0,180))) as BottomKeyCutoutRot:
161 | add(BottomKeyCutout)
162 | # %%
163 | ## ------------------------------------------------------------------------------
164 |
165 | bottomPlateWire = 0
166 |
167 | with BuildPart() as CaseHalf:
168 |
169 | # Build Case Bottom below Plate
170 | with BuildPart() as Bottom:
171 | add(CaseOutlineFilletOuter.sketch)
172 | extrude(amount=heightBelowPlate)
173 | # select faces that should not be offset = open faces
174 | remFaces = Bottom.faces().sort_by(Axis.Z)[0]
175 | remFaces += Bottom.faces().sort_by(Axis.Z)[-1]
176 | remFaces += Bottom.faces().sort_by(Axis.X)[:5].sort_by(Axis.Y)[-4:]
177 | # create shell
178 | offset(amount=-lWallWidth, openings=remFaces, kind=Kind.INTERSECTION)
179 | fillet(getInnerEdges(Bottom), outerRadSmall)
180 |
181 | # Build Plate part
182 | with BuildPart(Plane(origin=(0,0,heightBelowPlate))) as Plate:
183 | add(CaseOutlineFilletOuter.sketch)
184 | extrude(amount=plateHeight)
185 | fillet(getInnerEdges(Plate), outerRadSmall)
186 | # work plane for further operations
187 | wPlane = Plane(origin=(part_x_offset,0,heightBelowPlate)).rotated((0,0,handAngle))
188 | # add cutouts for switch clips
189 | with BuildSketch(wPlane) :
190 | with Locations(getAllKeyPos()):
191 | RectangleRounded(holeSize+2,holeSize, holeFillet)
192 | extrude(amount=plateHeight-plateClipHeight, mode=Mode.SUBTRACT)
193 | # add switch cutout
194 | with BuildSketch(wPlane) :
195 | with Locations(getAllKeyPos()):
196 | RectangleRounded(holeSize,holeSize,holeFillet)
197 | extrude(amount=plateHeight, mode=Mode.SUBTRACT)
198 |
199 | # Build Top part
200 | with BuildPart(Plane(origin=(0,0,heightBelowPlate+plateHeight))) as Top:
201 | add(CaseOutlineFilletOuter.sketch)
202 | extrude(amount=heightAbovePlate)
203 | fillet(getInnerEdges(Top), outerRadSmall)
204 | # work plane for further operations
205 | wPlane = Plane(origin=(part_x_offset,0,heightBelowPlate+plateHeight)).rotated((0,0,handAngle))
206 | # add keycap cutout
207 | with BuildSketch(wPlane) :
208 | add(KeyCutout.sketch)
209 | extrude(amount=heightAbovePlate, mode=Mode.SUBTRACT)
210 | # lower center cutout
211 | extrude(Top.faces().filter_by(Axis.Z).group_by(Axis.Z)[-1].sort_by(Axis.X)[0],
212 | amount=-centerInset, mode=Mode.SUBTRACT)
213 | #show_object(Bottom)
214 | #show_object(Plate)
215 | #show_object(Top)
216 | # %%
217 |
218 | with BuildPart() as CaseFull:
219 | add(CaseHalf.part)
220 | mirror(CaseHalf.part, about=Plane.YZ)
221 |
222 | # add fillets on mirrored edges
223 | fillet(CaseFull.edges()
224 | .filter_by(Axis.Z)
225 | .filter_by(
226 | lambda v: (v.center().X < 0.05 and v.center().X > -0.05) and
227 | ((v.center().Y < 0 and v.center().Y > -19) or v.center().Y > 7)), 1)
228 |
229 | # add fillets on mirrored edges
230 | fillet(CaseFull.edges()
231 | .filter_by(Axis.Z)
232 | .group_by(Axis.Z)[-1]
233 | .filter_by(
234 | lambda v: (v.center().X < 0.05 and v.center().X > -0.05) and
235 | ((v.center().Y < -19 and v.center().Y > -25) or v.center().Y > 7)), 1)
236 |
237 | # add fillets on mirrored edges
238 | fillet(CaseFull.edges()
239 | .filter_by(Axis.Z)
240 | .group_by(Axis.Z)[0]
241 | .filter_by(
242 | lambda v: (v.center().X < 0.05 and v.center().X > -0.05) and
243 | ((v.center().Y < -19 and v.center().Y > -25) or v.center().Y > 7)), 2)
244 |
245 | # add top groove
246 | groove_wire = CaseFull.faces().filter_by(Axis.Z).group_by(Axis.Z)[-2][0].outer_wire() #wires().sort_by(SortBy.LENGTH)[-1]
247 | groove_wire = groove_wire.rotate(Axis.Z, 180).translate((0,33,centerInset))
248 | extrude(Face(groove_wire), amount=-2, mode=Mode.SUBTRACT)
249 |
250 | # fillet top groove edges
251 | #groove_fil_edges = mainCase.edges(Select.LAST).group_by(Axis.Y)[-1].sort_by(Axis.X)[1:-1]
252 | groove_fil_edges = CaseFull.edges(Select.LAST).group_by(Axis.Y)[-1].filter_by(Axis.Z)
253 | fillet(groove_fil_edges, outerRadSmall)
254 |
255 |
256 | # outline Chamfer
257 | main_top_face = CaseFull.faces().filter_by(Axis.Z).group_by(Axis.Z)[-1].sort_by(Axis.X)[0]
258 | #chamfer(main_top_face.outer_wire().edges(), 1)
259 | #chamfer(main_top_face.inner_wires().edges(), 0.5)
260 |
261 | inset_face = CaseFull.faces().filter_by(Axis.Z).group_by(Axis.Z)[-2].sort_by(Axis.Y)[0]
262 | chamfer(inset_face.edges(), 0.5)
263 |
264 | # lower bottom ridge, added back with bottom part
265 | extrude(CaseFull.faces().sort_by(Axis.Z)[0], amount=-bottom_part_thickness, mode=Mode.SUBTRACT)
266 |
267 | #chamfer(bottom_face.outer_wire().edges(), 0.7)
268 |
269 | bottomPlateWire = CaseFull.faces().sort_by(Axis.Z)[0].inner_wires();
270 |
271 |
272 | # usb cutout
273 | usb_face = CaseFull.faces().filter_by(Axis.Y).group_by(Axis.Y)[-1].sort_by(SortBy.LENGTH)[-1]
274 | usb_plane = Plane(usb_face).shift_origin((usb_face.center().X,usb_face.center().Y,heightBelowPlate))
275 | with BuildSketch(usb_plane.shift_origin((usb_face.center().X,usb_face.center().Y,heightBelowPlate-usbStraightExtra/2-0.4))):
276 | add(USBCutoutInner.sketch)
277 | extrude(amount=-11, mode=Mode.SUBTRACT)
278 |
279 | with BuildSketch(usb_plane.shift_origin((usb_face.center().X,usb_face.center().Y,heightBelowPlate-usbStraightExtra/2+1.1))):
280 | add(USBCutoutOuter.sketch, rotation=180)
281 | extrude(amount=-1, mode=Mode.SUBTRACT)
282 |
283 | inner_usb_edges = CaseFull.faces(Select.LAST).filter_by(Axis.Y).sort_by(Axis.Y)[0].inner_wires().edges()
284 | outer_usb_edges = CaseFull.edges(Select.LAST).group_by(Axis.Y)[-1].sort_by(Axis.X)[1:-1]
285 |
286 | #chamfer(inner_usb_edges, 0.75)
287 | chamfer(outer_usb_edges, 0.75)
288 | show(CaseFull)
289 |
290 | # %%
291 |
292 | with BuildPart() as BottomPlate:
293 | extrude(CaseFull.faces().sort_by(Axis.Z)[0], amount=bottom_part_thickness)
294 | with BuildSketch():
295 | make_face(bottomPlateWire[0])
296 | extrude(amount=bottom_part_thickness)
297 | with BuildSketch():
298 | make_face(bottomPlateWire[0].offset_2d(-0.5))
299 | extrude(amount=hsThickness)
300 |
301 | middle_hole = inset_face.outer_wire().offset_2d(-1.5)
302 |
303 | with BuildSketch():
304 | make_face(middle_hole)
305 | extrude(amount=5, mode=Mode.SUBTRACT)
306 |
307 | wPlane = Plane(origin=(part_x_offset,0,0)).rotated((0,0,handAngle))
308 |
309 | #BottomPlate.part.export_step('grumpy_lp_choc_bottom_woHoles.step')
310 |
311 | with BuildSketch(wPlane) :
312 | with Locations(getAlphaKeyPos()):
313 | add(BottomKeyCutout.sketch)
314 | extrude(amount=max(bottom_part_thickness, hsThickness), mode=Mode.SUBTRACT)
315 |
316 | with BuildSketch(wPlane) :
317 | with Locations(getThumbKeyPos()):
318 | add(BottomKeyCutoutRot.sketch)
319 | extrude(amount=max(bottom_part_thickness, hsThickness), mode=Mode.SUBTRACT)
320 |
321 | wPlane = Plane(origin=(-part_x_offset,0,0)).rotated((0,0,-handAngle))
322 |
323 | with BuildSketch(wPlane) :
324 | with Locations(getAllKeyPosMir()[:-1]):
325 | add(BottomKeyCutout.sketch)
326 | extrude(amount=max(bottom_part_thickness, hsThickness), mode=Mode.SUBTRACT)
327 |
328 | with BuildSketch(wPlane) :
329 | with Locations(getAllKeyPosMir()[-1]):
330 | add(BottomKeyCutoutRot.sketch)
331 | extrude(amount=max(bottom_part_thickness, hsThickness), mode=Mode.SUBTRACT)
332 |
333 | show (BottomPlate)
334 | BottomPlate.part.export_step('grumpy_lp_choc_bottom.step')
335 |
336 | # %%
337 |
338 | show(CaseFull)
339 | #show(BottomPlate )
340 | #FullCase.part.export_stl('grumpy_lp_choc.stl')
341 | #FullCase.part.export_step('grumpy_lp_choc.step')
342 | BottomPlate.part.export_step('grumpy_lp_choc_bottom.step')
343 | #BottomPlate.part.export_stl('grumpy_lp_choc_bottom.stl')
344 |
--------------------------------------------------------------------------------
/case/grumpy_case_lp.py:
--------------------------------------------------------------------------------
1 | from build123d import *
2 | from ocp_vscode import *
3 | set_port(3939)
4 | set_defaults(reset_camera=Camera.CENTER)
5 |
6 | # CONSTANTS
7 | spacing = 19.05 # MX-Spacing
8 | holeSize = 13.9 # Platehole size
9 | pcbThickness = 1.6 # PCB Thickness
10 | hsThickness = 3.3-pcbThickness # HS Socket Thickness below PCB
11 | hsSafety = 0.3 # extra space to hide HS Sockets
12 |
13 | # CASE PARAMETERS
14 | keySafety = 0.5 # extra space between keycap and case
15 | spaceAbovePCB = 0.1 # space between PCB and Plate.
16 | plateHeight = 2.2 - spaceAbovePCB # heigth of plate
17 | plateClipHeight = 1.2 # switch clipping (1.2 for choc, 1.5 for MX)
18 | colStagger = 0.25 * spacing # stagger between cols
19 |
20 |
21 | heightAbovePlate = 8.5-6.6+3.5 # height of case rim measured from plate
22 | heightBelowPlate = pcbThickness+hsThickness+hsSafety # height of rim hiding pcb and Sockets
23 |
24 | overallHeight = heightAbovePlate+heightBelowPlate+plateHeight
25 |
26 | outerRad = 5 # radius of outer edge fillets
27 | outerRadSmall = 1.5 # radius of other outline fillets
28 |
29 | wallWidth = 7.5 # Wall Width (in effect only left and right)
30 | lWallWidth = 3 # min Wallthickness for keys outside of case body
31 |
32 | rectOffset = 0.125*19.05-colStagger/2 # rectangular case body y offset
33 | rectHeight = 3*spacing+2*lWallWidth+colStagger # rectangular case y height
34 |
35 |
36 | caseWidth = 10 *spacing + 2*wallWidth # absolute case width
37 | caseHeight = 3*spacing + 2*wallWidth + 3*colStagger # absolute case height
38 |
39 | handAngle = 14 # degrees of rotation for each hand
40 |
41 | centerInset = 1 #how much lower the inner cutout should be
42 |
43 | usbStraightExtra = 3 # extra Y length of cutout, if the inner cutout should be straight
44 |
45 | def getRowPos(rowOffset=0):
46 | """ returns x y coordinate tuple for each right hand switch of the selected row
47 |
48 | :param rowOffset: row number counted from the top
49 | :return list of coordinate tuples
50 | """
51 |
52 | topSwitchY = caseHeight/2-wallWidth-spacing/2-rowOffset*spacing
53 |
54 |
55 | points = [
56 | ( 1.5 * spacing, topSwitchY - 2 * colStagger ),
57 | ( 2.5 * spacing, topSwitchY - 1 * colStagger ),
58 | ( 3.5 * spacing, topSwitchY - 2 * colStagger ),
59 | ]
60 | if (rowOffset > 0):
61 | points.append(( 4.5 * spacing, topSwitchY - 3.5 * colStagger ) )
62 | # points.append(( 4.5 * spacing, topSwitchY - 4 * colStagger ) )
63 |
64 | if (rowOffset < 2):
65 | points.append(( 0.5 * spacing, topSwitchY - 4 * colStagger ))
66 |
67 |
68 |
69 | return points
70 |
71 | def getSwitchPositions(keys=True):
72 | """ collects all positions for the first three rows
73 |
74 | :param keys: if true returns alphakey positions, if false returns thumbkeyposition
75 | :return list of coordinate tuples
76 | """
77 | if keys:
78 | return getRowPos(0) + getRowPos(1) + getRowPos(2)
79 | else:
80 | return [( 0.25 * spacing, caseHeight/2-wallWidth-spacing/2-2*spacing - 4 * colStagger )]
81 |
82 | def getAlphaKeyPos():
83 | return getSwitchPositions(True)
84 |
85 | def getThumbKeyPos():
86 | return getSwitchPositions(False)
87 |
88 | def getAllKeyPos():
89 | return getAlphaKeyPos() + getThumbKeyPos()
90 |
91 | def getInnerEdges(object):
92 | obj = ( object.edges()
93 | .filter_by(Axis.Z)
94 | .filter_by(
95 | lambda v: v.center().X > 2 and v.center().X < (caseWidth/2-20))
96 | )
97 | return obj;
98 |
99 |
100 | ## ------------------------------------------------------------------------------
101 |
102 | with BuildSketch() as SketchOutline:
103 | # outline shapes for alpha and thumbs
104 | with Locations(getAlphaKeyPos()):
105 | Rectangle(spacing+2*lWallWidth, spacing+2*lWallWidth)
106 | with Locations(getThumbKeyPos()):
107 | Rectangle(spacing*1.5+2*lWallWidth, spacing+2*lWallWidth)
108 | with Locations((caseWidth/4-7+5,-8)):
109 | Rectangle(caseWidth/2+10, 2*spacing+2*wallWidth+2.5+10, rotation=-handAngle)
110 | with Locations((-21.2,5)):
111 | Rectangle(40-lWallWidth, 46.9, mode=Mode.SUBTRACT)
112 |
113 | with BuildSketch() as CaseOutline:
114 | with Locations((4.33,0,0)):
115 | add(SketchOutline.sketch, rotation=handAngle)
116 | with Locations((-20,0)):
117 | Rectangle(40,caseHeight*2, mode=Mode.SUBTRACT)
118 |
119 | with BuildSketch() as CaseOutlineFilletOuter:
120 | add(CaseOutline.sketch)
121 | fillet(CaseOutlineFilletOuter.edges().sort_by(Axis.X)[-1].vertices(), outerRad)
122 |
123 | with BuildSketch() as KeyCutout:
124 | with Locations(getAlphaKeyPos()):
125 | Rectangle(spacing+keySafety, spacing+keySafety)
126 | with Locations(getThumbKeyPos()):
127 | Rectangle(1.5*spacing+keySafety, spacing+keySafety)
128 | fillet(KeyCutout.vertices().sort_by(Axis.X)[4:], 1)
129 | fillet(KeyCutout.vertices().group_by(Axis.X)[0].sort_by(Axis.Y)[0], 1)
130 | fillet(KeyCutout.vertices().group_by(Axis.X)[2].sort_by(Axis.Y)[0], 1)
131 |
132 | with BuildSketch() as USBCutoutInner:
133 | Rectangle(11.5,6.5+usbStraightExtra)
134 | fillet(USBCutoutInner.vertices(), 1.5)
135 |
136 | with BuildSketch() as USBCutoutOuter:
137 | with Locations((0,-1.5)):
138 | Rectangle(12.5,10.5)
139 | fillet(USBCutoutOuter.vertices().group_by(Axis.Y)[-1], 1.5)
140 | ## ------------------------------------------------------------------------------
141 |
142 | bottomPlateWire = 0
143 |
144 | with BuildPart() as FullCase:
145 |
146 | # Build Case Bottom below Plate
147 | with BuildPart() as Bottom:
148 | add(CaseOutlineFilletOuter.sketch)
149 | extrude(amount=heightBelowPlate)
150 | # select faces that should not be offset = open faces
151 | remFaces = Bottom.faces().sort_by(Axis.Z)[0]
152 | remFaces += Bottom.faces().sort_by(Axis.Z)[-1]
153 | remFaces += Bottom.faces().sort_by(Axis.X)[:5].sort_by(Axis.Y)[-4:]
154 | # create shell
155 | offset(amount=-lWallWidth, openings=remFaces, kind=Kind.INTERSECTION)
156 | fillet(getInnerEdges(Bottom), outerRadSmall)
157 |
158 | # Build Plate part
159 | with BuildPart(Plane(origin=(0,0,heightBelowPlate))) as Plate:
160 | add(CaseOutlineFilletOuter.sketch)
161 | extrude(amount=plateHeight)
162 | fillet(getInnerEdges(Plate), outerRadSmall)
163 | # work plane for further operations
164 | wPlane = Plane(origin=(4.33,0,heightBelowPlate)).rotated((0,0,handAngle))
165 | # add cutouts for switch clips
166 | with BuildSketch(wPlane) :
167 | with Locations(getAllKeyPos()):
168 | Rectangle(holeSize+2,holeSize)
169 | extrude(amount=plateHeight-plateClipHeight, mode=Mode.SUBTRACT)
170 | # add switch cutout
171 | with BuildSketch(wPlane) :
172 | with Locations(getAllKeyPos()):
173 | Rectangle(holeSize,holeSize)
174 | extrude(amount=plateHeight, mode=Mode.SUBTRACT)
175 |
176 | # Build Top part
177 | with BuildPart(Plane(origin=(0,0,heightBelowPlate+plateHeight))) as Top:
178 | add(CaseOutlineFilletOuter.sketch)
179 | extrude(amount=heightAbovePlate)
180 | fillet(getInnerEdges(Top), outerRadSmall)
181 | # work plane for further operations
182 | wPlane = Plane(origin=(4.33,0,heightBelowPlate+plateHeight)).rotated((0,0,handAngle))
183 | # add keycap cutout
184 | with BuildSketch(wPlane) :
185 | add(KeyCutout.sketch)
186 | extrude(amount=heightAbovePlate, mode=Mode.SUBTRACT)
187 | # lower center cutout
188 | extrude(Top.faces().filter_by(Axis.Z).group_by(Axis.Z)[-1].sort_by(Axis.X)[0],
189 | amount=-centerInset, mode=Mode.SUBTRACT)
190 | #show_object(Bottom)
191 | #show_object(Plate)
192 | #show_object(Top)
193 |
194 | mirror(FullCase.part, about=Plane.YZ)
195 |
196 | # add fillets on mirrored edges
197 | fillet(FullCase.edges()
198 | .filter_by(Axis.Z)
199 | .filter_by(
200 | lambda v: (v.center().X < 0.05 and v.center().X > -0.05) and
201 | ((v.center().Y < 0 and v.center().Y > -21) or v.center().Y > 7)), 1)
202 |
203 | # add fillets on mirrored edges
204 | fillet(FullCase.edges()
205 | .filter_by(Axis.Z)
206 | .group_by(Axis.Z)[-1]
207 | .filter_by(
208 | lambda v: (v.center().X < 0.05 and v.center().X > -0.05) and
209 | ((v.center().Y < -21 and v.center().Y > -25) or v.center().Y > 7)), 1)
210 |
211 | # add fillets on mirrored edges
212 | fillet(FullCase.edges()
213 | .filter_by(Axis.Z)
214 | .group_by(Axis.Z)[0]
215 | .filter_by(
216 | lambda v: (v.center().X < 0.05 and v.center().X > -0.05) and
217 | ((v.center().Y < -21 and v.center().Y > -25) or v.center().Y > 7)), 2)
218 | # add top groove
219 | groove_wire = FullCase.faces().filter_by(Axis.Z).group_by(Axis.Z)[-2][0].outer_wire() #wires().sort_by(SortBy.LENGTH)[-1]
220 | groove_wire = groove_wire.rotate(Axis.Z, 180).translate((0,33,centerInset))
221 | extrude(Face(groove_wire), amount=-2, mode=Mode.SUBTRACT)
222 |
223 | # fillet top groove edges
224 | groove_fil_edges = FullCase.edges(Select.LAST).group_by(Axis.Y)[-1].sort_by(Axis.X)[1:-1]
225 | fillet(groove_fil_edges, outerRadSmall)
226 |
227 | # outline Chamfer
228 | main_top_face = FullCase.faces().filter_by(Axis.Z).group_by(Axis.Z)[-1].sort_by(Axis.X)[0]
229 | #chamfer(main_top_face.outer_wire().edges(), 1)
230 | #chamfer(main_top_face.inner_wires().edges(), 0.5)
231 |
232 | inset_face = FullCase.faces().filter_by(Axis.Z).group_by(Axis.Z)[-2].sort_by(Axis.Y)[0]
233 | chamfer(inset_face.edges(), 0.5)
234 |
235 | bottom_face = FullCase.faces().filter_by(Axis.Z).group_by(Axis.Z)[0][0]
236 | chamfer(bottom_face.outer_wire().edges(), 0.7)
237 |
238 | bottomPlateWire = FullCase.faces().sort_by(Axis.Z)[0].inner_wires();
239 |
240 | # usb cutout
241 | usb_face = FullCase.faces().filter_by(Axis.Y).group_by(Axis.Y)[-1].sort_by(SortBy.LENGTH)[-1]
242 | usb_plane = Plane(usb_face).shift_origin((usb_face.center().X,usb_face.center().Y,heightBelowPlate))
243 | with BuildSketch(usb_plane.shift_origin((usb_face.center().X,usb_face.center().Y,heightBelowPlate-usbStraightExtra/2))):
244 | add(USBCutoutInner.sketch)
245 | extrude(amount=-11, mode=Mode.SUBTRACT)
246 |
247 | with BuildSketch(usb_plane):
248 | add(USBCutoutOuter.sketch, rotation=180)
249 | extrude(amount=-1, mode=Mode.SUBTRACT)
250 |
251 | inner_usb_edges = FullCase.faces(Select.LAST).filter_by(Axis.Y).sort_by(Axis.Y)[0].inner_wires().edges()
252 | outer_usb_edges = FullCase.edges(Select.LAST).group_by(Axis.Y)[-1].sort_by(Axis.X)[1:-1]
253 |
254 | #chamfer(inner_usb_edges, 0.75)
255 | chamfer(outer_usb_edges, 0.75)
256 |
257 | with BuildPart() as BottomPlate:
258 | with BuildSketch() as bpsk:
259 | with BuildLine():
260 | add(bottomPlateWire)
261 | make_face()
262 | offset(amount=-0.2)
263 |
264 | extrude(amount=hsThickness)
265 |
266 | show(FullCase )
267 | #show(BottomPlate )
268 | #FullCase.part.export_stl('grumpy_lp.stl')
269 | FullCase.part.export_step('grumpy_lp.step')
270 | BottomPlate.part.export_step('grumpy_lp_bottom.step')
271 |
--------------------------------------------------------------------------------
/case/grumpy_lp.FCStd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weteor/Grumpy/0a1ea6c46a17778650b71261e2852e8dad9eb8cc/case/grumpy_lp.FCStd
--------------------------------------------------------------------------------
/case/grumpy_lp_choc.FCStd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weteor/Grumpy/0a1ea6c46a17778650b71261e2852e8dad9eb8cc/case/grumpy_lp_choc.FCStd
--------------------------------------------------------------------------------
/firmware/QMK/grumpy/config.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2022 weteor
3 |
4 | This program is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU General Public License as published by
6 | the Free Software Foundation, either version 2 of the License, or
7 | (at your option) any later version.
8 |
9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU General Public License for more details.
13 |
14 | You should have received a copy of the GNU General Public License
15 | along with this program. If not, see .
16 | */
17 |
18 | #pragma once
19 |
20 | //#include "config_common.h"
21 |
--------------------------------------------------------------------------------
/firmware/QMK/grumpy/halconf.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2022 weteor
3 |
4 | This program is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU General Public License as published by
6 | the Free Software Foundation, either version 2 of the License, or
7 | (at your option) any later version.
8 |
9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU General Public License for more details.
13 |
14 | You should have received a copy of the GNU General Public License
15 | along with this program. If not, see .
16 | */
17 |
18 | #pragma once
19 |
20 | #define HAL_USE_I2C TRUE
21 |
22 | #include_next
23 |
--------------------------------------------------------------------------------
/firmware/QMK/grumpy/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "keyboard_name": "grumpy",
3 | "manufacturer": "weteor",
4 | "url": "https://github.com/weteor/grumpy/",
5 | "maintainer": "weteor",
6 | "processor": "RP2040",
7 | "bootloader": "rp2040",
8 | "diode_direction": "COL2ROW",
9 | "rp2040_bootloader_double_tap_reset": true,
10 | "rp2040_bootloader_double_tap_reset_timeout": true,
11 | "matrix_pins" : {
12 | "cols": [ "GP26", "GP27", "GP28", "GP29", "GP6"],
13 | "rows": [ "GP7", "GP0", "GP1", "GP2", "GP4", "GP3" ]
14 | },
15 | "matrix_size": {
16 | "cols": 5,
17 | "rows": 6
18 | },
19 | "usb": {
20 | "vid": "0xFEED",
21 | "pid": "0x4657",
22 | "device_version": "0.2.0"
23 | },
24 | "build": {
25 | "lto": false,
26 | },
27 | "features": {
28 | "bootmagic": true,
29 | "extrakey": true,
30 | "command": false,
31 | "console": false,
32 | "mousekey": false,
33 | "nkro": true,
34 | },
35 | "layouts": {
36 | "LAYOUT_28": {
37 | "layout": [
38 | { "label": "01", "matrix": [0,0], "x": 1, "y": 0.25 },
39 | { "label": "02", "matrix": [0,1], "x": 2, "y": 0 },
40 | { "label": "03", "matrix": [0,2], "x": 3, "y": 0.25 },
41 | { "label": "04", "matrix": [0,3], "x": 4, "y": 0.75 },
42 | { "label": "34", "matrix": [0,4], "x": 6, "y": 0.75 },
43 | { "label": "33", "matrix": [1,0], "x": 7, "y": 0.25 },
44 | { "label": "32", "matrix": [1,1], "x": 8, "y": 0 },
45 | { "label": "31", "matrix": [1,2], "x": 9, "y": 0.25 },
46 | { "label": "10", "matrix": [1,3], "x": 0, "y": 1.625 },
47 | { "label": "11", "matrix": [1,4], "x": 1, "y": 1.25 },
48 | { "label": "12", "matrix": [2,0], "x": 2, "y": 1 },
49 | { "label": "13", "matrix": [2,1], "x": 3, "y": 1.25 },
50 | { "label": "14", "matrix": [2,2], "x": 4, "y": 1.75 },
51 | { "label": "44", "matrix": [2,3], "x": 6, "y": 1.75 },
52 | { "label": "43", "matrix": [2,4], "x": 7, "y": 1.25 },
53 | { "label": "42", "matrix": [3,0], "x": 8, "y": 1 },
54 | { "label": "41", "matrix": [3,1], "x": 9, "y": 1.25 },
55 | { "label": "40", "matrix": [3,2], "x": 10, "y": 1.625 },
56 | { "label": "20", "matrix": [3,3], "x": 0, "y": 2.625 },
57 | { "label": "21", "matrix": [3,4], "x": 1, "y": 2.25 },
58 | { "label": "22", "matrix": [4,0], "x": 2, "y": 2 },
59 | { "label": "23", "matrix": [4,1], "x": 3, "y": 2.25 },
60 | { "label": "24", "matrix": [4,2], "x": 4, "y": 2.75, "w": 1.5 },
61 | { "label": "54", "matrix": [4,3], "x": 5.5, "y": 2.75, "w": 1.5 },
62 | { "label": "53", "matrix": [4,4], "x": 7, "y": 2.25 },
63 | { "label": "52", "matrix": [5,0], "x": 8, "y": 2 },
64 | { "label": "51", "matrix": [5,1], "x": 9, "y": 2.25 },
65 | { "label": "50", "matrix": [5,2], "x": 10, "y": 2.625 }
66 | ]
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/firmware/QMK/grumpy/keymaps/default/keymap.c:
--------------------------------------------------------------------------------
1 | /* Copyright 2021 weteor
2 | *
3 | * This program is free software: you can redistribute it and/or modify
4 | * it under the terms of the GNU General Public License as published by
5 | * the Free Software Foundation, either version 2 of the License, or
6 | * (at your option) any later version.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License
14 | * along with this program. If not, see .
15 | */
16 |
17 | #include QMK_KEYBOARD_H
18 |
19 | enum layers
20 | {
21 | _ALPHA_QWERTY = 0,
22 | };
23 |
24 | const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
25 |
26 |
27 | [_ALPHA_QWERTY] = LAYOUT_grumpy(
28 | KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O,
29 | KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN,
30 | KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH
31 | )
32 | };
33 |
--------------------------------------------------------------------------------
/firmware/QMK/grumpy/keymaps/vial/config.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2022 weteor
3 |
4 | This program is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU General Public License as published by
6 | the Free Software Foundation, either version 2 of the License, or
7 | (at your option) any later version.
8 |
9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU General Public License for more details.
13 |
14 | You should have received a copy of the GNU General Public License
15 | along with this program. If not, see .
16 | */
17 |
18 | #pragma once
19 |
20 | #define VIAL_KEYBOARD_UID {0xD8, 0xE1, 0xE5, 0x27, 0x39, 0x36, 0x89, 0x45}
21 |
22 | #define VIAL_KEY_OVERRIDE_ENTRIES 20
23 | #define VIAL_COMBO_ENTRIES 20
24 | #define VIAL_TAP_DANCE_ENTRIES 20
25 | #define DYNAMIC_KEYMAP_LAYER_COUNT 6
26 |
--------------------------------------------------------------------------------
/firmware/QMK/grumpy/keymaps/vial/keymap.c:
--------------------------------------------------------------------------------
1 | /* Copyright 2021 weteor
2 | *
3 | * This program is free software: you can redistribute it and/or modify
4 | * it under the terms of the GNU General Public License as published by
5 | * the Free Software Foundation, either version 2 of the License, or
6 | * (at your option) any later version.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License
14 | * along with this program. If not, see .
15 | */
16 |
17 | #include QMK_KEYBOARD_H
18 |
19 | enum layers
20 | {
21 | _ALPHA_QWERTY = 0,
22 | };
23 |
24 | const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
25 |
26 |
27 | [_ALPHA_QWERTY] = LAYOUT_28(
28 | KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O,
29 | KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN,
30 | KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH
31 | )
32 | };
33 |
--------------------------------------------------------------------------------
/firmware/QMK/grumpy/keymaps/vial/rules.mk:
--------------------------------------------------------------------------------
1 | VIA_ENABLE = yes
2 | VIAL_ENABLE = yes
3 | VIAL_INSECURE = yes
4 |
--------------------------------------------------------------------------------
/firmware/QMK/grumpy/keymaps/vial/vial.json:
--------------------------------------------------------------------------------
1 | {
2 | "lighting": "none",
3 | "matrix": {
4 | "rows": 6,
5 | "cols": 5
6 | },
7 | "layouts": {
8 | "keymap":[
9 | [
10 | {
11 | "r": 14,
12 | "x": 3
13 | },
14 | "0,2"
15 | ],
16 | [
17 | {
18 | "y": -0.75,
19 | "x": 2
20 | },
21 | "0,1",
22 | {
23 | "x": 1
24 | },
25 | "0,3"
26 | ],
27 | [
28 | {
29 | "y": -0.5,
30 | "x": 5
31 | },
32 | "0,4"
33 | ],
34 | [
35 | {
36 | "y": -0.75,
37 | "x": 3
38 | },
39 | "1,2"
40 | ],
41 | [
42 | {
43 | "y": -0.75,
44 | "x": 2
45 | },
46 | "1,1",
47 | {
48 | "x": 1
49 | },
50 | "1,3"
51 | ],
52 | [
53 | {
54 | "y": -0.625,
55 | "x": 1
56 | },
57 | "1,0"
58 | ],
59 | [
60 | {
61 | "y": -0.875,
62 | "x": 5
63 | },
64 | "1,4"
65 | ],
66 | [
67 | {
68 | "y": -0.75,
69 | "x": 3
70 | },
71 | "2,2"
72 | ],
73 | [
74 | {
75 | "y": -0.75,
76 | "x": 2
77 | },
78 | "2,1",
79 | {
80 | "x": 1
81 | },
82 | "2,3"
83 | ],
84 | [
85 | {
86 | "y": -0.625,
87 | "x": 1
88 | },
89 | "2,0"
90 | ],
91 | [
92 | {
93 | "y": -0.875,
94 | "x": 5,
95 | "w": 1.5
96 | },
97 | "2,4"
98 | ],
99 | [
100 | {
101 | "r": -14,
102 | "y": -1,
103 | "x": 7
104 | },
105 | "3,2"
106 | ],
107 | [
108 | {
109 | "y": -0.75,
110 | "x": 6
111 | },
112 | "3,3",
113 | {
114 | "x": 1
115 | },
116 | "3,1"
117 | ],
118 | [
119 | {
120 | "y": -0.5,
121 | "x": 5
122 | },
123 | "3,4"
124 | ],
125 | [
126 | {
127 | "y": -0.75,
128 | "x": 7
129 | },
130 | "4,2"
131 | ],
132 | [
133 | {
134 | "y": -0.75,
135 | "x": 6
136 | },
137 | "4,3",
138 | {
139 | "x": 1
140 | },
141 | "4,1"
142 | ],
143 | [
144 | {
145 | "y": -0.625,
146 | "x": 9
147 | },
148 | "4,0"
149 | ],
150 | [
151 | {
152 | "y": -0.875,
153 | "x": 5
154 | },
155 | "4,4"
156 | ],
157 | [
158 | {
159 | "y": -0.75,
160 | "x": 7
161 | },
162 | "5,2"
163 | ],
164 | [
165 | {
166 | "y": -0.75,
167 | "x": 6
168 | },
169 | "5,3",
170 | {
171 | "x": 1
172 | },
173 | "5,1"
174 | ],
175 | [
176 | {
177 | "y": -0.625,
178 | "x": 9
179 | },
180 | "5,0"
181 | ],
182 | [
183 | {
184 | "y": -0.875,
185 | "x": 4.5,
186 | "w": 1.5
187 | },
188 | "5,4"
189 | ]
190 | ]
191 | }
192 | }
193 |
--------------------------------------------------------------------------------
/firmware/QMK/grumpy/mcuconf.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2022 weteor
3 |
4 | This program is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU General Public License as published by
6 | the Free Software Foundation, either version 2 of the License, or
7 | (at your option) any later version.
8 |
9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU General Public License for more details.
13 |
14 | You should have received a copy of the GNU General Public License
15 | along with this program. If not, see .
16 | */
17 |
18 | #pragma once
19 |
20 | #include_next
21 |
22 |
--------------------------------------------------------------------------------
/firmware/QMK/grumpy/rules.mk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weteor/Grumpy/0a1ea6c46a17778650b71261e2852e8dad9eb8cc/firmware/QMK/grumpy/rules.mk
--------------------------------------------------------------------------------
/firmware/QMK/grumpy_MX_vial.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weteor/Grumpy/0a1ea6c46a17778650b71261e2852e8dad9eb8cc/firmware/QMK/grumpy_MX_vial.uf2
--------------------------------------------------------------------------------
/firmware/QMK/grumpy_chocV1/config.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2022 weteor
3 |
4 | This program is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU General Public License as published by
6 | the Free Software Foundation, either version 2 of the License, or
7 | (at your option) any later version.
8 |
9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU General Public License for more details.
13 |
14 | You should have received a copy of the GNU General Public License
15 | along with this program. If not, see .
16 | */
17 |
18 | #pragma once
19 |
20 | //#include "config_common.h"
21 |
--------------------------------------------------------------------------------
/firmware/QMK/grumpy_chocV1/halconf.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2022 weteor
3 |
4 | This program is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU General Public License as published by
6 | the Free Software Foundation, either version 2 of the License, or
7 | (at your option) any later version.
8 |
9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU General Public License for more details.
13 |
14 | You should have received a copy of the GNU General Public License
15 | along with this program. If not, see .
16 | */
17 |
18 | #pragma once
19 |
20 | #define HAL_USE_I2C TRUE
21 |
22 | #include_next
23 |
--------------------------------------------------------------------------------
/firmware/QMK/grumpy_chocV1/info.json:
--------------------------------------------------------------------------------
1 | {
2 | "keyboard_name": "grumpy_choc",
3 | "manufacturer": "weteor",
4 | "url": "https://github.com/weteor/grumpy/",
5 | "maintainer": "weteor",
6 | "processor": "RP2040",
7 | "bootloader": "rp2040",
8 | "diode_direction": "COL2ROW",
9 | "rp2040_bootloader_double_tap_reset": true,
10 | "rp2040_bootloader_double_tap_reset_timeout": true,
11 | "matrix_pins" : {
12 | "cols": [ "GP29", "GP6", "GP0", "GP7", "GP1"],
13 | "rows": [ "GP26", "GP27", "GP28", "GP3", "GP4", "GP2" ]
14 | },
15 | "matrix_size": {
16 | "cols": 5,
17 | "rows": 6
18 | },
19 | "usb": {
20 | "vid": "0xFEED",
21 | "pid": "0x4657",
22 | "device_version": "0.2.0"
23 | },
24 | "build": {
25 | "lto": false,
26 | },
27 | "features": {
28 | "bootmagic": true,
29 | "extrakey": true,
30 | "command": false,
31 | "console": false,
32 | "mousekey": false,
33 | "nkro": true,
34 | },
35 | "layouts": {
36 | "LAYOUT_28": {
37 | "layout": [
38 | { "label": "01", "matrix": [0,0], "x": 1, "y": 0.25 },
39 | { "label": "02", "matrix": [0,1], "x": 2, "y": 0 },
40 | { "label": "03", "matrix": [0,2], "x": 3, "y": 0.25 },
41 | { "label": "04", "matrix": [0,3], "x": 4, "y": 0.75 },
42 | { "label": "34", "matrix": [0,4], "x": 6, "y": 0.75 },
43 | { "label": "33", "matrix": [1,0], "x": 7, "y": 0.25 },
44 | { "label": "32", "matrix": [1,1], "x": 8, "y": 0 },
45 | { "label": "31", "matrix": [1,2], "x": 9, "y": 0.25 },
46 | { "label": "10", "matrix": [1,3], "x": 0, "y": 1.625 },
47 | { "label": "11", "matrix": [1,4], "x": 1, "y": 1.25 },
48 | { "label": "12", "matrix": [2,0], "x": 2, "y": 1 },
49 | { "label": "13", "matrix": [2,1], "x": 3, "y": 1.25 },
50 | { "label": "14", "matrix": [2,2], "x": 4, "y": 1.75 },
51 | { "label": "44", "matrix": [2,3], "x": 6, "y": 1.75 },
52 | { "label": "43", "matrix": [2,4], "x": 7, "y": 1.25 },
53 | { "label": "42", "matrix": [3,0], "x": 8, "y": 1 },
54 | { "label": "41", "matrix": [3,1], "x": 9, "y": 1.25 },
55 | { "label": "40", "matrix": [3,2], "x": 10, "y": 1.625 },
56 | { "label": "20", "matrix": [3,3], "x": 0, "y": 2.625 },
57 | { "label": "21", "matrix": [3,4], "x": 1, "y": 2.25 },
58 | { "label": "22", "matrix": [4,0], "x": 2, "y": 2 },
59 | { "label": "23", "matrix": [4,1], "x": 3, "y": 2.25 },
60 | { "label": "24", "matrix": [4,2], "x": 4, "y": 2.75, "w": 1.5 },
61 | { "label": "54", "matrix": [4,3], "x": 5.5, "y": 2.75, "w": 1.5 },
62 | { "label": "53", "matrix": [4,4], "x": 7, "y": 2.25 },
63 | { "label": "52", "matrix": [5,0], "x": 8, "y": 2 },
64 | { "label": "51", "matrix": [5,1], "x": 9, "y": 2.25 },
65 | { "label": "50", "matrix": [5,2], "x": 10, "y": 2.625 }
66 | ]
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/firmware/QMK/grumpy_chocV1/keymaps/default/keymap.c:
--------------------------------------------------------------------------------
1 | /* Copyright 2021 weteor
2 | *
3 | * This program is free software: you can redistribute it and/or modify
4 | * it under the terms of the GNU General Public License as published by
5 | * the Free Software Foundation, either version 2 of the License, or
6 | * (at your option) any later version.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License
14 | * along with this program. If not, see .
15 | */
16 |
17 | #include QMK_KEYBOARD_H
18 |
19 | enum layers
20 | {
21 | _ALPHA_QWERTY = 0,
22 | };
23 |
24 | const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
25 |
26 |
27 | [_ALPHA_QWERTY] = LAYOUT_grumpy(
28 | KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O,
29 | KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN,
30 | KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH
31 | )
32 | };
33 |
--------------------------------------------------------------------------------
/firmware/QMK/grumpy_chocV1/keymaps/vial/config.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2022 weteor
3 |
4 | This program is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU General Public License as published by
6 | the Free Software Foundation, either version 2 of the License, or
7 | (at your option) any later version.
8 |
9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU General Public License for more details.
13 |
14 | You should have received a copy of the GNU General Public License
15 | along with this program. If not, see .
16 | */
17 |
18 | #pragma once
19 |
20 | #define VIAL_KEYBOARD_UID {0xD8, 0xE1, 0xE5, 0x27, 0x39, 0x36, 0x89, 0x45}
21 |
22 | #define VIAL_KEY_OVERRIDE_ENTRIES 20
23 | #define VIAL_COMBO_ENTRIES 20
24 | #define VIAL_TAP_DANCE_ENTRIES 20
25 | #define DYNAMIC_KEYMAP_LAYER_COUNT 6
26 |
--------------------------------------------------------------------------------
/firmware/QMK/grumpy_chocV1/keymaps/vial/keymap.c:
--------------------------------------------------------------------------------
1 | /* Copyright 2021 weteor
2 | *
3 | * This program is free software: you can redistribute it and/or modify
4 | * it under the terms of the GNU General Public License as published by
5 | * the Free Software Foundation, either version 2 of the License, or
6 | * (at your option) any later version.
7 | *
8 | * This program is distributed in the hope that it will be useful,
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | * GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License
14 | * along with this program. If not, see .
15 | */
16 |
17 | #include QMK_KEYBOARD_H
18 |
19 | enum layers
20 | {
21 | _ALPHA_QWERTY = 0,
22 | };
23 |
24 | const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
25 |
26 |
27 | [_ALPHA_QWERTY] = LAYOUT_28(
28 | KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O,
29 | KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN,
30 | KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH
31 | )
32 | };
33 |
--------------------------------------------------------------------------------
/firmware/QMK/grumpy_chocV1/keymaps/vial/rules.mk:
--------------------------------------------------------------------------------
1 | VIA_ENABLE = yes
2 | VIAL_ENABLE = yes
3 | VIAL_INSECURE = yes
4 |
--------------------------------------------------------------------------------
/firmware/QMK/grumpy_chocV1/keymaps/vial/vial.json:
--------------------------------------------------------------------------------
1 | {
2 | "lighting": "none",
3 | "matrix": {
4 | "rows": 6,
5 | "cols": 5
6 | },
7 | "layouts": {
8 | "keymap":[
9 | [
10 | {
11 | "r": 14,
12 | "x": 3
13 | },
14 | "0,2"
15 | ],
16 | [
17 | {
18 | "y": -0.75,
19 | "x": 2
20 | },
21 | "0,1",
22 | {
23 | "x": 1
24 | },
25 | "0,3"
26 | ],
27 | [
28 | {
29 | "y": -0.5,
30 | "x": 5
31 | },
32 | "0,4"
33 | ],
34 | [
35 | {
36 | "y": -0.75,
37 | "x": 3
38 | },
39 | "1,2"
40 | ],
41 | [
42 | {
43 | "y": -0.75,
44 | "x": 2
45 | },
46 | "1,1",
47 | {
48 | "x": 1
49 | },
50 | "1,3"
51 | ],
52 | [
53 | {
54 | "y": -0.625,
55 | "x": 1
56 | },
57 | "1,0"
58 | ],
59 | [
60 | {
61 | "y": -0.875,
62 | "x": 5
63 | },
64 | "1,4"
65 | ],
66 | [
67 | {
68 | "y": -0.75,
69 | "x": 3
70 | },
71 | "2,2"
72 | ],
73 | [
74 | {
75 | "y": -0.75,
76 | "x": 2
77 | },
78 | "2,1",
79 | {
80 | "x": 1
81 | },
82 | "2,3"
83 | ],
84 | [
85 | {
86 | "y": -0.625,
87 | "x": 1
88 | },
89 | "2,0"
90 | ],
91 | [
92 | {
93 | "y": -0.875,
94 | "x": 5,
95 | "w": 1.5
96 | },
97 | "2,4"
98 | ],
99 | [
100 | {
101 | "r": -14,
102 | "y": -1,
103 | "x": 7
104 | },
105 | "3,2"
106 | ],
107 | [
108 | {
109 | "y": -0.75,
110 | "x": 6
111 | },
112 | "3,3",
113 | {
114 | "x": 1
115 | },
116 | "3,1"
117 | ],
118 | [
119 | {
120 | "y": -0.5,
121 | "x": 5
122 | },
123 | "3,4"
124 | ],
125 | [
126 | {
127 | "y": -0.75,
128 | "x": 7
129 | },
130 | "4,2"
131 | ],
132 | [
133 | {
134 | "y": -0.75,
135 | "x": 6
136 | },
137 | "4,3",
138 | {
139 | "x": 1
140 | },
141 | "4,1"
142 | ],
143 | [
144 | {
145 | "y": -0.625,
146 | "x": 9
147 | },
148 | "4,0"
149 | ],
150 | [
151 | {
152 | "y": -0.875,
153 | "x": 5
154 | },
155 | "4,4"
156 | ],
157 | [
158 | {
159 | "y": -0.75,
160 | "x": 7
161 | },
162 | "5,2"
163 | ],
164 | [
165 | {
166 | "y": -0.75,
167 | "x": 6
168 | },
169 | "5,3",
170 | {
171 | "x": 1
172 | },
173 | "5,1"
174 | ],
175 | [
176 | {
177 | "y": -0.625,
178 | "x": 9
179 | },
180 | "5,0"
181 | ],
182 | [
183 | {
184 | "y": -0.875,
185 | "x": 4.5,
186 | "w": 1.5
187 | },
188 | "5,4"
189 | ]
190 | ]
191 | }
192 | }
193 |
--------------------------------------------------------------------------------
/firmware/QMK/grumpy_chocV1/mcuconf.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2022 weteor
3 |
4 | This program is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU General Public License as published by
6 | the Free Software Foundation, either version 2 of the License, or
7 | (at your option) any later version.
8 |
9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU General Public License for more details.
13 |
14 | You should have received a copy of the GNU General Public License
15 | along with this program. If not, see .
16 | */
17 |
18 | #pragma once
19 |
20 | #include_next
21 |
22 |
--------------------------------------------------------------------------------
/firmware/QMK/grumpy_chocV1/rules.mk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weteor/Grumpy/0a1ea6c46a17778650b71261e2852e8dad9eb8cc/firmware/QMK/grumpy_chocV1/rules.mk
--------------------------------------------------------------------------------
/firmware/QMK/grumpy_chocV1_vial.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weteor/Grumpy/0a1ea6c46a17778650b71261e2852e8dad9eb8cc/firmware/QMK/grumpy_chocV1_vial.uf2
--------------------------------------------------------------------------------
/grumpy_ch552t/fp-lib-table:
--------------------------------------------------------------------------------
1 | (fp_lib_table
2 | (version 7)
3 | (lib (name "mcu")(type "KiCad")(uri "D:/.build/kleeb/mcu.pretty")(options "")(descr ""))
4 | (lib (name "weteor")(type "KiCad")(uri "D:/.build/weteor_kicad_lib/footprints")(options "")(descr ""))
5 | )
6 |
--------------------------------------------------------------------------------
/grumpy_ch552t/grumpy_ch522t.kicad_prl:
--------------------------------------------------------------------------------
1 | {
2 | "board": {
3 | "active_layer": 0,
4 | "active_layer_preset": "",
5 | "auto_track_width": true,
6 | "hidden_netclasses": [],
7 | "hidden_nets": [],
8 | "high_contrast_mode": 0,
9 | "net_color_mode": 1,
10 | "opacity": {
11 | "images": 0.6,
12 | "pads": 1.0,
13 | "tracks": 1.0,
14 | "vias": 1.0,
15 | "zones": 0.6
16 | },
17 | "selection_filter": {
18 | "dimensions": true,
19 | "footprints": true,
20 | "graphics": true,
21 | "keepouts": true,
22 | "lockedItems": true,
23 | "otherItems": true,
24 | "pads": true,
25 | "text": true,
26 | "tracks": true,
27 | "vias": true,
28 | "zones": true
29 | },
30 | "visible_items": [
31 | 0,
32 | 1,
33 | 2,
34 | 3,
35 | 4,
36 | 5,
37 | 8,
38 | 9,
39 | 10,
40 | 11,
41 | 12,
42 | 13,
43 | 15,
44 | 16,
45 | 17,
46 | 18,
47 | 19,
48 | 20,
49 | 21,
50 | 22,
51 | 23,
52 | 24,
53 | 25,
54 | 26,
55 | 27,
56 | 28,
57 | 29,
58 | 30,
59 | 32,
60 | 33,
61 | 34,
62 | 35,
63 | 36,
64 | 40
65 | ],
66 | "visible_layers": "ffcffff_ffffffff",
67 | "zone_display_mode": 0
68 | },
69 | "meta": {
70 | "filename": "grumpy_lp.kicad_prl",
71 | "version": 3
72 | },
73 | "project": {
74 | "files": []
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/grumpy_ch552t/grumpy_ch522t.kicad_pro:
--------------------------------------------------------------------------------
1 | {
2 | "board": {
3 | "3dviewports": [],
4 | "design_settings": {
5 | "defaults": {
6 | "board_outline_line_width": 0.09999999999999999,
7 | "copper_line_width": 0.19999999999999998,
8 | "copper_text_italic": false,
9 | "copper_text_size_h": 1.5,
10 | "copper_text_size_v": 1.5,
11 | "copper_text_thickness": 0.3,
12 | "copper_text_upright": false,
13 | "courtyard_line_width": 0.049999999999999996,
14 | "dimension_precision": 4,
15 | "dimension_units": 3,
16 | "dimensions": {
17 | "arrow_length": 1270000,
18 | "extension_offset": 500000,
19 | "keep_text_aligned": true,
20 | "suppress_zeroes": false,
21 | "text_position": 0,
22 | "units_format": 1
23 | },
24 | "fab_line_width": 0.09999999999999999,
25 | "fab_text_italic": false,
26 | "fab_text_size_h": 1.0,
27 | "fab_text_size_v": 1.0,
28 | "fab_text_thickness": 0.15,
29 | "fab_text_upright": false,
30 | "other_line_width": 0.15,
31 | "other_text_italic": false,
32 | "other_text_size_h": 1.0,
33 | "other_text_size_v": 1.0,
34 | "other_text_thickness": 0.15,
35 | "other_text_upright": false,
36 | "pads": {
37 | "drill": 2.2,
38 | "height": 2.2,
39 | "width": 2.2
40 | },
41 | "silk_line_width": 0.15,
42 | "silk_text_italic": false,
43 | "silk_text_size_h": 1.0,
44 | "silk_text_size_v": 1.0,
45 | "silk_text_thickness": 0.15,
46 | "silk_text_upright": false,
47 | "zones": {
48 | "min_clearance": 0.5
49 | }
50 | },
51 | "diff_pair_dimensions": [],
52 | "drc_exclusions": [],
53 | "meta": {
54 | "version": 2
55 | },
56 | "rule_severities": {
57 | "annular_width": "error",
58 | "clearance": "error",
59 | "connection_width": "warning",
60 | "copper_edge_clearance": "error",
61 | "copper_sliver": "warning",
62 | "courtyards_overlap": "error",
63 | "diff_pair_gap_out_of_range": "error",
64 | "diff_pair_uncoupled_length_too_long": "error",
65 | "drill_out_of_range": "error",
66 | "duplicate_footprints": "warning",
67 | "extra_footprint": "warning",
68 | "footprint": "error",
69 | "footprint_type_mismatch": "ignore",
70 | "hole_clearance": "ignore",
71 | "hole_near_hole": "ignore",
72 | "invalid_outline": "error",
73 | "isolated_copper": "warning",
74 | "item_on_disabled_layer": "error",
75 | "items_not_allowed": "error",
76 | "length_out_of_range": "error",
77 | "lib_footprint_issues": "warning",
78 | "lib_footprint_mismatch": "warning",
79 | "malformed_courtyard": "error",
80 | "microvia_drill_out_of_range": "error",
81 | "missing_courtyard": "ignore",
82 | "missing_footprint": "warning",
83 | "net_conflict": "warning",
84 | "npth_inside_courtyard": "ignore",
85 | "padstack": "warning",
86 | "pth_inside_courtyard": "ignore",
87 | "shorting_items": "error",
88 | "silk_edge_clearance": "ignore",
89 | "silk_over_copper": "ignore",
90 | "silk_overlap": "ignore",
91 | "skew_out_of_range": "error",
92 | "solder_mask_bridge": "ignore",
93 | "starved_thermal": "error",
94 | "text_height": "warning",
95 | "text_thickness": "warning",
96 | "through_hole_pad_without_hole": "error",
97 | "too_many_vias": "error",
98 | "track_dangling": "warning",
99 | "track_width": "error",
100 | "tracks_crossing": "error",
101 | "unconnected_items": "error",
102 | "unresolved_variable": "error",
103 | "via_dangling": "warning",
104 | "zones_intersect": "error"
105 | },
106 | "rules": {
107 | "max_error": 0.005,
108 | "min_clearance": 0.0,
109 | "min_connection": 0.0,
110 | "min_copper_edge_clearance": 0.0,
111 | "min_hole_clearance": 0.25,
112 | "min_hole_to_hole": 0.25,
113 | "min_microvia_diameter": 0.19999999999999998,
114 | "min_microvia_drill": 0.09999999999999999,
115 | "min_resolved_spokes": 2,
116 | "min_silk_clearance": 0.0,
117 | "min_text_height": 0.7999999999999999,
118 | "min_text_thickness": 0.08,
119 | "min_through_hole_diameter": 0.3,
120 | "min_track_width": 0.0,
121 | "min_via_annular_width": 0.09999999999999999,
122 | "min_via_diameter": 0.5,
123 | "solder_mask_clearance": 0.0,
124 | "solder_mask_min_width": 0.0,
125 | "solder_mask_to_copper_clearance": 0.0,
126 | "use_height_for_length_calcs": true
127 | },
128 | "teardrop_options": [
129 | {
130 | "td_allow_use_two_tracks": true,
131 | "td_curve_segcount": 5,
132 | "td_on_pad_in_zone": false,
133 | "td_onpadsmd": true,
134 | "td_onroundshapesonly": false,
135 | "td_ontrackend": false,
136 | "td_onviapad": true
137 | }
138 | ],
139 | "teardrop_parameters": [
140 | {
141 | "td_curve_segcount": 0,
142 | "td_height_ratio": 1.0,
143 | "td_length_ratio": 0.5,
144 | "td_maxheight": 2.0,
145 | "td_maxlen": 1.0,
146 | "td_target_name": "td_round_shape",
147 | "td_width_to_size_filter_ratio": 0.9
148 | },
149 | {
150 | "td_curve_segcount": 0,
151 | "td_height_ratio": 1.0,
152 | "td_length_ratio": 0.5,
153 | "td_maxheight": 2.0,
154 | "td_maxlen": 1.0,
155 | "td_target_name": "td_rect_shape",
156 | "td_width_to_size_filter_ratio": 0.9
157 | },
158 | {
159 | "td_curve_segcount": 0,
160 | "td_height_ratio": 1.0,
161 | "td_length_ratio": 0.5,
162 | "td_maxheight": 2.0,
163 | "td_maxlen": 1.0,
164 | "td_target_name": "td_track_end",
165 | "td_width_to_size_filter_ratio": 0.9
166 | }
167 | ],
168 | "track_widths": [],
169 | "via_dimensions": [],
170 | "zones_allow_external_fillets": false
171 | },
172 | "layer_presets": [],
173 | "viewports": []
174 | },
175 | "boards": [],
176 | "cvpcb": {
177 | "equivalence_files": []
178 | },
179 | "erc": {
180 | "erc_exclusions": [],
181 | "meta": {
182 | "version": 0
183 | },
184 | "pin_map": [
185 | [
186 | 0,
187 | 0,
188 | 0,
189 | 0,
190 | 0,
191 | 0,
192 | 1,
193 | 0,
194 | 0,
195 | 0,
196 | 0,
197 | 2
198 | ],
199 | [
200 | 0,
201 | 2,
202 | 0,
203 | 1,
204 | 0,
205 | 0,
206 | 1,
207 | 0,
208 | 2,
209 | 2,
210 | 2,
211 | 2
212 | ],
213 | [
214 | 0,
215 | 0,
216 | 0,
217 | 0,
218 | 0,
219 | 0,
220 | 1,
221 | 0,
222 | 1,
223 | 0,
224 | 1,
225 | 2
226 | ],
227 | [
228 | 0,
229 | 1,
230 | 0,
231 | 0,
232 | 0,
233 | 0,
234 | 1,
235 | 1,
236 | 2,
237 | 1,
238 | 1,
239 | 2
240 | ],
241 | [
242 | 0,
243 | 0,
244 | 0,
245 | 0,
246 | 0,
247 | 0,
248 | 1,
249 | 0,
250 | 0,
251 | 0,
252 | 0,
253 | 2
254 | ],
255 | [
256 | 0,
257 | 0,
258 | 0,
259 | 0,
260 | 0,
261 | 0,
262 | 0,
263 | 0,
264 | 0,
265 | 0,
266 | 0,
267 | 2
268 | ],
269 | [
270 | 1,
271 | 1,
272 | 1,
273 | 1,
274 | 1,
275 | 0,
276 | 1,
277 | 1,
278 | 1,
279 | 1,
280 | 1,
281 | 2
282 | ],
283 | [
284 | 0,
285 | 0,
286 | 0,
287 | 1,
288 | 0,
289 | 0,
290 | 1,
291 | 0,
292 | 0,
293 | 0,
294 | 0,
295 | 2
296 | ],
297 | [
298 | 0,
299 | 2,
300 | 1,
301 | 2,
302 | 0,
303 | 0,
304 | 1,
305 | 0,
306 | 2,
307 | 2,
308 | 2,
309 | 2
310 | ],
311 | [
312 | 0,
313 | 2,
314 | 0,
315 | 1,
316 | 0,
317 | 0,
318 | 1,
319 | 0,
320 | 2,
321 | 0,
322 | 0,
323 | 2
324 | ],
325 | [
326 | 0,
327 | 2,
328 | 1,
329 | 1,
330 | 0,
331 | 0,
332 | 1,
333 | 0,
334 | 2,
335 | 0,
336 | 0,
337 | 2
338 | ],
339 | [
340 | 2,
341 | 2,
342 | 2,
343 | 2,
344 | 2,
345 | 2,
346 | 2,
347 | 2,
348 | 2,
349 | 2,
350 | 2,
351 | 2
352 | ]
353 | ],
354 | "rule_severities": {
355 | "bus_definition_conflict": "error",
356 | "bus_entry_needed": "error",
357 | "bus_to_bus_conflict": "error",
358 | "bus_to_net_conflict": "error",
359 | "conflicting_netclasses": "error",
360 | "different_unit_footprint": "error",
361 | "different_unit_net": "error",
362 | "duplicate_reference": "error",
363 | "duplicate_sheet_names": "error",
364 | "endpoint_off_grid": "warning",
365 | "extra_units": "error",
366 | "global_label_dangling": "warning",
367 | "hier_label_mismatch": "error",
368 | "label_dangling": "error",
369 | "lib_symbol_issues": "warning",
370 | "missing_bidi_pin": "warning",
371 | "missing_input_pin": "warning",
372 | "missing_power_pin": "error",
373 | "missing_unit": "warning",
374 | "multiple_net_names": "warning",
375 | "net_not_bus_member": "warning",
376 | "no_connect_connected": "warning",
377 | "no_connect_dangling": "warning",
378 | "pin_not_connected": "error",
379 | "pin_not_driven": "error",
380 | "pin_to_pin": "warning",
381 | "power_pin_not_driven": "error",
382 | "similar_labels": "warning",
383 | "simulation_model_issue": "ignore",
384 | "unannotated": "error",
385 | "unit_value_mismatch": "error",
386 | "unresolved_variable": "error",
387 | "wire_dangling": "error"
388 | }
389 | },
390 | "libraries": {
391 | "pinned_footprint_libs": [],
392 | "pinned_symbol_libs": []
393 | },
394 | "meta": {
395 | "filename": "grumpy_lp.kicad_pro",
396 | "version": 1
397 | },
398 | "net_settings": {
399 | "classes": [
400 | {
401 | "bus_width": 12,
402 | "clearance": 0.2,
403 | "diff_pair_gap": 0.25,
404 | "diff_pair_via_gap": 0.25,
405 | "diff_pair_width": 0.2,
406 | "line_style": 0,
407 | "microvia_diameter": 0.3,
408 | "microvia_drill": 0.1,
409 | "name": "Default",
410 | "pcb_color": "rgba(0, 0, 0, 0.000)",
411 | "schematic_color": "rgba(0, 0, 0, 0.000)",
412 | "track_width": 0.25,
413 | "via_diameter": 0.5,
414 | "via_drill": 0.3,
415 | "wire_width": 6
416 | }
417 | ],
418 | "meta": {
419 | "version": 3
420 | },
421 | "net_colors": null,
422 | "netclass_assignments": null,
423 | "netclass_patterns": []
424 | },
425 | "pcbnew": {
426 | "last_paths": {
427 | "gencad": "",
428 | "idf": "",
429 | "netlist": "",
430 | "plot": "",
431 | "pos_files": "",
432 | "specctra_dsn": "",
433 | "step": "grumpy_lp_mx.step",
434 | "svg": "",
435 | "vrml": ""
436 | },
437 | "page_layout_descr_file": ""
438 | },
439 | "schematic": {
440 | "annotate_start_num": 0,
441 | "drawing": {
442 | "dashed_lines_dash_length_ratio": 12.0,
443 | "dashed_lines_gap_length_ratio": 3.0,
444 | "default_line_thickness": 6.0,
445 | "default_text_size": 50.0,
446 | "field_names": [],
447 | "intersheets_ref_own_page": false,
448 | "intersheets_ref_prefix": "",
449 | "intersheets_ref_short": false,
450 | "intersheets_ref_show": false,
451 | "intersheets_ref_suffix": "",
452 | "junction_size_choice": 3,
453 | "label_size_ratio": 0.375,
454 | "pin_symbol_size": 25.0,
455 | "text_offset_ratio": 0.15
456 | },
457 | "legacy_lib_dir": "",
458 | "legacy_lib_list": [],
459 | "meta": {
460 | "version": 1
461 | },
462 | "net_format_name": "",
463 | "page_layout_descr_file": "",
464 | "plot_directory": "",
465 | "spice_current_sheet_as_root": false,
466 | "spice_external_command": "spice \"%I\"",
467 | "spice_model_current_sheet_as_root": true,
468 | "spice_save_all_currents": false,
469 | "spice_save_all_voltages": false,
470 | "subpart_first_id": 65,
471 | "subpart_id_separator": 0
472 | },
473 | "sheets": [
474 | [
475 | "614a618d-e872-4108-be17-bc533570c595",
476 | ""
477 | ]
478 | ],
479 | "text_variables": {}
480 | }
481 |
--------------------------------------------------------------------------------
/grumpy_choc/fp-lib-table:
--------------------------------------------------------------------------------
1 | (fp_lib_table
2 | (version 7)
3 | (lib (name "mcu")(type "KiCad")(uri "/home/weteor/.build/kleeb/mcu.pretty")(options "")(descr ""))
4 | (lib (name "weteor")(type "KiCad")(uri "/home/weteor/.build/weteor_kicad_lib/footprints")(options "")(descr ""))
5 | (lib (name "pg1350")(type "KiCad")(uri "/home/weteor/.build/kleeb/pg1350.pretty")(options "")(descr ""))
6 | )
7 |
--------------------------------------------------------------------------------
/grumpy_choc/grumpy_choc.kicad_prl:
--------------------------------------------------------------------------------
1 | {
2 | "board": {
3 | "active_layer": 0,
4 | "active_layer_preset": "",
5 | "auto_track_width": true,
6 | "hidden_netclasses": [],
7 | "hidden_nets": [],
8 | "high_contrast_mode": 0,
9 | "net_color_mode": 1,
10 | "opacity": {
11 | "images": 0.6,
12 | "pads": 1.0,
13 | "tracks": 1.0,
14 | "vias": 1.0,
15 | "zones": 0.6
16 | },
17 | "selection_filter": {
18 | "dimensions": true,
19 | "footprints": true,
20 | "graphics": true,
21 | "keepouts": true,
22 | "lockedItems": true,
23 | "otherItems": true,
24 | "pads": true,
25 | "text": true,
26 | "tracks": true,
27 | "vias": true,
28 | "zones": true
29 | },
30 | "visible_items": [
31 | 0,
32 | 1,
33 | 2,
34 | 3,
35 | 4,
36 | 5,
37 | 8,
38 | 9,
39 | 10,
40 | 11,
41 | 12,
42 | 13,
43 | 15,
44 | 16,
45 | 17,
46 | 18,
47 | 19,
48 | 20,
49 | 21,
50 | 22,
51 | 23,
52 | 24,
53 | 25,
54 | 26,
55 | 27,
56 | 28,
57 | 29,
58 | 30,
59 | 32,
60 | 33,
61 | 34,
62 | 35,
63 | 36,
64 | 40
65 | ],
66 | "visible_layers": "ffcffff_ffffffff",
67 | "zone_display_mode": 0
68 | },
69 | "git": {
70 | "repo_password": "",
71 | "repo_type": "",
72 | "repo_username": "",
73 | "ssh_key": ""
74 | },
75 | "meta": {
76 | "filename": "grumpy_choc.kicad_prl",
77 | "version": 3
78 | },
79 | "project": {
80 | "files": []
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/grumpy_choc/grumpy_choc.kicad_pro:
--------------------------------------------------------------------------------
1 | {
2 | "board": {
3 | "3dviewports": [],
4 | "design_settings": {
5 | "defaults": {
6 | "apply_defaults_to_fp_fields": false,
7 | "apply_defaults_to_fp_shapes": false,
8 | "apply_defaults_to_fp_text": false,
9 | "board_outline_line_width": 0.1,
10 | "copper_line_width": 0.2,
11 | "copper_text_italic": false,
12 | "copper_text_size_h": 1.5,
13 | "copper_text_size_v": 1.5,
14 | "copper_text_thickness": 0.3,
15 | "copper_text_upright": false,
16 | "courtyard_line_width": 0.05,
17 | "dimension_precision": 4,
18 | "dimension_units": 3,
19 | "dimensions": {
20 | "arrow_length": 1270000,
21 | "extension_offset": 500000,
22 | "keep_text_aligned": true,
23 | "suppress_zeroes": false,
24 | "text_position": 0,
25 | "units_format": 1
26 | },
27 | "fab_line_width": 0.1,
28 | "fab_text_italic": false,
29 | "fab_text_size_h": 1.0,
30 | "fab_text_size_v": 1.0,
31 | "fab_text_thickness": 0.15,
32 | "fab_text_upright": false,
33 | "other_line_width": 0.15,
34 | "other_text_italic": false,
35 | "other_text_size_h": 1.0,
36 | "other_text_size_v": 1.0,
37 | "other_text_thickness": 0.15,
38 | "other_text_upright": false,
39 | "pads": {
40 | "drill": 4.0,
41 | "height": 4.0,
42 | "width": 4.0
43 | },
44 | "silk_line_width": 0.15,
45 | "silk_text_italic": false,
46 | "silk_text_size_h": 1.0,
47 | "silk_text_size_v": 1.0,
48 | "silk_text_thickness": 0.15,
49 | "silk_text_upright": false,
50 | "zones": {
51 | "min_clearance": 0.5
52 | }
53 | },
54 | "diff_pair_dimensions": [],
55 | "drc_exclusions": [],
56 | "meta": {
57 | "version": 2
58 | },
59 | "rule_severities": {
60 | "annular_width": "error",
61 | "clearance": "error",
62 | "connection_width": "warning",
63 | "copper_edge_clearance": "error",
64 | "copper_sliver": "warning",
65 | "courtyards_overlap": "error",
66 | "diff_pair_gap_out_of_range": "error",
67 | "diff_pair_uncoupled_length_too_long": "error",
68 | "drill_out_of_range": "error",
69 | "duplicate_footprints": "warning",
70 | "extra_footprint": "warning",
71 | "footprint": "error",
72 | "footprint_symbol_mismatch": "warning",
73 | "footprint_type_mismatch": "ignore",
74 | "hole_clearance": "ignore",
75 | "hole_near_hole": "ignore",
76 | "holes_co_located": "warning",
77 | "invalid_outline": "error",
78 | "isolated_copper": "warning",
79 | "item_on_disabled_layer": "error",
80 | "items_not_allowed": "error",
81 | "length_out_of_range": "error",
82 | "lib_footprint_issues": "warning",
83 | "lib_footprint_mismatch": "warning",
84 | "malformed_courtyard": "error",
85 | "microvia_drill_out_of_range": "error",
86 | "missing_courtyard": "ignore",
87 | "missing_footprint": "warning",
88 | "net_conflict": "warning",
89 | "npth_inside_courtyard": "ignore",
90 | "padstack": "warning",
91 | "pth_inside_courtyard": "ignore",
92 | "shorting_items": "error",
93 | "silk_edge_clearance": "ignore",
94 | "silk_over_copper": "ignore",
95 | "silk_overlap": "ignore",
96 | "skew_out_of_range": "error",
97 | "solder_mask_bridge": "ignore",
98 | "starved_thermal": "error",
99 | "text_height": "warning",
100 | "text_thickness": "warning",
101 | "through_hole_pad_without_hole": "error",
102 | "too_many_vias": "error",
103 | "track_dangling": "warning",
104 | "track_width": "error",
105 | "tracks_crossing": "error",
106 | "unconnected_items": "error",
107 | "unresolved_variable": "error",
108 | "via_dangling": "warning",
109 | "zones_intersect": "error"
110 | },
111 | "rules": {
112 | "max_error": 0.005,
113 | "min_clearance": 0.0,
114 | "min_connection": 0.0,
115 | "min_copper_edge_clearance": 0.3,
116 | "min_hole_clearance": 0.25,
117 | "min_hole_to_hole": 0.25,
118 | "min_microvia_diameter": 0.2,
119 | "min_microvia_drill": 0.1,
120 | "min_resolved_spokes": 2,
121 | "min_silk_clearance": 0.0,
122 | "min_text_height": 0.8,
123 | "min_text_thickness": 0.08,
124 | "min_through_hole_diameter": 0.3,
125 | "min_track_width": 0.0,
126 | "min_via_annular_width": 0.1,
127 | "min_via_diameter": 0.5,
128 | "solder_mask_clearance": 0.0,
129 | "solder_mask_min_width": 0.0,
130 | "solder_mask_to_copper_clearance": 0.0,
131 | "use_height_for_length_calcs": true
132 | },
133 | "teardrop_options": [
134 | {
135 | "td_onpadsmd": true,
136 | "td_onroundshapesonly": false,
137 | "td_ontrackend": false,
138 | "td_onviapad": true
139 | }
140 | ],
141 | "teardrop_parameters": [
142 | {
143 | "td_allow_use_two_tracks": true,
144 | "td_curve_segcount": 0,
145 | "td_height_ratio": 1.0,
146 | "td_length_ratio": 0.5,
147 | "td_maxheight": 2.0,
148 | "td_maxlen": 1.0,
149 | "td_on_pad_in_zone": false,
150 | "td_target_name": "td_round_shape",
151 | "td_width_to_size_filter_ratio": 0.9
152 | },
153 | {
154 | "td_allow_use_two_tracks": true,
155 | "td_curve_segcount": 0,
156 | "td_height_ratio": 1.0,
157 | "td_length_ratio": 0.5,
158 | "td_maxheight": 2.0,
159 | "td_maxlen": 1.0,
160 | "td_on_pad_in_zone": false,
161 | "td_target_name": "td_rect_shape",
162 | "td_width_to_size_filter_ratio": 0.9
163 | },
164 | {
165 | "td_allow_use_two_tracks": true,
166 | "td_curve_segcount": 0,
167 | "td_height_ratio": 1.0,
168 | "td_length_ratio": 0.5,
169 | "td_maxheight": 2.0,
170 | "td_maxlen": 1.0,
171 | "td_on_pad_in_zone": false,
172 | "td_target_name": "td_track_end",
173 | "td_width_to_size_filter_ratio": 0.9
174 | }
175 | ],
176 | "track_widths": [],
177 | "tuning_pattern_settings": {
178 | "diff_pair_defaults": {
179 | "corner_radius_percentage": 80,
180 | "corner_style": 1,
181 | "max_amplitude": 1.0,
182 | "min_amplitude": 0.2,
183 | "single_sided": false,
184 | "spacing": 1.0
185 | },
186 | "diff_pair_skew_defaults": {
187 | "corner_radius_percentage": 80,
188 | "corner_style": 1,
189 | "max_amplitude": 1.0,
190 | "min_amplitude": 0.2,
191 | "single_sided": false,
192 | "spacing": 0.6
193 | },
194 | "single_track_defaults": {
195 | "corner_radius_percentage": 80,
196 | "corner_style": 1,
197 | "max_amplitude": 1.0,
198 | "min_amplitude": 0.2,
199 | "single_sided": false,
200 | "spacing": 0.6
201 | }
202 | },
203 | "via_dimensions": [],
204 | "zones_allow_external_fillets": false
205 | },
206 | "ipc2581": {
207 | "dist": "",
208 | "distpn": "",
209 | "internal_id": "",
210 | "mfg": "",
211 | "mpn": ""
212 | },
213 | "layer_presets": [],
214 | "viewports": []
215 | },
216 | "boards": [],
217 | "cvpcb": {
218 | "equivalence_files": []
219 | },
220 | "erc": {
221 | "erc_exclusions": [],
222 | "meta": {
223 | "version": 0
224 | },
225 | "pin_map": [
226 | [
227 | 0,
228 | 0,
229 | 0,
230 | 0,
231 | 0,
232 | 0,
233 | 1,
234 | 0,
235 | 0,
236 | 0,
237 | 0,
238 | 2
239 | ],
240 | [
241 | 0,
242 | 2,
243 | 0,
244 | 1,
245 | 0,
246 | 0,
247 | 1,
248 | 0,
249 | 2,
250 | 2,
251 | 2,
252 | 2
253 | ],
254 | [
255 | 0,
256 | 0,
257 | 0,
258 | 0,
259 | 0,
260 | 0,
261 | 1,
262 | 0,
263 | 1,
264 | 0,
265 | 1,
266 | 2
267 | ],
268 | [
269 | 0,
270 | 1,
271 | 0,
272 | 0,
273 | 0,
274 | 0,
275 | 1,
276 | 1,
277 | 2,
278 | 1,
279 | 1,
280 | 2
281 | ],
282 | [
283 | 0,
284 | 0,
285 | 0,
286 | 0,
287 | 0,
288 | 0,
289 | 1,
290 | 0,
291 | 0,
292 | 0,
293 | 0,
294 | 2
295 | ],
296 | [
297 | 0,
298 | 0,
299 | 0,
300 | 0,
301 | 0,
302 | 0,
303 | 0,
304 | 0,
305 | 0,
306 | 0,
307 | 0,
308 | 2
309 | ],
310 | [
311 | 1,
312 | 1,
313 | 1,
314 | 1,
315 | 1,
316 | 0,
317 | 1,
318 | 1,
319 | 1,
320 | 1,
321 | 1,
322 | 2
323 | ],
324 | [
325 | 0,
326 | 0,
327 | 0,
328 | 1,
329 | 0,
330 | 0,
331 | 1,
332 | 0,
333 | 0,
334 | 0,
335 | 0,
336 | 2
337 | ],
338 | [
339 | 0,
340 | 2,
341 | 1,
342 | 2,
343 | 0,
344 | 0,
345 | 1,
346 | 0,
347 | 2,
348 | 2,
349 | 2,
350 | 2
351 | ],
352 | [
353 | 0,
354 | 2,
355 | 0,
356 | 1,
357 | 0,
358 | 0,
359 | 1,
360 | 0,
361 | 2,
362 | 0,
363 | 0,
364 | 2
365 | ],
366 | [
367 | 0,
368 | 2,
369 | 1,
370 | 1,
371 | 0,
372 | 0,
373 | 1,
374 | 0,
375 | 2,
376 | 0,
377 | 0,
378 | 2
379 | ],
380 | [
381 | 2,
382 | 2,
383 | 2,
384 | 2,
385 | 2,
386 | 2,
387 | 2,
388 | 2,
389 | 2,
390 | 2,
391 | 2,
392 | 2
393 | ]
394 | ],
395 | "rule_severities": {
396 | "bus_definition_conflict": "error",
397 | "bus_entry_needed": "error",
398 | "bus_to_bus_conflict": "error",
399 | "bus_to_net_conflict": "error",
400 | "conflicting_netclasses": "error",
401 | "different_unit_footprint": "error",
402 | "different_unit_net": "error",
403 | "duplicate_reference": "error",
404 | "duplicate_sheet_names": "error",
405 | "endpoint_off_grid": "warning",
406 | "extra_units": "error",
407 | "global_label_dangling": "warning",
408 | "hier_label_mismatch": "error",
409 | "label_dangling": "error",
410 | "lib_symbol_issues": "warning",
411 | "missing_bidi_pin": "warning",
412 | "missing_input_pin": "warning",
413 | "missing_power_pin": "error",
414 | "missing_unit": "warning",
415 | "multiple_net_names": "warning",
416 | "net_not_bus_member": "warning",
417 | "no_connect_connected": "warning",
418 | "no_connect_dangling": "warning",
419 | "pin_not_connected": "error",
420 | "pin_not_driven": "error",
421 | "pin_to_pin": "warning",
422 | "power_pin_not_driven": "error",
423 | "similar_labels": "warning",
424 | "simulation_model_issue": "ignore",
425 | "unannotated": "error",
426 | "unit_value_mismatch": "error",
427 | "unresolved_variable": "error",
428 | "wire_dangling": "error"
429 | }
430 | },
431 | "libraries": {
432 | "pinned_footprint_libs": [],
433 | "pinned_symbol_libs": []
434 | },
435 | "meta": {
436 | "filename": "grumpy_choc.kicad_pro",
437 | "version": 1
438 | },
439 | "net_settings": {
440 | "classes": [
441 | {
442 | "bus_width": 12,
443 | "clearance": 0.2,
444 | "diff_pair_gap": 0.25,
445 | "diff_pair_via_gap": 0.25,
446 | "diff_pair_width": 0.2,
447 | "line_style": 0,
448 | "microvia_diameter": 0.3,
449 | "microvia_drill": 0.1,
450 | "name": "Default",
451 | "pcb_color": "rgba(0, 0, 0, 0.000)",
452 | "schematic_color": "rgba(0, 0, 0, 0.000)",
453 | "track_width": 0.25,
454 | "via_diameter": 0.5,
455 | "via_drill": 0.3,
456 | "wire_width": 6
457 | }
458 | ],
459 | "meta": {
460 | "version": 3
461 | },
462 | "net_colors": null,
463 | "netclass_assignments": null,
464 | "netclass_patterns": []
465 | },
466 | "pcbnew": {
467 | "last_paths": {
468 | "gencad": "",
469 | "idf": "",
470 | "netlist": "",
471 | "plot": "gerber/",
472 | "pos_files": "",
473 | "specctra_dsn": "",
474 | "step": "grumpy_lp_choc.step",
475 | "svg": "",
476 | "vrml": ""
477 | },
478 | "page_layout_descr_file": ""
479 | },
480 | "schematic": {
481 | "annotate_start_num": 0,
482 | "bom_export_filename": "",
483 | "bom_fmt_presets": [],
484 | "bom_fmt_settings": {
485 | "field_delimiter": ",",
486 | "keep_line_breaks": false,
487 | "keep_tabs": false,
488 | "name": "CSV",
489 | "ref_delimiter": ",",
490 | "ref_range_delimiter": "",
491 | "string_delimiter": "\""
492 | },
493 | "bom_presets": [],
494 | "bom_settings": {
495 | "exclude_dnp": false,
496 | "fields_ordered": [
497 | {
498 | "group_by": false,
499 | "label": "Reference",
500 | "name": "Reference",
501 | "show": true
502 | },
503 | {
504 | "group_by": true,
505 | "label": "Value",
506 | "name": "Value",
507 | "show": true
508 | },
509 | {
510 | "group_by": false,
511 | "label": "Datasheet",
512 | "name": "Datasheet",
513 | "show": true
514 | },
515 | {
516 | "group_by": false,
517 | "label": "Footprint",
518 | "name": "Footprint",
519 | "show": true
520 | },
521 | {
522 | "group_by": false,
523 | "label": "Qty",
524 | "name": "${QUANTITY}",
525 | "show": true
526 | },
527 | {
528 | "group_by": true,
529 | "label": "DNP",
530 | "name": "${DNP}",
531 | "show": true
532 | }
533 | ],
534 | "filter_string": "",
535 | "group_symbols": true,
536 | "name": "Grouped By Value",
537 | "sort_asc": true,
538 | "sort_field": "Reference"
539 | },
540 | "connection_grid_size": 50.0,
541 | "drawing": {
542 | "dashed_lines_dash_length_ratio": 12.0,
543 | "dashed_lines_gap_length_ratio": 3.0,
544 | "default_line_thickness": 6.0,
545 | "default_text_size": 50.0,
546 | "field_names": [],
547 | "intersheets_ref_own_page": false,
548 | "intersheets_ref_prefix": "",
549 | "intersheets_ref_short": false,
550 | "intersheets_ref_show": false,
551 | "intersheets_ref_suffix": "",
552 | "junction_size_choice": 3,
553 | "label_size_ratio": 0.375,
554 | "operating_point_overlay_i_precision": 3,
555 | "operating_point_overlay_i_range": "~A",
556 | "operating_point_overlay_v_precision": 3,
557 | "operating_point_overlay_v_range": "~V",
558 | "overbar_offset_ratio": 1.23,
559 | "pin_symbol_size": 25.0,
560 | "text_offset_ratio": 0.15
561 | },
562 | "legacy_lib_dir": "",
563 | "legacy_lib_list": [],
564 | "meta": {
565 | "version": 1
566 | },
567 | "net_format_name": "",
568 | "page_layout_descr_file": "",
569 | "plot_directory": "",
570 | "spice_current_sheet_as_root": false,
571 | "spice_external_command": "spice \"%I\"",
572 | "spice_model_current_sheet_as_root": true,
573 | "spice_save_all_currents": false,
574 | "spice_save_all_dissipations": false,
575 | "spice_save_all_voltages": false,
576 | "subpart_first_id": 65,
577 | "subpart_id_separator": 0
578 | },
579 | "sheets": [
580 | [
581 | "614a618d-e872-4108-be17-bc533570c595",
582 | "Root"
583 | ]
584 | ],
585 | "text_variables": {}
586 | }
587 |
--------------------------------------------------------------------------------
/grumpy_choc/sym-lib-table:
--------------------------------------------------------------------------------
1 | (sym_lib_table
2 | (version 7)
3 | (lib (name "mcu")(type "KiCad")(uri "/home/weteor/.build/kleeb/mcu.kicad_sym")(options "")(descr ""))
4 | )
5 |
--------------------------------------------------------------------------------
/grumpy_xiao/grumpy.kicad_prl:
--------------------------------------------------------------------------------
1 | {
2 | "board": {
3 | "active_layer": 31,
4 | "active_layer_preset": "",
5 | "auto_track_width": true,
6 | "hidden_netclasses": [],
7 | "hidden_nets": [],
8 | "high_contrast_mode": 0,
9 | "net_color_mode": 1,
10 | "opacity": {
11 | "images": 0.6,
12 | "pads": 1.0,
13 | "tracks": 1.0,
14 | "vias": 1.0,
15 | "zones": 0.6
16 | },
17 | "selection_filter": {
18 | "dimensions": true,
19 | "footprints": true,
20 | "graphics": true,
21 | "keepouts": true,
22 | "lockedItems": true,
23 | "otherItems": true,
24 | "pads": true,
25 | "text": true,
26 | "tracks": true,
27 | "vias": true,
28 | "zones": true
29 | },
30 | "visible_items": [
31 | 0,
32 | 1,
33 | 2,
34 | 3,
35 | 4,
36 | 5,
37 | 8,
38 | 9,
39 | 10,
40 | 11,
41 | 12,
42 | 13,
43 | 15,
44 | 16,
45 | 17,
46 | 18,
47 | 19,
48 | 20,
49 | 21,
50 | 22,
51 | 23,
52 | 24,
53 | 25,
54 | 26,
55 | 27,
56 | 28,
57 | 29,
58 | 30,
59 | 32,
60 | 33,
61 | 34,
62 | 35,
63 | 36,
64 | 40
65 | ],
66 | "visible_layers": "fffffff_ffffffff",
67 | "zone_display_mode": 0
68 | },
69 | "meta": {
70 | "filename": "grumpy.kicad_prl",
71 | "version": 3
72 | },
73 | "project": {
74 | "files": []
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/grumpy_xiao/grumpy.kicad_pro:
--------------------------------------------------------------------------------
1 | {
2 | "board": {
3 | "3dviewports": [],
4 | "design_settings": {
5 | "defaults": {
6 | "board_outline_line_width": 0.09999999999999999,
7 | "copper_line_width": 0.19999999999999998,
8 | "copper_text_italic": false,
9 | "copper_text_size_h": 1.5,
10 | "copper_text_size_v": 1.5,
11 | "copper_text_thickness": 0.3,
12 | "copper_text_upright": false,
13 | "courtyard_line_width": 0.049999999999999996,
14 | "dimension_precision": 4,
15 | "dimension_units": 3,
16 | "dimensions": {
17 | "arrow_length": 1270000,
18 | "extension_offset": 500000,
19 | "keep_text_aligned": true,
20 | "suppress_zeroes": false,
21 | "text_position": 0,
22 | "units_format": 1
23 | },
24 | "fab_line_width": 0.09999999999999999,
25 | "fab_text_italic": false,
26 | "fab_text_size_h": 1.0,
27 | "fab_text_size_v": 1.0,
28 | "fab_text_thickness": 0.15,
29 | "fab_text_upright": false,
30 | "other_line_width": 0.15,
31 | "other_text_italic": false,
32 | "other_text_size_h": 1.0,
33 | "other_text_size_v": 1.0,
34 | "other_text_thickness": 0.15,
35 | "other_text_upright": false,
36 | "pads": {
37 | "drill": 0.762,
38 | "height": 1.524,
39 | "width": 1.524
40 | },
41 | "silk_line_width": 0.15,
42 | "silk_text_italic": false,
43 | "silk_text_size_h": 1.0,
44 | "silk_text_size_v": 1.0,
45 | "silk_text_thickness": 0.15,
46 | "silk_text_upright": false,
47 | "zones": {
48 | "min_clearance": 0.5
49 | }
50 | },
51 | "diff_pair_dimensions": [],
52 | "drc_exclusions": [],
53 | "meta": {
54 | "version": 2
55 | },
56 | "rule_severities": {
57 | "annular_width": "error",
58 | "clearance": "error",
59 | "connection_width": "warning",
60 | "copper_edge_clearance": "error",
61 | "copper_sliver": "warning",
62 | "courtyards_overlap": "error",
63 | "diff_pair_gap_out_of_range": "error",
64 | "diff_pair_uncoupled_length_too_long": "error",
65 | "drill_out_of_range": "error",
66 | "duplicate_footprints": "warning",
67 | "extra_footprint": "warning",
68 | "footprint": "error",
69 | "footprint_type_mismatch": "ignore",
70 | "hole_clearance": "error",
71 | "hole_near_hole": "error",
72 | "invalid_outline": "error",
73 | "isolated_copper": "warning",
74 | "item_on_disabled_layer": "error",
75 | "items_not_allowed": "error",
76 | "length_out_of_range": "error",
77 | "lib_footprint_issues": "warning",
78 | "lib_footprint_mismatch": "warning",
79 | "malformed_courtyard": "error",
80 | "microvia_drill_out_of_range": "error",
81 | "missing_courtyard": "ignore",
82 | "missing_footprint": "warning",
83 | "net_conflict": "warning",
84 | "npth_inside_courtyard": "ignore",
85 | "padstack": "warning",
86 | "pth_inside_courtyard": "ignore",
87 | "shorting_items": "error",
88 | "silk_edge_clearance": "warning",
89 | "silk_over_copper": "ignore",
90 | "silk_overlap": "ignore",
91 | "skew_out_of_range": "error",
92 | "solder_mask_bridge": "error",
93 | "starved_thermal": "error",
94 | "text_height": "warning",
95 | "text_thickness": "warning",
96 | "through_hole_pad_without_hole": "error",
97 | "too_many_vias": "error",
98 | "track_dangling": "warning",
99 | "track_width": "error",
100 | "tracks_crossing": "error",
101 | "unconnected_items": "error",
102 | "unresolved_variable": "error",
103 | "via_dangling": "warning",
104 | "zones_intersect": "error"
105 | },
106 | "rules": {
107 | "max_error": 0.005,
108 | "min_clearance": 0.0,
109 | "min_connection": 0.0,
110 | "min_copper_edge_clearance": 0.0,
111 | "min_hole_clearance": 0.25,
112 | "min_hole_to_hole": 0.25,
113 | "min_microvia_diameter": 0.19999999999999998,
114 | "min_microvia_drill": 0.09999999999999999,
115 | "min_resolved_spokes": 2,
116 | "min_silk_clearance": 0.0,
117 | "min_text_height": 0.7999999999999999,
118 | "min_text_thickness": 0.08,
119 | "min_through_hole_diameter": 0.3,
120 | "min_track_width": 0.0,
121 | "min_via_annular_width": 0.09999999999999999,
122 | "min_via_diameter": 0.5,
123 | "solder_mask_clearance": 0.0,
124 | "solder_mask_min_width": 0.0,
125 | "solder_mask_to_copper_clearance": 0.0,
126 | "use_height_for_length_calcs": true
127 | },
128 | "teardrop_options": [
129 | {
130 | "td_onpadsmd": true,
131 | "td_onroundshapesonly": false,
132 | "td_ontrackend": false,
133 | "td_onviapad": true
134 | }
135 | ],
136 | "teardrop_parameters": [
137 | {
138 | "td_allow_use_two_tracks": true,
139 | "td_curve_segcount": 0,
140 | "td_height_ratio": 1.0,
141 | "td_length_ratio": 0.5,
142 | "td_maxheight": 2.0,
143 | "td_maxlen": 1.0,
144 | "td_on_pad_in_zone": false,
145 | "td_target_name": "td_round_shape",
146 | "td_width_to_size_filter_ratio": 0.9
147 | },
148 | {
149 | "td_allow_use_two_tracks": true,
150 | "td_curve_segcount": 0,
151 | "td_height_ratio": 1.0,
152 | "td_length_ratio": 0.5,
153 | "td_maxheight": 2.0,
154 | "td_maxlen": 1.0,
155 | "td_on_pad_in_zone": false,
156 | "td_target_name": "td_rect_shape",
157 | "td_width_to_size_filter_ratio": 0.9
158 | },
159 | {
160 | "td_allow_use_two_tracks": true,
161 | "td_curve_segcount": 0,
162 | "td_height_ratio": 1.0,
163 | "td_length_ratio": 0.5,
164 | "td_maxheight": 2.0,
165 | "td_maxlen": 1.0,
166 | "td_on_pad_in_zone": false,
167 | "td_target_name": "td_track_end",
168 | "td_width_to_size_filter_ratio": 0.9
169 | }
170 | ],
171 | "track_widths": [],
172 | "via_dimensions": [],
173 | "zones_allow_external_fillets": false
174 | },
175 | "layer_presets": [],
176 | "viewports": []
177 | },
178 | "boards": [],
179 | "cvpcb": {
180 | "equivalence_files": []
181 | },
182 | "erc": {
183 | "erc_exclusions": [],
184 | "meta": {
185 | "version": 0
186 | },
187 | "pin_map": [
188 | [
189 | 0,
190 | 0,
191 | 0,
192 | 0,
193 | 0,
194 | 0,
195 | 1,
196 | 0,
197 | 0,
198 | 0,
199 | 0,
200 | 2
201 | ],
202 | [
203 | 0,
204 | 2,
205 | 0,
206 | 1,
207 | 0,
208 | 0,
209 | 1,
210 | 0,
211 | 2,
212 | 2,
213 | 2,
214 | 2
215 | ],
216 | [
217 | 0,
218 | 0,
219 | 0,
220 | 0,
221 | 0,
222 | 0,
223 | 1,
224 | 0,
225 | 1,
226 | 0,
227 | 1,
228 | 2
229 | ],
230 | [
231 | 0,
232 | 1,
233 | 0,
234 | 0,
235 | 0,
236 | 0,
237 | 1,
238 | 1,
239 | 2,
240 | 1,
241 | 1,
242 | 2
243 | ],
244 | [
245 | 0,
246 | 0,
247 | 0,
248 | 0,
249 | 0,
250 | 0,
251 | 1,
252 | 0,
253 | 0,
254 | 0,
255 | 0,
256 | 2
257 | ],
258 | [
259 | 0,
260 | 0,
261 | 0,
262 | 0,
263 | 0,
264 | 0,
265 | 0,
266 | 0,
267 | 0,
268 | 0,
269 | 0,
270 | 2
271 | ],
272 | [
273 | 1,
274 | 1,
275 | 1,
276 | 1,
277 | 1,
278 | 0,
279 | 1,
280 | 1,
281 | 1,
282 | 1,
283 | 1,
284 | 2
285 | ],
286 | [
287 | 0,
288 | 0,
289 | 0,
290 | 1,
291 | 0,
292 | 0,
293 | 1,
294 | 0,
295 | 0,
296 | 0,
297 | 0,
298 | 2
299 | ],
300 | [
301 | 0,
302 | 2,
303 | 1,
304 | 2,
305 | 0,
306 | 0,
307 | 1,
308 | 0,
309 | 2,
310 | 2,
311 | 2,
312 | 2
313 | ],
314 | [
315 | 0,
316 | 2,
317 | 0,
318 | 1,
319 | 0,
320 | 0,
321 | 1,
322 | 0,
323 | 2,
324 | 0,
325 | 0,
326 | 2
327 | ],
328 | [
329 | 0,
330 | 2,
331 | 1,
332 | 1,
333 | 0,
334 | 0,
335 | 1,
336 | 0,
337 | 2,
338 | 0,
339 | 0,
340 | 2
341 | ],
342 | [
343 | 2,
344 | 2,
345 | 2,
346 | 2,
347 | 2,
348 | 2,
349 | 2,
350 | 2,
351 | 2,
352 | 2,
353 | 2,
354 | 2
355 | ]
356 | ],
357 | "rule_severities": {
358 | "bus_definition_conflict": "error",
359 | "bus_entry_needed": "error",
360 | "bus_to_bus_conflict": "error",
361 | "bus_to_net_conflict": "error",
362 | "conflicting_netclasses": "error",
363 | "different_unit_footprint": "error",
364 | "different_unit_net": "error",
365 | "duplicate_reference": "error",
366 | "duplicate_sheet_names": "error",
367 | "endpoint_off_grid": "warning",
368 | "extra_units": "error",
369 | "global_label_dangling": "warning",
370 | "hier_label_mismatch": "error",
371 | "label_dangling": "error",
372 | "lib_symbol_issues": "warning",
373 | "missing_bidi_pin": "warning",
374 | "missing_input_pin": "warning",
375 | "missing_power_pin": "error",
376 | "missing_unit": "warning",
377 | "multiple_net_names": "warning",
378 | "net_not_bus_member": "warning",
379 | "no_connect_connected": "warning",
380 | "no_connect_dangling": "warning",
381 | "pin_not_connected": "error",
382 | "pin_not_driven": "error",
383 | "pin_to_pin": "warning",
384 | "power_pin_not_driven": "error",
385 | "similar_labels": "warning",
386 | "simulation_model_issue": "ignore",
387 | "unannotated": "error",
388 | "unit_value_mismatch": "error",
389 | "unresolved_variable": "error",
390 | "wire_dangling": "error"
391 | }
392 | },
393 | "libraries": {
394 | "pinned_footprint_libs": [],
395 | "pinned_symbol_libs": []
396 | },
397 | "meta": {
398 | "filename": "grumpy.kicad_pro",
399 | "version": 1
400 | },
401 | "net_settings": {
402 | "classes": [
403 | {
404 | "bus_width": 12,
405 | "clearance": 0.2,
406 | "diff_pair_gap": 0.25,
407 | "diff_pair_via_gap": 0.25,
408 | "diff_pair_width": 0.2,
409 | "line_style": 0,
410 | "microvia_diameter": 0.3,
411 | "microvia_drill": 0.1,
412 | "name": "Default",
413 | "pcb_color": "rgba(0, 0, 0, 0.000)",
414 | "schematic_color": "rgba(0, 0, 0, 0.000)",
415 | "track_width": 0.25,
416 | "via_diameter": 0.8,
417 | "via_drill": 0.4,
418 | "wire_width": 6
419 | }
420 | ],
421 | "meta": {
422 | "version": 3
423 | },
424 | "net_colors": null,
425 | "netclass_assignments": null,
426 | "netclass_patterns": []
427 | },
428 | "pcbnew": {
429 | "last_paths": {
430 | "gencad": "",
431 | "idf": "",
432 | "netlist": "",
433 | "plot": "",
434 | "pos_files": "",
435 | "specctra_dsn": "",
436 | "step": "grumpypcb.step",
437 | "svg": "",
438 | "vrml": ""
439 | },
440 | "page_layout_descr_file": ""
441 | },
442 | "schematic": {
443 | "annotate_start_num": 0,
444 | "drawing": {
445 | "dashed_lines_dash_length_ratio": 12.0,
446 | "dashed_lines_gap_length_ratio": 3.0,
447 | "default_line_thickness": 6.0,
448 | "default_text_size": 50.0,
449 | "field_names": [],
450 | "intersheets_ref_own_page": false,
451 | "intersheets_ref_prefix": "",
452 | "intersheets_ref_short": false,
453 | "intersheets_ref_show": false,
454 | "intersheets_ref_suffix": "",
455 | "junction_size_choice": 3,
456 | "label_size_ratio": 0.375,
457 | "pin_symbol_size": 25.0,
458 | "text_offset_ratio": 0.15
459 | },
460 | "legacy_lib_dir": "",
461 | "legacy_lib_list": [],
462 | "meta": {
463 | "version": 1
464 | },
465 | "net_format_name": "",
466 | "page_layout_descr_file": "",
467 | "plot_directory": "",
468 | "spice_current_sheet_as_root": false,
469 | "spice_external_command": "spice \"%I\"",
470 | "spice_model_current_sheet_as_root": true,
471 | "spice_save_all_currents": false,
472 | "spice_save_all_voltages": false,
473 | "subpart_first_id": 65,
474 | "subpart_id_separator": 0
475 | },
476 | "sheets": [
477 | [
478 | "614a618d-e872-4108-be17-bc533570c595",
479 | ""
480 | ]
481 | ],
482 | "text_variables": {}
483 | }
484 |
--------------------------------------------------------------------------------
/img/choc_v1_alu.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weteor/Grumpy/0a1ea6c46a17778650b71261e2852e8dad9eb8cc/img/choc_v1_alu.jpg
--------------------------------------------------------------------------------
/img/grumpies.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weteor/Grumpy/0a1ea6c46a17778650b71261e2852e8dad9eb8cc/img/grumpies.jpg
--------------------------------------------------------------------------------
/img/grumpy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weteor/Grumpy/0a1ea6c46a17778650b71261e2852e8dad9eb8cc/img/grumpy.png
--------------------------------------------------------------------------------
/img/grumpy_mjf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weteor/Grumpy/0a1ea6c46a17778650b71261e2852e8dad9eb8cc/img/grumpy_mjf.png
--------------------------------------------------------------------------------
/prod/ChocV1 low profile/case_choc/grumpy case threads drawing.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weteor/Grumpy/0a1ea6c46a17778650b71261e2852e8dad9eb8cc/prod/ChocV1 low profile/case_choc/grumpy case threads drawing.pdf
--------------------------------------------------------------------------------
/prod/ChocV1 low profile/grumpy_chocV1_GERBER_20250107.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weteor/Grumpy/0a1ea6c46a17778650b71261e2852e8dad9eb8cc/prod/ChocV1 low profile/grumpy_chocV1_GERBER_20250107.zip
--------------------------------------------------------------------------------
/prod/MX ChocV2 low profile/case_chocV2/grumpy_lp.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weteor/Grumpy/0a1ea6c46a17778650b71261e2852e8dad9eb8cc/prod/MX ChocV2 low profile/case_chocV2/grumpy_lp.stl
--------------------------------------------------------------------------------
/prod/MX ChocV2 low profile/case_chocV2/grumpy_lp_bottom.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weteor/Grumpy/0a1ea6c46a17778650b71261e2852e8dad9eb8cc/prod/MX ChocV2 low profile/case_chocV2/grumpy_lp_bottom.stl
--------------------------------------------------------------------------------
/prod/MX ChocV2 low profile/grumpy_chocV2_GERBER_20240611.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weteor/Grumpy/0a1ea6c46a17778650b71261e2852e8dad9eb8cc/prod/MX ChocV2 low profile/grumpy_chocV2_GERBER_20240611.zip
--------------------------------------------------------------------------------
/prod/MX Xiao/case_mx/grumpy.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weteor/Grumpy/0a1ea6c46a17778650b71261e2852e8dad9eb8cc/prod/MX Xiao/case_mx/grumpy.stl
--------------------------------------------------------------------------------
/prod/MX Xiao/grumpy_mx_GERBER_20230724.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weteor/Grumpy/0a1ea6c46a17778650b71261e2852e8dad9eb8cc/prod/MX Xiao/grumpy_mx_GERBER_20230724.zip
--------------------------------------------------------------------------------