go.cpp
1 #include "go.h" 2 3 extern "C" { 4 #include "emuapi.h" 5 #include "iopins.h" 6 } 7 8 #include "esp_event.h" 9 10 #include "keyboard_osd.h" 11 12 13 #include "ili9341_t3dma.h" 14 #ifdef HAS_SND 15 #include "AudioPlaySystem.h" 16 #include "LibFC14/fc14audiodecoder.h" 17 #include "loader.h" 18 #endif 19 20 #include <rom/rtc.h> 21 #include <string.h> 22 #include <math.h> 23 #include "mcume.h" 24 25 #define RTC_SLOW_MEM ((uint32_t*) 0x50000000) /*!< RTC slow memory, 8k size */ 26 27 #define ULP_DATA_OFFSET 36 28 29 _Static_assert(ULP_DATA_OFFSET < CONFIG_ULP_COPROC_RESERVE_MEM/4 - 6, 30 "ULP_DATA_OFFSET is set too high, or CONFIG_ULP_COPROC_RESERVE_MEM is not sufficient"); 31 32 static inline uint16_t ulp_data_read(size_t offset) 33 { 34 return RTC_SLOW_MEM[ULP_DATA_OFFSET + offset] & 0xffff; 35 } 36 static inline void ulp_data_write(size_t offset, uint16_t value) 37 { 38 RTC_SLOW_MEM[ULP_DATA_OFFSET + offset] = value; 39 } 40 41 42 ILI9341_t3DMA tft = ILI9341_t3DMA(PIN_NUM_CS, PIN_NUM_DC, -1, PIN_NUM_MOSI, PIN_NUM_CLK, PIN_NUM_MISO, TPIN_NUM_CS, TPIN_NUM_IRQ); 43 #ifdef HAS_SND 44 AudioPlaySystem audio; 45 static void *decoder = nullptr; 46 #endif 47 48 49 #define MAX_FILENAME_SIZE 18 50 #define MAX_MENULINES 7 51 #define TEXT_HEIGHT 16 52 #define TEXT_WIDTH 8 53 #define MENU_FILE_XOFFSET (11*TEXT_WIDTH) 54 #define MENU_FILE_YOFFSET (7*TEXT_HEIGHT) 55 #define MENU_FILE_W (MAX_FILENAME_SIZE*TEXT_WIDTH) 56 #define MENU_FILE_H (MAX_MENULINES*TEXT_HEIGHT) 57 #define MENU_FILE_FGCOLOR RGBVAL16(0xff,0xff,0xff) 58 #define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x10) 59 60 61 #define NB_APPS 8 62 63 static bool menuRedraw=false; 64 static int nbFiles=NB_APPS; 65 static int curFile=0; 66 static int topFile=0; 67 static int xOffLogo=0; 68 static int swipeAngle=0; 69 70 static char * apps[NB_APPS] = { 71 " Zx81 ", 72 " Zx Spectrum ", 73 " Atari 800 ", 74 " C64 ", 75 " Atari 2600 ", 76 //" Odyssey ", 77 " NES ", 78 " Colecovision ", 79 " Atari 5200 " 80 }; 81 82 83 static void initBootMenu(void) { 84 menuRedraw=true; 85 tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00)); 86 //tft.drawSpriteNoDma(30,10,(uint16_t*)logo); 87 //tft.drawTextNoDma(0,0, TITLE, RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true); 88 } 89 90 91 92 static int handleBootMenu(unsigned short bClick) 93 { 94 int action = -1; 95 xOffLogo = 16*sin((2*3.14*swipeAngle)/256)+30; 96 swipeAngle = (swipeAngle + 2)&0xff; 97 //printf("xOffLogo %d %d\n",xOffLogo,swipeAngle); 98 tft.drawSpriteNoDma(xOffLogo,10,(uint16_t*)logo); 99 100 if (bClick & MASK_JOY2_UP) { 101 if (curFile!=0) { 102 menuRedraw=true; 103 curFile--; 104 } 105 } 106 else if (bClick & MASK_JOY2_DOWN) { 107 if ((curFile<(nbFiles-1)) && (nbFiles)) { 108 curFile++; 109 menuRedraw=true; 110 } 111 } 112 else if (bClick & MASK_JOY2_BTN) { 113 action = curFile; 114 } 115 116 if (menuRedraw && nbFiles) { 117 //printf("update\n"); 118 int fileIndex = 0; 119 int appcnt=0; 120 tft.drawRectNoDma(MENU_FILE_XOFFSET,MENU_FILE_YOFFSET, MENU_FILE_W, MENU_FILE_H, MENU_FILE_BGCOLOR); 121 if (curFile <= (MAX_MENULINES/2-1)) topFile=0; 122 else topFile=curFile-(MAX_MENULINES/2); 123 //if (curFile <= (MAX_MENULINES-1)) topFile=0; 124 //else topFile=curFile-(MAX_MENULINES/2); 125 126 int i=0; 127 while (i<MAX_MENULINES) { 128 if (appcnt == (NB_APPS)) { 129 break; 130 } 131 char * title=apps[appcnt++]; 132 if (fileIndex >= topFile) { 133 if ((i+topFile) < nbFiles ) { 134 int dx = (MAX_FILENAME_SIZE-strlen(title))*TEXT_WIDTH/2; 135 if ((i+topFile)==curFile) { 136 tft.drawTextNoDma(MENU_FILE_XOFFSET+dx,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, title, RGBVAL16(0xff,0xff,0x00), RGBVAL16(0xff,0x00,0x00), true); 137 } 138 else { 139 tft.drawTextNoDma(MENU_FILE_XOFFSET+dx,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, title, MENU_FILE_FGCOLOR, MENU_FILE_BGCOLOR, true); 140 } 141 } 142 i++; 143 } 144 fileIndex++; 145 } 146 147 148 menuRedraw=false; 149 } 150 151 152 return (action); 153 } 154 155 156 static void spi_task(void *args) 157 { 158 while(true) { 159 tft.refresh(); 160 } 161 } 162 163 static void input_task(void *args) 164 { 165 while(true) { 166 if ((emu_ReadKeys() & (MASK_KEY_USER1+MASK_KEY_USER2)) == (MASK_KEY_USER1+MASK_KEY_USER2)) { 167 printf("rebooting\n"); 168 esp_restart(); 169 } 170 171 uint16_t bClick = emu_DebounceLocalKeys(); 172 if (bClick & MASK_KEY_USER2) { 173 printf("%d\n",emu_SwapJoysticks(1)); 174 emu_SwapJoysticks(0); 175 } 176 else { 177 //emu_Input(bClick); 178 } 179 #ifdef HAS_SND 180 audio.step(); 181 #endif 182 vTaskDelay(20 / portTICK_PERIOD_MS); 183 } 184 } 185 186 187 static void main_step() { 188 uint16_t bClick = emu_DebounceLocalKeys(); 189 int action = handleBootMenu(bClick); 190 if (action >= 0) { 191 printf("launching\n"); 192 ulp_data_write(0, action); 193 esp_restart(); 194 } 195 #ifdef HAS_SND 196 audio.step(); 197 #endif 198 //vTaskDelay(20 / portTICK_PERIOD_MS); 199 } 200 201 202 203 204 void setup(void) 205 { 206 printf("App selector\n"); 207 208 tft.begin(); 209 tft.flipscreen(true); 210 tft.start(); 211 tft.refresh(); 212 213 emu_InitJoysticks(); 214 initBootMenu(); 215 216 xTaskCreatePinnedToCore(spi_task, "spithread", 4096, NULL, 1, NULL, 0); 217 //vTaskPrioritySet(NULL, tskIDLE_PRIORITY+1); 218 219 #ifdef HAS_SND 220 audio.begin(); 221 audio.start(); 222 bool haveModule = false; 223 decoder = fc14dec_new(); 224 haveModule = fc14dec_init(decoder,(void*)musym,sizeof(musym)); 225 if ( !haveModule ) { 226 fc14dec_delete(decoder); 227 printf("FC module not supported\n"); 228 } 229 else { 230 printf("FC music loaded\n"); 231 fc14dec_mixer_init(decoder,22050,16,1,0 /*32767*/); 232 233 } 234 #endif 235 } 236 237 void loop(void) 238 { 239 unsigned long t = esp_timer_get_time(); 240 main_step(); 241 //printf("%d\n",(int)((esp_timer_get_time()-t)/1000)); 242 } 243 244 245 void SND_Process( void* stream, int len) { 246 #ifdef HAS_SND 247 fc14dec_buffer_fill(decoder,stream,len*2); 248 #endif 249 } 250