1use arbitrary_int::{prelude::*, u11, u15, u3, u4};
2use embedded_can::Frame;
3
4use super::{
5 regs::{
6 self, BaseId, BufStatusAndControl, BufferState, ExtendedId, MmioCanMessageBuffer,
7 TwoBytesData,
8 },
9 CanFrame, CanFrameNormal, CanFrameRtr, CanId, InvalidBufferIndexError,
10};
11
12pub struct CanChannelLowLevel {
13 id: CanId,
14 idx: usize,
16 msg_buf: MmioCanMessageBuffer<'static>,
17}
18
19impl core::fmt::Debug for CanChannelLowLevel {
20 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
21 f.debug_struct("CanChannel")
22 .field("can_id", &self.id)
23 .field("idx", &self.idx)
24 .finish()
25 }
26}
27
28impl CanChannelLowLevel {
29 #[inline]
35 pub unsafe fn steal(can: CanId, idx: usize) -> Result<Self, InvalidBufferIndexError> {
36 if idx > 14 {
37 return Err(InvalidBufferIndexError(idx));
38 }
39 let msg_buf = unsafe { can.steal_regs().steal_cmbs_unchecked(idx) };
40 Ok(Self {
41 id: can,
42 idx,
43 msg_buf,
44 })
45 }
46
47 #[inline]
54 pub const unsafe fn steal_unchecked(can: CanId, idx: usize) -> Self {
55 if idx > 14 {
56 panic!("invalid buffer index for CAN low level channel");
57 }
58 let msg_buf = unsafe { can.steal_regs().steal_cmbs_unchecked(idx) };
59 Self {
60 id: can,
61 idx,
62 msg_buf,
63 }
64 }
65
66 #[inline]
71 pub const unsafe fn clone(&self) -> Self {
72 Self {
73 id: self.id,
74 idx: self.idx,
75 msg_buf: unsafe { self.msg_buf.clone() },
76 }
77 }
78
79 pub fn reset(&mut self) {
80 self.msg_buf.reset();
81 }
82
83 #[inline]
84 pub fn read_state(&self) -> Result<BufferState, u8> {
85 self.msg_buf.read_stat_ctrl().state()
86 }
87
88 #[inline]
89 pub fn write_state(&mut self, buffer_state: BufferState) {
90 self.msg_buf.modify_stat_ctrl(|mut val| {
91 val.set_state(buffer_state);
92 val
93 });
94 }
95
96 pub fn configure_for_transmission(&mut self, tx_priority: Option<u4>) {
97 self.msg_buf.modify_stat_ctrl(|mut val| {
98 val.set_dlc(u4::new(0));
99 if let Some(tx_priority) = tx_priority {
100 val.set_priority(tx_priority);
101 }
102 val.set_state(BufferState::TxNotActive);
103 val
104 });
105 }
106
107 pub fn set_standard_id(&mut self, standard_id: embedded_can::StandardId, set_rtr: bool) {
108 let mut id1_reg = standard_id.as_raw() << 5;
109 if set_rtr {
110 id1_reg |= 1 << 4;
111 }
112 self.msg_buf
113 .write_id1(BaseId::new_with_raw_value(id1_reg as u32));
114 }
115
116 pub fn set_extended_id(&mut self, extended_id: embedded_can::ExtendedId, set_rtr: bool) {
117 let id_raw = extended_id.as_raw();
118 let id1_reg = (((id_raw >> 18) & 0x7FF) << 4) as u16 | ((id_raw >> 15) & 0b111) as u16;
119 self.msg_buf
120 .write_id1(BaseId::new_with_raw_value(id1_reg as u32));
121 let id0_reg = ((id_raw & 0x7FFF) << 1) as u16 | set_rtr as u16;
122 self.msg_buf
123 .write_id0(ExtendedId::new_with_raw_value(id0_reg as u32));
124 }
125
126 pub fn configure_for_reception(&mut self) {
127 self.msg_buf.write_stat_ctrl(
128 BufStatusAndControl::builder()
129 .with_dlc(u4::new(0))
130 .with_priority(u4::new(0))
131 .with_state(BufferState::RxReady)
132 .build(),
133 );
134 }
135
136 pub fn transmit_frame_unchecked(&mut self, frame: CanFrame) {
137 let is_remote = frame.is_remote_frame();
138 self.write_id(frame.id(), is_remote);
139 let dlc = frame.dlc();
140 self.msg_buf.modify_stat_ctrl(|mut ctrl| {
141 ctrl.set_dlc(u4::new(dlc as u8));
142 ctrl
143 });
144 if !is_remote {
145 self.msg_buf
146 .write_data0(TwoBytesData::new_with_raw_value(0));
147 self.msg_buf
148 .write_data1(TwoBytesData::new_with_raw_value(0));
149 self.msg_buf
150 .write_data2(TwoBytesData::new_with_raw_value(0));
151 self.msg_buf
152 .write_data3(TwoBytesData::new_with_raw_value(0));
153 for idx in 0..dlc {
154 match idx {
155 0 => self.msg_buf.modify_data0(|mut val| {
156 val.set_data_upper_byte(frame.data()[idx]);
157 val
158 }),
159 1 => self.msg_buf.modify_data0(|mut val| {
160 val.set_data_lower_byte(frame.data()[idx]);
161 val
162 }),
163 2 => self.msg_buf.modify_data1(|mut val| {
164 val.set_data_upper_byte(frame.data()[idx]);
165 val
166 }),
167 3 => self.msg_buf.modify_data1(|mut val| {
168 val.set_data_lower_byte(frame.data()[idx]);
169 val
170 }),
171 4 => self.msg_buf.modify_data2(|mut val| {
172 val.set_data_upper_byte(frame.data()[idx]);
173 val
174 }),
175 5 => self.msg_buf.modify_data2(|mut val| {
176 val.set_data_lower_byte(frame.data()[idx]);
177 val
178 }),
179 6 => self.msg_buf.modify_data3(|mut val| {
180 val.set_data_upper_byte(frame.data()[idx]);
181 val
182 }),
183 7 => self.msg_buf.modify_data3(|mut val| {
184 val.set_data_lower_byte(frame.data()[idx]);
185 val
186 }),
187 _ => unreachable!(),
188 }
189 }
190 }
191 self.write_state(BufferState::TxOnce);
192 }
193
194 #[inline]
195 pub fn clear_interrupt(&mut self) {
196 let mut regs = unsafe { self.id.steal_regs() };
197 let mut clear = regs::InterruptClear::new_with_raw_value(0);
198 clear.set_buffer(self.idx, true);
199 regs.write_iclr(clear);
200 }
201
202 pub fn enable_error_interrupt(&mut self, enable_translation: bool) {
203 let mut regs = unsafe { self.id.steal_regs() };
204 if enable_translation {
205 regs.modify_icen(|mut val| {
206 val.set_error(true);
207 val
208 });
209 }
210 regs.modify_ien(|mut val| {
211 val.set_error(true);
212 val
213 });
214 }
215
216 pub fn enable_interrupt(&mut self, enable_translation: bool) {
217 let mut regs = unsafe { self.id.steal_regs() };
218 if enable_translation {
219 regs.modify_icen(|mut val| {
220 val.set_buffer(self.idx, true);
221 val
222 });
223 }
224 regs.modify_ien(|mut val| {
225 val.set_buffer(self.idx, true);
226 val
227 });
228 }
229
230 fn write_id(&mut self, id: embedded_can::Id, is_remote: bool) {
231 match id {
232 embedded_can::Id::Standard(standard_id) => {
233 self.msg_buf.write_id1(
234 BaseId::builder()
235 .with_mask_28_18(u11::new(standard_id.as_raw()))
236 .with_rtr_or_srr(is_remote)
237 .with_ide(false)
238 .with_mask_17_15(u3::new(0))
239 .build(),
240 );
241 self.msg_buf.write_id0(ExtendedId::new_with_raw_value(0));
242 }
243 embedded_can::Id::Extended(extended_id) => {
244 let id_raw = extended_id.as_raw();
245 self.msg_buf.write_id1(
246 BaseId::builder()
247 .with_mask_28_18(u11::new(((id_raw >> 18) & 0x7FF) as u16))
248 .with_rtr_or_srr(true)
249 .with_ide(true)
250 .with_mask_17_15(u3::new(((id_raw >> 15) & 0b111) as u8))
251 .build(),
252 );
253 self.msg_buf.write_id0(
254 ExtendedId::builder()
255 .with_mask_14_0(u15::new((id_raw & 0x7FFF) as u16))
256 .with_xrtr(is_remote)
257 .build(),
258 );
259 }
260 }
261 }
262
263 pub fn read_frame_unchecked(&self) -> CanFrame {
268 let id0 = self.msg_buf.read_id0();
269 let id1 = self.msg_buf.read_id1();
270 let data0 = self.msg_buf.read_data0();
271 let data1 = self.msg_buf.read_data1();
272 let data2 = self.msg_buf.read_data2();
273 let data3 = self.msg_buf.read_data3();
274 let mut data: [u8; 8] = [0; 8];
275 let mut read_data = |dlc: u4| {
276 (0..dlc.as_usize()).for_each(|i| match i {
277 0 => data[i] = data0.data_upper_byte().as_u8(),
278 1 => data[i] = data0.data_lower_byte().as_u8(),
279 2 => data[i] = data1.data_upper_byte().as_u8(),
280 3 => data[i] = data1.data_lower_byte().as_u8(),
281 4 => data[i] = data2.data_upper_byte().as_u8(),
282 5 => data[i] = data2.data_lower_byte().as_u8(),
283 6 => data[i] = data3.data_upper_byte().as_u8(),
284 7 => data[i] = data3.data_lower_byte().as_u8(),
285 _ => unreachable!(),
286 });
287 };
288 let (id, rtr) = if !id1.ide() {
289 let id = embedded_can::Id::Standard(
290 embedded_can::StandardId::new(id1.mask_28_18().as_u16()).unwrap(),
291 );
292 if id1.rtr_or_srr() {
293 (id, true)
294 } else {
295 (id, false)
296 }
297 } else {
298 let id_raw = (id1.mask_28_18().as_u32() << 18)
299 | (id1.mask_17_15().as_u32() << 15)
300 | id0.mask_14_0().as_u32();
301 let id = embedded_can::Id::Extended(embedded_can::ExtendedId::new(id_raw).unwrap());
302 if id0.xrtr() {
303 (id, true)
304 } else {
305 (id, false)
306 }
307 };
308 if rtr {
309 CanFrameRtr::new(id, self.msg_buf.read_stat_ctrl().dlc().as_usize()).into()
310 } else {
311 let dlc = self.msg_buf.read_stat_ctrl().dlc();
312 read_data(dlc);
313 CanFrameNormal::new(id, &data[0..dlc.as_usize()])
314 .unwrap()
315 .into()
316 }
317 }
318}