#use-added-syntax(jitx)
defpackage fpga_gigabit:
  import core
  import jitx
  import jitx/commands

  import ocdb/utils/bundles
  import ocdb/utils/box-symbol


public pcb-component VPX-conn :
  name = "ASP-134488-01"
  description = "Vita 57.1 HPC FMC connector"
  manufacturer = "Samtec"
  mpn = "ASP-134488-01"

  pin-properties :
    [pin:Ref | pads:Ref ... | side:Dir | bank:Int]
    [dp0-c2m-n | C[3]  | Right | 0 ]
    [dp0-c2m-p | C[2]  | Right | 0 ]
    [dp1-c2m-n | A[23] | Right | 0 ]
    [dp1-c2m-p | A[22] | Right | 0 ]

  pin-properties :
    [pin:Ref | clock-capable:(True|False) | gigabit-transceiver:(True|False)]
    [dp0-c2m-n | false | true]
    [dp0-c2m-p | false | true]
    [dp1-c2m-n | false | false]
    [dp1-c2m-p | false | false]


  make-box-symbol()
  assign-landpattern(ASP-134488-01-pkg)


  supports diff-pair:
    diff-pair.P => self.dp0-c2m-p
    diff-pair.N => self.dp0-c2m-n

  supports diff-pair:
    diff-pair.P => self.dp1-c2m-p
    diff-pair.N => self.dp1-c2m-n


public pcb-component Xilinx-FPGA :

  name = "Xilinx"
  description = "Excerpt of an IO Bank & High Speed Transceiver"
  manufacturer = "Xilinx"

  pin-properties :
    [pin:Ref | pads:Ref ... | side:Dir | bank:Int]
    [IO_L2N | C[3]  | Right | 0 ]
    [IO_L2P | C[2]  | Right | 0 ]
    [MGTHRXN0 | D[3] | Right | 0 ]
    [MGTHRXP0 | D[4] | Right | 0 ]

  pin-properties :
    [pin:Ref | clock-capable:(True|False) | gigabit-transceiver:(True|False)]
    [IO_L2N | false | false]
    [IO_L2P | false | false]
    [MGTHRXN0 | false | true]
    [MGTHRXP0 | false | true]

  make-box-symbol()
  assign-landpattern(FPGA-pkg)

  supports diff-pair:
    diff-pair.P => self.IO_L2P
    diff-pair.N => self.IO_L2N

  supports diff-pair:
    diff-pair.P => self.MGTHRXP0
    diff-pair.N => self.MGTHRXN0

defn is-gigabit-transceiver (x) -> True|False :
  if has-property?(x.gigabit-transceiver):
    property(x.gigabit-transceiver)
  else:
    false

public pcb-module gigabit-restrict-example: 

  inst fpga : Xilinx-FPGA
  inst conn : VPX-conn

  require h-dp:diff-pair from fpga
  require c-dp:diff-pair from conn

  for dp in [h-dp, c-dp] do:
    restrict(dp.P, is-gigabit-transceiver)

  ; Connect the two high-speed capable differential pairs.
  net (h-dp, c-dp)


; Land Patterns
defn bga-pkg (pitch:Double, pad-diam:Double, n-pads:[Int Int], courtyard:[Double Double], omit-pads:Tuple<Ref>) :
  inside pcb-landpattern :
    pcb-pad pin-pad :
      type = SMD
      shape = Circle(pad-diam / 2.0)
      layer(Paste(Top)) = Circle(pad-diam / 2.0)
      layer(SolderMask(Top)) = Circle(pad-diam / 2.0)

    defn make-pad (r:Int, c:Int) :
      val x = ((to-double(n-pads[0]) - 1.0) / -2.0 + to-double(c)) * pitch
      val y = ((to-double(n-pads[1]) - 1.0) / 2.0 - to-double(r)) * pitch
      ; I IS MISSING DELIBERATELY BECAUSE OF SAMTEC's ANNOYING LETTER SCHEME, but O is present.
      val letter = ["A" "B" "C" "D" "E" "F" "G" "H" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z"][r]
      val name = Ref(letter)[c + 1]

      if not contains?(omit-pads, name) :
        pad (name) : pin-pad at loc(x, y)

    for c in 0 to n-pads[0] do :
      for r in 0 to n-pads[1] do :
        make-pad(r, c)

    layer(Courtyard(Top)) = Rectangle(courtyard[0], courtyard[1])
    layer(Silkscreen("pol", Top)) = Circle(-0.3 - courtyard[0] / 2.0, courtyard[1] / 2.0, 0.127)

pcb-landpattern ASP-134488-01-pkg :
  bga-pkg(1.27, 0.64, [40 10], [55.78 14.68], [])
  ; Alignment holes
  let:
    val xdim =  27.19
    val yoff = -3.05
    val align-hole-diam = 1.27
    ; Aligment hole on the right is centered vertically
    ; Aligment hole on the left is offset vertically
    layer(Cutout()) = Circle(        xdim,  0.0, align-hole-diam / 2.0)
    layer(Cutout()) = Circle( -1.0 * xdim, yoff, align-hole-diam / 2.0)
  let:
    val xdim = 31.49695
    val yoff = 2.006
    val standoff-hole-diam = 3.2
    ; Standoff holes
    layer(Cutout()) = Circle(        xdim, yoff, standoff-hole-diam / 2.0)
    layer(Cutout()) = Circle( -1.0 * xdim, yoff, standoff-hole-diam / 2.0)

pcb-landpattern FPGA-pkg : 
  bga-pkg(1.0, 0.55, [23, 23], [24.0, 24.0], [])



; Set the design name     - a directory with this name will be generated under the "designs" directory
;     the board           - a Board object
;     [optional] rules    - the PCB design rules (if not givn default rules will be used)
;     [optional] vendors  - Strings or AuthorizedVendors (if not give default vendors will be used)
;     [optional] quantity - Minimum stock quantity the vendor should carry (if not give default quantity will be used)

public defn setup-design (name:String, board:Board
                          --
                          rules:Rules = ocdb/utils/defaults/default-rules
                          vendors:Tuple<String|AuthorizedVendor> = ocdb/utils/design-vars/APPROVED-DISTRIBUTOR-LIST
                          quantity:Int = ocdb/utils/design-vars/DESIGN-QUANTITY
                          bom-columns:Tuple<BOMColumn> = ocdb/utils/design-vars/BOM-COLUMNS) :
  set-current-design(name)
  set-board(board)
  set-rules(rules)
  set-bom-vendors(vendors)
  set-bom-design-quantity(quantity)
  set-bom-columns(bom-columns)
  set-paper(ANSI-A4)
  set-export-backend(`altium) ; set the CAD software for export to be altium (also supported: `kicad)

val board-shape = RoundedRectangle(100.0, 100.0, 0.25)

setup-design(
  "gigabit-restrict-example",
  ocdb/utils/defaults/default-board(ocdb/manufacturers/stackups/jlcpcb-jlc2313, board-shape)
)

; Set the schematic sheet size
set-paper(ANSI-A)

; Set the top level module (the module to be compile into a schematic and PCB)
set-main-module(gigabit-restrict-example)

; Use any helper function from helpers.stanza here
; run-check-on-design(my-design)

; View the results
view-board()
view-schematic()
; view-design-explorer()
; view-bom(BOM-STD)