Archive for the ‘Programming’ Category

NETMF and the SparkFun SerLCD

Tuesday, August 17th, 2010

Well… I’ve been spending some quality time with the .NET Micro Framework the last couple weeks. I’ve been always interested in electronics and the inner parts of devices. I even bought some Atmel AVR microcontrollers and a handful of components last year to get started with microcontrollers, but it didn’t work out (so many hobby projects, so less time…).

In May/June I discovered NETMF and I just had to try it. Embedded devices driven by C# code is just a dream come true.

So after some surfing I ordered a GHI Electronics EMX Development System to get started. Since I’m not that good at time management (and it’s holiday season with lots of social obligations) I didn’t come as far as I hoped to be. BUT… I would like to share some piece of code, though.

While working on a secret project called “BeerGuard” I created a small class to use the SparkFun SerLCD (16×2 and 20×4) with NETMF. I’m probably not the only one who has written such a class, but I’ll dump it on the Internet anyway.

Be aware that this is a quick implementation to get me started real quick. Not everything is tested and there is probably a lot of code improvement possible. I hope this might be a starting point for some people. Please don’t start bashing my coding style and please… post improvements and corrections!

using System;
using System.IO.Ports;

namespace LXIT.Hardware
{
    public sealed class SerLCD
    {
        public enum Direction { Left, Right }

        public enum DisplayType { C16L2, C16L4, C20L2, C20L4 }

        public enum Status { On, Off }

        private readonly SerialPort _serialPort;

        private readonly DisplayType _displayType;

        public SerLCD(string portName) : this(portName, DisplayType.C16L2)
        {}

        public SerLCD(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, 9600, Parity.None, 8, StopBits.One);

            _displayType = displayType;
        }

        public void ClearDisplay()
        {
            Write(new byte[] { 0xFE, 0x01 });
        }

        public void MoveCursor(Direction direction)
        {
            MoveCursor(direction, 1);
        }

        public void MoveCursor(Direction direction, int times)
        {
            byte command;

            switch (direction)
            {
                case Direction.Left: command = 0x10; break;
                case Direction.Right: command = 0x14; break;
                default: return;
            }

            for (int i = 0; i < times; i++)
            {
                Write(new byte[] { 0xFE, command });
            }
        }

        public void Open()
        {
            if (!_serialPort.IsOpen)
                _serialPort.Open();
        }

        public void SaveAsSplashScreen()
        {
            Write(new byte[] { 0x7C, 0x0A });
        }

        public void Scroll(Direction direction)
        {
            Scroll(direction, 1);
        }

        public void Scroll(Direction direction, int times)
        {
            byte command;

            switch (direction)
            {
                case Direction.Left: command = 0x18; break;
                case Direction.Right: command = 0x1C; break;
                default: return;
            }

            for (int i = 0; i < times; i++)
            {
                Write(new byte[] { 0xFE, command });
            }
        }

        public void SetBlinkingBoxCursor(Status status)
        {
            byte command;

            switch (status)
            {
                case Status.On: command = 0x0D; break;
                case Status.Off: command = 0x0C; break;
                default: return;
            }

            Write(new byte[] { 0xFE, command });
        }

        public void SetBrightness(int brightness)
        {
            if (brightness < 128 || brightness > 157)
                throw new ArgumentOutOfRangeException("brightness", "Value of brightness must be between 128-157.");

            Write(new byte[] { 0x7C, (byte)brightness });
        }

        public void SetCursorPosition(int line, int column)
        {
            if ((_displayType == DisplayType.C16L2 || _displayType == DisplayType.C16L4) && (column < 1 || column > 16))
                throw new ArgumentOutOfRangeException("column", "Column number must be between 1 and 16.");

            if ((_displayType == DisplayType.C20L2 || _displayType == DisplayType.C20L4) && (column < 1 || column > 20))
                throw new ArgumentOutOfRangeException("column", "Column number must be between 1 and 20.");

            if ((_displayType == DisplayType.C16L2 || _displayType == DisplayType.C20L2) && (line < 1 || line > 2))
                throw new ArgumentOutOfRangeException("line", "Line number must be 1 or 2.");

            if ((_displayType == DisplayType.C16L4 || _displayType == DisplayType.C20L4) && (line < 1 || line > 4))
                throw new ArgumentOutOfRangeException("line", "Line number must be between 1 and 4.");

            int[] startPos16 = { 0, 64, 16, 80 };
            int[] startPos20 = { 0, 64, 20, 84 };
            int charPos;

            switch (_displayType)
            {
                case DisplayType.C16L2:
                case DisplayType.C16L4:
                    charPos = startPos16[line - 1] + (column - 1);
                    break;
                case DisplayType.C20L2:
                case DisplayType.C20L4:
                    charPos = startPos20[line - 1] + (column - 1);
                    break;
                default:
                    return;
            }

            Write(new byte[] { 0xFE, (byte)(charPos + 0x80) });
        }

        public void SetDisplay(Status status)
        {
            byte command;

            switch (status)
            {
                case Status.On: command = 0x0C; break;
                case Status.Off: command = 0x08; break;
                default: return;
            }

            Write(new byte[] { 0xFE, command });
        }

        public void SetDisplayType(DisplayType displayType)
        {
            switch (displayType)
            {
                case DisplayType.C16L2:
                    Write(new byte[]{0x7C, 0x04}); // 16 characters
                    Write(new byte[]{0x7C, 0x06}); // 2 lines
                    break;
                case DisplayType.C16L4:
                    Write(new byte[]{0x7C, 0x04}); // 16 characters
                    Write(new byte[]{0x7C, 0x05}); // 4 lines
                    break;
                case DisplayType.C20L2:
                    Write(new byte[]{0x7C, 0x03}); // 20 characters
                    Write(new byte[]{0x7C, 0x06}); // 2 lines
                    break;
                case DisplayType.C20L4:
                    Write(new byte[]{0x7C, 0x03}); // 20 characters
                    Write(new byte[]{0x7C, 0x05}); // 4 lines
                    break;
            }
        }

        public void SetUnderlineCursor(Status status)
        {
            byte command;

            switch (status)
            {
                case Status.On: command = 0x0E; break;
                case Status.Off: command = 0x0C; break;
                default: return;
            }

            Write(new byte[] { 0xFE, command });
        }

        public void ToggleSplashScreen()
        {
            Write(new byte[] { 0x7C, 0x09 });
        }

        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);
        }
    }
}

Vici CoolStorage ported to MonoTouch

Tuesday, February 23rd, 2010

Philippe ported Vici CoolStorage to MonoTouch over the weekend. This makes Vici CoolStorage available for iPhone development using the MonoTouch framework.

Due to the lack of reflection on MonoTouch class declarations are not abstract. Classes have to be declared as concrete classes with getters and setters.

SQLite is the only supported relational database on iPhone, so Vici CoolStorage for MonoTouch only supports SQLite.

The port is still in beta, but is more or less functional. Input from beta testers is highly appreciated!

Check out the beta at the Vici CoolStorage webpage.

Vici Project support has moved to StackExchange

Wednesday, November 18th, 2009

We all love Stack Overflow, so when Joel Spolsky told the world that the platform would be made publicity available we move the Vici Project support to StackExchange.

All questions regarding Vici MVC, Vici CoolStorage, Vici Parser, Vici WinService and all other future Vici projects can be viewed and answered on http://vici.stackexchange.com.

The old http://support.viciproject.com URL will redirect you to the new support location.

iPhone development books

Sunday, June 21st, 2009

Just a list of books regarding iPhone development. It’s just for personal use. Please leave a comment with your experiences of a book (what do you like/dislike about one of the books) or when a book seems to be missing from the list.

Addison-Wesley Professional

Apress

Manning Publications Co.

O’Reilly

Wrox

Currently I’m reading “iPhone in Action” (Manning) and  I’ve had a look into “Beginning iPhone Develoment” (Apress) in the bookstore. “iPhone in Action” doesn’t seem to be a hands-on book like “Beginning iPhone Development”. I’m considering buying the PDF version of the latter, so I can switch between books/style while getting my hands dirty.

I’m looking out for the upcoming Apress books (“iPhone Games Projects” and “More iPhone 3 Development“) as they seems to cover my areas of interest.

Of course I’ve still a lot to read of the Apple documentation at the iPhone Dev Center.

Holidays are coming up. Lots of time to read or lots of time to spend outside? We’ll see what Belgian weather brings…

PS: I’ll update this post with more info, e.g. Objective-C development books. This is just a small wrap-up of some Googling about iPhone development books.

Improve website page loading with Page Speed

Friday, June 12th, 2009

Thanks to a colleague I discovered Google’s Firefox add-on Page Speed. It helps you determine what you can do to improve the loading speed of you web pages.

Page Speed needs to be used in combination with the well known Firebug add-on.

