Hey guys, I would like to learn how to program my own interrupt routines. I do not have much experience in assembly (I read TI in 28 Days until Interrupts) but the example does not work in debuggers.
I have also tried it on my own calculator and it works fine... Is there anything wrong with this code?

Code:
.nolist
#include "ti83plus.inc"
#define    ProgStart    $9D95
time .EQU AppBackUpScreen ;1 Byte
.list
.org    ProgStart - 2 ;-2 wegen den beiden tokens
.db    t2ByteTok, tAsmCmp   


INTRPT_MASK   .EQU   %00001011

    b_call(_ClrLCDFull)

    DI                     ; Turn interrupts off until we're ready

; Load interrupt address vectors
    LD     HL, interrupt
    LD     ($993F), HL
    LD     ($997F), HL
    LD     ($99BF), HL
    LD     ($99FF), HL

    LD     A, $99
    LD     I, A

    LD     A, INTRPT_MASK   ; Enable hardware
    OUT    (3), A

    IM     2               ; Switch to Mode 2
    EI                     ; Activate interrupts

; GetKey and GetCSC only function in Mode 1,
; so gotta use the key port.
    LD     A, %10111111
    OUT    (1), A

KeyLoop:
    IN     A, (1)
    CP     %01111111       ; If [DEL] pressed, exit
    JR     NZ, KeyLoop

    LD     A, %00001011     ; Enable hardware
    OUT    (3), A
    IM     1               ; Calculator needs Mode 1
    RET

interrupt:
    EX     AF, AF'
    EXX
    XOR     A              ; Disable hardware
    OUT    (3), A

    LD     HL, 0
    LD     (CurRow), HL
    LD     HL, (counter)
    INC    HL
    LD     (counter), HL
    b_call(_DispHL)

    LD     A, INTRPT_MASK   ; Enable hardware
    OUT    (3), A
    EX     AF, AF'
    EXX
    EI
    RET

counter:
    .DW    $0000
   
.end
Unfortunately, thought ASM in 28 Days is a great tutorial, it makes a lot of mistakes with interrupts. I've been meaning to rewrite the interrupts Day in the guide for a long time, but sadly I've never quite had the time to get around to it.

Anyway, one of the main problems is that you need to set a full 256-byte range $9A00 to $9B00, not just $993F, $997F, $99BF, and $99FF. For example, the CALCnet interrupt in Doors CS does this:


Code:
   ld a,$9a
   ld i,a
   ld h,a
   ld l,0
   ld (hl),$99
   push hl
   pop de
   inc de
   ld bc,256
   ldir
Then your interrupt can go at $9999.
thank you Wink
I'm gonna try it soon^^
CakeOfDestruction wrote:
thank you Wink
I'm gonna try it soon^^
Glad to hear it. Smile I'd be happy to explain more about how the code is supposed to work and how to troubleshoot it. If you're playing with interrupts, I also recommend taking a look at the PindurTI emulator if you plan to do a lot of interrupt work, as it is more accurate with ports and interrupts than WabbitEmu.
KermMartian wrote:
Unfortunately, thought ASM in 28 Days is a great tutorial, it makes a lot of mistakes with interrupts. I've been meaning to rewrite the interrupts Day in the guide for a long time, but sadly I've never quite had the time to get around to it.

Just a plug for my initiative. If you ever get the time to do so, I'd love to include it in the update.
KermMartian wrote:
Anyway, one of the main problems is that you need to set a full 256-byte range $9A00 to $9B00, not just $993F, $997F, $99BF, and $99FF.


<pedantic>Isn't that a 257-byte range?</pedantic> <duck />

A couple years ago I tested the IM2 behavior on the TI-86 and found that the lower byte in the vector address was always zero, so I wanted to save space and time by filling out only the first two bytes of the vector table. Unfortunately, I found out (from someone else who happened to do similar research a few months before me) that it depends on the specific hardware. Some would set it to 00 every time, others would set it to an apparently random value, and still others might set it to one of a small number of values (which might be what 83pa28d is basing its information on). The safest is to set 257 bytes to the same value, as Kerm said.
Can somebody explain me, why the interrupt is randomly choosen?
I do not understand the sense. Why are these values defined by chance?
(Sorry for my english...)

€dit: Hopefully I am able to describe my question more clearly...
The lower 8 Bits of the "interrupt-jump-table" is randomly choosen. But why did the engineers built it this way?

€dit2: How do I know that the RAM Area from $9900 to $9A01 and $9A9A (my interrupt) isn't used by TI-OS?
The vector for IM2 is effectively random on these calculators because we're using it in a way it wasn't intended to be used.

In mode 2, an external device causes an interrupt and puts a byte on the data bus. This byte is taken as the low byte of a vector (combined with I). Diagram taken from the Z80 User's Manual:

Since these calculators weren't meant to ever use mode 2, nothing puts vectors on the data bus when triggering interrupts, so the exact value is effectively random. In the worst case, the vector would be dependent on what was executing when the interrupt is triggered.

christop wrote:
<pedantic>Isn't that a 257-byte range?</pedantic> <duck />
Per the Z80 user's manual:
Quote:
A CPU reset clears the I register so that it is initialized to zero. The lower eight bits of the pointer must be supplied by the interrupting device. Only seven bits are required from the interrupting device because the least-significant bit must be a zero.
Maybe I'm wrong and it works fine even with a random value for bit zero, though, which may what we have to work with.
Quote:
The lower 8 Bits of the "interrupt-jump-table" is randomly choosen. But why did the engineers built it this way?
The intention is that a hardware device on the z80's bus would supply its own address when it triggered an interrupt. This would allow various devices, like mice, keyboards, network devices, etc to all generate interrupts, and by putting a unique identifier on the bus, jump to a different interrupt handler based on which hardware device had generated that interrupt. However, because for us the contents of the bus at interrupt time are effectively random, we need to have the same address at every word from $II00 to $IIFF.

Quote:
€dit2: How do I know that the RAM Area from $9900 to $9A01 and $9A9A (my interrupt) isn't used by TI-OS?
Firstly, because my own interrupt for CALCnet uses those areas, but also because of these notes from the dcs7.inc file:


Code:
;----> Safe Memory Areas
; saferam1 = 768 bytes (APDRAM)
; saferam2 = 531 bytes (statRAM)
; saferam3 = 128 bytes (textMem)
; saferam4 = 66 bytes (OpXs)
; saferam5 = 10 bytes (iMathPtrs)

saferam1   =9872h
saferam2   =8A3Ah
saferam3   =8508h
saferam4   =8478h
saferamp   =9872h
saferamp2   =8251h


SafeRAM1, being 768 bytes, goes from $9872 to $9B72.
But which device does trigger the timer-interrupt? Does this device not access the data bus?

@Tari Thank you al lot for this Picture. Now I think I'm able to write an alghorithm without copying the whole interrupt (because of the null).
TI's helper ASIC connected to the CPU triggers the timer interrupt. As far as we're aware, it leaves the data bus however it was when the interrupt triggered, so it could contain anything.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement