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

from itertools     import count, cycle

from torii.hdl.ast import Cat, Signal
from torii.hdl.dsl import Module
from torii.hdl.ir  import Elaboratable
from torii.build   import ResourceError

__all__ = (
	'Blinky',
)

class Blinky(Elaboratable):
	def elaborate(self, platform):
		m = Module()

		def get_all_resources(name):
			resources = []
			for number in count():
				try:
					resources.append(platform.request(name, number))
				except ResourceError:
					break
			return resources

		rgb_leds = [res for res in get_all_resources('rgb_led')]
		leds     = [res.o for res in get_all_resources('led')]
		leds.extend([led.r.o for led in rgb_leds])
		leds.extend([led.g.o for led in rgb_leds])
		leds.extend([led.b.o for led in rgb_leds])
		buttons  = [res.i for res in get_all_resources('button')]
		switches = [res.i for res in get_all_resources('switch')]

		inverts  = [0 for _ in leds]
		for index, button in zip(cycle(range(len(inverts))), buttons):
			inverts[index] ^= button
		for index, switch in zip(cycle(range(len(inverts))), switches):
			inverts[index] ^= switch

		clk_freq = platform.default_clk_frequency
		timer = Signal(range(int(clk_freq//2)), reset = int(clk_freq//2) - 1)
		flops = Signal(len(leds))

		m.d.comb += Cat(leds).eq(flops ^ Cat(inverts))
		with m.If(timer == 0):
			m.d.sync += timer.eq(timer.reset)
			m.d.sync += flops.eq(~flops)
		with m.Else():
			m.d.sync += timer.eq(timer - 1)

		return m
