General Terminology
SDK (TWELITE SDK, MWSDK)
Software Development Kit (SDK)
IEEE802.15.4
A wireless standard used by TWELITE wireless modules. As long as you are using the MWX library, you generally do not need to be concerned with the details of the protocol.
Packet
The smallest unit of transmission in wireless communication. The maximum size varies depending on the communication method and settings, but in MWX’s standard <NWK_SIMPLE> communication, up to 90 bytes can be transmitted in one packet.
Payload
While the literal meaning is “cargo”, it refers to the actual data content included in a wireless packet.
Node
Literally means “point” or “junction”, but in this context it refers to a wireless device within a wireless network.
MWX Library-Specific Terminology
Act
A program created using this library. Refers to either the source code or the running program.
Behavior
A program written in an event-driven style, defined within an Act. Refers to either the source code or the running program.
A behavior is written as a single class definition that encapsulates callbacks from TWENET, events, and interrupt handling. MWX defines three types of behaviors:
- Application Behavior: A user-defined class that describes application logic in an event-driven format.
- Board Behavior: A class that simplifies usage of functions provided by the TWELITE module board.
- Network Behavior: A class that simplifies wireless network procedures.
Behavior names are enclosed in angle brackets < >
. For example, the behavior name for the simple repeater network is <NWK_SIMPLE>
.
Class Object
In this documentation, class objects refer to globally declared objects provided by the library, such as Serial
or Wire
. These class objects can be used immediately or after an initialization procedure.
Class objects that consume a relatively large amount of memory allocate memory during the initialization process according to the provided parameters (via .setup()
or .begin()
methods).
Terminology Related to C++
C++
The C++ programming language.
C++11
A version of the C++ standard. It refers to the C++ standard established in 2011 by ISO. It added significant features compared to the previous C++03 standard. There are newer versions such as C++14 and C++17.
Class
A construct that groups data and procedures related to that data. It is like a structure that also contains procedures to operate on that structure. This is a simplified explanation; please refer to specialized books for deeper understanding.
In C++, the keywords struct
and class
are essentially the same; whichever keyword is used, it defines a class.
struct myhello {
int _i;
void say_hello() { printf("hello %d\n", _i); }
};
If the above class definition were done in C language, it might look like this:
typedef struct _c_myhello {
int _i;
void (*pf_say_hello)(struct _c_myhello *);
} c_myhello;
void say_hello(c_myhello*p) { p->pf_say_hello(); }
void init_c_my_hello(c_myhello*p) {
p->pf_say_hello = say_hello;
}
Wrapper Class
A class that encapsulates existing C language libraries or internal structures, adding C++-specific features to improve usability. In this documentation, you might see descriptions such as “wrapped the ~ structure”.
Method / Member Function
A function defined inside a class and bound to that class.
struct myhello {
int _i;
void say_hello() { printf("hello %d\n", _i); } // Method
};
Object / Instance
An instantiated class (allocated in memory).
void func() {
myhello obj_hello; // obj_hello is an object of class myhello
obj_hello._i = 10;
obj_hello.say_hello();
}
In this documentation, “object” and “instance” are used interchangeably.
Constructor
An initialization procedure called when an object is created.
struct myhello {
int _i;
void say_hello() { printf("hello %d\n", _i); }
myhello(int i = 0) : _i(i) {} // Constructor
};
void my_main() {
myhello helo(10); // Constructor is called here and _i is set to 10
}
Destructor
A procedure paired with the constructor, called when an object is destroyed.
struct myhello {
int _i;
void say_hello() { printf("hello! %d\n", _i); }
myhello(int i = 0) : _i(i) {} // Constructor
~myhello() {
printf("good bye! %d\n", _i);
} // Destructor
};
Abstract Class
In C++, polymorphism is achieved through virtual classes. Specifically, a class with pure virtual functions defined by the virtual
keyword.
struct Base {
virtual void say_hello() = 0;
};
struct DeriveEng : public Base {
void say_hello() { printf("Hello!"); }
};
struct DeriveJpn : public Base {
void say_hello() { printf("Kontiwa!"); }
};
Scope
In C/C++ languages, scope is defined by { }
. Objects created inside this scope are destroyed when exiting the scope, and their destructors are called.
The following example explicitly sets scope. The object helo2
is destroyed and its destructor called when execution reaches line 8.
void my_main() {
myhello helo1(1);
helo1.say_hello();
{
myhello helo2(2);
helo2.say_hello();
}
}
// hello! 1
// hello! 2
// good bye! 2
// good bye! 1
The MWX library uses the following syntax. Here, an object declared inside the condition expression of an if statement (which is not allowed in older C89-style C) is valid only within the {}
block of the if statement.
struct myhello {
int _i;
void say_hello() { printf("hello! %d\n", _i); }
operator bool() { return true; } // Operator for if() condition
myhello(int i = 0) : _i(i) {} // Constructor
~myhello() { printf("good bye! %d\n", _i); } // Destructor
};
// Generator function that creates a myhello object
myhello gen_greeting() { return my_hello(); }
void my_main() {
if (myhello x = gen_greeting()) {
// The myhello object x is valid inside the if block
x.say_hello();
}
// Object x is destroyed when exiting the if block
}
For example, in a dual serial bus, there are procedures for start and end, and the bus is operated by the object only during that time. After the object is created, if the bus connection is appropriate, the true branch of the if statement is executed, and the created object performs bus write or read operations. When the bus read/write operations are finished, the if statement is exited, and the destructor is called, performing the bus release procedure.
const uint8_t DEV_ADDR = 0x70;
if (auto&& wrt = Wire.get_writer(DEV_ADDR)) { // Initialize bus and check connection
wrt(SHTC3_TRIG_H); // Write
wrt(SHTC3_TRIG_L);
} // Bus release procedure
Namespace
Namespaces are actively used in C++ to avoid name collisions. To access definitions inside a namespace, use the ::
operator.
namespace MY_NAME { // Namespace declaration
const uint8_t MYVAL1 = 0x00;
}
...
void my_main() {
uint8_t i = MY_NAME::MYVAL1; // Reference MY_NAME
}
Template
Templates can be considered an extension of C language macros.
template <typename T, int N>
class myary {
T _buf[N];
public:
myary() : _buf{} {}
T operator [] (int i) { return _buf[i % N]; }
};
myary<int, 10> a1; // Array of 10 integers
myary<char, 128> a2; // Array of 128 chars
This example defines a simple array class. T
and N
are template parameters where T
is a type and N
is a number, defining an array class of N
elements of type T
.
nullptr
In C++11, the null pointer is written as nullptr
. NULL
is a macro representing 0
, but nullptr
often has a distinct entity different from 0
.
Reference Type
C++ supports reference types. Similar to pointers, but with the constraint that they must always refer to an object.
Functions with reference parameters like below can modify the value of i
inside incr()
.
void incr(int& lhs, int rhs) { lhs += rhs; }
void my_main() {
int i = 10; j = 20;
incr(i, j);
}
In this template example, the return type of operator[]
is changed to T&
. This allows direct assignment to internal array data like a[0] = 1
.
template <typename T, int N>
class myary {
T _buf[N];
public:
myary() : _buf{} {}
T& operator [] (int i) { return _buf[i % N]; }
};
myary<int, 10> a1;
void my_main() {
a1[0] = 1;
a1[1] = 2;
}
Type Inference
C++11 introduced the auto
keyword for type inference. The compiler deduces the object type from the initializer, allowing omission of explicit type names. This is effective when template class names become very long.
In this documentation, the universal reference auto&&
is often used. Consider it as a way to write code without worrying about whether the parameter is passed by reference or not.
auto&& p = std::make_pair("HELLO", 5);
// std::pair<const char*, int>
Container
A class that holds multiple objects of a specific data type, such as arrays. The array class myary
shown in the template example is also a container.
smplbuf
and FIFO queue class smplque
.Iterator, .begin()
, .end()
An extension of pointers in C language (pointers can also be used in C++). Pointers in C language are a means to access consecutive memory elements from start to end. Consider a FIFO queue. The simplest implementation is a ring buffer, which does not have contiguous memory. Even so, using iterators allows you to write code similarly to pointer use.
.begin()
and .end()
methods are used to obtain iterators. .begin()
returns an iterator pointing to the container’s first element. .end()
returns an iterator pointing to one past the last element. The reason it points past the last element, not the last itself, is for clarity in loop constructs like for
or while
, and for handling containers with zero elements.
my_queue que; // my_queue is a queue class
auto&& p = que.begin();
auto&& e = que.end();
while(p != e) {
some_process(*p);
++p;
}
Here, for each element in que
, the iterator p
is used to apply some_process()
. The iterator p
is incremented with ++
to point to the next element. Even for containers without contiguous memory, iterators allow pointer-like processing.
Because .end()
points past the last element, the loop termination condition is simply (p != e)
. If the queue is empty, .begin()
equals .end()
(both point to the position where the first element would be inserted).
For containers with contiguous memory, iterators are usually normal pointers, so the overhead is minimal.
C++ Standard Library
The C++ standard library includes the STL (Standard Template Library). The MWX library uses parts of it.
Algorithm
For example, finding the maximum or minimum value was written separately for each type in C language. Such code is often the same except for the type part. C++ uses template
and iterators to write these operations independent of type. This is called algorithms.
// Returns iterator to the maximum element in the range
template <class Iter>
Iter find_max(Iter b, Iter e) {
Iter m = b; ++b;
while(b != e) {
if (*b > *m) { m = b; }
++b;
}
return m;
}
The above is an algorithm to find the maximum value. It is type-independent (generic programming).
#include <algorithm>
auto&& minmax = std::minmax_element( // Get min and max algorithm
que.begin(), que.end());
auto&& min_val = *minmax.first;
auto&& max_val = *minmax.second;
Here, the iterator of que
is passed to std::minmax_element
, an algorithm defined in the C++ standard library. The return value is a std::pair
of two values. The algorithm requires the elements to support <
, >
, and ==
operators for comparison. The return type is deduced from the iterator type.