2019-12-19 00:27:23 +00:00
|
|
|
#pragma once
|
2019-12-24 23:34:02 +00:00
|
|
|
#include "arm710.h"
|
2019-12-19 00:27:23 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
struct Timer {
|
2019-12-24 23:34:02 +00:00
|
|
|
ARM710 *cpu;
|
2019-12-19 00:27:23 +00:00
|
|
|
|
|
|
|
enum {
|
|
|
|
MODE_512KHZ = 1<<3,
|
|
|
|
PERIODIC = 1<<6,
|
|
|
|
ENABLED = 1<<7
|
|
|
|
};
|
2019-12-26 00:19:37 +00:00
|
|
|
int64_t nextTickAt;
|
2019-12-19 00:27:23 +00:00
|
|
|
uint8_t config;
|
|
|
|
uint32_t interval;
|
|
|
|
int32_t value;
|
2019-12-24 23:34:02 +00:00
|
|
|
int clockSpeed;
|
2019-12-19 00:27:23 +00:00
|
|
|
|
|
|
|
int tickInterval() const {
|
2019-12-24 23:34:02 +00:00
|
|
|
return (config & MODE_512KHZ) ? (clockSpeed / 512000) : (clockSpeed / 2000);
|
2019-12-19 00:27:23 +00:00
|
|
|
}
|
|
|
|
void load(uint32_t lval) {
|
|
|
|
interval = lval;
|
|
|
|
value = lval;
|
|
|
|
}
|
2019-12-26 00:19:37 +00:00
|
|
|
void setConfig(uint8_t cval) {
|
|
|
|
nextTickAt -= tickInterval();
|
|
|
|
config = cval;
|
|
|
|
nextTickAt += tickInterval();
|
|
|
|
}
|
2019-12-19 00:27:23 +00:00
|
|
|
bool tick(int64_t cycles) {
|
2019-12-26 00:19:37 +00:00
|
|
|
if (cycles >= nextTickAt) {
|
|
|
|
nextTickAt += tickInterval();
|
2019-12-19 00:27:23 +00:00
|
|
|
|
|
|
|
if (config & ENABLED) {
|
|
|
|
--value;
|
|
|
|
if (value == 0) {
|
|
|
|
if (config & PERIODIC)
|
|
|
|
value = interval;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
void dump() {
|
|
|
|
printf("enabled=%s periodic=%s interval=%d value=%d\n",
|
|
|
|
(config & ENABLED) ? "true" : "false",
|
|
|
|
(config & PERIODIC) ? "true" : "false",
|
|
|
|
interval, value
|
|
|
|
);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-12-24 23:34:02 +00:00
|
|
|
enum UartRegs {
|
|
|
|
UART0DATA = 0x600,
|
|
|
|
UART0FCR = 0x604,
|
|
|
|
UART0LCR = 0x608,
|
|
|
|
UART0CON = 0x60C,
|
|
|
|
UART0FLG = 0x610,
|
|
|
|
UART0INT = 0x614,
|
|
|
|
UART0INTM = 0x618,
|
|
|
|
UART0INTR = 0x61C,
|
|
|
|
UART0TEST1 = 0x620,
|
|
|
|
UART0TEST2 = 0x624,
|
|
|
|
UART0TEST3 = 0x628,
|
|
|
|
UART1DATA = 0x700,
|
|
|
|
UART1FCR = 0x704,
|
|
|
|
UART1LCR = 0x708,
|
|
|
|
UART1CON = 0x70C,
|
|
|
|
UART1FLG = 0x710,
|
|
|
|
UART1INT = 0x714,
|
|
|
|
UART1INTM = 0x718,
|
|
|
|
UART1INTR = 0x71C,
|
|
|
|
UART1TEST1 = 0x720,
|
|
|
|
UART1TEST2 = 0x724,
|
|
|
|
UART1TEST3 = 0x728,
|
|
|
|
};
|
|
|
|
|
2019-12-19 00:27:23 +00:00
|
|
|
struct UART {
|
2019-12-24 23:34:02 +00:00
|
|
|
ARM710 *cpu;
|
2019-12-19 00:27:23 +00:00
|
|
|
|
|
|
|
enum {
|
|
|
|
IntRx = 1,
|
|
|
|
IntTx = 2,
|
|
|
|
IntModemStatus = 4,
|
|
|
|
PortCtrlEnable = 1,
|
|
|
|
PortCtrlSirEnable = 2,
|
|
|
|
PortCtrlIrdaTx = 4,
|
|
|
|
FrameCtrlBreak = 1,
|
|
|
|
FrameCtrlParityEnable = 2,
|
|
|
|
FrameCtrlEvenParity = 4,
|
|
|
|
FrameCtrlExtraStopBit = 8,
|
|
|
|
FrameCtrlUFifoEn = 0x10,
|
|
|
|
FrameCtrlWrdLenMask = 0x60,
|
|
|
|
FrameCtrlWlen5 = 0,
|
|
|
|
FrameCtrlWlen6 = 0x20,
|
|
|
|
FrameCtrlWlen7 = 0x40,
|
|
|
|
FrameCtrlWlen8 = 0x60,
|
|
|
|
RecvFrameError = 0x100,
|
|
|
|
RecvParityError = 0x200,
|
|
|
|
RecvOverrunError = 0x400,
|
|
|
|
FlagClearToSend = 1,
|
|
|
|
FlagDataSetReady = 2,
|
|
|
|
FlagDataCarrierDetect = 4,
|
|
|
|
FlagBusy = 8,
|
|
|
|
FlagReceiveFifoEmpty = 0x10,
|
|
|
|
FlagTransmitFifoFull = 0x20
|
|
|
|
};
|
|
|
|
uint8_t portControl = 0;
|
|
|
|
uint8_t frameControl = 0;
|
|
|
|
uint8_t interrupts = 0, interruptMask = 0;
|
|
|
|
|
|
|
|
// UART0DATA = 0x600, byte write, long read
|
|
|
|
// UART0FCR = 0x604, long
|
|
|
|
// UART0LCR = 0x608, long
|
|
|
|
// UART0CON = 0x60C, byte
|
|
|
|
// UART0FLG = 0x610, byte
|
|
|
|
// UART0INT = 0x614, long write, byte read
|
|
|
|
// UART0INTM = 0x618, byte
|
|
|
|
// UART0INTR = 0x61C, byte
|
|
|
|
// UART0TEST1 = 0x620,
|
|
|
|
// UART0TEST2 = 0x624,
|
|
|
|
// UART0TEST3 = 0x628,
|
|
|
|
uint32_t readReg8(uint32_t reg) {
|
|
|
|
// UART0DATA
|
|
|
|
if (reg == (UART0CON & 0xFF)) {
|
|
|
|
return portControl;
|
|
|
|
} else if (reg == (UART0FLG & 0xFF)) {
|
|
|
|
// we pretend we are never busy, never have full fifo
|
|
|
|
return FlagReceiveFifoEmpty;
|
|
|
|
// UART0INT?
|
|
|
|
// UART0INTM?
|
|
|
|
// UART0INTR?
|
|
|
|
} else {
|
2019-12-22 05:02:55 +00:00
|
|
|
printf("unhandled 8bit uart read %x at pc=%08x lr=%08x\n", reg, cpu->getGPR(15), cpu->getGPR(14));
|
2019-12-19 00:27:23 +00:00
|
|
|
return 0xFF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
uint32_t readReg32(uint32_t reg) {
|
|
|
|
// UART0DATA
|
|
|
|
if (reg == (UART0FCR & 0xFF)) {
|
|
|
|
return frameControl;
|
|
|
|
// UART0LCR
|
2019-12-21 11:09:58 +00:00
|
|
|
} else if (reg == (UART0FLG & 0xFF)) {
|
|
|
|
// we pretend we are never busy, never have full fifo
|
|
|
|
return FlagReceiveFifoEmpty;
|
2019-12-19 00:27:23 +00:00
|
|
|
} else {
|
2019-12-22 05:02:55 +00:00
|
|
|
printf("unhandled 32bit uart read %x at pc=%08x lr=%08x\n", reg, cpu->getGPR(15), cpu->getGPR(14));
|
2019-12-19 00:27:23 +00:00
|
|
|
return 0xFFFFFFFF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void writeReg8(uint32_t reg, uint8_t value) {
|
|
|
|
// UART0DATA
|
|
|
|
if (reg == (UART0CON & 0xFF)) {
|
|
|
|
portControl = value;
|
|
|
|
printf("portcon updated: enable=%d sirenable=%d irdatx=%d\n", value&1, value&2, value&4);
|
|
|
|
} else if (reg == (UART0INTM & 0xFF)) {
|
|
|
|
interruptMask = value;
|
|
|
|
printf("uart interruptmask updated: %d\n", value);
|
|
|
|
// UART0INTR?
|
|
|
|
} else {
|
2019-12-22 05:02:55 +00:00
|
|
|
printf("unhandled 8bit uart write %x value %02x at pc=%08x lr=%08x\n", reg, value, cpu->getGPR(15), cpu->getGPR(14));
|
2019-12-19 00:27:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
void writeReg32(uint32_t reg, uint32_t value) {
|
|
|
|
if (reg == (UART0FCR & 0xFF)) {
|
|
|
|
frameControl = value;
|
|
|
|
printf("frameControl updated: break=%d parityEn=%d evenParity=%d extraStop=%d ufifoEn=%d wrdLen=%d\n",
|
|
|
|
value&1,
|
|
|
|
value&2,
|
|
|
|
value&4,
|
|
|
|
value&8,
|
|
|
|
value&0x10,
|
|
|
|
((value&0x60)>>5)+5);
|
|
|
|
} else if (reg == (UART0LCR & 0xFF)) {
|
|
|
|
printf("** uart writing lcr %x **\n", value);
|
|
|
|
} else if (reg == (UART0INT & 0xFF)) {
|
|
|
|
printf("uart interrupts %x -> %x\n", interrupts, value);
|
|
|
|
interrupts = value;
|
|
|
|
} else {
|
2019-12-22 05:02:55 +00:00
|
|
|
printf("unhandled 32bit uart write %x value %08x at pc=%08x lr=%08x\n", reg, value, cpu->getGPR(15), cpu->getGPR(14));
|
2019-12-19 00:27:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|