diff options
Diffstat (limited to 'fpga/src/I2C.bs')
-rw-r--r-- | fpga/src/I2C.bs | 85 |
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 |