diff --git a/migen/blink-expanded.py b/migen/blink-expanded.py new file mode 100755 index 0000000..208187e --- /dev/null +++ b/migen/blink-expanded.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 +"""Simple tri-colour LED blink example.""" + +# Import lxbuildenv to integrate the deps/ directory +import os, sys +sys.path.insert(0, os.path.dirname(__file__)) +import lxbuildenv + +from migen import * +from migen.build.generic_platform import * +import fomu + +if 'FOMU_REV' not in os.environ: + print('Board type must be specified in FOMU_REV environment variable!') + exit(1) + +# +# Parameters from iCE40 UltraPlus LED Driver Usage Guide, pages 19-20 +# + +# Current modes +RGBA_CURRENT_MODE_FULL = '0b0' +RGBA_CURRENT_MODE_HALF = '0b1' + +# Current levels in Full / Half mode +RGBA_CURRENT_04MA_02MA = '0b000001' +RGBA_CURRENT_08MA_04MA = '0b000011' +RGBA_CURRENT_12MA_06MA = '0b000111' +RGBA_CURRENT_16MA_08MA = '0b001111' +RGBA_CURRENT_20MA_10MA = '0b011111' +RGBA_CURRENT_24MA_12MA = '0b111111' + +# Type for input pins, from ICE Technology Library Manual, pages 87-90 +SB_IO_TYPE_SIMPLE_INPUT = 0b000001 + +# +# Signals +# +counter = Signal(28) + +rgb0_pwm = Signal(1) +rgb1_pwm = Signal(1) +rgb2_pwm = Signal(1) + +input1 = Signal(1) +input2 = Signal(1) + +# Setup platform and correctly map pins for the +# iCE40UP5K SB_RGBA_DRV hard macro. +if os.environ['FOMU_REV'] in ['evt1', 'evt2']: + platform = fomu.FomuEvt2Platform() + blue_pwm = rgb0_pwm + red_pwm = rgb1_pwm + green_pwm = rgb2_pwm +elif os.environ['FOMU_REV'] == 'evt3': + platform = fomu.FomuEvt3Platform() + blue_pwm = rgb0_pwm + red_pwm = rgb1_pwm + green_pwm = rgb2_pwm +elif os.environ['FOMU_REV'] == 'hacker': + platform = fomu.FomuHackerPlatform() + blue_pwm = rgb0_pwm + green_pwm = rgb1_pwm + red_pwm = rgb2_pwm +elif os.environ['FOMU_REV'] == 'pvt': + platform = fomu.FomuPvtPlatform() + green_pwm = rgb0_pwm + red_pwm = rgb1_pwm + blue_pwm = rgb2_pwm +else: + print('Board not supported!') + exit(2) + +usb_pins = platform.request('usb') +rgb_pins = platform.request('rgb_led') + +touch_pins = [platform.request('user_touch_n', i) for i in range(0, 4)] + +m = Module() + +### + +# Drive the USB outputs to constant values as they are not in use. +# Assign USB pins to "0" so as to disconnect Fomu from +# the host system. Otherwise it would try to talk to +# us over USB, which wouldn't work since we have no stack. +m.comb += [usb_pins.d_p.eq(0), + usb_pins.d_n.eq(0), + usb_pins.pullup.eq(0)] + +# Use touch pins 1+2 to ground pulled-up inputs +m.comb += [touch_pins[1].eq(0), + touch_pins[2].eq(0)] + +# Wire inputs and clock divider to LEDs +m.comb += [red_pwm.eq(~input2), + green_pwm.eq(counter[23]), + blue_pwm.eq(~input1)] + +# Increment counter on clock signal +m.sync += counter.eq(counter + 1) + +# Instantiate iCE40 LED driver hard logic, connecting up +# latched button state, counter state, and LEDs. +# +# Note that it's possible to drive the LEDs directly, +# however that is not current-limited and results in +# overvolting the red LED. +# +# See also: +# https://www.latticesemi.com/-/media/LatticeSemi/Documents/ApplicationNotes/IK/ICE40LEDDriverUsageGuide.ashx?document_id=50668 +m.specials += Instance('SB_RGBA_DRV', + i_CURREN=0b1, + i_RGBLEDEN=0b1, + i_RGB0PWM=rgb0_pwm, + i_RGB1PWM=rgb1_pwm, + i_RGB2PWM=rgb2_pwm, + o_RGB0=rgb_pins.r, + o_RGB1=rgb_pins.g, + o_RGB2=rgb_pins.b, + p_CURRENT_MODE=RGBA_CURRENT_MODE_HALF, + p_RGB0_CURRENT=RGBA_CURRENT_08MA_04MA, + p_RGB1_CURRENT=RGBA_CURRENT_08MA_04MA, + p_RGB2_CURRENT=RGBA_CURRENT_08MA_04MA) + +m.specials += Instance('SB_IO', + i_PACKAGE_PIN=touch_pins[0], + i_OUTPUT_ENABLE=0b0, + o_D_IN_0=input1, + p_PIN_TYPE=SB_IO_TYPE_SIMPLE_INPUT, + p_PULLUP=0b1) + +m.specials += Instance('SB_IO', + i_PACKAGE_PIN=touch_pins[3], + i_OUTPUT_ENABLE=0b0, + o_D_IN_0=input2, + p_PIN_TYPE=SB_IO_TYPE_SIMPLE_INPUT, + p_PULLUP=0b1) + +platform.build(m) diff --git a/migen/blink.py b/migen/blink.py new file mode 100755 index 0000000..bdf34c6 --- /dev/null +++ b/migen/blink.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 +"""Simple tri-colour LED blink example.""" + +# Import lxbuildenv to integrate the deps/ directory +import os, sys +sys.path.insert(0, os.path.dirname(__file__)) +import lxbuildenv + +from migen import * +import fomu + +if 'FOMU_REV' not in os.environ: + print('Board type must be specified in FOMU_REV environment variable!') + exit(1) + +# +# Parameters from iCE40 UltraPlus LED Driver Usage Guide, pages 19-20 +# + +# Current modes +RGBA_CURRENT_MODE_FULL = '0b0' +RGBA_CURRENT_MODE_HALF = '0b1' + +# Current levels in Full / Half mode +RGBA_CURRENT_04MA_02MA = '0b000001' +RGBA_CURRENT_08MA_04MA = '0b000011' +RGBA_CURRENT_12MA_06MA = '0b000111' +RGBA_CURRENT_16MA_08MA = '0b001111' +RGBA_CURRENT_20MA_10MA = '0b011111' +RGBA_CURRENT_24MA_12MA = '0b111111' + +# +# Signals +# +counter = Signal(28) + +rgb0_pwm = Signal(1) +rgb1_pwm = Signal(1) +rgb2_pwm = Signal(1) + +# Setup platform and correctly map pins for the +# iCE40UP5K SB_RGBA_DRV hard macro. +if os.environ['FOMU_REV'] in ['evt1', 'evt2']: + platform = fomu.FomuEvt2Platform() + blue_pwm = rgb0_pwm + red_pwm = rgb1_pwm + green_pwm = rgb2_pwm +elif os.environ['FOMU_REV'] == 'evt3': + platform = fomu.FomuEvt3Platform() + blue_pwm = rgb0_pwm + red_pwm = rgb1_pwm + green_pwm = rgb2_pwm +elif os.environ['FOMU_REV'] == 'hacker': + platform = fomu.FomuHackerPlatform() + blue_pwm = rgb0_pwm + green_pwm = rgb1_pwm + red_pwm = rgb2_pwm +elif os.environ['FOMU_REV'] == 'pvt': + platform = fomu.FomuPvtPlatform() + green_pwm = rgb0_pwm + red_pwm = rgb1_pwm + blue_pwm = rgb2_pwm +else: + print('Board not supported!') + exit(2) + +usb_pins = platform.request('usb') +rgb_pins = platform.request('rgb_led') + +m = Module() + +### + +# Drive the USB outputs to constant values as they are not in use. +# Assign USB pins to "0" so as to disconnect Fomu from +# the host system. Otherwise it would try to talk to +# us over USB, which wouldn't work since we have no stack. +m.comb += [usb_pins.d_p.eq(0), + usb_pins.d_n.eq(0), + usb_pins.pullup.eq(0)] + +m.comb += [red_pwm.eq(counter[24]), + green_pwm.eq(counter[23]), + blue_pwm.eq(counter[25])] + +# Increment counter on clock signal +m.sync += counter.eq(counter + 1) + +# Instantiate iCE40 LED driver hard logic, connecting up +# latched button state, counter state, and LEDs. +# +# Note that it's possible to drive the LEDs directly, +# however that is not current-limited and results in +# overvolting the red LED. +# +# See also: +# https://www.latticesemi.com/-/media/LatticeSemi/Documents/ApplicationNotes/IK/ICE40LEDDriverUsageGuide.ashx?document_id=50668 +m.specials += Instance('SB_RGBA_DRV', + i_CURREN=0b1, + i_RGBLEDEN=0b1, + i_RGB0PWM=rgb0_pwm, + i_RGB1PWM=rgb1_pwm, + i_RGB2PWM=rgb2_pwm, + o_RGB0=rgb_pins.r, + o_RGB1=rgb_pins.g, + o_RGB2=rgb_pins.b, + p_CURRENT_MODE=RGBA_CURRENT_MODE_HALF, + p_RGB0_CURRENT=RGBA_CURRENT_08MA_04MA, + p_RGB1_CURRENT=RGBA_CURRENT_08MA_04MA, + p_RGB2_CURRENT=RGBA_CURRENT_08MA_04MA) + +platform.build(m) diff --git a/migen/fomu.py b/migen/fomu.py new file mode 100644 index 0000000..64bf352 --- /dev/null +++ b/migen/fomu.py @@ -0,0 +1,141 @@ +""" Fomu board definitions (mapping of I/O pins, clock, etc.) """ + +from migen import * +from migen.build.generic_platform import * +from migen.build.lattice import LatticePlatform + + +class FomuPvtPlatform(LatticePlatform): + """ Based on + https://github.com/litex-hub/litex-boards/blob/master/litex_boards/partner/platforms/fomu_pvt.py """ + + _io = [ + ('clk48', 0, Pins('F4'), IOStandard('LVCMOS33')), + + ('user_led_n', 0, Pins('A5'), IOStandard('LVCMOS33')), + ('rgb_led', 0, + Subsignal('r', Pins('C5')), + Subsignal('g', Pins('B5')), + Subsignal('b', Pins('A5')), + IOStandard('LVCMOS33')), + + ('user_touch_n', 0, Pins('E4'), IOStandard('LVCMOS33')), + ('user_touch_n', 1, Pins('D5'), IOStandard('LVCMOS33')), + ('user_touch_n', 2, Pins('E5'), IOStandard('LVCMOS33')), + ('user_touch_n', 3, Pins('F5'), IOStandard('LVCMOS33')), + + ('usb', 0, + Subsignal('d_p', Pins('A1')), + Subsignal('d_n', Pins('A2')), + Subsignal('pullup', Pins('A4')), + IOStandard('LVCMOS33')) + ] + + _connectors = [ + ('touch_pins', 'E4 D5 E5 F5') + ] + + default_clk_name = 'clk48' + default_clk_period = 1e9 / 48e6 + + def __init__(self): + LatticePlatform.__init__(self, + 'ice40-up5k-uwg30', + self._io, + self._connectors, + toolchain='icestorm') + + def create_programmer(self): + return IceStormProgrammer() + + +class FomuHackerPlatform(LatticePlatform): + """ Based on + https://github.com/litex-hub/litex-boards/blob/master/litex_boards/partner/platforms/fomu_hacker.py """ + + _io = [ + ('clk48', 0, Pins('F5'), IOStandard('LVCMOS33')), + + ('user_led_n', 0, Pins('A5'), IOStandard('LVCMOS33')), + ('rgb_led', 0, + Subsignal('r', Pins('C5')), + Subsignal('g', Pins('B5')), + Subsignal('b', Pins('A5')), + IOStandard('LVCMOS33')), + + ('user_touch_n', 0, Pins('F4'), IOStandard('LVCMOS33')), + ('user_touch_n', 1, Pins('E5'), IOStandard('LVCMOS33')), + ('user_touch_n', 2, Pins('E4'), IOStandard('LVCMOS33')), + ('user_touch_n', 3, Pins('F2'), IOStandard('LVCMOS33')), + + ('usb', 0, + Subsignal('d_p', Pins('A4')), + Subsignal('d_n', Pins('A2')), + Subsignal('pullup', Pins('D5')), + IOStandard('LVCMOS33')) + ] + + _connectors = [ + ('touch_pins', 'F4 E5 E4 F2') + ] + + default_clk_name = 'clk48' + default_clk_period = 1e9 / 48e6 + + def __init__(self): + LatticePlatform.__init__(self, + 'ice40-up5k-uwg30', + self._io, + self._connectors, + toolchain='icestorm') + + def create_programmer(self): + return IceStormProgrammer() + + +class FomuEvt2Platform(LatticePlatform): + """ Based on + https://github.com/litex-hub/litex-boards/blob/master/litex_boards/partner/platforms/fomu_evt.py """ + + _io = [ + ('clk48', 0, Pins('44'), IOStandard('LVCMOS33')), + + ('user_led_n', 0, Pins('41'), IOStandard('LVCMOS33')), + ('rgb_led', 0, + Subsignal('r', Pins('40')), + Subsignal('g', Pins('39')), + Subsignal('b', Pins('41')), + IOStandard('LVCMOS33')), + + ('user_touch_n', 0, Pins('48'), IOStandard('LVCMOS33')), + ('user_touch_n', 1, Pins('47'), IOStandard('LVCMOS33')), + ('user_touch_n', 2, Pins('46'), IOStandard('LVCMOS33')), + ('user_touch_n', 3, Pins('45'), IOStandard('LVCMOS33')), + + ('usb', 0, + Subsignal('d_p', Pins('34')), + Subsignal('d_n', Pins('37')), + Subsignal('pullup', Pins('35')), + Subsignal('pulldown', Pins('36')), + IOStandard('LVCMOS33')) + ] + + _connectors = [ + ('touch_pins', '48 47 46 45') + ] + + default_clk_name = 'clk48' + default_clk_period = 1e9 / 48e6 + + def __init__(self): + LatticePlatform.__init__(self, + 'ice40-up5k-sg48', + self._io, + self._connectors, + toolchain='icestorm') + + def create_programmer(self): + return IceStormProgrammer() + + +FomuEvt3Platform = FomuEvt2Platform