Compare commits

..

29 Commits
2.8.3 ... 2.8.7

Author SHA1 Message Date
9ef1653e73 Use inverse instead of fat for hex byte output because not all terminals support fat off 2018-11-16 15:26:33 +01:00
d1d65344af define feature test macro to ensure vsnprintf is available 2018-11-16 12:02:33 +01:00
a76adc31ab Implement needed vsnprintf for vxWorks 5. (vxWorks 6 has it already) 2018-11-16 11:49:25 +01:00
a2fcbc81c8 RTEMS has vsnprintf at least since 4.5.1-pre3 2018-11-16 11:22:45 +01:00
fa51c376c1 Windows has vsnprintf at least since 2003 2018-11-16 10:59:32 +01:00
483530f053 enable rendering of ANSI term colors on Windows console 2018-11-16 10:40:04 +01:00
8f34dd2c84 avoid problems with echo and quotes in Windows 2018-11-16 10:28:46 +01:00
493dc19d8b fix problem with redirects to records that do not start with a letter or underscore 2018-11-14 15:26:33 +01:00
3b64242ffd Merge branch 'master' of github.com:paulscherrerinstitute/StreamDevice 2018-11-14 11:41:47 +01:00
280cb7765a Merge pull request #19 from shadowguy/master
EPICS R3.15.6 dev guide
2018-11-14 11:01:48 +01:00
835e68bd76 fix test: sign extension does not depend on 32 or 64 bit architecture any more 2018-10-10 11:47:42 +02:00
92903361d0 handle state alarms in mbbo update 2018-10-10 11:08:41 +02:00
fb937316aa fix bug in mbbo string readback 2018-10-10 11:06:58 +02:00
ae6ebc4106 mbbo changes: use SHFT and MASK even with VAL (if no xxVL defined or ENUM format) 2018-10-10 11:06:22 +02:00
0f0dd31a0d test build with epics 7 2018-10-10 10:01:18 +02:00
189e61bbe8 Prep for EPICS R3.15.6 release 2018-10-06 15:22:48 +02:00
d8f88c340a remove STREAM_PATCHLEVEL macro because I always forget to update it anyway 2018-09-27 16:21:46 +02:00
2ef5c47f19 fix rule to rebuild StreamVersion.o whenever any other object code changed 2018-09-27 16:05:35 +02:00
cb4d490fb6 added RELEASE variable for SynApps 2018-09-25 14:35:20 +02:00
da281ebf97 Merge branch 'master' of github.com:paulscherrerinstitute/StreamDevice 2018-09-19 16:42:12 +02:00
c832efbcb6 Merge pull request #17 from shadowguy/master
Updated more EPICS web links.  SynApps link was actually broken
2018-09-19 16:41:37 +02:00
b7b3bc0af0 Fix problem with \? at end of input format when no more input is available. Used to work. Works again (but was not really intended) 2018-09-19 16:36:01 +02:00
4a42c3d43a Web link fixes, updated 3.14.8 dev guide link to 3.14.12 2018-09-17 14:13:39 +02:00
624cc0134a Merge branch 'master' of github.com:paulscherrerinstitute/StreamDevice 2018-09-14 16:19:09 +02:00
d9d5d5f55d Merge pull request #16 from shadowguy/master
Typo
2018-09-14 16:18:07 +02:00
53ea75dc80 use macro instead of magic value 2018-09-12 09:48:55 +02:00
b1f4c2a7d9 improve debug message 2018-09-11 18:27:52 +02:00
d87e9cedd2 reset proc to 0 in case it had been 2 to trigger @init 2018-09-11 18:19:58 +02:00
9e972d3f33 Typo 2018-09-05 22:21:12 +02:00
17 changed files with 131 additions and 73 deletions

View File

