Skip to content

API and constants

Larry Bank edited this page Oct 24, 2022 · 14 revisions

The OneBitDisplay library is based completely on C99 code and has a C++ wrapper class on top. Both the C and C++ APIs are equally valid for use in projects on embedded, Linux or PC.
Here is the C++ class definition:

{
  public:
    ONE_BIT_DISPLAY() { memset(&_obd, 0, sizeof(_obd)); _obd.iFG = OBD_BLACK; _obd.render = 1; _obd.type = OLED_128x64; _obd.iSpeed = 400000;}
    void SPIbegin(int iType = OLED_128x64, int32_t iSpeed = 2000000);
    void setSPIPins(int iCS, int iMOSI, int iSCLK, int iDC, int iReset=-1, int iLED=-1);
    void setI2CPins(int iSDA, int iSCL, int iReset=-1);
    BBI2C *getBB();
    void setBB(BBI2C *pBB);
    void setFlags(int iFlags);
    void setContrast(uint8_t ucContrast);
    void display(bool bRefresh = true);
    void displayFast();
    void displayPartial(int x, int y, int w, int h, uint8_t *pBuffer = NULL);
    void setBitBang(bool bBitBang);
    void setRender(bool bRAMOnly);
    int I2Cbegin(int iType=OLED_128x64, int iAddr=-1, int32_t iSpeed=400000);
    void setRotation(int iAngle);
    uint8_t getRotation(void);
    void fillScreen(int iColor);
    void setBuffer(uint8_t *pBuffer);
    bool allocBuffer(void);
    void * getBuffer(void);
    void freeBuffer(void);
    void setScroll(bool bScroll);
    void setTextWrap(bool bOn);
    void setTextSize(uint8_t s);
    void setTextSize(uint8_t sx, uint8_t sy);
    void drawPixel(int16_t x, int16_t y, uint16_t color);
    void drawSprite(uint8_t *pSprite, int cx, int cy, int iPitch, int x, int y, uint8_t iPriority);
    void drawTile(const uint8_t *pTile, int x, int y, int iRotation, int bInvert, int bRender);
    void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
    void setTextColor(int iFG, int iBG = -1);
    void setCursor(int x, int y);
    void setPower(bool bOn);
    int loadBMP(uint8_t *pBMP, int x, int y, int iFG, int iBG);
    int loadBMP3(uint8_t *pBMP, int x, int y);
    int16_t getCursorX(void);
    int16_t getCursorY(void);
    void wake(void);
    void sleep(void);
    void getTextBounds(const char *string, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
    void getTextBounds(const String &str, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
    void setTextWrap(bool bWrap);
    void setFont(int iFont);
    void setFreeFont(const GFXfont *pFont);
    int16_t height(void);
    int16_t width(void);
    void setPosition(int x, int y, int w, int h);
    void pushPixels(uint8_t *pPixels, int iCount);
    void pushImage(int x, int y, int w, int h, uint16_t *pixels);
    void drawLine(int x1, int y1, int x2, int y2, int iColor);
    void drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
    void drawCircle(int32_t x, int32_t y, int32_t r, uint32_t color);
    void fillCircle(int32_t x, int32_t y, int32_t r, uint32_t color);
    void drawEllipse(int16_t x, int16_t y, int32_t rx, int32_t ry, uint16_t color);
    void fillEllipse(int16_t x, int16_t y, int32_t rx, int32_t ry, uint16_t color);
#ifdef _LINUX_
    void print(const char *pString);
    void println(const char *pString);
    void print(int, int);
    void println(int, int);
    void print(const string &);
    void println(const string &);
    size_t write(uint8_t ucChar);
    void delayMicroseconds(int iTime);
#else
#ifndef __AVR__
    using Print::write;
    virtual size_t write(uint8_t);
#endif // !__AVR__
#endif // _LINUX_

  private:
    OBDISP _obd;
}; // class BB_SPI_LCD

The Print class is unique to Arduino and doesn't exist on Linux; I wrote work-alike functions to take its place on non-Arduino targets.
Here are the C++ class methods described in detail, along with the C equivalent:

Initializes an I2C display controller (C method):
int obdI2CInit(OBDISP *pOBD, int iType, int iAddr, int bFlip, int bInvert, int bWire, int iSDAPin, int iSCLPin, int iResetPin, int32_t iSpeed);
(C++ methods):
void setI2CPins(int iSDA, int iSCL, int iReset=-1);
int I2Cbegin(int iType=OLED_128x64, int iAddr=-1, int32_t iSpeed=400000);
Both methods use the value -1 to indicate default displays (SSD1306 128x64), dynamically find the address (0x3C or 0x3D), and default I2C pins (defined in Arduino for the target board).

Initialize an SPI display controller (C method):
void obdSPIInit(OBDISP *pOBD, int iType, int iDC, int iCS, int iReset, int iMOSI, int iCLK, int iLED, int bFlip, int bInvert, int iBitBang, int32_t iSpeed);
(C++ methods):
void setSPIPins(int iCS, int iMOSI, int iSCLK, int iDC, int iReset=-1, int iLED=-1);
void SPIbegin(int iType = OLED_128x64, int32_t iSpeed = 2000000);
Similar to the I2C methods, -1 indicates default values for the display type, SPI pins, and absence of reset/led pins.

Provide or revoke a back buffer. Many operations work by directly drawing on the display buffer without a local copy, but there are limitations. For target systems like AVR which may not have sufficient RAM to hold the entire frame buffer, all display types can draw text, lines, and BMP images.
Pass NULL to revoke the buffer. Make sure you provide a buffer large enough for your display (e.g. 128x64 needs 1K - 1024 bytes)
void obdSetBackBuffer(OBDISP *pOBD, uint8_t *pBuffer);
void obdAllocBuffer(OBDISP *pOBD);
(C++ methods):
void setBuffer(uint8_t *pBuffer); - provide your own buffer
bool allocBuffer(void); - use malloc() to allocate an internal buffer

Sets the contrast/brightness (0=off, 255=brightest)
(C method):
void obdSetContrast(OBDISP *pOBD, unsigned char ucContrast);
(C++ method):
void setContrast(uint8_t ucContrast);

Load a 1-bpp Windows bitmap (BMP file)
Pass the pointer to the beginning of the BMP file header, and the upper left coordinates. Bitmaps too large to display or invalid will return -1. Black/White/Red e-paper displays support loading 4-bit (16-color) image files. The code will do a best effort to match the colors to the closest display color.
(C method):
int obdLoadBMP(OBDISP *pOBD, uint8_t *pBMP, int bInvert, int bRender);
(C++ methods):
int loadBMP(uint8_t *pBMP, int x, int y, int iFG, int iBG);
int loadBMP3(uint8_t *pBMP, int x, int y);

Power up/down the LCD or OLED display; useful for low power situations
(C method):
void obdPower(OBDISP *pOBD, uint8_t bOn);
(C++ method):
void setPower(bool bOn);

Set the current cursor position; the coordinates represent the pixel column and row. The cursor position affects only text drawing. When drawing using the internal fonts, the y coordinate will be rounded to a multiple of 8 due to the internal byte layout of graphics memory.
(C method):
void obdSetCursor(OBDISP *pOBD, int x, int y);
(C++ method):
void setCursor(int x, int y);

Turn text wrap on or off
(C method):
void obdSetTextWrap(OBDISP *pOBD, int bWrap);
(C++ method):
void setTextWrap(bool bOn);

Draw a string of Adafruit_GFX compatible text (bitmap fonts) at the given x,y coordinates. You supply it with a pointer to the font descriptor and the font active pixels (not background cell) will be drawn in the given color.
(C method):
int obdWriteStringCustom(OBDISP *pOBD, GFXfont *pFont, int x, int y, char *szMsg, uint8_t ucColor);
(C++ methods):
All of the C++ text functions will use the currently selected font, so if a custom font is selected, it will be used.

This function returns the width, top line and bottom line of a given Adafruit_GFX compatible line of text. The top and bottom line values are relative to a baseline (Y value of 0) passed to obdWriteStringCustom(). The top value will be negative.
void obdGetStringBox(GFXfont *pFont, char *szMsg, int *width, int *top, int *bottom);

Draw a string of characters at the given col+row with the given scroll offset. The scroll offset allows you to horizontally scroll text which does not fit on the width of the display. The offset represents the pixels to skip when drawing the text. An offset of 0 starts at the beginning of the text. The system remembers where the last text was written (the cursor position). To continue writing from the last position, set the x,y values to -1. The text can optionally wrap around to the next line by calling oledSetTextWrap(1), otherwise text which would go off the right edge will not be drawn and the cursor will be left "off screen" until set to a new position explicitly. Returns 0 for success, -1 for invalid parameter
int obdWriteString(OBDISP *pOBD, int iScrollX, int x, int y, char *szMsg, int iSize, int bInvert, int bRender);

Draw a string with scaling. The scale factor (x & y) are unsigned 16-bit values which represent a fraction. The value 256 equals 1:1 (original size). To draw at 250% scale, you would use a value of 640 (256 x 2.5). For now, this only supports the FONT_6x8 and FONT_8x8 sizes. Depending on the demand, I may implement this for all types of font drawing. The last parameter represents the drawing direction and can be one of the following four values: ROT_0, ROT_90, ROT_180, ROT_270. Since this allows drawing of any size text on any pixel boundaries, it requires a backing buffer and can only draw into RAM.
int obdScaledString(OBDISP *pOBD, int x, int y, char *szMsg, int iSize, int bInvert, int iXScale, int iYScale, int iRotation);

Fill the frame buffer with a byte pattern or predefined color. For e-paper, the color has more significance because red is sent to a second memory plane.
(C method):
void obdFill(OBDISP *pOBD, uint8_t ucData, int bRender);
(C++ method):
void fillScreen(uint8_t ucData);

Set (or clear) an individual pixel. The local copy of the frame buffer is used to avoid reading data from the display controller (which isn't possible in most configurations). This function needs a backbuffer to be defined otherwise, new pixels will erase old pixels within the same byte.
(C method):
int obdSetPixel(OBDISP *pOBD, int x, int y, uint8_t ucColor, int bRender);
(C++ method):
int drawPixel(int x, int y, uint8_t ucColor);

Send the entire (ram copy) of the frame buffer to the display. If passed a NULL pointer, it will use the internal framebuffer. If neither exists (when using an e-paper device), it will cause a display refresh from the display's own internal RAM. The C++ version allows optionally sending the data to the display without causing a refresh (on e-paper displays).
(C method):
void obdDumpBuffer(OBDISP *pOBD, uint8_t *pBuffer);
(C++ method):
void display(bool bRefresh = true);

Write a single row of pixels to a Sharp Memory LCD. This function is only for memory LCDs since they must be updated a whole line at a time. The number of bytes in the buffer must be equal to the display width divided by 8. For example. For the 400x240 LCD, you must provide 50 bytes of pixel data (an entire line) when you use this function. This limit is due to the way the Sharp LCDs work and cannot be changed.The bytes are laid out left to right with the MSB on the left. For example, pixel 0 of the line is bit 7 (0x80) of the first byte. The data is sent directly to the LCD and does not modify the back buffer.
(C method only):
void obdWriteLCDLine(OBDISP *pOBD, uint8_t *pBuffer, int iLine);

Render a sprite/rectangle of pixels from a provided buffer to the display. The row values refer to byte rows, not pixel rows due to the memory layout of OLEDs.
Returns 0 for success, -1 for invalid parameter
(C method):
int obdDrawGFX(OBDISP *pOBD, uint8_t *pSrc, int iSrcCol, int iSrcRow, int iDestCol, int iDestRow, int iWidth, int iHeight, int iSrcPitch);
(C++ method):
int drawGFX(uint8_t *pSrc, int iSrcCol, int iSrcRow, int iDestCol, int iDestRow, int iWidth, int iHeight, int iSrcPitch);

Draw a line between 2 points
(C method):
void obdDrawLine(OBDISP *pOBD, int x1, int y1, int x2, int y2, uint8_t ucColor, int bRender);
(C++ method):
void drawLine(int x1, int y1, int x2, int y2, uint8_t ucColor);

Scroll the internal buffer by 1 scanline (up/down), width is in pixels, lines is group of 8 rows.
Returns 0 for success, -1 for invalid parameter
(C method):
int obdScrollBuffer(OBDISP *pOBD, int iStartCol, int iEndCol, int iStartRow, int iEndRow, int bUp);
(C++ method):
int scrollBuffer(int iStartCol, int iEndCol, int iStartRow, int iEndRow, int bUp);

Draw a sprite of any size in any position. If it goes beyond the left/right or top/bottom edges, it's trimmed to show the valid parts. This function requires a back buffer to be defined. The priority color (0 or 1) determines which color is painted when a 1 is encountered in the source image; e.g. when 0, the input bitmap acts like a mask to clear the destination where bits are set.
(C method):
void obdDrawSprite(OBDISP *pOBD, uint8_t *pSprite, int cx, int cy, int iPitch, int x, int y, uint8_t iPriority);
(C++ method):
void drawSprite(uint8_t *pSprite, int cx, int cy, int iPitch, int x, int y, uint8_t iPriority);

Draw a 16x16 tile in any of 4 rotated positions. Assumes input image is laid out like "normal" graphics with the MSB on the left and 2 bytes per line. On AVR, the source image is assumed to be in FLASH memory. The function can draw the tile on byte boundaries, so the x value can be from 0 to 112 and y can be from 0 to 6. (C method):
void obdDrawTile(OBDISP *pOBD, const uint8_t *pTile, int x, int y, int iRotation, int bInvert, int bRender);
(C++ method):
drawTile(const uint8_t *pTile, int x, int y, int iRotation, int bInvert, int bRender);

Draw an outline or filled ellipse. If the X and Y radius are equal, it will draw a perfect circle.

void obdEllipse(OBDISP *pOBD, int iCenterX, int iCenterY, int32_t iRadiusX, int32_t iRadiusY, uint8_t ucColor, uint8_t bFilled);

Draw an outline or filled rectangle

void obdRectangle(OBDISP *pOBD, int x1, int y1, int x2, int y2, uint8_t ucColor, uint8_t bFilled);

Turn the LCD backlight on or off

void obdBacklight(OBDISP *pODB, int bOn);

Copy/convert the bitmap backing buffer into any other format/orientation. The internal format of bitmap memory mimics that of OLED/LCD displays - bytes are oriented vertically with the least significant bit at the top. Many raster displays have the bytes laid out horizontally with the most significant bit on the left. Any combination is possible with obdCopy() as well as horizontal and vertical mirroring and rotating by 90 degrees. By combining the rotation flag with h_flip and v_flip, it's possible to create output at all 4 angles (0, 90, 180, 270).
The following constant flags can be combined to specify the output format:
Bit / Byte direction options -
OBD_LSB_FIRST 0x001
OBD_MSB_FIRST 0x002
OBD_VERT_BYTES 0x004
OBD_HORZ_BYTES 0x008
Orientation options -
OBD_ROTATE_90 0x010
OBD_FLIP_VERT 0x020
OBD_FLIP_HORZ 0x040
OBD_INVERT 0x080

void obdCopy(OBDISP *pODB, int iFlags, uint8_t *pDest);

The memory layout

If you define a back buffer for your display or use a virtual display (LCD_VIRTUAL), the memory layout will be the same as that of OLED/LCD displays. That is, from lower to higher addresses tracks from left to right. Each column is a byte and each pixel is a single bit where the LSB (least significant bit) represents the top row. For example, if the first byte of your buffer contains the value 0xc0, this means that pixels (0,0) and (0,1) are 'lit' and pixels (0,2) through (0,7) are not lit. This same memory layout is used for the back buffer of the Sharp Memory LCDs even though their internal memory layout is different. The obdDumpBuffer() function will translate the data to look correct on Sharp memory LCDs. To use the memory with output devices that have a different memory layout, you can use the obdCopy() function to create output in any orientation (rotated, flipped), any bit direction (LSB first / MSB first) and any byte orientation (horizontal or vertical).

The font size enumerated values:
FONT_6x8
FONT_8x8
FONT_12x16
FONT_16x16
FONT_16x32

Clone this wiki locally