1use core::convert::Infallible;
133
134use crate::FrameBufferOperations;
135use bitfield::bitfield;
136#[cfg(not(feature = "esp-hal-dma"))]
137use embedded_dma::ReadBuffer;
138use embedded_graphics::pixelcolor::RgbColor;
139use embedded_graphics::prelude::Point;
140#[cfg(feature = "esp-hal-dma")]
141use esp_hal::dma::ReadBuffer;
142
143use super::Color;
144use super::FrameBuffer;
145use super::WordSize;
146
147const BLANKING_DELAY: usize = 1;
148
149#[inline]
152const fn make_data_template<const COLS: usize>(addr: u8, prev_addr: u8) -> [Entry; COLS] {
153 let mut data = [Entry::new(); COLS];
154 let mut i = 0;
155
156 while i < COLS {
157 let mut entry = Entry::new();
158 entry.0 = prev_addr as u16;
159
160 if i == 1 {
162 entry.0 |= 0b1_0000_0000; } else if i == COLS - BLANKING_DELAY - 1 {
164 } else if i == COLS - 1 {
166 entry.0 |= 0b0010_0000; entry.0 = (entry.0 & !0b0001_1111) | (addr as u16); } else if i > 1 && i < COLS - BLANKING_DELAY - 1 {
169 entry.0 |= 0b1_0000_0000; }
171
172 data[map_index(i)] = entry;
173 i += 1;
174 }
175
176 data
177}
178
179bitfield! {
180 #[derive(Clone, Copy, Default, PartialEq)]
201 #[repr(transparent)]
202 struct Entry(u16);
203 dummy2, set_dummy2: 15;
204 blu2, set_blu2: 14;
205 grn2, set_grn2: 13;
206 red2, set_red2: 12;
207 blu1, set_blu1: 11;
208 grn1, set_grn1: 10;
209 red1, set_red1: 9;
210 output_enable, set_output_enable: 8;
211 dummy1, set_dummy1: 7;
212 dummy0, set_dummy0: 6;
213 latch, set_latch: 5;
214 addr, set_addr: 4, 0;
215}
216
217impl core::fmt::Debug for Entry {
218 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
219 f.debug_tuple("Entry")
220 .field(&format_args!("{:#x}", self.0))
221 .finish()
222 }
223}
224
225#[cfg(feature = "defmt")]
226impl defmt::Format for Entry {
227 fn format(&self, f: defmt::Formatter) {
228 defmt::write!(f, "Entry({=u16:#x})", self.0);
229 }
230}
231
232impl Entry {
233 const fn new() -> Self {
234 Self(0)
235 }
236
237 const COLOR0_MASK: u16 = 0b0000_1110_0000_0000; const COLOR1_MASK: u16 = 0b0111_0000_0000_0000; #[inline]
242 fn set_color0_bits(&mut self, bits: u8) {
243 let bits16 = u16::from(bits) << 9;
244 self.0 = (self.0 & !Self::COLOR0_MASK) | (bits16 & Self::COLOR0_MASK);
245 }
246
247 #[inline]
248 fn set_color1_bits(&mut self, bits: u8) {
249 let bits16 = u16::from(bits) << 12;
250 self.0 = (self.0 & !Self::COLOR1_MASK) | (bits16 & Self::COLOR1_MASK);
251 }
252}
253
254#[derive(Clone, Copy, PartialEq, Debug)]
263#[repr(C)]
264struct Row<const COLS: usize> {
265 data: [Entry; COLS],
266}
267
268const fn map_index(i: usize) -> usize {
269 #[cfg(feature = "esp32-ordering")]
270 {
271 i ^ 1
272 }
273 #[cfg(not(feature = "esp32-ordering"))]
274 {
275 i
276 }
277}
278
279impl<const COLS: usize> Default for Row<COLS> {
280 fn default() -> Self {
281 Self::new()
282 }
283}
284
285impl<const COLS: usize> Row<COLS> {
286 pub const fn new() -> Self {
287 Self {
288 data: [Entry::new(); COLS],
289 }
290 }
291
292 pub fn format(&mut self, addr: u8, prev_addr: u8) {
293 let template = make_data_template::<COLS>(addr, prev_addr);
295 self.data.copy_from_slice(&template);
296 }
297
298 #[inline]
301 pub fn clear_colors(&mut self) {
302 const COLOR_CLEAR_MASK: u16 = !0b0111_1110_0000_0000; for entry in &mut self.data {
306 entry.0 &= COLOR_CLEAR_MASK;
307 }
308 }
309
310 #[inline]
311 pub fn set_color0(&mut self, col: usize, r: bool, g: bool, b: bool) {
312 let bits = (u8::from(b) << 2) | (u8::from(g) << 1) | u8::from(r);
313 let col = map_index(col);
314 self.data[col].set_color0_bits(bits);
315 }
316
317 #[inline]
318 pub fn set_color1(&mut self, col: usize, r: bool, g: bool, b: bool) {
319 let bits = (u8::from(b) << 2) | (u8::from(g) << 1) | u8::from(r);
320 let col = map_index(col);
321 self.data[col].set_color1_bits(bits);
322 }
323}
324
325#[derive(Copy, Clone, Debug)]
326#[repr(C)]
327struct Frame<const ROWS: usize, const COLS: usize, const NROWS: usize> {
328 rows: [Row<COLS>; NROWS],
329}
330
331impl<const ROWS: usize, const COLS: usize, const NROWS: usize> Frame<ROWS, COLS, NROWS> {
332 pub const fn new() -> Self {
333 Self {
334 rows: [Row::new(); NROWS],
335 }
336 }
337
338 pub fn format(&mut self) {
339 for (addr, row) in self.rows.iter_mut().enumerate() {
340 let prev_addr = if addr == 0 {
341 NROWS as u8 - 1
342 } else {
343 addr as u8 - 1
344 };
345 row.format(addr as u8, prev_addr);
346 }
347 }
348
349 #[inline]
351 pub fn clear_colors(&mut self) {
352 for row in &mut self.rows {
353 row.clear_colors();
354 }
355 }
356
357 #[inline]
358 pub fn set_pixel(&mut self, y: usize, x: usize, red: bool, green: bool, blue: bool) {
359 let row = &mut self.rows[if y < NROWS { y } else { y - NROWS }];
360 if y < NROWS {
361 row.set_color0(x, red, green, blue);
362 } else {
363 row.set_color1(x, red, green, blue);
364 }
365 }
366}
367
368impl<const ROWS: usize, const COLS: usize, const NROWS: usize> Default
369 for Frame<ROWS, COLS, NROWS>
370{
371 fn default() -> Self {
372 Self::new()
373 }
374}
375
376#[derive(Copy, Clone)]
401#[repr(C)]
402pub struct DmaFrameBuffer<
403 const ROWS: usize,
404 const COLS: usize,
405 const NROWS: usize,
406 const BITS: u8,
407 const FRAME_COUNT: usize,
408> {
409 _align: u64,
410 frames: [Frame<ROWS, COLS, NROWS>; FRAME_COUNT],
411}
412
413impl<
414 const ROWS: usize,
415 const COLS: usize,
416 const NROWS: usize,
417 const BITS: u8,
418 const FRAME_COUNT: usize,
419 > Default for DmaFrameBuffer<ROWS, COLS, NROWS, BITS, FRAME_COUNT>
420{
421 fn default() -> Self {
422 Self::new()
423 }
424}
425
426impl<
427 const ROWS: usize,
428 const COLS: usize,
429 const NROWS: usize,
430 const BITS: u8,
431 const FRAME_COUNT: usize,
432 > DmaFrameBuffer<ROWS, COLS, NROWS, BITS, FRAME_COUNT>
433{
434 #[must_use]
457 pub fn new() -> Self {
458 debug_assert!(BITS <= 8);
459
460 let mut instance = Self {
461 _align: 0,
462 frames: [Frame::new(); FRAME_COUNT],
463 };
464
465 instance.format();
467 instance
468 }
469
470 #[cfg(feature = "esp-hal-dma")]
486 pub const fn dma_buffer_size_bytes() -> usize {
487 core::mem::size_of::<[Frame<ROWS, COLS, NROWS>; FRAME_COUNT]>()
488 }
489
490 #[inline]
510 pub fn format(&mut self) {
511 for frame in &mut self.frames {
512 frame.format();
513 }
514 }
515
516 #[inline]
536 pub fn erase(&mut self) {
537 for frame in &mut self.frames {
538 frame.clear_colors();
539 }
540 }
541
542 pub fn set_pixel(&mut self, p: Point, color: Color) {
558 if p.x < 0 || p.y < 0 {
559 return;
560 }
561 self.set_pixel_internal(p.x as usize, p.y as usize, color);
562 }
563
564 #[inline]
565 fn frames_on(v: u8) -> usize {
566 (v as usize) >> (8 - BITS)
568 }
569
570 #[inline]
571 fn set_pixel_internal(&mut self, x: usize, y: usize, color: Color) {
572 if x >= COLS || y >= ROWS {
573 return;
574 }
575
576 #[cfg(feature = "skip-black-pixels")]
579 if color == Color::BLACK {
580 return;
581 }
582
583 let red_frames = Self::frames_on(color.r());
585 let green_frames = Self::frames_on(color.g());
586 let blue_frames = Self::frames_on(color.b());
587
588 for (frame_idx, frame) in self.frames.iter_mut().enumerate() {
590 frame.set_pixel(
591 y,
592 x,
593 frame_idx < red_frames,
594 frame_idx < green_frames,
595 frame_idx < blue_frames,
596 );
597 }
598 }
599}
600
601impl<
602 const ROWS: usize,
603 const COLS: usize,
604 const NROWS: usize,
605 const BITS: u8,
606 const FRAME_COUNT: usize,
607 > FrameBufferOperations<ROWS, COLS, NROWS, BITS, FRAME_COUNT>
608 for DmaFrameBuffer<ROWS, COLS, NROWS, BITS, FRAME_COUNT>
609{
610 #[inline]
611 fn erase(&mut self) {
612 DmaFrameBuffer::<ROWS, COLS, NROWS, BITS, FRAME_COUNT>::erase(self);
613 }
614
615 #[inline]
616 fn set_pixel(&mut self, p: Point, color: Color) {
617 DmaFrameBuffer::<ROWS, COLS, NROWS, BITS, FRAME_COUNT>::set_pixel(self, p, color);
618 }
619}
620
621impl<
622 const ROWS: usize,
623 const COLS: usize,
624 const NROWS: usize,
625 const BITS: u8,
626 const FRAME_COUNT: usize,
627 > embedded_graphics::prelude::OriginDimensions
628 for DmaFrameBuffer<ROWS, COLS, NROWS, BITS, FRAME_COUNT>
629{
630 fn size(&self) -> embedded_graphics::prelude::Size {
631 embedded_graphics::prelude::Size::new(COLS as u32, ROWS as u32)
632 }
633}
634
635impl<
636 const ROWS: usize,
637 const COLS: usize,
638 const NROWS: usize,
639 const BITS: u8,
640 const FRAME_COUNT: usize,
641 > embedded_graphics::prelude::OriginDimensions
642 for &mut DmaFrameBuffer<ROWS, COLS, NROWS, BITS, FRAME_COUNT>
643{
644 fn size(&self) -> embedded_graphics::prelude::Size {
645 embedded_graphics::prelude::Size::new(COLS as u32, ROWS as u32)
646 }
647}
648
649impl<
650 const ROWS: usize,
651 const COLS: usize,
652 const NROWS: usize,
653 const BITS: u8,
654 const FRAME_COUNT: usize,
655 > embedded_graphics::draw_target::DrawTarget
656 for DmaFrameBuffer<ROWS, COLS, NROWS, BITS, FRAME_COUNT>
657{
658 type Color = Color;
659
660 type Error = Infallible;
661
662 fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
663 where
664 I: IntoIterator<Item = embedded_graphics::Pixel<Self::Color>>,
665 {
666 for pixel in pixels {
667 self.set_pixel_internal(pixel.0.x as usize, pixel.0.y as usize, pixel.1);
668 }
669 Ok(())
670 }
671}
672
673unsafe impl<
674 const ROWS: usize,
675 const COLS: usize,
676 const NROWS: usize,
677 const BITS: u8,
678 const FRAME_COUNT: usize,
679 > ReadBuffer for DmaFrameBuffer<ROWS, COLS, NROWS, BITS, FRAME_COUNT>
680{
681 #[cfg(not(feature = "esp-hal-dma"))]
682 type Word = u8;
683
684 unsafe fn read_buffer(&self) -> (*const u8, usize) {
685 let ptr = (&raw const self.frames).cast::<u8>();
686 let len = core::mem::size_of_val(&self.frames);
687 (ptr, len)
688 }
689}
690
691unsafe impl<
692 const ROWS: usize,
693 const COLS: usize,
694 const NROWS: usize,
695 const BITS: u8,
696 const FRAME_COUNT: usize,
697 > ReadBuffer for &mut DmaFrameBuffer<ROWS, COLS, NROWS, BITS, FRAME_COUNT>
698{
699 #[cfg(not(feature = "esp-hal-dma"))]
700 type Word = u8;
701
702 unsafe fn read_buffer(&self) -> (*const u8, usize) {
703 let ptr = (&raw const self.frames).cast::<u8>();
704 let len = core::mem::size_of_val(&self.frames);
705 (ptr, len)
706 }
707}
708
709impl<
710 const ROWS: usize,
711 const COLS: usize,
712 const NROWS: usize,
713 const BITS: u8,
714 const FRAME_COUNT: usize,
715 > core::fmt::Debug for DmaFrameBuffer<ROWS, COLS, NROWS, BITS, FRAME_COUNT>
716{
717 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
718 let brightness_step = 1 << (8 - BITS);
719 f.debug_struct("DmaFrameBuffer")
720 .field("size", &core::mem::size_of_val(&self.frames))
721 .field("frame_count", &self.frames.len())
722 .field("frame_size", &core::mem::size_of_val(&self.frames[0]))
723 .field("brightness_step", &&brightness_step)
724 .finish_non_exhaustive()
725 }
726}
727
728#[cfg(feature = "defmt")]
729impl<
730 const ROWS: usize,
731 const COLS: usize,
732 const NROWS: usize,
733 const BITS: u8,
734 const FRAME_COUNT: usize,
735 > defmt::Format for DmaFrameBuffer<ROWS, COLS, NROWS, BITS, FRAME_COUNT>
736{
737 fn format(&self, f: defmt::Formatter) {
738 let brightness_step = 1 << (8 - BITS);
739 defmt::write!(
740 f,
741 "DmaFrameBuffer<{}, {}, {}, {}, {}>",
742 ROWS,
743 COLS,
744 NROWS,
745 BITS,
746 FRAME_COUNT
747 );
748 defmt::write!(f, " size: {}", core::mem::size_of_val(&self.frames));
749 defmt::write!(
750 f,
751 " frame_size: {}",
752 core::mem::size_of_val(&self.frames[0])
753 );
754 defmt::write!(f, " brightness_step: {}", brightness_step);
755 }
756}
757
758impl<
759 const ROWS: usize,
760 const COLS: usize,
761 const NROWS: usize,
762 const BITS: u8,
763 const FRAME_COUNT: usize,
764 > FrameBuffer<ROWS, COLS, NROWS, BITS, FRAME_COUNT>
765 for DmaFrameBuffer<ROWS, COLS, NROWS, BITS, FRAME_COUNT>
766{
767 fn get_word_size(&self) -> WordSize {
768 WordSize::Sixteen
769 }
770}
771
772impl<
773 const ROWS: usize,
774 const COLS: usize,
775 const NROWS: usize,
776 const BITS: u8,
777 const FRAME_COUNT: usize,
778 > FrameBuffer<ROWS, COLS, NROWS, BITS, FRAME_COUNT>
779 for &mut DmaFrameBuffer<ROWS, COLS, NROWS, BITS, FRAME_COUNT>
780{
781 fn get_word_size(&self) -> WordSize {
782 WordSize::Sixteen
783 }
784}
785
786#[cfg(test)]
787mod tests {
788 extern crate std;
789
790 use std::format;
791 use std::vec;
792
793 use super::*;
794 use crate::{FrameBuffer, WordSize};
795 use embedded_graphics::pixelcolor::RgbColor;
796 use embedded_graphics::prelude::*;
797 use embedded_graphics::primitives::{Circle, PrimitiveStyle, Rectangle};
798
799 const TEST_ROWS: usize = 32;
800 const TEST_COLS: usize = 64;
801 const TEST_NROWS: usize = TEST_ROWS / 2;
802 const TEST_BITS: u8 = 3;
803 const TEST_FRAME_COUNT: usize = (1 << TEST_BITS) - 1; type TestFrameBuffer =
806 DmaFrameBuffer<TEST_ROWS, TEST_COLS, TEST_NROWS, TEST_BITS, TEST_FRAME_COUNT>;
807
808 fn get_mapped_index(index: usize) -> usize {
810 map_index(index)
811 }
812
813 #[test]
814 fn test_entry_construction() {
815 let entry = Entry::new();
816 assert_eq!(entry.0, 0);
817 assert_eq!(entry.dummy2(), false);
818 assert_eq!(entry.blu2(), false);
819 assert_eq!(entry.grn2(), false);
820 assert_eq!(entry.red2(), false);
821 assert_eq!(entry.blu1(), false);
822 assert_eq!(entry.grn1(), false);
823 assert_eq!(entry.red1(), false);
824 assert_eq!(entry.output_enable(), false);
825 assert_eq!(entry.dummy1(), false);
826 assert_eq!(entry.dummy0(), false);
827 assert_eq!(entry.latch(), false);
828 assert_eq!(entry.addr(), 0);
829 }
830
831 #[test]
832 fn test_entry_setters() {
833 let mut entry = Entry::new();
834
835 entry.set_dummy2(true);
836 assert_eq!(entry.dummy2(), true);
837 assert_eq!(entry.0 & 0b1000000000000000, 0b1000000000000000);
838
839 entry.set_blu2(true);
840 assert_eq!(entry.blu2(), true);
841 assert_eq!(entry.0 & 0b0100000000000000, 0b0100000000000000);
842
843 entry.set_grn2(true);
844 assert_eq!(entry.grn2(), true);
845 assert_eq!(entry.0 & 0b0010000000000000, 0b0010000000000000);
846
847 entry.set_red2(true);
848 assert_eq!(entry.red2(), true);
849 assert_eq!(entry.0 & 0b0001000000000000, 0b0001000000000000);
850
851 entry.set_blu1(true);
852 assert_eq!(entry.blu1(), true);
853 assert_eq!(entry.0 & 0b0000100000000000, 0b0000100000000000);
854
855 entry.set_grn1(true);
856 assert_eq!(entry.grn1(), true);
857 assert_eq!(entry.0 & 0b0000010000000000, 0b0000010000000000);
858
859 entry.set_red1(true);
860 assert_eq!(entry.red1(), true);
861 assert_eq!(entry.0 & 0b0000001000000000, 0b0000001000000000);
862
863 entry.set_output_enable(true);
864 assert_eq!(entry.output_enable(), true);
865 assert_eq!(entry.0 & 0b0000000100000000, 0b0000000100000000);
866
867 entry.set_dummy1(true);
868 assert_eq!(entry.dummy1(), true);
869 assert_eq!(entry.0 & 0b0000000010000000, 0b0000000010000000);
870
871 entry.set_dummy0(true);
872 assert_eq!(entry.dummy0(), true);
873 assert_eq!(entry.0 & 0b0000000001000000, 0b0000000001000000);
874
875 entry.set_latch(true);
876 assert_eq!(entry.latch(), true);
877 assert_eq!(entry.0 & 0b0000000000100000, 0b0000000000100000);
878
879 entry.set_addr(0b11111);
880 assert_eq!(entry.addr(), 0b11111);
881 assert_eq!(entry.0 & 0b0000000000011111, 0b0000000000011111);
882 }
883
884 #[test]
885 fn test_entry_bit_isolation() {
886 let mut entry = Entry::new();
887
888 entry.set_addr(0b11111);
890 entry.set_latch(true);
891 assert_eq!(entry.addr(), 0b11111);
892 assert_eq!(entry.latch(), true);
893 assert_eq!(entry.output_enable(), false);
894 assert_eq!(entry.red1(), false);
895
896 entry.set_red1(true);
897 entry.set_grn2(true);
898 assert_eq!(entry.addr(), 0b11111);
899 assert_eq!(entry.latch(), true);
900 assert_eq!(entry.red1(), true);
901 assert_eq!(entry.grn2(), true);
902 assert_eq!(entry.blu1(), false);
903 assert_eq!(entry.red2(), false);
904 }
905
906 #[test]
907 fn test_entry_set_color0() {
908 let mut entry = Entry::new();
909
910 let bits = (u8::from(true) << 2) | (u8::from(false) << 1) | u8::from(true); entry.set_color0_bits(bits);
912 assert_eq!(entry.red1(), true);
913 assert_eq!(entry.grn1(), false);
914 assert_eq!(entry.blu1(), true);
915 assert_eq!(entry.0 & 0b0000101000000000, 0b0000101000000000); }
918
919 #[test]
920 fn test_entry_set_color1() {
921 let mut entry = Entry::new();
922
923 let bits = (u8::from(true) << 2) | (u8::from(true) << 1) | u8::from(false); entry.set_color1_bits(bits);
925 assert_eq!(entry.red2(), false);
926 assert_eq!(entry.grn2(), true);
927 assert_eq!(entry.blu2(), true);
928 assert_eq!(entry.0 & 0b0110000000000000, 0b0110000000000000); }
931
932 #[test]
933 fn test_entry_debug_formatting() {
934 let entry = Entry(0x1234);
935 let debug_str = format!("{:?}", entry);
936 assert_eq!(debug_str, "Entry(0x1234)");
937
938 let entry = Entry(0xabcd);
939 let debug_str = format!("{:?}", entry);
940 assert_eq!(debug_str, "Entry(0xabcd)");
941 }
942
943 #[test]
944 fn test_row_construction() {
945 let row: Row<TEST_COLS> = Row::new();
946 assert_eq!(row.data.len(), TEST_COLS);
947
948 for entry in &row.data {
950 assert_eq!(entry.0, 0);
951 }
952 }
953
954 #[test]
955 fn test_row_format() {
956 let mut row: Row<TEST_COLS> = Row::new();
957 let test_addr = 5;
958 let prev_addr = 4;
959
960 row.format(test_addr, prev_addr);
961
962 for (physical_i, entry) in row.data.iter().enumerate() {
964 let logical_i = get_mapped_index(physical_i);
965
966 match logical_i {
967 i if i == TEST_COLS - BLANKING_DELAY - 1 => {
968 assert_eq!(entry.output_enable(), false);
970 assert_eq!(entry.addr(), prev_addr as u16);
971 assert_eq!(entry.latch(), false);
972 }
973 i if i == TEST_COLS - 1 => {
974 assert_eq!(entry.latch(), true);
976 assert_eq!(entry.addr(), test_addr as u16);
977 assert_eq!(entry.output_enable(), false);
978 }
979 1 => {
980 assert_eq!(entry.output_enable(), true);
982 assert_eq!(entry.addr(), prev_addr as u16);
983 assert_eq!(entry.latch(), false);
984 }
985 _ => {
986 assert_eq!(entry.addr(), prev_addr as u16);
988 assert_eq!(entry.latch(), false);
989 if logical_i > 1 && logical_i < TEST_COLS - BLANKING_DELAY - 1 {
990 assert_eq!(entry.output_enable(), true);
991 }
992 }
993 }
994 }
995 }
996
997 #[test]
998 fn test_row_set_color0() {
999 let mut row: Row<TEST_COLS> = Row::new();
1000
1001 row.set_color0(0, true, false, true);
1002
1003 let mapped_col_0 = get_mapped_index(0);
1004 assert_eq!(row.data[mapped_col_0].red1(), true);
1005 assert_eq!(row.data[mapped_col_0].grn1(), false);
1006 assert_eq!(row.data[mapped_col_0].blu1(), true);
1007
1008 row.set_color0(1, false, true, false);
1010
1011 let mapped_col_1 = get_mapped_index(1);
1012 assert_eq!(row.data[mapped_col_1].red1(), false);
1013 assert_eq!(row.data[mapped_col_1].grn1(), true);
1014 assert_eq!(row.data[mapped_col_1].blu1(), false);
1015 }
1016
1017 #[test]
1018 fn test_row_set_color1() {
1019 let mut row: Row<TEST_COLS> = Row::new();
1020
1021 row.set_color1(0, true, true, false);
1022
1023 let mapped_col_0 = get_mapped_index(0);
1024 assert_eq!(row.data[mapped_col_0].red2(), true);
1025 assert_eq!(row.data[mapped_col_0].grn2(), true);
1026 assert_eq!(row.data[mapped_col_0].blu2(), false);
1027 }
1028
1029 #[test]
1030 fn test_row_default() {
1031 let row1: Row<TEST_COLS> = Row::new();
1032 let row2: Row<TEST_COLS> = Row::default();
1033
1034 assert_eq!(row1, row2);
1036 assert_eq!(row1.data.len(), row2.data.len());
1037
1038 for (entry1, entry2) in row1.data.iter().zip(row2.data.iter()) {
1040 assert_eq!(entry1.0, entry2.0);
1041 assert_eq!(entry1.0, 0);
1042 }
1043 }
1044
1045 #[test]
1046 fn test_frame_construction() {
1047 let frame: Frame<TEST_ROWS, TEST_COLS, TEST_NROWS> = Frame::new();
1048 assert_eq!(frame.rows.len(), TEST_NROWS);
1049 }
1050
1051 #[test]
1052 fn test_frame_format() {
1053 let mut frame: Frame<TEST_ROWS, TEST_COLS, TEST_NROWS> = Frame::new();
1054
1055 frame.format();
1056
1057 for addr in 0..TEST_NROWS {
1059 let prev_addr = if addr == 0 { TEST_NROWS - 1 } else { addr - 1 };
1060
1061 let row = &frame.rows[addr];
1063
1064 let last_pixel_idx = get_mapped_index(TEST_COLS - 1);
1066 assert_eq!(row.data[last_pixel_idx].addr(), addr as u16);
1067 assert_eq!(row.data[last_pixel_idx].latch(), true);
1068
1069 let first_pixel_idx = get_mapped_index(0);
1071 assert_eq!(row.data[first_pixel_idx].addr(), prev_addr as u16);
1072 assert_eq!(row.data[first_pixel_idx].latch(), false);
1073 }
1074 }
1075
1076 #[test]
1077 fn test_frame_set_pixel() {
1078 let mut frame: Frame<TEST_ROWS, TEST_COLS, TEST_NROWS> = Frame::new();
1079
1080 frame.set_pixel(5, 10, true, false, true);
1082
1083 let mapped_col_10 = get_mapped_index(10);
1084 assert_eq!(frame.rows[5].data[mapped_col_10].red1(), true);
1085 assert_eq!(frame.rows[5].data[mapped_col_10].grn1(), false);
1086 assert_eq!(frame.rows[5].data[mapped_col_10].blu1(), true);
1087
1088 frame.set_pixel(TEST_NROWS + 5, 15, false, true, false);
1090
1091 let mapped_col_15 = get_mapped_index(15);
1092 assert_eq!(frame.rows[5].data[mapped_col_15].red2(), false);
1093 assert_eq!(frame.rows[5].data[mapped_col_15].grn2(), true);
1094 assert_eq!(frame.rows[5].data[mapped_col_15].blu2(), false);
1095 }
1096
1097 #[test]
1098 fn test_frame_default() {
1099 let frame1: Frame<TEST_ROWS, TEST_COLS, TEST_NROWS> = Frame::new();
1100 let frame2: Frame<TEST_ROWS, TEST_COLS, TEST_NROWS> = Frame::default();
1101
1102 assert_eq!(frame1.rows.len(), frame2.rows.len());
1104
1105 for (row1, row2) in frame1.rows.iter().zip(frame2.rows.iter()) {
1107 assert_eq!(row1, row2);
1108
1109 for (entry1, entry2) in row1.data.iter().zip(row2.data.iter()) {
1111 assert_eq!(entry1.0, entry2.0);
1112 assert_eq!(entry1.0, 0);
1113 }
1114 }
1115 }
1116
1117 #[test]
1118 fn test_dma_framebuffer_construction() {
1119 let fb = TestFrameBuffer::new();
1120 assert_eq!(fb.frames.len(), TEST_FRAME_COUNT);
1121 assert_eq!(fb._align, 0);
1122 }
1123
1124 #[test]
1125 #[cfg(feature = "esp-hal-dma")]
1126 fn test_dma_framebuffer_dma_buffer_size() {
1127 let expected_size =
1128 core::mem::size_of::<[Frame<TEST_ROWS, TEST_COLS, TEST_NROWS>; TEST_FRAME_COUNT]>();
1129 assert_eq!(TestFrameBuffer::dma_buffer_size_bytes(), expected_size);
1130 }
1131
1132 #[test]
1133 fn test_dma_framebuffer_erase() {
1134 let fb = TestFrameBuffer::new();
1135
1136 for frame in &fb.frames {
1138 for addr in 0..TEST_NROWS {
1139 let prev_addr = if addr == 0 { TEST_NROWS - 1 } else { addr - 1 };
1140
1141 let row = &frame.rows[addr];
1143
1144 let last_pixel_idx = get_mapped_index(TEST_COLS - 1);
1146 assert_eq!(row.data[last_pixel_idx].addr(), addr as u16);
1147 assert_eq!(row.data[last_pixel_idx].latch(), true);
1148
1149 let first_pixel_idx = get_mapped_index(0);
1151 assert_eq!(row.data[first_pixel_idx].addr(), prev_addr as u16);
1152 assert_eq!(row.data[first_pixel_idx].latch(), false);
1153 }
1154 }
1155 }
1156
1157 #[test]
1158 fn test_dma_framebuffer_set_pixel_bounds() {
1159 let mut fb = TestFrameBuffer::new();
1160
1161 fb.set_pixel(Point::new(-1, 5), Color::RED);
1163 fb.set_pixel(Point::new(5, -1), Color::RED);
1164
1165 fb.set_pixel(Point::new(TEST_COLS as i32, 5), Color::RED);
1167 fb.set_pixel(Point::new(5, TEST_ROWS as i32), Color::RED);
1168 }
1169
1170 #[test]
1171 fn test_dma_framebuffer_set_pixel_internal() {
1172 let mut fb = TestFrameBuffer::new();
1173
1174 let red_color = Color::RED;
1175 fb.set_pixel_internal(10, 5, red_color);
1176
1177 for frame in &fb.frames {
1181 let mapped_col_10 = get_mapped_index(10);
1183 assert_eq!(frame.rows[5].data[mapped_col_10].red1(), true);
1184 assert_eq!(frame.rows[5].data[mapped_col_10].grn1(), false);
1185 assert_eq!(frame.rows[5].data[mapped_col_10].blu1(), false);
1186 }
1187 }
1188
1189 #[test]
1190 fn test_dma_framebuffer_brightness_modulation() {
1191 let mut fb = TestFrameBuffer::new();
1192
1193 let brightness_step = 1 << (8 - TEST_BITS); let test_brightness = brightness_step * 3; let color = Color::from(embedded_graphics::pixelcolor::Rgb888::new(
1197 test_brightness,
1198 0,
1199 0,
1200 ));
1201
1202 fb.set_pixel_internal(0, 0, color);
1203
1204 for (frame_idx, frame) in fb.frames.iter().enumerate() {
1207 let frame_threshold = (frame_idx as u8 + 1) * brightness_step;
1208 let should_be_active = test_brightness >= frame_threshold;
1209
1210 let mapped_col_0 = get_mapped_index(0);
1211 assert_eq!(frame.rows[0].data[mapped_col_0].red1(), should_be_active);
1212 }
1213 }
1214
1215 #[test]
1216 fn test_origin_dimensions() {
1217 let fb = TestFrameBuffer::new();
1218 let size = fb.size();
1219 assert_eq!(size.width, TEST_COLS as u32);
1220 assert_eq!(size.height, TEST_ROWS as u32);
1221
1222 let size = (&fb).size();
1224 assert_eq!(size.width, TEST_COLS as u32);
1225 assert_eq!(size.height, TEST_ROWS as u32);
1226
1227 let mut fb = TestFrameBuffer::new();
1229 let fb_ref = &mut fb;
1230 let size = fb_ref.size();
1231 assert_eq!(size.width, TEST_COLS as u32);
1232 assert_eq!(size.height, TEST_ROWS as u32);
1233 }
1234
1235 #[test]
1236 fn test_draw_target() {
1237 let mut fb = TestFrameBuffer::new();
1238
1239 let pixels = vec![
1240 embedded_graphics::Pixel(Point::new(0, 0), Color::RED),
1241 embedded_graphics::Pixel(Point::new(1, 1), Color::GREEN),
1242 embedded_graphics::Pixel(Point::new(2, 2), Color::BLUE),
1243 ];
1244
1245 let result = fb.draw_iter(pixels);
1246 assert!(result.is_ok());
1247
1248 let result = (&mut fb).draw_iter(vec![embedded_graphics::Pixel(
1250 Point::new(3, 3),
1251 Color::WHITE,
1252 )]);
1253 assert!(result.is_ok());
1254 }
1255
1256 #[test]
1257 fn test_draw_iter_pixel_verification() {
1258 let mut fb = TestFrameBuffer::new();
1259
1260 let pixels = vec![
1262 embedded_graphics::Pixel(Point::new(5, 2), Color::RED), embedded_graphics::Pixel(Point::new(10, 5), Color::GREEN), embedded_graphics::Pixel(Point::new(15, 8), Color::BLUE), embedded_graphics::Pixel(Point::new(20, 10), Color::WHITE), embedded_graphics::Pixel(Point::new(25, (TEST_NROWS + 3) as i32), Color::RED), embedded_graphics::Pixel(Point::new(30, (TEST_NROWS + 7) as i32), Color::GREEN), embedded_graphics::Pixel(Point::new(35, (TEST_NROWS + 12) as i32), Color::BLUE), embedded_graphics::Pixel(Point::new(40, 1), Color::BLACK), ];
1274
1275 let result = fb.draw_iter(pixels);
1276 assert!(result.is_ok());
1277
1278 let first_frame = &fb.frames[0];
1280 let brightness_step = 1 << (8 - TEST_BITS); let first_frame_threshold = brightness_step; let col_idx = get_mapped_index(5);
1286 assert_eq!(
1287 first_frame.rows[2].data[col_idx].red1(),
1288 Color::RED.r() >= first_frame_threshold
1289 );
1290 assert_eq!(
1291 first_frame.rows[2].data[col_idx].grn1(),
1292 Color::RED.g() >= first_frame_threshold
1293 );
1294 assert_eq!(
1295 first_frame.rows[2].data[col_idx].blu1(),
1296 Color::RED.b() >= first_frame_threshold
1297 );
1298
1299 let col_idx = get_mapped_index(10);
1301 assert_eq!(
1302 first_frame.rows[5].data[col_idx].red1(),
1303 Color::GREEN.r() >= first_frame_threshold
1304 );
1305 assert_eq!(
1306 first_frame.rows[5].data[col_idx].grn1(),
1307 Color::GREEN.g() >= first_frame_threshold
1308 );
1309 assert_eq!(
1310 first_frame.rows[5].data[col_idx].blu1(),
1311 Color::GREEN.b() >= first_frame_threshold
1312 );
1313
1314 let col_idx = get_mapped_index(15);
1316 assert_eq!(
1317 first_frame.rows[8].data[col_idx].red1(),
1318 Color::BLUE.r() >= first_frame_threshold
1319 );
1320 assert_eq!(
1321 first_frame.rows[8].data[col_idx].grn1(),
1322 Color::BLUE.g() >= first_frame_threshold
1323 );
1324 assert_eq!(
1325 first_frame.rows[8].data[col_idx].blu1(),
1326 Color::BLUE.b() >= first_frame_threshold
1327 );
1328
1329 let col_idx = get_mapped_index(20);
1331 assert_eq!(
1332 first_frame.rows[10].data[col_idx].red1(),
1333 Color::WHITE.r() >= first_frame_threshold
1334 );
1335 assert_eq!(
1336 first_frame.rows[10].data[col_idx].grn1(),
1337 Color::WHITE.g() >= first_frame_threshold
1338 );
1339 assert_eq!(
1340 first_frame.rows[10].data[col_idx].blu1(),
1341 Color::WHITE.b() >= first_frame_threshold
1342 );
1343
1344 let col_idx = get_mapped_index(25);
1347 assert_eq!(
1348 first_frame.rows[3].data[col_idx].red2(),
1349 Color::RED.r() >= first_frame_threshold
1350 );
1351 assert_eq!(
1352 first_frame.rows[3].data[col_idx].grn2(),
1353 Color::RED.g() >= first_frame_threshold
1354 );
1355 assert_eq!(
1356 first_frame.rows[3].data[col_idx].blu2(),
1357 Color::RED.b() >= first_frame_threshold
1358 );
1359
1360 let col_idx = get_mapped_index(30);
1362 assert_eq!(
1363 first_frame.rows[7].data[col_idx].red2(),
1364 Color::GREEN.r() >= first_frame_threshold
1365 );
1366 assert_eq!(
1367 first_frame.rows[7].data[col_idx].grn2(),
1368 Color::GREEN.g() >= first_frame_threshold
1369 );
1370 assert_eq!(
1371 first_frame.rows[7].data[col_idx].blu2(),
1372 Color::GREEN.b() >= first_frame_threshold
1373 );
1374
1375 let col_idx = get_mapped_index(35);
1377 assert_eq!(
1378 first_frame.rows[12].data[col_idx].red2(),
1379 Color::BLUE.r() >= first_frame_threshold
1380 );
1381 assert_eq!(
1382 first_frame.rows[12].data[col_idx].grn2(),
1383 Color::BLUE.g() >= first_frame_threshold
1384 );
1385 assert_eq!(
1386 first_frame.rows[12].data[col_idx].blu2(),
1387 Color::BLUE.b() >= first_frame_threshold
1388 );
1389
1390 let col_idx = get_mapped_index(40);
1392 assert_eq!(first_frame.rows[1].data[col_idx].red1(), false);
1393 assert_eq!(first_frame.rows[1].data[col_idx].grn1(), false);
1394 assert_eq!(first_frame.rows[1].data[col_idx].blu1(), false);
1395 }
1396
1397 #[test]
1398 fn test_embedded_graphics_integration() {
1399 let mut fb = TestFrameBuffer::new();
1400
1401 let result = Rectangle::new(Point::new(5, 5), Size::new(10, 8))
1403 .into_styled(PrimitiveStyle::with_fill(Color::RED))
1404 .draw(&mut fb);
1405 assert!(result.is_ok());
1406
1407 let result = Circle::new(Point::new(30, 15), 8)
1409 .into_styled(PrimitiveStyle::with_fill(Color::BLUE))
1410 .draw(&mut fb);
1411 assert!(result.is_ok());
1412 }
1413
1414 #[test]
1415 #[cfg(feature = "skip-black-pixels")]
1416 fn test_skip_black_pixels_enabled() {
1417 let mut fb = TestFrameBuffer::new();
1418
1419 fb.set_pixel_internal(10, 5, Color::RED);
1421
1422 let mapped_col_10 = get_mapped_index(10);
1424 assert_eq!(fb.frames[0].rows[5].data[mapped_col_10].red1(), true);
1425 assert_eq!(fb.frames[0].rows[5].data[mapped_col_10].grn1(), false);
1426 assert_eq!(fb.frames[0].rows[5].data[mapped_col_10].blu1(), false);
1427
1428 fb.set_pixel_internal(10, 5, Color::BLACK);
1430
1431 assert_eq!(fb.frames[0].rows[5].data[mapped_col_10].red1(), true);
1433 assert_eq!(fb.frames[0].rows[5].data[mapped_col_10].grn1(), false);
1434 assert_eq!(fb.frames[0].rows[5].data[mapped_col_10].blu1(), false);
1435 }
1436
1437 #[test]
1438 #[cfg(not(feature = "skip-black-pixels"))]
1439 fn test_skip_black_pixels_disabled() {
1440 let mut fb = TestFrameBuffer::new();
1441
1442 fb.set_pixel_internal(10, 5, Color::RED);
1444
1445 let mapped_col_10 = get_mapped_index(10);
1447 assert_eq!(fb.frames[0].rows[5].data[mapped_col_10].red1(), true);
1448 assert_eq!(fb.frames[0].rows[5].data[mapped_col_10].grn1(), false);
1449 assert_eq!(fb.frames[0].rows[5].data[mapped_col_10].blu1(), false);
1450
1451 fb.set_pixel_internal(10, 5, Color::BLACK);
1453
1454 assert_eq!(fb.frames[0].rows[5].data[mapped_col_10].red1(), false);
1456 assert_eq!(fb.frames[0].rows[5].data[mapped_col_10].grn1(), false);
1457 assert_eq!(fb.frames[0].rows[5].data[mapped_col_10].blu1(), false);
1458 }
1459
1460 #[test]
1461 fn test_bcm_frame_overwrite() {
1462 let mut fb = TestFrameBuffer::new();
1463
1464 fb.set_pixel_internal(10, 5, Color::WHITE);
1466
1467 let mapped_col_10 = get_mapped_index(10);
1468
1469 for frame in fb.frames.iter() {
1471 assert_eq!(frame.rows[5].data[mapped_col_10].red1(), true);
1473 assert_eq!(frame.rows[5].data[mapped_col_10].grn1(), true);
1474 assert_eq!(frame.rows[5].data[mapped_col_10].blu1(), true);
1475 }
1476
1477 let half_white = Color::from(embedded_graphics::pixelcolor::Rgb888::new(128, 128, 128));
1479 fb.set_pixel_internal(10, 5, half_white);
1480
1481 let brightness_step = 1 << (8 - TEST_BITS); for (frame_idx, frame) in fb.frames.iter().enumerate() {
1487 let frame_threshold = (frame_idx as u8 + 1) * brightness_step;
1488 let should_be_active = 128 >= frame_threshold;
1489
1490 assert_eq!(frame.rows[5].data[mapped_col_10].red1(), should_be_active);
1491 assert_eq!(frame.rows[5].data[mapped_col_10].grn1(), should_be_active);
1492 assert_eq!(frame.rows[5].data[mapped_col_10].blu1(), should_be_active);
1493 }
1494
1495 for frame_idx in 0..4 {
1498 assert_eq!(
1499 fb.frames[frame_idx].rows[5].data[mapped_col_10].red1(),
1500 true
1501 );
1502 }
1503 for frame_idx in 4..TEST_FRAME_COUNT {
1505 assert_eq!(
1506 fb.frames[frame_idx].rows[5].data[mapped_col_10].red1(),
1507 false
1508 );
1509 }
1510 }
1511
1512 #[test]
1513 fn test_read_buffer_implementation() {
1514 let fb = TestFrameBuffer::new();
1516 let expected_size = core::mem::size_of_val(&fb.frames);
1517
1518 unsafe {
1520 let (ptr, len) = <TestFrameBuffer as ReadBuffer>::read_buffer(&fb);
1521 assert!(!ptr.is_null());
1522 assert_eq!(len, expected_size);
1523 }
1524
1525 unsafe {
1527 let (ptr, len) = fb.read_buffer();
1528 assert!(!ptr.is_null());
1529 assert_eq!(len, expected_size);
1530 }
1531
1532 let fb = TestFrameBuffer::new();
1534 let fb_ref = &fb;
1535 unsafe {
1536 let (ptr, len) = fb_ref.read_buffer();
1537 assert!(!ptr.is_null());
1538 assert_eq!(len, core::mem::size_of_val(&fb.frames));
1539 }
1540
1541 let mut fb = TestFrameBuffer::new();
1543 let fb_ref = &mut fb;
1544 unsafe {
1545 let (ptr, len) = fb_ref.read_buffer();
1546 assert!(!ptr.is_null());
1547 assert_eq!(len, core::mem::size_of_val(&fb.frames));
1548 }
1549 }
1550
1551 #[test]
1552 fn test_read_buffer_owned_implementation() {
1553 fn test_owned_read_buffer(fb: TestFrameBuffer) -> (bool, usize) {
1556 unsafe {
1557 let (ptr, len) = fb.read_buffer();
1558 (!ptr.is_null(), len)
1559 }
1560 }
1561
1562 let fb = TestFrameBuffer::new();
1563 let expected_len = core::mem::size_of_val(&fb.frames);
1564
1565 let (ptr_valid, actual_len) = test_owned_read_buffer(fb);
1566 assert!(ptr_valid);
1567 assert_eq!(actual_len, expected_len);
1568 }
1569
1570 #[test]
1571 fn test_framebuffer_trait() {
1572 let fb = TestFrameBuffer::new();
1573 assert_eq!(fb.get_word_size(), WordSize::Sixteen);
1574
1575 let fb_ref = &fb;
1576 assert_eq!(fb_ref.get_word_size(), WordSize::Sixteen);
1577
1578 let mut fb = TestFrameBuffer::new();
1579 let fb_ref = &mut fb;
1580 assert_eq!(fb_ref.get_word_size(), WordSize::Sixteen);
1581 }
1582
1583 #[test]
1584 fn test_debug_formatting() {
1585 let fb = TestFrameBuffer::new();
1586 let debug_string = format!("{:?}", fb);
1587 assert!(debug_string.contains("DmaFrameBuffer"));
1588 assert!(debug_string.contains("frame_count"));
1589 assert!(debug_string.contains("frame_size"));
1590 assert!(debug_string.contains("brightness_step"));
1591 }
1592
1593 #[test]
1594 fn test_default_implementation() {
1595 let fb1 = TestFrameBuffer::new();
1596 let fb2 = TestFrameBuffer::default();
1597
1598 assert_eq!(fb1.frames.len(), fb2.frames.len());
1600 assert_eq!(fb1._align, fb2._align);
1601 }
1602
1603 #[test]
1604 fn test_memory_alignment() {
1605 let fb = TestFrameBuffer::new();
1606 let ptr = &fb as *const _ as usize;
1607
1608 assert_eq!(ptr % 8, 0);
1610 }
1611
1612 #[test]
1613 fn test_color_values() {
1614 let mut fb = TestFrameBuffer::new();
1615
1616 let colors = [
1618 (Color::RED, (255, 0, 0)),
1619 (Color::GREEN, (0, 255, 0)),
1620 (Color::BLUE, (0, 0, 255)),
1621 (Color::WHITE, (255, 255, 255)),
1622 (Color::BLACK, (0, 0, 0)),
1623 ];
1624
1625 for (i, (color, (r, g, b))) in colors.iter().enumerate() {
1626 fb.set_pixel(Point::new(i as i32, 0), *color);
1627 assert_eq!(color.r(), *r);
1628 assert_eq!(color.g(), *g);
1629 assert_eq!(color.b(), *b);
1630 }
1631 }
1632
1633 #[test]
1634 fn test_blanking_delay() {
1635 let mut row: Row<TEST_COLS> = Row::new();
1636 let test_addr = 5;
1637 let prev_addr = 4;
1638
1639 row.format(test_addr, prev_addr);
1640
1641 let blanking_pixel_idx = get_mapped_index(TEST_COLS - BLANKING_DELAY - 1);
1643 assert_eq!(row.data[blanking_pixel_idx].output_enable(), false);
1644
1645 let before_blanking_idx = get_mapped_index(TEST_COLS - BLANKING_DELAY - 2);
1647 assert_eq!(row.data[before_blanking_idx].output_enable(), true);
1648 }
1649
1650 #[test]
1651 fn test_esp32_mapping() {
1652 #[cfg(feature = "esp32-ordering")]
1654 {
1655 assert_eq!(map_index(0), 1);
1656 assert_eq!(map_index(1), 0);
1657 assert_eq!(map_index(2), 3);
1658 assert_eq!(map_index(3), 2);
1659 assert_eq!(map_index(4), 5);
1660 assert_eq!(map_index(5), 4);
1661 }
1662 #[cfg(not(feature = "esp32-ordering"))]
1663 {
1664 assert_eq!(map_index(0), 0);
1665 assert_eq!(map_index(1), 1);
1666 assert_eq!(map_index(2), 2);
1667 assert_eq!(map_index(3), 3);
1668 }
1669 }
1670
1671 #[test]
1672 fn test_bits_assertion() {
1673 assert!(TEST_BITS <= 8);
1676 }
1677
1678 #[test]
1679 fn test_fast_clear_method() {
1680 let mut fb = TestFrameBuffer::new();
1681
1682 fb.set_pixel_internal(10, 5, Color::RED);
1684 fb.set_pixel_internal(20, 10, Color::GREEN);
1685
1686 let mapped_col_10 = get_mapped_index(10);
1688 assert_eq!(fb.frames[0].rows[5].data[mapped_col_10].red1(), true);
1689
1690 fb.erase();
1692
1693 assert_eq!(fb.frames[0].rows[5].data[mapped_col_10].red1(), false);
1695 assert_eq!(fb.frames[0].rows[5].data[mapped_col_10].grn1(), false);
1696 assert_eq!(fb.frames[0].rows[5].data[mapped_col_10].blu1(), false);
1697
1698 let last_col = get_mapped_index(TEST_COLS - 1);
1700 assert_eq!(fb.frames[0].rows[5].data[last_col].latch(), true);
1701 }
1702
1703 const CHAR_W: i32 = 6;
1707 const CHAR_H: i32 = 10;
1708
1709 fn verify_glyph_at(fb: &mut TestFrameBuffer, origin: Point) {
1711 use embedded_graphics::mock_display::MockDisplay;
1712 use embedded_graphics::mono_font::ascii::FONT_6X10;
1713 use embedded_graphics::mono_font::MonoTextStyle;
1714 use embedded_graphics::text::{Baseline, Text};
1715
1716 let style = MonoTextStyle::new(&FONT_6X10, Color::WHITE);
1718 Text::with_baseline("A", origin, style, Baseline::Top)
1719 .draw(fb)
1720 .unwrap();
1721
1722 let mut reference: MockDisplay<Color> = MockDisplay::new();
1724 Text::with_baseline("A", Point::zero(), style, Baseline::Top)
1725 .draw(&mut reference)
1726 .unwrap();
1727
1728 for dy in 0..CHAR_H {
1729 for dx in 0..CHAR_W {
1730 let expected_on = reference
1731 .get_pixel(Point::new(dx, dy))
1732 .unwrap_or(Color::BLACK)
1733 != Color::BLACK;
1734
1735 let gx = (origin.x + dx) as usize;
1736 let gy = (origin.y + dy) as usize;
1737
1738 let frame0 = &fb.frames[0];
1745 let e = if gy < TEST_NROWS {
1746 &frame0.rows[gy].data[get_mapped_index(gx)]
1747 } else {
1748 &frame0.rows[gy - TEST_NROWS].data[get_mapped_index(gx)]
1749 };
1750
1751 let (r, g, b) = if gy >= TEST_NROWS {
1752 (e.red2(), e.grn2(), e.blu2())
1753 } else {
1754 (e.red1(), e.grn1(), e.blu1())
1755 };
1756
1757 if expected_on {
1758 assert!(r && g && b,);
1759 } else {
1760 assert!(!r && !g && !b);
1761 }
1762 }
1763 }
1764 }
1765
1766 #[test]
1767 fn test_draw_char_corners() {
1768 let upper_left = Point::new(0, 0);
1769 let lower_right = Point::new(TEST_COLS as i32 - CHAR_W, TEST_ROWS as i32 - CHAR_H);
1770
1771 let mut fb = TestFrameBuffer::new();
1772
1773 verify_glyph_at(&mut fb, upper_left);
1774 verify_glyph_at(&mut fb, lower_right);
1775 }
1776
1777 #[test]
1778 fn test_framebuffer_operations_trait_erase() {
1779 let mut fb = TestFrameBuffer::new();
1780
1781 fb.set_pixel_internal(10, 5, Color::RED);
1783 fb.set_pixel_internal(20, 10, Color::GREEN);
1784
1785 <TestFrameBuffer as FrameBufferOperations<
1787 TEST_ROWS,
1788 TEST_COLS,
1789 TEST_NROWS,
1790 TEST_BITS,
1791 TEST_FRAME_COUNT,
1792 >>::erase(&mut fb);
1793
1794 let mc10 = get_mapped_index(10);
1796 let mc20 = get_mapped_index(20);
1797 assert_eq!(fb.frames[0].rows[5].data[mc10].red1(), false);
1798 assert_eq!(fb.frames[0].rows[10].data[mc20].grn1(), false);
1799
1800 let last_col = get_mapped_index(TEST_COLS - 1);
1802 assert!(fb.frames[0].rows[0].data[last_col].latch());
1803 }
1804
1805 #[test]
1806 fn test_framebuffer_operations_trait_set_pixel() {
1807 let mut fb = TestFrameBuffer::new();
1808
1809 <TestFrameBuffer as FrameBufferOperations<
1811 TEST_ROWS,
1812 TEST_COLS,
1813 TEST_NROWS,
1814 TEST_BITS,
1815 TEST_FRAME_COUNT,
1816 >>::set_pixel(&mut fb, Point::new(8, 3), Color::BLUE);
1817
1818 let idx = get_mapped_index(8);
1819 assert_eq!(fb.frames[0].rows[3].data[idx].blu1(), true);
1820 assert_eq!(fb.frames[0].rows[3].data[idx].red1(), false);
1821 assert_eq!(fb.frames[0].rows[3].data[idx].grn1(), false);
1822 }
1823}