Little Help?

I’m trying to get this driver for a Nokia knock-off with a PCD8544 controller working for my kids to play with. I found a driver that works for the netduino and I’m having a heck of a time porting it to Domino for some odd reason.

Pin out (LCD/Domino)
1 VCC - VBAT
2 GND - GND
3 SCE - IO9
4 RESET - IO10
5 D/C - IO8
6 SDIN - IO11 (SPI MOSI)
7 SCLK - IO13 (SPI SCK)
8 LED+ - IO6 (PWM6)

Program:

        private static Cpu.Pin RESET_PIN = Cpu.Pin.GPIO_Pin10;
        private static Cpu.Pin CS_PIN = Cpu.Pin.GPIO_Pin9;
        private static Cpu.Pin DC_PIN = Cpu.Pin.GPIO_Pin8;

        public static void Main()
        {
            Nokia_5110 LCD = new Nokia_5110(CS_PIN, PWM.Pin.PWM6, RESET_PIN, DC_PIN);
            LCD.BacklightBrightness = 100;
            LCD.DrawPoint(40, 40, true);
            LCD.DrawLine(0, 0, 48, 48, true);
            System.Threading.Thread.Sleep(-1);
        }

Class:

public class Nokia_5110
    {

        private OutputPort reset, dataMode;
        private PWM backlight;
        private SPI spi;

        public byte[] ByteMap = new byte[504];

        private uint _backlightVal = 0;
        private bool _invd = false;

        public Nokia_5110(Cpu.Pin latch, PWM.Pin backlight, Cpu.Pin reset, Cpu.Pin dataCommand)
        {
            SPI.Configuration spiConfiguration = new SPI.Configuration(
                latch,            // chip select port
                false,                 // IC is accessed when chip select is low
                0,                     // setup time 1 ms
                0,                     // hold chip select 1 ms after transfer
                false,                 // clock line is low if device is not selected
                true,                  // data is sampled at leading edge of clock
                4000,                 // clockrate is 15 MHz
                SPI.SPI_module.SPI1   // use first SPI bus
                );

            spi = new SPI(spiConfiguration);

            this.backlight = new PWM(backlight);
            this.reset = new OutputPort(reset, true);
            this.dataMode = new OutputPort(dataCommand, true);

            Initialize();
        }

        private void Initialize()
        {
            reset.Write(false);
            reset.Write(true);

            dataMode.Write(false);
            spi.Write(new byte[] { 0x21, 0xBF, 0x04, 0x14, 0x0C, 0x20, 0x0C });
            dataMode.Write(true);

            Clear();
            Refresh();
        }

        //public void WriteText(string text, bool noSpace = true)
        //{
        //    if (noSpace)
        //        foreach (char c in text.ToCharArray())
        //            spi.Write(ASCII[c - 0x20]);
        //    else
        //    {
        //        byte[] letter = new byte[6];
        //        foreach (char c in text.ToCharArray())
        //        {
        //            for (int i = 0; i < 5; i++)
        //                letter[i] = ASCII[c - 0x20][i];

        //            letter[5] = 0x00;
        //            spi.Write(letter);
        //        }

        //    }
        //}

        public bool DrawPoint(short x, short y, bool on)
        {
            if (x < 0 || x >= 84 || y < 0 || y >= 48)
                return true; // out of the range! return true to indicate failure.

            ushort index = (ushort)((x % 84) + (int)(y * 0.125) * 84);

            byte bitMask = (byte)(1 << (y % 8));

            if (on)
                ByteMap[index] |= bitMask;
            else
                ByteMap[index] &= (byte)~bitMask;

            return false; // all is good (false = no error), return false to continue
        }

        public void DrawLine(short x1, short y1, short x2, short y2, bool on)
        {
            // This is a common line drawing algorithm. Read about it here:
            // http://en.wikipedia.org/wiki/Bresenham's_line_algorithm

            short sx = (x1 < x2) ? sx = 1 : sx = -1;
            short sy = (y1 < y2) ? sy = 1 : sy = -1;

            short dx = (short)((x2 > x1) ? x2 - x1 : x1 - x2);
            short dy = (short)((y2 > x1) ? y2 - y1 : y1 - y2);

            float err = dx - dy, e2;

            // if there is an error with drawing a point or the line is finished get out of the loop!
            while (!((x1 == x2 && y1 == y2) || DrawPoint(x1, y1, on)))
            {
                e2 = 2 * err;

                if (e2 > -dy)
                {
                    err -= dy;
                    x1 += sx;
                }

                if (e2 < dx)
                {
                    err += dx;
                    y1 += sy;
                }
            }
        }

        public void DrawRectangle(short X, short Y, short width, short height, bool on, bool filled)
        {
            // this is easier to do with points instead of lines since the line algorithm isn't that great.
            // this is only best to do with points because its straight lines. 

            short xe = (short)(X + width);
            short ye = (short)(Y + height);

            if (filled)
                for (short y = Y; y != ye; y++)
                    for (short x = X; x != xe; x++)
                        DrawPoint(x, y, on);
            else
            {
                xe -= 1;
                ye -= 1;

                for (short x = X; x != xe; x++)
                    DrawPoint(x, Y, on);

                for (short x = X; x <= xe; x++)
                    DrawPoint(x, ye, on);

                for (short y = Y; y != ye; y++)
                    DrawPoint(X, y, on);

                for (short y = Y; y <= ye; y++)
                    DrawPoint(xe, y, on);
            }
        }

        public void Refresh()
        {
            spi.Write(ByteMap);
        }

        public void Clear()
        {
            ByteMap = new byte[504];
            dataMode.Write(false);
            spi.Write(new byte[] { 0x80, 0x40 });
            dataMode.Write(true);
        }

        private void Inverse(bool inverse)
        {
            _invd = inverse;
            dataMode.Write(false);
            spi.Write(inverse ? new byte[] { 0x0D } : new byte[] { 0x0C });
            dataMode.Write(true);
        }

        public bool InverseColors
        {
            get { return _invd; }
            set { Inverse(value); }
        }

        public uint BacklightBrightness
        {
            get
            { return _backlightVal; }
            set
            {
                if (value > 100)
                    value = 100;

                //backlight.SetDutyCycle(value);
                backlight.Set(72000, (byte)value);
                _backlightVal = 100;
            }
        }
    }

Original Code: [url]LCD Help needed, 16x2s are boring - Netduino 2 (and Netduino 1) - Netduino Forums

What exactly is wrong?
Have you tried it with Arduino/Netduino using existing working code (to make sure display is working)

@ Architect, screen is fine I had retested it on the Arduino before posting. Right now backlight is all I can control on the Domino so I’m guessing the issue here would be the SPI. Code is known to work on netduino but I can’t find my cable for it at the moment; besides I’d rather run it on the Domino w/ it’s faster CPU, USB & microSD

Oops, wrong code.

Do you know if your LCD is Nokia type 1 or type 2?

From the list of Pinouts(8 pins), I guessed it is type 1.
If so your knock off Nokia would not work with Nokia 5110 library!! ???
Because the Nokia 5110 is type 2, and it supposed to have 9 pins connection.

This is as much as I know about the Nokia LCD!

Sam,

He is porting the netduino code that is working with the exactly same display. And he verified that display is working with Arduino.

I am sure it is something small, but it just evades the eye. I have these moments sometimes too. :o

Lookng

@ Sam LCD is Nokia 5110 which is controlled by PCD8544; this is code for this specific screen. It [italic]does[/italic] work on other devices.

Already then! ::slight_smile:

What about the SPI configuration??

The clock speed on the Domino is higher than the clock speed on the Netduino.

Maybe the SPI clock is too high due to the higher clock speed.

Ok small steps:

  1. Try to “DrawPoint” directly instead of using offscreen buffer.
  2. Try to draw at specific location using “goto” command:

//Code from arduino lib
// gotoXY routine to position cursor 
// x - range: 0 to 84
// y - range: 0 to 5

void gotoXY(int x, int y)
{
  LcdWrite( 0, 0x80 | x);  // Column.
  LcdWrite( 0, 0x40 | y);  // Row.  

}

Wait a minute.

You forgot to “flush” out your offscreen buffer when you are done drawing:

public static void Main()
        {
            Nokia_5110 LCD = new Nokia_5110(CS_PIN, PWM.Pin.PWM6, RESET_PIN, DC_PIN);
            LCD.BacklightBrightness = 100;
            LCD.DrawPoint(40, 40, true);
            LCD.DrawLine(0, 0, 48, 48, true);

            LCD.Refresh(); //<--------------

            System.Threading.Thread.Sleep(-1);
        }

@ Architect; apparently don’t read code :-[. Everything works just fine, this driver however requires you to call .refresh(); it keeps everything in a buffer til then.

I’m just going to slink away now…thanks for the help.

Nice!!! Don’t forget to “fezzer” it when you are done! :smiley:

Later

Haha you and I keep posting the same thing & the same time. Great minds and all…

Hi Guys I have another problem in FEZ Panda II, I got a Exception when I make a new SPI, but I don’t know why this occurs…

NOTE: I am using this shield [url]http://iteadstudio.com/store/index.php?main_page=product_info&cPath=18&products_id=308[/url]


Nokia5110 lcd = new Nokia5110((Cpu.Pin)FEZ_Pin.Digital.Di12, (Cpu.Pin)FEZ_Pin.Digital.Di11, (Cpu.Pin)FEZ_Pin.Digital.Di10);

Nokia.cs:


SPI.Configuration spiConfiguration = new SPI.Configuration(
                chipSelect,            // chip select port 
                false,                 // IC is accessed when chip select is low 
                0,                     // setup time 1 ms 
                0,                     // hold chip select 1 ms after transfer 
                false,                 // clock line is low if device is not selected 
                true,                  // data is sampled at leading edge of clock 
                2000,                 // clockrate is 15 MHz 
                SPI.SPI_module.SPI1   // use first SPI bus 
                );

                _dataPort = new SPI(spiConfiguration);

Your best bet is to start a new thread.

nice!

well, actually I meant start a new topic in the forum :slight_smile: