diff --git a/common.mk b/common.mk
index 810f802c66d..5f47e5c1bc3 100644
--- 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
 
 
diff --git a/common/action.c b/common/action.c
index 0651887444c..c7c8f71f2cc 100644
--- a/common/action.c
+++ b/common/action.c
@@ -19,7 +19,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "keyboard.h"
 #include "mousekey.h"
 #include "command.h"
-#include "debug.h"
 #include "led.h"
 #include "action_layer.h"
 #include "action_tapping.h"
@@ -27,12 +26,18 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "action_macro.h"
 #include "action.h"
 
+#ifdef DEBUG_ACTION
+#include "debug.h"
+#else
+#include "nodebug.h"
+#endif
+
 
 void action_exec(keyevent_t event)
 {
     if (!IS_NOEVENT(event)) {
-        debug("\n---- action_exec: start -----\n");
-        debug("EVENT: "); debug_event(event); debug("\n");
+        dprint("\n---- action_exec: start -----\n");
+        dprint("EVENT: "); debug_event(event); dprintln();
     }
 
     keyrecord_t record = { .event = event };
@@ -42,7 +47,7 @@ void action_exec(keyevent_t event)
 #else
     process_action(&record);
     if (!IS_NOEVENT(record.event)) {
-        debug("processed: "); debug_record(record); debug("\n");
+        dprint("processed: "); debug_record(record); dprintln();
     }
 #endif
 }
@@ -57,12 +62,12 @@ void process_action(keyrecord_t *record)
     if (IS_NOEVENT(event)) { return; }
 
     action_t action = layer_switch_get_action(event.key);
-    debug("ACTION: "); debug_action(action);
+    dprint("ACTION: "); debug_action(action);
 #ifndef NO_ACTION_LAYER
-    debug(" layer_state: "); layer_debug();
-    debug(" default_layer_state: "); default_layer_debug();
+    dprint(" layer_state: "); layer_debug();
+    dprint(" default_layer_state: "); default_layer_debug();
 #endif
-    debug("\n");
+    dprintln();
 
     switch (action.kind.id) {
         /* Key and Mods */
@@ -98,37 +103,37 @@ void process_action(keyrecord_t *record)
                         // Oneshot modifier
                         if (event.pressed) {
                             if (tap_count == 0) {
-                                debug("MODS_TAP: Oneshot: add_mods\n");
+                                dprint("MODS_TAP: Oneshot: add_mods\n");
                                 add_mods(mods);
                             }
                             else if (tap_count == 1) {
-                                debug("MODS_TAP: Oneshot: start\n");
+                                dprint("MODS_TAP: Oneshot: start\n");
                                 oneshot_start(mods);
                             }
                             else if (tap_count == TAPPING_TOGGLE) {
-                                debug("MODS_TAP: Oneshot: toggle\n");
+                                dprint("MODS_TAP: Oneshot: toggle\n");
                                 oneshot_toggle();
                             }
                             else {
-                                debug("MODS_TAP: Oneshot: cancel&add_mods\n");
+                                dprint("MODS_TAP: Oneshot: cancel&add_mods\n");
                                 // double tap cancels oneshot and works as normal modifier.
                                 oneshot_cancel();
                                 add_mods(mods);
                             }
                         } else {
                             if (tap_count == 0) {
-                                debug("MODS_TAP: Oneshot: cancel/del_mods\n");
+                                dprint("MODS_TAP: Oneshot: cancel/del_mods\n");
                                 // cancel oneshot on hold
                                 oneshot_cancel();
                                 del_mods(mods);
                             }
                             else if (tap_count == 1) {
-                                debug("MODS_TAP: Oneshot: del_mods\n");
+                                dprint("MODS_TAP: Oneshot: del_mods\n");
                                 // retain Oneshot
                                 del_mods(mods);
                             }
                             else {
-                                debug("MODS_TAP: Oneshot: del_mods\n");
+                                dprint("MODS_TAP: Oneshot: del_mods\n");
                                 // cancel Mods
                                 del_mods(mods);
                             }
@@ -139,24 +144,24 @@ void process_action(keyrecord_t *record)
                         if (event.pressed) {
                             if (tap_count > 0) {
                                 if (record->tap.interrupted) {
-                                    debug("MODS_TAP: Tap: Cancel: add_mods\n");
+                                    dprint("MODS_TAP: Tap: Cancel: add_mods\n");
                                     // ad hoc: set 0 to cancel tap
                                     record->tap.count = 0;
                                     add_mods(mods);
                                 } else {
-                                    debug("MODS_TAP: Tap: register_code\n");
+                                    dprint("MODS_TAP: Tap: register_code\n");
                                     register_code(action.key.code);
                                 }
                             } else {
-                                debug("MODS_TAP: No tap: add_mods\n");
+                                dprint("MODS_TAP: No tap: add_mods\n");
                                 add_mods(mods);
                             }
                         } else {
                             if (tap_count > 0) {
-                                debug("MODS_TAP: Tap: unregister_code\n");
+                                dprint("MODS_TAP: Tap: unregister_code\n");
                                 unregister_code(action.key.code);
                             } else {
-                                debug("MODS_TAP: No tap: add_mods\n");
+                                dprint("MODS_TAP: No tap: add_mods\n");
                                 del_mods(mods);
                             }
                         }
@@ -261,18 +266,18 @@ void process_action(keyrecord_t *record)
                     /* tap key */
                     if (event.pressed) {
                         if (tap_count > 0) {
-                            debug("KEYMAP_TAP_KEY: Tap: register_code\n");
+                            dprint("KEYMAP_TAP_KEY: Tap: register_code\n");
                             register_code(action.layer_tap.code);
                         } else {
-                            debug("KEYMAP_TAP_KEY: No tap: On on press\n");
+                            dprint("KEYMAP_TAP_KEY: No tap: On on press\n");
                             layer_on(action.layer_tap.val);
                         }
                     } else {
                         if (tap_count > 0) {
-                            debug("KEYMAP_TAP_KEY: Tap: unregister_code\n");
+                            dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n");
                             unregister_code(action.layer_tap.code);
                         } else {
-                            debug("KEYMAP_TAP_KEY: No tap: Off on release\n");
+                            dprint("KEYMAP_TAP_KEY: No tap: Off on release\n");
                             layer_off(action.layer_tap.val);
                         }
                     }
@@ -448,40 +453,33 @@ bool is_tap_key(key_t key)
  */
 void debug_event(keyevent_t event)
 {
-    debug_hex16((event.key.row<<8) | event.key.col);
-    if (event.pressed) debug("d("); else debug("u(");
-    debug_dec(event.time); debug(")");
+    dprintf("%04X%c(%u)", (event.key.row<<8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time);
 }
 
 void debug_record(keyrecord_t record)
 {
     debug_event(record.event);
 #ifndef NO_ACTION_TAPPING
-    debug(":"); debug_dec(record.tap.count);
-    if (record.tap.interrupted) debug("-");
+    dprintf(":%u%c", record.tap.count, (record.tap.interrupted ? '-' : ' '));
 #endif
 }
 
 void debug_action(action_t action)
 {
     switch (action.kind.id) {
-        case ACT_LMODS:             debug("ACT_LMODS");             break;
-        case ACT_RMODS:             debug("ACT_RMODS");             break;
-        case ACT_LMODS_TAP:         debug("ACT_LMODS_TAP");         break;
-        case ACT_RMODS_TAP:         debug("ACT_RMODS_TAP");         break;
-        case ACT_USAGE:             debug("ACT_USAGE");             break;
-        case ACT_MOUSEKEY:          debug("ACT_MOUSEKEY");          break;
-        case ACT_LAYER:             debug("ACT_LAYER");             break;
-        case ACT_LAYER_TAP:         debug("ACT_LAYER_TAP");         break;
-        case ACT_LAYER_TAP1:        debug("ACT_LAYER_TAP1");        break;
-        case ACT_MACRO:             debug("ACT_MACRO");             break;
-        case ACT_COMMAND:           debug("ACT_COMMAND");           break;
-        case ACT_FUNCTION:          debug("ACT_FUNCTION");          break;
-        default:                    debug("UNKNOWN");               break;
+        case ACT_LMODS:             dprint("ACT_LMODS");             break;
+        case ACT_RMODS:             dprint("ACT_RMODS");             break;
+        case ACT_LMODS_TAP:         dprint("ACT_LMODS_TAP");         break;
+        case ACT_RMODS_TAP:         dprint("ACT_RMODS_TAP");         break;
+        case ACT_USAGE:             dprint("ACT_USAGE");             break;
+        case ACT_MOUSEKEY:          dprint("ACT_MOUSEKEY");          break;
+        case ACT_LAYER:             dprint("ACT_LAYER");             break;
+        case ACT_LAYER_TAP:         dprint("ACT_LAYER_TAP");         break;
+        case ACT_LAYER_TAP1:        dprint("ACT_LAYER_TAP1");        break;
+        case ACT_MACRO:             dprint("ACT_MACRO");             break;
+        case ACT_COMMAND:           dprint("ACT_COMMAND");           break;
+        case ACT_FUNCTION:          dprint("ACT_FUNCTION");          break;
+        default:                    dprint("UNKNOWN");               break;
     }
-    debug("[");
-    debug_hex4(action.kind.param>>8);
-    debug(":");
-    debug_hex8(action.kind.param & 0xff);
-    debug("]");
+    dprintf("[%X:%02X]", action.kind.param>>8, action.kind.param&0xff);
 }
diff --git a/common/action_layer.c b/common/action_layer.c
index 3413c53e651..d24aa2e19f3 100644
--- a/common/action_layer.c
+++ b/common/action_layer.c
@@ -1,10 +1,15 @@
 #include <stdint.h>
 #include "keyboard.h"
 #include "action.h"
-#include "debug.h"
 #include "util.h"
 #include "action_layer.h"
 
+#ifdef DEBUG_ACTION
+#include "debug.h"
+#else
+#include "nodebug.h"
+#endif
+
 
 /* 
  * Default Layer State
@@ -22,8 +27,7 @@ static void default_layer_state_set(uint32_t state)
 
 void default_layer_debug(void)
 {
-    debug_hex32(default_layer_state);
-    debug("("); debug_dec(biton32(default_layer_state)); debug(")");
+    dprintf("%08lX(%u)", default_layer_state, biton32(default_layer_state));
 }
 
 void default_layer_set(uint8_t layer)
@@ -55,10 +59,10 @@ uint32_t layer_state = 0;
 
 static void layer_state_set(uint32_t state)
 {
-    debug("layer_state: ");
-    layer_debug(); debug(" to ");
+    dprint("layer_state: ");
+    layer_debug(); dprint(" to ");
     layer_state = state;
-    layer_debug(); debug("\n");
+    layer_debug(); dprintln();
     clear_keyboard_but_mods(); // To avoid stuck keys
 }
 
@@ -102,8 +106,7 @@ void layer_xor(uint32_t state)
 
 void layer_debug(void)
 {
-    debug_hex32(layer_state);
-    debug("("); debug_dec(biton32(layer_state)); debug(")");
+    dprintf("%08lX(%u)", layer_state, biton32(layer_state));
 }
 #endif
 
diff --git a/common/action_macro.c b/common/action_macro.c
index 6d81a1efb46..71d1506f5ca 100644
--- a/common/action_macro.c
+++ b/common/action_macro.c
@@ -15,10 +15,15 @@ You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 #include <util/delay.h>
-#include "debug.h"
 #include "action.h"
 #include "action_macro.h"
 
+#ifdef DEBUG_ACTION
+#include "debug.h"
+#else
+#include "nodebug.h"
+#endif
+
 
 #ifndef NO_ACTION_MACRO
 
diff --git a/common/action_tapping.c b/common/action_tapping.c
index abb0bf51829..8b466079d21 100644
--- a/common/action_tapping.c
+++ b/common/action_tapping.c
@@ -3,8 +3,12 @@
 #include "action.h"
 #include "action_tapping.h"
 #include "timer.h"
-#include "debug.h"
 
+#ifdef DEBUG_ACTION
+#include "debug.h"
+#else
+#include "nodebug.h"
+#endif
 
 #ifndef NO_ACTION_TAPPING
 
diff --git a/common/debug.h b/common/debug.h
index cac682703de..8aaa5ed915e 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 00000000000..e00fd103367
--- /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/host.c b/common/host.c
index 6ed3d780f64..2c2279aa4e0 100644
--- a/common/host.c
+++ b/common/host.c
@@ -63,11 +63,11 @@ void host_keyboard_send(report_keyboard_t *report)
     (*driver->send_keyboard)(report);
 
     if (debug_keyboard) {
-        print("keys: ");
+        dprint("keys: ");
         for (int i = 0; i < REPORT_KEYS; i++) {
-            phex(keyboard_report->keys[i]); print(" ");
+            dprintf("%02X ", keyboard_report->keys[i]);
         }
-        print(" mods: "); phex(keyboard_report->mods); print("\n");
+        dprintf(" mods: %02X\n", keyboard_report->mods);
     }
 }
 
@@ -235,7 +235,7 @@ static inline void add_key_bit(uint8_t code)
     if ((code>>3) < REPORT_KEYS) {
         keyboard_report->keys[code>>3] |= 1<<(code&7);
     } else {
-        debug("add_key_bit: can't add: "); phex(code); debug("\n");
+        dprintf("add_key_bit: can't add: %02X\n", code);
     }
 }
 
@@ -244,6 +244,6 @@ static inline void del_key_bit(uint8_t code)
     if ((code>>3) < REPORT_KEYS) {
         keyboard_report->keys[code>>3] &= ~(1<<(code&7));
     } else {
-        debug("del_key_bit: can't del: "); phex(code); debug("\n");
+        dprintf("del_key_bit: can't del: %02X\n", code);
     }
 }
diff --git a/common/nodebug.h b/common/nodebug.h
new file mode 100644
index 00000000000..aec790bbc15
--- /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 329f835125a..783bb4e9bb6 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)
+void print_lf(void)
 {
-    uint8_t c;
-    while (1) {
-        c = pgm_read_byte(s++);
-        if (!c) break;
-        if (c == '\n') sendchar('\r');
-        sendchar(c);
-    }
+    sendchar('\n');
 }
 
-void print_CRLF(void)
+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)
-{
-    print_bin_reverse8(data);
-    print_bin_reverse8(data>>8);
-}
-
-void print_bin_reverse32(uint32_t data)
-{
-    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 80858b3bc51..930e84be99d 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 6d4d6bfda18..7e0d542993a 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 4b8b5ca3a49..7451cc084da 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 00000000000..b5a97b20a9e
--- /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 00000000000..cddec994098
--- /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
+