Compare commits
16 Commits
lift_axis_
...
home_zero
| Author | SHA1 | Date | |
|---|---|---|---|
| 6d46b3ac0c | |||
| ed0525e811 | |||
| 683fa2138f | |||
| 354e9d90fb | |||
| deea821e3f | |||
| 7a46788fd5 | |||
| 9e77eb585c | |||
| 7e1fc78f76 | |||
| 9e0d8a4322 | |||
| 3cccfe930c | |||
| 8860d0c59f | |||
| b6c38be113 | |||
| b14b50c25a | |||
| 477ffdbc0b | |||
| 0a23ec8f22 | |||
| 39098fd0d1 |
236
.clang-format
Normal file
236
.clang-format
Normal file
@@ -0,0 +1,236 @@
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignArrayOfStructures: None
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveBitFields:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveDeclarations:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveShortCaseStatements:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCaseColons: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments:
|
||||
Kind: Always
|
||||
OverEmptyLines: 0
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: MultiLine
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BitFieldColonSpacing: Both
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterExternBlock: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakAfterAttributes: Never
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakArrays: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeConceptDeclarations: Always
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInlineASMColon: OnlyMultiline
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IfMacros:
|
||||
- KJ_IF_MAYBE
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseBlocks: false
|
||||
IndentCaseLabels: false
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentRequiresClause: true
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertBraces: false
|
||||
InsertNewlineAtEOF: false
|
||||
InsertTrailingCommas: None
|
||||
IntegerLiteralSeparator:
|
||||
Binary: 0
|
||||
BinaryMinDigits: 0
|
||||
Decimal: 0
|
||||
DecimalMinDigits: 0
|
||||
Hex: 0
|
||||
HexMinDigits: 0
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
KeepEmptyLinesAtEOF: false
|
||||
LambdaBodyIndentation: Signature
|
||||
LineEnding: DeriveLF
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PackConstructorInitializers: BinPack
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakOpenParenthesis: 0
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Right
|
||||
PPIndentWidth: -1
|
||||
QualifierAlignment: Leave
|
||||
ReferenceAlignment: Pointer
|
||||
ReflowComments: true
|
||||
RemoveBracesLLVM: false
|
||||
RemoveParentheses: Leave
|
||||
RemoveSemicolon: false
|
||||
RequiresClausePosition: OwnLine
|
||||
RequiresExpressionIndentation: OuterScope
|
||||
SeparateDefinitionBlocks: Leave
|
||||
ShortNamespaceLines: 1
|
||||
SortIncludes: CaseSensitive
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: LexicographicNumeric
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeJsonColon: false
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: true
|
||||
AfterForeachMacros: true
|
||||
AfterFunctionDefinitionName: false
|
||||
AfterFunctionDeclarationName: false
|
||||
AfterIfMacros: true
|
||||
AfterOverloadedOperator: false
|
||||
AfterRequiresInClause: false
|
||||
AfterRequiresInExpression: false
|
||||
BeforeNonEmptyParentheses: false
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceBeforeSquareBrackets: false
|
||||
SpaceInEmptyBlock: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: Never
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParens: Never
|
||||
SpacesInParensOptions:
|
||||
InCStyleCasts: false
|
||||
InConditionalStatements: false
|
||||
InEmptyParentheses: false
|
||||
Other: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Latest
|
||||
StatementAttributeLikeMacros:
|
||||
- Q_EMIT
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
VerilogBreakBetweenInstancePorts: true
|
||||
WhitespaceSensitiveMacros:
|
||||
- BOOST_PP_STRINGIZE
|
||||
- CF_SWIFT_NAME
|
||||
- NS_SWIFT_NAME
|
||||
- PP_STRINGIZE
|
||||
- STRINGIZE
|
||||
...
|
||||
|
||||
21
.gitea/workflows/action.yaml
Normal file
21
.gitea/workflows/action.yaml
Normal file
@@ -0,0 +1,21 @@
|
||||
name: Test And Build
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
Lint:
|
||||
runs-on: linepics
|
||||
steps:
|
||||
- name: checkout repo
|
||||
uses: actions/checkout@v4
|
||||
- name: cppcheck
|
||||
run: cppcheck --std=c++17 --addon=cert --addon=misc --error-exitcode=1 sinqEPICSApp/src/*.cpp
|
||||
- name: formatting
|
||||
run: clang-format --style=file --Werror --dry-run sinqEPICSApp/src/*.cpp sinqEPICSApp/src/*.c sinqEPICSApp/src/*.h
|
||||
Build:
|
||||
runs-on: linepics
|
||||
steps:
|
||||
- name: checkout repo
|
||||
uses: actions/checkout@v4
|
||||
- run: |
|
||||
sed -i 's/ARCH_FILTER=.*/ARCH_FILTER=linux%/' Makefile.RHEL8
|
||||
make -f Makefile.RHEL8 install
|
||||
@@ -4,7 +4,7 @@ include /ioc/tools/driver.makefile
|
||||
MODULE=sinq
|
||||
BUILDCLASSES=Linux
|
||||
EPICS_VERSIONS=7.0.7
|
||||
ARCH_FILTER=RHEL%
|
||||
ARCH_FILTER=RHEL8%
|
||||
|
||||
# additional module dependencies
|
||||
REQUIRED+=SynApps
|
||||
@@ -12,13 +12,11 @@ REQUIRED+=stream
|
||||
REQUIRED+=scaler
|
||||
REQUIRED+=motorBase
|
||||
|
||||
# Release version
|
||||
LIBVERSION=2025
|
||||
|
||||
# DB files to include in the release
|
||||
TEMPLATES += sinqEPICSApp/Db/dimetix.db
|
||||
TEMPLATES += sinqEPICSApp/Db/slsvme.db
|
||||
TEMPLATES += sinqEPICSApp/Db/spsamor.db
|
||||
TEMPLATES += sinqEPICSApp/Db/el734.db
|
||||
|
||||
# DBD files to include in the release
|
||||
DBDS += sinqEPICSApp/src/sinq.dbd
|
||||
|
||||
@@ -38,3 +38,12 @@ Those political problems require a special development model:
|
||||
Take care of the sinqEPICsApp/src/sinq.dbd file. This is the one which differs mostly between
|
||||
amorsim and master branches.
|
||||
|
||||
# Formatting
|
||||
|
||||
Formatting is done via the [`.clang-format`](./.clang-format) file checked into
|
||||
the repository. One option to apply the formatting to a given file is via the
|
||||
command below.
|
||||
|
||||
```
|
||||
clang-format -i -style=file <file>
|
||||
```
|
||||
|
||||
34
sinqEPICSApp/Db/el734.db
Normal file
34
sinqEPICSApp/Db/el734.db
Normal file
@@ -0,0 +1,34 @@
|
||||
record(motor,"$(P)$(M)")
|
||||
{
|
||||
field(DESC,"$(DESC)")
|
||||
field(DTYP,"$(DTYP)")
|
||||
field(DIR,"$(DIR)")
|
||||
field(VELO,"$(VELO)")
|
||||
field(HVEL,"$(VELO)")
|
||||
field(VBAS,"$(VELO)")
|
||||
field(VMAX, "${VMAX}")
|
||||
field(ACCL,"$(ACCL)")
|
||||
field(BDST,"$(BDST)")
|
||||
field(BVEL,"$(BVEL)")
|
||||
field(BACC,"$(BACC)")
|
||||
field(OUT,"@asyn($(PORT),$(ADDR))")
|
||||
field(MRES,"$(MRES)")
|
||||
field(PREC,"$(PREC)")
|
||||
field(EGU,"$(EGU)")
|
||||
field(DHLM,"$(DHLM)")
|
||||
field(DLLM,"$(DLLM)")
|
||||
field(INIT,"$(INIT)")
|
||||
field(PINI, "NO")
|
||||
field(TWV,"1")
|
||||
field(RTRY,"0")
|
||||
}
|
||||
|
||||
# The message text
|
||||
record(waveform, "$(P)$(M)-MsgTxt") {
|
||||
field(DTYP, "asynOctetRead")
|
||||
field(INP, "@asyn($(PORT),$(N),1) MOTOR_MESSAGE_TEXT")
|
||||
field(FTVL, "CHAR")
|
||||
field(NELM, "80")
|
||||
field(SCAN, "I/O Intr")
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ January 2019
|
||||
#include "PhytronDriver.h"
|
||||
#include <epicsExport.h>
|
||||
|
||||
#define IDLEPOLL 60
|
||||
#define IDLEPOLL 5
|
||||
|
||||
/** Creates a new PhytronController object.
|
||||
* \param[in] portName The name of the asyn port that will be created for this driver
|
||||
@@ -56,7 +56,7 @@ January 2019
|
||||
* \param[in] numAxes The number of axes that this controller supports
|
||||
*/
|
||||
PhytronController::PhytronController(const char *portName, const char *PhytronPortName, const char *sel ,
|
||||
int encX, int encY)
|
||||
int encX, int encY, int ignoreLimitsX, int ignoreLimitsY)
|
||||
: SINQController(portName, PhytronPortName,2)
|
||||
{
|
||||
asynStatus status;
|
||||
@@ -82,8 +82,8 @@ PhytronController::PhytronController(const char *portName, const char *PhytronPo
|
||||
new PhytronDoseAxis(this, 1, encX);
|
||||
new PhytronDoseAxis(this, 2, encY);
|
||||
} else {
|
||||
new PhytronAxis(this, 1, encX);
|
||||
new PhytronAxis(this, 2, encY);
|
||||
new PhytronAxis(this, 1, encX, ignoreLimitsX);
|
||||
new PhytronAxis(this, 2, encY, ignoreLimitsY);
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ PhytronController::PhytronController(const char *portName, const char *PhytronPo
|
||||
|
||||
PhytronDoseController::PhytronDoseController(const char *portName, const char *PhytronPortName, const char *sel ,
|
||||
int encX, int encY)
|
||||
: PhytronController(portName, PhytronPortName, sel, encX, encY)
|
||||
: PhytronController(portName, PhytronPortName, sel, encX, encY, 0, 0)
|
||||
{
|
||||
new PhytronDoseAxis(this, 1, encX);
|
||||
new PhytronDoseAxis(this, 2, encY);
|
||||
@@ -106,9 +106,9 @@ PhytronDoseController::PhytronDoseController(const char *portName, const char *P
|
||||
* \param[in] numAxes The number of axes that this controller supports
|
||||
*/
|
||||
extern "C" int PhytronCreateController(const char *portName, const char *PhytronPortName, const char *selector,
|
||||
int encX, int encY)
|
||||
int encX, int encY, int ignoreLimitsX, int ignoreLimitsY)
|
||||
{
|
||||
new PhytronController(portName, PhytronPortName,selector, encX, encY);
|
||||
new PhytronController(portName, PhytronPortName,selector, encX, encY, ignoreLimitsX, ignoreLimitsY);
|
||||
return(asynSuccess);
|
||||
}
|
||||
|
||||
@@ -178,10 +178,10 @@ PhytronDoseAxis* PhytronDoseController::getAxis(int axisNo)
|
||||
|
||||
asynStatus PhytronController::transactController(int axisNo,char command[COMLEN], char reply[COMLEN])
|
||||
{
|
||||
asynStatus status;
|
||||
size_t in, out;
|
||||
int reason;
|
||||
char myReply[COMLEN+10], myCommand[COMLEN+10], *pPtr;
|
||||
asynStatus status = asynSuccess;
|
||||
size_t in = 0, out = 0;
|
||||
int reason = 0;
|
||||
char myReply[COMLEN+10] = {0}, myCommand[COMLEN+10] = {0}, *pPtr = {0};
|
||||
SINQAxis *axis = getAxis(axisNo);
|
||||
|
||||
|
||||
@@ -237,11 +237,12 @@ asynStatus PhytronController::transactController(int axisNo,char command[COMLEN]
|
||||
*
|
||||
* Initializes register numbers, etc.
|
||||
*/
|
||||
PhytronAxis::PhytronAxis(PhytronController *pC, int axisNo, int enc)
|
||||
PhytronAxis::PhytronAxis(PhytronController *pC, int axisNo, int enc, int ignoreLimits)
|
||||
: SINQAxis(pC, axisNo),
|
||||
pC_(pC)
|
||||
{
|
||||
encoder = enc;
|
||||
ignore_limits = ignoreLimits;
|
||||
if(axisNo == 1){
|
||||
phytronChar = 'X';
|
||||
} else {
|
||||
@@ -250,6 +251,8 @@ PhytronAxis::PhytronAxis(PhytronController *pC, int axisNo, int enc)
|
||||
haveBrake = 0;
|
||||
brakeIO = -1;
|
||||
next_poll = -1;
|
||||
homing = 0;
|
||||
homing_direction = 0;
|
||||
}
|
||||
|
||||
int PhytronAxis::setBrake(int brakeNO)
|
||||
@@ -434,8 +437,9 @@ asynStatus PhytronAxis::setPosition(double position)
|
||||
|
||||
errlogPrintf("PhytronAxis::setPosition called with %lf\n", position);
|
||||
|
||||
sprintf(command, "%s%cP22S%f", pC_->selector,phytronChar, position/1000.);
|
||||
status = pC_->transactController(axisNo_,command,reply);
|
||||
// writing encoder register is wrong
|
||||
//sprintf(command, "%s%cP22S%f", pC_->selector,phytronChar, position/1000.);
|
||||
//status = pC_->transactController(axisNo_,command,reply);
|
||||
sprintf(command, "%s%cP20S%f", pC_->selector,phytronChar, position/1000.);
|
||||
status = pC_->transactController(axisNo_,command,reply);
|
||||
next_poll = -1;
|
||||
@@ -465,8 +469,6 @@ asynStatus PhytronAxis::poll(bool *moving)
|
||||
{
|
||||
asynStatus comStatus = asynSuccess;
|
||||
char command[COMLEN], reply[COMLEN];
|
||||
double lowlim;
|
||||
|
||||
|
||||
// protect against excessive polling
|
||||
if(time(NULL) < next_poll){
|
||||
@@ -536,13 +538,7 @@ asynStatus PhytronAxis::poll(bool *moving)
|
||||
|
||||
if(!*moving) {
|
||||
if(homing){
|
||||
if(homing_direction) {
|
||||
pC_->getDoubleParam(axisNo_,pC_->motorHighLimit_,&lowlim);
|
||||
} else {
|
||||
pC_->getDoubleParam(axisNo_,pC_->motorLowLimit_,&lowlim);
|
||||
}
|
||||
setPosition(lowlim);
|
||||
setIntegerParam(pC_->motorStatusAtHome_, true);
|
||||
setIntegerParam(pC_->motorStatusAtHome_, true);
|
||||
} else {
|
||||
/*
|
||||
check limits and errors, upper
|
||||
@@ -554,7 +550,7 @@ asynStatus PhytronAxis::poll(bool *moving)
|
||||
updateMsgTxtFromDriver("No connection to phytron controller");
|
||||
goto skip;
|
||||
}
|
||||
if(strstr(reply,"ACKE") != NULL){
|
||||
if(strstr(reply,"ACKE") != NULL && ignore_limits == 0){
|
||||
setIntegerParam(pC_->motorStatusHighLimit_, true);
|
||||
updateMsgTxtFromDriver("Hit High Limit");
|
||||
comStatus = asynError;
|
||||
@@ -573,7 +569,7 @@ asynStatus PhytronAxis::poll(bool *moving)
|
||||
updateMsgTxtFromDriver("No connection to phytron controller");
|
||||
goto skip;
|
||||
}
|
||||
if(strstr(reply,"ACKE") != NULL){
|
||||
if(strstr(reply,"ACKE") != NULL && ignore_limits == 0){
|
||||
setIntegerParam(pC_->motorStatusLowLimit_, true);
|
||||
updateMsgTxtFromDriver("Low Limit Hit");
|
||||
comStatus = asynError;
|
||||
@@ -614,7 +610,7 @@ asynStatus PhytronAxis::poll(bool *moving)
|
||||
*/
|
||||
|
||||
PhytronDoseAxis::PhytronDoseAxis(PhytronController *pC, int axisNo, int enc)
|
||||
: PhytronAxis(pC, axisNo, enc)
|
||||
: PhytronAxis(pC, axisNo, enc, 0)
|
||||
{
|
||||
if(axisNo == 1){
|
||||
doseChar = '3';
|
||||
@@ -718,15 +714,19 @@ static const iocshArg PhytronCreateControllerArg1 = {"Phytron port name", iocshA
|
||||
static const iocshArg PhytronCreateControllerArg2 = {"Phytron Selector", iocshArgString};
|
||||
static const iocshArg PhytronCreateControllerArg3 = {"EncoderX", iocshArgInt};
|
||||
static const iocshArg PhytronCreateControllerArg4 = {"EncoderY", iocshArgInt};
|
||||
static const iocshArg PhytronCreateControllerArg5 = {"IgnoreLimitsX", iocshArgInt};
|
||||
static const iocshArg PhytronCreateControllerArg6 = {"IgnoreLimitsY", iocshArgInt};
|
||||
static const iocshArg * const PhytronCreateControllerArgs[] = {&PhytronCreateControllerArg0,
|
||||
&PhytronCreateControllerArg1,
|
||||
&PhytronCreateControllerArg2,
|
||||
&PhytronCreateControllerArg3,
|
||||
&PhytronCreateControllerArg4};
|
||||
static const iocshFuncDef PhytronCreateControllerDef = {"PhytronCreateController", 5, PhytronCreateControllerArgs};
|
||||
&PhytronCreateControllerArg2,
|
||||
&PhytronCreateControllerArg3,
|
||||
&PhytronCreateControllerArg4,
|
||||
&PhytronCreateControllerArg5,
|
||||
&PhytronCreateControllerArg6};
|
||||
static const iocshFuncDef PhytronCreateControllerDef = {"PhytronCreateController", 7, PhytronCreateControllerArgs};
|
||||
static void PhytronCreateContollerCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
PhytronCreateController(args[0].sval, args[1].sval, args[2].sval, args[3].ival,args[4].ival);
|
||||
PhytronCreateController(args[0].sval, args[1].sval, args[2].sval, args[3].ival,args[4].ival, args[5].ival, args[6].ival);
|
||||
}
|
||||
|
||||
static const iocshArg PhytronDoseCreateControllerArg0 = {"Port name", iocshArgString};
|
||||
|
||||
@@ -30,7 +30,7 @@ class PhytronAxis : public SINQAxis
|
||||
{
|
||||
public:
|
||||
/* These are the methods we override from the base class */
|
||||
PhytronAxis(class PhytronController *pC, int axis, int enc);
|
||||
PhytronAxis(class PhytronController *pC, int axis, int enc, int ignoreLimits);
|
||||
void report(FILE *fp, int level);
|
||||
asynStatus move(double position, int relative, double min_velocity, double max_velocity, double acceleration);
|
||||
asynStatus moveVelocity(double min_velocity, double max_velocity, double acceleration);
|
||||
@@ -50,6 +50,7 @@ protected:
|
||||
int homing_direction; /*1 forward, 0 backwards */
|
||||
time_t next_poll;
|
||||
int encoder;
|
||||
int ignore_limits;
|
||||
int haveBrake;
|
||||
int brakeIO;
|
||||
|
||||
@@ -74,7 +75,7 @@ PhytronDoseController *pC_;
|
||||
class PhytronController : public SINQController {
|
||||
public:
|
||||
PhytronController(const char *portName, const char *PhytronPortName, const char *selector,
|
||||
int encX, int encY);
|
||||
int encX, int encY, int ignoreLimitsX, int ignoreLimitsY);
|
||||
|
||||
void report(FILE *fp, int level);
|
||||
PhytronAxis* getAxis(asynUser *pasynUser);
|
||||
|
||||
@@ -114,7 +114,7 @@ typedef struct {
|
||||
unsigned int dbInit;
|
||||
}EL737priv;
|
||||
|
||||
static void dummyAsynCallback([[maybe_unused]] asynUser *pasynUser)
|
||||
static void dummyAsynCallback(asynUser *pasynUser)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
213
utils/decodeMasterMACStatusR10.py
Executable file
213
utils/decodeMasterMACStatusR10.py
Executable file
@@ -0,0 +1,213 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# List of tuples which encodes the states given in the file description.
|
||||
# Index first with the bit index, then with the bit value
|
||||
interpretation = [
|
||||
("Not ready to be switched on", "Ready to be switched on"), # Bit 0
|
||||
("Not switched on", "Switched on"), # Bit 1
|
||||
("Disabled", "Enabled"), # Bit 2
|
||||
("Ok", "Fault condition set"), # Bit 3
|
||||
("Motor supply voltage absent ", "Motor supply voltage present"), # Bit 4
|
||||
("Motor performs quick stop", "Ok"), # Bit 5
|
||||
("Switch on enabled", "Switch on disabled"), # Bit 6
|
||||
("Ok", "RWarning: Movement function was called while motor is still moving. The function call is ignored"), # Bit 7
|
||||
("Motor is idle", "Motor is currently moving"), # Bit 8
|
||||
("Motor does not execute command messages (local mode)", "Motor does execute command messages (remote mode)"), # Bit 9
|
||||
("Target not reached", "Target reached"), # Bit 10
|
||||
("Ok", "Internal limit active"), # Bit 11
|
||||
("Not specified", "Not specified"), # Bit 12
|
||||
("Not specified", "Not specified"), # Bit 13
|
||||
("No event set or event has not occurred yet", "Set event has occurred"), # Bit 14
|
||||
("Axis off (power disabled)", "Axis on (power enabled)"), # Bit 15
|
||||
]
|
||||
|
||||
def decode(value, big_endian: bool = False):
|
||||
|
||||
interpreted = []
|
||||
|
||||
bit_list = [(value >> shift_ind) & 1
|
||||
for shift_ind in range(value.bit_length())] # little endian
|
||||
|
||||
if big_endian:
|
||||
bit_list.reverse() # big endian
|
||||
|
||||
for (bit, interpretations) in zip(bit_list, interpretation):
|
||||
interpreted.append(interpretations[bit])
|
||||
return (bit_list, interpreted)
|
||||
|
||||
def print_decoded(bit_list, interpreted):
|
||||
for (idx, (bit_value, msg)) in enumerate(zip(bit_list, interpreted)):
|
||||
print(f"Bit {idx} = {bit_value}: {msg}")
|
||||
|
||||
def interactive():
|
||||
|
||||
# Imported here, because curses is not available in Windows. Using the
|
||||
# interactive mode therefore fails on Windows, but at least the single
|
||||
# command mode can be used (which would not be possible if we would import
|
||||
# curses at the top level)
|
||||
import curses
|
||||
|
||||
stdscr = curses.initscr()
|
||||
curses.noecho()
|
||||
curses.cbreak()
|
||||
stdscr.keypad(True)
|
||||
stdscr.scrollok(True)
|
||||
|
||||
stdscr.addstr(">> ")
|
||||
stdscr.refresh()
|
||||
|
||||
history = [""]
|
||||
ptr = len(history) - 1
|
||||
|
||||
while True:
|
||||
c = stdscr.getch()
|
||||
if c == curses.KEY_RIGHT:
|
||||
(y, x) = stdscr.getyx()
|
||||
if x < len(history[ptr]) + 3:
|
||||
stdscr.move(y, x+1)
|
||||
stdscr.refresh()
|
||||
elif c == curses.KEY_LEFT:
|
||||
(y, x) = stdscr.getyx()
|
||||
if x > 3:
|
||||
stdscr.move(y, x-1)
|
||||
stdscr.refresh()
|
||||
elif c == curses.KEY_UP:
|
||||
if ptr > 0:
|
||||
ptr -= 1
|
||||
stdscr.addch("\r")
|
||||
stdscr.clrtoeol()
|
||||
stdscr.addstr(">> " + history[ptr])
|
||||
elif c == curses.KEY_DOWN:
|
||||
if ptr < len(history) - 1:
|
||||
ptr += 1
|
||||
stdscr.addch("\r")
|
||||
stdscr.clrtoeol()
|
||||
stdscr.addstr(">> " + history[ptr])
|
||||
elif c == curses.KEY_ENTER or c == ord('\n') or c == ord('\r'):
|
||||
if history[ptr] == 'quit':
|
||||
break
|
||||
|
||||
# because of arrow keys move back to the end of the line
|
||||
(y, x) = stdscr.getyx()
|
||||
stdscr.move(y, 3+len(history[ptr]))
|
||||
|
||||
if history[ptr]:
|
||||
result = interpret_inputs(history[ptr].split())
|
||||
if result is None:
|
||||
stdscr.addstr(f"\nBAD INPUT: Expected input of 'value [big_endian]', where 'value' is an int or a float and 'big_endian' is an optional boolean argument.")
|
||||
else:
|
||||
(arg, big_endian) = result
|
||||
(bit_list, interpreted) = decode(arg, big_endian)
|
||||
for (idx, (bit_value, msg)) in enumerate(zip(bit_list, interpreted)):
|
||||
stdscr.addstr(f"\nBit {idx} = {bit_value}: {msg}")
|
||||
stdscr.refresh()
|
||||
|
||||
if ptr == len(history) - 1 and history[ptr] != "":
|
||||
history += [""]
|
||||
else:
|
||||
history[-1] = ""
|
||||
ptr = len(history) - 1
|
||||
|
||||
stdscr.addstr("\n>> ")
|
||||
stdscr.refresh()
|
||||
|
||||
else:
|
||||
if ptr < len(history) - 1: # Modifying previous input
|
||||
if len(history[-1]) == 0:
|
||||
history[-1] = history[ptr]
|
||||
ptr = len(history) - 1
|
||||
|
||||
else:
|
||||
history += [history[ptr]]
|
||||
ptr = len(history) - 1
|
||||
|
||||
if c == curses.KEY_BACKSPACE:
|
||||
if len(history[ptr]) == 0:
|
||||
continue
|
||||
(y, x) = stdscr.getyx()
|
||||
history[ptr] = history[ptr][0:x-4] + history[ptr][x-3:]
|
||||
stdscr.addch("\r")
|
||||
stdscr.clrtoeol()
|
||||
stdscr.addstr(">> " + history[ptr])
|
||||
stdscr.move(y, x-1)
|
||||
stdscr.refresh()
|
||||
|
||||
else:
|
||||
(y, x) = stdscr.getyx()
|
||||
history[ptr] = history[ptr][0:x-3] + chr(c) + history[ptr][x-3:]
|
||||
stdscr.addch("\r")
|
||||
stdscr.clrtoeol()
|
||||
stdscr.addstr(">> " + history[ptr])
|
||||
stdscr.move(y, x+1)
|
||||
stdscr.refresh()
|
||||
|
||||
# to quit
|
||||
curses.nocbreak()
|
||||
stdscr.keypad(False)
|
||||
curses.echo()
|
||||
curses.endwin()
|
||||
|
||||
def interpret_inputs(inputs):
|
||||
|
||||
number = None
|
||||
big_endian = False
|
||||
try:
|
||||
number = int(float(inputs[0]))
|
||||
if len(inputs) > 1:
|
||||
second_arg = inputs[1]
|
||||
if second_arg == "True" or second_arg == "true":
|
||||
big_endian = True
|
||||
elif second_arg == "False" or second_arg == "false":
|
||||
big_endian = False
|
||||
else:
|
||||
big_endian = bool(int(second_arg))
|
||||
return (number, big_endian)
|
||||
except:
|
||||
return None
|
||||
|
||||
if __name__ == "__main__":
|
||||
from sys import argv
|
||||
|
||||
if len(argv) == 1:
|
||||
# Start interactive mode
|
||||
interactive()
|
||||
else:
|
||||
|
||||
result = interpret_inputs(argv[1:])
|
||||
|
||||
if result is None:
|
||||
print("""
|
||||
Decode R10 message of MasterMACs
|
||||
------------------
|
||||
|
||||
MasterMACs returns its status message (R10) as a floating-point number.
|
||||
The bits of this float encode different states. These states are stored
|
||||
in the interpretation variable.
|
||||
|
||||
This script can be used in two different ways:
|
||||
|
||||
Option 1: Single Command
|
||||
------------------------
|
||||
|
||||
Usage: decodeMasterMACStatusR10.py value [big_endian]
|
||||
|
||||
'value' is the return value of a R10 command. This value is interpreted
|
||||
bit-wise and the result is printed out. The optional second argument can
|
||||
be used to specify whether the input value needs to be interpreted as
|
||||
little or big endian. Default is False.
|
||||
|
||||
Option 2: CLI Mode
|
||||
------------------
|
||||
|
||||
Usage: decodeMasterMACStatusR10.py
|
||||
|
||||
A prompt will be opened. Type in the return value of a R10 command, hit
|
||||
enter and the interpretation will be printed in the prompt. After that,
|
||||
the next value can be typed in. Type 'quit' to close the prompt.
|
||||
""")
|
||||
else:
|
||||
print("Motor status")
|
||||
print("============")
|
||||
(arg, big_endian) = result
|
||||
(bit_list, interpreted) = decode(arg, big_endian)
|
||||
print_decoded(bit_list, interpreted)
|
||||
@@ -64,6 +64,7 @@ if __name__ == "__main__":
|
||||
curses.noecho()
|
||||
curses.cbreak()
|
||||
stdscr.keypad(True)
|
||||
stdscr.scrollok(True)
|
||||
|
||||
stdscr.addstr(">> ")
|
||||
stdscr.refresh()
|
||||
|
||||
Reference in New Issue
Block a user