Time to try TinyCLR

Ok, I am interested in using TinyCLR, and would like some advice on hardware. I’ve got a number of rasp Pi’s and a beaglebone black all with suitable displays, a Cobra II, Panda III, and Spider II with the 4.3 inch gadgeteer NHVN display by GHI. I have a need for a micro which will talk to another remote micro (picaxe) using a standard network interface, I’d like a 4.3 inch display, preferably being able to use that NHVN display I already have. I have a gadgeteer wired network adaptor as well, and the gadgeteer GXP adaptor as well.

Should I build this using one of the 3 GHI boards I already have (I think the GXP adaptor will allow me to use the display on the non-gadgeteer boards), or should I just spend the $300 or so and buy new? (A new 2550 module, breakout board, and the 4.3 inch display).

Thanks in advance!

John

Your are always welcome to give us your money :slight_smile: but we are providing TinyCLR to almost all devices we have ever shipped. Go ahead and try it today.

2 Likes

Hi Gus, do you happen to know if that legacy Newhaven 4.3 display i already have (Your model Display NHVN rev 1.0) can be used with the new hardware as-is? The new one is listed as capacitance enabled, can’t remember if the old one was, and the developers guide isn’t available any more…

I think you haven’t visited the new docs yet.

http://docs.ghielectronics.com/hardware/gadgeteer/modules.html

Gus, is there any plans to port Glide to TinyCLR or something similar? Glide allowed rapid development of a decent and fast GUI (G400 at least although G120 was just about usable with 4.3" but sluggish with 5.0")

I am still using this with NETMF 4.3.8 until such time as there is something for TinyCLR. An offline editor would also be ideal to create the XML files. Sad that we lost BlackdogSpark as his Glide Editor has been really handy albeit with a few bugs here and there.

1 Like

This 0.12 release has subset of WPF support. We have tested it and it seem to work beautifully fast with our latest UCM hardware. It is a bit slow on G120 but should be fine on G400. We support many controls and have keyboard working as well. I think everything you need is there but we need to document it further.

As far as window editor, we are investigating options for the future, maybe even bring back Glide. This can also be a community group effort, in case you are bored this summer :wink:

3 Likes

I hope it for soon: it’s very promising ! I test it with fez raptor + T43, but I can’t find how to use touch of t43, and/or real buttons.

1 Like

HI there - can you send me your program? I have a spider II with the 4.3 inch, I’d like to experiment along with you!

We will need @John_Brochue to help here but basically you will inject in the touch events into the system. This means you can easily create managed drivers, specifically for capacitive touch displays. It also works great when adding a resistive touch driver chip.

Like I said, it is fantastic! Just need some documentations around it.

@John_Brochue of the give us a complete example code then we can together figure out the rest. Don’t forget keyboards and buttons please.

2 Likes

My “program” is based on docs : http://docs.ghielectronics.com/software/tinyclr/tutorials/display.html

using System.Runtime.InteropServices;
using G400UI.Properties;
using GHIElectronics.TinyCLR.Devices.Display;
using GHIElectronics.TinyCLR.UI;
using GHIElectronics.TinyCLR.UI.Controls;
using GHIElectronics.TinyCLR.UI.Media;

// ReSharper disable UnusedMember.Global

namespace G400UI
{
    class Program : Application
    {
        private Program(DisplayController d) : base(d) { }

