| // | |
| // Copyright (c) 2022 Google LLC | |
| // | |
| // This file is licensed under the MIT License. | |
| // Full license text is available in 'licenses/MIT.txt'. | |
| // | |
| using Antmicro.Renode.Core; | |
| using Antmicro.Renode.Core.Structure; | |
| using Antmicro.Renode.Core.Structure.Registers; | |
| using Antmicro.Renode.Logging; | |
| using Antmicro.Renode.Peripherals.Bus; | |
| using Antmicro.Renode.Peripherals.Sensor; | |
| namespace Antmicro.Renode.Peripherals.Sensors | |
| { | |
| public class DoubleBufferDMA: NullRegistrationPointPeripheralContainer<ICPIPeripheral>, IDoubleWordPeripheral, IKnownSize, IProvidesRegisterCollection<DoubleWordRegisterCollection>, IGPIOReceiver | |
| { | |
| public DoubleBufferDMA(Machine machine) : base(machine) | |
| { | |
| IRQ = new GPIO(); | |
| Trigger = new GPIO(); | |
| RegistersCollection = new DoubleWordRegisterCollection(this); | |
| DefineRegisters(); | |
| } | |
| public override void Reset() | |
| { | |
| IRQ.Unset(); | |
| Trigger.Unset(); | |
| RegistersCollection.Reset(); | |
| } | |
| public uint ReadDoubleWord(long offset) | |
| { | |
| return RegistersCollection.Read(offset); | |
| } | |
| public void WriteDoubleWord(long offset, uint value) | |
| { | |
| RegistersCollection.Write(offset, value); | |
| } | |
| public void OnGPIO(int number, bool value) { | |
| if (!value) { | |
| return; | |
| } | |
| if(RegisteredPeripheral == null) | |
| { | |
| this.Log(LogLevel.Warning, "Tried to enable the controller, but there is no device connected"); | |
| return; | |
| } | |
| var data = RegisteredPeripheral.ReadFrame(); | |
| if(data.Length != rxBufferSize.Value) | |
| { | |
| this.Log(LogLevel.Warning, "Received {0} bytes from the device, but RX DMA stream is configured for {1} bytes. This might indicate problems in the driver", data.Length, rxBufferSize.Value); | |
| } | |
| Machine.SystemBus.WriteBytes(data, rxBuffer1Address.Value); | |
| // TODO(jesionowski): re-enable double buffer once sw supports it | |
| // if(use_buffer1) { | |
| // Machine.SystemBus.WriteBytes(data, rxBuffer1Address.Value); | |
| // } else { | |
| // Machine.SystemBus.WriteBytes(data, rxBuffer2Address.Value); | |
| // } | |
| use_buffer1 = !use_buffer1; | |
| IRQ.Blink(); | |
| } | |
| public DoubleWordRegisterCollection RegistersCollection { get; } | |
| public GPIO Trigger { get; } | |
| public GPIO IRQ { get; } | |
| public long Size => 0x100; | |
| private void DefineRegisters() | |
| { | |
| Registers.RxBufferSize.Define(this) | |
| .WithValueField(0, 32, out rxBufferSize, name: "RX_SIZE") | |
| ; | |
| Registers.RxBufferBaseAddress1.Define(this) | |
| .WithValueField(0, 32, out rxBuffer1Address, name: "ADDR1") | |
| ; | |
| Registers.RxBufferBaseAddress2.Define(this) | |
| .WithValueField(0, 32, out rxBuffer2Address, name: "ADDR2") | |
| ; | |
| Registers.Configuration.Define(this) | |
| .WithReservedBits(0, 32) | |
| ; | |
| } | |
| private bool use_buffer1 = true; | |
| private IValueRegisterField rxBuffer1Address; | |
| private IValueRegisterField rxBuffer2Address; | |
| private IValueRegisterField rxBufferSize; | |
| private enum Registers | |
| { | |
| Configuration = 0x0, | |
| RxBufferSize = 0x4, | |
| RxBufferBaseAddress1 = 0x8, | |
| RxBufferBaseAddress2 = 0xc, | |
| } | |
| } | |
| } |