Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 24 additions & 18 deletions src/Emulator/Peripherals/Peripherals/Timers/SAM_TC.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ namespace Antmicro.Renode.Peripherals.Timers
{
public class SAM_TC : BasicDoubleWordPeripheral, INumberedGPIOOutput, IKnownSize
{
public SAM_TC(IMachine machine, ulong masterClockFrequency = 20000000) : base(machine)
public SAM_TC(IMachine machine, ulong masterClockFrequency = 20000000, int counterWidth = 16) : base(machine)
{
var connections = new Dictionary<int, IGPIO>();
channels = new Channel[NumberOfChannels];
var maxValue = counterWidth == 32 ? 0xFFFFFFFFUL : 0xFFFFUL;
for(int i = 0; i < NumberOfChannels; i++)
{
channels[i] = new Channel(machine.ClockSource, masterClockFrequency, this, i);
channels[i] = new Channel(machine.ClockSource, masterClockFrequency, this, i, maxValue);
connections[i] = channels[i].IRQ;
}
Connections = new ReadOnlyDictionary<int, IGPIO>(connections);
Expand Down Expand Up @@ -323,14 +324,15 @@ public enum Registers

private class Channel
{
public Channel(IClockSource clockSource, ulong masterClockFrequency, IPeripheral owner, int channel)
public Channel(IClockSource clockSource, ulong masterClockFrequency, IPeripheral owner, int channel, ulong maxValue = DefaultMaxValue)
{
this.masterClockFrequency = masterClockFrequency;
this.maxValue = maxValue;
this.channel = channel;
parent = owner;
IRQ = new GPIO();
timer = new LimitTimer(clockSource, masterClockFrequency, owner, $"channel-{channel}", MaxValue, Direction.Ascending, eventEnabled: true, divider: 2);
cTimer = new LimitTimer(clockSource, masterClockFrequency, owner, $"channel-{channel} C capture", MaxValue, Direction.Ascending, workMode: WorkMode.OneShot, eventEnabled: true, divider: 2);
timer = new LimitTimer(clockSource, masterClockFrequency, owner, $"channel-{channel}", maxValue, Direction.Ascending, eventEnabled: true, divider: 2);
cTimer = new LimitTimer(clockSource, masterClockFrequency, owner, $"channel-{channel} C capture", maxValue, Direction.Ascending, workMode: WorkMode.OneShot, eventEnabled: true, divider: 2);
timer.LimitReached += LimitReached;
cTimer.LimitReached += delegate
{
Expand Down Expand Up @@ -571,18 +573,20 @@ private void UpdateTimer(bool start = false)

if(!waveformMode)
{
parent.ErrorLog("Unimplemented");
// Capture mode: free-running counter up to MaxValue
timer.Direction = Direction.Ascending;
timer.Limit = maxValue;
}
else
{
switch(waveformSelected)
{
case WaveSelection.Up:
timer.Direction = Direction.Ascending;
timer.Limit = MaxValue;
timer.Limit = maxValue;
break;
case WaveSelection.UpDown:
timer.Limit = MaxValue;
timer.Limit = maxValue;
break;
case WaveSelection.UpRC:
timer.Direction = Direction.Ascending;
Expand All @@ -602,15 +606,15 @@ private void UpdateTimer(bool start = false)

private void UpdateCTimer()
{
if(!enabled || !waveformMode)
if(!enabled)
{
cTimer.Enabled = false;
return;
}
switch(waveformSelected)

// In capture mode or waveform Up/UpDown, use cTimer for RC compare
if(!waveformMode || waveformSelected == WaveSelection.Up || waveformSelected == WaveSelection.UpDown)
{
case WaveSelection.Up:
case WaveSelection.UpDown:
var direction = timer.Direction;
var value = timer.Value;
var limit = timer.Limit;
Expand All @@ -633,10 +637,10 @@ private void UpdateCTimer()
cTimer.Limit = limit - valueC;
}
cTimer.Enabled = timer.Enabled;
break;
default:
}
else
{
cTimer.Enabled = false;
break;
}
}

Expand All @@ -655,7 +659,8 @@ private void LimitReached()
}
if(!waveformMode)
{
parent.ErrorLog("Unimplemented");
// Capture mode: free-running counter overflow
overflow = true;
}
else
{
Expand All @@ -669,7 +674,7 @@ private void LimitReached()
compareCInterrupt = true;
break;
case WaveSelection.UpDown:
if(timer.Value == MaxValue)
if(timer.Value == maxValue)
{
parent.NoisyLog("Channel #{0} overflow", channel);
overflow = true;
Expand Down Expand Up @@ -718,7 +723,8 @@ private void LimitReached()
private readonly LimitTimer timer;
private readonly LimitTimer cTimer;

private const ulong MaxValue = 0xFFFF;
private readonly ulong maxValue;
private const ulong DefaultMaxValue = 0xFFFF;
}

private enum ClockSelection
Expand Down