PSNee further development

General information to do with the PlayStation 1 Hardware. Including modchips, pinouts, rare or obscure development equipment, etc.
daywalker
Interested PSXDEV User
Interested PSXDEV User
Posts: 9
Joined: Oct 28, 2018

Post by daywalker » October 29th, 2018, 5:13 pm

I inject the code six times because you're doing it as well. I am just not injecting each of the three regions twice, but the correct region 6 times. But also i did not investigate that part yet since it worked. So you would reduce the number of injections of the correct region to two?

This is the original code

Code: Select all

for (byte loop_counter = 0; loop_counter < 2; loop_counter++)
    {
      inject_SCEX('e'); // e = SCEE, a = SCEA, i = SCEI
      inject_SCEX('a'); // injects all 3 regions by default
      inject_SCEX('i'); // optimize boot time by sending only your console region letter (all 3 times per loop)
    }
About the fuses, here's some more info on embedding them
https://www.microchip.com/webdoc/AVRLib ... _fuse.html

rama3
Verified
/// PSXDEV | ELITE ///
/// PSXDEV | ELITE ///
Posts: 510
Joined: Apr 16, 2017

Post by rama3 » October 29th, 2018, 9:37 pm

Oh, never mind then. I guess I remembered wrong ;p

I guess we need to test whether the fuse API works on Arduino / using the Arduino IDE.
It could definitely cut down on potential user errors.

daywalker
Interested PSXDEV User
Interested PSXDEV User
Posts: 9
Joined: Oct 28, 2018

Post by daywalker » October 30th, 2018, 8:27 pm

I don't think that will work, as far as i know the fuse settings are packaged into the .elf file in Atmel Studio. Without having checked this, i seem to remember that the Arduino IDE flashes the .hex only.

superg
Active PSXDEV User
Active PSXDEV User
Posts: 48
Joined: Sep 22, 2018

Post by superg » November 1st, 2018, 12:59 am

I'm having troubles enabling bios patching on ATtiny (84 for now). I think it's timing but can't figure out the correct values. I used my logic analyser to monitor A18 / D2 but I'm getting different values every time and it's not clearly visible what's going on without seeing the other address lines. Does anybody have some ideas?

daywalker
Interested PSXDEV User
Interested PSXDEV User
Posts: 9
Joined: Oct 28, 2018

Post by daywalker » November 1st, 2018, 4:47 am

