An mbed library for the Embedded Artists QVGA OLED 2.8 inch panel
EAQVGAOLED.cpp
- Committer:
- gbloice
- Date:
- 2011-03-09
- Revision:
- 5:b3f5d19945ff
- Parent:
- 0:ae3d20db48fc
File content as of revision 5:b3f5d19945ff:
/* mbed library for driving the EA QVGA 2.8" OLED * Copyright (c) Graham Bloice 2011 * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "EAQVGAOLED.h" #include "mbed.h" // Constants const unsigned int EAQVGAOLED_ID = 0x63D6; // The display controller ID // Local functions inline void orderCoords ( const uint16_t x0, const uint16_t y0, const uint16_t x1, const uint16_t y1, uint16_t &startX, uint16_t &startY, uint16_t &endX, uint16_t &endY ) { // Order the drawing co-ords if (x1 > x0) { startX = x0; endX = x1; } else { startX = x1; endX = x0; } if (y1 > y0) { startY = y0; endY = y1; } else { startY = y1; endY = y0; } } EAQVGAOLED::EAQVGAOLED ( PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset, PinName bl ) : _spi(mosi, miso, sclk), _cs(cs), _reset(reset), _bl(bl) { // Initialise the hardware initHardware(); // And reset the display resetDisplay(); } void EAQVGAOLED::pixel ( int x, int y, int colour ) { // Set the x and y positions via their registers, then the colour writeDataRegister(0x20, x); writeDataRegister(0x21, y); writeDataRegister(0x22, colour); } void EAQVGAOLED::hLine ( const uint16_t x0, const uint16_t y0, const uint16_t x1, const uint16_t colour ) { // Make sure we are drawing in the correct direction uint16_t startPos; uint16_t length; if (x1 > x0) { startPos = x0; length = x1 - x0; } else { startPos = x1; length = x0 - x1; } // Now draw the line, the display is set to auto increment in x movePen(startPos, y0); for (uint16_t i = 0; i < length; i++) { writeData(colour); } } void EAQVGAOLED::vLine ( uint16_t x0, uint16_t y0, uint16_t y1, uint16_t colour ) { // Make sure we are drawing in the correct direction uint16_t startPos; uint16_t endPos; if (y1 > y0) { startPos = y0; endPos = y1; } else { startPos = y1; endPos = y0; } // TODO This might be optimised by setting the Addressing mode bit AM to 1 (reg 03) // Now draw the line for (uint16_t i = startPos; i < endPos; i++) { pixel(x0, i, colour); } } void EAQVGAOLED::rectangle ( const uint16_t x0, const uint16_t y0, const uint16_t x1, const uint16_t y1, uint16_t colour ) { // Order the drawing co-ords uint16_t startX, startY, endX, endY; orderCoords(x0, y0, x1, y1, startX, startY, endX, endY); // Now draw the 4 lines required hLine(startX, startY, endX, colour); vLine(endX, startY, endY, colour); hLine(startX, endY, endX, colour); vLine(startX, startY, endY, colour); } void EAQVGAOLED::fillRectangle ( const uint16_t x0, const uint16_t y0, const uint16_t x1, const uint16_t y1, uint16_t colour ) { // Order the drawing co-ords uint16_t startX, startY, endX, endY; orderCoords(x0, y0, x1, y1, startX, startY, endX, endY); // Now draw the all lines required for (uint16_t i = startY; i < endY; i++) { hLine(startX, i, endX, colour); } } int EAQVGAOLED::_putc ( int value ) { switch (value) { case CURSOR_CLS: // Clear the screen cls(); break; case CURSOR_UP: if (_row == 0) _row = rows(); else { _row--; } break; case CURSOR_DOWN: if (_row == rows()) { _row = 0; } else { _row++; } break; case CURSOR_LEFT: if (_column == 0) { _column = columns(); } else { _column--; } break; case CURSOR_RIGHT: if (_column == columns()) { _column = 0; } else { _column++; } break; default: GraphicsDisplay::_putc(value); break; } return value; } /****************************************************************************/ /* */ /* Private functions */ /* */ /****************************************************************************/ /** * Initialise the hardware required * */ void EAQVGAOLED::initHardware(void) { // Activate the display reset line _reset = 0; // Turn the chip select and backlight off _cs = 1; _bl = 0; // Set the spi port for 8 bits, clk phase and polarity 0 _spi.format(8, 0); // And frequency to 10MHz _spi.frequency(10000000); // Wait for 10uS and release reset wait_us(10); _reset = 1; // Wait for 10ms to allow access to controller wait_ms(10); } /** * Reset the display controller * */ bool EAQVGAOLED::resetDisplay(void) { // Ensure we are connected to the correct hardware unsigned int result = readDataRegister(0x0F); /* Doesn't seem to wrk ?? if (EAQVGAOLED_ID != result) { return false; } */ // Set the entry mode values for addessing and increment writeDataRegister(0x03, 0x130); // Set the standby off writeDataRegister(0x10, 0); // Delay till the clocks come up wait_ms(100); // Enable the backlight _bl = 1; // Delay until power is steady wait_ms(40); // Turn the display on writeDataRegister(0x05, 1); return true; } /** * Set the location of the pen * */ void EAQVGAOLED::movePen ( const uint16_t x, const uint16_t y ) { // Set x & y pos and select GRAM register writeDataRegister(0x20, x); writeDataRegister(0x21, y); setRegisterIndex(0x22); } /** * Read the value of a controller data register * * @param reg the register address to read */ uint16_t EAQVGAOLED::readDataRegister ( const uint8_t reg ) { // Set the register index setRegisterIndex(reg); // Read the response _cs = 0; _spi.write(0x71); // Command byte ID = 011100, RS = 0, R/W = 1 uint8_t msb = _spi.write(0); uint8_t lsb = _spi.write(0); _cs = 1; return (msb << 8) | lsb; } /** * Write to a controller data register * * @param reg the register address to read * @param data the data to write */ void EAQVGAOLED::writeDataRegister ( const uint8_t reg, const uint16_t data ) { // Set the register index setRegisterIndex(reg); // Write the data writeData(data); } inline void EAQVGAOLED::writeData ( const uint16_t data ) { // Write the data _cs = 0; _spi.write(0x72); // Command byte, ID = 011100, RS = 1, R/W = 0 _spi.write(data >> 8); _spi.write(data & 0xFF); _cs = 1; } /** Select a controller register * * @param reg register to select */ inline void EAQVGAOLED::setRegisterIndex ( const uint8_t reg ) { // Write to the register selector (RS = 0) _cs = 0; _spi.write(0x70); // Command byte ID = 011100, RS = 0, R/W = 0 _spi.write(0); _spi.write(reg); _cs = 1; }