ParallelPort Write error

When I invoke the Write method from ParallelPort the compiler inform CLR_E_INVALID_OPERATION error.

Any idea what could be wrong?

Error List:
OI
#### Exception System.InvalidOperationException - CLR_E_INVALID_OPERATION (1) ####
#### Message:
#### GHIElectronics.NETMF.Hardware.ParallelPort::Native_Write [IP: 0000] ####
#### GHIElectronics.NETMF.Hardware.ParallelPort::Write [IP: 000b] ####
#### MFConsoleApplication1.Program::Main [IP: 0051] ####
A first chance exception of type ‘System.InvalidOperationException’ occurred in GHIElectronics.NETMF.Hardware.dll
An unhandled exception of type ‘System.InvalidOperationException’ occurred in GHIElectronics.NETMF.Hardware.dll

Code:

using System;
using System.Threading;

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.Hardware;

using LCDGrafico;

namespace MFConsoleApplication1
{
    public class Program
    {
        public static void Main()
        {
            /* Definição dos Pinos de Barramento do LCD Gráfico*/
            Cpu.Pin[] DataBus = new Cpu.Pin[8] {
            (Cpu.Pin)USBizi.Pin.IO51,
            (Cpu.Pin)USBizi.Pin.IO52,
            (Cpu.Pin)USBizi.Pin.IO53,
            (Cpu.Pin)USBizi.Pin.IO54,
            (Cpu.Pin)USBizi.Pin.IO55,
            (Cpu.Pin)USBizi.Pin.IO56,
            (Cpu.Pin)USBizi.Pin.IO57,         
            (Cpu.Pin)USBizi.Pin.IO58,         
            };
            ParallelPort LCD_DataBus = new ParallelPort(DataBus, Cpu.Pin.GPIO_NONE, Cpu.Pin.GPIO_NONE);
            byte[] x = new byte[1];
            /* */
            Debug.Print("OI");

            while (true)
            {
                x[0] = 0x00;
                LCD_DataBus.Write(x, 0, 1);
                x[0] = 0x01;
                LCD_DataBus.Write(x, 0, 1);
            }
        }
    }
}

Parallel Port is a new feature, so let me ask - have you confirmed the firmware version on your device matches the SDK version you have installed on the PC?

Brett,

I review my SDK and USBIZI firmware.

SDK instalation: SDK Version 1.0.14 - April 11, 2011
• USBizi (FEZ Mini, FEZ Domino, FEZ Rhino, FEZ Panda) V 4.1.5.1
• EMX (FEZ Cobra) V 4.1.5.1, TinyBooter V 4.1.3.0
• ChipworkX V 4.1.5.1 TinyBooter V 4.1.5.1
• GHI NETMF Library V 4.1.5.0
• GHIElectronics.NETMF.W5100.Dhcp (4.1.5.1)

Deploy Tool:
HalSystemInfo.halVersion:
HalSystemInfo.halVendorInfo:
HalSystemInfo.oemCode: 0
HalSystemInfo.modelCode: 0
HalSystemInfo.skuCode: 0
HalSystemInfo.moduleSerialNumber:
HalSystemInfo.systemSerialNumber:
ClrInfo.clrVersion: 4.1.2821.0
ClrInfo.clrVendorInfo: Microsoft Copyright © Microsoft Corporation. All rig
ClrInfo.targetFrameworkVersion: 4.1.2821.0
SolutionReleaseInfo.solutionVersion: 4.1.5.1
SolutionReleaseInfo.solutionVendorInfo: GHI Electronics, LLC
SoftwareVersion.BuildDate: Apr 11 2011
SoftwareVersion.CompilerVersion: 410561
FloatingPoint: True
SourceLevelDebugging: True
ThreadCreateEx: True
LCD.Width: 0
LCD.Height: 0
LCD.BitsPerPixel: 0
AppDomains: True
ExceptionFilters: True
IncrementalDeployment: True
SoftReboot: True
Profiling: False
ProfilingAllocations: False
ProfilingCalls: False
IsUnknown: False

I can´t see what is wrong.

Some suggestion?

Are you sure it is allowed to use GOIO_NONE for RD and WR signals?

From the SDK:

