1
0
mirror of https://github.com/livingcomputermuseum/ContrAlto.git synced 2026-01-16 16:19:33 +00:00

Fixed display microcode and display controller. Alto display now generated 100% by microcode tasks. A few small optimizations.

This commit is contained in:
Josh Dersch 2015-11-16 16:46:24 -08:00
parent 30ecfa6900
commit 03661fc90b
11 changed files with 138 additions and 126 deletions

View File

@ -25,7 +25,7 @@ namespace Contralto
_keyboard = new Keyboard();
_diskController = new DiskController(this);
_displayController = new DisplayController(this);
_fakeDisplayController = new FakeDisplayController(this);
//_fakeDisplayController = new FakeDisplayController(this);
// Attach memory-mapped devices to the bus
_memBus.AddDevice(_mem);
@ -36,7 +36,7 @@ namespace Contralto
_clockableDevices.Add(_memBus);
_clockableDevices.Add(_diskController);
_clockableDevices.Add(_displayController);
_clockableDevices.Add(_fakeDisplayController);
//_clockableDevices.Add(_fakeDisplayController);
_clockableDevices.Add(_cpu);
Reset();
@ -62,13 +62,14 @@ namespace Contralto
public void AttachDisplay(Debugger d)
{
_displayController.AttachDisplay(d);
_fakeDisplayController.AttachDisplay(d);
// _fakeDisplayController.AttachDisplay(d);
}
public void SingleStep()
{
// Run every device that needs attention for a single clock cycle.
for (int i = 0; i < _clockableDevices.Count; i++)
int count = _clockableDevices.Count;
for (int i = 0; i < count; i++)
{
_clockableDevices[i].Clock();
}

View File

@ -31,27 +31,14 @@ namespace Contralto.CPU
_tasks[(int)TaskType.Emulator] = new EmulatorTask(this);
_tasks[(int)TaskType.DiskSector] = new DiskTask(this, true);
_tasks[(int)TaskType.DiskWord] = new DiskTask(this, false);
//_tasks[(int)TaskType.DisplayWord] = new DisplayWordTask(this);
//_tasks[(int)TaskType.DisplayHorizontal] = new DisplayHorizontalTask(this);
_tasks[(int)TaskType.DisplayWord] = new DisplayWordTask(this);
_tasks[(int)TaskType.DisplayHorizontal] = new DisplayHorizontalTask(this);
_tasks[(int)TaskType.DisplayVertical] = new DisplayVerticalTask(this);
_tasks[(int)TaskType.Cursor] = new CursorTask(this);
_tasks[(int)TaskType.MemoryRefresh] = new MemoryRefreshTask(this);
Reset();
}
public void Hack()
{
_tasks[(int)TaskType.DisplayWord] = new DisplayWordTask(this);
//_tasks[(int)TaskType.DisplayHorizontal] = new DisplayHorizontalTask(this);
//_tasks[(int)TaskType.DisplayVertical] = new DisplayVerticalTask(this);
//_tasks[(int)TaskType.Cursor] = new CursorTask(this);
_tasks[(int)TaskType.DisplayWord].Reset();
//_tasks[(int)TaskType.DisplayHorizontal].Reset();
//_tasks[(int)TaskType.DisplayVertical].Reset();
//_tasks[(int)TaskType.Cursor].Reset();
}
}
public Task[] Tasks
{

View File

@ -17,8 +17,16 @@ namespace Contralto.CPU
{
_taskType = TaskType.DisplayHorizontal;
_wakeup = false;
}
}
protected override bool ExecuteInstruction(MicroInstruction instruction)
{
// We put ourselves back to sleep immediately once we've started running
_wakeup = false;
return base.ExecuteInstruction(instruction);
}
protected override void ExecuteSpecialFunction2(MicroInstruction instruction)
{
DisplayHorizontalF2 dh2 = (DisplayHorizontalF2)instruction.F2;

View File

@ -18,7 +18,15 @@ namespace Contralto.CPU
{
_taskType = TaskType.DisplayWord;
_wakeup = false;
}
}
protected override bool ExecuteInstruction(MicroInstruction instruction)
{
// We put ourselves back to sleep immediately once we've started running
_wakeup = false;
return base.ExecuteInstruction(instruction);
}
protected override void ExecuteSpecialFunction2(MicroInstruction instruction)
{

View File

@ -110,7 +110,6 @@
this.NovaStep = new System.Windows.Forms.Button();
this.groupBox6 = new System.Windows.Forms.GroupBox();
this.DisplayBox = new System.Windows.Forms.PictureBox();
this.button1 = new System.Windows.Forms.Button();
this.Microcode.SuspendLayout();
this.SourceTabs.SuspendLayout();
this.Rom0Page.SuspendLayout();
@ -960,23 +959,11 @@
this.DisplayBox.TabStop = false;
this.DisplayBox.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(this.DisplayBox_PreviewKeyDown);
//
// button1
//
this.button1.Location = new System.Drawing.Point(799, 873);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 1;
this.button1.TabStop = false;
this.button1.Text = "HACK";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// Debugger
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(1376, 997);
this.Controls.Add(this.button1);
this.Controls.Add(this.groupBox6);
this.Controls.Add(this.NovaStep);
this.Controls.Add(this.RunToNextTaskButton);
@ -1071,7 +1058,6 @@
private System.Windows.Forms.DataGridViewTextBoxColumn Disassembly;
private System.Windows.Forms.GroupBox groupBox6;
private System.Windows.Forms.PictureBox DisplayBox;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.TabControl SourceTabs;
private System.Windows.Forms.TabPage Rom0Page;
private System.Windows.Forms.TabPage Rom1Page;

View File

@ -89,6 +89,8 @@ namespace Contralto
_displayBuffer.UnlockBits(data);
DisplayBox.Refresh();
Array.Clear(_displayData, 0, _displayData.Length);
}
/// <summary>
@ -833,7 +835,7 @@ namespace Contralto
break;
}
if (_execAbort || // The Stop button was hit
_microcodeBreakpointEnabled[_system.CPU.CurrentTask.MPC] || // A microcode breakpoint was hit
(execType == ExecutionType.NextTask &&
@ -855,7 +857,7 @@ namespace Contralto
_execAbort = false;
break;
}
}
}
}
@ -1031,12 +1033,6 @@ namespace Contralto
private Rectangle _displayRect = new Rectangle(0, 0, 608, 808);
// Keyboard mapping from windows vkeys to Alto keys
private Dictionary<Keys, AltoKey> _keyMap;
private void button1_Click(object sender, EventArgs e)
{
_system.CPU.Hack();
}
private Dictionary<Keys, AltoKey> _keyMap;
}
}

