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 System.Linq; 9 using Antmicro.Renode.Backends.Display; 10 using Antmicro.Renode.Core; 11 using Antmicro.Renode.Core.Structure.Registers; 12 using Antmicro.Renode.Logging; 13 using Antmicro.Renode.Peripherals.Bus; 14 15 namespace Antmicro.Renode.Peripherals.Video 16 { 17 public class LiteX_Framebuffer_CSR32 : AutoRepaintingVideo, IBusPeripheral 18 { LiteX_Framebuffer_CSR32(IMachine machine, PixelFormat format, IBusPeripheral memory, uint offset = 0, ushort hres = 0, ushort vres = 0)19 public LiteX_Framebuffer_CSR32(IMachine machine, PixelFormat format, IBusPeripheral memory, uint offset = 0, ushort hres = 0, ushort vres = 0) : base(machine) 20 { 21 this.memory = memory; 22 this.resetOffset = offset; 23 this.resetHres = hres; 24 this.resetVres = vres; 25 sysbus = machine.GetSystemBus(this); 26 this.format = format; 27 28 DefineDMARegisters(); 29 DefineVTGRegisters(); 30 } 31 32 [ConnectionRegion("dma")] WriteDoubleWordToDMA(long address, uint value)33 public void WriteDoubleWordToDMA(long address, uint value) 34 { 35 dmaRegisters.Write(address, value); 36 } 37 38 [ConnectionRegion("dma")] ReadDoubleWordFromDMA(long offset)39 public uint ReadDoubleWordFromDMA(long offset) 40 { 41 return dmaRegisters.Read(offset); 42 } 43 44 [ConnectionRegion("vtg")] WriteDoubleWordToVTG(long address, uint value)45 public void WriteDoubleWordToVTG(long address, uint value) 46 { 47 vtgRegisters.Write(address, value); 48 } 49 50 [ConnectionRegion("vtg")] ReadDoubleWordFromVTG(long offset)51 public uint ReadDoubleWordFromVTG(long offset) 52 { 53 return vtgRegisters.Read(offset); 54 } 55 Reset()56 public override void Reset() 57 { 58 dmaRegisters.Reset(); 59 vtgRegisters.Reset(); 60 bufferAddress = 0; 61 } 62 Repaint()63 protected override void Repaint() 64 { 65 sysbus.ReadBytes(bufferAddress, buffer.Length, buffer, 0); 66 } 67 DefineDMARegisters()68 private void DefineDMARegisters() 69 { 70 dmaRegisters = new DoubleWordRegisterCollection(this); 71 72 DMARegisters.Base.Define(dmaRegisters, resetOffset) 73 .WithValueField(0, 32, out bufferRegister, name: "base"); 74 75 DMARegisters.Enable.Define(dmaRegisters) 76 .WithFlag(0, writeCallback: (_, val) => 77 { 78 if(val) 79 { 80 var height = (int)vres.Value; 81 var width = (int)hres.Value; 82 bufferAddress = (uint)bufferRegister.Value; 83 84 var memoryBase = (uint)sysbus.GetRegistrationPoints(memory).First().Range.StartAddress; 85 bufferAddress += memoryBase; 86 87 this.Log(LogLevel.Debug, "Reconfiguring screen to {0}x{1}", width, height); 88 89 Reconfigure(width, height, format); 90 } 91 else 92 { 93 // it stops the repainter by passing nulls 94 Reconfigure(); 95 } 96 }); 97 } 98 DefineVTGRegisters()99 private void DefineVTGRegisters() 100 { 101 vtgRegisters = new DoubleWordRegisterCollection(this); 102 103 VTGRegisters.Hres.Define(vtgRegisters, resetHres) 104 .WithValueField(0, 16, out hres, name: "h_res").WithReservedBits(16, 16); 105 106 VTGRegisters.Vres.Define(vtgRegisters, resetVres) 107 .WithValueField(0, 16, out vres, name: "v_res").WithReservedBits(16, 16); 108 } 109 110 private DoubleWordRegisterCollection dmaRegisters; 111 private DoubleWordRegisterCollection vtgRegisters; 112 113 private IValueRegisterField vres; 114 private IValueRegisterField hres; 115 private IValueRegisterField bufferRegister; 116 117 private uint bufferAddress; 118 119 private readonly IBusPeripheral memory; 120 private readonly IBusController sysbus; 121 private readonly PixelFormat format; 122 private readonly uint resetOffset; 123 private readonly uint resetHres; 124 private readonly uint resetVres; 125 126 private enum DMARegisters 127 { 128 Base = 0x0, 129 Length = 0x4, 130 Enable = 0x8, 131 } 132 133 private enum VTGRegisters 134 { 135 Enable = 0x0, 136 Hres = 0x4, 137 HsyncStart = 0x8, 138 HsyncEnd = 0xc, 139 Hscan = 0x10, 140 Vres = 0x14, 141 VsyncStart = 0x18, 142 VsyncEnd = 0x1c, 143 Vscan = 0x20, 144 } 145 } 146 } 147