This may no be very clear…It said, RD and WR pins are required and using GPIO_NONE is not allowed. However, if you are not using Read method then RD pin can be GPIO none, same for WR.

Thanks Eric,

I forgot this little detail.
Now is working ok

My code do not use the data pins [IO61, IO62, IO63, IO64, IO65, IO21, IO66, IO67]

On my test the 8 bits port is writting 4000 times per second.

I hope it’s enough to update the display ((240x64)/8)

For display, you want to try to write all pixels in one “Write” to greatly speed things up.

Gus,

After some hundred lines of code the 240x64 based on t6963c, TEXT and GRAPHICS is working.

But the speed to refresh the screen is to slow. My project depend from this.

Each byte write needs the follow sequence:


private void WriteData(char data)
        {
            //AguardaStatus(3);
            
            d[0] = (byte)data;
            LCD_DataBus.Write(d, 0, 1);

            LCD_CD.Write(LO);
            LCD_RD.Write(HI);
            LCD_WR.Write(LO);
            LCD_EN.Write(LO);
            LCD_EN.Write(HI);
        }

The write and read signal from ParallelPort pulses to LOW when one write/read operation is realized. To my use i need that the read or write signal stay on low while the lcd enable signal (LCD_EN)is changed from low to hi.
Have a way to change this behavior ?

To work arround this detail, i create my own read and write pins. Buts this consumes more time per byte.

Some ideia to increase the data write speed ?

Here is the code writted to the t6963c 240x64 pixels:


using System;
using System.Threading;

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.Hardware;

namespace SysSoft_Display
{
    class LCD
    {   
        // Constants
        /* definição de Constantes */
        private const byte BYTES_LINHA_GRAFICA = 40;
        private const byte BYTES_LINHA_TEXTO = 40;

        private const ushort INICIO_AREA_GRAFICA = 0x0000;
        private const ushort INICIO_AREA_TEXTO = (8192 - ((128 / 8) * BYTES_LINHA_TEXTO));

        private const byte SET_CURSOR_POINTER = 0x21;
        private const byte SET_OFFSET_REGISTER = 0x22;
        private const byte SET_ADDRESS_POINTER = 0x24;

        private const byte SET_TEXT_HOME_ADDRESS = 0x40;
        private const byte SET_TEXT_AREA = 0x41;
        private const byte SET_GRAPHIC_HOME_ADDRESS = 0x42;
        private const byte SET_GRAPHIC_AREA = 0x43;

        private const byte SET_MODE = 0x80;
        private const byte OR_MODE = 0x00;
        private const byte EXOR_MODE = 0x01;
        private const byte AND_MODE = 0x03;
        private const byte ATTRIBUTE_MODE = 0x04;
        private const byte INTERNAL_CG_ROM = 0x00;
        private const byte EXTERNAL_CG_RAM = 0x80;

        private const byte SET_DISPLAY_MODE = 0x90;
        private const byte BLINK_ON = 0x01;
        private const byte CURSOR_ON = 0x02;
        private const byte TEXT_ON = 0x04;
        private const byte GRAPHIC_ON = 0x08;

        private const byte AUTO_WRITE_MODE = 0xB0;
        private const byte AUTO_READ_MODE = 0xB1;
        private const byte AUTO_DISABLE_MODE = 0xB2;

        private const byte DATA_WRITE_INC = 0xC0;
        private const byte DATA_READ_INC = 0xC1;
        private const byte DATA_WRITE_DEC = 0xC2;
        private const byte DATA_READ_DEC = 0xC3;
        private const byte DATA_WRITE = 0xC4;
        private const byte DATA_READ = 0xC5;

        private const bool HI = true;
        private const bool LO = false;

        
        // Fields
        private OutputPort LCD_EN;
        private OutputPort LCD_RD;
        private OutputPort LCD_WR;
        private OutputPort LCD_CD;
        private OutputPort LCD_RST;

        private Cpu.Pin[] DataBus;
        private ParallelPort LCD_DataBus;

        private byte[] d;
        private ushort[] LINHA_LCDG;
        private byte[] TELA_ABERTURA;

