1#![cfg_attr(
2 feature = "doc-images",
3 doc = ::embed_doc_image::embed_image!(
4 "linkage_blaze_gallery",
5 "docs/assets/linkage_blaze_gallery.png"
6 )
7)]
8#![cfg_attr(
23 feature = "doc-images",
24 doc = "\n[![Linkage Blaze gallery showing CYD applications][linkage_blaze_gallery]][interactive Linkage Blaze gallery]\n"
25)]
26mod buffer;
69mod display;
70mod one_spi;
71mod text;
72#[path = "cyd/touch.rs"]
73mod touch_driver;
74
75use core::{convert::Infallible, fmt};
76
77use device_envoy_core::button::Button;
78use device_envoy_core::cyd::backend;
79use device_envoy_core::cyd::{
80 SCREEN_PIXELS,
81 backend::{CalibrationConfig, RawTouchEvent, TouchUncalibrated},
82 display::CydFrame,
83 touch::TouchEvent,
84};
85use device_envoy_core::pixel_target::PixelTarget;
86pub use device_envoy_core::cyd::{
89 Cyd, CydDisplay, CydTouch,
90 display::{Orientation, tiling},
91 touch,
92};
93use embassy_rp::Peri;
94use embassy_rp::gpio::Pin;
95use embassy_rp::peripherals::{SPI0, SPI1};
96use embassy_rp::spi::{ClkPin, MisoPin, MosiPin};
97use embedded_graphics::{
98 Pixel,
99 mono_font::MonoFont,
100 pixelcolor::{IntoStorage, Rgb565, Rgb888},
101 prelude::{Dimensions, DrawTarget, OriginDimensions, Point, Size},
102 primitives::Rectangle,
103};
104use embedded_hal::spi::SpiDevice;
105use static_cell::StaticCell;
106
107use buffer::DynPixelBuffer;
108use buffer::{PixelBuffer, RegionView};
109pub use display::DEFAULT_DISPLAY_SPI_HZ;
110pub use one_spi::{CydRpOneSpi, CydRpOneSpiStatic};
111pub use text::DEFAULT_FONT;
112use touch_driver::TOUCH_SPI_HZ;
113
114use crate::flash_block::FlashBlockRp;
115use display::CydDisplayRp as CydDisplayRpDevice;
116use touch_driver::CydTouchRp as CydTouchRpDevice;
117
118pub struct CydDisplayRp<D: SpiDevice<u8> = display::CydDisplaySpiDevice> {
128 display: CydDisplayRpDevice<D>,
129 orientation: Orientation,
130 pixel_buffer: &'static mut dyn DynPixelBuffer,
133 background_color: Rgb888,
138 foreground_color: Rgb888,
139 background565: Rgb565,
140 foreground565: Rgb565,
141 font: &'static MonoFont<'static>,
142}
143
144pub(crate) struct CydTouchUncalibratedRp<D = touch_driver::CydTouchSpiDevice> {
149 touch: CydTouchRpDevice<D>,
150}
151
152pub struct CydTouchRp<D = touch_driver::CydTouchSpiDevice> {
158 raw: CydTouchUncalibratedRp<D>,
159 calibration_config: CalibrationConfig,
160 orientation: Orientation,
161}
162
163pub struct CydRp {
170 pub display: CydDisplayRp,
172 pub touch: CydTouchRp,
174}
175
176pub(crate) struct CydRpUncalibrated {
178 pub display: CydDisplayRp,
180 pub touch: CydTouchUncalibratedRp,
182}
183
184pub struct CydStaticRp<const PIXEL_COUNT: usize> {
198 pixel_buffer: StaticCell<PixelBuffer<PIXEL_COUNT>>,
199}
200
201impl<const PIXEL_COUNT: usize> CydStaticRp<PIXEL_COUNT> {
202 pub(crate) const fn new() -> Self {
205 assert!(
206 PIXEL_COUNT <= SCREEN_PIXELS,
207 "PIXEL_COUNT must not exceed SCREEN_PIXELS"
208 );
209 Self {
210 pixel_buffer: StaticCell::new(),
211 }
212 }
213}
214
215pub struct CydFrameRp<'a, D: SpiDevice<u8> = display::CydDisplaySpiDevice> {
222 display: &'a mut CydDisplayRpDevice<D>,
223 view: RegionView<'a>,
224 rectangle: Rectangle,
227 pub(crate) background565: Rgb565,
230 pub(crate) foreground565: Rgb565,
231 pub(crate) font: &'static MonoFont<'static>,
232}
233
234impl<'a, D: SpiDevice<u8>> CydFrameRp<'a, D> {
235 pub fn fill(&mut self, color: Rgb565) -> &mut Self {
241 self.view.fill(color);
242 self
243 }
244
245 #[must_use]
247 pub fn width(&self) -> usize {
248 self.view.width()
249 }
250
251 #[must_use]
253 pub fn height(&self) -> usize {
254 self.view.height()
255 }
256
257 pub fn raw_pixels_mut(&mut self) -> &mut [u16] {
259 self.view.raw_pixels_mut()
260 }
261
262 pub fn flush(&mut self) -> Result<(), Error> {
270 Ok(self.display.flush_buffer(
271 self.view.size().width as usize,
272 self.view.size().height as usize,
273 self.view.raw_pixels(),
274 self.rectangle.top_left,
275 )?)
276 }
277
278 fn local_x(&self, x: i32) -> Option<usize> {
279 usize::try_from(x.checked_sub(self.rectangle.top_left.x)?).ok()
280 }
281
282 fn local_y(&self, y: i32) -> Option<usize> {
283 usize::try_from(y.checked_sub(self.rectangle.top_left.y)?).ok()
284 }
285}
286
287impl<D: SpiDevice<u8>> DrawTarget for CydFrameRp<'_, D> {
288 type Color = Rgb565;
289 type Error = Infallible;
290
291 fn clear(&mut self, color: Self::Color) -> Result<(), Self::Error> {
292 self.fill(color);
293 Ok(())
294 }
295
296 fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
297 where
298 I: IntoIterator<Item = Pixel<Self::Color>>,
299 {
300 for Pixel(point, color) in pixels {
301 let Some(local_x) = self.local_x(point.x) else {
302 continue;
303 };
304 let Some(local_y) = self.local_y(point.y) else {
305 continue;
306 };
307 if local_x < self.view.width() && local_y < self.view.height() {
308 let index = local_y * self.view.width() + local_x;
309 self.raw_pixels_mut()[index] = color.into_storage();
310 }
311 }
312 Ok(())
313 }
314}
315
316impl<D: SpiDevice<u8>> Dimensions for CydFrameRp<'_, D> {
317 fn bounding_box(&self) -> Rectangle {
318 self.rectangle
319 }
320}
321
322impl<D: SpiDevice<u8>> PixelTarget for CydFrameRp<'_, D> {
323 fn width(&self) -> usize {
324 usize::try_from(self.rectangle.top_left.x)
325 .expect("frame top-left x must be non-negative")
326 .checked_add(self.width())
327 .expect("frame width must fit in usize")
328 }
329
330 fn height(&self) -> usize {
331 usize::try_from(self.rectangle.top_left.y)
332 .expect("frame top-left y must be non-negative")
333 .checked_add(self.height())
334 .expect("frame height must fit in usize")
335 }
336
337 fn put_pixel(&mut self, x: usize, y: usize, color: Rgb888) {
338 let Some(local_x) = self.local_x(x as i32) else {
339 return;
340 };
341 let Some(local_y) = self.local_y(y as i32) else {
342 return;
343 };
344 if local_x >= self.view.width() || local_y >= self.view.height() {
345 return;
346 }
347 let stride = self.view.width();
348 self.raw_pixels_mut()[local_y * stride + local_x] = Rgb565::from(color).into_storage();
349 }
350
351 fn put_pixel_565(&mut self, x: usize, y: usize, rgb565: u16) {
354 let Some(local_x) = self.local_x(x as i32) else {
355 return;
356 };
357 let Some(local_y) = self.local_y(y as i32) else {
358 return;
359 };
360 if local_x >= self.view.width() || local_y >= self.view.height() {
361 return;
362 }
363 let stride = self.view.width();
364 self.raw_pixels_mut()[local_y * stride + local_x] = rgb565;
365 }
366}
367
368#[derive(Debug)]
369pub enum Error {
373 InitDisplay,
376 FlushFrameBuffer,
379 SetOrientation,
382}
383
384impl<D: SpiDevice<u8>> CydDisplayRp<D> {
385 fn set_orientation(&mut self, orientation: Orientation) -> Result<(), Error> {
386 self.display.set_orientation(orientation)?;
387 self.orientation = orientation;
388 Ok(())
389 }
390
391 fn from_display_device(
392 mut display: CydDisplayRpDevice<D>,
393 orientation: Orientation,
394 background_color: Rgb888,
395 foreground_color: Rgb888,
396 font: &'static MonoFont<'static>,
397 pixel_buffer: &'static mut dyn DynPixelBuffer,
398 ) -> Result<Self, Error> {
399 let background565 = rgb565(background_color);
400 display.fill(background565)?;
401
402 Ok(Self {
403 display,
404 orientation,
405 pixel_buffer,
406 background_color,
407 foreground_color,
408 background565,
409 foreground565: rgb565(foreground_color),
410 font,
411 })
412 }
413
414 #[expect(clippy::too_many_arguments, reason = "mirrors CydDisplayRp::new")]
419 pub(crate) fn new_from_device<Dc, Rst, Backlight>(
420 spi_device: D,
421 dc_pin: Peri<'static, Dc>,
422 rst_pin: Peri<'static, Rst>,
423 backlight_pin: Peri<'static, Backlight>,
424 orientation: Orientation,
425 background_color: Rgb888,
426 foreground_color: Rgb888,
427 font: &'static MonoFont<'static>,
428 pixel_buffer: &'static mut dyn DynPixelBuffer,
429 ) -> Result<Self, Error>
430 where
431 Dc: Pin,
432 Rst: Pin,
433 Backlight: Pin,
434 {
435 let display = CydDisplayRpDevice::new_from_device(
436 spi_device,
437 dc_pin,
438 rst_pin,
439 backlight_pin,
440 orientation,
441 )?;
442 Self::from_display_device(
443 display,
444 orientation,
445 background_color,
446 foreground_color,
447 font,
448 pixel_buffer,
449 )
450 }
451}
452
453impl CydDisplayRp<display::CydDisplaySpiDevice> {
454 #[expect(
477 clippy::too_many_arguments,
478 reason = "mirrors CydEsp's constructor shape"
479 )]
480 pub fn new<const PIXEL_COUNT: usize, Sck, Mosi, Miso, Cs, Dc, Rst, Backlight>(
481 statics: &'static CydStaticRp<PIXEL_COUNT>,
482 display_spi: Peri<'static, SPI0>,
483 display_sck_pin: Peri<'static, Sck>,
484 display_mosi_pin: Peri<'static, Mosi>,
485 display_miso_pin: Peri<'static, Miso>,
486 display_cs_pin: Peri<'static, Cs>,
487 display_dc_pin: Peri<'static, Dc>,
488 display_rst_pin: Peri<'static, Rst>,
489 display_backlight_pin: Peri<'static, Backlight>,
490 display_spi_hz: u32,
491 orientation: Orientation,
492 background_color: Rgb888,
493 foreground_color: Rgb888,
494 font: &'static MonoFont<'static>,
495 ) -> Result<Self, Error>
496 where
497 Sck: Pin + ClkPin<SPI0>,
498 Mosi: Pin + MosiPin<SPI0>,
499 Miso: Pin + MisoPin<SPI0>,
500 Cs: Pin,
501 Dc: Pin,
502 Rst: Pin,
503 Backlight: Pin,
504 {
505 let pixel_buffer = PixelBuffer::init_static(&statics.pixel_buffer);
506 let display = CydDisplayRpDevice::new(
507 display_spi,
508 display_sck_pin,
509 display_mosi_pin,
510 display_miso_pin,
511 display_cs_pin,
512 display_dc_pin,
513 display_rst_pin,
514 display_backlight_pin,
515 display_spi_hz,
516 orientation,
517 )?;
518 Self::from_display_device(
519 display,
520 orientation,
521 background_color,
522 foreground_color,
523 font,
524 pixel_buffer,
525 )
526 }
527}
528
529impl<D: SpiDevice<u8>> CydTouchUncalibratedRp<D> {
530 pub(crate) fn from_device<Irq: Pin>(
535 touch_spi_device: D,
536 touch_irq_pin: Peri<'static, Irq>,
537 ) -> Self {
538 Self {
539 touch: CydTouchRpDevice::from_device(touch_spi_device, touch_irq_pin),
540 }
541 }
542}
543
544impl CydTouchUncalibratedRp<touch_driver::CydTouchSpiDevice> {
545 #[expect(clippy::too_many_arguments, reason = "mirrors CydDisplayRp::new")]
547 pub(crate) fn new<TouchSck, TouchMosi, TouchMiso, TouchCs, TouchIrq>(
548 touch_spi: Peri<'static, SPI1>,
549 touch_sck_pin: Peri<'static, TouchSck>,
550 touch_mosi_pin: Peri<'static, TouchMosi>,
551 touch_miso_pin: Peri<'static, TouchMiso>,
552 touch_cs_pin: Peri<'static, TouchCs>,
553 touch_irq_pin: Peri<'static, TouchIrq>,
554 ) -> Result<Self, Error>
555 where
556 TouchSck: Pin + ClkPin<SPI1>,
557 TouchMosi: Pin + MosiPin<SPI1>,
558 TouchMiso: Pin + MisoPin<SPI1>,
559 TouchCs: Pin,
560 TouchIrq: Pin,
561 {
562 Ok(Self {
563 touch: CydTouchRpDevice::new(
564 touch_spi,
565 touch_sck_pin,
566 touch_mosi_pin,
567 touch_miso_pin,
568 touch_cs_pin,
569 touch_irq_pin,
570 )?,
571 })
572 }
573}
574
575impl CydRp {
576 pub const SCREEN_PIXELS: usize = SCREEN_PIXELS;
580
581 #[must_use]
599 pub const fn new_static<const PIXEL_COUNT: usize>() -> CydStaticRp<PIXEL_COUNT> {
600 CydStaticRp::new()
601 }
602
603 #[expect(clippy::too_many_arguments, reason = "mirrors CydDisplayRp::new")]
671 pub async fn new<
672 const PIXEL_COUNT: usize,
673 Sck,
674 Mosi,
675 Miso,
676 Cs,
677 Dc,
678 Rst,
679 Backlight,
680 TouchSck,
681 TouchMosi,
682 TouchMiso,
683 TouchCs,
684 TouchIrq,
685 >(
686 statics: &'static CydStaticRp<PIXEL_COUNT>,
687 display_spi: Peri<'static, SPI0>,
688 display_sck_pin: Peri<'static, Sck>,
689 display_mosi_pin: Peri<'static, Mosi>,
690 display_miso_pin: Peri<'static, Miso>,
691 display_cs_pin: Peri<'static, Cs>,
692 display_dc_pin: Peri<'static, Dc>,
693 display_rst_pin: Peri<'static, Rst>,
694 display_backlight_pin: Peri<'static, Backlight>,
695 display_spi_hz: u32,
696 orientation: Orientation,
697 background_color: Rgb888,
698 foreground_color: Rgb888,
699 font: &'static MonoFont<'static>,
700 touch_spi: Peri<'static, SPI1>,
701 touch_sck_pin: Peri<'static, TouchSck>,
702 touch_mosi_pin: Peri<'static, TouchMosi>,
703 touch_miso_pin: Peri<'static, TouchMiso>,
704 touch_cs_pin: Peri<'static, TouchCs>,
705 touch_irq_pin: Peri<'static, TouchIrq>,
706 calibration_flash_block: &mut FlashBlockRp,
707 recalibration_button: &mut impl Button,
708 ) -> crate::Result<Self>
709 where
710 Sck: Pin + ClkPin<SPI0>,
711 Mosi: Pin + MosiPin<SPI0>,
712 Miso: Pin + MisoPin<SPI0>,
713 Cs: Pin,
714 Dc: Pin,
715 Rst: Pin,
716 Backlight: Pin,
717 TouchSck: Pin + ClkPin<SPI1>,
718 TouchMosi: Pin + MosiPin<SPI1>,
719 TouchMiso: Pin + MisoPin<SPI1>,
720 TouchCs: Pin,
721 TouchIrq: Pin,
722 {
723 let CydRpUncalibrated { mut display, touch } = CydRpUncalibrated::new(
724 statics,
725 display_spi,
726 display_sck_pin,
727 display_mosi_pin,
728 display_miso_pin,
729 display_cs_pin,
730 display_dc_pin,
731 display_rst_pin,
732 display_backlight_pin,
733 display_spi_hz,
734 orientation,
735 background_color,
736 foreground_color,
737 font,
738 touch_spi,
739 touch_sck_pin,
740 touch_mosi_pin,
741 touch_miso_pin,
742 touch_cs_pin,
743 touch_irq_pin,
744 )?;
745 let touch = backend::ensure_calibration(
746 &mut display,
747 touch,
748 calibration_flash_block,
749 recalibration_button,
750 None,
751 orientation,
752 )
753 .await
754 .map_err(|error| match error {
755 backend::Error::Device(cyd_error) => crate::Error::from(cyd_error),
756 backend::Error::Flash(flash_error) => flash_error,
757 })?;
758 display.set_orientation(orientation)?;
759 Ok(Self { display, touch })
760 }
761}
762
763impl Cyd for CydRp {
764 type Error = Error;
765 type Display = CydDisplayRp;
766 type Touch = CydTouchRp;
767
768 fn parts(&mut self) -> (&mut Self::Display, &mut Self::Touch) {
769 (&mut self.display, &mut self.touch)
770 }
771
772 fn orientation(&self) -> Orientation {
773 self.display.orientation
774 }
775}
776
777impl CydRpUncalibrated {
778 #[expect(clippy::too_many_arguments, reason = "mirrors CydDisplayRp::new")]
780 pub(crate) fn new<
781 const PIXEL_COUNT: usize,
782 Sck,
783 Mosi,
784 Miso,
785 Cs,
786 Dc,
787 Rst,
788 Backlight,
789 TouchSck,
790 TouchMosi,
791 TouchMiso,
792 TouchCs,
793 TouchIrq,
794 >(
795 statics: &'static CydStaticRp<PIXEL_COUNT>,
796 display_spi: Peri<'static, SPI0>,
797 display_sck_pin: Peri<'static, Sck>,
798 display_mosi_pin: Peri<'static, Mosi>,
799 display_miso_pin: Peri<'static, Miso>,
800 display_cs_pin: Peri<'static, Cs>,
801 display_dc_pin: Peri<'static, Dc>,
802 display_rst_pin: Peri<'static, Rst>,
803 display_backlight_pin: Peri<'static, Backlight>,
804 display_spi_hz: u32,
805 _orientation: Orientation,
806 background_color: Rgb888,
807 foreground_color: Rgb888,
808 font: &'static MonoFont<'static>,
809 touch_spi: Peri<'static, SPI1>,
810 touch_sck_pin: Peri<'static, TouchSck>,
811 touch_mosi_pin: Peri<'static, TouchMosi>,
812 touch_miso_pin: Peri<'static, TouchMiso>,
813 touch_cs_pin: Peri<'static, TouchCs>,
814 touch_irq_pin: Peri<'static, TouchIrq>,
815 ) -> Result<Self, Error>
816 where
817 Sck: Pin + ClkPin<SPI0>,
818 Mosi: Pin + MosiPin<SPI0>,
819 Miso: Pin + MisoPin<SPI0>,
820 Cs: Pin,
821 Dc: Pin,
822 Rst: Pin,
823 Backlight: Pin,
824 TouchSck: Pin + ClkPin<SPI1>,
825 TouchMosi: Pin + MosiPin<SPI1>,
826 TouchMiso: Pin + MisoPin<SPI1>,
827 TouchCs: Pin,
828 TouchIrq: Pin,
829 {
830 Ok(Self {
831 display: CydDisplayRp::new(
832 statics,
833 display_spi,
834 display_sck_pin,
835 display_mosi_pin,
836 display_miso_pin,
837 display_cs_pin,
838 display_dc_pin,
839 display_rst_pin,
840 display_backlight_pin,
841 display_spi_hz,
842 Orientation::Landscape,
843 background_color,
844 foreground_color,
845 font,
846 )?,
847 touch: CydTouchUncalibratedRp::new(
848 touch_spi,
849 touch_sck_pin,
850 touch_mosi_pin,
851 touch_miso_pin,
852 touch_cs_pin,
853 touch_irq_pin,
854 )?,
855 })
856 }
857}
858
859fn rgb565(color: Rgb888) -> Rgb565 {
860 Rgb565::from(color)
861}
862
863impl<D: SpiDevice<u8>> fmt::Debug for CydDisplayRp<D> {
864 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
865 formatter
866 .debug_struct("CydDisplayRp")
867 .field("orientation", &self.orientation)
868 .finish_non_exhaustive()
869 }
870}
871
872impl<D> fmt::Debug for CydTouchUncalibratedRp<D> {
873 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
874 formatter
875 .debug_struct("CydTouchUncalibratedRp")
876 .finish_non_exhaustive()
877 }
878}
879
880impl<D> fmt::Debug for CydTouchRp<D> {
881 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
882 formatter
883 .debug_struct("CydTouchRp")
884 .field("calibration_config", &self.calibration_config)
885 .field("orientation", &self.orientation)
886 .finish_non_exhaustive()
887 }
888}
889
890impl fmt::Debug for CydRp {
891 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
892 formatter
893 .debug_struct("CydRp")
894 .field("orientation", &self.display.orientation)
895 .finish_non_exhaustive()
896 }
897}
898
899impl fmt::Debug for CydRpUncalibrated {
900 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
901 formatter
902 .debug_struct("CydRpUncalibrated")
903 .field("orientation", &self.display.orientation)
904 .finish_non_exhaustive()
905 }
906}
907
908impl<D: SpiDevice<u8>> backend::DisplayBackend for CydDisplayRp<D> {
909 type Error = Error;
910 type Frame<'a>
911 = CydFrameRp<'a, D>
912 where
913 Self: 'a;
914
915 fn create_frame_mut(&mut self, rectangle: Rectangle) -> Self::Frame<'_> {
916 self.display.make_frame(
917 &mut *self.pixel_buffer,
918 rectangle,
919 self.background565,
920 self.foreground565,
921 self.font,
922 )
923 }
924}
925
926impl<D: SpiDevice<u8>> CydDisplay for CydDisplayRp<D> {
927 #[inline]
928 fn screen_size(&self) -> Size {
929 self.display.size()
930 }
931
932 fn background_color(&self) -> Rgb888 {
933 self.background_color
934 }
935
936 fn foreground_color(&self) -> Rgb888 {
937 self.foreground_color
938 }
939
940 fn background_565(&self) -> Rgb565 {
941 self.background565
942 }
943
944 fn foreground_565(&self) -> Rgb565 {
945 self.foreground565
946 }
947
948 #[inline]
949 fn fill_rectangle(&mut self, rectangle: Rectangle, color: Rgb565) -> Result<(), Error> {
950 Ok(self.display.fill_rectangle(rectangle, color)?)
951 }
952
953 #[inline]
954 fn fill_contiguous<I>(&mut self, rectangle: Rectangle, pixels: I) -> Result<(), Error>
955 where
956 I: IntoIterator<Item = Rgb565>,
957 {
958 Ok(self.display.fill_contiguous(rectangle, pixels)?)
959 }
960}
961
962impl<D: SpiDevice<u8>> TouchUncalibrated for CydTouchUncalibratedRp<D> {
963 type Error = Error;
964 type Calibrated = CydTouchRp<D>;
965
966 fn read_raw_touch_event(&mut self) -> Result<Option<RawTouchEvent>, Self::Error> {
967 Ok(self.touch.read_raw_touch_event())
968 }
969
970 fn calibrate(
971 self,
972 calibration_config: CalibrationConfig,
973 orientation: Orientation,
974 ) -> Self::Calibrated {
975 CydTouchRp {
976 raw: self,
977 calibration_config,
978 orientation,
979 }
980 }
981}
982
983impl<D: SpiDevice<u8>> CydTouch for CydTouchRp<D> {
984 type Error = Error;
985
986 fn try_read(&mut self) -> Result<Option<TouchEvent>, Error> {
987 Ok(self
988 .raw
989 .touch
990 .read_raw_touch_event()
991 .map(|raw_touch_event| match raw_touch_event {
992 RawTouchEvent::Down { raw_x, raw_y } => {
993 let (x, y) = self.calibration_config.map_raw_to_screen(raw_x, raw_y);
994 TouchEvent::Down {
995 point: self
996 .orientation
997 .map_landscape_point(Point::new(x as i32, y as i32)),
998 }
999 }
1000 RawTouchEvent::Move { raw_x, raw_y } => {
1001 let (x, y) = self.calibration_config.map_raw_to_screen(raw_x, raw_y);
1002 TouchEvent::Move {
1003 point: self
1004 .orientation
1005 .map_landscape_point(Point::new(x as i32, y as i32)),
1006 }
1007 }
1008 RawTouchEvent::Up => TouchEvent::Up,
1009 }))
1010 }
1011}
1012
1013impl<D: SpiDevice<u8>> CydFrame for CydFrameRp<'_, D> {
1014 type Error = Error;
1015
1016 fn rectangle(&self) -> Rectangle {
1017 self.rectangle
1018 }
1019
1020 fn fill(&mut self, color: Rgb565) -> &mut Self {
1021 CydFrameRp::fill(self, color)
1022 }
1023
1024 fn clear(&mut self) -> &mut Self {
1025 self.fill(self.background565)
1026 }
1027
1028 fn write_text(&mut self, text: &str) -> &mut Self {
1029 CydFrameRp::write_text(self, text)
1030 }
1031
1032 fn copy_from_565(&mut self, src: &[u16]) -> device_envoy_core::Result<()> {
1033 let dst = self.raw_pixels_mut();
1034 if dst.len() != src.len() {
1035 return Err(device_envoy_core::Error::CopySize {
1036 src_len: src.len(),
1037 frame_len: dst.len(),
1038 });
1039 }
1040 dst.copy_from_slice(src);
1041 Ok(())
1042 }
1043
1044 async fn flush(&mut self) -> Result<(), Error> {
1048 CydFrameRp::flush(self)
1049 }
1050}