RodCastler Posted June 1, 2014 Share Posted June 1, 2014 (edited) Hi, I was experimenting with the joystick ports and found that the attached program which simply outputs a pin high and then low within a loop, performs very irregular cycles. Frequencies can go from 79Hz to 91Hz to 77Hz, to 88Hz or any value really, while running the same instance. Both irregular in frequency and duty cycle. You can see it for yourself in the oscilloscope image. I also found that TurboBasic XL runs much faster but shows equal inconsistency and also tested an 800XL and 65XE with the same results. I am wondering what causes such irregularity. Is it PIA, is it software or what exactly? Edited June 1, 2014 by RodCastler Quote Link to comment Share on other sites More sharing options...
+Stephen Posted June 1, 2014 Share Posted June 1, 2014 Not sure how the timing is achieved, but this is probably due to irregular DMA overheads, based on the selected graphics mode. Also, seeing that it is a BASIC program, not sure at all how the looping and re-running is achieved. Quote Link to comment Share on other sites More sharing options...
sup8pdct Posted June 2, 2014 Share Posted June 2, 2014 Never use basic for timing like this. Assembly is the only way to go JAMES Quote Link to comment Share on other sites More sharing options...
kenjennings Posted June 2, 2014 Share Posted June 2, 2014 It's not PIA, or the OS. BASIC is just slow. Throw in the DMA overhead for the text mode. More than enough reasons for the inconsistent timing. You might try turning off screen DMA ( POKE 559,0 ) during the test to see how it changes the timing. Other variables: try a faster BASIC. Turbo Basic, or OSS BASIC XL. Quote Link to comment Share on other sites More sharing options...
Rybags Posted June 2, 2014 Share Posted June 2, 2014 Disabling VBlank or at least Stage 2 might help a bit too. POKE 54286,0 or POKE 66,1 But VBlank is just a blip, the screen DMA would be the largest spoiling factor for timing. Onscreen there's around 40% slowdown, offscreen about 8% slowdown. Another problem with Basic timing is that Floating-Point operations can be inconsistent in timing. The best method overall would probably be to use Pokey Timers and an assembly routine. It's the best method for doing waveforms/speech, and allows you to have the screen active and program running normally in the foreground. You still get some jitter but it's only noticable if you're dealing with waveforms over about 4 KHz. 1 Quote Link to comment Share on other sites More sharing options...
thorfdbg Posted June 2, 2014 Share Posted June 2, 2014 (edited) Another problem with Basic timing is that Floating-Point operations can be inconsistent in timing. Given the same input, the floating point routines always take the same time to generate the output. Since in this example no counting is involved and all numbers are constant, the mathpack is innocent. But the factors for the inconsistency have already been given: DMA, and the vertical blank interrupt. Edited June 2, 2014 by thorfdbg Quote Link to comment Share on other sites More sharing options...
Bryan Posted June 2, 2014 Share Posted June 2, 2014 This is why the Atari has things like Pokey timers. You can set an exact interval to toggle the pin, but you have to use a machine language routine to handle the interrupt. Quote Link to comment Share on other sites More sharing options...
RodCastler Posted June 3, 2014 Author Share Posted June 3, 2014 (edited) Thank you all. Interestingly enough, disabling DMA didn't make a big change besides running a bit faster. Still too irregular. What really made the difference was disabling VBlank right after disabling DMA. Almost rock solid frequency. Need the combination of the two. None of these pokes work on its own. They don't even work if one right after the other and had to add a small delay for some reason... Edited June 3, 2014 by RodCastler Quote Link to comment Share on other sites More sharing options...
Rybags Posted June 3, 2014 Share Posted June 3, 2014 (edited) You need the delay since you're disabling the VBlank, it needs to execute once to store the DMA shadow. Weird that you'd get inconsistencies with that example - of course the duty cycle of the wave won't be 50% - the two POKEs will execute fairly quickly but the GOTO suffers from Basic needing to scan from the start of the program to find the target line - although every chance it might be quicker as the POKEs themselves have to convert 2 numbers from BCD to binary. That's the weakness of Basic right there - you can't depend on it for much better than 1/50th or so of a second re timing and even then the control isn't very granular or reliable. Using assembler would cure almost all of the problems - one problem I found though is that the rise time from 0 -> 1 of PORT bits is inconsistent and can take a few cycles, the fall time from 1 -> 0 is almost instant. But that was for triggering scope monitoring of the video signal which requires that accuracy to give you a consistent trace. Edited June 3, 2014 by Rybags 1 Quote Link to comment Share on other sites More sharing options...
russg Posted June 3, 2014 Share Posted June 3, 2014 Thank you all. Interestingly enough, disabling DMA didn't make a big change besides running a bit faster. Still too irregular. What really made the difference was disabling VBlank right after disabling DMA. Almost rock solid frequency. Need the combination of the two. None of these pokes work on its own. They don't even work if one right after the other and had to add a small delay for some reason... Don't know if you want. But here's my effort of your BASIC program in assembler. 10 *= $0600 20 LDA #48 30 STA $D302 40 LDA #255 50 STA $D300 60 LDA #0 70 STA $22F 80 LDX #255 90 DELAY1 0100 STX $650 0110 DEX 0120 BNE DELAY1 0130 LDX #255 0140 DELAY2 0150 DEX 0160 BNE DELAY2 0170 LDA #0 0180 STA $D40E 0190 CYCLE 0200 LDA #8 0210 STA $D300 0220 LDA #4 0230 STA $D300 0240 JMP CYCLE 0250 *= $2E0 0260 .BYTE 0,6 0270 .END And a DOS 2.5 .ATR with ASM Editor and the source .ASM file.. And the .OBJ executable, RESET to exit. INOUT.zip 1 Quote Link to comment Share on other sites More sharing options...
Xuel Posted June 3, 2014 Share Posted June 3, 2014 Maybe you could even do this to speed it up a little more and give it closer to a 50% duty cycle: ldx #4 ldy #8 loop stx $D300 ; 4 cycles lda $00 ; 3 cycles nop sty $D300 ; 4 cycles jmp loop ; 3 cycles Though, you'd want to have a loop timed with the RAM refresh cycles taken into account for ultimate control. 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.