gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > Problem with interrupt processing

#122713 - Phantaseur - Wed Mar 21, 2007 1:30 pm

I'm trying to catch a button pressing but for some reason irq processing function cannot be called.
Code:
#include <nds.h>
#include <stdio.h>

void on_irq();

int main(void){
videoSetMode(0);
videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE);
vramSetBankC(VRAM_C_SUB_BG);
SUB_BG0_CR = BG_MAP_BASE(31);

BG_PALETTE_SUB[255] = RGB15(31,31,31);

consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(31), (u16*)CHAR_BASE_BLOCK_SUB(0), 16);

printf("Waiting for keys\n");

REG_IME = 0;
IRQ_HANDLER = on_irq;
REG_IE = IRQ_KEYS;
REG_IF = ~0;
REG_IME = 1;

while(1);
return(0);
}

void on_irq(){
   if(REG_IF&IRQ_KEYS){
   printf("Key pressed\n");
   VBLANK_INTR_WAIT_FLAGS |= IRQ_VBLANK;
   REG_IF |= IRQ_VBLANK;
   }
}

I think the label ,,Key pressed'' have to appear after I press any button but it never appears. What's wrong in this code?

#122716 - tepples - Wed Mar 21, 2007 1:42 pm

You need to turn on an interrupt at both the source and the REG_IE. Think of it as like hooking up two ends of a cable. In this case, you forgot to set up REG_KEYCNT.

Another thing: Don't use the |= operator with REG_IF. Instead, assign directly to it with the = operator.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#122721 - Phantaseur - Wed Mar 21, 2007 3:12 pm

I do not completely understand mechanism of interruptions; I didn't find any complete description of its working and I just copied code from some tutorial hoping that I'll understand it later. Now I just added REG_KEYCNT=~0, but I do not know what need I to do with REG_IE?

#122724 - Diddl - Wed Mar 21, 2007 3:21 pm

tepples wrote:
Another thing: Don't use the |= operator with REG_IF. Instead, assign directly to it with the = operator.



why? whats the reason?

#122753 - tepples - Wed Mar 21, 2007 7:43 pm

Diddl wrote:
tepples wrote:
Another thing: Don't use the |= operator with REG_IF. Instead, assign directly to it with the = operator.

why? whats the reason?

You should not use read-modify-write operators such as |= on REG_IF because it can cause you to miss other interrupts. you should read REG_IF only once in the interrupt service routine. For each bit you set to 1 in REG_IF, you acknowledge a corresponding interrupt. The following code:
Code:
REG_IF |= something;

has identical meaning to the following code:
Code:
{
  int temp = REG_IF;
  temp = temp | something;
  REG_IF = temp;
}

That will read REG_IF an additional time, and the value written back will acknowledge all pending interrupts, including other interrupts that were asserted between when you first read REG_IF and when you re-read REG_IF.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#122755 - Diddl - Wed Mar 21, 2007 8:19 pm

ah, thanks.

#123272 - Phantaseur - Mon Mar 26, 2007 10:08 pm

tepples wrote:
You need to turn on an interrupt at both the source and the REG_IE. Think of it as like hooking up two ends of a cable. In this case, you forgot to set up REG_KEYCNT.

I do not understand what means ''turn on an interrupt at both the source and the REG_IE'', please, tell me what I have to do for getting result....

#123274 - tepples - Mon Mar 26, 2007 10:32 pm

Every interrupt on the GBA or DS has a source and a destination. The source makes interrupts; the destination (REG_IE) receives them. Both must be turned on, or the interrupt will not fire. The source for vblank, hblank, and vcount interrupts is REG_DISPSTAT. The source for timer interrupts is the timer registers. And the source for key interrupts is REG_KEYCNT.

If you add the following line after your existing line "REG_IME = 0;", you set the key interrupt source to make an interrupt for every keypress:
Code:
  REG_KEYCNT = KEY_A | KEY_B | KEY_SELECT | KEY_START
               | KEY_RIGHT | KEY_LEFT | KEY_UP | KEY_DOWN
               | KEY_R | KEY_L
               | 0x4000;

You do get multiple interrupts when a button bounces. If this matters, set up your logic to take bouncing into account by filtering out presses of buttons that the main loop regards as already down.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#123721 - Phantaseur - Fri Mar 30, 2007 4:34 pm

How it have to look? Like this?
Code:
#include <nds.h>
#include <stdio.h>

void on_irq();

int main(void){
videoSetMode(0);
videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE);
vramSetBankC(VRAM_C_SUB_BG);
SUB_BG0_CR = BG_MAP_BASE(31);

BG_PALETTE_SUB[255] = RGB15(31,31,31);

consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(31), (u16*)CHAR_BASE_BLOCK_SUB(0), 16);

printf("Waiting for keys\n");

REG_IME = 0;
REG_KEYCNT = KEY_A | KEY_B | KEY_SELECT | KEY_START\
      | KEY_RIGHT | KEY_LEFT | KEY_UP | KEY_DOWN\
      | KEY_R | KEY_L\
      | 0x4000;
IRQ_HANDLER = on_irq;
REG_IE = IRQ_KEYS;
REG_IF = ~0;
REG_IME = 1;

while(1);
return(0);
}

void on_irq(){
int temp;
   if(REG_IF&IRQ_KEYS){
   printf("Key pressed\n");
   VBLANK_INTR_WAIT_FLAGS |= IRQ_VBLANK;
   temp = REG_IF;
   temp = temp | IRQ_VBLANK;
   REG_IF = temp;
   //REG_IF |=  IRQ_VBLANK;
   }
}

It doesn't work...
Something else missed?

#123940 - Phantaseur - Sun Apr 01, 2007 9:15 pm

I know that interraptions is most simple and basic idea, and without it I can create no serious programs. I know how I can use it but I cannot understand how to create proper code. Now I want working example of program which interrupts cycle ''while(1);'' when key pressed.
Does anybody can show me such code which is suitable for last version of devkitpro?

#123942 - Lick - Sun Apr 01, 2007 10:04 pm

Code:
int main() {
  irqInit();
  irqSet(IRQ_VBLANK, 0);
  irqEnable(IRQ_VBLANK);

  while(1) {
    scanKeys();
    if(keysHeld())
      break;
    swiWaitForVBlank();
  }
}


Why not simply use libnds' IRQ functions? They're A) more reliable, B) clean and easy.
_________________
http://licklick.wordpress.com