mirror of
https://github.com/im-tomu/fomu-workshop.git
synced 2024-09-20 03:10:12 +00:00
add migen examples for blink and blink-expanded
This commit is contained in:
parent
d42d25121a
commit
b009e1c533
140
migen/blink-expanded.py
Executable file
140
migen/blink-expanded.py
Executable file
@ -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)
|
112
migen/blink.py
Executable file
112
migen/blink.py
Executable file
@ -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)
|
141
migen/fomu.py
Normal file
141
migen/fomu.py
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user