add initial psram support and 8086 emulator for PICO

This commit is contained in:
jean-marcharvengt 2021-10-12 21:28:12 +02:00
parent 6a66f7ed41
commit 9685fa074b
26 changed files with 11253 additions and 2 deletions

View file

@ -19,6 +19,7 @@ add_subdirectory(FatFs_SPI build)
include_directories(config)
include_directories(vga_t4)
include_directories(tft_t)
include_directories(psram)
set(PICO81_SOURCES
@ -193,6 +194,19 @@ set(PICONOFRENDO_SOURCES
piconofrendo/AudioPlaySystem.cpp
)
set(PICO8086_SOURCES
pico8086/cpu.cpp
pico8086/disk.cpp
pico8086/network.cpp
pico8086/ports.cpp
pico8086/i8253.cpp
pico8086/i8259.cpp
pico8086/pc.cpp
pico8086/emuapi.cpp
pico8086/pico8086.cpp
pico8086/AudioPlaySystem.cpp
)
set(PICOSND_SOURCES
# picosnd/LibFC14/Dump.cpp
# picosnd/LibFC14/FC_Data.cpp
@ -220,6 +234,10 @@ set(VGA_T4_SOURCES
vga_t4/scanvideo.c
)
set(PSRAM_SOURCES
psram/psram_t.cpp
)
set(TFT_T_SOURCES
tft_t/tft_t_dma.cpp
)
@ -242,6 +260,11 @@ set(TESTTFT_SOURCES
testtft/emuapi.cpp
)
set(TESTPSRAM_SOURCES
testpsram/testpsram.cpp
testpsram/emuapi.cpp
)
#add_compile_definitions(OVERRULE_WIDTH=320 OVERRULE_HEIGHT=192)
add_executable(mcume
# ${GFXENGINE_SOURCES}
@ -249,6 +272,7 @@ add_executable(mcume
# ${PICO81_SOURCES}
# ${PICO800_SOURCES}
# ${PICO5200_SOURCES}
# ${PICO8086_SOURCES}
# ${PICOCOLEM_SOURCES}
# ${PICOO2EM_SOURCES}
# ${PICOVCS_SOURCES}
@ -258,6 +282,8 @@ add_executable(mcume
# ${TESTIO_SOURCES}
# ${TESTVGA_SOURCES}
# ${TESTTFT_SOURCES}
# ${TESTPSRAM_SOURCES}
${PSRAM_SOURCES}
${VGA_T4_SOURCES}
${TFT_T_SOURCES}
)

View file

@ -93,6 +93,14 @@
#define SD_CS 13
#define SD_DETECT 255 // 22
// PSRAM (exclusive with TFT)
#define PSRAM_SPIREG spi0
#define PSRAM_SCLK 18
#define PSRAM_MOSI 19
#define PSRAM_MISO 16 // DC
#define PSRAM_CS 17
#ifdef PICOMPUTER
// Keyboard matrix
//Cols (out)

View file

@ -37,10 +37,11 @@
#endif
#ifdef MCUME_REV2
//#define HAS_PSRAM 1
#define USE_VGA 1
//#define ILI9341 1
#define ST7789 1
#define ST7789_POL 1
//#define ST7789 1
//#define ST7789_POL 1
#define INVX 1
#define HAS_SND 1
#endif

View file

@ -0,0 +1,176 @@
#include "emuapi.h"
#ifdef HAS_SND
#include "AudioPlaySystem.h"
#define SAMPLERATE AUDIO_SAMPLE_RATE_EXACT
#define CLOCKFREQ 985248
#ifndef CUSTOM_SND
static const short square[]={
32767,32767,32767,32767,
32767,32767,32767,32767,
32767,32767,32767,32767,
32767,32767,32767,32767,
32767,32767,32767,32767,
32767,32767,32767,32767,
32767,32767,32767,32767,
32767,32767,32767,32767,
-32767,-32767,-32767,-32767,
-32767,-32767,-32767,-32767,
-32767,-32767,-32767,-32767,
-32767,-32767,-32767,-32767,
-32767,-32767,-32767,-32767,
-32767,-32767,-32767,-32767,
-32767,-32767,-32767,-32767,
-32767,-32767,-32767,-32767,
};
const short noise[] {
-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,
-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,-32767,32767,-32767,
-32767,-32767,32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,32767,-32767,
-32767,-32767,32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,32767,-32767,-32767,32767,32767,-32767,
-32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,32767,-32767,-32767,32767,32767,-32767,
-32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,32767,-32767,32767,32767,32767,-32767,
32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,32767,-32767,32767,32767,32767,-32767,
32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,32767,32767,32767,32767,32767,-32767,
32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,32767,32767,32767,32767,32767,-32767,
32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,-32767,-32767,32767,32767,32767,-32767,-32767,
32767,-32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,-32767,32767,32767,32767,32767,32767,-32767,
32767,-32767,32767,-32767,-32767,32767,32767,-32767,-32767,32767,-32767,32767,32767,32767,-32767,-32767,
32767,32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,-32767,32767,32767,32767,32767,32767,-32767,
32767,-32767,32767,-32767,-32767,32767,32767,-32767,32767,32767,-32767,32767,-32767,32767,-32767,-32767,
32767,32767,-32767,-32767,-32767,32767,-32767,-32767,-32767,-32767,32767,32767,32767,32767,32767,-32767,
32767,-32767,32767,-32767,-32767,32767,32767,32767,32767,32767,-32767,32767,-32767,32767,-32767,-32767,
};
#define NOISEBSIZE 0x100
typedef struct
{
unsigned int spos;
unsigned int sinc;
unsigned int vol;
} Channel;
static Channel chan[6] = {
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0} };
#endif
volatile bool playing = false;
static void snd_Reset(void)
{
#ifndef CUSTOM_SND
chan[0].vol = 0;
chan[1].vol = 0;
chan[2].vol = 0;
chan[3].vol = 0;
chan[4].vol = 0;
chan[5].vol = 0;
chan[0].sinc = 0;
chan[1].sinc = 0;
chan[2].sinc = 0;
chan[3].sinc = 0;
chan[4].sinc = 0;
chan[5].sinc = 0;
#endif
}
#ifdef CUSTOM_SND
//extern "C" {
void SND_Process(void *sndbuffer, int sndn);
//}
#endif
#include <stdio.h>
void AudioPlaySystem::snd_Mixer(short * stream, int len )
{
if (playing)
{
#ifdef CUSTOM_SND
//printf("s\n");
SND_Process((void*)stream, len);
#else
int i;
long s;
len = len >> 1;
short v0=chan[0].vol;
short v1=chan[1].vol;
short v2=chan[2].vol;
short v3=chan[3].vol;
short v4=chan[4].vol;
short v5=chan[5].vol;
for (i=0;i<len;i++)
{
s =((v0*square[(chan[0].spos>>8)&0x3f])>>11);
s+=((v1*square[(chan[1].spos>>8)&0x3f])>>11);
s+=((v2*square[(chan[2].spos>>8)&0x3f])>>11);
s+=((v3*noise[(chan[3].spos>>8)&(NOISEBSIZE-1)])>>11);
s+=((v4*noise[(chan[4].spos>>8)&(NOISEBSIZE-1)])>>11);
s+=((v5*noise[(chan[5].spos>>8)&(NOISEBSIZE-1)])>>11);
*stream++ = (short)(s);
*stream++ = (short)(s);
chan[0].spos += chan[0].sinc;
chan[1].spos += chan[1].sinc;
chan[2].spos += chan[2].sinc;
chan[3].spos += chan[3].sinc;
chan[4].spos += chan[4].sinc;
chan[5].spos += chan[5].sinc;
}
#endif
}
}
void AudioPlaySystem::begin(void)
{
this->reset();
}
void AudioPlaySystem::start(void)
{
playing = true;
}
void AudioPlaySystem::setSampleParameters(float clockfreq, float samplerate) {
}
void AudioPlaySystem::reset(void)
{
snd_Reset();
}
void AudioPlaySystem::stop(void)
{
playing = false;
}
bool AudioPlaySystem::isPlaying(void)
{
return playing;
}
void AudioPlaySystem::sound(int C, int F, int V) {
#ifndef CUSTOM_SND
if (C < 6) {
chan[C].vol = V;
chan[C].sinc = F>>1;
}
#endif
}
void AudioPlaySystem::step(void) {
}
#endif

View file

@ -0,0 +1,26 @@
#ifndef audioplaysystem_h_
#define audioplaysystem_h_
#ifdef HAS_SND
#include "platform_config.h"
class AudioPlaySystem
{
public:
AudioPlaySystem(void) { };
void begin(void);
void setSampleParameters(float clockfreq, float samplerate);
void reset(void);
void start(void);
void stop(void);
bool isPlaying(void);
void sound(int C, int F, int V);
void buzz(int size, int val);
void step(void);
static void snd_Mixer(short * stream, int len );
};
#endif
#endif

2267
MCUME_pico/pico8086/cpu.cpp Executable file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,257 @@
#include <stdint.h>
#include <stdio.h>
#include "emu.h"
extern "C" {
#include "emuapi.h"
}
extern uint8_t bootdrive, hdcount;
extern uint16_t segregs[6];
extern uint8_t cf;
extern _bytewordregs_ regs;
int file;
struct struct_drive {
uint32_t filesize;
uint16_t cyls;
uint16_t sects;
uint16_t heads;
uint8_t inserted;
} disk[4];
uint8_t sectorbuffer[512];
uint8_t insertdisk(uint8_t drivenum) {
if (drivenum & 0x80) {
drivenum -= 126;
disk[drivenum].sects = 63;
disk[drivenum].heads = 16;
disk[drivenum].cyls = 1023; //up to 512 MB
hdcount = 1;
} else {
#ifdef FDD_144M
disk[drivenum].cyls = 80;
disk[drivenum].sects = 18;
disk[drivenum].heads = 2;
#endif
#ifdef FDD_122M
disk[drivenum].cyls = 80;
disk[drivenum].sects = 15;
disk[drivenum].heads = 2;
#endif
#ifdef FDD_720K
disk[drivenum].cyls = 80;
disk[drivenum].sects = 9;
disk[drivenum].heads = 2;
#endif
#ifdef FDD_360K
disk[drivenum].cyls = 40;
disk[drivenum].sects = 9;
disk[drivenum].heads = 2;
#endif
#ifdef FDD_320K
disk[drivenum].cyls = 40;
disk[drivenum].sects = 8;
disk[drivenum].heads = 2;
#endif
#ifdef FDD_180K
disk[drivenum].cyls = 40;
disk[drivenum].sects = 9;
disk[drivenum].heads = 1;
#endif
}
disk[drivenum].inserted = 1;
return 0;
}
void ejectdisk(uint8_t drivenum) {
if (drivenum & 0x80) drivenum -= 126;
disk[drivenum].inserted = 0;
}
extern uint16_t ramseg;
extern "C" {
extern void emu_SdReadBlock(int block, void * buf);
}
uint8_t sectdone;
void getsect(uint32_t lba, uint8_t *dst) {
#ifdef USB_DISK
uint8_t chksum;
uint32_t curmicros;
retrysectget:
Serial.write(0xFF);
Serial.write(0x05);
outByte(lba & 0xFF); chksum = lba & 0xFF;
outByte((lba >> 8) & 0xFF); chksum += (lba >> 8) & 0xFF;
outByte((lba >> 16) & 0xFF); chksum += (lba >> 16) & 0xFF;
outByte((lba >> 24) & 0xFF); chksum += (lba >> 24) & 0xFF;
outByte(chksum);
Serial.write(0xFE);
Serial.write(0x02);
sectdone = 0;
curmicros = micros();
while (!sectdone) {
if (micros() < curmicros) curmicros = micros();
if ((micros() - curmicros) >= 200000) goto retrysectget;
net_loop();
}
#else
if (file)
{
//printf("read block %d\n",lba);
emu_FileSeek(lba*512);
emu_FileRead((char *)dst,1*512);
}
#endif
}
void putsect(uint32_t lba, uint8_t *src) {
#ifdef USB_DISK
uint8_t chksum;
uint16_t i;
uint32_t curmicros;
retrysectput:
Serial.write(0xFF);
Serial.write(0x06);
outByte(lba & 0xFF); chksum = lba & 0xFF;
outByte((lba >> 8) & 0xFF); chksum += (lba >> 8) & 0xFF;
outByte((lba >> 16) & 0xFF); chksum += (lba >> 16) & 0xFF;
outByte((lba >> 24) & 0xFF); chksum += (lba >> 24) & 0xFF;
for (i=0; i<512; i++) {
outByte(src[i]);
chksum += src[i];
}
outByte(chksum);
Serial.write(0xFE);
Serial.write(0x02);
sectdone = 0;
curmicros = micros();
while (!sectdone) {
if (micros() < curmicros) curmicros = micros();
if ((micros() - curmicros) >= 200000) goto retrysectput;
net_loop();
}
#else
//card.writeBlock(lba, src);
#endif
}
void readdisk(uint8_t drivenum, uint16_t dstseg, uint16_t dstoff, uint16_t cyl, uint16_t sect, uint16_t head, uint16_t sectcount) {
uint32_t memdest, goodsects, dummy, lba;
if ((sect == 0) || !disk[drivenum].inserted) return;
#ifdef MEGA
SPI.setClockDivider(SPI_CLOCK_SDCARD);
#endif
lba = ((long)cyl * (long)disk[drivenum].heads + (long)head) * (long)disk[drivenum].sects + (long)sect - 1;
memdest = (uint32_t)dstseg * 16 + (uint32_t)dstoff;
for (goodsects = 0; goodsects < sectcount; goodsects++) {
getsect(lba, sectorbuffer);
memdest = (uint32_t)dstseg * 16 + (uint32_t)dstoff;
for (dummy = 0; dummy < 512; dummy++) {
write86(memdest++, sectorbuffer[dummy]);
//Serial.write(sectorbuffer[dummy]);
}
dstoff += 512;
lba++;
}
cf = 0; regs.byteregs[regah] = 0; regs.byteregs[regal] = sectcount;
#ifdef MEGA
SPI.setClockDivider(SPI_CLOCK_SPIRAM);
#endif
}
void writedisk(uint8_t drivenum, uint16_t dstseg, uint16_t dstoff, uint16_t cyl, uint16_t sect, uint16_t head, uint16_t sectcount) {
uint32_t memdest, goodsects, dummy, lba;
if ((sect == 0) || !disk[drivenum].inserted) return;
#ifdef MEGA
SPI.setClockDivider(SPI_CLOCK_SDCARD);
#endif
lba = ((long)cyl * (long)disk[drivenum].heads + (long)head) * (long)disk[drivenum].sects + (long)sect - 1;
for (goodsects = 0; goodsects < sectcount; goodsects++) {
memdest = (uint32_t)dstseg * 16 + (uint32_t)dstoff;
for (dummy = 0; dummy < 512; dummy++) {
sectorbuffer[dummy] = read86(memdest++);
}
//card.erase(lba, lba);
putsect(lba, sectorbuffer);
dstoff += 512;
lba++;
}
cf = 0; regs.byteregs[regah] = 0; regs.byteregs[regal] = sectcount;
#ifdef MEGA
SPI.setClockDivider(SPI_CLOCK_SPIRAM);
#endif
}
void diskhandler() {
static uint8_t lastdiskah[4], lastdiskcf[4];
uint8_t drivenum;
drivenum = regs.byteregs[regdl];
if (drivenum & 0x80) drivenum -= 126;
switch (regs.byteregs[regah]) {
case 0: //reset disk system
regs.byteregs[regah] = 0; cf = 0; //useless function in an emulator. say success and return.
break;
case 1: //return last status
regs.byteregs[regah] = lastdiskah[drivenum];
cf = lastdiskcf[drivenum];
return;
case 2: //read sector(s) into memory
if (disk[drivenum].inserted) {
readdisk(drivenum, segregs[reges], getreg16(regbx), (uint16_t)regs.byteregs[regch] + ((uint16_t)regs.byteregs[regcl] / 64) * 256, regs.byteregs[regcl] & 63, regs.byteregs[regdh], regs.byteregs[regal]);
cf = 0; regs.byteregs[regah] = 0;
} else {
cf = 1;
regs.byteregs[regah] = 1;
}
break;
case 3: //write sector(s) from memory
if (disk[drivenum].inserted) {
writedisk(drivenum, segregs[reges], getreg16(regbx), regs.byteregs[regch] + (regs.byteregs[regcl] / 64) * 256, regs.byteregs[regcl] & 63, regs.byteregs[regdh], regs.byteregs[regal]);
cf = 0; regs.byteregs[regah] = 0;
} else {
cf = 1;
regs.byteregs[regah] = 1;
}
break;
case 4:
case 5: //format track
cf = 0; regs.byteregs[regah] = 0;
break;
case 8: //get drive parameters
if (disk[drivenum].inserted) {
cf = 0; regs.byteregs[regah] = 0;
regs.byteregs[regch] = disk[drivenum].cyls - 1;
regs.byteregs[regcl] = disk[drivenum].sects & 63;
regs.byteregs[regcl] = regs.byteregs[regcl] + (disk[drivenum].cyls / 256) * 64;
regs.byteregs[regdh] = disk[drivenum].heads - 1;
//segregs[reges] = 0; regs.wordregs[regdi] = 0x7C0B; //floppy parameter table
if (drivenum < 2) {
regs.byteregs[regbl] = 4; //else regs.byteregs[regbl] = 0;
regs.byteregs[regdl] = 2;
} else regs.byteregs[regdl] = hdcount;
} else {
cf = 1; regs.byteregs[regah] = 0xAA;
}
break;
default:
cf = 1;
}
lastdiskah[drivenum] = regs.byteregs[regah];
lastdiskcf[drivenum] = cf;
if (regs.byteregs[regdl] & 0x80) write86(0x474, regs.byteregs[regah]);
}
void initDisk(char * filename) {
int len=emu_FileSize(filename);
file = emu_FileOpen(filename);
if (len) {
bootdrive = 0x80;
insertdisk(0x80);
hdcount = 1;
}
else {
bootdrive = 0xFF;
emu_FileClose();
file = NULL;
}
}

159
MCUME_pico/pico8086/emu.h Normal file
View file

@ -0,0 +1,159 @@
//Uncomment MEGA define if using a Mega 2560, otherwise leave undefined if using a Teensy 3.6
//#define MEGA
extern "C" {
#include "iopins.h"
#include "emuapi.h"
}
#define NATIVE_RAM (0x20000) // 128k total
#define NATIVE_START 0UL
#ifdef HAS_PSRAM
#define RAM_SIZE (0xA0000) // 640k total
#else
#define RAM_SIZE (0x24000) // 128+16k total
#endif
#define ROM_READ(a,b) a[b]
//#define INCLUDE_ROM_BASIC
//#define BOOT_FDD
#define BOOT_HDD
//#define BOOT_BASIC
//#define FDD_180K
//#define FDD_320K
//#define FDD_360K
//#define FDD_720K
//#define FDD_122M
//#define FDD_144M
#define BAUD_RATE 1000000
//#define USE_NETWORKING
//#define USE_PARALLEL
//#define PROFILING
// END ARDUINO86 USER CONFIGURABLE OPTIONS
#define regax 0
#define regcx 1
#define regdx 2
#define regbx 3
#define regsp 4
#define regbp 5
#define regsi 6
#define regdi 7
#define reges 0
#define regcs 1
#define regss 2
#define regds 3
#define regal 0
#define regah 1
#define regcl 2
#define regch 3
#define regdl 4
#define regdh 5
#define regbl 6
#define regbh 7
#define StepIP(x) ip+=x
#define getmem8(x,y) read86(segbase(x)+(uint32_t)y)
//#define getmem16(x,y) (read86(segbase(x)+y) | ((uint16_t)read86(segbase(x)+y+1)<<8))
#define getmem16(x,y) readw86(segbase(x)+(uint32_t)y)
#define putmem8(x,y,z) write86(segbase(x)+(uint32_t)y, z)
//#define putmem16(x,y,z) write86(segbase(x)+y, ((z)&0xFF)); write86(segbase(x)+y+1, (((z)>>8)&0xFF))
#define putmem16(x,y,z) writew86(segbase(x)+(uint32_t)y, z)
#define signext(value) ((((uint16_t)value&0x80)*0x1FE)|(uint16_t)value)
#define signext32(value) ((((uint32_t)value&0x8000)*0x1FFFE)|(uint32_t)value)
#define getreg16(regid) regs.wordregs[regid]
#define getreg8(regid) regs.byteregs[byteregtable[regid]]
#define putreg16(regid, writeval) regs.wordregs[regid] = writeval
#define putreg8(regid, writeval) regs.byteregs[byteregtable[regid]] = writeval
#define getsegreg(regid) segregs[regid]
#define putsegreg(regid, writeval) segregs[regid] = writeval
#define segbase(x) ((uint32_t)x<<4)
#define makeflagsword() (2 | (uint16_t)cf | ((uint16_t)pf << 2) | ((uint16_t)af << 4) | ((uint16_t)zf << 6) \
| ((uint16_t)sf << 7) | ((uint16_t)tf << 8) | ((uint16_t)ifl << 9) | ((uint16_t)df << 10) | ((uint16_t)of << 11))
#define decodeflagsword(x) {\
temp16 = x;\
cf = temp16 & 1;\
pf = (temp16 >> 2) & 1;\
af = (temp16 >> 4) & 1;\
zf = (temp16 >> 6) & 1;\
sf = (temp16 >> 7) & 1;\
tf = (temp16 >> 8) & 1;\
ifl = (temp16 >> 9) & 1;\
df = (temp16 >> 10) & 1;\
of = (temp16 >> 11) & 1;\
}
//#define RAM_write(a,v) {
//}
//#define RAM_read(a,v) {
//}
void setup_memory();
void setup_timer();
uint8_t insertdisk(uint8_t drivenum);
void reset86();
void exec86(uint32_t execloops);
uint8_t read86(uint32_t addr32);
void write86(uint32_t addr32, uint8_t value);
void doirq(uint8_t irqnum);
void incsends();
void init_display();
void write_video(uint16_t addr);
void clear_display();
void palettereset();
void display_CSIP();
void ps2poll();
void setup_ps2(uint8_t data_pin, uint8_t irq_pin);
void video_init();
uint8_t VRAM_read(uint32_t addr32);
void VRAM_write(uint32_t addr32, uint8_t value);
void setup_ps2(uint8_t data_pin, uint8_t irq_pin);
void ps2poll();
void out8253 (uint16_t portnum, uint8_t value);
uint8_t in8253 (uint16_t portnum);
void init8259();
void out8259(uint16_t portnum, uint8_t value);
uint8_t in8259(uint16_t portnum);
extern uint8_t port3da;
void initDisk(char * filename);
void init8253();
void net_init();
void net_loop();
void net_handler();
uint8_t cached_read(uint32_t addr32);
void cached_write(uint32_t addr32, uint8_t value);
void cache_init();
uint8_t net_read_ram(uint32_t addr32);
void diskhandler();
//extern uint8_t SPI_RAM_pins[8];
extern uint8_t net_mac[6];
extern uint8_t bufSerial[1600];
void outByte(uint8_t cc);
extern struct i8253_s i8253;
union _bytewordregs_{
uint16_t wordregs[8];
uint8_t byteregs[8];
} ;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,147 @@
#ifndef EMUAPI_H
#define EMUAPI_H
#include "platform_config.h"
#define CUSTOM_SND 1
//#define TIMER_REND 1
#define EXTRA_HEAP 0x10
// Title: < >
#define TITLE " 8086 PC Emulator"
#define ROMSDIR "pc"
#define emu_Init(ROM) {apc_Start(ROM); apc_Init(); }
#define emu_Step(x) { apc_Step(); }
#define emu_Input(x) { apc_Input(x); }
#define PALETTE_SIZE 256
#define VID_FRAME_SKIP 0x0
#define TFT_VBUFFER_YCROP 0
#define SINGLELINE_RENDERING 1
#define ACTION_NONE 0
#define ACTION_MAXKBDVAL 12
#define ACTION_EXITKBD 128
#define ACTION_RUNTFT 129
#define ACTION_RUNVGA 130
#ifdef KEYMAP_PRESENT
#define keylables_map1_0 (char *)"qwertyuiop\x1a"
#define keylables_map1_1 (char *)" asdfghjkl\x19"
#define keylables_map1_2 (char *)" zxcvbnm.\x10 "
const unsigned short key_map1[] = {
'Q','W','E','R','T','Y','U','I','O','P',157,
0,'A','S','D','F','G','H','J','K','L',0x0D,
0,'Z','X','C','V','B','N','M','.',' ',
145,157,29,17
};
#define keylables_map2_0 (char *)"1234567890 "
#define keylables_map2_1 (char *)" !@#$%+&*- "
#define keylables_map2_2 (char *)" ()?/\"<>,: "
const unsigned short key_map2[] = {
'1','2','3','4','5','6','7','8','9','0',0,
0, '!','@','#','$','%','+','&','*','-','\/',
0, '(',')','?','\/','"','<','>',',',':',
0,0,0,0
};
#define keylables_map3_0 (char *)"\x11\x12\x13\x14\x15\x16\x17\x18 "
#define keylables_map3_1 (char *)" "
#define keylables_map3_2 (char *)" ;= "
const unsigned short key_map3[] = {
133,134,135,136,137,138,139,140,0,0,0, // function keys
0, 0,0,0,0,0,0,0,0,0,0,
0, 0,0,0,0,0,0,0,';','=',
0,0,0,0
};
const unsigned short matkeys[] = {
0x020,0x120,0x220,0x320,0x420,0x408,0x308,0x208,0x108,0x008,0x002, // row 1
0x510,0x010,0x110,0x210,0x310,0x410,0x401,0x301,0x201,0x101,0x001, // row 2
0x520,0x102,0x202,0x302,0x402,0x404,0x304,0x204,0x104,0x004, // row 3
0x508,0x501,0x502,0x504 }; // cursor keys
#endif
#define MASK_JOY2_RIGHT 0x0001
#define MASK_JOY2_LEFT 0x0002
#define MASK_JOY2_UP 0x0004
#define MASK_JOY2_DOWN 0x0008
#define MASK_JOY2_BTN 0x0010
#define MASK_KEY_USER1 0x0020
#define MASK_KEY_USER2 0x0040
#define MASK_KEY_USER3 0x0080
#define MASK_JOY1_RIGHT 0x0100
#define MASK_JOY1_LEFT 0x0200
#define MASK_JOY1_UP 0x0400
#define MASK_JOY1_DOWN 0x0800
#define MASK_JOY1_BTN 0x1000
#define MASK_KEY_USER4 0x2000
#define MASK_OSKB 0x8000
extern void emu_init(void);
extern void emu_start(void);
extern void emu_resetSD(void);
extern void emu_printf(char * text);
extern void emu_printi(int val);
extern void * emu_Malloc(int size);
extern void emu_Free(void * pt);
extern int emu_FileOpen(char * filename);
extern int emu_FileRead(char * buf, int size);
extern unsigned char emu_FileGetc(void);
extern int emu_FileSeek(int seek);
extern void emu_FileClose(void);
extern int emu_FileSize(char * filename);
extern int emu_LoadFile(char * filename, char * buf, int size);
extern int emu_LoadFileSeek(char * filename, char * buf, int size, int seek);
extern void emu_FileTempInit(void);
extern void emu_FileTempRead(int addr, unsigned char * val, int n);
extern void emu_FileTempWrite(int addr, unsigned char val);
extern void emu_SetPaletteEntry(unsigned char r, unsigned char g, unsigned char b, int index);
extern void emu_DrawScreen(unsigned char * VBuf, int width, int height, int stride);
extern void emu_DrawLine(unsigned char * VBuf, int width, int height, int line);
extern void emu_DrawLine8(unsigned char * VBuf, int width, int height, int line);
extern void emu_DrawLine16(unsigned short * VBuf, int width, int height, int line);
extern void emu_DrawVsync(void);
extern int emu_FrameSkip(void);
extern void * emu_LineBuffer(int line);
extern void emu_InitJoysticks(void);
extern int emu_SwapJoysticks(int statusOnly);
extern unsigned short emu_DebounceLocalKeys(void);
extern int emu_ReadKeys(void);
extern int emu_GetPad(void);
extern int emu_ReadAnalogJoyX(int min, int max);
extern int emu_ReadAnalogJoyY(int min, int max);
extern int emu_ReadI2CKeyboard(void);
extern unsigned char emu_ReadI2CKeyboard2(int row);
extern void emu_KeyboardOnUp(int keymodifer, int key);
extern void emu_KeyboardOnDown(int keymodifer, int key);
extern int emu_oskbActive(void);
extern void emu_sndPlaySound(int chan, int volume, int freq);
extern void emu_sndPlayBuzz(int size, int val);
extern void emu_sndInit();
extern void emu_resetus(void);
extern int emu_us(void);
extern int emu_setKeymap(int index);
extern void emu_FileTempInit(void);
extern void emu_FileTempRead(int addr, unsigned char * val, int n);
extern void emu_FileTempWrite(int addr, unsigned char val);
extern void emu_printh(int val);
#endif

264
MCUME_pico/pico8086/font.h Normal file
View file

@ -0,0 +1,264 @@
#ifdef MEGA
#include <Arduino.h>
const uint8_t font[2048] PROGMEM = {
#else
const uint8_t font[2048] = {
#endif
0,0,0,0,0,0,0,
0,126,129,165,129,189,153,129,
126,126,255,219,255,195,231,255,
126,54,127,127,127,62,28,8,
0,8,28,62,127,62,28,8,
0,28,62,28,127,127,62,28,
62,8,8,28,62,127,62,28,
62,0,0,0,0,0,0,0,
0,255,255,231,195,195,231,255,
255,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,254,198,254,198,198,230,103,
3,153,90,60,231,231,60,90,
153,1,7,31,127,31,7,1,
0,64,112,124,127,124,112,64,
0,24,60,126,24,24,126,60,
24,102,102,102,102,102,0,102,
0,254,219,219,222,216,216,216,
0,124,198,28,54,54,28,51,
30,0,0,0,0,126,126,126,
0,24,60,126,24,126,60,24,
255,24,60,126,24,24,24,24,
0,24,24,24,24,126,60,24,
0,0,24,48,127,48,24,0,
0,0,12,6,127,6,12,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,12,30,30,12,12,0,12,
0,54,54,54,0,0,0,0,
0,54,54,127,54,127,54,54,
0,12,62,3,30,48,31,12,
0,0,99,51,24,12,102,99,
0,28,54,28,110,59,51,110,
0,6,6,3,0,0,0,0,
0,24,12,6,6,6,12,24,
0,6,12,24,24,24,12,6,
0,0,102,60,255,60,102,0,
0,0,12,12,63,12,12,0,
0,0,0,0,0,0,12,12,
6,0,0,0,63,0,0,0,
0,0,0,0,0,0,12,12,
0,96,48,24,12,6,3,1,
0,62,99,115,123,111,103,62,
0,12,14,12,12,12,12,63,
0,30,51,48,28,6,51,63,
0,30,51,48,28,48,51,30,
0,56,60,54,51,127,48,120,
0,63,3,31,48,48,51,30,
0,28,6,3,31,51,51,30,
0,63,51,48,24,12,12,12,
0,30,51,51,30,51,51,30,
0,30,51,51,62,48,24,14,
0,0,12,12,0,0,12,12,
0,0,12,12,0,0,12,12,
6,24,12,6,3,6,12,24,
0,0,0,63,0,0,63,0,
0,6,12,24,48,24,12,6,
0,30,51,48,24,12,0,12,
0,62,99,123,123,123,3,30,
0,12,30,51,51,63,51,51,
0,63,102,102,62,102,102,63,
0,60,102,3,3,3,102,60,
0,31,54,102,102,102,54,31,
0,127,70,22,30,22,70,127,
0,127,70,22,30,22,6,15,
0,60,102,3,3,115,102,124,
0,51,51,51,63,51,51,51,
0,30,12,12,12,12,12,30,
0,120,48,48,48,51,51,30,
0,103,102,54,30,54,102,103,
0,15,6,6,6,70,102,127,
0,99,119,127,127,107,99,99,
0,99,103,111,123,115,99,99,
0,28,54,99,99,99,54,28,
0,63,102,102,62,6,6,15,
0,30,51,51,51,59,30,56,
0,63,102,102,62,54,102,103,
0,30,51,7,14,56,51,30,
0,63,45,12,12,12,12,30,
0,51,51,51,51,51,51,63,
0,51,51,51,51,51,30,12,
0,99,99,99,107,127,119,99,
0,99,99,54,28,28,54,99,
0,51,51,51,30,12,12,30,
0,127,99,49,24,76,102,127,
0,30,6,6,6,6,6,30,
0,3,6,12,24,48,96,64,
0,30,24,24,24,24,24,30,
0,8,28,54,99,0,0,0,
0,0,0,0,0,0,0,0,
255,12,12,24,0,0,0,0,
0,0,0,30,48,62,51,110,
0,7,6,6,62,102,102,59,
0,0,0,30,51,3,51,30,
0,56,48,48,62,51,51,110,
0,0,0,30,51,63,3,30,
0,28,54,6,15,6,6,15,
0,0,0,110,51,51,62,48,
31,7,6,54,110,102,102,103,
0,12,0,14,12,12,12,30,
0,48,0,48,48,48,51,51,
30,7,6,102,54,30,54,103,
0,14,12,12,12,12,12,30,
0,0,0,51,127,127,107,99,
0,0,0,31,51,51,51,51,
0,0,0,30,51,51,51,30,
0,0,0,59,102,102,62,6,
15,0,0,110,51,51,62,48,
120,0,0,59,110,102,6,15,
0,0,0,62,3,30,48,31,
0,8,12,62,12,12,44,24,
0,0,0,51,51,51,51,110,
0,0,0,51,51,51,30,12,
0,0,0,99,107,127,127,54,
0,0,0,99,54,28,54,99,
0,0,0,51,51,51,62,48,
31,0,0,63,25,12,38,63,
0,56,12,12,7,12,12,56,
0,24,24,24,0,24,24,24,
0,7,12,12,56,12,12,7,
0,110,59,0,0,0,0,0,
0,0,8,28,54,99,99,127,
0,30,51,3,51,30,24,48,
30,0,51,0,51,51,51,126,
0,56,0,30,51,63,3,30,
0,126,195,60,96,124,102,252,
0,51,0,30,48,62,51,126,
0,7,0,30,48,62,51,126,
0,12,12,30,48,62,51,126,
0,0,0,30,3,3,30,48,
28,126,195,60,102,126,6,60,
0,51,0,30,51,63,3,30,
0,7,0,30,51,63,3,30,
0,51,0,14,12,12,12,30,
0,62,99,28,24,24,24,60,
0,7,0,14,12,12,12,30,
0,99,28,54,99,127,99,99,
0,12,12,0,30,51,63,51,
0,56,0,63,6,30,6,63,
0,0,0,254,48,254,51,254,
0,124,54,51,127,51,51,115,
0,30,51,0,30,51,51,30,
0,0,51,0,30,51,51,30,
0,0,7,0,30,51,51,30,
0,30,51,0,51,51,51,126,
0,0,7,0,51,51,51,126,
0,0,51,0,51,51,62,48,
31,195,24,60,102,102,60,24,
0,51,0,51,51,51,51,30,
0,24,24,126,3,3,126,24,
24,28,54,38,15,6,103,63,
0,51,51,30,63,12,63,12,
12,31,51,51,95,99,243,99,
227,112,216,24,60,24,24,27,
14,56,0,30,48,62,51,126,
0,28,0,14,12,12,12,30,
0,0,56,0,30,51,51,30,
0,0,56,0,51,51,51,126,
0,0,31,0,31,51,51,51,
0,63,0,51,55,63,59,51,
0,60,54,54,124,0,126,0,
0,28,54,54,28,0,62,0,
0,12,0,12,6,3,51,30,
0,0,0,0,63,3,3,0,
0,0,0,0,63,48,48,0,
0,195,99,51,123,204,102,51,
240,195,99,51,219,236,246,243,
192,24,24,0,24,24,24,24,
0,0,204,102,51,102,204,0,
0,0,51,102,204,102,51,0,
0,68,17,68,17,68,17,68,
17,170,85,170,85,170,85,170,
85,219,238,219,119,219,238,219,
119,24,24,24,24,24,24,24,
24,24,24,24,24,31,24,24,
24,24,24,31,24,31,24,24,
24,108,108,108,108,111,108,108,
108,0,0,0,0,127,108,108,
108,0,0,31,24,31,24,24,
24,108,108,111,96,111,108,108,
108,108,108,108,108,108,108,108,
108,0,0,127,96,111,108,108,
108,108,108,111,96,127,0,0,
0,108,108,108,108,127,0,0,
0,24,24,31,24,31,0,0,
0,0,0,0,0,31,24,24,
24,24,24,24,24,248,0,0,
0,24,24,24,24,255,0,0,
0,0,0,0,0,255,24,24,
24,24,24,24,24,248,24,24,
24,0,0,0,0,255,0,0,
0,24,24,24,24,255,24,24,
24,24,24,248,24,248,24,24,
24,108,108,108,108,236,108,108,
108,108,108,236,12,252,0,0,
0,0,0,252,12,236,108,108,
108,108,108,239,0,255,0,0,
0,0,0,255,0,239,108,108,
108,108,108,236,12,236,108,108,
108,0,0,255,0,255,0,0,
0,108,108,239,0,239,108,108,
108,24,24,255,0,255,0,0,
0,108,108,108,108,255,0,0,
0,0,0,255,0,255,24,24,
24,0,0,0,0,255,108,108,
108,108,108,108,108,252,0,0,
0,24,24,248,24,248,0,0,
0,0,0,248,24,248,24,24,
24,0,0,0,0,252,108,108,
108,108,108,108,108,255,108,108,
108,24,24,255,24,255,24,24,
24,24,24,24,24,31,0,0,
0,0,0,0,0,248,24,24,
24,255,255,255,255,255,255,255,
255,0,0,0,0,255,255,255,
255,15,15,15,15,15,15,15,
15,240,240,240,240,240,240,240,
240,255,255,255,255,0,0,0,
0,0,0,110,59,19,59,110,
0,0,30,51,31,51,31,3,
3,0,63,51,3,3,3,3,
0,0,127,54,54,54,54,54,
0,63,51,6,12,6,51,63,
0,0,0,126,27,27,27,14,
0,0,102,102,102,102,62,6,
3,0,110,59,24,24,24,24,
0,63,12,30,51,51,30,12,
63,28,54,99,127,99,54,28,
0,28,54,99,99,54,54,119,
0,56,12,24,62,51,51,30,
0,0,0,126,219,219,126,0,
0,96,48,126,219,219,126,6,
3,28,6,3,31,3,6,28,
0,30,51,51,51,51,51,51,
0,0,63,0,63,0,63,0,
0,12,12,63,12,12,0,63,
0,6,12,24,12,6,0,63,
0,24,12,6,12,24,0,63,
0,112,216,216,24,24,24,24,
24,24,24,24,24,24,27,27,
14,12,12,0,63,0,12,12,
0,0,110,59,0,110,59,0,
0,28,54,54,28,0,0,0,
0,0,0,0,24,24,0,0,
0,0,0,0,0,24,0,0,
0,240,48,48,48,55,54,60,
56,30,54,54,54,54,0,0,
0,14,24,12,6,30,0,0,
0,0,0,60,60,60,60,0,
0,0,0,0,0,0,0,0,0
};

View file

@ -0,0 +1,119 @@
#include <stdint.h>
#include <string.h>
#ifdef MEGA
#include <Arduino.h>
#include <TimerOne.h>
#else
#include "pico.h"
#include "pico/stdlib.h"
struct repeating_timer timer;
#endif
#define PIT_MODE_LATCHCOUNT 0
#define PIT_MODE_LOBYTE 1
#define PIT_MODE_HIBYTE 2
#define PIT_MODE_TOGGLE 3
struct i8253_s {
uint16_t chandata[3];
uint8_t accessmode[3];
uint8_t bytetoggle[3];
uint32_t effectivedata[3];
float chanfreq[3];
uint8_t active[3];
uint16_t counter[3];
} i8253;
volatile uint8_t timerTick = 0;
#ifdef MEGA
void timer_isr() {
timerTick = 1;
}
#else
static bool timer_isr(struct repeating_timer *t) {
timerTick = 1;
return true;
}
#endif
void out8253 (uint16_t portnum, uint8_t value) {
uint8_t curbyte;
portnum &= 3;
switch (portnum) {
case 0:
case 1:
case 2: //channel data
if ( (i8253.accessmode[portnum] == PIT_MODE_LOBYTE) || ( (i8253.accessmode[portnum] == PIT_MODE_TOGGLE) && (i8253.bytetoggle[portnum] == 0) ) ) curbyte = 0;
else if ( (i8253.accessmode[portnum] == PIT_MODE_HIBYTE) || ( (i8253.accessmode[portnum] == PIT_MODE_TOGGLE) && (i8253.bytetoggle[portnum] == 1) ) ) curbyte = 1;
if (curbyte == 0) { //low byte
i8253.chandata[portnum] = (i8253.chandata[portnum] & 0xFF00) | value;
}
else { //high byte
i8253.chandata[portnum] = (i8253.chandata[portnum] & 0x00FF) | ( (uint16_t) value << 8);
}
if (i8253.chandata[portnum] == 0) i8253.effectivedata[portnum] = 65536;
else i8253.effectivedata[portnum] = i8253.chandata[portnum];
i8253.active[portnum] = 1;
if (i8253.accessmode[portnum] == PIT_MODE_TOGGLE) i8253.bytetoggle[portnum] = (~i8253.bytetoggle[portnum]) & 1;
//i8253.chanfreq[portnum] = (float) ( (uint32_t) ( ( (float) 1193182.0 / (float) i8253.effectivedata[portnum]) * (float) 1000.0) );
//Serial.print("period "); Serial.println((uint32_t) ((float)1000000.0 / ( ( (float) 1193182.0 / (float) i8253.effectivedata[portnum]))));
if (portnum == 0) {
uint32_t period;
period = (uint32_t) ((float)1000000.0 / ( ( (float) 1193182.0 / (float) i8253.effectivedata[portnum])));
#ifdef MEGA
if (period < 4000) period = 4000; //limit to 250 Hz, or the emulator just can't keep up on a Mega
//Serial.println((float)1000000.0 / (float)period);
Timer1.attachInterrupt(timer_isr, period);
#else
cancel_repeating_timer (&timer);
add_repeating_timer_us(period, timer_isr, NULL, &timer);
#endif
}
break;
case 3: //mode/command
i8253.accessmode[value>>6] = (value >> 4) & 3;
if (i8253.accessmode[value>>6] == PIT_MODE_TOGGLE) i8253.bytetoggle[value>>6] = 0;
break;
}
}
uint8_t in8253 (uint16_t portnum) {
uint8_t curbyte;
portnum &= 3;
switch (portnum) {
case 0:
case 1:
case 2: //channel data
if ( (i8253.accessmode[portnum] == 0) || (i8253.accessmode[portnum] == PIT_MODE_LOBYTE) || ( (i8253.accessmode[portnum] == PIT_MODE_TOGGLE) && (i8253.bytetoggle[portnum] == 0) ) ) curbyte = 0;
else if ( (i8253.accessmode[portnum] == PIT_MODE_HIBYTE) || ( (i8253.accessmode[portnum] == PIT_MODE_TOGGLE) && (i8253.bytetoggle[portnum] == 1) ) ) curbyte = 1;
if ( (i8253.accessmode[portnum] == 0) || (i8253.accessmode[portnum] == PIT_MODE_LOBYTE) || ( (i8253.accessmode[portnum] == PIT_MODE_TOGGLE) && (i8253.bytetoggle[portnum] == 0) ) ) curbyte = 0;
else if ( (i8253.accessmode[portnum] == PIT_MODE_HIBYTE) || ( (i8253.accessmode[portnum] == PIT_MODE_TOGGLE) && (i8253.bytetoggle[portnum] == 1) ) ) curbyte = 1;
if ( (i8253.accessmode[portnum] == 0) || (i8253.accessmode[portnum] == PIT_MODE_TOGGLE) ) i8253.bytetoggle[portnum] = (~i8253.bytetoggle[portnum]) & 1;
if (curbyte == 0) { //low byte
if (i8253.counter[portnum] < 10) i8253.counter[portnum] = i8253.chandata[portnum];
i8253.counter[portnum] -= 10;
return ( (uint8_t) i8253.counter[portnum]);
}
else { //high byte
return ( (uint8_t) (i8253.counter[portnum] >> 8) );
}
break;
}
return (0);
}
void init8253() {
memset (&i8253, 0, sizeof (i8253) );
#ifdef MEGA
Timer1.initialize(54925);
Timer1.attachInterrupt(timer_isr, 54925);
#else
add_repeating_timer_us(54925, timer_isr, NULL, &timer);
#endif
//set_port_write_redirector (0x40, 0x43, &out8253);
//set_port_read_redirector (0x40, 0x43, &in8253);
}

83
MCUME_pico/pico8086/i8259.cpp Executable file
View file

@ -0,0 +1,83 @@
/* i8259.c - emulation code for the Intel 8259 controller.
Note: This is not a very complete i8259 interrupt controller
implementation, but for the purposes of a PC, it's all we need. */
#include <stdint.h>
#include <string.h>
struct structpic {
uint8_t imr; //mask register
uint8_t irr; //request register
uint8_t isr; //service register
uint8_t icwstep; //used during initialization to keep track of which ICW we're at
uint8_t icw[5];
uint8_t intoffset; //interrupt vector offset
uint8_t priority; //which IRQ has highest priority
uint8_t autoeoi; //automatic EOI mode
uint8_t readmode; //remember what to return on read register from OCW3
uint8_t enabled;
} i8259;
void init8259() {
memset((void *)&i8259, 0, sizeof(i8259));
}
uint8_t in8259(uint16_t portnum) {
switch (portnum & 1) {
case 0:
if (i8259.readmode==0) return(i8259.irr); else return(i8259.isr);
case 1: //read mask register
return(i8259.imr);
}
return(0); //can't get here, but the compiler bitches
}
extern uint32_t makeupticks;
void out8259(uint16_t portnum, uint8_t value) {
uint8_t i;
switch (portnum & 1) {
case 0:
if (value & 0x10) { //begin initialization sequence
i8259.icwstep = 1;
i8259.imr = 0; //clear interrupt mask register
i8259.icw[i8259.icwstep++] = value;
return;
}
if ((value & 0x98)==8) { //it's an OCW3
if (value & 2) i8259.readmode = value & 2;
}
if (value & 0x20) { //EOI command
for (i=0; i<8; i++)
if ((i8259.isr >> i) & 1) {
i8259.isr ^= (1 << i);
if ((i==0) && (makeupticks>0)) { makeupticks = 0; i8259.irr |= 1; }
return;
}
}
break;
case 1:
if ((i8259.icwstep==3) && (i8259.icw[1] & 2)) i8259.icwstep = 4; //single mode, so don't read ICW3
if (i8259.icwstep<5) { i8259.icw[i8259.icwstep++] = value; return; }
//if we get to this point, this is just a new IMR value
i8259.imr = value;
break;
}
}
uint8_t nextintr() {
uint8_t i, tmpirr;
tmpirr = i8259.irr & (~i8259.imr); //XOR request register with inverted mask register
for (i=0; i<8; i++)
if ((tmpirr >> i) & 1) {
i8259.irr ^= (1 << i);
i8259.isr |= (1 << i);
return(i8259.icw[2] + i);
}
return(0); //can't get here, but the compiler bitches
}
void doirq(uint8_t irqnum) {
i8259.irr |= (1 << irqnum);
}

View file

@ -0,0 +1,20 @@
#ifndef keyboard_osd_h_
#define keyboard_osd_h_
extern bool virtualkeyboardIsActive(void);
extern void drawVirtualkeyboard(void);
extern void toggleVirtualkeyboard(bool keepOn);
extern void handleVirtualkeyboard(void);
extern bool callibrationActive(void);
extern int handleCallibration(uint16_t bClick);
extern bool menuActive(void);
extern char * menuSelection(void);
extern void toggleMenu(bool on);
extern int handleMenu(uint16_t bClick);
#endif

146
MCUME_pico/pico8086/network.cpp Executable file
View file

@ -0,0 +1,146 @@
#include <stdint.h>
#include <string.h>
#include "emu.h"
#ifdef USE_ENC28J60
#include <enc28j60.h>
byte ENC28J60::buffer[1514];
//uint8_t net_mac[6] = { 0x90, 0xAD, 0xBE, 0xEF, 0x13, 0x37 };
uint8_t net_mac[6] = { 0x2C, 0xFD, 0x13, 0x37, 0x13, 0x37 };
extern union _bytewordregs_ regs;
extern uint16_t segregs[6];
struct netstruct {
uint8_t enabled;
uint8_t canrecv;
uint16_t pktlen;
} net;
void net_handler() {
uint32_t i;
uint16_t j;
//if (ethif==254) return; //networking not enabled
switch (regs.byteregs[regah]) { //function number
case 0x00: //enable packet reception
net.enabled = 1;
net.canrecv = 1;
return;
case 0x01: //send packet of CX at DS:SI
//if (verbose) {
//Serial.println("Sending packet of %u bytes.", regs.wordregs[regcx]);
//}
//sendpkt (&RAM[ ( (uint32_t) segregs[regds] << 4) + (uint32_t) regs.wordregs[regsi]], regs.wordregs[regcx]);
i = ( (uint32_t) segregs[regds] << 4) + (uint32_t) regs.wordregs[regsi];
for (j=0; j<net.pktlen; j++) {
ENC28J60::buffer[j] = read86(i++);
}
SPI.setClockDivider(SPI_CLOCK_ENC28J60);
ENC28J60::packetSend(segregs[regcx]);
SPI.setClockDivider(SPI_CLOCK_SPIRAM);
return;
case 0x02: //return packet info (packet buffer in DS:SI, length in CX)
segregs[regds] = 0xD000;
regs.wordregs[regsi] = 0x0000;
regs.wordregs[regcx] = net.pktlen;
return;
case 0x03: //copy packet to final destination (given in ES:DI)
//memcpy (&RAM[ ( (uint32_t) segregs[reges] << 4) + (uint32_t) regs.wordregs[regdi]], &RAM[0xD0000], net.pktlen);
i = ( (uint32_t) segregs[reges] << 4) + (uint32_t) regs.wordregs[regdi];
for (j=0; j<net.pktlen; j++) {
write86(i++, ENC28J60::buffer[j]);
}
net.canrecv = 1;
net.pktlen = 0;
return;
case 0x04: //disable packets
net.enabled = 0;
net.canrecv = 0;
return;
case 0x05: //DEBUG: dump packet (DS:SI) of CX bytes to stdout
/*for (i=0; i<regs.wordregs[regcx]; i++) {
printf ("%c", RAM[ ( (uint32_t) segregs[regds] << 4) + (uint32_t) regs.wordregs[regsi] + i]);
}*/
return;
case 0x06: //DEBUG: print milestone string
//print("PACKET DRIVER MILESTONE REACHED\n");
return;
}
}
uint8_t net_read_ram(uint32_t addr32) {
if (addr32 < 1514) return ENC28J60::buffer[addr32];
return 0;
}
/*void net_write_ram(uint32_t addr32, uint8_t value) {
if (addr32 < 1514) ENC28J60::buffer[addr32] = value;
}*/
void net_loop() {
uint16_t i, len;
uint8_t cc;
if (!net.enabled || !net.canrecv) return;
SPI.setClockDivider(SPI_CLOCK_ENC28J60);
len = ENC28J60::packetReceive();
SPI.setClockDivider(SPI_CLOCK_SPIRAM);
if (len > 0) {
for (i=0; i<len; i++) {
Serial.print(ENC28J60::buffer[i], HEX);
Serial.write(' ');
}
Serial.println("");
Serial.println("");
net.canrecv = 0;
net.pktlen = len;
doirq(6);
}
}
void net_init() {
uint8_t ret;
Serial.println("enter net_init");
//SPI.setClockDivider(SPI_CLOCK_ENC28J60);
ret = ENC28J60::initialize(1514, net_mac, NET_PIN);
//SPI.setClockDivider(SPI_CLOCK_LCD);
Serial.print("net init result = ");
Serial.println(ret);
ENC28J60::enablePromiscuous();
//ENC28J60::broadcast_enabled = true;
while(1) {
uint16_t len, i;
//delay(100);
//SPI.setClockDivider(SPI_CLOCK_ENC28J60);
len = ENC28J60::packetReceive();
//SPI.setClockDivider(SPI_CLOCK_LCD);
if (len > 0) {
for (i=0; i<len; i++) {
Serial.print(ENC28J60::buffer[i], HEX);
Serial.write(' ');
}
Serial.println("");
Serial.println("");
}
}
}
#else
uint8_t net_mac[6] = { 0x2C, 0xFD, 0x13, 0x37, 0x13, 0x37 };
void net_init() {
}
void net_loop() {
}
void net_handler() {
}
uint8_t net_read_ram(uint32_t addr32) {
return 0;
}
#endif

664
MCUME_pico/pico8086/pc.cpp Normal file
View file

@ -0,0 +1,664 @@
#include "pico.h"
#include "pico/stdlib.h"
#include <stdio.h>
#include <string.h>
#include "emu.h"
#include "ps2.h"
static uint8_t LOMEM[NATIVE_RAM];
#ifdef HAS_PSRAM
#include "psram_t.h"
PSRAM_T psram = PSRAM_T(PSRAM_CS, PSRAM_MOSI, PSRAM_SCLK, PSRAM_MISO);
#else
static uint8_t HIMEM[RAM_SIZE-NATIVE_RAM];
#endif
extern void write_loram(int address, uint8_t val) {
LOMEM[address] = val;
}
extern uint8_t read_loram(int address) {
return LOMEM[address];
}
extern void write_hiram(int address, uint8_t val) {
#ifdef HAS_PSRAM
psram.pswrite(address,val);
#else
HIMEM[address] = val;
#endif
}
extern uint8_t read_hiram(int address) {
#ifdef HAS_PSRAM
return (psram.psread(address));
#else
return HIMEM[address];
#endif
}
#define PALMULT8(x) ((x)<<5)
#define RGBVAL16(r,g,b) ( (((r>>3)&0x1f)<<11) | (((g>>2)&0x3f)<<5) | (((b>>3)&0x1f)<<0) )
struct i8253_s {
uint16_t chandata[3];
uint8_t accessmode[3];
uint8_t bytetoggle[3];
uint32_t effectivedata[3];
float chanfreq[3];
uint8_t active[3];
uint16_t counter[3];
};
extern struct i8253_s i8253;
void doirq(uint8_t irqnum);
void write86(uint32_t addr32, uint8_t value);
uint8_t read86(uint32_t addr32);
uint8_t curkey = 0;
uint8_t VRAM[16384];
uint32_t updateaddrs[64];
uint8_t updatepos = 0;
void VRAM_write(uint32_t addr32, uint8_t value) {
if (addr32 < 16384) {
VRAM[addr32] = value;
//printf("%d %d\n",addr32,value);
}
}
uint8_t VRAM_read(uint32_t addr32) {
if (addr32 < 16384) return VRAM[addr32];
return 0;
}
uint8_t ansicolor[16] = { 0, 4, 2, 6, 1, 5, 3, 7, 0, 4, 2, 6, 1, 5, 3, 7 };
uint16_t palettecga[16], palettevga[256];
void installPalette(void) {
palettecga[0] = RGBVAL16(0, 0, 0);
palettecga[1] = RGBVAL16(0, 0, 0xAA);
palettecga[2] = RGBVAL16(0, 0xAA, 0);
palettecga[3] = RGBVAL16(0, 0xAA, 0xAA);
palettecga[4] = RGBVAL16(0xAA, 0, 0);
palettecga[5] = RGBVAL16(0xAA, 0, 0xAA);
palettecga[6] = RGBVAL16(0xAA, 0x55, 0);
palettecga[7] = RGBVAL16(0xAA, 0xAA, 0xAA);
palettecga[8] = RGBVAL16(0x55, 0x55, 0x55);
palettecga[9] = RGBVAL16(0x55, 0x55, 0xFF);
palettecga[10] = RGBVAL16(0x55, 0xFF, 0x55);
palettecga[11] = RGBVAL16(0x55, 0xFF, 0xFF);
palettecga[12] = RGBVAL16(0xFF, 0x55, 0x55);
palettecga[13] = RGBVAL16(0xFF, 0x55, 0xFF);
palettecga[14] = RGBVAL16(0xFF, 0xFF, 0x55);
palettecga[15] = RGBVAL16(0xFF, 0xFF, 0xFF);
palettevga[0] = RGBVAL16(0, 0, 0);
palettevga[1] = RGBVAL16(0, 0, 169);
palettevga[2] = RGBVAL16(0, 169, 0);
palettevga[3] = RGBVAL16(0, 169, 169);
palettevga[4] = RGBVAL16(169, 0, 0);
palettevga[5] = RGBVAL16(169, 0, 169);
palettevga[6] = RGBVAL16(169, 169, 0);
palettevga[7] = RGBVAL16(169, 169, 169);
palettevga[8] = RGBVAL16(0, 0, 84);
palettevga[9] = RGBVAL16(0, 0, 255);
palettevga[10] = RGBVAL16(0, 169, 84);
palettevga[11] = RGBVAL16(0, 169, 255);
palettevga[12] = RGBVAL16(169, 0, 84);
palettevga[13] = RGBVAL16(169, 0, 255);
palettevga[14] = RGBVAL16(169, 169, 84);
palettevga[15] = RGBVAL16(169, 169, 255);
palettevga[16] = RGBVAL16(0, 84, 0);
palettevga[17] = RGBVAL16(0, 84, 169);
palettevga[18] = RGBVAL16(0, 255, 0);
palettevga[19] = RGBVAL16(0, 255, 169);
palettevga[20] = RGBVAL16(169, 84, 0);
palettevga[21] = RGBVAL16(169, 84, 169);
palettevga[22] = RGBVAL16(169, 255, 0);
palettevga[23] = RGBVAL16(169, 255, 169);
palettevga[24] = RGBVAL16(0, 84, 84);
palettevga[25] = RGBVAL16(0, 84, 255);
palettevga[26] = RGBVAL16(0, 255, 84);
palettevga[27] = RGBVAL16(0, 255, 255);
palettevga[28] = RGBVAL16(169, 84, 84);
palettevga[29] = RGBVAL16(169, 84, 255);
palettevga[30] = RGBVAL16(169, 255, 84);
palettevga[31] = RGBVAL16(169, 255, 255);
palettevga[32] = RGBVAL16(84, 0, 0);
palettevga[33] = RGBVAL16(84, 0, 169);
palettevga[34] = RGBVAL16(84, 169, 0);
palettevga[35] = RGBVAL16(84, 169, 169);
palettevga[36] = RGBVAL16(255, 0, 0);
palettevga[37] = RGBVAL16(255, 0, 169);
palettevga[38] = RGBVAL16(255, 169, 0);
palettevga[39] = RGBVAL16(255, 169, 169);
palettevga[40] = RGBVAL16(84, 0, 84);
palettevga[41] = RGBVAL16(84, 0, 255);
palettevga[42] = RGBVAL16(84, 169, 84);
palettevga[43] = RGBVAL16(84, 169, 255);
palettevga[44] = RGBVAL16(255, 0, 84);
palettevga[45] = RGBVAL16(255, 0, 255);
palettevga[46] = RGBVAL16(255, 169, 84);
palettevga[47] = RGBVAL16(255, 169, 255);
palettevga[48] = RGBVAL16(84, 84, 0);
palettevga[49] = RGBVAL16(84, 84, 169);
palettevga[50] = RGBVAL16(84, 255, 0);
palettevga[51] = RGBVAL16(84, 255, 169);
palettevga[52] = RGBVAL16(255, 84, 0);
palettevga[53] = RGBVAL16(255, 84, 169);
palettevga[54] = RGBVAL16(255, 255, 0);
palettevga[55] = RGBVAL16(255, 255, 169);
palettevga[56] = RGBVAL16(84, 84, 84);
palettevga[57] = RGBVAL16(84, 84, 255);
palettevga[58] = RGBVAL16(84, 255, 84);
palettevga[59] = RGBVAL16(84, 255, 255);
palettevga[60] = RGBVAL16(255, 84, 84);
palettevga[61] = RGBVAL16(255, 84, 255);
palettevga[62] = RGBVAL16(255, 255, 84);
palettevga[63] = RGBVAL16(255, 255, 255);
palettevga[64] = RGBVAL16(255, 125, 125);
palettevga[65] = RGBVAL16(255, 157, 125);
palettevga[66] = RGBVAL16(255, 190, 125);
palettevga[67] = RGBVAL16(255, 222, 125);
palettevga[68] = RGBVAL16(255, 255, 125);
palettevga[69] = RGBVAL16(222, 255, 125);
palettevga[70] = RGBVAL16(190, 255, 125);
palettevga[71] = RGBVAL16(157, 255, 125);
palettevga[72] = RGBVAL16(125, 255, 125);
palettevga[73] = RGBVAL16(125, 255, 157);
palettevga[74] = RGBVAL16(125, 255, 190);
palettevga[75] = RGBVAL16(125, 255, 222);
palettevga[76] = RGBVAL16(125, 255, 255);
palettevga[77] = RGBVAL16(125, 222, 255);
palettevga[78] = RGBVAL16(125, 190, 255);
palettevga[79] = RGBVAL16(125, 157, 255);
palettevga[80] = RGBVAL16(182, 182, 255);
palettevga[81] = RGBVAL16(198, 182, 255);
palettevga[82] = RGBVAL16(218, 182, 255);
palettevga[83] = RGBVAL16(234, 182, 255);
palettevga[84] = RGBVAL16(255, 182, 255);
palettevga[85] = RGBVAL16(255, 182, 234);
palettevga[86] = RGBVAL16(255, 182, 218);
palettevga[87] = RGBVAL16(255, 182, 198);
palettevga[88] = RGBVAL16(255, 182, 182);
palettevga[89] = RGBVAL16(255, 198, 182);
palettevga[90] = RGBVAL16(255, 218, 182);
palettevga[91] = RGBVAL16(255, 234, 182);
palettevga[92] = RGBVAL16(255, 255, 182);
palettevga[93] = RGBVAL16(234, 255, 182);
palettevga[94] = RGBVAL16(218, 255, 182);
palettevga[95] = RGBVAL16(198, 255, 182);
palettevga[96] = RGBVAL16(182, 255, 182);
palettevga[97] = RGBVAL16(182, 255, 198);
palettevga[98] = RGBVAL16(182, 255, 218);
palettevga[99] = RGBVAL16(182, 255, 234);
palettevga[100] = RGBVAL16(182, 255, 255);
palettevga[101] = RGBVAL16(182, 234, 255);
palettevga[102] = RGBVAL16(182, 218, 255);
palettevga[103] = RGBVAL16(182, 198, 255);
palettevga[104] = RGBVAL16(0, 0, 113);
palettevga[105] = RGBVAL16(28, 0, 113);
palettevga[106] = RGBVAL16(56, 0, 113);
palettevga[107] = RGBVAL16(84, 0, 113);
palettevga[108] = RGBVAL16(113, 0, 113);
palettevga[109] = RGBVAL16(113, 0, 84);
palettevga[110] = RGBVAL16(113, 0, 56);
palettevga[111] = RGBVAL16(113, 0, 28);
palettevga[112] = RGBVAL16(113, 0, 0);
palettevga[113] = RGBVAL16(113, 28, 0);
palettevga[114] = RGBVAL16(113, 56, 0);
palettevga[115] = RGBVAL16(113, 84, 0);
palettevga[116] = RGBVAL16(113, 113, 0);
palettevga[117] = RGBVAL16(84, 113, 0);
palettevga[118] = RGBVAL16(56, 113, 0);
palettevga[119] = RGBVAL16(28, 113, 0);
palettevga[120] = RGBVAL16(0, 113, 0);
palettevga[121] = RGBVAL16(0, 113, 28);
palettevga[122] = RGBVAL16(0, 113, 56);
palettevga[123] = RGBVAL16(0, 113, 84);
palettevga[124] = RGBVAL16(0, 113, 113);
palettevga[125] = RGBVAL16(0, 84, 113);
palettevga[126] = RGBVAL16(0, 56, 113);
palettevga[127] = RGBVAL16(0, 28, 113);
palettevga[128] = RGBVAL16(56, 56, 113);
palettevga[129] = RGBVAL16(68, 56, 113);
palettevga[130] = RGBVAL16(84, 56, 113);
palettevga[131] = RGBVAL16(97, 56, 113);
palettevga[132] = RGBVAL16(113, 56, 113);
palettevga[133] = RGBVAL16(113, 56, 97);
palettevga[134] = RGBVAL16(113, 56, 84);
palettevga[135] = RGBVAL16(113, 56, 68);
palettevga[136] = RGBVAL16(113, 56, 56);
palettevga[137] = RGBVAL16(113, 68, 56);
palettevga[138] = RGBVAL16(113, 84, 56);
palettevga[139] = RGBVAL16(113, 97, 56);
palettevga[140] = RGBVAL16(113, 113, 56);
palettevga[141] = RGBVAL16(97, 113, 56);
palettevga[142] = RGBVAL16(84, 113, 56);
palettevga[143] = RGBVAL16(68, 113, 56);
palettevga[144] = RGBVAL16(56, 113, 56);
palettevga[145] = RGBVAL16(56, 113, 68);
palettevga[146] = RGBVAL16(56, 113, 84);
palettevga[147] = RGBVAL16(56, 113, 97);
palettevga[148] = RGBVAL16(56, 113, 113);
palettevga[149] = RGBVAL16(56, 97, 113);
palettevga[150] = RGBVAL16(56, 84, 113);
palettevga[151] = RGBVAL16(56, 68, 113);
palettevga[152] = RGBVAL16(80, 80, 113);
palettevga[153] = RGBVAL16(89, 80, 113);
palettevga[154] = RGBVAL16(97, 80, 113);
palettevga[155] = RGBVAL16(105, 80, 113);
palettevga[156] = RGBVAL16(113, 80, 113);
palettevga[157] = RGBVAL16(113, 80, 105);
palettevga[158] = RGBVAL16(113, 80, 97);
palettevga[159] = RGBVAL16(113, 80, 89);
palettevga[160] = RGBVAL16(113, 80, 80);
palettevga[161] = RGBVAL16(113, 89, 80);
palettevga[162] = RGBVAL16(113, 97, 80);
palettevga[163] = RGBVAL16(113, 105, 80);
palettevga[164] = RGBVAL16(113, 113, 80);
palettevga[165] = RGBVAL16(105, 113, 80);
palettevga[166] = RGBVAL16(97, 113, 80);
palettevga[167] = RGBVAL16(89, 113, 80);
palettevga[168] = RGBVAL16(80, 113, 80);
palettevga[169] = RGBVAL16(80, 113, 89);
palettevga[170] = RGBVAL16(80, 113, 97);
palettevga[171] = RGBVAL16(80, 113, 105);
palettevga[172] = RGBVAL16(80, 113, 113);
palettevga[173] = RGBVAL16(80, 105, 113);
palettevga[174] = RGBVAL16(80, 97, 113);
palettevga[175] = RGBVAL16(80, 89, 113);
palettevga[176] = RGBVAL16(0, 0, 64);
palettevga[177] = RGBVAL16(16, 0, 64);
palettevga[178] = RGBVAL16(32, 0, 64);
palettevga[179] = RGBVAL16(48, 0, 64);
palettevga[180] = RGBVAL16(64, 0, 64);
palettevga[181] = RGBVAL16(64, 0, 48);
palettevga[182] = RGBVAL16(64, 0, 32);
palettevga[183] = RGBVAL16(64, 0, 16);
palettevga[184] = RGBVAL16(64, 0, 0);
palettevga[185] = RGBVAL16(64, 16, 0);
palettevga[186] = RGBVAL16(64, 32, 0);
palettevga[187] = RGBVAL16(64, 48, 0);
palettevga[188] = RGBVAL16(64, 64, 0);
palettevga[189] = RGBVAL16(48, 64, 0);
palettevga[190] = RGBVAL16(32, 64, 0);
palettevga[191] = RGBVAL16(16, 64, 0);
palettevga[192] = RGBVAL16(0, 64, 0);
palettevga[193] = RGBVAL16(0, 64, 16);
palettevga[194] = RGBVAL16(0, 64, 32);
palettevga[195] = RGBVAL16(0, 64, 48);
palettevga[196] = RGBVAL16(0, 64, 64);
palettevga[197] = RGBVAL16(0, 48, 64);
palettevga[198] = RGBVAL16(0, 32, 64);
palettevga[199] = RGBVAL16(0, 16, 64);
palettevga[200] = RGBVAL16(32, 32, 64);
palettevga[201] = RGBVAL16(40, 32, 64);
palettevga[202] = RGBVAL16(48, 32, 64);
palettevga[203] = RGBVAL16(56, 32, 64);
palettevga[204] = RGBVAL16(64, 32, 64);
palettevga[205] = RGBVAL16(64, 32, 56);
palettevga[206] = RGBVAL16(64, 32, 48);
palettevga[207] = RGBVAL16(64, 32, 40);
palettevga[208] = RGBVAL16(64, 32, 32);
palettevga[209] = RGBVAL16(64, 40, 32);
palettevga[210] = RGBVAL16(64, 48, 32);
palettevga[211] = RGBVAL16(64, 56, 32);
palettevga[212] = RGBVAL16(64, 64, 32);
palettevga[213] = RGBVAL16(56, 64, 32);
palettevga[214] = RGBVAL16(48, 64, 32);
palettevga[215] = RGBVAL16(40, 64, 32);
palettevga[216] = RGBVAL16(32, 64, 32);
palettevga[217] = RGBVAL16(32, 64, 40);
palettevga[218] = RGBVAL16(32, 64, 48);
palettevga[219] = RGBVAL16(32, 64, 56);
palettevga[220] = RGBVAL16(32, 64, 64);
palettevga[221] = RGBVAL16(32, 56, 64);
palettevga[222] = RGBVAL16(32, 48, 64);
palettevga[223] = RGBVAL16(32, 40, 64);
palettevga[224] = RGBVAL16(44, 44, 64);
palettevga[225] = RGBVAL16(48, 44, 64);
palettevga[226] = RGBVAL16(52, 44, 64);
palettevga[227] = RGBVAL16(60, 44, 64);
palettevga[228] = RGBVAL16(64, 44, 64);
palettevga[229] = RGBVAL16(64, 44, 60);
palettevga[230] = RGBVAL16(64, 44, 52);
palettevga[231] = RGBVAL16(64, 44, 48);
palettevga[232] = RGBVAL16(64, 44, 44);
palettevga[233] = RGBVAL16(64, 48, 44);
palettevga[234] = RGBVAL16(64, 52, 44);
palettevga[235] = RGBVAL16(64, 60, 44);
palettevga[236] = RGBVAL16(64, 64, 44);
palettevga[237] = RGBVAL16(60, 64, 44);
palettevga[238] = RGBVAL16(52, 64, 44);
palettevga[239] = RGBVAL16(48, 64, 44);
palettevga[240] = RGBVAL16(44, 64, 44);
palettevga[241] = RGBVAL16(44, 64, 48);
palettevga[242] = RGBVAL16(44, 64, 52);
palettevga[243] = RGBVAL16(44, 64, 60);
palettevga[244] = RGBVAL16(44, 64, 64);
palettevga[245] = RGBVAL16(44, 60, 64);
palettevga[246] = RGBVAL16(44, 52, 64);
palettevga[247] = RGBVAL16(44, 48, 64);
palettevga[248] = RGBVAL16(0, 0, 0);
palettevga[249] = RGBVAL16(0, 0, 0);
palettevga[250] = RGBVAL16(0, 0, 0);
palettevga[251] = RGBVAL16(0, 0, 0);
palettevga[252] = RGBVAL16(0, 0, 0);
palettevga[253] = RGBVAL16(0, 0, 0);
palettevga[254] = RGBVAL16(0, 0, 0);
palettevga[255] = RGBVAL16(0, 0, 0);
}
extern uint8_t vidmode, portram[0x400];
#define XRES_MAX 640
#define XRES_HI 640
#define XRES_LO 320
#define YRES 200
#include "font.h"
static unsigned short line[XRES_MAX];
void drawscreentext80(void) {
uint16_t row, col, y, x, xpos;
uint16_t fontdata;
for (y=0; y<(25*8); y++)
{
row = y>>3;
uint8_t * vrampt=&VRAM[160*row];
xpos = 0;
for (col=0; col<80; col++)
{
uint8_t bold, attrib, cc, bg, fg;
cc = *vrampt++;
attrib = *vrampt++;
bg = (attrib >> 4) & 7;
fg = attrib & 0x0F;
//if (y == 0) {printf("0x%02X",cc);}
fontdata = ROM_READ(font, ((uint32_t)cc << 3) + (y&0x7));
for (x=0; x<8; x++)
//for (x=0; x<4; x++)
{
if (fontdata & 1) {
line[xpos++] = palettecga[fg];
} else {
line[xpos++] = palettecga[bg];
}
fontdata >>= 1;
//fontdata >>= 2;
}
}
emu_DrawLine16(&line[0], XRES_HI, YRES, y);
}
}
void drawscreenlorescga(void) {
uint16_t y, x, xpos;
uint8_t intensity, usepal;
uint16_t color;
usepal = (portram[0x3D9]>>5) & 1;
intensity = ( (portram[0x3D9]>>4) & 1) << 3;
for (y=0; y<(25*8); y++)
{
xpos = 0;
for (x=0; x<XRES_LO; x++)
{
int ychar = y;// >> 1;
int xchar = x;// >> 1;
uint8_t curchar = VRAM[((ychar & 1) * 8192 + (ychar >> 1) * 80 + (xchar >> 2))];
switch (xchar & 3) {
case 3: color = curchar & 3; break;
case 2: color = (curchar >> 2) & 3; break;
case 1: color = (curchar >> 4) & 3; break;
case 0: color = (curchar >> 6) & 3; break;
}
color = (color << 1) + usepal + intensity;
if (color == (usepal + intensity)) color = 0;
line[xpos++] = palettecga[color];
}
emu_DrawLine16(&line[0], XRES_LO, YRES, y);
}
}
void drawscreenhirescga(void) {
uint16_t y, x, xpos;
uint16_t color;
for (y=0; y<(25*8); y++)
{
xpos = 0;
for (x=0; x<XRES_HI; x++)
{
int ychar = y >> 1;
int xchar = x;
uint8_t curchar = VRAM[((ychar & 1) * 8192 + (ychar >> 1) * 80 + (xchar >> 3))];
color = ((curchar >> (7-(x&7))) & 1) ? 15 : 0;
line[xpos++] = palettecga[color];
}
emu_DrawLine16(&line[0], XRES_HI, YRES, y);
}
}
void updatescreen() {
switch (vidmode & 0x7F) {
case 0:
case 1:
//drawtext40(origaddr, value);
break;
case 2:
case 3:
//case 7:
drawscreentext80();
break;
case 4:
drawscreenlorescga();
break;
case 5:
drawscreenlorescga(); //change to BW function later
break;
case 6:
drawscreenhirescga();
break;
}
//printf("%d\n",vidmode & 0x7F);
}
static uint8_t nbkeys=0;
static uint8_t kcnt=0;
static int toggle=1;
static char * seq;
static char * seq1="PRINCE.BAT\r";
static char * seq2="CAT.EXE\r";
static char * seq3="y\r";
static int mouse_x = 160;
static int mouse_y = 100;
static int prev_key = 0;
static int prev_j = 0;
static int prev_mouseb = 0;
static bool isMouse = true;
static int joynum = 1;
static int hk = 0;
static int prev_hk = 0;
static int k = 0;
static void keyevent(int keysym, int isdown)
{
uint8_t scancode = translatescancode(keysym);
if (scancode != 0xFF) {
portram[0x60] = scancode;
if (!isdown) portram[0x60] |= 0x80;
portram[0x64] |= 2;
doirq(1);
}
}
extern void apc_Input(int bClick) {
hk = emu_ReadI2CKeyboard();
k = emu_ReadKeys();
if (nbkeys == 0) {
if ( (bClick & MASK_KEY_USER1) && (bClick & MASK_KEY_USER2) ) {
nbkeys = strlen(seq3);
seq=seq3;
kcnt=0;
}
else if (bClick & MASK_KEY_USER1) {
nbkeys = strlen(seq1);
seq=seq1;
kcnt=0;
}
else if (bClick & MASK_KEY_USER2) {
nbkeys = strlen(seq2);
seq=seq2;
kcnt=0;
}
}
else {
char k = seq[kcnt];
if (k == 13) keyevent(0xFF0D,toggle);
else keyevent(k,toggle);
//setKey(ascii2scan[k],toggle);
if (!toggle) {
kcnt++;
nbkeys--;
toggle = true;
}
else {
toggle = false;
}
}
}
static void do_events(void)
{
if (hk != prev_hk) {
prev_hk == hk;
if ( (hk != 0) && (hk != prev_key) ) {
prev_key = hk;
keyevent ( hk, 0 );
if (hk == 68) {
if (isMouse) isMouse = false;
else isMouse = true;
}
}
}
if ( (hk == 0) && (prev_key) ) {
keyevent ( prev_key, 1 );
prev_key = 0;
}
if (!isMouse)
{
int j = 0;
if (( k & MASK_JOY1_RIGHT) || ( k & MASK_JOY2_RIGHT)) {
j |= 0x08;
}
if (( k & MASK_JOY1_LEFT) || ( k & MASK_JOY2_LEFT)) {
j |= 0x04;
}
if (( k & MASK_JOY1_UP) || ( k & MASK_JOY2_UP)) {
j |= 0x01;
}
if (( k & MASK_JOY1_DOWN) || ( k & MASK_JOY2_DOWN)) {
j |= 0x02;
}
if ( k & MASK_JOY2_BTN) {
j |= 0x80;
}
if (j != prev_j) {
//IkbdJoystickChange(joynum,j);
prev_j = j;
}
}
else {
if (( k & MASK_JOY1_RIGHT) || ( k & MASK_JOY2_RIGHT)) {
if ( mouse_x < XRES_HI ) {
mouse_x += 1;
}
}
else if (( k & MASK_JOY1_LEFT) || ( k & MASK_JOY2_LEFT)) {
if ( mouse_x > 1 ) {
mouse_x -= 1;
}
}
else if (( k & MASK_JOY1_UP) || ( k & MASK_JOY2_UP)) {
if ( mouse_y > 1 ) {
mouse_y -= 1;
}
}
else if (( k & MASK_JOY1_DOWN) || ( k & MASK_JOY2_DOWN)) {
if ( mouse_y < YRES ) {
mouse_y += 1;
}
}
int mouseb=0;
if ( ( k & MASK_JOY2_BTN) ){
mouseb=1;
}
if ( (mouseb != prev_mouseb) ){
prev_mouseb = mouseb;
}
}
}
void emu_KeyboardOnDown(int keymodifer, int key) {
}
void emu_KeyboardOnUp(int keymodifer, int key) {
}
void apc_Step(void)
{
exec86(8000);
updatescreen();
do_events();
emu_DrawVsync();
}
void apc_Init(void)
{
#ifdef HAS_PSRAM
psram.begin();
#endif
installPalette();
init8253();
reset86();
init8259();
}
void apc_Start(char * filename)
{
emu_printf("init started");
initDisk(filename);
emu_printf("init done");
}

5
MCUME_pico/pico8086/pc.h Normal file
View file

@ -0,0 +1,5 @@
extern void apc_Init(void);
extern void apc_Step(void);
extern void apc_Start(char * filename);
extern void apc_Input(int click);

View file

@ -0,0 +1,178 @@
#include "pico.h"
#include "pico/stdlib.h"
extern "C" {
#include "iopins.h"
#include "emuapi.h"
}
#include "keyboard_osd.h"
#include "pc.h"
#include <stdio.h>
#ifdef USE_VGA
#include "vga_t_dma.h"
#else
#include "tft_t_dma.h"
#endif
volatile bool vbl=true;
bool repeating_timer_callback(struct repeating_timer *t) {
if (vbl) {
vbl = false;
} else {
vbl = true;
}
return true;
}
TFT_T_DMA tft;
static int skip=0;
#include "hardware/clocks.h"
#include "hardware/vreg.h"
int main(void) {
vreg_set_voltage(VREG_VOLTAGE_1_05);
// set_sys_clock_khz(125000, true);
// set_sys_clock_khz(150000, true);
// set_sys_clock_khz(133000, true);
// set_sys_clock_khz(200000, true);
// set_sys_clock_khz(225000, true);
set_sys_clock_khz(150000, true);
stdio_init_all();
#ifdef USE_VGA
// tft.begin(VGA_MODE_400x240);
tft.begin(VGA_MODE_320x240);
#else
tft.begin();
#endif
emu_init();
while (true) {
if (menuActive()) {
uint16_t bClick = emu_DebounceLocalKeys();
int action = handleMenu(bClick);
char * filename = menuSelection();
if (action == ACTION_RUNTFT) {
toggleMenu(false);
emu_start();
emu_Init(filename);
tft.fillScreenNoDma( RGBVAL16(0x00,0x00,0x00) );
tft.startDMA();
struct repeating_timer timer;
add_repeating_timer_ms(15, repeating_timer_callback, NULL, &timer);
}
tft.waitSync();
}
else {
uint16_t bClick = emu_DebounceLocalKeys();
emu_Input(bClick);
emu_Step();
}
//int c = getchar_timeout_us(0);
//switch (c) {
// case ' ':
// printf("test: %d\n", 1);
// break;
//}
}
}
static unsigned char palette8[PALETTE_SIZE];
static unsigned short palette16[PALETTE_SIZE];
void emu_SetPaletteEntry(unsigned char r, unsigned char g, unsigned char b, int index)
{
if (index<PALETTE_SIZE) {
palette8[index] = RGBVAL8(r,g,b);
palette16[index] = RGBVAL16(r,g,b);
}
}
void emu_DrawVsync(void)
{
skip += 1;
skip &= VID_FRAME_SKIP;
#ifdef USE_VGA
tft.waitSync();
#else
volatile bool vb=vbl;
while (vbl==vb) {};
#endif
}
void emu_DrawLine(unsigned char * VBuf, int width, int height, int line)
{
if (skip == 0) {
#ifdef USE_VGA
tft.writeLine(width,height,line, VBuf, palette8);
#else
tft.writeLine(width,height,line, VBuf, palette16);
#endif
}
}
void emu_DrawLine8(unsigned char * VBuf, int width, int height, int line)
{
if (skip == 0) {
#ifdef USE_VGA
tft.writeLine(width,height,line, VBuf);
#endif
}
}
void emu_DrawLine16(unsigned short * VBuf, int width, int height, int line)
{
if (skip == 0) {
#ifdef USE_VGA
tft.writeLine16(width,height,line, VBuf);
#endif
}
}
void emu_DrawScreen(unsigned char * VBuf, int width, int height, int stride)
{
if (skip == 0) {
#ifdef USE_VGA
tft.writeScreen(width,height-TFT_VBUFFER_YCROP,stride, VBuf+(TFT_VBUFFER_YCROP/2)*stride, palette8);
#else
tft.writeScreen(width,height-TFT_VBUFFER_YCROP,stride, VBuf+(TFT_VBUFFER_YCROP/2)*stride, palette16);
#endif
}
}
int emu_FrameSkip(void)
{
return skip;
}
void * emu_LineBuffer(int line)
{
return (void*)tft.getLineBuffer(line);
}
#ifdef HAS_SND
#include "AudioPlaySystem.h"
AudioPlaySystem mymixer;
void emu_sndInit() {
tft.begin_audio(256, mymixer.snd_Mixer);
mymixer.start();
}
void emu_sndPlaySound(int chan, int volume, int freq)
{
if (chan < 6) {
mymixer.sound(chan, freq, volume);
}
}
void emu_sndPlayBuzz(int size, int val) {
mymixer.buzz(size,val);
}
#endif

98
MCUME_pico/pico8086/ports.cpp Executable file
View file

@ -0,0 +1,98 @@
/* ports.c - handles port I/O for Fake86 CPU core. it's ugly, will fix up later. */
#include <stdint.h>
#include "emu.h"
volatile uint16_t pit0counter = 65535;
volatile uint32_t speakercountdown, latch42, pit0latch, pit0command, pit0divisor;
uint8_t portram[0x400];
uint8_t crt_controller_idx, crt_controller[256], port3D9 = 0;
void portout(uint16_t portnum, uint16_t value) {
if (portnum < 0x400) portram[portnum] = value;
switch (portnum) {
case 0x20:
case 0x21: //i8259
out8259(portnum, value);
return;
case 0x40:
case 0x41:
case 0x42:
case 0x43: //i8253
out8253(portnum, value);
break;
case 0x3D4:
crt_controller_idx = value;
break;
case 0x3D5:
crt_controller[crt_controller_idx] = value;
if ((crt_controller_idx == 0x0E) || (crt_controller_idx == 0x0F)) {
//setcursor(((uint16_t)crt_controller[0x0E] << 8) | crt_controller[0x0F]);
//Serial.write(27); Serial.write('['); Serial.print(crt_controller[0x0E] + 1); Serial.write(';'); Serial.print(crt_controller[0x0F] + 1); Serial.write('H');
}
break;
case 0x3D9:
port3D9 = value;
break;
}
#ifdef ADVANCED_CLIENT
if ((portnum >= 0x3C0) && (portnum <= 0x3DA)) {
uint8_t chksum;
Serial.write(0xFF);
Serial.write(0x04);
outByte(portnum & 0xFF); chksum = portnum & 0xFF;
outByte(portnum >> 8); chksum += portnum >> 8;
outByte(value); chksum += value;
outByte(chksum);
Serial.write(0xFE);
Serial.write(0x02);
}
#endif
#ifdef VGA
if ((portnum >= 0x3C0) && (portnum <= 0x3DA)) outVGA(portnum, value);
#endif
}
uint16_t portin(uint16_t portnum) {
#ifdef VGA
if ((portnum >= 0x3C0) && (portnum <= 0x3DA)) return inVGA(portnum);
#endif
/* uint8_t chksum;
Serial.write(0xFF);
Serial.write(0x07);
outByte(portnum & 0xFF); chksum = portnum & 0xFF;
outByte((portnum >> 8) & 0xFF); chksum += (portnum >> 8) & 0xFF;
outByte(chksum);
Serial.write(0xFE);
Serial.write(0x02);*/
switch (portnum) {
case 0x20:
case 0x21: //i8259
return (in8259(portnum));
case 0x40:
case 0x41:
case 0x42:
case 0x43: //i8253
return in8253(portnum);
case 0x60:
case 0x64:
return portram[portnum];
case 0x3D4:
return crt_controller_idx;
break;
case 0x3D5:
return crt_controller[crt_controller_idx];
break;
case 0x3DA:
port3da ^= 1;
if (!(port3da & 1)) port3da ^= 8;
//port3da = random(256) & 9;
return (port3da);
default:
return (0xFF);
}
}

89
MCUME_pico/pico8086/ps2.h Executable file
View file

@ -0,0 +1,89 @@
uint8_t translatescancode(uint32_t keysym) {
if ((keysym >= 'a') && (keysym <= 'z')) {
keysym -= 0x20;
}
switch (keysym) {
case 0xFF08: return 0x0E; //backspace
case 0xFF09: return 0x0F; //tab
case 0xFF0D: return 0x1C; //enter
case 0xFF1B: return 0x01; //escape
case 0xFF63: return 0x52; //KP 0 / insert
case 0xFFFF: return 0x53; //KP . / delete
case 0xFF55: return 0x49; //pgup
case 0xFF56: return 0x51; //pgdn
case 0xFF50: return 0x47; //home
case 0xFF57: return 0x4F; //end
case 'A': return 0x1E;
case 'B': return 0x30;
case 'C': return 0x2E;
case 'D': return 0x20;
case 'E': return 0x12;
case 'F': return 0x21;
case 'G': return 0x22;
case 'H': return 0x23;
case 'I': return 0x17;
case 'J': return 0x24;
case 'K': return 0x25;
case 'L': return 0x26;
case 'M': return 0x32;
case 'N': return 0x31;
case 'O': return 0x18;
case 'P': return 0x19;
case 'Q': return 0x10;
case 'R': return 0x13;
case 'S': return 0x1F;
case 'T': return 0x14;
case 'U': return 0x16;
case 'V': return 0x2F;
case 'W': return 0x11;
case 'X': return 0x2D;
case 'Y': return 0x15;
case 'Z': return 0x2C;
case '0': case ')': return 0x0B;
case '1': case '!': return 0x02;
case '2': case '@': return 0x03;
case '3': case '#': return 0x04;
case '4': case '$': return 0x05;
case '5': case '%': return 0x06;
case '6': case '^': return 0x07;
case '7': case '&': return 0x08;
case '8': case '*': return 0x09;
case '9': case '(': return 0x0A;
case '`': case '~': return 0x29;
case '-': case '_': return 0x0C;
case '=': case '+': return 0x0D;
case '[': case '{': return 0x1A;
case ']': case '}': return 0x1B;
case '\\': case '|': return 0x2B;
case ';': case ':': return 0x27;
case '\'': case '"': return 0x28;
case ' ': return 0x39;
case ',': case '<': return 0x33;
case '.': case '>': return 0x34;
case '/': case '?': return 0x35;
case 0xFFBE: return 0x3B; //F1
case 0xFFBF: return 0x3C; //F2
case 0xFFC0: return 0x3D; //F3
case 0xFFC1: return 0x3E; //F4
case 0xFFC2: return 0x3F; //F5
case 0xFFC3: return 0x40; //F6
case 0xFFC4: return 0x41; //F7
case 0xFFC5: return 0x42; //F8
case 0xFFC6: return 0x43; //F9
case 0xFFC7: return 0x44; //F10
case 0xFFC8: return 0x57; //F11
case 0xFFC9: return 0x58; //F12
case 0xFFE1: return 0x2A; //left shift
case 0xFFE2: return 0x36; //right shift
case 0xFFE3: case 0xFFE4: return 0x1D; //control
case 0xFFE9: case 0xFFEA: return 0x38; //alt
case 0xFF51: return 0x4B; //left
case 0xFF52: return 0x48; //up
case 0xFF53: return 0x4D; //right
case 0xFF54: return 0x50; //down
}
return 0xFF;
}

3749
MCUME_pico/pico8086/rom.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,269 @@
/*
PSRAM driver for IPS6404
*/
#include "iopins.h"
#include "psram_t.h"
#ifdef HAS_PSRAM
Page PSRAM_T::pages[MAX_PAGES];
uint8_t PSRAM_T::nbPages=0;
int8_t PSRAM_T::top=0;
int8_t PSRAM_T::last=0;
#include "pico/stdlib.h"
#include "hardware/spi.h"
#define digitalWrite(pin, val) gpio_put(pin, val)
static void SPItransfer(uint8_t val)
{
uint8_t dat8=val;
spi_write_blocking(PSRAM_SPIREG, &dat8, 1);
}
static uint8_t SPItransferRD(uint8_t val)
{
uint8_t dat8=0xff;
spi_read_blocking(PSRAM_SPIREG, val, &dat8, 1);
return dat8;
}
#define SPICLOCK 104000000
//#define SPICLOCK 70000000
//#define SPICLOCK 50000000
#define SPI_MODE SPI_CPOL_0
#define RAM_READ 0xB
//#define RAM_READ 0x3
#define RAM_WRITE 0x2
uint8_t PSRAM_T::_cs, PSRAM_T::_miso, PSRAM_T::_mosi, PSRAM_T::_sclk;
PSRAM_T::PSRAM_T(uint8_t cs, uint8_t mosi, uint8_t sclk, uint8_t miso)
{
_cs = cs;
_mosi = mosi;
_sclk = sclk;
_miso = miso;
}
void PSRAM_T::begin(void)
{
spi_init(PSRAM_SPIREG, SPICLOCK);
spi_set_format(PSRAM_SPIREG, 8, SPI_MODE, SPI_CPHA_0, SPI_MSB_FIRST);
gpio_set_function(_miso , GPIO_FUNC_SPI);
gpio_set_function(_cs , GPIO_FUNC_SPI);
gpio_set_function(_sclk , GPIO_FUNC_SPI);
gpio_set_function(_mosi , GPIO_FUNC_SPI);
gpio_init(_cs);
gpio_set_dir(_cs, GPIO_OUT);
digitalWrite(_cs, 1);
sleep_ms(1);
digitalWrite(_cs, 0);
SPItransfer(0x66);
digitalWrite(_cs, 1);
sleep_ms(1);
digitalWrite(_cs, 0);
SPItransfer(0x99);
digitalWrite(_cs, 1);
sleep_ms(20);
}
void PSRAM_T::psram_write(uint32_t addr, uint8_t val)
{
digitalWrite(_cs, 0);
SPItransfer(RAM_WRITE);
SPItransfer((addr>>16)&0xff);
SPItransfer((addr>>8)&0xff);
SPItransfer(addr&0xff);
SPItransfer(val);
digitalWrite(_cs, 1);
}
uint8_t PSRAM_T::psram_read(uint32_t addr)
{
uint8_t val=0;
digitalWrite(_cs, 0);
SPItransfer(RAM_READ);
SPItransfer((addr>>16)&0xff);
SPItransfer((addr>>8)&0xff);
SPItransfer(addr&0xff);
#if RAM_READ == 0xB
SPItransfer(0xFF);
#endif
val = SPItransferRD(0xFF);
digitalWrite(_cs, 1);
return val;
}
void PSRAM_T::psram_read_n(uint32_t addr, uint8_t * val, int n)
{
digitalWrite(_cs, 0);
SPItransfer(RAM_READ);
SPItransfer((addr>>16)&0xff);
SPItransfer((addr>>8)&0xff);
SPItransfer(addr&0xff);
#if RAM_READ == 0xB
SPItransferRD(0xFF);
#endif
//while (n > 0) {
// *val++ = SPItransferRD(0xFF);
// n--;
//}
spi_read_blocking(PSRAM_SPIREG, 0xFF, val, n);
digitalWrite(_cs, 1);
}
static uint8_t resp[PAGE_SIZE];
void PSRAM_T::psram_write_n(uint32_t addr, uint8_t * val, int n)
{
digitalWrite(_cs, 0);
SPItransfer(RAM_WRITE);
SPItransfer((addr>>16)&0xff);
SPItransfer((addr>>8)&0xff);
SPItransfer(addr&0xff);
while (n > 0) {
SPItransfer(*val++);
n--;
}
//SPItransfer(val,&resp[0],n);
digitalWrite(_cs, 1);
}
void PSRAM_T::pswrite(uint32_t addr, uint8_t val)
{
psram_write(addr, val);
//return
uint32_t curPage=addr&(~(PAGE_SIZE-1));
for (int i=0; i<nbPages; i++) {
if (pages[i].pageid == curPage) {
pages[i].page[addr&(PAGE_SIZE-1)] = val;
break;
}
}
}
uint8_t PSRAM_T::psread(uint32_t addr)
{
//uint8_t val = psram_read(addr);
//return val;
uint32_t curPage=addr&(~(PAGE_SIZE-1));
uint32_t offs = addr&(PAGE_SIZE-1);
for (int i=0; i<nbPages; i++) {
if (pages[i].pageid == curPage) {
if ( (pages[i].prev != i) && (pages[i].next != i) ) {
pages[pages[i].prev].next = pages[i].next;
pages[pages[i].next].prev = pages[i].prev;
}
else if (pages[i].next != i) {
pages[pages[i].next].prev = i;
}
else if (pages[i].prev != i) {
pages[pages[i].prev].next = pages[i].prev;
last = pages[i].prev;
}
// last page accessed to top
pages[i].prev = i; //-1;
pages[i].next = top;
pages[top].prev = i;
top = i;
return pages[top].page[offs];
}
}
if (nbPages<MAX_PAGES)
{
// add at top
pages[nbPages].pageid = curPage;
pages[nbPages].prev = nbPages; //-1;
pages[nbPages].next = top;
pages[top].prev = nbPages;
top = nbPages;
nbPages++;
}
else {
// replace last and move to top
int n = pages[last].prev;
pages[n].next = n; //-1;
pages[last].pageid = curPage;
pages[last].prev = last; //-1;
pages[last].next = top;
pages[top].prev = last;
top = last;
last = n;
}
//emu_printi(curPage);
psram_read_n(curPage,&(pages[top].page[0]),PAGE_SIZE);
return pages[top].page[offs];
}
uint16_t PSRAM_T::psread_w(uint32_t addr)
{
uint32_t curPage=addr&(~(PAGE_SIZE-1));
uint32_t offs = addr&(PAGE_SIZE-1);
for (int i=0; i<nbPages; i++) {
if (pages[i].pageid == curPage) {
if ( (pages[i].prev != i) && (pages[i].next != i) ) {
pages[pages[i].prev].next = pages[i].next;
pages[pages[i].next].prev = pages[i].prev;
}
else if (pages[i].next != i) {
pages[pages[i].next].prev = i;
}
else if (pages[i].prev != i) {
pages[pages[i].prev].next = pages[i].prev;
last = pages[i].prev;
}
// last page accessed to top
pages[i].prev = i; //-1;
pages[i].next = top;
pages[top].prev = i;
top = i;
return (pages[top].page[offs+1]<<8) + pages[top].page[offs];
}
}
if (nbPages<MAX_PAGES)
{
// add at top
pages[nbPages].pageid = curPage;
pages[nbPages].prev = nbPages; //-1;
pages[nbPages].next = top;
pages[top].prev = nbPages;
top = nbPages;
nbPages++;
}
else {
// replace last and move to top
int n = pages[last].prev;
pages[n].next = n; //-1;
pages[last].pageid = curPage;
pages[last].prev = last; //-1;
pages[last].next = top;
pages[top].prev = last;
top = last;
last = n;
}
//emu_printi(curPage);
psram_read_n(curPage,&(pages[top].page[0]),PAGE_SIZE);
return (pages[top].page[offs+1]<<8) + pages[top].page[offs];
}
#endif

View file

@ -0,0 +1,53 @@
/*
PSRAM driver for IPS6404
*/
#ifndef _PSRAM_T_H_
#define _PSRAM_T_H_
#ifdef HAS_PSRAM
#ifdef __cplusplus
#include <stdio.h>
#include <stdint.h>
#define PAGE_SIZE 256 //2048 //16 //32 //2048 //1024
#define MAX_PAGES 16//8
struct Page {
uint8_t page[PAGE_SIZE];
uint32_t pageid;
int8_t next;
int8_t prev;
};
class PSRAM_T
{
public:
PSRAM_T(uint8_t _CS, uint8_t _MOSI=11, uint8_t _SCLK=13, uint8_t _MISO=12);
void begin(void);
void pswrite(uint32_t addr, uint8_t val);
uint8_t psread(uint32_t addr);
uint16_t psread_w(uint32_t addr);
private:
static uint8_t psram_read(uint32_t addr);
static void psram_read_n(uint32_t addr, uint8_t * val, int n);
static void psram_write(uint32_t addr, uint8_t val);
static void psram_write_n(uint32_t addr, uint8_t * val, int n);
protected:
static uint8_t _cs, _miso, _mosi, _sclk;
static Page pages[MAX_PAGES];
static uint8_t nbPages;
static int8_t top;
static int8_t last;
};
#endif
#endif
#endif

View file

@ -0,0 +1,957 @@
#define KEYMAP_PRESENT 1
#define PROGMEM
#include "pico.h"
#include "pico/stdlib.h"
#include "hardware/adc.h"
#include <stdio.h>
#include <string.h>
extern "C" {
#include "emuapi.h"
#include "iopins.h"
}
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
// Dual display config, initialize TFT
#include "tft_t_dma.h"
static TFT_T_DMA tft;
#else
// Non Dual display config
#ifdef USE_VGA
#include "vga_t_dma.h"
#else
#include "tft_t_dma.h"
#endif
extern TFT_T_DMA tft;
#endif
#define MAX_FILES 64
#define MAX_FILENAME_SIZE 24
#define MAX_MENULINES 9
#define TEXT_HEIGHT 16
#define TEXT_WIDTH 8
#define MENU_FILE_XOFFSET (6*TEXT_WIDTH)
#define MENU_FILE_YOFFSET (2*TEXT_HEIGHT)
#define MENU_FILE_W (MAX_FILENAME_SIZE*TEXT_WIDTH)
#define MENU_FILE_H (MAX_MENULINES*TEXT_HEIGHT)
#define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x40)
#define MENU_JOYS_YOFFSET (12*TEXT_HEIGHT)
#define MENU_VBAR_XOFFSET (0*TEXT_WIDTH)
#define MENU_VBAR_YOFFSET (MENU_FILE_YOFFSET)
#define MENU_TFT_XOFFSET (MENU_FILE_XOFFSET+MENU_FILE_W+8)
#define MENU_TFT_YOFFSET (MENU_VBAR_YOFFSET+32)
#define MENU_VGA_XOFFSET (MENU_FILE_XOFFSET+MENU_FILE_W+8)
#define MENU_VGA_YOFFSET (MENU_VBAR_YOFFSET+MENU_FILE_H-32-37)
static char romspath[64];
static int nbFiles=0;
static int curFile=0;
static int topFile=0;
static char selection[MAX_FILENAME_SIZE+1]="";
static char files[MAX_FILES][MAX_FILENAME_SIZE];
static bool menuRedraw=true;
#ifdef PICOMPUTER
static const unsigned short * keys;
static unsigned char keymatrix[6];
static int keymatrix_hitrow=-1;
static bool key_fn=false;
static bool key_alt=false;
static uint32_t keypress_t_ms=0;
static uint32_t last_t_ms=0;
static uint32_t hundred_ms_cnt=0;
static bool ledflash_toggle=false;
#endif
static int keyMap;
static bool joySwapped = false;
static uint16_t bLastState;
static int xRef;
static int yRef;
static uint8_t usbnavpad=0;
static bool menuOn=true;
/********************************
* Generic output and malloc
********************************/
void emu_printf(char * text)
{
printf("%s\n",text);
}
void emu_printf(int val)
{
printf("%d\n",val);
}
void emu_printi(int val)
{
printf("%d\n",val);
}
void emu_printh(int val)
{
printf("0x%.8\n",val);
}
static int malbufpt = 0;
static char malbuf[EXTRA_HEAP];
void * emu_Malloc(int size)
{
void * retval = malloc(size);
if (!retval) {
emu_printf("failled to allocate");
emu_printf(size);
emu_printf("fallback");
if ( (malbufpt+size) < sizeof(malbuf) ) {
retval = (void *)&malbuf[malbufpt];
malbufpt += size;
}
else {
emu_printf("failure to allocate");
}
}
else {
emu_printf("could allocate dynamic ");
emu_printf(size);
}
return retval;
}
void * emu_MallocI(int size)
{
void * retval = NULL;
if ( (malbufpt+size) < sizeof(malbuf) ) {
retval = (void *)&malbuf[malbufpt];
malbufpt += size;
emu_printf("could allocate static ");
emu_printf(size);
}
else {
emu_printf("failure to allocate");
}
return retval;
}
void emu_Free(void * pt)
{
free(pt);
}
void emu_drawText(unsigned short x, unsigned short y, const char * text, unsigned short fgcolor, unsigned short bgcolor, int doublesize)
{
tft.drawText(x, y, text, fgcolor, bgcolor, doublesize?true:false);
}
/********************************
* OSKB handling
********************************/
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
// On screen keyboard position
#define KXOFF 28 //64
#define KYOFF 96
#define KWIDTH 11 //22
#define KHEIGHT 3
static bool oskbOn = false;
static int cxpos = 0;
static int cypos = 0;
static int oskbMap = 0;
static uint16_t oskbBLastState = 0;
static void lineOSKB2(int kxoff, int kyoff, char * str, int row)
{
char c[2] = {'A',0};
const char * cpt = str;
for (int i=0; i<KWIDTH; i++)
{
c[0] = *cpt++;
c[1] = 0;
uint16_t bg = RGBVAL16(0x00,0x00,0xff);
if ( (cxpos == i) && (cypos == row) ) bg = RGBVAL16(0xff,0x00,0x00);
tft.drawTextNoDma(kxoff+8*i,kyoff, &c[0], RGBVAL16(0x00,0xff,0xff), bg, ((i&1)?false:true));
}
}
static void lineOSKB(int kxoff, int kyoff, char * str, int row)
{
char c[4] = {' ',0,' ',0};
const char * cpt = str;
for (int i=0; i<KWIDTH; i++)
{
c[1] = *cpt++;
uint16_t bg;
if (row&1) bg = (i&1)?RGBVAL16(0xff,0xff,0xff):RGBVAL16(0xe0,0xe0,0xe0);
else bg = (i&1)?RGBVAL16(0xe0,0xe0,0xe0):RGBVAL16(0xff,0xff,0xff);
if ( (cxpos == i) && (cypos == row) ) bg = RGBVAL16(0x00,0xff,0xff);
tft.drawTextNoDma(kxoff+24*i,kyoff+32*row+0 , " ", RGBVAL16(0x00,0x00,0x00), bg, false);
tft.drawTextNoDma(kxoff+24*i,kyoff+32*row+8 , &c[0], RGBVAL16(0x00,0x00,0x00), bg, true);
tft.drawTextNoDma(kxoff+24*i,kyoff+32*row+24, " ", RGBVAL16(0x00,0x00,0x00), bg, false);
}
}
static void drawOskb(void)
{
// lineOSKB2(KXOFF,KYOFF+0, (char *)"Q1W2E3R4T5Y6U7I8O9P0<=", 0);
// lineOSKB2(KXOFF,KYOFF+16, (char *)" A!S@D#F$G%H+J&K*L-EN", 1);
// lineOSKB2(KXOFF,KYOFF+32, (char *)" Z(X)C?V/B\"N<M>.,SP ", 2);
if (oskbMap == 0) {
lineOSKB(KXOFF,KYOFF, keylables_map1_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map1_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map1_2, 2);
}
else if (oskbMap == 1) {
lineOSKB(KXOFF,KYOFF, keylables_map2_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map2_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map2_2, 2);
}
else {
lineOSKB(KXOFF,KYOFF, keylables_map3_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map3_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map3_2, 2);
}
}
void toggleOskb(bool forceoff) {
if (forceoff) oskbOn=true;
if (oskbOn) {
oskbOn = false;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,32, "Press USER2 to toggle onscreen keyboard.", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0x00,0x00,0x00), true);
} else {
oskbOn = true;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,32, " Press USER2 to exit onscreen keyboard. ", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0x00,0x00,0x00), true);
tft.drawTextNoDma(0,64, " (USER1 to toggle between keymaps) ", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);
tft.drawRectNoDma(KXOFF,KYOFF, 22*8, 3*16, RGBVAL16(0x00,0x00,0xFF));
drawOskb();
}
}
static int handleOskb(void)
{
int retval = 0;
uint16_t bClick = bLastState & ~oskbBLastState;
oskbBLastState = bLastState;
/*
static const char * digits = "0123456789ABCDEF";
char buf[5] = {0,0,0,0,0};
int val = bClick;
buf[0] = digits[(val>>12)&0xf];
buf[1] = digits[(val>>8)&0xf];
buf[2] = digits[(val>>4)&0xf];
buf[3] = digits[val&0xf];
tft.drawTextNoDma(0,KYOFF+ 64,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),1);
*/
if (bClick & MASK_KEY_USER2)
{
toggleOskb(false);
}
if (oskbOn)
{
bool updated = true;
if (bClick & MASK_KEY_USER1)
{
oskbMap += 1;
if (oskbMap == 3) oskbMap = 0;
}
else if (bClick & MASK_JOY2_LEFT)
{
cxpos++;
if (cxpos >= KWIDTH) cxpos = 0;
}
else if (bClick & MASK_JOY2_RIGHT)
{
cxpos--;
if (cxpos < 0) cxpos = KWIDTH-1;
}
else if (bClick & MASK_JOY2_DOWN)
{
cypos++;
if (cypos >= KHEIGHT) cypos = 0;
}
else if (bClick & MASK_JOY2_UP)
{
cypos--;
if (cypos < 0) cypos = KHEIGHT-1;
}
else if (oskbBLastState & MASK_JOY2_BTN)
{
retval = cypos*KWIDTH+cxpos+1;
if (retval) {
retval--;
//if (retval & 1) retval = key_map2[retval>>1];
//else retval = key_map1[retval>>1];
if (oskbMap == 0) {
retval = key_map1[retval];
}
else if (oskbMap == 1) {
retval = key_map2[retval];
}
else {
retval = key_map3[retval];
}
}
}
else {
updated=false;
}
if (updated) drawOskb();
}
return retval;
}
#endif
/********************************
* Input and keyboard
********************************/
int emu_ReadAnalogJoyX(int min, int max)
{
adc_select_input(0);
int val = adc_read();
#if INVX
val = 4095 - val;
#endif
val = val-xRef;
val = ((val*140)/100);
if ( (val > -512) && (val < 512) ) val = 0;
val = val+2048;
return (val*(max-min))/4096;
}
int emu_ReadAnalogJoyY(int min, int max)
{
adc_select_input(1);
int val = adc_read();
#if INVY
val = 4095 - val;
#endif
val = val-yRef;
val = ((val*120)/100);
if ( (val > -512) && (val < 512) ) val = 0;
//val = (val*(max-min))/4096;
val = val+2048;
//return val+(max-min)/2;
return (val*(max-min))/4096;
}
static uint16_t readAnalogJoystick(void)
{
uint16_t joysval = 0;
#ifdef PIN_JOY2_A1X
int xReading = emu_ReadAnalogJoyX(0,256);
if (xReading > 128) joysval |= MASK_JOY2_LEFT;
else if (xReading < 128) joysval |= MASK_JOY2_RIGHT;
int yReading = emu_ReadAnalogJoyY(0,256);
if (yReading < 128) joysval |= MASK_JOY2_UP;
else if (yReading > 128) joysval |= MASK_JOY2_DOWN;
#endif
// First joystick
#if INVY
#ifdef PIN_JOY2_1
if ( !gpio_get(PIN_JOY2_1) ) joysval |= MASK_JOY2_DOWN;
#endif
#ifdef PIN_JOY2_2
if ( !gpio_get(PIN_JOY2_2) ) joysval |= MASK_JOY2_UP;
#endif
#else
#ifdef PIN_JOY2_1
if ( !gpio_get(PIN_JOY2_1) ) joysval |= MASK_JOY2_UP;
#endif
#ifdef PIN_JOY2_2
if ( !gpio_get(PIN_JOY2_2) ) joysval |= MASK_JOY2_DOWN;
#endif
#endif
#if INVX
#ifdef PIN_JOY2_3
if ( !gpio_get(PIN_JOY2_3) ) joysval |= MASK_JOY2_LEFT;
#endif
#ifdef PIN_JOY2_4
if ( !gpio_get(PIN_JOY2_4) ) joysval |= MASK_JOY2_RIGHT;
#endif
#else
#ifdef PIN_JOY2_3
if ( !gpio_get(PIN_JOY2_3) ) joysval |= MASK_JOY2_RIGHT;
#endif
#ifdef PIN_JOY2_4
if ( !gpio_get(PIN_JOY2_4) ) joysval |= MASK_JOY2_LEFT;
#endif
#endif
#ifdef PIN_JOY2_BTN
joysval |= (gpio_get(PIN_JOY2_BTN) ? 0 : MASK_JOY2_BTN);
#endif
return (joysval);
}
int emu_SwapJoysticks(int statusOnly) {
if (!statusOnly) {
if (joySwapped) {
joySwapped = false;
}
else {
joySwapped = true;
}
}
return(joySwapped?1:0);
}
int emu_GetPad(void)
{
return(bLastState/*|((joySwapped?1:0)<<7)*/);
}
int emu_ReadKeys(void)
{
uint16_t retval;
uint16_t j1 = readAnalogJoystick();
uint16_t j2 = 0;
// Second joystick
#if INVY
#ifdef PIN_JOY1_1
if ( !gpio_get(PIN_JOY1_1) ) j2 |= MASK_JOY2_DOWN;
#endif
#ifdef PIN_JOY1_2
if ( !gpio_get(PIN_JOY1_2) ) j2 |= MASK_JOY2_UP;
#endif
#else
#ifdef PIN_JOY1_1
if ( !gpio_get(PIN_JOY1_1) ) j2 |= MASK_JOY2_UP;
#endif
#ifdef PIN_JOY1_2
if ( !gpio_get(PIN_JOY1_2) ) j2 |= MASK_JOY2_DOWN;
#endif
#endif
#if INVX
#ifdef PIN_JOY1_3
if ( !gpio_get(PIN_JOY1_3) ) j2 |= MASK_JOY2_LEFT;
#endif
#ifdef PIN_JOY1_4
if ( !gpio_get(PIN_JOY1_4) ) j2 |= MASK_JOY2_RIGHT;
#endif
#else
#ifdef PIN_JOY1_3
if ( !gpio_get(PIN_JOY1_3) ) j2 |= MASK_JOY2_RIGHT;
#endif
#ifdef PIN_JOY1_4
if ( !gpio_get(PIN_JOY1_4) ) j2 |= MASK_JOY2_LEFT;
#endif
#endif
#ifdef PIN_JOY1_BTN
if ( !gpio_get(PIN_JOY1_BTN) ) j2 |= MASK_JOY2_BTN;
#endif
if (joySwapped) {
retval = ((j1 << 8) | j2);
}
else {
retval = ((j2 << 8) | j1);
}
if (usbnavpad & MASK_JOY2_UP) retval |= MASK_JOY2_UP;
if (usbnavpad & MASK_JOY2_DOWN) retval |= MASK_JOY2_DOWN;
if (usbnavpad & MASK_JOY2_LEFT) retval |= MASK_JOY2_LEFT;
if (usbnavpad & MASK_JOY2_RIGHT) retval |= MASK_JOY2_RIGHT;
if (usbnavpad & MASK_JOY2_BTN) retval |= MASK_JOY2_BTN;
#ifdef PIN_KEY_USER1
if ( !gpio_get(PIN_KEY_USER1) ) retval |= MASK_KEY_USER1;
#endif
#ifdef PIN_KEY_USER2
if ( !gpio_get(PIN_KEY_USER2) ) retval |= MASK_KEY_USER2;
#endif
#ifdef PIN_KEY_USER3
if ( !gpio_get(PIN_KEY_USER3) ) retval |= MASK_KEY_USER3;
#endif
#ifdef PIN_KEY_USER4
if ( !gpio_get(PIN_KEY_USER4) ) retval |= MASK_KEY_USER4;
#endif
#ifdef PICOMPUTER
keymatrix_hitrow = -1;
unsigned char row;
unsigned short cols[6]={1,2,3,4,5,14};
unsigned char keymatrixtmp[6];
for (int i=0;i<6;i++){
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(8) ? 0 : 0x02);
row |= (gpio_get(6) ? 0 : 0x04);
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] = row;
}
#ifdef MULTI_DEBOUNCE
for (int i=0;i<6;i++){
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(8) ? 0 : 0x02);
row |= (gpio_get(6) ? 0 : 0x04);
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] |= row;
}
for (int i=0;i<6;i++){
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(8) ? 0 : 0x02);
row |= (gpio_get(6) ? 0 : 0x04);
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] |= row;
}
#endif
#ifdef SWAP_ALT_DEL
// Swap ALT and DEL
unsigned char alt = keymatrixtmp[0] & 0x02;
unsigned char del = keymatrixtmp[5] & 0x20;
keymatrixtmp[0] &= ~0x02;
keymatrixtmp[5] &= ~0x20;
if (alt) keymatrixtmp[5] |= 0x20;
if (del) keymatrixtmp[0] |= 0x02;
#endif
bool alt_pressed=false;
if ( keymatrixtmp[5] & 0x20 ) {alt_pressed=true; keymatrixtmp[5] &= ~0x20;};
for (int i=0;i<6;i++){
row = keymatrixtmp[i];
if (row) keymatrix_hitrow=i;
keymatrix[i] = row;
}
//6,9,15,8,7,22
#if INVX
if ( row & 0x2 ) retval |= MASK_JOY2_LEFT;
if ( row & 0x1 ) retval |= MASK_JOY2_RIGHT;
#else
if ( row & 0x1 ) retval |= MASK_JOY2_LEFT;
if ( row & 0x2 ) retval |= MASK_JOY2_RIGHT;
#endif
#if INVY
if ( row & 0x8 ) retval |= MASK_JOY2_DOWN;
if ( row & 0x4 ) retval |= MASK_JOY2_UP;
#else
if ( row & 0x4 ) retval |= MASK_JOY2_DOWN;
if ( row & 0x8 ) retval |= MASK_JOY2_UP;
#endif
if ( row & 0x10 ) retval |= MASK_JOY2_BTN;
// Handle LED flash
uint32_t time_ms=to_ms_since_boot (get_absolute_time());
if ((time_ms-last_t_ms) > 100) {
last_t_ms = time_ms;
if (ledflash_toggle == false) {
ledflash_toggle = true;
}
else {
ledflash_toggle = false;
}
}
if ( alt_pressed ) {
if (key_fn == false)
{
// Release to Press transition
if (hundred_ms_cnt == 0) {
keypress_t_ms=time_ms;
hundred_ms_cnt += 1; // 1
}
else {
hundred_ms_cnt += 1; // 2
if (hundred_ms_cnt >= 2)
{
hundred_ms_cnt = 0;
/*
if ( (time_ms-keypress_t_ms) < 500)
{
if (key_alt == false)
{
key_alt = true;
}
else
{
key_alt = false;
}
}
*/
}
}
}
else {
// Keep press
if (hundred_ms_cnt == 1) {
if ((to_ms_since_boot (get_absolute_time())-keypress_t_ms) > 2000)
{
if (key_alt == false)
{
key_alt = true;
}
else
{
key_alt = false;
}
hundred_ms_cnt = 0;
}
}
}
key_fn = true;
}
else {
key_fn = false;
}
// Handle LED
if (key_alt == true) {
gpio_put(KLED, (ledflash_toggle?1:0));
}
else {
if (key_fn == true) {
gpio_put(KLED, 1);
}
else {
gpio_put(KLED, 0);
}
}
if ( key_fn ) retval |= MASK_KEY_USER2;
if ( ( key_fn ) && (keymatrix[0] == 0x02 )) retval |= MASK_KEY_USER1;
#endif
//Serial.println(retval,HEX);
if ( ((retval & (MASK_KEY_USER1+MASK_KEY_USER2)) == (MASK_KEY_USER1+MASK_KEY_USER2))
|| (retval & MASK_KEY_USER4 ) )
{
}
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
if (oskbOn) {
retval |= MASK_OSKB;
}
#endif
return (retval);
}
unsigned short emu_DebounceLocalKeys(void)
{
uint16_t bCurState = emu_ReadKeys();
uint16_t bClick = bCurState & ~bLastState;
bLastState = bCurState;
return (bClick);
}
int emu_ReadI2CKeyboard(void) {
int retval=0;
#ifdef PICOMPUTER
if (key_alt) {
keys = (const unsigned short *)key_map3;
}
else if (key_fn) {
keys = (const unsigned short *)key_map2;
}
else {
keys = (const unsigned short *)key_map1;
}
if (keymatrix_hitrow >=0 ) {
unsigned short match = ((unsigned short)keymatrix_hitrow<<8) | keymatrix[keymatrix_hitrow];
for (int i=0; i<sizeof(matkeys)/sizeof(unsigned short); i++) {
if (match == matkeys[i]) {
hundred_ms_cnt = 0;
return (keys[i]);
}
}
}
#endif
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
if (!menuOn) {
retval = handleOskb();
}
#endif
return(retval);
}
unsigned char emu_ReadI2CKeyboard2(int row) {
int retval=0;
#ifdef PICOMPUTER
retval = keymatrix[row];
#endif
return retval;
}
void emu_InitJoysticks(void) {
// Second Joystick
#ifdef PIN_JOY1_1
gpio_set_pulls(PIN_JOY1_1,true,false);
gpio_set_dir(PIN_JOY1_1,GPIO_IN);
#endif
#ifdef PIN_JOY1_2
gpio_set_pulls(PIN_JOY1_2,true,false);
gpio_set_dir(PIN_JOY1_2,GPIO_IN);
#endif
#ifdef PIN_JOY1_3
gpio_set_pulls(PIN_JOY1_3,true,false);
gpio_set_dir(PIN_JOY1_3,GPIO_IN);
#endif
#ifdef PIN_JOY1_4
gpio_set_pulls(PIN_JOY1_4,true,false);
gpio_set_dir(PIN_JOY1_4,GPIO_IN);
#endif
#ifdef PIN_JOY1_BTN
gpio_set_pulls(PIN_JOY1_BTN,true,false);
gpio_set_dir(PIN_JOY1_BTN,GPIO_IN);
#endif
// User keys
#ifdef PIN_KEY_USER1
gpio_set_pulls(PIN_KEY_USER1,true,false);
gpio_set_dir(PIN_KEY_USER1,GPIO_IN);
#endif
#ifdef PIN_KEY_USER2
gpio_set_dir(PIN_KEY_USER2,GPIO_IN);
gpio_set_pulls(PIN_KEY_USER2,true,false);
#endif
#ifdef PIN_KEY_USER3
gpio_set_pulls(PIN_KEY_USER3,true,false);
gpio_set_dir(PIN_KEY_USER3,GPIO_IN);
#endif
#ifdef PIN_KEY_USER4
gpio_set_pulls(PIN_KEY_USER4,true,false);
gpio_set_dir(PIN_KEY_USER4,GPIO_IN);
#endif
// First Joystick
#ifdef PIN_JOY2_1
gpio_set_pulls(PIN_JOY2_1,true,false);
gpio_set_dir(PIN_JOY2_1,GPIO_IN);
gpio_set_input_enabled(PIN_JOY2_1, true); // Force ADC as digital input
#endif
#ifdef PIN_JOY2_2
gpio_set_pulls(PIN_JOY2_2,true,false);
gpio_set_dir(PIN_JOY2_2,GPIO_IN);
gpio_set_input_enabled(PIN_JOY2_2, true); // Force ADC as digital input
#endif
#ifdef PIN_JOY2_3
gpio_set_pulls(PIN_JOY2_3,true,false);
gpio_set_dir(PIN_JOY2_3,GPIO_IN);
gpio_set_input_enabled(PIN_JOY2_3, true); // Force ADC as digital input
#endif
#ifdef PIN_JOY2_4
gpio_set_pulls(PIN_JOY2_4,true,false);
gpio_set_dir(PIN_JOY2_4,GPIO_IN);
#endif
#ifdef PIN_JOY2_BTN
gpio_set_pulls(PIN_JOY2_BTN,true,false);
gpio_set_dir(PIN_JOY2_BTN,GPIO_IN);
#endif
#ifdef PIN_JOY2_A1X
adc_init();
adc_gpio_init(PIN_JOY2_A1X);
adc_gpio_init(PIN_JOY2_A2Y);
xRef=0; yRef=0;
for (int i=0; i<10; i++) {
adc_select_input(0);
xRef += adc_read();
adc_select_input(1);
yRef += adc_read();
sleep_ms(20);
}
#if INVX
xRef = 4095 -xRef/10;
#else
xRef /= 10;
#endif
#if INVY
yRef = 4095 -yRef/10;
#else
yRef /= 10;
#endif
#endif
#ifdef PICOMPUTER
// keyboard LED
gpio_init(KLED);
gpio_set_dir(KLED, GPIO_OUT);
gpio_put(KLED, 1);
// Output (rows)
gpio_init(1);
gpio_init(2);
gpio_init(3);
gpio_init(4);
gpio_init(5);
gpio_init(14);
gpio_set_dir(1, GPIO_OUT);
gpio_set_dir(2, GPIO_OUT);
gpio_set_dir(3, GPIO_OUT);
gpio_set_dir(4, GPIO_OUT);
gpio_set_dir(5, GPIO_OUT);
gpio_set_dir(14, GPIO_OUT);
gpio_put(1, 1);
gpio_put(2, 1);
gpio_put(3, 1);
gpio_put(4, 1);
gpio_put(5, 1);
gpio_put(14, 1);
// but set as input floating when not used!
gpio_set_dir(1, GPIO_IN);
gpio_set_dir(2, GPIO_IN);
gpio_set_dir(3, GPIO_IN);
gpio_set_dir(4, GPIO_IN);
gpio_set_dir(5, GPIO_IN);
gpio_set_dir(14, GPIO_IN);
gpio_disable_pulls(1);
gpio_disable_pulls(2);
gpio_disable_pulls(3);
gpio_disable_pulls(4);
gpio_disable_pulls(5);
gpio_disable_pulls(14);
// Input pins (cols)
gpio_init(6);
gpio_init(9);
gpio_init(15);
gpio_init(8);
gpio_init(7);
gpio_init(22);
gpio_set_dir(6,GPIO_IN);
gpio_set_dir(9,GPIO_IN);
gpio_set_dir(15,GPIO_IN);
gpio_set_dir(8,GPIO_IN);
gpio_set_dir(7,GPIO_IN);
gpio_set_dir(22,GPIO_IN);
gpio_pull_up(6);
gpio_pull_up(9);
gpio_pull_up(15);
gpio_pull_up(8);
gpio_pull_up(7);
gpio_pull_up(22);
#endif
}
int emu_setKeymap(int index) {
}
/********************************
* Initialization
********************************/
void emu_init(void)
{
// Dual display config, initialize TFT
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
tft.begin();
#endif
emu_InitJoysticks();
#ifdef SWAP_JOYSTICK
joySwapped = true;
#else
joySwapped = false;
#endif
#ifdef PICOMPUTER
// Flip screen if UP pressed
if (emu_ReadKeys() & MASK_JOY2_UP)
{
#ifdef PICOMPUTERMAX
tft.flipscreen(true);
#else
tft.flipscreen(true);
#endif
}
else
{
#ifdef PICOMPUTERMAX
tft.flipscreen(false);
#else
tft.flipscreen(false);
#endif
}
#endif
}
void emu_start(void)
{
usbnavpad = 0;
keyMap = 0;
}

View file

@ -0,0 +1,90 @@
#ifndef EMUAPI_H
#define EMUAPI_H
#include "platform_config.h"
#define CUSTOM_SND 1
//#define TIMER_REND 1
#define EXTRA_HEAP 0x10
#ifdef KEYMAP_PRESENT
#define keylables_map1_0 (char *)"qwertyuiop\x1a"
#define keylables_map1_1 (char *)" asdfghjkl\x19"
#define keylables_map1_2 (char *)" zxcvbnm.\x10 "
const unsigned short key_map1[] = {
'Q','W','E','R','T','Y','U','I','O','P',157,
0,'A','S','D','F','G','H','J','K','L',0x0D,
0,'Z','X','C','V','B','N','M','.',' ',
145,157,29,17
};
#define keylables_map2_0 (char *)"1234567890 "
#define keylables_map2_1 (char *)" !@#$%+&*- "
#define keylables_map2_2 (char *)" ()?/\"<>,: "
const unsigned short key_map2[] = {
'1','2','3','4','5','6','7','8','9','0',0,
0, '!','@','#','$','%','+','&','*','-','\/',
0, '(',')','?','\/','"','<','>',',',':',
0,0,0,0
};
#define keylables_map3_0 (char *)"\x11\x12\x13\x14\x15\x16\x17\x18 "
#define keylables_map3_1 (char *)" "
#define keylables_map3_2 (char *)" ;= "
const unsigned short key_map3[] = {
133,134,135,136,137,138,139,140,0,0,0, // function keys
0, 0,0,0,0,0,0,0,0,0,0,
0, 0,0,0,0,0,0,0,';','=',
0,0,0,0
};
const unsigned short matkeys[] = {
0x020,0x120,0x220,0x320,0x420,0x408,0x308,0x208,0x108,0x008,0x002, // row 1
0x510,0x010,0x110,0x210,0x310,0x410,0x401,0x301,0x201,0x101,0x001, // row 2
0x520,0x102,0x202,0x302,0x402,0x404,0x304,0x204,0x104,0x004, // row 3
0x508,0x501,0x502,0x504 }; // cursor keys
#endif
#define MASK_JOY2_RIGHT 0x0001
#define MASK_JOY2_LEFT 0x0002
#define MASK_JOY2_UP 0x0004
#define MASK_JOY2_DOWN 0x0008
#define MASK_JOY2_BTN 0x0010
#define MASK_KEY_USER1 0x0020
#define MASK_KEY_USER2 0x0040
#define MASK_KEY_USER3 0x0080
#define MASK_JOY1_RIGHT 0x0100
#define MASK_JOY1_LEFT 0x0200
#define MASK_JOY1_UP 0x0400
#define MASK_JOY1_DOWN 0x0800
#define MASK_JOY1_BTN 0x1000
#define MASK_KEY_USER4 0x2000
extern void emu_init(void);
extern void emu_start(void);
extern void emu_InitJoysticks(void);
extern int emu_SwapJoysticks(int statusOnly);
extern unsigned short emu_DebounceLocalKeys(void);
extern int emu_ReadKeys(void);
extern int emu_GetPad(void);
extern int emu_ReadAnalogJoyX(int min, int max);
extern int emu_ReadAnalogJoyY(int min, int max);
extern int emu_ReadI2CKeyboard(void);
extern unsigned char emu_ReadI2CKeyboard2(int row);
extern void emu_KeyboardOnUp(int keymodifer, int key);
extern void emu_KeyboardOnDown(int keymodifer, int key);
extern int emu_setKeymap(int index);
#endif

