Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: YATTT sd_map_test cPong SnowDemo ... more
PokittoLib
Library for programming Pokitto hardware
How to Use
- Import this library to online compiler (see button "import" on the right hand side
- DO NOT import mbed-src anymore, a better version is now included inside PokittoLib
- Change My_settings.h according to your project
- Start coding!
Revision 64:1d52d8287c39, committed 2019-03-23
- Comitter:
- Pokitto
- Date:
- Sat Mar 23 19:19:23 2019 +0000
- Parent:
- 60:8b6a110feeea
- Commit message:
- Mode 15 support added
Changed in this revision
--- a/POKITTO_CORE/PokittoDisplay.cpp Sun Oct 07 10:19:52 2018 +0000
+++ b/POKITTO_CORE/PokittoDisplay.cpp Sat Mar 23 19:19:23 2019 +0000
@@ -71,6 +71,7 @@
#include "PokittoSound.h"
#include <stdio.h>
#include <string.h>
+#include <ctype.h>
#ifdef DISABLEAVRMIN
#include <algorithm>
using std::min;
@@ -92,8 +93,6 @@
using namespace Pokitto;
-
-
uint8_t* Display::m_scrbuf;
uint8_t* Display::m_tileset;
uint8_t* Display::m_tilebuf;
@@ -124,7 +123,7 @@
const unsigned char* Display::font;
int8_t Display::adjustCharStep = 1;
int8_t Display::adjustLineStep = 1;
-bool Display::fixedWidthFont = false;
+bool Display::fixedWidthFont = false, Display::flipFontVertical = false;
/** drawing canvas **/
//uint8_t* Display::canvas; // points to the active buffer. if null, draw direct to screen
@@ -139,7 +138,7 @@
#elif (POK_SCREENMODE == MODE_HI_4COLOR)
uint8_t Display::width = POK_LCD_W;
uint8_t Display::height = POK_LCD_H;
- uint8_t __attribute__((section (".bss"))) Display::screenbuffer[((POK_LCD_H)*POK_LCD_W)/4]; // maximum resolution
+ uint8_t __attribute__((section (".bss"))) __attribute__ ((aligned)) Display::screenbuffer[((POK_LCD_H)*POK_LCD_W)/4]; // maximum resolution
#elif (POK_SCREENMODE == MODE_FAST_16COLOR)
uint8_t Display::width = POK_LCD_W/2;
uint8_t Display::height = POK_LCD_H/2;
@@ -164,10 +163,19 @@
uint8_t Display::width = 110;
uint8_t Display::height = 88;
uint8_t Display::screenbuffer[110*88]; // 8bit 110x88
+#elif (POK_SCREENMODE == MIXMODE)
+ uint8_t Display::width = 110;
+ uint8_t Display::height = 88;
+ uint8_t Display::screenbuffer[110*88]; // 8bit 110x88 or 4bit 110x176
+ uint8_t Display::scanType[88]; // scanline bit depth indicator
+#elif (POK_SCREENMODE == MODE64)
+ uint8_t Display::width = 110;
+ uint8_t Display::height = 176;
+ uint8_t __attribute__ ((aligned)) Display::screenbuffer[110*176]; // 8bit 110x176
#elif (POK_SCREENMODE == MODE15)
uint8_t Display::width = 220;
uint8_t Display::height = 176;
- uint8_t Display::screenbuffer[0x4BA0];
+ uint8_t __attribute__ ((aligned)) Display::screenbuffer[0x4BA0];
#else
uint8_t Display::width = 84;
uint8_t Display::height = 48;
@@ -206,7 +214,7 @@
#endif // POK_GAMEBUINO_SUPPORT
// Reset sprites
- m_tilecolorbuf = NULL; //!!HV
+ m_tilecolorbuf = NULL;
for (uint8_t s = 0; s < SPRITE_COUNT; s++) m_sprites[s].bitmapData = NULL;
}
@@ -289,6 +297,14 @@
lcdRefreshMode13(m_scrbuf, paletteptr, palOffset);
#endif
+ #if POK_SCREENMODE == MIXMODE
+ lcdRefreshMixMode(m_scrbuf, paletteptr, scanType);
+ #endif
+
+ #if POK_SCREENMODE == MODE64
+ lcdRefreshMode64(m_scrbuf, paletteptr);
+ #endif
+
#if POK_SCREENMODE == MODE_GAMEBOY
lcdRefreshModeGBC(m_scrbuf, paletteptr);
#endif
@@ -352,7 +368,9 @@
directcolor = COLOR_WHITE;
invisiblecolor = COLOR_BLACK;
directbgcolor = 0x0001; // Cannot be black as that is transparent color
- if (POK_SCREENMODE == MODE_FAST_16COLOR )
+ if (POK_SCREENMODE == MODE_FAST_16COLOR ||
+ POK_SCREENMODE == MODE13
+ )
directtextrotated = false;
else
directtextrotated = true;
@@ -484,39 +502,92 @@
// GLCD fonts are arranged LSB = topmost pixel of char, so its easy to just shift through the column
uint16_t bitcolumn; //16 bits for 2x8 bit high characters
+ if( fontSize != 2 ) fontSize = 1;
+
+ void (*drawPixelFG)(int16_t,int16_t, uint8_t) = &Display::drawPixelNOP;
+ void (*drawPixelBG)(int16_t,int16_t, uint8_t) = &Display::drawPixelNOP;
+ if( x>=0 && y >= 0 && x+w*fontSize<width && y+(h+1)*fontSize<height ){
+ if( color != invisiblecolor )
+ drawPixelFG = &Display::drawPixelRaw;
+ if( bgcolor != invisiblecolor )
+ drawPixelBG = &Display::drawPixelRaw;
+ }else{
+ if( color != invisiblecolor )
+ drawPixelFG = &Display::drawPixel;
+ if( bgcolor != invisiblecolor )
+ drawPixelBG = &Display::drawPixel;
+ }
+
+ void (*drawPixel[])(int16_t,int16_t, uint8_t) = {drawPixelBG, drawPixelFG};
+ uint8_t colors[] = {bgcolor, color};
+
+#if PROJ_ARDUBOY > 0
+#else
+ if( fontSize != 2 ){
+#endif
+
+ for (i = 0; i < numBytes; i++) {
+ bitcolumn = *bitmap++;
+ if (hbytes == 2) bitcolumn |= (*bitmap++)<<8; // add second byte for 16 bit high fonts
+ for (j = 0; j <= h; j++) { // was j<=h
+ uint8_t c = colors[ bitcolumn & 1 ];
+
+#if PROJ_ARDUBOY > 0
+ drawPixel[ bitcolumn&1 ](x, y + 7 - j,c);
+#elif PROJ_SUPPORT_FONTROTATION > 0
+ // if font flipping & rotation is allowed - do not slow down old programs!
+ if (flipFontVertical) {
+ drawPixel[ bitcolumn&1 ](x, y + h - j,c);
+ } else {
+ drawPixel[ bitcolumn&1 ](x, y + j,c);
+ }
+#else
+ // "Normal" case
+ drawPixel[ bitcolumn&1 ](x, y + j,c);
+#endif // PROJ_ARDUBOY
+ bitcolumn>>=1;
+
+ }
+#if PROJ_SUPPORT_FONTROTATION > 0
+ if (flipFontVertical) x--;
+ else x++;
+#else
+ x++;
+#endif
+ }
+
+#if PROJ_SUPPORT_FONTROTATION > 0
+ if (flipFontVertical) return -numBytes-adjustCharStep;
+ else return numBytes+adjustCharStep; // for character stepping
+#else
+ return numBytes+adjustCharStep;
+#endif
+
+
+#if PROJ_ARDUBOY > 0
+#else
+ }else{
+
for (i = 0; i < numBytes; i++) {
- bitcolumn = *bitmap++;
- if (hbytes == 2) bitcolumn |= (*bitmap++)<<8; // add second byte for 16 bit high fonts
- for (j = 0; j <= h; j++) { // was j<=h
- #if PROJ_ARDUBOY > 0
- if (bitcolumn&0x1) {
- drawPixel(x + i, y + 7 - j,color);
- } else drawPixel(x + i, y + 7 - j,bgcolor);
- bitcolumn>>=1;
- #else
- if (fontSize==2) {
- if (bitcolumn&0x1) {
- drawPixel(x + (i<<1) , y + (j<<1),color);
- drawPixel(x + (i<<1)+1, y + (j<<1),color);
- drawPixel(x + (i<<1) , y + (j<<1)+1,color);
- drawPixel(x + (i<<1)+1, y + (j<<1)+1,color);
- } else {
- drawPixel(x + (i<<1) , y + (j<<1),bgcolor);
- drawPixel(x + (i<<1)+1, y + (j<<1),bgcolor);
- drawPixel(x + (i<<1) , y + (j<<1)+1,bgcolor);
- drawPixel(x + (i<<1)+1, y + (j<<1)+1,bgcolor);
- }
- } else {
- if (bitcolumn&0x1) drawPixel(x + i, y + j,color);
- else drawPixel(x + i, y + j,bgcolor);
- }
- bitcolumn>>=1;
- #endif // PROJ_ARDUBOY
+ bitcolumn = *bitmap++;
+ if (hbytes == 2) bitcolumn |= (*bitmap++)<<8; // add second byte for 16 bit high fonts
+ for (j = 0; j <= h; j++) { // was j<=h
+ uint8_t c = colors[ bitcolumn & 1 ];
- }
+ drawPixel[ bitcolumn&1 ](x + (i<<1) , y + (j<<1), c);
+ drawPixel[ bitcolumn&1 ](x + (i<<1)+1, y + (j<<1), c);
+ drawPixel[ bitcolumn&1 ](x + (i<<1) , y + (j<<1)+1, c);
+ drawPixel[ bitcolumn&1 ](x + (i<<1)+1, y + (j<<1)+1, c);
+ bitcolumn>>=1;
+
+ }
+ }
+
+ return (numBytes+adjustCharStep)<<1;
+
}
- if (fontSize==2) return (numBytes+adjustCharStep)<<1;
- return numBytes+adjustCharStep; // for character stepping
+#endif // PROJ_ARDUBOY
+
}
void Display::clear() {
@@ -532,13 +603,13 @@
uint16_t j = POK_BITFRAME;
if (bgcolor & 0x1) memset((void*)m_scrbuf,0xFF,j);// R
else memset((void*)m_scrbuf,0x00,j);// R
- if ((bgcolor>>1) & 0x1) memset((void*)((uint8_t*)m_scrbuf+POK_BITFRAME),0xFF,j);// G
- else memset((void*)((uint8_t*)m_scrbuf+POK_BITFRAME),0x00,j);// G
- if ((bgcolor>>2) & 0x1) memset((void*)((uint8_t*)m_scrbuf+POK_BITFRAME*2),0xFF,j);// B
- else memset((void*)((uint8_t*)m_scrbuf+POK_BITFRAME*2),0x00,j);// B
+ if ((bgcolor>>1) & 0x1) memset((char*)m_scrbuf+POK_BITFRAME,0xFF,j);// G
+ else memset((char*)m_scrbuf+POK_BITFRAME,0x00,j);// G
+ if ((bgcolor>>2) & 0x1) memset((char*)m_scrbuf+POK_BITFRAME*2,0xFF,j);// B
+ else memset((char*)m_scrbuf+POK_BITFRAME*2,0x00,j);// B
setCursor(0,0);
return;
- } else {
+ } else if (bpp==4) {
c = (c & 0x0F) | (c << 4);
}
uint16_t j = sizeof(screenbuffer);
@@ -621,12 +692,10 @@
clipX = x; clipY = y; clipW = w; clipH = h;
}
+void Display::drawPixelNOP(int16_t x,int16_t y, uint8_t col) {
+}
-void Display::drawPixel(int16_t x,int16_t y, uint8_t col) {
- if (col==invisiblecolor) return; // do not draw transparent pixels
- if ((uint16_t)x >= width || (uint16_t)y >= height) return;
- col &= (PALETTE_SIZE-1);
-
+void Display::drawPixelRaw(int16_t x,int16_t y, uint8_t col) {
#if POK_COLORDEPTH == 8
m_scrbuf[x+width*y] = col;
#endif
@@ -689,75 +758,16 @@
#endif // POK_GAMEBUINO_SUPPORT
}
+void Display::drawPixel(int16_t x,int16_t y, uint8_t col) {
+ if (col==invisiblecolor) return; // do not draw transparent pixels
+ if ((uint16_t)x >= width || (uint16_t)y >= height) return;
+ col &= (PALETTE_SIZE-1);
+ drawPixelRaw( x, y, col );
+}
+
void Display::drawPixel(int16_t x,int16_t y) {
if ((uint16_t)x >= width || (uint16_t)y >= height) return;
-
- #if POK_COLORDEPTH == 8
- m_scrbuf[x+width*y] = color;
- #endif
-
- #if POK_GAMEBUINO_SUPPORT > 0
-
- uint8_t c = color;
- uint8_t ct = color;
- if(ct == INVERT){
- ct = !getPixel(x, y); //jonne - was c = !getP...
- }
-
- uint16_t bitptr=0;
- for (uint8_t cbit=0;cbit<POK_COLORDEPTH;cbit++) {
- c = ct & 1; // take the lowest bit of the color index number
- if(c == 0){ //white - or actually "Clear bit"
- #if DISPLAY_ROT == NOROT
- m_scrbuf[x + (y / 8) * LCDWIDTH + bitptr] &= ~_BV(y % 8);
- #elif DISPLAY_ROT == ROTCCW
- m_scrbuf[LCDHEIGHT - y - 1 + (x / 8) * LCDWIDTH_NOROT + bitptr] &= ~_BV(x % 8);
- #elif DISPLAY_ROT == ROT180
- m_scrbuf[LCDWIDTH - x - 1 + ((LCDHEIGHT - y - 1) / 8) * LCDWIDTH_NOROT + bitptr] &= ~_BV((LCDHEIGHT - y - 1) % 8);
- #elif DISPLAY_ROT == ROTCW
- m_scrbuf[y + ((LCDWIDTH - x - 1) / 8) * LCDWIDTH_NOROT + bitbtr] &= ~_BV((LCDWIDTH - x - 1) % 8);
- #endif
- //return; //jonne
- } else { //black - or actually "Set bit"
- #if DISPLAY_ROT == NOROT
- m_scrbuf[x + (y / 8) * LCDWIDTH + bitptr] |= _BV(y % 8);
- #elif DISPLAY_ROT == ROTCCW
- m_scrbuf[LCDHEIGHT - y - 1 + (x / 8) * LCDWIDTH_NOROT + bitptr] |= _BV(x % 8);
- #elif DISPLAY_ROT == ROT180
- m_scrbuf[LCDWIDTH - x - 1 + ((LCDHEIGHT - y - 1) / 8) * LCDWIDTH_NOROT + bitptr] |= _BV((LCDHEIGHT - y - 1) % 8);
- #elif DISPLAY_ROT == ROTCW
- m_scrbuf[y + ((LCDWIDTH - x - 1) / 8) * LCDWIDTH_NOROT + bitptr] |= _BV((LCDWIDTH - x -1) % 8);
- #endif
- //return; //jonne
- }
- ct >>=1; // shift to get next bit
- bitptr += POK_BITFRAME; // move one screen worth of buffer forward to get to the next color bit
- } // POK_COLOURDEPTH
-
- #else
-
- /** NOT Gamebuino */
- #if POK_COLORDEPTH == 1
- if (color) {m_scrbuf[(y >> 3) * width + x] |= (0x80 >> (y & 7)); return;}
- m_scrbuf[(y >> 3) * width + x] &= ~(0x80 >> (y & 7));
- #elif POK_COLORDEPTH == 2
- uint16_t i = y*(width>>2) + (x>>2);
- uint8_t pixel = m_scrbuf[i];
- uint8_t column = x&0x03;
- if (column==3) pixel = (pixel&0xFC)|(color); // bits 0-1
- else if (column==2) pixel = (pixel&0xF3)|(color<<2); // bits 2-3
- else if (column==1) pixel = (pixel&0xCF)|(color<<4); // bits 4-5
- else pixel = (pixel&0x3F)|(color<<6); // bits 6-7
- m_scrbuf[i] = pixel;
- #elif POK_COLORDEPTH == 3
- #elif POK_COLORDEPTH == 4
- uint16_t i = y*(width>>1) + (x>>1);
- uint8_t pixel = m_scrbuf[i];
- if (x&1) pixel = (pixel&0xF0)|(color);
- else pixel = (pixel&0x0F) | (color<<4);
- m_scrbuf[i] = pixel;
- #endif // POK_COLORDEPTH
- #endif // POK_GAMEBUINO_SUPPORT
+ drawPixelRaw( x, y, color );
}
uint8_t Display::getPixel(int16_t x,int16_t y) {
@@ -1496,6 +1506,7 @@
int16_t bitFrame = w * h / 8;
for (i = 0; i < w; i++) {
byteNum = i / 8;
+ //bitNum = i % 8;
uint8_t bitcount=0;
for (j = 0; j <= h/8; j++) {
@@ -1518,7 +1529,8 @@
else if (m_colordepth==4) {
/** 4bpp fast version */
- int16_t scrx,scry,xclip,xjump,scrxjump;
+ int16_t scrx,scry,xjump,scrxjump;
+ int16_t xclip;
xclip=xjump=scrxjump=0;
/** y clipping */
if (y<0) { h+=y; bitmap -= y*(w>>1); y=0;}
@@ -1555,8 +1567,9 @@
uint8_t sourcepixel = *bitmap;
if ((sourcepixel&0x0F) != invisiblecolor) {
sourcepixel <<=4;
- uint8_t targetpixel = *scrptr;// & 0x0F;
- targetpixel |= sourcepixel;
+ volatile uint8_t targetpixel = *scrptr;// & 0x0F;
+ targetpixel &= 0xF; //clear upper nibble
+ targetpixel |= sourcepixel; //now OR it
*scrptr = targetpixel;
}
//scrptr++;
@@ -1566,9 +1579,11 @@
}
bitmap += xjump; // needed if x<0 clipping occurs
} else { /** ODD pixel starting line **/
+ uint8_t sourcepixel;
+ uint8_t targetpixel;
for (scrx = x; scrx < w+x-xclip; scrx+=2) {
- uint8_t sourcepixel = *bitmap;
- uint8_t targetpixel = *scrptr;
+ sourcepixel = *bitmap;
+ targetpixel = *scrptr;
// store higher nibble of source pixel in lower nibble of target
if((sourcepixel>>4)!=invisiblecolor) targetpixel = (targetpixel & 0xF0) | (sourcepixel >> 4 );
*scrptr = targetpixel;
@@ -1579,6 +1594,12 @@
*scrptr = targetpixel;
bitmap++;
}
+ if (xclip) {
+ // last line, store higher nibble of last source pixel in lower nibble of last address
+ sourcepixel = *bitmap >> 4;
+ if(sourcepixel!=invisiblecolor) targetpixel = (targetpixel & 0xF0) | sourcepixel;
+ *scrptr = targetpixel;
+ }
bitmap+=xjump;
}
// increment the y jump in the scrptr
@@ -1591,16 +1612,15 @@
/** 4bpp fast version */
if (m_colordepth==8) {
- int16_t scrx,scry,xjump,scrxjump;
- xjump=scrxjump=0;
+ int16_t scrx,scry;//,scrxjump;
+ int16_t xjump=0;
/** y clipping */
if (y<0) { h+=y; bitmap -= y*w; y=0;}
else if (y+h>height) { h -=(y-height);}
/** x clipping */
if (x<0) { w+=x; xjump = (-x); bitmap += xjump; x=0;}
else if (x+w>width) {
- scrxjump = x;
- xjump=(x+w-width)+scrxjump;
+ xjump=(x+w-width);
w = width-x;}
uint8_t* scrptr = m_scrbuf + (y*width + x);
@@ -1614,8 +1634,8 @@
bitmap++;
scrptr++;
}
- bitmap += xjump; // needed if x<0 clipping occurs
- scrptr = scrptr + (width - w)+scrxjump;
+ bitmap += xjump; // needed if horizontal clipping occurs
+ scrptr = scrptr + (width - w);
}
return;
}
@@ -1779,83 +1799,105 @@
} // end for scry
}
-void Display::drawBitmapXFlipped(int16_t x, int16_t y, const uint8_t* bitmap)
+void Display::drawBitmapDataXFlipped(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t* bitmap)
{
- int16_t w = *bitmap;
- int16_t h = *(bitmap + 1);
- bitmap = bitmap + 2; //add an offset to the pointer to start after the width and height
/** visibility check */
if (y<-h || y>height) return; //invisible
if (x<-w || x>width) return; //invisible
/** 1 bpp mode */
- if (m_colordepth<2) {
- int16_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
- for (i = 0; i < w; i++) {
- byteNum = i / 8;
- bitNum = i % 8;
- for (j = 0; j < h; j++) {
- uint8_t source = *(bitmap + j * byteWidth + byteNum);
- if (source & (0x80 >> bitNum)) {
- drawPixel(x + w - i, y + j);
+ if (m_colordepth<2)
+ {
+ int16_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
+ for (i = 0; i < w; i++)
+ {
+ byteNum = i / 8;
+ bitNum = i % 8;
+ for (j = 0; j < h; j++)
+ {
+ uint8_t source = *(bitmap + j * byteWidth + byteNum);
+ if (source & (0x80 >> bitNum))
+ {
+ drawPixel(x + w - i, y + j);
+ }
}
}
- }
- return;
+ return;
}
/** 2 bpp mode */
- if (m_colordepth<4) {
- int16_t i, j, byteNum, bitNum, byteWidth = w >> 2;
- for (i = 0; i < w; i++) {
- byteNum = i / 4;
- bitNum = (i % 4)<<1;
- for (j = 0; j < h; j++) {
- uint8_t source = *(bitmap + j * byteWidth + byteNum);
- uint8_t output = (source & (0xC0 >> bitNum));
- output >>= (6-bitNum);
- if (output != invisiblecolor) {
- setColor(output);
- drawPixel(x + i, y + j);
+ else if (m_colordepth==2)
+ {
+ int16_t i, j, byteNum, bitNum, byteWidth = w >> 2;
+ for (i = 0; i < w; i++)
+ {
+ byteNum = i / 4;
+ bitNum = (i % 4)<<1;
+ for (j = 0; j < h; j++)
+ {
+ uint8_t source = *(bitmap + j * byteWidth + byteNum);
+ uint8_t output = (source & (0xC0 >> bitNum));
+ output >>= (6-bitNum);
+ if (output != invisiblecolor)
+ {
+ setColor(output);
+ drawPixel(x + i, y + j);
+ }
}
}
- }
- return;
+ return;
}
- /** 4bpp fast version */
- int16_t scrx,scry,xclip,xjump,scrxjump;
- xclip=xjump=scrxjump=0;
- /** y clipping */
- if (y<0) { h+=y; bitmap -= y*(w>>1); y=0;}
- else if (y+h>height) { h -=(y-height);}
- /** x clipping */
- bitmap += ((w>>1)-1); //inverted!
- if (x<0) {
+ else if (m_colordepth==4)
+ {
+ /** 4bpp fast version */
+ int16_t scrx,scry,xclip,xjump,scrxjump;
+ xclip=xjump=scrxjump=0;
+ /** y clipping */
+ if (y<0)
+ {
+ h+=y;
+ bitmap -= y*(w>>1);
+ y=0;
+ }
+ else if (y+h>height)
+ {
+ h -=(y-height);
+ }
+ /** x clipping */
+ bitmap += ((w>>1)-1); //inverted!
+ if (x<0)
+ {
xclip=(x&1)<<1;
w+=x;
xjump = ((-x)>>1);
//bitmap += xjump; // do not clip left edge of source, as bitmap is inverted !
x=0;
- }
- else if (x+w>width) {
+ }
+ else if (x+w>width)
+ {
xclip = (x&1)<<1;
scrxjump = x&1;
xjump=((x+w-width)>>1)+scrxjump;
- w = width-x;}
+ w = width-x;
+ }
- //uint8_t* scrptr = m_scrbuf + (y*(width>>1) + ((x+width)>>1));
- uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1));
- /** ONLY 4-bit mode for time being **/
- for (scry = y; scry < y+h; scry+=1) {
- // for (scry = y; scry < y+2; scry+=1) {
+ //uint8_t* scrptr = m_scrbuf + (y*(width>>1) + ((x+width)>>1));
+ uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1));
+ /** ONLY 4-bit mode for time being **/
+ for (scry = y; scry < y+h; scry+=1)
+ {
+ // for (scry = y; scry < y+2; scry+=1) {
if (scry>=height) return;
- if ((x&1)==0) { /** EVEN pixel starting line, very simple, just copypaste **/
+ if ((x&1)==0) /** EVEN pixel starting line, very simple, just copypaste **/
+ {
//for (scrx = w+x-xclip-1; scrx >= x; scrx-=2) {
- for (scrx = x; scrx < w+x-xclip; scrx+=2) {
+ for (scrx = x; scrx < w+x-xclip; scrx+=2)
+ {
uint8_t sourcepixel = *(bitmap);
- if (xclip) {
- sourcepixel <<=4;
- sourcepixel |= ((*(bitmap-1))>>4);//inverted!
+ if (xclip)
+ {
+ sourcepixel <<=4;
+ sourcepixel |= ((*(bitmap-1))>>4);//inverted!
}
uint8_t targetpixel = *scrptr;
// NIBBLES ARE INVERTED BECAUSE PICTURE IS FLIPPED !!!
@@ -1866,11 +1908,14 @@
scrptr++;
}
bitmap += w; // w*2 >> 1 because inverted and because 2 pixels per byte!!
- if (xclip){
- if (w&1) {
+ if (xclip)
+ {
+ if (w&1)
+ {
/**last pixel is odd pixel due to clipping & odd width*/
uint8_t sourcepixel = *bitmap;
- if ((sourcepixel&0x0F) != invisiblecolor) {
+ if ((sourcepixel&0x0F) != invisiblecolor)
+ {
sourcepixel <<=4;
uint8_t targetpixel = *scrptr;// & 0x0F;
targetpixel |= sourcepixel;
@@ -1882,8 +1927,11 @@
scrptr++;
}
bitmap += xjump; // needed if x<0 clipping occurs
- } else { /** ODD pixel starting line **/
- for (scrx = x; scrx < w+x-xclip; scrx+=2 ) {
+ }
+ else /** ODD pixel starting line **/
+ {
+ for (scrx = x; scrx < w+x-xclip; scrx+=2 )
+ {
uint8_t sourcepixel = *bitmap;
uint8_t targetpixel = *scrptr;
// inverted !!! store lower nibble of source pixel in lower nibble of target
@@ -1901,7 +1949,62 @@
}
// increment the y jump in the scrptr
scrptr = scrptr + ((width - w)>>1)+scrxjump;
+ }
}
+ /** 8 bpp mode */
+ else if (m_colordepth==8)
+ {
+ int16_t scrx,scry;//,scrxjump;
+ int16_t xjump=0;
+ /** y clipping */
+ if (y<0)
+ {
+ h+=y;
+ bitmap -= y*w;
+ y=0;
+ }
+ else if (y+h>height)
+ {
+ h -=(y-height);
+ }
+ /** x clipping */
+ if (x<0)
+ {
+ w+=x;
+ xjump = (-x);
+ bitmap += xjump;
+ x=0;
+ }
+ else if (x+w>width)
+ {
+ xjump=(x+w-width);
+ w = width-x;
+ }
+
+ uint8_t* scrptr = m_scrbuf + (y*width + x) + w;
+ for (scry = y; scry < y+h; scry+=1)
+ {
+ if (scry>=height) return;
+ for (scrx = x; scrx < w+x; scrx++)
+ {
+ uint8_t sourcepixel = *bitmap;
+ uint8_t targetpixel = *scrptr;
+ if (sourcepixel != invisiblecolor )
+ targetpixel = sourcepixel;
+ *scrptr = targetpixel;
+ bitmap++;
+ scrptr--;
+ }
+ bitmap += xjump; // needed if horizontal clipping occurs
+ scrptr = scrptr + (width + w);
+ }
+ return;
+ }
+}
+
+void Display::drawBitmapXFlipped(int16_t x, int16_t y, const uint8_t* bitmap)
+{
+ drawBitmapDataXFlipped(x, y, bitmap[0], bitmap[1], bitmap + 2);
}
void Display::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t rotation, uint8_t flip) {
@@ -2338,6 +2441,7 @@
}
}
+
void Display::draw4BitColumn(int16_t x, int16_t y, uint8_t h, uint8_t* bitmap)
{
int8_t scry;
@@ -2441,6 +2545,14 @@
lcdRefreshMode13(m_scrbuf, paletteptr, palOffset);
#endif
+#if POK_SCREENMODE == MIXMODE
+ lcdRefreshMixMode(m_scrbuf, paletteptr, scanType);
+#endif
+
+#if POK_SCREENMODE == MODE64
+ lcdRefreshMode64(m_scrbuf, paletteptr);
+#endif
+
#if POK_SCREENMODE == MODE_GAMEBOY
lcdRefreshModeGBC(scr, paletteptr);
#endif
@@ -2476,6 +2588,8 @@
m_tilebuf[i]=t;
};
+
+
// Convert an integer to a hexadecimal string
char* itoa_hex(int num, char* dest, int destLen) {
int i = destLen-1;
@@ -2489,6 +2603,7 @@
}
// Draw the crash screen and wait forever
+#define STR_TO_UPPER(str_from, str_to) for( int32_t i=0; i <= strlen(str_from); i++ ) str_to[i] = toupper(str_from[i]);
void ShowCrashScreenAndWait( const char* texLine1, const char* texLine2, const char* texLine3, const char* texLine4, const char* texLine5 ) {
// draw screen red
@@ -2505,15 +2620,17 @@
Display::fixedWidthFont = true; // Needed for the non-proportional C64 font (default value=false)
Display::enableDirectPrinting(true);
+ char convertedStr[128] = {0};
+
// Draw texts
int yOffsetInPixels = 5;
Display::set_cursor(0, 9 + yOffsetInPixels);
- Display::print(" "); Display::println(texLine1);
- Display::print(" "); Display::println(texLine2);
- Display::print(" "); Display::println(texLine3);
+ Display::print(" "); STR_TO_UPPER(texLine1, convertedStr); Display::println(convertedStr);
+ Display::print(" "); STR_TO_UPPER(texLine2, convertedStr); Display::println(convertedStr);
+ Display::print(" "); STR_TO_UPPER(texLine3, convertedStr); Display::println(convertedStr);
Display::println();
- Display::print(" *"); Display::println(texLine4);
- Display::print(" *"); Display::println(texLine5);
+ Display::print(" *"); STR_TO_UPPER(texLine4, convertedStr); Display::println(convertedStr);
+ Display::print(" *"); STR_TO_UPPER(texLine5, convertedStr); Display::println(convertedStr);
Display::set_cursor(0, 0 + yOffsetInPixels);
--- a/POKITTO_CORE/PokittoDisplay.h Sun Oct 07 10:19:52 2018 +0000
+++ b/POKITTO_CORE/PokittoDisplay.h Sat Mar 23 19:19:23 2019 +0000
@@ -141,12 +141,14 @@
private:
static uint8_t* canvas;
static uint8_t bpp;
- static uint8_t m_colordepth;
public:
+ static uint8_t m_colordepth; // public to be used elsewhere
+ static uint8_t subMode; // for mixed mode switching
static uint8_t palOffset;
static uint8_t width;
static uint8_t height;
static uint8_t screenbuffer[];
+ static uint8_t scanType[]; // for mixed screen mode
// PROPERTIES
static void setColorDepth(uint8_t);
@@ -312,6 +314,8 @@
static void drawRleBitmap(int16_t x, int16_t y, const uint8_t* bitmap);
/** Draw animated bitmap frame */
static void drawBitmap(int16_t x, int16_t y, const uint8_t* bitmap, uint8_t frame);
+ /** Draw bitmap data flipped on x-axis*/
+ static void drawBitmapDataXFlipped(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t* bitmap);
/** Draw bitmap flipped on x-axis*/
static void drawBitmapXFlipped(int16_t x, int16_t y, const uint8_t* bitmap);
/** Draw bitmap with options */
@@ -391,7 +395,7 @@
static int16_t cursorX,cursorY;
static uint8_t fontSize;
static int8_t adjustCharStep, adjustLineStep;
- static bool fixedWidthFont;
+ static bool fixedWidthFont, flipFontVertical;
static void inc_txtline();
static void printNumber(unsigned long, uint8_t);
--- a/POKITTO_HW/HWLCD.cpp Sun Oct 07 10:19:52 2018 +0000
+++ b/POKITTO_HW/HWLCD.cpp Sat Mar 23 19:19:23 2019 +0000
@@ -453,11 +453,132 @@
* @param updRectH The update rect.
* @param paletteptr The screen palette.
*/
+
+
+#define MODE1_LOOP \
+ " adds %[t], %[palette]" "\n" \
+ " ldm %[t], {%[t], %[x]}" "\n" \
+ " str %[t], [%[LCD], 0]" "\n" \
+ " movs %[t], 252" "\n" \
+ " str %[WRBit], [%[LCD], %[t]]" "\n" \
+ " str %[WRBit], [%[LCD], 124]" "\n" \
+ " str %[x], [%[LCD], 0]" "\n" \
+ " str %[WRBit], [%[LCD], %[t]]" "\n" \
+ " movs %[t], 0x0F" "\n" \
+ " ands %[t], %[t], %[c]" "\n" \
+ " str %[WRBit], [%[LCD], 124]" "\n" \
+ \
+ " lsls %[t], 3" "\n" \
+ " adds %[t], %[palette]" "\n" \
+ " ldm %[t], {%[t], %[x]}" "\n" \
+ " str %[t], [%[LCD], 0]" "\n" \
+ " movs %[t], 252" "\n" \
+ " str %[WRBit], [%[LCD], %[t]]" "\n" \
+ " str %[WRBit], [%[LCD], 124]" "\n" \
+ " str %[x], [%[LCD], 0]" "\n" \
+ " str %[WRBit], [%[LCD], %[t]]" "\n" \
+ " lsrs %[c], 8" "\n" \
+ " movs %[t], 0xF0" "\n" \
+ " ands %[t], %[t], %[c]" "\n" \
+ " lsrs %[t], %[t], 1" "\n" \
+ " str %[WRBit], [%[LCD], 124]" "\n"
+
+
void Pokitto::lcdRefreshMode1(uint8_t * scrbuf, uint8_t updRectX, uint8_t updRectY, uint8_t updRectW, uint8_t updRectH, uint16_t* paletteptr) {
- uint16_t x,y;
+
+#ifdef XPERIMENTAL
+//#define __ARMCC_VERSION 1
+#endif
+
+#ifndef __ARMCC_VERSION
+
+ write_command(0x03); write_data(0x1038);
+ write_command(0x20); // Horizontal DRAM Address
+ write_data(0);
+ write_command(0x21); // Vertical DRAM Address
+ write_data(0);
+ write_command(0x22); // write data to DRAM
+ CLR_CS_SET_CD_RD_WR;
+
+ uint8_t *end=&scrbuf[POK_SCREENBUFFERSIZE>>1]+4;
+
+ volatile uint32_t palette[32];
+ for( uint32_t i=0; i<16; ++i ){
+ palette[(i<<1)+1] = static_cast<uint32_t>(paletteptr[i&3 ]) << 3;
+ palette[(i<<1) ] = static_cast<uint32_t>(paletteptr[i>>2]) << 3;
+ }
+
+ SET_MASK_P2;
+
+ uint32_t c, WRBit = 1<<12;
+
+ register uint32_t x asm("r2");
+ register uint32_t t asm("r1");
+
+ asm volatile(
+
+ ".syntax unified" "\n"
+ "ldm %[scrbuf]!, {%[c]}" "\n" // load 4 bytes (16 pixels)
+ "movs %[t], 0xF0" "\n"
+ "ands %[t], %[t], %[c]" "\n"
+ "lsrs %[t], %[t], 1" "\n"
+ "mode1Loop%=:" "\n"
+ MODE1_LOOP
+ MODE1_LOOP
+ MODE1_LOOP
+ " adds %[t], %[palette]" "\n"
+ " ldm %[t], {%[t], %[x]}" "\n"
+ " str %[t], [%[LCD], 0]" "\n"
+ " movs %[t], 252" "\n"
+ " str %[WRBit], [%[LCD], %[t]]" "\n"
+ " str %[WRBit], [%[LCD], 124]" "\n"
+ " str %[x], [%[LCD], 0]" "\n"
+ " str %[WRBit], [%[LCD], %[t]]" "\n"
+ " movs %[t], 0x0F" "\n"
+ " ands %[t], %[t], %[c]" "\n"
+ " str %[WRBit], [%[LCD], 124]" "\n"
+
+ " lsls %[t], 3" "\n"
+ " adds %[t], %[palette]" "\n"
+ " ldm %[t], {%[t], %[x]}" "\n"
+ " str %[t], [%[LCD], 0]" "\n"
+ " movs %[t], 252" "\n"
+ " str %[WRBit], [%[LCD], %[t]]" "\n"
+ " str %[WRBit], [%[LCD], 124]" "\n"
+ " str %[x], [%[LCD], 0]" "\n"
+ " str %[WRBit], [%[LCD], %[t]]" "\n"
+
+ " ldm %[scrbuf]!, {%[c]}" "\n" // load next 4 bytes
+ " movs %[t], 0xF0" "\n"
+ " ands %[t], %[t], %[c]" "\n"
+ " lsrs %[t], %[t], 1" "\n"
+ " str %[WRBit], [%[LCD], 124]" "\n"
+
+ "cmp %[end], %[scrbuf]" "\n"
+ "bne mode1Loop%=" "\n" // if scrbuf < end, loop
+
+ : // outputs
+ [c]"+l" (c),
+ [t]"+l" (t),
+ [end]"+h" (end),
+ [scrbuf]"+l" (scrbuf),
+ [WRBit]"+l" (WRBit),
+ [x]"+l" (x)
+
+ : // inputs
+ [LCD]"l" (0xA0002188),
+ [palette]"l" (palette)
+
+ : // clobbers
+ "cc"
+ );
+
+
+#else
+ uint16_t x,y,xptr;
uint16_t scanline[4][176]; // read 4 half-nibbles = 4 pixels at a time
- uint8_t *d;
+ uint8_t *d, yoffset=0;
// If not the full screen is updated, check the validity of the update rect.
if ( updRectX != 0 || updRectY != 0 ||updRectW != LCDWIDTH ||updRectH != LCDHEIGHT ) {
@@ -477,6 +598,7 @@
xptr = 8;
setDRAMptr(8, 0);
#else
+ xptr = 0;
setDRAMptr(0, 0);
#endif
@@ -484,6 +606,7 @@
d = scrbuf+(x>>2);// point to beginning of line in data
/** find colours in one scanline **/
+ uint8_t s=0;
d += (updRectY * 220/4);
for (y=updRectY; y<updRectY+updRectH; y++) {
uint8_t tdata = *d;
@@ -555,6 +678,7 @@
}
}
}
+#endif
#ifdef POK_SIM
simulator.refreshDisplay();
@@ -945,7 +1069,7 @@
#endif
}
-
+
#define MODE2_INNER_LOOP_B \
" ldm %[scanline]!, {%[c]}" "\n" \
" str %[c], [%[LCD], 0]" "\n" \
@@ -955,98 +1079,104 @@
" str %[t], [%[LCD], 124]" "\n" \
" subs %[x], 1" "\n" \
" str %[t], [%[LCD], %[c]]" "\n" \
-
+
void Pokitto::lcdRefreshMode2(uint8_t * scrbuf, uint16_t* paletteptr ) {
- uint32_t x,y;
+ uint32_t x,y,byte,c,t=1<<12;
uint32_t scanline[110];
write_command(0x03); write_data(0x1038);
write_command(0x20); // Horizontal DRAM Address
write_data(0); // 0
write_command(0x21); // Vertical DRAM Address
- write_data(1);
+
+#ifndef __ARMCC_VERSION
+ write_data(1); // still has pixel 0 bug
write_command(0x22); // write data to DRAM
CLR_CS_SET_CD_RD_WR;
SET_MASK_P2;
-#ifndef __ARMCC_VERSION
- asm volatile(
+ #ifdef PROJ_SHOW_FPS_COUNTER
+ setDRAMptr(0, 8);
+ y=4;
+ #endif
+
+ asm volatile(
".syntax unified" "\n"
-
+
"mov r10, %[scanline]" "\n"
"mov r11, %[t]" "\n"
-
+
"mode2OuterLoop:" "\n"
-
+
"movs %[x], 110" "\n"
"mode2InnerLoopA:"
- " ldrb %[byte], [%[scrbuf],0]" "\n"
+ " ldrb %[byte], [%[scrbuf],0]" "\n"
" lsrs %[c], %[byte], 4" "\n"
" movs %[t], 15" "\n"
- " ands %[byte], %[t]" "\n"
-
- " lsls %[c], 1" "\n"
- " ldrh %[t], [%[paletteptr], %[c]]" "\n"
- " lsls %[t], %[t], 3" "\n"
- " str %[t], [%[LCD], 0]" "\n"
- " mov %[c], r11" "\n"
- " str %[c], [%[LCD], 124]" "\n"
- " stm %[scanline]!, {%[t]}" "\n"
- " movs %[t], 252" "\n"
- " str %[c], [%[LCD], %[t]]" "\n"
- " str %[c], [%[LCD], 124]" "\n"
- " lsls %[byte], %[byte], 1" "\n"
+ " ands %[byte], %[t]" "\n"
+
+ " lsls %[c], 1" "\n"
+ " ldrh %[t], [%[paletteptr], %[c]]" "\n"
+ " lsls %[t], %[t], 3" "\n"
+ " str %[t], [%[LCD], 0]" "\n"
+ " mov %[c], r11" "\n"
+ " str %[c], [%[LCD], 124]" "\n"
+ " stm %[scanline]!, {%[t]}" "\n"
+ " movs %[t], 252" "\n"
+ " str %[c], [%[LCD], %[t]]" "\n"
+ " str %[c], [%[LCD], 124]" "\n"
+ " lsls %[byte], %[byte], 1" "\n"
" str %[c], [%[LCD], %[t]]" "\n"
- " ldrh %[t], [%[paletteptr], %[byte]]" "\n"
- " lsls %[t], %[t], 3" "\n"
- " str %[t], [%[LCD], 0]" "\n"
- " mov %[c], r11" "\n"
- " str %[c], [%[LCD], 124]" "\n"
- " stm %[scanline]!, {%[t]}" "\n"
- " movs %[t], 252" "\n"
- " str %[c], [%[LCD], %[t]]" "\n"
- " str %[c], [%[LCD], 124]" "\n"
- " adds %[scrbuf], %[scrbuf], 1" "\n"
+ " ldrh %[t], [%[paletteptr], %[byte]]" "\n"
+ " lsls %[t], %[t], 3" "\n"
+ " str %[t], [%[LCD], 0]" "\n"
+ " mov %[c], r11" "\n"
+ " str %[c], [%[LCD], 124]" "\n"
+ " stm %[scanline]!, {%[t]}" "\n"
+ " movs %[t], 252" "\n"
" str %[c], [%[LCD], %[t]]" "\n"
-
- " subs %[x], 2" "\n"
+ " str %[c], [%[LCD], 124]" "\n"
+ " adds %[scrbuf], %[scrbuf], 1" "\n"
+ " str %[c], [%[LCD], %[t]]" "\n"
+
+ " subs %[x], 2" "\n"
" bne mode2InnerLoopA" "\n"
"mov %[scanline], r10" "\n"
"movs %[x], 110" "\n"
"mov %[t], r11" "\n"
"mode2InnerLoopB:"
- MODE2_INNER_LOOP_B
- MODE2_INNER_LOOP_B
- MODE2_INNER_LOOP_B
- MODE2_INNER_LOOP_B
- MODE2_INNER_LOOP_B
- MODE2_INNER_LOOP_B
- MODE2_INNER_LOOP_B
- MODE2_INNER_LOOP_B
- MODE2_INNER_LOOP_B
- MODE2_INNER_LOOP_B
+ MODE2_INNER_LOOP_B
+ MODE2_INNER_LOOP_B
+ MODE2_INNER_LOOP_B
+ MODE2_INNER_LOOP_B
+ MODE2_INNER_LOOP_B
+ MODE2_INNER_LOOP_B
+ MODE2_INNER_LOOP_B
+ MODE2_INNER_LOOP_B
+ MODE2_INNER_LOOP_B
+ MODE2_INNER_LOOP_B
" bne mode2InnerLoopB" "\n"
-
+
"mov %[scanline], r10" "\n"
"movs %[t], 1" "\n"
"movs %[c], 88" "\n"
"add %[y], %[t]" "\n" // y++... derpy, but it's the outer loop
"cmp %[y], %[c]" "\n"
"bne mode2OuterLoop" "\n" // if y != 88, loop
-
+
: // outputs
[c]"+l" (c),
[t]"+l" (t),
[x]"+l" (x),
[y]"+h" (y), // +:Read-Write l:lower (0-7) register
[scrbuf]"+l" (scrbuf)
-
+
: // inputs
[LCD]"l" (0xA0002188),
[scanline]"l" (scanline),
@@ -1056,8 +1186,13 @@
"cc", "r10", "r11"
);
-
+
#else
+ write_data(0); // does not have pixel 0 bug
+ write_command(0x22); // write data to DRAM
+ CLR_CS_SET_CD_RD_WR;
+ SET_MASK_P2;
+
uint8_t* d = scrbuf;// point to beginning of line in data
#ifdef PROJ_SHOW_FPS_COUNTER
@@ -1713,122 +1848,132 @@
}
#define MODE13_INNER_LOOP_A \
- " ldrb %[t], [%[scrbuf],0]" "\n" \
- " add %[t], %[t], %[offset]" "\n" \
+ " add %[t], %[t], r10" "\n" \
" uxtb %[c], %[t] " "\n" \
" lsls %[c], 1" "\n" \
" ldrh %[t], [%[paletteptr], %[c]]" "\n" \
" lsls %[t], %[t], 3" "\n" \
" str %[t], [%[LCD], 0]" "\n" \
- " mov %[c], r11" "\n" \
- " str %[c], [%[LCD], 124]" "\n" \
- " stm %[scanline]!, {%[t]}" "\n" \
- " movs %[t], 252" "\n" \
- " str %[c], [%[LCD], %[t]]" "\n" \
- " str %[c], [%[LCD], 124]" "\n" \
+ " movs %[c], 252" "\n" \
+ " str %[offset], [%[LCD], %[c]]" "\n" \
+ " stm %[scanline]!, {%[t]}" "\n" \
+ " str %[offset], [%[LCD], 124]" "\n" \
+ " str %[offset], [%[LCD], %[c]]" "\n" \
" adds %[scrbuf], %[scrbuf], 1" "\n" \
- " str %[c], [%[LCD], %[t]]" "\n"
-
-#define MODE13_INNER_LOOP_B \
- " ldm %[scanline]!, {%[c]}" "\n" \
- " str %[c], [%[LCD], 0]" "\n" \
- " str %[t], [%[LCD], 124]" "\n" \
- " movs %[c], 252" "\n" \
- " str %[t], [%[LCD], %[c]]" "\n" \
- " str %[t], [%[LCD], 124]" "\n" \
- " subs %[x], 1" "\n" \
- " str %[t], [%[LCD], %[c]]" "\n" \
+ " ldrb %[t], [%[scrbuf],0]" "\n" \
+ " str %[offset], [%[LCD], 124]" "\n"
-
+// This can be made 1 cycle faster (x -= 10 instead of x--),
+// but there will be noise
+#define MODE13_INNER_LOOP_B \
+ " str %[c], [%[LCD], 0]" "\n" \
+ " str %[offset], [%[LCD], %[t]]" "\n" \
+ " ldr %[c], [%[scanline]]" "\n" \
+ " str %[offset], [%[LCD], 124]" "\n" \
+ " str %[offset], [%[LCD], %[t]]" "\n" \
+ " adds %[scanline], 4" "\n" \
+ " subs %[x], 1" "\n" \
+ " str %[offset], [%[LCD], 124]" "\n"
+
+
void Pokitto::lcdRefreshMode13(uint8_t * scrbuf, uint16_t* paletteptr, uint8_t offset){
uint32_t scanline[110]; // read two nibbles = pixels at a time
-
+
write_command_16(0x03); write_data_16(0x1038);
write_command(0x20); write_data(0);
- write_command(0x21); write_data(1);
+ write_command(0x21); write_data(0);
write_command(0x22);
CLR_CS_SET_CD_RD_WR;
SET_MASK_P2;
-
- uint32_t x, y=0;
-
+
+ uint32_t x, y=0, c, t;
+
#ifndef __ARMCC_VERSION
+ #ifdef PROJ_SHOW_FPS_COUNTER
+ setDRAMptr(0, 8);
+ y=4;
+ #endif
+
asm volatile(
".syntax unified" "\n"
-
- "mov r10, %[scanline]" "\n"
-
- "movs %[t], 1" "\n"
- "lsls %[t], %[t], 12" "\n"
- "mov r11, %[t]" "\n"
-
+
+ "mov r10, %[offset]" "\n"
+ "movs %[offset], 1" "\n"
+ "lsls %[offset], %[offset], 12" "\n"
+
"mode13OuterLoop:" "\n"
-
+
"movs %[x], 110" "\n"
+ "ldrb %[t], [%[scrbuf],0]" "\n"
"mode13InnerLoopA:"
MODE13_INNER_LOOP_A
MODE13_INNER_LOOP_A
- " subs %[x], 2" "\n"
+ " subs %[x], 2" "\n"
" bne mode13InnerLoopA" "\n"
- "mov %[scanline], r10" "\n"
+ "subs %[scanline], 220" "\n"
+ "subs %[scanline], 220" "\n"
+
"movs %[x], 110" "\n"
- "mov %[t], r11" "\n"
+ "movs %[t], 252" "\n"
+ "ldm %[scanline]!, {%[c]}" "\n"
"mode13InnerLoopB:"
- MODE13_INNER_LOOP_B
- MODE13_INNER_LOOP_B
- MODE13_INNER_LOOP_B
- MODE13_INNER_LOOP_B
- MODE13_INNER_LOOP_B
- MODE13_INNER_LOOP_B
- MODE13_INNER_LOOP_B
- MODE13_INNER_LOOP_B
- MODE13_INNER_LOOP_B
- MODE13_INNER_LOOP_B
+ MODE13_INNER_LOOP_B
+ MODE13_INNER_LOOP_B
+ MODE13_INNER_LOOP_B
+ MODE13_INNER_LOOP_B
+ MODE13_INNER_LOOP_B
+ MODE13_INNER_LOOP_B
+ MODE13_INNER_LOOP_B
+ MODE13_INNER_LOOP_B
+ MODE13_INNER_LOOP_B
+ MODE13_INNER_LOOP_B
" bne mode13InnerLoopB" "\n"
-
- "mov %[scanline], r10" "\n"
+
+ "subs %[scanline], 220" "\n"
+ "subs %[scanline], 224" "\n"
"movs %[t], 1" "\n"
"movs %[c], 88" "\n"
- "add %[y], %[t]" "\n" // y++... derpy, but it's the outer loop
+ "add %[y], %[t]" "\n"
"cmp %[y], %[c]" "\n"
"bne mode13OuterLoop" "\n" // if y != 88, loop
-
+
: // outputs
[c]"+l" (c),
[t]"+l" (t),
[x]"+l" (x),
[y]"+h" (y), // +:Read-Write l:lower (0-7) register
- [scrbuf]"+l" (scrbuf)
-
+ [scrbuf]"+l" (scrbuf),
+ [offset]"+l" (offset)
+
: // inputs
[LCD]"l" (0xA0002188),
[scanline]"l" (scanline),
- [paletteptr]"l" (paletteptr),
- [offset]"l" (offset)
+ [paletteptr]"l" (paletteptr)
+
: // clobbers
- "cc", "r10", "r11"
+ "cc", "r10"
);
#else
uint8_t* d = scrbuf;// point to beginning of line in data
for(y=0;y<88;y++){
-
+
uint32_t* s = scanline;
-
+
for(x=0;x<110;x+=10){
- *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
- *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
- *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
- *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
- *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
- *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
- *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
- *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
- *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
- *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
+ *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
+ *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
+ *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
+ *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
+ *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
+ *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
+ *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
+ *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
+ *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
+ *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++);
}
-
+
s = scanline;
uint32_t c = *s;
for(x=0;x<110;x+=10){
@@ -1843,13 +1988,113 @@
*LCD = c; TGL_WR_OP(s++);TGL_WR_OP(c=*s);
*LCD = c; TGL_WR_OP(s++);TGL_WR_OP(c=*s);
}
-
+
}
#endif
}
+
+
+ void Pokitto::lcdRefreshMode64( uint8_t * scrbuf, uint16_t* paletteptr ){
+ uint8_t *end = &scrbuf[ POK_SCREENBUFFERSIZE+4 ];
+ write_command_16(0x03); write_data_16(0x1038);
+ write_command(0x20); write_data(0);
+#ifdef PROJ_SHOW_FPS_COUNTER
+ write_data(8);
+ scrbuf += 110*8;
+#else
+ write_data(0);
+#endif
+ write_command(0x21); write_data(0);
+ write_command(0x22);
+ CLR_CS_SET_CD_RD_WR;
+ SET_MASK_P2;
+
+ uint32_t TGL = 1<<12, CLR = 252, c, t;
+#ifndef __ARMCC_VERSION
+ asm volatile(
+ ".syntax unified" "\n"
+ "ldm %[scrbuf]!, {%[c]}" "\n"
+ "lsls %[t], %[c], 24" "\n"
+ "mode64loop%=:" "\n"
+ "lsrs %[c], %[c], 8" "\n"
+ "lsrs %[t], %[t], 23" "\n"
+ "ldrh %[t], [%[paletteptr], %[t]]" "\n"
+ "lsls %[t], 3" "\n"
+ "str %[t], [%[LCD], 0]" "\n"
+ "str %[TGL], [%[LCD], %[CLR]]" "\n"
+ "lsls %[t], %[c], 24" "\n"
+ "lsrs %[c], %[c], 8" "\n"
+ "lsrs %[t], %[t], 23" "\n"
+ "str %[TGL], [%[LCD], 124]" "\n"
+ "str %[TGL], [%[LCD], %[CLR]]" "\n"
+ "ldrh %[t], [%[paletteptr], %[t]]" "\n"
+ "lsls %[t], 3" "\n"
+ "str %[TGL], [%[LCD], 124]" "\n"
+
+ "str %[t], [%[LCD], 0]" "\n"
+ "str %[TGL], [%[LCD], %[CLR]]" "\n"
+ "lsls %[t], %[c], 24" "\n"
+ "lsrs %[t], %[t], 23" "\n"
+ "str %[TGL], [%[LCD], 124]" "\n"
+ "str %[TGL], [%[LCD], %[CLR]]" "\n"
+ "ldrh %[t], [%[paletteptr], %[t]]" "\n"
+ "lsls %[t], 3" "\n"
+ "str %[TGL], [%[LCD], 124]" "\n"
+ "str %[t], [%[LCD], 0]" "\n"
+ "str %[TGL], [%[LCD], %[CLR]]" "\n"
+ "lsrs %[c], %[c], 8" "\n"
+ "lsls %[t], %[c], 1" "\n"
+ "str %[TGL], [%[LCD], 124]" "\n"
+ "str %[TGL], [%[LCD], %[CLR]]" "\n"
+ "ldrh %[t], [%[paletteptr], %[t]]" "\n"
+ "lsls %[t], 3" "\n"
+ "str %[TGL], [%[LCD], 124]" "\n"
+
+ "str %[t], [%[LCD], 0]" "\n"
+ "str %[TGL], [%[LCD], %[CLR]]" "\n"
+ "ldm %[scrbuf]!, {%[c]}" "\n"
+ "str %[TGL], [%[LCD], 124]" "\n"
+ "str %[TGL], [%[LCD], %[CLR]]" "\n"
+ "lsls %[t], %[c], 24" "\n"
+ "cmp %[scrbuf], %[end]" "\n"
+ "str %[TGL], [%[LCD], 124]" "\n"
+
+ "bne mode64loop%=" "\n"
+
+ : // outputs
+ [c]"+l" (c),
+ [t]"+l" (t),
+ [scrbuf]"+l" (scrbuf)
+
+ : // inputs
+ [CLR]"l" (CLR),
+ [TGL]"l" (TGL),
+ [LCD]"l" (0xA0002188),
+ [paletteptr]"l" (paletteptr),
+ [end]"h" (end)
+
+ : // clobbers
+ "cc"
+ );
+
+#else
+
+ c = uint32_t(paletteptr[(*scrbuf)&255])<<3;
+ while( scrbuf < end-4 ){
+ *LCD = c; TGL_WR_OP(scrbuf++);TGL_WR_OP( c = uint32_t(paletteptr[(*scrbuf)&255])<<3 );
+ *LCD = c; TGL_WR_OP(scrbuf++);TGL_WR_OP( c = uint32_t(paletteptr[(*scrbuf)&255])<<3 );
+ *LCD = c; TGL_WR_OP(scrbuf++);TGL_WR_OP( c = uint32_t(paletteptr[(*scrbuf)&255])<<3 );
+ *LCD = c; TGL_WR_OP(scrbuf++);TGL_WR_OP( c = uint32_t(paletteptr[(*scrbuf)&255])<<3 );
+ }
+
+#endif
+ }
+
+
+
void Pokitto::lcdRefreshMode14(uint8_t * scrbuf, uint16_t* paletteptr) {
-uint16_t x,y;
+uint16_t x,y,data,xptr;
uint16_t scanline[176]; uint16_t* scptr;
uint8_t *d;
@@ -1986,10 +2231,99 @@
#else
void Pokitto::lcdRefreshMode15(uint16_t* paletteptr, uint8_t* scrbuf){
-uint16_t x,y;
+// #define __ARMCC_VERSION
+#ifndef __ARMCC_VERSION
+
+#define MODE15_LOOP \
+ "ands %[tmp], %[color]" "\n" \
+ "lsrs %[tmp], 2" "\n" \
+ "ldr %[tmp], [%[palette], %[tmp]]" "\n" \
+ "str %[tmp], [%[LCD]]" "\n" \
+ "str %[WRBit], [%[LCD], %[CLR]]" "\n" \
+ "movs %[tmp], 0x0F" "\n" \
+ "ands %[tmp], %[color]" "\n" \
+ "str %[WRBit], [%[LCD], 124]" "\n" \
+ "lsls %[tmp], 2" "\n" \
+ "ldr %[tmp], [%[palette], %[tmp]]" "\n" \
+ "str %[tmp], [%[LCD]]" "\n" \
+ "str %[WRBit], [%[LCD], %[CLR]]" "\n" \
+ "movs %[tmp], 0xF0" "\n" \
+ "lsrs %[color], 8" "\n" \
+ "str %[WRBit], [%[LCD], 124]" "\n"
+
+#define MODE15_ENDLOOP \
+ "ands %[tmp], %[color]" "\n" \
+ "lsrs %[tmp], 2" "\n" \
+ "ldr %[tmp], [%[palette], %[tmp]]" "\n" \
+ "str %[tmp], [%[LCD]]" "\n" \
+ "str %[WRBit], [%[LCD], %[CLR]]" "\n" \
+ "movs %[tmp], 0x0F" "\n" \
+ "ands %[tmp], %[color]" "\n" \
+ "str %[WRBit], [%[LCD], 124]" "\n" \
+ "lsls %[tmp], 2" "\n" \
+ "ldr %[tmp], [%[palette], %[tmp]]" "\n" \
+ "str %[tmp], [%[LCD]]" "\n" \
+ "str %[WRBit], [%[LCD], %[CLR]]" "\n" \
+ "ldm %[scrbuf]!, {%[color]}" "\n" \
+ "movs %[tmp], 0xF0" "\n" \
+ "str %[WRBit], [%[LCD], 124]" "\n"
+
+ uint8_t *end=&scrbuf[POK_SCREENBUFFERSIZE]+4;
+ volatile uint32_t palette[16];
+ for( uint32_t i=0; i<16; ++i )
+ palette[i] = uint32_t(paletteptr[i]) << 3;
+
+ write_command(0x03); write_data(0x1038);
+ write_command(0x21); // Vertical DRAM Address
+ write_data(0);
+ write_command(0x20); // Horizontal DRAM Address
+#ifdef PROJ_SHOW_FPS_COUNTER
+ write_data(8);
+ scrbuf += 110*8;
+#else
+ write_data(0);
+#endif
+ write_command(0x22); // write data to DRAM
+ CLR_CS_SET_CD_RD_WR;
+
+
+ SET_MASK_P2;
+
+ uint32_t WRBit = 1<<12, color, tmp;
+ asm volatile(
+ ".syntax unified" "\n"
+ "ldm %[scrbuf]!, {%[color]}" "\n"
+ "movs %[tmp], 0xF0" "\n"
+ "mode15Loop%=:" "\n"
+ MODE15_LOOP
+ MODE15_LOOP
+ MODE15_LOOP
+ MODE15_ENDLOOP
+ "cmp %[end], %[scrbuf]" "\n"
+ "bne mode15Loop%=" "\n"
+ :
+ [tmp]"+l" (tmp),
+ [color]"+l" (color),
+ [end]"+h" (end),
+ [scrbuf]"+l" (scrbuf),
+ [WRBit]"+l" (WRBit)
+
+ :
+ [CLR]"l" (252),
+ [LCD]"l" (0xA0002188),
+ [palette]"l" (palette)
+
+ :
+ "cc"
+ );
+
+#else
+
+uint16_t x,y,xptr;
uint16_t scanline[2][176]; // read two nibbles = pixels at a time
-uint8_t *d;
+uint8_t *d, yoffset=0;
+xptr = 0;
//setDRAMptr(xptr,yoffset);
write_command(0x20); write_data(0);
@@ -2042,11 +2376,130 @@
setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
}
}
+
+#endif
+
}
#endif //ADEKTOSMODE15
+void Pokitto::lcdRefreshMixMode(const uint8_t * screenBuffer, const uint16_t * palettePointer, const uint8_t * scanType)
+{
+ write_command(0x03);
+ write_data(0x1038);
+
+ // Horizontal DRAM Address
+ write_command(0x20);
+ write_data(0);
+
+ // Vertical DRAM Address
+ write_command(0x21);
+ write_data(0);
+
+ // write data to DRAM
+ write_command(0x22);
+ CLR_CS_SET_CD_RD_WR;
+ SET_MASK_P2;
+
+ uint32_t scanline[220];
+
+ // point to beginning of line in data
+ const uint8_t * d = screenBuffer;
+ for(uint32_t y = 0; y < 176; ++y)
+ {
+ // find colours in one scanline
+ uint8_t scanTypeIndex = y >> 1;
+ uint8_t lineIndex = 0;
+ switch(scanType[scanTypeIndex])
+ {
+ case 0:
+ {
+ // point to beginning of line in data
+ d = &screenBuffer[110 * scanTypeIndex];
+ for(uint8_t x = 0; x < (220 / 2); ++x)
+ {
+ uint32_t color = static_cast<uint32_t>(palettePointer[*d]) << 3;
+ ++d;
+ scanline[lineIndex] = color;
+ ++lineIndex;
+ scanline[lineIndex] = color;
+ ++lineIndex;
+ }
+ break;
+ }
+ case 1:
+ {
+ for(uint8_t x = 0; x < (220 / 4); ++x)
+ {
+ uint8_t t = *d;
+ ++d;
+
+ uint32_t color1 = static_cast<uint32_t>(palettePointer[256 + (t >> 4)]) << 3;
+ scanline[lineIndex] = color1;
+ ++lineIndex;
+ scanline[lineIndex] = color1;
+ ++lineIndex;
+
+ uint32_t color2 = static_cast<uint32_t>(palettePointer[256 + (t & 0xF)]) << 3;
+ scanline[lineIndex] = color2;
+ ++lineIndex;
+ scanline[lineIndex] = color2;
+ ++lineIndex;
+ }
+ break;
+ }
+ case 2:
+ {
+ for(uint8_t x = 0; x < (220 / 4); ++x)
+ {
+ uint8_t t = *d;
+ ++d;
+
+ scanline[lineIndex] = static_cast<uint32_t>(palettePointer[272 + ((t >> 6) & 0x03)]) << 3;
+ ++lineIndex;
+
+ scanline[lineIndex] = static_cast<uint32_t>(palettePointer[272 + ((t >> 4) & 0x03)]) << 3;
+ ++lineIndex;
+
+ scanline[lineIndex] = static_cast<uint32_t>(palettePointer[272 + ((t >> 2) & 0x03)]) << 3;
+ ++lineIndex;
+
+ scanline[lineIndex] = static_cast<uint32_t>(palettePointer[272 + ((t >> 0) & 0x03)]) << 3;
+ ++lineIndex;
+ }
+ break;
+ }
+ }
+
+ uint32_t color = scanline[0];
+ #define WRITE_SCANLINE *LCD = color; TGL_WR_OP(color = scanline[++i]);
+
+ volatile uint32_t * LCD = reinterpret_cast< volatile uint32_t * >(0xA0002188);
+ for (uint8_t i = 0; i < 220;)
+ {
+ WRITE_SCANLINE WRITE_SCANLINE WRITE_SCANLINE WRITE_SCANLINE
+ WRITE_SCANLINE WRITE_SCANLINE WRITE_SCANLINE WRITE_SCANLINE
+ WRITE_SCANLINE WRITE_SCANLINE WRITE_SCANLINE
+ WRITE_SCANLINE WRITE_SCANLINE WRITE_SCANLINE WRITE_SCANLINE
+ WRITE_SCANLINE WRITE_SCANLINE WRITE_SCANLINE WRITE_SCANLINE
+ WRITE_SCANLINE WRITE_SCANLINE WRITE_SCANLINE
+ WRITE_SCANLINE WRITE_SCANLINE WRITE_SCANLINE WRITE_SCANLINE
+ WRITE_SCANLINE WRITE_SCANLINE WRITE_SCANLINE WRITE_SCANLINE
+ WRITE_SCANLINE WRITE_SCANLINE WRITE_SCANLINE
+ WRITE_SCANLINE WRITE_SCANLINE WRITE_SCANLINE WRITE_SCANLINE
+ WRITE_SCANLINE WRITE_SCANLINE WRITE_SCANLINE WRITE_SCANLINE
+ WRITE_SCANLINE WRITE_SCANLINE WRITE_SCANLINE
+ }
+
+ #undef WRITE_SCANLINE
+ }
+
+ CLR_MASK_P2;
+}
+
+
void Pokitto::blitWord(uint16_t c) {
setup_data_16(c);CLR_WR;SET_WR;
}
+
--- a/POKITTO_HW/HWLCD.h Sun Oct 07 10:19:52 2018 +0000
+++ b/POKITTO_HW/HWLCD.h Sat Mar 23 19:19:23 2019 +0000
@@ -81,6 +81,8 @@
extern void lcdRefreshMode3(uint8_t *, uint16_t*);
extern void lcdRefreshModeGBC(uint8_t *, uint16_t*);
extern void lcdRefreshMode13(uint8_t *, uint16_t*, uint8_t);
+extern void lcdRefreshMixMode(const uint8_t *, const uint16_t*, const uint8_t*);
+extern void lcdRefreshMode64(uint8_t *, uint16_t*);
extern void lcdRefreshMode15(uint16_t*, uint8_t*);
@@ -147,14 +149,14 @@
#define CLR_MASK_P2 LPC_GPIO_PORT->MASK[2] = 0; // all on
#define TGL_WR_OP(OP) \
- LPC_GPIO_PORT->SET[LCD_WR_PORT] = 1 << LCD_WR_PIN; \
+ LPC_GPIO_PORT->CLR[LCD_WR_PORT] = 1 << LCD_WR_PIN; \
OP; \
- LPC_GPIO_PORT->CLR[LCD_WR_PORT] = 1 << LCD_WR_PIN;
+ LPC_GPIO_PORT->SET[LCD_WR_PORT] = 1 << LCD_WR_PIN;
#define TGL_WR \
- LPC_GPIO_PORT->SET[LCD_WR_PORT] = 1 << LCD_WR_PIN; \
- __asm("nop"); \
- LPC_GPIO_PORT->CLR[LCD_WR_PORT] = 1 << LCD_WR_PIN;
+ LPC_GPIO_PORT->CLR[LCD_WR_PORT] = 1 << LCD_WR_PIN; \
+ __asm("nop"); \
+ LPC_GPIO_PORT->SET[LCD_WR_PORT] = 1 << LCD_WR_PIN;
/**************************************************************************/
/** SETUP GPIO & DATA **/