        static void Main()
        {
            // Init button


            var version = new Version(DeviceInformation.Version);
            string info = "Device: " + DeviceInformation.DeviceName + " - " + version;
            Debug.WriteLine(info);

            var displayController = DisplayController.GetDefault();
            // Enter the proper display configurations
            displayController.ApplySettings(new ParallelDisplayControllerSettings
            {

                Width = 480,
                Height = 272,
                PixelClockRate = 20 * 1000 * 1000,
                PixelPolarity = false,
                OutputEnablePolarity = true,
                OutputEnableIsFixed = false,
                HorizontalFrontPorch = 2,
                HorizontalBackPorch = 2,
                HorizontalSyncPulseWidth = 41,
                HorizontalSyncPolarity = false,
                VerticalFrontPorch = 2,
                VerticalBackPorch = 2,
                VerticalSyncPulseWidth = 10,
                VerticalSyncPolarity = false
            });

            var app = new Program(displayController);

            app.Run(CreateWindow(displayController));

            //// Some needed objects
            //var screen = Graphics.FromHdc(displayController.Hdc);
            //// Start Drawing (to memroy)
            //screen.Clear(Color.Black);
            //var brush = new SolidBrush(Color.Green);
            //var font = Resources.GetFont(Resources.FontResources.NinaB);
            //screen.DrawString(info, font, brush, 20, 20);
            //// Flush the memory to the display. This is a very fast operation.
            //screen.Flush();

        }

        private static Window CreateWindow(DisplayController displayController)
        {
            var window = new Window
            {
                Height = (int)displayController.ActiveSettings.Height,
                Width = (int)displayController.ActiveSettings.Width
            };

            window.Background = new SolidColorBrush(Color.FromRgb(0, 0, 64));

            var font = Resources.GetFont(Resources.FontResources.small);

            OnScreenKeyboard.Font = font;

            //List
            var listBox = new ListBox { Child = { Width = window.Width } };

            //Text
            for (var i = 0; i < 3; i++)
            {
                var text = new Text(font, $"Text item {i}");

                text.SetMargin(5);
                text.ForeColor = Colors.Yellow;

                listBox.Items.Add(text);
            }

            //Button
            var j = 0;
            var val = new Text(font, "Tap Me");
            var btn = new Button
            {
                Child = val,
                Width = 100
            };

            btn.SetMargin(5);
            btn.Click += (s, e) => val.TextContent = "Tap Me " + (j++).ToString();

            listBox.Items.Add(btn);

            //Textbox
            var txt = new TextBox
            {
                Font = font,
                Text = "Text Sample"
            };

            txt.SetMargin(5);
            listBox.Items.Add(txt);

            // Text
            var label = new Text
            {
                Font = font,
                TextContent = DeviceInformation.DeviceName,
                ForeColor = Colors.Yellow
            };
            listBox.Items.Add(label);

            //Setup
            window.Child = listBox;
            window.Visibility = Visibility.Visible;

            return window;

        }
    }

    public class Version
    {
        private int Major { get; }

        private int Minor { get; }

        private int Patch { get; }

        private int Build { get; }

        public Version(ulong version)
        {
            Major = (int)((version >> 48) & 0x000000000000ffff);
            Minor = (int)((version >> 32) & 0x000000000000ffff);
            Patch = (int)((version >> 16) & 0x000000000000ffff);
            Build = (int)((version >> 00) & 0x000000000000ffff);
        }

        public override string ToString()
        {
            return Major + "." + Minor + "." + Patch + "." + Build;
        }
    }
}

1 Like

You can feed both touch and button events into the system using the below two lines:

app.InputProvider.RaiseTouch(x, y, touchState, DateTime.UtcNow);
app.InputProvider.RaiseButton(btn, btnState, DateTime.UtcNow);

Where the initial events come from is up to your application. In the case of a resistive touch display, like the Display T43, you’ll have to provide a resistive touch driver to get those events as we do not have one available ourselves at the moment.

For buttons, just create a GpioPin instance on the given physical pin and subscribe to its ValueChanged event. In that handler you can call RaiseButton with the appropriate parameters.

