paulscherrerinstitute / StreamDevice

EPICS Driver for message based I/O
GNU General Public License v3.0
28 stars 42 forks source link

Custom checksum converter with 2 digit decimal value #85

Open hinxx opened 2 years ago

hinxx commented 2 years ago

I'm looking into having https://www.instrumart.com/assets/GE-Druck-DPI104-Communications-Manual.pdf supported in EPICS using streamdevice. The commands include a checksum that is a modulo 100 of the command bytes. This results in checksum values 00 .. 99. So far I've added my own checksum calculation method to support the modulo 100 checksum. Looking at the debug output in the IOC shell I can see that the actual message contains a checksum with three digits which my device is not happy to see.

My checksum calculation function:


// Checksum used by Druck DPI104 pressure gauge
static uint32_t dpi104(const uint8_t* data, size_t len, uint32_t sum)
{
    while (len--)
    {
        sum += *data++;
    }
    sum %= 100;
    return sum;
}

...
static checksum checksumMap[] =
..
    {"dpi104",  dpi104,           0x00,       0x00,       1}  // 0x4D
..

Proto (not handling the input as-per the device docs ATM):

getString {
    out "\$1?:%+<dpi104>";
    in "%\$2[^\r\n]";
    ExtraInput = Ignore;
}

DB:

# Get serial number
record(stringin, "$(P)$(R)SN")
{
    field(DESC, "Serial number string")
    field(DTYP, "stream")
    field(INP,  "@gedpi104.proto getString(SN,39) $(PORT) 0")
}

IOC shell:

2022/04/08 11:06:27.536382 _main_ StreamEpics.cc:858: Stream::process(LAB:DPI0:SN)
2022/04/08 11:06:27.536442 _main_ StreamEpics.cc:884: Stream::process(LAB:DPI0:SN) start
2022/04/08 11:06:27.536505 _main_ StreamCore.cc:424: StreamCore::startProtocol(LAB:DPI0:SN, startMode=StartNormal)
2022/04/08 11:06:27.536559 _main_ StreamCore.cc:557: StreamCore::evalCommand(LAB:DPI0:SN): activeCommand = out
2022/04/08 11:06:27.536623 _main_ StreamCore.cc:682: StreamCore::formatOutput(LAB:DPI0:SN): format = %+<dpi104>
2022/04/08 11:06:27.536674 _main_ ChecksumConverter.cc:662: ChecksumConverter dpi104: output to check: "SN?:"
2022/04/08 11:06:27.536714 _main_ ChecksumConverter.cc:669: ChecksumConverter dpi104: output checksum is 0x52
2022/04/08 11:06:27.536777 _main_ ChecksumConverter.cc:680: ChecksumConverter dpi104: decimal appending 082
2022/04/08 11:06:27.536838 _main_ StreamCore.cc:605: StreamCore::evalOut: outputLine = "SN?:082<0d><0a>"
2022/04/08 11:06:27.536894 _main_ StreamCore.cc:616: StreamCore::evalOut(LAB:DPI0:SN): lockRequest(5000)
2022/04/08 11:06:27.536961 _main_ AsynDriverInterface.cc:551: AsynDriverInterface::lockRequest(LAB:DPI0:SN, 5000 msec)
2022/04/08 11:06:27.537086 DPI0 AsynDriverInterface.cc:1496: AsynDriverInterface::handleRequest(LAB:DPI0:SN) Lock
2022/04/08 11:06:27.537130 DPI0 AsynDriverInterface.cc:592: AsynDriverInterface::lockHandler(LAB:DPI0:SN)
2022/04/08 11:06:27.537170 _main_ StreamEpics.cc:898: Stream::process(LAB:DPI0:SN): protocol started
2022/04/08 11:06:27.537226 DPI0 StreamCore.cc:825: StreamCore::lockCallback(LAB:DPI0:SN, StreamIoSuccess)
2022/04/08 11:06:27.537257 DPI0 AsynDriverInterface.cc:629: AsynDriverInterface::writeRequest(LAB:DPI0:SN, "SN?:082<0d><0a>", 100 msec)
2022/04/08 11:06:27.537311 DPI0 AsynDriverInterface.cc:1496: AsynDriverInterface::handleRequest(LAB:DPI0:SN) Write
2022/04/08 11:06:27.537339 DPI0 AsynDriverInterface.cc:651: AsynDriverInterface::writeHandler(LAB:DPI0:SN)
2022/04/08 11:06:27.537364 DPI0 AsynDriverInterface.cc:669: AsynDriverInterface::writeHandler(LAB:DPI0:SN): reading old input

Notice the "SN?:082<0d><0a>" being sent, whereas "SN?:82<0d><0a>" is expected by the device.

Any tips or tricks on how to only get 2 digit decimal checksum?