1use core::borrow::BorrowMut;
36use core::ffi::CStr;
37use core::marker::PhantomData;
38use core::num::NonZeroU32;
39
40use enumset::{EnumSet, EnumSetType};
41
42use esp_idf_sys::*;
43
44use crate::cpu::Core;
45use crate::delay::{self, BLOCK, NON_BLOCK};
46use crate::interrupt::InterruptType;
47use crate::task::asynch::Notification;
48use crate::{gpio::*, task};
49
50crate::embedded_hal_error!(CanError, embedded_can::Error, embedded_can::ErrorKind);
51
52crate::embedded_hal_error!(
53 Can02Error,
54 embedded_hal_0_2::can::Error,
55 embedded_hal_0_2::can::ErrorKind
56);
57
58pub type CanConfig = config::Config;
59
60pub mod config {
61 use enumset::EnumSet;
62 use esp_idf_sys::*;
63
64 use crate::interrupt::InterruptType;
65
66 use super::Alert;
67
68 #[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Hash)]
70 pub enum Timing {
71 B25K,
72 B50K,
73 B100K,
74 B125K,
75 B250K,
76 #[default]
77 B500K,
78 B800K,
79 B1M,
80 Custom {
81 baudrate_prescaler: u32,
82 timing_segment_1: u8,
83 timing_segment_2: u8,
84 synchronization_jump_width: u8,
85 triple_sampling: bool,
86 },
87 }
88
89 impl From<Timing> for twai_timing_config_t {
90 #[allow(clippy::needless_update)]
91 fn from(resolution: Timing) -> Self {
92 match resolution {
93 Timing::B25K => twai_timing_config_t {
94 brp: 128,
95 tseg_1: 16,
96 tseg_2: 8,
97 sjw: 3,
98 ..Default::default()
99 },
100 Timing::B50K => twai_timing_config_t {
101 brp: 80,
102 tseg_1: 15,
103 tseg_2: 4,
104 sjw: 3,
105 ..Default::default()
106 },
107 Timing::B100K => twai_timing_config_t {
108 brp: 40,
109 tseg_1: 15,
110 tseg_2: 4,
111 sjw: 3,
112 ..Default::default()
113 },
114 Timing::B125K => twai_timing_config_t {
115 brp: 32,
116 tseg_1: 15,
117 tseg_2: 4,
118 sjw: 3,
119 ..Default::default()
120 },
121 Timing::B250K => twai_timing_config_t {
122 brp: 16,
123 tseg_1: 15,
124 tseg_2: 4,
125 sjw: 3,
126 ..Default::default()
127 },
128 Timing::B500K => twai_timing_config_t {
129 brp: 8,
130 tseg_1: 15,
131 tseg_2: 4,
132 sjw: 3,
133 ..Default::default()
134 },
135 Timing::B800K => twai_timing_config_t {
136 brp: 4,
137 tseg_1: 16,
138 tseg_2: 8,
139 sjw: 3,
140 ..Default::default()
141 },
142 Timing::B1M => twai_timing_config_t {
143 brp: 4,
144 tseg_1: 15,
145 tseg_2: 4,
146 sjw: 3,
147 ..Default::default()
148 },
149 Timing::Custom {
150 baudrate_prescaler,
151 timing_segment_1,
152 timing_segment_2,
153 synchronization_jump_width,
154 triple_sampling,
155 } => twai_timing_config_t {
156 brp: baudrate_prescaler,
157 tseg_1: timing_segment_1,
158 tseg_2: timing_segment_2,
159 sjw: synchronization_jump_width,
160 triple_sampling,
161 ..Default::default()
162 },
163 }
164 }
165 }
166
167 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
214 pub enum Filter {
215 Standard { filter: u16, mask: u16 },
217 Dual {
219 filter1: u16,
220 mask1: u16,
221 filter2: u16,
222 mask2: u16,
223 },
224 Extended { filter: u32, mask: u32 },
226 }
227
228 impl Filter {
229 pub const fn standard_allow_all() -> Self {
231 Self::Standard { filter: 0, mask: 0 }
232 }
233
234 pub const fn extended_allow_all() -> Self {
236 Self::Extended { filter: 0, mask: 0 }
237 }
238 }
239
240 impl Default for Filter {
241 fn default() -> Self {
242 Filter::standard_allow_all()
243 }
244 }
245
246 #[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash)]
247 pub enum Mode {
248 #[default]
249 Normal,
250 NoAck,
251 ListenOnly,
252 }
253
254 impl From<Mode> for twai_mode_t {
255 fn from(val: Mode) -> Self {
256 match val {
257 Mode::Normal => twai_mode_t_TWAI_MODE_NORMAL,
258 Mode::NoAck => twai_mode_t_TWAI_MODE_NO_ACK,
259 Mode::ListenOnly => twai_mode_t_TWAI_MODE_LISTEN_ONLY,
260 }
261 }
262 }
263
264 #[derive(Debug, Clone)]
265 pub struct Config {
266 pub timing: Timing,
267 pub filter: Filter,
268 pub tx_queue_len: u32,
269 pub rx_queue_len: u32,
270 pub mode: Mode,
271 pub alerts: EnumSet<Alert>,
272 pub intr_flags: EnumSet<InterruptType>,
273 }
274
275 impl Config {
276 pub fn new() -> Self {
277 Self {
278 timing: Default::default(),
279 filter: Default::default(),
280 tx_queue_len: 5,
281 rx_queue_len: 5,
282 mode: Default::default(),
283 alerts: Default::default(),
284 intr_flags: EnumSet::<InterruptType>::empty(),
285 }
286 }
287
288 #[must_use]
289 pub fn timing(mut self, timing: Timing) -> Self {
290 self.timing = timing;
291 self
292 }
293
294 #[must_use]
295 pub fn filter(mut self, filter: Filter) -> Self {
296 self.filter = filter;
297 self
298 }
299
300 #[must_use]
301 pub fn tx_queue_len(mut self, tx_queue_len: u32) -> Self {
302 self.tx_queue_len = tx_queue_len;
303 self
304 }
305
306 #[must_use]
307 pub fn rx_queue_len(mut self, rx_queue_len: u32) -> Self {
308 self.rx_queue_len = rx_queue_len;
309 self
310 }
311
312 #[must_use]
313 pub fn mode(mut self, mode: Mode) -> Self {
314 self.mode = mode;
315 self
316 }
317
318 #[must_use]
319 pub fn alerts(mut self, alerts: EnumSet<Alert>) -> Self {
320 self.alerts = alerts;
321 self
322 }
323
324 #[must_use]
325 pub fn intr_flags(mut self, flags: EnumSet<InterruptType>) -> Self {
326 self.intr_flags = flags;
327 self
328 }
329 }
330
331 impl Default for Config {
332 fn default() -> Self {
333 Self::new()
334 }
335 }
336}
337
338#[derive(Debug, EnumSetType)]
339#[enumset(repr = "u32")]
340#[repr(u32)]
341pub enum Alert {
342 TransmitIdle = 0,
344 Success = 1,
346 Received = 2,
348 BelowErrorWarning = 3,
350 ActiveError = 4,
352 RecoveryInProgress = 5,
354 BusRecovered = 6,
356 ArbLost = 7,
358 AboveErrorWarning = 8,
360 BusError = 9,
362 TransmitFailed = 10,
364 ReceiveQueueFull = 11,
366 ErrorPass = 12,
368 BusOffline = 13,
370 ReceiveFifoOverflow = 14,
372 TransmitRetried = 15,
374 PeripheralReset = 16,
376 AlertAndLog = 17,
378}
379
380pub struct CanDriver<'d>(PhantomData<&'d mut ()>, EnumSet<Alert>, bool);
382
383impl<'d> CanDriver<'d> {
384 pub fn new(
385 _can: CAN<'d>,
386 tx: impl OutputPin + 'd,
387 rx: impl InputPin + 'd,
388 config: &config::Config,
389 ) -> Result<Self, EspError> {
390 #[allow(clippy::needless_update)]
391 let general_config = twai_general_config_t {
392 mode: config.mode.into(),
393 tx_io: tx.pin() as _,
394 rx_io: rx.pin() as _,
395 clkout_io: -1,
396 bus_off_io: -1,
397 tx_queue_len: config.tx_queue_len,
398 rx_queue_len: config.rx_queue_len,
399 alerts_enabled: config.alerts.as_repr(),
400 clkout_divider: 0,
401 intr_flags: InterruptType::to_native(config.intr_flags) as _,
402 ..Default::default()
403 };
404
405 let timing_config = config.timing.into();
406
407 let (filter, mask, single_filter) = match config.filter {
409 config::Filter::Standard { filter, mask } => {
410 ((filter as u32) << 21, !((mask as u32) << 21), true)
411 }
412 config::Filter::Extended { filter, mask } => (filter << 3, !(mask << 3), true),
413 config::Filter::Dual {
414 filter1,
415 mask1,
416 filter2,
417 mask2,
418 } => (
419 ((filter1 as u32) << 21) | ((filter2 as u32) << 5),
420 !(((mask1 as u32) << 21) | ((mask2 as u32) << 5)),
421 false,
422 ),
423 };
424
425 let filter_config = twai_filter_config_t {
426 acceptance_code: filter,
427 acceptance_mask: mask,
428 single_filter,
429 };
430
431 esp!(unsafe { twai_driver_install(&general_config, &timing_config, &filter_config) })?;
432
433 Ok(Self(PhantomData, config.alerts, config.tx_queue_len > 0))
434 }
435
436 pub fn start(&mut self) -> Result<(), EspError> {
437 esp!(unsafe { twai_start() })
438 }
439
440 pub fn stop(&mut self) -> Result<(), EspError> {
441 esp!(unsafe { twai_stop() })
442 }
443
444 pub fn transmit(&self, frame: &Frame, timeout: TickType_t) -> Result<(), EspError> {
445 esp!(unsafe { twai_transmit(&frame.0, timeout) })
446 }
447
448 pub fn receive(&self, timeout: TickType_t) -> Result<Frame, EspError> {
449 let mut rx_msg = Default::default();
450
451 match esp_result!(unsafe { twai_receive(&mut rx_msg, timeout) }, ()) {
452 Ok(_) => Ok(Frame(rx_msg)),
453 Err(err) => Err(err),
454 }
455 }
456
457 pub fn read_alerts(&self, timeout: TickType_t) -> Result<EnumSet<Alert>, EspError> {
458 let mut alerts = 0;
459
460 esp!(unsafe { twai_read_alerts(&mut alerts, timeout) })?;
461
462 Ok(EnumSet::from_repr_truncated(alerts))
463 }
464}
465
466impl Drop for CanDriver<'_> {
467 fn drop(&mut self) {
468 let _ = self.stop();
469 esp!(unsafe { twai_driver_uninstall() }).unwrap();
470 }
471}
472
473unsafe impl Send for CanDriver<'_> {}
474
475impl embedded_hal_0_2::blocking::can::Can for CanDriver<'_> {
476 type Frame = Frame;
477 type Error = Can02Error;
478
479 fn transmit(&mut self, frame: &Self::Frame) -> Result<(), Self::Error> {
480 CanDriver::transmit(self, frame, BLOCK).map_err(Can02Error::other)
481 }
482
483 fn receive(&mut self) -> Result<Self::Frame, Self::Error> {
484 CanDriver::receive(self, BLOCK).map_err(Can02Error::other)
485 }
486}
487
488impl embedded_can::blocking::Can for CanDriver<'_> {
489 type Frame = Frame;
490 type Error = CanError;
491
492 fn transmit(&mut self, frame: &Self::Frame) -> Result<(), Self::Error> {
493 CanDriver::transmit(self, frame, BLOCK).map_err(CanError::other)
494 }
495
496 fn receive(&mut self) -> Result<Self::Frame, Self::Error> {
497 CanDriver::receive(self, BLOCK).map_err(CanError::other)
498 }
499}
500
501impl embedded_hal_0_2::can::nb::Can for CanDriver<'_> {
502 type Frame = Frame;
503 type Error = Can02Error;
504
505 fn transmit(&mut self, frame: &Self::Frame) -> nb::Result<Option<Self::Frame>, Self::Error> {
506 match CanDriver::transmit(self, frame, NON_BLOCK) {
507 Ok(_) => Ok(None),
508 Err(e) if e.code() == ESP_FAIL => Err(nb::Error::WouldBlock),
509 Err(e) if e.code() == ESP_ERR_TIMEOUT => Err(nb::Error::WouldBlock),
510 Err(e) => Err(nb::Error::Other(Can02Error::other(e))),
511 }
512 }
513
514 fn receive(&mut self) -> nb::Result<Self::Frame, Self::Error> {
515 match CanDriver::receive(self, NON_BLOCK) {
516 Ok(frame) => Ok(frame),
517 Err(e) if e.code() == ESP_ERR_TIMEOUT => Err(nb::Error::WouldBlock),
518 Err(e) => Err(nb::Error::Other(Can02Error::other(e))),
519 }
520 }
521}
522
523impl embedded_can::nb::Can for CanDriver<'_> {
524 type Frame = Frame;
525 type Error = CanError;
526
527 fn transmit(&mut self, frame: &Self::Frame) -> nb::Result<Option<Self::Frame>, Self::Error> {
528 match CanDriver::transmit(self, frame, NON_BLOCK) {
529 Ok(_) => Ok(None),
530 Err(e) if e.code() == ESP_FAIL => Err(nb::Error::WouldBlock),
531 Err(e) if e.code() == ESP_ERR_TIMEOUT => Err(nb::Error::WouldBlock),
532 Err(e) => Err(nb::Error::Other(CanError::other(e))),
533 }
534 }
535
536 fn receive(&mut self) -> nb::Result<Self::Frame, Self::Error> {
537 match CanDriver::receive(self, NON_BLOCK) {
538 Ok(frame) => Ok(frame),
539 Err(e) if e.code() == ESP_ERR_TIMEOUT => Err(nb::Error::WouldBlock),
540 Err(e) => Err(nb::Error::Other(CanError::other(e))),
541 }
542 }
543}
544
545fn read_alerts() -> EnumSet<Alert> {
546 Alert::Success | Alert::Received | Alert::ReceiveQueueFull
547}
548
549fn write_alerts() -> EnumSet<Alert> {
550 Alert::Success | Alert::TransmitIdle | Alert::TransmitFailed | Alert::TransmitRetried
551}
552
553pub type OwnedAsyncCanDriver<'d> = AsyncCanDriver<'d, CanDriver<'d>>;
554
555pub struct AsyncCanDriver<'d, T>
556where
557 T: BorrowMut<CanDriver<'d>>,
558{
559 driver: T,
560 task: TaskHandle_t,
561 _data: PhantomData<&'d ()>,
562}
563
564impl<'d> AsyncCanDriver<'d, CanDriver<'d>> {
565 pub fn new(
566 can: CAN<'d>,
567 tx: impl OutputPin + 'd,
568 rx: impl InputPin + 'd,
569 config: &config::Config,
570 ) -> Result<Self, EspError> {
571 Self::wrap(CanDriver::new(can, tx, rx, config)?)
572 }
573}
574
575impl<'d, T> AsyncCanDriver<'d, T>
576where
577 T: BorrowMut<CanDriver<'d>>,
578{
579 pub fn wrap(driver: T) -> Result<Self, EspError> {
580 Self::wrap_custom(driver, None, None)
581 }
582
583 pub fn wrap_custom(
584 mut driver: T,
585 priority: Option<u8>,
586 pin_to_core: Option<Core>,
587 ) -> Result<Self, EspError> {
588 let _ = driver.borrow_mut().stop();
589
590 let mut alerts = 0;
591 esp!(unsafe {
592 twai_reconfigure_alerts(
593 driver
594 .borrow()
595 .1
596 .union(read_alerts())
597 .union(write_alerts())
598 .as_repr(),
599 &mut alerts,
600 )
601 })?;
602
603 let task = unsafe {
604 task::create(
605 Self::process_alerts,
606 CStr::from_bytes_until_nul(b"CAN - Alerts task\0").unwrap(),
607 2048,
608 core::ptr::null_mut(),
609 priority.unwrap_or(6),
610 pin_to_core,
611 )?
612 };
613
614 Ok(Self {
615 driver,
616 task,
617 _data: PhantomData,
618 })
619 }
620
621 pub fn driver(&self) -> &CanDriver<'d> {
622 self.driver.borrow()
623 }
624
625 pub fn driver_mut(&mut self) -> &mut CanDriver<'d> {
626 self.driver.borrow_mut()
627 }
628
629 pub fn start(&mut self) -> Result<(), EspError> {
630 self.driver.borrow_mut().start()
631 }
632
633 pub fn stop(&mut self) -> Result<(), EspError> {
634 self.driver.borrow_mut().stop()
635 }
636
637 pub async fn transmit(&self, frame: &Frame) -> Result<(), EspError> {
638 loop {
639 let res = self.driver.borrow().transmit(frame, delay::NON_BLOCK);
640
641 match res {
642 Ok(()) => return Ok(()),
643 Err(e)
644 if e.code() != ESP_ERR_TIMEOUT
645 && (e.code() != ESP_FAIL || self.driver.borrow().2) =>
646 {
647 return Err(e)
648 }
649 _ => (),
650 }
651
652 WRITE_NOTIFICATION.wait().await;
653 }
654 }
655
656 pub async fn receive(&self) -> Result<Frame, EspError> {
657 loop {
658 let res = self.driver.borrow().receive(delay::NON_BLOCK);
659
660 match res {
661 Ok(frame) => return Ok(frame),
662 Err(e) if e.code() != ESP_ERR_TIMEOUT => return Err(e),
663 _ => (),
664 }
665
666 READ_NOTIFICATION.wait().await;
667 }
668 }
669
670 pub async fn read_alerts(&self) -> Result<EnumSet<Alert>, EspError> {
671 let alerts = loop {
672 let alerts = EnumSet::from_repr(ALERT_NOTIFICATION.wait().await.into())
673 .intersection(self.driver.borrow().1);
674
675 if !alerts.is_empty() {
676 break alerts;
677 }
678 };
679
680 Ok(alerts)
681 }
682
683 extern "C" fn process_alerts(_arg: *mut core::ffi::c_void) {
684 let mut alerts = 0;
685
686 loop {
687 if unsafe { twai_read_alerts(&mut alerts, delay::BLOCK) } == 0 {
688 let ealerts: EnumSet<Alert> = EnumSet::from_repr_truncated(alerts);
689
690 if !ealerts.is_disjoint(read_alerts()) {
691 READ_NOTIFICATION.notify_lsb();
692 }
693
694 if !ealerts.is_disjoint(write_alerts()) {
695 WRITE_NOTIFICATION.notify_lsb();
696 }
697
698 if let Some(alerts) = NonZeroU32::new(alerts) {
699 ALERT_NOTIFICATION.notify(alerts);
700 }
701 }
702 }
703 }
704}
705
706impl<'d, T> Drop for AsyncCanDriver<'d, T>
707where
708 T: BorrowMut<CanDriver<'d>>,
709{
710 fn drop(&mut self) {
711 let _ = self.stop();
712
713 unsafe { task::destroy(self.task) };
714
715 let mut alerts = 0;
716 esp!(unsafe { twai_reconfigure_alerts(self.driver.borrow().1.as_repr(), &mut alerts) })
717 .unwrap();
718
719 READ_NOTIFICATION.reset();
720 WRITE_NOTIFICATION.reset();
721 ALERT_NOTIFICATION.reset();
722 }
723}
724
725unsafe impl<'d, T> Send for AsyncCanDriver<'d, T> where T: BorrowMut<CanDriver<'d>> + Send {}
726
727static READ_NOTIFICATION: Notification = Notification::new();
728static WRITE_NOTIFICATION: Notification = Notification::new();
729static ALERT_NOTIFICATION: Notification = Notification::new();
730
731#[derive(Debug, EnumSetType)]
733pub enum Flags {
734 Extended,
736 Remote,
738 SingleShot,
742 SelfReception,
746 DlcNonComp,
749 None,
750}
751
752pub struct Frame(twai_message_t);
753
754impl Frame {
755 pub fn new(id: u32, flags: EnumSet<Flags>, data: &[u8]) -> Option<Self> {
756 let dlc = data.len();
757
758 if dlc <= 8 {
759 let mut twai_flags = twai_message_t__bindgen_ty_1::default();
762
763 for flag in flags.iter() {
765 match flag {
766 Flags::Extended => unsafe { twai_flags.__bindgen_anon_1.set_extd(1) },
767 Flags::Remote => unsafe { twai_flags.__bindgen_anon_1.set_rtr(1) },
768 Flags::SingleShot => unsafe { twai_flags.__bindgen_anon_1.set_ss(1) },
769 Flags::SelfReception => unsafe { twai_flags.__bindgen_anon_1.set_self(1) },
770 Flags::DlcNonComp => unsafe { twai_flags.__bindgen_anon_1.set_dlc_non_comp(1) },
771 Flags::None => {}
772 }
773 }
774
775 let mut payload = [0; 8];
776 payload[..dlc].copy_from_slice(data);
777
778 let twai_message = twai_message_t {
779 __bindgen_anon_1: twai_flags,
780 identifier: id,
781 data_length_code: dlc as u8,
782 data: payload,
783 };
784
785 Some(Frame(twai_message))
786 } else {
787 None
788 }
789 }
790
791 pub fn new_remote(id: u32, extended: bool, dlc: usize) -> Option<Self> {
792 if dlc <= 8 {
793 let mut flags = twai_message_t__bindgen_ty_1::default();
796
797 unsafe { flags.__bindgen_anon_1.set_rtr(1) };
799 if extended {
800 unsafe { flags.__bindgen_anon_1.set_extd(1) };
801 }
802
803 let twai_message = twai_message_t {
804 __bindgen_anon_1: flags,
805 identifier: id,
806 data_length_code: dlc as u8,
807 data: [0; 8],
808 };
809
810 Some(Frame(twai_message))
811 } else {
812 None
813 }
814 }
815
816 pub fn is_extended(&self) -> bool {
817 unsafe { self.0.__bindgen_anon_1.__bindgen_anon_1.extd() == 1 }
818 }
819
820 pub fn is_remote_frame(&self) -> bool {
821 unsafe { self.0.__bindgen_anon_1.__bindgen_anon_1.rtr() == 1 }
822 }
823
824 pub fn identifier(&self) -> u32 {
825 self.0.identifier
826 }
827
828 pub fn dlc(&self) -> usize {
829 self.0.data_length_code as usize
830 }
831
832 pub fn data(&self) -> &[u8] {
833 &self.0.data[..self.dlc()]
834 }
835}
836
837impl core::fmt::Display for Frame {
838 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
839 if self.is_extended() {
840 write!(
841 f,
842 "Frame {{ id: {:08x}, remote: {}, data: {:?} }}",
843 self.identifier(),
844 self.is_remote_frame(),
845 self.data()
846 )
847 } else {
848 write!(
849 f,
850 "Frame {{ id: {:03x}, remote: {}, data: {:?} }}",
851 self.identifier(),
852 self.is_remote_frame(),
853 self.data()
854 )
855 }
856 }
857}
858
859impl embedded_hal_0_2::can::Frame for Frame {
860 fn new(id: impl Into<embedded_hal_0_2::can::Id>, data: &[u8]) -> Option<Self> {
861 let (id, flags) = match id.into() {
862 embedded_hal_0_2::can::Id::Standard(id) => (id.as_raw() as u32, Flags::None),
863 embedded_hal_0_2::can::Id::Extended(id) => (id.as_raw(), Flags::Extended),
864 };
865
866 Self::new(id, flags.into(), data)
867 }
868
869 fn new_remote(id: impl Into<embedded_hal_0_2::can::Id>, dlc: usize) -> Option<Self> {
870 let (id, extended) = match id.into() {
871 embedded_hal_0_2::can::Id::Standard(id) => (id.as_raw() as u32, false),
872 embedded_hal_0_2::can::Id::Extended(id) => (id.as_raw(), true),
873 };
874
875 Self::new_remote(id, extended, dlc)
876 }
877
878 fn is_extended(&self) -> bool {
879 Frame::is_extended(self)
880 }
881
882 fn is_standard(&self) -> bool {
883 !self.is_extended()
884 }
885
886 fn is_remote_frame(&self) -> bool {
887 Frame::is_remote_frame(self)
888 }
889
890 fn is_data_frame(&self) -> bool {
891 !self.is_remote_frame()
892 }
893
894 fn id(&self) -> embedded_hal_0_2::can::Id {
895 if self.is_standard() {
896 let id = unsafe {
897 embedded_hal_0_2::can::StandardId::new_unchecked(self.identifier() as u16)
898 };
899 embedded_hal_0_2::can::Id::Standard(id)
900 } else {
901 let id = unsafe { embedded_hal_0_2::can::ExtendedId::new_unchecked(self.identifier()) };
902 embedded_hal_0_2::can::Id::Extended(id)
903 }
904 }
905
906 fn dlc(&self) -> usize {
907 Frame::dlc(self)
908 }
909
910 fn data(&self) -> &[u8] {
911 Frame::data(self)
912 }
913}
914
915impl embedded_can::Frame for Frame {
916 fn new(id: impl Into<embedded_can::Id>, data: &[u8]) -> Option<Self> {
917 let (id, flags) = match id.into() {
918 embedded_can::Id::Standard(id) => (id.as_raw() as u32, Flags::None),
919 embedded_can::Id::Extended(id) => (id.as_raw(), Flags::Extended),
920 };
921
922 Self::new(id, flags.into(), data)
923 }
924
925 fn new_remote(id: impl Into<embedded_can::Id>, dlc: usize) -> Option<Self> {
926 let (id, extended) = match id.into() {
927 embedded_can::Id::Standard(id) => (id.as_raw() as u32, false),
928 embedded_can::Id::Extended(id) => (id.as_raw(), true),
929 };
930
931 Self::new_remote(id, extended, dlc)
932 }
933
934 fn is_extended(&self) -> bool {
935 Frame::is_extended(self)
936 }
937
938 fn is_standard(&self) -> bool {
939 !self.is_extended()
940 }
941
942 fn is_remote_frame(&self) -> bool {
943 Frame::is_remote_frame(self)
944 }
945
946 fn is_data_frame(&self) -> bool {
947 !self.is_remote_frame()
948 }
949
950 fn id(&self) -> embedded_can::Id {
951 if self.is_standard() {
952 let id = unsafe { embedded_can::StandardId::new_unchecked(self.identifier() as u16) };
953 embedded_can::Id::Standard(id)
954 } else {
955 let id = unsafe { embedded_can::ExtendedId::new_unchecked(self.identifier()) };
956 embedded_can::Id::Extended(id)
957 }
958 }
959
960 fn dlc(&self) -> usize {
961 Frame::dlc(self)
962 }
963
964 fn data(&self) -> &[u8] {
965 Frame::data(self)
966 }
967}
968
969crate::impl_peripheral!(CAN);