+#![no_std]
+#![no_main]
+
+// Panic provider crate
+use panic_persist;
+use cortex_m;
+
+// Used to set the program entry point
+use cortex_m_rt::entry;
+
+// Provides definitions for our development board
+use nrf52840_hal::{
+ prelude::*,
+ target::{Peripherals, CorePeripherals},
+ Timer,
+ Rng,
+ Spim,
+ spim::{
+ Pins as SpimPins,
+ Frequency as SpimFrequency,
+ MODE_0,
+ },
+ gpio::{
+ p0::Parts as P0Parts,
+ p1::Parts as P1Parts,
+ Level,
+ },
+ Clocks,
+};
+
+use rtt_target::{
+ rprint, rprintln,
+ rtt_init_print,
+};
+
+use embedded_graphics::{
+ fonts::{Font8x16, Text},
+ pixelcolor::Rgb565,
+ prelude::*,
+ style::{TextStyle, TextStyleBuilder},
+};
+
+mod buffer;
+
+use ili9341::{Ili9341, Orientation};
+
+const TEXT_SAMPLE: &[&str] = &[
+ "for x in 0..10 {",
+ " for y in 0..10 {",
+ " let rand: u16 = rng.random_u16();",
+ " buffy.iter_mut().for_each(|px| {",
+ " *px = swap(rand)",
+ " });",
+ " lcd.draw_raw(",
+ " 32 * x,",
+ " 24 * y,",
+ " (32 * (x + 1)) - 1,",
+ " (24 * (y + 1)) - 1,",
+ " &buffy,",
+ " ).unwrap();",
+ " }",
+ "}",
+];
+
+const TEXT_SAMPLE2: &[&[(i32, Rgb565, &str)]] = &[
+ // "for x in 0..10 {",
+ &[(0, Rgb565::RED, "for "), (4, Rgb565::WHITE, "x "), (6, Rgb565::RED, "in "), (9, Rgb565::MAGENTA, "0"), (10, Rgb565::RED, ".."), (12, Rgb565::MAGENTA, "10"), (14, Rgb565::WHITE, " {")],
+ // " for y in 0..10 {",
+ &[(2, Rgb565::RED, "for "), (6, Rgb565::WHITE, "y "), (8, Rgb565::RED, "in "), (11, Rgb565::MAGENTA, "0"), (12, Rgb565::RED, ".."), (14, Rgb565::MAGENTA, "10"), (16, Rgb565::WHITE, " {")],
+ // " let rand: u16 = rng.random_u16();",
+ &[(4, Rgb565::CYAN, "let "), (8, Rgb565::WHITE, "rand: "), (14, Rgb565::CYAN, "u16 "), (18, Rgb565::RED, "= "), (20, Rgb565::WHITE, "rng."), (24, Rgb565::CYAN, "random_u16"), (34, Rgb565::WHITE, "();")],
+ // " buffy.iter_mut().for_each(|px| {",
+ &[(4, Rgb565::WHITE, "buffy."), (10, Rgb565::CYAN, "iter_mut"), (18, Rgb565::WHITE, "()."), (21, Rgb565::CYAN, "for_each"), (29, Rgb565::WHITE, "(|"), (31, Rgb565::YELLOW, "px"), (33, Rgb565::WHITE, "| {")],
+ // " *px = swap(rand)",
+ &[(6, Rgb565::RED, "*"), (7, Rgb565::WHITE, "px "), (10, Rgb565::RED, "= "), (12, Rgb565::CYAN, "swap"), (16, Rgb565::WHITE, "(rand)")],
+ // " });",
+ &[(4, Rgb565::WHITE, "});")],
+ // " lcd.draw_raw(",
+ &[(4, Rgb565::WHITE, "lcd."), (8, Rgb565::CYAN, "draw_raw"), (16, Rgb565::WHITE, "(")],
+ // " 32 * x,",
+ &[(6, Rgb565::MAGENTA, "32 "), (9, Rgb565::RED, "* "), (11, Rgb565::WHITE, "x,")],
+ // " 24 * y,",
+ &[(6, Rgb565::MAGENTA, "24 "), (9, Rgb565::RED, "* "), (11, Rgb565::WHITE, "y,")],
+ // " (32 * (x + 1)) - 1,",
+ &[(6, Rgb565::WHITE, "("), (7, Rgb565::MAGENTA,"32 "), (10, Rgb565::RED, "* "), (12, Rgb565::WHITE, "(x "), (15, Rgb565::RED, "+ "), (17, Rgb565::MAGENTA, "1"), (18, Rgb565::WHITE, ")) "), (21, Rgb565::RED, "- "), (23, Rgb565::MAGENTA, "1"), (24, Rgb565::WHITE, ",")],
+ // " (24 * (y + 1)) - 1,",
+ &[(6, Rgb565::WHITE, "("), (7, Rgb565::MAGENTA,"24 "), (10, Rgb565::RED, "* "), (12, Rgb565::WHITE, "(y "), (15, Rgb565::RED, "+ "), (17, Rgb565::MAGENTA, "1"), (18, Rgb565::WHITE, ")) "), (21, Rgb565::RED, "- "), (23, Rgb565::MAGENTA, "1"), (24, Rgb565::WHITE, ",")],
+ // " &buffy,",
+ &[(6, Rgb565::RED, "&"), (7, Rgb565::WHITE, "buffy,")],
+ // " ).unwrap();",
+ &[(4, Rgb565::WHITE, ")."), (6, Rgb565::CYAN, "unwrap"), (12, Rgb565::WHITE, "();")],
+ // " }",
+ &[(2, Rgb565::WHITE, "}")],
+ // "}",
+ &[(0, Rgb565::WHITE, "}")],
+];
+
+#[entry]
+fn main() -> ! {
+ match inner_main() {
+ Ok(()) => cortex_m::peripheral::SCB::sys_reset(),
+ Err(e) => panic!(e),
+ }
+}
+
+fn inner_main() -> Result<(), &'static str> {
+ let mut board = Peripherals::take().ok_or("Error getting board!")?;
+ let mut corep = CorePeripherals::take().ok_or("Error")?;
+ let mut timer = Timer::new(board.TIMER0);
+ let mut delay = Timer::new(board.TIMER1);
+ let mut rng = Rng::new(board.RNG);
+ let mut toggle = false;
+ let _clocks = Clocks::new(board.CLOCK).enable_ext_hfosc();
+
+ // use ChannelMode::NoBlockS
+ rtt_init_print!(NoBlockSkip, 4096);
+
+ if let Some(msg) = panic_persist::get_panic_message_utf8() {
+ rprintln!("{}", msg);
+ } else {
+ rprintln!("Clean boot!");
+ }
+
+
+ let p0 = P0Parts::new(board.P0);
+ let p1 = P1Parts::new(board.P1);
+
+ let kbd_lcd_reset = p1.p1_08; // GPIO5, D5
+ let stm_cs = p0.p0_07; // GPIO6, D6,
+ let lcd_cs = p0.p0_26; // GPIO9, D9,
+ let lcd_dc = p0.p0_27; // GPIO10, D10
+
+ // Pull the neopixel line low so noise doesn't make it turn on spuriously
+ let keywing_neopixel = p0.p0_06.into_push_pull_output(Level::Low); // GPIO11, D11
+
+ let spim = Spim::new(
+ board.SPIM3,
+ SpimPins {
+ sck: p0.p0_14.into_push_pull_output(Level::Low).degrade(),
+ miso: Some(p0.p0_15.into_floating_input().degrade()),
+ mosi: Some(p0.p0_13.into_push_pull_output(Level::Low).degrade()),
+ },
+ SpimFrequency::M32,
+ MODE_0,
+ 0x00,
+ );
+
+ let mut lcd = Ili9341::new_spi(
+ spim,
+ lcd_cs.into_push_pull_output(Level::High),
+ lcd_dc.into_push_pull_output(Level::High),
+ kbd_lcd_reset.into_push_pull_output(Level::High),
+ &mut delay,
+ ).unwrap();
+
+ lcd.set_orientation(Orientation::Landscape).unwrap();
+
+ let mut buffy = [0u16; 24 * 32];
+ let mut buffy2 = [[0u16; 320]; 240];
+
+ let mut fbuffy = buffer::FrameBuffer::new(&mut buffy2);
+
+ // // rrrrr gggggg bbbbb
+ // buffy.iter_mut().for_each(|px| *px = 0b11111_000000_00000);
+
+ let style = TextStyleBuilder::new(Font8x16)
+ .text_color(Rgb565::WHITE)
+ .background_color(Rgb565::BLACK)
+ .build();
+
+ loop {
+
+ rprintln!("Start colors raw");
+
+ for x in 0..10 {
+ for y in 0..10 {
+ let rand: u16 = rng.random_u16();
+ buffy.iter_mut().for_each(|px| {
+ *px = swap(rand)
+ });
+
+ lcd.draw_raw(
+ 32 * x,
+ 24 * y,
+ (32 * (x + 1)) - 1,
+ (24 * (y + 1)) - 1,
+ &buffy,
+ ).unwrap();
+ }
+ }
+
+ rprintln!("Done.\n");
+
+ timer.delay_ms(1000u16);
+
+ rprintln!("Start colors raw");
+
+ for x in 0..10 {
+ for y in 0..10 {
+ let rand: u16 = 0;
+ buffy.iter_mut().for_each(|px| {
+ *px = swap(rand)
+ });
+
+ lcd.draw_raw(
+ 32 * x,
+ 24 * y,
+ (32 * (x + 1)) - 1,
+ (24 * (y + 1)) - 1,
+ &buffy,
+ ).unwrap();
+ }
+ }
+
+ rprintln!("Done.\n");
+
+
+ timer.delay_ms(1000u16);
+
+ // buffy2.iter_mut().for_each(|px| *px = swap(0b00000_000000_00000));
+ // rprintln!("Start black");
+ // lcd.draw_raw(0, 0, 319, 239, &buffy2).unwrap();
+ // rprintln!("Done.\n");
+
+ rprintln!("text start");
+
+ for row in 0..15 {
+ Text::new(
+ TEXT_SAMPLE[row as usize],
+ Point::new(0, row * 16)
+ ).into_styled(style)
+ .draw(&mut lcd)
+ .unwrap();
+ }
+
+ rprintln!("text done");
+
+ timer.delay_ms(3000u16);
+
+ rprintln!("Start colors raw");
+
+ for x in 0..10 {
+ for y in 0..10 {
+ let rand: u16 = 0;
+ buffy.iter_mut().for_each(|px| {
+ *px = swap(rand)
+ });
+
+ lcd.draw_raw(
+ 32 * x,
+ 24 * y,
+ (32 * (x + 1)) - 1,
+ (24 * (y + 1)) - 1,
+ &buffy,
+ ).unwrap();
+ }
+ }
+
+ rprintln!("Done.\n");
+
+
+ timer.delay_ms(1000u16);
+
+ // buffy2.iter_mut().for_each(|px| *px = swap(0b00000_000000_00000));
+ // rprintln!("Start black");
+ // lcd.draw_raw(0, 0, 319, 239, &buffy2).unwrap();
+ // rprintln!("Done.\n");
+
+ rprintln!("text2 start");
+
+ for (i, row) in TEXT_SAMPLE2.iter().enumerate() {
+ for (offset, color, text) in row.iter() {
+ let styled = TextStyleBuilder::new(Font8x16)
+ .text_color(*color)
+ .background_color(Rgb565::BLACK)
+ .build();
+
+ Text::new(
+ text,
+ Point::new(*offset * 8, i as i32 * 16)
+ ).into_styled(styled)
+ .draw(&mut lcd)
+ .unwrap();
+ }
+ }
+
+ rprintln!("text2 done");
+
+ timer.delay_ms(3000u16);
+
+ rprintln!("Start colors raw");
+
+ for x in 0..10 {
+ for y in 0..10 {
+ let rand: u16 = 0;
+ buffy.iter_mut().for_each(|px| {
+ *px = swap(rand)
+ });
+
+ lcd.draw_raw(
+ 32 * x,
+ 24 * y,
+ (32 * (x + 1)) - 1,
+ (24 * (y + 1)) - 1,
+ &buffy,
+ ).unwrap();
+ }
+ }
+
+ rprintln!("Done.\n");
+
+ timer.delay_ms(1000u16);
+
+ // buffy2.iter_mut().for_each(|px| *px = swap(0b00000_000000_00000));
+ // rprintln!("Start black");
+ // lcd.draw_raw(0, 0, 319, 239, &buffy2).unwrap();
+ // rprintln!("Done.\n");
+
+ timer.start(1_000_000u32);
+
+ let start: u32 = timer.read();
+
+ for row in 0..15 {
+ Text::new(
+ TEXT_SAMPLE[row as usize],
+ Point::new(0, row * 16)
+ ).into_styled(style)
+ .draw(&mut fbuffy)
+ .unwrap();
+ }
+
+ let middle: u32 = timer.read();
+
+ lcd.draw_raw(0, 0, 319, 239, fbuffy.inner()).unwrap();
+
+ let end: u32 = timer.read();
+
+ rprintln!("text buffered done");
+ rprintln!("start: 0x{:08X}, middle: 0x{:08X}, end: 0x{:08X}", start, middle, end);
+ rprintln!("render: {} cycs", middle - start);
+ rprintln!("draw: {} cycs", end - middle);
+
+
+
+
+
+ timer.delay_ms(3000u16);
+
+ rprintln!("Start colors raw");
+
+ for x in 0..10 {
+ for y in 0..10 {
+ let rand: u16 = 0;
+ buffy.iter_mut().for_each(|px| {
+ *px = swap(rand)
+ });
+
+ lcd.draw_raw(
+ 32 * x,
+ 24 * y,
+ (32 * (x + 1)) - 1,
+ (24 * (y + 1)) - 1,
+ &buffy,
+ ).unwrap();
+ }
+ }
+
+ rprintln!("Done.\n");
+
+
+ timer.delay_ms(1000u16);
+
+ rprintln!("text2 buffered middle");
+
+ for (i, row) in TEXT_SAMPLE2.iter().enumerate() {
+ for (offset, color, text) in row.iter() {
+ let styled = TextStyleBuilder::new(Font8x16)
+ .text_color(*color)
+ .background_color(Rgb565::BLACK)
+ .build();
+
+ Text::new(
+ text,
+ Point::new(*offset * 8, i as i32 * 16)
+ ).into_styled(styled)
+ .draw(&mut fbuffy)
+ .unwrap();
+ }
+ }
+
+ rprintln!("text2 buffered middle");
+
+ lcd.draw_raw(0, 0, 319, 239, fbuffy.inner()).unwrap();
+
+ rprintln!("text2 buffered done");
+
+ timer.delay_ms(3000u16);
+
+ continue;
+
+
+ // // SHOULD BE
+ // // rrrrr gggggg bbbbb
+ // buffy2.iter_mut().for_each(|px| *px = swap(0b11111_000000_00000));
+ // rprintln!("Start red");
+ // lcd.draw_raw(0, 0, 319, 239, &buffy2).unwrap();
+ // rprintln!("Done.\n");
+
+ // timer.delay_ms(250u16);
+
+ // buffy2.iter_mut().for_each(|px| *px = swap(0b00000_111111_00000));
+ // rprintln!("Start green");
+ // lcd.draw_raw(0, 0, 319, 239, &buffy2).unwrap();
+ // rprintln!("Done.\n");
+
+ // timer.delay_ms(250u16);
+
+ // buffy2.iter_mut().for_each(|px| *px = swap(0b00000_000000_11111));
+ // rprintln!("Start blue");
+ // lcd.draw_raw(0, 0, 319, 239, &buffy2).unwrap();
+ // rprintln!("Done.\n");
+
+ // buffy2.iter_mut().for_each(|px| *px = swap(0b00000_000000_00000));
+ // rprintln!("Start black");
+ // lcd.draw_raw(0, 0, 319, 239, &buffy2).unwrap();
+ // rprintln!("Done.\n");
+
+ // 240 / 16: 15
+ // 320 / 8: 40
+
+ let text = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
+
+ let mut textiter = text.chars().cycle();
+
+ for row in 0..15 {
+ for col in 0..40 {
+ let mut buf = [0u8; 4];
+ let txt = textiter.next().unwrap().encode_utf8(&mut buf);
+ Text::new(
+ txt,
+ Point::new(col * 8, row * 16)
+ ).into_styled(style)
+ .draw(&mut lcd)
+ .unwrap();
+ }
+ timer.delay_ms(500u16);
+ }
+
+ timer.delay_ms(1000u16);
+
+
+ // buffy2.iter_mut().for_each(|px| *px = swap(0b00000_000000_00000));
+ // rprintln!("Start black");
+ // lcd.draw_raw(0, 0, 319, 239, &buffy2).unwrap();
+ // rprintln!("Done.\n");
+
+ rprintln!("Starting Text Fill...");
+
+ let mut text = Text::new(
+ "1234567890123456789012345678901234567890",
+ Point::new(0, 0)
+ ).into_styled(style);
+
+ for _y in 0..15 {
+ text.draw(&mut lcd).unwrap();
+ text = text.translate(Point::new(0, 16));
+ }
+
+ rprintln!("Finished Text Fill.");
+
+
+ timer.delay_ms(1000u16);
+
+
+ }
+
+ Ok(())
+}
+
+const fn swap(inp: u16) -> u16 {
+ (inp & 0x00FF) << 8 |
+ (inp & 0xFF00) >> 8
+}