remove everything we don't need

This commit is contained in:
Jeff Epler 2025-02-17 10:40:49 -06:00
parent d67479563f
commit 34546a5ad0
34 changed files with 0 additions and 2870 deletions

View file

@ -1,117 +0,0 @@
name: CMake
on:
push:
pull_request:
release:
types: [created]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
jobs:
build:
name: ${{matrix.name}}
strategy:
matrix:
include:
- os: ubuntu-22.04
name: Linux
cache-key: linux
cmake-args: '-DPIMORONI_PICO_PATH=$GITHUB_WORKSPACE/pimoroni-pico -DPICO_SDK_PATH=$GITHUB_WORKSPACE/pico-sdk -DCMAKE_INSTALL_PREFIX=$GITHUB_WORKSPACE/install'
apt-packages: clang-tidy gcc-arm-none-eabi libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlib
runs-on: ${{matrix.os}}
env:
PICO_SDK_PATH: $GITHUB_WORKSPACE/pico-sdk
PIMORONI_PICO_LIBS: $GITHUB_WORKSPACE/pimoroni-pico
RELEASE_FILE: ${{github.event.repository.name}}-${{github.event.release.tag_name}}
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
path: project
# Checkout the Pimoroni Pico Libraries
- name: Checkout Pimoroni Pico Libraries
uses: actions/checkout@v3
with:
repository: pimoroni/pimoroni-pico
path: pimoroni-pico
# Checkout the Pico SDK
- name: Checkout Pico SDK
uses: actions/checkout@v3
with:
repository: raspberrypi/pico-sdk
path: pico-sdk
submodules: true
# Linux deps
- name: Install deps
if: runner.os == 'Linux'
run: |
sudo apt update && sudo apt install ${{matrix.apt-packages}}
mkdir toolchain
cd toolchain
wget https://buildbot.embecosm.com/job/riscv32-gcc-ubuntu2204-release/10/artifact/riscv32-embecosm-ubuntu2204-gcc13.2.0.tar.gz
tar xzf riscv32-embecosm-ubuntu2204-gcc13.2.0.tar.gz
- name: Create Build Environment
run: |
cmake -E make_directory ${{runner.workspace}}/build
cmake -E make_directory ${{runner.workspace}}/build-riscv
- name: Configure CMake
shell: bash
working-directory: ${{runner.workspace}}/build
run: cmake $GITHUB_WORKSPACE/project -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCPACK_PACKAGE_FILE_NAME=${{env.RELEASE_FILE}} ${{matrix.cmake-args}}
- name: Build
working-directory: ${{runner.workspace}}/build
shell: bash
run: |
cmake --build . --config $BUILD_TYPE -j 2
- name: Configure CMake RiscV
shell: bash
working-directory: ${{runner.workspace}}/build-riscv
run: cmake $GITHUB_WORKSPACE/project -DPICO_PLATFORM=rp2350-riscv -DPICO_TOOLCHAIN_PATH=$GITHUB_WORKSPACE/toolchain/riscv32-embecosm-ubuntu2204-gcc13.2.0 -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCPACK_PACKAGE_FILE_NAME=${{env.RELEASE_FILE}} ${{matrix.cmake-args}}
- name: Build RiscV
working-directory: ${{runner.workspace}}/build-riscv
shell: bash
run: |
cmake --build . --config $BUILD_TYPE -j 2
- name: Build Release Packages
if: github.event_name == 'release'
working-directory: ${{runner.workspace}}/build
shell: bash
run: |
cmake --build . --config $BUILD_TYPE --target package -j 2
- name: Upload .zip
if: github.event_name == 'release'
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
with:
asset_path: ${{runner.workspace}}/build/${{env.RELEASE_FILE}}.zip
upload_url: ${{github.event.release.upload_url}}
asset_name: ${{env.RELEASE_FILE}}.zip
asset_content_type: application/zip
- name: Upload .tar.gz
if: github.event_name == 'release'
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
with:
asset_path: ${{runner.workspace}}/build/${{env.RELEASE_FILE}}.tar.gz
upload_url: ${{github.event.release.upload_url}}
asset_name: ${{env.RELEASE_FILE}}.tar.gz
asset_content_type: application/octet-stream

View file

@ -1,129 +0,0 @@
name: MicroPython
on:
push:
pull_request:
release:
types: [created]
env:
MICROPYTHON_VERSION: feature/psram
MICROPYTHON_FLAVOUR: MichaelBell
PIMORONI_PICO_VERSION: feature/sdk-2.0.0
jobs:
build:
name: ${{ matrix.name }} (${{ matrix.board }} ${{ matrix.variant }})
runs-on: ubuntu-20.04
continue-on-error: true
strategy:
matrix:
include:
- name: pico_plus2_rp2350_psram
board: PIMORONI_PICO_PLUS2
variant: PSRAM
env:
# MicroPython version will be contained in github.event.release.tag_name for releases
RELEASE_FILE: ${{ matrix.name }}-${{ github.event.release.tag_name || github.sha }}-micropython
PIMORONI_PICO_DIR: "${{ github.workspace }}/pimoroni-pico"
USER_C_MODULES: "${{ github.workspace }}/src-${{ github.sha }}/modules/dvhstx.cmake"
TAG_OR_SHA: ${{ github.event.release.tag_name || github.sha }}
MICROPY_BOARD: ${{ matrix.board }}
MICROPY_BOARD_VARIANT: ${{ matrix.variant }}
MICROPY_BOARD_DIR: "${{ github.workspace }}/src-${{ github.sha }}/micropython/board/${{ matrix.BOARD }}"
BOARD_NAME: ${{ matrix.name }}
BUILD_TOOLS: src-${{ github.sha }}/ci/micropython.sh
steps:
- name: "CCache: Restore saved cache"
uses: actions/cache@v4
with:
path: /home/runner/.ccache
key: ccache-micropython-${{ matrix.name }}-${{ github.ref }}-${{ github.sha }}
restore-keys: |
ccache-micropython-${{ matrix.name }}-${{ github.ref }}
ccache-micropython-${{ matrix.name }}-
- name: "Src: Checkout"
uses: actions/checkout@v4
with:
submodules: true
path: src-${{ github.sha }}
- name: "Pimoroni Pico: Checkout"
uses: actions/checkout@v4
with:
repository: pimoroni/pimoroni-pico
ref: ${{env.PIMORONI_PICO_VERSION}}
submodules: true
path: pimoroni-pico
- name: Install Arm GNU Toolchain (arm-none-eabi-gcc)
uses: carlosperate/arm-none-eabi-gcc-action@v1
with:
release: '13.3.Rel1'
- name: "CCache: Install"
run: |
source $BUILD_TOOLS
apt_install_build_deps
- name: "MicroPython: Checkout"
run: |
source $BUILD_TOOLS
micropython_clone
- name: "Py_Decl: Checkout"
uses: actions/checkout@v4
with:
repository: gadgetoid/py_decl
ref: v0.0.2
path: py_decl
- name: "dir2uf2: Checkout"
uses: actions/checkout@v4
with:
repository: gadgetoid/dir2uf2
ref: v0.0.7
path: dir2uf2
- name: "MicroPython: Build MPY Cross"
run: |
source $BUILD_TOOLS
micropython_build_mpy_cross
- name: "MicroPython: Configure"
shell: bash
run: |
source $BUILD_TOOLS
micropython_version
cmake_configure
- name: "MicroPython: Build"
shell: bash
run: |
source $BUILD_TOOLS
cmake_build
- name: "Py_Decl: Verify .uf2"
shell: bash
run: |
python3 py_decl/py_decl.py --to-json --verify build-${{ matrix.name }}/${{ env.RELEASE_FILE }}.uf2
- name: "Artifacts: Upload .uf2"
uses: actions/upload-artifact@v4
with:
name: ${{ env.RELEASE_FILE }}.uf2
path: build-${{ matrix.name }}/${{ env.RELEASE_FILE }}.uf2
- name: "Release: Upload .uf2"
if: github.event_name == 'release'
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
asset_path: build-${{ matrix.name }}/${{ env.RELEASE_FILE }}.uf2
upload_url: ${{ github.event.release.upload_url }}
asset_name: ${{ env.RELEASE_FILE }}.uf2
asset_content_type: application/octet-stream

View file

@ -1,23 +0,0 @@
cmake_minimum_required(VERSION 3.12)
if (NOT PICO_PLATFORM)
set(PICO_PLATFORM rp2350)
endif()
include(pico_sdk_import.cmake)
include(pimoroni_pico_import.cmake)
# Gooey boilerplate
project(pico_dvhstx_examples C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
# Initialize the SDK
pico_sdk_init()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror")
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
include(pico_dvhstx.cmake)
add_subdirectory(examples/dvhstx)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 708 KiB

View file

@ -1,65 +0,0 @@
export TERM=${TERM:="xterm-256color"}
function log_success {
echo -e "$(tput setaf 2)$1$(tput sgr0)"
}
function log_inform {
echo -e "$(tput setaf 6)$1$(tput sgr0)"
}
function log_warning {
echo -e "$(tput setaf 1)$1$(tput sgr0)"
}
function micropython_clone {
log_inform "Using MicroPython $MICROPYTHON_VERSION"
git clone https://github.com/$MICROPYTHON_FLAVOUR/micropython
cd micropython
git checkout $MICROPYTHON_VERSION
git submodule update --init lib/pico-sdk
git submodule update --init lib/cyw43-driver
git submodule update --init lib/lwip
git submodule update --init lib/mbedtls
git submodule update --init lib/micropython-lib
git submodule update --init lib/tinyusb
git submodule update --init lib/btstack
cd ../
}
function micropython_build_mpy_cross {
cd micropython/mpy-cross
ccache --zero-stats || true
CROSS_COMPILE="ccache " make
ccache --show-stats || true
cd ../../
}
function apt_install_build_deps {
sudo apt update && sudo apt install ccache
}
function micropython_version {
echo "MICROPY_GIT_TAG=$MICROPYTHON_VERSION, $BOARD_NAME $TAG_OR_SHA" >> $GITHUB_ENV
echo "MICROPY_GIT_HASH=$MICROPYTHON_VERSION-$TAG_OR_SHA" >> $GITHUB_ENV
}
function cmake_configure {
cmake -S micropython/ports/rp2 -B build-$BOARD_NAME \
-DPICO_BUILD_DOCS=0 \
-DPICO_NO_COPRO_DIS=1 \
-DUSER_C_MODULES=$USER_C_MODULES \
-DMICROPY_BOARD_DIR=$MICROPY_BOARD_DIR \
-DMICROPY_BOARD=$MICROPY_BOARD \
-DMICROPY_BOARD_VARIANT=$MICROPY_BOARD_VARIANT \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
}
function cmake_build {
ccache --zero-stats || true
cmake --build build-$BOARD_NAME -j 2
ccache --show-stats || true
cd build-$BOARD_NAME
cp firmware.uf2 $RELEASE_FILE.uf2
}

View file

@ -1 +0,0 @@
include(dvhstx.cmake)

View file

@ -1,20 +0,0 @@
set(DRIVER_NAME dvhstx)
# main DV display driver
add_library(${DRIVER_NAME} INTERFACE)
target_sources(${DRIVER_NAME} INTERFACE
${CMAKE_CURRENT_LIST_DIR}/dvi.cpp
${CMAKE_CURRENT_LIST_DIR}/${DRIVER_NAME}.cpp
${CMAKE_CURRENT_LIST_DIR}/intel_one_mono_2bpp.c
)
# Enforce consistent compile options.
# For the moment, don't use -O3 options that increase code size significantly
target_compile_options(${DRIVER_NAME} INTERFACE -Wall -Werror -O2 -fgcse-after-reload -floop-interchange -fpeel-loops -fpredictive-commoning -fsplit-paths -ftree-loop-distribute-patterns -ftree-loop-distribution -ftree-vectorize -ftree-partial-pre -funswitch-loops)
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)

View file

@ -1,24 +0,0 @@
add_executable(
mandelbrot
mandelbrot.cpp
mandelf.c
)
# Pull in pico libraries that we need
target_link_libraries(mandelbrot pico_stdlib pico_multicore pico_dvhstx)
pico_enable_stdio_usb(mandelbrot 1)
# create map/bin/hex file etc.
pico_add_extra_outputs(mandelbrot)
add_executable(
textmode
textmode.cpp
)
# Pull in pico libraries that we need
target_link_libraries(textmode pico_stdlib pico_dvhstx)
pico_enable_stdio_usb(textmode 1)
# create map/bin/hex file etc.
pico_add_extra_outputs(textmode)

View file

@ -1,130 +0,0 @@
#include <stdio.h>
#include "hardware/uart.h"
#include "pico/multicore.h"
#include "drivers/dvhstx/dvhstx.hpp"
#include "libraries/pico_graphics/pico_graphics_dvhstx.hpp"
extern "C" {
#include "mandelf.h"
}
using namespace pimoroni;
#ifdef __riscv
#define FRAME_WIDTH 400
#define FRAME_HEIGHT 300
#else
#define FRAME_WIDTH 640
#define FRAME_HEIGHT 360
#endif
//#define FRAME_WIDTH 320
//#define FRAME_HEIGHT 180
static DVHSTX display;
static PicoGraphics_PenDVHSTX_P8 graphics(FRAME_WIDTH, FRAME_HEIGHT, display);
static FractalBuffer fractal;
static void init_palette() {
graphics.create_pen(0, 0, 0);
for (int i = 0; i < 64; ++i) {
graphics.create_pen_hsv(i * (1.f / 63.f), 1.0f, 0.5f + (i & 7) * (0.5f / 7.f));
}
}
static void init_mandel() {
fractal.rows = FRAME_HEIGHT / 2;
fractal.cols = FRAME_WIDTH;
fractal.max_iter = 63;
fractal.iter_offset = 0;
fractal.minx = -2.25f;
fractal.maxx = 0.75f;
fractal.miny = -1.6f;
fractal.maxy = 0.f - (1.6f / FRAME_HEIGHT); // Half a row
fractal.use_cycle_check = true;
init_fractal(&fractal);
}
#define NUM_ZOOMS 100
static uint32_t zoom_count = 0;
static void zoom_mandel() {
if (++zoom_count == NUM_ZOOMS)
{
init_mandel();
zoom_count = 0;
sleep_ms(2000);
return;
}
float zoomx = -.75f - .7f * ((float)zoom_count / (float)NUM_ZOOMS);
float sizex = fractal.maxx - fractal.minx;
float sizey = fractal.miny * -2.f;
float zoomr = 0.974f * 0.5f;
fractal.minx = zoomx - zoomr * sizex;
fractal.maxx = zoomx + zoomr * sizex;
fractal.miny = -zoomr * sizey;
fractal.maxy = 0.f + fractal.miny / FRAME_HEIGHT;
init_fractal(&fractal);
}
static void display_row(int y, uint8_t* buf) {
display.write_palette_pixel_span({0, y}, FRAME_WIDTH, buf);
display.write_palette_pixel_span({0, FRAME_HEIGHT - 1 - y}, FRAME_WIDTH, buf);
}
static uint8_t row_buf_core1[FRAME_WIDTH];
void core1_main() {
while (true) {
int y = multicore_fifo_pop_blocking();
generate_one_line(&fractal, row_buf_core1, y);
multicore_fifo_push_blocking(y);
}
}
static uint8_t row_buf[FRAME_WIDTH];
static void draw_two_rows(int y) {
multicore_fifo_push_blocking(y+1);
generate_one_line(&fractal, row_buf, y);
display_row(y, row_buf);
multicore_fifo_pop_blocking();
display_row(y+1, row_buf_core1);
}
void draw_mandel() {
//display.wait_for_flip();
for (int y = 0; y < FRAME_HEIGHT / 2; y += 2)
{
draw_two_rows(y);
}
//display.flip_async();
display.flip_now();
}
int main() {
display.init(FRAME_WIDTH, FRAME_HEIGHT, DVHSTX::MODE_PALETTE);
stdio_init_all();
init_palette();
graphics.set_pen(0);
graphics.clear();
display.flip_now();
graphics.clear();
multicore_launch_core1(core1_main);
init_mandel();
draw_mandel();
while(true) {
absolute_time_t start_time = get_absolute_time();
zoom_mandel();
draw_mandel();
printf("Drawing zoom %ld took %.2fms\n", zoom_count, absolute_time_diff_us(start_time, get_absolute_time()) * 0.001f);
}
}

View file

@ -1,63 +0,0 @@
// Copyright (C) Michael Bell 2021
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "pico/stdlib.h"
#include "mandelf.h"
// Cycle checking parameters
#define MAX_CYCLE_LEN 8 // Must be power of 2
#define MIN_CYCLE_CHECK_ITER 24 // Must be multiple of max cycle len
#define CYCLE_TOLERANCE 4e-3
#define ESCAPE_SQUARE 4.f
void init_fractal(FractalBuffer* f)
{
f->done = false;
f->min_iter = f->max_iter - 1;
f->incx = (f->maxx - f->minx) / (f->cols - 1);
f->incy = (f->maxy - f->miny) / (f->rows - 1);
f->count_inside = 0;
}
static inline void generate_one(FractalBuffer* f, float x0, float y0, uint8_t* buffptr)
{
float x = x0;
float y = y0;
uint16_t k = 1;
for (; k < f->max_iter; ++k) {
float x_square = x*x;
float y_square = y*y;
if (x_square + y_square > ESCAPE_SQUARE) break;
float nextx = x_square - y_square + x0;
y = x*y*2.f + y0;
x = nextx;
}
if (k == f->max_iter) {
*buffptr = 0;
f->count_inside++;
} else {
if (k > f->iter_offset) k -= f->iter_offset;
else k = 1;
*buffptr = k;
if (f->min_iter > k) f->min_iter = k;
}
}
void generate_one_line(FractalBuffer* f, uint8_t* buf, uint16_t ipos)
{
if (f->done) return;
float y0 = f->miny + ipos * f->incy;
float x0 = f->minx;
for (int16_t j = 0; j < f->cols; ++j) {
generate_one(f, x0, y0, buf++);
x0 += f->incx;
}
}

View file

@ -1,24 +0,0 @@
#pragma once
typedef struct {
// Configuration
int16_t rows;
int16_t cols;
uint16_t max_iter;
uint16_t iter_offset;
float minx, miny, maxx, maxy;
bool use_cycle_check;
// State
volatile bool done;
volatile uint16_t min_iter;
float incx, incy;
volatile uint32_t count_inside;
} FractalBuffer;
// Generate a section of the fractal into buff
// Result written to buff is 0 for inside Mandelbrot set
// Otherwise iteration of escape minus min_iter (clamped to 1)
void init_fractal(FractalBuffer* fractal);
void generate_one_line(FractalBuffer* f, uint8_t* buf, uint16_t row);

View file

@ -1,49 +0,0 @@
#include <stdio.h>
#include "hardware/uart.h"
#include "drivers/dvhstx/dvhstx.hpp"
using namespace pimoroni;
#define FRAME_WIDTH 91
#define FRAME_HEIGHT 30
static DVHSTX display;
using namespace pimoroni;
void fill_text(int frame)
{
char buf[128];
sprintf(buf, "Hello World! Frame: %d", frame);
display.write_text({0,0}, buf);
for (int i = 0; i < 0x7f; ++i) {
buf[i] = i;
}
buf[0x7f] = 0;
for (int i = 1; i < FRAME_HEIGHT; ++i) {
display.write_text({0, i}, &buf[0x20 + i], (i & 1) ? (i & 2) ? DVHSTX::TEXT_WHITE : DVHSTX::TEXT_BLUE : (i & 2) ? DVHSTX::TEXT_YELLOW : DVHSTX::TEXT_RED);
}
}
int main()
{
stdio_init_all();
printf("Main\n");
bool rv = display.init(FRAME_WIDTH, FRAME_HEIGHT, DVHSTX::MODE_TEXT_RGB111);
printf("Init complete: %s", rv ? "True" : "False");
fill_text(0);
display.flip_now();
int frame = 1;
while(1) {
fill_text(frame++);
display.flip_blocking();
printf(".\n");
}
}

View file

@ -1,88 +0,0 @@
#include "pico_graphics.hpp"
#include "drivers/dvhstx/dvhstx.hpp"
namespace pimoroni {
enum BlendMode {
TARGET = 0,
FIXED = 1,
};
class PicoGraphicsDVHSTX : public PicoGraphics {
public:
DVHSTX &driver;
BlendMode blend_mode = BlendMode::TARGET;
void set_blend_mode(BlendMode mode) {
blend_mode = mode;
}
virtual void set_depth(uint8_t new_depth) {}
virtual void set_bg(uint c) {};
PicoGraphicsDVHSTX(uint16_t width, uint16_t height, DVHSTX &dv_display)
: PicoGraphics(width, height, nullptr),
driver(dv_display)
{
this->pen_type = PEN_DV_RGB555;
}
};
class PicoGraphics_PenDVHSTX_RGB565 : public PicoGraphicsDVHSTX {
public:
RGB565 color;
RGB565 background;
uint16_t depth = 0;
PicoGraphics_PenDVHSTX_RGB565(uint16_t width, uint16_t height, DVHSTX &dv_display);
void set_pen(uint c) override;
void set_bg(uint c) override;
void set_depth(uint8_t new_depth) override;
void set_pen(uint8_t r, uint8_t g, uint8_t b) override;
int create_pen(uint8_t r, uint8_t g, uint8_t b) override;
int create_pen_hsv(float h, float s, float v) override;
void set_pixel(const Point &p) override;
void set_pixel_span(const Point &p, uint l) override;
void set_pixel_alpha(const Point &p, const uint8_t a) override;
bool supports_alpha_blend() override {return true;}
bool render_pico_vector_tile(const Rect &bounds, uint8_t* alpha_data, uint32_t stride, uint8_t alpha_type) override;
static size_t buffer_size(uint w, uint h) {
return w * h * sizeof(RGB565);
}
};
class PicoGraphics_PenDVHSTX_P8 : public PicoGraphicsDVHSTX {
public:
static const uint16_t palette_size = 256;
uint8_t color;
uint8_t depth = 0;
bool used[palette_size];
std::array<std::array<uint8_t, 16>, 512> candidate_cache;
std::array<uint8_t, 16> candidates;
bool cache_built = false;
PicoGraphics_PenDVHSTX_P8(uint16_t width, uint16_t height, DVHSTX &dv_display);
void set_pen(uint c) override;
void set_pen(uint8_t r, uint8_t g, uint8_t b) override;
void set_depth(uint8_t new_depth) override;
int update_pen(uint8_t i, uint8_t r, uint8_t g, uint8_t b) override;
int create_pen(uint8_t r, uint8_t g, uint8_t b) override;
int create_pen_hsv(float h, float s, float v) override;
int reset_pen(uint8_t i) override;
int get_palette_size() override {return 0;};
RGB* get_palette() override {return nullptr;};
void set_pixel(const Point &p) override;
void set_pixel_span(const Point &p, uint l) override;
void get_dither_candidates(const RGB &col, const RGB *palette, size_t len, std::array<uint8_t, 16> &candidates);
void set_pixel_dither(const Point &p, const RGB &c) override;
static size_t buffer_size(uint w, uint h) {
return w * h;
}
};
}

View file

@ -1,112 +0,0 @@
#include "pico_graphics_dvhstx.hpp"
namespace pimoroni {
inline constexpr uint32_t RGB_to_RGB888(const uint8_t r, const uint8_t g, const uint8_t b) {
return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
}
PicoGraphics_PenDVHSTX_P8::PicoGraphics_PenDVHSTX_P8(uint16_t width, uint16_t height, DVHSTX &dv_display)
: PicoGraphicsDVHSTX(width, height, dv_display)
{
this->pen_type = PEN_DV_P5;
for(auto i = 0u; i < palette_size; i++) {
driver.set_palette_colour(i, RGB_to_RGB888(i, i, i) << 3);
used[i] = false;
}
cache_built = false;
}
void PicoGraphics_PenDVHSTX_P8::set_pen(uint c) {
color = c;
}
void PicoGraphics_PenDVHSTX_P8::set_depth(uint8_t new_depth) {
depth = new_depth > 0 ? 1 : 0;
}
void PicoGraphics_PenDVHSTX_P8::set_pen(uint8_t r, uint8_t g, uint8_t b) {
RGB888 *driver_palette = driver.get_palette();
RGB palette[palette_size];
for(auto i = 0u; i < palette_size; i++) {
palette[i] = RGB((uint)driver_palette[i]);
}
int pen = RGB(r, g, b).closest(palette, palette_size);
if(pen != -1) color = pen;
}
int PicoGraphics_PenDVHSTX_P8::update_pen(uint8_t i, uint8_t r, uint8_t g, uint8_t b) {
used[i] = true;
cache_built = false;
driver.set_palette_colour(i, RGB_to_RGB888(r, g, b));
return i;
}
int PicoGraphics_PenDVHSTX_P8::create_pen(uint8_t r, uint8_t g, uint8_t b) {
// Create a colour and place it in the palette if there's space
for(auto i = 0u; i < palette_size; i++) {
if(!used[i]) {
used[i] = true;
cache_built = false;
driver.set_palette_colour(i, RGB_to_RGB888(r, g, b));
return i;
}
}
return -1;
}
int PicoGraphics_PenDVHSTX_P8::create_pen_hsv(float h, float s, float v) {
RGB p = RGB::from_hsv(h, s, v);
return create_pen(p.r, p.g, p.b);
}
int PicoGraphics_PenDVHSTX_P8::reset_pen(uint8_t i) {
driver.set_palette_colour(i, 0);
used[i] = false;
cache_built = false;
return i;
}
void PicoGraphics_PenDVHSTX_P8::set_pixel(const Point &p) {
driver.write_palette_pixel(p, color);
}
void PicoGraphics_PenDVHSTX_P8::set_pixel_span(const Point &p, uint l) {
driver.write_palette_pixel_span(p, l, color);
}
void PicoGraphics_PenDVHSTX_P8::get_dither_candidates(const RGB &col, const RGB *palette, size_t len, std::array<uint8_t, 16> &candidates) {
RGB error;
for(size_t i = 0; i < candidates.size(); i++) {
candidates[i] = (col + error).closest(palette, len);
error += (col - palette[candidates[i]]);
}
// sort by a rough approximation of luminance, this ensures that neighbouring
// pixels in the dither matrix are at extreme opposites of luminence
// giving a more balanced output
std::sort(candidates.begin(), candidates.end(), [palette](int a, int b) {
return palette[a].luminance() > palette[b].luminance();
});
}
void PicoGraphics_PenDVHSTX_P8::set_pixel_dither(const Point &p, const RGB &c) {
if(!bounds.contains(p)) return;
if(!cache_built) {
RGB888 *driver_palette = driver.get_palette();
RGB palette[palette_size];
for(auto i = 0u; i < palette_size; i++) {
palette[i] = RGB((uint)driver_palette[i]);
}
for(uint i = 0; i < 512; i++) {
RGB cache_col((i & 0x1C0) >> 1, (i & 0x38) << 2, (i & 0x7) << 5);
get_dither_candidates(cache_col, palette, palette_size, candidate_cache[i]);
}
cache_built = true;
}
uint cache_key = ((c.r & 0xE0) << 1) | ((c.g & 0xE0) >> 2) | ((c.b & 0xE0) >> 5);
// find the pattern coordinate offset
uint pattern_index = (p.x & 0b11) | ((p.y & 0b11) << 2);
// set the pixel
color = candidate_cache[cache_key][dither16_pattern[pattern_index]];
set_pixel(p);
}
}

