1 //
2 // Copyright (c) 2010-2023 Antmicro
3 //
4 //  This file is licensed under the MIT License.
5 //  Full license text is available in 'licenses/MIT.txt'.
6 //
7 using System;
8 using System.Linq;
9 using System.Collections.Generic;
10 using Antmicro.Renode.Peripherals.Bus;
11 using Antmicro.Renode.Logging;
12 using Antmicro.Renode.Core;
13 
14 namespace Antmicro.Renode.Peripherals.I2C
15 {
16     public class MB85RC1MT : IGPIOReceiver
17     {
MB85RC1MT()18         public MB85RC1MT()
19         {
20             Reset();
21         }
22 
Reset()23         public void Reset()
24         {
25             address = 0x0;
26             transmissionPending = false;
27             writeProtected = false;
28         }
29 
OnGPIO(int number, bool value)30         public void OnGPIO(int number, bool value)
31         {
32             if(number == 0)
33             {
34                 writeProtected = value;
35             }
36             else
37             {
38                 this.Log(LogLevel.Warning, "Invalid gpio number {0}", number);
39             }
40         }
41 
Write(byte[] data, bool addr16)42         internal void Write(byte[] data, bool addr16)
43         {
44             this.Log(LogLevel.Noisy, "Write {0}", data.Select(x => x.ToString("X")).Aggregate((x, y) => x + " " + y));
45 
46             int writeDataIdx = 0;
47             if(!transmissionPending)
48             {
49                 transmissionPending = true;
50                 if(data.Length < 2)
51                 {
52                     this.Log(LogLevel.Warning, "Received message is too short");
53                     return;
54                 }
55                 address = (uint)((data[0] << 8) | data[1]);
56                 if(addr16)
57                 {
58                     address |= 1 << 16;
59                 }
60                 writeDataIdx = 2;
61             }
62             if(!writeProtected)
63             {
64                 for(int i = writeDataIdx; i < data.Length; i++)
65                 {
66                     memory[address] = data[i];
67                     IncreaseAddress();
68                 }
69             }
70             else
71             {
72                 this.Log(LogLevel.Warning, "Attempt to write to write protected module");
73             }
74         }
75 
Read(int count = 0)76         internal byte[] Read(int count = 0)
77         {
78             this.Log(LogLevel.Noisy, "Read {0}", count);
79 
80             byte[] buf = new byte[count];
81             for(int i = 0; i < count && address < memory.Length; i++)
82             {
83                 buf[i] = memory[address];
84                 IncreaseAddress();
85             }
86             return buf;
87         }
88 
FinishTransmission()89         internal void FinishTransmission()
90         {
91             transmissionPending = false;
92             //address is not reset, mb85rc1mt allows subsequent reads to use address of last transaction + 1
93         }
94 
IncreaseAddress()95         private void IncreaseAddress()
96         {
97             address = (uint)((address + 1) % memory.Length);
98         }
99 
100         private readonly byte[] memory = new byte[8 * 128 * 1 << 10];
101         private uint address;
102         private bool writeProtected;
103         private bool transmissionPending;
104     }
105 
106     public class MB85RC1MTI2CRelay : II2CPeripheral
107     {
MB85RC1MTI2CRelay(MB85RC1MT mb85rc1mt, bool addr16)108         public MB85RC1MTI2CRelay(MB85RC1MT mb85rc1mt, bool addr16)
109         {
110             this.mb85rc1mt = mb85rc1mt;
111             this.addr16 = addr16;
112         }
113 
Reset()114         public void Reset()
115         {
116         }
117 
Write(byte[] data)118         public void Write(byte[] data)
119         {
120             mb85rc1mt.Write(data, addr16);
121         }
122 
Read(int count = 0)123         public byte[] Read(int count = 0)
124         {
125             return mb85rc1mt.Read(count);
126         }
127 
FinishTransmission()128         public void FinishTransmission()
129         {
130             mb85rc1mt.FinishTransmission();
131         }
132 
133         private readonly MB85RC1MT mb85rc1mt;
134         private readonly bool addr16;
135     }
136 
137     public class MB85RC1MTLo : MB85RC1MTI2CRelay
138     {
MB85RC1MTLo(MB85RC1MT mb85rc1mt)139         public MB85RC1MTLo(MB85RC1MT mb85rc1mt) : base(mb85rc1mt, false)
140         {
141         }
142     }
143 
144     public class MB85RC1MTHi : MB85RC1MTI2CRelay
145     {
MB85RC1MTHi(MB85RC1MT mb85rc1mt)146         public MB85RC1MTHi(MB85RC1MT mb85rc1mt) : base(mb85rc1mt, true)
147         {
148         }
149     }
150 }
151