From 7d7c5dd6bc5624bf83e65bfdbb6a238d6d055e37 Mon Sep 17 00:00:00 2001 From: Martin Crossley Date: Wed, 31 Dec 2025 09:14:37 +0000 Subject: [PATCH 1/9] add ssd1309_spi_dma example --- spi/ssd1309_spi_dma/ssd1309_spi_dma.c | 217 ++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 spi/ssd1309_spi_dma/ssd1309_spi_dma.c diff --git a/spi/ssd1309_spi_dma/ssd1309_spi_dma.c b/spi/ssd1309_spi_dma/ssd1309_spi_dma.c new file mode 100644 index 000000000..c250af288 --- /dev/null +++ b/spi/ssd1309_spi_dma/ssd1309_spi_dma.c @@ -0,0 +1,217 @@ +/** + * Copyright (c) 2025 mjcross + * + * SPDX-License-Identifier: BSD-3-Clause +**/ + +// An example showing how to drive a ssd1309-based OLED panel over an SPI +// interface from a frame buffer that is transferred in the background under +// DMA control. It should also work on a ssd1306 device (not tested). +// +// To understand the commands and addressing modes for the display refer to +// the manufacturer's datasheet at https://www.hpinfotech.ro/SSD1309.pdf + +#include +#include "pico/stdlib.h" +#include "hardware/dma.h" +#include "hardware/clocks.h" +#include "hardware/spi.h" +#include "string.h" + +// dimensions of our OLED display panel +#define NUM_X_PIXELS 128 +#define NUM_Y_PIXELS 64 + +// how often we want to refresh the display from the frame buffer +#define FRAME_REFRESH_HZ 50 + +// ssd1309 accepts a maximum SPI clock rate of 10 Mbit/sec and for this +// example we will use it at full speed +#define SPI_BITRATE 10 * 1000 * 1000 + +// define the pins for the SPI interface +// we will use the spi0 peripheral and the following GPIO pins (see the +// GPIO function select table in the Pico datasheet). +#define SPI_DEVICE spi0 +#define PIN_CS 17 // chip select (active low) +#define PIN_SCK 18 // SPI clock +#define PIN_MOSI 19 // SPI data transmit (MOSI) +#define PIN_DC 20 // data/command mode (low for command) +#define PIN_R 21 // reset (active low) + +// modes for the ssd1309 data/command pin (see ssd1309 datasheet) +#define DC_COMMAND_MODE 0 +#define DC_DATA_MODE 1 + + +// global variables +int dma_ch_fb_transfer; // DMA channel for frame buffer transfers +int dma_ch_refresh_delay; // DMA channel for the frame period delay +int dma_ch_fb_clear; // DMA channel for clearing the screen +uint8_t frame_buffer[NUM_X_PIXELS * NUM_Y_PIXELS / 8]__attribute__((aligned(32))); + // the frame buffer (about 1kByte), aligned to a 32-bit address + // boundary so that we can clear the screen with 32-bit transfers + + +// a function to clear the frame buffer very quickly using a DMA channel +void fb_clear() { + dma_channel_transfer_to_buffer_now( + dma_ch_fb_clear, + frame_buffer, + dma_encode_transfer_count(sizeof(frame_buffer) / sizeof(uint32_t)) + ); + dma_channel_wait_for_finish_blocking(dma_ch_fb_clear); +} + +// initialise the SPI interface, DMA channels and display +int display_init() { + // configure the SPI controller for 8-bit transfers using Motorola SPI mode 0 + spi_init(SPI_DEVICE, DISP_SPI_BITRATE); + spi_set_format(SPI_DEVICE, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST); + + // configure our interface pins + gpio_set_function(PIN_CS, GPIO_FUNC_SPI); + gpio_set_function(PIN_SCK, GPIO_FUNC_SPI); + gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI); + gpio_init(PIN_DC); + gpio_set_dir(PIN_DC, GPIO_OUT); + gpio_init(PIN_R); + gpio_set_dir(PIN_R, GPIO_OUT); + + // claim free DMA channels (or panic) + dma_ch_fb_transfer = dma_claim_unused_channel(true); // used to transfer the frame buffer to SPI + dma_ch_refresh_delay = dma_claim_unused_channel(true); // used to delay for the frame refresh period + dma_ch_fb_clear = dma_claim_unused_channel(true); // used to clear the frame buffer + + // configure a DMA channel that transfers the frame buffer to the SPI device, then triggers the frame delay channel + dma_channel_config_t dma_config_fb_transfer = dma_channel_get_default_config(dma_ch_fb_transfer); + channel_config_set_transfer_data_size(&dma_config_fb_transfer, DMA_SIZE_8); // use 8-bit transfers + channel_config_set_dreq(&dma_config_fb_transfer, spi_get_dreq(SPI_DEVICE, true)); // paced by SPI TX DREQ + channel_config_set_chain_to(&dma_config_fb_transfer, dma_ch_refresh_delay); // chain to frame_delay + dma_channel_configure( + dma_ch_fb_transfer, + &dma_config_fb_transfer, // use the configuration that we just created + &spi_get_hw(SPI_DEVICE)->dr, // write to the data register of the SPI device (non-incrementing) + frame_buffer, // set the initial read address to the start of the frame buffer + dma_encode_transfer_count(count_of(frame_buffer)), // transfer the whole frame buffer + false // don't trigger yet + ); + + // claim a DMA pacing timer for the frame delay channel (or panic) + int dma_timer_frame_delay = dma_claim_unused_timer(true); + dma_timer_set_fraction(dma_timer_frame_delay, 1, 0xffff); // set the maximum clock divider + uint frame_delay_num_transfers = clock_get_hz(clk_sys) / 0xffff; // calculate number of transfers for the frame delay + + // configure a DMA channel that takes as long as the frame period, then triggers the frame-transfer channel + // the transfers aren't wasted: we use them to reset the read address of the other channel + dma_channel_config_t dma_config_framerate_delay = dma_channel_get_default_config(dma_ch_refresh_delay); + channel_config_set_read_increment(&dma_config_framerate_delay, false); // don't increment the read address + channel_config_set_dreq(&dma_config_framerate_delay, dma_get_timer_dreq(dma_timer_frame_delay)); // use our pacing timer + channel_config_set_chain_to(&dma_config_framerate_delay, dma_ch_fb_transfer); // chain to frame_transfer + static uint32_t fb_start = (uint32_t)frame_buffer; + dma_channel_configure( + dma_ch_refresh_delay, + &dma_config_framerate_delay, // the configuration that we just created + &dma_hw->ch[dma_ch_fb_transfer].read_addr, // write the frame_transfer channel read address register (32-bits) + &fb_start, // initial read address: start of frame buffer (increments, 32-bit reads) + dma_encode_transfer_count(frame_delay_num_transfers), // do the transfer enough times to get the required delay + false // don't trigger yet + ); + + // configure a DMA channel that fills the frame buffer with zeros + dma_channel_config_t dma_config_fb_clear = dma_channel_get_default_config(dma_ch_fb_clear); + channel_config_set_write_increment(&dma_config_fb_clear, true); // increment the write address + channel_config_set_read_increment(&dma_config_fb_clear, false); // don't increment the read address + static uint32_t fb_clear_value = 0x00000000; // this will be our source data for the transfer + dma_channel_configure( + dma_ch_fb_clear, + &dma_config_fb_clear, // the configuration that we just created + frame_buffer, // initial write address: start of frame buffer (increments, 32-bit writes) + &fb_clear_value, // read address: clear_value (does not increment, 32-bit reads) + dma_encode_transfer_count(sizeof(frame_buffer) / sizeof(uint32_t)), // number of 32-bit words in the frame buffer + false // don't trigger yet + ); + + // initialise display + gpio_put(PIN_R, 0); // generate a reset pulse (active low) + sleep_ms(1); + gpio_put(PIN_R, 1); + + // after a short pause, send the commands to initialise the display + sleep_ms(1); + gpio_put(PIN_DC, DC_COMMAND_MODE); // put the interface into command mode + uint8_t cmd_list[] = { 0xaf, 0x20, 0x00 }; // commands for 'display on' and 'horizontal addressing mode' (see datasheet) + spi_write_blocking(SPI_DEVICE, cmd_list, sizeof(cmd_list)); + gpio_put(PIN_DC, DC_DATA_MODE); // return the interface to data mode + + fb_clear(); // clear the frame buffer +} + + +// convenience functions to set and clear pixel positions in the frame buffer +void set_pixel_xy(uint x, uint y) { + if (x < NUM_X_PIXELS && y < NUM_Y_PIXELS) { + frame_buffer[x + (y / 8) * NUM_X_PIXELS] |= (1 << (y % 8)); + } +} + +void clear_pixel_xy(uint x, uint y) { + if (x < NUM_X_PIXELS && y < NUM_Y_PIXELS) { + frame_buffer[x + (y / 8) * NUM_X_PIXELS] &= ~(1 << (y % 8)); + } +} + + +int main(){ + stdio_init_all(); + display_init(); + fb_clear(); + + // start the DMA transfer cycle + dma_channel_start(dma_ch_fb_transfer); + + // You can now read and write the frame buffer at will, and the results will transparently + // appear on the display without any CPU intervention! For details of the address layout + // consult the manufacturer's datasheet (reference above). + + // NOTE: you can read and write the frame buffer at will, but once you have started the + // DMA transfers running don't send any commands or data direct to the display otherwise + // it will get very confused. + + + once you have started the DMA transfer cycle, or it + // will almost certainly lose sync with + // the frame buffer. You could in theory send a command while the frame_delay transfer + // is in progress (synchronised by the DMA interupt) but that is out of scope for this + // example. + + // simple example: draw a moving 'snake' + int head_x = NUM_Y_PIXELS - 1, head_y = NUM_Y_PIXELS - 1, head_dx = 1, head_dy = 1; + int tail_x = 0, tail_y = 0, tail_dx = 1, tail_dy = 1; + while(true) { + set_pixel_xy(head_x, head_y); + clear_pixel_xy(tail_x, tail_y); + + // update head position + if (head_x + head_dx < 0 || head_x + head_dx >= NUM_X_PIXELS) { + head_dx = -head_dx; + } + head_x += head_dx; + if (head_y + head_dy < 0 || head_y + head_dy >= NUM_Y_PIXELS) { + head_dy = -head_dy; + } + head_y += head_dy; + + // update tail position + if (tail_x + tail_dx < 0 || tail_x + tail_dx >= NUM_X_PIXELS) { + tail_dx = -tail_dx; + } + tail_x += tail_dx; + if (tail_y + tail_dy < 0 || tail_y + tail_dy >= NUM_Y_PIXELS) { + tail_dy = -tail_dy; + } + tail_y += tail_dy; + + sleep_ms(5); + } +} From 838fe3422d56b551d394807480d22c76d328da1a Mon Sep 17 00:00:00 2001 From: Martin Crossley Date: Wed, 31 Dec 2025 09:17:53 +0000 Subject: [PATCH 2/9] improve comments and names --- spi/ssd1309_spi_dma/ssd1309_spi_dma.c | 29 ++++++++++----------------- 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/spi/ssd1309_spi_dma/ssd1309_spi_dma.c b/spi/ssd1309_spi_dma/ssd1309_spi_dma.c index c250af288..c3a2df92a 100644 --- a/spi/ssd1309_spi_dma/ssd1309_spi_dma.c +++ b/spi/ssd1309_spi_dma/ssd1309_spi_dma.c @@ -122,7 +122,7 @@ int display_init() { dma_channel_config_t dma_config_fb_clear = dma_channel_get_default_config(dma_ch_fb_clear); channel_config_set_write_increment(&dma_config_fb_clear, true); // increment the write address channel_config_set_read_increment(&dma_config_fb_clear, false); // don't increment the read address - static uint32_t fb_clear_value = 0x00000000; // this will be our source data for the transfer + static uint32_t fb_clear_value = 0x00000000; // this will be our source data value for the transfer dma_channel_configure( dma_ch_fb_clear, &dma_config_fb_clear, // the configuration that we just created @@ -140,14 +140,13 @@ int display_init() { // after a short pause, send the commands to initialise the display sleep_ms(1); gpio_put(PIN_DC, DC_COMMAND_MODE); // put the interface into command mode - uint8_t cmd_list[] = { 0xaf, 0x20, 0x00 }; // commands for 'display on' and 'horizontal addressing mode' (see datasheet) + uint8_t cmd_list[] = { 0xaf, 0x20, 0x00 }; // commands for 'display on' and 'horizontal addr mode' (see datasheet) spi_write_blocking(SPI_DEVICE, cmd_list, sizeof(cmd_list)); gpio_put(PIN_DC, DC_DATA_MODE); // return the interface to data mode fb_clear(); // clear the frame buffer } - // convenience functions to set and clear pixel positions in the frame buffer void set_pixel_xy(uint x, uint y) { if (x < NUM_X_PIXELS && y < NUM_Y_PIXELS) { @@ -170,27 +169,21 @@ int main(){ // start the DMA transfer cycle dma_channel_start(dma_ch_fb_transfer); - // You can now read and write the frame buffer at will, and the results will transparently - // appear on the display without any CPU intervention! For details of the address layout - // consult the manufacturer's datasheet (reference above). - - // NOTE: you can read and write the frame buffer at will, but once you have started the - // DMA transfers running don't send any commands or data direct to the display otherwise - // it will get very confused. - - - once you have started the DMA transfer cycle, or it - // will almost certainly lose sync with - // the frame buffer. You could in theory send a command while the frame_delay transfer - // is in progress (synchronised by the DMA interupt) but that is out of scope for this - // example. + // You can now read and write the frame buffer and the results will automatically be + // transferred to the display without any CPU intervention. For details of the memory + // layout consult the manufacturer's datasheet (reference above). + + // NOTE: you can read and write the frame buffer as you please, but once you have started + // the DMA transfers running don't try to send commands or data direct to the display or + // it will get very confused. While you could in theory send a command during the frame_delay + // transfer (synchronised by the DMA interupt) that is out of scope for this example. // simple example: draw a moving 'snake' int head_x = NUM_Y_PIXELS - 1, head_y = NUM_Y_PIXELS - 1, head_dx = 1, head_dy = 1; int tail_x = 0, tail_y = 0, tail_dx = 1, tail_dy = 1; while(true) { set_pixel_xy(head_x, head_y); - clear_pixel_xy(tail_x, tail_y); + clear_pixel_xy(tail_x, tail_y); // update head position if (head_x + head_dx < 0 || head_x + head_dx >= NUM_X_PIXELS) { From fcc03d27662e4960469da132f7e1c35d6998c961 Mon Sep 17 00:00:00 2001 From: Martin Crossley Date: Fri, 2 Jan 2026 18:50:48 +0000 Subject: [PATCH 3/9] initial build --- spi/ssd1309_spi_dma/CMakeLists.txt | 17 +++ spi/ssd1309_spi_dma/font.h | 112 +++++++++++++++++ spi/ssd1309_spi_dma/ssd1309_spi_dma.c | 167 ++++++++++++-------------- 3 files changed, 209 insertions(+), 87 deletions(-) create mode 100644 spi/ssd1309_spi_dma/CMakeLists.txt create mode 100644 spi/ssd1309_spi_dma/font.h diff --git a/spi/ssd1309_spi_dma/CMakeLists.txt b/spi/ssd1309_spi_dma/CMakeLists.txt new file mode 100644 index 000000000..83b19a867 --- /dev/null +++ b/spi/ssd1309_spi_dma/CMakeLists.txt @@ -0,0 +1,17 @@ +add_executable(ssd1309_spi_dma + ssd1309_spi_dma.c + ) + +# pull in common dependencies and additional hardware support +target_link_libraries(ssd1309_spi_dma + pico_stdlib + hardware_spi + hardware_dma + hardware_clocks + ) + +# create map/bin/hex file etc. +pico_add_extra_outputs(ssd1309_spi_dma) + +# add url via pico_set_program_url +example_auto_set_url(ssd1309_spi_dma) \ No newline at end of file diff --git a/spi/ssd1309_spi_dma/font.h b/spi/ssd1309_spi_dma/font.h new file mode 100644 index 000000000..e76f682d6 --- /dev/null +++ b/spi/ssd1309_spi_dma/font.h @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2026 mjcross + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +// Vertical bitmaps for commonly-used characters. + +// Each bitmap is 8 pixels wide and 8 pixels high with the least +// significant bit at the top. The bitmaps are based on the +// original 'BIOS' font bitmaps credited to IBM + +#include + +static uint8_t font[] = { + 0xff, 0xfd, 0xfc, 0xae, 0xa6, 0xf0, 0xf9, 0xff, // 0 (code -1) UNDEFINED + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 1 (code 32) space + 0x06, 0x5f, 0x5f, 0x06, 0x00, 0x00, 0x00, 0x00, // 2 (code 33) exclam + 0x07, 0x07, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, // 3 (code 34) quotedbl + 0x14, 0x7f, 0x7f, 0x14, 0x7f, 0x7f, 0x14, 0x00, // 4 (code 35) numbersign + 0x24, 0x2e, 0x6b, 0x6b, 0x3a, 0x12, 0x00, 0x00, // 5 (code 36) dollar + 0x23, 0x33, 0x18, 0x0c, 0x06, 0x33, 0x31, 0x00, // 6 (code 37) percent + 0x30, 0x7a, 0x4f, 0x5d, 0x37, 0x7a, 0x48, 0x00, // 7 (code 38) ampersand + 0x04, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // 8 (code 39) quotesingle + 0x1c, 0x3e, 0x63, 0x41, 0x00, 0x00, 0x00, 0x00, // 9 (code 40) parenleft + 0x41, 0x63, 0x3e, 0x1c, 0x00, 0x00, 0x00, 0x00, // 10 (code 41) parenright + 0x04, 0x15, 0x1f, 0x0e, 0x0e, 0x1f, 0x15, 0x04, // 11 (code 42) asterisk + 0x04, 0x04, 0x1f, 0x1f, 0x04, 0x04, 0x00, 0x00, // 12 (code 43) plus + 0x04, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // 13 (code 44) comma + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, // 14 (code 45) hyphen + 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 15 (code 46) period + 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x01, 0x00, // 16 (code 47) slash + 0x3e, 0x7f, 0x71, 0x59, 0x4d, 0x7f, 0x3e, 0x00, // 17 (code 48) zero + 0x40, 0x42, 0x7f, 0x7f, 0x40, 0x40, 0x00, 0x00, // 18 (code 49) one + 0x62, 0x73, 0x59, 0x49, 0x4f, 0x66, 0x00, 0x00, // 19 (code 50) two + 0x22, 0x63, 0x49, 0x49, 0x7f, 0x36, 0x00, 0x00, // 20 (code 51) three + 0x18, 0x1c, 0x16, 0x53, 0x7f, 0x7f, 0x50, 0x00, // 21 (code 52) four + 0x27, 0x67, 0x45, 0x45, 0x7d, 0x39, 0x00, 0x00, // 22 (code 53) five + 0x3c, 0x7e, 0x4b, 0x49, 0x79, 0x30, 0x00, 0x00, // 23 (code 54) six + 0x03, 0x03, 0x71, 0x79, 0x0f, 0x07, 0x00, 0x00, // 24 (code 55) seven + 0x36, 0x7f, 0x49, 0x49, 0x7f, 0x36, 0x00, 0x00, // 25 (code 56) eight + 0x06, 0x4f, 0x49, 0x69, 0x3f, 0x1e, 0x00, 0x00, // 26 (code 57) nine + 0x33, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 27 (code 58) colon + 0x20, 0x3b, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, // 28 (code 59) semicolon + 0x08, 0x1c, 0x36, 0x63, 0x41, 0x00, 0x00, 0x00, // 29 (code 60) less + 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0x00, // 30 (code 61) equal + 0x41, 0x63, 0x36, 0x1c, 0x08, 0x00, 0x00, 0x00, // 31 (code 62) greater + 0x02, 0x03, 0x51, 0x59, 0x0f, 0x06, 0x00, 0x00, // 32 (code 63) question + 0x3e, 0x7f, 0x41, 0x5d, 0x5d, 0x1f, 0x1e, 0x00, // 33 (code 64) at + 0x7c, 0x7e, 0x13, 0x13, 0x7e, 0x7c, 0x00, 0x00, // 34 (code 65) A + 0x41, 0x7f, 0x7f, 0x49, 0x49, 0x7f, 0x36, 0x00, // 35 (code 66) B + 0x1c, 0x3e, 0x63, 0x41, 0x41, 0x63, 0x22, 0x00, // 36 (code 67) C + 0x41, 0x7f, 0x7f, 0x41, 0x63, 0x3e, 0x1c, 0x00, // 37 (code 68) D + 0x41, 0x7f, 0x7f, 0x49, 0x5d, 0x41, 0x63, 0x00, // 38 (code 69) E + 0x41, 0x7f, 0x7f, 0x49, 0x1d, 0x01, 0x03, 0x00, // 39 (code 70) F + 0x1c, 0x3e, 0x63, 0x41, 0x51, 0x73, 0x72, 0x00, // 40 (code 71) G + 0x7f, 0x7f, 0x08, 0x08, 0x7f, 0x7f, 0x00, 0x00, // 41 (code 72) H + 0x41, 0x7f, 0x7f, 0x41, 0x00, 0x00, 0x00, 0x00, // 42 (code 73) I + 0x30, 0x70, 0x40, 0x41, 0x7f, 0x3f, 0x01, 0x00, // 43 (code 74) J + 0x41, 0x7f, 0x7f, 0x08, 0x1c, 0x77, 0x63, 0x00, // 44 (code 75) K + 0x41, 0x7f, 0x7f, 0x41, 0x40, 0x60, 0x70, 0x00, // 45 (code 76) L + 0x7f, 0x7f, 0x0e, 0x1c, 0x0e, 0x7f, 0x7f, 0x00, // 46 (code 77) M + 0x7f, 0x7f, 0x06, 0x0c, 0x18, 0x7f, 0x7f, 0x00, // 47 (code 78) N + 0x1c, 0x3e, 0x63, 0x41, 0x63, 0x3e, 0x1c, 0x00, // 48 (code 79) O + 0x41, 0x7f, 0x7f, 0x49, 0x09, 0x0f, 0x06, 0x00, // 49 (code 80) P + 0x1e, 0x3f, 0x21, 0x71, 0x7f, 0x5e, 0x00, 0x00, // 50 (code 81) Q + 0x41, 0x7f, 0x7f, 0x09, 0x19, 0x7f, 0x66, 0x00, // 51 (code 82) R + 0x26, 0x6f, 0x4d, 0x59, 0x73, 0x32, 0x00, 0x00, // 52 (code 83) S + 0x03, 0x41, 0x7f, 0x7f, 0x41, 0x03, 0x00, 0x00, // 53 (code 84) T + 0x7f, 0x7f, 0x40, 0x40, 0x7f, 0x7f, 0x00, 0x00, // 54 (code 85) U + 0x1f, 0x3f, 0x60, 0x60, 0x3f, 0x1f, 0x00, 0x00, // 55 (code 86) V + 0x7f, 0x7f, 0x30, 0x18, 0x30, 0x7f, 0x7f, 0x00, // 56 (code 87) W + 0x43, 0x67, 0x3c, 0x18, 0x3c, 0x67, 0x43, 0x00, // 57 (code 88) X + 0x07, 0x4f, 0x78, 0x78, 0x4f, 0x07, 0x00, 0x00, // 58 (code 89) Y + 0x47, 0x63, 0x71, 0x59, 0x4d, 0x67, 0x73, 0x00, // 59 (code 90) Z + 0x7f, 0x7f, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, // 60 (code 91) bracketleft + 0x01, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, // 61 (code 92) backslash + 0x41, 0x41, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, // 62 (code 93) bracketright + 0x08, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x08, 0x00, // 63 (code 94) asciicircum + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 64 (code 95) underscore + 0x03, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // 65 (code 96) grave + 0x08, 0x1d, 0x15, 0x15, 0x0f, 0x1e, 0x10, 0x00, // 66 (code 97) a + 0x41, 0x7f, 0x3f, 0x48, 0x48, 0x78, 0x30, 0x00, // 67 (code 98) b + 0x0e, 0x1f, 0x11, 0x11, 0x1b, 0x0a, 0x00, 0x00, // 68 (code 99) c + 0x30, 0x78, 0x48, 0x49, 0x3f, 0x7f, 0x40, 0x00, // 69 (code 100) d + 0x0e, 0x1f, 0x15, 0x15, 0x17, 0x06, 0x00, 0x00, // 70 (code 101) e + 0x48, 0x7e, 0x7f, 0x49, 0x03, 0x02, 0x00, 0x00, // 71 (code 102) f + 0x26, 0x2f, 0x29, 0x29, 0x3e, 0x1f, 0x01, 0x00, // 72 (code 103) g + 0x41, 0x7f, 0x7f, 0x08, 0x04, 0x7c, 0x78, 0x00, // 73 (code 104) h + 0x44, 0x7d, 0x7d, 0x40, 0x00, 0x00, 0x00, 0x00, // 74 (code 105) i + 0x60, 0xe0, 0x80, 0x80, 0xfd, 0x7d, 0x00, 0x00, // 75 (code 106) j + 0x41, 0x7f, 0x7f, 0x10, 0x38, 0x6c, 0x44, 0x00, // 76 (code 107) k + 0x41, 0x7f, 0x7f, 0x40, 0x00, 0x00, 0x00, 0x00, // 77 (code 108) l + 0x1f, 0x1f, 0x06, 0x0e, 0x07, 0x1f, 0x1e, 0x00, // 78 (code 109) m + 0x1f, 0x1f, 0x01, 0x01, 0x1f, 0x1e, 0x00, 0x00, // 79 (code 110) n + 0x0e, 0x1f, 0x11, 0x11, 0x1f, 0x0e, 0x00, 0x00, // 80 (code 111) o + 0x21, 0x3f, 0x3e, 0x29, 0x09, 0x0f, 0x06, 0x00, // 81 (code 112) p + 0x06, 0x0f, 0x09, 0x29, 0x3e, 0x3f, 0x21, 0x00, // 82 (code 113) q + 0x11, 0x1f, 0x1e, 0x13, 0x01, 0x07, 0x06, 0x00, // 83 (code 114) r + 0x12, 0x17, 0x15, 0x15, 0x1d, 0x09, 0x00, 0x00, // 84 (code 115) s + 0x04, 0x3e, 0x7f, 0x44, 0x24, 0x00, 0x00, 0x00, // 85 (code 116) t + 0x0f, 0x1f, 0x10, 0x10, 0x0f, 0x1f, 0x10, 0x00, // 86 (code 117) u + 0x07, 0x0f, 0x18, 0x18, 0x0f, 0x07, 0x00, 0x00, // 87 (code 118) v + 0x0f, 0x1f, 0x1c, 0x0e, 0x1c, 0x1f, 0x0f, 0x00, // 88 (code 119) w + 0x11, 0x1b, 0x0e, 0x04, 0x0e, 0x1b, 0x11, 0x00, // 89 (code 120) x + 0x27, 0x2f, 0x28, 0x28, 0x3f, 0x1f, 0x00, 0x00, // 90 (code 121) y + 0x13, 0x19, 0x1d, 0x17, 0x13, 0x19, 0x00, 0x00, // 91 (code 122) z + 0x08, 0x08, 0x3e, 0x77, 0x41, 0x41, 0x00, 0x00, // 92 (code 123) braceleft + 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 93 (code 124) bar + 0x41, 0x41, 0x77, 0x3e, 0x08, 0x08, 0x00, 0x00, // 94 (code 125) braceright + 0x02, 0x03, 0x01, 0x03, 0x02, 0x03, 0x01, 0x00 // 95 (code 126) asciitilde +}; \ No newline at end of file diff --git a/spi/ssd1309_spi_dma/ssd1309_spi_dma.c b/spi/ssd1309_spi_dma/ssd1309_spi_dma.c index c3a2df92a..45ac0e168 100644 --- a/spi/ssd1309_spi_dma/ssd1309_spi_dma.c +++ b/spi/ssd1309_spi_dma/ssd1309_spi_dma.c @@ -4,9 +4,8 @@ * SPDX-License-Identifier: BSD-3-Clause **/ -// An example showing how to drive a ssd1309-based OLED panel over an SPI -// interface from a frame buffer that is transferred in the background under -// DMA control. It should also work on a ssd1306 device (not tested). +// An example showing how to drive a ssd1309-based OLED panel from a frame buffer using +// DMA transfers over SPI. It should also work on a ssd1306 device (not tested). // // To understand the commands and addressing modes for the display refer to // the manufacturer's datasheet at https://www.hpinfotech.ro/SSD1309.pdf @@ -14,9 +13,8 @@ #include #include "pico/stdlib.h" #include "hardware/dma.h" -#include "hardware/clocks.h" #include "hardware/spi.h" -#include "string.h" +#include "hardware/clocks.h" // dimensions of our OLED display panel #define NUM_X_PIXELS 128 @@ -25,8 +23,7 @@ // how often we want to refresh the display from the frame buffer #define FRAME_REFRESH_HZ 50 -// ssd1309 accepts a maximum SPI clock rate of 10 Mbit/sec and for this -// example we will use it at full speed +// ssd1309 accepts a maximum SPI clock rate of 10 Mbit/sec #define SPI_BITRATE 10 * 1000 * 1000 // define the pins for the SPI interface @@ -45,93 +42,81 @@ // global variables -int dma_ch_fb_transfer; // DMA channel for frame buffer transfers -int dma_ch_refresh_delay; // DMA channel for the frame period delay -int dma_ch_fb_clear; // DMA channel for clearing the screen -uint8_t frame_buffer[NUM_X_PIXELS * NUM_Y_PIXELS / 8]__attribute__((aligned(32))); - // the frame buffer (about 1kByte), aligned to a 32-bit address - // boundary so that we can clear the screen with 32-bit transfers - - -// a function to clear the frame buffer very quickly using a DMA channel -void fb_clear() { - dma_channel_transfer_to_buffer_now( - dma_ch_fb_clear, - frame_buffer, - dma_encode_transfer_count(sizeof(frame_buffer) / sizeof(uint32_t)) - ); - dma_channel_wait_for_finish_blocking(dma_ch_fb_clear); -} - -// initialise the SPI interface, DMA channels and display -int display_init() { - // configure the SPI controller for 8-bit transfers using Motorola SPI mode 0 - spi_init(SPI_DEVICE, DISP_SPI_BITRATE); - spi_set_format(SPI_DEVICE, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST); - - // configure our interface pins - gpio_set_function(PIN_CS, GPIO_FUNC_SPI); - gpio_set_function(PIN_SCK, GPIO_FUNC_SPI); - gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI); - gpio_init(PIN_DC); - gpio_set_dir(PIN_DC, GPIO_OUT); - gpio_init(PIN_R); - gpio_set_dir(PIN_R, GPIO_OUT); - - // claim free DMA channels (or panic) - dma_ch_fb_transfer = dma_claim_unused_channel(true); // used to transfer the frame buffer to SPI - dma_ch_refresh_delay = dma_claim_unused_channel(true); // used to delay for the frame refresh period - dma_ch_fb_clear = dma_claim_unused_channel(true); // used to clear the frame buffer - - // configure a DMA channel that transfers the frame buffer to the SPI device, then triggers the frame delay channel +int dma_ch_fb_transfer; +int dma_ch_refresh_delay; +int dma_ch_fb_clear; +uint8_t frame_buffer[NUM_X_PIXELS * NUM_Y_PIXELS / 8]__attribute__((aligned(32))); // align for 32-bit DMA + +// initialise the DMA channels +void dma_init() { + dma_ch_fb_transfer = dma_claim_unused_channel(true); + dma_ch_refresh_delay = dma_claim_unused_channel(true); + dma_ch_fb_clear = dma_claim_unused_channel(true); + + // transfer frame buffer to SPI device then trigger frame delay dma_channel_config_t dma_config_fb_transfer = dma_channel_get_default_config(dma_ch_fb_transfer); - channel_config_set_transfer_data_size(&dma_config_fb_transfer, DMA_SIZE_8); // use 8-bit transfers - channel_config_set_dreq(&dma_config_fb_transfer, spi_get_dreq(SPI_DEVICE, true)); // paced by SPI TX DREQ - channel_config_set_chain_to(&dma_config_fb_transfer, dma_ch_refresh_delay); // chain to frame_delay + channel_config_set_transfer_data_size(&dma_config_fb_transfer, DMA_SIZE_8); // 8-bit transfers + channel_config_set_dreq(&dma_config_fb_transfer, spi_get_dreq(SPI_DEVICE, true)); // pace by SPI_TX DREQ + channel_config_set_chain(&dma_config_fb_transfer, dma_ch_refresh_delay); // chain to frame delay dma_channel_configure( dma_ch_fb_transfer, - &dma_config_fb_transfer, // use the configuration that we just created - &spi_get_hw(SPI_DEVICE)->dr, // write to the data register of the SPI device (non-incrementing) - frame_buffer, // set the initial read address to the start of the frame buffer - dma_encode_transfer_count(count_of(frame_buffer)), // transfer the whole frame buffer + &dma_config_fb_transfer, + &spi_get_hw(SPI_DEVICE)->dr, // write to SPI data reg (non-incrementing) + frame_buffer, // read from frame buffer (incrementing) + dma_encode_transfer_count(count_of(frame_buffer)), false // don't trigger yet ); - // claim a DMA pacing timer for the frame delay channel (or panic) - int dma_timer_frame_delay = dma_claim_unused_timer(true); - dma_timer_set_fraction(dma_timer_frame_delay, 1, 0xffff); // set the maximum clock divider - uint frame_delay_num_transfers = clock_get_hz(clk_sys) / 0xffff; // calculate number of transfers for the frame delay - - // configure a DMA channel that takes as long as the frame period, then triggers the frame-transfer channel - // the transfers aren't wasted: we use them to reset the read address of the other channel + // delay for frame period then trigger buffer transfer + int dma_timer_frame_delay = dma_claim_unused_timer(true); // pacing timer + dma_timer_set_fraction(dma_timer_frame_delay, 1, 0xffff); // slowest possible + uint frame_delay_num_transfers = clock_get_hz(clk_sys) / 0xffff; // number of transfers to get frame delay dma_channel_config_t dma_config_framerate_delay = dma_channel_get_default_config(dma_ch_refresh_delay); - channel_config_set_read_increment(&dma_config_framerate_delay, false); // don't increment the read address - channel_config_set_dreq(&dma_config_framerate_delay, dma_get_timer_dreq(dma_timer_frame_delay)); // use our pacing timer - channel_config_set_chain_to(&dma_config_framerate_delay, dma_ch_fb_transfer); // chain to frame_transfer + channel_config_set_read_increment(&dma_config_framerate_delay, false); // don't increment read address + channel_config_set_dreq(&dma_config_framerate_delay, dma_get_timer_dreq(dma_timer_frame_delay)); // use pacing timer + channel_config_set_chain_to(&dma_config_framerate_delay, dma_ch_fb_transfer); // chain to buffer transfer static uint32_t fb_start = (uint32_t)frame_buffer; dma_channel_configure( dma_ch_refresh_delay, - &dma_config_framerate_delay, // the configuration that we just created - &dma_hw->ch[dma_ch_fb_transfer].read_addr, // write the frame_transfer channel read address register (32-bits) - &fb_start, // initial read address: start of frame buffer (increments, 32-bit reads) - dma_encode_transfer_count(frame_delay_num_transfers), // do the transfer enough times to get the required delay - false // don't trigger yet + &dma_config_framerate_delay, + &dma_hw->ch[dma_ch_fb_transfer].read_addr, // write to buffer transfer read address reg (non-incrementing) + &fb_start, // read frame buffer address (non-incrementing) + dma_encode_transfer_count(frame_delay_num_transfers), // get required delay + false // don't trigger yet ); - // configure a DMA channel that fills the frame buffer with zeros + // quickly zero the frame buffer - optional if you're short of DMA channels (unlikely!) dma_channel_config_t dma_config_fb_clear = dma_channel_get_default_config(dma_ch_fb_clear); - channel_config_set_write_increment(&dma_config_fb_clear, true); // increment the write address - channel_config_set_read_increment(&dma_config_fb_clear, false); // don't increment the read address - static uint32_t fb_clear_value = 0x00000000; // this will be our source data value for the transfer + channel_config_set_write_increment(&dma_config_fb_clear, true); // increment write address + channel_config_set_read_increment(&dma_config_fb_clear, false); // don't increment read address + static uint32_t fb_clear_value = 0x00000000; // source data for transfer dma_channel_configure( dma_ch_fb_clear, - &dma_config_fb_clear, // the configuration that we just created - frame_buffer, // initial write address: start of frame buffer (increments, 32-bit writes) - &fb_clear_value, // read address: clear_value (does not increment, 32-bit reads) - dma_encode_transfer_count(sizeof(frame_buffer) / sizeof(uint32_t)), // number of 32-bit words in the frame buffer + &dma_config_fb_clear, + frame_buffer, // write to frame buffer (32-bit writes) + &fb_clear_value, // read from our clear_value (non-incrementing) + dma_encode_transfer_count(sizeof(frame_buffer) / sizeof(uint32_t)), // 32-bit words in frame buffer false // don't trigger yet ); +} + +// initialise the SPI interface +void interface_init() { + // configure the SPI controller for 8-bit transfers using Motorola SPI mode 0 + spi_init(SPI_DEVICE, DISP_SPI_BITRATE); + spi_set_format(SPI_DEVICE, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST); + // configure our interface pins + gpio_set_function(PIN_CS, GPIO_FUNC_SPI); + gpio_set_function(PIN_SCK, GPIO_FUNC_SPI); + gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI); + gpio_init(PIN_DC); + gpio_set_dir(PIN_DC, GPIO_OUT); + gpio_init(PIN_R); + gpio_set_dir(PIN_R, GPIO_OUT); + +// reset and initialise the display +void display_init() { // initialise display gpio_put(PIN_R, 0); // generate a reset pulse (active low) sleep_ms(1); @@ -147,6 +132,13 @@ int display_init() { fb_clear(); // clear the frame buffer } + +// clear the frame buffer quickly using a DMA channel +void fb_clear() { + dma_channel_set_write_addr(dma_ch_fb_clear, frame_buffer, true); // reset write address and trigger + dma_channel_wait_for_finish_blocking(dma_ch_fb_clear); +} + // convenience functions to set and clear pixel positions in the frame buffer void set_pixel_xy(uint x, uint y) { if (x < NUM_X_PIXELS && y < NUM_Y_PIXELS) { @@ -163,22 +155,23 @@ void clear_pixel_xy(uint x, uint y) { int main(){ stdio_init_all(); + + // initialise everything + dma_init(); + interface_init(); display_init(); - fb_clear(); - // start the DMA transfer cycle + // start the DMA transfer (automatically repeats every frame period) dma_channel_start(dma_ch_fb_transfer); - // You can now read and write the frame buffer and the results will automatically be - // transferred to the display without any CPU intervention. For details of the memory - // layout consult the manufacturer's datasheet (reference above). - - // NOTE: you can read and write the frame buffer as you please, but once you have started - // the DMA transfers running don't try to send commands or data direct to the display or - // it will get very confused. While you could in theory send a command during the frame_delay - // transfer (synchronised by the DMA interupt) that is out of scope for this example. + // anything you write to the frame buffer will now be transferred transparently to the + // display - for the memory layout consult the manufacturer's datasheet (reference above). - // simple example: draw a moving 'snake' + // NOTE: don't send your own commands or data to the display while it is being controlled + // by the DMA channels, as confusion will result. Do all your interaction via the frame + // buffer. + + // simple example: a moving 'snake' int head_x = NUM_Y_PIXELS - 1, head_y = NUM_Y_PIXELS - 1, head_dx = 1, head_dy = 1; int tail_x = 0, tail_y = 0, tail_dx = 1, tail_dy = 1; while(true) { From b95012ffff18aa9d4e63dd7b2e4ce53914aef54c Mon Sep 17 00:00:00 2001 From: Martin Crossley Date: Sat, 3 Jan 2026 13:43:16 +0000 Subject: [PATCH 4/9] add font and basic stdio driver --- spi/CMakeLists.txt | 1 + spi/ssd1309_spi_dma/CMakeLists.txt | 1 - spi/ssd1309_spi_dma/font.h | 206 +++++++++++++------------- spi/ssd1309_spi_dma/ssd1309_spi_dma.c | 159 ++++++++++---------- 4 files changed, 185 insertions(+), 182 deletions(-) diff --git a/spi/CMakeLists.txt b/spi/CMakeLists.txt index d61abb2aa..da825de41 100644 --- a/spi/CMakeLists.txt +++ b/spi/CMakeLists.txt @@ -4,6 +4,7 @@ if (TARGET hardware_spi) add_subdirectory_exclude_platforms(spi_dma) add_subdirectory_exclude_platforms(spi_master_slave) add_subdirectory_exclude_platforms(spi_flash) + add_subdirectory_exclude_platforms(ssd1309_spi_dma) add_subdirectory_exclude_platforms(max7219_32x8_spi) add_subdirectory_exclude_platforms(max7219_8x7seg_spi) else() diff --git a/spi/ssd1309_spi_dma/CMakeLists.txt b/spi/ssd1309_spi_dma/CMakeLists.txt index 83b19a867..26e8f1d00 100644 --- a/spi/ssd1309_spi_dma/CMakeLists.txt +++ b/spi/ssd1309_spi_dma/CMakeLists.txt @@ -7,7 +7,6 @@ target_link_libraries(ssd1309_spi_dma pico_stdlib hardware_spi hardware_dma - hardware_clocks ) # create map/bin/hex file etc. diff --git a/spi/ssd1309_spi_dma/font.h b/spi/ssd1309_spi_dma/font.h index e76f682d6..0191a9e94 100644 --- a/spi/ssd1309_spi_dma/font.h +++ b/spi/ssd1309_spi_dma/font.h @@ -6,107 +6,113 @@ // Vertical bitmaps for commonly-used characters. -// Each bitmap is 8 pixels wide and 8 pixels high with the least -// significant bit at the top. The bitmaps are based on the -// original 'BIOS' font bitmaps credited to IBM +// Each bitmap is 8 pixels wide and 8 pixels high, with the least +// significant bit at the top. The patterns are based on bitmaps +// originally credited to IBM. #include -static uint8_t font[] = { - 0xff, 0xfd, 0xfc, 0xae, 0xa6, 0xf0, 0xf9, 0xff, // 0 (code -1) UNDEFINED - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 1 (code 32) space - 0x06, 0x5f, 0x5f, 0x06, 0x00, 0x00, 0x00, 0x00, // 2 (code 33) exclam - 0x07, 0x07, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, // 3 (code 34) quotedbl - 0x14, 0x7f, 0x7f, 0x14, 0x7f, 0x7f, 0x14, 0x00, // 4 (code 35) numbersign - 0x24, 0x2e, 0x6b, 0x6b, 0x3a, 0x12, 0x00, 0x00, // 5 (code 36) dollar - 0x23, 0x33, 0x18, 0x0c, 0x06, 0x33, 0x31, 0x00, // 6 (code 37) percent - 0x30, 0x7a, 0x4f, 0x5d, 0x37, 0x7a, 0x48, 0x00, // 7 (code 38) ampersand - 0x04, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // 8 (code 39) quotesingle - 0x1c, 0x3e, 0x63, 0x41, 0x00, 0x00, 0x00, 0x00, // 9 (code 40) parenleft - 0x41, 0x63, 0x3e, 0x1c, 0x00, 0x00, 0x00, 0x00, // 10 (code 41) parenright - 0x04, 0x15, 0x1f, 0x0e, 0x0e, 0x1f, 0x15, 0x04, // 11 (code 42) asterisk - 0x04, 0x04, 0x1f, 0x1f, 0x04, 0x04, 0x00, 0x00, // 12 (code 43) plus - 0x04, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // 13 (code 44) comma - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, // 14 (code 45) hyphen - 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 15 (code 46) period - 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x01, 0x00, // 16 (code 47) slash - 0x3e, 0x7f, 0x71, 0x59, 0x4d, 0x7f, 0x3e, 0x00, // 17 (code 48) zero - 0x40, 0x42, 0x7f, 0x7f, 0x40, 0x40, 0x00, 0x00, // 18 (code 49) one - 0x62, 0x73, 0x59, 0x49, 0x4f, 0x66, 0x00, 0x00, // 19 (code 50) two - 0x22, 0x63, 0x49, 0x49, 0x7f, 0x36, 0x00, 0x00, // 20 (code 51) three - 0x18, 0x1c, 0x16, 0x53, 0x7f, 0x7f, 0x50, 0x00, // 21 (code 52) four - 0x27, 0x67, 0x45, 0x45, 0x7d, 0x39, 0x00, 0x00, // 22 (code 53) five - 0x3c, 0x7e, 0x4b, 0x49, 0x79, 0x30, 0x00, 0x00, // 23 (code 54) six - 0x03, 0x03, 0x71, 0x79, 0x0f, 0x07, 0x00, 0x00, // 24 (code 55) seven - 0x36, 0x7f, 0x49, 0x49, 0x7f, 0x36, 0x00, 0x00, // 25 (code 56) eight - 0x06, 0x4f, 0x49, 0x69, 0x3f, 0x1e, 0x00, 0x00, // 26 (code 57) nine - 0x33, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 27 (code 58) colon - 0x20, 0x3b, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, // 28 (code 59) semicolon - 0x08, 0x1c, 0x36, 0x63, 0x41, 0x00, 0x00, 0x00, // 29 (code 60) less - 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0x00, // 30 (code 61) equal - 0x41, 0x63, 0x36, 0x1c, 0x08, 0x00, 0x00, 0x00, // 31 (code 62) greater - 0x02, 0x03, 0x51, 0x59, 0x0f, 0x06, 0x00, 0x00, // 32 (code 63) question - 0x3e, 0x7f, 0x41, 0x5d, 0x5d, 0x1f, 0x1e, 0x00, // 33 (code 64) at - 0x7c, 0x7e, 0x13, 0x13, 0x7e, 0x7c, 0x00, 0x00, // 34 (code 65) A - 0x41, 0x7f, 0x7f, 0x49, 0x49, 0x7f, 0x36, 0x00, // 35 (code 66) B - 0x1c, 0x3e, 0x63, 0x41, 0x41, 0x63, 0x22, 0x00, // 36 (code 67) C - 0x41, 0x7f, 0x7f, 0x41, 0x63, 0x3e, 0x1c, 0x00, // 37 (code 68) D - 0x41, 0x7f, 0x7f, 0x49, 0x5d, 0x41, 0x63, 0x00, // 38 (code 69) E - 0x41, 0x7f, 0x7f, 0x49, 0x1d, 0x01, 0x03, 0x00, // 39 (code 70) F - 0x1c, 0x3e, 0x63, 0x41, 0x51, 0x73, 0x72, 0x00, // 40 (code 71) G - 0x7f, 0x7f, 0x08, 0x08, 0x7f, 0x7f, 0x00, 0x00, // 41 (code 72) H - 0x41, 0x7f, 0x7f, 0x41, 0x00, 0x00, 0x00, 0x00, // 42 (code 73) I - 0x30, 0x70, 0x40, 0x41, 0x7f, 0x3f, 0x01, 0x00, // 43 (code 74) J - 0x41, 0x7f, 0x7f, 0x08, 0x1c, 0x77, 0x63, 0x00, // 44 (code 75) K - 0x41, 0x7f, 0x7f, 0x41, 0x40, 0x60, 0x70, 0x00, // 45 (code 76) L - 0x7f, 0x7f, 0x0e, 0x1c, 0x0e, 0x7f, 0x7f, 0x00, // 46 (code 77) M - 0x7f, 0x7f, 0x06, 0x0c, 0x18, 0x7f, 0x7f, 0x00, // 47 (code 78) N - 0x1c, 0x3e, 0x63, 0x41, 0x63, 0x3e, 0x1c, 0x00, // 48 (code 79) O - 0x41, 0x7f, 0x7f, 0x49, 0x09, 0x0f, 0x06, 0x00, // 49 (code 80) P - 0x1e, 0x3f, 0x21, 0x71, 0x7f, 0x5e, 0x00, 0x00, // 50 (code 81) Q - 0x41, 0x7f, 0x7f, 0x09, 0x19, 0x7f, 0x66, 0x00, // 51 (code 82) R - 0x26, 0x6f, 0x4d, 0x59, 0x73, 0x32, 0x00, 0x00, // 52 (code 83) S - 0x03, 0x41, 0x7f, 0x7f, 0x41, 0x03, 0x00, 0x00, // 53 (code 84) T - 0x7f, 0x7f, 0x40, 0x40, 0x7f, 0x7f, 0x00, 0x00, // 54 (code 85) U - 0x1f, 0x3f, 0x60, 0x60, 0x3f, 0x1f, 0x00, 0x00, // 55 (code 86) V - 0x7f, 0x7f, 0x30, 0x18, 0x30, 0x7f, 0x7f, 0x00, // 56 (code 87) W - 0x43, 0x67, 0x3c, 0x18, 0x3c, 0x67, 0x43, 0x00, // 57 (code 88) X - 0x07, 0x4f, 0x78, 0x78, 0x4f, 0x07, 0x00, 0x00, // 58 (code 89) Y - 0x47, 0x63, 0x71, 0x59, 0x4d, 0x67, 0x73, 0x00, // 59 (code 90) Z - 0x7f, 0x7f, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, // 60 (code 91) bracketleft - 0x01, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, // 61 (code 92) backslash - 0x41, 0x41, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, // 62 (code 93) bracketright - 0x08, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x08, 0x00, // 63 (code 94) asciicircum - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 64 (code 95) underscore - 0x03, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // 65 (code 96) grave - 0x08, 0x1d, 0x15, 0x15, 0x0f, 0x1e, 0x10, 0x00, // 66 (code 97) a - 0x41, 0x7f, 0x3f, 0x48, 0x48, 0x78, 0x30, 0x00, // 67 (code 98) b - 0x0e, 0x1f, 0x11, 0x11, 0x1b, 0x0a, 0x00, 0x00, // 68 (code 99) c - 0x30, 0x78, 0x48, 0x49, 0x3f, 0x7f, 0x40, 0x00, // 69 (code 100) d - 0x0e, 0x1f, 0x15, 0x15, 0x17, 0x06, 0x00, 0x00, // 70 (code 101) e - 0x48, 0x7e, 0x7f, 0x49, 0x03, 0x02, 0x00, 0x00, // 71 (code 102) f - 0x26, 0x2f, 0x29, 0x29, 0x3e, 0x1f, 0x01, 0x00, // 72 (code 103) g - 0x41, 0x7f, 0x7f, 0x08, 0x04, 0x7c, 0x78, 0x00, // 73 (code 104) h - 0x44, 0x7d, 0x7d, 0x40, 0x00, 0x00, 0x00, 0x00, // 74 (code 105) i - 0x60, 0xe0, 0x80, 0x80, 0xfd, 0x7d, 0x00, 0x00, // 75 (code 106) j - 0x41, 0x7f, 0x7f, 0x10, 0x38, 0x6c, 0x44, 0x00, // 76 (code 107) k - 0x41, 0x7f, 0x7f, 0x40, 0x00, 0x00, 0x00, 0x00, // 77 (code 108) l - 0x1f, 0x1f, 0x06, 0x0e, 0x07, 0x1f, 0x1e, 0x00, // 78 (code 109) m - 0x1f, 0x1f, 0x01, 0x01, 0x1f, 0x1e, 0x00, 0x00, // 79 (code 110) n - 0x0e, 0x1f, 0x11, 0x11, 0x1f, 0x0e, 0x00, 0x00, // 80 (code 111) o - 0x21, 0x3f, 0x3e, 0x29, 0x09, 0x0f, 0x06, 0x00, // 81 (code 112) p - 0x06, 0x0f, 0x09, 0x29, 0x3e, 0x3f, 0x21, 0x00, // 82 (code 113) q - 0x11, 0x1f, 0x1e, 0x13, 0x01, 0x07, 0x06, 0x00, // 83 (code 114) r - 0x12, 0x17, 0x15, 0x15, 0x1d, 0x09, 0x00, 0x00, // 84 (code 115) s - 0x04, 0x3e, 0x7f, 0x44, 0x24, 0x00, 0x00, 0x00, // 85 (code 116) t - 0x0f, 0x1f, 0x10, 0x10, 0x0f, 0x1f, 0x10, 0x00, // 86 (code 117) u - 0x07, 0x0f, 0x18, 0x18, 0x0f, 0x07, 0x00, 0x00, // 87 (code 118) v - 0x0f, 0x1f, 0x1c, 0x0e, 0x1c, 0x1f, 0x0f, 0x00, // 88 (code 119) w - 0x11, 0x1b, 0x0e, 0x04, 0x0e, 0x1b, 0x11, 0x00, // 89 (code 120) x - 0x27, 0x2f, 0x28, 0x28, 0x3f, 0x1f, 0x00, 0x00, // 90 (code 121) y - 0x13, 0x19, 0x1d, 0x17, 0x13, 0x19, 0x00, 0x00, // 91 (code 122) z - 0x08, 0x08, 0x3e, 0x77, 0x41, 0x41, 0x00, 0x00, // 92 (code 123) braceleft - 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 93 (code 124) bar - 0x41, 0x41, 0x77, 0x3e, 0x08, 0x08, 0x00, 0x00, // 94 (code 125) braceright - 0x02, 0x03, 0x01, 0x03, 0x02, 0x03, 0x01, 0x00 // 95 (code 126) asciitilde +#define FONT_INDEX_DEFAULT 0 +#define FONT_INDEX_START 1 +#define FONT_INDEX_END 95 +#define FONT_CODE_START 32 +#define FONT_BYTES_PER_CODE 8 + +static const uint8_t font[] = { + 0xff, 0xfd, 0xfe, 0xfe, 0xae, 0xf6, 0xf9, 0xff, // 00 (code -1) default + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 01 (code 32) space + 0x00, 0x00, 0x0c, 0xbe, 0x0c, 0x00, 0x00, 0x00, // 02 (code 33) exclam + 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, // 03 (code 34) quotedbl + 0x00, 0x28, 0xfe, 0x28, 0x28, 0xfe, 0x28, 0x00, // 04 (code 35) numbersign + 0x00, 0x48, 0x54, 0xd6, 0xd6, 0x54, 0x24, 0x00, // 05 (code 36) dollar + 0x00, 0x8c, 0x4c, 0x20, 0x10, 0xc8, 0xc4, 0x00, // 06 (code 37) percent + 0x60, 0x94, 0x8a, 0x9a, 0x64, 0x90, 0x90, 0x00, // 07 (code 38) ampersand + 0x00, 0x00, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, // 08 (code 39) quotesingle + 0x00, 0x38, 0x44, 0x82, 0x00, 0x00, 0x00, 0x00, // 09 (code 40) parenleft + 0x00, 0x00, 0x82, 0x44, 0x38, 0x00, 0x00, 0x00, // 10 (code 41) parenright + 0x10, 0x54, 0x38, 0x38, 0x38, 0x54, 0x10, 0x00, // 11 (code 42) asterisk + 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00, // 12 (code 43) plus + 0x00, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, // 13 (code 44) comma + 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, // 14 (code 45) hyphen + 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, // 15 (code 46) period + 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x00, // 16 (code 47) slash + 0x00, 0x7c, 0xc2, 0xa2, 0x92, 0x8a, 0x7c, 0x00, // 17 (code 48) zero + 0x00, 0x88, 0x84, 0xfe, 0x80, 0x80, 0x00, 0x00, // 18 (code 49) one + 0x00, 0xc4, 0xa2, 0xa2, 0x92, 0x92, 0xcc, 0x00, // 19 (code 50) two + 0x00, 0x44, 0x82, 0x92, 0x92, 0x92, 0x6c, 0x00, // 20 (code 51) three + 0x20, 0x30, 0x28, 0xa4, 0xfe, 0xa0, 0x20, 0x00, // 21 (code 52) four + 0x00, 0x4e, 0x8a, 0x8a, 0x8a, 0x8a, 0x72, 0x00, // 22 (code 53) five + 0x00, 0x78, 0x94, 0x92, 0x92, 0x92, 0x60, 0x00, // 23 (code 54) six + 0x00, 0x06, 0x02, 0xe2, 0x12, 0x0a, 0x06, 0x00, // 24 (code 55) seven + 0x00, 0x6c, 0x92, 0x92, 0x92, 0x92, 0x6c, 0x00, // 25 (code 56) eight + 0x00, 0x0c, 0x92, 0x92, 0x92, 0x52, 0x3c, 0x00, // 26 (code 57) nine + 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, // 27 (code 58) colon + 0x00, 0x00, 0x80, 0x66, 0x00, 0x00, 0x00, 0x00, // 28 (code 59) semicolon + 0x00, 0x10, 0x28, 0x44, 0x82, 0x00, 0x00, 0x00, // 29 (code 60) less + 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x00, // 30 (code 61) equal + 0x00, 0x00, 0x00, 0x82, 0x44, 0x28, 0x10, 0x00, // 31 (code 62) greater + 0x00, 0x04, 0x02, 0x02, 0xa2, 0x12, 0x0c, 0x00, // 32 (code 63) question + 0x00, 0x7c, 0x82, 0xba, 0xaa, 0xaa, 0x3c, 0x00, // 33 (code 64) at + 0x00, 0xf8, 0x24, 0x22, 0x22, 0x24, 0xf8, 0x00, // 34 (code 65) A + 0x00, 0x82, 0xfe, 0x92, 0x92, 0x92, 0x6c, 0x00, // 35 (code 66) B + 0x00, 0x38, 0x44, 0x82, 0x82, 0x82, 0x44, 0x00, // 36 (code 67) C + 0x00, 0x82, 0xfe, 0x82, 0x82, 0x44, 0x38, 0x00, // 37 (code 68) D + 0x00, 0x82, 0xfe, 0x92, 0xba, 0x82, 0xc6, 0x00, // 38 (code 69) E + 0x00, 0x82, 0xfe, 0x92, 0x3a, 0x02, 0x06, 0x00, // 39 (code 70) F + 0x00, 0x38, 0x44, 0x82, 0xa2, 0xa2, 0xe4, 0x00, // 40 (code 71) G + 0x00, 0xfe, 0x10, 0x10, 0x10, 0x10, 0xfe, 0x00, // 41 (code 72) H + 0x00, 0x00, 0x82, 0xfe, 0x82, 0x00, 0x00, 0x00, // 42 (code 73) I + 0x00, 0x60, 0x80, 0x80, 0x82, 0x7e, 0x02, 0x00, // 43 (code 74) J + 0x00, 0x82, 0xfe, 0x10, 0x28, 0x44, 0x82, 0x80, // 44 (code 75) K + 0x00, 0x82, 0xfe, 0x82, 0x80, 0x80, 0xc0, 0x00, // 45 (code 76) L + 0x00, 0xfe, 0x02, 0x04, 0x08, 0x04, 0x02, 0xfe, // 46 (code 77) M + 0x00, 0xfe, 0x02, 0x04, 0x08, 0x10, 0xfe, 0x00, // 47 (code 78) N + 0x00, 0x38, 0x44, 0x82, 0x82, 0x44, 0x38, 0x00, // 48 (code 79) O + 0x00, 0x82, 0xfe, 0x92, 0x12, 0x12, 0x0c, 0x00, // 49 (code 80) P + 0x00, 0x3c, 0x42, 0x42, 0x62, 0x42, 0xbc, 0x80, // 50 (code 81) Q + 0x00, 0x82, 0xfe, 0x92, 0x32, 0x52, 0x8c, 0x00, // 51 (code 82) R + 0x00, 0x4c, 0x92, 0x92, 0x92, 0x92, 0x64, 0x00, // 52 (code 83) S + 0x00, 0x06, 0x02, 0x82, 0xfe, 0x82, 0x02, 0x06, // 53 (code 84) T + 0x00, 0x7e, 0x80, 0x80, 0x80, 0x80, 0x7e, 0x00, // 54 (code 85) U + 0x00, 0x1e, 0x20, 0x40, 0x80, 0x40, 0x20, 0x1e, // 55 (code 86) V + 0x00, 0x7e, 0x80, 0x80, 0x70, 0x80, 0x80, 0x7e, // 56 (code 87) W + 0x00, 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82, // 57 (code 88) X + 0x00, 0x02, 0x04, 0x88, 0xf0, 0x88, 0x04, 0x02, // 58 (code 89) Y + 0x00, 0x86, 0xc2, 0xa2, 0x92, 0x8a, 0x86, 0xc2, // 59 (code 90) Z + 0x00, 0xfe, 0x82, 0x82, 0x82, 0x00, 0x00, 0x00, // 60 (code 91) bracketleft + 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, // 61 (code 92) backslash + 0x00, 0x82, 0x82, 0x82, 0xfe, 0x00, 0x00, 0x00, // 62 (code 93) bracketright + 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x00, // 63 (code 94) asciicircum + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 64 (code 95) underscore + 0x00, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x00, // 65 (code 96) grave + 0x00, 0x40, 0xa8, 0xa8, 0xa8, 0xa8, 0xf0, 0x80, // 66 (code 97) a + 0x00, 0x02, 0xfe, 0x60, 0x90, 0x90, 0x90, 0x60, // 67 (code 98) b + 0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x50, 0x00, // 68 (code 99) c + 0x00, 0x60, 0x90, 0x90, 0x90, 0x62, 0xfe, 0x80, // 69 (code 100) d + 0x00, 0x70, 0xa8, 0xa8, 0xa8, 0xa8, 0x30, 0x00, // 70 (code 101) e + 0x00, 0x00, 0x90, 0xfc, 0x92, 0x02, 0x04, 0x00, // 71 (code 102) f + 0x00, 0x98, 0xa4, 0xa4, 0xa4, 0xa4, 0x78, 0x04, // 72 (code 103) g + 0x00, 0x82, 0xfe, 0x10, 0x08, 0x08, 0xf0, 0x00, // 73 (code 104) h + 0x00, 0x00, 0x88, 0xfa, 0x80, 0x00, 0x00, 0x00, // 74 (code 105) i + 0x00, 0x60, 0x80, 0x80, 0x80, 0x84, 0x7d, 0x00, // 75 (code 106) j + 0x00, 0x02, 0xfe, 0x20, 0x50, 0x88, 0x80, 0x00, // 76 (code 107) k + 0x00, 0x00, 0x82, 0xfe, 0x80, 0x00, 0x00, 0x00, // 77 (code 108) l + 0x00, 0xf8, 0x08, 0x08, 0xf0, 0x08, 0x08, 0xf0, // 78 (code 109) m + 0x00, 0xf8, 0x10, 0x08, 0x08, 0x08, 0xf0, 0x00, // 79 (code 110) n + 0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, // 80 (code 111) o + 0x00, 0x84, 0xfc, 0x98, 0x24, 0x24, 0x18, 0x00, // 81 (code 112) p + 0x00, 0x18, 0x24, 0x24, 0x98, 0xfc, 0x84, 0x00, // 82 (code 113) q + 0x00, 0x88, 0xf8, 0x90, 0x08, 0x08, 0x30, 0x00, // 83 (code 114) r + 0x00, 0x90, 0xa8, 0xa8, 0xa8, 0xa8, 0x48, 0x00, // 84 (code 115) s + 0x00, 0x08, 0x08, 0x7e, 0x88, 0x88, 0x40, 0x00, // 85 (code 116) t + 0x00, 0x78, 0x80, 0x80, 0x80, 0x40, 0xf8, 0x00, // 86 (code 117) u + 0x00, 0x18, 0x20, 0x40, 0x80, 0x40, 0x20, 0x18, // 87 (code 118) v + 0x00, 0x78, 0x80, 0x80, 0x70, 0x80, 0x80, 0x78, // 88 (code 119) w + 0x00, 0x88, 0x50, 0x20, 0x50, 0x88, 0x00, 0x00, // 89 (code 120) x + 0x00, 0x9c, 0xa0, 0xa0, 0xa0, 0xa0, 0x7c, 0x00, // 90 (code 121) y + 0x00, 0x88, 0xc8, 0xa8, 0x98, 0x88, 0x00, 0x00, // 91 (code 122) z + 0x00, 0x10, 0x10, 0x6c, 0x82, 0x82, 0x00, 0x00, // 92 (code 123) braceleft + 0x00, 0x00, 0x00, 0xee, 0x00, 0x00, 0x00, 0x00, // 93 (code 124) bar + 0x00, 0x00, 0x82, 0x82, 0x6c, 0x10, 0x10, 0x00, // 94 (code 125) braceright + 0x00, 0x04, 0x02, 0x02, 0x04, 0x04, 0x02, 0x00 // 95 (code 126) asciitilde }; \ No newline at end of file diff --git a/spi/ssd1309_spi_dma/ssd1309_spi_dma.c b/spi/ssd1309_spi_dma/ssd1309_spi_dma.c index 45ac0e168..d327c6320 100644 --- a/spi/ssd1309_spi_dma/ssd1309_spi_dma.c +++ b/spi/ssd1309_spi_dma/ssd1309_spi_dma.c @@ -11,20 +11,24 @@ // the manufacturer's datasheet at https://www.hpinfotech.ro/SSD1309.pdf #include +#include "pico/stdio/driver.h" #include "pico/stdlib.h" #include "hardware/dma.h" #include "hardware/spi.h" -#include "hardware/clocks.h" +#include "string.h" + +#include "font.h" // dimensions of our OLED display panel #define NUM_X_PIXELS 128 #define NUM_Y_PIXELS 64 +#define PIXELS_PER_BYTE 8 // how often we want to refresh the display from the frame buffer -#define FRAME_REFRESH_HZ 50 +#define FRAME_PERIOD_MS 20 // ssd1309 accepts a maximum SPI clock rate of 10 Mbit/sec -#define SPI_BITRATE 10 * 1000 * 1000 +#define DISPLAY_SPI_BITRATE 10 * 1000 * 1000 // define the pins for the SPI interface // we will use the spi0 peripheral and the following GPIO pins (see the @@ -42,68 +46,33 @@ // global variables -int dma_ch_fb_transfer; -int dma_ch_refresh_delay; -int dma_ch_fb_clear; -uint8_t frame_buffer[NUM_X_PIXELS * NUM_Y_PIXELS / 8]__attribute__((aligned(32))); // align for 32-bit DMA +uint8_t frame_buffer[NUM_X_PIXELS * NUM_Y_PIXELS / PIXELS_PER_BYTE]; +int dma_ch_transfer_fb; +volatile bool display_needs_refresh; +volatile uint8_t *printf_write_ptr; -// initialise the DMA channels +// set up the DMA channels void dma_init() { - dma_ch_fb_transfer = dma_claim_unused_channel(true); - dma_ch_refresh_delay = dma_claim_unused_channel(true); - dma_ch_fb_clear = dma_claim_unused_channel(true); - - // transfer frame buffer to SPI device then trigger frame delay - dma_channel_config_t dma_config_fb_transfer = dma_channel_get_default_config(dma_ch_fb_transfer); - channel_config_set_transfer_data_size(&dma_config_fb_transfer, DMA_SIZE_8); // 8-bit transfers - channel_config_set_dreq(&dma_config_fb_transfer, spi_get_dreq(SPI_DEVICE, true)); // pace by SPI_TX DREQ - channel_config_set_chain(&dma_config_fb_transfer, dma_ch_refresh_delay); // chain to frame delay + // transfer the frame buffer to the SPI + // remember to reset the read address after each transfer + dma_ch_transfer_fb = dma_claim_unused_channel(true); + dma_channel_config_t c = dma_channel_get_default_config(dma_ch_transfer_fb); + channel_config_set_transfer_data_size(&c, DMA_SIZE_8); + channel_config_set_dreq(&c, spi_get_dreq(SPI_DEVICE, true)); dma_channel_configure( - dma_ch_fb_transfer, - &dma_config_fb_transfer, - &spi_get_hw(SPI_DEVICE)->dr, // write to SPI data reg (non-incrementing) - frame_buffer, // read from frame buffer (incrementing) + dma_ch_transfer_fb, + &c, + &spi_get_hw(SPI_DEVICE)->dr, // write address (doesn't increment) + frame_buffer, // initial read address dma_encode_transfer_count(count_of(frame_buffer)), false // don't trigger yet ); - - // delay for frame period then trigger buffer transfer - int dma_timer_frame_delay = dma_claim_unused_timer(true); // pacing timer - dma_timer_set_fraction(dma_timer_frame_delay, 1, 0xffff); // slowest possible - uint frame_delay_num_transfers = clock_get_hz(clk_sys) / 0xffff; // number of transfers to get frame delay - dma_channel_config_t dma_config_framerate_delay = dma_channel_get_default_config(dma_ch_refresh_delay); - channel_config_set_read_increment(&dma_config_framerate_delay, false); // don't increment read address - channel_config_set_dreq(&dma_config_framerate_delay, dma_get_timer_dreq(dma_timer_frame_delay)); // use pacing timer - channel_config_set_chain_to(&dma_config_framerate_delay, dma_ch_fb_transfer); // chain to buffer transfer - static uint32_t fb_start = (uint32_t)frame_buffer; - dma_channel_configure( - dma_ch_refresh_delay, - &dma_config_framerate_delay, - &dma_hw->ch[dma_ch_fb_transfer].read_addr, // write to buffer transfer read address reg (non-incrementing) - &fb_start, // read frame buffer address (non-incrementing) - dma_encode_transfer_count(frame_delay_num_transfers), // get required delay - false // don't trigger yet - ); - - // quickly zero the frame buffer - optional if you're short of DMA channels (unlikely!) - dma_channel_config_t dma_config_fb_clear = dma_channel_get_default_config(dma_ch_fb_clear); - channel_config_set_write_increment(&dma_config_fb_clear, true); // increment write address - channel_config_set_read_increment(&dma_config_fb_clear, false); // don't increment read address - static uint32_t fb_clear_value = 0x00000000; // source data for transfer - dma_channel_configure( - dma_ch_fb_clear, - &dma_config_fb_clear, - frame_buffer, // write to frame buffer (32-bit writes) - &fb_clear_value, // read from our clear_value (non-incrementing) - dma_encode_transfer_count(sizeof(frame_buffer) / sizeof(uint32_t)), // 32-bit words in frame buffer - false // don't trigger yet - ); } // initialise the SPI interface void interface_init() { // configure the SPI controller for 8-bit transfers using Motorola SPI mode 0 - spi_init(SPI_DEVICE, DISP_SPI_BITRATE); + spi_init(SPI_DEVICE, DISPLAY_SPI_BITRATE); spi_set_format(SPI_DEVICE, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST); // configure our interface pins @@ -114,66 +83,94 @@ void interface_init() { gpio_set_dir(PIN_DC, GPIO_OUT); gpio_init(PIN_R); gpio_set_dir(PIN_R, GPIO_OUT); +} // reset and initialise the display -void display_init() { - // initialise display - gpio_put(PIN_R, 0); // generate a reset pulse (active low) +void display_reset() { + // send active-low reset pulse + gpio_put(PIN_R, 0); sleep_ms(1); gpio_put(PIN_R, 1); - - // after a short pause, send the commands to initialise the display sleep_ms(1); - gpio_put(PIN_DC, DC_COMMAND_MODE); // put the interface into command mode - uint8_t cmd_list[] = { 0xaf, 0x20, 0x00 }; // commands for 'display on' and 'horizontal addr mode' (see datasheet) + + // wake the display and set horizontal addressing mode + gpio_put(PIN_DC, DC_COMMAND_MODE); + uint8_t cmd_list[] = { 0xaf, 0x20, 0x00 }; spi_write_blocking(SPI_DEVICE, cmd_list, sizeof(cmd_list)); - gpio_put(PIN_DC, DC_DATA_MODE); // return the interface to data mode - - fb_clear(); // clear the frame buffer -} + gpio_put(PIN_DC, DC_DATA_MODE); + // clear the frame buffer and set it to refresh + memset(frame_buffer, 0x00, sizeof(frame_buffer)); + printf_write_ptr = frame_buffer; + display_needs_refresh = true; +} -// clear the frame buffer quickly using a DMA channel -void fb_clear() { - dma_channel_set_write_addr(dma_ch_fb_clear, frame_buffer, true); // reset write address and trigger - dma_channel_wait_for_finish_blocking(dma_ch_fb_clear); +bool frame_refresh_callback(__unused struct repeating_timer *t) { + if (display_needs_refresh) { + // reset read address and start transfer + dma_channel_set_read_addr(dma_ch_transfer_fb, frame_buffer, true); + display_needs_refresh = false; + } + return true; // repeat timer } -// convenience functions to set and clear pixel positions in the frame buffer + +// convenience functions to set/clear pixels in the frame buffer void set_pixel_xy(uint x, uint y) { if (x < NUM_X_PIXELS && y < NUM_Y_PIXELS) { frame_buffer[x + (y / 8) * NUM_X_PIXELS] |= (1 << (y % 8)); + display_needs_refresh = true; } } void clear_pixel_xy(uint x, uint y) { if (x < NUM_X_PIXELS && y < NUM_Y_PIXELS) { frame_buffer[x + (y / 8) * NUM_X_PIXELS] &= ~(1 << (y % 8)); + display_needs_refresh = true; } } +// simple stdout callback for the display +void fb_out_chars(const char *buf, int len) { + while (len) { + memcpy( + (void *)printf_write_ptr, + &font[FONT_BYTES_PER_CODE * (FONT_INDEX_START + (*buf) - FONT_CODE_START)], + FONT_BYTES_PER_CODE + ); + printf_write_ptr += FONT_BYTES_PER_CODE; + buf += 1; + len -= 1; + // TODO: manage scrolling at end of display + } + display_needs_refresh = true; +} + int main(){ stdio_init_all(); - // initialise everything + // initialise the interface and display dma_init(); interface_init(); - display_init(); + display_reset(); + + // start the display referesh timer + struct repeating_timer timer; + add_repeating_timer_ms(FRAME_PERIOD_MS, frame_refresh_callback, NULL, &timer); + + // add a simple stdio driver for the display + stdio_driver_t fb_stdio_driver = { fb_out_chars }; + stdio_set_driver_enabled(&fb_stdio_driver, true); - // start the DMA transfer (automatically repeats every frame period) - dma_channel_start(dma_ch_fb_transfer); + printf("Hello, World!\n"); // anything you write to the frame buffer will now be transferred transparently to the // display - for the memory layout consult the manufacturer's datasheet (reference above). - // NOTE: don't send your own commands or data to the display while it is being controlled - // by the DMA channels, as confusion will result. Do all your interaction via the frame - // buffer. - // simple example: a moving 'snake' int head_x = NUM_Y_PIXELS - 1, head_y = NUM_Y_PIXELS - 1, head_dx = 1, head_dy = 1; - int tail_x = 0, tail_y = 0, tail_dx = 1, tail_dy = 1; + int tail_x = FONT_BYTES_PER_CODE + 1, tail_y = FONT_BYTES_PER_CODE + 1, tail_dx = 1, tail_dy = 1; while(true) { set_pixel_xy(head_x, head_y); clear_pixel_xy(tail_x, tail_y); @@ -183,7 +180,7 @@ int main(){ head_dx = -head_dx; } head_x += head_dx; - if (head_y + head_dy < 0 || head_y + head_dy >= NUM_Y_PIXELS) { + if (head_y + head_dy <= FONT_BYTES_PER_CODE || head_y + head_dy >= NUM_Y_PIXELS) { head_dy = -head_dy; } head_y += head_dy; @@ -193,7 +190,7 @@ int main(){ tail_dx = -tail_dx; } tail_x += tail_dx; - if (tail_y + tail_dy < 0 || tail_y + tail_dy >= NUM_Y_PIXELS) { + if (tail_y + tail_dy <= FONT_BYTES_PER_CODE || tail_y + tail_dy >= NUM_Y_PIXELS) { tail_dy = -tail_dy; } tail_y += tail_dy; From 2951c6e04152146f98cb1cf9e7a658878a8efe6b Mon Sep 17 00:00:00 2001 From: Martin Crossley Date: Sat, 3 Jan 2026 18:08:28 +0000 Subject: [PATCH 5/9] handle scrolling and tabs --- spi/ssd1309_spi_dma/font.h | 6 +-- spi/ssd1309_spi_dma/ssd1309_spi_dma.c | 63 +++++++++++++++++++-------- 2 files changed, 48 insertions(+), 21 deletions(-) diff --git a/spi/ssd1309_spi_dma/font.h b/spi/ssd1309_spi_dma/font.h index 0191a9e94..130cfa8d0 100644 --- a/spi/ssd1309_spi_dma/font.h +++ b/spi/ssd1309_spi_dma/font.h @@ -12,10 +12,10 @@ #include -#define FONT_INDEX_DEFAULT 0 +#define FONT_INDEX_UNDEF 0 #define FONT_INDEX_START 1 -#define FONT_INDEX_END 95 -#define FONT_CODE_START 32 +#define FONT_CODE_FIRST 32 +#define FONT_CODE_LAST 126 #define FONT_BYTES_PER_CODE 8 static const uint8_t font[] = { diff --git a/spi/ssd1309_spi_dma/ssd1309_spi_dma.c b/spi/ssd1309_spi_dma/ssd1309_spi_dma.c index d327c6320..c6e2e459f 100644 --- a/spi/ssd1309_spi_dma/ssd1309_spi_dma.c +++ b/spi/ssd1309_spi_dma/ssd1309_spi_dma.c @@ -23,6 +23,7 @@ #define NUM_X_PIXELS 128 #define NUM_Y_PIXELS 64 #define PIXELS_PER_BYTE 8 +#define TABSTOPS 4 // how often we want to refresh the display from the frame buffer #define FRAME_PERIOD_MS 20 @@ -49,7 +50,7 @@ uint8_t frame_buffer[NUM_X_PIXELS * NUM_Y_PIXELS / PIXELS_PER_BYTE]; int dma_ch_transfer_fb; volatile bool display_needs_refresh; -volatile uint8_t *printf_write_ptr; +volatile uint fb_out_index; // set up the DMA channels void dma_init() { @@ -101,7 +102,7 @@ void display_reset() { // clear the frame buffer and set it to refresh memset(frame_buffer, 0x00, sizeof(frame_buffer)); - printf_write_ptr = frame_buffer; + fb_out_index = 0; display_needs_refresh = true; } @@ -114,6 +115,38 @@ bool frame_refresh_callback(__unused struct repeating_timer *t) { return true; // repeat timer } +// simple stdout driver for the display +void fb_out_chars(const char *buf, int len) { + while (len) { + char code = *buf; + uint font_index; + buf += 1; + len -= 1; + // scroll display if needed (using DMA would almost certainly be OTT) + while (fb_out_index >= sizeof(frame_buffer)) { + memmove(frame_buffer, frame_buffer + NUM_X_PIXELS, sizeof(frame_buffer) - NUM_X_PIXELS); + fb_out_index -= NUM_X_PIXELS; + memset(&frame_buffer[sizeof(frame_buffer) - NUM_X_PIXELS - 1], 0x00, NUM_X_PIXELS); + } + // handle control codes + if (code == '\n') { + fb_out_index = (fb_out_index / NUM_X_PIXELS + 1) * NUM_X_PIXELS; + } else if (code == '\t') { + fb_out_index = (fb_out_index / (TABSTOPS * FONT_BYTES_PER_CODE) + 1) * TABSTOPS * FONT_BYTES_PER_CODE; + } else { + // handle alphanumeric codes + if (code < FONT_CODE_FIRST || code > FONT_CODE_LAST ) { + font_index = FONT_INDEX_UNDEF; + } else { + font_index = FONT_BYTES_PER_CODE * (FONT_INDEX_START + code - FONT_CODE_FIRST); + } + memcpy(&frame_buffer[fb_out_index], &font[font_index], FONT_BYTES_PER_CODE); + fb_out_index += FONT_BYTES_PER_CODE; + } + } + display_needs_refresh = true; +} + // convenience functions to set/clear pixels in the frame buffer void set_pixel_xy(uint x, uint y) { @@ -130,20 +163,13 @@ void clear_pixel_xy(uint x, uint y) { } } -// simple stdout callback for the display -void fb_out_chars(const char *buf, int len) { - while (len) { - memcpy( - (void *)printf_write_ptr, - &font[FONT_BYTES_PER_CODE * (FONT_INDEX_START + (*buf) - FONT_CODE_START)], - FONT_BYTES_PER_CODE - ); - printf_write_ptr += FONT_BYTES_PER_CODE; - buf += 1; - len -= 1; - // TODO: manage scrolling at end of display +// set text output position in rows and columns +// rows go from 0 (top) to NUM_Y_PIXELS / 8 - 1 +// columns go from 0 (left) to NUM_X_PIXELS / 8 - 1 +void set_cursor_pos(uint text_row, uint text_col) { + if (text_row < NUM_Y_PIXELS / PIXELS_PER_BYTE && text_col < NUM_X_PIXELS / FONT_BYTES_PER_CODE) { + fb_out_index = text_row * NUM_X_PIXELS + text_col * FONT_BYTES_PER_CODE; } - display_needs_refresh = true; } @@ -155,15 +181,16 @@ int main(){ interface_init(); display_reset(); - // start the display referesh timer + // start the display refresh timer struct repeating_timer timer; add_repeating_timer_ms(FRAME_PERIOD_MS, frame_refresh_callback, NULL, &timer); - // add a simple stdio driver for the display + // copy stdout to the frame buffer stdio_driver_t fb_stdio_driver = { fb_out_chars }; stdio_set_driver_enabled(&fb_stdio_driver, true); - printf("Hello, World!\n"); + set_cursor_pos(0, 2); + printf("Hello, World\n"); // anything you write to the frame buffer will now be transferred transparently to the // display - for the memory layout consult the manufacturer's datasheet (reference above). From e54125d5f1f1fc6c26cf7f9f480c43ebe1eb97a2 Mon Sep 17 00:00:00 2001 From: Martin Crossley Date: Sat, 3 Jan 2026 21:48:18 +0000 Subject: [PATCH 6/9] code tidy up and testing --- spi/ssd1309_spi_dma/ssd1309_spi_dma.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/spi/ssd1309_spi_dma/ssd1309_spi_dma.c b/spi/ssd1309_spi_dma/ssd1309_spi_dma.c index c6e2e459f..61425644d 100644 --- a/spi/ssd1309_spi_dma/ssd1309_spi_dma.c +++ b/spi/ssd1309_spi_dma/ssd1309_spi_dma.c @@ -45,17 +45,15 @@ #define DC_COMMAND_MODE 0 #define DC_DATA_MODE 1 - // global variables uint8_t frame_buffer[NUM_X_PIXELS * NUM_Y_PIXELS / PIXELS_PER_BYTE]; int dma_ch_transfer_fb; -volatile bool display_needs_refresh; -volatile uint fb_out_index; +volatile bool display_needs_refresh = false; +volatile uint fb_out_index = 0; + -// set up the DMA channels +// configure a DMA channel to transmit the frame buffer over SPI void dma_init() { - // transfer the frame buffer to the SPI - // remember to reset the read address after each transfer dma_ch_transfer_fb = dma_claim_unused_channel(true); dma_channel_config_t c = dma_channel_get_default_config(dma_ch_transfer_fb); channel_config_set_transfer_data_size(&c, DMA_SIZE_8); @@ -94,7 +92,7 @@ void display_reset() { gpio_put(PIN_R, 1); sleep_ms(1); - // wake the display and set horizontal addressing mode + // wake up the display and set horizontal addressing mode gpio_put(PIN_DC, DC_COMMAND_MODE); uint8_t cmd_list[] = { 0xaf, 0x20, 0x00 }; spi_write_blocking(SPI_DEVICE, cmd_list, sizeof(cmd_list)); @@ -106,6 +104,7 @@ void display_reset() { display_needs_refresh = true; } +// this will be called every frame period bool frame_refresh_callback(__unused struct repeating_timer *t) { if (display_needs_refresh) { // reset read address and start transfer @@ -140,6 +139,7 @@ void fb_out_chars(const char *buf, int len) { } else { font_index = FONT_BYTES_PER_CODE * (FONT_INDEX_START + code - FONT_CODE_FIRST); } + // copy bitmap from font table memcpy(&frame_buffer[fb_out_index], &font[font_index], FONT_BYTES_PER_CODE); fb_out_index += FONT_BYTES_PER_CODE; } @@ -181,27 +181,24 @@ int main(){ interface_init(); display_reset(); - // start the display refresh timer + // refresh the display from the frame buffer (if needed) once per frame using DMA struct repeating_timer timer; add_repeating_timer_ms(FRAME_PERIOD_MS, frame_refresh_callback, NULL, &timer); - // copy stdout to the frame buffer + // use a simple driver to copy stdout to the frame buffer stdio_driver_t fb_stdio_driver = { fb_out_chars }; stdio_set_driver_enabled(&fb_stdio_driver, true); + // show some text on the screen set_cursor_pos(0, 2); printf("Hello, World\n"); - // anything you write to the frame buffer will now be transferred transparently to the - // display - for the memory layout consult the manufacturer's datasheet (reference above). - - // simple example: a moving 'snake' + // show a moving 'snake' int head_x = NUM_Y_PIXELS - 1, head_y = NUM_Y_PIXELS - 1, head_dx = 1, head_dy = 1; int tail_x = FONT_BYTES_PER_CODE + 1, tail_y = FONT_BYTES_PER_CODE + 1, tail_dx = 1, tail_dy = 1; while(true) { set_pixel_xy(head_x, head_y); clear_pixel_xy(tail_x, tail_y); - // update head position if (head_x + head_dx < 0 || head_x + head_dx >= NUM_X_PIXELS) { head_dx = -head_dx; @@ -211,7 +208,6 @@ int main(){ head_dy = -head_dy; } head_y += head_dy; - // update tail position if (tail_x + tail_dx < 0 || tail_x + tail_dx >= NUM_X_PIXELS) { tail_dx = -tail_dx; @@ -221,7 +217,6 @@ int main(){ tail_dy = -tail_dy; } tail_y += tail_dy; - sleep_ms(5); } } From 4ab66a210bfc68cabe8300109e9a0d95c5687d74 Mon Sep 17 00:00:00 2001 From: Martin Crossley Date: Sun, 4 Jan 2026 20:35:38 +0000 Subject: [PATCH 7/9] finalise example --- README.md | 1 + spi/CMakeLists.txt | 2 +- .../CMakeLists.txt | 10 +- spi/ssd1309_stdout_spi/README.adoc | 59 +++++++++ .../font.h | 8 +- .../ssd1309_stdout_spi.c} | 119 ++++++++++-------- spi/ssd1309_stdout_spi/wiring_diagram.fzz | Bin 0 -> 35721 bytes spi/ssd1309_stdout_spi/wiring_diagram.png | Bin 0 -> 134031 bytes 8 files changed, 136 insertions(+), 63 deletions(-) rename spi/{ssd1309_spi_dma => ssd1309_stdout_spi}/CMakeLists.txt (51%) create mode 100644 spi/ssd1309_stdout_spi/README.adoc rename spi/{ssd1309_spi_dma => ssd1309_stdout_spi}/font.h (97%) rename spi/{ssd1309_spi_dma/ssd1309_spi_dma.c => ssd1309_stdout_spi/ssd1309_stdout_spi.c} (65%) create mode 100644 spi/ssd1309_stdout_spi/wiring_diagram.fzz create mode 100644 spi/ssd1309_stdout_spi/wiring_diagram.png diff --git a/README.md b/README.md index f43a7339a..c4a3b2b46 100644 --- a/README.md +++ b/README.md @@ -368,6 +368,7 @@ App|Description [spi_dma](spi/spi_dma) | Use DMA to transfer data both to and from the SPI simultaneously. The SPI is configured for loopback. [spi_flash](spi/spi_flash) | Erase, program and read a serial flash device attached to one of the SPI controllers. [spi_master_slave](spi/spi_master_slave) | Demonstrate SPI communication as master and slave. +[ssd1309_stdout_spi](spi/ssd1309_stdout_spi/) | Display text from stdout and simple graphics on an SSD1309-based OLED panel via SPI. [max7219_8x7seg_spi](spi/max7219_8x7seg_spi) | Attaching a Max7219 driving an 8 digit 7 segment display via SPI. [max7219_32x8_spi](spi/max7219_32x8_spi) | Attaching a Max7219 driving an 32x8 LED display via SPI. diff --git a/spi/CMakeLists.txt b/spi/CMakeLists.txt index da825de41..83fb5d9a2 100644 --- a/spi/CMakeLists.txt +++ b/spi/CMakeLists.txt @@ -4,7 +4,7 @@ if (TARGET hardware_spi) add_subdirectory_exclude_platforms(spi_dma) add_subdirectory_exclude_platforms(spi_master_slave) add_subdirectory_exclude_platforms(spi_flash) - add_subdirectory_exclude_platforms(ssd1309_spi_dma) + add_subdirectory_exclude_platforms(ssd1309_stdout_spi) add_subdirectory_exclude_platforms(max7219_32x8_spi) add_subdirectory_exclude_platforms(max7219_8x7seg_spi) else() diff --git a/spi/ssd1309_spi_dma/CMakeLists.txt b/spi/ssd1309_stdout_spi/CMakeLists.txt similarity index 51% rename from spi/ssd1309_spi_dma/CMakeLists.txt rename to spi/ssd1309_stdout_spi/CMakeLists.txt index 26e8f1d00..239a1d4ee 100644 --- a/spi/ssd1309_spi_dma/CMakeLists.txt +++ b/spi/ssd1309_stdout_spi/CMakeLists.txt @@ -1,16 +1,16 @@ -add_executable(ssd1309_spi_dma - ssd1309_spi_dma.c +add_executable(ssd1309_stdout_spi + ssd1309_stdout_spi.c ) # pull in common dependencies and additional hardware support -target_link_libraries(ssd1309_spi_dma +target_link_libraries(ssd1309_stdout_spi pico_stdlib hardware_spi hardware_dma ) # create map/bin/hex file etc. -pico_add_extra_outputs(ssd1309_spi_dma) +pico_add_extra_outputs(ssd1309_stdout_spi) # add url via pico_set_program_url -example_auto_set_url(ssd1309_spi_dma) \ No newline at end of file +example_auto_set_url(ssd1309_stdout_spi) \ No newline at end of file diff --git a/spi/ssd1309_stdout_spi/README.adoc b/spi/ssd1309_stdout_spi/README.adoc new file mode 100644 index 000000000..debd85528 --- /dev/null +++ b/spi/ssd1309_stdout_spi/README.adoc @@ -0,0 +1,59 @@ += Simple graphics and stdout text on an OLED display via SPI + +Ths example displays text and graphics on one of the widely-available small OLED panels based on the *SSD1309* controller. It should also work with compatible devices such as the *SSD1306* (not tested). + +These modules typically support either I2C or SPI. For this example you will need one configured for SPI. + +The code renders content onto a frame buffer that is transferred to the SPI port in the background, by a DMA channel under the control of a frame timer. A simple driver is used to copy _stdout_ to the frame buffer and some basic graphics functions are provided. + +The interface uses one of the Pico's onboard SPI peripherals and two extra GPIO pins as shown below. Note that in SPI mode the SSD1309 is a receive-only device. + +For details of the commands supported by the SSD1309 controller and its addressing modes see the manufacturer's datasheet: https://www.hpinfotech.ro/SSD1309.pdf. + + +== Wiring information + +Wiring up the device requires seven jumpers as follows: + + * Display CS (chip select) -> Pico GP17 (SPI0 CSn), pin 22 + * Display DC (data/command) -> Pico GP20, pin 26 + * Display RES (reset) -> Pico GP21, pin 27 + * Display SDA (MOSI) -> Pico GP19 (SPI0 TX), pin 25 + * Display SCLK (SPI clock) -> Pico GP18 (SPI0 SCK), pin 24 + * Display VDD (3.3v) -> Pico 3V3_OUT, pin 36 + * Display VSS (0v, gnd) -> Pico GND, pin 23 + +The example uses SPI device 0 and powers the display from the Pico 3.3v output. If you power the display from an external supply then ensure that the Pico's logic pins are not exposed to any voltage higher than 3.3v. + +[NOTE] +====== +The pins on your board may be labelled slightly differently to the list above. Check the documentation for your display. + +You can change the code to use different pins if you like, but the ones for CSn, TX and SCK must match your SPI device: see the GPIO Function Select Table in the datasheet. +====== + + +[[wiring_diagram.png]] +[pdfwidth=75%] +.Wiring Diagram for SSD1309 with SPI interface +image::wiring_diagram.png[] + +== List of Files + +CMakeLists.txt:: A file to configure the CMake build system for the example. +ssd1309_stdout_spi.c:: The example code. +font.h:: A basic 8x8 bit font table used by the example. + + +== Bill of Materials + +.A list of materials required for the example +[[SSD1309-bom-table]] +[cols=3] +|=== +| *Item* | *Quantity* | Details +| Breadboard | 1 | generic part +| Raspberry Pi Pico or Pico 2 | 1 | https://www.raspberrypi.com/products/raspberry-pi-pico/ +| SSD1309-based OLED display panel with SPI interface| 1 | generic part +| M/F Jumper wires (assorted colours) | 7 | generic part +|=== \ No newline at end of file diff --git a/spi/ssd1309_spi_dma/font.h b/spi/ssd1309_stdout_spi/font.h similarity index 97% rename from spi/ssd1309_spi_dma/font.h rename to spi/ssd1309_stdout_spi/font.h index 130cfa8d0..fe894b961 100644 --- a/spi/ssd1309_spi_dma/font.h +++ b/spi/ssd1309_stdout_spi/font.h @@ -2,13 +2,13 @@ * Copyright (c) 2026 mjcross * * SPDX-License-Identifier: BSD-3-Clause - */ +**/ // Vertical bitmaps for commonly-used characters. -// Each bitmap is 8 pixels wide and 8 pixels high, with the least -// significant bit at the top. The patterns are based on bitmaps -// originally credited to IBM. +// Each bitmap is 8 pixels wide and 8 pixels high, with the least significant bit +// at the top. The bitmaps were translated from one of the original IBM BIOS fonts +// released over 45yrs ago (see https://int10h.org/oldschool-pc-fonts/) #include diff --git a/spi/ssd1309_spi_dma/ssd1309_spi_dma.c b/spi/ssd1309_stdout_spi/ssd1309_stdout_spi.c similarity index 65% rename from spi/ssd1309_spi_dma/ssd1309_spi_dma.c rename to spi/ssd1309_stdout_spi/ssd1309_stdout_spi.c index 61425644d..f30da4681 100644 --- a/spi/ssd1309_spi_dma/ssd1309_spi_dma.c +++ b/spi/ssd1309_stdout_spi/ssd1309_stdout_spi.c @@ -1,37 +1,38 @@ /** - * Copyright (c) 2025 mjcross + * Copyright (c) 2026 mjcross * * SPDX-License-Identifier: BSD-3-Clause **/ -// An example showing how to drive a ssd1309-based OLED panel from a frame buffer using -// DMA transfers over SPI. It should also work on a ssd1306 device (not tested). +// Copy stdout and/or simple graphics to an OLED display panel based on the ssd1309 +// (or compatible) controller, using a frame buffer transferred by DMA over an SPI interface. // -// To understand the commands and addressing modes for the display refer to -// the manufacturer's datasheet at https://www.hpinfotech.ro/SSD1309.pdf +// For details of the display controller and its commands and addressing modes refer to the +// manufacturer's datasheet at https://www.hpinfotech.ro/SSD1309.pdf #include +#include +#include #include "pico/stdio/driver.h" #include "pico/stdlib.h" #include "hardware/dma.h" #include "hardware/spi.h" -#include "string.h" - #include "font.h" -// dimensions of our OLED display panel +// dimensions of the display panel #define NUM_X_PIXELS 128 #define NUM_Y_PIXELS 64 #define PIXELS_PER_BYTE 8 #define TABSTOPS 4 // how often we want to refresh the display from the frame buffer -#define FRAME_PERIOD_MS 20 +#define FRAME_PERIOD_MS 20 // 50 Hz -// ssd1309 accepts a maximum SPI clock rate of 10 Mbit/sec +// clock rate for the SPI interface +// the ssd1309 is specified up to 10 Mbit/sec #define DISPLAY_SPI_BITRATE 10 * 1000 * 1000 -// define the pins for the SPI interface +// pins to use for the SPI interface // we will use the spi0 peripheral and the following GPIO pins (see the // GPIO function select table in the Pico datasheet). #define SPI_DEVICE spi0 @@ -41,18 +42,18 @@ #define PIN_DC 20 // data/command mode (low for command) #define PIN_R 21 // reset (active low) -// modes for the ssd1309 data/command pin (see ssd1309 datasheet) +// modes for the ssd1309 data/command pin (see the datasheet) #define DC_COMMAND_MODE 0 #define DC_DATA_MODE 1 // global variables -uint8_t frame_buffer[NUM_X_PIXELS * NUM_Y_PIXELS / PIXELS_PER_BYTE]; +uint8_t frame_buffer[ NUM_X_PIXELS * NUM_Y_PIXELS / PIXELS_PER_BYTE ]; int dma_ch_transfer_fb; volatile bool display_needs_refresh = false; -volatile uint fb_out_index = 0; +volatile uint fb_cursor_index = 0; -// configure a DMA channel to transmit the frame buffer over SPI +// configure a dma channel to send the frame buffer over SPI void dma_init() { dma_ch_transfer_fb = dma_claim_unused_channel(true); dma_channel_config_t c = dma_channel_get_default_config(dma_ch_transfer_fb); @@ -60,7 +61,7 @@ void dma_init() { channel_config_set_dreq(&c, spi_get_dreq(SPI_DEVICE, true)); dma_channel_configure( dma_ch_transfer_fb, - &c, + &c, // the channel_config above &spi_get_hw(SPI_DEVICE)->dr, // write address (doesn't increment) frame_buffer, // initial read address dma_encode_transfer_count(count_of(frame_buffer)), @@ -70,7 +71,7 @@ void dma_init() { // initialise the SPI interface void interface_init() { - // configure the SPI controller for 8-bit transfers using Motorola SPI mode 0 + // configure the SPI controller for 8-bit transfers and Motorola SPI mode 0 spi_init(SPI_DEVICE, DISPLAY_SPI_BITRATE); spi_set_format(SPI_DEVICE, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST); @@ -98,40 +99,31 @@ void display_reset() { spi_write_blocking(SPI_DEVICE, cmd_list, sizeof(cmd_list)); gpio_put(PIN_DC, DC_DATA_MODE); - // clear the frame buffer and set it to refresh + // clear the frame buffer and flag it to be transferred memset(frame_buffer, 0x00, sizeof(frame_buffer)); - fb_out_index = 0; + fb_cursor_index = 0; display_needs_refresh = true; } -// this will be called every frame period -bool frame_refresh_callback(__unused struct repeating_timer *t) { - if (display_needs_refresh) { - // reset read address and start transfer - dma_channel_set_read_addr(dma_ch_transfer_fb, frame_buffer, true); - display_needs_refresh = false; - } - return true; // repeat timer -} -// simple stdout driver for the display +// a simple stdout driver for the display void fb_out_chars(const char *buf, int len) { + uint font_index; while (len) { char code = *buf; - uint font_index; buf += 1; len -= 1; - // scroll display if needed (using DMA would almost certainly be OTT) - while (fb_out_index >= sizeof(frame_buffer)) { + while (fb_cursor_index >= sizeof(frame_buffer)) { + // scroll frame buffer (on RP2350 you could use a decementing dma transfer but it's probably overkill) memmove(frame_buffer, frame_buffer + NUM_X_PIXELS, sizeof(frame_buffer) - NUM_X_PIXELS); - fb_out_index -= NUM_X_PIXELS; + fb_cursor_index -= NUM_X_PIXELS; memset(&frame_buffer[sizeof(frame_buffer) - NUM_X_PIXELS - 1], 0x00, NUM_X_PIXELS); } // handle control codes if (code == '\n') { - fb_out_index = (fb_out_index / NUM_X_PIXELS + 1) * NUM_X_PIXELS; + fb_cursor_index = (fb_cursor_index / NUM_X_PIXELS + 1) * NUM_X_PIXELS; } else if (code == '\t') { - fb_out_index = (fb_out_index / (TABSTOPS * FONT_BYTES_PER_CODE) + 1) * TABSTOPS * FONT_BYTES_PER_CODE; + fb_cursor_index = (fb_cursor_index / (TABSTOPS * FONT_BYTES_PER_CODE) + 1) * TABSTOPS * FONT_BYTES_PER_CODE; } else { // handle alphanumeric codes if (code < FONT_CODE_FIRST || code > FONT_CODE_LAST ) { @@ -139,57 +131,80 @@ void fb_out_chars(const char *buf, int len) { } else { font_index = FONT_BYTES_PER_CODE * (FONT_INDEX_START + code - FONT_CODE_FIRST); } - // copy bitmap from font table - memcpy(&frame_buffer[fb_out_index], &font[font_index], FONT_BYTES_PER_CODE); - fb_out_index += FONT_BYTES_PER_CODE; + // copy bitmap to frame buffer and advance cursor + memcpy(&frame_buffer[fb_cursor_index], &font[font_index], FONT_BYTES_PER_CODE); + fb_cursor_index += FONT_BYTES_PER_CODE; } } display_needs_refresh = true; } -// convenience functions to set/clear pixels in the frame buffer -void set_pixel_xy(uint x, uint y) { +// some simple graphics funtions (for the display memory layout see the datasheet) +void set_pixel(uint x, uint y) { if (x < NUM_X_PIXELS && y < NUM_Y_PIXELS) { frame_buffer[x + (y / 8) * NUM_X_PIXELS] |= (1 << (y % 8)); display_needs_refresh = true; } } -void clear_pixel_xy(uint x, uint y) { +void clear_pixel(uint x, uint y) { if (x < NUM_X_PIXELS && y < NUM_Y_PIXELS) { frame_buffer[x + (y / 8) * NUM_X_PIXELS] &= ~(1 << (y % 8)); display_needs_refresh = true; } } -// set text output position in rows and columns -// rows go from 0 (top) to NUM_Y_PIXELS / 8 - 1 -// columns go from 0 (left) to NUM_X_PIXELS / 8 - 1 +void draw_line(int x0, int y0, int x1, int y1) { + int dx = abs (x1 - x0), sx = x0 < x1 ? 1 : -1; + int dy = -abs (y1 - y0), sy = y0 < y1 ? 1 : -1; + int err = dx + dy, e2; + while(true) { + set_pixel (x0, y0); + if (x0 == x1 && y0 == y1) break; + e2 = 2 * err; + if (e2 >= dy) { err += dy; x0 += sx; } + if (e2 <= dx) { err += dx; y0 += sy; } + } + display_needs_refresh = true; +} + + +// set the text output position +// rows go from 0 at the top to NUM_Y_PIXELS/8 - 1 and columns go from 0 on the left to NUM_X_PIXELS/8 - 1 void set_cursor_pos(uint text_row, uint text_col) { if (text_row < NUM_Y_PIXELS / PIXELS_PER_BYTE && text_col < NUM_X_PIXELS / FONT_BYTES_PER_CODE) { - fb_out_index = text_row * NUM_X_PIXELS + text_col * FONT_BYTES_PER_CODE; + fb_cursor_index = text_row * NUM_X_PIXELS + text_col * FONT_BYTES_PER_CODE; + } +} + +// the callback function for our frame-rate timer +bool frame_refresh_callback(__unused struct repeating_timer *t) { + if (display_needs_refresh) { + dma_channel_set_read_addr(dma_ch_transfer_fb, frame_buffer, true); // reset and trigger the dma channel + display_needs_refresh = false; } + return true; // reschedule the timer } int main(){ stdio_init_all(); - // initialise the interface and display + // initialise everything dma_init(); interface_init(); display_reset(); - // refresh the display from the frame buffer (if needed) once per frame using DMA + // start refreshing the display struct repeating_timer timer; add_repeating_timer_ms(FRAME_PERIOD_MS, frame_refresh_callback, NULL, &timer); - // use a simple driver to copy stdout to the frame buffer + // install our simple driver to copy stdout to the frame buffer stdio_driver_t fb_stdio_driver = { fb_out_chars }; stdio_set_driver_enabled(&fb_stdio_driver, true); - // show some text on the screen + // display some text set_cursor_pos(0, 2); printf("Hello, World\n"); @@ -197,9 +212,8 @@ int main(){ int head_x = NUM_Y_PIXELS - 1, head_y = NUM_Y_PIXELS - 1, head_dx = 1, head_dy = 1; int tail_x = FONT_BYTES_PER_CODE + 1, tail_y = FONT_BYTES_PER_CODE + 1, tail_dx = 1, tail_dy = 1; while(true) { - set_pixel_xy(head_x, head_y); - clear_pixel_xy(tail_x, tail_y); - // update head position + set_pixel(head_x, head_y); + clear_pixel(tail_x, tail_y); if (head_x + head_dx < 0 || head_x + head_dx >= NUM_X_PIXELS) { head_dx = -head_dx; } @@ -208,7 +222,6 @@ int main(){ head_dy = -head_dy; } head_y += head_dy; - // update tail position if (tail_x + tail_dx < 0 || tail_x + tail_dx >= NUM_X_PIXELS) { tail_dx = -tail_dx; } diff --git a/spi/ssd1309_stdout_spi/wiring_diagram.fzz b/spi/ssd1309_stdout_spi/wiring_diagram.fzz new file mode 100644 index 0000000000000000000000000000000000000000..487d728f7a767293c258ef3da4839d2ab8cff24a GIT binary patch literal 35721 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 xAJ4_Ft%V Date: Mon, 5 Jan 2026 21:29:18 +0000 Subject: [PATCH 8/9] correct typo in README --- spi/ssd1309_stdout_spi/README.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spi/ssd1309_stdout_spi/README.adoc b/spi/ssd1309_stdout_spi/README.adoc index debd85528..88842953d 100644 --- a/spi/ssd1309_stdout_spi/README.adoc +++ b/spi/ssd1309_stdout_spi/README.adoc @@ -1,6 +1,6 @@ = Simple graphics and stdout text on an OLED display via SPI -Ths example displays text and graphics on one of the widely-available small OLED panels based on the *SSD1309* controller. It should also work with compatible devices such as the *SSD1306* (not tested). +This example displays text and graphics on one of the widely-available small OLED panels based on the *SSD1309* controller. It should also work with compatible devices such as the *SSD1306* (not tested). These modules typically support either I2C or SPI. For this example you will need one configured for SPI. @@ -56,4 +56,4 @@ font.h:: A basic 8x8 bit font table used by the example. | Raspberry Pi Pico or Pico 2 | 1 | https://www.raspberrypi.com/products/raspberry-pi-pico/ | SSD1309-based OLED display panel with SPI interface| 1 | generic part | M/F Jumper wires (assorted colours) | 7 | generic part -|=== \ No newline at end of file +|=== From 2672c8a1f3d49aec8a16a82600bda17cd3bcb370 Mon Sep 17 00:00:00 2001 From: mjcross Date: Tue, 6 Jan 2026 09:36:52 +0000 Subject: [PATCH 9/9] fix typo in comment --- spi/ssd1309_stdout_spi/ssd1309_stdout_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spi/ssd1309_stdout_spi/ssd1309_stdout_spi.c b/spi/ssd1309_stdout_spi/ssd1309_stdout_spi.c index f30da4681..5c3de42aa 100644 --- a/spi/ssd1309_stdout_spi/ssd1309_stdout_spi.c +++ b/spi/ssd1309_stdout_spi/ssd1309_stdout_spi.c @@ -114,7 +114,7 @@ void fb_out_chars(const char *buf, int len) { buf += 1; len -= 1; while (fb_cursor_index >= sizeof(frame_buffer)) { - // scroll frame buffer (on RP2350 you could use a decementing dma transfer but it's probably overkill) + // scroll frame buffer (on RP2350 you could use a decrementing dma transfer but it's probably overkill) memmove(frame_buffer, frame_buffer + NUM_X_PIXELS, sizeof(frame_buffer) - NUM_X_PIXELS); fb_cursor_index -= NUM_X_PIXELS; memset(&frame_buffer[sizeof(frame_buffer) - NUM_X_PIXELS - 1], 0x00, NUM_X_PIXELS);