Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Pico Display Pack 2.8 and fix SPI for st7789 on Pico2 #1006

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion drivers/st7789/st7789.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,13 @@ namespace pimoroni {

// The ST7789 requires 16 ns between SPI rising edges.
// 16 ns = 62,500,000 Hz
static const uint32_t SPI_BAUD = 62'500'000;
// 2350 doesn't support 62,500,000 so use 75,000,000 seems to work.
#if !PICO_RP2350
static const uint32_t SPI_BAUD = 62'500'000;
#else
static const uint32_t SPI_BAUD = 75'000'000;
#endif



public:
Expand Down
1 change: 1 addition & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ add_subdirectory(breakout_mlx90640)

add_subdirectory(pico_display)
add_subdirectory(pico_display_2)
add_subdirectory(pico_display_28)
add_subdirectory(pico_unicorn)
add_subdirectory(pico_unicorn_plasma)
add_subdirectory(pico_scroll)
Expand Down
12 changes: 12 additions & 0 deletions examples/pico_display_28/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
set(OUTPUT_NAME pico_display28_demo)

add_executable(
${OUTPUT_NAME}
pico_display_28_demo.cpp
)

# Pull in pico libraries that we need
target_link_libraries(${OUTPUT_NAME} pico_stdlib hardware_spi hardware_pwm hardware_dma rgbled button pico_display_28 st7789 pico_graphics)

# create map/bin/hex file etc.
pico_add_extra_outputs(${OUTPUT_NAME})
123 changes: 123 additions & 0 deletions examples/pico_display_28/pico_display_28_demo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#include <string.h>
#include <math.h>
#include <vector>
#include <cstdlib>

#include "libraries/pico_display_28/pico_display_28.hpp"
#include "drivers/st7789/st7789.hpp"
#include "libraries/pico_graphics/pico_graphics.hpp"
#include "rgbled.hpp"
#include "button.hpp"

using namespace pimoroni;

ST7789 st7789(320, 240, ROTATE_0, false, get_spi_pins(BG_SPI_FRONT));
PicoGraphics_PenRGB332 graphics(st7789.width, st7789.height, nullptr);

RGBLED led(PicoDisplay28::LED_R, PicoDisplay28::LED_G, PicoDisplay28::LED_B);

Button button_a(PicoDisplay28::A);
Button button_b(PicoDisplay28::B);
Button button_x(PicoDisplay28::X);
Button button_y(PicoDisplay28::Y);

int main() {
char fpsbuf[512]; // Make sure buffer don't overflow
int frame_counter; // Counter for number of frames displayed
uint64_t start, elapsed; // Microsecond timers
float fps; // Frames per second to display

frame_counter = 0;

st7789.set_backlight(255);
led.set_rgb(0, 0, 0);

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 < 100; 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 = graphics.create_pen(rand() % 255, rand() % 255, rand() % 255);
shapes.push_back(shape);
}

Point text_location(0, 0);

Pen BG = graphics.create_pen(120, 40, 60);
Pen WHITE = graphics.create_pen(255, 255, 255);

start = time_us_64();
// Get the start time

while(true) {
if(button_a.raw()) text_location.x -= 1;
if(button_b.raw()) text_location.x += 1;

if(button_x.raw()) text_location.y -= 1;
if(button_y.raw()) text_location.y += 1;

graphics.set_pen(BG);
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);

}

// Since HSV takes a float from 0.0 to 1.0 indicating hue,
// then we can divide millis by the number of milliseconds
// we want a full colour cycle to take. 5000 = 5 sec
RGB p = RGB::from_hsv((float)millis() / 5000.0f, 1.0f, 0.5f + sinf(millis() / 100.0f / 3.14159f) * 0.5f);

led.set_rgb(p.r, p.g, p.b);

frame_counter++;

elapsed = time_us_64();
// Get the current time to calculate the elapsed time next
fps = (frame_counter / float(elapsed - start)) * 1000000;
sprintf(fpsbuf, "Frame = %d, FPS = %5.2f", frame_counter, fps);
// Create output text

