Skip to content

Commit 88f8311

Browse files
chrysnnewAM
authored andcommitted
gpio: Enable access to high pins
Closes: #50
1 parent d581a6b commit 88f8311

File tree

2 files changed

+247
-33
lines changed

2 files changed

+247
-33
lines changed

src/gpio.rs

Lines changed: 54 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::sync::{Arc, Mutex};
77
#[derive(Debug, Copy, Clone)]
88
pub(crate) enum Pin {
99
Lower(u8),
10+
Upper(u8),
1011
}
1112

1213
/// FTDI output pin.
@@ -36,13 +37,19 @@ where
3637
{
3738
let mut lock = mtx.lock().expect("Failed to aquire FTDI mutex");
3839

39-
let Pin::Lower(idx) = pin;
40-
41-
lock.direction |= 1 << idx;
42-
lock.allocate_pin(idx, PinUse::Output);
43-
let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new()
44-
.set_gpio_lower(lock.value, lock.direction)
45-
.send_immediate();
40+
lock.allocate_pin_any(pin, PinUse::Output);
41+
42+
let (byte, idx) = match pin {
43+
Pin::Lower(idx) => (&mut lock.lower, idx),
44+
Pin::Upper(idx) => (&mut lock.upper, idx),
45+
};
46+
byte.direction |= 1 << idx;
47+
let cmd = MpsseCmdBuilder::new();
48+
let cmd = match pin {
49+
Pin::Lower(_) => cmd.set_gpio_lower(byte.value, byte.direction),
50+
Pin::Upper(_) => cmd.set_gpio_upper(byte.value, byte.direction),
51+
}
52+
.send_immediate();
4653
lock.ft.send(cmd.as_slice())?;
4754
}
4855
Ok(OutputPin { mtx, pin })
@@ -51,15 +58,23 @@ where
5158
pub(crate) fn set(&self, state: bool) -> Result<(), Error<E>> {
5259
let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex");
5360

61+
let byte = match self.pin {
62+
Pin::Lower(_) => &mut lock.lower,
63+
Pin::Upper(_) => &mut lock.upper,
64+
};
65+
5466
if state {
55-
lock.value |= self.mask();
67+
byte.value |= self.mask();
5668
} else {
57-
lock.value &= !self.mask();
69+
byte.value &= !self.mask();
5870
};
5971

60-
let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new()
61-
.set_gpio_lower(lock.value, lock.direction)
62-
.send_immediate();
72+
let cmd = MpsseCmdBuilder::new();
73+
let cmd = match self.pin {
74+
Pin::Lower(_) => cmd.set_gpio_lower(byte.value, byte.direction),
75+
Pin::Upper(_) => cmd.set_gpio_upper(byte.value, byte.direction),
76+
}
77+
.send_immediate();
6378
lock.ft.send(cmd.as_slice())?;
6479

6580
Ok(())
@@ -69,7 +84,10 @@ where
6984
impl<Device: MpsseCmdExecutor> OutputPin<Device> {
7085
/// Convert the GPIO pin index to a pin mask
7186
pub(crate) fn mask(&self) -> u8 {
72-
let Pin::Lower(idx) = self.pin;
87+
let idx = match self.pin {
88+
Pin::Lower(idx) => idx,
89+
Pin::Upper(idx) => idx,
90+
};
7391
1 << idx
7492
}
7593
}
@@ -142,13 +160,19 @@ where
142160
{
143161
let mut lock = mtx.lock().expect("Failed to aquire FTDI mutex");
144162

145-
let Pin::Lower(idx) = pin;
146-
147-
lock.direction &= !(1 << idx);
148-
lock.allocate_pin(idx, PinUse::Input);
149-
let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new()
150-
.set_gpio_lower(lock.value, lock.direction)
151-
.send_immediate();
163+
lock.allocate_pin_any(pin, PinUse::Input);
164+
165+
let (byte, idx) = match pin {
166+
Pin::Lower(idx) => (&mut lock.lower, idx),
167+
Pin::Upper(idx) => (&mut lock.upper, idx),
168+
};
169+
byte.direction &= !(1 << idx);
170+
let cmd = MpsseCmdBuilder::new();
171+
let cmd = match pin {
172+
Pin::Lower(_) => cmd.set_gpio_lower(byte.value, byte.direction),
173+
Pin::Upper(_) => cmd.set_gpio_upper(byte.value, byte.direction),
174+
}
175+
.send_immediate();
152176
lock.ft.send(cmd.as_slice())?;
153177
}
154178
Ok(InputPin { mtx, pin })
@@ -158,7 +182,12 @@ where
158182
let mut lock = self.mtx.lock().expect("Failed to aquire FTDI mutex");
159183

160184
let mut buffer = [0u8; 1];
161-
let cmd: MpsseCmdBuilder = MpsseCmdBuilder::new().gpio_lower().send_immediate();
185+
let cmd = MpsseCmdBuilder::new();
186+
let cmd = match self.pin {
187+
Pin::Lower(_) => cmd.gpio_lower(),
188+
Pin::Upper(_) => cmd.gpio_upper(),
189+
}
190+
.send_immediate();
162191
lock.ft.send(cmd.as_slice())?;
163192
lock.ft.recv(&mut buffer)?;
164193

@@ -169,7 +198,10 @@ where
169198
impl<Device: MpsseCmdExecutor> InputPin<Device> {
170199
/// Convert the GPIO pin index to a pin mask
171200
pub(crate) fn mask(&self) -> u8 {
172-
let Pin::Lower(idx) = self.pin;
201+
let idx = match self.pin {
202+
Pin::Lower(idx) => idx,
203+
Pin::Upper(idx) => idx,
204+
};
173205
1 << idx
174206
}
175207
}

src/lib.rs

Lines changed: 193 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,8 @@ impl std::fmt::Display for PinUse {
196196
}
197197
}
198198

199-
#[derive(Debug)]
200-
struct FtInner<Device: MpsseCmdExecutor> {
201-
/// FTDI device.
202-
ft: Device,
199+
#[derive(Debug, Default)]
200+
struct GpioByte {
203201
/// GPIO direction.
204202
direction: u8,
205203
/// GPIO value.
@@ -208,17 +206,58 @@ struct FtInner<Device: MpsseCmdExecutor> {
208206
pins: [Option<PinUse>; 8],
209207
}
210208

209+
#[derive(Debug)]
210+
struct FtInner<Device: MpsseCmdExecutor> {
211+
/// FTDI device.
212+
ft: Device,
213+
lower: GpioByte,
214+
upper: GpioByte,
215+
}
216+
217+
// FtInner deref's into .lower because SPI and I2C code were not adjusted yet to handle the split;
218+
// once those are updated, the Deref implementation can go away again
219+
220+
impl<Device: MpsseCmdExecutor> core::ops::Deref for FtInner<Device> {
221+
type Target = GpioByte;
222+
fn deref(&self) -> &GpioByte {
223+
&self.lower
224+
}
225+
}
226+
227+
impl<Device: MpsseCmdExecutor> core::ops::DerefMut for FtInner<Device> {
228+
fn deref_mut(&mut self) -> &mut GpioByte {
229+
&mut self.lower
230+
}
231+
}
232+
211233
impl<Device: MpsseCmdExecutor> FtInner<Device> {
212-
/// Allocate a pin for a specific use.
234+
/// Allocate a pin in the lower byte for a specific use.
213235
pub fn allocate_pin(&mut self, idx: u8, purpose: PinUse) {
214236
assert!(idx < 8, "Pin index {idx} is out of range 0 - 7");
215237

216-
if let Some(current) = self.pins[usize::from(idx)] {
238+
if let Some(current) = self.lower.pins[usize::from(idx)] {
217239
panic!(
218-
"Unable to allocate pin {idx} for {purpose}, pin is already allocated for {current}"
240+
"Unable to allocate pin {idx} for {purpose}, pin is already allocated for {current}"
219241
);
220242
} else {
221-
self.pins[usize::from(idx)] = Some(purpose)
243+
self.lower.pins[usize::from(idx)] = Some(purpose)
244+
}
245+
}
246+
247+
/// Allocate a pin for a specific use.
248+
pub fn allocate_pin_any(&mut self, pin: Pin, purpose: PinUse) {
249+
let (byte, idx) = match pin {
250+
Pin::Lower(idx) => (&mut self.lower, idx),
251+
Pin::Upper(idx) => (&mut self.upper, idx),
252+
};
253+
assert!(idx < 8, "Pin index {idx} is out of range 0 - 7");
254+
255+
if let Some(current) = byte.pins[usize::from(idx)] {
256+
panic!(
257+
"Unable to allocate pin {idx} for {purpose}, pin is already allocated for {current}"
258+
);
259+
} else {
260+
byte.pins[usize::from(idx)] = Some(purpose)
222261
}
223262
}
224263
}
@@ -227,9 +266,8 @@ impl<Device: MpsseCmdExecutor> From<Device> for FtInner<Device> {
227266
fn from(ft: Device) -> Self {
228267
FtInner {
229268
ft,
230-
direction: 0x00,
231-
value: 0x00,
232-
pins: [None; 8],
269+
lower: Default::default(),
270+
upper: Default::default(),
233271
}
234272
}
235273
}
@@ -585,4 +623,148 @@ where
585623
pub fn adi7(&self) -> Result<InputPin<Device>, Error<E>> {
586624
InputPin::new(self.mtx.clone(), Pin::Lower(7))
587625
}
626+
627+
/// Aquire the digital output upper pin 0 for the FT232H.
628+
///
629+
/// # Panics
630+
///
631+
/// Panics if the pin is already in-use.
632+
pub fn c0(&self) -> Result<OutputPin<Device>, Error<E>> {
633+
OutputPin::new(self.mtx.clone(), Pin::Upper(0))
634+
}
635+
636+
/// Aquire the digital input upper pin 0 for the FT232H.
637+
///
638+
/// # Panics
639+
///
640+
/// Panics if the pin is already in-use.
641+
pub fn ci0(&self) -> Result<InputPin<Device>, Error<E>> {
642+
InputPin::new(self.mtx.clone(), Pin::Upper(0))
643+
}
644+
645+
/// Aquire the digital output upper pin 1 for the FT232H.
646+
///
647+
/// # Panics
648+
///
649+
/// Panics if the pin is already in-use.
650+
pub fn c1(&self) -> Result<OutputPin<Device>, Error<E>> {
651+
OutputPin::new(self.mtx.clone(), Pin::Upper(1))
652+
}
653+
654+
/// Aquire the digital input upper pin 1 for the FT232H.
655+
///
656+
/// # Panics
657+
///
658+
/// Panics if the pin is already in-use.
659+
pub fn ci1(&self) -> Result<InputPin<Device>, Error<E>> {
660+
InputPin::new(self.mtx.clone(), Pin::Upper(1))
661+
}
662+
663+
/// Aquire the digital output upper pin 2 for the FT232H.
664+
///
665+
/// # Panics
666+
///
667+
/// Panics if the pin is already in-use.
668+
pub fn c2(&self) -> Result<OutputPin<Device>, Error<E>> {
669+
OutputPin::new(self.mtx.clone(), Pin::Upper(2))
670+
}
671+
672+
/// Aquire the digital input upper pin 2 for the FT232H.
673+
///
674+
/// # Panics
675+
///
676+
/// Panics if the pin is already in-use.
677+
pub fn ci2(&self) -> Result<InputPin<Device>, Error<E>> {
678+
InputPin::new(self.mtx.clone(), Pin::Upper(2))
679+
}
680+
681+
/// Aquire the digital output upper pin 3 for the FT232H.
682+
///
683+
/// # Panics
684+
///
685+
/// Panics if the pin is already in-use.
686+
pub fn c3(&self) -> Result<OutputPin<Device>, Error<E>> {
687+
OutputPin::new(self.mtx.clone(), Pin::Upper(3))
688+
}
689+
690+
/// Aquire the digital input upper pin 3 for the FT232H.
691+
///
692+
/// # Panics
693+
///
694+
/// Panics if the pin is already in-use.
695+
pub fn ci3(&self) -> Result<InputPin<Device>, Error<E>> {
696+
InputPin::new(self.mtx.clone(), Pin::Upper(3))
697+
}
698+
699+
/// Aquire the digital output upper pin 4 for the FT232H.
700+
///
701+
/// # Panics
702+
///
703+
/// Panics if the pin is already in-use.
704+
pub fn c4(&self) -> Result<OutputPin<Device>, Error<E>> {
705+
OutputPin::new(self.mtx.clone(), Pin::Upper(4))
706+
}
707+
708+
/// Aquire the digital input upper pin 4 for the FT232H.
709+
///
710+
/// # Panics
711+
///
712+
/// Panics if the pin is already in-use.
713+
pub fn ci4(&self) -> Result<InputPin<Device>, Error<E>> {
714+
InputPin::new(self.mtx.clone(), Pin::Upper(4))
715+
}
716+
717+
/// Aquire the digital output upper pin 5 for the FT232H.
718+
///
719+
/// # Panics
720+
///
721+
/// Panics if the pin is already in-use.
722+
pub fn c5(&self) -> Result<OutputPin<Device>, Error<E>> {
723+
OutputPin::new(self.mtx.clone(), Pin::Upper(5))
724+
}
725+
726+
/// Aquire the digital input upper pin 5 for the FT232H.
727+
///
728+
/// # Panics
729+
///
730+
/// Panics if the pin is already in-use.
731+
pub fn ci5(&self) -> Result<InputPin<Device>, Error<E>> {
732+
InputPin::new(self.mtx.clone(), Pin::Upper(5))
733+
}
734+
735+
/// Aquire the digital output upper pin 6 for the FT232H.
736+
///
737+
/// # Panics
738+
///
739+
/// Panics if the pin is already in-use.
740+
pub fn c6(&self) -> Result<OutputPin<Device>, Error<E>> {
741+
OutputPin::new(self.mtx.clone(), Pin::Upper(6))
742+
}
743+
744+
/// Aquire the digital input upper pin 6 for the FT232H.
745+
///
746+
/// # Panics
747+
///
748+
/// Panics if the pin is already in-use.
749+
pub fn ci6(&self) -> Result<InputPin<Device>, Error<E>> {
750+
InputPin::new(self.mtx.clone(), Pin::Upper(6))
751+
}
752+
753+
/// Aquire the digital output upper pin 7 for the FT232H.
754+
///
755+
/// # Panics
756+
///
757+
/// Panics if the pin is already in-use.
758+
pub fn c7(&self) -> Result<OutputPin<Device>, Error<E>> {
759+
OutputPin::new(self.mtx.clone(), Pin::Upper(7))
760+
}
761+
762+
/// Aquire the digital input upper pin 7 for the FT232H.
763+
///
764+
/// # Panics
765+
///
766+
/// Panics if the pin is already in-use.
767+
pub fn ci7(&self) -> Result<InputPin<Device>, Error<E>> {
768+
InputPin::new(self.mtx.clone(), Pin::Upper(7))
769+
}
588770
}

0 commit comments

Comments
 (0)