/ MCUME_teensy / teensy64 / emuapi.cpp
emuapi.cpp
   1  #define KEYMAP_PRESENT 1
   2  
   3  extern "C" {
   4    #include "emuapi.h"
   5    #include "iopins.h"
   6  }
   7  
   8  #ifdef HAS_T4_VGA
   9  #include "vga_t_dma.h"
  10  const uint16_t deflogo[] = {
  11    0,0
  12  };
  13  static const uint16_t * logo = deflogo;
  14  #else
  15  #include "tft_t_dma.h"
  16  #include "logo.h"
  17  #endif
  18  
  19  #include "bmpjoy.h"
  20  #include "bmpvbar.h"
  21  #ifdef OLD_LAYOUT    
  22  #include "bmpvga.h"
  23  #include "bmptft.h"
  24  #endif
  25  
  26  
  27  #ifdef HAS_I2CKBD
  28  #include <Wire.h>
  29  #endif
  30  
  31  #ifdef HAS_USBKEY
  32  #include "USBHost_t36.h"  // Read this header first for key info
  33  USBHost myusb;
  34  USBHub hub1(myusb);
  35  KeyboardController keyboard1(myusb);
  36  #endif
  37  static uint8_t usbnavpad=0;
  38  
  39  #ifdef USE_SDFS
  40  #include "uSDFS.h"
  41  static FATFS fatfs;
  42  static FIL file; 
  43  #else
  44  
  45  #ifdef USE_SDFAT
  46  #include "SdFat.h"
  47  #include "sdios.h"
  48  
  49  #ifndef SDCARD_SS_PIN
  50  const uint8_t SD_CS_PIN = SS;
  51  
  52  #else  // SDCARD_SS_PIN
  53  // Assume built-in SD is used.
  54  const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
  55  #endif  // SDCARD_SS_PIN
  56  
  57  #define SD_CONFIG SdioConfig(FIFO_SDIO)
  58  
  59  // Try to select the best SD card configuration.
  60  #if HAS_SDIO_CLASS
  61  #define SD_CONFIG SdioConfig(FIFO_SDIO)
  62  #elif ENABLE_DEDICATED_SPI
  63  #define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI)
  64  #else  // HAS_SDIO_CLASS
  65  #define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI)
  66  #endif  // HAS_SDIO_CLASS
  67  //------------------------------------------------------------------------------
  68  
  69  #if SD_FAT_TYPE == 0
  70  #elif SD_FAT_TYPE == 1
  71  #define SdFat SdFat32
  72  #define File File32
  73  #elif SD_FAT_TYPE == 2
  74  #define SdFat SdExFat
  75  #define File ExFile
  76  #elif SD_FAT_TYPE == 3
  77  #define SdFat SdFs
  78  #define File FsFile
  79  #endif  // SD_FAT_TYPE
  80  static SdFat SD;
  81  #else
  82  #include <SD.h>
  83  #endif
  84  static File file;
  85  #endif
  86  
  87  #define CALIBRATION_FILE    "/cal.cfg"
  88  
  89  #define MKEY_L1             1
  90  #define MKEY_L2             2
  91  #define MKEY_L3             3
  92  #define MKEY_L4             4
  93  #define MKEY_L5             5
  94  #define MKEY_L6             6
  95  #define MKEY_L7             7
  96  #define MKEY_L8             8
  97  #define MKEY_L9             9
  98  #define MKEY_UP             20
  99  #define MKEY_DOWN           21
 100  #define MKEY_JOY            22
 101  #define MKEY_TFT            23
 102  #define MKEY_VGA            24
 103  
 104  #define MAX_FILES           64
 105  #define MAX_FILENAME_SIZE   24
 106  #define MAX_MENULINES       (MKEY_L9)
 107  #define TEXT_HEIGHT         16
 108  #define TEXT_WIDTH          8
 109  #define MENU_FILE_XOFFSET   (6*TEXT_WIDTH)
 110  #define MENU_FILE_YOFFSET   (2*TEXT_HEIGHT)
 111  #define MENU_FILE_W         (MAX_FILENAME_SIZE*TEXT_WIDTH)
 112  #define MENU_FILE_H         (MAX_MENULINES*TEXT_HEIGHT)
 113  #define MENU_FILE_BGCOLOR   RGBVAL16(0x00,0x00,0x40)
 114  #define MENU_JOYS_YOFFSET   (12*TEXT_HEIGHT)
 115  #define MENU_VBAR_XOFFSET   (0*TEXT_WIDTH)
 116  #define MENU_VBAR_YOFFSET   (MENU_FILE_YOFFSET)
 117  
 118  #define MENU_TFT_XOFFSET    (MENU_FILE_XOFFSET+MENU_FILE_W+8)
 119  #define MENU_TFT_YOFFSET    (MENU_VBAR_YOFFSET+32)
 120  #define MENU_VGA_XOFFSET    (MENU_FILE_XOFFSET+MENU_FILE_W+8)
 121  #define MENU_VGA_YOFFSET    (MENU_VBAR_YOFFSET+MENU_FILE_H-32-37)
 122  
 123  extern TFT_T_DMA tft;
 124  
 125  static char romspath[64];
 126  static int nbFiles=0;
 127  static int curFile=0;
 128  static int topFile=0;
 129  static char selection[MAX_FILENAME_SIZE+1]="";
 130  static char files[MAX_FILES][MAX_FILENAME_SIZE];
 131  static bool menuRedraw=true;
 132  
 133  static int calMinX=-1,calMinY=-1,calMaxX=-1,calMaxY=-1;
 134  static bool i2cKeyboardPresent = false;
 135  static unsigned short * keys;
 136  static int keyMap;
 137  
 138  const unsigned short menutouchareas[] = {
 139    TAREA_XY,MENU_FILE_XOFFSET,MENU_FILE_YOFFSET,
 140    TAREA_WH,MENU_FILE_W, TEXT_HEIGHT,
 141    TAREA_NEW_COL,TEXT_HEIGHT,TEXT_HEIGHT,TEXT_HEIGHT,TEXT_HEIGHT,TEXT_HEIGHT,TEXT_HEIGHT,TEXT_HEIGHT,TEXT_HEIGHT,TEXT_HEIGHT,
 142    
 143    TAREA_XY,MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,
 144    TAREA_WH,32,48,
 145    TAREA_NEW_COL, 72,72,8,40,
 146  
 147    TAREA_XY,MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,
 148    TAREA_WH,32,37,
 149    TAREA_NEW_COL, 38,38,
 150      
 151    TAREA_END};
 152     
 153  const unsigned short menutouchactions[] = {
 154    MKEY_L1,MKEY_L2,MKEY_L3,MKEY_L4,MKEY_L5,MKEY_L6,MKEY_L7,MKEY_L8,MKEY_L9,
 155    MKEY_UP,MKEY_DOWN,ACTION_NONE,MKEY_JOY,
 156    MKEY_TFT,MKEY_VGA}; 
 157  
 158  
 159  static int keypadval=0; 
 160  static boolean joySwapped = false;
 161  static uint16_t bLastState;
 162  static int xRef;
 163  static int yRef;
 164  static uint8_t prev_zt=0; 
 165  
 166  static bool menuOn=true;
 167  static bool callibrationOn=false;
 168  static int callibrationStep=0;
 169  
 170  
 171  static char captureTouchZone(const unsigned short * areas, const unsigned short * actions, int *rx, int *ry, int *rw, int * rh) {
 172      uint16_t xt=0;
 173      uint16_t yt=0;
 174      uint16_t zt=0;
 175      boolean hDir=true;  
 176    
 177      if (tft.isTouching())
 178      {
 179          if (prev_zt == 0) {
 180              prev_zt =1;
 181              tft.readCal(&xt,&yt,&zt);
 182              if (zt<1000) {
 183                prev_zt=0; 
 184                return ACTION_NONE;
 185              }   
 186              int i=0;
 187              int k=0;
 188              int y2=0, y1=0;
 189              int x2=0, x1=0;
 190              int x=KEYBOARD_X,y=KEYBOARD_Y;
 191              int w=TAREA_W_DEF,h=TAREA_H_DEF;
 192              uint8_t s;
 193              while ( (s=areas[i++]) != TAREA_END ) {
 194                  if (s == TAREA_XY) {
 195                      x = areas[i++];
 196                      y = areas[i++];                    
 197                      x2 = x;
 198                      y2 = y;  
 199                  }
 200                  else if (s == TAREA_WH) {
 201                      w = areas[i++];
 202                      h = areas[i++];
 203                  }                     
 204                  else if (s == TAREA_NEW_ROW) {
 205                    hDir = true;
 206                    y1 = y2;
 207                    y2 = y1 + h;
 208                    x2 = x;
 209                  }  
 210                  else if (s == TAREA_NEW_COL) {
 211                    hDir = false;
 212                    x1 = x2;
 213                    x2 = x1 + w;
 214                    y2 = y;                  
 215                  }
 216                  else { 
 217                      if (hDir) {
 218                        x1 = x2;
 219                        x2 = x1+s;                                                            
 220                      } else {
 221                        y1 = y2;
 222                        y2 = y1+s;                      
 223                      }
 224                      if ( (yt >= y1) && (yt < y2) && (xt >= x1) && (xt < x2)  ) {
 225                          *rx = x1;
 226                          *ry = y1;
 227                          *rw = x2-x1;
 228                          *rh = y2-y1;
 229                          return (actions[k]);  
 230                      }
 231                      k++;
 232                  }                
 233              }
 234          } 
 235          prev_zt =1; 
 236      } else {
 237          prev_zt=0; 
 238      } 
 239    
 240      return ACTION_NONE;   
 241  } 
 242  
 243  
 244  
 245  
 246  
 247  
 248  
 249  
 250  void emu_printf(char * text)
 251  {
 252    Serial.println(text);
 253  }
 254  
 255  void emu_printf(int val)
 256  {
 257    Serial.println(val);
 258  }
 259  
 260  void emu_printi(int val)
 261  {
 262    Serial.println(val,HEX);
 263  }
 264  
 265  void emu_printh(int val)
 266  {
 267    Serial.println(val,HEX);
 268  }
 269  
 270  static int malbufpt = 0;
 271  static char malbuf[EXTRA_HEAP];
 272  
 273  void * emu_Malloc(int size)
 274  {
 275    void * retval =  malloc(size);
 276    if (!retval) {
 277      emu_printf("failled to allocate");
 278      emu_printf(size);
 279      emu_printf("fallback");
 280      if ( (malbufpt+size) < sizeof(malbuf) ) {
 281        retval = (void *)&malbuf[malbufpt];
 282        malbufpt += size;      
 283      }
 284      else {
 285        emu_printf("failure to allocate");
 286      }
 287    }
 288    else {
 289      emu_printf("could allocate dynamic ");
 290      emu_printf(size);    
 291    }
 292    
 293    return retval;
 294  }
 295  
 296  void * emu_MallocI(int size)
 297  {
 298    void * retval =  NULL; 
 299  
 300    if ( (malbufpt+size) < sizeof(malbuf) ) {
 301      retval = (void *)&malbuf[malbufpt];
 302      malbufpt += size;
 303      emu_printf("could allocate static ");
 304      emu_printf(size);          
 305    }
 306    else {
 307      emu_printf("failure to allocate");
 308    }
 309  
 310    return retval;
 311  }
 312  void emu_Free(void * pt)
 313  {
 314    free(pt);
 315  }
 316  
 317  
 318  
 319  
 320  
 321  int emu_ReadAnalogJoyX(int min, int max) 
 322  {
 323    int val = analogRead(PIN_JOY2_A1X);
 324  #if INVX
 325    val = 4095 - val;
 326  #endif
 327    val = val-xRef;
 328    val = ((val*140)/100);
 329    if ( (val > -512) && (val < 512) ) val = 0;
 330    val = val+2048;
 331    return (val*(max-min))/4096;
 332  }
 333  
 334  int emu_ReadAnalogJoyY(int min, int max) 
 335  {
 336    int val = analogRead(PIN_JOY2_A2Y);
 337  #if INVY
 338    val = 4095 - val;
 339  #endif
 340    val = val-yRef;
 341    val = ((val*120)/100);
 342    if ( (val > -512) && (val < 512) ) val = 0;
 343    //val = (val*(max-min))/4096;
 344    val = val+2048;
 345    //return val+(max-min)/2;
 346    return (val*(max-min))/4096;
 347  }
 348  
 349  
 350  static uint16_t readAnalogJoystick(void)
 351  {
 352    uint16_t joysval = 0;
 353  
 354    int xReading = emu_ReadAnalogJoyX(0,256);
 355    if (xReading > 128) joysval |= MASK_JOY2_LEFT;
 356    else if (xReading < 128) joysval |= MASK_JOY2_RIGHT;
 357    
 358    int yReading = emu_ReadAnalogJoyY(0,256);
 359    if (yReading < 128) joysval |= MASK_JOY2_UP;
 360    else if (yReading > 128) joysval |= MASK_JOY2_DOWN;
 361    
 362  #ifdef PIN_JOY2_BTN  
 363    joysval |= (digitalRead(PIN_JOY2_BTN) == HIGH ? 0 : MASK_JOY2_BTN);
 364  #endif
 365    return (joysval);     
 366  }
 367  
 368  
 369  int emu_SwapJoysticks(int statusOnly) {
 370    if (!statusOnly) {
 371      if (joySwapped) {
 372        joySwapped = false;
 373      }
 374      else {
 375        joySwapped = true;
 376      }
 377    }
 378    return(joySwapped?1:0);
 379  }
 380  
 381  int emu_GetPad(void) 
 382  {
 383    return(keypadval/*|((joySwapped?1:0)<<7)*/);
 384  }
 385  
 386  int emu_ReadKeys(void) 
 387  {
 388    uint16_t retval;
 389    uint16_t j1 = readAnalogJoystick();
 390    uint16_t j2 = 0;
 391    
 392    // Second joystick
 393  #if INVY
 394  #ifdef PIN_JOY1_1
 395    if ( digitalRead(PIN_JOY1_1) == LOW ) j2 |= MASK_JOY2_DOWN;
 396  #endif
 397  #ifdef PIN_JOY1_2
 398    if ( digitalRead(PIN_JOY1_2) == LOW ) j2 |= MASK_JOY2_UP;
 399  #endif
 400  #else
 401  #ifdef PIN_JOY1_1
 402    if ( digitalRead(PIN_JOY1_1) == LOW ) j2 |= MASK_JOY2_UP;
 403  #endif
 404  #ifdef PIN_JOY1_2
 405    if ( digitalRead(PIN_JOY1_2) == LOW ) j2 |= MASK_JOY2_DOWN;
 406  #endif
 407  #endif
 408  #if INVX
 409  #ifdef PIN_JOY1_3
 410    if ( digitalRead(PIN_JOY1_3) == LOW ) j2 |= MASK_JOY2_LEFT;
 411  #endif
 412  #ifdef PIN_JOY1_4
 413    if ( digitalRead(PIN_JOY1_4) == LOW ) j2 |= MASK_JOY2_RIGHT;
 414  #endif
 415  #else
 416  #ifdef PIN_JOY1_3
 417    if ( digitalRead(PIN_JOY1_3) == LOW ) j2 |= MASK_JOY2_RIGHT;
 418  #endif
 419  #ifdef PIN_JOY1_4
 420    if ( digitalRead(PIN_JOY1_4) == LOW ) j2 |= MASK_JOY2_LEFT;
 421  #endif
 422  #endif
 423  #ifdef PIN_JOY1_BTN
 424    if ( digitalRead(PIN_JOY1_BTN) == LOW ) j2 |= MASK_JOY2_BTN;
 425  #endif
 426    if (joySwapped) {
 427      retval = ((j1 << 8) | j2);
 428    }
 429    else {
 430      retval = ((j2 << 8) | j1);
 431    }
 432  
 433    if (usbnavpad & MASK_JOY2_UP) retval |= MASK_JOY2_UP;
 434    if (usbnavpad & MASK_JOY2_DOWN) retval |= MASK_JOY2_DOWN;
 435    if (usbnavpad & MASK_JOY2_LEFT) retval |= MASK_JOY2_LEFT;
 436    if (usbnavpad & MASK_JOY2_RIGHT) retval |= MASK_JOY2_RIGHT;
 437    if (usbnavpad & MASK_JOY2_BTN) retval |= MASK_JOY2_BTN;
 438  
 439  #ifdef PIN_KEY_USER1 
 440    if ( digitalRead(PIN_KEY_USER1) == LOW ) retval |= MASK_KEY_USER1;
 441  #endif
 442  #ifdef PIN_KEY_USER2 
 443    if ( digitalRead(PIN_KEY_USER2) == LOW ) retval |= MASK_KEY_USER2;
 444  #endif
 445  #ifdef PIN_KEY_USER3 
 446    if ( digitalRead(PIN_KEY_USER3) == LOW ) retval |= MASK_KEY_USER3;
 447  #endif
 448  #ifdef PIN_KEY_USER4 
 449    if ( digitalRead(PIN_KEY_USER4) == LOW ) retval |= MASK_KEY_USER4;
 450  #endif
 451  
 452    //Serial.println(retval,HEX);
 453  
 454    if ( ((retval & (MASK_KEY_USER1+MASK_KEY_USER2)) == (MASK_KEY_USER1+MASK_KEY_USER2))
 455       || (retval & MASK_KEY_USER4 ) )
 456    {  
 457  // Reset procedure T3.X and T4.0 by Frank Boesing !!   
 458  #if defined(__IMXRT1052__) || defined(__IMXRT1062__)    
 459      uint32_t tmp = SNVS_LPCR; // save control register
 460      
 461      SNVS_LPSR |= 1;
 462      
 463      // disable alarm
 464      SNVS_LPCR &= ~0x02;
 465      while (SNVS_LPCR & 0x02);
 466      
 467      __disable_irq();
 468      //get Time:
 469      uint32_t lsb, msb;
 470      do {
 471        msb = SNVS_LPSRTCMR;
 472        lsb = SNVS_LPSRTCLR;
 473      } while ( (SNVS_LPSRTCLR != lsb) | (SNVS_LPSRTCMR != msb) );
 474      uint32_t secs = (msb << 17) | (lsb >> 15);
 475      
 476      //set alarm
 477      secs += 2;
 478      SNVS_LPTAR = secs;
 479      while (SNVS_LPTAR != secs);
 480      
 481      SNVS_LPCR = tmp | 0x02; // restore control register and set alarm
 482      while (!(SNVS_LPCR & 0x02));
 483      
 484      SNVS_LPCR |= (1 << 6); // turn off power
 485      while (1) asm("wfi");  
 486  #else
 487      *(volatile uint32_t *)0xE000ED0C = 0x5FA0004;
 488      while (true) {
 489        ;
 490      } 
 491  #endif 
 492    }
 493    
 494    return (retval);
 495  }
 496  
 497  unsigned short emu_DebounceLocalKeys(void)
 498  {
 499    uint16_t bCurState = emu_ReadKeys();
 500    uint16_t bClick = bCurState & ~bLastState;
 501    bLastState = bCurState;
 502  
 503    return (bClick);
 504  }
 505  
 506  int emu_ReadI2CKeyboard(void) {
 507    int retval=0;
 508  #ifdef HAS_I2CKBD
 509    if (i2cKeyboardPresent) {
 510      byte msg[7]={0,0,0,0,0,0,0};
 511      Wire.requestFrom(8, 7);    // request 7 bytes from slave device #8 
 512      int i = 0;
 513      int hitindex=-1;
 514      while (Wire.available() && (i<7) ) { // slave may send less than requested
 515        byte b = Wire.read(); // receive a byte
 516        if (b != 0xff) hitindex=i; 
 517        msg[i++] = b;        
 518      }
 519      
 520      if (hitindex >=0 ) {
 521        /*
 522        Serial.println(msg[0], BIN);
 523        Serial.println(msg[1], BIN);
 524        Serial.println(msg[2], BIN);
 525        Serial.println(msg[3], BIN);
 526        Serial.println(msg[4], BIN);
 527        Serial.println(msg[5], BIN);
 528        Serial.println(msg[6], BIN);
 529        */
 530        unsigned short match = (~msg[hitindex])&0x00FF | (hitindex<<8);
 531        //Serial.println(match,HEX);  
 532        for (i=0; i<sizeof(i2ckeys); i++) {
 533          if (match == i2ckeys[i]) {
 534            //Serial.println((int)keys[i]);      
 535            return (keys[i]);
 536          }
 537        }
 538      }    
 539    }
 540  #endif
 541    return(retval);
 542  }
 543  
 544  void emu_InitJoysticks(void) { 
 545  
 546    // Second Joystick   
 547  #ifdef PIN_JOY1_1
 548    pinMode(PIN_JOY1_1, INPUT_PULLUP);
 549  #endif  
 550  #ifdef PIN_JOY1_2
 551    pinMode(PIN_JOY1_2, INPUT_PULLUP);
 552  #endif  
 553  #ifdef PIN_JOY1_3
 554    pinMode(PIN_JOY1_3, INPUT_PULLUP);
 555  #endif  
 556  #ifdef PIN_JOY1_4
 557    pinMode(PIN_JOY1_4, INPUT_PULLUP);
 558  #endif  
 559  #ifdef PIN_JOY1_BTN
 560    pinMode(PIN_JOY1_BTN, INPUT_PULLUP);
 561  #endif  
 562  
 563  #ifdef PIN_KEY_USER1
 564    pinMode(PIN_KEY_USER1, INPUT_PULLUP);
 565  #endif  
 566  #ifdef PIN_KEY_USER2
 567    pinMode(PIN_KEY_USER2, INPUT_PULLUP);
 568  #endif  
 569  #ifdef PIN_KEY_USER3
 570    pinMode(PIN_KEY_USER3, INPUT_PULLUP);
 571  #endif  
 572  #ifdef PIN_KEY_USER4
 573    pinMode(PIN_KEY_USER4, INPUT_PULLUP);
 574  #endif  
 575  #ifdef PIN_JOY2_BTN
 576    pinMode(PIN_JOY2_BTN, INPUT_PULLUP);
 577  #endif  
 578    analogReadResolution(12);
 579    xRef=0; yRef=0;
 580    for (int i=0; i<10; i++) {
 581      xRef += analogRead(PIN_JOY2_A1X);
 582      yRef += analogRead(PIN_JOY2_A2Y);  
 583      delay(20);
 584    }
 585  
 586  #if INVX
 587    xRef = 4095 -xRef/10;
 588  #else
 589    xRef /= 10;
 590  #endif
 591  #if INVY
 592    yRef = 4095 -yRef/10;
 593  #else
 594    yRef /= 10;
 595  #endif   
 596  }
 597  
 598  
 599  
 600  static bool vkbKeepOn = false;
 601  static bool vkbActive = false;
 602  static bool vkeyRefresh=false;
 603  static bool exitVkbd = false;
 604  static uint8_t keyPressCount=0; 
 605  
 606  
 607  bool virtualkeyboardIsActive(void) {
 608      return (vkbActive);
 609  }
 610  
 611  void toggleVirtualkeyboard(bool keepOn) {
 612         
 613      if (keepOn) {      
 614          tft.drawSpriteNoDma(0,0,logo);
 615          //prev_zt = 0;
 616          vkbKeepOn = true;
 617          vkbActive = true;
 618          exitVkbd = false;  
 619      }
 620      else {
 621          vkbKeepOn = false;
 622          if ( (vkbActive) /*|| (exitVkbd)*/ ) {
 623              tft.fillScreenNoDma( RGBVAL16(0x00,0x00,0x00) );
 624              tft.startDMA();                     
 625              //prev_zt = 0; 
 626              vkbActive = false;
 627              exitVkbd = false;
 628          }
 629          else {         
 630              tft.stopDMA();                  
 631              tft.drawSpriteNoDma(0,0,logo);           
 632              //prev_zt = 0;
 633              vkbActive = true;
 634              exitVkbd = false;
 635          }
 636      }   
 637  }
 638  
 639   
 640  void handleVirtualkeyboard() {
 641    int rx=0,ry=0,rw=0,rh=0;
 642  
 643      if (keyPressCount == 0) {
 644        keypadval = 0;      
 645      } else {
 646        keyPressCount--;
 647      }
 648      
 649      if ( (!virtualkeyboardIsActive()) && (tft.isTouching()) && (!keyPressCount) ) {
 650          toggleVirtualkeyboard(false);
 651          return;
 652      }
 653      
 654      if ( ( (vkbKeepOn) || (virtualkeyboardIsActive())  )  ) {
 655          char c = captureTouchZone(keysw, keys, &rx,&ry,&rw,&rh);
 656          if (c) {
 657  
 658              tft.drawRectNoDma( rx,ry,rw,rh, KEYBOARD_HIT_COLOR );
 659              if ( (c >=1) && (c <= ACTION_MAXKBDVAL) ) {
 660              
 661                keypadval = c;
 662                keyPressCount = 10;
 663                delay(50);
 664                vkeyRefresh = true;
 665                exitVkbd = true;
 666              }
 667              else if (c == ACTION_EXITKBD) {
 668                vkeyRefresh = true;
 669                exitVkbd = true;  
 670              }
 671          }   
 672       }    
 673       
 674      if (vkeyRefresh) {
 675          vkeyRefresh = false;
 676          tft.drawSpriteNoDma(0,0,logo, rx, ry, rw, rh);
 677      }  
 678           
 679      if ( (exitVkbd) && (vkbActive) ) {      
 680          if (!vkbKeepOn) {             
 681              toggleVirtualkeyboard(false);
 682          }
 683          else {         
 684              toggleVirtualkeyboard(true);           
 685          } 
 686      }
 687  }
 688  
 689  int emu_setKeymap(int index) {
 690  }
 691  
 692  
 693  
 694  
 695  static int readNbFiles(void) {
 696    int totalFiles = 0;
 697  
 698  #ifdef USE_SDFS
 699    DIR dir;
 700    FILINFO entry; 
 701    f_opendir(&dir, romspath);  
 702    while ( (true) && (totalFiles<MAX_FILES) ) {
 703      f_readdir(&dir, &entry);
 704      if (!entry.fname[0]) {
 705        // no more files
 706        break;
 707      }
 708      char * filename = entry.fname;
 709      Serial.println(filename);     
 710      if ( !(entry.fattrib & AM_DIR) ) {
 711        strncpy(&files[totalFiles][0], filename, MAX_FILENAME_SIZE-1);
 712        totalFiles++;
 713      }
 714      else {
 715        if ( (strcmp(filename,".")) && (strcmp(filename,"..")) ) {
 716          strncpy(&files[totalFiles][0], filename, MAX_FILENAME_SIZE-1);
 717          totalFiles++;
 718        }
 719      }  
 720    } 
 721    f_closedir(&dir);
 722  #else
 723    File entry;    
 724    file = SD.open(romspath);
 725    while ( (true) && (totalFiles<MAX_FILES) ) {
 726      entry = file.openNextFile();
 727      if (! entry) {
 728        // no more files
 729        break;
 730      }
 731  #ifdef USE_SDFAT
 732    char filename[MAX_FILENAME_SIZE];
 733    entry.getName(&filename[0], MAX_FILENAME_SIZE); 
 734  #else
 735    char * filename = entry.name();
 736  #endif 
 737      Serial.println(filename); 
 738      if (!entry.isDirectory())  {
 739        strncpy(&files[totalFiles][0], filename, MAX_FILENAME_SIZE-1);
 740        totalFiles++;
 741      }
 742      else {
 743        if ( (strcmp(filename,".")) && (strcmp(filename,"..")) ) {
 744          strncpy(&files[totalFiles][0], filename, MAX_FILENAME_SIZE-1);
 745          totalFiles++;
 746        }
 747      }  
 748      entry.close();
 749    }
 750    file.close();
 751  #endif  
 752    return totalFiles;  
 753  }  
 754  
 755  
 756  
 757  void backgroundMenu(void) {
 758      menuRedraw=true;  
 759      tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
 760      tft.drawTextNoDma(0,0, TITLE, RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);  
 761  #ifndef HAS_T4_VGA
 762      tft.drawSpriteNoDma(MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,bmpvbar);
 763  #endif    
 764  #ifdef OLD_LAYOUT    
 765      tft.drawSpriteNoDma(MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,bmptft);
 766      tft.drawSpriteNoDma(MENU_VGA_XOFFSET,MENU_VGA_YOFFSET,bmpvga);
 767  #endif      
 768  }
 769  
 770  int handleMenu(uint16_t bClick)
 771  {
 772    int action = ACTION_NONE;
 773  
 774    char newpath[80];
 775    strcpy(newpath, romspath);
 776    strcat(newpath, "/");
 777    strcat(newpath, selection);
 778  
 779    int rx=0,ry=0,rw=0,rh=0;
 780    char c = 0; //captureTouchZone(menutouchareas, menutouchactions, &rx,&ry,&rw,&rh);
 781   
 782    if ( (bClick & MASK_JOY2_BTN) || (c == MKEY_TFT) ) {     
 783        emu_printf(newpath);
 784  #ifdef USE_SDFS
 785        FILINFO entry;
 786        f_stat(newpath, &entry);
 787        if ( (entry.fattrib & AM_DIR) ) {
 788  #else
 789        File file = SD.open(newpath);
 790        if (file.isDirectory())  {
 791  #endif      
 792          strcpy(romspath,newpath);
 793          curFile = 0;
 794          nbFiles = readNbFiles();             
 795        }
 796        else {
 797          action = ACTION_RUNTFT;               
 798        }
 799        menuRedraw=true;
 800    }
 801    else if ( (bClick & MASK_KEY_USER1) || (c == MKEY_VGA) ) {
 802        menuRedraw=true;
 803        action = ACTION_RUNVGA;    
 804    }
 805    else if ( (c >= MKEY_L1) && (c <= MKEY_L9) ) {
 806      if ( (topFile+(int)c-1) <= (nbFiles-1)  )
 807      {
 808        curFile = topFile + (int)c -1;
 809        menuRedraw=true;
 810       //tft.drawRectNoDma( rx,ry,rw,rh, KEYBOARD_HIT_COLOR );
 811      }
 812    }
 813    else if (bClick & MASK_JOY2_UP) {
 814      if (curFile!=0) {
 815        menuRedraw=true;
 816        curFile--;
 817      }
 818    }
 819    else if ( (bClick & MASK_JOY2_RIGHT) || (bClick & MASK_JOY1_RIGHT) || (c == MKEY_UP) ) {
 820      if ((curFile-9)>=0) {
 821        menuRedraw=true;
 822        curFile -= 9;
 823      } else if (curFile!=0) {
 824        menuRedraw=true;
 825        curFile--;
 826      }
 827    }  
 828    else if (bClick & MASK_JOY2_DOWN)  {
 829      if ((curFile<(nbFiles-1)) && (nbFiles)) {
 830        curFile++;
 831        menuRedraw=true;
 832      }
 833    }
 834    else if ( (bClick & MASK_JOY2_LEFT) || (bClick & MASK_JOY1_LEFT) || (c == MKEY_DOWN) ) {
 835      if ((curFile<(nbFiles-9)) && (nbFiles)) {
 836        curFile += 9;
 837        menuRedraw=true;
 838      }
 839      else if ((curFile<(nbFiles-1)) && (nbFiles)) {
 840        curFile++;
 841        menuRedraw=true;
 842      }
 843    }
 844    else if ( (bClick & MASK_KEY_USER2) || (c == MKEY_JOY) ) {
 845      emu_SwapJoysticks(0);
 846      menuRedraw=true;  
 847    }   
 848      
 849    if (menuRedraw && nbFiles) {
 850      int fileIndex = 0;
 851      tft.drawRectNoDma(MENU_FILE_XOFFSET,MENU_FILE_YOFFSET, MENU_FILE_W, MENU_FILE_H, MENU_FILE_BGCOLOR);
 852  //    if (curFile <= (MAX_MENULINES/2-1)) topFile=0;
 853  //    else topFile=curFile-(MAX_MENULINES/2);
 854      if (curFile <= (MAX_MENULINES-1)) topFile=0;
 855      else topFile=curFile-(MAX_MENULINES/2);
 856  
 857      //Serial.print("curfile: ");
 858      //Serial.println(curFile);
 859      //Serial.print("topFile: ");
 860      //Serial.println(topFile);
 861      
 862      int i=0;
 863      while (i<MAX_MENULINES) {
 864        if (fileIndex>=nbFiles) {
 865            // no more files
 866            break;
 867        }
 868        char * filename = &files[fileIndex][0];    
 869        if (fileIndex >= topFile) {              
 870          if ((i+topFile) < nbFiles ) {
 871            if ((i+topFile)==curFile) {
 872              tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, RGBVAL16(0xff,0xff,0x00), RGBVAL16(0xff,0x00,0x00), true);
 873              strcpy(selection,filename);            
 874            }
 875            else {
 876              tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, RGBVAL16(0xff,0xff,0xff), MENU_FILE_BGCOLOR, true);      
 877            }
 878          }
 879          i++; 
 880        }
 881        fileIndex++;    
 882      }
 883  
 884  #ifndef HAS_T4_VGA
 885      tft.drawSpriteNoDma(0,MENU_JOYS_YOFFSET,(uint16_t*)bmpjoy);
 886  #endif      
 887      tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, (emu_SwapJoysticks(1)?(char*)"SWAP=1":(char*)"SWAP=0"), RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), false);
 888      menuRedraw=false;     
 889    }
 890  
 891    return (action);  
 892  }
 893  
 894  bool menuActive(void) 
 895  {
 896    return (menuOn);
 897  }
 898  
 899  void toggleMenu(bool on) {
 900    if (on) {
 901      callibrationOn=false;
 902      menuOn=true;
 903      backgroundMenu();
 904    } else {
 905      menuOn = false;    
 906    }
 907  }
 908  
 909  char * menuSelection(void)
 910  {
 911    return (selection);  
 912  }
 913    
 914  
 915  
 916  
 917  static void callibrationInit(void) 
 918  {
 919    callibrationOn=true;
 920    menuOn=false;
 921    callibrationStep = 0;
 922    calMinX=0,calMinY=0,calMaxX=0,calMaxY=0;
 923    tft.fillScreenNoDma(RGBVAL16(0xff,0xff,0xff));
 924    tft.drawTextNoDma(0,100, "          Callibration process:", RGBVAL16(0x00,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true);
 925    tft.drawTextNoDma(0,116, "     Hit the red cross at each corner", RGBVAL16(0x00,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true);
 926    tft.drawTextNoDma(0,0, "+", RGBVAL16(0xff,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true);
 927    prev_zt = 1;  
 928  }
 929  
 930  
 931  static void readCallibration(void) 
 932  {
 933    char fileBuffer[64];
 934  
 935  #ifdef USE_SDFS
 936    FIL file;
 937    int retval;          
 938    if( !(f_open(&file, CALIBRATION_FILE, FA_READ)) ) {
 939      if( !(f_read (&file, fileBuffer, 64, &retval)) ) {
 940        if (retval == 64) { 
 941          sscanf(fileBuffer,"%d %d %d %d", &calMinX,&calMinY,&calMaxX,&calMaxY); 
 942        }
 943      }
 944      f_close(&file);    
 945    }
 946  #else
 947    File file = SD.open(CALIBRATION_FILE, O_READ);  
 948    if (file) {
 949      if ( file.read(fileBuffer, 64) ) {
 950        sscanf(fileBuffer,"%d %d %d %d", &calMinX,&calMinY,&calMaxX,&calMaxY);
 951      }
 952      file.close();
 953      Serial.println("Current callibration params:");
 954      Serial.println(calMinX);
 955      Serial.println(calMinY);
 956      Serial.println(calMaxX);
 957      Serial.println(calMaxY);                 
 958    }
 959  #endif  
 960    else {
 961      Serial.println("Callibration read error");
 962    }  
 963    tft.callibrateTouch(calMinX,calMinY,calMaxX,calMaxY);   
 964  }
 965  
 966  static void writeCallibration(void) 
 967  {
 968    tft.callibrateTouch(calMinX,calMinY,calMaxX,calMaxY);
 969  
 970  #ifdef USE_SDFS
 971    FIL file; 
 972    int retval;       
 973    if( !(f_open(&file, CALIBRATION_FILE, FA_WRITE)) ) {
 974      //if( !(f_read (&file, fileBuffer, 64, &retval)) ) {
 975      //  if (retval == 64) { 
 976      //    sscanf(fileBuffer,"%d %d %d %d", &calMinX,&calMinY,&calMaxX,&calMaxY); 
 977      //  }
 978      //}
 979      f_close(&file);    
 980    }
 981  #else
 982    File file = SD.open(CALIBRATION_FILE, O_WRITE | O_CREAT | O_TRUNC);
 983    if (file) {
 984      file.print(calMinX);
 985      file.print(" ");
 986      file.print(calMinY);
 987      file.print(" ");
 988      file.print(calMaxX);
 989      file.print(" ");
 990      file.println(calMaxY);
 991      file.close();
 992    }
 993  #endif  
 994    else {
 995      Serial.println("Callibration write error");
 996    }  
 997  }
 998  
 999  
1000  bool callibrationActive(void) 
1001  {
1002    return (callibrationOn);
1003  }
1004  
1005  
1006  
1007  int handleCallibration(uint16_t bClick) {
1008    uint16_t xt=0;
1009    uint16_t yt=0;
1010    uint16_t zt=0;  
1011    if (tft.isTouching()) {
1012      if (prev_zt == 0) {
1013        prev_zt = 1;
1014        tft.readRaw(&xt,&yt,&zt);
1015        if (zt < 1000) {
1016          return 0;
1017        }
1018        switch (callibrationStep) 
1019        {
1020          case 0:
1021            callibrationStep++;
1022            tft.drawTextNoDma(0,0, " ", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0xff,0xff,0xff), true);
1023            tft.drawTextNoDma(TFT_REALWIDTH-8,0, "+", RGBVAL16(0xff,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true);
1024            calMinX += xt;
1025            calMinY += yt;          
1026            break;
1027          case 1:
1028            callibrationStep++;
1029            tft.drawTextNoDma(TFT_REALWIDTH-8,0, " ", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0xff,0xff,0xff), true);
1030            tft.drawTextNoDma(TFT_REALWIDTH-8,TFT_REALHEIGHT-16, "+", RGBVAL16(0xff,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true);
1031            calMaxX += xt;
1032            calMinY += yt;           
1033            break;
1034          case 2:
1035            callibrationStep++;
1036            tft.drawTextNoDma(TFT_REALWIDTH-8,TFT_REALHEIGHT-16, " ", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0xff,0xff,0xff), true);
1037            tft.drawTextNoDma(0,TFT_REALHEIGHT-16, "+", RGBVAL16(0xff,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true);
1038            calMaxX += xt;
1039            calMaxY += yt;
1040            break;
1041          case 3:
1042            tft.fillScreenNoDma(RGBVAL16(0xff,0xff,0xff));
1043            tft.drawTextNoDma(0,100, "          Callibration done!", RGBVAL16(0x00,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true);
1044            tft.drawTextNoDma(0,116, "        (Click center to exit)", RGBVAL16(0xff,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true);           
1045            callibrationStep++;
1046            calMinX += xt;
1047            calMaxY += yt;       
1048            break;                 
1049          case 4:
1050            //Serial.println(xt);
1051            //Serial.println(yt);
1052            if ( (xt > (TFT_REALWIDTH/4)) && (xt < (TFT_REALWIDTH*3)/4) 
1053              && (yt > (TFT_REALHEIGHT/4)) && (yt < (TFT_REALHEIGHT*3)/4) ) {
1054              calMinX /= 2;
1055              calMinY /= 2;
1056              calMaxX /= 2;
1057              calMaxY /= 2;
1058              writeCallibration();                       
1059              toggleMenu(true);
1060            }
1061            else {
1062              callibrationInit();              
1063            }
1064            break; 
1065                             
1066        }
1067        delay(100);
1068      }  
1069    }
1070    else {
1071      prev_zt = 0;
1072    }  
1073  }
1074  
1075  
1076  
1077  
1078  int emu_FileOpen(char * filename)
1079  {
1080    int retval = 0;
1081  
1082    char filepath[80];
1083    strcpy(filepath, romspath);
1084    strcat(filepath, "/");
1085    strcat(filepath, filename);
1086    emu_printf("FileOpen...");
1087    emu_printf(filepath);
1088  #ifdef USE_SDFS
1089    if( !(f_open(&file, filepath, FA_READ)) ) {
1090  #else    
1091    if ((file = SD.open(filepath, O_READ))) {
1092  #endif
1093      retval = 1;  
1094    }
1095    else {
1096      emu_printf("FileOpen failed");
1097    }
1098    return (retval);
1099  }
1100  
1101  int emu_FileRead(char * buf, int size)
1102  {
1103    unsigned char buffer[256];
1104    
1105    int remaining = size;
1106    int byteread = 0;
1107    int retval=0; 
1108    if (size < 256) {
1109  #ifdef USE_SDFS
1110      if( !(f_read (&file, buffer, size, &retval)) )
1111  #else
1112      retval = file.read(buffer, size);
1113  #endif
1114     if (retval>0) {
1115        memcpy(buf,buffer,retval);
1116        byteread += retval;   
1117     }   
1118    }
1119    else {
1120      while (remaining>0) {
1121  #ifdef USE_SDFS
1122        if( !(f_read (&file, buffer, 256, &retval)) )
1123        //f_read (&file, buffer, 256, &retval);
1124  #else
1125        retval = file.read(buffer, 256);
1126  #endif
1127        if (retval>0) {
1128          //emu_printi(retval);
1129          memcpy(buf,buffer,retval);
1130          buf += retval;
1131          byteread += retval;     
1132          remaining -= retval;
1133        }
1134        else {
1135          break;
1136        }
1137      }    
1138    }
1139  
1140    return byteread; 
1141  }
1142  
1143  unsigned char emu_FileGetc(void) {
1144    unsigned char c;
1145  #ifdef USE_SDFS
1146    int retval=0;
1147    if( !(f_read (&file, &c, 1, &retval)) )
1148  #else
1149    int retval = file.read(&c, 1);
1150  #endif  
1151    if (retval != 1) {
1152      emu_printf("emu_FileGetc failed");
1153    }  
1154    return c; 
1155  }
1156  
1157  
1158  void emu_FileClose(void)
1159  {
1160  #ifdef USE_SDFS
1161    f_close(&file); 
1162  #else
1163    file.close();  
1164  #endif  
1165  }
1166  
1167  int emu_FileSize(char * filename) 
1168  {
1169    int filesize=0;
1170    char filepath[80];
1171    strcpy(filepath, romspath);
1172    strcat(filepath, "/");
1173    strcat(filepath, filename);
1174    emu_printf("FileSize...");
1175    emu_printf(filepath);
1176  #ifdef USE_SDFS
1177    FILINFO entry;
1178    f_stat(filepath, &entry);
1179    filesize = entry.fsize; 
1180  #else
1181    if ((file = SD.open(filepath, O_READ))) 
1182    {
1183      emu_printf("filesize is...");
1184      filesize = file.size(); 
1185      emu_printf(filesize);
1186      file.close();    
1187    }
1188  #endif
1189   
1190    return(filesize);    
1191  }
1192  
1193  int emu_FileSeek(int seek) 
1194  {
1195  #ifdef USE_SDFS
1196    f_lseek(&file, seek);
1197  #else
1198    file.seek(seek);
1199  #endif
1200    return (seek);
1201  }
1202  
1203  int emu_FileTell(void) 
1204  {
1205  #ifdef USE_SDFS
1206    return (f_tell(&file));
1207  #else
1208    return (50);
1209  #endif
1210  }
1211  
1212  
1213  int emu_LoadFile(char * filename, char * buf, int size)
1214  {
1215    int filesize = 0;
1216      
1217    char filepath[80];
1218    strcpy(filepath, romspath);
1219    strcat(filepath, "/");
1220    strcat(filepath, filename);
1221    emu_printf("LoadFile...");
1222    emu_printf(filepath);
1223  #ifdef USE_SDFS
1224    if( !(f_open(&file, filepath, FA_READ)) ) {
1225      filesize = f_size(&file);
1226      emu_printf(filesize);
1227      if (size >= filesize)
1228      {
1229        int retval=0;
1230        if( (f_read (&file, buf, filesize, &retval)) ) {
1231          emu_printf("File read failed");        
1232        }
1233      }
1234      f_close(&file);
1235    }
1236  #else
1237    if ((file = SD.open(filepath, O_READ))) 
1238    {
1239      filesize = file.size(); 
1240      emu_printf(filesize);
1241      
1242      if (size >= filesize)
1243      {
1244        if (emu_FileRead(buf, filesize) != filesize) 
1245        {
1246          emu_printf("File read failed");
1247        }        
1248      }
1249      file.close();
1250    }
1251  #endif  
1252    
1253    return(filesize);
1254  }
1255  
1256  int emu_LoadFileSeek(char * filename, char * buf, int size, int seek)
1257  {
1258    int filesize = 0;
1259      
1260    char filepath[80];
1261    strcpy(filepath, romspath);
1262    strcat(filepath, "/");
1263    strcat(filepath, filename);
1264    emu_printf("LoadFileSeek...");
1265    emu_printf(filepath);
1266  #ifdef USE_SDFS
1267    if( !(f_open(&file, filepath, FA_READ)) ) {
1268      f_lseek(&file, seek);
1269      emu_printf(size);
1270      if (size >= filesize)
1271      {
1272        int retval=0;
1273        if( (!f_read (&file, buf, size, &retval)) ) 
1274        if (retval != size)
1275        {
1276          emu_printf("File read failed");      
1277        }
1278      }
1279      f_close(&file);
1280    }
1281  #else
1282    if ((file = SD.open(filepath, O_READ))) 
1283    {
1284      file.seek(seek);
1285      emu_printf(size);
1286      if (file.read(buf, size) != size) {
1287        emu_printf("File read failed");
1288      }        
1289      file.close();
1290    }
1291  #endif  
1292    
1293    return(filesize);
1294  }
1295  
1296  const uint32_t FILE_SIZE_MB = 8;
1297  const uint32_t FILE_SIZE = 1000000UL*FILE_SIZE_MB;
1298  #ifdef USE_SDFS
1299  static FIL tempfile; 
1300  #else
1301  static File tempfile;
1302  #endif
1303  
1304  void emu_FileTempInit(void) 
1305  {
1306  #ifdef USE_SDFS
1307   if( (f_open(&tempfile, SDFSDEV "/bench.dat", FA_READ| FA_WRITE )) ) {
1308  #else
1309  #ifdef USE_SDFAT
1310    if (!tempfile.open("/bench.dat", O_RDWR /*| O_CREAT | O_TRUNC*/)) {
1311  #else
1312    if ((tempfile = SD.open("/bench.dat", O_RDWR))) {
1313  #endif
1314  #endif
1315      Serial.println("psram open failed");
1316    }
1317  /*
1318    else {
1319      uint8_t buf[256];
1320      Serial.println("psram creating");    
1321      file = SD.open("/bench.dat", O_RDWR | O_CREAT | O_TRUNC);
1322      if (file) {
1323        Serial.println("psram opened");    
1324        file.truncate(0);
1325  
1326        if (!file.preAllocate(FILE_SIZE)) {
1327          Serial.println("allocate failed");  
1328        }      
1329        for(int i=0;i<FILE_SIZE/256;i++){
1330          file.write(buf, 256);
1331          Serial.println(i);
1332          
1333        }
1334        Serial.println("psram created");
1335      }
1336      
1337      //file.close();
1338    }
1339  */  
1340  #ifdef USE_SDFS
1341    FILINFO entry;
1342    f_stat(SDFSDEV "/bench.dat", &entry);
1343    int fs=entry.fsize;
1344  #else
1345    int fs=tempfile.size();
1346  #endif
1347    Serial.print("psram size is ");
1348    Serial.println(fs); 
1349  }
1350  
1351  void emu_FileTempRead(int addr, unsigned char * val, int n) 
1352  {
1353  #ifdef USE_SDFS
1354    f_lseek(&file, addr);
1355    int retval=0;
1356    f_read (&file, val, n, &retval);
1357  #else
1358    tempfile.seek(addr);
1359    tempfile.read(val, n);
1360  #endif    
1361  }
1362  
1363  void emu_FileTempWrite(int addr, unsigned char val) 
1364  {
1365    uint8_t v=val;
1366  #ifdef USE_SDFS
1367    f_lseek(&tempfile, addr);
1368    int retval=0;
1369    f_write (&tempfile, &v, 1, &retval);
1370  #else
1371    tempfile.seek(addr);
1372    tempfile.write(&v, 1);
1373  #endif   
1374  }
1375  
1376  #ifdef HAS_USBKEY
1377  void OnPress(auto key)
1378  {
1379    uint8_t keymodifier = keyboard1.getModifiers();
1380  
1381    if(keymodifier == 0x40){
1382      // ALTGR Key modifier FR Keyboard
1383      switch (key) {
1384  #ifdef LAYOUT_FRENCH
1385        case 233 : key = '~' ; break;
1386        case  34 : key = '#' ; break;
1387        case  39 : key = '{' ; break;
1388        case  40 : key = '[' ; break;
1389        case  45 : key = '|' ; break;
1390        case 232 : key = '`' ; break;
1391        case  95 : key = 92  ; break;
1392        case 231 : key = '^' ; break;
1393        case 224 : key = '@' ; break;
1394        case  41 : key = ']' ; break;
1395        case  61 : key = '}' ; break;
1396  #endif  
1397  #ifdef LAYOUT_FRENCH_BELGIAN
1398        case  38 : key = '|' ; break; //1
1399        case 233 : key = '@' ; break; //2
1400        case  34 : key = '#' ; break; //3
1401        case 167 : key = '^' ; break; //6
1402        case 231 : key = '{' ; break; //9
1403        case 224 : key = '}' ; break; //0
1404        case  36 : key = ']' ; break; //$
1405        case  61 : key = '~' ; break; //=
1406  #endif  
1407      }
1408    }  
1409  
1410    if (menuActive())
1411    {
1412      switch (key)  
1413      {
1414        case 217:
1415          usbnavpad |= MASK_JOY2_DOWN;
1416          break;
1417        case 218:
1418          usbnavpad |= MASK_JOY2_UP;
1419          break;
1420        case 216:
1421          usbnavpad |= MASK_JOY2_LEFT;
1422          break;
1423        case 215:
1424          usbnavpad |= MASK_JOY2_RIGHT;
1425          break;
1426        case 10:
1427          usbnavpad |= MASK_JOY2_BTN;
1428          break;
1429      }     
1430    }
1431    else
1432    {
1433      emu_KeyboardOnDown(keymodifier, key);
1434    }
1435  }
1436  
1437  void OnRelease(int key)
1438  {
1439    uint8_t keymodifier = keyboard1.getModifiers();
1440  
1441    if(keymodifier == 0x40){
1442      // ALTGR Key modifier FR Keyboard
1443      switch (key) {
1444  #ifdef LAYOUT_FRENCH
1445        case 233 : key = '~' ; break;
1446        case  34 : key = '#' ; break;
1447        case  39 : key = '{' ; break;
1448        case  40 : key = '[' ; break;
1449        case  45 : key = '|' ; break;
1450        case 232 : key = '`' ; break;
1451        case  95 : key = 92  ; break;
1452        case 231 : key = '^' ; break;
1453        case 224 : key = '@' ; break;
1454        case  41 : key = ']' ; break;
1455        case  61 : key = '}' ; break;
1456  #endif  
1457  #ifdef LAYOUT_FRENCH_BELGIAN
1458        case  38 : key = '|' ; break; //1
1459        case 233 : key = '@' ; break; //2
1460        case  34 : key = '#' ; break; //3
1461        case 167 : key = '^' ; break; //6
1462        case 231 : key = '{' ; break; //9
1463        case 224 : key = '}' ; break; //0
1464        case  36 : key = ']' ; break; //$
1465        case  61 : key = '~' ; break; //=
1466  #endif  
1467      }
1468    }
1469  
1470    if (menuActive())
1471    {
1472      switch (key)  
1473      {
1474        case 217:
1475          usbnavpad &= ~MASK_JOY2_DOWN;
1476          break;
1477        case 218:
1478          usbnavpad &= ~MASK_JOY2_UP;
1479          break;
1480        case 216:
1481          usbnavpad &= ~MASK_JOY2_LEFT;
1482          break;
1483        case 215:
1484          usbnavpad &= ~MASK_JOY2_RIGHT;
1485          break;
1486        case 10:
1487          usbnavpad &= ~MASK_JOY2_BTN;
1488          break;
1489      }     
1490    }
1491    else
1492    {
1493      emu_KeyboardOnUp(keymodifier, key);  
1494    }
1495  }
1496  #endif
1497  
1498  void emu_init(void)
1499  {
1500    Serial.begin(115200);
1501  
1502  #ifdef HAS_USBKEY
1503    myusb.begin();
1504    keyboard1.attachPress(OnPress);
1505    keyboard1.attachRelease(OnRelease);
1506  #endif
1507  
1508  #ifdef USE_SDFS
1509    strcpy(romspath,SDFSDEV);
1510    strcat(romspath,ROMSDIR);    
1511    FRESULT rc;
1512    if((rc = f_mount (&fatfs, romspath, 1))) {
1513      emu_printf("Fail mounting SDFS");  
1514    }
1515    else { 
1516      rc = f_chdrive(ROMSDIR);
1517    }
1518  #else  
1519  #ifdef USE_SDFAT
1520    while (!SD.begin(SD_CONFIG))
1521  #else
1522    while (!SD.begin(SD_CS))
1523  #endif
1524    {
1525      Serial.println("SD begin failed, retrying...");
1526      delay(1000);    
1527    }
1528    strcpy(romspath,ROMSDIR);
1529  #endif
1530  
1531    nbFiles = readNbFiles(); 
1532  
1533    Serial.print("SD initialized, files found: ");
1534    Serial.println(nbFiles);
1535  
1536    
1537    emu_InitJoysticks();
1538  #ifdef SWAP_JOYSTICK
1539    joySwapped = true;   
1540  #else
1541    joySwapped = false;   
1542  #endif  
1543    readCallibration();
1544   
1545    if ((tft.isTouching()) || (emu_ReadKeys() & MASK_JOY2_BTN) ) {
1546      callibrationInit();
1547    } 
1548    else  
1549    {
1550      toggleMenu(true);
1551    }
1552  }
1553  
1554  
1555  void emu_start(void)
1556  {
1557  #ifdef HAS_I2CKBD
1558    byte msg[7]={0,0,0,0,0,0,0};
1559    Wire.begin(); // join i2c bus SDA2/SCL2
1560    Wire.requestFrom(8, 7);    // request 7 bytes from slave device #8 
1561    int i = 0;
1562    while (Wire.available() && (i<7) ) { // slave may send less than requested
1563      byte b = Wire.read(); // receive a byte
1564      msg[i++] = b;        
1565    }
1566    /*     
1567    Serial.println(msg[0], BIN);
1568    Serial.println(msg[1], BIN);
1569    Serial.println(msg[2], BIN);
1570    Serial.println(msg[3], BIN);
1571    Serial.println(msg[4], BIN);
1572    Serial.println(msg[5], BIN);
1573    Serial.println(msg[6], BIN);
1574    */  
1575    if ( (msg[0] == 0xff) && (msg[1] == 0xff) && 
1576         (msg[2] == 0xff) && (msg[3] == 0xff) && 
1577         (msg[4] == 0xff) && (msg[5] == 0xff) && (msg[6] == 0xff)) {
1578      i2cKeyboardPresent = true;
1579      Serial.println("i2C keyboard found");            
1580    }
1581  #endif
1582  
1583    usbnavpad = 0;
1584    
1585    keys = key_map1;
1586    keyMap = 0;
1587  }