console.s
author Tero Marttila <terom@fixme.fi>
Fri, 07 May 2010 03:16:01 +0300
changeset 13 a18180e37d57
parent 11 49c5eeee4cb7
child 14 1ebd5fc73d86
permissions -rw-r--r--
Serial_Write_c + use in main
.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 0x0000
        rjmp        Main

;; Libraries
.include "div.inc"			; Division routines

;; 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, (1 << 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

;; Read a single byte from serial port
; Output byte in r16
Serial_Recv:
	; Wait for recv
		lds			r0, UCSR0A
		sbrs		r0, RXC0
		rjmp		Serial_Recv

	; Copy byte from buffer
		lds			r16, UDR0

	; Done
		ret

;; Write nul-terminated string to serial port
; Input string in Z
Serial_Write_s:
	; Load byte to r16
		lpm			r16, Z+

	; Quit if nul
		tst			r16
		breq		_serial_writes_end

	; Write it
		rcall		Serial_Send

	; Continue
		rjmp		Serial_Write_s

_serial_writes_end:
		ret

;; Write char to serial port
; Input byte in r16
Serial_Write_c:
		; ASCII offset for '0'
		ldi			r17, 48
		mov			r4, r17	
	
	; Convert
		ldi			r17, 100
		call		div8u
		add			r16, r4
		rcall		Serial_Send
		mov			r16, r15

		ldi			r17, 10
		call		div8u
		add			r16, r4
		rcall		Serial_Send
		mov			r16, r15

		add			r16, r4
		rcall		Serial_Send
		
	ret

;; Program
message:	.db "Hello World", 13, 10, 0

Main:
; Initialization
	; Stack
		poke		[SPL, r16:r17, RAMEND]

    ; Enable interrupts
        sei

	; Init
		rcall		Serial_Init

; Main program
		ldi			ZH, high(message * 2)
		ldi			ZL, low(message * 2)
		
		rcall		Serial_Write_s

; Echo out
		sbi			DDRB, PORTB5
		ldi			r20, 0
		ldi			r21, 0

Main_Echo:
		; blink LED
		out			PORTB, r20
		
		; read
		rcall		Serial_Recv
		push		r16
		
		; running counter
		inc			r21
		mov			r16, r21
		rcall		Serial_Write_c
		
		; ' '
		ldi			r16, 32
		rcall		Serial_Send
		
		pop			r16
		rcall		Serial_Send
		
		; '\r\n'
		ldi			r16, 13
		rcall		Serial_Send
		ldi			r16, 10
		rcall		Serial_Send
		
		; toggle
		com			r20
		
		; continue
		rjmp		Main_Echo