1
0
mirror of https://github.com/kalymos/PsNee.git synced 2026-02-27 17:14:06 +00:00

refactor: optimize sector filtering and unify system initialization

- Core logic: Optimized 'isDataSector' using a single 0xD0 bitwise mask for faster 0x41 sector detection.
- Architecture: Moved 'board_detection()' into 'Init()' for a cleaner entry point in 'main()'.
- Settings: Updated 'settings.h' with improved constant definitions and macro organization.
- Performance: Reduced instruction count in the main loop and improved peripheral power management.
This commit is contained in:
kalymos
2026-02-25 21:56:05 +01:00
parent 2cc73133c4
commit 0077acf94f
3 changed files with 113 additions and 54 deletions

View File

@@ -227,28 +227,26 @@
#ifdef ATmega328_168
static inline void optimizePeripherals(void) {
// Configuring Port C (A0-A5) as Digital Inputs
// DDRC at 0 = Input. Ensure that the first 6 bits are 0.
DDRC &= ~0x3F;
// --- Port C & Digital Input Configuration (A0-A5) ---
// 1. Set Port C as inputs (DDRC bits 0-5 to 0)
DDRC &= ~((1<<DDC5)|(1<<DDC4)|(1<<DDC3)|(1<<DDC2)|(1<<DDC1)|(1<<DDC0));
// 2. Enable Digital Input Buffers by clearing DIDR0 (Required for digital PINC reads)
DIDR0 &= ~((1<<ADC5D)|(1<<ADC4D)|(1<<ADC3D)|(1<<ADC2D)|(1<<ADC1D)|(1<<ADC0D));
// Disable the ADC (Analog-to-Digital Converter)
// ADEN at 0 disables the module. PRADC at 1 disables the module's clock.
// --- Analog Modules Shutdown (Power Saving & Noise Reduction) ---
// 1. Disable the ADC module (ADEN = 0)
ADCSRA &= ~(1 << ADEN);
PRR |= (1 << PRADC) | (1 << PRTIM2);
// 2. Disable the Analog Comparator (ACD = 1) to free resources on PD6/PD7
ACSR |= (1 << ACD);
// Configure DIDR0 (Digital Input Disable Register)
// To read digitally via PINC, the bits of DIDR0 MUST be set to 0.
// (0 = Digital Buffer enabled)
DIDR0 &= ~0x3F;
// --- Power Reduction Register (Hard Clock Shut Off) ---
// Stops the clock to internal modules: ADC, Timer 0 (millis), and Timer 2
PRR |= (1 << PRADC) | (1 << PRTIM0) | (1 << PRTIM2);
// Stop Timer 0 (Stops Arduino millis/micros)
// Setting TCCR0B to 0 stops the clock source. Setting TIMSK0 to 0 disables interrupts.
// --- Timer 0 Specific Shutdown ---
// Double security: disconnect clock source and disable interrupts
TCCR0B = 0;
//#define F TIMSK0 = 0;
// Disable the Analog Comparator (Frees up resources on PD6/PD7)
// ACD at 1 = Comparator off.
ACSR |= (1 << ACD);
TIMSK0 = 0;
}
// Define the clock speed for the microcontroller
@@ -322,6 +320,7 @@
#define PIN_AX_INTERRUPT_ENABLE EIMSK |= (1 << INT0) // Enable external interrupt on INT0 (PINB2)
#define PIN_AX_INTERRUPT_DISABLE EIMSK &= ~(1 << INT0) // Disable external interrupt on INT0
#define PIN_AX_INTERRUPT_RISING EICRA |= (1 << ISC01) | (1 << ISC00) // Configure INT0 for rising edge trigger
//#define PIN_AX_INTERRUPT_FALLING (EICRA = (1 << ISC01))
#define PIN_AX_INTERRUPT_FALLING (EICRA = (EICRA & ~(1 << ISC00)) | (1 << ISC01)) // Configure INT0 for falling edge trigger
// Interrupt vectors for external interrupts
@@ -358,6 +357,36 @@
#ifdef ATmega32U4_16U4
static inline void optimizePeripherals(void) {
// --- Digital Input Configuration (A0-A5) ---
// On 32U4, A0-A5 are spread across Port F (F7-F4) and Port D (D4, D7)
// 1. Set all Analog/Digital pins to Input
DDRF &= ~((1<<DDF7)|(1<<DDF6)|(1<<DDF5)|(1<<DDF4)); // A0-A3
DDRD &= ~((1<<DDD4)|(1<<DDD7)); // A4-A5
// 2. Disable Digital Input Buffers (DIDR0/DIDR2)
// On 32U4, DIDR0 and DIDR2 control the digital buffer for ADC pins.
// Setting these bits to 0 ENABLES digital reads (PINF/PIND).
DIDR0 &= ~((1<<ADC7D)|(1<<ADC6D)|(1<<ADC5D)|(1<<ADC4D)); // A0-A3
DIDR2 &= ~((1<<ADC10D)|(1<<ADC8D)); // A4-A5
// --- Analog Modules Shutdown (32U4 specific) ---
// 1. Disable the ADC module
ADCSRA &= ~(1 << ADEN);
// 2. Disable the Analog Comparator
ACSR |= (1 << ACD);
// --- Power Reduction Register (32U4 Hard Clock Shut Off) ---
// PRR0 and PRR1 handle the clocks on 32U4.
// Note: We DO NOT touch PRUSB if we want to keep the Serial/USB alive.
PRR0 |= (1 << PRADC) | (1 << PRTIM0) | (1 << PRTIM1);
PRR1 |= (1 << PRTIM3); // 32U4 has an extra Timer 3
// --- Timer 0 Specific Shutdown ---
TCCR0B = 0;
TIMSK0 = 0;
}
#define F_CPU 16000000L
@@ -449,6 +478,23 @@
#ifdef ATtiny85_45_25
static inline void optimizePeripherals(void) {
// --- Analog Modules Shutdown (ATtiny Specific) ---
// 1. Disable the ADC module
ADCSRA &= ~(1 << ADEN);
// 2. Disable the Analog Comparator
ACSR |= (1 << ACD);
// --- Power Reduction Register (Hard Clock Shut Off) ---
// On ATtiny85, PRR controls Timer 0, Timer 1, USI, and ADC.
// We stop the ADC and Timer 0 clocks.
PRR |= (1 << PRADC) | (1 << PRTIM0);
// --- Timer 0 Specific Shutdown ---
TCCR0B = 0;
TIMSK = 0; // On ATtiny85, it's TIMSK (not TIMSK0)
}
#define DF_CPU 8000000L
#define TIMER_TCNT_CLEAR TCNT0 = 0x00;
#define SET_OCROA_DIV OCR0A = 79; //OCR0A Output Compare Register A,100KHz

