diff options
| author | JuliDi <[email protected]> | 2023-06-24 13:10:59 +0200 |
|---|---|---|
| committer | JuliDi <[email protected]> | 2023-06-24 13:10:59 +0200 |
| commit | 388d3e273d3d003e6a058b4bad9e2517dd33d626 (patch) | |
| tree | b2b7830bc138d0a611125abe13f7afd4c8842525 | |
| parent | 915f79c974ace037e914397b42eb9d2448bd5ca3 (diff) | |
first attempt at fixing the 2nd channel problem
| -rw-r--r-- | embassy-stm32/src/dac/mod.rs | 366 |
1 files changed, 224 insertions, 142 deletions
diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs index 5b39758bf..e87292b86 100644 --- a/embassy-stm32/src/dac/mod.rs +++ b/embassy-stm32/src/dac/mod.rs | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | 2 | ||
| 3 | use core::marker::PhantomData; | ||
| 4 | |||
| 3 | use embassy_hal_common::{into_ref, PeripheralRef}; | 5 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 4 | 6 | ||
| 5 | use crate::dma::{Transfer, TransferOptions}; | 7 | use crate::dma::{Transfer, TransferOptions}; |
| @@ -108,166 +110,108 @@ pub enum ValueArray<'a> { | |||
| 108 | Bit12Right(&'a [u16]), | 110 | Bit12Right(&'a [u16]), |
| 109 | } | 111 | } |
| 110 | 112 | ||
| 111 | pub struct Dac<'d, T: Instance, Tx> { | 113 | pub trait DacChannel<T: Instance, Tx> { |
| 112 | ch1: bool, | 114 | const CHANNEL: Channel; |
| 113 | ch2: bool, | ||
| 114 | txdma: PeripheralRef<'d, Tx>, | ||
| 115 | _peri: PeripheralRef<'d, T>, | ||
| 116 | } | ||
| 117 | |||
| 118 | impl<'d, T: Instance, Tx> Dac<'d, T, Tx> { | ||
| 119 | pub fn new_ch1( | ||
| 120 | peri: impl Peripheral<P = T> + 'd, | ||
| 121 | txdma: impl Peripheral<P = Tx> + 'd, | ||
| 122 | _ch1: impl Peripheral<P = impl DacPin<T, 1>> + 'd, | ||
| 123 | ) -> Self { | ||
| 124 | into_ref!(peri); | ||
| 125 | Self::new_inner(peri, true, false, txdma) | ||
| 126 | } | ||
| 127 | |||
| 128 | pub fn new_ch2( | ||
| 129 | peri: impl Peripheral<P = T> + 'd, | ||
| 130 | txdma: impl Peripheral<P = Tx> + 'd, | ||
| 131 | _ch2: impl Peripheral<P = impl DacPin<T, 2>> + 'd, | ||
| 132 | ) -> Self { | ||
| 133 | into_ref!(peri); | ||
| 134 | Self::new_inner(peri, false, true, txdma) | ||
| 135 | } | ||
| 136 | |||
| 137 | pub fn new_ch1_and_ch2( | ||
| 138 | peri: impl Peripheral<P = T> + 'd, | ||
| 139 | txdma: impl Peripheral<P = Tx> + 'd, | ||
| 140 | _ch1: impl Peripheral<P = impl DacPin<T, 1>> + 'd, | ||
| 141 | _ch2: impl Peripheral<P = impl DacPin<T, 2>> + 'd, | ||
| 142 | ) -> Self { | ||
| 143 | into_ref!(peri); | ||
| 144 | Self::new_inner(peri, true, true, txdma) | ||
| 145 | } | ||
| 146 | |||
| 147 | /// Perform initialisation steps for the DAC | ||
| 148 | fn new_inner(peri: PeripheralRef<'d, T>, ch1: bool, ch2: bool, txdma: impl Peripheral<P = Tx> + 'd) -> Self { | ||
| 149 | into_ref!(txdma); | ||
| 150 | T::enable(); | ||
| 151 | T::reset(); | ||
| 152 | |||
| 153 | let mut dac = Self { | ||
| 154 | ch1, | ||
| 155 | ch2, | ||
| 156 | txdma, | ||
| 157 | _peri: peri, | ||
| 158 | }; | ||
| 159 | |||
| 160 | // Configure each activated channel. All results can be `unwrap`ed since they | ||
| 161 | // will only error if the channel is not configured (i.e. ch1, ch2 are false) | ||
| 162 | if ch1 { | ||
| 163 | dac.set_channel_mode(Channel::Ch1, 0).unwrap(); | ||
| 164 | dac.enable_channel(Channel::Ch1).unwrap(); | ||
| 165 | dac.set_trigger_enable(Channel::Ch1, true).unwrap(); | ||
| 166 | } | ||
| 167 | if ch2 { | ||
| 168 | dac.set_channel_mode(Channel::Ch2, 0).unwrap(); | ||
| 169 | dac.enable_channel(Channel::Ch2).unwrap(); | ||
| 170 | dac.set_trigger_enable(Channel::Ch2, true).unwrap(); | ||
| 171 | } | ||
| 172 | |||
| 173 | dac | ||
| 174 | } | ||
| 175 | |||
| 176 | /// Check the channel is configured | ||
| 177 | fn check_channel_configured(&self, ch: Channel) -> Result<(), Error> { | ||
| 178 | if (ch == Channel::Ch1 && !self.ch1) || (ch == Channel::Ch2 && !self.ch2) { | ||
| 179 | Err(Error::UnconfiguredChannel) | ||
| 180 | } else { | ||
| 181 | Ok(()) | ||
| 182 | } | ||
| 183 | } | ||
| 184 | 115 | ||
| 185 | /// Enable trigger of the given channel | 116 | /// Enable trigger of the given channel |
| 186 | fn set_trigger_enable(&mut self, ch: Channel, on: bool) -> Result<(), Error> { | 117 | fn set_trigger_enable(&mut self, on: bool) -> Result<(), Error> { |
| 187 | self.check_channel_configured(ch)?; | ||
| 188 | T::regs().cr().modify(|reg| { | 118 | T::regs().cr().modify(|reg| { |
| 189 | reg.set_ten(ch.index(), on); | 119 | reg.set_ten(Self::CHANNEL.index(), on); |
| 190 | }); | 120 | }); |
| 191 | Ok(()) | 121 | Ok(()) |
| 192 | } | 122 | } |
| 193 | 123 | ||
| 194 | /// Set mode register of the given channel | 124 | /// Set mode register of the given channel |
| 195 | fn set_channel_mode(&mut self, ch: Channel, val: u8) -> Result<(), Error> { | 125 | fn set_channel_mode(&mut self, val: u8) -> Result<(), Error> { |
| 196 | self.check_channel_configured(ch)?; | ||
| 197 | T::regs().mcr().modify(|reg| { | 126 | T::regs().mcr().modify(|reg| { |
| 198 | reg.set_mode(ch.index(), val); | 127 | reg.set_mode(Self::CHANNEL.index(), val); |
| 199 | }); | 128 | }); |
| 200 | Ok(()) | 129 | Ok(()) |
| 201 | } | 130 | } |
| 202 | 131 | ||
| 203 | /// Set enable register of the given channel | 132 | /// Set enable register of the given channel |
| 204 | fn set_channel_enable(&mut self, ch: Channel, on: bool) -> Result<(), Error> { | 133 | fn set_channel_enable(&mut self, on: bool) -> Result<(), Error> { |
| 205 | self.check_channel_configured(ch)?; | ||
| 206 | T::regs().cr().modify(|reg| { | 134 | T::regs().cr().modify(|reg| { |
| 207 | reg.set_en(ch.index(), on); | 135 | reg.set_en(Self::CHANNEL.index(), on); |
| 208 | }); | 136 | }); |
| 209 | Ok(()) | 137 | Ok(()) |
| 210 | } | 138 | } |
| 211 | 139 | ||
| 212 | /// Enable the DAC channel `ch` | 140 | /// Enable the DAC channel `ch` |
| 213 | pub fn enable_channel(&mut self, ch: Channel) -> Result<(), Error> { | 141 | fn enable_channel(&mut self) -> Result<(), Error> { |
| 214 | self.set_channel_enable(ch, true) | 142 | self.set_channel_enable(true) |
| 215 | } | 143 | } |
| 216 | 144 | ||
| 217 | /// Disable the DAC channel `ch` | 145 | /// Disable the DAC channel `ch` |
| 218 | pub fn disable_channel(&mut self, ch: Channel) -> Result<(), Error> { | 146 | fn disable_channel(&mut self) -> Result<(), Error> { |
| 219 | self.set_channel_enable(ch, false) | 147 | self.set_channel_enable(false) |
| 220 | } | ||
| 221 | |||
| 222 | /// Select a new trigger for CH1 (disables the channel) | ||
| 223 | pub fn select_trigger_ch1(&mut self, trigger: Ch1Trigger) -> Result<(), Error> { | ||
| 224 | self.check_channel_configured(Channel::Ch1)?; | ||
| 225 | unwrap!(self.disable_channel(Channel::Ch1)); | ||
| 226 | T::regs().cr().modify(|reg| { | ||
| 227 | reg.set_tsel1(trigger.tsel()); | ||
| 228 | }); | ||
| 229 | Ok(()) | ||
| 230 | } | ||
| 231 | |||
| 232 | /// Select a new trigger for CH2 (disables the channel) | ||
| 233 | pub fn select_trigger_ch2(&mut self, trigger: Ch2Trigger) -> Result<(), Error> { | ||
| 234 | self.check_channel_configured(Channel::Ch2)?; | ||
| 235 | unwrap!(self.disable_channel(Channel::Ch2)); | ||
| 236 | T::regs().cr().modify(|reg| { | ||
| 237 | reg.set_tsel2(trigger.tsel()); | ||
| 238 | }); | ||
| 239 | Ok(()) | ||
| 240 | } | 148 | } |
| 241 | 149 | ||
| 242 | /// Perform a software trigger on `ch` | 150 | /// Perform a software trigger on `ch` |
| 243 | pub fn trigger(&mut self, ch: Channel) -> Result<(), Error> { | 151 | fn trigger(&mut self) -> Result<(), Error> { |
| 244 | self.check_channel_configured(ch)?; | ||
| 245 | T::regs().swtrigr().write(|reg| { | 152 | T::regs().swtrigr().write(|reg| { |
| 246 | reg.set_swtrig(ch.index(), true); | 153 | reg.set_swtrig(Self::CHANNEL.index(), true); |
| 247 | }); | 154 | }); |
| 248 | Ok(()) | 155 | Ok(()) |
| 249 | } | 156 | } |
| 250 | 157 | ||
| 251 | /// Perform a software trigger on all channels | ||
| 252 | pub fn trigger_all(&mut self) { | ||
| 253 | T::regs().swtrigr().write(|reg| { | ||
| 254 | reg.set_swtrig(Channel::Ch1.index(), true); | ||
| 255 | reg.set_swtrig(Channel::Ch2.index(), true); | ||
| 256 | }); | ||
| 257 | } | ||
| 258 | |||
| 259 | /// Set a value to be output by the DAC on trigger. | 158 | /// Set a value to be output by the DAC on trigger. |
| 260 | /// | 159 | /// |
| 261 | /// The `value` is written to the corresponding "data holding register" | 160 | /// The `value` is written to the corresponding "data holding register" |
| 262 | pub fn set(&mut self, ch: Channel, value: Value) -> Result<(), Error> { | 161 | fn set(&mut self, value: Value) -> Result<(), Error> { |
| 263 | self.check_channel_configured(ch)?; | ||
| 264 | match value { | 162 | match value { |
| 265 | Value::Bit8(v) => T::regs().dhr8r(ch.index()).write(|reg| reg.set_dhr(v)), | 163 | Value::Bit8(v) => T::regs().dhr8r(Self::CHANNEL.index()).write(|reg| reg.set_dhr(v)), |
| 266 | Value::Bit12Left(v) => T::regs().dhr12l(ch.index()).write(|reg| reg.set_dhr(v)), | 164 | Value::Bit12Left(v) => T::regs().dhr12l(Self::CHANNEL.index()).write(|reg| reg.set_dhr(v)), |
| 267 | Value::Bit12Right(v) => T::regs().dhr12r(ch.index()).write(|reg| reg.set_dhr(v)), | 165 | Value::Bit12Right(v) => T::regs().dhr12r(Self::CHANNEL.index()).write(|reg| reg.set_dhr(v)), |
| 268 | } | 166 | } |
| 269 | Ok(()) | 167 | Ok(()) |
| 270 | } | 168 | } |
| 169 | } | ||
| 170 | |||
| 171 | pub struct Dac<'d, T: Instance, Tx> { | ||
| 172 | ch1: DacCh1<'d, T, Tx>, | ||
| 173 | ch2: DacCh2<'d, T, Tx>, | ||
| 174 | } | ||
| 175 | |||
| 176 | pub struct DacCh1<'d, T: Instance, Tx> { | ||
| 177 | _peri: PeripheralRef<'d, T>, | ||
| 178 | dma: PeripheralRef<'d, Tx>, | ||
| 179 | } | ||
| 180 | |||
| 181 | pub struct DacCh2<'d, T: Instance, Tx> { | ||
| 182 | phantom: PhantomData<&'d mut T>, | ||
| 183 | dma: PeripheralRef<'d, Tx>, | ||
| 184 | } | ||
| 185 | |||
| 186 | impl<'d, T: Instance, Tx> DacCh1<'d, T, Tx> { | ||
| 187 | /// Perform initialisation steps for the DAC | ||
| 188 | pub fn new( | ||
| 189 | peri: impl Peripheral<P = T> + 'd, | ||
| 190 | dma: impl Peripheral<P = Tx> + 'd, | ||
| 191 | _pin: impl Peripheral<P = impl DacPin<T, 1>> + 'd, | ||
| 192 | ) -> Self { | ||
| 193 | into_ref!(peri, dma); | ||
| 194 | T::enable(); | ||
| 195 | T::reset(); | ||
| 196 | |||
| 197 | let mut dac = Self { _peri: peri, dma }; | ||
| 198 | |||
| 199 | // Configure each activated channel. All results can be `unwrap`ed since they | ||
| 200 | // will only error if the channel is not configured (i.e. ch1, ch2 are false) | ||
| 201 | dac.set_channel_mode(0).unwrap(); | ||
| 202 | dac.enable_channel().unwrap(); | ||
| 203 | dac.set_trigger_enable(true).unwrap(); | ||
| 204 | |||
| 205 | dac | ||
| 206 | } | ||
| 207 | /// Select a new trigger for CH1 (disables the channel) | ||
| 208 | pub fn select_trigger(&mut self, trigger: Ch1Trigger) -> Result<(), Error> { | ||
| 209 | unwrap!(self.disable_channel()); | ||
| 210 | T::regs().cr().modify(|reg| { | ||
| 211 | reg.set_tsel1(trigger.tsel()); | ||
| 212 | }); | ||
| 213 | Ok(()) | ||
| 214 | } | ||
| 271 | 215 | ||
| 272 | /// Write `data` to the DAC CH1 via DMA. | 216 | /// Write `data` to the DAC CH1 via DMA. |
| 273 | /// | 217 | /// |
| @@ -276,36 +220,127 @@ impl<'d, T: Instance, Tx> Dac<'d, T, Tx> { | |||
| 276 | /// Note that for performance reasons in circular mode the transfer complete interrupt is disabled. | 220 | /// Note that for performance reasons in circular mode the transfer complete interrupt is disabled. |
| 277 | /// | 221 | /// |
| 278 | /// **Important:** Channel 1 has to be configured for the DAC instance! | 222 | /// **Important:** Channel 1 has to be configured for the DAC instance! |
| 279 | pub async fn write_ch1(&mut self, data: ValueArray<'_>, circular: bool) -> Result<(), Error> | 223 | async fn write(&mut self, data: ValueArray<'_>, circular: bool) -> Result<(), Error> |
| 280 | where | 224 | where |
| 281 | Tx: Dma<T>, | 225 | Tx: Dma<T>, |
| 282 | { | 226 | { |
| 283 | self.check_channel_configured(Channel::Ch1)?; | 227 | let channel = Channel::Ch1.index(); |
| 284 | self.write_inner(data, circular, Channel::Ch1).await | 228 | debug!("Writing to channel {}", channel); |
| 229 | |||
| 230 | // Enable DAC and DMA | ||
| 231 | T::regs().cr().modify(|w| { | ||
| 232 | w.set_en(channel, true); | ||
| 233 | w.set_dmaen(channel, true); | ||
| 234 | }); | ||
| 235 | |||
| 236 | let tx_request = self.dma.request(); | ||
| 237 | let dma_channel = &self.dma; | ||
| 238 | |||
| 239 | // Initiate the correct type of DMA transfer depending on what data is passed | ||
| 240 | let tx_f = match data { | ||
| 241 | ValueArray::Bit8(buf) => unsafe { | ||
| 242 | Transfer::new_write( | ||
| 243 | dma_channel, | ||
| 244 | tx_request, | ||
| 245 | buf, | ||
| 246 | T::regs().dhr8r(channel).as_ptr() as *mut u8, | ||
| 247 | TransferOptions { | ||
| 248 | circular, | ||
| 249 | half_transfer_ir: false, | ||
| 250 | complete_transfer_ir: !circular, | ||
| 251 | }, | ||
| 252 | ) | ||
| 253 | }, | ||
| 254 | ValueArray::Bit12Left(buf) => unsafe { | ||
| 255 | Transfer::new_write( | ||
| 256 | dma_channel, | ||
| 257 | tx_request, | ||
| 258 | buf, | ||
| 259 | T::regs().dhr12l(channel).as_ptr() as *mut u16, | ||
| 260 | TransferOptions { | ||
| 261 | circular, | ||
| 262 | half_transfer_ir: false, | ||
| 263 | complete_transfer_ir: !circular, | ||
| 264 | }, | ||
| 265 | ) | ||
| 266 | }, | ||
| 267 | ValueArray::Bit12Right(buf) => unsafe { | ||
| 268 | Transfer::new_write( | ||
| 269 | dma_channel, | ||
| 270 | tx_request, | ||
| 271 | buf, | ||
| 272 | T::regs().dhr12r(channel).as_ptr() as *mut u16, | ||
| 273 | TransferOptions { | ||
| 274 | circular, | ||
| 275 | half_transfer_ir: false, | ||
| 276 | complete_transfer_ir: !circular, | ||
| 277 | }, | ||
| 278 | ) | ||
| 279 | }, | ||
| 280 | }; | ||
| 281 | |||
| 282 | tx_f.await; | ||
| 283 | |||
| 284 | // finish dma | ||
| 285 | // TODO: Do we need to check any status registers here? | ||
| 286 | T::regs().cr().modify(|w| { | ||
| 287 | // Disable the DAC peripheral | ||
| 288 | w.set_en(channel, false); | ||
| 289 | // Disable the DMA. TODO: Is this necessary? | ||
| 290 | w.set_dmaen(channel, false); | ||
| 291 | }); | ||
| 292 | |||
| 293 | Ok(()) | ||
| 285 | } | 294 | } |
| 295 | } | ||
| 286 | 296 | ||
| 287 | /// Write `data` to the DAC CH2 via DMA. | 297 | impl<'d, T: Instance, Tx> DacCh2<'d, T, Tx> { |
| 298 | /// Perform initialisation steps for the DAC | ||
| 299 | pub fn new_ch2( | ||
| 300 | peri: impl Peripheral<P = T> + 'd, | ||
| 301 | dma: impl Peripheral<P = Tx> + 'd, | ||
| 302 | _pin: impl Peripheral<P = impl DacPin<T, 2>> + 'd, | ||
| 303 | ) -> Self { | ||
| 304 | into_ref!(peri, dma); | ||
| 305 | T::enable(); | ||
| 306 | T::reset(); | ||
| 307 | |||
| 308 | let mut dac = Self { | ||
| 309 | phantom: PhantomData, | ||
| 310 | dma, | ||
| 311 | }; | ||
| 312 | |||
| 313 | // Configure each activated channel. All results can be `unwrap`ed since they | ||
| 314 | // will only error if the channel is not configured (i.e. ch1, ch2 are false) | ||
| 315 | dac.set_channel_mode(0).unwrap(); | ||
| 316 | dac.enable_channel().unwrap(); | ||
| 317 | dac.set_trigger_enable(true).unwrap(); | ||
| 318 | |||
| 319 | dac | ||
| 320 | } | ||
| 321 | |||
| 322 | /// Select a new trigger for CH1 (disables the channel) | ||
| 323 | pub fn select_trigger(&mut self, trigger: Ch2Trigger) -> Result<(), Error> { | ||
| 324 | unwrap!(self.disable_channel()); | ||
| 325 | T::regs().cr().modify(|reg| { | ||
| 326 | reg.set_tsel2(trigger.tsel()); | ||
| 327 | }); | ||
| 328 | Ok(()) | ||
| 329 | } | ||
| 330 | |||
| 331 | /// Write `data` to the DAC CH1 via DMA. | ||
| 288 | /// | 332 | /// |
| 289 | /// To prevent delays/glitches when outputting a periodic waveform, the `circular` flag can be set. | 333 | /// To prevent delays/glitches when outputting a periodic waveform, the `circular` flag can be set. |
| 290 | /// This will configure a circular DMA transfer that periodically outputs the `data`. | 334 | /// This will configure a circular DMA transfer that periodically outputs the `data`. |
| 291 | /// Note that for performance reasons in circular mode the transfer complete interrupt is disabled. | 335 | /// Note that for performance reasons in circular mode the transfer complete interrupt is disabled. |
| 292 | /// | 336 | /// |
| 293 | /// **Important:** Channel 2 has to be configured for the DAC instance! | 337 | /// **Important:** Channel 1 has to be configured for the DAC instance! |
| 294 | pub async fn write_ch2(&mut self, data: ValueArray<'_>, circular: bool) -> Result<(), Error> | 338 | async fn write(&mut self, data: ValueArray<'_>, circular: bool) -> Result<(), Error> |
| 295 | where | ||
| 296 | Tx: Dma<T>, | ||
| 297 | { | ||
| 298 | self.check_channel_configured(Channel::Ch2)?; | ||
| 299 | self.write_inner(data, circular, Channel::Ch2).await | ||
| 300 | } | ||
| 301 | |||
| 302 | /// Performs the dma write for the given channel. | ||
| 303 | /// TODO: Should self be &mut? | ||
| 304 | async fn write_inner(&self, data_ch1: ValueArray<'_>, circular: bool, channel: Channel) -> Result<(), Error> | ||
| 305 | where | 339 | where |
| 306 | Tx: Dma<T>, | 340 | Tx: Dma<T>, |
| 307 | { | 341 | { |
| 308 | let channel = channel.index(); | 342 | let channel = Channel::Ch2.index(); |
| 343 | debug!("Writing to channel {}", channel); | ||
| 309 | 344 | ||
| 310 | // Enable DAC and DMA | 345 | // Enable DAC and DMA |
| 311 | T::regs().cr().modify(|w| { | 346 | T::regs().cr().modify(|w| { |
| @@ -313,11 +348,11 @@ impl<'d, T: Instance, Tx> Dac<'d, T, Tx> { | |||
| 313 | w.set_dmaen(channel, true); | 348 | w.set_dmaen(channel, true); |
| 314 | }); | 349 | }); |
| 315 | 350 | ||
| 316 | let tx_request = self.txdma.request(); | 351 | let tx_request = self.dma.request(); |
| 317 | let dma_channel = &self.txdma; | 352 | let dma_channel = &self.dma; |
| 318 | 353 | ||
| 319 | // Initiate the correct type of DMA transfer depending on what data is passed | 354 | // Initiate the correct type of DMA transfer depending on what data is passed |
| 320 | let tx_f = match data_ch1 { | 355 | let tx_f = match data { |
| 321 | ValueArray::Bit8(buf) => unsafe { | 356 | ValueArray::Bit8(buf) => unsafe { |
| 322 | Transfer::new_write( | 357 | Transfer::new_write( |
| 323 | dma_channel, | 358 | dma_channel, |
| @@ -374,6 +409,53 @@ impl<'d, T: Instance, Tx> Dac<'d, T, Tx> { | |||
| 374 | } | 409 | } |
| 375 | } | 410 | } |
| 376 | 411 | ||
| 412 | impl<'d, T: Instance, Tx> Dac<'d, T, Tx> { | ||
| 413 | pub fn new( | ||
| 414 | peri: impl Peripheral<P = T> + 'd, | ||
| 415 | dma_ch1: impl Peripheral<P = Tx> + 'd, | ||
| 416 | dma_ch2: impl Peripheral<P = Tx> + 'd, | ||
| 417 | _pin_ch1: impl Peripheral<P = impl DacPin<T, 1>> + 'd, | ||
| 418 | _pin_ch2: impl Peripheral<P = impl DacPin<T, 2>> + 'd, | ||
| 419 | ) -> Self { | ||
| 420 | into_ref!(peri, dma_ch1, dma_ch2); | ||
| 421 | T::enable(); | ||
| 422 | T::reset(); | ||
| 423 | |||
| 424 | let mut dac_ch1 = DacCh1 { | ||
| 425 | _peri: peri, | ||
| 426 | dma: dma_ch1, | ||
| 427 | }; | ||
| 428 | |||
| 429 | let mut dac_ch2 = DacCh2 { | ||
| 430 | phantom: PhantomData, | ||
| 431 | dma: dma_ch2, | ||
| 432 | }; | ||
| 433 | |||
| 434 | // Configure each activated channel. All results can be `unwrap`ed since they | ||
| 435 | // will only error if the channel is not configured (i.e. ch1, ch2 are false) | ||
| 436 | dac_ch1.set_channel_mode(0).unwrap(); | ||
| 437 | dac_ch1.enable_channel().unwrap(); | ||
| 438 | dac_ch1.set_trigger_enable(true).unwrap(); | ||
| 439 | |||
| 440 | dac_ch1.set_channel_mode(0).unwrap(); | ||
| 441 | dac_ch1.enable_channel().unwrap(); | ||
| 442 | dac_ch1.set_trigger_enable(true).unwrap(); | ||
| 443 | |||
| 444 | Self { | ||
| 445 | ch1: dac_ch1, | ||
| 446 | ch2: dac_ch2, | ||
| 447 | } | ||
| 448 | } | ||
| 449 | } | ||
| 450 | |||
| 451 | impl<'d, T: Instance, Tx> DacChannel<T, Tx> for DacCh1<'d, T, Tx> { | ||
| 452 | const CHANNEL: Channel = Channel::Ch1; | ||
| 453 | } | ||
| 454 | |||
| 455 | impl<'d, T: Instance, Tx> DacChannel<T, Tx> for DacCh2<'d, T, Tx> { | ||
| 456 | const CHANNEL: Channel = Channel::Ch2; | ||
| 457 | } | ||
| 458 | |||
| 377 | pub(crate) mod sealed { | 459 | pub(crate) mod sealed { |
| 378 | pub trait Instance { | 460 | pub trait Instance { |
| 379 | fn regs() -> &'static crate::pac::dac::Dac; | 461 | fn regs() -> &'static crate::pac::dac::Dac; |
