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