Start implementing via "timer 2"
This makes clicking "show notes" in the "Addresses" stack of HyperCardBootSystem7.img succeed. It also allows `play "Boing"` to work, but not `play "Boing" "a c e g"`. It also makes running on RP2350 really, really slow. It also makes glider come up complaining of a missing math co-processor(!?)
This commit is contained in:
parent
bc6529ea4b
commit
7b8b26f0e0
3 changed files with 67 additions and 10 deletions
|
|
@ -40,7 +40,8 @@ struct via_cb {
|
|||
void via_init(struct via_cb *cb);
|
||||
void via_write(unsigned int address, uint8_t data);
|
||||
uint8_t via_read(unsigned int address);
|
||||
void via_tick(uint64_t time);
|
||||
void via_tick(int cycles);
|
||||
int via_limit_cycles(int cycles);
|
||||
/* Trigger an event on CA1 or CA2: */
|
||||
void via_caX_event(int ca);
|
||||
void via_sr_rx(uint8_t val);
|
||||
|
|
|
|||
14
src/main.c
14
src/main.c
|
|
@ -75,7 +75,7 @@ uint8_t *_rom_base;
|
|||
static int umac_volume, umac_sndres;
|
||||
#endif
|
||||
int overlay = 1;
|
||||
static uint64_t global_time_us = 0;
|
||||
static uint64_t global_time_us = 0, global_cycles = 0;
|
||||
static int sim_done = 0;
|
||||
static jmp_buf main_loop_jb;
|
||||
|
||||
|
|
@ -665,12 +665,16 @@ int umac_loop(void)
|
|||
{
|
||||
setjmp(main_loop_jb);
|
||||
|
||||
const int us = UMAC_EXECLOOP_QUANTUM;
|
||||
m68k_execute(us*8);
|
||||
global_time_us += us;
|
||||
int cycles = UMAC_EXECLOOP_QUANTUM * 8;
|
||||
cycles = via_limit_cycles(cycles);
|
||||
int used_cycles = m68k_execute(cycles);
|
||||
printf("Asked to execute %d cycles, actual %d cycles\n",
|
||||
cycles, used_cycles);
|
||||
global_cycles += used_cycles;
|
||||
global_time_us = global_cycles / 8;
|
||||
|
||||
// Device polling
|
||||
via_tick(global_time_us);
|
||||
via_tick(used_cycles);
|
||||
kbd_check_work();
|
||||
|
||||
return sim_done;
|
||||
|
|
|
|||
60
src/via.c
60
src/via.c
|
|
@ -29,6 +29,7 @@
|
|||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "m68kcpu.h"
|
||||
#include "via.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
|
|
@ -47,7 +48,8 @@
|
|||
#define VIA_T1CH 5
|
||||
#define VIA_T1LL 6
|
||||
#define VIA_T1LH 7
|
||||
#define VIA_T2CL 8
|
||||
#define VIA_T2CL 8 // write latch
|
||||
#define VIA_T2LL 8 // read counter
|
||||
#define VIA_T2CH 9
|
||||
#define VIA_SR 10
|
||||
#define VIA_ACR 11
|
||||
|
|
@ -56,6 +58,7 @@
|
|||
#define VIA_IRQ_CA 0x01
|
||||
#define VIA_IRQ_CB 0x02
|
||||
#define VIA_IRQ_SR 0x04
|
||||
#define VIA_IRQ_T2 0x20
|
||||
#define VIA_IER 14
|
||||
#define VIA_RA_ALT 15 // No-handshake version
|
||||
|
||||
|
|
@ -68,7 +71,7 @@ static const char *dbg_regnames[] = {
|
|||
"VIA_T1CH",
|
||||
"VIA_T1LL",
|
||||
"VIA_T1LH",
|
||||
"VIA_T2CL",
|
||||
"VIA_T2xL",
|
||||
"VIA_T2CH",
|
||||
"VIA_SR",
|
||||
"VIA_ACR",
|
||||
|
|
@ -84,6 +87,8 @@ static int irq_status = 0;
|
|||
static uint8_t irq_active = 0;
|
||||
static uint8_t irq_enable = 0;
|
||||
|
||||
static uint16_t via_t2c;
|
||||
|
||||
void via_init(struct via_cb *cb)
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
|
|
@ -224,6 +229,25 @@ void via_write(unsigned int address, uint8_t data)
|
|||
case VIA_PCR:
|
||||
VDBG("VIA PCR %02x\n", data);
|
||||
break;
|
||||
case VIA_ACR:
|
||||
if(data & 0xe0)
|
||||
VDBG("VIA ACR %02x\n", data);
|
||||
break;
|
||||
case VIA_T2CH:
|
||||
VDBG("VIA T2CH %02x [ACR=%02x]\n", data, via_regs[VIA_ACR]);
|
||||
// writing T2CH loads the low 8 bits from the latch
|
||||
via_t2c = via_regs[VIA_T2CL] | (data << 8);
|
||||
VDBG("VIA Loaded timer 2 with %d cycles\n", via_t2c);
|
||||
if(via_t2c > 0 && GET_CYCLES() > via_t2c) {
|
||||
SET_CYCLES(via_t2c);
|
||||
}
|
||||
// writing T2CH clears associated IRQ flag
|
||||
irq_active &= ~VIA_IRQ_T2;
|
||||
via_assess_irq();
|
||||
break;
|
||||
case VIA_T2CL:
|
||||
VDBG("VIA T2CL %02x [ACR=%02x]\n", data, via_regs[VIA_ACR]);
|
||||
break;
|
||||
default:
|
||||
VDBG("[VIA: unhandled WR %02x to %s (reg 0x%x)]\n", data, rname, r);
|
||||
}
|
||||
|
|
@ -282,6 +306,15 @@ uint8_t via_read(unsigned int address)
|
|||
case VIA_IFR:
|
||||
data = via_read_ifr();
|
||||
break;
|
||||
|
||||
case VIA_T2LL:
|
||||
// not right, should be reduced according to cycles since
|
||||
// quantum began
|
||||
data = via_t2c & 0xff;
|
||||
// reading T2LL clears associated IRQ flag
|
||||
irq_active &= ~VIA_IRQ_T2;
|
||||
via_assess_irq();
|
||||
break;
|
||||
default:
|
||||
VDBG("[VIA: unhandled RD of %s (reg 0x%x)]\n", rname, r);
|
||||
}
|
||||
|
|
@ -290,10 +323,29 @@ uint8_t via_read(unsigned int address)
|
|||
return data;
|
||||
}
|
||||
|
||||
int via_limit_cycles(int cycles_in) {
|
||||
if (via_t2c > 0 && via_t2c < cycles_in) {
|
||||
return via_t2c;
|
||||
}
|
||||
return cycles_in;
|
||||
}
|
||||
|
||||
/* Time param in us */
|
||||
void via_tick(uint64_t time)
|
||||
void via_tick(int cycles)
|
||||
{
|
||||
(void)time;
|
||||
int i = via_t2c;
|
||||
if (i) {
|
||||
int old = i;
|
||||
i -= cycles;
|
||||
VDBG("Timer count down %d -> %d\n", old, i);
|
||||
if (i <= 0) {
|
||||
i = 0;
|
||||
VDBG("[VIA T2 reached zero, IRQ pending]\n");
|
||||
irq_active |= VIA_IRQ_T2;
|
||||
via_assess_irq();
|
||||
}
|
||||
via_t2c = i;
|
||||
}
|
||||
// FIXME: support actual timers.....!
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue