DEV: A print interface and a timer_delay added
This commit is contained in:
parent
ca944cb062
commit
d16242ecbc
@ -38,8 +38,8 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
|
@ -38,6 +38,8 @@
|
|||||||
#include <cont/equeue.h>
|
#include <cont/equeue.h>
|
||||||
|
|
||||||
#include <utils/shared.h>
|
#include <utils/shared.h>
|
||||||
|
#include <utils/print.h>
|
||||||
|
#include <utils/timer_delay.h>
|
||||||
|
|
||||||
#include <drv/cli_device.h>
|
#include <drv/cli_device.h>
|
||||||
#include <drv/gpio.h>
|
#include <drv/gpio.h>
|
||||||
|
314
include/utils/print.h
Normal file
314
include/utils/print.h
Normal file
@ -0,0 +1,314 @@
|
|||||||
|
/*!
|
||||||
|
* \file utils/print.h
|
||||||
|
* \brief
|
||||||
|
* A CRTP base class to provide print interface
|
||||||
|
*
|
||||||
|
* \copyright Copyright (C) 2021 Christos Choutouridis <christos@choutouridis.net>
|
||||||
|
*
|
||||||
|
* <dl class=\"section copyright\"><dt>License</dt><dd>
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* </dd></dl>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TBX_UTILS_PRINT_H_
|
||||||
|
#define TBX_UTILS_PRINT_H_
|
||||||
|
|
||||||
|
#include <core/core.h>
|
||||||
|
#include <core/crtp.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <math.h>
|
||||||
|
#include <string_view>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
namespace tbx {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \class Print
|
||||||
|
* \brief
|
||||||
|
* A CRTP print interface
|
||||||
|
*
|
||||||
|
* Requirements:
|
||||||
|
* - size_t write_impl(const Char_t* buffer, size_t size) : Return the number of \c Char_t written
|
||||||
|
* - size_t write_(const Char_t ch) : Return the number of \c Char_t written (normally one).
|
||||||
|
*
|
||||||
|
* \tparam Impl_t The derived type
|
||||||
|
* \tparam Char_t The char type to use
|
||||||
|
*/
|
||||||
|
template <typename Impl_t, typename Char_t>
|
||||||
|
class Print {
|
||||||
|
_CRTP_IMPL(Impl_t);
|
||||||
|
|
||||||
|
public:
|
||||||
|
using value_type = Char_t;
|
||||||
|
using pointer_type = Char_t*;
|
||||||
|
using iterator_type = Char_t*;
|
||||||
|
using const_iterator_type = const Char_t*;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using size_type = size_t;
|
||||||
|
using str_view_t = std::basic_string_view<Char_t>;
|
||||||
|
|
||||||
|
//! Enumerator for number base formating
|
||||||
|
enum class Base {
|
||||||
|
BIN =2, OCT =8, DEC =10, HEX =16
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
//! \name CRTP requirements
|
||||||
|
//! @{
|
||||||
|
size_t write_(const Char_t* buffer, size_t size) {
|
||||||
|
return impl().write_impl(buffer, size);
|
||||||
|
}
|
||||||
|
size_t write_(const Char_t ch) {
|
||||||
|
return impl().write_impl(ch);
|
||||||
|
}
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Print() noexcept = default; //!< Construct from derived only
|
||||||
|
|
||||||
|
private:
|
||||||
|
//! Helper tool to convert strong enums to their underlying type
|
||||||
|
template <typename E>
|
||||||
|
constexpr typename std::underlying_type_t<E> value(E e) noexcept {
|
||||||
|
return static_cast<typename std::underlying_type_t<E>>(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t print_unsigned(unsigned long n, Base base); // integer conversion base tool
|
||||||
|
size_t print_double(double number, uint8_t digits); // double conversion base tool
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*!
|
||||||
|
* \brief
|
||||||
|
* Prints a string view
|
||||||
|
* \param str The string view to print
|
||||||
|
* \return The number of printed \c Char_t
|
||||||
|
*/
|
||||||
|
size_t print(const str_view_t str) {
|
||||||
|
return write_(str.data(), str.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief
|
||||||
|
* Prints a string
|
||||||
|
* \param str Pointer to string to print
|
||||||
|
* \return The number of printed \c Char_t
|
||||||
|
*/
|
||||||
|
size_t print(const Char_t* str) {
|
||||||
|
if (str == nullptr)
|
||||||
|
return 0;
|
||||||
|
return write_(str, std::strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief
|
||||||
|
* Prints a buffer of size \c size. If there is a null termination
|
||||||
|
* before the end of the buffer, prints up to termination.
|
||||||
|
*
|
||||||
|
* \param str Pointer to string buffer to print
|
||||||
|
* \param size The size of buffer
|
||||||
|
* \return The number of printed \c Char_t
|
||||||
|
*/
|
||||||
|
size_t print(const Char_t* str, size_t size) {
|
||||||
|
if (str == nullptr)
|
||||||
|
return 0;
|
||||||
|
return write_(str, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief
|
||||||
|
* Prints a \c Char_t
|
||||||
|
* \param ch The Char_t to print
|
||||||
|
* \return The number of printed \c Char_t
|
||||||
|
*/
|
||||||
|
size_t print(Char_t ch) {
|
||||||
|
return write_ (ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief
|
||||||
|
* Convert and print a long.
|
||||||
|
* \param n The number to print
|
||||||
|
* \param base The number base to use for conversion.
|
||||||
|
* \return The number of printed \c Char_t
|
||||||
|
*/
|
||||||
|
size_t print(long n, Base base =Base::DEC) {
|
||||||
|
size_t cnt =0;
|
||||||
|
if (n < 0) {
|
||||||
|
n = -n;
|
||||||
|
cnt = write_ ('-');
|
||||||
|
}
|
||||||
|
return cnt + print_unsigned((unsigned long)n, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief
|
||||||
|
* Convert and print an int.
|
||||||
|
* \param n The number to print
|
||||||
|
* \param base The number base to use for conversion.
|
||||||
|
* \return The number of printed \c Char_t
|
||||||
|
*/
|
||||||
|
size_t print(int n, Base base= Base::DEC) {
|
||||||
|
return print ((long)n, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief
|
||||||
|
* Convert and print an unsigned long.
|
||||||
|
* \param n The number to print
|
||||||
|
* \param base The number base to use for conversion.
|
||||||
|
* \return The number of printed \c Char_t
|
||||||
|
*/
|
||||||
|
size_t print(unsigned long n, Base base= Base::DEC) {
|
||||||
|
return print_unsigned ((unsigned long)n, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief
|
||||||
|
* Convert and print an unsigned int.
|
||||||
|
* \param n The number to print
|
||||||
|
* \param base The number base to use for conversion.
|
||||||
|
* \return The number of printed \c Char_t
|
||||||
|
*/
|
||||||
|
size_t print(unsigned int n, Base base= Base::DEC) {
|
||||||
|
return print_unsigned ((unsigned long)n, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief
|
||||||
|
* Convert and print adouble
|
||||||
|
* \param n The number to print
|
||||||
|
* \param digits The number of decimal digits to print
|
||||||
|
* \return The number of printed \c Char_t
|
||||||
|
*/
|
||||||
|
size_t print(double n, uint8_t digits = 2) {
|
||||||
|
return print_double (n, digits);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief
|
||||||
|
* Perfect forwarder to print functionality with a new line termination
|
||||||
|
* \tparam Ts The types of parameters
|
||||||
|
* \param args The arguments to pass
|
||||||
|
* \return The number of printed \c Char_t
|
||||||
|
*/
|
||||||
|
template <typename ...Ts>
|
||||||
|
size_t println(Ts&& ...args) {
|
||||||
|
size_t r = print (std::forward<Ts>(args)...);
|
||||||
|
r += write_ ('\n');
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief
|
||||||
|
* Converts and prints an unsigned long
|
||||||
|
*
|
||||||
|
* \tparam Impl_t The derived type
|
||||||
|
* \tparam Char_t The char type to use
|
||||||
|
*
|
||||||
|
* \param n The number to print
|
||||||
|
* \param base The number base to use
|
||||||
|
* \return The number of printed \c Char_t
|
||||||
|
*/
|
||||||
|
template <typename Impl_t, typename Char_t>
|
||||||
|
size_t Print<Impl_t, Char_t>::print_unsigned(unsigned long n, Base base) {
|
||||||
|
Char_t buf[8 *sizeof(Char_t) * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
|
||||||
|
Char_t *str = &buf[sizeof(buf) - 1];
|
||||||
|
|
||||||
|
*str = '\0';
|
||||||
|
|
||||||
|
do {
|
||||||
|
Char_t c = n % value(base);
|
||||||
|
n /= value(base);
|
||||||
|
|
||||||
|
*--str = c < 10 ? c + '0' : c + 'A' - 10;
|
||||||
|
} while(n);
|
||||||
|
|
||||||
|
return write_(str, std::strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief
|
||||||
|
* Converts and prints a double
|
||||||
|
*
|
||||||
|
* \note
|
||||||
|
* Internally, this implementation uses a long to store the integer part of the number.
|
||||||
|
* Thus overflows for numbers bigger than std::numeric_limits<long>::max() / min().
|
||||||
|
* For these numbers it prints "ovf" instead.
|
||||||
|
*
|
||||||
|
* \tparam Impl_t The derived type
|
||||||
|
* \tparam Char_t The char type to use
|
||||||
|
*
|
||||||
|
* \param n The number to print
|
||||||
|
* \param digits The number of decimal digits to print
|
||||||
|
* \return The number of printed \c Char_t
|
||||||
|
*/
|
||||||
|
template <typename Impl_t, typename Char_t>
|
||||||
|
size_t Print<Impl_t, Char_t>::print_double(double number, uint8_t digits) {
|
||||||
|
size_t n = 0;
|
||||||
|
|
||||||
|
if (std::isnan(number)) return print("nan");
|
||||||
|
if (std::isinf(number)) return print("inf");
|
||||||
|
if (number > (double)std::numeric_limits<long>::max())
|
||||||
|
return print ("ovf");
|
||||||
|
if (number < (double)std::numeric_limits<long>::min())
|
||||||
|
return print ("-ovf");
|
||||||
|
|
||||||
|
// Handle negative numbers
|
||||||
|
if (number < 0.0) {
|
||||||
|
n += write_ ('-');
|
||||||
|
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;
|
||||||
|
n += print(int_part);
|
||||||
|
|
||||||
|
// Print the decimal point, but only if there are digits beyond
|
||||||
|
if (digits > 0) {
|
||||||
|
n += print('.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract digits from the remainder one at a time
|
||||||
|
while (digits-- > 0) {
|
||||||
|
remainder *= 10.0;
|
||||||
|
unsigned int toPrint = (unsigned int)(remainder);
|
||||||
|
n += print(toPrint);
|
||||||
|
remainder -= toPrint;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif /* TBX_UTILS_PRINT_H_ */
|
333
include/utils/timer_delay.h
Normal file
333
include/utils/timer_delay.h
Normal file
@ -0,0 +1,333 @@
|
|||||||
|
/*!
|
||||||
|
* \file utils/timer_delay.h
|
||||||
|
* \brief
|
||||||
|
* A CRTP timer delay utility
|
||||||
|
*
|
||||||
|
* \copyright Copyright (C) 2021 Christos Choutouridis <christos@choutouridis.net>
|
||||||
|
*
|
||||||
|
* <dl class=\"section copyright\"><dt>License</dt><dd>
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
* </dd></dl>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TBX_UTILS_TIMER_DELAY_H_
|
||||||
|
#define TBX_UTILS_TIMER_DELAY_H_
|
||||||
|
|
||||||
|
#include <core/core.h>
|
||||||
|
#include <core/crtp.h>
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace tbx {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \class timer_delay
|
||||||
|
* \brief
|
||||||
|
* A CRTP hw timer based, delay implementation.
|
||||||
|
*
|
||||||
|
* CRTP requirements:
|
||||||
|
* - int set_frequency_impl (size_t freq, Counter_t ticks)
|
||||||
|
* Initialize and start the hw timer with tick frequency \c freq and reload value \c ticks
|
||||||
|
* - volatile Counter_t* get_value_ptr_impl (Counter_t discard)
|
||||||
|
* Return a pointer to hw timer counter value register. The \c discard argument should discarded.
|
||||||
|
*
|
||||||
|
* \tparam Impl_t The derived class
|
||||||
|
* \tparam Counter_t The hw timer's type
|
||||||
|
*/
|
||||||
|
template <typename Impl_t, typename Counter_t>
|
||||||
|
class timer_delay {
|
||||||
|
_CRTP_IMPL(Impl_t);
|
||||||
|
using value_t = volatile Counter_t;
|
||||||
|
using marker_t = std::make_signed_t<std::remove_cv_t<Counter_t>>;
|
||||||
|
|
||||||
|
//! \name CRTP requirements
|
||||||
|
//! @{
|
||||||
|
private:
|
||||||
|
int set_frequency (size_t freq, Counter_t ticks) {
|
||||||
|
return impl().set_frequency_impl(freq, ticks);
|
||||||
|
}
|
||||||
|
volatile Counter_t* get_value_ptr (Counter_t discard = Counter_t{}) {
|
||||||
|
return impl().get_value_ptr_impl (discard);
|
||||||
|
}
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
//! \name Object lifetime
|
||||||
|
//! @{
|
||||||
|
protected:
|
||||||
|
//! \brief
|
||||||
|
//! Create and initialize
|
||||||
|
//! \param freq The required hw timer's frequency
|
||||||
|
//! \param ticks The required timer's reload value
|
||||||
|
timer_delay (size_t freq, Counter_t ticks) {
|
||||||
|
init (freq, ticks);
|
||||||
|
}
|
||||||
|
timer_delay() noexcept = default; //!< Default object is valid, but non-usable
|
||||||
|
timer_delay(const timer_delay&) = delete; //!< No copies
|
||||||
|
timer_delay& operator=(const timer_delay&) = delete; //!< No copies
|
||||||
|
//! \note
|
||||||
|
//! We are not initializing the timer via default ctor, in order to be able to
|
||||||
|
//! declare a timer_delay object globally and initialize it after the call to main().
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
private:
|
||||||
|
//! Period to frequency compile time tool
|
||||||
|
constexpr Counter_t period2freq (double period) noexcept {
|
||||||
|
return (Counter_t)(1 / period);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Return the systems best approximation for ticks per msec
|
||||||
|
* \return The calculated value or zero if no calculation can apply
|
||||||
|
*/
|
||||||
|
Counter_t ticks_per_msec () {
|
||||||
|
Counter_t tck = (Counter_t)(frequency / period2freq(0.001));
|
||||||
|
return (tck <= 1) ? 1 : tck;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Return the systems best approximation for ticks per usec
|
||||||
|
* \return The calculated value or zero if no calculation can apply
|
||||||
|
*/
|
||||||
|
Counter_t ticks_per_usec () {
|
||||||
|
Counter_t tck = (Counter_t)(frequency / period2freq(0.000001));
|
||||||
|
return (tck <= 1) ? 1 : tck;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Return the systems best approximation for ticks per usec
|
||||||
|
* \return The calculated value or zero if no calculation can apply
|
||||||
|
*/
|
||||||
|
Counter_t ticks_per_100nsec () {
|
||||||
|
Counter_t tck = (Counter_t)(frequency / period2freq(0.0000001));
|
||||||
|
return (tck <= 1) ? 1 : tck;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*!
|
||||||
|
* \brief
|
||||||
|
* Initializes both object members and hw timer.
|
||||||
|
*
|
||||||
|
* \param freq The required hw timer's frequency
|
||||||
|
* \param ticks The required timer's reload value
|
||||||
|
* \return
|
||||||
|
*/
|
||||||
|
bool init (size_t freq, Counter_t ticks) {
|
||||||
|
if (set_frequency(freq, ticks))
|
||||||
|
return false;
|
||||||
|
volatile Counter_t* v = get_value_ptr();
|
||||||
|
|
||||||
|
value = (v != nullptr) ? v : value;
|
||||||
|
frequency = freq;
|
||||||
|
max_ticks = ticks;
|
||||||
|
tp1ms = ticks_per_msec();
|
||||||
|
tp1us = ticks_per_usec();
|
||||||
|
tp100ns= ticks_per_100nsec();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief
|
||||||
|
* A code based delay implementation, using hw timer for timing.
|
||||||
|
* This is NOT accurate but it ensures that the time passed is always
|
||||||
|
* more than the requested value.
|
||||||
|
* The delay values are multiplications of 1 msec.
|
||||||
|
* \param msec Time in msec for delay
|
||||||
|
*/
|
||||||
|
void delay_ms (int msec) {
|
||||||
|
marker_t m, m2, m1 = (marker_t)*value;
|
||||||
|
|
||||||
|
msec *= tp1ms;
|
||||||
|
|
||||||
|
// Eat the time difference from msec value.
|
||||||
|
do {
|
||||||
|
m2 = (marker_t)(*value);
|
||||||
|
m = m2 - m1;
|
||||||
|
msec -= (m>=0) ? m : max_ticks + m;
|
||||||
|
m1 = m2;
|
||||||
|
} while (msec>0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief
|
||||||
|
* A code based delay implementation, using hw timer for timing.
|
||||||
|
* This is NOT accurate but it ensures that the time passed is always
|
||||||
|
* more than the requested value.
|
||||||
|
* The delay values are multiplications of 1 usec.
|
||||||
|
* \param usec Time in usec for delay
|
||||||
|
*/
|
||||||
|
void delay_us (int usec) {
|
||||||
|
marker_t m, m2, m1 = (marker_t)*value;
|
||||||
|
|
||||||
|
usec *= tp1us;
|
||||||
|
if ((marker_t)(*value) - m1 > usec) // Very small delays may return here.
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Eat the time difference from usec value.
|
||||||
|
do {
|
||||||
|
m2 = (marker_t)(*value);
|
||||||
|
m = m2 - m1;
|
||||||
|
usec -= (m>=0) ? m : max_ticks + m;
|
||||||
|
m1 = m2;
|
||||||
|
} while (usec>0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief
|
||||||
|
* A code based delay implementation, using hw timer for timing.
|
||||||
|
* This is NOT accurate but it ensures that the time passed is always
|
||||||
|
* more than the requested value.
|
||||||
|
* The delay values are multiplications of 100 nsec.
|
||||||
|
* \param _100nsec Time in 100nsec for delay
|
||||||
|
*/
|
||||||
|
void delay_100ns (int _100nsec) {
|
||||||
|
marker_t m, m2, m1 = (marker_t)*value;
|
||||||
|
|
||||||
|
_100nsec *= tp100ns;
|
||||||
|
if ((marker_t)(*value) - m1 > _100nsec) // Very small delays may return here.
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Eat the time difference from _100nsec value.
|
||||||
|
do {
|
||||||
|
m2 = (marker_t)(*value);
|
||||||
|
m = m2 - m1;
|
||||||
|
_100nsec -= (m>=0) ? m : max_ticks + m;
|
||||||
|
m1 = m2;
|
||||||
|
} while (_100nsec>0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief
|
||||||
|
* A code based polling version delay implementation, using hw timer for timing.
|
||||||
|
* This is NOT accurate but it ensures that the time passed is always
|
||||||
|
* more than the requested value.
|
||||||
|
* The delay values are multiplications of 1 msec.
|
||||||
|
* \param msec Time in msec for delay
|
||||||
|
* \return The status of ongoing delay
|
||||||
|
* \arg false: Delay time has passed
|
||||||
|
* \arg true: Delay is ongoing, keep calling
|
||||||
|
*/
|
||||||
|
bool check_msec (int msec) {
|
||||||
|
static marker_t m1=-1, cnt;
|
||||||
|
marker_t m, m2;
|
||||||
|
|
||||||
|
if (m1 == -1) {
|
||||||
|
m1 = *value;
|
||||||
|
cnt = tp1ms * msec;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eat the time difference from msec value.
|
||||||
|
if (cnt>0) {
|
||||||
|
m2 = (marker_t)(*value);
|
||||||
|
m = m2-m1;
|
||||||
|
cnt -= (m>=0) ? m : max_ticks + m;
|
||||||
|
m1 = m2;
|
||||||
|
return 1; // wait
|
||||||
|
} else {
|
||||||
|
m1 = -1;
|
||||||
|
return 0; // do not wait any more
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief
|
||||||
|
* A code based polling version delay implementation, using hw timer for timing.
|
||||||
|
* This is NOT accurate but it ensures that the time passed is always
|
||||||
|
* more than the requested value.
|
||||||
|
* The delay values are multiplications of 1 usec.
|
||||||
|
* \param usec Time in usec for delay
|
||||||
|
* \return The status of ongoing delay
|
||||||
|
* \arg false: Delay time has passed
|
||||||
|
* \arg true: Delay is ongoing, keep calling
|
||||||
|
*/
|
||||||
|
bool check_usec (int usec) {
|
||||||
|
static marker_t m1=-1, cnt;
|
||||||
|
marker_t m, m2;
|
||||||
|
|
||||||
|
if (m1 == -1) {
|
||||||
|
m1 = *value;
|
||||||
|
cnt = tp1us * usec;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eat the time difference from usec value.
|
||||||
|
if (cnt>0) {
|
||||||
|
m2 = (marker_t)(*value);
|
||||||
|
m = m2-m1;
|
||||||
|
cnt -= (m>=0) ? m : max_ticks + m;
|
||||||
|
m1 = m2;
|
||||||
|
return 1; // wait
|
||||||
|
} else {
|
||||||
|
m1 = -1;
|
||||||
|
return 0; // do not wait any more
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief
|
||||||
|
* A code based polling version delay implementation, using hw timer for timing.
|
||||||
|
* This is NOT accurate but it ensures that the time passed is always
|
||||||
|
* more than the requested value.
|
||||||
|
* The delay values are multiplications of 100 nsec.
|
||||||
|
* \param
|
||||||
|
* _100nsec Time in 100nsec for delay
|
||||||
|
* \return The status of ongoing delay
|
||||||
|
* \arg false: Delay time has passed
|
||||||
|
* \arg true: Delay is ongoing, keep calling
|
||||||
|
*/
|
||||||
|
bool check_100nsec (int _100nsec) {
|
||||||
|
static marker_t m1=-1, cnt;
|
||||||
|
marker_t m, m2;
|
||||||
|
|
||||||
|
if (m1 == -1) {
|
||||||
|
m1 = *value;
|
||||||
|
cnt = tp100ns * _100nsec;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eat the time difference from _100nsec value.
|
||||||
|
if (cnt>0) {
|
||||||
|
m2 = (marker_t)(*value);
|
||||||
|
m = m2-m1;
|
||||||
|
cnt -= (m>=0) ? m : max_ticks + m;
|
||||||
|
m1 = m2;
|
||||||
|
return 1; // wait
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m1 = -1;
|
||||||
|
return 0; // do not wait any more
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr Counter_t zero = 0; //!< A always zero place
|
||||||
|
|
||||||
|
value_t* value {(value_t*)&zero}; //!< Pointer to hw timer's counter register
|
||||||
|
//!< We initialize it to &zero to avoid nullptr dereference
|
||||||
|
size_t frequency{}; //!< The frequency of the timer
|
||||||
|
Counter_t max_ticks{}; //!< The reload value of the timer
|
||||||
|
Counter_t tp1ms{}; //!< ticks per ms temporary variable
|
||||||
|
Counter_t tp1us{}; //!< ticks per us temporary variable
|
||||||
|
Counter_t tp100ns{}; //!< ticks per 100ns temporary variable
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace tbx
|
||||||
|
|
||||||
|
#endif /* TBX_UTILS_TIMER_DELAY_H_ */
|
Loading…
x
Reference in New Issue
Block a user