@@ -43,8 +43,9 @@ use usb_device::{class_prelude::*, prelude::*};
43
43
use usbd_serial:: { SerialPort , USB_CLASS_CDC } ;
44
44
45
45
// Used to demonstrate writing formatted strings
46
- use core:: fmt:: { Debug , Write } ;
47
- use heapless:: String ;
46
+ use core:: fmt:: Debug ;
47
+ //use core::fmt::Write;
48
+ //use heapless::String;
48
49
49
50
use lotus_inputmodules:: control:: * ;
50
51
use lotus_inputmodules:: graphics:: * ;
@@ -66,6 +67,12 @@ type B1ST7306 = ST7306<
66
67
200 ,
67
68
> ;
68
69
70
+ const DEBUG : bool = false ;
71
+ const SCRNS_DELTA : i32 = 10 ;
72
+ const WIDTH : i32 = 300 ;
73
+ const HEIGHT : i32 = 400 ;
74
+ const SIZE : Size = Size :: new ( WIDTH as u32 , HEIGHT as u32 ) ;
75
+
69
76
#[ entry]
70
77
fn main ( ) -> ! {
71
78
let mut pac = pac:: Peripherals :: take ( ) . unwrap ( ) ;
@@ -128,7 +135,6 @@ fn main() -> ! {
128
135
let spi = bsp:: hal:: Spi :: < _ , _ , 8 > :: new ( pac. SPI0 ) ;
129
136
// Display control pins
130
137
let dc = pins. dc . into_push_pull_output ( ) ;
131
- //let mut lcd_led = pins.backlight.into_push_pull_output();
132
138
let mut cs = pins. cs . into_push_pull_output ( ) ;
133
139
cs. set_low ( ) . unwrap ( ) ;
134
140
let rst = pins. rstb . into_push_pull_output ( ) ;
@@ -157,68 +163,109 @@ fn main() -> ! {
157
163
hpm : HpmFps :: ThirtyTwo ,
158
164
lpm : LpmFps :: One ,
159
165
} ,
160
- 300 ,
161
- 400 ,
166
+ WIDTH as u16 ,
167
+ HEIGHT as u16 ,
162
168
COL_START ,
163
169
ROW_START ,
164
170
) ;
165
171
disp. init ( & mut delay) . unwrap ( ) ;
166
172
173
+ // Clear display, might have garbage in display memory
167
174
// TODO: Seems broken
168
175
//disp.clear(Rgb565::WHITE).unwrap();
169
- Rectangle :: new ( Point :: new ( 0 , 0 ) , Size :: new ( 300 , 400 ) )
176
+ Rectangle :: new ( Point :: new ( 0 , 0 ) , SIZE )
170
177
. into_styled ( PrimitiveStyle :: with_fill ( Rgb565 :: WHITE ) )
171
178
. draw ( & mut disp)
172
179
. unwrap ( ) ;
173
180
174
- let logo_rect = draw_logo ( & mut disp) . unwrap ( ) ;
175
- Rectangle :: new ( Point :: new ( 10 , 10 ) , Size :: new ( 10 , 10 ) )
176
- . into_styled ( PrimitiveStyle :: with_fill ( Rgb565 :: BLACK ) )
177
- . draw ( & mut disp)
178
- . unwrap ( ) ;
179
- Rectangle :: new ( Point :: new ( 20 , 20 ) , Size :: new ( 10 , 10 ) )
180
- . into_styled ( PrimitiveStyle :: with_fill ( Rgb565 :: BLACK ) )
181
- . draw ( & mut disp)
182
- . unwrap ( ) ;
183
- Rectangle :: new ( Point :: new ( 30 , 30 ) , Size :: new ( 10 , 10 ) )
184
- . into_styled ( PrimitiveStyle :: with_fill ( Rgb565 :: BLACK ) )
185
- . draw ( & mut disp)
181
+ let logo_rect = draw_logo ( & mut disp, Point :: new ( LOGO_OFFSET_X , LOGO_OFFSET_Y ) ) . unwrap ( ) ;
182
+ if DEBUG {
183
+ Rectangle :: new ( Point :: new ( 10 , 10 ) , Size :: new ( 10 , 10 ) )
184
+ . into_styled ( PrimitiveStyle :: with_fill ( Rgb565 :: BLACK ) )
185
+ . draw ( & mut disp)
186
+ . unwrap ( ) ;
187
+ Rectangle :: new ( Point :: new ( 20 , 20 ) , Size :: new ( 10 , 10 ) )
188
+ . into_styled ( PrimitiveStyle :: with_fill ( Rgb565 :: BLACK ) )
189
+ . draw ( & mut disp)
190
+ . unwrap ( ) ;
191
+ Rectangle :: new ( Point :: new ( 30 , 30 ) , Size :: new ( 10 , 10 ) )
192
+ . into_styled ( PrimitiveStyle :: with_fill ( Rgb565 :: BLACK ) )
193
+ . draw ( & mut disp)
194
+ . unwrap ( ) ;
195
+ Rectangle :: new ( Point :: new ( 40 , 40 ) , Size :: new ( 10 , 10 ) )
196
+ . into_styled ( PrimitiveStyle :: with_fill ( Rgb565 :: BLACK ) )
197
+ . draw ( & mut disp)
198
+ . unwrap ( ) ;
199
+ Rectangle :: new ( Point :: new ( 50 , 50 ) , Size :: new ( 10 , 10 ) )
200
+ . into_styled ( PrimitiveStyle :: with_fill ( Rgb565 :: BLACK ) )
201
+ . draw ( & mut disp)
202
+ . unwrap ( ) ;
203
+ draw_text (
204
+ & mut disp,
205
+ "Framework" ,
206
+ Point :: new ( LOGO_OFFSET_X , LOGO_OFFSET_Y + logo_rect. size . height as i32 ) ,
207
+ )
186
208
. unwrap ( ) ;
187
- Rectangle :: new ( Point :: new ( 40 , 40 ) , Size :: new ( 10 , 10 ) )
188
- . into_styled ( PrimitiveStyle :: with_fill ( Rgb565 :: BLACK ) )
189
- . draw ( & mut disp)
190
- . unwrap ( ) ;
191
- Rectangle :: new ( Point :: new ( 50 , 50 ) , Size :: new ( 10 , 10 ) )
192
- . into_styled ( PrimitiveStyle :: with_fill ( Rgb565 :: BLACK ) )
193
- . draw ( & mut disp)
194
- . unwrap ( ) ;
195
- draw_text (
196
- & mut disp,
197
- "Framework" ,
198
- Point :: new ( LOGO_OFFSET_X , LOGO_OFFSET_Y + logo_rect. size . height as i32 ) ,
199
- )
200
- . unwrap ( ) ;
209
+ }
210
+ disp. flush ( ) . unwrap ( ) ;
201
211
202
212
let sleep = pins. sleep . into_pull_down_input ( ) ;
203
213
204
214
let mut state = B1DIsplayState {
205
215
sleeping : SimpleSleepState :: Awake ,
206
216
screen_inverted : false ,
207
217
screen_on : true ,
218
+ screensaver : Some ( ScreenSaverState :: default ( ) ) ,
208
219
} ;
209
220
210
221
let timer = Timer :: new ( pac. TIMER , & mut pac. RESETS ) ;
211
222
let mut prev_timer = timer. get_counter ( ) . ticks ( ) ;
212
223
224
+ let mut logo_pos = Point :: new ( LOGO_OFFSET_X , LOGO_OFFSET_Y ) ;
225
+
213
226
loop {
214
227
// Go to sleep if the host is sleeping
215
228
let host_sleeping = sleep. is_low ( ) . unwrap ( ) ;
216
229
handle_sleep ( host_sleeping, & mut state, & mut delay, & mut disp) ;
217
230
218
231
// Handle period display updates. Don't do it too often
219
- if timer. get_counter ( ) . ticks ( ) > prev_timer + 20_000 {
220
- // TODO: Update display
232
+ if timer. get_counter ( ) . ticks ( ) > prev_timer + 500_000 {
221
233
prev_timer = timer. get_counter ( ) . ticks ( ) ;
234
+
235
+ if let Some ( ref mut screensaver) = state. screensaver {
236
+ logo_pos = {
237
+ let ( x, y) = ( logo_pos. x , logo_pos. y ) ;
238
+ let w = logo_rect. size . width as i32 ;
239
+ let h = logo_rect. size . height as i32 ;
240
+
241
+ // Bounce off the walls
242
+ if x <= 0 || x + w >= WIDTH {
243
+ screensaver. rightwards *= -1 ;
244
+ }
245
+ if y <= 0 || y + h >= HEIGHT {
246
+ screensaver. downwards *= -1 ;
247
+ }
248
+
249
+ Point :: new (
250
+ x + screensaver. rightwards * SCRNS_DELTA ,
251
+ y + screensaver. downwards * SCRNS_DELTA ,
252
+ )
253
+ } ;
254
+ // Draw a border around the new logo, to clear previously drawn adjacent logos
255
+ let style = PrimitiveStyleBuilder :: new ( )
256
+ . stroke_color ( Rgb565 :: WHITE )
257
+ . stroke_width ( 2 * SCRNS_DELTA as u32 )
258
+ . build ( ) ;
259
+ Rectangle :: new (
260
+ logo_pos - Point :: new ( SCRNS_DELTA , SCRNS_DELTA ) ,
261
+ logo_rect. size + Size :: new ( 2 * SCRNS_DELTA as u32 , 2 * SCRNS_DELTA as u32 ) ,
262
+ )
263
+ . into_styled ( style)
264
+ . draw ( & mut disp)
265
+ . unwrap ( ) ;
266
+ draw_logo ( & mut disp, logo_pos) . unwrap ( ) ;
267
+ disp. flush ( ) . unwrap ( ) ;
268
+ }
222
269
}
223
270
224
271
// Check for new data
@@ -253,14 +300,14 @@ fn main() -> ! {
253
300
} ;
254
301
// Must write AFTER writing response, otherwise the
255
302
// client interprets this debug message as the response
256
- let mut text: String < 64 > = String :: new ( ) ;
257
- write ! (
258
- & mut text,
259
- "Handled command {}:{}:{}:{}\r \n " ,
260
- buf[ 0 ] , buf[ 1 ] , buf[ 2 ] , buf[ 3 ]
261
- )
262
- . unwrap ( ) ;
263
- let _ = serial. write ( text. as_bytes ( ) ) ;
303
+ // let mut text: String<64> = String::new();
304
+ // write!(
305
+ // &mut text,
306
+ // "Handled command {}:{}:{}:{}\r\n",
307
+ // buf[0], buf[1], buf[2], buf[3]
308
+ // )
309
+ // .unwrap();
310
+ // let _ = serial.write(text.as_bytes());
264
311
}
265
312
_ => { }
266
313
}
@@ -307,6 +354,10 @@ fn handle_sleep<SPI, DC, CS, RST, const COLS: usize, const ROWS: usize>(
307
354
// Sleep-in has to go into HPM first, so we'll be in HPM after wake-up as well
308
355
disp. switch_mode ( delay, PowerMode :: Lpm ) . unwrap ( ) ;
309
356
357
+ // Turn screensaver on when resuming from sleep
358
+ // TODO Subject to change, but currently I want to avoid burn-in by default
359
+ state. screensaver = Some ( ScreenSaverState :: default ( ) ) ;
360
+
310
361
// TODO: Power display controller back on
311
362
}
312
363
}
0 commit comments