#define KEYMAP_PRESENT 1 extern "C" { #include "emuapi.h" #include "iopins.h" } #ifdef HAS_T4_VGA #include "vga_t_dma.h" const uint16_t deflogo[] = { 0,0 }; static const uint16_t * logo = deflogo; #else #include "tft_t_dma.h" #include "logo.h" #endif #include "bmpjoy.h" #include "bmpvbar.h" #ifdef OLD_LAYOUT #include "bmpvga.h" #include "bmptft.h" #endif #ifdef HAS_I2CKBD #include #endif #ifdef HAS_USBKEY #include "USBHost_t36.h" // Read this header first for key info USBHost myusb; USBHub hub1(myusb); KeyboardController keyboard1(myusb); USBHIDParser hid1(myusb); MouseController mouse1(myusb); MIDIDevice midi1(myusb); #endif static bool mouseDetected = false; static bool keyboardDetected = false; static uint8_t usbnavpad=0; #ifdef USE_SDFS #include "uSDFS.h" static FATFS fatfs; static FIL file; #else #ifdef USE_SDFAT #include "SdFat.h" #include "sdios.h" #ifndef SDCARD_SS_PIN const uint8_t SD_CS_PIN = SS; #else // SDCARD_SS_PIN // Assume built-in SD is used. const uint8_t SD_CS_PIN = SDCARD_SS_PIN; #endif // SDCARD_SS_PIN #define SD_CONFIG SdioConfig(FIFO_SDIO) // Try to select the best SD card configuration. #if HAS_SDIO_CLASS #define SD_CONFIG SdioConfig(FIFO_SDIO) #elif ENABLE_DEDICATED_SPI #define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI) #else // HAS_SDIO_CLASS #define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI) #endif // HAS_SDIO_CLASS //------------------------------------------------------------------------------ #if SD_FAT_TYPE == 0 #elif SD_FAT_TYPE == 1 #define SdFat SdFat32 #define File File32 #elif SD_FAT_TYPE == 2 #define SdFat SdExFat #define File ExFile #elif SD_FAT_TYPE == 3 #define SdFat SdFs #define File FsFile #endif // SD_FAT_TYPE static SdFat SD; #else #include #endif static File file; #endif #define CALIBRATION_FILE "/cal.cfg" #define MKEY_L1 1 #define MKEY_L2 2 #define MKEY_L3 3 #define MKEY_L4 4 #define MKEY_L5 5 #define MKEY_L6 6 #define MKEY_L7 7 #define MKEY_L8 8 #define MKEY_L9 9 #define MKEY_UP 20 #define MKEY_DOWN 21 #define MKEY_JOY 22 #define MKEY_TFT 23 #define MKEY_VGA 24 #define MAX_FILES 64 #define MAX_FILENAME_SIZE 24 #define MAX_MENULINES (MKEY_L9) #define TEXT_HEIGHT 16 #define TEXT_WIDTH 8 #define MENU_FILE_XOFFSET (6*TEXT_WIDTH) #define MENU_FILE_YOFFSET (2*TEXT_HEIGHT) #define MENU_FILE_W (MAX_FILENAME_SIZE*TEXT_WIDTH) #define MENU_FILE_H (MAX_MENULINES*TEXT_HEIGHT) #define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x40) #define MENU_JOYS_YOFFSET (12*TEXT_HEIGHT) #define MENU_VBAR_XOFFSET (0*TEXT_WIDTH) #define MENU_VBAR_YOFFSET (MENU_FILE_YOFFSET) #define MENU_TFT_XOFFSET (MENU_FILE_XOFFSET+MENU_FILE_W+8) #define MENU_TFT_YOFFSET (MENU_VBAR_YOFFSET+32) #define MENU_VGA_XOFFSET (MENU_FILE_XOFFSET+MENU_FILE_W+8) #define MENU_VGA_YOFFSET (MENU_VBAR_YOFFSET+MENU_FILE_H-32-37) extern TFT_T_DMA tft; static char romspath[64]; static int nbFiles=0; static int curFile=0; static int topFile=0; static char selection[MAX_FILENAME_SIZE+1]=""; static char shown_selection[MAX_FILENAME_SIZE+1]=""; static char files[MAX_FILES][MAX_FILENAME_SIZE]; static bool menuRedraw=true; static int calMinX=-1,calMinY=-1,calMaxX=-1,calMaxY=-1; static bool i2cKeyboardPresent = false; static unsigned short * keys; static int keyMap; const unsigned short menutouchareas[] = { TAREA_XY,MENU_FILE_XOFFSET,MENU_FILE_YOFFSET, TAREA_WH,MENU_FILE_W, TEXT_HEIGHT, TAREA_NEW_COL,TEXT_HEIGHT,TEXT_HEIGHT,TEXT_HEIGHT,TEXT_HEIGHT,TEXT_HEIGHT,TEXT_HEIGHT,TEXT_HEIGHT,TEXT_HEIGHT,TEXT_HEIGHT, TAREA_XY,MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET, TAREA_WH,32,48, TAREA_NEW_COL, 72,72,8,40, TAREA_XY,MENU_TFT_XOFFSET,MENU_TFT_YOFFSET, TAREA_WH,32,37, TAREA_NEW_COL, 38,38, TAREA_END}; const unsigned short menutouchactions[] = { MKEY_L1,MKEY_L2,MKEY_L3,MKEY_L4,MKEY_L5,MKEY_L6,MKEY_L7,MKEY_L8,MKEY_L9, MKEY_UP,MKEY_DOWN,ACTION_NONE,MKEY_JOY, MKEY_TFT,MKEY_VGA}; static int keypadval=0; static boolean joySwapped = false; static uint16_t bLastState; static int xRef; static int yRef; static uint8_t prev_zt=0; static bool menuOn=true; static bool callibrationOn=false; static int callibrationStep=0; static char captureTouchZone(const unsigned short * areas, const unsigned short * actions, int *rx, int *ry, int *rw, int * rh) { uint16_t xt=0; uint16_t yt=0; uint16_t zt=0; boolean hDir=true; if (tft.isTouching()) { if (prev_zt == 0) { prev_zt =1; tft.readCal(&xt,&yt,&zt); if (zt<1000) { prev_zt=0; return ACTION_NONE; } int i=0; int k=0; int y2=0, y1=0; int x2=0, x1=0; int x=KEYBOARD_X,y=KEYBOARD_Y; int w=TAREA_W_DEF,h=TAREA_H_DEF; uint8_t s; while ( (s=areas[i++]) != TAREA_END ) { if (s == TAREA_XY) { x = areas[i++]; y = areas[i++]; x2 = x; y2 = y; } else if (s == TAREA_WH) { w = areas[i++]; h = areas[i++]; } else if (s == TAREA_NEW_ROW) { hDir = true; y1 = y2; y2 = y1 + h; x2 = x; } else if (s == TAREA_NEW_COL) { hDir = false; x1 = x2; x2 = x1 + w; y2 = y; } else { if (hDir) { x1 = x2; x2 = x1+s; } else { y1 = y2; y2 = y1+s; } if ( (yt >= y1) && (yt < y2) && (xt >= x1) && (xt < x2) ) { *rx = x1; *ry = y1; *rw = x2-x1; *rh = y2-y1; return (actions[k]); } k++; } } } prev_zt =1; } else { prev_zt=0; } return ACTION_NONE; } void emu_printf(char * text) { Serial.println(text); } void emu_printf(int val) { Serial.println(val); } void emu_printi(int val) { Serial.println(val,HEX); } void emu_printh(int val) { Serial.println(val,HEX); } static int malbufpt = 0; static char malbuf[EXTRA_HEAP]; void * emu_Malloc(int size) { void * retval = malloc(size); if (!retval) { emu_printf("failled to allocate"); emu_printf(size); emu_printf("fallback"); if ( (malbufpt+size) < sizeof(malbuf) ) { retval = (void *)&malbuf[malbufpt]; malbufpt += size; } else { emu_printf("failure to allocate"); } } else { emu_printf("could allocate dynamic "); emu_printf(size); } return retval; } void * emu_MallocI(int size) { void * retval = NULL; if ( (malbufpt+size) < sizeof(malbuf) ) { retval = (void *)&malbuf[malbufpt]; malbufpt += size; emu_printf("could allocate static "); emu_printf(size); } else { emu_printf("failure to allocate"); } return retval; } void emu_Free(void * pt) { free(pt); } int emu_ReadAnalogJoyX(int min, int max) { int val = analogRead(PIN_JOY2_A1X); #if INVX val = 4095 - val; #endif val = val-xRef; val = ((val*140)/100); if ( (val > -512) && (val < 512) ) val = 0; val = val+2048; return (val*(max-min))/4096; } int emu_ReadAnalogJoyY(int min, int max) { int val = analogRead(PIN_JOY2_A2Y); #if INVY val = 4095 - val; #endif val = val-yRef; val = ((val*120)/100); if ( (val > -512) && (val < 512) ) val = 0; //val = (val*(max-min))/4096; val = val+2048; //return val+(max-min)/2; return (val*(max-min))/4096; } static uint16_t readAnalogJoystick(void) { uint16_t joysval = 0; int xReading = emu_ReadAnalogJoyX(0,256); if (xReading > 128) joysval |= MASK_JOY2_LEFT; else if (xReading < 128) joysval |= MASK_JOY2_RIGHT; int yReading = emu_ReadAnalogJoyY(0,256); if (yReading < 128) joysval |= MASK_JOY2_UP; else if (yReading > 128) joysval |= MASK_JOY2_DOWN; #ifdef PIN_JOY2_BTN joysval |= (digitalRead(PIN_JOY2_BTN) == HIGH ? 0 : MASK_JOY2_BTN); #endif return (joysval); } int emu_SwapJoysticks(int statusOnly) { if (!statusOnly) { if (joySwapped) { joySwapped = false; } else { joySwapped = true; } } return(joySwapped?1:0); } int emu_GetPad(void) { return(keypadval/*|((joySwapped?1:0)<<7)*/); } int emu_ReadKeys(void) { uint16_t retval; uint16_t j1 = readAnalogJoystick(); uint16_t j2 = 0; // Second joystick #ifdef PIN_JOY1_1 if ( digitalRead(PIN_JOY1_1) == LOW ) j2 |= MASK_JOY2_UP; #endif #ifdef PIN_JOY1_2 if ( digitalRead(PIN_JOY1_2) == LOW ) j2 |= MASK_JOY2_DOWN; #endif #ifdef PIN_JOY1_3 if ( digitalRead(PIN_JOY1_3) == LOW ) j2 |= MASK_JOY2_RIGHT; #endif #ifdef PIN_JOY1_4 if ( digitalRead(PIN_JOY1_4) == LOW ) j2 |= MASK_JOY2_LEFT; #endif #ifdef PIN_JOY1_BTN if ( digitalRead(PIN_JOY1_BTN) == LOW ) j2 |= MASK_JOY2_BTN; #endif if (joySwapped) { retval = ((j1 << 8) | j2); } else { retval = ((j2 << 8) | j1); } if (usbnavpad & MASK_JOY2_UP) retval |= MASK_JOY2_UP; if (usbnavpad & MASK_JOY2_DOWN) retval |= MASK_JOY2_DOWN; if (usbnavpad & MASK_JOY2_LEFT) retval |= MASK_JOY2_LEFT; if (usbnavpad & MASK_JOY2_RIGHT) retval |= MASK_JOY2_RIGHT; if (usbnavpad & MASK_JOY2_BTN) retval |= MASK_JOY2_BTN; if (usbnavpad & MASK_KEY_USER1) retval |= MASK_KEY_USER1; if (usbnavpad & MASK_KEY_USER2) retval |= MASK_KEY_USER2; #ifdef PIN_KEY_USER1 if ( digitalRead(PIN_KEY_USER1) == LOW ) retval |= MASK_KEY_USER1; #endif #ifdef PIN_KEY_USER2 if ( digitalRead(PIN_KEY_USER2) == LOW ) retval |= MASK_KEY_USER2; #endif #ifdef PIN_KEY_USER3 if ( digitalRead(PIN_KEY_USER3) == LOW ) retval |= MASK_KEY_USER3; #endif #ifdef PIN_KEY_USER4 if ( digitalRead(PIN_KEY_USER4) == LOW ) retval |= MASK_KEY_USER4; #endif //Serial.println(retval,HEX); if ( ((retval & (MASK_KEY_USER1+MASK_KEY_USER2)) == (MASK_KEY_USER1+MASK_KEY_USER2)) || (retval & MASK_KEY_USER4 ) ) { // Reset procedure T3.X and T4.0 by Frank Boesing !! #if defined(__IMXRT1052__) || defined(__IMXRT1062__) uint32_t tmp = SNVS_LPCR; // save control register SNVS_LPSR |= 1; // disable alarm SNVS_LPCR &= ~0x02; while (SNVS_LPCR & 0x02); __disable_irq(); //get Time: uint32_t lsb, msb; do { msb = SNVS_LPSRTCMR; lsb = SNVS_LPSRTCLR; } while ( (SNVS_LPSRTCLR != lsb) | (SNVS_LPSRTCMR != msb) ); uint32_t secs = (msb << 17) | (lsb >> 15); //set alarm secs += 2; SNVS_LPTAR = secs; while (SNVS_LPTAR != secs); SNVS_LPCR = tmp | 0x02; // restore control register and set alarm while (!(SNVS_LPCR & 0x02)); SNVS_LPCR |= (1 << 6); // turn off power while (1) asm("wfi"); #else *(volatile uint32_t *)0xE000ED0C = 0x5FA0004; while (true) { ; } #endif } return (retval); } unsigned short emu_DebounceLocalKeys(void) { uint16_t bCurState = emu_ReadKeys(); uint16_t bClick = bCurState & ~bLastState; bLastState = bCurState; return (bClick); } int emu_ReadI2CKeyboard(void) { int retval=0; #ifdef HAS_I2CKBD if (i2cKeyboardPresent) { byte msg[7]={0,0,0,0,0,0,0}; Wire.requestFrom(8, 7); // request 7 bytes from slave device #8 int i = 0; int hitindex=-1; while (Wire.available() && (i<7) ) { // slave may send less than requested byte b = Wire.read(); // receive a byte if (b != 0xff) hitindex=i; msg[i++] = b; } if (hitindex >=0 ) { /* Serial.println(msg[0], BIN); Serial.println(msg[1], BIN); Serial.println(msg[2], BIN); Serial.println(msg[3], BIN); Serial.println(msg[4], BIN); Serial.println(msg[5], BIN); Serial.println(msg[6], BIN); */ unsigned short match = (~msg[hitindex])&0x00FF | (hitindex<<8); //Serial.println(match,HEX); for (i=0; i=1) && (c <= ACTION_MAXKBDVAL) ) { keypadval = c; keyPressCount = 10; delay(50); vkeyRefresh = true; exitVkbd = true; } else if (c == ACTION_EXITKBD) { vkeyRefresh = true; exitVkbd = true; } } } if (vkeyRefresh) { vkeyRefresh = false; tft.drawSpriteNoDma(0,0,logo, rx, ry, rw, rh); } if ( (exitVkbd) && (vkbActive) ) { if (!vkbKeepOn) { toggleVirtualkeyboard(false); } else { toggleVirtualkeyboard(true); } } } int emu_setKeymap(int index) { if (keyMap == 2) { keyMap = 0; keys = key_map1; tft.drawText(0, 0, "N1 IN2 IN3 IN4 IN5 IN6 IN7 IN8 IN9 IN10I", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true); tft.drawText(0,16, "--- --- --- --- --- --- --- --- --- --- ", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), false); tft.drawText(0,24, " q I w I e I r I t I y I u I i I o I p I", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0x80), true); tft.drawText(0,40, "--- --- --- --- --- --- --- --- --- --- ", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0x80), false); tft.drawText(0,48, " a I s I d I f I g I h I j I k I l IRTNI", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true); tft.drawText(0,64, "--- --- --- --- --- --- --- --- --- --- ", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), false); tft.drawText(0,72, " z I x I c I v I b I n I m I , I ; ISPCI", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0x80), true); tft.drawText(0,88, "--- --- --- --- --- --- --- --- --- --- ", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0x80), false); delay(250); } else if (keyMap == 0) { keyMap = 1; keys = key_map2; tft.drawText(0, 0, "F1 IF2 IF3 IF4 IF5 IF6 IF7 IF8 IF9 IF10I", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true); tft.drawText(0,16, "--- --- --- --- --- --- --- --- --- --- ", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), false); tft.drawText(0,24, " q I w I e I r I t I y I u I i I o I p I", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0x80), true); tft.drawText(0,40, "--- --- --- --- --- --- --- --- --- --- ", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0x80), false); tft.drawText(0,48, " a I s I d I f I g I h I j I k I l IRTNI", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true); tft.drawText(0,64, "--- --- --- --- --- --- --- --- --- --- ", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), false); tft.drawText(0,72, " z I x I c I v I b I n I m I , I ; ISPCI", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0x80), true); tft.drawText(0,88, "--- --- --- --- --- --- --- --- --- --- ", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0x80), false); delay(250); } else { keyMap = 2; keys = key_map3; tft.drawText(0, 0, " 1 I 2 I 3 I 4 I 5 I 6 I 7 I 8 I 9 I 10I", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true); tft.drawText(0,16, "--- --- --- --- --- --- --- --- --- --- ", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), false); tft.drawText(0,24, " q I w I e I r I t I y I u I i I o I p I", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0x80), true); tft.drawText(0,40, "--- --- --- --- --- --- --- --- --- --- ", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0x80), false); tft.drawText(0,48, " a I s I d I f I g I h I j I k I l IRTNI", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true); tft.drawText(0,64, "--- --- --- --- --- --- --- --- --- --- ", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), false); tft.drawText(0,72, " z I x I c I v I b I n I m I , I ; ISPCI", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0x80), true); tft.drawText(0,88, "--- --- --- --- --- --- --- --- --- --- ", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0x80), false); delay(250); } } static int readNbFiles(void) { int totalFiles = 0; #ifdef USE_SDFS DIR dir; FILINFO entry; f_opendir(&dir, romspath); while ( (true) && (totalFiles= MKEY_L1) && (c <= MKEY_L9) ) { if ( (topFile+(int)c-1) <= (nbFiles-1) ) { curFile = topFile + (int)c -1; menuRedraw=true; //tft.drawRectNoDma( rx,ry,rw,rh, KEYBOARD_HIT_COLOR ); } } else if ( (bClick & MASK_JOY2_UP) || (bClick & MASK_JOY1_UP) ) { if (curFile!=0) { menuRedraw=true; curFile--; } } else if ( (bClick & MASK_JOY2_RIGHT) || (bClick & MASK_JOY1_RIGHT) || (c == MKEY_UP) ) { if ((curFile-9)>=0) { menuRedraw=true; curFile -= 9; } else if (curFile!=0) { menuRedraw=true; curFile--; } } else if ( (bClick & MASK_JOY2_DOWN) || (bClick & MASK_JOY1_DOWN) ) { if ((curFile<(nbFiles-1)) && (nbFiles)) { curFile++; menuRedraw=true; } } else if ( (bClick & MASK_JOY2_LEFT) || (bClick & MASK_JOY1_LEFT) || (c == MKEY_DOWN) ) { if ((curFile<(nbFiles-9)) && (nbFiles)) { curFile += 9; menuRedraw=true; } else if ((curFile<(nbFiles-1)) && (nbFiles)) { curFile++; menuRedraw=true; } } if (menuRedraw && nbFiles) { int fileIndex = 0; tft.drawRectNoDma(MENU_FILE_XOFFSET,MENU_FILE_YOFFSET, MENU_FILE_W, MENU_FILE_H, MENU_FILE_BGCOLOR); // if (curFile <= (MAX_MENULINES/2-1)) topFile=0; // else topFile=curFile-(MAX_MENULINES/2); if (curFile <= (MAX_MENULINES-1)) topFile=0; else topFile=curFile-(MAX_MENULINES/2); //Serial.print("curfile: "); //Serial.println(curFile); //Serial.print("topFile: "); //Serial.println(topFile); int i=0; while (i=nbFiles) { // no more files break; } char * filename = &files[fileIndex][0]; if (fileIndex >= topFile) { if ((i+topFile) < nbFiles ) { if ((i+topFile)==curFile) { tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, RGBVAL16(0xff,0xff,0x00), RGBVAL16(0xff,0x00,0x00), true); strcpy(selection,filename); } else { tft.drawTextNoDma(MENU_FILE_XOFFSET,i*TEXT_HEIGHT+MENU_FILE_YOFFSET, filename, RGBVAL16(0xff,0xff,0xff), MENU_FILE_BGCOLOR, true); } } i++; } fileIndex++; } #ifndef HAS_T4_VGA tft.drawSpriteNoDma(0,MENU_JOYS_YOFFSET,(uint16_t*)bmpjoy); #endif // 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); tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, "FLOPPY2:", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), false); tft.drawRectNoDma(120,MENU_JOYS_YOFFSET+8, MENU_FILE_W, 8, RGBVAL16(0x00,0x00,0x00)); tft.drawTextNoDma(120,MENU_JOYS_YOFFSET+8, shown_selection, RGBVAL16(0xff,0xff,0xff), RGBVAL16(0x00,0x00,0x00), false); menuRedraw=false; } return (action); } bool menuActive(void) { return (menuOn); } void toggleMenu(bool on) { if (on) { callibrationOn=false; menuOn=true; backgroundMenu(); } else { menuOn = false; } } char * menuSelection(void) { return (selection); } int emu_GetMouse(int *x, int *y, int *buts) { #ifdef HAS_USBKEY if (mouse1.available()) { *buts = mouse1.getButtons(); *x = mouse1.getMouseX(); *y = mouse1.getMouseY(); mouse1.mouseDataClear(); mouseDetected = true; return 1; } #endif return 0; } #ifdef HAS_USBKEY void OnPress(auto key) { keyboardDetected = true; uint8_t keymodifier = keyboard1.getModifiers(); if(keymodifier == 0x40){ // ALTGR Key modifier FR Keyboard switch (key) { #ifdef LAYOUT_FRENCH case 233 : key = '~' ; break; case 34 : key = '#' ; break; case 39 : key = '{' ; break; case 40 : key = '[' ; break; case 45 : key = '|' ; break; case 232 : key = '`' ; break; case 95 : key = 92 ; break; case 231 : key = '^' ; break; case 224 : key = '@' ; break; case 41 : key = ']' ; break; case 61 : key = '}' ; break; #endif #ifdef LAYOUT_FRENCH_BELGIAN case 38 : key = '|' ; break; //1 case 233 : key = '@' ; break; //2 case 34 : key = '#' ; break; //3 case 167 : key = '^' ; break; //6 case 231 : key = '{' ; break; //9 case 224 : key = '}' ; break; //0 case 36 : key = ']' ; break; //$ case 61 : key = '~' ; break; //= #endif } } if (menuActive()) { switch (key) { case 217: usbnavpad |= MASK_JOY2_DOWN; break; case 218: usbnavpad |= MASK_JOY2_UP; break; case 216: usbnavpad |= MASK_JOY2_LEFT; break; case 215: usbnavpad |= MASK_JOY2_RIGHT; break; case 10: usbnavpad |= MASK_JOY2_BTN; break; case 32: usbnavpad |= MASK_KEY_USER1; break; case 9: usbnavpad |= MASK_KEY_USER2; break; } } else { emu_KeyboardOnDown(keymodifier, key); } } void OnRelease(int key) { keyboardDetected = true; uint8_t keymodifier = keyboard1.getModifiers(); if(keymodifier == 0x40){ // ALTGR Key modifier FR Keyboard switch (key) { #ifdef LAYOUT_FRENCH case 233 : key = '~' ; break; case 34 : key = '#' ; break; case 39 : key = '{' ; break; case 40 : key = '[' ; break; case 45 : key = '|' ; break; case 232 : key = '`' ; break; case 95 : key = 92 ; break; case 231 : key = '^' ; break; case 224 : key = '@' ; break; case 41 : key = ']' ; break; case 61 : key = '}' ; break; #endif #ifdef LAYOUT_FRENCH_BELGIAN case 38 : key = '|' ; break; //1 case 233 : key = '@' ; break; //2 case 34 : key = '#' ; break; //3 case 167 : key = '^' ; break; //6 case 231 : key = '{' ; break; //9 case 224 : key = '}' ; break; //0 case 36 : key = ']' ; break; //$ case 61 : key = '~' ; break; //= #endif } } if (menuActive()) { switch (key) { case 217: usbnavpad &= ~MASK_JOY2_DOWN; break; case 218: usbnavpad &= ~MASK_JOY2_UP; break; case 216: usbnavpad &= ~MASK_JOY2_LEFT; break; case 215: usbnavpad &= ~MASK_JOY2_RIGHT; break; case 10: usbnavpad &= ~MASK_JOY2_BTN; break; case 32: usbnavpad &= ~MASK_KEY_USER1; break; case 9: usbnavpad &= ~MASK_KEY_USER2; break; } } else { emu_KeyboardOnUp(keymodifier, key); } } #endif int emu_MouseDetected(void) { return (mouseDetected?1:0); } int emu_KeyboardDetected(void) { return (keyboardDetected?1:0); } #ifdef HAS_USBKEY static unsigned char midiBuffer[16]; static unsigned char midiLastCmd=0; static int midiDataCnt=0; static int midiCmdNbParam=0; #endif void emu_MidiOnDataReceived(unsigned char value) { #ifdef HAS_USBKEY //Serial.println(value, HEX); //10000000 = 128 = note off //10010000 = 144 = note on //10100000 = 160 = aftertouch //10110000 = 176 = continuous controller //11000000 = 192 = patch change //11010000 = 208 = channel pressure //11100000 = 224 = pitch bend //11110000 = 240 = non-musical commands if (value >= 128) { midiDataCnt = 0; midiLastCmd = value; switch (value & 0xF0) { case 128: // 0x80 midiCmdNbParam = 2; //Serial.print("note off: "); //Serial.println(value&0xf); break; case 144: //0x90 midiCmdNbParam = 2; //Serial.print("note on: "); //Serial.println(value&0xf); break; case 160: //0xA0 midiCmdNbParam = 2; //Serial.print("aftertouch: "); // rare //Serial.println(value&0xf); break; case 176: //0xB0 midiCmdNbParam = 2; //Serial.print("continuous controller: "); //Serial.println(value&0xf); break; case 192: //0xC0 midiCmdNbParam = 1; //Serial.print("patch change: "); //some //Serial.println(value&0xf); break; case 208: //0xD0 midiCmdNbParam = 1; Serial.print("channel pressure: "); Serial.println(value&0xf); break; case 224: //0xE0 midiCmdNbParam = 2; //Serial.print("pitch bend: "); //Serial.println(value&0xf); break; case 240: //0xF0 // non-musical commands switch (value) { case 0xF0: //Serial.println("NI: System Exclusive"); break; case 0xF1: //Serial.println("NI: System Common - MIDI Time Code Quarter Frame"); break; case 0xF2: midiCmdNbParam = 2; break; case 0xF3: //Serial.println("NI: System Common - Song Select"); break; case 0xF6: //Serial.println("NI: System Common - Tune Request"); break; case 0xF8: //Serial.println("System Real Time - Timing Clock"); midi1.sendRealTime(value, 0); break; case 0xFA: //Serial.println("System Real Time - Start"); midi1.sendRealTime(value, 0); break; case 0xFB: //Serial.println("System Real Time - Continue"); midi1.sendRealTime(value, 0); break; case 0xFC: //Serial.println("System Real Time - Stop"); midi1.sendRealTime(value, 0); break; case 0xFE: //Serial.println("System Real Time - Active Sensing"); midi1.sendRealTime(value, 0); break; case 0xFF: //Serial.println("System Real Time - System Reset"); midi1.sendRealTime(value, 0); break; } //SystemExclusive = 0xF0, // System Exclusive //TimeCodeQuarterFrame = 0xF1, // System Common - MIDI Time Code Quarter Frame //SongPosition = 0xF2, // System Common - Song Position Pointer //SongSelect = 0xF3, // System Common - Song Select //TuneRequest = 0xF6, // System Common - Tune Request //Clock = 0xF8, // System Real Time - Timing Clock //Start = 0xFA, // System Real Time - Start //Continue = 0xFB, // System Real Time - Continue //Stop = 0xFC, // System Real Time - Stop //ActiveSensing = 0xFE, // System Real Time - Active Sensing //SystemReset = 0xFF, // System Real Time - System Reset break; default: Serial.print("??: "); Serial.println(value&0xf); break; } } else { if (midiDataCnt<16) midiBuffer[midiDataCnt++] = value ; if ( (midiLastCmd & 0xF0) == 240) { if (midiLastCmd == 0xF2) { if (midiDataCnt == midiCmdNbParam) { //Serial.println("System Common - Song Position Pointer"); midi1.sendSongPosition(((int)midiBuffer[1]<<7)+(int)midiBuffer[0], 0); } } else { Serial.println(value); } } else if (midiDataCnt == midiCmdNbParam) { unsigned char chan = (midiLastCmd&0xf)+1; //Serial.print("ch "); //Serial.println(chan); switch (midiLastCmd & 0xF0) { case 128: //0x80 //Serial.print("note off: "); midi1.sendNoteOff(midiBuffer[0], midiBuffer[1], chan); break; case 144: //0x90 //Serial.print("note on: "); midi1.sendNoteOn(midiBuffer[0], midiBuffer[1], chan); break; case 160: //0xA0 //Serial.print("aftertouch: "); midi1.sendPolyPressure(midiBuffer[0], midiBuffer[1], chan); break; case 176: //0xB0 //Serial.print("continuous controller: "); midi1.sendControlChange(midiBuffer[0], midiBuffer[1], chan); break; case 192: //0xC0 //Serial.print("patch change: "); midi1.sendProgramChange(midiBuffer[0], chan); break; case 208: //0xD0 //Serial.print("channel pressure: "); midi1.sendAfterTouch(midiBuffer[0], chan); break; case 224: //0xE0 //Serial.print("pitch bend: "); midi1.sendPitchBend((((int)midiBuffer[1]<<7)+(int)midiBuffer[0])-8192, chan); break; default: Serial.print("??: "); break; } } } #endif } static void callibrationInit(void) { callibrationOn=true; menuOn=false; callibrationStep = 0; calMinX=0,calMinY=0,calMaxX=0,calMaxY=0; tft.fillScreenNoDma(RGBVAL16(0xff,0xff,0xff)); tft.drawTextNoDma(0,100, " Callibration process:", RGBVAL16(0x00,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true); tft.drawTextNoDma(0,116, " Hit the red cross at each corner", RGBVAL16(0x00,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true); tft.drawTextNoDma(0,0, "+", RGBVAL16(0xff,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true); prev_zt = 1; } static void readCallibration(void) { char fileBuffer[64]; #ifdef USE_SDFS FIL file; int retval; if( !(f_open(&file, CALIBRATION_FILE, FA_READ)) ) { if( !(f_read (&file, fileBuffer, 64, &retval)) ) { if (retval == 64) { sscanf(fileBuffer,"%d %d %d %d", &calMinX,&calMinY,&calMaxX,&calMaxY); } } f_close(&file); } #else File file = SD.open(CALIBRATION_FILE, O_READ); if (file) { if ( file.read(fileBuffer, 64) ) { sscanf(fileBuffer,"%d %d %d %d", &calMinX,&calMinY,&calMaxX,&calMaxY); } file.close(); Serial.println("Current callibration params:"); Serial.println(calMinX); Serial.println(calMinY); Serial.println(calMaxX); Serial.println(calMaxY); } #endif else { Serial.println("Callibration read error"); } tft.callibrateTouch(calMinX,calMinY,calMaxX,calMaxY); } static void writeCallibration(void) { tft.callibrateTouch(calMinX,calMinY,calMaxX,calMaxY); #ifdef USE_SDFS FIL file; int retval; if( !(f_open(&file, CALIBRATION_FILE, FA_WRITE)) ) { //if( !(f_read (&file, fileBuffer, 64, &retval)) ) { // if (retval == 64) { // sscanf(fileBuffer,"%d %d %d %d", &calMinX,&calMinY,&calMaxX,&calMaxY); // } //} f_close(&file); } #else File file = SD.open(CALIBRATION_FILE, O_WRITE | O_CREAT | O_TRUNC); if (file) { file.print(calMinX); file.print(" "); file.print(calMinY); file.print(" "); file.print(calMaxX); file.print(" "); file.println(calMaxY); file.close(); } #endif else { Serial.println("Callibration write error"); } } bool callibrationActive(void) { return (callibrationOn); } int handleCallibration(uint16_t bClick) { uint16_t xt=0; uint16_t yt=0; uint16_t zt=0; if (tft.isTouching()) { if (prev_zt == 0) { prev_zt = 1; tft.readRaw(&xt,&yt,&zt); if (zt < 1000) { return 0; } switch (callibrationStep) { case 0: callibrationStep++; tft.drawTextNoDma(0,0, " ", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0xff,0xff,0xff), true); tft.drawTextNoDma(TFT_REALWIDTH-8,0, "+", RGBVAL16(0xff,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true); calMinX += xt; calMinY += yt; break; case 1: callibrationStep++; tft.drawTextNoDma(TFT_REALWIDTH-8,0, " ", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0xff,0xff,0xff), true); tft.drawTextNoDma(TFT_REALWIDTH-8,TFT_REALHEIGHT-16, "+", RGBVAL16(0xff,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true); calMaxX += xt; calMinY += yt; break; case 2: callibrationStep++; tft.drawTextNoDma(TFT_REALWIDTH-8,TFT_REALHEIGHT-16, " ", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0xff,0xff,0xff), true); tft.drawTextNoDma(0,TFT_REALHEIGHT-16, "+", RGBVAL16(0xff,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true); calMaxX += xt; calMaxY += yt; break; case 3: tft.fillScreenNoDma(RGBVAL16(0xff,0xff,0xff)); tft.drawTextNoDma(0,100, " Callibration done!", RGBVAL16(0x00,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true); tft.drawTextNoDma(0,116, " (Click center to exit)", RGBVAL16(0xff,0x00,0x00), RGBVAL16(0xff,0xff,0xff), true); callibrationStep++; calMinX += xt; calMaxY += yt; break; case 4: //Serial.println(xt); //Serial.println(yt); if ( (xt > (TFT_REALWIDTH/4)) && (xt < (TFT_REALWIDTH*3)/4) && (yt > (TFT_REALHEIGHT/4)) && (yt < (TFT_REALHEIGHT*3)/4) ) { calMinX /= 2; calMinY /= 2; calMaxX /= 2; calMaxY /= 2; writeCallibration(); toggleMenu(true); } else { callibrationInit(); } break; } delay(100); } } else { prev_zt = 0; } } static File filehandlers[3]; int emu_FileOpenBis(char * filename, int handler) { int retval = 0; char filepath[80]; strcpy(filepath, romspath); strcat(filepath, "/"); strcat(filepath, filename); emu_printf("FileOpen..."); emu_printf(filepath); #ifdef USE_SDFS if( !(f_open(&file, filepath, FA_READ)) ) { #else if ((filehandlers[handler] = SD.open(filepath, O_READ))) { #endif retval = handler; } else { emu_printf("FileOpen failed"); } return (retval); } int emu_FileReadBis(char * buf, int size, int handler) { unsigned char buffer[256]; int remaining = size; int byteread = 0; int retval=0; if (size < 256) { #ifdef USE_SDFS if( !(f_read (&file, buffer, size, &retval)) ) #else retval = filehandlers[handler].read(buffer, size); #endif if (retval>0) { memcpy(buf,buffer,retval); byteread += retval; } } else { while (remaining>0) { #ifdef USE_SDFS if( !(f_read (&file, buffer, 256, &retval)) ) //f_read (&file, buffer, 256, &retval); #else retval = filehandlers[handler].read(buffer, 256); #endif if (retval>0) { //emu_printi(retval); memcpy(buf,buffer,retval); buf += retval; byteread += retval; remaining -= retval; } else { break; } } } return byteread; } int emu_FileSeekBis(int seek, int handler) { #ifdef USE_SDFS f_lseek(&file, seek); #else filehandlers[handler].seek(seek); #endif return (seek); } int emu_FileOpen(char * filename) { int retval = 0; char filepath[80]; strcpy(filepath, romspath); strcat(filepath, "/"); strcat(filepath, filename); emu_printf("FileOpen..."); emu_printf(filepath); #ifdef USE_SDFS if( !(f_open(&file, filepath, FA_READ)) ) { #else if ((file = SD.open(filepath, O_READ))) { #endif retval = 1; } else { emu_printf("FileOpen failed"); } return (retval); } int emu_FileRead(char * buf, int size) { unsigned char buffer[256]; int remaining = size; int byteread = 0; int retval=0; if (size < 256) { #ifdef USE_SDFS if( !(f_read (&file, buffer, size, &retval)) ) #else retval = file.read(buffer, size); #endif if (retval>0) { memcpy(buf,buffer,retval); byteread += retval; } } else { while (remaining>0) { #ifdef USE_SDFS if( !(f_read (&file, buffer, 256, &retval)) ) //f_read (&file, buffer, 256, &retval); #else retval = file.read(buffer, 256); #endif if (retval>0) { //emu_printi(retval); memcpy(buf,buffer,retval); buf += retval; byteread += retval; remaining -= retval; } else { break; } } } return byteread; } int emu_FileSeek(int seek) { #ifdef USE_SDFS f_lseek(&file, seek); #else file.seek(seek); #endif return (seek); } int emu_FileTell(void) { #ifdef USE_SDFS return (f_tell(&file)); #else return (50); #endif } unsigned char emu_FileGetc(void) { unsigned char c; #ifdef USE_SDFS int retval=0; if( !(f_read (&file, &c, 1, &retval)) ) #else int retval = file.read(&c, 1); #endif if (retval != 1) { emu_printf("emu_FileGetc failed"); } return c; } void emu_FileClose(void) { #ifdef USE_SDFS f_close(&file); #else file.close(); #endif } int emu_FileSize(char * filename) { int filesize=0; char filepath[80]; strcpy(filepath, romspath); strcat(filepath, "/"); strcat(filepath, filename); emu_printf("FileSize..."); emu_printf(filepath); #ifdef USE_SDFS FILINFO entry; f_stat(filepath, &entry); filesize = entry.fsize; #else if ((file = SD.open(filepath, O_READ))) { emu_printf("filesize is..."); filesize = file.size(); emu_printf(filesize); file.close(); } #endif return(filesize); } int emu_LoadFile(char * filename, char * buf, int size) { int filesize = 0; char filepath[80]; strcpy(filepath, romspath); strcat(filepath, "/"); strcat(filepath, filename); emu_printf("LoadFile..."); emu_printf(filepath); #ifdef USE_SDFS if( !(f_open(&file, filepath, FA_READ)) ) { filesize = f_size(&file); emu_printf(filesize); if (size >= filesize) { int retval=0; if( (f_read (&file, buf, filesize, &retval)) ) { emu_printf("File read failed"); } } f_close(&file); } #else if ((file = SD.open(filepath, O_READ))) { filesize = file.size(); emu_printf(filesize); if (size >= filesize) { if (emu_FileRead(buf, filesize) != filesize) { emu_printf("File read failed"); } } file.close(); } #endif return(filesize); } int emu_LoadFileSeek(char * filename, char * buf, int size, int seek) { int filesize = 0; char filepath[80]; strcpy(filepath, romspath); strcat(filepath, "/"); strcat(filepath, filename); emu_printf("LoadFileSeek..."); emu_printf(filepath); #ifdef USE_SDFS if( !(f_open(&file, filepath, FA_READ)) ) { f_lseek(&file, seek); emu_printf(size); if (size >= filesize) { int retval=0; if( (!f_read (&file, buf, size, &retval)) ) if (retval != size) { emu_printf("File read failed"); } } f_close(&file); } #else if ((file = SD.open(filepath, O_READ))) { file.seek(seek); emu_printf(size); if (file.read(buf, size) != size) { emu_printf("File read failed"); } file.close(); } #endif return(filesize); } const uint32_t FILE_SIZE_MB = 8; const uint32_t FILE_SIZE = 1000000UL*FILE_SIZE_MB; #ifdef USE_SDFS static FIL tempfile; #else static File tempfile; #endif void emu_FileTempInit(void) { #ifdef USE_SDFS if( (f_open(&tempfile, SDFSDEV "/bench.dat", FA_READ| FA_WRITE )) ) { #else #ifdef USE_SDFAT if (!tempfile.open("/bench.dat", O_RDWR /*| O_CREAT | O_TRUNC*/)) { #else if ((tempfile = SD.open("/bench.dat", O_RDWR))) { #endif #endif Serial.println("psram open failed"); } /* else { uint8_t buf[256]; Serial.println("psram creating"); file = SD.open("/bench.dat", O_RDWR | O_CREAT | O_TRUNC); if (file) { Serial.println("psram opened"); file.truncate(0); if (!file.preAllocate(FILE_SIZE)) { Serial.println("allocate failed"); } for(int i=0;i