Skip to main content

omnitiles/hw/
pins_v1.rs

1// SPDX-License-Identifier: MIT
2// © 2025–2026 Christopher Liu
3
4//! Pin definitions for STM32F777 MCU for OmniTiles PCB v1.
5
6use stm32f7xx_hal::{
7    gpio::{
8        gpioa, gpiob, gpioc, gpiod, gpioe, gpioh, Alternate, Analog, Floating, Input, 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 encoder: EncoderPins,
23    pub can1: Can1Pins,
24    pub can2: Can2Pins,
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
33pub struct Usart1Pins {
34    pub tx: gpioa::PA9<Alternate<7>>,
35    pub rx: gpioa::PA10<Alternate<7>>,
36}
37
38/// SPI4 SCK/MISO/MOSI and CS
39pub struct Spi4Pins {
40    pub sck: gpioe::PE12<Alternate<5>>,
41    pub miso: gpioe::PE13<Alternate<5>>,
42    pub mosi: gpioe::PE14<Alternate<5>>,
43    pub cs1: gpioe::PE4<Output<PushPull>>,
44    pub cs2: gpioe::PE11<Output<PushPull>>,
45}
46
47/// TIM2/TIM3 Quadrature Encoder Inputs
48pub struct EncoderPins {
49    pub tim2_ch1: gpioa::PA0<Alternate<1>>,
50    pub tim2_ch2: gpioa::PA1<Alternate<1>>,
51
52    pub tim3_ch1: gpioa::PA6<Alternate<2>>,
53    pub tim3_ch2: gpioa::PA7<Alternate<2>>,
54}
55
56/// Motor 1 control pins
57pub struct Motor1Pins {
58    pub in1: gpioh::PH1<Output<PushPull>>,
59    pub in2: gpioc::PC0<Output<PushPull>>,
60    pub nsleep: gpioa::PA4<Output<PushPull>>,
61    pub disable: gpioa::PA3<Output<PushPull>>,
62    pub nfault: gpioa::PA2<Input<Floating>>,
63    pub iprop1: gpioc::PC4<Analog>, // ADC1_IN14
64    pub iprop2: gpioc::PC5<Analog>, // ADC1_IN15
65}
66
67/// Motor 2 control pins
68pub struct Motor2Pins {
69    pub in1: gpiod::PD3<Output<PushPull>>,
70    pub in2: gpiod::PD4<Output<PushPull>>,
71    pub nsleep: gpiod::PD2<Output<PushPull>>,
72    pub disable: gpiod::PD1<Output<PushPull>>,
73    pub nfault: gpiod::PD0<Input<Floating>>,
74    pub iprop1: gpioc::PC2<Analog>, // ADC1_IN12
75    pub iprop2: gpioc::PC3<Analog>, // ADC1_IN13
76}
77
78/// CAN1 bus pins
79pub struct Can1Pins {
80    pub tx: gpioa::PA12<Alternate<9>>,
81    pub rx: gpioa::PA11<Alternate<9>>,
82}
83
84/// CAN2 bus pins
85pub struct Can2Pins {
86    pub tx: gpiob::PB13<Alternate<9>>,
87    pub rx: gpiob::PB12<Alternate<9>>,
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        gpioh: pac::GPIOH,
99    ) -> Self {
100        let gpioa = gpioa.split();
101        let gpiob = gpiob.split();
102        let gpioc = gpioc.split();
103        let gpiod = gpiod.split();
104        let gpioe = gpioe.split();
105        let gpioh = gpioh.split();
106
107        Self {
108            leds: LedPins {
109                red: gpiod.pd8.into_push_pull_output(),
110                yellow: gpiod.pd9.into_push_pull_output(),
111                green: gpiod.pd10.into_push_pull_output(),
112            },
113
114            usart1: Usart1Pins {
115                tx: gpioa.pa9.into_alternate::<7>(),
116                rx: gpioa.pa10.into_alternate::<7>(),
117            },
118
119            spi4: Spi4Pins {
120                sck: gpioe.pe12.into_alternate::<5>(),
121                miso: gpioe.pe13.into_alternate::<5>(),
122                mosi: gpioe.pe14.into_alternate::<5>(),
123                cs1: gpioe.pe4.into_push_pull_output(),
124                cs2: gpioe.pe11.into_push_pull_output(),
125            },
126
127            encoder: EncoderPins {
128                tim2_ch1: gpioa.pa0.into_alternate::<1>(),
129                tim2_ch2: gpioa.pa1.into_alternate::<1>(),
130                tim3_ch1: gpioa.pa6.into_alternate::<2>(),
131                tim3_ch2: gpioa.pa7.into_alternate::<2>(),
132            },
133
134            m1: Motor1Pins {
135                in1: gpioh.ph1.into_push_pull_output(),
136                in2: gpioc.pc0.into_push_pull_output(),
137                nsleep: gpioa.pa4.into_push_pull_output(),
138                disable: gpioa.pa3.into_push_pull_output(),
139                nfault: gpioa.pa2.into_floating_input(),
140                iprop1: gpioc.pc4.into_analog(),
141                iprop2: gpioc.pc5.into_analog(),
142            },
143
144            m2: Motor2Pins {
145                in1: gpiod.pd3.into_push_pull_output(),
146                in2: gpiod.pd4.into_push_pull_output(),
147                nsleep: gpiod.pd2.into_push_pull_output(),
148                disable: gpiod.pd1.into_push_pull_output(),
149                nfault: gpiod.pd0.into_floating_input(),
150                iprop1: gpioc.pc2.into_analog(),
151                iprop2: gpioc.pc3.into_analog(),
152            },
153
154            can1: Can1Pins {
155                tx: gpioa.pa12.into_alternate::<9>(),
156                rx: gpioa.pa11.into_alternate::<9>().internal_pull_up(true),
157            },
158
159            can2: Can2Pins {
160                tx: gpiob.pb13.into_alternate::<9>(),
161                rx: gpiob.pb12.into_alternate::<9>().internal_pull_up(true),
162            },
163        }
164    }
165}