136 lines
2.6 KiB
Plaintext
136 lines
2.6 KiB
Plaintext
// Serial port address in MMIO
|
|
dw UART: 0x40000
|
|
|
|
// Reserve space for our read buffer
|
|
resb SERIAL_BUFFER: 1025 // final byte is a null terminator
|
|
dw SER_READ_PTR: 0
|
|
dw SER_WRITE_PTR: 0
|
|
|
|
reset: func
|
|
push rg0
|
|
|
|
lwi SERIAL_BUFFER, rg0
|
|
stw rg0, SER_READ_PTR, 0
|
|
stw rg0, SER_WRITE_PTR, 0
|
|
|
|
pop rg0
|
|
return
|
|
|
|
isr:
|
|
push rg0
|
|
push rg1
|
|
push rg2
|
|
|
|
ldw UART, rg0
|
|
ldb rg0, rg1, 2 // load ser_in_valid flag
|
|
|
|
// no serial input
|
|
jez rg1, _isr_end
|
|
|
|
// we should have a valid byte to read at offset 3
|
|
ldb rg0, rg1, 3 // data byte
|
|
stb zero, rg0, 2 // unset ser_in_valid
|
|
|
|
// write data to ptr and increment
|
|
ldw SER_WRITE_PTR, rg2
|
|
stb rg1, rg2
|
|
addi rg2, 1
|
|
|
|
// load buff+1024
|
|
lwi SERIAL_BUFFER, rg0
|
|
addi rg0, 1024, rg1
|
|
|
|
// if ptr != buff+1024, nowrap.
|
|
ine rg1, rg2, rg1
|
|
jnz rg1, _isr_nowrap
|
|
|
|
lwi SERIAL_BUFFER, rg2 // set the pointer
|
|
|
|
_isr_nowrap:
|
|
stw rg2, SER_WRITE_PTR
|
|
|
|
_isr_end:
|
|
pop rg2
|
|
pop rg1
|
|
pop rg0
|
|
iret
|
|
|
|
// serial_readline: waits until a null byte is received
|
|
// returns nothing, data is in SERIAL_BUFFER starting at SER_READ_PTR
|
|
readline: func
|
|
push rg0
|
|
push rg1
|
|
_readline_wait:
|
|
// check if write ptr == read ptr (buffer empty)
|
|
ldw SER_WRITE_PTR, rg0
|
|
ldw SER_READ_PTR, rg1
|
|
ieq rg0, rg1, rg0
|
|
jnz rg0, _readline_halt // nothing written yet, halt
|
|
|
|
// check if the byte just before write ptr is null
|
|
ldw SER_WRITE_PTR, rg0
|
|
// handle wrap: if write ptr == SERIAL_BUFFER, check last byte of buffer
|
|
lwi SERIAL_BUFFER, rg1
|
|
ieq rg0, rg1, rg1
|
|
jnz rg1, _readline_check_wrap
|
|
|
|
// normal case: read byte at write_ptr - 1
|
|
subi rg0, 1, rg0
|
|
ldb rg0, rg1, 0
|
|
jez rg1, _readline_done
|
|
jmp _readline_halt
|
|
|
|
_readline_check_wrap:
|
|
// write ptr is at start of buffer, last byte is at SERIAL_BUFFER + 1023
|
|
lwi SERIAL_BUFFER, rg0
|
|
addi rg0, 1023, rg0
|
|
ldb rg0, rg1, 0
|
|
jez rg1, _readline_done
|
|
|
|
_readline_halt:
|
|
hlt
|
|
jmp _readline_wait
|
|
|
|
_readline_done:
|
|
pop rg1
|
|
pop rg0
|
|
return
|
|
|
|
// _serial_send: trashes rg2, rg3, rg4, rg5
|
|
// byte to send in rg0
|
|
_serial_send:
|
|
ldw UART, rg5
|
|
_serial_wait:
|
|
ldb rg5, rg2, 0
|
|
lli 0x01, rg3
|
|
ieq rg2, rg3, rg4
|
|
jnz rg4, _serial_wait
|
|
stb rg0, rg5, 1
|
|
stb rg3, rg5, 0 // rg3 is still 0x01 from above
|
|
ret
|
|
|
|
print: func
|
|
push rg0
|
|
push rg1
|
|
ldw bpr, rg0, 8
|
|
_serial_print_loop:
|
|
ldb rg0, rg1
|
|
jez rg1, _serial_print_end
|
|
push rg0
|
|
mov rg1, rg0
|
|
call _serial_send
|
|
pop rg0
|
|
addi rg0, 1, rg0
|
|
jmp _serial_print_loop
|
|
_serial_print_end:
|
|
pop rg1
|
|
pop rg0
|
|
return
|
|
|
|
print_byte: func
|
|
push rg0
|
|
ldw bpr, rg0, 8
|
|
call _serial_send
|
|
pop rg0
|
|
return
|