mirror of
https://github.com/JorjBauer/aiie.git
synced 2025-02-27 23:29:05 +00:00
merging display paths between SDL and Teensy
This commit is contained in:
parent
c4954b9ec5
commit
efc36d40a8
@ -263,38 +263,41 @@ void SDLDisplay::clrScr(uint8_t coloridx)
|
||||
SDL_RenderPresent(renderer); // perform the render
|
||||
}
|
||||
|
||||
// This was called with the expectation that it can draw every one of
|
||||
// the 560x192 pixels that could be addressed. The SDLDISPLAY_SCALE is
|
||||
// basically half the X scale - so a 320-pixel-wide screen can show 40
|
||||
// columns fine, which means that we need to be creative for 80 columns,
|
||||
// which need to be alpha-blended...
|
||||
// This was called with the expectation that it can draw every one of
|
||||
// the 560x192 pixels that could be addressed. If TEENSYDISPLAY_SCALE
|
||||
// is 1, then we have half of that horizontal resolution - so we need
|
||||
// to be creative and blend neighboring pixels together.
|
||||
void SDLDisplay::cachePixel(uint16_t x, uint16_t y, uint8_t color)
|
||||
{
|
||||
if (SDLDISPLAY_SCALE == 1) {
|
||||
// we need to alpha blend the X because there aren't enough screen pixels.
|
||||
// This takes advantage of the fact that we always call this linearly
|
||||
// for the 80-column text -- we never (?) do partial screen blits, but
|
||||
// always wind up redrawing the entirety. So we can look at the pixel in
|
||||
// the "shared" cell of RAM, and come up with a color between the two.
|
||||
if (x&1) {
|
||||
uint32_t origColor = videoBuffer[y][(x>>1)*SDLDISPLAY_SCALE];
|
||||
uint32_t newColor = blendPackedColor(origColor, packColor32(loresPixelColors[color]));
|
||||
cacheDoubleWidePixel(x>>1,y,newColor);
|
||||
// Else if it's black, we leave whatever was in the other pixel.
|
||||
#if SDLDISPLAY_SCALE == 1
|
||||
// This is the case where we need to blend together neighboring
|
||||
// pixels, because we don't have enough physical screen resoultion.
|
||||
|
||||
if (x&1) {
|
||||
uint32_t origColor = videoBuffer[y][(x>>1)*SDLDISPLAY_SCALE];
|
||||
uint32_t newColor = packColor32(loresPixelColors[color]);
|
||||
if (g_displayType == m_blackAndWhite) {
|
||||
// FIXME: the two possible sets here of 'origColor && newColor' or 'origColor||newColor'
|
||||
// work well for black-on-white and white-on-black. But neither is good in the other.
|
||||
cacheDoubleWidePixel(x>>1,y,(uint32_t)((origColor && newColor) ? 0xFFFFFF : 0x000000));
|
||||
} else {
|
||||
// The even pixels always draw.
|
||||
cacheDoubleWidePixel(x>>1,y,color);
|
||||
cacheDoubleWidePixel(x>>1,y,(uint32_t)blendPackedColor(origColor, newColor));
|
||||
}
|
||||
|
||||
// Else if it's black, we leave whatever was in the other pixel.
|
||||
} else {
|
||||
// we have enough resolution to show all the pixels, so just do it
|
||||
x = (x * SDLDISPLAY_SCALE)/2;
|
||||
for (int yoff=0; yoff<SDLDISPLAY_SCALE; yoff++) {
|
||||
for (int xoff=0; xoff<SDLDISPLAY_SCALE; xoff++) {
|
||||
videoBuffer[(y*SDLDISPLAY_SCALE+yoff)][x+xoff] = packColor32(loresPixelColors[color]);
|
||||
}
|
||||
// The even pixels always draw.
|
||||
cacheDoubleWidePixel(x>>1,y,color);
|
||||
}
|
||||
#else
|
||||
// we have enough resolution to show all the pixels, so just do it
|
||||
x = (x * SDLDISPLAY_SCALE)/2;
|
||||
for (int yoff=0; yoff<SDLDISPLAY_SCALE; yoff++) {
|
||||
for (int xoff=0; xoff<SDLDISPLAY_SCALE; xoff++) {
|
||||
videoBuffer[(y*SDLDISPLAY_SCALE+yoff)][x+xoff] = packColor32(loresPixelColors[color]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// "DoubleWide" means "please double the X because I'm in low-res width mode"
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
// scale can be 1,2,4. '1' is half-width at the highest resolution
|
||||
// (80-col mode). '2' is full width. '4' is double full width.
|
||||
#define SDLDISPLAY_SCALE 2
|
||||
#define SDLDISPLAY_SCALE 1
|
||||
#define SDLDISPLAY_WIDTH (320*SDLDISPLAY_SCALE)
|
||||
#define SDLDISPLAY_HEIGHT (240*SDLDISPLAY_SCALE)
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "teensy-display.h"
|
||||
|
||||
#include "appleui.h"
|
||||
// FIXME should be able to omit this include and relay on the xterns, which
|
||||
// FIXME should be able to omit this include and rely on the xterns, which
|
||||
// would prove it's linking properly
|
||||
#include "font.h"
|
||||
extern const unsigned char ucase_glyphs[512];
|
||||
@ -12,8 +12,10 @@ extern const unsigned char lcase_glyphs[256];
|
||||
extern const unsigned char mousetext_glyphs[256];
|
||||
extern const unsigned char interface_glyphs[256];
|
||||
|
||||
#include <SPI.h>
|
||||
#include "globals.h"
|
||||
#include "applevm.h"
|
||||
|
||||
#include <SPI.h>
|
||||
#define _clock 75000000
|
||||
|
||||
|
||||
@ -24,33 +26,8 @@ extern const unsigned char interface_glyphs[256];
|
||||
#define PIN_MISO 1
|
||||
#define PIN_SCK 27
|
||||
|
||||
// Inside the 320x240 display, the Apple display is 280x192.
|
||||
// (That's half the "correct" width, b/c of double-hi-res.)
|
||||
#define apple_display_w 280
|
||||
#define apple_display_h 192
|
||||
|
||||
// Inset inside the apple2 "frame" where we draw the display
|
||||
// remember these are "starts at pixel number" values, where 0 is the first.
|
||||
#define HOFFSET 18
|
||||
#define VOFFSET 13
|
||||
|
||||
#include "globals.h"
|
||||
#include "applevm.h"
|
||||
|
||||
#define PHYSMAXX 320
|
||||
#define PHYSMAXY 240
|
||||
DMAMEM uint16_t dmaBuffer[PHYSMAXY][PHYSMAXX]; // 240 rows, 320 columns
|
||||
|
||||
#define RGBto565(r,g,b) ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | ((b) >> 3))
|
||||
#define _565toR(c) ( ((c) & 0xF800) >> 8 )
|
||||
#define _565toG(c) ( ((c) & 0x07E0) >> 5 )
|
||||
#define _565toB(c) ( ((c) & 0x001F) )
|
||||
|
||||
//ILI9341_t3 tft = ILI9341_t3(PIN_CS, PIN_DC, PIN_RST, PIN_MOSI, PIN_SCK, PIN_MISO);
|
||||
ILI9341_t3n tft = ILI9341_t3n(PIN_CS, PIN_DC, PIN_RST, PIN_MOSI, PIN_SCK, PIN_MISO);
|
||||
|
||||
DMAChannel dmatx;
|
||||
DMASetting dmaSetting;
|
||||
#define SCREENINSET_X (18*TEENSYDISPLAY_SCALE)
|
||||
#define SCREENINSET_Y (13*TEENSYDISPLAY_SCALE)
|
||||
|
||||
// RGB map of each of the lowres colors
|
||||
const uint16_t loresPixelColors[16] = { 0x0000, // 0 black
|
||||
@ -71,41 +48,20 @@ const uint16_t loresPixelColors[16] = { 0x0000, // 0 black
|
||||
0xFFFF // 15 white
|
||||
};
|
||||
|
||||
const uint16_t loresPixelColorsGreen[16] = { 0x0000,
|
||||
0x0140,
|
||||
0x0040,
|
||||
0x0280,
|
||||
0x0300,
|
||||
0x0340,
|
||||
0x0300,
|
||||
0x0480,
|
||||
0x02C0,
|
||||
0x0240,
|
||||
0x0500,
|
||||
0x0540,
|
||||
0x0580,
|
||||
0x0700,
|
||||
0x0680,
|
||||
0x07C0
|
||||
};
|
||||
// This definition can't live in the class header because of the
|
||||
// DMAMEM adornment
|
||||
DMAMEM uint16_t dmaBuffer[TEENSYDISPLAY_HEIGHT][TEENSYDISPLAY_WIDTH];
|
||||
|
||||
#define RGBto565(r,g,b) ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | ((b) >> 3))
|
||||
#define _565toR(c) ( ((c) & 0xF800) >> 8 )
|
||||
#define _565toG(c) ( ((c) & 0x07E0) >> 5 )
|
||||
#define _565toB(c) ( ((c) & 0x001F) )
|
||||
|
||||
ILI9341_t3n tft = ILI9341_t3n(PIN_CS, PIN_DC, PIN_RST, PIN_MOSI, PIN_SCK, PIN_MISO);
|
||||
|
||||
DMAChannel dmatx;
|
||||
DMASetting dmaSetting;
|
||||
|
||||
const uint16_t loresPixelColorsWhite[16] = { 0x0000,
|
||||
0x2945,
|
||||
0x0841,
|
||||
0x528A,
|
||||
0x630C,
|
||||
0x6B4D,
|
||||
0x630C,
|
||||
0x9492,
|
||||
0x5ACB,
|
||||
0x4A49,
|
||||
0xA514,
|
||||
0xAD55,
|
||||
0xB596,
|
||||
0xE71C,
|
||||
0xD69A,
|
||||
0xFFDF
|
||||
};
|
||||
|
||||
TeensyDisplay::TeensyDisplay()
|
||||
{
|
||||
@ -125,36 +81,60 @@ TeensyDisplay::~TeensyDisplay()
|
||||
{
|
||||
}
|
||||
|
||||
void TeensyDisplay::flush()
|
||||
{
|
||||
// Nothing to flush, b/c the DMA driver is regularly flushing everything
|
||||
}
|
||||
|
||||
void TeensyDisplay::redraw()
|
||||
{
|
||||
g_ui->drawStaticUIElement(UIeOverlay);
|
||||
|
||||
if (g_vm) {
|
||||
if (g_vm && g_ui) {
|
||||
g_ui->drawOnOffUIElement(UIeDisk1_state, ((AppleVM *)g_vm)->DiskName(0)[0] == '\0');
|
||||
g_ui->drawOnOffUIElement(UIeDisk2_state, ((AppleVM *)g_vm)->DiskName(1)[0] == '\0');
|
||||
}
|
||||
}
|
||||
|
||||
void TeensyDisplay::clrScr(uint8_t coloridx)
|
||||
void TeensyDisplay::drawImageOfSizeAt(const uint8_t *img,
|
||||
uint16_t sizex, uint8_t sizey,
|
||||
uint16_t wherex, uint8_t wherey)
|
||||
{
|
||||
if (coloridx == c_black) {
|
||||
memset(dmaBuffer, 0x00, sizeof(dmaBuffer));
|
||||
} else if (coloridx == c_white) {
|
||||
memset(dmaBuffer, 0xFF, sizeof(dmaBuffer));
|
||||
} else {
|
||||
uint16_t color16 = loresPixelColors[c_black];
|
||||
if (coloridx < 16)
|
||||
color16 = loresPixelColors[coloridx];
|
||||
// This could be faster - make one line, then memcpy the line to the other
|
||||
// lines?
|
||||
for (uint8_t y=0; y<PHYSMAXY; y++) {
|
||||
for (uint16_t x=0; x<PHYSMAXX; x++) {
|
||||
dmaBuffer[y][x] = color16;
|
||||
}
|
||||
uint8_t r, g, b;
|
||||
|
||||
for (uint8_t y=0; y<sizey; y++) {
|
||||
for (uint16_t x=0; x<sizex; x++) {
|
||||
r = pgm_read_byte(&img[(y*sizex + x)*3 + 0]);
|
||||
g = pgm_read_byte(&img[(y*sizex + x)*3 + 1]);
|
||||
b = pgm_read_byte(&img[(y*sizex + x)*3 + 2]);
|
||||
dmaBuffer[y+wherey][x+wherex] = RGBto565(r,g,b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TeensyDisplay::blit()
|
||||
{
|
||||
// Start DMA transfers if they aren't running
|
||||
if (!tft.asyncUpdateActive())
|
||||
tft.updateScreenAsync(true);
|
||||
|
||||
// draw overlay, if any, occasionally
|
||||
{
|
||||
static uint32_t nextMessageTime = 0;
|
||||
if (millis() >= nextMessageTime) {
|
||||
if (overlayMessage[0]) {
|
||||
drawString(M_SELECTDISABLED, 1, TEENSYDISPLAY_HEIGHT - (16 + 12)*TEENSYDISPLAY_SCALE, overlayMessage);
|
||||
}
|
||||
nextMessageTime = millis() + 1000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TeensyDisplay::blit(AiieRect r)
|
||||
{
|
||||
// Nothing to do here, since we're regularly blitting the whole screen via DMA
|
||||
}
|
||||
|
||||
void TeensyDisplay::drawUIPixel(uint16_t x, uint16_t y, uint16_t color)
|
||||
{
|
||||
// These pixels are just cached in the buffer; they're not drawn directly.
|
||||
@ -173,34 +153,6 @@ void TeensyDisplay::drawPixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint
|
||||
drawPixel(x,y,color16);
|
||||
}
|
||||
|
||||
void TeensyDisplay::flush()
|
||||
{
|
||||
blit({0,0,191,279});
|
||||
}
|
||||
|
||||
void TeensyDisplay::blit()
|
||||
{
|
||||
// Start DMA transfers if they aren't running
|
||||
if (!tft.asyncUpdateActive())
|
||||
tft.updateScreenAsync(true);
|
||||
|
||||
// draw overlay, if any, occasionally
|
||||
{
|
||||
static uint32_t nextMessageTime = 0;
|
||||
if (millis() >= nextMessageTime) {
|
||||
if (overlayMessage[0]) {
|
||||
drawString(M_SELECTDISABLED, 1, PHYSMAXY - 16 - 12, overlayMessage);
|
||||
}
|
||||
nextMessageTime = millis() + 1000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TeensyDisplay::blit(AiieRect r)
|
||||
{
|
||||
// Nothing to do here, since we're regularly blitting the whole screen via DMA
|
||||
}
|
||||
|
||||
void TeensyDisplay::drawCharacter(uint8_t mode, uint16_t x, uint8_t y, char c)
|
||||
{
|
||||
int8_t xsize = 8,
|
||||
@ -234,15 +186,11 @@ void TeensyDisplay::drawCharacter(uint8_t mode, uint16_t x, uint8_t y, char c)
|
||||
// This does not scale when drawing, because drawPixel scales.
|
||||
const unsigned char *ch = asciiToAppleGlyph(c);
|
||||
for (int8_t y_off = 0; y_off <= ysize; y_off++) {
|
||||
if (y + y_off < PHYSMAXY) {
|
||||
for (int8_t x_off = 0; x_off <= xsize; x_off++) {
|
||||
if (x+x_off < PHYSMAXX) {
|
||||
if (*ch & (1 << (x_off))) {
|
||||
dmaBuffer[y+y_off][x+x_off] = onPixel;
|
||||
} else {
|
||||
dmaBuffer[y+y_off][x+x_off] = offPixel;
|
||||
}
|
||||
}
|
||||
for (int8_t x_off = 0; x_off <= xsize; x_off++) {
|
||||
if (*ch & (1 << (x_off))) {
|
||||
drawUIPixel(x + x_off, y + y_off, onPixel);
|
||||
} else {
|
||||
drawUIPixel(x + x_off, y + y_off, offPixel);
|
||||
}
|
||||
}
|
||||
ch++;
|
||||
@ -251,58 +199,35 @@ void TeensyDisplay::drawCharacter(uint8_t mode, uint16_t x, uint8_t y, char c)
|
||||
|
||||
void TeensyDisplay::drawString(uint8_t mode, uint16_t x, uint8_t y, const char *str)
|
||||
{
|
||||
int8_t xsize = 8; // width of a char in this font
|
||||
int8_t xsize = 8; // width of a char in this font
|
||||
|
||||
for (int8_t i=0; i<strlen(str); i++) {
|
||||
drawCharacter(mode, x, y, str[i]);
|
||||
x += xsize;
|
||||
if (x >= PHYSMAXX) break;
|
||||
x += xsize; // fixme: any inter-char spacing?
|
||||
if (x >= 320) break; // FIXME constant - and pre-scaling, b/c that's in drawCharacter
|
||||
}
|
||||
}
|
||||
|
||||
void TeensyDisplay::drawImageOfSizeAt(const uint8_t *img,
|
||||
uint16_t sizex, uint8_t sizey,
|
||||
uint16_t wherex, uint8_t wherey)
|
||||
void TeensyDisplay::clrScr(uint8_t coloridx)
|
||||
{
|
||||
uint8_t r, g, b;
|
||||
|
||||
for (uint8_t y=0; y<sizey; y++) {
|
||||
for (uint16_t x=0; x<sizex; x++) {
|
||||
r = pgm_read_byte(&img[(y*sizex + x)*3 + 0]);
|
||||
g = pgm_read_byte(&img[(y*sizex + x)*3 + 1]);
|
||||
b = pgm_read_byte(&img[(y*sizex + x)*3 + 2]);
|
||||
dmaBuffer[y+wherey][x+wherex] = RGBto565(r,g,b);
|
||||
if (coloridx == c_black) {
|
||||
memset(dmaBuffer, 0x00, sizeof(dmaBuffer));
|
||||
} else if (coloridx == c_white) {
|
||||
memset(dmaBuffer, 0xFF, sizeof(dmaBuffer));
|
||||
} else {
|
||||
uint16_t color16 = loresPixelColors[c_black];
|
||||
if (coloridx < 16)
|
||||
color16 = loresPixelColors[coloridx];
|
||||
// This could be faster - make one line, then memcpy the line to the other
|
||||
// lines?
|
||||
for (uint8_t y=0; y<TEENSYDISPLAY_HEIGHT; y++) {
|
||||
for (uint16_t x=0; x<TEENSYDISPLAY_WIDTH; x++) {
|
||||
dmaBuffer[y][x] = color16;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// "DoubleWide" means "please double the X because I'm in low-res
|
||||
// width mode". But we only have half the horizontal width required on
|
||||
// the Teensy, so it's divided in half.
|
||||
void TeensyDisplay::cacheDoubleWidePixel(uint16_t x, uint16_t y, uint8_t color)
|
||||
{
|
||||
uint16_t color16;
|
||||
color16 = loresPixelColors[(( color & 0x0F ) )];
|
||||
dmaBuffer[y+VOFFSET][x+HOFFSET] = color16;
|
||||
}
|
||||
|
||||
// This exists for 4bpp optimization. We could totally call
|
||||
// cacheDoubleWidePixel twice, but the (x&1) pfutzing is messy if
|
||||
// we're just storing both halves anyway...
|
||||
void TeensyDisplay::cache2DoubleWidePixels(uint16_t x, uint16_t y,
|
||||
uint8_t colorA, uint8_t colorB)
|
||||
{
|
||||
dmaBuffer[y+VOFFSET][x+ HOFFSET] = loresPixelColors[colorB&0xF];
|
||||
dmaBuffer[y+VOFFSET][x+1+HOFFSET] = loresPixelColors[colorA&0xF];
|
||||
}
|
||||
|
||||
inline double logfn(double x)
|
||||
{
|
||||
// At a value of x=255, log(base 1.022)(x) is 254.636.
|
||||
return log(x)/log(1.022);
|
||||
}
|
||||
|
||||
|
||||
inline uint16_t blendColors(uint16_t a, uint16_t b)
|
||||
{
|
||||
// Straight linear average doesn't work well for inverted text, because the
|
||||
@ -327,56 +252,80 @@ inline uint16_t blendColors(uint16_t a, uint16_t b)
|
||||
|
||||
}
|
||||
|
||||
// This is the full 560-pixel-wide version -- and we only have 280
|
||||
// pixels in our buffer b/c the display is only 320 pixels wide
|
||||
// itself. So we'll divide x by 2. On odd-numbered X pixels, we also
|
||||
// blend the colors of the two virtual pixels that share an onscreen
|
||||
// pixel
|
||||
// This was called with the expectation that it can draw every one of
|
||||
// the 560x192 pixels that could be addressed. If TEENSYDISPLAY_SCALE
|
||||
// is 1, then we have half of that horizontal resolution - so we need
|
||||
// to be creative and blend neighboring pixels together.
|
||||
void TeensyDisplay::cachePixel(uint16_t x, uint16_t y, uint8_t color)
|
||||
{
|
||||
#if 0
|
||||
static uint8_t previousColor = 0;
|
||||
#endif
|
||||
#if TEENSYDISPLAY_SCALE == 1
|
||||
// This is the case where we need to blend together neighboring
|
||||
// pixels, because we don't have enough physical screen resoultion.
|
||||
if (x&1) {
|
||||
// Blend the two pixels. This takes advantage of the fact that we
|
||||
// always call this linearly for 80-column text drawing -- we never
|
||||
// do partial screen blits, but always draw at least a whole character.
|
||||
// So we can look at the pixel in the "shared" cell of RAM, and come up
|
||||
// with a color between the two.
|
||||
|
||||
#if 1
|
||||
// This is straight blending, R/G/B average, except in B&W mode
|
||||
uint16_t origColor = dmaBuffer[y+VOFFSET][(x>>1)+HOFFSET];
|
||||
uint16_t newColor = loresPixelColors[color];
|
||||
uint8_t origColor = dmaBuffer[y+SCREENINSET_Y][(x>>1)*TEENSYDISPLAY_SCALE+SCREENINSET_X];
|
||||
cacheDoubleWidePixel(x>>1, y, color);
|
||||
#if 0
|
||||
uint8_t newColor = (uint16_t) (origColor + color) / 2;
|
||||
if (g_displayType == m_blackAndWhite) {
|
||||
cacheDoubleWidePixel(x>>1, y, (origColor && newColor) ? 0xFFFF : 0x0000);
|
||||
} else {
|
||||
cacheDoubleWidePixel(x>>1, y, blendColors(origColor, newColor));
|
||||
cacheDoubleWidePixel(x>>1,y,blendColors(origColor, newColor));
|
||||
// Else if it's black, we leave whatever was in the other pixel.
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// The model we use for the SDL display works better, strangely - it keeps
|
||||
// the lores pixel index color (black, magenda, dark blue, purple, dark
|
||||
// green, etc.) until render time; so when it does the blend here, it's
|
||||
// actually blending in a very nonlinear way - e.g. "black + white / 2"
|
||||
// is actually "black(0) + white(15) / 2 = 15/2 = 7 (light blue)". Weird,
|
||||
// but definitely legible in a mini laptop SDL window with the same scale.
|
||||
// Unfortunately, it doesn't translate well to a ILI9341 panel; the pixels
|
||||
// are kind of muddy and indistinct, so the blue spills over and makes it
|
||||
// very difficult to read.
|
||||
uint8_t origColor = previousColor;
|
||||
uint8_t newColor = (uint16_t)(origColor + color) / 2;
|
||||
cacheDoubleWidePixel(x>>1, y, (uint16_t)color + (uint16_t)previousColor/2);
|
||||
#endif
|
||||
} else {
|
||||
#if 0
|
||||
previousColor = color; // used for blending
|
||||
// The even pixels always draw.
|
||||
cacheDoubleWidePixel(x>>1,y,color);
|
||||
}
|
||||
#else
|
||||
// we have enough resolution to show all the pixels, so just do it
|
||||
x = (x * TEENSYDISPLAY_SCALE)/2;
|
||||
for (int yoff=0; yoff<TEENSYDISPLAY_SCALE; yoff++) {
|
||||
for (int xoff=0; xoff<TEENSYDISPLAY_SCALE; xoff++) {
|
||||
dmaBuffer[y*TEENSYDISPLAY_SCALE+yoff+SCREENINSET_Y][x+xoff+SCREENINSET_X] = color;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
cacheDoubleWidePixel(x>>1, y, color);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// "DoubleWide" means "please double the X because I'm in low-res
|
||||
// width mode".
|
||||
void TeensyDisplay::cacheDoubleWidePixel(uint16_t x, uint16_t y, uint8_t color)
|
||||
{
|
||||
uint16_t color16;
|
||||
color16 = loresPixelColors[(( color & 0x0F ) )];
|
||||
|
||||
for (int yoff=0; yoff<TEENSYDISPLAY_SCALE; yoff++) {
|
||||
for (int xoff=0; xoff<TEENSYDISPLAY_SCALE; xoff++) {
|
||||
dmaBuffer[(y*TEENSYDISPLAY_SCALE+yoff+SCREENINSET_Y)][x*TEENSYDISPLAY_SCALE+xoff+SCREENINSET_X] = color16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This exists for 4bpp optimization. We could totally call
|
||||
// cacheDoubleWidePixel twice, but the (x&1) pfutzing is messy if
|
||||
// we're just storing both halves anyway...
|
||||
void TeensyDisplay::cache2DoubleWidePixels(uint16_t x, uint16_t y,
|
||||
uint8_t colorA, uint8_t colorB)
|
||||
{
|
||||
for (int yoff=0; yoff<TEENSYDISPLAY_SCALE; yoff++) {
|
||||
for (int xoff=0; xoff<TEENSYDISPLAY_SCALE; xoff++) {
|
||||
dmaBuffer[(y*TEENSYDISPLAY_SCALE+yoff+SCREENINSET_Y)][x*TEENSYDISPLAY_SCALE+2*xoff+SCREENINSET_X] = loresPixelColors[colorA];
|
||||
dmaBuffer[(y*TEENSYDISPLAY_SCALE+yoff+SCREENINSET_Y)][x*TEENSYDISPLAY_SCALE+1+2*xoff+SCREENINSET_X] = loresPixelColors[colorB];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline double logfn(double x)
|
||||
{
|
||||
// At a value of x=255, log(base 1.022)(x) is 254.636.
|
||||
return log(x)/log(1.022);
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t TeensyDisplay::frameCount()
|
||||
{
|
||||
return tft.frameCount();
|
||||
|
@ -8,6 +8,10 @@
|
||||
|
||||
class BIOS;
|
||||
|
||||
#define TEENSYDISPLAY_SCALE 1
|
||||
#define TEENSYDISPLAY_WIDTH (320*TEENSYDISPLAY_SCALE)
|
||||
#define TEENSYDISPLAY_HEIGHT (240*TEENSYDISPLAY_SCALE)
|
||||
|
||||
class TeensyDisplay : public PhysicalDisplay {
|
||||
friend class BIOS;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user