View file

@ -1,72 +0,0 @@
#include "pico_graphics_dvhstx.hpp"
#ifndef MICROPY_BUILD_TYPE
#define mp_printf(_, ...) printf(__VA_ARGS__);
#else
extern "C" {
#include "py/runtime.h"
}
#endif
namespace pimoroni {
RGB565 to_rgb565_noswap(const RGB& color) {
uint16_t p = ((color.r & 0b11111000) << 8) |
((color.g & 0b11111100) << 3) |
((color.b & 0b11111000) >> 3);
return p;
}
PicoGraphics_PenDVHSTX_RGB565::PicoGraphics_PenDVHSTX_RGB565(uint16_t width, uint16_t height, DVHSTX &dv_display)
: PicoGraphicsDVHSTX(width, height, dv_display)
{
this->pen_type = PEN_DV_RGB555;
}
void PicoGraphics_PenDVHSTX_RGB565::set_pen(uint c) {
color = c;
}
void PicoGraphics_PenDVHSTX_RGB565::set_bg(uint c) {
background = c;
}
void PicoGraphics_PenDVHSTX_RGB565::set_depth(uint8_t new_depth) {
depth = new_depth > 0 ? 0x8000 : 0;
}
void PicoGraphics_PenDVHSTX_RGB565::set_pen(uint8_t r, uint8_t g, uint8_t b) {
RGB src_color{r, g, b};
color = to_rgb565_noswap(src_color);
}
int PicoGraphics_PenDVHSTX_RGB565::create_pen(uint8_t r, uint8_t g, uint8_t b) {
return to_rgb565_noswap(RGB(r, g, b));
}
int PicoGraphics_PenDVHSTX_RGB565::create_pen_hsv(float h, float s, float v) {
return to_rgb565_noswap(RGB::from_hsv(h, s, v));
}
void PicoGraphics_PenDVHSTX_RGB565::set_pixel(const Point &p) {
driver.write_pixel(p, color);
}
void PicoGraphics_PenDVHSTX_RGB565::set_pixel_span(const Point &p, uint l) {
driver.write_pixel_span(p, l, color);
}
void PicoGraphics_PenDVHSTX_RGB565::set_pixel_alpha(const Point &p, const uint8_t a) {
uint16_t src = background;
if (blend_mode == BlendMode::TARGET) {
driver.read_pixel_span(p, 1, &src);
}
uint8_t src_r = (src >> 8) & 0b11111000;
uint8_t src_g = (src >> 3) & 0b11111100;
uint8_t src_b = (src << 3) & 0b11111000;
uint8_t dst_r = (color >> 8) & 0b11111000;
uint8_t dst_g = (color >> 3) & 0b11111100;
uint8_t dst_b = (color << 3) & 0b11111000;
RGB565 blended = to_rgb565_noswap(RGB(src_r, src_g, src_b).blend(RGB(dst_r, dst_g, dst_b), a));
driver.write_pixel(p, blended);
}
bool PicoGraphics_PenDVHSTX_RGB565::render_pico_vector_tile(const Rect &src_bounds, uint8_t* alpha_data, uint32_t stride, uint8_t alpha_type) {
return false;
}
}

View file

@ -1,19 +0,0 @@
{
"deploy": [
"../deploy.md"
],
"docs": "",
"features": [
"Dual-core",
"External Flash",
"USB"
],
"images": [
"rp2-picos.jpg"
],
"mcu": "rp2350",
"product": "Pico2",
"thumbnail": "",
"url": "https://shop.pimoroni.com/products/raspberry-pi-pico-plus2/",
"vendor": "Raspberry Pi"
}

View file

@ -1,3 +0,0 @@
include("$(PORT_DIR)/boards/manifest.py")
include("../manifest_pico2.py")

View file

@ -1,9 +0,0 @@
# cmake file for Raspberry Pi Pico
set(PICO_BOARD "pimoroni_pico_plus2_rp2350")
set(PICO_PLATFORM "rp2350")
set(PICO_NUM_GPIOS 48)
# Board specific version of the frozen manifest
set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
set(MICROPY_C_HEAP_SIZE 32768)

View file

@ -1,11 +0,0 @@
// Board and hardware specific configuration
#ifndef MICROPY_HW_BOARD_NAME
// Might be defined by mpconfigvariant.cmake
#define MICROPY_HW_BOARD_NAME "Pimoroni Pico Plus 2"
#endif
#define MICROPY_HW_FLASH_STORAGE_BYTES (PICO_FLASH_SIZE_BYTES - (2 * 1024 * 1024))
#define MICROPY_HW_PSRAM_CS_PIN PIMORONI_PICO_PLUS2_PSRAM_CS_PIN
extern void display_setup_clock_preinit();
#define MICROPY_BOARD_STARTUP() display_setup_clock_preinit()

View file

@ -1,6 +0,0 @@
# Override the MicroPython board name
list(APPEND MICROPY_DEF_BOARD
"MICROPY_HW_ENABLE_PSRAM=1"
"MICROPY_GC_SPLIT_HEAP=0"
"MICROPY_HW_BOARD_NAME=\"Pimoroni Pico Plus 2 (PSRAM)\""
)

View file

@ -1,47 +0,0 @@
GP0,GPIO0
GP1,GPIO1
GP2,GPIO2
GP3,GPIO3
GP4,GPIO4
GP5,GPIO5
GP6,GPIO6
GP7,GPIO7
GP8,GPIO8
GP9,GPIO9
GP10,GPIO10
GP11,GPIO11
GP12,GPIO12
GP13,GPIO13
GP14,GPIO14
GP15,GPIO15
GP16,GPIO16
GP17,GPIO17
GP18,GPIO18
GP19,GPIO19
GP20,GPIO20
GP21,GPIO21
GP22,GPIO22
GP25,GPIO25
GP26,GPIO26
GP27,GPIO27
GP28,GPIO28
GP29,GPIO29
GP30,GPIO30
GP31,GPIO31
GP32,GPIO32
GP33,GPIO33
GP34,GPIO34
GP35,GPIO35
GP36,GPIO36
GP37,GPIO37
GP38,GPIO38
GP39,GPIO39
GP40,GPIO40
GP41,GPIO41
GP42,GPIO42
GP43,GPIO43
GP44,GPIO44
GP45,GPIO45
GP46,GPIO46
GP47,GPIO47
LED,GPIO25
1 GP0 GPIO0
2 GP1 GPIO1
3 GP2 GPIO2
4 GP3 GPIO3
5 GP4 GPIO4
6 GP5 GPIO5
7 GP6 GPIO6
8 GP7 GPIO7
9 GP8 GPIO8
10 GP9 GPIO9
11 GP10 GPIO10
12 GP11 GPIO11
13 GP12 GPIO12
14 GP13 GPIO13
15 GP14 GPIO14
16 GP15 GPIO15
17 GP16 GPIO16
18 GP17 GPIO17
19 GP18 GPIO18
20 GP19 GPIO19
21 GP20 GPIO20
22 GP21 GPIO21
23 GP22 GPIO22
24 GP25 GPIO25
25 GP26 GPIO26
26 GP27 GPIO27
27 GP28 GPIO28
28 GP29 GPIO29
29 GP30 GPIO30
30 GP31 GPIO31
31 GP32 GPIO32
32 GP33 GPIO33
33 GP34 GPIO34
34 GP35 GPIO35
35 GP36 GPIO36
36 GP37 GPIO37
37 GP38 GPIO38
38 GP39 GPIO39
39 GP40 GPIO40
40 GP41 GPIO41
41 GP42 GPIO42
42 GP43 GPIO43
43 GP44 GPIO44
44 GP45 GPIO45
45 GP46 GPIO46
46 GP47 GPIO47
47 LED GPIO25

View file

@ -1,6 +0,0 @@
MODULES_PY = "../../../pimoroni-pico/micropython/modules_py"
freeze(MODULES_PY, "gfx_pack.py")
freeze(MODULES_PY, "pimoroni.py")
freeze(MODULES_PY, "boot.py")

View file

@ -1,120 +0,0 @@
import time
import gc
from dvhstx import DVHSTX, PEN_P8, PEN_RGB565
from picovector import PicoVector, Polygon, RegularPolygon, Rectangle, ANTIALIAS_X4, ANTIALIAS_X16
display = DVHSTX(PEN_P8, 640, 360)
vector = PicoVector(display)
vector.set_antialiasing(ANTIALIAS_X4)
BG = display.create_pen(20, 20, 50)
RED = display.create_pen(200, 0, 0)
BLACK = display.create_pen(0, 0, 0)
GREY = display.create_pen(200, 200, 200)
WHITE = display.create_pen(255, 255, 255)
"""
# Redefine colours for a Blue clock
RED = display.create_pen(200, 0, 0)
BLACK = display.create_pen(135, 159, 169)
GREY = display.create_pen(10, 40, 50)
WHITE = display.create_pen(14, 60, 76)
"""
WIDTH, HEIGHT = display.get_bounds()
hub = RegularPolygon(int(WIDTH / 2), int(HEIGHT / 2), 24, 5)
face = RegularPolygon(int(WIDTH / 2), int(HEIGHT / 2), 48, int(HEIGHT / 2))
print(time.localtime())
last_second = None
while True:
t_start = time.ticks_ms()
year, month, day, hour, minute, second, _, _ = time.localtime()
if last_second == second:
continue
last_second = second
display.set_pen(0)
display.clear()
display.set_pen(BLACK)
display.circle(int(WIDTH / 2), int(HEIGHT / 2), int(HEIGHT / 2))
display.set_pen(WHITE)
display.circle(int(WIDTH / 2), int(HEIGHT / 2), int(HEIGHT / 2) - 4)
display.set_pen(GREY)
for a in range(60):
tick_mark = Rectangle(int(WIDTH / 2) - 3, 10, 6, int(HEIGHT / 48))
vector.rotate(tick_mark, 360 / 60.0 * a, int(WIDTH / 2), int(HEIGHT / 2))
vector.translate(tick_mark, 0, 2)
vector.draw(tick_mark)
for a in range(12):
hour_mark = Rectangle(int(WIDTH / 2) - 5, 10, 10, int(HEIGHT / 10))
vector.rotate(hour_mark, 360 / 12.0 * a, int(WIDTH / 2), int(HEIGHT / 2))
vector.translate(hour_mark, 0, 2)
vector.draw(hour_mark)
angle_second = second * 6
second_hand_length = int(HEIGHT / 2) - int(HEIGHT / 8)
second_hand = Polygon((-2, -second_hand_length), (-2, int(HEIGHT / 8)), (2, int(HEIGHT / 8)), (2, -second_hand_length))
vector.rotate(second_hand, angle_second, 0, 0)
vector.translate(second_hand, int(WIDTH / 2), int(HEIGHT / 2) + 5)
angle_minute = minute * 6
angle_minute += second / 10.0
minute_hand_length = int(HEIGHT / 2) - int(HEIGHT / 24)
minute_hand = Polygon((-5, -minute_hand_length), (-10, int(HEIGHT / 16)), (10, int(HEIGHT / 16)), (5, -minute_hand_length))
vector.rotate(minute_hand, angle_minute, 0, 0)
vector.translate(minute_hand, int(WIDTH / 2), int(HEIGHT / 2) + 5)
angle_hour = (hour % 12) * 30
angle_hour += minute / 2
hour_hand_length = int(HEIGHT / 2) - int(HEIGHT / 8)
hour_hand = Polygon((-5, -hour_hand_length), (-10, int(HEIGHT / 16)), (10, int(HEIGHT / 16)), (5, -hour_hand_length))
vector.rotate(hour_hand, angle_hour, 0, 0)
vector.translate(hour_hand, int(WIDTH / 2), int(HEIGHT / 2) + 5)
display.set_pen(GREY)
vector.draw(minute_hand)
vector.draw(hour_hand)
vector.draw(second_hand)
display.set_pen(BLACK)
for a in range(60):
tick_mark = Rectangle(int(WIDTH / 2) - 3, 10, 6, int(HEIGHT / 48))
vector.rotate(tick_mark, 360 / 60.0 * a, int(WIDTH / 2), int(HEIGHT / 2))
vector.draw(tick_mark)
for a in range(12):
hour_mark = Rectangle(int(WIDTH / 2) - 5, 10, 10, int(HEIGHT / 10))
vector.rotate(hour_mark, 360 / 12.0 * a, int(WIDTH / 2), int(HEIGHT / 2))
vector.draw(hour_mark)
vector.translate(minute_hand, 0, -5)
vector.translate(hour_hand, 0, -5)
vector.draw(minute_hand)
vector.draw(hour_hand)
display.set_pen(RED)
vector.translate(second_hand, 0, -5)
vector.draw(second_hand)
vector.draw(hub)
display.update()
gc.collect()
t_end = time.ticks_ms()
print(f"Took {t_end - t_start}ms")

