Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Anders Blomdell
moberg
Commits
c70bcabb
Commit
c70bcabb
authored
Mar 26, 2019
by
Anders Blomdell
Browse files
Added libtest plugin for testing
parent
bc029da6
Changes
6
Hide whitespace changes
Inline
Side-by-side
test/.config/moberg.d
/00-comedi_ttyUSB0_serial.conf
→
examples
/00-comedi_ttyUSB0_serial.conf
View file @
c70bcabb
File moved
test/.config/moberg.d
/30-comedi_ttyUSB0_serial.conf
→
examples
/30-comedi_ttyUSB0_serial.conf
View file @
c70bcabb
File moved
plugins/libtest/Makefile
0 → 100644
View file @
c70bcabb
LIBRARIES
=
libmoberg_libtest.so
CCFLAGS
+=
-Wall
-Werror
-I
../..
-I
.
-O3
-g
-fPIC
LDFLAGS
+=
-Lbuild
/
-lmoberg
LDFLAGS_libtest
=
-shared
-fPIC
-L
../../build
-lmoberg
all
:
$(LIBRARIES:%=build/%)
build/libmoberg_%.so
:
build/%.o Makefile | build
$(CC)
$(LDFLAGS)
$
(
LDFLAGS_
$
(
*
))
-o
$@
$(
filter
%.o,
$^
)
.PRECIOUS
:
build/%.o
build/%.o
:
%.c Makefile | build
$(CC)
$(CCFLAGS)
-c
-o
$@
$<
build
:
mkdir
-p
$@
build/libtest.o
:
../../moberg_module.h
plugins/libtest/libtest.c
0 → 100644
View file @
c70bcabb
/*
libtest.c -- libtest plugin for moberg
Copyright (C) 2019 Anders Blomdell <anders.blomdell@gmail.com>
This file is part of Moberg.
Moberg 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 3 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, see <https://www.gnu.org/licenses/>.
*/
#include
<sys/types.h>
#include
<sys/stat.h>
#include
<fcntl.h>
#include
<sys/ioctl.h>
#include
<asm/termbits.h>
#include
<linux/serial.h>
#include
<unistd.h>
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
#include
<errno.h>
#include
<moberg.h>
#include
<moberg_config.h>
#include
<moberg_device.h>
#include
<moberg_inline.h>
#include
<moberg_module.h>
#include
<moberg_parser.h>
struct
moberg_device_context
{
struct
moberg
*
moberg
;
int
(
*
dlclose
)(
void
*
dlhandle
);
void
*
dlhandle
;
int
use_count
;
double
analog
;
int
digital
;
long
encoder
;
};
struct
moberg_channel_context
{
void
*
to_free
;
/* To be free'd when use_count goes to zero */
struct
moberg_device_context
*
device
;
int
use_count
;
int
index
;
};
struct
moberg_channel_analog_in
{
struct
moberg_channel
channel
;
struct
moberg_channel_context
channel_context
;
};
struct
moberg_channel_analog_out
{
struct
moberg_channel
channel
;
struct
moberg_channel_context
channel_context
;
};
struct
moberg_channel_digital_in
{
struct
moberg_channel
channel
;
struct
moberg_channel_context
channel_context
;
};
struct
moberg_channel_digital_out
{
struct
moberg_channel
channel
;
struct
moberg_channel_context
channel_context
;
};
struct
moberg_channel_encoder_in
{
struct
moberg_channel
channel
;
struct
moberg_channel_context
channel_context
;
};
static
struct
moberg_status
analog_in_read
(
struct
moberg_channel_analog_in
*
analog_in
,
double
*
value
)
{
if
(
!
value
)
{
goto
err_einval
;
}
struct
moberg_channel_context
*
channel
=
&
analog_in
->
channel_context
;
struct
moberg_device_context
*
device
=
channel
->
device
;
*
value
=
device
->
analog
/
(
channel
->
index
+
1
);
return
MOBERG_OK
;
err_einval:
return
MOBERG_ERRNO
(
EINVAL
);
}
static
struct
moberg_status
analog_out_write
(
struct
moberg_channel_analog_out
*
analog_out
,
double
value
)
{
struct
moberg_channel_context
*
channel
=
&
analog_out
->
channel_context
;
struct
moberg_device_context
*
device
=
channel
->
device
;
device
->
analog
=
value
*
(
channel
->
index
+
1
);
return
MOBERG_OK
;
}
static
struct
moberg_status
digital_in_read
(
struct
moberg_channel_digital_in
*
digital_in
,
int
*
value
)
{
if
(
!
value
)
{
goto
err_einval
;
}
struct
moberg_channel_context
*
channel
=
&
digital_in
->
channel_context
;
struct
moberg_device_context
*
device
=
channel
->
device
;
*
value
=
(
device
->
digital
&
(
1
<<
channel
->
index
))
!=
0
;
return
MOBERG_OK
;
err_einval:
return
MOBERG_ERRNO
(
EINVAL
);
}
static
struct
moberg_status
digital_out_write
(
struct
moberg_channel_digital_out
*
digital_out
,
int
value
)
{
struct
moberg_channel_context
*
channel
=
&
digital_out
->
channel_context
;
struct
moberg_device_context
*
device
=
channel
->
device
;
int
mask
=
(
1
<<
channel
->
index
);
if
(
value
)
{
device
->
digital
|=
mask
;
}
else
{
device
->
digital
&=
~
mask
;
}
return
MOBERG_OK
;
}
static
struct
moberg_status
encoder_in_read
(
struct
moberg_channel_encoder_in
*
encoder_in
,
long
*
value
)
{
if
(
!
value
)
{
goto
err_einval
;
}
struct
moberg_channel_context
*
channel
=
&
encoder_in
->
channel_context
;
struct
moberg_device_context
*
device
=
channel
->
device
;
*
value
=
device
->
digital
;
return
MOBERG_OK
;
err_einval:
return
MOBERG_ERRNO
(
EINVAL
);
}
static
struct
moberg_device_context
*
new_context
(
struct
moberg
*
moberg
,
int
(
*
dlclose
)(
void
*
dlhandle
),
void
*
dlhandle
)
{
struct
moberg_device_context
*
result
=
malloc
(
sizeof
(
*
result
));
if
(
result
)
{
memset
(
result
,
0
,
sizeof
(
*
result
));
result
->
moberg
=
moberg
;
result
->
dlclose
=
dlclose
;
result
->
dlhandle
=
dlhandle
;
}
return
result
;
}
static
int
device_up
(
struct
moberg_device_context
*
context
)
{
context
->
use_count
++
;
return
context
->
use_count
;
}
static
int
device_down
(
struct
moberg_device_context
*
context
)
{
context
->
use_count
--
;
if
(
context
->
use_count
<=
0
)
{
moberg_deferred_action
(
context
->
moberg
,
context
->
dlclose
,
context
->
dlhandle
);
free
(
context
);
return
0
;
}
return
context
->
use_count
;
}
static
struct
moberg_status
device_open
(
struct
moberg_device_context
*
device
)
{
return
MOBERG_OK
;
}
static
struct
moberg_status
device_close
(
struct
moberg_device_context
*
device
)
{
return
MOBERG_OK
;
}
static
int
channel_up
(
struct
moberg_channel
*
channel
)
{
device_up
(
channel
->
context
->
device
);
channel
->
context
->
use_count
++
;
return
channel
->
context
->
use_count
;
}
static
int
channel_down
(
struct
moberg_channel
*
channel
)
{
device_down
(
channel
->
context
->
device
);
channel
->
context
->
use_count
--
;
if
(
channel
->
context
->
use_count
<=
0
)
{
free
(
channel
->
context
->
to_free
);
return
0
;
}
return
channel
->
context
->
use_count
;
}
static
struct
moberg_status
channel_open
(
struct
moberg_channel
*
channel
)
{
device_open
(
channel
->
context
->
device
);
return
MOBERG_OK
;
}
static
struct
moberg_status
channel_close
(
struct
moberg_channel
*
channel
)
{
device_close
(
channel
->
context
->
device
);
return
MOBERG_OK
;
}
static
void
init_channel
(
struct
moberg_channel
*
channel
,
void
*
to_free
,
struct
moberg_channel_context
*
context
,
struct
moberg_device_context
*
device
,
int
index
,
enum
moberg_channel_kind
kind
,
union
moberg_channel_action
action
)
{
context
->
to_free
=
to_free
;
context
->
device
=
device
;
context
->
use_count
=
0
;
context
->
index
=
index
;
channel
->
context
=
context
;
channel
->
up
=
channel_up
;
channel
->
down
=
channel_down
;
channel
->
open
=
channel_open
;
channel
->
close
=
channel_close
;
channel
->
kind
=
kind
;
channel
->
action
=
action
;
};
static
struct
moberg_status
parse_config
(
struct
moberg_device_context
*
device
,
struct
moberg_parser_context
*
c
)
{
if
(
!
acceptsym
(
c
,
tok_LBRACE
,
NULL
))
{
goto
syntax_err
;
}
for
(;;)
{
if
(
acceptsym
(
c
,
tok_RBRACE
,
NULL
))
{
break
;
}
else
{
goto
syntax_err
;
}
}
return
MOBERG_OK
;
syntax_err:
return
moberg_parser_failed
(
c
,
stderr
);
}
static
struct
moberg_status
parse_map
(
struct
moberg_device_context
*
device
,
struct
moberg_parser_context
*
c
,
enum
moberg_channel_kind
ignore
,
struct
moberg_channel_map
*
map
)
{
enum
moberg_channel_kind
kind
;
token_t
min
,
max
;
if
(
acceptkeyword
(
c
,
"analog_in"
))
{
kind
=
chan_ANALOGIN
;
}
else
if
(
acceptkeyword
(
c
,
"analog_out"
))
{
kind
=
chan_ANALOGOUT
;
}
else
if
(
acceptkeyword
(
c
,
"digital_in"
))
{
kind
=
chan_DIGITALIN
;
}
else
if
(
acceptkeyword
(
c
,
"digital_out"
))
{
kind
=
chan_DIGITALOUT
;
}
else
if
(
acceptkeyword
(
c
,
"encoder_in"
))
{
kind
=
chan_ENCODERIN
;
}
else
{
goto
syntax_err
;
}
if
(
!
acceptsym
(
c
,
tok_LBRACKET
,
NULL
))
{
goto
syntax_err
;
}
if
(
!
acceptsym
(
c
,
tok_INTEGER
,
&
min
))
{
goto
syntax_err
;
}
if
(
acceptsym
(
c
,
tok_COLON
,
NULL
))
{
if
(
!
acceptsym
(
c
,
tok_INTEGER
,
&
max
))
{
goto
syntax_err
;
}
}
else
{
max
=
min
;
}
if
(
!
acceptsym
(
c
,
tok_RBRACKET
,
NULL
))
{
goto
syntax_err
;
}
for
(
int
i
=
min
.
u
.
integer
.
value
;
i
<=
max
.
u
.
integer
.
value
;
i
++
)
{
switch
(
kind
)
{
case
chan_ANALOGIN
:
{
struct
moberg_channel_analog_in
*
channel
=
malloc
(
sizeof
(
*
channel
));
if
(
!
channel
)
{
goto
err_enomem
;
}
init_channel
(
&
channel
->
channel
,
channel
,
&
channel
->
channel_context
,
device
,
i
,
kind
,
(
union
moberg_channel_action
)
{
.
analog_in
.
context
=
channel
,
.
analog_in
.
read
=
analog_in_read
});
map
->
map
(
map
->
device
,
&
channel
->
channel
);
}
break
;
case
chan_ANALOGOUT
:
{
struct
moberg_channel_analog_out
*
channel
=
malloc
(
sizeof
(
*
channel
));
if
(
!
channel
)
{
goto
err_enomem
;
}
init_channel
(
&
channel
->
channel
,
channel
,
&
channel
->
channel_context
,
device
,
i
,
kind
,
(
union
moberg_channel_action
)
{
.
analog_out
.
context
=
channel
,
.
analog_out
.
write
=
analog_out_write
});
map
->
map
(
map
->
device
,
&
channel
->
channel
);
}
break
;
case
chan_DIGITALIN
:
{
struct
moberg_channel_digital_in
*
channel
=
malloc
(
sizeof
(
*
channel
));
if
(
!
channel
)
{
goto
err_enomem
;
}
init_channel
(
&
channel
->
channel
,
channel
,
&
channel
->
channel_context
,
device
,
i
,
kind
,
(
union
moberg_channel_action
)
{
.
digital_in
.
context
=
channel
,
.
digital_in
.
read
=
digital_in_read
});
map
->
map
(
map
->
device
,
&
channel
->
channel
);
}
break
;
case
chan_DIGITALOUT
:
{
struct
moberg_channel_digital_out
*
channel
=
malloc
(
sizeof
(
*
channel
));
if
(
!
channel
)
{
goto
err_enomem
;
}
init_channel
(
&
channel
->
channel
,
channel
,
&
channel
->
channel_context
,
device
,
i
,
kind
,
(
union
moberg_channel_action
)
{
.
digital_out
.
context
=
channel
,
.
digital_out
.
write
=
digital_out_write
});
map
->
map
(
map
->
device
,
&
channel
->
channel
);
}
break
;
case
chan_ENCODERIN
:
{
struct
moberg_channel_encoder_in
*
channel
=
malloc
(
sizeof
(
*
channel
));
if
(
!
channel
)
{
goto
err_enomem
;
}
init_channel
(
&
channel
->
channel
,
channel
,
&
channel
->
channel_context
,
device
,
i
,
kind
,
(
union
moberg_channel_action
)
{
.
encoder_in
.
context
=
channel
,
.
encoder_in
.
read
=
encoder_in_read
});
map
->
map
(
map
->
device
,
&
channel
->
channel
);
}
break
;
}
}
return
MOBERG_OK
;
err_enomem:
return
MOBERG_ERRNO
(
ENOMEM
);
syntax_err:
return
moberg_parser_failed
(
c
,
stderr
);
}
static
struct
moberg_status
start
(
struct
moberg_device_context
*
device
,
FILE
*
f
)
{
fprintf
(
f
,
"# %s %s
\n
"
,
__FILE__
,
__FUNCTION__
);
return
MOBERG_OK
;
}
static
struct
moberg_status
stop
(
struct
moberg_device_context
*
device
,
FILE
*
f
)
{
fprintf
(
f
,
"# %s %s
\n
"
,
__FILE__
,
__FUNCTION__
);
return
MOBERG_OK
;
}
struct
moberg_device_driver
moberg_device_driver
=
{
.
new
=
new_context
,
.
up
=
device_up
,
.
down
=
device_down
,
.
parse_config
=
parse_config
,
.
parse_map
=
parse_map
,
.
start
=
start
,
.
stop
=
stop
};
test/.config/moberg.d/moberg.conf
View file @
c70bcabb
driver
(
comedi
) {
config
{
/*
Parsed
by
parse_config
in
libmoberg_comedi
.
so
*/
device
=
"/dev/comedi0"
;
modprobe
= [
comedi
"8255"
comedi_fc
mite
ni_tio
ni_tiocmd
ni_pcimio
] ;
config
= [
ni_pcimio
] ;
}
/*
Moberg
mapping
[
indices
] = {
driver
specific
}[
indices
]
{
driver
specific
}
is
parsed
by
parse_map
in
libmoberg_comedi
.
so
*/
map
analog_in
[
0
:
15
] = {
subdevice
[
0
][
0
:
15
] };
map
analog_out
[
0
:
1
] = {
subdevice
[
1
][
0
:
1
] };
map
digital_in
[
0
:
7
] = {
subdevice
[
7
][
15
],
subdevice
[
7
][
2
],
subdevice
[
7
][
11
],
subdevice
[
7
][
4
],
subdevice
[
7
][
3
],
subdevice
[
7
][
10
],
subdevice
[
7
][
8
],
subdevice
[
7
][
9
] };
map
digital_out
[
0
:
7
] = {
subdevice
[
7
]
route
16
[
0
:
1
],
subdevice
[
7
]
route
16
[
5
:
7
],
subdevice
[
7
]
route
16
[
14
],
subdevice
[
7
]
route
16
[
13
],
subdevice
[
7
]
route
16
[
12
] };
}
driver
(
comedi
) {
config
{
/*
Parsed
by
parse_config
in
libmoberg_comedi
.
so
*/
device
=
"/dev/comedi0"
;
modprobe
= [
comedi
serial2002
] ;
config
= [
serial2002
"100"
"115200"
] ;
}
/*
Moberg
mapping
[
indices
] = {
driver
specific
}[
indices
]
{
driver
specific
}
is
parsed
by
parse_map
in
libmoberg_comedi
.
so
*/
map
analog_in
[
0
:
1
] = {
subdevice
[
2
][
0
:
1
] };
}
driver
(
serial2002
) {
config
{
/*
Parsed
by
parse_config
in
libmoberg_serial2002
.
so
*/
device
=
"/dev/ttyS0"
;
baud
=
115200
;
}
/*
Moberg
mapping
[
indices
] = {
driver
specific
}[
indices
]
{
driver
specific
}
is
parsed
by
parse_map
in
libmoberg_serial2002
.
so
*/
map
analog_in
[
30
:
37
] =
analog_in
[
0
:
7
] ;
map
analog_out
[
30
:
37
] =
analog_out
[
0
:
7
] ;
map
digital_in
[
30
:
37
] =
digital_in
[
0
:
7
] ;
map
digital_out
[
30
:
37
] =
digital_out
[
0
:
7
] ;
map
encoder_in
[
30
:
37
] =
encoder_in
[
0
:
7
] ;
driver
(
libtest
) {
config
{ }
map
analog_in
[
0
:
7
] =
analog_in
[
0
:
7
] ;
map
analog_out
[
0
:
7
] =
analog_out
[
0
:
7
] ;
map
digital_in
[
0
:
7
] =
digital_in
[
0
:
7
] ;
map
digital_out
[
0
:
7
] =
digital_out
[
0
:
7
] ;
map
encoder_in
[
0
:
7
] =
encoder_in
[
0
:
7
] ;
}
test/Makefile
View file @
c70bcabb
TEST
=
test_start_stop test_io test_moberg4simulink
CCFLAGS
+=
-Wall
-Werror
-I
$(
shell
pwd
)
-g
LDFLAGS
+=
-L
$(
shell
pwd
)
/build/
-lmoberg
ENV_TEST
=
LD_LIBRARY_PATH
=
../build
HOME
=
.
ENV_TEST
=
LD_LIBRARY_PATH
=
../build
XDG_CONFIG_HOME
=
.config
XDG_CONFIG_DIRS
=
.
LDFLAGS_test_moberg4simulink
=
-lmoberg4simulink
CCFLAGS_test_moberg4simulink
=
-I
../adaptors/matlab
-Wall
-Werror
-I
$(
shell
pwd
)
-g
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment