Menu

OLED - Display -Text Shift?

Help
Thomas K.
2013-02-26
2013-03-31
  • Thomas K.

    Thomas K. - 2013-02-26

    Hi,

    at first great work guys and sorry for my bad english. I have a problem to get a OLED display work correctly.
    I use a OLED - Display (EA W162-X3LG from electronic assembly) in 4bit mode. This ist similar to the WEH001602A from Winstar with the WS0010 controller. The display is connected over gpio's to the Isis-Board from Toradex with a colibri t20. A ubuntu with a 3.1.10 kernel is works well.

    After start the LCDd i can see on the display at the first line "LPT 0x378" and on the second line "HD44780 16x2" Message. After a short time the message shfited about 10 characters to the rigt and stops there for a moment  then schiftet about 4 characters back to the left. After that the message is shitet out on the left side and i see nothing. I have try to set various "Hallo"-messages but without success. If i kill the LCDd then i see on the right side "LCDproc &" and on the second line "Thanks for". I took some pictures to show you the messages.



    I use a customized version of the HD44780 drivers for GPIOs.

    //** \file server/drivers/hd44780-4bit-gpio.c
     * \c 4bit connection type of \c hd44780 driver for Hitachi HD44780 based LCD displays.
     *
     * The LCD is operated in its 4 bit-mode to be connected to GPIO lines.
     */
    #define D4_GPIO_PIN     88
    #define D5_GPIO_PIN     91
    #define D6_GPIO_PIN     94
    #define D7_GPIO_PIN     90
    #define RS_GPIO_PIN 29
    #define EN_GPIO_PIN 89
    #include "hd44780-4bit-gpio.h"
    #include "hd44780-low.h"
    #include "lpt-port.h"
    #include "port.h"
    #include "report.h"
    #include <stdio.h>
    #include <string.h>
    #include <errno.h>
    // Generally, any function that accesses the LCD control lines needs to be
    // implemented separately for each HW design. This is typically (but not
    // restricted to):
    // HD44780_senddata
    // HD44780_readkeypad
    void gpio_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char flags, unsigned char ch);
    void gpio_HD44780_backlight(PrivateData *p, unsigned char state);
    unsigned char gpio_HD44780_readkeypad(PrivateData *p, unsigned int YData);
    int gpio_HD44780_export(Driver* drvthis, int pinNr) {
        FILE* fp;
        char set_value[5]; 
        if ((fp = fopen("/sys/class/gpio/export", "ab")) == NULL) {
            report(RPT_ERR, "%s: cannot open GPIO export file: %s",
                                    drvthis->name, strerror(errno));
            return -1;
        }
        //Set pointer to begining of the file
        rewind(fp);
        //Write our value to the file
        sprintf(&set_value[0], "%d", pinNr);
        fwrite(&set_value[0], sizeof(char), strlen(set_value), fp);
        fclose(fp);
        return 0;
    }
    int gpio_HD44780_set_direction(Driver* drvthis, int pinNr, int direction) {
            FILE* fp;
        char filename[35];
            char set_value[5];
        sprintf(&filename[0], "/sys/class/gpio/gpio%d/direction", pinNr);
            if ((fp = fopen(filename, "rb+")) == NULL) {
                    report(RPT_ERR, "%s: cannot open GPIO %d direction file: %s",
                                    drvthis->name, pinNr, strerror(errno));
                    return -1;
            }
            //Set pointer to begining of the file
            rewind(fp);
            //Write our value to the file
        if (direction == 1) {
            strcpy(&set_value[0], "out");
        } else {
            strcpy(&set_value[0], "in");
        }
            fwrite(&set_value[0], sizeof(char), strlen(set_value), fp);
            fclose(fp);
            return 0;
    }
    FILE* gpio_HD44780_open_gpio(Driver* drvthis, int pinNr) {
            FILE* fp;
            char filename[35];
            sprintf(&filename[0], "/sys/class/gpio/gpio%d/value", pinNr);
            if ((fp = fopen(filename, "rb+")) == NULL) {
                    report(RPT_ERR, "%s: cannot open GPIO %d value file: %s",
                                    drvthis->name, pinNr, strerror(errno));
                    return NULL;
            }
            return fp;
    }
    void gpio_HD44780_set_gpio(FILE* fp, int state) {
        if (fp != NULL) {
            rewind(fp);
            if (state == 0) {
                fwrite("0", sizeof(char), 1, fp);
            } else {
                fwrite("1", sizeof(char), 1, fp);
            }
            fflush(fp);
        }
    }
    void gpio_HD44780_set_nibble(PrivateData* p, int nibble) {
        gpio_HD44780_set_gpio(p->gpio_line_D[0], (nibble & 0x1));
        gpio_HD44780_set_gpio(p->gpio_line_D[1], (nibble & 0x2));
        gpio_HD44780_set_gpio(p->gpio_line_D[2], (nibble & 0x4));
        gpio_HD44780_set_gpio(p->gpio_line_D[3], (nibble & 0x8));
    }
    /**
     * Initialize the driver.
     * \param drvthis  Pointer to driver structure.
     * \retval 0       Success.
     * \retval -1      Error.
     */
    int hd_init_4bit_gpio(Driver *drvthis)
    {
        PrivateData *p = (PrivateData*) drvthis->private_data;
        HD44780_functions *hd44780_functions = p->hd44780_functions;
        // Export GPIOs
        if (gpio_HD44780_export(drvthis, D4_GPIO_PIN) < 0) return -1;
        if (gpio_HD44780_export(drvthis, D5_GPIO_PIN) < 0) return -1;
        if (gpio_HD44780_export(drvthis, D6_GPIO_PIN) < 0) return -1;
        if (gpio_HD44780_export(drvthis, D7_GPIO_PIN) < 0) return -1;
        if (gpio_HD44780_export(drvthis, RS_GPIO_PIN) < 0) return -1;
        if (gpio_HD44780_export(drvthis, EN_GPIO_PIN) < 0) return -1;
            // Set all as output
            if (gpio_HD44780_set_direction(drvthis, D4_GPIO_PIN, 1) < 0) return -1;
            if (gpio_HD44780_set_direction(drvthis, D5_GPIO_PIN, 1) < 0) return -1;
            if (gpio_HD44780_set_direction(drvthis, D6_GPIO_PIN, 1) < 0) return -1;
            if (gpio_HD44780_set_direction(drvthis, D7_GPIO_PIN, 1) < 0) return -1;
            if (gpio_HD44780_set_direction(drvthis, RS_GPIO_PIN, 1) < 0) return -1;
            if (gpio_HD44780_set_direction(drvthis, EN_GPIO_PIN, 1) < 0) return -1;
        if ((p->gpio_line_D[0] = gpio_HD44780_open_gpio(drvthis, D4_GPIO_PIN)) == NULL) return -1;
        if ((p->gpio_line_D[1] = gpio_HD44780_open_gpio(drvthis, D5_GPIO_PIN)) == NULL) return -1;
        if ((p->gpio_line_D[2] = gpio_HD44780_open_gpio(drvthis, D6_GPIO_PIN)) == NULL) return -1;
        if ((p->gpio_line_D[3] = gpio_HD44780_open_gpio(drvthis, D7_GPIO_PIN)) == NULL) return -1;
        if ((p->gpio_line_RS = gpio_HD44780_open_gpio(drvthis, RS_GPIO_PIN)) == NULL) return -1;
        if ((p->gpio_line_EN = gpio_HD44780_open_gpio(drvthis, EN_GPIO_PIN)) == NULL) return -1;
        hd44780_functions->senddata = gpio_HD44780_senddata;
        hd44780_functions->backlight = gpio_HD44780_backlight;
        hd44780_functions->readkeypad = gpio_HD44780_readkeypad;
        // powerup the lcd now
            gpio_HD44780_set_gpio(p->gpio_line_EN, 0);
        gpio_HD44780_set_gpio(p->gpio_line_RS, 0);
        gpio_HD44780_set_nibble(p, 0x03);
        hd44780_functions->uPause(p, 40000); //150
        // We'll now send 0x03 a coulpe of times,
        // which is in fact (FUNCSET | IF_8BIT) >> 4
        gpio_HD44780_set_gpio(p->gpio_line_EN, 1);
        if (p->delayBus) hd44780_functions->uPause(p, 1000); // 1
        gpio_HD44780_set_gpio(p->gpio_line_EN, 0);
        hd44780_functions->uPause(p, 40000); //15000
        gpio_HD44780_set_gpio(p->gpio_line_EN, 1);
        if (p->delayBus) hd44780_functions->uPause(p, 1000); // 1
        gpio_HD44780_set_gpio(p->gpio_line_EN, 0);
        hd44780_functions->uPause(p, 10000); //5000
        gpio_HD44780_set_gpio(p->gpio_line_EN, 1);
        if (p->delayBus) hd44780_functions->uPause(p, 1000); // 1
        gpio_HD44780_set_gpio(p->gpio_line_EN, 0);
        hd44780_functions->uPause(p, 10000); //100
        gpio_HD44780_set_gpio(p->gpio_line_EN, 1);
        if (p->delayBus) hd44780_functions->uPause(p, 1000); // 1
        gpio_HD44780_set_gpio(p->gpio_line_EN, 0);
        hd44780_functions->uPause(p, 10000); //100
        // now in 8-bit mode...  set 4-bit mode
        gpio_HD44780_set_nibble(p, 0x02);
        if (p->delayBus) hd44780_functions->uPause(p, 1000); // 1
        gpio_HD44780_set_gpio(p->gpio_line_EN, 1);
        if (p->delayBus) hd44780_functions->uPause(p, 1000); // 1
        gpio_HD44780_set_gpio(p->gpio_line_EN, 0);
        hd44780_functions->uPause(p, 10000); //100
        // Set up two-line, small character (5x8) mode
        hd44780_functions->senddata(p, 0, RS_INSTR, FUNCSET | IF_4BIT | TWOLINE | SMALLCHAR);
        hd44780_functions->uPause(p, 1000);// 40
        common_init(p, IF_4BIT);
    /*  printf("\nown init\n");
        hd44780_functions->senddata(p, 0, RS_INSTR, 0x08);
        hd44780_functions->senddata(p, 0, RS_INSTR, 0x06);
    //  hd44780_functions->senddata(p, 0, RS_INSTR, 0x10);
        hd44780_functions->senddata(p, 0, RS_INSTR, 0x17);
        hd44780_functions->senddata(p, 0, RS_INSTR, 0x01);
        hd44780_functions->senddata(p, 0, RS_INSTR, 0x02);
        hd44780_functions->senddata(p, 0, RS_INSTR, 0x0C);
        printf("\nInit finish!\n");
    /*
        if (p->have_keypad) {
            // Remember which input lines are stuck
            p->stuckinputs = gpio_HD44780_readkeypad(p, 0);
        }
    */
        return 0;
    }
    /**
     * Send data or commands to the display.
     * \param p          Pointer to driver's private data structure.
     * \param displayID  ID of the display (or 0 for all) to send data to.
     * \param flags      Defines whether to end a command or data.
     * \param ch         The value to send.
     */
    void gpio_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char flags, unsigned char ch) {
        unsigned char h = (ch >> 4) & 0x0f;     // high and low nibbles
        unsigned char l = ch & 0x0f;
        if (flags == RS_INSTR) {
    //      printf("instr ");
            gpio_HD44780_set_gpio(p->gpio_line_RS, 0);
        } else {//if (flags == RS_DATA)
    //      printf("data ");
            gpio_HD44780_set_gpio(p->gpio_line_RS, 1);
        }
    //  printf("first nibble: ");
        gpio_HD44780_set_nibble(p, h);
        if (p->delayBus) p->hd44780_functions->uPause(p, 100); // 1
        gpio_HD44780_set_gpio(p->gpio_line_EN, 1);
        if (p->delayBus) p->hd44780_functions->uPause(p, 100); // 1
        gpio_HD44780_set_gpio(p->gpio_line_EN, 0);
    //  printf("second nibble: ");
        gpio_HD44780_set_nibble(p, l);
            if (p->delayBus) p->hd44780_functions->uPause(p, 100); // 1
            gpio_HD44780_set_gpio(p->gpio_line_EN, 1);
            if (p->delayBus) p->hd44780_functions->uPause(p, 10000); // 100
            gpio_HD44780_set_gpio(p->gpio_line_EN, 0);
    //  printf("done");
    }
    /**
     * Turn display backlight on or off.
     * \param p      Pointer to driver's private data structure.
     * \param state  New backlight status.
     */
    void gpio_HD44780_backlight(PrivateData *p, unsigned char state) {
    }
    /**
     * Read keypress.
     * \param p      Pointer to driver's private data structure.
     * \param YData  Bitmap of rows / lines to enable.
     * \return       Bitmap of the pressed keys.
     */
    unsigned char gpio_HD44780_readkeypad(PrivateData *p, unsigned int YData) {
    /*unsigned char readval;
        // If at most two controllers and NO backlight, 10 bits may be used
        if ((p->numDisplays <= 2) && (!p->have_backlight)) {
            port_out(p->port, ~YData & 0x003F);
            port_out(p->port + 2, (((~YData & 0x03C0) >> 6)) ^ OUTMASK);
        }
        else {
            // Else ignore D5, because it may be either backlight or EN3.
            // Note: If three displays are used, have_backlight must be
            // set to 'no' in the config.
            port_out(p->port, (~YData & 0x001F) | p->backlight_bit);
            // With at most three controllers or backlight 9 bits may be
            // used.
            if (p->numDisplays<=3) {
                port_out(p->port + 2, (((~YData & 0x01E0) >> 5)) ^ OUTMASK);
            }
        }
        if (p->delayBus) p->hd44780_functions->uPause(p, 1);
        // Read inputs
        readval = ~ port_in(p->port + 1) ^ INMASK;
        // Put port back into idle state for backlight
        port_out(p->port, p->backlight_bit);
        // And convert value back (MSB first)
        return (((readval & FAULT) / FAULT <<4) |       // pin 15
            ((readval & SELIN) / SELIN <<3) |       // pin 13
            ((readval & PAPEREND) / PAPEREND <<2) |     // pin 12
            ((readval & BUSY) / BUSY <<1) |         // pin 11
            ((readval & ACK) / ACK)) & ~p->stuckinputs; // pin 10
    */
        return 0;
    }
    

    how can I fix the fault?

     
  • Thomas K.

    Thomas K. - 2013-02-28

    Sorry for the large pictures :D



     
  • Thomas K.

    Thomas K. - 2013-02-28

     

Log in to post a comment.