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 }