Move scroll_text, show_text, bitmap_1d and set_pixels into C++ library
Move scroll_text into the C++ library and make it support std::string. Move show_bitmap_1d to set_bitmap_1d in the C++ library. Use it as the basis for show_text and scroll_text. Change show_text to set_text since it does not implicitly show the result. Add a new pico-scroll demo to show off the scrolling text functionality.
This commit is contained in:
parent
54e4c1c177
commit
8a15da1f66
|
@ -1,10 +1,2 @@
|
|||
add_executable(
|
||||
scroll
|
||||
demo.cpp
|
||||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(scroll pico_stdlib pico_scroll)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(scroll)
|
||||
include(demo.cmake)
|
||||
include(scroll-text.cmake)
|
|
@ -0,0 +1,10 @@
|
|||
add_executable(
|
||||
scroll
|
||||
demo.cpp
|
||||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(scroll pico_stdlib pico_scroll)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(scroll)
|
|
@ -12,6 +12,7 @@ PicoScroll pico_scroll;
|
|||
int main() {
|
||||
|
||||
pico_scroll.init();
|
||||
pico_scroll.scroll_text("Hello World, how are you today?", 255, 100);
|
||||
|
||||
|
||||
bool a_pressed = false;
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
add_executable(
|
||||
scroll-text
|
||||
scroll-text.cpp
|
||||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(scroll-text pico_stdlib pico_scroll)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(scroll-text)
|
|
@ -0,0 +1,41 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "pico/stdlib.h"
|
||||
|
||||
#include "pico_scroll.hpp"
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
PicoScroll pico_scroll;
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
pico_scroll.init();
|
||||
|
||||
while(true) {
|
||||
pico_scroll.scroll_text("Hello World, how are you today?", 64, 100);
|
||||
sleep_ms(500);
|
||||
|
||||
pico_scroll.set_text("Test", 64);
|
||||
pico_scroll.update();
|
||||
sleep_ms(1000);
|
||||
|
||||
// Set pixels to a chessboard pattern
|
||||
char pixels[PicoScroll::WIDTH * PicoScroll::HEIGHT] = {};
|
||||
|
||||
pico_scroll.set_pixels(pixels);
|
||||
for (int y = 0; y < PicoScroll::HEIGHT; y++) {
|
||||
for (int x = 0; x < PicoScroll::WIDTH; x++) {
|
||||
pixels[y * PicoScroll::WIDTH + x] = ((x + y) & 0b1) * 64;
|
||||
}
|
||||
}
|
||||
|
||||
pico_scroll.set_pixels(pixels);
|
||||
pico_scroll.update();
|
||||
|
||||
sleep_ms(1000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,10 +1 @@
|
|||
add_library(pico_scroll INTERFACE)
|
||||
|
||||
target_sources(pico_scroll INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/pico_scroll.cpp
|
||||
)
|
||||
|
||||
target_include_directories(pico_scroll INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(pico_scroll INTERFACE pico_stdlib hardware_i2c)
|
||||
include(pico_scroll.cmake)
|
|
@ -1,7 +1,11 @@
|
|||
add_library(pico_scroll INTERFACE)
|
||||
|
||||
target_sources(pico_scroll INTERFACE
|
||||
set(PICO_SCROLL_SOURCES
|
||||
${CMAKE_CURRENT_LIST_DIR}/pico_scroll.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/pico_scroll_font.cpp)
|
||||
|
||||
target_sources(pico_scroll INTERFACE
|
||||
${PICO_SCROLL_SOURCES}
|
||||
)
|
||||
|
||||
target_include_directories(pico_scroll INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "hardware/i2c.h"
|
||||
|
||||
#include "pico_scroll.hpp"
|
||||
#include "pico_scroll_font.hpp"
|
||||
|
||||
enum pin {
|
||||
SDA = 4,
|
||||
|
@ -84,6 +85,77 @@ namespace pimoroni {
|
|||
memset(__fb, 0, BUFFER_SIZE);
|
||||
}
|
||||
|
||||
void PicoScroll::set_pixels(const char *pixels) {
|
||||
for (int y = 0; y < HEIGHT; y++) {
|
||||
for (int x = 0; x < WIDTH; x++) {
|
||||
set_pixel(x, y, pixels[y * WIDTH + x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PicoScroll::set_bitmap_1d(const char *bitmap, size_t bitmap_len, int brightness, int offset) {
|
||||
for (int x = 0; x < WIDTH; x++) {
|
||||
int k = offset + x;
|
||||
if ((k >= 0) && (k < (int)bitmap_len)) {
|
||||
unsigned char col = bitmap[k];
|
||||
for (int y = 0; y < HEIGHT; y++) {
|
||||
int val = brightness * ((col >> y) & 1);
|
||||
set_pixel(x, y, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PicoScroll::set_text(const char *text, size_t text_len, int brightness, int offset) {
|
||||
int draw_buffer_len = PicoScroll::WIDTH + 7;
|
||||
unsigned char draw_buffer[draw_buffer_len];
|
||||
|
||||
// clear the scroll, so only need to write visible bytes
|
||||
clear();
|
||||
|
||||
if ((offset < -WIDTH) || (offset > (int)(6 * text_len))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// compute what can actually be seen, render only that...
|
||||
// modify offset and bfr_len accordingly
|
||||
if (offset < 0) {
|
||||
int space = 1 + (WIDTH + offset) / 6;
|
||||
if (space < (int)text_len) {
|
||||
text_len = space;
|
||||
}
|
||||
} else {
|
||||
int start = offset / 6;
|
||||
offset -= start * 6;
|
||||
text_len = text_len - start;
|
||||
if (text_len > 4) {
|
||||
text_len = 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (draw_buffer_len > (int)(6 * text_len)) {
|
||||
draw_buffer_len = 6 * text_len;
|
||||
}
|
||||
|
||||
render_text(text, text_len, draw_buffer, draw_buffer_len);
|
||||
set_bitmap_1d((const char *)draw_buffer, draw_buffer_len, brightness, offset);
|
||||
}
|
||||
|
||||
void PicoScroll::scroll_text(const char *text, size_t text_len, int brightness, int delay_ms) {
|
||||
int draw_buffer_len = 6 * text_len;
|
||||
|
||||
unsigned char *draw_buffer = (unsigned char *)malloc(sizeof(unsigned char) * draw_buffer_len);
|
||||
render_text(text, text_len, draw_buffer, draw_buffer_len);
|
||||
|
||||
for (int offset = -WIDTH; offset < draw_buffer_len; offset++) {
|
||||
clear();
|
||||
set_bitmap_1d((const char *)draw_buffer, draw_buffer_len, brightness, offset);
|
||||
update();
|
||||
sleep_ms(delay_ms);
|
||||
}
|
||||
free(draw_buffer);
|
||||
}
|
||||
|
||||
void PicoScroll::update() {
|
||||
i2c_write(COLOR_OFFSET, (const char *)__fb, BUFFER_SIZE);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <string>
|
||||
#pragma once
|
||||
|
||||
namespace pimoroni {
|
||||
|
@ -20,6 +21,16 @@ namespace pimoroni {
|
|||
public:
|
||||
void init();
|
||||
void update();
|
||||
void set_pixels(const char *pixels);
|
||||
void set_bitmap_1d(const char *bitmap, size_t bitmap_len, int brightness, int offset);
|
||||
void scroll_text(const char *text, size_t text_len, int brightness, int delay_ms);
|
||||
void scroll_text(std::string text, int brightness, int delay_ms=100) {
|
||||
scroll_text(text.c_str(), text.length(), brightness, delay_ms);
|
||||
};
|
||||
void set_text(const char *text, size_t text_len, int brightness, int offset);
|
||||
void set_text(std::string text, int brightness, int offset=0) {
|
||||
set_text(text.c_str(), text.length(), brightness, offset);
|
||||
}
|
||||
void set_pixel(uint8_t x, uint8_t y, uint8_t v);
|
||||
void clear();
|
||||
bool is_pressed(uint8_t button);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "pico_scroll_font.h"
|
||||
#include "pico_scroll_font.hpp"
|
||||
|
||||
/* static font data */
|
||||
static unsigned char __bitmap[256][5] = {
|
||||
|
@ -133,12 +133,12 @@ static unsigned char __bitmap[256][5] = {
|
|||
};
|
||||
|
||||
/* render a text string to a pre-allocated buffer - strlen(text) * 6 bytes */
|
||||
int render(unsigned char *text, int nchr, unsigned char *buffer, int nbfr) {
|
||||
int render_text(const char *text, unsigned int nchr, unsigned char *buffer, unsigned int nbfr) {
|
||||
// TODO check nbfr >= 6 * nchr
|
||||
|
||||
for (int i = 0; i < nchr; i++) {
|
||||
unsigned char *symbol = __bitmap[text[i]];
|
||||
for (int j = 0; j < 5; j++) {
|
||||
for (unsigned int i = 0; i < nchr; i++) {
|
||||
unsigned char *symbol = __bitmap[(unsigned int)text[i]];
|
||||
for (unsigned int j = 0; j < 5; j++) {
|
||||
buffer[i * 6 + j] = symbol[j];
|
||||
}
|
||||
buffer[i * 6 + 5] = 0x0;
|
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
// external font API
|
||||
int render_text(const char *text, unsigned int nchr, unsigned char *buffer, unsigned int nbfr);
|
|
@ -1,10 +1,11 @@
|
|||
include(${CMAKE_CURRENT_LIST_DIR}/../../../libraries/pico_scroll/pico_scroll.cmake)
|
||||
|
||||
add_library(usermod_pico_scroll INTERFACE)
|
||||
|
||||
target_sources(usermod_pico_scroll INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/pico_scroll.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/pico_scroll_font.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/pico_scroll.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../../libraries/pico_scroll/pico_scroll.cpp
|
||||
${PICO_SCROLL_SOURCES}
|
||||
)
|
||||
|
||||
target_include_directories(usermod_pico_scroll INTERFACE
|
||||
|
|
|
@ -12,7 +12,6 @@ PicoScroll *scroll = nullptr;
|
|||
|
||||
extern "C" {
|
||||
#include "pico_scroll.h"
|
||||
#include "pico_scroll_font.h"
|
||||
|
||||
#define NOT_INITIALISED_MSG "Cannot call this function, as picoscroll is not initialised. Call picoscroll.init() first."
|
||||
#define BUFFER_TOO_SMALL_MSG "bytearray too small: len(image) < width * height."
|
||||
|
@ -65,40 +64,12 @@ mp_obj_t picoscroll_scroll_text(mp_obj_t text_obj, mp_obj_t brightness_obj,
|
|||
mp_obj_t delay_ms_obj) {
|
||||
if (scroll != nullptr) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
unsigned char *buffer;
|
||||
int text_len, bfr_len;
|
||||
|
||||
mp_get_buffer_raise(text_obj, &bufinfo, MP_BUFFER_READ);
|
||||
unsigned char *values = (unsigned char *)bufinfo.buf;
|
||||
int brightness = mp_obj_get_int(brightness_obj);
|
||||
int delay_ms = mp_obj_get_int(delay_ms_obj);
|
||||
|
||||
text_len = bufinfo.len;
|
||||
bfr_len = 6 * text_len;
|
||||
scroll->scroll_text((const char *)bufinfo.buf, bufinfo.len, brightness, delay_ms);
|
||||
|
||||
int width = PicoScroll::WIDTH;
|
||||
int height = PicoScroll::HEIGHT;
|
||||
|
||||
buffer = (unsigned char *)m_malloc(sizeof(unsigned char) * bfr_len);
|
||||
render(values, text_len, buffer, bfr_len);
|
||||
|
||||
for (int offset = -width; offset < bfr_len; offset++) {
|
||||
scroll->clear();
|
||||
|
||||
for (int x = 0; x < width; x++) {
|
||||
int k = offset + x;
|
||||
if ((k >= 0) && (k < bfr_len)) {
|
||||
unsigned char col = buffer[k];
|
||||
for (int y = 0; y < height; y++) {
|
||||
int val = brightness * ((col >> y) & 1);
|
||||
scroll->set_pixel(x, y, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
scroll->update();
|
||||
sleep_ms(delay_ms);
|
||||
}
|
||||
m_free(buffer);
|
||||
} else {
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
}
|
||||
|
@ -110,60 +81,11 @@ mp_obj_t picoscroll_show_text(mp_obj_t text_obj, mp_obj_t brightness_obj,
|
|||
mp_obj_t offset_obj) {
|
||||
if (scroll != nullptr) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
unsigned char buffer[PicoScroll::WIDTH + 7];
|
||||
int text_len, bfr_len;
|
||||
|
||||
mp_get_buffer_raise(text_obj, &bufinfo, MP_BUFFER_READ);
|
||||
unsigned char *values = (unsigned char *)bufinfo.buf;
|
||||
int brightness = mp_obj_get_int(brightness_obj);
|
||||
int offset = mp_obj_get_int(offset_obj);
|
||||
|
||||
text_len = bufinfo.len;
|
||||
bfr_len = PicoScroll::WIDTH + 7;
|
||||
|
||||
int width = PicoScroll::WIDTH;
|
||||
int height = PicoScroll::HEIGHT;
|
||||
|
||||
// clear the scroll, so only need to write visible bytes
|
||||
scroll->clear();
|
||||
|
||||
if ((offset < -width) || (offset > 6 * text_len)) {
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
// compute what can actually be seen, render only that...
|
||||
// modify offset and bfr_len accordingly
|
||||
if (offset < 0) {
|
||||
int space = 1 + (width + offset) / 6;
|
||||
if (space < text_len) {
|
||||
text_len = space;
|
||||
}
|
||||
} else {
|
||||
int start = offset / 6;
|
||||
offset -= start * 6;
|
||||
text_len = text_len - start;
|
||||
if (text_len > 4) {
|
||||
text_len = 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (bfr_len > 6 * text_len) {
|
||||
bfr_len = 6 * text_len;
|
||||
}
|
||||
|
||||
render(values, text_len, buffer, bfr_len);
|
||||
|
||||
for (int x = 0; x < width; x++) {
|
||||
int k = offset + x;
|
||||
if ((k >= 0) && (k < bfr_len)) {
|
||||
unsigned char col = buffer[k];
|
||||
for (int y = 0; y < height; y++) {
|
||||
int val = brightness * ((col >> y) & 1);
|
||||
scroll->set_pixel(x, y, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scroll->set_text((const char *)bufinfo.buf, bufinfo.len, brightness, offset);
|
||||
} else {
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
}
|
||||
|
@ -180,14 +102,7 @@ mp_obj_t picoscroll_set_pixels(mp_obj_t image_obj) {
|
|||
mp_raise_msg(&mp_type_IndexError, BUFFER_TOO_SMALL_MSG);
|
||||
}
|
||||
|
||||
unsigned char *values = (unsigned char *)bufinfo.buf;
|
||||
|
||||
for (int y = 0; y < PicoScroll::HEIGHT; y++) {
|
||||
for (int x = 0; x < PicoScroll::WIDTH; x++) {
|
||||
int val = values[y * PicoScroll::WIDTH + x];
|
||||
scroll->set_pixel(x, y, val);
|
||||
}
|
||||
}
|
||||
scroll->set_pixels((const char*)bufinfo.buf);
|
||||
} else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
|
||||
|
@ -202,34 +117,15 @@ mp_obj_t picoscroll_show_bitmap_1d(mp_obj_t bitmap_obj, mp_obj_t brightness_obj,
|
|||
int offset = mp_obj_get_int(offset_obj);
|
||||
int brightness = mp_obj_get_int(brightness_obj);
|
||||
int length = bufinfo.len;
|
||||
int width = PicoScroll::WIDTH;
|
||||
int height = PicoScroll::HEIGHT;
|
||||
|
||||
// this obviously shouldn't happen as the scroll is 17x7 pixels
|
||||
// would fall off end of byte if this the case
|
||||
if (height > 8) {
|
||||
mp_raise_msg(&mp_type_RuntimeError, INCORRECT_SIZE_MSG);
|
||||
}
|
||||
|
||||
unsigned char *values = (unsigned char *)bufinfo.buf;
|
||||
|
||||
// clear the scroll, so only need to write visible bytes
|
||||
scroll->clear();
|
||||
|
||||
if ((offset < -width) || (offset > length)) {
|
||||
if ((offset < -PicoScroll::WIDTH) || (offset > length)) {
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
for (int x = 0; x < width; x++) {
|
||||
int k = offset + x;
|
||||
if ((k >= 0) && (k < length)) {
|
||||
unsigned char col = values[k];
|
||||
for (int y = 0; y < height; y++) {
|
||||
int val = brightness * ((col >> y) & 1);
|
||||
scroll->set_pixel(x, y, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
scroll->set_bitmap_1d((const char *)bufinfo.buf, bufinfo.len, brightness, offset);
|
||||
} else {
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
}
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
// external font API
|
||||
int render(unsigned char *text, int nchr, unsigned char *buffer, int nbfr);
|
Loading…
Reference in New Issue