Mega Drive Switchless (Arduino)

Discussion in 'Modding and Hacking - Consoles and Electronics' started by Bearking, May 14, 2019.

  1. Bearking

    Bearking Konsolkongen

    Joined:
    Aug 2, 2010
    Messages:
    856
    Likes Received:
    100
    I'm trying to learn some programming using Arduino. I have more or less completed my own switchless Mega Drive mod. In theory this works and everything seem to check out on the breadboard, but some minor tweaks are still needed.

    I'm wondering if the boot time of the Arduino is going to be a problem for the Mega Drive? It takes about a second before the Arduino is up and running. And for this second the jumpers on the Mega Drive are both pulled low to GND (JAP 50Hz), and then switched to whatever region was stored in the EEPROM.

    How fast do the games, and Mega CD/32X check region after power on?

    I guess I could hook up the CPU halt line to the Arduino and have the CPU wait a bit if it turns out to be a problem. That would probably work for Mega Drive games, but what about the Mega CD and 32X? Would they allow the Mega Drive's CPU to start slightly later and still work?

    I know that there already is a Mega Drive switchless code for the Arduino. But I haven't looked at it. I wanted to learn myself by trial and error. But I guess it either just works fine, or that he found some other way to force the Arduino to instantly set the region on power on?
     
    Last edited: May 17, 2019
  2. Bad_Ad84

    Bad_Ad84 The Tick

    Joined:
    May 26, 2011
    Messages:
    8,594
    Likes Received:
    1,372
    I assume you are using the reset button, then a pin to reset?

    Why not reset the console after the arduino has booted and set the jumpers?
     
  3. Bearking

    Bearking Konsolkongen

    Joined:
    Aug 2, 2010
    Messages:
    856
    Likes Received:
    100
    Yes, that's what I'm doing. And your suggestion is the obvious solution. Thanks :D
     
  4. Bad_Ad84

    Bad_Ad84 The Tick

    Joined:
    May 26, 2011
    Messages:
    8,594
    Likes Received:
    1,372
    All in this together. We all need help at times, even if it seems obvious after the fact!
     
    Bearking likes this.
  5. Bearking

    Bearking Konsolkongen

    Joined:
    Aug 2, 2010
    Messages:
    856
    Likes Received:
    100
    Yeah, some of it is still tricky to wrap my head around. The whole thing with having to compare variables to increase a counter for example is something that I mess up almost every time. I get why it has to be done the way it is, but in my mind I still think that one variable should be plenty :D

    I can post the code here when it's done and tested :)
     
  6. Bearking

    Bearking Konsolkongen

    Joined:
    Aug 2, 2010
    Messages:
    856
    Likes Received:
    100
    Yes! I believe it works just fine. Have yet to try with Mega CD though, and I wonder if the initial reset could be a problem if used with a Mega CD1 with EU or US BIOS as they eject the tray with the reset button? Not a problem for me as I use the region free JAP BIOS, but worth mentioning nonetheless.

    This mod was just written how I wanted it to be. It may not suit everyones needs.

    *Press the reset button for less than 200ms to reset, hold it to cycle regions (EU = Blue, US = Purple, JAP = Red).
    *Each region is saved to EEPROM, so the region will remain the same after power cycling the console.
    *EU mode auto switches to 60Hz after 8 seconds, because I never want to play anything in 50Hz ever again. Resetting the console in this mode will start in 50 and change to 60 every time.

    The library FastLED was used to cycle the LED color every n seconds. This method was recommended several places when I was looking for a solution, and for the moment I can't figure out how to do it any other way :)

    The only very slight issue I found with my code is that region is saved to EEPROM every time the console is in EU mode and you reset it. I don't believe this will ever be an issue, but it's an oversight due to the way I switch regions. Might be easily fixable but I highly doubt I will ever reset the console enough that the EEPROM will wear out because of this :)

    Phantasy Star IV booting in 50Hz and auto switching to 60 (you can hear the music speed up):


    Code:
    //Mega Drive Switchless v1
    //2019 by Martin Larsen (Konsolkongen/Bearking)
    
    //Pinout was chosen to fit the layout of the Arduino Pro Mini, but can be modified below
    
    #include <EEPROM.h>
    #include <FastLED.h>       // Used to cycle the LED color every second
    
    const int LEDblue = 5;     // PWM output - Blue LED
    const int LEDred = 3;      // PWM output - Red LED
    const int button = 2;      // Connects to the reset button. This is active low and the original reset-trace has been cut
    const int resetSignal = 4; // Connects to the reset signal after the cut
    const int Hz = A2;         // Speed select - LOW = 50hz, HIGH = 60Hz
    const int language = A3;   // Language select - LOW = JAP, HIGH = ENG
    
    int address = 16;          // The address used in EEPROM to store the current setting
    int region = 0;            // 0 = EU, 1 = US, 2 = JAP
    int tempRegion = 0;        // Temporary variable for storing the region while the button is held
    int buttonState = 0;       // Is the button pressed?
    int lastButtonState = 0;   // Previous state of the button
    
    unsigned long millis_held; // How long the button was held (milliseconds)
    unsigned long firstTime;   // How long since the button was first pressed
    unsigned long force60Hz;   // Variable to store time used to force 60Hz when EU mode is selected
    
    void setup() {
    //  Serial.begin(9600);
     
      pinMode(LEDblue, OUTPUT);
      pinMode(LEDred, OUTPUT);
      pinMode(button, INPUT_PULLUP);
      pinMode(resetSignal, OUTPUT);
      pinMode(Hz, OUTPUT);
      pinMode(language, OUTPUT);
    
      region = EEPROM.read(address);
      tempRegion = EEPROM.read(address);  //tempRegion and region has to match at power on, to avoid LED color/region mismatch.
    
    // Resets the console before the loop starts, to rule out any boot problems due to the Arduinos startup time. - This may be a problem if using a Mega CD1 with EU or US BIOS, as reset ejects the tray.
      digitalWrite(resetSignal, LOW);
      delay(100);
      digitalWrite(resetSignal, HIGH);
    }
    
    void loop() {
      buttonState = digitalRead(button); // Read the state of the button and move it to the variable.
    
    //  Serial.print("Time: ");
    //  Serial.print(millis());
    //  Serial.print(" Since push: ");
    //  Serial.print(millis_held);
    //  Serial.print(" Button: ");
    //  Serial.print(buttonState);
    //  Serial.print(" Last Button: ");
    //  Serial.print(lastButtonState);
    //  Serial.print(" Temp: ");
    //  Serial.print(tempRegion);
    //  Serial.print(" Region: ");
    //  Serial.println(region);
    
    // If the button is pressed. Remember the start time.
      if (buttonState == LOW && lastButtonState == HIGH) {
        firstTime = millis();
      }
    
      millis_held = (millis() - firstTime);
    
    // Debounce - Button must be held for at least 20ms.
      if (millis_held > 20) {
    
    // Every second the button is held, the tempRegion variable will increase by one.
        if (buttonState == LOW && millis_held >= 200) {
          EVERY_N_MILLISECONDS(1000) { // Function defined in the FastLED library. Every 1000ms, do the following...
            if (millis_held >= 1200) { // EVERY_N... relies on the millis counter, so this ensures that the button has been held for at least 1200ms, so that the LED doesnt switch too fast.
              tempRegion++;
              if (tempRegion > 2) { // If the tempRegion variable reaches 3 it will reset to 0.
                tempRegion = 0;
              }
            }
          }
          force60Hz = millis(); // Time is moved into a variable used to compare times when forcing 60Hz in EU mode.
        }
       
        switch (tempRegion) {  // Cycles LED color according to the tempRegion variable.
          case 0: // EU - Blue
            analogWrite (LEDblue, 50), analogWrite (LEDred, 0);
            break;
          case 1: // US - Purple
            analogWrite (LEDblue, 50), analogWrite (LEDred, 50);
            break;
          case 2: // JAP - Red
            analogWrite (LEDblue, 0), analogWrite (LEDred, 50);
            break;
        }
    
    // If the tempRegion variable at this point differs from the region variable, move the tempRegion variable into region, and save to EEPROM.
        if (buttonState == HIGH && lastButtonState == LOW && region != tempRegion) {
          region = tempRegion;
          EEPROM.write(address, region); // Stores the region setting in the EEPROM variable address
    //    Serial.println("Config saved!");
        }
    
    // If the region changed above, set the jumpers.
        switch (region) {
          case 0: // EU
            digitalWrite (Hz, LOW), digitalWrite (language, HIGH);
              if ((millis() - force60Hz) >= 8000) { // When 8 seconds have passsed, switch speed to 60Hz.
                region = 3;
              }
            break;
          case 1: // US
            digitalWrite (Hz, HIGH), digitalWrite (language, HIGH);
            break;
          case 2: // JAP
            digitalWrite (Hz, HIGH), digitalWrite (language, LOW);
            break;
          case 3: // EU forced 60Hz - A separate region to change into when auto switching to 60Hz. Is not saved in config. When reset the console will boot in 50Hz.
            digitalWrite (Hz, HIGH), digitalWrite (language, HIGH);
            break;
        }
    
    // If the button is released before 200ms has passed, reset the console.
        if (buttonState == HIGH && lastButtonState == LOW) {
          if (millis_held < 200) {
            digitalWrite(resetSignal, LOW);
            analogWrite (LEDblue, 0), analogWrite (LEDred, 0); // Turns off the LED for 200ms
            delay(200);
            digitalWrite(resetSignal, HIGH);
            force60Hz = millis();
            if (region == 3 && tempRegion == 0) {
              region = 0;
            }
          }
        }
      }
     
      lastButtonState = buttonState;     // Save the current button state as last state.
    }
     

    Attached Files:

    Last edited: May 17, 2019
    Jackhead likes this.
  7. Bearking

    Bearking Konsolkongen

    Joined:
    Aug 2, 2010
    Messages:
    856
    Likes Received:
    100
    Works fine with Mega CD1 (JAP BIOS tested) and 32X. Nice of both of them to wait for the Mega Drive :)
     
  8. segasonicfan

    segasonicfan Robust Member

    Joined:
    Sep 23, 2011
    Messages:
    262
    Likes Received:
    40
    I'm glad somebody's working on this, it seems a no-brainer to use an Arduino for such a simple modification. It seems much better to me than the PIC programmable method.

    Have you considered posting on GitHub? I'm sure people would love to see it there, and it would it would help to preserve the project.

    I imagine the only problem you would have with this is on the earliest non-TMSS consoles. I bet they check the region setting pretty quickly.

    Personally, I would keep the jumpers pulled High through 10K resistors before the Arduino is booted. That way it's defaulted at US 60 hertz.

    Anyways, great work!
     
    Bearking likes this.
  9. Bearking

    Bearking Konsolkongen

    Joined:
    Aug 2, 2010
    Messages:
    856
    Likes Received:
    100
    Not really familiar with github at all, so that's something I would have to research first.

    Thank you :)

    My Mega Drive 1 is a TMSS model, but I don't think it's a problem for earlier units. The Arduino is all things considered a little slow to boot, but during the setup it resets the Mega Drive and sets the jumpers according to the last used region. So once the Mega Drive is allowed to power on, the jumpers are already set and working properly.

    Which is also why it doesn't really matter if the jumpers are pulled high or low on power on :)

    I've been using the console for about 10 hours over the last week or so, as I've been testing out my new Retro-Bit 6 button controllers, and there hasn't been a single problem with the code :)
     

Share This Page