simple Graphics LCD library. This Lib is used with GDM12864B 128x64 display.

Dependents:   LCD_Test

glcd.cpp

Committer:
dupuyb
Date:
2011-09-18
Revision:
0:e3bff63312e5

File content as of revision 0:e3bff63312e5:

/***********************************************************
Author: Dupuy Bruno
Date: 5 mars 2001
Version: beta
************************************************************/
#include "glcd.h"

GLCD::GLCD (PinName _DI, PinName _RW, PinName _E, PinName _CS2, PinName _CS1, BusInOut *BUSLCD):GLCD_DI(_DI),GLCD_RW(_RW),GLCD_E(_E),GLCD_CS2(_CS2),GLCD_CS1(_CS1) {
    LCD_PORT = BUSLCD;
    ready = false;
}

void GLCD::reset_pins(int val) {
    GLCD_DI = val;
    GLCD_RW = val;
    GLCD_E = val;
    GLCD_CS2 = val;
    GLCD_CS1 = val;
    LCD_PORT->output();
    LCD_PORT->write((val==0)?(0):(0xFF));
}

void GLCD::setTest(int step) {
    char* strpin[] = {"DI", "RW", "E" ,"CS2", "CS1"};
    DigitalOut* ctrl[] = {&GLCD_DI, &GLCD_RW , &GLCD_E, &GLCD_CS2, &GLCD_CS1};
    printf("\n\rScanning all lcd pins mode:%d\n\r",step);
    if (step== 0) {
        reset_pins(0);;
        printf("All pins are set to 0\n\r");
    }
    if (step > 0 && step < 6) {
        ctrl[step-1]->write(1);
        printf("Pins (%s) is set to 1\n\r", strpin[step-1]);
    }
    if (step > 5 & step < 14) {
        LCD_PORT->write((1<<(step-6)));
        printf("Pins LCD_PORT are set to value 0x%X\n\r", (1<<(step-6)));
    }
    if (step == 255) {
        reset_pins(1);;
        printf("All pins are set to 1\n\r");
    }
}

bool GLCD::isUsed() {
    return isused;
}

bool GLCD::getXor() {
    return _xor;
}
void GLCD::setXor(bool s) {
    _xor = s;
}

// Purpose:    Write a byte of data to the specified chip
// Inputs:     1) chipSelect - which chip to write the data to
//             2) data - the byte of data to write
void GLCD::writeByte(unsigned char side, unsigned char data) {
    // Choose which side to write to
    if (side == LEFT) GLCD_CS2 = 1;
    else              GLCD_CS1 = 1;
    GLCD_RW = 0; // Set for writing
    LCD_PORT->write(data); // Put the data on the port
    GLCD_E = 1;  // Pulse the enable pin
    wait_us(1);
    GLCD_E = 0;
    GLCD_CS1 = 0; // Reset the chip select lines
    GLCD_CS2 = 0;
}

// Purpose:       Reads a byte of data from the specified chip
// Ouputs:        A byte of data read from the chip
unsigned char GLCD::readByte(unsigned char side) {
    unsigned char data; // Stores the data reading in LCD
    // Choose which side to write to
    if (side == LEFT)  GLCD_CS2 = 1;
    else               GLCD_CS1 = 1;
    LCD_PORT->input(); // Set port b to input
    GLCD_RW = 1; // Set for reading
    GLCD_E = 1;
    wait_us(1);
    GLCD_E = 0; // Pulse the enable pin
    // wait_us(1);
    GLCD_E = 1;
    wait_us(1);
    data =  LCD_PORT->read(); // Get the data from the display's output register
    GLCD_E = 0;
    GLCD_CS1 = 0; // Reset the chip select lines
    GLCD_CS2 = 0;
    return data; // Return the read data
}

void GLCD::init(bool mode) {
    ready = true;
    // Initialize some pins.
    // Don't reset because GLCD_RST is connected to VDD
    // GLCD_RST = 1;
    isused = true;
    _xor = false;
    GLCD_E = 0;
    GLCD_CS1 = 0;
    GLCD_CS2 = 0;
    GLCD_DI = 0; // Set for instruction
    LCD_PORT->output();
    LCD_PORT->mode(PullDown);
    writeByte(LEFT, 0xC0); // Specify first RAM line at the top
    writeByte(RIGHT, 0xC0); // of the screen
    writeByte(LEFT, 0x40); // Set the column address to 0
    writeByte(RIGHT, 0x40);
    writeByte(LEFT, 0xB8); // Set the page address to 0
    writeByte(RIGHT, 0xB8);
    if (mode) {
        writeByte(LEFT, 0x3F); // Turn the display on
        writeByte(RIGHT, 0x3F);
    } else {
        writeByte(LEFT, 0x3E); // Turn the display off
        writeByte(RIGHT, 0x3E);
    }
    fillScreen(WHITE); // Clear the display
    repaint();
    isused = false;
}

