Skip to content

Commit 39ac639

Browse files
Add int64in/out record support
1 parent 4bbc933 commit 39ac639

File tree

11 files changed

+72
-34
lines changed

11 files changed

+72
-34
lines changed

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Unreleased_
1212

1313
Added:
1414

15+
- `Add int64In/Out record support <../../pull/161>`_
1516
- `Enable setting alarm status of Out records <../../pull/157>`_
1617
- `Adding the non_interactive_ioc function <../../pull/156>`_
1718

docs/reference/api.rst

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ and stderr streams, is sent directly to the terminal.
155155
but note that only the following records types have direct support from this
156156
module:
157157

158-
ai, ao, bi, bo, longin, longout, mbbi, mbbo, stringin, stringout, waveform
158+
ai, ao, bi, bo, int64in, int64out, longin, longout, mbbi, mbbo, stringin, stringout, waveform
159159

160160
The following methods create records of the corresponding type. For all records
161161
the `initial_value` parameter can be used to specify an initial value for the
@@ -285,6 +285,15 @@ All functions return a wrapped `ProcessDeviceSupportIn` or
285285
Create ``bi`` and ``bo`` records with the specified names for false (zero)
286286
and true (one).
287287

288+
.. function::
289+
int64In(name, LOPR=None, HOPR=None, EGU=None, **fields)
290+
int64Out(name, DRVL=None, DRVH=None, EGU=None, **fields)
291+
292+
Create ``int64In`` and ``int64Out`` records with specified limits and units.
293+
The lower and upper display limits for the record can be specified. For
294+
``int64Out`` records the ``LOPR`` and ``HOPR`` fields will be set by default
295+
to the values of the ``DRVL`` and ``DRVH`` fields respectively.
296+
288297
.. function::
289298
longIn(name, LOPR=None, HOPR=None, EGU=None, **fields)
290299
longOut(name, DRVL=None, DRVH=None, EGU=None, **fields)
@@ -532,15 +541,17 @@ Create IN records (used for publishing data *from* the IOC, the naming of the
532541
direction is confusing) using the following `softioc.builder` methods:
533542

534543
:func:`~softioc.builder.aIn`, :func:`~softioc.builder.boolIn`,
535-
:func:`~softioc.builder.longIn`, :func:`~softioc.builder.stringIn`,
536-
:func:`~softioc.builder.mbbIn`, :func:`~softioc.builder.WaveformIn`.
544+
:func:`~softioc.builder.int64In` :func:`~softioc.builder.longIn`,
545+
:func:`~softioc.builder.stringIn`, :func:`~softioc.builder.mbbIn`,
546+
:func:`~softioc.builder.WaveformIn`.
537547

538548
Create OUT records for receiving control information into the IOC using the
539549
following methods:
540550

541551
:func:`~softioc.builder.aOut`, :func:`~softioc.builder.boolOut`,
542-
:func:`~softioc.builder.longOut`, :func:`~softioc.builder.stringOut`,
543-
:func:`~softioc.builder.mbbOut`, :func:`~softioc.builder.WaveformOut`.
552+
:func:`~softioc.builder.int64Out`, :func:`~softioc.builder.longOut`,
553+
:func:`~softioc.builder.stringOut`, :func:`~softioc.builder.mbbOut`,
554+
:func:`~softioc.builder.WaveformOut`.
544555

545556
For all records the `initial_value` keyword argument can be used to specify the
546557
records value on startup.
@@ -554,7 +565,7 @@ class which provides the methods documented below.
554565
.. class:: ProcessDeviceSupportIn
555566

556567
This class is used to implement Python device support for the record types
557-
``ai``, ``bi``, ``longin``, ``mbbi`` and IN ``waveform`` records.
568+
``ai``, ``bi``, ``int64in``, ``longin``, ``mbbi`` and IN ``waveform`` records.
558569

559570
.. method:: set(value, severity=NO_ALARM, alarm=NO_ALARM, timestamp=None)
560571

softioc/builder.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,17 @@ def longOut(name, DRVL=None, DRVH=None, EGU=None, **fields):
7878
_set_scalar_out_defaults(fields, DRVL, DRVH)
7979
return PythonDevice.longout(name, EGU = EGU, **fields)
8080

81+
def int64In(name, LOPR=None, HOPR=None, EGU=None, **fields):
82+
_set_in_defaults(fields)
83+
fields.setdefault('MDEL', -1)
84+
return PythonDevice.int64in(
85+
name, LOPR = LOPR, HOPR = HOPR, EGU = EGU, **fields)
86+
87+
def int64Out(name, DRVL=None, DRVH=None, EGU=None, **fields):
88+
_set_out_defaults(fields)
89+
_set_scalar_out_defaults(fields, DRVL, DRVH)
90+
return PythonDevice.int64out(name, EGU = EGU, **fields)
91+
8192

8293
# Field name prefixes for mbbi/mbbo records.
8394
_mbbPrefixes = [

softioc/device.dbd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
device(longin, INST_IO, devPython_longin, "Python")
22
device(longout, INST_IO, devPython_longout, "Python")
3+
device(int64in, INST_IO, devPython_int64in, "Python")
4+
device(int64out, INST_IO, devPython_int64out, "Python")
35
device(ai, INST_IO, devPython_ai, "Python")
46
device(ao, INST_IO, devPython_ao, "Python")
57
device(bi, INST_IO, devPython_bi, "Python")

softioc/device.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,8 @@ def _Device_Out(*args, **kargs):
316316

317317
longin = _Device_In('longin', c_int32, fields.DBF_LONG, EPICS_OK)
318318
longout = _Device_Out('longout', c_int32, fields.DBF_LONG, EPICS_OK)
319+
int64in = _Device_In('int64in', c_int64, fields.DBF_INT64, EPICS_OK)
320+
int64out = _Device_Out('int64out', c_int64, fields.DBF_INT64, EPICS_OK)
319321
bi = _Device_In('bi', c_uint16, fields.DBF_CHAR, NO_CONVERT)
320322
bo = _Device_Out('bo', c_uint16, fields.DBF_CHAR, NO_CONVERT)
321323
mbbi = _Device_In('mbbi', c_uint16, fields.DBF_SHORT, NO_CONVERT)

softioc/extension.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ static void set_dict_item_steal(
3232

3333
/* Alas, EPICS has changed the numerical assignments of the DBF_ enums between
3434
* versions, so to avoid unpleasant surprises, we compute thes values here in C
35-
* and pass them back to the Python layer. */
35+
* and pass them back to the Python layer. Order matches dbFldTypes.h. */
3636
static PyObject *get_DBF_values(PyObject *self, PyObject *args)
3737
{
3838
PyObject *dict = PyDict_New();
@@ -43,6 +43,8 @@ static PyObject *get_DBF_values(PyObject *self, PyObject *args)
4343
ADD_ENUM(dict, DBF_USHORT);
4444
ADD_ENUM(dict, DBF_LONG);
4545
ADD_ENUM(dict, DBF_ULONG);
46+
ADD_ENUM(dict, DBF_INT64);
47+
ADD_ENUM(dict, DBF_UINT64);
4648
ADD_ENUM(dict, DBF_FLOAT);
4749
ADD_ENUM(dict, DBF_DOUBLE);
4850
ADD_ENUM(dict, DBF_ENUM);

softioc/fields.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22

33
from __future__ import print_function
44

5-
import sys
65
from ctypes import *
76
from .imports import get_field_offsets, get_DBF_values
8-
import numpy
7+
98

109
from epicscorelibs.ca.dbr import *
1110
from epicscorelibs.ca.dbr import ca_timestamp, EPICS_epoch
@@ -32,6 +31,8 @@
3231
DBF_SHORT: c_int16,
3332
DBF_USHORT: c_uint16,
3433
DBF_LONG: c_int32,
34+
DBF_INT64: c_int64,
35+
DBF_UINT64: c_uint64, # TODO: Check whether this has same issue as below note
3536
DBF_ULONG: c_int32, # Should be uint32, but causes trouble later.
3637
DBF_FLOAT: c_float,
3738
DBF_DOUBLE: c_double,
@@ -50,6 +51,8 @@
5051
DBR_ENUM: DBF_ENUM,
5152
DBR_CHAR: DBF_CHAR,
5253
DBR_LONG: DBF_LONG,
54+
# DBR_INT64: DBF_INT64, # TODO: the DBR_ definitions come from epicscorelibs.ca.dbr, but they don't define the 64 versions
55+
# DBR_UINT64: DBF_UINT64,
5356
DBR_DOUBLE: DBF_DOUBLE
5457
}
5558

softioc/pythonSoftIoc.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,9 @@ class PythonDevice(object):
8989
@classmethod
9090
def __init_class__(cls):
9191
for name in [
92-
'ai', 'bi', 'longin', 'mbbi', 'stringin',
93-
'ao', 'bo', 'longout', 'mbbo', 'stringout', 'waveform']:
92+
'ai', 'bi', 'longin', 'mbbi', 'stringin', 'int64in',
93+
'ao', 'bo', 'longout', 'mbbo', 'stringout', 'int64out',
94+
'waveform']:
9495
builder = getattr(epicsdbbuilder.records, name)
9596
record = getattr(device, name)
9697
setattr(cls, name, cls.makeRecord(builder, record))

tests/conftest.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,20 @@
99
from typing import Any
1010
import pytest
1111

12+
from softioc import builder
1213
from softioc.builder import ClearRecords
1314

15+
in_records = [
16+
builder.aIn,
17+
builder.boolIn,
18+
builder.longIn,
19+
builder.int64In,
20+
builder.mbbIn,
21+
builder.stringIn,
22+
builder.WaveformIn,
23+
builder.longStringIn,
24+
]
25+
1426
requires_cothread = pytest.mark.skipif(
1527
sys.platform.startswith("win"), reason="Cothread doesn't work on windows"
1628
)

tests/test_record_values.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import multiprocessing
21
from typing import List
32
import numpy
43
import pytest
@@ -12,7 +11,8 @@
1211
log,
1312
select_and_recv,
1413
TIMEOUT,
15-
get_multiprocessing_context
14+
get_multiprocessing_context,
15+
in_records,
1616
)
1717

