Last active
June 13, 2021 17:13
-
-
Save nitwhiz/ba63eac81ba8dd11321df83ed26911e2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; --- | |
; constants | |
pit_count: equ 18432 ; pit counter constant - 10ms | |
segm_setting: equ 7 ; digit to display seconds set | |
segm_time_seconds: equ 3 ; digit to display seconds of timer | |
segm_time_100th: equ 0 ; digit to display 100th seconds of timer | |
; segment display address | |
segm_addr: equ 90h | |
; determinate output offsets for display digits | |
segm_setting_offset: equ segm_setting * 2 | |
segm_time_seconds_offset: equ segm_time_seconds * 2 | |
segm_time_100th_offset: equ segm_time_100th * 2 | |
org 100h | |
cli | |
call IVTABinit ; init vector table | |
call PICinit ; init IC | |
call PITinit ; init PIT | |
sti | |
call display_clear | |
main: | |
call read_switches | |
call display_timer | |
cmp [time_running], byte 0 | |
je main ; s7 is off, don't run timer | |
;call cycle_timer | |
;call delay | |
jmp main | |
; --- | |
; init IC | |
PICinit: | |
in al, 0c2h | |
and al, 11111110b | |
out 0c2h, al | |
ret | |
; --- | |
; init pit | |
PITinit: | |
mov al, 01110110b | |
out 0a6h, al ; counter 1 mode 3 | |
mov al, pit_count % 255 | |
out 0a2h,al | |
mov al, pit_count / 256 | |
out 0a2h,al | |
ret | |
; --- | |
; init vector 8 to our ISR | |
IVTABinit: | |
; set address of ISR in vektor 8 | |
mov [8 * 4], word isr8 | |
mov [8 * 4 + 2], cs | |
ret | |
; --- | |
; interrupt service routine (ISR) | |
isr8: | |
push ax | |
inc byte [tick_count] | |
cmp [tick_count], byte 5 | |
jne under_100ms | |
call cycle_timer | |
mov [tick_count], byte 0 | |
under_100ms: | |
mov al, 20h | |
out 0c0h, al ; unlock PIC | |
pop ax | |
iret | |
; --- | |
; get state of switches | |
read_switches: | |
push ax | |
push cx | |
in al, 0 | |
mov ah, al | |
and al, 7fh ; mask lower 7 bit | |
cmp [time_setting], al | |
je switches_unchanged ; s6-s0 are the same as before, don't reset | |
; s6-s0 changed, reset timer | |
mov [time_setting], al | |
mov [time_seconds], al | |
mov [time_100th], byte 0 | |
switches_unchanged: | |
mov cl, 7 | |
shr ah, cl ; remove lower 7 bit | |
mov [time_running], ah | |
cmp ah, 1 | |
jne interrupt_off | |
sti | |
jmp switches_end | |
interrupt_off: | |
cli | |
switches_end: | |
pop cx | |
pop ax | |
ret | |
; --- | |
; decrements timer and wraps milliseconds if necessary | |
cycle_timer: | |
cmp [time_100th], byte 0 | |
je cycle_wrap ; time_100th == 0 | |
; time_100th != 0 | |
dec byte [time_100th] | |
jmp cycle_end | |
cycle_wrap: | |
cmp [time_seconds], byte 0 | |
je cycle_end ; seconds == 0 | |
; seconds != 0 | |
mov [time_100th], byte 9 | |
dec byte [time_seconds] | |
cycle_end: | |
ret | |
; --- | |
; converts AX to BCD | |
ax_as_bcd: | |
push bx | |
push cx | |
mov bl, al ; copy complete input | |
and bl, 00001111b ; mask to lower nibble | |
and al, 11110000b ; mask to upper nibble | |
mov cl, 4 | |
shr al, cl ; remove lower nibble | |
cmp al, 0 ; check if there is an upper nibble | |
jz no_upper_nibble ; jump if upper nibble is 0 | |
mov cl, al ; prepare loop counter (repeat upper-nibble times) | |
mov al, 0h ; clear al for upper nibble value | |
mov ah, 0h ; clear ah for carry | |
upper_nibble_to_bcd: | |
add al, 0fh ; add 15 to al | |
daa ; make valid BCD | |
adc ah, 0h ; add 1 to ah if carry | |
; --- necessary, because 10h is 10d with DAA | |
add al, 1h ; add 1 more to add 16 in total | |
daa ; make value BCD | |
adc ah, 0h ; add 1 to ah if carry | |
loop upper_nibble_to_bcd ; will happen 0 to 7 times | |
; used to skip loop if there is no upper nibble | |
no_upper_nibble: | |
mov bh, al ; copy current BCD (from upper nibble) | |
mov al, bl ; move lower nibble to al | |
daa ; turn lower nibble into BCD | |
add al, bh ; add BCDs | |
daa ; ensure BCD output | |
adc ah, 0h ; add 1 to ah if carry | |
pop cx | |
pop bx | |
ret | |
; --- | |
; display setting and current time | |
display_timer: | |
push ax | |
push dx | |
; setting | |
mov dl, segm_setting_offset | |
mov al, [time_setting] | |
mov ah, 0 | |
call ax_as_bcd | |
call display_3 | |
; seconds | |
mov dl, segm_time_seconds_offset | |
mov al, [time_seconds] | |
mov ah, 0 | |
call ax_as_bcd | |
call display_3 | |
; 100th | |
mov dl, segm_time_100th_offset | |
mov al, [time_100th] | |
call display_1 | |
pop dx | |
pop ax | |
ret | |
; wait for 025000 cycles | |
delay: | |
push cx | |
mov cx, 025000d | |
delay_cycle: | |
loop delay_cycle | |
pop cx | |
ret | |
; --- | |
; display 3 hex numbers | |
; AX - number to display | |
; DL - digit to display value at | |
display_3: | |
push ax | |
push cx | |
push dx | |
xchg al, ah ; make sure al contains upper 8 bit | |
call display_1 ; display upper 4 bit | |
xchg al, ah ; make sure al contains lower 8 bit | |
sub dl, 2 ; move display digit 1 digit to right | |
call display_2 ; display lower 8 bit | |
pop dx | |
pop cx | |
pop ax | |
ret | |
; --- | |
; display 2 hex numbers | |
; AL - number to display | |
; DL - digit to display value at | |
display_2: | |
push cx | |
push dx | |
sub dl, 2 ; move display digit right by 1 | |
call display_1 ; display lower 4 bit | |
mov cl, 4 | |
shr al, cl ; cut off lower 4 bit | |
add dl, 2 ; move display digit left again | |
call display_1 ; display upper 4 bit | |
pop dx | |
pop cx | |
ret | |
; --- | |
; display 1 hex number | |
; AL - number to display | |
; DL - digit to display value at | |
display_1: | |
push ax | |
push bx | |
push dx | |
add dl, segm_addr ; add display port address to position | |
mov bx, codetab ; point to codetab | |
and ax, 0fh ; mask AX | |
add bx, ax ; add which number to display from codetab | |
mov al, [bx] ; copy codetab value | |
out dx, al ; output codetab value | |
pop dx | |
pop bx | |
pop ax | |
ret | |
; --- | |
; clear display | |
display_clear: | |
push ax | |
push cx | |
push dx | |
mov ax, 0 | |
mov dx, segm_addr ; start at display digit 0 | |
mov cx, 8 ; repeat for 7 digits | |
clear_step: | |
out dx, ax ; turn off digit | |
add dx, 2 ; next display digit | |
loop clear_step | |
pop dx | |
pop cx | |
pop ax | |
ret | |
tick_count: | |
db 0 | |
time_running: | |
db 0 | |
time_100th: | |
db 0 | |
time_seconds: | |
db 0 | |
time_setting: | |
db 0 | |
codetab: | |
db 00111111b ; 0 | |
db 00000110b ; 1 | |
db 01011011b ; 2 | |
db 01001111b ; 3 | |
db 01100110b ; 4 | |
db 01101101b ; 5 | |
db 01111101b ; 6 | |
db 00000111b ; 7 | |
db 01111111b ; 8 | |
db 01101111b ; 9 | |
db 01110111b ; A | |
db 01111100b ; b | |
db 01011000b ; c | |
db 01011110b ; d | |
db 01111001b ; E | |
db 01110001b ; F |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment