1 // 2 // Copyright (c) 2010-2018 Antmicro 3 // Copyright (c) 2011-2015 Realtime Embedded 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 9 using Antmicro.Renode.Core; 10 using Antmicro.Renode.Core.Structure; 11 using Antmicro.Renode.Logging; 12 using Antmicro.Renode.Peripherals.Bus; 13 14 15 using System.Collections.Generic; 16 using System.Linq; 17 using Antmicro.Renode.Utilities; 18 19 namespace Antmicro.Renode.Peripherals.I2C 20 { 21 public sealed class VybridI2C : SimpleContainer<II2CPeripheral>, IBytePeripheral, IKnownSize 22 { VybridI2C(IMachine machine)23 public VybridI2C(IMachine machine) : base(machine) 24 { 25 IRQ = new GPIO(); 26 Reset(); 27 } 28 ReadByte(long offset)29 public byte ReadByte(long offset) 30 { 31 switch((Registers)offset) 32 { 33 case Registers.AddressRegister: 34 return address; 35 case Registers.FrequencyDividerRegister: 36 return frequencyDivider; 37 case Registers.ControlRegister: 38 return control; 39 case Registers.StatusRegister: 40 return status; 41 case Registers.DataIORegister: 42 if(mode == Mode.Transmit || state == State.AwaitingAddress) 43 { 44 //reading not ready 45 return 0; 46 } 47 if(state == State.DummyRead) 48 { 49 //return 0, because read mode was just enabled. 50 state = State.AwaitingData; 51 return 0; 52 } 53 if(receiveFifo.Count == 0) 54 { 55 //current state is State.AwaitingData - perform read 56 II2CPeripheral device; 57 if(!TryGetByAddress(address, out device)) 58 { 59 return 0; 60 } 61 receiveFifo = new Queue<byte>(device.Read()); 62 if(receiveFifo.Count == 0) 63 { 64 this.Log(LogLevel.Warning, "Reading from slave device {0} did not return any data.", device.GetType()); 65 } 66 67 } 68 //Acknowledge before returning 69 TransferComplete(); 70 return receiveFifo.Dequeue(); 71 72 case Registers.DebugRegister: 73 case Registers.InterruptConfigRegister: 74 //not used in driver 75 default: 76 this.LogUnhandledRead(offset); 77 return 0; 78 } 79 } 80 WriteByte(long offset, byte value)81 public void WriteByte(long offset, byte value) 82 { 83 switch((Registers)offset) 84 { 85 case Registers.AddressRegister: 86 address = value; 87 break; 88 case Registers.FrequencyDividerRegister: 89 frequencyDivider = value; 90 break; 91 case Registers.ControlRegister: 92 control = value; 93 //Changing Master-Slave mode. Be warned, that slave mode is not implemented. 94 if(BitHelper.IsBitSet(control, (byte)ControlBits.MasterSlaveMode)) 95 { 96 if(!isMaster) 97 { 98 isMaster = true; 99 BitHelper.SetBit(ref status, (byte)StatusBits.BusBusy, true); 100 } 101 } 102 else 103 { 104 if(isMaster) 105 { 106 isMaster = false; 107 BitHelper.SetBit(ref status, (byte)StatusBits.BusBusy, false); 108 receiveFifo.Clear(); 109 } 110 } 111 112 //Switching direction Tx<->Rx 113 if(BitHelper.IsBitSet(control, (byte)ControlBits.TxRx)) 114 { 115 state = State.AwaitingAddress; 116 mode = Mode.Transmit; 117 } 118 else 119 { 120 if(state == State.AwaitingData) 121 { 122 II2CPeripheral device; 123 if(TryGetByAddress(address, out device)) 124 { 125 device.Write(transmitFifo.ToArray()); 126 transmitFifo.Clear(); 127 } 128 } 129 state = State.DummyRead; 130 mode = Mode.Receive; 131 } 132 TransferComplete(); 133 break; 134 case Registers.StatusRegister: 135 //Write 1 to clear interrupt 136 if(BitHelper.IsBitSet(status, (byte)StatusBits.InterruptFlag)) 137 { 138 BitHelper.SetBit(ref status, (byte)StatusBits.InterruptFlag, false); 139 IRQ.Unset(); 140 } 141 break; 142 case Registers.DataIORegister: 143 if(mode == Mode.Receive && state != State.AwaitingAddress) 144 { 145 this.Log(LogLevel.Warning, "Writing in incorrect mode: {0} or state: {1}.", mode, state); 146 } 147 else if(state == State.AwaitingAddress) 148 { 149 address = (byte)(value >> 1); 150 if(BitHelper.IsBitSet(value, 0)) 151 { 152 //read 153 state = State.DummyRead; 154 } 155 else 156 { 157 //write 158 state = State.AwaitingData; 159 } 160 } 161 else if(state == State.AwaitingData) 162 { 163 transmitFifo.Enqueue(value); 164 TransferComplete(); 165 } 166 else 167 { 168 this.Log(LogLevel.Warning, "Writing in incorrect mode: {0} or state: {1}.", mode, state); 169 } 170 break; 171 case Registers.InterruptConfigRegister: 172 case Registers.DebugRegister: 173 //not used in driver 174 default: 175 this.LogUnhandledWrite(offset, value); 176 break; 177 } 178 } 179 Reset()180 public override void Reset() 181 { 182 isMaster = true; 183 state = State.AwaitingAddress; 184 mode = Mode.Receive; 185 address = 0; 186 frequencyDivider = 0; 187 control = 0; 188 status = (byte)(1 << (int)StatusBits.TransferComplete); 189 transmitFifo.Clear(); 190 receiveFifo.Clear(); 191 } 192 193 public GPIO IRQ { get; private set; } 194 195 public long Size { get { return 0x10; } } 196 Update()197 private void Update() 198 { 199 if(BitHelper.IsBitSet(control, (byte)ControlBits.InterruptEnable) && BitHelper.IsBitSet(status, (byte)StatusBits.InterruptFlag)) 200 { 201 IRQ.Set(); 202 } 203 } 204 TransferComplete()205 private void TransferComplete() 206 { 207 BitHelper.SetBit(ref status, (byte)StatusBits.TransferComplete, true); 208 BitHelper.SetBit(ref status, (byte)StatusBits.InterruptFlag, true); 209 Update(); 210 } 211 212 private Queue<byte> transmitFifo = new Queue<byte>(); 213 private Queue<byte> receiveFifo = new Queue<byte>(); 214 215 private byte address; 216 private byte frequencyDivider; 217 private byte control; 218 private byte status; 219 private Mode mode; 220 private State state; 221 private bool isMaster; 222 223 private enum Mode 224 { 225 Transmit, 226 Receive 227 } 228 229 private enum State 230 { 231 AwaitingAddress, 232 AwaitingData, 233 DummyRead 234 } 235 236 private enum Registers 237 { 238 AddressRegister = 0x0, 239 // IBAD 240 FrequencyDividerRegister = 0x1, 241 // IBFD 242 ControlRegister = 0x2, 243 // IBCR 244 StatusRegister = 0x3, 245 // IBSR 246 DataIORegister = 0x4, 247 // IBDR 248 InterruptConfigRegister = 0x5, 249 // IBIC 250 DebugRegister = 0x6 251 // IBDBG 252 } 253 254 private enum ControlBits : byte 255 { 256 InterruptEnable = 6, 257 MasterSlaveMode = 5, 258 TxRx = 4, 259 } 260 261 private enum StatusBits : byte 262 { 263 TransferComplete = 7, 264 AddressedAsASlave = 6, 265 BusBusy = 5, 266 ArbitrationLost = 4, 267 InterruptFlag = 1 268 269 } 270 } 271 }