superg wrote: November 1st, 2018, 12:59 am I'm having troubles enabling bios patching on ATtiny (84 for now). I think it's timing but can't figure out the correct values. I used my logic analyser to monitor A18 / D2 but I'm getting different values every time and it's not clearly visible what's going on without seeing the other address lines. Does anybody have some ideas?
Hey, not sure this will help but i thought about using the two remaining I/O-pins on the AttinyX5 for that feature. Since i only have a PU-22 board, i left out the code for the time being(Since i can't verify it on hardware). But i tried to convert the function as well:

Code: Select all

void NTSC_fix() {
    #define A18 B,3
    #define D2  B,5
    INPUT(A18);
    INPUT(D2);
 
    _delay_ms(100); // this is right after SQCK appeared. wait a little to avoid noise

    while (!READ(A18));//wait for stage 1 A18 pulse

    _delay_ms(1350); //wait through stage 1 of A18 activity
 
    cli(); // start critical section
        while (!READ(A18));//wait for priming A18 pulse
         
        _delay_us(17); // max 17us for 16Mhz ATmega (maximize this when tuning!)

        LOW(D2); // store a low
        OUTPUT(D2); // D2 = output. drags line low now

        _delay_us(4); // min 2us for 16Mhz ATmega, 8Mhz requires 3us (minimize this when tuning, after maximizing first us delay!)

        INPUT(D2); // D2 = input / high-z
    sei(); // end critical section
}
The timing looks quite straight forward, especially because interrupts are disabled for the microsecond stuff. Do you have data from the logic analyzer of what is happening? It the outgoing timing at least what the code is asking for?

superg
Active PSXDEV User
Active PSXDEV User
Posts: 48
Joined: Sep 22, 2018

Post by superg » November 1st, 2018, 7:31 am

daywalker wrote: November 1st, 2018, 4:47 am Hey, not sure this will help but i thought about using the two remaining I/O-pins on the AttinyX5 for that feature.
I suggest you read the last few pages of this topic to find out where we are with this and what is the goal. That was already discussed and my current effort is to get BIOS patching work on ATtiny84 before 85 as the moment you reassign 85 reset pin to i/o you will loose the ability to reprogram the chip without high voltage programmer (to reset the fuses). 84 is the same family but more pins, you probably know this. I've already added the device support and everything except BIOS patching works.
daywalker wrote: November 1st, 2018, 4:47 am convert the function as well:

Code: Select all

void NTSC_fix() {
    #define A18 B,3
    #define D2  B,5
    INPUT(A18);
    INPUT(D2);
 
    _delay_ms(100); // this is right after SQCK appeared. wait a little to avoid noise

    while (!READ(A18));//wait for stage 1 A18 pulse

    _delay_ms(1350); //wait through stage 1 of A18 activity
 
    cli(); // start critical section
        while (!READ(A18));//wait for priming A18 pulse
         
        _delay_us(17); // max 17us for 16Mhz ATmega (maximize this when tuning!)

        LOW(D2); // store a low
        OUTPUT(D2); // D2 = output. drags line low now

        _delay_us(4); // min 2us for 16Mhz ATmega, 8Mhz requires 3us (minimize this when tuning, after maximizing first us delay!)

        INPUT(D2); // D2 = input / high-z
    sei(); // end critical section
}
Please don't get it wrong but some critic will follow. All you did is you took something generic (Arduino) and made something very specific (Atmel Studio etc.). I'm not a fan of Arduino or anything like this but here I clearly see the benefits, we need one code base which supports a lot of platforms, is well debugged and actively maintained. What you did is fine as an experiment and for personal use but I don't see any advantage. Except maybe that you can debug it with AVR-ICE but it's useless because you can't pause the PlayStation hardware :).
ATtiny has 2Kb flash and Arduino code without debug info is already under 1Kb. Arduino port manipulation probably compiles to the same code but it's generic. The current code base probably works fine on ATtiny25 without any modification. I can also tell a lot about your improper use of #define, downgrading from C++ to C code etc, but that's another story. Now imagine somebody new will come to the topic, sees your code and will think that this is what he has to use for his equipment, easily get confused and complain that stuff is too hard to use (it already is). Thus when you refer to code, please use main code base from kalymos, I hope my stuff will get added there once I make sure everything is stable, that improves the readability and corrects some things.
daywalker wrote: November 1st, 2018, 4:47 am The timing looks quite straight forward, especially because interrupts are disabled for the microsecond stuff. Do you have data from the logic analyzer of what is happening? It the outgoing timing at least what the code is asking for?
Yes, it does look pretty straightforward but it doesn't work and I have yet to find a reason why. If you can help, you're more than welcome. The timing is the likely reason. I have some dumps from my logic analyser software which I can share. I'm not sure if the dumps are legit as I get a variation in A18 readings every time I run, it's either me doing something stupid like setting incorrect sample rate or logic analyser is at fault (EasySync ES-DLA-16).

rama3
Verified
/// PSXDEV | ELITE ///
/// PSXDEV | ELITE ///
Posts: 510
Joined: Apr 16, 2017

Post by rama3 » November 1st, 2018, 1:32 pm

Superg: Check here for what you should get with your logic analyzer:
http://www.psxdev.net/forum/viewtopic.p ... 220#p12848

superg
Active PSXDEV User
Active PSXDEV User
Posts: 48
Joined: Sep 22, 2018

Post by superg » November 1st, 2018, 11:04 pm

rama3 wrote: November 1st, 2018, 1:32 pm Superg: Check here for what you should get with your logic analyzer:
http://www.psxdev.net/forum/viewtopic.p ... 220#p12848
Oh, this is very helpful, thanks! Don't know how did I miss that!

superg
Active PSXDEV User
Active PSXDEV User
Posts: 48
Joined: Sep 22, 2018

Post by superg » November 2nd, 2018, 4:54 am

Speaking of fuses, there is a way to get the values runtime, more info here:
https://arduino.stackexchange.com/quest ... -my-sketch
This is gcc-avr functionality thus not limited to Arduino btw.
I will incorporate the checks after ATtiny bios patching.

superg
Active PSXDEV User
Active PSXDEV User
Posts: 48
Joined: Sep 22, 2018

Post by superg » November 2nd, 2018, 12:32 pm

Ok, I almost burned my PAL PSOne by inserting my psnee modchip header to ISP by mistake. Got some smoke and had to bridge the fuse temporarily to get it working. I'm so happy it hasn't died as it would take a while to get replacement PAL PSOne shipped to the US.

But on a bright note I figured out the timing:
Image
Channel 2 high marks start of patching D2 low. As we can see here, ATtiny timing is 2 microseconds slower comparing to arduino:
Image
By changing NTSC_fix() delay from 17 to 15 I am able to consistently get my Tekken 3 to boot using my ATtiny84. Ideally I would like to get a few more dumps before we can set the final timing and also I would like to check internal oscillator calibration routine, maybe it will improve the timing.
Also my logic analyzer software is really terrible, I can't set timing ranges, it changes by itself when I zoom in and I can't seem to find how to control it.

daywalker
Interested PSXDEV User
Interested PSXDEV User
Posts: 9
Joined: Oct 28, 2018

Post by daywalker » November 3rd, 2018, 6:38 am

Hey superg,
Sorry I did not mean to change the topic of this discussion, I just wanted to have a ready to go version of this project to fit on a tiny25. Basically to use it for myself and after I was done, wanted to share the code. I read the rest of this discussion and yes, i have a high voltage programmer so i can reprogram even if I use the reset pin as an input. I did not mean that development should be done on a 8 pin device, but it would be nice as a final version, even if you need the bios patch.

Sorry for the #defines. Always copy/paste them from project to project because they make port manipulation more readable, not because they are the most correct or efficient ;)

rama3
Verified
/// PSXDEV | ELITE ///
/// PSXDEV | ELITE ///
Posts: 510
Joined: Apr 16, 2017

Post by rama3 » November 4th, 2018, 12:14 am

Meh, I had a big reply typed up, but lost it :/

When patching D2, the bits right before the patch location are important, the bits after it not so much.
We're patching the region string from 'E' to 'A'.
Image
The BIOS probably reads in the string and does some string manipulation on it that requires the earlier bits to be intact.

So the patcher can drag D2 low for a bit longer, but it must be timed to start exactly right.

The 2uS delay:
I never checked whether bitSet() and co. (Arduino convenience functions) compile to the same code on all AVRs.
If they're not directly usable for port manipulation, that could explain the delay.
I don't think the issue is with the oscillator, as we've just waited for the A18 signal and only 45uS have passed since then.
Having a 2uS divergence so soon would be a bit much, I think.

There's 16 operations possible within 2uS on the 8Mhz chips. Maybe something is possible with regards to sampling D2?
The ports would have to be able to switch at CPU speed and each opcode would have to be 1 cycle, including switching from input to output... Surely needs hand coded ASM.. Not sure.

But the fuse stuff is great! That will allow for some nice things :)