graphics.set_pen(WHITE);
graphics.text(fpsbuf, text_location, 320, 2);
// Render Frame counter and FPS to screen

// update screen
st7789.update(&graphics);
}

return 0;
}
1 change: 1 addition & 0 deletions libraries/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ add_subdirectory(breakout_bh1745)
add_subdirectory(pico_graphics)
add_subdirectory(pico_display)
add_subdirectory(pico_display_2)
add_subdirectory(pico_display_28)
add_subdirectory(pico_unicorn)
add_subdirectory(pico_scroll)
add_subdirectory(pico_explorer)
Expand Down
11 changes: 11 additions & 0 deletions libraries/pico_display_28/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
set(LIB_NAME pico_display_28)
add_library(${LIB_NAME} INTERFACE)

target_sources(${LIB_NAME} INTERFACE
${CMAKE_CURRENT_LIST_DIR}/${LIB_NAME}.cpp
)

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 hardware_spi hardware_pwm hardware_dma st7789 pico_graphics)
84 changes: 84 additions & 0 deletions libraries/pico_display_28/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Pico Display 2.8" Pack <!-- omit in toc -->

Our Pico Display Pack offers a vibrant 2.8" (320x240) IPS LCD screen for your Raspberry Pi Pico it also includes four switches and and an RGB LED!

- [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 RGB LED green if the A button is pressed.

```c++
#include "pico_display_28.hpp"
#include "drivers/st7789/st7789.hpp"
#include "libraries/pico_graphics/pico_graphics.hpp"
#include "rgbled.hpp"
#include "button.hpp"

// Display driver
ST7789 st7789(PicoDisplay28::WIDTH, PicoDisplay28::HEIGHT, ROTATE_0, false, get_spi_pins(BG_SPI_FRONT));

// Graphics library - in RGB332 mode you get 256 colours and optional dithering for 75K RAM.
PicoGraphics_PenRGB332 graphics(st7789.width, st7789.height, nullptr);

// RGB LED
RGBLED led(PicoDisplay28::LED_R, PicoDisplay28::LED_G, PicoDisplay28::LED_B);

// And each button
Button button_a(PicoDisplay28::A);
Button button_b(PicoDisplay28::B);
Button button_x(PicoDisplay28::X);
Button button_y(PicoDisplay28::Y);

int main() {

// set the backlight to a value between 0 and 255
// the backlight is driven via PWM and is gamma corrected by our
// library to give a gorgeous linear brightness range.
st7789.set_backlight(100);

while(true) {
// detect if the A button is pressed (could be A, B, X, or Y)
if(button_a.raw(display.A)) {
// make the led glow green
// parameters are red, green, blue all between 0 and 255
// these are also gamma corrected
led.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
st7789.update(&graphics);
}
}
```

## Function Reference

### PicoGraphics

Pico Display 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).

### ST7789

Pico Display uses the ST7789 display driver to handle the LCD. For more information [read the ST7789 README.](../../drivers/st7789/README.md).
10 changes: 10 additions & 0 deletions libraries/pico_display_28/pico_display_28.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
add_library(pico_display_28 INTERFACE)

target_sources(pico_display_28 INTERFACE
${CMAKE_CURRENT_LIST_DIR}/pico_display_28.cpp
)

target_include_directories(pico_display_28 INTERFACE ${CMAKE_CURRENT_LIST_DIR})

# Pull in pico libraries that we need
target_link_libraries(pico_display_28 INTERFACE pico_stdlib)
1 change: 1 addition & 0 deletions libraries/pico_display_28/pico_display_28.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "pico_display_28.hpp"
18 changes: 18 additions & 0 deletions libraries/pico_display_28/pico_display_28.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

#include "pico/stdlib.h"

namespace pimoroni {
class PicoDisplay28 {
public:
static const int WIDTH = 320;
static const int HEIGHT = 240;
static const uint8_t A = 12;
static const uint8_t B = 13;
static const uint8_t X = 14;
static const uint8_t Y = 15;
static const uint8_t LED_R = 26;
static const uint8_t LED_G = 27;
static const uint8_t LED_B = 28;
};
}