LocalTalk LLAP now works. Implemented this as a dummy network which responds with an ack to each enq, which coincidentally makes the Mac hang...
This commit is contained in:
parent
6d04d3b857
commit
c59ce7fbb0
|
@ -4,7 +4,7 @@ TARGET:=tme
|
||||||
MUSASHI_GEN_SRC:=musashi/m68kopac.c musashi/m68kopdm.c musashi/m68kopnz.c
|
MUSASHI_GEN_SRC:=musashi/m68kopac.c musashi/m68kopdm.c musashi/m68kopnz.c
|
||||||
MUSASHI_OP_PREGEN_SRC:=musashi/m68kops_pre.c
|
MUSASHI_OP_PREGEN_SRC:=musashi/m68kops_pre.c
|
||||||
OBJ:=$(MUSASHI_GEN_SRC:%.x=%.o) $(MUSASHI_OP_PREGEN_SRC:%.x=%.o) musashi/m68kcpu.o sdl/main.o sdl/disp.o sdl/hd.o \
|
OBJ:=$(MUSASHI_GEN_SRC:%.x=%.o) $(MUSASHI_OP_PREGEN_SRC:%.x=%.o) musashi/m68kcpu.o sdl/main.o sdl/disp.o sdl/hd.o \
|
||||||
emu.o iwm.o via.o rtc.o ncr.o scc.o mouse.o hostbuild/espspiramemu.o
|
emu.o iwm.o via.o rtc.o ncr.o scc.o mouse.o hostbuild/espspiramemu.o hexdump.o localtalk.o
|
||||||
#musashi/m68kdasm.o
|
#musashi/m68kdasm.o
|
||||||
CFLAGS=-Wall -I. -I./musashi -I./hostbuild -Og -ggdb `sdl2-config --cflags`
|
CFLAGS=-Wall -I. -I./musashi -I./hostbuild -Og -ggdb `sdl2-config --cflags`
|
||||||
LDFLAGS=`sdl2-config --libs`
|
LDFLAGS=`sdl2-config --libs`
|
||||||
|
|
|
@ -458,11 +458,11 @@ void tmeStartEmu(void *rom) {
|
||||||
printf("Creating HD and registering it...\n");
|
printf("Creating HD and registering it...\n");
|
||||||
SCSIDevice *hd=hdCreate("hd.img");
|
SCSIDevice *hd=hdCreate("hd.img");
|
||||||
ncrRegisterDevice(6, hd);
|
ncrRegisterDevice(6, hd);
|
||||||
printf("Initializing m68k...\n");
|
|
||||||
viaClear(VIA_PORTA, 0x7F);
|
viaClear(VIA_PORTA, 0x7F);
|
||||||
viaSet(VIA_PORTA, 0x80);
|
viaSet(VIA_PORTA, 0x80);
|
||||||
viaClear(VIA_PORTA, 0xFF);
|
viaClear(VIA_PORTA, 0xFF);
|
||||||
viaSet(VIA_PORTB, (1<<3));
|
viaSet(VIA_PORTB, (1<<3));
|
||||||
|
sccInit();
|
||||||
printf("Initializing m68k...\n");
|
printf("Initializing m68k...\n");
|
||||||
m68k_init();
|
m68k_init();
|
||||||
printf("Setting CPU type and resetting...");
|
printf("Setting CPU type and resetting...");
|
||||||
|
@ -475,6 +475,7 @@ void tmeStartEmu(void *rom) {
|
||||||
for (x=0; x<8000000/60; x+=10) {
|
for (x=0; x<8000000/60; x+=10) {
|
||||||
m68k_execute(10);
|
m68k_execute(10);
|
||||||
viaStep(1); //should run at 783.36KHz
|
viaStep(1); //should run at 783.36KHz
|
||||||
|
sccTick();
|
||||||
m++;
|
m++;
|
||||||
if (m>=1000) {
|
if (m>=1000) {
|
||||||
int r=mouseTick();
|
int r=mouseTick();
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
//Utility function to perform hexdumps in the default format of the bsd hexdump utility
|
||||||
|
//(C) 2017 Jeroen Domburg <jeroen at spritesmods dot com>
|
||||||
|
//This file is public domain where possible or CC0-licensed where not.
|
||||||
|
//CC0: https://creativecommons.org/share-your-work/public-domain/cc0/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void hexdumpFrom(void *mem, int len, int adrStart) {
|
||||||
|
uint8_t *data=(uint8_t*)mem;
|
||||||
|
int pos=0;
|
||||||
|
while (pos<len) {
|
||||||
|
//Print address
|
||||||
|
printf("%08x", pos+adrStart);
|
||||||
|
//Print hex bytes
|
||||||
|
for (int i=0; i<16; i++) {
|
||||||
|
if ((i&7)==0) printf(" ");
|
||||||
|
if (pos+i<len) {
|
||||||
|
printf(" %02x", data[pos+i]);
|
||||||
|
} else {
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Print ASCII bytes
|
||||||
|
printf(" |");
|
||||||
|
for (int i=0; i<16; i++) {
|
||||||
|
//Abort if at end
|
||||||
|
if (pos+i>=len) break;
|
||||||
|
//Print if printable
|
||||||
|
if (isprint((int)data[pos+i])) {
|
||||||
|
printf("%c", data[pos+i]);
|
||||||
|
} else {
|
||||||
|
printf(".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("|\n");
|
||||||
|
pos+=16;
|
||||||
|
}
|
||||||
|
printf("%08x\n", adrStart+len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void hexdump(void *mem, int len) {
|
||||||
|
hexdumpFrom(mem, len, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Uncomment the following line and compile 'gcc -o hexdump hexdump.c' to create a barebones hexdump utility that
|
||||||
|
//reads stdin and dumps the hex content of it to stdout
|
||||||
|
//#define TESTCASE
|
||||||
|
|
||||||
|
#ifdef TESTCASE
|
||||||
|
#include <stdlib.h>
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
char buff[1024];
|
||||||
|
int adr=0;
|
||||||
|
if (argc>1) adr=strtol(argv[1], NULL, 0);
|
||||||
|
int i=0;
|
||||||
|
int ch;
|
||||||
|
while ((ch=getchar())!=EOF) buff[i++]=ch;
|
||||||
|
hexdumpFrom(buff, i, adr);
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef HEXDUMP_H
|
||||||
|
#define HEXDUMP_H
|
||||||
|
|
||||||
|
void hexdump(void *mem, int len);
|
||||||
|
void hexdumpFrom(void *mem, int len, int addrFrom);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,18 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "hexdump.h"
|
||||||
|
#include "scc.h"
|
||||||
|
|
||||||
|
void localtalkSend(uint8_t *data, int len) {
|
||||||
|
uint8_t resp[128];
|
||||||
|
if (data[2]==0x81) {
|
||||||
|
resp[0]=data[1];
|
||||||
|
resp[1]=data[0];
|
||||||
|
resp[2]=0x82;
|
||||||
|
sccRecv(1, resp, 3);
|
||||||
|
printf("LocalTalk: Sent ack\n");
|
||||||
|
} else {
|
||||||
|
printf("LocalTalk... errm... dunno what to do with this (cmd=%x).\n", data[2]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef LOCALTALK_H
|
||||||
|
#define LOCALTALK_H
|
||||||
|
|
||||||
|
void localtalkSend(uint8_t *data, int len);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -19,6 +19,8 @@ void rtcTick() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void saveRtcMem(char *mem);
|
||||||
|
|
||||||
int rtcCom(int en, int dat, int clk) {
|
int rtcCom(int en, int dat, int clk) {
|
||||||
int ret=0;
|
int ret=0;
|
||||||
clk=clk?1:0;
|
clk=clk?1:0;
|
||||||
|
@ -35,7 +37,10 @@ int rtcCom(int en, int dat, int clk) {
|
||||||
}
|
}
|
||||||
ret=((rtc.cmd&(1<<(15-rtc.pos)))?1:0);
|
ret=((rtc.cmd&(1<<(15-rtc.pos)))?1:0);
|
||||||
} else if (rtc.pos==15) {
|
} else if (rtc.pos==15) {
|
||||||
if ((rtc.cmd&0x8000)==0) rtc.mem[(rtc.cmd&0x7C00)>>10]=rtc.cmd&0xff;
|
if ((rtc.cmd&0x8000)==0) {
|
||||||
|
rtc.mem[(rtc.cmd&0x7C00)>>10]=rtc.cmd&0xff;
|
||||||
|
saveRtcMem(rtc.mem);
|
||||||
|
}
|
||||||
printf("RTC/PRAM CMD %x\n", rtc.cmd);
|
printf("RTC/PRAM CMD %x\n", rtc.cmd);
|
||||||
}
|
}
|
||||||
rtc.pos++;
|
rtc.pos++;
|
||||||
|
@ -45,3 +50,6 @@ int rtcCom(int en, int dat, int clk) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rtcInit(char *mem) {
|
||||||
|
memcpy(rtc.mem, mem, 32);
|
||||||
|
}
|
||||||
|
|
|
@ -2,23 +2,40 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "scc.h"
|
#include "scc.h"
|
||||||
#include "m68k.h"
|
#include "m68k.h"
|
||||||
|
#include "hexdump.h"
|
||||||
|
#include "localtalk.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
THis is an extremely minimal SCC implementation: it only somewhat implements the interrupt mechanism for the
|
Emulation of the Zilog 8530 SCC.
|
||||||
|
|
||||||
|
This is an extremely minimal SCC implementation: it only somewhat implements the interrupt mechanism for the
|
||||||
DCD pins because that is what is needed for the mouse to work.
|
DCD pins because that is what is needed for the mouse to work.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
void sccIrq(int ena);
|
void sccIrq(int ena);
|
||||||
|
|
||||||
|
#define BUFLEN 8192
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int dcd;
|
||||||
|
int cts;
|
||||||
|
int wr1;
|
||||||
|
int sdlcaddr;
|
||||||
|
int wr15;
|
||||||
|
int hunting;
|
||||||
|
int txTimer;
|
||||||
|
uint8_t txData[BUFLEN];
|
||||||
|
uint8_t rxData[BUFLEN];
|
||||||
|
int txPos, rxPos, rxLen;
|
||||||
|
int rxDelay;
|
||||||
|
} SccChan;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int regptr;
|
int regptr;
|
||||||
int intpending;
|
int intpending;
|
||||||
int intpendingOld;
|
int intpendingOld;
|
||||||
int dcd[2];
|
SccChan chan[2];
|
||||||
int cts[2];
|
|
||||||
int wr1[2];
|
|
||||||
int wr15[2];
|
|
||||||
} Scc;
|
} Scc;
|
||||||
|
|
||||||
static Scc scc;
|
static Scc scc;
|
||||||
|
@ -40,8 +57,9 @@ static Scc scc;
|
||||||
#define SCC_WR3_CHA_TX (1<<4)
|
#define SCC_WR3_CHA_TX (1<<4)
|
||||||
#define SCC_WR3_CHA_RX (1<<5)
|
#define SCC_WR3_CHA_RX (1<<5)
|
||||||
|
|
||||||
|
|
||||||
static void raiseInt(int chan) {
|
static void raiseInt(int chan) {
|
||||||
if ((scc.wr1[chan]&1) && (scc.intpending&(~scc.intpendingOld))) {
|
if ((scc.chan[chan].wr1&1) && (scc.intpending&(~scc.intpendingOld))) {
|
||||||
scc.intpendingOld=scc.intpending;
|
scc.intpendingOld=scc.intpending;
|
||||||
// printf("SCC int, pending %x\n", scc.intpending);
|
// printf("SCC int, pending %x\n", scc.intpending);
|
||||||
sccIrq(1);
|
sccIrq(1);
|
||||||
|
@ -50,18 +68,59 @@ static void raiseInt(int chan) {
|
||||||
|
|
||||||
void sccSetDcd(int chan, int val) {
|
void sccSetDcd(int chan, int val) {
|
||||||
val=val?1:0;
|
val=val?1:0;
|
||||||
if (scc.dcd[chan]!=val) {
|
if (scc.chan[chan].dcd!=val) {
|
||||||
if (chan==SCC_CHANA) {
|
if (chan==SCC_CHANA) {
|
||||||
scc.intpending|=SCC_WR3_CHA_EXT;
|
if (scc.chan[SCC_CHANA].wr15&SCC_WR15_DCD) {
|
||||||
|
scc.intpending|=SCC_WR3_CHA_EXT;
|
||||||
|
raiseInt(SCC_CHANA);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
scc.intpending|=SCC_WR3_CHB_EXT;
|
if (scc.chan[SCC_CHANB].wr15&SCC_WR15_DCD) {
|
||||||
|
scc.intpending|=SCC_WR3_CHB_EXT;
|
||||||
|
raiseInt(SCC_CHANB);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((scc.intpending&SCC_WR3_CHA_EXT) && (scc.wr15[SCC_CHANA]&SCC_WR15_DCD)) raiseInt(SCC_CHANA);
|
scc.chan[chan].dcd=val;
|
||||||
if ((scc.intpending&SCC_WR3_CHB_EXT) && (scc.wr15[SCC_CHANB]&SCC_WR15_DCD)) raiseInt(SCC_CHANB);
|
}
|
||||||
if ((scc.intpending&SCC_WR3_CHA_EXT) && (scc.wr15[SCC_CHANA]&SCC_WR15_CTS)) raiseInt(SCC_CHANA);
|
|
||||||
if ((scc.intpending&SCC_WR3_CHB_EXT) && (scc.wr15[SCC_CHANB]&SCC_WR15_CTS)) raiseInt(SCC_CHANB);
|
void sccTxFinished(int chan) {
|
||||||
scc.dcd[chan]=val;
|
hexdump(scc.chan[chan].txData, scc.chan[chan].txPos);
|
||||||
|
localtalkSend(scc.chan[chan].txData, scc.chan[chan].txPos);
|
||||||
|
scc.chan[chan].txPos=0;
|
||||||
|
scc.chan[chan].hunting=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sccRecv(int chan, uint8_t *data, int len) {
|
||||||
|
memcpy(scc.chan[chan].rxData, data, len);
|
||||||
|
scc.chan[chan].rxData[len]=0xA5; //crc1
|
||||||
|
scc.chan[chan].rxData[len+1]=0xA5; //crc2
|
||||||
|
scc.chan[chan].rxData[len+2]=0; //abort
|
||||||
|
scc.chan[chan].rxLen=len+3;
|
||||||
|
scc.chan[chan].rxDelay=30;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void triggerRx(int chan) {
|
||||||
|
if (!scc.chan[chan].hunting) return;
|
||||||
|
printf("Receiving:\n");
|
||||||
|
hexdump(scc.chan[chan].rxData, scc.chan[chan].rxLen);
|
||||||
|
if (scc.chan[chan].rxData[0]==0xFF || scc.chan[chan].rxData[0]==scc.chan[chan].sdlcaddr) {
|
||||||
|
scc.chan[chan].rxPos=0;
|
||||||
|
//Sync int
|
||||||
|
if (scc.chan[chan].wr15&SCC_WR15_SYNC) {
|
||||||
|
scc.intpending|=(chan?SCC_WR3_CHA_EXT:SCC_WR3_CHB_EXT);
|
||||||
|
raiseInt(chan);
|
||||||
|
}
|
||||||
|
//RxD int
|
||||||
|
int rxintena=scc.chan[chan].wr1&0x18;
|
||||||
|
if (rxintena==0x10 || rxintena==0x08) {
|
||||||
|
scc.intpending|=(chan?SCC_WR3_CHA_RX:SCC_WR3_CHB_RX);
|
||||||
|
raiseInt(chan);
|
||||||
|
}
|
||||||
|
scc.chan[chan].hunting=0;
|
||||||
|
} else {
|
||||||
|
scc.chan[chan].rxLen=0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sccWrite(unsigned int addr, unsigned int val) {
|
void sccWrite(unsigned int addr, unsigned int val) {
|
||||||
|
@ -75,6 +134,7 @@ void sccWrite(unsigned int addr, unsigned int val) {
|
||||||
reg=scc.regptr;
|
reg=scc.regptr;
|
||||||
scc.regptr=0;
|
scc.regptr=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg==0) {
|
if (reg==0) {
|
||||||
scc.regptr=val&0x7;
|
scc.regptr=val&0x7;
|
||||||
if ((val&0x38)==0x8) scc.regptr|=8;
|
if ((val&0x38)==0x8) scc.regptr|=8;
|
||||||
|
@ -82,12 +142,31 @@ void sccWrite(unsigned int addr, unsigned int val) {
|
||||||
scc.intpending=0;
|
scc.intpending=0;
|
||||||
scc.intpendingOld=0;
|
scc.intpendingOld=0;
|
||||||
}
|
}
|
||||||
|
if ((val&0x38)==0x18) {
|
||||||
|
//SCC abort: parse whatever we sent
|
||||||
|
printf("SCC ABORT: Sent data\n");
|
||||||
|
sccTxFinished(chan);
|
||||||
|
}
|
||||||
|
if ((val&0xc0)==0xC0) {
|
||||||
|
//reset tx underrun latch
|
||||||
|
if (scc.chan[chan].txTimer==0) scc.chan[chan].txTimer=-1;
|
||||||
|
}
|
||||||
} else if (reg==1) {
|
} else if (reg==1) {
|
||||||
scc.wr1[chan]=val;
|
scc.chan[chan].wr1=val;
|
||||||
|
} else if (reg==3) {
|
||||||
|
//bitsperchar1, bitsperchar0, autoenables, enterhuntmode, rxcrcen, addresssearch, synccharloadinh, rxena
|
||||||
|
//autoenable: cts = tx ena, dcd = rx ena
|
||||||
|
if (val&0x10) scc.chan[chan].hunting=1;
|
||||||
|
} else if (reg==6) {
|
||||||
|
scc.chan[chan].sdlcaddr=val;
|
||||||
|
} else if (reg==8) {
|
||||||
|
scc.chan[chan].txData[scc.chan[chan].txPos++]=val;
|
||||||
|
printf("TX! Pos %d\n", scc.chan[chan].txPos);
|
||||||
|
scc.chan[chan].txTimer+=30;
|
||||||
} else if (reg==15) {
|
} else if (reg==15) {
|
||||||
scc.wr15[chan]=val;
|
scc.chan[chan].wr15=val;
|
||||||
}
|
}
|
||||||
// printf("SCC: write to addr %x chan %d reg %d val %x\n", addr, chan, reg, val);
|
printf("SCC: write to addr %x chan %d reg %d val %x\n", addr, chan, reg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -103,11 +182,17 @@ unsigned int sccRead(unsigned int addr) {
|
||||||
scc.regptr=0;
|
scc.regptr=0;
|
||||||
}
|
}
|
||||||
if (reg==0) {
|
if (reg==0) {
|
||||||
val=(1<<2);
|
val=(1<<2); //tx buffer always empty
|
||||||
if (scc.dcd[chan]) val|=(1<<3);
|
if (scc.chan[chan].rxLen && !scc.chan[chan].rxDelay) val|=(1<<0);
|
||||||
if (scc.cts[chan]) val|=(1<<5);
|
if (scc.chan[chan].txTimer==0) val|=(1<<6);
|
||||||
|
if (scc.chan[chan].dcd) val|=(1<<3);
|
||||||
|
if (scc.chan[chan].cts) val|=(1<<5);
|
||||||
|
if (scc.chan[chan].hunting) val|=(1<<4);
|
||||||
|
if (scc.chan[chan].rxPos==scc.chan[chan].rxLen-1) val|=(1<<7); //abort
|
||||||
} else if (reg==1) {
|
} else if (reg==1) {
|
||||||
val=scc.wr1[chan];
|
//EndOfFrame, CRCErr, RXOverrun, ParityErr, Residue0, Residue1, Residue2, AllSent
|
||||||
|
val=0x7; //residue code 011, all sent
|
||||||
|
if (scc.chan[chan].rxPos==scc.chan[chan].rxLen-2) val|=(1<<7); //end of frame
|
||||||
} else if (reg==2 && chan==SCC_CHANB) {
|
} else if (reg==2 && chan==SCC_CHANB) {
|
||||||
//We assume this also does an intack.
|
//We assume this also does an intack.
|
||||||
int rsn=0;
|
int rsn=0;
|
||||||
|
@ -124,10 +209,60 @@ unsigned int sccRead(unsigned int addr) {
|
||||||
if (scc.intpending&0x07) raiseInt(SCC_CHANB);
|
if (scc.intpending&0x07) raiseInt(SCC_CHANB);
|
||||||
} else if (reg==3) {
|
} else if (reg==3) {
|
||||||
if (chan==SCC_CHANA) val=scc.intpending; else val=0;
|
if (chan==SCC_CHANA) val=scc.intpending; else val=0;
|
||||||
|
} else if (reg==8) {
|
||||||
|
//rx buffer
|
||||||
|
if (scc.chan[chan].rxLen && !scc.chan[chan].rxDelay) {
|
||||||
|
val=scc.chan[chan].rxData[scc.chan[chan].rxPos++];
|
||||||
|
if (scc.chan[chan].rxPos==scc.chan[chan].rxLen) {
|
||||||
|
scc.chan[chan].rxLen=0;
|
||||||
|
} else {
|
||||||
|
int rxintena=scc.chan[chan].wr1&0x18;
|
||||||
|
if (rxintena==0x10) {
|
||||||
|
scc.intpending|=(chan?SCC_WR3_CHA_RX:SCC_WR3_CHB_RX);
|
||||||
|
raiseInt(chan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (scc.chan[chan].rxPos==scc.chan[chan].rxLen-1) scc.chan[chan].hunting=1;
|
||||||
|
if (scc.chan[chan].rxPos==scc.chan[chan].rxLen-1 && scc.chan[chan].wr15&SCC_WR15_BREAK) {
|
||||||
|
scc.intpending|=(chan?SCC_WR3_CHA_EXT:SCC_WR3_CHB_EXT);
|
||||||
|
raiseInt(chan);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val=0;
|
||||||
|
}
|
||||||
|
} else if (reg==10) {
|
||||||
|
//Misc status (mostly SDLC)
|
||||||
|
val=0;
|
||||||
} else if (reg==15) {
|
} else if (reg==15) {
|
||||||
val=scc.wr15[chan];
|
val=scc.chan[chan].wr15;
|
||||||
}
|
}
|
||||||
// printf("SCC: read from chan %d reg %d val %x\n", chan, reg, val);
|
printf("SCC: read from chan %d reg %d val %x\n", chan, reg, val);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Called at about 800KHz
|
||||||
|
void sccTick() {
|
||||||
|
for (int n=0; n<2; n++) {
|
||||||
|
if (scc.chan[n].txTimer>0) {
|
||||||
|
scc.chan[n].txTimer--;
|
||||||
|
if (scc.chan[n].txTimer==0) {
|
||||||
|
printf("Tx buffer empty: Sent data\n");
|
||||||
|
sccTxFinished(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (scc.chan[n].rxDelay!=0) {
|
||||||
|
scc.chan[n].rxDelay--;
|
||||||
|
if (scc.chan[n].rxDelay==0) {
|
||||||
|
triggerRx(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sccInit() {
|
||||||
|
sccSetDcd(1, 1);
|
||||||
|
sccSetDcd(2, 1);
|
||||||
|
scc.chan[0].txTimer=-1;
|
||||||
|
scc.chan[1].txTimer=-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,4 +5,7 @@
|
||||||
void sccWrite(unsigned int addr, unsigned int val);
|
void sccWrite(unsigned int addr, unsigned int val);
|
||||||
unsigned int sccRead(unsigned int addr);
|
unsigned int sccRead(unsigned int addr);
|
||||||
void sccSetDcd(int chan, int val);
|
void sccSetDcd(int chan, int val);
|
||||||
|
void sccInit();
|
||||||
|
void sccTick();
|
||||||
|
void sccRecv(int chan, uint8_t *data, int len);
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,22 @@ static void *loadRom(char *file) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void saveRtcMem(char *data) {
|
||||||
|
FILE *f=fopen("pram.dat", "wb");
|
||||||
|
if (f!=NULL) {
|
||||||
|
fwrite(data, 32, 1, f);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
void *rom=loadRom("rom.bin");
|
void *rom=loadRom("rom.bin");
|
||||||
|
FILE *f=fopen("pram.dat", "r");
|
||||||
|
if (f!=NULL) {
|
||||||
|
char data[32];
|
||||||
|
fread(data, 32, 1, f);
|
||||||
|
rtcInit(data);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
tmeStartEmu(rom);
|
tmeStartEmu(rom);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue