From 356fc4e3a3ae2f3bfbad876798513398f86be962 Mon Sep 17 00:00:00 2001 From: Hugo Villeneuve Date: Wed, 27 Nov 2013 20:56:05 -0500 Subject: [PATCH] Move timer functions to timers.c --- src/Makefile.am | 1 + src/cpu8051.c | 110 +----------------------------------- src/timers.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++ src/timers.h | 29 ++++++++++ 4 files changed, 176 insertions(+), 108 deletions(-) create mode 100644 src/timers.c create mode 100644 src/timers.h diff --git a/src/Makefile.am b/src/Makefile.am index b5b4fbb..52e4061 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -27,6 +27,7 @@ common_SOURCES = \ memory.h \ psw.c psw.h \ sfr.c sfr.h \ + timers.c timers.h \ common.h \ reg8051.h diff --git a/src/cpu8051.c b/src/cpu8051.c index 1fd0251..6480853 100644 --- a/src/cpu8051.c +++ b/src/cpu8051.c @@ -29,6 +29,7 @@ #include "cpu8051.h" #include "memory.h" #include "psw.h" +#include "timers.h" #include "disasm.h" #include "options.h" #include "instructions_8051.h" @@ -278,113 +279,6 @@ cpu8051_CheckInterrupts(void) } } -static void -process_timer(uint8_t tl, uint8_t th, uint8_t tf_mask, uint8_t TR, uint8_t mode, - uint8_t GATE, uint32_t TimerCounter) -{ - unsigned int tmp; - unsigned int prescaler; - - switch (mode) { - case 0: - /* Mode 0, 8-bit timer "TH" with "TL" as 5-bit prescaler. */ - prescaler = cpu8051_ReadD(tl); - prescaler++; - prescaler &= 0x1F; /* We keep only 5 bits */ - cpu8051_WriteD(tl, prescaler); - - if (prescaler == 0) { - /* If overflow, increment TH */ - tmp = cpu8051_ReadD(th); - tmp++; - tmp &= 0xFF; /* We keep only 8 bits */ - - if (tmp == 0) /* If overflow set TF */ - cpu8051_WriteD(_TCON_, cpu8051_ReadD(_TCON_) | tf_mask); - - cpu8051_WriteD(th, tmp); - } - break; - case 1: - /* Mode 1, 16-bits counter */ - tmp = cpu8051_ReadD(th) * 0x100 + cpu8051_ReadD(tl); - tmp++; - tmp &= 0xFFFF; /* We keep only 16 bits */ - if (tmp == 0) /* If overflow set TF0 */ - cpu8051_WriteD(_TCON_, cpu8051_ReadD(_TCON_) | tf_mask); - cpu8051_WriteD(th, (tmp / 0x100)); - cpu8051_WriteD(tl, (tmp & 0xFF)); - break; - case 2: - /* Mode 2, 8-bits counter with Auto-Reload */ - tmp = cpu8051_ReadD(tl); - tmp++; - tmp &= 0xFF; - if (tmp == 0) { - /* If overflow -> reload and set TF0 */ - cpu8051_WriteD(_TCON_, cpu8051_ReadD(_TCON_) | tf_mask); - cpu8051_WriteD(tl, cpu8051_ReadD(th)); - } else - cpu8051_WriteD(tl, tmp); - break; - case 3: - /* Mode 3 : inactive mode for timer 1 */ - if (tl == _TL0_) { - /* TL0 and TH0 are 2 independents 8-bits timers. */ - if (TR && !GATE && !TimerCounter) { - tmp = cpu8051_ReadD(tl); - tmp++; - tmp &= 0xFF; - if (tmp == 0) /* If TL0 overflow set TF0 */ - cpu8051_WriteD(_TCON_, - cpu8051_ReadD(_TCON_) | - tf_mask); - cpu8051_WriteD(tl, tmp); - } /* TH0 utilise TR1 et TF1. */ - TR = cpu8051_ReadD(_TCON_) & 0x40; - if (TR) { - tmp = cpu8051_ReadD(th); - tmp++; - tmp &= 0xFF; - if (tmp == 0) /* If TH0 overflow set TF1 */ - cpu8051_WriteD(_TCON_, - cpu8051_ReadD(_TCON_) | - 0x80); - cpu8051_WriteD(_TH0_, tmp); - } - } - break; - } -} - -/* Run timers */ -static void -cpu8051_DoTimers(void) -{ - unsigned int TR; - unsigned int MODE; - unsigned int GATE; - unsigned int TimerCounter; - - /* Timer 0 */ - TR = cpu8051_ReadD(_TCON_) & 0x10; - MODE = cpu8051_ReadD(_TMOD_) & 0x03; - GATE = cpu8051_ReadD(_TMOD_) & 0x08; - TimerCounter = cpu8051_ReadD(_TMOD_) & 0x04; - - if ((TR && !GATE && !TimerCounter) || (MODE == 3)) - process_timer(_TL0_, _TH0_, 0x20, TR, MODE, GATE, TimerCounter); - - /* Timer 1 */ - TR = cpu8051_ReadD(_TCON_) & 0x40; - MODE = (cpu8051_ReadD(_TMOD_) & 0x30) >> 4 ; - GATE = cpu8051_ReadD(_TMOD_) & 0x80; - TimerCounter = cpu8051_ReadD(_TMOD_) & 0x40; - - if (TR && !GATE && !TimerCounter) - process_timer(_TL1_, _TH1_, 0x80, TR, MODE, GATE, TimerCounter); -} - /* Execute at address cpu8051.pc from PGMMem */ void cpu8051_Exec(void) @@ -405,7 +299,7 @@ cpu8051_Exec(void) for (i = 0; i < insttiming; i++) { cpu8051_CheckInterrupts(); - cpu8051_DoTimers(); + timers_check(); cpu8051.clock++; } } diff --git a/src/timers.c b/src/timers.c new file mode 100644 index 0000000..68a92bc --- /dev/null +++ b/src/timers.c @@ -0,0 +1,144 @@ +/* + * timers.c + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * 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 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include "config.h" + +#include "common.h" +#include "reg8051.h" +#include "cpu8051.h" +#include "memory.h" +#include "psw.h" +#include "options.h" +#include "instructions_8051.h" + +extern struct options_t options; + +static void +timer_increment_check_overflow(uint8_t counter_address, uint8_t tf_mask) +{ + unsigned int tmp; + + tmp = cpu8051_ReadD(counter_address); + tmp++; + tmp &= 0xFF; + if (tmp == 0) { + /* If overflow set TFx */ + cpu8051_WriteD(_TCON_, cpu8051_ReadD(_TCON_) | tf_mask); + } + + cpu8051_WriteD(counter_address, tmp); /* Save new value. */ +} + +static void +timer_with_prescaler(uint8_t tl, uint8_t th, uint8_t tf_mask, int prescaler_width) +{ + unsigned int prescaler; + + prescaler = cpu8051_ReadD(tl); + prescaler++; + + prescaler &= (1 << prescaler_width) - 1; /* Keep only required bits */ + cpu8051_WriteD(tl, prescaler); + + if (prescaler == 0) + timer_increment_check_overflow(th, tf_mask); +} + +static void +process_timer(uint8_t tl, uint8_t th, uint8_t tf_mask, uint8_t TR, uint8_t mode, + uint8_t GATE, uint32_t TimerCounter) +{ + unsigned int tmp; + + switch (mode) { + case 0: + /* Mode 0, 8-bit timer "TH" with "TL" as 5-bit prescaler. */ + timer_with_prescaler(tl, th, tf_mask, 5); + break; + case 1: + /* Mode 1, 16-bits counter */ + timer_with_prescaler(tl, th, tf_mask, 8); + break; + case 2: + /* Mode 2, 8-bits counter with Auto-Reload */ + tmp = cpu8051_ReadD(tl); + tmp++; + tmp &= 0xFF; + if (tmp == 0) { + /* If overflow -> reload and set TF0 */ + cpu8051_WriteD(_TCON_, cpu8051_ReadD(_TCON_) | tf_mask); + cpu8051_WriteD(tl, cpu8051_ReadD(th)); + } else + cpu8051_WriteD(tl, tmp); + break; + case 3: + /* + * Mode 3: + * inactive mode for timer 1 + * 2 independents 8-bits timers for timer 0. + */ + + if (tl == _TL1_) + break; + + if (TR && !GATE && !TimerCounter) + timer_increment_check_overflow(tl, tf_mask); + + /* TH0 uses TR1 et TF1. */ + TR = cpu8051_ReadD(_TCON_) & 0x40; + + if (TR) + timer_increment_check_overflow(th, 0x80); + + break; + } +} + +/* Run timers */ +void +timers_check(void) +{ + unsigned int TR; + unsigned int MODE; + unsigned int GATE; + unsigned int TimerCounter; + + /* Timer 0 */ + TR = cpu8051_ReadD(_TCON_) & 0x10; + MODE = cpu8051_ReadD(_TMOD_) & 0x03; + GATE = cpu8051_ReadD(_TMOD_) & 0x08; + TimerCounter = cpu8051_ReadD(_TMOD_) & 0x04; + + if ((TR && !GATE && !TimerCounter) || (MODE == 3)) + process_timer(_TL0_, _TH0_, 0x20, TR, MODE, GATE, TimerCounter); + + /* Timer 1 */ + TR = cpu8051_ReadD(_TCON_) & 0x40; + MODE = (cpu8051_ReadD(_TMOD_) & 0x30) >> 4 ; + GATE = cpu8051_ReadD(_TMOD_) & 0x80; + TimerCounter = cpu8051_ReadD(_TMOD_) & 0x40; + + if (TR && !GATE && !TimerCounter) + process_timer(_TL1_, _TH1_, 0x80, TR, MODE, GATE, TimerCounter); +} diff --git a/src/timers.h b/src/timers.h new file mode 100644 index 0000000..932ace4 --- /dev/null +++ b/src/timers.h @@ -0,0 +1,29 @@ +/* + * timers.h + * + * Copyright (C) 2013 Hugo Villeneuve + * + * 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 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef TIMERS_H +#define TIMERS_H 1 + +#include + +int +timers_check(void); + +#endif /* TIMERS_H */ -- 2.20.1