]> git.armaanb.net Git - atreides.git/blob - atreus.rkt
Programmatically place repeated traces.
[atreides.git] / atreus.rkt
1 #lang racket
2
3 (define cols 6)
4 (define rows 4)
5
6 (define x-offset 20)
7 (define y-offset 20)
8
9 (define spacing 19)
10 (define angle 0)
11
12 (define column-offsets '(8 5 0 6 11 15))
13
14 (define (switch-module x y rotation label net-pos net-neg)
15   `(module MX_FLIP (layer Front) (tedit 4FD81CDD) (tstamp 543EF801)
16     (at ,x ,y ,rotation)
17     (path /543DB910)
18     (fp_text reference ,label (at 0 3.302 ,rotation) (layer F.SilkS)
19              (effects (font (size 1.524 1.778) (thickness 0.254))))
20     (fp_line (start -6.35 -6.35) (end 6.35 -6.35)
21              (layer F.SilkS) (width 0.381))
22     (fp_line (start 6.35 -6.35) (end 6.35 6.35)
23              (layer F.SilkS) (width 0.381))
24     (fp_line (start 6.35 6.35) (end -6.35 6.35)
25              (layer F.SilkS) (width 0.381))
26     (fp_line (start -6.35 6.35) (end -6.35 -6.35)
27              (layer F.SilkS) (width 0.381))
28     (pad 0 np_thru_hole circle (at 0 0) (size 3.9878 3.9878)
29          (drill 3.9878)) ; switch hole, no copper
30     (pad 0 np_thru_hole circle (at -5.08 0) (size 1.7018 1.7018)
31          (drill 1.7018)) ; board-mount hole, no copper
32     (pad 0 np_thru_hole circle (at 5.08 0) (size 1.7018 1.7018)
33          (drill 1.7018)) ; board-mount hole, no copper
34     (pad 1 thru_hole circle (at 2.54 -5.08) (size 2.286 2.286) (drill 1.4986)
35          (layers *.Cu *.SilkS *.Mask) ,net-pos)
36     (pad 1 thru_hole circle (at 3.81 -2.54) (size 2.286 2.286) (drill 1.4986)
37          (layers *.Cu *.SilkS *.Mask) ,net-pos)
38     (pad 2 thru_hole circle (at -2.54 -5.08) (size 2.286 2.286) (drill 1.4986)
39          (layers *.Cu *.SilkS *.Mask) ,net-neg)
40     (pad 2 thru_hole circle (at -3.81 -2.54) (size 2.286 2.286) (drill 1.4986)
41          (layers *.Cu *.SilkS *.Mask) ,net-neg)))
42
43 (define (diode-module x y rotation label net-pos net-neg)
44   `(module DIODE (layer Front) (tedit 4E0F7A99) (tstamp 543EF854)
45     (at ,x ,y ,(+ 90 rotation))
46     (path /543DB90F)
47     (fp_text reference D2:2 (at 0 0 180) (layer F.SilkS) hide
48              (effects (font (size 1.016 1.016) (thickness 0.2032))))
49     (fp_line (start -1.524 -1.143) (end 1.524 -1.143)
50              (layer F.SilkS) (width 0.2032))
51     (fp_line (start 1.524 -1.143) (end 1.524 1.143)
52              (layer F.SilkS) (width 0.2032))
53     (fp_line (start 0 -1.143) (end 0 1.143)
54              (layer F.SilkS) (width 0.2032))
55     (fp_line (start 0 -1.143) (end -1.524 0)
56              (layer F.SilkS) (width 0.2032))
57     (fp_line (start -1.524 0) (end 0 1.143)
58              (layer F.SilkS) (width 0.2032))
59     (fp_line (start 1.524 1.143) (end -1.524 1.143)
60              (layer F.SilkS) (width 0.2032))
61     (fp_line (start -1.524 1.143) (end -1.524 -1.143)
62              (layer F.SilkS) (width 0.2032))
63     (fp_line (start -3.81 0) (end -1.6637 0) (layer Back) (width 0.6096))
64     (fp_line (start 1.6637 0) (end 3.81 0) (layer Back) (width 0.6096))
65     (fp_line (start -3.81 0) (end -1.6637 0) (layer Front) (width 0.6096))
66     (fp_line (start 1.6637 0) (end 3.81 0) (layer Front) (width 0.6096))
67
68     (pad 1 thru_hole circle (at -3.81 0 180) (size 1.651 1.651)
69          (drill 0.9906) (layers *.Cu *.SilkS *.Mask) ,net-neg)
70     (pad 2 thru_hole rect (at 3.81 0 ,rotation) (size 1.651 1.651)
71          (drill 0.9906) (layers *.Cu *.SilkS *.Mask) ,net-pos)
72     (pad 99 smd rect (at -1.6637 0 ,rotation) (size 0.8382 0.8382)
73          (layers Front F.Paste F.Mask))
74     (pad 99 smd rect (at -1.6637 0 ,rotation) (size 0.8382 0.8382)
75          (layers Back B.Paste B.Mask))
76     (pad 99 smd rect (at 1.6637 0 ,rotation) (size 0.8382 0.8382)
77          (layers Front F.Paste F.Mask))
78     (pad 99 smd rect (at 1.6637 0 ,rotation) (size 0.8382 0.8382)
79          (layers Back B.Paste B.Mask))))
80
81 (define microcontroller-module
82   `(module A_STAR (layer Front) (tedit 4FDC31C8) (tstamp 543EF800)
83     (at 134 50 270)
84     (path /543EEB02)
85     (fp_line (start -15.24 7.62) (end 10.1 7.62) (layer F.SilkS) (width 0.381))
86
87     ;; columns
88     (pad B5 thru_hole circle (at -13.97 6.35 270) (size 1.7526 1.7526)
89          (drill 1.0922) (layers *.Cu *.SilkS *.Mask) (net 7 N-col-2))
90     (pad B4 thru_hole circle (at -11.43 6.35 270) (size 1.7526 1.7526)
91          (drill 1.0922) (layers *.Cu *.SilkS *.Mask) (net 8 N-col-3))
92     (pad E6 thru_hole circle (at -8.89 6.35 270) (size 1.7526 1.7526)
93          (drill 1.0922) (layers *.Cu *.SilkS *.Mask) (net 9 N-col-4))
94     (pad D7 thru_hole circle (at -6.35 6.35 270) (size 1.7526 1.7526)
95          (drill 1.0922) (layers *.Cu *.SilkS *.Mask) (net 5 N-col-0))
96     (pad C6 thru_hole circle (at -3.81 6.35 270) (size 1.7526 1.7526)
97          (drill 1.0922) (layers *.Cu *.SilkS *.Mask) (net 6 N-col-1))
98     (pad D4 thru_hole circle (at -1.27 6.35 270) (size 1.7526 1.7526)
99          (drill 1.0922) (layers *.Cu *.SilkS *.Mask) (net 10 N-col-5))
100
101     ;; rows
102     (pad D0 thru_hole circle (at 1.27 6.35 270) (size 1.7526 1.7526)
103          (drill 1.0922) (layers *.Cu *.SilkS *.Mask) (net 1 N-row-0))
104     (pad D1 thru_hole circle (at 3.81 6.35 270) (size 1.7526 1.7526)
105          (drill 1.0922) (layers *.Cu *.SilkS *.Mask) (net 2 N-row-1))
106     (pad D3 thru_hole circle (at 6.35 6.35 270) (size 1.7526 1.7526)
107          (drill 1.0922) (layers *.Cu *.SilkS *.Mask) (net 3 N-row-2))
108     (pad D2 thru_hole circle (at 8.89 6.35 270) (size 1.7526 1.7526)
109          (drill 1.0922) (layers *.Cu *.SilkS *.Mask) (net 4 N-row-3))))
110
111 (define nets
112   `((net 0 "")
113     (net 1 N-row-0)
114     (net 2 N-row-1)
115     (net 3 N-row-2)
116     (net 4 N-row-3)
117     (net 5  N-col-0)
118     (net 6  N-col-1)
119     (net 7  N-col-2)
120     (net 8  N-col-3)
121     (net 9  N-col-4)
122     (net 10 N-col-5)
123     ,@(for/list ([s (in-range 24)])
124         (list 'net (+ 11 s) (string->symbol (format "N-diode-~s" s))))))
125
126 (define (net-class nets)
127   (append '(net_class Default "This is the default net class."
128             (clearance 0.254)
129             (trace_width 0.2032)
130             (via_dia 0.889)
131             (via_drill 0.635)
132             (uvia_dia 0.508)
133             (uvia_drill 0.127))
134           (for/list ([n nets])
135             (list 'add_net (last n)))))
136
137 (define (switch row col)
138   (let* ([x (+ (* (+ 1 col) spacing) x-offset)]
139          [y (+ (list-ref column-offsets col) (* spacing row) y-offset)]
140          [label (format "SW~a:~a" col row)]
141          [diode (+ row (* col 4))]
142          [diode-net `(net ,(+ 11 diode)
143                       ,(string->symbol (format "N-diode-~s" diode)))]
144          [column-net `(net ,(+ col 5)
145                        ,(string->symbol (format "N-col-~s" col)))])
146     (switch-module x y 0 label diode-net column-net)))
147
148 (define (diode row col)
149   (let* ([x (if (= col 5)
150                 134
151                 (+ (* (+ 1 col) spacing) x-offset 9))]
152          [y (cond [(and (= col 5) (= row 2)) 81]
153                   [(and (= col 5) (= row 3)) 84]
154                   [true (+ (list-ref column-offsets col)
155                            (* spacing row) y-offset)])]
156          [r (if (= col 5) 270 0)]
157          [label (format "D~a:~a" col row)]
158          [diode (+ row (* col 4))])
159     (diode-module x y r label
160                   `(net ,(+ 11 diode)
161                     ,(string->symbol (format "N-diode-~s" diode)))
162                   `(net ,(+ row 1)
163                         ,(string->symbol (format "N-row-~s" row))))))
164
165 (define (column-traces col)
166   (let* ([xo (* col spacing)]
167          [yo (- (list-ref column-offsets col) 8)])
168     (for/list ([coords '[[36.46 22.92 34.23 22.92]
169                          [33.02 24.13 33.02 26.67]
170                          [34.23 22.92 33.02 24.13]
171                          [35.19 44.46 31.75 44.46]
172                          [31.75 44.46 31.75 44.45]
173                          [31.75 41.91 36.45 41.91]
174                          [36.45 41.91 35.19 43.17]
175                          [35.19 43.17 35.19 44.46]
176                          [36.46 79.92 36.46 81.19]
177                          [36.46 81.19 35.19 82.46]
178                          [31.75 60.96 36.42 60.96]
179                          [36.42 60.96 36.83 60.55]
180                          [36.83 60.55 36.83 59.69]
181                          [31.75 63.50 35.15 63.50]
182                          [35.15 63.50 36.46 62.19]
183                          [36.46 62.19 36.46 60.92]
184                          [31.75 79.02 35.56 79.02]
185                          [35.56 79.02 36.46 79.92]
186                          [36.46 22.92 36.46 24.19]
187                          [36.46 24.19 35.25 25.40]
188                          [35.25 25.40 34.29 25.40]
189                          [34.29 25.40 33.02 26.67]
190                          [33.02 26.67 31.75 27.94]
191                          [31.75 27.94 31.75 41.91]
192                          [31.75 41.91 31.75 44.45]
193                          [31.75 44.45 31.75 60.96]
194                          [31.75 60.96 31.75 63.50]
195                          [31.75 63.50 31.75 79.02]
196                          [31.75 79.02 35.19 82.46]]])
197       (match coords
198         [(list xs ys xe ye) `(segment (start ,(+ xo xs) ,(+ yo ys))
199                                       (end ,(+ xo xe) ,(+ yo ye))
200                                       (width 0.2032) (layer Front)
201                                       (net ,(+ col 5)))]))))
202 (define (row-traces row)
203   (let* ([yo (+ (* rows spacing -1) (* (add1 row) spacing))]
204          [row3 '[[127.65 58.89 127.65 62.88] ; extra bits for the middle keys
205                  [127.00 95.25 125.73 93.98]
206                  [140.97 95.25 127.00 95.25]
207                  [140.97 68.58 140.97 95.25]
208                  [138.43 66.04 140.97 68.58]
209                  [130.81 66.04 138.43 66.04]
210                  [127.65 62.88 130.81 66.04]
211                  [125.73 93.98 125.73 90.17]
212                  [123.19 93.98 125.73 93.98]
213                  [121.02 91.81 123.19 93.98]
214                  [124.09 91.81 125.73 90.17]
215                  [125.73 90.17 127.00 88.90]
216                  [127.00 87.19 130.19 84.00]
217                  [127.00 88.90 127.00 87.19]]]
218          [all-rows '[[102.87 86.81 102.87 87.63]
219                      [104.14 88.90 105.41 88.90]
220                      [102.87 87.63 104.14 88.90]
221                      [120.65 91.81 121.02 91.81]
222                      [105.00 86.81 105.00 88.49]
223                      [105.00 88.49 105.41 88.90]
224                      [108.32 91.81 120.65 91.81]
225                      [105.41 88.90 108.32 91.81]
226                      [120.65 91.81 124.09 91.81]
227                      [69.850 85.81 69.130 85.81]
228                      [67.310 87.63 65.200 87.63]
229                      [69.130 85.81 67.310 87.63]
230                      [84.040 82.77 87.630 82.77]
231                      [67.000 85.81 69.850 85.81]
232                      [69.850 85.81 81.000 85.81]
233                      [81.000 85.81 84.040 82.77]
234                      [84.040 82.77 86.000 80.81]
235                      [48.000 88.81 64.000 88.81]
236                      [72.000 80.81 86.000 80.81]
237                      [64.000 88.81 72.000 80.81]
238                      [86.000 80.81 87.630 82.44]
239                      [87.630 82.44 87.630 82.77]
240                      [87.630 82.77 87.630 85.09]
241                      [89.350 86.81 101.60 86.81]
242                      [87.630 85.09 89.350 86.81]
243                      [101.60 86.81 102.87 86.81]
244                      [102.87 86.81 104.59 86.81]]])
245     (for/list ([coords (if (= row 3) (append row3 all-rows) all-rows)])
246       (match coords
247         [(list xs ys xe ye) `(segment (start ,xs ,(+ yo ys))
248                                       (end ,xe ,(+ yo ye))
249                                       (width 0.2032) (layer Back)
250                                       (net ,(+ row 1)))]))))
251
252 (define (diode-traces row col)
253   (let* ([xo (* col spacing)]
254          [yo (+ (list-ref column-offsets col) -8 (* row spacing))])
255     (for/list ([coords '[[48.00 24.19 48.00 23.87]
256                          [48.00 23.87 47.05 22.92]
257                          [47.05 22.92 41.54 22.92]
258                          [41.54 22.92 42.81 24.19]
259                          [42.81 24.19 42.81 25.46]
260                          [42.81 25.46 44.08 24.19]
261                          [44.08 24.19 48.00 24.19]]])
262       (match coords
263         [(list xs ys xe ye) `(segment (start ,(+ xo xs) ,(+ yo ys))
264                                       (end ,(+ xo xe) ,(+ yo ye))
265                                       (width 0.2032) (layer Back)
266                                       (net ,(+ row (* col 4) 11)))]))))
267
268 (define switches+diodes
269   (for/list ([col (in-range cols)] #:when true
270              [row (if (= 5 col)
271                       '(2 3)
272                       (in-range rows))])
273     (append (list (switch row col) (diode row col))
274             (if (= 5 col)
275                 '()
276                 (diode-traces row col)))))
277
278 (define board
279   (apply append nets
280          (list (net-class nets))
281          (list microcontroller-module)
282          (apply append (map column-traces (range (sub1 cols))))
283          (apply append (map row-traces (range rows)))
284          switches+diodes))
285
286 (define (write-placement filename)
287   (when (file-exists? filename) (delete-file filename))
288   (call-with-output-file filename
289     (λ (op)
290       (display (call-with-input-file "header.rktd"
291                  (curry read-string 9999)) op)
292       ;; kicad has this terrible bug where it's whitespace-sensitive here =(
293       (display "\n" op)
294       (for ([f board])
295         (pretty-print f op 1))
296       (display ")" op))))
297
298 (write-placement "atreus.kicad_pcb")