commit
55821d2896
|
@ -38,3 +38,4 @@ add_subdirectory(vl53l5cx)
|
|||
add_subdirectory(pcf85063a)
|
||||
add_subdirectory(pms5003)
|
||||
add_subdirectory(sh1107)
|
||||
add_subdirectory(st7567)
|
|
@ -0,0 +1 @@
|
|||
include(st7567.cmake)
|
|
@ -0,0 +1,42 @@
|
|||
# ST7567 Display Driver for Pimoroni LCDs <!-- omit in toc -->
|
||||
|
||||
The ST7567 driver supports Serial (SPI) ST7567 displays and is intended for use with:
|
||||
|
||||
* Pico GFX Pack
|
||||
|
||||
## Setup
|
||||
|
||||
Construct an instance of the ST7567 driver with SPI pins.
|
||||
|
||||
|
||||
SPI:
|
||||
|
||||
```c++
|
||||
ST7567 st7567(WIDTH, HEIGHT, {
|
||||
PIMORONI_SPI_DEFAULT_INSTANCE, // SPI instance
|
||||
SPI_BG_FRONT_CS, // Chip-select
|
||||
SPI_DEFAULT_SCK, // SPI Clock
|
||||
SPI_DEFAULT_MOSI, // SPI Out
|
||||
PIN_UNUSED, // SPI In
|
||||
SPI_DEFAULT_DC, // SPI Data/Command
|
||||
PIN_UNUSED // Backlight
|
||||
});
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
### Update
|
||||
|
||||
ST7567's `update` accepts an instance of `PicoGraphics` in 1 bit colour mode:
|
||||
|
||||
```c++
|
||||
st7567.update(&graphics);
|
||||
```
|
||||
|
||||
### Set Backlight
|
||||
|
||||
If a backlight pin has been configured, you can set the backlight from 0 to 255:
|
||||
|
||||
```c++
|
||||
st7567.set_backlight(128)
|
||||
```
|
|
@ -0,0 +1,10 @@
|
|||
set(DRIVER_NAME st7567)
|
||||
add_library(${DRIVER_NAME} INTERFACE)
|
||||
|
||||
target_sources(${DRIVER_NAME} INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/${DRIVER_NAME}.cpp)
|
||||
|
||||
target_include_directories(${DRIVER_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(${DRIVER_NAME} INTERFACE pico_stdlib pimoroni_bus hardware_spi hardware_pwm pico_graphics)
|
|
@ -0,0 +1,183 @@
|
|||
#include "st7567.hpp"
|
||||
#include <math.h>
|
||||
|
||||
|
||||
#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c"
|
||||
#define BYTE_TO_BINARY(byte) \
|
||||
(byte & 0x80 ? '1' : '0'), \
|
||||
(byte & 0x40 ? '1' : '0'), \
|
||||
(byte & 0x20 ? '1' : '0'), \
|
||||
(byte & 0x10 ? '1' : '0'), \
|
||||
(byte & 0x08 ? '1' : '0'), \
|
||||
(byte & 0x04 ? '1' : '0'), \
|
||||
(byte & 0x02 ? '1' : '0'), \
|
||||
(byte & 0x01 ? '1' : '0')
|
||||
|
||||
namespace pimoroni {
|
||||
|
||||
enum reg : uint8_t {
|
||||
DISPOFF = 0xAE,//
|
||||
DISPON = 0xAF,//
|
||||
SETSTARTLINE = 0x40,//
|
||||
STARTLINE_MASK = 0x3f,//
|
||||
REG_RATIO = 0x20,//
|
||||
SETPAGESTART = 0xb0,//
|
||||
PAGESTART_MASK = 0x07,//
|
||||
SETCOLL = 0x00, // # 0x00-0x0f: Set lower column address */
|
||||
COLL_MASK = 0x0f,//
|
||||
SETCOLH = 0x10, //# 0x10-0x1f: Set higher column address */
|
||||
COLH_MASK = 0x0F,//
|
||||
SEG_DIR_NORMAL = 0xa0, //# 0xa0: Column address 0 is mapped to SEG0 */
|
||||
SEG_DIR_REV = 0xa1, //# 0xa1: Column address 128 is mapped to S
|
||||
DISPNORMAL = 0xa6, //# 0xa6: Normal display */
|
||||
DISPINVERSE = 0xa7, //# 0xa7: Inverse disp
|
||||
DISPRAM = 0xa4, //# 0xa4: Resume to RAM content display */
|
||||
DISPENTIRE = 0xa5, //# 0xa5: Entire display
|
||||
BIAS_1_9 = 0xa2, //# 0xa2: Select BIAS setting 1/9 */
|
||||
BIAS_1_7 = 0xa3, // # 0xa3: Select BIAS setting
|
||||
ENTER_RMWMODE = 0xe0, //# 0xe0: Enter the Read Modify Write mode */
|
||||
EXIT_RMWMODE = 0xee, //# 0xee: Leave the Read Modify Write mode */
|
||||
EXIT_SOFTRST = 0xe2, // # 0xe2: Software RE
|
||||
SETCOMNORMAL = 0xc0, //# 0xc0: Set COM output direction, normal mode */
|
||||
SETCOMREVERSE = 0xc8, // # 0xc8: Set COM output direction, reverse m
|
||||
POWERCTRL_VF = 0x29, //# 0x29: Control built-in power circuit */
|
||||
POWERCTRL_VR = 0x2a, //# 0x2a: Control built-in power circuit */
|
||||
POWERCTRL_VB = 0x2c, //# 0x2c: Control built-in power circuit */
|
||||
POWERCTRL = 0x2f, // # 0x2c: Control built-in power circ
|
||||
REG_RES_RR0 = 0x21, //# 0x21: Regulation Resistior ratio */
|
||||
REG_RES_RR1 = 0x22, //# 0x22: Regulation Resistior ratio */
|
||||
REG_RES_RR2 = 0x24, // # 0x24: Regulation Resistior ra
|
||||
SETCONTRAST = 0x81, // # 0x81: Set contrast cont
|
||||
SETBOOSTER = 0xf8, //# Set booster level */
|
||||
SETBOOSTER4X = 0x00, //# Set booster level */
|
||||
SETBOOSTER5X = 0x01 , // # Set booster le
|
||||
NOP = 0xe3, //# 0xe3: NOP Command for no operation */
|
||||
STARTBYTES = 0,
|
||||
};
|
||||
|
||||
void ST7567::reset() {
|
||||
if(reset_pin == PIN_UNUSED)
|
||||
return;
|
||||
|
||||
gpio_put(reset_pin, 0); sleep_ms(10);
|
||||
sleep_ms(100);
|
||||
gpio_put(reset_pin, 1); sleep_ms(10);
|
||||
sleep_ms(100);
|
||||
}
|
||||
|
||||
|
||||
void ST7567::init(bool auto_init_sequence) {
|
||||
spi_init(spi, spi_baud);
|
||||
|
||||
gpio_set_function(reset_pin, GPIO_FUNC_SIO);
|
||||
gpio_set_dir(reset_pin, GPIO_OUT);
|
||||
|
||||
gpio_set_function(dc, GPIO_FUNC_SIO);
|
||||
gpio_set_dir(dc, GPIO_OUT);
|
||||
|
||||
gpio_set_function(cs, GPIO_FUNC_SIO);
|
||||
gpio_set_dir(cs, GPIO_OUT);
|
||||
|
||||
gpio_set_function(sck, GPIO_FUNC_SPI);
|
||||
gpio_set_function(mosi, GPIO_FUNC_SPI);
|
||||
|
||||
// if a backlight pin is provided then set it up for
|
||||
// pwm control
|
||||
if(bl != PIN_UNUSED) {
|
||||
pwm_config cfg = pwm_get_default_config();
|
||||
pwm_set_wrap(pwm_gpio_to_slice_num(bl), 65535);
|
||||
pwm_init(pwm_gpio_to_slice_num(bl), &cfg, true);
|
||||
gpio_set_function(bl, GPIO_FUNC_PWM);
|
||||
set_backlight(0); // Turn backlight off initially to avoid nasty surprises
|
||||
}
|
||||
|
||||
//reset display
|
||||
reset();
|
||||
|
||||
|
||||
// if auto_init_sequence then send initialisation sequence
|
||||
// for our standard displays based on the width and height
|
||||
if(auto_init_sequence) {
|
||||
command(reg::BIAS_1_7);
|
||||
command(reg::SEG_DIR_NORMAL);
|
||||
command(reg::SETCOMREVERSE);
|
||||
command(reg::DISPNORMAL);
|
||||
command(reg::SETSTARTLINE | 0x00); //Startline from 0x40-0x7F
|
||||
command(reg::POWERCTRL);
|
||||
command(reg::REG_RATIO | 4);
|
||||
command(reg::DISPON);
|
||||
command(reg::SETCONTRAST);
|
||||
command(30); // defalut contrast level
|
||||
}
|
||||
|
||||
if(bl != PIN_UNUSED) {
|
||||
set_backlight(255); // Turn backlight on now surprises have passed
|
||||
}
|
||||
}
|
||||
|
||||
void ST7567::command(uint8_t command, size_t len, const char *data) {
|
||||
gpio_put(cs, 0);
|
||||
|
||||
gpio_put(dc, 0); // command mode
|
||||
spi_write_blocking(spi, &command, 1);
|
||||
gpio_put(cs, 1);
|
||||
|
||||
sleep_us(100);
|
||||
if(data) {
|
||||
gpio_put(cs, 0);
|
||||
gpio_put(dc, 1); // data mode
|
||||
spi_write_blocking(spi, (const uint8_t*)data, len);
|
||||
gpio_put(cs, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Native 16-bit framebuffer update
|
||||
void ST7567::update(PicoGraphics *graphics) {
|
||||
uint8_t *fb = (uint8_t *)graphics->frame_buffer;
|
||||
uint8_t page_buffer[PAGESIZE];
|
||||
uint8_t page_byte_selector;
|
||||
uint8_t page_bit_selector;
|
||||
|
||||
for(uint8_t page=0; page < 8 ; page++) { //select page
|
||||
for(uint16_t pixel_index=0 ; pixel_index < (PAGESIZE * 8) ; pixel_index++) { //cycle through a page worth of bits from the fb
|
||||
page_byte_selector = ((pixel_index % 128));
|
||||
page_bit_selector = (pixel_index / 128);
|
||||
|
||||
if(*fb & (0b10000000 >> (pixel_index % 8))) { // check selected pixel is present
|
||||
page_buffer[page_byte_selector] |= (1 << page_bit_selector);
|
||||
}
|
||||
else {
|
||||
page_buffer[page_byte_selector] &= ~( 1 << page_bit_selector);
|
||||
}
|
||||
|
||||
if((pixel_index % 8) >= 7) { //increment fb pointer at end of byte
|
||||
fb++;
|
||||
}
|
||||
}
|
||||
|
||||
if(graphics->pen_type == PicoGraphics::PEN_1BIT) {
|
||||
command(reg::ENTER_RMWMODE);
|
||||
command(reg::SETPAGESTART | page);
|
||||
command(reg::SETCOLL);
|
||||
command(reg::SETCOLH);
|
||||
gpio_put(dc, 1); // data mode
|
||||
gpio_put(cs, 0);
|
||||
spi_write_blocking(spi, &page_buffer[0], PAGESIZE );
|
||||
gpio_put(cs, 1);
|
||||
gpio_put(dc, 0); // Back to command mode
|
||||
}
|
||||
else { //other pen types incompatable
|
||||
return;
|
||||
}
|
||||
}
|
||||
gpio_put(cs, 1);
|
||||
}
|
||||
|
||||
void ST7567::set_backlight(uint8_t brightness) {
|
||||
// gamma correct the provided 0-255 brightness value onto a
|
||||
// 0-65535 range for the pwm counter
|
||||
float gamma = 2.8;
|
||||
uint16_t value = (uint16_t)(pow((float)(brightness) / 255.0f, gamma) * 65535.0f + 0.5f);
|
||||
pwm_set_gpio_level(bl, value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
#pragma once
|
||||
|
||||
#include "hardware/spi.h"
|
||||
#include "hardware/pwm.h"
|
||||
#include "common/pimoroni_bus.hpp"
|
||||
#include "libraries/pico_graphics/pico_graphics.hpp"
|
||||
|
||||
namespace pimoroni {
|
||||
class ST7567 : public DisplayDriver {
|
||||
//--------------------------------------------------
|
||||
// Constants
|
||||
//--------------------------------------------------
|
||||
private:
|
||||
static const uint8_t ROWS = 64;
|
||||
static const uint8_t COLS = 128;
|
||||
static const uint8_t PAGESIZE = 128;
|
||||
|
||||
//--------------------------------------------------
|
||||
// Variables
|
||||
//--------------------------------------------------
|
||||
private:
|
||||
spi_inst_t *spi = spi0;
|
||||
|
||||
uint32_t dma_channel;
|
||||
|
||||
// interface pins with our standard defaults where appropriate
|
||||
uint cs;
|
||||
uint dc;
|
||||
uint sck;
|
||||
uint mosi;
|
||||
uint bl;
|
||||
uint reset_pin=21;
|
||||
|
||||
uint32_t spi_baud = 10000000; //10Mhz
|
||||
|
||||
uint8_t offset_cols = 0;
|
||||
uint8_t offset_rows = 0;
|
||||
|
||||
//--------------------------------------------------
|
||||
// Constructors/Destructor
|
||||
//--------------------------------------------------
|
||||
public:
|
||||
|
||||
ST7567(uint16_t width, uint16_t height, SPIPins pins) :
|
||||
DisplayDriver(width, height, ROTATE_0),
|
||||
spi(pins.spi), cs(pins.cs), dc(pins.dc), sck(pins.sck), mosi(pins.mosi), bl(pins.bl) {
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// Methods
|
||||
//--------------------------------------------------
|
||||
public:
|
||||
void update(PicoGraphics *graphics) override;
|
||||
void set_backlight(uint8_t brightness) override;
|
||||
void reset();
|
||||
|
||||
private:
|
||||
void init(bool auto_init_sequence = true);
|
||||
void command(uint8_t command, size_t len = 0, const char *data = NULL);
|
||||
};
|
||||
|
||||
}
|
|
@ -57,3 +57,4 @@ add_subdirectory(motor2040)
|
|||
add_subdirectory(inventor2040w)
|
||||
add_subdirectory(encoder)
|
||||
add_subdirectory(galactic_unicorn)
|
||||
add_subdirectory(gfx_pack)
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
set(OUTPUT_NAME gfx_pack_demo)
|
||||
|
||||
add_executable(
|
||||
${OUTPUT_NAME}
|
||||
gfx_demo.cpp
|
||||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(${OUTPUT_NAME} pico_stdlib gfx_pack)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(${OUTPUT_NAME})
|
|
@ -0,0 +1,124 @@
|
|||
#include "pico/stdlib.h"
|
||||
#include "libraries/pico_graphics/pico_graphics.hpp"
|
||||
#include "libraries/gfx_pack/gfx_pack.hpp"
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
ST7567 st7567(128, 64, GfxPack::gfx_pack_pins);
|
||||
PicoGraphics_Pen1Bit graphics(st7567.width, st7567.height, nullptr);
|
||||
RGBLED backlight_rgb(GfxPack::BL_R, GfxPack::BL_G, GfxPack::BL_B, Polarity::ACTIVE_HIGH);
|
||||
Button button_a(GfxPack::A);
|
||||
Button button_b(GfxPack::B);
|
||||
Button button_c(GfxPack::C);
|
||||
Button button_d(GfxPack::D);
|
||||
Button button_e(GfxPack::E);
|
||||
|
||||
// HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel
|
||||
// Outputs are rgb in the range 0-255 for each channel
|
||||
void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) {
|
||||
float i = floor(h * 6.0f);
|
||||
float f = h * 6.0f - i;
|
||||
v *= 255.0f;
|
||||
uint8_t p = v * (1.0f - s);
|
||||
uint8_t q = v * (1.0f - f * s);
|
||||
uint8_t t = v * (1.0f - (1.0f - f) * s);
|
||||
|
||||
switch (int(i) % 6) {
|
||||
case 0: r = v; g = t; b = p; break;
|
||||
case 1: r = q; g = v; b = p; break;
|
||||
case 2: r = p; g = v; b = t; break;
|
||||
case 3: r = p; g = q; b = v; break;
|
||||
case 4: r = t; g = p; b = v; break;
|
||||
case 5: r = v; g = p; b = q; break;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
sleep_ms(100);
|
||||
|
||||
st7567.set_backlight(64); // 0 to 255
|
||||
|
||||
struct pt {
|
||||
float x;
|
||||
float y;
|
||||
uint8_t r;
|
||||
float dx;
|
||||
float dy;
|
||||
uint16_t pen;
|
||||
};
|
||||
|
||||
std::vector<pt> shapes;
|
||||
for(int i = 0; i < 10; i++) {
|
||||
pt shape;
|
||||
shape.x = rand() % graphics.bounds.w;
|
||||
shape.y = rand() % graphics.bounds.h;
|
||||
shape.r = (rand() % 10) + 3;
|
||||
shape.dx = float(rand() % 255) / 64.0f;
|
||||
shape.dy = float(rand() % 255) / 64.0f;
|
||||
shape.pen = rand() % 14;
|
||||
shapes.push_back(shape);
|
||||
}
|
||||
|
||||
Point text_location(0, 0);
|
||||
|
||||
float hue = 0.0f;
|
||||
while(true) {
|
||||
if(button_a.raw()) {
|
||||
text_location.x -= 1;
|
||||
}
|
||||
if(button_b.raw()) {
|
||||
text_location.x += 1;
|
||||
}
|
||||
|
||||
if(button_c.raw()) {
|
||||
text_location.y -= 1;
|
||||
}
|
||||
if(button_d.raw()) {
|
||||
text_location.y += 1;
|
||||
}
|
||||
|
||||
if(button_e.raw()) {
|
||||
text_location.x = 0;
|
||||
text_location.y = 0;
|
||||
}
|
||||
|
||||
graphics.set_pen(0);
|
||||
graphics.clear();
|
||||
|
||||
for(auto &shape : shapes) {
|
||||
shape.x += shape.dx;
|
||||
shape.y += shape.dy;
|
||||
if((shape.x - shape.r) < 0) {
|
||||
shape.dx *= -1;
|
||||
shape.x = shape.r;
|
||||
}
|
||||
if((shape.x + shape.r) >= graphics.bounds.w) {
|
||||
shape.dx *= -1;
|
||||
shape.x = graphics.bounds.w - shape.r;
|
||||
}
|
||||
if((shape.y - shape.r) < 0) {
|
||||
shape.dy *= -1;
|
||||
shape.y = shape.r;
|
||||
}
|
||||
if((shape.y + shape.r) >= graphics.bounds.h) {
|
||||
shape.dy *= -1;
|
||||
shape.y = graphics.bounds.h - shape.r;
|
||||
}
|
||||
|
||||
graphics.set_pen(shape.pen);
|
||||
graphics.circle(Point(shape.x, shape.y), shape.r);
|
||||
|
||||
}
|
||||
|
||||
graphics.set_pen(15);
|
||||
graphics.text("Hello World", text_location, 320);
|
||||
|
||||
// update screen
|
||||
backlight_rgb.set_hsv(hue, 1.0f, 1.0f);
|
||||
hue += 0.002;
|
||||
st7567.update(&graphics);
|
||||
sleep_ms(1000/15);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -37,3 +37,4 @@ add_subdirectory(adcfft)
|
|||
add_subdirectory(jpegdec)
|
||||
add_subdirectory(inky_frame)
|
||||
add_subdirectory(galactic_unicorn)
|
||||
add_subdirectory(gfx_pack)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
include(gfx_pack.cmake)
|
|
@ -0,0 +1,88 @@
|
|||
# Pico GFX Pack (C++) <!-- omit in toc -->
|
||||
|
||||
This library offers convenient functions for interacting with [Pico GFX Pack](https://shop.pimoroni.com/products/gfxpack) - The Pico GFX Pack adds a 128x64 LCD Matrix display to your headered Raspberry Pi Pico or PicoW, with RGBW backlight and 5 input buttons for all your display and control needs.
|
||||
|
||||
- [Example Program](#example-program)
|
||||
- [Function Reference](#function-reference)
|
||||
- [PicoGraphics](#picographics)
|
||||
- [ST7789](#st7789)
|
||||
|
||||
## Example Program
|
||||
|
||||
The following example sets up Pico Display, displays some basic demo text and graphics and will illuminate the backlight green if the A button is pressed.
|
||||
|
||||
```c++
|
||||
#include "gfx_pack.hpp"
|
||||
#include "drivers/st7567/st7576.hpp"
|
||||
#include "libraries/pico_graphics/pico_graphics.hpp"
|
||||
#include "rgbled.hpp"
|
||||
#include "button.hpp"
|
||||
|
||||
// Display driver
|
||||
ST7567 st7567(128, 64, GfxPack::gfx_pack_pins);
|
||||
|
||||
// Graphics library - in 1 Bit mode you get 16 shades with dithering.
|
||||
PicoGraphics_Pen1Bit graphics(st7567.width, st7567.height, nullptr);
|
||||
|
||||
// RGB backlight elements
|
||||
RGBLED backlight_rgb(GfxPack::BL_R, GfxPack::BL_G, GfxPack::BL_B, Polarity::ACTIVE_HIGH);
|
||||
|
||||
// And each button
|
||||
Button button_a(GfxPack::A);
|
||||
Button button_b(GfxPack::B);
|
||||
Button button_c(GfxPack::C);
|
||||
Button button_d(GfxPack::D);
|
||||
Button button_e(GfxPack::E);
|
||||
|
||||
|
||||
// RGB LED
|
||||
RGBLED led(GfxPack::LED_R, GfxPack::LED_G, GfxPack::LED_B);
|
||||
|
||||
int main() {
|
||||
|
||||
// set the backlight to a value between 0 and 255
|
||||
// This controls the white elements of the RGBW backlight
|
||||
st7567.set_backlight(100);
|
||||
|
||||
while(true) {
|
||||
// detect if the A button is pressed (could be A, B, C, D or E)
|
||||
if(button_a.raw(display.A)) {
|
||||
// make the LCD glow green
|
||||
// parameters are red, green, blue all between 0 and 255
|
||||
// these are also gamma corrected
|
||||
backlight_rgb.set_rgb(0, 255, 0);
|
||||
}
|
||||
|
||||
// set the colour of the pen
|
||||
// parameters are red, green, blue all between 0 and 255
|
||||
graphics.set_pen(30, 40, 50);
|
||||
|
||||
// fill the screen with the current pen colour
|
||||
graphics.clear();
|
||||
|
||||
// draw a box to put some text in
|
||||
graphics.set_pen(10, 20, 30);
|
||||
Rect text_rect(10, 10, 150, 150);
|
||||
graphics.rectangle(text_rect);
|
||||
|
||||
// write some text inside the box with 10 pixels of margin
|
||||
// automatically word wrapping
|
||||
text_rect.deflate(10);
|
||||
graphics.set_pen(110, 120, 130);
|
||||
graphics.text("This is a message", Point(text_rect.x, text_rect.y), text_rect.w);
|
||||
|
||||
// now we've done our drawing let's update the screen
|
||||
st7567.update(&graphics);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Function Reference
|
||||
|
||||
### PicoGraphics
|
||||
|
||||
Pico GFX Pack uses our Pico Graphics library to draw graphics and text. For more information [read the Pico Graphics function reference.](../pico_graphics/README.md#function-reference).
|
||||
|
||||
### ST7567
|
||||
|
||||
Pico Display uses the ST7567 display driver to handle the LCD. For more information [read the ST7567 README.](../../drivers/st7789/README.md).
|
|
@ -0,0 +1,7 @@
|
|||
set(LIB_NAME gfx_pack)
|
||||
add_library(${LIB_NAME} INTERFACE)
|
||||
|
||||
target_include_directories(${LIB_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(${LIB_NAME} INTERFACE pico_stdlib st7567 button rgbled)
|
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include "drivers/st7567/st7567.hpp"
|
||||
#include "drivers/button/button.hpp"
|
||||
#include "drivers/rgbled/rgbled.hpp"
|
||||
|
||||
namespace pimoroni {
|
||||
|
||||
namespace GfxPack{
|
||||
static const SPIPins gfx_pack_pins = {PIMORONI_SPI_DEFAULT_INSTANCE, 17, SPI_DEFAULT_SCK, SPI_DEFAULT_MOSI, PIN_UNUSED, 20, 9};
|
||||
static const int WIDTH = 128;
|
||||
static const int HEIGHT = 64;
|
||||
static const uint8_t A = 12;
|
||||
static const uint8_t B = 13;
|
||||
static const uint8_t C = 14;
|
||||
static const uint8_t D = 15;
|
||||
static const uint8_t E = 22;
|
||||
static const uint8_t BL_R = 6;
|
||||
static const uint8_t BL_G = 7;
|
||||
static const uint8_t BL_B = 8;
|
||||
static const uint8_t BL_W = 9;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
import time
|
||||
import random
|
||||
from gfx_pack import GfxPack
|
||||
|
||||
"""
|
||||
Bouncing Ball demo
|
||||
10 balls of different shades will be bouncing around your display.
|
||||
Funky...
|
||||
"""
|
||||
|
||||
gp = GfxPack()
|
||||
gp.set_backlight(0, 0, 0, 255)
|
||||
display = gp.display
|
||||
|
||||
WIDTH, HEIGHT = display.get_bounds()
|
||||
|
||||
|
||||
class Ball:
|
||||
def __init__(self, x, y, r, dx, dy, pen):
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.r = r
|
||||
self.dx = dx
|
||||
self.dy = dy
|
||||
self.pen = pen
|
||||
|
||||
|
||||
# initialise shapes
|
||||
balls = []
|
||||
for i in range(0, 10):
|
||||
r = random.randint(0, 10) + 3
|
||||
balls.append(
|
||||
Ball(
|
||||
random.randint(r, r + (WIDTH - 2 * r)),
|
||||
random.randint(r, r + (HEIGHT - 2 * r)),
|
||||
r,
|
||||
(14 - r) / 2,
|
||||
(14 - r) / 2,
|
||||
random.randint(0, 15),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
while True:
|
||||
display.set_pen(0)
|
||||
display.clear()
|
||||
|
||||
for ball in balls:
|
||||
ball.x += ball.dx
|
||||
ball.y += ball.dy
|
||||
|
||||
xmax = WIDTH - ball.r
|
||||
xmin = ball.r
|
||||
ymax = HEIGHT - ball.r
|
||||
ymin = ball.r
|
||||
|
||||
if ball.x < xmin or ball.x > xmax:
|
||||
ball.dx *= -1
|
||||
|
||||
if ball.y < ymin or ball.y > ymax:
|
||||
ball.dy *= -1
|
||||
|
||||
display.set_pen(ball.pen)
|
||||
display.circle(int(ball.x), int(ball.y), int(ball.r))
|
||||
|
||||
display.update()
|
||||
time.sleep(0.05)
|
|
@ -0,0 +1,71 @@
|
|||
# This example borrows a CircuitPython hsv_to_rgb function to cycle through some rainbows on GFX Pack's screen.
|
||||
# If you're into rainbows, HSV (Hue, Saturation, Value) is very useful!
|
||||
|
||||
import time
|
||||
from gfx_pack import GfxPack
|
||||
|
||||
gp = GfxPack()
|
||||
display = gp.display
|
||||
|
||||
WIDTH, HEIGHT = display.get_bounds()
|
||||
display.set_backlight(0) # turn off the white component of the backlight
|
||||
|
||||
DANCE_TIME = 1.0
|
||||
|
||||
|
||||
# From CPython Lib/colorsys.py
|
||||
def hsv_to_rgb(h, s, v):
|
||||
if s == 0.0:
|
||||
return v, v, v
|
||||
i = int(h * 6.0)
|
||||
f = (h * 6.0) - i
|
||||
p = v * (1.0 - s)
|
||||
q = v * (1.0 - s * f)
|
||||
t = v * (1.0 - s * (1.0 - f))
|
||||
i = i % 6
|
||||
if i == 0:
|
||||
return v, t, p
|
||||
if i == 1:
|
||||
return q, v, p
|
||||
if i == 2:
|
||||
return p, v, t
|
||||
if i == 3:
|
||||
return p, q, v
|
||||
if i == 4:
|
||||
return t, p, v
|
||||
if i == 5:
|
||||
return v, p, q
|
||||
|
||||
|
||||
# some variables to keep track of rainbows and dancing
|
||||
h = 0
|
||||
dancing = True
|
||||
last_time = time.ticks_ms()
|
||||
|
||||
display.set_font("bitmap8")
|
||||
|
||||
while True:
|
||||
time_ms = time.ticks_ms()
|
||||
|
||||
h += 1
|
||||
r, g, b = [int(255 * c) for c in hsv_to_rgb(h / 360.0, 1.0, 1.0)] # rainbow magic
|
||||
gp.set_backlight(r, g, b) # Set backlight to a converted HSV value
|
||||
display.set_pen(0) # Set pen to white
|
||||
display.clear()
|
||||
display.set_pen(15) # Set pen to black
|
||||
# draw text and mans
|
||||
if dancing:
|
||||
display.text("pico!", 9, 5, WIDTH, 2)
|
||||
display.text("\\o\\ \\o\\ \\o\\ ", 7, 25, WIDTH, 2)
|
||||
display.text("\\o\\ \\o\\ \\o\\ ", 7, 45, WIDTH, 2)
|
||||
else:
|
||||
display.text("disco!", 69, 5, WIDTH, 2)
|
||||
display.text("/o/ /o/ /o/ ", 21, 25, WIDTH, 2)
|
||||
display.text("/o/ /o/ /o/ ", 21, 45, WIDTH, 2)
|
||||
# our main loop is faster than our dancing loop
|
||||
# this 'if' checks when it's time to dance
|
||||
if time_ms - last_time > DANCE_TIME * 1000:
|
||||
dancing = not dancing
|
||||
last_time = time_ms
|
||||
display.update()
|
||||
time.sleep(1.0 / 60)
|
|
@ -0,0 +1,153 @@
|
|||
import time
|
||||
import random
|
||||
from gfx_pack import GfxPack, SWITCH_A, SWITCH_B, SWITCH_C, SWITCH_D, SWITCH_E
|
||||
|
||||
"""
|
||||
Basic Snake demo for GFX Pack
|
||||
Feel free to add your own improvements :)
|
||||
|
||||
A = up
|
||||
B = down
|
||||
C = reset
|
||||
D = left
|
||||
E = right
|
||||
"""
|
||||
# Constants for next move state
|
||||
MOVE_UP = 0
|
||||
MOVE_DOWN = 1
|
||||
MOVE_LEFT = 2
|
||||
MOVE_RIGHT = 3
|
||||
# In-game variables
|
||||
next_move = MOVE_RIGHT
|
||||
score = 0
|
||||
head_position = (30, 30)
|
||||
segments = [head_position]
|
||||
ate_apple = False
|
||||
apple_position = None
|
||||
|
||||
gp = GfxPack()
|
||||
gp.set_backlight(0, 0, 0, 255)
|
||||
display = gp.display
|
||||
|
||||
WIDTH, HEIGHT = display.get_bounds()
|
||||
|
||||
|
||||
# Draw the apple in a random possition within the play field
|
||||
def set_new_apple():
|
||||
global apple_position
|
||||
apple_position = random.randint(0, WIDTH), random.randint(30, HEIGHT)
|
||||
|
||||
|
||||
# Reset game to start position and score
|
||||
def game_over():
|
||||
global score, segments, head_position, ate_apple
|
||||
score = 0
|
||||
head_position = (30, 30)
|
||||
segments = [head_position]
|
||||
ate_apple = False
|
||||
set_new_apple()
|
||||
pass
|
||||
|
||||
|
||||
# Poll all the butttons to see if anything has been pressed and change next direction accoringly
|
||||
def check_button():
|
||||
global next_move, ate_apple
|
||||
if gp.switch_pressed(SWITCH_A):
|
||||
if next_move != MOVE_DOWN:
|
||||
next_move = MOVE_UP
|
||||
elif gp.switch_pressed(SWITCH_B):
|
||||
if next_move != MOVE_UP:
|
||||
next_move = MOVE_DOWN
|
||||
elif gp.switch_pressed(SWITCH_D):
|
||||
if next_move != MOVE_RIGHT:
|
||||
next_move = MOVE_LEFT
|
||||
elif gp.switch_pressed(SWITCH_E):
|
||||
if next_move != MOVE_LEFT:
|
||||
next_move = MOVE_RIGHT
|
||||
elif gp.switch_pressed(SWITCH_C):
|
||||
game_over()
|
||||
|
||||
|
||||
# If the snake head and apple are on the same pixel the apple has been eaten
|
||||
def check_eaten():
|
||||
global ate_apple, head_position, apple_position, score
|
||||
if head_position == apple_position:
|
||||
ate_apple = True
|
||||
score += 1
|
||||
set_new_apple()
|
||||
|
||||
|
||||
def check_collision():
|
||||
# Check if the head or any of the tail segments are on the same pixel
|
||||
for index in range(len(segments) - 1):
|
||||
if head_position == segments[index]:
|
||||
game_over()
|
||||
return
|
||||
# Check the snake head has not gone beyond the play area
|
||||
if head_position[0] >= WIDTH:
|
||||
game_over()
|
||||
if head_position[0] <= 0:
|
||||
game_over()
|
||||
if head_position[1] >= HEIGHT:
|
||||
game_over()
|
||||
if head_position[1] <= 20:
|
||||
game_over()
|
||||
|
||||
|
||||
def move():
|
||||
global head_position, segments, ate_apple
|
||||
|
||||
head_x, head_y = head_position
|
||||
|
||||
if next_move == MOVE_UP:
|
||||
head_y -= 1
|
||||
elif next_move == MOVE_DOWN:
|
||||
head_y += 1
|
||||
elif next_move == MOVE_LEFT:
|
||||
head_x -= 1
|
||||
elif next_move == MOVE_RIGHT:
|
||||
head_x += 1
|
||||
|
||||
head_position = (head_x, head_y)
|
||||
# Add head to body segments
|
||||
segments.append(head_position)
|
||||
|
||||
# I there is no apple remove end of the tail otherwise tail grows by 1
|
||||
if ate_apple:
|
||||
ate_apple = False
|
||||
else:
|
||||
segments.pop(0)
|
||||
|
||||
|
||||
def draw():
|
||||
display.set_pen(0)
|
||||
display.clear()
|
||||
display.set_pen(15)
|
||||
# Draw play field including score
|
||||
display.text("score: {0}".format(score), 0, 0)
|
||||
display.line(0, 20, 127, 20)
|
||||
display.line(0, 63, 127, 63)
|
||||
display.line(0, 63, 0, 20)
|
||||
display.line(128, 63, 127, 20)
|
||||
# Draw apple
|
||||
display.pixel(apple_position[0], apple_position[1])
|
||||
|
||||
# Drawing snake
|
||||
for segment in segments:
|
||||
display.pixel(segment[0], segment[1])
|
||||
|
||||
display.update()
|
||||
|
||||
|
||||
# Make sure game is reset to begin with
|
||||
game_over()
|
||||
|
||||
while True:
|
||||
# Game logic
|
||||
check_button()
|
||||
check_eaten()
|
||||
move()
|
||||
check_collision()
|
||||
draw()
|
||||
|
||||
time.sleep(0.2)
|
|
@ -0,0 +1,72 @@
|
|||
import time
|
||||
import machine
|
||||
from gfx_pack import GfxPack
|
||||
from breakout_bme68x import BreakoutBME68X, STATUS_HEATER_STABLE
|
||||
|
||||
"""
|
||||
GFX temp DEMO
|
||||
|
||||
This demo uses a BME680 or BME688 attached to the QWST connector to
|
||||
measure temperature, pressure, and humidity and display it on the GFX display,
|
||||
or the internal temperature sensor can be used in place of the
|
||||
BME68x breakout. Just change use_bme68x_breakout to False
|
||||
"""
|
||||
|
||||
# Settings
|
||||
lower_temp_bound = 15
|
||||
upper_temp_bound = 30
|
||||
use_bme68x_breakout = True
|
||||
|
||||
sensor_temp = machine.ADC(4)
|
||||
conversion_factor = 3.3 / (65535) # used for calculating a temperature from the raw sensor reading
|
||||
|
||||
gp = GfxPack()
|
||||
gp.set_backlight(0, 0, 0) # turn the RGB backlight off
|
||||
display = gp.display
|
||||
display.set_backlight(0.4) # set the white to a low value
|
||||
|
||||
if use_bme68x_breakout:
|
||||
bmp = BreakoutBME68X(gp.i2c)
|
||||
|
||||
display.set_pen(0)
|
||||
display.clear()
|
||||
display.set_font("bitmap14_outline")
|
||||
|
||||
while True:
|
||||
# Clear display
|
||||
display.set_pen(0)
|
||||
display.clear()
|
||||
|
||||
display.set_pen(15)
|
||||
display.text("GFXPack Temp demo", 0, 0, scale=0.1)
|
||||
|
||||
if use_bme68x_breakout:
|
||||
temperature, pressure, humidity, gas, status, _, _ = bmp.read()
|
||||
display.text("Temp: {:0.2f}c".format(temperature), 0, 20, scale=0.2)
|
||||
display.text("Press: {:0.2f}Pa".format(pressure), 0, 35, scale=0.2)
|
||||
display.text("Humid: {:0.2f}%".format(humidity), 0, 50, scale=0.2)
|
||||
|
||||
heater = "Stable" if status & STATUS_HEATER_STABLE else "Unstable"
|
||||
print("{:0.2f}c, {:0.2f}Pa, {:0.2f}%, {:0.2f} Ohms, Heater: {}".format(
|
||||
temperature, pressure, humidity, gas, heater))
|
||||
|
||||
else:
|
||||
reading = sensor_temp.read_u16() * conversion_factor
|
||||
temperature = 27 - (reading - 0.706) / 0.001721
|
||||
display.text("Temperature", 25, 15, scale=0.2)
|
||||
display.text("{:0.2f}c".format(temperature), 25, 30, scale=2)
|
||||
|
||||
if temperature < lower_temp_bound:
|
||||
r = 0
|
||||
b = 255
|
||||
elif temperature > upper_temp_bound:
|
||||
r = 255
|
||||
b = 0
|
||||
else:
|
||||
r = (temperature - lower_temp_bound) / (upper_temp_bound - lower_temp_bound) * 255
|
||||
b = 255 - ((temperature - lower_temp_bound) / (upper_temp_bound - lower_temp_bound) * 255)
|
||||
|
||||
gp.set_backlight(r, 0, b)
|
||||
display.update()
|
||||
|
||||
time.sleep(0.2)
|
|
@ -63,6 +63,7 @@ Bear in mind that MicroPython has only 192K of RAM available- a 320x240 pixel di
|
|||
* 128x128 I2C OLED - `DISPLAY_I2C_OLED_128X128`
|
||||
* Pico Inky Pack - 296x128 mono e-ink - `DISPLAY_INKY_PACK`
|
||||
* Inky Frame - 600x447 7-colour e-ink - `DISPLAY_INKY_FRAME`
|
||||
* Pico GFX Pack - 128x64 mono LCD Matrix - `DISPLAY_GFX_PACK`
|
||||
* Galactic Unicorn - 53x11 LED Matrix - `DISPLAY_GALACTIC_UNICORN`
|
||||
|
||||
### Supported Graphics Modes (Pen Type)
|
||||
|
|
|
@ -10,6 +10,7 @@ target_sources(usermod_${MOD_NAME} INTERFACE
|
|||
${CMAKE_CURRENT_LIST_DIR}/../../../drivers/sh1107/sh1107.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../../drivers/uc8151/uc8151.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../../drivers/uc8159/uc8159.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../../drivers/st7567/st7567.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../../libraries/pico_graphics/pico_graphics.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../../libraries/pico_graphics/pico_graphics_pen_1bit.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../../libraries/pico_graphics/pico_graphics_pen_1bitY.cpp
|
||||
|
|
|
@ -126,6 +126,7 @@ STATIC const mp_map_elem_t picographics_globals_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_INKY_FRAME), MP_ROM_INT(DISPLAY_INKY_FRAME) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_INKY_FRAME_4), MP_ROM_INT(DISPLAY_INKY_FRAME_4) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_GALACTIC_UNICORN), MP_ROM_INT(DISPLAY_GALACTIC_UNICORN) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_GFX_PACK), MP_ROM_INT(DISPLAY_GFX_PACK) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_PEN_1BIT), MP_ROM_INT(PEN_1BIT) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_PEN_P4), MP_ROM_INT(PEN_P4) },
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "drivers/sh1107/sh1107.hpp"
|
||||
#include "drivers/uc8151/uc8151.hpp"
|
||||
#include "drivers/uc8159/uc8159.hpp"
|
||||
#include "drivers/st7567/st7567.hpp"
|
||||
#include "libraries/pico_graphics/pico_graphics.hpp"
|
||||
#include "common/pimoroni_common.hpp"
|
||||
#include "common/pimoroni_bus.hpp"
|
||||
|
@ -120,6 +121,13 @@ bool get_display_settings(PicoGraphicsDisplay display, int &width, int &height,
|
|||
if(rotate == -1) rotate = (int)Rotation::ROTATE_0;
|
||||
if(pen_type == -1) pen_type = PEN_RGB888;
|
||||
break;
|
||||
case DISPLAY_GFX_PACK:
|
||||
width = 128;
|
||||
height = 64;
|
||||
bus_type = BUS_SPI;
|
||||
if(rotate == -1) rotate = (int)Rotation::ROTATE_0;
|
||||
if(pen_type == -1) pen_type = PEN_1BIT;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -178,7 +186,7 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size
|
|||
PicoGraphicsBusType bus_type = BUS_SPI;
|
||||
if(!get_display_settings(display, width, height, rotate, pen_type, bus_type)) mp_raise_ValueError("Unsupported display!");
|
||||
if(rotate == -1) rotate = (int)Rotation::ROTATE_0;
|
||||
|
||||
|
||||
pimoroni::SPIPins spi_bus = get_spi_pins(BG_SPI_FRONT);
|
||||
pimoroni::ParallelPins parallel_bus = {10, 11, 12, 13, 14, 2}; // Default for Tufty 2040 parallel
|
||||
pimoroni::I2C *i2c_bus = nullptr;
|
||||
|
@ -208,6 +216,8 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size
|
|||
spi_bus = {PIMORONI_SPI_DEFAULT_INSTANCE, SPI_BG_FRONT_CS, SPI_DEFAULT_SCK, SPI_DEFAULT_MOSI, PIN_UNUSED, 28, PIN_UNUSED};
|
||||
} else if (display == DISPLAY_INKY_PACK) {
|
||||
spi_bus = {PIMORONI_SPI_DEFAULT_INSTANCE, SPI_BG_FRONT_CS, SPI_DEFAULT_SCK, SPI_DEFAULT_MOSI, PIN_UNUSED, 20, PIN_UNUSED};
|
||||
} else if (display == DISPLAY_GFX_PACK) {
|
||||
spi_bus = {PIMORONI_SPI_DEFAULT_INSTANCE, 17, SPI_DEFAULT_SCK, SPI_DEFAULT_MOSI, PIN_UNUSED, 20, 9};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -235,8 +245,11 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size
|
|||
|
||||
} else if (display == DISPLAY_GALACTIC_UNICORN) {
|
||||
self->display = m_new_class(DisplayDriver, width, height, (Rotation)rotate);
|
||||
}
|
||||
else {
|
||||
|
||||
} else if (display == DISPLAY_GFX_PACK) {
|
||||
self->display = m_new_class(ST7567, width, height, spi_bus);
|
||||
|
||||
} else {
|
||||
self->display = m_new_class(ST7789, width, height, (Rotation)rotate, round, spi_bus);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,8 @@ enum PicoGraphicsDisplay {
|
|||
DISPLAY_INKY_PACK,
|
||||
DISPLAY_INKY_FRAME,
|
||||
DISPLAY_INKY_FRAME_4,
|
||||
DISPLAY_GALACTIC_UNICORN
|
||||
DISPLAY_GALACTIC_UNICORN,
|
||||
DISPLAY_GFX_PACK
|
||||
};
|
||||
|
||||
enum PicoGraphicsPenType {
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
# Pico GFX Pack (MicroPython) <!-- omit in toc -->
|
||||
|
||||
This library offers convenient functions for interacting with [Pico GFX Pack](https://shop.pimoroni.com/products/gfxpack) - The Pico GFX Pack adds a 128x64 LCD Matrix display to your headered Raspberry Pi Pico or PicoW, with RGBW backlight and 5 input buttons for all your display and control needs.
|
||||
|
||||
## Table of Content
|
||||
- [Table of Content](#table-of-content)
|
||||
- [GFX Pack Class](#gfx-pack-class)
|
||||
- [Switches](#switches)
|
||||
- [RGBW Backlight](#rgbw-backlight)
|
||||
- [Display](#display)
|
||||
- [Backlight](#backlight)
|
||||
|
||||
|
||||
## GFX Pack Class
|
||||
|
||||
The `GfxPack` class deals with RGBW backlight and buttons on the GFX Pack. To create one, import the `gfx_pack` module, then define a new `board` variable:
|
||||
|
||||
```python
|
||||
import gfx_pack
|
||||
|
||||
board = gfx_pack.GfxPack()
|
||||
```
|
||||
|
||||
From here, all features can be accessed by calling functions on `board`. In addition, when using Qwiic / Stemma QT devices, the I2C channel to use can be accessed with `board.i2c`.
|
||||
|
||||
### Switches
|
||||
|
||||
GFX Pack has five switches just below the display. To read one of the switches, call `.switch_pressed(switch)`, where `switch` is a value from `0` to `.NUM_SWITCHES - 1`. This returns `True` when the specified switch is pressed, and `False` otherwise.
|
||||
|
||||
To read a specific input, the `gfx_pack` module contains these handy constants:
|
||||
|
||||
* `SWITCH_A` = `0`
|
||||
* `SWITCH_B` = `1`
|
||||
* `SWITCH_C` = `2`
|
||||
* `SWITCH_D` = `3`
|
||||
* `SWITCH_E` = `4`
|
||||
|
||||
```python
|
||||
if board.switch_pressed(SWITCH_A):
|
||||
# Do something interesting here!
|
||||
|
||||
if board.switch_pressed(SWITCH_B):
|
||||
# Do something else even more interesting here!
|
||||
```
|
||||
|
||||
|
||||
### RGBW Backlight
|
||||
|
||||
The GFX has an RGB backlight as well as the regular Matrix display backlight to change the colour of the backlight. This is accessed via the following method.
|
||||
|
||||
|
||||
`.set_backlight(r, g, b, w=None)`
|
||||
|
||||
Where r, g, b and w are values between 0 and 255
|
||||
|
||||
|
||||
example:
|
||||
|
||||
```python
|
||||
board.set_backlight(255, 0, 0) # Makes the Backlight Red
|
||||
board.set_backlight(0, 255, 0) # Makes the Backlight Blue
|
||||
board.set_backlight(0, 0, 255) # Makes the Backlight Green
|
||||
board.set_backlight(0, 0, 0, 255) # Makes the Backlight White
|
||||
```
|
||||
|
||||
## Display
|
||||
|
||||
The display is all handled by our custom picographics drivers the can be accessed via `.display`.
|
||||
|
||||
example:
|
||||
|
||||
```python
|
||||
display = board.display
|
||||
display.text("Hello World!", 0, 0)
|
||||
display.line(0, 0, 128, 64)
|
||||
display.update() # Update display with the above items
|
||||
```
|
||||
All the picographics functions can be found [Here](../modules/picographics/README.md)
|
||||
|
||||
### Backlight
|
||||
|
||||
Included in the picographics display drivers is a function for controling the displays white backlight only which is accessed via `.set_backlight()`.
|
||||
|
||||
This function takes a floating point value between `0.0` and `1.0`
|
||||
|
||||
```python
|
||||
display = board.display
|
||||
display.set_backlight(0.0) # Backlight is off
|
||||
display.set_backlight(0.5) # Backlight is 50%
|
||||
display.set_backlight(1.0) # Backlight is 100%
|
||||
```
|
|
@ -0,0 +1,45 @@
|
|||
from pimoroni import RGBLED, Button
|
||||
from picographics import PicoGraphics, DISPLAY_GFX_PACK
|
||||
from pimoroni_i2c import PimoroniI2C
|
||||
|
||||
# Index Constants
|
||||
SWITCH_A = 0
|
||||
SWITCH_B = 1
|
||||
SWITCH_C = 2
|
||||
SWITCH_D = 3
|
||||
SWITCH_E = 4
|
||||
|
||||
|
||||
class GfxPack:
|
||||
I2C_SDA_PIN = 4
|
||||
I2C_SCL_PIN = 5
|
||||
SWITCH_PINS = (12, 13, 14, 15, 22)
|
||||
LED_R_PIN = 6
|
||||
LED_G_PIN = 7
|
||||
LED_B_PIN = 8
|
||||
|
||||
# Count Constants
|
||||
NUM_SWITCHES = 5
|
||||
|
||||
def __init__(self):
|
||||
self.display = PicoGraphics(display=DISPLAY_GFX_PACK)
|
||||
|
||||
# Set up the user switches
|
||||
self.__switches = []
|
||||
for i in range(self.NUM_SWITCHES):
|
||||
self.__switches.append(Button(self.SWITCH_PINS[i]))
|
||||
|
||||
self.__rgb = RGBLED(GfxPack.LED_R_PIN, GfxPack.LED_G_PIN, GfxPack.LED_B_PIN, invert=False)
|
||||
|
||||
# Set up the i2c for Qw/st and Breakout Garden
|
||||
self.i2c = PimoroniI2C(self.I2C_SDA_PIN, self.I2C_SCL_PIN, 100000)
|
||||
|
||||
def switch_pressed(self, switch):
|
||||
if switch < 0 or switch >= self.NUM_SWITCHES:
|
||||
raise ValueError("switch out of range. Expected SWITCH_A (0), SWITCH_B (1), SWITCH_C (2), SWITCH_D (3), or SWITCH_E (4)")
|
||||
return self.__switches[switch].is_pressed
|
||||
|
||||
def set_backlight(self, r, g, b, w=None):
|
||||
self.__rgb.set_rgb(r, g, b)
|
||||
if w is not None:
|
||||
self.display.set_backlight(w / 255)
|
|
@ -18,7 +18,7 @@ target_link_libraries(usermod INTERFACE usermod_modules_py)
|
|||
# .py files to copy from modules_py to ports/rp2/modules
|
||||
#copy_module(usermod_modules_py ${CMAKE_CURRENT_LIST_DIR}/picosystem.py picosystem)
|
||||
copy_module(usermod_modules_py ${CMAKE_CURRENT_LIST_DIR}/pimoroni.py pimoroni)
|
||||
|
||||
copy_module(usermod_modules_py ${CMAKE_CURRENT_LIST_DIR}/gfx_pack.py gfx_pack)
|
||||
if(PICO_BOARD STREQUAL "pico_w")
|
||||
copy_module(usermod_modules_py ${CMAKE_CURRENT_LIST_DIR}/automation.py automation)
|
||||
copy_module(usermod_modules_py ${CMAKE_CURRENT_LIST_DIR}/inventor.py inventor)
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue