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