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
diff -r 000000000000 -r ae3d20db48fc EAQVGAOLED.cpp
--- /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;
+}