namespace XFESystem.NativeKernel; public static unsafe class Serial { const ushort Port = 0x3f8; const uint PollLimit = 100000; public static bool Present; public static ulong DroppedBytes; public static void Initialize() { Present = false; byte old = Native.In8(Port + 7); Native.Out8(Port + 7, 0x5a); bool detected = Native.In8(Port + 7) == 0x5a; Native.Out8(Port + 7, old); if (!detected) return; Native.Out8(Port + 1, 0); Native.Out8(Port + 3, 0x80); Native.Out8(Port, 1); Native.Out8(Port + 1, 0); Native.Out8(Port + 3, 3); Native.Out8(Port + 2, 0xc7); Native.Out8(Port + 4, 0x0b); Present = true; } public static void Byte(byte value) { if (!Present) return; for (uint i = 0; i < PollLimit; i++) { if ((Native.In8(Port + 5) & 0x20) != 0) { Native.Out8(Port, value); return; } Native.Pause(); } DroppedBytes++; // A disappeared or stalled UART must never block the kernel. Present = false; } public static void Write(string value) { fixed (char* text = value) for (int i = 0; i < value.Length; i++) { char ch = text[i]; if (ch == '\n') Byte(13); Byte(ch < 128 ? (byte)ch : (byte)'?'); } } public static void Line(string value) { Write(value); Byte(13); Byte(10); } public static void Number(ulong value) { byte* digits = stackalloc byte[20]; uint count = 0; do { digits[count++] = (byte)('0' + value % 10); value /= 10; } while (value != 0); while (count != 0) Byte(digits[--count]); } public static void Hex(ulong value) { Write("0x"); for (int shift = 60; shift >= 0; shift -= 4) { byte digit = (byte)((value >> shift) & 15); Byte((byte)(digit < 10 ? '0' + digit : 'a' + digit - 10)); } } }