# SPDX-License-Identifier: BSD-2-Clause

from torii.build                        import Attrs, Clock, Connector, Pins, PinsN, Resource, Subsignal
from torii.build.run                    import BuildPlan, BuildProducts
from torii.hdl.ir                       import Fragment
from torii.platform.resources           import ButtonResources, LEDResources, SDRAMResource, UARTResource
from torii.platform.vendor.lattice.ecp5 import ECP5Platform

__all__ = (
	'Colorlight_5A75B_R70Platform',
)

class Colorlight_5A75B_R70Platform(ECP5Platform):
	device      = 'LFE5U-25F'
	package     = 'BG256'
	speed       = '6'
	default_clk = 'clk25'

	pretty_name = 'Colorlight 5A-75B'
	description = 'Colorlight 5A-75B Lattice ECP5-25F FPGA Board'

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

		*LEDResources(
			pins = 'P11', invert = True,
			attrs = Attrs(IO_TYPE = 'LVCMOS33', DRIVE = '4')
		),

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

		UARTResource(0,
			tx = 'P11', # led (J19 DATA_LED-)
			rx = 'M13', # btn (J19 KEY+)
			attrs = Attrs(IO_TYPE = 'LVCMOS33')
		),

		# SPIFlash (W25Q32JV)   1x/2x/4x speed
		Resource('spi_flash', 0,
			Subsignal('cs',   PinsN('N8', dir = 'o')),
			# Subsignal('clk', Pins(', dir = 'i')),             # driven through USRMCLK
			Subsignal('cipo', Pins('T8', dir = 'i')),           # Chip: DI/IO0
			Subsignal('copi', Pins('T7', dir = 'o')),           #       DO/IO1
			# Subsignal('wp', PinsN('unknown', dir = 'o')),     #          IO2 Todo
			# Subsignal('hold', PinsN('unknown', dir = 'o')),   #          IO3 Todo
			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 = 'C6', we_n = 'C7', cas_n = 'E7', ras_n = 'D7',
			ba = 'A7', a = 'A9 E10 B12 D13 C12 D11 D10 E9 D9 B7 C8',
			dq = 'B13 C11 C10 A11 C9 E8  B6  B9  A6  B5  A5  B4  B3 C3  A2  B2 '
				'E2  D3  A4  E4  D4 C4  E5  D5  E6  D6  D8  A8  B8 B10 B11 E11',
			attrs = Attrs(PULLMODE = 'NONE', DRIVE = '4', SLEWRATE = 'FAST', IO_TYPE = 'LVCMOS33')
		),

		# Broadcom B50612D Gigabit Ethernet Transceiver
		Resource('eth_rgmii', 0,
			Subsignal('rst',     PinsN('P5', dir = 'o')),
			Subsignal('mdc',     Pins('P3', dir = 'o')),
			Subsignal('mdio',    Pins('T2', dir = 'io')),
			Subsignal('tx_clk',  Pins('M2', dir = 'o')),
			Subsignal('tx_ctl',  Pins('M3', dir = 'o')),
			Subsignal('tx_data', Pins('L1 L3 P2 L4', dir = 'o')),
			Subsignal('rx_clk',  Pins('M1', dir = 'i')),
			Subsignal('rx_ctl',  Pins('N6', dir = 'i')),
			Subsignal('rx_data', Pins('N1 M5 N5 M6', dir = 'i')),
			Attrs(IO_TYPE = 'LVCMOS33')
		),

		# Broadcom B50612D Gigabit Ethernet Transceiver
		Resource('eth_rgmii', 1,
			Subsignal('rst',     PinsN('P5', dir = 'o')),
			Subsignal('mdc',     Pins('P3', dir = 'o')),
			Subsignal('mdio',    Pins('T2', dir = 'io')),
			Subsignal('tx_clk',  Pins('M12', dir = 'o')),
			Subsignal('tx_ctl',  Pins('R15', dir = 'o')),
			Subsignal('tx_data', Pins('T14 R12 R13 R14', dir = 'o')),
			Subsignal('rx_clk',  Pins('M16', dir = 'i')),
			Subsignal('rx_ctl',  Pins('L15', dir = 'i')),
			Subsignal('rx_data', Pins('P13 N13 P14 M15', dir = 'i')),
			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) -> list[str]:
		return super().required_tools + [
			'openFPGALoader'
		]

	def toolchain_prepare(self, fragment: Fragment, name: str, **kwargs) -> BuildPlan:
		overrides = dict(ecppack_opts = '--compress')
		overrides.update(kwargs)
		return super().toolchain_prepare(fragment, name, **overrides)

	def toolchain_program(self, products: BuildProducts, name: str) -> None:
		from os         import environ
		from subprocess import check_call

		tool = environ.get('OPENFPGALOADER', 'openFPGALoader')
		with products.extract(f'{name}.bit') as bitstream_filename:
			check_call([
				tool, '-c', 'ft232', '-m', bitstream_filename
			])


if __name__ == '__main__':
	from ..test.blinky import Blinky
	Colorlight_5A75B_R70Platform().build(Blinky(), do_program = True)
