public static void Initialize()
        {
            // Default to SDL interface for cross platform desktop support
            Platform = HardwareType.PC;
            Screen   = ScreenType.SDLWindow480x360;

            // Check for supported embedded platforms
            if (File.Exists("/proc/device-tree/model"))
            {
                var model = File.ReadAllText("/proc/device-tree/model");

                if (model.Contains("Orange Pi"))
                {
                    Platform = HardwareType.OrangePi;
                }
                else if (model.Contains("Raspberry Pi"))
                {
                    Platform = HardwareType.RaspberryPi;
                }
            }

            // Check for supported embedded screens
            if (File.Exists("/sys/class/graphics/fb1/virtual_size"))
            {
                var size = File.ReadAllText("/sys/class/graphics/fb1/virtual_size");

                switch (size)
                {
                case "480,320":
                    Screen = ScreenType.FB480x360;
                    break;

                case "800,480":
                    Screen = ScreenType.FB800x480;
                    break;
                }
            }
            else if (File.Exists("/sys/class/graphics/fb0/virtual_size"))
            {
                var size = File.ReadAllText("/sys/class/graphics/fb0/virtual_size");

                switch (size)
                {
                case "480,320":
                    Screen = ScreenType.FB480x360;
                    break;

                case "800,480":
                    Screen = ScreenType.FB800x480;
                    break;
                }
            }
            // Check for supported embedded screens
            if (File.Exists("/sys/class/graphics/fb1/virtual_size"))
            {
                var size = File.ReadAllText("/sys/class/graphics/fb1/virtual_size");

                switch (size)
                {
                case "480,320":
                    Screen = ScreenType.FB480x360;
                    break;

                case "800,480":
                    Screen = ScreenType.FB800x480;
                    break;
                }
            }
            else if (File.Exists("/sys/class/graphics/fb0/virtual_size"))
            {
                var size = File.ReadAllText("/sys/class/graphics/fb0/virtual_size");

                switch (size)
                {
                case "480,320":
                    Screen = ScreenType.FB480x360;
                    break;

                case "800,480":
                    Screen = ScreenType.FB800x480;
                    break;
                }
            }

            switch (Platform)
            {
            case HardwareType.OrangePi:
                serialPort = new SerialPort("/dev/ttyS3", 9600, Parity.None, 8, StopBits.One);

                address0Pin = 11;
                address1Pin = 6;
                address2Pin = 0;
                address3Pin = 3;
                address4Pin = 7;
                address5Pin = 8;
                address6Pin = 10;
                address7Pin = 20;
                triggerPin  = 9;
                ledPin      = 200;
                beeperPin   = 201;
                break;

            case HardwareType.RaspberryPi:
                serialPort = new SerialPort("/dev/serial0", 9600, Parity.None, 8, StopBits.One);

                address0Pin = 3;
                address1Pin = 4;
                address2Pin = 27;
                address3Pin = 22;
                address4Pin = 5;
                address5Pin = 6;
                address6Pin = 19;
                address7Pin = 26;
                triggerPin  = 13;
                ledPin      = 12;
                beeperPin   = 16;
                break;
            }

            switch (Platform)
            {
            case HardwareType.OrangePi:
            case HardwareType.RaspberryPi:
                W26Pipe.Initalize();

                serialPort.Open();

                var driver = new LibGpiodDriver(0);
                gpio = new GpioController(PinNumberingScheme.Logical, driver);

                gpio.OpenPin(address0Pin, PinMode.Output);
                gpio.OpenPin(address1Pin, PinMode.Output);
                gpio.OpenPin(address2Pin, PinMode.Output);
                gpio.OpenPin(address3Pin, PinMode.Output);
                gpio.OpenPin(address4Pin, PinMode.Output);
                gpio.OpenPin(address5Pin, PinMode.Output);
                gpio.OpenPin(address6Pin, PinMode.Output);
                gpio.OpenPin(address7Pin, PinMode.Output);
                gpio.OpenPin(triggerPin, PinMode.Output);
                gpio.OpenPin(ledPin, PinMode.Output);
                gpio.OpenPin(beeperPin, PinMode.Output);
                break;
            }

            Logout();
        }
        public static string Read()
        {
            switch (Platform)
            {
            case HardwareType.OrangePi:
            case HardwareType.RaspberryPi:
                var output = W26Pipe.Read();

                if (string.IsNullOrEmpty(output))
                {
                    output = serialPort.ReadExisting();
                }

                if (!string.IsNullOrEmpty(output))
                {
                    Console.WriteLine($"Received raw input [{output.Length}]: {output} {Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(output))}");
                }

                return(output);

            default:
                Thread.Sleep(5);

                SDL2.SDL.SDL_PollEvent(out var pollEvent);

                if (pollEvent.type == SDL.SDL_EventType.SDL_KEYDOWN)
                {
                    var keycode = pollEvent.key.keysym.sym;

                    switch (keycode)
                    {
                    case SDL.SDL_Keycode.SDLK_HASH:
                    case SDL.SDL_Keycode.SDLK_RETURN:
                    case SDL.SDL_Keycode.SDLK_RETURN2:
                        return("B");

                    case SDL.SDL_Keycode.SDLK_ASTERISK:
                    case SDL.SDL_Keycode.SDLK_BACKSPACE:
                        return("A");

                    case SDL.SDL_Keycode.SDLK_ESCAPE:
                        Environment.Exit(0);
                        break;
                    }

                    var character = (char)keycode;

                    // Numerals
                    if (character > 47 && character < 58)
                    {
                        return(character.ToString());
                    }
                }
                else if (pollEvent.type == SDL.SDL_EventType.SDL_WINDOWEVENT)
                {
                    if (pollEvent.window.windowEvent ==
                        SDL.SDL_WindowEventID.SDL_WINDOWEVENT_CLOSE)
                    {
                        Environment.Exit(0);
                    }
                }

                return("");
            }
        }