Friday, November 30, 2018

Cheap Signal Analyzer



I bought this very cheap 8-input signal analyzer sometime ago on E-Bay, but since then never had time to use it, mostly due to the driver available was for Windows only.  But a few days ago, I plugged it in on my Linux Mint and googled based on VID I found, I stumbled upon a cool opensource project called "SigOk", a complete project to support various embedded instruments, including my signal analyzer.  It comes with a nice GUI front-end called "PulseView".

Operator Overloading in C++

// Assignment operators:
Type &operator&=(Type &lhs, const Type &rhs); // Assign bitwise and
Type &operator^=(Type &lhs, const Type &rhs); // Assign exclusive or
Type &operator|=(Type &lhs, const Type &rhs); // Assign bitwise or
Type &operator-=(Type &lhs, const Type &rhs); // Assign difference
Type &operator<<=(Type &lhs, const Type &rhs); // Assign left shift
Type &operator*=(Type &lhs, const Type &rhs); // Assign product
Type &operator/=(Type &lhs, const Type &rhs); // Assign quotient
Type &operator%=(Type &lhs, const Type &rhs); // Assign remainder
Type &operator>>=(Type &lhs, const Type &rhs); // Assign right shift
Type &operator+=(Type &lhs, const Type &rhs); // Assign sum

//Other modification operators
Type &operator--(Type &lhs); // Prefix decrement - decrement and return new value
Type operator--(Type &lhs, int unused); // Postfix decrement - decrement and return copy of old value
Type &operator++(Type &lhs); // Prefix increment - increment and return new value
Type operator++(Type &lhs, int unused); // Postfix increment - increment and return copy of old value

//Comparison operators
bool operator==(const Type &lhs, const Type &rhs); // Equal
bool operator>(const Type &lhs, const Type &rhs); // Greater than
bool operator>=(const Type &lhs, const Type &rhs); // Greater than or equal
bool operator<(const Type &lhs, const Type &rhs); // less than
bool operator<=(const Type &lhs, const Type &rhs); // less than or equal
bool operator!(const Type &lhs); // logical complement
bool operator!=(const Type &lhs, const Type &rhs); // no equal
//Other operators
Type operator+(const Type &lhs, const Type &rhs); // Addition
Type operator+(const Type &lhs); // Unary plus
Type operator-(const Type &lhs, const Type &rhs); // Subtraction
Type operator-(const Type &lhs); // Unary minus
ContainedType* operator&(const Type &lhs); // Address of
Type operator&(const Type &lhs, const Type &rhs); // Bitwise and
Type operator~(const Type &lhs, const Type &rhs); // Bitwise complement
Type operator^(const Type &lhs, const Type &rhs); // Bitwise exclusive or
Type operator|(const Type &lhs, const Type &rhs); // Bitwise or
Type operator/(const Type &lhs, const Type &rhs); // Division
Type operator<<(const Type &lhs, const Type &rhs); // Left shift
Type operator*(const Type &lhs, const Type &rhs); // Multiplication
ContainedType &operator*(const Type &lhs); // Dereference
Type operator%(const Type &lhs, const Type &rhs); // Remainder
Type operator>>(const Type &lhs, const Type &rhs); // Right shift

class Type
{
 
// Overloads which must be member functions
  ContainedType &operator[](const IndexType &index); // Array subscript
  Type &operator=(const Type &rhs); // Assignment
  ContainedType &operator->*(); // Member reference
  const ContainedType &operator->*() const; // Member reference
  ContainedType &operator->(); // Member reference
  const ContainedType &operator->() const; // Member reference
 
