// 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