/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2005 Jens Arnold * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include "cpu.h" #include "system.h" #include "timer.h" void IMIA4(void) __attribute__((interrupt_handler)); void IMIA4(void) { if (pfn_timer != NULL) pfn_timer(); and_b(~0x01, &TSR4); /* clear the interrupt */ } bool timer_set(long cycles, bool start) { int phi = 0; /* bits for the prescaler */ int prescale = 1; while (cycles > 0x10000) { /* work out the smallest prescaler that makes it fit */ phi++; prescale <<= 1; cycles >>= 1; } if (prescale > 8) return false; if (start) { if (pfn_unregister != NULL) { pfn_unregister(); pfn_unregister = NULL; } and_b(~0x10, &TSTR); /* Stop the timer 4 */ and_b(~0x10, &TSNC); /* No synchronization */ and_b(~0x10, &TMDR); /* Operate normally */ TIER4 = 0xF9; /* Enable GRA match interrupt */ } TCR4 = 0x20 | phi; /* clear at GRA match, set prescaler */ GRA4 = (unsigned short)(cycles - 1); if (start || (TCNT4 >= GRA4)) TCNT4 = 0; and_b(~0x01, &TSR4); /* clear an eventual interrupt */ return true; } bool timer_start(void) { IPRD = (IPRD & 0xFF0F) | 1 << 4; /* interrupt priority */ or_b(0x10, &TSTR); /* start timer 4 */ return true; } void timer_stop(void) { and_b(~0x10, &TSTR); /* stop the timer 4 */ IPRD = (IPRD & 0xFF0F); /* disable interrupt */ }