View file

@ -1,44 +0,0 @@
if(NOT DEFINED PIMORONI_PICO_PATH)
set(PIMORONI_PICO_PATH ../pimoroni-pico)
endif()
include(${CMAKE_CURRENT_LIST_DIR}/../pimoroni_pico_import.cmake)
include_directories(${PIMORONI_PICO_PATH}/micropython)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../")
list(APPEND CMAKE_MODULE_PATH "${PIMORONI_PICO_PATH}/micropython")
list(APPEND CMAKE_MODULE_PATH "${PIMORONI_PICO_PATH}/micropython/modules")
# Allows us to find /pga/modules/c/<module>/micropython
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
# Essential
include(pimoroni_i2c/micropython)
include(pimoroni_bus/micropython)
# Pico Graphics Essential
include(hershey_fonts/micropython)
include(bitmap_fonts/micropython)
include(picovector/micropython)
include(modules/picographics/micropython)
# Pico Graphics Extra
include(jpegdec/micropython)
include(pngdec/micropython)
include(qrcode/micropython/micropython)
# Sensors & Breakouts
include(micropython-common-breakouts)
# Utility
include(adcfft/micropython)
# Note: cppmem is *required* for C++ code to function on MicroPython
# it redirects `malloc` and `free` calls to MicroPython's heap
include(cppmem/micropython)
# version.py, pimoroni.py and boot.py
include(modules_py/modules_py)

View file

