Skip to content

Commit

Permalink
cores/i2c: documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
povauboin committed Nov 14, 2024
1 parent e9b2b05 commit bda3491
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 0 deletions.
33 changes: 33 additions & 0 deletions lambdalib/cores/i2c/proto.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,39 @@
STATUS_ERR = 1

class I2CProto(Elaboratable):
""" Protocol oriented wrapper around the bidirectional I2CStream.
The main use of this module is for creating a I2C bridge from software,
typically over UART or USB.
Sink stream description:
`data`: header
header[0]: 1 == read
0 == write
`data`: length
amount of data bytes to read or write
When writing:
-> `sink.data`
header
-> `sink.data`
length
-> `sink.data` ... `sink.data`
data write ... data write
<- `source.data`
status
When reading:
-> `sink.data`
header
-> `sink.data`
length
<- `source.data`
status
<- `source.data` ... `source.data`
data read ... data read
"""
def __init__(self,
sys_clk_freq,
i2c_freq=400e3,
Expand Down
90 changes: 90 additions & 0 deletions lambdalib/cores/i2c/stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,82 @@ class I2CStage:


class I2CStream(Elaboratable):
""" Bidirectional stream wrapper for I2C.
Sink stream description:
`r_wn`: 1 == read 8 bits on SDA
0 == write 8 bits on SDA
`data`: for write: data to write on SDA
for read: N/A
`last`: 1 to indicate this is the last I2C transfer,
I2C stop will be sent at the end of this transaction.
Source stream description:
`data`: for read: 8 bits read from SDA
for write: N/A
`last`: for read: indicate this was the last data read
before the end of the I2C transaction.
Example of use: I2C 8bit address register write
===============================================
Step 1: Write I2C chip address
r_wn == 0
data == I2C chip address << 1
last == 0
Step 2: Write register address
r_wn == 0
data == register address
last == 0
Step 3: Write register values
r_wn == 0
data == 1st register value
last == 0
[...]
r_wn == 0
data == nth register value
last == 1 <--- I2C STOP
Example of use: I2C 8bit address register read
==============================================
Step 1: Write I2C chip address
r_wn == 0
data == I2C chip address << 1
last == 0
Step 2: Write register address
r_wn == 0
data == register address
last == 1 <--- I2C STOP
Step 3: Write I2C chip address
r_wn == 0
data == (I2C chip address << 1) | 1
last == 0
Step 4: Read register values
sink.r_wn == 1
sink.data == N/A
sink.last == 0
source.data == 1st register value
source.last == 0
[...]
sink.r_wn == 1
sink.data == N/A
sink.last == 1 <--- I2C STOP
source.data == nth register value
source.last == 1
"""

def __init__(self, pins, period_cyc, **kwargs):
self.pins = pins
self.period_cyc = period_cyc
Expand Down Expand Up @@ -132,6 +208,20 @@ def elaborate(self, platform):


class I2CWriterStream(Elaboratable):
""" Write only stream wrapper around I2CInitiator.
Important note:
This module is intented to be used only
when I2C transactions always have the same 3 steps format:
1. I2C chip address
2. register address
3. register value
The `sink.last` signal is not used and I2C transaction is
always stopped on the 3rd step after writing one register value.
As such, this module cannot be used to write a burst of registers.
"""
def __init__(self, pins, period_cyc, **kwargs):
self.pins = pins
self.period_cyc = period_cyc
Expand Down

0 comments on commit bda3491

Please sign in to comment.