Skip to content

Commit

Permalink
Use Analog records, with PREC=0, for uint records
Browse files Browse the repository at this point in the history
This removes the need to clamp the values to the max of a 32-bit integer
Instead we have the full value of a float64 to represent the value,
which allows us to represent the full range of PandA values
  • Loading branch information
AlexanderWells-diamond committed Sep 23, 2022
1 parent bc0e865 commit 6a30ec7
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 16 deletions.
16 changes: 11 additions & 5 deletions pandablocks/ioc/ioc.py
Original file line number Diff line number Diff line change
Expand Up @@ -1117,12 +1117,12 @@ def _make_uint(
# Ensure VAL is clamped to valid range of values.
# The DRVH field is a signed LONG value, but PandA uses unsigned 32-bit
# which can overflow it.
if field_info.max_val > np.iinfo(np.int32).max:
if field_info.max_val > np.finfo(np.float64).max:
logging.warning(
f"Configured maximum value for {record_name} was too large."
f"Restricting to int32 maximum value."
)
max_val = np.iinfo(np.int32).max
max_val = np.finfo(np.float64).max
else:
max_val = field_info.max_val

Expand All @@ -1144,8 +1144,9 @@ def _make_uint_param(
return self._make_uint(
record_name,
field_info,
builder.longOut,
builder.aOut,
initial_value=values[record_name],
PREC=0,
)

def _make_uint_read(
Expand All @@ -1158,8 +1159,9 @@ def _make_uint_read(
return self._make_uint(
record_name,
field_info,
builder.longIn,
builder.aIn,
initial_value=values[record_name],
PREC=0,
)

def _make_uint_write(
Expand All @@ -1170,7 +1172,11 @@ def _make_uint_write(
) -> Dict[EpicsName, RecordInfo]:
self._check_num_values(values, 0)
return self._make_uint(
record_name, field_info, builder.longOut, always_update=True
record_name,
field_info,
builder.aOut,
always_update=True,
PREC=0,
)

def _make_int_param(
Expand Down
17 changes: 6 additions & 11 deletions tests/ioc/test_ioc.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from pathlib import Path
from typing import Dict

import numpy as np
import pytest
from conftest import TEST_PREFIX
from mock import AsyncMock, patch
Expand Down Expand Up @@ -711,23 +710,19 @@ def test_uint_sets_record_attributes(ioc_record_factory: IocRecordFactory):
assert longin_rec.HOPR.Value() == max_val


def test_uint_truncates_max_value(ioc_record_factory: IocRecordFactory, caplog):
"""Test that we correctly truncate a too large maximum value and emit a warning"""
def test_uint_allows_large_value(ioc_record_factory: IocRecordFactory, caplog):
"""Test that we allow large max_values for uint fields"""
name = EpicsName("TEST1")
max_val = 99999999999999999999
uint_field_info = UintFieldInfo("param", "uint", None, max_val)

with caplog.at_level(logging.WARNING):
record_dict = ioc_record_factory._make_uint(
name, uint_field_info, builder.longOut
)
record_dict = ioc_record_factory._make_uint(name, uint_field_info, builder.aOut)

longout_rec = record_dict[name].record
assert longout_rec.DRVH.Value() == np.iinfo(np.int32).max
assert longout_rec.HOPR.Value() == np.iinfo(np.int32).max

assert len(caplog.messages) == 1
assert "Restricting to int32 maximum value." in caplog.text
assert longout_rec.DRVH.Value() == max_val
assert longout_rec.HOPR.Value() == max_val
assert len(caplog.messages) == 0


def test_string_record_label_validator_valid_label():
Expand Down

0 comments on commit 6a30ec7

Please sign in to comment.