$(COMMON_DIR)/print.c \
$(COMMON_DIR)/bootloader.c \
$(COMMON_DIR)/suspend.c \
+ $(COMMON_DIR)/xprintf.S \
$(COMMON_DIR)/util.c
#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 { \
#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
--- /dev/null
+/*
+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
--- /dev/null
+/*
+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
-/* 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;
}
}
-/* 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
#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
#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)
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;
+}
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
--- /dev/null
+;---------------------------------------------------------------------------;\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
--- /dev/null
+/*---------------------------------------------------------------------------\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