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 8 using Antmicro.Renode.Core; 9 using Antmicro.Renode.Core.Structure; 10 using Antmicro.Renode.Core.Structure.Registers; 11 using Antmicro.Renode.Logging; 12 using Antmicro.Renode.Peripherals.Bus; 13 using Antmicro.Renode.Peripherals.Sensor; 14 15 namespace Antmicro.Renode.Peripherals.Sensors 16 { 17 public class PULP_uDMA_Camera: NullRegistrationPointPeripheralContainer<ICPIPeripheral>, IDoubleWordPeripheral, IKnownSize, IProvidesRegisterCollection<DoubleWordRegisterCollection> 18 { PULP_uDMA_Camera(IMachine machine)19 public PULP_uDMA_Camera(IMachine machine) : base(machine) 20 { 21 IRQ = new GPIO(); 22 sysbus = machine.GetSystemBus(this); 23 24 RegistersCollection = new DoubleWordRegisterCollection(this); 25 DefineRegisters(); 26 } 27 Reset()28 public override void Reset() 29 { 30 RegistersCollection.Reset(); 31 // there is no need to clear IRQ 32 // as we only blink with it 33 } 34 ReadDoubleWord(long offset)35 public uint ReadDoubleWord(long offset) 36 { 37 return RegistersCollection.Read(offset); 38 } 39 WriteDoubleWord(long offset, uint value)40 public void WriteDoubleWord(long offset, uint value) 41 { 42 RegistersCollection.Write(offset, value); 43 } 44 45 public DoubleWordRegisterCollection RegistersCollection { get; } 46 47 public GPIO IRQ { get; } 48 49 public long Size => 0x100; 50 DefineRegisters()51 private void DefineRegisters() 52 { 53 Registers.RxBufferBaseAddress.Define(this) 54 // this is not consistent with the documentation 55 // that states that only 16 bits are used for the address, 56 // but otherwise the sample fails 57 .WithValueField(0, 32, out rxBufferAddress, name: "RX_SADDR") 58 ; 59 60 Registers.RxBufferSize.Define(this) 61 .WithValueField(0, 17, out rxBufferSize, name: "RX_SIZE") 62 .WithReservedBits(17, 15) 63 ; 64 65 Registers.RxStreamConfiguration.Define(this) 66 .WithTag("CONTINOUS", 0, 1) 67 .WithTag("DATASIZE", 1, 2) 68 .WithReservedBits(3, 1) 69 .WithFlag(4, out rxStreamEnabled, name: "EN") 70 .WithTag("PENDING", 5, 1) 71 .WithTag("CLR", 6, 1) 72 .WithReservedBits(7, 25) 73 ; 74 75 Registers.GlobalConfiguration.Define(this) 76 .WithTag("FRAMEDROP_EN", 0, 1) 77 .WithTag("FRAMEDROP_VAL", 1, 6) 78 .WithTag("FRAMESLICE_EN", 7, 1) 79 .WithTag("FORMAT", 8, 3) 80 .WithTag("SHIFT", 11, 4) 81 .WithReservedBits(15, 16) 82 .WithFlag(31, FieldMode.Read | FieldMode.WriteOneToClear, name: "EN", writeCallback: (_, val) => 83 { 84 // write-one-to-clear means that this bit is automatically 85 // cleared after writing 86 87 if(!val) 88 { 89 return; 90 } 91 92 if(!rxStreamEnabled.Value) 93 { 94 this.Log(LogLevel.Warning, "Tried to enable the controller, but RX DMA stream is not enabled. Dropping it"); 95 return; 96 } 97 98 if(RegisteredPeripheral == null) 99 { 100 this.Log(LogLevel.Warning, "Tried to enable the controller, but there is no device connected"); 101 return; 102 } 103 104 var data = RegisteredPeripheral.ReadFrame(); 105 106 if(data.Length != (int)rxBufferSize.Value) 107 { 108 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); 109 } 110 111 sysbus.WriteBytes(data, rxBufferAddress.Value); 112 rxStreamEnabled.Value = false; 113 IRQ.Blink(); 114 }) 115 ; 116 117 Registers.LowerLeftCornerConfiguration.Define(this) 118 .WithTag("FRAMESLICE_LLX", 0, 16) 119 .WithTag("FRAMESLICE_LLY", 16, 16) 120 ; 121 122 Registers.UpperRightCornderConfiguration.Define(this) 123 .WithTag("FRAMESLICE_URX", 0, 16) 124 .WithTag("FRAMESLICE_URY", 16, 16) 125 ; 126 127 Registers.HorizontalResolutionConfiguration.Define(this) 128 .WithReservedBits(0, 16) 129 .WithTag("ROWLEN", 16, 16) 130 ; 131 132 Registers.RGBCoefficientsConfiguration.Define(this) 133 .WithTag("B_COEFF", 0, 8) 134 .WithTag("G_COEFF", 8, 8) 135 .WithTag("R_COEFF", 16, 8) 136 .WithReservedBits(24, 8) 137 ; 138 139 Registers.VSYNCPolarity.Define(this) 140 .WithTag("VSYNC_POLARITY", 0, 1) 141 .WithReservedBits(1, 31) 142 ; 143 } 144 145 private IValueRegisterField rxBufferAddress; 146 private IValueRegisterField rxBufferSize; 147 private IFlagRegisterField rxStreamEnabled; 148 149 private readonly IBusController sysbus; 150 151 private enum Registers 152 { 153 RxBufferBaseAddress = 0x0, 154 RxBufferSize = 0x4, 155 RxStreamConfiguration = 0x8, 156 157 GlobalConfiguration = 0x20, 158 LowerLeftCornerConfiguration = 0x24, 159 UpperRightCornderConfiguration = 0x28, 160 HorizontalResolutionConfiguration = 0x2C, 161 RGBCoefficientsConfiguration = 0x30, 162 VSYNCPolarity = 0x34 163 } 164 } 165 } 166