SG12864A

Dependents:   SG12864A_TestProgram

SG12864A.cpp

Committer:
shintamainjp
Date:
2010-07-20
Revision:
1:aacd73a4e7ee
Parent:
0:238f2d048222
Child:
2:91c03e41c927

File content as of revision 1:aacd73a4e7ee:

/**
 * SG12864A Graphics LCD module driver class (Version 0.0.1)
 *
 * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
 * http://shinta.main.jp/
 */

#include "SG12864A.h"

#define setPixel(x,y) buffer[((COLUMNS * 2)* (y / 8)) + x] |= (1 << (y % 8))
#define unsetPixel(x,y) buffer[((COLUMNS * 2)* (y / 8)) + x] &= ~(1 << (y % 8))
#define swap(a,b) {int c=a;a=b;b=c;}

SG12864A::SG12864A(PinName di,
                   PinName rw,
                   PinName en,
                   PinName db0,
                   PinName db1,
                   PinName db2,
                   PinName db3,
                   PinName db4,
                   PinName db5,
                   PinName db6,
                   PinName db7,
                   PinName cs1,
                   PinName cs2,
                   PinName res)
        :
        ioDI(di),
        ioRW(rw),
        ioEN(en),
        ioDB(db0, db1, db2, db3, db4, db5, db6, db7),
        ioCS1(cs1),
        ioCS2(cs2),
        ioRES(res) {
    bufferClear();
    setDirectionToWrite();
}

SG12864A::~SG12864A() {
}

void SG12864A::bufferPush(void) {
    for (uint8_t i = 0; i < PAGES; i++) {
        // CS1
        setPageAddress(SG12864A::CS1, i);
        setColumnAddress(SG12864A::CS1, 0);
        for (uint8_t j = 0; j < COLUMNS; j++) {
            writeData(CS1, buffer[0 + ((COLUMNS * 2) * i) + j]);
        }
        // CS2
        setPageAddress(SG12864A::CS2, i);
        setColumnAddress(SG12864A::CS2, 0);
        for (uint8_t j = 0; j < COLUMNS; j++) {
            writeData(CS2, buffer[COLUMNS + ((COLUMNS * 2) * i) + j]);
        }
    }
}

void SG12864A::bufferPull(void) {
}

void SG12864A::bufferClear(void) {
    for (int i = 0; i < sizeof(buffer); i++) {
        buffer[i] = 0x00;
    }
}

void SG12864A::bufferDrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
    /*
     * Bresenham's line algorithm
     */
    bool steep = abs(y2 - y1) > abs(x2 - x1);
    if (steep) {
        swap(x1, y1);
        swap(x2, y2);
    }
    if (x1 > x2) {
        swap(x1, x2);
        swap(y1, y2);
    }
    int deltax = x2 - x1;
    int deltay = abs(y2 - y1);
    int error = deltax / 2;
    int ystep;
    int y = y1;
    if (y1 < y2) {
        ystep = 1;
    } else {
        ystep = -1;
    }
    for (int x = x1; x <= x2; x++) {
        if (steep) {
            setPixel(y,x);
        } else {
            setPixel(x,y);
        }
        error = error - deltay;
        if (error < 0) {
            y = y + ystep;
            error = error + deltax;
        }
    }
}

void SG12864A::bufferDrawBox(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
    for (int x = x1; x <= x2; x++) {
        setPixel(x, y1);
        setPixel(x, y2);
    }
    for (int y = y1; y <= y2; y++) {
        setPixel(x1, y);
        setPixel(x2, y);
    }
}

void SG12864A::bufferFillBox(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
    for (int x = x1; x <= x2; x++) {
        for (int y = y1; y <= y2; y++) {
            setPixel(x, y);
        }
    }
}

/**
 * High Level Interface.
 *
 * Reset display module.
 */
void SG12864A::reset(void) {
    reset(true);
    wait_ms(200);
    reset(false);
    wait_ms(200);

    setDisplayOnOff(SG12864A::CS1, true);
    setDisplayOnOff(SG12864A::CS2, true);
    setDisplayStartLine(SG12864A::CS1, 0);
    setDisplayStartLine(SG12864A::CS2, 0);
    setPageAddress(SG12864A::CS1, 0);
    setPageAddress(SG12864A::CS2, 0);
    setColumnAddress(SG12864A::CS1, 0);
    setColumnAddress(SG12864A::CS2, 0);
}

