GHIGraphicalDemo on v4.3

Hi,
For familiarization purposes I took some code from the GHIGraphicalDemo solution and attempted to get it working on a FEZ Spider II with a DisplayT43.

This TestApp solution structure is a single .NETMF v4.3 Window application in VS2013, and consists of the following .cs files (BaseWindow, Desktop, GPIOButtonInputProvider, InfoWindow, Program, TitleBar), which are all located in the TestApp namespace. A few bitmap and font resources were added as resources. The Firmware version on the G120 is 4.3.7.10.

Exceptions occur at a number of places in the code, which I have commented as " // THIS CODE CAUSES EXCEPTION", and I have also added the exception reported in Visual Studio.

After sequencially commenting the lines of code which cause exceptions, I eventually obtain a blue bar across the top of the display with “TitleBar” in white text , and “TestApp on FEZ Spider II” in white text on the black background just below that.

Any assistance towards resolving the exceptions will be appreciated.

// Program.cs
namespace TestApp
{
    public class Program : Microsoft.SPOT.Application
    {
        public static Program program;
        public static bool TF12H = true;
	
        public static void Main()
        {
            Display.Populate(Display.GHIDisplay.DisplayT43);
            if (Display.Save())
                PowerState.RebootDevice(false);
		
            // THIS CODE CAUSES EXCEPTION
            //StartupLogo.Image = Resources.GetBitmap(Resources.BitmapResources.logo);
            //StartupLogo.X = 0;
            //StartupLogo.Y = 0;
            //StartupLogo.Save();
	    /*********************************************************
	    The thread '<No Name>' (0x2) has exited with code 0 (0x0).
                #### Exception System.Exception - CLR_E_WRONG_TYPE (1) ####
                #### Message: 
                #### Microsoft.SPOT.Bitmap::get_Width [IP: 0000] ####
                #### GHI.Processor.StartupLogo::set_Image [IP: 0007] ####
                #### TestApp.Program::Main [IP: 0018] ####
            A first chance exception of type 'System.Exception' occurred in Microsoft.SPOT.Graphics.dll
            An unhandled exception of type 'System.Exception' occurred in Microsoft.SPOT.Graphics.dll
            *********************************************************/

            Program program = new Program();

            Touch.Initialize(program);
            TouchCollectorConfiguration.CollectionMethod = CollectionMethod.Native;
            TouchCollectorConfiguration.CollectionMode = CollectionMode.InkAndGesture;

            // THIS CODE CAUSES EXCEPTION
            //TouchCollectorConfiguration.TouchMoveFrequency = 100;
	    /*********************************************************
            The thread '<No Name>' (0x2) has exited with code 0 (0x0).
                #### Exception System.ArgumentOutOfRangeException - CLR_E_OUT_OF_RANGE (1) ####
                #### Message: 
                #### Microsoft.SPOT.Touch.TouchCollectorConfiguration::SetTouchInput [IP: 0000] ####
                #### Microsoft.SPOT.Touch.TouchCollectorConfiguration::set_TouchMoveFrequency [IP: 000d] ####
                #### TestApp.Program::Main [IP: 0022] ####
            A first chance exception of type 'System.ArgumentOutOfRangeException' occurred in Microsoft.SPOT.Touch.dll
            An unhandled exception of type 'System.ArgumentOutOfRangeException' occurred in Microsoft.SPOT.Touch.dll
            *********************************************************/	    

            Desktop desktopWindow = new Desktop(program);

            // THIS CODE CAUSES EXCEPTION
            // GPIOButtonInputProvider inputProvider = new GPIOButtonInputProvider(null);
	    //==== the following is the code in GPIOButtonInputProvider.cs at which the exception occurs ===
	    // port = new InterruptPort(pin, true,
            //     Port.ResistorMode.PullUp,
            //     Port.InterruptMode.InterruptEdgeBoth);
	    /*********************************************************
            The thread '<No Name>' (0x2) has exited with code 0 (0x0).
                #### Exception System.ArgumentException - 0xfd000000 (1) ####
                #### Message: 
                #### Microsoft.SPOT.Hardware.Port::.ctor [IP: 0000] ####
                #### Microsoft.SPOT.Hardware.InputPort::.ctor [IP: 0009] ####
                #### Microsoft.SPOT.Hardware.InterruptPort::.ctor [IP: 0009] ####
                #### TestApp.GPIOButtonInputProvider+ButtonPad::.ctor [IP: 0024] ####
                #### TestApp.GPIOButtonInputProvider::.ctor [IP: 00a1] ####
                #### TestApp.Program::Main [IP: 0026] ####
            A first chance exception of type 'System.ArgumentException' occurred in Microsoft.SPOT.Hardware.dll
            An unhandled exception of type 'System.ArgumentException' occurred in Microsoft.SPOT.Hardware.dll
            *********************************************************/
	    
            // Start 
            program.Run(desktopWindow);
        }
	
    }
}

