| // |
| // 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, |
| } |
| } |
| } |