<commit_before>use core::mem;
use core::cell::Cell;
use hil::Controller;
use hil::alarm::{Alarm, AlarmClient, Freq16KHz};
use peripheral_registers::{RTC1_BASE, RTC1};
use peripheral_interrupts::NvicIdx;
use chip;
use nvic;

fn rtc1() -> &'static RTC1 {
    unsafe { mem::transmute(RTC1_BASE as usize) }
}

pub struct Rtc {
    callback: Cell<Option<&'static AlarmClient>>
}

pub static mut RTC : Rtc = Rtc {
    callback: Cell::new(None),
};

impl Controller for Rtc {
    type Config = &'static AlarmClient;

    fn configure(&self, client: &'static AlarmClient) {
        self.callback.set(Some(client));

        // FIXME: what to do here?
        //self.start();
        // Set counter incrementing frequency to 16KHz
        // rtc1().prescaler.set(1);
    }
}

// CLEAR, STOP, START and TRIGOVRFLW tasks have up to 46us delay to process.
// See 18.1.8 "TASK and EVENT jitter/delay" on the nRF51 Reference Manual.
//
// wait_task() will delay approximately this time. For a 16 MHz CPU,
// 1us == 16 instructions (assuming each instruction takes one cycle).
#[inline(never)]
fn wait_task() {
    // The inner loop instructions are: 14 NOPs + 1 SUBS + 1 CMP
    unsafe {
        asm!(
            "movs r0, #47\n\
            1:\n\
            nop\n\
            nop\n\
            nop\n\
            nop\n\
            nop\n\
            nop\n\
            nop\n\
            nop\n\
            nop\n\
            nop\n\
            nop\n\
            nop\n\
            nop\n\
            nop\n\
            subs r0, #1\n\
            cmp r0, #0\n\
            bne.n 1b"
            : /* no output */
            : /* no input */
            : "{r0}"
        );
   }
}

const COMPARE0_EVENT: u32 = 1 << 16;

impl Rtc {

    fn start(&self) {
        nvic::clear_pending(NvicIdx::RTC1);
        nvic::enable(NvicIdx::RTC1);
        rtc1().tasks_start.set(1);
        wait_task();
    }

    fn stop(&self) {
        nvic::disable(NvicIdx::RTC1);
        rtc1().intenclr.set(COMPARE0_EVENT);
        rtc1().cc[0].set(0);
        rtc1().tasks_stop.set(1);
        wait_task();
    }

    fn is_running(&self) -> bool {
        rtc1().evten.get() & (COMPARE0_EVENT) == (COMPARE0_EVENT)
    }

    pub fn handle_interrupt(&self) {
        self.callback.get().map(|cb| {
            cb.fired();<commit_msg>Fix clobber in assembly.<commit_after>use core::mem;
use core::cell::Cell;
use hil::Controller;
use hil::alarm::{Alarm, AlarmClient, Freq16KHz};
use peripheral_registers::{RTC1_BASE, RTC1};
use peripheral_interrupts::NvicIdx;
use chip;
use nvic;

fn rtc1() -> &'static RTC1 {
    unsafe { mem::transmute(RTC1_BASE as usize) }
}

pub struct Rtc {
    callback: Cell<Option<&'static AlarmClient>>
}

pub static mut RTC : Rtc = Rtc {
    callback: Cell::new(None),
};

impl Controller for Rtc {
    type Config = &'static AlarmClient;

    fn configure(&self, client: &'static AlarmClient) {
        self.callback.set(Some(client));

        // FIXME: what to do here?
        //self.start();
        // Set counter incrementing frequency to 16KHz
        // rtc1().prescaler.set(1);
    }
}

// CLEAR, STOP, START and TRIGOVRFLW tasks have up to 46us delay to process.
// See 18.1.8 "TASK and EVENT jitter/delay" on the nRF51 Reference Manual.
//
// wait_task() will delay approximately this time. For a 16 MHz CPU,
// 1us == 16 instructions (assuming each instruction takes one cycle).
#[inline(never)]
fn wait_task() {
    // The inner loop instructions are: 14 NOPs + 1 SUBS + 1 CMP
    unsafe {
        asm!(
            "movs r0, #47\n\
            1:\n\
            nop\n\
            nop\n\
            nop\n\
            nop\n\
            nop\n\
            nop\n\
            nop\n\
            nop\n\
            nop\n\
            nop\n\
            nop\n\
            nop\n\
            nop\n\
            nop\n\
            subs r0, #1\n\
            cmp r0, #0\n\
            bne.n 1b"
            : /* no output */
            : /* no input */
            : "r0"
        );
   }
}

const COMPARE0_EVENT: u32 = 1 << 16;

impl Rtc {

    fn start(&self) {
        nvic::clear_pending(NvicIdx::RTC1);
        nvic::enable(NvicIdx::RTC1);
        rtc1().tasks_start.set(1);
        wait_task();
    }

    fn stop(&self) {
        nvic::disable(NvicIdx::RTC1);
        rtc1().intenclr.set(COMPARE0_EVENT);
        rtc1().cc[0].set(0);
        rtc1().tasks_stop.set(1);
        wait_task();
    }

    fn is_running(&self) -> bool {
        rtc1().evten.get() & (COMPARE0_EVENT) == (COMPARE0_EVENT)
    }

    pub fn handle_interrupt(&self) {
        self.callback.get().map(|cb| {
            cb.fired();
{'fraction_non_alphanumeric': 0.1426715739337519, 'fraction_numerical': 0.025546655120155876, 'mean_word_length': 1.781456953642384, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3594614', 'n_tokens_mistral': 1718, 'n_tokens_neox': 1589, 'n_words': 382}