summaryrefslogtreecommitdiff
path: root/src/hal/user_comps/mb2hal/mb2hal.h
blob: f5a8d1f63892511438a91063259b3a7c66310de4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#include <stdlib.h>
#include <signal.h>
#include <sys/time.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

#include "rtapi.h"
#ifdef RTAPI
#include "rtapi_app.h"
#endif
#include "rtapi_string.h"
#include "rtapi_errno.h"
#include "hal.h"
#include "inifile.h"
#include "emcglb.h"

#include <modbus.h>

#define MB2HAL_MAX_LINKS            32
#define MB2HAL_MAX_DEVICE_LENGTH    32
#define MB2HAL_DEFAULT_TCP_PORT    502
#define MB2HAL_DEFAULT_MB_RESPONSE_TIMEOUT_MS 500
#define MB2HAL_DEFAULT_MB_BYTE_TIMEOUT_MS     500
#define MB2HAL_DEFAULT_TCP_PORT    502
#define MB2HAL_MAX_FNCT02_ELEMENTS 100
#define MB2HAL_MAX_FNCT03_ELEMENTS 100
#define MB2HAL_MAX_FNCT04_ELEMENTS 100
#define MB2HAL_MAX_FNCT05_ELEMENTS 100
#define MB2HAL_MAX_FNCT15_ELEMENTS 100
#define MB2HAL_MAX_FNCT16_ELEMENTS 100

#ifdef MODULE_VERBOSE
MODULE_VERBOSE(emc2, "component:mb2hal:Userspace HAL component to communicate with one or more Modbus devices");
MODULE_VERBOSE(emc2, "license:LGPL");
MODULE_LICENSE("LGPL");
#endif

typedef enum { linkRTU,
               linkTCP
             } link_type_t;

typedef enum { mbtxERR,
               mbtx_02_READ_DISCRETE_INPUTS,
               mbtx_03_READ_HOLDING_REGISTERS,
               mbtx_04_READ_INPUT_REGISTERS,
               mbtx_15_WRITE_MULTIPLE_COILS,
               mbtx_16_WRITE_MULTIPLE_REGISTERS,
               mbtxMAX
             } mb_tx_fnct; //modbus transaction code
typedef enum { debugSILENT, debugERR, debugOK, debugDEBUG, debugMAX
             } DEBUG_TYPE; //message levels
typedef enum { retOK, retOKwithWarning, retERR
             } retCode; //funtions return codes

#define ERR(debug, fmt, args...) if(debug >= debugERR) {fprintf(stderr, "%s %s ERR: "fmt"\n", gbl.hal_mod_name, fnct_name, ## args);}
#define OK(debug, fmt, args...) if(debug >= debugOK) {fprintf(stdout, "%s %s OK: "fmt"\n", gbl.hal_mod_name, fnct_name, ## args);}
#define DBG(debug, fmt, args...) if(debug >= debugDEBUG) {fprintf(stdout, "%s %s DEBUG: "fmt"\n", gbl.hal_mod_name, fnct_name, ## args);}

//Modbus transaction structure (mb_tx_t)
//Store each transaction defined in INI config file
//Plus HAL and run time parameters for each transaction
typedef struct {
    //cfg_* are link params only for INI config reading purpose
    //then we use the parameters of mb_link_t
    link_type_t cfg_link_type; //RTU (serial) or TCP
    char cfg_link_type_str[10]; //str version of lp_link_type
    char cfg_serial_device[MB2HAL_MAX_DEVICE_LENGTH]; //device: example "/dev/ttyS0"
    int  cfg_serial_baud;      //bauds
    char cfg_serial_parity[5]; //parity: "even", "odd", "none"
    int  cfg_serial_data_bit;  //data bit
    int  cfg_serial_stop_bit;  //stop bit
    int  cfg_serial_delay_ms;  //delay between tx in serial lines
    char cfg_tcp_ip[17];       //tcp address
    int  cfg_tcp_port;         //tcp port number
    //mb_* are Modbus transaction protocol related params
    int        mb_tx_slave_id; //MB device id
    mb_tx_fnct mb_tx_fnct;     //MB function code id
    char       mb_tx_fnct_name[64]; //str version of mb_tx_fnct
    int        mb_tx_1st_addr; //MB first register
    int        mb_tx_nelem;    //MB n registers
    int        mb_response_timeout_ms; //MB response timeout
    int        mb_byte_timeout_ms;     //MB byte timeout
    //cfg_* are others INI config params
    double cfg_update_rate;    //tx update rate
    int    cfg_debug;          //tx debug level (program, may be also protocol)
    //Modbus protocol debug
    int  protocol_debug;       //Flag debug Modbus protocol
    //internal processing values
    int mb_tx_num;         //each tx know it's own number
    int mb_link_num;       //each tx know it's own link
    //internal processing values
    double time_increment; //wait time between tx
    double next_time;      //next time for this tx
    double last_time_ok;   //last OK tx time
    //HAL related params
    char hal_tx_name[HAL_NAME_LEN + 1];
    hal_float_t **float_value;
    hal_s32_t **int_value;
    //hal_float_t *scale;  //not yet implemented
    //hal_float_t *offset; //not yet implemented
    hal_bit_t **bit;
    hal_u32_t **num_errors;     //num of acummulated errors (0=last tx OK)
} mb_tx_t;

//Modbus link structure (mb_link_t)
//Group common transaction's links in one unique link
//Store each run time Modbus link parameters here
typedef struct {
    //lp_* are real link params for real time use
    link_type_t lp_link_type; //RTU (serial) or TCP
    char lp_type_com_str[10]; //str version of lp_type_com
    char lp_serial_device[MB2HAL_MAX_DEVICE_LENGTH]; //device: example "/dev/ttyS0"
    int  lp_serial_baud;      //bauds
    char lp_serial_parity;    //parity: 'E', 'O', 'N'
    //NOTE in mb_tx is "even", "odd", "none"
    int  lp_serial_data_bit;  //data bit
    int  lp_serial_stop_bit;  //stop bit
    int  lp_serial_delay_ms;  //delay between tx in serial lines
    char lp_tcp_ip[17];       //tcp address
    int  lp_tcp_port;         //tcp port number
    //run time processing values
    int mb_link_num;       //corresponding number of this link/thread
    modbus_t *modbus;
    pthread_t thrd;
} mb_link_t;

//Structure of global data (gbl_t)
//Reduce functions parameters using this common global structure.
typedef struct {
    //INI config file
    FILE *ini_file_ptr;
    char *ini_file_path;
    //INI config, common section
    int    init_dbg;
    double slowdown;
    //HAL related
    int   hal_mod_id;
    char *hal_mod_name;
    //mb_tx
    mb_tx_t *mb_tx;
    int tot_mb_tx;
    //mb_links
    mb_link_t *mb_links;
    int   tot_mb_links;
    //others
    const char *mb_tx_fncts[mbtxMAX];
    int quit_flag;
} gbl_t;

extern gbl_t gbl;

//mb2hal.c
void *link_loop_and_logic(void *thrd_link_num);
retCode is_this_tx_ready(const int this_mb_link_num, const int this_mb_tx_num, int *ret_available);
retCode get_tx_connection(const int mb_tx_num, int *ret_connected);
void set_init_gbl_params();
double get_time();
void quit_signal(int signal);
void quit_cleanup(void);

//mb2hal_init.c
retCode parse_main_args(int argc, char **argv);
retCode parse_ini_file();
retCode parse_common_section();
retCode parse_transaction_section(const int mb_tx_num);
retCode parse_tcp_subsection(const char *section, const int mb_tx_num);
retCode parse_serial_subsection(const char *section, const int mb_tx_num);
retCode check_int_in(int n_args, const int int_value, ...);
retCode check_str_in(int n_args, const char *str_value, ...);
retCode init_mb_links();
retCode init_mb_tx();

//mb2hal_hal.c
retCode create_HAL_pins();
retCode create_each_mb_tx_hal_pins(mb_tx_t *mb_tx);

//mb2hal_modbus.c
retCode fnct_15_write_multiple_coils(mb_tx_t *this_mb_tx, mb_link_t *this_mb_link);
retCode fnct_02_read_discrete_inputs(mb_tx_t *this_mb_tx, mb_link_t *this_mb_link);
retCode fnct_04_read_input_registers(mb_tx_t *this_mb_tx, mb_link_t *this_mb_link);
retCode fnct_03_read_holding_registers(mb_tx_t *this_mb_tx, mb_link_t *this_mb_link);
retCode fnct_16_write_multiple_registers(mb_tx_t *this_mb_tx, mb_link_t *this_mb_link);