Skip to content

Commit 10e2759

Browse files
eldruinjamwaffles
authored andcommitted
Forward communication errors
1 parent b4cce1f commit 10e2759

File tree

9 files changed

+62
-60
lines changed

9 files changed

+62
-60
lines changed

src/builder.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,9 @@ impl Builder {
9696
}
9797

9898
/// Finish the builder and use I2C to communicate with the display
99-
pub fn connect_i2c<I2C>(&self, i2c: I2C) -> DisplayMode<RawMode<I2cInterface<I2C>>>
99+
pub fn connect_i2c<I2C, CommE>(&self, i2c: I2C) -> DisplayMode<RawMode<I2cInterface<I2C>>>
100100
where
101-
I2C: hal::blocking::i2c::Write,
101+
I2C: hal::blocking::i2c::Write<Error = CommE>,
102102
{
103103
let properties = DisplayProperties::new(
104104
I2cInterface::new(i2c, self.i2c_addr),
@@ -109,13 +109,14 @@ impl Builder {
109109
}
110110

111111
/// Finish the builder and use SPI to communicate with the display
112-
pub fn connect_spi<SPI, DC>(
112+
pub fn connect_spi<SPI, DC, CommE>(
113113
&self,
114114
spi: SPI,
115115
dc: DC,
116116
) -> DisplayMode<RawMode<SpiInterface<SPI, DC>>>
117117
where
118-
SPI: hal::blocking::spi::Transfer<u8> + hal::blocking::spi::Write<u8>,
118+
SPI: hal::blocking::spi::Transfer<u8, Error = CommE>
119+
+ hal::blocking::spi::Write<u8, Error = CommE>,
119120
DC: OutputPin,
120121
{
121122
let properties =

src/command.rs

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

8585
impl Command {
8686
/// Send command to SSD1306
87-
pub fn send<DI>(self, iface: &mut DI) -> Result<(), ()>
87+
pub fn send<DI>(self, iface: &mut DI) -> Result<(), DI::Error>
8888
where
8989
DI: DisplayInterface,
9090
{
@@ -156,9 +156,7 @@ impl Command {
156156
};
157157

158158
// Send command over the interface
159-
iface.send_commands(&data[0..len])?;
160-
161-
Ok(())
159+
iface.send_commands(&data[0..len])
162160
}
163161
}
164162

src/interface/i2c.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use hal;
44

55
use super::DisplayInterface;
6+
use crate::Error;
67

78
// TODO: Add to prelude
89
/// SSD1306 I2C communication interface
@@ -11,33 +12,33 @@ pub struct I2cInterface<I2C> {
1112
addr: u8,
1213
}
1314

14-
impl<I2C> I2cInterface<I2C>
15+
impl<I2C, CommE> I2cInterface<I2C>
1516
where
16-
I2C: hal::blocking::i2c::Write,
17+
I2C: hal::blocking::i2c::Write<Error = CommE>,
1718
{
1819
/// Create new SSD1306 I2C interface
1920
pub fn new(i2c: I2C, addr: u8) -> Self {
2021
Self { i2c, addr }
2122
}
2223
}
2324

24-
impl<I2C> DisplayInterface for I2cInterface<I2C>
25+
impl<I2C, CommE> DisplayInterface for I2cInterface<I2C>
2526
where
26-
I2C: hal::blocking::i2c::Write,
27+
I2C: hal::blocking::i2c::Write<Error = CommE>,
2728
{
28-
fn send_commands(&mut self, cmds: &[u8]) -> Result<(), ()> {
29+
type Error = Error<CommE>;
30+
31+
fn send_commands(&mut self, cmds: &[u8]) -> Result<(), Self::Error> {
2932
// Copy over given commands to new aray to prefix with command identifier
3033
let mut writebuf: [u8; 8] = [0; 8];
3134
writebuf[1..=cmds.len()].copy_from_slice(&cmds[0..cmds.len()]);
3235

3336
self.i2c
3437
.write(self.addr, &writebuf[..=cmds.len()])
35-
.map_err(|_| ())?;
36-
37-
Ok(())
38+
.map_err(Error::Comm)
3839
}
3940

40-
fn send_data(&mut self, buf: &[u8]) -> Result<(), ()> {
41+
fn send_data(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
4142
// Noop if the data buffer is empty
4243
if buf.is_empty() {
4344
return Ok(());
@@ -57,7 +58,7 @@ where
5758

5859
self.i2c
5960
.write(self.addr, &writebuf[..=chunklen])
60-
.map_err(|_| ())?;
61+
.map_err(Error::Comm)?;
6162
}
6263

6364
Ok(())

src/interface/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,12 @@ pub mod spi;
5656

5757
/// A method of communicating with SSD1306
5858
pub trait DisplayInterface {
59+
/// Interface error type
60+
type Error;
5961
/// Send a batch of up to 8 commands to display.
60-
fn send_commands(&mut self, cmd: &[u8]) -> Result<(), ()>;
62+
fn send_commands(&mut self, cmd: &[u8]) -> Result<(), Self::Error>;
6163
/// Send data to display.
62-
fn send_data(&mut self, buf: &[u8]) -> Result<(), ()>;
64+
fn send_data(&mut self, buf: &[u8]) -> Result<(), Self::Error>;
6365
}
6466

6567
pub use self::i2c::I2cInterface;

src/interface/spi.rs

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

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

89
// TODO: Add to prelude
910
/// SPI display interface.
@@ -14,9 +15,9 @@ pub struct SpiInterface<SPI, DC> {
1415
dc: DC,
1516
}
1617

17-
impl<SPI, DC> SpiInterface<SPI, DC>
18+
impl<SPI, DC, CommE> SpiInterface<SPI, DC>
1819
where
19-
SPI: hal::blocking::spi::Write<u8>,
20+
SPI: hal::blocking::spi::Write<u8, Error = CommE>,
2021
DC: OutputPin,
2122
{
2223
/// Create new SPI interface for communciation with SSD1306
@@ -25,27 +26,28 @@ where
2526
}
2627
}
2728

28-
impl<SPI, DC> DisplayInterface for SpiInterface<SPI, DC>
29+
impl<SPI, DC, CommE> DisplayInterface for SpiInterface<SPI, DC>
2930
where
30-
SPI: hal::blocking::spi::Write<u8>,
31+
SPI: hal::blocking::spi::Write<u8, Error = CommE>,
3132
DC: OutputPin,
3233
{
33-
fn send_commands(&mut self, cmds: &[u8]) -> Result<(), ()> {
34+
type Error = Error<CommE>;
35+
36+
fn send_commands(&mut self, cmds: &[u8]) -> Result<(), Self::Error> {
3437
self.dc.set_low();
3538

36-
self.spi.write(&cmds).map_err(|_| ())?;
39+
self.spi.write(&cmds).map_err(Error::Comm)?;
3740

3841
self.dc.set_high();
3942

4043
Ok(())
4144
}
4245

43-
fn send_data(&mut self, buf: &[u8]) -> Result<(), ()> {
46+
fn send_data(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
4447
// 1 = data, 0 = command
4548
self.dc.set_high();
4649

47-
self.spi.write(&buf).map_err(|_| ())?;
4850

49-
Ok(())
51+
self.spi.write(&buf).map_err(Error::Comm)
5052
}
5153
}

src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,13 @@
166166
#![deny(unused_import_braces)]
167167
#![deny(unused_qualifications)]
168168

169+
/// Errors in this crate
170+
#[derive(Debug)]
171+
pub enum Error<CommE> {
172+
/// Communication error
173+
Comm(CommE),
174+
}
175+
169176
extern crate embedded_hal as hal;
170177

171178
pub mod builder;

src/mode/graphics.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ where
7676
}
7777

7878
/// Write out data to display
79-
pub fn flush(&mut self) -> Result<(), ()> {
79+
pub fn flush(&mut self) -> Result<(), DI::Error> {
8080
let display_size = self.properties.get_size();
8181

8282
// Ensure the display buffer is at the origin of the display before we send the full frame
@@ -144,9 +144,8 @@ where
144144

145145
/// Display is set up in column mode, i.e. a byte walks down a column of 8 pixels from
146146
/// column 0 on the left, to column _n_ on the right
147-
pub fn init(&mut self) -> Result<(), ()> {
148-
self.properties.init_column_mode()?;
149-
Ok(())
147+
pub fn init(&mut self) -> Result<(), DI::Error> {
148+
self.properties.init_column_mode()
150149
}
151150

152151
/// Get display dimensions, taking into account the current rotation of the display
@@ -155,7 +154,7 @@ where
155154
}
156155

157156
/// Set the display rotation
158-
pub fn set_rotation(&mut self, rot: DisplayRotation) -> Result<(), ()> {
157+
pub fn set_rotation(&mut self, rot: DisplayRotation) -> Result<(), DI::Error> {
159158
self.properties.set_rotation(rot)
160159
}
161160
}

src/mode/terminal.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ where
165165
DI: DisplayInterface,
166166
{
167167
/// Clear the display
168-
pub fn clear(&mut self) -> Result<(), ()> {
168+
pub fn clear(&mut self) -> Result<(), DI::Error> {
169169
let display_size = self.properties.get_size();
170170

171171
let numchars = match display_size {
@@ -205,24 +205,22 @@ where
205205
}
206206

207207
/// Print a character to the display
208-
pub fn print_char<T>(&mut self, c: T) -> Result<(), ()>
208+
pub fn print_char<T>(&mut self, c: T) -> Result<(), DI::Error>
209209
where
210210
TerminalMode<DI>: CharacterBitmap<T>,
211211
{
212212
// Send the pixel data to the display
213-
self.properties.draw(&Self::to_bitmap(c))?;
214-
Ok(())
213+
self.properties.draw(&Self::to_bitmap(c))
215214
}
216215

217216
/// Initialise the display in column mode (i.e. a byte walks down a column of 8 pixels) with
218217
/// column 0 on the left and column _(display_width - 1)_ on the right.
219-
pub fn init(&mut self) -> Result<(), ()> {
220-
self.properties.init_column_mode()?;
221-
Ok(())
218+
pub fn init(&mut self) -> Result<(), DI::Error> {
219+
self.properties.init_column_mode()
222220
}
223221

224222
/// Set the display rotation
225-
pub fn set_rotation(&mut self, rot: DisplayRotation) -> Result<(), ()> {
223+
pub fn set_rotation(&mut self, rot: DisplayRotation) -> Result<(), DI::Error> {
226224
self.properties.set_rotation(rot)
227225
}
228226
}

src/properties.rs

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ where
3131

3232
/// Initialise the display in column mode (i.e. a byte walks down a column of 8 pixels) with
3333
/// column 0 on the left and column _(display_width - 1)_ on the right.
34-
pub fn init_column_mode(&mut self) -> Result<(), ()> {
34+
pub fn init_column_mode(&mut self) -> Result<(), DI::Error> {
3535
// TODO: Break up into nice bits so display modes can pick whathever they need
3636
let (_, display_height) = self.display_size.dimensions();
3737

@@ -60,26 +60,22 @@ where
6060
Command::AllOn(false).send(&mut self.iface)?;
6161
Command::Invert(false).send(&mut self.iface)?;
6262
Command::EnableScroll(false).send(&mut self.iface)?;
63-
Command::DisplayOn(true).send(&mut self.iface)?;
64-
65-
Ok(())
63+
Command::DisplayOn(true).send(&mut self.iface)
6664
}
6765

6866
/// Set the position in the framebuffer of the display where any sent data should be
6967
/// drawn. This method can be used for changing the affected area on the screen as well
7068
/// as (re-)setting the start point of the next `draw` call.
71-
pub fn set_draw_area(&mut self, start: (u8, u8), end: (u8, u8)) -> Result<(), ()> {
69+
pub fn set_draw_area(&mut self, start: (u8, u8), end: (u8, u8)) -> Result<(), DI::Error> {
7270
Command::ColumnAddress(start.0, end.0 - 1).send(&mut self.iface)?;
73-
Command::PageAddress(start.1.into(), (end.1 - 1).into()).send(&mut self.iface)?;
74-
Ok(())
71+
Command::PageAddress(start.1.into(), (end.1 - 1).into()).send(&mut self.iface)
7572
}
7673

7774
/// Send the data to the display for drawing at the current position in the framebuffer
7875
/// and advance the position accordingly. Cf. `set_draw_area` to modify the affected area by
7976
/// this method.
80-
pub fn draw(&mut self, buffer: &[u8]) -> Result<(), ()> {
81-
self.iface.send_data(&buffer)?;
82-
Ok(())
77+
pub fn draw(&mut self, buffer: &[u8]) -> Result<(), DI::Error> {
78+
self.iface.send_data(&buffer)
8379
}
8480

8581
/// Get the configured display size
@@ -131,28 +127,26 @@ where
131127
}
132128

133129
/// Set the display rotation
134-
pub fn set_rotation(&mut self, display_rotation: DisplayRotation) -> Result<(), ()> {
130+
pub fn set_rotation(&mut self, display_rotation: DisplayRotation) -> Result<(), DI::Error> {
135131
self.display_rotation = display_rotation;
136132

137133
match display_rotation {
138134
DisplayRotation::Rotate0 => {
139135
Command::SegmentRemap(true).send(&mut self.iface)?;
140-
Command::ReverseComDir(true).send(&mut self.iface)?;
136+
Command::ReverseComDir(true).send(&mut self.iface)
141137
}
142138
DisplayRotation::Rotate90 => {
143139
Command::SegmentRemap(false).send(&mut self.iface)?;
144-
Command::ReverseComDir(true).send(&mut self.iface)?;
140+
Command::ReverseComDir(true).send(&mut self.iface)
145141
}
146142
DisplayRotation::Rotate180 => {
147143
Command::SegmentRemap(false).send(&mut self.iface)?;
148-
Command::ReverseComDir(false).send(&mut self.iface)?;
144+
Command::ReverseComDir(false).send(&mut self.iface)
149145
}
150146
DisplayRotation::Rotate270 => {
151147
Command::SegmentRemap(true).send(&mut self.iface)?;
152-
Command::ReverseComDir(false).send(&mut self.iface)?;
148+
Command::ReverseComDir(false).send(&mut self.iface)
153149
}
154-
};
155-
156-
Ok(())
150+
}
157151
}
158152
}

0 commit comments

Comments
 (0)