Skip to content

Commit

Permalink
Release 0.5.4.0: Handling Timer interrupts. Only the CHARGE registers…
Browse files Browse the repository at this point in the history
… are used to determine the interval. Minimum interval allowed is 1 millisecond.
  • Loading branch information
dtremblay committed Dec 30, 2020
1 parent feb2695 commit 45c2cdd
Show file tree
Hide file tree
Showing 13 changed files with 310 additions and 237 deletions.
260 changes: 129 additions & 131 deletions FoenixIDETester/CpuTests.cs

Large diffs are not rendered by default.

42 changes: 41 additions & 1 deletion Main/Devices/TimerRegister.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using FoenixIDE.Timers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
Expand All @@ -8,17 +9,56 @@ namespace FoenixIDE.Simulator.Devices
{
public class TimerRegister : MemoryLocations.MemoryRAM
{
private MultimediaTimer hiresTimer = null;

public delegate void RaiseInterruptFunction();
public RaiseInterruptFunction TimerInterruptDelegate;
const int CPU_FREQ = 14318000;

public TimerRegister(int StartAddress, int Length) : base(StartAddress, Length)
{
hiresTimer = new MultimediaTimer(1000);
hiresTimer.Elapsed += new MultimediaElapsedEventHandler(Timer_Tick);
}

public override void WriteByte(int Address, byte Value)
{
// Address 0 is control register
data[Address] = Value;
if (Address == 0)
{
bool enabled = (Value & 1) != 0;
if (enabled)
{
hiresTimer.Start();
}
else
{
hiresTimer.Stop();
}
}
else if (Address > 4 && Address < 8)
{
// Calculate interval in milliseconds
int longInterval = data[5] + (data[6] << 8) + (data[7] << 16);
double msInterval = (double)(longInterval) * 1000/ (double)CPU_FREQ;
uint adjInterval = (uint)msInterval;
if (adjInterval==0)
{
hiresTimer.Interval = 1;
}
else
{
hiresTimer.Interval = adjInterval;
}


}
}

void Timer_Tick(object sender, EventArgs e)
{
TimerInterruptDelegate?.Invoke();
}
}
}
40 changes: 40 additions & 0 deletions Main/FoenixSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ public FoenixSystem(Gpu gpu, BoardVersion version, string DefaultKernel)
// Write bytes $9F in the joystick registers to mean that they are not installed.
MemMgr.WriteWord(0xAFE800, 0x9F9F);
MemMgr.WriteWord(0xAFE802, 0x9F9F);
MemMgr.TIMER0.TimerInterruptDelegate += TimerEvent0;
MemMgr.TIMER1.TimerInterruptDelegate += TimerEvent1;
MemMgr.TIMER2.TimerInterruptDelegate += TimerEvent2;
}

private void CPU_SimulatorCommand(int EventID)
Expand All @@ -102,6 +105,43 @@ private void CPU_SimulatorCommand(int EventID)
}
}

private void TimerEvent0()
{
byte mask = MemMgr.ReadByte(MemoryLocations.MemoryMap.INT_MASK_REG0);
if (!CPU.DebugPause && !CPU.Flags.IrqDisable && ((~mask & (byte)Register0.FNX0_INT02_TMR0) == (byte)Register0.FNX0_INT02_TMR0))
{
// Set the Timer0 Interrupt
byte IRQ0 = MemMgr.ReadByte(MemoryLocations.MemoryMap.INT_PENDING_REG0);
IRQ0 |= (byte)Register0.FNX0_INT02_TMR0;
MemMgr.WriteByte(MemoryLocations.MemoryMap.INT_PENDING_REG0, IRQ0);
CPU.Pins.IRQ = true;
}
}
private void TimerEvent1()
{
byte mask = MemMgr.ReadByte(MemoryLocations.MemoryMap.INT_MASK_REG0);
if (!CPU.DebugPause && !CPU.Flags.IrqDisable && ((~mask & (byte)Register0.FNX0_INT03_TMR1) == (byte)Register0.FNX0_INT03_TMR1))
{
// Set the Timer1 Interrupt
byte IRQ0 = MemMgr.ReadByte(MemoryLocations.MemoryMap.INT_PENDING_REG0);
IRQ0 |= (byte)Register0.FNX0_INT03_TMR1;
MemMgr.WriteByte(MemoryLocations.MemoryMap.INT_PENDING_REG0, IRQ0);
CPU.Pins.IRQ = true;
}
}
private void TimerEvent2()
{
byte mask = MemMgr.ReadByte(MemoryLocations.MemoryMap.INT_MASK_REG0);
if (!CPU.DebugPause && !CPU.Flags.IrqDisable && ((~mask & (byte)Register0.FNX0_INT04_TMR2) == (byte)Register0.FNX0_INT04_TMR2))
{
// Set the Timer2 Interrupt
byte IRQ0 = MemMgr.ReadByte(MemoryLocations.MemoryMap.INT_PENDING_REG0);
IRQ0 |= (byte)Register0.FNX0_INT04_TMR2;
MemMgr.WriteByte(MemoryLocations.MemoryMap.INT_PENDING_REG0, IRQ0);
CPU.Pins.IRQ = true;
}
}

