-
Notifications
You must be signed in to change notification settings - Fork 12
Use display-interface crate to abstract data interface #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
s-ol
wants to merge
8
commits into
edarc:master
Choose a base branch
from
s-ol:display-interface
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
158a7ab
update for embedded-hal v1.0
s-ol 336c6f1
Use display-interface crate to abstract data interface
s-ol d475d4b
Expose remapping in Config, remove PersistentConfig
s-ol 41ff6d9
display-interface: update documentation
s-ol f096ba7
display-interface: add nrf52-graphics-embassy example
s-ol f3ccfdd
Align imports - Single use statement per crate/cfg
s-ol e05d054
display-interface: add back TestSpyInterface
s-ol 1e9561f
update tests (init command order, grayscale table)
s-ol File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| /target | ||
| embedded-examples/*/target | ||
| **/*.rs.bk | ||
| Cargo.lock | ||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | ||
| # replace nRF82810_xxAA with your chip as listed in `probe-rs chip list` | ||
| runner = "probe-rs run --chip nRF52840_xxAA" | ||
|
|
||
| [build] | ||
| target = "thumbv7em-none-eabi" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| [package] | ||
| name = "ssd1322-examples" | ||
| license = "MIT OR Apache-2.0" | ||
| edition = "2018" | ||
| publish = false | ||
|
|
||
| [dependencies] | ||
| embassy-sync = "0.7.2" | ||
| embassy-time = "0.5" | ||
| embassy-executor = { version = "0.9.0", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } | ||
| embassy-nrf = { version = "0.8.0", features = ["nrf52840", "time-driver-rtc1", "time", "nfc-pins-as-gpio"] } | ||
|
|
||
| ssd1322 = { path = "../.." } | ||
|
|
||
| embedded-hal = "1.0" | ||
| embedded-hal-bus = { version = "0.3", features = ["async"] } | ||
| embedded-graphics = "0.8" | ||
|
|
||
| cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } | ||
| cortex-m-rt = "0.7.0" | ||
| panic-probe = { version = "1.0.0" } | ||
| display-interface-spi = "0.5.0" | ||
|
|
||
| [profile.release] | ||
| debug = 2 | ||
|
|
||
| [package.metadata.embassy] | ||
| build = [{ target = "thumbv7em-none-eabi" }] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| //! This build script copies the `memory.x` file from the crate root into | ||
| //! a directory where the linker can always find it at build time. | ||
| //! For many projects this is optional, as the linker always searches the | ||
| //! project root directory -- wherever `Cargo.toml` is. However, if you | ||
| //! are using a workspace or have a more complicated build setup, this | ||
| //! build script becomes required. Additionally, by requesting that | ||
| //! Cargo re-run the build script whenever `memory.x` is changed, | ||
| //! updating `memory.x` ensures a rebuild of the application with the | ||
| //! new memory settings. | ||
|
|
||
| use std::env; | ||
| use std::fs::File; | ||
| use std::io::Write; | ||
| use std::path::PathBuf; | ||
|
|
||
| fn main() { | ||
| // Put `memory.x` in our output directory and ensure it's | ||
| // on the linker search path. | ||
| let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); | ||
| File::create(out.join("memory.x")) | ||
| .unwrap() | ||
| .write_all(include_bytes!("memory.x")) | ||
| .unwrap(); | ||
| println!("cargo:rustc-link-search={}", out.display()); | ||
|
|
||
| // By default, Cargo will re-run a build script whenever | ||
| // any file in the project changes. By specifying `memory.x` | ||
| // here, we ensure the build script is only re-run when | ||
| // `memory.x` is changed. | ||
| println!("cargo:rerun-if-changed=memory.x"); | ||
|
|
||
| println!("cargo:rustc-link-arg-bins=--nmagic"); | ||
| println!("cargo:rustc-link-arg-bins=-Tlink.x"); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| MEMORY | ||
| { | ||
|
|
||
| FLASH (rx) : ORIGIN = 0x26000 , LENGTH = 0xED000 - 0x26000 | ||
| RAM (rwx) : ORIGIN = 0x20006000, LENGTH = 0x20040000 - 0x20006000 | ||
|
|
||
| /* | ||
| FLASH : ORIGIN = 0x00000000, LENGTH = 256K | ||
| RAM : ORIGIN = 0x20000000, LENGTH = 24K | ||
| */ | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| //! Full example code for setting up an SSD1322 display and drawing to it using | ||
| //! `embedded_graphics`. This runs on an NRF52840, using a Newhaven Displays NHD-2.7-12864WD*. | ||
|
|
||
| #![no_std] | ||
| #![no_main] | ||
|
|
||
| use embassy_executor::Spawner; | ||
| use embassy_nrf::gpio::{Level, Output, OutputDrive}; | ||
| use embassy_nrf::{bind_interrupts, peripherals, spim}; | ||
| use embassy_time::Timer; | ||
| use embedded_hal_bus::spi as spi_bus; | ||
|
|
||
| use display_interface_spi::SPIInterface; | ||
| use embedded_graphics::{ | ||
| framebuffer::{buffer_size, Framebuffer}, | ||
| pixelcolor::{raw::LittleEndian, Gray4}, | ||
| prelude::*, | ||
| primitives::{Line, PrimitiveStyle}, | ||
| }; | ||
| use ssd1322 as oled; | ||
|
|
||
| use panic_probe as _; | ||
|
|
||
| bind_interrupts!(struct Irqs { | ||
| SPIM3 => spim::InterruptHandler<peripherals::SPI3>; | ||
| }); | ||
|
|
||
| #[embassy_executor::main] | ||
| async fn main(_spawner: Spawner) { | ||
| let p = embassy_nrf::init(Default::default()); | ||
|
|
||
| let pin_rst = p.P0_05; | ||
| let pin_sck = p.P1_12; | ||
| let pin_sdo = p.P1_14; | ||
| let pin_cs = p.P1_15; | ||
| let pin_dc = p.P1_13; | ||
| let spi_instance = p.SPI3; | ||
|
|
||
| // My dev board has a switchable power regulator, turn that on | ||
| Output::new(p.P0_21, Level::High, OutputDrive::Standard).persist(); | ||
|
|
||
| // Assert the display's /RESET. | ||
| let mut out_rst = Output::new(pin_rst, Level::Low, OutputDrive::Standard); | ||
| Timer::after_millis(2).await; | ||
| out_rst.set_high(); | ||
| Timer::after_millis(2).await; | ||
|
|
||
| // Set up the push-pull outputs for CS and D/C signals. | ||
| let out_cs = Output::new(pin_cs, Level::High, OutputDrive::Standard); | ||
| let out_dc = Output::new(pin_dc, Level::High, OutputDrive::Standard); | ||
|
|
||
| // Set up the SPI master interface. | ||
| let mut spi_config = spim::Config::default(); | ||
| spi_config.frequency = spim::Frequency::M8; | ||
| let spi_bus = spim::Spim::new_txonly(spi_instance, Irqs, pin_sck, pin_sdo, spi_config); | ||
| let spi_dev = spi_bus::ExclusiveDevice::new(spi_bus, out_cs, embassy_time::Delay).unwrap(); | ||
|
|
||
| // Wrap all I/O in the `display-interface` SPI implementation. | ||
| // This is what the `ssd1322` crate interacts with. | ||
| let spi_iface = SPIInterface::new(spi_dev, out_dc); | ||
|
|
||
| // Create the Display instance. | ||
| let mut display = oled::DisplayAsync::new( | ||
| spi_iface, | ||
| oled::PixelCoord(256, 64), // double width because of duplicate pixels, see below | ||
| oled::PixelCoord(56 * 2, 0), | ||
| ); | ||
|
|
||
| display | ||
| .init( | ||
| oled::ConfigAsync::new( | ||
| oled::ComScanDirection::RowZeroLast, | ||
| oled::ComLayout::Progressive, | ||
| ) | ||
| .column_remap(oled::command::ColumnRemap::Reverse) | ||
| .clock_fosc_divset(9, 1) | ||
| .display_enhancements(true, true) | ||
| .contrast_current(0x7f) | ||
| .phase_lengths(5, 15) | ||
| .precharge_voltage(0x1f) | ||
| .com_deselect_voltage(0x04), | ||
| ) | ||
| .await | ||
| .unwrap(); | ||
|
|
||
| let mut fb = | ||
| Framebuffer::<Gray4, _, LittleEndian, 128, 64, { buffer_size::<Gray4>(128, 64) }>::new(); | ||
|
|
||
| let mut i = 0; | ||
| let mut shade = 0; | ||
| loop { | ||
| // fb.clear(Gray4::BLACK).unwrap(); | ||
|
|
||
| if i > 128 + 64 { | ||
| i = (i + 1) % 8; | ||
| shade = (shade + 1) % 16; | ||
| } | ||
|
|
||
| let point = if i < 128 { | ||
| Point::new(i, 0) | ||
| } else { | ||
| Point::new(127, i - 128) | ||
| }; | ||
|
|
||
| Line::new(Point::new(0, 64), point) | ||
| .into_styled(PrimitiveStyle::with_stroke(Gray4::new(16 - shade), 1)) | ||
| .draw(&mut fb) | ||
| .unwrap(); | ||
|
|
||
| i += 8; | ||
|
|
||
| // the NHD-2.7-12864WD is a little odd in that each visible pixel is driven as two | ||
| // consecutive virtual pixels. This duplicates each nibble to account for that. | ||
| let pixels = fb.data().iter().flat_map(|n| { | ||
| let upper = n & 0xf0; | ||
| let lower = n & 0x0f; | ||
| [upper | (upper >> 4), lower | (lower << 4)] | ||
| }); | ||
|
|
||
| // send framebuffer to display: get a region and send the packed pixel data. | ||
| display | ||
| .region(oled::PixelCoord(0, 0), oled::PixelCoord(256, 64)) | ||
| .unwrap() | ||
| .draw_packed(pixels) | ||
| .await | ||
| .unwrap(); | ||
|
|
||
| Timer::after_millis(1).await; | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this is common, maybe it's worth including support for this? I may open an issue and see if anyone +1's it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have no clue but found this to be rather poorly documented and some other people I've talked to also seem to have found it rather odd, see mastodon thread and monome norns ssd1322 driver code for example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually doing a web search now that I know what's up it does seem like there might be at least one other manufacturer doing something similar:
https://forum.arduino.cc/t/using-u8glib-with-ssd1322-controller-and-128x64-oled/363454/9
and it seems i'm not the only person that struggled to find documentation for this, so maybe sticking a heads-up in the main library comment would help someone out:
https://www.reddit.com/r/embedded/comments/1n5mjac/cant_get_proper_output_on_ssd1322based_128x64/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey. I've also stumbled upon this issue while trying to use this library. The workaround of using a double-width
Framebufferdoes get it to render content on the full display, but that's still not ideal as text and shapes get squished horizontally, so "proper" support would be very much appreciated :)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@supertassu if you take a look at the code sample this comment thread is in, I'm actually using a "normal" framebuffer at the true aspect ratio, and the data is duplicated just while writing it out by modifying the data while iterating with
flat_map: