include "hardware.inc" section "home/serial.asm@hram", hram h_serial_len: dw h_serial_send_ptr: dw h_serial_recv_ptr: dw section "home/serial.asm@int58", rom0[$58] push af push hl push bc push de jp serial_shift_int section "home/serial.asm", rom0 serial_shift_int: call serial_shift pop de pop bc pop hl pop af reti serial_end: serial_shift: ldh a, [h_serial_len + 0] ld c, a ldh a, [h_serial_len + 1] ld b, a ; End early if we're done or c ret z ldh a, [h_serial_recv_ptr + 0] ld e, a ldh a, [h_serial_recv_ptr + 1] ld d, a ; Store the last received byte or e jr z, .no_recv ldh a, [r_sb] ld [de], a inc de .no_recv ; We've transferred an entire byte in both directions dec bc ldh a, [h_serial_send_ptr + 0] ld l, a ldh a, [h_serial_send_ptr + 1] ld h, a ; fallthrough serial_queue: ; If the length is 0, not much should be done ld a, b or c jr z, .empty ld a, h or l ld a, -1 jr z, .no_send ld a, [hli] .no_send ldh [r_sb], a ldh a, [r_sc] set r_sc_start_f, a jr .store .empty ldh a, [r_sc] res r_sc_start_f, a .store ldh [r_sc], a ld a, c ldh [h_serial_len + 0], a ld a, b ldh [h_serial_len + 1], a ld a, e ldh [h_serial_recv_ptr + 0], a ld a, d ldh [h_serial_recv_ptr + 1], a ld a, l ldh [h_serial_send_ptr + 0], a ld a, h ldh [h_serial_send_ptr + 1], a ret serial_finished:: ; ret: z if done, nz if not done ldh a, [r_sc] bit r_sc_start_f, a ret serial_transfer:: ; hl: Source buffer ; de: Destination buffer ; bc: Size ; ret: nz if previous transfer is still in transit call serial_finished ret nz jp serial_queue serial_init_master:: ld a, 1 db $fe ; CP A, n8 serial_init_slave:: xor a ; fallthrough serial_init: ldh [r_sc], a ldh a, [r_ie] set r_int_serial_f, a ldh [r_ie], a ret