Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: EAQVGAOLED.cpp
- Revision:
- 0:ae3d20db48fc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EAQVGAOLED.cpp Wed Feb 09 21:23:49 2011 +0000 @@ -0,0 +1,387 @@ +/* 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; +}