8 Commits
1.1.0 ... 1.2.1

Author SHA1 Message Date
ab596ded48 Lift and angle axis now move simultaneously
Some checks failed
Test And Build / Lint (push) Failing after 3s
Test And Build / Build (push) Successful in 15s
Fixed a bug which caused the axes not to move in parallel, but after
each other.
2025-08-14 08:05:35 +02:00
bfd565aabd Hide visibility of classes
All checks were successful
Test And Build / Lint (push) Successful in 3s
Test And Build / Build (push) Successful in 15s
2025-08-12 09:20:25 +02:00
0005775c9d Updated turboPmac to 1.4.0 2025-08-12 09:18:37 +02:00
e5f9e33c66 Test to hide visibility 2025-08-12 08:09:36 +02:00
46b839cc66 Removed symbol visibility for turboPmac 2025-08-11 16:48:18 +02:00
38b4ba9843 Fixed record setup in detectorTower.db
All checks were successful
Test And Build / Lint (push) Successful in 4s
Test And Build / Build (push) Successful in 16s
2025-07-21 17:04:09 +02:00
8eba612524 UDF state is not shown during initialization anymore
All checks were successful
Test And Build / Lint (push) Successful in 4s
Test And Build / Build (push) Successful in 15s
These changes process the AdjustOrigin record during initialization to
make sure its .STAT field does not show "UDF" anymore before the first
processing. The gate record makes sure that no command is send to the
underlying hardware during initial processing.
2025-07-09 11:43:31 +02:00
9565198424 adds gitea action
All checks were successful
Test And Build / Lint (push) Successful in 3s
Test And Build / Build (push) Successful in 14s
2025-07-04 14:40:11 +02:00
12 changed files with 111 additions and 113 deletions

View File

@@ -0,0 +1,30 @@
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 src/*.cpp
- name: formatting
run: clang-format --style=file --Werror --dry-run src/*.cpp src/*.h
Build:
runs-on: linepics
steps:
- name: checkout repo
uses: actions/checkout@v4
with:
submodules: 'true'
- run: |
pushd turboPmac
sed -i 's/ARCH_FILTER=.*/ARCH_FILTER=linux%/' Makefile
echo -e "\nIGNORE_SUBMODULES += sinqmotor" >> Makefile
make install
popd
- run: |
sed -i 's/ARCH_FILTER=.*/ARCH_FILTER=linux%/' Makefile
echo -e "\nIGNORE_SUBMODULES += turboPmac" >> Makefile
make install

View File

@@ -1,58 +0,0 @@
default:
image: docker.psi.ch:5000/sinqdev/sinqepics:latest
stages:
- lint
- build
- test
cppcheck:
stage: lint
script:
- cppcheck --std=c++17 --addon=cert --addon=misc --error-exitcode=1 src/*.cpp
artifacts:
expire_in: 1 week
tags:
- sinq
formatting:
stage: lint
script:
- clang-format --style=file --Werror --dry-run src/*.cpp
artifacts:
expire_in: 1 week
tags:
- sinq
# clangtidy:
# stage: lint
# script:
# - curl https://docker.psi.ch:5000/v2/_catalog
# # - dnf update -y
# # - dnf install -y clang-tools-extra
# # - clang-tidy sinqEPICSApp/src/*.cpp sinqEPICSApp/src/*.c sinqEPICSApp/src/*.h -checks=cppcoreguidelines-*,cert-*
# # tags:
# # - sinq
build_module:
stage: build
script:
- export TURBOPMAC_VERSION="$(grep 'turboPmac_VERSION=' Makefile | cut -d= -f2)"
- git clone --depth 1 --branch "${TURBOPMAC_VERSION}" https://gitlab-ci-token:${CI_JOB_TOKEN}@git.psi.ch/sinq-epics-modules/sinqmotor.git
- pushd sinqmotor
- sed -i 's/ARCH_FILTER=.*/ARCH_FILTER=linux%/' Makefile
- echo "LIBVERSION=${TURBOPMAC_VERSION}" >> Makefile
- make install
- popd
- sed -i 's/ARCH_FILTER=.*/ARCH_FILTER=linux%/' Makefile
- echo "LIBVERSION=${CI_COMMIT_TAG:-0.0.1}" >> Makefile
- make install
- cp -rT "/ioc/modules/detectorTower/$(ls -U /ioc/modules/detectorTower/ | head -1)" "./detectorTower-${CI_COMMIT_TAG:-$CI_COMMIT_SHORT_SHA}"
artifacts:
name: "detectorTower-${CI_COMMIT_TAG:-$CI_COMMIT_SHORT_SHA}"
paths:
- "detectorTower-${CI_COMMIT_TAG:-$CI_COMMIT_SHORT_SHA}/*"
expire_in: 1 week
when: always
tags:
- sinq

View File

@@ -42,4 +42,4 @@ DBDS += turboPmac/sinqMotor/src/sinqMotor.dbd
DBDS += turboPmac/src/turboPmac.dbd
DBDS += src/detectorTower.dbd
USR_CFLAGS += -Wall -Wextra -Weffc++ -Wunused-result -Wextra -Werror # -Wpedantic // Does not work because EPICS macros trigger warnings
USR_CFLAGS += -Wall -Wextra -Weffc++ -Wunused-result -Wextra -Werror -fvisibility=hidden # -Wpedantic // Does not work because EPICS macros trigger warnings

View File

@@ -58,7 +58,6 @@ record(ai, "$(INSTR)$(M):Origin") {
field(INP, "@asyn($(CONTROLLER),$(AXIS)) MOTOR_ORIGIN")
field(SCAN, "I/O Intr")
field(PINI, "NO")
field(VAL, "0")
}
# Shift the origin of the corresponding axis by the given value. The axis will move to this
@@ -69,16 +68,28 @@ record(ao, "$(INSTR)$(M):AdjustOrigin") {
field(PINI, "NO")
field(FLNK, "$(INSTR)$(M):ResetAO")
field(VAL, "0")
field(UDF, "0")
field(SCAN, "Passive")
}
# Only forward nonzero inputs for the origin adjustment
record(calcout, "$(INSTR)$(M):GateOrigin") {
field(CALC, "A!=0?A:0")
field(INPA, "$(INSTR)$(M):AdjustOrigin")
field(OUT, "$(INSTR)$(M):WriteAO.VAL PP") # Forward the value to the driver
field(PINI, "NO")
field(SCAN, "Passive")
}
# Reset the PV $(INSTR)$(M):AdjustOrigin to zero after it has been written to and
# forward the value to $(INSTR)$(M):WriteAO which does the actual writing.
record(seq, "$(INSTR)$(M):ResetAO") {
field(DESC, "Write value to hardware then reset to 0")
field(DOL1, "$(INSTR)$(M):AdjustOrigin")
field(LNK1, "$(INSTR)$(M):WriteAO.VAL PP") # Perform write to hardware
field(DOL1, "1") # Dummy value which is only here to trigger processing of LNK1
field(LNK1, "$(INSTR)$(M):GateOrigin.PROC PP")
field(DOL2, "0.0")
field(LNK2, "$(INSTR)$(M):AdjustOrigin.VAL PP") # Reset to zero
field(UDF, "0")
}
# This record forwards the adjustment of the origin to the asyn driver.

View File

@@ -34,17 +34,16 @@ static void deferredMovementCollectorLoop(void *drvPvt) {
detectorTowerAngleAxis *axis = (detectorTowerAngleAxis *)drvPvt;
while (1) {
if (axis->receivedTarget_) {
// Wait for 100 ms and then start the movement with the information
// available
axis->startingDeferredMovement_ = true;
// Wait for the time span defined in deferredMovementWait_ and then
// start the movement with the information available
epicsThreadSleep(axis->deferredMovementWait_);
axis->startCombinedMove();
// After the movement command has been send, reset the flag
axis->receivedTarget_ = false;
}
// Limit this loop to an idle frequency of 1 kHz
epicsThreadSleep(0.001);
// Limit this loop to an idle frequency of 10 kHz
epicsThreadSleep(0.01);
}
}
@@ -76,11 +75,10 @@ detectorTowerAngleAxis::detectorTowerAngleAxis(detectorTowerController *pC,
}
// Initialize all member variables
// Assumed to be not ready by default, this is overwritten in the next poll
error_ = 0;
waitingForStart_ = false;
receivedTarget_ = false;
startingDeferredMovement_ = false;
deferredMovementWait_ = 0.1; // seconds
deferredMovementWait_ = 0.5; // seconds
// Will be populated in the init() method
beamRadius_ = 0.0;
@@ -199,7 +197,7 @@ asynStatus detectorTowerAngleAxis::doMove(double position, int relative,
// started to the defined target position.
setTargetPosition(position * motorRecResolution);
receivedTarget_ = true;
waitingForStart_ = true;
return asynSuccess;
}
@@ -237,7 +235,6 @@ asynStatus detectorTowerAngleAxis::startCombinedMove() {
setAxisParamChecked(this, motorStatusProblem, true);
callParamCallbacks();
startingDeferredMovement_ = false;
return asynError;
}
@@ -293,9 +290,9 @@ asynStatus detectorTowerAngleAxis::stop(double acceleration) {
}
// Reset the deferred movement flags
startingDeferredMovement_ = false;
deferredMovementWait_ = false;
receivedTarget_ = false;
waitingForStart_ = false;
liftAxis()->waitingForStart_ = false;
return status;
}
@@ -422,8 +419,9 @@ asynStatus detectorTowerAngleAxis::doReset() {
getAxisParamChecked(this, positionStateRBV, &positionState);
// Reset the deferred movement flags
startingDeferredMovement_ = false;
deferredMovementWait_ = false;
receivedTarget_ = false;
waitingForStart_ = false;
liftAxis()->waitingForStart_ = false;
/*
Check which action should be performed:
@@ -552,11 +550,12 @@ static void configDetectorTowerCreateAxisCallFunc(const iocshArgBuf *args) {
// =============================================================================
/**
* @brief Set the setDeferredMovementWait (FFI implementation)
* @brief Set the setDeferredMovementWait time (FFI implementation)
*
* @param portName Name of the controller
* @param axisNo Axis number
* @param scaleMovTimeout Scaling factor (in seconds)
* @param deferredMovementWait Time (in seconds) the driver waits to collect
* all movement commands from the different axes
* @return asynStatus
*/
asynStatus setDeferredMovementWait(const char *portName, int axisNo,

View File

@@ -3,7 +3,7 @@
#include "detectorTowerController.h"
#include "turboPmacAxis.h"
class detectorTowerAngleAxis : public turboPmacAxis {
class HIDDEN detectorTowerAngleAxis : public turboPmacAxis {
public:
/**
* @brief Construct a new detectorTowerAngleAxis
@@ -136,15 +136,15 @@ class detectorTowerAngleAxis : public turboPmacAxis {
*/
detectorTowerSupportAxis *supportAxis() { return supportAxis_; }
/**
* @brief Return a pointer to the axis controller
*/
virtual detectorTowerController *pController() override { return pC_; };
// If true, either this axis or one of the detectorTowerLiftAxis
// attached to it received a movement command.
bool receivedTarget_;
// If set to true, the virtual axis is about to start a deferred movement
// (but is currently still collecting movement commands from its component
// axes)
bool startingDeferredMovement_;
/*
The collector cycle waits until this time in seconds has passed before
starting a deferred movement
@@ -157,10 +157,9 @@ class detectorTowerAngleAxis : public turboPmacAxis {
*/
int error_;
/**
* @brief Return a pointer to the axis controller
*/
virtual detectorTowerController *pController() override { return pC_; };
// True, if this axis has received a move command and the driver is
// currently starting a deferred movement.
bool waitingForStart_;
protected:
detectorTowerController *pC_;

View File

@@ -418,15 +418,14 @@ asynStatus detectorTowerController::pollDetectorAxes(
// Check if the tower is moving
if (notInPosition == 1 || positionState > 2) {
// By now, the controller has actually started the movement
angleAxis->startingDeferredMovement_ = false;
*moving = true;
// Since the tower is now moving, the axis by definition do not wait for
// movement start anymore.
liftAxis->waitingForStart_ = false;
angleAxis->waitingForStart_ = false;
} else {
if (angleAxis->startingDeferredMovement_) {
*moving = true;
} else {
*moving = false;
}
*moving = false;
}
// Calculate the lift position /w consideration of the angle
@@ -809,14 +808,26 @@ asynStatus detectorTowerController::pollDetectorAxes(
setAxisParamChecked(liftAxis, motorEnableRBV, true);
setAxisParamChecked(supportAxis, motorEnableRBV, true);
// Are the axes currently moving?
setAxisParamChecked(angleAxis, motorStatusMoving, *moving);
setAxisParamChecked(liftAxis, motorStatusMoving, *moving);
setAxisParamChecked(supportAxis, motorStatusMoving, *moving);
// If the axis is starting a movement, mark it as moving. Otherwise use the
// moving parameter.
if (angleAxis->waitingForStart_) {
setAxisParamChecked(angleAxis, motorStatusMoving, true);
setAxisParamChecked(angleAxis, motorStatusDone, false);
} else {
setAxisParamChecked(angleAxis, motorStatusMoving, *moving);
setAxisParamChecked(angleAxis, motorStatusDone, !(*moving));
}
// Is the axis movement done?
setAxisParamChecked(angleAxis, motorStatusDone, !(*moving));
setAxisParamChecked(liftAxis, motorStatusDone, !(*moving));
if (liftAxis->waitingForStart_) {
setAxisParamChecked(liftAxis, motorStatusMoving, true);
setAxisParamChecked(liftAxis, motorStatusDone, false);
} else {
setAxisParamChecked(liftAxis, motorStatusMoving, *moving);
setAxisParamChecked(liftAxis, motorStatusDone, !(*moving));
}
// Support axis status is solely deduced from system movement state
setAxisParamChecked(supportAxis, motorStatusMoving, *moving);
setAxisParamChecked(supportAxis, motorStatusDone, !(*moving));
// In which direction are the axes currently moving?

View File

@@ -13,11 +13,11 @@
// Forward declaration of the axis classes to resolve the cyclic dependency
// between the controller and the axis .h-file. See
// https://en.cppreference.com/w/cpp/language/class.
class detectorTowerAngleAxis;
class detectorTowerLiftAxis;
class detectorTowerSupportAxis;
class HIDDEN detectorTowerAngleAxis;
class HIDDEN detectorTowerLiftAxis;
class HIDDEN detectorTowerSupportAxis;
class detectorTowerController : public turboPmacController {
class HIDDEN detectorTowerController : public turboPmacController {
public:
/**

View File

@@ -70,6 +70,9 @@ detectorTowerLiftAxis::detectorTowerLiftAxis(detectorTowerController *pC,
angleAxis_ = angleAxis;
angleAxis->liftAxis_ = this;
// Initialize the flag to false
waitingForStart_ = false;
}
detectorTowerLiftAxis::~detectorTowerLiftAxis(void) {
@@ -157,7 +160,6 @@ asynStatus detectorTowerLiftAxis::doMove(double position, int relative,
double min_velocity,
double max_velocity,
double acceleration) {
double motorRecResolution = 0.0;
getAxisParamChecked(this, motorRecResolution, &motorRecResolution);
@@ -166,7 +168,7 @@ asynStatus detectorTowerLiftAxis::doMove(double position, int relative,
// defined target position.
setTargetPosition(position * motorRecResolution);
angleAxis_->receivedTarget_ = true;
waitingForStart_ = true;
return asynSuccess;
}
@@ -222,4 +224,4 @@ asynStatus detectorTowerLiftAxis::adjustOrigin(double newOrigin) {
}
return status;
}
}

View File

@@ -3,7 +3,7 @@
#include "detectorTowerController.h"
#include "turboPmacAxis.h"
class detectorTowerLiftAxis : public turboPmacAxis {
class HIDDEN detectorTowerLiftAxis : public turboPmacAxis {
public:
/**
* @brief Construct a new detectorTowerAngleAxis
@@ -110,6 +110,10 @@ class detectorTowerLiftAxis : public turboPmacAxis {
*/
virtual detectorTowerController *pController() override { return pC_; };
// True, if this axis has received a move command and the driver is
// currently starting a deferred movement.
bool waitingForStart_;
protected:
detectorTowerController *pC_;
detectorTowerAngleAxis *angleAxis_;

View File

@@ -7,7 +7,7 @@
* @brief Passive axis which is mostly controlled indirectly by the hardware
*
*/
class detectorTowerSupportAxis : public turboPmacAxis {
class HIDDEN detectorTowerSupportAxis : public turboPmacAxis {
public:
/**
* @brief Construct a new detectorTowerSupportAxis