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 #else // defines are compatible with printf_tiny
69 void printf_tiny(code char *fmt, ...) reentrant
71 fmt; /* suppress unreferenced variable warning */
76 mov a, _bp // r0 will point to va_args (stack)
78 mov r0, a // r0 points to MSB of fmt
81 mov dpl, @r0 // dptr has address of fmt
87 movc a, @a+dptr // get next byte of fmt string
90 jz printf_format // check for '%'
102 movc a, @a+dptr // get next byte of data format
109 //cjne a, #'s', printf_format_c
110 cjne a, #115, printf_format_c
112 /* print a string... just grab each byte with __gptrget */
113 /* the user much pass a 24 bit generic pointer */
114 mov b, @r0 // b has type of address (generic *)
118 mov dpl, @r0 // dptr has address of user's string
122 jz printf_format_done
129 //cjne a, #'c', printf_format_d
130 cjne a, #99, printf_format_d
131 mov a, @r0 // Acc has the character to print
134 sjmp printf_format_done
138 //cjne a, #'d', printf_format_u
139 cjne a, #100, printf_format_x
140 #ifndef ALWAYS_PRINT_UNSIGNED
142 jnb acc.7, printf_uint
161 //cjne a, #'x', printf_format_u
162 cjne a, #120, printf_format_u
169 lcall printf_phex_lsn
171 lcall printf_phex_msn
173 lcall printf_phex_lsn
175 lcall printf_phex_msn
177 lcall printf_phex_lsn
178 jnb print_zero_flag, printf_format_done
185 ljmp printf_main_loop
189 //cjne a, #'u', printf_format_done
190 cjne a, #117, printf_format_done
222 // Divide r2/r1 by r5/r4 using successive subtraction
223 // returns quotient in r2/r1 and remainder in acc.
247 /* print a hex digit, either upper 4 bit (msn) or lower 4 bits (lsn) */
253 jb print_zero_flag, printf_ret
261 #ifdef DIRECT_SERIAL_OUTPUT
262 jnb ti, printf_putchar
288 #endif // defines compatible with printf_tiny