The Netduino forums have been replaced by new forums at community.wildernesslabs.co.
This site has been preserved for archival purposes only
and the ability to make new accounts or posts has been turned off.
Serial Graphic Display from Sparkfun - set of classes
I put together the classes to drive a Sparkfun serial garphic display - with a lot of help from this forum.
You use the WindowLibrary to gather a collection of windows type objects on a page. You can call up and display the pages at any time while you update the data contents of the fields in the background.
It is my first go at a C# project so it is not perfect but useable. Please comment and advise.
This class is to drive the Sparkfun with.
using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;
using System.IO.Ports;
namespace MC.Hardware.SerialGraphicLcd
{
public sealed class SGLcd
{
public enum DisplayType { H12864, H240320 } // will expand later
public enum Status { On, Off }
private readonly SerialPort _serialPort;
private readonly DisplayType _displayType;
public SGLcd(string portName)
: this(portName, DisplayType.H12864)
{ }
public SGLcd(string portName, DisplayType displayType)
{
// Defaults for SerialPort are the same as the settings for the LCD, but I'll set them explicitly
_serialPort = new SerialPort(portName, 115200, Parity.None, 8, StopBits.One);
_displayType = displayType;
}
public void DemoDisplay()
{
Write(new byte[] { 0x7C, 0x04 });
}
public void ClearDisplay()
{
Write(new byte[] { 0x7C, 0x00 });
}
// Reverse Mode
public void Reverse()
{
Write(new byte[] { 0x7C, 0x12 });
}
//Splash Screen
public void SplashScreen()
{
Write(new byte[] { 0x7C, 0x13 });
}
//Set Backlight Duty Cycle
public void BackLightDutyCycle(byte dutycycle)
{
byte[] buffer = new byte[3];
buffer[0] = 0x7c;
buffer[1] = 0x02;
buffer[2] = dutycycle;
Write(buffer);
}
//Change Baud Rate
/*
“1” = 4800bps
“2” = 9600bps
“3” = 19,200bps
“4” = 38,400bps
“5” = 57,600bps
“6” = 115,200bps
*/
public void NewBaudRate(string baud)
{
byte[] temp = new byte[3];
temp[0] = 0x7c;
temp[1] = 0x07;
temp[2] = (byte)baud[0];
Write(temp);
}
//Set X or Y Coordinates
public void GotoXY(byte x, byte y)
{
//set x first
byte[] temp = new byte[3];
temp[0] = 0x7c;
temp[1] = 0x18;
temp[2] = x;
Write(temp);
//set y
temp[0] = 0x7c;
temp[1] = 0x19;
temp[2] = y;
Write(temp);
}
//Set/Reset Pixel - x =0 to xmax, y = 0 to ymax, state = 0 or 1
public void SetPixel(byte x, byte y, byte state)
{
byte[] temp = new byte[5];
temp[0] = 0x7c;
temp[1] = 0x10;
temp[2] = x;
temp[3] = y;
temp[4] = state;
Write(temp);
}
//Draw Line x1 y1 first coords, x2 y2 second coords, state 0 = erase 1 = draw
public void DrawLine(byte x1, byte y1, byte x2, byte y2, byte state)
{
byte[] temp = new byte[7];
temp[0] = 0x7c;
temp[1] = 0x0c;
temp[2] = x1;
temp[3] = y1;
temp[4] = x2;
temp[5] = y2;
temp[6] = state;
Write(temp);
}
//Draw Circle
public void DrawCircle(byte x, byte y, byte r, byte state)
{
byte[] temp = new byte[6];
temp[0] = 0x7c;
temp[1] = 0x03;
temp[2] = x;
temp[3] = y;
temp[4] = r;
temp[5] = state;
Write(temp);
}
//Draw Box
public void DrawBox(byte x1, byte y1, byte x2, byte y2, byte state)
{
byte[] temp = new byte[7];
temp[0] = 0x7c;
temp[1] = 0x0f;
temp[2] = x1;
temp[3] = y1;
temp[4] = x2;
temp[5] = y2;
temp[6] = state;
Write(temp);
}
//Erase Block
public void EraseBlock(byte x1, byte y1, byte x2, byte y2)
{
byte[] temp = new byte[6];
temp[0] = 0x7c;
temp[1] = 0x05;
temp[2] = x1;
temp[3] = y1;
temp[4] = x2;
temp[5] = y2;
Write(temp);
}
public void Open()
{
if (!_serialPort.IsOpen)
_serialPort.Open();
}
public void Write(byte buffer)
{
Write(new[] { buffer });
}
public void Write(byte[] buffer)
{
Open();
_serialPort.Write(buffer, 0, buffer.Length);
}
public void Write(char character)
{
Write((byte)character);
}
public void Write(string text)
{
byte[] buffer = new byte[text.Length];
for (int i = 0; i < text.Length; i++)
{
buffer[i] = (byte)text[i];
}
Write(buffer);
}
public void WriteXY(byte x, byte y, string text)
{
byte[] buffer = new byte[text.Length];
for (int i = 0; i < text.Length; i++)
{
buffer[i] = (byte)text[i];
}
this.GotoXY(x, y);
Write(buffer);
}
}
}
And this one is used to create and use the screen objects on pages.
using System;
using Microsoft.SPOT;
using MC.Hardware.SerialGraphicLcd;
using System.Collections;
namespace MC.Hardware.WindowLibrary
{
public class Window
{
private readonly ArrayList widgets = new ArrayList();
private SGLcd lcd;
public Window(SGLcd Lcd)
{
lcd = Lcd;
}
public void Add(Widget widget)
{
widgets.Add(widget);
}
public void Delete(string name)
{
foreach (Widget widget in widgets)
{
if (widget != null && widget.Name == name)
{
widgets.Remove(widget);
lcd.ClearDisplay();
this.DrawAll();
}
}
}
public void DrawAll()
{
this.ForEach(w => w.Draw(lcd));
}
public Widget Search(string id)
{
Widget wid = null;
foreach (Widget widget in widgets)
{
if (widget != null && widget.Name == id)
{
wid = widget;
}
}
return (wid);
}
public delegate void WidgetAction(Widget widget);
public void ForEach(WidgetAction action)
{
foreach (Widget widget in widgets)
{
action(widget);
}
}
}
public abstract class Widget
{
public string Name { get; set; }
public byte X { get; set; }
public byte Y { get; set; }
public byte D { get; set; }
public string Text { get; set; }
protected Widget(string name, byte x, byte y, byte d, byte state, string text)
{
Name = name;
X = x;
Y = y;
D = d;
Text = text;
}
public abstract void Draw(SGLcd lcd);
}
public sealed class Circle : Widget
{
public byte Radius { get; set; }
public Circle(string name, byte x, byte y, byte radius, byte state, string text)
: base(name, x, y, radius, state, text)
{
Radius = radius;
}
public override void Draw(SGLcd lcd)
{
lcd.DrawCircle(X, Y, Radius, 1);
}
}
public sealed class Rectangle : Widget
{
public byte Width { get; set; }
public byte Height { get; set; }
public Rectangle(string name, byte x, byte y, byte width, byte height, string state)
: base(name, x, y, width, height, state)
{
Width = width;
Height = height;
}
public override void Draw(SGLcd lcd)
{
lcd.DrawBox(X, Y, Width, Height, 1);
}
}
public sealed class TextArea : Widget
{
public string Text { get; set; }
public TextArea(string name, byte x, byte y, byte d1, byte d2, string text)
: base(name, x, y, d1, d2, text)
{
Text = text;
}
public override void Draw(SGLcd lcd)
{
lcd.GotoXY(X, Y);
lcd.Write(Text);
}
}
}
And this is some silly test code.
using System.Collections;
using MC.Hardware.WindowLibrary;
using Microsoft.SPOT;
using MC.Hardware.SerialGraphicLcd;
using System.Threading;
namespace DisplayTest
{
public class Program
{
public static void Main()
{
SGLcd Screen = new SGLcd("COM1", 0);
var display = new Window(Screen);
display.Add(new Circle("circle1", 10, 10, 10,1,"text"));
display.Add(new Rectangle("rect1", 30, 40, 50, 60,"text"));
display.Add(new TextArea("text", 22, 33,0,0, "hello World"));
Screen.ClearDisplay();
display.DrawAll();
Thread.Sleep(1000);
var pageOne = new Window(Screen);
pageOne.Add(new TextArea("heading",10,10,0,0,"Page One"));
//Screen.ClearDisplay();
pageOne.DrawAll();
Thread.Sleep(1000);
var pageTwo = new Window(Screen);
pageTwo.Add(new TextArea("heading", 10, 56, 0, 0, "Page TWO"));
//Screen.ClearDisplay();
pageTwo.DrawAll();
Thread.Sleep(1000);
// Calling the display driver class directly to do some tricks
Screen.WriteXY(1, 8, pageOne.Search("heading").Text.ToString());
// retreiving some of the object information and using it to write some data from another object
var p = display.Search("rect1");
Screen.WriteXY(p.X , p.Y , pageOne.Search("heading").Text.ToString());
//advanced section I: move every widget by (20,20)
/*
display.ForEach(w =>
{
w.X += 5;
w.Y += 5;
});
*/
//advanced section II: find all circles and double their radius
/*
display.ForEach(w =>
{
var c = w as Circle;
if (c != null && c.Name == "circle1")
{
c.Radius += 5;
}
});
*/
}
}
}
crazy ol' bump
Hi Folks,
I've written some code to use the SF LCD backpack and had it working well until I found this - it's far better. Thanks!
One problem I had, and this code does the same, is each time a square is drawn a black "box" is filled in top left corner of the screen.
I've seen one other people who has also had this problem but no solution - can anyone here say they are using this code and don't suffer from this?
A clear screen makes it go away, circles and lines are all fine. Just the box...
Cheers,
Crispin
One problem I had, and this code does the same, is each time a square is drawn a black "box" is filled in top left corner of the screen.
I've seen one other people who has also had this problem but no solution - can anyone here say they are using this code and don't suffer from this?
A clear screen makes it go away, circles and lines are all fine. Just the box...
Cheers,
Crispin
Crispin,
I get the same and I have tried all kinds of tricks to get rid of the black block. I have a sneaky suspicion that it might be something in the LCD backpack code. I downloaded the code but have had no time to look at it yet.
It would seem that the cursor is put on in block mode and then turned off again after the box is drawn.
This is the last piece of code I used to generate a screen. Have a look if you use it together with my last version of the libraries and see what you get. I don't know if I updated the libraries to the forum.
Create the handles
public static SGLcd Screen = new SGLcd("COM1", 0);
public static Window winTestResults = new Window(Screen);
Hey Marius,
Thanks - awesome class btw. Saves me a lot of work
I still get the box but now it is next to your speed (tbSpeed) box. Still happen with you?
I did make some changes the other code which resets the box when it draws it. Slight issue is that it would reset any valid set ones. Seeing as I am just playing, that's ok for now.
I still get the box but now it is next to your speed (tbSpeed) box. Still happen with you?
Crispin,
Yes still the same. It only happens when you draw a rectangle and that is why I have the suspicion that it resides in the LCD backpack code. I just wrote the classes to test the display. Maybe one day I will actually use them in a project. I hate writing to screens and using keypads. They always give the same headaches and I seem to never learn how to do it properly. So when I encounter a new toy (Netduino etc), I write the stuff that will irritate me later as part of me getting to know the board. I also have not been programming for about twelve years so that was me getting into C# for the first time. I must say I love it. At the moment I have several projects running concurrently in C, C# and CPP. Luckily all on Atmel products. Oh and some VB as well.
When I have some time I will look at the Sparkfun code to see if there is a bug or not. I will keep you posted.
If at first you don't succeed, then try and try again.
Crispin,
I am busy with the same graphic lcd on the Arduino and from another forum it was very clear that there where many issues with the firmware. apparently someone has written new stuff and the latest hardware should have it installed.
This extract from the Arduino forum: http://arduino.cc/pl...Code/SerialGLCD
The library is meant to work with Jenn Holt's serialGLCD firmware found HERE It only works for the 128x64 LCD, hence this library only works with that display. This firmware fixes all the bugs in the original firmware, and features great improvements in speed.
If at first you don't succeed, then try and try again.
Miha,
No this code is for the graphic display. There are two serial drivers from Sparkfun. For this one you are refering to, there are many libraries around.
If at first you don't succeed, then try and try again.
No this code is for the graphic display. There are two serial drivers from Sparkfun. For this one you are refering to, there are many libraries around.
Oh... thanks anyway . I bought a 128x64 (not serial) one and I'm having quite some issues with it and would like to try something simpler; don't know which one to take, and it would be nice if there would be some code to go with it.
If I can suggest, get yourself the Graphic Lcd Backpack from Sparkfun and use the libraries with your display. The firmware for the graphic lcd is not that trivial and unless you need to go through that pain rather go the easy way. As I get older I am learning that no man is an island. Use what others make available and give some back in time.
If at first you don't succeed, then try and try again.
Can someone attach the entire project please?
I'm new to .Net Micro and Netduino Plus and I can't seem to get it to build properly. I keep getting these errors -
Error 1 The type 'System.IO.Ports.Parity' exists in both 'c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.dll' and 'c:\Program Files (x86)\Microsoft .NET Micro Framework\v4.1\Assemblies\be\Microsoft.SPOT.Hardware.dll' C:\Users\Phil\Documents\Visual Studio 2010\Projects\Hardware\Hardware\SerialGraphicDisplay.cs 31 60 Hardware
Error 2 The type 'System.IO.Ports.StopBits' exists in both 'c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.dll' and 'c:\Program Files (x86)\Microsoft .NET Micro Framework\v4.1\Assemblies\be\Microsoft.SPOT.Hardware.dll' C:\Users\Phil\Documents\Visual Studio 2010\Projects\Hardware\Hardware\SerialGraphicDisplay.cs 31 76 Hardware
Thanks!