/**
 * High Level Interface.
 *
 * Clear display module.
 */
void SG12864A::clear(void) {
    for (uint8_t page = 0; page < PAGES; page++) {
        for (uint8_t column = 0; column < COLUMNS; column++) {
            // CS1
            setPageAddress(SG12864A::CS1, page);
            setColumnAddress(SG12864A::CS1, column);
            writeData(CS1, 0x00);
            // CS2
            setPageAddress(SG12864A::CS2, page);
            setColumnAddress(SG12864A::CS2, column);
            writeData(CS2, 0x00);
        }
    }
    // CS1
    setPageAddress(SG12864A::CS1, 0);
    setColumnAddress(SG12864A::CS1, 0);
    writeData(CS1, 0x00);
    // CS2
    setPageAddress(SG12864A::CS2, 0);
    setColumnAddress(SG12864A::CS2, 0);
    writeData(CS2, 0x00);
}

/**
 * Middle Level Interface.
 *
 * Set display on/off.
 *
 * @param t Target (CS1, CS2).
 * @param on ON/OFF (true, false).
 */
void SG12864A::setDisplayOnOff(Target t, bool on) {
    setDirectionToWrite();
    uint8_t c = 0x3e | (on ? 0x01 : 0x00);
    write(t, SG12864A::Instruction, c);
    wait_us(1);
}

/**
 * Middle Level Interface.
 *
 * Set display start line.
 *
 * @param t Target (CS1, CS2).
 * @param addr Display start line (0-63).
 */
void SG12864A::setDisplayStartLine(Target t, uint8_t addr) {
    setDirectionToWrite();
    uint8_t c = 0xc0 | (addr & 0x3f);
    write(t, SG12864A::Instruction, c);
    wait_us(1);
}

/**
 * Middle Level Interface.
 *
 * Set page address.
 *
 * @param t Target (CS1, CS2).
 * @param addr Page address(0-7).
 */
void SG12864A::setPageAddress(Target t, uint8_t addr) {
    setDirectionToWrite();
    uint8_t c = 0xb8 | (addr & 0x07);
    write(t, SG12864A::Instruction, c);
    wait_us(1);
}

/**
 * Middle Level Interface.
 *
 * Set column address.
 *
 * @param t Target. (CS1, CS2)
 * @param addr Column address (0-63).
 */
void SG12864A::setColumnAddress(Target t, uint8_t addr) {
    setDirectionToWrite();
    uint8_t c = 0x40 | (addr & 0x3f);
    write(t, SG12864A::Instruction, c);
    wait_us(1);
}

/**
 * Middle Level Interface.
 */
void SG12864A::readStatus(Target t, uint8_t *c) {
    setDirectionToRead();
    read(t, SG12864A::Instruction, c);
    wait_us(1);
}

/**
 * Middle Level Interface.
 */
void SG12864A::writeData(Target t, uint8_t c) {
    setDirectionToWrite();
    write(t, SG12864A::Data, c);
    wait_us(1);
}

/**
 * Middle Level Interface.
 */
void SG12864A::readData(Target t, uint8_t *c) {
    setDirectionToRead();
    read(t, SG12864A::Data, c);
    wait_us(1);
}

/**
 * Low Level Interface.
 */
void SG12864A::setDirectionToRead() {
    ioDB.input();
    ioRW = 1;
}

/**
 * Low Level Interface.
 */
void SG12864A::setDirectionToWrite() {
    ioDB.output();
    ioRW = 0;
}

/**
 * Low Level Interface.
 */
void SG12864A::write(Target t, Mode m, uint8_t c) {
    switch (t) {
        case CS1:
            ioCS1 = 1;
            ioCS2 = 0;
            break;
        case CS2:
            ioCS1 = 0;
            ioCS2 = 1;
            break;
    }
    switch (m) {
        case Data:
            ioDI = 1;
            break;
        case Instruction:
            ioDI = 0;
            break;
    }
    ioDB = c;
    wait_us(1);
    ioEN = 1;
    wait_us(1);
    ioEN = 0;
    wait_us(5);
}

/**
 * Low Level Interface.
 */
void SG12864A::read(Target t, Mode m, uint8_t *c) {
    // TODO
}

/**
 * Low Level Interface.
 */
void SG12864A::reset(bool b) {
    if (b) {
        ioRES = 0;
    } else {
        ioRES = 1;
    }
}