Skip to content
Snippets Groups Projects
main.rs 6.14 KiB
Newer Older
#![no_std]
#![no_main]

Stephen D's avatar
Stephen D committed
mod keyboard;

#[rtic::app(
    device = rp2040_hal::pac,
    dispatchers = [TIMER_IRQ_1]
)]
mod app {
Stephen D's avatar
Stephen D committed
    use crate::keyboard::Keyboard;
    use cortex_m::delay::Delay;
    use display_interface_spi::SPIInterfaceNoCS;
    use embedded_graphics::{
        draw_target::DrawTarget,
        mono_font::{ascii::FONT_10X20, MonoTextStyleBuilder},
        pixelcolor::{Rgb565, RgbColor},
        prelude::{Point, Primitive},
        primitives::{Circle, PrimitiveStyle, Triangle},
        text::{Baseline, Text},
        Drawable,
    };
    use embedded_hal::PwmPin;
    use fugit::RateExtU32;
Stephen D's avatar
Stephen D committed
    use hal::{
        gpio::{
            bank0::{Gpio0, Gpio1, Gpio2},
            DynPinId, FunctionSio, Pin, PullDown, PullUp, SioInput, SioOutput,
        },
        Clock,
    };
    use mipidsi::Builder;
    use panic_probe as _;
    use rp2040_hal as hal;
    use rtic_monotonics::rp2040::*;
    use shift_register_driver::sipo::ShiftRegister16;

    const XTAL_FREQ_HZ: u32 = 12_000_000u32;

Stephen D's avatar
Stephen D committed
    type MyShiftRegister = ShiftRegister16<
        Pin<Gpio1, FunctionSio<SioOutput>, PullDown>,
        Pin<Gpio2, FunctionSio<SioOutput>, PullDown>,
        Pin<Gpio0, FunctionSio<SioOutput>, PullDown>,
    >;

    #[shared]
    struct Shared {}

    #[local]
    struct Local {}

    #[init]
    fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) {
        let mut pac = ctx.device;

        let mut watchdog = hal::Watchdog::new(pac.WATCHDOG);

        let clocks = hal::clocks::init_clocks_and_plls(
            XTAL_FREQ_HZ,
            pac.XOSC,
            pac.CLOCKS,
            pac.PLL_SYS,
            pac.PLL_USB,
            &mut pac.RESETS,
            &mut watchdog,
        )
        .ok()
        .unwrap();

        let sio = hal::Sio::new(pac.SIO);

        let pins = hal::gpio::Pins::new(
            pac.IO_BANK0,
            pac.PADS_BANK0,
            sio.gpio_bank0,
            &mut pac.RESETS,
        );

        // Init PWMs
        let mut pwm_slices = hal::pwm::Slices::new(pac.PWM, &mut pac.RESETS);

        // Display backlight
        let pwm = &mut pwm_slices.pwm5;
        pwm.set_ph_correct();
        pwm.enable();
        let disp_backlight = &mut pwm.channel_a;
        disp_backlight.output_to(pins.gpio10);
        let max_duty = disp_backlight.get_max_duty();
        disp_backlight.set_duty(max_duty / 2);

        // Shift register
        let sr_clk = pins.gpio1.into_push_pull_output();
        let sr_ser = pins.gpio0.into_push_pull_output();
        let sr_rclk = pins.gpio2.into_push_pull_output();
Stephen D's avatar
Stephen D committed
        let sr =
            cortex_m::singleton!(: MyShiftRegister = ShiftRegister16::new(sr_clk, sr_rclk, sr_ser))
                .unwrap();
        let sr_pins = sr.decompose();
Stephen D's avatar
Stephen D committed
        let [_led_b, _led_g, _led_r, _tp_reset, disp_reset, _, _, _, col1, col2, col3, col4, col5, col6, col7, _unused] =
Stephen D's avatar
Stephen D committed
        // Keyboard
        let cols = [col1, col2, col3, col4, col5, col6, col7];
        let rows: [Pin<DynPinId, FunctionSio<SioInput>, PullUp>; 7] = [
            pins.gpio9.into_pull_up_input().into_dyn_pin(),
            pins.gpio8.into_pull_up_input().into_dyn_pin(),
            pins.gpio7.into_pull_up_input().into_dyn_pin(),
            pins.gpio6.into_pull_up_input().into_dyn_pin(),
            pins.gpio5.into_pull_up_input().into_dyn_pin(),
            pins.gpio4.into_pull_up_input().into_dyn_pin(),
            pins.gpio3.into_pull_up_input().into_dyn_pin(),
        ];
        let keyboard = Keyboard::new(cols, rows);

        // SPI Display
        let display_cs = pins.gpio16.into_push_pull_output();
        let spi_mosi = pins.gpio15.into_function::<hal::gpio::FunctionSpi>();
        let spi_miso = pins.gpio12.into_function::<hal::gpio::FunctionSpi>();
        let spi_sclk = pins.gpio14.into_function::<hal::gpio::FunctionSpi>();
        let spi = hal::spi::Spi::<_, _, _, 8>::new(pac.SPI1, (spi_mosi, spi_miso, spi_sclk));

        let spi = spi.init(
            &mut pac.RESETS,
            clocks.peripheral_clock.freq(),
            16.MHz(),
            embedded_hal::spi::MODE_0,
        );

        let spi_cs = SPIInterfaceNoCS::new(spi, display_cs);

        let mut delay = Delay::new(ctx.core.SYST, clocks.system_clock.freq().to_Hz());
        let mut display = Builder::st7789(spi_cs)
            .with_display_size(320, 240)
            .init(&mut delay, Some(disp_reset))
            .unwrap();

        // Make the display all black
        display.clear(Rgb565::BLACK).unwrap();

        // Draw a smiley face with white eyes and a red mouth
        draw_smiley(&mut display).unwrap();

        // text!
        let text_style = MonoTextStyleBuilder::new()
            .font(&FONT_10X20)
            .text_color(Rgb565::YELLOW)
            .build();

        Text::with_baseline(
            "Hello world!",
            Point::new(16, 128),
            text_style,
            Baseline::Top,
        )
        .draw(&mut display)
        .unwrap();

        (Shared {}, Local {}, init::Monotonics())
    }

    fn draw_smiley<T: DrawTarget<Color = Rgb565>>(display: &mut T) -> Result<(), T::Error> {
        // Draw the left eye as a circle located at (50, 100), with a diameter of 40, filled with white
        Circle::new(Point::new(50, 100), 40)
            .into_styled(PrimitiveStyle::with_fill(Rgb565::WHITE))
            .draw(display)?;

        // Draw the right eye as a circle located at (50, 200), with a diameter of 40, filled with white
        Circle::new(Point::new(50, 200), 40)
            .into_styled(PrimitiveStyle::with_fill(Rgb565::WHITE))
            .draw(display)?;

        // Draw an upside down red triangle to represent a smiling mouth
        Triangle::new(
            Point::new(130, 140),
            Point::new(130, 200),
            Point::new(160, 170),
        )
        .into_styled(PrimitiveStyle::with_fill(Rgb565::RED))
        .draw(display)?;

        // Cover the top part of the mouth with a black triangle so it looks closed instead of open
        Triangle::new(
            Point::new(130, 150),
            Point::new(130, 190),
            Point::new(150, 170),
        )
        .into_styled(PrimitiveStyle::with_fill(Rgb565::BLACK))
        .draw(display)?;

        Ok(())
    }
}