Skip to content

Conversation

@ckuethe
Copy link
Contributor

@ckuethe ckuethe commented May 5, 2025

Following on to #48 , I thought I might do some initial work on simplifying the batch_read_vsfrs() API. As best I can tell, radiacode transports all VSFRs as uint32le on the wire, no matter how many information-bearing bits they contain: a bool takes 32 bits, just like a float.

Conveniently, the SFR_FILE VS tells us which VSFR IDs are defined, and how to interpret them. It is fairly straightforward to parse the output of the commands() function which reads the SFR_FILE to produce a dict of format strings.

I updated batch_read_vsfrs() and its callers to omit the format argument, and just use the lookup dict to figure out what format to use.

As a quick test, the get_alarm_limits() function works correctly, as does the hand-rolled equivalent of energy_calib(): rc.batch_read_vsfrs([ CHN_TO_keV_A0, CHN_TO_keV_A1, CHN_TO_keV_A2])

Thoughs?

PS. here's the trashy script I used to generate the body of the lookup dict...

import iniconfig
import radiacode

cf = iniconfig.IniConfig('', data=radiacode.RadiaCode().commands())

for k in cf.sections:
    v = dict(cf[k].items())
    k = k.removeprefix('RC_').removeprefix('VSFR_')
    c = None
    if v.get('Type', "") == 'float':
        c = 'f'
    else:
        if v.get('Size', False) == '1':
            if v.get('Min', False) == '0' and v.get('Max', False) == '1':
                c = '3x?'
            else:
                c = '3xb' if v.get('Signed', False) == '1' else '3xB'
        elif v.get('Size', False) == '2':
            c = '2xh' if v.get('Signed', False) == '1' else '2xH'
        elif v.get('Size', False) == '4':
            c = 'i' if v.get('Signed', False) == '1' else 'I'

    print(f"\tVSFR.{k}: '{c}',")

As best I can tell, radiacode transports all VSFRs as uint32le on the wire,
no matter how many information-bearing bits they contain: a bool takes 32
bits, just like a float.

Conveniently, the SFR_FILE VS tells us which VSFR IDs are defined, and how
to interpret them. It is fairly straightforward to parse the output of the
`commands()` function which reads the `SFR_FILE` to produce a dict of format
strings.

Update `batch_read_vsfrs()` and its callers to omit the format argument,
and just use the lookup dict to figure out what format to use.

As an initial test, the `get_alarm_limits()` function works correctly, as
does the hand-rolled equivalent of `energy_calib()`:

`rc.batch_read_vsfrs( [ CHN_TO_keV_A0, CHN_TO_keV_A1, CHN_TO_keV_A2 ] )`

```
import iniconfig

cf = iniconfig.IniConfig('', data=radiacode.RadiaCode().commands())

for k in cf.sections:
    v = dict(cf[k].items())
    k = k.removeprefix('RC_').removeprefix('VSFR_')
    c = None
    if v.get('Type', "") == 'float':
        c = 'f'
    else:
        if v.get('Size', False) == '1':
            if v.get('Min', False) == '0' and v.get('Max', False) == '1':
                c = '3x?'
            else:
                c = '3xb' if v.get('Signed', False) == '1' else '3xB'
        elif v.get('Size', False) == '2':
            c = '2xh' if v.get('Signed', False) == '1' else '2xH'
        elif v.get('Size', False) == '4':
            c = 'i' if v.get('Signed', False) == '1' else 'I'

    print(f"\tVSFR.{k}: '{c}',")
```
@cdump cdump merged commit 99c5bb0 into cdump:master Jun 2, 2025
1 check passed
@ckuethe ckuethe deleted the embed_unpack_format_in_vsfr branch September 30, 2025 19:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants