Netduino + FT800 Eve = MicroWPF

The spare time is few, but step by step the target is getting closer.
It’s a been I’ve started playing around the FTDI FT800 Eve board, and it must admit it is awesome. If you need a quick solution to add a small touch display to your *duino board, the Eve is something you should consider.

EVE image

You know, I love Netduino and C#. That’s because I chose to play with the display using Netduino (Plus 2), and honestly I’d expected a pretty bad performance. Instead, the graphic engine of the Eve can be easily driven via SPI from any board. That is, the SPI on Netduino is fast, very fast.

My goal is creating a small library for helping many users to create small and funny home/hobby projects with the Netduino and the Eve display boards. Since I love the classic WPF, how could I avoid to inspire from them?

Micro WPF

If you know WPF, many concepts would come easier. Otherwise, I recommend to take a look to the documentation, tutorials and whatever you want. Even if you don’t harm with a PC, rather with the Windows Store/Phone APIs, the approach here isn’t too far from.
The “WPF” term for a simple Netduino is clearly abused. Here is just the visual approach, the XAML-like approach to create the UI, and -yes- the same ability to create your own controls: MeasureOverride and ArrangeOverride.
That’s not all.
If you have any visual application in mind with Netduino+Eve (e.g. a climate control, IoT client, etc), then probably you’d need some kind of navigation service across several pages. That’s the most modern UI experience, on every device: PC, tablets, and phones.

I still don’t write what the library will offer, because it’s just something made for fun: for helping hobbists and even students working with a UI on a such small board as Netduino is.
For sure, there are NOT (nor in the future):

  • data binding
  • XAML parsing (the tree has to be created programmatically)
  • styling
  • the remaining 99.99% of regular WPF…

An example of layout

The most versatile yet complex layout control is the Grid, but it seems working fine.
Let’s take this sample XAML:

<Page x:Class="WpfApplication2.Page1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"
	Title="Page1">

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="150" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="2*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <StackPanel
            Grid.Row="0"
            Grid.Column="0"
            x:Name="R0C0"
            Background="Blue"
            />

        <StackPanel
            Grid.Row="0"
            Grid.Column="1"
            x:Name="R0C1"
            Background="DarkGreen"
            />

        <StackPanel
            Grid.Row="0"
            Grid.Column="2"
            x:Name="R0C2"
            Background="Red"
            >
            <Button
                Content="Caption"
                Width="120"
                Height="30"
                Margin="10,5"
                HorizontalAlignment="Center"
                x:Name="B0"
                />
        </StackPanel>


        <StackPanel
            Grid.Row="1"
            Grid.Column="0"
            Grid.ColumnSpan="2"
            x:Name="R1C0"
            Background="LightPink"
            />


        <StackPanel
            Grid.Row="2"
            Grid.Column="1"
            Grid.ColumnSpan="2"
            x:Name="R2C1"
            Background="MediumSlateBlue"
            >
            <Button
                Content="Caption"
                Width="120"
                Height="30"
                Margin="10,5"
                HorizontalAlignment="Center"
                x:Name="B2"
                />
        </StackPanel>

    </Grid>
</Page>

On the regular WPF the result is the following:

sample-wpf

Now, let’s see how to write the same thing on Netduino:

    public class DemoPage2 : PageBase
    {
        protected override void OnCreate(FT800Device dc)
        {
            var btn_prev = new WidgetButton() { Margin = new Thickness(10, 5), Text = "Prev" };
            btn_prev.Click += new EventHandler(btn_prev_Click);

            var btn_next = new WidgetButton() { Margin = new Thickness(10, 5), Text = "Next" };
            btn_next.Click += new EventHandler(btn_next_Click);
            btn_next.HAlign = HorizontalAlignment.Center;

            var grid = new WidgetGridContainer();
            grid.Name = "GRID";

            grid.AddColumnDefinition(150);
            grid.AddColumnDefinition(1, GridUnitType.Star);
            grid.AddColumnDefinition(1, GridUnitType.Auto);

            grid.AddRowDefinition(1, GridUnitType.Star);
            grid.AddRowDefinition(2, GridUnitType.Star);
            grid.AddRowDefinition(1, GridUnitType.Auto);

            {
                var ctr = new WidgetStackContainer();
                ctr.Name = "R0C0";
                ctr.Background = Colors.Blue;
                grid.SetRowCol(ctr, 0, 0);
                grid.Children.Add(ctr);

                ctr.Children.Add(btn_prev);
            }
            {
                var ctr = new WidgetStackContainer();
                ctr.Name = "R0C1";
                ctr.Background = Colors.DarkGreen;
                grid.SetRowCol(ctr, 0, 1);
                grid.Children.Add(ctr);
            }
            {
                var ctr = new WidgetStackContainer();
                ctr.Name = "R0C2";
                ctr.Background = Colors.Red;
                grid.SetRowCol(ctr, 0, 2);
                grid.Children.Add(ctr);

                ctr.Children.Add(
                    new WidgetButton() { Name = "B0", Margin = new Thickness(10, 5) }
                    );
            }
            {
                var ctr = new WidgetStackContainer();
                ctr.Name = "R1C0";
                ctr.Background = Colors.LightPink;
                grid.SetRowCol(ctr, 1, 0, 1, 2);
                grid.Children.Add(ctr);
            }
            {
                var ctr = new WidgetStackContainer();
                ctr.Name = "R2C1";
                ctr.Background = Colors.MediumSlateBlue;
                grid.SetRowCol(ctr, 2, 1, 1, 2);
                grid.Children.Add(ctr);

                ctr.Children.Add(btn_next);
            }

            this.Content = grid;
        }

        void btn_prev_Click(object sender, EventArgs e)
        {
            NavigationService.Instance.GoBack();
        }

        void btn_next_Click(object sender, EventArgs e)
        {
            NavigationService.Instance.Navigate(new DemoPage3());
        }
    }

That leads the following snapshot:

My Snapshot5

NOTE: by live the display shows the colors correctly. However, the picture taken renders a bad result.

Widgets, widgets, widgets…

The Eve board is very well designed, because it’s plenty of useful widgets. I don’t believe you’d need something different from the provided.
At the moment of writing, the Netduino library supports:

  • (normal) Button
  • ToggleButton
  • TextBlock
  • Slider
  • Dial

and, as for the layout control:

  • StackPanel
  • Grid

As long the spare time helps me, I will try to add some other useful component as the TextBox and the Image.

Yet some screens generated by the Netduino and the FT800 Eve board.
WP_000595

My Snapshot4

My Snapshot3

My Snapshot7

Source code

I will release a beta release soon.

Advertisements

LcdBoost library for Netduino

Introduction.


This article show a concrete application of the circuit presented in my previous post.
Although the hacking is something versatile, it has been focused on driving LCD modules in general.
Here is a presentation of a small yet powerful library to simplify the graphic management, even having few memory resources.

Hardware.

There’s almost no changes from the circuit shown in my past article: just some improvement, which has been tested over two-three different kinds of LCD modules. Every time, with no problems.


For my convenience, I created the circuit on a piece of proto-board. I know, it’s not the best solution I could do, but it seems working okay. It’s easy to connect, and it leaves the Netduino pins free for further extensions.


I just added a transistor more, to drive the LCD backlight, where available. Nothing special, but it came almost for free, because luckily on the same Netduino connector there’s a PWM output also.
By the way, there’s no power supply, and most of the LCDs are using the old, faithful, +5VDC. Thus, I used a dedicated connector, using the same pinout as the *duino like connector. It means almost nothing, but it’s worthwhile keeping almost the same pinout pattern, as for convention.
Moreover, this separate power connector yields to a dedicate power supply, instead of overloading the Netduino’s embedded regulator.

Software.

Having a very fast data transfer offers the possibility to structure the library better. Abstraction is asking often a little more of memory resources, but also yields to a better integration of modules. The result is somewhat amazing, at least for a managed device as Netduino is.

First off, I wanted to separate the two layers involved in the UI: the physical and the logical. The physical layer is meant as the “driver”, which actually knows how is the LCD module, its features, and much more. The logical layer should not know anything about the hardware, instead has to organize the user’s API at best, so the user will find comfortable interacting with any display.
Of course this is just the goal: we must bear in mind that never ever will achieve a WPF-like APIs.

Secondly, I wished to offer the APIs in two flavors. Okay, the library is actually the same, but the user can choose to access the display in a imperative-way, or in a declarative-way. However, you can mix all that: no exclusivity at all.