// Purpose:       Fill the LCD screen with the passed in color.
//                Works much faster than drawing a rectangle to fill the screen.
// Inputs:        ON - turn all the pixels on
//                OFF - turn all the pixels off
void GLCD::fillScreen(bool color) {
    unsigned char data;
    char *p1, *p2;
    unsigned short i;
    p1 = left;
    p2 = right;
    data = 0xFF * color;
    for (i = 0; i < 512; ++i) {
        *p1++ = data;
        *p2++ = data;
    }
}

// Exec time 5.221ms
void GLCD::repaint() {
    int j, i;
    isused = true;
    char* p1 = left;
    char* p2 = right;
    int page = 0xB8;
    GLCD_DI = 0;                // Set for instruction
    writeByte(LEFT, 0x40);     // Set the column address to 0
    writeByte(RIGHT, 0x40);
    writeByte(LEFT, page);     // Set the page address to 0
    writeByte(RIGHT, page);
    for (j = 0; j < 8; j++, page+=1) {
        GLCD_DI = 0;
        writeByte(LEFT, page);
        writeByte(RIGHT, page);
        for (i = 0; i < 64; i++) {
            GLCD_DI = 1;
            writeByte(LEFT, *p1++);
            writeByte(RIGHT, *p2++);
        }
    }
    isused = false;
}

void GLCD::setPixel( unsigned short x,  unsigned short y, bool color) {
    char* p;
    unsigned short temp;
    bool nec;
    if (x > 127 || y > 63) return;
    temp = y / 8;
    temp *= 64;
    temp += x;
    if (x > 63)
        p = right + temp - 64;
    else
        p = left + temp;
    if (_xor)
        nec = BIT_TEST(*p, y % 8) ^ color;
    else
        nec = color;
    if (nec == BLACK)
        BIT_SET(*p, y % 8);
    else
        BIT_CLEAR(*p, y % 8);
}

bool GLCD::getPixel( unsigned short x, unsigned short y) {
    char* p;
    unsigned short temp;
    if (x > 127 || y > 63) return false;
    temp = y / 8;
    temp *= 64;
    temp += x;
    if (x > 63)
        p = right + temp - 64;
    else
        p = left + temp;
    return  BIT_TEST(*p, y % 8);
}

void GLCD::lineh( unsigned short x0,  unsigned short y0,  unsigned short x1, bool color) {
    unsigned short x;
    for (x = x0; x < x1; x++) {
        setPixel(x, y0, color);
    }
}

void GLCD::linev( unsigned short x0,  unsigned short y0,  unsigned short y1, bool color) {
    unsigned short y;
    for (y = y0; y < y1; y++) {
        setPixel(x0, y, color);
    }
}

// Purpose:       Draw a line on a graphic LCD using Bresenham's
//                line drawing algorithm
// Inputs:        (x1, y1) - the start coordinate
//                (x2, y2) - the end coordinate
//                color - ON or OFF
// Dependencies:  pixel()
void GLCD::line( unsigned short x1,  unsigned short y1,  unsigned short x2,  unsigned short y2, char dash, bool color) {
    short x, y, addx, addy, dx, dy;
    signed long P;
    short i;
    int pat = 0;
    dx = abs((short)(x2 - x1));
    dy = abs((short)(y2 - y1));
    x = x1;
    y = y1;
    if (x1 > x2)
        addx = -1;
    else
        addx = 1;
    if (y1 > y2)
        addy = -1;
    else
        addy = 1;
    if (dx >= dy) {
        P = 2 * dy - dx;
        for (i = 0; i <= dx; ++i) {
            if ( (dash & (char)(1 << pat)) != 0)
                setPixel(x, y, color);
            pat = ( (pat<7)? (pat+1): ( 0 ) );
            if (P < 0) {
                P += 2 * dy;
                x += addx;
            } else {
                P += 2 * dy - 2 * dx;
                x += addx;
                y += addy;
            }
        }
    } else {
        P = 2 * dx - dy;
        for (i = 0; i <= dy; ++i) {
            if ( (dash & (char)(1 << pat)) != 0)
                setPixel(x, y, color);
            pat = ( (pat<7)? (pat+1): ( 0 ) );
            if (P < 0) {
                P += 2 * dx;
                y += addy;
            } else {
                P += 2 * dx - 2 * dy;
                x += addx;
                y += addy;
            }
        }
    }
}

