;******************************************
;* Convert upper case Alpha to lower case *
;******************************************
_tolower:
          cpi       zl,'A'
          brlo      _tolowerx
          cpi       zl,'Z'+1
          brsh      _tolowerx
          subi      zl,-' '
_tolowerx:
          ret
;
;********************************************
;* Some ASCII 'string' operations	    *
;********************************************
;** Get one byte from either Flash or Sram **
_getmemoryR0:
	brts	_getmemoryR0a	; Are we dealing with a Constant ?
	lpm			; Yes, get the byte from Flash
	adiw	zl,1		; Advance the 'z' pointer to next address
	ret			; return to caller
_getmemoryR0a:			; No, get it from Sram
	ld	r0,z+		; Load 'r0' w/byte, and advance to next address
	ret			; return to caller
;
;** Copy a string from (primary$) to (secondary$) **
_stringcopy:
	rcall	_getmemoryR0
	st	x+,r0
	or	r0,r0
	brne	_stringcopy
	ret
;
;** String Length functions **
_stringlengthc:
	clt
	rcall	_stringlength
_stringlengthp:
	mov	zl,r24
	mov	zh,r25
	ret
_stringlengths:
	set
	rcall	_stringlength
	rjmp	_stringlengthp
;
_stringlength:
	clr	r24
	clr	r25
_stringlengthlp:
	rcall	_getmemoryR0
	or	r0,r0		; Found NULL yet ?
	breq	_stringlengthx	; Yes, the 'length' is in r24,r25
	adiw	r24,1		; Not yet, add 1 to the length
	rjmp	_stringlengthlp	; and keep going.
_stringlengthx:
	ret
;
;******************************************
;** String concatenation		  *
;* (primary$) = (primary$) + (secondary$) *
;******************************************
_stringcat:
	rcall	_stringlength
	sbiw	xl,1		; Back-up 1 to the 'NULL'
_stringcatlp:
	rcall	_getmemoryR0
	st	x+,r0
	or	r0,r0
	brne	_stringcatlp
	ret
;
;** String Compare (primary$) to (secondary$) **
_stringcompare:
	rcall	_getmemoryR0
	ld	r25,x+
	or	r0,r0		; Have we reached the end of (primary$) string1 ?
	breq	_stringcompare2	; Yes, (primary$) 'could be' < or = (secondary$)
	or	r25,r25		; Have we reached the end of (secondary$) string2 ?
	breq	_stringcompare3	; Yes, (primary$) 'is' > (secondary$) !
	cp	r0,r25		; Do the strings match so far ?
	breq	_stringcompare	; Yes, keep going
	brsh	_stringcompare3	; No, (primary$) > (secondary$)
_stringcompare1:		; If we are here, (primary$) string1 < (secondary$)
	clr	zl
	ldi	r24,1
	ret
_stringcompare2:
	or	r25,r25		; At the end of (secondary$)/string2 ?
	brne	_stringcompare1	; No, (primary$) is < (secondary$)
	clr	zl		; The strings are 'equal', return to caller
	clr	r24
	ret	
_stringcompare3:		; (primary$) string1 is > (secondary$) string2
	ldi	zl,1
	clr	r24
	ret
;
;********************************************
;* 8 and 16 bit unsigned integer Square Root*
;********************************************
_sqrt8:
	clr	zh
_sqrt16:
	push	r22
	clr     r22
	ldi     r24,1	; initialize the seed to be subtracted
	clr     r25		;	for each iteration
_sqrtlp:
	sub     zl,r24
	sbc     zh,r25
	brlo	_sqrtx
	inc     r22
	adiw    r24,2	; keep the number to subtract ODD.
	rjmp    _sqrtlp
_sqrtx:
	mov	zl,r22
	clr	zh
	pop	r22
	ret
;

