import os
import subprocess

from amaranth.build import *
from amaranth.vendor.lattice_ecp5 import *
from amaranth_boards.resources import *


__all__ = ["Colorlight_i9_Platform"]


class Colorlight_i9_Platform(LatticeECP5Platform):
    device                 = "LFE5U-45F"
    package                = "BG381"
    speed                  = "6"
    default_clk            = "clk25"

    resources = [
        Resource("clk25", 0, Pins("P3", dir="i"), Clock(25e6), Attrs(IO_TYPE="LVCMOS33")),

        *LEDResources(pins="L2", invert = True,
                      attrs=Attrs(IO_TYPE="LVCMOS33", DRIVE="4")),

        #*ButtonResources(pins="M13", invert = True,
        #                 attrs=Attrs(IO_TYPE="LVCMOS33", PULLMODE="UP")),

        UARTResource(0,
            tx="E17",
            rx="D18",
            attrs=Attrs(IO_TYPE="LVCMOS33")
        ),
        UARTResource(1,
            tx="P16",
            rx="L5",
            attrs=Attrs(IO_TYPE="LVCMOS33")
        ),
        UARTResource(2,
            tx="J18",
            rx="J16",
            attrs=Attrs(IO_TYPE="LVCMOS33")
        ),

        # SPIFlash (W25Q32JV)   1x/2x/4x speed
        Resource("spi_flash", 0,
            Subsignal("cs",   PinsN("R2", dir="o")),
            # Subsignal("clk", Pins("", dir="i")),              # driven through USRMCLK
            Subsignal("cipo", Pins("V2", dir="i")),             # Chip: DI/IO0
            Subsignal("copi", Pins("W2", dir="o")),             #       DO/IO1
            Attrs(IO_TYPE="LVCMOS33")
        ),

        # 2x ESMT M12L16161A-5T 1M x 16bit 200MHz SDRAMs (organized as 1M x 32bit)
        # 2x WinBond W9816G6JH-6 1M x 16bit 166MHz SDRAMs (organized as 1M x 32bit) are lso reported 
        SDRAMResource(0,
            clk="B9", we_n="A10", cas_n="A9", ras_n="B10",
            ba="B11 C8", a="B13 C14 A16 A17 B16 B15 A14 A13 A12 A11 B12",
            dq="D15 E14 E13 D12 E12 D11 C10 B17 B8  A8  C7  A7  A6  B6  A5  B5 "
               "D5  C5  D6  C6  E7  D7  E8  D8  E9  D9  E11 C11 C12 D13 D14 C15",
            attrs=Attrs(PULLMODE="NONE", DRIVE="4", SLEWRATE="FAST", IO_TYPE="LVCMOS33")
        ),

        # Broadcom B50612D Gigabit Ethernet Transceiver
        Resource("eth_rgmii", 0,
            Subsignal("rst",     Pins("P4", dir="o")),
            Subsignal("mdc",     Pins("N5", dir="o")),
            Subsignal("mdio",    Pins("P5", dir="io")),
            Subsignal("tx_clk",  Pins("U19", dir="i")),
            Subsignal("tx_ctl",  Pins("P19", dir="o")),
            Subsignal("tx_data", Pins("U20 T19 T20 R20", dir="o")),
            Subsignal("rx_clk",  Pins("L19", dir="i")),
            Subsignal("rx_ctl",  Pins("M20", dir="i")),
            Subsignal("rx_data", Pins("P20 N19 N20 M19", dir="i")),
            Attrs(IO_TYPE="LVCMOS33")
        ),

        # Broadcom B50612D Gigabit Ethernet Transceiver
        Resource("eth_rgmii", 1,
            Subsignal("rst",     Pins("P4", dir="o")),
            Subsignal("mdc",     Pins("N5", dir="o")),
            Subsignal("mdio",    Pins("P5", dir="io")),
            Subsignal("tx_clk",  Pins("G1", dir="o")),
            Subsignal("tx_ctl",  Pins("K1", dir="o")),
            Subsignal("tx_data", Pins("G2 H1 J1 J3", dir="o")),
            Subsignal("rx_clk",  Pins("H2", dir="i")),
            Subsignal("rx_ctl",  Pins("P2", dir="i")),
            Subsignal("rx_data", Pins("K2 L1 N1 P1", dir="i")),
            Attrs(IO_TYPE="LVCMOS33")
        ),

        Resource("jtag", 0,
            Subsignal("trst", Pins("J17", dir="i")),
            Subsignal("tck", Pins("G18", dir="i")),
            Subsignal("tms", Pins("H16", dir="i")),
            Subsignal("tdo", Pins("H17", dir="o")),
            Subsignal("tdi", Pins("H18", dir="i")),
            Attrs(IO_TYPE="LVCMOS33")
        ),

        Resource("i2c", 0,
            Subsignal("sda", Pins("D16", dir="io")),
            Subsignal("scl", Pins("F5", dir="io")), # Hacky stuff for now, amlib needs it to be io for some reason
            Attrs(IO_TYPE="LVCMOS33")
        ),
    ]
    connectors = []
    #    Connector("j",  1, "F3  F1  G3  - G2  H3  H5  F15 L2 K1 J5 K2 B16 J14 F12 -"),
    #    Connector("j",  2, "J4  K3  G1  - K4  C2  E3  F15 L2 K1 J5 K2 B16 J14 F12 -"),
    #    Connector("j",  3, "H4  K5  P1  - R1  L5  F2  F15 L2 K1 J5 K2 B16 J14 F12 -"),
    #    Connector("j",  4, "P4  R2  M8  - M9  T6  R6  F15 L2 K1 J5 K2 B16 J14 F12 -"),
    #    Connector("j",  5, "M11 N11 P12 - K15 N12 L16 F15 L2 K1 J5 K2 B16 J14 F12 -"),
    #    Connector("j",  6, "K16 J15 J16 - J12 H15 G16 F15 L2 K1 J5 K2 B16 J14 F12 -"),
    #    Connector("j",  7, "H13 J13 H12 - G14 H14 G15 F15 L2 K1 J5 K2 B16 J14 F12 -"),
    #    Connector("j",  8, "A15 F16 A14 - E13 B14 A13 F15 L2 K1 J5 K2 B16 J14 F12 -"),
    #    Connector("j", 19, " -  M13  -  - P11"),
    #]

    @property
    def required_tools(self):
        return super().required_tools + [
            "ecpdap"
        ]

    def toolchain_prepare(self, fragment, name, **kwargs):
        overrides = dict(ecppack_opts="--compress")
        overrides.update(kwargs)
        return super().toolchain_prepare(fragment, name, **overrides)

    def toolchain_program(self, products, name):
        tool = os.environ.get("ECPDAP", "ecpdap")
        with products.extract("{}.bit".format(name)) as bitstream_filename:
            subprocess.check_call([tool, "program", bitstream_filename, "--freq", "10M"])


if __name__ == "__main__":
    from .test.blinky import *
    Colorlight_i9_Platform().build(Blinky(), do_program=True)
