Skip to content

Commit

Permalink
[io] Refactor IOStream to use external printf
Browse files Browse the repository at this point in the history
  • Loading branch information
salkinium committed Apr 27, 2019
1 parent a45d4ce commit 45b158c
Show file tree
Hide file tree
Showing 16 changed files with 624 additions and 1,306 deletions.
1 change: 1 addition & 0 deletions examples/arduino_uno/basic/read_analog_voltage/project.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<extends>modm:arduino-uno</extends>
<options>
<option name="modm:build:build.path">../../../../build/arduino_uno/basic/read_analog_voltage</option>
<option name="modm:io:with_float">True</option>
</options>
<modules>
<module>modm:platform:adc</module>
Expand Down
1 change: 1 addition & 0 deletions examples/avr/block_device_mirror/project.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<option name="modm:target">atmega644</option>
<option name="modm:platform:clock:f_cpu">14745600</option>
<option name="modm:build:build.path">../../../build/avr/block_device_mirror</option>
<option name="modm:io:with_printf">True</option>
</options>
<modules>
<module>modm:debug</module>
Expand Down
1 change: 1 addition & 0 deletions examples/avr/can/mcp2515/project.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<option name="modm:target">atmega644</option>
<option name="modm:platform:clock:f_cpu">14745600</option>
<option name="modm:build:build.path">../../../../build/avr/can/mcp2515</option>
<option name="modm:io:with_printf">True</option>
</options>
<modules>
<module>modm:driver:mcp2515</module>
Expand Down
1 change: 1 addition & 0 deletions examples/avr/can/mcp2515_uart/project.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<option name="modm:target">atmega644</option>
<option name="modm:platform:clock:f_cpu">14745600</option>
<option name="modm:build:build.path">../../../../build/avr/can/mcp2515_uart</option>
<option name="modm:io:with_printf">True</option>
</options>
<modules>
<module>modm:architecture:interrupt</module>
Expand Down
2 changes: 2 additions & 0 deletions examples/avr/xpcc/receiver/project.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
<option name="modm:build:build.path">../../../../build/avr/xpcc/receiver</option>
<option name="modm::xpcc:generator:source">../../../xpcc/xml/communication.xml</option>
<option name="modm::xpcc:generator:container">receiver</option>
<option name="modm:io:with_printf">True</option>
<option name="modm:io:with_float">True</option>
</options>
<modules>
<module>modm:communication:xpcc:generator</module>
Expand Down
2 changes: 2 additions & 0 deletions examples/avr/xpcc/sender/project.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
<option name="modm:build:build.path">../../../../build/avr/xpcc/sender</option>
<option name="modm::xpcc:generator:source">../../../xpcc/xml/communication.xml</option>
<option name="modm::xpcc:generator:container">sender</option>
<option name="modm:io:with_printf">True</option>
<option name="modm:io:with_float">True</option>
</options>
<modules>
<module>modm:communication:xpcc:generator</module>
Expand Down
26 changes: 26 additions & 0 deletions ext/mpaland/printf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2019, Niklas Hauser
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#pragma once

// empty include header for printf.c
#include <stdarg.h>
#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

void _putchar(char character);

#ifdef __cplusplus
}
#endif
258 changes: 49 additions & 209 deletions src/modm/io/iostream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright (c) 2009-2010, Martin Rosekeit
* Copyright (c) 2009-2012, Fabian Greif
* Copyright (c) 2011, Georgi Grinshpun
* Copyright (c) 2012-2014, Niklas Hauser
* Copyright (c) 2012-2014, 2019 Niklas Hauser
* Copyright (c) 2016, Sascha Schade
*
* This file is part of the modm project.
Expand All @@ -13,256 +13,96 @@
*/
// ----------------------------------------------------------------------------

#include <stdlib.h>

#include <modm/math/utils/arithmetic_traits.hpp>
#include <modm/architecture/interface/accessor_flash.hpp>

#include "iostream.hpp"

FLASH_STORAGE(uint16_t base[]) = { 10, 100, 1000, 10000 };

// ----------------------------------------------------------------------------
modm::IOStream::IOStream(IODevice& outputDevice) :
device(&outputDevice),
mode(Mode::Ascii)
namespace modm
{
}

// ----------------------------------------------------------------------------
void
modm::IOStream::writeInteger(int16_t value)
IOStream&
IOStream::get(char* s, size_t n)
{
if (value < 0) {
this->device->write('-');
this->writeInteger(static_cast<uint16_t>(-value));
}
else{
this->writeInteger(static_cast<uint16_t>(value));
if(n < 1) {
return *this;
}
}

void
modm::IOStream::writeInteger(uint16_t value)
{
accessor::Flash<uint16_t> basePtr = modm::accessor::asFlash(base);

bool zero = true;
uint8_t i = 4;
do {
i--;
char d;
for (d = static_cast<uint16_t>('0'); value >= basePtr[i]; value -= basePtr[i])
{
d++;
zero = false;
}
if (!zero) {
this->device->write(d);
char cc;
size_t ii;
for(ii = 0; ii < (n-1); ++ii) {
if(device->read(cc)) {
s[ii] = cc;
} else {
break;
}
} while (i);

this->device->write(static_cast<char>(value) + '0');
}

void
modm::IOStream::writeInteger(int32_t value)
{
#if defined(MODM_CPU_AVR)
char buffer[ArithmeticTraits<int32_t>::decimalDigits + 1]; // +1 for '\0'

// Uses the optimized non standard function 'ltoa()' which is
// not always available.

this->device->write(ltoa(value, buffer, 10));
#else
if (value < 0) {
this->device->write('-');
this->writeInteger(static_cast<uint32_t>(-value));
}
else{
this->writeInteger(static_cast<uint32_t>(value));
}
#endif
}

void
modm::IOStream::writeInteger(uint32_t value)
{
#if defined(MODM_CPU_AVR)
char buffer[ArithmeticTraits<uint32_t>::decimalDigits + 1]; // +1 for '\0'

// Uses the optimized non standard function 'ultoa()' which is
// not always available.
this->device->write(ultoa(value, buffer, 10));
#else
char buffer[ArithmeticTraits<uint32_t>::decimalDigits + 1]; // +1 for '\0'

// ptr points to the end of the string, it will be filled backwards
char *ptr = buffer + ArithmeticTraits<uint32_t>::decimalDigits;

*ptr = '\0';

// calculate the string backwards
do{
uint32_t quot = value / 10;
uint8_t rem = value - quot*10;
*(--ptr) = static_cast<char>(rem) + '0';
value = quot;
}while (value != 0);

// write string
this->device->write(ptr);
#endif
}

#ifndef MODM_CPU_AVR
void
modm::IOStream::writeInteger(int64_t value)
{
if (value < 0) {
this->device->write('-');
this->writeInteger(static_cast<uint64_t>(-value));
}
else{
this->writeInteger(static_cast<uint64_t>(value));
}
}

void
modm::IOStream::writeInteger(uint64_t value)
{
char buffer[ArithmeticTraits<uint64_t>::decimalDigits + 1]; // +1 for '\0'

// ptr points to the end of the string, it will be filled backwards
char *ptr = buffer + ArithmeticTraits<uint64_t>::decimalDigits;

*ptr = '\0';

// calculate the string backwards
do{
uint64_t quot = value / 10;
uint8_t rem = value - quot*10;
*(--ptr) = static_cast<char>(rem) + '0';
value = quot;
}while (value != 0);

// write string
this->device->write(ptr);
s[ii] = '\0';
return *this;
}
#endif

// ----------------------------------------------------------------------------
void
modm::IOStream::writeHex(const char* s)
{
while (*s != '\0') {
this->writeHex(*s);
s++;
}
}

void
modm::IOStream::writeBin(const char* s)
IOStream&
IOStream::operator << (const bool& v)
{
while (*s != '\0') {
this->writeBin(*s);
s++;
switch (mode)
{
case Mode::Ascii:
device->write(v ? "true" : "false");
break;
case Mode::Hexadecimal:
device->write('0');
// fallthrough
case Mode::Binary:
device->write(v ? '1' : '0');
break;
}
return *this;
}

// ----------------------------------------------------------------------------
void
modm::IOStream::writeHexNibble(uint8_t nibble)
IOStream::writeHex(uint8_t value)
{
char character;
if (nibble > 9) {
character = nibble + 'A' - 10;
}
else {
character = nibble + '0';
}
this->device->write(character);
const auto fn_nibble = [this](uint8_t nibble)
{
device->write( (nibble > 9) ? (nibble + 'A' - 10) : (nibble + '0') );
};
fn_nibble(value >> 4);
fn_nibble(value & 0xF);
}

// ----------------------------------------------------------------------------
void
modm::IOStream::writeHex(uint8_t value)
{
writeHexNibble(value >> 4);
writeHexNibble(value & 0xF);
}

void
modm::IOStream::writeBin(uint8_t value)
IOStream::writeBin(uint8_t value)
{
for (uint_fast8_t ii = 0; ii < 8; ii++)
{
if (value & 0x80) {
this->device->write('1');
}
else {
this->device->write('0');
}
device->write(value & 0x80 ? '1' : '0');
value <<= 1;
}

}

// ----------------------------------------------------------------------------
modm::IOStream&
modm::IOStream::operator << (const myfunc& value)
void
IOStream::writePointer(const void* p)
{
unsigned char *p = (unsigned char *)&value;
device->write('0');
device->write('x');
const uintptr_t value = reinterpret_cast<uintptr_t>(p);

for (std::size_t i = 0; i < sizeof(myfunc); i++)
{
writeHex(p[sizeof(myfunc) - i - 1]);
}
return *this;
}

modm::IOStream&
modm::IOStream::operator << (const void* p)
{
#if MODM_SIZEOF_POINTER == 2

this->device->write('0');
this->device->write('x');

uint16_t value = reinterpret_cast<uint16_t>(p);

writeHex(value >> 8);
writeHex(value);

#elif MODM_SIZEOF_POINTER == 4

this->device->write('0');
this->device->write('x');

uint32_t value = reinterpret_cast<uint32_t>(p);

writeHex(value >> 24);
writeHex(value >> 16);
writeHex(value >> 8);
writeHex(value);
for (uint8_t ii=24; ii < 32; ii -= 8)
writeHex(value >> ii);

#elif MODM_SIZEOF_POINTER == 8

this->device->write('0');
this->device->write('x');

uint64_t value = reinterpret_cast<uint64_t>(p);

writeHex(value >> 56);
writeHex(value >> 48);
writeHex(value >> 40);
writeHex(value >> 32);
writeHex(value >> 24);
writeHex(value >> 16);
writeHex(value >> 8);
writeHex(value);
for (uint8_t ii=56; ii < 64; ii -= 8)
writeHex(value >> ii);

#endif
return *this;
}

} // namespace modm
Loading

0 comments on commit 45b158c

Please sign in to comment.