MCUME/MCUME_teensy/teensy800/emuapi.cpp

1418 wiersze
32 KiB
C++

#define KEYMAP_PRESENT 1
extern "C" {
#include "emuapi.h"
#include "iopins.h"
}
#include "tft_t_dma.h"
#include "logo.h"
#include "bmpjoy.h"
#include "bmpvbar.h"
#ifdef OLD_LAYOUT
#include "bmpvga.h"
#include "bmptft.h"
#endif
#ifdef HAS_I2CKBD
#include <Wire.h>
#endif
#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 <SD.h>
#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 32
#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,0x20)
#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 files[MAX_FILES][MAX_FILENAME_SIZE];
static bool menuRedraw=true;
static int16_t calMinX=-1,calMinY=-1,calMaxX=-1,calMaxY=-1;
static bool i2cKeyboardPresent = false;
//const uint16_t deflogo[] = {
// 0x0000,0x0000
//};
//static const uint16_t * logo = deflogo;
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);
}
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 ");
emu_printf(size);
}
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
#if INVY
#ifdef PIN_JOY1_1
if ( digitalRead(PIN_JOY1_1) == LOW ) j2 |= MASK_JOY2_DOWN;
#endif
#ifdef PIN_JOY1_2
if ( digitalRead(PIN_JOY1_2) == LOW ) j2 |= MASK_JOY2_UP;
#endif
#else
#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
#endif
#if INVX
#ifdef PIN_JOY1_3
if ( digitalRead(PIN_JOY1_3) == LOW ) j2 |= MASK_JOY2_LEFT;
#endif
#ifdef PIN_JOY1_4
if ( digitalRead(PIN_JOY1_4) == LOW ) j2 |= MASK_JOY2_RIGHT;
#endif
#else
#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
#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);
}
#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<sizeof(i2ckeys); i++) {
if (match == i2ckeys[i]) {
//Serial.println((int)keys[i]);
return (keys[i]);
}
}
}
}
#endif
return(retval);
}
void emu_InitJoysticks(void) {
// Second Joystick
#ifdef PIN_JOY1_1
pinMode(PIN_JOY1_1, INPUT_PULLUP);
#endif
#ifdef PIN_JOY1_2
pinMode(PIN_JOY1_2, INPUT_PULLUP);
#endif
#ifdef PIN_JOY1_3
pinMode(PIN_JOY1_3, INPUT_PULLUP);
#endif
#ifdef PIN_JOY1_4
pinMode(PIN_JOY1_4, INPUT_PULLUP);
#endif
#ifdef PIN_JOY1_BTN
pinMode(PIN_JOY1_BTN, INPUT_PULLUP);
#endif
#ifdef PIN_KEY_USER1
pinMode(PIN_KEY_USER1, INPUT_PULLUP);
#endif
#ifdef PIN_KEY_USER2
pinMode(PIN_KEY_USER2, INPUT_PULLUP);
#endif
#ifdef PIN_KEY_USER3
pinMode(PIN_KEY_USER3, INPUT_PULLUP);
#endif
#ifdef PIN_KEY_USER4
pinMode(PIN_KEY_USER4, INPUT_PULLUP);
#endif
#ifdef PIN_JOY2_BTN
pinMode(PIN_JOY2_BTN, INPUT_PULLUP);
#endif
analogReadResolution(12);
xRef=0; yRef=0;
for (int i=0; i<10; i++) {
xRef += analogRead(PIN_JOY2_A1X);
yRef += analogRead(PIN_JOY2_A2Y);
delay(20);
}
#if INVX
xRef = 4095 -xRef/10;
#else
xRef /= 10;
#endif
#if INVY
yRef = 4095 -yRef/10;
#else
yRef /= 10;
#endif
}
static bool vkbKeepOn = false;
static bool vkbActive = false;
static bool vkeyRefresh=false;
static bool exitVkbd = false;
static uint8_t keyPressCount=0;
bool virtualkeyboardIsActive(void) {
return (vkbActive);
}
void toggleVirtualkeyboard(bool keepOn) {
if (keepOn) {
tft.drawSpriteNoDma(0,0,(uint16_t*)logo);
//prev_zt = 0;
vkbKeepOn = true;
vkbActive = true;
exitVkbd = false;
}
else {
vkbKeepOn = false;
if ( (vkbActive) /*|| (exitVkbd)*/ ) {
tft.fillScreenNoDma( RGBVAL16(0x00,0x00,0x00) );
tft.startDMA();
//prev_zt = 0;
vkbActive = false;
exitVkbd = false;
}
else {
tft.stopDMA();
tft.drawSpriteNoDma(0,0,(uint16_t*)logo);
//prev_zt = 0;
vkbActive = true;
exitVkbd = false;
}
}
}
void handleVirtualkeyboard() {
int rx=0,ry=0,rw=0,rh=0;
if (keyPressCount == 0) {
keypadval = 0;
} else {
keyPressCount--;
}
if ( (!virtualkeyboardIsActive()) && (tft.isTouching()) && (!keyPressCount) ) {
toggleVirtualkeyboard(false);
return;
}
if ( ( (vkbKeepOn) || (virtualkeyboardIsActive()) ) ) {
char c = captureTouchZone(keysw, keys, &rx,&ry,&rw,&rh);
if (c) {
tft.drawRectNoDma( rx,ry,rw,rh, KEYBOARD_HIT_COLOR );
if ( (c >=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,(uint16_t*)logo, rx, ry, rw, rh);
}
if ( (exitVkbd) && (vkbActive) ) {
if (!vkbKeepOn) {
toggleVirtualkeyboard(false);
}
else {
toggleVirtualkeyboard(true);
}
}
}
int emu_setKeymap(int index) {
if (index) {
}
else {
}
}
static int readNbFiles(void) {
int totalFiles = 0;
#ifdef USE_SDFS
DIR dir;
FILINFO entry;
f_opendir(&dir, romspath);
while ( (true) && (totalFiles<MAX_FILES) ) {
f_readdir(&dir, &entry);
if (!entry.fname[0]) {
// no more files
break;
}
char * filename = entry.fname;
Serial.println(filename);
if ( !(entry.fattrib & AM_DIR) ) {
strncpy(&files[totalFiles][0], filename, MAX_FILENAME_SIZE-1);
totalFiles++;
}
else {
if ( (strcmp(filename,".")) && (strcmp(filename,"..")) ) {
strncpy(&files[totalFiles][0], filename, MAX_FILENAME_SIZE-1);
totalFiles++;
}
}
}
f_closedir(&dir);
#else
File entry;
file = SD.open(romspath);
while ( (true) && (totalFiles<MAX_FILES) ) {
entry = file.openNextFile();
if (! entry) {
// no more files
break;
}
#ifdef USE_SDFAT
char filename[MAX_FILENAME_SIZE];
entry.getName(&filename[0], MAX_FILENAME_SIZE);
#else
char * filename = entry.name();
#endif
Serial.println(filename);
if (!entry.isDirectory()) {
strncpy(&files[totalFiles][0], filename, MAX_FILENAME_SIZE-1);
totalFiles++;
}
else {
if ( (strcmp(filename,".")) && (strcmp(filename,"..")) ) {
strncpy(&files[totalFiles][0], filename, MAX_FILENAME_SIZE-1);
totalFiles++;
}
}
entry.close();
}
file.close();
#endif
return totalFiles;
}
void backgroundMenu(void) {
menuRedraw=true;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,0, TITLE, RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);
tft.drawSpriteNoDma(MENU_VBAR_XOFFSET,MENU_VBAR_YOFFSET,(uint16_t*)bmpvbar);
#ifdef OLD_LAYOUT
tft.drawSpriteNoDma(MENU_TFT_XOFFSET,MENU_TFT_YOFFSET,(uint16_t*)bmptft);
tft.drawSpriteNoDma(MENU_VGA_XOFFSET,MENU_VGA_YOFFSET,(uint16_t*)bmpvga);
#endif
}
int handleMenu(uint16_t bClick)
{
int action = ACTION_NONE;
char newpath[80];
strcpy(newpath, romspath);
strcat(newpath, "/");
strcat(newpath, selection);
int rx=0,ry=0,rw=0,rh=0;
char c = 0; //captureTouchZone(menutouchareas, menutouchactions, &rx,&ry,&rw,&rh);
if ( (bClick & MASK_JOY2_BTN) || (c == MKEY_TFT) ) {
emu_printf(newpath);
#ifdef USE_SDFS
FILINFO entry;
f_stat(newpath, &entry);
if ( (entry.fattrib & AM_DIR) ) {
#else
File file = SD.open(newpath);
if (file.isDirectory()) {
#endif
strcpy(romspath,newpath);
curFile = 0;
nbFiles = readNbFiles();
}
else {
action = ACTION_RUNTFT;
}
menuRedraw=true;
}
else if ( (bClick & MASK_KEY_USER1) || (c == MKEY_VGA) ) {
menuRedraw=true;
action = ACTION_RUNVGA;
}
else if ( (c >= 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) {
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) {
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;
}
}
else if ( (bClick & MASK_KEY_USER2) || (c == MKEY_JOY) ) {
emu_SwapJoysticks(0);
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<MAX_MENULINES) {
if (fileIndex>=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, 0xFFFF, 0x0000, true);
}
}
i++;
}
fileIndex++;
}
tft.drawSpriteNoDma(0,MENU_JOYS_YOFFSET,(uint16_t*)bmpjoy);
tft.drawTextNoDma(48,MENU_JOYS_YOFFSET+8, (emu_SwapJoysticks(1)?(char*)"SWAP=1":(char*)"SWAP=0"), RGBVAL16(0x00,0xff,0xff), RGBVAL16(0xff,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);
}
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;
}
}
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;
}
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_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
}
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<FILE_SIZE/256;i++){
file.write(buf, 256);
Serial.println(i);
}
Serial.println("psram created");
}
//file.close();
}
*/
#ifdef USE_SDFS
FILINFO entry;
f_stat(SDFSDEV "/bench.dat", &entry);
int fs=entry.fsize;
#else
int fs=tempfile.size();
#endif
Serial.print("psram size is ");
Serial.println(fs);
}
void emu_FileTempRead(int addr, unsigned char * val, int n)
{
#ifdef USE_SDFS
f_lseek(&file, addr);
int retval=0;
f_read (&file, val, n, &retval);
#else
tempfile.seek(addr);
tempfile.read(val, n);
#endif
}
void emu_FileTempWrite(int addr, unsigned char val)
{
uint8_t v=val;
#ifdef USE_SDFS
f_lseek(&tempfile, addr);
int retval=0;
f_write (&tempfile, &v, 1, &retval);
#else
tempfile.seek(addr);
tempfile.write(&v, 1);
#endif
}
void emu_init(void)
{
Serial.begin(115200);
#ifdef USE_SDFS
strcpy(romspath,SDFSDEV);
strcat(romspath,ROMSDIR);
FRESULT rc;
if((rc = f_mount (&fatfs, romspath, 1))) {
emu_printf("Fail mounting SDFS");
}
else {
rc = f_chdrive(ROMSDIR);
}
#else
#ifdef USE_SDFAT
while (!SD.begin(SD_CONFIG))
#else
while (!SD.begin(SD_CS))
#endif
{
Serial.println("SD begin failed, retrying...");
delay(1000);
}
strcpy(romspath,ROMSDIR);
#endif
nbFiles = readNbFiles();
Serial.print("SD initialized, files found: ");
Serial.println(nbFiles);
emu_InitJoysticks();
#ifdef SWAP_JOYSTICK
joySwapped = true;
#else
joySwapped = false;
#endif
readCallibration();
if ((tft.isTouching()) || (emu_ReadKeys() & MASK_JOY2_BTN) ) {
callibrationInit();
}
else
{
toggleMenu(true);
}
#ifdef HAS_I2CKBD
byte msg[7]={0,0,0,0,0,0,0};
Wire.begin(); // join i2c bus SDA2/SCL2
Wire.requestFrom(8, 7); // request 7 bytes from slave device #8
int i = 0;
while (Wire.available() && (i<7) ) { // slave may send less than requested
byte b = Wire.read(); // receive a byte
msg[i++] = b;
}
/*
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);
*/
if ( (msg[0] == 0xff) && (msg[1] == 0xff) &&
(msg[2] == 0xff) && (msg[3] == 0xff) &&
(msg[4] == 0xff) && (msg[5] == 0xff) && (msg[6] == 0xff)) {
i2cKeyboardPresent = true;
Serial.println("i2C keyboard found");
}
#endif
}