diff --git a/ch32v/epaper_demo/User/main.c b/ch32v/epaper_demo/User/main.c index a9212d6..cfa915b 100644 --- a/ch32v/epaper_demo/User/main.c +++ b/ch32v/epaper_demo/User/main.c @@ -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" diff --git a/rpi_pico/epaper_example/CMakeLists.txt b/rpi_pico/epaper_example/CMakeLists.txt new file mode 100644 index 0000000..21668a5 --- /dev/null +++ b/rpi_pico/epaper_example/CMakeLists.txt @@ -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) + diff --git a/rpi_pico/epaper_example/epaper_example.c b/rpi_pico/epaper_example/epaper_example.c new file mode 100644 index 0000000..b25375a --- /dev/null +++ b/rpi_pico/epaper_example/epaper_example.c @@ -0,0 +1,59 @@ +#include +#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); + } +} diff --git a/rpi_pico/epaper_example/pico_sdk_import.cmake b/rpi_pico/epaper_example/pico_sdk_import.cmake new file mode 100644 index 0000000..a0721d0 --- /dev/null +++ b/rpi_pico/epaper_example/pico_sdk_import.cmake @@ -0,0 +1,84 @@ +# This is a copy of /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}) diff --git a/src/bb_ep_gfx.inl b/src/bb_ep_gfx.inl index 51fcec2..89231fe 100644 --- a/src/bb_ep_gfx.inl +++ b/src/bb_ep_gfx.inl @@ -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; yucScreen) - { - 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>= 1; - } // for x + for (y=0; yucScreen) { + 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> 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= 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; diff --git a/src/bb_epaper.cpp b/src/bb_epaper.cpp index 1c3af7b..4a099ac 100644 --- a/src/bb_epaper.cpp +++ b/src/bb_epaper.cpp @@ -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. diff --git a/src/bb_epaper.h b/src/bb_epaper.h index 24e4a5e..121c4b7 100644 --- a/src/bb_epaper.h +++ b/src/bb_epaper.h @@ -17,6 +17,10 @@ #ifdef ARDUINO #include +#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