Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

331 lines
8.1KB

  1. /*
  2. Print.cpp - Base class that provides print() and println()
  3. Copyright (c) 2008 David A. Mellis. All right reserved.
  4. many modifications, by Paul Stoffregen <paul@pjrc.com>
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2.1 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 GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with this library; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. Modified 23 November 2006 by David A. Mellis
  17. */
  18. //#include <stdio.h>
  19. //#include <string.h>
  20. #include <inttypes.h>
  21. #include <math.h>
  22. //#include <avr/pgmspace.h>
  23. //#include "wiring.h"
  24. #include "Print.h"
  25. size_t Print::write(const uint8_t *buffer, size_t size)
  26. {
  27. size_t count = 0;
  28. while (size--) count += write(*buffer++);
  29. return count;
  30. }
  31. size_t Print::print(const String &s)
  32. {
  33. uint8_t buffer[33];
  34. size_t count = 0;
  35. unsigned int index = 0;
  36. unsigned int len = s.length();
  37. while (len > 0) {
  38. s.getBytes(buffer, sizeof(buffer), index);
  39. unsigned int nbytes = len;
  40. if (nbytes > sizeof(buffer)-1) nbytes = sizeof(buffer)-1;
  41. index += nbytes;
  42. len -= nbytes;
  43. count += write(buffer, nbytes);
  44. }
  45. return count;
  46. }
  47. size_t Print::print(long n)
  48. {
  49. uint8_t sign=0;
  50. if (n < 0) {
  51. sign = '-';
  52. n = -n;
  53. }
  54. return printNumber(n, 10, sign);
  55. }
  56. size_t Print::println(void)
  57. {
  58. uint8_t buf[2]={'\r', '\n'};
  59. return write(buf, 2);
  60. }
  61. extern "C" {
  62. __attribute__((weak))
  63. int _write(int file, char *ptr, int len)
  64. {
  65. ((class Print *)file)->write((uint8_t *)ptr, len);
  66. return 0;
  67. }
  68. }
  69. int Print::printf(const char *format, ...)
  70. {
  71. va_list ap;
  72. va_start(ap, format);
  73. #ifdef __STRICT_ANSI__
  74. return 0; // TODO: make this work with -std=c++0x
  75. #else
  76. return vdprintf((int)this, format, ap);
  77. #endif
  78. }
  79. int Print::printf(const __FlashStringHelper *format, ...)
  80. {
  81. va_list ap;
  82. va_start(ap, format);
  83. #ifdef __STRICT_ANSI__
  84. return 0;
  85. #else
  86. return vdprintf((int)this, (const char *)format, ap);
  87. #endif
  88. }
  89. #ifdef __MKL26Z64__
  90. // optimized code inspired by Stimmer's optimization
  91. // obviously a dit different, adapted to 32 bit Cortex-M0+
  92. // http://forum.arduino.cc/index.php?topic=167414.msg1293679#msg1293679
  93. // http://forum.arduino.cc/index.php?topic=167414.msg1309482#msg1309482
  94. // equivelant code:
  95. // mod = div % 10;
  96. // div = div / 10;
  97. // tmp1 = {random};
  98. // tmp2 = 10;
  99. #if 1
  100. // https://forum.pjrc.com/threads/28932-LC-is-10-9-times-slower-than-T3-1?p=76072&viewfull=1#post76072
  101. void inline divmod10_v2(uint32_t n,uint32_t *div,uint32_t *mod) {
  102. uint32_t p,q;
  103. /* Using 32.16 fixed point representation p.q */
  104. /* p.q = (n+1)/512 */
  105. q = (n&0xFFFF) + 1;
  106. p = (n>>16);
  107. /* p.q = 51*(n+1)/512 */
  108. q = 13107*q;
  109. p = 13107*p;
  110. /* p.q = (1+1/2^8+1/2^16+1/2^24)*51*(n+1)/512 */
  111. q = q + (q>>16) + (p&0xFFFF);
  112. p = p + (p>>16) + (q>>16);
  113. /* divide by 2 */
  114. p = p>>1;
  115. *div = p;
  116. *mod = n-10*p;
  117. }
  118. #define divmod10_asm(div, mod, tmp1, tmp2, const3333) \
  119. divmod10_v2(div, &div, &mod);
  120. /*
  121. #define divmod10_asm(div, mod, tmp1, tmp2, const3333) \
  122. asm ( \
  123. " lsr %2, %0, #16" "\n\t" \
  124. " mul %2, %4" "\n\t" \
  125. " uxth %1, %0" "\n\t" \
  126. " mul %1, %4" "\n\t" \
  127. " add %1, #1" "\n\t" \
  128. " lsr %0, %2, #16" "\n\t" \
  129. " lsl %2, %2, #16" "\n\t" \
  130. " add %1, %2" "\n\t" \
  131. " mov %3, #0" "\n\t" \
  132. " adc %0, %3" "\n\t" \
  133. " lsl %0, %0, #15" "\n\t" \
  134. " lsr %2, %1, #17" "\n\t" \
  135. " orr %0, %2" "\n\t" \
  136. " lsl %1, %1, #15" "\n\t" \
  137. " lsr %2, %1, #16" "\n\t" \
  138. " lsl %3, %0, #16" "\n\t" \
  139. " orr %2, %3" "\n\t" \
  140. " lsr %3, %0, #16" "\n\t" \
  141. " add %1, %0" "\n\t" \
  142. " adc %0, %1" "\n\t" \
  143. " sub %0, %1" "\n\t" \
  144. " add %1, %2" "\n\t" \
  145. " adc %0, %3" "\n\t" \
  146. " lsr %1, %1, #4" "\n\t" \
  147. " mov %3, #10" "\n\t" \
  148. " mul %1, %3" "\n\t" \
  149. " lsr %1, %1, #28" "\n\t" \
  150. : "+l" (div), \
  151. "=&l" (mod), \
  152. "=&l" (tmp1), \
  153. "=&l" (tmp2) \
  154. : "l" (const3333) \
  155. : \
  156. )
  157. */
  158. #else
  159. #define divmod10_asm(_div, _mod, _tmp1, _tmp2, _const3333) \
  160. ({ _tmp1 = _div; _div = _div / 10; _mod = _tmp1 - _div * 10; })
  161. // ({_mod = _div % 10, _div = _div / 10; })
  162. #endif
  163. size_t Print::printNumberDec(unsigned long n, uint8_t sign)
  164. {
  165. uint8_t buf[11], *p;
  166. uint32_t digit;
  167. //uint32_t t1, t2, c3333=0x3333;
  168. p = buf + (sizeof(buf));
  169. do {
  170. uint32_t div;
  171. divmod10_v2(n, &div, &digit);
  172. n = div;
  173. //divmod10_asm(n, digit, t1, t2, c3333);
  174. *--p = digit + '0';
  175. } while (n);
  176. if (sign) *--p = '-';
  177. return write(p, sizeof(buf) - (p - buf));
  178. }
  179. size_t Print::printNumberHex(unsigned long n)
  180. {
  181. uint8_t digit, buf[8], *p;
  182. p = buf + (sizeof(buf));
  183. do {
  184. digit = n & 15;
  185. *--p = (digit < 10) ? '0' + digit : 'A' + digit - 10;
  186. n >>= 4;
  187. } while (n);
  188. return write(p, sizeof(buf) - (p - buf));
  189. }
  190. size_t Print::printNumberBin(unsigned long n)
  191. {
  192. uint8_t buf[32], *p;
  193. p = buf + (sizeof(buf));
  194. do {
  195. *--p = '0' + ((uint8_t)n & 1);
  196. n >>= 1;
  197. } while (n);
  198. return write(p, sizeof(buf) - (p - buf));
  199. }
  200. size_t Print::printNumberAny(unsigned long n, uint8_t base)
  201. {
  202. uint8_t digit, buf[21], *p;
  203. uint32_t tmp;
  204. p = buf + sizeof(buf);
  205. do {
  206. tmp = n;
  207. n = n / base;
  208. digit = tmp - n * base;
  209. *--p = (digit < 10) ? '0' + digit : 'A' + digit - 10;
  210. } while (n);
  211. return write(p, sizeof(buf) - (p - buf));
  212. }
  213. #else
  214. size_t Print::printNumber(unsigned long n, uint8_t base, uint8_t sign)
  215. {
  216. uint8_t buf[34];
  217. uint8_t digit, i;
  218. // TODO: make these checks as inline, since base is
  219. // almost always a constant. base = 0 (BYTE) should
  220. // inline as a call directly to write()
  221. if (base == 0) {
  222. return write((uint8_t)n);
  223. } else if (base == 1) {
  224. base = 10;
  225. }
  226. if (n == 0) {
  227. buf[sizeof(buf) - 1] = '0';
  228. i = sizeof(buf) - 1;
  229. } else {
  230. i = sizeof(buf) - 1;
  231. while (1) {
  232. digit = n % base;
  233. buf[i] = ((digit < 10) ? '0' + digit : 'A' + digit - 10);
  234. n /= base;
  235. if (n == 0) break;
  236. i--;
  237. }
  238. }
  239. if (sign) {
  240. i--;
  241. buf[i] = '-';
  242. }
  243. return write(buf + i, sizeof(buf) - i);
  244. }
  245. #endif
  246. size_t Print::printFloat(double number, uint8_t digits)
  247. {
  248. uint8_t sign=0;
  249. size_t count=0;
  250. if (isnan(number)) return print("nan");
  251. if (isinf(number)) return print("inf");
  252. if (number > 4294967040.0f) return print("ovf"); // constant determined empirically
  253. if (number <-4294967040.0f) return print("ovf"); // constant determined empirically
  254. // Handle negative numbers
  255. if (number < 0.0) {
  256. sign = 1;
  257. number = -number;
  258. }
  259. // Round correctly so that print(1.999, 2) prints as "2.00"
  260. double rounding = 0.5;
  261. for (uint8_t i=0; i<digits; ++i) {
  262. rounding *= 0.1;
  263. }
  264. number += rounding;
  265. // Extract the integer part of the number and print it
  266. unsigned long int_part = (unsigned long)number;
  267. double remainder = number - (double)int_part;
  268. count += printNumber(int_part, 10, sign);
  269. // Print the decimal point, but only if there are digits beyond
  270. if (digits > 0) {
  271. uint8_t n, buf[16], count=1;
  272. buf[0] = '.';
  273. // Extract digits from the remainder one at a time
  274. if (digits > sizeof(buf) - 1) digits = sizeof(buf) - 1;
  275. while (digits-- > 0) {
  276. remainder *= 10.0;
  277. n = (uint8_t)(remainder);
  278. buf[count++] = '0' + n;
  279. remainder -= n;
  280. }
  281. count += write(buf, count);
  282. }
  283. return count;
  284. }