@ -1,582 +0,0 @@
# Pico Graphics <!-- omit in toc -->
Pico Graphics is our unified graphics and display library for driving displays from your Pico in MicroPython.
Pico Graphics replaces the individual drivers for displays- if you're been using breakout_colorlcd, ST7789 then you'll need to update your code!
- [Setting up Pico Graphics](#setting-up-pico-graphics)
- [Supported Displays](#supported-displays)
- [Interstate75 and Interstate75W Display modes](#interstate75-and-interstate75w-display-modes)
- [Supported Graphics Modes (Pen Type)](#supported-graphics-modes-pen-type)
- [Supported Rotations](#supported-rotations)
- [Custom Pins](#custom-pins)
- [SPI / Parallel](#spi--parallel)
- [I2C](#i2c)
- [Function Reference](#function-reference)
- [General](#general)
- [Creating and Setting Pens](#creating-and-setting-pens)
- [RGB888, RGB565, RGB332, P8 and P4 modes](#rgb888-rgb565-rgb332-p8-and-p4-modes)
- [Monochrome Modes](#monochrome-modes)
- [Inky Frame](#inky-frame)
- [Controlling the Backlight](#controlling-the-backlight)
- [Clipping](#clipping)
- [Clear](#clear)
- [Update](#update)
- [Get Bounds](#get-bounds)
- [Text](#text)
- [Changing The Font](#changing-the-font)
- [Changing The Thickness](#changing-the-thickness)
- [Drawing Text](#drawing-text)
- [Basic Shapes](#basic-shapes)
- [Line](#line)
- [Circle](#circle)
- [Rectangle](#rectangle)
- [Triangle](#triangle)
- [Polygon](#polygon)
- [Pixels](#pixels)
- [Palette Management](#palette-management)
- [Utility Functions](#utility-functions)
- [Sprites](#sprites)
- [Loading Sprites](#loading-sprites)
- [Drawing Sprites](#drawing-sprites)
- [JPEG Files](#jpeg-files)
## Setting up Pico Graphics
You must construct an instance of PicoGraphics with your desired display:
```python
from picographics import PicoGraphics, DISPLAY_LCD_160X80
display = PicoGraphics(display=DISPLAY_LCD_160X80)
```
Bear in mind that MicroPython has only 192K of RAM available- a 320x240 pixel display in RGB565 mode uses 150K!
### Supported Displays
* Pico Display - 240x135 SPI LCD - `DISPLAY_PICO_DISPLAY`
* Pico Display 2 - 320x240 SPI LCD - `DISPLAY_PICO_DISPLAY_2`
* Tufty 2040 - 320x240 Parallel LCD - `DISPLAY_TUFTY_2040`
* Pico Explorer - 240x240 SPI LCD - `DISPLAY_PICO_EXPLORER`
* Enviro Plus - 240x240 SPI LCD - `DISPLAY_ENVIRO_PLUS`
* 240x240 Round SPI LCD Breakout - `DISPLAY_ROUND_LCD_240X240`
* 240x240 Square SPI LCD Breakout - `DISPLAY_LCD_240X240`
* 160x80 SPI LCD Breakout - `DISPLAY_LCD_160X80`
* 128x128 I2C OLED - `DISPLAY_I2C_OLED_128X128`
* Pico Inky Pack / Badger 2040 / Badger 2040 W - 296x128 mono E ink - `DISPLAY_INKY_PACK`
* Inky Frame 5.7" - 600x448 7-colour E ink - `DISPLAY_INKY_FRAME`
* Inky Frame 4.0" - 640x400 7-colour E ink - `DISPLAY_INKY_FRAME_4`
* Inky Frame 7.3" - 800x480 7-colour E ink - `DISPLAY_INKY_FRAME_7`
* Pico GFX Pack - 128x64 mono LCD Matrix - `DISPLAY_GFX_PACK`
* Galactic Unicorn - 53x11 LED Matrix - `DISPLAY_GALACTIC_UNICORN`
* Interstate75 and 75W - HUB75 Matrix driver - `DISPLAY_INTERSTATE75_SIZEOFMATRIX` please read below!
* Cosmic Unicorn - 32x32 LED Matrix - `DISPLAY_COSMIC_UNICORN`
#### Interstate75 and Interstate75W Display modes
Both the Interstate75 and Interstate75W support lots of different sizes of HUB75 matrix displays.
The available display settings are listed here:
* 32 x 32 Matrix - `DISPLAY_INTERSTATE75_32X32`
* 64 x 32 Matrix - `DISPLAY_INTERSTATE75_64X32`
* 96 x 32 Matrix - `DISPLAY_INTERSTATE75_96X32`
* 128 x 32 Matrix - `DISPLAY_INTERSTATE75_128X32`
* 64 x 64 Matrix - `DISPLAY_INTERSTATE75_64X64`
* 128 x 64 Matrix - `DISPLAY_INTERSTATE75_128X64`
* 192 x 64 Matrix - `DISPLAY_INTERSTATE75_192X64`
* 256 x 64 Matrix - `DISPLAY_INTERSTATE75_256X64`
### Supported Graphics Modes (Pen Type)
* 1-bit - `PEN_1BIT` - mono, used for Pico Inky Pack and i2c OLED
* 3-bit - `PEN_3BIT` - 8-colour, used for Inky Frame
* 4-bit - `PEN_P4` - 16-colour palette of your choice
* 8-bit - `PEN_P8` - 256-colour palette of your choice
* 8-bit RGB332 - `PEN_RGB332` - 256 fixed colours (3 bits red, 3 bits green, 2 bits blue)
* 16-bit RGB565 - `PEN_RGB565` - 64K colours at the cost of RAM. (5 bits red, 6 bits green, 5 bits blue)
* 24-bit RGB888 - `PEN_RGB888` - 16M colours at the cost of lots of RAM. (8 bits red, 8 bits green, 8 bits blue)
These offer a tradeoff between RAM usage and available colours. In most cases you would probably use `RGB332` since it offers the easiest tradeoff. It's also the default for colour LCDs.
Eg:
```python
display = PicoGraphics(display=PICO_DISPLAY)
```
Is equivalent to:
```python
display = PicoGraphics(display=PICO_DISPLAY, pen_type=PEN_RGB332)
```
### Supported Rotations
All SPI LCDs support 0, 90, 180 and 270 degree rotations.
Eg:
```python
display = PicoGraphics(display=PICO_DISPLAY, rotate=90)
```
### Custom Pins
#### SPI / Parallel
The `pimoroni_bus` library includes `SPIBus` for SPI LCDs and `ParallelBus` for Parallel LCDs (like Tufty 2040).
In most cases you'll never need to use these, but they come in useful if you're wiring breakouts to your Pico or using multiple LCDs.
A custom SPI bus:
```python
from pimoroni_bus import SPIBus
from picographics import PicoGraphics, DISPLAY_PICO_EXPLORER, PEN_RGB332
spibus = SPIBus(cs=17, dc=16, sck=18, mosi=19)
display = PicoGraphics(display=DISPLAY_PICO_EXPLORER, bus=spibus, pen_type=PEN_RGB332)
```
#### I2C
The `pimoroni_i2c` library includes `PimoroniI2C` which can be used to change the pins used by the mono OLED:
```python
from pimoroni_i2c import PimoroniI2C
from picographics import PicoGraphics, DISPLAY_I2C_OLED_128X128
i2cbus = PimoroniI2C(4, 5)
display = PicoGraphics(display=DISPLAY_I2C_OLED_128X128, bus=i2cbus)
```
## Function Reference
### General
#### Creating and Setting Pens
##### RGB888, RGB565, RGB332, P8 and P4 modes
Create a pen colour for drawing into a screen:
```python
my_pen = display.create_pen(r, g, b)
```
In RGB565 and RGB332 modes this packs the given RGB into an integer representing a colour in these formats and returns the result.
In P4 and P8 modes this will consume one palette entry, or return an error if your palette is full. Palette colours are stored as RGB and converted when they are displayed on screen.
You can also now specify an HSV pen, which allows a pen to be created from HSV (Hue, Saturation, Value) values between 0.0 and 1.0, avoiding the need to calculate the RGB result in Python.
```python
display.create_pen_hsv(h, s, v)
```
To tell PicoGraphics which pen to use:
```python
display.set_pen(my_pen)
```
This will be either an RGB332, RGB565 or RGB888 colour, or a palette index.
##### Monochrome Modes
For 1BIT mode - such as for Inky Pack and the Mono OLED - pens are handled a little differently.
There's no need to create one, since mapping an RGB colour to black/white is meaningless.
Instead you can pick from 16 shades of grey which are automatically dithered into the PicoGraphics buffer, where:
* `0` is Black,
* `1 - 14` are shades of grey,
* `15` is white.
And just call `set_pen` with your desired shade:
```python
display.set_pen(0) # Black
display.set_pen(15) # White
```
Because shades 1 through 14 are created with ordered dither you should avoid using them for text, small details or lines.
Dithering works by mixing black and white pixels in various patterns and quantities to fake grey shades.
If you were to try and draw a single "grey" pixel it will end up either black or white depending on where it's drawn and which shade of grey you pick.
##### Inky Frame
Inky Frame is a special case- the display itself supports only 7 (8 if you include its cleaning "clear" colour, which we call Taupe) colours.
These are:
* `BLACK` = 0
* `WHITE` = 1
* `GREEN` = 2
* `BLUE` = 3
* `RED` = 4
* `YELLOW` = 5
* `ORANGE` = 6
* `TAUPE` = 7
#### Controlling the Backlight
You can set the display backlight brightness between `0.0` and `1.0`:
```python
display.set_backlight(0.5)
```
#### Clipping
Set the clipping bounds for drawing:
```python
display.set_clip(x, y, w, h)
```
Remove the clipping bounds:
```python
display.remove_clip()
```
#### Clear
Clear the display to the current pen colour:
```python
display.clear()
```
This is equivalent to:
```python
w, h = display.get_bounds()
display.rectangle(0, 0, w, h)
```
You can clear portions of the screen with rectangles to save time redrawing things like JPEGs or complex graphics.
#### Update
Send the contents of your Pico Graphics buffer to your screen:
```python
display.update()
```
If you are using a Galactic Unicorn, then the process for updating the display is different. Instead of the above, do:
```python
galactic_unicorn.update(display)
```
#### Get Bounds
You can use `get_bounds()` to get the width and height of the display - useful for writing code that's portable across different displays.
```python
WIDTH, HEIGHT = display.get_bounds()
```
### Text
#### Changing The Font
Change the font:
```python
display.set_font(font)
```
Bitmap fonts.
These are aligned from their top-left corner.
* `bitmap6`
* `bitmap8`
* `bitmap14_outline`
Vector (Hershey) fonts.
These are aligned horizontally (x) to their left edge, but vertically (y) to their midline excluding descenders [i.e., aligned at top edge of lower case letter m]. At `scale=1`, the top edge of upper case letters is 10 pixels above the specified `y`, text baseline is 10 pixels below the specified `y`, and descenders go down to 20 pixels below the specified `y`.
* `sans`
* `gothic`
* `cursive`
* `serif_italic`
* `serif`
#### Changing The Thickness
Vector (Hershey) fonts are drawn with individual lines. By default these are 1px thick, making for very thin and typically illegible text.
To change the thickness of lines used for Vector fonts, use the `set_thickness` method:
```python
display.set_thickness(n)
```
Drawing thick text involves setting a lot more pixels and may slow your drawing down considerably. Be careful how and where you use this.
#### Drawing Text
Write some text:
```python
display.text(text, x, y, wordwrap, scale, angle, spacing)
```
* `text` - the text string to draw
* `x` - the destination X coordinate
* `y` - the destination Y coordinate
* `wordwrap` - number of pixels width before trying to break text into multiple lines
* `scale` - size
* `angle` - rotation angle (Vector only!)
* `spacing` - letter spacing
Text scale can be a whole number (integer) for Bitmap fonts, or a decimal (float) for Vector (Hershey) fonts.
For example:
```python
display.set_font("bitmap8")
display.text("Hello World", 0, 0, scale=2)
```
Draws "Hello World" in a 16px tall, 2x scaled version of the `bitmap8` font.
Sometimes you might want to measure a text string for centering or alignment on screen, you can do this with:
```python
width = display.measure_text(text, scale, spacing)
```
The height of each Bitmap font is explicit in its name.
Write a single character:
```python
display.character(char, x, y, scale)
```
Specify `char` using a [decimal ASCII code](https://www.ascii-code.com/). Note not all characters are supported.
For example:
```python
display.set_font("bitmap8")
display.character(38, 0, 0, scale=2)
```
Draws an ampersand in a 16px tall, 2x scaled version of the 'bitmap8' font.
### Basic Shapes
#### Line
To draw a straight line at any angle between two specified points:
```python
display.line(x1, y1, x2, y2)
```
The X1/Y1 and X2/Y2 coordinates describe the start and end of the line respectively.
If you need a thicker line, for an outline or UI elements you can supply a fifth parameter - thickness - like so:
```python
display.line(x1, y1, x2, y2, thickness)
```
#### Circle
To draw a circle:
```python
display.circle(x, y, r)
```
* `x` - the destination X coordinate
* `y` - the destination Y coordinate
* `r` - the radius
The X/Y coordinates describe the center of your circle.
#### Rectangle
```python
display.rectangle(x, y, w, h)
```
* `x` - the destination X coordinate
* `y` - the destination Y coordinate
* `w` - the width
* `h` - the height
#### Triangle
```python
display.triangle(x1, y1, x2, y2, x3, y3)
```
The three pairs of X/Y coordinates describe each point of the triangle.
#### Polygon
To draw other shapes, you can provide a list of points to `polygon`:
```python
display.polygon([
(0, 10),
(20, 10),
(20, 0),
(30, 20),
(20, 30),
(20, 20),
(0, 20),
])
```
### Pixels
Setting individual pixels is slow, but you can do it with:
```python
display.pixel(x, y)
```
You can draw a horizontal span of pixels a little faster with:
```python
display.pixel_span(x, y, length)
```
(use `display.line()` instead if you want to draw a straight line at any angle)
### Palette Management
Intended for P4 and P8 modes.
You have a 16-color and 256-color palette respectively.
Set n elements in the palette from a list of RGB tuples:
```python
display.set_palette([
(r, g, b),
(r, g, b),
(r, g, b)
])
```
Update an entry in the P4 or P8 palette with the given colour.
```python
display.update_pen(index, r, g, b)
```
This is stored internally as RGB and converted to whatever format your screen requires when displayed.
Reset a pen back to its default value (black, marked unused):
```python
display.reset_pen(index)
```
#### Utility Functions
Sometimes it can be useful to convert between colour formats:
* `RGB332_to_RGB`
* `RGB_to_RGB332`
* `RGB565_to_RGB`
* `RGB_to_RGB565`
### Sprites
Pico Display has very limited support for sprites in RGB332 mode.
Sprites must be 8x8 pixels arranged in a 128x128 pixel spritesheet. 1-bit transparency is handled by electing a single colour to skip over.
We've prepared some RGB332-compatible sprite assets for you, but you can use `spritesheet-to-rgb332.py <filename>` to convert your own.
#### Loading Sprites
You'll need to include the [pen_type](#supported-graphics-modes-pen-type) in the import statement, and define the pen_type before using loading the spritesheet:
``` python
from picographics import PicoGraphics, PEN_RGB565, PEN_RGB332
display = PicoGraphics(display=PICO_DISPLAY, pen_type=PEN_RGB332)
```
Use Thonny to upload your `spritesheet.rgb332` file onto your Pico. Then load it into Pico Graphics:
```python
display.load_spritesheet("s4m_ur4i-dingbads.rgb332")
```
and then update the display, to show the sprite:
```python
display.update()
```
#### Drawing Sprites
And finally display a sprite:
```python
display.sprite(0, 0, 0, 0)
```
These arguments for `sprite` are as follows:
1. Sprite X position (from 0-15) - this selects the horizontal location of an 8x8 sprite from your 128x128 pixel spritesheet.
2. Sprite Y position (from 0-15)
3. Destination X - where to draw on your screen horizontally
4. Destination Y = where to draw on your screen vertically
5. Scale (optional) - an integer scale value, 1 = 8x8, 2 = 16x16 etc.
6. Transparent (optional) - specify a colour to treat as transparent
### JPEG Files
We've included BitBank's JPEGDEC - https://github.com/bitbank2/JPEGDEC - so you can display JPEG files on your LCDs.
Eg:
```python
import picographics
import jpegdec
display = picographics.PicoGraphics(display=picographics.DISPLAY_PICO_EXPLORER)
# Create a new JPEG decoder for our PicoGraphics
j = jpegdec.JPEG(display)
# Open the JPEG file
j.open_file("filename.jpeg")
# Decode the JPEG
j.decode(0, 0, jpegdec.JPEG_SCALE_FULL, dither=True)
# Display the result
display.update()
```
JPEG files must be small enough to load into RAM for decoding, and must *not* be progressive.
JPEG files will be automatically dithered in RGB332 mode.
In P4 and P8 modes JPEGs are dithered to your custom colour palette. Their appearance of an image will vary based on the colours you choose.
The arguments for `decode` are as follows:
1. Decode X - where to place the decoded JPEG on screen
2. Decode Y
3. Flags - one of `JPEG_SCALE_FULL`, `JPEG_SCALE_HALF`, `JPEG_SCALE_QUARTER` or `JPEG_SCALE_EIGHTH`
4. If you want to turn off dither altogether, try `dither=False`. This is useful if you want to [pre-dither your images](https://ditherit.com/) or for artsy posterization effects.

View file

@ -1,48 +0,0 @@
set(MOD_NAME picographics)
string(TOUPPER ${MOD_NAME} MOD_NAME_UPPER)
add_library(usermod_${MOD_NAME} INTERFACE)
get_filename_component(PICOVISION_PATH ${CMAKE_CURRENT_LIST_DIR}/../.. ABSOLUTE)
target_sources(usermod_${MOD_NAME} INTERFACE
${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.c
${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.cpp
${PICOVISION_PATH}/drivers/dvhstx/dvhstx.cpp
${PICOVISION_PATH}/drivers/dvhstx/dvi.cpp
${PICOVISION_PATH}/drivers/dvhstx/intel_one_mono_2bpp.c
${PIMORONI_PICO_PATH}/libraries/pico_graphics/pico_graphics.cpp
${PICOVISION_PATH}/libraries/pico_graphics/pico_graphics_pen_dvhstx_rgb565.cpp
${PICOVISION_PATH}/libraries/pico_graphics/pico_graphics_pen_dvhstx_p8.cpp
${PIMORONI_PICO_PATH}/libraries/pico_graphics/types.cpp
)
# MicroPython compiles with -Os by default, these functions are critical path enough that -O2 is worth it (note -O3 is slower in this case)
set_source_files_properties(${PICOVISION_PATH}/drivers/dvhstx/dvhstx.cpp PROPERTIES COMPILE_OPTIONS "-O2")
target_include_directories(usermod_${MOD_NAME} INTERFACE
${CMAKE_CURRENT_LIST_DIR}
${PICOVISION_PATH}
${PICOVISION_PATH}/drivers/dvhstx
${PICOVISION_PATH}/libraries/pico_graphics # for pico_graphics_dv.hpp
${PIMORONI_PICO_PATH}/libraries/pico_graphics # for pico_graphics.hpp
# ${PIMORONI_PICO_PATH}/libraries/pngdec
)
target_compile_definitions(usermod_${MOD_NAME} INTERFACE
-DMODULE_${MOD_NAME_UPPER}_ENABLED=1
)
if (SUPPORT_WIDE_MODES)
target_compile_definitions(usermod_${MOD_NAME} INTERFACE
-DSUPPORT_WIDE_MODES=1
)
endif()
target_link_libraries(usermod INTERFACE usermod_${MOD_NAME} hardware_vreg)
set_source_files_properties(
${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.c
PROPERTIES COMPILE_FLAGS
"-Wno-discarded-qualifiers"
)

View file

@ -1,147 +0,0 @@
#include "picographics.h"
// Class Methods
MP_DEFINE_CONST_FUN_OBJ_1(ModPicoGraphics_update_obj, ModPicoGraphics_update);
// Palette management
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ModPicoGraphics_update_pen_obj, 5, 5, ModPicoGraphics_update_pen);
MP_DEFINE_CONST_FUN_OBJ_2(ModPicoGraphics_reset_pen_obj, ModPicoGraphics_reset_pen);
MP_DEFINE_CONST_FUN_OBJ_KW(ModPicoGraphics_set_palette_obj, 2, ModPicoGraphics_set_palette);
// Pen
MP_DEFINE_CONST_FUN_OBJ_2(ModPicoGraphics_set_pen_obj, ModPicoGraphics_set_pen);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ModPicoGraphics_create_pen_obj, 4, 4, ModPicoGraphics_create_pen);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ModPicoGraphics_create_pen_hsv_obj, 4, 4, ModPicoGraphics_create_pen_hsv);
MP_DEFINE_CONST_FUN_OBJ_2(ModPicoGraphics_set_thickness_obj, ModPicoGraphics_set_thickness);
// Alpha Blending
MP_DEFINE_CONST_FUN_OBJ_2(ModPicoGraphics_set_bg_obj, ModPicoGraphics_set_bg);
MP_DEFINE_CONST_FUN_OBJ_2(ModPicoGraphics_set_blend_mode_obj, ModPicoGraphics_set_blend_mode);
// Depth
MP_DEFINE_CONST_FUN_OBJ_2(ModPicoGraphics_set_depth_obj, ModPicoGraphics_set_depth);
// Primitives
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ModPicoGraphics_set_clip_obj, 5, 5, ModPicoGraphics_set_clip);
MP_DEFINE_CONST_FUN_OBJ_1(ModPicoGraphics_remove_clip_obj, ModPicoGraphics_remove_clip);
MP_DEFINE_CONST_FUN_OBJ_1(ModPicoGraphics_clear_obj, ModPicoGraphics_clear);
MP_DEFINE_CONST_FUN_OBJ_3(ModPicoGraphics_pixel_obj, ModPicoGraphics_pixel);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ModPicoGraphics_pixel_span_obj, 4, 4, ModPicoGraphics_pixel_span);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ModPicoGraphics_rectangle_obj, 5, 5, ModPicoGraphics_rectangle);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ModPicoGraphics_circle_obj, 4, 4, ModPicoGraphics_circle);
MP_DEFINE_CONST_FUN_OBJ_KW(ModPicoGraphics_character_obj, 1, ModPicoGraphics_character);
MP_DEFINE_CONST_FUN_OBJ_KW(ModPicoGraphics_text_obj, 1, ModPicoGraphics_text);
MP_DEFINE_CONST_FUN_OBJ_KW(ModPicoGraphics_measure_text_obj, 1, ModPicoGraphics_measure_text);
MP_DEFINE_CONST_FUN_OBJ_KW(ModPicoGraphics_polygon_obj, 2, ModPicoGraphics_polygon);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ModPicoGraphics_triangle_obj, 7, 7, ModPicoGraphics_triangle);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ModPicoGraphics_line_obj, 5, 6, ModPicoGraphics_line);
// Sprites
MP_DEFINE_CONST_FUN_OBJ_KW(ModPicoGraphics_load_sprite_obj, 2, ModPicoGraphics_load_sprite);
MP_DEFINE_CONST_FUN_OBJ_KW(ModPicoGraphics_display_sprite_obj, 5, ModPicoGraphics_display_sprite);
MP_DEFINE_CONST_FUN_OBJ_2(ModPicoGraphics_clear_sprite_obj, ModPicoGraphics_clear_sprite);
// Utility
MP_DEFINE_CONST_FUN_OBJ_1(ModPicoGraphics_get_bounds_obj, ModPicoGraphics_get_bounds);
MP_DEFINE_CONST_FUN_OBJ_2(ModPicoGraphics_set_font_obj, ModPicoGraphics_set_font);
MP_DEFINE_CONST_FUN_OBJ_1(ModPicoGraphics__del__obj, ModPicoGraphics__del__);
// Loop
MP_DEFINE_CONST_FUN_OBJ_3(ModPicoGraphics_loop_obj, ModPicoGraphics_loop);
static const mp_rom_map_elem_t ModPicoGraphics_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&ModPicoGraphics_pixel_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_pen), MP_ROM_PTR(&ModPicoGraphics_set_pen_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_thickness), MP_ROM_PTR(&ModPicoGraphics_set_thickness_obj) },
{ MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&ModPicoGraphics_clear_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_bg), MP_ROM_PTR(&ModPicoGraphics_set_bg_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_blend_mode), MP_ROM_PTR(&ModPicoGraphics_set_blend_mode_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_depth), MP_ROM_PTR(&ModPicoGraphics_set_depth_obj) },
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&ModPicoGraphics_update_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_clip), MP_ROM_PTR(&ModPicoGraphics_set_clip_obj) },
{ MP_ROM_QSTR(MP_QSTR_remove_clip), MP_ROM_PTR(&ModPicoGraphics_remove_clip_obj) },
{ MP_ROM_QSTR(MP_QSTR_pixel_span), MP_ROM_PTR(&ModPicoGraphics_pixel_span_obj) },
{ MP_ROM_QSTR(MP_QSTR_rectangle), MP_ROM_PTR(&ModPicoGraphics_rectangle_obj) },
{ MP_ROM_QSTR(MP_QSTR_circle), MP_ROM_PTR(&ModPicoGraphics_circle_obj) },
{ MP_ROM_QSTR(MP_QSTR_character), MP_ROM_PTR(&ModPicoGraphics_character_obj) },
{ MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&ModPicoGraphics_text_obj) },
{ MP_ROM_QSTR(MP_QSTR_measure_text), MP_ROM_PTR(&ModPicoGraphics_measure_text_obj) },
{ MP_ROM_QSTR(MP_QSTR_polygon), MP_ROM_PTR(&ModPicoGraphics_polygon_obj) },
{ MP_ROM_QSTR(MP_QSTR_triangle), MP_ROM_PTR(&ModPicoGraphics_triangle_obj) },
{ MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&ModPicoGraphics_line_obj) },
{ MP_ROM_QSTR(MP_QSTR_create_pen), MP_ROM_PTR(&ModPicoGraphics_create_pen_obj) },
{ MP_ROM_QSTR(MP_QSTR_create_pen_hsv), MP_ROM_PTR(&ModPicoGraphics_create_pen_hsv_obj) },
{ MP_ROM_QSTR(MP_QSTR_update_pen), MP_ROM_PTR(&ModPicoGraphics_update_pen_obj) },
{ MP_ROM_QSTR(MP_QSTR_reset_pen), MP_ROM_PTR(&ModPicoGraphics_reset_pen_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_palette), MP_ROM_PTR(&ModPicoGraphics_set_palette_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_bounds), MP_ROM_PTR(&ModPicoGraphics_get_bounds_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_font), MP_ROM_PTR(&ModPicoGraphics_set_font_obj) },
// { MP_ROM_QSTR(MP_QSTR_loop), MP_ROM_PTR(&ModPicoGraphics_loop_obj) },
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&ModPicoGraphics__del__obj) },
};
static MP_DEFINE_CONST_DICT(ModPicoGraphics_locals_dict, ModPicoGraphics_locals_dict_table);
/***** Class Definition *****/
#ifdef MP_DEFINE_CONST_OBJ_TYPE
MP_DEFINE_CONST_OBJ_TYPE(
ModPicoGraphics_type,
MP_QSTR_dvhstx,
MP_TYPE_FLAG_NONE,
make_new, ModPicoGraphics_make_new,
locals_dict, (mp_obj_dict_t*)&ModPicoGraphics_locals_dict
);
#else
const mp_obj_type_t ModPicoGraphics_type = {
{ &mp_type_type },
.name = MP_QSTR_dvhstx,
.make_new = ModPicoGraphics_make_new,
.locals_dict = (mp_obj_dict_t*)&ModPicoGraphics_locals_dict,
};
#endif
/***** Module Globals *****/
static const mp_map_elem_t picographics_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_dvhstx) },
{ MP_ROM_QSTR(MP_QSTR_DVHSTX), (mp_obj_t)&ModPicoGraphics_type },
{ MP_ROM_QSTR(MP_QSTR_PEN_RGB888), MP_ROM_INT(PEN_RGB888) },
{ MP_ROM_QSTR(MP_QSTR_PEN_RGB565), MP_ROM_INT(PEN_RGB565) },
{ MP_ROM_QSTR(MP_QSTR_PEN_P8), MP_ROM_INT(PEN_P8) },
{ MP_ROM_QSTR(MP_QSTR_BLEND_TARGET), MP_ROM_INT(0) },
{ MP_ROM_QSTR(MP_QSTR_BLEND_FIXED), MP_ROM_INT(1) },
{ MP_ROM_QSTR(MP_QSTR_SPRITE_OVERWRITE), MP_ROM_INT(0) },
{ MP_ROM_QSTR(MP_QSTR_SPRITE_UNDER), MP_ROM_INT(1) },
{ MP_ROM_QSTR(MP_QSTR_SPRITE_OVER), MP_ROM_INT(2) },
{ MP_ROM_QSTR(MP_QSTR_SPRITE_BLEND_UNDER), MP_ROM_INT(3) },
{ MP_ROM_QSTR(MP_QSTR_SPRITE_BLEND_OVER), MP_ROM_INT(4) },
#if SUPPORT_WIDE_MODES
{ MP_ROM_QSTR(MP_QSTR_WIDESCREEN), MP_ROM_TRUE },
#else
{ MP_ROM_QSTR(MP_QSTR_WIDESCREEN), MP_ROM_FALSE },
#endif
};
static MP_DEFINE_CONST_DICT(mp_module_picographics_globals, picographics_globals_table);
/***** Module Definition *****/
const mp_obj_module_t picographics_user_cmodule = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&mp_module_picographics_globals,
};
#if MICROPY_VERSION <= 70144
MP_REGISTER_MODULE(MP_QSTR_dvhstx, picographics_user_cmodule, MODULE_PICOGRAPHICS_ENABLED);
#else
MP_REGISTER_MODULE(MP_QSTR_dvhstx, picographics_user_cmodule);
#endif

View file

@ -1,620 +0,0 @@
#include "drivers/dvhstx/dvhstx.hpp"
#include "libraries/pico_graphics/pico_graphics_dvhstx.hpp"
#include "common/pimoroni_common.hpp"
#include "micropython/modules/util.hpp"
using namespace pimoroni;
extern "C" {
#include "picographics.h"
#include "pimoroni_i2c.h"
#include "py/stream.h"
#include "py/reader.h"
#include "py/objarray.h"
#include "extmod/vfs.h"
const std::string_view mp_obj_to_string_r(const mp_obj_t &obj) {
if(mp_obj_is_str_or_bytes(obj)) {
GET_STR_DATA_LEN(obj, str, str_len);
return std::string_view((const char*)str, str_len);
}
mp_raise_TypeError("can't convert object to str implicitly");
}
void __printf_debug_flush() {
for(auto i = 0u; i < 10; i++) {
sleep_ms(2);
mp_event_handle_nowait();
}
}
int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args);
void dvhstx_debug(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
int ret = mp_vprintf(&mp_plat_print, fmt, ap);
va_end(ap);
__printf_debug_flush();
(void)ret;
}
static DVHSTX dv_display;
typedef struct _ModPicoGraphics_obj_t {
mp_obj_base_t base;
PicoGraphicsDVHSTX *graphics;
DVHSTX *display;
} ModPicoGraphics_obj_t;
size_t get_required_buffer_size(PicoGraphicsPenType pen_type, uint width, uint height) {
switch(pen_type) {
//case PEN_RGB888:
//return PicoGraphics_PenDVHSTX_RGB888::buffer_size(width, height);
case PEN_RGB565:
return PicoGraphics_PenDVHSTX_RGB565::buffer_size(width, height);
case PEN_P8:
return PicoGraphics_PenDVHSTX_P8::buffer_size(width, height);
default:
return 0;
}
}
mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
ModPicoGraphics_obj_t *self = nullptr;
enum { ARG_pen_type, ARG_width, ARG_height };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_pen_type, MP_ARG_INT, { .u_int = PEN_P8 } },
{ MP_QSTR_width, MP_ARG_INT, { .u_int = 320 } },
{ MP_QSTR_height, MP_ARG_INT, { .u_int = 240 } }
};
// Parse args.
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
self = mp_obj_malloc_with_finaliser(ModPicoGraphics_obj_t, &ModPicoGraphics_type);
self->base.type = &ModPicoGraphics_type;
bool status = false;
int width = args[ARG_width].u_int;
int height = args[ARG_height].u_int;
int pen_type = args[ARG_pen_type].u_int;
dvhstx_debug("DVHSTX create display\n");
// Create an instance of the graphics library and DV display driver
switch((PicoGraphicsPenType)pen_type) {
case PEN_RGB888:
//self->graphics = m_new_class(PicoGraphics_PenDVHSTX_RGB888, width, height, dv_display);
//status = dv_display.init(width, height, DVHSTX::MODE_RGB888);
break;
case PEN_RGB565:
self->graphics = m_new_class(PicoGraphics_PenDVHSTX_RGB565, width, height, dv_display);
status = dv_display.init(width, height, DVHSTX::MODE_RGB565);
break;
case PEN_P8:
self->graphics = m_new_class(PicoGraphics_PenDVHSTX_P8, width, height, dv_display);
status = dv_display.init(width, height, DVHSTX::MODE_PALETTE);
break;
default:
break;
}
if (!status) {
mp_raise_msg(&mp_type_RuntimeError, "PicoVision: Unsupported Mode!");
}
dvhstx_debug("DVHSTX created\n");
self->display = &dv_display;
// Clear each buffer
for(auto x = 0u; x < 2u; x++){
self->graphics->set_pen(0);
self->graphics->clear();
dv_display.flip_now();
}
return MP_OBJ_FROM_PTR(self);
}
mp_obj_t ModPicoGraphics__del__(mp_obj_t self_in) {
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(self_in, ModPicoGraphics_obj_t);
dv_display.reset();
if (self->graphics) {
m_del_class(PicoGraphicsDVHSTX, self->graphics);
self->graphics = nullptr;
}
return mp_const_none;
}
mp_obj_t ModPicoGraphics_set_font(mp_obj_t self_in, mp_obj_t font) {
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(self_in, ModPicoGraphics_obj_t);
self->graphics->set_font(mp_obj_to_string_r(font));
return mp_const_none;
}
mp_obj_t ModPicoGraphics_get_bounds(mp_obj_t self_in) {
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(self_in, ModPicoGraphics_obj_t);
mp_obj_t tuple[2] = {
mp_obj_new_int(self->graphics->bounds.w),
mp_obj_new_int(self->graphics->bounds.h)
};
return mp_obj_new_tuple(2, tuple);
}
mp_obj_t ModPicoGraphics_update(mp_obj_t self_in) {
(void)self_in;
dv_display.flip_blocking();
return mp_const_none;
}
mp_obj_t ModPicoGraphics_module_RGB332_to_RGB(mp_obj_t rgb332) {
RGB c((RGB332)mp_obj_get_int(rgb332));
mp_obj_t t[] = {
mp_obj_new_int(c.r),
mp_obj_new_int(c.g),
mp_obj_new_int(c.b),
};
return mp_obj_new_tuple(3, t);
}
mp_obj_t ModPicoGraphics_module_RGB565_to_RGB(mp_obj_t rgb565) {
RGB c((RGB565)mp_obj_get_int(rgb565));
mp_obj_t t[] = {
mp_obj_new_int(c.r),
mp_obj_new_int(c.g),
mp_obj_new_int(c.b),
};
return mp_obj_new_tuple(3, t);
}
mp_obj_t ModPicoGraphics_module_RGB_to_RGB332(mp_obj_t r, mp_obj_t g, mp_obj_t b) {
return mp_obj_new_int(RGB(
mp_obj_get_int(r),
mp_obj_get_int(g),
mp_obj_get_int(b)
).to_rgb332());
}
mp_obj_t ModPicoGraphics_module_RGB_to_RGB565(mp_obj_t r, mp_obj_t g, mp_obj_t b) {
return mp_obj_new_int(RGB(
mp_obj_get_int(r),
mp_obj_get_int(g),
mp_obj_get_int(b)
).to_rgb565());
}
mp_obj_t ModPicoGraphics_set_pen(mp_obj_t self_in, mp_obj_t pen) {
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(self_in, ModPicoGraphics_obj_t);
self->graphics->set_pen(mp_obj_get_int(pen));
return mp_const_none;
}
mp_obj_t ModPicoGraphics_set_bg(mp_obj_t self_in, mp_obj_t pen) {
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(self_in, ModPicoGraphics_obj_t);
self->graphics->set_bg(mp_obj_get_int(pen));
return mp_const_none;
}
mp_obj_t ModPicoGraphics_set_blend_mode(mp_obj_t self_in, mp_obj_t pen) {
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(self_in, ModPicoGraphics_obj_t);
self->graphics->set_blend_mode((BlendMode)mp_obj_get_int(pen));
return mp_const_none;
}
mp_obj_t ModPicoGraphics_set_depth(mp_obj_t self_in, mp_obj_t depth) {
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(self_in, ModPicoGraphics_obj_t);
self->graphics->set_depth(mp_obj_get_int(depth));
return mp_const_none;
}
mp_obj_t ModPicoGraphics_reset_pen(mp_obj_t self_in, mp_obj_t pen) {
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(self_in, ModPicoGraphics_obj_t);
self->graphics->reset_pen(mp_obj_get_int(pen));
return mp_const_none;
}
mp_obj_t ModPicoGraphics_update_pen(size_t n_args, const mp_obj_t *args) {
enum { ARG_self, ARG_i, ARG_r, ARG_g, ARG_b };
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self], ModPicoGraphics_obj_t);
self->graphics->update_pen(
mp_obj_get_int(args[ARG_i]) & 0xff,
mp_obj_get_int(args[ARG_r]) & 0xff,
mp_obj_get_int(args[ARG_g]) & 0xff,
mp_obj_get_int(args[ARG_b]) & 0xff
);
return mp_const_none;
}
mp_obj_t ModPicoGraphics_create_pen(size_t n_args, const mp_obj_t *args) {
enum { ARG_self, ARG_r, ARG_g, ARG_b };
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self], ModPicoGraphics_obj_t);
int result = self->graphics->create_pen(
mp_obj_get_int(args[ARG_r]) & 0xff,
mp_obj_get_int(args[ARG_g]) & 0xff,
mp_obj_get_int(args[ARG_b]) & 0xff
);
if (result == -1) mp_raise_ValueError("create_pen failed. No matching colour or space in palette!");
return mp_obj_new_int(result);
}
mp_obj_t ModPicoGraphics_create_pen_hsv(size_t n_args, const mp_obj_t *args) {
enum { ARG_self, ARG_h, ARG_s, ARG_v };
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self], ModPicoGraphics_obj_t);
int result = self->graphics->create_pen_hsv(
mp_obj_get_float(args[ARG_h]),
mp_obj_get_float(args[ARG_s]),
mp_obj_get_float(args[ARG_v])
);
if (result == -1) mp_raise_ValueError("create_pen failed. No matching colour or space in palette!");
return mp_obj_new_int(result);
}
mp_obj_t ModPicoGraphics_set_thickness(mp_obj_t self_in, mp_obj_t pen) {
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(self_in, ModPicoGraphics_obj_t);
self->graphics->set_thickness(mp_obj_get_int(pen));
return mp_const_none;
}
mp_obj_t ModPicoGraphics_set_palette(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
size_t num_tuples = n_args - 1;
const mp_obj_t *tuples = pos_args + 1;
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(pos_args[0], ModPicoGraphics_obj_t);
// Check if there is only one argument, which might be a list
if(n_args == 2) {
if(mp_obj_is_type(pos_args[1], &mp_type_list)) {
mp_obj_list_t *points = MP_OBJ_TO_PTR2(pos_args[1], mp_obj_list_t);
if(points->len <= 0) mp_raise_ValueError("set_palette(): cannot provide an empty list");
num_tuples = points->len;
tuples = points->items;
}
else {
mp_raise_TypeError("set_palette(): can't convert object to list");
}
}
for(size_t i = 0; i < num_tuples; i++) {
mp_obj_t obj = tuples[i];
if(!mp_obj_is_type(obj, &mp_type_tuple)) mp_raise_ValueError("set_palette(): can't convert object to tuple");
mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR2(obj, mp_obj_tuple_t);
if(tuple->len != 3) mp_raise_ValueError("set_palette(): tuple must contain R, G, B values");
self->graphics->update_pen(
i,
mp_obj_get_int(tuple->items[0]),
mp_obj_get_int(tuple->items[1]),
mp_obj_get_int(tuple->items[2])
);
}
return mp_const_none;
}
mp_obj_t ModPicoGraphics_set_clip(size_t n_args, const mp_obj_t *args) {
enum { ARG_self, ARG_x, ARG_y, ARG_w, ARG_h };
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self], ModPicoGraphics_obj_t);
self->graphics->set_clip({
mp_obj_get_int(args[ARG_x]),
mp_obj_get_int(args[ARG_y]),
mp_obj_get_int(args[ARG_w]),
mp_obj_get_int(args[ARG_h])
});
return mp_const_none;
}
mp_obj_t ModPicoGraphics_remove_clip(mp_obj_t self_in) {
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(self_in, ModPicoGraphics_obj_t);
self->graphics->remove_clip();
return mp_const_none;
}
mp_obj_t ModPicoGraphics_clear(mp_obj_t self_in) {
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(self_in, ModPicoGraphics_obj_t);
self->graphics->clear();
return mp_const_none;
}
mp_obj_t ModPicoGraphics_pixel(mp_obj_t self_in, mp_obj_t x, mp_obj_t y) {
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(self_in, ModPicoGraphics_obj_t);
self->graphics->pixel({
mp_obj_get_int(x),
mp_obj_get_int(y)
});
return mp_const_none;
}
mp_obj_t ModPicoGraphics_pixel_span(size_t n_args, const mp_obj_t *args) {
enum { ARG_self, ARG_x, ARG_y, ARG_l };
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self], ModPicoGraphics_obj_t);
self->graphics->pixel_span({
mp_obj_get_int(args[ARG_x]),
mp_obj_get_int(args[ARG_y])
}, mp_obj_get_int(args[ARG_l]));
return mp_const_none;
}
mp_obj_t ModPicoGraphics_rectangle(size_t n_args, const mp_obj_t *args) {
enum { ARG_self, ARG_x, ARG_y, ARG_w, ARG_h };
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self], ModPicoGraphics_obj_t);
self->graphics->rectangle({
mp_obj_get_int(args[ARG_x]),
mp_obj_get_int(args[ARG_y]),
mp_obj_get_int(args[ARG_w]),
mp_obj_get_int(args[ARG_h])
});
return mp_const_none;
}
mp_obj_t ModPicoGraphics_circle(size_t n_args, const mp_obj_t *args) {
enum { ARG_self, ARG_x, ARG_y, ARG_r };
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self], ModPicoGraphics_obj_t);
self->graphics->circle({
mp_obj_get_int(args[ARG_x]),
mp_obj_get_int(args[ARG_y])
}, mp_obj_get_int(args[ARG_r]));
return mp_const_none;
}
mp_obj_t ModPicoGraphics_character(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_self, ARG_char, ARG_x, ARG_y, ARG_scale };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_char, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT },
{ MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT },
{ MP_QSTR_scale, MP_ARG_INT, {.u_int = 2} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, ModPicoGraphics_obj_t);
int c = mp_obj_get_int(args[ARG_char].u_obj);
int x = args[ARG_x].u_int;
int y = args[ARG_y].u_int;
int scale = args[ARG_scale].u_int;
self->graphics->character((char)c, Point(x, y), scale);
return mp_const_none;
}
mp_obj_t ModPicoGraphics_text(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_self, ARG_text, ARG_x, ARG_y, ARG_wrap, ARG_scale, ARG_angle, ARG_spacing, ARG_fixed_width };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_text, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_x1, MP_ARG_REQUIRED | MP_ARG_INT },
{ MP_QSTR_y1, MP_ARG_REQUIRED | MP_ARG_INT },
{ MP_QSTR_wordwrap, MP_ARG_INT, {.u_int = __INT32_MAX__} }, // Sort-of a fudge, but wide-enough to avoid wrapping on any display size
{ MP_QSTR_scale, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_angle, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_spacing, MP_ARG_INT, {.u_int = 1} },
{ MP_QSTR_fixed_width, MP_ARG_OBJ, {.u_obj = mp_const_false} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, ModPicoGraphics_obj_t);
mp_obj_t text_obj = args[ARG_text].u_obj;
if(!mp_obj_is_str_or_bytes(text_obj)) mp_raise_TypeError("text: string required");
GET_STR_DATA_LEN(text_obj, str, str_len);
const std::string_view t((const char*)str, str_len);
int x = args[ARG_x].u_int;
int y = args[ARG_y].u_int;
int wrap = args[ARG_wrap].u_int;
float scale = args[ARG_scale].u_obj == mp_const_none ? 2.0f : mp_obj_get_float(args[ARG_scale].u_obj);
int angle = args[ARG_angle].u_int;
int letter_spacing = args[ARG_spacing].u_int;
bool fixed_width = args[ARG_fixed_width].u_obj == mp_const_true;
self->graphics->text(t, Point(x, y), wrap, scale, angle, letter_spacing, fixed_width);
return mp_const_none;
}
mp_obj_t ModPicoGraphics_measure_text(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_self, ARG_text, ARG_scale, ARG_spacing, ARG_fixed_width };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_text, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_scale, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_spacing, MP_ARG_INT, {.u_int = 1} },
{ MP_QSTR_fixed_width, MP_ARG_OBJ, {.u_obj = mp_const_false} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, ModPicoGraphics_obj_t);
mp_obj_t text_obj = args[ARG_text].u_obj;
if(!mp_obj_is_str_or_bytes(text_obj)) mp_raise_TypeError("text: string required");
GET_STR_DATA_LEN(text_obj, str, str_len);
const std::string_view t((const char*)str, str_len);
float scale = args[ARG_scale].u_obj == mp_const_none ? 2.0f : mp_obj_get_float(args[ARG_scale].u_obj);
int letter_spacing = args[ARG_spacing].u_int;
bool fixed_width = args[ARG_fixed_width].u_obj == mp_const_true;
int width = self->graphics->measure_text(t, scale, letter_spacing, fixed_width);
return mp_obj_new_int(width);
}
mp_obj_t ModPicoGraphics_polygon(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
size_t num_tuples = n_args - 1;
const mp_obj_t *tuples = pos_args + 1;
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(pos_args[0], ModPicoGraphics_obj_t);
// Check if there is only one argument, which might be a list
if(n_args == 2) {
if(mp_obj_is_type(pos_args[1], &mp_type_list)) {
mp_obj_list_t *points = MP_OBJ_TO_PTR2(pos_args[1], mp_obj_list_t);
if(points->len <= 0) mp_raise_ValueError("poly(): cannot provide an empty list");
num_tuples = points->len;
tuples = points->items;
}
else {
mp_raise_TypeError("poly(): can't convert object to list");
}
}
if(num_tuples > 0) {
std::vector<Point> points;
for(size_t i = 0; i < num_tuples; i++) {
mp_obj_t obj = tuples[i];
if(!mp_obj_is_type(obj, &mp_type_tuple)) mp_raise_ValueError("poly(): can't convert object to tuple");
mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR2(obj, mp_obj_tuple_t);
if(tuple->len != 2) mp_raise_ValueError("poly(): tuple must only contain two numbers");
points.push_back({
mp_obj_get_int(tuple->items[0]),
mp_obj_get_int(tuple->items[1])
});
}
self->graphics->polygon(points);
}
return mp_const_none;
}
mp_obj_t ModPicoGraphics_triangle(size_t n_args, const mp_obj_t *args) {
enum { ARG_self, ARG_x1, ARG_y1, ARG_x2, ARG_y2, ARG_x3, ARG_y3 };
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self], ModPicoGraphics_obj_t);
self->graphics->triangle(
{mp_obj_get_int(args[ARG_x1]),
mp_obj_get_int(args[ARG_y1])},
{mp_obj_get_int(args[ARG_x2]),
mp_obj_get_int(args[ARG_y2])},
{mp_obj_get_int(args[ARG_x3]),
mp_obj_get_int(args[ARG_y3])}
);
return mp_const_none;
}
mp_obj_t ModPicoGraphics_line(size_t n_args, const mp_obj_t *args) {
enum { ARG_self, ARG_x1, ARG_y1, ARG_x2, ARG_y2, ARG_thickness };
ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self], ModPicoGraphics_obj_t);
if(n_args == 5) {
self->graphics->line(
{mp_obj_get_int(args[ARG_x1]),
mp_obj_get_int(args[ARG_y1])},
{mp_obj_get_int(args[ARG_x2]),
mp_obj_get_int(args[ARG_y2])}
);
}
else if(n_args == 6) {
self->graphics->thick_line(
{mp_obj_get_int(args[ARG_x1]),
mp_obj_get_int(args[ARG_y1])},
{mp_obj_get_int(args[ARG_x2]),
mp_obj_get_int(args[ARG_y2])},
mp_obj_get_int(args[ARG_thickness])
);
}
return mp_const_none;
}
mp_obj_t ModPicoGraphics_loop(mp_obj_t self_in, mp_obj_t update, mp_obj_t render) {
(void)self_in;
/*
TODO: Uh how do we typecheck a function?
if(!mp_obj_is_type(update, &mp_type_function)) {
mp_raise_TypeError("update(ticks_ms) must be a function.");
}
if(!mp_obj_is_type(render, &mp_type_function)) {
mp_raise_TypeError("render(ticks_ms) must be a function.");
}*/
//ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(self_in, ModPicoGraphics_obj_t);
absolute_time_t t_start = get_absolute_time();
mp_obj_t result;
while(true) {
uint32_t tick = absolute_time_diff_us(t_start, get_absolute_time()) / 1000;
result = mp_call_function_1(update, mp_obj_new_int(tick));
if (result == mp_const_false) break;
dv_display.wait_for_flip();
result = mp_call_function_1(render, mp_obj_new_int(tick));
if (result == mp_const_false) break;
dv_display.flip_async();
#ifdef mp_event_handle_nowait
mp_event_handle_nowait();
#endif
}
return mp_const_none;
}
}