@ -32,9 +32,8 @@ HEADERS += StreamError.h
StreamCore.o StreamCore.d: streamReferences
# Update version string (contains __DATE__ and __TIME__)
# each time make runs.
StreamVersion.o: FORCE
FORCE:
# each time anything changes.
StreamVersion.o: $(filter-out StreamVersion.o stream_exportAddress.o,$(LIBOBJS))
streamReferences:
$(PERL) ../src/makeref.pl Interface $(BUSSES) > $@

View File

@ -1,6 +1,6 @@
# StreamDevice
_StreamDevice_ is a generic [EPICS](https://www.aps.anl.gov/epics)
_StreamDevice_ is a generic [EPICS](https://epics.anl.gov/)
device support for devices with a "byte stream" based
communication interface.
That means devices that can be controlled by sending and receiving

View File

@ -14,14 +14,21 @@ TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top
# define INSTALL_LOCATION_APP here
#INSTALL_LOCATION_APP=<fullpathname>
# For SynApps:
RELEASE=
EPICS_BASE=/usr/local/epics/base-3.16.1
ASYN=~/top-3.16/asyn4-30
CALC=~/top-3.16/SynApps/calc-2-8
PCRE=~/top-3.16/pcre-7-2
PCRE_INCLUDE_SL6-x86=/usr/include
PCRE_INCLUDE_SL6-x86_64=/usr/include
PCRE_INCLUDE_SL6-x86_64-clang=/usr/include
EPICS_BASE=/usr/local/epics/base-7.0.1
ASYN=~/top-7/asyn4-33
CALC=~/top-7/SynApps/calc-2-8
PCRE=~/top-7/pcre-7-2
#EPICS_BASE=/usr/local/epics/base-3.16.1
#ASYN=~/top-3.16/asyn4-30
#CALC=~/top-3.16/SynApps/calc-2-8
#PCRE=~/top-3.16/pcre-7-2
#PCRE_INCLUDE_SL6-x86=/usr/include
#PCRE_INCLUDE_SL6-x86_64=/usr/include
#PCRE_INCLUDE_SL6-x86_64-clang=/usr/include
#EPICS_BASE=/usr/local/epics/base-3.15.5
#ASYN=~/top-3.15/asyn4-30

View File

@ -53,7 +53,7 @@ RegisterConverter(MyConverter,"Q");
</pre>
<a name="theory"></a>
<h2>Theroy of Operation</h2>
<h2>Theory of Operation</h2>
<a name="registration"></a>
<h3>Registration </h3>

View File

@ -15,7 +15,7 @@
<h2>What is <em>StreamDevice</em>?</h2>
<p>
<em>StreamDevice</em> is a generic
<a href="https://www.aps.anl.gov/epics" target="ex">EPICS</a>
<a href="https://epics.anl.gov/" target="ex">EPICS</a>
device support for devices with a "byte stream" based
communication interface.
That means devices that can be controlled by sending and
@ -98,7 +98,7 @@ come in a predictible order to be parsable by <em>StreamDevice</em>.
IOC Application Developer's Guide:
<a href="https://epics.anl.gov/base/R3-14/12-docs/AppDevGuide/"
target="ex">R3.14.12</a>,
<a href="https://epics.anl.gov/base/R3-15/5-docs/AppDevGuide/AppDevGuide.html"
<a href="https://epics.anl.gov/base/R3-15/6-docs/AppDevGuide/AppDevGuide.html"
target="ex">R3.15.5</a>,
<a href="https://epics.anl.gov/base/R3-16/1-docs/AppDevGuide/AppDevGuide.html"
target="ex">R3.16.1</a>

View File

@ -23,7 +23,7 @@ written or read value.
<dd>
Not allowed.
</dd>
<dt>LONG format (e.g. <code>%i</code>):</dt>
<dt>LONG <span class=new>or ENUM</span> format (e.g. <code>%i</code>):</dt>
<dd>
<dl>
<dt>If any of <code>ZRVL</code> ... <code>FFVL</code> is set
@ -41,17 +41,12 @@ written or read value.
</dd>
<dt>If none of <code>ZRVL</code> ... <code>FFVL</code> is set
(all are <code>0</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=VAL</code><br>
<u>Input:</u> <code>VAL=<i>x</i></code><br>
<dd class=new>
<u>Output:</u> <code><i>x</i>=(VAL&lt;&lt;SHFT)&amp;MASK</code><br>
<u>Input:</u> <code>VAL=(RBV=(<i>x</i>&amp;MASK))&gt;&gt;SHFT</code><br>
</dd>
</dl>
</dd>
<dt>ENUM format (e.g. <code>%{</code>):</dt>
<dd>
<u>Output:</u> <code><i>x</i>=VAL</code><br>
<u>Input:</u> <code>VAL=<i>x</i></code><br>
</dd>
<dt>STRING format (e.g. <code>%s</code>):</dt>
<dd>
<u>Output:</u> Depending on <code>VAL</code>, one of <code>ZRST</code>

View File

@ -16,7 +16,7 @@
<h2>1. Normal Processing</h2>
<p>
<em>StreamDevice</em> is an asynchronous device support
(see <a href="http://www.aps.anl.gov/epics/base/R3-14/8-docs/AppDevGuide.pdf"
(see <a href="http://www.aps.anl.gov/epics/base/R3-14/12-docs/AppDevGuide.pdf"
target="ex">IOC Application Developer's Guide</a> chapter 12:
Device Support).
Whenever the record is processed, the <a href="protocol.html">protocol</a>

View File

@ -15,7 +15,7 @@
<p>
<b>Note:</b> The scalcout record is part of the <i>calc</i> module of
the <a target="ex"
href="http://www.aps.anl.gov/aod/bcda/synApps/index.php"
href="https://www.aps.anl.gov/BCDA/synApps"
><em>synApps</em></a> package.
Device support for scalcout records is only available for <i>calc</i>
module release 2-4 or higher.

View File

@ -74,7 +74,7 @@ CPPFLAGS += -DUSE_TYPED_RSET
-include $(TOP)/configure/RULES
# Update version string whenever something changes
StreamVersion$(OBJ): ../*.c ../*.h ../*.cc ../CONFIG_STREAM
StreamVersion$(OBJ): $(filter-out StreamVersion.o,$(LIBOBJS)$(LIBRARY_OBJS))
# Add references to all registrars to main file to avoid
# missing initialization.
@ -86,10 +86,7 @@ streamReferences: ../CONFIG_STREAM
# create stream.dbd from all RECORDTYPES
$(COMMON_DIR)/$(LIBRARY_DEFAULT).dbd: ../CONFIG_STREAM
$(PERL) ../makedbd.pl $(RECORDTYPES) > $@
ifdef ASYN
echo "registrar(AsynDriverInterfaceRegistrar)" >> $@
endif
$(PERL) ../makedbd.pl $(if $(ASYN),--with-asyn) $(if $(BASE_3_14),,-3.13) $(RECORDTYPES) > $@
$(LIBRARY_DEFAULT).dbd$(DEP): ../CONFIG_STREAM
echo $(LIBRARY_DEFAULT).dbd: $< > $@

View File

@ -17,6 +17,11 @@
* *
***************************************************************/
// Make sure that vsnprintf is available
#ifndef _BSD_SOURCE
#define _BSD_SOURCE
#endif
#include "StreamBuffer.h"
#include "StreamError.h"
@ -24,10 +29,47 @@
#include <stdarg.h>
#include <stdlib.h>
#if defined(__vxworks) || defined(vxWorks) || defined(_WIN32) || defined(__rtems__)
// These systems have no vsnprintf
#define vsnprintf(p,l,f,v) vsprintf(p,f,v)
#endif
#ifdef vxWorks
#include <version.h>
#ifndef _WRS_VXWORKS_MAJOR
// VxWorks 5 has no vsnprintf
// Implementation taken from EPICS 3.14
#include <vxWorks.h>
#include <fioLib.h>
struct outStr_s {
char *str;
int free;
};
static STATUS outRoutine(char *buffer, int nchars, int outarg) {
struct outStr_s *poutStr = (struct outStr_s *) outarg;
int free = poutStr->free;
int len;
if (free < 1) { /*let fioFormatV continue to count length*/
return OK;
} else if (free > 1) {
len = min(free-1, nchars);
strncpy(poutStr->str, buffer, len);
poutStr->str += len;
poutStr->free -= len;
}
/*make sure final string is null terminated*/
*poutStr->str = 0;
return OK;
}
int vsnprintf(char *str, size_t size, const char *format, va_list ap) {
struct outStr_s outStr;
outStr.str = str;
outStr.free = size;
return fioFormatV(format, ap, (FUNCPTR)outRoutine, (int)&outStr);
}
#endif // ! _WRS_VXWORKS_MAJOR
#endif // vxWorks
#define P PRINTF_SIZE_T_PREFIX
@ -296,7 +338,7 @@ StreamBuffer StreamBuffer::expand(ssize_t start, ssize_t length) const
{
c = buffer[i];
if (c < 0x20 || c >= 0x7f)
result.print("\033[1m<%02x>\033[22m", c & 0xff);
result.print("\033[7m<%02x>\033[27m", c & 0xff);
else
result.append(c);
}
@ -316,7 +358,7 @@ dump() const
c = buffer[i];
if (offs && i == offs) result.append("\033[0m");
if (c < 0x20 || c >= 0x7f)
result.print("\033[1m<%02x>\033[22m", c & 0xff);
result.print("\033[7m<%02x>\033[27m", c & 0xff);
else
result.append(c);
if (i == offs+len-1) result.append("\033[47m");

View File

@ -1315,12 +1315,12 @@ normal_format:
break;
}
case StreamProtocolParser::skip:
// ignore next input byte
consumedInput++;
// ignore next input byte (if exists)
if (consumedInput < inputLine.length()) consumedInput++;
break;
case StreamProtocolParser::whitespace:
// any number of whitespace (including 0)
while (isspace(inputLine[consumedInput])) consumedInput++;
while (consumedInput < inputLine.length() && isspace(inputLine[consumedInput])) consumedInput++;
break;
case esc:
// escaped literal byte

View File

@ -831,7 +831,7 @@ initRecord(const char* filename, const char* protocol,
return ERROR;
}
debug("Stream::initRecord %s: initialized. %s\n",
name(), convert==2 ?
name(), convert == DO_NOT_CONVERT ?
"convert" : "don't convert");
return convert;
}
@ -843,6 +843,7 @@ process()
debug("Stream::process(%s)\n", name());
if (record->pact || record->scan == SCAN_IO_EVENT)
{
record->proc = 0;
if (status != NO_ALARM)
{
debug("Stream::process(%s) error status=%s (%d)\n",
@ -854,7 +855,7 @@ process()
return false;
}
debug("Stream::process(%s) ready. %s\n",
name(), convert==2 ?
name(), convert == DO_NOT_CONVERT ?
"convert" : "don't convert");
return true;
}
@ -870,9 +871,13 @@ process()
convert = OK;
if (!startProtocol(record->proc == 2 ? StreamCore::StartInit : StreamCore::StartNormal))
{
debug("Stream::process(%s): could not start %sprotocol, status=%d\n",
name(), record->proc==2 ? "@init " : "", status);
debug("Stream::process(%s): could not start %sprotocol, status=%s (%d)\n",
name(), record->proc == 2 ? "@init " : "",
status >= 0 && status < ALARM_NSTATUS ?
epicsAlarmConditionStrings[status] : "ERROR",
status);
(void) recGblSetSevr(record, status ? status : UDF_ALARM, INVALID_ALARM);
record->proc = 0;
return false;
}
debug("Stream::process(%s): protocol started\n", name());
@ -1083,7 +1088,7 @@ getFieldAddress(const char* fieldname, StreamBuffer& address)
// FIELD in this record or VAL in other record
StreamBuffer fullname;
fullname.print("%s.%s", name(), fieldname);
if (dbNameToAddr(fullname(), &dbaddr) != OK)
if (dbNameToAddr(fullname(), &dbaddr) != OK || strcmp(((dbFldDes*)dbaddr.pfldDes)->name, fieldname) != 0)
{
// VAL in other record
fullname.clear().print("%s.VAL", fieldname);

View File

@ -18,6 +18,9 @@
***************************************************************/
#include "StreamError.h"
#ifdef _WIN32
#include <windows.h>
#endif
#include <string.h>
#include <time.h>
#include <stdio.h>
@ -39,6 +42,18 @@ FILE *StreamDebugFile = NULL;
#ifdef _WIN32
#define localtime_r(timet,tm) localtime_s(tm,timet)
/* Enable ANSI colors in Windows console */
static int win_console_init() {
DWORD dwMode = 0;
HANDLE hCons = GetStdHandle(STD_ERROR_HANDLE);
GetConsoleMode(hCons, &dwMode);
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
SetConsoleMode(hCons, dwMode);
return 0;
}
static int s = win_console_init();
#endif
/* You can globally change the printTimestamp function
@ -115,4 +130,3 @@ print(const char* fmt, ...)
va_end(args);
return 1;
}

View File

@ -32,7 +32,6 @@ extern "C" {
#define STREAM_MAJOR 2
#define STREAM_MINOR 8
#define STREAM_PATCHLEVEL 0
#ifndef OK
#define OK 0

View File

@ -33,11 +33,12 @@ static long readData(dbCommon *record, format_t *format)
{
case DBF_ULONG:
case DBF_LONG:
case DBF_ENUM:
{
if (streamScanf(record, format, &val) == ERROR) return ERROR;
if (mbbo->mask) val &= mbbo->mask;
mbbo->rbv = val;
mbbo->rval = val;
if (mbbo->mask) val &= mbbo->mask;
if (mbbo->shft > 0) val >>= mbbo->shft;
/* read VAL or RBV? Look if any value is defined */
if (mbbo->sdef)
@ -56,17 +57,12 @@ static long readData(dbCommon *record, format_t *format)
mbbo->val = (epicsEnum16)val;
break;
}
case DBF_ENUM:
{
if (streamScanf(record, format, &val) == ERROR) return ERROR;
mbbo->val = (epicsEnum16)val;
break;
}
case DBF_STRING:
{
char buffer[sizeof(mbbo->zrst)];
if (streamScanfN(record, format, buffer, sizeof(buffer)) == ERROR)
return ERROR;
mbbo->val = 65535; /* initalize to unknown state*/
for (val = 0; val < 16; val++)
{
if (strcmp ((&mbbo->zrst)[val], buffer) == 0)
@ -75,6 +71,7 @@ static long readData(dbCommon *record, format_t *format)
break;
}
}
break;
}
default:
return ERROR;
@ -82,6 +79,15 @@ static long readData(dbCommon *record, format_t *format)
if (record->pact) return DO_NOT_CONVERT;
/* In @init handler, no processing, enforce monitor updates. */
monitor_mask = recGblResetAlarms(record);
if (mbbo->val > 15) {
recGblSetSevr(record, STATE_ALARM, mbbo->unsv);
} else {
recGblSetSevr(record, STATE_ALARM, (&(mbbo->zrsv))[mbbo->val]);
}
mbbo->lalm = mbbo->val;
if (mbbo->val != mbbo->lalm) {
if (!recGblSetSevr(record, COS_ALARM, mbbo->cosv)) mbbo->lalm = mbbo->val;
}
if (mbbo->mlst != mbbo->val)
{
monitor_mask |= (DBE_VALUE | DBE_LOG);
@ -110,39 +116,38 @@ static long writeData(dbCommon *record, format_t *format)
switch (format->type)
{
case DBF_ULONG:
case DBF_ENUM:
/* print VAL or RVAL ? */
val = mbbo->val;
if (mbbo->shft > 0) val <<= mbbo->shft;
if (mbbo->sdef) for (i=0; i<16; i++)
{
if ((&mbbo->zrvl)[i])
{
/* any values defined ? */
val = mbbo->rval;
if (mbbo->mask) val &= mbbo->mask;
break;
}
}
if (mbbo->mask) val &= mbbo->mask;
return streamPrintf(record, format, val);
case DBF_LONG:
{
/* print VAL or RVAL ? */
val = (epicsInt16)mbbo->val;
if (mbbo->shft > 0) val <<= mbbo->shft;
if (mbbo->sdef) for (i=0; i<16; i++)
{
if ((&mbbo->zrvl)[i])
{
/* any values defined ? */
val = (epicsInt32)mbbo->rval;
if (mbbo->mask) val &= mbbo->mask;
break;
}
}
if (mbbo->mask) val &= mbbo->mask;
return streamPrintf(record, format, val);
}
case DBF_ENUM:
{
return streamPrintf(record, format, mbbo->val);
}
case DBF_STRING:
{
if (mbbo->val >= 16) return ERROR;

View File

@ -1,9 +1,14 @@
if (@ARGV[0] == "-3.13") {
if (@ARGV[0] eq "--with-asyn") {
shift;
$asyn = 1;
}
if (@ARGV[0] eq "-3.13") {
shift;
} else {
print "variable(streamDebug, int)\n";
print "variable(streamError, int)\n";
print "registrar(streamRegistrar)\n";
if ($asyn) { print "registrar(AsynDriverInterfaceRegistrar)\n"; }
}
print "driver(stream)\n";
for (@ARGV) {

View File

@ -54,8 +54,6 @@ set debug 0
startioc
# Some formats give different results on 32 bit and 64 bit machines.
# This occurs when printing negative numbers with unsigned formats.
# This is normal. E.g. -1 HAS a different number of 1 bits.
# Specify the width field in the format if this is a problem.
put DZ:percent 1
@ -75,17 +73,9 @@ assure "12345 12345 012345 3039 003039 11000000111001 11000000111001 111001 !!..
put DZ:lo 2147483647
assure "2147483647 2147483647 2147483647 7fffffff FFFFFF 1111111111111111111111111111111 1111111111111111111111111111111 111111 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
put DZ:lo -1
if {$tcl_platform(machine) == "x86_64"} {
assure "-1 -1 -00001 ffffffffffffffff FFFFFF 1111111111111111111111111111111111111111111111111111111111111111 1111111111111111111111111111111111111111111111111111111111111111 111111 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
} else {
assure "-1 -1 -00001 ffffffff FFFFFF 11111111111111111111111111111111 11111111111111111111111111111111 111111 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
}
put DZ:lo -1234
if {$tcl_platform(machine) == "x86_64"} {
assure "-1234 -1234 -01234 fffffffffffffb2e FFFB2E 1111111111111111111111111111111111111111111111111111101100101110 1111111111111111111111111111111111111111111111111111101100101110 101110 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.!!..!.!!!. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.!!..!.!!!.\n"
} else {
assure "-1234 -1234 -01234 fffffb2e FFFB2E 11111111111111111111101100101110 11111111111111111111101100101110 101110 !!!!!!!!!!!!!!!!!!!!!.!!..!.!!!. !!!!!!!!!!!!!!!!!!!!!.!!..!.!!!.\n"
}
put DZ:lo 255
assure "255 255 000255 ff 0000FF 11111111 11111111 111111 !!!!!!!! !!!!!!!!\n"
put DZ:lo 65535