IRQ interupt

Here you can ask questions or provide insights about how to use efficiently 6502 assembly code on the Oric.
6502man
Private
Posts: 7
Joined: Sun Jan 22, 2006 8:26 pm
Location: Var, France

IRQ interupt

Post by 6502man »

Hello,

Sorry do not write english !!!


Est ce que quelqu'un connaitrait le moyen de generer une interruption IRQ sous Oric version ATMOS ?

Pour l'integrer dans un programme ASM !!!

J'ai beau chercher dans les docs que j'ai, mais j'ai rien trouve ?

Tchao.
User avatar
Euphoric
Game master
Posts: 99
Joined: Mon Jan 09, 2006 11:33 am
Location: France

Post by Euphoric »

Salut, une IRQ c'est une interruption matérielle, donc normalement ça ne se génère pas de façon logicielle...
Sur le 6502, on peut toutefois utiliser l'instruction BRK, qui simule "presque" l'apparition d'une IRQ (la différence est minime: un bit est différent dans les flags sauvés sur la pile). Mais souvent, le code appelé par l'interruption vérifie justement la valeur de ce bit pour savoir s'il s'agit d'une interruption matérielle (IRQ) ou logicielle (BRK), c'est le cas par exemple avec le traitement d'interruption de l'OS Sedoric. Si on veut vraiment provoquer une interruption IRQ, il faut demander à des périphériques de le faire, par exemple on peut programmer un compteur de temps sur le VIA pour qu'il se termine "tout de suite" et provoque ainsi une IRQ...

A+

Fabrice

[ENGLISH]
6502man asks how to generate an IRQ on the Oric...
An IRQ is an hardware interrupt, caused by a peripheral, so normally a program doesn't generate an IRQ. However, the 6502 has a BRK instruction that "nearly" generates an IRQ, only a single bit differs in the saved flags on the stack. So, if the interrupt handler doesn't make the difference, it's ok, but often it does, like does the interrupt handler of the Sedoric OS. In this case, the only way to have an IRQ is to ask a peripheral to generate one, for example you can program a VIA timer to elapse straight away.
6502man
Private
Posts: 7
Joined: Sun Jan 22, 2006 8:26 pm
Location: Var, France

irq

Post by 6502man »

Merci pour la reponse.

Justement comment acceder au VIA en ASM, dans le but de temporiser un programme pour le rendre fluide, par exemple pour un scrolling ?

D'autres part je n'est pas trouve de registre type 'RASTER' sur Oric !

En fait lorsque je code mon prog, je n'est aucun moyen de savoir si je suis en fin de balayage ecran ou non, ce qui n'est pas tres pratique, notamment pour rendre l'affichage fluide.

Car si on n'affiche plus ou moins de choses le processeur prendra donc plus ou moins de cycle a le faire, et on ne pourras pas attendre un balayage ce qui risque de rendre le tous saccade !

Voila.

[English]
Thanks for the answer.
How to access the VIA to temporise a program in order to make it a bit more smoother in the animation, for example in a scrolling ?
I did not found any 'raster' register in the oric.
When I code I have no way to know where I am relatively to the electron beam, so this is very hard to make a smooth display, because depending of what the processor is doing it takes more or less time to do things, and thus looks chopy.
User avatar
Dbug
Site Admin
Posts: 4437
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Post by Dbug »

Salut
Hi

Il n'y a aucun registre sur l'oric permettanr de savoir où se trouve la position du balayage. On peut bidouiller (hardware) entre la prise K7 et la prise péritel pour obtenir l'information, mais ca n'est évidement pas disponible en standard.

There is no register on the oric to know where the electron beam is. We can get this information by hacking with the SCART and TAPE sockets, but obviously it's not something available on all the machines.

De toute façon on ne peut pas non plus faire de double écran, donc l'animation reste problématique a faire proprement même avec la bidouille en question.

Anyway, there is no double buffering on the oric, so geting a clean animation remains a challenge even with such a hack.

Reste le VIA.

L'idée est de programmer un timer pour se déclancher toutes les 1/50ème de seconde. Personnelement moi j'utilise un code similare à celui-ci.

Then we have the VIA.

The idea is to setup a timer to trigger every 1/50th of a second. I use a code similar to that one:


Installation de l'IRQ - Installing IRQ
#define VBLVIA 19968

sei
lda #<VBLVIA
sta $306
lda #>VBLVIA
sta $307

lda #0
sta _VblCounter

lda #<_VBLIrq
sta $0245
lda #>_VBLIrq
sta $0246

cli
La routine d'interruption elle même - The IRQ routine

Code: Select all

_VBLIrq
	bit $304
	inc _VblCounter
	rti
Et la routine de synchronisation - The synchronisation code

Code: Select all

_VSync
loop_wait
	lda _VblCounter
	beq loop_wait
	lda #0
	sta _VblCounter
	rts
C'est pas extremement élégant, mais ca marche.
Par contre je ne suis par sur que 19968 soit la meilleur valeur.

This is not very nice looking, but this works.
Anyway I am not sure that 19968 is the best possible value.
6502man
Private
Posts: 7
Joined: Sun Jan 22, 2006 8:26 pm
Location: Var, France

irq

Post by 6502man »

Merci pour ces precisions.

Je vais tester avec le VIA !

La programation en ASM sur Oric c'est pas des plus pratique!

Bravo pour ce forum, belle initiave !

Tchao.
Last edited by 6502man on Tue Jan 24, 2006 8:24 pm, edited 1 time in total.
User avatar
Euphoric
Game master
Posts: 99
Joined: Mon Jan 09, 2006 11:33 am
Location: France

Post by Euphoric »

Par contre je ne suis par sur que 19968 soit la meilleur valeur.

Anyway I am not sure that 19968 is the best possible value.
19968 = 64*312 is the precise number of cycles of the screen raster.
However, to get an interrupt every 19968 cycles, you must program the VIA timer with a value of 19966, because the VIA adds two cycles to each count (19966, 19965, 19964,.... , 2, 1, 0, -1, 19966, 19965, 19964,...).

Cheers,

Fabrice
User avatar
waskol
Flight Lieutenant
Posts: 414
Joined: Wed Jun 13, 2007 8:20 pm
Location: FRANCE, Paris

Post by waskol »

Hello
How can you manage to include this tip in an animation with the OSDK, in C ?

thank you
User avatar
Dbug
Site Admin
Posts: 4437
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Post by Dbug »

waskol wrote:Hello
How can you manage to include this tip in an animation with the OSDK, in C ?
Ok, you want a simple callback function called every 50th of a second to do something ?

You can already do that using the functions in irq.s:
install_irq_handler
chain_irq_handler
uninstall_irq_handler
User avatar
waskol
Flight Lieutenant
Posts: 414
Joined: Wed Jun 13, 2007 8:20 pm
Location: FRANCE, Paris

Post by waskol »

Dbug wrote:
waskol wrote:Hello
How can you manage to include this tip in an animation with the OSDK, in C ?
Ok, you want a simple callback function called every 50th of a second to do something ?

You can already do that using the functions in irq.s:
install_irq_handler
chain_irq_handler
uninstall_irq_handler
Exactly what I need !
User avatar
Dbug
Site Admin
Posts: 4437
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Post by Dbug »

Actually it's called on the main oric irq, the one that also control the keyboard, sound, etc... so you may want to do something once every two calls, because I think this main timer runs at 100 hz, not 50.
User avatar
waskol
Flight Lieutenant
Posts: 414
Joined: Wed Jun 13, 2007 8:20 pm
Location: FRANCE, Paris

Post by waskol »

Then, the structure of my program should be basically like this :

Code: Select all

void main()
{
install_irq_handler
...
while (animate==1) {
  //Chain twice
  chain_irq_handler;
  chain_irq_handler;
  //Then display next frame
  Display_frame();
}
...

uninstall_irq_handler;
}
am I right ?
User avatar
Chema
Game master
Posts: 3013
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

