opsroller / arduino

Automatically exported from code.google.com/p/arduino
Other
0 stars 0 forks source link

Print class to use block write #164

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What change would like to see?

The Print class could make use if its own block write method.

Why?

Some classes that use Print, such as Ethernet, can substantially benefit
from the block write.

Would this cause any incompatibilities with previous versions?  If so, how
can these be mitigated?

If another class does not make use of the block write, the single byte
write is automatically used to write each byte from the block. There should
be no incompatibilities.

For example, printNumber already buffers, but then duplicates the
functionality of transmitting the bytes one at a time.  It's simple to
change so the bytes are packed into the buffer in the correct order, so the
block write can be used:

void Print::printNumber(unsigned long n, uint8_t base, uint8_t sign)
{
        uint8_t buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars.
        uint8_t digit, i;

        if (n == 0) {
                buf[sizeof(buf) - 1] = '0';
                i = sizeof(buf) - 1;
        } else {
                i = sizeof(buf) - 1;
                while (1) {
                        digit = n % base;
                        buf[i] = ((digit < 10) ? '0' + digit : 'A' + digit
- 10);
                        n /= base;
                        if (n == 0) break;
                        i--;
                }
        }
        if (sign) {
                i--;
                buf[i] = sign;
        }
        write(buf + i, sizeof(buf) - i);
}

This also includes packing the sign into the buffer.  This it can be called
like this:

void Print::print(long n)
{
        uint8_t sign=0;

        if (n < 0) {
                sign = '-';
                n = -n;
        }
        printNumber(n, 10, sign);
}

void Print::print(unsigned long n)
{
        printNumber(n, 10, 0);
}

Likewise, printing the newline is easy to change:

void Print::println(void)
{
        uint8_t buf[2]={'\r', '\n'};
        write(buf, 2);
}

Float printing requires a bit more effort, but it's also not too difficult
(especially if this already-tested code is just copied):

void Print::printFloat(double number, uint8_t digits)
{
  uint8_t sign=0;

  // Handle negative numbers
  if (number < 0.0) {
     sign = '-';
     number = -number;
  }

  // Round correctly so that print(1.999, 2) prints as "2.00"
  double rounding = 0.5;
  for (uint8_t i=0; i<digits; ++i)
    rounding /= 10.0;

  number += rounding;

  // Extract the integer part of the number and print it
  unsigned long int_part = (unsigned long)number;
  double remainder = number - (double)int_part;
  printNumber(int_part, 10, sign);

  // Print the decimal point, but only if there are digits beyond
  if (digits > 0) {
        uint8_t n, buf[5], count=1;
        buf[0] = '.';

        //write('.'); 
        // Extract digits from the remainder one at a time
        if (digits > sizeof(buf) - 1) digits = sizeof(buf) - 1;

        while (digits-- > 0) {
                remainder *= 10.0;
                n = (uint8_t)(remainder);
                buf[count++] = '0' + n;
                remainder -= n;
        }
        write(buf, count);
  }
}

Original issue reported on code.google.com by paul.sto...@gmail.com on 2 Jan 2010 at 12:48

GoogleCodeExporter commented 9 years ago
Here is a newer version of this code

Original comment by paul.sto...@gmail.com on 24 Feb 2011 at 6:04

Attachments:

GoogleCodeExporter commented 9 years ago
Applied for positive numbers: 
https://github.com/arduino/Arduino/commit/174729271194e50e13ce9c6c6be0272c169470
50

Original comment by dmel...@gmail.com on 7 May 2011 at 10:20