Merge branch 'master' of ichibi:/home/git/Repositories/pato-z80-home-computer
This commit is contained in:
77
assembly/os/drivers/arduino_terminal.asm
Normal file
77
assembly/os/drivers/arduino_terminal.asm
Normal file
@ -0,0 +1,77 @@
|
||||
; Arduino terminal driver
|
||||
; @author Daniele Verducci
|
||||
|
||||
; config (IO port 0)
|
||||
TERM_DATA_REG: EQU IO_0
|
||||
TERM_DATA_AVAIL_REG: EQU IO_0 + 1
|
||||
|
||||
; variables
|
||||
TERM_VAR_SPACE: EQU DRV_VAR_SPACE + 128
|
||||
incoming_string: EQU TERM_VAR_SPACE
|
||||
|
||||
; functions
|
||||
|
||||
; Sends string
|
||||
; @param BC Pointer to a null-terminated string first character
|
||||
Term_print:
|
||||
ld a, (bc) ; bc is the pointer to passed string's first char
|
||||
cp 0 ; compare A content with 0 (subtract 0 from value and set zero flag Z if result is 0)
|
||||
ret z ; if prev compare is true (Z flag set), string is finished, return
|
||||
out (TERM_DATA_REG),a ; output char
|
||||
inc bc ; increment bc to move to next char
|
||||
jp Term_print
|
||||
|
||||
; Writes a single character
|
||||
; @param A Value of character to print
|
||||
Term_printc:
|
||||
out (TERM_DATA_REG),a
|
||||
ret
|
||||
|
||||
; Reads a single character. 0s are ignored (can be used with keyboard).
|
||||
; Doesn't check DATA_AVAILABLE register of parallel port, because a 0 byte
|
||||
; is ignored anyway (it represents the ASCII NUL control char).
|
||||
; @return A The read character
|
||||
Term_readc:
|
||||
in a, (TERM_DATA_REG) ; reads a character
|
||||
add a, 0
|
||||
jp z, Term_readc ; if char is 0 (NULL), ignores it and waits for another character
|
||||
ret ; if not NULL, returns it in the a register
|
||||
|
||||
; Reads a line. 0s are ignored (can be used with keyboard)
|
||||
; Doesn't check DATA_AVAILABLE register of parallel port, because a 0 byte
|
||||
; is ignored anyway (it represents the ASCII NUL control char).
|
||||
; @return BC The pointer to a null-terminated read string
|
||||
Term_readline:
|
||||
ld bc, incoming_string ; this array will contain read string
|
||||
in a, (TERM_DATA_REG) ; reads a character
|
||||
; if char is 0 (ascii NULL), ignore it
|
||||
add a, 0
|
||||
jp z, Term_readline ; if 0 (= ascii NULL), ignores it and waits for another character
|
||||
; if char is a newline (CR or LF), line is finished.
|
||||
cp 10 ; CR
|
||||
jp z, term_readline_foundcr ; Found newline. Jump to term_readline_foundcr
|
||||
cp 13 ; LF
|
||||
jp z, term_readline_foundcr ; Found newline. Jump to term_readline_foundcr
|
||||
; At this point the read character is a valid ascii character
|
||||
ld (bc), a ; adds char to the read string
|
||||
inc bc ; point to next array position
|
||||
jp Term_readline
|
||||
term_readline_foundcr: ; called when carriage return was found (end of line)
|
||||
;ld (bc), 0 ; Null-terminate string
|
||||
ld bc, incoming_string ; Returns read string pointer
|
||||
ret
|
||||
|
||||
; Returns the number of bytes available on the parallel port using the
|
||||
; DATA_AVAILABLE register.
|
||||
; @return a the number of available bytes
|
||||
Term_availb:
|
||||
in a, (TERM_DATA_AVAIL_REG)
|
||||
ret
|
||||
|
||||
; Reads the first available byte on the serial port using the DATA register.
|
||||
; 0s are not ignored (cannot be used with keyboard)
|
||||
; Affects NO condition bits!
|
||||
; @return the available byte, even if 0
|
||||
Term_readb:
|
||||
in a, (TERM_DATA_REG) ; reads a byte
|
||||
ret
|
112
assembly/os/drivers/hd44780.asm
Normal file
112
assembly/os/drivers/hd44780.asm
Normal file
@ -0,0 +1,112 @@
|
||||
; HD44780 20x4 characters LCD display driver
|
||||
; @author Daniele Verducci
|
||||
;
|
||||
; USAGE:
|
||||
; STR: DB "Hello world!",0 <-- null terminated string
|
||||
; call Lcd_init <-- inits hd44780 controller
|
||||
; ld bc, STR <-- load pointer to string's first char in reg BC
|
||||
; call Lcd_print <-- this function will print the string
|
||||
|
||||
; LCD config (IO port 0)
|
||||
LCD_INSTR_REG: EQU IO_0
|
||||
LCD_DATA_REG: EQU IO_0 + 1
|
||||
|
||||
; constants
|
||||
LCD_LINES_LEFT: DB 0x80, 0xA8, 0x94, 0xBC ;array defining lcd command codes for the first char of every line
|
||||
|
||||
; variables
|
||||
LCD_VAR_SPACE: EQU DRV_VAR_SPACE
|
||||
lcd_cur_x: EQU LCD_VAR_SPACE
|
||||
lcd_cur_y: EQU lcd_cur_x + 1
|
||||
|
||||
; functions
|
||||
|
||||
; Inits the lcd display
|
||||
Lcd_init:
|
||||
;reset procedure
|
||||
ld a,0x38
|
||||
out (LCD_INSTR_REG),a
|
||||
ld a,0x08
|
||||
out (LCD_INSTR_REG),a
|
||||
ld a,0x01
|
||||
out (LCD_INSTR_REG),a
|
||||
|
||||
;init procedure
|
||||
ld a,0x38
|
||||
out (LCD_INSTR_REG),a
|
||||
ld a,0x0F
|
||||
out (LCD_INSTR_REG),a
|
||||
|
||||
ret
|
||||
|
||||
; Writes text starting from current cursor position
|
||||
; @param BC Pointer to a null-terminated string first character
|
||||
Lcd_print:
|
||||
ld a, (bc) ; bc is the pointer to passed string's first char
|
||||
cp 0 ; compare A content with 0 (subtract 0 from value and set zero flag Z if result is 0)
|
||||
ret z ; if prev compare is true (Z flag set), string is finished, return
|
||||
out (LCD_DATA_REG),a ; output char
|
||||
inc bc ; increment bc to move to next char
|
||||
; increment x position
|
||||
ld a, (lcd_cur_x)
|
||||
inc a
|
||||
ld (lcd_cur_x), a
|
||||
; if x position > 19, increment y position and set x to 0
|
||||
ld a, (lcd_cur_x)
|
||||
cp 20
|
||||
jp nz, Lcd_print ; if x position is not 20, continue cycle
|
||||
ld a, 0
|
||||
ld (lcd_cur_x), a ; else set x to 0
|
||||
; and increment y
|
||||
ld a, (lcd_cur_y)
|
||||
inc a
|
||||
ld (lcd_cur_y), a
|
||||
; if y > 3 set y to 0
|
||||
cp 4 ; a still contains lcd_cur_y: compare with 4
|
||||
jp nz, Lcd_print ; if y position is not 4, continue cycle
|
||||
ld a, 0
|
||||
ld (lcd_cur_x), a ; else set y pos to 0
|
||||
jp Lcd_print
|
||||
|
||||
; Writes a single character at current cursror position
|
||||
; @param A Value of character to print
|
||||
Lcd_printc:
|
||||
out (LCD_DATA_REG),a
|
||||
ret
|
||||
|
||||
|
||||
; Set cursor position
|
||||
; @param B X-axis position (0 to 19)
|
||||
; @param C Y-axis position (0 to 3)
|
||||
Lcd_locate:
|
||||
ld a, b
|
||||
ld (lcd_cur_x), a
|
||||
ld a, c
|
||||
ld (lcd_cur_y), a
|
||||
call lcd_locate
|
||||
ret
|
||||
|
||||
; private
|
||||
; The cursor position can seem like black magic but it makes much more sense once you know that the HD44780 is designed to control a 40 character 4-line display. So if you have a 16×2 then you will only see the first 16 characters of the top two lines. Simple enough once you get used to taking these character positions into account. For example, in a 16×2 display, the first line is position 0-15. So 0x80 is the first position, 0x80 + 12 = 0x8C is the 13th (remember, they are zero indexed). The second line is a little tricky since it shows positions 64-79. Just add the position number (in decimal) to 0x80 (in hex) to get the hex address of the cursor position. The address is the command to move the cursor to that location. So, to move to the 13th position of the top line in a 16×2 Sparkfun Display, I would send “0xFE 0x8C”. The first byte warns the onboard microcontroller that a command is coming, and the second byte is the command.
|
||||
lcd_locate:
|
||||
; warns the lcd microcontroller that a command is coming
|
||||
ld a, 0xFE
|
||||
out (LCD_INSTR_REG),a
|
||||
; get line start command code from array
|
||||
ld hl, LCD_LINES_LEFT ; load array pointer
|
||||
ld bc, lcd_cur_y ; load line number
|
||||
ld b, 0 ; since line number is only 8 bit, clean garbage on the upper bit
|
||||
add hl, bc ; sum first array element to line number to access correct array element. Now hl contains array pointer
|
||||
; now sum x offset to the start line code to obtain lcd controller complete position code
|
||||
ld a, (lcd_cur_x) ; load cursor x position
|
||||
add a, (hl) ; sum cursor x pos to line start code. Result is in a
|
||||
out (LCD_INSTR_REG),a ; send cursor position to lcd controller
|
||||
ret
|
||||
|
||||
; Clears the screen
|
||||
Lcd_cls:
|
||||
ld a,0x01
|
||||
out (LCD_INSTR_REG),a ; clear display
|
||||
ld a,0x02
|
||||
out (LCD_INSTR_REG),a ; cursor to home (top left)
|
||||
ret
|
56
assembly/os/drivers/keyboard.asm
Normal file
56
assembly/os/drivers/keyboard.asm
Normal file
@ -0,0 +1,56 @@
|
||||
; Keyboard driver
|
||||
; @author Daniele Verducci
|
||||
;
|
||||
; Requires declaration of following pointers, one for every column of the keys grid:
|
||||
; KEYB_A0_REG
|
||||
; KEYB_A1_REG
|
||||
; KEYB_A2_REG
|
||||
; KEYB_A3_REG
|
||||
; KEYB_A4_REG
|
||||
; These address must be exclusive if a decoder is not present.
|
||||
;
|
||||
; Example (no decoder):
|
||||
; KEYB_A0_REG = 0000001
|
||||
; KEYB_A1_REG = 0000010
|
||||
; KEYB_A2_REG = 0000100
|
||||
; KEYB_A3_REG = 0001000
|
||||
; etc...
|
||||
;
|
||||
; Example (with decoder):
|
||||
; KEYB_A0_REG = 0000000
|
||||
; KEYB_A1_REG = 0000001
|
||||
; KEYB_A2_REG = 0000010
|
||||
; KEYB_A3_REG = 0000011
|
||||
; etc...
|
||||
|
||||
; Keyboard config (IO port 1)
|
||||
KEYB_A0_REG: EQU IO_1 + %00000001
|
||||
KEYB_A1_REG: EQU IO_1 + %00000010
|
||||
KEYB_A2_REG: EQU IO_1 + %00000100
|
||||
KEYB_A3_REG: EQU IO_1 + %00001000
|
||||
KEYB_A4_REG: EQU IO_1 + %00010000
|
||||
|
||||
; Reads the keyboard
|
||||
; @return: a 0-terminated array of keycodes representing the pressed keys
|
||||
Keyb_read:
|
||||
in a, (KEYB_A0_REG)
|
||||
cp 0
|
||||
jp z, _keyb_read_a1
|
||||
add a, %01000000
|
||||
call Lcd_printc ; A already contains char to print
|
||||
_loop:
|
||||
in a, (KEYB_A0_REG)
|
||||
cp 0
|
||||
jp nz, _loop
|
||||
ret
|
||||
_keyb_read_a1:
|
||||
in a, (KEYB_A1_REG)
|
||||
cp 0
|
||||
ret z
|
||||
add a, %01010000
|
||||
call Lcd_printc ; A already contains char to print
|
||||
_loop2:
|
||||
in a, (KEYB_A1_REG)
|
||||
cp 0
|
||||
jp nz, _loop2
|
||||
ret
|
55
assembly/os/drivers/sn76489.asm
Normal file
55
assembly/os/drivers/sn76489.asm
Normal file
@ -0,0 +1,55 @@
|
||||
; TI SN76489 sound chip display driver
|
||||
; @author Daniele Verducci
|
||||
;
|
||||
; USAGE:
|
||||
; call Snd_init <-- inits sound (and silences default tone)
|
||||
; call Snd_beep <-- system beep
|
||||
|
||||
; Sound card is on port 1
|
||||
SND_DATA_REG: EQU IO_1
|
||||
|
||||
; Init device (silence all channels)
|
||||
; Bits meaning:
|
||||
; 1 R0 R1 R2 A0 A1 A2 A3
|
||||
; Bit0 is 1
|
||||
; Bit1,2,3 select the channel: 001, 011, 101, 111(noise)
|
||||
; Bit4,5,6,7 selecy the attenuation (0000=full volume, 1111=silent)
|
||||
Snd_init:
|
||||
; silence ch1
|
||||
ld a,%10011111
|
||||
out (SND_DATA_REG),a
|
||||
; silence ch2
|
||||
ld a,%10111111
|
||||
out (SND_DATA_REG),a
|
||||
; silence ch3
|
||||
ld a,%11011111
|
||||
out (SND_DATA_REG),a
|
||||
; silence noise ch
|
||||
ld a,%11111111
|
||||
out (SND_DATA_REG),a
|
||||
ret
|
||||
|
||||
; Plays the system beep.
|
||||
Snd_beep:
|
||||
; ch1 max volume
|
||||
ld a,%10010000
|
||||
out (SND_DATA_REG),a
|
||||
; play beep freq
|
||||
ld a,%10000000
|
||||
out (SND_DATA_REG),a
|
||||
ld a,%00001000
|
||||
out (SND_DATA_REG),a
|
||||
; wait
|
||||
ld bc, (TIME_DUR_MILLIS * 10)
|
||||
call Time_delay55
|
||||
; silence ch1
|
||||
ld a,%10011111
|
||||
out (SND_DATA_REG),a
|
||||
ret
|
||||
|
||||
; Sets the attenuation value for a channel
|
||||
; @param a Channel (0, 1, 2, 3(Noise))
|
||||
; @param c Attenuation (0 to 16)
|
||||
; Snd_setAtt:
|
||||
; cp a, 0
|
||||
|
103
assembly/os/drivers/vgax.asm
Normal file
103
assembly/os/drivers/vgax.asm
Normal file
@ -0,0 +1,103 @@
|
||||
; Vgax display driver
|
||||
; @author Daniele Verducci
|
||||
;
|
||||
; Requires declaration of following pointers:
|
||||
; VGAX_INSTR_REG
|
||||
; VGAX_DATA_REG
|
||||
|
||||
; variables
|
||||
lcd_cur_x: EQU DRV_VAR_SPACE
|
||||
lcd_cur_y: EQU lcd_cur_x + 1
|
||||
|
||||
; functions
|
||||
|
||||
; Inits the lcd display
|
||||
Lcd_init:
|
||||
;reset procedure
|
||||
ld a,0x38
|
||||
out (LCD_INSTR_REG),a
|
||||
ld a,0x08
|
||||
out (LCD_INSTR_REG),a
|
||||
ld a,0x01
|
||||
out (LCD_INSTR_REG),a
|
||||
|
||||
;init procedure
|
||||
ld a,0x38
|
||||
out (LCD_INSTR_REG),a
|
||||
ld a,0x0F
|
||||
out (LCD_INSTR_REG),a
|
||||
|
||||
ret
|
||||
|
||||
; Writes text starting from current cursor position
|
||||
; @param BC Pointer to a null-terminated string first character
|
||||
Lcd_print:
|
||||
ld a, (bc) ; bc is the pointer to passed string's first char
|
||||
cp 0 ; compare A content with 0 (subtract 0 from value and set zero flag Z if result is 0)
|
||||
ret z ; if prev compare is true (Z flag set), string is finished, return
|
||||
out (LCD_DATA_REG),a ; output char
|
||||
inc bc ; increment bc to move to next char
|
||||
; increment x position
|
||||
ld a, (lcd_cur_x)
|
||||
inc a
|
||||
ld (lcd_cur_x), a
|
||||
; if x position > 19, increment y position and set x to 0
|
||||
ld a, (lcd_cur_x)
|
||||
cp 20
|
||||
jp nz, Lcd_print ; if x position is not 20, continue cycle
|
||||
ld a, 0
|
||||
ld (lcd_cur_x), a ; else set x to 0
|
||||
; and increment y
|
||||
ld a, (lcd_cur_y)
|
||||
inc a
|
||||
ld (lcd_cur_y), a
|
||||
; if y > 3 set y to 0
|
||||
cp 4 ; a still contains lcd_cur_y: compare with 4
|
||||
jp nz, Lcd_print ; if y position is not 4, continue cycle
|
||||
ld a, 0
|
||||
ld (lcd_cur_x), a ; else set y pos to 0
|
||||
jp Lcd_print
|
||||
ret
|
||||
|
||||
; Writes a single character at current cursror position
|
||||
; @param A Value of character to print
|
||||
Lcd_printc:
|
||||
out (LCD_DATA_REG),a
|
||||
ret
|
||||
|
||||
|
||||
; Set cursor position
|
||||
; @param B X-axis position (0 to 19)
|
||||
; @param C Y-axis position (0 to 3)
|
||||
Lcd_locate:
|
||||
ld a, b
|
||||
ld (lcd_cur_x), a
|
||||
ld a, c
|
||||
ld (lcd_cur_y), a
|
||||
call lcd_locate
|
||||
ret
|
||||
|
||||
; private
|
||||
; The cursor position can seem like black magic but it makes much more sense once you know that the HD44780 is designed to control a 40 character 4-line display. So if you have a 16×2 then you will only see the first 16 characters of the top two lines. Simple enough once you get used to taking these character positions into account. For example, in a 16×2 display, the first line is position 0-15. So 0x80 is the first position, 0x80 + 12 = 0x8C is the 13th (remember, they are zero indexed). The second line is a little tricky since it shows positions 64-79. Just add the position number (in decimal) to 0x80 (in hex) to get the hex address of the cursor position. The address is the command to move the cursor to that location. So, to move to the 13th position of the top line in a 16×2 Sparkfun Display, I would send “0xFE 0x8C”. The first byte warns the onboard microcontroller that a command is coming, and the second byte is the command.
|
||||
lcd_locate:
|
||||
; warns the lcd microcontroller that a command is coming
|
||||
ld a, 0xFE
|
||||
out (LCD_INSTR_REG),a
|
||||
; get line start command code from array
|
||||
ld hl, LCD_LINES_LEFT ; load array pointer
|
||||
ld bc, lcd_cur_y ; load line number
|
||||
ld b, 0 ; since line number is only 8 bit, clean garbage on the upper bit
|
||||
add hl, bc ; sum first array element to line number to access correct array element. Now hl contains array pointer
|
||||
; now sum x offset to the start line code to obtain lcd controller complete position code
|
||||
ld a, (lcd_cur_x) ; load cursor x position
|
||||
add a, (hl) ; sum cursor x pos to line start code. Result is in a
|
||||
out (LCD_INSTR_REG),a ; send cursor position to lcd controller
|
||||
ret
|
||||
|
||||
; Clears the screen
|
||||
Lcd_cls:
|
||||
ld a,0x01
|
||||
out (LCD_INSTR_REG),a ; clear display
|
||||
ld a,0x02
|
||||
out (LCD_INSTR_REG),a ; cursor to home (top left)
|
||||
ret
|
Reference in New Issue
Block a user