/ MCUME_teensy / teensylogo / 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  KeyboardController keyboard1(myusb);
  35  #endif
  36  static uint8_t usbnavpad=0;
  37  
  38  #ifdef USE_SDFS
  39  #include "uSDFS.h"
  40  static FATFS fatfs;
  41  static FIL file; 
  42  #else
  43  
  44  #ifdef USE_SDFAT
  45  #include "SdFat.h"
  46  #include "sdios.h"
  47  
  48  #ifndef SDCARD_SS_PIN
  49  const uint8_t SD_CS_PIN = SS;
  50  
  51  #else  // SDCARD_SS_PIN
  52  // Assume built-in SD is used.
  53  const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
  54  #endif  // SDCARD_SS_PIN
  55  
  56  #define SD_CONFIG SdioConfig(FIFO_SDIO)
  57  
  58  // Try to select the best SD card configuration.
  59  #if HAS_SDIO_CLASS
  60  #define SD_CONFIG SdioConfig(FIFO_SDIO)
  61  #elif ENABLE_DEDICATED_SPI
  62  #define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI)
  63  #else  // HAS_SDIO_CLASS
  64  #define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI)
  65  #endif  // HAS_SDIO_CLASS
  66  //------------------------------------------------------------------------------
  67  
  68  #if SD_FAT_TYPE == 0
  69  #elif SD_FAT_TYPE == 1
  70  #define SdFat SdFat32
  71  #define File File32
  72  #elif SD_FAT_TYPE == 2
  73  #define SdFat SdExFat
  74  #define File ExFile
  75  #elif SD_FAT_TYPE == 3
  76  #define SdFat SdFs
  77  #define File FsFile
  78  #endif  // SD_FAT_TYPE
  79  static SdFat SD;
  80  #else
  81  #include <SD.h>
  82  #endif
  83  static File file;
  84  #endif
  85  
  86  #define CALIBRATION_FILE    "/cal.cfg"
  87  
  88  #define MKEY_L1             1
  89  #define MKEY_L2             2
  90  #define MKEY_L3             3
  91  #define MKEY_L4             4
  92  #define MKEY_L5             5
  93  #define MKEY_L6             6
  94  #define MKEY_L7             7
  95  #define MKEY_L8             8
  96  #define MKEY_L9             9
  97  #define MKEY_UP             20
  98  #define MKEY_DOWN           21
  99  #define MKEY_JOY            22
 100  #define MKEY_TFT            23
 101  #define MKEY_VGA            24
 102  
 103  #define MAX_FILES           64
 104  #define MAX_FILENAME_SIZE   24
 105  #define MAX_MENULINES       (MKEY_L9)
 106  #define TEXT_HEIGHT         16
 107  #define TEXT_WIDTH          8
 108  #define MENU_FILE_XOFFSET   (6*TEXT_WIDTH)
 109  #define MENU_FILE_YOFFSET   (2*TEXT_HEIGHT)
 110  #define MENU_FILE_W         (MAX_FILENAME_SIZE*TEXT_WIDTH)
 111  #define MENU_FILE_H         (MAX_MENULINES*TEXT_HEIGHT)
 112  #define MENU_FILE_BGCOLOR   RGBVAL16(0x00,0x00,0x40)
 113  #define MENU_JOYS_YOFFSET   (12*TEXT_HEIGHT)
 114  #define MENU_VBAR_XOFFSET   (0*TEXT_WIDTH)
 115  #define MENU_VBAR_YOFFSET   (MENU_FILE_YOFFSET)
 116  
 117  #define MENU_TFT_XOFFSET    (MENU_FILE_XOFFSET+MENU_FILE_W+8)
 118  #define MENU_TFT_YOFFSET    (MENU_VBAR_YOFFSET+32)
 119  #define MENU_VGA_XOFFSET    (MENU_FILE_XOFFSET+MENU_FILE_W+8)
 120  #define MENU_VGA_YOFFSET    (MENU_VBAR_YOFFSET+MENU_FILE_H-32-37)
 121  
 122  extern TFT_T_DMA tft;
 123  
 124  static char romspath[64];
 125  static int nbFiles=0;
 126  static int curFile=0;
 127  static int topFile=0;
 128  static char selection[MAX_FILENAME_SIZE+1]="";
 129  static char files[MAX_FILES][MAX_FILENAME_SIZE];
 130  static bool menuRedraw=true;
 131  
 132  static int calMinX=-1,calMinY=-1,calMaxX=-1,calMaxY=-1;
 133  static bool i2cKeyboardPresent = false;
 134  static unsigned short * keys;
 135  static int keyMap;
 136  
 137  const unsigned short menutouchareas[] = {
 138    TAREA_XY,MENU_FILE_XOFFSET,MENU_FILE_YOFFSET,
 139    TAREA_WH,MENU_FILE_W, TEXT_HEIGHT,
 140    TAREA_NEW_COL,TEXT_HEIGHT,TEXT_HEIGHT,TEXT_HEIGHT,TEXT_HEIGHT,TEXT_HEIGHT,TEXT_HEIGHT,TEXT_HEIGHT,TEXT_HEIGHT,TEXT_HEIGHT,
 141    
 142    TAREA_XY,MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,
 143    TAREA_WH,32,48,
 144    TAREA_NEW_COL, 72,72,8,40,
 145  
 146    TAREA_XY,MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,
 147    TAREA_WH,32,37,
 148    TAREA_NEW_COL, 38,38,
 149      
 150    TAREA_END};
 151     
 152  const unsigned short menutouchactions[] = {
 153    MKEY_L1,MKEY_L2,MKEY_L3,MKEY_L4,MKEY_L5,MKEY_L6,MKEY_L7,MKEY_L8,MKEY_L9,
 154    MKEY_UP,MKEY_DOWN,ACTION_NONE,MKEY_JOY,
 155    MKEY_TFT,MKEY_VGA}; 
 156  
 157  
 158  static int keypadval=0; 
 159  static boolean joySwapped = false;
 160  static uint16_t bLastState;
 161  static int xRef;
 162  static int yRef;
 163  static uint8_t prev_zt=0; 
 164  
 165  static bool menuOn=true;
 166  static bool callibrationOn=false;
 167  static int callibrationStep=0;
 168  
 169  
 170  static char captureTouchZone(const unsigned short * areas, const unsigned short * actions, int *rx, int *ry, int *rw, int * rh) {
 171      uint16_t xt=0;
 172      uint16_t yt=0;
 173      uint16_t zt=0;
 174      boolean hDir=true;  
 175    
 176      if (tft.isTouching())
 177      {
 178          if (prev_zt == 0) {
 179              prev_zt =1;
 180              tft.readCal(&xt,&yt,&zt);
 181              if (zt<1000) {
 182                prev_zt=0; 
 183                return ACTION_NONE;
 184              }   
 185              int i=0;
 186              int k=0;
 187              int y2=0, y1=0;
 188              int x2=0, x1=0;
 189              int x=KEYBOARD_X,y=KEYBOARD_Y;
 190              int w=TAREA_W_DEF,h=TAREA_H_DEF;
 191              uint8_t s;
 192              while ( (s=areas[i++]) != TAREA_END ) {
 193                  if (s == TAREA_XY) {
 194                      x = areas[i++];
 195                      y = areas[i++];                    
 196                      x2 = x;
 197                      y2 = y;  
 198                  }
 199                  else if (s == TAREA_WH) {
 200                      w = areas[i++];
 201                      h = areas[i++];
 202                  }                     
 203                  else if (s == TAREA_NEW_ROW) {
 204                    hDir = true;
 205                    y1 = y2;
 206                    y2 = y1 + h;
 207                    x2 = x;
 208                  }  
 209                  else if (s == TAREA_NEW_COL) {
 210                    hDir = false;
 211                    x1 = x2;
 212                    x2 = x1 + w;
 213                    y2 = y;                  
 214                  }
 215                  else { 
 216                      if (hDir) {
 217                        x1 = x2;
 218                        x2 = x1+s;                                                            
 219                      } else {
 220                        y1 = y2;
 221                        y2 = y1+s;                      
 222                      }
 223                      if ( (yt >= y1) && (yt < y2) && (xt >= x1) && (xt < x2)  ) {
 224                          *rx = x1;
 225                          *ry = y1;
 226                          *rw = x2-x1;
 227                          *rh = y2-y1;
 228                          return (actions[k]);  
 229                      }
 230                      k++;
 231                  }                
 232              }
 233          } 
 234          prev_zt =1; 
 235      } else {
 236          prev_zt=0; 
 237      } 
 238    
 239      return ACTION_NONE;   
 240  } 
 241  
 242  
 243  
 244  
 245  
 246  
 247  
 248  
 249  void emu_printf(char * text)
 250  {
 251    Serial.println(text);
 252  }
 253  
 254  void emu_printf(int val)
 255  {
 256    Serial.println(val);
 257  }
 258  
 259  void emu_printi(int val)
 260  {
 261    Serial.println(val,HEX);
 262  }
 263  
 264  void emu_printh(int val)
 265  {
 266    Serial.println(val,HEX);
 267  }
 268  
 269  static int malbufpt = 0;
 270  static char malbuf[EXTRA_HEAP];
 271  
 272  void * emu_Malloc(int size)
 273  {
 274    void * retval =  malloc(size);
 275    if (!retval) {
 276      emu_printf("failled to allocate");
 277      emu_printf(size);
 278      emu_printf("fallback");
 279      if ( (malbufpt+size) < sizeof(malbuf) ) {
 280        retval = (void *)&malbuf[malbufpt];
 281        malbufpt += size;      
 282      }
 283      else {
 284        emu_printf("failure to allocate");
 285      }
 286    }
 287    else {
 288      emu_printf("could allocate dynamic ");
 289      emu_printf(size);    
 290    }
 291    
 292    return retval;
 293  }
 294  
 295  void * emu_MallocI(int size)
 296  {
 297    void * retval =  NULL; 
 298  
 299    if ( (malbufpt+size) < sizeof(malbuf) ) {
 300      retval = (void *)&malbuf[malbufpt];
 301      malbufpt += size;
 302      emu_printf("could allocate static ");
 303      emu_printf(size);          
 304    }
 305    else {
 306      emu_printf("failure to allocate");
 307    }
 308  
 309    return retval;
 310  }
 311  void emu_Free(void * pt)
 312  {
 313    free(pt);
 314  }
 315  
 316  
 317  
 318  
 319  
 320  int emu_ReadAnalogJoyX(int min, int max) 
 321  {
 322    int val = analogRead(PIN_JOY2_A1X);
 323  #if INVX
 324    val = 4095 - val;
 325  #endif
 326    val = val-xRef;
 327    val = ((val*140)/100);
 328    if ( (val > -512) && (val < 512) ) val = 0;
 329    val = val+2048;
 330    return (val*(max-min))/4096;
 331  }
 332  
 333  int emu_ReadAnalogJoyY(int min, int max) 
 334  {
 335    int val = analogRead(PIN_JOY2_A2Y);
 336  #if INVY
 337    val = 4095 - val;
 338  #endif
 339    val = val-yRef;
 340    val = ((val*120)/100);
 341    if ( (val > -512) && (val < 512) ) val = 0;
 342    //val = (val*(max-min))/4096;
 343    val = val+2048;
 344    //return val+(max-min)/2;
 345    return (val*(max-min))/4096;
 346  }
 347  
 348  
 349  static uint16_t readAnalogJoystick(void)
 350  {
 351    uint16_t joysval = 0;
 352  
 353    int xReading = emu_ReadAnalogJoyX(0,256);
 354    if (xReading > 128) joysval |= MASK_JOY2_LEFT;
 355    else if (xReading < 128) joysval |= MASK_JOY2_RIGHT;
 356    
 357    int yReading = emu_ReadAnalogJoyY(0,256);
 358    if (yReading < 128) joysval |= MASK_JOY2_UP;
 359    else if (yReading > 128) joysval |= MASK_JOY2_DOWN;
 360    
 361  #ifdef PIN_JOY2_BTN  
 362    joysval |= (digitalRead(PIN_JOY2_BTN) == HIGH ? 0 : MASK_JOY2_BTN);
 363  #endif
 364    return (joysval);     
 365  }
 366  
 367  
 368  int emu_SwapJoysticks(int statusOnly) {
 369    if (!statusOnly) {
 370      if (joySwapped) {
 371        joySwapped = false;
 372      }
 373      else {
 374        joySwapped = true;
 375      }
 376    }
 377    return(joySwapped?1:0);
 378  }
 379  
 380  int emu_GetPad(void) 
 381  {
 382    return(keypadval/*|((joySwapped?1:0)<<7)*/);
 383  }
 384  
 385  int emu_ReadKeys(void) 
 386  {
 387    uint16_t retval;
 388    uint16_t j1 = readAnalogJoystick();
 389    uint16_t j2 = 0;
 390    
 391    // Second joystick
 392  #if INVY
 393  #ifdef PIN_JOY1_1
 394    if ( digitalRead(PIN_JOY1_1) == LOW ) j2 |= MASK_JOY2_DOWN;
 395  #endif
 396  #ifdef PIN_JOY1_2
 397    if ( digitalRead(PIN_JOY1_2) == LOW ) j2 |= MASK_JOY2_UP;
 398  #endif
 399  #else
 400  #ifdef PIN_JOY1_1
 401    if ( digitalRead(PIN_JOY1_1) == LOW ) j2 |= MASK_JOY2_UP;
 402  #endif
 403  #ifdef PIN_JOY1_2
 404    if ( digitalRead(PIN_JOY1_2) == LOW ) j2 |= MASK_JOY2_DOWN;
 405  #endif
 406  #endif
 407  #if INVX
 408  #ifdef PIN_JOY1_3
 409    if ( digitalRead(PIN_JOY1_3) == LOW ) j2 |= MASK_JOY2_LEFT;
 410  #endif
 411  #ifdef PIN_JOY1_4
 412    if ( digitalRead(PIN_JOY1_4) == LOW ) j2 |= MASK_JOY2_RIGHT;
 413  #endif
 414  #else
 415  #ifdef PIN_JOY1_3
 416    if ( digitalRead(PIN_JOY1_3) == LOW ) j2 |= MASK_JOY2_RIGHT;
 417  #endif
 418  #ifdef PIN_JOY1_4
 419    if ( digitalRead(PIN_JOY1_4) == LOW ) j2 |= MASK_JOY2_LEFT;
 420  #endif
 421  #endif
 422  #ifdef PIN_JOY1_BTN
 423    if ( digitalRead(PIN_JOY1_BTN) == LOW ) j2 |= MASK_JOY2_BTN;
 424  #endif
 425    if (joySwapped) {
 426      retval = ((j1 << 8) | j2);
 427    }
 428    else {
 429      retval = ((j2 << 8) | j1);
 430    }
 431  
 432    if (usbnavpad & MASK_JOY2_UP) retval |= MASK_JOY2_UP;
 433    if (usbnavpad & MASK_JOY2_DOWN) retval |= MASK_JOY2_DOWN;
 434    if (usbnavpad & MASK_JOY2_LEFT) retval |= MASK_JOY2_LEFT;
 435    if (usbnavpad & MASK_JOY2_RIGHT) retval |= MASK_JOY2_RIGHT;
 436    if (usbnavpad & MASK_JOY2_BTN) retval |= MASK_JOY2_BTN;
 437  
 438  #ifdef PIN_KEY_USER1 
 439    if ( digitalRead(PIN_KEY_USER1) == LOW ) retval |= MASK_KEY_USER1;
 440  #endif
 441  #ifdef PIN_KEY_USER2 
 442    if ( digitalRead(PIN_KEY_USER2) == LOW ) retval |= MASK_KEY_USER2;
 443  #endif
 444  #ifdef PIN_KEY_USER3 
 445    if ( digitalRead(PIN_KEY_USER3) == LOW ) retval |= MASK_KEY_USER3;
 446  #endif
 447  #ifdef PIN_KEY_USER4 
 448    if ( digitalRead(PIN_KEY_USER4) == LOW ) retval |= MASK_KEY_USER4;
 449  #endif
 450  
 451    //Serial.println(retval,HEX);
 452  
 453    if ( ((retval & (MASK_KEY_USER1+MASK_KEY_USER2)) == (MASK_KEY_USER1+MASK_KEY_USER2))
 454       || (retval & MASK_KEY_USER4 ) )
 455    {  
 456  // Reset procedure T3.X and T4.0 by Frank Boesing !!   
 457  #if defined(__IMXRT1052__) || defined(__IMXRT1062__)    
 458      uint32_t tmp = SNVS_LPCR; // save control register
 459      
 460      SNVS_LPSR |= 1;
 461      
 462      // disable alarm
 463      SNVS_LPCR &= ~0x02;
 464      while (SNVS_LPCR & 0x02);
 465      
 466      __disable_irq();
 467      //get Time:
 468      uint32_t lsb, msb;
 469      do {
 470        msb = SNVS_LPSRTCMR;
 471        lsb = SNVS_LPSRTCLR;
 472      } while ( (SNVS_LPSRTCLR != lsb) | (SNVS_LPSRTCMR != msb) );
 473      uint32_t secs = (msb << 17) | (lsb >> 15);
 474      
 475      //set alarm
 476      secs += 2;
 477      SNVS_LPTAR = secs;
 478      while (SNVS_LPTAR != secs);
 479      
 480      SNVS_LPCR = tmp | 0x02; // restore control register and set alarm
 481      while (!(SNVS_LPCR & 0x02));
 482      
 483      SNVS_LPCR |= (1 << 6); // turn off power
 484      while (1) asm("wfi");  
 485  #else
 486      *(volatile uint32_t *)0xE000ED0C = 0x5FA0004;
 487      while (true) {
 488        ;
 489      } 
 490  #endif 
 491    }
 492    
 493    return (retval);
 494  }
 495  
 496  unsigned short emu_DebounceLocalKeys(void)
 497  {
 498    uint16_t bCurState = emu_ReadKeys();
 499    uint16_t bClick = bCurState & ~bLastState;
 500    bLastState = bCurState;
 501  
 502    return (bClick);
 503  }
 504  
 505  int emu_ReadI2CKeyboard(void) {
 506    int retval=0;
 507  #ifdef HAS_I2CKBD
 508    if (i2cKeyboardPresent) {
 509      byte msg[7]={0,0,0,0,0,0,0};
 510      Wire.requestFrom(8, 7);    // request 7 bytes from slave device #8 
 511      int i = 0;
 512      int hitindex=-1;
 513      while (Wire.available() && (i<7) ) { // slave may send less than requested
 514        byte b = Wire.read(); // receive a byte
 515        if (b != 0xff) hitindex=i; 
 516        msg[i++] = b;        
 517      }
 518      
 519      if (hitindex >=0 ) {
 520        /*
 521        Serial.println(msg[0], BIN);
 522        Serial.println(msg[1], BIN);
 523        Serial.println(msg[2], BIN);
 524        Serial.println(msg[3], BIN);
 525        Serial.println(msg[4], BIN);
 526        Serial.println(msg[5], BIN);
 527        Serial.println(msg[6], BIN);
 528        */
 529        unsigned short match = (~msg[hitindex])&0x00FF | (hitindex<<8);
 530        //Serial.println(match,HEX);  
 531        for (i=0; i<sizeof(i2ckeys); i++) {
 532          if (match == i2ckeys[i]) {
 533            //Serial.println((int)keys[i]);      
 534            return (keys[i]);
 535          }
 536        }
 537      }    
 538    }
 539  #endif
 540    return(retval);
 541  }
 542  
 543  void emu_InitJoysticks(void) { 
 544  
 545    // Second Joystick   
 546  #ifdef PIN_JOY1_1
 547    pinMode(PIN_JOY1_1, INPUT_PULLUP);
 548  #endif  
 549  #ifdef PIN_JOY1_2
 550    pinMode(PIN_JOY1_2, INPUT_PULLUP);
 551  #endif  
 552  #ifdef PIN_JOY1_3
 553    pinMode(PIN_JOY1_3, INPUT_PULLUP);
 554  #endif  
 555  #ifdef PIN_JOY1_4
 556    pinMode(PIN_JOY1_4, INPUT_PULLUP);
 557  #endif  
 558  #ifdef PIN_JOY1_BTN
 559    pinMode(PIN_JOY1_BTN, INPUT_PULLUP);
 560  #endif  
 561  
 562  #ifdef PIN_KEY_USER1
 563    pinMode(PIN_KEY_USER1, INPUT_PULLUP);
 564  #endif  
 565  #ifdef PIN_KEY_USER2
 566    pinMode(PIN_KEY_USER2, INPUT_PULLUP);
 567  #endif  
 568  #ifdef PIN_KEY_USER3
 569    pinMode(PIN_KEY_USER3, INPUT_PULLUP);
 570  #endif  
 571  #ifdef PIN_KEY_USER4
 572    pinMode(PIN_KEY_USER4, INPUT_PULLUP);
 573  #endif  
 574  #ifdef PIN_JOY2_BTN
 575    pinMode(PIN_JOY2_BTN, INPUT_PULLUP);
 576  #endif  
 577    analogReadResolution(12);
 578    xRef=0; yRef=0;
 579    for (int i=0; i<10; i++) {
 580      xRef += analogRead(PIN_JOY2_A1X);
 581      yRef += analogRead(PIN_JOY2_A2Y);  
 582      delay(20);
 583    }
 584  
 585  #if INVX
 586    xRef = 4095 -xRef/10;
 587  #else
 588    xRef /= 10;
 589  #endif
 590  #if INVY
 591    yRef = 4095 -yRef/10;
 592  #else
 593    yRef /= 10;
 594  #endif   
 595  }
 596  
 597  
 598  
 599  static bool vkbKeepOn = false;
 600  static bool vkbActive = false;
 601  static bool vkeyRefresh=false;
 602  static bool exitVkbd = false;
 603  static uint8_t keyPressCount=0; 
 604  
 605  
 606  bool virtualkeyboardIsActive(void) {
 607      return (vkbActive);
 608  }
 609  
 610  void toggleVirtualkeyboard(bool keepOn) {
 611         
 612      if (keepOn) {      
 613          tft.drawSpriteNoDma(0,0,logo);
 614          //prev_zt = 0;
 615          vkbKeepOn = true;
 616          vkbActive = true;
 617          exitVkbd = false;  
 618      }
 619      else {
 620          vkbKeepOn = false;
 621          if ( (vkbActive) /*|| (exitVkbd)*/ ) {
 622              tft.fillScreenNoDma( RGBVAL16(0x00,0x00,0x00) );
 623              tft.startDMA();                     
 624              //prev_zt = 0; 
 625              vkbActive = false;
 626              exitVkbd = false;
 627          }
 628          else {         
 629              tft.stopDMA();                  
 630              tft.drawSpriteNoDma(0,0,logo);           
 631              //prev_zt = 0;
 632              vkbActive = true;
 633              exitVkbd = false;
 634          }
 635      }   
 636  }
 637  
 638   
 639  void handleVirtualkeyboard() {
 640    int rx=0,ry=0,rw=0,rh=0;
 641  
 642      if (keyPressCount == 0) {
 643        keypadval = 0;      
 644      } else {
 645        keyPressCount--;
 646      }
 647      
 648      if ( (!virtualkeyboardIsActive()) && (tft.isTouching()) && (!keyPressCount) ) {
 649          toggleVirtualkeyboard(false);
 650          return;
 651      }
 652      
 653      if ( ( (vkbKeepOn) || (virtualkeyboardIsActive())  )  ) {
 654          char c = captureTouchZone(keysw, keys, &rx,&ry,&rw,&rh);
 655          if (c) {
 656  
 657              tft.drawRectNoDma( rx,ry,rw,rh, KEYBOARD_HIT_COLOR );
 658              if ( (c >=1) && (c <= ACTION_MAXKBDVAL) ) {
 659              
 660                keypadval = c;
 661                keyPressCount = 10;
 662                delay(50);
 663                vkeyRefresh = true;
 664                exitVkbd = true;
 665              }
 666              else if (c == ACTION_EXITKBD) {
 667                vkeyRefresh = true;
 668                exitVkbd = true;  
 669              }
 670          }   
 671       }    
 672       
 673      if (vkeyRefresh) {
 674          vkeyRefresh = false;
 675          tft.drawSpriteNoDma(0,0,logo, rx, ry, rw, rh);
 676      }  
 677           
 678      if ( (exitVkbd) && (vkbActive) ) {      
 679          if (!vkbKeepOn) {             
 680              toggleVirtualkeyboard(false);
 681          }
 682          else {         
 683              toggleVirtualkeyboard(true);           
 684          } 
 685      }
 686  }
 687  
 688  int emu_setKeymap(int index) {
 689  }
 690  
 691  
 692  
 693  
 694  static int readNbFiles(void) {
 695    int totalFiles = 0;
 696  
 697  #ifdef USE_SDFS
 698    DIR dir;
 699    FILINFO entry; 
 700    f_opendir(&dir, romspath);  
 701    while ( (true) && (totalFiles<MAX_FILES) ) {
 702      f_readdir(&dir, &entry);
 703      if (!entry.fname[0]) {
 704        // no more files
 705        break;
 706      }
 707      char * filename = entry.fname;
 708      Serial.println(filename);     
 709      if ( !(entry.fattrib & AM_DIR) ) {
 710        strncpy(&files[totalFiles][0], filename, MAX_FILENAME_SIZE-1);
 711        totalFiles++;
 712      }
 713      else {
 714        if ( (strcmp(filename,".")) && (strcmp(filename,"..")) ) {
 715          strncpy(&files[totalFiles][0], filename, MAX_FILENAME_SIZE-1);
 716          totalFiles++;
 717        }
 718      }  
 719    } 
 720    f_closedir(&dir);
 721  #else
 722    File entry;    
 723    file = SD.open(romspath);
 724    while ( (true) && (totalFiles<MAX_FILES) ) {
 725      entry = file.openNextFile();
 726      if (! entry) {
 727        // no more files
 728        break;
 729      }
 730  #ifdef USE_SDFAT
 731    char filename[MAX_FILENAME_SIZE];
 732    entry.getName(&filename[0], MAX_FILENAME_SIZE); 
 733  #else
 734    char * filename = entry.name();
 735  #endif 
 736      Serial.println(filename); 
 737      if (!entry.isDirectory())  {
 738        strncpy(&files[totalFiles][0], filename, MAX_FILENAME_SIZE-1);
 739        totalFiles++;
 740      }
 741      else {
 742        if ( (strcmp(filename,".")) && (strcmp(filename,"..")) ) {
 743          strncpy(&files[totalFiles][0], filename, MAX_FILENAME_SIZE-1);
 744          totalFiles++;
 745        }
 746      }  
 747      entry.close();
 748    }
 749    file.close();
 750  #endif  
 751    return totalFiles;  
 752  }  
 753  
 754  
 755  
 756  void backgroundMenu(void) {
 757      menuRedraw=true;  
 758      tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
 759      tft.drawTextNoDma(0,0, TITLE, RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);  
 760  #ifndef HAS_T4_VGA
 761      tft.drawSpriteNoDma(MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,bmpvbar);
 762  #endif    
 763  #ifdef OLD_LAYOUT    
 764      tft.drawSpriteNoDma(MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,bmptft);
 765      tft.drawSpriteNoDma(MENU_VGA_XOFFSET,MENU_VGA_YOFFSET,bmpvga);
 766  #endif      
 767  }
 768  
 769  int handleMenu(uint16_t bClick)
 770  {
 771    int action = ACTION_NONE;
 772  
 773    char newpath[80];
 774    strcpy(newpath, romspath);
 775    strcat(newpath, "/");
 776    strcat(newpath, selection);
 777  
 778    int rx=0,ry=0,rw=0,rh=0;
 779    char c = 0; //captureTouchZone(menutouchareas, menutouchactions, &rx,&ry,&rw,&rh);
 780   
 781    if ( (bClick & MASK_JOY2_BTN) || (c == MKEY_TFT) ) {     
 782        emu_printf(newpath);
 783  #ifdef USE_SDFS
 784        FILINFO entry;
 785        f_stat(newpath, &entry);
 786        if ( (entry.fattrib & AM_DIR) ) {
 787  #else
 788        File file = SD.open(newpath);
 789        if (file.isDirectory())  {
 790  #endif      
 791          strcpy(romspath,newpath);
 792          curFile = 0;
 793          nbFiles = readNbFiles();             
 794        }
 795        else {
 796          action = ACTION_RUNTFT;               
 797        }
 798        menuRedraw=true;
 799    }
 800    else if ( (bClick & MASK_KEY_USER1) || (c == MKEY_VGA) ) {
 801        menuRedraw=true;
 802        action = ACTION_RUNVGA;    
 803    }
 804    else if ( (c >= MKEY_L1) && (c <= MKEY_L9) ) {
 805      if ( (topFile+(int)c-1) <= (nbFiles-1)  )
 806      {
 807        curFile = topFile + (int)c -1;
 808        menuRedraw=true;
 809       //tft.drawRectNoDma( rx,ry,rw,rh, KEYBOARD_HIT_COLOR );
 810      }
 811    }
 812    else if (bClick & MASK_JOY2_UP) {
 813      if (curFile!=0) {
 814        menuRedraw=true;
 815        curFile--;
 816      }
 817    }
 818    else if ( (bClick & MASK_JOY2_RIGHT) || (bClick & MASK_JOY1_RIGHT) || (c == MKEY_UP) ) {
 819      if ((curFile-9)>=0) {
 820        menuRedraw=true;
 821        curFile -= 9;
 822      } else if (curFile!=0) {
 823        menuRedraw=true;
 824        curFile--;
 825      }
 826    }  
 827    else if (bClick & MASK_JOY2_DOWN)  {
 828      if ((curFile<(nbFiles-1)) && (nbFiles)) {
 829        curFile++;
 830        menuRedraw=true;
 831      }
 832    }
 833    else if ( (bClick & MASK_JOY2_LEFT) || (bClick & MASK_JOY1_LEFT) || (c == MKEY_DOWN) ) {
 834      if ((curFile<(nbFiles-9)) && (nbFiles)) {
 835        curFile += 9;
 836        menuRedraw=true;
 837      }
 838      else if ((curFile<(nbFiles-1)) && (nbFiles)) {
 839        curFile++;
 840        menuRedraw=true;
 841      }
 842    }
 843    else if ( (bClick & MASK_KEY_USER2) || (c == MKEY_JOY) ) {
 844      emu_SwapJoysticks(0);
 845      menuRedraw=true;  
 846    }   
 847      
 848    if (menuRedraw && nbFiles) {
 849      int fileIndex = 0;
 850      tft.drawRectNoDma(MENU_FILE_XOFFSET,MENU_FILE_YOFFSET, MENU_FILE_W, MENU_FILE_H, MENU_FILE_BGCOLOR);
 851  //    if (curFile <= (MAX_MENULINES/2-1)) topFile=0;
 852  //    else topFile=curFile-(MAX_MENULINES/2);
 853      if (curFile <= (MAX_MENULINES-1)) topFile=0;
 854      else topFile=curFile-(MAX_MENULINES/2);
 855  
 856      //Serial.print("curfile: ");
 857      //Serial.println(curFile);
 858      //Serial.print("topFile: ");
 859      //Serial.println(topFile);
 860      
 861      int i=0;
 862      while (i<MAX_MENULINES) {
 863        if (fileIndex>=nbFiles) {
 864            // no more files
 865            break;
 866        }
 867        char * filename = &files[fileIndex][0];    
 868        if (fileIndex >= topFile) {              
 869          if ((i+topFile) < nbFiles ) {
 870            if ((i+topFile)==curFile) {
 871              tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, RGBVAL16(0xff,0xff,0x00), RGBVAL16(0xff,0x00,0x00), true);
 872              strcpy(selection,filename);            
 873            }
 874            else {
 875              tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, RGBVAL16(0xff,0xff,0xff), MENU_FILE_BGCOLOR, true);      
 876            }
 877          }
 878          i++; 
 879        }
 880        fileIndex++;    
 881      }
 882  
 883  #ifndef HAS_T4_VGA
 884      tft.drawSpriteNoDma(0,MENU_JOYS_YOFFSET,(uint16_t*)bmpjoy);
 885  #endif      
 886      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);
 887      menuRedraw=false;     
 888    }
 889  
 890    return (action);  
 891  }
 892  
 893  bool menuActive(void) 
 894  {
 895    return (menuOn);
 896  }
 897  
 898  void toggleMenu(bool on) {
 899    if (on) {
 900      callibrationOn=false;
 901      menuOn=true;
 902      backgroundMenu();
 903    } else {
 904      menuOn = false;    
 905    }
 906  }
 907  
 908  char * menuSelection(void)
 909  {
 910    return (selection);  
 911  }
 912    
 913  
 914  
 915  
 916  static void callibrationInit(void) 
 917  {
 918    callibrationOn=true;
 919    menuOn=false;
 920    callibrationStep = 0;
 921    calMinX=0,calMinY=0,calMaxX=0,calMaxY=0;
 922    tft.fillScreenNoDma(RGBVAL16(0xff,0xff,0xff));
 923    tft.drawTextNoDma(0,100, "          Callibration process:", RGBVAL16(0x00,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true);
 924    tft.drawTextNoDma(0,116, "     Hit the red cross at each corner", RGBVAL16(0x00,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true);
 925    tft.drawTextNoDma(0,0, "+", RGBVAL16(0xff,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true);
 926    prev_zt = 1;  
 927  }
 928  
 929  
 930  static void readCallibration(void) 
 931  {
 932    char fileBuffer[64];
 933  
 934  #ifdef USE_SDFS
 935    FIL file;
 936    int retval;          
 937    if( !(f_open(&file, CALIBRATION_FILE, FA_READ)) ) {
 938      if( !(f_read (&file, fileBuffer, 64, &retval)) ) {
 939        if (retval == 64) { 
 940          sscanf(fileBuffer,"%d %d %d %d", &calMinX,&calMinY,&calMaxX,&calMaxY); 
 941        }
 942      }
 943      f_close(&file);    
 944    }
 945  #else
 946    File file = SD.open(CALIBRATION_FILE, O_READ);  
 947    if (file) {
 948      if ( file.read(fileBuffer, 64) ) {     
 949        sscanf(fileBuffer,"%d %d %d %d", &calMinX,&calMinY,&calMaxX,&calMaxY);
 950      }
 951      file.close();
 952      Serial.println("Current callibration params:");
 953      Serial.println(calMinX);
 954      Serial.println(calMinY);
 955      Serial.println(calMaxX);
 956      Serial.println(calMaxY);                 
 957    }
 958  #endif  
 959    else {
 960      Serial.println("Callibration read error");
 961    }  
 962     tft.callibrateTouch(calMinX,calMinY,calMaxX,calMaxY);   
 963  }
 964  
 965  static void writeCallibration(void) 
 966  {
 967    tft.callibrateTouch(calMinX,calMinY,calMaxX,calMaxY);
 968  
 969  #ifdef USE_SDFS
 970    FIL file; 
 971    int retval;       
 972    if( !(f_open(&file, CALIBRATION_FILE, FA_WRITE)) ) {
 973      //if( !(f_read (&file, fileBuffer, 64, &retval)) ) {
 974      //  if (retval == 64) { 
 975      //    sscanf(fileBuffer,"%d %d %d %d", &calMinX,&calMinY,&calMaxX,&calMaxY); 
 976      //  }
 977      //}
 978      f_close(&file);    
 979    }
 980  #else
 981    File file = SD.open(CALIBRATION_FILE, O_WRITE | O_CREAT | O_TRUNC);
 982    if (file) {
 983      file.print(calMinX);
 984      file.print(" ");
 985      file.print(calMinY);
 986      file.print(" ");
 987      file.print(calMaxX);
 988      file.print(" ");
 989      file.println(calMaxY);
 990      file.close();
 991    }
 992  #endif  
 993    else {
 994      Serial.println("Callibration write error");
 995    }  
 996  }
 997  
 998  
 999  bool callibrationActive(void) 
1000  {
1001    return (callibrationOn);
1002  }
1003  
1004  
1005  
1006  int handleCallibration(uint16_t bClick) {
1007    uint16_t xt=0;
1008    uint16_t yt=0;
1009    uint16_t zt=0;  
1010    if (tft.isTouching()) {
1011      if (prev_zt == 0) {
1012        prev_zt = 1;
1013        tft.readRaw(&xt,&yt,&zt);
1014        if (zt < 1000) {
1015          return 0;
1016        }
1017        switch (callibrationStep) 
1018        {
1019          case 0:
1020            callibrationStep++;
1021            tft.drawTextNoDma(0,0, " ", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0xff,0xff,0xff), true);
1022            tft.drawTextNoDma(TFT_REALWIDTH-8,0, "+", RGBVAL16(0xff,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true);
1023            calMinX += xt;
1024            calMinY += yt;          
1025            break;
1026          case 1:
1027            callibrationStep++;
1028            tft.drawTextNoDma(TFT_REALWIDTH-8,0, " ", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0xff,0xff,0xff), true);
1029            tft.drawTextNoDma(TFT_REALWIDTH-8,TFT_REALHEIGHT-16, "+", RGBVAL16(0xff,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true);
1030            calMaxX += xt;
1031            calMinY += yt;           
1032            break;
1033          case 2:
1034            callibrationStep++;
1035            tft.drawTextNoDma(TFT_REALWIDTH-8,TFT_REALHEIGHT-16, " ", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0xff,0xff,0xff), true);
1036            tft.drawTextNoDma(0,TFT_REALHEIGHT-16, "+", RGBVAL16(0xff,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true);
1037            calMaxX += xt;
1038            calMaxY += yt;
1039            break;
1040          case 3:
1041            tft.fillScreenNoDma(RGBVAL16(0xff,0xff,0xff));
1042            tft.drawTextNoDma(0,100, "          Callibration done!", RGBVAL16(0x00,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true);
1043            tft.drawTextNoDma(0,116, "        (Click center to exit)", RGBVAL16(0xff,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true);           
1044            callibrationStep++;
1045            calMinX += xt;
1046            calMaxY += yt;       
1047            break;                 
1048          case 4:
1049            //Serial.println(xt);
1050            //Serial.println(yt);
1051            if ( (xt > (TFT_REALWIDTH/4)) && (xt < (TFT_REALWIDTH*3)/4) 
1052              && (yt > (TFT_REALHEIGHT/4)) && (yt < (TFT_REALHEIGHT*3)/4) ) {
1053              calMinX /= 2;
1054              calMinY /= 2;
1055              calMaxX /= 2;
1056              calMaxY /= 2;
1057              writeCallibration();                       
1058              toggleMenu(true);
1059            }
1060            else {
1061              callibrationInit();              
1062            }
1063            break; 
1064                             
1065        }
1066        delay(100);
1067      }  
1068    }
1069    else {
1070      prev_zt = 0;
1071    }  
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    emu_InitJoysticks();
1537  #ifdef SWAP_JOYSTICK
1538    joySwapped = true;   
1539  #else
1540    joySwapped = false;   
1541  #endif  
1542    readCallibration();
1543   
1544    if ((tft.isTouching()) || (emu_ReadKeys() & MASK_JOY2_BTN) ) {
1545      callibrationInit();
1546    } 
1547    else  
1548    {
1549      toggleMenu(true);
1550    }
1551  }
1552  
1553  
1554  void emu_start(void)
1555  {
1556  #ifdef HAS_I2CKBD
1557    byte msg[7]={0,0,0,0,0,0,0};
1558    Wire.begin(); // join i2c bus SDA2/SCL2
1559    Wire.requestFrom(8, 7);    // request 7 bytes from slave device #8 
1560    int i = 0;
1561    while (Wire.available() && (i<7) ) { // slave may send less than requested
1562      byte b = Wire.read(); // receive a byte
1563      msg[i++] = b;        
1564    }
1565    /*     
1566    Serial.println(msg[0], BIN);
1567    Serial.println(msg[1], BIN);
1568    Serial.println(msg[2], BIN);
1569    Serial.println(msg[3], BIN);
1570    Serial.println(msg[4], BIN);
1571    Serial.println(msg[5], BIN);
1572    Serial.println(msg[6], BIN);
1573    */  
1574    if ( (msg[0] == 0xff) && (msg[1] == 0xff) && 
1575         (msg[2] == 0xff) && (msg[3] == 0xff) && 
1576         (msg[4] == 0xff) && (msg[5] == 0xff) && (msg[6] == 0xff)) {
1577      i2cKeyboardPresent = true;
1578      Serial.println("i2C keyboard found");            
1579    }
1580  #endif
1581  
1582    usbnavpad = 0;
1583    
1584    keys = key_map1;
1585    keyMap = 0;
1586  }