Omnimaga

Calculator Community => TI Calculators => ASM => Topic started by: Xeda112358 on October 12, 2011, 05:36:19 pm

Title: Interrupt Questions
Post by: Xeda112358 on October 12, 2011, 05:36:19 pm
Okay, I have this code that is causing a crash for me and I am trying to figure out why:
Code: [Select]
interrupt:
     push af
     push bc
     push de
     push hl
     ld hl,(progPtr)
     push hl
     .db 21h
IprogPtr:
     .dw 0
     ld a,h \ or l
     ld (progPtr),hl
     call nz,ParserNext
EndExec:
     pop hl
     ld (progPtr),hl
     pop hl
     pop de
     pop bc
     pop af
     ret
interrupt_end:
This is for Grammer which is why I am asking. (progPtr) is the program counter and calling ParserNext will parse the data at progPtr.

I also disable interrupts and switch it back to mode 1 before exiting the program in case I need to do that
Title: Re: Interrupt Questions
Post by: Geekboy1011 on October 12, 2011, 05:46:50 pm
Your forgetting to set the interupt mask would be my guess
try tacking this before you restore progptr
Code: [Select]
Xor a
out (3),a
ld a,%00001011 ; this set interupts to go on with hardware timer 1 the on key and the link port
out (3),a

more info on port 3 is here
http://wikiti.brandonw.net/index.php?title=83Plus:Ports:03

hopefully that helps ^_^

Edit:

you may also want to look at port four bits 1 and 2
http://wikiti.brandonw.net/index.php?title=83Plus:Ports:04

used for setting the speed of the hardware timers ^^
Title: Re: Interrupt Questions
Post by: thepenguin77 on October 12, 2011, 08:58:38 pm
Along with Geekboy's suggestion. You also need to reenable interrupts. When the interrupt fires, there is an automatic DI that gets run, so you need to undo it.
Title: Re: Interrupt Questions
Post by: Geekboy1011 on October 12, 2011, 10:04:54 pm
Along with Geekboy's suggestion. You also need to reenable interrupts. When the interrupt fires, there is an automatic DI that gets run, so you need to undo it.

Wow i missed this while reading my own code >.<
Title: Re: Interrupt Questions
Post by: Xeda112358 on October 12, 2011, 10:18:50 pm
Hmm, I have tried these suggestions, but they aren't working. I also notice that whenever I open the debugger in Wabbit, the interrupt is executing. I feel like it might be activating too often. Does the interrupt automatically execute after certain conditions?

EDIT: Here is the installer code:
Code: [Select]
     di
     ld hl,interrupt
     ld de,8A8Ah
     ld bc,interrupt_end - interrupt
     ldir

     ld hl,8000h
     ld de,8001h
     ld bc,256
     ld (hl),8Ah
     ldir

     ld a,80h
     ld i,a
     im 2
It is inline which is why there is no "ei" or "ret" (the ei comes later).
Title: Re: Interrupt Questions
Post by: Geekboy1011 on October 12, 2011, 11:07:54 pm

Code: [Select]
     di
     ld hl,interrupt
     ld de,8A8Ah
     ld bc,interrupt_end - interrupt
     ldir

     ld hl,8000h
     ld de,8001h
     ld bc,257
     ld (hl),8Ah
     ldir
     ld a,%00001011
     out (3),a
     ld a,80h
     ld i,a
     im 2

made a few changes thats the only differences in my code from yours :/ if that doesnt do it idk what it is :/
Title: Re: Interrupt Questions
Post by: calc84maniac on October 12, 2011, 11:09:56 pm
What's your current interrupt routine?
Title: Re: Interrupt Questions
Post by: Xeda112358 on October 12, 2011, 11:11:15 pm
The current one is the one up at the top with the changes suggested.
Title: Re: Interrupt Questions
Post by: calc84maniac on October 12, 2011, 11:17:18 pm
It helps to see the code as it is now, because when interacting with hardware it can be pretty important that everything is done in the right order. Just wanted to make sure.
Title: Re: Interrupt Questions
Post by: Xeda112358 on October 12, 2011, 11:21:55 pm
Okay, well this is the current version that I am toying with. I added some code because it seemed to recursively call itself and I wanted to fix that a little.

