diff options
| -rw-r--r-- | common.mk | 1 | ||||
| -rw-r--r-- | common/debug.h | 63 | ||||
| -rw-r--r-- | common/debug_config.h | 51 | ||||
| -rw-r--r-- | common/nodebug.h | 49 | ||||
| -rw-r--r-- | common/print.c | 147 | ||||
| -rw-r--r-- | common/print.h | 71 | ||||
| -rw-r--r-- | common/util.c | 22 | ||||
| -rw-r--r-- | common/util.h | 4 | ||||
| -rw-r--r-- | common/xprintf.S | 500 | ||||
| -rw-r--r-- | common/xprintf.h | 103 | 
10 files changed, 789 insertions, 222 deletions
| @@ -11,6 +11,7 @@ SRC +=	$(COMMON_DIR)/host.c \  	$(COMMON_DIR)/print.c \  	$(COMMON_DIR)/bootloader.c \  	$(COMMON_DIR)/suspend.c \ +	$(COMMON_DIR)/xprintf.S \  	$(COMMON_DIR)/util.c diff --git a/common/debug.h b/common/debug.h index cac682703..8aaa5ed91 100644 --- a/common/debug.h +++ b/common/debug.h @@ -18,14 +18,20 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #ifndef DEBUG_H  #define DEBUG_H 1 -#include <stdbool.h>  #include "print.h" +#include "debug_config.h"  #ifndef NO_DEBUG +#define dprint(s)           do { if (debug_enable) print(s); } while (0) +#define dprintln()          do { if (debug_enable) print_crlf(); } while (0) +#define dprintf(fmt, ...)   do { if (debug_enable) __xprintf(PSTR(fmt), ##__VA_ARGS__); } while (0) +#define dmsg(s)             dprintf("%s at %s: %S\n", __FILE__, __LINE__, PSTR(s)) + +/* DO NOT USE these anymore */  #define debug(s)                  do { if (debug_enable) print(s); } while (0) -#define debugln(s)                do { if (debug_enable) println(s); } while (0) +#define debugln(s)                do { if (debug_enable) print_crlf(); } while (0)  #define debug_S(s)                do { if (debug_enable) print_S(s); } while (0)  #define debug_P(s)                do { if (debug_enable) print_P(s); } while (0)  #define debug_msg(s)              do { \ @@ -50,58 +56,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #define debug_bin_reverse(data)   debug_bin8(data)  #else - -#define debug(s) -#define debugln(s) -#define debug_S(s) -#define debug_P(s) -#define debug_msg(s) -#define debug_dec(data) -#define debug_decs(data) -#define debug_hex4(data) -#define debug_hex8(data) -#define debug_hex16(data) -#define debug_hex32(data) -#define debug_bin8(data) -#define debug_bin16(data) -#define debug_bin32(data) -#define debug_bin_reverse8(data) -#define debug_bin_reverse16(data) -#define debug_bin_reverse32(data) -#define debug_hex(data) -#define debug_bin(data) -#define debug_bin_reverse(data) - -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* NOTE: Not portable. Bit field order depends on implementation */ -typedef union { -    uint8_t raw; -    struct { -        bool enable:1; -        bool matrix:1; -        bool keyboard:1; -        bool mouse:1; -        uint8_t reserved:4; -    }; -} debug_config_t; -debug_config_t debug_config; - -/* for backward compatibility */ -#define debug_enable    (debug_config.enable) -#define debug_matrix    (debug_config.matrix) -#define debug_keyboard  (debug_config.keyboard) -#define debug_mouse     (debug_config.mouse) - - -#ifdef __cplusplus -} +#include "nodebug.h"  #endif  #endif diff --git a/common/debug_config.h b/common/debug_config.h new file mode 100644 index 000000000..e00fd1033 --- /dev/null +++ b/common/debug_config.h @@ -0,0 +1,51 @@ +/* +Copyright 2013 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program.  If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef DEBUG_CONFIG_H +#define DEBUG_CONFIG_H 1 + +#include <stdbool.h> + + +#ifdef __cplusplus +extern "C" { +#endif + +/* NOTE: Not portable. Bit field order depends on implementation */ +typedef union { +    uint8_t raw; +    struct { +        bool enable:1; +        bool matrix:1; +        bool keyboard:1; +        bool mouse:1; +        uint8_t reserved:4; +    }; +} debug_config_t; +debug_config_t debug_config; + +/* for backward compatibility */ +#define debug_enable    (debug_config.enable) +#define debug_matrix    (debug_config.matrix) +#define debug_keyboard  (debug_config.keyboard) +#define debug_mouse     (debug_config.mouse) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/common/nodebug.h b/common/nodebug.h new file mode 100644 index 000000000..aec790bbc --- /dev/null +++ b/common/nodebug.h @@ -0,0 +1,49 @@ +/* +Copyright 2013 Jun Wako <wakojun@gmail.com> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program.  If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef NODEBUG_H +#define NODEBUG_H 1 + +#include "debug_config.h" + +#define dprint(s) +#define dprintln(s) +#define dprintf(fmt, ...) +#define dmsg(s) + +#define debug(s) +#define debugln(s) +#define debug_S(s) +#define debug_P(s) +#define debug_msg(s) +#define debug_dec(data) +#define debug_decs(data) +#define debug_hex4(data) +#define debug_hex8(data) +#define debug_hex16(data) +#define debug_hex32(data) +#define debug_bin8(data) +#define debug_bin16(data) +#define debug_bin32(data) +#define debug_bin_reverse8(data) +#define debug_bin_reverse16(data) +#define debug_bin_reverse32(data) +#define debug_hex(data) +#define debug_bin(data) +#define debug_bin_reverse(data) + +#endif diff --git a/common/print.c b/common/print.c index 329f83512..783bb4e9b 100644 --- a/common/print.c +++ b/common/print.c @@ -1,4 +1,4 @@ -/* Copyright 2012 Jun Wako <wakojun@gmail.com> */ +/* Copyright 2012,2013 Jun Wako <wakojun@gmail.com> */  /* Very basic print functions, intended to be used with usb_debug_only.c   * http://www.pjrc.com/teensy/   * Copyright (c) 2008 PJRC.COM, LLC @@ -29,20 +29,14 @@  #ifndef NO_PRINT -#define sendchar(c)    do { if (print_sendchar_func) (print_sendchar_func)(c); } while (0) +#define sendchar(c)    xputc(c) -static int8_t (*print_sendchar_func)(uint8_t) = 0; -  void print_set_sendchar(int8_t (*sendchar_func)(uint8_t))  { -    print_sendchar_func = sendchar_func; +    xdev_out(sendchar_func);  } -/* print string stored in data memory(SRAM) - *     print_P("hello world"); - * This consumes precious SRAM memory space for string. - */  void print_S(const char *s)  {      uint8_t c; @@ -54,140 +48,15 @@ void print_S(const char *s)      }  } -/* print string stored in program memory(FLASH) - *     print_P(PSTR("hello world"); - * This consumes relatively abundant FLASH memory area not SRAM. - */ -void print_P(const char *s) -{ -    uint8_t c; -    while (1) { -        c = pgm_read_byte(s++); -        if (!c) break; -        if (c == '\n') sendchar('\r'); -        sendchar(c); -    } -} - -void print_CRLF(void) -{ -    sendchar('\r'); sendchar('\n'); -} - - -#define SIGNED  0x80 -#define BIN     2 -#define OCT     8 -#define DEC     10 -#define HEX     16 - -static inline -char itoc(uint8_t i) -{ -    return (i < 10 ? '0' + i : 'A' + i - 10); -} - -static inline -void print_int(uint16_t data, uint8_t base) -{ -    char buf[7] = {'\0'}; -    char *p = &buf[6]; -    if ((base & SIGNED) && (data & 0x8000)) { -        data = -data; -        buf[0] = '-'; -    } -    base &= ~SIGNED; -    uint16_t n; -    do { -        n = data; -        data /= base; -        *(--p) = itoc(n - data*base); -    } while (data); -    if (buf[0]) *(--p) = buf[0]; -    print_S(p); -} - -void print_dec(uint16_t data) -{ -    print_int(data, DEC); -} - -void print_decs(int16_t data) -{ -    print_int(data, DEC|SIGNED); -} - - -void print_hex4(uint8_t data) -{ -    sendchar(data + ((data < 10) ? '0' : 'A' - 10)); -} - -void print_hex8(uint8_t data) -{ -    print_hex4(data>>4); -    print_hex4(data&0x0F); -} - -void print_hex16(uint16_t data) -{ -    print_hex8(data>>8); -    print_hex8(data); -} - -void print_hex32(uint32_t data) -{ -    print_hex16(data>>16); -    print_hex16(data); -} - -void print_bin4(uint8_t data) -{ -    for (int i = 4; i >= 0; i--) { -        sendchar((data & (1<<i)) ? '1' : '0'); -    } -} - -void print_bin8(uint8_t data) -{ -    for (int i = 7; i >= 0; i--) { -        sendchar((data & (1<<i)) ? '1' : '0'); -    } -} - -void print_bin16(uint16_t data) -{ -    print_bin8(data>>8); -    print_bin8(data); -} - -void print_bin32(uint32_t data) -{ -    print_bin8(data>>24); -    print_bin8(data>>16); -    print_bin8(data>>8); -    print_bin8(data); -} - -void print_bin_reverse8(uint8_t data) -{ -    for (int i = 0; i < 8; i++) { -        sendchar((data & (1<<i)) ? '1' : '0'); -    } -} - -void print_bin_reverse16(uint16_t data) +void print_lf(void)  { -    print_bin_reverse8(data); -    print_bin_reverse8(data>>8); +    sendchar('\n');  } -void print_bin_reverse32(uint32_t data) +void print_crlf(void)  { -    print_bin_reverse8(data); -    print_bin_reverse8(data>>8); -    print_bin_reverse8(data>>16); -    print_bin_reverse8(data>>24); +    sendchar('\r'); +    sendchar('\n');  }  #endif diff --git a/common/print.h b/common/print.h index 80858b3bc..930e84be9 100644 --- a/common/print.h +++ b/common/print.h @@ -28,6 +28,8 @@  #include <stdint.h>  #include <stdbool.h>  #include <avr/pgmspace.h> +#include "xprintf.h" +#include "util.h"  // this macro allows you to write print("some text") and @@ -49,17 +51,17 @@  #define pbin_reverse16(data)    print_bin_reverse16(data)  /* print value utility */ -#define print_val_dec(v)           do { print_P(PSTR(#v ": ")); print_dec(v);  print_P(PSTR("\n")); } while (0) -#define print_val_decs(v)          do { print_P(PSTR(#v ": ")); print_decs(v);  print_P(PSTR("\n")); } while (0) -#define print_val_hex8(v)          do { print_P(PSTR(#v ": ")); print_hex8(v);  print_P(PSTR("\n")); } while (0) -#define print_val_hex16(v)         do { print_P(PSTR(#v ": ")); print_hex16(v); print_P(PSTR("\n")); } while (0) -#define print_val_hex32(v)         do { print_P(PSTR(#v ": ")); print_hex32(v); print_P(PSTR("\n")); } while (0) -#define print_val_bin8(v)          do { print_P(PSTR(#v ": ")); print_bin8(v);  print_P(PSTR("\n")); } while (0) -#define print_val_bin16(v)         do { print_P(PSTR(#v ": ")); print_bin16(v); print_P(PSTR("\n")); } while (0) -#define print_val_bin32(v)         do { print_P(PSTR(#v ": ")); print_bin32(v); print_P(PSTR("\n")); } while (0) -#define print_val_bin_reverse8(v)  do { print_P(PSTR(#v ": ")); print_bin_reverse8(v);  print_P(PSTR("\n")); } while (0) -#define print_val_bin_reverse16(v) do { print_P(PSTR(#v ": ")); print_bin_reverse16(v); print_P(PSTR("\n")); } while (0) -#define print_val_bin_reverse32(v) do { print_P(PSTR(#v ": ")); print_bin_reverse32(v); print_P(PSTR("\n")); } while (0) +#define print_val_dec(v)           xprintf(#v ": %u\n", v) +#define print_val_decs(v)          xprintf(#v ": %d\n", v) +#define print_val_hex8(v)          xprintf(#v ": %X\n", v) +#define print_val_hex16(v)         xprintf(#v ": %02X\n", v) +#define print_val_hex32(v)         xprintf(#v ": %04lX\n", v) +#define print_val_bin8(v)          xprintf(#v ": %08b\n", v) +#define print_val_bin16(v)         xprintf(#v ": %016b\n", v) +#define print_val_bin32(v)         xprintf(#v ": %032lb\n", v) +#define print_val_bin_reverse8(v)  xprintf(#v ": %08b\n", bitrev(v)) +#define print_val_bin_reverse16(v) xprintf(#v ": %016b\n", bitrev16(v)) +#define print_val_bin_reverse32(v) xprintf(#v ": %032lb\n", bitrev32(v)) @@ -68,34 +70,46 @@  #ifdef __cplusplus  extern "C" {  #endif +  /* function pointer of sendchar to be used by print utility */  void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t)); -/* print string stored in data memory(SRAM) */ +/* print string stored in data memory(SRAM) + *     print_S("hello world"); + * This consumes precious SRAM memory space for string. + */  void print_S(const char *s); -/* print string stored in program memory(FLASH) */ -void print_P(const char *s); -void print_CRLF(void); +void print_lf(void); +void print_crlf(void); + + +/* print string stored in program memory(FLASH) + *     print_P(PSTR("hello world"); + * This consumes relatively abundant FLASH memory area not SRAM. + */ +#define print_P(s)          xputs(s)  /* decimal */ -void print_dec(uint16_t data); -void print_decs(int16_t data); +#define print_dec(i)        xprintf("%u", i) +#define print_decs(i)       xprintf("%d", i)  /* hex */ -void print_hex4(uint8_t data); -void print_hex8(uint8_t data); -void print_hex16(uint16_t data); -void print_hex32(uint32_t data); +#define print_hex4(i)       xprintf("%X", i) +#define print_hex8(i)       xprintf("%02X", i) +#define print_hex16(i)      xprintf("%04X", i) +#define print_hex32(i)      xprintf("%08lX", i)  /* binary */ -void print_bin4(uint8_t data); -void print_bin8(uint8_t data); -void print_bin16(uint16_t data); -void print_bin32(uint32_t data); -void print_bin_reverse8(uint8_t data); -void print_bin_reverse16(uint16_t data); -void print_bin_reverse32(uint32_t data); +#define print_bin4(i)       xprintf("%04b", i) +#define print_bin8(i)       xprintf("%08b", i) +#define print_bin16(i)      xprintf("%016b", i) +#define print_bin32(i)      xprintf("%032lb", i) + +#define print_bin_reverse8(i)   xprintf("%08b", bitrev(i)) +#define print_bin_reverse16(i)  xprintf("%016b", bitrev16(i)) +#define print_bin_reverse32(i)  xprintf("%032lb", bitrev32(i)) +  #ifdef __cplusplus  }  #endif @@ -105,7 +119,6 @@ void print_bin_reverse32(uint32_t data);  #define print_set_sendchar(func)  #define print_S(s)  #define print_P(s) -#define print_CRLF()  #define print_dec(data)  #define print_decs(data)  #define print_hex4(data) diff --git a/common/util.c b/common/util.c index 6d4d6bfda..7e0d54299 100644 --- a/common/util.c +++ b/common/util.c @@ -77,3 +77,25 @@ uint8_t biton32(uint32_t bits)      if (bits >> 1) { bits >>= 1; n += 1;}      return n;  } + + + +uint8_t bitrev(uint8_t bits) +{ +    bits = (bits & 0x0f)<<4 | (bits & 0xf0)>>4; +    bits = (bits & 0b00110011)<<2 | (bits & 0b11001100)>>2; +    bits = (bits & 0b01010101)<<1 | (bits & 0b10101010)>>1; +    return bits; +} + +uint16_t bitrev16(uint16_t bits) +{ +    bits = bitrev(bits & 0x00ff)<<8 | bitrev((bits & 0xff00)>>8); +    return bits; +} + +uint32_t bitrev32(uint32_t bits) +{ +    bits = (uint32_t)bitrev16(bits & 0x0000ffff)<<16 | bitrev16((bits & 0xffff0000)>>16); +    return bits; +} diff --git a/common/util.h b/common/util.h index 4b8b5ca3a..7451cc084 100644 --- a/common/util.h +++ b/common/util.h @@ -36,4 +36,8 @@ uint8_t biton(uint8_t bits);  uint8_t biton16(uint16_t bits);  uint8_t biton32(uint32_t bits); +uint8_t  bitrev(uint8_t bits); +uint16_t bitrev16(uint16_t bits); +uint32_t bitrev32(uint32_t bits); +  #endif diff --git a/common/xprintf.S b/common/xprintf.S new file mode 100644 index 000000000..b5a97b20a --- /dev/null +++ b/common/xprintf.S @@ -0,0 +1,500 @@ +;---------------------------------------------------------------------------;
 +; 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	0	// Add xsprintf function (+78 bytes)
 +#define USE_XFPRINTF	0	// Add xfprintf function (+54 bytes)
 +#define USE_XATOI	0	// 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: 12/12 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 xputc
 +xputc:
 +#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		;/
 +	icall
 +2:	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 xputs
 +xputs:
 +	_MOVW	ZH,ZL, r25,r24	; Z = pointer to rom string
 +1:	_LPMI	r24
 +	cpi	r24, 0
 +	breq	2f
 +	rcall	xputc
 +	rjmp	1b
 +2:	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 xitoa
 +xitoa:
 +				;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 loop
 +1:	ldi	r21, 32		;r26 = r25:r22 % r20
 +	clr	r26		;r25:r22 /= r20
 +2:	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 xvprintf
 +xvprintf:
 +	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:	ret
 +
 +20:	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 width
 +23:	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			;abort
 +40:	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,r24
 +51:	ld	r24, Z+
 +	cpi	r24, 0
 +	breq	42b
 +	rcall	xputc
 +	rjmp	51b
 +
 +60:	push	ZH		;Put a string on the ROM
 +	push	ZL
 +	rcall	xputs
 +	rjmp	42b
 +.endfunc
 +
 +
 +.func __xprintf
 +.global __xprintf
 +__xprintf:
 +	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 __xsprintf
 +putram:
 +	_MOVW	ZH,ZL, r15,r14
 +	st	Z+, r24
 +	_MOVW	r15,r14, ZH,ZL
 +	ret
 +.global __xsprintf
 +__xsprintf:
 +	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 __xfprintf
 +__xfprintf:
 +	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 xatoi
 +xatoi:
 +	_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		;repeat
 +
 +70:	ldi	r24, 0
 +	rjmp	81f
 +80:	ldi	r24, 1
 +81:	brtc	82f
 +	clr	r22
 +	com	r18
 +	com	r19
 +	com	r20
 +	com	r21
 +	adc	r18, r22
 +	adc	r19, r22
 +	adc	r20, r22
 +	adc	r21, r22
 +82:	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
 +
 +
 diff --git a/common/xprintf.h b/common/xprintf.h new file mode 100644 index 000000000..cddec9940 --- /dev/null +++ b/common/xprintf.h @@ -0,0 +1,103 @@ +/*---------------------------------------------------------------------------
 +   Extended itoa, puts and printf                    (C)ChaN, 2011
 +-----------------------------------------------------------------------------*/
 +
 +#ifndef XPRINTF_H
 +#define XPRINTF_H
 +
 +#include <inttypes.h>
 +#include <avr/pgmspace.h>
 +
 +extern void (*xfunc_out)(uint8_t);
 +#define xdev_out(func) xfunc_out = (void(*)(uint8_t))(func)
 +
 +/* This is a pointer to user defined output function. It must be initialized
 +   before using this modle.
 +*/
 +
 +void xputc(char chr);
 +
 +/* This is a stub function to forward outputs to user defined output function.
 +   All outputs from this module are output via this function.
 +*/
 +
 +
 +/*-----------------------------------------------------------------------------*/
 +void xputs(const prog_char *string);
 +
 +/*  The string placed in the ROM is forwarded to xputc() directly.
 +*/
 +
 +
 +/*-----------------------------------------------------------------------------*/
 +void xitoa(long value, char radix, char width);
 +
 +/* Extended itoa().
 +
 +      value  radix  width   output
 +        100     10      6   "   100"
 +        100     10     -6   "000100"
 +        100     10      0   "100"
 + 4294967295     10      0   "4294967295"
 + 4294967295    -10      0   "-1"
 +     655360     16     -8   "000A0000"
 +       1024     16      0   "400"
 +       0x55      2     -8   "01010101"
 +*/
 +
 +
 +/*-----------------------------------------------------------------------------*/
 +#define xprintf(format, ...)            __xprintf(PSTR(format), ##__VA_ARGS__)
 +#define xsprintf(str, format, ...)      __xsprintf(str, PSTR(format), ##__VA_ARGS__)
 +#define xfprintf(func, format, ...)     __xfprintf(func, PSTR(format), ##__VA_ARGS__)
 +
 +void __xprintf(const prog_char *format, ...);	/* Send formatted string to the registered device */
 +void __xsprintf(char*, const prog_char *format, ...);	/* Put formatted string to the memory */
 +void __xfprintf(void(*func)(uint8_t), const prog_char *format, ...); /* Send formatted string to the specified device */
 +
 +/* Format string is placed in the ROM. The format flags is similar to printf().
 +
 +   %[flag][width][size]type
 +
 +   flag
 +     A '0' means filled with '0' when output is shorter than width.
 +     ' ' is used in default. This is effective only numeral type.
 +   width
 +     Minimum width in decimal number. This is effective only numeral type.
 +     Default width is zero.
 +   size
 +     A 'l' means the argument is long(32bit). Default is short(16bit).
 +     This is effective only numeral type.
 +   type
 +     'c' : Character, argument is the value
 +     's' : String placed on the RAM, argument is the pointer
 +     'S' : String placed on the ROM, argument is the pointer
 +     'd' : Signed decimal, argument is the value
 +     'u' : Unsigned decimal, argument is the value
 +     'X' : Hexdecimal, argument is the value
 +     'b' : Binary, argument is the value
 +     '%' : '%'
 +
 +*/
 +
 +
 +/*-----------------------------------------------------------------------------*/
 +char xatoi(char **str, long *ret);
 +
 +/* Get value of the numeral string. 
 +
 +  str
 +    Pointer to pointer to source string
 +
 +    "0b11001010" binary
 +    "0377" octal
 +    "0xff800" hexdecimal
 +    "1250000" decimal
 +    "-25000" decimal
 +
 +  ret
 +    Pointer to return value
 +*/
 +
 +#endif
 +
 | 
