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_USE_XSTACK)
61 #warning "printf_tiny not built, does not support --xstack"
62 #elif defined(_SDCC_NO_ASM_LIB_FUNCS)
63 #warning "printf_tiny not built, _SDCC_NO_ASM_LIB_FUNCS defined"
65 /* Disable "ISO C forbids an empty source file" wraning message */
66 #pragma disable_warning 190
68 #else // defines are compatible with printf_tiny
72 void printf_tiny(code char *fmt, ...) reentrant
74 fmt; /* suppress unreferenced variable warning */
79 mov a, _bp // r0 will point to va_args (stack)
81 mov r0, a // r0 points to MSB of fmt
84 mov dpl, @r0 // dptr has address of fmt
90 movc a, @a+dptr // get next byte of fmt string
93 jz printf_format // check for '%'
105 movc a, @a+dptr // get next byte of data format
112 //cjne a, #'s', printf_format_c
113 cjne a, #115, printf_format_c
115 /* print a string... just grab each byte with __gptrget */
116 /* the user much pass a 24 bit generic pointer */
117 mov b, @r0 // b has type of address (generic *)
121 mov dpl, @r0 // dptr has address of user's string
125 jz printf_format_done
132 //cjne a, #'c', printf_format_d
133 cjne a, #99, printf_format_d
134 mov a, @r0 // Acc has the character to print
137 sjmp printf_format_done
141 //cjne a, #'d', printf_format_u
142 cjne a, #100, printf_format_x
143 #ifndef ALWAYS_PRINT_UNSIGNED
145 jnb acc.7, printf_uint
164 //cjne a, #'x', printf_format_u
165 cjne a, #120, printf_format_u
172 lcall printf_phex_lsn
174 lcall printf_phex_msn
176 lcall printf_phex_lsn
178 lcall printf_phex_msn
180 lcall printf_phex_lsn
181 jnb print_zero_flag, printf_format_done
188 ljmp printf_main_loop
192 //cjne a, #'u', printf_format_done
193 cjne a, #117, printf_format_done
225 // Divide r2/r1 by r5/r4 using successive subtraction
226 // returns quotient in r2/r1 and remainder in acc.
250 /* print a hex digit, either upper 4 bit (msn) or lower 4 bits (lsn) */
256 jb print_zero_flag, printf_ret
264 #ifdef DIRECT_SERIAL_OUTPUT
265 jnb ti, printf_putchar
291 #endif // defines compatible with printf_tiny