1 // 2 // Copyright (c) 2010-2019 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 8 using System; 9 using System.Linq; 10 using System.Collections.Generic; 11 12 using Antmicro.Renode.Core; 13 using Antmicro.Renode.Utilities; 14 using Antmicro.Renode.Core.Structure; 15 using Antmicro.Renode.Core.Structure.Registers; 16 using Antmicro.Renode.Peripherals.Bus; 17 using Antmicro.Renode.Logging; 18 using Antmicro.Renode.Debugging; 19 20 namespace Antmicro.Renode.Peripherals.I2C 21 { 22 public class LiteX_I2C : SimpleContainer<II2CPeripheral>, IDoubleWordPeripheral, IKnownSize 23 { LiteX_I2C(IMachine machine)24 public LiteX_I2C(IMachine machine) : base(machine) 25 { 26 // 0 - clock, 1 - data, 2 - direction 27 i2cDecoder = new BitPatternDetector(new [] { true, true, true }, this); 28 i2cDecoder.RegisterPatternHandler((prev, curr) => !prev[ClockSignal] && curr[ClockSignal], name: "clockRising", action: HandleClockRising); 29 i2cDecoder.RegisterPatternHandler((prev, curr) => prev[ClockSignal] && !curr[ClockSignal], name: "clockFalling", action: HandleClockFalling); 30 i2cDecoder.RegisterPatternHandler((prev, curr) => prev[ClockSignal] && curr[ClockSignal] && prev[DataSignal] && !curr[DataSignal], name: "start", action: HandleStartCondition); 31 i2cDecoder.RegisterPatternHandler((prev, curr) => prev[ClockSignal] && curr[ClockSignal] && !prev[DataSignal] && curr[DataSignal], name: "stop", action: HandleStopCondition); 32 33 var registers = new Dictionary<long, DoubleWordRegister> 34 { 35 {(long)Registers.BitBang, new DoubleWordRegister(this, 0x5) // SCL && SDA are high by default 36 .WithFlag(0, out var clockSignal, name: "SCL") 37 .WithFlag(1, out var directionSignal, name: "OE") 38 .WithFlag(2, out var dataSignal, name: "SDA") 39 .WithWriteCallback((_, val) => i2cDecoder.AcceptState(new [] { clockSignal.Value, dataSignal.Value, directionSignal.Value })) 40 }, 41 42 {(long)Registers.Data, new DoubleWordRegister(this) 43 .WithFlag(0, FieldMode.Read, valueProviderCallback: _ => 44 { 45 if(directionSignal.Value) 46 { 47 this.Log(LogLevel.Warning, "Trying to read data, but the direction signal is set to OUTPUT"); 48 return true; 49 } 50 51 if(bufferFromDevice.Count == 0) 52 { 53 if(state == State.Read) 54 { 55 // try - maybe there is sth more waiting for us 56 ReadNextByteFromDevice(); 57 } 58 59 if(bufferFromDevice.Count == 0) 60 { 61 this.Log(LogLevel.Warning, "There are no more output bits to read"); 62 // SDA is high when no data 63 return true; 64 } 65 } 66 67 return bufferFromDevice.Peek(); 68 }) 69 }, 70 }; 71 72 bufferFromDevice = new Queue<bool>(); 73 bufferToDevice = new Stack<bool>(); 74 bytesToDevice = new Queue<byte>(); 75 76 registersCollection = new DoubleWordRegisterCollection(this, registers); 77 Reset(); 78 } 79 Reset()80 public override void Reset() 81 { 82 registersCollection.Reset(); 83 i2cDecoder.Reset(); 84 ResetBuffers(); 85 86 state = State.Idle; 87 tickCounter = 0; 88 slave = null; 89 isRead = false; 90 } 91 ReadDoubleWord(long offset)92 public uint ReadDoubleWord(long offset) 93 { 94 return registersCollection.Read(offset); 95 } 96 WriteDoubleWord(long offset, uint value)97 public void WriteDoubleWord(long offset, uint value) 98 { 99 registersCollection.Write(offset, value); 100 } 101 102 public long Size => 0x10; 103 HandleStopCondition(bool[] signals)104 private void HandleStopCondition(bool[] signals) 105 { 106 if(slave != null && bytesToDevice.Count > 0) 107 { 108 this.Log(LogLevel.Noisy, "Writing data to the device"); 109 slave.Write(bytesToDevice.DequeueAll()); 110 } 111 112 ResetBuffers(); 113 114 this.Log(LogLevel.Noisy, "Stop condition detected in state: {0}", state); 115 state = State.Idle; 116 } 117 HandleStartCondition(bool[] signals)118 private void HandleStartCondition(bool[] signals) 119 { 120 this.Log(LogLevel.Noisy, "(repeated) Start condition detected in state: {0}", state); 121 122 if(slave != null && bytesToDevice.Count > 0) 123 { 124 this.Log(LogLevel.Noisy, "Writing data to the device"); 125 slave.Write(bytesToDevice.DequeueAll()); 126 } 127 128 ResetBuffers(); 129 state = State.Address; 130 } 131 HandleClockRising(bool[] signals)132 private void HandleClockRising(bool[] signals) 133 { 134 switch(state) 135 { 136 case State.Address: 137 { 138 this.Log(LogLevel.Noisy, "Appending address bit #{0}: {1}", bufferToDevice.Count, signals[DataSignal]); 139 bufferToDevice.Push(signals[DataSignal]); 140 141 if(bufferToDevice.Count == 7) 142 { 143 var address = (int)BitHelper.GetValueFromBitsArray(bufferToDevice.PopAll()); 144 145 this.Log(LogLevel.Noisy, "Address decoded: 0x{0:X}", address); 146 state = State.Operation; 147 148 if(!TryGetByAddress(address, out slave)) 149 { 150 this.Log(LogLevel.Warning, "Trying to access a non-existing I2C device at address 0x{0:X}", address); 151 } 152 } 153 break; 154 } 155 156 case State.Operation: 157 { 158 isRead = signals[DataSignal]; 159 this.Log(LogLevel.Noisy, "Operation decoded: {0}", isRead ? "read" : "write"); 160 161 state = State.AddressAck; 162 break; 163 } 164 165 case State.AddressAck: 166 { 167 // write ACK(false) or NACK(true) 168 bufferFromDevice.Enqueue(slave == null); 169 170 if(slave == null) 171 { 172 // ignore the rest of transmission until the next (repeated) start condition 173 state = State.Idle; 174 } 175 else if(isRead) 176 { 177 tickCounter = 0; 178 state = State.Read; 179 } 180 else // it must be write 181 { 182 state = State.Write; 183 } 184 break; 185 } 186 187 case State.Read: 188 { 189 tickCounter++; 190 if(tickCounter == 8) 191 { 192 state = State.ReadAck; 193 } 194 break; 195 } 196 197 case State.ReadAck: 198 { 199 tickCounter = 0; 200 state = State.Read; 201 break; 202 } 203 204 case State.Write: 205 { 206 this.Log(LogLevel.Noisy, "Latching data bit #{0}: {1}", bufferToDevice.Count, signals[DataSignal]); 207 bufferToDevice.Push(signals[DataSignal]); 208 209 if(bufferToDevice.Count == 8) 210 { 211 state = State.WriteAck; 212 } 213 break; 214 } 215 216 case State.WriteAck: 217 { 218 DebugHelper.Assert(bufferToDevice.Count == 8); 219 220 var dataByte = (byte)BitHelper.GetValueFromBitsArray(bufferToDevice.PopAll()); 221 this.Log(LogLevel.Noisy, "Decoded data byte #{0}: 0x{1:X}", bytesToDevice.Count, dataByte); 222 223 bytesToDevice.Enqueue(dataByte); 224 225 // ACK 226 this.Log(LogLevel.Noisy, "Enqueuing ACK"); 227 bufferFromDevice.Enqueue(false); 228 229 state = State.Write; 230 break; 231 } 232 } 233 } 234 HandleClockFalling(bool[] signals)235 private void HandleClockFalling(bool[] signals) 236 { 237 if(!signals[DirectionSignal]) 238 { 239 bufferFromDevice.TryDequeue(out var unused); 240 } 241 } 242 ResetBuffers()243 private void ResetBuffers() 244 { 245 bufferToDevice.Clear(); 246 bufferFromDevice.Clear(); 247 bytesToDevice.Clear(); 248 249 state = State.Idle; 250 slave = null; 251 isRead = false; 252 } 253 ReadNextByteFromDevice()254 private void ReadNextByteFromDevice() 255 { 256 if(slave == null) 257 { 258 this.Log(LogLevel.Warning, "Trying to read data from the device, but no slave is currently selected"); 259 return; 260 } 261 262 this.Log(LogLevel.Noisy, "Reading byte from device"); 263 foreach(var @byte in slave.Read()) 264 { 265 // bits in I2C are transmitted most-significant-bit first 266 var bits = BitHelper.GetBits(@byte).Take(8).Reverse(); 267 foreach(var bit in bits) 268 { 269 bufferFromDevice.Enqueue(bit); 270 } 271 } 272 } 273 274 private readonly DoubleWordRegisterCollection registersCollection; 275 private readonly BitPatternDetector i2cDecoder; 276 private readonly Stack<bool> bufferToDevice; 277 private readonly Queue<bool> bufferFromDevice; 278 private readonly Queue<byte> bytesToDevice; 279 280 private State state; 281 private int tickCounter; 282 private II2CPeripheral slave; 283 private bool isRead; 284 285 private const int ClockSignal = 0; 286 private const int DataSignal = 1; 287 private const int DirectionSignal = 2; 288 289 private enum Registers 290 { 291 BitBang = 0x0, 292 Data = 0x4 293 } 294 295 private enum State 296 { 297 Idle, 298 Address, 299 AddressAck, 300 Operation, 301 Write, 302 WriteAck, 303 Read, 304 ReadAck 305 } 306 } 307 } 308