mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-27 05:52:11 +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 System.Text;
|
||||||
using Cosmos.Kernel;
|
using Cosmos.Kernel;
|
||||||
|
|
||||||
namespace Cosmos.Hardware {
|
namespace Cosmos.Hardware
|
||||||
public class PIT: Hardware {
|
{
|
||||||
|
/*
|
||||||
|
public class PIT: Hardware
|
||||||
|
{
|
||||||
public const int TicksPerSecond = 1000;
|
public const int TicksPerSecond = 1000;
|
||||||
public static void Wait(uint aMSecs) {
|
public static void Wait(uint aMSecs) {
|
||||||
for(int i = 0; i < (aMSecs/54);i++)
|
for(int i = 0; i < (aMSecs/54);i++)
|
||||||
|
|
@ -25,7 +28,7 @@ namespace Cosmos.Hardware {
|
||||||
}
|
}
|
||||||
|
|
||||||
//private static void SetInterval(ushort hz) {
|
//private static void SetInterval(ushort hz) {
|
||||||
// ushort xDivisor = (ushort)(1193180 / hz); /* Calculate our divisor */
|
// ushort xDivisor = (ushort)(1193180 / hz); /* Calculate our divisor * /
|
||||||
// SetDivisor(xDivisor);
|
// 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)
|
if (aDuration <= 0)
|
||||||
throw new ArgumentOutOfRangeException("Duration must be more than 0");
|
throw new ArgumentOutOfRangeException("Duration must be more than 0");
|
||||||
|
|
||||||
PIT.PlaySound(aFrequency);
|
PIT.EnableSound();
|
||||||
PIT.Wait((uint)aDuration);
|
PIT.T2Frequency = aFrequency;
|
||||||
PIT.MuteSound();
|
PIT.Wait(aDuration);
|
||||||
|
PIT.DisableSound();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int get_CursorLeft()
|
public static int get_CursorLeft()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue