PokittoLib is the library needed for programming the Pokitto DIY game console (www.pokitto.com)
Embed:
(wiki syntax)
Show/hide line numbers
HWLCD.cpp
Go to the documentation of this file.
00001 /**************************************************************************/ 00002 /*! 00003 @file HWLCD.cpp 00004 @author Jonne Valola 00005 00006 @section LICENSE 00007 00008 Software License Agreement (BSD License) 00009 00010 Copyright (c) 2016, Jonne Valola 00011 All rights reserved. 00012 00013 Redistribution and use in source and binary forms, with or without 00014 modification, are permitted provided that the following conditions are met: 00015 1. Redistributions of source code must retain the above copyright 00016 notice, this list of conditions and the following disclaimer. 00017 2. Redistributions in binary form must reproduce the above copyright 00018 notice, this list of conditions and the following disclaimer in the 00019 documentation and/or other materials provided with the distribution. 00020 3. Neither the name of the copyright holders nor the 00021 names of its contributors may be used to endorse or promote products 00022 derived from this software without specific prior written permission. 00023 00024 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY 00025 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00026 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00027 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 00028 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00029 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00030 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00031 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00032 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00033 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00034 */ 00035 /**************************************************************************/ 00036 00037 #include "HWLCD.h " //HWLCD.h" #include "HWLCD.h" 00038 #include "Pokitto_settings.h " 00039 00040 #define avrmax(a,b) ((a)>(b)?(a):(b)) 00041 #define avrmin(a,b) ((a)<(b)?(a):(b)) 00042 00043 #ifdef DISABLEAVRMIN 00044 #include <algorithm> 00045 using std::min; 00046 using std::max; 00047 #endif // DISABLEAVRMIN 00048 00049 #define AB_JUMP 1024 // jump one 1-bit Arduboy screen forward to get next color bit 00050 #define GB_JUMP 504 // jump one 1-bit Gamebuino screen forward to get next color bit 00051 00052 using namespace Pokitto; 00053 00054 uint16_t prevdata=0; // if data does not change, do not adjust LCD bus lines 00055 00056 #if POK_BOARDREV == 2 00057 pwmout_t backlightpwm; 00058 #endif 00059 00060 volatile uint32_t *LCD = reinterpret_cast< volatile uint32_t * >(0xA0002188); 00061 00062 /**************************************************************************/ 00063 /*! 00064 @brief set up the 16-bit bus 00065 */ 00066 /**************************************************************************/ 00067 00068 static inline void setup_data_16(uint16_t data) 00069 { 00070 //uint32_t p2=0; 00071 00072 //if (data != prevdata) { 00073 // 00074 //prevdata=data; 00075 00076 /** D0...D16 = P2_3 ... P2_18 **/ 00077 //p2 = data << 3; 00078 00079 //__disable_irq(); // Disable Interrupts 00080 SET_MASK_P2; 00081 LPC_GPIO_PORT->MPIN[2] = (data<<3); // write bits to port 00082 CLR_MASK_P2; 00083 //__enable_irq(); // Enable Interrupts 00084 //} 00085 } 00086 00087 00088 /**************************************************************************/ 00089 /*! 00090 @brief Write a command to the lcd, 16-bit bus 00091 */ 00092 /**************************************************************************/ 00093 inline void write_command_16(uint16_t data) 00094 { 00095 CLR_CS; // select lcd 00096 CLR_CD; // clear CD = command 00097 SET_RD; // RD high, do not read 00098 setup_data_16(data); // function that inputs the data into the relevant bus lines 00099 CLR_WR_SLOW; // WR low 00100 SET_WR; // WR low, then high = write strobe 00101 SET_CS; // de-select lcd 00102 } 00103 00104 /**************************************************************************/ 00105 /*! 00106 @brief Write data to the lcd, 16-bit bus 00107 */ 00108 /**************************************************************************/ 00109 inline void write_data_16(uint16_t data) 00110 { 00111 CLR_CS; 00112 SET_CD; 00113 SET_RD; 00114 setup_data_16(data); 00115 CLR_WR; 00116 SET_WR; 00117 SET_CS; 00118 } 00119 00120 /**************************************************************************/ 00121 /*! 00122 @brief Pump data to the lcd, 16-bit bus, public function 00123 */ 00124 /**************************************************************************/ 00125 void Pokitto::pumpDRAMdata(uint16_t* data,uint16_t counter) 00126 { 00127 while (counter--) { 00128 CLR_CS; 00129 SET_CD; 00130 SET_RD; 00131 setup_data_16(*data++); 00132 CLR_WR; 00133 SET_WR; 00134 SET_CS; 00135 } 00136 } 00137 00138 00139 /**************************************************************************/ 00140 /*! 00141 @brief Point to a (x,y) location in the LCD DRAM 00142 */ 00143 /**************************************************************************/ 00144 static inline void setDRAMptr(uint8_t xptr, uint8_t yoffset) 00145 { 00146 write_command(0x20); // Vertical DRAM Address 00147 write_data(yoffset); 00148 write_command(0x21); // Horizontal DRAM Address 00149 write_data(xptr); // 00150 write_command(0x22); // write data to DRAM 00151 CLR_CS_SET_CD_RD_WR; 00152 } 00153 00154 /**************************************************************************/ 00155 /*! 00156 @brief Point to a (x,y) location in the LCD DRAM, public function 00157 */ 00158 /**************************************************************************/ 00159 void Pokitto::setDRAMpoint(uint8_t xptr, uint8_t yoffset) 00160 { 00161 write_command(0x20); // Vertical DRAM Address 00162 write_data(yoffset); 00163 write_command(0x21); // Horizontal DRAM Address 00164 write_data(xptr); // 00165 write_command(0x22); // write data to DRAM 00166 CLR_CS_SET_CD_RD_WR; 00167 } 00168 00169 void Pokitto::initBacklight() { 00170 #if POK_BOARDREV == 2 00171 pwmout_init(&backlightpwm,POK_BACKLIGHT_PIN); 00172 pwmout_period_us(&backlightpwm,5); 00173 pwmout_write(&backlightpwm,POK_BACKLIGHT_INITIALVALUE); 00174 #endif 00175 } 00176 00177 void Pokitto::setBacklight(float value) { 00178 if (value>0.999f) value = 0.999f; 00179 pwmout_write(&backlightpwm,value); 00180 } 00181 00182 void Pokitto::lcdInit() { 00183 initBacklight(); 00184 00185 SET_RESET; 00186 wait_ms(10); 00187 CLR_RESET; 00188 wait_ms(10); 00189 SET_RESET; 00190 wait_ms(10); 00191 //************* Start Initial Sequence **********// 00192 write_command(0x01); // driver output control, this also affects direction 00193 write_data(0x11C); // originally: 0x11C 100011100 SS,NL4,NL3,NL2 00194 // NL4...0 is the number of scan lines to drive the screen !!! 00195 // so 11100 is 1c = 220 lines, correct 00196 // test 1: 0x1C 11100 SS=0,NL4,NL3,NL2 -> no effect 00197 // test 2: 0x31C 1100011100 GS=1,SS=1,NL4,NL3,NL2 -> no effect 00198 // test 3: 0x51C 10100011100 SM=1,GS=0,SS=1,NL4,NL3,NL2 -> no effect 00199 // test 4: 0x71C SM=1,GS=1,SS=1,NL4,NL3,NL2 00200 // test 5: 0x 00201 // seems to have no effect... is this perhaps only for RGB mode ? 00202 00203 write_command(0x02); // LCD driving control 00204 write_data(0x0100); // INV = 1 00205 00206 write_command(0x03); // Entry mode... lets try if this affects the direction 00207 write_data(0x1030); // originally 0x1030 1000000110000 BGR,ID1,ID0 00208 // test 1: 0x1038 1000000111000 BGR,ID1,ID0,AM=1 ->drawing DRAM horizontally 00209 // test 4: am=1, id0=0, id1=0, 1000000001000,0x1008 -> same as above, but flipped on long 00210 // test 2: am=0, id0=0, 1000000100000, 0x1020 -> flipped on long axis 00211 // test 3: am=0, id1=0, 1000000010000, 0x1010 -> picture flowed over back to screen 00212 00213 00214 write_command(0x08); // Display control 2 00215 write_data(0x0808); // 100000001000 FP2,BP2 00216 00217 write_command(0x0C); // RGB display interface 00218 write_data(0x0000); // all off 00219 00220 write_command(0x0F); // Frame marker position 00221 write_data(0x0001); // OSC_EN 00222 00223 write_command(0x20); // Horizontal DRAM Address 00224 write_data(0x0000); // 0 00225 00226 write_command(0x21); // Vertical DRAM Address 00227 write_data(0x0000); // 0 00228 00229 //*************Power On sequence ****************// 00230 write_command(0x10); 00231 write_data(0x0000); 00232 00233 write_command(0x11); 00234 write_data(0x1000); 00235 wait_ms(10); 00236 //------------------------ Set GRAM area --------------------------------// 00237 write_command(0x30); // Gate scan position 00238 write_data(0x0000); // if GS=0, 00h=G1, else 00h=G220 00239 00240 write_command(0x31); // Vertical scroll control 00241 write_data(0x00DB); // scroll start line 11011011 = 219 00242 00243 write_command(0x32); // Vertical scroll control 00244 write_data(0x0000); // scroll end line 0 00245 00246 write_command(0x33); // Vertical scroll control 00247 write_data(0x0000); // 0=vertical scroll disabled 00248 00249 write_command(0x34); // Partial screen driving control 00250 write_data(0x00DB); // db = full screen (end) 00251 00252 write_command(0x35); // partial screen 00253 write_data(0x0000); // 0 = start 00254 00255 write_command(0x36); // Horizontal and vertical RAM position 00256 write_data(0x00AF); //end address 175 00257 00258 write_command(0x37); 00259 write_data(0x0000); // start address 0 00260 00261 write_command(0x38); 00262 write_data(0x00DB); //end address 219 00263 00264 write_command(0x39); // start address 0 00265 write_data(0x0000); 00266 wait_ms(10); 00267 write_command(0xff); // start gamma register control 00268 write_data(0x0003); 00269 00270 // ----------- Adjust the Gamma Curve ----------// 00271 write_command(0x50); 00272 write_data(0x0203); 00273 00274 write_command(0x051); 00275 write_data(0x0A09); 00276 00277 write_command(0x52); 00278 write_data(0x0005); 00279 00280 write_command(0x53); 00281 write_data(0x1021); 00282 00283 write_command(0x54); 00284 write_data(0x0602); 00285 00286 write_command(0x55); 00287 write_data(0x0003); 00288 00289 write_command(0x56); 00290 write_data(0x0703); 00291 00292 write_command(0x57); 00293 write_data(0x0507); 00294 00295 write_command(0x58); 00296 write_data(0x1021); 00297 00298 write_command(0x59); 00299 write_data(0x0703); 00300 00301 write_command(0xB0); 00302 write_data(0x2501); 00303 00304 write_command(0xFF); 00305 write_data(0x0000); 00306 00307 write_command(0x07); 00308 write_data(0x1017); 00309 wait_ms(200); 00310 write_command(0x22); 00311 00312 lcdClear(); 00313 } 00314 00315 void Pokitto::lcdSleep(void){ 00316 write_command(0xFF); 00317 write_data(0x0000); 00318 00319 write_command(0x07); 00320 write_data(0x0000); 00321 wait_ms(50); 00322 write_command(0x10);// Enter Standby mode 00323 write_data(0x0003); 00324 wait_ms(200); 00325 00326 } 00327 00328 void Pokitto::lcdWakeUp (void){ 00329 00330 wait_ms(200); 00331 write_command(0xFF); 00332 write_data(0x0000); 00333 00334 write_command(0x10);// Exit Sleep/ Standby mode 00335 write_data(0x0000); 00336 wait_ms(50); 00337 write_command(0x07); 00338 write_data(0x0117); 00339 wait_ms(200); 00340 } 00341 00342 void Pokitto::lcdFillSurface(uint16_t c) { 00343 uint32_t i; 00344 write_command(0x20); // Horizontal DRAM Address 00345 write_data(0x0000); // 0 00346 write_command(0x21); // Vertical DRAM Address 00347 write_data(0); 00348 write_command(0x22); // write data to DRAM 00349 setup_data_16(c); 00350 CLR_CS_SET_CD_RD_WR; 00351 for(i=0;i<220*176;i++) 00352 { 00353 CLR_WR; 00354 SET_WR; 00355 } 00356 } 00357 00358 void Pokitto::lcdClear() { 00359 uint32_t i; 00360 write_command(0x20); // Horizontal DRAM Address 00361 write_data(0x0000); // 0 00362 write_command(0x21); // Vertical DRAM Address 00363 write_data(0); 00364 write_command(0x22); // write data to DRAM 00365 setup_data_16(0x0000); 00366 CLR_CS_SET_CD_RD_WR; 00367 for(i=0;i<220*176;i++) 00368 { 00369 CLR_WR; 00370 SET_WR; 00371 } 00372 } 00373 00374 void Pokitto::lcdPixel(int16_t x, int16_t y, uint16_t color) { 00375 if ((x < 0) || (x >= POK_LCD_W) || (y < 0) || (y >= POK_LCD_H)) 00376 return; 00377 write_command(0x20); // Horizontal DRAM Address 00378 write_data(y); // 0 00379 write_command(0x21); // Vertical DRAM Address 00380 write_data(x); 00381 write_command(0x22); // write data to DRAM 00382 CLR_CS_SET_CD_RD_WR; 00383 setup_data_16(color); 00384 CLR_WR;SET_WR; 00385 } 00386 00387 void Pokitto::setWindow(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) { 00388 write_command(0x37); write_data(x1); 00389 write_command(0x36); write_data(x2); 00390 write_command(0x39); write_data(y1); 00391 write_command(0x38); write_data(y2); 00392 write_command(0x20); write_data(x1); 00393 write_command(0x21); write_data(y1); 00394 } 00395 00396 void Pokitto::lcdTile(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t* gfx){ 00397 int width=x1-x0; 00398 int height=y1-y0; 00399 if (x0 > POK_LCD_W) return; 00400 if (y0 > POK_LCD_H) return; 00401 if (x0 < 0) x0=0; 00402 if (y0 < 0) y0=0; 00403 00404 setWindow(y0, x0, y1-1, x1-1); 00405 write_command(0x22); 00406 00407 for (int x=0; x<=width*height-1;x++) { 00408 write_data(gfx[x]); 00409 } 00410 setWindow(0, 0, 175, 219); 00411 } 00412 00413 void Pokitto::lcdRectangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color) { 00414 int16_t temp; 00415 if (x0>x1) {temp=x0;x0=x1;x1=temp;} 00416 if (y0>y1) {temp=y0;y0=y1;y1=temp;} 00417 if (x0 > POK_LCD_W) return; 00418 if (y0 > POK_LCD_H) return; 00419 if (x1 > POK_LCD_W) x1=POK_LCD_W; 00420 if (y1 > POK_LCD_H) y1=POK_LCD_H; 00421 if (x0 < 0) x0=0; 00422 if (y0 < 0) y0=0; 00423 00424 int16_t x,y; 00425 00426 for (y=y0; y<y1;y++) { 00427 00428 write_command(0x20); // Horizontal DRAM Address (=y on pokitto screen) 00429 00430 write_data(y); 00431 00432 write_command(0x21); // Vertical DRAM Address (=x on pokitto screen) 00433 00434 write_data(x0); 00435 00436 write_command(0x22); // write data to DRAM 00437 00438 CLR_CS_SET_CD_RD_WR; // go to vram write mode 00439 00440 for (x=x0; x<x1;x++) { 00441 00442 setup_data_16(color); // setup the data (flat color = no change between pixels) 00443 00444 CLR_WR;SET_WR; //CLR_WR;SET_WR;//toggle writeline, pokitto screen writes a column up to down 00445 00446 } 00447 00448 } 00449 00450 } 00451 00452 00453 /*** 00454 * Update the screen buffer of 220x176 pixels, 4 colors to LCD. 00455 * 00456 * The update rect is used for drawing only part of the screen buffer to LCD. Because of speed optimizations, the 00457 * x, y, and width of the update rect must be dividable by 4 pixels, and the height must be dividable by 8 pixels. 00458 * Note: The update rect is currently used for 220x176, 4 colors, screen mode only. 00459 * @param scrbuf The screen buffer. 00460 * @param updRectX The update rect. 00461 * @param updRectY The update rect. 00462 * @param updRectW The update rect. 00463 * @param updRectH The update rect. 00464 * @param paletteptr The screen palette. 00465 */ 00466 void Pokitto::lcdRefreshMode1(uint8_t * scrbuf, uint8_t updRectX, uint8_t updRectY, uint8_t updRectW, uint8_t updRectH, uint16_t* paletteptr) { 00467 00468 uint16_t x,y; 00469 uint16_t scanline[4][176]; // read 4 half-nibbles = 4 pixels at a time 00470 uint8_t *d; 00471 00472 // If not the full screen is updated, check the validity of the update rect. 00473 if ( updRectX != 0 || updRectY != 0 ||updRectW != LCDWIDTH ||updRectH != LCDHEIGHT ) { 00474 uint8_t org_screenx = updRectX; 00475 updRectX &= 0xfc; // Make the value dividable by 4. 00476 updRectW += org_screenx - updRectX; 00477 updRectW = (updRectW + 3) & 0xfc; // Make the value dividable by 4, round up. 00478 00479 uint8_t org_screeny = updRectY; 00480 updRectY &= 0xfc; // Make the value dividable by 4. 00481 updRectH += org_screeny - updRectY; 00482 updRectH = (updRectH + 7) & 0xf8; // Make the value dividable by 8 (because of loop unroll optimization), round up. 00483 } 00484 00485 00486 #ifdef PROJ_SHOW_FPS_COUNTER 00487 xptr = 8; 00488 setDRAMptr(8, 0); 00489 #else 00490 setDRAMptr(0, 0); 00491 #endif 00492 00493 for (x=updRectX; x<updRectX+updRectW; x+=4) { 00494 d = scrbuf+(x>>2);// point to beginning of line in data 00495 00496 /** find colours in one scanline **/ 00497 d += (updRectY * 220/4); 00498 for (y=updRectY; y<updRectY+updRectH; y++) { 00499 uint8_t tdata = *d; 00500 uint8_t t4 = tdata & 0x03; tdata >>= 2;// lowest half-nibble 00501 uint8_t t3 = tdata & 0x03; tdata >>= 2;// second lowest half-nibble 00502 uint8_t t2 = tdata & 0x03; tdata >>= 2;// second highest half-nibble 00503 uint8_t t = tdata & 0x03;// highest half-nibble 00504 00505 /** put nibble values in the scanlines **/ 00506 scanline[0][y] = paletteptr[t]; 00507 scanline[1][y] = paletteptr[t2]; 00508 scanline[2][y] = paletteptr[t3]; 00509 scanline[3][y] = paletteptr[t4]; 00510 00511 d += 220/4; // jump to read byte directly below in screenbuffer 00512 } 00513 00514 #ifdef PROJ_SHOW_FPS_COUNTER 00515 if (x>=8 ) { 00516 #else 00517 { 00518 00519 #endif 00520 00521 // Draw 8 vertical pixels at a time for performance reasons 00522 setDRAMptr(x, updRectY); 00523 for (uint8_t s=updRectY; s<updRectY+updRectH;) { 00524 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 00525 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 00526 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 00527 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 00528 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 00529 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 00530 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 00531 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 00532 } 00533 setDRAMptr(x+1, updRectY); 00534 for (uint8_t s=updRectY; s<updRectY+updRectH;) { 00535 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 00536 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 00537 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 00538 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 00539 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 00540 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 00541 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 00542 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 00543 } 00544 setDRAMptr(x+2, updRectY); 00545 for (uint8_t s=updRectY; s<updRectY+updRectH;) { 00546 setup_data_16(scanline[2][s++]);CLR_WR;SET_WR; 00547 setup_data_16(scanline[2][s++]);CLR_WR;SET_WR; 00548 setup_data_16(scanline[2][s++]);CLR_WR;SET_WR; 00549 setup_data_16(scanline[2][s++]);CLR_WR;SET_WR; 00550 setup_data_16(scanline[2][s++]);CLR_WR;SET_WR; 00551 setup_data_16(scanline[2][s++]);CLR_WR;SET_WR; 00552 setup_data_16(scanline[2][s++]);CLR_WR;SET_WR; 00553 setup_data_16(scanline[2][s++]);CLR_WR;SET_WR; 00554 } 00555 setDRAMptr(x+3, updRectY); 00556 for (uint8_t s=updRectY; s<updRectY+updRectH;) { 00557 setup_data_16(scanline[3][s++]);CLR_WR;SET_WR; 00558 setup_data_16(scanline[3][s++]);CLR_WR;SET_WR; 00559 setup_data_16(scanline[3][s++]);CLR_WR;SET_WR; 00560 setup_data_16(scanline[3][s++]);CLR_WR;SET_WR; 00561 setup_data_16(scanline[3][s++]);CLR_WR;SET_WR; 00562 setup_data_16(scanline[3][s++]);CLR_WR;SET_WR; 00563 setup_data_16(scanline[3][s++]);CLR_WR;SET_WR; 00564 setup_data_16(scanline[3][s++]);CLR_WR;SET_WR; 00565 } 00566 } 00567 } 00568 00569 #ifdef POK_SIM 00570 simulator.refreshDisplay(); 00571 #endif 00572 } 00573 00574 // Copy sprite pixels to the scanline 00575 #define SPRITE_2BPP_INNER_LOOP(n)\ 00576 \ 00577 /* If the sprite is enabled and contained in this vertical scanline, copy 4 pixels. */\ 00578 if (sprScanlineAddr[(n)] &&\ 00579 y >= sprites[(n)].y && y < sprites[(n)].y + sprites[(n)].h ) {\ 00580 \ 00581 int16_t sprx = sprites[(n)].x;\ 00582 uint16_t s_data16b = 0; /* sprite data, 2 bytes */\ 00583 \ 00584 /* Get pixel block, 4 or 8 pixels horizontally. Use the predefined bitshift mode. */\ 00585 /* Note:it is cheapest to compare to 0 first. */\ 00586 if (sprScanlineBitshiftMode[(n)] == BITSHIFT_MODE_MIDDLE_BYTE) {\ 00587 s_data16b = *(sprScanlineAddr[(n)]);\ 00588 uint16_t leftByte = *(sprScanlineAddr[(n)]-1);\ 00589 s_data16b = (leftByte << 8) | s_data16b;\ 00590 }\ 00591 else if (sprScanlineBitshiftMode[(n)] == BITSHIFT_MODE_FIRST_BYTE) {\ 00592 s_data16b = *(sprScanlineAddr[(n)]);\ 00593 }\ 00594 else { /* BITSHIFT_MODE_LAST_BYTE */\ 00595 uint16_t leftByte = *(sprScanlineAddr[(n)]-1);\ 00596 s_data16b = (leftByte << 8) | s_data16b;\ 00597 }\ 00598 \ 00599 /* Shift sprite pixels according to sprite x. After shifting we have only 4 pixels. */\ 00600 uint8_t shiftRight = (sprx&0x3) << 1;\ 00601 s_data16b = (s_data16b >> shiftRight);\ 00602 \ 00603 /* Get individual pixels */\ 00604 uint8_t s_t4 = s_data16b & 0x03; s_data16b >>= 2; /* lowest half-nibble */\ 00605 uint8_t s_t3 = s_data16b & 0x03; s_data16b >>= 2; /* second lowest half-nibble */\ 00606 uint8_t s_t2 = s_data16b & 0x03; s_data16b >>= 2; /* second highest half-nibble */\ 00607 uint8_t s_t1 = s_data16b & 0x03; /* highest half-nibble */\ 00608 \ 00609 /* Store pixels as 16-bit colors from the palette */\ 00610 if (s_t4 != transparentColor) p4 = sprites[(n)].palette[s_t4];\ 00611 if (s_t3 != transparentColor) p3 = sprites[(n)].palette[s_t3];\ 00612 if (s_t2 != transparentColor) p2 = sprites[(n)].palette[s_t2];\ 00613 if (s_t1 != transparentColor) p = sprites[(n)].palette[s_t1];\ 00614 \ 00615 /* Advance scanline address */\ 00616 sprScanlineAddr[(n)] += (sprites[(n)].w >> 2);\ 00617 } 00618 00619 // Loop unrolling macros 00620 #define UNROLLED_LOOP_1() SPRITE_2BPP_INNER_LOOP(0) 00621 #define UNROLLED_LOOP_2() UNROLLED_LOOP_1() SPRITE_2BPP_INNER_LOOP(1) 00622 #define UNROLLED_LOOP_3() UNROLLED_LOOP_2() SPRITE_2BPP_INNER_LOOP(2) 00623 #define UNROLLED_LOOP_4() UNROLLED_LOOP_3() SPRITE_2BPP_INNER_LOOP(3) 00624 #define UNROLLED_LOOP_5() UNROLLED_LOOP_4() SPRITE_2BPP_INNER_LOOP(4) 00625 #define UNROLLED_LOOP_6() UNROLLED_LOOP_5() SPRITE_2BPP_INNER_LOOP(5) 00626 #define UNROLLED_LOOP_7() UNROLLED_LOOP_6() SPRITE_2BPP_INNER_LOOP(6) 00627 #define UNROLLED_LOOP_8() UNROLLED_LOOP_7() SPRITE_2BPP_INNER_LOOP(7) 00628 #define UNROLLED_LOOP_9() UNROLLED_LOOP_8() SPRITE_2BPP_INNER_LOOP(8) 00629 #define UNROLLED_LOOP_10() UNROLLED_LOOP_9() SPRITE_2BPP_INNER_LOOP(9) 00630 #define UNROLLED_LOOP_11() UNROLLED_LOOP_10() SPRITE_2BPP_INNER_LOOP(10) 00631 #define UNROLLED_LOOP_12() UNROLLED_LOOP_11() SPRITE_2BPP_INNER_LOOP(11) 00632 #define UNROLLED_LOOP_13() UNROLLED_LOOP_12() SPRITE_2BPP_INNER_LOOP(12) 00633 #define UNROLLED_LOOP_14() UNROLLED_LOOP_13() SPRITE_2BPP_INNER_LOOP(13) 00634 #define UNROLLED_LOOP_15() UNROLLED_LOOP_14() SPRITE_2BPP_INNER_LOOP(14) 00635 #define UNROLLED_LOOP_16() UNROLLED_LOOP_15() SPRITE_2BPP_INNER_LOOP(15) 00636 #define UNROLLED_LOOP_N_(n) UNROLLED_LOOP_##n() 00637 #define UNROLLED_LOOP_N(n) UNROLLED_LOOP_N_(n) 00638 00639 /*** 00640 * Update the screen buffer of 220x176 pixels, 4 colors and free size 4 color sprites to LCD. 00641 * 00642 * The update rect is used for drawing only part of the screen buffer to LCD. Because of speed optimizations, the 00643 * x, y, and width of the update rect must be dividable by 4 pixels, and the height must be dividable by 8 pixels. 00644 * Note: The update rect is currently used for 220x176, 4 colors, screen mode only. 00645 * If drawSpritesOnly=true, only sprites are fully updated to LCD. However, the dirty rect of the screen buffer is 00646 * drawn behind the sprite current and previous location. 00647 * Note: Sprite is enabled if sprite.bitmapData is not NULL. Also all enabled sprites must be at the beginning of 00648 * the sprites array. No gaps are allowed in the array. 00649 * @param scrbuf The screen buffer. 00650 * @param updRectX The update rect. 00651 * @param updRectY The update rect. 00652 * @param updRectW The update rect. 00653 * @param updRectH The update rect. 00654 * @param paletteptr The screen palette. 00655 * @param sprites The sprite array. 00656 * @param drawSpritesOnly True, if only sprites are drawn. False, if both sprites and the screen buffer are drawn. 00657 */ 00658 void Pokitto::lcdRefreshMode1Spr( 00659 uint8_t * scrbuf, uint8_t updRectX, uint8_t updRectY, uint8_t updRectW, uint8_t updRectH, uint16_t* paletteptr, 00660 SpriteInfo* sprites, bool drawSpritesOnly) { 00661 00662 // In direct mode draw only sprites and their dirty rects. Return now if there are no sprites 00663 if (drawSpritesOnly && (sprites == NULL || sprites[0].bitmapData == NULL)) 00664 return; 00665 00666 uint16_t x,y; 00667 uint16_t scanline[4][176]; // read 4 half-nibbles (= 4 pixels) at a time 00668 const uint8_t transparentColor = 0; // fixed palette index 0 for transparency 00669 00670 // If not the full screen is updated, check the validity of the update rect. 00671 if ( updRectX != 0 || updRectY != 0 ||updRectW != LCDWIDTH ||updRectH != LCDHEIGHT ) { 00672 uint8_t org_screenx = updRectX; 00673 updRectX &= 0xfc; // Make the value dividable by 4. 00674 updRectW += org_screenx - updRectX; 00675 updRectW = (updRectW + 3) & 0xfc; // Make the value dividable by 4, round up. 00676 00677 uint8_t org_screeny = updRectY; 00678 updRectY &= 0xfc; // Make the value dividable by 4. 00679 updRectH += org_screeny - updRectY; 00680 updRectH = (updRectH + 7) & 0xf8; // Make the value dividable by 8 (because of loop unroll optimization), round up. 00681 } 00682 00683 // Calculate the current amount of sprites 00684 // Note: Sprites must be taken into use from index 0 upwards, because the first sprite with bitmapData==NULL is considered as the last sprite 00685 uint8_t spriteCount = 0; 00686 if (sprites != NULL) 00687 for (;sprites[spriteCount].bitmapData != NULL && spriteCount < SPRITE_COUNT; spriteCount++); 00688 00689 // If drawing the screen buffer, set the start pos to LCD commands only here. 00690 #ifdef PROJ_SHOW_FPS_COUNTER 00691 if (!drawSpritesOnly) setDRAMptr(8, 0); 00692 #else 00693 if (!drawSpritesOnly) setDRAMptr(0, 0); 00694 #endif 00695 00696 //*** GO THROUGH EACH VERTICAL GROUP OF 4 SCANLINES.*** 00697 00698 for (x=0; x<LCDWIDTH; x+=4) { 00699 00700 uint8_t *screenBufScanlineAddr = scrbuf + (x>>2);// point to beginning of line in data 00701 00702 /*Prepare scanline start address for sprites that are visible in this vertical scanline. Sprite width cannot exceed the screen width*/ 00703 uint8_t *sprScanlineAddr[SPRITE_COUNT]; // Sprite start address for the scanline 00704 uint8_t sprScanlineBitshiftMode[SPRITE_COUNT]; // Sprite bitshift mode for the scanline 00705 const uint8_t BITSHIFT_MODE_MIDDLE_BYTE = 0; 00706 const uint8_t BITSHIFT_MODE_FIRST_BYTE = 1; 00707 const uint8_t BITSHIFT_MODE_LAST_BYTE = 2; 00708 uint8_t scanlineMinY = 255; // Init to uninitialized value. Do not draw by default. 00709 uint8_t scanlineMaxY = 0; // Init to uninitialized value. Do not draw by default. 00710 00711 //*** CALCULATE DIRTY RECTS AND RESOLVE WHICH SPRITES BELONG TO THIS SCANLINE GROUP *** 00712 00713 if (sprites != NULL) { 00714 00715 // Check all the sprites for this scanline. That is used for handling the given update rect 00716 // Note that the last round is when (sprindex == spriteCount). That is used to add the screen buffer 00717 // update rect to the dirty rect. 00718 for (int sprindex = 0; sprindex <= spriteCount; sprindex++) { 00719 00720 int16_t sprx, spry, sprOldX, sprOldY; 00721 uint8_t sprw, sprh; 00722 bool isCurrentSpriteOutOfScreen = false; 00723 bool isOldSpriteOutOfScreen = false; 00724 00725 if (sprindex < spriteCount) { 00726 00727 sprx = sprites[sprindex].x; 00728 spry = sprites[sprindex].y; 00729 sprw = sprites[sprindex].w; 00730 sprh = sprites[sprindex].h; 00731 sprOldX = sprites[sprindex].oldx; 00732 sprOldY = sprites[sprindex].oldy; 00733 } 00734 00735 // Handle the screen buffer update rect after all sprites 00736 else if(!drawSpritesOnly){ 00737 00738 sprx = updRectX; 00739 spry = updRectY; 00740 sprw = updRectW; 00741 sprh = updRectH; 00742 sprOldX = updRectX; 00743 sprOldY = updRectY; 00744 isCurrentSpriteOutOfScreen = false; 00745 isOldSpriteOutOfScreen = false; 00746 } 00747 00748 // Check for out-of-screen 00749 if (sprx >= LCDWIDTH || spry >= LCDHEIGHT) 00750 isCurrentSpriteOutOfScreen = true; 00751 if (sprOldX >= LCDWIDTH || sprOldY >= LCDHEIGHT) 00752 isOldSpriteOutOfScreen = true; 00753 00754 // Skip if current and old sprites are out-of-screen 00755 if (isCurrentSpriteOutOfScreen && isOldSpriteOutOfScreen) 00756 continue; 00757 00758 // Detect the dirty rect x-span by combining the previous and current sprite position. 00759 int16_t sprDirtyXMin = avrmin(sprx, sprOldX); 00760 int16_t sprDirtyXMax = avrmax(sprx, sprOldX); 00761 if (isCurrentSpriteOutOfScreen) 00762 sprDirtyXMax = sprOldX; 00763 if (isOldSpriteOutOfScreen) 00764 sprDirtyXMax = sprx; 00765 00766 // Is current x inside the sprite combined dirty rect ? 00767 int16_t sprDirtyXMaxEnd = sprDirtyXMax + sprw - 1 + 4; // Add 4 pixels to dirty rect width (needed?) 00768 if (sprDirtyXMin <= x+3 && x <= sprDirtyXMaxEnd) { 00769 00770 // *** COMBINE DIRTY RECTS FOR THIS SCANLINE GROUP *** 00771 00772 // Dirty rect 00773 int sprDirtyYMin = avrmin(spry, sprOldY); 00774 sprDirtyYMin = avrmax((int)sprDirtyYMin, 0); 00775 int sprDirtyYMax = avrmax(spry, sprOldY); 00776 if (isCurrentSpriteOutOfScreen) 00777 sprDirtyYMax = sprOldY; 00778 if (isOldSpriteOutOfScreen) 00779 sprDirtyYMax = spry; 00780 int sprDirtyYMaxEnd = sprDirtyYMax + sprh - 1; 00781 sprDirtyYMaxEnd = avrmin(sprDirtyYMaxEnd, LCDHEIGHT - 1); // Should use LCDHEIGHT instead of screenH? Same with other screen* ? 00782 00783 // Get the scanline min and max y values for drawing 00784 if (sprDirtyYMin < scanlineMinY) 00785 scanlineMinY = sprDirtyYMin; 00786 if (sprDirtyYMaxEnd > scanlineMaxY) 00787 scanlineMaxY = sprDirtyYMaxEnd; 00788 00789 // *** PREPARE SPRITE FOR DRAWING *** 00790 00791 // Check if the sprite should be active for this vertical scanline group. 00792 if (sprindex < spriteCount && // not for update rect 00793 !isCurrentSpriteOutOfScreen && //out-of-screen 00794 sprx <= x+3 && x < sprx + sprw) { // note: cover group of 4 pixels of the scanline (x+3) 00795 00796 // Find the byte number in the sprite data 00797 int16_t byteNum = ((x+3) - sprx)>>2; 00798 00799 // Get the start addres of the spite data in this scanline. 00800 sprScanlineAddr[sprindex] = const_cast<uint8_t*>(sprites[sprindex].bitmapData + byteNum); 00801 00802 // If the sprite goes over the top, it must be clipped from the top. 00803 if(spry < 0) 00804 sprScanlineAddr[sprindex] += (-spry) * (sprw >> 2); 00805 00806 // Select the bitshift mode for the blit algorithm 00807 if (byteNum == 0) 00808 sprScanlineBitshiftMode[sprindex] = BITSHIFT_MODE_FIRST_BYTE; 00809 else if (byteNum >= (sprw >> 2)) 00810 sprScanlineBitshiftMode[sprindex] = BITSHIFT_MODE_LAST_BYTE; 00811 else 00812 sprScanlineBitshiftMode[sprindex] = BITSHIFT_MODE_MIDDLE_BYTE; 00813 } 00814 else 00815 sprScanlineAddr[sprindex] = NULL; // Deactive sprite for this scanline 00816 } 00817 else 00818 sprScanlineAddr[sprindex] = NULL; // Deactive sprite for this scanline 00819 } 00820 } 00821 00822 // *** ADJUST THE SCANLINE GROUP HEIGHT *** 00823 00824 // The height must dividable by 8. That is needed because later we copy 8 pixels at a time to the LCD. 00825 if (scanlineMaxY - scanlineMinY + 1 > 0) { 00826 uint8_t scanlineH = scanlineMaxY - scanlineMinY + 1; 00827 uint8_t addW = 8 - (scanlineH & 0x7); 00828 00829 // if height is not dividable by 8, make it be. 00830 if (addW != 0) { 00831 if (scanlineMinY > addW ) 00832 scanlineMinY -= addW; 00833 else if( scanlineMaxY + addW < updRectY+updRectH) 00834 scanlineMaxY += addW; 00835 else { 00836 // Draw full height scanline 00837 scanlineMinY = updRectY; 00838 scanlineMaxY = updRectY+updRectH-1; 00839 } 00840 } 00841 } 00842 00843 // *** COMBINE THE SCANLINE GROUP OF THE SCREEN BUFFER AND ALL SPRITES *** 00844 00845 // Find colours in this group of 4 scanlines 00846 screenBufScanlineAddr += (scanlineMinY * 220/4); 00847 for (y=scanlineMinY; y<=scanlineMaxY; y++) 00848 { 00849 // get the screen buffer data first 00850 uint8_t tdata = *screenBufScanlineAddr; 00851 uint8_t t4 = tdata & 0x03; tdata >>= 2;// lowest half-nibble 00852 uint8_t t3 = tdata & 0x03; tdata >>= 2;// second lowest half-nibble 00853 uint8_t t2 = tdata & 0x03; tdata >>= 2;// second highest half-nibble 00854 uint8_t t = tdata & 0x03;// highest half-nibble 00855 00856 // Convert to 16-bit colors in palette 00857 uint16_t p = paletteptr[t]; 00858 uint16_t p2 = paletteptr[t2]; 00859 uint16_t p3 = paletteptr[t3]; 00860 uint16_t p4 = paletteptr[t4]; 00861 00862 #if 0 00863 // Dirty rect visual test 00864 p = COLOR_BLUE >> (Core::frameCount % 5); 00865 p2 = COLOR_BLUE >> (Core::frameCount % 5); 00866 p3 = COLOR_BLUE >> (Core::frameCount % 5); 00867 p4 = COLOR_BLUE >> (Core::frameCount % 5); 00868 #endif 00869 00870 // Add active sprite pixels 00871 if (sprites != NULL) { 00872 00873 // Use loop unrolling for speed optimization 00874 UNROLLED_LOOP_N(SPRITE_COUNT) 00875 } 00876 00877 // put the result nibble values in the scanline 00878 scanline[0][y] = p; 00879 scanline[1][y] = p2; 00880 scanline[2][y] = p3; 00881 scanline[3][y] = p4; 00882 00883 screenBufScanlineAddr += 220>>2; // jump to read byte directly below in screenbuffer 00884 } 00885 00886 // *** DRAW THE SCANLINE GROUP TO LCD 00887 00888 #ifdef PROJ_SHOW_FPS_COUNTER 00889 if (x>=8 && scanlineMaxY - scanlineMinY +1 > 0) { 00890 #else 00891 if (scanlineMaxY - scanlineMinY +1 > 0) { 00892 #endif 00893 // Draw 8 vertical pixels at a time for performance reasons 00894 00895 setDRAMptr(x, scanlineMinY); 00896 for (uint8_t s=scanlineMinY;s<=scanlineMaxY;) { 00897 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 00898 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 00899 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 00900 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 00901 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 00902 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 00903 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 00904 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 00905 } 00906 00907 setDRAMptr(x+1, scanlineMinY); 00908 for (uint8_t s=scanlineMinY;s<=scanlineMaxY;) { 00909 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 00910 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 00911 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 00912 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 00913 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 00914 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 00915 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 00916 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 00917 } 00918 00919 setDRAMptr(x+2, scanlineMinY); 00920 for (uint8_t s=scanlineMinY;s<=scanlineMaxY;) { 00921 setup_data_16(scanline[2][s++]);CLR_WR;SET_WR; 00922 setup_data_16(scanline[2][s++]);CLR_WR;SET_WR; 00923 setup_data_16(scanline[2][s++]);CLR_WR;SET_WR; 00924 setup_data_16(scanline[2][s++]);CLR_WR;SET_WR; 00925 setup_data_16(scanline[2][s++]);CLR_WR;SET_WR; 00926 setup_data_16(scanline[2][s++]);CLR_WR;SET_WR; 00927 setup_data_16(scanline[2][s++]);CLR_WR;SET_WR; 00928 setup_data_16(scanline[2][s++]);CLR_WR;SET_WR; 00929 } 00930 00931 setDRAMptr(x+3, scanlineMinY); 00932 for (uint8_t s=scanlineMinY;s<=scanlineMaxY;) { 00933 setup_data_16(scanline[3][s++]);CLR_WR;SET_WR; 00934 setup_data_16(scanline[3][s++]);CLR_WR;SET_WR; 00935 setup_data_16(scanline[3][s++]);CLR_WR;SET_WR; 00936 setup_data_16(scanline[3][s++]);CLR_WR;SET_WR; 00937 setup_data_16(scanline[3][s++]);CLR_WR;SET_WR; 00938 setup_data_16(scanline[3][s++]);CLR_WR;SET_WR; 00939 setup_data_16(scanline[3][s++]);CLR_WR;SET_WR; 00940 setup_data_16(scanline[3][s++]);CLR_WR;SET_WR; 00941 } 00942 } 00943 } 00944 00945 // Update old x and y for the sprites 00946 if (sprites != NULL) { 00947 for (int sprindex = 0; sprindex < spriteCount; sprindex++) { 00948 sprites[sprindex].oldx = sprites[sprindex].x; 00949 sprites[sprindex].oldy = sprites[sprindex].y; 00950 } 00951 } 00952 00953 #ifdef POK_SIM 00954 simulator.refreshDisplay(); 00955 #endif 00956 } 00957 00958 00959 #define MODE2_INNER_LOOP_B \ 00960 " ldm %[scanline]!, {%[c]}" "\n" \ 00961 " str %[c], [%[LCD], 0]" "\n" \ 00962 " str %[t], [%[LCD], 124]" "\n" \ 00963 " movs %[c], 252" "\n" \ 00964 " str %[t], [%[LCD], %[c]]" "\n" \ 00965 " str %[t], [%[LCD], 124]" "\n" \ 00966 " subs %[x], 1" "\n" \ 00967 " str %[t], [%[LCD], %[c]]" "\n" \ 00968 00969 00970 void Pokitto::lcdRefreshMode2(uint8_t * scrbuf, uint16_t* paletteptr ) { 00971 uint32_t x,y; 00972 uint32_t scanline[110]; 00973 00974 write_command(0x03); write_data(0x1038); 00975 write_command(0x20); // Horizontal DRAM Address 00976 write_data(0); // 0 00977 write_command(0x21); // Vertical DRAM Address 00978 write_data(1); 00979 write_command(0x22); // write data to DRAM 00980 CLR_CS_SET_CD_RD_WR; 00981 SET_MASK_P2; 00982 00983 #ifndef __ARMCC_VERSION 00984 asm volatile( 00985 ".syntax unified" "\n" 00986 00987 "mov r10, %[scanline]" "\n" 00988 "mov r11, %[t]" "\n" 00989 00990 "mode2OuterLoop:" "\n" 00991 00992 "movs %[x], 110" "\n" 00993 "mode2InnerLoopA:" 00994 00995 00996 " ldrb %[byte], [%[scrbuf],0]" "\n" 00997 " lsrs %[c], %[byte], 4" "\n" 00998 00999 " movs %[t], 15" "\n" 01000 " ands %[byte], %[t]" "\n" 01001 01002 " lsls %[c], 1" "\n" 01003 " ldrh %[t], [%[paletteptr], %[c]]" "\n" 01004 " lsls %[t], %[t], 3" "\n" 01005 " str %[t], [%[LCD], 0]" "\n" 01006 " mov %[c], r11" "\n" 01007 " str %[c], [%[LCD], 124]" "\n" 01008 " stm %[scanline]!, {%[t]}" "\n" 01009 " movs %[t], 252" "\n" 01010 " str %[c], [%[LCD], %[t]]" "\n" 01011 " str %[c], [%[LCD], 124]" "\n" 01012 " lsls %[byte], %[byte], 1" "\n" 01013 " str %[c], [%[LCD], %[t]]" "\n" 01014 01015 " ldrh %[t], [%[paletteptr], %[byte]]" "\n" 01016 " lsls %[t], %[t], 3" "\n" 01017 " str %[t], [%[LCD], 0]" "\n" 01018 " mov %[c], r11" "\n" 01019 " str %[c], [%[LCD], 124]" "\n" 01020 " stm %[scanline]!, {%[t]}" "\n" 01021 " movs %[t], 252" "\n" 01022 " str %[c], [%[LCD], %[t]]" "\n" 01023 " str %[c], [%[LCD], 124]" "\n" 01024 " adds %[scrbuf], %[scrbuf], 1" "\n" 01025 " str %[c], [%[LCD], %[t]]" "\n" 01026 01027 " subs %[x], 2" "\n" 01028 " bne mode2InnerLoopA" "\n" 01029 01030 "mov %[scanline], r10" "\n" 01031 "movs %[x], 110" "\n" 01032 "mov %[t], r11" "\n" 01033 "mode2InnerLoopB:" 01034 MODE2_INNER_LOOP_B 01035 MODE2_INNER_LOOP_B 01036 MODE2_INNER_LOOP_B 01037 MODE2_INNER_LOOP_B 01038 MODE2_INNER_LOOP_B 01039 MODE2_INNER_LOOP_B 01040 MODE2_INNER_LOOP_B 01041 MODE2_INNER_LOOP_B 01042 MODE2_INNER_LOOP_B 01043 MODE2_INNER_LOOP_B 01044 " bne mode2InnerLoopB" "\n" 01045 01046 "mov %[scanline], r10" "\n" 01047 "movs %[t], 1" "\n" 01048 "movs %[c], 88" "\n" 01049 "add %[y], %[t]" "\n" // y++... derpy, but it's the outer loop 01050 "cmp %[y], %[c]" "\n" 01051 "bne mode2OuterLoop" "\n" // if y != 88, loop 01052 01053 : // outputs 01054 [c]"+l" (c), 01055 [t]"+l" (t), 01056 [x]"+l" (x), 01057 [y]"+h" (y), // +:Read-Write l:lower (0-7) register 01058 [scrbuf]"+l" (scrbuf) 01059 01060 : // inputs 01061 [LCD]"l" (0xA0002188), 01062 [scanline]"l" (scanline), 01063 [paletteptr]"l" (paletteptr), 01064 [byte]"l" (byte) 01065 : // clobbers 01066 "cc", "r10", "r11" 01067 ); 01068 01069 01070 #else 01071 uint8_t* d = scrbuf;// point to beginning of line in data 01072 01073 #ifdef PROJ_SHOW_FPS_COUNTER 01074 setDRAMptr(0, 8); 01075 wait_us(200); // Add wait to compensate skipping of 8 lines. Makes FPS counter to show the correct value. 01076 for(y=4;y<88;y++) 01077 #else 01078 for(y=0;y<88;y++) 01079 #endif 01080 { 01081 01082 01083 uint8_t s=0; 01084 for(x=0;x<110;x+=2) 01085 { 01086 uint8_t t = *d++; 01087 uint32_t color; 01088 color = uint32_t(paletteptr[t>>4])<<3; 01089 scanline[s]=*LCD=color;TGL_WR_OP(s++);TGL_WR; 01090 color = uint32_t(paletteptr[t&0xF])<<3; 01091 scanline[s]=*LCD=color;TGL_WR_OP(s++);TGL_WR; 01092 } 01093 01094 s=0; 01095 for (s=0;s<110;) { 01096 *LCD = (scanline[s]);TGL_WR_OP(s++);TGL_WR; 01097 *LCD = (scanline[s]);TGL_WR_OP(s++);TGL_WR; 01098 *LCD = (scanline[s]);TGL_WR_OP(s++);TGL_WR; 01099 *LCD = (scanline[s]);TGL_WR_OP(s++);TGL_WR; 01100 *LCD = (scanline[s]);TGL_WR_OP(s++);TGL_WR; 01101 *LCD = (scanline[s]);TGL_WR_OP(s++);TGL_WR; 01102 *LCD = (scanline[s]);TGL_WR_OP(s++);TGL_WR; 01103 *LCD = (scanline[s]);TGL_WR_OP(s++);TGL_WR; 01104 *LCD = (scanline[s]);TGL_WR_OP(s++);TGL_WR; 01105 *LCD = (scanline[s]);TGL_WR_OP(s++);TGL_WR; 01106 } 01107 01108 } 01109 #endif 01110 01111 CLR_MASK_P2; 01112 } 01113 01114 void Pokitto::lcdRefreshMode3(uint8_t * scrbuf, uint16_t* paletteptr) { 01115 uint16_t x,y; 01116 uint16_t scanline[2][176]; // read two nibbles = pixels at a time 01117 uint8_t *d; 01118 01119 write_command(0x20); // Horizontal DRAM Address 01120 write_data(0); // 0 01121 write_command(0x21); // Vertical DRAM Address 01122 write_data(0); 01123 write_command(0x22); // write data to DRAM 01124 CLR_CS_SET_CD_RD_WR; 01125 01126 for(x=0;x<220;x+=2) 01127 { 01128 d = scrbuf+(x>>1);// point to beginning of line in data 01129 /** find colours in one scanline **/ 01130 uint8_t s=0; 01131 for(y=0;y<176;y++) 01132 { 01133 uint8_t t = *d >> 4; // higher nibble 01134 uint8_t t2 = *d & 0xF; // lower nibble 01135 /** higher nibble = left pixel in pixel pair **/ 01136 scanline[0][s] = paletteptr[t]; 01137 scanline[1][s++] = paletteptr[t2]; 01138 /** testing only **/ 01139 //scanline[0][s] = 0xFFFF*(s&1); 01140 //scanline[1][s] = 0xFFFF*(!(s&1)); 01141 //s++; 01142 /** until here **/ 01143 d+=220/2; // jump to read byte directly below in screenbuffer 01144 } 01145 s=0; 01146 /** draw scanlines **/ 01147 /** leftmost scanline**/ 01148 01149 #ifdef PROJ_SHOW_FPS_COUNTER 01150 if (x<8) continue; 01151 setDRAMptr(x, 0); 01152 #endif 01153 01154 for (s=0;s<176;) { 01155 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 01156 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 01157 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 01158 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 01159 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 01160 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 01161 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 01162 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 01163 } 01164 01165 /** rightmost scanline**/ 01166 //setDRAMptr(xptr++,yoffset); 01167 for (s=0;s<176;) { 01168 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 01169 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 01170 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 01171 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 01172 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 01173 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 01174 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 01175 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 01176 } 01177 } 01178 } 01179 01180 void Pokitto::lcdRefreshGB(uint8_t * scrbuf, uint16_t* paletteptr) { 01181 uint16_t x,y; 01182 uint16_t scanline[48]; 01183 uint8_t * d; 01184 01185 #if POK_STRETCH 01186 //uint16_t xptr = 8; 01187 #else 01188 //xptr = 26; 01189 #endif 01190 01191 write_command(0x20); // Horizontal DRAM Address 01192 write_data(0); // 0 01193 write_command(0x21); // Vertical DRAM Address 01194 write_data(0); 01195 write_command(0x22); // write data to DRAM 01196 CLR_CS_SET_CD_RD_WR; 01197 01198 /** draw border **/ 01199 for (int s=0;s<5*176;) { 01200 setup_data_16(COLOR_BLACK);CLR_WR;SET_WR;s++; 01201 } 01202 01203 for(x=0;x<84;x++) 01204 { 01205 01206 d = scrbuf + x;// point to beginning of line in data 01207 01208 /** find colours in one scanline **/ 01209 uint8_t s=0; 01210 for(y=0;y<6;y++) 01211 { 01212 uint8_t t = *d; 01213 #if POK_COLORDEPTH > 1 01214 uint8_t t2 = *(d+504); 01215 #endif 01216 #if POK_COLORDEPTH > 2 01217 uint8_t t3 = *(d+504+504); 01218 #endif 01219 #if POK_COLORDEPTH > 3 01220 uint8_t t4 = *(d+504+504+504); 01221 #endif 01222 uint8_t paletteindex = 0; 01223 01224 /** bit 1 **/ 01225 #if POK_COLORDEPTH == 1 01226 paletteindex = (t & 0x1); 01227 #elif POK_COLORDEPTH == 2 01228 paletteindex = ((t & 0x1)) | ((t2 & 0x01)<<1); 01229 #elif POK_COLORDEPTH == 3 01230 paletteindex = (t & 0x1) | ((t2 & 0x1)<<1) | ((t3 & 0x1)<<2); 01231 #elif POK_COLORDEPTH == 4 01232 paletteindex = (t & 0x1) | ((t2 & 0x1)<<1) | ((t3 & 0x1)<<2) | ((t4 & 0x1)<<3); 01233 #endif 01234 scanline[s++] = paletteptr[paletteindex]; 01235 01236 /** bit 2 **/ 01237 #if POK_COLORDEPTH == 1 01238 paletteindex = (t & 0x2)>>1; 01239 #elif POK_COLORDEPTH == 2 01240 paletteindex = ((t & 0x2)>>1) | ((t2 & 0x02)); 01241 #elif POK_COLORDEPTH == 3 01242 paletteindex = ((t & 0x2)>>1) | ((t2 & 0x2)) | ((t3 & 0x2)<<1); 01243 #elif POK_COLORDEPTH == 4 01244 paletteindex = ((t & 0x2)>>1) | ((t2 & 0x2)) | ((t3 & 0x2)<<1) | ((t4 & 0x2)<<2); 01245 #endif 01246 scanline[s++] = paletteptr[paletteindex]; 01247 01248 /** bit 3 **/ 01249 #if POK_COLORDEPTH == 1 01250 paletteindex = (t & 0x4)>>2; 01251 #elif POK_COLORDEPTH == 2 01252 paletteindex = ((t & 4)>>2) | ((t2 & 0x04)>>1); 01253 #elif POK_COLORDEPTH == 3 01254 paletteindex = ((t & 0x4)>>2) | ((t2 & 0x4)>>1) | (t3 & 0x4); 01255 #elif POK_COLORDEPTH == 4 01256 paletteindex = ((t & 0x4)>>2) | ((t2 & 0x4)>>1) | (t3 & 0x4) | ((t4 & 0x4)<<1); 01257 #endif 01258 scanline[s++] = paletteptr[paletteindex]; 01259 01260 /** bit 4 **/ 01261 #if POK_COLORDEPTH == 1 01262 paletteindex = (t & 0x8)>>3; 01263 #elif POK_COLORDEPTH == 2 01264 paletteindex = ((t & 0x8)>>3) | ((t2 & 0x08)>>2); 01265 #elif POK_COLORDEPTH == 3 01266 paletteindex = ((t & 0x8)>>3) | ((t2 & 0x8)>>2) | ((t3 & 0x8)>>1); 01267 #elif POK_COLORDEPTH == 4 01268 paletteindex = ((t & 0x8)>>3) | ((t2 & 0x8)>>2) | ((t3 & 0x8)>>1) | (t4 & 0x8); 01269 #endif 01270 scanline[s++] = paletteptr[paletteindex]; 01271 01272 /** bit 5 **/ 01273 #if POK_COLORDEPTH == 1 01274 paletteindex = (t & 0x10)>>4; 01275 #elif POK_COLORDEPTH == 2 01276 paletteindex = ((t & 0x10)>>4) | ((t2 & 0x10)>>3); 01277 #elif POK_COLORDEPTH == 3 01278 paletteindex = ((t & 0x10)>>4) | ((t2 & 0x10)>>3) | ((t3 & 0x10)>>2); 01279 #elif POK_COLORDEPTH == 4 01280 paletteindex = ((t & 0x10)>>4) | ((t2 & 0x10)>>3) | ((t3 & 0x10)>>2) | ((t4 & 0x10)>>1); 01281 #endif 01282 scanline[s++] = paletteptr[paletteindex]; 01283 01284 /** bit 6 **/ 01285 #if POK_COLORDEPTH == 1 01286 paletteindex = (t & 0x20)>>5; 01287 #elif POK_COLORDEPTH == 2 01288 paletteindex = ((t & 0x20)>>5) | ((t2 & 0x20)>>4); 01289 #elif POK_COLORDEPTH == 3 01290 paletteindex = ((t & 0x20)>>5) | ((t2 & 0x20)>>4) | ((t3 & 0x20)>>3); 01291 #elif POK_COLORDEPTH == 4 01292 paletteindex = ((t & 0x20)>>5) | ((t2 & 0x20)>>4) | ((t3 & 0x20)>>3) | ((t4 & 0x20)>>2); 01293 #endif 01294 scanline[s++] = paletteptr[paletteindex]; 01295 01296 /** bit 7 **/ 01297 #if POK_COLORDEPTH == 1 01298 paletteindex = (t & 0x40)>>6; 01299 #elif POK_COLORDEPTH == 2 01300 paletteindex = ((t & 0x40)>>6) | ((t2 & 0x40)>>5); 01301 #elif POK_COLORDEPTH == 3 01302 paletteindex = ((t & 0x40)>>6) | ((t2 & 0x40)>>5) | ((t3 & 0x40)>>4) ; 01303 #elif POK_COLORDEPTH == 4 01304 paletteindex = ((t & 0x40)>>6) | ((t2 & 0x40)>>5) | ((t3 & 0x40)>>4) | ((t4 & 0x40)>>3); 01305 #endif 01306 scanline[s++] = paletteptr[paletteindex]; 01307 01308 /** bit 8 **/ 01309 #if POK_COLORDEPTH == 1 01310 paletteindex = (t & 0x80)>>7; 01311 #elif POK_COLORDEPTH == 2 01312 paletteindex = ((t & 0x80)>>7) | ((t2 & 0x80)>>6); 01313 #elif POK_COLORDEPTH == 3 01314 paletteindex = ((t & 0x80)>>7) | ((t2 & 0x80)>>6) | ((t3 & 0x80)>>5); 01315 #elif POK_COLORDEPTH == 4 01316 paletteindex = ((t & 0x80)>>7) | ((t2 & 0x80)>>6) | ((t3 & 0x80)>>5) | ((t4 & 0x80)>>4); 01317 #endif 01318 scanline[s++] = paletteptr[paletteindex]; 01319 01320 d+=84; // jump to byte directly below 01321 } 01322 01323 01324 /*write_command(0x20); // Horizontal DRAM Address 01325 write_data(0x10); // 0 01326 write_command(0x21); // Vertical DRAM Address 01327 write_data(xptr++); 01328 write_command(0x22); // write data to DRAM 01329 CLR_CS_SET_CD_RD_WR;*/ 01330 /** draw border **/ 01331 setup_data_16(COLOR_BLACK);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01332 01333 s=0; 01334 01335 /** draw scanlines **/ 01336 for (s=0;s<48;) { 01337 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01338 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01339 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01340 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01341 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01342 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01343 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01344 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01345 } 01346 /** draw border **/ 01347 setup_data_16(COLOR_BLACK);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01348 01349 01350 /*write_command(0x20); // Horizontal DRAM Address 01351 write_data(0x10); // 0 01352 write_command(0x21); // Vertical DRAM Address 01353 write_data(xptr++); 01354 write_command(0x22); // write data to DRAM 01355 CLR_CS_SET_CD_RD_WR;*/ 01356 /** draw border **/ 01357 setup_data_16(COLOR_BLACK);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01358 01359 for (s=0;s<48;) { 01360 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01361 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01362 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01363 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01364 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01365 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01366 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01367 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01368 } 01369 01370 /** draw border **/ 01371 setup_data_16(COLOR_BLACK);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01372 01373 01374 #if POK_STRETCH 01375 //if (x>16 && x<68) 01376 if (x&2)// && x&2) 01377 { 01378 /*write_command(0x20); // Horizontal DRAM Address 01379 write_data(0x10); // 0 01380 write_command(0x21); // Vertical DRAM Address 01381 write_data(xptr++); 01382 write_command(0x22); // write data to DRAM 01383 CLR_CS_SET_CD_RD_WR;*/ 01384 /** draw border **/ 01385 setup_data_16(COLOR_BLACK);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01386 01387 01388 for (s=0;s<48;) { 01389 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01390 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01391 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01392 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01393 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01394 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01395 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01396 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01397 } 01398 01399 /** draw border **/ 01400 setup_data_16(COLOR_BLACK);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR; 01401 01402 } 01403 #endif 01404 } 01405 /** draw border **/ 01406 for (int s=0;s<5*176;) { 01407 setup_data_16(COLOR_BLACK);CLR_WR;SET_WR;s++; 01408 } 01409 } 01410 01411 01412 void Pokitto::lcdRefreshAB(uint8_t * scrbuf, uint16_t* paletteptr) { 01413 uint16_t x,y; 01414 uint16_t scanline[64]; 01415 uint8_t *d; 01416 //lcdClear(); 01417 #if POK_STRETCH 01418 uint16_t xptr = 14; 01419 uint8_t yoffset = 24; 01420 #else 01421 uint16_t xptr = 0; 01422 uint8_t yoffset = 0; 01423 #endif 01424 01425 for(x=0;x<128;x++) 01426 { 01427 write_command(0x20); // Horizontal DRAM Address 01428 write_data(yoffset); // 0 01429 write_command(0x21); // Vertical DRAM Address 01430 write_data(xptr++); 01431 write_command(0x22); // write data to DRAM 01432 CLR_CS_SET_CD_RD_WR; 01433 //setDRAMptr(xptr++,yoffset); 01434 01435 d = scrbuf + x;// point to beginning of line in data 01436 01437 /** find colours in one scanline **/ 01438 uint8_t s=0; 01439 for(y=0;y<8;y++) 01440 { 01441 uint8_t t = *d; 01442 #if POK_COLORDEPTH > 1 01443 uint8_t t2 = *(d+AB_JUMP); 01444 #endif // POK_COLORDEPTH 01445 #if POK_COLORDEPTH > 2 01446 uint8_t t3 = *(d+AB_JUMP+AB_JUMP); 01447 #endif // POK_COLORDEPTH 01448 #if POK_COLORDEPTH > 3 01449 uint8_t t4 = *(d+AB_JUMP+AB_JUMP+AB_JUMP); 01450 #endif // POK_COLORDEPTH 01451 uint8_t paletteindex = 0; 01452 01453 /** bit 1 **/ 01454 #if POK_COLORDEPTH == 1 01455 paletteindex = (t & 0x1); 01456 #elif POK_COLORDEPTH == 2 01457 paletteindex = ((t & 0x1)) | ((t2 & 0x01)<<1); 01458 #elif POK_COLORDEPTH == 3 01459 paletteindex = (t & 0x1) | ((t2 & 0x1)<<1) | ((t3 & 0x1)<<2); 01460 #elif POK_COLORDEPTH == 4 01461 paletteindex = (t & 0x1) | ((t2 & 0x1)<<1) | ((t3 & 0x1)<<2) | ((t4 & 0x1)<<3); 01462 #endif 01463 scanline[s++] = paletteptr[paletteindex]; 01464 01465 /** bit 2 **/ 01466 #if POK_COLORDEPTH == 1 01467 paletteindex = (t & 0x2)>>1; 01468 #elif POK_COLORDEPTH == 2 01469 paletteindex = ((t & 0x2)>>1) | ((t2 & 0x02)); 01470 #elif POK_COLORDEPTH == 3 01471 paletteindex = ((t & 0x2)>>1) | ((t2 & 0x2)) | ((t3 & 0x2)<<1); 01472 #elif POK_COLORDEPTH == 4 01473 paletteindex = ((t & 0x2)>>1) | ((t2 & 0x2)) | ((t3 & 0x2)<<1) | ((t4 & 0x2)<<2); 01474 #endif 01475 scanline[s++] = paletteptr[paletteindex]; 01476 01477 /** bit 3 **/ 01478 #if POK_COLORDEPTH == 1 01479 paletteindex = (t & 0x4)>>2; 01480 #elif POK_COLORDEPTH == 2 01481 paletteindex = ((t & 4)>>2) | ((t2 & 0x04)>>1); 01482 #elif POK_COLORDEPTH == 3 01483 paletteindex = ((t & 0x4)>>2) | ((t2 & 0x4)>>1) | (t3 & 0x4); 01484 #elif POK_COLORDEPTH == 4 01485 paletteindex = ((t & 0x4)>>2) | ((t2 & 0x4)>>1) | (t3 & 0x4) | ((t4 & 0x4)<<1); 01486 #endif 01487 scanline[s++] = paletteptr[paletteindex]; 01488 01489 /** bit 4 **/ 01490 #if POK_COLORDEPTH == 1 01491 paletteindex = (t & 0x8)>>3; 01492 #elif POK_COLORDEPTH == 2 01493 paletteindex = ((t & 0x8)>>3) | ((t2 & 0x08)>>2); 01494 #elif POK_COLORDEPTH == 3 01495 paletteindex = ((t & 0x8)>>3) | ((t2 & 0x8)>>2) | ((t3 & 0x8)>>1); 01496 #elif POK_COLORDEPTH == 4 01497 paletteindex = ((t & 0x8)>>3) | ((t2 & 0x8)>>2) | ((t3 & 0x8)>>1) | (t4 & 0x8); 01498 #endif 01499 scanline[s++] = paletteptr[paletteindex]; 01500 01501 /** bit 5 **/ 01502 #if POK_COLORDEPTH == 1 01503 paletteindex = (t & 0x10)>>4; 01504 #elif POK_COLORDEPTH == 2 01505 paletteindex = ((t & 0x10)>>4) | ((t2 & 0x10)>>3); 01506 #elif POK_COLORDEPTH == 3 01507 paletteindex = ((t & 0x10)>>4) | ((t2 & 0x10)>>3) | ((t3 & 0x10)>>2); 01508 #elif POK_COLORDEPTH == 4 01509 paletteindex = ((t & 0x10)>>4) | ((t2 & 0x10)>>3) | ((t3 & 0x10)>>2) | ((t4 & 0x10)>>1); 01510 #endif 01511 scanline[s++] = paletteptr[paletteindex]; 01512 01513 /** bit 6 **/ 01514 #if POK_COLORDEPTH == 1 01515 paletteindex = (t & 0x20)>>5; 01516 #elif POK_COLORDEPTH == 2 01517 paletteindex = ((t & 0x20)>>5) | ((t2 & 0x20)>>4); 01518 #elif POK_COLORDEPTH == 3 01519 paletteindex = ((t & 0x20)>>5) | ((t2 & 0x20)>>4) | ((t3 & 0x20)>>3); 01520 #elif POK_COLORDEPTH == 4 01521 paletteindex = ((t & 0x20)>>5) | ((t2 & 0x20)>>4) | ((t3 & 0x20)>>3) | ((t4 & 0x20)>>2); 01522 #endif 01523 scanline[s++] = paletteptr[paletteindex]; 01524 01525 /** bit 7 **/ 01526 #if POK_COLORDEPTH == 1 01527 paletteindex = (t & 0x40)>>6; 01528 #elif POK_COLORDEPTH == 2 01529 paletteindex = ((t & 0x40)>>6) | ((t2 & 0x40)>>5); 01530 #elif POK_COLORDEPTH == 3 01531 paletteindex = ((t & 0x40)>>6) | ((t2 & 0x40)>>5) | ((t3 & 0x40)>>4) ; 01532 #elif POK_COLORDEPTH == 4 01533 paletteindex = ((t & 0x40)>>6) | ((t2 & 0x40)>>5) | ((t3 & 0x40)>>4) | ((t4 & 0x40)>>3); 01534 #endif 01535 scanline[s++] = paletteptr[paletteindex]; 01536 01537 /** bit 8 **/ 01538 #if POK_COLORDEPTH == 1 01539 paletteindex = (t & 0x80)>>7; 01540 #elif POK_COLORDEPTH == 2 01541 paletteindex = ((t & 0x80)>>7) | ((t2 & 0x80)>>6); 01542 #elif POK_COLORDEPTH == 3 01543 paletteindex = ((t & 0x80)>>7) | ((t2 & 0x80)>>6) | ((t3 & 0x80)>>5); 01544 #elif POK_COLORDEPTH == 4 01545 paletteindex = ((t & 0x80)>>7) | ((t2 & 0x80)>>6) | ((t3 & 0x80)>>5) | ((t4 & 0x80)>>4); 01546 #endif 01547 scanline[s++] = paletteptr[paletteindex]; 01548 01549 d+=128; // jump to byte directly below 01550 } 01551 01552 s=0; 01553 01554 /** draw scanlines **/ 01555 for (s=0;s<64;) { 01556 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR; 01557 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR; 01558 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR; 01559 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR; 01560 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR; 01561 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR; 01562 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR; 01563 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR; 01564 } 01565 01566 #if POK_STRETCH 01567 if (x&1) { 01568 write_command(0x20); // Horizontal DRAM Address 01569 write_data(yoffset); // 0 01570 write_command(0x21); // Vertical DRAM Address 01571 write_data(xptr++); 01572 write_command(0x22); // write data to DRAM 01573 CLR_CS_SET_CD_RD_WR; 01574 //setDRAMptr(xptr++,yoffset); 01575 01576 for (s=0;s<64;) { 01577 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR; 01578 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR; 01579 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR; 01580 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR; 01581 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR; 01582 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR; 01583 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR; 01584 setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR; 01585 } 01586 } 01587 #endif 01588 } 01589 } 01590 01591 void Pokitto::lcdRefreshModeGBC(uint8_t * scrbuf, uint16_t* paletteptr) { 01592 uint16_t x,y,xptr; 01593 uint16_t scanline[4][144]; // read 4 half-nibbles = 4 pixels at a time 01594 uint8_t *d, yoffset=0; 01595 01596 xptr = 0; 01597 setDRAMptr(xptr,yoffset); 01598 01599 01600 for(x=0;x<160;x+=4) 01601 { 01602 d = scrbuf+(x>>2);// point to beginning of line in data 01603 /** find colours in one scanline **/ 01604 uint8_t s=0; 01605 for(y=0;y<144;y++) 01606 { 01607 uint8_t tdata = *d; 01608 uint8_t t4 = tdata & 0x03; tdata >>= 2;// lowest half-nibble 01609 uint8_t t3 = tdata & 0x03; tdata >>= 2;// second lowest half-nibble 01610 uint8_t t2 = tdata & 0x03; tdata >>= 2;// second highest half-nibble 01611 uint8_t t = tdata & 0x03;// highest half-nibble 01612 01613 /** put nibble values in the scanlines **/ 01614 01615 scanline[0][s] = paletteptr[t]; 01616 scanline[1][s] = paletteptr[t2]; 01617 scanline[2][s] = paletteptr[t3]; 01618 scanline[3][s++] = paletteptr[t4]; 01619 01620 d+=160/4; // jump to read byte directly below in screenbuffer 01621 } 01622 01623 s=0; 01624 /** draw scanlines **/ 01625 for (s=0;s<144;) { 01626 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 01627 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 01628 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 01629 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 01630 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 01631 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 01632 } 01633 setDRAMptr(++xptr,yoffset); 01634 for (s=0;s<144;) { 01635 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 01636 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 01637 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 01638 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 01639 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 01640 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 01641 } 01642 setDRAMptr(++xptr,yoffset); 01643 for (s=0;s<144;) { 01644 setup_data_16(scanline[2][s++]);CLR_WR;SET_WR; 01645 setup_data_16(scanline[2][s++]);CLR_WR;SET_WR; 01646 setup_data_16(scanline[2][s++]);CLR_WR;SET_WR; 01647 setup_data_16(scanline[2][s++]);CLR_WR;SET_WR; 01648 setup_data_16(scanline[2][s++]);CLR_WR;SET_WR; 01649 setup_data_16(scanline[2][s++]);CLR_WR;SET_WR; 01650 } 01651 setDRAMptr(++xptr,yoffset); 01652 for (s=0;s<144;) { 01653 setup_data_16(scanline[3][s++]);CLR_WR;SET_WR; 01654 setup_data_16(scanline[3][s++]);CLR_WR;SET_WR; 01655 setup_data_16(scanline[3][s++]);CLR_WR;SET_WR; 01656 setup_data_16(scanline[3][s++]);CLR_WR;SET_WR; 01657 setup_data_16(scanline[3][s++]);CLR_WR;SET_WR; 01658 setup_data_16(scanline[3][s++]);CLR_WR;SET_WR; 01659 } 01660 setDRAMptr(++xptr,yoffset); 01661 } 01662 } 01663 01664 01665 void Pokitto::lcdRefreshT1(uint8_t* tilebuf, uint8_t* tilecolorbuf, uint8_t* tileset, uint16_t* paletteptr) { 01666 #ifdef POK_TILEMODE 01667 uint16_t x,y,data,xptr; 01668 uint16_t scanline[176]; 01669 uint8_t yoffset=0, tilebyte, tileindex, tilex=0, tiley=0,xcount; 01670 01671 01672 if (!tileset) return; 01673 01674 #if LCDWIDTH < POK_LCD_W 01675 xptr = (POK_LCD_W-LCDWIDTH)/2; 01676 #else 01677 xptr = 0; 01678 #endif 01679 #if LCDHEIGHT < POK_LCD_H 01680 yoffset = (POK_LCD_H-LCDHEIGHT)/2; 01681 #else 01682 yoffset = 0; 01683 #endif 01684 01685 for(x=0, xcount=0 ;x<LCDWIDTH;x++,xcount++) // loop through vertical columns 01686 { 01687 setDRAMptr(xptr++,yoffset); //point to VRAM 01688 01689 /** find colours in one scanline **/ 01690 uint8_t s=0, tiley=0; 01691 //tileindex = tilebuf[tilex*POK_TILES_Y]; 01692 if (xcount==POK_TILE_W) { 01693 tilex++; 01694 xcount=0; 01695 } 01696 01697 for(y=0;y<LCDHEIGHT;) 01698 { 01699 uint8_t tileval = tilebuf[tilex+tiley*POK_TILES_X]; //get tile number 01700 uint16_t index = tileval*POK_TILE_W+xcount; 01701 uint8_t tilebyte = tileset[index]; //get bitmap data 01702 for (uint8_t ycount=0, bitcount=0; ycount<POK_TILE_H; ycount++, y++, bitcount++) { 01703 if (bitcount==8) { 01704 bitcount=0; 01705 index += 176; //jump to byte below in the tileset bitmap 01706 tilebyte = tileset[index]; //get bitmap data 01707 } 01708 //tilebyte = tile[(tileindex>>4)+*POK_TILE_W]; //tilemaps are 16x16 01709 //uint8_t paletteindex = ((tilebyte>>(bitcount&0x7)) & 0x1); 01710 if (!tileval) scanline[s++] = COLOR_MAGENTA*((tilebyte>>bitcount)&0x1);//paletteptr[paletteindex]; 01711 else scanline[s++] = paletteptr[((tilebyte>>bitcount)&0x1)*tileval];//paletteptr[paletteindex]; 01712 } 01713 tiley++; //move to next tile 01714 } 01715 s=0; 01716 01717 /** draw scanlines **/ 01718 for (s=0;s<LCDHEIGHT;) { 01719 setup_data_16(scanline[s++]);CLR_WR;SET_WR; 01720 } 01721 } 01722 #endif 01723 } 01724 01725 #define MODE13_INNER_LOOP_A \ 01726 " ldrb %[t], [%[scrbuf],0]" "\n" \ 01727 " add %[t], %[t], %[offset]" "\n" \ 01728 " uxtb %[c], %[t] " "\n" \ 01729 " lsls %[c], 1" "\n" \ 01730 " ldrh %[t], [%[paletteptr], %[c]]" "\n" \ 01731 " lsls %[t], %[t], 3" "\n" \ 01732 " str %[t], [%[LCD], 0]" "\n" \ 01733 " mov %[c], r11" "\n" \ 01734 " str %[c], [%[LCD], 124]" "\n" \ 01735 " stm %[scanline]!, {%[t]}" "\n" \ 01736 " movs %[t], 252" "\n" \ 01737 " str %[c], [%[LCD], %[t]]" "\n" \ 01738 " str %[c], [%[LCD], 124]" "\n" \ 01739 " adds %[scrbuf], %[scrbuf], 1" "\n" \ 01740 " str %[c], [%[LCD], %[t]]" "\n" 01741 01742 #define MODE13_INNER_LOOP_B \ 01743 " ldm %[scanline]!, {%[c]}" "\n" \ 01744 " str %[c], [%[LCD], 0]" "\n" \ 01745 " str %[t], [%[LCD], 124]" "\n" \ 01746 " movs %[c], 252" "\n" \ 01747 " str %[t], [%[LCD], %[c]]" "\n" \ 01748 " str %[t], [%[LCD], 124]" "\n" \ 01749 " subs %[x], 1" "\n" \ 01750 " str %[t], [%[LCD], %[c]]" "\n" \ 01751 01752 01753 void Pokitto::lcdRefreshMode13(uint8_t * scrbuf, uint16_t* paletteptr, uint8_t offset){ 01754 uint32_t scanline[110]; // read two nibbles = pixels at a time 01755 01756 write_command_16(0x03); write_data_16(0x1038); 01757 write_command(0x20); write_data(0); 01758 write_command(0x21); write_data(1); 01759 write_command(0x22); 01760 CLR_CS_SET_CD_RD_WR; 01761 SET_MASK_P2; 01762 01763 uint32_t x, y=0; 01764 01765 #ifndef __ARMCC_VERSION 01766 asm volatile( 01767 ".syntax unified" "\n" 01768 01769 "mov r10, %[scanline]" "\n" 01770 01771 "movs %[t], 1" "\n" 01772 "lsls %[t], %[t], 12" "\n" 01773 "mov r11, %[t]" "\n" 01774 01775 "mode13OuterLoop:" "\n" 01776 01777 "movs %[x], 110" "\n" 01778 "mode13InnerLoopA:" 01779 MODE13_INNER_LOOP_A 01780 MODE13_INNER_LOOP_A 01781 " subs %[x], 2" "\n" 01782 " bne mode13InnerLoopA" "\n" 01783 01784 "mov %[scanline], r10" "\n" 01785 "movs %[x], 110" "\n" 01786 "mov %[t], r11" "\n" 01787 "mode13InnerLoopB:" 01788 MODE13_INNER_LOOP_B 01789 MODE13_INNER_LOOP_B 01790 MODE13_INNER_LOOP_B 01791 MODE13_INNER_LOOP_B 01792 MODE13_INNER_LOOP_B 01793 MODE13_INNER_LOOP_B 01794 MODE13_INNER_LOOP_B 01795 MODE13_INNER_LOOP_B 01796 MODE13_INNER_LOOP_B 01797 MODE13_INNER_LOOP_B 01798 " bne mode13InnerLoopB" "\n" 01799 01800 "mov %[scanline], r10" "\n" 01801 "movs %[t], 1" "\n" 01802 "movs %[c], 88" "\n" 01803 "add %[y], %[t]" "\n" // y++... derpy, but it's the outer loop 01804 "cmp %[y], %[c]" "\n" 01805 "bne mode13OuterLoop" "\n" // if y != 88, loop 01806 01807 : // outputs 01808 [c]"+l" (c), 01809 [t]"+l" (t), 01810 [x]"+l" (x), 01811 [y]"+h" (y), // +:Read-Write l:lower (0-7) register 01812 [scrbuf]"+l" (scrbuf) 01813 01814 : // inputs 01815 [LCD]"l" (0xA0002188), 01816 [scanline]"l" (scanline), 01817 [paletteptr]"l" (paletteptr), 01818 [offset]"l" (offset) 01819 : // clobbers 01820 "cc", "r10", "r11" 01821 ); 01822 01823 #else 01824 uint8_t* d = scrbuf;// point to beginning of line in data 01825 for(y=0;y<88;y++){ 01826 01827 uint32_t* s = scanline; 01828 01829 for(x=0;x<110;x+=10){ 01830 *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++); 01831 *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++); 01832 *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++); 01833 *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++); 01834 *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++); 01835 *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++); 01836 *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++); 01837 *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++); 01838 *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++); 01839 *LCD = *s = paletteptr[(*d + offset)&255]<<3; TGL_WR_OP(s++);TGL_WR_OP(d++); 01840 } 01841 01842 s = scanline; 01843 uint32_t c = *s; 01844 for(x=0;x<110;x+=10){ 01845 *LCD = c; TGL_WR_OP(s++);TGL_WR_OP(c=*s); 01846 *LCD = c; TGL_WR_OP(s++);TGL_WR_OP(c=*s); 01847 *LCD = c; TGL_WR_OP(s++);TGL_WR_OP(c=*s); 01848 *LCD = c; TGL_WR_OP(s++);TGL_WR_OP(c=*s); 01849 *LCD = c; TGL_WR_OP(s++);TGL_WR_OP(c=*s); 01850 *LCD = c; TGL_WR_OP(s++);TGL_WR_OP(c=*s); 01851 *LCD = c; TGL_WR_OP(s++);TGL_WR_OP(c=*s); 01852 *LCD = c; TGL_WR_OP(s++);TGL_WR_OP(c=*s); 01853 *LCD = c; TGL_WR_OP(s++);TGL_WR_OP(c=*s); 01854 *LCD = c; TGL_WR_OP(s++);TGL_WR_OP(c=*s); 01855 } 01856 01857 } 01858 #endif 01859 } 01860 01861 void Pokitto::lcdRefreshMode14(uint8_t * scrbuf, uint16_t* paletteptr) { 01862 uint16_t x,y; 01863 uint16_t scanline[176]; uint16_t* scptr; 01864 uint8_t *d; 01865 01866 write_command(0x20); write_data(0); 01867 write_command(0x21); write_data(0); 01868 write_command(0x22); 01869 CLR_CS_SET_CD_RD_WR; 01870 01871 for(x=0;x<220;x++) 01872 { 01873 d = scrbuf+x; 01874 scptr = &scanline[0]; 01875 01876 /** find colours in one scanline **/ 01877 /*for(y=0;y<22;y++) 01878 { 01879 01880 uint16_t t = *d; 01881 uint16_t t2 = *(d+POK_BITFRAME); 01882 uint16_t t3 = *(d+POK_BITFRAME+POK_BITFRAME); 01883 01884 *scptr++ = (t & 0x1)*R_MASK | (t2 & 0x1)*G_MASK | (t3 & 0x1)*B_MASK; t >>= 1;t2 >>= 1;t3 >>= 1; 01885 *scptr++ = (t & 0x1)*R_MASK | (t2 & 0x1)*G_MASK | (t3 & 0x1)*B_MASK; t >>= 1;t2 >>= 1;t3 >>= 1; 01886 *scptr++ = (t & 0x1)*R_MASK | (t2 & 0x1)*G_MASK | (t3 & 0x1)*B_MASK; t >>= 1;t2 >>= 1;t3 >>= 1; 01887 *scptr++ = (t & 0x1)*R_MASK | (t2 & 0x1)*G_MASK | (t3 & 0x1)*B_MASK; t >>= 1;t2 >>= 1;t3 >>= 1; 01888 01889 *scptr++ = (t & 0x1)*R_MASK | (t2 & 0x1)*G_MASK | (t3 & 0x1)*B_MASK; t >>= 1;t2 >>= 1;t3 >>= 1; 01890 *scptr++ = (t & 0x1)*R_MASK | (t2 & 0x1)*G_MASK | (t3 & 0x1)*B_MASK; t >>= 1;t2 >>= 1;t3 >>= 1; 01891 *scptr++ = (t & 0x1)*R_MASK | (t2 & 0x1)*G_MASK | (t3 & 0x1)*B_MASK; t >>= 1;t2 >>= 1;t3 >>= 1; 01892 *scptr++ = (t & 0x1)*R_MASK | (t2 & 0x1)*G_MASK | (t3 & 0x1)*B_MASK; t >>= 1;t2 >>= 1;t3 >>= 1; 01893 01894 01895 d+=220; // jump to word directly below 01896 } 01897 */ 01898 /** alternative way: go through one color at a time **/ 01899 scptr = &scanline[0]; // set to beginning of scanline 01900 for(y=0;y<22;y++, d +=220) 01901 { 01902 uint16_t t = *d & 0xFF; 01903 01904 *scptr++ = R_MASK * (t&0x1); t >>= 1; 01905 *scptr++ = R_MASK * (t&0x1); t >>= 1; 01906 *scptr++ = R_MASK * (t&0x1); t >>= 1; 01907 *scptr++ = R_MASK * (t&0x1); t >>= 1; 01908 *scptr++ = R_MASK * (t&0x1); t >>= 1; 01909 *scptr++ = R_MASK * (t&0x1); t >>= 1; 01910 *scptr++ = R_MASK * (t&0x1); t >>= 1; 01911 *scptr++ = R_MASK * (t&0x1); 01912 } 01913 scptr = &scanline[0]; // set to beginning of scanline 01914 d = scrbuf+x+POK_BITFRAME; 01915 for(y=0;y<22;y++, d +=220) 01916 { 01917 uint16_t t = *d & 0xFF; 01918 01919 *scptr++ |= G_MASK * (t&0x1); t >>= 1; 01920 *scptr++ |= G_MASK * (t&0x1); t >>= 1; 01921 *scptr++ |= G_MASK * (t&0x1); t >>= 1; 01922 *scptr++ |= G_MASK * (t&0x1); t >>= 1; 01923 *scptr++ |= G_MASK * (t&0x1); t >>= 1; 01924 *scptr++ |= G_MASK * (t&0x1); t >>= 1; 01925 *scptr++ |= G_MASK * (t&0x1); t >>= 1; 01926 *scptr++ |= G_MASK * (t&0x1); 01927 } 01928 scptr = &scanline[0]; // set to beginning of scanline 01929 d = scrbuf+x+POK_BITFRAME*2; 01930 for(y=0;y<22;y++, d +=220) 01931 { 01932 uint16_t t = *d & 0xFF; 01933 01934 *scptr++ |= B_MASK * (t&0x1); t >>= 1; 01935 *scptr++ |= B_MASK * (t&0x1); t >>= 1; 01936 *scptr++ |= B_MASK * (t&0x1); t >>= 1; 01937 *scptr++ |= B_MASK * (t&0x1); t >>= 1; 01938 *scptr++ |= B_MASK * (t&0x1); t >>= 1; 01939 *scptr++ |= B_MASK * (t&0x1); t >>= 1; 01940 *scptr++ |= B_MASK * (t&0x1); t >>= 1; 01941 *scptr++ |= B_MASK * (t&0x1); 01942 } 01943 01944 01945 #ifdef PROJ_SHOW_FPS_COUNTER 01946 if (x<8) continue; 01947 setDRAMptr(x, 0); 01948 #endif 01949 01950 /** draw scanlines **/ 01951 for (int s=0;s<176;) { 01952 setup_data_16(scanline[s++]);CLR_WR;SET_WR; 01953 setup_data_16(scanline[s++]);CLR_WR;SET_WR; 01954 setup_data_16(scanline[s++]);CLR_WR;SET_WR; 01955 setup_data_16(scanline[s++]);CLR_WR;SET_WR; 01956 setup_data_16(scanline[s++]);CLR_WR;SET_WR; 01957 setup_data_16(scanline[s++]);CLR_WR;SET_WR; 01958 setup_data_16(scanline[s++]);CLR_WR;SET_WR; 01959 setup_data_16(scanline[s++]);CLR_WR;SET_WR; 01960 01961 } 01962 01963 } 01964 } 01965 01966 //#define ADEKTOSMODE15 01967 01968 #ifdef ADEKTOSMODE15 01969 void Pokitto::lcdRefreshMode15(uint16_t* pal, uint8_t* scrbuf){ 01970 write_command(0x03); write_data(0x1038); //realy only need to call this once 01971 write_command(0x20); write_data(0); 01972 write_command(0x21); write_data(0); 01973 01974 write_command(0x22); 01975 01976 #ifdef PROJ_SHOW_FPS_COUNTER 01977 for (int x=0,xt=0; x<0x4BA0;x++,xt++) { 01978 if (xt==110) xt=0; 01979 if (xt<8) { 01980 write_data(0); 01981 write_data(0); 01982 } else { 01983 write_data(pal[(((scrbuf[x]) & 0xf0) >> 4)]); 01984 write_data(pal[( (scrbuf[x]) & 0x0f)]); 01985 } 01986 01987 } 01988 #else 01989 for (int x=0; x<0x4BA0;x++) { 01990 write_data(pal[(((scrbuf[x]) & 0xf0) >> 4)]); 01991 write_data(pal[( (scrbuf[x]) & 0x0f)]); 01992 } 01993 #endif //PROJ_SHOW_FPS_COUNTER 01994 } 01995 01996 #else 01997 01998 void Pokitto::lcdRefreshMode15(uint16_t* paletteptr, uint8_t* scrbuf){ 01999 uint16_t x,y; 02000 uint16_t scanline[2][176]; // read two nibbles = pixels at a time 02001 uint8_t *d; 02002 02003 //setDRAMptr(xptr,yoffset); 02004 02005 write_command(0x20); write_data(0); 02006 write_command(0x21); write_data(0); 02007 write_command(0x22); 02008 CLR_CS_SET_CD_RD_WR; 02009 02010 for(x=0;x<220;x+=2) 02011 { 02012 d = scrbuf+(x>>1);// point to beginning of line in data 02013 // find colours in one scanline 02014 uint8_t s=0; 02015 for(y=0;y<176;y++) 02016 { 02017 uint8_t t = *d >> 4; // higher nibble 02018 uint8_t t2 = *d & 0xF; // lower nibble 02019 // higher nibble = left pixel in pixel pair 02020 scanline[0][s] = paletteptr[t]; 02021 scanline[1][s++] = paletteptr[t2]; 02022 02023 d+=220/2; // jump to read byte directly below in screenbuffer 02024 } 02025 s=0; 02026 // draw scanlines 02027 02028 #ifdef PROJ_SHOW_FPS_COUNTER 02029 if (x<8) continue; 02030 setDRAMptr(x, 0); 02031 #endif 02032 02033 for (s=0;s<176;) { 02034 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 02035 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 02036 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 02037 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 02038 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 02039 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 02040 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 02041 setup_data_16(scanline[0][s++]);CLR_WR;SET_WR; 02042 } 02043 02044 for (s=0;s<176;) { 02045 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 02046 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 02047 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 02048 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 02049 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 02050 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 02051 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 02052 setup_data_16(scanline[1][s++]);CLR_WR;SET_WR; 02053 } 02054 } 02055 } 02056 #endif //ADEKTOSMODE15 02057 02058 void Pokitto::blitWord(uint16_t c) { 02059 setup_data_16(c);CLR_WR;SET_WR; 02060 } 02061 02062
Generated on Tue Jul 12 2022 21:03:50 by 1.7.2