The imperative way is the most intuitive (really?), which came from our childhood. Most of the personal computer had no enough resources, and the “do this”/”do that” programming manner became the most famous. Both the code samples contained in my old post about LCD driving with SPI, are shaped in the imperative fashion.
The declarative way is much more powerful, elegant, and -I’d add- intuitive. Instead of polluting our code with specific actions, let’s declare a bunch of “object”, which we’ll interact with. Each object has its own properties, along with methods. Isn’t sounding familiar?
Further I’ll show a small example of using the LcdBoost library, taking advantage of its declarative APIs.

How is this library made?

As stated, the library is designed to be a “satellite” project to be linked to your own application. You shouldn’t copy-and-paste modules, which leads to errors, and misalignment.
The user interact normally with the logical layer, although it can access the specific physical layer wherever some custom chip-tailored function should be performed. For instance, often the LCD modules are based on the Hitachi HD44780 chip, which offers a character pattern customization. This feature is specific for that chip, thus should be accessed directly to the driver instance.
Also, the library is meant to be improved, and extended. Both the logical and the physical layers are structured to be easily extended. Physical drivers are pluggable, and the logical graphic entities are also pluggables.
At the moment of writing this post, there’s only support for character matrix LCD modules. I’d like to drive some dot-matrix module, but I’m not sure to be able to do it.

The imperative access consists in just three methods:

        /// <summary>
        /// Clear the entire screen
        /// </summary>
        public void Clear()
        {
            // ...
        }


        /// <summary>
        /// Set the starting (reference) position
        /// to be used by any further text operation
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public void SetCursorPosition(
            int x,
            int y
            )
        {
            // ...
        }


        /// <summary>
        /// Write a text string (as plain ASCII) on the video cache
        /// </summary>
        /// <param name="text">The string to be written</param>
        /// <remarks>
        /// The text starting reference has to be set by using the <see cref="SetCursorPosition"/>.
        /// After this call, the logical position is moved accordingly
        /// </remarks>
        public void Write(string text)
        {
            // ...
        }

It’s really the minimum, and -honestly- I would not care so much, in favor of the declarative APIs (which I’m proud of!)

Okay, I’m a big fan of WPF, thus I *tried* to mimic that approach. The problem is that WPF would require *TONS* of memory, plus several parts of the regular framework, not implemented in the .Net Micro Framework.
So, the declarative API allow to operate with objects, which must implement a common interface:

namespace Toolbox.NETMF.Hardware
{
    /// <summary>
    /// Fundamental interface for implementing any graphic element
    /// to be managed in the declarative-way by the LcdBoos library
    /// </summary>
    public interface ILcdBoostElement
    {
        /// <summary>
        /// Indicates whether the graphic element is hidden or not
        /// </summary>
        bool IsHidden { get; }

        /// <summary>
        /// Renders the element's cache onto the video viewport
        /// </summary>
        /// <param name="cache">The target video cache to be filled</param>
        /// <param name="container">The parent container bounding rectangle</param>
        void Render(
            LcdBoostVideoCache cache,
            LcdBoostRect container
            );
    }
}

The library comes with just two “renderable” objects (so far):

It’s clearly limited to the character-matrix modules, but surely enough at first attempt.
Again, the LcdBoostElementCharPoint is a particular case of the more generic LcdBoostElementTextArea. It has been tailored for a single character entity, but is performing much better due the fewer calculations.

Performance.

Well, I had hard time to believe my eyes: the rendering is blazing fast. The physical driver has been improved several times, always within a compromise of performance and readability.
I must admit that the only result I have are for character matrix display, all based on the Hitachi HD44780 chip. The “practical” result is that the slowest part is surely the LCD itself, but…I mean the *real* LCD: the crystals! It looks that the crystal inertia is so huge, that you can reach 2-3 fps. At this point, the Netduino speed is a minor problem.

Anyway, here is a couple of snapshots taken with the scope.
The first one shows the overall rendering process (logic arrangement, plus physical transfer), along the timer cycle (100ms). The high-level interval is the actual busy period.


The second picture (below) is showing the physical transfer time via SPI. Since my display is a 20×4 character matrix, the transfer is accomplished on two sequential steps. The overall transfer takes less than 20 ms.

NOTE: the timing of the pictures is based on the demo game presented below.

A simple demo game.