rama3
Verified
/// PSXDEV | ELITE ///
/// PSXDEV | ELITE ///
Posts: 510
Joined: Apr 16, 2017

Post by rama3 » November 4th, 2018, 12:27 am

Oh, and some practical things with regards to the PSOne:
There's just the one power button on the console, and people are probably pushing it twice in quick succession for a reset.
The AVR should have brownout detection enabled and simply stop working when Vcc drops below ~3.0V.
A PSX reset will probably drain all the capacitors in the system, but potentially not all the way to 0V, but rather maybe 1V or so.

2nd thing:
The AVRs have hardware timers. Their accuracy somehow is better than code such as while(bitRead()), though that may depend on other factors.
If we can't sample D2 when patching the BIOS, maybe usage of a timer can help with .. timing xD

superg
Active PSXDEV User
Active PSXDEV User
Posts: 48
Joined: Sep 22, 2018

Post by superg » November 4th, 2018, 5:52 am

rama3 wrote: November 4th, 2018, 12:14 am The 2uS delay:
I never checked whether bitSet() and co. (Arduino convenience functions) compile to the same code on all AVRs.
If they're not directly usable for port manipulation, that could explain the delay.
I don't think the issue is with the oscillator, as we've just waited for the A18 signal and only 45uS have passed since then.
Having a 2uS divergence so soon would be a bit much, I think.
Those bit routines are actually very simple [hardware/arduino/avr/cores/arduino/Arduino.h]:

