Log inRegister an accountBrowse CSDbHelp & documentationFacts & StatisticsThe forumsAvailable RSS-feeds on CSDbSupport CSDb Commodore 64 Scene Database
You are not logged in - nap
CSDb User Forums


Forums > C64 Coding > Raster X position.
2012-01-26 19:51
Flavioweb

Registered: Nov 2011
Posts: 463
Raster X position.

From VIC article:
Quote:

As the LP input of the VIC is connected to the keyboard matrix as are all
lines of the joystick ports, it can also be controlled by software. This is
done with bit 4 of port B of CIA A ($dc01/$dc03). This allows to determine
the current X position of the raster beam by triggering an LP edge and
reading from LPX afterwards (the VIC has no register that would allow
reading the X position directly). This can e.g. be used to synchronize
raster interrupt routines on exact cycles.


What means?
I can write some code to know exactly where raster is in his X position?
Something like: raster irq trigger -> irq routine -> wait for X raster position -> start do someting...

Is it possible?
There are some assembly examples somewhere?
 
... 11 posts hidden. Click here to view all posts....
 
2012-01-28 11:54
Flavioweb

Registered: Nov 2011
Posts: 463
during my experiments with stable raster i reached a good level having a stable raster, of course with less cycles availables, also on badline.
Usually i use the timer method to stabilize it, but when i tried to make a multicolor bg line just using 3 inc $d021 in a irq stable, i noticed that starting the same routine many times, the multicolor line start at different positions.
The difference is about 8 pixel, so i think is only 1 cycle in plus or minus.
This is caused into the init part of my routine and could be just when cia timer is initialized.
I tried to solve this problem using the 'force dma' trick to stabilize the code of cia init and have reached a quite perfect situation where first cycles of irq routine start about in same x position into rasterline.
'about' because there is this cycle delay and i searching for a method to detect and compensate it.
Is just for my skill improvement. The irp routine is stable and works for all normal applications.
2012-01-28 12:33
JackAsser

Registered: Jun 2002
Posts: 2014
To use a timer for stabilization u first need another way of raster beam synkronization to init the timer properly. Using a timer with count 63 will implicitly give u raster x pos, given the timer was synced when inited.
2012-01-28 14:01
Flavioweb

Registered: Nov 2011
Posts: 463
Quote: To use a timer for stabilization u first need another way of raster beam synkronization to init the timer properly. Using a timer with count 63 will implicitly give u raster x pos, given the timer was synced when inited.

...and this is the problem!
Where raster beam is EXACTLY when init countdown start or end? The irq is stable but starting from different x position.
2012-01-28 14:01
Flavioweb

Registered: Nov 2011
Posts: 463
Quote: To use a timer for stabilization u first need another way of raster beam synkronization to init the timer properly. Using a timer with count 63 will implicitly give u raster x pos, given the timer was synced when inited.

...and this is the problem!
Where raster beam is EXACTLY when init countdown start or end? The irq is stable but starting from different x position.
2012-01-28 15:54
JackAsser

Registered: Jun 2002
Posts: 2014
Quote: ...and this is the problem!
Where raster beam is EXACTLY when init countdown start or end? The irq is stable but starting from different x position.


What the timer does is to help remove cpu jitter, it has nothing to do with raster position. You will need to stabalize the raster using some other method before launching the timer, f.e. by d012 polling or via the double raster irq method etc.
2012-01-28 19:24
Flavioweb

Registered: Nov 2011
Posts: 463
Quote: What the timer does is to help remove cpu jitter, it has nothing to do with raster position. You will need to stabalize the raster using some other method before launching the timer, f.e. by d012 polling or via the double raster irq method etc.

- start first timer to avoid jitter ( 0 - 8 cycles )
- start second timer (63 cycles to be in sync with raster)
- fire irq
- check first timer and compensate jitter
- wait second timer X value and do what do to at X position
- exit irq

ok?

But how we can know where X time of second timer is in X raster position?

During the SAME execution X will be always the same because is a stable and sync irq...
But if you restart the routine, the second initialization (63 cycles) will come on a different X position of raster beam...
So we are in sync but at one different position.

If we check raster position with:

lda #rasterline ; 2 cycles
cmp $d012 ; 4 cycles
bne *-3 ; 3 cycles (2 if not taken)

and rasterline change just after the "cmp" instruction, we need to wait 3 (bne taken) + 4 (cmp absolute) + 2 (bne not taken) = 9 cycles before start the 63 cycles sync timer.
If rasterline change just after "lda" we wait only 4+2 = 6 cycles delay.
The difference from first and second case is "3 cycles" that translate in "pixels" mean about 24 point of difference.
And this because we are doing the "sync" just after raster line change.
If we don't check this, the sync will go absolutely at a random X position...
This is "stable", but -randomly- stable and not stable at -one and always one- fixed position.


2012-01-28 21:37
Copyfault

Registered: Dec 2001
Posts: 478
Quoting Flavioweb
[...]
If we check raster position with:

lda #rasterline ; 2 cycles
cmp $d012 ; 4 cycles
bne *-3 ; 3 cycles (2 if not taken)

and rasterline change just after the "cmp" instruction, we need to wait 3 (bne taken) + 4 (cmp absolute) + 2 (bne not taken) = 9 cycles before start the 63 cycles sync timer.
If rasterline change just after "lda" we wait only 4+2 = 6 cycles delay.
The difference from first and second case is "3 cycles" that translate in "pixels" mean about 24 point of difference.
And this because we are doing the "sync" just after raster line change.
If we don't check this, the sync will go absolutely at a random X position...
This is "stable", but -randomly- stable and not stable at -one and always one- fixed position.

You can get rid of this "random X position" e.g. by doing the $d012-check several times with a suitable number of waiting cycles between each check (this is the socalled "$d012-polling" already mentioned by JA).

pseudo-code would look like this:

lda #ras_pos
cmp $d012 ;if equal on read access the real X position can be 0..8
bne *-3

[wait 54 cycles so next $d012-read access will be exactly 62 cycles after previous $d012-read access]

lda #ras_pos+1
cmp $d012 ;real X position on read access can be "-1"..7
bne *+2 ;if not equal to ras_pos+1 we're still in line ras_pos so will add a cycle by branching to next opcode

[wait 54 cycles so next $d012-read access will be either 62 cycles after previous $d012 acess or exactly 63 cycles]

lda #ras_pos+2
cmp $d012
bne *+2

[...and so on until...]

lda #ras_pos+8
cmp $d012 ;here the read access will be exactly at X position=0 of line ras_pos+8

[now delay cycles to define the wanted X position and make sure the 63-cycles-timer will start exactly on this cycle]


Voila: the timer will always give you the correct position relative to the one defined on line ras_pos+8

Ofcourse the waiting cycles can be arranged in a more clever way so you don't need nine lines in total to get rid of jitter (e.g. "variance halfing") but I hope the pseudo code above shows the general idea.
2012-01-28 21:38
chatGPZ

Registered: Dec 2001
Posts: 11386
you should read the "auxiliary timer" article by marko makäla (in C=Hacking, it should be linked on codebase). its for vic20, but translates to c64 quite well.

as jackasser said you have to do two things:

a) sync to the screen and then start a timer that counts 63 cycles. i usually do that by disabling interrupts and display, use the polling method, and start the timer. others prefer to use double irq. doesnt really matter at all, just make sure the timer starts running at a defined x positon

b) in your interrupt, every time you want to re-sync, read the timer and then delay according to timer value (usually done by modifying a branch that points into a nop cascade)
2012-01-29 07:01
Flavioweb

Registered: Nov 2011
Posts: 463
Quoting Copyfault

You can get rid of this "random X position" ...
pseudo-code would look like this:

cmp $d012 ;if equal on read access the real X position can be 0..8

...

cmp $d012 ;real X position on read access can be "-1"..7

...

lda #ras_pos+2
cmp $d012
bne *+2

[...and so on until...]

lda #ras_pos+8
cmp $d012 ;here the read access will be exactly at X position=0 of line ras_pos+8

