;
; hello.asm
; Neil Gershenfeld CBA MIT 7/8/05
; tiny13 hello world program
;
;
;5   vcc
;3   2
;4   1
;gnd 0

.include "tn13def.inc"

.equ ledpin = PB4; LED pin
.equ txpin = PB0; transmit pin
.equ rxpin = PB2; receive pin

.def bitcnt = R16; bit counter
.def temp = R17; temporary storage
.def temp1 = R18; temporary storage
.def temp2 = R21; temporary storage
.def txbyte = R19; transmit byte
.def rxbyte = R20; received byte

.cseg
.org 0
rjmp reset

;
; putchar
; assumes no line driver (doesn't invert bits)
;
.equ sb = 1; number of stop bits
putchar:
   ldi bitcnt, 9+sb; 1+8+sb
   com txbyte; invert everything
   sec; set start bit
   putchar0:
      brcc putchar1; if carry set
      sbi PORTB, txpin; send a '0'
      rjmp putchar2; else
   putchar1:
       cbi PORTB, txpin	; send a '1'
       nop ; even out timing
   putchar2:
       rcall bitdelay; one bit delay
       rcall bitdelay
       lsr txbyte; get next bit
       dec bitcnt; if not all bits sent
       brne putchar0; send next bit
   ret;

	;
	; getchar
	; assumes no line driver (doesn't invert bits)
	;
	getchar:
	   ldi bitcnt,9 ; 8 data bit + 1 stop bit
	   getchar1:
	      sbis PINB, rxpin ; wait for start bit
	      rjmp getchar1
	   rcall bitdelay ; 0.5 bit delay
	   getchar2:
	      rcall bitdelay ; 1 bit delay
	      rcall bitdelay ;
	      clc ; clear carry
	      sbis PINB, rxpin ; if RX pin high skip
	         sec ; otherwise set carry
	      dec bitcnt
	      breq getchar3 ; return if all bits read
	      ror rxbyte ; otherwise shift bit into receive byte
	      rjmp getchar2 ; go get next bit
	   getchar3:
	      ret
	
;
; bit delay
;
.equ b = 17 ; 9600 bps
bitdelay:
   ldi temp, b
   bitloop:
      dec temp
      brne bitloop
   ret
;
; print_delay
; delay between printed lines
;
.equ delay = 200
print_delay:
   ldi temp1, delay
   charloop1:
      ldi temp, delay
      charloop0:
         dec temp
         brne charloop0
      dec temp1
      brne charloop1
   ret

;
; long_print_delay
; delay between printed lines
;
.equ delay2 = 100
long_print_delay:
   ldi temp2, delay2
   charloop2:
      ldi temp1, delay2
      charloopa:
         ldi temp, delay2
         charloopB:
            dec temp
            brne charloopB
         dec temp1
         brne charloopa
      dec temp2
      brne charloop2
   ret

;
; print
; prints a null-terminated string
;
print:
   print_loop:
      lpm
      mov txbyte,R0
      cpi txbyte,0
      breq return
      rcall putchar
      inc zl
      rjmp print_loop
   return:
      ret
;
; string to print
;
print_string:
   .db "I am a webserver",13,10,0
;
; main program
;
ldi temp, low(RAMEND) ; set stack pointer to top of RAM
out SPL, temp ;
reset:
   sbi PORTB, txpin; init comm pin
   sbi DDRB, txpin
   sbi PORTB, ledpin; init comm pin
   sbi DDRB, ledpin
   loop:
   	cbi PORTB, ledpin

      ldi zl,low(print_string*2)
      ldi zh,high(print_string*2)
      rcall print
      rcall print_delay
	doop:
      
   	cbi PORTB, ledpin
      rcall getchar
      inc rxbyte
      mov txbyte, rxbyte
      rcall putchar
      sbi PORTB, ledpin
      rcall long_print_delay

      rjmp doop	


      rjmp loop
