diff --git a/drivers/st7567/st7567.cmake b/drivers/st7567/st7567.cmake index 85c022a4..f3af5a90 100644 --- a/drivers/st7567/st7567.cmake +++ b/drivers/st7567/st7567.cmake @@ -7,4 +7,4 @@ target_sources(${DRIVER_NAME} INTERFACE 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) +target_link_libraries(${DRIVER_NAME} INTERFACE pico_stdlib pimoroni_bus hardware_spi hardware_pwm pico_graphics) diff --git a/drivers/st7567/st7567.cpp b/drivers/st7567/st7567.cpp index c03fad58..0796052b 100644 --- a/drivers/st7567/st7567.cpp +++ b/drivers/st7567/st7567.cpp @@ -1,6 +1,4 @@ #include "st7567.hpp" -#include "hardware/pwm.h" -#include #include @@ -58,7 +56,9 @@ namespace pimoroni { }; void ST7567::reset() { - if(reset_pin == PIN_UNUSED) return; + 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); @@ -95,11 +95,9 @@ namespace pimoroni { 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); @@ -130,56 +128,49 @@ namespace pimoroni { 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(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); - 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); + 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++; + } } - 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; + 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); - + gpio_put(cs, 1); } void ST7567::set_backlight(uint8_t brightness) { diff --git a/drivers/st7567/st7567.hpp b/drivers/st7567/st7567.hpp index 79a8c6cb..a4b25d2a 100644 --- a/drivers/st7567/st7567.hpp +++ b/drivers/st7567/st7567.hpp @@ -2,15 +2,10 @@ #include "hardware/spi.h" #include "hardware/pwm.h" -#include "hardware/gpio.h" -#include "common/pimoroni_common.hpp" #include "common/pimoroni_bus.hpp" #include "libraries/pico_graphics/pico_graphics.hpp" namespace pimoroni { - - - class ST7567 : public DisplayDriver { //-------------------------------------------------- // Constants @@ -24,8 +19,7 @@ namespace pimoroni { // Variables //-------------------------------------------------- private: - - spi_inst_t *spi = spi0; + spi_inst_t *spi = spi0; uint32_t dma_channel; @@ -50,8 +44,8 @@ namespace pimoroni { 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(); - } + init(); + } //-------------------------------------------------- diff --git a/examples/gfx_pack/CMakeLists.txt b/examples/gfx_pack/CMakeLists.txt index 0e378638..131534d4 100644 --- a/examples/gfx_pack/CMakeLists.txt +++ b/examples/gfx_pack/CMakeLists.txt @@ -6,7 +6,7 @@ add_executable( ) # Pull in pico libraries that we need -target_link_libraries(${OUTPUT_NAME} pico_stdlib gfx_pack pico_graphics) +target_link_libraries(${OUTPUT_NAME} pico_stdlib gfx_pack) # create map/bin/hex file etc. pico_add_extra_outputs(${OUTPUT_NAME}) \ No newline at end of file diff --git a/examples/gfx_pack/gfx_demo.cpp b/examples/gfx_pack/gfx_demo.cpp index 1ab96c75..ca818de7 100644 --- a/examples/gfx_pack/gfx_demo.cpp +++ b/examples/gfx_pack/gfx_demo.cpp @@ -1,10 +1,5 @@ -#include -#include -#include -#include -#include - #include "pico/stdlib.h" +#include "libraries/pico_graphics/pico_graphics.hpp" #include "libraries/gfx_pack/gfx_pack.hpp" using namespace pimoroni; @@ -41,7 +36,7 @@ void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) { int main() { sleep_ms(100); - st7567.set_backlight(50); + st7567.set_backlight(64); // 0 to 255 struct pt { float x; @@ -66,17 +61,26 @@ int main() { Point text_location(0, 0); -float hue = 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_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_c.raw()) { + text_location.y -= 1; + } + if(button_d.raw()) { + text_location.y += 1; + } - if(button_e.raw()){ + if(button_e.raw()) { text_location.x = 0; - text_location.y = 0;} + text_location.y = 0; + } graphics.set_pen(0); graphics.clear(); @@ -116,5 +120,5 @@ float hue = 0.0; sleep_ms(1000/15); } - return 0; + return 0; } diff --git a/libraries/gfx_pack/gfx_pack.cmake b/libraries/gfx_pack/gfx_pack.cmake index 2985f968..dcba5dad 100644 --- a/libraries/gfx_pack/gfx_pack.cmake +++ b/libraries/gfx_pack/gfx_pack.cmake @@ -1,11 +1,7 @@ set(LIB_NAME gfx_pack) 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 pimoroni_bus st7567 pico_graphics button rgbled) \ No newline at end of file +target_link_libraries(${LIB_NAME} INTERFACE pico_stdlib st7567 button rgbled) \ No newline at end of file diff --git a/libraries/gfx_pack/gfx_pack.cpp b/libraries/gfx_pack/gfx_pack.cpp deleted file mode 100644 index a2c8e02b..00000000 --- a/libraries/gfx_pack/gfx_pack.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "gfx_pack.hpp" - - -using namespace pimoroni; - namespace GfxPack{ - - //SPIPins gfx_pack_pins; - - } \ No newline at end of file diff --git a/libraries/gfx_pack/gfx_pack.hpp b/libraries/gfx_pack/gfx_pack.hpp index bb9734e5..2d329115 100644 --- a/libraries/gfx_pack/gfx_pack.hpp +++ b/libraries/gfx_pack/gfx_pack.hpp @@ -1,13 +1,8 @@ #pragma once -#include "pico/stdlib.h" -#include "common/pimoroni_bus.hpp" #include "drivers/st7567/st7567.hpp" #include "drivers/button/button.hpp" #include "drivers/rgbled/rgbled.hpp" -#include "libraries/pico_graphics/pico_graphics.hpp" - - namespace pimoroni { diff --git a/micropython/examples/gfx_pack/balls_demo.py b/micropython/examples/gfx_pack/balls_demo.py index 2d550971..fb94ebfd 100644 --- a/micropython/examples/gfx_pack/balls_demo.py +++ b/micropython/examples/gfx_pack/balls_demo.py @@ -1,9 +1,14 @@ import time import random -from picographics import PicoGraphics, DISPLAY_GFX_PACK +from gfx_pack import GfxPack -display = PicoGraphics(display=DISPLAY_GFX_PACK) -display.set_backlight(1.0) +""" +Add something here Gee +""" + +gp = GfxPack() +gp.set_backlight(0, 0, 0, 255) +display = gp.display WIDTH, HEIGHT = display.get_bounds() diff --git a/micropython/examples/gfx_pack/snake.py b/micropython/examples/gfx_pack/snake.py index 7c724175..de8d544b 100644 --- a/micropython/examples/gfx_pack/snake.py +++ b/micropython/examples/gfx_pack/snake.py @@ -1,46 +1,47 @@ +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 """ -from picographics import PicoGraphics, DISPLAY_GFX_PACK -from gfx_pack import GfxPack -import time -import random MOVE_UP = 0 MOVE_DOWN = 1 MOVE_LEFT = 2 MOVE_RIGHT = 3 + next_move = MOVE_RIGHT score = 0 -head_possition = (30, 30) -segments = [head_possition] +head_position = (30, 30) +segments = [head_position] ate_apple = False -apple_possition = None - -display = PicoGraphics(display=DISPLAY_GFX_PACK) -display.set_backlight(1.0) +apple_position = None gp = GfxPack() +gp.set_backlight(0, 0, 0, 255) +display = gp.display WIDTH, HEIGHT = display.get_bounds() def set_new_apple(): - global apple_possition - apple_possition = (random.randint(0, WIDTH), random.randint(30, HEIGHT)) + global apple_position + apple_position = random.randint(0, WIDTH), random.randint(30, HEIGHT) def game_over(): - global score, segments, head_possition, ate_apple + global score, segments, head_position, ate_apple score = 0 - head_possition = (30, 30) - segments = [head_possition] + head_position = (30, 30) + segments = [head_position] ate_apple = False set_new_apple() pass @@ -48,25 +49,25 @@ def game_over(): def check_button(): global next_move, ate_apple - if gp.switch_a.is_pressed: - if (next_move != MOVE_DOWN): + if gp.switch_pressed(SWITCH_A): + if next_move != MOVE_DOWN: next_move = MOVE_UP - elif gp.switch_b.is_pressed: - if (next_move != MOVE_UP): + elif gp.switch_pressed(SWITCH_B): + if next_move != MOVE_UP: next_move = MOVE_DOWN - elif gp.switch_d.is_pressed: - if (next_move != MOVE_RIGHT): + elif gp.switch_pressed(SWITCH_C): + if next_move != MOVE_RIGHT: next_move = MOVE_LEFT - elif gp.switch_e.is_pressed: - if (next_move != MOVE_LEFT): + elif gp.switch_pressed(SWITCH_D): + if next_move != MOVE_LEFT: next_move = MOVE_RIGHT - elif gp.switch_c.is_pressed: + elif gp.switch_pressed(SWITCH_E): game_over() def check_eaten(): - global ate_apple, head_possition, apple_possition, score - if (head_possition == apple_possition): + global ate_apple, head_position, apple_position, score + if head_position == apple_position: ate_apple = True score += 1 set_new_apple() @@ -74,37 +75,37 @@ def check_eaten(): def check_collision(): for index in range(len(segments) - 1): - if (head_possition == segments[index]): + if head_position == segments[index]: game_over() return - if (head_possition[0] >= WIDTH): + if head_position[0] >= WIDTH: game_over() - if (head_possition[0] <= 0): + if head_position[0] <= 0: game_over() - if (head_possition[1] >= HEIGHT): + if head_position[1] >= HEIGHT: game_over() - if (head_possition[1] <= 20): + if head_position[1] <= 20: game_over() def move(): - global head_possition, segments, ate_apple + global head_position, segments, ate_apple - head_x, head_y = head_possition + head_x, head_y = head_position - if (next_move == MOVE_UP): + if next_move == MOVE_UP: head_y -= 1 - elif (next_move == MOVE_DOWN): + elif next_move == MOVE_DOWN: head_y += 1 - elif (next_move == MOVE_LEFT): + elif next_move == MOVE_LEFT: head_x -= 1 - elif (next_move == MOVE_RIGHT): + elif next_move == MOVE_RIGHT: head_x += 1 - head_possition = (head_x, head_y) - segments.append(head_possition) + head_position = (head_x, head_y) + segments.append(head_position) - if (ate_apple): + if ate_apple: ate_apple = False else: segments.pop(0) @@ -120,7 +121,7 @@ def draw(): display.line(0, 63, 0, 20) display.line(128, 63, 127, 20) # Draw apple - display.pixel(apple_possition[0], apple_possition[1]) + display.pixel(apple_position[0], apple_position[1]) # Drawing snake for segment in segments: @@ -131,10 +132,11 @@ def draw(): game_over() -while 1: +while True: check_button() check_eaten() move() check_collision() draw() + time.sleep(0.2) diff --git a/micropython/examples/gfx_pack/thermometer.py b/micropython/examples/gfx_pack/thermometer.py index be67ecf8..dbd12d47 100644 --- a/micropython/examples/gfx_pack/thermometer.py +++ b/micropython/examples/gfx_pack/thermometer.py @@ -1,17 +1,16 @@ -"""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 GXF display -or -the internal temperature sensor can be used in place of the BME68x breakout -just change use_bme68x_breakout to False -""" - import time -from breakout_bme68x import BreakoutBME68X, STATUS_HEATER_STABLE -from pimoroni_i2c import PimoroniI2C -from picographics import PicoGraphics, DISPLAY_GFX_PACK -from gfx_pack import GfxPack 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 @@ -22,19 +21,13 @@ sensor_temp = machine.ADC(4) conversion_factor = 3.3 / (65535) # used for calculating a temperature from the raw sensor reading gp = GfxPack() -display = PicoGraphics(display=DISPLAY_GFX_PACK) -display.set_backlight(0.4) -gp.rgb.set_rgb(0, 0, 0) +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 - -PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5} -PINS_PICO_EXPLORER = {"sda": 20, "scl": 21} - -i2c = PimoroniI2C(**PINS_BREAKOUT_GARDEN) - -bmp = BreakoutBME68X(i2c) +bmp = BreakoutBME68X(gp.i2c) # If this gives an error, try the alternative address -# bmp = BreakoutBME68X(i2c, 0x77) +# bmp = BreakoutBME68X(gp.i2c, 0x77) display.set_pen(0) display.clear() @@ -64,16 +57,17 @@ while True: display.text("Temperature", 25, 15, scale=0.2) display.text("{:0.2f}c".format(temperature), 25, 30, scale=2) - if (temperature < lower_temp_bound): + if temperature < lower_temp_bound: r = 0 b = 255 - elif (temperature > upper_temp_bound): + elif temperature > upper_temp_bound: r = 255 b = 0 else: - r = ((temperature - lower_temp_bound) / (upper_temp_bound - lower_temp_bound) * 255) + 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.rgb.set_rgb(r, 0, b) + gp.set_backlight(r, 0, b) display.update() + time.sleep(0.2) diff --git a/micropython/modules_py/gfx_pack.md b/micropython/modules_py/gfx_pack.md index 6bd47ec2..1b4e68c1 100644 --- a/micropython/modules_py/gfx_pack.md +++ b/micropython/modules_py/gfx_pack.md @@ -1,10 +1,10 @@ -# GFX Pack MicroPython +# GFX Pack (MicroPython) 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 anc control needs. ## Table of Content - [Table of Content](#table-of-content) -- [GFX Pack Classes](#GFX-Pack-class) +- [GFX Pack Class](#gfx-pack-class) - [Switches](#switches) - [RGB Backlight](#rgb-backlight) diff --git a/micropython/modules_py/gfx_pack.py b/micropython/modules_py/gfx_pack.py index c7b232a5..dad1c77e 100644 --- a/micropython/modules_py/gfx_pack.py +++ b/micropython/modules_py/gfx_pack.py @@ -1,21 +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 - SW_A = 12 - SW_B = 13 - SW_C = 14 - SW_D = 15 - SW_E = 22 - LED_R = 6 - LED_G = 7 - LED_B = 8 + # Count Constants + NUM_SWITCHES = 5 def __init__(self): - self.rgb = RGBLED(GfxPack.LED_R, GfxPack.LED_G, GfxPack.LED_B, invert=False) - self.switch_a = Button(GfxPack.SW_A) - self.switch_b = Button(GfxPack.SW_B) - self.switch_c = Button(GfxPack.SW_C) - self.switch_d = Button(GfxPack.SW_D) - self.switch_e = Button(GfxPack.SW_E) + 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 not self.__switches[switch].value() + + 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)