Code: Select all

#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
That's exactly how I would do it manually.

Honestly I don't know where the delay is coming from, that needs more investigation. I'll try to put some debugging in and check timing with logic analyzer.

EDIT: now that I posted it I realized that there is no variable shift instruction, usually it gets substituted with a loop, I'll try to experiment with it :)
EDIT2: yeah, but BIOS_D2_BIT is compile time constant so it gets optimized.

superg
Active PSXDEV User
Active PSXDEV User
Posts: 48
Joined: Sep 22, 2018

Post by superg » November 4th, 2018, 1:26 pm

Ok, the problem resolved. Turned out delayMicroseconds() yields different results for different chips. According to my logic analyzer dumps, there is a constant difference ~1.3us for every delayMicroseconds() call. Apart from the difference, the actual delay is quite different in the dumps comparing to what we specify as an argument. I looked into the Arduino implementation a bit but decided not to spend too much time on this:

Code: Select all

#elif F_CPU >= 8000000L
	// for the 8 MHz internal clock

	// for a 1 and 2 microsecond delay, simply return.  the overhead
	// of the function call takes 14 (16) cycles, which is 2us
	if (us <= 2) return; //  = 3 cycles, (4 when true)

	// the following loop takes 1/2 of a microsecond (4 cycles)
	// per iteration, so execute it twice for each microsecond of
	// delay requested.
	us <<= 1; //x2 us, = 2 cycles

	// account for the time taken in the preceeding commands.
	// we just burned 17 (19) cycles above, remove 4, (4*4=16)
	// us is at least 6 so we can substract 4
	us -= 4; // = 2 cycles

#else 
// ...

	// busy wait
	__asm__ __volatile__ (
		"1: sbiw %0,1" "\n\t" // 2 cycles
		"brne 1b" : "=w" (us) : "0" (us) // 2 cycles
	);
	// return = 4 cycles 
My ATtiny and Arduino Pro Micro are both configured for 8MHz internal oscillator so it should be the same but it isn't.

Fortunately enough avr-gcc libc implementation has function _delay_us which is precise and supports fractions.
I fine tuned delay values, optimized everything and made sure my logic analyzer dumps are as close to reference as possible, Pro Micro (Channel 2 is my debugging, ignore it):
Image
ATtiny84 dump is very similar but D2 pull down delay is 0.3us longer comparing to Pro Micro, which I guess is ok because it's still shorter than it was before.
Everything is consistent so far, the modified NTSC_fix() snippet:

Code: Select all

	noInterrupts(); // start critical section
	while(!bitRead(BIOS_PI, BIOS_A18_BIT))
		;  // wait for priming A18 pulse
	
	// delayMicroseconds() yields different delay under ATtiny which breaks timing
	// (~1.3us difference comparing to ATmega), use avr-gcc _delay_us() instead
	_delay_us(15.2); // the value has been maximized for stable operation under ATmega and ATtiny
	
	bitClear(BIOS_PO, BIOS_D2_BIT); // store a low
	bitSet(BIOS_PD, BIOS_D2_BIT); // D2 = output. drags line low now

	// _delay_us() is imprecise for small values, 0.3 here yields ~1.1us on ATmega and ~1.4us on ATtiny
	_delay_us(0.3); // the value has been minimized for stable operation under ATmega and ATtiny
	bitClear(BIOS_PD, BIOS_D2_BIT); // D2 = input / high-z
	interrupts(); // end critical section
}
Everything is uploaded here: https://github.com/superg/PsNee

rama3
Verified
/// PSXDEV | ELITE ///
/// PSXDEV | ELITE ///
Posts: 510
Joined: Apr 16, 2017

