pico-flipdot/src/main.rs

204 lines
6.8 KiB
Rust

//! Blinks the LED on a Pico board
//!
//! This will blink an LED attached to GP25, which is the pin the Pico uses for the on-board LED.
#![no_std]
#![no_main]
use defmt_rtt as _;
use panic_probe as _;
mod flipdot;
#[rtic::app(device = rp_pico::hal::pac, peripherals = true, dispatchers = [XIP_IRQ])]
mod app {
use embedded_hal::digital::v2::OutputPin;
use rp_pico::hal;
use rp_pico::hal::*;
use rp_pico::XOSC_CRYSTAL_FREQ;
// USB Device support
use usb_device::{class_prelude::*, prelude::*};
// USB Communications Class Device support
use usbd_serial::SerialPort;
use rp2040_monotonic::fugit::ExtU64;
use rp2040_monotonic::*;
use crate::flipdot::write_display;
#[monotonic(binds = TIMER_IRQ_0, default = true)]
type Monotonic = Rp2040Monotonic;
#[shared]
struct Shared {
serial: SerialPort<'static, hal::usb::UsbBus>,
usb_dev: usb_device::device::UsbDevice<'static, hal::usb::UsbBus>,
}
#[local]
struct Local {
led_pin: hal::gpio::Pin<hal::gpio::pin::bank0::Gpio25, hal::gpio::PushPullOutput>,
row_data_pin: hal::gpio::Pin<hal::gpio::pin::bank0::Gpio4, hal::gpio::PushPullOutput>,
row_clock_pin: hal::gpio::Pin<hal::gpio::pin::bank0::Gpio5, hal::gpio::PushPullOutput>,
col_data_pin: hal::gpio::Pin<hal::gpio::pin::bank0::Gpio2, hal::gpio::PushPullOutput>,
col_clock_pin: hal::gpio::Pin<hal::gpio::pin::bank0::Gpio3, hal::gpio::PushPullOutput>,
white_pin: hal::gpio::Pin<hal::gpio::pin::bank0::Gpio6, hal::gpio::PushPullOutput>,
black_pin: hal::gpio::Pin<hal::gpio::pin::bank0::Gpio7, hal::gpio::PushPullOutput>,
strobe_pin: hal::gpio::Pin<hal::gpio::pin::bank0::Gpio8, hal::gpio::PushPullOutput>,
delay: cortex_m::delay::Delay,
pattern: bool,
}
#[init(local = [usb_bus: Option<usb_device::bus::UsbBusAllocator<hal::usb::UsbBus>> = None])]
fn init(c: init::Context) -> (Shared, Local, init::Monotonics) {
let mut resets = c.device.RESETS;
let mut watchdog = hal::watchdog::Watchdog::new(c.device.WATCHDOG);
// Configure the clocks - The default is to generate a 125 MHz system clock
let clocks = hal::clocks::init_clocks_and_plls(
XOSC_CRYSTAL_FREQ,
c.device.XOSC,
c.device.CLOCKS,
c.device.PLL_SYS,
c.device.PLL_USB,
&mut resets,
&mut watchdog,
)
.ok()
.unwrap();
let mut delay =
cortex_m::delay::Delay::new(c.core.SYST, clocks.system_clock.freq().to_Hz());
let usb_bus: &'static _ =
c.local
.usb_bus
.insert(UsbBusAllocator::new(hal::usb::UsbBus::new(
c.device.USBCTRL_REGS,
c.device.USBCTRL_DPRAM,
clocks.usb_clock,
true,
&mut resets,
)));
let serial = SerialPort::new(usb_bus);
let usb_dev = UsbDeviceBuilder::new(usb_bus, UsbVidPid(0x16c0, 0x27dd))
.manufacturer("Fake company")
.product("Serial port")
.serial_number("TEST")
.device_class(2) // from: https://www.usb.org/defined-class-codes
.build();
let sio = hal::Sio::new(c.device.SIO);
let pins = rp_pico::Pins::new(
c.device.IO_BANK0,
c.device.PADS_BANK0,
sio.gpio_bank0,
&mut resets,
);
let mut led_pin = pins.led.into_push_pull_output();
led_pin.set_low().unwrap();
let row_data_pin = pins.gpio4.into_push_pull_output();
let row_clock_pin = pins.gpio5.into_push_pull_output();
let col_data_pin = pins.gpio2.into_push_pull_output();
let col_clock_pin = pins.gpio3.into_push_pull_output();
let white_pin = pins.gpio6.into_push_pull_output();
let black_pin = pins.gpio7.into_push_pull_output();
let strobe_pin = pins.gpio8.into_push_pull_output();
let pattern = false;
update_display::spawn_after(1.secs()).unwrap();
(
Shared { serial, usb_dev },
Local {
led_pin,
row_data_pin,
row_clock_pin,
col_data_pin,
col_clock_pin,
white_pin,
black_pin,
strobe_pin,
delay,
pattern,
},
init::Monotonics(Rp2040Monotonic::new(c.device.TIMER)),
)
}
#[task(local = [pattern, led_pin, row_data_pin, row_clock_pin, col_data_pin,
col_clock_pin, white_pin, black_pin, strobe_pin, delay])]
fn update_display(cx: update_display::Context) {
let pattern = if *cx.local.pattern {
[
0b1010_1010_1010_1010_1010,
0b0101_0101_0101_0101_0101,
0b1010_1010_1010_1010_1010,
0b0101_0101_0101_0101_0101,
0b1010_1010_1010_1010_1010,
0b0101_0100_0000_0101_0101,
0b1010_1010_1111_0010_1010,
0b0101_0100_0001_0101_0101,
0b1010_1010_0001_0010_1010,
0b0101_0100_1001_0101_0101,
0b1010_1010_0000_0010_1010,
0b0101_0101_0101_0101_0101,
0b1010_1010_1010_1010_1010,
0b0101_0101_0101_0101_0101,
0b1010_1010_1010_1010_1010,
0b0101_0101_0101_0101_0101,
]
} else {
[
0b0101_0101_0101_0101_0101,
0b1010_1010_1010_1010_1010,
0b0101_0101_0101_0101_0101,
0b1010_1010_1010_1010_1010,
0b0101_0101_0101_0101_0101,
0b1010_1010_0000_0010_1010,
0b0101_0100_1111_0101_0101,
0b1010_1010_0001_0010_1010,
0b0101_0100_0001_0101_0101,
0b1010_1010_1001_0010_1010,
0b0101_0100_0000_0101_0101,
0b1010_1010_1010_1010_1010,
0b0101_0101_0101_0101_0101,
0b1010_1010_1010_1010_1010,
0b0101_0101_0101_0101_0101,
0b1010_1010_1010_1010_1010,
]
};
if *cx.local.pattern {
cx.local.led_pin.set_high().unwrap();
} else {
cx.local.led_pin.set_low().unwrap();
}
*cx.local.pattern = !*cx.local.pattern;
write_display(
&pattern,
cx.local.col_clock_pin,
cx.local.col_data_pin,
cx.local.row_clock_pin,
cx.local.row_data_pin,
cx.local.strobe_pin,
cx.local.white_pin,
cx.local.black_pin,
cx.local.delay,
);
update_display::spawn_after(1.secs()).unwrap();
}
}