Code: [Select]

interrupt:
;     or a \ ret nc
     push af
     push bc
     push de
     push hl
     ld hl,(progPtr)
     push hl
     .db 21h
IprogPtr:
     .dw 0
     ld a,h \ or l
     jr z,EndExec
 jr nz,$
       ld (progPtr),hl
       ld (IprogPtr2),hl
       sbc hl,hl \ ld (IprogPtr),hl
       call ParserNext
       .db 21h
IprogPtr2:
       .dw 0
       ld (IprogPtr),hl
EndExec:
     sub a
     out (3),a
     ld a,%00001011
     out (3),a
     pop hl
     ld (progPtr),hl
     pop hl
     pop de
     pop bc
     pop af
     ei
     ret
interrupt_end:
EDIT: I have the jr nz,$ for debugging puproses
Title: Re: Interrupt Questions
Post by: DrDnar on October 13, 2011, 03:35:35 am
After the call to ParserNext, IprogPtr is never updated. I'm not sure if ParserNext is supposed to advance any pointers, but it certainly won't here. Also, for those of us who don't have the Z80 opcode table memorized, you should add a comment for .db 21h that says ; ld hl, imm16

The only other thing that comes to mind is that you need to make ensure that ParseNext completes quickly or else the main code won't run. Also, make sure that the routine never EIs. Check to make sure the interrupt vector table is correct. And don't even think of running that from flash.
Title: Re: Interrupt Questions
Post by: Xeda112358 on October 13, 2011, 08:41:40 am
After the call to ParserNext, IprogPtr is never updated. I'm not sure if ParserNext is supposed to advance any pointers, but it certainly won't here. Also, for those of us who don't have the Z80 opcode table memorized, you should add a comment for .db 21h that says ; ld hl, imm16

The only other thing that comes to mind is that you need to make ensure that ParseNext completes quickly or else the main code won't run. Also, make sure that the routine never EIs. Check to make sure the interrupt vector table is correct. And don't even think of running that from flash.
Okay, thanks! The call actually takes care of the progPtr stuff and that is working fine, but the routine does in fact use EI, so I will try to work around that.
I have ideas >.>

Thanks much! I will see if this works :)

EDIT: It works! Here is how I fixed it:
In the interrupt, I set a flag and then reset it as it finishes
In the program code, whenever I need to EI, I check that flag first to see if it is okay
And it works now :) I am now executing Grammer code as an interrupt that updates the LCD

Is there a better way to check if an interrupt is currently executing? I am pretty sure I saw a way, so I will check.
Title: Re: Interrupt Questions
Post by: DrDnar on October 13, 2011, 02:04:52 pm
You can check whether interrupts are enabled, but there's a bug in the Z80:
# If a LD A,I or LD A,R (which copy IFF2 to the P/V flag) is interrupted, then the P/V flag is reset, even if interrupts were enabled beforehand.
Title: Re: Interrupt Questions
Post by: Xeda112358 on October 13, 2011, 02:06:07 pm
Is there a way to check if an interrupt is currently being executed, though?
Title: Re: Interrupt Questions
Post by: Geekboy1011 on October 13, 2011, 02:13:37 pm
easiest way i can think of is to just set a flag at the start of hte interupt and reset it at the end? you might be able to do something with a port to check though i forget :/
Title: Re: Interrupt Questions
Post by: Xeda112358 on October 13, 2011, 02:16:12 pm
Yeah, I am currently setting a flag to do it, but that takes up more memory. I was thinking of setting or resetting the upper bit of the r register and using the s flag in some way.
Title: Re: Interrupt Questions
Post by: Geekboy1011 on October 13, 2011, 02:22:03 pm
well if you are succsesfully masking the bits on port 3 and 4 you can probably just check port 4 to see if a interrupt is running. i think im reading the wiki page right.