From 121f83a420a465f19159fec9c3ba75f0a35f3902 Mon Sep 17 00:00:00 2001 From: David Sidrane Date: Wed, 19 Aug 2015 10:54:02 -1000 Subject: [PATCH 01/15] Proper file IO loops #40 --- .../basic_file_server_backend.hpp | 34 +++++++++------- .../file_event_tracer.hpp | 21 +++++++--- .../file_storage_backend.hpp | 40 +++++++++++++++---- .../uavcan_posix/firmware_version_checker.hpp | 20 ++++++++-- 4 files changed, 85 insertions(+), 30 deletions(-) diff --git a/libuavcan_drivers/posix/include/uavcan_posix/basic_file_server_backend.hpp b/libuavcan_drivers/posix/include/uavcan_posix/basic_file_server_backend.hpp index 11e291a955..dd501e82fe 100644 --- a/libuavcan_drivers/posix/include/uavcan_posix/basic_file_server_backend.hpp +++ b/libuavcan_drivers/posix/include/uavcan_posix/basic_file_server_backend.hpp @@ -380,7 +380,7 @@ protected: { int rv = uavcan::protocol::file::Error::INVALID_VALUE; - if (path.size() > 0) + if (path.size() > 0 && inout_size != 0) { FDCacheBase& cache = getFDCache(); int fd = cache.open(path.c_str(), O_RDONLY); @@ -391,9 +391,9 @@ protected: } else { - rv = ::lseek(fd, offset, SEEK_SET); + ssize_t total_read = 0; - ssize_t len = 0; + rv = ::lseek(fd, offset, SEEK_SET); if (rv < 0) { @@ -401,21 +401,27 @@ protected: } else { - // TODO use a read at offset to fill on EAGAIN - len = ::read(fd, out_buffer, inout_size); - - if (len < 0) + rv = 0; + ssize_t remaining = inout_size; + ssize_t nread; + do { - rv = errno; - } - else - { - rv = 0; + nread = ::read(fd, &out_buffer[total_read], remaining); + if (nread < 0) + { + rv = errno; + } + else + { + remaining -= nread, + total_read += nread; + } } + while (nread > 0 && remaining > 0); } - (void)cache.close(fd, rv != 0 || len != inout_size); - inout_size = len; + (void)cache.close(fd, rv != 0 || total_read != inout_size); + inout_size = total_read; } } return rv; diff --git a/libuavcan_drivers/posix/include/uavcan_posix/dynamic_node_id_server/file_event_tracer.hpp b/libuavcan_drivers/posix/include/uavcan_posix/dynamic_node_id_server/file_event_tracer.hpp index d07f6d5624..c3328929a7 100644 --- a/libuavcan_drivers/posix/include/uavcan_posix/dynamic_node_id_server/file_event_tracer.hpp +++ b/libuavcan_drivers/posix/include/uavcan_posix/dynamic_node_id_server/file_event_tracer.hpp @@ -51,10 +51,22 @@ protected: { const int FormatBufferLength = 63; char buffer[FormatBufferLength + 1]; - int n = snprintf(buffer, FormatBufferLength, "%ld.%06ld\t%d\t%lld\n", - static_cast(ts.tv_sec), static_cast(ts.tv_nsec / 1000L), - static_cast(code), static_cast(argument)); - (void)write(fd, buffer, n); // TODO FIXME Write loop + ssize_t remaining = snprintf(buffer, FormatBufferLength, "%ld.%06ld\t%d\t%lld\n", + static_cast(ts.tv_sec), static_cast(ts.tv_nsec / 1000L), + static_cast(code), static_cast(argument)); + + ssize_t total_written = 0; + ssize_t written; + do + { + written = write(fd, &buffer[total_written], remaining); + if (written > 0) + { + total_written += written; + remaining -= written; + } + } + while (written > 0 && remaining > 0); (void)close(fd); } } @@ -82,7 +94,6 @@ public: return rv; } }; - } } diff --git a/libuavcan_drivers/posix/include/uavcan_posix/dynamic_node_id_server/file_storage_backend.hpp b/libuavcan_drivers/posix/include/uavcan_posix/dynamic_node_id_server/file_storage_backend.hpp index 7374c3cc0d..664fc7f611 100644 --- a/libuavcan_drivers/posix/include/uavcan_posix/dynamic_node_id_server/file_storage_backend.hpp +++ b/libuavcan_drivers/posix/include/uavcan_posix/dynamic_node_id_server/file_storage_backend.hpp @@ -55,13 +55,25 @@ protected: { char buffer[MaxStringLength + 1]; (void)memset(buffer, 0, sizeof(buffer)); - int len = read(fd, buffer, MaxStringLength); - (void)close(fd); - if (len > 0) + ssize_t remaining = MaxStringLength; + ssize_t total_read = 0; + ssize_t nread; + do { - for (int i = 0; i < len; i++) + nread = ::read(fd, &buffer[total_read], remaining); + if (nread > 0) { - if (buffer[i] == ' ' || buffer[i] == '\n' || buffer[i] == '\r' ) + remaining -= nread, + total_read += nread; + } + } + while (nread > 0 && remaining > 0); + (void)close(fd); + if (total_read > 0) + { + for (int i = 0; i < total_read; i++) + { + if (buffer[i] == ' ' || buffer[i] == '\n' || buffer[i] == '\r') { buffer[i] = '\0'; break; @@ -81,7 +93,20 @@ protected: int fd = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, FilePermissions); if (fd >= 0) { - (void)write(fd, value.c_str(), value.size()); // TODO FIXME Write loop + ssize_t remaining = value.size(); + ssize_t total_written = 0; + ssize_t written; + do + { + written = write(fd, &value.c_str()[total_written], remaining); + if (written > 0) + { + total_written += written; + remaining -= written; + } + } + while (written > 0 && remaining > 0); + (void)fsync(fd); (void)close(fd); } @@ -117,7 +142,7 @@ public: // coverity[toctou] rv = mkdir(base_path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); } - if (rv >= 0 ) + if (rv >= 0) { base_path.push_back('/'); if ((base_path.size() + MaxStringLength) > MaxPathLength) @@ -129,7 +154,6 @@ public: return rv; } }; - } } diff --git a/libuavcan_drivers/posix/include/uavcan_posix/firmware_version_checker.hpp b/libuavcan_drivers/posix/include/uavcan_posix/firmware_version_checker.hpp index 58143e1056..7fe66d6ae6 100644 --- a/libuavcan_drivers/posix/include/uavcan_posix/firmware_version_checker.hpp +++ b/libuavcan_drivers/posix/include/uavcan_posix/firmware_version_checker.hpp @@ -125,10 +125,24 @@ class FirmwareVersionChecker : public uavcan::IFirmwareVersionChecker } else { - if (size != write(dfd, buffer, size)) + rv = 0; + ssize_t remaining = size; + ssize_t total_written = 0; + ssize_t written; + do { - rv = -errno; + written = write(dfd, &buffer[total_written], remaining); + if (written < 0) + { + rv = -errno; + } + else + { + total_written += written; + remaining -= written; + } } + while (written > 0 && remaining > 0); } } } @@ -251,7 +265,7 @@ protected: node_info.hardware_version.major, node_info.hardware_version.minor); - if (n > 0 && n < (int) sizeof(fname_root) - 2) + if (n > 0 && n < (int)sizeof(fname_root) - 2) { DIR* const fwdir = opendir(fname_root); From b4b6c9eff577023243d12d62418cae32cdcb9344 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Thu, 20 Aug 2015 05:30:15 +0300 Subject: [PATCH 02/15] Default initialization of stack variables --- .../include/uavcan_posix/basic_file_server_backend.hpp | 2 +- .../dynamic_node_id_server/file_event_tracer.hpp | 2 +- .../dynamic_node_id_server/file_storage_backend.hpp | 4 ++-- .../posix/include/uavcan_posix/firmware_version_checker.hpp | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libuavcan_drivers/posix/include/uavcan_posix/basic_file_server_backend.hpp b/libuavcan_drivers/posix/include/uavcan_posix/basic_file_server_backend.hpp index dd501e82fe..e8059b0f89 100644 --- a/libuavcan_drivers/posix/include/uavcan_posix/basic_file_server_backend.hpp +++ b/libuavcan_drivers/posix/include/uavcan_posix/basic_file_server_backend.hpp @@ -403,7 +403,7 @@ protected: { rv = 0; ssize_t remaining = inout_size; - ssize_t nread; + ssize_t nread = 0; do { nread = ::read(fd, &out_buffer[total_read], remaining); diff --git a/libuavcan_drivers/posix/include/uavcan_posix/dynamic_node_id_server/file_event_tracer.hpp b/libuavcan_drivers/posix/include/uavcan_posix/dynamic_node_id_server/file_event_tracer.hpp index c3328929a7..50b8202184 100644 --- a/libuavcan_drivers/posix/include/uavcan_posix/dynamic_node_id_server/file_event_tracer.hpp +++ b/libuavcan_drivers/posix/include/uavcan_posix/dynamic_node_id_server/file_event_tracer.hpp @@ -56,7 +56,7 @@ protected: static_cast(code), static_cast(argument)); ssize_t total_written = 0; - ssize_t written; + ssize_t written = 0; do { written = write(fd, &buffer[total_written], remaining); diff --git a/libuavcan_drivers/posix/include/uavcan_posix/dynamic_node_id_server/file_storage_backend.hpp b/libuavcan_drivers/posix/include/uavcan_posix/dynamic_node_id_server/file_storage_backend.hpp index 664fc7f611..03ee6175bb 100644 --- a/libuavcan_drivers/posix/include/uavcan_posix/dynamic_node_id_server/file_storage_backend.hpp +++ b/libuavcan_drivers/posix/include/uavcan_posix/dynamic_node_id_server/file_storage_backend.hpp @@ -57,7 +57,7 @@ protected: (void)memset(buffer, 0, sizeof(buffer)); ssize_t remaining = MaxStringLength; ssize_t total_read = 0; - ssize_t nread; + ssize_t nread = 0; do { nread = ::read(fd, &buffer[total_read], remaining); @@ -95,7 +95,7 @@ protected: { ssize_t remaining = value.size(); ssize_t total_written = 0; - ssize_t written; + ssize_t written = 0; do { written = write(fd, &value.c_str()[total_written], remaining); diff --git a/libuavcan_drivers/posix/include/uavcan_posix/firmware_version_checker.hpp b/libuavcan_drivers/posix/include/uavcan_posix/firmware_version_checker.hpp index 7fe66d6ae6..7c6b76cad0 100644 --- a/libuavcan_drivers/posix/include/uavcan_posix/firmware_version_checker.hpp +++ b/libuavcan_drivers/posix/include/uavcan_posix/firmware_version_checker.hpp @@ -113,7 +113,7 @@ class FirmwareVersionChecker : public uavcan::IFirmwareVersionChecker } else { - ssize_t size; + ssize_t size = 0; do { size = ::read(sfd, buffer, sizeof(buffer)); @@ -128,7 +128,7 @@ class FirmwareVersionChecker : public uavcan::IFirmwareVersionChecker rv = 0; ssize_t remaining = size; ssize_t total_written = 0; - ssize_t written; + ssize_t written = 0; do { written = write(dfd, &buffer[total_written], remaining); @@ -146,7 +146,7 @@ class FirmwareVersionChecker : public uavcan::IFirmwareVersionChecker } } } - while (rv == 0 && size); + while (rv == 0 && size != 0); (void)close(sfd); } From cf39ecf87900be8be30911194d366a43d9b56e2e Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Thu, 20 Aug 2015 05:42:17 +0300 Subject: [PATCH 03/15] POSIX driver: Proper use of std:: and uavcan:: --- .../basic_file_server_backend.hpp | 19 ++++++++++++------- .../uavcan_posix/firmware_version_checker.hpp | 16 +++++++++------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/libuavcan_drivers/posix/include/uavcan_posix/basic_file_server_backend.hpp b/libuavcan_drivers/posix/include/uavcan_posix/basic_file_server_backend.hpp index e8059b0f89..54fc5de6a3 100644 --- a/libuavcan_drivers/posix/include/uavcan_posix/basic_file_server_backend.hpp +++ b/libuavcan_drivers/posix/include/uavcan_posix/basic_file_server_backend.hpp @@ -75,7 +75,7 @@ protected: friend FDCache; FDCacheItem* next_; - time_t last_access_; + std::time_t last_access_; const int fd_; const int oflags_; const char* const path_; @@ -101,6 +101,7 @@ protected: ~FDCacheItem() { + using namespace std; if (valid()) { ::free(const_cast(path_)); @@ -117,13 +118,14 @@ protected: return fd_; } - time_t getAccess() const + std::time_t getAccess() const { return last_access_; } - time_t acessed() + std::time_t acessed() { + using namespace std; last_access_ = time(NULL); return getAccess(); } @@ -135,11 +137,13 @@ protected: bool expired() const { + using namespace std; return 0 == last_access_ || (time(NULL) - last_access_) > MaxAgeSeconds; } bool equals(const char* path, int oflags) const { + using namespace std; return oflags_ == oflags && 0 == ::strcmp(path, path_); } @@ -275,7 +279,6 @@ protected: if (pi && !pi->valid()) { /* Allocation worked but clone or path failed */ - delete pi; pi = NULL; } @@ -286,7 +289,6 @@ protected: * If allocation fails no harm just can not cache it * return open fd */ - return fd; } /* add new */ @@ -334,7 +336,7 @@ protected: * Implementation of this method is required. * On success the method must return zero. */ - virtual int16_t getInfo(const Path& path, uint64_t& out_size, EntryType& out_type) + virtual uavcan::int16_t getInfo(const Path& path, uavcan::uint64_t& out_size, EntryType& out_type) { int rv = uavcan::protocol::file::Error::INVALID_VALUE; @@ -376,12 +378,15 @@ protected: * if the end of file is reached. * On success the method must return zero. */ - virtual int16_t read(const Path& path, const uint64_t offset, uint8_t* out_buffer, uint16_t& inout_size) + virtual uavcan::int16_t read(const Path& path, const uavcan::uint64_t offset, uavcan::uint8_t* out_buffer, + uavcan::uint16_t& inout_size) { int rv = uavcan::protocol::file::Error::INVALID_VALUE; if (path.size() > 0 && inout_size != 0) { + using namespace std; + FDCacheBase& cache = getFDCache(); int fd = cache.open(path.c_str(), O_RDONLY); diff --git a/libuavcan_drivers/posix/include/uavcan_posix/firmware_version_checker.hpp b/libuavcan_drivers/posix/include/uavcan_posix/firmware_version_checker.hpp index 7c6b76cad0..a258a6a368 100644 --- a/libuavcan_drivers/posix/include/uavcan_posix/firmware_version_checker.hpp +++ b/libuavcan_drivers/posix/include/uavcan_posix/firmware_version_checker.hpp @@ -86,6 +86,8 @@ class FirmwareVersionChecker : public uavcan::IFirmwareVersionChecker int copyIfNot(const char* srcpath, const char* destpath) { + using namespace std; + // Does the file exist int rv = 0; int dfd = open(destpath, O_RDONLY, 0); @@ -158,13 +160,13 @@ class FirmwareVersionChecker : public uavcan::IFirmwareVersionChecker struct AppDescriptor { - uint8_t signature[sizeof(uavcan::uint64_t)]; - uint64_t image_crc; - uint32_t image_size; - uint32_t vcs_commit; - uint8_t major_version; - uint8_t minor_version; - uint8_t reserved[6]; + uavcan::uint8_t signature[sizeof(uavcan::uint64_t)]; + uavcan::uint64_t image_crc; + uavcan::uint32_t image_size; + uavcan::uint32_t vcs_commit; + uavcan::uint8_t major_version; + uavcan::uint8_t minor_version; + uavcan::uint8_t reserved[6]; }; static int getFileInfo(const char* path, AppDescriptor& descriptor) From 3ae5400aa5ead18139106d30f730114d5e9b65dd Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Thu, 20 Aug 2015 12:21:56 +0300 Subject: [PATCH 04/15] DSDL sync --- dsdl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dsdl b/dsdl index fd12483ddd..1abd370556 160000 --- a/dsdl +++ b/dsdl @@ -1 +1 @@ -Subproject commit fd12483ddd4e58242d61d74a163e7aeaa1e0f466 +Subproject commit 1abd370556aea6aa93dfb0683965a8a43a26a29f From cfa77b13a4ade17fcb2ece403f6d8f1bea734161 Mon Sep 17 00:00:00 2001 From: Ben Dyer Date: Fri, 21 Aug 2015 15:57:04 +1000 Subject: [PATCH 05/15] Add UAVCAN_NO_GLOBAL_DATA_TYPE_REGISTRY flag to allow the global data type registry to be disabled --- libuavcan/include/uavcan/build_config.hpp | 7 +++++++ .../include/uavcan/node/global_data_type_registry.hpp | 2 ++ 2 files changed, 9 insertions(+) diff --git a/libuavcan/include/uavcan/build_config.hpp b/libuavcan/include/uavcan/build_config.hpp index 6b8768c3e5..7fa799def8 100644 --- a/libuavcan/include/uavcan/build_config.hpp +++ b/libuavcan/include/uavcan/build_config.hpp @@ -100,6 +100,13 @@ # define UAVCAN_TINY 0 #endif +/** + * Disable the global data type registry, which can save some space on embedded systems. + */ +#ifndef UAVCAN_NO_GLOBAL_DATA_TYPE_REGISTRY +# define UAVCAN_NO_GLOBAL_DATA_TYPE_REGISTRY 1 +#endif + /** * toString() methods will be disabled by default, unless the library is built for a general-purpose target like Linux. * It is not recommended to enable toString() on embedded targets as code size will explode. diff --git a/libuavcan/include/uavcan/node/global_data_type_registry.hpp b/libuavcan/include/uavcan/node/global_data_type_registry.hpp index cedf0d9724..fb8d43c39b 100644 --- a/libuavcan/include/uavcan/node/global_data_type_registry.hpp +++ b/libuavcan/include/uavcan/node/global_data_type_registry.hpp @@ -187,6 +187,7 @@ struct UAVCAN_EXPORT DefaultDataTypeRegistrator { DefaultDataTypeRegistrator() { +#if !UAVCAN_NO_GLOBAL_DATA_TYPE_REGISTRY const GlobalDataTypeRegistry::RegistrationResult res = GlobalDataTypeRegistry::instance().registerDataType(Type::DefaultDataTypeID); @@ -194,6 +195,7 @@ struct UAVCAN_EXPORT DefaultDataTypeRegistrator { handleFatalError("Type reg failed"); } +#endif } }; From adfe61d613690d05c3bae978d6fd0cd78a51105b Mon Sep 17 00:00:00 2001 From: Ben Dyer Date: Fri, 21 Aug 2015 17:57:41 +1000 Subject: [PATCH 06/15] Use NumPy half<->float routines to avoid dependence on math functions in C stdlib --- libuavcan/src/marshal/uc_float_spec.cpp | 179 +++++++++++++++--------- 1 file changed, 111 insertions(+), 68 deletions(-) diff --git a/libuavcan/src/marshal/uc_float_spec.cpp b/libuavcan/src/marshal/uc_float_spec.cpp index 18a6e6b05e..6ca25b3604 100644 --- a/libuavcan/src/marshal/uc_float_spec.cpp +++ b/libuavcan/src/marshal/uc_float_spec.cpp @@ -6,87 +6,130 @@ #include #include -#if !defined(UAVCAN_CPP_VERSION) || !defined(UAVCAN_CPP11) -# error UAVCAN_CPP_VERSION -#endif - -#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 -# include -#endif - namespace uavcan { -/* +/** * IEEE754Converter - * Float16 conversion algorithm: http://half.sourceforge.net/ (MIT License) */ uint16_t IEEE754Converter::nativeNonIeeeToHalf(float value) { - uint16_t hbits = uint16_t(getSignBit(value) ? 0x8000U : 0); - if (areFloatsExactlyEqual(value, 0.0F)) - { - return hbits; + /** + https://github.com/numpy/numpy/blob/master/numpy/core/src/npymath/halffloat.c + BSD license + */ + union { float val; uint32_t valbits; } conv; + uint32_t f_exp, f_sig; + uint16_t h_sgn, h_exp, h_sig; + + conv.val = value; + + h_sgn = uint16_t((conv.valbits & 0x80000000U) >> 16); + f_exp = (conv.valbits & 0x7F800000U); + + /* Exponent overflow/NaN converts to signed inf/NaN */ + if (f_exp >= 0x47800000U) { + if (f_exp == 0x7F800000U) { + /* Inf or NaN */ + f_sig = (conv.valbits & 0x007FFFFFU); + if (f_sig != 0) { + /* NaN - propagate the flag in the significand... */ + return uint16_t(h_sgn | 0x7FFFU); + } else { + /* signed inf */ + return uint16_t(h_sgn + 0x7C00U); + } + } else { + /* overflow to signed inf */ + return uint16_t(h_sgn + 0x7C00U); + } } - if (isNaN(value)) - { - return hbits | 0x7FFFU; + + /* Exponent underflow converts to a subnormal half or signed zero */ + if (f_exp <= 0x38000000U) { + /** + * Signed zeros, subnormal floats, and floats with small + * exponents all convert to signed zero halfs. + */ + if (f_exp < 0x33000000U) { + return h_sgn; + } + + /* Make the subnormal significand */ + f_exp >>= 23; + f_sig = (0x00800000U + (conv.valbits & 0x007FFFFFU)); + f_sig >>= (113 - f_exp); + /* Handle rounding by adding 1 to the bit beyond half precision */ + f_sig += 0x00001000U; + + h_sig = uint16_t(f_sig >> 13); + + /** + * If the rounding causes a bit to spill into h_exp, it will + * increment h_exp from zero to one and h_sig will be zero. + * This is the correct result. + */ + return uint16_t(h_sgn + h_sig); } - if (isInfinity(value)) - { - return hbits | 0x7C00U; - } - int exp; - (void)std::frexp(value, &exp); - if (exp > 16) - { - return hbits | 0x7C00U; - } - if (exp < -13) - { - value = std::ldexp(value, 24); - } - else - { - value = std::ldexp(value, 11 - exp); - hbits |= uint16_t((exp + 14) << 10); - } - const int32_t ival = static_cast(value); - hbits = uint16_t(hbits | (uint32_t((ival < 0) ? (-ival) : ival) & 0x3FFU)); - float diff = std::fabs(value - static_cast(ival)); - hbits = uint16_t(hbits + (diff >= 0.5F)); - return hbits; + + /* Regular case with no overflow or underflow */ + h_exp = uint16_t((f_exp - 0x38000000U) >> 13); + + /* Handle rounding by adding 1 to the bit beyond half precision */ + f_sig = (conv.valbits & 0x007FFFFFU); + f_sig += 0x00001000U; + + h_sig = uint16_t(f_sig >> 13); + + /** + * If the rounding causes a bit to spill into h_exp, it will + * increment h_exp by one and h_sig will be zero. This is the + * correct result. h_exp may increment to 15, at greatest, in + * which case the result overflows to a signed inf. + */ + return uint16_t(h_sgn + h_exp + h_sig); } float IEEE754Converter::halfToNativeNonIeee(uint16_t value) { - float out; - unsigned abs = value & 0x7FFFU; - if (abs > 0x7C00U) - { -#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 - out = std::numeric_limits::has_quiet_NaN ? std::numeric_limits::quiet_NaN() : 0.0F; -#else - out = nanf(""); -#endif + /** + https://github.com/numpy/numpy/blob/master/numpy/core/src/npymath/halffloat.c + BSD license + */ + union { float ret; uint32_t retbits; } conv; + + uint16_t h_exp, h_sig; + uint32_t f_sgn, f_exp, f_sig; + + h_exp = value & 0x7C00U; + f_sgn = uint32_t(value & 0x8000U) << 16; + switch (h_exp) { + case 0x0000U: /* 0 or subnormal */ + h_sig = (value & 0x03FFU); + if (h_sig == 0) { + /* Signed zero */ + conv.retbits = f_sgn; + } else { + /* Subnormal */ + h_sig = uint16_t(h_sig << 1); + while ((h_sig & 0x0400U) == 0) { + h_sig = uint16_t(h_sig << 1); + h_exp++; + } + f_exp = uint32_t(127 - 15 - h_exp) << 23; + f_sig = uint32_t(h_sig & 0x03FFU) << 13; + conv.retbits = f_sgn + f_exp + f_sig; + } + break; + case 0x7C00U: /* inf or NaN */ + /* All-ones exponent and a copy of the significand */ + conv.retbits = f_sgn + 0x7F800000U + (uint32_t(value & 0x03FFU) << 13); + break; + default: /* normalized */ + /* Just need to adjust the exponent and shift */ + conv.retbits = f_sgn + ((uint32_t(value & 0x7FFFU) + 0x1C000U) << 13); + break; } - else if (abs == 0x7C00U) - { -#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 - out = std::numeric_limits::has_infinity ? - std::numeric_limits::infinity() : std::numeric_limits::max(); -#else - out = NumericTraits::infinity(); -#endif - } - else if (abs > 0x3FFU) - { - out = std::ldexp(static_cast((value & 0x3FFU) | 0x400U), int(abs >> 10) - 25); - } - else - { - out = std::ldexp(static_cast(abs), -24); - } - return (value & 0x8000U) ? -out : out; + return conv.ret; } } From dfc350a67ac17f6feedbe43f52f616c8712ca7db Mon Sep 17 00:00:00 2001 From: Ben Dyer Date: Fri, 21 Aug 2015 20:31:29 +1000 Subject: [PATCH 07/15] Correct default flag value --- libuavcan/include/uavcan/build_config.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libuavcan/include/uavcan/build_config.hpp b/libuavcan/include/uavcan/build_config.hpp index 7fa799def8..0045fe6f0c 100644 --- a/libuavcan/include/uavcan/build_config.hpp +++ b/libuavcan/include/uavcan/build_config.hpp @@ -104,7 +104,7 @@ * Disable the global data type registry, which can save some space on embedded systems. */ #ifndef UAVCAN_NO_GLOBAL_DATA_TYPE_REGISTRY -# define UAVCAN_NO_GLOBAL_DATA_TYPE_REGISTRY 1 +# define UAVCAN_NO_GLOBAL_DATA_TYPE_REGISTRY 0 #endif /** From e97f948b9abbbf129057e73f6c571aa5d1558a5f Mon Sep 17 00:00:00 2001 From: Ben Dyer Date: Fri, 21 Aug 2015 20:35:59 +1000 Subject: [PATCH 08/15] Uncrustified --- libuavcan/src/marshal/uc_float_spec.cpp | 106 +++++++++++++++--------- 1 file changed, 66 insertions(+), 40 deletions(-) diff --git a/libuavcan/src/marshal/uc_float_spec.cpp b/libuavcan/src/marshal/uc_float_spec.cpp index 6ca25b3604..5a13ad3973 100644 --- a/libuavcan/src/marshal/uc_float_spec.cpp +++ b/libuavcan/src/marshal/uc_float_spec.cpp @@ -14,10 +14,15 @@ namespace uavcan uint16_t IEEE754Converter::nativeNonIeeeToHalf(float value) { /** - https://github.com/numpy/numpy/blob/master/numpy/core/src/npymath/halffloat.c - BSD license - */ - union { float val; uint32_t valbits; } conv; + https://github.com/numpy/numpy/blob/master/numpy/core/src/npymath/halffloat.c + BSD license + */ + union + { + float val; + uint32_t valbits; + } conv; + uint32_t f_exp, f_sig; uint16_t h_sgn, h_exp, h_sig; @@ -27,30 +32,39 @@ uint16_t IEEE754Converter::nativeNonIeeeToHalf(float value) f_exp = (conv.valbits & 0x7F800000U); /* Exponent overflow/NaN converts to signed inf/NaN */ - if (f_exp >= 0x47800000U) { - if (f_exp == 0x7F800000U) { + if (f_exp >= 0x47800000U) + { + if (f_exp == 0x7F800000U) + { /* Inf or NaN */ f_sig = (conv.valbits & 0x007FFFFFU); - if (f_sig != 0) { + if (f_sig != 0) + { /* NaN - propagate the flag in the significand... */ return uint16_t(h_sgn | 0x7FFFU); - } else { + } + else + { /* signed inf */ return uint16_t(h_sgn + 0x7C00U); } - } else { + } + else + { /* overflow to signed inf */ return uint16_t(h_sgn + 0x7C00U); } } /* Exponent underflow converts to a subnormal half or signed zero */ - if (f_exp <= 0x38000000U) { + if (f_exp <= 0x38000000U) + { /** * Signed zeros, subnormal floats, and floats with small * exponents all convert to signed zero halfs. */ - if (f_exp < 0x33000000U) { + if (f_exp < 0x33000000U) + { return h_sgn; } @@ -92,44 +106,56 @@ uint16_t IEEE754Converter::nativeNonIeeeToHalf(float value) float IEEE754Converter::halfToNativeNonIeee(uint16_t value) { /** - https://github.com/numpy/numpy/blob/master/numpy/core/src/npymath/halffloat.c - BSD license - */ - union { float ret; uint32_t retbits; } conv; + https://github.com/numpy/numpy/blob/master/numpy/core/src/npymath/halffloat.c + BSD license + */ + union + { + float ret; + uint32_t retbits; + } conv; uint16_t h_exp, h_sig; uint32_t f_sgn, f_exp, f_sig; h_exp = value & 0x7C00U; f_sgn = uint32_t(value & 0x8000U) << 16; - switch (h_exp) { - case 0x0000U: /* 0 or subnormal */ - h_sig = (value & 0x03FFU); - if (h_sig == 0) { - /* Signed zero */ - conv.retbits = f_sgn; - } else { - /* Subnormal */ + switch (h_exp) + { + case 0x0000U: /* 0 or subnormal */ + { + h_sig = (value & 0x03FFU); + if (h_sig == 0) + { + /* Signed zero */ + conv.retbits = f_sgn; + } + else + { + /* Subnormal */ + h_sig = uint16_t(h_sig << 1); + while ((h_sig & 0x0400U) == 0) + { h_sig = uint16_t(h_sig << 1); - while ((h_sig & 0x0400U) == 0) { - h_sig = uint16_t(h_sig << 1); - h_exp++; - } - f_exp = uint32_t(127 - 15 - h_exp) << 23; - f_sig = uint32_t(h_sig & 0x03FFU) << 13; - conv.retbits = f_sgn + f_exp + f_sig; + h_exp++; } - break; - case 0x7C00U: /* inf or NaN */ - /* All-ones exponent and a copy of the significand */ - conv.retbits = f_sgn + 0x7F800000U + (uint32_t(value & 0x03FFU) << 13); - break; - default: /* normalized */ - /* Just need to adjust the exponent and shift */ - conv.retbits = f_sgn + ((uint32_t(value & 0x7FFFU) + 0x1C000U) << 13); - break; + f_exp = uint32_t(127 - 15 - h_exp) << 23; + f_sig = uint32_t(h_sig & 0x03FFU) << 13; + conv.retbits = f_sgn + f_exp + f_sig; + } + break; + } + case 0x7C00U: /* inf or NaN */ + { /* All-ones exponent and a copy of the significand */ + conv.retbits = f_sgn + 0x7F800000U + (uint32_t(value & 0x03FFU) << 13); + break; + } + default: /* normalized */ + { /* Just need to adjust the exponent and shift */ + conv.retbits = f_sgn + ((uint32_t(value & 0x7FFFU) + 0x1C000U) << 13); + break; + } } return conv.ret; } - } From ec1210dfece2ae17ff53cddf860df4005d891152 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Fri, 21 Aug 2015 14:43:37 +0300 Subject: [PATCH 09/15] Fixed doxygen comments --- libuavcan/src/marshal/uc_float_spec.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libuavcan/src/marshal/uc_float_spec.cpp b/libuavcan/src/marshal/uc_float_spec.cpp index 5a13ad3973..233de0ec84 100644 --- a/libuavcan/src/marshal/uc_float_spec.cpp +++ b/libuavcan/src/marshal/uc_float_spec.cpp @@ -8,14 +8,14 @@ namespace uavcan { -/** +/* * IEEE754Converter */ uint16_t IEEE754Converter::nativeNonIeeeToHalf(float value) { - /** - https://github.com/numpy/numpy/blob/master/numpy/core/src/npymath/halffloat.c - BSD license + /* + * https://github.com/numpy/numpy/blob/master/numpy/core/src/npymath/halffloat.c + * BSD license */ union { @@ -59,7 +59,7 @@ uint16_t IEEE754Converter::nativeNonIeeeToHalf(float value) /* Exponent underflow converts to a subnormal half or signed zero */ if (f_exp <= 0x38000000U) { - /** + /* * Signed zeros, subnormal floats, and floats with small * exponents all convert to signed zero halfs. */ @@ -77,7 +77,7 @@ uint16_t IEEE754Converter::nativeNonIeeeToHalf(float value) h_sig = uint16_t(f_sig >> 13); - /** + /* * If the rounding causes a bit to spill into h_exp, it will * increment h_exp from zero to one and h_sig will be zero. * This is the correct result. @@ -94,7 +94,7 @@ uint16_t IEEE754Converter::nativeNonIeeeToHalf(float value) h_sig = uint16_t(f_sig >> 13); - /** + /* * If the rounding causes a bit to spill into h_exp, it will * increment h_exp by one and h_sig will be zero. This is the * correct result. h_exp may increment to 15, at greatest, in @@ -105,9 +105,9 @@ uint16_t IEEE754Converter::nativeNonIeeeToHalf(float value) float IEEE754Converter::halfToNativeNonIeee(uint16_t value) { - /** - https://github.com/numpy/numpy/blob/master/numpy/core/src/npymath/halffloat.c - BSD license + /* + * https://github.com/numpy/numpy/blob/master/numpy/core/src/npymath/halffloat.c + * BSD license */ union { From 9c185b3ddf2b362e5f9f8e76005e3945ec3cd2a0 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Fri, 21 Aug 2015 14:50:29 +0300 Subject: [PATCH 10/15] float16 converter is explicitly declared non-compatible with non-IEEE754 --- libuavcan/include/uavcan/marshal/float_spec.hpp | 11 ++++++----- libuavcan/src/marshal/uc_float_spec.cpp | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/libuavcan/include/uavcan/marshal/float_spec.hpp b/libuavcan/include/uavcan/marshal/float_spec.hpp index b77328f44a..1e8627c052 100644 --- a/libuavcan/include/uavcan/marshal/float_spec.hpp +++ b/libuavcan/include/uavcan/marshal/float_spec.hpp @@ -36,9 +36,10 @@ struct NativeFloatSelector class UAVCAN_EXPORT IEEE754Converter { - // TODO: Non-IEEE float support for float32 and float64 - static uint16_t nativeNonIeeeToHalf(float value); - static float halfToNativeNonIeee(uint16_t value); + // TODO: Non-IEEE float support + + static uint16_t nativeIeeeToHalf(float value); + static float halfToNativeIeee(uint16_t value); IEEE754Converter(); @@ -80,13 +81,13 @@ template <> inline typename IntegerSpec<16, SignednessUnsigned, CastModeTruncate>::StorageType IEEE754Converter::toIeee<16>(typename NativeFloatSelector<16>::Type value) { - return nativeNonIeeeToHalf(value); + return nativeIeeeToHalf(value); } template <> inline typename NativeFloatSelector<16>::Type IEEE754Converter::toNative<16>(typename IntegerSpec<16, SignednessUnsigned, CastModeTruncate>::StorageType value) { - return halfToNativeNonIeee(value); + return halfToNativeIeee(value); } diff --git a/libuavcan/src/marshal/uc_float_spec.cpp b/libuavcan/src/marshal/uc_float_spec.cpp index 233de0ec84..1e2c68bd9d 100644 --- a/libuavcan/src/marshal/uc_float_spec.cpp +++ b/libuavcan/src/marshal/uc_float_spec.cpp @@ -11,7 +11,7 @@ namespace uavcan /* * IEEE754Converter */ -uint16_t IEEE754Converter::nativeNonIeeeToHalf(float value) +uint16_t IEEE754Converter::nativeIeeeToHalf(float value) { /* * https://github.com/numpy/numpy/blob/master/numpy/core/src/npymath/halffloat.c @@ -103,7 +103,7 @@ uint16_t IEEE754Converter::nativeNonIeeeToHalf(float value) return uint16_t(h_sgn + h_exp + h_sig); } -float IEEE754Converter::halfToNativeNonIeee(uint16_t value) +float IEEE754Converter::halfToNativeIeee(uint16_t value) { /* * https://github.com/numpy/numpy/blob/master/numpy/core/src/npymath/halffloat.c From aeb8beadc13ae32da55e65d9e3b7c5564152e856 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Fri, 21 Aug 2015 15:00:50 +0300 Subject: [PATCH 11/15] IEEE754Converter::enforceIeee<>() --- libuavcan/include/uavcan/marshal/float_spec.hpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libuavcan/include/uavcan/marshal/float_spec.hpp b/libuavcan/include/uavcan/marshal/float_spec.hpp index 1e8627c052..aa2604c9d5 100644 --- a/libuavcan/include/uavcan/marshal/float_spec.hpp +++ b/libuavcan/include/uavcan/marshal/float_spec.hpp @@ -43,6 +43,16 @@ class UAVCAN_EXPORT IEEE754Converter IEEE754Converter(); + template + static void enforceIeee() + { + /* + * Some compilers may have is_iec559 to be defined false despite the fact that IEEE754 is supported. + * An acceptable workaround would be to put an #ifdef here. + */ + StaticAssert::Type>::is_iec559>::check(); + } + public: #if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 /// UAVCAN requires rounding to nearest for all float conversions @@ -53,6 +63,7 @@ public: static typename IntegerSpec::StorageType toIeee(typename NativeFloatSelector::Type value) { + enforceIeee(); union { typename IntegerSpec::StorageType i; @@ -67,6 +78,7 @@ public: static typename NativeFloatSelector::Type toNative(typename IntegerSpec::StorageType value) { + enforceIeee(); union { typename IntegerSpec::StorageType i; From a7fe27a365ddcf74391d959c238cfb580cc62006 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Fri, 21 Aug 2015 15:03:09 +0300 Subject: [PATCH 12/15] Ninja fix --- libuavcan/include/uavcan/marshal/float_spec.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libuavcan/include/uavcan/marshal/float_spec.hpp b/libuavcan/include/uavcan/marshal/float_spec.hpp index aa2604c9d5..ef3e93b884 100644 --- a/libuavcan/include/uavcan/marshal/float_spec.hpp +++ b/libuavcan/include/uavcan/marshal/float_spec.hpp @@ -50,7 +50,9 @@ class UAVCAN_EXPORT IEEE754Converter * Some compilers may have is_iec559 to be defined false despite the fact that IEEE754 is supported. * An acceptable workaround would be to put an #ifdef here. */ +#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 StaticAssert::Type>::is_iec559>::check(); +#endif } public: From 9ca9d941c7d8480f73fb379599e0d5422bf24339 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Sun, 23 Aug 2015 17:54:58 +0300 Subject: [PATCH 13/15] STM32 test updated with autobauding --- .../stm32/test_stm32f107/src/main.cpp | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp b/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp index 784cee33e3..a5481c94a1 100644 --- a/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp +++ b/libuavcan_drivers/stm32/test_stm32f107/src/main.cpp @@ -32,22 +32,26 @@ void ledSet(bool state) palWritePad(GPIO_PORT_LED, GPIO_PIN_LED, state); } -int init() +void init() { - int res = 0; - halInit(); chibios_rt::System::init(); sdStart(&STDOUT_SD, NULL); - res = can.init(1000000); - if (res < 0) + int res = 0; + do { - goto leave; - } + ::sleep(1); + ::lowsyslog("CAN auto bit rate detection...\n"); -leave: - return res; + std::uint32_t bitrate = 0; + res = can.init([]() { ::usleep(can.getRecommendedListeningDelay().toUSec()); }, bitrate); + if (res >= 0) + { + ::lowsyslog("CAN inited at %u bps\n", unsigned(bitrate)); + } + } + while (res < 0); } #if __GNUC__ @@ -55,7 +59,7 @@ __attribute__((noreturn)) #endif void die(int status) { - lowsyslog("Now I am dead x_x %i\n", status); + lowsyslog("Initialization failure %i\n", status); while (1) { ledSet(false); @@ -166,11 +170,7 @@ public: int main() { - const int init_res = app::init(); - if (init_res != 0) - { - app::die(init_res); - } + app::init(); lowsyslog("Starting the UAVCAN thread\n"); app::uavcan_node_thread.start(LOWPRIO); From 37bd23e4faad0f4318e17186ddf640df97157502 Mon Sep 17 00:00:00 2001 From: Ben Dyer Date: Mon, 24 Aug 2015 20:07:03 +1000 Subject: [PATCH 14/15] Replace float<->half implementation with public domain code --- libuavcan/include/uavcan/build_config.hpp | 8 + libuavcan/src/marshal/uc_float_spec.cpp | 178 +++++++--------------- 2 files changed, 59 insertions(+), 127 deletions(-) diff --git a/libuavcan/include/uavcan/build_config.hpp b/libuavcan/include/uavcan/build_config.hpp index 6b8768c3e5..81bde86938 100644 --- a/libuavcan/include/uavcan/build_config.hpp +++ b/libuavcan/include/uavcan/build_config.hpp @@ -136,6 +136,14 @@ # define UAVCAN_USE_EXTERNAL_SNPRINTF 0 #endif +/** + * Allows the user's application to provide a custom implementation of IEEE754Converter::nativeIeeeToHalf and + * IEEE754Converter::halfToNativeIeee. + */ +#ifndef UAVCAN_USE_EXTERNAL_FLOAT16_CONVERSION +# define UAVCAN_USE_EXTERNAL_FLOAT16_CONVERSION 0 +#endif + /** * Run time checks. * Resolves to the standard assert() by default. diff --git a/libuavcan/src/marshal/uc_float_spec.cpp b/libuavcan/src/marshal/uc_float_spec.cpp index 1e2c68bd9d..3254768e43 100644 --- a/libuavcan/src/marshal/uc_float_spec.cpp +++ b/libuavcan/src/marshal/uc_float_spec.cpp @@ -6,156 +6,80 @@ #include #include +#if !UAVCAN_USE_EXTERNAL_FLOAT16_CONVERSION namespace uavcan { +typedef union +{ + uint32_t u; + float f; +} fp32; + /* * IEEE754Converter */ uint16_t IEEE754Converter::nativeIeeeToHalf(float value) { /* - * https://github.com/numpy/numpy/blob/master/numpy/core/src/npymath/halffloat.c - * BSD license + * https://gist.github.com/rygorous/2156668 + * Public domain, by Fabian "ryg" Giesen */ - union + const fp32 f32infty = { 255U << 23 }; + const fp32 f16infty = { 31U << 23 }; + const fp32 magic = { 15U << 23 }; + const uint32_t sign_mask = 0x80000000U; + const uint32_t round_mask = ~0xFFFU; + + fp32 in; + uint16_t out; + + in.f = value; + + uint32_t sign = in.u & sign_mask; + in.u ^= sign; + + if (in.u >= f32infty.u) /* Inf or NaN (all exponent bits set) */ { - float val; - uint32_t valbits; - } conv; - - uint32_t f_exp, f_sig; - uint16_t h_sgn, h_exp, h_sig; - - conv.val = value; - - h_sgn = uint16_t((conv.valbits & 0x80000000U) >> 16); - f_exp = (conv.valbits & 0x7F800000U); - - /* Exponent overflow/NaN converts to signed inf/NaN */ - if (f_exp >= 0x47800000U) + /* NaN->sNaN and Inf->Inf */ + out = (in.u > f32infty.u) ? 0x7FFFU : 0x7C00U; + } + else /* (De)normalized number or zero */ { - if (f_exp == 0x7F800000U) + in.u &= round_mask; + in.f *= magic.f; + in.u -= round_mask; + if (in.u > f16infty.u) { - /* Inf or NaN */ - f_sig = (conv.valbits & 0x007FFFFFU); - if (f_sig != 0) - { - /* NaN - propagate the flag in the significand... */ - return uint16_t(h_sgn | 0x7FFFU); - } - else - { - /* signed inf */ - return uint16_t(h_sgn + 0x7C00U); - } - } - else - { - /* overflow to signed inf */ - return uint16_t(h_sgn + 0x7C00U); + in.u = f16infty.u; /* Clamp to signed infinity if overflowed */ } + + out = uint16_t(in.u >> 13); /* Take the bits! */ } - /* Exponent underflow converts to a subnormal half or signed zero */ - if (f_exp <= 0x38000000U) - { - /* - * Signed zeros, subnormal floats, and floats with small - * exponents all convert to signed zero halfs. - */ - if (f_exp < 0x33000000U) - { - return h_sgn; - } + out |= uint16_t(sign >> 16); - /* Make the subnormal significand */ - f_exp >>= 23; - f_sig = (0x00800000U + (conv.valbits & 0x007FFFFFU)); - f_sig >>= (113 - f_exp); - /* Handle rounding by adding 1 to the bit beyond half precision */ - f_sig += 0x00001000U; - - h_sig = uint16_t(f_sig >> 13); - - /* - * If the rounding causes a bit to spill into h_exp, it will - * increment h_exp from zero to one and h_sig will be zero. - * This is the correct result. - */ - return uint16_t(h_sgn + h_sig); - } - - /* Regular case with no overflow or underflow */ - h_exp = uint16_t((f_exp - 0x38000000U) >> 13); - - /* Handle rounding by adding 1 to the bit beyond half precision */ - f_sig = (conv.valbits & 0x007FFFFFU); - f_sig += 0x00001000U; - - h_sig = uint16_t(f_sig >> 13); - - /* - * If the rounding causes a bit to spill into h_exp, it will - * increment h_exp by one and h_sig will be zero. This is the - * correct result. h_exp may increment to 15, at greatest, in - * which case the result overflows to a signed inf. - */ - return uint16_t(h_sgn + h_exp + h_sig); + return out; } float IEEE754Converter::halfToNativeIeee(uint16_t value) { /* - * https://github.com/numpy/numpy/blob/master/numpy/core/src/npymath/halffloat.c - * BSD license + * https://gist.github.com/rygorous/2144712 + * Public domain, by Fabian "ryg" Giesen */ - union - { - float ret; - uint32_t retbits; - } conv; + const fp32 magic = { (254U - 15U) << 23 }; + const fp32 was_infnan = { (127U + 16U) << 23 }; + fp32 out; - uint16_t h_exp, h_sig; - uint32_t f_sgn, f_exp, f_sig; + out.u = (value & 0x7FFFU) << 13; /* exponent/mantissa bits */ + out.f *= magic.f; /* exponent adjust */ + if (out.f >= was_infnan.f) /* make sure Inf/NaN survive */ + { + out.u |= 255U << 23; + } + out.u |= (value & 0x8000U) << 16; /* sign bit */ - h_exp = value & 0x7C00U; - f_sgn = uint32_t(value & 0x8000U) << 16; - switch (h_exp) - { - case 0x0000U: /* 0 or subnormal */ - { - h_sig = (value & 0x03FFU); - if (h_sig == 0) - { - /* Signed zero */ - conv.retbits = f_sgn; - } - else - { - /* Subnormal */ - h_sig = uint16_t(h_sig << 1); - while ((h_sig & 0x0400U) == 0) - { - h_sig = uint16_t(h_sig << 1); - h_exp++; - } - f_exp = uint32_t(127 - 15 - h_exp) << 23; - f_sig = uint32_t(h_sig & 0x03FFU) << 13; - conv.retbits = f_sgn + f_exp + f_sig; - } - break; - } - case 0x7C00U: /* inf or NaN */ - { /* All-ones exponent and a copy of the significand */ - conv.retbits = f_sgn + 0x7F800000U + (uint32_t(value & 0x03FFU) << 13); - break; - } - default: /* normalized */ - { /* Just need to adjust the exponent and shift */ - conv.retbits = f_sgn + ((uint32_t(value & 0x7FFFU) + 0x1C000U) << 13); - break; - } - } - return conv.ret; + return out.f; } } +#endif // !UAVCAN_USE_EXTERNAL_FLOAT16_CONVERSION From 4ecdfd844e421d6f9d68f108f9207d1c180e8eff Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Mon, 24 Aug 2015 14:06:56 +0300 Subject: [PATCH 15/15] Minor style fix in IEEE754Converter; no changes to the logic --- libuavcan/src/marshal/uc_float_spec.cpp | 26 ++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/libuavcan/src/marshal/uc_float_spec.cpp b/libuavcan/src/marshal/uc_float_spec.cpp index 3254768e43..13a1a7ac62 100644 --- a/libuavcan/src/marshal/uc_float_spec.cpp +++ b/libuavcan/src/marshal/uc_float_spec.cpp @@ -6,14 +6,16 @@ #include #include -#if !UAVCAN_USE_EXTERNAL_FLOAT16_CONVERSION namespace uavcan { -typedef union + +#if !UAVCAN_USE_EXTERNAL_FLOAT16_CONVERSION + +union Fp32 { uint32_t u; float f; -} fp32; +}; /* * IEEE754Converter @@ -24,13 +26,13 @@ uint16_t IEEE754Converter::nativeIeeeToHalf(float value) * https://gist.github.com/rygorous/2156668 * Public domain, by Fabian "ryg" Giesen */ - const fp32 f32infty = { 255U << 23 }; - const fp32 f16infty = { 31U << 23 }; - const fp32 magic = { 15U << 23 }; + const Fp32 f32infty = { 255U << 23 }; + const Fp32 f16infty = { 31U << 23 }; + const Fp32 magic = { 15U << 23 }; const uint32_t sign_mask = 0x80000000U; const uint32_t round_mask = ~0xFFFU; - fp32 in; + Fp32 in; uint16_t out; in.f = value; @@ -67,9 +69,9 @@ float IEEE754Converter::halfToNativeIeee(uint16_t value) * https://gist.github.com/rygorous/2144712 * Public domain, by Fabian "ryg" Giesen */ - const fp32 magic = { (254U - 15U) << 23 }; - const fp32 was_infnan = { (127U + 16U) << 23 }; - fp32 out; + const Fp32 magic = { (254U - 15U) << 23 }; + const Fp32 was_infnan = { (127U + 16U) << 23 }; + Fp32 out; out.u = (value & 0x7FFFU) << 13; /* exponent/mantissa bits */ out.f *= magic.f; /* exponent adjust */ @@ -81,5 +83,7 @@ float IEEE754Converter::halfToNativeIeee(uint16_t value) return out.f; } -} + #endif // !UAVCAN_USE_EXTERNAL_FLOAT16_CONVERSION + +}