1 /* Tiny printf routine for use with sdcc/mcs51
2 * Copyright (c) 2004, Paul Stoffregen, paul@pjrc.com
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * This tiny printf uses minimal code space, and it is fully reentrant
21 * and register bank neutral (usually safe to call from within an
22 * interrupt routine). Code size is under 270 bytes. Only one library
23 * function is called (_gptrget, 41 bytes), in addition to calls to
26 * Five simple formats are supported
28 * %d signed 16 bit integer decimal (-32768 to 32767)
29 * %u unsigned 16 bit integer decimal (0 to 65535)
30 * %s string, takes a 24 bit generic pointer
31 * %c character. You must explicitly cast to char in SDCC
32 * %x 16 bit integer in hex (0 to FFFF)
34 * For a more complete printf that supports longs, floating point and
35 * field width, try using printf_fast() or printf_large().
39 /* This removes the negative number code, causing "%d" to be the same
40 as "%u". If you don't care about printing negative numbers, this
41 will save 21 bytes of code. */
42 /* #define ALWAYS_PRINT_UNSIGNED */
44 /* Directly output characters to the serial port using simple polling,
45 rather than calling putchar(). This saves 14 bytes, plus the size
47 /* #define DIRECT_SERIAL_OUTPUT */
51 /* extern void putchar(char ); */
54 #define print_zero_flag PSW.5
57 #if !defined(SDCC_mcs51) || defined(SDCC_USE_XSTACK) || defined(_SDCC_NO_ASM_LIB_FUNCS)
58 /* Does printf_tiny really work on ds390 and ds400?
59 If it does, enable them in the line above */
60 #if defined(_SDCC_BUILD_LIB)
61 /* Disable all warnings if building a library */
62 #pragma disable_warning 190
63 #elif defined(SDCC_USE_XSTACK)
64 #warning "printf_tiny not built, does not support --xstack"
65 #elif defined(_SDCC_NO_ASM_LIB_FUNCS)
66 #warning "printf_tiny not built, _SDCC_NO_ASM_LIB_FUNCS defined"
68 /* Disable "ISO C forbids an empty source file" wraning message */
69 #pragma disable_warning 190
71 #else /* defines are compatible with printf_tiny */
75 void printf_tiny(__code char *fmt, ...) __reentrant
77 fmt; /* suppress unreferenced variable warning */
82 mov a, _bp /* r0 will point to va_args (stack) */
84 mov r0, a /* r0 points to MSB of fmt */
87 mov dpl, @r0 /* dptr has address of fmt */
93 movc a, @a+dptr /* get next byte of fmt string */
96 jz printf_format /* check for '%' */
100 sjmp printf_main_loop
108 movc a, @a+dptr /* get next byte of data format */
115 /*cjne a, #'s', printf_format_c*/
116 cjne a, #115, printf_format_c
118 /* print a string... just grab each byte with __gptrget */
119 /* the user much pass a 24 bit generic pointer */
120 mov b, @r0 /* b has type of address (generic *) */
124 mov dpl, @r0 /* dptr has address of user's string */
128 jz printf_format_done
135 /*cjne a, #'c', printf_format_d*/
136 cjne a, #99, printf_format_d
138 mov a, @r0 /* Acc has the character to print */
141 sjmp printf_format_done
145 /*cjne a, #'d', printf_format_u*/
146 cjne a, #100, printf_format_x
147 #ifndef ALWAYS_PRINT_UNSIGNED
149 jnb acc.7, printf_uint
168 /*cjne a, #'x', printf_format_u*/
169 cjne a, #120, printf_format_u
176 lcall printf_phex_lsn
178 lcall printf_phex_msn
180 lcall printf_phex_lsn
182 lcall printf_phex_msn
184 lcall printf_phex_lsn
185 jnb print_zero_flag, printf_format_done
192 ljmp printf_main_loop
196 /*cjne a, #'u', printf_format_done*/
197 cjne a, #117, printf_format_done
229 /* Divide r2/r1 by r5/r4 using successive subtraction
230 returns quotient in r2/r1 and remainder in acc. */
254 /* print a hex digit, either upper 4 bit (msn) or lower 4 bits (lsn) */
260 jb print_zero_flag, printf_ret
268 #ifdef DIRECT_SERIAL_OUTPUT
269 jnb ti, printf_putchar
295 #endif /* defines compatible with printf_tiny */