| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500 | ;---------------------------------------------------------------------------;; Extended itoa, puts, printf and atoi                     (C)ChaN, 2011;---------------------------------------------------------------------------;				// Base size is 152 bytes#define	CR_CRLF		0	// Convert \n to \r\n (+10 bytes)#define USE_XPRINTF	1	// Enable xprintf function (+194 bytes)#define USE_XSPRINTF	1	// Add xsprintf function (+78 bytes)#define USE_XFPRINTF	1	// Add xfprintf function (+54 bytes)#define USE_XATOI	1	// Enable xatoi function (+182 bytes)#if FLASHEND > 0x1FFFF#error xitoa module does not support 256K devices#endif.nolist#include <avr/io.h>	// Include device specific definitions..list#ifdef SPM_PAGESIZE	// Recent devices have "lpm Rd,Z+" and "movw"..macro	_LPMI	reg	lpm	\reg, Z+.endm.macro	_MOVW	dh,dl, sh,sl	movw	\dl, \sl.endm#else			// Earlier devices do not have "lpm Rd,Z+" nor "movw"..macro	_LPMI	reg	lpm	mov	\reg, r0	adiw	ZL, 1.endm.macro	_MOVW	dh,dl, sh,sl	mov	\dl, \sl	mov	\dh, \sh.endm#endif;---------------------------------------------------------------------------; Stub function to forward to user output function;;Prototype: void xputc (char chr	// a character to be output;			);;Size: 10/10 words.section .bss.global xfunc_out	; xfunc_out must be initialized before using this module.xfunc_out:	.ds.w	1.section .text.func xputc.global xputcxputc:#if CR_CRLF	cpi	r24, 10		;LF --> CRLF	brne	1f		;	ldi	r24, 13		;	rcall	1f		;	ldi	r24, 10		;/1:#endif	push	ZH	push	ZL	lds	ZL, xfunc_out+0	;Pointer to the registered output function.	lds	ZH, xfunc_out+1	;/	sbiw	ZL, 0		;Skip if null	breq	2f		;/	icall2:	pop	ZL	pop	ZH	ret.endfunc;---------------------------------------------------------------------------; Direct ROM string output;;Prototype: void xputs (const prog_char *str // rom string to be output;			);.func xputs.global xputsxputs:	_MOVW	ZH,ZL, r25,r24	; Z = pointer to rom string1:	_LPMI	r24	cpi	r24, 0	breq	2f	rcall	xputc	rjmp	1b2:	ret.endfunc;---------------------------------------------------------------------------; Extended direct numeral string output (32bit version);;Prototype: void xitoa (long value,	// value to be output;                       char radix,	// radix;                       char width);	// minimum width;.func xitoa.global xitoaxitoa:				;r25:r22 = value, r20 = base, r18 = digits	clr	r31		;r31 = stack level	ldi	r30, ' '	;r30 = sign	ldi	r19, ' '	;r19 = filler	sbrs	r20, 7		;When base indicates signd format and the value	rjmp	0f		;is minus, add a '-'.	neg	r20		;	sbrs	r25, 7		;	rjmp	0f		;	ldi	r30, '-'	;	com	r22		;	com	r23		;	com	r24		;	com	r25		;	adc	r22, r1		;	adc	r23, r1		;	adc	r24, r1		;	adc	r25, r1		;/0:	sbrs	r18, 7		;When digits indicates zero filled,	rjmp	1f		;filler is '0'.	neg	r18		;	ldi	r19, '0'	;/				;----- string conversion loop1:	ldi	r21, 32		;r26 = r25:r22 % r20	clr	r26		;r25:r22 /= r202:	lsl	r22		;	rol	r23		;	rol	r24		;	rol	r25		;	rol	r26		;	cp	r26, r20	;	brcs	3f		;	sub	r26, r20	;	inc	r22		;3:	dec	r21		;	brne	2b		;/	cpi	r26, 10		;r26 is a numeral digit '0'-'F'	brcs	4f		;	subi	r26, -7		;4:	subi	r26, -'0'	;/	push	r26		;Stack it	inc	r31		;/	cp	r22, r1		;Repeat until r25:r22 gets zero	cpc	r23, r1		;	cpc	r24, r1		;	cpc	r25, r1		;	brne	1b		;/	cpi	r30, '-'	;Minus sign if needed	brne	5f		;	push	r30		;	inc	r31		;/5:	cp	r31, r18	;Filler	brcc	6f		;	push	r19		;	inc	r31		;	rjmp	5b		;/6:	pop	r24		;Flush stacked digits and exit	rcall	xputc		;	dec	r31		;	brne	6b		;/	ret.endfunc;---------------------------------------------------------------------------;; Formatted string output (16/32bit version);;Prototype:; void xprintf (const prog_char *format, ...);; void xsprintf(char*, const prog_char *format, ...);; void xfprintf(void(*func)(char), const prog_char *format, ...);;#if USE_XPRINTF.func xvprintfxvprintf:	ld	ZL, Y+		;Z = pointer to format string	ld	ZH, Y+		;/0:	_LPMI	r24		;Get a format char	cpi	r24, 0		;End of format string?	breq	90f		;/	cpi	r24, '%'	;Is format?	breq	20f		;/1:	rcall	xputc		;Put a normal character	rjmp	0b		;/90:	ret20:	ldi	r18, 0		;r18: digits	clt			;T: filler	_LPMI	r21		;Get flags	cpi	r21, '%'	;Is a %?	breq	1b		;/	cpi	r21, '0'	;Zero filled?	brne	23f		;	set			;/22:	_LPMI	r21		;Get width23:	cpi	r21, '9'+1	;	brcc	24f		;	subi	r21, '0'	;	brcs	90b		;	lsl	r18		;	mov	r0, r18		;	lsl	r18		;	lsl	r18		;	add	r18, r0		;	add	r18, r21	;	rjmp	22b		;/24:	brtc	25f		;get value (low word)	neg	r18		;25:	ld	r24, Y+		;	ld	r25, Y+		;/	cpi	r21, 'c'	;Is type character?	breq	1b		;/	cpi	r21, 's'	;Is type RAM string?	breq	50f		;/	cpi	r21, 'S'	;Is type ROM string?	breq	60f		;/	_MOVW	r23,r22,r25,r24	;r25:r22 = value	clr	r24		;	clr	r25		;	clt			;/	cpi	r21, 'l'	;Is long int?	brne	26f		;	ld	r24, Y+		;get value (high word)	ld	r25, Y+		;	set			;	_LPMI	r21		;/26:	cpi	r21, 'd'	;Is type signed decimal?	brne	27f		;/	ldi	r20, -10	;	brts	40f		;	sbrs	r23, 7		;	rjmp	40f		;	ldi	r24, -1		;	ldi	r25, -1		;	rjmp	40f		;/27:	cpi	r21, 'u'	;Is type unsigned decimal?	ldi	r20, 10		;	breq	40f		;/	cpi	r21, 'X'	;Is type hexdecimal?	ldi	r20, 16		;	breq	40f		;/	cpi	r21, 'b'	;Is type binary?	ldi	r20, 2		;	breq	40f		;/	ret			;abort40:	push	ZH		;Output the value	push	ZL		;	rcall	xitoa		;42:	pop	ZL		;	pop	ZH		;	rjmp	0b		;/50:	push	ZH		;Put a string on the RAM	push	ZL	_MOVW	ZH,ZL, r25,r2451:	ld	r24, Z+	cpi	r24, 0	breq	42b	rcall	xputc	rjmp	51b60:	push	ZH		;Put a string on the ROM	push	ZL	rcall	xputs	rjmp	42b.endfunc.func xprintf.global xprintfxprintf:	push	YH	push	YL	in	YL, _SFR_IO_ADDR(SPL)#ifdef SPH	in	YH, _SFR_IO_ADDR(SPH)#else	clr	YH#endif	adiw	YL, 5		;Y = pointer to arguments	rcall	xvprintf	pop	YL	pop	YH	ret.endfunc#if USE_XSPRINTF.func xsprintfputram:	_MOVW	ZH,ZL, r15,r14	st	Z+, r24	_MOVW	r15,r14, ZH,ZL	ret.global xsprintfxsprintf:	push	YH	push	YL	in	YL, _SFR_IO_ADDR(SPL)#ifdef SPH	in	YH, _SFR_IO_ADDR(SPH)#else	clr	YH#endif	adiw	YL, 5		;Y = pointer to arguments	lds	ZL, xfunc_out+0	;Save registered output function	lds	ZH, xfunc_out+1	;	push	ZL		;	push	ZH		;/	ldi	ZL, lo8(pm(putram));Set local output function	ldi	ZH, hi8(pm(putram));	sts	xfunc_out+0, ZL	;	sts	xfunc_out+1, ZH	;/	push	r15		;Initialize pointer to string buffer	push	r14		;	ld	r14, Y+		;	ld	r15, Y+		;/	rcall	xvprintf	_MOVW	ZH,ZL, r15,r14	;Terminate string	st	Z, r1		;	pop	r14		;	pop	r15		;/	pop	ZH		;Restore registered output function	pop	ZL		;	sts	xfunc_out+0, ZL	;	sts	xfunc_out+1, ZH	;/	pop	YL	pop	YH	ret.endfunc#endif#if USE_XFPRINTF.func xfprintf.global xfprintfxfprintf:	push	YH	push	YL	in	YL, _SFR_IO_ADDR(SPL)#ifdef SPH	in	YH, _SFR_IO_ADDR(SPH)#else	clr	YH#endif	adiw	YL, 5		;Y = pointer to arguments	lds	ZL, xfunc_out+0	;Save registered output function	lds	ZH, xfunc_out+1	;	push	ZL		;	push	ZH		;/	ld	ZL, Y+		;Set output function	ld	ZH, Y+		;	sts	xfunc_out+0, ZL	;	sts	xfunc_out+1, ZH	;/	rcall	xvprintf	pop	ZH		;Restore registered output function	pop	ZL		;	sts	xfunc_out+0, ZL	;	sts	xfunc_out+1, ZH	;/	pop	YL	pop	YH	ret.endfunc#endif#endif;---------------------------------------------------------------------------; Extended numeral string input;;Prototype:; char xatoi (           /* 1: Successful, 0: Failed */;      const char **str, /* pointer to pointer to source string */;      long *res         /* result */; );;#if USE_XATOI.func xatoi.global xatoixatoi:	_MOVW	r1, r0, r23, r22	_MOVW	XH, XL, r25, r24	ld	ZL, X+	ld	ZH, X+	clr	r18		;r21:r18 = 0;	clr	r19		;	clr	r20		;	clr	r21		;/	clt			;T = 0;	ldi	r25, 10		;r25 = 10;	rjmp	41f		;/40:	adiw	ZL, 1		;Z++;41:	ld	r22, Z		;r22 = *Z;	cpi	r22, ' '	;if(r22 == ' ') continue	breq	40b		;/	brcs	70f		;if(r22 < ' ') error;	cpi	r22, '-'	;if(r22 == '-') {	brne	42f		; T = 1;	set			; continue;	rjmp	40b		;}42:	cpi	r22, '9'+1	;if(r22 > '9') error;	brcc	70f		;/	cpi	r22, '0'	;if(r22 < '0') error;	brcs	70f		;/	brne	51f		;if(r22 > '0') cv_start;	ldi	r25, 8		;r25 = 8;	adiw	ZL, 1		;r22 = *(++Z);	ld	r22, Z		;/	cpi	r22, ' '+1	;if(r22 <= ' ') exit;	brcs	80f		;/	cpi	r22, 'b'	;if(r22 == 'b') {	brne	43f		; r25 = 2;	ldi	r25, 2		; cv_start;	rjmp	50f		;}43:	cpi	r22, 'x'	;if(r22 != 'x') error;	brne	51f		;/	ldi	r25, 16		;r25 = 16;50:	adiw	ZL, 1		;Z++;	ld	r22, Z		;r22 = *Z;51:	cpi	r22, ' '+1	;if(r22 <= ' ') break;	brcs	80f		;/	cpi	r22, 'a'	;if(r22 >= 'a') r22 =- 0x20;	brcs	52f		;	subi	r22, 0x20	;/52:	subi	r22, '0'	;if((r22 -= '0') < 0) error;	brcs	70f		;/	cpi	r22, 10		;if(r22 >= 10) {	brcs	53f		; r22 -= 7;	subi	r22, 7		; if(r22 < 10) 	cpi	r22, 10		;	brcs	70f		;}53:	cp	r22, r25	;if(r22 >= r25) error;	brcc	70f		;/60:	ldi	r24, 33		;r21:r18 *= r25;	sub	r23, r23	;61:	brcc	62f		;	add	r23, r25	;62:	lsr	r23		;	ror	r21		;	ror	r20		;	ror	r19		;	ror	r18		;	dec	r24		;	brne	61b		;/	add	r18, r22	;r21:r18 += r22;	adc	r19, r24	;	adc	r20, r24	;	adc	r21, r24	;/	rjmp	50b		;repeat70:	ldi	r24, 0	rjmp	81f80:	ldi	r24, 181:	brtc	82f	clr	r22	com	r18	com	r19	com	r20	com	r21	adc	r18, r22	adc	r19, r22	adc	r20, r22	adc	r21, r2282:	st	-X, ZH	st	-X, ZL	_MOVW	XH, XL, r1, r0	st	X+, r18	st	X+, r19	st	X+, r20	st	X+, r21	clr	r1	ret.endfunc#endif
 |