Browse Source

machine, runtime/interrupt: switch to use register definitions from device/gba

Signed-off-by: deadprogram <ron@hybridgroup.com>
pull/3566/head
deadprogram 2 years ago
committed by Ayke
parent
commit
383e7ae14a
  1. 42
      src/machine/machine_gameboyadvance.go
  2. 94
      src/runtime/interrupt/interrupt_gameboyadvance.go

42
src/machine/machine_gameboyadvance.go

@ -3,8 +3,9 @@
package machine
import (
"device/gba"
"image/color"
"runtime/interrupt"
"runtime/volatile"
"unsafe"
)
@ -16,40 +17,37 @@ const deviceName = "GBA"
// Interrupt numbers as used on the GameBoy Advance. Register them with
// runtime/interrupt.New.
const (
IRQ_VBLANK = interrupt.IRQ_VBLANK
IRQ_HBLANK = interrupt.IRQ_HBLANK
IRQ_VCOUNT = interrupt.IRQ_VCOUNT
IRQ_TIMER0 = interrupt.IRQ_TIMER0
IRQ_TIMER1 = interrupt.IRQ_TIMER1
IRQ_TIMER2 = interrupt.IRQ_TIMER2
IRQ_TIMER3 = interrupt.IRQ_TIMER3
IRQ_COM = interrupt.IRQ_COM
IRQ_DMA0 = interrupt.IRQ_DMA0
IRQ_DMA1 = interrupt.IRQ_DMA1
IRQ_DMA2 = interrupt.IRQ_DMA2
IRQ_DMA3 = interrupt.IRQ_DMA3
IRQ_KEYPAD = interrupt.IRQ_KEYPAD
IRQ_GAMEPAK = interrupt.IRQ_GAMEPAK
IRQ_VBLANK = gba.IRQ_VBLANK
IRQ_HBLANK = gba.IRQ_HBLANK
IRQ_VCOUNT = gba.IRQ_VCOUNT
IRQ_TIMER0 = gba.IRQ_TIMER0
IRQ_TIMER1 = gba.IRQ_TIMER1
IRQ_TIMER2 = gba.IRQ_TIMER2
IRQ_TIMER3 = gba.IRQ_TIMER3
IRQ_COM = gba.IRQ_COM
IRQ_DMA0 = gba.IRQ_DMA0
IRQ_DMA1 = gba.IRQ_DMA1
IRQ_DMA2 = gba.IRQ_DMA2
IRQ_DMA3 = gba.IRQ_DMA3
IRQ_KEYPAD = gba.IRQ_KEYPAD
IRQ_GAMEPAK = gba.IRQ_GAMEPAK
)
// Make it easier to directly write to I/O RAM.
var ioram = (*[0x400]volatile.Register8)(unsafe.Pointer(uintptr(0x04000000)))
// Set has not been implemented.
func (p Pin) Set(value bool) {
// do nothing
}
var Display = FramebufDisplay{(*[160][240]volatile.Register16)(unsafe.Pointer(uintptr(0x06000000)))}
var Display = FramebufDisplay{(*[160][240]volatile.Register16)(unsafe.Pointer(uintptr(gba.MEM_VRAM)))}
type FramebufDisplay struct {
port *[160][240]volatile.Register16
}
func (d FramebufDisplay) Configure() {
// Write into the I/O registers, setting video display parameters.
ioram[0].Set(0x03) // Use video mode 3 (in BG2, a 16bpp bitmap in VRAM)
ioram[1].Set(0x04) // Enable BG2 (BG0 = 1, BG1 = 2, BG2 = 4, ...)
// Use video mode 3 (in BG2, a 16bpp bitmap in VRAM) and Enable BG2
gba.DISP.DISPCNT.Set(gba.DISPCNT_BGMODE_3<<gba.DISPCNT_BGMODE_Pos |
gba.DISPCNT_SCREENDISPLAY_BG2_ENABLE<<gba.DISPCNT_SCREENDISPLAY_BG2_Pos)
}
func (d FramebufDisplay) Size() (x, y int16) {

94
src/runtime/interrupt/interrupt_gameboyadvance.go

@ -5,37 +5,13 @@ package interrupt
// This is good documentation of the GBA: https://www.akkit.org/info/gbatek.htm
import (
"runtime/volatile"
"unsafe"
)
const (
IRQ_VBLANK = 0
IRQ_HBLANK = 1
IRQ_VCOUNT = 2
IRQ_TIMER0 = 3
IRQ_TIMER1 = 4
IRQ_TIMER2 = 5
IRQ_TIMER3 = 6
IRQ_COM = 7
IRQ_DMA0 = 8
IRQ_DMA1 = 9
IRQ_DMA2 = 10
IRQ_DMA3 = 11
IRQ_KEYPAD = 12
IRQ_GAMEPAK = 13
)
var (
regInterruptEnable = (*volatile.Register16)(unsafe.Pointer(uintptr(0x4000200)))
regInterruptRequestFlags = (*volatile.Register16)(unsafe.Pointer(uintptr(0x4000202)))
regGlobalInterruptEnable = (*volatile.Register16)(unsafe.Pointer(uintptr(0x4000208)))
"device/gba"
)
// Enable enables this interrupt. Right after calling this function, the
// interrupt may be invoked if it was already pending.
func (irq Interrupt) Enable() {
regInterruptEnable.SetBits(1 << uint(irq.num))
gba.INTERRUPT.IE.SetBits(1 << uint(irq.num))
}
var inInterrupt bool
@ -43,10 +19,10 @@ var inInterrupt bool
//export handleInterrupt
func handleInterrupt() {
inInterrupt = true
flags := regInterruptRequestFlags.Get()
flags := gba.INTERRUPT.IF.Get()
for i := 0; i < 14; i++ {
if flags&(1<<uint(i)) != 0 {
regInterruptRequestFlags.Set(1 << uint(i)) // acknowledge interrupt
gba.INTERRUPT.IF.Set(1 << uint(i)) // acknowledge interrupt
callInterruptHandler(i)
}
}
@ -62,34 +38,34 @@ func callHandlers(num int)
func callInterruptHandler(id int) {
switch id {
case IRQ_VBLANK:
callHandlers(IRQ_VBLANK)
case IRQ_HBLANK:
callHandlers(IRQ_HBLANK)
case IRQ_VCOUNT:
callHandlers(IRQ_VCOUNT)
case IRQ_TIMER0:
callHandlers(IRQ_TIMER0)
case IRQ_TIMER1:
callHandlers(IRQ_TIMER1)
case IRQ_TIMER2:
callHandlers(IRQ_TIMER2)
case IRQ_TIMER3:
callHandlers(IRQ_TIMER3)
case IRQ_COM:
callHandlers(IRQ_COM)
case IRQ_DMA0:
callHandlers(IRQ_DMA0)
case IRQ_DMA1:
callHandlers(IRQ_DMA1)
case IRQ_DMA2:
callHandlers(IRQ_DMA2)
case IRQ_DMA3:
callHandlers(IRQ_DMA3)
case IRQ_KEYPAD:
callHandlers(IRQ_KEYPAD)
case IRQ_GAMEPAK:
callHandlers(IRQ_GAMEPAK)
case gba.IRQ_VBLANK:
callHandlers(gba.IRQ_VBLANK)
case gba.IRQ_HBLANK:
callHandlers(gba.IRQ_HBLANK)
case gba.IRQ_VCOUNT:
callHandlers(gba.IRQ_VCOUNT)
case gba.IRQ_TIMER0:
callHandlers(gba.IRQ_TIMER0)
case gba.IRQ_TIMER1:
callHandlers(gba.IRQ_TIMER1)
case gba.IRQ_TIMER2:
callHandlers(gba.IRQ_TIMER2)
case gba.IRQ_TIMER3:
callHandlers(gba.IRQ_TIMER3)
case gba.IRQ_COM:
callHandlers(gba.IRQ_COM)
case gba.IRQ_DMA0:
callHandlers(gba.IRQ_DMA0)
case gba.IRQ_DMA1:
callHandlers(gba.IRQ_DMA1)
case gba.IRQ_DMA2:
callHandlers(gba.IRQ_DMA2)
case gba.IRQ_DMA3:
callHandlers(gba.IRQ_DMA3)
case gba.IRQ_KEYPAD:
callHandlers(gba.IRQ_KEYPAD)
case gba.IRQ_GAMEPAK:
callHandlers(gba.IRQ_GAMEPAK)
}
}
@ -107,9 +83,9 @@ type State uint8
// as you called Disable (this happens naturally with the pattern above).
func Disable() (state State) {
// Save the previous interrupt state.
state = State(regGlobalInterruptEnable.Get())
state = State(gba.INTERRUPT.PAUSE.Get())
// Disable all interrupts.
regGlobalInterruptEnable.Set(0)
gba.INTERRUPT.PAUSE.Set(0)
return
}
@ -119,7 +95,7 @@ func Disable() (state State) {
// cricital sections.
func Restore(state State) {
// Restore interrupts to the previous state.
regGlobalInterruptEnable.Set(uint16(state))
gba.INTERRUPT.PAUSE.Set(uint16(state))
}
// In returns whether the system is currently in an interrupt.

Loading…
Cancel
Save