Danjovic Posted March 6, 2022 Share Posted March 6, 2022 I am working on the SNES function for my homebrew joystick tester and two bars are appearing on the sides of the screen (see attached picture) I have tracked down the problem to the instruction rol INPT5 and can I think of a workaround, but I could not understand why do this would affect the TIA (at least in Stella emulator). Any thoughts? asm lda #$0 ; 2 clock down, latch down sta SWCHA ; 4 make both latch and clock down ldx #$01 ; 2 clock up, latch down ldy #16 ; 2 16 bits lda #$ff ; 2 Initialize with no button pressed sta snesButtonsL ; 5 if necessary to gain a few microseconds sta snesButtonsH ; 5 from latch/clk down till first bit sample lda #$0 ; 2 SMPSN0: rol INPT5 ; 5 sample data stx SWCHA ; 5 clock up ror snesButtonsL ; 5 take some time assume ror snesButtonsH ; 5 sta SWCHA ; 4 clock down dey ; 2 next bit bne SMPSN0 ; 2 repeat stx SWCHA ; 5 clock up, next edge to read 17th bit rol INPT5 ; 5 sample data, 17th bit on Carry rol bit17 ; 5 temp1 bit 0 contains 17th bit value. should be zero for SNES lda #$03 ; 2 both clock and latch up sta SWCHA ; 5 finish sampling end Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted March 6, 2022 Share Posted March 6, 2022 Aren't INPT4 and INPT5 read-only ports? The rol instruction will attempt to write data to these. Is that what you want? I've not had a close look at your code, sorry. 1 Quote Link to comment Share on other sites More sharing options...
+splendidnut Posted March 6, 2022 Share Posted March 6, 2022 The ROL is a read-modify-write instruction, so you're reading from INPT5 (address $0D) and then writing to PF0 (address $0D). 1 Quote Link to comment Share on other sites More sharing options...
Danjovic Posted March 6, 2022 Author Share Posted March 6, 2022 Thanks ! that should explain the vertical bars, but I went down on another rabbit hole, lol!! My workaround was to read the INPT5 to register A, then rotate register A, but it did not worked the way I expected because I came across a really strange behavior, probably in the emulation. Let me explain better ( reducing the code to a minimum) : First the code without the workaround. At the end of execution the state of the snesButton variables will follow the state of the fire button input, as expected because I am shifting in the logic state of the fire button. for the button released snesButtonsL ; = %11111111 snesButtonsH ; = %11111111 for the button pressed snesButtonsL ; = %00000000 snesButtonsH ; = %00000000 lda #$c3 ; initialize sta snesButtonsL ; = %11000011 sta snesButtonsH ; = %11000011 SMPSN0: rol INPT5 ; ror snesButtonsL ; ror snesButtonsH ; dey ; bne SMPSN0 ; On the other hand, with my workaround, no matter the state of the fire button input I always have the outputs like only one shift was performed, just once snesButtonsL ; = %10000111 snesButtonsH ; = %11000010 lda #$c3 ; initialize sta snesButtonsL ; = %11000011 sta snesButtonsH ; = %11000011 SMPSN0: lda INPT5 ; WORKAROUND rol a ;rol INPT5 ; commented ror snesButtonsL ; ror snesButtonsH ; dey ; bne SMPSN0 ; The most bizarre is that the state of these variables won't be different even if I do something like this lda #$c3 ; initialize sta snesButtonsL ; = %11000011 sta snesButtonsH ; = %11000011 SMPSN0: lda, #$ff rol a ror snesButtonsL ; ror snesButtonsH ; dey ; bne SMPSN0 ; This behaviour is teh same on either Stella and Z26.. Quote Link to comment Share on other sites More sharing options...
Danjovic Posted March 6, 2022 Author Share Posted March 6, 2022 Well at the end I wrote the sampling routine in Basic. __sampleSNES rem initialize ports SWCHB{2} = 0 : rem disable transistors Q6 (for 7800) SWCHB{4} = 0 : rem disable transistors Q5 (for 7800) SWACNT = 3 : rem enable pins UP/DOWN to work as outputs SWCHA = 3 : rem make pins clock (UP) and latch (DOWN) to go high rem sample first 8 bits temp1 = 8 __sampleH SWCHA = 0 : rem latch down, clock down snesButtonsH = snesButtonsH * 2 if !joy1fire then snesButtonsH{0} = 1 SWCHA = 1 : rem latch down, clock up (next bit) temp1 = temp1 - 1 if temp1 > 0 then goto __sampleH rem sample next 8 bits temp1 = 8 __sampleL SWCHA = 0 : rem latch down, clock down snesButtonsL = snesButtonsL * 2 if !joy1fire then snesButtonsL{0} = 1 SWCHA = 1 : rem latch down, clock up (next bit) temp1 = temp1 - 1 if temp1 > 0 then goto __sampleL rem sample 17th bit __bit17 if !joy1fire then bit17{7} = 1 else bit17{7} = 0 SWCHA = 3 : rem latch up, clock up return Quote Link to comment Share on other sites More sharing options...
RevEng Posted March 7, 2022 Share Posted March 7, 2022 18 hours ago, Danjovic said: [...] On the other hand, with my workaround, no matter the state of the fire button input I always have the outputs like only one shift was performed, just once [...] If you were running this code within bB, "a" is actually a defined symbol that references some ZP memory. If that's the case, using just "rol" (implicitly referencing the accumulator) instead of "rol a" would do what you want. 1 Quote Link to comment Share on other sites More sharing options...
Danjovic Posted March 7, 2022 Author Share Posted March 7, 2022 3 hours ago, RevEng said: If that's the case, using just "rol" (implicitly referencing the accumulator) instead of "rol a" would do what you want. Thanks!! I will try that!! 1 Quote Link to comment Share on other sites More sharing options...
Danjovic Posted March 19, 2022 Author Share Posted March 19, 2022 Hi @RevEng, I have tested the code with rol and it worked fine on emulator, thanks! On the other hand, it did not worked on the real console either with the assembly code or with the Basic code. I should investigate it further with the aid of an oscilloscope. 1 Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted March 19, 2022 Share Posted March 19, 2022 2 hours ago, Danjovic said: Hi @RevEng, I have tested the code with rol and it worked fine on emulator, thanks! On the other hand, it did not worked on the real console either with the assembly code or with the Basic code. I should investigate it further with the aid of an oscilloscope. Binaries that work in emulators but not on hardware are valuable for emulator authors to improve emulator accuracy. Have you checked it on the Gopher emulator? If not, possibly worth doing so. I would be happy to check, if you wish - I'd need a binary. 1 Quote Link to comment Share on other sites More sharing options...
Danjovic Posted March 19, 2022 Author Share Posted March 19, 2022 (edited) In fact I was dumb enough to plug the cable in the left port instead of the right port! On the go, I have captured some insteresting waveforms: The SNES reading pulses, followed by two of the row selection pulses to read the keyboard Yellow is CLOCK (UP) and blue is LATCH (DOWN) The whole SNES sampling time, marked by LATCH signal low, takes 426us. There are 17 rising edges on the clock signal, 12 for the buttons and the last 5 for reading the ID of the controller (to allow its detection) The keyboard is read every frame (16.7ms, rounded to 17 by the resolution of the scope cursor) One thing that makes me wonder. As the duration of the LATCH signal coincides with the waiting required to read the POT lines (~400us) it should be possible to use some optimization to gain some machine cycles by using the following algorithm: ROW123 LOW Wait400us read FIRE, POT1, POT2 ROW123 HIGH ROW456 ->LOW SAMPLE SNES CONTROLLER read FIRE, POT1, POT2 ROW456 ->HIGH ROW789 LOW Wait400us read FIRE, POT1, POT2 ROW789 HIGH ROW*0# LOW Wait400us read FIRE, POT1, POT2 ROW*0# HIGH @Andrew Davie, here follows the source code and the binary. I am still working on the detection logic. JK2tester.basJK2tester.bas.binkeyread.asm Edited March 19, 2022 by Danjovic added a missing file Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted March 19, 2022 Share Posted March 19, 2022 (edited) 1 hour ago, Danjovic said: @Andrew Davie, here follows the source code and the binary. I am still working on the detection logic. Had a quick look in Gopher. 267 scanlines is rather unusual. This will be unsuitable for a PAL TV. It "ran" on all my emulators and hardware (harmony cart, NTSC console) - I see a screen as shown... So I'm not sure what you meant by "not working"; I thought you meant you got nothing at all... Edited March 19, 2022 by Andrew Davie Quote Link to comment Share on other sites More sharing options...
Danjovic Posted March 19, 2022 Author Share Posted March 19, 2022 1 hour ago, Andrew Davie said: So I'm not sure what you meant by "not working"; I thought you meant you got nothing at all.. Ok... a bit of context.... "not working" was a reference to a previous post where I used the "rol a" instruction on the inline assembly code to shift in the data sent by the SNES controller, but Mike pointed me out that Batari Basic will take the "a" as the predefined variable and therefore I should use the implicit form of the rotation instruction "rol". After doing that I was able to visualize on the emulator that the bits have been properly shifted in, by press "F" to emulate the 2nd trigger line on Stella. I have then burned a EPROM and started to test the code on the real hardware, but plugged the cable by mistake on the left port instead of the right port and it looked like the code was not reading the button line. 2 hours ago, Andrew Davie said: It "ran" on all my emulators and hardware (harmony cart, NTSC console) - I see a screen as shown... To use the program press START and the program will read the difficulty keys as well as the Black/White switch to decide which combination of keyboard and controller should be tested. With the color mode switch on position COLOR: Difficulty A means Joystick, B means Keyboard controller. While the color mode switch set to B/W you enter the SNES test mode on right port, regardless of the state of Difficulty switches. Some screenshots and more info here: https://hackaday.io/project/183582-wolf/log/204102-custom-atari-2600-test-cart 2 hours ago, Andrew Davie said: 267 scanlines is rather unusual. This will be unsuitable for a PAL TV. I am using a standard kernel plus an inline routine on the vblank to scan the keyboard controllers. I can't tell if the extra scanlines are being caused by such routine. I suppose we should have 263 scanlines, right ? Can you point me a clue to fix that ? Thanks! Quote Link to comment Share on other sites More sharing options...
bogax Posted March 19, 2022 Share Posted March 19, 2022 (edited) On 3/6/2022 at 12:36 PM, Danjovic said: Thanks ! that should explain the vertical bars, but I went down on another rabbit hole, lol!! My workaround was to read the INPT5 to register A, then rotate register A, but it did not worked the way I expected because I came across a really strange behavior, probably in the emulation. Let me explain better ( reducing the code to a minimum) : First the code without the workaround. At the end of execution the state of the snesButton variables will follow the state of the fire button input, as expected because I am shifting in the logic state of the fire button. for the button released snesButtonsL ; = %11111111 snesButtonsH ; = %11111111 for the button pressed snesButtonsL ; = %00000000 snesButtonsH ; = %00000000 lda #$c3 ; initialize sta snesButtonsL ; = %11000011 sta snesButtonsH ; = %11000011 SMPSN0: rol INPT5 ; ror snesButtonsL ; ror snesButtonsH ; dey ; bne SMPSN0 ; On the other hand, with my workaround, no matter the state of the fire button input I always have the outputs like only one shift was performed, just once snesButtonsL ; = %10000111 snesButtonsH ; = %11000010 lda #$c3 ; initialize sta snesButtonsL ; = %11000011 sta snesButtonsH ; = %11000011 SMPSN0: lda INPT5 ; WORKAROUND rol a ;rol INPT5 ; commented ror snesButtonsL ; ror snesButtonsH ; dey ; bne SMPSN0 ; The most bizarre is that the state of these variables won't be different even if I do something like this lda #$c3 ; initialize sta snesButtonsL ; = %11000011 sta snesButtonsH ; = %11000011 SMPSN0: lda, #$ff rol a ror snesButtonsL ; ror snesButtonsH ; dey ; bne SMPSN0 ; This behaviour is teh same on either Stella and Z26.. no idea what you're doing.. shouldn't the SMPSN0: be after the lda? also do you know what the carry is at that point? (may not matter) edit oh hell I just realized what you're doing. never mind (I'll go back to sleep now) Edited March 19, 2022 by bogax 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.