mirror of
https://github.com/eddyem/BTA_utils.git
synced 2025-12-06 18:55:18 +03:00
add code for raspberry-pi based p1 derotator
This commit is contained in:
parent
26075401b4
commit
841ac20c88
48
p1rotator/Makefile
Normal file
48
p1rotator/Makefile
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# run `make DEF=...` to add extra defines
|
||||||
|
PROGRAM := p1rot
|
||||||
|
LDFLAGS := -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,--discard-all
|
||||||
|
LDFLAGS += -lcrypt -lm -pthread
|
||||||
|
#-lpthread
|
||||||
|
ifneq (,$(filter arm%, $(shell uname -m)))
|
||||||
|
LDFLAGS += -lwiringPi
|
||||||
|
endif
|
||||||
|
SRCS := $(wildcard *.c)
|
||||||
|
DEFINES := $(DEF) -D_GNU_SOURCE -D_XOPEN_SOURCE=1111
|
||||||
|
DEFINES += -DEBUG
|
||||||
|
OBJDIR := mk
|
||||||
|
CFLAGS += -O2 -Wall -Werror -Wextra -Wno-trampolines -std=gnu99 -pthread
|
||||||
|
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
|
||||||
344
p1rotator/bta_shdata.c
Normal file
344
p1rotator/bta_shdata.c
Normal file
@ -0,0 +1,344 @@
|
|||||||
|
#include "bta_shdata.h"
|
||||||
|
#include "usefull_macros.h"
|
||||||
|
|
||||||
|
#pragma pack(push, 4)
|
||||||
|
// Main command channel (level 5)
|
||||||
|
struct CMD_Queue mcmd = {{"Mcmd"}, 0200,0,-1,0};
|
||||||
|
// Operator command channel (level 4)
|
||||||
|
struct CMD_Queue ocmd = {{"Ocmd"}, 0200,0,-1,0};
|
||||||
|
// User command channel (level 2/3)
|
||||||
|
struct CMD_Queue ucmd = {{"Ucmd"}, 0200,0,-1,0};
|
||||||
|
|
||||||
|
#define MSGLEN (80)
|
||||||
|
static char msg[MSGLEN];
|
||||||
|
#define PERR(...) do{snprintf(msg, MSGLEN, __VA_ARGS__); perror(msg);} while(0)
|
||||||
|
|
||||||
|
#ifndef BTA_MODULE
|
||||||
|
volatile struct BTA_Data *sdt;
|
||||||
|
volatile struct BTA_Local *sdtl;
|
||||||
|
|
||||||
|
volatile struct SHM_Block sdat = {
|
||||||
|
{"Sdat"},
|
||||||
|
sizeof(struct BTA_Data),
|
||||||
|
2048,0444,
|
||||||
|
SHM_RDONLY,
|
||||||
|
bta_data_init,
|
||||||
|
bta_data_check,
|
||||||
|
bta_data_close,
|
||||||
|
ClientSide,-1,NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
int snd_id = -1; // client sender ID
|
||||||
|
int cmd_src_pid = 0; // next command source PID
|
||||||
|
uint32_t cmd_src_ip = 0;// next command source IP
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init data
|
||||||
|
*/
|
||||||
|
void bta_data_init() {
|
||||||
|
sdt = (struct BTA_Data *)sdat.addr;
|
||||||
|
sdtl = (struct BTA_Local *)(sdat.addr+sizeof(struct BTA_Data));
|
||||||
|
if(sdat.side == ClientSide) {
|
||||||
|
if(sdt->magic != sdat.key.code) {
|
||||||
|
WARN("Wrong shared data (maybe server turned off)");
|
||||||
|
}
|
||||||
|
if(sdt->version == 0) {
|
||||||
|
WARN("Null shared data version (maybe server turned off)");
|
||||||
|
}
|
||||||
|
else if(sdt->version != BTA_Data_Ver) {
|
||||||
|
WARN("Wrong shared data version: I'am - %d, but server - %d ...",
|
||||||
|
BTA_Data_Ver, sdt->version );
|
||||||
|
}
|
||||||
|
if(sdt->size != sdat.size) {
|
||||||
|
if(sdt->size > sdat.size) {
|
||||||
|
WARN("Wrong shared area size: I needs - %d, but server - %d ...",
|
||||||
|
sdat.size, sdt->size );
|
||||||
|
} else {
|
||||||
|
WARN("Attention! Too little shared data structure!");
|
||||||
|
WARN("I needs - %d, but server gives only %d ...",
|
||||||
|
sdat.size, sdt->size );
|
||||||
|
WARN("May be server's version too old!?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* ServerSide */
|
||||||
|
if(sdt->magic == sdat.key.code &&
|
||||||
|
sdt->version == BTA_Data_Ver &&
|
||||||
|
sdt->size == sdat.size)
|
||||||
|
return;
|
||||||
|
memset(sdat.addr, 0, sdat.maxsize);
|
||||||
|
sdt->magic = sdat.key.code;
|
||||||
|
sdt->version = BTA_Data_Ver;
|
||||||
|
sdt->size = sdat.size;
|
||||||
|
Tel_Hardware = Hard_On;
|
||||||
|
Pos_Corr = PC_On;
|
||||||
|
TrkOk_Mode = UseDiffVel | UseDiffAZ ;
|
||||||
|
inp_B = 591.;
|
||||||
|
Pressure = 595.;
|
||||||
|
PEP_code_A = 0x002aaa;
|
||||||
|
PEP_code_Z = 0x002aaa;
|
||||||
|
PEP_code_P = 0x002aaa;
|
||||||
|
PEP_code_F = 0x002aaa;
|
||||||
|
PEP_code_D = 0x002aaa;
|
||||||
|
DomeSEW_N = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bta_data_check() {
|
||||||
|
return( (sdt->magic == sdat.key.code) && (sdt->version == BTA_Data_Ver) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void bta_data_close() {
|
||||||
|
if(sdat.side == ServerSide) {
|
||||||
|
sdt->magic = 0;
|
||||||
|
sdt->version = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate shared memory segment
|
||||||
|
*/
|
||||||
|
int get_shm_block(volatile struct SHM_Block *sb, int server) {
|
||||||
|
int getsize = (server)? sb->maxsize : sb->size;
|
||||||
|
// first try to find existing one
|
||||||
|
sb->id = shmget(sb->key.code, getsize, sb->mode);
|
||||||
|
if(sb->id < 0 && errno == ENOENT && server){
|
||||||
|
// if no - try to create a new one
|
||||||
|
int cresize = sb->maxsize;
|
||||||
|
if(sb->size > cresize){
|
||||||
|
WARN("Wrong shm maxsize(%d) < realsize(%d)",sb->maxsize,sb->size);
|
||||||
|
cresize = sb->size;
|
||||||
|
}
|
||||||
|
sb->id = shmget(sb->key.code, cresize, IPC_CREAT|IPC_EXCL|sb->mode);
|
||||||
|
}
|
||||||
|
if(sb->id < 0){
|
||||||
|
if(server)
|
||||||
|
PERR("Can't create shared memory segment '%s'",sb->key.name);
|
||||||
|
else
|
||||||
|
PERR("Can't find shared segment '%s' (maybe no server process) ",sb->key.name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// attach it to our memory space
|
||||||
|
sb->addr = (unsigned char *) shmat(sb->id, NULL, sb->atflag);
|
||||||
|
if((long)sb->addr == -1){
|
||||||
|
PERR("Can't attach shared memory segment '%s'",sb->key.name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(server && (shmctl(sb->id, SHM_LOCK, NULL) < 0)){
|
||||||
|
PERR("Can't prevents swapping of shared memory segment '%s'",sb->key.name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
DBG("Create & attach shared memory segment '%s' %dbytes", sb->key.name, sb->size);
|
||||||
|
sb->side = server;
|
||||||
|
if(sb->init != NULL)
|
||||||
|
sb->init();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int close_shm_block(volatile struct SHM_Block *sb){
|
||||||
|
int ret;
|
||||||
|
if(sb->close != NULL)
|
||||||
|
sb->close();
|
||||||
|
if(sb->side == ServerSide) {
|
||||||
|
// ret = shmctl(sb->id, SHM_UNLOCK, NULL);
|
||||||
|
ret = shmctl(sb->id, IPC_RMID, NULL);
|
||||||
|
}
|
||||||
|
ret = shmdt (sb->addr);
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create|Find command queue
|
||||||
|
*/
|
||||||
|
void get_cmd_queue(struct CMD_Queue *cq, int server){
|
||||||
|
if (!server && cq->id >= 0) { //if already in use set current
|
||||||
|
snd_id = cq->id;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// first try to find existing one
|
||||||
|
cq->id = msgget(cq->key.code, cq->mode);
|
||||||
|
// if no - try to create a new one
|
||||||
|
if(cq->id<0 && errno == ENOENT && server)
|
||||||
|
cq->id = msgget(cq->key.code, IPC_CREAT|IPC_EXCL|cq->mode);
|
||||||
|
if(cq->id<0){
|
||||||
|
if(server)
|
||||||
|
PERR("Can't create comand queue '%s'",cq->key.name);
|
||||||
|
else
|
||||||
|
PERR("Can't find comand queue '%s' (maybe no server process) ",cq->key.name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cq->side = server;
|
||||||
|
if(server){
|
||||||
|
char buf[120]; /* выбросить все команды из очереди */
|
||||||
|
while(msgrcv(cq->id, (struct msgbuf *)buf, 112, 0, IPC_NOWAIT) > 0);
|
||||||
|
}else
|
||||||
|
snd_id = cq->id;
|
||||||
|
cq->acckey = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // BTA_MODULE
|
||||||
|
|
||||||
|
|
||||||
|
int check_shm_block(volatile struct SHM_Block *sb) {
|
||||||
|
if(sb->check)
|
||||||
|
return(sb->check());
|
||||||
|
else return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set access key in current channel
|
||||||
|
*/
|
||||||
|
void set_acckey(uint32_t newkey){
|
||||||
|
if(snd_id < 0) return;
|
||||||
|
if(ucmd.id == snd_id) ucmd.acckey = newkey;
|
||||||
|
else if(ocmd.id == snd_id) ocmd.acckey = newkey;
|
||||||
|
else if(mcmd.id == snd_id) mcmd.acckey = newkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup source data for one following command if default values
|
||||||
|
* (IP == 0 - local, PID = current) not suits
|
||||||
|
*/
|
||||||
|
void set_cmd_src(uint32_t ip, int pid) {
|
||||||
|
cmd_src_pid = pid;
|
||||||
|
cmd_src_ip = ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma pack(push, 4)
|
||||||
|
/**
|
||||||
|
* Send client commands to server
|
||||||
|
*/
|
||||||
|
void send_cmd(int cmd_code, char *buf, int size) {
|
||||||
|
struct my_msgbuf mbuf;
|
||||||
|
if(snd_id < 0) return;
|
||||||
|
if(size > 100) size = 100;
|
||||||
|
if(cmd_code > 0)
|
||||||
|
mbuf.mtype = cmd_code;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
if(ucmd.id == snd_id) mbuf.acckey = ucmd.acckey;
|
||||||
|
else if(ocmd.id == snd_id) mbuf.acckey = ocmd.acckey;
|
||||||
|
else if(mcmd.id == snd_id) mbuf.acckey = mcmd.acckey;
|
||||||
|
|
||||||
|
mbuf.src_pid = cmd_src_pid ? cmd_src_pid : getpid();
|
||||||
|
mbuf.src_ip = cmd_src_ip;
|
||||||
|
cmd_src_pid = cmd_src_ip = 0;
|
||||||
|
|
||||||
|
if(size > 0)
|
||||||
|
memcpy(mbuf.mtext, buf, size);
|
||||||
|
else {
|
||||||
|
mbuf.mtext[0] = 0;
|
||||||
|
size = 1;
|
||||||
|
}
|
||||||
|
msgsnd(snd_id, (struct msgbuf *)&mbuf, size+12, IPC_NOWAIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void send_cmd_noarg(int cmd_code) {
|
||||||
|
send_cmd(cmd_code, NULL, 0);
|
||||||
|
}
|
||||||
|
void send_cmd_str(int cmd_code, char *arg) {
|
||||||
|
send_cmd(cmd_code, arg, strlen(arg)+1);
|
||||||
|
}
|
||||||
|
void send_cmd_i1(int cmd_code, int32_t arg1) {
|
||||||
|
send_cmd(cmd_code, (char *)&arg1, sizeof(int32_t));
|
||||||
|
}
|
||||||
|
void send_cmd_i2(int cmd_code, int32_t arg1, int32_t arg2) {
|
||||||
|
int32_t ibuf[2];
|
||||||
|
ibuf[0] = arg1;
|
||||||
|
ibuf[1] = arg2;
|
||||||
|
send_cmd(cmd_code, (char *)ibuf, 2*sizeof(int32_t));
|
||||||
|
}
|
||||||
|
void send_cmd_i3(int cmd_code, int32_t arg1, int32_t arg2, int32_t arg3) {
|
||||||
|
int32_t ibuf[3];
|
||||||
|
ibuf[0] = arg1;
|
||||||
|
ibuf[1] = arg2;
|
||||||
|
ibuf[2] = arg3;
|
||||||
|
send_cmd(cmd_code, (char *)ibuf, 3*sizeof(int32_t));
|
||||||
|
}
|
||||||
|
void send_cmd_i4(int cmd_code, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4) {
|
||||||
|
int32_t ibuf[4];
|
||||||
|
ibuf[0] = arg1;
|
||||||
|
ibuf[1] = arg2;
|
||||||
|
ibuf[2] = arg3;
|
||||||
|
ibuf[3] = arg4;
|
||||||
|
send_cmd(cmd_code, (char *)ibuf, 4*sizeof(int32_t));
|
||||||
|
}
|
||||||
|
void send_cmd_d1(int32_t cmd_code, double arg1) {
|
||||||
|
send_cmd(cmd_code, (char *)&arg1, sizeof(double));
|
||||||
|
}
|
||||||
|
void send_cmd_d2(int cmd_code, double arg1, double arg2) {
|
||||||
|
double dbuf[2];
|
||||||
|
dbuf[0] = arg1;
|
||||||
|
dbuf[1] = arg2;
|
||||||
|
send_cmd(cmd_code, (char *)dbuf, 2*sizeof(double));
|
||||||
|
}
|
||||||
|
void send_cmd_i1d1(int cmd_code, int32_t arg1, double arg2) {
|
||||||
|
struct {
|
||||||
|
int32_t ival;
|
||||||
|
double dval;
|
||||||
|
} buf;
|
||||||
|
buf.ival = arg1;
|
||||||
|
buf.dval = arg2;
|
||||||
|
send_cmd(cmd_code, (char *)&buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
void send_cmd_i2d1(int cmd_code, int32_t arg1, int32_t arg2, double arg3) {
|
||||||
|
struct {
|
||||||
|
int32_t ival[2];
|
||||||
|
double dval;
|
||||||
|
} buf;
|
||||||
|
buf.ival[0] = arg1;
|
||||||
|
buf.ival[1] = arg2;
|
||||||
|
buf.dval = arg3;
|
||||||
|
send_cmd(cmd_code, (char *)&buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
void send_cmd_i3d1(int cmd_code, int32_t arg1, int32_t arg2, int32_t arg3, double arg4) {
|
||||||
|
struct {
|
||||||
|
int32_t ival[3];
|
||||||
|
double dval;
|
||||||
|
} buf;
|
||||||
|
buf.ival[0] = arg1;
|
||||||
|
buf.ival[1] = arg2;
|
||||||
|
buf.ival[2] = arg3;
|
||||||
|
buf.dval = arg4;
|
||||||
|
send_cmd(cmd_code, (char *)&buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
void encode_lev_passwd(char *passwd, int nlev, uint32_t *keylev, uint32_t *codlev){
|
||||||
|
char salt[4];
|
||||||
|
char *encr;
|
||||||
|
union {
|
||||||
|
uint32_t ui;
|
||||||
|
char c[4];
|
||||||
|
} key, cod;
|
||||||
|
sprintf(salt,"L%1d",nlev);
|
||||||
|
encr = (char *)crypt(passwd, salt);
|
||||||
|
cod.c[0] = encr[2];
|
||||||
|
key.c[0] = encr[3];
|
||||||
|
cod.c[1] = encr[4];
|
||||||
|
key.c[1] = encr[5];
|
||||||
|
cod.c[2] = encr[6];
|
||||||
|
key.c[2] = encr[7];
|
||||||
|
cod.c[3] = encr[8];
|
||||||
|
key.c[3] = encr[9];
|
||||||
|
*keylev = key.ui;
|
||||||
|
*codlev = cod.ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
int find_lev_passwd(char *passwd, uint32_t *keylev, uint32_t *codlev){
|
||||||
|
int nlev;
|
||||||
|
for(nlev = 5; nlev > 0; --nlev){
|
||||||
|
encode_lev_passwd(passwd, nlev, keylev, codlev);
|
||||||
|
if(*codlev == code_Lev(nlev)) break;
|
||||||
|
}
|
||||||
|
return(nlev);
|
||||||
|
}
|
||||||
|
|
||||||
|
int check_lev_passwd(char *passwd){
|
||||||
|
uint32_t keylev,codlev;
|
||||||
|
int nlev;
|
||||||
|
nlev = find_lev_passwd(passwd, &keylev, &codlev);
|
||||||
|
if(nlev > 0) set_acckey(keylev);
|
||||||
|
return(nlev);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
850
p1rotator/bta_shdata.h
Normal file
850
p1rotator/bta_shdata.h
Normal file
@ -0,0 +1,850 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef __BTA_SHDATA_H__
|
||||||
|
#define __BTA_SHDATA_H__
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/ipc.h>
|
||||||
|
#include <sys/shm.h>
|
||||||
|
#include <sys/msg.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#pragma pack(push, 4)
|
||||||
|
/*
|
||||||
|
* Shared memory block
|
||||||
|
*/
|
||||||
|
struct SHM_Block {
|
||||||
|
union {
|
||||||
|
char name[5]; // memory segment identificator
|
||||||
|
key_t code;
|
||||||
|
} key;
|
||||||
|
int32_t size; // size of memory used
|
||||||
|
int32_t maxsize; // size when created
|
||||||
|
int32_t mode; // access mode (rwxrwxrwx)
|
||||||
|
int32_t atflag; // connection mode (SHM_RDONLY or 0)
|
||||||
|
void (*init)(); // init function
|
||||||
|
int32_t (*check)(); // test function
|
||||||
|
void (*close)(); // deinit function
|
||||||
|
int32_t side; // connection type: client/server
|
||||||
|
int32_t id; // connection identificator
|
||||||
|
uint8_t *addr; // connection address
|
||||||
|
};
|
||||||
|
|
||||||
|
extern volatile struct SHM_Block sdat;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Command queue descriptor
|
||||||
|
*/
|
||||||
|
struct CMD_Queue {
|
||||||
|
union {
|
||||||
|
char name[5]; // queue key
|
||||||
|
key_t code;
|
||||||
|
} key;
|
||||||
|
int32_t mode; // access mode (rwxrwxrwx)
|
||||||
|
int32_t side; // connection type (Sender/Receiver - server/client)
|
||||||
|
int32_t id; // connection identificator
|
||||||
|
uint32_t acckey; // access key (for transmission from client to server)
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct CMD_Queue mcmd;
|
||||||
|
extern struct CMD_Queue ocmd;
|
||||||
|
extern struct CMD_Queue ucmd;
|
||||||
|
|
||||||
|
void send_cmd_noarg(int);
|
||||||
|
void send_cmd_str(int, char *);
|
||||||
|
void send_cmd_i1(int, int32_t);
|
||||||
|
void send_cmd_i2(int, int32_t, int32_t);
|
||||||
|
void send_cmd_i3(int, int32_t, int32_t, int32_t);
|
||||||
|
void send_cmd_i4(int, int32_t, int32_t, int32_t, int32_t);
|
||||||
|
void send_cmd_d1(int, double);
|
||||||
|
void send_cmd_d2(int, double, double);
|
||||||
|
void send_cmd_i1d1(int, int32_t, double);
|
||||||
|
void send_cmd_i2d1(int, int32_t, int32_t, double);
|
||||||
|
void send_cmd_i3d1(int, int32_t, int32_t, int32_t, double);
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Command list *
|
||||||
|
*******************************************************************************/
|
||||||
|
/* name code args type */
|
||||||
|
// Stop telescope
|
||||||
|
#define StopTel 1
|
||||||
|
#define StopTeleskope() send_cmd_noarg( 1 )
|
||||||
|
// High/low speed
|
||||||
|
#define StartHS 2
|
||||||
|
#define StartHighSpeed() send_cmd_noarg( 2 )
|
||||||
|
#define StartLS 3
|
||||||
|
#define StartLowSpeed() send_cmd_noarg( 3 )
|
||||||
|
// Timer setup (Ch7_15 or SysTimer)
|
||||||
|
#define SetTmr 4
|
||||||
|
#define SetTimerMode(T) send_cmd_i1 ( 4, (int)(T))
|
||||||
|
// Simulation (modeling) mode
|
||||||
|
#define SetModMod 5
|
||||||
|
#define SetModelMode(M) send_cmd_i1 ( 5, (int)(M))
|
||||||
|
// Azimuth speed code
|
||||||
|
#define SetCodA 6
|
||||||
|
#define SetPKN_A(iA,sA) send_cmd_i2 ( 6, (int)(iA),(int)(sA))
|
||||||
|
// Zenith speed code
|
||||||
|
#define SetCodZ 7
|
||||||
|
#define SetPKN_Z(iZ) send_cmd_i1 ( 7, (int)(iZ))
|
||||||
|
// Parangle speed code
|
||||||
|
#define SetCodP 8
|
||||||
|
#define SetPKN_P(iP) send_cmd_i1 ( 8, (int)(iP))
|
||||||
|
// Set Az velocity
|
||||||
|
#define SetVA 9
|
||||||
|
#define SetSpeedA(vA) send_cmd_d1 ( 9, (double)(vA))
|
||||||
|
// Set Z velocity
|
||||||
|
#define SetVZ 10
|
||||||
|
#define SetSpeedZ(vZ) send_cmd_d1 (10, (double)(vZ))
|
||||||
|
// Set P velocity
|
||||||
|
#define SetVP 11
|
||||||
|
#define SetSpeedP(vP) send_cmd_d1 (11, (double)(vP))
|
||||||
|
// Set new polar coordinates
|
||||||
|
#define SetAD 12
|
||||||
|
#define SetRADec(Alp,Del) send_cmd_d2 (12, (double)(Alp),(double)(Del))
|
||||||
|
// Set new azimutal coordinates
|
||||||
|
#define SetAZ 13
|
||||||
|
#define SetAzimZ(A,Z) send_cmd_d2 (13, (double)(A),(double)(Z))
|
||||||
|
// Goto new object by polar coords
|
||||||
|
#define GoToAD 14
|
||||||
|
#define GoToObject() send_cmd_noarg(14 )
|
||||||
|
// Start steering to object by polar coords
|
||||||
|
#define MoveToAD 15
|
||||||
|
#define MoveToObject() send_cmd_noarg(15 )
|
||||||
|
// Go to object by azimutal coords
|
||||||
|
#define GoToAZ 16
|
||||||
|
#define GoToAzimZ() send_cmd_noarg(16 )
|
||||||
|
// Set A&Z for simulation
|
||||||
|
#define WriteAZ 17
|
||||||
|
#define WriteModelAZ() send_cmd_noarg(17 )
|
||||||
|
// Set P2 mode
|
||||||
|
#define SetModP 18
|
||||||
|
#define SetPMode(pmod) send_cmd_i1 (18, (int)(pmod))
|
||||||
|
// Move(+-1)/Stop(0) P2
|
||||||
|
#define P2Move 19
|
||||||
|
#define MoveP2(dir) send_cmd_i1 (19, (int)(dir))
|
||||||
|
// Move(+-2,+-1)/Stop(0) focus
|
||||||
|
#define FocMove 20
|
||||||
|
#define MoveFocus(speed,time) send_cmd_i1d1(20,(int)(speed),(double)(time))
|
||||||
|
// Use/don't use pointing correction system
|
||||||
|
#define UsePCorr 21
|
||||||
|
#define SwitchPosCorr(pc_flag) send_cmd_i1 (21, (int)(pc_flag))
|
||||||
|
// Tracking flags
|
||||||
|
#define SetTrkFlags 22
|
||||||
|
#define SetTrkOkMode(trk_flags) send_cmd_i1 (22, (int)(trk_flags))
|
||||||
|
// Set focus (0 - primary, 1 - N1, 2 - N2)
|
||||||
|
#define SetTFoc 23
|
||||||
|
#define SetTelFocus(N) send_cmd_i1 ( 23, (int)(N))
|
||||||
|
// Set intrinsic move parameters by RA/Decl
|
||||||
|
#define SetVAD 24
|
||||||
|
#define SetVelAD(VAlp,VDel) send_cmd_d2 (24, (double)(VAlp),(double)(VDel))
|
||||||
|
// Reverse Azimuth direction when pointing
|
||||||
|
#define SetRevA 25
|
||||||
|
#define SetAzRevers(amod) send_cmd_i1 (25, (int)(amod))
|
||||||
|
// Set P2 velocity
|
||||||
|
#define SetVP2 26
|
||||||
|
#define SetVelP2(vP2) send_cmd_d1 (26, (double)(vP2))
|
||||||
|
// Set pointing target
|
||||||
|
#define SetTarg 27
|
||||||
|
#define SetSysTarg(Targ) send_cmd_i1 (27, (int)(Targ))
|
||||||
|
// Send message to all clients (+write into protocol)
|
||||||
|
#define SendMsg 28
|
||||||
|
#define SendMessage(Mesg) send_cmd_str (28, (char *)(Mesg))
|
||||||
|
// RA/Decl user correction
|
||||||
|
#define CorrAD 29
|
||||||
|
#define DoADcorr(dAlp,dDel) send_cmd_d2 (29, (double)(dAlp),(double)(dDel))
|
||||||
|
// A/Z user correction
|
||||||
|
#define CorrAZ 30
|
||||||
|
#define DoAZcorr(dA,dZ) send_cmd_d2 (30, (double)(dA),(double)(dZ))
|
||||||
|
// sec A/Z user correction speed
|
||||||
|
#define SetVCAZ 31
|
||||||
|
#define SetVCorr(vA,vZ) send_cmd_d2 (31, (double)(vA),(double)(vZ))
|
||||||
|
// move P2 with given velocity for a given time
|
||||||
|
#define P2MoveTo 32
|
||||||
|
#define MoveP2To(vP2,time) send_cmd_d2 (32, (double)(vP2),(double)(time))
|
||||||
|
// Go to t/Decl position
|
||||||
|
#define GoToTD 33
|
||||||
|
#define GoToSat() send_cmd_noarg (33 )
|
||||||
|
// Move to t/Decl
|
||||||
|
#define MoveToTD 34
|
||||||
|
#define MoveToSat() send_cmd_noarg (34 )
|
||||||
|
// Empty command for synchronisation
|
||||||
|
#define NullCom 35
|
||||||
|
#define SyncCom() send_cmd_noarg (35 )
|
||||||
|
// Button "Start"
|
||||||
|
#define StartTel 36
|
||||||
|
#define StartTeleskope() send_cmd_noarg(36 )
|
||||||
|
// Set telescope mode
|
||||||
|
#define SetTMod 37
|
||||||
|
#define SetTelMode(M) send_cmd_i1 ( 37, (int)(M))
|
||||||
|
// Turn telescope on (oil etc)
|
||||||
|
#define TelOn 38
|
||||||
|
#define TeleskopeOn() send_cmd_noarg(38 )
|
||||||
|
// Dome mode
|
||||||
|
#define SetModD 39
|
||||||
|
#define SetDomeMode(dmod) send_cmd_i1 (39, (int)(dmod))
|
||||||
|
// Move(+-3,+-2,+-1)/Stop(0) dome
|
||||||
|
#define DomeMove 40
|
||||||
|
#define MoveDome(speed,time) send_cmd_i1d1(40,(int)(speed),(double)(time))
|
||||||
|
// Set account password
|
||||||
|
#define SetPass 41
|
||||||
|
#define SetPasswd(LPass) send_cmd_str (41, (char *)(LPass))
|
||||||
|
// Set code of access level
|
||||||
|
#define SetLevC 42
|
||||||
|
#define SetLevCode(Nlev,Cod) send_cmd_i2(42, (int)(Nlev),(int)(Cod))
|
||||||
|
// Set key for access level
|
||||||
|
#define SetLevK 43
|
||||||
|
#define SetLevKey(Nlev,Key) send_cmd_i2(43, (int)(Nlev),(int)(Key))
|
||||||
|
// Setup network
|
||||||
|
#define SetNet 44
|
||||||
|
#define SetNetAcc(Mask,Addr) send_cmd_i2(44, (int)(Mask),(int)(Addr))
|
||||||
|
// Input meteo data
|
||||||
|
#define SetMet 45
|
||||||
|
#define SetMeteo(m_id,m_val) send_cmd_i1d1(45,(int)(m_id),(double)(m_val))
|
||||||
|
// Cancel meteo data
|
||||||
|
#define TurnMetOff 46
|
||||||
|
#define TurnMeteoOff(m_id) send_cmd_i1 (46, (int)(m_id))
|
||||||
|
// Set time correction (IERS DUT1=UT1-UTC)
|
||||||
|
#define SetDUT1 47
|
||||||
|
#define SetDtime(dT) send_cmd_d1 (47, (double)(dT))
|
||||||
|
// Set polar motion (IERS polar motion)
|
||||||
|
#define SetPM 48
|
||||||
|
#define SetPolMot(Xp,Yp) send_cmd_d2 (48, (double)(Xp),(double)(Yp))
|
||||||
|
// Get SEW parameter
|
||||||
|
#define GetSEW 49
|
||||||
|
#define GetSEWparam(Ndrv,Indx,Cnt) send_cmd_i3(49,(int)(Ndrv),(int)(Indx),(int)(Cnt))
|
||||||
|
// Set SEW parameter
|
||||||
|
#define PutSEW 50
|
||||||
|
#define PutSEWparam(Ndrv,Indx,Key,Val) send_cmd_i4(50,(int)(Ndrv),(int)(Indx),(int)(Key),(int)(Val))
|
||||||
|
// Set lock flags
|
||||||
|
#define SetLocks 51
|
||||||
|
#define SetLockFlags(f) send_cmd_i1 (SetLocks, (int)(f))
|
||||||
|
// Clear lock flags
|
||||||
|
#define ClearLocks 52
|
||||||
|
#define ClearLockFlags(f) send_cmd_i1 (ClearLocks, (int)(f))
|
||||||
|
// Set PEP-RK bits
|
||||||
|
#define SetRKbits 53
|
||||||
|
#define AddRKbits(f) send_cmd_i1 (SetRKbits, (int)(f))
|
||||||
|
// Clear PEP-RK bits
|
||||||
|
#define ClrRKbits 54
|
||||||
|
#define ClearRKbits(f) send_cmd_i1 (ClrRKbits, (int)(f))
|
||||||
|
// Set SEW dome motor number (for indication)
|
||||||
|
#define SetSEWnd 55
|
||||||
|
#define SetDomeDrive(ND) send_cmd_i1 (SetSEWnd, (int)(ND))
|
||||||
|
// Turn SEW controllers of dome on/off
|
||||||
|
#define SEWsDome 56
|
||||||
|
#define DomeSEW(OnOff) send_cmd_i1 (SEWsDome, (int)(OnOff))
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* BTA data structure definitions *
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#define ServPID (sdt->pid) // PID of main program
|
||||||
|
// model
|
||||||
|
#define UseModel (sdt->model) // model variants
|
||||||
|
enum{
|
||||||
|
NoModel = 0 // OFF
|
||||||
|
,CheckModel // control motors by model
|
||||||
|
,DriveModel // "blind" management without real sensors
|
||||||
|
,FullModel // full model without telescope
|
||||||
|
};
|
||||||
|
// timer
|
||||||
|
#define ClockType (sdt->timer) // which timer to use
|
||||||
|
enum{
|
||||||
|
Ch7_15 = 0 // Inner timer with synchronisation by CH7_15
|
||||||
|
,SysTimer // System timer (synchronisation unknown)
|
||||||
|
,ExtSynchro // External synchronisation (bta_time or xntpd)
|
||||||
|
};
|
||||||
|
// system
|
||||||
|
#define Sys_Mode (sdt->system) // main system mode
|
||||||
|
enum{
|
||||||
|
SysStop = 0 // Stop
|
||||||
|
,SysWait // Wait for start (pointing)
|
||||||
|
,SysPointAZ // Pointing by A/Z
|
||||||
|
,SysPointAD // Pointing by RA/Decl
|
||||||
|
,SysTrkStop // Tracking stop
|
||||||
|
,SysTrkStart // Start tracking (acceleration to nominal velocity)
|
||||||
|
,SysTrkMove // Tracking move to object
|
||||||
|
,SysTrkSeek // Tracking in seeking mode
|
||||||
|
,SysTrkOk // Tracking OK
|
||||||
|
,SysTrkCorr // Correction of tracking position
|
||||||
|
,SysTest // Test
|
||||||
|
};
|
||||||
|
// sys_target
|
||||||
|
#define Sys_Target (sdt->sys_target) // system pointing target
|
||||||
|
enum{
|
||||||
|
TagPosition = 0 // point by A/Z
|
||||||
|
,TagObject // point by RA/Decl
|
||||||
|
,TagNest // point to "nest"
|
||||||
|
,TagZenith // point to zenith
|
||||||
|
,TagHorizon // point to horizon
|
||||||
|
,TagStatObj // point to statinary object (t/Decl)
|
||||||
|
};
|
||||||
|
// tel_focus
|
||||||
|
#define Tel_Focus (sdt->tel_focus) // telescope focus type
|
||||||
|
enum{
|
||||||
|
Prime = 0
|
||||||
|
,Nasmyth1
|
||||||
|
,Nasmyth2
|
||||||
|
};
|
||||||
|
// PCS
|
||||||
|
#define PosCor_Coeff (sdt->pc_coeff) // pointing correction system coefficients
|
||||||
|
// tel_state
|
||||||
|
#define Tel_State (sdt->tel_state) // telescope state
|
||||||
|
#define Req_State (sdt->req_state) // required state
|
||||||
|
enum{
|
||||||
|
Stopping = 0
|
||||||
|
,Pointing
|
||||||
|
,Tracking
|
||||||
|
};
|
||||||
|
// tel_hard_state
|
||||||
|
#define Tel_Hardware (sdt->tel_hard_state) // Power state
|
||||||
|
enum{
|
||||||
|
Hard_Off = 0
|
||||||
|
,Hard_On
|
||||||
|
};
|
||||||
|
// tel_mode
|
||||||
|
#define Tel_Mode (sdt->tel_mode) // telescope mode
|
||||||
|
enum{
|
||||||
|
Automatic = 0 // Automatic (normal) mode
|
||||||
|
,Manual = 1 // manual mode
|
||||||
|
,ZenHor = 2 // work when Z<5 || Z>80
|
||||||
|
,A_Move = 4 // hand move by A
|
||||||
|
,Z_Move = 8 // hand move by Z
|
||||||
|
,Balance =0x10// balancing
|
||||||
|
};
|
||||||
|
// az_mode
|
||||||
|
#define Az_Mode (sdt->az_mode) // azimuth reverce
|
||||||
|
enum{
|
||||||
|
Rev_Off = 0 // move by nearest way
|
||||||
|
,Rev_On // move by longest way
|
||||||
|
};
|
||||||
|
// p2_state
|
||||||
|
#define P2_State (sdt->p2_state) // P2 motor state
|
||||||
|
#define P2_Mode (sdt->p2_req_mode)
|
||||||
|
enum{
|
||||||
|
P2_Off = 0 // Stop
|
||||||
|
,P2_On // Guiding
|
||||||
|
,P2_Plus // Move to +
|
||||||
|
,P2_Minus = -2 // Move to -
|
||||||
|
};
|
||||||
|
// focus_state
|
||||||
|
#define Foc_State (sdt->focus_state) // focus motor state
|
||||||
|
enum{
|
||||||
|
Foc_Hminus = -2// fast "-" move
|
||||||
|
,Foc_Lminus // slow "-" move
|
||||||
|
,Foc_Off // Off
|
||||||
|
,Foc_Lplus // slow "+" move
|
||||||
|
,Foc_Hplus // fast "+" move
|
||||||
|
};
|
||||||
|
// dome_state
|
||||||
|
#define Dome_State (sdt->dome_state) // dome motors state
|
||||||
|
enum{
|
||||||
|
D_Hminus = -3 // speeds: low, medium, high
|
||||||
|
,D_Mminus
|
||||||
|
,D_Lminus
|
||||||
|
,D_Off // off
|
||||||
|
,D_Lplus
|
||||||
|
,D_Mplus
|
||||||
|
,D_Hplus
|
||||||
|
,D_On = 7 // auto
|
||||||
|
};
|
||||||
|
// pcor_mode
|
||||||
|
#define Pos_Corr (sdt->pcor_mode) // pointing correction mode
|
||||||
|
enum{
|
||||||
|
PC_Off = 0
|
||||||
|
,PC_On
|
||||||
|
};
|
||||||
|
// trkok_mode
|
||||||
|
#define TrkOk_Mode (sdt->trkok_mode) // tracking mode
|
||||||
|
enum{
|
||||||
|
UseDiffVel = 1 // Isodrome (correction by real motors speed)
|
||||||
|
,UseDiffAZ = 2 // Tracking by coordinate difference
|
||||||
|
,UseDFlt = 4 // Turn on digital filter
|
||||||
|
};
|
||||||
|
// input RA/Decl values
|
||||||
|
#define InpAlpha (sdt->i_alpha)
|
||||||
|
#define InpDelta (sdt->i_delta)
|
||||||
|
// current source RA/Decl values
|
||||||
|
#define SrcAlpha (sdt->s_alpha)
|
||||||
|
#define SrcDelta (sdt->s_delta)
|
||||||
|
// intrinsic object velocity
|
||||||
|
#define VelAlpha (sdt->v_alpha)
|
||||||
|
#define VelDelta (sdt->v_delta)
|
||||||
|
// input A/Z values
|
||||||
|
#define InpAzim (sdt->i_azim)
|
||||||
|
#define InpZdist (sdt->i_zdist)
|
||||||
|
// calculated values
|
||||||
|
#define CurAlpha (sdt->c_alpha)
|
||||||
|
#define CurDelta (sdt->c_delta)
|
||||||
|
// current values (from sensors)
|
||||||
|
#define tag_A (sdt->tag_a)
|
||||||
|
#define tag_Z (sdt->tag_z)
|
||||||
|
#define tag_P (sdt->tag_p)
|
||||||
|
// calculated corrections
|
||||||
|
#define pos_cor_A (sdt->pcor_a)
|
||||||
|
#define pos_cor_Z (sdt->pcor_z)
|
||||||
|
#define refract_Z (sdt->refr_z)
|
||||||
|
// reverse calculation corr.
|
||||||
|
#define tel_cor_A (sdt->tcor_a)
|
||||||
|
#define tel_cor_Z (sdt->tcor_z)
|
||||||
|
#define tel_ref_Z (sdt->tref_z)
|
||||||
|
// coords difference
|
||||||
|
#define Diff_A (sdt->diff_a)
|
||||||
|
#define Diff_Z (sdt->diff_z)
|
||||||
|
#define Diff_P (sdt->diff_p)
|
||||||
|
// base object velocity
|
||||||
|
#define vel_objA (sdt->vbasea)
|
||||||
|
#define vel_objZ (sdt->vbasez)
|
||||||
|
#define vel_objP (sdt->vbasep)
|
||||||
|
// correction by real speed
|
||||||
|
#define diff_vA (sdt->diffva)
|
||||||
|
#define diff_vZ (sdt->diffvz)
|
||||||
|
#define diff_vP (sdt->diffvp)
|
||||||
|
// motor speed
|
||||||
|
#define speedA (sdt->speeda)
|
||||||
|
#define speedZ (sdt->speedz)
|
||||||
|
#define speedP (sdt->speedp)
|
||||||
|
// last precipitation time
|
||||||
|
#define Precip_time (sdt->m_time_precip)
|
||||||
|
// reserved
|
||||||
|
#define Reserve (sdt->reserve)
|
||||||
|
// real motor speed (''/sec)
|
||||||
|
#define req_speedA (sdt->rspeeda)
|
||||||
|
#define req_speedZ (sdt->rspeedz)
|
||||||
|
#define req_speedP (sdt->rspeedp)
|
||||||
|
// model speed
|
||||||
|
#define mod_vel_A (sdt->simvela)
|
||||||
|
#define mod_vel_Z (sdt->simvelz)
|
||||||
|
#define mod_vel_P (sdt->simvelp)
|
||||||
|
#define mod_vel_F (sdt->simvelf)
|
||||||
|
#define mod_vel_D (sdt->simvelf)
|
||||||
|
// telescope & hand correction state
|
||||||
|
/*
|
||||||
|
* 0x8000 - ÁÚÉÍÕÔ ÐÏÌÏÖÉÔÅÌØÎÙÊ
|
||||||
|
* 0x4000 - ÏÔÒÁÂÏÔËÁ ×ËÌ.
|
||||||
|
* 0x2000 - ÒÅÖÉÍ ×ÅÄÅÎÉÑ
|
||||||
|
* 0x1000 - ÏÔÒÁÂÏÔËÁ P2 ×ËÌ.
|
||||||
|
* 0x01F0 - ÓË.ËÏÒÒ. 0.2 0.4 1.0 2.0 5.0("/ÓÅË)
|
||||||
|
* 0x000F - ÎÁÐÒ.ËÏÒÒ. +Z -Z +A -A
|
||||||
|
*/
|
||||||
|
#define code_KOST (sdt->kost)
|
||||||
|
// different time (UTC, stellar, local)
|
||||||
|
#define M_time (sdt->m_time)
|
||||||
|
#define S_time (sdt->s_time)
|
||||||
|
#define L_time (sdt->l_time)
|
||||||
|
// PPNDD sensor (rough) code
|
||||||
|
#define ppndd_A (sdt->ppndd_a)
|
||||||
|
#define ppndd_Z (sdt->ppndd_z)
|
||||||
|
#define ppndd_P (sdt->ppndd_p)
|
||||||
|
#define ppndd_B (sdt->ppndd_b) // atm. pressure
|
||||||
|
// DUP sensor (precise) code (Gray code)
|
||||||
|
#define dup_A (sdt->dup_a)
|
||||||
|
#define dup_Z (sdt->dup_z)
|
||||||
|
#define dup_P (sdt->dup_p)
|
||||||
|
#define dup_F (sdt->dup_f)
|
||||||
|
#define dup_D (sdt->dup_d)
|
||||||
|
// binary 14-digit precise code
|
||||||
|
#define low_A (sdt->low_a)
|
||||||
|
#define low_Z (sdt->low_z)
|
||||||
|
#define low_P (sdt->low_p)
|
||||||
|
#define low_F (sdt->low_f)
|
||||||
|
#define low_D (sdt->low_d)
|
||||||
|
// binary 23-digit rough code
|
||||||
|
#define code_A (sdt->code_a)
|
||||||
|
#define code_Z (sdt->code_z)
|
||||||
|
#define code_P (sdt->code_p)
|
||||||
|
#define code_B (sdt->code_b)
|
||||||
|
#define code_F (sdt->code_f)
|
||||||
|
#define code_D (sdt->code_d)
|
||||||
|
// ADC PCL818 (8-channel) codes
|
||||||
|
#define ADC(N) (sdt->adc[(N)])
|
||||||
|
#define code_T1 ADC(0) // External temperature code
|
||||||
|
#define code_T2 ADC(1) // In-dome temperature code
|
||||||
|
#define code_T3 ADC(2) // Mirror temperature code
|
||||||
|
#define code_Wnd ADC(3) // Wind speed code
|
||||||
|
// calculated values
|
||||||
|
#define val_A (sdt->val_a) // A, ''
|
||||||
|
#define val_Z (sdt->val_z) // Z, ''
|
||||||
|
#define val_P (sdt->val_p) // P, ''
|
||||||
|
#define val_B (sdt->val_b) // atm. pressure, mm.hg.
|
||||||
|
#define val_F (sdt->val_f) // focus, mm
|
||||||
|
#define val_D (sdt->val_d) // Dome Az, ''
|
||||||
|
#define val_T1 (sdt->val_t1) // ext. T, degrC
|
||||||
|
#define val_T2 (sdt->val_t2) // in-dome T, degrC
|
||||||
|
#define val_T3 (sdt->val_t3) // mirror T, degrC
|
||||||
|
#define val_Wnd (sdt->val_wnd) // wind speed, m/s
|
||||||
|
// RA/Decl calculated by A/Z
|
||||||
|
#define val_Alp (sdt->val_alp)
|
||||||
|
#define val_Del (sdt->val_del)
|
||||||
|
// measured speed
|
||||||
|
#define vel_A (sdt->vel_a)
|
||||||
|
#define vel_Z (sdt->vel_z)
|
||||||
|
#define vel_P (sdt->vel_p)
|
||||||
|
#define vel_F (sdt->vel_f)
|
||||||
|
#define vel_D (sdt->vel_d)
|
||||||
|
// system messages queue
|
||||||
|
#define MesgNum 3
|
||||||
|
#define MesgLen 39
|
||||||
|
// message type
|
||||||
|
enum{
|
||||||
|
MesgEmpty = 0
|
||||||
|
,MesgInfor
|
||||||
|
,MesgWarn
|
||||||
|
,MesgFault
|
||||||
|
,MesgLog
|
||||||
|
};
|
||||||
|
#define Sys_Mesg(N) (sdt->sys_msg_buf[N])
|
||||||
|
// access levels
|
||||||
|
#define code_Lev1 (sdt->code_lev[0]) // remote observer - only information
|
||||||
|
#define code_Lev2 (sdt->code_lev[1]) // local observer - input coordinates
|
||||||
|
#define code_Lev3 (sdt->code_lev[2]) // main observer - correction by A/Z, P2/F management
|
||||||
|
#define code_Lev4 (sdt->code_lev[3]) // operator - start/stop telescope, testing
|
||||||
|
#define code_Lev5 (sdt->code_lev[4]) // main operator - full access
|
||||||
|
#define code_Lev(x) (sdt->code_lev[(x-1)])
|
||||||
|
// network settings
|
||||||
|
#define NetMask (sdt->netmask) // subnet mask (usually 255.255.255.0)
|
||||||
|
#define NetWork (sdt->netaddr) // subnet address (for ex.: 192.168.3.0)
|
||||||
|
#define ACSMask (sdt->acsmask) // ACS network mask (for ex.: 255.255.255.0)
|
||||||
|
#define ACSNet (sdt->acsaddr) // ACS subnet address (for ex.: 192.168.13.0)
|
||||||
|
// meteo data
|
||||||
|
#define MeteoMode (sdt->meteo_stat)
|
||||||
|
enum{
|
||||||
|
INPUT_B = 1 // pressure
|
||||||
|
,INPUT_T1 = 2 // external T
|
||||||
|
,INPUT_T2 = 4 // in-dome T
|
||||||
|
,INPUT_T3 = 8 // mirror T
|
||||||
|
,INPUT_WND = 0x10 // wind speed
|
||||||
|
,INPUT_HMD = 0x20 // humidity
|
||||||
|
};
|
||||||
|
#define SENSOR_B (INPUT_B <<8) // external data flags
|
||||||
|
#define SENSOR_T1 (INPUT_T1 <<8)
|
||||||
|
#define SENSOR_T2 (INPUT_T2 <<8)
|
||||||
|
#define SENSOR_T3 (INPUT_T3 <<8)
|
||||||
|
#define SENSOR_WND (INPUT_WND<<8)
|
||||||
|
#define SENSOR_HMD (INPUT_HMD<<8)
|
||||||
|
#define ADC_B (INPUT_B <<16) // reading from ADC flags
|
||||||
|
#define ADC_T1 (INPUT_T1 <<16)
|
||||||
|
#define ADC_T2 (INPUT_T2 <<16)
|
||||||
|
#define ADC_T3 (INPUT_T3 <<16)
|
||||||
|
#define ADC_WND (INPUT_WND<<16)
|
||||||
|
#define ADC_HMD (INPUT_HMD<<16)
|
||||||
|
#define NET_B (INPUT_B <<24) // got by network flags
|
||||||
|
#define NET_T1 (INPUT_T1 <<24)
|
||||||
|
#define NET_WND (INPUT_WND<<24)
|
||||||
|
#define NET_HMD (INPUT_HMD<<24)
|
||||||
|
// input meteo values
|
||||||
|
#define inp_B (sdt->inp_b) // atm.pressure (mm.hg)
|
||||||
|
#define inp_T1 (sdt->inp_t1) // ext T
|
||||||
|
#define inp_T2 (sdt->inp_t2) // in-dome T
|
||||||
|
#define inp_T3 (sdt->inp_t3) // mirror T
|
||||||
|
#define inp_Wnd (sdt->inp_wnd) // wind
|
||||||
|
// values used for refraction calculation
|
||||||
|
#define Temper (sdt->temper)
|
||||||
|
#define Pressure (sdt->press)
|
||||||
|
// last wind gust time
|
||||||
|
#define Wnd10_time (sdt->m_time10)
|
||||||
|
#define Wnd15_time (sdt->m_time15)
|
||||||
|
// IERS DUT1
|
||||||
|
#define DUT1 (sdt->dut1)
|
||||||
|
// sensors reading time
|
||||||
|
#define A_time (sdt->a_time)
|
||||||
|
#define Z_time (sdt->z_time)
|
||||||
|
#define P_time (sdt->p_time)
|
||||||
|
// input speeds
|
||||||
|
#define speedAin (sdt->speedain)
|
||||||
|
#define speedZin (sdt->speedzin)
|
||||||
|
#define speedPin (sdt->speedpin)
|
||||||
|
// acceleration (''/sec^2)
|
||||||
|
#define acc_A (sdt->acc_a)
|
||||||
|
#define acc_Z (sdt->acc_z)
|
||||||
|
#define acc_P (sdt->acc_p)
|
||||||
|
#define acc_F (sdt->acc_f)
|
||||||
|
#define acc_D (sdt->acc_d)
|
||||||
|
// SEW code
|
||||||
|
#define code_SEW (sdt->code_sew)
|
||||||
|
// sew data
|
||||||
|
#define statusSEW(Drv) (sdt->sewdrv[(Drv)-1].status)
|
||||||
|
#define statusSEW1 (sdt->sewdrv[0].status)
|
||||||
|
#define statusSEW2 (sdt->sewdrv[1].status)
|
||||||
|
#define statusSEW3 (sdt->sewdrv[2].status)
|
||||||
|
#define speedSEW(Drv) (sdt->sewdrv[(Drv)-1].set_speed)
|
||||||
|
#define speedSEW1 (sdt->sewdrv[0].set_speed)
|
||||||
|
#define speedSEW2 (sdt->sewdrv[1].set_speed)
|
||||||
|
#define speedSEW3 (sdt->sewdrv[2].set_speed)
|
||||||
|
#define vel_SEW(Drv) (sdt->sewdrv[(Drv)-1].mes_speed)
|
||||||
|
#define vel_SEW1 (sdt->sewdrv[0].mes_speed)
|
||||||
|
#define vel_SEW2 (sdt->sewdrv[1].mes_speed)
|
||||||
|
#define vel_SEW3 (sdt->sewdrv[2].mes_speed)
|
||||||
|
#define currentSEW(Drv) (sdt->sewdrv[(Drv)-1].current)
|
||||||
|
#define currentSEW1 (sdt->sewdrv[0].current)
|
||||||
|
#define currentSEW2 (sdt->sewdrv[1].current)
|
||||||
|
#define currentSEW3 (sdt->sewdrv[2].current)
|
||||||
|
#define indexSEW(Drv) (sdt->sewdrv[(Drv)-1].index)
|
||||||
|
#define indexSEW1 (sdt->sewdrv[0].index)
|
||||||
|
#define indexSEW2 (sdt->sewdrv[1].index)
|
||||||
|
#define indexSEW3 (sdt->sewdrv[2].index)
|
||||||
|
#define valueSEW(Drv) (sdt->sewdrv[(Drv)-1].value.l)
|
||||||
|
#define valueSEW1 (sdt->sewdrv[0].value.l)
|
||||||
|
#define valueSEW2 (sdt->sewdrv[1].value.l)
|
||||||
|
#define valueSEW3 (sdt->sewdrv[2].value.l)
|
||||||
|
#define bvalSEW(Drv,Nb) (sdt->sewdrv[(Drv)-1].value.b[Nb])
|
||||||
|
// 23-digit PEP-controllers code
|
||||||
|
#define PEP_code_A (sdt->pep_code_a)
|
||||||
|
#define PEP_code_Z (sdt->pep_code_z)
|
||||||
|
#define PEP_code_P (sdt->pep_code_p)
|
||||||
|
// PEP end-switches code
|
||||||
|
#define switch_A (sdt->pep_sw_a)
|
||||||
|
enum{
|
||||||
|
Sw_minus_A = 1 // negative A value
|
||||||
|
,Sw_plus240_A = 2 // end switch +240degr
|
||||||
|
,Sw_minus240_A = 4 // end switch -240degr
|
||||||
|
,Sw_minus45_A = 8 // "horizon" end switch
|
||||||
|
};
|
||||||
|
#define switch_Z (sdt->pep_sw_z)
|
||||||
|
enum{
|
||||||
|
Sw_0_Z = 1
|
||||||
|
,Sw_5_Z = 2
|
||||||
|
,Sw_20_Z = 4
|
||||||
|
,Sw_60_Z = 8
|
||||||
|
,Sw_80_Z = 0x10
|
||||||
|
,Sw_90_Z = 0x20
|
||||||
|
};
|
||||||
|
#define switch_P (sdt->pep_sw_p)
|
||||||
|
enum{
|
||||||
|
Sw_No_P = 0 // no switches
|
||||||
|
,Sw_22_P = 1 // 22degr
|
||||||
|
,Sw_89_P = 2 // 89degr
|
||||||
|
,Sw_Sm_P = 0x80 // Primary focus smoke sensor
|
||||||
|
};
|
||||||
|
// PEP codes
|
||||||
|
#define PEP_code_F (sdt->pep_code_f)
|
||||||
|
#define PEP_code_D (sdt->pep_code_d)
|
||||||
|
#define PEP_code_Rin (sdt->pep_code_ri)
|
||||||
|
#define PEP_code_Rout (sdt->pep_code_ro)
|
||||||
|
// PEP flags
|
||||||
|
#define PEP_A_On (sdt->pep_on[0])
|
||||||
|
#define PEP_A_Off (PEP_A_On==0)
|
||||||
|
#define PEP_Z_On (sdt->pep_on[1])
|
||||||
|
#define PEP_Z_Off (PEP_Z_On==0)
|
||||||
|
#define PEP_P_On (sdt->pep_on[2])
|
||||||
|
#define PEP_P_Off (PEP_P_On==0)
|
||||||
|
#define PEP_F_On (sdt->pep_on[3])
|
||||||
|
#define PEP_F_Off (PEP_F_On==0)
|
||||||
|
#define PEP_D_On (sdt->pep_on[4])
|
||||||
|
#define PEP_D_Off (PEP_D_On==0)
|
||||||
|
#define PEP_R_On (sdt->pep_on[5])
|
||||||
|
#define PEP_R_Off ((PEP_R_On&1)==0)
|
||||||
|
#define PEP_R_Inp ((PEP_R_On&2)!=0)
|
||||||
|
#define PEP_K_On (sdt->pep_on[6])
|
||||||
|
#define PEP_K_Off ((PEP_K_On&1)==0)
|
||||||
|
#define PEP_K_Inp ((PEP_K_On&2)!=0)
|
||||||
|
// IERS polar motion
|
||||||
|
#define polarX (sdt->xpol)
|
||||||
|
#define polarY (sdt->ypol)
|
||||||
|
// current Julian date, sidereal time correction by "Equation of the Equinoxes"
|
||||||
|
#define JDate (sdt->jdate)
|
||||||
|
#define EE_time (sdt->eetime)
|
||||||
|
// humidity value (%%) & hand input
|
||||||
|
#define val_Hmd (sdt->val_hmd)
|
||||||
|
#define inp_Hmd (sdt->val_hmd)
|
||||||
|
// worm position, mkm
|
||||||
|
#define worm_A (sdt->worm_a)
|
||||||
|
#define worm_Z (sdt->worm_z)
|
||||||
|
// locking flags
|
||||||
|
#define LockFlags (sdt->lock_flags)
|
||||||
|
enum{
|
||||||
|
Lock_A = 1
|
||||||
|
,Lock_Z = 2
|
||||||
|
,Lock_P = 4
|
||||||
|
,Lock_F = 8
|
||||||
|
,Lock_D = 0x10
|
||||||
|
};
|
||||||
|
#define A_Locked (LockFlags&Lock_A)
|
||||||
|
#define Z_Locked (LockFlags&Lock_Z)
|
||||||
|
#define P_Locked (LockFlags&Lock_P)
|
||||||
|
#define F_Locked (LockFlags&Lock_F)
|
||||||
|
#define D_Locked (LockFlags&Lock_D)
|
||||||
|
// SEW dome divers speed
|
||||||
|
#define Dome_Speed (sdt->sew_dome_speed)
|
||||||
|
// SEW dome drive number (for indication)
|
||||||
|
#define DomeSEW_N (sdt->sew_dome_num)
|
||||||
|
// SEW dome driver parameters
|
||||||
|
#define statusSEWD (sdt->sewdomedrv.status) // controller status
|
||||||
|
#define speedSEWD (sdt->sewdomedrv.set_speed) // speed, rpm
|
||||||
|
#define vel_SEWD (sdt->sewdomedrv.mes_speed) /*ÉÚÍÅÒÅÎÎÁÑ ÓËÏÒÏÓÔØ ÏÂ/ÍÉÎ (rpm)*/
|
||||||
|
#define currentSEWD (sdt->sewdomedrv.current) // current, A
|
||||||
|
#define indexSEWD (sdt->sewdomedrv.index) // parameter index
|
||||||
|
#define valueSEWD (sdt->sewdomedrv.value.l) // parameter value
|
||||||
|
// dome PEP codes
|
||||||
|
#define PEP_code_Din (sdt->pep_code_di) // data in
|
||||||
|
#define PEP_Dome_SEW_Ok 0x200
|
||||||
|
#define PEP_Dome_Cable_Ok 0x100
|
||||||
|
#define PEP_code_Dout (sdt->pep_code_do) // data out
|
||||||
|
#define PEP_Dome_SEW_On 0x10
|
||||||
|
#define PEP_Dome_SEW_Off 0x20
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* BTA data structure *
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#define BTA_Data_Ver 2
|
||||||
|
struct BTA_Data {
|
||||||
|
int32_t magic; // magic value
|
||||||
|
int32_t version; // BTA_Data_Ver
|
||||||
|
int32_t size; // sizeof(struct BTA_Data)
|
||||||
|
int32_t pid; // main process PID
|
||||||
|
int32_t model; // model modes
|
||||||
|
int32_t timer; // timer selected
|
||||||
|
int32_t system; // main system mode
|
||||||
|
int32_t sys_target; // system pointing target
|
||||||
|
int32_t tel_focus; // telescope focus type
|
||||||
|
double pc_coeff[8]; // pointing correction system coefficients
|
||||||
|
int32_t tel_state; // telescope state
|
||||||
|
int32_t req_state; // new (required) state
|
||||||
|
int32_t tel_hard_state; // Power state
|
||||||
|
int32_t tel_mode; // telescope mode
|
||||||
|
int32_t az_mode; // azimuth reverce
|
||||||
|
int32_t p2_state; // P2 motor state
|
||||||
|
int32_t p2_req_mode; // P2 required state
|
||||||
|
int32_t focus_state; // focus motor state
|
||||||
|
int32_t dome_state; // dome motors state
|
||||||
|
int32_t pcor_mode; // pointing correction mode
|
||||||
|
int32_t trkok_mode; // tracking mode
|
||||||
|
double i_alpha, i_delta; // input values
|
||||||
|
double s_alpha, s_delta; // source
|
||||||
|
double v_alpha, v_delta; // intrinsic vel.
|
||||||
|
double i_azim, i_zdist; // input A/Z
|
||||||
|
double c_alpha, c_delta; // calculated values
|
||||||
|
double tag_a, tag_z, tag_p; // current values (from sensors)
|
||||||
|
double pcor_a, pcor_z, refr_z; // calculated corrections
|
||||||
|
double tcor_a, tcor_z, tref_z; // reverse calculation corr.
|
||||||
|
double diff_a, diff_z, diff_p; // coords difference
|
||||||
|
double vbasea,vbasez,vbasep; // base object velocity
|
||||||
|
double diffva,diffvz,diffvp; // correction by real speed
|
||||||
|
double speeda,speedz,speedp; // motor speed
|
||||||
|
double m_time_precip; // last precipitation time
|
||||||
|
uint8_t reserve[16]; // reserved
|
||||||
|
double rspeeda, rspeedz, rspeedp; // real motor speed (''/sec)
|
||||||
|
double simvela, simvelz, simvelp, simvelf, simveld; // model speed
|
||||||
|
uint32_t kost; // telescope & hand correction state
|
||||||
|
double m_time, s_time, l_time; // different time (UTC, stellar, local)
|
||||||
|
uint32_t ppndd_a, ppndd_z, ppndd_p, ppndd_b; // PPNDD sensor (rough) code
|
||||||
|
uint32_t dup_a, dup_z, dup_p, dup_f, dup_d; // DUP sensor (precise) code (Gray code)
|
||||||
|
uint32_t low_a, low_z, low_p, low_f, low_d; // binary 14-digit precise code
|
||||||
|
uint32_t code_a, code_z, code_p, code_b, code_f, code_d; // binary 23-digit rough code
|
||||||
|
uint32_t adc[8]; // ADC PCL818 (8-channel) codes
|
||||||
|
double val_a, val_z, val_p, val_b, val_f, val_d;
|
||||||
|
double val_t1, val_t2, val_t3, val_wnd; // calculated values
|
||||||
|
double val_alp, val_del; // RA/Decl calculated by A/Z
|
||||||
|
double vel_a, vel_z, vel_p, vel_f, vel_d; // measured speed
|
||||||
|
// system messages queue
|
||||||
|
struct SysMesg {
|
||||||
|
int32_t seq_num;
|
||||||
|
char type; // message type
|
||||||
|
char text[MesgLen]; // message itself
|
||||||
|
} sys_msg_buf[MesgNum];
|
||||||
|
// access levels
|
||||||
|
uint32_t code_lev[5];
|
||||||
|
// network settings
|
||||||
|
uint32_t netmask, netaddr, acsmask, acsaddr;
|
||||||
|
int32_t meteo_stat; // meteo data
|
||||||
|
double inp_b, inp_t1, inp_t2, inp_t3, inp_wnd; // input meteo values
|
||||||
|
double temper, press; // values used for refraction calculation
|
||||||
|
double m_time10, m_time15; // last wind gust time
|
||||||
|
double dut1; // IERS DUT1 (src: ftp://maia.usno.navy.mil/ser7/ser7.dat), DUT1 = UT1-UTC
|
||||||
|
double a_time, z_time, p_time; // sensors reading time
|
||||||
|
double speedain, speedzin, speedpin; // input speeds
|
||||||
|
double acc_a, acc_z, acc_p, acc_f, acc_d; // acceleration (''/sec^2)
|
||||||
|
uint32_t code_sew; // SEW code
|
||||||
|
struct SEWdata { // sew data
|
||||||
|
int32_t status;
|
||||||
|
double set_speed; // target speed, rpm
|
||||||
|
double mes_speed; // measured speed, rpm
|
||||||
|
double current; // measured current, A
|
||||||
|
int32_t index; // parameter number
|
||||||
|
union{ // parameter code
|
||||||
|
uint8_t b[4];
|
||||||
|
uint32_t l;
|
||||||
|
} value;
|
||||||
|
} sewdrv[3];
|
||||||
|
uint32_t pep_code_a, pep_code_z, pep_code_p; // 23-digit PEP-controllers code
|
||||||
|
uint32_t pep_sw_a, pep_sw_z, pep_sw_p; // PEP end-switches code
|
||||||
|
uint32_t pep_code_f, pep_code_d, pep_code_ri, pep_code_ro; // PEP codes
|
||||||
|
uint8_t pep_on[10]; // PEP flags
|
||||||
|
double xpol, ypol; // IERS polar motion (src: ftp://maia.usno.navy.mil/ser7/ser7.dat)
|
||||||
|
double jdate, eetime; // current Julian date, sidereal time correction by "Equation of the Equinoxes"
|
||||||
|
double val_hmd, inp_hmd; // humidity value (%%) & hand input
|
||||||
|
double worm_a, worm_z; // worm position, mkm
|
||||||
|
/* ÆÌÁÇÉ ÂÌÏËÉÒÏ×ËÉ ÕÐÒÁ×ÌÅÎÉÑ ÕÚÌÁÍÉ */
|
||||||
|
uint32_t lock_flags; // locking flags
|
||||||
|
int32_t sew_dome_speed; // SEW dome divers speed: D_Lplus, D_Hminus etc
|
||||||
|
int32_t sew_dome_num; // SEW dome drive number (for indication)
|
||||||
|
struct SEWdata sewdomedrv; // SEW dome driver parameters
|
||||||
|
uint32_t pep_code_di, pep_code_do; // dome PEP codes
|
||||||
|
};
|
||||||
|
|
||||||
|
extern volatile struct BTA_Data *sdt;
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Local data structure *
|
||||||
|
*******************************************************************************/
|
||||||
|
// Oil pressure, MPa
|
||||||
|
#define PressOilA (sdtl->pr_oil_a)
|
||||||
|
#define PressOilZ (sdtl->pr_oil_z)
|
||||||
|
#define PressOilTank (sdtl->pr_oil_t)
|
||||||
|
// Oil themperature, degrC
|
||||||
|
#define OilTemper1 (sdtl->t_oil_1) // oil
|
||||||
|
#define OilTemper2 (sdtl->t_oil_2) // water
|
||||||
|
|
||||||
|
// Local data structure
|
||||||
|
struct BTA_Local {
|
||||||
|
uint8_t reserve[120]; // reserved data
|
||||||
|
double pr_oil_a,pr_oil_z,pr_oil_t; // Oil pressure
|
||||||
|
double t_oil_1,t_oil_2; // Oil themperature
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message buffer structure
|
||||||
|
*/
|
||||||
|
struct my_msgbuf {
|
||||||
|
int32_t mtype; // message type
|
||||||
|
uint32_t acckey; // client access key
|
||||||
|
uint32_t src_pid; // source PID
|
||||||
|
uint32_t src_ip; // IP of command source or 0 for local
|
||||||
|
char mtext[100]; // message itself
|
||||||
|
};
|
||||||
|
|
||||||
|
extern volatile struct BTA_Local *sdtl;
|
||||||
|
extern int snd_id;
|
||||||
|
extern int cmd_src_pid;
|
||||||
|
extern uint32_t cmd_src_ip;
|
||||||
|
|
||||||
|
#define ClientSide 0
|
||||||
|
#define ServerSide 1
|
||||||
|
|
||||||
|
#ifndef BTA_MODULE
|
||||||
|
void bta_data_init();
|
||||||
|
int bta_data_check();
|
||||||
|
void bta_data_close();
|
||||||
|
int get_shm_block(volatile struct SHM_Block *sb, int server);
|
||||||
|
int close_shm_block(volatile struct SHM_Block *sb);
|
||||||
|
void get_cmd_queue(struct CMD_Queue *cq, int server);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int check_shm_block(volatile struct SHM_Block *sb);
|
||||||
|
|
||||||
|
void encode_lev_passwd(char *passwd, int nlev, uint32_t *keylev, uint32_t *codlev);
|
||||||
|
int find_lev_passwd(char *passwd, uint32_t *keylev, uint32_t *codlev);
|
||||||
|
int check_lev_passwd(char *passwd);
|
||||||
|
void set_acckey(uint32_t newkey);
|
||||||
|
|
||||||
|
// restore packing
|
||||||
|
#pragma pack(pop)
|
||||||
|
//#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
#endif // __BTA_SHDATA_H__
|
||||||
120
p1rotator/ch4run.c
Normal file
120
p1rotator/ch4run.c
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* ch4run.c - functions for checking whether this process already run
|
||||||
|
*
|
||||||
|
* Copyright 2013 Edward V. Emelianoff <eddy@sao.ru>
|
||||||
|
*
|
||||||
|
* 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 "ch4run.h"
|
||||||
|
#include <stdio.h> // printf, fopen, ...
|
||||||
|
#include <unistd.h> // getpid
|
||||||
|
#include <stdio.h> // perror
|
||||||
|
#include <sys/types.h> // opendir
|
||||||
|
#include <dirent.h> // opendir
|
||||||
|
#include <sys/stat.h> // stat
|
||||||
|
#include <fcntl.h> // fcntl
|
||||||
|
#include <stdlib.h> // exit
|
||||||
|
#include <string.h> // memset
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read process name from /proc/PID/cmdline
|
||||||
|
* @param pid - PID of interesting process
|
||||||
|
* @return filename or NULL if not found
|
||||||
|
* don't use this function twice for different names without copying
|
||||||
|
* its returning by strdup, because `name` contains in static array
|
||||||
|
*/
|
||||||
|
char *readname(pid_t pid){
|
||||||
|
static char name[256];
|
||||||
|
char *pp = name, byte, path[256];
|
||||||
|
FILE *file;
|
||||||
|
int cntr = 0;
|
||||||
|
size_t sz;
|
||||||
|
snprintf (path, 255, PROC_BASE "/%d/cmdline", pid);
|
||||||
|
file = fopen(path, "r");
|
||||||
|
if(!file) return NULL; // there's no such file
|
||||||
|
do{ // read basename
|
||||||
|
sz = fread(&byte, 1, 1, file);
|
||||||
|
if(sz != 1) break;
|
||||||
|
if(byte != '/') *pp++ = byte;
|
||||||
|
else{
|
||||||
|
pp = name;
|
||||||
|
cntr = 0;
|
||||||
|
}
|
||||||
|
}while(byte && cntr++ < 255);
|
||||||
|
name[cntr] = 0;
|
||||||
|
fclose(file);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void iffound_default(pid_t pid){
|
||||||
|
fprintf(stderr, "\nFound running process (pid=%d), exit.\n", pid);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check wether there is a same running process
|
||||||
|
* exit if there is a running process or error
|
||||||
|
* Checking have 3 steps:
|
||||||
|
* 1) lock executable file
|
||||||
|
* 2) check pidfile (if you run a copy?)
|
||||||
|
* 3) check /proc for executables with the same name (no/wrong pidfile)
|
||||||
|
* @param pidfilename - name of pidfile or NULL if none
|
||||||
|
* @param iffound - action to run if file found or NULL for exit(0)
|
||||||
|
*/
|
||||||
|
void check4running(char *pidfilename, void (*iffound)(pid_t pid)){
|
||||||
|
DIR *dir;
|
||||||
|
FILE *pidfile;
|
||||||
|
struct dirent *de;
|
||||||
|
struct stat s_buf;
|
||||||
|
pid_t pid = 0, self;
|
||||||
|
char *name, *myname;
|
||||||
|
if(!iffound) iffound = iffound_default;
|
||||||
|
self = getpid(); // get self PID
|
||||||
|
if(!(dir = opendir(PROC_BASE))){ // open /proc directory
|
||||||
|
perror(PROC_BASE);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if(!(name = readname(self))){ // error reading self name
|
||||||
|
perror("Can't read self name");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
myname = strdup(name);
|
||||||
|
if(pidfilename && stat(pidfilename, &s_buf) == 0){ // pidfile exists
|
||||||
|
pidfile = fopen(pidfilename, "r");
|
||||||
|
if(pidfile){
|
||||||
|
if(fscanf(pidfile, "%d", &pid) > 0){ // read PID of (possibly) running process
|
||||||
|
if((name = readname(pid)) && strncmp(name, myname, 255) == 0)
|
||||||
|
iffound(pid);
|
||||||
|
}
|
||||||
|
fclose(pidfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// There is no pidfile or it consists a wrong record
|
||||||
|
while((de = readdir(dir))){ // scan /proc
|
||||||
|
if(!(pid = (pid_t)atoi(de->d_name)) || pid == self) // pass non-PID files and self
|
||||||
|
continue;
|
||||||
|
if((name = readname(pid)) && strncmp(name, myname, 255) == 0)
|
||||||
|
iffound(pid);
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
if(pidfilename){
|
||||||
|
pidfile = fopen(pidfilename, "w");
|
||||||
|
fprintf(pidfile, "%d\n", self); // write self PID to pidfile
|
||||||
|
fclose(pidfile);
|
||||||
|
}
|
||||||
|
free(myname);
|
||||||
|
}
|
||||||
28
p1rotator/ch4run.h
Normal file
28
p1rotator/ch4run.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* daemon.h
|
||||||
|
*
|
||||||
|
* Copyright 2015 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
#ifndef PROC_BASE
|
||||||
|
#define PROC_BASE "/proc"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <unistd.h> // pid_t
|
||||||
|
|
||||||
|
void iffound_default(pid_t pid);
|
||||||
|
void check4running(char *pidfilename, void (*iffound)(pid_t pid));
|
||||||
76
p1rotator/cmdlnopts.c
Normal file
76
p1rotator/cmdlnopts.c
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* cmdlnopts.c - the only function that parse cmdln args and returns glob parameters
|
||||||
|
*
|
||||||
|
* Copyright 2013 Edward V. Emelianoff <eddy@sao.ru>
|
||||||
|
*
|
||||||
|
* 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 <assert.h>
|
||||||
|
#include "cmdlnopts.h"
|
||||||
|
#include "usefull_macros.h"
|
||||||
|
|
||||||
|
#define RAD 57.2957795130823
|
||||||
|
#define D2R(x) ((x) / RAD)
|
||||||
|
#define R2D(x) ((x) * RAD)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* here are global parameters initialisation
|
||||||
|
*/
|
||||||
|
int help;
|
||||||
|
glob_pars G;
|
||||||
|
|
||||||
|
int verbose = 0; // each -v increments this value, e.g. -vvv sets it to 3
|
||||||
|
// DEFAULTS
|
||||||
|
// default global parameters
|
||||||
|
glob_pars const Gdefault = {
|
||||||
|
.gotoangle = 400.,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define command line options by filling structure:
|
||||||
|
* name has_arg flag val type argptr help
|
||||||
|
*/
|
||||||
|
myoption cmdlnopts[] = {
|
||||||
|
// set 1 to param despite of its repeating number:
|
||||||
|
{"help", NO_ARGS, NULL, 'h', arg_int, APTR(&help), _("show this help")},
|
||||||
|
// change p3 position, don't run guiding
|
||||||
|
{"goto", NEED_ARG, NULL, 'g', arg_double, APTR(&G.gotoangle), _("rotate for given angle")},
|
||||||
|
// goto 0, don't run guiding
|
||||||
|
{"absmove", NO_ARGS, NULL, 'a', arg_none, APTR(&G.absmove), _("rotate to given absolute angle (or zero without -g)")},
|
||||||
|
// incremented parameter without args (any -v will increment value of "verbose")
|
||||||
|
{"verbose", NO_ARGS, NULL, 'v', arg_none, APTR(&verbose), _("verbose level (each -v increase it)")},
|
||||||
|
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"
|
||||||
|
change_helpstring("Usage: %s [args]\n\n\tWhere args are:\n");
|
||||||
|
// parse arguments
|
||||||
|
parseargs(&argc, &argv, cmdlnopts);
|
||||||
|
if(help || argc > 0) showhelp(-1, cmdlnopts);
|
||||||
|
return &G;
|
||||||
|
}
|
||||||
|
|
||||||
44
p1rotator/cmdlnopts.h
Normal file
44
p1rotator/cmdlnopts.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* cmdlnopts.h - comand line options for parceargs
|
||||||
|
*
|
||||||
|
* Copyright 2013 Edward V. Emelianoff <eddy@sao.ru>
|
||||||
|
*
|
||||||
|
* 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 "parseargs.h"
|
||||||
|
|
||||||
|
#define MSG(lvl, ...) do{if(lvl >= verbose) printf(__VA_ARGS__);}while(0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* here are some typedef's for global data
|
||||||
|
*/
|
||||||
|
typedef struct{
|
||||||
|
double gotoangle; // rotate for given angle
|
||||||
|
int absmove; // absolute move (from zero angle)
|
||||||
|
} glob_pars;
|
||||||
|
|
||||||
|
|
||||||
|
// default & global parameters
|
||||||
|
extern glob_pars const Gdefault;
|
||||||
|
extern int verbose;
|
||||||
|
|
||||||
|
glob_pars *parse_args(int argc, char **argv);
|
||||||
|
#endif // __CMDLNOPTS_H__
|
||||||
74
p1rotator/config.h
Normal file
74
p1rotator/config.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* geany_encoding=koi8-r
|
||||||
|
* config.h
|
||||||
|
*
|
||||||
|
* Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 __CONFIG_H__
|
||||||
|
#define __CONFIG_H__
|
||||||
|
|
||||||
|
// amount of microsteps for each step
|
||||||
|
#define USTEPS (8.)
|
||||||
|
// gear ratio
|
||||||
|
#define GEARRAT (8.)
|
||||||
|
// steps per one revolution
|
||||||
|
#define ONETURN_STEPS (200.)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pins definition (used BROADCOM GPIO pins numbering)
|
||||||
|
*/
|
||||||
|
|
||||||
|
// End-switch - GPIO25 (leg22)
|
||||||
|
#define ESW_PIN (25)
|
||||||
|
// Stepper: EN - GPIO18 (leg12), DIR - GPIO23 (leg16), STEP - GPIO24 (leg18)
|
||||||
|
#define DIR_PIN (23)
|
||||||
|
#define STEP_PIN (24)
|
||||||
|
#define EN_PIN (18)
|
||||||
|
|
||||||
|
// active/passive levels (depending on stepper driver connection schematic)
|
||||||
|
#define PIN_ACTIVE (1)
|
||||||
|
#define PIN_PASSIVE (0)
|
||||||
|
|
||||||
|
// active level on end-switch: 0 - normally opened, 1 - normally closed
|
||||||
|
#define ESW_ACTIVE (0)
|
||||||
|
|
||||||
|
// positive & negative directions (signal @ DIR pin)
|
||||||
|
#define DIR_POSITIVE (1)
|
||||||
|
#define DIR_NEGATIVE (0)
|
||||||
|
|
||||||
|
// maximum 200 steps per second
|
||||||
|
#define MAX_SPEED (200)
|
||||||
|
#define USTEP_DELAY (1./MAX_SPEED/USTEPS)
|
||||||
|
|
||||||
|
// Position angle calculation (val_Alp, val_Del, S_time - for real work)
|
||||||
|
#define CALC_PA() calc_PA(SrcAlpha, SrcDelta, S_time)
|
||||||
|
|
||||||
|
// PA value for zero end-switch (add this value to desired PA)
|
||||||
|
#define PA_ZEROVAL (0.)
|
||||||
|
|
||||||
|
|
||||||
|
// microsteps per one revolution
|
||||||
|
#define ONETURN_USTEPS (ONETURN_STEPS * USTEPS * GEARRAT)
|
||||||
|
// initial (wrong) value of microsteps counter
|
||||||
|
#define USTEPSBAD (2*ONETURN_USTEPS)
|
||||||
|
// minimal PA delta
|
||||||
|
#define PA_MINSTEP (360. / ONETURN_USTEPS)
|
||||||
|
|
||||||
|
#endif // __CONFIG_H__
|
||||||
94
p1rotator/main.c
Normal file
94
p1rotator/main.c
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* main.c - main file
|
||||||
|
*
|
||||||
|
* Copyright 2015 Edward V. Emelianoff <eddy@sao.ru>
|
||||||
|
*
|
||||||
|
* 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 <termios.h> // tcsetattr
|
||||||
|
#include <unistd.h> // tcsetattr, close, read, write
|
||||||
|
#include <sys/ioctl.h> // ioctl
|
||||||
|
#include <stdio.h> // printf, getchar, fopen, perror
|
||||||
|
#include <stdlib.h> // exit
|
||||||
|
#include <sys/stat.h> // read
|
||||||
|
#include <fcntl.h> // read
|
||||||
|
#include <signal.h> // signal
|
||||||
|
#include <time.h> // time
|
||||||
|
#include <string.h> // memcpy
|
||||||
|
#include <stdint.h> // int types
|
||||||
|
#include <sys/time.h> // gettimeofday
|
||||||
|
#include <assert.h> // assert
|
||||||
|
//#include <pthread.h> // threads
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "tmout.h"
|
||||||
|
#include "bta_shdata.h"
|
||||||
|
#include "cmdlnopts.h"
|
||||||
|
#include "usefull_macros.h"
|
||||||
|
#include "ch4run.h"
|
||||||
|
#include "stepper.h"
|
||||||
|
|
||||||
|
#ifndef PIDFILE
|
||||||
|
#define PIDFILE "/tmp/p1move.pid"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BUFLEN 1024
|
||||||
|
|
||||||
|
glob_pars *Global_parameters = NULL;
|
||||||
|
|
||||||
|
void signals(int sig){
|
||||||
|
if(sig > 0)
|
||||||
|
WARNX(_("Get signal %d, quit.\n"), sig);
|
||||||
|
unlink(PIDFILE);
|
||||||
|
stop_motor();
|
||||||
|
exit(sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]){
|
||||||
|
check4running(PIDFILE, NULL);
|
||||||
|
initial_setup();
|
||||||
|
Global_parameters = parse_args(argc, argv);
|
||||||
|
assert(Global_parameters);
|
||||||
|
if(!get_shm_block(&sdat, ClientSide) || !check_shm_block(&sdat)){
|
||||||
|
ERRX("Can't get SHM block!");
|
||||||
|
}
|
||||||
|
#ifndef EBUG
|
||||||
|
PRINT(_("Test multicast connection\n"));
|
||||||
|
double last = M_time;
|
||||||
|
WAIT_EVENT((fabs(M_time - last) > 0.02), 5.);
|
||||||
|
if(tmout && fabs(M_time - last) < 4.)
|
||||||
|
ERRX(_("Multicasts stale!"));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
signal(SIGTERM, signals); // kill (-15)
|
||||||
|
signal(SIGHUP, SIG_IGN); // hup - daemon
|
||||||
|
signal(SIGINT, signals); // ctrl+C
|
||||||
|
signal(SIGQUIT, signals); // ctrl+\ .
|
||||||
|
signal(SIGTSTP, SIG_IGN); // ctrl+Z
|
||||||
|
setbuf(stdout, NULL);
|
||||||
|
|
||||||
|
setup_pins();
|
||||||
|
if(Global_parameters->absmove && gotozero()) ERRX(_("Can't locate zero-endswitch"));
|
||||||
|
|
||||||
|
if(Global_parameters->gotoangle > -360. && Global_parameters->gotoangle < 360.){
|
||||||
|
if(Global_parameters->absmove) Global_parameters->gotoangle += PA_ZEROVAL;
|
||||||
|
if(gotoangle(Global_parameters->gotoangle)) ERRX(_("Can't move for given angle"));
|
||||||
|
}
|
||||||
|
|
||||||
|
stepper_process();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
497
p1rotator/parseargs.c
Normal file
497
p1rotator/parseargs.c
Normal file
@ -0,0 +1,497 @@
|
|||||||
|
/* geany_encoding=koi8-r
|
||||||
|
* parseargs.c - parsing command line arguments & print help
|
||||||
|
*
|
||||||
|
* Copyright 2013 Edward V. Emelianoff <eddy@sao.ru>
|
||||||
|
*
|
||||||
|
* 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 <stdio.h> // printf
|
||||||
|
#include <getopt.h> // getopt_long
|
||||||
|
#include <stdlib.h> // calloc, exit, strtoll
|
||||||
|
#include <assert.h> // assert
|
||||||
|
#include <string.h> // strdup, strchr, strlen
|
||||||
|
#include <strings.h>// strcasecmp
|
||||||
|
#include <limits.h> // INT_MAX & so on
|
||||||
|
#include <libintl.h>// gettext
|
||||||
|
#include <ctype.h> // 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;
|
||||||
|
}
|
||||||
124
p1rotator/parseargs.h
Normal file
124
p1rotator/parseargs.h
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* parseargs.h - headers for parsing command line arguments
|
||||||
|
*
|
||||||
|
* Copyright 2013 Edward V. Emelianoff <eddy@sao.ru>
|
||||||
|
*
|
||||||
|
* 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 <stdbool.h>// bool
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#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__
|
||||||
338
p1rotator/stepper.c
Normal file
338
p1rotator/stepper.c
Normal file
@ -0,0 +1,338 @@
|
|||||||
|
/*
|
||||||
|
* stepper.c - functions for working with stepper motors by wiringPi
|
||||||
|
*
|
||||||
|
* Copyright 2015 Edward V. Emelianoff <eddy@sao.ru>
|
||||||
|
*
|
||||||
|
* 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 <stdio.h> // printf, getchar, fopen, perror
|
||||||
|
#include <stdlib.h> // exit
|
||||||
|
#include <signal.h> // signal
|
||||||
|
#include <time.h> // time
|
||||||
|
#include <string.h> // memcpy
|
||||||
|
#include <stdint.h> // int types
|
||||||
|
#include <sys/time.h> // gettimeofday
|
||||||
|
#include <math.h> // fabs, round
|
||||||
|
#include <limits.h> // std types
|
||||||
|
#include <unistd.h> // usleep
|
||||||
|
#include <pthread.h> // threads
|
||||||
|
// use wiringPi on ARM & simple echo on PC (for tests)
|
||||||
|
#ifdef __arm__
|
||||||
|
#include <wiringPi.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "stepper.h"
|
||||||
|
#include "usefull_macros.h"
|
||||||
|
#include "bta_shdata.h"
|
||||||
|
|
||||||
|
#ifndef M_PI
|
||||||
|
#define M_PI (3.14159265358979323846)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define R2D (180./M_PI) // rad. to degr.
|
||||||
|
#define D2R (M_PI/180.) // degr. to rad.
|
||||||
|
#define R2S (648000./M_PI) // rad. to sec
|
||||||
|
#define S2R (M_PI/648000.) // sec. to rad.
|
||||||
|
#define S360 (1296000.) // sec in 360degr
|
||||||
|
|
||||||
|
// By google maps: 43.646683 (43 38 48.0588), 41.440681 (41 26 26.4516)
|
||||||
|
// (real coordinates should be measured relative to mass center, not geoid)
|
||||||
|
//static const double longitude = 149189.175; // SAO longitude 41 26 29.175 (-2:45:45.945)
|
||||||
|
//static const double Fi = 157152.7; // SAO latitude 43 39 12.7
|
||||||
|
static const double cos_fi = 0.7235272793; // Cos of SAO latitude
|
||||||
|
static const double sin_fi = 0.6902957888; // Sin --- "" -----
|
||||||
|
|
||||||
|
// microsteps counter
|
||||||
|
#ifdef __arm__
|
||||||
|
static int32_t absusteps = USTEPSBAD; // rotation in both directions relative to zero
|
||||||
|
#endif // __arm__
|
||||||
|
|
||||||
|
// stop all threads @ exit
|
||||||
|
//static volatile int force_exit = 0;
|
||||||
|
|
||||||
|
#define getpval() (absusteps * PA_MINSTEP)
|
||||||
|
|
||||||
|
double calc_PA(double alpha, double delta, double stime){
|
||||||
|
double sin_t,cos_t, sin_d,cos_d;
|
||||||
|
double t, d, p, sp, cp;
|
||||||
|
|
||||||
|
t = (stime - alpha) * 15.;
|
||||||
|
if (t < 0.)
|
||||||
|
t += S360; // +360degr
|
||||||
|
t *= S2R; // -> rad
|
||||||
|
d = delta * S2R;
|
||||||
|
sincos(t, &sin_t, &cos_t);
|
||||||
|
sincos(d, &sin_d, &cos_d);
|
||||||
|
|
||||||
|
sp = sin_t * cos_fi;
|
||||||
|
cp = sin_fi * cos_d - sin_d * cos_fi * cos_t;
|
||||||
|
p = atan2(sp, cp);
|
||||||
|
if (p < 0.0)
|
||||||
|
p += 2.0*M_PI;
|
||||||
|
return(p * R2D);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_PA(double ang){
|
||||||
|
int d, m;
|
||||||
|
printf("PA: %g degr == ", ang);
|
||||||
|
d = (int)ang;
|
||||||
|
ang = (ang - d) * 60.;
|
||||||
|
m = (int)ang;
|
||||||
|
ang = (ang - m) * 60.;
|
||||||
|
printf("%02d:%02d:%02.1f\n", d, m, ang);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __arm__
|
||||||
|
static void Write(int pin, int val){
|
||||||
|
if(val) val = 1;
|
||||||
|
digitalWrite(pin, val);
|
||||||
|
while(digitalRead(pin) != val);
|
||||||
|
}
|
||||||
|
static void Toggle(int pin){
|
||||||
|
int v = digitalRead(pin);
|
||||||
|
Write(pin, !v);
|
||||||
|
}
|
||||||
|
#endif // __arm__
|
||||||
|
|
||||||
|
void setup_pins(){
|
||||||
|
#ifdef __arm__
|
||||||
|
wiringPiSetupGpio();
|
||||||
|
Write(EN_PIN, PIN_PASSIVE); // disable all @ start
|
||||||
|
Write(DIR_PIN, PIN_PASSIVE);
|
||||||
|
Write(STEP_PIN, PIN_PASSIVE);
|
||||||
|
pinMode(DIR_PIN, OUTPUT);
|
||||||
|
pinMode(EN_PIN, OUTPUT);
|
||||||
|
pinMode(STEP_PIN, OUTPUT);
|
||||||
|
pinMode(ESW_PIN, INPUT);
|
||||||
|
pullUpDnControl(ESW_PIN, PUD_UP);
|
||||||
|
#else // __arm__
|
||||||
|
green("Setup GPIO\n");
|
||||||
|
#endif // __arm__
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable stepper motor
|
||||||
|
*/
|
||||||
|
void stop_motor(){
|
||||||
|
// force_exit = 1;
|
||||||
|
usleep(1000);
|
||||||
|
#ifdef __arm__
|
||||||
|
// disable motor & all other
|
||||||
|
pullUpDnControl(ESW_PIN, PUD_OFF);
|
||||||
|
pinMode(DIR_PIN, INPUT);
|
||||||
|
pinMode(EN_PIN, INPUT);
|
||||||
|
pinMode(STEP_PIN, INPUT);
|
||||||
|
// return values to initial state
|
||||||
|
Write(EN_PIN, 0);
|
||||||
|
Write(DIR_PIN, 0);
|
||||||
|
Write(STEP_PIN, 0);
|
||||||
|
DBG("STOPPED");
|
||||||
|
#else
|
||||||
|
green("Stop Stepper\n");
|
||||||
|
#endif // __arm__
|
||||||
|
}
|
||||||
|
|
||||||
|
// make pause for dt seconds
|
||||||
|
void mk_pause(double dt){
|
||||||
|
int nfd;
|
||||||
|
struct timeval tv;
|
||||||
|
tv.tv_sec = (int)dt;
|
||||||
|
tv.tv_usec = (int)((dt - tv.tv_sec)*1000000.);
|
||||||
|
slipping:
|
||||||
|
nfd = select(0, (fd_set *)NULL,(fd_set *)NULL,(fd_set *)NULL, &tv);
|
||||||
|
if(nfd < 0){
|
||||||
|
if(errno == EINTR) goto slipping;
|
||||||
|
WARN("select()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move motor with max speed for nusteps microsteps
|
||||||
|
*/
|
||||||
|
static void move_motor(int nusteps){
|
||||||
|
if(nusteps == 0) return;
|
||||||
|
int dir = 1;
|
||||||
|
if(nusteps < 0){
|
||||||
|
dir = -1;
|
||||||
|
nusteps = -nusteps;
|
||||||
|
}
|
||||||
|
#ifdef __arm__
|
||||||
|
Write(DIR_PIN, (dir > 0) ? DIR_POSITIVE : DIR_NEGATIVE); // prepare direction
|
||||||
|
for(; nusteps; --nusteps){
|
||||||
|
Toggle(STEP_PIN);
|
||||||
|
mk_pause(USTEP_DELAY);
|
||||||
|
absusteps += dir;
|
||||||
|
}
|
||||||
|
#else // __arm__
|
||||||
|
green("Move motor to %c%g steps\n", (dir > 0) ? '+':'-', (double)nusteps/USTEPS);
|
||||||
|
#endif // __arm__
|
||||||
|
}
|
||||||
|
|
||||||
|
// go to zero end-switch. Return 0 if all OK
|
||||||
|
int gotozero(){
|
||||||
|
#ifdef __arm__
|
||||||
|
int nusteps = ONETURN_USTEPS * 1.1;
|
||||||
|
Write(DIR_PIN, DIR_NEGATIVE);
|
||||||
|
for(; nusteps; --nusteps){
|
||||||
|
Toggle(STEP_PIN);
|
||||||
|
mk_pause(USTEP_DELAY);
|
||||||
|
if(digitalRead(ESW_PIN) == ESW_ACTIVE){
|
||||||
|
DBG("ESW");
|
||||||
|
absusteps = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// didn't catch the end-switch
|
||||||
|
return 1;
|
||||||
|
#else // __arm__
|
||||||
|
green("Go to zero\n");
|
||||||
|
return 0;
|
||||||
|
#endif // __arm__
|
||||||
|
}
|
||||||
|
|
||||||
|
// go to given angle (degrees). Return 0 if catch zero-endswitch
|
||||||
|
int gotoangle(double pa){
|
||||||
|
if(pa > 360. || pa < -360){
|
||||||
|
int x = pa / 360.;
|
||||||
|
pa -= x*360.;
|
||||||
|
}
|
||||||
|
if(pa > 180.) pa -= 360.; // the shortest way
|
||||||
|
DBG("Rotate to %gdegr", pa);
|
||||||
|
int nusteps = pa / PA_MINSTEP;
|
||||||
|
move_motor(nusteps);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/**
|
||||||
|
* Main thread for steppers management
|
||||||
|
*/
|
||||||
|
static void *steppers_thread(_U_ void *buf){
|
||||||
|
DBG("steppers_thr");
|
||||||
|
//double starting_pa_value = CALC_PA(); // starting PA for convert angle into steps
|
||||||
|
// difference in steps === (target_pa_value - starting_pa_value)/PA_MINSTEP
|
||||||
|
#ifdef __arm__
|
||||||
|
double laststeptime, curtime;
|
||||||
|
halfsteptime = 1. / (stepspersec * 8.);
|
||||||
|
DBG("halfsteptime: %g", halfsteptime);
|
||||||
|
laststeptime = dtime();
|
||||||
|
int eswsteps = 0;
|
||||||
|
while(!force_exit){
|
||||||
|
while(target_pa_period < 0.); // no rotation
|
||||||
|
// check rotation direction
|
||||||
|
double current_pa_value = ;
|
||||||
|
if(target_pa_value)
|
||||||
|
if((curtime = dtime()) - laststeptime > halfsteptime + corrtime){
|
||||||
|
Write(STEP_PIN, (++i)%2);
|
||||||
|
laststeptime = curtime;
|
||||||
|
++nusteps;
|
||||||
|
if(nusteps%10 == 0){
|
||||||
|
double have = curtime - t0, need, delt;
|
||||||
|
int x = stepspersec ? stepspersec : 1;
|
||||||
|
if(x > 0) need = (double)nusteps/USTEPS/2./x;
|
||||||
|
else need = (double)nusteps/USTEPS/2.*(-x);
|
||||||
|
delt = have - need;
|
||||||
|
if(fabs(delt) > fabs(olddelt)){
|
||||||
|
corrtime -= delt/20.;
|
||||||
|
}else{
|
||||||
|
corrtime -= delt/100.;
|
||||||
|
}
|
||||||
|
olddelt = delt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else // __arm__
|
||||||
|
green("Main steppers' thread\n");
|
||||||
|
while(!force_exit){
|
||||||
|
usleep(500);
|
||||||
|
}
|
||||||
|
#endif // __arm__
|
||||||
|
DBG("exit motors_thr");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif // 0
|
||||||
|
|
||||||
|
void stepper_process(){
|
||||||
|
DBG("Main thread");
|
||||||
|
/* pthread_t motor_thread;
|
||||||
|
if(pthread_create(&motor_thread, NULL, steppers_thread, NULL)){
|
||||||
|
ERR(_("Can't run motor thread"));
|
||||||
|
}*/
|
||||||
|
// target motor speed & position
|
||||||
|
double target_pa_period = USTEP_DELAY; // max speed
|
||||||
|
int target_usteps = 0, current_usteps = 0, dir = 0;
|
||||||
|
double p_first = CALC_PA(); // initial PA value & value for speed calculation
|
||||||
|
double T_last = dtime();
|
||||||
|
green("Starting PA value: ");
|
||||||
|
print_PA(p_first);
|
||||||
|
DBG("minstep: %g == %g'", PA_MINSTEP, PA_MINSTEP*60.);
|
||||||
|
double curtime = T_last, laststeptime = T_last;
|
||||||
|
//while(!force_exit){ // === while(1)
|
||||||
|
while(1){
|
||||||
|
#ifndef EBUG
|
||||||
|
// don't rotate corrector in non-tracking modes
|
||||||
|
if(Sys_Mode != SysTrkOk){
|
||||||
|
usleep(300000);
|
||||||
|
DBG("Mode: %d", Sys_Mode);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
target_usteps = (CALC_PA() - p_first)/PA_MINSTEP;
|
||||||
|
if(target_usteps == current_usteps){ // no rotation
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
curtime = dtime();
|
||||||
|
if(curtime - T_last > 1.){ // recalculate speed
|
||||||
|
target_pa_period = (curtime - T_last)/fabs(target_usteps - current_usteps)/2. - USTEP_DELAY;
|
||||||
|
if(target_pa_period < USTEP_DELAY) target_pa_period = USTEP_DELAY; // max speed
|
||||||
|
T_last = curtime;
|
||||||
|
green("Current period: %g seconds. Steps: need=%d, curr=%d\n", target_pa_period, target_usteps, current_usteps);
|
||||||
|
}
|
||||||
|
// check rotation direction
|
||||||
|
if(target_usteps > current_usteps){
|
||||||
|
if(dir != 1){ // change direction
|
||||||
|
DBG("Change rotation to positive");
|
||||||
|
dir = 1;
|
||||||
|
#ifdef __arm__
|
||||||
|
Write(DIR_PIN, DIR_POSITIVE);
|
||||||
|
#endif // __arm__
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if(dir != -1){ // change direction
|
||||||
|
DBG("Change rotation to negative");
|
||||||
|
dir = -1;
|
||||||
|
#ifdef __arm__
|
||||||
|
Write(DIR_PIN, DIR_NEGATIVE);
|
||||||
|
#endif // __arm__
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(curtime - laststeptime > target_pa_period){
|
||||||
|
#ifdef __arm__
|
||||||
|
Toggle(STEP_PIN);
|
||||||
|
#endif // __arm__
|
||||||
|
current_usteps += dir;
|
||||||
|
DBG("STEP");
|
||||||
|
}
|
||||||
|
print_PA(CALC_PA());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
#ifdef __arm__
|
||||||
|
#else // __arm__
|
||||||
|
#endif // __arm__
|
||||||
|
*/
|
||||||
48
p1rotator/stepper.h
Normal file
48
p1rotator/stepper.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* stepper.h
|
||||||
|
*
|
||||||
|
* Copyright 2015 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 __STEPPER_H__
|
||||||
|
#define __STEPPER_H__
|
||||||
|
|
||||||
|
double getcurpos();
|
||||||
|
void setup_pins();
|
||||||
|
int gotozero();
|
||||||
|
void stop_motor();
|
||||||
|
int gotoangle(double pa);
|
||||||
|
double corrpa(double newval);
|
||||||
|
double getpval();
|
||||||
|
void mk_pause(double dt);
|
||||||
|
|
||||||
|
void stepper_process();
|
||||||
|
|
||||||
|
//void stop_motor();
|
||||||
|
|
||||||
|
//void *steppers_thread(void *buf);
|
||||||
|
//void Xmove(int dir, unsigned int Nsteps);
|
||||||
|
|
||||||
|
/*
|
||||||
|
int get_rest_steps();
|
||||||
|
int get_direction();
|
||||||
|
int get_endsw();
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif // __STEPPER_H__
|
||||||
75
p1rotator/tmout.c
Normal file
75
p1rotator/tmout.c
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* geany_encoding=koi8-r
|
||||||
|
* tmout.c
|
||||||
|
*
|
||||||
|
* Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <stdio.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include "usefull_macros.h"
|
||||||
|
|
||||||
|
char indi[] = "|/-\\";
|
||||||
|
volatile int tmout = 0;
|
||||||
|
|
||||||
|
static void *tmout_thread(void *buf){
|
||||||
|
int selfd = -1;
|
||||||
|
struct timeval *tv = (struct timeval *) buf;
|
||||||
|
errno = 0;
|
||||||
|
while(selfd < 0){
|
||||||
|
selfd = select(0, NULL, NULL, NULL, tv);
|
||||||
|
if(selfd < 0 && errno != EINTR){
|
||||||
|
WARN(_("Error while select()"));
|
||||||
|
tmout = 1;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tmout = 1;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* run thread with pause [delay] (in seconds), at its end set variable tmout
|
||||||
|
*/
|
||||||
|
void set_timeout(double delay){
|
||||||
|
static int run = 0;
|
||||||
|
static pthread_t athread;
|
||||||
|
static struct timeval tv; // should be static to send this as argument of tmout_thread
|
||||||
|
if(delay < 0.){
|
||||||
|
tmout = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(run && (pthread_kill(athread, 0) != ESRCH)){ // another timeout process detected - kill it
|
||||||
|
pthread_cancel(athread);
|
||||||
|
pthread_join(athread, NULL);
|
||||||
|
}
|
||||||
|
tmout = 0;
|
||||||
|
run = 1;
|
||||||
|
tv.tv_sec = (time_t) delay;
|
||||||
|
tv.tv_usec = (suseconds_t)((delay - (double)tv.tv_sec)*1e6);
|
||||||
|
if(pthread_create(&athread, NULL, tmout_thread, (void*)&tv)){
|
||||||
|
WARN(_("Can't create timeout thread!"));
|
||||||
|
tmout = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
41
p1rotator/tmout.h
Normal file
41
p1rotator/tmout.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* geany_encoding=koi8-r
|
||||||
|
* tmout.h
|
||||||
|
*
|
||||||
|
* Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 __TMOUT_H__
|
||||||
|
#define __TMOUT_H__
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
extern int verbose;
|
||||||
|
extern char indi[];
|
||||||
|
|
||||||
|
#define PRINT(...) do{if(verbose) printf(__VA_ARGS__);}while(0)
|
||||||
|
|
||||||
|
#define WAIT_EVENT(evt, max_delay) do{int __ = 0; set_timeout(max_delay); \
|
||||||
|
char *iptr = indi; PRINT(" "); while(!tmout && !(evt)){ \
|
||||||
|
usleep(100000); if(!*(++iptr)) iptr = indi; if(++__%10==0) PRINT("\b. "); \
|
||||||
|
PRINT("\b%c", *iptr);}; PRINT("\n");}while(0)
|
||||||
|
|
||||||
|
void set_timeout(double delay);
|
||||||
|
extern volatile int tmout;
|
||||||
|
|
||||||
|
#endif // __TMOUT_H__
|
||||||
369
p1rotator/usefull_macros.c
Normal file
369
p1rotator/usefull_macros.c
Normal file
@ -0,0 +1,369 @@
|
|||||||
|
/*
|
||||||
|
* usefull_macros.h - a set of usefull functions: memory, color etc
|
||||||
|
*
|
||||||
|
* Copyright 2013 Edward V. Emelianoff <eddy@sao.ru>
|
||||||
|
*
|
||||||
|
* 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...\n");
|
||||||
|
if ((comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0){
|
||||||
|
WARN("Can't use port %s\n",comdev);
|
||||||
|
ioctl(comfd, TCSANOW, &oldtty); // return TTY to previous state
|
||||||
|
close(comfd);
|
||||||
|
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 = 0; // ~(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
|
||||||
|
tty.c_cc[VTIME] = 5;
|
||||||
|
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 readed bytes
|
||||||
|
*/
|
||||||
|
size_t read_tty(uint8_t *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
|
||||||
|
retval = select(comfd + 1, &rfds, NULL, NULL, &tv);
|
||||||
|
if (!retval) return 0;
|
||||||
|
if(FD_ISSET(comfd, &rfds)){
|
||||||
|
if((L = read(comfd, buff, length)) < 1) return 0;
|
||||||
|
}
|
||||||
|
return (size_t)L;
|
||||||
|
}
|
||||||
|
|
||||||
|
int write_tty(uint8_t *buff, size_t length){
|
||||||
|
ssize_t L = write(comfd, buff, length);
|
||||||
|
if((size_t)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;
|
||||||
|
}
|
||||||
138
p1rotator/usefull_macros.h
Normal file
138
p1rotator/usefull_macros.h
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* usefull_macros.h - a set of usefull macros: memory, color etc
|
||||||
|
*
|
||||||
|
* Copyright 2013 Edward V. Emelianoff <eddy@sao.ru>
|
||||||
|
*
|
||||||
|
* 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 <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#if defined GETTEXT_PACKAGE && defined LOCALEDIR
|
||||||
|
/*
|
||||||
|
* GETTEXT
|
||||||
|
*/
|
||||||
|
#include <libintl.h>
|
||||||
|
#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 <stdlib.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <termio.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
// unused arguments with -Wall -Werror
|
||||||
|
#define _U_ __attribute__((__unused__))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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(uint8_t *buff, size_t length);
|
||||||
|
int write_tty(uint8_t *buff, size_t length);
|
||||||
|
|
||||||
|
int str2double(double *num, const char *str);
|
||||||
|
|
||||||
|
#endif // __USEFULL_MACROS_H__
|
||||||
Loading…
x
Reference in New Issue
Block a user