Skip to content

Commit a07a3ce

Browse files
committed
cores/i2c: add a driver for the tca9548a i2c multiplexer
1 parent 75b5079 commit a07a3ce

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed

lambdalib/cores/i2c/tca9548a.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# 2024 - LambdaConcept - [email protected]
2+
3+
from amaranth import *
4+
5+
from ...interface import stream
6+
from ..i2c.stream import *
7+
8+
9+
__all__ = ["TCA9548A"]
10+
11+
12+
class TCA9548A(Elaboratable):
13+
""" Driver for TCA9548A I2C multiplexer.
14+
15+
On `self.ctrl` change, an I2C write is triggered to update
16+
the control register of the TCA9548A multiplexer:
17+
byte 0: i2c_addr
18+
byte 1: ctrl byte
19+
20+
This module `source` stream is intented to be connected to an existing
21+
I2CStream instance through a stream arbiter.
22+
"""
23+
def __init__(self, i2c_addr=0x70):
24+
self.i2c_addr = i2c_addr
25+
26+
self.done = Signal()
27+
self.ctrl = Signal(8)
28+
self.source = stream.Endpoint(i2c_stream_description)
29+
30+
def elaborate(self, platform):
31+
source = self.source
32+
33+
m = Module()
34+
35+
init = Signal()
36+
ctrl_r = Signal.like(self.ctrl)
37+
ctrl_addr_n = Signal()
38+
39+
update = (self.ctrl != ctrl_r)
40+
41+
with m.FSM():
42+
with m.State("IDLE"):
43+
with m.If(~init):
44+
m.d.sync += init.eq(1)
45+
m.next = "MUX"
46+
with m.Elif(update):
47+
m.d.sync += ctrl_r.eq(self.ctrl)
48+
m.next = "MUX"
49+
with m.Else():
50+
m.d.comb += self.done.eq(1)
51+
52+
with m.State("MUX"):
53+
m.d.comb += [
54+
source.r_wn .eq(0), # Write
55+
source.data .eq(Mux(~ctrl_addr_n,
56+
self.i2c_addr << 1, ctrl_r)),
57+
source.last .eq(ctrl_addr_n),
58+
source.valid.eq(1),
59+
]
60+
with m.If(source.valid & source.ready):
61+
m.d.sync += ctrl_addr_n.eq(~ctrl_addr_n)
62+
with m.If(source.last):
63+
m.next = "IDLE"
64+
65+
return m

0 commit comments

Comments
 (0)