Browse Source

More modular app

Nearly possible to enable/disable epd,bme and rtc parts.
gpiod ISR still need to be commented, so not only via cargo features.

Rewired rotary switch from PB7 to PC4 as it's shorting the board. Most probably
the pin can't be used like this on the stellaris board (should better check).
dev/doc
Marc Poulhiès 2 years ago
parent
commit
fecf9a654d
  1. 4
      Cargo.toml
  2. 474
      src/main.rs

4
Cargo.toml

@ -83,3 +83,7 @@ default = [ ]
## This will use semihosting for printing debug trace.
usesemihosting = [ "default" ]
epd = ["default"]
bme = ["default"]
rtc = ["default"]
testranges = ["default"]

474
src/main.rs

@ -128,7 +128,7 @@ use ds323x::{Ds323x, NaiveTime};
use tm4c123x_hal::{
gpio::gpioa::{PA2, PA4, PA5, PA6, PA7},
gpio::gpiob::{PB1, PB2, PB3, PB4, PB5, PB7},
gpio::gpioc::PC6,
gpio::gpioc::{PC4, PC6},
gpio::gpiod::{PD0, PD1, PD2, PD3},
gpio::gpioe::{PE2, PE4},
gpio::{
@ -189,6 +189,13 @@ type Spi1T = Spi<
),
>;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum EPDModeHint {
None,
ForceFull,
ForcePartial,
}
pub type EpdT = EPD2in13<
Spi0T,
PC6<Output<PushPull>>,
@ -260,20 +267,20 @@ where
type ToggleSwitchPinT = PB5<Input<PullUp>>;
type ToggleSwitchT = Switch<ToggleSwitchPinT>;
type RotarySwitchPinT = PB7<Input<PullUp>>;
type RotarySwitchPinT = PC4<Input<PullUp>>;
type RotarySwitchT = Switch<RotarySwitchPinT>;
#[rtic::app(device = tm4c123x_hal::pac, peripherals = true, monotonic = rtic::cyccnt::CYCCNT, dispatchers = [UART1, UART2, UART3, UART4])]
mod app {
use rtic::cyccnt::Instant;
use crate::{
draw_config_hint, Bme680T, FSMState, OperatingMode, RotarySwitchT, RotaryT, RtcT, Screen,
SimpleAsmDelay, Spi1T, SubConfig, TimeRange, ToggleSwitchT, FONT_RIGHT_BAR, FONT_TIME,
MAX_NUM_QUICK_REFRESH, NUM_LEDS, SCR_HOUR_X_OFF, SCR_HOUR_Y_OFF,
draw_config_hint, Bme680T, EPDModeHint, FSMState, OperatingMode, RotarySwitchT, RotaryT,
RtcT, Screen, SimpleAsmDelay, Spi1T, SubConfig, TimeRange, ToggleSwitchT, FONT_RIGHT_BAR,
FONT_TIME, MAX_NUM_QUICK_REFRESH, NUM_LEDS, SCR_HOUR_X_OFF, SCR_HOUR_Y_OFF,
SCR_RIGHT_BAR_ERRCNT_X_OFF, SCR_RIGHT_BAR_ERRCNT_Y_OFF, SCR_RIGHT_BAR_HUMID_X_OFF,
SCR_RIGHT_BAR_HUMID_Y_OFF, SCR_RIGHT_BAR_TEMP_X_OFF, SCR_RIGHT_BAR_TEMP_Y_OFF,
};
use rtic::cyccnt::Instant;
use tm4c123x_hal::{
gpio::{gpiod::PD6, Floating, GpioExt, Input, InterruptMode, PullUp, AF2, AF3},
@ -334,16 +341,17 @@ mod app {
}
// Runnig at 80Mhz
const ONE_MS: u32 = 80_000;
const ONE_MUS: u32 = 80;
const ONE_MUSEC: u32 = 80;
const ONE_MSEC: u32 = ONE_MUSEC * 1000;
const ONE_SEC: u32 = ONE_MSEC * 1000;
const TRANSITION_STEPS: u32 = 50;
const TRANSITION_STEP_CYCLES: u32 = (1000 / TRANSITION_STEPS) * ONE_MS;
const TRANSITION_STEP_CYCLES: u32 = (1000 / TRANSITION_STEPS) * ONE_MSEC;
// At 80Mhz, this is ~1ms
const POLL_SWITCH_PERIOD: u32 = 10 * ONE_MUS;
const POLL_SWITCH_PERIOD: u32 = 10 * ONE_MUSEC;
const DEBOUNCE_SAMPLE_CNT: i8 = 20;
const ROTARY_SAMPLING_PERIOD: u32 = 10 * ONE_MUS;
const ROTARY_SAMPLING_PERIOD: u32 = 10 * ONE_MUSEC;
#[resources]
struct Resources {
@ -351,12 +359,16 @@ mod app {
submode: SubConfig,
// The RTC periph
#[cfg(feature = "rtc")]
rtc: RtcT,
// e-ink
#[cfg(feature = "epd")]
screen: Screen,
display: Display2in13,
#[cfg(feature = "rtc")]
rtc_int_pin: PD6<Input<PullUp>>,
// ws2812
@ -364,18 +376,26 @@ mod app {
leds_data: [RGB8; NUM_LEDS],
// temp & cov
#[cfg(feature = "bme")]
bme680: Bme680T,
toggle_switch: ToggleSwitchT,
rotary_switch: RotarySwitchT,
#[cfg(feature = "rtc")]
new_time: NaiveTime,
rotary: RotaryT,
i2c_error: u32,
#[cfg(feature = "rtc")]
next_or_current_range: usize,
ranges: [TimeRange; 3],
#[cfg(feature = "rtc")]
ranges: [TimeRange; 2],
#[cfg(feature = "rtc")]
state: FSMState,
}
@ -405,6 +425,7 @@ mod app {
let mut portd = p.GPIO_PORTD.split(&sc.power_control);
let porte = p.GPIO_PORTE.split(&sc.power_control);
#[cfg(feature = "rtc")]
let i2c_rtc_dev = I2c::i2c0(
p.I2C0,
(
@ -417,6 +438,7 @@ mod app {
&clocks,
&sc.power_control,
);
#[cfg(feature = "rtc")]
let mut rtc = Ds323x::new_ds3231(i2c_rtc_dev);
let mut spi0 = Spi::spi0(
@ -438,6 +460,8 @@ mod app {
// Cortex-M peripherals
// : cortex_m::Peripherals
#[cfg(feature = "bme")]
let i2c_bme680 = I2c::i2c1(
p.I2C1,
(
@ -451,8 +475,10 @@ mod app {
&sc.power_control,
);
let bme680_sensor = Bme680Sensor::from(i2c_bme680, Address::Primary).unwrap();
#[cfg(feature = "bme")]
let bme680_sensor = Bme680Sensor::from(i2c_bme680, Address::Secondary).unwrap();
#[cfg(feature = "bme")]
let bme680 = Bme680Controller::new(
bme680_sensor,
SimpleAsmDelay { freq: 80_000_000 },
@ -462,12 +488,14 @@ mod app {
.unwrap();
let mut delay = SimpleAsmDelay { freq: 80_000_000 };
#[cfg(feature = "epd")]
let mut epd =
EPD2in13::new(&mut spi0, cs_pin, busy_pin, dc_pin, rst_pin, &mut delay).unwrap();
let mut display = Display2in13::default();
display.set_rotation(DisplayRotation::Rotate90);
display.set_rotation(DisplayRotation::Rotate90);
display.clear(White).unwrap();
let spi_ws2812 = Spi::spi1(
@ -489,145 +517,180 @@ mod app {
let rot_pinB = portb.pb4.into_pull_up_input();
let rotary = Rotary::new(rot_pinA, rot_pinB);
let rotary_pin = portc.pc4.into_pull_up_input();
// GPIO for interrupt
// SQW/INT pin wired to PD6
#[cfg(feature = "rtc")]
let mut rtc_int_pin = portd.pd6.into_pull_up_input();
rtc_int_pin.set_interrupt_mode(InterruptMode::EdgeFalling);
rtc_int_pin.clear_interrupt();
rtc.clear_alarm1_matched_flag().unwrap();
rtc.clear_alarm2_matched_flag().unwrap();
rtc.use_int_sqw_output_as_interrupt().unwrap();
#[cfg(feature = "rtc")]
let ranges;
// alarm1 used to track events
// alarm2 used to refresh clock display every minute.
rtc.enable_alarm1_interrupts().unwrap();
rtc.enable_alarm2_interrupts().unwrap();
#[cfg(feature = "rtc")]
let (mut next_or_current_range, mut state);
rtc.set_alarm2_day(
DayAlarm2 {
day: 1,
hour: Hours::H24(1),
minute: 0,
},
Alarm2Matching::OncePerMinute,
)
.unwrap();
#[cfg(feature = "rtc")]
{
rtc_int_pin.set_interrupt_mode(InterruptMode::EdgeFalling);
rtc_int_pin.clear_interrupt();
rtc.clear_alarm1_matched_flag().unwrap();
rtc.clear_alarm2_matched_flag().unwrap();
rtc.use_int_sqw_output_as_interrupt().unwrap();
// alarm1 used to track events
// alarm2 used to refresh clock display every minute.
rtc.enable_alarm1_interrupts().unwrap();
rtc.enable_alarm2_interrupts().unwrap();
rtc.set_alarm2_day(
DayAlarm2 {
day: 1,
hour: Hours::H24(1),
minute: 0,
},
Alarm2Matching::OncePerMinute,
)
.unwrap();
let time = rtc.get_time().unwrap();
refresh_time::spawn(time, false).unwrap();
refresh_bme680::spawn(false).unwrap();
let time = rtc.get_time().unwrap();
refresh_time::spawn(time, false).unwrap();
let ranges = [
TimeRange {
start: time
.overflowing_add_signed(chrono::Duration::seconds(60 * 1))
.0,
end: time
.overflowing_add_signed(chrono::Duration::seconds(60 * 2))
.0,
// start: NaiveTime::from_hms(0, 0, 0),
// end: NaiveTime::from_hms(5, 0, 0),
in_color: colors::RED,
name: "0:0->5:0",
},
TimeRange {
start: time
.overflowing_add_signed(chrono::Duration::seconds(60 * 3))
.0,
end: time
.overflowing_add_signed(chrono::Duration::seconds(60 * 4))
.0,
// start: NaiveTime::from_hms(5, 1, 0),
// end: NaiveTime::from_hms(7, 0, 0),
in_color: colors::GREEN,
name: "5:1->7:0",
},
TimeRange {
start: time
.overflowing_add_signed(chrono::Duration::seconds(60 * 5))
.0,
end: time
.overflowing_add_signed(chrono::Duration::seconds(60 * 6))
.0,
// start: NaiveTime::from_hms(7, 1, 0),
// end: NaiveTime::from_hms(23, 59, 0),
in_color: colors::BLUE,
name: "7:1->23:59",
},
];
#[cfg(feature = "testranges")]
{
ranges = [
TimeRange {
start: time
.overflowing_add_signed(chrono::Duration::seconds(60 * 1))
.0,
end: time
.overflowing_add_signed(chrono::Duration::seconds(60 * 2))
.0,
// start: NaiveTime::from_hms(0, 0, 0),
// end: NaiveTime::from_hms(5, 0, 0),
in_color: colors::RED,
name: "0:0->5:0",
},
TimeRange {
start: time
.overflowing_add_signed(chrono::Duration::seconds(60 * 3))
.0,
end: time
.overflowing_add_signed(chrono::Duration::seconds(60 * 4))
.0,
// start: NaiveTime::from_hms(5, 1, 0),
// end: NaiveTime::from_hms(7, 0, 0),
in_color: colors::GREEN,
name: "5:1->7:0",
},
];
}
let mut state = FSMState::Idle;
let mut found = false;
let mut next_or_current_range = 0;
#[cfg(not(feature = "testranges"))]
{
ranges = [
TimeRange {
start: NaiveTime::from_hms(20, 0, 0),
end: NaiveTime::from_hms(7, 30, 0),
in_color: colors::PINK,
name: "night",
},
TimeRange {
start: NaiveTime::from_hms(14, 00, 0),
end: NaiveTime::from_hms(16, 0, 0),
in_color: colors::PINK,
name: "nap",
},
];
}
state = FSMState::Idle;
let mut found = false;
next_or_current_range = 0;
for (i, range) in ranges.iter().enumerate() {
next_or_current_range = i;
let mut current_color = &IDLE_COLOR;
debug_only! {
hprintln!(
"Testing range #{}",
i
"Testing with time #{:?}",
time
).unwrap()
}
if time < range.start {
state = FSMState::WaitNextRange(i);
for (i, range) in ranges.iter().enumerate() {
next_or_current_range = i;
debug_only! {
hprintln!(
"Waiting for next range to activate: {} -> {}",
"Testing range #{}: {} -> {}",
i,
range.start,
range.end
).unwrap()
}
rtc.set_alarm1_hms(range.start).unwrap();
found = true;
break;
}
if time < range.start {
state = FSMState::WaitNextRange(i);
debug_only! {
hprintln!(
"Waiting for next range to activate: {} -> {}",
range.start,
range.end
).unwrap()
}
transition_leds::spawn(colors::GREEN, 50).unwrap();
rtc.set_alarm1_hms(range.start).unwrap();
found = true;
break;
}
transition_leds::spawn(colors::GREEN, 50).unwrap();
if time >= range.start && time < range.end {
state = FSMState::InRange(i);
debug_only! {hprintln!("In range: {}:{}", range.start, range.end).unwrap()}
if time >= range.start && time < range.end {
state = FSMState::InRange(i);
debug_only! {hprintln!("In range: {}:{}", range.start, range.end).unwrap()}
transition_leds::spawn(range.in_color, 50).unwrap();
transition_leds::spawn(range.in_color, 50).unwrap();
rtc.set_alarm1_hms(range.end).unwrap();
rtc.set_alarm1_hms(range.end).unwrap();
found = true;
break;
found = true;
break;
}
}
}
if !found {
next_or_current_range = 0;
if !found {
next_or_current_range = 0;
debug_only! {hprintln!(
"Next alarm is tomorrow: {}:{}",
ranges[0].start,
ranges[0].end
)
.unwrap()}
rtc.set_alarm1_hms(ranges[0].start).unwrap();
debug_only! {hprintln!(
"Next alarm is tomorrow: {}:{}",
ranges[0].start,
ranges[0].end
)
.unwrap()}
rtc.set_alarm1_hms(ranges[0].start).unwrap();
}
#[cfg(feature = "epd")]
epd.update_and_display_frame(&mut spi0, &display.buffer())
.unwrap();
// enable partial refresh from now on
#[cfg(feature = "epd")]
epd.set_refresh(&mut spi0, &mut delay, RefreshLUT::QUICK)
.unwrap();
}
epd.update_and_display_frame(&mut spi0, &display.buffer())
.unwrap();
#[cfg(feature = "bme")]
refresh_bme680::spawn(false).unwrap();
// enable partial refresh from now on
epd.set_refresh(&mut spi0, &mut delay, RefreshLUT::QUICK)
.unwrap();
let is_rot_switch_pressed = rotary_pin.is_low().unwrap();
let rotary_switch = RotarySwitchT::new(rotary_pin, is_rot_switch_pressed);
let rotary_pin = portb.pb7.into_pull_up_input();
let init_state = rotary_pin.is_high().unwrap();
let rotary_switch = RotarySwitchT::new(rotary_pin, init_state);
debug_only! {
hprintln!("init switch {:?}", is_rot_switch_pressed).unwrap()
}
// switch is using PUR, is_low() <=> pressed <=> 'true' state
let toggle_pin = portb.pb5.into_pull_up_input();
@ -660,25 +723,39 @@ mod app {
mode: OperatingMode::Normal,
submode: SubConfig::Hour,
#[cfg(feature = "rtc")]
rtc,
#[cfg(feature = "epd")]
screen: Screen {
epd,
spi: spi0,
delay,
quick_refresh_count: 0,
},
display,
#[cfg(feature = "rtc")]
rtc_int_pin,
leds,
leds_data: [colors::BLACK; NUM_LEDS],
#[cfg(feature = "bme")]
bme680,
#[cfg(feature = "rtc")]
ranges,
#[cfg(feature = "rtc")]
next_or_current_range,
#[cfg(feature = "rtc")]
state,
rotary,
#[cfg(feature = "rtc")]
new_time: NaiveTime::from_hms(0, 0, 0),
i2c_error: 0,
@ -694,10 +771,13 @@ mod app {
// relying on the naive Delay implementation counting some nop. If they are
// interrupted, timing will be incorrect.
#[cfg(feature = "epd")]
#[task(priority = 5, resources = [screen, display])]
fn refresh_epd(cx: refresh_epd::Context) {
fn refresh_epd(cx: refresh_epd::Context, mode_hint: EPDModeHint) {
(cx.resources.screen, cx.resources.display).lock(|screen, display| {
let do_full_refresh = screen.quick_refresh_count > MAX_NUM_QUICK_REFRESH;
let do_full_refresh = (screen.quick_refresh_count > MAX_NUM_QUICK_REFRESH
&& mode_hint != EPDModeHint::ForcePartial)
|| mode_hint == EPDModeHint::ForceFull;
let mut errcnt_s: String<U5> = String::new();
uwrite!(errcnt_s, "#{}", screen.quick_refresh_count).unwrap();
@ -736,6 +816,7 @@ mod app {
});
}
#[cfg(feature = "bme")]
#[task(priority = 5, resources = [display, bme680, i2c_error])]
fn refresh_bme680(cx: refresh_bme680::Context, refresh_epd: bool) {
(cx.resources.bme680, cx.resources.i2c_error, cx.resources.display ).lock(|bme680, i2c_error, display| {
@ -830,12 +911,11 @@ mod app {
.draw(display);
});
if refresh_epd {
refresh_epd::spawn().unwrap();
#[cfg(feature = "epd")]
refresh_epd::spawn(EPDModeHint::None).unwrap();
}
}
// Priority 4 tasks
//
// These must be executed ASAP: change mode and ISR.
@ -859,51 +939,54 @@ mod app {
}
match mode {
OperatingMode::Normal => {
OperatingMode::Normal => {
ctx.resources.display.lock(|mut display| {
draw_config_hint(&mut display, false);
});
let copy_new_time = ctx.resources.new_time.lock(|t| *t);
ctx.resources.rtc.lock(|rtc| {
rtc.set_time(&copy_new_time).unwrap();
rtc.clear_alarm2_matched_flag().unwrap();
rtc.clear_alarm1_matched_flag().unwrap();
});
// Monitor alarms from RTC
ctx.resources.rtc_int_pin.lock(|p| {
p.clear_interrupt();
p.set_interrupt_mode(InterruptMode::EdgeFalling);
});
#[cfg(feature = "rtc")]
{
let copy_new_time = ctx.resources.new_time.lock(|t| *t);
ctx.resources.rtc.lock(|rtc| {
rtc.set_time(&copy_new_time).unwrap();
rtc.clear_alarm2_matched_flag().unwrap();
rtc.clear_alarm1_matched_flag().unwrap();
});
// Monitor alarms from RTC
ctx.resources.rtc_int_pin.lock(|p| {
p.clear_interrupt();
p.set_interrupt_mode(InterruptMode::EdgeFalling);
});
}
// Disable anything comming from rotary switch
// ctx.resources.rotary_switch.lock(|rs| {
// rs.pin.set_interrupt_mode(InterruptMode::Disabled);
// });
}
OperatingMode::Configuration => {
let cur_time = ctx.resources.rtc.lock(|rtc| rtc.get_time().unwrap());
ctx.resources.new_time.lock(|t| {
*t = cur_time;
});
ctx.resources.display.lock(|display| {
draw_config_hint(display, true);
});
#[cfg(feature = "rtc")]
{
let cur_time = ctx.resources.rtc.lock(|rtc| rtc.get_time().unwrap());
ctx.resources.new_time.lock(|t| {
*t = cur_time;
});
ctx.resources.display.lock(|display| {
draw_config_hint(display, true);
});
// Do not monitor alarms from RTC
ctx.resources
.rtc_int_pin
.lock(|p| p.set_interrupt_mode(InterruptMode::Disabled));
}
rotary_sampling::spawn(true).unwrap();
// Do not monitor alarms from RTC
ctx.resources
.rtc_int_pin
.lock(|p| p.set_interrupt_mode(InterruptMode::Disabled));
refresh_during_configuration::spawn().unwrap();
}
}
// refresh_epd::spawn().unwrap();
}
#[task(priority = 4, binds = GPIOB, resources = [toggle_switch])]
fn gpiob(mut cx: gpiob::Context) {
debug_only! {hprintln!("toggle switch IT raised!").unwrap()}
@ -924,6 +1007,7 @@ mod app {
});
}
#[cfg(feature = "rtc")]
#[task(priority = 4, binds = GPIOD, resources = [rtc, mode, rtc_int_pin])]
fn gpiod(mut cx: gpiod::Context) {
let mut a1 = false;
@ -952,10 +1036,14 @@ mod app {
.mode
.lock(|mode| a2 && *mode == OperatingMode::Normal)
{
#[cfg(feature = "bme")]
refresh_bme680::spawn(false).unwrap();
#[cfg(feature = "rtc")]
refresh_time::spawn(time, false).unwrap();
}
refresh_epd::spawn().unwrap();
#[cfg(feature = "epd")]
refresh_epd::spawn(EPDModeHint::None).unwrap();
debug_only! {hprintln!("hep").unwrap()}
}
@ -964,6 +1052,30 @@ mod app {
//
// These are not really critical and can afford being preempted.
// Mostly the polling tasks.
#[task(
priority = 3,
resources = [mode, new_time],
)]
fn refresh_during_configuration(mut ctx: refresh_during_configuration::Context) {
let scheduled = Instant::now(); // ctx.scheduled;
#[cfg(feature = "rtc")]
let newtime = ctx.resources.new_time.lock(|nt| *nt);
ctx.resources.mode.lock(|mode| {
if *mode == OperatingMode::Configuration {
#[cfg(feature = "rtc")]
refresh_time::spawn(newtime, false).unwrap();
refresh_during_configuration::schedule(scheduled + (2 * ONE_SEC).cycles()).unwrap();
#[cfg(feature = "epd")]
refresh_epd::spawn(EPDModeHint::ForcePartial).unwrap();
}
});
}
#[task(
priority = 3,
resources = [mode, toggle_switch],
@ -1000,23 +1112,22 @@ mod app {
}
});
}
#[cfg(feature = "rtc")]
#[task(priority = 3, resources = [rtc, ranges, state, next_or_current_range])]
fn handle_event_alarm(cx: handle_event_alarm::Context) {
debug_only! {hprintln!("handle event alarm!").unwrap()}
(cx.resources.state, cx.resources.ranges , cx.resources.rtc).lock(|state, ranges, rtc| {
(cx.resources.state, cx.resources.ranges, cx.resources.rtc).lock(|state, ranges, rtc| {
let ns = match state {
FSMState::Idle => None,
FSMState::WaitNextRange(ref range) => {
debug_only! {hprintln!("Enter").unwrap()}
transition_leds::spawn(ranges[*range].in_color, TRANSITION_STEPS)
.unwrap();
transition_leds::spawn(ranges[*range].in_color, TRANSITION_STEPS).unwrap();
debug_only! {hprintln!("Alarm :{}", ranges[*range].end).unwrap()}
rtc
.set_alarm1_hms(ranges[*range].end)
.unwrap();
rtc.set_alarm1_hms(ranges[*range].end).unwrap();
Some(FSMState::InRange(*range))
}
@ -1027,14 +1138,10 @@ mod app {
transition_leds::spawn(colors::GREEN, 50).unwrap();
if *range == ranges.len() - 1 {
rtc
.set_alarm1_hms(ranges[0].start)
.unwrap();
rtc.set_alarm1_hms(ranges[0].start).unwrap();
Some(FSMState::WaitNextRange(0))
} else {
rtc
.set_alarm1_hms(ranges[*range + 1].start)
.unwrap();
rtc.set_alarm1_hms(ranges[*range + 1].start).unwrap();
Some(FSMState::WaitNextRange(*range + 1))
}
}
@ -1046,7 +1153,6 @@ mod app {
});
}
#[task(priority = 3, capacity = 2, resources = [display])]
fn refresh_time(mut cx: refresh_time::Context, time: NaiveTime, refresh_epd: bool) {
cx.resources.display.lock(|display| {
@ -1075,25 +1181,29 @@ mod app {
});
if refresh_epd {
refresh_epd::spawn().unwrap();
#[cfg(feature = "epd")]
refresh_epd::spawn(EPDModeHint::None).unwrap();
}
}
#[task(priority = 3,
resources =[mode, submode, rotary, rotary_switch, new_time])]
fn rotary_sampling(cx: rotary_sampling::Context, first: bool) {
fn rotary_sampling(mut cx: rotary_sampling::Context, first: bool) {
if first {
debug_only! {hprintln!("rotary sampling").unwrap()}
}
let scheduled = Instant::now() ; //cx.scheduled;
let scheduled = Instant::now(); //cx.scheduled;
#[cfg(feature = "rtc")]
let mut new_time = cx.resources.new_time.lock(|t| *t);
(
cx.resources.mode,
cx.resources.submode,
cx.resources.rotary_switch,
cx.resources.rotary,
cx.resources.new_time,
)
.lock(|mode, submode, rs, r, new_time| {
.lock(|mode, submode, rs, r| {
let current_mode = *mode;
match current_mode {
@ -1114,24 +1224,27 @@ mod app {
};
let add = match *submode {
SubConfig::Hour => chrono::Duration::hours(1*sign),
SubConfig::Minute => chrono::Duration::minutes(1*sign),
SubConfig::Hour => chrono::Duration::hours(1 * sign),
SubConfig::Minute => chrono::Duration::minutes(1 * sign),
};
*new_time = new_time
.overflowing_add_signed(add)
.0;
#[cfg(feature = "rtc")]
{
new_time = new_time.overflowing_add_signed(add).0;
}
// Should be quick as EDP in partial refresh during configuration.
refresh_time::spawn(*new_time, true).unwrap();
debug_only! {hprintln!("knob turned").unwrap()}
// Should be quick as EPD in partial refresh during configuration.
// refresh_time::spawn(*new_time, false).unwrap();
}
Direction::None => {}
}
// Refresh switch and maybe spawn handler
let pressed: bool = rs.pin.is_low().unwrap();
let edge = rs.debouncer.update(pressed);
let edge = rs.debouncer.update(pressed);
// debug_only! {hprintln!("rotary switch status {:?}", pressed).unwrap()}
// Dispatch event
if edge == Some(Edge::Rising) {
debug_only! {hprintln!("rotary PRESSED").unwrap()}
@ -1152,6 +1265,9 @@ mod app {
}
}
});
#[cfg(feature = "rtc")]
cx.resources.new_time.lock(|t| *t = new_time);
}
// Priority 1 tasks.
@ -1221,7 +1337,6 @@ mod app {
// refresh_leds::spawn().unwrap();
// }
// #[task(capacity = 10, priority = 1, resources =[rtc, new_time, submode])]
// fn knob_turned(cx: knob_turned::Context, dir: Direction) {
// (cx.resources.submode, cx.resources.new_time).lock(|submode, new_time| {
@ -1229,7 +1344,6 @@ mod app {
// });
// }
}
fn draw_config_hint(display: &mut Display2in13, is_config: bool) {

Loading…
Cancel
Save