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.
EAQVGAOLED.cpp
- Committer:
- gbloice
- Date:
- 2011-02-09
- Revision:
- 0:ae3d20db48fc
File content as of revision 0:ae3d20db48fc:
/* 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;
}