// Purpose:       Draw a rectangle on a graphic LCD
// Inputs:        (x1, y1) - the start coordinate
//                (x2, y2) - the end coordinate
//                fill  - YES or NO
//                color - ON or OFF
// Dependencies:  pixel(), line()
void GLCD::rectangle( unsigned short x1,  unsigned short y1,  unsigned short x2,  unsigned short y2, char dash, bool fill, bool color) {
    if (fill) {
        unsigned short y, ymax; // Find the y min and max
        if (y1 < y2) {
            y = y1;
            ymax = y2;
        } else {
            y = y2;
            ymax = y1;
        }
        for (; y <= ymax; ++y)
            // Draw lines to fill the rectangle
            line(x1, y, x2, y, dash, color);
    } else {
        line(x1, y1, x2, y1, dash, color); // Draw the 4 sides
        line(x1, y2, x2, y2, dash, color);
        line(x1, y1, x1, y2, dash, color);
        line(x2, y1, x2, y2, dash, color);
    }
}

// Purpose:       Draw a bar (wide line) on a graphic LCD
// Inputs:        (x1, y1) - the start coordinate
//                (x2, y2) - the end coordinate
//                width  - The number of pixels wide
//                color - ON or OFF
void GLCD::bar( unsigned short x1,  unsigned short y1,  unsigned short x2,  unsigned short y2, int width, bool color) {
    short x, y, addx, addy, j;
    int P, dx, dy, c1, c2;
    unsigned short i;
    dx = abs((short)(x2 - x1));
    dy = abs((short)(y2 - y1));
    x = x1;
    y = y1;
    c1 = -dx * x1 - dy * y1;
    c2 = -dx * x2 - dy * y2;
    if (x1 > x2) {
        addx = -1;
        c1 = -dx * x2 - dy * y2;
        c2 = -dx * x1 - dy * y1;
    } else
        addx = 1;
    if (y1 > y2) {
        addy = -1;
        c1 = -dx * x2 - dy * y2;
        c2 = -dx * x1 - dy * y1;
    } else
        addy = 1;
    if (dx >= dy) {
        P = 2 * dy - dx;
        for (i = 0; i <= dx; ++i) {
            for (j = -(width / 2); j < width
                    / 2 + width % 2; ++j) {
                if (dx * x + dy * (y + j) + c1   >= 0 && dx * x + dy   * (y + j) + c2 <= 0)
                    setPixel(x, y + j,   color);
            }
            if (P < 0) {
                P += 2 * dy;
                x += addx;
            } else {
                P += 2 * dy - 2 * dx;
                x += addx;
                y += addy;
            }
        }
    } else {
        P = 2 * dx - dy;
        for (i = 0; i <= dy; ++i) {
            if (P < 0) {
                P += 2 * dx;
                y += addy;
            } else {
                P += 2 * dx - 2 * dy;
                x += addx;
                y += addy;
            }
            for (j = -(width / 2); j < width/ 2 + width % 2; ++j) {
                if (dx * x + dy * (y + j) + c1   >= 0 && dx * x + dy   * (y + j) + c2 <= 0)
                    setPixel(x + j, y,   color);
            }
        }
    }
}

// Purpose:       Draw a circle on a graphic LCD
// Inputs:        (x,y) - the center of the circle
//                radius - the radius of the circle
//                fill - YES or NO
//                color - ON or OFF
void GLCD::circle( unsigned short x,  unsigned short y, unsigned short radius, bool fill, bool color) {
    short a, b, P;
    a = 0;
    b = radius;
    P = 1 - radius;
    do {
        if (fill) {
            line(x - a, y + b, x + a, y + b, (char)0xff, color);
            line(x - a, y - b, x + a, y - b, (char)0xff, color);
            line(x - b, y + a, x + b, y + a, (char)0xff, color);
            line(x - b, y - a, x + b, y - a, (char)0xff, color);
        } else {
            setPixel(a + x, b + y, color);
            setPixel(b + x, a + y, color);
            setPixel(x - a, b + y, color);
            setPixel(x - b, a + y, color);
            setPixel(b + x, y - a, color);
            setPixel(a + x, y - b, color);
            setPixel(x - a, y - b, color);
            setPixel(x - b, y - a, color);
        }
        if (P < 0)
            P += 3 + 2 * a++;
        else
            P += 5 + 2 * (a++ - b--);
    } while (a <= b);
}

