Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Inky what #14

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/raspberry_pi_inky_phat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use std::{fs, io};
// see https://github.com/rust-embedded/rust-sysfs-gpio/issues/5 and follow-up issues

const ROWS: u16 = 212;
const COLS: u8 = 104;
const COLS: u16 = 104;

#[rustfmt::skip]
const LUT: [u8; 70] = [
Expand Down
87 changes: 79 additions & 8 deletions src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,6 @@ pub enum BufCommand<'buf> {
WriteLUT(&'buf [u8]),
}

fn u16_as_u8(val: u16) -> [u8; 2] {
[(val & 0xFF00 >> 8) as u8, (val & 0xFF) as u8]
}

/// Populates data buffer (array) and returns a pair (tuple) with command and
/// appropriately sized slice into populated buffer.
/// E.g.
Expand Down Expand Up @@ -219,7 +215,7 @@ impl Command {
let mut buf = [0u8; 4];
let (command, data) = match *self {
DriverOutputControl(gate_lines, scanning_seq_and_dir) => {
let [upper, lower] = u16_as_u8(gate_lines);
let [upper, lower] = gate_lines.to_be_bytes();
pack!(buf, 0x01, [lower, upper, scanning_seq_and_dir])
}
GateDrivingVoltage(voltages) => pack!(buf, 0x03, [voltages]),
Expand All @@ -229,7 +225,7 @@ impl Command {
}
GateScanStartPostion(position) => {
debug_assert!(Contains::contains(&(0..MAX_GATES), position));
let [upper, lower] = u16_as_u8(position);
let [upper, lower] = position.to_be_bytes();
pack!(buf, 0x0F, [lower, upper])
}
DeepSleepMode(mode) => {
Expand Down Expand Up @@ -281,8 +277,8 @@ impl Command {
BorderWaveform(border_waveform) => pack!(buf, 0x3C, [border_waveform]),
StartEndXPosition(start, end) => pack!(buf, 0x44, [start, end]),
StartEndYPosition(start, end) => {
let [start_upper, start_lower] = u16_as_u8(start);
let [end_upper, end_lower] = u16_as_u8(end);
let [start_upper, start_lower] = start.to_be_bytes();
let [end_upper, end_lower] = end.to_be_bytes();
pack!(buf, 0x45, [start_lower, start_upper, end_lower, end_upper])
}
// AutoWriteRedPattern(u8) => {
Expand Down Expand Up @@ -342,3 +338,78 @@ where
item >= *self.start() && item <= *self.end()
}
}

#[cfg(test)]
mod tests {
use super::*;

struct MockInterface {
data: [u8; 256],
offset: usize,
}

impl MockInterface {
fn new() -> Self {
MockInterface {
data: [0; 256],
offset: 0,
}
}

fn write(&mut self, byte: u8) {
self.data[self.offset] = byte;
self.offset += 1;
}

fn data(&self) -> &[u8] {
&self.data[0..self.offset]
}
}

impl DisplayInterface for MockInterface {
type Error = ();

/// Send a command to the controller.
///
/// Prefer calling `execute` on a [Commmand](../command/enum.Command.html) over calling this
/// directly.
fn send_command(&mut self, command: u8) -> Result<(), Self::Error> {
self.write(command);
Ok(())
}

/// Send data for a command.
fn send_data(&mut self, data: &[u8]) -> Result<(), Self::Error> {
for byte in data {
self.write(*byte)
}
Ok(())
}

/// Reset the controller.
fn reset<D: hal::blocking::delay::DelayMs<u8>>(&mut self, _delay: &mut D) {
self.data = [0; 256];
self.offset = 0;
}

/// Wait for the controller to indicate it is not busy.
fn busy_wait(&self) {
// nop
}
}

#[test]
fn test_command_execute() {
let mut interface = MockInterface::new();
let upper = 0x12;
let lower = 0x34;
let scanning_seq_and_dir = 1;
let command = Command::DriverOutputControl(0x1234, scanning_seq_and_dir);

command.execute(&mut interface).unwrap();
assert_eq!(
interface.data(),
&[0x01, lower, upper, scanning_seq_and_dir]
);
}
}
20 changes: 10 additions & 10 deletions src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ use interface::DisplayInterface;

// Max display resolution is 160x296
/// The maximum number of rows supported by the controller
pub const MAX_GATE_OUTPUTS: u16 = 296;
pub const MAX_GATE_OUTPUTS: u16 = 300;
/// The maximum number of columns supported by the controller
pub const MAX_SOURCE_OUTPUTS: u8 = 160;
pub const MAX_SOURCE_OUTPUTS: u16 = 400;

// Magic numbers from the data sheet
const ANALOG_BLOCK_CONTROL_MAGIC: u8 = 0x54;
Expand All @@ -25,7 +25,7 @@ pub struct Dimensions {
/// The number of columns the display has.
///
/// Must be less than or equal to MAX_SOURCE_OUTPUTS.
pub cols: u8,
pub cols: u16,
}

/// Represents the physical rotation of the display relative to the native orientation.
Expand Down Expand Up @@ -91,23 +91,23 @@ where
Command::DriverOutputControl(self.config.dimensions.rows, 0x00)
.execute(&mut self.interface)?;

Command::GateDrivingVoltage(0x17).execute(&mut self.interface)?;
Command::SourceDrivingVoltage(0x41, 0xAC, 0x32).execute(&mut self.interface)?;
self.config.dummy_line_period.execute(&mut self.interface)?;
self.config.gate_line_width.execute(&mut self.interface)?;
self.config.data_entry_mode.execute(&mut self.interface)?;

// Command::GateDrivingVoltage(0b10000 | 0b0001);
// Command::SourceDrivingVoltage(0x2D, 0xB2, 0x22).execute(&mut self.interface)?;
self.config.write_vcom.execute(&mut self.interface)?;

// POR is HiZ. Need pull from config
// Command::BorderWaveform(u8).execute(&mut self.interface)?;
Command::BorderWaveform(0b00110001).execute(&mut self.interface)?;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of / in addition to calling this in init, it might be nice to expose this via a set_border function.


if let Some(ref write_lut) = self.config.write_lut {
write_lut.execute(&mut self.interface)?;
}

self.config.data_entry_mode.execute(&mut self.interface)?;

let end = self.config.dimensions.cols / 8 - 1;
let end = (self.config.dimensions.cols / 8 - 1) as u8;
Command::StartEndXPosition(0, end).execute(&mut self.interface)?;
Command::StartEndYPosition(0, self.config.dimensions.rows).execute(&mut self.interface)?;

Expand All @@ -125,7 +125,7 @@ where
delay: &mut D,
) -> Result<(), I::Error> {
// Write the B/W RAM
let buf_limit = libm::ceilf((self.rows() * self.cols() as u16) as f32 / 8.) as usize;
let buf_limit = libm::ceilf((self.rows() as usize * self.cols() as usize) as f32 / 8.) as usize;
Command::XAddress(0).execute(&mut self.interface)?;
Command::YAddress(0).execute(&mut self.interface)?;
BufCommand::WriteBlackData(&black[..buf_limit]).execute(&mut self.interface)?;
Expand Down Expand Up @@ -162,7 +162,7 @@ where
}

/// Returns the number of columns the display has.
pub fn cols(&self) -> u8 {
pub fn cols(&self) -> u16 {
self.config.dimensions.cols
}

Expand Down
2 changes: 1 addition & 1 deletion src/graphics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ mod tests {
use {Builder, Color, Dimensions, Display, DisplayInterface, GraphicDisplay, Rotation};

const ROWS: u16 = 3;
const COLS: u8 = 8;
const COLS: u16 = 8;
const BUFFER_SIZE: usize = (ROWS * COLS as u16) as usize / 8;

struct MockInterface {}
Expand Down