mirror of
https://github.com/eclipse/upm.git
synced 2025-03-15 04:57:30 +03:00
eboled: Sparkfun OLED Block Improvements
Signed-off-by: Tyler Gibson <tgibson@microsoft.com> Signed-off-by: Mihai Tudor Panu <mihai.tudor.panu@intel.com>
This commit is contained in:
parent
7935ef1622
commit
14a3924fb2
@ -5,6 +5,9 @@
|
||||
* Author: Jon Trulson <jtrulson@ics.com>
|
||||
* Copyright (c) 2015 Intel Corporation.
|
||||
*
|
||||
* Author: Tyler Gibson <tgibson@microsoft.com>
|
||||
* Copyright (c) 2015 Microsoft Corporation.
|
||||
*
|
||||
* 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
|
||||
@ -25,27 +28,123 @@
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
var lcdObj = require('jsupm_i2clcd');
|
||||
var oled = new lcdObj.EBOLED();
|
||||
|
||||
var sample = 0;
|
||||
var samples = 13;
|
||||
|
||||
function exit()
|
||||
{
|
||||
lcd = null;
|
||||
lcdObj.cleanUp();
|
||||
lcdObj = null;
|
||||
process.exit(0);
|
||||
oled = null;
|
||||
lcdObj.cleanUp();
|
||||
lcdObj = null;
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Load i2clcd module
|
||||
var lcdObj = require('jsupm_i2clcd');
|
||||
|
||||
var lcd = new lcdObj.EBOLED();
|
||||
|
||||
lcd.clear();
|
||||
lcd.setCursor(2, 0);
|
||||
lcd.write("Hello");
|
||||
lcd.setCursor(3, 5);
|
||||
lcd.write("World!");
|
||||
|
||||
console.log("Sleeping for 5 seconds...");
|
||||
setTimeout(exit, 5000);
|
||||
|
||||
|
||||
setInterval( function()
|
||||
{
|
||||
if(sample>samples)
|
||||
{
|
||||
exit();
|
||||
}
|
||||
oled.clearScreenBuffer();
|
||||
runSample(sample++);
|
||||
oled.refresh();
|
||||
}, 1500);
|
||||
|
||||
function runSample(sample)
|
||||
{
|
||||
switch(sample) {
|
||||
case 0:
|
||||
// x/y coords are 0 based, using 1 here for padding.
|
||||
oled.setCursor(1,1);
|
||||
// nowrap = 0, wrapping = 1
|
||||
oled.setTextWrap(1);
|
||||
oled.write("HELLO WORLD! Mixed with #123 and y's, g's and q's.");
|
||||
break;
|
||||
case 1:
|
||||
oled.setCursor(12, 1);
|
||||
//multiply text size, only integers
|
||||
oled.setTextSize(3);
|
||||
oled.write("BOO!");
|
||||
oled.setTextSize(1);
|
||||
break;
|
||||
case 2:
|
||||
oled.drawRectangleFilled(0,0,48,9);
|
||||
oled.setCursor(1,1);
|
||||
// 0=Black, 1=White, 2=Xor (Toggle)
|
||||
oled.setTextColor(2);
|
||||
oled.write("Cutout");
|
||||
break;
|
||||
case 3:
|
||||
var total = Math.random()*100;
|
||||
for(var stars=0; stars<total; stars++ )
|
||||
oled.drawPixel(Math.floor(Math.random()*63), Math.floor(Math.random()*47), 1);
|
||||
break;
|
||||
case 4:
|
||||
for(var burst=0; burst<12; burst++)
|
||||
oled.drawLine(31, 24, Math.floor(Math.random()*63), Math.floor(Math.random()*47), 1);
|
||||
break;
|
||||
case 5:
|
||||
var lastPeak = 24;
|
||||
for(var peak=0; peak < 64; peak++)
|
||||
{
|
||||
var thisPeak = Math.abs(lastPeak + Math.floor(Math.random()*(-6) + Math.random()*6));
|
||||
oled.drawLine(peak, thisPeak, peak, 47, 1);
|
||||
lastPeak = thisPeak;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
for(var y=0; y<47; y++)
|
||||
{
|
||||
oled.drawLineHorizontal(0,y+1,63,2);
|
||||
oled.refresh();
|
||||
oled.drawLineHorizontal(0,y,63,2);
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
var eqbarHeights = [ Math.floor(Math.random()*32),
|
||||
Math.floor(Math.random()*32),
|
||||
Math.floor(Math.random()*32),
|
||||
Math.floor(Math.random()*32),
|
||||
Math.floor(Math.random()*32),
|
||||
Math.floor(Math.random()*32),
|
||||
Math.floor(Math.random()*32) ];
|
||||
var begin = Date.now();
|
||||
while(Date.now()-begin < 2000)
|
||||
{
|
||||
oled.clearScreenBuffer();
|
||||
for(var eqbar=0; eqbar<7; eqbar++)
|
||||
{
|
||||
oled.drawRectangleFilled(eqbar*9, 49 - eqbarHeights[eqbar], 8, eqbarHeights[eqbar], 1);
|
||||
eqbarHeights[eqbar] = eqbarHeights[eqbar] + Math.random()*(-2) + Math.random()*2;
|
||||
if(eqbarHeights[eqbar]<0)
|
||||
eqbarHeights[eqbar] = 1;
|
||||
}
|
||||
oled.refresh();
|
||||
}
|
||||
oled.clear();
|
||||
break;
|
||||
case 8:
|
||||
oled.drawRoundedRectangle(8, 8, 48, 16, 4, 1);
|
||||
oled.setCursor(12, 16);
|
||||
oled.write("Cancel");
|
||||
break;
|
||||
case 9:
|
||||
oled.drawTriangle(2, 2, 52, 7, 17, 37, 1);
|
||||
break;
|
||||
case 10:
|
||||
oled.drawTriangleFilled(2, 2, 52, 7, 17, 37, 1);
|
||||
break;
|
||||
case 11:
|
||||
oled.drawCircle(32, 24, 14, 1);
|
||||
break;
|
||||
case 12:
|
||||
oled.drawCircleFilled(32, 24, 14, 1);
|
||||
break;
|
||||
case 13:
|
||||
oled.fillScreen(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,9 @@
|
||||
* Author: Jon Trulson <jtrulson@ics.com>
|
||||
* Copyright (c) 2015 Intel Corporation.
|
||||
*
|
||||
* Author: Tyler Gibson <tgibson@microsoft.com>
|
||||
* Copyright (c) 2015 Microsoft Corporation.
|
||||
*
|
||||
* 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
|
||||
@ -29,15 +32,23 @@
|
||||
using namespace upm;
|
||||
using namespace std;
|
||||
|
||||
EBOLED::EBOLED(int spi, int CD, int reset) :
|
||||
static uint16_t screenBuffer[BUFFER_SIZE];
|
||||
|
||||
EBOLED::EBOLED(int spi, int CD, int reset) :
|
||||
m_spi(spi), m_gpioCD(CD), m_gpioRST(reset)
|
||||
{
|
||||
m_name = "EBOLED";
|
||||
|
||||
m_textColor = COLOR_WHITE;
|
||||
m_textWrap = 0;
|
||||
m_textSize = 1;
|
||||
m_cursorX = 0;
|
||||
m_cursorY = 0;
|
||||
|
||||
m_gpioCD.dir(mraa::DIR_OUT);
|
||||
m_gpioRST.dir(mraa::DIR_OUT);
|
||||
|
||||
m_spi.frequency(1000000);
|
||||
//1000000 is standard.
|
||||
m_spi.frequency(10000000);
|
||||
|
||||
// reset the device
|
||||
m_gpioRST.write(1);
|
||||
@ -53,40 +64,48 @@ EBOLED::EBOLED(int spi, int CD, int reset) :
|
||||
|
||||
command(CMD_SETMULTIPLEX);
|
||||
command(0x2f);
|
||||
|
||||
|
||||
command(CMD_SETDISPLAYOFFSET);
|
||||
command(0x0); // no offset
|
||||
|
||||
|
||||
command(CMD_SETSTARTLINE | 0x0); // line #0
|
||||
|
||||
|
||||
command(CMD_CHARGEPUMP); // enable charge pump
|
||||
command(0x14);
|
||||
|
||||
|
||||
command(CMD_NORMALDISPLAY);
|
||||
command(CMD_DISPLAYALLONRESUME);
|
||||
|
||||
|
||||
command(CMD_SEGREMAP | 0x1); // reverse mapping (SEG0==COL127)
|
||||
command(CMD_COMSCANDEC);
|
||||
|
||||
|
||||
command(CMD_SETCOMPINS); // custom COM PIN mapping
|
||||
command(0x12);
|
||||
|
||||
|
||||
command(CMD_SETCONTRAST);
|
||||
command(0x8f);
|
||||
|
||||
|
||||
command(CMD_SETPRECHARGE);
|
||||
command(0xf1);
|
||||
|
||||
|
||||
command(CMD_SETVCOMDESELECT);
|
||||
command(0x40);
|
||||
|
||||
|
||||
command(CMD_DISPLAYON);
|
||||
|
||||
|
||||
usleep(4500);
|
||||
|
||||
clear();
|
||||
setAddressingMode(PAGE);
|
||||
|
||||
setAddressingMode(HORIZONTAL);
|
||||
|
||||
//Set Page Address range, required for horizontal addressing mode.
|
||||
command(CMD_SETPAGEADDRESS); // triple-byte cmd
|
||||
command(0x00); //Initial page address
|
||||
command(0x05); //Final page address
|
||||
|
||||
//Set Column Address range, required for horizontal addressing mode.
|
||||
command(CMD_SETCOLUMNADDRESS); // triple-byte cmd
|
||||
command(0x20); // this display has a horizontal offset of 20 columns
|
||||
command(0x5f); // 64 columns wide - 0 based 63 offset
|
||||
}
|
||||
|
||||
EBOLED::~EBOLED()
|
||||
@ -94,68 +113,117 @@ EBOLED::~EBOLED()
|
||||
clear();
|
||||
}
|
||||
|
||||
mraa::Result EBOLED::draw(uint8_t* bdata, int bytes)
|
||||
mraa::Result EBOLED::refresh()
|
||||
{
|
||||
mraa::Result error = mraa::SUCCESS;
|
||||
mraa::Result error = mraa::SUCCESS;;
|
||||
|
||||
setAddressingMode(HORIZONTAL);
|
||||
|
||||
command(CMD_SETCOLUMNADDRESS); // triple-byte cmd
|
||||
command(0x20); // this display has a horizontal offset of 20 columns
|
||||
command(0x20 + 0x40); // 64 columns wide
|
||||
|
||||
for (int idx = 0; idx < bytes; idx++)
|
||||
error = data(bdata[idx]);
|
||||
|
||||
// reset addressing mode
|
||||
setAddressingMode(PAGE);
|
||||
m_gpioCD.write(1); // data mode
|
||||
for(int i=0; i<BUFFER_SIZE; i++)
|
||||
{
|
||||
error = data(screenBuffer[i]);
|
||||
if(error != MRAA_SUCCESS)
|
||||
return error;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
mraa::Result EBOLED::write(std::string msg)
|
||||
mraa::Result EBOLED::write (std::string msg)
|
||||
{
|
||||
mraa::Result error = mraa::SUCCESS;
|
||||
int len = msg.length();
|
||||
uint8_t temp_cursorX = m_cursorX;
|
||||
for (int idx = 0; idx < len; idx++)
|
||||
{
|
||||
if (msg[idx] == '\n')
|
||||
{
|
||||
m_cursorY += m_textSize * 9;
|
||||
temp_cursorX = m_cursorX;
|
||||
}
|
||||
else if (msg[idx] == '\r')
|
||||
{
|
||||
// skip em
|
||||
}
|
||||
else
|
||||
{
|
||||
drawChar(temp_cursorX, m_cursorY, msg[idx], m_textColor, m_textSize);
|
||||
temp_cursorX += m_textSize * 6;
|
||||
|
||||
setAddressingMode(PAGE);
|
||||
for (std::string::size_type i = 0; i < msg.size(); ++i)
|
||||
error = writeChar(msg[i]);
|
||||
|
||||
return error;
|
||||
//textColor used to avoid wrapping if COLOR_BLACK is set.
|
||||
if (m_textWrap && (m_textColor > OLED_WIDTH - temp_cursorX - 6))
|
||||
{
|
||||
m_cursorY += m_textSize * 9;
|
||||
temp_cursorX = m_cursorX;
|
||||
}
|
||||
}
|
||||
}
|
||||
return mraa::SUCCESS;;
|
||||
}
|
||||
|
||||
mraa::Result EBOLED::setCursor(int row, int column)
|
||||
{
|
||||
mraa::Result error = mraa::SUCCESS;
|
||||
mraa::Result EBOLED::setCursor (int row, int column) {
|
||||
m_cursorX = column;
|
||||
m_cursorY = row;
|
||||
return mraa::SUCCESS;;
|
||||
}
|
||||
|
||||
// set page address
|
||||
error = command(CMD_SETPAGESTARTADDR | (row & 0x07));
|
||||
void EBOLED::setTextColor (uint8_t textColor) {
|
||||
m_textColor = textColor;
|
||||
}
|
||||
|
||||
// set column address
|
||||
error = command(CMD_SETLOWCOLUMN | (column & 0x0f));
|
||||
// ediblock oled starts at col 20 apparently...
|
||||
error = command(CMD_SETHIGHCOLUMN | ((column >> 4) & 0x0f) + 0x02);
|
||||
void EBOLED::setTextSize (uint8_t size) {
|
||||
m_textSize = (size > 0) ? size : 1;
|
||||
}
|
||||
|
||||
return error;
|
||||
void EBOLED::setTextWrap (uint8_t wrap) {
|
||||
m_textWrap = wrap;
|
||||
}
|
||||
|
||||
void EBOLED::drawChar (uint8_t x, uint8_t y, uint8_t data, uint8_t color, uint8_t size) {
|
||||
if( (x >= OLED_WIDTH) || // Clip right
|
||||
(y >= OLED_HEIGHT) || // Clip bottom
|
||||
((x + 6 * size - 1) < 0) || // Clip left
|
||||
((y + 8 * size - 1) < 0)) // Clip top
|
||||
return;
|
||||
|
||||
if (data < 0x20 || data > 0x7F) {
|
||||
data = 0x20; // space
|
||||
}
|
||||
|
||||
for (int8_t i=0; i<6; i++ ) {
|
||||
uint8_t line;
|
||||
if (i == 6)
|
||||
line = 0x0;
|
||||
else
|
||||
{
|
||||
//32 offset to align standard ASCII range to index
|
||||
line = BasicFont[data - 32][i+1];
|
||||
for (int8_t j = 0; j<8; j++)
|
||||
{
|
||||
if (line & 0x1)
|
||||
{
|
||||
if (size == 1) // default size
|
||||
drawPixel(x+i, y+j, color);
|
||||
else
|
||||
drawRectangleFilled(x+(i*size), y+(j*size), size, size, color); // big size
|
||||
}
|
||||
line >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mraa::Result EBOLED::clear()
|
||||
{
|
||||
mraa::Result error = mraa::SUCCESS;
|
||||
uint8_t columnIdx, rowIdx;
|
||||
|
||||
for (rowIdx = 0; rowIdx < 8; rowIdx++)
|
||||
{
|
||||
setCursor(rowIdx, 0);
|
||||
|
||||
// clear all columns (8 * 8 pixels per char)
|
||||
for (columnIdx = 0; columnIdx < 8; columnIdx++)
|
||||
error = writeChar(' ');
|
||||
}
|
||||
|
||||
home();
|
||||
|
||||
return mraa::SUCCESS;
|
||||
mraa::Result error = mraa::SUCCESS;;
|
||||
|
||||
m_gpioCD.write(1); // data mode
|
||||
for(int i=0; i<BUFFER_SIZE; i++)
|
||||
{
|
||||
error = data(0x0000);
|
||||
if(error != MRAA_SUCCESS)
|
||||
return error;
|
||||
}
|
||||
|
||||
return mraa::SUCCESS;;
|
||||
}
|
||||
|
||||
mraa::Result EBOLED::home()
|
||||
@ -163,19 +231,310 @@ mraa::Result EBOLED::home()
|
||||
return setCursor(0, 0);
|
||||
}
|
||||
|
||||
mraa::Result EBOLED::writeChar(uint8_t value)
|
||||
void EBOLED::drawPixel(int8_t x, int8_t y, uint8_t color)
|
||||
{
|
||||
mraa::Result rv;
|
||||
if(x<0 || x>=OLED_WIDTH || y<0 || y>=OLED_HEIGHT)
|
||||
return;
|
||||
|
||||
if (value < 0x20 || value > 0x7F) {
|
||||
value = 0x20; // space
|
||||
/* Screenbuffer is uint16 array, but pages are 8bit high so each buffer
|
||||
* index is two columns. This means the index is based on x/2 and
|
||||
* OLED_WIDTH/2 = VERT_COLUMNS.
|
||||
*
|
||||
* Then to set the appropriate bit, we need to shift based on the y
|
||||
* offset in relation to the page and then adjust for high/low based
|
||||
* on the x position.
|
||||
*/
|
||||
|
||||
switch(color)
|
||||
{
|
||||
case COLOR_XOR:
|
||||
screenBuffer[(x/2) + ((y/8) * VERT_COLUMNS)] ^= (1<<(y%8+(x%2 * 8)));
|
||||
return;
|
||||
case COLOR_WHITE:
|
||||
screenBuffer[(x/2) + ((y/8) * VERT_COLUMNS)] |= (1<<(y%8+(x%2 * 8)));
|
||||
return;
|
||||
case COLOR_BLACK:
|
||||
screenBuffer[(x/2) + ((y/8) * VERT_COLUMNS)] &= ~(1<<(y%8+(x%2 * 8)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void EBOLED::drawLine(int8_t x0, int8_t y0, int8_t x1, int8_t y1, uint8_t color)
|
||||
{
|
||||
int16_t steep = abs(y1 - y0) > abs(x1 - x0);
|
||||
|
||||
if (steep) {
|
||||
swap(x0, y0);
|
||||
swap(x1, y1);
|
||||
}
|
||||
|
||||
for (uint8_t idx = 0; idx < 8; idx++) {
|
||||
rv = data(BasicFont[value - 32][idx]);
|
||||
if (x0 > x1) {
|
||||
swap(x0, x1);
|
||||
swap(y0, y1);
|
||||
}
|
||||
|
||||
return rv;
|
||||
int16_t dx, dy;
|
||||
dx = x1 - x0;
|
||||
dy = abs (y1 - y0);
|
||||
|
||||
int16_t err = dx / 2;
|
||||
int16_t ystep;
|
||||
|
||||
if (y0 < y1) {
|
||||
ystep = 1;
|
||||
} else {
|
||||
ystep = -1;
|
||||
}
|
||||
|
||||
for (; x0 <= x1; x0++) {
|
||||
if (steep) {
|
||||
drawPixel(y0, x0, color);
|
||||
} else {
|
||||
drawPixel(x0, y0, color);
|
||||
}
|
||||
err -= dy;
|
||||
if (err < 0) {
|
||||
y0 += ystep;
|
||||
err += dx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EBOLED::drawLineHorizontal(int8_t x, int8_t y, uint8_t width, uint8_t color)
|
||||
{
|
||||
drawLine(x, y, x+width-1, y, color);
|
||||
}
|
||||
|
||||
void EBOLED::drawLineVertical(int8_t x, int8_t y, uint8_t height, uint8_t color)
|
||||
{
|
||||
drawLine(x, y, x, y+height-1, color);
|
||||
}
|
||||
|
||||
void EBOLED::drawRectangle(int8_t x, int8_t y, uint8_t width, uint8_t height, uint8_t color)
|
||||
{
|
||||
drawLineHorizontal(x, y, width, color);
|
||||
drawLineHorizontal(x, y+height-1, color);
|
||||
|
||||
uint8_t innerHeight = height - 2;
|
||||
if(innerHeight > 0)
|
||||
{
|
||||
drawLineVertical(x, y+1, innerHeight, color);
|
||||
drawLineVertical(x+width-1, y+1, innerHeight, color);
|
||||
}
|
||||
}
|
||||
|
||||
void EBOLED::drawRoundedRectangle(int8_t x, int8_t y, int8_t width, int8_t height, int16_t radius, uint8_t color) {
|
||||
// smarter version
|
||||
drawLineHorizontal(x+radius , y , width-2*radius, color); // Top
|
||||
drawLineHorizontal(x+radius , y+height-1, width-2*radius, color); // Bottom
|
||||
drawLineVertical( x , y+radius , height-2*radius, color); // Left
|
||||
drawLineVertical( x+width-1 , y+radius , height-2*radius, color); // Right
|
||||
// draw four corners
|
||||
drawRoundCorners(x+radius , y+radius , radius, 1, color);
|
||||
drawRoundCorners(x+width-radius-1, y+radius , radius, 2, color);
|
||||
drawRoundCorners(x+width-radius-1, y+height-radius-1, radius, 4, color);
|
||||
drawRoundCorners(x+radius , y+height-radius-1, radius, 8, color);
|
||||
}
|
||||
|
||||
void EBOLED::drawRectangleFilled(int8_t x, int8_t y, uint8_t width, uint8_t height, uint8_t color)
|
||||
{
|
||||
for (uint8_t i=x; i<x+width; i++) {
|
||||
drawLineVertical(i, y, height, color);
|
||||
}
|
||||
}
|
||||
|
||||
void EBOLED::drawTriangle(int8_t x0, int8_t y0, int8_t x1, int8_t y1, int8_t x2, int8_t y2, uint8_t color)
|
||||
{
|
||||
drawLine(x0, y0, x1, y1, color);
|
||||
drawLine(x1, y1, x2, y2, color);
|
||||
drawLine(x2, y2, x0, y0, color);
|
||||
}
|
||||
|
||||
void EBOLED::drawTriangleFilled ( int8_t x0, int8_t y0, int8_t x1, int8_t y1, int8_t x2, int8_t y2, uint8_t color) {
|
||||
|
||||
int16_t a, b, y, last;
|
||||
|
||||
// Sort coordinates by Y order (y2 >= y1 >= y0)
|
||||
if (y0 > y1) {
|
||||
swap(y0, y1); swap(x0, x1);
|
||||
}
|
||||
if (y1 > y2) {
|
||||
swap(y2, y1); swap(x2, x1);
|
||||
}
|
||||
if (y0 > y1) {
|
||||
swap(y0, y1); swap(x0, x1);
|
||||
}
|
||||
|
||||
if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing
|
||||
a = b = x0;
|
||||
if(x1 < a) a = x1;
|
||||
else if(x1 > b) b = x1;
|
||||
if(x2 < a) a = x2;
|
||||
else if(x2 > b) b = x2;
|
||||
drawLineHorizontal(a, y0, b-a+1, color);
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t
|
||||
dx01 = x1 - x0,
|
||||
dy01 = y1 - y0,
|
||||
dx02 = x2 - x0,
|
||||
dy02 = y2 - y0,
|
||||
dx12 = x2 - x1,
|
||||
dy12 = y2 - y1;
|
||||
int32_t
|
||||
sa = 0,
|
||||
sb = 0;
|
||||
|
||||
// For upper part of triangle, find scanline crossings for segments
|
||||
// 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
|
||||
// is included here (and second loop will be skipped, avoiding a /0
|
||||
// error there), otherwise scanline y1 is skipped here and handled
|
||||
// in the second loop...which also avoids a /0 error here if y0=y1
|
||||
// (flat-topped triangle).
|
||||
if(y1 == y2) last = y1; // Include y1 scanline
|
||||
else last = y1-1; // Skip it
|
||||
|
||||
for(y=y0; y<=last; y++) {
|
||||
a = x0 + sa / dy01;
|
||||
b = x0 + sb / dy02;
|
||||
sa += dx01;
|
||||
sb += dx02;
|
||||
/* longhand:
|
||||
a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
|
||||
b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
|
||||
*/
|
||||
if(a > b) swap(a,b);
|
||||
drawLineHorizontal(a, y, b-a+1, color);
|
||||
}
|
||||
|
||||
// For lower part of triangle, find scanline crossings for segments
|
||||
// 0-2 and 1-2. This loop is skipped if y1=y2.
|
||||
sa = dx12 * (y - y1);
|
||||
sb = dx02 * (y - y0);
|
||||
for(; y<=y2; y++) {
|
||||
a = x1 + sa / dy12;
|
||||
b = x0 + sb / dy02;
|
||||
sa += dx12;
|
||||
sb += dx02;
|
||||
/* longhand:
|
||||
a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
|
||||
b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
|
||||
*/
|
||||
if(a > b) swap(a,b);
|
||||
drawLineHorizontal(a, y, b-a+1, color);
|
||||
}
|
||||
}
|
||||
|
||||
void EBOLED::drawCircle(int16_t x0, int16_t y0, int16_t radius, uint8_t color)
|
||||
{
|
||||
int16_t f = 1 - radius;
|
||||
int16_t ddF_x = 1;
|
||||
int16_t ddF_y = -2 * radius;
|
||||
int16_t x = 0;
|
||||
int16_t y = radius;
|
||||
|
||||
drawPixel(x0 , y0+radius, color);
|
||||
drawPixel(x0 , y0-radius, color);
|
||||
drawPixel(x0+radius, y0 , color);
|
||||
drawPixel(x0-radius, y0 , color);
|
||||
|
||||
while (x<y)
|
||||
{
|
||||
if (f >= 0)
|
||||
{
|
||||
y--;
|
||||
ddF_y += 2;
|
||||
f += ddF_y;
|
||||
}
|
||||
x++;
|
||||
|
||||
ddF_x += 2;
|
||||
f += ddF_x;
|
||||
|
||||
drawPixel(x0 + x, y0 + y, color);
|
||||
drawPixel(x0 - x, y0 + y, color);
|
||||
drawPixel(x0 + x, y0 - y, color);
|
||||
drawPixel(x0 - x, y0 - y, color);
|
||||
drawPixel(x0 + y, y0 + x, color);
|
||||
drawPixel(x0 - y, y0 + x, color);
|
||||
drawPixel(x0 + y, y0 - x, color);
|
||||
drawPixel(x0 - y, y0 - x, color);
|
||||
}
|
||||
}
|
||||
|
||||
void EBOLED::drawRoundCorners( int8_t x0, int8_t y0, int16_t radius, uint8_t cornername, uint8_t color) {
|
||||
int16_t f = 1 - radius;
|
||||
int16_t ddF_x = 1;
|
||||
int16_t ddF_y = -2 * radius;
|
||||
int16_t x = 0;
|
||||
int16_t y = radius;
|
||||
|
||||
while (x<y) {
|
||||
if (f >= 0) {
|
||||
y--;
|
||||
ddF_y += 2;
|
||||
f += ddF_y;
|
||||
}
|
||||
x++;
|
||||
ddF_x += 2;
|
||||
f += ddF_x;
|
||||
if (cornername & 0x4) {
|
||||
drawPixel(x0 + x, y0 + y, color);
|
||||
drawPixel(x0 + y, y0 + x, color);
|
||||
}
|
||||
if (cornername & 0x2) {
|
||||
drawPixel(x0 + x, y0 - y, color);
|
||||
drawPixel(x0 + y, y0 - x, color);
|
||||
}
|
||||
if (cornername & 0x8) {
|
||||
drawPixel(x0 - y, y0 + x, color);
|
||||
drawPixel(x0 - x, y0 + y, color);
|
||||
}
|
||||
if (cornername & 0x1) {
|
||||
drawPixel(x0 - y, y0 - x, color);
|
||||
drawPixel(x0 - x, y0 - y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EBOLED::drawCircleFilled(int8_t x0, int8_t y0, int16_t radius, uint8_t color) {
|
||||
drawLineVertical(x0, y0-radius, 2*radius+1, color);
|
||||
drawRoundedCornersFilled(x0, y0, radius, 3, 0, color);
|
||||
}
|
||||
|
||||
void EBOLED::drawRoundedCornersFilled(int8_t x0, int8_t y0, int16_t radius, uint8_t cornername, int16_t delta, uint8_t color) {
|
||||
|
||||
int16_t f = 1 - radius;
|
||||
int16_t ddF_x = 1;
|
||||
int16_t ddF_y = -2 * radius;
|
||||
int16_t x = 0;
|
||||
int16_t y = radius;
|
||||
|
||||
while (x<y) {
|
||||
if (f >= 0) {
|
||||
y--;
|
||||
ddF_y += 2;
|
||||
f += ddF_y;
|
||||
}
|
||||
x++;
|
||||
ddF_x += 2;
|
||||
f += ddF_x;
|
||||
|
||||
if (cornername & 0x1) {
|
||||
drawLineVertical(x0+x, y0-y, 2*y+1+delta, color);
|
||||
drawLineVertical(x0+y, y0-x, 2*x+1+delta, color);
|
||||
}
|
||||
if (cornername & 0x2) {
|
||||
drawLineVertical(x0-x, y0-y, 2*y+1+delta, color);
|
||||
drawLineVertical(x0-y, y0-x, 2*x+1+delta, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EBOLED::fillScreen(uint8_t color)
|
||||
{
|
||||
drawRectangleFilled(0, 0, OLED_WIDTH-1, OLED_HEIGHT-1, color);
|
||||
}
|
||||
|
||||
mraa::Result EBOLED::setAddressingMode(displayAddressingMode mode)
|
||||
@ -195,9 +554,14 @@ mraa::Result EBOLED::command(uint8_t cmd)
|
||||
return mraa::SUCCESS;
|
||||
}
|
||||
|
||||
mraa::Result EBOLED::data(uint8_t data)
|
||||
mraa::Result EBOLED::data(uint16_t data)
|
||||
{
|
||||
m_gpioCD.write(1); // data mode
|
||||
m_spi.writeByte(data);
|
||||
m_spi.write_word(data);
|
||||
return mraa::SUCCESS;
|
||||
}
|
||||
|
||||
void EBOLED::clearScreenBuffer()
|
||||
{
|
||||
for(int i=0; i<BUFFER_SIZE;i++)
|
||||
screenBuffer[i] = 0x0000;
|
||||
}
|
||||
|
233
src/lcd/eboled.h
233
src/lcd/eboled.h
@ -2,6 +2,12 @@
|
||||
* Author: Jon Trulson <jtrulson@ics.com>
|
||||
* Copyright (c) 2015 Intel Corporation.
|
||||
*
|
||||
* Author: Tyler Gibson <tgibson@microsoft.com>
|
||||
* Copyright (c) 2015 Microsoft Corporation.
|
||||
*
|
||||
* Credits to Adafruit.
|
||||
* Based on Adafruit ST7735 library, see original license in license.txt file.
|
||||
*
|
||||
* 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
|
||||
@ -35,6 +41,8 @@
|
||||
#define EBOLED_DEFAULT_CD 36
|
||||
#define EBOLED_DEFAULT_RESET 48
|
||||
|
||||
#define swap(a, b) { uint8_t t = a; a = b; b = t; }
|
||||
|
||||
namespace upm
|
||||
{
|
||||
/**
|
||||
@ -60,6 +68,15 @@ namespace upm
|
||||
*
|
||||
* @snippet eboled.cxx Interesting
|
||||
*/
|
||||
|
||||
const uint8_t COLOR_WHITE = 0x01;
|
||||
const uint8_t COLOR_BLACK = 0x00;
|
||||
const uint8_t COLOR_XOR = 0x02;
|
||||
const uint8_t OLED_WIDTH = 0x40; // 64 pixels
|
||||
const uint8_t VERT_COLUMNS = 0x20; // half width for hi/lo 16bit writes.
|
||||
const uint8_t OLED_HEIGHT = 0x30; // 48 pixels
|
||||
const int BUFFER_SIZE = 192;
|
||||
|
||||
class EBOLED : public LCD
|
||||
{
|
||||
// SSD commands
|
||||
@ -73,7 +90,7 @@ namespace upm
|
||||
CMD_SETPAGEADDRESS = 0x22,
|
||||
CMD_SETSTARTLINE = 0x40, // 0x40 - 0x7f
|
||||
CMD_SETCONTRAST = 0x81,
|
||||
CMD_CHARGEPUMP = 0x8d,
|
||||
CMD_CHARGEPUMP = 0x8d,
|
||||
CMD_SEGREMAP = 0xa0,
|
||||
CMD_DISPLAYALLONRESUME = 0xa4,
|
||||
CMD_DISPLAYALLON = 0xa5,
|
||||
@ -102,28 +119,28 @@ namespace upm
|
||||
* @param reset reset pin
|
||||
* @param address the slave address the lcd is registered on
|
||||
*/
|
||||
EBOLED(int spi=EBOLED_DEFAULT_SPI_BUS, int CD=EBOLED_DEFAULT_CD,
|
||||
EBOLED(int spi=EBOLED_DEFAULT_SPI_BUS, int CD=EBOLED_DEFAULT_CD,
|
||||
int reset=EBOLED_DEFAULT_RESET);
|
||||
|
||||
|
||||
/**
|
||||
* EBOLED Destructor
|
||||
*/
|
||||
~EBOLED();
|
||||
|
||||
/**
|
||||
* Draw an image, see examples/python/make_oled_pic.py for an
|
||||
* explanation on how the pixels are mapped to bytes
|
||||
* Draw the buffer to screen, see examples/python/make_oled_pic.py for an
|
||||
* explanation on how the pixels are mapped to bytes.
|
||||
*
|
||||
* @param data the buffer to write
|
||||
* @param bytes the number of bytes to write
|
||||
* @return result of operation
|
||||
*/
|
||||
mraa::Result draw(uint8_t* data, int bytes);
|
||||
mraa::Result refresh();
|
||||
|
||||
/**
|
||||
* Write a string to LCD
|
||||
*
|
||||
* @param msg the std::string to write to display, note only ascii
|
||||
* @param msg the std::string to write to display, note only ascii
|
||||
* chars are supported
|
||||
* @return result of operation
|
||||
*/
|
||||
@ -132,12 +149,45 @@ namespace upm
|
||||
/**
|
||||
* Set cursor to a coordinate
|
||||
*
|
||||
* @param row the row to set cursor to. This device supports 6 rows.
|
||||
* @param column the column to set cursor to. This device support
|
||||
* 64 columns
|
||||
* @param y Axis on the vertical scale. This device supports 6 rows.
|
||||
* @param x Axis on the horizontal scale This device supports 64 columns
|
||||
*
|
||||
* @return result of operation
|
||||
*/
|
||||
mraa::Result setCursor(int row, int column);
|
||||
mraa::Result setCursor (int row, int column);
|
||||
|
||||
/**
|
||||
* Sets a text color for a message
|
||||
*
|
||||
* @param textColor Font color: COLOR_WHITE, COLOR_BLACK or COLOR_XOR
|
||||
*/
|
||||
void setTextColor (uint8_t textColor);
|
||||
|
||||
/**
|
||||
* Sets the size of the font
|
||||
*
|
||||
* @param size Font size
|
||||
*/
|
||||
void setTextSize (uint8_t size);
|
||||
|
||||
/**
|
||||
* Wraps a printed message
|
||||
*
|
||||
* @param wrap True (1) or false (0)
|
||||
*/
|
||||
void setTextWrap (uint8_t wrap);
|
||||
|
||||
/**
|
||||
* Write a single character to the screen.
|
||||
*
|
||||
* @param x Axis on the horizontal scale
|
||||
* @param y Axis on the vertical scale
|
||||
* @param data Character to write
|
||||
* @param color Character color
|
||||
* @param bg Character background color
|
||||
* @param size Size of the font
|
||||
*/
|
||||
void drawChar (uint8_t x, uint8_t y, uint8_t data, uint8_t color, uint8_t size);
|
||||
|
||||
/**
|
||||
* Clear display
|
||||
@ -146,6 +196,8 @@ namespace upm
|
||||
*/
|
||||
mraa::Result clear();
|
||||
|
||||
void clearScreenBuffer();
|
||||
|
||||
/**
|
||||
* Return to coordinate 0,0
|
||||
*
|
||||
@ -153,9 +205,160 @@ namespace upm
|
||||
*/
|
||||
mraa::Result home();
|
||||
|
||||
/**
|
||||
* Write a single pixel to the screen buffer.
|
||||
* Can do an specific color write or toggle (xor) a pixel.
|
||||
*
|
||||
* @param x the x position of the pixel
|
||||
* @param y the y position of the pixel
|
||||
* @param color pixel is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
|
||||
*/
|
||||
void drawPixel (int8_t x, int8_t y, uint8_t color=COLOR_WHITE);
|
||||
|
||||
/**
|
||||
* Draw a line to the screen buffer.
|
||||
*
|
||||
* @param x0 the x position of the beginning of the line
|
||||
* @param y0 the y position of the beginning of the line
|
||||
* @param x1 the x position of the end of the line
|
||||
* @param y1 the y position of the end of the line
|
||||
* @param color line is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
|
||||
*/
|
||||
void drawLine (int8_t x0, int8_t y0, int8_t x1, int8_t y1, uint8_t color = COLOR_WHITE);
|
||||
|
||||
/**
|
||||
* Draw a horizontal line to the screen buffer.
|
||||
*
|
||||
* @param x the x position of the beginning of the line
|
||||
* @param y the y position of the beginning of the line
|
||||
* @param width is the horizontal length of the line
|
||||
* @param color line is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
|
||||
*/
|
||||
void drawLineHorizontal (int8_t x, int8_t y, uint8_t width, uint8_t color = COLOR_WHITE);
|
||||
|
||||
/**
|
||||
* Draw a vertical line to the screen buffer.
|
||||
*
|
||||
* @param x the x position of the beginning of the line
|
||||
* @param y the y position of the beginning of the line
|
||||
* @param width is the vertical length of the line
|
||||
* @param color line is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
|
||||
*/
|
||||
void drawLineVertical (int8_t x, int8_t y, uint8_t height, uint8_t color = COLOR_WHITE);
|
||||
|
||||
/**
|
||||
* Draw a rectangle to the screen buffer.
|
||||
*
|
||||
* @param x the left edge
|
||||
* @param y the top edge
|
||||
* @param width sets the right edge
|
||||
* @param height bottom edge
|
||||
* @param color outline is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
|
||||
*/
|
||||
void drawRectangle (int8_t x, int8_t y, uint8_t width, uint8_t height, uint8_t color = COLOR_WHITE);
|
||||
|
||||
/**
|
||||
* Draw a rectangle with rounded corners to the screen buffer.
|
||||
*
|
||||
* @param x the left edge
|
||||
* @param y the top edge
|
||||
* @param width sets the right edge
|
||||
* @param height bottom edge
|
||||
* @param radius of the rounded corners
|
||||
* @param color outline is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
|
||||
*/
|
||||
void drawRoundedRectangle(int8_t x, int8_t y, int8_t width, int8_t height, int16_t radius, uint8_t color);
|
||||
|
||||
/**
|
||||
* Draw a filled rectangle to the screen buffer.
|
||||
*
|
||||
* @param x the left edge
|
||||
* @param y the top edge
|
||||
* @param width sets the right edge
|
||||
* @param height bottom edge
|
||||
* @param color fill color is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
|
||||
*/
|
||||
void drawRectangleFilled (int8_t x, int8_t y, uint8_t width, uint8_t height, uint8_t color = COLOR_WHITE);
|
||||
|
||||
/**
|
||||
* Draw a triangle to the screen buffer.
|
||||
*
|
||||
* @param x0 the x coordinate of the first corner
|
||||
* @param y0 the y coordinate of the first corner
|
||||
* @param x1 the x coordinate of the second corner
|
||||
* @param y1 the y coordinate of the second corner
|
||||
* @param x2 the x coordinate of the third corner
|
||||
* @param y2 the y coordinate of the third corner
|
||||
* @param color outline is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
|
||||
*/
|
||||
void drawTriangle (int8_t x0, int8_t y0, int8_t x1, int8_t y1, int8_t x2, int8_t y2, uint8_t color = COLOR_WHITE);
|
||||
|
||||
/**
|
||||
* Draw a filled triangle to the screen buffer.
|
||||
*
|
||||
* @param x0 the x coordinate of the first corner
|
||||
* @param y0 the y coordinate of the first corner
|
||||
* @param x1 the x coordinate of the second corner
|
||||
* @param y1 the y coordinate of the second corner
|
||||
* @param x2 the x coordinate of the third corner
|
||||
* @param y2 the y coordinate of the third corner
|
||||
* @param color fill color is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
|
||||
*/
|
||||
void drawTriangleFilled ( int8_t x0, int8_t y0, int8_t x1, int8_t y1, int8_t x2, int8_t y2, uint8_t color);
|
||||
|
||||
/**
|
||||
* Draw a circle to the screen buffer.
|
||||
*
|
||||
* @param x0 the x coordinate of the circle's center
|
||||
* @param y0 the y coordinate of the circle's center
|
||||
* @param radius the radius of the circle
|
||||
* @param color outline is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
|
||||
*/
|
||||
void drawCircle (int16_t x0, int16_t y0, int16_t radius, uint8_t color = COLOR_WHITE);
|
||||
|
||||
/**
|
||||
* Draw a quarter circle arc to the screen buffer.
|
||||
*
|
||||
* @param x0 the x coordinate of the arc's center
|
||||
* @param y0 the y coordinate of the arc's center
|
||||
* @param radius the radius of the arc
|
||||
* @param cornername denotes which of the 4 quarters to draw - 1,2,4,8
|
||||
* @param color outline is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
|
||||
*/
|
||||
void drawRoundCorners( int8_t x0, int8_t y0, int16_t radius, uint8_t cornername, uint8_t color);
|
||||
|
||||
/**
|
||||
* Draw a filled circle to the screen buffer.
|
||||
*
|
||||
* @param x0 the x coordinate of the circle's center
|
||||
* @param y0 the y coordinate of the circle's center
|
||||
* @param radius the radius of the circle
|
||||
* @param color outline is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
|
||||
*/
|
||||
void drawCircleFilled(int8_t x0, int8_t y0, int16_t radius, uint8_t color);
|
||||
|
||||
/**
|
||||
* Draw a quarter pie to the screen buffer.
|
||||
*
|
||||
* @param x0 the x coordinate of the arc's center
|
||||
* @param y0 the y coordinate of the arc's center
|
||||
* @param radius the radius of the arc
|
||||
* @param cornername denotes which of the 4 quarters to draw - 1,2,4,8
|
||||
* @param color fill color is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
|
||||
*/
|
||||
void drawRoundedCornersFilled(int8_t x0, int8_t y0, int16_t radius, uint8_t cornername, int16_t delta, uint8_t color);
|
||||
|
||||
/**
|
||||
* Fill the screen buffer with specified color.
|
||||
*
|
||||
* @param color fill color is COLOR_WHITE, COLOR_BLACK or COLOR_XOR
|
||||
*/
|
||||
void fillScreen (uint8_t color=COLOR_WHITE);
|
||||
|
||||
|
||||
protected:
|
||||
mraa::Result command(uint8_t cmd);
|
||||
mraa::Result data(uint8_t data);
|
||||
mraa::Result data(uint16_t data);
|
||||
mraa::Result writeChar(uint8_t value);
|
||||
mraa::Result setAddressingMode(displayAddressingMode mode);
|
||||
|
||||
@ -164,5 +367,11 @@ namespace upm
|
||||
mraa::Gpio m_gpioRST; // reset pin
|
||||
|
||||
mraa::Spi m_spi;
|
||||
|
||||
uint8_t m_cursorX;
|
||||
uint8_t m_cursorY;
|
||||
uint8_t m_textSize;
|
||||
uint8_t m_textColor;
|
||||
uint8_t m_textWrap;
|
||||
};
|
||||
}
|
||||
|
24
src/lcd/license.txt
Normal file
24
src/lcd/license.txt
Normal file
@ -0,0 +1,24 @@
|
||||
Software License Agreement (BSD License)
|
||||
|
||||
Copyright (c) 2012 Adafruit Industries. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
Loading…
x
Reference in New Issue
Block a user