add initial psram support and 8086 emulator for PICO
This commit is contained in:
parent
6a66f7ed41
commit
9685fa074b
26 changed files with 11253 additions and 2 deletions
|
|
@ -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}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
176
MCUME_pico/pico8086/AudioPlaySystem.cpp
Normal file
176
MCUME_pico/pico8086/AudioPlaySystem.cpp
Normal 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
|
||||
26
MCUME_pico/pico8086/AudioPlaySystem.h
Normal file
26
MCUME_pico/pico8086/AudioPlaySystem.h
Normal 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
2267
MCUME_pico/pico8086/cpu.cpp
Executable file
File diff suppressed because it is too large
Load diff
257
MCUME_pico/pico8086/disk.cpp
Normal file
257
MCUME_pico/pico8086/disk.cpp
Normal 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
159
MCUME_pico/pico8086/emu.h
Normal 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];
|
||||
} ;
|
||||
1274
MCUME_pico/pico8086/emuapi.cpp
Normal file
1274
MCUME_pico/pico8086/emuapi.cpp
Normal file
File diff suppressed because it is too large
Load diff
147
MCUME_pico/pico8086/emuapi.h
Normal file
147
MCUME_pico/pico8086/emuapi.h
Normal 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
264
MCUME_pico/pico8086/font.h
Normal 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
|
||||
};
|
||||
|
||||
119
MCUME_pico/pico8086/i8253.cpp
Normal file
119
MCUME_pico/pico8086/i8253.cpp
Normal 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
83
MCUME_pico/pico8086/i8259.cpp
Executable 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);
|
||||
}
|
||||
|
||||
20
MCUME_pico/pico8086/keyboard_osd.h
Normal file
20
MCUME_pico/pico8086/keyboard_osd.h
Normal 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
146
MCUME_pico/pico8086/network.cpp
Executable 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
664
MCUME_pico/pico8086/pc.cpp
Normal 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
5
MCUME_pico/pico8086/pc.h
Normal 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);
|
||||
|
||||
178
MCUME_pico/pico8086/pico8086.cpp
Normal file
178
MCUME_pico/pico8086/pico8086.cpp
Normal 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
98
MCUME_pico/pico8086/ports.cpp
Executable 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
89
MCUME_pico/pico8086/ps2.h
Executable 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
3749
MCUME_pico/pico8086/rom.h
Normal file
File diff suppressed because it is too large
Load diff
269
MCUME_pico/psram/psram_t.cpp
Normal file
269
MCUME_pico/psram/psram_t.cpp
Normal 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
|
||||
53
MCUME_pico/psram/psram_t.h
Normal file
53
MCUME_pico/psram/psram_t.h
Normal 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
|
||||
|
||||
957
MCUME_pico/testpsram/emuapi.cpp
Normal file
957
MCUME_pico/testpsram/emuapi.cpp
Normal 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;
|
||||
}
|
||||
90
MCUME_pico/testpsram/emuapi.h
Normal file
90
MCUME_pico/testpsram/emuapi.h
Normal 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
|
||||
126
MCUME_pico/testpsram/testpsram.cpp
Normal file
126
MCUME_pico/testpsram/testpsram.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in a new issue