// BaseWindow.cs
namespace TestApp
{
    public abstract class BaseWindow : Window
    {
        public BaseWindow()
        {
            this.Width = SystemMetrics.ScreenWidth;
            this.Height = SystemMetrics.ScreenHeight;
            this.Visibility = Visibility.Visible;

            Buttons.Focus(this);

            this.Background = new SolidColorBrush(Color.Black);
        }

        public abstract void Exit();
    }
}

// Desktop.cs
namespace TestApp
{
    public class Desktop : Window
    {
        private Program _program;

        private BaseWindow currentWindow;

        private DispatcherOperationCallback dispatcherCallback;

        public Desktop(Program program)
        {
            _program = program;

            this.Width = SystemMetrics.ScreenWidth;
            this.Height = SystemMetrics.ScreenHeight;
            this.Visibility = Visibility.Visible;
            this.Background = new SolidColorBrush(Color.Black);
            Buttons.Focus(this);

            StackPanel panel = new StackPanel(Orientation.Vertical);

            this.Child = panel;

            currentWindow = new InfoWindow(this);
        }

        public void CloseWindow(Type type)
        {
            if (currentWindow != null && currentWindow.GetType() == type)
            {
                dispatcherCallback = new DispatcherOperationCallback(delegate(object param)
                {
                    currentWindow.Exit();
                    SetFocus();
                    return 0;
                });
                this.Dispatcher.BeginInvoke(dispatcherCallback, false);
            }
        }

        public void SetFocus()
        {
            Buttons.Focus(this);

            currentWindow = null;
        }

    }
}

// GPIOButtonInputProvider.cs
namespace TestApp
{
    public sealed class GPIOButtonInputProvider
    {
        public readonly Dispatcher Dispatcher;

        private ButtonPad[] buttons;
        private DispatcherOperationCallback callback;
        private InputProviderSite site;
        private PresentationSource source;

        public GPIOButtonInputProvider(PresentationSource source)
        {
            // Set the input source.
            this.source = source;

            // Register our object as an input source with the input manager and 
            // get back an InputProviderSite object which forwards the input 
            // report to the input manager, which then places the input in the 
            // staging area.
            site = InputManager.CurrentInputManager.RegisterInputProvider(this);

            // Create a delegate that refers to the InputProviderSite object's 
            // ReportInput method.
            callback = new DispatcherOperationCallback(delegate(object report)
                {
 #if MF_FRAMEWORK_VERSION_V3_0
                    return site.ReportInput((InputReport)report);
 #else
                    InputReportArgs args = (InputReportArgs)report;
                    return site.ReportInput(args.Device, args.Report);
 #endif
                });
            Dispatcher = Dispatcher.CurrentDispatcher;

            // Create a hardware provider.
            HardwareProvider hwProvider = new HardwareProvider();

            // Create the pins that are needed for the buttons.  Default their 
            // values for the emulator.
            Cpu.Pin pinLeft = Cpu.Pin.GPIO_Pin0;
            Cpu.Pin pinRight = Cpu.Pin.GPIO_Pin1;
            Cpu.Pin pinUp = Cpu.Pin.GPIO_Pin2;
            Cpu.Pin pinSelect = Cpu.Pin.GPIO_Pin3;
            Cpu.Pin pinDown = Cpu.Pin.GPIO_Pin4;

            // Use the hardware provider to get the pins.  If the left pin is 
            // not set, assume none of the pins are set, and set the left pin 
            // back to the default emulator value.
            if ((pinLeft = hwProvider.GetButtonPins(Button.VK_LEFT)) ==
                Cpu.Pin.GPIO_NONE)
                pinLeft = Cpu.Pin.GPIO_Pin0;
            else
            {
                pinRight = hwProvider.GetButtonPins(Button.VK_RIGHT);
                pinUp = hwProvider.GetButtonPins(Button.VK_UP);
                pinSelect = hwProvider.GetButtonPins(Button.VK_SELECT);
                pinDown = hwProvider.GetButtonPins(Button.VK_DOWN);
            }

            // Allocate button pads and assign the (emulated) hardware pins as 
            // input from specific buttons.
            ButtonPad[] buttons = new ButtonPad[]
            {
                // Associate the buttons to the pins as discovered or set above
                new ButtonPad(this, Button.VK_LEFT  , pinLeft),
                new ButtonPad(this, Button.VK_RIGHT , pinRight),
                new ButtonPad(this, Button.VK_UP    , pinUp),
                new ButtonPad(this, Button.VK_SELECT, pinSelect),
                new ButtonPad(this, Button.VK_DOWN  , pinDown),
            };

            this.buttons = buttons;
        }

        internal class ButtonPad : IDisposable
        {
            private Button button;
            private InterruptPort port;
            private GPIOButtonInputProvider sink;
            private ButtonDevice buttonDevice;

            public ButtonPad(GPIOButtonInputProvider sink, Button button,
                Cpu.Pin pin)
            {
                this.sink = sink;
                this.button = button;
 #if !MF_FRAMEWORK_VERSION_V3_0
                this.buttonDevice = InputManager.CurrentInputManager.ButtonDevice;
 #endif

                /// Do not set an InterruptPort with GPIO_NONE.
                if (pin != Cpu.Pin.GPIO_NONE)
                {
                    // When this GPIO pin is true, call the Interrupt method.
                    port = new InterruptPort(pin, true,
                        Port.ResistorMode.PullUp,
                        Port.InterruptMode.InterruptEdgeBoth);
                    port.OnInterrupt += new NativeEventHandler(this.Interrupt);
                }
            }

            protected virtual void Dispose(bool disposing)
            {
                if (disposing)
                {
                    // dispose managed resources
                    if (port != null)
                    {
                        port.Dispose();
                        port = null;
                    }
                }
                // free native resources
            }

            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }

 #if MF_FRAMEWORK_VERSION_V3_0
            void Interrupt(uint data1, uint data2, TimeSpan time)
 #else
            void Interrupt(uint data1, uint data2, DateTime time)
 #endif
            {
                RawButtonActions action = (data2 != 0) ?
                    RawButtonActions.ButtonUp : RawButtonActions.ButtonDown;

                RawButtonInputReport report = new RawButtonInputReport(
                    sink.source, time, button, action);

                // Queue the button press to the input provider site.
 #if MF_FRAMEWORK_VERSION_V3_0
                sink.Dispatcher.BeginInvoke(sink.callback, report);
 #else
                sink.Dispatcher.BeginInvoke(sink.callback, new InputReportArgs(buttonDevice, report));
 #endif
            }
        }
    }
}	

// InfoWindow.cs
namespace TestApp
{
    public class InfoWindow : BaseWindow
    {
        private Desktop _window;

        public InfoWindow(Desktop window)
        {
            _window = window;

            StackPanel panel = new StackPanel(Orientation.Vertical);

            // Titlebar
            TitleBar titleBar = new TitleBar("TitleBar");
            titleBar.HorizontalAlignment = HorizontalAlignment.Left;
            titleBar.TouchDown += TitleBarTouchDown;

            Font font = Resources.GetFont(Resources.FontResources.NinaB);

            // TextFlow component
            TextFlow textFlow = new TextFlow();
            textFlow.ScrollingStyle = ScrollingStyle.LineByLine;
            textFlow.HorizontalAlignment = HorizontalAlignment.Center;
            textFlow.VerticalAlignment = VerticalAlignment.Top;
            textFlow.TextAlignment = TextAlignment.Left;
            textFlow.SetMargin(10);
            textFlow.TextRuns.Add("TestApp on FEZ Spider II", font, Color.White);
            textFlow.TextRuns.Add(TextRun.EndOfLine);

            this.Child = panel;

            panel.Children.Add(titleBar);
            panel.Children.Add(textFlow);

            Buttons.Focus(textFlow);
        }

        private void TitleBarTouchDown(object sender, TouchEventArgs e)
        {
            if (TitleBar.TouchedClose(sender, e))
                Exit();
        }

        protected override void OnButtonDown(ButtonEventArgs e)
        {
            if (e.Button == Button.VK_SELECT)
                Exit();
        }

        public override void Exit()
        {
            this.Close();
            _window.SetFocus();
        }

    }
}

// TitleBar.cs
namespace TestApp
{
    public class TitleBar : UIElement
    {
        private static Bitmap closeBitmap;
        private Font _font;
        private string _defaultTitle;
        private Brush _brush;

        public TitleBar(string title)
        {
            this.Visibility = Visibility.Visible;
            this.Width = SystemMetrics.ScreenWidth;
            this.Height = 30;

            closeBitmap = Resources.GetBitmap(Resources.BitmapResources.btn_close);
            _font = Resources.GetFont(Resources.FontResources.NinaB);
            _brush = new SolidColorBrush(ColorUtility.ColorFromRGB(0, 81, 123));
            Title = title;
        }

        public override void OnRender(DrawingContext dc)
        {
            base.OnRender(dc);

            dc.DrawRectangle(_brush, null, 0, 0, this.Width, 30);
	    // THIS CODE CAUSES EXCEPTION
            dc.DrawImage(closeBitmap, this.Width - closeBitmap.Width, 0);
	    /*********************************************************
            The thread '<No Name>' (0x2) has exited with code 0 (0x0).
                #### Exception System.Exception - CLR_E_WRONG_TYPE (1) ####
                #### Message: 
                #### Microsoft.SPOT.Bitmap::get_Width [IP: 0000] ####
                #### TestApp.TitleBar::OnRender [IP: 0024] ####
                #### Microsoft.SPOT.Presentation.UIElement::RenderRecursive [IP: 0025] ####
                #### Microsoft.SPOT.Presentation.UIElement::RenderRecursive [IP: 0047] ####
                #### Microsoft.SPOT.Presentation.UIElement::RenderRecursive [IP: 0047] ####
                #### Microsoft.SPOT.Presentation.UIElement::RenderRecursive [IP: 0047] ####
                #### Microsoft.SPOT.Presentation.WindowManager::RenderRecursive [IP: 0005] ####
                #### Microsoft.SPOT.Dispatcher::PushFrameImpl [IP: 0054] ####
                #### Microsoft.SPOT.Dispatcher::PushFrame [IP: 001a] ####
                #### Microsoft.SPOT.Dispatcher::Run [IP: 0006] ####
                #### Microsoft.SPOT.Application::Run [IP: 0062] ####
                #### TestApp.Program::Main [IP: 0027] ####
            A first chance exception of type 'System.Exception' occurred in Microsoft.SPOT.Graphics.dll
            An exception of type 'System.Exception' occurred in Microsoft.SPOT.Graphics.dll but was not handled in user code
            *********************************************************/	    
            dc.DrawText(_defaultTitle, _font, Color.White, 10, 8);
        }

        public static bool TouchedClose(object sender, TouchEventArgs e)
        {
            int x, y;
            e.GetPosition((TitleBar)sender, 0, out x, out y);
	    // THIS CODE CAUSES EXCEPTION
            bool allow = (x >= (SystemMetrics.ScreenWidth - closeBitmap.Width) && y <= closeBitmap.Height);
	    /*********************************************************	    
            The thread '<No Name>' (0x2) has exited with code 0 (0x0).
                #### Exception System.Exception - CLR_E_WRONG_TYPE (1) ####
                #### Message: 
                #### Microsoft.SPOT.Bitmap::get_Width [IP: 0000] ####
                #### TestApp.TitleBar::TouchedClose [IP: 0017] ####
                #### TestApp.InfoWindow::TitleBarTouchDown [IP: 0005] ####
                #### Microsoft.SPOT.Presentation.UIElement::OnTouchDown [IP: 000f] ####
                #### Microsoft.SPOT.RoutedEventArgs::InvokeHandler [IP: 0029] ####
                #### Microsoft.SPOT.EventRoute::InvokeHandlers [IP: 00a3] ####
                #### Microsoft.SPOT.Presentation.UIElement::RaiseEvent [IP: 0052] ####
                #### Microsoft.SPOT.Input.InputManager::ProcessStagingArea [IP: 00a0] ####
                #### Microsoft.SPOT.Dispatcher::PushFrameImpl [IP: 0054] ####
                #### Microsoft.SPOT.Dispatcher::PushFrame [IP: 001a] ####
                #### Microsoft.SPOT.Dispatcher::Run [IP: 0006] ####
                #### Microsoft.SPOT.Application::Run [IP: 0062] ####
                #### TestApp.Program::Main [IP: 0027] ####
            A first chance exception of type 'System.Exception' occurred in Microsoft.SPOT.Graphics.dll
            An exception of type 'System.Exception' occurred in Microsoft.SPOT.Graphics.dll but was not handled in user code
            
                #### Exception System.Exception - CLR_E_WRONG_TYPE (4) ####
                #### Message: 
                #### Microsoft.SPOT.Bitmap::get_Width [IP: 0000] ####
             Uncaught exception	    
	    *********************************************************/

            return allow;
        }

        public string Title
        {
            set { _defaultTitle = value; }
            get { return _defaultTitle; }
        }
    }
}

@ Oldevel - The demo you started with is pretty old. You may want to consult https://www.ghielectronics.com/glide and https://www.ghielectronics.com/docs/315/glide to get started with Glide. Some of your errors look like they are caused by API changes between 4.1, 4.2, and 4.3. https://www.ghielectronics.com/docs and https://www.ghielectronics.com/downloads/man/Library_Documentation_v4.3/html/R_Project_NETMF_Libraries_API_Reference.htm have documentation on the current 4.3 API.

@ John - I am doing as you have suggested, thanks.

1 Like