From 2925e4d78611aa5222a864e2240fbad9183b4387 Mon Sep 17 00:00:00 2001 From: peri4 Date: Tue, 30 Nov 2010 08:11:27 +0300 Subject: [PATCH] 30.11.2010 - initial commit --- .kdev4/pip.kdev4 | 32 ++++ CMakeLists.txt | 11 ++ main.cpp | 5 + piconfig.cpp | 253 ++++++++++++++++++++++++++++ piconfig.h | 72 ++++++++ piconsole.cpp | 412 ++++++++++++++++++++++++++++++++++++++++++++++ piconsole.h | 197 ++++++++++++++++++++++ piethernet.cpp | 128 ++++++++++++++ piethernet.h | 50 ++++++ pifile.cpp | 57 +++++++ pifile.h | 77 +++++++++ piincludes.h | 112 +++++++++++++ pikbdlistener.cpp | 39 +++++ pikbdlistener.h | 34 ++++ pimutex.h | 37 +++++ pip.kdev4 | 3 + piprotocol.cpp | 167 +++++++++++++++++++ piprotocol.h | 78 +++++++++ piserial.cpp | 245 +++++++++++++++++++++++++++ piserial.h | 75 +++++++++ pithread.cpp | 61 +++++++ pithread.h | 61 +++++++ pitimer.cpp | 128 ++++++++++++++ pitimer.h | 69 ++++++++ 24 files changed, 2403 insertions(+) create mode 100644 .kdev4/pip.kdev4 create mode 100644 CMakeLists.txt create mode 100644 main.cpp create mode 100644 piconfig.cpp create mode 100644 piconfig.h create mode 100644 piconsole.cpp create mode 100644 piconsole.h create mode 100644 piethernet.cpp create mode 100644 piethernet.h create mode 100644 pifile.cpp create mode 100644 pifile.h create mode 100644 piincludes.h create mode 100644 pikbdlistener.cpp create mode 100644 pikbdlistener.h create mode 100644 pimutex.h create mode 100644 pip.kdev4 create mode 100644 piprotocol.cpp create mode 100644 piprotocol.h create mode 100644 piserial.cpp create mode 100644 piserial.h create mode 100644 pithread.cpp create mode 100644 pithread.h create mode 100644 pitimer.cpp create mode 100644 pitimer.h diff --git a/.kdev4/pip.kdev4 b/.kdev4/pip.kdev4 new file mode 100644 index 00000000..0de0e122 --- /dev/null +++ b/.kdev4/pip.kdev4 @@ -0,0 +1,32 @@ +[Buildset] +BuildItems=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x01\x00\x00\x00\x06\x00p\x00i\x00p) + +[CMake] +BuildDirs=/home/peri4/pprojects/pip/ +CMakeDir=/usr/share/cmake/Modules +Current CMake Binary=file:///usr/bin/cmake +CurrentBuildDir=file:///home/peri4/pprojects/pip/ +CurrentBuildType=Debug +CurrentInstallDir= +ProjectRootRelative=./ + +[Launch] +Launch Configurations=Launch Configuration 0 + +[Launch][Launch Configuration 0] +Configured Launch Modes=execute +Configured Launchers=nativeAppLauncher +Name=pip +Type=Native Application + +[Launch][Launch Configuration 0][Data] +Arguments= +Dependencies=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x01\x00\x00\x00\x06\x00p\x00i\x00p) +Dependency Action=Build +EnvironmentGroup=default +Project Target=pip,pip +Working Directory= +isExecutable=false + +[Project] +VersionControlSupport=kdevgit diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..d1b36d93 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,11 @@ +project(pip) +cmake_minimum_required(VERSION 2.6) +include_directories(${CMAKE_CURRENT_SOURCE_DIR} .) +file(GLOB CPPS "*.cpp") +add_definitions(-O2 -g3 -DMV_DEBUG) +add_executable(pip ${CPPS}) +if (${WIN32}) + target_link_libraries(pip pthread ws2_32) +else (${WIN32}) + target_link_libraries(pip pthread rt) +endif (${WIN32}) diff --git a/main.cpp b/main.cpp new file mode 100644 index 00000000..9587e97a --- /dev/null +++ b/main.cpp @@ -0,0 +1,5 @@ +#include "pitimer.h" + +int main(int argc, char * argv[]) { + cout << date2string(currentDate()) << endl; +}; diff --git a/piconfig.cpp b/piconfig.cpp new file mode 100644 index 00000000..27f3affe --- /dev/null +++ b/piconfig.cpp @@ -0,0 +1,253 @@ +#include "piconfig.h" + + +PIConfig::PIConfig(const string & path): PIFile(path) { + if (!isOpened()) + open(path, Read | Write | New); + parse(); +} + + +bool PIConfig::getValue(const string & vname, const bool def, bool * exist) const { + return atob(getValue(vname, btos(def), exist));} +char PIConfig::getValue(const string & vname, const char def, bool * exist) const { + return atoi(getValue(vname, string(1, def), exist).c_str());} +short PIConfig::getValue(const string & vname, const short def, bool * exist) const { + return atoi(getValue(vname, itos(def), exist).c_str());} +int PIConfig::getValue(const string & vname, const int def, bool * exist) const { + return atoi(getValue(vname, itos(def), exist).c_str());} +long PIConfig::getValue(const string & vname, const long def, bool * exist) const { + return atoi(getValue(vname, ltos(def), exist).c_str());} +uchar PIConfig::getValue(const string & vname, const uchar def, bool * exist) const { + return atoi(getValue(vname, uitos(def), exist).c_str());} +ushort PIConfig::getValue(const string & vname, const ushort def, bool * exist) const { + return atoi(getValue(vname, uitos(def), exist).c_str());} +uint PIConfig::getValue(const string & vname, const uint def, bool * exist) const { + return atoi(getValue(vname, uitos(def), exist).c_str());} +ulong PIConfig::getValue(const string & vname, const ulong def, bool * exist) const { + return atoi(getValue(vname, ultos(def), exist).c_str());} +float PIConfig::getValue(const string & vname, const float def, bool * exist) const { + return atof(getValue(vname, ftos(def), exist).c_str());} +double PIConfig::getValue(const string & vname, const double def, bool * exist) const { + return atof(getValue(vname, dtos(def), exist).c_str());} + + +void PIConfig::setValue(const string & name, const char * value, bool write) { + setValue(name, string(value), "s", write);} +void PIConfig::setValue(const string & name, const bool value, bool write) { + setValue(name, btos(value), "b", write);} +void PIConfig::setValue(const string & name, const char value, bool write) { + setValue(name, string(1, value), "s", write);} +void PIConfig::setValue(const string & name, const short value, bool write) { + setValue(name, itos(value), "n", write);} +void PIConfig::setValue(const string & name, const int value, bool write) { + setValue(name, itos(value), "n", write);} +void PIConfig::setValue(const string & name, const long value, bool write) { + setValue(name, ltos(value), "n", write);} +void PIConfig::setValue(const string & name, const uchar value, bool write) { + setValue(name, uitos(value), "n", write);} +void PIConfig::setValue(const string & name, const ushort value, bool write) { + setValue(name, uitos(value), "n", write);} +void PIConfig::setValue(const string & name, const uint value, bool write) { + setValue(name, uitos(value), "n", write);} +void PIConfig::setValue(const string & name, const ulong value, bool write) { + setValue(name, ultos(value), "n", write);} +void PIConfig::setValue(const string & name, const float value, bool write) { + setValue(name, ftos(value), "f", write);} +void PIConfig::setValue(const string & name, const double value, bool write) { + setValue(name, dtos(value), "f", write);} + + +string PIConfig::getValue(const string & vname, const string & def, bool * exist) const { + for (int i = 0; i < settname.size(); i++) { + if (settname[i] == vname) { + if (exist != 0) *exist = true; + return settval[i]; + } + } + if (exist != 0) *exist = false; + return def; +} + + +void PIConfig::setValue(const string & name, const string & value, const string & type, bool write) { + int number = getNumber(name); + if (number == -1) { + addLine(name, value, type); + return; + } + string tmp = settname[number] + " = " + value + " #" + setttype[number] + " " + settcom[number]; + settval[number] = value; + all[settlines[number]] = tmp; + if (write) writeAll(); +} + + +bool PIConfig::existsValue(const string & name) { + for (int i = 0; i < settname.size(); i++) + if (settname[i] == name) return true; + return false; +} + + +void PIConfig::addLine(const string & name, const string & value, const string & type) { + if (setttab.size() > 0) *this << setttab[setttab.size() - 1] << name << " = " << value << " #" << type << "\n"; + else *this << name << " = " << value << " #" << type << "\n"; + settname.push_back(name); + settval.push_back(value); + settcom.push_back(""); + setttype.push_back(type); + if (setttab.size() > 0) setttab.push_back(setttab[setttab.size() - 1]); + else setttab.push_back("\t"); + settlines.push_back(all.size()); + all.push_back(name + " = " + value + " #" + type); + flush(); +} + + +void PIConfig::insertLine(int number, const string & name, const string & value, const string & type) { + if (number >= settname.size()) { + addLine(name, value, type); + return; + } + settname.insert(settname.begin() + number, name); + settval.insert(settval.begin() + number, value); + settcom.insert(settcom.begin() + number, ""); + setttab.insert(setttab.begin() + number, setttab[number]); + setttype.insert(setttype.begin() + number, type); + settlines.insert(settlines.begin() + number, settlines[number]); + for (int i = number + 1; i < settlines.size(); i++) settlines[i]++; + all.insert(all.begin() + settlines[number], name + " = " + value + " #" + type); + flush(); + writeAll(); +} + + +int PIConfig::getNumber(const string & name) { + for (int i = 0; i < settname.size(); i++) + if (settname[i] == name) + return i; + return -1; +} + + +void PIConfig::setValue(int number, const string & value, bool write) { + string tmp = settname[number] + " = " + value + " #" + setttype[number] + " " + settcom[number]; + settval[number] = value; + all[settlines[number]] = tmp; + if (write) writeAll(); +} + + +void PIConfig::setName(int number, const string & name) { + string tmp = name + " = " + settval[number] + " #" + setttype[number] + " " + settcom[number]; + settname[number] = name; + all[settlines[number]] = tmp; + writeAll(); +} + + +void PIConfig::setType(int number, const string & type) { + string tmp = settname[number] + " = " + settval[number] + " #" + type + " " + settcom[number]; + setttype[number] = type; + all[settlines[number]] = tmp; + writeAll(); +} + + +void PIConfig::setComment(int number, const string & comment) { + string tmp = settname[number] + " = " + settval[number] + " #" + setttype[number] + " " + comment; + settcom[number] = comment; + all[settlines[number]] = tmp; + writeAll(); +} + + +void PIConfig::deleteLine(const string & name) { + bool exist = false; + int i; + for (i = 0; i < settname.size(); i++) { + if (settname[i] == name) { + exist = true; + break; + } + } + if (!exist) return; + deleteLine(i); +} + + +void PIConfig::deleteLine(int number) { + settname.erase(settname.begin() + number); + settval.erase(settval.begin() + number); + settcom.erase(settcom.begin() + number); + setttab.erase(setttab.begin() + number); + setttype.erase(setttype.begin() + number); + all.erase(all.begin() + settlines[number]); + for (int i = number; i < settlines.size(); i++) settlines[i]--; + settlines.erase(settlines.begin() + number); + writeAll(); +} + + +void PIConfig::writeAll() { + clear(); + int c = 0; + for (int i = 0; i < all.size() - 1; i++) { + if (c < settlines.size() && c < setttab.size()) { + if (settlines[c] == i) { + *this << setttab[c]; + c++; + } + } + *this << all[i] << "\n"; + } + readAll(); +} + + +void PIConfig::readAll() { + settname.clear(); + settval.clear(); + settcom.clear(); + setttab.clear(); + settlines.clear(); + setttype.clear(); + all.clear(); + flush(); + parse(); +} + + +void PIConfig::parse() { + string str, tab, comm; + int ind, sind; + if (!isOpened()) return; + seek(0); + lines = 0; + while (!isEnd()) { + str = readLine(); + tab = s_left(str, str.find_first_of(s_left(s_trimmed(str), 1))); + str = s_trimmed(str); + all.push_back(str); + ind = str.find_first_of('='); + if ((ind > 0) && !(str[0] == '#')) { + sind = str.find_first_of('#'); + if (sind > 0) { + comm = s_trimmed(s_right(str, str.size() - sind - 1)); + setttype.push_back(s_left(comm, 1)); + comm = s_trimmed(s_right(comm, comm.size() - 1)); + settcom.push_back(comm); + str = s_left(str, sind); + } else { + setttype.push_back("s"); + settcom.push_back(""); + } + settname.push_back(s_trimmed(s_left(str, ind))); + settval.push_back(s_trimmed(s_right(str, str.size() - ind - 1))); + setttab.push_back(tab); + settlines.push_back(lines); + } + lines++; + } +} diff --git a/piconfig.h b/piconfig.h new file mode 100644 index 00000000..39f89cb4 --- /dev/null +++ b/piconfig.h @@ -0,0 +1,72 @@ +#ifndef PICONFIG_H +#define PICONFIG_H + +#include "pifile.h" + +class PIConfig: public PIFile +{ +public: + PIConfig(const string & path); + ~PIConfig() {;} + + string getValue(const string & vname, const string & def = "", bool * exist = 0) const; + string getValue(const string & vname, const char * def = "", bool * exist = 0) const; + bool getValue(const string & vname, const bool def = false, bool * exist = 0) const; + char getValue(const string & vname, const char def = 0, bool * exist = 0) const; + short getValue(const string & vname, const short def = 0, bool * exist = 0) const; + int getValue(const string & vname, const int def = 0, bool * exist = 0) const; + long getValue(const string & vname, const long def = 0, bool * exist = 0) const; + uchar getValue(const string & vname, const uchar def = 0, bool * exist = 0) const; + ushort getValue(const string & vname, const ushort def = 0, bool * exist = 0) const; + uint getValue(const string & vname, const uint def = 0, bool * exist = 0) const; + ulong getValue(const string & vname, const ulong def = 0, bool * exist = 0) const; + float getValue(const string & vname, const float def = 0., bool * exist = 0) const; + double getValue(const string & vname, const double def = 0., bool * exist = 0) const; + + void setValue(const string & name, const string & value, const string & type = "s", bool write = true); + void setValue(const string & name, const char * value, bool write = true); + void setValue(const string & name, const bool value, bool write = true); + void setValue(const string & name, const char value, bool write = true); + void setValue(const string & name, const short value, bool write = true); + void setValue(const string & name, const int value, bool write = true); + void setValue(const string & name, const long value, bool write = true); + void setValue(const string & name, const uchar value, bool write = true); + void setValue(const string & name, const ushort value, bool write = true); + void setValue(const string & name, const uint value, bool write = true); + void setValue(const string & name, const ulong value, bool write = true); + void setValue(const string & name, const float value, bool write = true); + void setValue(const string & name, const double value, bool write = true); + + string getValue(int number) const {return settval[number];} + string getName(int number) const {return settname[number];} + string getComment(int number) const {return settcom[number];} + void setValue(int number, const string & value, bool write = true); + bool existsValue(const string & name); + char getType(int number) const {return setttype[number][0];} + int getNumber(const string & name); + void setName(int number, const string & name); + void setType(int number, const string & type); + void setComment(int number, const string & comment); + int numValues() const {return settval.size();} + void addLine(const string & name, const string & value, const string & type = "s"); + void insertLine(int number, const string & name, const string & value, const string & type = "s"); + void deleteLine(const string & name); + void deleteLine(int number); + void readAll(); + void writeAll(); + +private: + void parse(); + + vector settname; + vector settval; + vector settcom; + vector setttab; + vector setttype; + vector all; + vector settlines; + int lines; + +}; + +#endif // PICONFIG_H diff --git a/piconsole.cpp b/piconsole.cpp new file mode 100644 index 00000000..e6cb2230 --- /dev/null +++ b/piconsole.cpp @@ -0,0 +1,412 @@ +#include "piconsole.h" + + +PIConsole::PIConsole(bool startNow, KeyFunc slot): PIThread() { + setPriority(piLow); + needLockRun(true); + ret_func = slot; + num_format = 0; + cur_tab = width = height = my = 0; +#ifdef WINDOWS + ulcoord.X = ulcoord.Y = 0; + hOut = GetStdHandle(STD_OUTPUT_HANDLE); + GetConsoleScreenBufferInfo(hOut, &sbi); + dattr = sbi.wAttributes; + width = sbi.srWindow.Right - sbi.srWindow.Left; + height = sbi.srWindow.Bottom - sbi.srWindow.Top; + GetConsoleMode(hOut, &smode); + GetConsoleCursorInfo(hOut, &curinfo); +#endif + addTab(string("main")); + listener = new PIKbdListener(key_event, this); + if (startNow) start(40); +} + + +PIConsole::~PIConsole() { + if (isRunning()) { + stop(); + waitForFinish(); + moveTo(0, my + 4); + showCursor(); + } + delete listener; + clearTabs(false); +#ifdef WINDOWS + SetConsoleMode(hOut, smode); + SetConsoleTextAttribute(hOut, dattr); +#endif +} + + +int PIConsole::addTab(string name, char bind_key) { + tabs.push_back(Tab(name, bind_key)); + cur_tab = tabs.size() - 1; + return tabs.size(); +} + + +void PIConsole::removeTab(uint index) { + if (index >= tabs.size()) return; + tabs.erase(vector::iterator(&tabs[index])); + if (cur_tab >= tabs.size()) cur_tab = tabs.size() - 1; +} + + +void PIConsole::removeTab(string name) { + uint index = tabs.size() + 1; + for (uint i = 0; i < tabs.size(); ++i) { + if (tabs[i].name == name) { + index = i; + break; + } + } + removeTab(index); +} + + +bool PIConsole::setTab(uint index) { + if (index >= tabs.size() || index < 0) + return false; + cur_tab = index; + if (!isRunning()) return true; + lock(); + clearScreen(); + fillLabels(); + unlock(); + return true; +} + + +bool PIConsole::setTab(string name) { + uint index = tabs.size() + 1; + for (uint i = 0; i < tabs.size(); ++i) { + if (tabs[i].name == name) { + index = i; + break; + } + } + return setTab(index); +} + + +bool PIConsole::setTabBindKey(uint index, char bind_key) { + if (index < 0 || index >= tabs.size()) + return false; + tabs[index].key = bind_key; + return true; +} + + +bool PIConsole::setTabBindKey(string name, char bind_key) { + uint index =tabs.size() + 1; + for (uint i = 0; i < tabs.size(); ++i) { + if (tabs[i].name == name) { + index = i; + break; + } + } + return setTabBindKey(index, bind_key); +} + + +void PIConsole::key_event(void * t, char key) { + PIConsole * p = (PIConsole * )t; + for (uint i = 0; i < p->tabsCount(); ++i) { + if (p->tabs[i].key == key) { + p->setTab(i); + return; + } + } + if (p->ret_func != 0) p->ret_func(t, key); +} + + +string PIConsole::fstr(Flags f) { + if (f[PIConsole::Dec]) num_format = 0; + if (f[PIConsole::Hex]) num_format = 1; + if (f[PIConsole::Oct]) num_format = 2; + if (f[PIConsole::Scientific]) num_format = 3; + +#ifdef WINDOWS + WORD attr = dattr; + + if (f[PIConsole::Inverse]) { + if (f[PIConsole::Red]) attr |= BACKGROUND_RED; + if (f[PIConsole::Green]) attr |= BACKGROUND_GREEN; + if (f[PIConsole::Blue]) attr |= BACKGROUND_BLUE; + if (f[PIConsole::Yellow]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN); + if (f[PIConsole::Magenta]) attr |= (BACKGROUND_RED | BACKGROUND_BLUE); + if (f[PIConsole::Cyan]) attr |= (BACKGROUND_GREEN | BACKGROUND_BLUE); + if (f[PIConsole::White]) attr |= (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); + attr |= (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + } else { + if (f[PIConsole::Red]) attr |= FOREGROUND_RED; + if (f[PIConsole::Green]) attr |= FOREGROUND_GREEN; + if (f[PIConsole::Blue]) attr |= FOREGROUND_BLUE; + if (f[PIConsole::Yellow]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN); + if (f[PIConsole::Magenta]) attr |= (FOREGROUND_RED | FOREGROUND_BLUE); + if (f[PIConsole::Cyan]) attr |= (FOREGROUND_GREEN | FOREGROUND_BLUE); + if (f[PIConsole::White]) attr |= (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + } + if (f[PIConsole::Bold]) attr |= FOREGROUND_INTENSITY; + + SetConsoleTextAttribute(hOut, attr); + return ""; +#else + string ts = "\e[0"; + + if (f[PIConsole::Bold]) ts += ";1"; + if (f[PIConsole::Faint]) ts += ";2"; + if (f[PIConsole::Italic]) ts += ";3"; + if (f[PIConsole::Underline]) ts += ";4"; + if (f[PIConsole::Blink]) ts += ";5"; + if (f[PIConsole::Inverse]) ts += ";7"; + + if (f[PIConsole::Black]) ts += ";30"; + if (f[PIConsole::Red]) ts += ";31"; + if (f[PIConsole::Green]) ts += ";32"; + if (f[PIConsole::Yellow]) ts += ";33"; + if (f[PIConsole::Blue]) ts += ";34"; + if (f[PIConsole::Magenta]) ts += ";35"; + if (f[PIConsole::Cyan]) ts += ";36"; + if (f[PIConsole::White]) ts += ";37"; + + return ts + "m"; +#endif +} + +#define siprint(x) switch (num_format) {case (1): return printf("0x%.4hX", x); break; case (2): return printf("%o", x); break; default: return printf("%hd", x); break;} +#define iprint(x) switch (num_format) {case (1): return printf("0x%.8X", x); break; case (2): return printf("%o", x); break; default: return printf("%d", x); break;} +#define liprint(x) switch (num_format) {case (1): return printf("0x%.16lX", x); break; case (2): return printf("%lo", x); break; default: return printf("%ld", x); break;} +#define lliprint(x) switch (num_format) {case (1): return printf("0x%.16LX", x); break; case (2): return printf("%Lo", x); break; default: return printf("%Ld", x); break;} +#define suprint(x) switch (num_format) {case (1): return printf("0x%.4hX", x); break; case (2): return printf("%o", x); break; default: return printf("%hd", x); break;} +#define uprint(x) switch (num_format) {case (1): return printf("0x%.8X", x); break; case (2): return printf("%o", x); break; default: return printf("%u", x); break;} +#define luprint(x) switch (num_format) {case (1): return printf("0x%.16lX", x); break; case (2): return printf("%lo", x); break; default: return printf("%lu", x); break;} +#define lluprint(x) switch (num_format) {case (1): return printf("0x%.16LX", x); break; case (2): return printf("%Lo", x); break; default: return printf("%Lu", x); break;} +#define fprint(x) switch (num_format) {case (3): return printf("%e", x); break; default: return printf("%.5g", x); break;} +#define dprint(x) switch (num_format) {case (3): return printf("%le", x); break; default: return printf("%.5lg", x); break;} + +inline int PIConsole::couts(string v) {return printf("%s", v.c_str());} +inline int PIConsole::couts(char * v) {return printf("%s", v);} +inline int PIConsole::couts(bool v) {return (v ? printf("true") : printf("false"));} +inline int PIConsole::couts(char v) {return printf("%c", v);} +inline int PIConsole::couts(short v) {siprint(v);} +inline int PIConsole::couts(int v) {iprint(v);} +inline int PIConsole::couts(long v) {liprint(v);} +inline int PIConsole::couts(llong v) {lliprint(v);} +inline int PIConsole::couts(uchar v) {uprint(v);} +inline int PIConsole::couts(ushort v) {suprint(v);} +inline int PIConsole::couts(uint v) {uprint(v);} +inline int PIConsole::couts(ulong v) {luprint(v);} +inline int PIConsole::couts(ullong v) {lluprint(v);} +inline int PIConsole::couts(float v) {fprint(v);} +inline int PIConsole::couts(double v) {dprint(v);} + + +void PIConsole::begin() { +#ifdef WINDOWS + SetConsoleMode(hOut, ENABLE_WRAP_AT_EOL_OUTPUT); +#endif + clearScreen(); + hideCursor(); + fillLabels(); +} + + +void PIConsole::run() { + uint cx, clen = 0; +#ifdef WINDOWS + GetConsoleScreenBufferInfo(hOut, &sbi); + width = sbi.srWindow.Right - sbi.srWindow.Left; + height = sbi.srWindow.Bottom - sbi.srWindow.Top; +#else + winsize ws; + ioctl(0, TIOCGWINSZ, &ws); + width = ws.ws_col; + height = ws.ws_row; +#endif + col_cnt = vars().size(); + col_wid = (col_cnt > 0) ? width / col_cnt : width; + for (uint i = 0; i < col_cnt; ++i) { + cx = col_wid * i; + toUpperLeft(); + for (uint j = 0; j < vars()[i].size(); ++j) { + if (my < j) my = j; + tv = vars()[i][j]; + moveRight(cx); + if (tv.name.size() == 0) { + newLine(); + continue; + } + if (tv.type == 0 && tv.s == 0) { + newLine(); + continue; + } + moveRight(tv.offset); + switch (tv.type) { + case 0: clen = printValue(*tv.s, tv.format); break; + case 1: clen = printValue(*tv.b, tv.format); break; + case 2: clen = printValue(*tv.i, tv.format); break; + case 3: clen = printValue(*tv.l, tv.format); break; + case 4: clen = printValue(*tv.c, tv.format); break; + case 5: clen = printValue(*tv.f, tv.format); break; + case 6: clen = printValue(*tv.d, tv.format); break; + case 7: clen = printValue(*tv.sh, tv.format); break; + case 8: clen = printValue(*tv.ui, tv.format); break; + case 9: clen = printValue(*tv.ul, tv.format); break; + case 10: clen = printValue(*tv.ush, tv.format); break; + case 11: clen = printValue(*tv.uc, tv.format); break; + case 12: clen = printValue(*tv.ll, tv.format); break; + case 13: clen = printValue(*tv.ull, tv.format); break; + case 14: clen = printValue(bitsValue(tv.uc, tv.bitFrom, tv.bitCount), tv.format); break; + } + if (clen + tv.offset < (uint)col_wid) + printf("%s", string(col_wid - clen - tv.offset, ' ').c_str()); + newLine(); + } + } + fflush(0); +} + + +void PIConsole::fillLabels() { + uint cx, my = 0; +#ifdef WINDOWS + GetConsoleScreenBufferInfo(hOut, &sbi); + width = sbi.srWindow.Right - sbi.srWindow.Left; + height = sbi.srWindow.Bottom - sbi.srWindow.Top; +#else + winsize ws; + ioctl(0, TIOCGWINSZ, &ws); + width = ws.ws_col; + height = ws.ws_row; +#endif + col_cnt = vars().size(); + col_wid = (col_cnt > 0) ? width / col_cnt : width; + for (uint i = 0; i < col_cnt; ++i) { + cx = col_wid * i; + toUpperLeft(); + for (uint j = 0; j < vars()[i].size(); ++j) { + if (my < j) my = j; + moveRight(cx); + tv = vars()[i][j]; + if (tv.name.size() == 0) { + newLine(); + continue; + } + clearLine(); + if (tv.type == 0 && tv.s == 0) { + printLine(tv.name, cx, tv.format); + newLine(); + continue; + } + vars()[i][j].offset = printValue(tv.name + ": ", tv.format); + newLine(); + } + } + moveTo(0, my + 2); + if (tabs[cur_tab].status.length() > 0) { + printValue(tabs[cur_tab].status); + newLine(); + } + status(); + //fflush(0); +} + + +void PIConsole::status() { + Tab * ctab; + //clearLine(); + for (uint i = 0; i < tabsCount(); ++i) { + ctab = &tabs[i]; + if (ctab->key == 0) continue; + printValue(ctab->key, PIConsole::Bold); + printValue(ctab->name + " ", PIConsole::Cyan | PIConsole::Inverse); + printValue(string(" "), PIConsole::Normal); + } + newLine(); +} + + +int PIConsole::bitsValue(unsigned char * src, int offset, int count) { + int ret = 0, stbyte = offset / 8, cbit = offset - stbyte * 8; + char cbyte = src[stbyte]; + for (int i = 0; i < count; i++) { + ret |= ((cbyte >> cbit & 1) << i); + cbit++; + if (cbit == 8) { + cbit = 0; + stbyte++; + cbyte = src[stbyte]; + } + } + return ret; +} + +#define ADD_VAR_BODY tv.name = name; tv.bitFrom = tv.bitCount = 0; tv.format = format; checkColumn(column); + +void PIConsole::addString(string name, int column, Flags format) { + ADD_VAR_BODY tv.type = 0; tv.s = 0; vars()[column - 1].push_back(tv);} +void PIConsole::addVariable(string name, string* ptr, int column, Flags format) { + ADD_VAR_BODY tv.type = 0; tv.s = ptr; vars()[column - 1].push_back(tv);} +void PIConsole::addVariable(string name, bool * ptr, int column, Flags format) { + ADD_VAR_BODY tv.type = 1; tv.b = ptr; vars()[column - 1].push_back(tv);} +void PIConsole::addVariable(string name, int * ptr, int column, Flags format) { + ADD_VAR_BODY tv.type = 2; tv.i = ptr; vars()[column - 1].push_back(tv);} +void PIConsole::addVariable(string name, long * ptr, int column, Flags format) { + ADD_VAR_BODY tv.type = 3; tv.l = ptr; vars()[column - 1].push_back(tv);} +void PIConsole::addVariable(string name, char * ptr, int column, Flags format) { + ADD_VAR_BODY tv.type = 4; tv.c = ptr; vars()[column - 1].push_back(tv);} +void PIConsole::addVariable(string name, float * ptr, int column, Flags format) { + ADD_VAR_BODY tv.type = 5; tv.f = ptr; vars()[column - 1].push_back(tv);} +void PIConsole::addVariable(string name, double * ptr, int column, Flags format) { + ADD_VAR_BODY tv.type = 6; tv.d = ptr; vars()[column - 1].push_back(tv);} +void PIConsole::addVariable(string name, short * ptr, int column, Flags format) { + ADD_VAR_BODY tv.type = 7; tv.sh = ptr; vars()[column - 1].push_back(tv);} +void PIConsole::addVariable(string name, uint * ptr, int column, Flags format) { + ADD_VAR_BODY tv.type = 8; tv.ui = ptr; vars()[column - 1].push_back(tv);} +void PIConsole::addVariable(string name, ulong * ptr, int column, Flags format) { + ADD_VAR_BODY tv.type = 9; tv.ul = ptr; vars()[column - 1].push_back(tv);} +void PIConsole::addVariable(string name, ushort * ptr, int column, Flags format) { + ADD_VAR_BODY tv.type = 10; tv.ush = ptr; vars()[column - 1].push_back(tv);} +void PIConsole::addVariable(string name, uchar * ptr, int column, Flags format) { + ADD_VAR_BODY tv.type = 11; tv.uc = ptr; vars()[column - 1].push_back(tv);} +void PIConsole::addVariable(string name, llong * ptr, int column, Flags format) { + ADD_VAR_BODY tv.type = 12; tv.ll = ptr; vars()[column - 1].push_back(tv);} +void PIConsole::addVariable(string name, ullong * ptr, int column, Flags format) { + ADD_VAR_BODY tv.type = 13; tv.ull = ptr; vars()[column - 1].push_back(tv);} +void PIConsole::addBitVariable(string name, uchar * ptr, int fromBit, int bitCount, int column, Flags format) { + tv.name = name; tv.bitFrom = fromBit; tv.bitCount = bitCount; tv.type = 14; tv.uc = ptr; tv.format = format; + checkColumn(column); vars()[column - 1].push_back(tv);} +void PIConsole::addEmptyLine(int column) { + tv.name = ""; tv.type = 0; tv.d = 0; tv.format = Normal; + checkColumn(column); vars()[column - 1].push_back(tv);} + +#define PRINT_VAR_BODY couts(fstr(format)); int ret = couts(value); fstr(PIConsole::Dec); return ret; + +void PIConsole::printLine(string value, int dx, Flags format) { + int i = width - value.length() - dx; +#ifdef QNX + --i; +#endif + couts(fstr(format)); + if (i >= 0) couts(value + string(i, ' ')); + else couts(string(value, 0, value.length() + i)); + couts(fstr(Dec)); +} +int PIConsole::printValue(string value, Flags format) {PRINT_VAR_BODY} +int PIConsole::printValue(char * value, Flags format) {PRINT_VAR_BODY} +int PIConsole::printValue(bool value, Flags format) {PRINT_VAR_BODY} +int PIConsole::printValue(int value, Flags format) {PRINT_VAR_BODY} +int PIConsole::printValue(long value, Flags format) {PRINT_VAR_BODY} +int PIConsole::printValue(llong value, Flags format) {PRINT_VAR_BODY} +int PIConsole::printValue(float value, Flags format) {PRINT_VAR_BODY} +int PIConsole::printValue(double value, Flags format) {PRINT_VAR_BODY} +int PIConsole::printValue(char value, Flags format) {PRINT_VAR_BODY} +int PIConsole::printValue(short value, Flags format) {PRINT_VAR_BODY} +int PIConsole::printValue(uchar value, Flags format) {PRINT_VAR_BODY} +int PIConsole::printValue(ushort value, Flags format) {PRINT_VAR_BODY} +int PIConsole::printValue(uint value, Flags format) {PRINT_VAR_BODY} +int PIConsole::printValue(ulong value, Flags format) {PRINT_VAR_BODY} +int PIConsole::printValue(ullong value, Flags format) {PRINT_VAR_BODY} diff --git a/piconsole.h b/piconsole.h new file mode 100644 index 00000000..759b70da --- /dev/null +++ b/piconsole.h @@ -0,0 +1,197 @@ +#ifndef PICONSOLE_H +#define PICONSOLE_H + +#include "pikbdlistener.h" +#ifndef WINDOWS +#include +#include +#endif + +typedef void (*KeyFunc)(void * , char); + +class PIConsole: public PIThread +{ +public: + PIConsole(bool startNow = true, KeyFunc slot = 0); + ~PIConsole(); + + enum Format {Normal = 0x01, + Bold = 0x02, + Faint = 0x04, + Italic = 0x08, + Underline = 0x10, + Blink = 0x20, + Inverse = 0x40, + Black = 0x100, + Red = 0x200, + Green = 0x400, + Yellow = 0x800, + Blue = 0x1000, + Magenta = 0x2000, + Cyan = 0x4000, + White = 0x8000, + Dec = 0x10000, + Hex = 0x20000, + Oct = 0x40000, + Scientific = 0x80000}; + + void addString(string name, int column = 1, Flags format = PIConsole::Normal); + void addVariable(string name, string * ptr, int column = 1, Flags format = PIConsole::Normal); + void addVariable(string name, char * ptr, int column = 1, Flags format = PIConsole::Normal); + void addVariable(string name, bool * ptr, int column = 1, Flags format = PIConsole::Normal); + void addVariable(string name, short * ptr, int column = 1, Flags format = PIConsole::Normal); + void addVariable(string name, int * ptr, int column = 1, Flags format = PIConsole::Normal); + void addVariable(string name, long * ptr, int column = 1, Flags format = PIConsole::Normal); + void addVariable(string name, llong * ptr, int column = 1, Flags format = PIConsole::Normal); + void addVariable(string name, uchar * ptr, int column = 1, Flags format = PIConsole::Normal); + void addVariable(string name, ushort * ptr, int column = 1, Flags format = PIConsole::Normal); + void addVariable(string name, uint * ptr, int column = 1, Flags format = PIConsole::Normal); + void addVariable(string name, ulong * ptr, int column = 1, Flags format = PIConsole::Normal); + void addVariable(string name, ullong * ptr, int column = 1, Flags format = PIConsole::Normal); + void addVariable(string name, float * ptr, int column = 1, Flags format = PIConsole::Normal); + void addVariable(string name, double * ptr, int column = 1, Flags format = PIConsole::Normal); + void addBitVariable(string name, uchar * ptr, int fromBit, int bitCount, int column = 1, Flags format = PIConsole::Normal); + void addEmptyLine(int column = 1); + int addTab(string name, char bind_key = 0); + void removeTab(uint index); + void removeTab(string name); + uint tabsCount() const {return tabs.size();} + bool setTab(uint index); + bool setTab(string name); + bool setTabBindKey(uint index, char bind_key); + bool setTabBindKey(string name, char bind_key); + void addCustomStatus(string str) {tabs[cur_tab].status = str;} + void clearCustomStatus() {tabs[cur_tab].status = "";} + void clearVariables(bool clearScreen = true) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} vars().clear();} + void clearTabs(bool clearScreen = true) {if (clearScreen && isRunning()) {toUpperLeft(); clearScreenLower();} tabs.clear();} + string fstr(Flags f); + string currentTab() const {return tabs[cur_tab].name;} + +private: + void begin(); + void run(); + void fillLabels(); + +#ifdef WINDOWS + inline void getWinCurCoord() {GetConsoleScreenBufferInfo(hOut, &csbi); ccoord = csbi.dwCursorPosition;} + inline COORD & getWinCoord(int dx = 0, int dy = 0) {getWinCurCoord(); ccoord.X += dx; ccoord.Y += dy; return ccoord;} + inline void toUpperLeft() {SetConsoleCursorPosition(hOut, ulcoord);} + inline void moveRight(int n = 1) {SetConsoleCursorPosition(hOut, getWinCoord(n));} + inline void moveLeft(int n = 1) {SetConsoleCursorPosition(hOut, getWinCoord(-n));} + inline void moveTo(int x = 0, int y = 0) {ccoord.X = x; ccoord.Y = y; SetConsoleCursorPosition(hOut, ccoord);} + inline void clearScreen() {FillConsoleOutputAttribute(hOut, dattr, width * (height + 1), ulcoord, &written); + FillConsoleOutputCharacter(hOut, ' ', width * (height + 1), ulcoord, &written);} + inline void clearScreenLower() {getWinCurCoord(); FillConsoleOutputAttribute(hOut, dattr, width * height - width * ccoord.Y + ccoord.X, ccoord, &written); + FillConsoleOutputCharacter(hOut, ' ', width * height - width * ccoord.Y + ccoord.X, ccoord, &written);} + inline void clearLine() {getWinCurCoord(); FillConsoleOutputAttribute(hOut, dattr, width - ccoord.X, ccoord, &written); + FillConsoleOutputCharacter(hOut, ' ', width - ccoord.X, ccoord, &written);} + inline void newLine() {getWinCurCoord(); ccoord.X = 0; ccoord.Y++; SetConsoleCursorPosition(hOut, ccoord);} + inline void hideCursor() {curinfo.bVisible = false; SetConsoleCursorInfo(hOut, &curinfo);} + inline void showCursor() {curinfo.bVisible = true; SetConsoleCursorInfo(hOut, &curinfo);} +#else + inline void toUpperLeft() {printf("\e[H");} + inline void moveRight(int n = 1) {if (n > 0) printf("\e[%dC", n);} + inline void moveLeft(int n = 1) {if (n > 0) printf("\e[%dD", n);} + inline void moveTo(int x = 0, int y = 0) {printf("\e[%d;%dH", y, x);} + inline void clearScreen() {printf("\e[H\e[J");} + inline void clearScreenLower() {printf("\e[J");} + inline void clearLine() {printf("\e[K");} + inline void newLine() {printf("\eE");} + inline void hideCursor() {printf("\e[?25l");} + inline void showCursor() {printf("\e[?25h");} +#endif + void status(); + void checkColumn(uint col) {if (vars().size() < col) {vars().resize(col);}} + int bitsValue(unsigned char * src, int offset, int count); + void printLine(string str, int dx = 0, Flags format = PIConsole::Normal); + int printValue(string str, Flags format = PIConsole::Normal); + int printValue(char * str, Flags format = PIConsole::Normal); + int printValue(bool value, Flags format = PIConsole::Normal); + int printValue(int value, Flags format = PIConsole::Normal); + int printValue(long value, Flags format = PIConsole::Normal); + int printValue(llong value, Flags format = PIConsole::Normal); + int printValue(float value, Flags format = PIConsole::Normal); + int printValue(double value, Flags format = PIConsole::Normal); + int printValue(char value, Flags format = PIConsole::Normal); + int printValue(short value, Flags format = PIConsole::Normal); + int printValue(uchar value, Flags format = PIConsole::Normal); + int printValue(ushort value, Flags format = PIConsole::Normal); + int printValue(uint value, Flags format = PIConsole::Normal); + int printValue(ulong value, Flags format = PIConsole::Normal); + int printValue(ullong value, Flags format = PIConsole::Normal); + static void key_event(void * t, char key); + + struct Variable { + string name; + Flags format; + int type; + int offset; + int bitFrom; + int bitCount; + union { + string * s; + bool * b; + short * sh; + int * i; + long * l; + llong * ll; + float * f; + double * d; + char * c; + uchar * uc; + ushort * ush; + uint * ui; + ulong * ul; + ullong * ull; + }; + void operator =(const Variable & src) {name = src.name; format = src.format; type = src.type; offset = src.offset; + bitFrom = src.bitFrom; bitCount = src.bitCount; c = src.c;} + }; + + struct Tab { + vector > variables; + string name; + string status; + char key; + Tab() {;} + Tab(string n, char k) {name = n; key = k;} + }; + + inline vector > & vars() {return tabs[cur_tab].variables;} + inline int couts(string v); + inline int couts(char * v); + inline int couts(bool v); + inline int couts(char v); + inline int couts(short v); + inline int couts(int v); + inline int couts(long v); + inline int couts(llong v); + inline int couts(uchar v); + inline int couts(ushort v); + inline int couts(uint v); + inline int couts(ulong v); + inline int couts(ullong v); + inline int couts(float v); + inline int couts(double v); + +#ifdef WINDOWS + void * hOut; + CONSOLE_SCREEN_BUFFER_INFO sbi, csbi; + CONSOLE_CURSOR_INFO curinfo; + COORD ccoord, ulcoord; + WORD dattr; + DWORD smode, written; +#else + struct termios sterm, vterm; +#endif + vector tabs; + Variable tv; + PIKbdListener * listener; + KeyFunc ret_func; + int width, height, ret, col_wid, num_format; + uint my; + uint cur_tab, col_cnt; + +}; + +#endif // PICONSOLE_H diff --git a/piethernet.cpp b/piethernet.cpp new file mode 100644 index 00000000..3f1e32cb --- /dev/null +++ b/piethernet.cpp @@ -0,0 +1,128 @@ +#include "piethernet.h" + + +PIEthernet::PIEthernet(string ip, int port, void * data_, EthernetFunc slot): PIThread() { + setPriority(piHigh); + data = data_; + ip_ = ip_s = ip; + port_ = port_s = port; + sock = sock_s = -1; + ret_func = slot; + buffer = new char[BUFFER_SIZE]; +#ifdef WINDOWS + WSADATA wsaData; + WSAStartup(MAKEWORD(2, 2), &wsaData); +#endif + sock = socket(PF_INET, SOCK_DGRAM, 0); + sock_s = socket(PF_INET, SOCK_DGRAM, 0); + if (sock == -1 || sock_s == -1) + cout << "[PIEthernet] Unable to create socket" << endl; +} + + +PIEthernet::~PIEthernet() { + if (isRunning()) { + stop(); + pthread_cancel(thread); + } + if (sock != -1) { + shutdown(sock, SHUT_RDWR); + close(sock); + } + if (sock_s != -1) { + shutdown(sock_s, SHUT_RDWR); + close(sock_s); + } +#ifdef WINDOWS + WSACleanup(); +#endif + delete buffer; +} + + +void PIEthernet::begin() { + if (!init()) stop(); +} + + +void PIEthernet::run() { +#ifdef WINDOWS + int addr_len; +#else + socklen_t addr_len; +#endif + //cout << "[PIEthernet] reading ... "; + readed = recvfrom(sock, buffer, BUFFER_SIZE, 0, (sockaddr * )&addr_, &addr_len); + //cout << WSAGetLastError() << endl; + if (readed < 0) { + //cout << "[PIEthernet] Error while reading" << endl; + //stop(); + //init(); + return; + } + if (ret_func != 0) ret_func(data, buffer); +} + + +void PIEthernet::end() { + if (sock != -1) { + shutdown(sock, SHUT_RDWR); + close(sock); + sock = -1; + } + if (sock_s != -1) { + shutdown(sock_s, SHUT_RDWR); + close(sock_s); + sock_s = -1; + } + //cout << "[PIEthernet] end" << endl; +} + + +bool PIEthernet::init() { + addr_.sin_addr.s_addr = inet_addr(ip_.c_str()); + addr_.sin_family = PF_INET; + addr_.sin_port = htons(port_); + if (bind(sock, (sockaddr * )&addr_, sizeof(addr_)) == -1) { + cout << "[PIEthernet] Cant`t bind to " << ip_ << ":" << port_ << endl; + return false; + } + return true; +} + + +bool PIEthernet::send(string ip, int port, char * data, int size) { + if (sock_s == -1) { + //cout << "[PIEthernet] Can`t send to uninitialized socket" << endl; + return false; + } + saddr_.sin_port = htons(port); + saddr_.sin_addr.s_addr = inet_addr(ip.c_str()); + saddr_.sin_family = PF_INET; + wrote = sendto(sock_s, data, size, 0, (sockaddr * )&saddr_, sizeof(saddr_)); + if (wrote != size) { + //cout << "[PIEthernet] Error while sending" << endl; + return false; + } + //cout << "[PIEthernet] Wrote " << wrote << " bytes in " << devName << endl; + return true; +} + + +bool PIEthernet::send(char * data, int size) { + if (sock_s == -1) { + //cout << "[PIEthernet] Can`t send to uninitialized socket" << endl; + return false; + } + saddr_.sin_port = htons(port_s); + saddr_.sin_addr.s_addr = inet_addr(ip_s.data()); + saddr_.sin_family = PF_INET; + //cout << "[PIEthernet] sending in " << sock_s << endl; + wrote = sendto(sock_s, data, size, 0, (sockaddr * )&saddr_, sizeof(saddr_)); + if (wrote != size) { + //cout << "[PIEthernet] Error while sending" << endl; + return false; + } + //cout << "[PIEthernet] Wrote " << wrote << " bytes" << endl; + return true; +} diff --git a/piethernet.h b/piethernet.h new file mode 100644 index 00000000..0725985e --- /dev/null +++ b/piethernet.h @@ -0,0 +1,50 @@ +#ifndef PIETHERNET_H +#define PIETHERNET_H + +#include "pithread.h" +#ifndef WINDOWS +# include +# include +# include +#else +# include +# define SHUT_RDWR SD_BOTH +#endif + +#define BUFFER_SIZE 4096 + +typedef bool (*EthernetFunc)(void * , char * ); + +class PIEthernet: public PIThread +{ +public: + // slot is any function format "bool (void*, char*)" + PIEthernet(string ip, int port, void * data, EthernetFunc slot = 0); + ~PIEthernet(); + + void setSlot(EthernetFunc func) {ret_func = func;} + void setReadAddress(string ip, int port) {ip_ = ip; port_ = port;} + void setSendAddress(string ip, int port) {ip_s = ip; port_s = port;} + + bool send(string ip, int port, char * data, int size); + bool send(char * data, int size); + bool init(); + bool initialized() const {return sock != -1;} + +private: + void begin(); + void run(); + void end(); + + + int sock, sock_s, port_, port_s, wrote; + sockaddr_in addr_, saddr_; + string ip_, ip_s; + EthernetFunc ret_func; + char * buffer; + void * data; + int readed; + +}; + +#endif // PIETHERNET_H diff --git a/pifile.cpp b/pifile.cpp new file mode 100644 index 00000000..d3e6ebcd --- /dev/null +++ b/pifile.cpp @@ -0,0 +1,57 @@ +#include "pifile.h" + + +bool PIFile::open(const string & path_, Flags mode_) { + cpath = path_; + cmode = mode_; + if (cmode[New]) { + stream.open(cpath.c_str(), fstream::in | fstream::out | fstream::trunc); + stream.close(); + cmode &= ~New; + stream.open(cpath.c_str(), (fstream::openmode)(int)cmode | fstream::binary); + } else stream.open(cpath.c_str(), (fstream::openmode)(int)cmode | fstream::binary); + return isOpened(); +} + + +string PIFile::readLine() { + char * buff = new char[4096]; + stream.getline(buff, 4096); + return string(buff); +} + + +int PIFile::size() { + int s, cp = stream.tellg(); + stream.seekg(0, fstream::end); + s = stream.tellg(); + stream.seekg(cp); + return s; +} + + +void PIFile::seek(int position) { + if (cmode[Read]) stream.seekg(position); + if (cmode[Write]) stream.seekp(position); +} + + +void PIFile::resize(int new_size, char fill_) { + int ds = new_size - size(); + if (ds == 0) return; + if (ds > 0) { + char * buff = new char[ds]; + memset(buff, fill_, ds); + stream.write(buff, ds); + delete buff; + return; + } + cout << "[PIFile] Downsize is not support yet :-(" << endl; +} + + +int PIFile::pos() { + if (cmode[Read]) return stream.tellg(); + if (cmode[Write]) return stream.tellp(); + return -1; +} diff --git a/pifile.h b/pifile.h new file mode 100644 index 00000000..70377f05 --- /dev/null +++ b/pifile.h @@ -0,0 +1,77 @@ +#ifndef PIFILE_H +#define PIFILE_H + +#include +#include "piincludes.h" + +using std::fstream; + +class PIFile +{ +public: + PIFile() {;} + enum Mode {Read = fstream::in, Write = fstream::out, Truncate = fstream::trunc, New = fstream::app}; + PIFile(const string & path, Flags mode = Read | Write) {open(path, mode);} + ~PIFile() {if (isOpened()) close();} + + bool open(const string & path, Flags mode = Read | Write); + void close() {stream.close();} + void clear() {close(); stream.open(cpath.c_str(), fstream::trunc | (fstream::openmode)(int)cmode);} + void seek(int position); + void resize(int new_size, char fill = 0); + void fill(char c) {stream.fill(c);} + void flush() {stream.flush();} + string readLine(); + + string path() const {return cpath;} + Flags mode() const {return cmode;} + int size(); + int pos(); + bool isOpened() const {return stream.is_open();} + bool isEnd() const {return stream.eof();} + + PIFile & writeData(const void * data, int size_) {stream.write((char * )data, size_); return *this;} + PIFile & readData(void * data, int size_) {stream.read((char * )data, size_); return *this;} + + PIFile & writeBinary(const char v) {stream.write((char * )&v, sizeof(v)); return *this;} + PIFile & writeBinary(const short v) {stream.write((char * )&v, sizeof(v)); return *this;} + PIFile & writeBinary(const int v) {stream.write((char * )&v, sizeof(v)); return *this;} + PIFile & writeBinary(const long v) {stream.write((char * )&v, sizeof(v)); return *this;} + PIFile & writeBinary(const uchar v) {stream.write((char * )&v, sizeof(v)); return *this;} + PIFile & writeBinary(const ushort v) {stream.write((char * )&v, sizeof(v)); return *this;} + PIFile & writeBinary(const uint v) {stream.write((char * )&v, sizeof(v)); return *this;} + PIFile & writeBinary(const ulong v) {stream.write((char * )&v, sizeof(v)); return *this;} + PIFile & writeBinary(const float v) {stream.write((char * )&v, sizeof(v)); return *this;} + PIFile & writeBinary(const double v) {stream.write((char * )&v, sizeof(v)); return *this;} + + PIFile & operator <<(const char & v) {stream.write(&v, 1); return *this;} + PIFile & operator <<(const string & v) {stream.write(v.c_str(), v.size()); return *this;} + PIFile & operator <<(const short & v) {stream << v; return *this;} + PIFile & operator <<(const int & v) {stream << v; return *this;} + PIFile & operator <<(const long & v) {stream << v; return *this;} + PIFile & operator <<(const uchar & v) {stream << v; return *this;} + PIFile & operator <<(const ushort & v) {stream << v; return *this;} + PIFile & operator <<(const uint & v) {stream << v; return *this;} + PIFile & operator <<(const ulong & v) {stream << v; return *this;} + PIFile & operator <<(const float & v) {stream << v; return *this;} + PIFile & operator <<(const double & v) {stream << v; return *this;} + + PIFile & operator >>(char & v) {stream >> v; return *this;} + PIFile & operator >>(short & v) {stream >> v; return *this;} + PIFile & operator >>(int & v) {stream >> v; return *this;} + PIFile & operator >>(long & v) {stream >> v; return *this;} + PIFile & operator >>(uchar & v) {stream >> v; return *this;} + PIFile & operator >>(ushort & v) {stream >> v; return *this;} + PIFile & operator >>(uint & v) {stream >> v; return *this;} + PIFile & operator >>(ulong & v) {stream >> v; return *this;} + PIFile & operator >>(float & v) {stream >> v; return *this;} + PIFile & operator >>(double & v) {stream >> v; return *this;} + +private: + fstream stream; + string cpath; + Flags cmode; + +}; + +#endif // PIFILE_H diff --git a/piincludes.h b/piincludes.h new file mode 100644 index 00000000..cdc471aa --- /dev/null +++ b/piincludes.h @@ -0,0 +1,112 @@ +#ifndef PIINCLUDES_H +#define PIINCLUDES_H + +#if __WIN32__ || __WIN64__ +# define WINDOWS +#endif +#if __QNX__ +# define QNX +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef WINDOWS +#include +#include +#include +#endif + +#define FOREVER for (;;) +#define FOREVER_WAIT FOREVER msleep(10); + +typedef long long llong; +typedef unsigned char uchar; +typedef unsigned short int ushort; +typedef unsigned int uint; +typedef unsigned long ulong; +typedef unsigned long long ullong; + +using std::cout; +using std::cin; +using std::endl; +using std::flush; +using std::vector; +using std::list; +using std::deque; +using std::string; + +template +class Flags { +private: + int flags; +public: + inline Flags(): flags(0) {;} + inline Flags(Enum e): flags(e) {;} + inline Flags(const Flags & f): flags(f.flags) {;} + inline Flags(const int i): flags(i) {;} + inline void operator =(const Flags & f) {flags = f.flags;} + inline void operator |=(const Flags & f) {flags = flags | f.flags;} + inline void operator |=(const Enum & e) {flags = flags | e;} + inline void operator |=(const int i) {flags = flags | i;} + inline void operator &=(const Flags & f) {flags = flags & f.flags;} + inline void operator &=(const Enum & e) {flags = flags & e;} + inline void operator &=(const int i) {flags = flags & i;} + inline Flags & operator |(Flags f) const {Flags tf(flags | f.flags); return tf;} + inline Flags & operator |(Enum e) const {Flags tf(flags | e); return tf;} + inline Flags & operator |(int i) const {Flags tf(flags | i); return tf;} + inline Flags & operator &(Flags f) const {Flags tf(flags & f.flags); return tf;} + inline Flags & operator &(Enum e) const {Flags tf(flags & e); return tf;} + inline Flags & operator &(int i) const {Flags tf(flags & i); return tf;} + inline bool operator [](Enum e) {return (flags & e) == e;} + inline operator int() const {return flags;} +}; + + +inline bool atob(const string & str) { return str == "1" ? true : false;}; +inline string btos(const bool num) { return num ? "0" : "1";}; +inline string itos(const int num) { + char ch[256]; + sprintf(ch, "%d", num); + return string(ch); }; +inline string ltos(const long num) { + char ch[256]; + sprintf(ch, "%ld", num); + return string(ch); }; +inline string uitos(const uint num) { + char ch[256]; + sprintf(ch, "%ud", num); + return string(ch); }; +inline string ultos(const ulong num) { + char ch[256]; + sprintf(ch, "%lud", num); + return string(ch); }; +inline string ftos(const float num) { + char ch[256]; + sprintf(ch, "%g", num); + return string(ch); }; +inline string dtos(const double num) { + char ch[256]; + sprintf(ch, "%g", num); + return string(ch); }; +inline string s_left(const string & str, int len) {return str.substr(0, len);}; +inline string s_right(const string & str, int len) {return str.size() < len ? str : str.substr(str.size() - len, len);}; +inline string s_trimmed(const string & str) { + int st = 0, fn = 0; + for (int i = 0; i < str.size(); ++i) + if (str[i] != ' ' && str[i] != '\t') + {st = i; break;} + for (int i = str.size() - 1; i >= 0; --i) + if (str[i] != ' ' && str[i] != '\t') + {fn = i; break;} + return str.substr(st, fn - st + 1); +}; + +#endif // PIINCLUDES_H diff --git a/pikbdlistener.cpp b/pikbdlistener.cpp new file mode 100644 index 00000000..d9e8e33b --- /dev/null +++ b/pikbdlistener.cpp @@ -0,0 +1,39 @@ +#include "pikbdlistener.h" + + +PIKbdListener::PIKbdListener(KBFunc slot, void * data_): PIThread() { + ret_func = slot; + data = data_; +#ifdef __WIN32__ + hIn = GetStdHandle(STD_INPUT_HANDLE); + GetConsoleMode(hIn, &smode); + SetConsoleMode(hIn, ENABLE_PROCESSED_INPUT); +#else + struct termios term; + tcgetattr(0, &term); + sterm = term; + term.c_lflag &= ~(ECHO | ICANON) | NOFLSH; + tcsetattr(0, TCSAFLUSH, &term); +#endif + start(); +} + + +PIKbdListener::~PIKbdListener() { +#ifdef __WIN32__ + SetConsoleMode(hIn, smode); +#else + tcsetattr(0, TCSANOW, &sterm); +#endif +} + + +void PIKbdListener::run() { +#ifdef __WIN32__ + ReadConsole(hIn, &rc, 1, &ret, 0); +#else + ret = read(0, &rc, 1); +#endif + if (ret_func != 0 && ret > 0) ret_func(data, rc); +} + diff --git a/pikbdlistener.h b/pikbdlistener.h new file mode 100644 index 00000000..f4da00bd --- /dev/null +++ b/pikbdlistener.h @@ -0,0 +1,34 @@ +#ifndef PIKBDLISTENER_H +#define PIKBDLISTENER_H + +#include "pithread.h" +#ifndef __WIN32__ +#include +#endif + +typedef void (*KBFunc)(void * , char); + +class PIKbdListener: public PIThread { +public: + // slot is any function format "void (void * , char)" + PIKbdListener(KBFunc slot = 0, void * data = 0); + ~PIKbdListener(); + +private: + void run(); + + KBFunc ret_func; + char rc; + void * data; +#ifdef __WIN32__ + DWORD ret; + void * hIn; + DWORD smode; +#else + int ret; + struct termios sterm; +#endif + +}; + +#endif // PIKBDLISTENER_H diff --git a/pimutex.h b/pimutex.h new file mode 100644 index 00000000..fe1e1118 --- /dev/null +++ b/pimutex.h @@ -0,0 +1,37 @@ +#ifndef PIMUTEX_H +#define PIMUTEX_H + +#include +#include "piincludes.h" + +class PIMutex +{ +public: + PIMutex() { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_PROCESS_SHARED); + pthread_mutex_init(&mutex, &attr); + pthread_mutexattr_destroy(&attr); + } + ~PIMutex() {pthread_mutex_destroy(&mutex);} + void lock() {pthread_mutex_lock(&mutex);} + void unlock() {pthread_mutex_unlock(&mutex);} + bool tryLock() {return (pthread_mutex_trylock(&mutex) == 0);} + +private: + pthread_mutex_t mutex; + +}; + +class PIMutexLocker +{ +public: + PIMutexLocker(PIMutex * m): mutex(m) {mutex->lock();} + PIMutexLocker(PIMutex & m): mutex(&m) {mutex->lock();} + ~PIMutexLocker() {mutex->unlock();} +private: + PIMutex * mutex; +}; + +#endif // PIMUTEX_H diff --git a/pip.kdev4 b/pip.kdev4 new file mode 100644 index 00000000..fb90c960 --- /dev/null +++ b/pip.kdev4 @@ -0,0 +1,3 @@ +[Project] +Manager=KDevCMakeManager +Name=pip diff --git a/piprotocol.cpp b/piprotocol.cpp new file mode 100644 index 00000000..935cb0c2 --- /dev/null +++ b/piprotocol.cpp @@ -0,0 +1,167 @@ +#include "piprotocol.h" + + +PIProtocol::PIProtocol(string devName, int speed, void * headerPtr, int headerSize, void * dataPtr, int dataSize) { + init(); + type = PIProtocol::Serial; + serial = new PISerial(devName, this, received); + serial->setReadData(headerPtr, headerSize, dataSize); + this->devName = devName; + this->headerPtr = (unsigned char * )headerPtr; + this->headerSize = headerSize; + this->dataPtr = (unsigned char * )dataPtr; + this->dataSize = dataSize; + packet = new char[headerSize + dataSize]; +} + + +PIProtocol::PIProtocol(string ip, int port, void * dataPtr, int dataSize) { + init(); + type = PIProtocol::Ethernet; + ether = new PIEthernet(ip, port, this, received); + this->devName = ip + ":" + itos(port); + this->dataPtr = (unsigned char * )dataPtr; + this->dataSize = dataSize; + packet = new char[dataSize]; +} + + +PIProtocol::~PIProtocol() { + delete sendtimer; + if (timer != 0) delete timer; + if (type == PIProtocol::Serial) delete serial; + if (type == PIProtocol::Ethernet) delete ether; +} + + +void PIProtocol::init() { + work = false; + net_diag = PIProtocol::Unknown; + cur_pckt = 0; + timer = 0; + sendtimer = new PITimer(this, run); + wrong_count = receive_count = send_count = 0; + immediateFreq = integralFreq = 0.f; + headerPtr = dataPtr = sendDataPtr = 0; + headerSize = dataSize = sendDataSize = 0; + exp_freq = 20.f; + devState = "Unknown"; +} + + +void PIProtocol::setExpectedFrequency(float frequency) +{ + exp_freq = frequency; + if (exp_freq < 3.33) pckt_cnt_max = 10; + else pckt_cnt_max = 3 * (int)exp_freq; + last_packets.resize(pckt_cnt_max); + timer = new PITimer(this, diag_event); + timer->start(1000. / exp_freq); + timer->reset(); +} + + +void PIProtocol::startReceive() +{ + if (type == PIProtocol::Serial) serial->start(); + if (type == PIProtocol::Ethernet) ether->start(); +} + + +void PIProtocol::stopReceive() +{ + if (type == PIProtocol::Serial) serial->stop(); + if (type == PIProtocol::Ethernet) ether->stop(); +} + + +bool PIProtocol::received(void * t, char * data) { + PIProtocol * p = (PIProtocol * )t; + memcpy(p->dataPtr, data, p->dataSize); + p->work = true; + //p->lock(); + if (p->validate()) + { + //p->unlock(); + p->receive_count++; + p->cur_pckt = 1; + return true; + } + //p->unlock(); + p->wrong_count++; + return false; +} + + +void PIProtocol::diag_event(void * t) { + PIProtocol * p = (PIProtocol * )t; + p->calc_freq(); + p->calc_diag(); + p->check_state(); +} + + +void PIProtocol::calc_diag() { + PIProtocol::Quality diag; + if (!work) { + diag = PIProtocol::Unknown; + return; + } + if (pckt_cnt < pckt_cnt_max) { + last_packets[pckt_cnt] = cur_pckt; + pckt_cnt++; + } else { + packets[last_packets.back()]--; + last_packets.pop_back(); + last_packets.push_front(cur_pckt); + } + packets[cur_pckt]++; + cur_pckt = 0; + float good_percents; + good_percents = (float)packets[1] / pckt_cnt * 100.0f; + if (good_percents == 0.0) diag = PIProtocol::Failure; + else if (good_percents <= 20.0) diag = PIProtocol::Bad; + else if (good_percents > 20.0 && good_percents <= 80.0) diag = PIProtocol::Average; + else diag = PIProtocol::Good; + if (diag != net_diag) net_diag = diag; +} + + +void PIProtocol::calc_freq() { + tf = 1000. / timer->elapsed_m(); + timer->reset(); + if (cur_pckt != 1) tf = 0.; + immediateFreq = tf; + if (last_freq.size() >= pckt_cnt_max) last_freq.pop_front(); + last_freq.push_back(tf); + tf = last_freq[0]; + for (int i = 1; i < last_freq.size(); ++i) + tf += last_freq[i]; + integralFreq = tf / last_freq.size(); +} + + +void PIProtocol::check_state() { + if (type == PIProtocol::Serial) { + if (serial->initialized()) devState = "Initialized"; + else devState = "Uninitialized"; + } + if (type == PIProtocol::Ethernet) { + if (ether->initialized()) devState = "Initialized"; + else devState = "Uninitialized"; + } +} + + + +void PIProtocol::send() { + //lock(); + memcpy(packet, sendDataPtr, sendDataSize); + //unlock(); + if (type == PIProtocol::Serial) + if (serial->send(packet, sendDataSize)) + send_count++; + if (type == PIProtocol::Ethernet) + if (ether->send(packet, sendDataSize)) + send_count++; +} diff --git a/piprotocol.h b/piprotocol.h new file mode 100644 index 00000000..8b54d176 --- /dev/null +++ b/piprotocol.h @@ -0,0 +1,78 @@ +#ifndef PIPROTOCOL_H +#define PIPROTOCOL_H + +#include "piserial.h" +#include "piethernet.h" +#include "pitimer.h" + +class PIProtocol +{ + enum Type {Serial, Ethernet}; +public: + PIProtocol(string devName, int speed, void * headerPtr, int headerSize, void * dataPtr, int dataSize); // for RS + PIProtocol(string ip, int port, void * dataPtr, int dataSize); // for Ethernet + ~PIProtocol(); + + enum Quality {Unknown = 1, Failure = 2, Bad = 3, Average = 4, Good = 5}; + + void startReceive(); // start receive + void stopReceive(); // stop receive + void startSend(float frequency = 20.f) {sendtimer->start(frequency > 0 ? 1000.f / frequency : 1000);} // start sending + void stopSend() {sendtimer->stop();} // stop sending + void setSendData(void * dataPtr, int dataSize) {sendDataPtr = (unsigned char * )dataPtr; sendDataSize = dataSize;} + void setReceiveData(void * dataPtr, int dataSize) {this->dataPtr = (unsigned char * )dataPtr; this->dataSize = dataSize;} + void setSendAddress(string ip, int port) {if (type == PIProtocol::Ethernet) ether->setReadAddress(ip, port);} // for Ethernet + void setParameters(Flags parameters) {if (type == PIProtocol::Serial) serial->setParameters(parameters);} // for RS + + void setExpectedFrequency(float frequency); // for start diagnostic connection quality + float * immediateFrequency_ptr() {return &immediateFreq;} + float * integralFrequency_ptr() {return &integralFreq;} + unsigned long long int * wrongCount_ptr() {return &wrong_count;} + unsigned long long int * receiveCount_ptr() {return &receive_count;} + unsigned long long int * sendCount_ptr() {return &send_count;} + PIProtocol::Quality * quality_ptr() {return &net_diag;} + string * deviceState_ptr() {return &devState;} + string deviceName() {return devName;} + +protected: + virtual bool validate() {return true;} // function for validate algorithm and save data from dataPtr to external struct + virtual unsigned int checksum(unsigned char * data, int size) // function for checksum + { + unsigned char c = 0; + for (int i = 0; i < size; ++i) + c += data[i]; + c = ~(c + 1); + return c; + } + virtual bool aboutSend() {return true;} // executed before send data, if return 'false' then data is not sending + + void init(); + void send(); + void check_state(); + void calc_freq(); + void calc_diag(); + static bool received(void * t, char * data); + static void diag_event(void * t); + + PISerial * serial; + PIEthernet * ether; + unsigned int dataSize, headerSize, sendDataSize; + unsigned char * dataPtr, * headerPtr, * sendDataPtr; + +private: + static void run(void * e) {PIProtocol* p = (PIProtocol*)e; if (p->aboutSend()) p->send();} + PITimer * timer, * sendtimer; + PIProtocol::Type type; + PIProtocol::Quality net_diag; + deque last_freq; + deque last_packets; + string devState, devName; + bool work; + float exp_freq, immediateFreq, integralFreq, tf; + int pckt_cnt, pckt_cnt_max, packets[2]; + char * packet; + char cur_pckt; + unsigned long long int wrong_count, receive_count, send_count; +}; + +#endif // PIPROTOCOL_H diff --git a/piserial.cpp b/piserial.cpp new file mode 100644 index 00000000..fe427fae --- /dev/null +++ b/piserial.cpp @@ -0,0 +1,245 @@ +#include "piserial.h" + + +PISerial::PISerial(string name, void * data_, SerialFunc slot): PIThread() { + setPriority(piHigh); + data = data_; + devName = name; + fd = -1; + dataSize = headerSize = 0; + headerPtr = 0; + ret_func = slot; + buffer = new char[BUFFER_SIZE]; + sbuffer = new char[BUFFER_SIZE]; +#ifdef WINDOWS + hCom = 0; +#endif + ispeed = ospeed = B115200; +} + + +PISerial::~PISerial() { + stop(); + pthread_cancel(thread); +#ifdef WINDOWS + if (fd != -1) { + SetCommState(hCom, &sdesc); + SetCommMask(hCom, mask); + CloseHandle(hCom); + } +#else + if (fd != -1) { + tcsetattr(fd, TCSANOW, &sdesc); + close(fd); + } +#endif + delete buffer; + delete sbuffer; +} + + +void PISerial::begin() { + sbuffIndex = 0; + startIndex = 0; + backIndex = 0; + tryagain = first = false; + hbuffer = new char[headerSize]; + pbuffer = new char[dataSize]; + if (!init()) stop(); +} + + +void PISerial::run() { + if (dataSize == 0) return; + char b; + int i = 0, j; +#ifdef WINDOWS + WaitCommEvent(hCom, 0, 0); + ReadFile(hCom, buffer, dataSize, &readed, 0); +#else + readed = read(fd, buffer, BUFFER_SIZE); +#endif + if (headerSize > 0) + { + while (i < readed) + { + //cout << sbuffIndex << ";" << startIndex << endl; + if (!tryagain) + { + b = buffer[i]; + sbuffer[sbuffIndex] = b; + } else { + backIndex++; + if (backIndex == headerSize + dataSize) tryagain = false; + } + if (first) + { + if (sbuffIndex-startIndex == headerSize + dataSize - 1) + { + //cout << "vsdfgvb" << endl; + memcpy(pbuffer,&sbuffer[startIndex+headerSize],dataSize); + if (ret_func(data, pbuffer)) + { + startIndex = 0; + sbuffIndex = -1; + } else { + //startIndex++; + memcpy(sbuffer, hbuffer, headerSize); + memcpy(&sbuffer[headerSize], pbuffer, dataSize); + backIndex = 0; + tryagain = true; + startIndex = 1; + sbuffIndex = -1; + } + first = false; + } + } else { + if (sbuffIndex - startIndex == headerSize - 1) + { + memcpy(hbuffer, &sbuffer[startIndex], headerSize); + for (j = 0; j < headerSize; ++j) { + if (hbuffer[j] != ((char*)headerPtr)[j]) { + startIndex++; + //cout << "no" << endl; + break; + } + } + if (j == headerSize) { + first = true; + //cout << "yes" << endl; + } + } + } + sbuffIndex++; + if (sbuffIndex >= BUFFER_SIZE) + { + if (first) + { + memcpy(pbuffer, &sbuffer[startIndex + headerSize], BUFFER_SIZE - startIndex - headerSize); + memcpy(sbuffer, hbuffer, headerSize); + memcpy(&sbuffer[headerSize], pbuffer, BUFFER_SIZE - startIndex - headerSize); + sbuffIndex = BUFFER_SIZE - startIndex - 1; + } else { + memcpy(sbuffer, hbuffer, headerSize); + sbuffIndex = headerSize - 1; + startIndex = 0; + } + } + if (!tryagain) i++; + } + } else { + for (uint i = 0; i < readed; ++i) { + b = buffer[i]; + sbuffer[sbuffIndex] = b; + if (sbuffIndex == dataSize - 1) { + if (ret_func != 0) ret_func(data, sbuffer); + sbuffIndex = -1; + } + sbuffIndex++; + } + } +} + + +void PISerial::end() { + delete pbuffer; + delete hbuffer; + if (fd == -1) return; +#ifdef WINDOWS + SetCommState(hCom, &sdesc); + CloseHandle(hCom); +#else + tcsetattr(fd, TCSANOW, &sdesc); + close(fd); +#endif + fd = -1; +} + + +bool PISerial::init() { +#ifdef WINDOWS + hCom = CreateFile(devName.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0); + if(hCom == INVALID_HANDLE_VALUE) { + cout << "[PISerial] Unable to open " << devName << endl; + return false; + } + fd = 0; + COMMTIMEOUTS times; + times.ReadIntervalTimeout = 1; + times.ReadTotalTimeoutConstant = 1; + times.ReadTotalTimeoutMultiplier = 0; + times.WriteTotalTimeoutConstant = 0; + times.WriteTotalTimeoutMultiplier = 1; + if (SetCommTimeouts(hCom, ×) == -1) { + cout << "[PISerial] Unable to set timeouts for " << devName << endl; + CloseHandle(hCom); + fd = -1; + return false; + } + GetCommMask(hCom, &mask); + SetCommMask(hCom, EV_RXCHAR); + GetCommState(hCom, &sdesc); + desc = sdesc; + desc.DCBlength = sizeof(desc); + desc.BaudRate = ispeed; + desc.ByteSize = 8; + desc.fParity = params[PISerial::IgnoreParityControl] ? 0 : 1; + desc.StopBits = params[PISerial::TwoStopBits] ? TWOSTOPBITS : ONESTOPBIT; + if (SetCommState(hCom, &desc) == -1) { + cout << "[PISerial] Unable to set comm state for " << devName << endl; + CloseHandle(hCom); + fd = -1; + return false; + } +#else + fd = open(devName.data(), O_NOCTTY | O_RDWR); + if(fd == -1) { + cout << "[PISerial] Unable to open " << devName << endl; + return false; + } + fcntl(fd, F_SETFL, 0); + + tcgetattr(fd, &desc); + sdesc = desc; + desc.c_iflag = desc.c_oflag = desc.c_lflag = 0; + desc.c_cflag = CLOCAL | CREAD | CSIZE; + if (params[PISerial::TwoStopBits]) desc.c_cflag &= CSTOPB; + if (params[PISerial::IgnoreParityControl]) desc.c_iflag &= IGNPAR ; // | INPCK | IGNBRK | IGNCR; + desc.c_cc[VMIN] = 0; + desc.c_cc[VTIME] = 1; + + cfsetispeed(&desc, ispeed); + cfsetospeed(&desc, ospeed); + + if(tcsetattr(fd, TCSANOW, &desc) < 0) { + cout << "[PISerial] Can`t set attributes for " << devName << endl; + close(fd); + return false; + } + tcflush(fd, TCIOFLUSH); + //cout << "[PISerial] Initialized " << devName << endl; +#endif + return true; +} + + +bool PISerial::send(char * data, int size) { + //cout << "[PISerial] send size: " << sizeof(data) << endl; + if (fd == -1) { + //cout << "[PISerial] Can`t write to uninitialized COM" << endl; + return false; + } +#ifdef WINDOWS + DWORD wrote; + WriteFile(hCom, data, size, &wrote, 0); +#else + int wrote; + wrote = write(fd, data, size); +#endif + if ((int)wrote != size) { + //cout << "[PISerial] Error while sending" << endl; + return false; + } + //cout << "[PISerial] Wrote " << wrote << " bytes in " << devName << endl; + return true; +} diff --git a/piserial.h b/piserial.h new file mode 100644 index 00000000..c67a68d1 --- /dev/null +++ b/piserial.h @@ -0,0 +1,75 @@ +#ifndef PISERIAL_H +#define PISERIAL_H + +#include "pithread.h" +#ifndef WINDOWS +#include +#include +#else +#define B110 110 +#define B300 300 +#define B600 600 +#define B1200 1200 +#define B2400 2400 +#define B4800 4800 +#define B9600 9600 +#define B14400 14400 +#define B19200 19200 +#define B38400 38400 +#define B57600 57600 +#define B115200 115200 +#define B128000 128000 +#define B256000 256000 +#endif + +#define BUFFER_SIZE 4096 + +typedef bool (*SerialFunc)(void * , char * ); + +class PISerial: public PIThread +{ +public: + // slot is any function format "bool (void*, char*)" + PISerial(string name, void * data, SerialFunc slot = 0); + ~PISerial(); + + enum Parameters {IgnoreParityControl = 0x01, TwoStopBits = 0x02}; + + void setSlot(SerialFunc func) {ret_func = func;} + void setSpeed(int speed) {ospeed = ispeed = speed;} + void setOutSpeed(int speed) {ospeed = speed;} + void setInSpeed(int speed) {ispeed = speed;} + void setParameters(Flags parameters) {params = parameters;} + void setReadData(void * headerPtr, int headerSize, int dataSize) {this->headerPtr = headerPtr; + this->headerSize = headerSize; + this->dataSize = dataSize;} + + bool send(char * data, int size); + bool init(); + bool initialized() const {return fd != -1;} + +private: + void begin(); + void run(); + void end(); + +#ifdef WINDOWS + DCB desc, sdesc; + void * hCom; + DWORD readed, mask; +#else + termios desc, sdesc; + int readed; +#endif + int fd, ospeed, ispeed; + string devName; + SerialFunc ret_func; + char * buffer, * sbuffer, * hbuffer, * pbuffer; + void * headerPtr, * data; + int dataSize, headerSize, sbuffIndex, startIndex, backIndex; + Flags params; + bool first, tryagain; + +}; + +#endif // PISERIAL_H diff --git a/pithread.cpp b/pithread.cpp new file mode 100644 index 00000000..9483def5 --- /dev/null +++ b/pithread.cpp @@ -0,0 +1,61 @@ +#include "pithread.h" + + +PIThread::PIThread(bool startNow, int timer_delay) { + running = lockRun = false; + priority_ = piNormal; + timer = timer_delay; + if (startNow) start(timer_delay); +} + + +PIThread::~PIThread() { + if (!running) return; + pthread_cancel(thread); +} + + +bool PIThread::start(int timer_delay) { + pthread_attr_t attr; + terminating = false; + timer = timer_delay; + pthread_attr_init(&attr); + pthread_attr_setschedparam(&attr, &sparam); + if (pthread_create(&thread, &attr, thread_function, this) == 0) { + running = true; + return true; + } + return false; +} + + +void * PIThread::thread_function(void * t) { + PIThread * ct = (PIThread * )t; + ct->begin(); + while (!ct->terminating) { + if (ct->lockRun) ct->mutex_.lock(); + ct->run(); + if (ct->lockRun) ct->mutex_.unlock();; + if (ct->timer > 0) msleep(ct->timer); + } + ct->end(); + ct->running = false; + //cout << "thread " << t << " exiting ... " << endl; + pthread_exit(0); + return 0; +} + + +void PIThread::setPriority(PIThread::Priority prior) { + priority_ = prior; +#if __QNX__ || __WIN32__ + sparam.sched_priority = (int)priority_; +#else + sparam.__sched_priority = (int)priority_; +#endif + if (!running) return; + pthread_getschedparam(thread, &policy, &sparam); + pthread_setschedparam(thread, policy, &sparam); +} + + diff --git a/pithread.h b/pithread.h new file mode 100644 index 00000000..c491cdb2 --- /dev/null +++ b/pithread.h @@ -0,0 +1,61 @@ +#ifndef PITHREAD_H +#define PITHREAD_H + +#include +#include "piincludes.h" +#include "pimutex.h" + +#ifdef WINDOWS + inline void msleep(int msecs) {Sleep(msecs);} +#else + inline void msleep(int msecs) {usleep(msecs * 1000);} +#endif + +class PIThread { +public: + PIThread(bool startNow = false, int timer_delay = -1); + ~PIThread(); + +#ifdef QNX + enum Priority {piHighest = 12, + piHigh = 11, + piNormal = 10, + piLow = 9, + piLowerst = 8 }; +#else + enum Priority {piHighest = -2, + piHigh = -1, + piNormal = 0, + piLow = 1, + piLowerst = 2 }; +#endif + + bool start(int timer_delay = -1); + void stop() {terminating = true;} + void setPriority(PIThread::Priority prior); + PIThread::Priority priority() const {return priority_;} + bool isRunning() const {return running;} + void waitForFinish() {while (running) msleep(1);} + void needLockRun(bool need) {lockRun = need;} + void lock() {mutex_.lock();;} + void unlock() {mutex_.unlock();} + PIMutex & mutex() {return mutex_;} + +private: + virtual void begin() {;} // executed at start + virtual void run() {;} // main loop + virtual void end() {;} // executed at finish + +protected: + static void * thread_function(void * t); + + volatile bool terminating, running, lockRun; + int timer, policy; + pthread_t thread; + PIMutex mutex_; + sched_param sparam; + PIThread::Priority priority_; + +}; + +#endif // PITHREAD_H diff --git a/pitimer.cpp b/pitimer.cpp new file mode 100644 index 00000000..c2e06569 --- /dev/null +++ b/pitimer.cpp @@ -0,0 +1,128 @@ +#include "pitimer.h" + + +PITimer::PITimer(void * data_, TimerEvent slot) { + ret_func = slot; + data = data_; +#ifndef __WIN32__ + ti = -1; + running = false; + se.sigev_notify = SIGEV_THREAD; + se.sigev_value.sival_ptr = this; + se.sigev_notify_function = timer_event; + se.sigev_notify_attributes = 0; +#endif + reset(); +} + + +#ifndef __WIN32__ +void PITimer::start(double msecs) { + spec.it_interval.tv_nsec = ((int)(msecs * 1000) % 1000000) * 1000; + spec.it_interval.tv_sec = (time_t)(msecs / 1000); + spec.it_value = spec.it_interval; + ti = timer_create(CLOCK_REALTIME, &se, &timer); + timer_settime(timer, 0, &spec, 0); + running = true; +} + + +void PITimer::timer_event(sigval e) { + PITimer * ct = (PITimer * )e.sival_ptr; + if (ct->ret_func != 0) ct->ret_func(ct->data); +} +#endif + + +double PITimer::elapsed_n() { +#ifdef __WIN32__ + t_cur = GetCurrentTime(); + return (t_cur * 1000000. - t_st * 1000000.); +#else + clock_gettime(0, &t_cur); + return (t_cur.tv_sec * 1.e+9 + t_cur.tv_nsec) - + (t_st.tv_sec * 1.e+9 + t_st.tv_nsec); +#endif +} + + +double PITimer::elapsed_u() { +#ifdef __WIN32__ + t_cur = GetCurrentTime(); + return (t_cur * 1000. - t_st * 1000.); +#else + clock_gettime(0, &t_cur); + return (t_cur.tv_sec * 1.e+6 + (t_cur.tv_nsec / 1.e+3)) - + (t_st.tv_sec * 1.e+6 + (t_st.tv_nsec / 1.e+3)); +#endif +} + + +double PITimer::elapsed_m() { +#ifdef __WIN32__ + t_cur = GetCurrentTime(); + return (double)(t_cur - t_st); +#else + clock_gettime(0, &t_cur); + return (t_cur.tv_sec * 1.e+3 + (t_cur.tv_nsec / 1.e+6)) - + (t_st.tv_sec * 1.e+3 + (t_st.tv_nsec / 1.e+6)); +#endif +} + + +double PITimer::elapsed_s() { +#ifdef __WIN32__ + t_cur = GetCurrentTime(); + return (t_cur / 1000. - t_st / 1000.); +#else + clock_gettime(0, &t_cur); + return (t_cur.tv_sec + (t_cur.tv_nsec / 1.e+9)) - + (t_st.tv_sec + (t_st.tv_nsec / 1.e+9)); +#endif +} + + +PITime currentTime() { + time_t rt = time(0); + tm * pt = localtime(&rt); + PITime t; + t.seconds = pt->tm_sec; + t.minutes = pt->tm_min; + t.hours = pt->tm_hour; + return t; +} + + +PIDate currentDate() { + time_t rt = time(0); + tm * pt = localtime(&rt); + PIDate d; + d.day = pt->tm_mday; + d.month = pt->tm_mon + 1; + d.year = pt->tm_year + 1900; + return d; +} + + +string time2string(const PITime & time, const string & format) { + string ts = format; + int i = ts.find_first_of('h'); + if (i >= 0) ts = ts.replace(i, 1, itos(time.hours)); + i = ts.find_first_of('m'); + if (i >= 0) ts = ts.replace(i, 1, itos(time.minutes)); + i = ts.find_first_of('s'); + if (i >= 0) ts = ts.replace(i, 1, itos(time.seconds)); + return ts; +} + + +string date2string(const PIDate & date, const string & format) { + string ts = format; + int i = ts.find_first_of('y'); + if (i >= 0) ts = ts.replace(i, 1, itos(date.year)); + i = ts.find_first_of('m'); + if (i >= 0) ts = ts.replace(i, 1, itos(date.month)); + i = ts.find_first_of('d'); + if (i >= 0) ts = ts.replace(i, 1, itos(date.day)); + return ts; +} diff --git a/pitimer.h b/pitimer.h new file mode 100644 index 00000000..6b8dfdad --- /dev/null +++ b/pitimer.h @@ -0,0 +1,69 @@ +#ifndef PITIMER_H +#define PITIMER_H + +#include +#include +#include "pithread.h" + +typedef void (*TimerEvent)(void * ); + +struct PITime { + int seconds; + int minutes; + int hours; +}; + +struct PIDate { + int day; + int month; + int year; // since 1900 +}; + +class PITimer +#ifdef __WIN32__ +: public PIThread +#endif +{ +public: + PITimer(void * data = 0, TimerEvent slot = 0); + ~PITimer() {stop();} +#ifdef __WIN32__ + void reset() {t_st = GetCurrentTime();} +#else + void reset() {clock_gettime(0, &t_st);} + void start(double msecs); + void stop() {if (ti == 0) timer_delete(timer); ti = -1; running = false;} + bool isRunning() const {return running;} +#endif + double elapsed_n(); // nanoseconds + double elapsed_u(); // microseconds + double elapsed_m(); // miliseconds + double elapsed_s(); // seconds + +private: +#ifdef __WIN32__ + void run() {if (ret_func != 0) ret_func(data);} + + long int t_st, t_cur; +#else + static void timer_event(sigval e); + + bool running; + int ti; + itimerspec spec; + timespec t_st, t_cur; + timer_t timer; + sigevent se; +#endif + + void * data; + TimerEvent ret_func; + +}; + +PITime currentTime(); +PIDate currentDate(); +string time2string(const PITime & time, const string & format = "h:m:s"); +string date2string(const PIDate & date, const string & format = "d.m.y"); + +#endif // PITIMER_H