This is a work in progress of my IM2 routines for z88dk and could be used for reference for assembly use.
I use the z88dk ability to auto create a Z80 interrupt table as a desired location and assign functions.
There is some assembly used in creating the interrupt table, here is an example
/* interrupt.asm */
SECTION interrupt_vectors
; device vector id 0PUBLIC _vid_ctc_0EXTERN _isr_ctc_0_vid_ctc_0:defw _isr_ctc_0
; device vector id 1PUBLIC _vid_ctc_1EXTERN _isr_ctc_1_vid_ctc_1:defw _isr_ctc_1
; device vector id 2PUBLIC _vid_ctc_2EXTERN _isr_ctc_2_vid_ctc_2:defw _isr_ctc_2
; device vector id 3PUBLIC _vid_ctc_3EXTERN _isr_ctc_3_vid_ctc_3:defw _isr_ctc_3
; device vector id 4PUBLIC _vid_pio_0_aEXTERN _isr_pio_0_a_vid_pio_0_a:defw _isr_pio_0_a
; device vector id 5PUBLIC _vid_pio_0_bEXTERN _isr_pio_0_b_vid_pio_0_b:defw _isr_pio_0_b
; skip vectors 4 through 126defs 120Some examples of the code in the C portion, in the compile settings I set the start of the Interrupt table at 0x0100:
// define our interrupt routines to call
extern void isr_ctc_0(void);extern void isr_ctc_1(void);extern void isr_ctc_2(void);extern void isr_ctc_3(void);
extern void isr_pio_0_a(void);extern void isr_pio_0_b(void);
int main( ){
int ctc0_int_0 = 0; // example of a flag I set when for example CTC-0 sends the interrupt__asm ld hl, (0x100) ld (_add_isr),hl // Just for test to see memory location of first interrupt routine in the table ld a, 0x01 // Here we set the upper 8-bit address of the interrupt table. ld i, a // load Z80 interrupt register i im 2 // Interrupt mode ei // Enable Interrupts
__endasm;
// CTC low byte interrupt is set by writing to CTC 0
z80_outp( 0x20, 0x00); // You can only set CTC_0 vector for all four channels and lower three bits of reserved so table must always be in order of CTC_0, CTC_1, CTC_2, CTC_3, CTC is at start of table 0x0100, CTC automatically add the channel that has reach count // 0x0100 = CTC_0, 0x0102 = CTC_1, CTC_2 = 0x0104, CTC_3 = 0x0106
}
void isr_ctc_0(void) // Basic interrupt routine format for C routines called by interrupt{__asm
push ix push hl di ld hl,0x0001 ld (_ctc0_int_0),hl // Write a one to my variable flag to show interrupt was called, but you would put your service routine here for other actions. pop hl pop ix ei reti
__endasm; }
z88dk compile file example and flags:
Build file
#!/bin/bash
export PATH=/home/eric/projects/z88dk/bin:$PATH // location of z88dkexport ZCCCFG=/home/eric/projects/z88dk/lib/config
zcc +z80 -m -g -s --max-allocs-per-node2000 -SO3 -startup=1 -clib=sdcc_iy interrupt.asm Hyundai_256x128.c z80_pio.c $1.c -o $1 -lm -create-app -pragma-include:simz80.inc --c-code-in-asm // Compiler settings and files to include
scp $1.bin pi@192.168.7.2:/home/projects/z80_host // Write file to my Z80 interface to load code into the Z80 RAM
*simz80.inc* extra compiler flags and settings
#pragma output CRT_ORG_CODE = 0#pragma output CRT_INCLUDE_PREAMBLE = 0#pragma output CRT_ORG_DATA = 0x2000 // start of RAM#pragma output CRT_MODEL = 1#pragma output REGISTER_SP = 0x4000 // Top of RAM#pragma output CRT_STACK_SIZE = 256#pragma output CLIB_MALLOC_HEAP_SIZE = 0#pragma output CLIB_STDIO_HEAP_SIZE = 0#pragma output CRT_ORG_VECTOR_TABLE = -0x100#pragma output CRT_ENABLE_RST = 0x80#pragma output CRT_ENABLE_EIDI = 0x03#pragma output CRT_INTERRUPT_MODE = 0