1 // 2 // Copyright (c) 2010-2020 Antmicro 3 // Copyright (c) 2020 Hugh Breslin <Hugh.Breslin@microchip.com> 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 using System; 9 using System.Collections.Generic; 10 using Antmicro.Renode.Core; 11 using Antmicro.Renode.Core.Structure.Registers; 12 using Antmicro.Renode.Logging; 13 using Antmicro.Renode.Peripherals.I2C; 14 15 namespace Antmicro.Renode.Peripherals.Sensors 16 { 17 public class PAC1934 : II2CPeripheral 18 { PAC1934()19 public PAC1934() 20 { 21 channels = new Channel[ChannelCount]; 22 for(var i = 0; i < ChannelCount; ++i) 23 { 24 channels[i] = new Channel(this, i); 25 } 26 27 var registersMap = new Dictionary<long, ByteRegister>(); 28 registersMap.Add( 29 (long)Registers.ChannelDisable, 30 new ByteRegister(this) 31 .WithReservedBits(0, 1) 32 .WithFlag(1, out skipInactiveChannels, name: "NO_SKIP") 33 .WithTag("BYTE_COUNT", 2, 1) 34 .WithTag("TIMEOUT", 3, 1) 35 .WithFlag(4, out channels[3].IsChannelDisabled, name: "CH4") 36 .WithFlag(5, out channels[2].IsChannelDisabled, name: "CH3") 37 .WithFlag(6, out channels[1].IsChannelDisabled, name: "CH2") 38 .WithFlag(7, out channels[0].IsChannelDisabled, name: "CH1") 39 ); 40 registersMap.Add( 41 (long)Registers.ProductId, 42 new ByteRegister(this) 43 .WithValueField(0, 8, FieldMode.Read, valueProviderCallback: (_) => ProductId) 44 ); 45 registersMap.Add( 46 (long)Registers.ManufacturerId, 47 new ByteRegister(this) 48 .WithValueField(0, 8, FieldMode.Read, valueProviderCallback: (_) => ManufacturerId) 49 ); 50 registersMap.Add( 51 (long)Registers.RevisionId, 52 new ByteRegister(this) 53 .WithValueField(0, 8, FieldMode.Read, valueProviderCallback: (_) => RevisionId) 54 ); 55 56 registers = new ByteRegisterCollection(this, registersMap); 57 } 58 FinishTransmission()59 public void FinishTransmission() 60 { 61 } 62 Read(int count = 1)63 public byte[] Read(int count = 1) 64 { 65 // we do not use `count` due to block read operations 66 if(state == State.NoRegisterContext) 67 { 68 this.Log(LogLevel.Warning, "Trying to read but no register is selected"); 69 return new byte[] { 0 }; 70 } 71 return ReadRegister((uint)context); 72 } 73 Write(byte[] data)74 public void Write(byte[] data) 75 { 76 // TODO: implement the auto-incrementing pointer described in the docs 77 if(state == State.NoRegisterContext) 78 { 79 context = (Registers)data[0]; 80 state = GetStateBasedOnContext(context); 81 if(state != State.RefreshContext) 82 { 83 return; 84 } 85 } 86 WriteRegister(context, data[0]); 87 } 88 Reset()89 public void Reset() 90 { 91 accumulatorCount = 0; 92 state = default(State); 93 context = default(Registers); 94 for(var i = 0; i < ChannelCount; ++i) 95 { 96 channels[i].Reset(); 97 } 98 registers.Reset(); 99 } 100 WriteRegister(Registers register, byte data)101 private void WriteRegister(Registers register, byte data) 102 { 103 switch(register) 104 { 105 case Registers.Refresh: 106 case Registers.RefreshG: 107 RefreshChannels(RefreshType.WithAccumulators); 108 break; 109 case Registers.RefreshV: 110 RefreshChannels(RefreshType.NoAccumulators); 111 break; 112 default: 113 registers.Write((long)register, data); 114 break; 115 } 116 state = State.NoRegisterContext; 117 } 118 ReadRegister(uint offset)119 private byte[] ReadRegister(uint offset) 120 { 121 state = State.NoRegisterContext; 122 if(offset >= (uint)Registers.ProportionalPowerAccumulator1 && offset <= (uint)Registers.ProportionalPower4) 123 { 124 var channelNumber = (offset - 3) % 4; 125 return channels[channelNumber].GetBytesFromChannelOffset(offset - channelNumber); 126 } 127 if(offset == (uint)Registers.AccumulatorCount) 128 { 129 return BitConverter.GetBytes(accumulatorCount); 130 } 131 return BitConverter.GetBytes((ushort)registers.Read(offset)); 132 } 133 RefreshChannels(RefreshType refresh)134 private void RefreshChannels(RefreshType refresh) 135 { 136 for(int i = 0; i < ChannelCount; ++i) 137 { 138 if(channels[i].IsChannelDisabled.Value && !skipInactiveChannels.Value) 139 { 140 channels[i].RefreshInactiveChannel(refresh); 141 } 142 else if(!channels[i].IsChannelDisabled.Value) 143 { 144 channels[i].RefreshActiveChannel(refresh); 145 accumulatorCount += (refresh == RefreshType.WithAccumulators ? 1u : 0); 146 } 147 } 148 } 149 GetStateBasedOnContext(Registers data)150 private State GetStateBasedOnContext(Registers data) 151 { 152 if(data == Registers.Refresh || data == Registers.RefreshG || data == Registers.RefreshV) 153 { 154 return State.RefreshContext; 155 } 156 return State.RegisterContextSet; 157 } 158 159 private State state; 160 private Registers context; 161 private uint accumulatorCount; 162 163 private readonly Channel[] channels; 164 private readonly ByteRegisterCollection registers; 165 166 private readonly IFlagRegisterField skipInactiveChannels; 167 168 private const int ProductId = 0x5B; 169 private const int ManufacturerId = 0x5D; 170 private const int RevisionId = 0x3; 171 172 private const int ChannelCount = 4; 173 private const int ShiftBetweenChannelRegisters = 4; 174 175 private class Channel 176 { Channel(PAC1934 parent, int number)177 public Channel(PAC1934 parent, int number) 178 { 179 this.parent = parent; 180 channelNumber = number; 181 vBusQueue = new Queue<ushort>(); 182 vSenseQueue = new Queue<ushort>(); 183 } 184 GetBytesFromChannelOffset(long offset)185 public byte[] GetBytesFromChannelOffset(long offset) 186 { 187 switch(offset) 188 { 189 case (long)Registers.ProportionalPowerAccumulator1: 190 return BitConverter.GetBytes(proportionalPowerAccumulator); 191 case (long)Registers.BusVoltage1: 192 return BitConverter.GetBytes(busVoltage); 193 case (long)Registers.SenseResistorVoltage1: 194 return BitConverter.GetBytes(senseResistorVoltage); 195 case (long)Registers.AverageBusVoltage1: 196 return BitConverter.GetBytes(averageBusVoltage); 197 case (long)Registers.SenseResistorAverageVoltage1: 198 return BitConverter.GetBytes(senseResistorAverageVoltage); 199 case (long)Registers.ProportionalPower1: 200 return BitConverter.GetBytes(proportionalPower); 201 default: 202 parent.Log(LogLevel.Warning, "Trying to read bytes from unhandled channel {0} at offset 0x{1:X}", channelNumber, offset); 203 return new byte[] { 0 }; 204 } 205 } 206 Reset()207 public void Reset() 208 { 209 busVoltage = 0; 210 proportionalPower = 0; 211 averageBusVoltage = 0; 212 senseResistorVoltage = 0; 213 senseResistorAverageVoltage = 0; 214 proportionalPowerAccumulator = 0; 215 } 216 RefreshActiveChannel(RefreshType refresh)217 public void RefreshActiveChannel(RefreshType refresh) 218 { 219 // populate the registers with dummy data 220 var randomizer = EmulationManager.Instance.CurrentEmulation.RandomGenerator; 221 222 proportionalPower = SampleBusVoltage * SampleSenseResistorVoltage; 223 if(refresh == RefreshType.WithAccumulators) 224 { 225 proportionalPowerAccumulator += proportionalPower; 226 } 227 busVoltage = (ushort)(SampleBusVoltage + randomizer.Next(-20, 20)); 228 senseResistorVoltage = (ushort)(SampleSenseResistorVoltage + randomizer.Next(-20, 20)); 229 averageBusVoltage = GetAverage(vBusQueue, busVoltage); 230 senseResistorAverageVoltage = GetAverage(vSenseQueue, senseResistorVoltage); 231 } 232 RefreshInactiveChannel(RefreshType refresh)233 public void RefreshInactiveChannel(RefreshType refresh) 234 { 235 if(refresh == RefreshType.WithAccumulators) 236 { 237 proportionalPowerAccumulator = 0xFFFFFFFFFFFF; 238 } 239 busVoltage = 0xFFFF; 240 senseResistorVoltage = 0xFFFF; 241 averageBusVoltage = 0xFFFF; 242 senseResistorAverageVoltage = 0xFFFF; 243 proportionalPower = 0xFFFFFFF; 244 } 245 246 public IFlagRegisterField IsChannelDisabled; 247 GetAverage(Queue<ushort> queue, ushort value)248 private ushort GetAverage(Queue<ushort> queue, ushort value) 249 { 250 var result = 0u; 251 if(queue.Count == 8) 252 { 253 queue.Dequeue(); 254 } 255 queue.Enqueue(value); 256 foreach(var val in queue) 257 { 258 result += val; 259 } 260 return (ushort)(result / queue.Count); 261 } 262 263 private readonly Queue<ushort> vSenseQueue; 264 private readonly Queue<ushort> vBusQueue; 265 private readonly int channelNumber; 266 private readonly PAC1934 parent; 267 private ulong proportionalPowerAccumulator; 268 private ushort busVoltage; 269 private ushort senseResistorVoltage; 270 private ushort averageBusVoltage; 271 private ushort senseResistorAverageVoltage; 272 private uint proportionalPower; 273 274 private const ushort SampleBusVoltage = 3500; 275 private const ushort SampleSenseResistorVoltage = 3500; 276 } 277 278 private enum Registers : byte 279 { 280 // General Registers 281 Refresh = 0x00, 282 Control = 0x1, 283 AccumulatorCount = 0x2, 284 285 // Channel Registers 286 ProportionalPowerAccumulator1 = 0x3, 287 ProportionalPowerAccumulator2 = 0x4, 288 ProportionalPowerAccumulator3 = 0x5, 289 ProportionalPowerAccumulator4 = 0x6, 290 BusVoltage1 = 0x7, 291 BusVoltage2 = 0x8, 292 BusVoltage3 = 0x9, 293 BusVoltage4 = 0xA, 294 SenseResistorVoltage1 = 0xB, 295 SenseResistorVoltage2 = 0xC, 296 SenseResistorVoltage3 = 0xD, 297 SenseResistorVoltage4 = 0xE, 298 AverageBusVoltage1 = 0xF, 299 AverageBusVoltage2 = 0x10, 300 AverageBusVoltage3 = 0x11, 301 AverageBusVoltage4 = 0x12, 302 SenseResistorAverageVoltage1 = 0x13, 303 SenseResistorAverageVoltage2 = 0x14, 304 SenseResistorAverageVoltage3 = 0x15, 305 SenseResistorAverageVoltage4 = 0x16, 306 ProportionalPower1 = 0x17, 307 ProportionalPower2 = 0x18, 308 ProportionalPower3 = 0x19, 309 ProportionalPower4 = 0x1A, 310 311 // General Registers 312 ChannelDisable = 0x1C, 313 BidirectionalCurrentMeasurement = 0x1D, 314 RefreshG = 0x1E, 315 RefreshV = 0x1F, 316 SlowMode = 0x20, 317 ControlImage = 0x21, 318 ChannelDisableImage = 0x22, 319 BidirectionalCurrentMeasurementImage = 0x23, 320 ControlPreviousImage = 0x24, 321 ChannelDisablePreviousImage = 0x25, 322 BidirectionalCurrentMeasurementPreviousImage = 0x26, 323 ProductId = 0xFD, 324 ManufacturerId = 0xFE, 325 RevisionId = 0xFF 326 } 327 328 private enum State : byte 329 { 330 NoRegisterContext = 0, 331 RegisterContextSet = 1, 332 RefreshContext = 2 333 } 334 335 private enum RefreshType : byte 336 { 337 NoAccumulators = 0, 338 WithAccumulators = 1 339 } 340 } 341 } 342