Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of PokittoLib by
PokittoCore.cpp
00001 /**************************************************************************/ 00002 /*! 00003 @file PokittoCore.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 "PokittoCore.h " 00038 #include "Pokitto_settings.h " 00039 #include "PokittoConsole.h " 00040 #include "PokittoFonts.h " 00041 #include "PokittoTimer.h " 00042 #include "PokittoLogos.h " 00043 #include <stdlib.h> 00044 #ifndef DISABLEAVRMIN 00045 #define max(a,b) ((a)>(b)?(a):(b)) 00046 #endif // DISABLEAVRMIN 00047 00048 char selectedfile[25]; 00049 00050 //#define F 00051 #ifdef __ARMCC_VERSION 00052 typedef void (*func_t)(void); 00053 #endif 00054 00055 #ifndef POK_SIM 00056 /** start the user application 00057 * https://community.nxp.com/thread/417695 00058 * 00059 */ 00060 void start_application(unsigned long app_link_location){ 00061 //asm(" ldr sp, [r0,#0]"); 00062 //asm(" ldr pc, [r0,#4]"); 00063 //This code is not valid for the Cortex-m0+ instruction set. 00064 // The equivalent for this (as used by the KL26) is 00065 __disable_irq();// Start by disabling interrupts, before changing interrupt vectors 00066 00067 // delete buttons 00068 //pokDeleteButtons(); 00069 00070 // completely kill button interrupts in preparation for reset 00071 LPC_PINT->IENR = 0; 00072 LPC_PINT->IENF = 0; 00073 00074 SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk & ~(SysTick_CTRL_ENABLE_Msk); //disable systick 00075 LPC_SYSCON->PDRUNCFG |= (1 << 10); /* Power-down USB PHY */ 00076 LPC_SYSCON->PDRUNCFG |= (1 << 8); /* Power-down USB PLL */ 00077 00078 // reset clock source to IRC 00079 LPC_SYSCON->MAINCLKUEN = 0x01; /* Update MCLK Clock Source */ 00080 LPC_SYSCON->MAINCLKUEN = 0x00; /* Toggle Update Register */ 00081 while (LPC_SYSCON->MAINCLKUEN & 0x01); /* Wait Until Updated */ 00082 // switch clock selection to IRC 00083 LPC_SYSCON->MAINCLKSEL = 0; /* Select Clock Source */ 00084 LPC_SYSCON->MAINCLKUEN = 0x01; /* Update MCLK Clock Source */ 00085 LPC_SYSCON->MAINCLKUEN = 0x00; /* Toggle Update Register */ 00086 while (LPC_SYSCON->MAINCLKUEN & 0x01); /* Wait Until Updated */ 00087 //disable PLL clock output 00088 LPC_SYSCON->SYSPLLCLKUEN = 0; 00089 while (LPC_SYSCON->SYSPLLCLKUEN & 0x00); 00090 LPC_SYSCON->SYSPLLCTRL = 0; 00091 00092 //kill peripherals 00093 LPC_SYSCON->MAINCLKSEL = 0; 00094 LPC_SYSCON->PRESETCTRL = 0; //disable all peripherals 00095 00096 //power down PLL 00097 volatile uint32_t tmp; 00098 tmp = (LPC_SYSCON->PDRUNCFG & 0x000025FFL); 00099 tmp |= ((1<<7) & 0x000025FFL); 00100 LPC_SYSCON->PDRUNCFG = (tmp | 0x0000C800L); /* Power-down SYSPLL */ 00101 00102 //Chip_Clock_SetMainClockSource(SYSCTL_MAINCLKSRC_IRC); //switch to IRC 00103 00104 // clear all gpio states 00105 LPC_GPIO_PORT->PIN[0] = 0; 00106 LPC_GPIO_PORT->PIN[1] = 0; 00107 LPC_GPIO_PORT->PIN[2] = 0; 00108 00109 SCB->VTOR = app_link_location;//APPL_ADDRESS; /* Change vector table address */ 00110 #ifndef __ARMCC_VERSION 00111 asm(" mov r0, %[address]"::[address] "r" (app_link_location)); 00112 asm(" ldr r1, [r0,#0]"); // get the stack pointer value from the program's reset vector 00113 asm(" mov sp, r1"); // copy the value to the stack pointer 00114 asm(" ldr r0, [r0,#4]"); // get the program counter value from the program's reset vector 00115 asm(" blx r0"); // jump to the' start address 00116 #else 00117 uint32_t *app_loc = (uint32_t*)app_link_location; 00118 __set_MSP (app_loc[0]); 00119 ((func_t)(app_loc[1]))(); 00120 #endif 00121 } 00122 #endif 00123 00124 // returns a random integar between 0 and maxVal 00125 int random(int maxVal) 00126 { 00127 return random( 0, maxVal); 00128 } 00129 00130 // returns a random integar between minVal and maxVal 00131 int random(int minVal, int maxVal) 00132 { 00133 // int rand(void); included by default from newlib 00134 return rand() % (maxVal-minVal+1) + minVal; 00135 } 00136 00137 using namespace Pokitto; 00138 00139 bool Core::run_state; // this definition needed 00140 00141 /** Components */ 00142 Backlight Core::backlight; 00143 Buttons Core::buttons; 00144 Battery Core::battery; 00145 #if POK_ENABLE_SOUND > 0 00146 Sound Core::sound; 00147 #endif 00148 Display Core::display; 00149 00150 //GB Related 00151 uint8_t Core::startMenuTimer; 00152 uint8_t Core::timePerFrame; 00153 uint32_t Core::nextFrameMillis; 00154 uint32_t Core::frameCount; 00155 const char* Core::popupText; 00156 uint8_t Core::popupTimeLeft; 00157 uint16_t Core::frameDurationMicros; 00158 uint32_t Core::frameStartMicros, Core::frameEndMicros; 00159 uint8_t Core::volbar_visible=0; 00160 00161 00162 Core::Core() { 00163 00164 } 00165 00166 void Core::showWarning() { 00167 display.enableDirectPrinting(true); 00168 display.directbgcolor = COLOR_BLACK; 00169 display.clearLCD(); 00170 display.directcolor = COLOR_RED; 00171 display.setFont(fntC64UIGfx); 00172 display.adjustCharStep = 0; 00173 display.adjustLineStep = 0; 00174 display.setCursor(10*8,9); 00175 display.print("WARNING!"); 00176 display.directcolor = COLOR_WHITE; 00177 display.setCursor(5*8,4*9); 00178 display.print("LOUD SOUND THROUGH"); 00179 display.setCursor(2*8,5*9); 00180 display.print("HEADPHONES COULD DAMAGE"); 00181 display.setCursor(7*8,6*9); 00182 display.print("YOUR HEARING."); 00183 display.setCursor(5*8,8*9); 00184 display.print("USE "); display.directcolor = COLOR_GREEN; 00185 display.print("0-100% VOLUME"); 00186 display.directcolor = COLOR_WHITE; 00187 display.setCursor(5*8,9*9); 00188 display.print("FOR LISTENING WITH"); 00189 display.setCursor(8*8,10*9); 00190 display.print("HEADPHONES"); 00191 display.setCursor(5*8,12*9); 00192 display.print("USE "); display.directcolor = COLOR_RED; 00193 display.print("> 100% VOLUME"); display.directcolor = COLOR_GREEN; 00194 display.directcolor = COLOR_WHITE; 00195 display.setCursor(1*8,13*9); 00196 display.print("ONLY FOR LISTENING VIA THE"); 00197 display.setCursor(5*8,14*9); 00198 display.print("BUILT-IN SPEAKER"); 00199 display.setCursor(5*8,17*9); 00200 display.print("PRESS ");display.directcolor = COLOR_GREEN; 00201 display.print("C ");display.directcolor = COLOR_WHITE; 00202 display.print("TO ACCEPT"); 00203 while (!buttons.cBtn()) { 00204 wait(100); 00205 } 00206 display.clearLCD(); 00207 display.enableDirectPrinting(false); 00208 } 00209 00210 void Core::jumpToLoader() { 00211 display.fontSize=1; 00212 display.directbgcolor=COLOR_BLACK; 00213 display.directcolor=COLOR_GREEN; 00214 display.setCursor(0,0); 00215 display.enableDirectPrinting(true); 00216 #ifdef POK_SIM 00217 display.println("LOADER IS NOT AVAILABLE ON THE SIMULATOR. PRESS A TO RETURN."); 00218 #else 00219 uint32_t* bootinfo; 00220 bootinfo = (uint32_t*)0x3FE04; 00221 if (*bootinfo != 0xB007AB1E) display.println("NO LOADER CONNECTED!"); 00222 else start_application(*(bootinfo+2)); //never returns 00223 //display.println((unsigned int)(*(bootinfo+2)),16); 00224 #endif // POK_SIM 00225 while (!buttons.aBtn()) { 00226 buttons.pollButtons(); 00227 if (buttons.aBtn()) { 00228 while (buttons.aBtn()) { 00229 buttons.pollButtons(); 00230 } 00231 return; 00232 } 00233 } 00234 } 00235 00236 void Core::askLoader() { 00237 display.enableDirectPrinting(true); 00238 display.directbgcolor = COLOR_BLACK; 00239 display.clearLCD(); 00240 display.directcolor = COLOR_RED; 00241 display.setFont(fntC64UIGfx); 00242 display.fontSize=1; 00243 display.adjustCharStep = 0; 00244 display.adjustLineStep = 0; 00245 display.directcolor=COLOR_GREEN; 00246 display.set_cursor(12*8,6*8); 00247 display.print("ijkl"); 00248 display.set_cursor(12*8,7*8); 00249 display.print("mnop"); 00250 display.set_cursor(12*8,8*8); 00251 display.print("qrst"); 00252 display.set_cursor(12*8,9*8); 00253 display.print("uvwx"); 00254 display.set_cursor(5*8,12*8); 00255 display.print("PRESS"); 00256 display.directcolor=COLOR_WHITE; 00257 display.print(" C "); 00258 display.directcolor=COLOR_GREEN; 00259 display.print("FOR LOADER"); 00260 display.directcolor=COLOR_WHITE; 00261 display.fontSize=2; 00262 int countd=POK_LOADER_COUNTDOWN; uint16_t c2 = getTime(); 00263 while (countd) { 00264 buttons.pollButtons(); 00265 display.set_cursor(13*8,15*8); 00266 display.print(countd); 00267 if (getTime()>c2+1000) { 00268 c2=getTime(); 00269 countd--; 00270 } 00271 if (cBtn()) {while (cBtn()) buttons.pollButtons();jumpToLoader();countd=0;} 00272 if (aBtn()) {while (aBtn()) buttons.pollButtons();countd=0;} 00273 if (bBtn()) {while (bBtn()) buttons.pollButtons();countd=0;} 00274 } 00275 display.fontSize=1; 00276 display.clearLCD(); 00277 display.enableDirectPrinting(false); 00278 } 00279 00280 00281 void Core::drawvolbar(int x, int y, int level, bool text) { 00282 uint16_t oldcol = display.directcolor; 00283 if (text) display.directRectangle(0,0,50,50,COLOR_BLACK); 00284 display.directcolor = COLOR_GREEN; 00285 if (text) { 00286 bool temp = display.isDirectPrintingEnabled(); 00287 display.enableDirectPrinting(true); 00288 display.print(x-1,y-20,(int)sound.getVolume()); 00289 display.print(" "); 00290 display.enableDirectPrinting(temp); 00291 } 00292 if (level<12) display.directcolor = COLOR_GRAY_80; 00293 display.directBitmap(x,y,Pokitto_volumebar,1,1); 00294 if (level<24) display.directcolor = COLOR_GRAY_80; 00295 display.directBitmap(x+8,y,Pokitto_volumebar,1,1); 00296 display.directBitmap(x+8,y-4,Pokitto_volumebar,1,1); 00297 display.directcolor = COLOR_RED; 00298 if (level<48) display.directcolor = COLOR_GRAY_80; 00299 display.directBitmap(x+16,y,Pokitto_volumebar,1,1); 00300 display.directBitmap(x+16,y-4,Pokitto_volumebar,1,1); 00301 display.directBitmap(x+16,y-8,Pokitto_volumebar,1,1); 00302 00303 if (level<96) { 00304 display.directcolor = COLOR_GRAY_80; 00305 } 00306 display.directBitmap(x+24,y,Pokitto_volumebar,1,1); 00307 display.directBitmap(x+24,y-4,Pokitto_volumebar,1,1); 00308 display.directBitmap(x+24,y-8,Pokitto_volumebar,1,1); 00309 display.directBitmap(x+24,y-12,Pokitto_volumebar,1,1); 00310 if (level<160) { 00311 display.directcolor = COLOR_GRAY_80; 00312 } 00313 display.directBitmap(x+32,y,Pokitto_volumebar,1,1); 00314 display.directBitmap(x+32,y-4,Pokitto_volumebar,1,1); 00315 display.directBitmap(x+32,y-8,Pokitto_volumebar,1,1); 00316 display.directBitmap(x+32,y-12,Pokitto_volumebar,1,1); 00317 display.directBitmap(x+32,y-16,Pokitto_volumebar,1,1); 00318 display.directcolor = oldcol; 00319 } 00320 00321 00322 #ifdef POK_SIM 00323 #define VINCMULT 1 00324 #else 00325 #define VINCMULT 50 00326 #endif //POK_SIM 00327 void Core::setVolLimit() { 00328 display.enableDirectPrinting(true); 00329 display.adjustCharStep = 0; 00330 sound.setMaxVol(VOLUME_HEADPHONE_MAX); 00331 int dstate=1; 00332 bool wipe = true; 00333 float vol = sound.getVolume(); float tvol; 00334 volbar_visible=0; 00335 while (core.isRunning() && dstate){ 00336 switch (dstate) { 00337 case 1: 00338 //redraw 00339 if (wipe) { 00340 display.clearLCD(); 00341 display.directcolor = COLOR_WHITE; 00342 display.setCursor(4*8,2*8); 00343 display.print("SELECT VOLUME LIMIT"); 00344 display.setCursor(5*8,17*9); 00345 display.print("PRESS "); 00346 display.directcolor = COLOR_GREEN; 00347 display.print("A"); 00348 display.directcolor = COLOR_WHITE; 00349 display.print(" TO ACCEPT"); 00350 display.directcolor = COLOR_GREEN; 00351 // draw frame below first 00352 display.setCursor(0,11*8); 00353 display.println(" abbbbbbbbbbbbbbbbbbbbbbbc"); 00354 display.println(" | |"); 00355 display.println(" | |"); 00356 display.println(" | |"); 00357 display.println(" | |"); 00358 display.println(" dbbbbbbbbbbbbbbbbbbbbbbbe"); 00359 } // wipe = true 00360 display.setCursor(6*8,17*9); 00361 if (sound.getVolume()-5<=VOLUME_HEADPHONE_MAX) display.directcolor = COLOR_WHITE; 00362 else display.directcolor = COLOR_RED; 00363 display.directBitmap(21*8-4,6*8,Pokitto_headphones,1,2); 00364 display.setCursor(3*8,6*8+6); 00365 display.print("HEADPHONES"); 00366 display.setCursor(3*8,8*8+2); 00367 if (sound.getVolume()-8>VOLUME_HEADPHONE_MAX) display.print("TOO LOUD!"); 00368 else display.print("OK "); 00369 display.directcolor = COLOR_GREEN; 00370 display.directBitmap(21*8-4,12*8,Pokitto_speaker,1,2); 00371 display.setCursor(3*8,12*8+6); 00372 display.print("VOLUME MAX"); 00373 display.setCursor(3*8,14*8+2); 00374 tvol = (vol/float(VOLUME_HEADPHONE_MAX))*100; 00375 if (tvol > 100 && tvol < 120) tvol=100; 00376 if (sound.getVolume()-5>VOLUME_HEADPHONE_MAX) { display.directcolor=COLOR_RED;} 00377 else display.directcolor=COLOR_GREEN; 00378 display.print(int(sound.getVolume())); 00379 //display.print(int(tvol)); 00380 display.print(" "); 00381 display.directcolor=COLOR_GREEN; 00382 drawvolbar(14*8,14*8+4+2,sound.getVolume(),false); 00383 //display.setCursor(1,10); 00384 //display.print(vol); 00385 dstate=2; break; 00386 case 2: 00387 buttons.pollButtons(); 00388 if (aBtn()) {dstate=0;while(aBtn()){buttons.pollButtons();};break;} 00389 if (rightBtn()) { 00390 if (vol >= VOLUME_HEADPHONE_MAX && vol < VOLUME_HEADPHONE_MAX+1 ) vol += 0.00025f*VINCMULT; 00391 else if (vol >= VOLUME_HEADPHONE_MAX) vol += 0.025f*VINCMULT; 00392 else vol += 0.05f*VINCMULT; 00393 if (vol > VOLUME_HEADPHONE_MAX + 20) { 00394 sound.setMaxVol(VOLUME_SPEAKER_MAX); 00395 } 00396 if (vol > VOLUME_SPEAKER_MAX) vol=VOLUME_SPEAKER_MAX; 00397 sound.setVolume(vol); 00398 dstate=1; wipe=false; 00399 break; 00400 } 00401 if (leftBtn()) { 00402 vol -= 0.025f*VINCMULT; 00403 if (vol <= VOLUME_HEADPHONE_MAX) sound.setMaxVol(VOLUME_HEADPHONE_MAX); 00404 if (vol < 0) vol=0; 00405 sound.setVolume(vol); 00406 dstate=1; wipe=false; 00407 break; 00408 } 00409 break; 00410 } 00411 } 00412 } 00413 00414 void Core::begin() { 00415 00416 init(); // original functions 00417 timePerFrame = POK_FRAMEDURATION; 00418 //nextFrameMillis = 0; 00419 //frameCount = 0; 00420 frameEndMicros = 1; 00421 startMenuTimer = 255; 00422 //read default settings from flash memory (set using settings.hex) 00423 readSettings(); 00424 //init everything 00425 backlight.begin(); 00426 backlight.set(BACKLIGHT_MAX); 00427 buttons.begin(); 00428 buttons.update(); 00429 battery.begin(); 00430 display.begin(); 00431 #if POK_DISPLAYLOGO 00432 showLogo(); 00433 #endif // POK_DISPLAYLOGO 00434 display.enableDirectPrinting(true); 00435 display.directbgcolor = COLOR_BLACK; 00436 display.clearLCD(); 00437 display.setFont(fntC64UIGfx); 00438 askLoader(); 00439 #ifndef DISABLE_SOUND_WARNING 00440 //showWarning(); 00441 setVolLimit(); 00442 //sound.setVolume(sound.getVolume());//make sure we're at set volume before continue 00443 sound.volumeUp(); 00444 #endif 00445 display.enableDirectPrinting(false); 00446 display.adjustCharStep=1; 00447 display.adjustLineStep=1; 00448 display.fontSize=1; 00449 display.textWrap=true; 00450 #if POK_GAMEBUINO_SUPPORT > 0 00451 display.setFont(font5x7); 00452 #else 00453 display.setFont(fontC64); 00454 #endif 00455 00456 #if POK_ENABLE_SOUND > 0 00457 sound.begin(); 00458 00459 //mute when B is held during start up or if battery is low 00460 battery.update(); 00461 00462 if(buttons.pressed(BTN_B) || (battery.level == 0)){ 00463 sound.setVolume(0); 00464 } 00465 else{ //play the startup sound on each channel for it to be louder 00466 #if POK_GBSOUND > 0 00467 #if(NUM_CHANNELS > 0) 00468 sound.playPattern(startupSound, 0); 00469 #endif 00470 #if(NUM_CHANNELS > 1) 00471 sound.playPattern(startupSound, 1); 00472 #endif 00473 #if(NUM_CHANNELS > 2) 00474 sound.playPattern(startupSound, 2); 00475 #endif 00476 #if(NUM_CHANNELS > 3) 00477 sound.playPattern(startupSound, 3); 00478 #endif 00479 #endif // POK_GBSOUND 00480 } 00481 #endif // POK ENABLE_SOUND 00482 } 00483 00484 void Core::init() { 00485 run_state = true; 00486 display.enableDirectPrinting(false); 00487 display.setFont(DEFAULT_FONT); 00488 initClock(); 00489 initGPIO(); 00490 initButtons(); 00491 initRandom(); 00492 //initAudio(); 00493 //initDisplay(); 00494 } 00495 00496 void Core::init(uint8_t switches) { 00497 run_state = true; 00498 display.enableDirectPrinting(false); 00499 display.setFont(DEFAULT_FONT); 00500 initClock(); 00501 initGPIO(); 00502 initButtons(); 00503 initRandom(); 00504 //initAudio(); 00505 //initDisplay(); 00506 } 00507 00508 void Core::initButtons() { 00509 #ifndef POK_SIM 00510 Pokitto::initButtons(); 00511 #endif 00512 } 00513 00514 bool Core::isRunning() { 00515 #ifdef POK_SIM 00516 run_state = simulator.isRunning(); 00517 #endif // POK_SIM 00518 return run_state; 00519 } 00520 00521 void Core::initDisplay() { 00522 #if POK_DISPLAYLOGO > 0 00523 showLogo(); 00524 #endif 00525 #if POK_USE_CONSOLE > 0 00526 console.AddMessage(MSOURCE_LCD,MSG_INIT_OK); 00527 #endif 00528 } 00529 00530 void Core::showLogo() { 00531 uint32_t now; 00532 uint8_t state=0; //jump directly to logo, bypass teeth 00533 uint16_t i=0; 00534 uint16_t sc; 00535 while (state < 255/6) { 00536 now=getTime(); 00537 if (now>refreshtime) { 00538 refreshtime=now+30; 00539 switch (state) { 00540 case 0: 00541 /** POKITTO CLEAN **/ 00542 display.directbgcolor = COLOR_BLACK; 00543 display.fillLCD(display.directbgcolor); 00544 sc = COLOR_BLACK; 00545 state++; 00546 break; 00547 case 1: 00548 /** POKITTO FADE IN **/ 00549 display.directcolor = display.interpolateColor(sc, COLOR_GREEN, i); 00550 display.directBitmap(POK_LCD_W/2 - (*Pokitto_logo/2),POK_LCD_H/2-(*(Pokitto_logo+1)/2),Pokitto_logo,1,1); 00551 i += 28; 00552 if (i>=0xFF) { state++; i=0;} 00553 break; 00554 case 2: 00555 /** POKITTO WAIT **/ 00556 display.directcolor = COLOR_GREEN; 00557 display.directBitmap(POK_LCD_W/2 - (*Pokitto_logo/2),POK_LCD_H/2-(*(Pokitto_logo+1)/2),Pokitto_logo,1,1); 00558 i+= 0x3F; 00559 if (i>0x3FF) state = 255; 00560 break; 00561 } 00562 if(buttons.aBtn()) state=255; 00563 } 00564 } 00565 } 00566 00567 void Core::readSettings() { 00568 // ToDo 00569 /*display.contrast = SCR_CONTRAST; 00570 backlight.backlightMin = BACKLIGHT_MIN; 00571 backlight.backlightMax = BACKLIGHT_MAX; 00572 backlight.ambientLightMin = AMBIENTLIGHT_MIN; 00573 backlight.ambientLightMax = AMBIENTLIGHT_MAX; 00574 */ 00575 sound.setMaxVol(VOLUME_HEADPHONE_MAX); 00576 sound.globalVolume = VOLUME_STARTUP; 00577 00578 startMenuTimer = START_MENU_TIMER; 00579 /* 00580 battery.thresolds[0] = BAT_LVL_CRITIC; 00581 battery.thresolds[1] = BAT_LVL_LOW; 00582 battery.thresolds[2] = BAT_LVL_MED; 00583 battery.thresolds[3] = BAT_LVL_FULL;*/ 00584 } 00585 00586 void Core::titleScreen(const char* name){ 00587 titleScreen(name, 0); 00588 } 00589 00590 void Core::titleScreen(const uint8_t* logo){ 00591 titleScreen((""), logo); 00592 } 00593 00594 void Core::titleScreen(){ 00595 titleScreen(("")); 00596 } 00597 00598 void Core::titleScreen(const char* name, const uint8_t *logo){ 00599 display.setFont(font5x7); 00600 if(startMenuTimer){ 00601 display.fontSize = 1; 00602 display.textWrap = false; 00603 display.persistence = false; 00604 battery.show = false; 00605 display.setColor(BLACK); 00606 while(isRunning()){ 00607 if(update()){ 00608 uint8_t logoOffset = name[0]?display.fontHeight:0; //add an offset the logo when there is a name to display 00609 //draw graphics 00610 display.setColorDepth(1); 00611 display.setColor(3); 00612 //display.drawBitmap(0,0, gamebuinoLogo); 00613 display.setColor(1); 00614 if(logo){ 00615 display.drawBitmap(0, 12+logoOffset, logo); 00616 } 00617 display.cursorX = 0; 00618 display.cursorY = 12; 00619 display.print(name); 00620 00621 //A button 00622 display.cursorX = LCDWIDTH - display.fontWidth*3 -1; 00623 display.cursorY = LCDHEIGHT - display.fontHeight*3 - 3; 00624 if((frameCount/16)%2) 00625 display.println(("\25 \20")); 00626 else 00627 display.println(("\25\20 ")); 00628 //B button 00629 display.cursorX = LCDWIDTH - display.fontWidth*3 - 1; 00630 display.cursorY++; 00631 if(sound.globalVolume) 00632 display.println(("\26\23\24")); 00633 else 00634 display.println(("\26\23x")); 00635 //C button 00636 display.cursorX = LCDWIDTH - display.fontWidth*3 - 1; 00637 display.cursorY++; 00638 //display.println(F("\27SD")); 00639 00640 //toggle volume when B is pressed 00641 if(buttons.pressed(BTN_B)){ 00642 sound.setVolume(sound.getVolume() + 1); 00643 sound.playTick(); 00644 } 00645 //leave the menu 00646 if(buttons.pressed(BTN_A) || ((frameCount>=startMenuTimer)&&(startMenuTimer != 255))){ 00647 startMenuTimer = 255; //don't automatically skip the title screen next time it's displayed 00648 sound.stopPattern(0); 00649 sound.playOK(); 00650 break; 00651 } 00652 //flash the loader 00653 //if(buttons.pressed(BTN_C)) 00654 // ToDo changeGame(); 00655 } 00656 } 00657 battery.show = true; 00658 } 00659 } 00660 00661 bool Core::update(bool useDirectMode) { 00662 #if POK_STREAMING_MUSIC 00663 sound.updateStream(); 00664 #endif 00665 00666 if ((((nextFrameMillis - getTime())) > timePerFrame) && frameEndMicros) { //if time to render a new frame is reached and the frame end has ran once 00667 nextFrameMillis = getTime() + timePerFrame; 00668 frameCount++; 00669 00670 frameEndMicros = 0; 00671 backlight.update(); 00672 buttons.update(); 00673 battery.update(); 00674 00675 return true; 00676 00677 } else { 00678 if (!frameEndMicros) { //runs once at the end of the frame 00679 #if POK_ENABLE_SOUND > 0 00680 sound.updateTrack(); 00681 sound.updatePattern(); 00682 sound.updateNote(); 00683 #endif 00684 updatePopup(); 00685 displayBattery(); 00686 00687 if(!useDirectMode) 00688 display.update(); //send the buffer to the screen 00689 00690 frameEndMicros = 1; //jonne 00691 00692 } 00693 return false; 00694 } 00695 } 00696 00697 void Core::displayBattery(){ 00698 #if (ENABLE_BATTERY > 0) 00699 //display.setColor(BLACK, WHITE); 00700 uint8_t ox,oy; 00701 ox=display.cursorX; 00702 oy=display.cursorY; 00703 display.cursorX = LCDWIDTH-display.fontWidth+1; 00704 display.cursorY = 0; 00705 switch(battery.level){ 00706 case 0://battery critic, power down 00707 sound.stopPattern(); 00708 backlight.set(0); 00709 display.clear(); 00710 display.fontSize = 1; 00711 display.print(("LOW BATTERY\n")); 00712 display.print(battery.voltage); 00713 display.print(("mV\n\nPLEASE\nTURN OFF")); 00714 display.update(); 00715 break; 00716 case 1: //empty battery 00717 if((frameCount % 16) < 8) display.print('\7'); //blinking battery 00718 else display.print('x'); 00719 break; 00720 case 2://low battery 00721 case 3://full battery 00722 case 4://full battery 00723 if(battery.show){ 00724 display.print(char(5+battery.level)); 00725 } 00726 break; 00727 default: 00728 if(battery.show){ 00729 display.print('/'); 00730 } 00731 break; 00732 } 00733 display.cursorX = ox; 00734 display.cursorY = oy; 00735 #endif 00736 } 00737 00738 char* Core::filemenu(char *ext) { 00739 display.persistence = false; 00740 uint16_t oldpal0=display.palette[0]; 00741 uint16_t oldpal1=display.palette[1]; 00742 uint16_t oldpal2=display.palette[2]; 00743 display.palette[2]=COLOR_GREEN; 00744 display.palette[1]=COLOR_WHITE; 00745 display.palette[0]=COLOR_BLACK; 00746 uint8_t oldbg=display.bgcolor; 00747 uint8_t oldfg=display.color; 00748 display.color=1; 00749 display.bgcolor=0; 00750 00751 int8_t activeItem = 0; 00752 int16_t currentY = 100; 00753 int16_t targetY = 0, rowh = display.fontHeight + 2; 00754 boolean exit = false; 00755 00756 char* txt; 00757 00758 00759 while (isRunning()) { 00760 if (update()) { 00761 getFirstFile(ext); 00762 if (buttons.pressed(BTN_A) || buttons.pressed(BTN_B) || buttons.pressed(BTN_C)) { 00763 exit = true; //time to exit menu ! 00764 targetY = - display.fontHeight * 10 - 2; //send the menu out of the screen 00765 if (buttons.pressed(BTN_A)) { 00766 //answer = activeItem; 00767 sound.playOK(); 00768 } else { 00769 sound.playCancel(); 00770 } 00771 } 00772 if (exit == false) { 00773 if (buttons.repeat(BTN_DOWN,4)) { 00774 activeItem++; 00775 sound.playTick(); 00776 } 00777 if (buttons.repeat(BTN_UP,4)) { 00778 activeItem--; 00779 sound.playTick(); 00780 } 00781 //don't go out of the menu 00782 //if (activeItem == length) activeItem = 0; 00783 //if (activeItem < 0) activeItem = length - 1; 00784 if (currentY>targetY) currentY-=16; 00785 if (currentY<targetY) currentY=targetY; 00786 //targetY = -rowh * activeItem + (rowh+4); //center the menu on the active item 00787 } else { //exit : 00788 if (currentY>targetY) currentY-=16; 00789 if (currentY<targetY) currentY=targetY; 00790 if ((currentY - targetY) <= 1) 00791 { 00792 display.bgcolor=oldbg; 00793 display.color=oldfg; 00794 display.palette[0] = oldpal0; 00795 display.palette[1] = oldpal1; 00796 display.palette[2] = oldpal2; 00797 return selectedfile; 00798 } 00799 00800 } 00801 //draw a fancy menu 00802 //currentY = 0;//(currentY + targetY) / 2 + 5; 00803 display.cursorX = 0; 00804 display.cursorY = currentY; 00805 display.textWrap = false; 00806 //getFirstFile(ext); 00807 for (int i = 0; i<20; i++) { 00808 display.invisiblecolor=255; 00809 display.cursorY = currentY + rowh * i; 00810 if (i==3) display.color=1; 00811 if (i == activeItem){ 00812 display.cursorX = 3; 00813 00814 //display.fillRoundRect(0, currentY + display.fontHeight * activeItem - 2, LCDWIDTH, (display.fontHeight+3), 3); 00815 display.color=2; 00816 display.fillRect(0, currentY + rowh * activeItem - 2, LCDWIDTH, (rowh)); 00817 display.setColor(0,2); 00818 } else display.setColor(1,0); 00819 //display.println((char*)*(const unsigned int*)(items+i)); 00820 //display.println((int)i); 00821 txt = getNextFile(ext); 00822 if (txt) { 00823 display.println(txt); 00824 if (i == activeItem) { 00825 strcpy(selectedfile,txt); 00826 } 00827 } else i--; 00828 display.setColor(1,0); 00829 } // draw menu loop 00830 } // update 00831 } 00832 return 0; 00833 } 00834 00835 char* Core::filemenu() { 00836 return filemenu(""); 00837 } 00838 00839 int8_t Core::menu(const char* const* items, uint8_t length) { 00840 #if (ENABLE_GUI > 0) 00841 display.persistence = false; 00842 int8_t activeItem = 0; 00843 int16_t currentY = display.height; 00844 int16_t targetY = 0, rowh = display.fontHeight + 2; 00845 boolean exit = false; 00846 int8_t answer = -1; 00847 while (isRunning()) { 00848 if (update()) { 00849 if (buttons.pressed(BTN_A) || buttons.pressed(BTN_B) || buttons.pressed(BTN_C)) { 00850 exit = true; //time to exit menu ! 00851 targetY = - display.fontHeight * length - 2; //send the menu out of the screen 00852 if (buttons.pressed(BTN_A)) { 00853 answer = activeItem; 00854 sound.playOK(); 00855 } else { 00856 sound.playCancel(); 00857 } 00858 } 00859 if (exit == false) { 00860 if (buttons.repeat(BTN_DOWN,4)) { 00861 activeItem++; 00862 sound.playTick(); 00863 } 00864 if (buttons.repeat(BTN_UP,4)) { 00865 activeItem--; 00866 sound.playTick(); 00867 } 00868 //don't go out of the menu 00869 if (activeItem == length) activeItem = 0; 00870 if (activeItem < 0) activeItem = length - 1; 00871 00872 targetY = -rowh * activeItem + (rowh+4); //center the menu on the active item 00873 } else { //exit : 00874 if ((currentY - targetY) <= 1) 00875 return (answer); 00876 } 00877 //draw a fancy menu 00878 currentY = (currentY + targetY) / 2; 00879 display.cursorX = 0; 00880 display.cursorY = currentY; 00881 display.textWrap = false; 00882 uint16_t fc,bc; 00883 fc = display.color; 00884 bc = display.bgcolor; 00885 for (byte i = 0; i < length; i++) { 00886 display.cursorY = currentY + rowh * i; 00887 if (i == activeItem){ 00888 display.cursorX = 3; 00889 00890 //display.fillRoundRect(0, currentY + display.fontHeight * activeItem - 2, LCDWIDTH, (display.fontHeight+3), 3); 00891 display.fillRect(0, currentY + rowh * activeItem - 2, LCDWIDTH, (rowh)); 00892 display.setColor(bc,fc); 00893 } else display.setColor(fc,bc); 00894 00895 display.println((char*)*(const unsigned int*)(items+i)); 00896 display.setColor(fc,bc); 00897 } 00898 00899 } 00900 } 00901 #else 00902 return 0; 00903 #endif 00904 return 0; 00905 } 00906 00907 void Core::keyboard(char* text, uint8_t length) { 00908 #if (ENABLE_GUI > 0) 00909 display.persistence = false; 00910 //memset(text, 0, length); //clear the text 00911 text[length-1] = '\0'; 00912 //active character in the typing area 00913 int8_t activeChar = 0; 00914 //selected char on the keyboard 00915 int8_t activeX = 0; 00916 int8_t activeY = 2; 00917 //position of the keyboard on the screen 00918 int8_t currentX = LCDWIDTH; 00919 int8_t currentY = LCDHEIGHT; 00920 int8_t targetX = 0; 00921 int8_t targetY = 0; 00922 00923 while (1) { 00924 if (update()) { 00925 //move the character selector 00926 if (buttons.repeat(BTN_DOWN, 4)) { 00927 activeY++; 00928 sound.playTick(); 00929 } 00930 if (buttons.repeat(BTN_UP, 4)) { 00931 activeY--; 00932 sound.playTick(); 00933 } 00934 if (buttons.repeat(BTN_RIGHT, 4)) { 00935 activeX++; 00936 sound.playTick(); 00937 } 00938 if (buttons.repeat(BTN_LEFT, 4)) { 00939 activeX--; 00940 sound.playTick(); 00941 } 00942 //don't go out of the keyboard 00943 if (activeX == KEYBOARD_W) activeX = 0; 00944 if (activeX < 0) activeX = KEYBOARD_W - 1; 00945 if (activeY == KEYBOARD_H) activeY = 0; 00946 if (activeY < 0) activeY = KEYBOARD_H - 1; 00947 //set the keyboard position on screen 00948 targetX = -(display.fontWidth+1) * activeX + LCDWIDTH / 2 - 3; 00949 targetY = -(display.fontHeight+1) * activeY + LCDHEIGHT / 2 - 4 - display.fontHeight; 00950 //smooth the keyboard displacement 00951 currentX = (targetX + currentX) / 2; 00952 currentY = (targetY + currentY) / 2; 00953 //type character 00954 if (buttons.pressed(BTN_A)) { 00955 if (activeChar < (length-1)) { 00956 byte thisChar = activeX + KEYBOARD_W * activeY; 00957 if((thisChar == 0)||(thisChar == 10)||(thisChar == 13)) //avoid line feed and carriage return 00958 continue; 00959 text[activeChar] = thisChar; 00960 text[activeChar+1] = '\0'; 00961 } 00962 activeChar++; 00963 sound.playOK(); 00964 if (activeChar > length) 00965 activeChar = length; 00966 } 00967 //erase character 00968 if (buttons.pressed(BTN_B)) { 00969 activeChar--; 00970 sound.playCancel(); 00971 if (activeChar >= 0) 00972 text[activeChar] = 0; 00973 else 00974 activeChar = 0; 00975 } 00976 //leave menu 00977 if (buttons.pressed(BTN_C)) { 00978 sound.playOK(); 00979 while (1) { 00980 if (update()) { 00981 //display.setCursor(0,0); 00982 display.println(("You entered\n")); 00983 display.print(text); 00984 display.println(("\n\n\n\x15:okay \x16:edit")); 00985 if(buttons.pressed(BTN_A)){ 00986 sound.playOK(); 00987 return; 00988 } 00989 if(buttons.pressed(BTN_B)){ 00990 sound.playCancel(); 00991 break; 00992 } 00993 } 00994 } 00995 } 00996 //draw the keyboard 00997 for (int8_t y = 0; y < KEYBOARD_H; y++) { 00998 for (int8_t x = 0; x < KEYBOARD_W; x++) { 00999 display.drawChar(currentX + x * (display.fontWidth+1), currentY + y * (display.fontHeight+1), x + y * KEYBOARD_W, 1); 01000 } 01001 } 01002 //draw instruction 01003 display.cursorX = currentX-display.fontWidth*6-2; 01004 display.cursorY = currentY+1*(display.fontHeight+1); 01005 display.print(("\25type")); 01006 01007 display.cursorX = currentX-display.fontWidth*6-2; 01008 display.cursorY = currentY+2*(display.fontHeight+1); 01009 display.print(("\26back")); 01010 01011 display.cursorX = currentX-display.fontWidth*6-2; 01012 display.cursorY = currentY+3*(display.fontHeight+1); 01013 display.print(("\27save")); 01014 01015 //erase some pixels around the selected character 01016 display.setColor(WHITE); 01017 display.drawFastHLine(currentX + activeX * (display.fontWidth+1) - 1, currentY + activeY * (display.fontHeight+1) - 2, 7); 01018 //draw the selection rectangle 01019 display.setColor(BLACK); 01020 display.drawRoundRect(currentX + activeX * (display.fontWidth+1) - 2, currentY + activeY * (display.fontHeight+1) - 3, (display.fontWidth+2)+(display.fontWidth-1)%2, (display.fontHeight+5), 3); 01021 //draw keyboard outline 01022 //display.drawRoundRect(currentX - 6, currentY - 6, KEYBOARD_W * (display.fontWidth+1) + 12, KEYBOARD_H * (display.fontHeight+1) + 12, 8, BLACK); 01023 //text field 01024 display.drawFastHLine(0, LCDHEIGHT-display.fontHeight-2, LCDWIDTH); 01025 display.setColor(WHITE); 01026 display.fillRect(0, LCDHEIGHT-display.fontHeight-1, LCDWIDTH, display.fontHeight+1); 01027 //typed text 01028 display.cursorX = 0; 01029 display.cursorY = LCDHEIGHT-display.fontHeight; 01030 display.setColor(BLACK); 01031 display.print(text); 01032 //blinking cursor 01033 if (((frameCount % 8) < 4) && (activeChar < (length-1))) 01034 display.drawChar(display.fontWidth * activeChar, LCDHEIGHT-display.fontHeight, '_',1); 01035 } 01036 } 01037 #endif 01038 } 01039 01040 void Core::popup(const char* text, uint8_t duration){ 01041 #if (ENABLE_GUI > 0) 01042 popupText = text; 01043 popupTimeLeft = duration+12; 01044 #endif 01045 } 01046 01047 void Core::updatePopup(){ 01048 #if (ENABLE_GUI > 0) 01049 if (popupTimeLeft){ 01050 uint8_t yOffset = 0; 01051 if(popupTimeLeft<12){ 01052 yOffset = 12-popupTimeLeft; 01053 } 01054 display.fontSize = 1; 01055 display.setColor(WHITE); 01056 display.fillRoundRect(0,LCDHEIGHT-display.fontHeight+yOffset-3,84,display.fontHeight+3,3); 01057 display.setColor(BLACK); 01058 display.drawRoundRect(0,LCDHEIGHT-display.fontHeight+yOffset-3,84,display.fontHeight+3,3); 01059 display.cursorX = 4; 01060 display.cursorY = LCDHEIGHT-display.fontHeight+yOffset-1; 01061 display.print(popupText); 01062 popupTimeLeft--; 01063 } 01064 #endif 01065 } 01066 01067 void Core::setFrameRate(uint8_t fps) { 01068 timePerFrame = 1000 / fps; 01069 sound.prescaler = fps / 20; 01070 sound.prescaler = __avrmax(1, sound.prescaler); 01071 } 01072 01073 void Core::pickRandomSeed(){ 01074 initRandom(); 01075 } 01076 01077 bool Core::collidePointRect(int16_t x1, int16_t y1 ,int16_t x2 ,int16_t y2, int16_t w, int16_t h){ 01078 if((x1>=x2)&&(x1<x2+w)) 01079 if((y1>=y2)&&(y1<y2+h)) 01080 return true; 01081 return false; 01082 } 01083 01084 bool Core::collideRectRect(int16_t x1, int16_t y1, int16_t w1, int16_t h1 ,int16_t x2 ,int16_t y2, int16_t w2, int16_t h2){ 01085 return !( x2 >= x1+w1 || 01086 x2+w2 <= x1 || 01087 y2 >= y1+h1 || 01088 y2+h2 <= y1 ); 01089 } 01090 01091 bool Core::collideBitmapBitmap(int16_t x1, int16_t y1, const uint8_t* b1, int16_t x2, int16_t y2, const uint8_t* b2){ 01092 int16_t w1 = pgm_read_byte(b1); 01093 int16_t h1 = pgm_read_byte(b1 + 1); 01094 int16_t w2 = pgm_read_byte(b2); 01095 int16_t h2 = pgm_read_byte(b2 + 1); 01096 01097 if(collideRectRect(x1, y1, w1, h1, x2, y2, w2, h2) == false){ 01098 return false; 01099 } 01100 01101 int16_t xmin = (x1>=x2)? 0 : x2-x1; 01102 int16_t ymin = (y1>=y2)? 0 : y2-y1; 01103 int16_t xmax = (x1+w1>=x2+w2)? x2+w2-x1 : w1; 01104 int16_t ymax = (y1+h1>=y2+h2)? y2+h2-y1 : h1; 01105 for(uint8_t y = ymin; y < ymax; y++){ 01106 for(uint8_t x = xmin; x < xmax; x++){ 01107 if(display.getBitmapPixel(b1, x, y) && display.getBitmapPixel(b2, x1+x-x2, y1+y-y2)){ 01108 return true; 01109 } 01110 } 01111 } 01112 return false; 01113 } 01114 01115 01116 //** EOF **// 01117 01118 01119 01120 01121 01122 01123 01124
Generated on Tue Jul 12 2022 18:08:12 by
1.7.2
