7
var OSCILLATOR_FREQ = 1193.1816666;
21
this.counter_start_time = new Float64Array(3);
22
this.counter_start_value = new Uint16Array(3);
24
this.counter_next_low = new Uint8Array(4);
25
this.counter_enabled = new Uint8Array(4);
26
this.counter_mode = new Uint8Array(4);
27
this.counter_read_mode = new Uint8Array(4);
30
this.counter_latch = new Uint8Array(4);
31
this.counter_latch_value = new Uint16Array(3);
33
this.counter_reload = new Uint16Array(3);
38
cpu.io.register_read(0x61, this, function()
40
var now = v86.microtick();
42
var ref_toggle = (now * (1000 * 1000 / 15000)) & 1;
43
var counter2_out = this.did_rollover(2, now);
45
return ref_toggle << 4 | counter2_out << 5;
47
cpu.io.register_write(0x61, this, function(data)
51
this.bus.send("pcspeaker-enable");
55
this.bus.send("pcspeaker-disable");
59
cpu.io.register_read(0x40, this, function() { return this.counter_read(0); });
60
cpu.io.register_read(0x41, this, function() { return this.counter_read(1); });
61
cpu.io.register_read(0x42, this, function() { return this.counter_read(2); });
63
cpu.io.register_write(0x40, this, function(data) { this.counter_write(0, data); });
64
cpu.io.register_write(0x41, this, function(data) { this.counter_write(1, data); });
65
cpu.io.register_write(0x42, this, function(data) {
66
this.counter_write(2, data);
67
this.bus.send("pcspeaker-update", [this.counter_mode[2], this.counter_reload[2]]);
70
cpu.io.register_write(0x43, this, this.port43_write);
73
PIT.prototype.get_state = function()
77
state[0] = this.counter_next_low;
78
state[1] = this.counter_enabled;
79
state[2] = this.counter_mode;
80
state[3] = this.counter_read_mode;
81
state[4] = this.counter_latch;
82
state[5] = this.counter_latch_value;
83
state[6] = this.counter_reload;
84
state[7] = this.counter_start_time;
85
state[8] = this.counter_start_value;
90
PIT.prototype.set_state = function(state)
92
this.counter_next_low = state[0];
93
this.counter_enabled = state[1];
94
this.counter_mode = state[2];
95
this.counter_read_mode = state[3];
96
this.counter_latch = state[4];
97
this.counter_latch_value = state[5];
98
this.counter_reload = state[6];
99
this.counter_start_time = state[7];
100
this.counter_start_value = state[8];
103
PIT.prototype.timer = function(now, no_irq)
105
var time_to_next_interrupt = 100;
110
if(this.counter_enabled[0] && this.did_rollover(0, now))
112
this.counter_start_value[0] = this.get_counter_value(0, now);
113
this.counter_start_time[0] = now;
115
dbg_log("pit interrupt. new value: " + this.counter_start_value[0], LOG_PIT);
120
this.cpu.device_lower_irq(0);
122
this.cpu.device_raise_irq(0);
123
var mode = this.counter_mode[0];
127
this.counter_enabled[0] = 0;
132
this.cpu.device_lower_irq(0);
135
if(this.counter_enabled[0])
137
const diff = now - this.counter_start_time[0];
138
const diff_in_ticks = Math.floor(diff * OSCILLATOR_FREQ);
139
const ticks_missing = this.counter_start_value[0] - diff_in_ticks;
140
time_to_next_interrupt = ticks_missing / OSCILLATOR_FREQ;
144
return time_to_next_interrupt;
147
PIT.prototype.get_counter_value = function(i, now)
149
if(!this.counter_enabled[i])
154
var diff = now - this.counter_start_time[i];
155
var diff_in_ticks = Math.floor(diff * OSCILLATOR_FREQ);
157
var value = this.counter_start_value[i] - diff_in_ticks;
159
dbg_log("diff=" + diff + " dticks=" + diff_in_ticks + " value=" + value + " reload=" + this.counter_reload[i], LOG_PIT);
161
var reload = this.counter_reload[i];
165
dbg_log("Warning: Counter" + i + " value " + value + " is larger than reload " + reload, LOG_PIT);
170
value = value % reload + reload;
176
PIT.prototype.did_rollover = function(i, now)
178
var diff = now - this.counter_start_time[i];
183
dbg_log("Warning: PIT timer difference is negative, resetting (timer " + i + ")");
186
var diff_in_ticks = Math.floor(diff * OSCILLATOR_FREQ);
189
return this.counter_start_value[i] < diff_in_ticks;
192
PIT.prototype.counter_read = function(i)
194
var latch = this.counter_latch[i];
198
this.counter_latch[i]--;
202
return this.counter_latch_value[i] & 0xFF;
206
return this.counter_latch_value[i] >> 8;
211
var next_low = this.counter_next_low[i];
213
if(this.counter_mode[i] === 3)
215
this.counter_next_low[i] ^= 1;
218
var value = this.get_counter_value(i, v86.microtick());
231
PIT.prototype.counter_write = function(i, value)
233
if(this.counter_next_low[i])
235
this.counter_reload[i] = this.counter_reload[i] & ~0xFF | value;
239
this.counter_reload[i] = this.counter_reload[i] & 0xFF | value << 8;
242
if(this.counter_read_mode[i] !== 3 || !this.counter_next_low[i])
244
if(!this.counter_reload[i])
246
this.counter_reload[i] = 0xFFFF;
251
this.counter_start_value[i] = this.counter_reload[i];
253
this.counter_enabled[i] = true;
255
this.counter_start_time[i] = v86.microtick();
257
dbg_log("counter" + i + " reload=" + h(this.counter_reload[i]) +
258
" tick=" + (this.counter_reload[i] || 0x10000) / OSCILLATOR_FREQ + "ms", LOG_PIT);
261
if(this.counter_read_mode[i] === 3)
263
this.counter_next_low[i] ^= 1;
267
PIT.prototype.port43_write = function(reg_byte)
269
var mode = reg_byte >> 1 & 7,
270
binary_mode = reg_byte & 1,
271
i = reg_byte >> 6 & 3,
272
read_mode = reg_byte >> 4 & 3;
276
dbg_log("Unimplemented timer1", LOG_PIT);
281
dbg_log("Unimplemented read back", LOG_PIT);
288
this.counter_latch[i] = 2;
289
var value = this.get_counter_value(i, v86.microtick());
290
dbg_log("latch: " + value, LOG_PIT);
291
this.counter_latch_value[i] = value ? value - 1 : 0;
302
dbg_log("Control: mode=" + mode + " ctr=" + i +
303
" read_mode=" + read_mode + " bcd=" + binary_mode, LOG_PIT);
308
this.counter_next_low[i] = 0;
310
else if(read_mode === 2)
313
this.counter_next_low[i] = 1;
318
this.counter_next_low[i] = 1;
323
this.cpu.device_lower_irq(0);
329
else if(mode === 3 || mode === 2)
335
dbg_log("Unimplemented counter mode: " + h(mode), LOG_PIT);
338
this.counter_mode[i] = mode;
339
this.counter_read_mode[i] = read_mode;
343
this.bus.send("pcspeaker-update", [this.counter_mode[2], this.counter_reload[2]]);
347
PIT.prototype.dump = function()
349
const reload = this.counter_reload[0];
350
const time = (reload || 0x10000) / OSCILLATOR_FREQ;
351
dbg_log("counter0 ticks every " + time + "ms (reload=" + reload + ")");