 // Assignment operators
  Type &operator&=(const Type &rhs); // Assign bitwise and
  Type &operator^=(const Type &rhs); // Assign exclusive or
  Type &operator|=(const Type &rhs); // Assign bitwise or
  Type &operator-=(const Type &rhs); // Assign difference
  Type &operator<<=(const Type &rhs); // Assign left shift
  Type &operator*=(const Type &rhs); // Assign product
  Type &operator/=(const Type &rhs); // Assign quotient
  Type &operator%=(const Type &rhs); // Assign remainder
  Type &operator>>=(const Type &rhs); // Assign right shift
  Type &operator+=(const Type &rhs); // Assign sum
//Other modification operators
  Type &operator--(Type &lhs); // Prefix decrement - decrement and return new value
  Type operator--(Type &lhs, int unused); // Postfix decrement - decrement and return copy of old value
  Type &operator++(); // Prefix increment - increment and return new value
  Type operator++(int unused); // Postfix increment - increment and return copy of old value
//Comparison operators
  bool operator==(const Type &rhs) const; // Equal
  bool operator>(const Type &rhs) const; // Greater than
  bool operator>=(const Type &rhs) const; // Greater than or equal 
  bool operator<(const Type &rhs) const; // Less than
  bool operator<=(const Type &rhs) const; // Less than or equal
  bool operator!=(const Type &rhs) const; // Not equal
//Other operators
  Type operator+(const Type &rhs) const; // Addition
  Type operator+() const; // Unary plus
  Type operator-(const Type &rhs) const; // Subtraction
  Type operator-() const; // Unary minus
  ContainedType* operator&(); // Address of
  const ContainedType* operator&() const; // Address of
  Type operator&(const Type &rhs) const; // Bitwise and
  Type operator~(const Type &rhs) const; // Bitwise complement
  Type operator^(const Type &rhs) const; // Bitwise exclusive or
  Type operator|(const Type &rhs) const; // Bitwise or
  ContainedType &operator*(); // Dereference
  const ContainedType &operator*() const; // Dereference
  Type operator/(const Type &rhs) const; // Division
  Type operator<<(const Type &rhs) const; // Left shift
  bool operator!() const; // Logical complement
  Type operator*(const Type &rhs) const; // Multiplication
  Type operator%(const Type &rhs) const; // Remainder
  Type operator>>(const Type &rhs) const; // Right shift
};


Example


Type& Type::operator = (Type const & rhs)
{
    if (&rhs != this)
    {
        // perform assignment to the class T's attributes
    }
    // return by reference
    return *this;
}


Type Type::operator &= (Type const & rhs)
{
    return *this = (*this) & rhs;
}


Type Type::operator & (Type const & rhs)
{
    Type newObjVal;

    // do customized bitwise AND for the type against rhs
    ….

    // return an object by value
    return newObjVal;
}

Type& Type::operator++()  // prefix
{
    ++m_data;
    return *this;
}



class MyClass
{
public:
    // conversion operator, so expression like: Type b = myClass;
    operator Type() { return *m_ptr; }
...
private:
    int m_data;
    Type m_ptr;
};

MyClassMyClass::operator++(int unused)  // postfix
{
    MyClassresult = *this;
    ++m_data;
    // return value before increment
    return result;
}


T* MyClass::operator->() const {return m_ptr; }

// Conversion operator

Tuesday, August 14, 2018

Pointers of String

It is always tricky dealing with string in C/C++, but if we know the rule of evaluation of expression in C++, it's not that hard to understand it.

A string declaration is always evaluated from right to left.  For example, "char *str" is evaluated as "a variable with name 'str' is a pointer (*) of type char".

Another example:

"const char *str" is evaluated as variable str as a pointer of type char that is const (the content is immutable").  (Please remember, "const char .." expression is identical to expression "char const ...")

"char * const str" is evaluated as a variable with name 'str' is a constant pointer to type char, meaning once the pointer is initialized to point to a string, it cannot be changed to point to another string.

"char const * const str" is evaluated as "a variable with name 'str' is a constant pointer to constant char content.  It is a combination to all above.



#include <iostream>

/*

char* str: 
const char* str OR char const *str
char* const str: 
const char* const str: 


*/

#define L(v)       #v << " = " << v

using namespace std;

static char cstr[] = "String ini statis!";

int main()
{
    char*   ps1;  // just a regular pointer to a string
    ps1 = cstr;
    cout << L(ps1) << endl;

#if 0
    char const * p_constr = cstr;
    // the following causes compile error, as it tries to change value of the static string
    *p_constr = '1';
    cout << L(p_constr) << endl;
#endif

    // a dialect of the above (char const *)
    const char* p_constr2 = cstr;
    *p_constr2 = '1';
    cout << L(p_constr2) << endl;


#if 0
    const char* const const_ptr = cstr;  // the pointer cannot be set to different one

    // the following will cause compile error
    const_ptr = cstr2;
    cout << L(const_ptr) << std::endl;
#endif
}