Newer
Older
use panic_rtt_target as _;
#[link_section = ".boot2"]
#[used]
pub static BOOT_LOADER: [u8; 256] = rp2040_boot2::BOOT_LOADER_GD25Q64CS;
#[rtic::app(
device = rp2040_hal::pac,
use embedded_graphics::{pixelcolor::Rgb565, prelude::RgbColor};
bank0::{
Gpio0, Gpio1, Gpio12, Gpio13, Gpio14, Gpio15, Gpio16, Gpio18, Gpio2, Gpio23,
FunctionI2C, FunctionSio, FunctionSpi, Pin, PinState, PullDown, PullNone, PullUp,
SioInput, SioOutput,
pac::{I2C1, SPI1},
pwm::{self, Channel, FreeRunning, Pwm4, Pwm5, Slice},
timer::{monotonic::Monotonic, Instant, Timer},
use mipidsi::{models::ST7789, Builder, Orientation};
use rp2040_hal::{self as hal, gpio::FunctionNull, timer::Alarm0};
use rtic_monotonics::rp2040::*;
const XTAL_FREQ_HZ: u32 = 12_000_000u32;
const WIDTH: usize = 320;
const HEIGHT: usize = 240;
const BACKLIGHT_DELAY_TIME_SECS: u64 = 5;
const BACKLIGHT_FADE_TIME_SECS: u64 = 2;
type KeyboardBl = Channel<Slice<Pwm4, FreeRunning>, pwm::B>;
type MyTouchpad = Touchpad<
I2C<
I2C1,
(
Pin<Gpio18, FunctionI2C, PullUp>,
Pin<Gpio23, FunctionI2C, PullUp>,
),
>,
Pin<Gpio3, FunctionSio<SioOutput>, PullDown>,
Pin<Gpio24, FunctionSio<SioOutput>, PullDown>,
>;
type MyKeyboard = Keyboard<
Pin<Gpio1, FunctionSio<SioOutput>, PullDown>,
Pin<Gpio0, FunctionSio<SioOutput>, PullDown>,
Pin<Gpio2, FunctionSio<SioOutput>, PullDown>,
Pin<Gpio8, FunctionSio<SioOutput>, PullDown>,
Pin<Gpio6, FunctionSio<SioInput>, PullNone>,
Pin<Gpio7, FunctionSio<SioOutput>, PullDown>,
>;
type MyBufferedDisplay = BufferedDisplay<
{ WIDTH * HEIGHT },
SPIInterface<
spi::Spi<
spi::Enabled,
SPI1,
(
Pin<Gpio15, FunctionSpi, PullDown>,
Pin<Gpio12, FunctionSpi, PullDown>,
Pin<Gpio14, FunctionSpi, PullDown>,
),
>,
Pin<Gpio16, FunctionSio<SioOutput>, PullDown>,
Pin<Gpio13, FunctionSio<SioOutput>, PullDown>,
>,
ST7789,
Pin<Gpio4, FunctionSio<SioOutput>, PullDown>,
>;
type DisplayBl = Channel<Slice<Pwm5, FreeRunning>, pwm::A>;
#[monotonic(binds = TIMER_IRQ_0, default = true)]
type MyMono = Monotonic<Alarm0>;
struct Local {
touchpad: MyTouchpad,
keyboard: MyKeyboard,
keyboard_bl: KeyboardBl,
#[init]
fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) {
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
let pwm_slices = hal::pwm::Slices::new(pac.PWM, &mut pac.RESETS);
let mut timer = Timer::new(pac.TIMER, &mut pac.RESETS, &clocks);
// Set up the USB driver
/*let usb_bus = UsbBusAllocator::new(hal::usb::UsbBus::new(
pac.USBCTRL_REGS,
pac.USBCTRL_DPRAM,
clocks.usb_clock,
true,
&mut pac.RESETS,
));*/
// Set up the USB Communications Class Device driver
/*let mut serial = SerialPort::new(&usb_bus);
// Create a USB device with a fake VID and PID
let mut 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 mut vibrator = pins.gpio9.into_push_pull_output();
let mut delay = Delay::new(ctx.core.SYST, clocks.system_clock.freq().to_Hz());
pwm.set_ph_correct();
pwm.enable();
let mut display_bl = pwm.channel_a;
display_bl.output_to(pins.gpio10);
display_bl.set_inverted();
display_bl.set_duty(display_bl.get_max_duty());
let mut disp_reset = pins.gpio4.into_push_pull_output_in_state(PinState::Low);
delay.delay_us(10);
disp_reset.set_high().unwrap();
// Touchpad
let sda_pin: Pin<_, FunctionI2C, PullUp> = pins.gpio18.reconfigure();
let scl_pin: Pin<_, FunctionI2C, PullUp> = pins.gpio23.reconfigure();
let tp_shutdown = pins.gpio24.into_push_pull_output();
let i2c = I2C::i2c1(
pac.I2C1,
sda_pin,
scl_pin,
400.kHz(),
&mut pac.RESETS,
&clocks.system_clock,
);
let touchpad = Touchpad::new(i2c, tp_reset, tp_shutdown, timer);
let col_clk = pins.gpio1.into_push_pull_output();
let col_ser = pins.gpio0.into_push_pull_output();
let col_rclk = pins.gpio2.into_push_pull_output();
let row_clk = pins.gpio8.into_push_pull_output();
let row_ser = pins.gpio6.into_floating_input();
let row_ld = pins.gpio7.into_push_pull_output();
let keyboard = Keyboard::new(timer, col_clk, col_ser, col_rclk, row_clk, row_ser, row_ld);
let mut pwm = pwm_slices.pwm4;
pwm.set_ph_correct();
pwm.enable();
let mut keyboard_bl = pwm.channel_b;
keyboard_bl.output_to(pins.gpio25);
keyboard_bl.set_duty(0);
let display_cs = pins.gpio13.into_push_pull_output();
let display_dc = 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(),
.with_display_size(HEIGHT.try_into().unwrap(), WIDTH.try_into().unwrap())
.with_orientation(Orientation::LandscapeInverted(true))
let mut buf =
singleton!(: [Rgb565;WIDTH * HEIGHT] = [Rgb565::BLACK; WIDTH * HEIGHT]).unwrap();
let display = BufferedDisplay::new(display, buf);
// Set up voltage monitoring
let adc = Adc::new(pac.ADC, &mut pac.RESETS);
let volt_meter = VoltMeter::new(
adc,
pins.gpio26.into_floating_disabled(),
pins.gpio28.into_floating_disabled(),
);
// Setup app
let gui = Gui::new(volt_meter);
display_update::spawn().unwrap();
keyboard_update::spawn().unwrap();
let mut mono = Monotonic::new(timer, timer.alarm_0().unwrap());
Local {
keyboard_bl,
touchpad,
keyboard,
display,
display_bl,
#[task(priority = 2, local = [display_bl, keyboard_bl, touchpad, keyboard, last_key_press], shared = [gui])]
//while usb_dev.poll(&mut [&mut serial]) {}
let keyboard_update::LocalResources {
display_bl,
keyboard_bl,
touchpad,
keyboard,
} = ctx.local;
let max_duty = keyboard_bl.get_max_duty();
let mut cur_duty = display_bl.get_duty();
let state = keyboard.read_state();
if state > 0 {
if let Some(k) = keyboard.pushed_key() {
}
let (x, y) = touchpad.get_delta_motion().unwrap();
match y {
x if x > 0 => {
cur_duty = cur_duty.saturating_sub(250);
}
x if x < 0 => {
cur_duty = cur_duty.saturating_add(250);
}
_ => {}
}
display_bl.set_duty(cur_duty.min(display_bl.get_max_duty()));
// keyboard backlight logic
let delta = monotonics::now() - *last_key_press;
if let Some(fade_delta) = delta.checked_sub(BACKLIGHT_DELAY_TIME_SECS.secs::<1, 1>()) {
let fade_delta = fade_delta.to_millis();
let fade_time_ms = BACKLIGHT_FADE_TIME_SECS * 1000;
let frac = u64::from(keyboard_bl.get_max_duty())
* (fade_time_ms.saturating_sub(fade_delta))
/ fade_time_ms;
keyboard_bl.set_duty(frac.try_into().unwrap());
} else {
keyboard_bl.set_duty(keyboard_bl.get_max_duty());
}
// re-enqueue ourselves
fn display_update(mut ctx: display_update::Context) {
let display_update::LocalResources { display } = ctx.local;
}
#[idle]
fn idle(_: idle::Context) -> ! {
loop {
cortex_m::asm::wfi();
}