Added initial RPI-Pico support and fixed graphics primitives for back buffer and no-buffer

This commit is contained in:
Laurence Bank
2024-09-27 18:39:47 +01:00
parent 2579ad4750
commit 77955a604f
7 changed files with 318 additions and 171 deletions
+3 -1
View File
@@ -1,5 +1,7 @@
#include "debug.h"
#include "debug.h"
// This makes the compiled code smaller on systems with almost no RAM
// since it can't use a local copy of the framebuffer for drawing
#define NO_RAM
#include "../../../src/bb_epaper.h"
#include "../../ch32v_io.inl"
#include "../../../src/bb_ep.inl"
+64
View File
@@ -0,0 +1,64 @@
# Generated Cmake Pico project file
cmake_minimum_required(VERSION 3.13)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Initialise pico_sdk from installed location
# (note this can come from environment, CMake cache etc)
# == DO NEVER EDIT THE NEXT LINES for Raspberry Pi Pico VS Code Extension to work ==
if(WIN32)
set(USERHOME $ENV{USERPROFILE})
else()
set(USERHOME $ENV{HOME})
endif()
set(sdkVersion 2.0.0)
set(toolchainVersion 13_2_Rel1)
set(picotoolVersion 2.0.0)
set(picoVscode ${USERHOME}/.pico-sdk/cmake/pico-vscode.cmake)
if (EXISTS ${picoVscode})
include(${picoVscode})
endif()
# ====================================================================================
set(PICO_BOARD pico2 CACHE STRING "Board type")
# Pull in Raspberry Pi Pico SDK (must be before project)
include(pico_sdk_import.cmake)
project(epaper_example C CXX ASM)
# Initialise the Raspberry Pi Pico SDK
pico_sdk_init()
# Add executable. Default name is the project name, version 0.1
add_executable(epaper_example epaper_example.c )
pico_set_program_name(epaper_example "epaper_example")
pico_set_program_version(epaper_example "0.1")
# Modify the below lines to enable/disable output over UART/USB
pico_enable_stdio_uart(epaper_example 0)
pico_enable_stdio_usb(epaper_example 0)
# Add the standard library to the build
target_link_libraries(epaper_example
pico_stdlib)
# Add the standard include files to the build
target_include_directories(epaper_example PRIVATE
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts or any other standard includes, if required
)
# Add any user requested libraries
target_link_libraries(epaper_example
hardware_spi
hardware_i2c
)
pico_add_extra_outputs(epaper_example)
+59
View File
@@ -0,0 +1,59 @@
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/spi.h"
#include "hardware/i2c.h"
// SPI Defines
// We are going to use SPI 0, and allocate it to the following GPIO pins
// Pins can be changed, see the GPIO function select table in the datasheet for information on GPIO assignments
#define SPI_PORT spi0
#define PIN_MISO 16
#define PIN_CS 17
#define PIN_SCK 18
#define PIN_MOSI 19
// I2C defines
// This example will use I2C0 on GPIO8 (SDA) and GPIO9 (SCL) running at 400KHz.
// Pins can be changed, see the GPIO function select table in the datasheet for information on GPIO assignments
#define I2C_PORT i2c0
#define I2C_SDA 8
#define I2C_SCL 9
#include "../../src/bb_epaper.h"
#include "../pico_io.inl"
#include "../../src/bb_ep.inl"
#include "../../src/bb_ep_gfx.inl"
//#include "Roboto_Black_20r.h"
BBEPDISP bbep; // the main display structure
int main()
{
stdio_init_all();
// SPI initialisation. This example will use SPI at 1MHz.
spi_init(SPI_PORT, 1000*1000);
gpio_set_function(PIN_MISO, GPIO_FUNC_SPI);
gpio_set_function(PIN_CS, GPIO_FUNC_SIO);
gpio_set_function(PIN_SCK, GPIO_FUNC_SPI);
gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI);
// Chip select is active-low, so we'll initialise it to a driven-high state
gpio_set_dir(PIN_CS, GPIO_OUT);
gpio_put(PIN_CS, 1);
// For more examples of SPI use see https://github.com/raspberrypi/pico-examples/tree/master/spi
// I2C Initialisation. Using it at 400Khz.
i2c_init(I2C_PORT, 400*1000);
gpio_set_function(I2C_SDA, GPIO_FUNC_I2C);
gpio_set_function(I2C_SCL, GPIO_FUNC_I2C);
gpio_pull_up(I2C_SDA);
gpio_pull_up(I2C_SCL);
// For more examples of I2C use see https://github.com/raspberrypi/pico-examples/tree/master/i2c
while (true) {
printf("Hello, world!\n");
sleep_ms(1000);
}
}
@@ -0,0 +1,84 @@
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
# This can be dropped into an external project to help locate this SDK
# It should be include()ed prior to project()
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_TAG} AND (NOT PICO_SDK_FETCH_FROM_GIT_TAG))
set(PICO_SDK_FETCH_FROM_GIT_TAG $ENV{PICO_SDK_FETCH_FROM_GIT_TAG})
message("Using PICO_SDK_FETCH_FROM_GIT_TAG from environment ('${PICO_SDK_FETCH_FROM_GIT_TAG}')")
endif ()
if (PICO_SDK_FETCH_FROM_GIT AND NOT PICO_SDK_FETCH_FROM_GIT_TAG)
set(PICO_SDK_FETCH_FROM_GIT_TAG "master")
message("Using master as default value for PICO_SDK_FETCH_FROM_GIT_TAG")
endif()
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
set(PICO_SDK_FETCH_FROM_GIT_TAG "${PICO_SDK_FETCH_FROM_GIT_TAG}" CACHE FILEPATH "release tag for SDK")
if (NOT PICO_SDK_PATH)
if (PICO_SDK_FETCH_FROM_GIT)
include(FetchContent)
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
if (PICO_SDK_FETCH_FROM_GIT_PATH)
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
endif ()
# GIT_SUBMODULES_RECURSE was added in 3.17
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0")
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
GIT_SUBMODULES_RECURSE FALSE
)
else ()
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
)
endif ()
if (NOT pico_sdk)
message("Downloading Raspberry Pi Pico SDK")
FetchContent_Populate(pico_sdk)
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
endif ()
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
else ()
message(FATAL_ERROR
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
)
endif ()
endif ()
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
if (NOT EXISTS ${PICO_SDK_PATH})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
endif ()
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
endif ()
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
include(${PICO_SDK_INIT_CMAKE_FILE})
+103 -170
View File
@@ -299,10 +299,11 @@ void bbepDrawSprite(BBEPDISP *pBBEP, const uint8_t *pSprite, int cx, int cy, int
} // for ty
}
} /* bbepDrawSprite() */
//
// Set (or clear) an individual pixel
// The local copy of the frame buffer is used to avoid
// reading data from the display controller
// This function only works with a back buffer defined. A bufferless version
// is possible, but would be too impractical.
//
int bbepSetPixel(BBEPDISP *pBBEP, int x, int y, unsigned char ucColor)
{
int i;
@@ -370,11 +371,6 @@ uint8_t b=0, *s, *d=NULL;
uint8_t ucFill, dst_mask=0, src_mask;
uint8_t bFlipped = 0;
if (pBBEP->ucScreen == NULL) {
// no BG specified or no back buffer, BG color is opposite of FG
if (iFG == -1) iFG = BBEP_WHITE;
if (iBG == -1) iBG = BBEP_BLACK;
}
// Don't use pgm_read_word because it can cause an unaligned
// access on RP2040 for odd addresses
i16 = pgm_read_byte(pBMP);
@@ -391,6 +387,14 @@ uint8_t bFlipped = 0;
else bFlipped = 1;
if (cy + dy > pBBEP->height) // must fit on the display
return BBEP_ERROR_BAD_PARAMETER;
if (pBBEP->ucScreen == NULL) {
// no BG specified or no back buffer, BG color is opposite of FG
if (iFG == -1) iFG = BBEP_WHITE;
if (iBG == -1) iBG = BBEP_BLACK;
bbepSetAddrWindow(pBBEP, dx, dy, cx+(dx&7), cy);
bbepStartWrite(pBBEP, pBBEP->iPlane); // get ready to write the data
}
i16 = pgm_read_byte(pBMP + 28);
i16 += (pgm_read_byte(pBMP+29)<<8);
if (i16 != 1) // must be 1 bit per pixel
@@ -410,51 +414,32 @@ uint8_t bFlipped = 0;
iFG = iBG;
iBG = x; // swap colors
}
for (y=0; y<cy; y++)
{
if (!pBBEP->ucScreen)
{
dst_mask = (1 << (y & 7));
d = u8Cache;
if ((y & 7) == 0)
memset(u8Cache, ucFill, sizeof(u8Cache));
}
s = (uint8_t *)&pBMP[iOffBits + (y*iPitch)];
src_mask = 0;
if (!pBBEP->ucScreen) // direct to display
{
for (x=0; x<cx; x++)
{
if (src_mask == 0) // need to load the next byte
{
b = pgm_read_byte(s++);
src_mask = 0x80; // MSB on left
}
if (b & src_mask)
{
if (iFG == BBEP_WHITE)
d[0] &= ~dst_mask;
else
d[0] |= dst_mask;
} else {
if (iBG == BBEP_BLACK)
d[0] |= dst_mask;
else
d[0] &= ~dst_mask;
}
d++;
src_mask >>= 1;
} // for x
for (y=0; y<cy; y++) {
s = (uint8_t *)&pBMP[iOffBits + (y*iPitch)];
if (!pBBEP->ucScreen) {
if (dx & 7) { // need to shift it over by 1-7 bits
uint8_t *d = u8Cache, uc1, uc0 = 0; // last shifted byte
uint8_t n = dx & 7; // shift amount
for (int j=0; j<cx+7; j+= 8) {
uc1 = pgm_read_byte(s++);
uc0 |= (uc1 >> n);
*d++ = uc0;
uc0 = uc1 << (8-n);
}
*d++ = uc0; // store final byte
*d++ = 0; // and a zero for good measure
} else {
memcpy_P(u8Cache, s, (cx+7)>>3);
}
bbepWriteData(pBBEP, u8Cache, (cx+(dx&7)+7)>>3);
} else { // use the setPixel function for more features
for (x=0; x<cx; x++)
{
if (src_mask == 0) // need to load the next byte
{
src_mask = 0; // make it read a byte to start
for (x=0; x<cx; x++) {
if (src_mask == 0) { // need to load the next byte
b = pgm_read_byte(s++);
src_mask = 0x80; // MSB on left
}
if (b & src_mask)
{
if (b & src_mask) {
if (iFG >= 0)
bbepSetPixel(pBBEP, dx+x, dy+y, (uint8_t)iFG);
} else {
@@ -464,11 +449,6 @@ uint8_t bFlipped = 0;
src_mask >>= 1;
} // for x
}
if (pBBEP->ucScreen == NULL && ((y & 7) == 7 || y == cy-1)) // dump to LCD
{
bbepSetAddrWindow(pBBEP, dx, y+dy, cx, 1);
bbepWriteData(pBBEP, u8Cache, cx);
}
} // for y
return BBEP_SUCCESS;
} /* bbepLoadBMP() */
@@ -1000,7 +980,10 @@ void bbepAllocBuffer(BBEPDISP *pBBEP)
pBBEP->iScreenOffset = 0;
#endif
} /* obdAllocBuffer() */
//
// Draw a line from x1,y1 to x2,y2 in the given color
// This function supports both buffered and bufferless drawing
//
void bbepDrawLine(BBEPDISP *pBBEP, int x1, int y1, int x2, int y2, uint8_t ucColor)
{
int temp;
@@ -1010,29 +993,23 @@ void bbepDrawLine(BBEPDISP *pBBEP, int x1, int y1, int x2, int y2, uint8_t ucCol
uint8_t *p, *pStart, ucFill = 0, mask, bOld, bNew;
int xinc, yinc;
int y, x;
int iPitch = pBBEP->width;
int iPitch;
int iRedOffset = 0;
if (pBBEP == NULL) return;
if (x1 < 0 || x2 < 0 || y1 < 0 || y2 < 0 || x1 >= pBBEP->width || x2 >= pBBEP->width || y1 >= pBBEP->height || y2 >= pBBEP->height)
return;
iPitch = (pBBEP->width + 7)>>3;
if (ucColor >= BBEP_YELLOW && pBBEP->iFlags & (BBEP_3COLOR | BBEP_4COLOR)) {
// use the second half of the image buffer
iRedOffset = pBBEP->width * ((pBBEP->height+7)/8);
iRedOffset = iPitch * pBBEP->height;
}
if (!pBBEP->ucScreen) { // no back buffer, draw in local buffer
if (pBBEP->type >= EPD42_400x300) {
// no back buffer on EPD means we may need to invert the color
if (ucColor >= BBEP_YELLOW)
ucColor = BBEP_BLACK;
else
ucColor = 1-ucColor; // swap black/white
}
if (ucColor == BBEP_BLACK) // fill with opposite color
ucFill = 0;
else
ucFill = 0xff;
else
ucFill = 0;
memset(u8Cache, ucFill, sizeof(u8Cache));
}
if(abs(dx) > abs(dy)) {
@@ -1057,45 +1034,45 @@ void bbepDrawLine(BBEPDISP *pBBEP, int x1, int y1, int x2, int y2, uint8_t ucCol
yinc = -1;
}
if (pBBEP->ucScreen) {
p = pStart = &pBBEP->ucScreen[iRedOffset + x1 + ((y >> 3) * iPitch)]; // point to current spot in back buffer
p = pStart = &pBBEP->ucScreen[iRedOffset + (x1>>3) + (y * iPitch)]; // point to current spot in back buffer
} else { // no back buffer, draw directly to the display RAM
p = pStart = u8Cache;
}
mask = 1 << (y & 7); // current bit offset
mask = 0x80 >> (x1 & 7); // current bit offset
for(x=x1; x1 <= x2; x1++) {
if (ucColor == BBEP_BLACK)
*p++ |= mask; // set pixel and increment x pointer
else
*p++ &= ~mask;
if (ucColor == BBEP_BLACK) {
*p &= ~mask; // set pixel and increment x pointer
} else {
*p |= mask;
}
mask >>= 1;
if (mask == 0) {
p++;
mask = 0x80; // next byte
}
error -= dy;
if (error < 0)
{
error += dx;
if (yinc > 0)
mask <<= 1;
else
mask >>= 1;
if (mask == 0) // we've moved outside the current row, write the data we changed
{
bbepSetAddrWindow(pBBEP, x, y, 8*(int)(p-pStart), 1);
bbepWriteData(pBBEP, pStart, (int)(p-pStart)); // write the row we changed
error += dx;
if (pBBEP->ucScreen) {
p += (yinc > 0) ? iPitch : -iPitch;
pStart = p;
} else { // no buffer
// y is changing, dump the pixels we modified
bbepSetAddrWindow(pBBEP, x, y1, 8*(int)(p-pStart), 1);
bbepStartWrite(pBBEP, pBBEP->iPlane);
bbepWriteData(pBBEP, pStart, (int)(p-pStart)); // write the row we changed
memset(pStart, ucFill, (int)(p-pStart));
p = pStart;
}
x = x1+1; // we've already written the byte at x1
y1 = y+yinc;
if (pBBEP->ucScreen) {
p += (yinc > 0) ? iPitch : -iPitch;
pStart = p;
} else { // no buffer
memset(pStart, ucFill, (int)(p-pStart));
p = pStart;
}
mask = 1 << (y1 & 7);
}
y += yinc;
y1 += yinc;
}
} // for x1
if (p != pStart) // some data needs to be written
{
bbepSetAddrWindow(pBBEP, x, y, 8*(int)(p-pStart), 1);
bbepSetAddrWindow(pBBEP, x, y1, 8*(int)(p-pStart), 1);
bbepStartWrite(pBBEP, pBBEP->iPlane);
bbepWriteData(pBBEP, pStart, (int)(p-pStart));
}
} else {
@@ -1109,69 +1086,44 @@ void bbepDrawLine(BBEPDISP *pBBEP, int x1, int y1, int x2, int y2, uint8_t ucCol
y1 = y2;
y2 = temp;
}
if (pBBEP->ucScreen) {
p = &pBBEP->ucScreen[iRedOffset + x1 + ((y1 >> 3) * iPitch)]; // point to current spot in back buffer
bOld = bNew = p[0]; // current pixels
} else {
p = u8Cache;
bOld = bNew = ucFill;
}
mask = 1 << (y1 & 7); // current bit offset
dx = (x2 - x1);
error = dy >> 1;
xinc = 1;
if (dx < 0)
{
if (dx < 0) {
dx = -dx;
xinc = -1;
}
for(x = x1; y1 <= y2; y1++) {
if (ucColor == BBEP_BLACK)
bNew |= mask; // set the pixel
else
bNew &= ~mask;
error -= dx;
mask <<= 1; // y1++
if (mask == 0) // we're done with this byte, write it if necessary
{
if (bOld != bNew)
{
p[0] = bNew; // save to RAM
bbepSetAddrWindow(pBBEP, x, y1, 8, 1);
bbepWriteData(pBBEP, &bNew, 1);
} // data changed
for(; y1 <= y2; y1++) {
mask = 0x80 >> (x1 & 7); // current bit offset
if (pBBEP->ucScreen) {
p += iPitch; // next line
bOld = bNew = p[0];
p = &pBBEP->ucScreen[iRedOffset + (x1>>3) + (y1 * iPitch)]; // point if (ucColor == BBEP_BLACK)
bOld = bNew = p[0]; // current pixels
} else {
bOld = bNew = ucFill;
}
mask = 1; // start at LSB again
}
if (error < 0)
{
error += dy;
if (bOld != bNew) // write the last byte we modified if it changed
{
p[0] = bNew; // save to RAM
bbepSetAddrWindow(pBBEP, x, y1, 8, 1);
bbepWriteData(pBBEP, &bNew, 1);
if (ucColor == BBEP_BLACK) {
bNew &= ~mask; // set the pixel
} else {
bNew |= mask;
}
x += xinc;
if (pBBEP->ucScreen) {
p += xinc;
bOld = bNew = p[0];
} else {
bOld = bNew = ucFill;
}
error -= dx;
if (bOld != bNew) {
if (pBBEP->ucScreen) {
p[0] = bNew; // save to RAM
p += iPitch; // next line
bOld = bNew = p[0];
} else {
bbepSetAddrWindow(pBBEP, x1, y1, 8, 1);
bbepStartWrite(pBBEP, pBBEP->iPlane);
bbepWriteData(pBBEP, &bNew, 1);
bOld = bNew = ucFill;
}
}
if (error < 0) {
error += dy;
x1 += xinc;
}
} // for y
if (bOld != bNew) // write the last byte we modified if it changed
{
p[0] = bNew; // save to RAM
bbepSetAddrWindow(pBBEP, x, y2, 8, 1);
bbepWriteData(pBBEP, &bNew, 1);
}
} // y major case
} /* bbepDrawLine() */
@@ -1185,18 +1137,18 @@ static void DrawScaledPixel(BBEPDISP *pBBEP, int iCX, int iCY, int x, int y, int
int iPitch;
int iRedOffset = 0;
iPitch = pBBEP->width;
iPitch = (pBBEP->width + 7) >> 3;
if (ucColor >= BBEP_YELLOW && pBBEP->iFlags & (BBEP_3COLOR | BBEP_4COLOR)) {
// use the second half of the image buffer
iRedOffset = pBBEP->width * ((pBBEP->height+7)/8);
iRedOffset = iPitch * pBBEP->height;
}
if (iXFrac != 0x10000) x = ((x * iXFrac) >> 16);
if (iYFrac != 0x10000) y = ((y * iYFrac) >> 16);
x += iCX; y += iCY;
if (x < 0 || x >= pBBEP->width || y < 0 || y >= pBBEP->height)
return; // off the screen
d = &pBBEP->ucScreen[iRedOffset + ((y >> 3)*iPitch) + x];
ucMask = 1 << (y & 7);
d = &pBBEP->ucScreen[iRedOffset + (x>>3) + (y * iPitch)];
ucMask = 0x80 >> (x & 7);
if (ucColor)
*d |= ucMask;
else
@@ -1208,15 +1160,7 @@ static void DrawScaledPixel(BBEPDISP *pBBEP, int iCX, int iCY, int x, int y, int
static void DrawScaledLine(BBEPDISP *pBBEP, int iCX, int iCY, int x, int y, int32_t iXFrac, int32_t iYFrac, uint8_t ucColor)
{
int iLen, x2;
uint8_t *d, ucMask;
int iPitch;
int iRedOffset = 0;
if (ucColor >= BBEP_YELLOW && pBBEP->iFlags & (BBEP_3COLOR | BBEP_4COLOR)) {
// use the second half of the image buffer
iRedOffset = pBBEP->width * ((pBBEP->height+7)/8);
}
iPitch = pBBEP->width;
if (iXFrac != 0x10000) x = ((x * iXFrac) >> 16);
if (iYFrac != 0x10000) y = ((y * iYFrac) >> 16);
iLen = x*2;
@@ -1226,19 +1170,7 @@ static void DrawScaledLine(BBEPDISP *pBBEP, int iCX, int iCY, int x, int y, int3
return; // completely off the screen
if (x < 0) x = 0;
if (x2 >= pBBEP->width) x2 = pBBEP->width-1;
iLen = x2 - x + 1; // new length
d = &pBBEP->ucScreen[iRedOffset + ((y >> 3)*iPitch) + x];
ucMask = 1 << (y & 7);
if (ucColor) // white
{
for (; iLen > 0; iLen--)
*d++ |= ucMask;
}
else // black
{
for (; iLen > 0; iLen--)
*d++ &= ~ucMask;
}
bbepDrawLine(pBBEP, x, y, x2, y, ucColor);
} /* DrawScaledLine() */
//
// Draw the 8 pixels around the Bresenham circle
@@ -1275,8 +1207,8 @@ void bbepEllipse(BBEPDISP *pBBEP, int iCenterX, int iCenterY, int32_t iRadiusX,
int32_t iXFrac, iYFrac;
int iRadius, iDelta, x, y;
if (pBBEP == NULL || pBBEP->ucScreen == NULL)
return; // must have back buffer defined
if (pBBEP == NULL || (pBBEP->ucScreen == NULL && !bFilled)
return; // must have back buffer defined for outline mode
if (iRadiusX <= 0 || iRadiusY <= 0) return; // invalid radii
@@ -1312,6 +1244,7 @@ void bbepEllipse(BBEPDISP *pBBEP, int iCenterX, int iCenterY, int32_t iRadiusX,
//
// Draw an outline or filled rectangle
//
//
void bbepRectangle(BBEPDISP *pBBEP, int x1, int y1, int x2, int y2, uint8_t ucColor, uint8_t bFilled)
{
uint8_t *d, ucMask, ucMask2;
+1
View File
@@ -8,6 +8,7 @@
// included in the file ./LICENSE.
//
// As of the Change Date specified in that file, in accordance with
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// ./APL.txt.
+4
View File
@@ -17,6 +17,10 @@
#ifdef ARDUINO
#include <Arduino.h>
#ifdef __AVR__
// AVR doesn't have enough RAM for a back buffer
#define NO_RAM
#endif // __AVR__
#else // _LINUX_
// for Print support
#define DEC 10