.nolist
.include "m168def.inc" ; Same family as 328P
.list
.macro poke
.message "No parameters"
.endm
.macro poke_i_8_i
ldi @1, @2
sts @0, @1
.endm
.macro poke_i_16_i
ldi @1, low(@3)
sts @0+0, @1
ldi @2, high(@3)
sts @0+1, @2
.endm
;; Load a 16-bit *word* address into the given register a a byte address
.macro loadp_16_i
ldi @0, high(2 * @2)
ldi @1, low(2 * @2)
.endm
.macro load_16_i
ldi @0, high(@2)
ldi @1, low(@2)
.endm
;; Interrupt Vector
.org 0x00
rjmp Main
;; Serial
.set SERIAL_BAUD = 103 ; 9.6k @ 16Mhz
;; Initialize the UART for
Serial_Init:
; Set up control registers
; Single-speed
poke [UCSR0A, r16, (0 << U2X0)]
; Async
; n parity
; 1 stop
; 8 bits
poke [UCSR0C, r16, (0b00 << UMSEL00) | (0b00 << UPM00) | (0 << USBS0) | (0b11 << UCSZ00)]
; Baud rate
poke [UBRR0L, r16:r17, SERIAL_BAUD]
; Enable RX
; Enable TX
; 8 bits
poke [UCSR0B, r16, (0 << RXEN0) | (1 << TXEN0) | (0 << UCSZ02)]
; Done
ret
;; Send a single byte on serial port
; Input byte in r16
Serial_Send:
; Wait for idle
lds r0, UCSR0A
sbrs r0, UDRE0
rjmp Serial_Send
; Copy byte to buffer
sts UDR0, r16
; Done
ret
;; Write nul-terminated string to serial port
; Input string in Z
Serial_Write:
; Load byte to r16
lpm r16, Z+
; Quit if nul
tst r16
breq _serial_write_end
; Write it
rcall Serial_Send
; Continue
rjmp Serial_Write
_serial_write_end:
ret
;; Program
message: .db "Hello World", 13, 10, 0
Main:
; Initialization
; Stack
poke [SPL, r16:r17, RAMEND]
; Enable interrupts
sei
; Init
rcall Serial_Init
loop:
; Main program
ldi ZH, high(message * 2)
ldi ZL, low(message * 2)
rcall Serial_Write
; repeat
rjmp loop