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.
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.
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:
@ -738,3 +740,16 @@ rrestore()
read_flags()
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!
The result value(s) of a subroutine are returned on the evaluation stack,
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 {
const ubyte boardOffsetX = 14
@ -52,7 +59,9 @@ waitkey:
if_z goto waitkey
if key>='1' and key<='7' {
; select block type
; select block type, reset to start pos
xpos = startXpos
ypos = startYpos
drawBlock(xpos, ypos, 32)
blocklogic.newCurrentBlock(key-'1')
drawBlock(xpos, ypos, 160)
@ -202,52 +211,55 @@ waitkey:
ubyte[16] currentBlock
ubyte[16] rotated
; block colors I, J, L, O, S, T, Z: cyan, blue, orange, yellow, green, purple, red
ubyte[7] blockColors = [3, 6, 8, 7, 5, 4, 2]
ubyte[4] blockI = [4, 5, 6, 7] ; note: special rotation (only 2 states)
ubyte[4] blockJ = [0, 4, 5, 6]
ubyte[4] blockL = [2, 4, 5, 6]
ubyte[4] blockO = [1, 2, 5, 6] ; note: no rotation (square)
ubyte[4] blockS = [1, 2, 4, 5]
ubyte[4] blockT = [1, 4, 5, 6]
ubyte[4] blockZ = [0, 1, 5, 6]
; the 7 tetrominos
ubyte[16] blockI = [0,0,0,0, ; cyan ; note: special rotation (only 2 states)
3,3,3,3,
0,0,0,0,
0,0,0,0]
ubyte[16] blockJ = [6,0,0,0, ; blue
6,6,6,0,
0,0,0,0,
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) {
memset(currentBlock, len(currentBlock), 0)
currentBlockNum = block
; @todo would be nice to have an explicit pointer type to reference the array, and code the loop only once...
ubyte blockCol = blockColors[block]
ubyte i
if block==0 { ; I
for i in blockI
currentBlock[i] = blockCol
}
else if block==1 { ; J
for i in blockJ
currentBlock[i] = blockCol
}
else if block==2 { ; L
for i in blockL
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
}
if block==0
memcopy(blockI, currentBlock, len(currentBlock))
else if block==1
memcopy(blockJ, currentBlock, len(currentBlock))
else if block==2
memcopy(blockL, currentBlock, len(currentBlock))
else if block==3
memcopy(blockO, currentBlock, len(currentBlock))
else if block==4
memcopy(blockS, currentBlock, len(currentBlock))
else if block==5
memcopy(blockT, currentBlock, len(currentBlock))
else if block==6
memcopy(blockZ, currentBlock, len(currentBlock))
}
sub rotateCW() {

View File

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