// ***************************************************************************************************************** // Configuration for different microcontrollers (MCU) to ensure compatibility with the code: // - Defines the clock speed, timers, and interrupts for each MCU. // - Configures I/O pins for data, clocks, and switches according to the requirements. // - Enables pull-up resistors on input pins where needed. // - Manages external interrupts and LED outputs for system feedback. // - Ensures the setup is compatible with various microcontroller models (e.g., ATmega328, ATtiny series, etc.) // ***************************************************************************************************************** //****************************************************************************************************************** // Configuring the clock speed and associated registers. The formula for calculating // the clock frequency is F_CPU / (TCCR0B |= (1< #include #include #include #include #include // Main pin configuration // Define the main pins as inputs #define PIN_DATA_INPUT DDRB &= ~(1 << DDB0) // Set DDRB register to configure PINB0 as input #define PIN_WFCK_INPUT DDRB &= ~(1 << DDB1) // Set DDRB register to configure PINB1 as input #define PIN_SQCK_INPUT DDRD &= ~(1 << DDD6) // Set DDRD register to configure PINB6 as input #define PIN_SUBQ_INPUT DDRD &= ~(1 << DDD7) // Set DDRD register to configure PINB7 as input // Configure lines as outputs (for injection/override) #define PIN_DATA_OUTPUT DDRB |= (1 << DDB0) // Set DDRB register to configure PINB0 as output #define PIN_WFCK_OUTPUT DDRB |= (1 << DDB1) // Set DDRB register to configure PINB1 as output // Bus line state control (Set High / Clear Low) #define PIN_DATA_SET PORTB |= (1 << PB0) // Set PORTB register to make PINB0 high (enable pull-up)) #define PIN_DATA_CLEAR PORTB &= ~(1 << PB0) // Set PORTB register to make PINB0 low #define PIN_WFCK_CLEAR PORTB &= ~(1 << PB1) // Set PORTB register to make PINB1 low // Direct Register Reading (High-speed polling) #define PIN_SQCK_READ (!!(PIND & (1 << PIND6))) // Check if the value of PIND6 is high (1) #define PIN_SUBQ_READ (!!(PIND & (1 << PIND7))) // Check if the value of PIND7 is high (1) #define PIN_WFCK_READ (!!(PINB & (1 << PINB1))) // Check if the value of PINB1 is high (1) // --- Status Indication (LED) --- #ifdef LED_RUN #define PIN_LED_OUTPUT DDRB |= (1 << DDB5) // Configure PINB5 as output (for LED) #define PIN_LED_ON PORTB |= (1 << PB5) // Set PINB5 high (turn on LED) #define PIN_LED_OFF PORTB &= ~(1 << PB5) // Set PINB5 low (turn off LED) #endif // --- BIOS Patching Configuration --- #if defined(SCPH_102) || \ defined(SCPH_100) || \ defined(SCPH_7000_7500_9000) || \ defined(SCPH_7000) || \ defined(SCPH_3500_5000_5500) || \ defined(SCPH_3000) || \ defined(SCPH_1000) // Address (AX) and Data (DX) lines for BIOS override #define PIN_DX_INPUT DDRD &= ~(1 << DDD4) #define PIN_DX_OUTPUT DDRD |= (1 << DDD4) #define PIN_DX_SET PORTD |= (1 << PD4) #define PIN_DX_CLEAR PORTD &= ~(1 << PD4) #define PIN_AX_INPUT DDRD &= ~(1 << DDD2) #define WAIT_AX_RISING (!(PIND & (1 << PIND2))) // Wait for pulse start (Blocking until Rising Edge) #define WAIT_AX_FALLING (PIND & (1 << PIND2)) // Wait for pulse end (Blocking until Falling Edge) #define PIN_AX_READ (!!(PIND & (1 << PIND2))) // Hardware Interrupt (INT0) for AX pulse counting #define PIN_AX_INTERRUPT_ENABLE EIMSK |= (1< #include #include #include #include #include // --- Main Bus Interface (CD-ROM Controller) --- // Define the main pins as inputs #define PIN_DATA_INPUT DDRB &= ~(1 << DDB4) // DATA line (PB4) #define PIN_WFCK_INPUT DDRB &= ~(1 << DDB5) // WFCK / GATE line (PB5) #define PIN_SQCK_INPUT DDRD &= ~(1 << DDD7) // SQCK Clock (PD7) #define PIN_SUBQ_INPUT DDRE &= ~(1 << DDE6) // SUBQ Data (PE6) // Configure lines as outputs (for injection/override) #define PIN_DATA_OUTPUT DDRB |= (1 << DDB4) #define PIN_WFCK_OUTPUT DDRB |= (1 << DDB5) // Bus line state control (Set High / Clear Low) #define PIN_DATA_SET PORTB |= (1 << PB4) // Enable pull-up or drive HIGH #define PIN_DATA_CLEAR PORTB &= ~(1 << PB4) // Drive line LOW #define PIN_WFCK_CLEAR PORTB &= ~(1 << PB5) // Drive line LOW // Direct Register Reading (High-speed polling) #define PIN_SQCK_READ (!!(PIND & (1 << PIND7))) #define PIN_SUBQ_READ (!!(PINE & (1 << PINE6))) #define PIN_WFCK_READ (!!(PINB & (1 << PINB5))) // --- Status Indication (LED) --- #ifdef LED_RUN #define PIN_LED_OUTPUT DDRB |= (1 << DDB6) // LED on PB6 #define PIN_LED_ON PORTB |= (1 << PB6) #define PIN_LED_OFF PORTB &= ~(1 << PB6) #endif // --- BIOS Patching Configuration (32U4 Mapping) --- #if defined(SCPH_102) || \ defined(SCPH_100) || \ defined(SCPH_7000_7500_9000) || \ defined(SCPH_3500_5000_5500) || \ defined(SCPH_3000) || \ defined(SCPH_1000) // Address (AX) and Data (DX) lines for BIOS override #define PIN_DX_INPUT DDRD &= ~(1 << DDD4) // DX on PD4 #define PIN_DX_OUTPUT DDRD |= (1 << DDD4) #define PIN_DX_SET PORTD |= (1 << PD4) #define PIN_DX_CLEAR PORTD &= ~(1 << PD4) #define PIN_AX_INPUT DDRD &= ~(1 << DDD1) // AX on PD1 (INT1) #define WAIT_AX_RISING (!(PIND & (1 << PIND1))) // Wait for pulse start #define WAIT_AX_FALLING (PIND & (1 << PIND1)) // Wait for pulse end #define PIN_AX_READ (PIND & (1 << PIND1)) // Hardware Interrupt (INT1) for AX pulse counting #define PIN_AX_INTERRUPT_ENABLE EIMSK |= (1 << INT1) #define PIN_AX_INTERRUPT_DISABLE EIMSK &= ~(1 << INT1) #define PIN_AX_INTERRUPT_RISING EICRA |= (1 << ISC11) | (1 << ISC10) #define PIN_AX_INTERRUPT_VECTOR INT1_vect #define PIN_AX_INTERRUPT_CLEAR EIFR |= (1 << INTF1) // Secondary Address line (AY) for multi-stage patching (INT0) #if defined(SCPH_3000) || defined(SCPH_1000) #define PIN_AY_INPUT DDRD &= ~(1 << DDD0) // AY on PD0 (INT0) #define PIN_AY_READ (PIND & (1 << PIND0)) #define WAIT_AY_RISING (!(PIND & (1 << PIND0))) #define WAIT_AY_FALLING (PIND & (1 << PIND0)) #define PIN_AY_INTERRUPT_ENABLE EIMSK |= (1 << INT0) #define PIN_AY_INTERRUPT_DISABLE EIMSK &= ~(1 << INT0) #define PIN_AY_INTERRUPT_RISING EICRA |= (1 << ISC01) | (1 << ISC00) #define PIN_AY_INTERRUPT_VECTOR INT0_vect #define PIN_AY_INTERRUPT_CLEAR EIFR |= (1 << INTF0) #define PIN_AY_INTERRUPT_FALLING EICRA = (EICRA & ~((1 << ISC01) | (1 << ISC00))) | (1 << ISC01) // Configure INT1 for falling edge trigger #endif // Hardware Bypass Switch (On-the-fly deactivation) #ifdef PATCH_SWITCHE #define PIN_SWITCH_INPUT DDRC &= ~(1 << DDC6) // Bypass on PC6 #define PIN_SWITCH_SET PORTC |= (1 << PC6) // Enable pull-up #define PIN_SWITCH_READ (!!(PINC & (1 << PINC6))) #endif #endif #endif #if defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny25__) #define IS_ATTINY_FAMILY void OptimizePeripherals(void) __attribute__((naked, section(".init3"))); void OptimizePeripherals(void) { // Ultra-Fast Boot (Clock & Watchdog) // Forced 8MHz is mandatory for stable SoftwareSerial baudrate CLKPR = 0x80; CLKPR = 0x00; MCUSR = 0; //Global Interrupt Disable during reconfiguration cli(); // Analog Modules Shutdown ADCSRA = 0; // Power off ADC completely ACSR |= (1 << ACD); // Disable Analog Comparator // Power Reduction Register (PRR) // Shuts down clocks to ADC and Timer 0. // We KEEP USI or Timer 1 if required for specific logic. PRR |= (1 << PRADC) | (0 << PRTIM0) | // KEEP TIMER 0 FOR SOFTWARE SERIAL (1 << PRTIM1) | (1 << PRUSI); // Timer 0 Specific Shutdown (Hardware Redundancy) TCCR0B = 0; TCCR0B = 0; TIMSK = 0; // Disable ALL timer interrupts (OCIE0A, OCIE0B, TOIE0, etc.) // Watchdog: Ensure it's disabled to prevent random resets MCUSR &= ~(1 << WDRF); WDTCR |= (1 << WDCE) | (1 << WDE); WDTCR = 0x00; } #include #include #include #include #include #include // --- Main Bus Interface (CD-ROM Controller) --- // Define the main pins as inputs #define PIN_DATA_INPUT DDRB &= ~(1 << DDB2) // DATA line (PB2) #define PIN_WFCK_INPUT DDRB &= ~(1 << DDB4) // WFCK / GATE line (PB4) #define PIN_SQCK_INPUT DDRB &= ~(1 << DDB0) // SQCK Clock (PB0) #define PIN_SUBQ_INPUT DDRB &= ~(1 << DDB1) // SUBQ Data (PB1) // Configure lines as outputs (for injection/override) #define PIN_DATA_OUTPUT DDRB |= (1 << DDB2) #define PIN_WFCK_OUTPUT DDRB |= (1 << DDB4) // Bus line state control (Set High / Clear Low) #define PIN_DATA_SET PORTB |= (1 << PB2) // Enable pull-up or drive HIGH #define PIN_DATA_CLEAR PORTB &= ~(1 << PB2) // Drive line LOW #define PIN_WFCK_CLEAR PORTB &= ~(1 << PB4) // Drive line LOW // Direct Register Reading (High-speed polling) #define PIN_SQCK_READ (PINB & (1 << PINB0)) #define PIN_SUBQ_READ (PINB & (1 << PINB1)) #define PIN_WFCK_READ (PINB & (1 << PINB4)) // --- Status Indication (LED) --- #ifdef LED_RUN #define PIN_LED_OUTPUT DDRB |= (1 << DDB3) // LED on PB3 #define PIN_LED_ON PORTB |= (1 << PB3) #define PIN_LED_OFF PORTB &= ~(1 << PB3) #endif // --- Debug Serial (Software Serial) --- #if defined(DEBUG_SERIAL_MONITOR) #include // SoftwareSerial(RX, TX): RX set to -1 (disabled), TX on PB3 // Note: Resource conflict if LED_RUN is also on PB3 SoftwareSerial mySerial(-1, 3); #define PIN_TXD_OUTPUT DDRB |= (1 << DDB3) #endif // --- Safety Check: BIOS Patch Compatibility --- #if defined(SCPH_1000) || \ defined(SCPH_3000) || \ defined(SCPH_3500_5000_5500) || \ defined(SCPH_7000_7500_9000) || \ defined(SCPH_100) || \ defined(SCPH_102) #error "ATtiny85/45/25 architecture is not compatible with the BIOS patch feature." #endif #endif // ***************************************************************************************************************** // WARNING: // The following code is not functional as-is. // ***************************************************************************************************************** #ifdef ATtiny88_48 #define F_CPU 16000000L #define TIMER_TCNT_CLEAR TCNT0 = 0x00 //TCNT0 - Timer/Counter Register #define SET_OCROA_DIV OCR0A = 159; //OCR0A – Output Compare Register A, 0x10011111, 100KHz #define SET_TIMER_TCCROA TCCR0A |= (1 << CTC0); //TCCR0A – Timer/Counter Control Register A. turn on CTC mode, CTC0 // On ATtiny88, TCCR0B doesn't exist — clock select bits (CS01, CS00) are in TCCR0A. // This sets the prescaler to 1, so the timer runs at full system clock (16 MHz). #define SET_TIMER_TCCROB TCCR0A |= (1 << CS01) | (1 << CS00) #define CTC_TIMER_VECTOR TIMER0_COMPA_vect //interrupt vector for match event, OCR0A comparison and Timer/Counter 0 #include #include #include #include #include #include // Globale interrupt seting #define GLOBAL_INTERRUPT_ENABLE SREG |= (1 << 7) #define GLOBAL_INTERRUPT_DISABLE SREG &= ~(1 << 7) // Handling the main pins // Main pins input #define PIN_DATA_INPUT DDRB &= ~(1 << DDB0) #define PIN_WFCK_INPUT DDRB &= ~(1 << DDB1) // Create a mask (1<<0) with the first bit at 1 b00000001 uses the ~ operator to perform a bit inversion b11111110, #define PIN_SQCK_INPUT DDRD &= ~(1 << DDD6) // &= updates the DDRB register with the AND operator and the mask, DDRB bxxxxxxxx OR mask b11111110 = bxxxxxxx0 #define PIN_SUBQ_INPUT DDRD &= ~(1 << DDD7) // Main pin output #define PIN_DATA_OUTPUT DDRB |= (1 << DDB0) // Create a mask (1<<0) with the first bit at 1 b00000001, #define PIN_WFCK_OUTPUT DDRB |= (1 << DDB1) // |= updates the DDRB register with the OR operator and the mask, DDRB bxxxxxxxx OR mask b00000001 = bxxxxxxx1 // Define pull-ups and set high at the main pin #define PIN_DATA_SET PORTB |= (1 << PB0) // Create a mask (1<<0) with the first bit at 1 b00000001, // |= updates the PORTB register with the OR operator and the mask, PORTB bxxxxxxxx OR mask b00000001 = bxxxxxxx1 // Define pull-ups set down at the main pin #define PIN_DATA_CLEAR PORTB &= ~(1 << PB0) // Create a mask (1<<0) with the first bit at 1 b00000001 uses the ~ operator to perform a bit inversion b11111110, #define PIN_WFCK_CLEAR PORTB &= ~(1 << PB1) // &= updates the DDRB register with the AND operator and the mask, DDRB bxxxxxxxx OR mask b11111110 = bxxxxxxx0 // Read the main pins #define PIN_SQCK_READ (PIND & (1 << PIND6)) // Create a mask (1<<6) with the six bit at 1 b00100000, #define PIN_SUBQ_READ (PIND & (1 << PIND7)) // compare the PINB register and the mask with the AND operator, and returns the result, PINB bxx1xxxxx AND mask b00100000 = 1 #define PIN_WFCK_READ (PINB & (1 << PINB1)) // Handling and use of the LED pin #ifdef LED_RUN #define PIN_LED_OUTPUT DDRD |= (1 << DDD0) #define PIN_LED_ON PORTD |= (1 << PD0) #define PIN_LED_OFF PORTD &= ~(1 << PD0) #endif // Handling the BIOS patch #if defined(SCPH_102) || defined(SCPH_100) || defined(SCPH_7000_9000) || defined(SCPH_5500) || defined(SCPH_3500_5000) || defined(SCPH_3000) || defined(SCPH_1000) // BIOS interrupt seting #define TIMER_INTERRUPT_ENABLE TIMSK0 |= (1 << OCIE0A) #define TIMER_INTERRUPT_DISABLE TIMSK0 &= ~(1 << OCIE0A) // BIOS timer clear #define TIMER_TIFR_CLEAR TIFR0 |= (1 << OCF0A) // Pins input #define PIN_AX_INPUT DDRD &= ~(1 << DDD2) #define PIN_AY_INPUT DDRD &= ~(1 << DDD3) #define PIN_DX_INPUT DDRD &= ~(1 << DDD4) // Pin output #define PIN_DX_OUTPUT DDRD |= (1 << DDD4) // Define pull-ups set high #define PIN_DX_SET PORTD |= (1 << PD4) // Define pull-ups set down #define PIN_DX_CLEAR PORTD &= ~(1 << PD4) // Read pins for BIOS patch #define PIN_AX_READ (PIND & (1 << PIND2)) #define PIN_AY_READ (PIND & (1 << PIND3)) // Handling the external interrupt #define PIN_AX_INTERRUPT_ENABLE EIMSK |= (1 << INT0) #define PIN_AY_INTERRUPT_ENABLE EIMSK |= (1 << INT1) #define PIN_AX_INTERRUPT_DISABLE EIMSK &= ~(1 << INT0) #define PIN_AY_INTERRUPT_DISABLE EIMSK &= ~(1 << INT1) #define PIN_AX_INTERRUPT_RISING EICRA |= (1 << ISC01) | (1 << ISC00) #define PIN_AY_INTERRUPT_RISING EICRA |= (1 << ISC11) | (1 << ISC10) #define PIN_AX_INTERRUPT_FALLING (EICRA = (EICRA & ~(1 << ISC00)) | (1 << ISC01)) #define PIN_AY_INTERRUPT_FALLING (EICRA = (EICRA & ~(1 << ISC10)) | (1 << ISC11)) #define PIN_AX_INTERRUPT_VECTOR INT0_vect #define PIN_AY_INTERRUPT_VECTOR INT1_vect // Handling and reading the switch pin for patch BIOS #ifdef PATCH_SWITCH #define PIN_SWITCH_INPUT DDRD &= ~(1 << DDD5) #define PIN_SWITCH_SET PORTD |= (1 << PD5) #define PIN_SWITCH_READ (PIND & (1 << PIND5)) #endif #endif #endif #ifdef ATtiny214_414 //#define SET_CTRLA #define DF_CPU 20000000L #define TIMER_TCNT_CLEAR TCA0.SINGLE.CNT = 0x00 //TCNT0 - Timer/Counter Register #define SET_OCROA_DIV TCA0.SINGLE.CMP0L = 100; //OCR0A – Output Compare Register A, 0x10011111, 100KHz #define SET_TIMER_TCCROA TCA0.SINGLE.CTRLB |= (1 << TCA_SINGLE_WGM0); //TCA_SINGLE_WGMODE_FRQ_gc //TCCR0A – Timer/Counter Control Register A. turn on CTC mode, CTC0 #define SET_TIMER_TCCROB TCA0.SINGLE.CTRLA |= (1 << TCA_SINGLE_CLKSEL0); //TCA_SINGLE_CLKSEL_DIV1_gc//TCCR0B – Timer/Counter Control Register B, CS00: Clock Select, clk I/O //Waveform Generation Mode, Mode 2 CTC #define CTC_TIMER_VECTOR TCA0_OVF_vect //TCA0_CMP0_vect //interrupt vector for match event, OCR0A comparison and Timer/Counter 0 #include #include #include #include #include #include // Globale interrupt seting #define GLOBAL_INTERRUPT_ENABLE __asm__ __volatile__("sei" ::) //CPU.SREG |= (1<<7) #define GLOBAL_INTERRUPT_DISABLE __asm__ __volatile__("cli" ::) //CPU.SREG &= ~(1<<7) // Handling the main pins // Main pins input #define PIN_DATA_INPUT PORTA.DIR = PIN2_bm #define PIN_WFCK_INPUT PORTA.DIR = PIN1_bm // Create a mask (1<<0) with the first bit at 1 b00000001 uses the ~ operator to perform a bit inversion b11111110, #define PIN_SQCK_INPUT PORTA.DIR = PIN4_bm // &= updates the DDRB register with the AND operator and the mask, DDRB bxxxxxxxx OR mask b11111110 = bxxxxxxx0 #define PIN_SUBQ_INPUT PORTA.DIR = PIN3_bm // Main pin output #define PIN_DATA_OUTPUT PORTA.DIR |= PIN2_bm // Create a mask (1<<0) with the first bit at 1 b00000001, #define PIN_WFCK_OUTPUT PORTA.DIR |= PIN1_bm // |= updates the DDRB register with the OR operator and the mask, DDRB bxxxxxxxx OR mask b00000001 = bxxxxxxx1 // Define pull-ups and set high at the main pin #define PIN_DATA_SET PORTA.OUT |= PIN2_bm // Create a mask (1<<0) with the first bit at 1 b00000001, // |= updates the PORTB register with the OR operator and the mask, PORTB bxxxxxxxx OR mask b00000001 = bxxxxxxx1 // Define pull-ups set down at the main pin #define PIN_DATA_CLEAR PORTA.OUT &= ~PIN2_bm // Create a mask (1<<0) with the first bit at 1 b00000001 uses the ~ operator to perform a bit inversion b11111110, #define PIN_WFCK_CLEAR PORTA.OUT &= ~PIN1_bm // &= updates the DDRB register with the AND operator and the mask, DDRB bxxxxxxxx OR mask b11111110 = bxxxxxxx0 // Read the main pins #define PIN_SQCK_READ PORTA.IN& PIN4_bm // Create a mask (1<<6) with the six bit at 1 b00100000, #define PIN_SUBQ_READ PORTA.IN& PIN3_bm // compare the PINB register and the mask with the AND operator, and returns the result, PINB bxx1xxxxx AND mask b00100000 = 1 #define PIN_WFCK_READ PORTA.IN& PIN1_bm // Handling and use of the LED pin #define LED_RUN #define PIN_LED_OUTPUT PORTB.DIR |= PIN2_bm #define PIN_LED_ON PORTB.OUT |= PIN2_bm #define PIN_LED_OFF PORTB.OUT &= ~PIN2_bm // Handling the BIOS patch // BIOS interrupt seting #define TIMER_INTERRUPT_ENABLE TCA0.SPLIT.INTCTRL |= TCA_SINGLE_CMP0_bm #define TIMER_INTERRUPT_DISABLE TCA0.SPLIT.INTCTRL &= ~TCA_SPLIT_HCMP0_bm // BIOS timer clear #define TIMER_TIFR_CLEAR TCA0.SPLIT.INTFLAGS = TCA_SPLIT_HCMP0_bm // Pins input #define PIN_AX_INPUT PORTB.DIR &= ~PIN3_bm #define PIN_AY_INPUT PORTA.DIR &= ~PIN7_bm #define PIN_DX_INPUT PORTA.DIR &= ~PIN6_bm // Pin output #define PIN_DX_OUTPUT PORTA.DIR |= PIN6_bm // Define pull-ups set high #define PIN_DX_SET PORTA.OUT |= PIN6_bm // Define pull-ups set down #define PIN_DX_CLEAR PORTA.OUT &= ~PIN6_bm // Read pins for BIOS patch #define PIN_AX_READ PORTB.IN& PIN3_bm #define PIN_AY_READ PORTA.IN& PIN6_bm // Handling the external interrupt //#define PIN_AX_INTERRUPT_ENABLE PORTB.PIN3CTRL |= (1< 0) { // if (PIN_AX_READ != 0) { // while (WAIT_AX_FALLING); // Pulse detected: wait for bus to clear // break; // Reset and try a new silence block // } // count--; // } // // If count reaches 0, a silent block is validated // if (count == 0) { // current_confirms++; // } // } // impulse = PULSE_COUNT; // PIN_LED_ON; // PIN_AX_INTERRUPT_RISING; // PIN_AX_INTERRUPT_ENABLE; // while (patch != 1); // Wait for the first stage of the patch to complete: // //PIN_LED_OFF; // // -------- Secondary Patch ---------- // #ifdef PHASE_TWO_PATCH // current_confirms = 0; // while (current_confirms < CONFIRM_COUNTER_TARGET_2) { // uint16_t count = SILENCE_THRESHOLD; // while (count > 0) { // if (PIN_AX_READ != 0) { // while (WAIT_AX_FALLING); // break; // } // count--; // } // if (count == 0) { // current_confirms++; // } // } // PIN_LED_ON; // impulse = PULSE_COUNT_2; // PIN_AY_INTERRUPT_RISING; // PIN_AY_INTERRUPT_ENABLE; // while (patch != 2); // Wait for the second stage of the patch to complete: // #endif // cli(); // } // #endif