You want ASP.NET MVC? Choose Vici MVC!

Sunday, May 31st, 2009

Yesterday, Philippe Leybaert released Vici MVC 2.0. This full-blown MVC framework for building ASP.NET web applications without using WebForms is now part of the open-source Vici Project.

Philippe describes Vici Project as follows: “The idea of the Vici Project is to provide .NET developers with a collection of lightweight libraries and frameworks, and at the same time get the community involved in the development and support of these libraries.”

The first sub-project of the Vici Project to be released is Vici MVC, formerly known as ProMesh.NET. Later this week, 2 other projects will be released as well: Vici Parser (formerly LazyParser.NET/SharpTemplate.NET) and Vici CoolStorage (formerly CoolStorage.NET).

I personally use Promesh.NET/Vici.Mvc with Coolstorage.NET/Vici.CoolStorage for some months now and I really enjoy developing web applications using this powerful framework.
After getting tired of using WebForms I’m happy that I now again have full control of my application! No more ViewState’s, no more “wanna-be-events”, …

Are you a .NET web developer? Get your ass over there and try out this wonderful products!

MonoDevelop 2.0 and Mono 2.4 officially released

Wednesday, April 1st, 2009

The Mono project has announced the official release of Mono 2.4 and MonoDevelop 2.0. The new version of MonoDevelop introduces support for a long-awaited integrated debugging tool.

Full article at Ars Technica

Release notes

Wanna test it right away? Download VMWare images, LiveCD or packages at the Mono website.

Internet Explorer 8 and ASP.NET MVC 1.0 released on MIX09

Friday, March 20th, 2009

Well, well, well… Microsoft has released two new “things”…

First, you can all enjoy the official 1.0 release of ASP.NET MVC by downloading it from the Microsoft Download Center.

I must say that I’m not really thrilled about it, because I’m already enjoyng an excellent MVC framework for ASP.NET called ProMesh.NET. It’s lightweight, open source and a perfect match with the open source ORM CoolStorage.NET. Both projects will become part of the Vici Project collection of free tools.

Of course I’ll try out ASP.NET MVC, but I must say I expect it to be “too much, too heavy”. I like it to be no-nonsense and lightweight.

Second… The horror of Internet Explorer continues… Microsoft released the 8.0 version of their web browser. As a real opposer to Internet Explorer I will not install it to use as my daily web browser, but I need it to test my web applications. You want to download it and install it out of free will, please visit the Internet Explorer homepage.

GetHashCode() on a 32-bit vs a 64-bit platform

Friday, February 20th, 2009

If you compile your .NET application with the standard “Any CPU” option, it will run as a 32-bit process on a 32-bit OS and as a 64-bit process on a 64-bis process.

When you use GetHashCode() the generated hashes on the 32-bit platform will differ from the hashes on the 64-bit platform…

The solution is either to not use the GetHashCode() the way you do it, or if you can’t change the way your program works you can run it in 32-bit mode by setting the 32-bit flag in the executable’s headers using CorFlags.exe.

Set the 32-bit flag:CorFlags.exe YourApplication.exe /32BIT+

Remove the 32-bit flag:CorFlags.exe YourApplication.exe /32BIT-

More info about CoreFlags.exe on MSDN: http://msdn.microsoft.com/en-us/library/ms164699(VS.80).aspx

GetHashCode() in .NET 1.1 vs .NET 2.0

Thursday, February 19th, 2009

notepadd

When migrating GarageTV from .NET 1.1 to .NET 3.5 I ran in a “strange” problem.

It seems that there is a SearchBarrel table containing the links between keywords and posts (and some other info like keyword weight etc), so when a search is made you simply do a select using this table.

But… the keyword is hashed using String.GetHashCode() and that’s stored in the DB. Not clever it seems, because the GetHashCode() in .NET 2.0+ differs from the .NET 1.1 version.

Quote from MSDN: Prior to the .NET Framework version 2.0, the hash code provider was based on the System.Collections.IHashCodeProvider interface. Starting with version 2.0, the hash code provider is based on the System.Collections.IEqualityComparer interface.”

And for your information I’ve found an implementation of the GetHashCode() of the .NET 1.1 version, so you can use this method in .NET 2.0 projects.


Int32 HashString(String szStr)
{
ulong hash = 5381;

foreach (int ch in szStr)
{
hash = ((hash << 5) + hash) ^ (ulong)ch;
}

return (Int32)hash;
}

So… enjoy.