irq (Interrupt Requests)

Hardware interrupt manager from libugba.

Note

Importing this module will automatically enable interrupts and set up the master ISR.

Example:

import natu/[video, graphics, irq]

proc onVBlank() =
  # Copy palette buffers into PAL RAM:
  flushPals()
  
  # Do other updates to VRAM and video registers here.
  # ...

# Enable vblank interrupt and register our handler:
irq.put(iiVBlank, onVBlank)

Types

type IrqIndex = enum

IRQ indices, used to enable/disable and register handlers for interrupts.

Each interrupt fires at a particular moment.

  • iiVBlankAt the start of the VBlank period (when the LCD has finished updating)
  • iiHBlankAt the start of the HBlank period (when a scanline on the LCD has finished updating)
  • iiVCountWhen vcount matches dispstat.vcountTrigger
  • iiTimer0When timer 0 overflows.
  • iiTimer1When timer 1 overflows.
  • iiTimer2When timer 2 overflows.
  • iiTimer3When timer 3 overflows.
  • iiSerialOn serial transfer complete.
  • iiDma0When DMA channel 0 completes a transfer.
  • iiDma1When DMA channel 1 completes a transfer.
  • iiDma2When DMA channel 2 completes a transfer.
  • iiDma3When DMA channel 3 completes a transfer.
  • iiKeypadWhen any or all of the keys in keycnt are held.
  • iiGamepakWhen the game pak is removed.
type IrqIndices = set[IrqIndex]

Interrupt Management

proc put(irqId: IrqIndex, handler: FnPtr)

Enable an interrupt, and register a handler for it.

If the interrupt already has a handler it will be replaced.

proc delete(irqId: IrqIndex)

Disable an interrupt, and remove its handler.

proc enable(irqId: IrqIndex)

Enable an interrupt.

proc disable(irqId: IrqIndex)

Disable an interrupt.


I/O Registers

Note

The registers are exposed directly, but for most purposes you don’t need to worry about them as the IRQ management procs above can take care of everything.

var ie: IrqIndices

“Interrupt Enable” register.

Setting a bit allows an interrupt to be received. But nothing will happen unless the relevant bit to request the interrupt is also set, e.g. dispcnt.vblankIrq = true.

Note

irq.put or irq.enable will take care of this for you.

var `if`: IrqIndices

“Interrupt Flags” register.

When an interrupt occurs, the corresponding bit in if will be set.

Once the interrupt has been handled, it is acknowledged by setting the bit again (even though it’s already set)! After doing so, the bit will be automatically cleared by the hardware.

Note

The master ISR will take care of this for you.

var ime: bool

“Interrupt Master Enable” register.

Setting this to false will disable all interrupts.

Note

This is automatically set to true when the module is initialised, and temporarily set to false while one of your handlers is being called.

Setting ime = true within a handler will allow that handler to be interrupted by another interrupt. i.e. nested interrupts are supported.

var ifbios: IrqIndices

“BIOS Interrupt Flags” register.

In addition to the if register, this must be acknowledged in order to wake up from the IntrWait and VBlankIntrWait system calls.

Note

The master ISR will take care of this for you.

var isr: FnPtr

Contains the address of the master interrupt service routine.