@John_Brochue: for now, touch seems to be complicated to implement for me.
I try code below, but can’t see change control (maybe I don’t understand what right,left … behaviour is):

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using G400UI.Properties;
using GHIElectronics.TinyCLR.Devices.Display;
using GHIElectronics.TinyCLR.Devices.Gpio.Provider;
using GHIElectronics.TinyCLR.Pins;
using GHIElectronics.TinyCLR.UI;
using GHIElectronics.TinyCLR.UI.Controls;
using GHIElectronics.TinyCLR.UI.Input;
using GHIElectronics.TinyCLR.UI.Media;
using ButtonEventHandler = Bauland.Gadgeteer.ButtonEventHandler;

// ReSharper disable UnusedMember.Global

namespace G400UI
{
    class Program : Application
    {
        private static  InputProvider _inputProvider;
        private Program(DisplayController d) : base(d) { }

        
        static void Main()
        {
            // Init button

            Bauland.Gadgeteer.Button buttonLeft =
                new Bauland.Gadgeteer.Button(FEZRaptor.GpioPin.Socket13.Pin3, FEZRaptor.GpioPin.Socket13.Pin4);
            Bauland.Gadgeteer.Button buttonRight =
                new Bauland.Gadgeteer.Button(FEZRaptor.GpioPin.Socket12.Pin3, FEZRaptor.GpioPin.Socket12.Pin4);
            //Bauland.Gadgeteer.Button buttonUp =
            //    new Bauland.Gadgeteer.Button(FEZRaptor.GpioPin.Socket11.Pin3, FEZRaptor.GpioPin.Socket11.Pin4);
            Bauland.Gadgeteer.Button buttonDown =
                new Bauland.Gadgeteer.Button(FEZRaptor.GpioPin.Socket10.Pin3, FEZRaptor.GpioPin.Socket10.Pin4);

            var version = new Version(DeviceInformation.Version);
            string info = "Device: " + DeviceInformation.DeviceName + " - " + version;
            Debug.WriteLine(info);

            var displayController = DisplayController.GetDefault();
            // Enter the proper display configurations
            displayController.ApplySettings(new ParallelDisplayControllerSettings
            {

                Width = 480,
                Height = 272,
                PixelClockRate = 20 * 1000 * 1000,
                PixelPolarity = false,
                OutputEnablePolarity = true,
                OutputEnableIsFixed = false,
                HorizontalFrontPorch = 2,
                HorizontalBackPorch = 2,
                HorizontalSyncPulseWidth = 41,
                HorizontalSyncPolarity = false,
                VerticalFrontPorch = 2,
                VerticalBackPorch = 2,
                VerticalSyncPulseWidth = 10,
                VerticalSyncPolarity = false
            });

            var app = new Program(displayController);
            _inputProvider = app.InputProvider;

            buttonLeft.Pressed += Btn_Left_Pressed;
            buttonLeft.Released += Btn_Left_Released;
            buttonRight.Pressed += Btn_Right_Pressed;
            buttonRight.Released += Btn_Right_Released;
            //buttonUp.Pressed += Btn_Up_Pressed;
            //buttonUp.Released += Btn_Up_Released;
            buttonDown.Pressed += Btn_Down_Pressed;
            buttonDown.Released += Btn_Down_Released;
            
            app.Run(CreateWindow(displayController));

            //// Some needed objects
            //var screen = Graphics.FromHdc(displayController.Hdc);
            //// Start Drawing (to memroy)
            //screen.Clear(Color.Black);
            //var brush = new SolidBrush(Color.Green);
            //var font = Resources.GetFont(Resources.FontResources.NinaB);
            //screen.DrawString(info, font, brush, 20, 20);
            //// Flush the memory to the display. This is a very fast operation.
            //screen.Flush();

        }

        private static void Btn_Left_Released(object sender, Bauland.Gadgeteer.ButtonEventHandlerArgs args)
        {
            _inputProvider.RaiseButton(HardwareButton.Left, false, DateTime.UtcNow);

        }

        private static void Btn_Left_Pressed(object sender, Bauland.Gadgeteer.ButtonEventHandlerArgs args)
        {
            _inputProvider.RaiseButton(HardwareButton.Left, true, DateTime.UtcNow);
        }

        private static void Btn_Right_Released(object sender, Bauland.Gadgeteer.ButtonEventHandlerArgs args)
        {
            _inputProvider.RaiseButton(HardwareButton.Right, false, DateTime.UtcNow);

        }

        private static void Btn_Right_Pressed(object sender, Bauland.Gadgeteer.ButtonEventHandlerArgs args)
        {
            _inputProvider.RaiseButton(HardwareButton.Right, true, DateTime.UtcNow);
        }


        private static void Btn_Up_Released(object sender, Bauland.Gadgeteer.ButtonEventHandlerArgs args)
        {
            _inputProvider.RaiseButton(HardwareButton.Up, false, DateTime.UtcNow);

        }

        private static void Btn_Up_Pressed(object sender, Bauland.Gadgeteer.ButtonEventHandlerArgs args)
        {
            _inputProvider.RaiseButton(HardwareButton.Up, true, DateTime.UtcNow);
        }

        private static void Btn_Down_Released(object sender, Bauland.Gadgeteer.ButtonEventHandlerArgs args)
        {
            _inputProvider.RaiseButton(HardwareButton.Down, false, DateTime.UtcNow);

        }

        private static void Btn_Down_Pressed(object sender, Bauland.Gadgeteer.ButtonEventHandlerArgs args)
        {
            _inputProvider.RaiseButton(HardwareButton.Down, true, DateTime.UtcNow);
        }

        private static Window CreateWindow(DisplayController displayController)
        {
            var window = new Window
            {
                Height = (int)displayController.ActiveSettings.Height,
                Width = (int)displayController.ActiveSettings.Width
            };

            window.Background = new SolidColorBrush(Color.FromRgb(0, 0, 64));

            var font = Resources.GetFont(Resources.FontResources.small);

            OnScreenKeyboard.Font = font;

            //List
            var listBox = new ListBox { Child = { Width = window.Width } };

            //Text
            for (var i = 0; i < 3; i++)
            {
                var text = new Text(font, $"Text item {i}");

                text.SetMargin(5);
                text.ForeColor = Colors.Yellow;

                listBox.Items.Add(text);
            }

            //Button
            var j = 0;
            var val = new Text(font, "Tap Me");
            var btn = new Button
            {
                Child = val,
                Width = 100
            };

            btn.SetMargin(5);
            btn.Click += (s, e) => val.TextContent = "Tap Me " + (j++).ToString();

            listBox.Items.Add(btn);

            //Textbox
            var txt = new TextBox
            {
                Font = font,
                Text = "Text Sample"
            };

            txt.SetMargin(5);
            listBox.Items.Add(txt);

            // Text
            var label = new Text
            {
                Font = font,
                TextContent = DeviceInformation.DeviceName,
                ForeColor = Colors.Yellow
            };
            listBox.Items.Add(label);

            //Setup
            window.Child = listBox;
            window.Visibility = Visibility.Visible;

            return window;

        }
    }

    public class Version
    {
        private int Major { get; }

        private int Minor { get; }

        private int Patch { get; }

        private int Build { get; }

        public Version(ulong version)
        {
            Major = (int)((version >> 48) & 0x000000000000ffff);
            Minor = (int)((version >> 32) & 0x000000000000ffff);
            Patch = (int)((version >> 16) & 0x000000000000ffff);
            Build = (int)((version >> 00) & 0x000000000000ffff);
        }

        public override string ToString()
        {
            return Major + "." + Minor + "." + Patch + "." + Build;
        }
    }
}

You still have to handle the input events yourself in most cases. Only a few built in handlers exist. One such handler is the listbox. It will respond to button up and down and scroll the list. But it doesn’t render anything special for that. You can see the event by listening to the SelectionChanged event on the list box, then taking whatever action you want, like changing the color of the selected item.

1 Like

That’s why I can’t see any change on list. Thanks for this clear explanation (as Always :wink:).