kopia lustrzana https://github.com/Jean-MarcHarvengt/MCUME
add 400x240@50 GFX mode
rodzic
9853808e6a
commit
d13af01361
Plik binarny nie jest wyświetlany.
|
@ -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);
|
||||
|
||||
};
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Ładowanie…
Reference in New Issue