Skip to content

Commit

Permalink
Changes kuboble-pygamer to be able to check for idle efficiency by …
Browse files Browse the repository at this point in the history
…changing the NeoPixel colors each time the idle function is called.

Note that efficiency is very bad using the `SysTick` RTIC monotonic driver.
  • Loading branch information
kyp44 committed Oct 4, 2024
1 parent 7160604 commit 8d9551f
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 55 deletions.
1 change: 1 addition & 0 deletions kuboble-pygamer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/vendor
80 changes: 43 additions & 37 deletions kuboble-pygamer/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,44 +24,52 @@ systick_monotonic!(Mono, 1000);

#[rtic::app(device = pygamer::pac, dispatchers = [TC0])]
mod app {
use crate::{output, Mono};
use pygamer::{delay::Delay, timer::SpinTimer, Pins};
use rtic_monotonics::Monotonic;

use crate::{
output::{self, neopixels_test, DisplayDriver, NeoPixels},
Mono,
};

#[shared]
struct Shared {}

#[local]
struct Local {}
struct Local {
neopixels: NeoPixels<SpinTimer>,
np_color: bool,
display: DisplayDriver,
}

#[init]
fn init(cx: init::Context) -> (Shared, Local) {
fn init(mut cx: init::Context) -> (Shared, Local) {
// Get the peripherals and pins and setup clocks
let mut clocks = pygamer::clock::GenericClockController::with_internal_32kosc(
peripherals.GCLK,
&mut peripherals.MCLK,
&mut peripherals.OSC32KCTRL,
&mut peripherals.OSCCTRL,
&mut peripherals.NVMCTRL,
cx.device.GCLK,
&mut cx.device.MCLK,
&mut cx.device.OSC32KCTRL,
&mut cx.device.OSCCTRL,
&mut cx.device.NVMCTRL,
);
let mut pins = Pins::new(peripherals.PORT).split();
// TODO: use sleeping delay here for battery life? Evidently worth it even for delays of like 50ms
//let x = SleepingDelay::new();
let mut delay = Delay::new(core.SYST, &mut clocks);
let mut pins = Pins::new(cx.device.PORT).split();
let mut delay = Delay::new(cx.core.SYST, &mut clocks);

// Initialize the display
let (display, _backlight) = pins
.display
.init(
&mut clocks,
peripherals.SERCOM4,
&mut peripherals.MCLK,
peripherals.TC2,
cx.device.SERCOM4,
&mut cx.device.MCLK,
cx.device.TC2,
&mut delay,
&mut pins.port,
)
.unwrap();

// Need to share the delay
let delay = RefCell::new(delay);
// Start the monotonic
Mono::start(delay.free(), 120_000_000);

// Set up the neo-pixels driver
// Note: This is the non-deprecated way but is jittery as commented in the example
Expand All @@ -73,38 +81,36 @@ mod app {
let neopixels_timer = SpinTimer::new(4);
let neopixels = pins.neopixel.init(neopixels_timer, &mut pins.port);

neopixels_test::spawn(0).unwrap();
display_test::spawn().unwrap();

Mono::start(cx.core.SYST, 12_000_000);
display_test::spawn().unwrap_or_else(|_| panic!());

(Shared {}, Local {})
}

#[task(priority = 1)]
async fn neopixels_test(
_: neopixels_test::Context,
mut neopixels: crate::output::NeoPixels<pygamer::timer::SpinTimer>,
) {
output::neopixels_test(neopixels).await
(
Shared {},
Local {
neopixels,
display,
np_color: false,
},
)
}

#[task(priority = 1)]
async fn display_test(_: display_test::Context, mut display: output::DisplayDriver) {
output::display_test(display).await
#[task(priority = 1, local = [display])]
async fn display_test(cx: display_test::Context) {
output::display_test(cx.local.display).await
}

// TODO: Do a test about idle if there are suspended higher priority software tasks
#[idle]
#[idle(local = [np_color, neopixels])]
fn idle(cx: idle::Context) -> ! {
// error: no `local_to_foo` field in `idle::LocalResources`
// _cx.local.local_to_foo += 1;

// error: no `local_to_bar` field in `idle::LocalResources`
// _cx.local.local_to_bar += 1;
let color = *cx.local.np_color;

neopixels_test(cx.local.neopixels, color);
loop {
cortex_m::asm::nop();
*cx.local.np_color = !color;
rtic::export::wfi();
}
}
}
Expand All @@ -122,7 +128,7 @@ fn main() -> ! {
&mut peripherals.NVMCTRL,
);
let mut pins = Pins::new(peripherals.PORT).split();
// TODO: use sleeping delay here for battery life? Evidently worth it even for delays of like 50ms
//let x = SleepingDelay::new();
let mut delay = Delay::new(core.SYST, &mut clocks);
Expand Down
30 changes: 12 additions & 18 deletions kuboble-pygamer/src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,38 +51,32 @@ impl PieceExt for Piece {

const STAR_COLOR: RGB<u8> = RGB::new(4, 4, 0);

pub async fn neopixels_test(mut neopixels: NeoPixels<pygamer::timer::SpinTimer>) -> ! {
pub fn neopixels_test(neopixels: &mut NeoPixels<pygamer::timer::SpinTimer>, color: bool) {
loop {
let colors = [Piece::Green.neopixel_color(), RGB::default()];
let colors = if color {
[Piece::Green.neopixel_color(), RGB::default()]
} else {
[Piece::Orange.neopixel_color(), RGB::default()]
};

neopixels.write(colors.into_iter().cycle().take(5)).unwrap();
Mono::delay(500.millis()).await;

let colors = [Piece::Orange.neopixel_color(), RGB::default()];

neopixels.write(colors.into_iter().cycle().take(5)).unwrap();
Mono::delay(500.millis()).await;

let colors = [Piece::Blue.neopixel_color(), RGB::default()];

neopixels.write(colors.into_iter().cycle().take(5)).unwrap();
Mono::delay(500.millis()).await;
}
}

pub async fn display_test(mut display: DisplayDriver) -> ! {
pub async fn display_test(display: &mut DisplayDriver) -> ! {
display.clear(Rgb565::WHITE).unwrap();
loop {
embedded_graphics::primitives::Rectangle::new(Point::zero(), Size::new(100, 100))
.into_styled(PrimitiveStyle::with_fill(Rgb565::CSS_DARK_BLUE))
.draw(&mut display)
.draw(display)
.unwrap();
Mono::delay(750.millis()).await;
Mono::delay(2000.millis()).await;

embedded_graphics::primitives::Rectangle::new(Point::zero(), Size::new(100, 100))
.into_styled(PrimitiveStyle::with_fill(Rgb565::CSS_DARK_RED))
.draw(&mut display)
.draw(display)
.unwrap();
Mono::delay(750.millis()).await;
Mono::delay(2000.millis()).await;
}
}

Expand Down

0 comments on commit 8d9551f

Please sign in to comment.