kopia lustrzana https://github.com/pimoroni/pimoroni-pico
PicoVector: C++ basic bringup.
rodzic
0da5eda410
commit
3add0024f6
|
@ -25,6 +25,3 @@
|
||||||
[submodule "drivers/mlx90640/src"]
|
[submodule "drivers/mlx90640/src"]
|
||||||
path = drivers/mlx90640/src
|
path = drivers/mlx90640/src
|
||||||
url = https://github.com/melexis/mlx90640-library
|
url = https://github.com/melexis/mlx90640-library
|
||||||
[submodule "libraries/pico_vector/pretty_poly"]
|
|
||||||
path = libraries/pico_vector/pretty_poly
|
|
||||||
url = https://github.com/lowfatcode/pretty-poly/
|
|
||||||
|
|
|
@ -1,14 +1,3 @@
|
||||||
add_subdirectory(mandelbrot)
|
add_subdirectory(mandelbrot)
|
||||||
|
include(pico_display_2_demo.cmake)
|
||||||
set(OUTPUT_NAME pico_display2_demo)
|
include(pico_display_2_vector.cmake)
|
||||||
|
|
||||||
add_executable(
|
|
||||||
${OUTPUT_NAME}
|
|
||||||
pico_display_2_demo.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
# Pull in pico libraries that we need
|
|
||||||
target_link_libraries(${OUTPUT_NAME} pico_stdlib hardware_spi hardware_pwm hardware_dma rgbled button pico_display_2 st7789 pico_graphics)
|
|
||||||
|
|
||||||
# create map/bin/hex file etc.
|
|
||||||
pico_add_extra_outputs(${OUTPUT_NAME})
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
add_executable(
|
||||||
|
pico_display_2_demo
|
||||||
|
pico_display_2_demo.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Pull in pico libraries that we need
|
||||||
|
target_link_libraries(pico_display_2_demo pico_stdlib hardware_spi hardware_pwm hardware_dma rgbled button pico_display_2 st7789 pico_graphics)
|
||||||
|
|
||||||
|
# create map/bin/hex file etc.
|
||||||
|
pico_add_extra_outputs(pico_display_2_demo)
|
|
@ -0,0 +1,41 @@
|
||||||
|
function(static_asset NAME PATH)
|
||||||
|
get_filename_component(PATH ${PATH} ABSOLUTE)
|
||||||
|
get_filename_component(ASSET ${PATH} NAME)
|
||||||
|
get_filename_component(PATH ${PATH} DIRECTORY)
|
||||||
|
set(OBJNAME ${ASSET}.o)
|
||||||
|
add_custom_command(OUTPUT ${OBJNAME}
|
||||||
|
DEPENDS ${PATH}/${ASSET}
|
||||||
|
COMMENT "Building ${OBJNAME}"
|
||||||
|
WORKING_DIRECTORY "${PATH}"
|
||||||
|
COMMAND ${CMAKE_LINKER} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/${OBJNAME} ${ASSET}
|
||||||
|
COMMAND ${CMAKE_OBJDUMP} -t ${CMAKE_CURRENT_BINARY_DIR}/${OBJNAME}
|
||||||
|
)
|
||||||
|
# TODO figure out how to make static resources work
|
||||||
|
## COMMAND ${CMAKE_OBJCOPY} --rename-section .data=.rodata,alloc,load,readonly,data,contents ${CMAKE_CURRENT_BINARY_DIR}/${OBJNAME} ${CMAKE_CURRENT_BINARY_DIR}/${OBJNAME})
|
||||||
|
target_sources(${NAME} PRIVATE ${OBJNAME})
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
add_executable(
|
||||||
|
pico_display_2_vector
|
||||||
|
pico_display_2_vector.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Pull in pico libraries that we need
|
||||||
|
target_link_libraries(pico_display_2_vector
|
||||||
|
pico_stdlib
|
||||||
|
hardware_spi
|
||||||
|
hardware_pwm
|
||||||
|
hardware_dma
|
||||||
|
pico_display_2
|
||||||
|
st7789
|
||||||
|
pico_graphics
|
||||||
|
pico_vector
|
||||||
|
)
|
||||||
|
|
||||||
|
static_asset(pico_display_2_vector ${CMAKE_CURRENT_LIST_DIR}/vector/DynaPuff-Medium.af)
|
||||||
|
|
||||||
|
pico_enable_stdio_usb(pico_display_2_vector 0)
|
||||||
|
pico_enable_stdio_uart(pico_display_2_vector 1)
|
||||||
|
|
||||||
|
# create map/bin/hex file etc.
|
||||||
|
pico_add_extra_outputs(pico_display_2_vector)
|
|
@ -0,0 +1,66 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include "libraries/pico_display_2/pico_display_2.hpp"
|
||||||
|
#include "drivers/st7789/st7789.hpp"
|
||||||
|
#include "libraries/pico_graphics/pico_graphics.hpp"
|
||||||
|
#include "libraries/pico_vector/pico_vector.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace pimoroni;
|
||||||
|
|
||||||
|
ST7789 st7789(320, 240, ROTATE_180, false, get_spi_pins(BG_SPI_FRONT));
|
||||||
|
PicoGraphics_PenRGB332 graphics(st7789.width, st7789.height, nullptr);
|
||||||
|
|
||||||
|
uint8_t vector_mem[PicoVector::pretty_poly_buffer_size()];
|
||||||
|
|
||||||
|
PicoVector vector(&graphics);
|
||||||
|
|
||||||
|
extern char _binary_DynaPuff_Medium_af_start[];
|
||||||
|
extern size_t _binary_DynaPuff_Medium_af_size;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
stdio_init_all();
|
||||||
|
|
||||||
|
Pen BG = graphics.create_pen(120, 40, 60);
|
||||||
|
Pen TEXT = graphics.create_pen(255, 255, 255);
|
||||||
|
|
||||||
|
st7789.set_backlight(255);
|
||||||
|
|
||||||
|
vector.set_font(_binary_DynaPuff_Medium_af_start, 30);
|
||||||
|
|
||||||
|
unsigned int a = 0;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
Point text_location(0, 0);
|
||||||
|
graphics.set_pen(BG);
|
||||||
|
graphics.clear();
|
||||||
|
graphics.set_pen(TEXT);
|
||||||
|
graphics.text("Hello World", text_location, 320);
|
||||||
|
|
||||||
|
pp_point_t outline[] = {{-64, -64}, {64, -64}, {64, 64}, {-64, 64}};
|
||||||
|
pp_point_t hole[] = {{ -32, 32}, { 32, 32}, { 32, -32}, { -32, -32}};
|
||||||
|
pp_path_t paths[] = {
|
||||||
|
{.points = outline, .count = 4},
|
||||||
|
{.points = hole, .count = 4}
|
||||||
|
};
|
||||||
|
pp_poly_t poly = {.paths = paths, .count = 2};
|
||||||
|
|
||||||
|
pp_mat3_t pos = pp_mat3_identity();
|
||||||
|
pp_mat3_translate(&pos, 50, 50);
|
||||||
|
pp_mat3_rotate(&pos, a);
|
||||||
|
vector.draw(&poly);
|
||||||
|
vector.text("Hello World", &pos);
|
||||||
|
|
||||||
|
// update screen
|
||||||
|
st7789.update(&graphics);
|
||||||
|
a += 1;
|
||||||
|
if (a > 359) {
|
||||||
|
a = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Plik binarny nie jest wyświetlany.
|
@ -0,0 +1,36 @@
|
||||||
|
#include "af-file-io.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
|
static size_t ptr = 0;
|
||||||
|
|
||||||
|
void* fileio_open(const char* filename) {
|
||||||
|
ptr = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fileio_close(void* fhandle) {
|
||||||
|
ptr = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t fileio_read(void* fhandle, void *buf, size_t len) {
|
||||||
|
memcpy(buf, fhandle + ptr, len);
|
||||||
|
ptr += len;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fileio_getc(void* fhandle) {
|
||||||
|
uint8_t *f = fhandle;
|
||||||
|
int c = f[ptr];
|
||||||
|
ptr += 1;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t fileio_tell(void* fhandle) {
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t fileio_seek(void* fhandle, size_t pos) {
|
||||||
|
ptr = pos;
|
||||||
|
return ptr;
|
||||||
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
#endif
|
||||||
void* fileio_open(const char* filename);
|
void* fileio_open(const char* filename);
|
||||||
|
|
||||||
void fileio_close(void* fhandle);
|
void fileio_close(void* fhandle);
|
||||||
|
@ -13,4 +15,6 @@ int fileio_getc(void* fhandle);
|
||||||
size_t fileio_tell(void* fhandle);
|
size_t fileio_tell(void* fhandle);
|
||||||
|
|
||||||
size_t fileio_seek(void* fhandle, size_t pos);
|
size_t fileio_seek(void* fhandle, size_t pos);
|
||||||
}
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,24 @@
|
||||||
|
#include "af-memory.h"
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
void *af_malloc(size_t size) {
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *af_realloc(void *p, size_t size) {
|
||||||
|
return realloc(p, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void af_free(void *p) {
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void af_debug(const char *fmt, ...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
int ret = printf(fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
(void)ret;
|
||||||
|
}
|
|
@ -1,6 +1,12 @@
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
#endif
|
||||||
void *af_malloc(size_t size);
|
void *af_malloc(size_t size);
|
||||||
void *af_realloc(void *p, size_t size);
|
void *af_realloc(void *p, size_t size);
|
||||||
void af_free(void *p);
|
void af_free(void *p);
|
||||||
void af_debug(const char *fmt, ...);
|
void af_debug(const char *fmt, ...);
|
||||||
}
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -1,136 +0,0 @@
|
||||||
#include <cstdint>
|
|
||||||
#include <math.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
|
||||||
#include <optional>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "alright_fonts.hpp"
|
|
||||||
|
|
||||||
namespace alright_fonts {
|
|
||||||
/*
|
|
||||||
utility functions
|
|
||||||
*/
|
|
||||||
pp_rect_t measure_character(text_metrics_t &tm, uint16_t codepoint) {
|
|
||||||
if(tm.face.glyphs.count(codepoint) == 1) {
|
|
||||||
glyph_t glyph = tm.face.glyphs[codepoint];
|
|
||||||
|
|
||||||
return {0, 0, ((glyph.advance * tm.size) / 128), tm.size};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {0, 0, 0, 0};
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
render functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
void render_character(text_metrics_t &tm, uint16_t codepoint, pp_point_t origin, pp_mat3_t *transform) {
|
|
||||||
if(tm.face.glyphs.count(codepoint) == 1) {
|
|
||||||
glyph_t glyph = tm.face.glyphs[codepoint];
|
|
||||||
pp_transform(transform);
|
|
||||||
pp_render(&glyph.contours);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
load functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
// big endian stream value helpers
|
|
||||||
uint16_t ru16(file_io &ifs) {uint8_t w[2]; ifs.read((char *)w, 2); return w[0] << 8 | w[1];}
|
|
||||||
int16_t rs16(file_io &ifs) {uint8_t w[2]; ifs.read((char *)w, 2); return w[0] << 8 | w[1];}
|
|
||||||
uint32_t ru32(file_io &ifs) {uint8_t dw[4]; ifs.read((char *)dw, 4); return dw[0] << 24 | dw[1] << 16 | dw[2] << 8 | dw[3];}
|
|
||||||
uint8_t ru8(file_io &ifs) {uint8_t w; ifs.read(&w, 1); return w;}
|
|
||||||
int8_t rs8(file_io &ifs) {int8_t w; ifs.read(&w, 1); return w;}
|
|
||||||
|
|
||||||
bool face_t::load(file_io &ifs) {
|
|
||||||
char marker[4];
|
|
||||||
ifs.read(marker, sizeof(marker));
|
|
||||||
|
|
||||||
// check header magic bytes are present
|
|
||||||
if(memcmp(marker, "af!?", 4) != 0) {
|
|
||||||
// doesn't start with magic marker
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// number of glyphs embedded in font file
|
|
||||||
this->glyph_count = ru16(ifs);
|
|
||||||
|
|
||||||
// extract flags and ensure none set
|
|
||||||
this->flags = ru16(ifs);
|
|
||||||
if(this->flags != 0) {
|
|
||||||
// unknown flags set
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// extract glyph dictionary
|
|
||||||
uint16_t glyph_entry_size = 9;
|
|
||||||
uint32_t contour_data_offset = 8 + this->glyph_count * glyph_entry_size;
|
|
||||||
for(auto i = 0; i < this->glyph_count; i++) {
|
|
||||||
glyph_t g;
|
|
||||||
g.codepoint = ru16(ifs);
|
|
||||||
g.bounds.x = rs8(ifs);
|
|
||||||
g.bounds.y = rs8(ifs);
|
|
||||||
g.bounds.w = ru8(ifs);
|
|
||||||
g.bounds.h = ru8(ifs);
|
|
||||||
g.advance = ru8(ifs);
|
|
||||||
|
|
||||||
g.contours.paths = (pp_path_t *)malloc(sizeof(pp_path_t) * 10);
|
|
||||||
|
|
||||||
if(ifs.fail()) {
|
|
||||||
// could not read glyph dictionary entry
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// allocate space for the contour data and read it from the font file
|
|
||||||
uint16_t contour_data_length = ru16(ifs);
|
|
||||||
|
|
||||||
// remember where we are in the dictionary
|
|
||||||
int pos = ifs.tell();
|
|
||||||
|
|
||||||
// read contour data
|
|
||||||
ifs.seek(contour_data_offset);
|
|
||||||
while(true) {
|
|
||||||
// get number of points in contour
|
|
||||||
uint16_t count = ru16(ifs);
|
|
||||||
|
|
||||||
// if count is zero then this is the end of contour marker
|
|
||||||
if(count == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// allocate space to store point data for contour and read
|
|
||||||
// from file
|
|
||||||
g.contours.paths[g.contours.count].points = (pp_point_t *)malloc(sizeof(pp_point_t) * count);
|
|
||||||
|
|
||||||
ifs.read((char *)g.contours.paths[g.contours.count].points, sizeof(pp_point_t) * count);
|
|
||||||
|
|
||||||
g.contours.count ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return back to position in dictionary
|
|
||||||
ifs.seek(pos);
|
|
||||||
contour_data_offset += contour_data_length;
|
|
||||||
|
|
||||||
if(ifs.fail()) {
|
|
||||||
// could not read glyph contour data
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->glyphs[g.codepoint] = g;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool face_t::load(std::string_view path) {
|
|
||||||
file_io ifs(path);
|
|
||||||
if(ifs.fail()) {
|
|
||||||
// could not open file
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return load(ifs);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
#include <cstdint>
|
|
||||||
#include <math.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
|
||||||
#include <optional>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "pretty-poly.h"
|
|
||||||
#include "file_io.hpp"
|
|
||||||
|
|
||||||
namespace alright_fonts {
|
|
||||||
|
|
||||||
struct glyph_t {
|
|
||||||
uint16_t codepoint;
|
|
||||||
pp_rect_t bounds;
|
|
||||||
uint8_t advance;
|
|
||||||
pp_poly_t contours;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct face_t {
|
|
||||||
uint16_t glyph_count;
|
|
||||||
uint16_t flags;
|
|
||||||
std::map<uint16_t, glyph_t> glyphs;
|
|
||||||
|
|
||||||
face_t() {};
|
|
||||||
face_t(file_io &ifs) {load(ifs);}
|
|
||||||
face_t(std::string_view path) {load(path);}
|
|
||||||
|
|
||||||
bool load(file_io &ifs);
|
|
||||||
bool load(std::string_view path);
|
|
||||||
};
|
|
||||||
|
|
||||||
enum alignment_t {
|
|
||||||
left = 0,
|
|
||||||
center = 1,
|
|
||||||
right = 2,
|
|
||||||
justify = 4,
|
|
||||||
top = 8,
|
|
||||||
bottom = 16
|
|
||||||
};
|
|
||||||
|
|
||||||
struct text_metrics_t {
|
|
||||||
face_t face; // font to write in
|
|
||||||
int size; // text size in pixels
|
|
||||||
uint scroll; // vertical scroll offset
|
|
||||||
int line_height; // spacing between lines (%)
|
|
||||||
int letter_spacing; // spacing between characters
|
|
||||||
int word_spacing; // spacing between words
|
|
||||||
alignment_t align; // horizontal and vertical alignment
|
|
||||||
//optional<mat3_t> transform; // arbitrary transformation
|
|
||||||
pp_antialias_t antialiasing = PP_AA_X4; // level of antialiasing to apply
|
|
||||||
|
|
||||||
void set_size(int s) {
|
|
||||||
size = s;
|
|
||||||
line_height = size;
|
|
||||||
letter_spacing = 0;
|
|
||||||
word_spacing = size / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
text_metrics_t() {};
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
utility functions
|
|
||||||
*/
|
|
||||||
pp_rect_t measure_character(text_metrics_t &tm, uint16_t codepoint);
|
|
||||||
|
|
||||||
/*
|
|
||||||
render functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
void render_character(text_metrics_t &tm, uint16_t codepoint, pp_point_t origin, pp_mat3_t *transform);
|
|
||||||
}
|
|
|
@ -4,7 +4,8 @@ endif()
|
||||||
|
|
||||||
add_library(pico_vector
|
add_library(pico_vector
|
||||||
${CMAKE_CURRENT_LIST_DIR}/pico_vector.cpp
|
${CMAKE_CURRENT_LIST_DIR}/pico_vector.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/alright_fonts.cpp
|
${CMAKE_CURRENT_LIST_DIR}/af-file-io.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/af-memory.c
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(pico_vector INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
target_include_directories(pico_vector INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||||
|
|
|
@ -112,7 +112,20 @@ namespace pimoroni {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pp_point_t text(std::string_view text, pp_mat3_t *t);
|
bool set_font(void* font, unsigned int font_size) {
|
||||||
|
if(text_metrics.face) {
|
||||||
|
af_free(text_metrics.face->glyphs);
|
||||||
|
af_free(text_metrics.face);
|
||||||
|
}
|
||||||
|
text_metrics.face = (af_face_t *)af_malloc(sizeof(af_face_t));
|
||||||
|
bool result = af_load_font_file(font, text_metrics.face);
|
||||||
|
|
||||||
|
set_font_size(font_size);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
pp_point_t text(std::string_view text, pp_mat3_t *t=nullptr);
|
||||||
|
|
||||||
void transform(pp_path_t *path, pp_mat3_t *t);
|
void transform(pp_path_t *path, pp_mat3_t *t);
|
||||||
void transform(pp_poly_t *poly, pp_mat3_t *t);
|
void transform(pp_poly_t *poly, pp_mat3_t *t);
|
||||||
|
|
Ładowanie…
Reference in New Issue