]> patrickod personal git archive - keywing-rs.git/blobdiff - keywing/src/main.rs
2021 nix flake updates & some minor cleanup
[keywing-rs.git] / keywing / src / main.rs
index fd713503492fd18b2c906c1443cade2fc638dd25..aaa1d488e7e114d422597a8f9efe7d85f180fc82 100644 (file)
@@ -2,99 +2,37 @@
 #![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() {
@@ -104,13 +42,25 @@ fn 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);
@@ -121,363 +71,215 @@ fn inner_main() -> Result<(), &'static str> {
         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)
+    }
 }