aboutsummaryrefslogtreecommitdiff
path: root/fpga/src/I2C.bs
diff options
context:
space:
mode:
authorNathan Ringo <nathan@remexre.com>2024-10-24 21:37:09 -0500
committerNathan Ringo <nathan@remexre.com>2024-10-24 21:37:09 -0500
commitd3bcde4eedd2dd3dcf5cbc4302821f38ff553498 (patch)
tree504e0122bafe4230ec6ff9c05f2afc8b19bc338e /fpga/src/I2C.bs
parent7d5d900b63103469e9592e365031a979a24c95f6 (diff)
Single writes working?
Diffstat (limited to 'fpga/src/I2C.bs')
-rw-r--r--fpga/src/I2C.bs85
1 files changed, 80 insertions, 5 deletions
diff --git a/fpga/src/I2C.bs b/fpga/src/I2C.bs
index 2752acd..2a0614f 100644
--- a/fpga/src/I2C.bs
+++ b/fpga/src/I2C.bs
@@ -79,6 +79,22 @@ data I2CBusState
| -- | We're reading SDA, which should be the ACK bit after sending an
-- address.
GetAddrAckReadSDA
+ | -- | TODO
+ WriteLowerSCL (Bit 1) (Bit 3)
+ | -- | TODO
+ WriteWriteSDA (Bit 3)
+ | -- | TODO
+ WriteRaiseSCL (Bit 1) (Bit 3) (Bit 1)
+ | -- | TODO
+ WriteAckLowerSCL (Bit 1)
+ | -- | TODO
+ WriteAckRaiseSDA
+ | -- | TODO
+ WriteAckRaiseSCL
+ | -- | TODO
+ WriteAckReadSDA
+ | -- | TODO
+ TODO
| -- | We're about to either lower SCL or keep it low as part of reading a
-- byte from a device.
ReadLowerSCL (Bit 3) (Bit 1)
@@ -98,7 +114,13 @@ data I2CBusState
-- hold, the second is the number of cycles to hold it for.
ReadAckRaiseSCL (Bit 1) (Bit 1)
| -- | TODO
- TODO
+ StopLowerSCL
+ | -- | TODO
+ StopLowerSDA
+ | -- | TODO
+ StopRaiseSCL
+ | -- | TODO
+ StopRaiseSDA
deriving (Bits, FShow)
-- | Runs an I²C interface on the current clock.
@@ -164,8 +186,44 @@ mkI2C' rxSCL rxSDA txSCL txSDA addrReg dataReg statusReg = module
state := if rxSDA == 1 -- NACK
then TODO
else if savedAddr[0:0] == 0 -- R/!W
- then TODO -- !W
- else ReadLowerSCL 7 1
+ then WriteLowerSCL 1 7 -- !W
+ else ReadLowerSCL 7 1 -- R
+ txSCL := 1
+ txSDA := 1
+ "WriteLowerSCL": when WriteLowerSCL bit n <- state ==> do
+ state := WriteWriteSDA n
+ txSCL := 0
+ txSDA := bit
+ "WriteWriteSDA": when WriteWriteSDA n <- state ==> do
+ let bit = savedData[n:n]
+ state := WriteRaiseSCL bit n 1
+ txSCL := 0
+ txSDA := bit
+ "WriteRaiseSCL": when WriteRaiseSCL bit n time <- state ==> do
+ state := if time == 1
+ then WriteRaiseSCL bit n (time - 1)
+ else if n == 0
+ then WriteAckLowerSCL bit
+ else WriteLowerSCL bit (n - 1)
+ txSCL := 1
+ txSDA := bit
+ "WriteAckLowerSCL": when WriteAckLowerSCL bit <- state ==> do
+ state := WriteAckRaiseSDA
+ txSCL := 0
+ txSDA := bit
+ "WriteAckRaiseSDA": when WriteAckRaiseSDA <- state ==> do
+ state := WriteAckRaiseSCL
+ txSCL := 0
+ txSDA := 1
+ "WriteAckRaiseSCL": when WriteAckRaiseSCL <- state ==> do
+ state := WriteAckReadSDA
+ txSCL := 1
+ txSDA := 1
+ "WriteAckReadSDA": when WriteAckReadSDA <- state ==> do
+ statusReg := statusReg { ready = True; dataAckBit = unpack rxSDA }
+ state := if rxSDA == 1 -- NACK
+ then StopLowerSCL
+ else TODO
txSCL := 1
txSDA := 1
"ReadLowerSCL": when ReadLowerSCL n time <- state ==> do
@@ -201,9 +259,26 @@ mkI2C' rxSCL rxSDA txSCL txSDA addrReg dataReg statusReg = module
then ReadAckRaiseSCL bit (time - 1)
else if bit == 0
then ReadLowerSCL 7 1 -- ACK
- else TODO -- NACK
+ else StopLowerSCL -- NACK
txSCL := 1
txSDA := bit
+ "StopLowerSCL": when StopLowerSCL <- state ==> do
+ state := StopLowerSDA
+ txSCL := 0
+ txSDA := 1
+ "StopLowerSDA": when StopLowerSDA <- state ==> do
+ state := StopRaiseSCL
+ txSCL := 0
+ txSDA := 0
+ "StopRaiseSCL": when StopRaiseSCL <- state ==> do
+ state := StopRaiseSDA
+ txSCL := 1
+ txSDA := 0
+ "StopRaiseSDA": when StopRaiseSDA <- state ==> do
+ state := Idle
+ statusReg := statusReg { busIdle = True }
+ txSCL := 1
+ txSDA := 1
return ()
-- | Returns an I²C interface that runs on the current clock. This is not what
@@ -216,7 +291,7 @@ mkI2C rxSCL rxSDA = module
dataReg <- mkReg 0
statusReg <- mkReg (I2CStatus
{ ready = True
- ; busIdle = False
+ ; busIdle = True
; addrAckBit = False
; dataAckBit = False
; arbitrationLost = False