diff --git a/source/Cosmos/Cosmos.Hardware/PIT.cs b/source/Cosmos/Cosmos.Hardware/PIT.cs index 2481b7a2c..089073d2c 100644 --- a/source/Cosmos/Cosmos.Hardware/PIT.cs +++ b/source/Cosmos/Cosmos.Hardware/PIT.cs @@ -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 ActiveHandlers = new List(); + 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; + } + } + } + } } \ No newline at end of file diff --git a/source/Cosmos/Cosmos.Kernel.Plugs/Console.cs b/source/Cosmos/Cosmos.Kernel.Plugs/Console.cs index 80922bc24..e892756ed 100644 --- a/source/Cosmos/Cosmos.Kernel.Plugs/Console.cs +++ b/source/Cosmos/Cosmos.Kernel.Plugs/Console.cs @@ -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()