Post by Chema »

waskol wrote:Then, the structure of my program should be basically like this :

Code: Select all

void main()
{
install_irq_handler
...
while (animate==1) {
  //Chain twice
  chain_irq_handler;
  chain_irq_handler;
  //Then display next frame
  Display_frame();
}
...

uninstall_irq_handler;
}
am I right ?
Maybe I am wrong, surely Dbug can tell, but I think it is not correct.

I suppose install_irq_handler needs a pointer to a function, so it is called every interrupt (@100Hz). chain_irq_handler simply adds another function to the chain, so both are called in order. The call is done by the system (thus they are callbacks), so what you want to do is:

Code: Select all

void animate_frame()
{
  // do whatever
}

main()
{
 install_irq_handler(animate_frame);
 ...
}
This way animate_frame will be called every 100th of a second. If you need it to run at 50Hz, then you should use a static or global variable and use it to check. Simply use a byte (char) and increment it. Check bit 0 (with "and" 0x1, or with a rotation) and if not zero perform animation frame.

However this would run "outside" the control of the main function, so maybe you want this other approach:

Code: Select all

char ticks;
void f()
{
 ticks=1;
}


main()
{
  install_irq_handler(f);

  while (whatever) do
  {
   if (ticks)
   { 
     // run animation
    ticks=0;
   }
  }

}
This way your loop will be running doing nothing until the irq routine signals its activation by setting ticks to 1;

This is a rough approach, of course, as you would need to control if your irq is being called more than once during your animation stage (maybe disable interrupts) or while you are doing other things... A better approach would be having your program stopped until a certain numbers of irq calls are made.

Simply make f do ticks++ and include a wait loop before your animation:

Code: Select all

ticks=0;
// HALT until irq happens NUM_TICKS times
while (ticks<NUM_TICKS){ }
ticks=0;
something like that.

Finaly, chain_irq_handler(f2) would add another function (f2) that will be called after f at each irq.

Cheers
User avatar
waskol
Flight Lieutenant
Posts: 414
Joined: Wed Jun 13, 2007 8:20 pm
Location: FRANCE, Paris

Post by waskol »

off couuuuuuuurrrrrrrrrrrssssssssseeeeeee !!! :lol:
chema, now I understand so many things a bit better with your explanation.

I was wondering if there was any callback event to manage and how to manage it in this case. You gave me the answer I needed to the question I was not able to ask. :wink:
So many thanks.

Now, I will try to experiment a little bit with this
User avatar
Chema
Game master
Posts: 3013
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

Post by Chema »

waskol wrote: chema, now I understand so many things a bit better with your explanation.
Well... thanks. I am not used to hear my explanations are clear :)

Anyway I was just guessing, so many details can be wrong. As I said surely Dbug can bring more light to this.

However managing interrupts is quite tricky IMHO, and I would do it in asm whenever possible (maybe write a small set of routines which can be called from C, such as halt(), which would wait for an interrupt, or halt(char n), to wait for a number of irqs to occur.

Surely people used to work with irqs can help, such as Twilighte or Dbug.

Finaly (again) everything would be marvelous if your program runs continuously doing whatever and updating some variables so that a display() routine performs the animation as an irq callback depending on the value of those variables (and if they changed). They can operate in "paralell" to say it somehow, and the program logic is separated from the visual display matters...

Cheers.
JamesD
Flight Lieutenant
Posts: 358
Joined: Tue Nov 07, 2006 7:38 am

Post by JamesD »

My experience with this type of routine is on other computers but a couple things here...

1. If you can eventually convert you interrupt handler to assembly you'll definitely save some clock cycles.

2. I usually use:

Code: Select all

void f()
{
 ticks++;
}
That way I know if I've missed any ticks doing something time consuming and have to compensate to catch up.
If you are animating something and it moves every so many ticks then you're counter is sure to be accurate and you don't really need to keep count outside the interrupt... just check if ticks > your trigger value.
Post Reply