From a57a78adeef5d8ebd713f5ab4f395e7c977f7414 Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Thu, 10 Mar 2022 12:19:52 +0300 Subject: [PATCH] remove deprecated code --- {MMPP_lib => MMPP:lib}/99-edmund_hsfw.rules | 0 {MMPP_lib => MMPP:lib}/CMake.readme | 0 {MMPP_lib => MMPP:lib}/CMakeLists.txt | 0 {MMPP_lib => MMPP:lib}/Readme.md | 0 {MMPP_lib => MMPP:lib}/common.h | 0 .../examples/CMakeLists.txt | 0 {MMPP_lib => MMPP:lib}/examples/template.c | 0 .../examples/templatecmdlnopts.c | 0 .../examples/templatecmdlnopts.h | 0 {MMPP_lib => MMPP:lib}/examples/tm.c | 0 {MMPP_lib => MMPP:lib}/examples/tmcmdlnopts.c | 0 {MMPP_lib => MMPP:lib}/examples/tmcmdlnopts.h | 0 {MMPP_lib => MMPP:lib}/examples/wheels.c | 0 .../examples/wheelscmdlnopts.c | 0 .../examples/wheelscmdlnopts.h | 0 {MMPP_lib => MMPP:lib}/hidmanage.c | 0 {MMPP_lib => MMPP:lib}/hsfw.h | 0 {MMPP_lib => MMPP:lib}/libmmpp.c | 0 {MMPP_lib => MMPP:lib}/libmmpp.h | 0 {MMPP_lib => MMPP:lib}/mmpp.pc.in | 0 {MMPP_lib => MMPP:lib}/tty_procs.c | 0 {MMPP_lib => MMPP:lib}/tty_procs.h | 0 MMPP_control/{new => }/MMPP_control.c.tags | 0 MMPP_control/{new => }/MMPP_control.config | 0 MMPP_control/{new => }/MMPP_control.creator | 0 .../{new => }/MMPP_control.creator.user | 0 MMPP_control/{new => }/MMPP_control.files | 0 MMPP_control/{new => }/MMPP_control.includes | 0 MMPP_control/Makefile | 3 +- MMPP_control/Readme | 1 - MMPP_control/{new => }/Readme.md | 0 MMPP_control/cmdlnopts.c | 38 +- MMPP_control/cmdlnopts.h | 15 +- MMPP_control/main.c | 180 +++--- MMPP_control/new/Makefile | 44 -- MMPP_control/new/cmdlnopts.c | 111 ---- MMPP_control/new/cmdlnopts.h | 57 -- MMPP_control/new/main.c | 203 ------- MMPP_control/new/tty_procs.c | 536 ------------------ MMPP_control/new/tty_procs.h | 54 -- MMPP_control/parseargs.c | 497 ---------------- MMPP_control/parseargs.h | 124 ---- MMPP_control/tty_procs.c | 324 ++++++++--- MMPP_control/tty_procs.h | 31 +- MMPP_control/usefull_macros.c | 372 ------------ MMPP_control/usefull_macros.h | 141 ----- STM32/inc/gen042 | 0 STM32/steppers/main.c | 7 +- STM32/steppers/steppers.bin | Bin electronics/fp-info-cache | 1 + ...l_and_usb_pcb.pdf => hall_and_usb:pcb.pdf} | Bin electronics/steppers.pro | 12 +- 52 files changed, 428 insertions(+), 2323 deletions(-) rename {MMPP_lib => MMPP:lib}/99-edmund_hsfw.rules (100%) rename {MMPP_lib => MMPP:lib}/CMake.readme (100%) rename {MMPP_lib => MMPP:lib}/CMakeLists.txt (100%) rename {MMPP_lib => MMPP:lib}/Readme.md (100%) rename {MMPP_lib => MMPP:lib}/common.h (100%) rename {MMPP_lib => MMPP:lib}/examples/CMakeLists.txt (100%) rename {MMPP_lib => MMPP:lib}/examples/template.c (100%) rename {MMPP_lib => MMPP:lib}/examples/templatecmdlnopts.c (100%) rename {MMPP_lib => MMPP:lib}/examples/templatecmdlnopts.h (100%) rename {MMPP_lib => MMPP:lib}/examples/tm.c (100%) rename {MMPP_lib => MMPP:lib}/examples/tmcmdlnopts.c (100%) rename {MMPP_lib => MMPP:lib}/examples/tmcmdlnopts.h (100%) rename {MMPP_lib => MMPP:lib}/examples/wheels.c (100%) rename {MMPP_lib => MMPP:lib}/examples/wheelscmdlnopts.c (100%) rename {MMPP_lib => MMPP:lib}/examples/wheelscmdlnopts.h (100%) rename {MMPP_lib => MMPP:lib}/hidmanage.c (100%) rename {MMPP_lib => MMPP:lib}/hsfw.h (100%) rename {MMPP_lib => MMPP:lib}/libmmpp.c (100%) rename {MMPP_lib => MMPP:lib}/libmmpp.h (100%) rename {MMPP_lib => MMPP:lib}/mmpp.pc.in (100%) rename {MMPP_lib => MMPP:lib}/tty_procs.c (100%) rename {MMPP_lib => MMPP:lib}/tty_procs.h (100%) rename MMPP_control/{new => }/MMPP_control.c.tags (100%) rename MMPP_control/{new => }/MMPP_control.config (100%) rename MMPP_control/{new => }/MMPP_control.creator (100%) rename MMPP_control/{new => }/MMPP_control.creator.user (100%) rename MMPP_control/{new => }/MMPP_control.files (100%) rename MMPP_control/{new => }/MMPP_control.includes (100%) delete mode 100644 MMPP_control/Readme rename MMPP_control/{new => }/Readme.md (100%) delete mode 100644 MMPP_control/new/Makefile delete mode 100644 MMPP_control/new/cmdlnopts.c delete mode 100644 MMPP_control/new/cmdlnopts.h delete mode 100644 MMPP_control/new/main.c delete mode 100644 MMPP_control/new/tty_procs.c delete mode 100644 MMPP_control/new/tty_procs.h delete mode 100644 MMPP_control/parseargs.c delete mode 100644 MMPP_control/parseargs.h delete mode 100644 MMPP_control/usefull_macros.c delete mode 100644 MMPP_control/usefull_macros.h mode change 100755 => 100644 STM32/inc/gen042 mode change 100755 => 100644 STM32/steppers/steppers.bin create mode 100644 electronics/fp-info-cache rename electronics/{hall_and_usb_pcb.pdf => hall_and_usb:pcb.pdf} (100%) diff --git a/MMPP_lib/99-edmund_hsfw.rules b/MMPP:lib/99-edmund_hsfw.rules similarity index 100% rename from MMPP_lib/99-edmund_hsfw.rules rename to MMPP:lib/99-edmund_hsfw.rules diff --git a/MMPP_lib/CMake.readme b/MMPP:lib/CMake.readme similarity index 100% rename from MMPP_lib/CMake.readme rename to MMPP:lib/CMake.readme diff --git a/MMPP_lib/CMakeLists.txt b/MMPP:lib/CMakeLists.txt similarity index 100% rename from MMPP_lib/CMakeLists.txt rename to MMPP:lib/CMakeLists.txt diff --git a/MMPP_lib/Readme.md b/MMPP:lib/Readme.md similarity index 100% rename from MMPP_lib/Readme.md rename to MMPP:lib/Readme.md diff --git a/MMPP_lib/common.h b/MMPP:lib/common.h similarity index 100% rename from MMPP_lib/common.h rename to MMPP:lib/common.h diff --git a/MMPP_lib/examples/CMakeLists.txt b/MMPP:lib/examples/CMakeLists.txt similarity index 100% rename from MMPP_lib/examples/CMakeLists.txt rename to MMPP:lib/examples/CMakeLists.txt diff --git a/MMPP_lib/examples/template.c b/MMPP:lib/examples/template.c similarity index 100% rename from MMPP_lib/examples/template.c rename to MMPP:lib/examples/template.c diff --git a/MMPP_lib/examples/templatecmdlnopts.c b/MMPP:lib/examples/templatecmdlnopts.c similarity index 100% rename from MMPP_lib/examples/templatecmdlnopts.c rename to MMPP:lib/examples/templatecmdlnopts.c diff --git a/MMPP_lib/examples/templatecmdlnopts.h b/MMPP:lib/examples/templatecmdlnopts.h similarity index 100% rename from MMPP_lib/examples/templatecmdlnopts.h rename to MMPP:lib/examples/templatecmdlnopts.h diff --git a/MMPP_lib/examples/tm.c b/MMPP:lib/examples/tm.c similarity index 100% rename from MMPP_lib/examples/tm.c rename to MMPP:lib/examples/tm.c diff --git a/MMPP_lib/examples/tmcmdlnopts.c b/MMPP:lib/examples/tmcmdlnopts.c similarity index 100% rename from MMPP_lib/examples/tmcmdlnopts.c rename to MMPP:lib/examples/tmcmdlnopts.c diff --git a/MMPP_lib/examples/tmcmdlnopts.h b/MMPP:lib/examples/tmcmdlnopts.h similarity index 100% rename from MMPP_lib/examples/tmcmdlnopts.h rename to MMPP:lib/examples/tmcmdlnopts.h diff --git a/MMPP_lib/examples/wheels.c b/MMPP:lib/examples/wheels.c similarity index 100% rename from MMPP_lib/examples/wheels.c rename to MMPP:lib/examples/wheels.c diff --git a/MMPP_lib/examples/wheelscmdlnopts.c b/MMPP:lib/examples/wheelscmdlnopts.c similarity index 100% rename from MMPP_lib/examples/wheelscmdlnopts.c rename to MMPP:lib/examples/wheelscmdlnopts.c diff --git a/MMPP_lib/examples/wheelscmdlnopts.h b/MMPP:lib/examples/wheelscmdlnopts.h similarity index 100% rename from MMPP_lib/examples/wheelscmdlnopts.h rename to MMPP:lib/examples/wheelscmdlnopts.h diff --git a/MMPP_lib/hidmanage.c b/MMPP:lib/hidmanage.c similarity index 100% rename from MMPP_lib/hidmanage.c rename to MMPP:lib/hidmanage.c diff --git a/MMPP_lib/hsfw.h b/MMPP:lib/hsfw.h similarity index 100% rename from MMPP_lib/hsfw.h rename to MMPP:lib/hsfw.h diff --git a/MMPP_lib/libmmpp.c b/MMPP:lib/libmmpp.c similarity index 100% rename from MMPP_lib/libmmpp.c rename to MMPP:lib/libmmpp.c diff --git a/MMPP_lib/libmmpp.h b/MMPP:lib/libmmpp.h similarity index 100% rename from MMPP_lib/libmmpp.h rename to MMPP:lib/libmmpp.h diff --git a/MMPP_lib/mmpp.pc.in b/MMPP:lib/mmpp.pc.in similarity index 100% rename from MMPP_lib/mmpp.pc.in rename to MMPP:lib/mmpp.pc.in diff --git a/MMPP_lib/tty_procs.c b/MMPP:lib/tty_procs.c similarity index 100% rename from MMPP_lib/tty_procs.c rename to MMPP:lib/tty_procs.c diff --git a/MMPP_lib/tty_procs.h b/MMPP:lib/tty_procs.h similarity index 100% rename from MMPP_lib/tty_procs.h rename to MMPP:lib/tty_procs.h diff --git a/MMPP_control/new/MMPP_control.c.tags b/MMPP_control/MMPP_control.c.tags similarity index 100% rename from MMPP_control/new/MMPP_control.c.tags rename to MMPP_control/MMPP_control.c.tags diff --git a/MMPP_control/new/MMPP_control.config b/MMPP_control/MMPP_control.config similarity index 100% rename from MMPP_control/new/MMPP_control.config rename to MMPP_control/MMPP_control.config diff --git a/MMPP_control/new/MMPP_control.creator b/MMPP_control/MMPP_control.creator similarity index 100% rename from MMPP_control/new/MMPP_control.creator rename to MMPP_control/MMPP_control.creator diff --git a/MMPP_control/new/MMPP_control.creator.user b/MMPP_control/MMPP_control.creator.user similarity index 100% rename from MMPP_control/new/MMPP_control.creator.user rename to MMPP_control/MMPP_control.creator.user diff --git a/MMPP_control/new/MMPP_control.files b/MMPP_control/MMPP_control.files similarity index 100% rename from MMPP_control/new/MMPP_control.files rename to MMPP_control/MMPP_control.files diff --git a/MMPP_control/new/MMPP_control.includes b/MMPP_control/MMPP_control.includes similarity index 100% rename from MMPP_control/new/MMPP_control.includes rename to MMPP_control/MMPP_control.includes diff --git a/MMPP_control/Makefile b/MMPP_control/Makefile index 45b0a02..3e46add 100644 --- a/MMPP_control/Makefile +++ b/MMPP_control/Makefile @@ -1,8 +1,9 @@ # run `make DEF=...` to add extra defines PROGRAM := MMPP_control LDFLAGS := -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,--discard-all +LDFLAGS += -lusefull_macros SRCS := $(wildcard *.c) -DEFINES := $(DEF) -DBAUD_RATE=B115200 -D_GNU_SOURCE -D_XOPEN_SOURCE=1111 +DEFINES := $(DEF) -DBAUD_RATE=9600 -D_GNU_SOURCE -D_XOPEN_SOURCE=1111 #DEFINES += -DEBUG OBJDIR := mk CFLAGS += -O2 -Wall -Werror -Wextra -Wno-trampolines -std=gnu99 diff --git a/MMPP_control/Readme b/MMPP_control/Readme deleted file mode 100644 index 874aff6..0000000 --- a/MMPP_control/Readme +++ /dev/null @@ -1 +0,0 @@ -Simple CLI control tool allowing bash scripting \ No newline at end of file diff --git a/MMPP_control/new/Readme.md b/MMPP_control/Readme.md similarity index 100% rename from MMPP_control/new/Readme.md rename to MMPP_control/Readme.md diff --git a/MMPP_control/cmdlnopts.c b/MMPP_control/cmdlnopts.c index bc852ad..7899f8e 100644 --- a/MMPP_control/cmdlnopts.c +++ b/MMPP_control/cmdlnopts.c @@ -18,14 +18,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ + +#include "cmdlnopts.h" #include +#include +#include #include #include #include -#include -#include -#include "cmdlnopts.h" -#include "usefull_macros.h" /* * here are global parameters initialisation @@ -40,6 +40,8 @@ int quiet = 0; // less messages @ stdout glob_pars const Gdefault = { .showtemp = 0 ,.comdev = "/dev/ttyUSB0" + ,.pidfile = "/tmp/MMPP_control.pid" + ,.speed = BAUD_RATE ,.rot1angle = -1000. ,.rot2angle = -1000. ,.l1steps = INT_MAX @@ -50,20 +52,23 @@ glob_pars const Gdefault = { * Define command line options by filling structure: * name has_arg flag val type argptr help */ -myoption cmdlnopts[] = { +static myoption cmdlnopts[] = { {"help", NO_ARGS, NULL, 'h', arg_none, APTR(&help), N_("show this help")}, {"quiet", NO_ARGS, NULL, 'q', arg_none, APTR(&quiet), N_("don't show anything @screen from stdout")}, + {"absmove", NO_ARGS, NULL, 'A', arg_none, APTR(&G.absmove), N_("absolute move (without this flag moving is relative)")}, {"temp", NO_ARGS, NULL, 't', arg_none, APTR(&G.showtemp), N_("show temperature of both MCU")}, {"comdev", NEED_ARG, NULL, 'd', arg_string, APTR(&G.comdev), N_("terminal device filename")}, {"sendraw", NEED_ARG, NULL, 'a', arg_string, APTR(&G.sendraw), N_("send RAW string to port and read the answer")}, + {"reset", MULT_PAR, NULL, 'E', arg_int, APTR(&G.reset), N_("reset given mcu (may be included several times)")}, {"rot1", NEED_ARG, NULL, 'R', arg_double, APTR(&G.rot1angle), N_("rotate polaroid to given angle")}, {"rot2", NEED_ARG, NULL, 'r', arg_double, APTR(&G.rot2angle), N_("rotate lambda/4 to given angle")}, {"status", NO_ARGS, NULL, 's', arg_none, APTR(&G.getstatus), N_("get device status")}, - {"wait", NO_ARGS, NULL, 'w', arg_none, APTR(&G.waitold), N_("wait while all moving ends")}, - {"async", NO_ARGS, NULL, 'y', arg_none, APTR(&G.dontwait), N_("asyncronous moving - don't wait")}, - {"lin1", NEED_ARG, NULL, 'L', arg_int, APTR(&G.l1steps), N_("move linear stage 1 (polaroid) to N steps")}, - {"lin2", NEED_ARG, NULL, 'l', arg_int, APTR(&G.l2steps), N_("move linear stage 2 (L/4) to N steps")}, - {"absmove", NO_ARGS, NULL, 'A', arg_none, APTR(&G.absmove), N_("absolute move (without this flag moving is relative)")}, + {"baudrate",NEED_ARG, NULL, 'b', arg_int, APTR(&G.speed), N_("TTY baudrate")}, + {"wait", NO_ARGS, NULL, 'w', arg_none, APTR(&G.waitold), N_("wait while all previous moving ends")}, + {"async", NO_ARGS, NULL, 'y', arg_none, APTR(&G.dontwait), N_("asynchronous moving - don't wait")}, + {"lin1", NEED_ARG, NULL, 'L', arg_int, APTR(&G.l1steps), N_("move polaroid linear stage to N steps")}, + {"lin2", NEED_ARG, NULL, 'l', arg_int, APTR(&G.l2steps), N_("move wave-plate linear stage to N steps")}, + {"pidfile", NEED_ARG, NULL, 'p', arg_string, APTR(&G.pidfile), N_("PID-file name")}, {"stop", NO_ARGS, NULL, 'S', arg_none, APTR(&G.stopall), N_("stop any moving")}, end_option }; @@ -91,3 +96,16 @@ glob_pars *parse_args(int argc, char **argv){ return &G; } +/** + * @brief MSG show coloured message if `quiet` not set + * !! This function adds trailing '\n' to message + * @param s1 - green part of message (may be null) + * @param s2 - normal colored part of messate (may be null) + */ +void MSG(const char *s1, const char *s2){ + if(quiet) return; + if(s1){ + green("%s%s", s1, s2 ? ": " : "\n"); + } + if(s2) printf("%s\n", s2); +} diff --git a/MMPP_control/cmdlnopts.h b/MMPP_control/cmdlnopts.h index ed6019b..671c15e 100644 --- a/MMPP_control/cmdlnopts.h +++ b/MMPP_control/cmdlnopts.h @@ -20,10 +20,11 @@ */ #pragma once -#ifndef __CMDLNOPTS_H__ -#define __CMDLNOPTS_H__ +#ifndef CMDLNOPTS_H__ +#define CMDLNOPTS_H__ -#include "parseargs.h" +#include +#include /* * here are some typedef's for global data @@ -32,8 +33,10 @@ typedef struct{ int showtemp; // show temperatures of both MCU char *comdev; // TTY device char *sendraw; // send RAW string + char *pidfile; // pid file name double rot1angle; // rotator 1 angle double rot2angle; // rotator 2 angle + int speed; // TTY speed int getstatus; // get both MCU status int waitold; // wait for previous moving ends int dontwait; // don't wait for moving end @@ -41,12 +44,14 @@ typedef struct{ int l2steps; // move linear stage 2 (L/4) for N steps int absmove; // absolute move (to given position from zero-esw) int stopall; // stop all moving + int **reset; // reset given MCU's } glob_pars; - // default & global parameters extern glob_pars const Gdefault; extern int quiet; glob_pars *parse_args(int argc, char **argv); -#endif // __CMDLNOPTS_H__ +void MSG(const char *s1, const char *s2); + +#endif // CMDLNOPTS_H__ diff --git a/MMPP_control/main.c b/MMPP_control/main.c index 47d5b62..6faf006 100644 --- a/MMPP_control/main.c +++ b/MMPP_control/main.c @@ -21,27 +21,48 @@ * */ -#include "usefull_macros.h" #include "cmdlnopts.h" -#include "tty_procs.h" #include "signal.h" +#include "tty_procs.h" +#include +#include +#include + +// All return states of main(): +enum{ + RET_ALLOK = 0, + RET_NOTFOUND, // none of MCU found or didn't found seeking MCU + RET_ONLYONE, // only one MCU found + RET_COMMERR, // communication error + RET_CANTINIT, // can't init motors: error during initiation or some of motors are moving + RET_WAITERR, // error occured during waiting procedure + RET_ERROR = 9, // uncoverable error - from libsnippets + RET_HELPCALL = 255 // user call help (or give wrong parameter[s]) - from libsnippets +}; static glob_pars *G; -void signals(int signo){ - restore_tty(); - exit(signo); +/** + * We REDEFINE the default WEAK function of signal processing + */ +void __attribute__((noreturn)) signals(int sig){ + if(sig){ + signal(sig, SIG_IGN); + DBG("Get signal %d, quit.\n", sig); + } + if(G->pidfile) // remove unnesessary PID file + unlink(G->pidfile); + restore_console(); + tty_close(); + exit(sig); } -static void MSG(const char *s1, const char *s2){ - DBG("%s: %s", s1, s2); - if(quiet) return; - if(s1) green("%s: ", s1); - if(s2) printf("%s\n", s2); +void __attribute__((noreturn)) iffound_default(pid_t pid){ + ERRX("Another copy of this process found, pid=%d. Exit.", pid); } static double convangle(double val){ - int X = val / 360.; + int X = (int)(val / 360.); val -= 360. * (double)X; return val; } @@ -49,50 +70,42 @@ static double convangle(double val){ /** * @return 1 if motor start moving else return 0 */ -static int parsemotans(int ans, const char *prefix){ - if(ans == 0) return 1; - else if(ans == -1) WARNX(_("%s moving error!"), prefix); - else if(ans == 1) WARNX(_("%s is on end-switch and can't move further"), prefix); - else if(ans == 2) WARNX(_("Can't move %s: bad steps amount or still moving"), prefix); +static int parsemotans(ttysend_status ans, const char *prefix){ + DBG("parse ans: %d (prefix: %s)", ans, prefix); + if(ans == SEND_ALLOK) return 1; + else if(ans == SEND_ERR) WARNX(_("%s moving error!"), prefix); + else if(ans == SEND_ESWITCH) WARNX(_("%s is on end-switch and can't move further"), prefix); + else if(ans == SEND_OTHER) WARNX(_("Can't move %s: bad steps amount or still moving"), prefix); return 0; } /** * move motor - * @return waitforstop value + * @return 0 if motor can't move, else return 1 */ -int movemotor(int mcu, int motnum, int steps, const char *name){ +/** + * @brief movemotor - move motor + * @param mcu - MCU# (controller No, 1 or 2) + * @param motnum - motor# (0 or 1) + * @param steps - steps amount ( + * @param name + * @return 0 if motor can't move, else return 1 + */ +static int movemotor(int mcu, int motnum, int steps, const char *name){ char buf[32]; int curpos = mot_getpos(mcu, motnum); if(curpos == INT_MIN){ WARNX(_("Can't get current %s position"), name); return 0; } + if(curpos < 0){ // need to init + WARNX(_("Init of %s failed"), name); + return 0; + } if(G->absmove){ - if(curpos < 0){ // need to init - // check if we are on zero endswitch - int esw = mot_getesw(mcu, motnum); - if(esw == 0){ // move a little - sprintf(buf, "%dM%dM100", mcu, motnum); - tty_sendcmd(buf); - tty_wait(); - } - sprintf(buf, "%dM%dM-40000", mcu, motnum); - if(tty_sendcmd(buf)){ - WARNX(_("Can't initialize %s"), name); - return 0; - } - tty_wait(); // wait for initialisation ends - handshake(); - curpos = mot_getpos(mcu, motnum); - if(curpos){ - WARNX(_("Can't return to zero")); - return 0; - } - } if(steps < 0){ if(motnum == 1){ - steps += (mcu == 1) ? 36000 : 28800; // convert rotator angle to positive + steps += (mcu == 1) ? STEPSREV1 : STEPSREV2; // convert rotator angle to positive }else{ WARNX(_("Can't move to negative position")); return 0; @@ -101,61 +114,90 @@ int movemotor(int mcu, int motnum, int steps, const char *name){ steps -= curpos; } if(steps == 0){ - MSG(name, "already at position"); + MSG(name, _("already at position")); return 0; } DBG("try to move motor%d of mcu %d for %d steps", motnum, mcu, steps); snprintf(buf, 32, "%dM%dM%d", mcu, motnum, steps); - int ans = tty_sendcmd(buf); + ttysend_status ans = tty_sendcmd(buf); return parsemotans(ans, name); } int main(int argc, char **argv){ // char cmd[32]; int waitforstop = 0; + int rtn_status = RET_ALLOK; + initial_setup(); signal(SIGTERM, signals); // kill (-15) signal(SIGINT, signals); // ctrl+C signal(SIGQUIT, SIG_IGN); // ctrl+\ . signal(SIGTSTP, SIG_IGN); // ctrl+Z setbuf(stdout, NULL); - initial_setup(); G = parse_args(argc, argv); - tty_init(G->comdev); - handshake(); // test connection & get all positions + check4running(NULL, G->pidfile); + DBG("Try to open serial %s", G->comdev); + if(tty_tryopen(G->comdev, G->speed)){ + ERR(_("Can't open %s with speed %d. Exit."), G->comdev, G->speed); + } + + if(handshake()) signals(RET_NOTFOUND); // test connection & get all positions + if(G->waitold){ + if(tty_wait()) signals(RET_WAITERR); + handshake(); + } if(G->showtemp){ - tty_showtemp(); + if(tty_showtemp() != 2) rtn_status = RET_ONLYONE; } if(G->stopall){ // stop everything before analyze other commands - tty_sendcmd("1M0S"); - tty_sendcmd("1M1S"); - tty_sendcmd("2M0S"); - tty_sendcmd("2M1S"); + if(tty_stopall()) rtn_status = RET_COMMERR; + else MSG(_("All motors stopped"), NULL); } if(G->sendraw){ MSG(_("Send raw string"), G->sendraw); char *got = tty_sendraw(G->sendraw); if(got){ - if(!quiet) green("Receive:\n"); - printf("%s", got); + MSG(_("Receive"), got); + if(quiet) printf("%s", got); }else WARNX(_("Nothing received")); } - if(G->rot1angle > -999.){ - double angle = convangle(G->rot1angle); - int steps = (int)(100. * angle); - waitforstop = movemotor(1, 1, steps, "polaroid"); + if(G->rot1angle > -999. || G->rot2angle > -999. || G->l1steps != INT_MAX || G->l2steps != INT_MAX){ + // all other commands are tied with moving, so check if motors are inited + if(init_motors()) rtn_status = RET_CANTINIT; + else{ + if(G->rot1angle > -999.){ + double angle = convangle(G->rot1angle); + int steps = (int)((STEPSREV1/360.) * angle); + waitforstop = movemotor(1, 1, steps, "polaroid"); + } + if(G->rot2angle > -999.){ + double angle = convangle(G->rot2angle); + int steps = (int)((STEPSREV2/360.) * angle); + waitforstop = movemotor(2, 1, steps, "lambda/4"); + } + if(G->l1steps != INT_MAX){ + waitforstop = movemotor(1, 0, G->l1steps, "polaroid stage"); + } + if(G->l2steps != INT_MAX){ + waitforstop = movemotor(2, 0, G->l2steps, "lambda/4 stage"); + } + } } - if(G->rot2angle > -999.){ - double angle = convangle(G->rot2angle); - int steps = (int)(80. * angle); - waitforstop = movemotor(2, 1, steps, "lambda/4"); - } - if(G->l1steps != INT_MAX){ - waitforstop = movemotor(1, 0, G->l1steps, "polaroid stage"); - } - if(G->l2steps != INT_MAX){ - waitforstop = movemotor(2, 0, G->l2steps, "lambda/4 stage"); - } - if((waitforstop && !G->dontwait) || G->waitold) tty_wait(); + if((waitforstop && !G->dontwait)) if(tty_wait()) rtn_status = RET_WAITERR; if(G->getstatus) tty_getstatus(); - signals(0); + if(G->reset){ + int **N = G->reset; + while(*N){ + char cmd[3]; + if(**N < 1 || **N > 2){ + WARNX(_("Wrong MCU number (%d)"), **N); + }else{ + if(!quiet) green("Reset controller #%d\n", **N); + snprintf(cmd, 3, "%dR", **N); + ttysend_status _U_ rt = tty_sendcmd(cmd); + DBG("reset %d, result: %d", **N, rt); + } + ++N; + } + } + signals(rtn_status); } diff --git a/MMPP_control/new/Makefile b/MMPP_control/new/Makefile deleted file mode 100644 index 3e46add..0000000 --- a/MMPP_control/new/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -# run `make DEF=...` to add extra defines -PROGRAM := MMPP_control -LDFLAGS := -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,--discard-all -LDFLAGS += -lusefull_macros -SRCS := $(wildcard *.c) -DEFINES := $(DEF) -DBAUD_RATE=9600 -D_GNU_SOURCE -D_XOPEN_SOURCE=1111 -#DEFINES += -DEBUG -OBJDIR := mk -CFLAGS += -O2 -Wall -Werror -Wextra -Wno-trampolines -std=gnu99 -OBJS := $(addprefix $(OBJDIR)/, $(SRCS:%.c=%.o)) -DEPS := $(OBJS:.o=.d) -CC = gcc -#CXX = g++ - - -all : $(OBJDIR) $(PROGRAM) - -$(PROGRAM) : $(OBJS) - @echo -e "\t\tLD $(PROGRAM)" - $(CC) $(LDFLAGS) $(OBJS) -o $(PROGRAM) - -$(OBJDIR): - mkdir $(OBJDIR) - -ifneq ($(MAKECMDGOALS),clean) --include $(DEPS) -endif - -$(OBJDIR)/%.o: %.c - @echo -e "\t\tCC $<" - $(CC) -MD -c $(LDFLAGS) $(CFLAGS) $(DEFINES) -o $@ $< - -clean: - @echo -e "\t\tCLEAN" - @rm -f $(OBJS) $(DEPS) - @rmdir $(OBJDIR) 2>/dev/null || true - -xclean: clean - @rm -f $(PROGRAM) - -gentags: - CFLAGS="$(CFLAGS) $(DEFINES)" geany -g $(PROGRAM).c.tags *[hc] 2>/dev/null - -.PHONY: gentags clean xclean diff --git a/MMPP_control/new/cmdlnopts.c b/MMPP_control/new/cmdlnopts.c deleted file mode 100644 index 7899f8e..0000000 --- a/MMPP_control/new/cmdlnopts.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * cmdlnopts.c - the only function that parse cmdln args and returns glob parameters - * - * Copyright 2013 Edward V. Emelianoff - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -#include "cmdlnopts.h" -#include -#include -#include -#include -#include -#include - -/* - * here are global parameters initialisation - */ -static int help; -static glob_pars G; - -int quiet = 0; // less messages @ stdout - -// DEFAULTS -// default global parameters -glob_pars const Gdefault = { - .showtemp = 0 - ,.comdev = "/dev/ttyUSB0" - ,.pidfile = "/tmp/MMPP_control.pid" - ,.speed = BAUD_RATE - ,.rot1angle = -1000. - ,.rot2angle = -1000. - ,.l1steps = INT_MAX - ,.l2steps = INT_MAX -}; - -/* - * Define command line options by filling structure: - * name has_arg flag val type argptr help -*/ -static myoption cmdlnopts[] = { - {"help", NO_ARGS, NULL, 'h', arg_none, APTR(&help), N_("show this help")}, - {"quiet", NO_ARGS, NULL, 'q', arg_none, APTR(&quiet), N_("don't show anything @screen from stdout")}, - {"absmove", NO_ARGS, NULL, 'A', arg_none, APTR(&G.absmove), N_("absolute move (without this flag moving is relative)")}, - {"temp", NO_ARGS, NULL, 't', arg_none, APTR(&G.showtemp), N_("show temperature of both MCU")}, - {"comdev", NEED_ARG, NULL, 'd', arg_string, APTR(&G.comdev), N_("terminal device filename")}, - {"sendraw", NEED_ARG, NULL, 'a', arg_string, APTR(&G.sendraw), N_("send RAW string to port and read the answer")}, - {"reset", MULT_PAR, NULL, 'E', arg_int, APTR(&G.reset), N_("reset given mcu (may be included several times)")}, - {"rot1", NEED_ARG, NULL, 'R', arg_double, APTR(&G.rot1angle), N_("rotate polaroid to given angle")}, - {"rot2", NEED_ARG, NULL, 'r', arg_double, APTR(&G.rot2angle), N_("rotate lambda/4 to given angle")}, - {"status", NO_ARGS, NULL, 's', arg_none, APTR(&G.getstatus), N_("get device status")}, - {"baudrate",NEED_ARG, NULL, 'b', arg_int, APTR(&G.speed), N_("TTY baudrate")}, - {"wait", NO_ARGS, NULL, 'w', arg_none, APTR(&G.waitold), N_("wait while all previous moving ends")}, - {"async", NO_ARGS, NULL, 'y', arg_none, APTR(&G.dontwait), N_("asynchronous moving - don't wait")}, - {"lin1", NEED_ARG, NULL, 'L', arg_int, APTR(&G.l1steps), N_("move polaroid linear stage to N steps")}, - {"lin2", NEED_ARG, NULL, 'l', arg_int, APTR(&G.l2steps), N_("move wave-plate linear stage to N steps")}, - {"pidfile", NEED_ARG, NULL, 'p', arg_string, APTR(&G.pidfile), N_("PID-file name")}, - {"stop", NO_ARGS, NULL, 'S', arg_none, APTR(&G.stopall), N_("stop any moving")}, - end_option -}; - - -/** - * Parse command line options and return dynamically allocated structure - * to global parameters - * @param argc - copy of argc from main - * @param argv - copy of argv from main - * @return allocated structure with global parameters - */ -glob_pars *parse_args(int argc, char **argv){ - void *ptr; - ptr = memcpy(&G, &Gdefault, sizeof(G)); assert(ptr); - // format of help: "Usage: progname [args]\n" - // parse arguments - parseargs(&argc, &argv, cmdlnopts); - if(help) showhelp(-1, cmdlnopts); - if(argc > 0){ - WARNX("%d unused parameters:\n", argc); - for(int i = 0; i < argc; ++i) - printf("\t%4d: %s\n", i+1, argv[i]); - } - return &G; -} - -/** - * @brief MSG show coloured message if `quiet` not set - * !! This function adds trailing '\n' to message - * @param s1 - green part of message (may be null) - * @param s2 - normal colored part of messate (may be null) - */ -void MSG(const char *s1, const char *s2){ - if(quiet) return; - if(s1){ - green("%s%s", s1, s2 ? ": " : "\n"); - } - if(s2) printf("%s\n", s2); -} diff --git a/MMPP_control/new/cmdlnopts.h b/MMPP_control/new/cmdlnopts.h deleted file mode 100644 index 671c15e..0000000 --- a/MMPP_control/new/cmdlnopts.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * cmdlnopts.h - comand line options for parceargs - * - * Copyright 2013 Edward V. Emelianoff - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -#pragma once -#ifndef CMDLNOPTS_H__ -#define CMDLNOPTS_H__ - -#include -#include - -/* - * here are some typedef's for global data - */ -typedef struct{ - int showtemp; // show temperatures of both MCU - char *comdev; // TTY device - char *sendraw; // send RAW string - char *pidfile; // pid file name - double rot1angle; // rotator 1 angle - double rot2angle; // rotator 2 angle - int speed; // TTY speed - int getstatus; // get both MCU status - int waitold; // wait for previous moving ends - int dontwait; // don't wait for moving end - int l1steps; // move linear stage 1 (polaroid) for N steps - int l2steps; // move linear stage 2 (L/4) for N steps - int absmove; // absolute move (to given position from zero-esw) - int stopall; // stop all moving - int **reset; // reset given MCU's -} glob_pars; - -// default & global parameters -extern glob_pars const Gdefault; -extern int quiet; - -glob_pars *parse_args(int argc, char **argv); -void MSG(const char *s1, const char *s2); - -#endif // CMDLNOPTS_H__ diff --git a/MMPP_control/new/main.c b/MMPP_control/new/main.c deleted file mode 100644 index 6faf006..0000000 --- a/MMPP_control/new/main.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * geany_encoding=koi8-r - * main.c - * - * Copyright 2018 Edward V. Emelianov - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - * - */ - -#include "cmdlnopts.h" -#include "signal.h" -#include "tty_procs.h" -#include -#include -#include - -// All return states of main(): -enum{ - RET_ALLOK = 0, - RET_NOTFOUND, // none of MCU found or didn't found seeking MCU - RET_ONLYONE, // only one MCU found - RET_COMMERR, // communication error - RET_CANTINIT, // can't init motors: error during initiation or some of motors are moving - RET_WAITERR, // error occured during waiting procedure - RET_ERROR = 9, // uncoverable error - from libsnippets - RET_HELPCALL = 255 // user call help (or give wrong parameter[s]) - from libsnippets -}; - -static glob_pars *G; - -/** - * We REDEFINE the default WEAK function of signal processing - */ -void __attribute__((noreturn)) signals(int sig){ - if(sig){ - signal(sig, SIG_IGN); - DBG("Get signal %d, quit.\n", sig); - } - if(G->pidfile) // remove unnesessary PID file - unlink(G->pidfile); - restore_console(); - tty_close(); - exit(sig); -} - -void __attribute__((noreturn)) iffound_default(pid_t pid){ - ERRX("Another copy of this process found, pid=%d. Exit.", pid); -} - -static double convangle(double val){ - int X = (int)(val / 360.); - val -= 360. * (double)X; - return val; -} - -/** - * @return 1 if motor start moving else return 0 - */ -static int parsemotans(ttysend_status ans, const char *prefix){ - DBG("parse ans: %d (prefix: %s)", ans, prefix); - if(ans == SEND_ALLOK) return 1; - else if(ans == SEND_ERR) WARNX(_("%s moving error!"), prefix); - else if(ans == SEND_ESWITCH) WARNX(_("%s is on end-switch and can't move further"), prefix); - else if(ans == SEND_OTHER) WARNX(_("Can't move %s: bad steps amount or still moving"), prefix); - return 0; -} - -/** - * move motor - * @return 0 if motor can't move, else return 1 - */ -/** - * @brief movemotor - move motor - * @param mcu - MCU# (controller No, 1 or 2) - * @param motnum - motor# (0 or 1) - * @param steps - steps amount ( - * @param name - * @return 0 if motor can't move, else return 1 - */ -static int movemotor(int mcu, int motnum, int steps, const char *name){ - char buf[32]; - int curpos = mot_getpos(mcu, motnum); - if(curpos == INT_MIN){ - WARNX(_("Can't get current %s position"), name); - return 0; - } - if(curpos < 0){ // need to init - WARNX(_("Init of %s failed"), name); - return 0; - } - if(G->absmove){ - if(steps < 0){ - if(motnum == 1){ - steps += (mcu == 1) ? STEPSREV1 : STEPSREV2; // convert rotator angle to positive - }else{ - WARNX(_("Can't move to negative position")); - return 0; - } - } - steps -= curpos; - } - if(steps == 0){ - MSG(name, _("already at position")); - return 0; - } - DBG("try to move motor%d of mcu %d for %d steps", motnum, mcu, steps); - snprintf(buf, 32, "%dM%dM%d", mcu, motnum, steps); - ttysend_status ans = tty_sendcmd(buf); - return parsemotans(ans, name); -} - -int main(int argc, char **argv){ -// char cmd[32]; - int waitforstop = 0; - int rtn_status = RET_ALLOK; - initial_setup(); - signal(SIGTERM, signals); // kill (-15) - signal(SIGINT, signals); // ctrl+C - signal(SIGQUIT, SIG_IGN); // ctrl+\ . - signal(SIGTSTP, SIG_IGN); // ctrl+Z - setbuf(stdout, NULL); - G = parse_args(argc, argv); - check4running(NULL, G->pidfile); - DBG("Try to open serial %s", G->comdev); - if(tty_tryopen(G->comdev, G->speed)){ - ERR(_("Can't open %s with speed %d. Exit."), G->comdev, G->speed); - } - - if(handshake()) signals(RET_NOTFOUND); // test connection & get all positions - if(G->waitold){ - if(tty_wait()) signals(RET_WAITERR); - handshake(); - } - if(G->showtemp){ - if(tty_showtemp() != 2) rtn_status = RET_ONLYONE; - } - if(G->stopall){ // stop everything before analyze other commands - if(tty_stopall()) rtn_status = RET_COMMERR; - else MSG(_("All motors stopped"), NULL); - } - if(G->sendraw){ - MSG(_("Send raw string"), G->sendraw); - char *got = tty_sendraw(G->sendraw); - if(got){ - MSG(_("Receive"), got); - if(quiet) printf("%s", got); - }else WARNX(_("Nothing received")); - } - if(G->rot1angle > -999. || G->rot2angle > -999. || G->l1steps != INT_MAX || G->l2steps != INT_MAX){ - // all other commands are tied with moving, so check if motors are inited - if(init_motors()) rtn_status = RET_CANTINIT; - else{ - if(G->rot1angle > -999.){ - double angle = convangle(G->rot1angle); - int steps = (int)((STEPSREV1/360.) * angle); - waitforstop = movemotor(1, 1, steps, "polaroid"); - } - if(G->rot2angle > -999.){ - double angle = convangle(G->rot2angle); - int steps = (int)((STEPSREV2/360.) * angle); - waitforstop = movemotor(2, 1, steps, "lambda/4"); - } - if(G->l1steps != INT_MAX){ - waitforstop = movemotor(1, 0, G->l1steps, "polaroid stage"); - } - if(G->l2steps != INT_MAX){ - waitforstop = movemotor(2, 0, G->l2steps, "lambda/4 stage"); - } - } - } - if((waitforstop && !G->dontwait)) if(tty_wait()) rtn_status = RET_WAITERR; - if(G->getstatus) tty_getstatus(); - if(G->reset){ - int **N = G->reset; - while(*N){ - char cmd[3]; - if(**N < 1 || **N > 2){ - WARNX(_("Wrong MCU number (%d)"), **N); - }else{ - if(!quiet) green("Reset controller #%d\n", **N); - snprintf(cmd, 3, "%dR", **N); - ttysend_status _U_ rt = tty_sendcmd(cmd); - DBG("reset %d, result: %d", **N, rt); - } - ++N; - } - } - signals(rtn_status); -} diff --git a/MMPP_control/new/tty_procs.c b/MMPP_control/new/tty_procs.c deleted file mode 100644 index 79c4648..0000000 --- a/MMPP_control/new/tty_procs.c +++ /dev/null @@ -1,536 +0,0 @@ -/* - * geany_encoding=koi8-r - * tty_procs.c - * - * Copyright 2018 Edward V. Emelianov - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - * - */ -#include "cmdlnopts.h" // for `verbose` -#include "tty_procs.h" -#include -#include -#include -#include - -// tty Rx static buffer -#define TBUFLEN (1024) -// read timeout (in seconds) -#define TTYTIMEOUT (0.05) - -static TTY_descr *dev = NULL; - -// two buffers for data -static char buf[TBUFLEN+1]; -static char bufo[TBUFLEN+1]; - -static int motpos[3][2]; // motor's positions, 1 - number of mcu, 2 - number of motor -static int reset[3]; // reset occured -static int endswitches[3][2]; // ESW of motors: 0 - zero esw, 1 - limit esw, -1 - clear -static int alive[3] = {0,0,0}; // ==1 if controller answers, 0 if no - -/** - * @brief tty_tryopen - try to open serial device - * @param devnm - path to device - * @param spd - speed (number) - * @return 0 if all OK - */ -int tty_tryopen(char *devnm, int spd){ - dev = new_tty(devnm, spd, 256); - if(!tty_open(dev, TRUE)) return 1; - return 0; -} - -void tty_close(){ - close_tty(&dev); -} - -/** - * read data from TTY - * WARNING! Not thread-safe!!! - * @return static buffer with data read or NULL - */ -static char *tty_get(){ - char *ptr = buf; - size_t L = 0, l = TBUFLEN; - double t0 = dtime(); - *ptr = 0; - while(dtime() - t0 < TTYTIMEOUT && l){ - size_t r = read_tty(dev); - if(!r) continue; - t0 = dtime(); - if(r > l) r = l; - DBG("got %zd bytes: %s", r, dev->buf); - strncpy(ptr, dev->buf, r); - L += r; l -= r; ptr += r; - } - buf[L] = 0; - if(L){ - return buf; - } - DBG("no answer"); - return NULL; -} - -/** - * copy given string to `buf` & add '\n' if need - * @return 0 if failed - */ -static size_t cpy2buf(char *string){ - size_t l = strlen(string); - if(l > TBUFLEN-1){ - WARNX(_("String too long! Nothing would be send.")); - return 0; - } - strcpy(bufo, string); - if(bufo[l-1] != '\n'){ - bufo[l++] = '\n'; - bufo[l] = 0; - } - return l; -} - -/** - * Send given string command to port - * @return 0 if failed - */ -static int ttysend(char *cmd){ - size_t l = cpy2buf(cmd); - if(!l) return 0; - if(write_tty(dev->comfd, bufo, l)) return 0; - return 1; -} - -/** - * send RAW string to port device - * @param string - string to send - * @return string received or NULL in case of error - */ -char* tty_sendraw(char *string){ - DBG("sendraw %s", string); - if(!ttysend(string)) return NULL; - return tty_get(); -} - -/** - * Send given string command to port with answer analysis - * @return status - */ -ttysend_status tty_sendcmd(char *cmd){ - DBG("SEND: %s", cmd); - if(!ttysend(cmd)) return SEND_ERR; - char *got = tty_get(); - if(!got) return SEND_ERR; - DBG("GOT: %s", got); - if(strcmp(got, "ALLOK\n") == 0) return SEND_ALLOK; - if(strcmp(got, "OnEndSwitch\n") == 0) return SEND_ESWITCH; - return SEND_OTHER; -} - -/** - * return static buffer - value of `key` - * NOT THREAD SAFE! - */ -static char *keyval(char *key){ - //DBG("search %s in\n%s", key, buf); - static char buff[32]; - char *got = strstr(buf, key); - if(!got) return NULL; - got = strchr(got, '='); - if(!got) return NULL; - ++got; - char *el = strchr(got, '\n'); - if(!el) return NULL; - size_t L = (size_t)(el - got); - if(L > 31 || L == 0 || !*got) return NULL; - strncpy(buff, got, L); - buff[L] = 0; - return buff; -} - -/** - * parse status with given command `cmd` - * @return: - * 1 if one of motors still moving - * 0 if both are stopped - * -1 if failed - */ -static int parsestatus(char *cmd){ - if(!cmd) return 0; - if(!tty_sendraw(cmd)) return -1; - char buff[32], stat[2][5], left[2][7], pos[2][7]; - int mvng = 0; - for(int i = 0; i < 2; ++i){ - sprintf(buff, "POS%d", i); - char *val = keyval(buff); - if(!val) return -1; - strncpy(pos[i], val, 7); - sprintf(buff, "MOTOR%d", i); - val = keyval(buff); - if(!val) return -1; - if(strcmp(val, "SLEEP") == 0){ - strcpy(stat[i], "STOP"); - strcpy(left[i], "0"); - continue; - }else if(strcmp(val, "UNKNOWN")){ - strcpy(stat[i], "MOVE"); - mvng = 1; - sprintf(buff, "STEPSLEFT%d", i); - val = keyval(buff); - if(!val) return -1; - strncpy(left[i], val, 7); - }else return -1; - } - snprintf(bufo, TBUFLEN, "%4s %6s %6s - %4s %6s %6s", - stat[0], left[0], pos[0], stat[1], left[1], pos[1]); - if(mvng){ - return 1; - } else return 0; -} - -/** - * Wait for all motors stop with current data indication - * @return 0 if all OK - */ -int tty_wait(){ - FNAME(); - int failcount = 0, chk1 = 1, chk2 = 1; - if(!quiet) - green("Pol: M0ST M0LEFT M0POS - M1ST M1LEFT M1POS || L/4: M0ST M0LEFT M0POS - M1ST M1LEFT M1POS \n"); - while(failcount < 5 && (chk1 || chk2)){ // 5 tries - if(alive[1]){ - chk1 = parsestatus("1GS"); - if(!quiet){ - printf("Pol: "); - if(chk1 == -1){ - chk1 = 1; - ++failcount; - printf("%39s", "failed "); - }else printf("%s", bufo); - } - }else{ - if(!quiet) printf("Pol: %39s", "failed "); - chk1 = 0; - } - if(alive[2]){ - chk2 = parsestatus("2GS"); - if(!quiet){ - printf(" || L/4: "); - if(chk2 == -1){ - chk2 = 1; - ++failcount; - printf("%38s", "failed"); - }else printf("%s", bufo); - printf(" \r"); - } - }else{ - if(!quiet) printf(" || L/4: %38s\r", "failed"); - chk2 = 0; - } - } - if(!quiet) printf("\n\n"); - if(failcount > 4){ - WARNX(_("Can't get status answer!")); - return 1; - } - return 0; -} - -#if 0 -MOTOR0=SLEEP -POS0=43 -ESW00=RLSD -ESW01=HALL -MOTOR1=MOVE -STEPSLEFT1=6921 -POS1=3238 -ESW10=HALL -ESW11=RLSD -#endif - -// tty_getstatus when `quiet==1` -static void ttystatq(){ - char st[4] = "xGS"; - char *nm[3] = {NULL, "POL", "L4"}; - for(int Nmcu = 1; Nmcu < 3; ++Nmcu){ - if(!alive[Nmcu]) continue; - st[0] = '0' + Nmcu; - if(!tty_sendraw(st)) continue; - char *str = strtok(buf, "\n"); - while(str){ - printf("%s%s\n", nm[Nmcu], str); - str = strtok(NULL, "\n"); - } - } -} - -// tty_getstatus when `quiet==0` -static void ttystat(){ - int chk1 = -1, chk2 = -1; - char buff[TBUFLEN+1]; - if(!quiet) green("Pol: M0ST M0LEFT M0POS - M1ST M1LEFT M1POS || L/4: M0ST M0LEFT M0POS - M1ST M1LEFT M1POS \n"); - if(alive[1]) chk1 = parsestatus("1GS"); - if(!quiet) printf("Pol: "); - if(chk1 == -1){ - if(!quiet) printf("%39s", "failed "); - }else printf("%s", bufo); - char *val = keyval("ESW00"); - if(!val) val = " "; - sprintf(buff, "%5s ", val); - val = keyval("ESW01"); - if(!val) val = " "; - sprintf(&buff[6], "%5s ", val); - val = keyval("ESW10"); - if(!val) val = " "; - sprintf(&buff[12], "%5s ", val); - val = keyval("ESW11"); - if(!val) val = " "; - sprintf(&buff[18], "%5s ", val); - if(alive[2]) chk2 = parsestatus("2GS"); - printf(" || L/4: "); - if(chk2 == -1){ - printf("%38s", "failed"); - }else printf("%s", bufo); - printf("\n"); - sprintf(&buff[24], "|| "); - val = keyval("ESW00"); - DBG("ESW00=%s", val); - if(!val) val = " "; - sprintf(&buff[27], "%5s ", val); - val = keyval("ESW01"); - if(!val) val = " "; - sprintf(&buff[33], "%5s ", val); - val = keyval("ESW10"); - if(!val) val = " "; - sprintf(&buff[39], "%5s ", val); - val = keyval("ESW11"); - if(!val) val = " "; - sprintf(&buff[45], "%5s ", val); - // end-switches - green("ESW00 ESW01 ESW10 ESW11 || ESW00 ESW01 ESW10 ESW11\n"); - printf("%s\n", buff); - for(int i = 1; i < 3; ++i){ - if(reset[i]) printf("RESET%d=1\n", i); - } -} - -void tty_getstatus(){ - FNAME(); - if(quiet) ttystatq(); - else ttystat(); -} - - -/** - * Show temperature of both MCU - * @return amount of successful calls - */ -int tty_showtemp(){ - char *val, buff[] = "xGT\n"; - const char *nm[3] = {NULL, "POL", "L4"}; - int ret = 0; - for(int i = 1; i < 3; ++i){ - if(!alive[i]){ - DBG("MCU %d didn't respond!", i); - continue; - } - buff[0] = '0' + (char)i; - if(tty_sendraw(buff)){ - val = keyval("TEMP"); - if(val){ - ++ret; - double t; - if(str2double(&t, val)){ - if(quiet){ - printf("%sTEMP=%g\n", nm[i], t/10.); - }else{ - green("MCU%d temperature:", i); - printf(" %g degC\n", t/10.); - } - } - } - } - } - return ret; -} - -/** - * get current motor position (if move or error return INT_MIN) - * - */ -int mot_getpos(int mcu, int motor){ - if(mcu < 1 || mcu > 2){ - WARNX(_("Bad MCU number")); - return INT_MIN; - } - if(motor < 0 || motor > 1){ - WARNX(_("Bad motor number")); - return INT_MIN; - } - return motpos[mcu][motor]; -} - -/** - * get motor endswitches status - * @return -1 if error or intermediate position, 0 - on zero's esw, 1 - on end's esw - */ -int mot_getesw(int mcu, int motor){ - if(mcu < 1 || mcu > 2){ - WARNX(_("Bad MCU number")); - return -1; - } - if(motor < 0 || motor > 1){ - WARNX(_("Bad motor number")); - return -1; - } - return endswitches[mcu][motor]; -} - -/** - * test connection (1,2 -> ALIVE) - * and get positions - * @return 1 if none of MCU found, 0 if at least 1 found - */ -int handshake(){ - char buff[32], *val; - int mcu, motor; - FNAME(); - for(mcu = 1; mcu < 3; ++ mcu){ - // check if MCU alive - sprintf(buff, "%d", mcu); - int notresp = 1; - // make HANDSHAKE_TRIES tries - for(int tr = 0; tr < HANDSHAKE_TRIES; ++tr){ - if(tty_sendraw(buff) && 0 == strcmp(buf, "ALIVE\n")){ - notresp = 0; - break; - } - } - if(notresp){ - WARNX(_("MCU %d not response!"), mcu); - continue; - } - alive[mcu] = 1; - sprintf(buff, "%dGS", mcu); - if(tty_sendraw(buff)){ - // check reboot states - if(strstr(buf, "RESET")){ - reset[mcu] = 1; - WARNX(_("MCU %d had reset state!"), mcu); - }else - reset[mcu] = 0; - for(motor = 0; motor < 2; ++motor){ - /*sprintf(buff, "MOTOR%d", motor); - val = keyval(buff); - if(!val || strcmp(val, "SLEEP")){ - motpos[mcu][motor] = INT_MIN; - continue; - }*/ - sprintf(buff, "POS%d", motor); - val = keyval(buff); - DBG("----%s=%s", buff, val); - motpos[mcu][motor] = val ? atoi(val) : INT_MIN; - DBG("MOTPOS[%d][%d] = %d", mcu, motor, motpos[mcu][motor]); - // end-switches - sprintf(buff, "ESW%d0", motor); - val = keyval(buff); - if(!val || strcmp(val, "HALL")){ - sprintf(buff, "ESW%d1", motor); - val = keyval(buff); - if(!val || strcmp(val, "HALL")){ - endswitches[mcu][motor] = -1; - }else - endswitches[mcu][motor] = 1; - }else endswitches[mcu][motor] = 0; - DBG("ENDSWITCHES[%d][%d] = %d", mcu, motor, endswitches[mcu][motor]); - } - }else{ - motpos[mcu][0] = INT_MIN; - motpos[mcu][1] = INT_MIN; - } - } - if(alive[1] == 0 && alive[2] == 0) return 1; - return 0; -} - -/** - * @brief tty_stopall - send commands to stop all motors - * @return 0 if all OK, else return amount of motors failed to stop - */ -int tty_stopall(){ - int ret = 4; - if(alive[1]){ - if(SEND_ALLOK == tty_sendcmd("1M0S")) --ret; - if(SEND_ALLOK == tty_sendcmd("1M1S")) --ret; - } - if(alive[2]){ - if(SEND_ALLOK == tty_sendcmd("2M0S")) --ret; - if(SEND_ALLOK == tty_sendcmd("2M1S")) --ret; - } - return ret; -} - -/** - * @brief init_motors - init all motors simultaneously (if they need to) - * @return 0 if all OK, or Nmcu*10+motnum for problem motor - */ -int init_motors(){ -#define RETVAL() (Nmcu*10+motnum) - int Nmcu, motnum, needinit = 0; - for(Nmcu = 1; Nmcu < 3; ++Nmcu){ - for(motnum = 0; motnum < 2; ++motnum){ - // check position - int pos = motpos[Nmcu][motnum]; - if(pos == INT_MIN) continue; // communication error on handshake - if(pos < 0) needinit = 1; - }} - if(!needinit) return 0; - DBG("Need to init, start!"); - for(Nmcu = 1; Nmcu < 3; ++Nmcu){ - for(motnum = 0; motnum < 2; ++motnum){ - int pos = motpos[Nmcu][motnum]; - if(pos >= 0) continue; - // check if we are on zero endswitch - int esw = mot_getesw(Nmcu, motnum); - if(esw == 0){ // move a little from zero esw - sprintf(buf, "%dM%dM100", Nmcu, motnum); - if(SEND_ERR == tty_sendcmd(buf)){ - WARNX(_("Can't move from endswitch")); - return RETVAL(); - } - tty_wait(); - } - sprintf(buf, "%dM%dM-40000", Nmcu, motnum); - if(SEND_ALLOK != tty_sendcmd(buf)){ - WARNX(_("Can't move to endwsitch 0")); - return RETVAL(); - } - }} - tty_wait(); - handshake(); - for(Nmcu = 1; Nmcu < 3; ++Nmcu){ - for(motnum = 0; motnum < 2; ++motnum){ - int curpos = mot_getpos(Nmcu, motnum); - if(curpos){ - WARNX(_("Can't return to zero")); - return RETVAL(); - } - }} - return 0; -#undef RETVAL -} - diff --git a/MMPP_control/new/tty_procs.h b/MMPP_control/new/tty_procs.h deleted file mode 100644 index 6c26f0f..0000000 --- a/MMPP_control/new/tty_procs.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * tty_procs.h - * - * Copyright 2018 Edward V. Emelianov - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - * - */ -#pragma once -#ifndef TTY_PROCS_H__ -#define TTY_PROCS_H__ - -#include - -// amount of tries to establish handshake -#define HANDSHAKE_TRIES (10) -// steps per full revolution for both rotation stages (1 - polaroid, 2 - waveplate) -#define STEPSREV1 (36000) -#define STEPSREV2 (28800) - -typedef enum{ - SEND_ERR, - SEND_ALLOK, - SEND_ESWITCH, - SEND_OTHER -} ttysend_status; - -int tty_tryopen(char *dev, int spd); -void tty_close(); -char* tty_sendraw(char *string); -int tty_wait(); -ttysend_status tty_sendcmd(char *cmd); -int tty_showtemp(); -int tty_stopall(); -void tty_getstatus(); -int handshake(); -int mot_getpos(int mcu, int motor); -int mot_getesw(int mcu, int motor); -int init_motors(); - -#endif // TTY_PROCS_H__ diff --git a/MMPP_control/parseargs.c b/MMPP_control/parseargs.c deleted file mode 100644 index b235752..0000000 --- a/MMPP_control/parseargs.c +++ /dev/null @@ -1,497 +0,0 @@ -/* geany_encoding=koi8-r - * parseargs.c - parsing command line arguments & print help - * - * Copyright 2013 Edward V. Emelianoff - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -#include // printf -#include // getopt_long -#include // calloc, exit, strtoll -#include // assert -#include // strdup, strchr, strlen -#include // strcasecmp -#include // INT_MAX & so on -#include // gettext -#include // isalpha -#include "parseargs.h" -#include "usefull_macros.h" - -char *helpstring = "%s\n"; - -/** - * Change standard help header - * MAY consist ONE "%s" for progname - * @param str (i) - new format - */ -void change_helpstring(char *s){ - int pcount = 0, scount = 0; - char *str = s; - // check `helpstring` and set it to default in case of error - for(; pcount < 2; str += 2){ - if(!(str = strchr(str, '%'))) break; - if(str[1] != '%') pcount++; // increment '%' counter if it isn't "%%" - else{ - str += 2; // pass next '%' - continue; - } - if(str[1] == 's') scount++; // increment "%s" counter - }; - if(pcount > 1 || pcount != scount){ // amount of pcount and/or scount wrong - /// "Неправильный формат строки помощи" - ERRX(_("Wrong helpstring!")); - } - helpstring = s; -} - -/** - * Carefull atoll/atoi - * @param num (o) - returning value (or NULL if you wish only check number) - allocated by user - * @param str (i) - string with number must not be NULL - * @param t (i) - T_INT for integer or T_LLONG for long long (if argtype would be wided, may add more) - * @return TRUE if conversion sone without errors, FALSE otherwise - */ -static bool myatoll(void *num, char *str, argtype t){ - long long tmp, *llptr; - int *iptr; - char *endptr; - assert(str); - assert(num); - tmp = strtoll(str, &endptr, 0); - if(endptr == str || *str == '\0' || *endptr != '\0') - return FALSE; - switch(t){ - case arg_longlong: - llptr = (long long*) num; - *llptr = tmp; - break; - case arg_int: - default: - if(tmp < INT_MIN || tmp > INT_MAX){ - /// "Целое вне допустимого диапазона" - WARNX(_("Integer out of range")); - return FALSE; - } - iptr = (int*)num; - *iptr = (int)tmp; - } - return TRUE; -} - -// the same as myatoll but for double -// There's no NAN & INF checking here (what if they would be needed?) -static bool myatod(void *num, const char *str, argtype t){ - double tmp, *dptr; - float *fptr; - char *endptr; - assert(str); - tmp = strtod(str, &endptr); - if(endptr == str || *str == '\0' || *endptr != '\0') - return FALSE; - switch(t){ - case arg_double: - dptr = (double *) num; - *dptr = tmp; - break; - case arg_float: - default: - fptr = (float *) num; - *fptr = (float)tmp; - break; - } - return TRUE; -} - -/** - * Get index of current option in array options - * @param opt (i) - returning val of getopt_long - * @param options (i) - array of options - * @return index in array - */ -static int get_optind(int opt, myoption *options){ - int oind; - myoption *opts = options; - assert(opts); - for(oind = 0; opts->name && opts->val != opt; oind++, opts++); - if(!opts->name || opts->val != opt) // no such parameter - showhelp(-1, options); - return oind; -} - -/** - * reallocate new value in array of multiple repeating arguments - * @arg paptr - address of pointer to array (**void) - * @arg type - its type (for realloc) - * @return pointer to new (next) value - */ -void *get_aptr(void *paptr, argtype type){ - int i = 1; - void **aptr = *((void***)paptr); - if(aptr){ // there's something in array - void **p = aptr; - while(*p++) ++i; - } - size_t sz = 0; - switch(type){ - default: - case arg_none: - /// "Не могу использовать несколько параметров без аргументов!" - ERRX("Can't use multiple args with arg_none!"); - break; - case arg_int: - sz = sizeof(int); - break; - case arg_longlong: - sz = sizeof(long long); - break; - case arg_double: - sz = sizeof(double); - break; - case arg_float: - sz = sizeof(float); - break; - case arg_string: - sz = 0; - break; - /* case arg_function: - sz = sizeof(argfn *); - break;*/ - } - aptr = realloc(aptr, (i + 1) * sizeof(void*)); - *((void***)paptr) = aptr; - aptr[i] = NULL; - if(sz){ - aptr[i - 1] = malloc(sz); - }else - aptr[i - 1] = &aptr[i - 1]; - return aptr[i - 1]; -} - - -/** - * Parse command line arguments - * ! If arg is string, then value will be strdup'ed! - * - * @param argc (io) - address of argc of main(), return value of argc stay after `getopt` - * @param argv (io) - address of argv of main(), return pointer to argv stay after `getopt` - * BE CAREFUL! if you wanna use full argc & argv, save their original values before - * calling this function - * @param options (i) - array of `myoption` for arguments parcing - * - * @exit: in case of error this function show help & make `exit(-1)` - */ -void parseargs(int *argc, char ***argv, myoption *options){ - char *short_options, *soptr; - struct option *long_options, *loptr; - size_t optsize, i; - myoption *opts = options; - // check whether there is at least one options - assert(opts); - assert(opts[0].name); - // first we count how much values are in opts - for(optsize = 0; opts->name; optsize++, opts++); - // now we can allocate memory - short_options = calloc(optsize * 3 + 1, 1); // multiply by three for '::' in case of args in opts - long_options = calloc(optsize + 1, sizeof(struct option)); - opts = options; loptr = long_options; soptr = short_options; - // in debug mode check the parameters are not repeated -#ifdef EBUG - char **longlist = MALLOC(char*, optsize); - char *shortlist = MALLOC(char, optsize); -#endif - // fill short/long parameters and make a simple checking - for(i = 0; i < optsize; i++, loptr++, opts++){ - // check - assert(opts->name); // check name -#ifdef EBUG - longlist[i] = strdup(opts->name); -#endif - if(opts->has_arg){ - assert(opts->type != arg_none); // check error with arg type - assert(opts->argptr); // check pointer - } - if(opts->type != arg_none) // if there is a flag without arg, check its pointer - assert(opts->argptr); - // fill long_options - // don't do memcmp: what if there would be different alignment? - loptr->name = opts->name; - loptr->has_arg = (opts->has_arg < MULT_PAR) ? opts->has_arg : 1; - loptr->flag = opts->flag; - loptr->val = opts->val; - // fill short options if they are: - if(!opts->flag && opts->val){ -#ifdef EBUG - shortlist[i] = (char) opts->val; -#endif - *soptr++ = opts->val; - if(loptr->has_arg) // add ':' if option has required argument - *soptr++ = ':'; - if(loptr->has_arg == 2) // add '::' if option has optional argument - *soptr++ = ':'; - } - } - // sort all lists & check for repeating -#ifdef EBUG - int cmpstringp(const void *p1, const void *p2){ - return strcmp(* (char * const *) p1, * (char * const *) p2); - } - int cmpcharp(const void *p1, const void *p2){ - return (int)(*(char * const)p1 - *(char *const)p2); - } - qsort(longlist, optsize, sizeof(char *), cmpstringp); - qsort(shortlist,optsize, sizeof(char), cmpcharp); - char *prevl = longlist[0], prevshrt = shortlist[0]; - for(i = 1; i < optsize; ++i){ - if(longlist[i]){ - if(prevl){ - if(strcmp(prevl, longlist[i]) == 0) ERRX("double long arguments: --%s", prevl); - } - prevl = longlist[i]; - } - if(shortlist[i]){ - if(prevshrt){ - if(prevshrt == shortlist[i]) ERRX("double short arguments: -%c", prevshrt); - } - prevshrt = shortlist[i]; - } - } -#endif - // now we have both long_options & short_options and can parse `getopt_long` - while(1){ - int opt; - int oindex = 0, optind = 0; // oindex - number of option in argv, optind - number in options[] - if((opt = getopt_long(*argc, *argv, short_options, long_options, &oindex)) == -1) break; - if(opt == '?'){ - opt = optopt; - optind = get_optind(opt, options); - if(options[optind].has_arg == NEED_ARG || options[optind].has_arg == MULT_PAR) - showhelp(optind, options); // need argument - } - else{ - if(opt == 0 || oindex > 0) optind = oindex; - else optind = get_optind(opt, options); - } - opts = &options[optind]; - // if(opt == 0 && opts->has_arg == NO_ARGS) continue; // only long option changing integer flag - // now check option - if(opts->has_arg == NEED_ARG || opts->has_arg == MULT_PAR) - if(!optarg) showhelp(optind, options); // need argument - void *aptr; - if(opts->has_arg == MULT_PAR){ - aptr = get_aptr(opts->argptr, opts->type); - }else - aptr = opts->argptr; - bool result = TRUE; - // even if there is no argument, but argptr != NULL, think that optarg = "1" - if(!optarg) optarg = "1"; - switch(opts->type){ - default: - case arg_none: - if(opts->argptr) *((int*)aptr) += 1; // increment value - break; - case arg_int: - result = myatoll(aptr, optarg, arg_int); - break; - case arg_longlong: - result = myatoll(aptr, optarg, arg_longlong); - break; - case arg_double: - result = myatod(aptr, optarg, arg_double); - break; - case arg_float: - result = myatod(aptr, optarg, arg_float); - break; - case arg_string: - result = (*((void**)aptr) = (void*)strdup(optarg)); - break; - case arg_function: - result = ((argfn)aptr)(optarg); - break; - } - if(!result){ - showhelp(optind, options); - } - } - *argc -= optind; - *argv += optind; -} - -/** - * compare function for qsort - * first - sort by short options; second - sort arguments without sort opts (by long options) - */ -static int argsort(const void *a1, const void *a2){ - const myoption *o1 = (myoption*)a1, *o2 = (myoption*)a2; - const char *l1 = o1->name, *l2 = o2->name; - int s1 = o1->val, s2 = o2->val; - int *f1 = o1->flag, *f2 = o2->flag; - // check if both options has short arg - if(f1 == NULL && f2 == NULL && s1 && s2){ // both have short arg - return (s1 - s2); - }else if((f1 != NULL || !s1) && (f2 != NULL || !s2)){ // both don't have short arg - sort by long - return strcmp(l1, l2); - }else{ // only one have short arg -- return it - if(f2 || !s2) return -1; // a1 have short - it is 'lesser' - else return 1; - } -} - -/** - * Show help information based on myoption->help values - * @param oindex (i) - if non-negative, show only help by myoption[oindex].help - * @param options (i) - array of `myoption` - * - * @exit: run `exit(-1)` !!! - */ -void showhelp(int oindex, myoption *options){ - int max_opt_len = 0; // max len of options substring - for right indentation - const int bufsz = 255; - char buf[bufsz+1]; - myoption *opts = options; - assert(opts); - assert(opts[0].name); // check whether there is at least one options - if(oindex > -1){ // print only one message - opts = &options[oindex]; - printf(" "); - if(!opts->flag && isalpha(opts->val)) printf("-%c, ", opts->val); - printf("--%s", opts->name); - if(opts->has_arg == 1) printf("=arg"); - else if(opts->has_arg == 2) printf("[=arg]"); - printf(" %s\n", _(opts->help)); - exit(-1); - } - // header, by default is just "progname\n" - printf("\n"); - if(strstr(helpstring, "%s")) // print progname - printf(helpstring, __progname); - else // only text - printf("%s", helpstring); - printf("\n"); - // count max_opt_len - do{ - int L = strlen(opts->name); - if(max_opt_len < L) max_opt_len = L; - }while((++opts)->name); - max_opt_len += 14; // format: '-S , --long[=arg]' - get addition 13 symbols - opts = options; - // count amount of options - int N; for(N = 0; opts->name; ++N, ++opts); - if(N == 0) exit(-2); - // Now print all help (sorted) - opts = options; - qsort(opts, N, sizeof(myoption), argsort); - do{ - int p = sprintf(buf, " "); // a little indent - if(!opts->flag && opts->val) // .val is short argument - p += snprintf(buf+p, bufsz-p, "-%c, ", opts->val); - p += snprintf(buf+p, bufsz-p, "--%s", opts->name); - if(opts->has_arg == 1) // required argument - p += snprintf(buf+p, bufsz-p, "=arg"); - else if(opts->has_arg == 2) // optional argument - p += snprintf(buf+p, bufsz-p, "[=arg]"); - assert(p < max_opt_len); // there would be magic if p >= max_opt_len - printf("%-*s%s\n", max_opt_len+1, buf, _(opts->help)); // write options & at least 2 spaces after - ++opts; - }while(--N); - printf("\n\n"); - exit(-1); -} - -/** - * get suboptions from parameter string - * @param str - parameter string - * @param opt - pointer to suboptions structure - * @return TRUE if all OK - */ -bool get_suboption(char *str, mysuboption *opt){ - int findsubopt(char *par, mysuboption *so){ - int idx = 0; - if(!par) return -1; - while(so[idx].name){ - if(strcasecmp(par, so[idx].name) == 0) return idx; - ++idx; - } - return -1; // badarg - } - bool opt_setarg(mysuboption *so, int idx, char *val){ - mysuboption *soptr = &so[idx]; - bool result = FALSE; - void *aptr = soptr->argptr; - switch(soptr->type){ - default: - case arg_none: - if(soptr->argptr) *((int*)aptr) += 1; // increment value - result = TRUE; - break; - case arg_int: - result = myatoll(aptr, val, arg_int); - break; - case arg_longlong: - result = myatoll(aptr, val, arg_longlong); - break; - case arg_double: - result = myatod(aptr, val, arg_double); - break; - case arg_float: - result = myatod(aptr, val, arg_float); - break; - case arg_string: - result = (*((void**)aptr) = (void*)strdup(val)); - break; - case arg_function: - result = ((argfn)aptr)(val); - break; - } - return result; - } - char *tok; - bool ret = FALSE; - char *tmpbuf; - tok = strtok_r(str, ":,", &tmpbuf); - do{ - char *val = strchr(tok, '='); - int noarg = 0; - if(val == NULL){ // no args - val = "1"; - noarg = 1; - }else{ - *val++ = '\0'; - if(!*val || *val == ':' || *val == ','){ // no argument - delimeter after = - val = "1"; noarg = 1; - } - } - int idx = findsubopt(tok, opt); - if(idx < 0){ - /// "Неправильный параметр: %s" - WARNX(_("Wrong parameter: %s"), tok); - goto returning; - } - if(noarg && opt[idx].has_arg == NEED_ARG){ - /// "%s: необходим аргумент!" - WARNX(_("%s: argument needed!"), tok); - goto returning; - } - if(!opt_setarg(opt, idx, val)){ - /// "Неправильный аргумент \"%s\" параметра \"%s\"" - WARNX(_("Wrong argument \"%s\" of parameter \"%s\""), val, tok); - goto returning; - } - }while((tok = strtok_r(NULL, ":,", &tmpbuf))); - ret = TRUE; -returning: - return ret; -} diff --git a/MMPP_control/parseargs.h b/MMPP_control/parseargs.h deleted file mode 100644 index a0ac099..0000000 --- a/MMPP_control/parseargs.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * parseargs.h - headers for parsing command line arguments - * - * Copyright 2013 Edward V. Emelianoff - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ -#pragma once -#ifndef __PARSEARGS_H__ -#define __PARSEARGS_H__ - -#include // bool -#include - -#ifndef TRUE - #define TRUE true -#endif - -#ifndef FALSE - #define FALSE false -#endif - -// macro for argptr -#define APTR(x) ((void*)x) - -// if argptr is a function: -typedef bool(*argfn)(void *arg); - -/* - * type of getopt's argument - * WARNING! - * My function change value of flags by pointer, so if you want to use another type - * make a latter conversion, example: - * char charg; - * int iarg; - * myoption opts[] = { - * {"value", 1, NULL, 'v', arg_int, &iarg, "char val"}, ..., end_option}; - * ..(parse args).. - * charg = (char) iarg; - */ -typedef enum { - arg_none = 0, // no arg - arg_int, // integer - arg_longlong, // long long - arg_double, // double - arg_float, // float - arg_string, // char * - arg_function // parse_args will run function `bool (*fn)(char *optarg, int N)` -} argtype; - -/* - * Structure for getopt_long & help - * BE CAREFUL: .argptr is pointer to data or pointer to function, - * conversion depends on .type - * - * ATTENTION: string `help` prints through macro PRNT(), bu default it is gettext, - * but you can redefine it before `#include "parseargs.h"` - * - * if arg is string, then value wil be strdup'ed like that: - * char *str; - * myoption opts[] = {{"string", 1, NULL, 's', arg_string, &str, "string val"}, ..., end_option}; - * *(opts[1].str) = strdup(optarg); - * in other cases argptr should be address of some variable (or pointer to allocated memory) - * - * NON-NULL argptr should be written inside macro APTR(argptr) or directly: (void*)argptr - * - * !!!LAST VALUE OF ARRAY SHOULD BE `end_option` or ZEROS !!! - * - */ -typedef enum{ - NO_ARGS = 0, // first three are the same as in getopt_long - NEED_ARG = 1, - OPT_ARG = 2, - MULT_PAR -} hasarg; - -typedef struct{ - // these are from struct option: - const char *name; // long option's name - hasarg has_arg; // 0 - no args, 1 - nesessary arg, 2 - optionally arg, 4 - need arg & key can repeat (args are stored in null-terminated array) - int *flag; // NULL to return val, pointer to int - to set its value of val (function returns 0) - int val; // short opt name (if flag == NULL) or flag's value - // and these are mine: - argtype type; // type of argument - void *argptr; // pointer to variable to assign optarg value or function `bool (*fn)(char *optarg, int N)` - const char *help; // help string which would be shown in function `showhelp` or NULL -} myoption; - -/* - * Suboptions structure, almost the same like myoption - * used in parse_subopts() - */ -typedef struct{ - const char *name; - hasarg has_arg; - argtype type; - void *argptr; -} mysuboption; - -// last string of array (all zeros) -#define end_option {0,0,0,0,0,0,0} -#define end_suboption {0,0,0,0} - -extern const char *__progname; - -void showhelp(int oindex, myoption *options); -void parseargs(int *argc, char ***argv, myoption *options); -void change_helpstring(char *s); -bool get_suboption(char *str, mysuboption *opt); - -#endif // __PARSEARGS_H__ diff --git a/MMPP_control/tty_procs.c b/MMPP_control/tty_procs.c index 86f83a6..79c4648 100644 --- a/MMPP_control/tty_procs.c +++ b/MMPP_control/tty_procs.c @@ -20,16 +20,20 @@ * MA 02110-1301, USA. * */ - -#include "tty_procs.h" #include "cmdlnopts.h" // for `verbose` -#include "usefull_macros.h" +#include "tty_procs.h" +#include +#include +#include +#include // tty Rx static buffer #define TBUFLEN (1024) // read timeout (in seconds) #define TTYTIMEOUT (0.05) +static TTY_descr *dev = NULL; + // two buffers for data static char buf[TBUFLEN+1]; static char bufo[TBUFLEN+1]; @@ -37,6 +41,23 @@ static char bufo[TBUFLEN+1]; static int motpos[3][2]; // motor's positions, 1 - number of mcu, 2 - number of motor static int reset[3]; // reset occured static int endswitches[3][2]; // ESW of motors: 0 - zero esw, 1 - limit esw, -1 - clear +static int alive[3] = {0,0,0}; // ==1 if controller answers, 0 if no + +/** + * @brief tty_tryopen - try to open serial device + * @param devnm - path to device + * @param spd - speed (number) + * @return 0 if all OK + */ +int tty_tryopen(char *devnm, int spd){ + dev = new_tty(devnm, spd, 256); + if(!tty_open(dev, TRUE)) return 1; + return 0; +} + +void tty_close(){ + close_tty(&dev); +} /** * read data from TTY @@ -46,21 +67,22 @@ static int endswitches[3][2]; // ESW of motors: 0 - zero esw, 1 - limit esw, -1 static char *tty_get(){ char *ptr = buf; size_t L = 0, l = TBUFLEN; -// double t0 = dtime(); -// while(dtime() - t0 < TTYTIMEOUT){ - while(1){ - size_t r = read_tty(ptr, l); - if(!r) break; - /*if(r) t0 = dtime(); - else{ - DBG("Nothing"); - continue; - }*/ - ptr[r] = 0; - DBG("next portion: %s", ptr); + double t0 = dtime(); + *ptr = 0; + while(dtime() - t0 < TTYTIMEOUT && l){ + size_t r = read_tty(dev); + if(!r) continue; + t0 = dtime(); + if(r > l) r = l; + DBG("got %zd bytes: %s", r, dev->buf); + strncpy(ptr, dev->buf, r); L += r; l -= r; ptr += r; } - if(L) return buf; + buf[L] = 0; + if(L){ + return buf; + } + DBG("no answer"); return NULL; } @@ -70,15 +92,14 @@ static char *tty_get(){ */ static size_t cpy2buf(char *string){ size_t l = strlen(string); - if(l > TBUFLEN){ + if(l > TBUFLEN-1){ WARNX(_("String too long! Nothing would be send.")); return 0; } - strcpy(buf, string); - if(buf[l-1] != '\n'){ - DBG("add \\n"); - buf[l++] = '\n'; - buf[l] = 0; + strcpy(bufo, string); + if(bufo[l-1] != '\n'){ + bufo[l++] = '\n'; + bufo[l] = 0; } return l; } @@ -90,7 +111,7 @@ static size_t cpy2buf(char *string){ static int ttysend(char *cmd){ size_t l = cpy2buf(cmd); if(!l) return 0; - if(write_tty(buf, l)) return 0; + if(write_tty(dev->comfd, bufo, l)) return 0; return 1; } @@ -106,34 +127,20 @@ char* tty_sendraw(char *string){ } /** - * Send given motor string command to port with answer analysis - * @return: - * -1 if failed - * 0 if started moving - * 1 if on endswitch and can't move further - * 2 if other error occured + * Send given string command to port with answer analysis + * @return status */ -int tty_sendcmd(char *cmd){ - if(!ttysend(cmd)) return -1; +ttysend_status tty_sendcmd(char *cmd){ + DBG("SEND: %s", cmd); + if(!ttysend(cmd)) return SEND_ERR; char *got = tty_get(); - if(!got) return -1; - if(strcmp(got, "ALL OK\n") == 0) return 0; - if(strcmp(got, "OnEndSwitch\n") == 0) return 1; - return 2; + if(!got) return SEND_ERR; + DBG("GOT: %s", got); + if(strcmp(got, "ALLOK\n") == 0) return SEND_ALLOK; + if(strcmp(got, "OnEndSwitch\n") == 0) return SEND_ESWITCH; + return SEND_OTHER; } -#if 0 -MOTOR0=SLEEP -POS0=43 -ESW00=RLSD -ESW01=HALL -MOTOR1=MOVE -STEPSLEFT1=6921 -POS1=3238 -ESW10=HALL -ESW11=RLSD -#endif - /** * return static buffer - value of `key` * NOT THREAD SAFE! @@ -148,7 +155,7 @@ static char *keyval(char *key){ ++got; char *el = strchr(got, '\n'); if(!el) return NULL; - size_t L = el - got; + size_t L = (size_t)(el - got); if(L > 31 || L == 0 || !*got) return NULL; strncpy(buff, got, L); buff[L] = 0; @@ -197,48 +204,89 @@ static int parsestatus(char *cmd){ /** * Wait for all motors stop with current data indication + * @return 0 if all OK */ -void tty_wait(){ +int tty_wait(){ FNAME(); int failcount = 0, chk1 = 1, chk2 = 1; if(!quiet) green("Pol: M0ST M0LEFT M0POS - M1ST M1LEFT M1POS || L/4: M0ST M0LEFT M0POS - M1ST M1LEFT M1POS \n"); while(failcount < 5 && (chk1 || chk2)){ // 5 tries - chk1 = parsestatus("1GS"); - if(!quiet){ - printf("Pol: "); - if(chk1 == -1){ - chk1 = 1; - ++failcount; - printf("%39s", "failed"); - }else printf("%s", bufo); + if(alive[1]){ + chk1 = parsestatus("1GS"); + if(!quiet){ + printf("Pol: "); + if(chk1 == -1){ + chk1 = 1; + ++failcount; + printf("%39s", "failed "); + }else printf("%s", bufo); + } + }else{ + if(!quiet) printf("Pol: %39s", "failed "); + chk1 = 0; } - chk2 = parsestatus("2GS"); - if(!quiet){ - printf(" || L/4: "); - if(chk2 == -1){ - chk2 = 1; - ++failcount; - printf("%39s", "failed"); - }else printf("%s", bufo); - printf(" \r"); + if(alive[2]){ + chk2 = parsestatus("2GS"); + if(!quiet){ + printf(" || L/4: "); + if(chk2 == -1){ + chk2 = 1; + ++failcount; + printf("%38s", "failed"); + }else printf("%s", bufo); + printf(" \r"); + } + }else{ + if(!quiet) printf(" || L/4: %38s\r", "failed"); + chk2 = 0; } - //usleep(100000); } if(!quiet) printf("\n\n"); - if(failcount > 4) WARNX(_("Can't get status answer!")); + if(failcount > 4){ + WARNX(_("Can't get status answer!")); + return 1; + } + return 0; } -void tty_getstatus(){ - FNAME(); - int chk1, chk2; +#if 0 +MOTOR0=SLEEP +POS0=43 +ESW00=RLSD +ESW01=HALL +MOTOR1=MOVE +STEPSLEFT1=6921 +POS1=3238 +ESW10=HALL +ESW11=RLSD +#endif + +// tty_getstatus when `quiet==1` +static void ttystatq(){ + char st[4] = "xGS"; + char *nm[3] = {NULL, "POL", "L4"}; + for(int Nmcu = 1; Nmcu < 3; ++Nmcu){ + if(!alive[Nmcu]) continue; + st[0] = '0' + Nmcu; + if(!tty_sendraw(st)) continue; + char *str = strtok(buf, "\n"); + while(str){ + printf("%s%s\n", nm[Nmcu], str); + str = strtok(NULL, "\n"); + } + } +} + +// tty_getstatus when `quiet==0` +static void ttystat(){ + int chk1 = -1, chk2 = -1; char buff[TBUFLEN+1]; - if(!quiet) - green("Pol: M0ST M0LEFT M0POS - M1ST M1LEFT M1POS || L/4: M0ST M0LEFT M0POS - M1ST M1LEFT M1POS \n"); - chk1 = parsestatus("1GS"); - printf("Pol: "); + if(!quiet) green("Pol: M0ST M0LEFT M0POS - M1ST M1LEFT M1POS || L/4: M0ST M0LEFT M0POS - M1ST M1LEFT M1POS \n"); + if(alive[1]) chk1 = parsestatus("1GS"); + if(!quiet) printf("Pol: "); if(chk1 == -1){ - printf("%39s", "failed"); + if(!quiet) printf("%39s", "failed "); }else printf("%s", bufo); char *val = keyval("ESW00"); if(!val) val = " "; @@ -252,10 +300,10 @@ void tty_getstatus(){ val = keyval("ESW11"); if(!val) val = " "; sprintf(&buff[18], "%5s ", val); - chk2 = parsestatus("2GS"); + if(alive[2]) chk2 = parsestatus("2GS"); printf(" || L/4: "); if(chk2 == -1){ - printf("%39s", "failed"); + printf("%38s", "failed"); }else printf("%s", bufo); printf("\n"); sprintf(&buff[24], "|| "); @@ -273,31 +321,51 @@ void tty_getstatus(){ if(!val) val = " "; sprintf(&buff[45], "%5s ", val); // end-switches - if(!quiet) green("ESW00 ESW01 ESW10 ESW11 || ESW00 ESW01 ESW10 ESW11\n"); + green("ESW00 ESW01 ESW10 ESW11 || ESW00 ESW01 ESW10 ESW11\n"); printf("%s\n", buff); for(int i = 1; i < 3; ++i){ if(reset[i]) printf("RESET%d=1\n", i); } } +void tty_getstatus(){ + FNAME(); + if(quiet) ttystatq(); + else ttystat(); +} + /** * Show temperature of both MCU + * @return amount of successful calls */ -void tty_showtemp(){ +int tty_showtemp(){ char *val, buff[] = "xGT\n"; + const char *nm[3] = {NULL, "POL", "L4"}; + int ret = 0; for(int i = 1; i < 3; ++i){ - buff[0] = '0' + i; + if(!alive[i]){ + DBG("MCU %d didn't respond!", i); + continue; + } + buff[0] = '0' + (char)i; if(tty_sendraw(buff)){ val = keyval("TEMP"); if(val){ + ++ret; double t; if(str2double(&t, val)){ - green("MCU%d temperature: %g degC\n", i, t/10.); + if(quiet){ + printf("%sTEMP=%g\n", nm[i], t/10.); + }else{ + green("MCU%d temperature:", i); + printf(" %g degC\n", t/10.); + } } } } } + return ret; } /** @@ -318,7 +386,7 @@ int mot_getpos(int mcu, int motor){ /** * get motor endswitches status - * + * @return -1 if error or intermediate position, 0 - on zero's esw, 1 - on end's esw */ int mot_getesw(int mcu, int motor){ if(mcu < 1 || mcu > 2){ @@ -335,20 +403,28 @@ int mot_getesw(int mcu, int motor){ /** * test connection (1,2 -> ALIVE) * and get positions + * @return 1 if none of MCU found, 0 if at least 1 found */ -void handshake(){ +int handshake(){ char buff[32], *val; int mcu, motor; + FNAME(); for(mcu = 1; mcu < 3; ++ mcu){ // check if MCU alive sprintf(buff, "%d", mcu); - int notresp = 0; - if(!tty_sendraw(buff)) notresp = 1; - else if(strcmp(buf, "ALIVE\n")) notresp = 1; + int notresp = 1; + // make HANDSHAKE_TRIES tries + for(int tr = 0; tr < HANDSHAKE_TRIES; ++tr){ + if(tty_sendraw(buff) && 0 == strcmp(buf, "ALIVE\n")){ + notresp = 0; + break; + } + } if(notresp){ WARNX(_("MCU %d not response!"), mcu); continue; } + alive[mcu] = 1; sprintf(buff, "%dGS", mcu); if(tty_sendraw(buff)){ // check reboot states @@ -358,12 +434,12 @@ void handshake(){ }else reset[mcu] = 0; for(motor = 0; motor < 2; ++motor){ - sprintf(buff, "MOTOR%d", motor); + /*sprintf(buff, "MOTOR%d", motor); val = keyval(buff); if(!val || strcmp(val, "SLEEP")){ motpos[mcu][motor] = INT_MIN; continue; - } + }*/ sprintf(buff, "POS%d", motor); val = keyval(buff); DBG("----%s=%s", buff, val); @@ -387,4 +463,74 @@ void handshake(){ motpos[mcu][1] = INT_MIN; } } + if(alive[1] == 0 && alive[2] == 0) return 1; + return 0; } + +/** + * @brief tty_stopall - send commands to stop all motors + * @return 0 if all OK, else return amount of motors failed to stop + */ +int tty_stopall(){ + int ret = 4; + if(alive[1]){ + if(SEND_ALLOK == tty_sendcmd("1M0S")) --ret; + if(SEND_ALLOK == tty_sendcmd("1M1S")) --ret; + } + if(alive[2]){ + if(SEND_ALLOK == tty_sendcmd("2M0S")) --ret; + if(SEND_ALLOK == tty_sendcmd("2M1S")) --ret; + } + return ret; +} + +/** + * @brief init_motors - init all motors simultaneously (if they need to) + * @return 0 if all OK, or Nmcu*10+motnum for problem motor + */ +int init_motors(){ +#define RETVAL() (Nmcu*10+motnum) + int Nmcu, motnum, needinit = 0; + for(Nmcu = 1; Nmcu < 3; ++Nmcu){ + for(motnum = 0; motnum < 2; ++motnum){ + // check position + int pos = motpos[Nmcu][motnum]; + if(pos == INT_MIN) continue; // communication error on handshake + if(pos < 0) needinit = 1; + }} + if(!needinit) return 0; + DBG("Need to init, start!"); + for(Nmcu = 1; Nmcu < 3; ++Nmcu){ + for(motnum = 0; motnum < 2; ++motnum){ + int pos = motpos[Nmcu][motnum]; + if(pos >= 0) continue; + // check if we are on zero endswitch + int esw = mot_getesw(Nmcu, motnum); + if(esw == 0){ // move a little from zero esw + sprintf(buf, "%dM%dM100", Nmcu, motnum); + if(SEND_ERR == tty_sendcmd(buf)){ + WARNX(_("Can't move from endswitch")); + return RETVAL(); + } + tty_wait(); + } + sprintf(buf, "%dM%dM-40000", Nmcu, motnum); + if(SEND_ALLOK != tty_sendcmd(buf)){ + WARNX(_("Can't move to endwsitch 0")); + return RETVAL(); + } + }} + tty_wait(); + handshake(); + for(Nmcu = 1; Nmcu < 3; ++Nmcu){ + for(motnum = 0; motnum < 2; ++motnum){ + int curpos = mot_getpos(Nmcu, motnum); + if(curpos){ + WARNX(_("Can't return to zero")); + return RETVAL(); + } + }} + return 0; +#undef RETVAL +} + diff --git a/MMPP_control/tty_procs.h b/MMPP_control/tty_procs.h index 6a6986d..6c26f0f 100644 --- a/MMPP_control/tty_procs.h +++ b/MMPP_control/tty_procs.h @@ -1,5 +1,4 @@ /* - * geany_encoding=koi8-r * tty_procs.h * * Copyright 2018 Edward V. Emelianov @@ -20,14 +19,36 @@ * MA 02110-1301, USA. * */ +#pragma once +#ifndef TTY_PROCS_H__ +#define TTY_PROCS_H__ #include +// amount of tries to establish handshake +#define HANDSHAKE_TRIES (10) +// steps per full revolution for both rotation stages (1 - polaroid, 2 - waveplate) +#define STEPSREV1 (36000) +#define STEPSREV2 (28800) + +typedef enum{ + SEND_ERR, + SEND_ALLOK, + SEND_ESWITCH, + SEND_OTHER +} ttysend_status; + +int tty_tryopen(char *dev, int spd); +void tty_close(); char* tty_sendraw(char *string); -void tty_wait(); -int tty_sendcmd(char *cmd); -void tty_showtemp(); +int tty_wait(); +ttysend_status tty_sendcmd(char *cmd); +int tty_showtemp(); +int tty_stopall(); void tty_getstatus(); -void handshake(); +int handshake(); int mot_getpos(int mcu, int motor); int mot_getesw(int mcu, int motor); +int init_motors(); + +#endif // TTY_PROCS_H__ diff --git a/MMPP_control/usefull_macros.c b/MMPP_control/usefull_macros.c deleted file mode 100644 index a7b9cce..0000000 --- a/MMPP_control/usefull_macros.c +++ /dev/null @@ -1,372 +0,0 @@ -/* - * usefull_macros.h - a set of usefull functions: memory, color etc - * - * Copyright 2013 Edward V. Emelianoff - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -#include "usefull_macros.h" - -/** - * function for different purposes that need to know time intervals - * @return double value: time in seconds - */ -double dtime(){ - double t; - struct timeval tv; - gettimeofday(&tv, NULL); - t = tv.tv_sec + ((double)tv.tv_usec)/1e6; - return t; -} - -/******************************************************************************\ - * Coloured terminal -\******************************************************************************/ -int globErr = 0; // errno for WARN/ERR - -// pointers to coloured output printf -int (*red)(const char *fmt, ...); -int (*green)(const char *fmt, ...); -int (*_WARN)(const char *fmt, ...); - -/* - * format red / green messages - * name: r_pr_, g_pr_ - * @param fmt ... - printf-like format - * @return number of printed symbols - */ -int r_pr_(const char *fmt, ...){ - va_list ar; int i; - printf(RED); - va_start(ar, fmt); - i = vprintf(fmt, ar); - va_end(ar); - printf(OLDCOLOR); - return i; -} -int g_pr_(const char *fmt, ...){ - va_list ar; int i; - printf(GREEN); - va_start(ar, fmt); - i = vprintf(fmt, ar); - va_end(ar); - printf(OLDCOLOR); - return i; -} -/* - * print red error/warning messages (if output is a tty) - * @param fmt ... - printf-like format - * @return number of printed symbols - */ -int r_WARN(const char *fmt, ...){ - va_list ar; int i = 1; - fprintf(stderr, RED); - va_start(ar, fmt); - if(globErr){ - errno = globErr; - vwarn(fmt, ar); - errno = 0; - }else - i = vfprintf(stderr, fmt, ar); - va_end(ar); - i++; - fprintf(stderr, OLDCOLOR "\n"); - return i; -} - -static const char stars[] = "****************************************"; -/* - * notty variants of coloured printf - * name: s_WARN, r_pr_notty - * @param fmt ... - printf-like format - * @return number of printed symbols - */ -int s_WARN(const char *fmt, ...){ - va_list ar; int i; - i = fprintf(stderr, "\n%s\n", stars); - va_start(ar, fmt); - if(globErr){ - errno = globErr; - vwarn(fmt, ar); - errno = 0; - }else - i = +vfprintf(stderr, fmt, ar); - va_end(ar); - i += fprintf(stderr, "\n%s\n", stars); - i += fprintf(stderr, "\n"); - return i; -} -int r_pr_notty(const char *fmt, ...){ - va_list ar; int i; - i = printf("\n%s\n", stars); - va_start(ar, fmt); - i += vprintf(fmt, ar); - va_end(ar); - i += printf("\n%s\n", stars); - return i; -} - -/** - * Run this function in the beginning of main() to setup locale & coloured output - */ -void initial_setup(){ - // setup coloured output - if(isatty(STDOUT_FILENO)){ // make color output in tty - red = r_pr_; green = g_pr_; - }else{ // no colors in case of pipe - red = r_pr_notty; green = printf; - } - if(isatty(STDERR_FILENO)) _WARN = r_WARN; - else _WARN = s_WARN; - // Setup locale - setlocale(LC_ALL, ""); - setlocale(LC_NUMERIC, "C"); -#if defined GETTEXT_PACKAGE && defined LOCALEDIR - bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); - textdomain(GETTEXT_PACKAGE); -#endif -} - -/******************************************************************************\ - * Memory -\******************************************************************************/ -/* - * safe memory allocation for macro ALLOC - * @param N - number of elements to allocate - * @param S - size of single element (typically sizeof) - * @return pointer to allocated memory area - */ -void *my_alloc(size_t N, size_t S){ - void *p = calloc(N, S); - if(!p) ERR("malloc"); - //assert(p); - return p; -} - -/** - * Mmap file to a memory area - * - * @param filename (i) - name of file to mmap - * @return stuct with mmap'ed file or die - */ -mmapbuf *My_mmap(char *filename){ - int fd; - char *ptr; - size_t Mlen; - struct stat statbuf; - /// "Не задано имя файла!" - if(!filename){ - WARNX(_("No filename given!")); - return NULL; - } - if((fd = open(filename, O_RDONLY)) < 0){ - /// "Не могу открыть %s для чтения" - WARN(_("Can't open %s for reading"), filename); - return NULL; - } - if(fstat (fd, &statbuf) < 0){ - /// "Не могу выполнить stat %s" - WARN(_("Can't stat %s"), filename); - close(fd); - return NULL; - } - Mlen = statbuf.st_size; - if((ptr = mmap (0, Mlen, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED){ - /// "Ошибка mmap" - WARN(_("Mmap error for input")); - close(fd); - return NULL; - } - /// "Не могу закрыть mmap'нутый файл" - if(close(fd)) WARN(_("Can't close mmap'ed file")); - mmapbuf *ret = MALLOC(mmapbuf, 1); - ret->data = ptr; - ret->len = Mlen; - return ret; -} - -void My_munmap(mmapbuf *b){ - if(munmap(b->data, b->len)){ - /// "Не могу munmap" - WARN(_("Can't munmap")); - } - FREE(b); -} - - -/******************************************************************************\ - * Terminal in no-echo mode -\******************************************************************************/ -static struct termios oldt, newt; // terminal flags -static int console_changed = 0; -// run on exit: -void restore_console(){ - if(console_changed) - tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // return terminal to previous state - console_changed = 0; -} - -// initial setup: -void setup_con(){ - if(console_changed) return; - tcgetattr(STDIN_FILENO, &oldt); - newt = oldt; - newt.c_lflag &= ~(ICANON | ECHO); - if(tcsetattr(STDIN_FILENO, TCSANOW, &newt) < 0){ - /// "Не могу настроить консоль" - WARN(_("Can't setup console")); - tcsetattr(STDIN_FILENO, TCSANOW, &oldt); - signals(0); //quit? - } - console_changed = 1; -} - -/** - * Read character from console without echo - * @return char readed - */ -int read_console(){ - int rb; - struct timeval tv; - int retval; - fd_set rfds; - FD_ZERO(&rfds); - FD_SET(STDIN_FILENO, &rfds); - tv.tv_sec = 0; tv.tv_usec = 10000; - retval = select(1, &rfds, NULL, NULL, &tv); - if(!retval) rb = 0; - else { - if(FD_ISSET(STDIN_FILENO, &rfds)) rb = getchar(); - else rb = 0; - } - return rb; -} - -/** - * getchar() without echo - * wait until at least one character pressed - * @return character readed - */ -int mygetchar(){ // getchar() without need of pressing ENTER - int ret; - do ret = read_console(); - while(ret == 0); - return ret; -} - - -/******************************************************************************\ - * TTY with select() -\******************************************************************************/ -static struct termio oldtty, tty; // TTY flags -static int comfd = -1; // TTY fd - -// run on exit: -void restore_tty(){ - if(comfd == -1) return; - ioctl(comfd, TCSANOW, &oldtty ); // return TTY to previous state - close(comfd); - comfd = -1; -} - -#ifndef BAUD_RATE -#define BAUD_RATE B9600 -#endif -// init: -void tty_init(char *comdev){ - DBG("\nOpen port %s with baudrate %s", comdev, STRING(BAUD_RATE)); - //if ((comfd = open(comdev, O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0){ - if ((comfd = open(comdev, O_RDWR|O_NOCTTY)) < 0){ - WARN("Can't use port %s\n",comdev); - signals(0); // quit? - } - DBG(" OK\nGet current settings... "); - if(ioctl(comfd,TCGETA,&oldtty) < 0){ // Get settings - /// "Не могу получить настройки" - WARN(_("Can't get settings")); - signals(0); - } - tty = oldtty; - tty.c_lflag = ICANON; // ~(ICANON | ECHO | ECHOE | ISIG) - tty.c_oflag = 0; - tty.c_cflag = BAUD_RATE|CS8|CREAD|CLOCAL; // 9.6k, 8N1, RW, ignore line ctrl - tty.c_cc[VMIN] = 0; // non-canonical mode with - tty.c_cc[VTIME] = 1; // polling read with max 0.1s pause - if(ioctl(comfd,TCSETA,&tty) < 0){ - /// "Не могу установить настройки" - WARN(_("Can't set settings")); - signals(0); - } - DBG(" OK\n"); -} -/** - * Read data from TTY - * @param buff (o) - buffer for data read - * @param length - buffer len - * @return amount of bytes read - */ -size_t read_tty(char *buff, size_t length){ - ssize_t L = 0; - fd_set rfds; - struct timeval tv; - int retval; - FD_ZERO(&rfds); - FD_SET(comfd, &rfds); - tv.tv_sec = 0; tv.tv_usec = 50000; // wait for 50ms max - retval = select(comfd + 1, &rfds, NULL, NULL, &tv); - if (!retval) return 0; - if(FD_ISSET(comfd, &rfds)){ - if((L = read(comfd, buff, length)) < 1){ - WARNX(_("Terminal disconnected!")); - return 0; - } - } - return (size_t)L; -} - -int write_tty(char *buff, size_t length){ - ssize_t L = write(comfd, buff, length); - if((size_t)L != length){ - DBG("L = %zd, len=%zd", L, length); - /// "Ошибка записи!" - WARN("Write error!"); - return 1; - } - return 0; -} - - -/** - * Safely convert data from string to double - * - * @param num (o) - double number read from string - * @param str (i) - input string - * @return 1 if success, 0 if fails - */ -int str2double(double *num, const char *str){ - double res; - char *endptr; - if(!str) return 0; - res = strtod(str, &endptr); - if(endptr == str || *str == '\0' || *endptr != '\0'){ - /// "Неправильный формат числа double!" - WARNX("Wrong double number format!"); - return FALSE; - } - if(num) *num = res; // you may run it like myatod(NULL, str) to test wether str is double number - return TRUE; -} diff --git a/MMPP_control/usefull_macros.h b/MMPP_control/usefull_macros.h deleted file mode 100644 index e5cf42b..0000000 --- a/MMPP_control/usefull_macros.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * usefull_macros.h - a set of usefull macros: memory, color etc - * - * Copyright 2013 Edward V. Emelianoff - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -#pragma once -#ifndef __USEFULL_MACROS_H__ -#define __USEFULL_MACROS_H__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined GETTEXT_PACKAGE && defined LOCALEDIR -/* - * GETTEXT - */ -#include -#define _(String) gettext(String) -#define gettext_noop(String) String -#define N_(String) gettext_noop(String) -#else -#define _(String) (String) -#define N_(String) (String) -#endif -#include -#include -#include -#include -#include -#include - - -// unused arguments with -Wall -Werror -#define _U_ __attribute__((__unused__)) - -#define ASTRING(MACRO) #MACRO -#define STRING(MACRO) ASTRING(MACRO) - -/* - * Coloured messages output - */ -#define RED "\033[1;31;40m" -#define GREEN "\033[1;32;40m" -#define OLDCOLOR "\033[0;0;0m" - -#ifndef FALSE -#define FALSE (0) -#endif - -#ifndef TRUE -#define TRUE (1) -#endif - -/* - * ERROR/WARNING messages - */ -extern int globErr; -extern void signals(int sig); -#define ERR(...) do{globErr=errno; _WARN(__VA_ARGS__); signals(9);}while(0) -#define ERRX(...) do{globErr=0; _WARN(__VA_ARGS__); signals(9);}while(0) -#define WARN(...) do{globErr=errno; _WARN(__VA_ARGS__);}while(0) -#define WARNX(...) do{globErr=0; _WARN(__VA_ARGS__);}while(0) - -/* - * print function name, debug messages - * debug mode, -DEBUG - */ -#ifdef EBUG - #define FNAME() fprintf(stderr, "\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__) - #define DBG(...) do{fprintf(stderr, "%s (%s, line %d): ", __func__, __FILE__, __LINE__); \ - fprintf(stderr, __VA_ARGS__); \ - fprintf(stderr, "\n");} while(0) -#else - #define FNAME() do{}while(0) - #define DBG(...) do{}while(0) -#endif //EBUG - -/* - * Memory allocation - */ -#define ALLOC(type, var, size) type * var = ((type *)my_alloc(size, sizeof(type))) -#define MALLOC(type, size) ((type *)my_alloc(size, sizeof(type))) -#define FREE(ptr) do{if(ptr){free(ptr); ptr = NULL;}}while(0) - -#ifndef DBL_EPSILON -#define DBL_EPSILON (2.2204460492503131e-16) -#endif - -double dtime(); - -// functions for color output in tty & no-color in pipes -extern int (*red)(const char *fmt, ...); -extern int (*_WARN)(const char *fmt, ...); -extern int (*green)(const char *fmt, ...); -void * my_alloc(size_t N, size_t S); -void initial_setup(); - -// mmap file -typedef struct{ - char *data; - size_t len; -} mmapbuf; -mmapbuf *My_mmap(char *filename); -void My_munmap(mmapbuf *b); - -void restore_console(); -void setup_con(); -int read_console(); -int mygetchar(); - -void restore_tty(); -void tty_init(char *comdev); -size_t read_tty(char *buff, size_t length); -int write_tty(char *buff, size_t length); - -int str2double(double *num, const char *str); - -#endif // __USEFULL_MACROS_H__ diff --git a/STM32/inc/gen042 b/STM32/inc/gen042 old mode 100755 new mode 100644 diff --git a/STM32/steppers/main.c b/STM32/steppers/main.c index 49cee6c..c544fca 100644 --- a/STM32/steppers/main.c +++ b/STM32/steppers/main.c @@ -85,7 +85,7 @@ void iwdg_setup(){ } int main(void){ - //uint32_t lastT = 0; + uint32_t lastT = 0; uint32_t ostctr = 0; #if 0 //def EBUG @@ -104,9 +104,10 @@ int main(void){ //pin_set(GPIOA, 1<<5); // clear extern LED while (1){ IWDG->KR = IWDG_REFRESH; // refresh watchdog - /*if(lastT > Tms || Tms - lastT > 499){ + if(lastT > Tms || Tms - lastT > 499){ + sendbuf(); lastT = Tms; - }*/ + } if(usart1rx()){ // usart1 received data, store in in buffer if(usart1_getline(&txt)){ ret = process_command(txt); diff --git a/STM32/steppers/steppers.bin b/STM32/steppers/steppers.bin old mode 100755 new mode 100644 diff --git a/electronics/fp-info-cache b/electronics/fp-info-cache new file mode 100644 index 0000000..573541a --- /dev/null +++ b/electronics/fp-info-cache @@ -0,0 +1 @@ +0 diff --git a/electronics/hall_and_usb_pcb.pdf b/electronics/hall_and_usb:pcb.pdf similarity index 100% rename from electronics/hall_and_usb_pcb.pdf rename to electronics/hall_and_usb:pcb.pdf diff --git a/electronics/steppers.pro b/electronics/steppers.pro index 207b9a0..48c87a5 100644 --- a/electronics/steppers.pro +++ b/electronics/steppers.pro @@ -1,4 +1,4 @@ -update=п║я─ 16 я▐п╫п╡ 2019 08:21:59 +update=п╖я┌ 06 п╟п╡пЁ 2020 17:52:47 last_client=kicad [pcbnew] version=1 @@ -36,3 +36,13 @@ version=1 [eeschema] version=1 LibDir= +[schematic_editor] +version=1 +PageLayoutDescrFile= +PlotDirectoryName= +SubpartIdSeparator=0 +SubpartFirstId=65 +NetFmtName= +SpiceAjustPassiveValues=0 +LabSize=50 +ERC_TestSimilarLabels=1