mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-19 12:30:32 +00:00
correct console scrolling,
correct error for cgt
example:
int k = 1000;
UInt32 k2 = 960;
if (k <= k2)
{
Console.Write("true");
}
else
{
Console.Write("false");
}
210 lines
6.6 KiB
C#
210 lines
6.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
namespace Cosmos.Hardware {
|
|
/// <summary>
|
|
/// Programmable Interval Timer
|
|
/// with 1,193181818... MHz
|
|
/// </summary>
|
|
public class PIT : Device {
|
|
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) {
|
|
//Global.PIT.UnregisterTimer(ID);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected Core.IOGroup.PIT IO = Core.Global.BaseIOGroups.PIT;
|
|
private List<PITTimer> ActiveHandlers = new List<PITTimer>();
|
|
private ushort _T0Countdown = 65535;
|
|
private ushort _T2Countdown = 65535;
|
|
private int TimerCounter = 0;
|
|
private bool WaitSignaled = false;
|
|
public const uint PITFrequency = 1193180;
|
|
public const uint PITDelayNS = 838;
|
|
public bool T0RateGen = false;
|
|
|
|
public ushort T0Countdown {
|
|
get {
|
|
return _T0Countdown;
|
|
}
|
|
set {
|
|
_T0Countdown = value;
|
|
|
|
IO.Command.Byte = (byte)(T0RateGen ? 0x34 : 0x30);
|
|
IO.Data0.Byte = (byte)(value & 0xFF);
|
|
IO.Data0.Byte = (byte)(value >> 8);
|
|
}
|
|
}
|
|
public 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 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 ushort T2Countdown {
|
|
get {
|
|
return _T2Countdown;
|
|
}
|
|
set {
|
|
_T2Countdown = value;
|
|
|
|
IO.Command.Byte = 0xB6;
|
|
IO.Data0.Byte = (byte)(value & 0xFF);
|
|
IO.Data0.Byte = (byte)(value >> 8);
|
|
}
|
|
}
|
|
public 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 uint T2DelyNS {
|
|
get {
|
|
return (PITDelayNS * _T2Countdown);
|
|
}
|
|
set {
|
|
if (value > 54918330)
|
|
throw new ArgumentException("Delay must be no greater than 54918330");
|
|
|
|
T2Countdown = (ushort)(value / PITDelayNS);
|
|
}
|
|
}
|
|
|
|
//TODO: Why is sound in PIT? Is it a function of the PIT?
|
|
public void EnableSound() {
|
|
//IO.Port61.Byte = (byte)(IO.Port61.Byte | 0x03);
|
|
}
|
|
public void DisableSound() {
|
|
//IO.Port61.Byte = (byte)(IO.Port61.Byte | 0xFC);
|
|
}
|
|
public void PlaySound(int aFreq) {
|
|
EnableSound();
|
|
T2Frequency = (uint)aFreq;
|
|
}
|
|
public void MuteSound() {
|
|
DisableSound();
|
|
}
|
|
|
|
private void SignalWait() {
|
|
WaitSignaled = true;
|
|
}
|
|
|
|
public void Wait(uint TimeoutMS) {
|
|
WaitSignaled = false;
|
|
|
|
RegisterTimer(new PITTimer(SignalWait, (int)(TimeoutMS * 1000000), false));
|
|
|
|
while (!WaitSignaled) {
|
|
Core.Global.CPU.Halt();
|
|
}
|
|
}
|
|
public void WaitNS(int TimeoutNS) {
|
|
WaitSignaled = false;
|
|
|
|
RegisterTimer(new PITTimer(SignalWait, TimeoutNS, false));
|
|
|
|
while (!WaitSignaled) {
|
|
Core.Global.CPU.Halt();
|
|
}
|
|
}
|
|
|
|
public 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 = hndlr.NanosecondsTimeout;
|
|
} else {
|
|
hndlr.ID = -1;
|
|
ActiveHandlers.RemoveAt(i);
|
|
}
|
|
hndlr.HandleTrigger();
|
|
}
|
|
}
|
|
}
|
|
|
|
public int RegisterTimer(PITTimer timer) {
|
|
if (timer.ID != -1)
|
|
throw new InvalidOperationException("Timer has already been registered!");
|
|
|
|
timer.ID = (TimerCounter++);
|
|
ActiveHandlers.Add(timer);
|
|
|
|
return timer.ID;
|
|
}
|
|
public 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|