aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortmk <nobody@nowhere>2013-05-14 16:16:57 +0900
committertmk <nobody@nowhere>2013-05-14 16:16:57 +0900
commitd9c06db60006e2191d8b86e34f651644a54426b4 (patch)
tree14b79372b1d0f0d9623b21e6dbffa73ce2036b7f
parentb9f558b3d89fc434d6dab348698d5100ff82d16b (diff)
downloadqmk_firmware-d9c06db60006e2191d8b86e34f651644a54426b4.tar.gz
qmk_firmware-d9c06db60006e2191d8b86e34f651644a54426b4.zip
Add xprintf(xitoa) from elm-chan.org
-rw-r--r--common.mk1
-rw-r--r--common/debug.h63
-rw-r--r--common/debug_config.h51
-rw-r--r--common/nodebug.h49
-rw-r--r--common/print.c147
-rw-r--r--common/print.h71
-rw-r--r--common/util.c22
-rw-r--r--common/util.h4
-rw-r--r--common/xprintf.S500
-rw-r--r--common/xprintf.h103
10 files changed, 789 insertions, 222 deletions
diff --git a/common.mk b/common.mk
index 810f802c6..5f47e5c1b 100644
--- a/common.mk
+++ b/common.mk
@@ -11,6 +11,7 @@ SRC += $(COMMON_DIR)/host.c \
11 $(COMMON_DIR)/print.c \ 11 $(COMMON_DIR)/print.c \
12 $(COMMON_DIR)/bootloader.c \ 12 $(COMMON_DIR)/bootloader.c \
13 $(COMMON_DIR)/suspend.c \ 13 $(COMMON_DIR)/suspend.c \
14 $(COMMON_DIR)/xprintf.S \
14 $(COMMON_DIR)/util.c 15 $(COMMON_DIR)/util.c
15 16
16 17
diff --git a/common/debug.h b/common/debug.h
index cac682703..8aaa5ed91 100644
--- a/common/debug.h
+++ b/common/debug.h
@@ -18,14 +18,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
18#ifndef DEBUG_H 18#ifndef DEBUG_H
19#define DEBUG_H 1 19#define DEBUG_H 1
20 20
21#include <stdbool.h>
22#include "print.h" 21#include "print.h"
22#include "debug_config.h"
23 23
24 24
25#ifndef NO_DEBUG 25#ifndef NO_DEBUG
26 26
27#define dprint(s) do { if (debug_enable) print(s); } while (0)
28#define dprintln() do { if (debug_enable) print_crlf(); } while (0)
29#define dprintf(fmt, ...) do { if (debug_enable) __xprintf(PSTR(fmt), ##__VA_ARGS__); } while (0)
30#define dmsg(s) dprintf("%s at %s: %S\n", __FILE__, __LINE__, PSTR(s))
31
32/* DO NOT USE these anymore */
27#define debug(s) do { if (debug_enable) print(s); } while (0) 33#define debug(s) do { if (debug_enable) print(s); } while (0)
28#define debugln(s) do { if (debug_enable) println(s); } while (0) 34#define debugln(s) do { if (debug_enable) print_crlf(); } while (0)
29#define debug_S(s) do { if (debug_enable) print_S(s); } while (0) 35#define debug_S(s) do { if (debug_enable) print_S(s); } while (0)
30#define debug_P(s) do { if (debug_enable) print_P(s); } while (0) 36#define debug_P(s) do { if (debug_enable) print_P(s); } while (0)
31#define debug_msg(s) do { \ 37#define debug_msg(s) do { \
@@ -50,58 +56,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
50#define debug_bin_reverse(data) debug_bin8(data) 56#define debug_bin_reverse(data) debug_bin8(data)
51 57
52#else 58#else
53 59#include "nodebug.h"
54#define debug(s)
55#define debugln(s)
56#define debug_S(s)
57#define debug_P(s)
58#define debug_msg(s)
59#define debug_dec(data)
60#define debug_decs(data)
61#define debug_hex4(data)
62#define debug_hex8(data)
63#define debug_hex16(data)
64#define debug_hex32(data)
65#define debug_bin8(data)
66#define debug_bin16(data)
67#define debug_bin32(data)
68#define debug_bin_reverse8(data)
69#define debug_bin_reverse16(data)
70#define debug_bin_reverse32(data)
71#define debug_hex(data)
72#define debug_bin(data)
73#define debug_bin_reverse(data)
74
75#endif
76
77
78#ifdef __cplusplus
79extern "C" {
80#endif
81
82
83/* NOTE: Not portable. Bit field order depends on implementation */
84typedef union {
85 uint8_t raw;
86 struct {
87 bool enable:1;
88 bool matrix:1;
89 bool keyboard:1;
90 bool mouse:1;
91 uint8_t reserved:4;
92 };
93} debug_config_t;
94debug_config_t debug_config;
95
96/* for backward compatibility */
97#define debug_enable (debug_config.enable)
98#define debug_matrix (debug_config.matrix)
99#define debug_keyboard (debug_config.keyboard)
100#define debug_mouse (debug_config.mouse)
101
102
103#ifdef __cplusplus
104}
105#endif 60#endif
106 61
107#endif 62#endif
diff --git a/common/debug_config.h b/common/debug_config.h
new file mode 100644
index 000000000..e00fd1033
--- /dev/null
+++ b/common/debug_config.h
@@ -0,0 +1,51 @@
1/*
2Copyright 2013 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef DEBUG_CONFIG_H
19#define DEBUG_CONFIG_H 1
20
21#include <stdbool.h>
22
23
24#ifdef __cplusplus
25extern "C" {
26#endif
27
28/* NOTE: Not portable. Bit field order depends on implementation */
29typedef union {
30 uint8_t raw;
31 struct {
32 bool enable:1;
33 bool matrix:1;
34 bool keyboard:1;
35 bool mouse:1;
36 uint8_t reserved:4;
37 };
38} debug_config_t;
39debug_config_t debug_config;
40
41/* for backward compatibility */
42#define debug_enable (debug_config.enable)
43#define debug_matrix (debug_config.matrix)
44#define debug_keyboard (debug_config.keyboard)
45#define debug_mouse (debug_config.mouse)
46
47#ifdef __cplusplus
48}
49#endif
50
51#endif
diff --git a/common/nodebug.h b/common/nodebug.h
new file mode 100644
index 000000000..aec790bbc
--- /dev/null
+++ b/common/nodebug.h
@@ -0,0 +1,49 @@
1/*
2Copyright 2013 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#ifndef NODEBUG_H
19#define NODEBUG_H 1
20
21#include "debug_config.h"
22
23#define dprint(s)
24#define dprintln(s)
25#define dprintf(fmt, ...)
26#define dmsg(s)
27
28#define debug(s)
29#define debugln(s)
30#define debug_S(s)
31#define debug_P(s)
32#define debug_msg(s)
33#define debug_dec(data)
34#define debug_decs(data)
35#define debug_hex4(data)
36#define debug_hex8(data)
37#define debug_hex16(data)
38#define debug_hex32(data)
39#define debug_bin8(data)
40#define debug_bin16(data)
41#define debug_bin32(data)
42#define debug_bin_reverse8(data)
43#define debug_bin_reverse16(data)
44#define debug_bin_reverse32(data)
45#define debug_hex(data)
46#define debug_bin(data)
47#define debug_bin_reverse(data)
48
49#endif
diff --git a/common/print.c b/common/print.c
index 329f83512..783bb4e9b 100644
--- a/common/print.c
+++ b/common/print.c
@@ -1,4 +1,4 @@
1/* Copyright 2012 Jun Wako <wakojun@gmail.com> */ 1/* Copyright 2012,2013 Jun Wako <wakojun@gmail.com> */
2/* Very basic print functions, intended to be used with usb_debug_only.c 2/* Very basic print functions, intended to be used with usb_debug_only.c
3 * http://www.pjrc.com/teensy/ 3 * http://www.pjrc.com/teensy/
4 * Copyright (c) 2008 PJRC.COM, LLC 4 * Copyright (c) 2008 PJRC.COM, LLC
@@ -29,20 +29,14 @@
29 29
30#ifndef NO_PRINT 30#ifndef NO_PRINT
31 31
32#define sendchar(c) do { if (print_sendchar_func) (print_sendchar_func)(c); } while (0) 32#define sendchar(c) xputc(c)
33 33
34 34
35static int8_t (*print_sendchar_func)(uint8_t) = 0;
36
37void print_set_sendchar(int8_t (*sendchar_func)(uint8_t)) 35void print_set_sendchar(int8_t (*sendchar_func)(uint8_t))
38{ 36{
39 print_sendchar_func = sendchar_func; 37 xdev_out(sendchar_func);
40} 38}
41 39
42/* print string stored in data memory(SRAM)
43 * print_P("hello world");
44 * This consumes precious SRAM memory space for string.
45 */
46void print_S(const char *s) 40void print_S(const char *s)
47{ 41{
48 uint8_t c; 42 uint8_t c;
@@ -54,140 +48,15 @@ void print_S(const char *s)
54 } 48 }
55} 49}
56 50
57/* print string stored in program memory(FLASH) 51void print_lf(void)
58 * print_P(PSTR("hello world");
59 * This consumes relatively abundant FLASH memory area not SRAM.
60 */
61void print_P(const char *s)
62{
63 uint8_t c;
64 while (1) {
65 c = pgm_read_byte(s++);
66 if (!c) break;
67 if (c == '\n') sendchar('\r');
68 sendchar(c);
69 }
70}
71
72void print_CRLF(void)
73{
74 sendchar('\r'); sendchar('\n');
75}
76
77
78#define SIGNED 0x80
79#define BIN 2
80#define OCT 8
81#define DEC 10
82#define HEX 16
83
84static inline
85char itoc(uint8_t i)
86{
87 return (i < 10 ? '0' + i : 'A' + i - 10);
88}
89
90static inline
91void print_int(uint16_t data, uint8_t base)
92{
93 char buf[7] = {'\0'};
94 char *p = &buf[6];
95 if ((base & SIGNED) && (data & 0x8000)) {
96 data = -data;
97 buf[0] = '-';
98 }
99 base &= ~SIGNED;
100 uint16_t n;
101 do {
102 n = data;
103 data /= base;
104 *(--p) = itoc(n - data*base);
105 } while (data);
106 if (buf[0]) *(--p) = buf[0];
107 print_S(p);
108}
109
110void print_dec(uint16_t data)
111{
112 print_int(data, DEC);
113}
114
115void print_decs(int16_t data)
116{
117 print_int(data, DEC|SIGNED);
118}
119
120
121void print_hex4(uint8_t data)
122{
123 sendchar(data + ((data < 10) ? '0' : 'A' - 10));
124}
125
126void print_hex8(uint8_t data)
127{
128 print_hex4(data>>4);
129 print_hex4(data&0x0F);
130}
131
132void print_hex16(uint16_t data)
133{
134 print_hex8(data>>8);
135 print_hex8(data);
136}
137
138void print_hex32(uint32_t data)
139{
140 print_hex16(data>>16);
141 print_hex16(data);
142}
143
144void print_bin4(uint8_t data)
145{
146 for (int i = 4; i >= 0; i--) {
147 sendchar((data & (1<<i)) ? '1' : '0');
148 }
149}
150
151void print_bin8(uint8_t data)
152{
153 for (int i = 7; i >= 0; i--) {
154 sendchar((data & (1<<i)) ? '1' : '0');
155 }
156}
157
158void print_bin16(uint16_t data)
159{
160 print_bin8(data>>8);
161 print_bin8(data);
162}
163
164void print_bin32(uint32_t data)
165{
166 print_bin8(data>>24);
167 print_bin8(data>>16);
168 print_bin8(data>>8);
169 print_bin8(data);
170}
171
172void print_bin_reverse8(uint8_t data)
173{
174 for (int i = 0; i < 8; i++) {
175 sendchar((data & (1<<i)) ? '1' : '0');
176 }
177}
178
179void print_bin_reverse16(uint16_t data)
180{ 52{
181 print_bin_reverse8(data); 53 sendchar('\n');
182 print_bin_reverse8(data>>8);
183} 54}
184 55
185void print_bin_reverse32(uint32_t data) 56void print_crlf(void)
186{ 57{
187 print_bin_reverse8(data); 58 sendchar('\r');
188 print_bin_reverse8(data>>8); 59 sendchar('\n');
189 print_bin_reverse8(data>>16);
190 print_bin_reverse8(data>>24);
191} 60}
192 61
193#endif 62#endif
diff --git a/common/print.h b/common/print.h
index 80858b3bc..930e84be9 100644
--- a/common/print.h
+++ b/common/print.h
@@ -28,6 +28,8 @@
28#include <stdint.h> 28#include <stdint.h>
29#include <stdbool.h> 29#include <stdbool.h>
30#include <avr/pgmspace.h> 30#include <avr/pgmspace.h>
31#include "xprintf.h"
32#include "util.h"
31 33
32 34
33// this macro allows you to write print("some text") and 35// this macro allows you to write print("some text") and
@@ -49,17 +51,17 @@
49#define pbin_reverse16(data) print_bin_reverse16(data) 51#define pbin_reverse16(data) print_bin_reverse16(data)
50 52
51/* print value utility */ 53/* print value utility */
52#define print_val_dec(v) do { print_P(PSTR(#v ": ")); print_dec(v); print_P(PSTR("\n")); } while (0) 54#define print_val_dec(v) xprintf(#v ": %u\n", v)
53#define print_val_decs(v) do { print_P(PSTR(#v ": ")); print_decs(v); print_P(PSTR("\n")); } while (0) 55#define print_val_decs(v) xprintf(#v ": %d\n", v)
54#define print_val_hex8(v) do { print_P(PSTR(#v ": ")); print_hex8(v); print_P(PSTR("\n")); } while (0) 56#define print_val_hex8(v) xprintf(#v ": %X\n", v)
55#define print_val_hex16(v) do { print_P(PSTR(#v ": ")); print_hex16(v); print_P(PSTR("\n")); } while (0) 57#define print_val_hex16(v) xprintf(#v ": %02X\n", v)
56#define print_val_hex32(v) do { print_P(PSTR(#v ": ")); print_hex32(v); print_P(PSTR("\n")); } while (0) 58#define print_val_hex32(v) xprintf(#v ": %04lX\n", v)
57#define print_val_bin8(v) do { print_P(PSTR(#v ": ")); print_bin8(v); print_P(PSTR("\n")); } while (0) 59#define print_val_bin8(v) xprintf(#v ": %08b\n", v)
58#define print_val_bin16(v) do { print_P(PSTR(#v ": ")); print_bin16(v); print_P(PSTR("\n")); } while (0) 60#define print_val_bin16(v) xprintf(#v ": %016b\n", v)
59#define print_val_bin32(v) do { print_P(PSTR(#v ": ")); print_bin32(v); print_P(PSTR("\n")); } while (0) 61#define print_val_bin32(v) xprintf(#v ": %032lb\n", v)
60#define print_val_bin_reverse8(v) do { print_P(PSTR(#v ": ")); print_bin_reverse8(v); print_P(PSTR("\n")); } while (0) 62#define print_val_bin_reverse8(v) xprintf(#v ": %08b\n", bitrev(v))
61#define print_val_bin_reverse16(v) do { print_P(PSTR(#v ": ")); print_bin_reverse16(v); print_P(PSTR("\n")); } while (0) 63#define print_val_bin_reverse16(v) xprintf(#v ": %016b\n", bitrev16(v))
62#define print_val_bin_reverse32(v) do { print_P(PSTR(#v ": ")); print_bin_reverse32(v); print_P(PSTR("\n")); } while (0) 64#define print_val_bin_reverse32(v) xprintf(#v ": %032lb\n", bitrev32(v))
63 65
64 66
65 67
@@ -68,34 +70,46 @@
68#ifdef __cplusplus 70#ifdef __cplusplus
69extern "C" { 71extern "C" {
70#endif 72#endif
73
71/* function pointer of sendchar to be used by print utility */ 74/* function pointer of sendchar to be used by print utility */
72void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t)); 75void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
73 76
74/* print string stored in data memory(SRAM) */ 77/* print string stored in data memory(SRAM)
78 * print_S("hello world");
79 * This consumes precious SRAM memory space for string.
80 */
75void print_S(const char *s); 81void print_S(const char *s);
76/* print string stored in program memory(FLASH) */
77void print_P(const char *s);
78 82
79void print_CRLF(void); 83void print_lf(void);
84void print_crlf(void);
85
86
87/* print string stored in program memory(FLASH)
88 * print_P(PSTR("hello world");
89 * This consumes relatively abundant FLASH memory area not SRAM.
90 */
91#define print_P(s) xputs(s)
80 92
81/* decimal */ 93/* decimal */
82void print_dec(uint16_t data); 94#define print_dec(i) xprintf("%u", i)
83void print_decs(int16_t data); 95#define print_decs(i) xprintf("%d", i)
84 96
85/* hex */ 97/* hex */
86void print_hex4(uint8_t data); 98#define print_hex4(i) xprintf("%X", i)
87void print_hex8(uint8_t data); 99#define print_hex8(i) xprintf("%02X", i)
88void print_hex16(uint16_t data); 100#define print_hex16(i) xprintf("%04X", i)
89void print_hex32(uint32_t data); 101#define print_hex32(i) xprintf("%08lX", i)
90 102
91/* binary */ 103/* binary */
92void print_bin4(uint8_t data); 104#define print_bin4(i) xprintf("%04b", i)
93void print_bin8(uint8_t data); 105#define print_bin8(i) xprintf("%08b", i)
94void print_bin16(uint16_t data); 106#define print_bin16(i) xprintf("%016b", i)
95void print_bin32(uint32_t data); 107#define print_bin32(i) xprintf("%032lb", i)
96void print_bin_reverse8(uint8_t data); 108
97void print_bin_reverse16(uint16_t data); 109#define print_bin_reverse8(i) xprintf("%08b", bitrev(i))
98void print_bin_reverse32(uint32_t data); 110#define print_bin_reverse16(i) xprintf("%016b", bitrev16(i))
111#define print_bin_reverse32(i) xprintf("%032lb", bitrev32(i))
112
99#ifdef __cplusplus 113#ifdef __cplusplus
100} 114}
101#endif 115#endif
@@ -105,7 +119,6 @@ void print_bin_reverse32(uint32_t data);
105#define print_set_sendchar(func) 119#define print_set_sendchar(func)
106#define print_S(s) 120#define print_S(s)
107#define print_P(s) 121#define print_P(s)
108#define print_CRLF()
109#define print_dec(data) 122#define print_dec(data)
110#define print_decs(data) 123#define print_decs(data)
111#define print_hex4(data) 124#define print_hex4(data)
diff --git a/common/util.c b/common/util.c
index 6d4d6bfda..7e0d54299 100644
--- a/common/util.c
+++ b/common/util.c
@@ -77,3 +77,25 @@ uint8_t biton32(uint32_t bits)
77 if (bits >> 1) { bits >>= 1; n += 1;} 77 if (bits >> 1) { bits >>= 1; n += 1;}
78 return n; 78 return n;
79} 79}
80
81
82
83uint8_t bitrev(uint8_t bits)
84{
85 bits = (bits & 0x0f)<<4 | (bits & 0xf0)>>4;
86 bits = (bits & 0b00110011)<<2 | (bits & 0b11001100)>>2;
87 bits = (bits & 0b01010101)<<1 | (bits & 0b10101010)>>1;
88 return bits;
89}
90
91uint16_t bitrev16(uint16_t bits)
92{
93 bits = bitrev(bits & 0x00ff)<<8 | bitrev((bits & 0xff00)>>8);
94 return bits;
95}
96
97uint32_t bitrev32(uint32_t bits)
98{
99 bits = (uint32_t)bitrev16(bits & 0x0000ffff)<<16 | bitrev16((bits & 0xffff0000)>>16);
100 return bits;
101}
diff --git a/common/util.h b/common/util.h
index 4b8b5ca3a..7451cc084 100644
--- a/common/util.h
+++ b/common/util.h
@@ -36,4 +36,8 @@ uint8_t biton(uint8_t bits);
36uint8_t biton16(uint16_t bits); 36uint8_t biton16(uint16_t bits);
37uint8_t biton32(uint32_t bits); 37uint8_t biton32(uint32_t bits);
38 38
39uint8_t bitrev(uint8_t bits);
40uint16_t bitrev16(uint16_t bits);
41uint32_t bitrev32(uint32_t bits);
42
39#endif 43#endif
diff --git a/common/xprintf.S b/common/xprintf.S
new file mode 100644
index 000000000..b5a97b20a
--- /dev/null
+++ b/common/xprintf.S
@@ -0,0 +1,500 @@
1;---------------------------------------------------------------------------;
2; Extended itoa, puts, printf and atoi (C)ChaN, 2011
3;---------------------------------------------------------------------------;
4
5 // Base size is 152 bytes
6#define CR_CRLF 0 // Convert \n to \r\n (+10 bytes)
7#define USE_XPRINTF 1 // Enable xprintf function (+194 bytes)
8#define USE_XSPRINTF 0 // Add xsprintf function (+78 bytes)
9#define USE_XFPRINTF 0 // Add xfprintf function (+54 bytes)
10#define USE_XATOI 0 // Enable xatoi function (+182 bytes)
11
12
13#if FLASHEND > 0x1FFFF
14#error xitoa module does not support 256K devices
15#endif
16
17.nolist
18#include <avr/io.h> // Include device specific definitions.
19.list
20
21#ifdef SPM_PAGESIZE // Recent devices have "lpm Rd,Z+" and "movw".
22.macro _LPMI reg
23 lpm \reg, Z+
24.endm
25.macro _MOVW dh,dl, sh,sl
26 movw \dl, \sl
27.endm
28#else // Earlier devices do not have "lpm Rd,Z+" nor "movw".
29.macro _LPMI reg
30 lpm
31 mov \reg, r0
32 adiw ZL, 1
33.endm
34.macro _MOVW dh,dl, sh,sl
35 mov \dl, \sl
36 mov \dh, \sh
37.endm
38#endif
39
40
41
42;---------------------------------------------------------------------------
43; Stub function to forward to user output function
44;
45;Prototype: void xputc (char chr // a character to be output
46; );
47;Size: 12/12 words
48
49.section .bss
50.global xfunc_out ; xfunc_out must be initialized before using this module.
51xfunc_out: .ds.w 1
52.section .text
53
54
55.func xputc
56.global xputc
57xputc:
58#if CR_CRLF
59 cpi r24, 10 ;LF --> CRLF
60 brne 1f ;
61 ldi r24, 13 ;
62 rcall 1f ;
63 ldi r24, 10 ;/
641:
65#endif
66 push ZH
67 push ZL
68 lds ZL, xfunc_out+0 ;Pointer to the registered output function.
69 lds ZH, xfunc_out+1 ;/
70 sbiw ZL, 0 ;Skip if null
71 breq 2f ;/
72 icall
732: pop ZL
74 pop ZH
75 ret
76.endfunc
77
78
79
80;---------------------------------------------------------------------------
81; Direct ROM string output
82;
83;Prototype: void xputs (const prog_char *str // rom string to be output
84; );
85
86.func xputs
87.global xputs
88xputs:
89 _MOVW ZH,ZL, r25,r24 ; Z = pointer to rom string
901: _LPMI r24
91 cpi r24, 0
92 breq 2f
93 rcall xputc
94 rjmp 1b
952: ret
96.endfunc
97
98
99;---------------------------------------------------------------------------
100; Extended direct numeral string output (32bit version)
101;
102;Prototype: void xitoa (long value, // value to be output
103; char radix, // radix
104; char width); // minimum width
105;
106
107.func xitoa
108.global xitoa
109xitoa:
110 ;r25:r22 = value, r20 = base, r18 = digits
111 clr r31 ;r31 = stack level
112 ldi r30, ' ' ;r30 = sign
113 ldi r19, ' ' ;r19 = filler
114 sbrs r20, 7 ;When base indicates signd format and the value
115 rjmp 0f ;is minus, add a '-'.
116 neg r20 ;
117 sbrs r25, 7 ;
118 rjmp 0f ;
119 ldi r30, '-' ;
120 com r22 ;
121 com r23 ;
122 com r24 ;
123 com r25 ;
124 adc r22, r1 ;
125 adc r23, r1 ;
126 adc r24, r1 ;
127 adc r25, r1 ;/
1280: sbrs r18, 7 ;When digits indicates zero filled,
129 rjmp 1f ;filler is '0'.
130 neg r18 ;
131 ldi r19, '0' ;/
132 ;----- string conversion loop
1331: ldi r21, 32 ;r26 = r25:r22 % r20
134 clr r26 ;r25:r22 /= r20
1352: lsl r22 ;
136 rol r23 ;
137 rol r24 ;
138 rol r25 ;
139 rol r26 ;
140 cp r26, r20 ;
141 brcs 3f ;
142 sub r26, r20 ;
143 inc r22 ;
1443: dec r21 ;
145 brne 2b ;/
146 cpi r26, 10 ;r26 is a numeral digit '0'-'F'
147 brcs 4f ;
148 subi r26, -7 ;
1494: subi r26, -'0' ;/
150 push r26 ;Stack it
151 inc r31 ;/
152 cp r22, r1 ;Repeat until r25:r22 gets zero
153 cpc r23, r1 ;
154 cpc r24, r1 ;
155 cpc r25, r1 ;
156 brne 1b ;/
157
158 cpi r30, '-' ;Minus sign if needed
159 brne 5f ;
160 push r30 ;
161 inc r31 ;/
1625: cp r31, r18 ;Filler
163 brcc 6f ;
164 push r19 ;
165 inc r31 ;
166 rjmp 5b ;/
167
1686: pop r24 ;Flush stacked digits and exit
169 rcall xputc ;
170 dec r31 ;
171 brne 6b ;/
172
173 ret
174.endfunc
175
176
177
178;---------------------------------------------------------------------------;
179; Formatted string output (16/32bit version)
180;
181;Prototype:
182; void xprintf (const prog_char *format, ...);
183; void xsprintf(char*, const prog_char *format, ...);
184; void xfprintf(void(*func)(char), const prog_char *format, ...);
185;
186
187#if USE_XPRINTF
188
189.func xvprintf
190xvprintf:
191 ld ZL, Y+ ;Z = pointer to format string
192 ld ZH, Y+ ;/
193
1940: _LPMI r24 ;Get a format char
195 cpi r24, 0 ;End of format string?
196 breq 90f ;/
197 cpi r24, '%' ;Is format?
198 breq 20f ;/
1991: rcall xputc ;Put a normal character
200 rjmp 0b ;/
20190: ret
202
20320: ldi r18, 0 ;r18: digits
204 clt ;T: filler
205 _LPMI r21 ;Get flags
206 cpi r21, '%' ;Is a %?
207 breq 1b ;/
208 cpi r21, '0' ;Zero filled?
209 brne 23f ;
210 set ;/
21122: _LPMI r21 ;Get width
21223: cpi r21, '9'+1 ;
213 brcc 24f ;
214 subi r21, '0' ;
215 brcs 90b ;
216 lsl r18 ;
217 mov r0, r18 ;
218 lsl r18 ;
219 lsl r18 ;
220 add r18, r0 ;
221 add r18, r21 ;
222 rjmp 22b ;/
223
22424: brtc 25f ;get value (low word)
225 neg r18 ;
22625: ld r24, Y+ ;
227 ld r25, Y+ ;/
228 cpi r21, 'c' ;Is type character?
229 breq 1b ;/
230 cpi r21, 's' ;Is type RAM string?
231 breq 50f ;/
232 cpi r21, 'S' ;Is type ROM string?
233 breq 60f ;/
234 _MOVW r23,r22,r25,r24 ;r25:r22 = value
235 clr r24 ;
236 clr r25 ;
237 clt ;/
238 cpi r21, 'l' ;Is long int?
239 brne 26f ;
240 ld r24, Y+ ;get value (high word)
241 ld r25, Y+ ;
242 set ;
243 _LPMI r21 ;/
24426: cpi r21, 'd' ;Is type signed decimal?
245 brne 27f ;/
246 ldi r20, -10 ;
247 brts 40f ;
248 sbrs r23, 7 ;
249 rjmp 40f ;
250 ldi r24, -1 ;
251 ldi r25, -1 ;
252 rjmp 40f ;/
25327: cpi r21, 'u' ;Is type unsigned decimal?
254 ldi r20, 10 ;
255 breq 40f ;/
256 cpi r21, 'X' ;Is type hexdecimal?
257 ldi r20, 16 ;
258 breq 40f ;/
259 cpi r21, 'b' ;Is type binary?
260 ldi r20, 2 ;
261 breq 40f ;/
262 ret ;abort
26340: push ZH ;Output the value
264 push ZL ;
265 rcall xitoa ;
26642: pop ZL ;
267 pop ZH ;
268 rjmp 0b ;/
269
27050: push ZH ;Put a string on the RAM
271 push ZL
272 _MOVW ZH,ZL, r25,r24
27351: ld r24, Z+
274 cpi r24, 0
275 breq 42b
276 rcall xputc
277 rjmp 51b
278
27960: push ZH ;Put a string on the ROM
280 push ZL
281 rcall xputs
282 rjmp 42b
283.endfunc
284
285
286.func __xprintf
287.global __xprintf
288__xprintf:
289 push YH
290 push YL
291 in YL, _SFR_IO_ADDR(SPL)
292#ifdef SPH
293 in YH, _SFR_IO_ADDR(SPH)
294#else
295 clr YH
296#endif
297 adiw YL, 5 ;Y = pointer to arguments
298 rcall xvprintf
299 pop YL
300 pop YH
301 ret
302.endfunc
303
304
305#if USE_XSPRINTF
306
307.func __xsprintf
308putram:
309 _MOVW ZH,ZL, r15,r14
310 st Z+, r24
311 _MOVW r15,r14, ZH,ZL
312 ret
313.global __xsprintf
314__xsprintf:
315 push YH
316 push YL
317 in YL, _SFR_IO_ADDR(SPL)
318#ifdef SPH
319 in YH, _SFR_IO_ADDR(SPH)
320#else
321 clr YH
322#endif
323 adiw YL, 5 ;Y = pointer to arguments
324 lds ZL, xfunc_out+0 ;Save registered output function
325 lds ZH, xfunc_out+1 ;
326 push ZL ;
327 push ZH ;/
328 ldi ZL, lo8(pm(putram));Set local output function
329 ldi ZH, hi8(pm(putram));
330 sts xfunc_out+0, ZL ;
331 sts xfunc_out+1, ZH ;/
332 push r15 ;Initialize pointer to string buffer
333 push r14 ;
334 ld r14, Y+ ;
335 ld r15, Y+ ;/
336 rcall xvprintf
337 _MOVW ZH,ZL, r15,r14 ;Terminate string
338 st Z, r1 ;
339 pop r14 ;
340 pop r15 ;/
341 pop ZH ;Restore registered output function
342 pop ZL ;
343 sts xfunc_out+0, ZL ;
344 sts xfunc_out+1, ZH ;/
345 pop YL
346 pop YH
347 ret
348.endfunc
349#endif
350
351
352#if USE_XFPRINTF
353.func __xfprintf
354.global __xfprintf
355__xfprintf:
356 push YH
357 push YL
358 in YL, _SFR_IO_ADDR(SPL)
359#ifdef SPH
360 in YH, _SFR_IO_ADDR(SPH)
361#else
362 clr YH
363#endif
364 adiw YL, 5 ;Y = pointer to arguments
365 lds ZL, xfunc_out+0 ;Save registered output function
366 lds ZH, xfunc_out+1 ;
367 push ZL ;
368 push ZH ;/
369 ld ZL, Y+ ;Set output function
370 ld ZH, Y+ ;
371 sts xfunc_out+0, ZL ;
372 sts xfunc_out+1, ZH ;/
373 rcall xvprintf
374 pop ZH ;Restore registered output function
375 pop ZL ;
376 sts xfunc_out+0, ZL ;
377 sts xfunc_out+1, ZH ;/
378 pop YL
379 pop YH
380 ret
381.endfunc
382#endif
383
384#endif
385
386
387
388;---------------------------------------------------------------------------
389; Extended numeral string input
390;
391;Prototype:
392; char xatoi ( /* 1: Successful, 0: Failed */
393; const char **str, /* pointer to pointer to source string */
394; long *res /* result */
395; );
396;
397
398
399#if USE_XATOI
400.func xatoi
401.global xatoi
402xatoi:
403 _MOVW r1, r0, r23, r22
404 _MOVW XH, XL, r25, r24
405 ld ZL, X+
406 ld ZH, X+
407 clr r18 ;r21:r18 = 0;
408 clr r19 ;
409 clr r20 ;
410 clr r21 ;/
411 clt ;T = 0;
412
413 ldi r25, 10 ;r25 = 10;
414 rjmp 41f ;/
41540: adiw ZL, 1 ;Z++;
41641: ld r22, Z ;r22 = *Z;
417 cpi r22, ' ' ;if(r22 == ' ') continue
418 breq 40b ;/
419 brcs 70f ;if(r22 < ' ') error;
420 cpi r22, '-' ;if(r22 == '-') {
421 brne 42f ; T = 1;
422 set ; continue;
423 rjmp 40b ;}
42442: cpi r22, '9'+1 ;if(r22 > '9') error;
425 brcc 70f ;/
426 cpi r22, '0' ;if(r22 < '0') error;
427 brcs 70f ;/
428 brne 51f ;if(r22 > '0') cv_start;
429 ldi r25, 8 ;r25 = 8;
430 adiw ZL, 1 ;r22 = *(++Z);
431 ld r22, Z ;/
432 cpi r22, ' '+1 ;if(r22 <= ' ') exit;
433 brcs 80f ;/
434 cpi r22, 'b' ;if(r22 == 'b') {
435 brne 43f ; r25 = 2;
436 ldi r25, 2 ; cv_start;
437 rjmp 50f ;}
43843: cpi r22, 'x' ;if(r22 != 'x') error;
439 brne 51f ;/
440 ldi r25, 16 ;r25 = 16;
441
44250: adiw ZL, 1 ;Z++;
443 ld r22, Z ;r22 = *Z;
44451: cpi r22, ' '+1 ;if(r22 <= ' ') break;
445 brcs 80f ;/
446 cpi r22, 'a' ;if(r22 >= 'a') r22 =- 0x20;
447 brcs 52f ;
448 subi r22, 0x20 ;/
44952: subi r22, '0' ;if((r22 -= '0') < 0) error;
450 brcs 70f ;/
451 cpi r22, 10 ;if(r22 >= 10) {
452 brcs 53f ; r22 -= 7;
453 subi r22, 7 ; if(r22 < 10)
454 cpi r22, 10 ;
455 brcs 70f ;}
45653: cp r22, r25 ;if(r22 >= r25) error;
457 brcc 70f ;/
45860: ldi r24, 33 ;r21:r18 *= r25;
459 sub r23, r23 ;
46061: brcc 62f ;
461 add r23, r25 ;
46262: lsr r23 ;
463 ror r21 ;
464 ror r20 ;
465 ror r19 ;
466 ror r18 ;
467 dec r24 ;
468 brne 61b ;/
469 add r18, r22 ;r21:r18 += r22;
470 adc r19, r24 ;
471 adc r20, r24 ;
472 adc r21, r24 ;/
473 rjmp 50b ;repeat
474
47570: ldi r24, 0
476 rjmp 81f
47780: ldi r24, 1
47881: brtc 82f
479 clr r22
480 com r18
481 com r19
482 com r20
483 com r21
484 adc r18, r22
485 adc r19, r22
486 adc r20, r22
487 adc r21, r22
48882: st -X, ZH
489 st -X, ZL
490 _MOVW XH, XL, r1, r0
491 st X+, r18
492 st X+, r19
493 st X+, r20
494 st X+, r21
495 clr r1
496 ret
497.endfunc
498#endif
499
500
diff --git a/common/xprintf.h b/common/xprintf.h
new file mode 100644
index 000000000..cddec9940
--- /dev/null
+++ b/common/xprintf.h
@@ -0,0 +1,103 @@
1/*---------------------------------------------------------------------------
2 Extended itoa, puts and printf (C)ChaN, 2011
3-----------------------------------------------------------------------------*/
4
5#ifndef XPRINTF_H
6#define XPRINTF_H
7
8#include <inttypes.h>
9#include <avr/pgmspace.h>
10
11extern void (*xfunc_out)(uint8_t);
12#define xdev_out(func) xfunc_out = (void(*)(uint8_t))(func)
13
14/* This is a pointer to user defined output function. It must be initialized
15 before using this modle.
16*/
17
18void xputc(char chr);
19
20/* This is a stub function to forward outputs to user defined output function.
21 All outputs from this module are output via this function.
22*/
23
24
25/*-----------------------------------------------------------------------------*/
26void xputs(const prog_char *string);
27
28/* The string placed in the ROM is forwarded to xputc() directly.
29*/
30
31
32/*-----------------------------------------------------------------------------*/
33void xitoa(long value, char radix, char width);
34
35/* Extended itoa().
36
37 value radix width output
38 100 10 6 " 100"
39 100 10 -6 "000100"
40 100 10 0 "100"
41 4294967295 10 0 "4294967295"
42 4294967295 -10 0 "-1"
43 655360 16 -8 "000A0000"
44 1024 16 0 "400"
45 0x55 2 -8 "01010101"
46*/
47
48
49/*-----------------------------------------------------------------------------*/
50#define xprintf(format, ...) __xprintf(PSTR(format), ##__VA_ARGS__)
51#define xsprintf(str, format, ...) __xsprintf(str, PSTR(format), ##__VA_ARGS__)
52#define xfprintf(func, format, ...) __xfprintf(func, PSTR(format), ##__VA_ARGS__)
53
54void __xprintf(const prog_char *format, ...); /* Send formatted string to the registered device */
55void __xsprintf(char*, const prog_char *format, ...); /* Put formatted string to the memory */
56void __xfprintf(void(*func)(uint8_t), const prog_char *format, ...); /* Send formatted string to the specified device */
57
58/* Format string is placed in the ROM. The format flags is similar to printf().
59
60 %[flag][width][size]type
61
62 flag
63 A '0' means filled with '0' when output is shorter than width.
64 ' ' is used in default. This is effective only numeral type.
65 width
66 Minimum width in decimal number. This is effective only numeral type.
67 Default width is zero.
68 size
69 A 'l' means the argument is long(32bit). Default is short(16bit).
70 This is effective only numeral type.
71 type
72 'c' : Character, argument is the value
73 's' : String placed on the RAM, argument is the pointer
74 'S' : String placed on the ROM, argument is the pointer
75 'd' : Signed decimal, argument is the value
76 'u' : Unsigned decimal, argument is the value
77 'X' : Hexdecimal, argument is the value
78 'b' : Binary, argument is the value
79 '%' : '%'
80
81*/
82
83
84/*-----------------------------------------------------------------------------*/
85char xatoi(char **str, long *ret);
86
87/* Get value of the numeral string.
88
89 str
90 Pointer to pointer to source string
91
92 "0b11001010" binary
93 "0377" octal
94 "0xff800" hexdecimal
95 "1250000" decimal
96 "-25000" decimal
97
98 ret
99 Pointer to return value
100*/
101
102#endif
103