kopia lustrzana https://github.com/pimoroni/pimoroni-pico
UC8151: New DisplayDriver based UC8151 driver.
HACK: Adds PicoGraphics_Pen1BitY to work around the UC8151 weird addressing. TODO: Replace hack with an in-place transform to UC8151 pixel order from Pen1Bit.pull/400/head
rodzic
646bd1a9b0
commit
04d8d66390
|
@ -27,6 +27,7 @@ add_subdirectory(rgbled)
|
||||||
add_subdirectory(icp10125)
|
add_subdirectory(icp10125)
|
||||||
add_subdirectory(scd4x)
|
add_subdirectory(scd4x)
|
||||||
add_subdirectory(hub75)
|
add_subdirectory(hub75)
|
||||||
|
add_subdirectory(uc8151)
|
||||||
add_subdirectory(uc8151_legacy)
|
add_subdirectory(uc8151_legacy)
|
||||||
add_subdirectory(pwm)
|
add_subdirectory(pwm)
|
||||||
add_subdirectory(servo)
|
add_subdirectory(servo)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
include(uc8151.cmake)
|
|
@ -0,0 +1,10 @@
|
||||||
|
set(DRIVER_NAME uc8151)
|
||||||
|
add_library(${DRIVER_NAME} INTERFACE)
|
||||||
|
|
||||||
|
target_sources(${DRIVER_NAME} INTERFACE
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/${DRIVER_NAME}.cpp)
|
||||||
|
|
||||||
|
target_include_directories(${DRIVER_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||||
|
|
||||||
|
# Pull in pico libraries that we need
|
||||||
|
target_link_libraries(${DRIVER_NAME} INTERFACE pico_stdlib hardware_spi pimoroni_bus pico_graphics)
|
|
@ -0,0 +1,549 @@
|
||||||
|
#include "uc8151.hpp"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
namespace pimoroni {
|
||||||
|
|
||||||
|
enum reg {
|
||||||
|
PSR = 0x00,
|
||||||
|
PWR = 0x01,
|
||||||
|
POF = 0x02,
|
||||||
|
PFS = 0x03,
|
||||||
|
PON = 0x04,
|
||||||
|
PMES = 0x05,
|
||||||
|
BTST = 0x06,
|
||||||
|
DSLP = 0x07,
|
||||||
|
DTM1 = 0x10,
|
||||||
|
DSP = 0x11,
|
||||||
|
DRF = 0x12,
|
||||||
|
DTM2 = 0x13,
|
||||||
|
LUT_VCOM = 0x20,
|
||||||
|
LUT_WW = 0x21,
|
||||||
|
LUT_BW = 0x22,
|
||||||
|
LUT_WB = 0x23,
|
||||||
|
LUT_BB = 0x24,
|
||||||
|
PLL = 0x30,
|
||||||
|
TSC = 0x40,
|
||||||
|
TSE = 0x41,
|
||||||
|
TSR = 0x43,
|
||||||
|
TSW = 0x42,
|
||||||
|
CDI = 0x50,
|
||||||
|
LPD = 0x51,
|
||||||
|
TCON = 0x60,
|
||||||
|
TRES = 0x61,
|
||||||
|
REV = 0x70,
|
||||||
|
FLG = 0x71,
|
||||||
|
AMV = 0x80,
|
||||||
|
VV = 0x81,
|
||||||
|
VDCS = 0x82,
|
||||||
|
PTL = 0x90,
|
||||||
|
PTIN = 0x91,
|
||||||
|
PTOU = 0x92,
|
||||||
|
PGM = 0xa0,
|
||||||
|
APG = 0xa1,
|
||||||
|
ROTP = 0xa2,
|
||||||
|
CCSET = 0xe0,
|
||||||
|
PWS = 0xe3,
|
||||||
|
TSSET = 0xe5
|
||||||
|
};
|
||||||
|
|
||||||
|
bool UC8151::is_busy() {
|
||||||
|
if(BUSY == PIN_UNUSED) return false;
|
||||||
|
return !gpio_get(BUSY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UC8151::busy_wait() {
|
||||||
|
while(is_busy()) {
|
||||||
|
tight_loop_contents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UC8151::reset() {
|
||||||
|
if(RESET == PIN_UNUSED) return;
|
||||||
|
gpio_put(RESET, 0); sleep_ms(10);
|
||||||
|
gpio_put(RESET, 1); sleep_ms(10);
|
||||||
|
busy_wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UC8151::default_luts() {
|
||||||
|
command(LUT_VCOM, {
|
||||||
|
0x00, 0x64, 0x64, 0x37, 0x00, 0x01,
|
||||||
|
0x00, 0x8c, 0x8c, 0x00, 0x00, 0x04,
|
||||||
|
0x00, 0x64, 0x64, 0x37, 0x00, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00
|
||||||
|
});
|
||||||
|
|
||||||
|
command(LUT_WW, {
|
||||||
|
0x54, 0x64, 0x64, 0x37, 0x00, 0x01,
|
||||||
|
0x60, 0x8c, 0x8c, 0x00, 0x00, 0x04,
|
||||||
|
0xa8, 0x64, 0x64, 0x37, 0x00, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
});
|
||||||
|
|
||||||
|
command(LUT_BW, {
|
||||||
|
0x54, 0x64, 0x64, 0x37, 0x00, 0x01,
|
||||||
|
0x60, 0x8c, 0x8c, 0x00, 0x00, 0x04,
|
||||||
|
0xa8, 0x64, 0x64, 0x37, 0x00, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
});
|
||||||
|
|
||||||
|
command(LUT_WB, {
|
||||||
|
0xa8, 0x64, 0x64, 0x37, 0x00, 0x01,
|
||||||
|
0x60, 0x8c, 0x8c, 0x00, 0x00, 0x04,
|
||||||
|
0x54, 0x64, 0x64, 0x37, 0x00, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
});
|
||||||
|
|
||||||
|
command(LUT_BB, {
|
||||||
|
0xa8, 0x64, 0x64, 0x37, 0x00, 0x01,
|
||||||
|
0x60, 0x8c, 0x8c, 0x00, 0x00, 0x04,
|
||||||
|
0x54, 0x64, 0x64, 0x37, 0x00, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
});
|
||||||
|
|
||||||
|
busy_wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UC8151::medium_luts() {
|
||||||
|
|
||||||
|
command(LUT_VCOM, {
|
||||||
|
0x00, 0x16, 0x16, 0x0d, 0x00, 0x01,
|
||||||
|
0x00, 0x23, 0x23, 0x00, 0x00, 0x02,
|
||||||
|
0x00, 0x16, 0x16, 0x0d, 0x00, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00
|
||||||
|
});
|
||||||
|
|
||||||
|
command(LUT_WW, {
|
||||||
|
0x54, 0x16, 0x16, 0x0d, 0x00, 0x01,
|
||||||
|
0x60, 0x23, 0x23, 0x00, 0x00, 0x02,
|
||||||
|
0xa8, 0x16, 0x16, 0x0d, 0x00, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
});
|
||||||
|
|
||||||
|
command(LUT_BW, {
|
||||||
|
0x54, 0x16, 0x16, 0x0d, 0x00, 0x01,
|
||||||
|
0x60, 0x23, 0x23, 0x00, 0x00, 0x02,
|
||||||
|
0xa8, 0x16, 0x16, 0x0d, 0x00, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
});
|
||||||
|
|
||||||
|
command(LUT_WB, {
|
||||||
|
0xa8, 0x16, 0x16, 0x0d, 0x00, 0x01,
|
||||||
|
0x60, 0x23, 0x23, 0x00, 0x00, 0x02,
|
||||||
|
0x54, 0x16, 0x16, 0x0d, 0x00, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
});
|
||||||
|
|
||||||
|
command(LUT_BB, {
|
||||||
|
0xa8, 0x16, 0x16, 0x0d, 0x00, 0x01,
|
||||||
|
0x60, 0x23, 0x23, 0x00, 0x00, 0x02,
|
||||||
|
0x54, 0x16, 0x16, 0x0d, 0x00, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
});
|
||||||
|
|
||||||
|
busy_wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UC8151::fast_luts() {
|
||||||
|
// 0x3c, 0x00, 0x2b, 0x2b, 0x24, 0x1a, ????
|
||||||
|
command(LUT_VCOM, {
|
||||||
|
0x00, 0x04, 0x04, 0x07, 0x00, 0x01,
|
||||||
|
0x00, 0x0c, 0x0c, 0x00, 0x00, 0x02,
|
||||||
|
0x00, 0x04, 0x04, 0x07, 0x00, 0x02,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00
|
||||||
|
});
|
||||||
|
|
||||||
|
command(LUT_WW, {
|
||||||
|
0x54, 0x04, 0x04, 0x07, 0x00, 0x01,
|
||||||
|
0x60, 0x0c, 0x0c, 0x00, 0x00, 0x02,
|
||||||
|
0xa8, 0x04, 0x04, 0x07, 0x00, 0x02,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
});
|
||||||
|
|
||||||
|
command(LUT_BW, {
|
||||||
|
0x54, 0x04, 0x04, 0x07, 0x00, 0x01,
|
||||||
|
0x60, 0x0c, 0x0c, 0x00, 0x00, 0x02,
|
||||||
|
0xa8, 0x04, 0x04, 0x07, 0x00, 0x02,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
});
|
||||||
|
|
||||||
|
command(LUT_WB, {
|
||||||
|
0xa8, 0x04, 0x04, 0x07, 0x00, 0x01,
|
||||||
|
0x60, 0x0c, 0x0c, 0x00, 0x00, 0x02,
|
||||||
|
0x54, 0x04, 0x04, 0x07, 0x00, 0x02,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
});
|
||||||
|
|
||||||
|
command(LUT_BB, {
|
||||||
|
0xa8, 0x04, 0x04, 0x07, 0x00, 0x01,
|
||||||
|
0x60, 0x0c, 0x0c, 0x00, 0x00, 0x02,
|
||||||
|
0x54, 0x04, 0x04, 0x07, 0x00, 0x02,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
});
|
||||||
|
|
||||||
|
command(PLL, {
|
||||||
|
HZ_200
|
||||||
|
});
|
||||||
|
|
||||||
|
busy_wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UC8151::turbo_luts() {
|
||||||
|
// 0x3c, 0x00, 0x2b, 0x2b, 0x24, 0x1a, ????
|
||||||
|
command(LUT_VCOM, {
|
||||||
|
0x00, 0x01, 0x01, 0x02, 0x00, 0x01,
|
||||||
|
0x00, 0x02, 0x02, 0x00, 0x00, 0x02,
|
||||||
|
0x00, 0x02, 0x02, 0x03, 0x00, 0x02,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00
|
||||||
|
});
|
||||||
|
|
||||||
|
command(LUT_WW, {
|
||||||
|
0x54, 0x01, 0x01, 0x02, 0x00, 0x01,
|
||||||
|
0x60, 0x02, 0x02, 0x00, 0x00, 0x02,
|
||||||
|
0xa8, 0x02, 0x02, 0x03, 0x00, 0x02,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
});
|
||||||
|
|
||||||
|
command(LUT_BW, {
|
||||||
|
0x54, 0x01, 0x01, 0x02, 0x00, 0x01,
|
||||||
|
0x60, 0x02, 0x02, 0x00, 0x00, 0x02,
|
||||||
|
0xa8, 0x02, 0x02, 0x03, 0x00, 0x02,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
});
|
||||||
|
|
||||||
|
command(LUT_WB, {
|
||||||
|
0xa8, 0x01, 0x01, 0x02, 0x00, 0x01,
|
||||||
|
0x60, 0x02, 0x02, 0x00, 0x00, 0x02,
|
||||||
|
0x54, 0x02, 0x02, 0x03, 0x00, 0x02,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
});
|
||||||
|
|
||||||
|
command(LUT_BB, {
|
||||||
|
0xa8, 0x01, 0x01, 0x02, 0x00, 0x01,
|
||||||
|
0x60, 0x02, 0x02, 0x00, 0x00, 0x02,
|
||||||
|
0x54, 0x02, 0x02, 0x03, 0x00, 0x02,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
});
|
||||||
|
|
||||||
|
command(PLL, {
|
||||||
|
HZ_200
|
||||||
|
});
|
||||||
|
|
||||||
|
busy_wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UC8151::init() {
|
||||||
|
// configure spi interface and pins
|
||||||
|
spi_init(spi, 12'000'000);
|
||||||
|
|
||||||
|
gpio_set_function(DC, GPIO_FUNC_SIO);
|
||||||
|
gpio_set_dir(DC, GPIO_OUT);
|
||||||
|
|
||||||
|
gpio_set_function(CS, GPIO_FUNC_SIO);
|
||||||
|
gpio_set_dir(CS, GPIO_OUT);
|
||||||
|
gpio_put(CS, 1);
|
||||||
|
|
||||||
|
gpio_set_function(RESET, GPIO_FUNC_SIO);
|
||||||
|
gpio_set_dir(RESET, GPIO_OUT);
|
||||||
|
gpio_put(RESET, 1);
|
||||||
|
|
||||||
|
gpio_set_function(BUSY, GPIO_FUNC_SIO);
|
||||||
|
gpio_set_dir(BUSY, GPIO_IN);
|
||||||
|
gpio_set_pulls(BUSY, true, false);
|
||||||
|
|
||||||
|
gpio_set_function(SCK, GPIO_FUNC_SPI);
|
||||||
|
gpio_set_function(MOSI, GPIO_FUNC_SPI);
|
||||||
|
|
||||||
|
setup();
|
||||||
|
};
|
||||||
|
|
||||||
|
void UC8151::setup(uint8_t speed) {
|
||||||
|
reset();
|
||||||
|
|
||||||
|
update_speed = speed;
|
||||||
|
|
||||||
|
if(speed == 0) {
|
||||||
|
command(PSR, {
|
||||||
|
RES_128x296 | LUT_OTP | FORMAT_BW | SHIFT_RIGHT | BOOSTER_ON | RESET_NONE
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
command(PSR, {
|
||||||
|
RES_128x296 | LUT_REG | FORMAT_BW | SHIFT_RIGHT | BOOSTER_ON | RESET_NONE
|
||||||
|
});
|
||||||
|
}
|
||||||
|
switch(speed) {
|
||||||
|
case 0:
|
||||||
|
// Note: the defult luts are built in so we don't really need to flash them here
|
||||||
|
// they are preserved above for posterity and reference mostly.
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
medium_luts();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
fast_luts();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
turbo_luts();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
command(PWR, {
|
||||||
|
VDS_INTERNAL | VDG_INTERNAL,
|
||||||
|
VCOM_VD | VGHL_16V,
|
||||||
|
0b101011,
|
||||||
|
0b101011,
|
||||||
|
0b101011
|
||||||
|
});
|
||||||
|
|
||||||
|
command(PON); // power on
|
||||||
|
busy_wait();
|
||||||
|
|
||||||
|
// booster soft start configuration
|
||||||
|
command(BTST, {
|
||||||
|
START_10MS | STRENGTH_3 | OFF_6_58US,
|
||||||
|
START_10MS | STRENGTH_3 | OFF_6_58US,
|
||||||
|
START_10MS | STRENGTH_3 | OFF_6_58US
|
||||||
|
});
|
||||||
|
|
||||||
|
command(PFS, {
|
||||||
|
FRAMES_1
|
||||||
|
});
|
||||||
|
|
||||||
|
command(TSE, {
|
||||||
|
TEMP_INTERNAL | OFFSET_0
|
||||||
|
});
|
||||||
|
|
||||||
|
command(TCON, {0x22}); // tcon setting
|
||||||
|
command(CDI, {(uint8_t)(inverted ? 0b01'01'1100 : 0b01'00'1100)}); // vcom and data interval
|
||||||
|
|
||||||
|
command(PLL, {
|
||||||
|
HZ_100
|
||||||
|
});
|
||||||
|
|
||||||
|
command(POF);
|
||||||
|
busy_wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UC8151::power_off() {
|
||||||
|
command(POF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UC8151::read(uint8_t reg, size_t len, uint8_t *data) {
|
||||||
|
gpio_put(CS, 0);
|
||||||
|
|
||||||
|
gpio_put(DC, 0); // command mode
|
||||||
|
spi_write_blocking(spi, ®, 1);
|
||||||
|
|
||||||
|
if(len > 0) {
|
||||||
|
gpio_put(DC, 1); // data mode
|
||||||
|
gpio_set_function(SCK, GPIO_FUNC_SIO);
|
||||||
|
gpio_set_dir(SCK, GPIO_OUT);
|
||||||
|
gpio_set_function(MOSI, GPIO_FUNC_SIO);
|
||||||
|
gpio_set_dir(MOSI, GPIO_IN);
|
||||||
|
for(auto i = 0u; i < len; i++) {
|
||||||
|
int byte = i / 8;
|
||||||
|
int bit = i % 8;
|
||||||
|
gpio_put(SCK, true);
|
||||||
|
bool value = gpio_get(MOSI);
|
||||||
|
data[byte] |= value << (7-bit);
|
||||||
|
gpio_put(SCK, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
gpio_set_function(SCK, GPIO_FUNC_SPI);
|
||||||
|
gpio_set_function(MOSI, GPIO_FUNC_SPI);
|
||||||
|
}
|
||||||
|
|
||||||
|
gpio_put(CS, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UC8151::command(uint8_t reg, size_t len, const uint8_t *data) {
|
||||||
|
gpio_put(CS, 0);
|
||||||
|
|
||||||
|
gpio_put(DC, 0); // command mode
|
||||||
|
spi_write_blocking(spi, ®, 1);
|
||||||
|
|
||||||
|
if(len > 0) {
|
||||||
|
gpio_put(DC, 1); // data mode
|
||||||
|
spi_write_blocking(spi, (const uint8_t*)data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
gpio_put(CS, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UC8151::data(size_t len, const uint8_t *data) {
|
||||||
|
gpio_put(CS, 0);
|
||||||
|
gpio_put(DC, 1); // data mode
|
||||||
|
spi_write_blocking(spi, (const uint8_t*)data, len);
|
||||||
|
gpio_put(CS, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UC8151::command(uint8_t reg, std::initializer_list<uint8_t> values) {
|
||||||
|
command(reg, values.size(), (uint8_t *)values.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
void UC8151::set_update_speed(uint8_t speed) {
|
||||||
|
setup(speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t UC8151::get_update_speed() {
|
||||||
|
return update_speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t UC8151::update_time() {
|
||||||
|
switch(update_speed) {
|
||||||
|
case 0:
|
||||||
|
return 4500;
|
||||||
|
case 1:
|
||||||
|
return 2000;
|
||||||
|
case 2:
|
||||||
|
return 800;
|
||||||
|
case 3:
|
||||||
|
return 250;
|
||||||
|
default:
|
||||||
|
return 4500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UC8151::partial_update(PicoGraphics *graphics, Rect region) {
|
||||||
|
// region.y is given in columns ("banks"), which are groups of 8 horiontal pixels
|
||||||
|
// region.x is given in pixels
|
||||||
|
|
||||||
|
uint8_t *fb = (uint8_t *)graphics->frame_buffer;
|
||||||
|
|
||||||
|
if(blocking) {
|
||||||
|
busy_wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
int cols = region.h / 8;
|
||||||
|
int y1 = region.y / 8;
|
||||||
|
|
||||||
|
int rows = region.w;
|
||||||
|
int x1 = region.x;
|
||||||
|
|
||||||
|
uint8_t partial_window[7] = {
|
||||||
|
(uint8_t)(region.y),
|
||||||
|
(uint8_t)(region.y + region.h - 1),
|
||||||
|
(uint8_t)(region.x >> 8),
|
||||||
|
(uint8_t)(region.x & 0xff),
|
||||||
|
(uint8_t)((region.x + region.w - 1) >> 8),
|
||||||
|
(uint8_t)((region.x + region.w - 1) & 0xff),
|
||||||
|
0b00000001 // PT_SCAN
|
||||||
|
};
|
||||||
|
command(PON); // turn on
|
||||||
|
|
||||||
|
command(PTIN); // enable partial mode
|
||||||
|
command(PTL, sizeof(partial_window), partial_window);
|
||||||
|
|
||||||
|
command(DTM2);
|
||||||
|
for (auto dx = 0; dx < rows; dx++) {
|
||||||
|
int sx = dx + x1;
|
||||||
|
int sy = y1;
|
||||||
|
data(cols, &fb[sy + (sx * (height / 8))]);
|
||||||
|
}
|
||||||
|
command(DSP); // data stop
|
||||||
|
|
||||||
|
command(DRF); // start display refresh
|
||||||
|
|
||||||
|
if(blocking) {
|
||||||
|
busy_wait();
|
||||||
|
|
||||||
|
command(POF); // turn off
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UC8151::update(PicoGraphics *graphics) {
|
||||||
|
uint8_t *fb = (uint8_t *)graphics->frame_buffer;
|
||||||
|
|
||||||
|
if(blocking) {
|
||||||
|
busy_wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
command(PON); // turn on
|
||||||
|
|
||||||
|
command(PTOU); // disable partial mode
|
||||||
|
|
||||||
|
command(DTM2, (width * height) / 8, fb); // transmit framebuffer
|
||||||
|
command(DSP); // data stop
|
||||||
|
|
||||||
|
command(DRF); // start display refresh
|
||||||
|
|
||||||
|
if(blocking) {
|
||||||
|
busy_wait();
|
||||||
|
|
||||||
|
command(POF); // turn off
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UC8151::off() {
|
||||||
|
busy_wait();
|
||||||
|
command(POF); // turn off
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,192 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <initializer_list>
|
||||||
|
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "hardware/spi.h"
|
||||||
|
#include "hardware/gpio.h"
|
||||||
|
|
||||||
|
#include "common/pimoroni_common.hpp"
|
||||||
|
#include "common/pimoroni_bus.hpp"
|
||||||
|
#include "libraries/pico_graphics/pico_graphics.hpp"
|
||||||
|
|
||||||
|
namespace pimoroni {
|
||||||
|
|
||||||
|
class UC8151 : public DisplayDriver {
|
||||||
|
enum PSR_FLAGS {
|
||||||
|
RES_96x230 = 0b00000000,
|
||||||
|
RES_96x252 = 0b01000000,
|
||||||
|
RES_128x296 = 0b10000000,
|
||||||
|
RES_160x296 = 0b11000000,
|
||||||
|
|
||||||
|
LUT_OTP = 0b00000000,
|
||||||
|
LUT_REG = 0b00100000,
|
||||||
|
|
||||||
|
FORMAT_BWR = 0b00000000,
|
||||||
|
FORMAT_BW = 0b00010000,
|
||||||
|
|
||||||
|
SCAN_DOWN = 0b00000000,
|
||||||
|
SCAN_UP = 0b00001000,
|
||||||
|
|
||||||
|
SHIFT_LEFT = 0b00000000,
|
||||||
|
SHIFT_RIGHT = 0b00000100,
|
||||||
|
|
||||||
|
BOOSTER_OFF = 0b00000000,
|
||||||
|
BOOSTER_ON = 0b00000010,
|
||||||
|
|
||||||
|
RESET_SOFT = 0b00000000,
|
||||||
|
RESET_NONE = 0b00000001
|
||||||
|
};
|
||||||
|
|
||||||
|
enum PWR_FLAGS_1 {
|
||||||
|
VDS_EXTERNAL = 0b00000000,
|
||||||
|
VDS_INTERNAL = 0b00000010,
|
||||||
|
|
||||||
|
VDG_EXTERNAL = 0b00000000,
|
||||||
|
VDG_INTERNAL = 0b00000001
|
||||||
|
};
|
||||||
|
|
||||||
|
enum PWR_FLAGS_2 {
|
||||||
|
VCOM_VD = 0b00000000,
|
||||||
|
VCOM_VG = 0b00000100,
|
||||||
|
|
||||||
|
VGHL_16V = 0b00000000,
|
||||||
|
VGHL_15V = 0b00000001,
|
||||||
|
VGHL_14V = 0b00000010,
|
||||||
|
VGHL_13V = 0b00000011
|
||||||
|
};
|
||||||
|
|
||||||
|
enum BOOSTER_FLAGS {
|
||||||
|
START_10MS = 0b00000000,
|
||||||
|
START_20MS = 0b01000000,
|
||||||
|
START_30MS = 0b10000000,
|
||||||
|
START_40MS = 0b11000000,
|
||||||
|
|
||||||
|
STRENGTH_1 = 0b00000000,
|
||||||
|
STRENGTH_2 = 0b00001000,
|
||||||
|
STRENGTH_3 = 0b00010000,
|
||||||
|
STRENGTH_4 = 0b00011000,
|
||||||
|
STRENGTH_5 = 0b00100000,
|
||||||
|
STRENGTH_6 = 0b00101000,
|
||||||
|
STRENGTH_7 = 0b00110000,
|
||||||
|
STRENGTH_8 = 0b00111000,
|
||||||
|
|
||||||
|
OFF_0_27US = 0b00000000,
|
||||||
|
OFF_0_34US = 0b00000001,
|
||||||
|
OFF_0_40US = 0b00000010,
|
||||||
|
OFF_0_54US = 0b00000011,
|
||||||
|
OFF_0_80US = 0b00000100,
|
||||||
|
OFF_1_54US = 0b00000101,
|
||||||
|
OFF_3_34US = 0b00000110,
|
||||||
|
OFF_6_58US = 0b00000111
|
||||||
|
};
|
||||||
|
|
||||||
|
enum PFS_FLAGS {
|
||||||
|
FRAMES_1 = 0b00000000,
|
||||||
|
FRAMES_2 = 0b00010000,
|
||||||
|
FRAMES_3 = 0b00100000,
|
||||||
|
FRAMES_4 = 0b00110000
|
||||||
|
};
|
||||||
|
|
||||||
|
enum TSE_FLAGS {
|
||||||
|
TEMP_INTERNAL = 0b00000000,
|
||||||
|
TEMP_EXTERNAL = 0b10000000,
|
||||||
|
|
||||||
|
OFFSET_0 = 0b00000000,
|
||||||
|
OFFSET_1 = 0b00000001,
|
||||||
|
OFFSET_2 = 0b00000010,
|
||||||
|
OFFSET_3 = 0b00000011,
|
||||||
|
OFFSET_4 = 0b00000100,
|
||||||
|
OFFSET_5 = 0b00000101,
|
||||||
|
OFFSET_6 = 0b00000110,
|
||||||
|
OFFSET_7 = 0b00000111,
|
||||||
|
|
||||||
|
OFFSET_MIN_8 = 0b00001000,
|
||||||
|
OFFSET_MIN_7 = 0b00001001,
|
||||||
|
OFFSET_MIN_6 = 0b00001010,
|
||||||
|
OFFSET_MIN_5 = 0b00001011,
|
||||||
|
OFFSET_MIN_4 = 0b00001100,
|
||||||
|
OFFSET_MIN_3 = 0b00001101,
|
||||||
|
OFFSET_MIN_2 = 0b00001110,
|
||||||
|
OFFSET_MIN_1 = 0b00001111
|
||||||
|
};
|
||||||
|
|
||||||
|
enum PLL_FLAGS {
|
||||||
|
// other frequency options exist but there doesn't seem to be much
|
||||||
|
// point in including them - this is a fair range of options...
|
||||||
|
HZ_29 = 0b00111111,
|
||||||
|
HZ_33 = 0b00111110,
|
||||||
|
HZ_40 = 0b00111101,
|
||||||
|
HZ_50 = 0b00111100,
|
||||||
|
HZ_67 = 0b00111011,
|
||||||
|
HZ_100 = 0b00111010,
|
||||||
|
HZ_200 = 0b00111001
|
||||||
|
};
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// Variables
|
||||||
|
//--------------------------------------------------
|
||||||
|
private:
|
||||||
|
spi_inst_t *spi = PIMORONI_SPI_DEFAULT_INSTANCE;
|
||||||
|
|
||||||
|
// interface pins with our standard defaults where appropriate
|
||||||
|
uint CS = SPI_BG_FRONT_CS;
|
||||||
|
uint DC = 20;
|
||||||
|
uint SCK = SPI_DEFAULT_SCK;
|
||||||
|
uint MOSI = SPI_DEFAULT_MOSI;
|
||||||
|
uint BUSY = PIN_UNUSED;
|
||||||
|
uint RESET = PIN_UNUSED;
|
||||||
|
|
||||||
|
uint8_t update_speed = 0;
|
||||||
|
bool inverted = false;
|
||||||
|
bool blocking = true;
|
||||||
|
|
||||||
|
public:
|
||||||
|
UC8151(uint16_t width, uint16_t height) : UC8151(width, height, {PIMORONI_SPI_DEFAULT_INSTANCE, SPI_BG_FRONT_CS, SPI_DEFAULT_SCK, SPI_DEFAULT_MOSI, PIN_UNUSED, 20, PIN_UNUSED}) {};
|
||||||
|
|
||||||
|
UC8151(uint16_t width, uint16_t height, SPIPins pins, uint busy=26, uint reset=21) :
|
||||||
|
DisplayDriver(width, height, ROTATE_0),
|
||||||
|
spi(pins.spi),
|
||||||
|
CS(pins.cs), DC(pins.dc), SCK(pins.sck), MOSI(pins.mosi), BUSY(busy), RESET(reset) {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// Methods
|
||||||
|
//--------------------------------------------------
|
||||||
|
public:
|
||||||
|
void busy_wait();
|
||||||
|
void reset();
|
||||||
|
void power_off();
|
||||||
|
|
||||||
|
// DisplayDriver API
|
||||||
|
bool is_busy() override;
|
||||||
|
void update(PicoGraphics *graphics) override;
|
||||||
|
void partial_update(PicoGraphics *graphics, Rect region) override;
|
||||||
|
|
||||||
|
// UC8151 Specific
|
||||||
|
void default_luts();
|
||||||
|
void medium_luts();
|
||||||
|
void fast_luts();
|
||||||
|
void turbo_luts();
|
||||||
|
|
||||||
|
void set_update_speed(uint8_t speed);
|
||||||
|
uint8_t get_update_speed();
|
||||||
|
uint32_t update_time();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void init();
|
||||||
|
void setup(uint8_t speed=0);
|
||||||
|
|
||||||
|
void read(uint8_t reg, size_t len, uint8_t *data);
|
||||||
|
void command(uint8_t reg, size_t len, const uint8_t *data);
|
||||||
|
void command(uint8_t reg, std::initializer_list<uint8_t> values);
|
||||||
|
void command(uint8_t reg) {command(reg, 0, nullptr);};
|
||||||
|
void data(size_t len, const uint8_t *data);
|
||||||
|
|
||||||
|
void update(bool blocking = true);
|
||||||
|
void partial_update(int x, int y, int w, int h, bool blocking = true);
|
||||||
|
void off();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -43,6 +43,8 @@ add_subdirectory(pico_trackball_display)
|
||||||
add_subdirectory(pico_audio)
|
add_subdirectory(pico_audio)
|
||||||
add_subdirectory(pico_wireless)
|
add_subdirectory(pico_wireless)
|
||||||
|
|
||||||
|
add_subdirectory(inky_pack)
|
||||||
|
|
||||||
add_subdirectory(plasma2040)
|
add_subdirectory(plasma2040)
|
||||||
add_subdirectory(badger2040)
|
add_subdirectory(badger2040)
|
||||||
add_subdirectory(tufty2040)
|
add_subdirectory(tufty2040)
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
set(OUTPUT_NAME inky_pack_demo)
|
||||||
|
|
||||||
|
add_executable(
|
||||||
|
${OUTPUT_NAME}
|
||||||
|
inky_pack_demo.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Pull in pico libraries that we need
|
||||||
|
target_link_libraries(${OUTPUT_NAME} pico_stdlib hardware_spi hardware_pwm hardware_dma rgbled button uc8151 pico_graphics)
|
||||||
|
|
||||||
|
# create map/bin/hex file etc.
|
||||||
|
pico_add_extra_outputs(${OUTPUT_NAME})
|
|
@ -0,0 +1,57 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include "drivers/uc8151/uc8151.hpp"
|
||||||
|
#include "libraries/pico_graphics/pico_graphics.hpp"
|
||||||
|
#include "button.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace pimoroni;
|
||||||
|
|
||||||
|
enum Pin {
|
||||||
|
A = 12,
|
||||||
|
B = 13,
|
||||||
|
C = 14,
|
||||||
|
D = 15,
|
||||||
|
E = 11,
|
||||||
|
UP = 15, // alias for D
|
||||||
|
DOWN = 11, // alias for E
|
||||||
|
USER = 23,
|
||||||
|
CS = 17,
|
||||||
|
CLK = 18,
|
||||||
|
MOSI = 19,
|
||||||
|
DC = 20,
|
||||||
|
RESET = 21,
|
||||||
|
BUSY = 26,
|
||||||
|
VBUS_DETECT = 24,
|
||||||
|
LED = 25,
|
||||||
|
BATTERY = 29,
|
||||||
|
ENABLE_3V3 = 10
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
UC8151 uc8151(296, 128);
|
||||||
|
PicoGraphics_Pen1BitY graphics(uc8151.width, uc8151.height, nullptr);
|
||||||
|
|
||||||
|
Button button_a(Pin::A);
|
||||||
|
Button button_b(Pin::B);
|
||||||
|
Button button_c(Pin::C);
|
||||||
|
Button button_d(Pin::D);
|
||||||
|
Button button_e(Pin::E);
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
graphics.set_pen(0);
|
||||||
|
graphics.clear();
|
||||||
|
|
||||||
|
graphics.set_pen(1);
|
||||||
|
graphics.set_font("bitmap8");
|
||||||
|
graphics.text("Hello World", {0, 0}, 296);
|
||||||
|
graphics.text("Has this worked?!", {0, 16}, 296);
|
||||||
|
|
||||||
|
uc8151.update(&graphics);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ add_library(pico_graphics
|
||||||
${CMAKE_CURRENT_LIST_DIR}/types.cpp
|
${CMAKE_CURRENT_LIST_DIR}/types.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/pico_graphics.cpp
|
${CMAKE_CURRENT_LIST_DIR}/pico_graphics.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/pico_graphics_pen_1bit.cpp
|
${CMAKE_CURRENT_LIST_DIR}/pico_graphics_pen_1bit.cpp
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/pico_graphics_pen_1bitY.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/pico_graphics_pen_p4.cpp
|
${CMAKE_CURRENT_LIST_DIR}/pico_graphics_pen_p4.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/pico_graphics_pen_p8.cpp
|
${CMAKE_CURRENT_LIST_DIR}/pico_graphics_pen_p8.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/pico_graphics_pen_rgb332.cpp
|
${CMAKE_CURRENT_LIST_DIR}/pico_graphics_pen_rgb332.cpp
|
||||||
|
|
|
@ -259,6 +259,21 @@ namespace pimoroni {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PicoGraphics_Pen1BitY : public PicoGraphics {
|
||||||
|
public:
|
||||||
|
uint8_t color;
|
||||||
|
|
||||||
|
PicoGraphics_Pen1BitY(uint16_t width, uint16_t height, void *frame_buffer);
|
||||||
|
void set_pen(uint c) override;
|
||||||
|
void set_pen(uint8_t r, uint8_t g, uint8_t b) override;
|
||||||
|
|
||||||
|
void set_pixel(const Point &p) override;
|
||||||
|
void set_pixel_span(const Point &p, uint l) override;
|
||||||
|
|
||||||
|
static size_t buffer_size(uint w, uint h) {
|
||||||
|
return w * h / 8;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class PicoGraphics_PenP4 : public PicoGraphics {
|
class PicoGraphics_PenP4 : public PicoGraphics {
|
||||||
public:
|
public:
|
||||||
|
@ -368,7 +383,9 @@ namespace pimoroni {
|
||||||
: width(width), height(height), rotation(rotation) {};
|
: width(width), height(height), rotation(rotation) {};
|
||||||
|
|
||||||
virtual void update(PicoGraphics *display) {};
|
virtual void update(PicoGraphics *display) {};
|
||||||
|
virtual void partial_update(PicoGraphics *display, Rect region) {};
|
||||||
virtual void set_backlight(uint8_t brightness) {};
|
virtual void set_backlight(uint8_t brightness) {};
|
||||||
|
virtual bool is_busy() {return false;};
|
||||||
virtual void cleanup() {};
|
virtual void cleanup() {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
#include "pico_graphics.hpp"
|
||||||
|
|
||||||
|
namespace pimoroni {
|
||||||
|
|
||||||
|
PicoGraphics_Pen1BitY::PicoGraphics_Pen1BitY(uint16_t width, uint16_t height, void *frame_buffer)
|
||||||
|
: PicoGraphics(width, height, frame_buffer) {
|
||||||
|
this->pen_type = PEN_1BIT;
|
||||||
|
if(this->frame_buffer == nullptr) {
|
||||||
|
this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PicoGraphics_Pen1BitY::set_pen(uint c) {
|
||||||
|
color = c != 0 ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PicoGraphics_Pen1BitY::set_pen(uint8_t r, uint8_t g, uint8_t b) {
|
||||||
|
color = r != 0 || g != 0 || b != 0 ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PicoGraphics_Pen1BitY::set_pixel(const Point &p) {
|
||||||
|
// pointer to byte in framebuffer that contains this pixel
|
||||||
|
uint8_t *buf = (uint8_t *)frame_buffer;
|
||||||
|
uint8_t *f = &buf[(p.y / 8) + (p.x * bounds.h / 8)];
|
||||||
|
|
||||||
|
uint bo = 7 - (p.y & 0b111);
|
||||||
|
|
||||||
|
// forceably clear the bit
|
||||||
|
*f &= ~(1U << bo);
|
||||||
|
|
||||||
|
// set pixel
|
||||||
|
*f |= (color << bo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PicoGraphics_Pen1BitY::set_pixel_span(const Point &p, uint l) {
|
||||||
|
Point po(p);
|
||||||
|
while(l--) {
|
||||||
|
set_pixel(po);
|
||||||
|
po.x++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Ładowanie…
Reference in New Issue