View file

@ -0,0 +1,126 @@
#include "pico.h"
#include "pico/stdlib.h"
extern "C" {
#include "iopins.h"
#include "emuapi.h"
}
#include <stdio.h>
#include "psram_t.h"
#ifdef USE_VGA
#include "vga_t_dma.h"
#else
#include "tft_t_dma.h"
#endif
TFT_T_DMA tft;
#define BLUE RGBVAL16(0, 0, 170)
#define LIGHT_BLUE RGBVAL16(0, 136, 255)
static int fb_width, fb_height;
#include "hardware/clocks.h"
#include "hardware/vreg.h"
static const char * digits = "0123456789ABCDEF";
static int hk = 0;
void emu_Input(uint16_t bClick) {
hk = emu_ReadI2CKeyboard();
}
bool repeating_timer_callback(struct repeating_timer *t) {
uint16_t bClick = emu_DebounceLocalKeys();
emu_Input(bClick);
return true;
}
PSRAM_T psram = PSRAM_T(PSRAM_CS, PSRAM_MOSI, PSRAM_SCLK, PSRAM_MISO);
extern void write_loram(int address, uint8_t val) {
psram.pswrite(address,val);
}
extern uint8_t read_loram(int address) {
return (psram.psread(address));
}
int main(void) {
vreg_set_voltage(VREG_VOLTAGE_1_05);
// set_sys_clock_khz(125000, true);
// set_sys_clock_khz(150000, true);
// set_sys_clock_khz(133000, true);
// set_sys_clock_khz(200000, true);
// set_sys_clock_khz(225000, true);
set_sys_clock_khz(250000, true);
stdio_init_all();
printf("start\n");
#ifdef USE_VGA
// tft.begin(VGA_MODE_400x240);
tft.begin(VGA_MODE_320x240);
#else
tft.begin();
#endif
psram.begin();
emu_init();
emu_start();
tft.startDMA();
struct repeating_timer timer;
add_repeating_timer_ms(20, repeating_timer_callback, NULL, &timer);
tft.fillScreenNoDma(LIGHT_BLUE);
tft.get_frame_buffer_size(&fb_width, &fb_height);
tft.drawRect((fb_width-320)/2,(fb_height-200)/2, 320,200, BLUE);
char buf[4] = {32,32,32,0};
uint sys_clk = clock_get_hz(clk_sys)/1000000;
uint r1 = sys_clk/100;
uint r = sys_clk - r1*100;
uint r2 = r/10;
r = sys_clk - r1*100 - r2*10;
uint r3 = r;
buf[0] = digits[r1];
buf[1] = digits[r2];
buf[2] = digits[r3];
tft.drawText(0,0,buf,BLUE,LIGHT_BLUE,false);
int addr = 0;
while (true) {
char buf[5] = {0,0,0,0,0};
buf[0] = digits[(addr>>12)&0xf];
buf[1] = digits[(addr>>8)&0xf];
buf[2] = digits[(addr>>4)&0xf];
buf[3] = digits[addr&0xf];
buf[4] = 0;
tft.drawText(8,64+0,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),false);
for (int i=0; i<0x10; i++) {
write_loram(addr,i);
uint8_t val = 0xff;
val = read_loram(addr);
buf[0] = digits[(val>>4)&0xf];
buf[1] = digits[val&0xf];
buf[2] = 0;
tft.drawText(8,64+16+i*8,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),false);
addr += 1;
addr &= 0x1fff;
}
sleep_ms(100);
}
}