aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTyler <[email protected]>2023-09-30 16:06:11 -0600
committerGitHub <[email protected]>2023-09-30 16:06:11 -0600
commitfa8d5da4a5c5270a66d4bdf59aa215c32b14ad43 (patch)
tree39e7849e8fa2d1a4c60e645f6c78495f1da3ce4d
parentc52320f467c64a4944ed7df72fe7cca6a2b77564 (diff)
parent7bc57ca3f79b4b40ea11b11d34d82d933b198fba (diff)
Merge pull request #5 from embassy-rs/main
Merge latest including SAI driver
-rw-r--r--embassy-stm32/build.rs11
-rw-r--r--embassy-stm32/src/lib.rs2
-rw-r--r--embassy-stm32/src/rcc/f4.rs60
-rw-r--r--embassy-stm32/src/sai/mod.rs894
-rw-r--r--embassy-stm32/src/timer/mod.rs620
-rw-r--r--examples/wasm/README.md4
6 files changed, 1124 insertions, 467 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index b36af4795..ccc9210df 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -463,6 +463,15 @@ fn main() {
463 (("lpuart", "RTS"), quote!(crate::usart::RtsPin)), 463 (("lpuart", "RTS"), quote!(crate::usart::RtsPin)),
464 (("lpuart", "CK"), quote!(crate::usart::CkPin)), 464 (("lpuart", "CK"), quote!(crate::usart::CkPin)),
465 (("lpuart", "DE"), quote!(crate::usart::DePin)), 465 (("lpuart", "DE"), quote!(crate::usart::DePin)),
466 (("sai", "SCK_A"), quote!(crate::sai::SckAPin)),
467 (("sai", "SCK_B"), quote!(crate::sai::SckBPin)),
468 (("sai", "FS_A"), quote!(crate::sai::FsAPin)),
469 (("sai", "FS_B"), quote!(crate::sai::FsBPin)),
470 (("sai", "SD_A"), quote!(crate::sai::SdAPin)),
471 (("sai", "SD_B"), quote!(crate::sai::SdBPin)),
472 (("sai", "MCLK_A"), quote!(crate::sai::MclkAPin)),
473 (("sai", "MCLK_B"), quote!(crate::sai::MclkBPin)),
474 (("sai", "WS"), quote!(crate::sai::WsPin)),
466 (("spi", "SCK"), quote!(crate::spi::SckPin)), 475 (("spi", "SCK"), quote!(crate::spi::SckPin)),
467 (("spi", "MOSI"), quote!(crate::spi::MosiPin)), 476 (("spi", "MOSI"), quote!(crate::spi::MosiPin)),
468 (("spi", "MISO"), quote!(crate::spi::MisoPin)), 477 (("spi", "MISO"), quote!(crate::spi::MisoPin)),
@@ -750,6 +759,8 @@ fn main() {
750 (("usart", "TX"), quote!(crate::usart::TxDma)), 759 (("usart", "TX"), quote!(crate::usart::TxDma)),
751 (("lpuart", "RX"), quote!(crate::usart::RxDma)), 760 (("lpuart", "RX"), quote!(crate::usart::RxDma)),
752 (("lpuart", "TX"), quote!(crate::usart::TxDma)), 761 (("lpuart", "TX"), quote!(crate::usart::TxDma)),
762 (("sai", "A"), quote!(crate::sai::DmaA)),
763 (("sai", "B"), quote!(crate::sai::DmaB)),
753 (("spi", "RX"), quote!(crate::spi::RxDma)), 764 (("spi", "RX"), quote!(crate::spi::RxDma)),
754 (("spi", "TX"), quote!(crate::spi::TxDma)), 765 (("spi", "TX"), quote!(crate::spi::TxDma)),
755 (("i2c", "RX"), quote!(crate::i2c::RxDma)), 766 (("i2c", "RX"), quote!(crate::i2c::RxDma)),
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 1e184f9d7..2718c96da 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -55,6 +55,8 @@ pub mod qspi;
55pub mod rng; 55pub mod rng;
56#[cfg(all(rtc, not(rtc_v1)))] 56#[cfg(all(rtc, not(rtc_v1)))]
57pub mod rtc; 57pub mod rtc;
58#[cfg(sai)]
59pub mod sai;
58#[cfg(sdmmc)] 60#[cfg(sdmmc)]
59pub mod sdmmc; 61pub mod sdmmc;
60#[cfg(spi)] 62#[cfg(spi)]
diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs
index 5914c926a..ebf78d0e2 100644
--- a/embassy-stm32/src/rcc/f4.rs
+++ b/embassy-stm32/src/rcc/f4.rs
@@ -32,6 +32,9 @@ pub struct Config {
32 #[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] 32 #[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))]
33 pub plli2s: Option<Hertz>, 33 pub plli2s: Option<Hertz>,
34 34
35 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
36 pub pllsai: Option<Hertz>,
37
35 pub pll48: bool, 38 pub pll48: bool,
36 pub rtc: Option<RtcClockSource>, 39 pub rtc: Option<RtcClockSource>,
37 pub lsi: bool, 40 pub lsi: bool,
@@ -50,10 +53,9 @@ fn setup_i2s_pll(_vco_in: u32, _plli2s: Option<u32>) -> Option<u32> {
50} 53}
51 54
52#[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] 55#[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))]
53fn setup_i2s_pll(vco_in: u32, plli2s: Option<u32>) -> Option<u32> { 56fn calculate_sai_i2s_pll_values(vco_in: u32, max_div: u32, target: Option<u32>) -> Option<(u32, u32, u32)> {
54 let min_div = 2; 57 let min_div = 2;
55 let max_div = 7; 58 let target = match target {
56 let target = match plli2s {
57 Some(target) => target, 59 Some(target) => target,
58 None => return None, 60 None => return None,
59 }; 61 };
@@ -77,15 +79,48 @@ fn setup_i2s_pll(vco_in: u32, plli2s: Option<u32>) -> Option<u32> {
77 }) 79 })
78 .min_by_key(|(_, _, _, error)| *error)?; 80 .min_by_key(|(_, _, _, error)| *error)?;
79 81
82 Some((n, outdiv, output))
83}
84
85#[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))]
86fn setup_i2s_pll(vco_in: u32, plli2s: Option<u32>) -> Option<u32> {
87 let (n, outdiv, output) = calculate_sai_i2s_pll_values(vco_in, 7, plli2s)?;
88
80 RCC.plli2scfgr().modify(|w| { 89 RCC.plli2scfgr().modify(|w| {
81 w.set_plli2sn(n as u16); 90 w.set_plli2sn(n as u16);
82 w.set_plli2sr(outdiv as u8); 91 w.set_plli2sr(outdiv as u8);
92 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
93 w.set_plli2sq(outdiv as u8); //set sai divider same as i2s
83 }); 94 });
84 95
85 Some(output) 96 Some(output)
86} 97}
87 98
88fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, plli2s: Option<u32>, pll48clk: bool) -> PllResults { 99#[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479)))]
100fn setup_sai_pll(_vco_in: u32, _pllsai: Option<u32>) -> Option<u32> {
101 None
102}
103
104#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
105fn setup_sai_pll(vco_in: u32, pllsai: Option<u32>) -> Option<u32> {
106 let (n, outdiv, output) = calculate_sai_i2s_pll_values(vco_in, 15, pllsai)?;
107
108 RCC.pllsaicfgr().modify(|w| {
109 w.set_pllsain(n as u16);
110 w.set_pllsaiq(outdiv as u8);
111 });
112
113 Some(output)
114}
115
116fn setup_pll(
117 pllsrcclk: u32,
118 use_hse: bool,
119 pllsysclk: Option<u32>,
120 plli2s: Option<u32>,
121 pllsai: Option<u32>,
122 pll48clk: bool,
123) -> PllResults {
89 use crate::pac::rcc::vals::{Pllp, Pllsrc}; 124 use crate::pac::rcc::vals::{Pllp, Pllsrc};
90 125
91 let sysclk = pllsysclk.unwrap_or(pllsrcclk); 126 let sysclk = pllsysclk.unwrap_or(pllsrcclk);
@@ -97,6 +132,7 @@ fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, plli2s: Opti
97 pllsysclk: None, 132 pllsysclk: None,
98 pll48clk: None, 133 pll48clk: None,
99 plli2sclk: None, 134 plli2sclk: None,
135 pllsaiclk: None,
100 }; 136 };
101 } 137 }
102 // Input divisor from PLL source clock, must result to frequency in 138 // Input divisor from PLL source clock, must result to frequency in
@@ -147,6 +183,7 @@ fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, plli2s: Opti
147 w.set_pllp(Pllp::from_bits(pllp as u8)); 183 w.set_pllp(Pllp::from_bits(pllp as u8));
148 w.set_pllq(pllq as u8); 184 w.set_pllq(pllq as u8);
149 w.set_pllsrc(Pllsrc::from_bits(use_hse as u8)); 185 w.set_pllsrc(Pllsrc::from_bits(use_hse as u8));
186 w.set_pllr(0);
150 }); 187 });
151 188
152 let real_pllsysclk = vco_in * plln / sysclk_div; 189 let real_pllsysclk = vco_in * plln / sysclk_div;
@@ -156,6 +193,7 @@ fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, plli2s: Opti
156 pllsysclk: Some(real_pllsysclk), 193 pllsysclk: Some(real_pllsysclk),
157 pll48clk: if pll48clk { Some(real_pll48clk) } else { None }, 194 pll48clk: if pll48clk { Some(real_pll48clk) } else { None },
158 plli2sclk: setup_i2s_pll(vco_in, plli2s), 195 plli2sclk: setup_i2s_pll(vco_in, plli2s),
196 pllsaiclk: setup_sai_pll(vco_in, pllsai),
159 } 197 }
160} 198}
161 199
@@ -343,6 +381,10 @@ pub(crate) unsafe fn init(config: Config) {
343 config.plli2s.map(|i2s| i2s.0), 381 config.plli2s.map(|i2s| i2s.0),
344 #[cfg(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))] 382 #[cfg(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))]
345 None, 383 None,
384 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
385 config.pllsai.map(|sai| sai.0),
386 #[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479)))]
387 None,
346 config.pll48, 388 config.pll48,
347 ); 389 );
348 390
@@ -440,6 +482,12 @@ pub(crate) unsafe fn init(config: Config) {
440 while !RCC.cr().read().plli2srdy() {} 482 while !RCC.cr().read().plli2srdy() {}
441 } 483 }
442 484
485 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
486 if plls.pllsaiclk.is_some() {
487 RCC.cr().modify(|w| w.set_pllsaion(true));
488 while !RCC.cr().read().pllsairdy() {}
489 }
490
443 RCC.cfgr().modify(|w| { 491 RCC.cfgr().modify(|w| {
444 w.set_ppre2(Ppre::from_bits(ppre2_bits)); 492 w.set_ppre2(Ppre::from_bits(ppre2_bits));
445 w.set_ppre1(Ppre::from_bits(ppre1_bits)); 493 w.set_ppre1(Ppre::from_bits(ppre1_bits));
@@ -490,7 +538,7 @@ pub(crate) unsafe fn init(config: Config) {
490 plli2s: plls.plli2sclk.map(Hertz), 538 plli2s: plls.plli2sclk.map(Hertz),
491 539
492 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] 540 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
493 pllsai: None, 541 pllsai: plls.pllsaiclk.map(Hertz),
494 542
495 rtc: rtc, 543 rtc: rtc,
496 rtc_hse: None, 544 rtc_hse: None,
@@ -503,6 +551,8 @@ struct PllResults {
503 pll48clk: Option<u32>, 551 pll48clk: Option<u32>,
504 #[allow(dead_code)] 552 #[allow(dead_code)]
505 plli2sclk: Option<u32>, 553 plli2sclk: Option<u32>,
554 #[allow(dead_code)]
555 pllsaiclk: Option<u32>,
506} 556}
507 557
508mod max { 558mod max {
diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs
new file mode 100644
index 000000000..4ffa6e9ce
--- /dev/null
+++ b/embassy-stm32/src/sai/mod.rs
@@ -0,0 +1,894 @@
1#![macro_use]
2
3use embassy_embedded_hal::SetConfig;
4use embassy_hal_internal::{into_ref, PeripheralRef};
5
6pub use crate::dma::word;
7use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, TransferOptions, WritableRingBuffer};
8use crate::gpio::sealed::{AFType, Pin as _};
9use crate::gpio::AnyPin;
10use crate::pac::sai::{vals, Sai as Regs};
11use crate::rcc::RccPeripheral;
12use crate::{peripherals, Peripheral};
13
14#[derive(Debug)]
15#[cfg_attr(feature = "defmt", derive(defmt::Format))]
16pub enum Error {
17 NotATransmitter,
18 NotAReceiver,
19 OverrunError,
20}
21
22impl From<ringbuffer::OverrunError> for Error {
23 fn from(_: ringbuffer::OverrunError) -> Self {
24 Self::OverrunError
25 }
26}
27
28#[derive(Copy, Clone)]
29pub enum SyncBlock {
30 None,
31 Sai1BlockA,
32 Sai1BlockB,
33 Sai2BlockA,
34 Sai2BlockB,
35}
36
37#[derive(Copy, Clone)]
38pub enum SyncIn {
39 None,
40 ChannelZero,
41 ChannelOne,
42}
43
44#[derive(Copy, Clone)]
45pub enum Mode {
46 Master,
47 Slave,
48}
49
50#[derive(Copy, Clone)]
51enum TxRx {
52 Transmiter,
53 Receiver,
54}
55
56impl Mode {
57 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
58 const fn mode(&self, tx_rx: TxRx) -> vals::Mode {
59 match tx_rx {
60 TxRx::Transmiter => match self {
61 Mode::Master => vals::Mode::MASTERTX,
62 Mode::Slave => vals::Mode::SLAVETX,
63 },
64 TxRx::Receiver => match self {
65 Mode::Master => vals::Mode::MASTERRX,
66 Mode::Slave => vals::Mode::SLAVERX,
67 },
68 }
69 }
70}
71
72#[derive(Copy, Clone)]
73pub enum SlotSize {
74 DataSize,
75 /// 16 bit data length on 16 bit wide channel
76 Channel16,
77 /// 16 bit data length on 32 bit wide channel
78 Channel32,
79}
80
81impl SlotSize {
82 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
83 pub const fn slotsz(&self) -> vals::Slotsz {
84 match self {
85 SlotSize::DataSize => vals::Slotsz::DATASIZE,
86 SlotSize::Channel16 => vals::Slotsz::BIT16,
87 SlotSize::Channel32 => vals::Slotsz::BIT32,
88 }
89 }
90}
91
92#[derive(Copy, Clone)]
93pub enum DataSize {
94 Data8,
95 Data10,
96 Data16,
97 Data20,
98 Data24,
99 Data32,
100}
101
102impl DataSize {
103 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
104 pub const fn ds(&self) -> vals::Ds {
105 match self {
106 DataSize::Data8 => vals::Ds::BIT8,
107 DataSize::Data10 => vals::Ds::BIT10,
108 DataSize::Data16 => vals::Ds::BIT16,
109 DataSize::Data20 => vals::Ds::BIT20,
110 DataSize::Data24 => vals::Ds::BIT24,
111 DataSize::Data32 => vals::Ds::BIT32,
112 }
113 }
114}
115
116#[derive(Copy, Clone)]
117pub enum FifoThreshold {
118 Empty,
119 Quarter,
120 Half,
121 ThreeQuarters,
122 Full,
123}
124
125impl FifoThreshold {
126 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
127 pub const fn fth(&self) -> vals::Fth {
128 match self {
129 FifoThreshold::Empty => vals::Fth::EMPTY,
130 FifoThreshold::Quarter => vals::Fth::QUARTER1,
131 FifoThreshold::Half => vals::Fth::QUARTER2,
132 FifoThreshold::ThreeQuarters => vals::Fth::QUARTER3,
133 FifoThreshold::Full => vals::Fth::FULL,
134 }
135 }
136}
137
138#[derive(Copy, Clone)]
139pub enum FifoLevel {
140 Empty,
141 FirstQuarter,
142 SecondQuarter,
143 ThirdQuarter,
144 FourthQuarter,
145 Full,
146}
147
148#[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
149impl From<vals::Flvl> for FifoLevel {
150 fn from(flvl: vals::Flvl) -> Self {
151 match flvl {
152 vals::Flvl::EMPTY => FifoLevel::Empty,
153 vals::Flvl::QUARTER1 => FifoLevel::FirstQuarter,
154 vals::Flvl::QUARTER2 => FifoLevel::SecondQuarter,
155 vals::Flvl::QUARTER3 => FifoLevel::ThirdQuarter,
156 vals::Flvl::QUARTER4 => FifoLevel::FourthQuarter,
157 vals::Flvl::FULL => FifoLevel::Full,
158 _ => FifoLevel::Empty,
159 }
160 }
161}
162
163#[derive(Copy, Clone)]
164pub enum MuteDetection {
165 NoMute,
166 Mute,
167}
168
169#[derive(Copy, Clone)]
170pub enum MuteValue {
171 Zero,
172 LastValue,
173}
174
175impl MuteValue {
176 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
177 pub const fn muteval(&self) -> vals::Muteval {
178 match self {
179 MuteValue::Zero => vals::Muteval::SENDZERO,
180 MuteValue::LastValue => vals::Muteval::SENDLAST,
181 }
182 }
183}
184
185#[derive(Copy, Clone)]
186pub enum OverUnderStatus {
187 NoError,
188 OverUnderRunDetected,
189}
190
191#[derive(Copy, Clone)]
192pub enum Protocol {
193 Free,
194 Spdif,
195 Ac97,
196}
197
198impl Protocol {
199 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
200 pub const fn prtcfg(&self) -> vals::Prtcfg {
201 match self {
202 Protocol::Free => vals::Prtcfg::FREE,
203 Protocol::Spdif => vals::Prtcfg::SPDIF,
204 Protocol::Ac97 => vals::Prtcfg::AC97,
205 }
206 }
207}
208
209#[derive(Copy, Clone)]
210pub enum SyncEnable {
211 Asynchronous,
212 /// Syncs with the other A/B sub-block within the SAI unit
213 Internal,
214 /// Syncs with a sub-block in the other SAI unit - use set_sync_output() and set_sync_input()
215 External,
216}
217
218impl SyncEnable {
219 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
220 pub const fn syncen(&self) -> vals::Syncen {
221 match self {
222 SyncEnable::Asynchronous => vals::Syncen::ASYNCHRONOUS,
223 SyncEnable::Internal => vals::Syncen::INTERNAL,
224 SyncEnable::External => vals::Syncen::EXTERNAL,
225 }
226 }
227}
228
229#[derive(Copy, Clone, PartialEq)]
230pub enum StereoMono {
231 Stereo,
232 Mono,
233}
234
235impl StereoMono {
236 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
237 pub const fn mono(&self) -> vals::Mono {
238 match self {
239 StereoMono::Stereo => vals::Mono::STEREO,
240 StereoMono::Mono => vals::Mono::MONO,
241 }
242 }
243}
244
245#[derive(Copy, Clone)]
246pub enum BitOrder {
247 LsbFirst,
248 MsbFirst,
249}
250
251impl BitOrder {
252 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
253 pub const fn lsbfirst(&self) -> vals::Lsbfirst {
254 match self {
255 BitOrder::LsbFirst => vals::Lsbfirst::LSBFIRST,
256 BitOrder::MsbFirst => vals::Lsbfirst::MSBFIRST,
257 }
258 }
259}
260
261#[derive(Copy, Clone)]
262pub enum FrameSyncOffset {
263 /// This is used in modes other than standard I2S phillips mode
264 OnFirstBit,
265 /// This is used in standard I2S phillips mode
266 BeforeFirstBit,
267}
268
269impl FrameSyncOffset {
270 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
271 pub const fn fsoff(&self) -> vals::Fsoff {
272 match self {
273 FrameSyncOffset::OnFirstBit => vals::Fsoff::ONFIRST,
274 FrameSyncOffset::BeforeFirstBit => vals::Fsoff::BEFOREFIRST,
275 }
276 }
277}
278
279#[derive(Copy, Clone)]
280pub enum FrameSyncPolarity {
281 ActiveLow,
282 ActiveHigh,
283}
284
285impl FrameSyncPolarity {
286 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
287 pub const fn fspol(&self) -> vals::Fspol {
288 match self {
289 FrameSyncPolarity::ActiveLow => vals::Fspol::FALLINGEDGE,
290 FrameSyncPolarity::ActiveHigh => vals::Fspol::RISINGEDGE,
291 }
292 }
293}
294
295#[derive(Copy, Clone)]
296pub enum FrameSyncDefinition {
297 StartOfFrame,
298 ChannelIdentification,
299}
300
301impl FrameSyncDefinition {
302 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
303 pub const fn fsdef(&self) -> bool {
304 match self {
305 FrameSyncDefinition::StartOfFrame => false,
306 FrameSyncDefinition::ChannelIdentification => true,
307 }
308 }
309}
310
311#[derive(Copy, Clone)]
312pub enum ClockStrobe {
313 Falling,
314 Rising,
315}
316
317impl ClockStrobe {
318 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
319 pub const fn ckstr(&self) -> vals::Ckstr {
320 match self {
321 ClockStrobe::Falling => vals::Ckstr::FALLINGEDGE,
322 ClockStrobe::Rising => vals::Ckstr::RISINGEDGE,
323 }
324 }
325}
326
327#[derive(Copy, Clone)]
328pub enum ComplementFormat {
329 OnesComplement,
330 TwosComplement,
331}
332
333impl ComplementFormat {
334 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
335 pub const fn cpl(&self) -> vals::Cpl {
336 match self {
337 ComplementFormat::OnesComplement => vals::Cpl::ONESCOMPLEMENT,
338 ComplementFormat::TwosComplement => vals::Cpl::TWOSCOMPLEMENT,
339 }
340 }
341}
342
343#[derive(Copy, Clone)]
344pub enum Companding {
345 None,
346 MuLaw,
347 ALaw,
348}
349
350impl Companding {
351 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
352 pub const fn comp(&self) -> vals::Comp {
353 match self {
354 Companding::None => vals::Comp::NOCOMPANDING,
355 Companding::MuLaw => vals::Comp::MULAW,
356 Companding::ALaw => vals::Comp::ALAW,
357 }
358 }
359}
360
361#[derive(Copy, Clone)]
362pub enum OutputDrive {
363 OnStart,
364 Immediately,
365}
366
367impl OutputDrive {
368 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
369 pub const fn outdriv(&self) -> vals::Outdriv {
370 match self {
371 OutputDrive::OnStart => vals::Outdriv::ONSTART,
372 OutputDrive::Immediately => vals::Outdriv::IMMEDIATELY,
373 }
374 }
375}
376
377#[derive(Copy, Clone, PartialEq)]
378pub enum MasterClockDivider {
379 MasterClockDisabled,
380 Div1,
381 Div2,
382 Div4,
383 Div6,
384 Div8,
385 Div10,
386 Div12,
387 Div14,
388 Div16,
389 Div18,
390 Div20,
391 Div22,
392 Div24,
393 Div26,
394 Div28,
395 Div30,
396}
397
398impl MasterClockDivider {
399 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
400 pub const fn mckdiv(&self) -> u8 {
401 match self {
402 MasterClockDivider::MasterClockDisabled => 0,
403 MasterClockDivider::Div1 => 0,
404 MasterClockDivider::Div2 => 1,
405 MasterClockDivider::Div4 => 2,
406 MasterClockDivider::Div6 => 3,
407 MasterClockDivider::Div8 => 4,
408 MasterClockDivider::Div10 => 5,
409 MasterClockDivider::Div12 => 6,
410 MasterClockDivider::Div14 => 7,
411 MasterClockDivider::Div16 => 8,
412 MasterClockDivider::Div18 => 9,
413 MasterClockDivider::Div20 => 10,
414 MasterClockDivider::Div22 => 11,
415 MasterClockDivider::Div24 => 12,
416 MasterClockDivider::Div26 => 13,
417 MasterClockDivider::Div28 => 14,
418 MasterClockDivider::Div30 => 15,
419 }
420 }
421}
422
423/// [`SAI`] configuration.
424#[non_exhaustive]
425#[derive(Copy, Clone)]
426pub struct Config {
427 pub mode: Mode,
428 pub sync_enable: SyncEnable,
429 pub is_sync_output: bool,
430 pub protocol: Protocol,
431 pub slot_size: SlotSize,
432 pub slot_count: word::U4,
433 pub slot_enable: u16,
434 pub first_bit_offset: word::U5,
435 pub data_size: DataSize,
436 pub stereo_mono: StereoMono,
437 pub bit_order: BitOrder,
438 pub frame_sync_offset: FrameSyncOffset,
439 pub frame_sync_polarity: FrameSyncPolarity,
440 pub frame_sync_active_level_length: word::U7,
441 pub frame_sync_definition: FrameSyncDefinition,
442 pub frame_length: u8,
443 pub clock_strobe: ClockStrobe,
444 pub output_drive: OutputDrive,
445 pub master_clock_divider: MasterClockDivider,
446 pub is_high_impedenane_on_inactive_slot: bool,
447 pub fifo_threshold: FifoThreshold,
448 pub companding: Companding,
449 pub complement_format: ComplementFormat,
450 pub mute_value: MuteValue,
451 pub mute_detection_counter: word::U5,
452}
453
454impl Default for Config {
455 fn default() -> Self {
456 Self {
457 mode: Mode::Master,
458 is_sync_output: false,
459 sync_enable: SyncEnable::Asynchronous,
460 protocol: Protocol::Free,
461 slot_size: SlotSize::DataSize,
462 slot_count: word::U4(2),
463 first_bit_offset: word::U5(0),
464 slot_enable: 0b11,
465 data_size: DataSize::Data16,
466 stereo_mono: StereoMono::Stereo,
467 bit_order: BitOrder::LsbFirst,
468 frame_sync_offset: FrameSyncOffset::BeforeFirstBit,
469 frame_sync_polarity: FrameSyncPolarity::ActiveLow,
470 frame_sync_active_level_length: word::U7(16),
471 frame_sync_definition: FrameSyncDefinition::ChannelIdentification,
472 frame_length: 32,
473 master_clock_divider: MasterClockDivider::MasterClockDisabled,
474 clock_strobe: ClockStrobe::Rising,
475 output_drive: OutputDrive::Immediately,
476 is_high_impedenane_on_inactive_slot: false,
477 fifo_threshold: FifoThreshold::ThreeQuarters,
478 companding: Companding::None,
479 complement_format: ComplementFormat::TwosComplement,
480 mute_value: MuteValue::Zero,
481 mute_detection_counter: word::U5(4),
482 }
483 }
484}
485
486impl Config {
487 pub fn new_i2s() -> Self {
488 return Default::default();
489 }
490
491 pub fn new_msb_first() -> Self {
492 Self {
493 bit_order: BitOrder::MsbFirst,
494 frame_sync_offset: FrameSyncOffset::OnFirstBit,
495 ..Default::default()
496 }
497 }
498}
499
500#[derive(Copy, Clone)]
501pub enum SubBlock {
502 A = 0,
503 B = 1,
504}
505
506enum RingBuffer<'d, C: Channel, W: word::Word> {
507 Writable(WritableRingBuffer<'d, C, W>),
508 #[allow(dead_code)] // remove this after implementing new_* functions for receiver
509 Readable(ReadableRingBuffer<'d, C, W>),
510}
511
512#[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
513fn wdr<W: word::Word>(w: crate::pac::sai::Sai, sub_block: SubBlock) -> *mut W {
514 let ch = w.ch(sub_block as usize);
515 ch.dr().as_ptr() as _
516}
517
518pub struct Sai<'d, T: Instance, C: Channel, W: word::Word> {
519 _peri: PeripheralRef<'d, T>,
520 sd: Option<PeripheralRef<'d, AnyPin>>,
521 fs: Option<PeripheralRef<'d, AnyPin>>,
522 sck: Option<PeripheralRef<'d, AnyPin>>,
523 mclk: Option<PeripheralRef<'d, AnyPin>>,
524 ring_buffer: RingBuffer<'d, C, W>,
525 sub_block: SubBlock,
526}
527
528impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> {
529 fn get_transmitter_af_types(mode: Mode) -> (AFType, AFType) {
530 match mode {
531 Mode::Master => (AFType::OutputPushPull, AFType::OutputPushPull),
532 Mode::Slave => (AFType::OutputPushPull, AFType::Input),
533 }
534 }
535
536 pub fn new_asynchronous_transmitter_with_mclk_a(
537 peri: impl Peripheral<P = T> + 'd,
538 sck: impl Peripheral<P = impl SckAPin<T>> + 'd,
539 sd: impl Peripheral<P = impl SdAPin<T>> + 'd,
540 fs: impl Peripheral<P = impl FsAPin<T>> + 'd,
541 mclk: impl Peripheral<P = impl MclkAPin<T>> + 'd,
542 dma: impl Peripheral<P = C> + 'd,
543 dma_buf: &'d mut [W],
544 mut config: Config,
545 ) -> Self
546 where
547 C: Channel + DmaA<T>,
548 {
549 into_ref!(mclk);
550
551 mclk.set_as_af(mclk.af_num(), AFType::OutputPushPull);
552 mclk.set_speed(crate::gpio::Speed::VeryHigh);
553
554 if config.master_clock_divider == MasterClockDivider::MasterClockDisabled {
555 config.master_clock_divider = MasterClockDivider::Div1;
556 }
557
558 Self::new_asynchronous_transmitter_a(peri, sck, sd, fs, dma, dma_buf, config)
559 }
560
561 pub fn new_asynchronous_transmitter_a(
562 peri: impl Peripheral<P = T> + 'd,
563 sck: impl Peripheral<P = impl SckAPin<T>> + 'd,
564 sd: impl Peripheral<P = impl SdAPin<T>> + 'd,
565 fs: impl Peripheral<P = impl FsAPin<T>> + 'd,
566 dma: impl Peripheral<P = C> + 'd,
567 dma_buf: &'d mut [W],
568 config: Config,
569 ) -> Self
570 where
571 C: Channel + DmaA<T>,
572 {
573 into_ref!(peri, dma, sck, sd, fs);
574
575 let (sd_af_type, ck_af_type) = Self::get_transmitter_af_types(config.mode);
576 sd.set_as_af(sd.af_num(), sd_af_type);
577 sd.set_speed(crate::gpio::Speed::VeryHigh);
578
579 sck.set_as_af(sck.af_num(), ck_af_type);
580 sck.set_speed(crate::gpio::Speed::VeryHigh);
581 fs.set_as_af(fs.af_num(), ck_af_type);
582 fs.set_speed(crate::gpio::Speed::VeryHigh);
583
584 let request = dma.request();
585 let opts = TransferOptions {
586 half_transfer_ir: true,
587 circular: true,
588 ..Default::default()
589 };
590
591 let sub_block = SubBlock::A;
592
593 Self::new_inner(
594 peri,
595 sub_block,
596 Some(sck.map_into()),
597 None,
598 Some(sd.map_into()),
599 Some(fs.map_into()),
600 RingBuffer::Writable(unsafe {
601 WritableRingBuffer::new_write(dma, request, wdr(T::REGS, sub_block), dma_buf, opts)
602 }),
603 config,
604 )
605 }
606
607 pub fn new_asynchronous_transmitter_with_mclk_b(
608 peri: impl Peripheral<P = T> + 'd,
609 sck: impl Peripheral<P = impl SckBPin<T>> + 'd,
610 sd: impl Peripheral<P = impl SdBPin<T>> + 'd,
611 fs: impl Peripheral<P = impl FsBPin<T>> + 'd,
612 mclk: impl Peripheral<P = impl MclkBPin<T>> + 'd,
613 dma: impl Peripheral<P = C> + 'd,
614 dma_buf: &'d mut [W],
615 mut config: Config,
616 ) -> Self
617 where
618 C: Channel + DmaB<T>,
619 {
620 into_ref!(mclk);
621
622 mclk.set_as_af(mclk.af_num(), AFType::OutputPushPull);
623 mclk.set_speed(crate::gpio::Speed::VeryHigh);
624
625 if config.master_clock_divider == MasterClockDivider::MasterClockDisabled {
626 config.master_clock_divider = MasterClockDivider::Div1;
627 }
628
629 Self::new_asynchronous_transmitter_b(peri, sck, sd, fs, dma, dma_buf, config)
630 }
631
632 pub fn new_asynchronous_transmitter_b(
633 peri: impl Peripheral<P = T> + 'd,
634 sck: impl Peripheral<P = impl SckBPin<T>> + 'd,
635 sd: impl Peripheral<P = impl SdBPin<T>> + 'd,
636 fs: impl Peripheral<P = impl FsBPin<T>> + 'd,
637 dma: impl Peripheral<P = C> + 'd,
638 dma_buf: &'d mut [W],
639 config: Config,
640 ) -> Self
641 where
642 C: Channel + DmaB<T>,
643 {
644 into_ref!(dma, peri, sck, sd, fs);
645
646 let (sd_af_type, ck_af_type) = Self::get_transmitter_af_types(config.mode);
647
648 sd.set_as_af(sd.af_num(), sd_af_type);
649 sd.set_speed(crate::gpio::Speed::VeryHigh);
650
651 sck.set_as_af(sck.af_num(), ck_af_type);
652 sck.set_speed(crate::gpio::Speed::VeryHigh);
653 fs.set_as_af(fs.af_num(), ck_af_type);
654 fs.set_speed(crate::gpio::Speed::VeryHigh);
655
656 let request = dma.request();
657 let opts = TransferOptions {
658 half_transfer_ir: true,
659 ..Default::default()
660 };
661
662 let sub_block = SubBlock::B;
663
664 Self::new_inner(
665 peri,
666 sub_block,
667 Some(sck.map_into()),
668 None,
669 Some(sd.map_into()),
670 Some(fs.map_into()),
671 RingBuffer::Writable(unsafe {
672 WritableRingBuffer::new_write(dma, request, wdr(T::REGS, sub_block), dma_buf, opts)
673 }),
674 config,
675 )
676 }
677
678 pub fn start(self: &mut Self) {
679 match self.ring_buffer {
680 RingBuffer::Writable(ref mut rb) => {
681 rb.start();
682 }
683 RingBuffer::Readable(ref mut rb) => {
684 rb.start();
685 }
686 }
687 }
688
689 fn is_transmitter(ring_buffer: &RingBuffer<C, W>) -> bool {
690 match ring_buffer {
691 RingBuffer::Writable(_) => true,
692 _ => false,
693 }
694 }
695
696 fn new_inner(
697 peri: impl Peripheral<P = T> + 'd,
698 sub_block: SubBlock,
699 sck: Option<PeripheralRef<'d, AnyPin>>,
700 mclk: Option<PeripheralRef<'d, AnyPin>>,
701 sd: Option<PeripheralRef<'d, AnyPin>>,
702 fs: Option<PeripheralRef<'d, AnyPin>>,
703 ring_buffer: RingBuffer<'d, C, W>,
704 config: Config,
705 ) -> Self {
706 T::enable();
707 T::reset();
708
709 #[cfg(any(sai_v4))]
710 {
711 // Not totally clear from the datasheet if this is right
712 // This is only used if using SyncEnable::External
713 let value: u8 = if T::REGS.as_ptr() == stm32_metapac::SAI1.as_ptr() {
714 1 //this is SAI1, so sync with SAI2
715 } else {
716 0 //this is SAI2, so sync with SAI1
717 };
718 T::REGS.gcr().modify(|w| {
719 w.set_syncin(value);
720 });
721
722 if config.is_sync_output {
723 let syncout: u8 = match sub_block {
724 SubBlock::A => 0b01,
725 SubBlock::B => 0b10,
726 };
727 T::REGS.gcr().modify(|w| {
728 w.set_syncout(syncout);
729 });
730 }
731 }
732
733 #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))]
734 {
735 let ch = T::REGS.ch(sub_block as usize);
736 ch.cr1().modify(|w| {
737 w.set_mode(config.mode.mode(if Self::is_transmitter(&ring_buffer) {
738 TxRx::Transmiter
739 } else {
740 TxRx::Receiver
741 }));
742 w.set_prtcfg(config.protocol.prtcfg());
743 w.set_ds(config.data_size.ds());
744 w.set_lsbfirst(config.bit_order.lsbfirst());
745 w.set_ckstr(config.clock_strobe.ckstr());
746 w.set_syncen(config.sync_enable.syncen());
747 w.set_mono(config.stereo_mono.mono());
748 w.set_outdriv(config.output_drive.outdriv());
749 w.set_mckdiv(config.master_clock_divider.mckdiv());
750 w.set_nodiv(
751 if config.master_clock_divider == MasterClockDivider::MasterClockDisabled {
752 vals::Nodiv::NODIV
753 } else {
754 vals::Nodiv::MASTERCLOCK
755 },
756 );
757 w.set_dmaen(true);
758 });
759
760 ch.cr2().modify(|w| {
761 w.set_fth(config.fifo_threshold.fth());
762 w.set_comp(config.companding.comp());
763 w.set_cpl(config.complement_format.cpl());
764 w.set_muteval(config.mute_value.muteval());
765 w.set_mutecnt(config.mute_detection_counter.0 as u8);
766 w.set_tris(config.is_high_impedenane_on_inactive_slot);
767 });
768
769 ch.frcr().modify(|w| {
770 w.set_fsoff(config.frame_sync_offset.fsoff());
771 w.set_fspol(config.frame_sync_polarity.fspol());
772 w.set_fsdef(config.frame_sync_definition.fsdef());
773 w.set_fsall(config.frame_sync_active_level_length.0 as u8);
774 w.set_frl(config.frame_length - 1);
775 });
776
777 ch.slotr().modify(|w| {
778 w.set_nbslot(config.slot_count.0 as u8 - 1);
779 w.set_slotsz(config.slot_size.slotsz());
780 w.set_fboff(config.first_bit_offset.0 as u8);
781 w.set_sloten(vals::Sloten(config.slot_enable as u16));
782 });
783
784 ch.cr1().modify(|w| w.set_saien(true));
785 }
786
787 Self {
788 _peri: peri.into_ref(),
789 sub_block,
790 sck,
791 mclk,
792 sd,
793 fs,
794 ring_buffer,
795 }
796 }
797
798 pub fn flush(&mut self) {
799 let ch = T::REGS.ch(self.sub_block as usize);
800 ch.cr1().modify(|w| w.set_saien(false));
801 #[cfg(any(sai_v1, sai_v2))]
802 {
803 ch.cr2().modify(|w| w.set_fflush(vals::Fflush::FLUSH));
804 }
805 #[cfg(any(sai_v3, sai_v4))]
806 {
807 ch.cr2().modify(|w| w.set_fflush(true));
808 }
809 ch.cr1().modify(|w| w.set_saien(true));
810 }
811
812 pub fn set_mute(&mut self, value: bool) {
813 let ch = T::REGS.ch(self.sub_block as usize);
814 ch.cr2().modify(|w| w.set_mute(value));
815 }
816
817 /// Reconfigures it with the supplied config.
818 pub fn reconfigure(&mut self, _config: Config) {}
819
820 pub fn get_current_config(&self) -> Config {
821 Config::default()
822 }
823
824 pub async fn write(&mut self, data: &[W]) -> Result<(), Error> {
825 match &mut self.ring_buffer {
826 RingBuffer::Writable(buffer) => {
827 buffer.write_exact(data).await?;
828 Ok(())
829 }
830 _ => return Err(Error::NotATransmitter),
831 }
832 }
833
834 pub async fn read(&mut self, data: &mut [W]) -> Result<(), Error> {
835 match &mut self.ring_buffer {
836 RingBuffer::Readable(buffer) => {
837 buffer.read_exact(data).await?;
838 Ok(())
839 }
840 _ => Err(Error::NotAReceiver),
841 }
842 }
843}
844
845impl<'d, T: Instance, C: Channel, W: word::Word> Drop for Sai<'d, T, C, W> {
846 fn drop(&mut self) {
847 let ch = T::REGS.ch(self.sub_block as usize);
848 ch.cr1().modify(|w| w.set_saien(false));
849 self.fs.as_ref().map(|x| x.set_as_disconnected());
850 self.sd.as_ref().map(|x| x.set_as_disconnected());
851 self.sck.as_ref().map(|x| x.set_as_disconnected());
852 self.mclk.as_ref().map(|x| x.set_as_disconnected());
853 }
854}
855
856pub(crate) mod sealed {
857 use super::*;
858
859 pub trait Instance {
860 const REGS: Regs;
861 }
862}
863
864pub trait Word: word::Word {}
865
866pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {}
867pin_trait!(SckAPin, Instance);
868pin_trait!(SckBPin, Instance);
869pin_trait!(FsAPin, Instance);
870pin_trait!(FsBPin, Instance);
871pin_trait!(SdAPin, Instance);
872pin_trait!(SdBPin, Instance);
873pin_trait!(MclkAPin, Instance);
874pin_trait!(MclkBPin, Instance);
875
876dma_trait!(DmaA, Instance);
877dma_trait!(DmaB, Instance);
878
879foreach_peripheral!(
880 (sai, $inst:ident) => {
881 impl sealed::Instance for peripherals::$inst {
882 const REGS: Regs = crate::pac::$inst;
883 }
884
885 impl Instance for peripherals::$inst {}
886 };
887);
888
889impl<'d, T: Instance, C: Channel, W: word::Word> SetConfig for Sai<'d, T, C, W> {
890 type Config = Config;
891 fn set_config(&mut self, config: &Self::Config) {
892 self.reconfigure(*config);
893 }
894}
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 1d642ed37..d88fbcfdb 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -5,7 +5,6 @@ pub mod simple_pwm;
5use stm32_metapac::timer::vals; 5use stm32_metapac::timer::vals;
6 6
7use crate::interrupt; 7use crate::interrupt;
8use crate::rcc::sealed::RccPeripheral as __RccPeri;
9use crate::rcc::RccPeripheral; 8use crate::rcc::RccPeripheral;
10use crate::time::Hertz; 9use crate::time::Hertz;
11 10
@@ -22,33 +21,88 @@ pub(crate) mod sealed {
22 21
23 fn regs() -> crate::pac::timer::TimBasic; 22 fn regs() -> crate::pac::timer::TimBasic;
24 23
25 fn start(&mut self); 24 fn start(&mut self) {
25 Self::regs().cr1().modify(|r| r.set_cen(true));
26 }
26 27
27 fn stop(&mut self); 28 fn stop(&mut self) {
29 Self::regs().cr1().modify(|r| r.set_cen(false));
30 }
28 31
29 fn reset(&mut self); 32 fn reset(&mut self) {
33 Self::regs().cnt().write(|r| r.set_cnt(0));
34 }
30 35
31 fn set_frequency(&mut self, frequency: Hertz); 36 fn set_frequency(&mut self, frequency: Hertz) {
37 let f = frequency.0;
38 let timer_f = Self::frequency().0;
39 assert!(f > 0);
40 let pclk_ticks_per_timer_period = timer_f / f;
41 let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 16)).try_into());
42 let arr: u16 = unwrap!((pclk_ticks_per_timer_period / (u32::from(psc) + 1)).try_into());
43
44 let regs = Self::regs();
45 regs.psc().write(|r| r.set_psc(psc));
46 regs.arr().write(|r| r.set_arr(arr));
47
48 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY));
49 regs.egr().write(|r| r.set_ug(true));
50 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
51 }
32 52
33 fn clear_update_interrupt(&mut self) -> bool; 53 fn clear_update_interrupt(&mut self) -> bool {
54 let regs = Self::regs();
55 let sr = regs.sr().read();
56 if sr.uif() {
57 regs.sr().modify(|r| {
58 r.set_uif(false);
59 });
60 true
61 } else {
62 false
63 }
64 }
34 65
35 fn enable_update_interrupt(&mut self, enable: bool); 66 fn enable_update_interrupt(&mut self, enable: bool) {
67 Self::regs().dier().write(|r| r.set_uie(enable));
68 }
36 69
37 fn set_autoreload_preload(&mut self, enable: vals::Arpe); 70 fn set_autoreload_preload(&mut self, enable: vals::Arpe) {
71 Self::regs().cr1().modify(|r| r.set_arpe(enable));
72 }
38 } 73 }
39 74
40 pub trait GeneralPurpose16bitInstance: Basic16bitInstance { 75 pub trait GeneralPurpose16bitInstance: Basic16bitInstance {
41 fn regs_gp16() -> crate::pac::timer::TimGp16; 76 fn regs_gp16() -> crate::pac::timer::TimGp16;
42 77
43 fn set_count_direction(&mut self, direction: vals::Dir); 78 fn set_count_direction(&mut self, direction: vals::Dir) {
79 Self::regs_gp16().cr1().modify(|r| r.set_dir(direction));
80 }
44 81
45 fn set_clock_division(&mut self, ckd: vals::Ckd); 82 fn set_clock_division(&mut self, ckd: vals::Ckd) {
83 Self::regs_gp16().cr1().modify(|r| r.set_ckd(ckd));
84 }
46 } 85 }
47 86
48 pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance { 87 pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance {
49 fn regs_gp32() -> crate::pac::timer::TimGp32; 88 fn regs_gp32() -> crate::pac::timer::TimGp32;
50 89
51 fn set_frequency(&mut self, frequency: Hertz); 90 fn set_frequency(&mut self, frequency: Hertz) {
91 let f = frequency.0;
92 assert!(f > 0);
93 let timer_f = Self::frequency().0;
94 let pclk_ticks_per_timer_period = (timer_f / f) as u64;
95 let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 32)).try_into());
96 let arr: u32 = unwrap!((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into());
97
98 let regs = Self::regs_gp32();
99 regs.psc().write(|r| r.set_psc(psc));
100 regs.arr().write(|r| r.set_arr(arr));
101
102 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY));
103 regs.egr().write(|r| r.set_ug(true));
104 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
105 }
52 } 106 }
53 107
54 pub trait AdvancedControlInstance: GeneralPurpose16bitInstance { 108 pub trait AdvancedControlInstance: GeneralPurpose16bitInstance {
@@ -56,68 +110,115 @@ pub(crate) mod sealed {
56 } 110 }
57 111
58 pub trait CaptureCompare16bitInstance: GeneralPurpose16bitInstance { 112 pub trait CaptureCompare16bitInstance: GeneralPurpose16bitInstance {
59 fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf); 113 fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf) {
60 114 let raw_channel = channel.raw();
61 fn clear_input_interrupt(&mut self, channel: Channel); 115 Self::regs_gp16()
62 116 .ccmr_input(raw_channel / 2)
63 fn enable_input_interrupt(&mut self, channel: Channel, enable: bool); 117 .modify(|r| r.set_icf(raw_channel % 2, icf));
64 118 }
65 fn set_input_capture_prescaler(&mut self, channel: Channel, val: u8);
66 119
67 fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection); 120 fn clear_input_interrupt(&mut self, channel: Channel) {
121 Self::regs_gp16().sr().modify(|r| r.set_ccif(channel.raw(), false));
122 }
68 123
69 fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode); 124 fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) {
125 Self::regs_gp16().dier().modify(|r| r.set_ccie(channel.raw(), enable));
126 }
127 fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) {
128 let raw_channel = channel.raw();
129 Self::regs_gp16()
130 .ccmr_input(raw_channel / 2)
131 .modify(|r| r.set_icpsc(raw_channel % 2, factor));
132 }
70 133
71 /// Global output enable. Does not do anything on non-advanced timers. 134 fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
72 fn enable_outputs(&mut self, enable: bool); 135 let raw_channel = channel.raw();
136 Self::regs_gp16()
137 .ccmr_input(raw_channel / 2)
138 .modify(|r| r.set_ccs(raw_channel % 2, tisel.into()));
139 }
140 fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
141 Self::regs_gp16().ccer().modify(|r| match mode {
142 InputCaptureMode::Rising => {
143 r.set_ccnp(channel.raw(), false);
144 r.set_ccp(channel.raw(), false);
145 }
146 InputCaptureMode::Falling => {
147 r.set_ccnp(channel.raw(), false);
148 r.set_ccp(channel.raw(), true);
149 }
150 InputCaptureMode::BothEdges => {
151 r.set_ccnp(channel.raw(), true);
152 r.set_ccp(channel.raw(), true);
153 }
154 });
155 }
156 fn enable_outputs(&mut self, _enable: bool) {}
73 157
74 fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); 158 fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
159 let r = Self::regs_gp16();
160 let raw_channel: usize = channel.raw();
161 r.ccmr_output(raw_channel / 2)
162 .modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
163 }
75 164
76 fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity); 165 fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
166 Self::regs_gp16()
167 .ccer()
168 .modify(|w| w.set_ccp(channel.raw(), polarity.into()));
169 }
77 170
78 fn enable_channel(&mut self, channel: Channel, enable: bool); 171 fn enable_channel(&mut self, channel: Channel, enable: bool) {
172 Self::regs_gp16().ccer().modify(|w| w.set_cce(channel.raw(), enable));
173 }
79 174
80 fn set_compare_value(&mut self, channel: Channel, value: u16); 175 fn set_compare_value(&mut self, channel: Channel, value: u16) {
176 Self::regs_gp16().ccr(channel.raw()).modify(|w| w.set_ccr(value));
177 }
81 178
82 fn get_capture_value(&mut self, channel: Channel) -> u16; 179 fn get_capture_value(&mut self, channel: Channel) -> u16 {
180 Self::regs_gp16().ccr(channel.raw()).read().ccr()
181 }
83 182
84 fn get_max_compare_value(&self) -> u16; 183 fn get_max_compare_value(&self) -> u16 {
184 Self::regs_gp16().arr().read().arr()
185 }
85 } 186 }
86 187
87 pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance { 188 pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance + AdvancedControlInstance {
88 fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity); 189 fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
190 Self::regs_advanced()
191 .ccer()
192 .modify(|w| w.set_ccnp(channel.raw(), polarity.into()));
193 }
89 194
90 fn set_dead_time_clock_division(&mut self, value: vals::Ckd); 195 fn set_dead_time_clock_division(&mut self, value: vals::Ckd) {
196 Self::regs_advanced().cr1().modify(|w| w.set_ckd(value));
197 }
91 198
92 fn set_dead_time_value(&mut self, value: u8); 199 fn set_dead_time_value(&mut self, value: u8) {
200 Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value));
201 }
93 202
94 fn enable_complementary_channel(&mut self, channel: Channel, enable: bool); 203 fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) {
204 Self::regs_advanced()
205 .ccer()
206 .modify(|w| w.set_ccne(channel.raw(), enable));
207 }
95 } 208 }
96 209
97 pub trait CaptureCompare32bitInstance: GeneralPurpose32bitInstance { 210 pub trait CaptureCompare32bitInstance: GeneralPurpose32bitInstance + CaptureCompare16bitInstance {
98 fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf); 211 fn set_compare_value(&mut self, channel: Channel, value: u32) {
99 212 Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value));
100 fn clear_input_interrupt(&mut self, channel: Channel); 213 }
101
102 fn enable_input_interrupt(&mut self, channel: Channel, enable: bool);
103
104 fn set_input_capture_prescaler(&mut self, channel: Channel, val: u8);
105
106 fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection);
107
108 fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode);
109
110 fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode);
111
112 fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity);
113
114 fn enable_channel(&mut self, channel: Channel, enable: bool);
115
116 fn set_compare_value(&mut self, channel: Channel, value: u32);
117 214
118 fn get_capture_value(&mut self, channel: Channel) -> u32; 215 fn get_capture_value(&mut self, channel: Channel) -> u32 {
216 Self::regs_gp32().ccr(channel.raw()).read().ccr()
217 }
119 218
120 fn get_max_compare_value(&self) -> u32; 219 fn get_max_compare_value(&self) -> u32 {
220 Self::regs_gp32().arr().read().arr()
221 }
121 } 222 }
122} 223}
123 224
@@ -254,57 +355,6 @@ macro_rules! impl_basic_16bit_timer {
254 fn regs() -> crate::pac::timer::TimBasic { 355 fn regs() -> crate::pac::timer::TimBasic {
255 unsafe { crate::pac::timer::TimBasic::from_ptr(crate::pac::$inst.as_ptr()) } 356 unsafe { crate::pac::timer::TimBasic::from_ptr(crate::pac::$inst.as_ptr()) }
256 } 357 }
257
258 fn start(&mut self) {
259 Self::regs().cr1().modify(|r| r.set_cen(true));
260 }
261
262 fn stop(&mut self) {
263 Self::regs().cr1().modify(|r| r.set_cen(false));
264 }
265
266 fn reset(&mut self) {
267 Self::regs().cnt().write(|r| r.set_cnt(0));
268 }
269
270 fn set_frequency(&mut self, frequency: Hertz) {
271 use core::convert::TryInto;
272 let f = frequency.0;
273 let timer_f = Self::frequency().0;
274 assert!(f > 0);
275 let pclk_ticks_per_timer_period = timer_f / f;
276 let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 16)).try_into());
277 let arr: u16 = unwrap!((pclk_ticks_per_timer_period / (u32::from(psc) + 1)).try_into());
278
279 let regs = Self::regs();
280 regs.psc().write(|r| r.set_psc(psc));
281 regs.arr().write(|r| r.set_arr(arr));
282
283 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY));
284 regs.egr().write(|r| r.set_ug(true));
285 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
286 }
287
288 fn clear_update_interrupt(&mut self) -> bool {
289 let regs = Self::regs();
290 let sr = regs.sr().read();
291 if sr.uif() {
292 regs.sr().modify(|r| {
293 r.set_uif(false);
294 });
295 true
296 } else {
297 false
298 }
299 }
300
301 fn enable_update_interrupt(&mut self, enable: bool) {
302 Self::regs().dier().write(|r| r.set_uie(enable));
303 }
304
305 fn set_autoreload_preload(&mut self, enable: vals::Arpe) {
306 Self::regs().cr1().modify(|r| r.set_arpe(enable));
307 }
308 } 358 }
309 }; 359 };
310} 360}
@@ -316,24 +366,6 @@ macro_rules! impl_32bit_timer {
316 fn regs_gp32() -> crate::pac::timer::TimGp32 { 366 fn regs_gp32() -> crate::pac::timer::TimGp32 {
317 crate::pac::$inst 367 crate::pac::$inst
318 } 368 }
319
320 fn set_frequency(&mut self, frequency: Hertz) {
321 use core::convert::TryInto;
322 let f = frequency.0;
323 assert!(f > 0);
324 let timer_f = Self::frequency().0;
325 let pclk_ticks_per_timer_period = (timer_f / f) as u64;
326 let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 32)).try_into());
327 let arr: u32 = unwrap!(((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into()));
328
329 let regs = Self::regs_gp32();
330 regs.psc().write(|r| r.set_psc(psc));
331 regs.arr().write(|r| r.set_arr(arr));
332
333 regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY));
334 regs.egr().write(|r| r.set_ug(true));
335 regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT));
336 }
337 } 369 }
338 }; 370 };
339} 371}
@@ -341,99 +373,7 @@ macro_rules! impl_32bit_timer {
341#[allow(unused)] 373#[allow(unused)]
342macro_rules! impl_compare_capable_16bit { 374macro_rules! impl_compare_capable_16bit {
343 ($inst:ident) => { 375 ($inst:ident) => {
344 impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { 376 impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {}
345 fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf) {
346 use sealed::GeneralPurpose16bitInstance;
347 let raw_channel = channel.raw();
348 Self::regs_gp16()
349 .ccmr_input(raw_channel / 2)
350 .modify(|r| r.set_icf(raw_channel % 2, icf));
351 }
352
353 fn clear_input_interrupt(&mut self, channel: Channel) {
354 use sealed::GeneralPurpose16bitInstance;
355 Self::regs_gp16()
356 .sr()
357 .modify(|r| r.set_ccif(channel.raw(), false));
358 }
359
360 fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) {
361 use sealed::GeneralPurpose16bitInstance;
362 Self::regs_gp16()
363 .dier()
364 .modify(|r| r.set_ccie(channel.raw(), enable));
365 }
366 fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) {
367 use sealed::GeneralPurpose16bitInstance;
368 let raw_channel = channel.raw();
369 Self::regs_gp16()
370 .ccmr_input(raw_channel / 2)
371 .modify(|r| r.set_icpsc(raw_channel % 2, factor));
372 }
373
374 fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
375 use sealed::GeneralPurpose16bitInstance;
376 let raw_channel = channel.raw();
377 Self::regs_gp16()
378 .ccmr_input(raw_channel / 2)
379 .modify(|r| r.set_ccs(raw_channel % 2, tisel.into()));
380 }
381 fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
382 use sealed::GeneralPurpose16bitInstance;
383 Self::regs_gp16().ccer().modify(|r| match mode {
384 InputCaptureMode::Rising => {
385 r.set_ccnp(channel.raw(), false);
386 r.set_ccp(channel.raw(), false);
387 }
388 InputCaptureMode::Falling => {
389 r.set_ccnp(channel.raw(), false);
390 r.set_ccp(channel.raw(), true);
391 }
392 InputCaptureMode::BothEdges => {
393 r.set_ccnp(channel.raw(), true);
394 r.set_ccp(channel.raw(), true);
395 }
396 });
397 }
398 fn enable_outputs(&mut self, _enable: bool) {}
399
400 fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
401 use sealed::GeneralPurpose16bitInstance;
402 let r = Self::regs_gp16();
403 let raw_channel: usize = channel.raw();
404 r.ccmr_output(raw_channel / 2)
405 .modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
406 }
407
408 fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
409 use sealed::GeneralPurpose16bitInstance;
410 Self::regs_gp16()
411 .ccer()
412 .modify(|w| w.set_ccp(channel.raw(), polarity.into()));
413 }
414
415 fn enable_channel(&mut self, channel: Channel, enable: bool) {
416 use sealed::GeneralPurpose16bitInstance;
417 Self::regs_gp16()
418 .ccer()
419 .modify(|w| w.set_cce(channel.raw(), enable));
420 }
421
422 fn set_compare_value(&mut self, channel: Channel, value: u16) {
423 use sealed::GeneralPurpose16bitInstance;
424 Self::regs_gp16().ccr(channel.raw()).modify(|w| w.set_ccr(value));
425 }
426
427 fn get_capture_value(&mut self, channel: Channel) -> u16 {
428 use sealed::GeneralPurpose16bitInstance;
429 Self::regs_gp16().ccr(channel.raw()).read().ccr()
430 }
431
432 fn get_max_compare_value(&self) -> u16 {
433 use sealed::GeneralPurpose16bitInstance;
434 Self::regs_gp16().arr().read().arr()
435 }
436 }
437 }; 377 };
438} 378}
439 379
@@ -453,14 +393,6 @@ foreach_interrupt! {
453 fn regs_gp16() -> crate::pac::timer::TimGp16 { 393 fn regs_gp16() -> crate::pac::timer::TimGp16 {
454 crate::pac::$inst 394 crate::pac::$inst
455 } 395 }
456
457 fn set_count_direction(&mut self, direction: vals::Dir) {
458 Self::regs_gp16().cr1().modify(|r| r.set_dir(direction));
459 }
460
461 fn set_clock_division(&mut self, ckd: vals::Ckd) {
462 Self::regs_gp16().cr1().modify(|r| r.set_ckd(ckd));
463 }
464 } 396 }
465 }; 397 };
466 398
@@ -473,111 +405,12 @@ foreach_interrupt! {
473 impl CaptureCompare32bitInstance for crate::peripherals::$inst {} 405 impl CaptureCompare32bitInstance for crate::peripherals::$inst {}
474 impl GeneralPurpose16bitInstance for crate::peripherals::$inst {} 406 impl GeneralPurpose16bitInstance for crate::peripherals::$inst {}
475 impl GeneralPurpose32bitInstance for crate::peripherals::$inst {} 407 impl GeneralPurpose32bitInstance for crate::peripherals::$inst {}
476 408 impl sealed::CaptureCompare32bitInstance for crate::peripherals::$inst {}
477 impl sealed::CaptureCompare32bitInstance for crate::peripherals::$inst {
478 fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf) {
479 use sealed::GeneralPurpose32bitInstance;
480 let raw_channel = channel.raw();
481 Self::regs_gp32()
482 .ccmr_input(raw_channel / 2)
483 .modify(|r| r.set_icf(raw_channel % 2, icf));
484 }
485
486 fn clear_input_interrupt(&mut self, channel: Channel) {
487 use sealed::GeneralPurpose32bitInstance;
488 Self::regs_gp32()
489 .sr()
490 .modify(|r| r.set_ccif(channel.raw(), false));
491 }
492 fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) {
493 use sealed::GeneralPurpose32bitInstance;
494 Self::regs_gp32()
495 .dier()
496 .modify(|r| r.set_ccie(channel.raw(), enable));
497 }
498 fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) {
499 use crate::timer::sealed::GeneralPurpose32bitInstance;
500 let raw_channel = channel.raw();
501 Self::regs_gp32()
502 .ccmr_input(raw_channel / 2)
503 .modify(|r| r.set_icpsc(raw_channel % 2, factor));
504 }
505
506 fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
507 use crate::timer::sealed::GeneralPurpose32bitInstance;
508 let raw_channel = channel.raw();
509 Self::regs_gp32()
510 .ccmr_input(raw_channel / 2)
511 .modify(|r| r.set_ccs(raw_channel % 2, tisel.into()));
512 }
513
514 fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
515 use crate::timer::sealed::GeneralPurpose32bitInstance;
516 Self::regs_gp32().ccer().modify(|r| match mode {
517 InputCaptureMode::Rising => {
518 r.set_ccnp(channel.raw(), false);
519 r.set_ccp(channel.raw(), false);
520 }
521 InputCaptureMode::Falling => {
522 r.set_ccnp(channel.raw(), false);
523 r.set_ccp(channel.raw(), true);
524 }
525 InputCaptureMode::BothEdges => {
526 r.set_ccnp(channel.raw(), true);
527 r.set_ccp(channel.raw(), true);
528 }
529 });
530 }
531 fn set_output_compare_mode(
532 &mut self,
533 channel: Channel,
534 mode: OutputCompareMode,
535 ) {
536 use crate::timer::sealed::GeneralPurpose32bitInstance;
537 let raw_channel = channel.raw();
538 Self::regs_gp32().ccmr_output(raw_channel / 2).modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
539 }
540
541 fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
542 use crate::timer::sealed::GeneralPurpose32bitInstance;
543 Self::regs_gp32()
544 .ccer()
545 .modify(|w| w.set_ccp(channel.raw(), polarity.into()));
546 }
547
548 fn enable_channel(&mut self, channel: Channel, enable: bool) {
549 use crate::timer::sealed::GeneralPurpose32bitInstance;
550 Self::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), enable));
551 }
552
553 fn set_compare_value(&mut self, channel: Channel, value: u32) {
554 use crate::timer::sealed::GeneralPurpose32bitInstance;
555 Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value));
556 }
557
558 fn get_capture_value(&mut self, channel: Channel) -> u32 {
559 use crate::timer::sealed::GeneralPurpose32bitInstance;
560 Self::regs_gp32().ccr(channel.raw()).read().ccr()
561 }
562
563 fn get_max_compare_value(&self) -> u32 {
564 use crate::timer::sealed::GeneralPurpose32bitInstance;
565 Self::regs_gp32().arr().read().arr() as u32
566 }
567 }
568 409
569 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { 410 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst {
570 fn regs_gp16() -> crate::pac::timer::TimGp16 { 411 fn regs_gp16() -> crate::pac::timer::TimGp16 {
571 unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } 412 unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) }
572 } 413 }
573
574 fn set_count_direction(&mut self, direction: vals::Dir) {
575 Self::regs_gp16().cr1().modify(|r| r.set_dir(direction));
576 }
577
578 fn set_clock_division(&mut self, ckd: vals::Ckd) {
579 Self::regs_gp16().cr1().modify(|r| r.set_ckd(ckd));
580 }
581 } 414 }
582 }; 415 };
583 416
@@ -589,19 +422,12 @@ foreach_interrupt! {
589 impl CaptureCompare16bitInstance for crate::peripherals::$inst {} 422 impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
590 impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {} 423 impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
591 impl AdvancedControlInstance for crate::peripherals::$inst {} 424 impl AdvancedControlInstance for crate::peripherals::$inst {}
592 425 impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {}
426 impl sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
593 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { 427 impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst {
594 fn regs_gp16() -> crate::pac::timer::TimGp16 { 428 fn regs_gp16() -> crate::pac::timer::TimGp16 {
595 unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } 429 unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) }
596 } 430 }
597
598 fn set_count_direction(&mut self, direction: vals::Dir) {
599 Self::regs_gp16().cr1().modify(|r| r.set_dir(direction));
600 }
601
602 fn set_clock_division(&mut self, ckd: vals::Ckd) {
603 Self::regs_gp16().cr1().modify(|r| r.set_ckd(ckd));
604 }
605 } 431 }
606 432
607 impl sealed::AdvancedControlInstance for crate::peripherals::$inst { 433 impl sealed::AdvancedControlInstance for crate::peripherals::$inst {
@@ -610,133 +436,7 @@ foreach_interrupt! {
610 } 436 }
611 } 437 }
612 438
613 impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {
614 fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf) {
615 use crate::timer::sealed::AdvancedControlInstance;
616 let raw_channel = channel.raw();
617 Self::regs_advanced()
618 .ccmr_input(raw_channel / 2)
619 .modify(|r| r.set_icf(raw_channel % 2, icf));
620 }
621 439
622 fn clear_input_interrupt(&mut self, channel: Channel) {
623 use crate::timer::sealed::AdvancedControlInstance;
624 Self::regs_advanced()
625 .sr()
626 .modify(|r| r.set_ccif(channel.raw(), false));
627 }
628 fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) {
629 use crate::timer::sealed::AdvancedControlInstance;
630 Self::regs_advanced()
631 .dier()
632 .modify(|r| r.set_ccie(channel.raw(), enable));
633 }
634 fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) {
635 use crate::timer::sealed::AdvancedControlInstance;
636 let raw_channel = channel.raw();
637 Self::regs_advanced()
638 .ccmr_input(raw_channel / 2)
639 .modify(|r| r.set_icpsc(raw_channel % 2, factor));
640 }
641 fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
642 use crate::timer::sealed::AdvancedControlInstance;
643 let raw_channel = channel.raw();
644 Self::regs_advanced()
645 .ccmr_input(raw_channel / 2)
646 .modify(|r| r.set_ccs(raw_channel % 2, tisel.into()));
647 }
648 fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
649 use crate::timer::sealed::AdvancedControlInstance;
650 Self::regs_advanced().ccer().modify(|r| match mode {
651 InputCaptureMode::Rising => {
652 r.set_ccnp(channel.raw(), false);
653 r.set_ccp(channel.raw(), false);
654 }
655 InputCaptureMode::Falling => {
656 r.set_ccnp(channel.raw(), false);
657 r.set_ccp(channel.raw(), true);
658 }
659 InputCaptureMode::BothEdges => {
660 r.set_ccnp(channel.raw(), true);
661 r.set_ccp(channel.raw(), true);
662 }
663 });
664 }
665 fn enable_outputs(&mut self, enable: bool) {
666 use crate::timer::sealed::AdvancedControlInstance;
667 let r = Self::regs_advanced();
668 r.bdtr().modify(|w| w.set_moe(enable));
669 }
670
671 fn set_output_compare_mode(
672 &mut self,
673 channel: Channel,
674 mode: OutputCompareMode,
675 ) {
676 use crate::timer::sealed::AdvancedControlInstance;
677 let r = Self::regs_advanced();
678 let raw_channel: usize = channel.raw();
679 r.ccmr_output(raw_channel / 2)
680 .modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
681 }
682
683 fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
684 use crate::timer::sealed::AdvancedControlInstance;
685 Self::regs_advanced()
686 .ccer()
687 .modify(|w| w.set_ccp(channel.raw(), polarity.into()));
688 }
689
690 fn enable_channel(&mut self, channel: Channel, enable: bool) {
691 use crate::timer::sealed::AdvancedControlInstance;
692 Self::regs_advanced()
693 .ccer()
694 .modify(|w| w.set_cce(channel.raw(), enable));
695 }
696
697 fn get_capture_value(&mut self, channel: Channel) -> u16 {
698 use crate::timer::sealed::AdvancedControlInstance;
699 Self::regs_advanced().ccr(channel.raw()).read().ccr()
700 }
701
702 fn set_compare_value(&mut self, channel: Channel, value: u16) {
703 use crate::timer::sealed::AdvancedControlInstance;
704 Self::regs_advanced()
705 .ccr(channel.raw())
706 .modify(|w| w.set_ccr(value));
707 }
708
709 fn get_max_compare_value(&self) -> u16 {
710 use crate::timer::sealed::AdvancedControlInstance;
711 Self::regs_advanced().arr().read().arr()
712 }
713 }
714
715 impl sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {
716 fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
717 use crate::timer::sealed::AdvancedControlInstance;
718 Self::regs_advanced()
719 .ccer()
720 .modify(|w| w.set_ccnp(channel.raw(), polarity.into()));
721 }
722
723 fn set_dead_time_clock_division(&mut self, value: vals::Ckd) {
724 use crate::timer::sealed::AdvancedControlInstance;
725 Self::regs_advanced().cr1().modify(|w| w.set_ckd(value));
726 }
727
728 fn set_dead_time_value(&mut self, value: u8) {
729 use crate::timer::sealed::AdvancedControlInstance;
730 Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value));
731 }
732
733 fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) {
734 use crate::timer::sealed::AdvancedControlInstance;
735 Self::regs_advanced()
736 .ccer()
737 .modify(|w| w.set_ccne(channel.raw(), enable));
738 }
739 }
740 440
741 441
742 }; 442 };
diff --git a/examples/wasm/README.md b/examples/wasm/README.md
index b7fee2dc8..3d300d9aa 100644
--- a/examples/wasm/README.md
+++ b/examples/wasm/README.md
@@ -3,7 +3,7 @@
3Examples use a CLI tool named `wasm-pack` to build this example: 3Examples use a CLI tool named `wasm-pack` to build this example:
4 4
5``` 5```
6cargo install wasm-pack --version 0.9.1 6cargo install wasm-pack --version 0.12.1
7``` 7```
8 8
9## Building 9## Building
@@ -23,4 +23,4 @@ To run the example, start a webserver server the local folder:
23python -m http.server 23python -m http.server
24``` 24```
25 25
26Then, open a browser at https://127.0.0.1:8000 and watch the ticker print entries to the window. 26Then, open a browser at http://127.0.0.1:8000 and watch the ticker print entries to the window.