Skip to content

Commit 124f53e

Browse files
committed
chryse-to-niar: init.
1 parent 472c24e commit 124f53e

File tree

15 files changed

+394
-152
lines changed

15 files changed

+394
-152
lines changed

.gitignore

+3-12
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,7 @@
1-
build/
1+
__pycache__
2+
/build
23
*.vcd
4+
35
.zig-cache/
46
zig-out/
57
rom.bin
6-
7-
target/
8-
test_run_dir/
9-
10-
.cache/
11-
.metals/
12-
.bloop/
13-
.bsp/
14-
metals.sbt
15-
16-
.DS_Store

.scalafmt.conf

-47
This file was deleted.

.vscode/settings.json

+9-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
{
2-
"files.watcherExclude": {
3-
"**/target": true
4-
},
52
"editor.formatOnSave": true,
3+
"[python]": {
4+
"editor.codeActionsOnSave": {
5+
"source.organizeImports": "explicit"
6+
}
7+
},
8+
"python.analysis.autoImportCompletions": true,
9+
"python.analysis.diagnosticSeverityOverrides": {
10+
"reportGeneralTypeIssues": "none"
11+
}
612
}

build.sbt

-28
This file was deleted.

ili9341spi/__init__.py

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import niar
2+
3+
from . import rtl
4+
from .targets import cxxrtl, icebreaker, ulx3s
5+
6+
__all__ = ["ILI9341SPI"]
7+
8+
9+
class ILI9341SPI(niar.Project):
10+
name = "ili9341spi"
11+
top = rtl.Top
12+
targets = [icebreaker, ulx3s]
13+
cxxrtl_targets = [cxxrtl]

ili9341spi/__main__.py

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from . import ILI9341SPI
2+
3+
ILI9341SPI().main()