Post by rama3 » November 5th, 2018, 12:14 pm

Fantastic :D

superg
Active PSXDEV User
Active PSXDEV User
Posts: 48
Joined: Sep 22, 2018

Post by superg » November 7th, 2018, 3:30 am

rama3 wrote: October 29th, 2018, 12:45 am You inject the license symbols 6 times. That could be too much for some anti mod games. It's possible that you're still in the sending loop while the game has long moved the laser, and thus it becomes detectable.
Just my observation, I experience a delay in boot on my test PAL PSOne if I do inject_SCEX('E') just twice. When increased back to 6 times (the default in kalymos master branch) it's fast again. I think my test PU-18 board was fast regardless of this setting (2 or 6).

rama3
Verified
/// PSXDEV | ELITE ///
/// PSXDEV | ELITE ///
Posts: 510
Joined: Apr 16, 2017

Post by rama3 » November 7th, 2018, 4:20 am

Yeah, that difference has a couple of factors.
First, the PU-18 Mechacon is still using the old, direct injection method.
The PSOne has long switched to the modulated injection path.

In Mechacon code, the asynchronous symbol checking routine will surely behave differently, just because the external factors have changed so much.

I can't tell what exactly happens, but it's possible that the PSOne Mechacon first accepts the symbols, but soon after, an unexpected symbol comes in, resetting the detection routine.
(It can even fail at this point, if it runs out of verification attempts.)
In case of the PU-18, that Mechacon may just accept the string instantly, and move on (ignoring any extra symbols, since it's not doing that code path anymore).

So these different Mechacon revisions have "characteristics" that we could optimize for.
That would require knowing what works best on each, of course ;p

superg
Active PSXDEV User
Active PSXDEV User
Posts: 48
Joined: Sep 22, 2018

Post by superg » November 11th, 2018, 1:21 am

A few things, I got pro micro here and while ISP programming pin numbers are different, all the PSX pins that we use in psnee are the same, chances are that it will work as is. I am able to compile everything just fine with ARDUINO_BOARD defined but I can't flash it within Arduino IDE because they hardcoded usb programmer for pro micro somewhere in the configuration. I will try to flash the hex file directly using my AVR-ICE, just need to make a wire adapter.

Next I would like to make BIOS patching optional so we can have a universal firmware which will only patch BIOS if A12 is connected. Currently if I have BIOS patching enabled and use the chip on my PU-18, it hangs here obviously:

Code: Select all

	while(!bitRead(BIOS_PI, BIOS_A18_BIT))
		;  // wait for stage 1 A18 pulse
For my testing I added return from NTSC_fix() if we don't get anything in 1 second and it works fine as long as I force the state of disconnected A12 pin. I plan to add a small solder jumper to force a state for models which don't need a BIOS patching. rama3, what do you think, is it something we want to have?

The idea behind this is that in my opinion there are two types of users, most will want one universal hex file which will have BIOS patching, multi-region and PU-22+ detection, and some (like me) who want to fine tune everything, force region, force PU-22+ or not and disable BIOS patching if not needed. So technically we can always have a universal hex file / and suggested fuse settings for a given platform which can be flashed by the user's tool of choice.

Still have to add fuse reading code to make sure that bits are set exactly as we want it.

rama3
Verified
/// PSXDEV | ELITE ///
/// PSXDEV | ELITE ///
Posts: 510
Joined: Apr 16, 2017

Post by rama3 » November 11th, 2018, 3:43 am

I'm undecided what would be best here, but some thoughts:

- automatic BIOS patching:
If it's going to be automatic, then we have to know the logic level for the involved pins.
They will have to be connected either to A18 / D2, or to Gnd / Vcc.
Once this is known, we can look at D2 or A18 for level changes.
As soon as we see one, we can assume BIOS patching is necessary.

The early NTSC patch routine can be within a timeout handler for that.
If there's no level change on A18 / D2, then abort the patch routine before it would go on to disable interrupts.
This way there's no need for a jumper. Just declare the pins must be connected.

Post Reply

Who is online

Users browsing this forum: No registered users and 5 guests