#undef SLOWCLOCK ; Defined if we are running slow
#undef NOPRINT ; Defined to turn off printing
; library.asm must be first!
#include "library.asm"
#include "stdio.asm"
#include "string.asm"
PIC_COMMAND EQU 08000H
NUMKEY EQU 08001H
PICBYTE EQU 08003H
SHIFT_STATUS EQU 08004H
CTRL_STATUS EQU 08005H
ALT_STATUS EQU 08006H
UPKEY_FLAG EQU 08007H
CURRENT_CMD EQU 08008H
CURRENT_ADDR EQU 08009H ; two bytes
CURRENT_LEN EQU 0800BH
CURRENT_PTR EQU 0800CH ; point into CURRENT_CMD
SHOULD_RUN EQU 0800DH
KEYBUF EQU 0A000H
INPUT_BUF EQU 0C000H
OUTPUT_BUF EQU 0C040H
LSHIFT_KEY EQU 012H
RSHIFT_KEY EQU 059H
CTRL_KEY EQU 014H
ALT_KEY EQU 011H
UP_KEY EQU 0F0H
EXT_KEY EQU 0E0H
EXT2_KEY EQU 0E1H
PIC_NON_CMD EQU 000H
PIC_SER_CMD EQU 001H
PIC_KBD_CMD EQU 002H
PIC_TIM_CMD EQU 003H
CMD_SEND EQU 001H
CMD_RUN EQU 002H
CMD_MAX EQU 003H ; one past max value of a command
;----------------------------------------
;
; Memory test program
;
MAIN
LD HL, INTROSTR
CALL LCDPRINT
;
; Setup the 8259
;
LD A, 016H ; F = 1, S = 1
OUT (I8259A), A
LD A, 03FH ; Table is at 03F00H
OUT (I8259B), A
LD A, 0F0H ; Enable lower 4 IRQs
OUT (I8259B), A
;
; Initialize our variables
;
LD A, 0
LD (PIC_COMMAND), A
LD (NUMKEY), A
LD (SHIFT_STATUS), A
LD (CTRL_STATUS), A
LD (ALT_STATUS), A
LD (UPKEY_FLAG), A
LD (CURRENT_PTR), A
LD (SHOULD_RUN), A
;
; Read a byte from the pic in case it triggered
; an interrupt before we were ready (keyboard
; reset). This resets the PIC interrupt line.
;
; The command read routine throws away commands it does not understand,
; so it is likely we will get the keyboard init status byte here but the
; command read routine will chuck it and we will catch up on the next byte.
;
IN A, (PIC)
;
; Setup interrupt mode 0
;
IM 0
EI
;
; Go, go, go!
;
PRINTAGAIN
LD HL, PLEASESTR
CALL LCDPRINT
LD HL, INPUT_BUF
CALL GETS
LD HL, HELLOSTR
LD IX, OUTPUT_BUF
CALL STRCPY
LD HL, INPUT_BUF
CALL STRCPY
LD (IX), PAUSE
INC IX
LD (IX), 0
LD HL, OUTPUT_BUF
CALL LCDPRINT
JP PRINTAGAIN
;----------------------------------------
ISR0 ; PIC interrupt
;
; The PIC sends a command byte followed by an
; optional data byte.
;
; Command byte: PIC_SER_CMD
; Data byte: serial byte in ASCII
;
; Command byte: PIC_KBD_CMD
; Data byte: keyboard byte as scan code
;
; Command byte: PIC_TIM_CMD
; Data byte: none
;
; Current command is stored in PIC_COMMAND, which is
; equal to PIC_NON_CMD if we are waiting for a command.
;
PUSH AF
IN A, (PIC)
LD (PICBYTE), A
; START TEST
#if 0
PUSH IX
PUSH HL
PUSH BC
LD IX, OUTPUT_BUF
CALL PHEXBYTE ; Hex A into IX
LD HL, KEYBUF
LD A, (NUMKEY)
LD C, A
LD B, 0
ADD HL, BC ; HL = pointer into buffer
INC A
LD (NUMKEY), A
LD A, (OUTPUT_BUF) ; Key in A
LD (HL), A ; Stick our letter in buffer
LD HL, KEYBUF
LD A, (NUMKEY)
LD C, A
LD B, 0
ADD HL, BC ; HL = pointer into buffer
INC A
LD (NUMKEY), A
LD A, (OUTPUT_BUF+1); Key in A
LD (HL), A ; Stick our letter in buffer
POP BC
POP HL
POP IX
JP ISR0_END
#endif
; END TEST
LD A, (PIC_COMMAND)
CP PIC_NON_CMD ; Cmd not read yet
JP Z, ISR0_IS_COMMAND
CP PIC_SER_CMD
JP Z, ISR0_IS_SERIAL
CP PIC_KBD_CMD
JP Z, ISR0_IS_KEYBOARD
JP ISR0_RESET ; Whoa, bad byte
ISR0_IS_COMMAND
LD A, (PICBYTE)
CP PIC_TIM_CMD ; special case for timer cause no data
JP Z, ISR0_IS_TIMER
LD (PIC_COMMAND), A
JP ISR0_END
ISR0_IS_TIMER
; do something
JP ISR0_RESET
ISR0_IS_SERIAL
CALL HANDLE_SERIAL
JP ISR0_RESET
ISR0_IS_KEYBOARD
CALL HANDLE_KEYBOARD
JP ISR0_RESET
ISR0_RESET
LD A, PIC_NON_CMD
LD (PIC_COMMAND), A
; FALLTHROUGH
ISR0_END
LD A, 020H ; End of Interrupt
OUT (I8259A), A
POP AF
EI
RET
;------------------
HANDLE_SERIAL ; trashes A
PUSH HL
PUSH BC
; we get downloaded programs through serial. handle
; that first. we get one command byte, then two
; address bytes, then a length byte. if the command
; is CMD_SEND, then this header is followed by "length"
; bytes to stick into "address". if the command is
; CMD_RUN, then the length is zero and SHOULD_RUN is
; set to 1, which causes the input routine to jump
; to the address in CURRENT_ADDR.
LD A, (CURRENT_PTR)
CP 3
JP NZ, GET_CMD_HEADER
; just got last byte of header
LD A, (CURRENT_CMD)
CP CMD_RUN
JP NZ, GET_CMD_HEADER
; ignore length and run
LD A, 1
LD (SHOULD_RUN), A
JP END_HANDLE_SERIAL
GET_CMD_HEADER
LD A, (CURRENT_PTR)
CP 4
JP Z, TRANSFER_BYTE
; check if it is not a transfer
CP 0
JP NZ, TRANSFER_HEADER
LD A, (PICBYTE)
CP CMD_MAX
JP P, SIMULATE_KEYBOARD ; >= CMD_MAX
TRANSFER_HEADER
; transfer into the header
LD HL, CURRENT_CMD
LD A, (CURRENT_PTR)
LD C, A
LD B, 0
ADD HL, BC
LD A, (PICBYTE)
LD (HL), A
INC C
LD A, C
LD (CURRENT_PTR), A
JP END_HANDLE_SERIAL
TRANSFER_BYTE
; transfer into RAM
LD HL, (CURRENT_ADDR)
LD A, (PICBYTE)
LD (HL), A
INC HL
LD (CURRENT_ADDR), HL
LD A, (CURRENT_LEN)
DEC A
LD (CURRENT_LEN), A
JP NZ, END_HANDLE_SERIAL
LD (CURRENT_PTR), A
JP END_HANDLE_SERIAL
SIMULATE_KEYBOARD
LD HL, KEYBUF
LD A, (NUMKEY)
LD C, A
LD B, 0
ADD HL, BC ; HL = pointer into buffer
INC A
LD (NUMKEY), A
LD A, (PICBYTE) ; Key in A
LD (HL), A ; Stick our letter in buffer
END_HANDLE_SERIAL
POP BC
POP HL
RET
;------------------
HANDLE_KEYBOARD
PUSH HL
PUSH BC
LD A, (PICBYTE) ; Get the byte
CP UP_KEY ; Key-up is preceded by UP_KEY
JP NZ, NOT_UP_KEY
LD A, 1
LD (UPKEY_FLAG), A
JP END_HANDLE_KEYBOARD
NOT_UP_KEY
CP EXT_KEY ; Extended keys preceded by EXT_KEY
JP Z, DID_KEY ; For now just ignore
CP EXT2_KEY ; Break preceded by EXT2_KEY
JP Z, DID_KEY ; For now just ignore
BIT 7, A ; See if high bit is on
JP NZ, DID_KEY ; Ignore if >= 128
CP LSHIFT_KEY ; See if it is a shift key
JP Z, IS_SHIFT
CP RSHIFT_KEY
JP NZ, NOT_SHIFT
IS_SHIFT
LD A, (UPKEY_FLAG)
XOR 1
LD (SHIFT_STATUS), A
JP DID_KEY
NOT_SHIFT
CP CTRL_KEY ; See if it is a control key
JP NZ, NOT_CTRL
LD A, (UPKEY_FLAG)
XOR 1
LD (CTRL_STATUS), A
JP DID_KEY
NOT_CTRL
CP ALT_KEY ; See if it is an alt key
JP NZ, NOT_ALT
LD A, (UPKEY_FLAG)
XOR 1
LD (ALT_STATUS), A
JP DID_KEY
NOT_ALT
LD L, A ; HL = A
LD H, 0
LD A, (UPKEY_FLAG) ; Ignore all other key ups
CP 1
JP Z, DID_KEY
ADD HL, HL ; HL *= 4
ADD HL, HL
LD B, 0
LD A, (SHIFT_STATUS)
LD C, A
ADD HL, BC
LD A, (CTRL_STATUS)
LD C, A
ADD HL, BC
ADD HL, BC
LD A, (ALT_STATUS)
LD C, A
ADD HL, BC
ADD HL, BC
ADD HL, BC
LD BC, KEY_XLAT ; Translation table
ADD HL, BC
LD A, (HL) ; Get actual key
PUSH AF
LD HL, KEYBUF
LD A, (NUMKEY)
LD C, A
LD B, 0
ADD HL, BC ; HL = pointer into buffer
INC A
LD (NUMKEY), A
POP AF ; Key in A
LD (HL), A ; Stick our ASCII letter in there
DID_KEY
; Reset "up" flag
LD A, 0
LD (UPKEY_FLAG), A
END_HANDLE_KEYBOARD
POP BC
POP HL
RET
;------------------
ISR1
PUSH AF
LD A, 020H ; End of Interrupt
OUT (I8259A), A
POP AF
EI
RET
;------------------
ISR2
PUSH AF
LD A, 020H ; End of Interrupt
OUT (I8259A), A
POP AF
EI
RET
;------------------
ISR3
PUSH AF
LD A, 020H ; End of Interrupt
OUT (I8259A), A
POP AF
EI
RET
;------------------
ISR4
PUSH AF
LD A, 020H ; End of Interrupt
OUT (I8259A), A
POP AF
EI
RET
;------------------
ISR5
PUSH AF
LD A, 020H ; End of Interrupt
OUT (I8259A), A
POP AF
EI
RET
;------------------
ISR6
PUSH AF
LD A, 020H ; End of Interrupt
OUT (I8259A), A
POP AF
EI
RET
;------------------
ISR7
PUSH AF
LD A, 020H ; End of Interrupt
OUT (I8259A), A
POP AF
EI
RET
;----------------------------------------
INTROSTR DB "PIC16C64 test", 10, 0
PLEASESTR DB "Your name?", 10, 0
HELLOSTR DB "Hello ", 0
KEY_XLAT ; Normal, shift, ctrl, alt
DB '?', '?', '?', '?'
DB '9', '9', '9', '9' ; F9
DB '?', '?', '?', '?'
DB '5', '5', '5', '5' ; F5
DB '3', '3', '3', '3' ; F3
DB '1', '1', '1', '1' ; F1
DB '2', '2', '2', '2' ; F2
DB '1', '1', '1', '1' ; F12
DB '?', '?', '?', '?'
DB '1', '1', '1', '1' ; F10
DB '8', '8', '8', '8' ; F8
DB '6', '6', '6', '6' ; F6
DB '4', '4', '4', '4' ; F4
DB 9, 9, 9, 9 ; Tab
DB '`', '~', '`', '`'
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB '?', '?', '?', '?' ; Alt
DB '?', '?', '?', '?' ; Left shift
DB '?', '?', '?', '?'
DB '?', '?', '?', '?' ; Control
DB 'q', 'Q', 17, 17
DB '1', '!', '1', '1'
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB 'z', 'Z', 26, 26
DB 's', 'S', 19, 19
DB 'a', 'A', 1, 1
DB 'w', 'W', 23, 23
DB '2', '@', '2', '2'
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB 'c', 'C', 3, 3
DB 'x', 'X', 24, 24
DB 'd', 'D', 4, 4
DB 'e', 'E', 5, 5
DB '4', '$', '4', '4'
DB '3', '#', '3', '3'
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB ' ', ' ', ' ', ' '
DB 'v', 'V', 22, 22
DB 'f', 'F', 6, 6
DB 't', 'T', 20, 20
DB 'r', 'R', 18, 18
DB '5', '%', '5', '5'
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB 'n', 'N', 14, 14
DB 'b', 'B', 2, 2
DB 'h', 'H', 8, 8
DB 'g', 'G', 7, 7
DB 'y', 'Y', 25, 25
DB '6', '^', '6', '6'
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB 'm', 'M', 13, 13
DB 'j', 'J', 10, 10
DB 'u', 'U', 21, 21
DB '7', '&', '7', '7'
DB '8', '*', '8', '8'
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB ',', '<', ',', ','
DB 'k', 'K', 11, 11
DB 'i', 'I', 9, 9
DB 'o', 'O', 15, 15
DB '0', ')', '0', '0'
DB '9', '(', '9', '9'
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB '.', '>', '.', '.'
DB '/', '?', '/', '/'
DB 'l', 'L', 12, 12
DB ';', ':', ';', ';'
DB 'p', 'P', 16, 16
DB '-', '_', '-', '-'
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB 39, '"', 39, 39 ; Single quote
DB '?', '?', '?', '?'
DB '[', '{', '[', '['
DB '=', '+', '=', '='
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB '?', '?', '?', '?' ; Caps lock
DB '?', '?', '?', '?' ; Right shift
DB 10, 10, 10, 10 ; Enter
DB ']', '}', ']', ']'
DB '?', '?', '?', '?'
DB 92, '|', 92, 92 ; Backslash
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB 8, 8, 8, 8 ; Backspace
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB '1', '1', '1', '1' ; Numeric 1
DB '?', '?', '?', '?'
DB '4', '4', '4', '4' ; Numeric 4
DB '7', '7', '7', '7' ; Numeric 7
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB '?', '?', '?', '?'
DB '0', '0', '0', '0' ; Numeric 0
DB '.', '.', '.', '.' ; Numeric .
DB '2', '2', '2', '2' ; Numeric 2
DB '5', '5', '5', '5' ; Numeric 5
DB '6', '6', '6', '6' ; Numeric 6
DB '8', '8', '8', '8' ; Numeric 8
DB 27, 27, 27, 27 ; Escape
DB '?', '?', '?', '?' ; Num lock
DB '1', '1', '1', '1' ; F11
DB '+', '+', '+', '+' ; Numeric +
DB '3', '3', '3', '3' ; Numeric 3
DB '-', '-', '-', '-' ; Numeric -
DB '*', '*', '*', '*' ; Numeric *
DB '9', '9', '9', '9' ; Numeric 9
DB '?', '?', '?', '?' ; Scroll lock
DB '?', '?', '?', '?'
ORG 03F00H
INTTABLE
; IRQ0
JP ISR0
DB 0
; IRQ1
JP ISR1
DB 0
; IRQ2
JP ISR2
DB 0
; IRQ3
JP ISR3
DB 0
; IRQ4
JP ISR4
DB 0
; IRQ5
JP ISR5
DB 0
; IRQ6
JP ISR6
DB 0
; IRQ7
JP ISR7
DB 0
ORG 04000H
#if 0
; start tmp code
ORG 06000H /* J UMP TO HERE */
#if 0
;this code writes 0-255 in 0x4000 through 0x40ff continuously
DI
LD A, 0
LD HL, 04000H
TEST_WRITE_AGAIN
LD (HL), A
INC A
INC L
JP TEST_WRITE_AGAIN
#endif
LD HL, 07000H
LD A, 0
TEST_AGAIN
PUSH HL
LD (HL), A
LD A, (HL)
LD IX, OUTPUT_BUF
CALL PHEXBYTE
LD (IX), PAUSE
INC IX
LD (IX), 0
LD HL, OUTPUT_BUF
CALL LCDPRINT
#if 0
LD HL, 04000H
LD (HL), 0FFH
LD A, (HL)
LD IX, OUTPUT_BUF
CALL PHEXBYTE
LD (IX), PAUSE
INC IX
LD (IX), 0
LD HL, OUTPUT_BUF
CALL LCDPRINT
#endif
POP HL
INC HL
INC A
JP TEST_AGAIN
; end tmp code
#endif
#if 1
#include "image.asm"
#endif
#if 1
ORG 09000H /* JUMP TO HERE */
#endif
#if 0
/* fill the screen */
LD HL, 16384
LD A, 088H
LOOP_AGAIN_YES
LD (HL), A
INC HL
JP LOOP_AGAIN_YES
DJNZ LOOP_AGAIN_YES
#endif
#if 0
#include "zcc_out.asm"
#include "libc.asm"
#endif
LOOP_FOREVER
JP LOOP_FOREVER
END