3
3
4
4
extern crate alloc;
5
5
use alloc:: boxed:: Box ;
6
+ use embedded_graphics_framebuf:: backends:: FrameBufferBackend ;
6
7
8
+ use bevy_ecs:: prelude:: * ;
7
9
use core:: fmt:: Write ;
8
- use embedded_hal:: delay:: DelayNs ;
9
10
use embedded_graphics:: {
10
- mono_font:: { ascii:: FONT_8X13 , MonoTextStyle } ,
11
+ Drawable ,
12
+ mono_font:: { MonoTextStyle , ascii:: FONT_8X13 } ,
11
13
pixelcolor:: Rgb565 ,
12
14
prelude:: * ,
13
15
primitives:: { PrimitiveStyle , Rectangle } ,
14
16
text:: Text ,
15
- Drawable ,
16
17
} ;
17
18
use embedded_graphics_framebuf:: FrameBuf ;
19
+ use embedded_hal:: delay:: DelayNs ;
20
+ use embedded_hal_bus:: spi:: ExclusiveDevice ;
18
21
use esp_hal:: delay:: Delay ;
22
+ use esp_hal:: dma:: { DmaRxBuf , DmaTxBuf } ;
23
+ use esp_hal:: dma_buffers;
19
24
use esp_hal:: {
20
- gpio:: { Level , Output , OutputConfig , DriveMode } ,
21
- rng:: Rng ,
22
- spi:: master:: { Spi , SpiDmaBus } ,
23
25
Blocking ,
26
+ gpio:: { DriveMode , Level , Output , OutputConfig } ,
24
27
main,
28
+ rng:: Rng ,
29
+ spi:: master:: { Spi , SpiDmaBus } ,
25
30
time:: Rate ,
26
31
} ;
27
- use esp_hal:: dma:: { DmaRxBuf , DmaTxBuf } ;
28
- use esp_hal:: dma_buffers;
29
- use embedded_hal_bus:: spi:: ExclusiveDevice ;
30
32
use esp_println:: { logger:: init_logger_from_env, println} ;
31
33
use log:: info;
32
- use mipidsi:: { interface:: SpiInterface , options:: { ColorInversion , Orientation , ColorOrder } } ;
33
- use mipidsi:: { models:: ILI9486Rgb565 , Builder } ;
34
- use bevy_ecs:: prelude:: * ; // includes NonSend and NonSendMut
34
+ use mipidsi:: { Builder , models:: ILI9486Rgb565 } ;
35
+ use mipidsi:: {
36
+ interface:: SpiInterface ,
37
+ options:: { ColorInversion , ColorOrder , Orientation } ,
38
+ } ; // includes NonSend and NonSendMut
35
39
36
40
#[ panic_handler]
37
41
fn panic ( _info : & core:: panic:: PanicInfo ) -> ! {
38
42
println ! ( "Panic: {}" , _info) ;
39
43
loop { }
40
44
}
41
45
46
+ /// A wrapper around a boxed array that implements FrameBufferBackend.
47
+ /// This allows the framebuffer to be allocated on the heap.
48
+ pub struct HeapBuffer < C : PixelColor , const N : usize > ( Box < [ C ; N ] > ) ;
49
+
50
+ impl < C : PixelColor , const N : usize > HeapBuffer < C , N > {
51
+ pub fn new ( data : Box < [ C ; N ] > ) -> Self {
52
+ Self ( data)
53
+ }
54
+ }
55
+
56
+ impl < C : PixelColor , const N : usize > core:: ops:: Deref for HeapBuffer < C , N > {
57
+ type Target = [ C ; N ] ;
58
+ fn deref ( & self ) -> & Self :: Target {
59
+ & * self . 0
60
+ }
61
+ }
62
+
63
+ impl < C : PixelColor , const N : usize > core:: ops:: DerefMut for HeapBuffer < C , N > {
64
+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
65
+ & mut * self . 0
66
+ }
67
+ }
68
+
69
+ impl < C : PixelColor , const N : usize > FrameBufferBackend for HeapBuffer < C , N > {
70
+ type Color = C ;
71
+ fn set ( & mut self , index : usize , color : Self :: Color ) {
72
+ self . 0 [ index] = color;
73
+ }
74
+ fn get ( & self , index : usize ) -> Self :: Color {
75
+ self . 0 [ index]
76
+ }
77
+ fn nr_elements ( & self ) -> usize {
78
+ N
79
+ }
80
+ }
81
+
42
82
// --- Type Alias for the Concrete Display ---
43
83
// Use the DMA-enabled SPI bus type.
44
84
type MyDisplay = mipidsi:: Display <
45
85
SpiInterface <
46
86
' static ,
47
87
ExclusiveDevice < SpiDmaBus < ' static , Blocking > , Output < ' static > , Delay > ,
48
- Output < ' static >
88
+ Output < ' static > ,
49
89
> ,
50
90
ILI9486Rgb565 ,
51
- Output < ' static >
91
+ Output < ' static > ,
52
92
> ;
53
93
54
94
// --- LCD Resolution and FrameBuffer Type Aliases ---
@@ -57,7 +97,7 @@ const LCD_V_RES: usize = 240;
57
97
const LCD_BUFFER_SIZE : usize = LCD_H_RES * LCD_V_RES ;
58
98
59
99
// We want our pixels stored as Rgb565.
60
- type FbBuffer = [ Rgb565 ; LCD_BUFFER_SIZE ] ;
100
+ type FbBuffer = HeapBuffer < Rgb565 , LCD_BUFFER_SIZE > ;
61
101
// Define a type alias for the complete FrameBuf.
62
102
type MyFrameBuf = FrameBuf < Rgb565 , FbBuffer > ;
63
103
@@ -68,9 +108,10 @@ struct FrameBufferResource {
68
108
69
109
impl FrameBufferResource {
70
110
fn new ( ) -> Self {
71
- // Allocate the framebuffer data as an owned array of Rgb565.
72
- let fb_data: FbBuffer = * Box :: new ( [ Rgb565 :: BLACK ; LCD_BUFFER_SIZE ] ) ;
73
- let frame_buf = MyFrameBuf :: new ( fb_data, LCD_H_RES , LCD_V_RES ) ;
111
+ // Allocate the framebuffer data on the heap.
112
+ let fb_data: Box < [ Rgb565 ; LCD_BUFFER_SIZE ] > = Box :: new ( [ Rgb565 :: BLACK ; LCD_BUFFER_SIZE ] ) ;
113
+ let heap_buffer = HeapBuffer :: new ( fb_data) ;
114
+ let frame_buf = MyFrameBuf :: new ( heap_buffer, LCD_H_RES , LCD_V_RES ) ;
74
115
Self { frame_buf }
75
116
}
76
117
}
@@ -100,7 +141,9 @@ fn update_game_of_life(grid: &mut [[u8; GRID_WIDTH]; GRID_HEIGHT]) {
100
141
let mut alive_neighbors = 0 ;
101
142
for i in 0 ..3 {
102
143
for j in 0 ..3 {
103
- if i == 1 && j == 1 { continue ; }
144
+ if i == 1 && j == 1 {
145
+ continue ;
146
+ }
104
147
let nx = ( x + i + GRID_WIDTH - 1 ) % GRID_WIDTH ;
105
148
let ny = ( y + j + GRID_HEIGHT - 1 ) % GRID_HEIGHT ;
106
149
if grid[ ny] [ nx] > 0 {
@@ -128,7 +171,7 @@ fn update_game_of_life(grid: &mut [[u8; GRID_WIDTH]; GRID_HEIGHT]) {
128
171
* grid = new_grid;
129
172
}
130
173
131
- /// Maps cell age (1..=max_age) to a color. Newborn cells are dark blue and older cells become brighter (toward white).
174
+ /// Maps cell age (1... =max_age) to a color. Newborn cells are dark blue and older cells become brighter (toward white).
132
175
fn age_to_color ( age : u8 ) -> Rgb565 {
133
176
if age == 0 {
134
177
Rgb565 :: BLACK
@@ -315,7 +358,11 @@ fn main() -> ! {
315
358
display_delay. delay_ns ( 500_000u32 ) ;
316
359
317
360
// Reset pin: OpenDrain required for ESP32-S3-BOX! Tricky setting.
318
- let reset = Output :: new ( peripherals. GPIO48 , Level :: High , OutputConfig :: default ( ) . with_drive_mode ( DriveMode :: OpenDrain ) ) ;
361
+ let reset = Output :: new (
362
+ peripherals. GPIO48 ,
363
+ Level :: High ,
364
+ OutputConfig :: default ( ) . with_drive_mode ( DriveMode :: OpenDrain ) ,
365
+ ) ;
319
366
// Initialize the display using mipidsi's builder.
320
367
let mut display: MyDisplay = Builder :: new ( ILI9486Rgb565 , di)
321
368
. reset_pin ( reset)
0 commit comments