To be attractive, a sample should be something funny.
Here is a simple pong-like game. The game itself has no meaning: using a 20×4 display is still playable with difficulty.
The interesting thing is how readable is the code, and how simple is creating even complex tasks. I’d also add that a similar approach will probably improve both efficiency, and compactness of the resulting code.
Do you have ever programmed any XNA game?
Well, the concept is quite simple: declare your resources (e.g. bitmaps, sounds, etc), then add the game logic. All the life is hanging to a “loop” which renders the game scenery. Here is the same.
Just add your ILcdBoostElement-derived elements to an array, that will be you resource-bag to be rendered. Afterward, the actual rendering will be performed automatically within a timed loop.

namespace Toolbox.NETMF.Hardware
{
    /// <summary>
    /// A demo of a simple pong-like game
    /// </summary>
    /// <remarks>
    /// The aim of the demo is demonstrating how simpler is
    /// creating even pretty complex games, by taking advantage
    /// of the declarative approach, instead of the imperative one.
    /// 
    /// The paddle is controlled by any numeric port
    /// 
    /// NOTE: although this demo can work on any lcd size,
    /// has been tailored for a 20x4 char matrix LCD module
    /// </remarks>
    class DemoPong
    {
        private const int BrickRows = 2;
        private const int BrickColumns = 16;
        private const int TotalBricks = BrickRows * BrickColumns;

        private const int AvailablePaddles = 5;

        private static LcdBoostElementCharPoint[][] _elem_bricks;
        private static LcdBoostElementTextArea _elem_paddle;
        private static LcdBoostElementTextArea _elem_score;
        private static LcdBoostElementTextArea _elem_paddles_left;
        private static LcdBoostElementCharPoint _elem_ball;
        private static LcdBoostElementTextArea _elem_gameover;

        private static Random _rnd;


        public static void Run(
            LcdBoostProxy lcd,
            NumericInput paddle)
        {
            //init the random number generator using a pseudo random seed
            _rnd = new Random(DateTime.Now.Millisecond);

            //define an array for containing all the UI-elements
            var elements = new ILcdBoostElement[TotalBricks + 6];
            var elem_count = 0;

            /**
             * Allocates the resources to be used in the program
             * this is very similar to the "sprite" approach
             **/

            //right-side wall
            var wall = new LcdBoostElementTextArea();
            wall.Text = "||||";
            wall.Bounds.Left = 16;
            wall.Bounds.Top = 0;
            wall.Bounds.Width = 1;
            wall.Bounds.Height = 4;
            elements[elem_count++] = wall;


            // ...


            /**
             * Create a new session of game.
             * The session contains only the dynamic data used
             * by the game. The logic is meant to be outside.
             * That's much like a functional approach
             **/
            var session = new GameSession();
            session.NewBall();


            /**
             * Master clock for the game refresh
             * 
             * Notice that the clock is handling the display refresh
             * at 10 fps, but the game logic has to be slowed down
             * because would be too fast to play
             **/
            int clock_counter = 0;
            var clock = new Timer(
                _ =>
                {
                    //invoke the game logic
                    Worker(
                        session,
                        clock_counter++
                        );

                    //refresh display
                    lcd.Dump(elements);
                },
                null,
                100,
                100);


            Thread.Sleep(Timeout.Infinite);
        }


        /// <summary>
        /// The game logic
        /// </summary>
        /// <param name="session"></param>
        /// <param name="clock_counter"></param>
        private static void Worker(
            GameSession session,
            int clock_counter)
        {
            //stop logic when there'are no more paddles left
            if (session.PaddlesLeft <= 0)
                return;

            //timer scaling to slow down the game logic
            if ((clock_counter & 0x07) != 0)
                return;

            //retrieve the current ball coords
            int x = _elem_ball.X;
            int y = _elem_ball.Y;

            // ...

        }


        /// <summary>
        /// 
        /// </summary>
        private class GameSession
        {
            /// <summary>
            /// Overall score
            /// </summary>
            public int Score;

            /// <summary>
            /// Paddles left
            /// </summary>
            public int PaddlesLeft = AvailablePaddles;

            /// <summary>
            /// 2D vector defining the ball speed
            /// </summary>
            public readonly Vector BallSpeed = new Vector();


