commit 2925e4d78611aa5222a864e2240fbad9183b4387 Author: peri4 Date: Tue Nov 30 08:11:27 2010 +0300 30.11.2010 - initial commit 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