public BoardVersion GetVersion()
{
return boardVersion;
Expand Down
19 changes: 5 additions & 14 deletions Main/MemoryLocations/MemoryManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,7 @@ public int EndAddress
/// <param name="DeviceAddress"></param>
public void GetDeviceAt(int Address, out IMappable Device, out int DeviceAddress)
{
//foreach (IMappable device in devices)
//{
// if (Address >= device.StartAddress && Address < device.EndAddress)
// {
// Device = device;
// DeviceAddress = Address - device.StartAddress;
// return;
// }
//}
if (Address == CODEC.StartAddress)
if (Address == MemoryMap.CODEC_WR_CTRL_FMX)
{
Device = CODEC;
DeviceAddress = 0;
Expand All @@ -96,25 +87,25 @@ public void GetDeviceAt(int Address, out IMappable Device, out int DeviceAddress
DeviceAddress = Address - MATH.StartAddress;
return;
}
if (Address >= INTERRUPT.StartAddress && Address <= INTERRUPT.EndAddress)
if (Address >= MemoryMap.INT_PENDING_REG0 && Address <= MemoryMap.INT_PENDING_REG0 + 3)
{
Device = INTERRUPT;
DeviceAddress = Address - INTERRUPT.StartAddress;
return;
}
if (Address >= TIMER0.StartAddress && Address <= TIMER0.EndAddress)
if (Address >= MemoryMap.TIMER0_CTRL_REG && Address <= MemoryMap.TIMER0_CTRL_REG + 7)
{
Device = TIMER0;
DeviceAddress = Address - TIMER0.StartAddress;
return;
}
if (Address >= TIMER1.StartAddress && Address <= TIMER1.EndAddress)
if (Address >= MemoryMap.TIMER1_CTRL_REG && Address <= MemoryMap.TIMER1_CTRL_REG + 7)
{
Device = TIMER1;
DeviceAddress = Address - TIMER1.StartAddress;
return;
}
if (Address >= TIMER2.StartAddress && Address <= TIMER2.EndAddress)
if (Address >= MemoryMap.TIMER2_CTRL_REG && Address <= MemoryMap.TIMER2_CTRL_REG + 7)
{
Device = TIMER2;
DeviceAddress = Address - TIMER2.StartAddress;
Expand Down
32 changes: 16 additions & 16 deletions Main/Processor/CPU.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public partial class CPU
/// </summary>
private DateTime checkStartTime = DateTime.Now;

public MemoryManager Memory = null;
public MemoryManager MemMgr = null;
public Thread CPUThread = null;

public event Operations.SimulatorCommandEvent SimulatorCommand;
Expand Down Expand Up @@ -91,9 +91,9 @@ public int[] Snapshot
}
}

public CPU(MemoryManager newMemory)
public CPU(MemoryManager mm)
{
Memory = newMemory;
MemMgr = mm;
clockSpeed = 14000000;
clockCyles = 0;
Operations operations = new Operations(this);
Expand Down Expand Up @@ -153,7 +153,7 @@ public bool ExecuteNext()
}

// TODO - if pc > RAM size, then throw an exception
CurrentOpcode = opcodes[Memory.RAM.ReadByte(PC)];
CurrentOpcode = opcodes[MemMgr.RAM.ReadByte(PC)];
OpcodeLength = CurrentOpcode.Length;
OpcodeCycles = 1;
SignatureBytes = ReadSignature(OpcodeLength, PC);
Expand Down Expand Up @@ -182,7 +182,7 @@ public void Halt()
public void Reset()
{
Pins.VectorPull = true;
Memory.VectorPull = true;
MemMgr.VectorPull = true;

SetEmulationMode();
Flags.Value = 0;
Expand All @@ -194,12 +194,12 @@ public void Reset()
DirectPage.Value = 0;
//ProgramBank.Value = 0;

PC = Memory.ReadWord(MemoryMap.VECTOR_ERESET);
PC = MemMgr.ReadWord(MemoryMap.VECTOR_ERESET);

Flags.IrqDisable = true;
Pins.IRQ = false;
Pins.VectorPull = false;
Memory.VectorPull = false;
MemMgr.VectorPull = false;
Waiting = false;
}

Expand Down Expand Up @@ -237,19 +237,19 @@ public void SyncFlags()
/// </summary>
public OpCode PreFetch()
{
return opcodes[Memory[PC]];
return opcodes[MemMgr[PC]];
}

public int ReadSignature(int length, int pc)
{
switch (length)
{
case 2:
return Memory.RAM.ReadByte(pc + 1);
return MemMgr.RAM.ReadByte(pc + 1);
case 3:
return Memory.RAM.ReadWord(pc + 1);
return MemMgr.RAM.ReadWord(pc + 1);
case 4:
return Memory.RAM.ReadLong(pc + 1);
return MemMgr.RAM.ReadLong(pc + 1);
}

return 0;
Expand Down Expand Up @@ -291,7 +291,7 @@ private int GetPointerDirect(int baseAddress, Register Index = null)
int addr = DirectPage.Value + baseAddress;
if (Index != null)
addr += Index.Value;
int pointer = Memory.ReadWord(addr);
int pointer = MemMgr.ReadWord(addr);
return DataBank.GetLongAddress(pointer);
}

Expand All @@ -306,7 +306,7 @@ private int GetPointerLong(int baseAddress, Register Index = null)
int addr = baseAddress;
if (Index != null)
addr += Index.Value;
return DataBank.GetLongAddress(Memory.ReadWord(addr));
return DataBank.GetLongAddress(MemMgr.ReadWord(addr));
}

#endregion
Expand All @@ -333,7 +333,7 @@ public void JumpLong(int addr)

public void JumpVector(int VectorAddress)
{
int addr = Memory.ReadWord(VectorAddress);
int addr = MemMgr.ReadWord(VectorAddress);
//ProgramBank.Value = 0;
//PC.Value = addr;
PC = addr;
Expand All @@ -357,7 +357,7 @@ public void Push(int value, int bytes)
throw new Exception("bytes must be between 1 and 3. Got " + bytes.ToString());

Stack.Value -= bytes;
Memory.Write(Stack.Value + 1, value, bytes);
MemMgr.Write(Stack.Value + 1, value, bytes);
}

public void Push(Register Reg, int Offset)
Expand All @@ -375,7 +375,7 @@ public int Pull(int bytes)
if (bytes < 1 || bytes > 3)
throw new Exception("bytes must be between 1 and 3. got " + bytes.ToString());

int ret = Memory.Read(Stack.Value + 1, bytes);
int ret = MemMgr.Read(Stack.Value + 1, bytes);

Stack.Value += bytes;
return ret;
Expand Down
Loading

0 comments on commit 45c2cdd

Please sign in to comment.