add 400x240@50 GFX mode

pull/9/head
jean-marcharvengt 2021-05-16 21:37:48 +02:00
rodzic 9853808e6a
commit d13af01361
15 zmienionych plików z 2595 dodań i 294 usunięć

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -54,11 +54,12 @@ private:
public:
MyIntervalTimer() {
//channel = NULL;
nvic_priority = 128;
//nvic_priority = 128;
}
~MyIntervalTimer() {
end();
}
/*
bool begin(void (*funct)(), unsigned int microseconds) {
if (microseconds == 0 || microseconds > MAX_PERIOD) return false;
uint32_t cycles = (F_BUS / 1000000) * microseconds - 1;
@ -84,61 +85,41 @@ public:
bool begin(void (*funct)(), double microseconds) {
return begin(funct, (float)microseconds);
}
*/
void setIntervalFast(float microseconds) { /*NEW*/
uint32_t cycles = (float)(F_BUS / 1000000) * microseconds - 0.5;
//channel->LDVAL = cycles;
}
bool setInterval(float microseconds) { /*NEW*/
/*
bool setInterval(float microseconds) {
//if (!channel) return false;
if (microseconds <= 0 || microseconds > MAX_PERIOD) return false;
setIntervalFast(microseconds);
return true;
}
*/
void end() {};
/*
void priority(uint8_t n) {
nvic_priority = n;
#if defined(KINETISK)
/*
if (channel) {
int index = channel - KINETISK_PIT_CHANNELS;
NVIC_SET_PRIORITY(IRQ_PIT_CH0 + index, nvic_priority);
//NVIC_SET_PRIORITY(IRQ_PIT_CH0 + index, nvic_priority);
}
*/
#elif defined(KINETISL)
/*
if (channel) {
int index = channel - KINETISK_PIT_CHANNELS;
nvic_priorites[index] = nvic_priority;
if (nvic_priorites[0] <= nvic_priorites[1]) {
NVIC_SET_PRIORITY(IRQ_PIT, nvic_priorites[0]);
} else {
NVIC_SET_PRIORITY(IRQ_PIT, nvic_priorites[1]);
}
}
*/
#endif
}
*/
//operator IRQ_NUMBER_t() {
/*
if (channel) {
#if defined(KINETISK)
int index = channel - KINETISK_PIT_CHANNELS;
return (IRQ_NUMBER_t)(IRQ_PIT_CH0 + index);
#elif defined(KINETISL)
return IRQ_PIT;
#endif
}
*/
//return (IRQ_NUMBER_t)NVIC_NUM_INTERRUPTS;
//}
private:
//KINETISK_PIT_CHANNEL_t *channel;
uint8_t nvic_priority;
#if defined(KINETISL)
static uint8_t nvic_priorites[2];
#endif
//uint8_t nvic_priority;
bool beginCycles(void (*funct)(), uint32_t cycles);
};

Wyświetl plik

@ -0,0 +1,150 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2017 PJRC.COM, LLC.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* 1. The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* 2. If the Software is incorporated into a build system that allows
* selection among a list of target devices, then similar target
* devices manufactured by PJRC.COM must be included in the list of
* target devices and selectable in the same manner.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
Added :
- void setIntervalFast(float microseconds)
- bool setInterval(float microseconds)
F.B.
*/
#ifndef __INTERVALTIMERX_H__
#define __INTERVALTIMERX_H__
//#include "kinetis.h"
#ifdef __cplusplus
extern "C" {
#endif
class MyIntervalTimer {
private:
static const uint32_t MAX_PERIOD = UINT32_MAX / (F_BUS / 1000000.0);
public:
MyIntervalTimer() {
//channel = NULL;
nvic_priority = 128;
}
~MyIntervalTimer() {
end();
}
bool begin(void (*funct)(), unsigned int microseconds) {
if (microseconds == 0 || microseconds > MAX_PERIOD) return false;
uint32_t cycles = (F_BUS / 1000000) * microseconds - 1;
if (cycles < 36) return false;
return beginCycles(funct, cycles);
}
bool begin(void (*funct)(), int microseconds) {
if (microseconds < 0) return false;
return begin(funct, (unsigned int)microseconds);
}
bool begin(void (*funct)(), unsigned long microseconds) {
return begin(funct, (unsigned int)microseconds);
}
bool begin(void (*funct)(), long microseconds) {
return begin(funct, (int)microseconds);
}
bool begin(void (*funct)(), float microseconds) {
if (microseconds <= 0 || microseconds > MAX_PERIOD) return false;
uint32_t cycles = (float)(F_BUS / 1000000) * microseconds - 0.5;
if (cycles < 36) return false;
return beginCycles(funct, cycles);
}
bool begin(void (*funct)(), double microseconds) {
return begin(funct, (float)microseconds);
}
void setIntervalFast(float microseconds) { /*NEW*/
uint32_t cycles = (float)(F_BUS / 1000000) * microseconds - 0.5;
//channel->LDVAL = cycles;
}
bool setInterval(float microseconds) { /*NEW*/
//if (!channel) return false;
if (microseconds <= 0 || microseconds > MAX_PERIOD) return false;
setIntervalFast(microseconds);
return true;
}
void end() {};
void priority(uint8_t n) {
nvic_priority = n;
#if defined(KINETISK)
/*
if (channel) {
int index = channel - KINETISK_PIT_CHANNELS;
NVIC_SET_PRIORITY(IRQ_PIT_CH0 + index, nvic_priority);
}
*/
#elif defined(KINETISL)
/*
if (channel) {
int index = channel - KINETISK_PIT_CHANNELS;
nvic_priorites[index] = nvic_priority;
if (nvic_priorites[0] <= nvic_priorites[1]) {
NVIC_SET_PRIORITY(IRQ_PIT, nvic_priorites[0]);
} else {
NVIC_SET_PRIORITY(IRQ_PIT, nvic_priorites[1]);
}
}
*/
#endif
}
//operator IRQ_NUMBER_t() {
/*
if (channel) {
#if defined(KINETISK)
int index = channel - KINETISK_PIT_CHANNELS;
return (IRQ_NUMBER_t)(IRQ_PIT_CH0 + index);
#elif defined(KINETISL)
return IRQ_PIT;
#endif
}
*/
//return (IRQ_NUMBER_t)NVIC_NUM_INTERRUPTS;
//}
private:
//KINETISK_PIT_CHANNEL_t *channel;
uint8_t nvic_priority;
#if defined(KINETISL)
static uint8_t nvic_priorites[2];
#endif
bool beginCycles(void (*funct)(), uint32_t cycles);
};
#ifdef __cplusplus
}
#endif
#endif

Wyświetl plik

@ -27,14 +27,14 @@ static void oneRasterLine(void) {
while (true) {
cpu.lineStartTime = get_ccount();
cpu.lineStartTime = fbmicros(); //get_ccount();
cpu.lineCycles = cpu.lineCyclesAbs = 0;
if (!cpu.exactTiming) {
vic_do();
} else {
vic_do_simple();
}
vic_do();
} else {
vic_do_simple();
}
if (--lc == 0) {
lc = LINEFREQ / 10; // 10Hz
@ -44,11 +44,10 @@ static void oneRasterLine(void) {
//Switch "ExactTiming" Mode off after a while:
if (!cpu.exactTiming) break;
// no exact timing !! JMH
//if (get_ccount() - cpu.exactTimingStartTime >= EXACTTIMINGDURATION * (F_CPU / 1000)) {
// cpu_disableExactTiming();
// break;
//}
if ( (fbmicros() - cpu.exactTimingStartTime)*1000 >= EXACTTIMINGDURATION ) {
cpu_disableExactTiming();
break;
}
};
}
@ -289,11 +288,8 @@ static char textkey[1];
static bool res=false;
static bool firsttime=true;
static unsigned char dummyline[320];
static char * oskbtext1 = "1234567890 \"$,ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static char * oskbtext2 = "FFFFFFFF ";
static char * oskbtext1 = "FFFFFFFF RD\"$ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static char * oskbtext2 = "12345678 TL ,.* 0123456789 ";
static int oskbXPos = 10;
static int oskbYPos = 0;
@ -301,14 +297,20 @@ static int oskbYPos = 0;
#define OSKB_BG VGA_RGB(255, 255, 255)
#define OSKB_HL VGA_RGB(255, 255, 0)
int emu_oskbActive(void) {
return (oskbActive?1:0);
}
void emu_DrawVsync(void)
{
char sel[2]={0,0};
if (oskbActive) {
tft.drawText(0,OSKB_YPOS,oskbtext1,OSKB_TEXT,OSKB_BG,false);
tft.drawText(0,OSKB_YPOS+8,oskbtext2,OSKB_TEXT,OSKB_BG,false);
int fbwidth;
tft.get_frame_buffer_size(&fbwidth,NULL);
tft.drawText((fbwidth-320)/2,OSKB_YPOS,oskbtext1,OSKB_TEXT,OSKB_BG,false);
tft.drawText((fbwidth-320)/2,OSKB_YPOS+8,oskbtext2,OSKB_TEXT,OSKB_BG,false);
sel[0]=(oskbYPos==0)?oskbtext1[oskbXPos]:oskbtext2[oskbXPos];
tft.drawText(oskbXPos*8,OSKB_YPOS+8*oskbYPos,sel,OSKB_TEXT,OSKB_HL,false);
tft.drawText((fbwidth-320)/2+oskbXPos*8,OSKB_YPOS+8*oskbYPos,sel,OSKB_TEXT,OSKB_HL,false);
}
//skip += 1;
//skip &= VID_FRAME_SKIP;
@ -316,20 +318,13 @@ void emu_DrawVsync(void)
}
void * emu_LineBuffer(int line)
{
if ( (line >= OSKB_YPOS) && (oskbActive) )
return &dummyline[0];
return (void*)tft.getLineBuffer(line);
}
void c64_Input(int bClick) {
if (oskbActive) {
if (bClick & MASK_JOY2_BTN) {
textkey[0] = oskbtext1[oskbXPos];
if (oskbYPos==1) if (oskbXPos<8) textkey[0] = 0x85+oskbXPos;
if (bClick & MASK_JOY2_BTN) {
if (oskbXPos == 10) textkey[0] = 13;
else if (oskbXPos == 11) textkey[0] = 157;
else if (oskbXPos < 8) textkey[0] = 0x85+oskbXPos;
else textkey[0] = (oskbYPos == 0)?oskbtext1[oskbXPos]:oskbtext2[oskbXPos];
textseq = textkey;
nbkeys = 1;
kcnt = 0;

Wyświetl plik

@ -2677,11 +2677,11 @@ noOpcode:
cia_clockt(cpu.ticks);
c-= cpu.ticks;
cpu.lineCycles += cpu.ticks;
//if (cpu.exactTiming) {
//uint32_t t = cpu.lineCycles * MCU_C64_RATIO;
//while (ARM_DWT_CYCCNT - cpu.lineStartTime < t){;}
//}
#define US_C64_CYCLE (1000000.0f / CLOCKSPEED) // Duration (µs) of a C64 Cycle
if (cpu.exactTiming) {
uint32_t t = cpu.lineCycles * US_C64_CYCLE;
while (fbmicros() - cpu.lineStartTime < t){;}
}
};
@ -2696,9 +2696,9 @@ void cpu_setExactTiming() {
vic_displaySimpleModeScreen();
}
//cpu.exactTiming = 1;
//cpu.exactTimingStartTime = ARM_DWT_CYCCNT;
cpu.exactTiming = 0;
cpu.exactTiming = 1;
cpu.exactTimingStartTime = fbmicros();
//cpu.exactTiming = 0;
}
//Disable "ExactTiming" Mode

Wyświetl plik

@ -118,6 +118,7 @@ extern int emu_ReadAnalogJoyY(int min, int max);
extern int emu_ReadI2CKeyboard(void);
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);

Wyświetl plik

@ -35,7 +35,8 @@ int main(void) {
stdio_init_all();
tft.begin(VGA_MODE_320x240);
tft.begin(VGA_MODE_400x240);
// tft.begin(VGA_MODE_320x240);
emu_init();
while (true) {
if (menuActive()) {
@ -76,7 +77,10 @@ void emu_SetPaletteEntry(unsigned char r, unsigned char g, unsigned char b, int
}
}
void * emu_LineBuffer(int line)
{
return (void*)tft.getLineBuffer(line);
}
void emu_DrawLine(unsigned char * VBuf, int width, int height, int line)
{

Wyświetl plik

@ -39,12 +39,12 @@ Copyright Frank Bösing, 2017
#include "Teensy64.h"
static inline unsigned get_ccount(void)
{
//unsigned r;
//asm volatile ("rsr %0, ccount" : "=r"(r));
return 0;
}
//static inline unsigned get_ccount(void)
//{
// //unsigned r;
// //asm volatile ("rsr %0, ccount" : "=r"(r));
// return (time_us_32());
//}
void disableEventResponder(void);

199
MCUME_pico/pico64/vic.cpp 100644 → 100755
Wyświetl plik

@ -45,7 +45,6 @@
- optimize more
*/
#include "Teensy64.h"
#include "vic.h"
#include <string.h>
@ -58,22 +57,35 @@
#define PALETTE(r,g,b) (RGBVAL16(r,g,b)) //(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3))
#include "vic_palette.h"
#define BORDER (240-200)/2
#define SCREEN_HEIGHT (200+2*BORDER)
#define SCREEN_WIDTH 320
//#define LINE_MEM_WIDTH 320
#define FIRSTDISPLAYLINE ( 51 - BORDER )
#define LASTDISPLAYLINE ( 250 + BORDER )
#define BORDER_LEFT 0
#define BORDER_RIGHT 0
typedef uint8_t tpixel;
#define MAXCYCLESSPRITES0_2 3
#define MAXCYCLESSPRITES3_7 5
#define MAXCYCLESSPRITES (MAXCYCLESSPRITES0_2 + MAXCYCLESSPRITES3_7)
static tpixel * SCREENMEM=NULL;
static int LINE_MEM_WIDTH=0;
static int REAL_XRES=0;
static int REAL_YRES=0;
#define SCREEN_WIDTH (320)
/*
static int BORDER=0;
static int SCREEN_HEIGHT=0;
static int FIRSTDISPLAYLINE=0;
static int LASTDISPLAYLINE=0;
static int BORDER_LEFT=0;
static int BORDER_RIGHT=0;
*/
#define BORDER ((REAL_YRES-200)/2)
#define SCREEN_HEIGHT (200+2*BORDER)
#define FIRSTDISPLAYLINE ( 51 - BORDER )
#define LASTDISPLAYLINE ( 250 + BORDER )
#define BORDER_LEFT ((REAL_XRES-320)/2)
#define BORDER_RIGHT ((REAL_XRES-320)/2)
#define MAXCYCLESSPRITES0_2 3
#define MAXCYCLESSPRITES3_7 5
#define MAXCYCLESSPRITES (MAXCYCLESSPRITES0_2 + MAXCYCLESSPRITES3_7)
/*****************************************************************************************************/
@ -1271,8 +1283,6 @@ typedef void (*modes_t)( tpixel *p, const tpixel *pe, uint16_t *spl, const uint1
const modes_t modes[8] = {mode0, mode1, mode2, mode3, mode4, mode5, mode6, mode7};
//static tpixel linebuffer[SCREEN_WIDTH];
void vic_do(void) {
uint16_t vc;
@ -1291,6 +1301,7 @@ void vic_do(void) {
*/
if ( cpu.vic.rasterLine >= LINECNT ) {
//reSID sound needs much time - too much to keep everything in sync and with stable refreshrate
//but it is not called very often, so most of the time, we have more time than needed.
//We can measure the time needed for a frame and calc a correction factor to speed things up.
@ -1302,14 +1313,14 @@ void vic_do(void) {
cpu.vic.rasterLine = 0;
cpu.vic.vcbase = 0;
cpu.vic.denLatch = 0;
//if (cpu.vic.rasterLine == LINECNT) {
emu_DrawVsync();
//}
emu_DrawVsync();
} else cpu.vic.rasterLine++;
int r = cpu.vic.rasterLine;
// if ( (r >= LASTDISPLAYLINE) && (emu_oskbActive()) ) return;
if (r == cpu.vic.intRasterLine )//Set Rasterline-Interrupt
cpu.vic.R[0x19] |= 1 | ((cpu.vic.R[0x1a] & 1) << 7);
@ -1392,18 +1403,61 @@ void vic_do(void) {
}
//max_x = (!cpu.vic.CSEL) ? 40:38;
//p = SCREENMEM + (r - FIRSTDISPLAYLINE) * LINE_MEM_WIDTH;
//p = &linebuffer[0]; //tft.getLineBuffer((r - FIRSTDISPLAYLINE));
p = (tpixel*)emu_LineBuffer((r - FIRSTDISPLAYLINE));
p = SCREENMEM + (r - FIRSTDISPLAYLINE) * LINE_MEM_WIDTH;
uint16_t col;
//#if !VGA
if(REAL_XRES == SCREEN_WIDTH) {
pe = p + SCREEN_WIDTH;
//Left Screenborder: Cycle 10
spl = &cpu.vic.spriteLine[24];
cpu_clock(6);
}
else {
pe = p + SCREEN_WIDTH + BORDER_LEFT;
col = cpu.vic.colors[0];
//Left Screenborder: Cycle 10
for (int i = 0; i <2; i++) {
cpu_clock(1);
*p++ = col;*p++ = col;*p++ = col;*p++ = col;
*p++ = col;*p++ = col;*p++ = col;*p++ = col;
}
//Left Screenborder: Cycle 13
#if 0 //mit Sprites
spl = &cpu.vic.spriteLine[0];
uint16_t sprite;
for (int i=0; i<3; i++) {
cpu_clock(1);
SPRITEORFIXEDCOLOR();
SPRITEORFIXEDCOLOR();
SPRITEORFIXEDCOLOR();
SPRITEORFIXEDCOLOR();
SPRITEORFIXEDCOLOR();
SPRITEORFIXEDCOLOR();
SPRITEORFIXEDCOLOR();
SPRITEORFIXEDCOLOR();
}
#else //ohne sprites
spl = &cpu.vic.spriteLine[24];
for (int i=0; i<3; i++) {
cpu_clock(1);
*p++ = col;*p++ = col;*p++ = col;*p++ = col;
*p++ = col;*p++ = col;*p++ = col;*p++ = col;
}
#endif
}
if (cpu.vic.borderFlag) {
cpu_clock(5);
fastFillLineNoSprites(p, pe + BORDER_RIGHT, cpu.vic.colors[0]);
//#if !VGA
if(REAL_XRES == SCREEN_WIDTH) {
cpu_clock(5);
}
if ( (!emu_oskbActive()) )
fastFillLineNoSprites(p, pe + BORDER_RIGHT, cpu.vic.colors[0]);
goto noDisplayIncRC ;
}
@ -1558,9 +1612,7 @@ g-Zugriff
cpu_clock(1);
uint16_t col = cpu.vic.colors[0];
//p = &screen[r - FIRSTDISPLAYLINE][0];
//p = SCREENMEM + (r - FIRSTDISPLAYLINE) * LINE_MEM_WIDTH + BORDER_LEFT;
//p = &linebuffer[0]; // tft.getLineBuffer((r - FIRSTDISPLAYLINE));
p = (tpixel*)emu_LineBuffer((r - FIRSTDISPLAYLINE));
p = SCREENMEM + (r - FIRSTDISPLAYLINE) * LINE_MEM_WIDTH + BORDER_LEFT;
#if 0
// Sprites im Rand
uint16_t sprite;
@ -1583,10 +1635,8 @@ g-Zugriff
//Rand rechts:
//p = &screen[r - FIRSTDISPLAYLINE][SCREEN_WIDTH - 9];
//p = SCREENMEM + (r - FIRSTDISPLAYLINE) * LINE_MEM_WIDTH + SCREEN_WIDTH - 9 + BORDER_LEFT;
//p = &linebuffer[SCREEN_WIDTH - 9 + BORDER_LEFT]; //tft.getLineBuffer((r - FIRSTDISPLAYLINE)) + SCREEN_WIDTH - 9 + BORDER_LEFT;
p = (tpixel*)emu_LineBuffer((r - FIRSTDISPLAYLINE)) + SCREEN_WIDTH - 9 + BORDER_LEFT;
pe = p + 9;
p = SCREENMEM + (r - FIRSTDISPLAYLINE) * LINE_MEM_WIDTH + SCREEN_WIDTH - 9 + BORDER_LEFT;
pe = p + 9;
#if 0
// Sprites im Rand
@ -1596,20 +1646,32 @@ g-Zugriff
}
#else
//keine Sprites im Rand
//while (p < pe) {
// *p++ = col;
//}
while (p < pe) {
*p++ = col;
}
#endif
}
// emu_DrawLine8(&linebuffer[0], SCREEN_WIDTH, SCREEN_HEIGHT, (r - FIRSTDISPLAYLINE));
//Rechter Rand nach CSEL, im Textbereich
cpu_clock(5);
//#if VGA
if(REAL_XRES != SCREEN_WIDTH) {
p = SCREENMEM + (r - FIRSTDISPLAYLINE) * LINE_MEM_WIDTH + SCREEN_WIDTH + BORDER_LEFT;
pe += BORDER_RIGHT;
#if 0
// Sprites im Rand
while (p < pe) {
SPRITEORFIXEDCOLOR();
}
#else
//keine Sprites im Rand
while (p < pe) {
*p++ = col;
}
#endif
}
noDisplayIncRC:
@ -1891,7 +1953,7 @@ if ( cpu.vic.rasterLine >= LINECNT ) {
cpu.vic.rasterLine = 0;
cpu.vic.vcbase = 0;
cpu.vic.denLatch = 0;
emu_DrawVsync();
} else {
cpu.vic.rasterLine++;
cpu_clock(1);
@ -1899,6 +1961,8 @@ if ( cpu.vic.rasterLine >= LINECNT ) {
}
int r = cpu.vic.rasterLine;
// if ( (r >= LASTDISPLAYLINE) && (emu_oskbActive()) ) return;
if (r == cpu.vic.intRasterLine )//Set Rasterline-Interrupt
cpu.vic.R[0x19] |= 1 | ((cpu.vic.R[0x1a] & 1) << 7);
@ -1964,16 +2028,6 @@ if ( cpu.vic.rasterLine >= LINECNT ) {
}
/*****************************************************************************************************/
/*****************************************************************************************************/
/*****************************************************************************************************/
void installPalette(void) {
memcpy(cpu.vic.palette, (void*)palette, sizeof(cpu.vic.palette));
}
/*****************************************************************************************************/
/*****************************************************************************************************/
/*****************************************************************************************************/
@ -2002,17 +2056,17 @@ void vic_write(uint32_t address, uint8_t value) {
switch (address) {
case 0x11 :
cpu.vic.R[address] = value;
cpu.vic.R[address] = value;
cpu.vic.intRasterLine = (cpu.vic.intRasterLine & 0xff) | ((((uint16_t) value) << 1) & 0x100);
if (cpu.vic.rasterLine == 0x30 ) cpu.vic.denLatch |= value & 0x10;
cpu.vic.badline = (cpu.vic.denLatch && (cpu.vic.rasterLine >= 0x30) && (cpu.vic.rasterLine <= 0xf7) && ( (cpu.vic.rasterLine & 0x07) == (value & 0x07)));
if (cpu.vic.badline) {
cpu.vic.idle = 0;
}
if (cpu.vic.badline) {
cpu.vic.idle = 0;
}
vic_adrchange();
vic_adrchange();
break;
case 0x12 :
@ -2109,7 +2163,40 @@ uint8_t vic_read(uint32_t address) {
/*****************************************************************************************************/
/*****************************************************************************************************/
void installPalette(void) {
memcpy(cpu.vic.palette, (void*)palette, sizeof(cpu.vic.palette));
}
/*****************************************************************************************************/
/*****************************************************************************************************/
/*****************************************************************************************************/
#define XOFFSET 4
#define YOFFSET 16
void resetVic(void) {
LINE_MEM_WIDTH = tft.get_frame_buffer_size(&REAL_XRES,&REAL_YRES);
SCREENMEM=(tpixel*)emu_LineBuffer(0);
/*
if (REAL_XRES == SCREEN_WIDTH) {
BORDER = (REAL_YRES-200)/2;
SCREEN_HEIGHT = (200+2*BORDER);
FIRSTDISPLAYLINE = ( 51 - BORDER );
LASTDISPLAYLINE = ( 250 + BORDER );
BORDER_LEFT = 0;
BORDER_RIGHT = 0;
}
else {
BORDER = (REAL_YRES-200)/2;
SCREEN_HEIGHT = (200+2*BORDER);
FIRSTDISPLAYLINE = ( 51 - BORDER );
LASTDISPLAYLINE = ( 250 + BORDER );
BORDER_LEFT = (REAL_XRES-320)/2;
BORDER_RIGHT = (REAL_XRES-320)/2;
}
*/
enableCycleCounter();
cpu.vic.intRasterLine = 0;
@ -2117,8 +2204,6 @@ void resetVic(void) {
cpu.vic.lineHasSprites = 0;
memset(&cpu.RAM[0x400], 0, 1000);
memset(&cpu.vic, 0, sizeof(cpu.vic));
installPalette();

Plik diff jest za duży Load Diff

Wyświetl plik

@ -34,7 +34,7 @@ static vga_pixel * visible_framebuffer = NULL;
static vga_pixel * framebuffer = NULL;
static vga_pixel * fb0 = NULL;
uint8_t * pio_fb = NULL;
uint32_t * pio_fb = NULL;
int pio_fbwidth=0;
@ -46,14 +46,13 @@ static int fb_stride;
static int left_border;
static int top_border;
static scanvideo_mode_t vga_mode;
static semaphore_t video_initted;
static semaphore_t core1_initted;
static void core1_func();
PolyDef PolySet; // will contain a polygon data
#define vga_mode vga_mode_320x240_60
#define RGBVAL16(r,g,b) ( (((b>>3)&0x1f)<<11) | (((g>>2)&0x3f)<<5) | (((r>>3)&0x1f)<<0) )
#define PICO_SCANVIDEO_PIXEL_FROM_RGBVAL8(rgb) (((rgb&0x3)<<(PICO_SCANVIDEO_PIXEL_BSHIFT))|(((rgb&0x1C)>>2)<<(PICO_SCANVIDEO_PIXEL_GSHIFT))|(((rgb&0xE0)>>5)<<(PICO_SCANVIDEO_PIXEL_RSHIFT)))
@ -63,15 +62,16 @@ static void core1_sio_irq();
static void core1_func() {
// initialize video and interrupts on core 1
scanvideo_setup(&vga_mode);
scanvideo_timing_enable(true);
sem_release(&video_initted);
// initialize video
scanvideo_setup(&vga_mode);
scanvideo_timing_enable(true);
multicore_fifo_clear_irq();
irq_set_exclusive_handler(SIO_IRQ_PROC1,core1_sio_irq);
//irq_set_priority (SIO_IRQ_PROC1, 129);
irq_set_enabled(SIO_IRQ_PROC1,true);
sem_release(&core1_initted);
while (true) {
tight_loop_contents();
@ -116,26 +116,23 @@ vga_error_t VGA_T4::begin(vga_mode_t mode)
{
switch(mode) {
case VGA_MODE_320x240:
vga_mode = vga_mode_320x240_60;
fb_width = 320;
fb_height = 240;
left_border = (320-fb_width)/2;
top_border = (240-fb_height)/2;
fb_height = 240;
left_border = 0;
top_border = 0;
fb_stride = fb_width+16;
break;
case VGA_MODE_320x480:
break;
case VGA_MODE_640x240:
break;
case VGA_MODE_640x480:
break;
case VGA_MODE_512x240:
break;
case VGA_MODE_512x480:
break;
case VGA_MODE_352x240:
break;
case VGA_MODE_400x240:
vga_mode = vga_mode_tft_400x240_50;
fb_width = 400;
fb_height = 240;
left_border = 0;
top_border = 0;
fb_stride = fb_width+16;
break;
case VGA_MODE_352x480:
break;
}
@ -147,19 +144,19 @@ vga_error_t VGA_T4::begin(vga_mode_t mode)
init_pio_framebuffer(fb0);
pio_fb = fb0;
pio_fbwidth = (320 + 2*6)/4;
pio_fb = (uint32_t*)fb0;
pio_fbwidth = (fb_width + 2*6)/4;
visible_framebuffer = fb0+PIO_FB_OFFSET;
framebuffer = fb0+PIO_FB_OFFSET;
// create a semaphore to be posted when video init is complete
sem_init(&video_initted, 0, 1);
// launch all the video on core 1, so it isn't affected by USB handling on core 0
// create a semaphore to be posted when audio init is complete
sem_init(&core1_initted, 0, 1);
multicore_launch_core1(core1_func);
// wait for initialization of video to be complete
sem_acquire_blocking(&video_initted);
// wait for initialization of audio to be complete
sem_acquire_blocking(&core1_initted);
return(VGA_OK);
}
@ -173,10 +170,11 @@ void VGA_T4::debug()
}
// retrieve size of the frame buffer
void VGA_T4::get_frame_buffer_size(int *width, int *height)
int VGA_T4::get_frame_buffer_size(int *width, int *height)
{
*width = fb_width;
*height = fb_height;
if (width != nullptr) *width = fb_width;
if (height != nullptr) *height = fb_height;
return fb_stride;
}
void VGA_T4::waitSync()
@ -1450,13 +1448,13 @@ void VGA_T4::run_gfxengine()
waitSync();
if (fb1 != NULL) {
if (pio_fb == fb0) {
pio_fb = fb1;
if (pio_fb == (uint32_t*)fb0) {
pio_fb = (uint32_t*)fb1;
visible_framebuffer = fb1+PIO_FB_OFFSET;
framebuffer = fb0+PIO_FB_OFFSET;
}
else {
pio_fb = fb0;
pio_fb = (uint32_t*)fb0;
visible_framebuffer = fb0+PIO_FB_OFFSET;
framebuffer = fb1+PIO_FB_OFFSET;
}

Wyświetl plik

@ -32,13 +32,8 @@ typedef uint8_t vga_pixel;
typedef enum vga_mode_t
{
VGA_MODE_320x240 = 0,
VGA_MODE_320x480 = 1,
VGA_MODE_352x240 = 2,
VGA_MODE_352x480 = 3,
VGA_MODE_512x240 = 4,
VGA_MODE_512x480 = 5,
VGA_MODE_640x240 = 6,
VGA_MODE_640x480 = 7
VGA_MODE_352x240 = 1,
VGA_MODE_400x240 = 2,
} vga_mode_t;
@ -170,7 +165,7 @@ public:
void tweak_video(int shiftdelta, int numdelta, int denomdelta);
// retrieve real size of the frame buffer
void get_frame_buffer_size(int *width, int *height);
int get_frame_buffer_size(int *width, int *height);
// wait next Vsync
void waitSync();

Wyświetl plik

@ -48,7 +48,7 @@
#define PICO_SCANVIDEO_SCANLINE_DMA_CHANNELS_MASK (1u << PICO_SCANVIDEO_SCANLINE_DMA_CHANNEL)
extern uint8_t * pio_fb;
extern uint32_t * pio_fb;
extern int pio_fbwidth;
@ -75,6 +75,28 @@ const scanvideo_timing_t vga_timing_640x480_60_default =
.enable_den = 0
};
const scanvideo_timing_t vga_timing_wide_480_50 =
{
.clock_freq = 24000000, //24000000,
.h_active = 800,
.v_active = 480,
.h_front_porch = 32, //12,
.h_pulse = 48,
.h_total = 960,
.h_sync_polarity = 0,
.v_front_porch = 1,
.v_pulse = 2,
.v_total = 500,
.v_sync_polarity = 0,
.enable_clock = 0,
.clock_polarity = 0,
.enable_den = 0
};
const scanvideo_mode_t vga_mode_320x240_60 =
{
@ -87,6 +109,15 @@ const scanvideo_mode_t vga_mode_320x240_60 =
};
const scanvideo_mode_t vga_mode_tft_400x240_50 =
{
.default_timing = &vga_timing_wide_480_50,
.pio_program = &video_24mhz_composable,
.width = 400,
.height = 240,
.xscale = 2,
.yscale = 2,
};
#define scanline_assert(x) (void)0
@ -120,7 +151,6 @@ const scanvideo_pio_program_t video_24mhz_composable = {
.configure_pio = video_24mhz_composable_configure_pio
};
#define PIO_WAIT_IRQ4 pio_encode_wait_irq(1, false, 4)
static uint8_t video_htiming_load_offset;
static uint8_t video_program_load_offset;
@ -231,9 +261,9 @@ void __video_time_critical_func(prepare_for_active_scanline_irqs_enabled)() {
full_scanline_buffer_t *fsb = &scanline_buffer;
uint16_t scanline = shared_state.scanline.next_scanline_id & 0xffffu;
if (scanline < 240)
fsb->core.data = (uint32_t *)&pio_fb[(320+16)*scanline];
fsb->core.data = &pio_fb[(pio_fbwidth+1)*scanline];
else
fsb->core.data = (uint32_t *)&pio_fb[(320+16)*(0)];
fsb->core.data = &pio_fb[0];
dma_channel_transfer_from_buffer_now(PICO_SCANVIDEO_SCANLINE_DMA_CHANNEL, fsb->core.data,
(uint32_t) fsb->core.data_used);
shared_state.scanline.in_vblank = false;
@ -352,19 +382,9 @@ void setup_sm(int sm, uint offset) {
sm_config_set_out_shift(&config, true, true, 32);
const uint BASE = PICO_SCANVIDEO_SYNC_PIN_BASE; // hsync and vsync are +0 and +1, clock is +2
uint pin_count;
#if PICO_SCANVIDEO_ENABLE_DEN_PIN
pin_count = 3;
// 3 OUT pins and maybe 1 sideset pin following them
#else
// 2 OUT pins and 1 sideset pin following them
pin_count = 2;
#endif
sm_config_set_out_pins(&config, BASE, pin_count);
#if PICO_SCANVIDEO_ENABLE_DEN_PIN
// side set pin as well
sm_config_set_sideset_pins(&config, BASE + pin_count);
pin_count++;
#endif
pio_sm_set_consecutive_pindirs(video_pio, sm, BASE, pin_count, true);
}
@ -387,9 +407,6 @@ void scanvideo_set_scanline_repeat_fn(scanvideo_scanline_repeat_count_fn fn) {
_scanline_repeat_count_fn = fn ? fn : default_scanvideo_scanline_repeat_count_fn;
}
bool scanvideo_setup(const scanvideo_mode_t *mode) {
return scanvideo_setup_with_timing(mode, mode->default_timing);
}
static pio_program_t copy_program(const pio_program_t *program, uint16_t *instructions,
uint32_t max_instructions) {
@ -400,8 +417,7 @@ static pio_program_t copy_program(const pio_program_t *program, uint16_t *instru
return copy;
}
bool scanvideo_setup_with_timing(const scanvideo_mode_t *mode, const scanvideo_timing_t *timing) {
static bool scanvideo_setup_with_timing(const scanvideo_mode_t *mode, const scanvideo_timing_t *timing) {
__builtin_memset(&shared_state, 0, sizeof(shared_state));
// init non zero members
@ -409,9 +425,6 @@ bool scanvideo_setup_with_timing(const scanvideo_mode_t *mode, const scanvideo_t
video_mode = *mode;
video_mode.default_timing = timing;
static_assert(BPP == 16, ""); // can't do 8 bit now because of pixel count
// this is no longer necessary
//assert(!(mode->width & 1));
if (!video_mode.yscale_denominator) video_mode.yscale_denominator = 1;
// todo is this still necessary?
//invalid_params_if(SCANVIDEO_DPI, (timing->v_active % mode->yscale));
@ -424,15 +437,6 @@ bool scanvideo_setup_with_timing(const scanvideo_mode_t *mode, const scanvideo_t
uint pin_mask = 3u << PICO_SCANVIDEO_SYNC_PIN_BASE;
bi_decl_if_func_used(bi_2pins_with_names(PICO_SCANVIDEO_SYNC_PIN_BASE, "HSync",
PICO_SCANVIDEO_SYNC_PIN_BASE + 1, "VSync"));
#if PICO_SCANVIDEO_ENABLE_DEN_PIN
bi_decl_if_func_used(bi_1pin_with_name(PICO_SCANVIDEO_SYNC_PIN_BASE + 2, "Display Enable"));
pin_mask |= 4u << PICO_SCANVIDEO_SYNC_PIN_BASE;
#endif
#if PICO_SCANVIDEO_ENABLE_CLOCK_PIN
bi_decl_if_func_used(bi_1pin_with_name(PICO_SCANVIDEO_SYNC_PIN_BASE + 3, "Pixel Clock"));
pin_mask |= 8u << PICO_SCANVIDEO_SYNC_PIN_BASE;
#endif
static_assert(PICO_SCANVIDEO_PIXEL_RSHIFT + PICO_SCANVIDEO_PIXEL_RCOUNT <= PICO_SCANVIDEO_COLOR_PIN_COUNT, "red bits do not fit in color pins");
static_assert(PICO_SCANVIDEO_PIXEL_GSHIFT + PICO_SCANVIDEO_PIXEL_GCOUNT <= PICO_SCANVIDEO_COLOR_PIN_COUNT, "green bits do not fit in color pins");
static_assert(PICO_SCANVIDEO_PIXEL_BSHIFT + PICO_SCANVIDEO_PIXEL_BCOUNT <= PICO_SCANVIDEO_COLOR_PIN_COUNT, "blue bits do not fit in color pins");
@ -455,15 +459,9 @@ bool scanvideo_setup_with_timing(const scanvideo_mode_t *mode, const scanvideo_t
#else
uint sys_clk = clock_get_hz(clk_sys);
video_clock_down_times_2 = sys_clk / timing->clock_freq;
#if PICO_SCANVIDEO_ENABLE_CLOCK_PIN
if (video_clock_down_times_2 * timing->clock_freq != sys_clk) {
panic("System clock (%d) must be an integer multiple of 2 times the requested pixel clock (%d).", sys_clk, timing->clock_freq);
}
#else
if (video_clock_down_times_2 * timing->clock_freq != sys_clk) {
panic("System clock (%d) must be an integer multiple of the requested pixel clock (%d).", sys_clk, timing->clock_freq);
}
#endif
//if (video_clock_down_times_2 * timing->clock_freq != sys_clk) {
// panic("System clock (%d) must be an integer multiple of the requested pixel clock (%d).", sys_clk, timing->clock_freq);
//}
#endif
valid_params_if(SCANVIDEO_DPI, mode->width * mode->xscale <= timing->h_active);
@ -583,6 +581,11 @@ bool scanvideo_setup_with_timing(const scanvideo_mode_t *mode, const scanvideo_t
return true;
}
bool scanvideo_setup(const scanvideo_mode_t *mode) {
return scanvideo_setup_with_timing(mode, mode->default_timing);
}
bool video_24mhz_composable_adapt_for_mode(const scanvideo_pio_program_t *program, const scanvideo_mode_t *mode,
scanvideo_scanline_buffer_t *missing_scanline_buffer,
uint16_t *modifiable_instructions) {
@ -602,22 +605,13 @@ bool video_24mhz_composable_adapt_for_mode(const scanvideo_pio_program_t *progra
}
void scanvideo_default_configure_pio(pio_hw_t *pio, uint sm, uint offset, pio_sm_config *config, bool overlay) {
pio_sm_set_consecutive_pindirs(pio, sm, PICO_SCANVIDEO_COLOR_PIN_BASE, PICO_SCANVIDEO_COLOR_PIN_COUNT, true);
sm_config_set_out_pins(config, PICO_SCANVIDEO_COLOR_PIN_BASE, PICO_SCANVIDEO_COLOR_PIN_COUNT);
sm_config_set_out_shift(config, true, true, 32); // autopull
sm_config_set_fifo_join(config, PIO_FIFO_JOIN_TX);
if (overlay) {
sm_config_set_out_special(config, 1, 1, PICO_SCANVIDEO_ALPHA_PIN);
} else {
sm_config_set_out_special(config, 1, 0, 0);
}
}
pio_sm_config video_24mhz_composable_configure_pio(pio_hw_t *pio, uint sm, uint offset) {
pio_sm_config config = video_24mhz_composable_default_program_get_default_config(offset);
scanvideo_default_configure_pio(pio, sm, offset, &config, sm != PICO_SCANVIDEO_SCANLINE_SM);
pio_sm_set_consecutive_pindirs(pio, sm, PICO_SCANVIDEO_COLOR_PIN_BASE, PICO_SCANVIDEO_COLOR_PIN_COUNT, true);
sm_config_set_out_pins(&config, PICO_SCANVIDEO_COLOR_PIN_BASE, PICO_SCANVIDEO_COLOR_PIN_COUNT);
sm_config_set_out_shift(&config, true, true, 32); // autopull
sm_config_set_fifo_join(&config, PIO_FIFO_JOIN_TX);
sm_config_set_out_special(&config, 1, 0, 0);
return config;
}

Wyświetl plik

@ -9,7 +9,7 @@
// note that defining to false will force non-inclusion also
#if !defined(PICO_SCANVIDEO_DPI)
#define PICO_SCANVIDEO_DPI 1
//#define PICO_SCANVIDEO_DPI 1
#ifndef PARAM_ASSERTIONS_ENABLED_SCANVIDEO_DPI
#define PARAM_ASSERTIONS_ENABLED_SCANVIDEO_DPI 0
@ -17,10 +17,6 @@
#include "scanvideo_base.h"
#ifndef PICO_SCANVIDEO_DPI_ALPHA_PIN
#define PICO_SCANVIDEO_DPI_ALPHA_PIN 5u
#endif
#ifndef PICO_SCANVIDEO_DPI_PIXEL_RSHIFT
#define PICO_SCANVIDEO_DPI_PIXEL_RSHIFT 0u
#endif
@ -45,10 +41,6 @@
#define PICO_SCANVIDEO_DPI_PIXEL_BCOUNT 2
#endif
#ifndef PICO_SCANVIDEO_ALPHA_PIN
#define PICO_SCANVIDEO_ALPHA_PIN PICO_SCANVIDEO_DPI_ALPHA_PIN
#endif
#ifndef PICO_SCANVIDEO_PIXEL_RSHIFT
#define PICO_SCANVIDEO_PIXEL_RSHIFT PICO_SCANVIDEO_DPI_PIXEL_RSHIFT
#endif

Wyświetl plik

@ -8,13 +8,8 @@
#define SCANVIDEO_scanvideo_H_
#include "pico/types.h"
#if !PICO_NO_HARDWARE
#include "hardware/pio.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -26,14 +21,6 @@ extern "C" {
*/
// == CONFIG ============
#ifndef PICO_SCANVIDEO_ENABLE_CLOCK_PIN
#define PICO_SCANVIDEO_ENABLE_CLOCK_PIN 0
#endif
#ifndef PICO_SCANVIDEO_ENABLE_DEN_PIN
#define PICO_SCANVIDEO_ENABLE_DEN_PIN 0
#endif
#ifndef PICO_SCANVIDEO_COLOR_PIN_BASE
#define PICO_SCANVIDEO_COLOR_PIN_BASE 2
#endif
@ -46,16 +33,10 @@ extern "C" {
#define PICO_SCANVIDEO_SYNC_PIN_BASE (PICO_SCANVIDEO_COLOR_PIN_BASE + PICO_SCANVIDEO_COLOR_PIN_COUNT)
#endif
#ifndef PICO_SCANVIDEO_ENABLE_VIDEO_CLOCK_DOWN
#define PICO_SCANVIDEO_ENABLE_VIDEO_CLOCK_DOWN 0
#endif
// ======================
#define BPP 16
// most likely 24000000
extern const uint32_t video_clock_freq;
@ -101,12 +82,7 @@ typedef struct scanvideo_mode {
} scanvideo_mode_t;
extern bool scanvideo_setup(const scanvideo_mode_t *mode);
extern bool scanvideo_setup_with_timing(const scanvideo_mode_t *mode, const scanvideo_timing_t *timing);
extern void scanvideo_timing_enable(bool enable);
// these take effect after the next vsync
extern void scanvideo_display_enable(bool enable);
// doesn't exist yet!
// extern void video_set_display_mode(const struct scanvideo_mode *mode);
// --- scanline management ---
@ -158,53 +134,24 @@ void scanvideo_set_scanline_repeat_fn(scanvideo_scanline_repeat_count_fn fn);
extern const scanvideo_timing_t vga_timing_640x480_60_default;
extern const scanvideo_mode_t vga_mode_320x240_60;
extern const scanvideo_mode_t vga_mode_tft_400x240_50;
// mode implementation
struct scanvideo_pio_program {
#if !PICO_NO_HARDWARE
const pio_program_t *program;
const uint8_t entry_point;
// modifiable_instructions is of size program->length
bool (*adapt_for_mode)(const scanvideo_pio_program_t *program, const scanvideo_mode_t *mode,
scanvideo_scanline_buffer_t *missing_scanline_buffer, uint16_t *modifiable_instructions);
pio_sm_config (*configure_pio)(pio_hw_t *pio, uint sm, uint offset);
#else
const char *id;
#endif
};
extern const scanvideo_pio_program_t video_24mhz_composable;
#if !PICO_NO_HARDWARE
extern void scanvideo_default_configure_pio(pio_hw_t *pio, uint sm, uint offset, pio_sm_config *config, bool overlay);
#endif
// note this is not necessarily an absolute gpio pin mask, it is still shifted by PICO_SCANVIDEO_COLOR_PIN_BASE
#define PICO_SCANVIDEO_ALPHA_MASK (1u << PICO_SCANVIDEO_ALPHA_PIN)
#ifndef PICO_SCANVIDEO_PIXEL_FROM_RGB8
#define PICO_SCANVIDEO_PIXEL_FROM_RGB8(r, g, b) ((((b)>>3u)<<PICO_SCANVIDEO_PIXEL_BSHIFT)|(((g)>>3u)<<PICO_SCANVIDEO_PIXEL_GSHIFT)|(((r)>>3u)<<PICO_SCANVIDEO_PIXEL_RSHIFT))
#endif
#ifndef PICO_SCANVIDEO_PIXEL_FROM_RGB5
#define PICO_SCANVIDEO_PIXEL_FROM_RGB5(r, g, b) (((b)<<PICO_SCANVIDEO_PIXEL_BSHIFT)|((g)<<PICO_SCANVIDEO_PIXEL_GSHIFT)|((r)<<PICO_SCANVIDEO_PIXEL_RSHIFT))
#endif
#ifndef PICO_SCANVIDEO_R5_FROM_PIXEL
#define PICO_SCANVIDEO_R5_FROM_PIXEL(p) (((p)>>PICO_SCANVIDEO_PIXEL_RSHIFT)&0x1f)
#endif
#ifndef PICO_SCANVIDEO_G5_FROM_PIXEL
#define PICO_SCANVIDEO_G5_FROM_PIXEL(p) (((p)>>PICO_SCANVIDEO_PIXEL_GSHIFT)&0x1f)
#endif
#ifndef PICO_SCANVIDEO_B5_FROM_PIXEL
#define PICO_SCANVIDEO_B5_FROM_PIXEL(p) (((p)>>PICO_SCANVIDEO_PIXEL_BSHIFT)&0x1f)
#endif
#ifdef __cplusplus
}
#endif