|
2 | 2 | from cmath import phase, rect
|
3 | 3 | from math import pi
|
4 | 4 | from warnings import warn
|
5 |
| -from .utils import (Cbox, Terminal, BOMData, XML, Side, |
| 5 | +from .utils import (Cbox, Terminal, BOMData, XML, Side, arrow_points, |
6 | 6 | polylinegon, id_text, make_text_point,
|
7 | 7 | bunch_o_lines, deep_transform, make_plus, make_variable,
|
8 |
| - sort_counterclockwise, light_arrows) |
| 8 | + sort_counterclockwise, light_arrows, sort_for_flags, is_clockwise) |
9 | 9 | from .errors import TerminalsError, BOMError, UnsupportedComponentError
|
10 | 10 |
|
11 | 11 | RENDERERS = {}
|
@@ -291,6 +291,60 @@ def jack(
|
291 | 291 | + id_text(box, bom_data, terminals, None, sc_text_pt, **options))
|
292 | 292 |
|
293 | 293 |
|
| 294 | +@component("Q", "MOSFET", "MOS", "FET") |
| 295 | +@n_terminal(3) |
| 296 | +@no_ambiguous |
| 297 | +def transistor( |
| 298 | + box: Cbox, |
| 299 | + terminals: list[Terminal], |
| 300 | + bom_data: BOMData, |
| 301 | + **options): |
| 302 | + "Draw a bipolar transistor (PNP/NPN) or FET (NFET/PFET)" |
| 303 | + if all(x not in bom_data.data.lower() for x in ("pnp:", "npn:", "nfet:", "pfet:")): |
| 304 | + raise BOMError( |
| 305 | + f"Need type of transistor for {box.type}{box.id}") |
| 306 | + silicon_type, part_num = bom_data.data.split(":") |
| 307 | + silicon_type = silicon_type.lower() |
| 308 | + bom_data = BOMData(bom_data.type, bom_data.id, part_num) |
| 309 | + if 'fet' in silicon_type: |
| 310 | + ae, se, ctl = sort_for_flags(terminals, box, "s", "d", "g") |
| 311 | + else: |
| 312 | + ae, se, ctl = sort_for_flags(terminals, box, "e", "c", "b") |
| 313 | + ap, sp = ae.pt, se.pt |
| 314 | + mid = (ap + sp) / 2 # TODO: slide this to line up with middle |
| 315 | + theta = phase(ap - sp) |
| 316 | + backwards = 1 if is_clockwise([ae, se, ctl]) else -1 |
| 317 | + thetaquarter = theta + (backwards * pi / 2) |
| 318 | + out_lines = [ |
| 319 | + (ap, mid + rect(.8, theta)), # Lead in |
| 320 | + (sp, mid - rect(.8, theta)), # Lead out |
| 321 | + ] |
| 322 | + if 'fet' in silicon_type: |
| 323 | + arr = mid + rect(.8, theta), mid + rect(.8, theta) + rect(.7, thetaquarter) |
| 324 | + if 'nfet' == silicon_type: |
| 325 | + arr = arr[1], arr[0] |
| 326 | + out_lines.extend([ |
| 327 | + *arrow_points(*arr), |
| 328 | + (mid - rect(.8, theta), mid - rect(.8, theta) + rect(.7, thetaquarter)), |
| 329 | + (mid + rect(1, theta) + rect(.7, thetaquarter), |
| 330 | + mid - rect(1, theta) + rect(.7, thetaquarter)), |
| 331 | + (mid + rect(.5, theta) + rect(1, thetaquarter), |
| 332 | + mid - rect(.5, theta) + rect(1, thetaquarter)), |
| 333 | + ]) |
| 334 | + else: |
| 335 | + arr = mid + rect(.8, theta), mid + rect(.4, theta) + rect(1, thetaquarter) |
| 336 | + if 'npn' == silicon_type: |
| 337 | + arr = arr[1], arr[0] |
| 338 | + out_lines.extend([ |
| 339 | + *arrow_points(*arr), |
| 340 | + (mid - rect(.8, theta), mid - rect(.4, theta) + rect(1, thetaquarter)), |
| 341 | + (mid + rect(1, theta) + rect(1, thetaquarter), |
| 342 | + mid - rect(1, theta) + rect(1, thetaquarter)), |
| 343 | + ]) |
| 344 | + text_pt = make_text_point(ap, sp, **options) |
| 345 | + return (id_text(box, bom_data, [ae, se], None, text_pt, **options) |
| 346 | + + bunch_o_lines(out_lines, **options)) |
| 347 | + |
294 | 348 | # code for drawing stuff
|
295 | 349 | # https://github.com/pfalstad/circuitjs1/tree/master/src/com/lushprojects/circuitjs1/client
|
296 | 350 | # https://github.com/KenKundert/svg_schematic/blob/0abb5dc/svg_schematic.py
|
|
0 commit comments