Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

私の解答

#![deny(unsafe_code)]
#![no_main]
#![no_std]

use cortex_m_rt::entry;
use rtt_target::{rtt_init_print, rprintln};
use panic_rtt_target as _;

#[cfg(feature = "v1")]
use microbit::{
    hal::twi,
    pac::twi0::frequency::FREQUENCY_A,
};

#[cfg(feature = "v2")]
use microbit::{
    hal::twim,
    pac::twim0::frequency::FREQUENCY_A,
};

use lsm303agr::{
    AccelScale, AccelOutputDataRate, Lsm303agr,
};

use microbit::hal::timer::Timer;
use microbit::hal::prelude::*;
use nb::Error;

#[entry]
fn main() -> ! {
    const THRESHOLD: f32 = 0.5;

    rtt_init_print!();
    let board = microbit::Board::take().unwrap();

    #[cfg(feature = "v1")]
    let i2c = { twi::Twi::new(board.TWI0, board.i2c.into(), FREQUENCY_A::K100) };

    #[cfg(feature = "v2")]
    let i2c = { twim::Twim::new(board.TWIM0, board.i2c_internal.into(), FREQUENCY_A::K100) };

    let mut countdown = Timer::new(board.TIMER0);
    let mut delay = Timer::new(board.TIMER1);
    let mut sensor = Lsm303agr::new_with_i2c(i2c);
    sensor.init().unwrap();
    sensor.set_accel_odr(AccelOutputDataRate::Hz50).unwrap();
    // 人のパンチは実際かなり速くなり得るため、センサーが最大 16 G まで
    // 測定できるようにする
    sensor.set_accel_scale(AccelScale::G16).unwrap();

    let mut max_g = 0.;
    let mut measuring = false;

    loop {
        while !sensor.accel_status().unwrap().xyz_new_data {}
        // x 軸の加速度(g)
        let g_x = sensor.accel_data().unwrap().x as f32 / 1000.0;

        if measuring {
            // カウントダウンの状態を確認する
            match countdown.wait() {
                // カウントダウンはまだ完了していない
                Err(Error::WouldBlock) => {
                    if g_x > max_g {
                        max_g = g_x;
                    }
                },
                // カウントダウンが完了した
                Ok(_) => {
                    // 最大値を報告する
                    rprintln!("最大加速度: {}g", max_g);

                    // リセット
                    max_g = 0.;
                    measuring = false;
                },
                // nrf52 と nrf51 の HAL ではエラー型として Void を使用しているため
                // Void は空型なので、この経路は発生しない
                Err(Error::Other(_)) => {
                    unreachable!()
                }
            }
        } else {
            // 加速度がしきい値を超えたら、測定を開始する
            if g_x > THRESHOLD {
                rprintln!("開始!");

                measuring = true;
                max_g = g_x;
                // ドキュメントによると、このタイマーは 1 MHz の周波数で動作するため、
                // 1 秒待機するには
                // 1_000_000 ティックに設定する必要がある。
                countdown.start(1_000_000_u32);
            }
        }
        delay.delay_ms(20_u8);
    }
}