ili9341spi/rtl/__init__.py

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
from amaranth import Module, Signal
2+
from amaranth.build import Attrs, Pins, PinsN, Resource, Subsignal
3+
from amaranth.lib import wiring
4+
from amaranth.lib.cdc import FFSynchronizer
5+
from amaranth.lib.wiring import In, Out
6+
from amaranth_stdio.serial import AsyncSerial
7+
8+
from ..targets import cxxrtl, icebreaker, ulx3s
9+
from .lcd import Lcd
10+
11+
__all__ = ["Top"]
12+
13+
14+
icebreaker_spi_lcd = Resource(
15+
"spi_lcd",
16+
0,
17+
Subsignal(
18+
"clk", Pins("3", dir="o", conn=("pmod", 0)), Attrs(IO_STANDARD="SB_LVCMOS")
19+
),
20+
Subsignal(
21+
"copi", Pins("4", dir="o", conn=("pmod", 0)), Attrs(IO_STANDARD="SB_LVCMOS")
22+
),
23+
Subsignal(
24+
"res", PinsN("7", dir="o", conn=("pmod", 0)), Attrs(IO_STANDARD="SB_LVCMOS")
25+
),
26+
Subsignal(
27+
"dc", PinsN("8", dir="o", conn=("pmod", 0)), Attrs(IO_STANDARD="SB_LVCMOS")
28+
),
29+
Subsignal(
30+
"blk", Pins("9", dir="o", conn=("pmod", 0)), Attrs(IO_STANDARD="SB_LVCMOS")
31+
),
32+
Subsignal(
33+
"cipo", Pins("10", dir="i", conn=("pmod", 0)), Attrs(IO_STANDARD="SB_LVCMOS")
34+
),
35+
)
36+
37+
38+
class Top(wiring.Component):
39+
def __init__(self, platform):
40+
if isinstance(platform, cxxrtl):
41+
super().__init__(
42+
{
43+
"lcd": Out(Lcd.PinSignature),
44+
"lcd_res": Out(1),
45+
"uart_rx": In(1),
46+
"uart_tx": Out(1),
47+
}
48+
)
49+
else:
50+
super().__init__({})
51+
52+
def elaborate(self, platform):
53+
m = Module()
54+
55+
m.submodules.serial = serial = AsyncSerial(
56+
divisor=int(platform.default_clk_frequency // 115_200)
57+
)
58+
59+
res = Signal(init=0)
60+
blk = Signal(init=1)
61+
62+
ili = wiring.flipped(Lcd.PinSignature.create())
63+
64+
m.submodules.lcd = lcd = Lcd()
65+
wiring.connect(m, lcd.pins, ili)
66+
67+
match platform:
68+
case icebreaker():
69+
platform.add_resources([icebreaker_spi_lcd])
70+
plat_spi = platform.request("spi_lcd")
71+
m.d.comb += [
72+
plat_spi.clk.o.eq(ili.clk),
73+
plat_spi.copi.o.eq(ili.copi),
74+
plat_spi.res.o.eq(res),
75+
plat_spi.dc.o.eq(ili.dc),
76+
plat_spi.blk.o.eq(blk),
77+
ili.cipo.eq(plat_spi.cipo.i),
78+
]
79+
80+
plat_uart = platform.request("uart")
81+
m.d.comb += plat_uart.tx.o.eq(serial.tx.o)
82+
m.submodules += FFSynchronizer(plat_uart.rx.i, serial.rx.i, init=1)
83+
84+
case ulx3s():
85+
plat_uart = platform.request("uart")
86+
m.d.comb += plat_uart.tx.o.eq(serial.tx.o)
87+
m.submodules += FFSynchronizer(plat_uart.rx.i, serial.rx.i, init=1)
88+
89+
case cxxrtl():
90+
m.d.comb += self.uart_tx.eq(serial.tx.o)
91+
m.d.comb += serial.rx.i.eq(self.uart_rx)
92+
wiring.connect(m, self.lcd, ili)
93+
m.d.comb += self.lcd_res.eq(res)
94+
95+
return m
96+
97+
98+
class Blinker(wiring.Component):
99+
ledr: Out(1)
100+
ledg: Out(1)
101+
102+
def elaborate(self, platform):
103+
m = Module()
104+
105+
m.d.comb += self.ledg.eq(1)
106+
107+
timer_top = (int(platform.default_clk_frequency) // 2) - 1
108+
timer_half = (int(platform.default_clk_frequency) // 4) - 1
109+
timer_reg = Signal(range(timer_top), init=timer_half)
110+
111+
with m.If(timer_reg == 0):
112+
m.d.sync += [
113+
self.ledr.eq(~self.ledr),
114+
timer_reg.eq(timer_top),
115+
]
116+
with m.Else():
117+
m.d.sync += timer_reg.eq(timer_reg - 1)
118+
119+
return m

ili9341spi/rtl/lcd.py

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
from amaranth import Cat, Module, Signal
2+
from amaranth.lib import data, stream, wiring
3+
from amaranth.lib.wiring import In, Out
4+
5+
__all__ = ["Lcd"]
6+
7+
8+
class Lcd(wiring.Component):
9+
PinSignature = wiring.Signature(
10+
{
11+
"clk": Out(1),
12+
"copi": Out(1),
13+
"dc": Out(1),
14+
"cipo": In(1),
15+
}
16+
)
17+
18+
class Request(data.Struct):
19+
data: 8
20+
dc: 1
21+
resp_len: 4
22+
23+
CommandSignature = wiring.Signature(
24+
{
25+
"req": In(stream.Signature(Request)),
26+
"resp": Out(stream.Signature(8)),
27+
}
28+
)
29+
30+
pins: Out(PinSignature)
31+
command: Out(CommandSignature)
32+
33+
def elaborate(self, platform):
34+
m = Module()
35+
36+
m.d.comb += self.pins.clk.eq(0)
37+
38+
sr = Signal(8)
39+
with m.If(self.pins.clk):
40+
m.d.sync += sr.eq(Cat(self.pins.cipo, sr[:7]))
41+
m.d.comb += self.pins.copi.eq(sr[7])
42+
43+
self.command.req.nodeq(m)
44+
self.command.resp.noenq(m)
45+
46+
bit_rem = Signal(3)
47+
rcv_byte_rem = Signal(4)
48+
49+
with m.FSM():
50+
with m.State("idle"):
51+
payload = self.command.req.deq(m)
52+
with m.If(self.command.req.fire):
53+
m.d.sync += [
54+
sr.eq(payload.data),
55+
self.pins.dc.eq(payload.dc),
56+
bit_rem.eq(7),
57+
rcv_byte_rem.eq(payload.resp_len),
58+
]
59+
m.next = "snd_low"
60+
61+
with m.State("snd_low"):
62+
m.next = "snd_high"
63+
64+
with m.State("snd_high"):
65+
m.d.comb += self.pins.clk.eq(1)
66+
m.d.sync += bit_rem.eq(bit_rem - 1)
67+
m.next = "snd_low"
68+
69+
with m.If(bit_rem == 0):
70+
m.d.sync += [
71+
bit_rem.eq(7),
72+
rcv_byte_rem.eq(rcv_byte_rem - 1),
73+
self.pins.dc.eq(0),
74+
]
75+
with m.If(rcv_byte_rem == 0):
76+
m.next = "idle"
77+
with m.Else():
78+
m.next = "rcv_low"
79+
80+
with m.State("rcv_low"):
81+
m.next = "rcv_high"
82+
83+
with m.State("rcv_high"):
84+
m.d.comb += self.pins.clk.eq(1)
85+
m.d.sync += bit_rem.eq(bit_rem - 1)
86+
m.next = "rcv_low"
87+
88+
with m.If(bit_rem == 0):
89+
m.d.sync += bit_rem.eq(7)
90+
m.next = "rcv_done"
91+
92+
with m.State("rcv_done"):
93+
# no backpressure, oops.
94+
self.command.resp.enq(m, sr)
95+
m.d.sync += rcv_byte_rem.eq(rcv_byte_rem - 1)
96+
97+
with m.If(rcv_byte_rem == 0):
98+
m.next = "idle"
99+
with m.Else():
100+
m.next = "rcv_high"
101+
102+
return m

ili9341spi/targets.py

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import niar
2+
from amaranth_boards.icebreaker import ICEBreakerPlatform
3+
from amaranth_boards.ulx3s import ULX3S_45F_Platform
4+
5+
__all__ = ["icebreaker", "ulx3s", "cxxrtl"]
6+
7+
8+
class icebreaker(ICEBreakerPlatform):
9+
pass
10+
11+
12+
class ulx3s(ULX3S_45F_Platform):
13+
pass
14+
15+
16+
class cxxrtl(niar.CxxrtlPlatform):
17+
default_clk_frequency = 1_000_000.0

project/build.properties

-1
This file was deleted.

project/plugins.sbt

-3
This file was deleted.

pyproject.toml

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[project]
2+
name = "ili9341spi"
3+
version = "0.0"
4+
description = ""
5+
authors = [{ name = "Asherah Connor", email = "[email protected]" }]
6+
dependencies = [
7+
"amaranth >= 0.5, < 0.7",
8+
"amaranth-boards",
9+
"amaranth-stdio",
10+
"niar >= 0.1",
11+
]
12+
requires-python = ">=3.8"
13+
license = { text = "BSD-2-Clause" }
14+
15+
[build-system]
16+
requires = ["pdm-backend"]
17+
build-backend = "pdm.backend"

0 commit comments

Comments
 (0)