/ MCUME_teensy / teensypce / 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  
1079  int emu_FileOpen(char * filename)
1080  {
1081    int retval = 0;
1082  
1083    char filepath[80];
1084    strcpy(filepath, romspath);
1085    strcat(filepath, "/");
1086    strcat(filepath, filename);
1087    emu_printf("FileOpen...");
1088    emu_printf(filepath);
1089  #ifdef USE_SDFS
1090    if( !(f_open(&file, filepath, FA_READ)) ) {
1091  #else    
1092    if ((file = SD.open(filepath, O_READ))) {
1093  #endif
1094      retval = 1;  
1095    }
1096    else {
1097      emu_printf("FileOpen failed");
1098    }
1099    return (retval);
1100  }
1101  
1102  int emu_FileRead(char * buf, int size)
1103  {
1104    unsigned char buffer[256];
1105    
1106    int remaining = size;
1107    int byteread = 0;
1108    int retval=0; 
1109    if (size < 256) {
1110  #ifdef USE_SDFS
1111      if( !(f_read (&file, buffer, size, &retval)) )
1112  #else
1113      retval = file.read(buffer, size);
1114  #endif
1115     if (retval>0) {
1116        memcpy(buf,buffer,retval);
1117        byteread += retval;   
1118     }   
1119    }
1120    else {
1121      while (remaining>0) {
1122  #ifdef USE_SDFS
1123        if( !(f_read (&file, buffer, 256, &retval)) )
1124        //f_read (&file, buffer, 256, &retval);
1125  #else
1126        retval = file.read(buffer, 256);
1127  #endif
1128        if (retval>0) {
1129          //emu_printi(retval);
1130          memcpy(buf,buffer,retval);
1131          buf += retval;
1132          byteread += retval;     
1133          remaining -= retval;
1134        }
1135        else {
1136          break;
1137        }
1138      }    
1139    }
1140  
1141    return byteread; 
1142  }
1143  
1144  unsigned char emu_FileGetc(void) {
1145    unsigned char c;
1146  #ifdef USE_SDFS
1147    int retval=0;
1148    if( !(f_read (&file, &c, 1, &retval)) )
1149  #else
1150    int retval = file.read(&c, 1);
1151  #endif  
1152    if (retval != 1) {
1153      emu_printf("emu_FileGetc failed");
1154    }  
1155    return c; 
1156  }
1157  
1158  
1159  void emu_FileClose(void)
1160  {
1161  #ifdef USE_SDFS
1162    f_close(&file); 
1163  #else
1164    file.close();  
1165  #endif  
1166  }
1167  
1168  int emu_FileSize(char * filename) 
1169  {
1170    int filesize=0;
1171    char filepath[80];
1172    strcpy(filepath, romspath);
1173    strcat(filepath, "/");
1174    strcat(filepath, filename);
1175    emu_printf("FileSize...");
1176    emu_printf(filepath);
1177  #ifdef USE_SDFS
1178    FILINFO entry;
1179    f_stat(filepath, &entry);
1180    filesize = entry.fsize; 
1181  #else
1182    if ((file = SD.open(filepath, O_READ))) 
1183    {
1184      emu_printf("filesize is...");
1185      filesize = file.size(); 
1186      emu_printf(filesize);
1187      file.close();    
1188    }
1189  #endif
1190   
1191    return(filesize);    
1192  }
1193  
1194  int emu_FileSeek(int seek) 
1195  {
1196  #ifdef USE_SDFS
1197    f_lseek(&file, seek);
1198  #else
1199    file.seek(seek);
1200  #endif
1201    return (seek);
1202  }
1203  
1204  int emu_FileTell(void) 
1205  {
1206  #ifdef USE_SDFS
1207    return (f_tell(&file));
1208  #else
1209    return (50);
1210  #endif
1211  }
1212  
1213  
1214  int emu_LoadFile(char * filename, char * buf, int size)
1215  {
1216    int filesize = 0;
1217      
1218    char filepath[80];
1219    strcpy(filepath, romspath);
1220    strcat(filepath, "/");
1221    strcat(filepath, filename);
1222    emu_printf("LoadFile...");
1223    emu_printf(filepath);
1224  #ifdef USE_SDFS
1225    if( !(f_open(&file, filepath, FA_READ)) ) {
1226      filesize = f_size(&file);
1227      emu_printf(filesize);
1228      if (size >= filesize)
1229      {
1230        int retval=0;
1231        if( (f_read (&file, buf, filesize, &retval)) ) {
1232          emu_printf("File read failed");        
1233        }
1234      }
1235      f_close(&file);
1236    }
1237  #else
1238    if ((file = SD.open(filepath, O_READ))) 
1239    {
1240      filesize = file.size(); 
1241      emu_printf(filesize);
1242      
1243      if (size >= filesize)
1244      {
1245        if (emu_FileRead(buf, filesize) != filesize) 
1246        {
1247          emu_printf("File read failed");
1248        }        
1249      }
1250      file.close();
1251    }
1252  #endif  
1253    
1254    return(filesize);
1255  }
1256  
1257  int emu_LoadFileSeek(char * filename, char * buf, int size, int seek)
1258  {
1259    int filesize = 0;
1260      
1261    char filepath[80];
1262    strcpy(filepath, romspath);
1263    strcat(filepath, "/");
1264    strcat(filepath, filename);
1265    emu_printf("LoadFileSeek...");
1266    emu_printf(filepath);
1267  #ifdef USE_SDFS
1268    if( !(f_open(&file, filepath, FA_READ)) ) {
1269      f_lseek(&file, seek);
1270      emu_printf(size);
1271      if (size >= filesize)
1272      {
1273        int retval=0;
1274        if( (!f_read (&file, buf, size, &retval)) ) 
1275        if (retval != size)
1276        {
1277          emu_printf("File read failed");      
1278        }
1279      }
1280      f_close(&file);
1281    }
1282  #else
1283    if ((file = SD.open(filepath, O_READ))) 
1284    {
1285      file.seek(seek);
1286      emu_printf(size);
1287      if (file.read(buf, size) != size) {
1288        emu_printf("File read failed");
1289      }        
1290      file.close();
1291    }
1292  #endif  
1293    
1294    return(filesize);
1295  }
1296  
1297  const uint32_t FILE_SIZE_MB = 8;
1298  const uint32_t FILE_SIZE = 1000000UL*FILE_SIZE_MB;
1299  #ifdef USE_SDFS
1300  static FIL tempfile; 
1301  #else
1302  static File tempfile;
1303  #endif
1304  
1305  void emu_FileTempInit(void) 
1306  {
1307  #ifdef USE_SDFS
1308   if( (f_open(&tempfile, SDFSDEV "/bench.dat", FA_READ| FA_WRITE )) ) {
1309  #else
1310  #ifdef USE_SDFAT
1311    if (!tempfile.open("/bench.dat", O_RDWR /*| O_CREAT | O_TRUNC*/)) {
1312  #else
1313    if ((tempfile = SD.open("/bench.dat", O_RDWR))) {
1314  #endif
1315  #endif
1316      Serial.println("psram open failed");
1317    }
1318  /*
1319    else {
1320      uint8_t buf[256];
1321      Serial.println("psram creating");    
1322      file = SD.open("/bench.dat", O_RDWR | O_CREAT | O_TRUNC);
1323      if (file) {
1324        Serial.println("psram opened");    
1325        file.truncate(0);
1326  
1327        if (!file.preAllocate(FILE_SIZE)) {
1328          Serial.println("allocate failed");  
1329        }      
1330        for(int i=0;i<FILE_SIZE/256;i++){
1331          file.write(buf, 256);
1332          Serial.println(i);
1333          
1334        }
1335        Serial.println("psram created");
1336      }
1337      
1338      //file.close();
1339    }
1340  */  
1341  #ifdef USE_SDFS
1342    FILINFO entry;
1343    f_stat(SDFSDEV "/bench.dat", &entry);
1344    int fs=entry.fsize;
1345  #else
1346    int fs=tempfile.size();
1347  #endif
1348    Serial.print("psram size is ");
1349    Serial.println(fs); 
1350  }
1351  
1352  void emu_FileTempRead(int addr, unsigned char * val, int n) 
1353  {
1354  #ifdef USE_SDFS
1355    f_lseek(&file, addr);
1356    int retval=0;
1357    f_read (&file, val, n, &retval);
1358  #else
1359    tempfile.seek(addr);
1360    tempfile.read(val, n);
1361  #endif    
1362  }
1363  
1364  void emu_FileTempWrite(int addr, unsigned char val) 
1365  {
1366    uint8_t v=val;
1367  #ifdef USE_SDFS
1368    f_lseek(&tempfile, addr);
1369    int retval=0;
1370    f_write (&tempfile, &v, 1, &retval);
1371  #else
1372    tempfile.seek(addr);
1373    tempfile.write(&v, 1);
1374  #endif   
1375  }
1376  
1377  #ifdef HAS_USBKEY
1378  void OnPress(auto key)
1379  {
1380    uint8_t keymodifier = keyboard1.getModifiers();
1381  
1382    if(keymodifier == 0x40){
1383      // ALTGR Key modifier FR Keyboard
1384      switch (key) {
1385  #ifdef LAYOUT_FRENCH
1386        case 233 : key = '~' ; break;
1387        case  34 : key = '#' ; break;
1388        case  39 : key = '{' ; break;
1389        case  40 : key = '[' ; break;
1390        case  45 : key = '|' ; break;
1391        case 232 : key = '`' ; break;
1392        case  95 : key = 92  ; break;
1393        case 231 : key = '^' ; break;
1394        case 224 : key = '@' ; break;
1395        case  41 : key = ']' ; break;
1396        case  61 : key = '}' ; break;
1397  #endif  
1398  #ifdef LAYOUT_FRENCH_BELGIAN
1399        case  38 : key = '|' ; break; //1
1400        case 233 : key = '@' ; break; //2
1401        case  34 : key = '#' ; break; //3
1402        case 167 : key = '^' ; break; //6
1403        case 231 : key = '{' ; break; //9
1404        case 224 : key = '}' ; break; //0
1405        case  36 : key = ']' ; break; //$
1406        case  61 : key = '~' ; break; //=
1407  #endif  
1408      }
1409    }  
1410  
1411    if (menuActive())
1412    {
1413      switch (key)  
1414      {
1415        case 217:
1416          usbnavpad |= MASK_JOY2_DOWN;
1417          break;
1418        case 218:
1419          usbnavpad |= MASK_JOY2_UP;
1420          break;
1421        case 216:
1422          usbnavpad |= MASK_JOY2_LEFT;
1423          break;
1424        case 215:
1425          usbnavpad |= MASK_JOY2_RIGHT;
1426          break;
1427        case 10:
1428          usbnavpad |= MASK_JOY2_BTN;
1429          break;
1430      }     
1431    }
1432    else
1433    {
1434      emu_KeyboardOnDown(keymodifier, key);
1435    }
1436  }
1437  
1438  void OnRelease(int key)
1439  {
1440    uint8_t keymodifier = keyboard1.getModifiers();
1441  
1442    if(keymodifier == 0x40){
1443      // ALTGR Key modifier FR Keyboard
1444      switch (key) {
1445  #ifdef LAYOUT_FRENCH
1446        case 233 : key = '~' ; break;
1447        case  34 : key = '#' ; break;
1448        case  39 : key = '{' ; break;
1449        case  40 : key = '[' ; break;
1450        case  45 : key = '|' ; break;
1451        case 232 : key = '`' ; break;
1452        case  95 : key = 92  ; break;
1453        case 231 : key = '^' ; break;
1454        case 224 : key = '@' ; break;
1455        case  41 : key = ']' ; break;
1456        case  61 : key = '}' ; break;
1457  #endif  
1458  #ifdef LAYOUT_FRENCH_BELGIAN
1459        case  38 : key = '|' ; break; //1
1460        case 233 : key = '@' ; break; //2
1461        case  34 : key = '#' ; break; //3
1462        case 167 : key = '^' ; break; //6
1463        case 231 : key = '{' ; break; //9
1464        case 224 : key = '}' ; break; //0
1465        case  36 : key = ']' ; break; //$
1466        case  61 : key = '~' ; break; //=
1467  #endif  
1468      }
1469    }
1470  
1471    if (menuActive())
1472    {
1473      switch (key)  
1474      {
1475        case 217:
1476          usbnavpad &= ~MASK_JOY2_DOWN;
1477          break;
1478        case 218:
1479          usbnavpad &= ~MASK_JOY2_UP;
1480          break;
1481        case 216:
1482          usbnavpad &= ~MASK_JOY2_LEFT;
1483          break;
1484        case 215:
1485          usbnavpad &= ~MASK_JOY2_RIGHT;
1486          break;
1487        case 10:
1488          usbnavpad &= ~MASK_JOY2_BTN;
1489          break;
1490      }     
1491    }
1492    else
1493    {
1494      emu_KeyboardOnUp(keymodifier, key);  
1495    }
1496  }
1497  #endif
1498  
1499  void emu_init(void)
1500  {
1501    Serial.begin(115200);
1502  
1503  #ifdef HAS_USBKEY
1504    myusb.begin();
1505    keyboard1.attachPress(OnPress);
1506    keyboard1.attachRelease(OnRelease);
1507  #endif
1508  
1509  #ifdef USE_SDFS
1510    strcpy(romspath,SDFSDEV);
1511    strcat(romspath,ROMSDIR);    
1512    FRESULT rc;
1513    if((rc = f_mount (&fatfs, romspath, 1))) {
1514      emu_printf("Fail mounting SDFS");  
1515    }
1516    else { 
1517      rc = f_chdrive(ROMSDIR);
1518    }
1519  #else  
1520  #ifdef USE_SDFAT
1521    while (!SD.begin(SD_CONFIG))
1522  #else
1523    while (!SD.begin(SD_CS))
1524  #endif
1525    {
1526      Serial.println("SD begin failed, retrying...");
1527      delay(1000);    
1528    }
1529    strcpy(romspath,ROMSDIR);
1530  #endif
1531  
1532    nbFiles = readNbFiles(); 
1533  
1534    Serial.print("SD initialized, files found: ");
1535    Serial.println(nbFiles);
1536  
1537    
1538    emu_InitJoysticks();
1539  #ifdef SWAP_JOYSTICK
1540    joySwapped = true;   
1541  #else
1542    joySwapped = false;   
1543  #endif  
1544    readCallibration();
1545   
1546    if ((tft.isTouching()) || (emu_ReadKeys() & MASK_JOY2_BTN) ) {
1547      callibrationInit();
1548    } 
1549    else  
1550    {
1551      toggleMenu(true);
1552    }
1553  }
1554  
1555  
1556  void emu_start(void)
1557  {
1558  #ifdef HAS_I2CKBD
1559    byte msg[7]={0,0,0,0,0,0,0};
1560    Wire.begin(); // join i2c bus SDA2/SCL2
1561    Wire.requestFrom(8, 7);    // request 7 bytes from slave device #8 
1562    int i = 0;
1563    while (Wire.available() && (i<7) ) { // slave may send less than requested
1564      byte b = Wire.read(); // receive a byte
1565      msg[i++] = b;        
1566    }
1567    /*     
1568    Serial.println(msg[0], BIN);
1569    Serial.println(msg[1], BIN);
1570    Serial.println(msg[2], BIN);
1571    Serial.println(msg[3], BIN);
1572    Serial.println(msg[4], BIN);
1573    Serial.println(msg[5], BIN);
1574    Serial.println(msg[6], BIN);
1575    */  
1576    if ( (msg[0] == 0xff) && (msg[1] == 0xff) && 
1577         (msg[2] == 0xff) && (msg[3] == 0xff) && 
1578         (msg[4] == 0xff) && (msg[5] == 0xff) && (msg[6] == 0xff)) {
1579      i2cKeyboardPresent = true;
1580      Serial.println("i2C keyboard found");            
1581    }
1582  #endif
1583  
1584    usbnavpad = 0;
1585    
1586    keys = key_map1;
1587    keyMap = 0;
1588  }