[now delay cycles to define the wanted X position and make sure the 63-cycles-timer will start exactly on this cycle]


Voila: the timer will always give you the correct position relative to the one defined on line ras_pos+8


As you write: "if equal on read access the real X position can be...".
Then: how do you know if "is equal on read access"?

And again, the code:

lda #ras_pos+2 ; 2
cmp $d012 ; 4
bne *+3 ; 2 or 3

add at least 6 cycles.

First irq -> jitter 0...8
Wait for N rasterline and if rasterline change after "cmp" instruction, the opcode after "bne" is executed with 9 cycles delay. Otherwise after 6.

So we now are into X position form 0 to 9 at line N.

Wait 62 cycles and execute:

lda #ras_pos+2 ; 2
cmp $d012 ; 4
bne *+2 ; 2 or 3

and also if we are on correct rasterline we add 6 cycles.

Now we are in a possible (0...9) + 62 + 6 or 7 position from previous rasterline...

How can i know how many time execute the loop ending with "bne *+2" if i don't know the inital jitter?
Anyway this loop add at least 6 cycles after the "62" waited to reach next rasterline so, after 8 execution, we are 6x8=48 cycles late... ad if we are always on correct line!

...or i missed something?
2012-01-30 07:31
Copyfault

Registered: Dec 2001
Posts: 478
Let's fix the following 'polling1_done'-position in the pseudo code:

polling_loop
lda #ras_pos
cmp $d012
bne *-3
polling1_done
<opcode>

Asuming that we operate only on non-badline without sprites and that all IRQs are turned off it is clear that the opcode placed at _1st_line is read between raster cycle 3 to 11 depending on when raster line "ras_pos" was reached during the polling loop.

Having exactly 62 waiting cycles between each read access of the "cmp $d012"-commands ensures that in the next polling loop the read cycle will be exactly one cycle earlier:

polling2
lda #ras_pos+1
cmp $d012 ;read access between cycle#62@line"ras_pos" to cycle#7@line"ras_pos+1"
bne polling2_done
polling2_done
<opcode>

The "bne polling2_done" will only be taken if the read access of "cmp $d012" was still on line ras_pos. If so we have to waste one cycle to make sure to be on line ras_pos+1. Thus the opcode at "polling2_done" is read between cycle 3 to 10.

Continuing in this fashion you can eliminate one jitter cycle per polling. Take the time and keep track of the possbile raster cycle position for a fixed position in the polling loops to fully get the idea. Feel free to PM if smth remains unclear.
Previous - 1 | 2 | 3 - Next
RefreshSubscribe to this thread:

You need to be logged in to post in the forum.

Search the forum:
Search   for   in  
All times are CET.
Search CSDb
Advanced
Users Online
Scrap/Genesis Project
Dr. Doom/RAD
Guests online: 95
Top Demos
1 Next Level  (9.7)
2 13:37  (9.7)
3 Mojo  (9.7)
4 Coma Light 13  (9.6)
5 Edge of Disgrace  (9.6)
6 What Is The Matrix 2  (9.6)
7 The Demo Coder  (9.6)
8 Uncensored  (9.6)
9 Comaland 100%  (9.6)
10 Wonderland XIV  (9.6)
Top onefile Demos
1 No Listen  (9.6)
2 Layers  (9.6)
3 Cubic Dream  (9.6)
4 Party Elk 2  (9.6)
5 Copper Booze  (9.6)
6 Dawnfall V1.1  (9.5)
7 Rainbow Connection  (9.5)
8 Onscreen 5k  (9.5)
9 Morph  (9.5)
10 Libertongo  (9.5)
Top Groups
1 Performers  (9.3)
2 Booze Design  (9.3)
3 Oxyron  (9.3)
4 Triad  (9.3)
5 Censor Design  (9.3)
Top Webmasters
1 Slaygon  (9.6)
2 Perff  (9.6)
3 Sabbi  (9.5)
4 Morpheus  (9.4)
5 CreaMD  (9.1)

Home - Disclaimer
Copyright © No Name 2001-2024
Page generated in: 0.048 sec.