mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-20 04:48:53 +00:00
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:
parent
e378e212a1
commit
577dcdb49e
2 changed files with 285 additions and 6 deletions
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Reference in a new issue