esp_hal/pcnt/channel.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
//! # PCNT - Channel Configuration
//!
//! ## Overview
//! The `channel` module allows users to configure and manage individual
//! channels of the `PCNT` peripheral. It provides methods to set various
//! parameters for each channel, such as control modes for signal edges, action
//! on control level, and configurations for positive and negative edge count
//! modes.
use core::marker::PhantomData;
pub use crate::pac::pcnt::unit::conf0::{CTRL_MODE as CtrlMode, EDGE_MODE as EdgeMode};
use crate::{
gpio::{interconnect::PeripheralInput, InputSignal},
peripheral::Peripheral,
peripherals::PCNT,
system::GenericPeripheralGuard,
};
/// Represents a channel within a pulse counter unit.
pub struct Channel<'d, const UNIT: usize, const NUM: usize> {
_phantom: PhantomData<&'d ()>,
// Individual channels are not Send, since they share registers.
_not_send: PhantomData<*const ()>,
_guard: GenericPeripheralGuard<{ crate::system::Peripheral::Pcnt as u8 }>,
}
impl<const UNIT: usize, const NUM: usize> Channel<'_, UNIT, NUM> {
/// return a new Channel
pub(super) fn new() -> Self {
let guard = GenericPeripheralGuard::new();
Self {
_phantom: PhantomData,
_not_send: PhantomData,
_guard: guard,
}
}
/// Configures how the channel behaves based on the level of the control
/// signal.
///
/// * `low` - The behaviour of the channel when the control signal is low.
/// * `high` - The behaviour of the channel when the control signal is high.
pub fn set_ctrl_mode(&self, low: CtrlMode, high: CtrlMode) {
let pcnt = PCNT::regs();
let conf0 = pcnt.unit(UNIT).conf0();
conf0.modify(|_, w| {
w.ch_hctrl_mode(NUM as u8)
.variant(high)
.ch_lctrl_mode(NUM as u8)
.variant(low)
});
}
/// Configures how the channel affects the counter based on the transition
/// made by the input signal.
///
/// * `neg_edge` - The effect on the counter when the input signal goes 1 ->
/// 0.
/// * `pos_edge` - The effect on the counter when the input signal goes 0 ->
/// 1.
pub fn set_input_mode(&self, neg_edge: EdgeMode, pos_edge: EdgeMode) {
let pcnt = PCNT::regs();
let conf0 = pcnt.unit(UNIT).conf0();
conf0.modify(|_, w| {
w.ch_neg_mode(NUM as u8).variant(neg_edge);
w.ch_pos_mode(NUM as u8).variant(pos_edge)
});
}
/// Set the control signal (pin/high/low) for this channel
pub fn set_ctrl_signal<P: PeripheralInput>(&self, source: impl Peripheral<P = P>) -> &Self {
let signal = match UNIT {
0 => match NUM {
0 => InputSignal::PCNT0_CTRL_CH0,
1 => InputSignal::PCNT0_CTRL_CH1,
_ => unreachable!(),
},
1 => match NUM {
0 => InputSignal::PCNT1_CTRL_CH0,
1 => InputSignal::PCNT1_CTRL_CH1,
_ => unreachable!(),
},
2 => match NUM {
0 => InputSignal::PCNT2_CTRL_CH0,
1 => InputSignal::PCNT2_CTRL_CH1,
_ => unreachable!(),
},
3 => match NUM {
0 => InputSignal::PCNT3_CTRL_CH0,
1 => InputSignal::PCNT3_CTRL_CH1,
_ => unreachable!(),
},
#[cfg(esp32)]
4 => match NUM {
0 => InputSignal::PCNT4_CTRL_CH0,
1 => InputSignal::PCNT4_CTRL_CH1,
_ => unreachable!(),
},
#[cfg(esp32)]
5 => match NUM {
0 => InputSignal::PCNT5_CTRL_CH0,
1 => InputSignal::PCNT5_CTRL_CH1,
_ => unreachable!(),
},
#[cfg(esp32)]
6 => match NUM {
0 => InputSignal::PCNT6_CTRL_CH0,
1 => InputSignal::PCNT6_CTRL_CH1,
_ => unreachable!(),
},
#[cfg(esp32)]
7 => match NUM {
0 => InputSignal::PCNT7_CTRL_CH0,
1 => InputSignal::PCNT7_CTRL_CH1,
_ => unreachable!(),
},
_ => unreachable!(),
};
if (signal as usize) <= crate::gpio::INPUT_SIGNAL_MAX as usize {
crate::into_mapped_ref!(source);
source.enable_input(true);
signal.connect_to(source);
}
self
}
/// Set the edge signal (pin/high/low) for this channel
pub fn set_edge_signal<P: PeripheralInput>(&self, source: impl Peripheral<P = P>) -> &Self {
let signal = match UNIT {
0 => match NUM {
0 => InputSignal::PCNT0_SIG_CH0,
1 => InputSignal::PCNT0_SIG_CH1,
_ => unreachable!(),
},
1 => match NUM {
0 => InputSignal::PCNT1_SIG_CH0,
1 => InputSignal::PCNT1_SIG_CH1,
_ => unreachable!(),
},
2 => match NUM {
0 => InputSignal::PCNT2_SIG_CH0,
1 => InputSignal::PCNT2_SIG_CH1,
_ => unreachable!(),
},
3 => match NUM {
0 => InputSignal::PCNT3_SIG_CH0,
1 => InputSignal::PCNT3_SIG_CH1,
_ => unreachable!(),
},
#[cfg(esp32)]
4 => match NUM {
0 => InputSignal::PCNT4_SIG_CH0,
1 => InputSignal::PCNT4_SIG_CH1,
_ => unreachable!(),
},
#[cfg(esp32)]
5 => match NUM {
0 => InputSignal::PCNT5_SIG_CH0,
1 => InputSignal::PCNT5_SIG_CH1,
_ => unreachable!(),
},
#[cfg(esp32)]
6 => match NUM {
0 => InputSignal::PCNT6_SIG_CH0,
1 => InputSignal::PCNT6_SIG_CH1,
_ => unreachable!(),
},
#[cfg(esp32)]
7 => match NUM {
0 => InputSignal::PCNT7_SIG_CH0,
1 => InputSignal::PCNT7_SIG_CH1,
_ => unreachable!(),
},
_ => unreachable!(),
};
if (signal as usize) <= crate::gpio::INPUT_SIGNAL_MAX as usize {
crate::into_mapped_ref!(source);
source.enable_input(true);
signal.connect_to(source);
}
self
}
}