/**
* This functions draw an
* ellipse.
*
* @param x {double} X coordinate
* @param y {double} Y coordinate
* @param a {double} Semimajor axis
* @param b {double} Semiminor axis
* @param angle {double} Angle of the ellipse
*/
unsigned short GLCD::ellipse(unsigned short x, unsigned short y,unsigned short  a, unsigned short b, float angle, unsigned short steps, bool color) {
    if (steps == 0)
        steps = 36;

    // Angle is given by Degree Value
    float beta = -angle * (PI / 180); //(Math.PI/180) converts Degree Value into Radians
    float sinbeta = sin(beta);
    float cosbeta = cos(beta);

    for (int i = 0; i < 360; i += 360 / steps) {
        float alpha = i * (PI / 180) ;
        float sinalpha = sin(alpha);
        float cosalpha = cos(alpha);

        float X = x + (a * cosalpha * cosbeta - b * sinalpha * sinbeta);
        float Y = y + (a * cosalpha * sinbeta + b * sinalpha * cosbeta);
        setPixel((int)X, (int)Y, color);

    }
   return x+a;
}

unsigned short GLCD::icon(unsigned short  xo, unsigned short  yo, const char* iconptr, bool color, bool transparency) {
    unsigned short  x, y, h, w, i=0;
    short b;
    char c;
    c = iconptr[i++]; // Codage 'H' or 'V'
    w = iconptr[i++]; // width in pixel
    h = iconptr[i++]; // height in pixel
    if (c=='V') {
        for (y=yo; y< yo + h;  y+=8) {
            for (x = xo;   x< xo + w;  x++) {
                c = iconptr[i++];
                for (b = 0; b < 8; b++) {
                    if ( (y+b)-yo < h) {
                        if (BIT_TEST(c, b))
                            setPixel(x, y+b, color);
                        else if (!transparency)
                            setPixel(x, y+b, !color);
                    }
                }
            }
        }
        return xo + w; // last x position
    }
    if (c=='H') {
        for (y=yo; y< yo + h;  y++) {
            for (x = xo;   x< xo + w;  x+=8) {
                c = iconptr[i++];
                for (b = 0; b < 8; b++) {
                    if ( (x+b)-xo < w) {
                        if (BIT_TEST(c, b))
                            setPixel(x+b, y, color);
                        else if (!transparency)
                            setPixel(x+b, y, !color);
                    }
                }
            }
        }
        return xo + w; // last x position
    }
    return xo + w; // last x position
}

// Purpose:       Write text on a graphic LCD
// Inputs:        (x,y) - The upper left coordinate of the first letter
//                textptr - A pointer to an array of text to display
//                fontptr - A pointer to font
//                size - The size of the text: 1 = 5x7, 2 = 10x14, ...
//                color - ON or OFF
//                transparency - ON or OFF
unsigned short GLCD::text( unsigned short x, unsigned short y, const char* textptr, const char* fontptr, unsigned char size, bool color, bool transparency) {
    unsigned short i, j, k, l, m = 0; // Loop counters
    int w = fontptr[0]; // width
    int h = fontptr[1]; // height
    char fc = fontptr[2]; // First char
    char lc = fontptr[3]; // Last char
    char pixData;
    // Loop through the passed string
    for (i = 0; textptr[i] != '\0'; ++i, ++x) {
        // Loop through character byte data
        for (j = 0; j < w; ++j, x += size) {
            if ( textptr[i] >= fc && textptr[i] <= lc)
                pixData = fontptr[((textptr[i] - fc) * w + j) + 4];
            else
                pixData = 0xAA; // Bad char
            // Loop through the vertical pixels
            for (k = 0; k < h; k++) {
                // Check if the pixel should be set
                if (BIT_TEST(pixData, k)) {
                    // The next two loops change the character's size
                    for (l = 0; l < size; ++l) {
                        for (m = 0; m < size; ++m) {
                            // Draws the pixel at color
                            setPixel(x + m, y + k * size + l, color);
                        }
                    }
                } else {
                    if (!transparency) {
                        for (l = 0; l < size; ++l) {
                            for (m = 0; m < size; ++m) {
                                // Draws the pixel at ~color
                                setPixel(x + m, y + k * size + l, !color);
                            }
                        }
                    }
                }
            }
        }
        // Clean gap between two caracters
        if (!transparency) {
            for (k = 0; k < h * size; ++k) {
                // Draws the pixel at ~color
                setPixel(x, y + k, !color);
            }
        }
    }
    return x + m; // last x position
}