            /// <summary>
            /// Init for a new incoming ball
            /// </summary>
            public void NewBall()
            {
                int n = _rnd.Next(10000);

                //gets the new ball position
                _elem_ball.X = 2 + n % 12;
                _elem_ball.Y = 0;

                //gets the new ball speed
                this.BallSpeed.DX = n < 5000 ? -1 : 1;
                this.BallSpeed.DY = 1;

                //update the paddles left box
                _elem_paddles_left.Text = "_" + this.PaddlesLeft.ToString() + "_";
            }
        }


        /// <summary>
        /// Simple class for defining a 2D vector
        /// </summary>
        private class Vector
        {
            public int DX;
            public int DY;

            public void InvertX()
            {
                this.DX = -this.DX;
            }

            public void InvertY()
            {
                this.DY = -this.DY;
            }
        }

    }
}

As seen previously, in the performance section, the rendering loop is timed to refresh the display on every 100 ms, that is 10 fps. It’s fairly poor as it were a normal video game, but it’s indeed too fast to be playable. Thus, the logic update has been scaled down of a factor of 8.

The paddle controller deserves a word of mention.

The poor-man game controller

In any decent arcade game, the controller is an important component. However, I’m not going to produce video-consoles, nor focusing on the comparison on game controllers. I just needed a quick-and-dirty way to move the paddle for my pong-like game, but…I also realized that I hadn’t anything fitting the goal.
So, I took my bag of trashy stuffs, carefully collected by my (poor) dad, and I began digging. The most obvious thing is the last to be considered: why not a normal brushed motor? My dad had dozen of small motors, so I got one of them, probably originally built on a old tape-deck.
The circuit is somewhat ridiculous: just a 1/2 voltage divider, and the motor. Okay, I’ve seen that a capacitor is a good way to get the reading more stable.


The voltage divider just creates an halfway voltage, so that the working point for the ADC is about in the middle of the range. As stated, the capacitor yields more stability to this voltage point. Finally, the motor is connected from this voltage divider, and any Netduino analog input.
When you take the motor spinning by using fingers, it works actually as a dynamo, and produces a little voltage. This voltage can be either positive or negative respect to the voltage divider point. The software samples the analog input periodically, and converts the samples accordingly.

As long you don’t get the motor spinning fast, there’s no danger at all.

Conclusions.

Once again, Netduino does it better.
It’s just another little piece of knowledge to get you working better with Netduino, and the .Net Micro Framework. Sometime the solution isn’t coming quickly as expected, but collecting experience helps a lot.

Future goals is hacking the new gaming console Netduino-based: the PIX-6T4, by Nwazet.

The library is part of the Cet Open Toolbox, and can be downloaded together with schematics and Fritzing diagrams.

Very fast SPI-to-parallel interface for Netduino

Introduction.

In my previous post about the Netduino SPI, I pointed out how to perform a faster data transfer. However, to achieve a better performance, the hardware required a pretty complex circuit, and probably most of you don’t like too much components.
This time my actual goal is to connect a normal character-matrix LCD module to my Netduino. Several times I’ve used the fantastic uLiquidCrystal library available on Codeplex, which has been improved for the 74HC595 shift-register by Szymon Kobalczyk.

So, what’s the problem on doing that?
Although that library is very well done, it has several limitations:

  • it performs the data exchange very slowly;
  • it is quite large (due to the many plugins offered);
  • the SPI port cannot shared among other devices.

Let’s analyze how the uLiquidCrystal works.

The “basic” approach.

I’ll consider only the 74HC595 version, because it is a very well-known chip, especially in the Netduino world. The 74HC595 is a serial-in/parallel-out shift-register, that allow a very easy interfacing with any SPI-enabled device, such the Netduino or the Arduino.
From the hardware perspective, the interface is pretty simple: it requires just one 74HC595 chip, and an optional transistor for the LCD backlight (not shown here).


Basically, the SPI’s master-out serial data output (MOSI) feeds the shifter input. Each bit is actually shifted thanks the master clock (SCLK), on every rising edge. Finally, this technique takes advantage of an additional SPI’s master output (SS) rising edge, to freeze a snapshot of the shift register onto the parallel outputs latch.
That’s all.
Being so intuitive, this approach suffers of serious limitations, especially about the performance. In the Netduino world (i.e. the .Net Micro Framework), the SPI is low-level driven automatically, and that’s contrary to the Arduino fashion which implies an imperative “manual” management of the outgoing stream. So, the Netduino-way is much like a “buffer-oriented” approach, while the Arduino-was is simply “byte-oriented”. The SS-pin of the Netduino SPI goes active (false in this case) at the beginning of the transfer. When the entire stream is flushed out, the SS is restored to its inactive state (i.e. true).
Since the register latch is updated thanks to the SS rising edge, it’s clear that the automatic management offered by the Netduino cannot be an advantage. Instead, the stream must be split into several one-byte blocks, getting more complex the software.
Moreover, since the low-level management of the SPI introduces a small delay before and after the transfer, it results the actual data-rate is really poor.
Let’s take an example:

using MicroLiquidCrystal;

namespace NetduinoSpiBoost
{
    public class Program
    {
        public static void Main()
        {
            //create the transfer provider
            var lcdProvider = new Shifter74Hc595LcdTransferProvider(
                SPI_Devices.SPI1,
                Pins.GPIO_PIN_D10);

            //create the LCD interface
            var lcd = new Lcd(lcdProvider);

            //define the LCD size (cols, rows)
            lcd.Begin(16, 2);

            while (true)
            {
                //clear the screen
                lcd.Clear();

                //set the text origin to the beginning of the first row
                lcd.SetCursorPosition(0, 0);
                lcd.Write("Upper row.");

                //set the text origin to the beginning of the second row
                lcd.SetCursorPosition(0, 1);
                lcd.Write("Lower row.");

                Thread.Sleep(1000);
            }
        }
    }
}

The above program does a very simple work: every second clears the LCD screen, then writes a string at the first row, and another on the second one.
Oh, yes: this program does almost nothing, but…unless the target is just to play with characters, I guess that the visual management should be a kind of “dress” over the real application running. Thus, the display driver has to be pretty lightweight and fast enough to keep the main application free to run.
Let’s take a peek at the handshake of the SPI through a single cycle (see the above example):

NOTE: the light blue trace is the SCLK, and the yellow trace is the SS.
The very basic task used in the example takes almost 100ms to complete. The Netduino must “halts” its main application for such a long time, just to output less than 20 characters.
Not so good as expected.

Netduino does it better.

Perhaps you can’t believe, but this “inability” to take advantage of the high-speed SPI, almost drove me crazy.
Damn, I just need some way to trigger the data onto the output latch, every single byte…is it possible that there’s no a decent solution?
Finally…gotcha: the Columbus’ Egg!
Here follows the new schematic, much easier than my previous one, and surely appreciated from anyone who does not like too many components!


On the LCD side, most of the lines have been reorganized. The backlight line has been taken off the circuit (later described in this article).
So, the eighth output of the 74HC595 will be free: that’s the trick!
Just consider every single byte shifted into the 74HC595 having the MSB high. As soon this bit reaches the last stage (QHh/LATCH in the schematic), it will produce a low-to-high transition useful to trigger the data onto the chip’s output latch.
That’s not enough, though.
The base shifter must be cleared (RESET), otherwise any other further high-bit shifted into the last stage will cause a spurious latch. I don’t want this.
Thus, the transistor circuit will help to solve the problem…twice!
First off, as soon the LATCH signal rises, the transistor will be polarized, thus its collector become as a “short” to the ground. Such a condition resets the 74HC595 shift register.
Secondly, when the SS in inactive (i.e. high), the transistor is polarized as well, keeping stable in the reset state the 74HC595. This allows a safe sharing of the SPI with other devices, without involving the 74HC595 at all.
This simple trick is really valuable, because it allows to take advantage of the automatic SPI management offered by the Netduino.

The handshake in the new scenario.

I think it would be pretty interesting having a look at some signal of the new circuit.
The first scope snapshot shows the eight clock pulses of the SPI “SCK” output (yellow trace), and the LATCH pulse (light blue) generated on every 8th clock rising edge. This very short pulse is enough to move the current shift register data to the output register (74HC595).

The following picture shows the same signals, but zooming the detail around the short latching pulse. Please, notice the duration of the pulse, being about 100ns.

The next screenshot is about the same LATCH pulse (light blue, even zoomed), and the consequent RESET signal derived from the inversion of the same pulse.
Notice the smooth falling and rising of the RESET signal (yellow), due to the stray capacitance. A pull-up inverter is not the best choice for nanoseconds-timings, but surely enough for a DIY circuit.

The last picture shows the overall performance of the driver.
Although the text strings are exactly the same as the original driver, the CPU-time is dramatically lesser. About 8ms versus 100ms: a 12x-speed improvement.

