<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace elbgb.gbcore
{
	public class Timer : ClockedComponent
	{
		public static class Registers
		{
			public const ushort DIV  = 0xFF04;
			public const ushort TIMA = 0xFF05;
			public const ushort TMA  = 0xFF06;
			public const ushort TAC  = 0xFF07;
		}

		// divider
		private ushort _divider;

		// timer
		private bool _timerEnabled;

		private uint _timerInterval;
		private uint _timerCounter;

		private byte _tima, _tma, _tac;
		
		public Timer(GameBoy gameBoy)
			: base(gameBoy)
		{

		}

		public byte ReadByte(ushort address)
		{
			SynchroniseWithSystemClock();

			switch (address)
			{
				// the divider is the upper 8 bits of the 16-bit counter that counts the 
				// basic clock frequency (f). f = 4.194304 MHz
				case Registers.DIV: return (byte)(_divider >> 8);

				// timer counter
				case Registers.TIMA:
					return _tima;

				// timer modulo 
				case Registers.TMA:
					return _tma;

				// timer controller
				case Registers.TAC:
					return (byte)(_tac & 0x07);

				default:
					throw new ArgumentOutOfRangeException("address");
			}
		}

		public void WriteByte(ushort address, byte value)
		{
			SynchroniseWithSystemClock();

			switch (address)
			{
				// a write always clears the upper 8 bits of DIV, regardless of value
				case Registers.DIV: _divider &= 0x00FF; break;

				// timer counter
				case Registers.TIMA:
					_tima = value; break;

				// timer modulo 
				case Registers.TMA:
					_tma = value; break;

				// timer controller
				case Registers.TAC:
					_tac = (byte)(value & 0x07);

					// update enabled state from bit 2
					_timerEnabled = (value & 0x04) == 0x04;

					// bits 0/1 specify timer frequency, set interval
					switch (value & 0x03)
					{
						// 00 - f/2^10 (4.096 KHz)
						case 0x00: _timerInterval = SystemClock.ClockFrequency / 4096; break;

						// 01 - f/2^4 (262.144 KHz)
						case 0x01: _timerInterval = SystemClock.ClockFrequency / 262144; break;

						// 10 - f/2^6 (65.436 KHz)
						case 0x10: _timerInterval = SystemClock.ClockFrequency / 65436; break;

						// 11 - f/2^8 (16.384 KHz)
						case 0x11: _timerInterval = SystemClock.ClockFrequency / 16384; break;
					}<commit_msg>Fix timer interval selection, could not select middle two timer speeds<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace elbgb.gbcore
{
	public class Timer : ClockedComponent
	{
		public static class Registers
		{
			public const ushort DIV  = 0xFF04;
			public const ushort TIMA = 0xFF05;
			public const ushort TMA  = 0xFF06;
			public const ushort TAC  = 0xFF07;
		}

		// divider
		private ushort _divider;

		// timer
		private bool _timerEnabled;

		private uint _timerInterval;
		private uint _timerCounter;

		private byte _tima, _tma, _tac;
		
		public Timer(GameBoy gameBoy)
			: base(gameBoy)
		{

		}

		public byte ReadByte(ushort address)
		{
			SynchroniseWithSystemClock();

			switch (address)
			{
				// the divider is the upper 8 bits of the 16-bit counter that counts the 
				// basic clock frequency (f). f = 4.194304 MHz
				case Registers.DIV: return (byte)(_divider >> 8);

				// timer counter
				case Registers.TIMA:
					return _tima;

				// timer modulo 
				case Registers.TMA:
					return _tma;

				// timer controller
				case Registers.TAC:
					return (byte)(_tac & 0x07);

				default:
					throw new ArgumentOutOfRangeException("address");
			}
		}

		public void WriteByte(ushort address, byte value)
		{
			SynchroniseWithSystemClock();

			switch (address)
			{
				// a write always clears the upper 8 bits of DIV, regardless of value
				case Registers.DIV: _divider &= 0x00FF; break;

				// timer counter
				case Registers.TIMA:
					_tima = value; break;

				// timer modulo 
				case Registers.TMA:
					_tma = value; break;

				// timer controller
				case Registers.TAC:
					_tac = (byte)(value & 0x07);

					// update enabled state from bit 2
					_timerEnabled = (value & 0x04) == 0x04;

					// bits 0/1 specify timer frequency, set interval
					switch (value & 0x03)
					{
						// 00 - f/2^10 (4.096 KHz)
						case 0x00: _timerInterval = SystemClock.ClockFrequency / 4096; break;

						// 01 - f/2^4 (262.144 KHz)
						case 0x01: _timerInterval = SystemClock.ClockFrequency / 262144; break;

						// 10 - f/2^6 (65.436 KHz)
						case 0x02: _timerInterval = SystemClock.ClockFrequency / 65436; break;

						// 11 - f/2^8 (16.384 KHz)
						case 0x03: _timerInterval = SystemClock.ClockFrequency / 16384; break;
					}
{'fraction_non_alphanumeric': 0.09435569755058573, 'fraction_numerical': 0.04856230031948882, 'mean_word_length': 2.581998474446987, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, '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': '5249117', 'n_tokens_mistral': 2142, 'n_tokens_neox': 1540, 'n_words': 464}