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 using System; 8 using Antmicro.Renode.Logging; 9 10 namespace Antmicro.Renode.Utilities 11 { 12 public class BitBangHelper 13 { BitBangHelper(int width, bool outputMsbFirst = false, IEmulationElement loggingParent = null)14 public BitBangHelper(int width, bool outputMsbFirst = false, IEmulationElement loggingParent = null) 15 { 16 outputDecoder = new Decoder(width, outputMsbFirst, loggingParent); 17 inputEncoder = new Encoder(width, loggingParent); 18 19 this.loggingParent = loggingParent; 20 Reset(); 21 } 22 ResetOutput()23 public void ResetOutput() 24 { 25 outputDecoder.Reset(); 26 } 27 Update(uint encodedSignals, int dataBit, int clockBit, bool dataEnabled = true)28 public bool Update(uint encodedSignals, int dataBit, int clockBit, bool dataEnabled = true) 29 { 30 var clockSignal = (encodedSignals & (1 << clockBit)) != 0; 31 var dataSignal = (encodedSignals & (1 << dataBit)) != 0; 32 33 return Update(clockSignal, dataSignal, dataEnabled); 34 } 35 Update(bool clockSignal, bool dataSignal, bool dataEnabled = true)36 public bool Update(bool clockSignal, bool dataSignal, bool dataEnabled = true) 37 { 38 var result = false; 39 // clock rising 40 var tickDetected = (clockSignal && !previousClockSignal); 41 if(tickDetected) 42 { 43 loggingParent?.Log(LogLevel.Noisy, "Tick detected"); 44 45 inputEncoder.Tick(); 46 if(dataEnabled) 47 { 48 result = outputDecoder.Tick(dataSignal); 49 } 50 } 51 52 previousClockSignal = clockSignal; 53 return result; 54 } 55 SetInputBuffer(uint data)56 public void SetInputBuffer(uint data) 57 { 58 inputEncoder.Encode(data); 59 } 60 Reset()61 public void Reset() 62 { 63 inputEncoder.Reset(); 64 outputDecoder.Reset(); 65 66 previousClockSignal = false; 67 } 68 69 public uint DecodedOutput => outputDecoder.DecodedData; 70 71 public bool EncodedInput => inputEncoder.CurrentBit; 72 73 private bool previousClockSignal; 74 75 private readonly Decoder outputDecoder; 76 private readonly Encoder inputEncoder; 77 private readonly IEmulationElement loggingParent; 78 79 public class Encoder 80 { Encoder(int width, IEmulationElement loggingParent = null)81 public Encoder(int width, IEmulationElement loggingParent = null) 82 { 83 this.loggingParent = loggingParent; 84 buffer = new bool[width]; 85 Reset(); 86 } 87 Tick()88 public void Tick() 89 { 90 if(bufferPosition >= 0) 91 { 92 bufferPosition--; 93 } 94 } 95 Encode(uint data)96 public void Encode(uint data) 97 { 98 var dataBits = BitHelper.GetBits(data); 99 Array.Copy(dataBits, 0, buffer, 0, buffer.Length); 100 bufferPosition = buffer.Length; 101 } 102 Reset()103 public void Reset() 104 { 105 bufferPosition = -1; 106 } 107 108 public bool CurrentBit 109 { 110 get 111 { 112 if(bufferPosition < 0 || bufferPosition >= buffer.Length) 113 { 114 loggingParent?.Log(LogLevel.Warning, "Trying to read bit, but the buffer is empty"); 115 return false; 116 } 117 118 return buffer[bufferPosition]; 119 } 120 } 121 122 private int bufferPosition; 123 124 private readonly bool[] buffer; 125 private readonly IEmulationElement loggingParent; 126 } 127 128 public class Decoder 129 { Decoder(int width, bool msbFirst = false, IEmulationElement loggingParent = null)130 public Decoder(int width, bool msbFirst = false, IEmulationElement loggingParent = null) 131 { 132 this.loggingParent = loggingParent; 133 this.msbFirst = msbFirst; 134 buffer = new bool[width]; 135 136 Reset(); 137 } 138 Tick(bool dataSignal)139 public bool Tick(bool dataSignal) 140 { 141 loggingParent?.Log(LogLevel.Noisy, "Latching bit #{0}, value: {1}", bufferPosition, dataSignal); 142 143 buffer[bufferPosition] = dataSignal; 144 bufferPosition += msbFirst 145 ? -1 146 : 1; 147 148 if(bufferPosition == buffer.Length || bufferPosition == -1) 149 { 150 ResetBuffer(); 151 DecodedData = BitHelper.GetValueFromBitsArray(buffer); 152 return true; 153 } 154 155 return false; 156 } 157 Reset()158 public void Reset() 159 { 160 ResetBuffer(); 161 DecodedData = 0; 162 } 163 164 public uint DecodedData { get; private set; } 165 ResetBuffer()166 private void ResetBuffer() 167 { 168 bufferPosition = msbFirst 169 ? buffer.Length - 1 170 : 0; 171 } 172 173 private int bufferPosition; 174 175 private readonly bool[] buffer; 176 private readonly bool msbFirst; 177 private readonly IEmulationElement loggingParent; 178 } 179 } 180 } 181