mirror of
https://github.com/usetrmnl/bb_epaper.git
synced 2026-04-29 13:43:26 -07:00
Added initial RPI-Pico support and fixed graphics primitives for back buffer and no-buffer
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user