Files
2015-09-03 01:20:11 -07:00

692 lines
20 KiB
C

/*
PokeMini - Pokémon-Mini Emulator
Copyright (C) 2009-2015 JustBurn
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 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PokeMini.h"
TMinxTimers MinxTimers;
// Calculate decrease on oscillator 1
const uint32_t MinxTimers_CalculateDecOsc1[16] = {
// Osci1 disabled
0, 0, 0, 0, 0, 0, 0, 0,
// Osci1 Enabled
(16777216/2), // 2000000 Hz
(16777216/8), // 500000 Hz
(16777216/32), // 125000 Hz
(16777216/64), // 62500 Hz
(16777216/128), // 31250 Hz
(16777216/256), // 15625 Hz
(16777216/1024), // 3906.25 Hz
(16777216/4096), // 976.5625 Hz
};
// Calculate decrease on oscillator 2
const uint32_t MinxTimers_CalculateDecOsc2[16] = {
// Osci2 disabled
0, 0, 0, 0, 0, 0, 0, 0,
// Osci2 Enabled (Aproximate values)
(16777216/122), // 32768 Hz
(16777216/244), // 16384 Hz
(16777216/488), // 8192 Hz
(16777216/977), // 4096 Hz
(16777216/1953), // 2048 Hz
(16777216/3906), // 1024 Hz
(16777216/7812), // 512 Hz
(16777216/15625) // 256 Hz
};
// Timers counting frequency table
const uint32_t MinxTimers_CountFreq[32] = {
// Osci1 disabled
0, 0, 0, 0, 0, 0, 0, 0,
// Osci1 Enabled
(4000000/2), (4000000/8), (4000000/32), (4000000/64),
(4000000/128), (4000000/256), (4000000/1024), (4000000/4096),
// Osci2 disabled
0, 0, 0, 0, 0, 0, 0, 0,
// Osci2 Enabled
(32768/1), (32768/2), (32768/4), (32768/8),
(32768/16), (32768/32), (32768/64), (32768/128)
};
//
// Functions
//
int MinxTimers_Create(void)
{
// Reset
memset((void *)&MinxTimers, 0, sizeof(TMinxTimers));
MinxTimers_Reset(1);
return 1;
}
void MinxTimers_Destroy(void)
{
}
void MinxTimers_Reset(int hardreset)
{
if (hardreset) {
// Init state
memset((void *)&MinxTimers, 0, sizeof(TMinxTimers));
}
// Init variables
MinxTimers.Tmr1PreA = 0xFFFFFFFF;
MinxTimers.Tmr1PreB = 0xFFFFFFFF;
MinxTimers.Tmr2PreA = 0xFFFFFFFF;
MinxTimers.Tmr2PreB = 0xFFFFFFFF;
MinxTimers.Tmr3PreA = 0xFFFFFFFF;
MinxTimers.Tmr3PreB = 0xFFFFFFFF;
}
int MinxTimers_LoadState(FILE *fi, uint32_t bsize)
{
POKELOADSS_START(128);
POKELOADSS_32(MinxTimers.SecTimerCnt);
POKELOADSS_32(MinxTimers.TmrSecs);
POKELOADSS_32(MinxTimers.Tmr1DecA);
POKELOADSS_32(MinxTimers.Tmr1DecB);
POKELOADSS_32(MinxTimers.Tmr1CntA);
POKELOADSS_32(MinxTimers.Tmr1CntB);
POKELOADSS_32(MinxTimers.Tmr1PreA);
POKELOADSS_32(MinxTimers.Tmr1PreB);
POKELOADSS_32(MinxTimers.Tmr2DecA);
POKELOADSS_32(MinxTimers.Tmr2DecB);
POKELOADSS_32(MinxTimers.Tmr2CntA);
POKELOADSS_32(MinxTimers.Tmr2CntB);
POKELOADSS_32(MinxTimers.Tmr2PreA);
POKELOADSS_32(MinxTimers.Tmr2PreB);
POKELOADSS_32(MinxTimers.Tmr3DecA);
POKELOADSS_32(MinxTimers.Tmr3DecB);
POKELOADSS_32(MinxTimers.Tmr3CntA);
POKELOADSS_32(MinxTimers.Tmr3CntB);
POKELOADSS_32(MinxTimers.Tmr3PreA);
POKELOADSS_32(MinxTimers.Tmr3PreB);
POKELOADSS_32(MinxTimers.Tmr8Cnt);
POKELOADSS_32(MinxTimers.PRCCnt);
POKELOADSS_16(MinxTimers.Tmr3Cnt16.W);
POKELOADSS_16(MinxTimers.Timer3Piv);
POKELOADSS_8(MinxTimers.TmrXEna2);
POKELOADSS_8(MinxTimers.TmrXEna1);
POKELOADSS_X(34);
POKELOADSS_END(128);
MinxTimers.Tmr1WMode = PMR_TMR1_CTRL_L & 0x80;
MinxTimers.Tmr1LEna = PMR_TMR1_CTRL_L & 0x04;
MinxTimers.Tmr1HEna = PMR_TMR1_CTRL_H & 0x04;
MinxTimers.Tmr2WMode = PMR_TMR2_CTRL_L & 0x80;
MinxTimers.Tmr2LEna = PMR_TMR2_CTRL_L & 0x04;
MinxTimers.Tmr2HEna = PMR_TMR2_CTRL_H & 0x04;
MinxTimers.Tmr3WMode = PMR_TMR3_CTRL_L & 0x80;
MinxTimers.Tmr3LEna = PMR_TMR3_CTRL_L & 0x04;
MinxTimers.Tmr3HEna = PMR_TMR3_CTRL_H & 0x04;
}
int MinxTimers_SaveState(FILE *fi)
{
POKESAVESS_START(128);
POKESAVESS_32(MinxTimers.SecTimerCnt);
POKESAVESS_32(MinxTimers.TmrSecs);
POKESAVESS_32(MinxTimers.Tmr1DecA);
POKESAVESS_32(MinxTimers.Tmr1DecB);
POKESAVESS_32(MinxTimers.Tmr1CntA);
POKESAVESS_32(MinxTimers.Tmr1CntB);
POKESAVESS_32(MinxTimers.Tmr1PreA);
POKESAVESS_32(MinxTimers.Tmr1PreB);
POKESAVESS_32(MinxTimers.Tmr2DecA);
POKESAVESS_32(MinxTimers.Tmr2DecB);
POKESAVESS_32(MinxTimers.Tmr2CntA);
POKESAVESS_32(MinxTimers.Tmr2CntB);
POKESAVESS_32(MinxTimers.Tmr2PreA);
POKESAVESS_32(MinxTimers.Tmr2PreB);
POKESAVESS_32(MinxTimers.Tmr3DecA);
POKESAVESS_32(MinxTimers.Tmr3DecB);
POKESAVESS_32(MinxTimers.Tmr3CntA);
POKESAVESS_32(MinxTimers.Tmr3CntB);
POKESAVESS_32(MinxTimers.Tmr3PreA);
POKESAVESS_32(MinxTimers.Tmr3PreB);
POKESAVESS_32(MinxTimers.Tmr8Cnt);
POKESAVESS_32(MinxTimers.PRCCnt);
POKESAVESS_16(MinxTimers.Tmr3Cnt16.W);
POKESAVESS_16(MinxTimers.Timer3Piv);
POKESAVESS_8(MinxTimers.TmrXEna2);
POKESAVESS_8(MinxTimers.TmrXEna1);
POKESAVESS_X(34);
POKESAVESS_END(128);
}
void MinxTimers_Sync(void)
{
register uint32_t PreCount;
// Process 256Hz Timer (Increment)
if (PMR_TMR256_CTRL) {
PreCount = MinxTimers.Tmr8Cnt;
MinxTimers.Tmr8Cnt += MINX_TIMER256INC * PokeHWCycles;
if ((PreCount & 0x08000000) ^ (MinxTimers.Tmr8Cnt & 0x08000000)) {
// 32Hz
MinxCPU_OnIRQAct(MINX_INTR_0B);
}
if ((PreCount & 0x20000000) ^ (MinxTimers.Tmr8Cnt & 0x20000000)) {
// 8Hz
MinxCPU_OnIRQAct(MINX_INTR_0C);
}
if ((PreCount & 0x80000000) ^ (MinxTimers.Tmr8Cnt & 0x80000000)) {
// 2Hz
MinxCPU_OnIRQAct(MINX_INTR_0D);
}
if (PreCount > MinxTimers.Tmr8Cnt) {
// 1Hz
MinxCPU_OnIRQAct(MINX_INTR_0E);
}
}
// Process Second Timer (Increment)
if (PMR_SEC_CTRL) {
MinxTimers.TmrSecs += PokeHWCycles;
if (MinxTimers.TmrSecs >= 4000000) {
MinxTimers.SecTimerCnt++;
MinxTimers.TmrSecs -= 4000000;
}
}
// Process Timer 1 (Decrement)
if (MinxTimers.Tmr1WMode) {
// 1x 16-Bits Timer
if (MinxTimers.Tmr1LEna) {
PreCount = MinxTimers.Tmr1CntA;
MinxTimers.Tmr1CntA -= MinxTimers.Tmr1DecA * PokeHWCycles;
if (PreCount < MinxTimers.Tmr1CntA) {
PreCount = MinxTimers.Tmr1CntB;
MinxTimers.Tmr1CntB -= 0x01000000;
if (PreCount < MinxTimers.Tmr1CntB) {
MinxTimers.Tmr1CntA = MinxTimers.Tmr1PreA;
MinxTimers.Tmr1CntB = MinxTimers.Tmr1PreB;
// IRQ Timer 1-Hi underflow
MinxCPU_OnIRQAct(MINX_INTR_07);
}
}
}
} else {
// 2x 8-Bits Timers
if (MinxTimers.Tmr1LEna) {
// Timer Lo
PreCount = MinxTimers.Tmr1CntA;
MinxTimers.Tmr1CntA -= MinxTimers.Tmr1DecA * PokeHWCycles;
if (PreCount < MinxTimers.Tmr1CntA) {
MinxTimers.Tmr1CntA = MinxTimers.Tmr1PreA;
// IRQ Timer 1-Lo underflow
MinxCPU_OnIRQAct(MINX_INTR_08);
}
}
if (MinxTimers.Tmr1HEna) {
// Timer Hi
PreCount = MinxTimers.Tmr1CntB;
MinxTimers.Tmr1CntB -= MinxTimers.Tmr1DecB * PokeHWCycles;
if (PreCount < MinxTimers.Tmr1CntB) {
MinxTimers.Tmr1CntB = MinxTimers.Tmr1PreB;
// IRQ Timer 1-Hi underflow
MinxCPU_OnIRQAct(MINX_INTR_07);
}
}
}
// Process Timer 2 (Decrement)
if (MinxTimers.Tmr2WMode) {
// 1x 16-Bits Timer
if (MinxTimers.Tmr2LEna) {
PreCount = MinxTimers.Tmr2CntA;
MinxTimers.Tmr2CntA -= MinxTimers.Tmr2DecA * PokeHWCycles;
if (PreCount < MinxTimers.Tmr2CntA) {
PreCount = MinxTimers.Tmr2CntB;
MinxTimers.Tmr2CntB -= 0x01000000;
if (PreCount < MinxTimers.Tmr2CntB) {
MinxTimers.Tmr2CntA = MinxTimers.Tmr2PreA;
MinxTimers.Tmr2CntB = MinxTimers.Tmr2PreB;
// IRQ Timer 2-Hi underflow
MinxCPU_OnIRQAct(MINX_INTR_05);
}
}
}
} else {
// 2x 8-Bits Timers
if (MinxTimers.Tmr2LEna) {
// Timer Lo
PreCount = MinxTimers.Tmr2CntA;
MinxTimers.Tmr2CntA -= MinxTimers.Tmr2DecA * PokeHWCycles;
if (PreCount < MinxTimers.Tmr2CntA) {
MinxTimers.Tmr2CntA = MinxTimers.Tmr2PreA;
// IRQ Timer 2-Lo underflow
MinxCPU_OnIRQAct(MINX_INTR_06);
}
}
if (MinxTimers.Tmr2HEna) {
// Timer Hi
PreCount = MinxTimers.Tmr2CntB;
MinxTimers.Tmr2CntB -= MinxTimers.Tmr2DecB * PokeHWCycles;
if (PreCount < MinxTimers.Tmr2CntB) {
MinxTimers.Tmr2CntB = MinxTimers.Tmr2PreB;
// IRQ Timer 2-Hi underflow
MinxCPU_OnIRQAct(MINX_INTR_05);
}
}
}
// Process Timer 3 (Decrement)
if (MinxTimers.Tmr3WMode) {
// 1x 16-Bits Timer
if (MinxTimers.Tmr3LEna) {
PreCount = MinxTimers.Tmr3CntA;
MinxTimers.Tmr3CntA -= MinxTimers.Tmr3DecA * PokeHWCycles;
if (PreCount < MinxTimers.Tmr3CntA) {
PreCount = MinxTimers.Tmr3CntB;
MinxTimers.Tmr3CntB -= 0x01000000;
if (PreCount < MinxTimers.Tmr3CntB) {
MinxTimers.Tmr3CntA = MinxTimers.Tmr3PreA;
MinxTimers.Tmr3CntB = MinxTimers.Tmr3PreB;
// IRQ Timer 3 underflow
MinxCPU_OnIRQAct(MINX_INTR_09);
}
MinxTimers.Tmr3Cnt16.B.H = MinxTimers.Tmr3CntB >> 24;
}
// Check pivot
PreCount = MinxTimers.Tmr3Cnt16.W;
MinxTimers.Tmr3Cnt16.B.L = MinxTimers.Tmr3CntA >> 24;
if ((PreCount > MinxTimers.Timer3Piv) && (MinxTimers.Tmr3Cnt16.W <= MinxTimers.Timer3Piv)) {
// IRQ Timer 3 Pivot
MinxCPU_OnIRQAct(MINX_INTR_0A);
}
}
} else {
// 2x 8-Bits Timers
if (MinxTimers.Tmr3LEna) {
// Timer Lo
PreCount = MinxTimers.Tmr3CntA;
MinxTimers.Tmr3CntA -= MinxTimers.Tmr3DecA * PokeHWCycles; // Osci2
if (PreCount < MinxTimers.Tmr3CntA) {
MinxTimers.Tmr3CntA = MinxTimers.Tmr3PreA;
}
MinxTimers.Tmr3Cnt16.B.L = MinxTimers.Tmr3CntA >> 24;
}
if (MinxTimers.Tmr3HEna) {
// Timer Hi
PreCount = MinxTimers.Tmr3CntB;
MinxTimers.Tmr3CntB -= MinxTimers.Tmr3DecB * PokeHWCycles; // Osci2
if (PreCount < MinxTimers.Tmr3CntB) {
MinxTimers.Tmr3CntB = MinxTimers.Tmr3PreB;
// IRQ Timer 3 underflow
MinxCPU_OnIRQAct(MINX_INTR_09);
}
// Check pivot
PreCount = MinxTimers.Tmr3Cnt16.W;
MinxTimers.Tmr3Cnt16.B.H = MinxTimers.Tmr3CntB >> 24;
if ((PreCount > MinxTimers.Timer3Piv) && (MinxTimers.Tmr3Cnt16.W <= MinxTimers.Timer3Piv)) {
// IRQ Timer 3 Pivot
MinxCPU_OnIRQAct(MINX_INTR_0A);
}
}
}
}
uint8_t MinxTimers_ReadReg(uint8_t reg)
{
// 0x08 to 0x0F, 0x18 to 0x1F, 0x30 to 0x41, 0x48 to 0x4F
switch(reg) {
case 0x08: // Second Counter Control
return PMR_SEC_CTRL & 0x01;
case 0x09: // Second Counter Low
return (uint8_t)MinxTimers.SecTimerCnt;
case 0x0A: // Second Counter Med
return (uint8_t)(MinxTimers.SecTimerCnt >> 8);
case 0x0B: // Second Counter High
return (uint8_t)(MinxTimers.SecTimerCnt >> 16);
case 0x18: // Timer 1 Prescaler
return PMR_TMR1_SCALE;
case 0x19: // Timer 1 Osc. Select + Osc. Enable
return PMR_TMR1_ENA_OSC & 0x33;
case 0x1A: // Timer 2 Prescaler
return PMR_TMR2_SCALE;
case 0x1B: // Timer 2 Osc. Select
return PMR_TMR2_OSC & 0x03;
case 0x1C: // Timer 3 Prescaler
return PMR_TMR3_SCALE;
case 0x1D: // Timer 3 Osc. Select
return PMR_TMR3_OSC & 0x03;
case 0x30: // Timer 1 Control A
if (PMR_TMR1_CTRL_L & 0x80) {
return PMR_TMR1_CTRL_L & 0x85; // 16-Bits
} else {
return PMR_TMR1_CTRL_L & 0x0D; // 8-Bits Mode
}
case 0x31: // Timer 1 Control B
if (PMR_TMR1_CTRL_L & 0x80) {
return PMR_TMR1_CTRL_H & 0x08; // 16-Bits Mode
} else {
return PMR_TMR1_CTRL_H & 0x0D; // 8-Bits Mode
}
case 0x32: // Timer 1 Preset A
return (uint8_t)(MinxTimers.Tmr1PreA >> 24);
case 0x33: // Timer 1 Preset B
return (uint8_t)(MinxTimers.Tmr1PreB >> 24);
case 0x34: // Timer 1 Pivot A
return PMR_TMR1_PVT_L;
case 0x35: // Timer 1 Pivot B
return PMR_TMR1_PVT_H;
case 0x36: // Timer 1 Count A
return (uint8_t)(MinxTimers.Tmr1CntA >> 24);
case 0x37: // Timer 1 Count B
return (uint8_t)(MinxTimers.Tmr1CntB >> 24);
case 0x38: // Timer 2 Control A
if (PMR_TMR2_CTRL_L & 0x80) {
return PMR_TMR2_CTRL_L & 0x85; // 16-Bits
} else {
return PMR_TMR2_CTRL_L & 0x0D; // 8-Bits Mode
}
case 0x39: // Timer 2 Control B
if (PMR_TMR2_CTRL_L & 0x80) {
return PMR_TMR2_CTRL_H & 0x08; // 16-Bits Mode
} else {
return PMR_TMR2_CTRL_H & 0x0D; // 8-Bits Mode
}
case 0x3A: // Timer 2 Preset A
return (uint8_t)(MinxTimers.Tmr2PreA >> 24);
case 0x3B: // Timer 2 Preset B
return (uint8_t)(MinxTimers.Tmr2PreB >> 24);
case 0x3C: // Timer 2 Pivot A
return PMR_TMR2_PVT_L;
case 0x3D: // Timer 2 Pivot B
return PMR_TMR2_PVT_H;
case 0x3E: // Timer 2 Count A
return (uint8_t)(MinxTimers.Tmr2CntA >> 24);
case 0x3F: // Timer 2 Count B
return (uint8_t)(MinxTimers.Tmr2CntB >> 24);
case 0x40: // 256 Hz Timer Control
return PMR_TMR256_CTRL;
case 0x41: // 256 Hz Timer Counter
return MinxTimers.Tmr8Cnt >> 24;
case 0x48: // Timer 3 Control A
if (PMR_TMR3_CTRL_L & 0x80) {
return PMR_TMR3_CTRL_L & 0x85; // 16-Bits
} else {
return PMR_TMR3_CTRL_L & 0x0D; // 8-Bits Mode
}
case 0x49: // Timer 3 Control B
if (PMR_TMR3_CTRL_L & 0x80) {
return PMR_TMR3_CTRL_H & 0x08; // 16-Bits Mode
} else {
return PMR_TMR3_CTRL_H & 0x0D; // 8-Bits Mode
}
case 0x4A: // Timer 3 Preset A
return (uint8_t)(MinxTimers.Tmr3PreA >> 24);
case 0x4B: // Timer 3 Preset B
return (uint8_t)(MinxTimers.Tmr3PreB >> 24);
case 0x4C: // Timer 3 Pivot A
return (uint8_t)MinxTimers.Timer3Piv;
case 0x4D: // Timer 3 Pivot B
return (uint8_t)(MinxTimers.Timer3Piv >> 8);
case 0x4E: // Timer 3 Count A
return (uint8_t)(MinxTimers.Tmr3CntA >> 24);
case 0x4F: // Timer 3 Count B
return (uint8_t)(MinxTimers.Tmr3CntB >> 24);
default: // Unused
return reg;
}
}
#define MinxTimers_UpdateScalarTimer1() { \
if (PMR_TMR1_ENA_OSC & 0x01) { \
if (MinxTimers.TmrXEna2) MinxTimers.Tmr1DecA = MinxTimers_CalculateDecOsc2[(PMR_TMR1_SCALE & 0xF)]; \
else MinxTimers.Tmr1DecA = 0; \
} else { \
if (MinxTimers.TmrXEna1) MinxTimers.Tmr1DecA = MinxTimers_CalculateDecOsc1[(PMR_TMR1_SCALE & 0xF)]; \
else MinxTimers.Tmr1DecA = 0; \
} \
if (PMR_TMR1_ENA_OSC & 0x02) { \
if (MinxTimers.TmrXEna2) MinxTimers.Tmr1DecB = MinxTimers_CalculateDecOsc2[((PMR_TMR1_SCALE >> 4) & 0xF)]; \
else MinxTimers.Tmr1DecB = 0; \
} else { \
if (MinxTimers.TmrXEna1) MinxTimers.Tmr1DecB = MinxTimers_CalculateDecOsc1[((PMR_TMR1_SCALE >> 4) & 0xF)]; \
else MinxTimers.Tmr1DecB = 0; \
} \
}
#define MinxTimers_UpdateScalarTimer2() { \
if (PMR_TMR2_OSC & 0x01) { \
if (MinxTimers.TmrXEna2) MinxTimers.Tmr2DecA = MinxTimers_CalculateDecOsc2[(PMR_TMR2_SCALE & 0xF)]; \
else MinxTimers.Tmr2DecA = 0; \
} else { \
if (MinxTimers.TmrXEna1) MinxTimers.Tmr2DecA = MinxTimers_CalculateDecOsc1[(PMR_TMR2_SCALE & 0xF)]; \
else MinxTimers.Tmr2DecA = 0; \
} \
if (PMR_TMR2_OSC & 0x02) { \
if (MinxTimers.TmrXEna2) MinxTimers.Tmr2DecB = MinxTimers_CalculateDecOsc2[((PMR_TMR2_SCALE >> 4) & 0xF)]; \
else MinxTimers.Tmr2DecB = 0; \
} else { \
if (MinxTimers.TmrXEna1) MinxTimers.Tmr2DecB = MinxTimers_CalculateDecOsc1[((PMR_TMR2_SCALE >> 4) & 0xF)]; \
else MinxTimers.Tmr2DecB = 0; \
} \
}
#define MinxTimers_UpdateScalarTimer3() { \
if (PMR_TMR3_OSC & 0x01) { \
if (MinxTimers.TmrXEna2) MinxTimers.Tmr3DecA = MinxTimers_CalculateDecOsc2[(PMR_TMR3_SCALE & 0xF)]; \
else MinxTimers.Tmr3DecA = 0; \
} else { \
if (MinxTimers.TmrXEna1) MinxTimers.Tmr3DecA = MinxTimers_CalculateDecOsc1[(PMR_TMR3_SCALE & 0xF)]; \
else MinxTimers.Tmr3DecA = 0; \
} \
if (PMR_TMR3_OSC & 0x02) { \
if (MinxTimers.TmrXEna2) MinxTimers.Tmr3DecB = MinxTimers_CalculateDecOsc2[((PMR_TMR3_SCALE >> 4) & 0xF)]; \
else MinxTimers.Tmr3DecB = 0; \
} else { \
if (MinxTimers.TmrXEna1) MinxTimers.Tmr3DecB = MinxTimers_CalculateDecOsc1[((PMR_TMR3_SCALE >> 4) & 0xF)]; \
else MinxTimers.Tmr3DecB = 0; \
} \
}
void MinxTimers_WriteReg(unsigned char reg, unsigned char val)
{
// 0x08 to 0x0F, 0x18 to 0x1F, 0x30 to 0x41, 0x48 to 0x4F
switch(reg) {
case 0x08: // Second Counter Control
if (val & 0x02) MinxTimers.SecTimerCnt = 0x000000;
PMR_SEC_CTRL = val & 0x01;
return;
case 0x09: // Second Counter Low
case 0x0A: // Second Counter Med
case 0x0B: // Second Counter High
return;
case 0x18: // Timer 1 Prescaler
PMR_TMR1_SCALE = val;
MinxTimers_UpdateScalarTimer1();
return;
case 0x19: // Timer 1 Osc. Select + Osc. Enable
PMR_TMR1_ENA_OSC = val & 0x33;
MinxTimers.TmrXEna2 = val & 0x10;
MinxTimers.TmrXEna1 = val & 0x20;
MinxTimers_UpdateScalarTimer1();
MinxTimers_UpdateScalarTimer2(); // Because of the TmrXEna#
MinxTimers_UpdateScalarTimer3(); // Because of the TmrXEna#
return;
case 0x1A: // Timer 2 Prescaler
PMR_TMR2_SCALE = val;
MinxTimers_UpdateScalarTimer2();
return;
case 0x1B: // Timer 2 Osc. Select
PMR_TMR2_OSC = val & 0x03;
MinxTimers_UpdateScalarTimer2();
return;
case 0x1C: // Timer 3 Prescaler
PMR_TMR3_SCALE = val;
MinxTimers_UpdateScalarTimer3();
return;
case 0x1D: // Timer 3 Osc. Select
PMR_TMR3_OSC = val & 0x03;
MinxTimers_UpdateScalarTimer3();
return;
case 0x30: // Timer 1 Control A
PMR_TMR1_CTRL_L = val & 0x8D;
MinxTimers.Tmr1LEna = val & 0x04;
if (PMR_TMR1_CTRL_L & 0x80) {
// 16-Bits
MinxTimers.Tmr1WMode = 1;
if (val & 0x02) {
MinxTimers.Tmr1CntA = MinxTimers.Tmr1PreA;
MinxTimers.Tmr1CntB = MinxTimers.Tmr1PreB;
}
} else {
// 8-Bits
MinxTimers.Tmr1WMode = 0;
if (val & 0x02) {
MinxTimers.Tmr1CntA = MinxTimers.Tmr1PreA;
}
}
return;
case 0x31: // Timer 1 Control B
PMR_TMR1_CTRL_H = val & 0x0D;
MinxTimers.Tmr1HEna = val & 0x04;
if (PMR_TMR1_CTRL_L & 0x80) {
// 16-Bits, unused
} else {
// 8-Bits
if (val & 0x02) {
MinxTimers.Tmr1CntB = MinxTimers.Tmr1PreB;
}
}
return;
case 0x32: // Timer 1 Preset A
MinxTimers.Tmr1PreA = val << 24;
return;
case 0x33: // Timer 1 Preset B
MinxTimers.Tmr1PreB = val << 24;
return;
case 0x34: // Timer 1 Pivot A
PMR_TMR1_PVT_L = val;
return;
case 0x35: // Timer 1 Pivot B
PMR_TMR1_PVT_H = val;
return;
case 0x36: // Timer 1 Count A
return;
case 0x37: // Timer 1 Count B
return;
case 0x38: // Timer 2 Control A
PMR_TMR2_CTRL_L = val & 0x8D;
MinxTimers.Tmr2LEna = val & 0x04;
if (PMR_TMR2_CTRL_L & 0x80) {
// 16-Bits
MinxTimers.Tmr2WMode = 1;
if (val & 0x02) {
MinxTimers.Tmr2CntA = MinxTimers.Tmr2PreA;
MinxTimers.Tmr2CntB = MinxTimers.Tmr2PreB;
}
} else {
// 8-Bits
MinxTimers.Tmr2WMode = 0;
if (val & 0x02) {
MinxTimers.Tmr2CntA = MinxTimers.Tmr2PreA;
}
}
return;
case 0x39: // Timer 2 Control B
PMR_TMR2_CTRL_H = val & 0x0D;
MinxTimers.Tmr2HEna = val & 0x04;
if (PMR_TMR2_CTRL_L & 0x80) {
// 16-Bits, unused
} else {
// 8-Bits
if (val & 0x02) {
MinxTimers.Tmr2CntB = MinxTimers.Tmr2PreB;
}
}
return;
case 0x3A: // Timer 2 Preset A
MinxTimers.Tmr2PreA = val << 24;
return;
case 0x3B: // Timer 2 Preset B
MinxTimers.Tmr2PreB = val << 24;
return;
case 0x3C: // Timer 2 Pivot A
PMR_TMR2_PVT_L = val;
return;
case 0x3D: // Timer 2 Pivot B
PMR_TMR2_PVT_H = val;
return;
case 0x3E: // Timer 2 Count A
return;
case 0x3F: // Timer 2 Count B
return;
case 0x40: // 256 Hz Timer Control
PMR_TMR256_CTRL = val & 0x01;
if (val & 0x02) {
MinxTimers.Tmr8Cnt = 0;
}
return;
case 0x41: // 256 Hz Timer Counter
return;
case 0x48: // Timer 3 Control A
PMR_TMR3_CTRL_L = val & 0x8D;
MinxTimers.Tmr3LEna = val & 0x04;
if (PMR_TMR3_CTRL_L & 0x80) {
// 16-Bits
MinxTimers.Tmr3WMode = 1;
if (val & 0x02) {
MinxTimers.Tmr3CntA = MinxTimers.Tmr3PreA;
MinxTimers.Tmr3CntB = MinxTimers.Tmr3PreB;
}
} else {
// 8-Bits
MinxTimers.Tmr3WMode = 0;
if (val & 0x02) {
MinxTimers.Tmr3CntA = MinxTimers.Tmr3PreA;
}
}
return;
case 0x49: // Timer 3 Control B
PMR_TMR3_CTRL_H = val & 0x0D;
MinxTimers.Tmr3HEna = val & 0x04;
if (PMR_TMR3_CTRL_L & 0x80) {
// 16-Bits, unused
} else {
// 8-Bits
if (val & 0x02) {
MinxTimers.Tmr3CntB = MinxTimers.Tmr3PreB;
}
}
return;
case 0x4A: // Timer 3 Preset A
MinxTimers.Tmr3PreA = val << 24;
return;
case 0x4B: // Timer 3 Preset B
MinxTimers.Tmr3PreB = val << 24;
return;
case 0x4C: // Timer 3 Pivot A
MinxTimers.Timer3Piv = (MinxTimers.Timer3Piv & 0xFF00) | val;
return;
case 0x4D: // Timer 3 Pivot B
MinxTimers.Timer3Piv = (MinxTimers.Timer3Piv & 0x00FF) | (val << 8);
return;
case 0x4E: // Timer 3 Count A
return;
case 0x4F: // Timer 3 Count B
return;
}
}