View file

@ -1,103 +0,0 @@
#include "py/runtime.h"
#include "py/objstr.h"
enum PicoGraphicsPenType {
PEN_1BIT = 0,
PEN_3BIT,
PEN_P2,
PEN_P4,
PEN_P8,
PEN_RGB332,
PEN_RGB565,
PEN_RGB888,
PEN_INKY7
};
enum PicoGraphicsBusType {
BUS_I2C,
BUS_SPI,
BUS_PARALLEL,
BUS_PIO
};
// Type
extern const mp_obj_type_t ModPicoGraphics_type;
// Module functions
extern mp_obj_t ModPicoGraphics_get_required_buffer_size(mp_obj_t display_in, mp_obj_t pen_type_in);
// DV Display specific functions
extern mp_obj_t ModPicoGraphics_set_scroll_group_offset(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
extern mp_obj_t ModPicoGraphics_set_scroll_group_for_lines(size_t n_args, const mp_obj_t *args);
extern mp_obj_t ModPicoGraphics_tilemap(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
extern mp_obj_t ModPicoGraphics_load_animation(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
// Class methods
extern mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args);
extern mp_obj_t ModPicoGraphics_update(mp_obj_t self_in);
// Palette management
extern mp_obj_t ModPicoGraphics_update_pen(size_t n_args, const mp_obj_t *args);
extern mp_obj_t ModPicoGraphics_reset_pen(mp_obj_t self_in, mp_obj_t pen);
extern mp_obj_t ModPicoGraphics_set_palette(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
extern mp_obj_t ModPicoGraphics_hsv_to_rgb(size_t n_args, const mp_obj_t *args);
// Pen
extern mp_obj_t ModPicoGraphics_set_pen(mp_obj_t self_in, mp_obj_t pen);
extern mp_obj_t ModPicoGraphics_create_pen(size_t n_args, const mp_obj_t *args);
extern mp_obj_t ModPicoGraphics_create_pen_hsv(size_t n_args, const mp_obj_t *args);
extern mp_obj_t ModPicoGraphics_set_thickness(mp_obj_t self_in, mp_obj_t thickness);
// Alpha Blending
extern mp_obj_t ModPicoGraphics_set_bg(mp_obj_t self_in, mp_obj_t pen);
extern mp_obj_t ModPicoGraphics_set_blend_mode(mp_obj_t self_in, mp_obj_t pen);
// Depth
extern mp_obj_t ModPicoGraphics_set_depth(mp_obj_t self_in, mp_obj_t depth);
// Primitives
extern mp_obj_t ModPicoGraphics_set_clip(size_t n_args, const mp_obj_t *args);
extern mp_obj_t ModPicoGraphics_remove_clip(mp_obj_t self_in);
extern mp_obj_t ModPicoGraphics_clear(mp_obj_t self_in);
extern mp_obj_t ModPicoGraphics_pixel(mp_obj_t self_in, mp_obj_t x, mp_obj_t y);
extern mp_obj_t ModPicoGraphics_pixel_span(size_t n_args, const mp_obj_t *args);
extern mp_obj_t ModPicoGraphics_rectangle(size_t n_args, const mp_obj_t *args);
extern mp_obj_t ModPicoGraphics_circle(size_t n_args, const mp_obj_t *args);
extern mp_obj_t ModPicoGraphics_character(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
extern mp_obj_t ModPicoGraphics_text(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
extern mp_obj_t ModPicoGraphics_measure_text(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
extern mp_obj_t ModPicoGraphics_polygon(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
extern mp_obj_t ModPicoGraphics_triangle(size_t n_args, const mp_obj_t *args);
extern mp_obj_t ModPicoGraphics_line(size_t n_args, const mp_obj_t *args);
// Sprites
extern mp_obj_t ModPicoGraphics_load_sprite(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
extern mp_obj_t ModPicoGraphics_display_sprite(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
extern mp_obj_t ModPicoGraphics_clear_sprite(mp_obj_t self_in, mp_obj_t slot);
// Utility
extern mp_obj_t ModPicoGraphics_set_font(mp_obj_t self_in, mp_obj_t font);
extern mp_obj_t ModPicoGraphics_get_bounds(mp_obj_t self_in);
extern mp_obj_t ModPicoGraphics_get_i2c(mp_obj_t self_in);
extern mp_obj_t ModPicoGraphics__del__(mp_obj_t self_in);
// IO IO
extern mp_obj_t ModPicoGraphics_is_button_x_pressed(mp_obj_t self_in);
extern mp_obj_t ModPicoGraphics_is_button_a_pressed(mp_obj_t self_in);
extern mp_obj_t ModPicoGraphics_get_gpu_io_value(mp_obj_t self_in, mp_obj_t pin);
extern mp_obj_t ModPicoGraphics_set_gpu_io_value(mp_obj_t self_in, mp_obj_t pin, mp_obj_t value);
extern mp_obj_t ModPicoGraphics_set_gpu_io_output_enable(mp_obj_t self_in, mp_obj_t pin, mp_obj_t enable);
extern mp_obj_t ModPicoGraphics_set_gpu_io_pull_up(mp_obj_t self_in, mp_obj_t pin, mp_obj_t enable);
extern mp_obj_t ModPicoGraphics_set_gpu_io_pull_down(mp_obj_t self_in, mp_obj_t pin, mp_obj_t enable);
extern mp_obj_t ModPicoGraphics_set_gpu_io_adc_enable(mp_obj_t self_in, mp_obj_t pin, mp_obj_t enable);
extern mp_obj_t ModPicoGraphics_get_gpu_io_adc_voltage(mp_obj_t self_in, mp_obj_t pin);
extern mp_obj_t ModPicoGraphics_get_gpu_temp(mp_obj_t self_in);
// Loop
extern mp_obj_t ModPicoGraphics_loop(mp_obj_t self_in, mp_obj_t update, mp_obj_t render);

View file

@ -1,37 +0,0 @@
#!/bin/env python3
from PIL import Image
import numpy
import sys
import pathlib
# Run with `./filename.py source-image.jpg`
IMAGE_PATH = pathlib.Path(sys.argv[1])
OUTPUT_PATH = IMAGE_PATH.with_suffix(".rgb332")
def image_to_data(image):
"""Generator function to convert a PIL image to 16-bit 565 RGB bytes."""
# NumPy is much faster at doing this. NumPy code provided by:
# Keith (https://www.blogger.com/profile/02555547344016007163)
pb = numpy.array(image.convert('RGBA')).astype('uint16')
r = (pb[:, :, 0] & 0b11100000) >> 0
g = (pb[:, :, 1] & 0b11100000) >> 3
b = (pb[:, :, 2] & 0b11000000) >> 6
a = pb[:, :, 3] # Discard
# AAAA RRRR GGGG BBBB
color = r | g | b
return color.astype("uint8").flatten().tobytes()
img = Image.open(IMAGE_PATH)
w, h = img.size
data = image_to_data(img)
print(f"Converted: {w}x{h} {len(data)} bytes")
with open(OUTPUT_PATH, "wb") as f:
f.write(data)
print(f"Written to: {OUTPUT_PATH}")

View file

@ -1,22 +0,0 @@
include(drivers/dvhstx/dvhstx)
set(LIB_NAME pico_dvhstx)
add_library(${LIB_NAME} INTERFACE)
target_sources(${LIB_NAME} INTERFACE
${PIMORONI_PICO_PATH}/libraries/pico_graphics/pico_graphics.cpp
# ${CMAKE_CURRENT_LIST_DIR}/libraries/pico_graphics/pico_graphics_pen_dvhstx_rgb888.cpp
${CMAKE_CURRENT_LIST_DIR}/libraries/pico_graphics/pico_graphics_pen_dvhstx_rgb565.cpp
${CMAKE_CURRENT_LIST_DIR}/libraries/pico_graphics/pico_graphics_pen_dvhstx_p8.cpp
${PIMORONI_PICO_PATH}/libraries/pico_graphics/types.cpp
)
target_include_directories(${LIB_NAME} INTERFACE
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/libraries/pico_graphics # for pico_graphics_dv.hpp
${PIMORONI_PICO_PATH}/libraries/pico_graphics # for pico_graphics.hpp
${PIMORONI_PICO_PATH}/libraries/pngdec
)
target_link_libraries(${LIB_NAME} INTERFACE dvhstx pico_stdlib hardware_i2c hardware_dma)

View file

@ -1,73 +0,0 @@
# 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 ()
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 Pico 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 Pico 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 master
GIT_SUBMODULES_RECURSE FALSE
)
else ()
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG master
)
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
"Pico 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})

View file

@ -1,56 +0,0 @@
# This file can be dropped into a project to help locate the Pimoroni Pico libraries
# It will also set up the required include and module search paths.
if (DEFINED ENV{PIMORONI_PICO_FETCH_FROM_GIT} AND (NOT PIMORONI_PICO_FETCH_FROM_GIT))
set(PIMORONI_PICO_FETCH_FROM_GIT $ENV{PIMORONI_PICO_FETCH_FROM_GIT})
message("Using PIMORONI_PICO_FETCH_FROM_GIT from environment ('${PIMORONI_PICO_FETCH_FROM_GIT}')")
endif ()
if (DEFINED ENV{PIMORONI_PICO_FETCH_FROM_GIT_PATH} AND (NOT PIMORONI_PICO_FETCH_FROM_GIT_PATH))
set(PIMORONI_PICO_FETCH_FROM_GIT_PATH $ENV{PIMORONI_PICO_FETCH_FROM_GIT_PATH})
message("Using PIMORONI_PICO_FETCH_FROM_GIT_PATH from environment ('${PIMORONI_PICO_FETCH_FROM_GIT_PATH}')")
endif ()
if (NOT PIMORONI_PICO_PATH)
if (PIMORONI_PICO_FETCH_FROM_GIT)
include(FetchContent)
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
if (PIMORONI_PICO_FETCH_FROM_GIT_PATH)
get_filename_component(FETCHCONTENT_BASE_DIR "${PIMORONI_PICO_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
endif ()
FetchContent_Declare(
pimoroni_pico
GIT_REPOSITORY https://github.com/pimoroni/pimoroni-pico
GIT_TAG main
)
if (NOT pimoroni_pico)
message("Downloading PIMORONI_PICO SDK")
FetchContent_Populate(pimoroni_pico)
set(PIMORONI_PICO_PATH ${pimoroni_pico_SOURCE_DIR})
endif ()
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
elseif(PICO_SDK_PATH AND EXISTS "${PICO_SDK_PATH}/../pimoroni-pico")
set(PIMORONI_PICO_PATH ${PICO_SDK_PATH}/../pimoroni-pico)
message("Defaulting PIMORONI_PICO_PATH as sibling of PICO_SDK_PATH: ${PIMORONI_PICO_PATH}")
elseif(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/../../pimoroni-pico/")
set(PIMORONI_PICO_PATH ${CMAKE_CURRENT_BINARY_DIR}/../../pimoroni-pico/)
else()
message(FATAL_ERROR "Pimoroni Pico location was not specified. Please set PIMORONI_PICO_PATH.")
endif()
endif()
get_filename_component(PIMORONI_PICO_PATH "${PIMORONI_PICO_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
if (NOT EXISTS ${PIMORONI_PICO_PATH})
message(FATAL_ERROR "Directory '${PIMORONI_PICO_PATH}' not found")
endif ()
if (NOT EXISTS ${PIMORONI_PICO_PATH}/pimoroni_pico_import.cmake)
message(FATAL_ERROR "Directory '${PIMORONI_PICO_PATH}' does not appear to contain the Pimoroni Pico libraries")
endif ()
message("PIMORONI_PICO_PATH is ${PIMORONI_PICO_PATH}")
set(PIMORONI_PICO_PATH ${PIMORONI_PICO_PATH} CACHE PATH "Path to the Pimoroni Pico libraries" FORCE)
include_directories(${PIMORONI_PICO_PATH})
list(APPEND CMAKE_MODULE_PATH ${PIMORONI_PICO_PATH})