View File

@@ -19,11 +19,11 @@
SCPH model number // region code | region
-------------------------------------------------------------------------------------------------*/
#define SCPH_xxxx // | Universal.
//#define SCPH_xxxx // | Universal.
//#define SCPH_xxx1 // NTSC U/C | America.
//#define SCPH_xxx2 // PAL | Europ.
//#define SCPH_xxx3 // NTSC J | Asia.
//#define SCPH_5903 // NTSC J | Asia VCD.
#define SCPH_5903 // NTSC J | Asia VCD.
// Models that require a BIOS patch.
@@ -127,25 +127,29 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
//Flag initializing for automatic console generation selection 0 = old, 1 = pu-22 end ++
uint8_t wfck_mode = 0;
volatile uint8_t wfck_mode = 0;
// --- Prototypes (Forward declarations) ---
// These tell the compiler that the functions exist later in the code.
//#ifdef SCPH_5903
void logic_SCPH_5903(uint8_t isDataSector);
//#else
void logic_Standard(uint8_t isDataSector);
//#endif
// Function pointer type definition for the console detection logic.
// This allows switching between 'Standard' and 'SCPH-5903' heuristics dynamically.
typedef void (*ConsoleLogicPtr)(uint8_t isDataSector);
#ifdef SCPH_5903
void logic_SCPH_5903(uint8_t isDataSector);
volatile ConsoleLogicPtr currentLogic = logic_SCPH_5903;
#else
void logic_Standard(uint8_t isDataSector);
volatile ConsoleLogicPtr currentLogic = logic_Standard;
#endif
// Global pointer holding the currently active logic function.
// Using a function pointer eliminates the need for repetitive 'if/else' checks in the main loop.
volatile ConsoleLogicPtr currentLogic = logic_Standard;
//volatile ConsoleLogicPtr currentLogic = logic_Standard;
// Variables de contrôle globales
uint8_t scbuf[12] = { 0 };
@@ -204,6 +208,10 @@ void board_detection() {
// Low count implies a static signal (Older boards)
wfck_mode = 0; // Target: PU-7 to PU-20
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
Debug_Log(wfck_mode);
#endif
}
@@ -233,6 +241,10 @@ void captureSubQ(void) {
scbuf[scpos++] = bitbuf;
} while (scpos < 12);
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
Debug_Scbuf(scbuf);
#endif
}
/**************************************************************************************
@@ -405,6 +417,10 @@ void performInjectionSequence(uint8_t injectSCEx) {
#ifdef LED_RUN
PIN_LED_OFF;
#endif
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
Debug_Inject();
#endif
}
void Init() {
@@ -453,23 +469,21 @@ void Init() {
#elif defined(PSNEE_DEBUG_SERIAL_MONITOR) && !defined(ATtiny85_45_25)
Serial.begin(500000); // 60 bytes in 12ms (expected data: ~26 bytes / 12ms) // update: this is actually quicker
#endif
board_detection();
}
int main() {
Init();
// #ifdef SCPH_5903
// currentLogic = logic_SCPH_5903;
// #else
// currentLogic = logic_Standard;
// #endif
#ifdef SCPH_5903
currentLogic = logic_SCPH_5903;
#else
currentLogic = logic_Standard;
#endif
board_detection();
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
Debug_Log(lows, wfck_mode);
#endif
while (1) {
@@ -477,10 +491,6 @@ int main() {
in cases where the MCU loops too quickly and picks up the laster SUBQ trailing end*/
captureSubQ();
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
Debug_Scbuf(scbuf);
#endif
/*-------------------------------------------------------------------------------
Check if read head is in wobble area
We only want to unlock game discs (0x41) and only if the read head is in the outer TOC area.
@@ -490,19 +500,22 @@ int main() {
While the laser lens moves to correct for the error, they can pick up a few TOC sectors.
-------------------------------------------------------------------------------*/
//This variable initialization macro is to replace (0x41) with a filter that will check that only the three most significant bits are correct. 0x001xxxxx
uint8_t isDataSector = (((scbuf[0] & 0x40) == 0x40) && (((scbuf[0] & 0x10) == 0) && ((scbuf[0] & 0x80) == 0)));
//This variable initialization macro is to replace (0x41) with a filter that will check that only the three most significant bits are correct. 0x001xxxxx
//uint8_t isDataSector = (((scbuf[0] & 0x40) == 0x40) &&
// (((scbuf[0] & 0x10) == 0) &&
// ((scbuf[0] & 0x80) == 0)));
// Optimized Sector Filtering:
// Masking bits 7, 6, and 4 simultaneously using 0xD0 (binary 11010000).
// This verifies that the "Data/TOC" bit (0x40) is SET, while bits 7 and 4 are CLEARED.
// Equivalent to: (bit7 == 0 && bit6 == 1 && bit4 == 0).
uint8_t isDataSector = ((scbuf[0] & 0xD0) == 0x40);
// Execute selected logic through function pointer
currentLogic(isDataSector);
if (hysteresis >= HYSTERESIS_MAX) {
performInjectionSequence(INJECT_SCEx);
}
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
Debug_Inject();
#endif
// Execute selected logic through function pointer
currentLogic(isDataSector);
if (hysteresis >= HYSTERESIS_MAX) {
performInjectionSequence(INJECT_SCEx);
}
}
}

View File

@@ -144,13 +144,13 @@
#if defined(PSNEE_DEBUG_SERIAL_MONITOR)
void Debug_Log (uint16_t Lows, int Wfck_mode){ //Information about the MCU, and old or late console mode.
void Debug_Log (int Wfck_mode){ //Information about the MCU, and old or late console mode.
#if defined(ATtiny85_45_25)
mySerial.print("m "); mySerial.println(Wfck_mode);
#elif !defined(ATtiny85_45_25)
Serial.print(" MCU frequency: "); Serial.print(F_CPU); Serial.println(" Hz");
Serial.print(" lows: "); Serial.println(Lows);
//Serial.print(" lows: "); Serial.println(Lows);
Serial.print(" wfck_mode: "); Serial.println(Wfck_mode);
Serial.print(" region: "); Serial.print(region[0]); Serial.print(region[1]); Serial.println(region[2]);
#endif