Files
bb_epaper/src/bb_eink.cpp
T
2024-09-22 11:44:10 +01:00

462 lines
11 KiB
C++

//
// bb_eink
// Copyright (c) 2024 BitBank Software, Inc.
// Written by Larry Bank (bitbank@pobox.com)
// Project started 9/11/2024
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifdef _LINUX_
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
// convert wire library constants into ArmbianIO values
#define OUTPUT GPIO_OUT
#define INPUT GPIO_IN
#define INPUT_PULLUP GPIO_IN_PULLUP
#define HIGH 1
#define LOW 0
void delay(int);
#else // Arduino
#endif // _LINUX_
#include "bb_eink.h"
#include "arduino_io.inl" // I/O (non-portable) code is in here
#include "bb_ei.inl" // All of the display interface code is in here
#include "bb_ei_gfx.inl" // drawing code
#include "Group5.h" // Group5 data compression library
#include "bb_font.h" // bitbank compressed font info
#ifdef __cplusplus
//
// C++ Class implementation
//
//uint32_t BBEINK::getRefreshTime(void)
//{
// return _bbei.iTimeout;
//}
void BBEINK::setPosition(int x, int y, int w, int h)
{
bbeiSetPosition(&_bbei, x, y, w, h);
}
int BBEINK::setPanelType(int iPanel)
{
return bbeiSetPanelType(&_bbei, iPanel);
}
void BBEINK::initIO(int iDC, int iReset, int iBusy, int iCS, int iMOSI, int iSCLK, uint32_t u32Speed)
{
_bbei.iCSPin = iCS;
_bbei.iMOSIPin = iMOSI;
_bbei.iCLKPin = iSCLK;
_bbei.iDCPin = iDC;
_bbei.iRSTPin = iReset;
_bbei.iBUSYPin = iBusy;
bbeiInitIO(&_bbei, u32Speed);
bbeiWakeUp(&_bbei);
bbeiSendCMDSequence(&_bbei, _bbei.pInitFull);
} /* initIO() */
int BBEINK::writePlane(int iPlane)
{
return bbeiWritePlane(&_bbei, iPlane);
} /* writePlane() */
int BBEINK::refresh(int iMode, bool bWait)
{
int rc;
rc = bbeiRefresh(&_bbei, iMode);
if (rc == BBEI_SUCCESS && bWait) {
bbeiWaitBusy(&_bbei);
}
return rc;
} /* refresh() */
//int BBEINK::getFlags(void)
//{
// return _bbei.iFlags;
//}
//void BBEINK::setFlags(int iFlags)
//{
// _bbei.iFlags = iFlags;
//}
void BBEINK::setBuffer(uint8_t *pBuffer)
{
_bbei.ucScreen = pBuffer;
}
int BBEINK::allocBuffer(void)
{
int iSize = ((_bbei.native_width+7)>>3) * _bbei.native_height;
if (_bbei.iFlags & (BBEI_3COLOR | BBEI_4COLOR) || _bbei.chip_type == BBEI_CHIP_UC81xx)
iSize *= 2; // 2 bit planes
_bbei.ucScreen = (uint8_t *)malloc(iSize);
if (_bbei.ucScreen != NULL) {
return BBEI_SUCCESS;
}
return BBEI_ERROR_NO_MEMORY; // failed
} /* allocBuffer() */
void * BBEINK::getBuffer(void)
{
return (void *)_bbei.ucScreen;
} /* getBuffer() */
void BBEINK::freeBuffer(void)
{
if (_bbei.ucScreen) {
free(_bbei.ucScreen);
_bbei.ucScreen = NULL;
}
} /* freeBuffer() */
uint32_t BBEINK::capabilities(void)
{
return _bbei.iFlags;
}
void BBEINK::setRotation(int iRotation)
{
// obdSetRotation(&_bbei, iRotation);
} /* setRotation() */
int BBEINK::getRotation(void)
{
return _bbei.iOrientation;
}
void BBEINK::fillScreen(int iColor, int iPlane)
{
bbeiFill(&_bbei, iColor, iPlane);
} /* fillScreen() */
void BBEINK::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
{
bbeiRectangle(&_bbei, x, y, x+w-1, y+h-1, color, 0);
} /* drawRect() */
void BBEINK::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
{
bbeiRectangle(&_bbei, x, y, x+w-1, y+h-1, color, 1);
} /* fillRect() */
void BBEINK::setTextWrap(bool bWrap)
{
_bbei.wrap = (int)bWrap;
}
void BBEINK::setTextColor(int iFG, int iBG)
{
if (iFG > BBEI_RED) iFG = BBEI_BLACK;
if (iBG > BBEI_RED) iBG = BBEI_BLACK;
if ((_bbei.iFlags & (BBEI_3COLOR | BBEI_4COLOR)) == 0) {
if (iFG == BBEI_RED) iFG = BBEI_BLACK; // can't set red color
if (iBG == BBEI_RED) iBG = BBEI_BLACK;
}
_bbei.iFG = iFG;
_bbei.iBG = (iBG == -1) ? iFG : iBG;
} /* setTextColor() */
void BBEINK::setCursor(int x, int y)
{
if (x >= 0)
_bbei.iCursorX = x;
if (y >= 0)
_bbei.iCursorY = y;
} /* setCursor() */
int BBEINK::loadBMP(const uint8_t *pBMP, int x, int y, int iFG, int iBG)
{
return bbeiLoadBMP(&_bbei, pBMP, x, y, iFG, iBG);
} /* loadBMP() */
int BBEINK::loadBMP3(const uint8_t *pBMP, int x, int y)
{
return bbeiLoadBMP3(&_bbei, pBMP, x, y);
} /* loadBMP3() */
void BBEINK::setFont(int iFont)
{
_bbei.iFont = iFont;
_bbei.pFont = NULL;
} /* setFont() */
void BBEINK::setFont(const void *pFont)
{
_bbei.iFont = -1;
_bbei.pFont = (void *)pFont;
} /* setFont() */
//void BBEINK::setFreeFont(const GFXfont *pFont)
//{
// _bbei.pFreeFont = (GFXfont *)pFont;
//} /* setFreeFont() */
void BBEINK::drawLine(int x1, int y1, int x2, int y2, int iColor)
{
bbeiDrawLine(&_bbei, x1, y1, x2, y2, iColor);
} /* drawLine() */
#ifdef _LINUX_
void BBEINK::print(const string &str)
{
print(str.c_str());
} /* print() */
void BBEINK::println(const string &str)
{
char ucTemp[4];
print(str);
ucTemp[0] = '\n';
ucTemp[1] = '\r';
ucTemp[2] = 0;
print((const char *)ucTemp);
} /* print() */
void BBEINK::print(const char *pString)
{
uint8_t *s = (uint8_t *)pString;
while (*s != 0) {
write(*s++);
}
} /* print() */
void BBEINK::println(const char *pString)
{
char ucTemp[4];
print(pString);
ucTemp[0] = '\n';
ucTemp[1] = '\r';
ucTemp[2] = 0;
print((const char *)ucTemp);
} /* println() */
void BBEINK::print(int value, int format)
{
char c, ucTemp[32];
char *d = &ucTemp[31];
if (value) {
d[0] = 0;
switch(format) {
case DEC:
while (value) {
d--;
*d = '0' + (value % 10);
value /= 10;
}
break;
case HEX:
while (value) {
d--;
c = value & 0xf;
if (c < 10)
*d = '0' + c;
else
*d = 'A' + (c-10);
value >>= 4;
}
break;
case OCT:
while (value) {
d--;
*d = '0' + (value & 7);
value >>= 3;
}
break;
case BIN:
while (value) {
d--;
*d = '0' + (value & 1);
value >>= 1;
}
break;
default:
break;
}
} else { // if zero value
d--;
*d = '0';
}
print((const char *)d);
} /* print() */
void BBEINK::println(int value, int format)
{
char ucTemp[4];
print(value, format);
ucTemp[0] = '\n';
ucTemp[1] = '\r';
ucTemp[2] = 0;
print((const char *)ucTemp);
} /* println() */
#endif // _LINUX_
//
// write (Arduino Print friend class)
//
#ifndef __AVR__
size_t BBEINK::write(uint8_t c) {
char szTemp[2]; // used to draw 1 character at a time to the C methods
int w, h;
szTemp[0] = c; szTemp[1] = 0;
if (_bbei.pFont == NULL) { // use built-in fonts
if (_bbei.iFont == FONT_8x8 || _bbei.iFont == FONT_6x8) {
h = 8;
w = (_bbei.iFont == FONT_8x8) ? 8 : 6;
} else if (_bbei.iFont == FONT_12x16) {
h = 16;
w = 12;
}
if (c == '\n') { // Newline?
_bbei.iCursorX = 0; // Reset x to zero,
_bbei.iCursorY += h; // advance y one line
} else if (c != '\r') { // Ignore carriage returns
if (_bbei.wrap && ((_bbei.iCursorX + w) > _bbei.width)) { // Off right?
_bbei.iCursorX = 0; // Reset x to zero,
_bbei.iCursorY += h; // advance y one line
}
bbeiWriteString(&_bbei, -1, -1, szTemp, _bbei.iFont, _bbei.iFG);
}
} else { // Custom font
BB_FONT *pBBF = (BB_FONT *)_bbei.pFont;
if (c == '\n') {
_bbei.iCursorX = 0;
_bbei.iCursorY += pBBF->height;
} else if (c != '\r') {
if (c >= pBBF->first && c <= pBBF->last) {
BB_GLYPH *pBBG = &pBBF->glyphs[c-pBBF->first];
w = pBBG->width;
h = pBBG->height;
if ((w > 0) && (h > 0)) { // Is there an associated bitmap?
int16_t xo = pBBG->xOffset;
w += xo; // xadvance
h = pBBF->height;
if (_bbei.wrap && ((_bbei.iCursorX + w) > _bbei.width)) {
_bbei.iCursorX = 0;
_bbei.iCursorY += h;
}
bbeiWriteStringCustom(&_bbei, (BB_FONT *)_bbei.pFont, -1, -1, szTemp, _bbei.iFG, _bbei.iPlane);
}
}
}
}
return 1;
} /* write() */
#endif // !__AVR__
void BBEINK::drawPixel(int16_t x, int16_t y, uint8_t color)
{
bbeiSetPixel(&_bbei, x, y, color);
}
int16_t BBEINK::getCursorX(void)
{
return _bbei.iCursorX;
}
int16_t BBEINK::getCursorY(void)
{
return _bbei.iCursorY;
}
void BBEINK::getTextBounds(const char *string, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h)
{
if (_bbei.pFont) {
int width, top, bottom;
bbeiGetStringBox((BB_FONT *)_bbei.pFont, string, &width, &top, &bottom);
*x1 = x;
*w = width;
*y1 = y + top;
*h = (bottom - top + 1);
}
}
void BBEINK::getTextBounds(const String &str, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h)
{
getTextBounds(str.c_str(), x, y, x1, y1, w, h);
}
int BBEINK::dataTime(void)
{
return _bbei.iDataTime;
}
int BBEINK::opTime(void)
{
return _bbei.iOpTime;
}
int16_t BBEINK::width(void)
{
return _bbei.width;
}
int16_t BBEINK::height(void)
{
return _bbei.height;
}
void BBEINK::drawCircle(int32_t x, int32_t y, int32_t r, uint32_t color)
{
bbeiEllipse(&_bbei, x, y, r, r, color, 0);
}
void BBEINK::fillCircle(int32_t x, int32_t y, int32_t r, uint32_t color)
{
bbeiEllipse(&_bbei, x, y, r, r, color, 1);
}
void BBEINK::drawEllipse(int16_t x, int16_t y, int32_t rx, int32_t ry, uint16_t color)
{
bbeiEllipse(&_bbei, x, y, rx, ry, color, 0);
}
void BBEINK::fillEllipse(int16_t x, int16_t y, int32_t rx, int32_t ry, uint16_t color)
{
bbeiEllipse(&_bbei, x, y, rx, ry, color, 1);
}
void BBEINK::sleep(int bDeep)
{
bbeiSleep(&_bbei, bDeep);
}
void BBEINK::wait(bool bQuick)
{
bbeiWaitBusy(&_bbei);
}
void BBEINK::drawString(const char *pText, int x, int y)
{
if (_bbei.pFont) {
bbeiWriteStringCustom(&_bbei, (BB_FONT *)_bbei.pFont, x, y, (char *)pText, _bbei.iFG, 0); // iPlane);
} else if (_bbei.iFont >= FONT_6x8 && _bbei.iFont < FONT_COUNT) {
bbeiWriteString(&_bbei, x, y, (char *)pText, _bbei.iFont, _bbei.iFG);
}
} /* drawString() */
void BBEINK::setPlane(int iPlane)
{
_bbei.iPlane = iPlane;
}
int BBEINK::getPlane(void)
{
return _bbei.iPlane;
}
int BBEINK::getChip(void)
{
return _bbei.chip_type;
}
void BBEINK::drawSprite(const uint8_t *pSprite, int cx, int cy, int iPitch, int x, int y, uint8_t iColor)
{
bbeiDrawSprite(&_bbei, pSprite, cx, cy, iPitch, x, y, iColor);
}
#endif // __cplusplus