View File

@ -35,8 +35,16 @@ namespace Contralto.Display
_state = DisplayState.VerticalBlank;
_scanline = 0;
_word = 0;
_dwtBlocked = false;
_dwtBlocked = true;
_dhtBlocked = false;
_whiteOnBlack = false;
_lowRes = false;
// Wakeup DVT
_system.CPU.WakeupTask(TaskType.DisplayVertical);
_system.CPU.BlockTask(TaskType.DisplayHorizontal);
_system.CPU.BlockTask(TaskType.DisplayWord);
}
public void Clock()
@ -63,13 +71,16 @@ namespace Contralto.Display
//
// Check the BLOCK status of the DWT and DHT tasks for the last executed uInstruction.
//
_dhtBlocked = _system.CPU.CurrentTask.Priority == (int)CPU.TaskType.DisplayHorizontal &&
_system.CPU.CurrentTask.BLOCK;
if (_system.CPU.CurrentTask.Priority == (int)CPU.TaskType.DisplayHorizontal &&
_system.CPU.CurrentTask.BLOCK)
{
_dhtBlocked = true;
}
if (_system.CPU.CurrentTask.Priority == (int)CPU.TaskType.DisplayWord &&
_system.CPU.CurrentTask.BLOCK)
{
//Console.WriteLine("DWT BLOCK");
{
_dwtBlocked = true;
//
@ -88,23 +99,12 @@ namespace Contralto.Display
// "If the DWT has not executed a BLOCK, if DHT is not blocked, and if the
// buffer is not full, DWT wakeups are generated."
//
if (_dataBuffer.Count < 16 &&
!_system.CPU.IsBlocked(TaskType.DisplayHorizontal) &&
if (_dataBuffer.Count < 16 &&
!_dhtBlocked &&
!_dwtBlocked)
{
//Console.WriteLine("DWT wakeup, {0}", _dataBuffer.Count);
{
_system.CPU.WakeupTask(TaskType.DisplayWord);
}
else
{
// We can't take any words right now, remove Wakeup from
// the DWT.
if (_dataBuffer.Count >= 16)
{
//Log.Write(LogComponent.Display, "buffer full, blocking DWT.");
}
_system.CPU.BlockTask(TaskType.DisplayWord);
}
}
switch (_state)
{
@ -112,7 +112,7 @@ namespace Contralto.Display
// Just killing time
if (_clocks > _verticalBlankClocks)
{
// End of VBlank
// End of VBlank, start new visible frame
_clocks -= _verticalBlankClocks;
_scanline = _evenField ? 0 : 1;
_word = 0;
@ -121,12 +121,9 @@ namespace Contralto.Display
// Wake up DVT, DHT
_dwtBlocked = false;
_dhtBlocked = false;
_system.CPU.WakeupTask(TaskType.DisplayHorizontal);
_system.CPU.BlockTask(TaskType.DisplayWord);
_system.CPU.WakeupTask(TaskType.DisplayHorizontal);
_state = DisplayState.HorizontalBlank;
//Console.WriteLine("Frame");
_state = DisplayState.HorizontalBlank;
}
break;
@ -139,14 +136,14 @@ namespace Contralto.Display
{
_clocks -= _wordClocks;
ushort displayWord = 0xaaaa;
ushort displayWord = (ushort)(_whiteOnBlack ? 0 : 0xffff);
if (_dataBuffer.Count > 0)
{
// Dequeue a word and draw it to the screen
displayWord = _dataBuffer.Dequeue();
displayWord = _whiteOnBlack ? _dataBuffer.Dequeue() : (ushort)~_dataBuffer.Dequeue();
}
//_display.DrawDisplayWord(_scanline, _word, displayWord);
_display.DrawDisplayWord(_scanline, _word, displayWord);
_word++;
if (_word > 37)
@ -154,7 +151,7 @@ namespace Contralto.Display
// Done with this line
_dwtBlocked = false;
_dataBuffer.Clear();
_state = DisplayState.HorizontalBlank;
_state = DisplayState.HorizontalBlank;
}
}
break;
@ -170,7 +167,7 @@ namespace Contralto.Display
_word = 0;
if (_scanline > 807)
{
{
// Done with field, move to vblank, tell display to render
_state = DisplayState.VerticalBlank;
_evenField = !_evenField;
@ -178,13 +175,13 @@ namespace Contralto.Display
// Wakeup DVT
_system.CPU.WakeupTask(TaskType.DisplayVertical);
// Block DHT
// Block DHT, DWT
_system.CPU.BlockTask(TaskType.DisplayHorizontal);
_system.CPU.BlockTask(TaskType.DisplayWord);
//_display.RefreshAltoDisplay();
_display.RefreshAltoDisplay();
_frames++;
_fields++;
//Log.Write(LogComponent.Display, "Display field completed. {0} total clocks elapsed.", _totalClocks);
_totalClocks = 0;
}
@ -204,16 +201,22 @@ namespace Contralto.Display
{
_dataBuffer.Enqueue(word);
//Console.WriteLine("Enqueue {0}", _dataBuffer.Count);
//Console.WriteLine("Enqueue {0}, scanline {1}", word, _scanline);
// Sanity check: data length should never exceed 16 words.
if (_dataBuffer.Count > 16)
{
_dataBuffer.Dequeue();
_system.CPU.BlockTask(TaskType.DisplayWord);
{
//_dataBuffer.Dequeue();
//_system.CPU.BlockTask(TaskType.DisplayWord);
}
}
public void SETMODE(ushort word)
{
_lowRes = (word & 0x8000) != 0;
_whiteOnBlack = (word & 0x4000) != 0;
}
public bool EVENFIELD
{
get { return _evenField; }
@ -228,15 +231,17 @@ namespace Contralto.Display
}
private bool _evenField;
private bool _lowRes;
private bool _whiteOnBlack;
private double _clocks;
private double _totalClocks;
private int _frames;
private int _fields;
private DisplayState _state;
// Indicates whether the DWT or DHT blocked itself
// in which case they cannot be reawakened until the next field.
private bool _dwtBlocked;
private bool _dhtBlocked;
private bool _dhtBlocked;
private int _scanline;
private int _word;

View File

@ -98,7 +98,7 @@ namespace Contralto.Display
_display.DrawDisplayWord(scanline, wordOffset, (ushort)(dcb.whiteOnBlack ? 0x0 : 0xffff));
}
//_display.RefreshAltoDisplay();
_display.RefreshAltoDisplay();
// decrement scan line counter for this DCB, if < 0, grab next DCB.
dcb.scanlineCount--;

View File

@ -48,7 +48,7 @@ namespace Contralto.Logging
static Log()
{
// TODO: make configurable
_components = LogComponent.All;
_components = LogComponent.None;
_type = LogType.Normal | LogType.Warning | LogType.Error;
}

View File

@ -15,6 +15,14 @@ namespace Contralto.Memory
Reset();
}
/// <summary>
/// The top address of main memory (above which lies the I/O space)
/// </summary>
public static ushort MemTop
{
get { return _memTop; }
}
public void Reset()
{
// 4 64K banks
@ -33,13 +41,6 @@ namespace Contralto.Memory
{
address += 0x10000 * GetBankNumber(task, extendedMemory);
ushort data = _mem[address];
/*
if (extendedMemory)
{
Log.Write(LogComponent.Memory, "extended memory read from {0} - {1}", Conversion.ToOctal(address), Conversion.ToOctal(data));
} */
return data;
}
}
@ -58,18 +59,7 @@ namespace Contralto.Memory
else
{
address += 0x10000 * GetBankNumber(task, extendedMemory);
_mem[address] = data;
if (address == 0x110 && data != 0)
{
Console.WriteLine("DASTART WRITE!");
}
/*
if (extendedMemory)
{
Log.Write(LogComponent.Memory, "extended memory write to {0} of {1}", Conversion.ToOctal(address), Conversion.ToOctal(data));
} */
_mem[address] = data;
}
}
@ -85,12 +75,12 @@ namespace Contralto.Memory
private readonly MemoryRange[] _addresses =
{
new MemoryRange(0, _memTop), // Main bank of RAM to 176777; IO page above this.
new MemoryRange(_xmBanksStart, _xmBanksStart + 16), // Memory bank registers
new MemoryRange(0, _memTop), // Main bank of RAM to 176777; IO page above this.
new MemoryRange(_xmBanksStart, (ushort)(_xmBanksStart + 16)), // Memory bank registers
};
private const int _memTop = 0xfdff; // 176777
private const int _xmBanksStart = 0xffe0; // 177740
private static readonly ushort _memTop = 0xfdff; // 176777
private static readonly ushort _xmBanksStart = 0xffe0; // 177740
private ushort[] _mem;

View File

@ -42,6 +42,11 @@ namespace Contralto.Memory
else
{
_bus.Add(addr, dev);
if (dev is Memory)
{
_mainMemory = (Memory)dev;
}
}
}
}
@ -269,17 +274,27 @@ namespace Contralto.Memory
/// <returns></returns>
private ushort ReadFromBus(ushort address, TaskType task, bool extendedMemoryReference)
{
// Look up address in hash; if populated ask the device
// to return a value otherwise throw.
if (_bus.ContainsKey(address))
if (address <= Memory.MemTop)
{
return _bus[address].Read(address, task, extendedMemoryReference);
// Main memory access; shortcut hashtable lookup for performance reasons.
return _mainMemory.Read(address, task, extendedMemoryReference);
}
else
{
//throw new NotImplementedException(String.Format("Read from unimplemented memory-mapped I/O device at {0}.", OctalHelpers.ToOctal(address)));
//Console.WriteLine("Read from unimplemented memory-mapped I/O device at {0}.", Conversion.ToOctal(address));
return 0;
// Memory-mapped device access:
// Look up address in hash; if populated ask the device
// to return a value otherwise throw.
IMemoryMappedDevice memoryMappedDevice = null;
if (_bus.TryGetValue(address, out memoryMappedDevice))
{
return memoryMappedDevice.Read(address, task, extendedMemoryReference);
}
else
{
//throw new NotImplementedException(String.Format("Read from unimplemented memory-mapped I/O device at {0}.", OctalHelpers.ToOctal(address)));
//Console.WriteLine("Read from unimplemented memory-mapped I/O device at {0}.", Conversion.ToOctal(address));
return 0;
}
}
}
@ -291,16 +306,26 @@ namespace Contralto.Memory
/// <returns></returns>
private void WriteToBus(ushort address, ushort data, TaskType task, bool extendedMemoryReference)
{
// Look up address in hash; if populated ask the device
// to store a value otherwise throw.
if (_bus.ContainsKey(address))
{
_bus[address].Load(address, data, task, extendedMemoryReference);
if (address <= Memory.MemTop)
{
// Main memory access; shortcut hashtable lookup for performance reasons.
_mainMemory.Load(address, data, task, extendedMemoryReference);
}
else
{
// throw new NotImplementedException(String.Format("Write to unimplemented memory-mapped I/O device at {0}.", OctalHelpers.ToOctal(address)));
//Console.WriteLine("Write to unimplemented memory-mapped I/O device at {0}.", Conversion.ToOctal(address));
// Memory-mapped device access:
// Look up address in hash; if populated ask the device
// to store a value otherwise throw.
IMemoryMappedDevice memoryMappedDevice = null;
if (_bus.TryGetValue(address, out memoryMappedDevice))
{
memoryMappedDevice.Load(address, data, task, extendedMemoryReference);
}
else
{
// throw new NotImplementedException(String.Format("Write to unimplemented memory-mapped I/O device at {0}.", OctalHelpers.ToOctal(address)));
//Console.WriteLine("Write to unimplemented memory-mapped I/O device at {0}.", Conversion.ToOctal(address));
}
}
}
@ -308,7 +333,13 @@ namespace Contralto.Memory
/// Hashtable used for address-based dispatch to devices on the memory bus.
/// </summary>
private Dictionary<ushort, IMemoryMappedDevice> _bus;
//
// Optimzation: keep reference to main memory; since 99.9999% of accesses go directly there,
// we can avoid the hashtable overhead using a simple address check.
//
private Memory _mainMemory;
private bool _memoryOperationActive;
private int _memoryCycle;
private ushort _memoryAddress;