#![no_main]
// Panic provider crate
-use panic_persist;
-use cortex_m;
+use panic_persist as _;
// 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,
-};
+extern crate feather_m4 as hal;
-use rtt_target::{
- rprint, rprintln,
- rtt_init_print,
-};
+use hal::prelude::*;
+use hal::clock::GenericClockController;
+use hal::pac::{CorePeripherals,Peripherals};
+use hal::trng::Trng;
+use hal::delay::Delay;
+use hal::Pins;
+use hal::{i2c_master,spi_master};
+use hal::time::U32Ext;
+
+use rtt_target::{rprintln, rtt_init_print};
use embedded_graphics::{
fonts::{Font8x16, Text},
pixelcolor::Rgb565,
prelude::*,
- style::{TextStyle, TextStyleBuilder},
+ style::TextStyleBuilder,
};
+use bbq10kbd::{Bbq10Kbd, KeyRaw};
+
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() {
}
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();
+ let mut peripherals = Peripherals::take().ok_or("Error getting board!")?;
+ let mut _pins = Pins::new(peripherals.PORT);
+ let _core = CorePeripherals::take().unwrap();
+
+ let mut _rng: Trng = Trng::new(&mut peripherals.MCLK, peripherals.TRNG);
+ let mut _clocks = GenericClockController::with_external_32kosc(
+ peripherals.GCLK,
+ &mut peripherals.MCLK,
+ &mut peripherals.OSC32KCTRL,
+ &mut peripherals.OSCCTRL,
+ &mut peripherals.NVMCTRL,
+ );
+ let mut delay = Delay::new(_core.SYST, &mut _clocks);
+
+ // set pins low to prevent floating values read as data by the pixels
+ let mut front_neopixel_pin = _pins.d11.into_push_pull_output(&mut _pins.port);
+ let mut rear_neopixel_pin = _pins.neopixel.into_push_pull_output(&mut _pins.port);
+ front_neopixel_pin.set_low().unwrap();
+ rear_neopixel_pin.set_high().unwrap();
// use ChannelMode::NoBlockS
rtt_init_print!(NoBlockSkip, 4096);
rprintln!("Clean boot!");
}
+ let kbd_lcd_reset = _pins.d5;
+ let _stm_cs = _pins.d6;
+ let lcd_cs = _pins.d9;
+ let lcd_dc = _pins.d10;
+
+ // i2c keyboard interface
+ // kbd SDA = D12
+ // kbd SCL = D11
+ // FREQ 100KHZ
+ let kbd_i2c = i2c_master(
+ &mut _clocks,
+ 100u32.khz(),
+ peripherals.SERCOM2,
+ &mut peripherals.MCLK,
+ _pins.sda,
+ _pins.scl,
+ &mut _pins.port
+ );
- 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 kbd = Bbq10Kbd::new(kbd_i2c);
+
+ let lcd_spi = spi_master(
+ &mut _clocks,
+ 32u32.mhz(),
+ peripherals.SERCOM1,
+ &mut peripherals.MCLK,
+ _pins.sck,
+ _pins.mosi,
+ _pins.miso,
+ &mut _pins.port
);
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),
+ lcd_spi,
+ lcd_cs.into_push_pull_output(&mut _pins.port),
+ lcd_dc.into_push_pull_output(&mut _pins.port),
+ kbd_lcd_reset.into_push_pull_output(&mut _pins.port),
&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)
+ let mut 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);
+ kbd.set_backlight(255).unwrap();
- 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();
- }
- }
+ kbd.sw_reset().unwrap();
+ delay.delay_ms(10u8);
- rprintln!("Done.\n");
+ let vers = kbd.get_version().unwrap();
+ rprintln!("Vers: {:?}", vers);
- timer.delay_ms(1000u16);
+ let mut cursor = Cursor { x: 0, y: 0 };
- // 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");
+ lcd.clear(Rgb565::BLACK).map_err(|_| "Fade to error")?;
+ fbuffy.clear(Rgb565::BLACK).map_err(|_| "Fade to error")?;
- 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");
+ loop {
+ let key = kbd.get_fifo_key_raw().map_err(|_| "bad fifo")?;
- 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();
-
- Text::new(
- text,
- Point::new(*offset * 8, i as i32 * 16)
- ).into_styled(styled)
- .draw(&mut fbuffy)
- .unwrap();
}
+ // 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 {
+ delay.delay_ms(38u8);
+ }
+ }
+ _ => {}
}
+ }
+}
- 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
+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);
-
-
}
- Ok(())
-}
+ fn enter(&mut self) {
+ if self.y != 14 {
+ self.x = 0;
+ self.down();
+ }
+ }
-const fn swap(inp: u16) -> u16 {
- (inp & 0x00FF) << 8 |
- (inp & 0xFF00) >> 8
+ fn pos(&self) -> Point {
+ Point::new(self.x * 8, self.y * 16)
+ }
}