Skip to main content

omnitiles/hw/
pins_v2.rs

1// SPDX-License-Identifier: MIT
2// © 2025–2026 Christopher Liu
3
4//! Pin definitions for STM32F777 MCU Devboard for OmniTiles.
5
6use stm32f7xx_hal::{
7    gpio::{
8        gpioa, gpiob, gpioc, gpiod, gpioe, Alternate, Analog, Floating, Input, OpenDrain, Output,
9        PushPull,
10    },
11    pac,
12    prelude::*,
13};
14
15/// All board pins. Construct this once at startup.
16pub struct BoardPins {
17    pub leds: LedPins,
18    pub usart1: Usart1Pins,
19    pub spi4: Spi4Pins,
20    pub m1: Motor1Pins,
21    pub m2: Motor2Pins,
22    pub i2c1: I2c1Pins,
23    #[cfg(feature = "mobile-base")]
24    pub wheels: WheelPins,
25}
26
27pub struct LedPins {
28    pub red: gpiod::PD8<Output<PushPull>>,
29    pub yellow: gpiod::PD9<Output<PushPull>>,
30    pub green: gpiod::PD10<Output<PushPull>>,
31}
32
33// USART1 TX/RX
34pub struct Usart1Pins {
35    pub tx: gpioa::PA9<Alternate<7>>,
36    pub rx: gpioa::PA10<Alternate<7>>,
37}
38
39/// SPI4 SCK/MISO/MOSI and CS
40pub struct Spi4Pins {
41    pub sck: gpioe::PE12<Alternate<5>>,
42    pub miso: gpioe::PE5<Alternate<5>>,
43    pub mosi: gpioe::PE14<Alternate<5>>,
44    pub cs1: gpioe::PE4<Output<PushPull>>,
45    pub drdy: gpioe::PE11<Input<Floating>>,
46    pub cs2: gpioe::PE3<Output<PushPull>>,
47}
48
49pub struct Motor1Pins {
50    pub in1: gpioc::PC6<Alternate<2>>, // TIM3_CH1 (PWM)
51    pub in2: gpioc::PC7<Alternate<2>>, // TIM3_CH2 (PWM)
52    pub nsleep: gpiod::PD2<Output<PushPull>>,
53    pub disable: gpiod::PD1<Output<PushPull>>,
54    pub adc1: gpioc::PC4<Analog>, // ADC1_IN14
55    pub adc2: gpiob::PB1<Analog>, // ADC1_IN9
56    pub adc3: gpioc::PC0<Analog>, // ADC1_IN10
57    pub adc4: gpioc::PC1<Analog>, // ADC1_IN11
58}
59
60pub struct Motor2Pins {
61    pub in1: gpioc::PC8<Alternate<2>>, // TIM3_CH3 (PWM)
62    pub in2: gpioa::PA8<Alternate<1>>, // TIM1_CH1 (PWM)
63    pub nsleep: gpiod::PD4<Output<PushPull>>,
64    pub disable: gpiod::PD5<Output<PushPull>>,
65    pub adc1: gpioc::PC5<Analog>, // ADC1_IN15
66    pub adc2: gpioc::PC3<Analog>, // ADC1_IN13
67}
68
69pub struct I2c1Pins {
70    pub scl: gpiob::PB6<Alternate<4, OpenDrain>>,
71    pub sda: gpiob::PB9<Alternate<4, OpenDrain>>,
72}
73
74#[cfg(feature = "mobile-base")]
75pub struct WheelPins {
76    pub fl_pwm: gpiod::PD12<Alternate<2>>, // TIM4_CH1
77    pub fl_in1: gpiod::PD3<Output<PushPull>>,
78    pub fl_in2: gpiod::PD6<Output<PushPull>>,
79    pub fr_pwm: gpiod::PD13<Alternate<2>>, // TIM4_CH2
80    pub fr_in1: gpiod::PD7<Output<PushPull>>,
81    pub fr_in2: gpiod::PD11<Output<PushPull>>,
82    pub bl_pwm: gpiod::PD14<Alternate<2>>, // TIM4_CH3
83    pub bl_in1: gpioe::PE0<Output<PushPull>>,
84    pub bl_in2: gpioe::PE1<Output<PushPull>>,
85    pub br_pwm: gpiod::PD15<Alternate<2>>, // TIM4_CH4
86    pub br_in1: gpioe::PE2<Output<PushPull>>,
87    pub br_in2: gpioe::PE6<Output<PushPull>>,
88}
89
90impl BoardPins {
91    /// Create all named pins from raw GPIO peripherals.
92    pub fn new(
93        gpioa: pac::GPIOA,
94        gpiob: pac::GPIOB,
95        gpioc: pac::GPIOC,
96        gpiod: pac::GPIOD,
97        gpioe: pac::GPIOE,
98    ) -> Self {
99        let gpioa = gpioa.split();
100        let gpiob = gpiob.split();
101        let gpioc = gpioc.split();
102        let gpiod = gpiod.split();
103        let gpioe = gpioe.split();
104
105        Self {
106            leds: LedPins {
107                red: gpiod.pd8.into_push_pull_output(),
108                yellow: gpiod.pd9.into_push_pull_output(),
109                green: gpiod.pd10.into_push_pull_output(),
110            },
111
112            usart1: Usart1Pins {
113                tx: gpioa.pa9.into_alternate::<7>(),
114                rx: gpioa.pa10.into_alternate::<7>(),
115            },
116
117            spi4: Spi4Pins {
118                sck: gpioe.pe12.into_alternate::<5>(),
119                miso: gpioe.pe5.into_alternate::<5>(),
120                mosi: gpioe.pe14.into_alternate::<5>(),
121                cs1: gpioe.pe4.into_push_pull_output(),
122                drdy: gpioe.pe11.into_floating_input(),
123                cs2: gpioe.pe3.into_push_pull_output(),
124            },
125
126            m1: Motor1Pins {
127                in1: gpioc.pc6.into_alternate::<2>(),
128                in2: gpioc.pc7.into_alternate::<2>(),
129                nsleep: gpiod.pd2.into_push_pull_output(),
130                disable: gpiod.pd1.into_push_pull_output(),
131                adc1: gpioc.pc4.into_analog(),
132                adc2: gpiob.pb1.into_analog(),
133                adc3: gpioc.pc0.into_analog(), // Inverted
134                adc4: gpioc.pc1.into_analog(), // Inverted
135            },
136
137            m2: Motor2Pins {
138                in1: gpioc.pc8.into_alternate::<2>(),
139                in2: gpioa.pa8.into_alternate::<1>(),
140                nsleep: gpiod.pd4.into_push_pull_output(),
141                disable: gpiod.pd5.into_push_pull_output(),
142                adc1: gpioc.pc5.into_analog(),
143                adc2: gpioc.pc3.into_analog(),
144            },
145
146            i2c1: I2c1Pins {
147                scl: gpiob
148                    .pb6
149                    .into_alternate::<4>()
150                    .internal_pull_up(true)
151                    .set_open_drain(),
152                sda: gpiob
153                    .pb9
154                    .into_alternate::<4>()
155                    .internal_pull_up(true)
156                    .set_open_drain(),
157            },
158
159            #[cfg(feature = "mobile-base")]
160            wheels: WheelPins {
161                fl_pwm: gpiod.pd12.into_alternate::<2>(),
162                fl_in1: gpiod.pd3.into_push_pull_output(),
163                fl_in2: gpiod.pd6.into_push_pull_output(),
164                fr_pwm: gpiod.pd13.into_alternate::<2>(),
165                fr_in1: gpiod.pd7.into_push_pull_output(),
166                fr_in2: gpiod.pd11.into_push_pull_output(),
167                bl_pwm: gpiod.pd14.into_alternate::<2>(),
168                bl_in1: gpioe.pe0.into_push_pull_output(),
169                bl_in2: gpioe.pe1.into_push_pull_output(),
170                br_pwm: gpiod.pd15.into_alternate::<2>(),
171                br_in1: gpioe.pe2.into_push_pull_output(),
172                br_in2: gpioe.pe6.into_push_pull_output(),
173            },
174        }
175    }
176}