From 33c8a9b8a02a9811d2330817c33af3d91eadbd41 Mon Sep 17 00:00:00 2001 From: jmlee337 Date: Wed, 28 Feb 2024 17:15:07 +0900 Subject: [PATCH] Revise ReplaysLED 'Yes' implementation LED will stay lit while there is nothing to write or writing is making progress. Because the timeout is 1s, spurious f_open or f_write errors won't cause the LED to turn off as long as they start succeeding again shortly. But if writing stalls for more than 1s while there is data to write, the LED will go off --- kernel/SlippiFileWriter.c | 93 +++++++++++++++------------------------ kernel/SlippiFileWriter.h | 1 + kernel/main.c | 12 +++-- 3 files changed, 46 insertions(+), 60 deletions(-) diff --git a/kernel/SlippiFileWriter.c b/kernel/SlippiFileWriter.c index f1fa0e3e6..cc7e57313 100644 --- a/kernel/SlippiFileWriter.c +++ b/kernel/SlippiFileWriter.c @@ -14,7 +14,7 @@ // double that, making our read buffer 10000 bytes #define READ_BUF_SIZE 10000 #define THREAD_CYCLE_TIME_MS 100 -#define THREAD_ERROR_TIME_MS 1000 +#define THREAD_ERROR_TIME_MS 2000 #define LED_FLASH_TIME_MS 1000 #define FOOTER_BUFFER_LENGTH 200 @@ -63,11 +63,30 @@ void SlippiFileWriterInit() thread_continue(Slippi_Thread); } +void SlippiFileWriterUpdateRegisters() +{ + if (driveTimerSet && TimerDiffMs(driveTimer) >= LED_FLASH_TIME_MS) + { + clear32(HW_GPIO_OUT, GPIO_SLOT_LED); + driveTimerSet = false; + } +} + void SlippiFileWriterShutdown() { thread_cancel(Slippi_Thread, 0); } +void flashLED() +{ + driveTimer = read32(HW_TIMER); + if (!driveTimerSet) + { + set32(HW_GPIO_OUT, GPIO_SLOT_LED); + driveTimerSet = true; + } +} + //we cant include time.h so hardcode what we need struct tm { @@ -173,15 +192,8 @@ void completeFile(FIL *file, SlpGameReader *reader, u32 writtenByteCount) f_lseek(file, 11); FRESULT fileWriteResult = f_write(file, &writtenByteCount, 4, &wrote); - if ((replaysLED == 0 && fileWriteResult != FR_OK) || (replaysLED == 1 && fileWriteResult == FR_OK)) - { - if (replaysLED == 0) - clear32(HW_GPIO_OUT, GPIO_SLOT_LED); - else - set32(HW_GPIO_OUT, GPIO_SLOT_LED); - driveTimer = read32(HW_TIMER); - driveTimerSet = true; - } + if (replaysLED == 1 && fileWriteResult == FR_OK) + flashLED(); f_sync(file); } @@ -202,8 +214,6 @@ static u32 SlippiHandlerThread(void *arg) bool hasFile = false; bool mounted = true; const bool use_usb = ConfigGetUseUSB() != 1; - if (replaysLED == 0) - set32(HW_GPIO_OUT, GPIO_SLOT_LED); while (1) { @@ -215,11 +225,7 @@ static u32 SlippiHandlerThread(void *arg) if (!USBStorage_IsInserted_SlippiThread()) { if (mounted) - { f_mount_char(NULL, "usb:", 1); - if (replaysLED == 0) - clear32(HW_GPIO_OUT, GPIO_SLOT_LED); - } failedToMount = false; hasFile = false; @@ -236,15 +242,8 @@ static u32 SlippiHandlerThread(void *arg) mounted = true; - if (replaysLED < 2) - { - set32(HW_GPIO_OUT, GPIO_SLOT_LED); - if (replaysLED == 1) - { - driveTimer = read32(HW_TIMER); // flash drive LED on successful insertion. - driveTimerSet = true; - } - } + if (replaysLED == 1) + flashLED(); } else { @@ -256,32 +255,14 @@ static u32 SlippiHandlerThread(void *arg) continue; } - if (driveTimerSet && TimerDiffMs(driveTimer) >= LED_FLASH_TIME_MS) - { - if (mounted && replaysLED == 0) - set32(HW_GPIO_OUT, GPIO_SLOT_LED); - else if (replaysLED == 1) - clear32(HW_GPIO_OUT, GPIO_SLOT_LED); - - driveTimerSet = false; - } - // Read from memory and write to file SlpMemError err = SlippiMemoryRead(&reader, readBuf, READ_BUF_SIZE, memReadPos); if (err) { if (err == SLP_READ_OVERFLOW) - { memReadPos = SlippiRestoreReadPos(); - if (replaysLED == 0) - { - clear32(HW_GPIO_OUT, GPIO_SLOT_LED); - driveTimer = read32(HW_TIMER); // flash LED off because this means a replay has been lost/corrupted. - driveTimerSet = true; - } - } - mdelay(THREAD_ERROR_TIME_MS); + mdelay(LED_FLASH_TIME_MS + 1000); // we always want LED visibly off if this happens // For specific errors, bytes will still be read. Not continueing to deal with those } @@ -299,16 +280,12 @@ static u32 SlippiHandlerThread(void *arg) FRESULT fileOpenResult = f_open_secondary_drive(¤tFile, fileName, FA_CREATE_ALWAYS | FA_WRITE | FA_READ); if (fileOpenResult != FR_OK) { - if (replaysLED == 0) - { - clear32(HW_GPIO_OUT, GPIO_SLOT_LED); - driveTimer = read32(HW_TIMER); // flash LED off on fs error. - driveTimerSet = true; - } dbgprintf("Slippi: failed to open file: %s, errno: %d\r\n", fileName, fileOpenResult); - mdelay(THREAD_ERROR_TIME_MS); + mdelay(LED_FLASH_TIME_MS - THREAD_CYCLE_TIME_MS - 100); // short enough so we can recover with running out of LED time. continue; } + else if (replaysLED == 0) + flashLED(); hasFile = true; writtenByteCount = 0; @@ -316,7 +293,11 @@ static u32 SlippiHandlerThread(void *arg) } if (reader.lastReadResult.bytesRead == 0) + { + if (replaysLED == 0) + flashLED(); continue; + } // dbgprintf("Bytes read: %d\r\n", reader.lastReadResult.bytesRead); @@ -324,18 +305,16 @@ static u32 SlippiHandlerThread(void *arg) { // we can reach this state if the user inserts a usb device during a game. // skip over and don't write anything until we see the start of a new game + if (replaysLED == 0) + flashLED(); memReadPos += reader.lastReadResult.bytesRead; continue; } UINT wrote; FRESULT writeResult = f_write(¤tFile, readBuf, reader.lastReadResult.bytesRead, &wrote); - if (replaysLED == 0 && writeResult != FR_OK) - { - clear32(HW_GPIO_OUT, GPIO_SLOT_LED); - driveTimer = read32(HW_TIMER); // flash LED off on fs error. - driveTimerSet = true; - } + if (replaysLED == 0 && writeResult == FR_OK && wrote > 0) + flashLED(); f_sync(¤tFile); if (wrote == 0) diff --git a/kernel/SlippiFileWriter.h b/kernel/SlippiFileWriter.h index 353d6f63b..da6ed28cc 100644 --- a/kernel/SlippiFileWriter.h +++ b/kernel/SlippiFileWriter.h @@ -4,6 +4,7 @@ #include "global.h" void SlippiFileWriterInit(); +void SlippiFileWriterUpdateRegisters(); void SlippiFileWriterShutdown(); #endif diff --git a/kernel/main.c b/kernel/main.c index e22850164..dee642e8b 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -587,9 +587,15 @@ int _main( int argc, char *argv[] ) BTUpdateRegisters(); HIDUpdateRegisters(0); - if (SlippiFileWrite == 1 && !UseUSB) - // Must consistently call to enable USB hotswap - USBStorage_UpdateRegisters_MainThread(); + if (SlippiFileWrite == 1) + { + SlippiFileWriterUpdateRegisters(); + if (!UseUSB) + { + // Must consistently call to enable USB hotswap + USBStorage_UpdateRegisters_MainThread(); + } + } // Native SI is always enabled in Slippi Nintendont //if (DisableSIPatch == 0) SIUpdateRegisters();