/ MCUME_teensy / teensygen / teensygen.ino
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