1818
from softioc import asyncio_dispatcher, builder, softioc
@@ -54,23 +54,15 @@ def record_func_names(fixture_value):
5454
builder.WaveformOut,
5555
builder.longStringIn,
5656
builder.longStringOut,
57+
builder.int64In,
58+
builder.int64Out,
5759
],
5860
ids=record_func_names,
5961
)
6062
def record_func(request):
6163
"""The list of record creation functions"""
6264
return request.param
6365

64-
# A list of all In records, used to filter out various tests
65-
in_records = [
66-
builder.aIn,
67-
builder.boolIn,
68-
builder.longIn,
69-
builder.mbbIn,
70-
builder.stringIn,
71-
builder.WaveformIn,
72-
builder.longStringIn,
73-
]
7466

7567
def record_values_names(fixture_value):
7668
"""Provide a nice name for the tests in the record_values fixture"""
@@ -96,6 +88,8 @@ def record_values_names(fixture_value):
9688
("aOut_nan", builder.aOut, nan, nan, float),
9789
("longIn_int", builder.longIn, 5, 5, int),
9890
("longOut_int", builder.longOut, 5, 5, int),
91+
("int64In_int", builder.int64In, 65, 65, int),
92+
("int64Out_int", builder.int64Out, 65, 65, int),
9993
("boolIn_int", builder.boolIn, 1, 1, int),
10094
("boolOut_int", builder.boolOut, 1, 1, int),
10195
("boolIn_true", builder.boolIn, True, 1, int),
@@ -737,6 +731,8 @@ def test_value_post_init_caput(self):
737731
("default_aIn", builder.aIn, None, 0.0, float),
738732
("default_longOut", builder.longOut, None, 0, int),
739733
("default_longIn", builder.longIn, None, 0, int),
734+
("default_int64Out", builder.int64Out, None, 0, int),
735+
("default_int64In", builder.int64In, None, 0, int),
740736
("default_boolOut", builder.boolOut, None, 0, int),
741737
("default_boolIn", builder.boolIn, None, 0, int),
742738
("default_Action", builder.Action, None, 0, int),
@@ -761,6 +757,8 @@ class TestDefaultValue:
761757
(builder.aIn, 0.0, float),
762758
(builder.longOut, 0, int),
763759
(builder.longIn, 0, int),
760+
(builder.int64Out, 0, int),
761+
(builder.int64In, 0, int),
764762
(builder.boolOut, 0, int),
765763
(builder.boolIn, 0, int),
766764
(builder.Action, 0, int),

0 commit comments

Comments
 (0)