-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathmain.rs
208 lines (180 loc) · 6.13 KB
/
main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
//! QT PY RP2040 with Framework 16 Input Module Firmware
//!
//! Neopixel/WS2812 compatible RGB LED is connected to GPIO12.
//! This pin doesn't support SPI TX.
//! It does support UART TX, but that output would have to be inverted.
//! So instead we use PIO to drive the LED.
#![no_std]
#![no_main]
#![allow(clippy::needless_range_loop)]
use bsp::entry;
use cortex_m::delay::Delay;
use defmt_rtt as _;
use rp2040_hal::gpio::bank0::Gpio12;
use rp2040_hal::pio::PIOExt;
//#[cfg(debug_assertions)]
//use panic_probe as _;
use rp2040_panic_usb_boot as _;
// Provide an alias for our BSP so we can switch targets quickly.
// Uncomment the BSP you included in Cargo.toml, the rest of the code does not need to change.
use adafruit_qt_py_rp2040 as bsp;
//use rp_pico as bsp;
use bsp::hal::{
clocks::{init_clocks_and_plls, Clock},
gpio::PinState,
pac,
sio::Sio,
usb,
watchdog::Watchdog,
Timer,
};
// USB Device support
use usb_device::{class_prelude::*, prelude::*, descriptor::lang_id};
// USB Communications Class Device support
use usbd_serial::{SerialPort, USB_CLASS_CDC};
use usbd_picotool_reset::PicoToolReset;
// Used to demonstrate writing formatted strings
// use core::fmt::Write;
// use heapless::String;
// RGB LED
use smart_leds::{colors, SmartLedsWrite, RGB8};
pub type Ws2812<'a> = ws2812_pio::Ws2812<
crate::pac::PIO0,
rp2040_hal::pio::SM0,
rp2040_hal::timer::CountDown<'a>,
Gpio12,
>;
use fl16_inputmodules::control::*;
use fl16_inputmodules::serialnum::device_release;
const FRAMEWORK_VID: u16 = 0x32AC;
const COMMUNITY_PID: u16 = 0x001F;
#[entry]
fn main() -> ! {
let mut pac = pac::Peripherals::take().unwrap();
let core = pac::CorePeripherals::take().unwrap();
let mut watchdog = Watchdog::new(pac.WATCHDOG);
let sio = Sio::new(pac.SIO);
let clocks = init_clocks_and_plls(
bsp::XOSC_CRYSTAL_FREQ,
pac.XOSC,
pac.CLOCKS,
pac.PLL_SYS,
pac.PLL_USB,
&mut pac.RESETS,
&mut watchdog,
)
.ok()
.unwrap();
let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz());
let pins = bsp::Pins::new(
pac.IO_BANK0,
pac.PADS_BANK0,
sio.gpio_bank0,
&mut pac.RESETS,
);
// Set up the USB driver
let usb_bus = UsbBusAllocator::new(usb::UsbBus::new(
pac.USBCTRL_REGS,
pac.USBCTRL_DPRAM,
clocks.usb_clock,
true,
&mut pac.RESETS,
));
let mut picotool: PicoToolReset<_> = PicoToolReset::new(&usb_bus);
// Set up the USB Communications Class Device driver
let mut serial = SerialPort::new(&usb_bus);
let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(FRAMEWORK_VID, COMMUNITY_PID))
//.strings(&[StringDescriptors::new(lang_id::ENGLISH_US)
// .manufacturer("Adafruit")
// .product("QT PY - Framework 16 Inputmodule FW")])
//.expect("Failed to set strings")
.manufacturer("Adafruit")
.product("QT PY - Framework 16 Inputmodule FW")
.max_power(500)
.device_release(device_release())
.device_class(USB_CLASS_CDC)
.build();
let mut state = C1MinimalState {
sleeping: SimpleSleepState::Awake,
color: colors::GREEN,
brightness: 10,
};
let timer = Timer::new(pac.TIMER, &mut pac.RESETS);
let mut prev_timer = timer.get_counter().ticks();
pins.neopixel_power
.into_push_pull_output_in_state(PinState::High);
let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
let mut ws2812: Ws2812 = ws2812_pio::Ws2812::new(
pins.neopixel_data.into_mode(),
&mut pio,
sm0,
clocks.peripheral_clock.freq(),
timer.count_down(),
);
ws2812
.write(smart_leds::brightness(
[state.color].iter().cloned(),
state.brightness,
))
.unwrap();
loop {
// Handle period LED updates. Don't do it too often or USB will get stuck
if timer.get_counter().ticks() > prev_timer + 20_000 {
// TODO: Can do animations here
prev_timer = timer.get_counter().ticks();
}
// Check for new data
// usb_dev.poll(&mut [&mut picotool, &mut serial]);
if usb_dev.poll(&mut [&mut picotool, &mut serial]) {
let mut buf = [0u8; 64];
match serial.read(&mut buf) {
Err(_e) => {
// Do nothing
}
Ok(0) => {
// Do nothing
}
Ok(count) => {
if let Some(command) = parse_command(count, &buf) {
if let Command::Sleep(go_sleeping) = command {
handle_sleep(go_sleeping, &mut state, &mut delay, &mut ws2812);
} else if let SimpleSleepState::Awake = state.sleeping {
// While sleeping no command is handled, except waking up
if let Some(response) =
handle_command(&command, &mut state, &mut ws2812)
{
let _ = serial.write(&response);
};
}
}
}
}
}
}
}
fn handle_sleep(
go_sleeping: bool,
state: &mut C1MinimalState,
_delay: &mut Delay,
ws2812: &mut impl SmartLedsWrite<Color = RGB8, Error = ()>,
) {
match (state.sleeping.clone(), go_sleeping) {
(SimpleSleepState::Awake, false) => (),
(SimpleSleepState::Awake, true) => {
state.sleeping = SimpleSleepState::Sleeping;
// Turn off LED
ws2812.write([colors::BLACK].iter().cloned()).unwrap();
}
(SimpleSleepState::Sleeping, true) => (),
(SimpleSleepState::Sleeping, false) => {
state.sleeping = SimpleSleepState::Awake;
// Turn LED back on
ws2812
.write(smart_leds::brightness(
[state.color].iter().cloned(),
state.brightness,
))
.unwrap();
}
}
}