1d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen/*
2d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen Print.cpp - Base class that provides print() and println()
3d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen Copyright (c) 2008 David A. Mellis.  All right reserved.
4d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
5d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen This library is free software; you can redistribute it and/or
6d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen modify it under the terms of the GNU Lesser General Public
7d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen License as published by the Free Software Foundation; either
8d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen version 2.1 of the License, or (at your option) any later version.
9d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
10d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen This library is distributed in the hope that it will be useful,
11d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen but WITHOUT ANY WARRANTY; without even the implied warranty of
12d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen Lesser General Public License for more details.
14d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
15d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen You should have received a copy of the GNU Lesser General Public
16d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen License along with this library; if not, write to the Free Software
17d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
19d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen Modified 23 November 2006 by David A. Mellis
20d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen */
21d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
22d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen#include <stdlib.h>
23d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen#include <stdio.h>
24d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen#include <string.h>
25d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen#include <math.h>
26d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen#include "wiring.h"
27d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
28d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen#include "Print.h"
29d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
30d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen// Public Methods //////////////////////////////////////////////////////////////
31d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
32d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen/* default implementation: may be overridden */
33d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::write(const char *str)
34d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
35d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  while (*str)
36d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen    write(*str++);
37d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
38d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
39d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen/* default implementation: may be overridden */
40d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::write(const uint8_t *buffer, size_t size)
41d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
42d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  while (size--)
43d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen    write(*buffer++);
44d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
45d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
46d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::print(const String &s)
47d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
48d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  for (int i = 0; i < s.length(); i++) {
49d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen    write(s[i]);
50d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  }
51d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
52d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
53d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::print(const char str[])
54d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
55d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  write(str);
56d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
57d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
58d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::print(char c, int base)
59d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
60d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  print((long) c, base);
61d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
62d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
63d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::print(unsigned char b, int base)
64d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
65d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  print((unsigned long) b, base);
66d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
67d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
68d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::print(int n, int base)
69d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
70d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  print((long) n, base);
71d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
72d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
73d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::print(unsigned int n, int base)
74d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
75d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  print((unsigned long) n, base);
76d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
77d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
78d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::print(long n, int base)
79d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
80d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  if (base == 0) {
81d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen    write(n);
82d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  } else if (base == 10) {
83d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen    if (n < 0) {
84d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen      print('-');
85d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen      n = -n;
86d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen    }
87d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen    printNumber(n, 10);
88d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  } else {
89d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen    printNumber(n, base);
90d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  }
91d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
92d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
93d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::print(unsigned long n, int base)
94d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
95d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  if (base == 0) write(n);
96d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  else printNumber(n, base);
97d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
98d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
99d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::print(double n, int digits)
100d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
101d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  printFloat(n, digits);
102d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
103d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
104d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::println(void)
105d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
106d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  print('\r');
107d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  print('\n');
108d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
109d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
110d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::println(const String &s)
111d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
112d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  print(s);
113d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  println();
114d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
115d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
116d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::println(const char c[])
117d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
118d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  print(c);
119d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  println();
120d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
121d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
122d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::println(char c, int base)
123d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
124d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  print(c, base);
125d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  println();
126d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
127d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
128d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::println(unsigned char b, int base)
129d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
130d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  print(b, base);
131d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  println();
132d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
133d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
134d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::println(int n, int base)
135d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
136d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  print(n, base);
137d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  println();
138d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
139d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
140d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::println(unsigned int n, int base)
141d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
142d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  print(n, base);
143d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  println();
144d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
145d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
146d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::println(long n, int base)
147d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
148d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  print(n, base);
149d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  println();
150d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
151d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
152d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::println(unsigned long n, int base)
153d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
154d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  print(n, base);
155d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  println();
156d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
157d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
158d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::println(double n, int digits)
159d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
160d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  print(n, digits);
161d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  println();
162d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
163d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
164d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen// Private Methods /////////////////////////////////////////////////////////////
165d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
166d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::printNumber(unsigned long n, uint8_t base)
167d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
168d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars.
169d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  unsigned long i = 0;
170d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
171d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  if (n == 0) {
172d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen    print('0');
173d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen    return;
174d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  }
175d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
176d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  while (n > 0) {
177d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen    buf[i++] = n % base;
178d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen    n /= base;
179d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  }
180d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
181d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  for (; i > 0; i--)
182d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen    print((char) (buf[i - 1] < 10 ?
183d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen      '0' + buf[i - 1] :
184d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen      'A' + buf[i - 1] - 10));
185d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
186d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
187d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chenvoid Print::printFloat(double number, uint8_t digits)
188d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen{
189d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  // Handle negative numbers
190d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  if (number < 0.0)
191d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  {
192d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen     print('-');
193d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen     number = -number;
194d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  }
195d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
196d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  // Round correctly so that print(1.999, 2) prints as "2.00"
197d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  double rounding = 0.5;
198d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  for (uint8_t i=0; i<digits; ++i)
199d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen    rounding /= 10.0;
200d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
201d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  number += rounding;
202d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
203d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  // Extract the integer part of the number and print it
204d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  unsigned long int_part = (unsigned long)number;
205d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  double remainder = number - (double)int_part;
206d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  print(int_part);
207d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
208d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  // Print the decimal point, but only if there are digits beyond
209d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  if (digits > 0)
210d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen    print(".");
211d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen
212d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  // Extract digits from the remainder one at a time
213d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  while (digits-- > 0)
214d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  {
215d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen    remainder *= 10.0;
216d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen    int toPrint = int(remainder);
217d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen    print(toPrint);
218d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen    remainder -= toPrint;
219d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen  }
220d5790d78880d4bd60be277ee20e53a851aa8c11Mike J. Chen}
221