# Strongly inspired by the migen build of humpback
# Using STM32 Nucleo-H743ZI2 board
# Note to self: Pin assignment differs from Nucleo-H743ZI

import os
import subprocess

from nmigen.build import *
from nmigen.vendor.lattice_ice40 import *
from nmigen_boards.resources import *
from resources import *
from pin_mapper import *


__all__ = ["HumpbackPlatform"]


class HumpbackPlatform(LatticeICE40Platform):
	device = "iCE40HX8K"		# Using ICE40HX8K-CT256
	package = "CT256"
	default_clk = "clk25"		# Point of deviation: Clock speed for humpback is fixed at 25MHz

	# Acquire GPIO mappings from gpio_mapper
	gpio_dict, global_gpio_dict = GPIOMapping()
	resources = [

		# Define clock
		Resource("clk25", 0, Pins("K9", dir="i"),
			Clock(25e6), Attrs(GLOBAL=True, IO_STANDARD="SB_LVCMOS")
		),

		# Define user LED
		Resource("user_led", 0, Pins("H3", dir="o"),
			Attrs(IO_STANDARD="SB_LVCMOS")
		),

		# Serial interfaces: Only including pins usable to STM32

		# Define UART interfaces
		# UART interface: There are no pull ups from humpback.
		#		  Need to configure STM32 pins to pull up.
		# Note: Use USART in asynchronous mode
		UARTResource(0,
			rx="T11", tx="M13", rts="M15", cts="T10",
			attrs=Attrs(IO_STANDARD="SB_LVCMOS", PULLUP=1)
		),

		# UART1 interface: Read note for UART interface above
		# UART1 interface is broken due to pin rearrangement introduced for Nucleo-H743ZI2
		# Uncomment if fixed, or found an alternative (e.g. bit banging UART)
#		*UARTResource(1,
#			tx="M11", rx="T13", rts="A6", cts="B16",
#			attrs=Attrs(IO_STANDARD="SB_LVCMOS", PULLUP=1)
#		),

		# Define SPI interfaces
		# Note: Use "role=device" to make humpback a SPI slave
		#	The ~CS pin is a global pin, but not being configured global.
		SPIResource(0,
			cs="R2", clk="C8", mosi="N5", miso="T2",
			attrs=Attrs(IO_STANDARD="SB_LVCMOS")
		),

		# Define I2C interface
		# Note: Need to program pull up in stm32
		#	Use "role=device" to make humpback a I2C slave
		I2CResource(0,
			sda="T16", scl="M12",
			attrs=Attrs(IO_STANDARD="SB_LVCMOS", PULLUP=1)
		),


		# TODO:STM32 GPIO pins, ignore other unusable pins as well
		*GPIOResources(
			pins_dict = gpio_dict, dir = "o",
			attrs=Attrs(IO_STANDARD="SB_LVCMOS"),
		),
		*GPIOResources(
			pins_dict = global_gpio_dict, dir = "o",
			attrs=Attrs(GLOBAL=True, IO_STANDARD="SB_LVCMOS"),
		),

	]

	connectors = []

	# tool chain setup, using default ICE40 HX8K evaluation code
	def toolchain_program(self, products, name):
		iceprog = os.environ.get("ICEPROG", "iceprog")
		with products.extract("{}.bin".format(name)) as bitstream_filename:
           	# TODO: this should be factored out and made customizable
			subprocess.check_call([iceprog, "-S", bitstream_filename])

if __name__ == "__main__":
   	from nmigen_boards.test.blinky import *
   	HumpbackPlatform().build(Blinky(), do_program=False)