rmicrobit 1.0.1

Drivers for the micro:bit 5×5 LED display and buttons.
Documentation
use rmicrobit::display::Render;
use rmicrobit::graphics::image::GreyscaleImage;
use rmicrobit::graphics::scrolling::{Animate, ScrollingImages};
use rmicrobit::graphics::scrolling_text;

pub trait Animator {

    type Image: Render;

    fn next(&mut self);
    fn get_image(&self) -> Self::Image;

}

pub trait RefAnimator {

    type Image: Render;

    fn next(&mut self);
    fn get_image_ref(&self) -> &Self::Image;

}


struct Ticker {
    slowdown: usize,
    subtick: usize,
}

impl Ticker {

    fn reset(&mut self, slowdown: usize) {
        self.slowdown = slowdown;
        self.subtick = 0;
    }

    fn tick(&mut self) -> bool {
        self.subtick += 1;
        if self.subtick == self.slowdown {
            self.subtick = 0;
            true
        } else {
            false
        }
    }
}

impl Default for Ticker {

    fn default() -> Ticker {
        Ticker {slowdown: 1, subtick: 0}
    }

}


///////////

pub struct FunctionalAnimation {
    pub length: usize,
    pub render: fn (usize) -> GreyscaleImage,
}

impl FunctionalAnimation {
    const BLANK: FunctionalAnimation = FunctionalAnimation {
        length: 1,
        render: {
            fn blank(_index: usize) -> GreyscaleImage {GreyscaleImage::blank()};
            blank
        },
    };
}

pub struct FunctionalAnimator {
    frame_index: usize,
    animation: &'static FunctionalAnimation,
}

impl FunctionalAnimator {

    pub fn reset(&mut self, animation: &'static FunctionalAnimation) {
        self.frame_index = 0;
        self.animation = animation;
    }

}

impl Default for FunctionalAnimator {

    fn default() -> FunctionalAnimator {
        FunctionalAnimator {
            frame_index: 0,
            animation: &FunctionalAnimation::BLANK,
        }
    }

}

impl Animator for FunctionalAnimator {

    type Image = GreyscaleImage;

    fn next(&mut self) {
        self.frame_index += 1;
        if self.frame_index == self.animation.length {
            self.frame_index = 0;
        }
    }

    fn get_image(&self) -> Self::Image {
        (self.animation.render)(self.frame_index)
    }

}

///////////

#[derive(Default)]
pub struct ScrollingImageAnimator {
    ticker: Ticker,
    scroller: ScrollingImages<&'static GreyscaleImage>,
}

impl ScrollingImageAnimator {

    pub fn reset(&mut self, images: &'static [&'static GreyscaleImage], slowdown: usize) {
        self.ticker.reset(slowdown);
        self.scroller.set_images(images);
    }

}

impl RefAnimator for ScrollingImageAnimator {

    type Image = ScrollingImages<&'static GreyscaleImage>;

    fn next(&mut self) {
        if self.ticker.tick() {
            self.scroller.tick();
        }
    }

    fn get_image_ref(&self) -> &Self::Image {
        &self.scroller
    }

}


///////////

#[derive(Default)]
pub struct ScrollingStaticTextAnimator {
    ticker: Ticker,
    scroller: scrolling_text::ScrollingStaticText,
}

impl ScrollingStaticTextAnimator {

    pub fn reset(&mut self, message: &'static [u8], slowdown: usize) {
        self.ticker.reset(slowdown);
        self.scroller.set_message(message);
    }

}

impl RefAnimator for ScrollingStaticTextAnimator {

    type Image = scrolling_text::ScrollingStaticText;

    fn next(&mut self) {
        if self.ticker.tick() {
            self.scroller.tick();
        }
    }

    fn get_image_ref(&self) -> &Self::Image {
        &self.scroller
    }

}


///////////

#[derive(Default)]
pub struct ScrollingBufferedTextAnimator {
    ticker: Ticker,
    scroller: scrolling_text::ScrollingBufferedText,
}

impl ScrollingBufferedTextAnimator {

    pub fn reset(&mut self, message: &[u8], slowdown: usize) {
        self.ticker.reset(slowdown);
        self.scroller.set_message(message);
    }

}

impl RefAnimator for ScrollingBufferedTextAnimator {

    type Image = scrolling_text::ScrollingBufferedText;

    fn next(&mut self) {
        if self.ticker.tick() {
            self.scroller.tick();
        }
    }

    fn get_image_ref(&self) -> &Self::Image {
        &self.scroller
    }

}