#![no_main]
// Panic provider crate
-use panic_persist;
use cortex_m;
+use panic_persist;
// Used to set the program entry point
use cortex_m_rt::entry;
// Provides definitions for our development board
use nrf52840_hal::{
+ gpio::{p0::Parts as P0Parts, p1::Parts as P1Parts, Level},
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,
+ spim::{Frequency as SpimFrequency, Pins as SpimPins, MODE_0},
+ target::{CorePeripherals, Peripherals},
+ twim::{Frequency as TwimFrequency, Pins as TwimPins},
+ Clocks, Rng, Spim, Timer, Twim,
};
-use rtt_target::{
- rprint, rprintln,
- rtt_init_print,
-};
+use rtt_target::{rprint, rprintln, rtt_init_print};
use embedded_graphics::{
fonts::{Font8x16, Text},
style::{TextStyle, TextStyleBuilder},
};
+use bbq10kbd::{Bbq10Kbd, KeyRaw};
+
mod buffer;
use ili9341::{Ili9341, Orientation};
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, " {")],
+ &[
+ (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, " {")],
+ &[
+ (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, "();")],
+ &[
+ (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, "| {")],
+ &[
+ (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)")],
+ &[
+ (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, "(")],
+ &[
+ (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,")],
+ &[
+ (6, Rgb565::MAGENTA, "32 "),
+ (9, Rgb565::RED, "* "),
+ (11, Rgb565::WHITE, "x,"),
+ ],
// " 24 * y,",
- &[(6, Rgb565::MAGENTA, "24 "), (9, Rgb565::RED, "* "), (11, Rgb565::WHITE, "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, ",")],
+ &[
+ (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, ",")],
+ &[
+ (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, "();")],
+ &[
+ (4, Rgb565::WHITE, ")."),
+ (6, Rgb565::CYAN, "unwrap"),
+ (12, Rgb565::WHITE, "();"),
+ ],
// " }",
&[(2, Rgb565::WHITE, "}")],
// "}",
rprintln!("Clean boot!");
}
-
let p0 = P0Parts::new(board.P0);
let p1 = P1Parts::new(board.P1);
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 kbd_sda = p0.p0_12.into_floating_input().degrade();
+ let kbd_scl = p0.p0_11.into_floating_input().degrade();
+
+ let kbd_i2c = Twim::new(
+ board.TWIM0,
+ TwimPins {
+ sda: kbd_sda,
+ scl: kbd_scl,
+ },
+ TwimFrequency::K100,
+ );
+
+ let mut kbd = Bbq10Kbd::new(kbd_i2c);
+
+ // Pull the neopixel lines 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 feather_neopixel = p0.p0_16.into_push_pull_output(Level::Low);
let spim = Spim::new(
board.SPIM3,
lcd_dc.into_push_pull_output(Level::High),
kbd_lcd_reset.into_push_pull_output(Level::High),
&mut delay,
- ).unwrap();
+ )
+ .unwrap();
lcd.set_orientation(Orientation::Landscape).unwrap();
- let mut buffy = [0u16; 24 * 32];
+ 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)
+ let mut style = TextStyleBuilder::new(Font8x16)
.text_color(Rgb565::WHITE)
.background_color(Rgb565::BLACK)
.build();
- loop {
+ let mut ctr: u8 = 0;
+ kbd.set_backlight(ctr).unwrap();
- 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();
- }
- }
+ let vers = kbd.get_version().unwrap();
- rprintln!("Done.\n");
+ rprintln!("Vers: {:?}", vers);
- timer.delay_ms(1000u16);
+ kbd.sw_reset().unwrap();
+ timer.delay_ms(10u8);
- rprintln!("Start colors raw");
+ let vers = kbd.get_version().unwrap();
- for x in 0..10 {
- for y in 0..10 {
- let rand: u16 = 0;
- buffy.iter_mut().for_each(|px| {
- *px = swap(rand)
- });
+ rprintln!("Vers: {:?}", vers);
- 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");
+ let mut cursor_y = 0;
+ let mut cursor_x = 0;
- 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();
- }
- }
+ let mut cursor = Cursor { x: 0, y: 0 };
- rprintln!("Done.\n");
+ lcd.clear(Rgb565::BLACK).map_err(|_| "Fade to error")?;
+ fbuffy.clear(Rgb565::BLACK).map_err(|_| "Fade to error")?;
+ loop {
+ let key = kbd.get_fifo_key_raw().map_err(|_| "bad fifo")?;
- 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)
+ match key {
+ // LL
+ KeyRaw::Pressed(6) => {
+ style = TextStyleBuilder::new(Font8x16)
+ .text_color(Rgb565::WHITE)
.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();
+ // LR
+ KeyRaw::Pressed(17) => {
+ style = TextStyleBuilder::new(Font8x16)
+ .text_color(Rgb565::RED)
+ .background_color(Rgb565::BLACK)
+ .build();
}
- }
-
- 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();
+ // RL
+ KeyRaw::Pressed(7) => {
+ style = TextStyleBuilder::new(Font8x16)
+ .text_color(Rgb565::GREEN)
+ .background_color(Rgb565::BLACK)
+ .build();
}
- }
-
- 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)
+ // RR
+ KeyRaw::Pressed(18) => {
+ style = TextStyleBuilder::new(Font8x16)
+ .text_color(Rgb565::BLUE)
.background_color(Rgb565::BLACK)
.build();
+ }
+ // Up
+ KeyRaw::Pressed(1) => {
+ cursor.up();
+ }
+ // Down
+ KeyRaw::Pressed(2) => {
+ cursor.down();
+ }
+ // Left
+ KeyRaw::Pressed(3) => {
+ cursor.left();
+ }
+ // Right
+ KeyRaw::Pressed(4) => {
+ cursor.right();
+ }
+ // Center
+ KeyRaw::Pressed(5) => {
+ kbd.sw_reset().unwrap();
+ cursor = Cursor { x: 0, y: 0 };
+ fbuffy.clear(Rgb565::BLACK).map_err(|_| "Fade to error")?;
+ }
+ // Backspace
+ KeyRaw::Pressed(8) => {
+ cursor.left();
+ Text::new(" ", cursor.pos())
+ .into_styled(style)
+ .draw(&mut fbuffy)
+ .map_err(|_| "bad lcd")?;
+ }
+ // Enter
+ KeyRaw::Pressed(10) => {
+ cursor.enter();
+ }
+ KeyRaw::Pressed(k) => {
+ rprintln!("Got key {}", k);
+ if let Ok(s) = core::str::from_utf8(&[k]) {
+ Text::new(s, cursor.pos())
+ .into_styled(style)
+ .draw(&mut fbuffy)
+ .map_err(|_| "bad lcd")?;
+
+ cursor.right();
+ }
+ }
+ KeyRaw::Invalid => {
+ if let Some(buf) = fbuffy.inner() {
+ timer.start(1_000_000u32);
+ lcd.draw_raw(
+ 0, 0,
+ 319, 239,
+ buf
+ ).map_err(|_| "bad buffy")?;
+ let done = timer.read();
+ rprintln!("Drew in {}ms.", done / 1000);
+ } else {
+ timer.delay_ms(38u8);
+ }
- 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");
+ Ok(())
+}
- // 240 / 16: 15
- // 320 / 8: 40
+struct Cursor {
+ x: i32,
+ y: i32,
+}
- let text = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
+impl Cursor {
+ fn up(&mut self) {
+ self.y -= 1;
+ if self.y < 0 {
+ self.y = 0;
+ }
+ }
- let mut textiter = text.chars().cycle();
+ fn down(&mut self) {
+ self.y += 1;
+ if self.y >= 15 {
+ self.y = 14;
+ }
+ }
- 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();
+ fn left(&mut self) {
+ self.x -= 1;
+ if self.x < 0 {
+ if self.y != 0 {
+ self.x = 39;
+ self.up();
+ } else {
+ self.x = 0;
}
- 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));
+ fn right(&mut self) {
+ self.x += 1;
+ if self.x >= 40 {
+ self.x = 0;
+ self.down();
}
+ }
- rprintln!("Finished Text Fill.");
-
-
- timer.delay_ms(1000u16);
-
-
+ fn enter(&mut self) {
+ if self.y != 14 {
+ self.x = 0;
+ self.down();
+ }
}
- Ok(())
+ fn pos(&self) -> Point {
+ Point::new(self.x * 8, self.y * 16)
+ }
}
-const fn swap(inp: u16) -> u16 {
- (inp & 0x00FF) << 8 |
- (inp & 0xFF00) >> 8
-}
+// let key_raw = kbd.get_fifo_key_raw().unwrap();
+
+// match key_raw {
+// KeyRaw::Invalid => {
+// timer.delay_ms(1000u16);
+// let state = kbd.get_key_status().unwrap();
+// rprintln!("Key Status: {:?}", state);
+// }
+// key @ _ => {
+// ctr = ctr.wrapping_add(5);
+// rprintln!("Key: {:?} - {}", key, ctr);
+// kbd.set_backlight(ctr).unwrap();
+// assert_eq!(kbd.get_backlight().unwrap(), ctr);
+// }
+// }
+
+// Special keys
+// LL: 6
+// LR: 17
+// RL: 7
+// RR: 18
+//
+// D-L: 3
+// D-U: 1
+// D-R: 4
+// D-D: 2
+// D-C: 5