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