docs about irq handlers

This commit is contained in:
Irmen de Jong 2019-03-06 22:11:16 +01:00
parent 77dc35dc6a
commit 06f0984fa1
4 changed files with 103 additions and 46 deletions

View File

@ -544,7 +544,9 @@ will issue a warning then telling you the result values of a subroutine call are
subroutines are *non-reentrant*. This means you cannot create recursive calls. subroutines are *non-reentrant*. This means you cannot create recursive calls.
If you do need a recursive algorithm, you'll have to hand code it in embedded assembly for now, If you do need a recursive algorithm, you'll have to hand code it in embedded assembly for now,
or rewrite it into an iterative algorithm. or rewrite it into an iterative algorithm.
Also, subroutines used in the main program should not be used from an IRQ handler. Also, subroutines used in the main program should not be used from an IRQ handler. This is because
the subroutine may be interrupted, and will then call itself from the IRQ handler. Results are
then undefined because the variables will get overwritten.
.. _builtinfunctions: .. _builtinfunctions:
@ -738,3 +740,16 @@ rrestore()
read_flags() read_flags()
Returns the current value of the CPU status register. Returns the current value of the CPU status register.
Library routines
----------------
There are many routines available in the compiler libraries.
Some are used internally by the compiler as well.
There's too many to list here, just have a look through the source code
of the library modules to see what's there.
(They can be found in the compiler/res directory)
The example programs also use a small set of the library routines, you can study
their source code to see how they might be used.

View File

@ -145,3 +145,35 @@ Arguments and result values are passed via global variables stored in memory
*These are not allocated on a stack* so it is not possible to create recursive calls! *These are not allocated on a stack* so it is not possible to create recursive calls!
The result value(s) of a subroutine are returned on the evaluation stack, The result value(s) of a subroutine are returned on the evaluation stack,
to make it possible to use subroutines in expressions. to make it possible to use subroutines in expressions.
IRQ Handling
============
Normally, the system's default IRQ handling is not interfered with.
You can however install your own IRQ handler.
This is possible ofcourse by doing it all using customized inline assembly,
but there are a few library routines available to make setting up C-64 IRQs and raster IRQs a lot easier (no assembly code required).
These routines are::
c64utils.set_irqvec()
c64utils.set_irqvec_excl()
c64utils.set_rasterirq( <raster line> )
c64utils.set_rasterirq_excl( <raster line> )
c64utils.restore_irqvec() ; set it back to the systems default irq handler
If you activate an IRQ handler with one of these, it expects the handler to be defined
as a subroutine ``irq`` in the module ``irq`` so like this::
~ irq {
sub irq() {
; ... irq handling here ...
}
}
.. todo::
@todo the irq handler should use its own eval-stack to avoid stack interference issues

View File

@ -1,3 +1,10 @@
; TehTriz - a Tetris clone.
;
; @todo: hold block.
; @todo: show next 2 blocks instead of just 1.
~ main { ~ main {
const ubyte boardOffsetX = 14 const ubyte boardOffsetX = 14
@ -52,7 +59,9 @@ waitkey:
if_z goto waitkey if_z goto waitkey
if key>='1' and key<='7' { if key>='1' and key<='7' {
; select block type ; select block type, reset to start pos
xpos = startXpos
ypos = startYpos
drawBlock(xpos, ypos, 32) drawBlock(xpos, ypos, 32)
blocklogic.newCurrentBlock(key-'1') blocklogic.newCurrentBlock(key-'1')
drawBlock(xpos, ypos, 160) drawBlock(xpos, ypos, 160)
@ -202,52 +211,55 @@ waitkey:
ubyte[16] currentBlock ubyte[16] currentBlock
ubyte[16] rotated ubyte[16] rotated
; block colors I, J, L, O, S, T, Z: cyan, blue, orange, yellow, green, purple, red ; the 7 tetrominos
ubyte[7] blockColors = [3, 6, 8, 7, 5, 4, 2] ubyte[16] blockI = [0,0,0,0, ; cyan ; note: special rotation (only 2 states)
ubyte[4] blockI = [4, 5, 6, 7] ; note: special rotation (only 2 states) 3,3,3,3,
ubyte[4] blockJ = [0, 4, 5, 6] 0,0,0,0,
ubyte[4] blockL = [2, 4, 5, 6] 0,0,0,0]
ubyte[4] blockO = [1, 2, 5, 6] ; note: no rotation (square) ubyte[16] blockJ = [6,0,0,0, ; blue
ubyte[4] blockS = [1, 2, 4, 5] 6,6,6,0,
ubyte[4] blockT = [1, 4, 5, 6] 0,0,0,0,
ubyte[4] blockZ = [0, 1, 5, 6] 0,0,0,0]
ubyte[16] blockL = [0,0,8,0, ; orange
8,8,8,0,
0,0,0,0,
0,0,0,0]
ubyte[16] blockO = [0,7,7,0, ; yellow ; note: no rotation (square)
0,7,7,0,
0,0,0,0,
0,0,0,0]
ubyte[16] blockS = [0,5,5,0, ; green
5,5,0,0,
0,0,0,0,
0,0,0,0]
ubyte[16] blockT = [0,4,0,0, ; purple
4,4,4,0,
0,0,0,0,
0,0,0,0]
ubyte[16] blockZ = [2,2,0,0, ; red
0,2,2,0,
0,0,0,0,
0,0,0,0]
; @todo would be nice to have a pointer type, like so:
; uword[7] blocks = [&blockI, &blockJ, &blockL, &blockO, &blockS, &blockT, &blockZ]
sub newCurrentBlock(ubyte block) { sub newCurrentBlock(ubyte block) {
memset(currentBlock, len(currentBlock), 0)
currentBlockNum = block currentBlockNum = block
if block==0
; @todo would be nice to have an explicit pointer type to reference the array, and code the loop only once... memcopy(blockI, currentBlock, len(currentBlock))
ubyte blockCol = blockColors[block] else if block==1
ubyte i memcopy(blockJ, currentBlock, len(currentBlock))
if block==0 { ; I else if block==2
for i in blockI memcopy(blockL, currentBlock, len(currentBlock))
currentBlock[i] = blockCol else if block==3
} memcopy(blockO, currentBlock, len(currentBlock))
else if block==1 { ; J else if block==4
for i in blockJ memcopy(blockS, currentBlock, len(currentBlock))
currentBlock[i] = blockCol else if block==5
} memcopy(blockT, currentBlock, len(currentBlock))
else if block==2 { ; L else if block==6
for i in blockL memcopy(blockZ, currentBlock, len(currentBlock))
currentBlock[i] = blockCol
}
else if block==3 { ; O
for i in blockO
currentBlock[i] = blockCol
}
else if block==4 { ; S
for i in blockS
currentBlock[i] = blockCol
}
else if block==5 { ; T
for i in blockT
currentBlock[i] = blockCol
}
else if block==6 { ; Z
for i in blockZ
currentBlock[i] = blockCol
}
} }
sub rotateCW() { sub rotateCW() {

View File

@ -5,8 +5,6 @@
; @todo see problem in looplabelproblem.p8 ; @todo see problem in looplabelproblem.p8
; @todo gradle fatJar should include the antlr runtime jar
sub start() { sub start() {
uword w = 12345 uword w = 12345