New PIT engine - 100% compatible with old version, but much more powerful. Tested and works on real hardware.

Small changes to Console.cs were also made to improve beep.
This commit is contained in:
Xenni_cp 2009-05-11 00:54:27 +00:00
parent e378e212a1
commit 577dcdb49e
2 changed files with 285 additions and 6 deletions

View file

@ -3,8 +3,11 @@ using System.Collections.Generic;
using System.Text;
using Cosmos.Kernel;
namespace Cosmos.Hardware {
public class PIT: Hardware {
namespace Cosmos.Hardware
{
/*
public class PIT: Hardware
{
public const int TicksPerSecond = 1000;
public static void Wait(uint aMSecs) {
for(int i = 0; i < (aMSecs/54);i++)
@ -25,7 +28,7 @@ namespace Cosmos.Hardware {
}
//private static void SetInterval(ushort hz) {
// ushort xDivisor = (ushort)(1193180 / hz); /* Calculate our divisor */
// ushort xDivisor = (ushort)(1193180 / hz); /* Calculate our divisor * /
// SetDivisor(xDivisor);
//}
@ -61,4 +64,279 @@ namespace Cosmos.Hardware {
}
}
*/
public class PIT : Hardware
{
public class PITTimer : IDisposable
{
internal int NSRemaining;
public int NanosecondsTimeout;
public bool Recuring;
internal int ID = -1;
public int TimerID
{
get
{
return ID;
}
}
public delegate void dOnTrigger();
public dOnTrigger HandleTrigger;
public PITTimer(dOnTrigger HandleOnTrigger, int NanosecondsTimeout, bool Recuring)
{
this.HandleTrigger = HandleOnTrigger;
this.NanosecondsTimeout = NanosecondsTimeout;
this.NSRemaining = this.NanosecondsTimeout;
this.Recuring = Recuring;
}
public PITTimer(dOnTrigger HandleOnTrigger, int NanosecondsTimeout, int NanosecondsLeft)
{
this.HandleTrigger = HandleOnTrigger;
this.NanosecondsTimeout = NanosecondsTimeout;
this.NSRemaining = NanosecondsLeft;
this.Recuring = true;
}
~PITTimer()
{
Dispose();
}
public void Dispose()
{
if (ID != -1)
PIT.UnregisterTimer(ID);
}
}
private static List<PITTimer> ActiveHandlers = new List<PITTimer>();
private static ushort _T0Countdown = 65535;
private static ushort _T2Countdown = 65535;
private static int TimerCounter = 0;
private static bool WaitSignaled = false;
public const uint PITFrequency = 1193180;
public const uint PITDelayNS = 838;
public static bool T0RateGen = false;
public static ushort T0Countdown
{
get
{
return _T0Countdown;
}
set
{
_T0Countdown = value;
IOWriteByte(0x43, (byte)(T0RateGen ? 0x34 : 0x30));
IOWriteByte(0x40, (byte)(value & 0xFF));
IOWriteByte(0x40, (byte)(value >> 8));
}
}
public static uint T0Frequency
{
get
{
return (PITFrequency / ((uint)_T0Countdown));
}
set
{
if (value < 19 || value > 1193180)
throw new ArgumentException("Frequency must be between 19 and 1193180!");
T0Countdown = (ushort)(PITFrequency / value);
}
}
public static uint T0DelyNS
{
get
{
return (PITDelayNS * _T0Countdown);
}
set
{
if (value > 54918330)
throw new ArgumentException("Delay must be no greater that 54918330");
T0Countdown = (ushort)(value / PITDelayNS);
}
}
public static ushort T2Countdown
{
get
{
return _T2Countdown;
}
set
{
_T2Countdown = value;
IOWriteByte(0x43, 0xB6);
IOWriteByte(0x42, (byte)(value & 0xFF));
IOWriteByte(0x42, (byte)(value >> 8));
}
}
public static uint T2Frequency
{
get
{
return (PITFrequency / ((uint)_T2Countdown));
}
set
{
if (value < 19 || value > 1193180)
throw new ArgumentException("Frequency must be between 19 and 1193180!");
T2Countdown = (ushort)(PITFrequency / value);
}
}
public static uint T2DelyNS
{
get
{
return (PITDelayNS * _T2Countdown);
}
set
{
if (value > 54918330)
throw new ArgumentException("Delay must be no greater that 54918330");
T2Countdown = (ushort)(value / PITDelayNS);
}
}
public static void EnableSound()
{
IOWriteByte(0x61, (byte)(IOReadByte(0x61) | 0x03));
}
public static void DisableSound()
{
IOWriteByte(0x61, (byte)(IOReadByte(0x61) & 0xFC));
}
private static void SignalWait()
{
WaitSignaled = true;
}
public static void Wait(int TimeoutMS)
{
WaitNS(TimeoutMS * 1000000);
}
public static void WaitNS(int TimeoutNS)
{
WaitSignaled = false;
RegisterTimer(new PITTimer(SignalWait, TimeoutNS, false));
while (!WaitSignaled)
{
CPU.Halt();
}
}
public static void HandleInterrupt()
{
int T0Delay = (int)T0DelyNS;
PITTimer hndlr = null;
for (int i = ActiveHandlers.Count - 1;i >= 0;i--)
{
hndlr = ActiveHandlers[i];
hndlr.NSRemaining -= T0Delay;
if (hndlr.NSRemaining < 1)
{
if (hndlr.Recuring)
{
hndlr.NSRemaining = ActiveHandlers[i].NanosecondsTimeout;
}
else
{
hndlr.ID = -1;
ActiveHandlers.RemoveAt(i);
}
hndlr.HandleTrigger();
}
}
}
public static int RegisterTimer(PITTimer timer)
{
if (timer.ID != -1)
throw new InvalidOperationException("Timer has allready been registered!");
timer.ID = (TimerCounter++);
ActiveHandlers.Add(timer);
return timer.ID;
}
public static void UnregisterTimer(int timerid)
{
for (int i = 0;i < ActiveHandlers.Count;i++)
{
if (ActiveHandlers[i].ID == timerid)
{
ActiveHandlers[i].ID = -1;
ActiveHandlers.RemoveAt(i);
return;
}
}
}
}
public class PITUtil
{
public sealed class SoftwareTimer : IDisposable
{
private uint _Countdown;
private uint _TicksLeft;
private int TimerID;
public delegate void dOnTrigger();
public dOnTrigger HandleTrigger;
private void OnPITTrigger()
{
_TicksLeft--;
if (_TicksLeft == 0)
{
_TicksLeft = _Countdown;
HandleTrigger();
}
}
public SoftwareTimer(uint Countdown, int NSResolution)
{
_Countdown = Countdown;
_TicksLeft = _Countdown;
TimerID = PIT.RegisterTimer(new PIT.PITTimer(OnPITTrigger, NSResolution, true));
}
public SoftwareTimer(uint Countdown, uint CountdownLeft, int NSResolution)
{
_Countdown = Countdown;
_TicksLeft = CountdownLeft;
TimerID = PIT.RegisterTimer(new PIT.PITTimer(OnPITTrigger, NSResolution, true));
}
~SoftwareTimer()
{
Dispose();
}
public void Dispose()
{
if (TimerID != -1)
{
PIT.UnregisterTimer(TimerID);
TimerID = -1;
}
}
}
}
}

View file

@ -42,9 +42,10 @@ namespace Cosmos.Kernel.Plugs
if (aDuration <= 0)
throw new ArgumentOutOfRangeException("Duration must be more than 0");
PIT.PlaySound(aFrequency);
PIT.Wait((uint)aDuration);
PIT.MuteSound();
PIT.EnableSound();
PIT.T2Frequency = aFrequency;
PIT.Wait(aDuration);
PIT.DisableSound();
}
public static int get_CursorLeft()