; com1.fasm

use16

PORT equ 0x3f8 ; COM1

; section '.text'

init_uart:
    pusha                   ; Save all general-purpose registers
    call disable_interrupts
    call enable_divisor_latch_access
    call set_baud_rate
    call set_line_control
    call enable_fifo
    call set_modem_control
    call test_serial_chip
    popa                    ; Restore all general-purpose registers
    ret

disable_interrupts:
    mov dx, PORT + 1    ; Load the address of the interrupt enable register
    mov al, 0x00        ; Value to write to the register, disabling interrupts
    out dx, al          ; Write the value to the port
    ret

enable_divisor_latch_access:
    mov dx, PORT + 3    
    mov al, 0x80        ; Enable DLAB (set baud rate divisor)
    out dx, al 
    ret

set_baud_rate:
    mov dx, PORT + 0    ; Set divisor to 3 (lo byte) for 38400 baud
    mov al, 0x03
    out dx, al
    mov dx, PORT + 1    ; Set divisor (hi byte)
    xor al, al          ; AL = 0x00
    out dx, al
    ret

set_line_control:
    mov dx, PORT + 3    
    mov al, 0x03        ; 8 bits, no parity, one stop bit
    out dx, al
    ret

enable_fifo:
    mov dx, PORT + 2    
    mov al, 0xC7        ; Enable FIFO, clear them, with 14-byte threshold
    out dx, al
    ret

set_modem_control:
    mov dx, PORT + 4    
    mov al, 0x0B        ; IRQs enabled, RTS/DSR set
    out dx, al
    mov dx, PORT + 4
    mov al, 0x1E        ; Set loopback mode
    out dx, al
    ret

test_serial_chip:
    mov dx, PORT + 0
    mov al, 0xAE        ; Test serial chip (send byte 0xAE and check)
    out dx, al
    in al, dx           ; Read back to check if the chip is responding
    cmp al, 0xAE
    jne com_error
    ret

com_error: 
	; "E" for beginning of call_subroutine:
	mov ah, 0x0E
	mov al, 'E'
	int 0x10
	hlt
	
; UART I/O routines: 
; Corrected send_byte_to_com1 routine to wait for the transmit buffer to be empty before sending a byte
send_byte_to_com1:
    push ax
    push dx
    mov dx, PORT + 5  ; Line Status Register
wait_for_transmit_empty:
    in al, dx
    test al, 0x20     ; Check if THR is empty
    jz wait_for_transmit_empty
    mov dx, PORT      ; Reset dx to base of COM1
    pop dx            ; Restore original DX value, containing PORT address
    mov al, [si]      ; Assuming SI points to the byte to send
    out dx, al
    pop ax
    ret
	
; Corrected read_byte_from_com1 routine to wait for data to be available before reading a byte
read_byte_from_com1:
    push ax
    push dx
    mov dx, PORT + 5      ; Line Status Register (LSR)
wait_for_data_available:
    in al, dx
    test al, 1            ; Check Data Ready bit
    jz wait_for_data_available
    mov dx, PORT          ; Reset dx to base of COM1
    in al, dx             ; Read byte from data register
    ; Ignore carriage returns and line feeds
    cmp al, 0x0D
    je wait_for_data_available
    cmp al, 0x0A
    je wait_for_data_available
    pop dx
    pop ax
    ret



	

