Commit ee9be737 authored by Anders Blomdell's avatar Anders Blomdell
Browse files

Return the actual value from write operations

parent da5d119e
......@@ -28,7 +28,7 @@ public class Moberg {
public static native void analogOutOpen(int index) throws MobergException;
public static native void analogOutClose(int index) throws MobergException;
public static native void analogOut(int index, double value) throws MobergException;
public static native double analogOut(int index, double value) throws MobergException;
public static native void digitalInOpen(int index) throws MobergException;
public static native void digitalInClose(int index) throws MobergException;
......@@ -36,7 +36,7 @@ public class Moberg {
public static native void digitalOutOpen(int index) throws MobergException;
public static native void digitalOutClose(int index) throws MobergException;
public static native void digitalOut(int index, boolean value) throws MobergException;
public static native boolean digitalOut(int index, boolean value) throws MobergException;
public static native void encoderInOpen(int index) throws MobergException;
public static native void encoderInClose(int index) throws MobergException;
......
......@@ -261,16 +261,19 @@ Java_se_lth_control_realtime_moberg_Moberg_analogOutClose(
}
JNIEXPORT void JNICALL
JNIEXPORT double JNICALL
Java_se_lth_control_realtime_moberg_Moberg_analogOut(
JNIEnv *env, jobject obj, jint index, jdouble value
JNIEnv *env, jobject obj, jint index, jdouble desired
)
{
struct channel *channel = channel_get(&analog_out, index);
if (! channel) {
throwMobergNotOpenException(env, index);
return 0.0;
} else {
channel->analog_out.write(channel->analog_out.context, value);
double actual;
channel->analog_out.write(channel->analog_out.context, desired, &actual);
return actual;
}
}
......@@ -354,16 +357,19 @@ Java_se_lth_control_realtime_moberg_Moberg_digitalOutClose(
}
}
JNIEXPORT void JNICALL
JNIEXPORT jboolean JNICALL
Java_se_lth_control_realtime_moberg_Moberg_digitalOut(
JNIEnv *env, jobject obj, jint index, jboolean value
JNIEnv *env, jobject obj, jint index, jboolean desired
)
{
struct channel *channel = channel_get(&digital_out, index);
if (! channel) {
throwMobergNotOpenException(env, index);
return 0;
} else {
channel->digital_out.write(channel->digital_out.context, value);
int actual;
channel->digital_out.write(channel->digital_out.context, desired, &actual);
return actual;
}
}
......
......@@ -29,8 +29,10 @@ function close(aout::AnalogOut)
end
function write(aout::AnalogOut, value::Cdouble)
result = Ref{Cdouble}(0.0)
checkOK(ccall(aout.channel.write,
Status,
(Ptr{Nothing}, Cdouble),
aout.channel.context, value))
(Ptr{Nothing}, Cdouble, Ptr{Cdouble}),
aout.channel.context, value, result))
return result[];
end
......@@ -29,8 +29,10 @@ function close(dout::DigitalOut)
end
function write(dout::DigitalOut, value::Bool)
result = Ref{Cint}(0)
checkOK(ccall(dout.channel.write,
Status,
(Ptr{Nothing}, Cint),
dout.channel.context, value ? 1 : 0))
(Ptr{Nothing}, Cint, Ptr{Cint}),
dout.channel.context, value ? 1 : 0, result))
return result[] != 0
end
......@@ -136,7 +136,7 @@ static void mdlOutputs(SimStruct *S, int_T tid)
for (i = 0 ; i < ssGetNumPWork(S) ; i++) {
struct moberg_analog_out *aout = (struct moberg_analog_out*)pwork[i];
if (! moberg_OK(aout->write(aout->context, *up[i]))) {
if (! moberg_OK(aout->write(aout->context, *up[i], NULL))) {
static char error[256];
double *channel = mxGetPr(ssGetSFcnParam(S,1));
sprintf(error, "Failed to write analogout #%d", (int)channel[i]);
......
......@@ -136,7 +136,7 @@ static void mdlOutputs(SimStruct *S, int_T tid)
for (i = 0 ; i < ssGetNumPWork(S) ; i++) {
struct moberg_digital_out *dout = (struct moberg_digital_out*)pwork[i];
if (! moberg_OK(dout->write(dout->context, *up[i]))) {
if (! moberg_OK(dout->write(dout->context, *up[i], NULL))) {
static char error[256];
double *channel = mxGetPr(ssGetSFcnParam(S,1));
sprintf(error, "Failed to write digitalout #%d", (int)channel[i]);
......
......@@ -276,7 +276,7 @@ MobergAnalogIn_read(MobergAnalogInObject *self, PyObject *Py_UNUSED(ignored))
PyErr_Format(PyExc_OSError, "moberg._AnalogIn(%d).read() failed with %d",
self->index, status.result);
}
return Py_BuildValue("f", value);
return Py_BuildValue("d", value);
}
static PyMethodDef MobergAnalogIn_methods[] = {
......@@ -373,19 +373,20 @@ MobergAnalogOut_init(MobergAnalogOutObject *self, PyObject *args, PyObject *kwds
static PyObject *
MobergAnalogOut_write(MobergAnalogOutObject *self, PyObject *args)
{
double value = 1.23;
if (! PyArg_ParseTuple(args, "d", &value)) {
double desired_value, actual_value;
if (! PyArg_ParseTuple(args, "d", &desired_value)) {
goto err;
}
struct moberg_status status = self->channel.write(self->channel.context,
value);
desired_value,
&actual_value);
if (!moberg_OK(status)) {
PyErr_Format(PyExc_OSError, "moberg._AnalogOut(%d).write() failed with %d",
self->index, status.result);
goto err;
}
Py_INCREF(Py_None);
return Py_None;
return Py_BuildValue("d", actual_value);
err:
return NULL;
}
......@@ -588,19 +589,20 @@ MobergDigitalOut_init(MobergDigitalOutObject *self, PyObject *args, PyObject *kw
static PyObject *
MobergDigitalOut_write(MobergDigitalOutObject *self, PyObject *args)
{
double value = 1.23;
if (! PyArg_ParseTuple(args, "d", &value)) {
PyObject *desired;
int actual;
if (! PyArg_ParseTuple(args, "O", &desired)) {
goto err;
}
struct moberg_status status = self->channel.write(self->channel.context,
value);
PyObject_IsTrue(desired),
&actual);
if (!moberg_OK(status)) {
PyErr_Format(PyExc_OSError, "moberg._DigitalOut(%d).write() failed with %d",
self->index, status.result);
goto err;
}
Py_INCREF(Py_None);
return Py_None;
return Py_BuildValue("O", actual ? Py_True: Py_False);
err:
return NULL;
}
......
......@@ -53,7 +53,8 @@ struct moberg_analog_in {
struct moberg_analog_out {
struct moberg_channel_analog_out *context;
struct moberg_status (*write)(struct moberg_channel_analog_out *,
double value);
double desired_value,
double *actual_value);
};
struct moberg_digital_in {
......@@ -65,7 +66,8 @@ struct moberg_digital_in {
struct moberg_digital_out {
struct moberg_channel_digital_out *context;
struct moberg_status (*write)(struct moberg_channel_digital_out *,
int value);
int desired_value,
int *actual_value);
};
struct moberg_encoder_in {
......
......@@ -112,16 +112,17 @@ err_errno:
static struct moberg_status analog_out_write(
struct moberg_channel_analog_out *analog_out,
double value)
double desired_value,
double *actual_value)
{
struct channel_descriptor descriptor = analog_out->channel_context.descriptor;
lsampl_t data;
if (value < descriptor.min) {
if (desired_value < descriptor.min) {
data = 0;
} else if (value > descriptor.max) {
} else if (desired_value > descriptor.max) {
data = descriptor.maxdata;
} else {
data = (value - descriptor.min) / descriptor.delta;
data = (desired_value - descriptor.min) / descriptor.delta;
}
if (data < 0) {
data = 0;
......@@ -134,6 +135,10 @@ static struct moberg_status analog_out_write(
0, 0, data)) {
goto err_errno;
}
if (actual_value) {
*actual_value = data * descriptor.delta + descriptor.min;
}
return MOBERG_OK;
err_errno:
return MOBERG_ERRNO(comedi_errno());
......@@ -162,16 +167,20 @@ err_errno:
static struct moberg_status digital_out_write(
struct moberg_channel_digital_out *digital_out,
int value)
int desired_value,
int *actual_value)
{
struct channel_descriptor descriptor = digital_out->channel_context.descriptor;
lsampl_t data = value==0?0:1;
lsampl_t data = desired_value==0?0:1;
if (0 > comedi_data_write(digital_out->channel_context.device->comedi.handle,
descriptor.subdevice,
descriptor.subchannel,
0, 0, data)) {
goto err_errno;
}
if (actual_value) {
*actual_value = data;
}
return MOBERG_OK;
err_errno:
return MOBERG_ERRNO(comedi_errno());
......
......@@ -96,11 +96,15 @@ err_einval:
static struct moberg_status analog_out_write(
struct moberg_channel_analog_out *analog_out,
double value)
double desired_value,
double *actual_value)
{
struct moberg_channel_context *channel = &analog_out->channel_context;
struct moberg_device_context *device = channel->device;
device->analog = value * (channel->index + 1);
device->analog = desired_value * (channel->index + 1);
if (actual_value) {
*actual_value = desired_value;
}
return MOBERG_OK;
}
......@@ -120,16 +124,20 @@ err_einval:
static struct moberg_status digital_out_write(
struct moberg_channel_digital_out *digital_out,
int value)
int desired_value,
int *actual_value)
{
struct moberg_channel_context *channel = &digital_out->channel_context;
struct moberg_device_context *device = channel->device;
int mask = (1<<channel->index);
if (value) {
if (desired_value) {
device->digital |= mask;
} else {
device->digital &= ~mask;
}
if (actual_value) {
*actual_value = desired_value;
}
return MOBERG_OK;
}
......
......@@ -128,12 +128,13 @@ err_einval:
static struct moberg_status analog_out_write(
struct moberg_channel_analog_out *analog_out,
double value)
double desired_value,
double *actual_value)
{
struct moberg_channel_context *channel = &analog_out->channel_context;
struct moberg_device_context *device = channel->device;
struct analog_map map = device->analog_out.map[channel->index];
long as_long = (value - map.min) / map.delta;
long as_long = (desired_value - map.min) / map.delta;
if (as_long < 0) {
as_long = 0;
} else if (as_long > map.maxdata) {
......@@ -141,7 +142,11 @@ static struct moberg_status analog_out_write(
}
struct serial2002_data data = { is_channel, map.index, as_long };
return serial2002_write(device->port.fd, data);
struct moberg_status result = serial2002_write(device->port.fd, data);
if (OK(result) && actual_value) {
*actual_value = data.value * map.delta + map.min;
}
return result;
}
static struct moberg_status digital_in_read(
......@@ -173,13 +178,18 @@ err_einval:
static struct moberg_status digital_out_write(
struct moberg_channel_digital_out *digital_out,
int value)
int desired_value,
int *actual_value)
{
struct moberg_channel_context *channel = &digital_out->channel_context;
struct moberg_device_context *device = channel->device;
struct digital_map map = device->digital_out.map[channel->index];
struct serial2002_data data = { is_digital, map.index, value != 0 };
return serial2002_write(device->port.fd, data);
struct serial2002_data data = { is_digital, map.index, desired_value != 0 };
struct moberg_status result = serial2002_write(device->port.fd, data);
if (OK(result) && actual_value) {
*actual_value = data.value;
}
return result;
}
static struct moberg_status encoder_in_read(
......
......@@ -14,12 +14,13 @@ PYTHON3PATH=$(shell realpath ../adaptors/python/install/usr/lib*/python3*/site-p
all:
.PHONY: test
test: $(PYTEST:%=run_py_%) $(JULIATEST:%=run_jl_%) $(CTEST:%=run_c_%)
test: $(CTEST:%=run_c_%) $(PYTEST:%=run_py_%) $(JULIATEST:%=run_jl_%)
echo Tests run
.PHONY: run_c_%
run_c_%:build/%
$(ENV_TEST) valgrind --leak-check=full ./build/$*
env -i LD_LIBRARY_PATH=../build valgrind --leak-check=full ./build/$*
.PHONY: run_py_%
run_py_%: %.py
......
......@@ -10,7 +10,7 @@ int main(int argc, char *argv[])
}
struct moberg_analog_in ai0;
struct moberg_analog_out ao0;
double ai0_value;
double ai0_value, ao0_actual;
if (! moberg_OK(moberg_analog_in_open(moberg, 0, &ai0))) {
fprintf(stderr, "OPEN failed\n");
goto free;
......@@ -24,11 +24,11 @@ int main(int argc, char *argv[])
fprintf(stderr, "OPEN failed\n");
goto free;
}
if (! moberg_OK(ao0.write(ao0.context, ai0_value * 2))) {
if (! moberg_OK(ao0.write(ao0.context, ai0_value * 2, &ao0_actual))) {
fprintf(stderr, "READ failed\n");
goto close_ao0;
}
fprintf(stderr, "WROTE ao0: %f\n", ai0_value * 2);
fprintf(stderr, "WROTE ao0: %f %f\n", ai0_value * 2, ao0_actual);
close_ao0:
moberg_analog_out_close(moberg, 0, ao0);
close_ai0:
......
......@@ -7,33 +7,32 @@ import MobergIO: read, write
function test()
m = MobergIO.Moberg()
println(stderr,m)
println(m)
for v in -10.0:2.0:10
for i in 0:1
try
aout = MobergIO.AnalogOut(m, Unsigned(i))
value = v + i;
write(aout, value)
print("$value ")
actual = write(aout, value)
print("($value, $actual)")
catch ex
println(stderr,"analog_out $i does not exist $(ex)")
end
end
println(stderr)
flush(stderr)
println()
sleep(0.01)
for j in 0:3
try
ain = MobergIO.AnalogIn(m, Unsigned(j))
println(stderr,read(ain))
catch ex
println(stderr,"analog_in $j does not exist $(ex)")
println("analog_in $j does not exist $(ex)")
end
flush(stderr)
flush(stdout)
end
println(stderr)
flush(stderr)
println()
flush(stdout)
end
for v in false:true
for i in 0:6
......@@ -43,34 +42,34 @@ function test()
write(dout, value)
print("$value ")
catch ex
println(stderr,"digital_out $i does not exist $(ex)")
println("digital_out $i does not exist $(ex)")
end
flush(stderr)
flush(stdout)
end
println(stderr)
flush(stderr)
println()
flush(stdout)
for i in 0:6
try
din = MobergIO.DigitalIn(m, Unsigned(i))
print("$(read(din)) ")
catch ex
println(stderr,"digital_in $i does not exist $(ex)")
println("digital_in $i does not exist $(ex)")
end
flush(stderr)
flush(stdout)
end
println(stderr)
println(stderr)
println()
println()
sleep(0.01)
end
end
test()
println(stderr,"DONE")
flush(stderr)
println("DONE")
flush(stdout)
GC.gc()
println(stderr,"....")
flush(stderr)
println("....")
flush(stdout)
GC.gc() # See https://github.com/JuliaCI/BenchmarkTools.jl/blob/af35d0513fe1e336ad0d8b9a35f924e8461aefa2/src/execution.jl#L1
println(stderr,"Really DONE")
flush(stderr)
println("Really DONE")
flush(stdout)
......@@ -3,11 +3,13 @@
int main(int argc, char *argv[])
{
fprintf(stderr, "NEW\n");
struct moberg *moberg = moberg_new(NULL);
printf("START:\n");
fprintf(stderr, "START:\n");
moberg_start(moberg, stdout);
printf("STOP:\n");
fprintf(stderr, "STOP:\n");
moberg_stop(moberg, stdout);
printf("DONE\n");
fprintf(stderr, "FREE\n");
moberg_free(moberg);
fprintf(stderr, "DONE\n");
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment