diff --git a/kuboble-pygamer/Cargo.toml b/kuboble-pygamer/Cargo.toml index a5d7299..b587f7f 100644 --- a/kuboble-pygamer/Cargo.toml +++ b/kuboble-pygamer/Cargo.toml @@ -3,18 +3,22 @@ edition = "2021" name = "kuboble-pygamer" version = "0.1.0" +[patch.crates-io] +# Needed currently due to unpublished updated +pygamer = {path = "../../atsamd/boards/pygamer"} + [dependencies] cortex-m = {version = "0.7.7", features = ["critical-section-single-core"]} derive-new = "0.7.0" embedded-graphics = "0.7.1" kuboble-core = {path = "../kuboble-core"} -pygamer = {version = "0.9.0", features = ["panic_led", "rt"]} +pygamer = {version = "0.10.0", features = ["panic_led"]} pygamer-engine = {path = "../pygamer-engine"} rtic = {version = "2.1.1", features = ["thumbv7-backend"]} rtic-monotonics = {version = "2.0.2", features = ["cortex-m-systick"]} -smart-leds = "0.3.0" +smart-leds = "0.4.0" st7735-lcd = "0.8.1" -ws2812-timer-delay = "0.3.0" +ws2812-spi = "0.5.0" [features] unlocked = ["kuboble-core/unlocked"] diff --git a/kuboble-pygamer/src/controls.rs b/kuboble-pygamer/src/controls.rs index 1c9d7d9..645afd1 100644 --- a/kuboble-pygamer/src/controls.rs +++ b/kuboble-pygamer/src/controls.rs @@ -1,11 +1,10 @@ use core::cell::RefCell; use kuboble_core::level_run::Direction; -use pygamer::adc::Adc; -use pygamer::delay::Delay; +use pygamer::hal::adc::Adc; +use pygamer::hal::delay::Delay; use pygamer::pac::ADC1; use pygamer::pins::{ButtonReader, JoystickReader, Keys}; -use pygamer::prelude::*; use pygamer_engine::{ControlAction, Controller, GameResult}; const JOYSTICK_THRESH: i16 = 1024; diff --git a/kuboble-pygamer/src/main.rs b/kuboble-pygamer/src/main.rs index d2af899..cc06c99 100644 --- a/kuboble-pygamer/src/main.rs +++ b/kuboble-pygamer/src/main.rs @@ -2,33 +2,28 @@ #![no_main] #![feature(let_chains)] -use controls::PyGamerController; -use core::cell::RefCell; -use kuboble_core::level_select::LevelProgress; -use output::PyGamerOutput; -use pac::{CorePeripherals, Peripherals}; -use pygamer::adc::Adc; -use pygamer::clock::GenericClockController; -use pygamer::delay::Delay; -use pygamer::pac::gclk::pchctrl::GEN_A; -use pygamer::sleeping_delay::SleepingDelay; -use pygamer::timer::SpinTimer; -use pygamer::{entry, pac, Pins}; -use pygamer_engine::run_game; use rtic_monotonics::systick::prelude::*; -mod controls; +//mod controls; mod output; systick_monotonic!(Mono, 1000); #[rtic::app(device = pygamer::pac, dispatchers = [TC0])] mod app { - use pygamer::{delay::Delay, timer::SpinTimer, Pins}; - use rtic_monotonics::Monotonic; + use embedded_graphics::{pixelcolor::Rgb565, prelude::RgbColor}; + use pygamer::{ + hal::{ + clock::GenericClockController, + delay::Delay, + sercom::{spi, IoSet1, Sercom2}, + time::Hertz, + }, + Pins, + }; use crate::{ - output::{self, neopixels_test, DisplayDriver, NeoPixels}, + output::{self, DisplayDriver, NeoPixels}, Mono, }; @@ -37,7 +32,7 @@ mod app { #[local] struct Local { - neopixels: NeoPixels, + //neopixels: NeoPixels, np_color: bool, display: DisplayDriver, } @@ -45,7 +40,7 @@ mod app { #[init] 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( + let mut clocks = GenericClockController::with_internal_32kosc( cx.device.GCLK, &mut cx.device.MCLK, &mut cx.device.OSC32KCTRL, @@ -56,7 +51,7 @@ mod app { let mut delay = Delay::new(cx.core.SYST, &mut clocks); // Initialize the display - let (display, _backlight) = pins + let (mut display, _backlight) = pins .display .init( &mut clocks, @@ -64,29 +59,46 @@ mod app { &mut cx.device.MCLK, cx.device.TC2, &mut delay, - &mut pins.port, ) .unwrap(); + output::wtf(&mut display); + panic!(); + // 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 - // here: https://github.com/atsamd-rs/atsamd/blob/master/boards/pygamer/examples/neopixel_rainbow_spi.rs - // Maybe look back into this later so we don't have to use the deprecated SpinTimer. - /* let tc4_clock = clocks.tc4_tc5(&clocks.gclk0()).unwrap(); - let mut neopixels_timer = TimerCounter::tc4_(&tc4_clock, peripherals.TC4, &mut peripherals.MCLK); - neopixels_timer.start(3.mhz()); */ - let neopixels_timer = SpinTimer::new(4); + // Currently in the `pygamer` examples there are no neopixel examples, because the timers are too jittery + // and are not reliable. + // `SpinTimer` seemed to work well but this has been fully deprecated and removed. + // `TimeCounter` was jittery and did not work well. + // Using a luckily placed SPI pin TODO. + // TODO: Once this is resolved, switch to the best method, check here for new examples: https://github.com/atsamd-rs/atsamd/tree/master/boards/pygamer/examples + /*let mut neopixels_timer = + TimerCounter::tc4_(&tc4_clock, cx.device.TC4, &mut cx.device.MCLK); + neopixels_timer.start(3.mhz()); let neopixels = pins.neopixel.init(neopixels_timer, &mut pins.port); + let neopixels = pins.neopixel.init(); */ + /* let config = spi::Config::new( + &cx.device.MCLK, + cx.device.SERCOM2, + spi::Pads::::default() + .data_in(pins.i2c.sda) + .data_out(pins.neopixel.neopixel) + .sclk(pins.i2c.scl), + Hertz::MHz(3), + ); + let mut neopixels = ws2812_spi::Ws2812::new(config.enable()); + output::neopixels_test(&mut neopixels, true); + panic!(); */ - display_test::spawn().unwrap_or_else(|_| panic!()); + display_test::spawn().unwrap(); ( Shared {}, Local { - neopixels, + //neopixels, display, np_color: false, }, @@ -98,7 +110,7 @@ mod app { output::display_test(cx.local.display).await } - #[idle(local = [np_color, neopixels])] + /* #[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; @@ -107,12 +119,12 @@ mod app { // _cx.local.local_to_bar += 1; let color = *cx.local.np_color; - neopixels_test(cx.local.neopixels, color); + //neopixels_test(cx.local.neopixels, color); loop { *cx.local.np_color = !color; rtic::export::wfi(); } - } + } */ } /* #[entry] diff --git a/kuboble-pygamer/src/output.rs b/kuboble-pygamer/src/output.rs index 085f336..4c81612 100644 --- a/kuboble-pygamer/src/output.rs +++ b/kuboble-pygamer/src/output.rs @@ -1,40 +1,40 @@ -use core::iter::{repeat, repeat_n}; - use crate::Mono; use embedded_graphics::pixelcolor::Rgb565; use embedded_graphics::prelude::*; use embedded_graphics::primitives::PrimitiveStyle; -use kuboble_core::{LevelRating, Piece}; -use pygamer::gpio::v2::PA15; -use pygamer::gpio::Pin; -use pygamer::hal::hal::digital::v1_compat::OldOutputPin; -use pygamer::hal::hal::timer::{CountDown, Periodic}; -use pygamer::{ - gpio::v2::{Alternate, Output, PushPull, C, PA00, PB05, PB13, PB14, PB15}, - pac::SERCOM4, - sercom::{ - v2::{Pad1, Pad2, Pad3}, - Pad, SPIMaster4, - }, +use kuboble_core::Piece; +use pygamer::hal::gpio::{ + Alternate, Output, Pin, PushPull, C, PA00, PA12, PA13, PA15, PB05, PB13, PB15, }; -use pygamer_engine::{BufferedDisplay, GameDisplay, GameIndicator, GameOutput}; -use rtic_monotonics::rtic_time::embedded_hal::delay::DelayNs; +use pygamer::hal::sercom::spi::{Config, Duplex, Pads, Spi, Tx}; +use pygamer::hal::sercom::IoSet1; +use pygamer::hal::typelevel::NoneT; +use pygamer::pac::{SERCOM2, SERCOM4}; +use pygamer::{TftDc, TftReset, TftSpi}; use rtic_monotonics::systick::prelude::*; use rtic_monotonics::Monotonic; use smart_leds::{SmartLedsWrite, RGB}; -use ws2812_timer_delay::Ws2812; pub type DisplayDriver = st7735_lcd::ST7735< - SPIMaster4< - Pad>>, - Pad>>, - Pad>>, - >, + Spi>, Pin>>>, Tx>, Pin>, Pin>, >; -pub type NeoPixels = Ws2812>>>; +pub type NeoPixels = ws2812_spi::Ws2812< + Spi< + Config< + Pads< + SERCOM2, + IoSet1, + Pin>, + Pin>, + Pin>, + >, + >, + Duplex, + >, +>; trait PieceExt { fn neopixel_color(&self) -> RGB; @@ -51,16 +51,23 @@ impl PieceExt for Piece { const STAR_COLOR: RGB = RGB::new(4, 4, 0); -pub fn neopixels_test(neopixels: &mut NeoPixels, color: bool) { - loop { - let colors = if color { - [Piece::Green.neopixel_color(), RGB::default()] - } else { - [Piece::Orange.neopixel_color(), RGB::default()] - }; +pub fn neopixels_test(neopixels: &mut NeoPixels, color: bool) { + 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(); - } + neopixels.write(colors.into_iter().cycle().take(5)).unwrap(); +} + +// TODO +pub fn wtf(display: &mut DisplayDriver) { + display.clear(Rgb565::WHITE).unwrap(); + embedded_graphics::primitives::Rectangle::new(Point::zero(), Size::new(100, 100)) + .into_styled(PrimitiveStyle::with_fill(Rgb565::CSS_DARK_BLUE)) + .draw(display) + .unwrap(); } pub async fn display_test(display: &mut DisplayDriver) -> ! { @@ -70,16 +77,16 @@ pub async fn display_test(display: &mut DisplayDriver) -> ! { .into_styled(PrimitiveStyle::with_fill(Rgb565::CSS_DARK_BLUE)) .draw(display) .unwrap(); - Mono::delay(2000.millis()).await; + Mono::delay(2.secs()).await; embedded_graphics::primitives::Rectangle::new(Point::zero(), Size::new(100, 100)) .into_styled(PrimitiveStyle::with_fill(Rgb565::CSS_DARK_RED)) .draw(display) .unwrap(); - Mono::delay(2000.millis()).await; + Mono::delay(2.secs()).await; } } - +/* pub struct PyGamerOutput { display: DisplayDriver, buffer: BufferedDisplay, @@ -146,3 +153,4 @@ impl GameDisplay for PyGamerOutput { impl GameOutput for PyGamerOutput { const SLIDE_SPEED: i32 = 14; } + */