        // Methods
        public void Init()
        {
            d = new byte[1];

            LINHA_LCDG = new ushort[16] {
                0x1D80, 0x1DA8, 0x1DD0, 0x1DF8,
                0x1E20, 0X1E48, 0X1E70, 0x1E98,
                0x1EC0, 0x1EE8, 0x1F10, 0x1F38,
                0x1F60, 0x1F88, 0x1FB0, 0x1FD8 };

            TELA_ABERTURA = new byte[5120] {
/*000*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
/*124*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
/*125*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
/*126*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
/*127*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };


            /* CG_ROM - OR entre TEXTO e GRÁFICO */
            WriteComand(SET_MODE | OR_MODE | INTERNAL_CG_ROM);

            /* Início da Área Gráfica */
            WriteData((char)0x00); /* 0x0000 L */
            WriteData((char)0x00); /* H */
            WriteComand(SET_GRAPHIC_HOME_ADDRESS); /* 0x42 */

            /* Número de bytes por linha gráfica */
            WriteData((char)BYTES_LINHA_GRAFICA); /* 40 L*/
            WriteData((char)0x00); /* H */
            WriteComand(SET_GRAPHIC_AREA); /* 0x43 */

            /* Início da Área Texto */
            /* RAM  -  linhas       linhas de texto */
            /* 8192 - (  128 / 8) * 40              */
            /* 8192 - 640 = 7552 */
            /* 0x1D80 */
            WriteData((char)0x80);
            WriteData((char)0x1D);
            WriteComand(SET_TEXT_HOME_ADDRESS); /* 0x42 */

            /* Número de bytes por linha texto */
            WriteData((char)BYTES_LINHA_TEXTO); /* 40 L*/
            WriteData((char)0x00); /* H */
            WriteComand(SET_TEXT_AREA); /* 0x41 */

            /* CG_ROM  - OR entre TEXTO e GRÁFICO */
            WriteComand(SET_MODE | EXOR_MODE | INTERNAL_CG_ROM); /* 0x80 */

            /* Habilita Texto e Gráfico juntos */
            WriteComand(SET_DISPLAY_MODE | TEXT_ON | GRAPHIC_ON); /* 0x9C */
        }

        // --------------------------------------------------------------------- //
        public void BuildIO()
        {
            LCD_EN = new OutputPort((Cpu.Pin)USBizi.Pin.IO69, true);
            LCD_RD = new OutputPort((Cpu.Pin)USBizi.Pin.IO68, true);
            LCD_WR = new OutputPort((Cpu.Pin)USBizi.Pin.IO67, true);
            LCD_CD = new OutputPort((Cpu.Pin)USBizi.Pin.IO66, true);
            LCD_RST = new OutputPort((Cpu.Pin)USBizi.Pin.IO7, false);

            DataBus = new Cpu.Pin[8] {
            (Cpu.Pin)USBizi.Pin.IO51,
            (Cpu.Pin)USBizi.Pin.IO52,
            (Cpu.Pin)USBizi.Pin.IO53,
            (Cpu.Pin)USBizi.Pin.IO54,
            (Cpu.Pin)USBizi.Pin.IO55,
            (Cpu.Pin)USBizi.Pin.IO56,
            (Cpu.Pin)USBizi.Pin.IO57,         
            (Cpu.Pin)USBizi.Pin.IO58,         
            };

            LCD_DataBus = new ParallelPort(DataBus, (Cpu.Pin)USBizi.Pin.IO9, (Cpu.Pin)USBizi.Pin.IO60);
        }

        // --------------------------------------------------------------------- //
        public void Reset()
        {
            LCD_RST.Write(LO);
            Delay();
            LCD_RST.Write(HI);
            Delay();
            Delay();
            Delay();
        }

        // --------------------------------------------------------------------- //
        private void Delay()
        {
            byte x;
            for (x = 0; x < 2; x++) ;
        }

        // --------------------------------------------------------------------- //
        private void AguardaStatus(byte status)
        {
            byte result = 0;
            /* */

            do
            {
                LCD_CD.Write(HI);
                LCD_RD.Write(LO);
                LCD_WR.Write(HI);
                LCD_EN.Write(LO);
                LCD_DataBus.Read(d, 0, 1);
                LCD_EN.Write(HI);

                if ((d[0] & status) == status)
                    result = 1;
                else
                    result = 0;
            } while (result == 0);
        }

        // --------------------------------------------------------------------- //
        private void WriteData(char data)
        {
            //AguardaStatus(3);
            
            d[0] = (byte)data;
            LCD_DataBus.Write(d, 0, 1);

            LCD_CD.Write(LO);
            LCD_RD.Write(HI);
            LCD_WR.Write(LO);
            LCD_EN.Write(LO);
            LCD_EN.Write(HI);
        }

        // --------------------------------------------------------------------- //

        private void WriteComand(byte command)
        {
            //AguardaStatus(3);
            
            d[0] = command;
            LCD_DataBus.Write(d, 0, 1);

            LCD_CD.Write(HI);
            LCD_RD.Write(HI);
            LCD_WR.Write(LO);
            LCD_EN.Write(LO);
            LCD_EN.Write(HI);
        }

        // --------------------------------------------------------------------- //
        private void Address_Pointer(ushort end)
        {
            AguardaStatus(3);
            WriteData((char)(end & 0x00FF));
            WriteData((char)(end >> 8));
            WriteComand(SET_ADDRESS_POINTER);
        }

        // --------------------------------------------------------------------- //
        private void WriteAutoD(char value)
        {
            AguardaStatus(3);
            WriteData(value);
        }

        // --------------------------------------------------------------------- //
        public void ClearGrafico()
        {
            ushort x;
            /* */
            Address_Pointer(INICIO_AREA_GRAFICA);
            WriteComand(AUTO_WRITE_MODE);

            for (x = 0; x < 2560 /*5120*/; x++)
                WriteAutoD((char)0x00);

            WriteComand(AUTO_DISABLE_MODE);
        }

        // --------------------------------------------------------------------- //
        public void ClearTexto()
        {
            ushort x;
            /* */
            Address_Pointer(INICIO_AREA_TEXTO);
            WriteComand(AUTO_WRITE_MODE);

            for (x = 0; x < 320 /*640*/; x++)
                WriteAutoD((char)0x00);

            WriteComand(AUTO_DISABLE_MODE);
        }

        // --------------------------------------------------------------------- //
        public void SetRowCol(byte row, byte col)
        {
            Address_Pointer((ushort)(LINHA_LCDG[row] + col));
        }

        // --------------------------------------------------------------------- //
        public void PutChar(char c)
        {
            c -= (char)0x20;
            WriteData(c);
            WriteComand(DATA_WRITE_INC); 
        }

        // --------------------------------------------------------------------- //
        public void PutString(string s)
        {
            int i;
            /* */
            for (i = 0; i < s.Length; i++)
                PutChar(s.ToCharArray(i, 1)[0]);
        }

        // --------------------------------------------------------------------- //
        public void DrawBitmap()
        {
            int j;
            /* */
            Address_Pointer(0x0000);
            WriteComand(AUTO_WRITE_MODE);
            for (j=0; j<2560; j++)
                WriteAutoD((char)TELA_ABERTURA[j]);
            WriteComand(AUTO_DISABLE_MODE);
        }
        // --------------------------------------------------------------------- //
    }
}

#define DEPURACAO

using System;
using System.Threading;

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.Hardware;

using SysSoft_Display;


namespace MFConsoleApplication1
{
    public class Program
    {
        static LCD display;
        static ushort x = 0;

        public static void Main()
        {
            display = new LCD();
            /* */

 #if DEPURACAO
            Debug.Print("OI");
 #endif
            display.BuildIO();
            display.Reset();
            display.Init();

            display.ClearGrafico();
            display.ClearTexto();

            display.DrawBitmap();

            display.ClearGrafico();
            display.ClearTexto();

            display.SetRowCol(4, 20);
            display.PutChar((char)'A');

            display.SetRowCol(0, 0);
            display.PutString("Orbisonic");

            while (true)
            {
 #if DEPURACAO
                Debug.Print(x.ToString());
                x++;
 #endif
            }
        }
    }
}

Make your own write buffer routine in RLP.

On fez touch, the display update was over a minute but then using tbd right code we had it refreshing in 0.2 seconds!