]> git.friedersdorff.com Git - max/tmk_keyboard.git/commitdiff
Add xprintf(xitoa) from elm-chan.org
authortmk <nobody@nowhere>
Tue, 14 May 2013 07:16:57 +0000 (16:16 +0900)
committertmk <nobody@nowhere>
Tue, 14 May 2013 07:16:57 +0000 (16:16 +0900)
common.mk
common/debug.h
common/debug_config.h [new file with mode: 0644]
common/nodebug.h [new file with mode: 0644]
common/print.c
common/print.h
common/util.c
common/util.h
common/xprintf.S [new file with mode: 0644]
common/xprintf.h [new file with mode: 0644]

index 810f802c66d6ba56c56e13d1bb1e0980dc970f0f..5f47e5c1bc3de8faa372ba6f98c04e8d6a0a722b 100644 (file)
--- a/common.mk
+++ b/common.mk
@@ -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
 
 
index cac682703deccc75d23fe5d74e3ab490e3645e82..8aaa5ed915e2b62a9ada6ff3b9e6b628cc21122c 100644 (file)
@@ -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 (file)
index 0000000..e00fd10
--- /dev/null
@@ -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 (file)
index 0000000..aec790b
--- /dev/null
@@ -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
index 329f835125ac569397a256b517a78e35cc079c9f..783bb4e9bb676a39b979be1405988b2e99991ce6 100644 (file)
@@ -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
 
 #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
index 80858b3bc519b97ce2fee33fd5f0cda0fe0494ef..930e84be99d555871aec946f27cf2c49f909eb76 100644 (file)
@@ -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
 #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))
 
 
 
 #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)
index 6d4d6bfda1801550c68e3d04c8a37d214a45f8c5..7e0d542993a955be815c2dbb495793f40ed68dd1 100644 (file)
@@ -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;
+}
index 4b8b5ca3a49dcffcef00111ca8d626bcaf00c20b..7451cc084da9e4483977411dc1ed19eb99475d5a 100644 (file)
@@ -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 (file)
index 0000000..b5a97b2
--- /dev/null
@@ -0,0 +1,500 @@
+;---------------------------------------------------------------------------;\r
+; Extended itoa, puts, printf and atoi                     (C)ChaN, 2011\r
+;---------------------------------------------------------------------------;\r
+\r
+                               // Base size is 152 bytes\r
+#define        CR_CRLF         0       // Convert \n to \r\n (+10 bytes)\r
+#define USE_XPRINTF    1       // Enable xprintf function (+194 bytes)\r
+#define USE_XSPRINTF   0       // Add xsprintf function (+78 bytes)\r
+#define USE_XFPRINTF   0       // Add xfprintf function (+54 bytes)\r
+#define USE_XATOI      0       // Enable xatoi function (+182 bytes)\r
+\r
+\r
+#if FLASHEND > 0x1FFFF\r
+#error xitoa module does not support 256K devices\r
+#endif\r
+\r
+.nolist\r
+#include <avr/io.h>    // Include device specific definitions.\r
+.list\r
+\r
+#ifdef SPM_PAGESIZE    // Recent devices have "lpm Rd,Z+" and "movw".\r
+.macro _LPMI   reg\r
+       lpm     \reg, Z+\r
+.endm\r
+.macro _MOVW   dh,dl, sh,sl\r
+       movw    \dl, \sl\r
+.endm\r
+#else                  // Earlier devices do not have "lpm Rd,Z+" nor "movw".\r
+.macro _LPMI   reg\r
+       lpm\r
+       mov     \reg, r0\r
+       adiw    ZL, 1\r
+.endm\r
+.macro _MOVW   dh,dl, sh,sl\r
+       mov     \dl, \sl\r
+       mov     \dh, \sh\r
+.endm\r
+#endif\r
+\r
+\r
+\r
+;---------------------------------------------------------------------------\r
+; Stub function to forward to user output function\r
+;\r
+;Prototype: void xputc (char chr       // a character to be output\r
+;                      );\r
+;Size: 12/12 words\r
+\r
+.section .bss\r
+.global xfunc_out      ; xfunc_out must be initialized before using this module.\r
+xfunc_out:     .ds.w   1\r
+.section .text\r
+\r
+\r
+.func xputc\r
+.global xputc\r
+xputc:\r
+#if CR_CRLF\r
+       cpi     r24, 10         ;LF --> CRLF\r
+       brne    1f              ;\r
+       ldi     r24, 13         ;\r
+       rcall   1f              ;\r
+       ldi     r24, 10         ;/\r
+1:\r
+#endif\r
+       push    ZH\r
+       push    ZL\r
+       lds     ZL, xfunc_out+0 ;Pointer to the registered output function.\r
+       lds     ZH, xfunc_out+1 ;/\r
+       sbiw    ZL, 0           ;Skip if null\r
+       breq    2f              ;/\r
+       icall\r
+2:     pop     ZL\r
+       pop     ZH\r
+       ret\r
+.endfunc\r
+\r
+\r
+\r
+;---------------------------------------------------------------------------\r
+; Direct ROM string output\r
+;\r
+;Prototype: void xputs (const prog_char *str // rom string to be output\r
+;                      );\r
+\r
+.func xputs\r
+.global xputs\r
+xputs:\r
+       _MOVW   ZH,ZL, r25,r24  ; Z = pointer to rom string\r
+1:     _LPMI   r24\r
+       cpi     r24, 0\r
+       breq    2f\r
+       rcall   xputc\r
+       rjmp    1b\r
+2:     ret\r
+.endfunc\r
+\r
+\r
+;---------------------------------------------------------------------------\r
+; Extended direct numeral string output (32bit version)\r
+;\r
+;Prototype: void xitoa (long value,    // value to be output\r
+;                       char radix,    // radix\r
+;                       char width);   // minimum width\r
+;\r
+\r
+.func xitoa\r
+.global xitoa\r
+xitoa:\r
+                               ;r25:r22 = value, r20 = base, r18 = digits\r
+       clr     r31             ;r31 = stack level\r
+       ldi     r30, ' '        ;r30 = sign\r
+       ldi     r19, ' '        ;r19 = filler\r
+       sbrs    r20, 7          ;When base indicates signd format and the value\r
+       rjmp    0f              ;is minus, add a '-'.\r
+       neg     r20             ;\r
+       sbrs    r25, 7          ;\r
+       rjmp    0f              ;\r
+       ldi     r30, '-'        ;\r
+       com     r22             ;\r
+       com     r23             ;\r
+       com     r24             ;\r
+       com     r25             ;\r
+       adc     r22, r1         ;\r
+       adc     r23, r1         ;\r
+       adc     r24, r1         ;\r
+       adc     r25, r1         ;/\r
+0:     sbrs    r18, 7          ;When digits indicates zero filled,\r
+       rjmp    1f              ;filler is '0'.\r
+       neg     r18             ;\r
+       ldi     r19, '0'        ;/\r
+                               ;----- string conversion loop\r
+1:     ldi     r21, 32         ;r26 = r25:r22 % r20\r
+       clr     r26             ;r25:r22 /= r20\r
+2:     lsl     r22             ;\r
+       rol     r23             ;\r
+       rol     r24             ;\r
+       rol     r25             ;\r
+       rol     r26             ;\r
+       cp      r26, r20        ;\r
+       brcs    3f              ;\r
+       sub     r26, r20        ;\r
+       inc     r22             ;\r
+3:     dec     r21             ;\r
+       brne    2b              ;/\r
+       cpi     r26, 10         ;r26 is a numeral digit '0'-'F'\r
+       brcs    4f              ;\r
+       subi    r26, -7         ;\r
+4:     subi    r26, -'0'       ;/\r
+       push    r26             ;Stack it\r
+       inc     r31             ;/\r
+       cp      r22, r1         ;Repeat until r25:r22 gets zero\r
+       cpc     r23, r1         ;\r
+       cpc     r24, r1         ;\r
+       cpc     r25, r1         ;\r
+       brne    1b              ;/\r
+\r
+       cpi     r30, '-'        ;Minus sign if needed\r
+       brne    5f              ;\r
+       push    r30             ;\r
+       inc     r31             ;/\r
+5:     cp      r31, r18        ;Filler\r
+       brcc    6f              ;\r
+       push    r19             ;\r
+       inc     r31             ;\r
+       rjmp    5b              ;/\r
+\r
+6:     pop     r24             ;Flush stacked digits and exit\r
+       rcall   xputc           ;\r
+       dec     r31             ;\r
+       brne    6b              ;/\r
+\r
+       ret\r
+.endfunc\r
+\r
+\r
+\r
+;---------------------------------------------------------------------------;\r
+; Formatted string output (16/32bit version)\r
+;\r
+;Prototype:\r
+; void xprintf (const prog_char *format, ...);\r
+; void xsprintf(char*, const prog_char *format, ...);\r
+; void xfprintf(void(*func)(char), const prog_char *format, ...);\r
+;\r
+\r
+#if USE_XPRINTF\r
+\r
+.func xvprintf\r
+xvprintf:\r
+       ld      ZL, Y+          ;Z = pointer to format string\r
+       ld      ZH, Y+          ;/\r
+\r
+0:     _LPMI   r24             ;Get a format char\r
+       cpi     r24, 0          ;End of format string?\r
+       breq    90f             ;/\r
+       cpi     r24, '%'        ;Is format?\r
+       breq    20f             ;/\r
+1:     rcall   xputc           ;Put a normal character\r
+       rjmp    0b              ;/\r
+90:    ret\r
+\r
+20:    ldi     r18, 0          ;r18: digits\r
+       clt                     ;T: filler\r
+       _LPMI   r21             ;Get flags\r
+       cpi     r21, '%'        ;Is a %?\r
+       breq    1b              ;/\r
+       cpi     r21, '0'        ;Zero filled?\r
+       brne    23f             ;\r
+       set                     ;/\r
+22:    _LPMI   r21             ;Get width\r
+23:    cpi     r21, '9'+1      ;\r
+       brcc    24f             ;\r
+       subi    r21, '0'        ;\r
+       brcs    90b             ;\r
+       lsl     r18             ;\r
+       mov     r0, r18         ;\r
+       lsl     r18             ;\r
+       lsl     r18             ;\r
+       add     r18, r0         ;\r
+       add     r18, r21        ;\r
+       rjmp    22b             ;/\r
+\r
+24:    brtc    25f             ;get value (low word)\r
+       neg     r18             ;\r
+25:    ld      r24, Y+         ;\r
+       ld      r25, Y+         ;/\r
+       cpi     r21, 'c'        ;Is type character?\r
+       breq    1b              ;/\r
+       cpi     r21, 's'        ;Is type RAM string?\r
+       breq    50f             ;/\r
+       cpi     r21, 'S'        ;Is type ROM string?\r
+       breq    60f             ;/\r
+       _MOVW   r23,r22,r25,r24 ;r25:r22 = value\r
+       clr     r24             ;\r
+       clr     r25             ;\r
+       clt                     ;/\r
+       cpi     r21, 'l'        ;Is long int?\r
+       brne    26f             ;\r
+       ld      r24, Y+         ;get value (high word)\r
+       ld      r25, Y+         ;\r
+       set                     ;\r
+       _LPMI   r21             ;/\r
+26:    cpi     r21, 'd'        ;Is type signed decimal?\r
+       brne    27f             ;/\r
+       ldi     r20, -10        ;\r
+       brts    40f             ;\r
+       sbrs    r23, 7          ;\r
+       rjmp    40f             ;\r
+       ldi     r24, -1         ;\r
+       ldi     r25, -1         ;\r
+       rjmp    40f             ;/\r
+27:    cpi     r21, 'u'        ;Is type unsigned decimal?\r
+       ldi     r20, 10         ;\r
+       breq    40f             ;/\r
+       cpi     r21, 'X'        ;Is type hexdecimal?\r
+       ldi     r20, 16         ;\r
+       breq    40f             ;/\r
+       cpi     r21, 'b'        ;Is type binary?\r
+       ldi     r20, 2          ;\r
+       breq    40f             ;/\r
+       ret                     ;abort\r
+40:    push    ZH              ;Output the value\r
+       push    ZL              ;\r
+       rcall   xitoa           ;\r
+42:    pop     ZL              ;\r
+       pop     ZH              ;\r
+       rjmp    0b              ;/\r
+\r
+50:    push    ZH              ;Put a string on the RAM\r
+       push    ZL\r
+       _MOVW   ZH,ZL, r25,r24\r
+51:    ld      r24, Z+\r
+       cpi     r24, 0\r
+       breq    42b\r
+       rcall   xputc\r
+       rjmp    51b\r
+\r
+60:    push    ZH              ;Put a string on the ROM\r
+       push    ZL\r
+       rcall   xputs\r
+       rjmp    42b\r
+.endfunc\r
+\r
+\r
+.func __xprintf\r
+.global __xprintf\r
+__xprintf:\r
+       push    YH\r
+       push    YL\r
+       in      YL, _SFR_IO_ADDR(SPL)\r
+#ifdef SPH\r
+       in      YH, _SFR_IO_ADDR(SPH)\r
+#else\r
+       clr     YH\r
+#endif\r
+       adiw    YL, 5           ;Y = pointer to arguments\r
+       rcall   xvprintf\r
+       pop     YL\r
+       pop     YH\r
+       ret\r
+.endfunc\r
+\r
+\r
+#if USE_XSPRINTF\r
+\r
+.func __xsprintf\r
+putram:\r
+       _MOVW   ZH,ZL, r15,r14\r
+       st      Z+, r24\r
+       _MOVW   r15,r14, ZH,ZL\r
+       ret\r
+.global __xsprintf\r
+__xsprintf:\r
+       push    YH\r
+       push    YL\r
+       in      YL, _SFR_IO_ADDR(SPL)\r
+#ifdef SPH\r
+       in      YH, _SFR_IO_ADDR(SPH)\r
+#else\r
+       clr     YH\r
+#endif\r
+       adiw    YL, 5           ;Y = pointer to arguments\r
+       lds     ZL, xfunc_out+0 ;Save registered output function\r
+       lds     ZH, xfunc_out+1 ;\r
+       push    ZL              ;\r
+       push    ZH              ;/\r
+       ldi     ZL, lo8(pm(putram));Set local output function\r
+       ldi     ZH, hi8(pm(putram));\r
+       sts     xfunc_out+0, ZL ;\r
+       sts     xfunc_out+1, ZH ;/\r
+       push    r15             ;Initialize pointer to string buffer\r
+       push    r14             ;\r
+       ld      r14, Y+         ;\r
+       ld      r15, Y+         ;/\r
+       rcall   xvprintf\r
+       _MOVW   ZH,ZL, r15,r14  ;Terminate string\r
+       st      Z, r1           ;\r
+       pop     r14             ;\r
+       pop     r15             ;/\r
+       pop     ZH              ;Restore registered output function\r
+       pop     ZL              ;\r
+       sts     xfunc_out+0, ZL ;\r
+       sts     xfunc_out+1, ZH ;/\r
+       pop     YL\r
+       pop     YH\r
+       ret\r
+.endfunc\r
+#endif\r
+\r
+\r
+#if USE_XFPRINTF\r
+.func __xfprintf\r
+.global __xfprintf\r
+__xfprintf:\r
+       push    YH\r
+       push    YL\r
+       in      YL, _SFR_IO_ADDR(SPL)\r
+#ifdef SPH\r
+       in      YH, _SFR_IO_ADDR(SPH)\r
+#else\r
+       clr     YH\r
+#endif\r
+       adiw    YL, 5           ;Y = pointer to arguments\r
+       lds     ZL, xfunc_out+0 ;Save registered output function\r
+       lds     ZH, xfunc_out+1 ;\r
+       push    ZL              ;\r
+       push    ZH              ;/\r
+       ld      ZL, Y+          ;Set output function\r
+       ld      ZH, Y+          ;\r
+       sts     xfunc_out+0, ZL ;\r
+       sts     xfunc_out+1, ZH ;/\r
+       rcall   xvprintf\r
+       pop     ZH              ;Restore registered output function\r
+       pop     ZL              ;\r
+       sts     xfunc_out+0, ZL ;\r
+       sts     xfunc_out+1, ZH ;/\r
+       pop     YL\r
+       pop     YH\r
+       ret\r
+.endfunc\r
+#endif\r
+\r
+#endif\r
+\r
+\r
+\r
+;---------------------------------------------------------------------------\r
+; Extended numeral string input\r
+;\r
+;Prototype:\r
+; char xatoi (           /* 1: Successful, 0: Failed */\r
+;      const char **str, /* pointer to pointer to source string */\r
+;      long *res         /* result */\r
+; );\r
+;\r
+\r
+\r
+#if USE_XATOI\r
+.func xatoi\r
+.global xatoi\r
+xatoi:\r
+       _MOVW   r1, r0, r23, r22\r
+       _MOVW   XH, XL, r25, r24\r
+       ld      ZL, X+\r
+       ld      ZH, X+\r
+       clr     r18             ;r21:r18 = 0;\r
+       clr     r19             ;\r
+       clr     r20             ;\r
+       clr     r21             ;/\r
+       clt                     ;T = 0;\r
+\r
+       ldi     r25, 10         ;r25 = 10;\r
+       rjmp    41f             ;/\r
+40:    adiw    ZL, 1           ;Z++;\r
+41:    ld      r22, Z          ;r22 = *Z;\r
+       cpi     r22, ' '        ;if(r22 == ' ') continue\r
+       breq    40b             ;/\r
+       brcs    70f             ;if(r22 < ' ') error;\r
+       cpi     r22, '-'        ;if(r22 == '-') {\r
+       brne    42f             ; T = 1;\r
+       set                     ; continue;\r
+       rjmp    40b             ;}\r
+42:    cpi     r22, '9'+1      ;if(r22 > '9') error;\r
+       brcc    70f             ;/\r
+       cpi     r22, '0'        ;if(r22 < '0') error;\r
+       brcs    70f             ;/\r
+       brne    51f             ;if(r22 > '0') cv_start;\r
+       ldi     r25, 8          ;r25 = 8;\r
+       adiw    ZL, 1           ;r22 = *(++Z);\r
+       ld      r22, Z          ;/\r
+       cpi     r22, ' '+1      ;if(r22 <= ' ') exit;\r
+       brcs    80f             ;/\r
+       cpi     r22, 'b'        ;if(r22 == 'b') {\r
+       brne    43f             ; r25 = 2;\r
+       ldi     r25, 2          ; cv_start;\r
+       rjmp    50f             ;}\r
+43:    cpi     r22, 'x'        ;if(r22 != 'x') error;\r
+       brne    51f             ;/\r
+       ldi     r25, 16         ;r25 = 16;\r
+\r
+50:    adiw    ZL, 1           ;Z++;\r
+       ld      r22, Z          ;r22 = *Z;\r
+51:    cpi     r22, ' '+1      ;if(r22 <= ' ') break;\r
+       brcs    80f             ;/\r
+       cpi     r22, 'a'        ;if(r22 >= 'a') r22 =- 0x20;\r
+       brcs    52f             ;\r
+       subi    r22, 0x20       ;/\r
+52:    subi    r22, '0'        ;if((r22 -= '0') < 0) error;\r
+       brcs    70f             ;/\r
+       cpi     r22, 10         ;if(r22 >= 10) {\r
+       brcs    53f             ; r22 -= 7;\r
+       subi    r22, 7          ; if(r22 < 10) \r
+       cpi     r22, 10         ;\r
+       brcs    70f             ;}\r
+53:    cp      r22, r25        ;if(r22 >= r25) error;\r
+       brcc    70f             ;/\r
+60:    ldi     r24, 33         ;r21:r18 *= r25;\r
+       sub     r23, r23        ;\r
+61:    brcc    62f             ;\r
+       add     r23, r25        ;\r
+62:    lsr     r23             ;\r
+       ror     r21             ;\r
+       ror     r20             ;\r
+       ror     r19             ;\r
+       ror     r18             ;\r
+       dec     r24             ;\r
+       brne    61b             ;/\r
+       add     r18, r22        ;r21:r18 += r22;\r
+       adc     r19, r24        ;\r
+       adc     r20, r24        ;\r
+       adc     r21, r24        ;/\r
+       rjmp    50b             ;repeat\r
+\r
+70:    ldi     r24, 0\r
+       rjmp    81f\r
+80:    ldi     r24, 1\r
+81:    brtc    82f\r
+       clr     r22\r
+       com     r18\r
+       com     r19\r
+       com     r20\r
+       com     r21\r
+       adc     r18, r22\r
+       adc     r19, r22\r
+       adc     r20, r22\r
+       adc     r21, r22\r
+82:    st      -X, ZH\r
+       st      -X, ZL\r
+       _MOVW   XH, XL, r1, r0\r
+       st      X+, r18\r
+       st      X+, r19\r
+       st      X+, r20\r
+       st      X+, r21\r
+       clr     r1\r
+       ret\r
+.endfunc\r
+#endif\r
+\r
+\r
diff --git a/common/xprintf.h b/common/xprintf.h
new file mode 100644 (file)
index 0000000..cddec99
--- /dev/null
@@ -0,0 +1,103 @@
+/*---------------------------------------------------------------------------\r
+   Extended itoa, puts and printf                    (C)ChaN, 2011\r
+-----------------------------------------------------------------------------*/\r
+\r
+#ifndef XPRINTF_H\r
+#define XPRINTF_H\r
+\r
+#include <inttypes.h>\r
+#include <avr/pgmspace.h>\r
+\r
+extern void (*xfunc_out)(uint8_t);\r
+#define xdev_out(func) xfunc_out = (void(*)(uint8_t))(func)\r
+\r
+/* This is a pointer to user defined output function. It must be initialized\r
+   before using this modle.\r
+*/\r
+\r
+void xputc(char chr);\r
+\r
+/* This is a stub function to forward outputs to user defined output function.\r
+   All outputs from this module are output via this function.\r
+*/\r
+\r
+\r
+/*-----------------------------------------------------------------------------*/\r
+void xputs(const prog_char *string);\r
+\r
+/*  The string placed in the ROM is forwarded to xputc() directly.\r
+*/\r
+\r
+\r
+/*-----------------------------------------------------------------------------*/\r
+void xitoa(long value, char radix, char width);\r
+\r
+/* Extended itoa().\r
+\r
+      value  radix  width   output\r
+        100     10      6   "   100"\r
+        100     10     -6   "000100"\r
+        100     10      0   "100"\r
+ 4294967295     10      0   "4294967295"\r
+ 4294967295    -10      0   "-1"\r
+     655360     16     -8   "000A0000"\r
+       1024     16      0   "400"\r
+       0x55      2     -8   "01010101"\r
+*/\r
+\r
+\r
+/*-----------------------------------------------------------------------------*/\r
+#define xprintf(format, ...)            __xprintf(PSTR(format), ##__VA_ARGS__)\r
+#define xsprintf(str, format, ...)      __xsprintf(str, PSTR(format), ##__VA_ARGS__)\r
+#define xfprintf(func, format, ...)     __xfprintf(func, PSTR(format), ##__VA_ARGS__)\r
+\r
+void __xprintf(const prog_char *format, ...);  /* Send formatted string to the registered device */\r
+void __xsprintf(char*, const prog_char *format, ...);  /* Put formatted string to the memory */\r
+void __xfprintf(void(*func)(uint8_t), const prog_char *format, ...); /* Send formatted string to the specified device */\r
+\r
+/* Format string is placed in the ROM. The format flags is similar to printf().\r
+\r
+   %[flag][width][size]type\r
+\r
+   flag\r
+     A '0' means filled with '0' when output is shorter than width.\r
+     ' ' is used in default. This is effective only numeral type.\r
+   width\r
+     Minimum width in decimal number. This is effective only numeral type.\r
+     Default width is zero.\r
+   size\r
+     A 'l' means the argument is long(32bit). Default is short(16bit).\r
+     This is effective only numeral type.\r
+   type\r
+     'c' : Character, argument is the value\r
+     's' : String placed on the RAM, argument is the pointer\r
+     'S' : String placed on the ROM, argument is the pointer\r
+     'd' : Signed decimal, argument is the value\r
+     'u' : Unsigned decimal, argument is the value\r
+     'X' : Hexdecimal, argument is the value\r
+     'b' : Binary, argument is the value\r
+     '%' : '%'\r
+\r
+*/\r
+\r
+\r
+/*-----------------------------------------------------------------------------*/\r
+char xatoi(char **str, long *ret);\r
+\r
+/* Get value of the numeral string. \r
+\r
+  str\r
+    Pointer to pointer to source string\r
+\r
+    "0b11001010" binary\r
+    "0377" octal\r
+    "0xff800" hexdecimal\r
+    "1250000" decimal\r
+    "-25000" decimal\r
+\r
+  ret\r
+    Pointer to return value\r
+*/\r
+\r
+#endif\r
+\r