teensygen.ino
1 extern "C" { 2 #include "iopins.h" 3 #include "emuapi.h" 4 } 5 #include "keyboard_osd.h" 6 7 8 #include "emu.h" 9 10 #ifdef HAS_VGA 11 #include <uVGA.h> 12 uVGA uvga; 13 #if F_CPU == 144000000 14 #define UVGA_144M_326X240 15 #define UVGA_XRES 326 16 #define UVGA_YRES 240 17 #define UVGA_XRES_EXTRA 10 18 #elif F_CPU == 180000000 19 #define UVGA_180M_360X300 20 #define UVGA_XRES 360 21 #define UVGA_YRES 300 22 #define UVGA_XRES_EXTRA 8 23 #elif F_CPU == 240000000 24 #define UVGA_240M_452X240 25 #define UVGA_XRES 452 26 #define UVGA_YRES 240 27 #define UVGA_XRES_EXTRA 12 28 #else 29 #error Please select F_CPU=240MHz or F_CPU=180MHz or F_CPU=144MHz 30 #endif 31 32 #include <uVGA_valid_settings.h> 33 34 uint8_t * VGA_frame_buffer; 35 #endif 36 37 38 #ifdef HAS_T4_VGA 39 #include "vga_t_dma.h" 40 TFT_T_DMA tft; 41 #else 42 #include "tft_t_dma.h" 43 TFT_T_DMA tft = TFT_T_DMA(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO, TFT_TOUCH_CS, TFT_TOUCH_INT); 44 #endif 45 46 bool vgaMode = false; 47 48 static unsigned char palette8[PALETTE_SIZE]; 49 static unsigned short palette16[PALETTE_SIZE]; 50 static IntervalTimer myTimer; 51 volatile boolean vbl=true; 52 static int skip=0; 53 static elapsedMicros tius; 54 55 static void vblCount() { 56 if (vbl) { 57 vbl = false; 58 } else { 59 vbl = true; 60 } 61 } 62 63 void emu_SetPaletteEntry(unsigned char r, unsigned char g, unsigned char b, int index) 64 { 65 if (index<PALETTE_SIZE) { 66 palette8[index] = RGBVAL8(r,g,b); 67 palette16[index] = RGBVAL16(r,g,b); 68 } 69 } 70 71 void emu_DrawVsync(void) 72 { 73 volatile boolean vb=vbl; 74 skip += 1; 75 skip &= VID_FRAME_SKIP; 76 if (!vgaMode) { 77 #ifdef HAS_T4_VGA 78 tft.waitSync(); 79 #else 80 while (vbl==vb) {}; 81 #endif 82 } 83 #ifdef HAS_VGA 84 else { 85 while (vbl==vb) {}; 86 } 87 #endif 88 } 89 90 void emu_DrawLine(unsigned char * VBuf, int width, int height, int line) 91 { 92 if (!vgaMode) { 93 #ifdef HAS_T4_VGA 94 tft.writeLine(width,height,line, VBuf, palette8); 95 #else 96 tft.writeLine(width,1,line, VBuf, palette16); 97 #endif 98 } 99 #ifdef HAS_VGA 100 else { 101 int fb_width=UVGA_XRES,fb_height=UVGA_YRES; 102 fb_width += UVGA_XRES_EXTRA; 103 int offx = (fb_width-width)/2; 104 int offy = (fb_height-height)/2+line; 105 uint8_t * dst=VGA_frame_buffer+(fb_width*offy)+offx; 106 for (int i=0; i<width; i++) 107 { 108 uint8_t pixel = palette8[*VBuf++]; 109 *dst++=pixel; 110 } 111 } 112 #endif 113 } 114 115 void emu_DrawLine8(unsigned char * VBuf, int width, int height, int line) 116 { 117 if (!vgaMode) { 118 if (skip==0) { 119 #ifdef HAS_T4_VGA 120 tft.writeLine(width,height,line, VBuf); 121 #endif 122 } 123 } 124 #ifdef HAS_VGA 125 #endif 126 } 127 128 void emu_DrawLine16(unsigned short * VBuf, int width, int height, int line) 129 { 130 if (!vgaMode) { 131 if (skip==0) { 132 #ifdef HAS_T4_VGA 133 tft.writeLine16(width,height,line, VBuf); 134 #else 135 tft.writeLine(width,height,line, VBuf); 136 #endif 137 } 138 } 139 #ifdef HAS_VGA 140 #endif 141 } 142 143 void emu_DrawScreen(unsigned char * VBuf, int width, int height, int stride) 144 { 145 if (!vgaMode) { 146 if (skip==0) { 147 #ifdef HAS_T4_VGA 148 tft.writeScreen(width,height-TFT_VBUFFER_YCROP,stride, VBuf+(TFT_VBUFFER_YCROP/2)*stride, palette8); 149 #else 150 tft.writeScreen(width,height-TFT_VBUFFER_YCROP,stride, VBuf+(TFT_VBUFFER_YCROP/2)*stride, palette16); 151 #endif 152 } 153 } 154 #ifdef HAS_VGA 155 else { 156 int fb_width=UVGA_XRES, fb_height=UVGA_YRES; 157 //uvga.get_frame_buffer_size(&fb_width, &fb_height); 158 fb_width += UVGA_XRES_EXTRA; 159 int offx = (fb_width-width)/2; 160 int offy = (fb_height-height)/2; 161 uint8_t * buf=VGA_frame_buffer+(fb_width*offy)+offx; 162 for (int y=0; y<height; y++) 163 { 164 uint8_t * dest = buf; 165 for (int x=0; x<width; x++) 166 { 167 uint8_t pixel = palette8[*VBuf++]; 168 *dest++=pixel; 169 //*dest++=pixel; 170 } 171 buf += fb_width; 172 VBuf += (stride-width); 173 } 174 } 175 #endif 176 } 177 178 int emu_FrameSkip(void) 179 { 180 return skip; 181 } 182 183 void * emu_LineBuffer(int line) 184 { 185 if (!vgaMode) { 186 return (void*)tft.getLineBuffer(line); 187 } 188 #ifdef HAS_VGA 189 else { 190 int fb_width=UVGA_XRES; 191 fb_width += UVGA_XRES_EXTRA; 192 return (void*)VGA_frame_buffer+(fb_width*line); 193 } 194 #endif 195 } 196 197 // **************************************************** 198 // the setup() method runs once, when the sketch starts 199 // **************************************************** 200 void setup() { 201 202 #ifdef HAS_T4_VGA 203 tft.begin(VGA_MODE_320x240); 204 // NVIC_SET_PRIORITY(IRQ_QTIMER3, 0); 205 #else 206 tft.begin(); 207 #endif 208 emu_init(); 209 210 myTimer.begin(vblCount, 20000); //to run every 20ms 211 } 212 213 214 // **************************************************** 215 // the loop() method runs continuously 216 // **************************************************** 217 void loop(void) 218 { 219 if (menuActive()) { 220 uint16_t bClick = emu_DebounceLocalKeys(); 221 int action = handleMenu(bClick); 222 char * filename = menuSelection(); 223 if (action == ACTION_RUNTFT) { 224 toggleMenu(false); 225 vgaMode = false; 226 emu_start(); 227 emu_Init(filename); 228 //digitalWrite(TFT_CS, 1); 229 //digitalWrite(SD_CS, 1); 230 tft.fillScreenNoDma( RGBVAL16(0x00,0x00,0x00) ); 231 tft.startDMA(); 232 } 233 else if (action == ACTION_RUNVGA) { 234 #ifdef HAS_VGA 235 toggleMenu(false); 236 vgaMode = true; 237 VGA_frame_buffer = (uint8_t *)malloc((UVGA_YRES*(UVGA_XRES+UVGA_XRES_EXTRA))*sizeof(uint8_t)); 238 uvga.set_static_framebuffer(VGA_frame_buffer); 239 emu_start(); 240 emu_Init(filename); 241 int retvga = uvga.begin(&modeline); 242 Serial.println(retvga); 243 Serial.print("VGA init: "); 244 Serial.println(retvga); 245 uvga.clear(0x00); 246 tft.fillScreenNoDma( RGBVAL16(0x00,0x00,0x00) ); 247 // In VGA mode, we show the keyboard on TFT 248 toggleVirtualkeyboard(true); // keepOn 249 Serial.println("Starting"); 250 #endif 251 } 252 delay(20); 253 } 254 else if (callibrationActive()) { 255 uint16_t bClick = emu_DebounceLocalKeys(); 256 handleCallibration(bClick); 257 } 258 else { 259 #if defined(__IMXRT1052__) || defined(__IMXRT1062__) 260 #else 261 handleVirtualkeyboard(); 262 #endif 263 if ( (!virtualkeyboardIsActive()) || (vgaMode) ) { 264 emu_Step(); 265 uint16_t bClick = emu_DebounceLocalKeys(); 266 emu_Input(bClick); 267 } 268 } 269 } 270 271 #ifdef HAS_SND 272 273 #include "AudioPlaySystem.h" 274 275 AudioPlaySystem mymixer; 276 #ifndef HAS_T4_VGA 277 #include <Audio.h> 278 #if defined(__IMXRT1052__) || defined(__IMXRT1062__) 279 //AudioOutputMQS mqs; 280 //AudioConnection patchCord9(mymixer, 0, mqs, 1); 281 AudioOutputI2S i2s1; 282 AudioConnection patchCord8(mymixer, 0, i2s1, 0); 283 AudioConnection patchCord9(mymixer, 0, i2s1, 1); 284 AudioControlSGTL5000 sgtl5000_1; 285 #else 286 AudioOutputAnalog dac1; 287 AudioConnection patchCord1(mymixer, dac1); 288 #endif 289 #endif 290 291 void emu_sndInit() { 292 Serial.println("sound init"); 293 #ifdef HAS_T4_VGA 294 tft.begin_audio(256, mymixer.snd_Mixer); 295 // sgtl5000_1.enable(); 296 // sgtl5000_1.volume(0.6); 297 #endif 298 mymixer.start(); 299 } 300 301 void emu_sndPlaySound(int chan, int volume, int freq) 302 { 303 if (chan < 6) { 304 mymixer.sound(chan, freq, volume); 305 } 306 /* 307 Serial.print(chan); 308 Serial.print(":" ); 309 Serial.print(volume); 310 Serial.print(":" ); 311 Serial.println(freq); 312 */ 313 } 314 315 void emu_sndPlayBuzz(int size, int val) { 316 mymixer.buzz(size,val); 317 //Serial.print((val==1)?1:0); 318 //Serial.print(":"); 319 //Serial.println(size); 320 } 321 #endif