WIP: ATmodem (renamed after BG95_base) and sequencer

This commit is contained in:
2021-09-27 17:04:46 +03:00
parent ca38dfa2f1
commit f7c904e9c2
5 changed files with 205 additions and 106 deletions
@@ -1,7 +1,7 @@
/*!
* \file cont/BG95_base.h
* \file drv/ATmodem.h
* \brief
* BG95 driver functionality as CRTP base class
* ATmodem driver functionality as CRTP base class
*
* \copyright Copyright (C) 2021 Christos Choutouridis <christos@choutouridis.net>
*
@@ -28,8 +28,8 @@
* </dd></dl>
*/
#ifndef TBX_DRV_BG95_base_H_
#define TBX_DRV_BG95_base_H_
#ifndef TBX_DRV_ATmodem_H_
#define TBX_DRV_ATmodem_H_
#define __cplusplus 201703L
@@ -37,7 +37,7 @@
#include <core/crtp.h>
#include <cont/equeue.h>
#include <cont/range.h>
#include <utils/sequencer.h>
#include <com/sequencer.h>
#include <cstring>
#include <cstdlib>
@@ -63,12 +63,12 @@ namespace tbx {
* \tparam Delimiter
*/
template<typename Impl_t, size_t N, char Delimiter ='\n'>
class BG95_base
: public sequencer<BG95_base<Impl_t, N, Delimiter>, char, N>{
class ATmodem
: public sequencer<ATmodem<Impl_t, N, Delimiter>, char, N>{
_CRTP_IMPL(Impl_t);
// local type dispatch
using base_type = sequencer<BG95_base, char, N>;
using base_type = sequencer<ATmodem, char, N>;
//! \name Public types
//! @{
@@ -106,10 +106,10 @@ class BG95_base
//!@{
protected:
//!< \brief A default constructor from derived only
BG95_base() = default;
~BG95_base () = default; //!< \brief Allow destructor from derived only
BG95_base(const BG95_base&) = delete; //!< No copies
BG95_base& operator= (const BG95_base&) = delete; //!< No copy assignments
ATmodem() noexcept = default;
~ATmodem () = default; //!< \brief Allow destructor from derived only
ATmodem(const ATmodem&) = delete; //!< No copies
ATmodem& operator= (const ATmodem&) = delete; //!< No copy assignments
//!@}
//! \name Sequencer interface requirements
@@ -139,6 +139,28 @@ class BG95_base
//! \name Private functionality
//! @{
private:
template <typename... Ts>
struct typelist {
using type = typelist; //!< act as identity
};
template <typename L>
struct front_impl {
using type = void;
};
template <typename Head, typename... Tail>
struct front_impl<typelist<Head, Tail...>> {
using type = Head;
};
//! Return the first element in \c meta::typelist \c List.
//!
//! Complexity \f$ O(1) \f$.
template <typename List>
using front = typename front_impl<List>::type;
template<typename T>
void extract (const char* str, T* value) {
static_assert (
@@ -154,6 +176,9 @@ class BG95_base
std::strcpy(value, str);
}
}
void extract (const char* str, void* value) {
(void)*str; (void)value;
}
template <char Marker = '%'>
std::pair<size_t, bool> parse (const char* expected, const string_view buffer, char* token) {
@@ -253,29 +278,45 @@ class BG95_base
* if (done && status == 1)
* std::cout << "Connected to home network\n"
* \endcode
* element_type (&arr)[N]
*/
template <typename T, char Marker = '%'>
bool command (const string_view cmd, const string_view expected, T* value, clock_t timeout =0) {
char buffer[N];
char token[N];
template<char Marker = '%', typename ...Ts>
bool command (const string_view cmd, const string_view expected, clock_t timeout, Ts* ...values) {
transmit(cmd.data()); // send command
constexpr size_t Nr = sizeof...(Ts);
front<typelist<Ts...>>* vargs[Nr] = {values...};
if constexpr (Nr == 0) { (void)vargs; }
char buffer[N], token[N];
size_t v =0;
transmit(cmd.data()); // send command
for (auto ex = expected.begin() ; ex != expected.end() ; ) {
clock_t mark = clock(); // load the answer with timeout
clock_t mark = clock(); // load the answer with timeout
size_t sz =0;
do {
sz = receive(buffer);
if ((timeout != 0 )&& ((clock() - mark) >= timeout))
return false;
} while (!sz);
bool redo = false; do {
do {
sz = receive(buffer);
if ((timeout != 0 )&& ((clock() - mark) >= timeout))
return false;
} while (!sz);
for (size_t i=0 ; i<sz ; ) { // parse buffer based on expected
auto [step, marker] = parse<Marker> (ex++, {&buffer[i], sz-i}, token);
if (!step) return false;
if (marker) extract(token, value);
i += step;
}
redo = false; // have faith to parse successfully
for (size_t i=0 ; i<sz ; ) { // parse buffer based on expected
auto [step, marker] = parse<Marker> (ex++, {&buffer[i], sz-i}, token);
if (!step) {
redo = true; // fail to parse, reload and retry
break;
}
if constexpr (Nr > 0) {
if (marker && v< Nr)
extract(token, vargs[v++]);
}
i += step;
}
} while (redo);
}
return true;
}
@@ -324,4 +365,4 @@ class BG95_base
} // namespace tbx;
#endif /* TBX_DRV_BG95_base_H_ */
#endif /* #ifndef TBX_DRV_ATmodem_H_ */