iPod Classic: minor modifications in TIMER

The current behaviour should not change.

Change-Id: Ia8f44cdccf41dbc3881722f9aebab91de51a9bc5
This commit is contained in:
Cástor Muñoz 2014-12-01 02:33:41 +01:00
parent 8618f2c227
commit bfb63f8017
3 changed files with 24 additions and 23 deletions

View file

@ -39,19 +39,16 @@ void tick_start(unsigned int interval_in_ms)
{ {
int cycles = 10 * interval_in_ms; int cycles = 10 * interval_in_ms;
/* configure timer for 10 kHz (external source) */ /* configure timer for 10 kHz (12 MHz / 16 / 75) */
TBCMD = (1 << 1); /* TB_CLR */ TBCMD = (1 << 1); /* TB_CLR */
TBPRE = 75 - 1; /* prescaler */ /* 12 MHz / 16 / 75 = 10 KHz */ TBPRE = 75 - 1; /* prescaler */
TBCON = (0 << 13) | /* TB_INT1_EN */ TBCON = (0 << 13) | /* TB_INT1_EN */
(1 << 12) | /* TB_INT0_EN */ (1 << 12) | /* TB_INT0_EN */
(0 << 11) | /* TB_START */ (0 << 11) | /* TB_START */
(2 << 8) | /* TB_CS = PCLK / 16 */ (2 << 8) | /* TB_CS = ECLK / 16 */
(1 << 6) | /* UNKNOWN bit */ /* external 12 MHz clock (?) */ (1 << 6) | /* select ECLK (12 MHz) */
(0 << 4); /* TB_MODE_SEL = interval mode */ (0 << 4); /* TB_MODE_SEL = interval mode */
TBDATA0 = cycles; /* set interval period */ TBDATA0 = cycles; /* set interval period */
TBCMD = (1 << 0); /* TB_EN */ TBCMD = (1 << 0); /* TB_EN */
/* enable timer interrupt */
VIC0INTENABLE = 1 << IRQ_TIMER;
} }

View file

@ -134,7 +134,7 @@ void INT_TIMER32(void) ICODE_ATTR;
void INT_TIMER32() void INT_TIMER32()
{ {
uint32_t tstat = TSTAT; uint32_t tstat = TSTAT;
/*if ((TECON >> 12) & 0x7 & (tstat >> 24)) INT_TIMERE();*/ if ((TECON >> 12) & 0x7 & (tstat >> 24)) INT_TIMERE();
if ((TFCON >> 12) & 0x7 & (tstat >> 16)) INT_TIMERF(); if ((TFCON >> 12) & 0x7 & (tstat >> 16)) INT_TIMERF();
if ((TGCON >> 12) & 0x7 & (tstat >> 8)) INT_TIMERG(); if ((TGCON >> 12) & 0x7 & (tstat >> 8)) INT_TIMERG();
if ((THCON >> 12) & 0x7 & tstat) INT_TIMERH(); if ((THCON >> 12) & 0x7 & tstat) INT_TIMERH();
@ -226,6 +226,7 @@ void system_init(void)
VIC0INTENABLE = 1 << IRQ_WHEEL; VIC0INTENABLE = 1 << IRQ_WHEEL;
VIC0INTENABLE = 1 << IRQ_ATA; VIC0INTENABLE = 1 << IRQ_ATA;
VIC1INTENABLE = 1 << (IRQ_MMC - 32); VIC1INTENABLE = 1 << (IRQ_MMC - 32);
VIC0INTENABLE = 1 << IRQ_TIMER;
VIC0INTENABLE = 1 << IRQ_TIMER32; VIC0INTENABLE = 1 << IRQ_TIMER32;
} }

View file

@ -38,8 +38,10 @@ void INT_TIMERF(void)
bool timer_set(long cycles, bool start) bool timer_set(long cycles, bool start)
{ {
int tf_en = TFCMD & (1 << 0); /* save TF_EN status */
/* stop timer */ /* stop timer */
TFCMD = (0 << 0); /* TF_ENABLE */ TFCMD = (0 << 0); /* TF_EN = disable */
/* optionally unregister any previously registered timer user */ /* optionally unregister any previously registered timer user */
if (start) { if (start) {
@ -49,33 +51,34 @@ bool timer_set(long cycles, bool start)
} }
} }
/* There is an odd behaviour when the 32-bit timers are launched
for the first time, the interrupt status bits are set and an
unexpected interrupt is generated if they are enabled. A way to
workaround this is to write the data registers before clearing
the counter. */
TFDATA0 = cycles;
TFCMD = (1 << 1); /* TF_CLR */
/* configure timer */ /* configure timer */
TFCON = (1 << 12) | /* TF_INT0_EN */ TFCON = (1 << 12) | /* TF_INT0_EN */
(4 << 8) | /* TF_CS, 4 = ECLK / 1 */ (4 << 8) | /* TF_CS = ECLK / 1 */
(1 << 6) | /* use ECLK (12MHz) */ (1 << 6) | /* select ECLK (12 MHz) */
(0 << 4); /* TF_MODE_SEL, 0 = interval mode */ (0 << 4); /* TF_MODE_SEL = interval mode */
TFPRE = 0; /* no prescaler */ TFPRE = 0; /* no prescaler */
TFDATA0 = cycles; /* set interval period */
TFCMD = (1 << 0); /* TF_ENABLE */ /* After the configuration, we must write '1' in TF_CLR to
* initialize the timer (s5l8700 DS):
* - Clear the counter register.
* - The value of TF_START is set to TF_OUT.
* - TF_DATA0 and TF_DATA1 are updated to the internal buffers.
* - Initialize the state of the previously captured signal.
*/
TFCMD = (1 << 1) | /* TF_CLR = initialize timer */
(tf_en << 0); /* TF_EN = restore previous status */
return true; return true;
} }
bool timer_start(void) bool timer_start(void)
{ {
TFCMD = (1 << 0); /* TF_ENABLE */ TFCMD = (1 << 0); /* TF_EN = enable */
return true; return true;
} }
void timer_stop(void) void timer_stop(void)
{ {
TFCMD = (0 << 0); /* TF_ENABLE */ TFCMD = (0 << 0); /* TF_EN = disable */
} }