;--------------------------------------------------------------------------- ; L352.ASM ; ; This program that uses the 8254A timer-0 built into the 80C206 peripheral ; to generate a periodic interrupt at the external interrupt pin, INT0, ; of the 80C188. LED-7 of PC is toggled once with every 20 interrupts. ; Timer-0 interrupts within the 82C206 are turned off after LED-7 is ; toggled 20 times. ; ; ASM code for the SBC188 boards. ; C.P. Diduch, March 1999. ;--------------------------------------------------------------------------- KEY_PC EQU 13CH ; Port Addresses for the 8255A. KEY_CON EQU 13EH ; ; ICW1_MAST EQU 0020H ; Port Addresses for the 82C206 MASTER ICW2_MAST EQU 0021H ; (8259A type) interrupt controller. ICW3_MAST EQU 0021H ; IR0 of the MASTER is connected internally ICW4_MAST EQU 0021H ; to COUNTER 0 of an on-chip 8254A timer. OCW1_MAST EQU 0021H ; OCW2_MAST EQU 0020H ; MAST_TYPE EQU 00F0H ; ; TIMER_CON EQU 0043H ; Addresses of the 82C206 Timer Control TIMER_0 EQU 0040H ; Register and COUNTER 0. ; I0CON EQU 0FF38H ; 80C188XL interrupt control register 0. EOI EQU 0FF22H ; 80C188XL EOI register. I0_TYPE EQU 12 ; 80C188XL INT0 TYPE NO. ; TRUE EQU 1 ; ;--------------------------------------------------------------------------- _DATA segment word public 'DATA' assume cs:_TEXT, ds:_DATA ; Program variables and stack ; DW 10 DUP(?) ; Reserve stack area TOS LABEL WORD ; Top of stack label N DW ? ; int N, M; M DW ? ; ; _DATA ends ; ;--------------------------------------------------------------------------- _TEXT segment para public 'CODE' assume cs:_TEXT, ds:_DATA ; Program code ; ENTRY: cli ; Turn interrupts off. mov ax, _DATA ; Initialize segment registers mov ds, ax ; and so variables & stack are in mov ss, ax ; in segment _DATA, program code is mov sp, offset TOS ; in segment _TEXT. ; mov N, 0 ; N = 0; mov M, 0 ; M = 0; ; mov dx, KEY_CON ; outportb(KEY_CON, 0x92); mov al, 92H ; Initialize PC of 8255A as out dx, al ; a simple O/P port. ; call INT_VECT_INIT ; Initialize interrupt vector table. sti ; Unmask interrupts. call TIMER_8254_INIT ; Init COUNTER 0 for interrupt generation. call INT_CON_INIT ; Initialize interrupt controllers. ; HERE: mov ax, 5000 ; call DELAY ; while(TRUE) { jmp HERE ; delay(5000); ; } ; } and ax, 7FH ; Gracefully return to push ax ; the debug/monitor. xor bx, bx ; mov es, bx ; pushf ; push bx ; push bx ; jmp dword ptr es:[000CH] ; ;--------------------------------------------------------------------------- TIMER_8254_INT_HANDLER proc far push ax ; Save status. push dx ; ; add N, 1 ; N++; cmp N, 20 ; if (N > 20) { jc T0 ; mov dx, KEY_PC ; Toggle LED 7 once every in al, dx ; 20 interrupts. xor al, 80H ; out dx, al ; mov N, 0 ; N = 0; add M, 1 ; if ((M++) > 20) { cmp M, 20 ; jc T0 ; mov dx, OCW1_MAST ; mov al, 0FFH ; outportb(OCW1_MAST, 0xFF) out dx, al ; Mask off interrupts at master mov dx, I0CON; ; & mask off interrupts at INT0. mov ax, 0038H ; outport(I0CON, 0x0038); out dx, ax ; ; } ; } T0: call TIMER_8254_INIT ; Reset timer for another interrupt. mov dx, OCW2_MAST ; mov al, 60H ; outportb(OCW2_MAST, 0x60) out dx, al ; Send specific EOI to MASTER for IR0. ; mov dx, EOI ; mov al, 12 ; outport(EOI, 12) out dx, al ; Send EOI to 80C188XL for INT0. ; pop dx ; Resrore status. pop ax ; iret ; TIMER_8254_INT_HANDLER endp ;--------------------------------------------------------------------------- INT_VECT_INIT proc near ; Initialize interrupt vector table. push ds push bx push ax mov ax, 0 mov ds, ax mov bx, 4*MAST_TYPE mov word ptr [bx], offset TIMER_8254_INT_HANDLER mov word ptr [bx+2], seg TIMER_8254_INT_HANDLER pop ax pop bx pop ds ret INT_VECT_INIT endp ;--------------------------------------------------------------------------- TIMER_8254_INIT proc near ;{ ; Program COUNTER 0 for binary counting and mov dx, TIMER_CON ; mov al, 30H ; outportb(TIMER_CON, 0x30) out dx, al ; interrupt on Terminal Count. mov dx, TIMER_0 ; mov al, 0FFH ; outportb(TIMER_0, 0xFF) out dx, al ; out dx, al ; outportb(TIMER_0, 0xFF) ; Load CNTR0 with 0xFFFF. This will produce ; an INTERRUPT after approx = 30 ms, i.e., ret ; 65535/1.8432 MHz. ;} TIMER_8254_INIT endp ;--------------------------------------------------------------------------- INT_CON_INIT proc near mov dx, ICW1_MAST ; Program master 8259A for level triggered, mov al, 19H ; cascade operation. out dx, al ; ; mov dx, ICW2_MAST ; Program interrupt base type for the mov al, MAST_TYPE ; 8259A MASTER as 0xF0 - 0xF7. out dx, al ; ; mov dx, ICW3_MAST ; Slave controller is connected to IR2. mov al, 04H ; out dx, al ; ; mov dx, ICW4_MAST ; Program MASTER for single and normal EOI. mov al, 01H ; out dx, al ; ; mov dx, OCW1_MAST ; Mask off all MASTER 8259A interrupts. mov al, 0FFH ; out dx, al ; ; mov dx, I0CON ; Program 80C188 INT0 for high level trigger, mov ax, 0031H ; cascade mode, not special function nested mode, out dx, ax ; with priority 000, (highest). ; mov dx, OCW1_MAST ; Unmask IR0 in the MASTER 8259A. mov al, 0FEH ; out dx, al ; ret INT_CON_INIT endp ;--------------------------------------------------------------------------- DELAY proc near cmp ax, 0 jz D3 D0: mov bx, 375; D1: cmp bx, 0 jz D2 sub bx, 1; jmp D1 D2: sub ax, 1 jnz D0 D3: ret DELAY endp _TEXT ends ; end ENTRY ; ENTRY is the label of the first ; instruction of the program.