The LCD driver software (early stage)

Now, let’s take a look at the software.
From the application perspective, the usage of the new driver looks similar to the previous one. To compare better the two drivers’ performance, the application does the same thing on the LCD, on both cases.

using Toolbox.NETMF.Hardware;

namespace NetduinoSpiBoost
{
    public class Program
    {
        public static void Main()
        {
            //create the LCD interface
            var lcd = new LcdBoost(Pins.GPIO_PIN_D10);

            lcd.Begin(16, 2);

            lcd.Clear();
            lcd.SetCursorPosition(0, 0);
            lcd.Write("Upper row.");

            lcd.SetCursorPosition(0, 1);
            lcd.Write("Lower row.");

            while (true)
            {
                lcd.Dump();
                Thread.Sleep(1000);
            }
        }
    }
}

By the way, this time the approach is much like the “declarative-way”, instead of the “imperative-way”. Basically, the text strings are “located” on the video cache, then the physical transfer of the bytes is performed cyclically, in the main application loop. This approach allows a different view of point to treat our display, much more “WPF-like”, although the tiny Netduino cannot afford a so huge framework.
How looks the LCD driver inside?
Well, instead of posting the entire code (which is not particularly long, though), I prefer to highlight some interesting point.

First of all, the entire driver is just a class. This is far shorter than the uLiquidCrystal library, which counts over 10 modules.
The driver hosts a video cache, one byte per char, which is the actual buffer accessed when the user’s application does any operation, such as writing text, for instance. Since the LCD is character based, the size of this cache won’t be a problem.
To physically transfer the video cache to the LCD module, the main application must call the Dump method periodically. This could have been done automatically, within the driver class, using a timer or a separate thread. However, since it consists only in a trivial method call, I prefer to leave this task to be managed by the main application, in a explicit fashion. This avoids noisy thread safeguards and useless overheads.

        /// <summary>
        /// Perform the buffer transfer to the LCD module
        /// </summary>
        /// <remarks>
        /// This function resets the buffer index
        /// </remarks>
        private void Send()
        {
            //open the SPI using the specified configuration,
            //manage the buffer transfer, finally release the port
            using (var spi = new SPI(this._spiConfig))
            {
                spi.WriteRead(
                    this._buffer,
                    0,
                    this._bufferIndex,
                    this._incoming,
                    0,
                    0,
                    0);
            }

            //reset buffer index
            this._bufferIndex = 0;
        }

The physical transfer is actually managed by the Send method, which is a private member of the driver class. This because the video cache contains the character to be displayed, but the external hardware needs an encoding on the outgoing stream. For instance, the eighth bit (MSB) must be always “true”. Then it must be taken in account the LCD module chip (HD44780) handshake, because it works on a 4-bit bus mode.
Thus, the video cache (better, any required command) is encoded on a secondary buffer. This buffer is the actual outgoing stream managed by the SPI.

The physical transfer

I guess that the Send method deserves some additional consideration.
First off, the SPI device is instantiated specifically for the buffer transfer, then it is released. This allows an easy sharing of the SPI for other devices connected on the same wires.
Secondly, despite there’s no any data incoming, the .Net Micro Framework defined WriteRead method offers a better chance to perform a stream transfer. Since the alternative Write (only) method requires the exact buffer to be sent, every time the driver should create a byte-array, then trash it after the transfer. This leads to an unnecessary (and costing) background work for the garbage collector. A better approach is to keep a fixed-length byte-array in the driver, and counting how many bytes should be actually sent. The WriteRead method offers this kind of usage.

The backlight driver

The backlight driver is not included in the driver, because I think has no direct relation with the data to display.
The LCD module I’ve used has no backlight, for instance. Furthermore, the backlight is a set of leds, connected in series or in parallel. The proper driver could vary from module and module, thus is not worthwhile inserting any kind of management in this class.
A feasible idea about the backlight driver, could be to dim it by using any of the PWM outputs available on the Netduino.

Conclusions

Often the Netduino is considered too slow to perform certain operations.
Well, here is a very simple solution to take advantage of the best “hidden” features of this nice board. Simple hackings and smart software can lead you Netudino several satisfactions.
At the moment the driver is still in an early stage, but fully working.

The LcdBoost driver libary is part of the .NET Micro Framework Toolbox on CodePlex.