Commit 41a3f15e authored by Doc's avatar Doc 💀
Browse files

xmb

parent c54bfb83
Loading
Loading
Loading
Loading
+99 −50
Original line number Diff line number Diff line
@@ -6,6 +6,8 @@ using System.IO.Ports;
    https://git.en0.io/alyx/matrixorbital-serial-display-library/-/blob/master/morbital.py
*/

// we should not open or close the device in the library, outside of init; let the program do this

namespace MatrixOrbital;

internal static class SerialControl {
@@ -22,11 +24,65 @@ internal static class SerialControl {
        return false;
    }

    public static void WriteAndClose(this SerialPort? device, byte[] bytepayload) {
    public static void WritePayload(this SerialPort? device, byte[] bytepayload) {
        device.Write(bytepayload, 0, bytepayload.Length);
    }
    
}

public static class Device {
    public static SerialPort Initialize(string device, int baud = 19200) {
        /* MatrixOrbital.Device.Initialize(device, baud) 
            Instatiates a device to be used.
            Returns a System.IO.Ports.SerialPort.
            device  (required) device name of the controller
            baud    (optional) baud rate, defaults to 19200
                               should not need to set baud unless
                               BaudRate() was called
        */
        var newdev = new SerialPort(device, baud);
        bool sanity = SerialControl.CheckSerialPermissionAndOpen(newdev);
        if (sanity) throw(new UnauthorizedAccessException());
        return newdev;
    }

    public static SerialPort BaudRate(this SerialPort? device, int baud) {
        /* MatrixOrbital.Device.BaudRate(device, baud) 
            Sets the baud rate of the device, and then reinitializes it.
            Returns a System.IO.Ports.SerialPort.
            device  (required) device name of the controller
            baud    (required) baud rate
        */
        int baudv = 0;
        switch (baud)
        {
            case (9600): baudv = 207; break;
            case (14400): baudv = 138; break;
            case (19200): baudv = 103; break;
            case (28800): baudv = 68; break;
            case (38400): baudv = 51; break;
            case (57600): baudv = 34; break;
            case (76800): baudv = 25; break;
            case (115200): baudv = 16; break;
            default: throw(new ArgumentException());
        }
        byte[] bytepayload = new byte[3] { 254,57,(byte)baudv };
        SerialControl.WritePayload(device, bytepayload);
        device.Close();
        return Initialize(device.PortName, baud);
    }

    public static void SoftReset(this SerialPort? device) {
        /* MatrixOrbital.Device.SoftReset(device) 
            Soft restarts the device.
            device  (required) device name of the controller
        */
        byte[] bytepayload = new byte[6] { 254,253,77,79,117,110 };
        SerialControl.WritePayload(device, bytepayload);
        device.Close();
        Thread.Sleep(4000);
        device.Open();
    }
}

public static class Display {
@@ -36,10 +92,7 @@ public static class Display {
            device  (required) device name of the controller
            text    (required) text to write
        */
        bool sanity = SerialControl.CheckSerialPermissionAndOpen(device);
        if (sanity) return;
        device.Write(text);
        device.Close();
    }

    public static void DrawBitmap(this SerialPort? device, int x, int y, int w, int h, byte[] bitmap) {
@@ -52,24 +105,21 @@ public static class Display {
            h       (required) bitmap height
            bitmap  (required) bitmap data
        */
        bool sanity = SerialControl.CheckSerialPermissionAndOpen(device);
        if (sanity) return;
        byte[] initbytepayload = new byte[6] { 254,100,(byte)x,(byte)y,(byte)w,(byte)h };
        var t = new MemoryStream();
        t.Write(initbytepayload, 0, initbytepayload.Length);
        t.Write(bitmap, 0, bitmap.Length);
        var bytepayload = t.ToArray();
        SerialControl.WriteAndClose(device, bytepayload);
        SerialControl.WritePayload(device, bytepayload);
    }

    public static void ClearDisplay(this SerialPort? device) {
        /* MatrixOrbital.Display.ClearDisplay(device) 
            Clears the contents of the display.
            device  (required) device name of the controller
        */
        bool sanity = SerialControl.CheckSerialPermissionAndOpen(device);
        if (sanity) return;
        byte[] bytepayload = new byte[2] { 254,88 };
        SerialControl.WriteAndClose(device, bytepayload);
        SerialControl.WritePayload(device, bytepayload);
    }

    public static void ResetCursorPos(this SerialPort? device) {
@@ -77,22 +127,8 @@ public static class Display {
            Sets cursor position to top left of display.
            device  (required) device name of the controller
        */
        bool sanity = SerialControl.CheckSerialPermissionAndOpen(device);
        if (sanity) return;
        byte[] bytepayload = new byte[2] { 254,72 };
        SerialControl.WriteAndClose(device, bytepayload);
    }

    public static void SoftReset(this SerialPort? device) {
        /* MatrixOrbital.Display.SoftReset(device) 
            Soft restarts the device.
            device  (required) device name of the controller
        */
        bool sanity = SerialControl.CheckSerialPermissionAndOpen(device);
        if (sanity) return;
        byte[] bytepayload = new byte[6] { 254,253,77,79,117,110 };
        SerialControl.WriteAndClose(device, bytepayload);
        Thread.Sleep(4000);
        SerialControl.WritePayload(device, bytepayload);
    }

    public static void PositionCursor(this SerialPort? device, int x, int y) {
@@ -105,10 +141,8 @@ public static class Display {
        if (x < 1 || x > 27 || y < 1 || y > 8) {
            throw new ArgumentOutOfRangeException("Cursor position is invalid. Make sure x is a positive value less than 28 or y is a positive value less than 9.");
        }
        bool sanity = SerialControl.CheckSerialPermissionAndOpen(device);
        if (sanity) return;
        byte[] bytepayload = new byte[4] { 254,71,(byte)x,(byte)y };
        SerialControl.WriteAndClose(device, bytepayload);
        SerialControl.WritePayload(device, bytepayload);
    }

    public static void PositionCoord(this SerialPort? device, int x, int y) {
@@ -121,10 +155,8 @@ public static class Display {
        if (x < 1 || x > 192 || y < 1 || y > 64) {
            throw new ArgumentOutOfRangeException("Coordinate position is invalid. Make sure x is a positive value less than 193 or y is a positive value less than 65.");
        }
        bool sanity = SerialControl.CheckSerialPermissionAndOpen(device);
        if (sanity) return;
        byte[] bytepayload = new byte[4] { 254,121,(byte)x,(byte)y };
        SerialControl.WriteAndClose(device, bytepayload);
        SerialControl.WritePayload(device, bytepayload);
    }

    public static void BacklightControl(this SerialPort? device, int b, int c = -1 ) {
@@ -143,15 +175,41 @@ public static class Display {
        if (b < 0 || b > 255 || c < -1 || c > 255) {
            throw new ArgumentOutOfRangeException("Display settings are invalid. Make sure brightness and contrast are between 0 (off) and 255 (full on).");
        }
        bool sanity = SerialControl.CheckSerialPermissionAndOpen(device);
        if (sanity) return;
        byte[] bytepayload;
        if (c == -1) {
            bytepayload = new byte[3] { 254,153,(byte)b };
        } else {
            bytepayload = new byte[6] { 254,153,(byte)b,254,80,(byte)c };
        }
        SerialControl.WriteAndClose(device, bytepayload);
        SerialControl.WritePayload(device, bytepayload);
    }

    public static void SetFont(this SerialPort? device, int f) {
        /* MatrixOrbital.Display.SetFont(device, f) 
            Sets display's text font
            device  (required) device name of the controller
            f       (required) font id, 0-1023
        */
        short fontsel = (short)f;
        byte[] fontselAsBytes = BitConverter.GetBytes(fontsel);
        byte[] bytepayload = new byte[4] { 254,49,fontselAsBytes[0],fontselAsBytes[1] };
        SerialControl.WritePayload(device, bytepayload);
    }

    public static void AddFont(this SerialPort? device, int id, int size, byte[] data) {
        /* MatrixOrbital.Display.ResetCursorPos(device) 
            Sets cursor position to top left of display.
            device  (required) device name of the controller
        */
        short fontid = (short)id;
        byte[] fontidAsBytes = BitConverter.GetBytes(fontid);
        byte[] sizeAsBytes = BitConverter.GetBytes(size);
        byte[] initbytepayload = new byte[] { 254,49,fontidAsBytes[0],fontidAsBytes[1],sizeAsBytes[0],sizeAsBytes[1],sizeAsBytes[2],sizeAsBytes[3] };
        var t = new MemoryStream();
        t.Write(initbytepayload, 0, initbytepayload.Length);
        t.Write(data, 0, data.Length);
        var bytepayload = t.ToArray();
        SerialControl.WritePayload(device, bytepayload);
    }
}

@@ -167,29 +225,22 @@ public static class LED {
        if (led < 0 || led > 2 || color < 0 || color > 3) {
            throw new ArgumentOutOfRangeException("LED configuration is invalid. Make sure led is a positive value less than 3 or color is a positive value less than 4.");
        }
        bool sanity = SerialControl.CheckSerialPermissionAndOpen(device);
        if (sanity) return;
        byte[] bytepayload = new byte[4] { 254,90,(byte)led,(byte)color };
        SerialControl.WriteAndClose(device, bytepayload);
        SerialControl.WritePayload(device, bytepayload);
    }
}

public static class Keypad {
    /*public static string ReceiveKeypress(this SerialPort? device) {
        // MatrixOrbital.Keypad.ReceiveKeypress(device) 
        //  I don't know if this works yet.
        //  Retrieve the most recent keypress on command
        //  device  (required) device name of the controller
        //
        bool sanity = SerialControl.CheckSerialPermissionAndOpen(device);
        if (sanity) return "None";
        
        device.DataReceived += new SerialDataReceivedEventHandler(ReceiveKeypressEvent);
        return "";
    }

    public static void ReceiveKeypressEvent(object sender, SerialDataReceivedEventArgs e) {
        SerialPort sp = (SerialPort)sender;
        string indata = sp.ReadExisting();
        string hurf;
        hurf = new SerialDataReceivedEventHandler(ReceiveKeypressEvent);
        return hurf;
    }*/

    public static void BacklightControl(this SerialPort? device, int b ) {
@@ -205,9 +256,7 @@ public static class Keypad {
        if (b < 0 || b > 255) {
            throw new ArgumentOutOfRangeException("Display settings are invalid. Make sure brightness and contrast are between 0 (off) and 255 (full on).");
        }
        bool sanity = SerialControl.CheckSerialPermissionAndOpen(device);
        if (sanity) return;
        byte[] bytepayload = new byte[3] { 254,156,(byte)b };
        SerialControl.WriteAndClose(device, bytepayload);
        SerialControl.WritePayload(device, bytepayload);
    }
}
 No newline at end of file
+130 −8
Original line number Diff line number Diff line
@@ -3,24 +3,146 @@ using System.IO;
using System.IO.Ports;
using MatrixOrbital;

// create a SerialPort before using
public static class GlobalDefs {
    public static string keypressdata = "None";
    public static string[] xmbhorizontal = {"settings","radio","music","photo","extra"};
    public static int horizontalsel = 1;
    public static string[][] xmbvertical = new string[5][]{
        new string[3]{"display","network","sources"},
        new string[2]{"fm","internet"},
        new string[2]{"local","network"},
        new string[2]{"local","network"},
        new string[4]{"todo","fill","this","in"}
        };
    public static int verticalsel = 1;
    public static string settingbuttonlabel = "settings";
    public static string actionbuttonlabel = "action";
}

class Program {
    static SerialPort _serialPort;

    static void Main() {
        _serialPort = new SerialPort("/dev/ttyUSB0",19200);
        var loadedfile = new FileStream(@"ripnet.hex",FileMode.Open);
        _serialPort = MatrixOrbital.Device.Initialize("/dev/ttyUSB0");
        _serialPort = MatrixOrbital.Device.BaudRate(_serialPort, 115200);

        //var loadedfile = new FileStream(@"ripnet.hex",FileMode.Open);

        /*var loadedfont = new FileStream(@"inv-sm.mgf",FileMode.Open);
        var fontdata = new byte[(int)loadedfont.Length];
        loadedfont.Read(fontdata, 0, (int)loadedfont.Length);
        MatrixOrbital.Display.AddFont(_serialPort,3,25,fontdata);*/

        //insert other display commands here
        /*var bitmapdata = new byte[(int)loadedfile.Length];
        loadedfile.Read(bitmapdata, 0, (int)loadedfile.Length);
        //var bitmapdata = new byte[(int)loadedfile.Length];
        //loadedfile.Read(bitmapdata, 0, (int)loadedfile.Length);
        //MatrixOrbital.Display.SetFont(_serialPort,3);
        MatrixOrbital.Display.ClearDisplay(_serialPort);
        MatrixOrbital.Display.DrawBitmap(_serialPort,1,11,192,42,bitmapdata);*/
        _serialPort.DataReceived += new SerialDataReceivedEventHandler(MatrixOrbital.Keypad.ReceiveKeypressEvent);
        //MatrixOrbital.Display.DrawBitmap(_serialPort,1,11,192,42,bitmapdata);
        for (int i = 0; i < 3; i++) MatrixOrbital.LED.SetColor(_serialPort,i,1);

        _serialPort.Open();
        MenuViewGenerator(GlobalDefs.xmbhorizontal, GlobalDefs.xmbvertical[GlobalDefs.horizontalsel], GlobalDefs.horizontalsel, GlobalDefs.verticalsel, GlobalDefs.settingbuttonlabel, GlobalDefs.actionbuttonlabel);

        _serialPort.DataReceived += new SerialDataReceivedEventHandler(ReceiveKeypressEvent);

        InitClock();

        Console.WriteLine("Press any key to continue...");
        Console.WriteLine();
        Console.ReadKey();
        _serialPort.Close();
    }

    public async static Task InitClock() {
        var timer = new PeriodicTimer(TimeSpan.FromSeconds(1));

        while (await timer.WaitForNextTickAsync()) {
            MatrixOrbital.Display.ResetCursorPos(_serialPort);
            MatrixOrbital.Display.WriteText(_serialPort, DateTime.Now.ToString("HH:mm:ss"));
        }
    }
    public static void ReceiveKeypressEvent(object sender, SerialDataReceivedEventArgs e) {
        /* MatrixOrbital.Keypad.ReceiveKeypressEvent(event, e)
            Fires the keypress to a global variable <keypressdata>
            which is required for this event handler to function
        */
        SerialPort sp = (SerialPort)sender;
        string indata = sp.ReadExisting();
        ParseKeypress(sp, indata);
    }

    private static void ParseKeypress(SerialPort sp, string rawinput) {
        string parsedinput = "";
        switch (rawinput)
        {
            case("A"): parsedinput = "Top"; break;
            case("B"): parsedinput = "Up"; break;
            case("C"): parsedinput = "Right"; break;
            case("D"): parsedinput = "Left"; break;
            case("E"): parsedinput = "Center"; break;
            case("G"): parsedinput = "Bottom"; break;
            case("H"): parsedinput = "Down"; break;
        }
        GlobalDefs.keypressdata = parsedinput;
        // MatrixOrbital.Display.WriteText(sp, keypressdata + "\n");
        Console.WriteLine(parsedinput);
        switch (parsedinput) {
            case("Left"): GlobalDefs.horizontalsel--; break;
            case("Right"): GlobalDefs.horizontalsel++; break;
            case("Up"): GlobalDefs.verticalsel--; break;
            case("Down"): GlobalDefs.verticalsel++; break;
            default: break;
        }
        // we can't be going out of bounds, so just reset it
        if (GlobalDefs.horizontalsel < 0) GlobalDefs.horizontalsel = 0;
        if (GlobalDefs.horizontalsel > GlobalDefs.xmbhorizontal.Length-1) GlobalDefs.horizontalsel = GlobalDefs.xmbhorizontal.Length-1;
        if (GlobalDefs.verticalsel < 0) GlobalDefs.verticalsel = 0;
        if (GlobalDefs.verticalsel > GlobalDefs.xmbvertical[GlobalDefs.horizontalsel].Length-1) GlobalDefs.verticalsel = GlobalDefs.xmbvertical[GlobalDefs.horizontalsel].Length-1;
        MenuViewGenerator(GlobalDefs.xmbhorizontal, GlobalDefs.xmbvertical[GlobalDefs.horizontalsel], GlobalDefs.horizontalsel, GlobalDefs.verticalsel, GlobalDefs.settingbuttonlabel, GlobalDefs.actionbuttonlabel);
    }

    public static void MenuViewGenerator(string[] horz, string[] vert, int selh, int selv, string s, string a) {
        // Matrix Orbital is characters 27 wide, 8 high
        /* here's a mockup of what it could look like
            0123456789012345678901234567
            1  [status bar is up here] <- clock left, settings button label right
            2    fm
            3ngs radio music photo extra
            4    internet
            5
            6
            7
            8  [leave this empty] <- action button label right
        */
        // just in case we've already rendered a menu, blank it out
        MatrixOrbital.Display.PositionCursor(_serialPort,1,2);
        MatrixOrbital.Display.WriteText(_serialPort,"                                                                                                                                       ");
        // first generate horizontal menu
        string hrender = "   ";
        if (selh > 0) hrender = horz[selh-1].Substring(horz[selh-1].Length-3);
        for (int i = selh; i < horz.Length; i++) hrender = String.Concat(hrender, " ", horz[i]);
        // render it on screen
        MatrixOrbital.Display.PositionCursor(_serialPort,1,3);
        if (hrender.Length > 27) {
            MatrixOrbital.Display.WriteText(_serialPort,hrender.Substring(0,27));
        } else {
            MatrixOrbital.Display.WriteText(_serialPort,hrender);
        }
        // vertical menu is a bit more involved
        if (selv > 0) {
            MatrixOrbital.Display.PositionCursor(_serialPort,5,2);
            MatrixOrbital.Display.WriteText(_serialPort, vert[selv-1]);
        }
        int vmask = 4;
        if ((vert.Length - selv) < 4) vmask = vert.Length - selv;
        for (int i = 0; i < vmask; i++) {
            MatrixOrbital.Display.PositionCursor(_serialPort,5,i+4);
            MatrixOrbital.Display.WriteText(_serialPort, vert[selv+i]);
        }
        // then the two corner buttons get labels
        MatrixOrbital.Display.PositionCursor(_serialPort,28-s.Length,1);
        MatrixOrbital.Display.WriteText(_serialPort,s);
        MatrixOrbital.Display.PositionCursor(_serialPort,28-a.Length,8);
        MatrixOrbital.Display.WriteText(_serialPort,a);
    }
}
 No newline at end of file