Skip to content

Commit 5c7c056

Browse files
eldruinjamwaffles
authored andcommitted
Use the embedded-hal::digital::v2::OutputPin traits (#8)
* Forward communication errors * Use fallible OutputPin traits
1 parent 67dc7e0 commit 5c7c056

File tree

9 files changed

+105
-81
lines changed

9 files changed

+105
-81
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ branch = "master"
1616
repository = "jamwaffles/sh1106"
1717

1818
[dependencies]
19-
embedded-hal = "0.2.2"
19+
embedded-hal = "0.2.3"
2020

2121
[dependencies.embedded-graphics]
2222
optional = true

src/builder.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
//! ```
4242
4343
use hal;
44-
use hal::digital::OutputPin;
44+
use hal::digital::v2::OutputPin;
4545

4646
use crate::displayrotation::DisplayRotation;
4747
use crate::displaysize::DisplaySize;
@@ -77,9 +77,9 @@ impl Builder {
7777
}
7878
}
7979

80-
impl<CS> Builder<CS>
80+
impl<CS, PinE> Builder<CS>
8181
where
82-
CS: OutputPin,
82+
CS: OutputPin<Error = PinE>,
8383
{
8484
/// Set the size of the display. Supported sizes are defined by [DisplaySize].
8585
pub fn with_size(self, display_size: DisplaySize) -> Self {
@@ -116,9 +116,9 @@ where
116116
}
117117

118118
/// Finish the builder and use I2C to communicate with the display
119-
pub fn connect_i2c<I2C>(self, i2c: I2C) -> DisplayMode<RawMode<I2cInterface<I2C>>>
119+
pub fn connect_i2c<I2C, CommE>(self, i2c: I2C) -> DisplayMode<RawMode<I2cInterface<I2C>>>
120120
where
121-
I2C: hal::blocking::i2c::Write,
121+
I2C: hal::blocking::i2c::Write<Error = CommE>,
122122
{
123123
let properties = DisplayProperties::new(
124124
I2cInterface::new(i2c, self.i2c_addr),
@@ -129,14 +129,16 @@ where
129129
}
130130

131131
/// Finish the builder and use SPI to communicate with the display
132-
pub fn connect_spi<SPI, DC>(
132+
pub fn connect_spi<SPI, DC, CommE>(
133133
self,
134134
spi: SPI,
135135
dc: DC,
136136
) -> DisplayMode<RawMode<SpiInterface<SPI, DC, CS>>>
137137
where
138-
SPI: hal::blocking::spi::Transfer<u8> + hal::blocking::spi::Write<u8>,
139-
DC: OutputPin,
138+
SPI: hal::blocking::spi::Transfer<u8, Error = CommE>
139+
+ hal::blocking::spi::Write<u8, Error = CommE>,
140+
DC: OutputPin<Error = PinE>,
141+
CS: OutputPin<Error = PinE>,
140142
{
141143
let properties = DisplayProperties::new(
142144
SpiInterface::new(spi, dc, self.spi_cs),
@@ -152,6 +154,11 @@ where
152154
pub struct NoOutputPin;
153155

154156
impl OutputPin for NoOutputPin {
155-
fn set_low(&mut self) {}
156-
fn set_high(&mut self) {}
157+
type Error = ();
158+
fn set_low(&mut self) -> Result<(), ()> {
159+
Ok(())
160+
}
161+
fn set_high(&mut self) -> Result<(), ()> {
162+
Ok(())
163+
}
157164
}

src/command.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ pub enum Command {
5151

5252
impl Command {
5353
/// Send command to sh1106
54-
pub fn send<DI>(self, iface: &mut DI) -> Result<(), ()>
54+
pub fn send<DI>(self, iface: &mut DI) -> Result<(), DI::Error>
5555
where
5656
DI: DisplayInterface,
5757
{
@@ -83,9 +83,7 @@ impl Command {
8383
};
8484

8585
// Send command over the interface
86-
iface.send_commands(&data[0..len])?;
87-
88-
Ok(())
86+
iface.send_commands(&data[0..len])
8987
}
9088
}
9189

src/interface/i2c.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use hal;
44

55
use super::DisplayInterface;
66
use crate::command::Page;
7+
use crate::Error;
78

89
// TODO: Add to prelude
910
/// sh1106 I2C communication interface
@@ -22,23 +23,27 @@ where
2223
}
2324
}
2425

25-
impl<I2C> DisplayInterface for I2cInterface<I2C>
26+
impl<I2C, CommE> DisplayInterface for I2cInterface<I2C>
2627
where
27-
I2C: hal::blocking::i2c::Write,
28+
I2C: hal::blocking::i2c::Write<Error = CommE>,
2829
{
29-
fn send_commands(&mut self, cmds: &[u8]) -> Result<(), ()> {
30+
type Error = Error<CommE, ()>;
31+
32+
fn init(&mut self) -> Result<(), Self::Error> {
33+
Ok(())
34+
}
35+
36+
fn send_commands(&mut self, cmds: &[u8]) -> Result<(), Self::Error> {
3037
// Copy over given commands to new aray to prefix with command identifier
3138
let mut writebuf: [u8; 8] = [0; 8];
3239
writebuf[1..=cmds.len()].copy_from_slice(&cmds);
3340

3441
self.i2c
3542
.write(self.addr, &writebuf[..=cmds.len()])
36-
.map_err(|_| ())?;
37-
38-
Ok(())
43+
.map_err(Error::Comm)
3944
}
4045

41-
fn send_data(&mut self, buf: &[u8]) -> Result<(), ()> {
46+
fn send_data(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
4247
// Display is always 128px wide
4348
const CHUNKLEN: usize = 128;
4449

@@ -70,9 +75,9 @@ where
7075
0x10, // Upper column address (always zero, base is 10h)
7176
],
7277
)
73-
.map_err(|_| ())?;
78+
.map_err(Error::Comm)?;
7479

75-
self.i2c.write(self.addr, &writebuf).map_err(|_| ())?;
80+
self.i2c.write(self.addr, &writebuf).map_err(Error::Comm)?;
7681

7782
page += 1;
7883
}

src/interface/mod.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,15 @@ pub mod spi;
5252

5353
/// A method of communicating with sh1106
5454
pub trait DisplayInterface {
55+
/// Interface error type
56+
type Error;
57+
58+
/// Initialize device.
59+
fn init(&mut self) -> Result<(), Self::Error>;
5560
/// Send a batch of up to 8 commands to display.
56-
fn send_commands(&mut self, cmd: &[u8]) -> Result<(), ()>;
61+
fn send_commands(&mut self, cmd: &[u8]) -> Result<(), Self::Error>;
5762
/// Send data to display.
58-
fn send_data(&mut self, buf: &[u8]) -> Result<(), ()>;
63+
fn send_data(&mut self, buf: &[u8]) -> Result<(), Self::Error>;
5964
}
6065

6166
pub use self::i2c::I2cInterface;

src/interface/spi.rs

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
//! sh1106 SPI interface
22
33
use hal;
4-
use hal::digital::OutputPin;
4+
use hal::digital::v2::OutputPin;
55

66
use super::DisplayInterface;
7+
use crate::Error;
78

89
/// SPI display interface.
910
///
@@ -14,48 +15,48 @@ pub struct SpiInterface<SPI, DC, CS> {
1415
cs: CS,
1516
}
1617

17-
impl<SPI, DC, CS> SpiInterface<SPI, DC, CS>
18+
impl<SPI, DC, CS, CommE, PinE> SpiInterface<SPI, DC, CS>
1819
where
19-
SPI: hal::blocking::spi::Write<u8>,
20-
DC: OutputPin,
21-
CS: OutputPin,
20+
SPI: hal::blocking::spi::Write<u8, Error = CommE>,
21+
DC: OutputPin<Error = PinE>,
22+
CS: OutputPin<Error = PinE>,
2223
{
2324
/// Create new SPI interface for communciation with sh1106
24-
pub fn new(spi: SPI, dc: DC, mut cs: CS) -> Self {
25-
cs.set_high();
26-
25+
pub fn new(spi: SPI, dc: DC, cs: CS) -> Self {
2726
Self { spi, dc, cs }
2827
}
2928
}
3029

31-
impl<SPI, DC, CS> DisplayInterface for SpiInterface<SPI, DC, CS>
30+
impl<SPI, DC, CS, CommE, PinE> DisplayInterface for SpiInterface<SPI, DC, CS>
3231
where
33-
SPI: hal::blocking::spi::Write<u8>,
34-
DC: OutputPin,
35-
CS: OutputPin,
32+
SPI: hal::blocking::spi::Write<u8, Error = CommE>,
33+
DC: OutputPin<Error = PinE>,
34+
CS: OutputPin<Error = PinE>,
3635
{
37-
fn send_commands(&mut self, cmds: &[u8]) -> Result<(), ()> {
38-
self.cs.set_low();
39-
self.dc.set_low();
36+
type Error = Error<CommE, PinE>;
37+
38+
fn init(&mut self) -> Result<(), Self::Error> {
39+
self.cs.set_high().map_err(Error::Pin)
40+
}
4041

41-
self.spi.write(&cmds).map_err(|_| ())?;
42+
fn send_commands(&mut self, cmds: &[u8]) -> Result<(), Self::Error> {
43+
self.cs.set_low().map_err(Error::Pin)?;
44+
self.dc.set_low().map_err(Error::Pin)?;
4245

43-
self.dc.set_high();
44-
self.cs.set_high();
46+
self.spi.write(&cmds).map_err(Error::Comm)?;
4547

46-
Ok(())
48+
self.dc.set_high().map_err(Error::Pin)?;
49+
self.cs.set_high().map_err(Error::Pin)
4750
}
4851

49-
fn send_data(&mut self, buf: &[u8]) -> Result<(), ()> {
50-
self.cs.set_low();
52+
fn send_data(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
53+
self.cs.set_low().map_err(Error::Pin)?;
5154

5255
// 1 = data, 0 = command
53-
self.dc.set_high();
54-
55-
self.spi.write(&buf).map_err(|_| ())?;
56+
self.dc.set_high().map_err(Error::Pin)?;
5657

57-
self.cs.set_high();
58+
self.spi.write(&buf).map_err(Error::Comm)?;
5859

59-
Ok(())
60+
self.cs.set_high().map_err(Error::Pin)
6061
}
6162
}

src/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,15 @@
9696
#![deny(unused_import_braces)]
9797
#![deny(unused_qualifications)]
9898

99+
/// Errors in this crate
100+
#[derive(Debug)]
101+
pub enum Error<CommE, PinE> {
102+
/// Communication error
103+
Comm(CommE),
104+
/// Pin setting error
105+
Pin(PinE),
106+
}
107+
99108
extern crate embedded_hal as hal;
100109

101110
pub mod builder;

src/mode/graphics.rs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@
1616
//! ```
1717
1818
use hal::blocking::delay::DelayMs;
19-
use hal::digital::OutputPin;
19+
use hal::digital::v2::OutputPin;
2020

2121
use crate::displayrotation::DisplayRotation;
2222
use crate::displaysize::DisplaySize;
2323
use crate::interface::DisplayInterface;
2424
use crate::mode::displaymode::DisplayModeTrait;
2525
use crate::properties::DisplayProperties;
26+
use crate::Error;
2627

2728
const BUFFER_SIZE: usize = 132 * 64 / 8;
2829

@@ -65,20 +66,24 @@ where
6566

6667
/// Reset display
6768
// TODO: Move to a more appropriate place
68-
pub fn reset<RST, DELAY>(&mut self, rst: &mut RST, delay: &mut DELAY)
69+
pub fn reset<RST, DELAY, PinE>(
70+
&mut self,
71+
rst: &mut RST,
72+
delay: &mut DELAY,
73+
) -> Result<(), Error<(), PinE>>
6974
where
70-
RST: OutputPin,
75+
RST: OutputPin<Error = PinE>,
7176
DELAY: DelayMs<u8>,
7277
{
73-
rst.set_high();
78+
rst.set_high().map_err(Error::Pin)?;
7479
delay.delay_ms(1);
75-
rst.set_low();
80+
rst.set_low().map_err(Error::Pin)?;
7681
delay.delay_ms(10);
77-
rst.set_high();
82+
rst.set_high().map_err(Error::Pin)
7883
}
7984

8085
/// Write out data to display
81-
pub fn flush(&mut self) -> Result<(), ()> {
86+
pub fn flush(&mut self) -> Result<(), DI::Error> {
8287
let display_size = self.properties.get_size();
8388

8489
// Ensure the display buffer is at the origin of the display before we send the full frame
@@ -147,9 +152,8 @@ where
147152

148153
/// Display is set up in column mode, i.e. a byte walks down a column of 8 pixels from
149154
/// column 0 on the left, to column _n_ on the right
150-
pub fn init(&mut self) -> Result<(), ()> {
151-
self.properties.init_column_mode()?;
152-
Ok(())
155+
pub fn init(&mut self) -> Result<(), DI::Error> {
156+
self.properties.init_column_mode()
153157
}
154158

155159
/// Get display dimensions, taking into account the current rotation of the display
@@ -158,7 +162,7 @@ where
158162
}
159163

160164
/// Set the display rotation
161-
pub fn set_rotation(&mut self, rot: DisplayRotation) -> Result<(), ()> {
165+
pub fn set_rotation(&mut self, rot: DisplayRotation) -> Result<(), DI::Error> {
162166
self.properties.set_rotation(rot)
163167
}
164168
}

0 commit comments

Comments
 (0)