Compare commits
24
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70111c4272 | ||
|
|
f837314f5c | ||
|
|
851c7eece3 | ||
|
|
b67c7ca318 | ||
|
|
7744518b87 | ||
|
|
18c6a4c89d | ||
|
|
c4cc3de0ec | ||
|
|
16eb647b1a | ||
|
|
20bce9dff4 | ||
|
|
cb5e740688 | ||
|
|
5392458515 | ||
|
|
39cad74c43 | ||
|
|
d1bf83928d | ||
|
|
e194514264 | ||
|
|
2261ebd331 | ||
|
|
de3065f4cc | ||
|
|
9c3982354d | ||
|
|
86e692ecda | ||
|
|
f30d16816f | ||
|
|
cf93305fdd | ||
|
|
1eb72e865b | ||
|
|
e0f86eec29 | ||
|
|
c196912bed | ||
|
|
ebbc675297 |
@@ -0,0 +1,198 @@
|
|||||||
|
name: macOS Release Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- arch: x86_64
|
||||||
|
machtype: x86_64-apple-darwin
|
||||||
|
artifact: macOS_x86_64_bin
|
||||||
|
- arch: arm64
|
||||||
|
machtype: arm64-apple-darwin
|
||||||
|
artifact: macOS_arm64_bin
|
||||||
|
runs-on: macos
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install ftjam
|
||||||
|
run: |
|
||||||
|
curl -fsSL -o ftjam.tar.gz https://sourceforge.net/projects/freetype/files/ftjam/2.5.2/ftjam-2.5.2.tar.gz/download || wget --no-check-certificate -q -O ftjam.tar.gz https://sourceforge.net/projects/freetype/files/ftjam/2.5.2/ftjam-2.5.2.tar.gz/download
|
||||||
|
tar -xzf ftjam.tar.gz
|
||||||
|
cd ftjam-2.5.2
|
||||||
|
make jam0 CC="cc -Wno-implicit-function-declaration -Wno-incompatible-pointer-types -Wno-int-conversion -Wno-implicit-int"
|
||||||
|
mkdir -p "$HOME/.local/bin"
|
||||||
|
cp jam0 "$HOME/.local/bin/jam"
|
||||||
|
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||||
|
cp jam0 /usr/local/bin/jam 2>/dev/null || true
|
||||||
|
|
||||||
|
- name: Build ArgyllCMS
|
||||||
|
run: |
|
||||||
|
export PATH="$HOME/.local/bin:/usr/local/bin:$PATH"
|
||||||
|
export OSTYPE=darwin
|
||||||
|
export MACHTYPE=${{ matrix.machtype }}
|
||||||
|
export HOSTTYPE=${{ matrix.arch }}
|
||||||
|
export CCOPTFLAG="-O0 -Wno-error=implicit-function-declaration -Wno-error=incompatible-pointer-types -Wno-error=int-conversion -Wno-error=implicit-int"
|
||||||
|
jam -q -d2 -fJambase -j1 -sBUILTIN_TIFF=true -sBUILTIN_JPEG=true -sBUILTIN_PNG=true -sBUILTIN_Z=true -sBUILTIN_SSL=true install
|
||||||
|
|
||||||
|
- name: Ad-hoc Sign & Verify Binaries
|
||||||
|
run: |
|
||||||
|
for f in bin/*; do
|
||||||
|
if [ -f "$f" ] && file "$f" | grep -q "Mach-O"; then
|
||||||
|
echo "Ad-hoc signing $f"
|
||||||
|
codesign -f -s - "$f"
|
||||||
|
codesign -dvv "$f"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Smoke Tests
|
||||||
|
env:
|
||||||
|
ARGYLL_NOT_INTERACTIVE: "1"
|
||||||
|
ARGYLL_EXCLUDE_SERIAL_SCAN: "1"
|
||||||
|
run: |
|
||||||
|
./bin/dispcal -? || true
|
||||||
|
./bin/chartread -? || true
|
||||||
|
./bin/colprof -? || true
|
||||||
|
./bin/targen -? || true
|
||||||
|
|
||||||
|
- name: Package Release
|
||||||
|
run: |
|
||||||
|
export PATH="$HOME/.local/bin:/usr/local/bin:$PATH"
|
||||||
|
export OSTYPE=darwin
|
||||||
|
export MACHTYPE=${{ matrix.machtype }}
|
||||||
|
export HOSTTYPE=${{ matrix.arch }}
|
||||||
|
export CCOPTFLAG="-O0 -Wno-error=implicit-function-declaration -Wno-error=incompatible-pointer-types -Wno-error=int-conversion -Wno-error=implicit-int"
|
||||||
|
export NO_BUILD=1
|
||||||
|
./makepackagebin.sh
|
||||||
|
TAG="${{ github.ref_name }}"
|
||||||
|
SHORT_SHA="$(git rev-parse --short HEAD)"
|
||||||
|
echo "SHORT_SHA=${SHORT_SHA}" >> $GITHUB_ENV
|
||||||
|
mv Argyll_V*_${{ matrix.artifact }}.tgz "Argyll_${TAG}_${SHORT_SHA}_${{ matrix.artifact }}.tgz"
|
||||||
|
|
||||||
|
- name: Upload Raw Binaries
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: raw-bin-${{ matrix.arch }}
|
||||||
|
path: bin/
|
||||||
|
|
||||||
|
- name: Upload Artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: Argyll_${{ github.ref_name }}_${{ env.SHORT_SHA }}_${{ matrix.artifact }}
|
||||||
|
path: Argyll_*_${{ matrix.artifact }}.tgz
|
||||||
|
|
||||||
|
- name: Upload Release Asset
|
||||||
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
|
uses: akkuman/gitea-release-action@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
name: Release ${{ github.ref_name }}
|
||||||
|
body: "Release ${{ github.ref_name }} built from commit ${{ github.sha }}"
|
||||||
|
files: Argyll_*_${{ matrix.artifact }}.tgz
|
||||||
|
|
||||||
|
universal:
|
||||||
|
needs: build
|
||||||
|
runs-on: macos
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Download x86_64 binaries
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: raw-bin-x86_64
|
||||||
|
path: raw-bin-x86_64
|
||||||
|
|
||||||
|
- name: Download arm64 binaries
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: raw-bin-arm64
|
||||||
|
path: raw-bin-arm64
|
||||||
|
|
||||||
|
- name: Create Universal Binaries
|
||||||
|
run: |
|
||||||
|
mkdir -p bin
|
||||||
|
for file in raw-bin-arm64/*; do
|
||||||
|
bin_name=$(basename "$file")
|
||||||
|
if [ -f "raw-bin-x86_64/$bin_name" ]; then
|
||||||
|
if file "raw-bin-arm64/$bin_name" | grep -q "Mach-O" && file "raw-bin-x86_64/$bin_name" | grep -q "Mach-O"; then
|
||||||
|
echo "Creating universal binary with lipo: $bin_name"
|
||||||
|
lipo -create "raw-bin-x86_64/$bin_name" "raw-bin-arm64/$bin_name" -output "bin/$bin_name"
|
||||||
|
chmod +x "bin/$bin_name"
|
||||||
|
codesign -f -s - "bin/$bin_name"
|
||||||
|
else
|
||||||
|
echo "Non Mach-O file, copying directly: $bin_name"
|
||||||
|
cp "$file" "bin/$bin_name"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Warning: $bin_name not found in raw-bin-x86_64, copying arm64 version"
|
||||||
|
cp "$file" "bin/$bin_name"
|
||||||
|
if file "bin/$bin_name" | grep -q "Mach-O"; then
|
||||||
|
codesign -f -s - "bin/$bin_name"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
for file in raw-bin-x86_64/*; do
|
||||||
|
bin_name=$(basename "$file")
|
||||||
|
if [ ! -f "bin/$bin_name" ]; then
|
||||||
|
echo "Warning: $bin_name only found in raw-bin-x86_64, copying x86_64 version"
|
||||||
|
cp "$file" "bin/$bin_name"
|
||||||
|
if file "bin/$bin_name" | grep -q "Mach-O"; then
|
||||||
|
codesign -f -s - "bin/$bin_name"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Verify Architecture & Code Signatures
|
||||||
|
env:
|
||||||
|
ARGYLL_NOT_INTERACTIVE: "1"
|
||||||
|
ARGYLL_EXCLUDE_SERIAL_SCAN: "1"
|
||||||
|
run: |
|
||||||
|
echo "=== Binary Architecture & Signature Verification ==="
|
||||||
|
for file in bin/*; do
|
||||||
|
if [ -f "$file" ] && file "$file" | grep -q "Mach-O"; then
|
||||||
|
file "$file"
|
||||||
|
codesign -dvv "$file"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "=== Smoke Tests ==="
|
||||||
|
./bin/dispcal -? || true
|
||||||
|
./bin/chartread -? || true
|
||||||
|
./bin/colprof -? || true
|
||||||
|
./bin/targen -? || true
|
||||||
|
|
||||||
|
- name: Package Universal Release
|
||||||
|
run: |
|
||||||
|
export OSTYPE=darwin
|
||||||
|
export MACHTYPE=universal-apple-darwin
|
||||||
|
export HOSTTYPE=universal
|
||||||
|
export NO_BUILD=1
|
||||||
|
./makepackagebin.sh
|
||||||
|
TAG="${{ github.ref_name }}"
|
||||||
|
SHORT_SHA="$(git rev-parse --short HEAD)"
|
||||||
|
echo "SHORT_SHA=${SHORT_SHA}" >> $GITHUB_ENV
|
||||||
|
mv Argyll_V*_macOS_universal_bin.tgz "Argyll_${TAG}_${SHORT_SHA}_macOS_universal_bin.tgz"
|
||||||
|
|
||||||
|
- name: Upload Universal Artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: Argyll_${{ github.ref_name }}_${{ env.SHORT_SHA }}_macOS_universal_bin
|
||||||
|
path: Argyll_*_macOS_universal_bin.tgz
|
||||||
|
|
||||||
|
- name: Upload Universal Release Asset
|
||||||
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
|
uses: akkuman/gitea-release-action@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
name: Release ${{ github.ref_name }}
|
||||||
|
body: "Release ${{ github.ref_name }} built from commit ${{ github.sha }}"
|
||||||
|
files: Argyll_*_macOS_universal_bin.tgz
|
||||||
@@ -11,11 +11,11 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: macos-15-intel
|
- os: macos-26-intel
|
||||||
arch: x86_64
|
arch: x86_64
|
||||||
machtype: x86_64-apple-darwin
|
machtype: x86_64-apple-darwin
|
||||||
artifact: macOS_x86_64_bin
|
artifact: macOS_x86_64_bin
|
||||||
- os: macos-15
|
- os: macos-latest
|
||||||
arch: arm64
|
arch: arm64
|
||||||
machtype: arm64-apple-darwin
|
machtype: arm64-apple-darwin
|
||||||
artifact: macOS_arm64_bin
|
artifact: macOS_arm64_bin
|
||||||
@@ -43,6 +43,16 @@ jobs:
|
|||||||
export CCOPTFLAG="-O0"
|
export CCOPTFLAG="-O0"
|
||||||
jam -q -d2 -fJambase -j1 -sBUILTIN_TIFF=true -sBUILTIN_JPEG=true -sBUILTIN_PNG=true -sBUILTIN_Z=true -sBUILTIN_SSL=true install
|
jam -q -d2 -fJambase -j1 -sBUILTIN_TIFF=true -sBUILTIN_JPEG=true -sBUILTIN_PNG=true -sBUILTIN_Z=true -sBUILTIN_SSL=true install
|
||||||
|
|
||||||
|
- name: Ad-hoc Sign & Verify Binaries
|
||||||
|
run: |
|
||||||
|
for f in bin/*; do
|
||||||
|
if [ -f "$f" ] && file "$f" | grep -q "Mach-O"; then
|
||||||
|
echo "Ad-hoc signing $f"
|
||||||
|
codesign -f -s - "$f"
|
||||||
|
codesign -dvv "$f"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
- name: Smoke Tests
|
- name: Smoke Tests
|
||||||
env:
|
env:
|
||||||
ARGYLL_NOT_INTERACTIVE: "1"
|
ARGYLL_NOT_INTERACTIVE: "1"
|
||||||
@@ -86,7 +96,7 @@ jobs:
|
|||||||
|
|
||||||
universal:
|
universal:
|
||||||
needs: build
|
needs: build
|
||||||
runs-on: macos-15
|
runs-on: macos-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
|
||||||
@@ -112,24 +122,44 @@ jobs:
|
|||||||
for file in raw-bin-arm64/*; do
|
for file in raw-bin-arm64/*; do
|
||||||
bin_name=$(basename "$file")
|
bin_name=$(basename "$file")
|
||||||
if [ -f "raw-bin-x86_64/$bin_name" ]; then
|
if [ -f "raw-bin-x86_64/$bin_name" ]; then
|
||||||
|
if file "raw-bin-arm64/$bin_name" | grep -q "Mach-O" && file "raw-bin-x86_64/$bin_name" | grep -q "Mach-O"; then
|
||||||
echo "Creating universal binary with lipo: $bin_name"
|
echo "Creating universal binary with lipo: $bin_name"
|
||||||
lipo -create "raw-bin-x86_64/$bin_name" "raw-bin-arm64/$bin_name" -output "bin/$bin_name"
|
lipo -create "raw-bin-x86_64/$bin_name" "raw-bin-arm64/$bin_name" -output "bin/$bin_name"
|
||||||
chmod +x "bin/$bin_name"
|
chmod +x "bin/$bin_name"
|
||||||
|
codesign -f -s - "bin/$bin_name"
|
||||||
|
else
|
||||||
|
echo "Non Mach-O file, copying directly: $bin_name"
|
||||||
|
cp "$file" "bin/$bin_name"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo "Warning: $bin_name not found in raw-bin-x86_64, copying arm64 version"
|
echo "Warning: $bin_name not found in raw-bin-x86_64, copying arm64 version"
|
||||||
cp "$file" "bin/$bin_name"
|
cp "$file" "bin/$bin_name"
|
||||||
|
if file "bin/$bin_name" | grep -q "Mach-O"; then
|
||||||
|
codesign -f -s - "bin/$bin_name"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
for file in raw-bin-x86_64/*; do
|
||||||
|
bin_name=$(basename "$file")
|
||||||
|
if [ ! -f "bin/$bin_name" ]; then
|
||||||
|
echo "Warning: $bin_name only found in raw-bin-x86_64, copying x86_64 version"
|
||||||
|
cp "$file" "bin/$bin_name"
|
||||||
|
if file "bin/$bin_name" | grep -q "Mach-O"; then
|
||||||
|
codesign -f -s - "bin/$bin_name"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
- name: Verify Architecture & Smoke Tests
|
- name: Verify Architecture & Code Signatures
|
||||||
env:
|
env:
|
||||||
ARGYLL_NOT_INTERACTIVE: "1"
|
ARGYLL_NOT_INTERACTIVE: "1"
|
||||||
ARGYLL_EXCLUDE_SERIAL_SCAN: "1"
|
ARGYLL_EXCLUDE_SERIAL_SCAN: "1"
|
||||||
run: |
|
run: |
|
||||||
echo "=== Binary Architecture Verification ==="
|
echo "=== Binary Architecture & Signature Verification ==="
|
||||||
for file in bin/*; do
|
for file in bin/*; do
|
||||||
if [ -f "$file" ]; then
|
if [ -f "$file" ] && file "$file" | grep -q "Mach-O"; then
|
||||||
file "$file"
|
file "$file"
|
||||||
|
codesign -dvv "$file"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
echo "=== Smoke Tests ==="
|
echo "=== Smoke Tests ==="
|
||||||
|
|||||||
+12
-1
@@ -7,7 +7,7 @@ echo "Script to invoke Jam and then package the binary release."
|
|||||||
PRODUCT=Argyll
|
PRODUCT=Argyll
|
||||||
|
|
||||||
# Set the environment string VERSION from the #define, ie 1.0.0
|
# Set the environment string VERSION from the #define, ie 1.0.0
|
||||||
VERSION=`grep ARGYLL_VERSION_STR h/aconfig.h | head -1 | sed 's/# define ARGYLL_VERSION_STR //' | sed 's/"//g'`
|
VERSION=`grep ARGYLL_VERSION_STR h/aconfig.h | head -1 | sed 's/# define ARGYLL_VERSION_STR //' | sed 's/\"//g'`
|
||||||
|
|
||||||
# Typical environment variables:
|
# Typical environment variables:
|
||||||
# (NOTE some systems don't export these ENV vars. by default !!!)
|
# (NOTE some systems don't export these ENV vars. by default !!!)
|
||||||
@@ -173,6 +173,17 @@ if [ X$NO_BUILD = "X" ] ; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Apply ad-hoc code signatures to macOS Mach-O binaries before staging
|
||||||
|
if [ "${OSTYPE#*darwin*}" != "$OSTYPE" ] ; then
|
||||||
|
echo "=== Applying ad-hoc code signatures to macOS Mach-O binaries ==="
|
||||||
|
for f in bin/* ; do
|
||||||
|
if [ -f "$f" ] && file "$f" | grep -q "Mach-O" ; then
|
||||||
|
echo "Signing $f..."
|
||||||
|
codesign -f -s - "$f" || true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
rm -rf $TOPDIR
|
rm -rf $TOPDIR
|
||||||
mkdir $TOPDIR
|
mkdir $TOPDIR
|
||||||
|
|
||||||
|
|||||||
+48
-2
@@ -204,6 +204,17 @@ typedef struct {
|
|||||||
extern int json_ui_out;
|
extern int json_ui_out;
|
||||||
int json_ui_out = 0;
|
int json_ui_out = 0;
|
||||||
|
|
||||||
|
static int g_use_leds = 0; /* Enable i1Pro 2 visual LED feedback */
|
||||||
|
|
||||||
|
/* Update instrument LED state safely */
|
||||||
|
static void update_led_state(inst *it, inst_led_state state) {
|
||||||
|
if (!g_use_leds || it == NULL)
|
||||||
|
return;
|
||||||
|
if (it->set_led_state != NULL) {
|
||||||
|
it->set_led_state(it, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void compute_patch_metrics(chcol *scb, double *eLab, double *mLab) {
|
static void compute_patch_metrics(chcol *scb, double *eLab, double *mLab) {
|
||||||
/* Expected Lab */
|
/* Expected Lab */
|
||||||
if (scb->eXYZ[0] != 0.0 || scb->eXYZ[1] != 0.0 || scb->eXYZ[2] != 0.0) {
|
if (scb->eXYZ[0] != 0.0 || scb->eXYZ[1] != 0.0 || scb->eXYZ[2] != 0.0) {
|
||||||
@@ -1486,8 +1497,10 @@ a1log *log /* verb, debug & error log */
|
|||||||
|
|
||||||
/* Do any needed calibration before the user places the instrument on a desired spot */
|
/* Do any needed calibration before the user places the instrument on a desired spot */
|
||||||
if (it->needs_calibration(it) & inst_calt_n_dfrble_mask) {
|
if (it->needs_calibration(it) & inst_calt_n_dfrble_mask) {
|
||||||
|
update_led_state(it, inst_led_cal_wait);
|
||||||
if ((rv = inst_handle_calibrate(it, inst_calt_needed, inst_calc_none, NULL, NULL, 0))
|
if ((rv = inst_handle_calibrate(it, inst_calt_needed, inst_calc_none, NULL, NULL, 0))
|
||||||
!= inst_ok) {
|
!= inst_ok) {
|
||||||
|
update_led_state(it, inst_led_off);
|
||||||
printf("\nCalibration failed with error :'%s' (%s)\n",
|
printf("\nCalibration failed with error :'%s' (%s)\n",
|
||||||
it->inst_interp_error(it, rv), it->interp_error(it, rv));
|
it->inst_interp_error(it, rv), it->interp_error(it, rv));
|
||||||
it->del(it);
|
it->del(it);
|
||||||
@@ -1495,6 +1508,7 @@ a1log *log /* verb, debug & error log */
|
|||||||
free(pfname);
|
free(pfname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
update_led_state(it, inst_led_off);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable (switch or user) via uicallback trigger if possible */
|
/* Enable (switch or user) via uicallback trigger if possible */
|
||||||
@@ -1637,6 +1651,7 @@ a1log *log /* verb, debug & error log */
|
|||||||
printf("Press any other key to start:%s",fl_end);
|
printf("Press any other key to start:%s",fl_end);
|
||||||
}
|
}
|
||||||
do_fflush();
|
do_fflush();
|
||||||
|
update_led_state(it, inst_led_row_ready);
|
||||||
if ((rv = it->read_strip(it, "STRIP", stipa+nextrap, nn, guide, plen, glen, tlen, vals)) != inst_ok
|
if ((rv = it->read_strip(it, "STRIP", stipa+nextrap, nn, guide, plen, glen, tlen, vals)) != inst_ok
|
||||||
&& (rv & inst_mask) != inst_user_trig) {
|
&& (rv & inst_mask) != inst_user_trig) {
|
||||||
|
|
||||||
@@ -1698,6 +1713,7 @@ a1log *log /* verb, debug & error log */
|
|||||||
printf("Hit Esc or 'q' to give up, any other key to retry:%s",fl_end);
|
printf("Hit Esc or 'q' to give up, any other key to retry:%s",fl_end);
|
||||||
do_fflush();
|
do_fflush();
|
||||||
if ((ch = next_con_char()) == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') {
|
if ((ch = next_con_char()) == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') {
|
||||||
|
update_led_state(it, inst_led_off);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
if (nn != NULL) free(nn);
|
if (nn != NULL) free(nn);
|
||||||
free(vals);
|
free(vals);
|
||||||
@@ -1717,7 +1733,9 @@ a1log *log /* verb, debug & error log */
|
|||||||
if (cap2 & inst2_no_feedback)
|
if (cap2 & inst2_no_feedback)
|
||||||
bad_beep();
|
bad_beep();
|
||||||
printf("\nStrip read failed because instruments needs calibration\n");
|
printf("\nStrip read failed because instruments needs calibration\n");
|
||||||
|
update_led_state(it, inst_led_cal_wait);
|
||||||
ev = inst_handle_calibrate(it, inst_calt_needed, inst_calc_none, NULL, NULL, 0);
|
ev = inst_handle_calibrate(it, inst_calt_needed, inst_calc_none, NULL, NULL, 0);
|
||||||
|
update_led_state(it, inst_led_off);
|
||||||
if (ev != inst_ok) { /* Abort or fatal error */
|
if (ev != inst_ok) { /* Abort or fatal error */
|
||||||
if (nn != NULL) free(nn);
|
if (nn != NULL) free(nn);
|
||||||
free(vals);
|
free(vals);
|
||||||
@@ -1735,12 +1753,14 @@ a1log *log /* verb, debug & error log */
|
|||||||
|
|
||||||
/* Deal with a misread */
|
/* Deal with a misread */
|
||||||
} else if ((rv & inst_mask) == inst_misread) {
|
} else if ((rv & inst_mask) == inst_misread) {
|
||||||
|
update_led_state(it, inst_led_row_fail);
|
||||||
if (cap2 & inst2_no_feedback)
|
if (cap2 & inst2_no_feedback)
|
||||||
bad_beep();
|
bad_beep();
|
||||||
empty_con_chars();
|
empty_con_chars();
|
||||||
printf("\nStrip read failed due to misread (%s)\n",it->interp_error(it, rv));
|
printf("\nStrip read failed due to misread (%s)\n",it->interp_error(it, rv));
|
||||||
printf("Hit Esc to give up, any other key to retry%s:",fl_end); do_fflush();
|
printf("Hit Esc to give up, any other key to retry%s:",fl_end); do_fflush();
|
||||||
if ((ch = next_con_char()) == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') {
|
if ((ch = next_con_char()) == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') {
|
||||||
|
update_led_state(it, inst_led_off);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
if (nn != NULL) free(nn);
|
if (nn != NULL) free(nn);
|
||||||
free(vals);
|
free(vals);
|
||||||
@@ -1754,12 +1774,14 @@ a1log *log /* verb, debug & error log */
|
|||||||
|
|
||||||
/* Deal with a communications error */
|
/* Deal with a communications error */
|
||||||
} else if ((rv & inst_mask) == inst_coms_fail) {
|
} else if ((rv & inst_mask) == inst_coms_fail) {
|
||||||
|
update_led_state(it, inst_led_row_fail);
|
||||||
if (cap2 & inst2_no_feedback)
|
if (cap2 & inst2_no_feedback)
|
||||||
bad_beep();
|
bad_beep();
|
||||||
empty_con_chars();
|
empty_con_chars();
|
||||||
printf("\nStrip read failed due to communication problem.\n");
|
printf("\nStrip read failed due to communication problem.\n");
|
||||||
printf("Hit Esc or 'q' to give up, any other key to retry:%s",fl_end); do_fflush();
|
printf("Hit Esc or 'q' to give up, any other key to retry:%s",fl_end); do_fflush();
|
||||||
if ((ch = next_con_char()) == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') {
|
if ((ch = next_con_char()) == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') {
|
||||||
|
update_led_state(it, inst_led_off);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
if (nn != NULL) free(nn);
|
if (nn != NULL) free(nn);
|
||||||
free(vals);
|
free(vals);
|
||||||
@@ -1798,12 +1820,14 @@ a1log *log /* verb, debug & error log */
|
|||||||
|
|
||||||
/* Some other error. Treat it as fatal */
|
/* Some other error. Treat it as fatal */
|
||||||
} else {
|
} else {
|
||||||
|
update_led_state(it, inst_led_row_fail);
|
||||||
if (cap2 & inst2_no_feedback)
|
if (cap2 & inst2_no_feedback)
|
||||||
bad_beep();
|
bad_beep();
|
||||||
printf("\nStrip read failed due unexpected error :'%s' (%s)\n",
|
printf("\nStrip read failed due unexpected error :'%s' (%s)\n",
|
||||||
it->inst_interp_error(it, rv), it->interp_error(it, rv));
|
it->inst_interp_error(it, rv), it->interp_error(it, rv));
|
||||||
printf("Hit Esc or 'q' to give up, any other key to retry:%s",fl_end); do_fflush();
|
printf("Hit Esc or 'q' to give up, any other key to retry:%s",fl_end); do_fflush();
|
||||||
if ((ch = next_con_char()) == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') {
|
if ((ch = next_con_char()) == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') {
|
||||||
|
update_led_state(it, inst_led_off);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
if (nn != NULL) free(nn);
|
if (nn != NULL) free(nn);
|
||||||
free(vals);
|
free(vals);
|
||||||
@@ -1953,6 +1977,7 @@ a1log *log /* verb, debug & error log */
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (ch != 0x0d && ch != 0x0a) { /* !(CR or LF) */
|
if (ch != 0x0d && ch != 0x0a) { /* !(CR or LF) */
|
||||||
|
update_led_state(it, inst_led_row_fail);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
continue; /* Try again */
|
continue; /* Try again */
|
||||||
}
|
}
|
||||||
@@ -1976,6 +2001,7 @@ a1log *log /* verb, debug & error log */
|
|||||||
printf("\nThere is at least one patch with an very unexpected response! (DeltaE %f)\n",werror);
|
printf("\nThere is at least one patch with an very unexpected response! (DeltaE %f)\n",werror);
|
||||||
printf("Hit Return to use it anyway, any other key to retry, Esc or 'q' to give up:%s",fl_end); do_fflush();
|
printf("Hit Return to use it anyway, any other key to retry, Esc or 'q' to give up:%s",fl_end); do_fflush();
|
||||||
if ((ch = next_con_char()) == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') {
|
if ((ch = next_con_char()) == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') {
|
||||||
|
update_led_state(it, inst_led_off);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
if (nn != NULL) free(nn);
|
if (nn != NULL) free(nn);
|
||||||
free(vals);
|
free(vals);
|
||||||
@@ -1985,6 +2011,7 @@ a1log *log /* verb, debug & error log */
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (ch != 0x0d && ch != 0x0a) { /* !Cr */
|
if (ch != 0x0d && ch != 0x0a) { /* !Cr */
|
||||||
|
update_led_state(it, inst_led_row_fail);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1995,6 +2022,7 @@ a1log *log /* verb, debug & error log */
|
|||||||
/* Must be OK - save the readings */
|
/* Must be OK - save the readings */
|
||||||
if (cap2 & inst2_no_feedback)
|
if (cap2 & inst2_no_feedback)
|
||||||
good_beep();
|
good_beep();
|
||||||
|
update_led_state(it, inst_led_row_success);
|
||||||
printf(" Strip read OK");
|
printf(" Strip read OK");
|
||||||
if (boff != 0)
|
if (boff != 0)
|
||||||
printf(" (DTP51 offset fix of %d applied)",boff);
|
printf(" (DTP51 offset fix of %d applied)",boff);
|
||||||
@@ -2048,6 +2076,7 @@ a1log *log /* verb, debug & error log */
|
|||||||
|
|
||||||
|
|
||||||
} /* Go around to read another row */
|
} /* Go around to read another row */
|
||||||
|
update_led_state(it, inst_led_off);
|
||||||
free(vals);
|
free(vals);
|
||||||
|
|
||||||
/* -------------------------------------------------- */
|
/* -------------------------------------------------- */
|
||||||
@@ -2065,8 +2094,10 @@ a1log *log /* verb, debug & error log */
|
|||||||
|
|
||||||
/* Do any needed calibration before the user places the instrument on a desired spot */
|
/* Do any needed calibration before the user places the instrument on a desired spot */
|
||||||
if (it->needs_calibration(it) & inst_calt_n_dfrble_mask) {
|
if (it->needs_calibration(it) & inst_calt_n_dfrble_mask) {
|
||||||
|
update_led_state(it, inst_led_cal_wait);
|
||||||
if ((rv = inst_handle_calibrate(it, inst_calt_needed, inst_calc_none, NULL, NULL, 0))
|
if ((rv = inst_handle_calibrate(it, inst_calt_needed, inst_calc_none, NULL, NULL, 0))
|
||||||
!= inst_ok) {
|
!= inst_ok) {
|
||||||
|
update_led_state(it, inst_led_off);
|
||||||
printf("\nCalibration failed with error :'%s' (%s)\n",
|
printf("\nCalibration failed with error :'%s' (%s)\n",
|
||||||
it->inst_interp_error(it, rv), it->interp_error(it, rv));
|
it->inst_interp_error(it, rv), it->interp_error(it, rv));
|
||||||
it->del(it);
|
it->del(it);
|
||||||
@@ -2074,6 +2105,7 @@ a1log *log /* verb, debug & error log */
|
|||||||
free(pfname);
|
free(pfname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
update_led_state(it, inst_led_off);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable (switch or user) via uicallback trigger if possible */
|
/* Enable (switch or user) via uicallback trigger if possible */
|
||||||
@@ -2302,7 +2334,9 @@ a1log *log /* verb, debug & error log */
|
|||||||
if (cap2 & inst2_no_feedback)
|
if (cap2 & inst2_no_feedback)
|
||||||
bad_beep();
|
bad_beep();
|
||||||
printf("\nSpot read failed because instruments needs calibration\n");
|
printf("\nSpot read failed because instruments needs calibration\n");
|
||||||
|
update_led_state(it, inst_led_cal_wait);
|
||||||
ev = inst_handle_calibrate(it, inst_calt_needed, inst_calc_none, NULL, NULL, 0);
|
ev = inst_handle_calibrate(it, inst_calt_needed, inst_calc_none, NULL, NULL, 0);
|
||||||
|
update_led_state(it, inst_led_off);
|
||||||
if (ev != inst_ok) { /* Abort or fatal error */
|
if (ev != inst_ok) { /* Abort or fatal error */
|
||||||
it->del(it);
|
it->del(it);
|
||||||
if (pfname != NULL)
|
if (pfname != NULL)
|
||||||
@@ -2312,12 +2346,14 @@ a1log *log /* verb, debug & error log */
|
|||||||
continue;
|
continue;
|
||||||
/* Deal with a misread */
|
/* Deal with a misread */
|
||||||
} else if ((rv & inst_mask) == inst_misread) {
|
} else if ((rv & inst_mask) == inst_misread) {
|
||||||
|
update_led_state(it, inst_led_row_fail);
|
||||||
if (cap2 & inst2_no_feedback)
|
if (cap2 & inst2_no_feedback)
|
||||||
bad_beep();
|
bad_beep();
|
||||||
empty_con_chars();
|
empty_con_chars();
|
||||||
printf("\nStrip read failed due to misread (%s)\n",it->interp_error(it, rv));
|
printf("\nStrip read failed due to misread (%s)\n",it->interp_error(it, rv));
|
||||||
printf("Hit Esc or 'q' to give up, any other key to retry:%s",fl_end); do_fflush();
|
printf("Hit Esc or 'q' to give up, any other key to retry:%s",fl_end); do_fflush();
|
||||||
if ((ch = next_con_char()) == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') {
|
if ((ch = next_con_char()) == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') {
|
||||||
|
update_led_state(it, inst_led_off);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
it->del(it);
|
it->del(it);
|
||||||
if (pfname != NULL)
|
if (pfname != NULL)
|
||||||
@@ -2328,12 +2364,14 @@ a1log *log /* verb, debug & error log */
|
|||||||
continue;
|
continue;
|
||||||
/* Deal with a communications error */
|
/* Deal with a communications error */
|
||||||
} else if ((rv & inst_mask) == inst_coms_fail) {
|
} else if ((rv & inst_mask) == inst_coms_fail) {
|
||||||
|
update_led_state(it, inst_led_row_fail);
|
||||||
if (cap2 & inst2_no_feedback)
|
if (cap2 & inst2_no_feedback)
|
||||||
bad_beep();
|
bad_beep();
|
||||||
empty_con_chars();
|
empty_con_chars();
|
||||||
printf("\nStrip read failed due to communication problem.\n");
|
printf("\nStrip read failed due to communication problem.\n");
|
||||||
printf("Hit Esc or 'q' to give up, any other key to retry:%s",fl_end); do_fflush();
|
printf("Hit Esc or 'q' to give up, any other key to retry:%s",fl_end); do_fflush();
|
||||||
if ((ch = next_con_char()) == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') {
|
if ((ch = next_con_char()) == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') {
|
||||||
|
update_led_state(it, inst_led_off);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
it->del(it);
|
it->del(it);
|
||||||
if (pfname != NULL)
|
if (pfname != NULL)
|
||||||
@@ -2369,12 +2407,14 @@ a1log *log /* verb, debug & error log */
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* Some other error. Treat it as fatal */
|
/* Some other error. Treat it as fatal */
|
||||||
|
update_led_state(it, inst_led_row_fail);
|
||||||
if (cap2 & inst2_no_feedback)
|
if (cap2 & inst2_no_feedback)
|
||||||
bad_beep();
|
bad_beep();
|
||||||
printf("\nPatch read failed due unexpected error :'%s' (%s)\n",
|
printf("\nPatch read failed due unexpected error :'%s' (%s)\n",
|
||||||
it->inst_interp_error(it, rv), it->interp_error(it, rv));
|
it->inst_interp_error(it, rv), it->interp_error(it, rv));
|
||||||
printf("Hit Esc or 'q' to give up, any other key to retry:%s",fl_end); do_fflush();
|
printf("Hit Esc or 'q' to give up, any other key to retry:%s",fl_end); do_fflush();
|
||||||
if ((ch = next_con_char()) == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') {
|
if ((ch = next_con_char()) == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') {
|
||||||
|
update_led_state(it, inst_led_off);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
it->del(it);
|
it->del(it);
|
||||||
if (pfname != NULL)
|
if (pfname != NULL)
|
||||||
@@ -2390,6 +2430,7 @@ a1log *log /* verb, debug & error log */
|
|||||||
empty_con_chars();
|
empty_con_chars();
|
||||||
printf("\nAbort ? - Are you sure ? [y/n]:%s",fl_end); do_fflush();
|
printf("\nAbort ? - Are you sure ? [y/n]:%s",fl_end); do_fflush();
|
||||||
if ((ch = next_con_char()) == 'y' || ch == 'Y') {
|
if ((ch = next_con_char()) == 'y' || ch == 'Y') {
|
||||||
|
update_led_state(it, inst_led_off);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
it->del(it);
|
it->del(it);
|
||||||
if (pfname != NULL)
|
if (pfname != NULL)
|
||||||
@@ -2401,7 +2442,9 @@ a1log *log /* verb, debug & error log */
|
|||||||
} else if (ch == 'k') {
|
} else if (ch == 'k') {
|
||||||
inst_code ev;
|
inst_code ev;
|
||||||
|
|
||||||
|
update_led_state(it, inst_led_cal_wait);
|
||||||
ev = inst_handle_calibrate(it, inst_calt_available, inst_calc_none, NULL, NULL, 0);
|
ev = inst_handle_calibrate(it, inst_calt_available, inst_calc_none, NULL, NULL, 0);
|
||||||
|
update_led_state(it, inst_led_off);
|
||||||
if (ev != inst_ok) { /* Abort or fatal error */
|
if (ev != inst_ok) { /* Abort or fatal error */
|
||||||
it->del(it);
|
it->del(it);
|
||||||
if (pfname != NULL)
|
if (pfname != NULL)
|
||||||
@@ -2556,6 +2599,7 @@ a1log *log /* verb, debug & error log */
|
|||||||
/* -------------------------------------------------- */
|
/* -------------------------------------------------- */
|
||||||
|
|
||||||
/* clean up */
|
/* clean up */
|
||||||
|
update_led_state(it, inst_led_off);
|
||||||
if (it != NULL)
|
if (it != NULL)
|
||||||
it->del(it);
|
it->del(it);
|
||||||
if (pfname != NULL)
|
if (pfname != NULL)
|
||||||
@@ -2621,7 +2665,7 @@ usage() {
|
|||||||
}
|
}
|
||||||
fprintf(stderr," -T ratio Modify strip patch consistency tolerance by ratio\n");
|
fprintf(stderr," -T ratio Modify strip patch consistency tolerance by ratio\n");
|
||||||
fprintf(stderr," -S Suppress wrong strip & unexpected value warnings\n");
|
fprintf(stderr," -S Suppress wrong strip & unexpected value warnings\n");
|
||||||
// fprintf(stderr," -Y U Test i1pro2 UV measurement mode\n");
|
fprintf(stderr," -Y l Enable i1Pro 2 visual LED feedback\n");
|
||||||
fprintf(stderr," -W n|h|x Override serial port flow control: n = none, h = HW, x = Xon/Xoff\n");
|
fprintf(stderr," -W n|h|x Override serial port flow control: n = none, h = HW, x = Xon/Xoff\n");
|
||||||
#ifndef SALONEINSTLIB
|
#ifndef SALONEINSTLIB
|
||||||
fprintf(stderr," -P Plot spectral if patch by patch\n");
|
fprintf(stderr," -P Plot spectral if patch by patch\n");
|
||||||
@@ -2902,7 +2946,9 @@ int main(int argc, char *argv[]) {
|
|||||||
if (na == NULL)
|
if (na == NULL)
|
||||||
usage(); /* "Parameter expected after -Y" */
|
usage(); /* "Parameter expected after -Y" */
|
||||||
|
|
||||||
{
|
if (na[0] == 'l' || na[0] == 'L') {
|
||||||
|
g_use_leds = 1;
|
||||||
|
} else {
|
||||||
usage(); /* "-Y parameter '%c' not recognised",na[0] */
|
usage(); /* "-Y parameter '%c' not recognised",na[0] */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-1
@@ -170,9 +170,14 @@ i1pro_determine_capabilities(i1pro *p) {
|
|||||||
| inst2_user_switch_trig
|
| inst2_user_switch_trig
|
||||||
| inst2_bidi_scan
|
| inst2_bidi_scan
|
||||||
| inst2_has_scan_toll
|
| inst2_has_scan_toll
|
||||||
| inst2_no_feedback
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
if (p->dtype == instI1Pro2) {
|
||||||
|
p->cap2 |= inst2_has_leds;
|
||||||
|
} else {
|
||||||
|
p->cap2 |= inst2_no_feedback;
|
||||||
|
}
|
||||||
|
|
||||||
if (p->m != NULL) {
|
if (p->m != NULL) {
|
||||||
i1proimp *m = (i1proimp *)p->m;
|
i1proimp *m = (i1proimp *)p->m;
|
||||||
i1pro_state *s = &m->ms[m->mmode];
|
i1pro_state *s = &m->ms[m->mmode];
|
||||||
@@ -943,11 +948,24 @@ i1pro_get_set_opt(inst *pp, inst_opt_type m, ...) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set device indicator LED status */
|
||||||
|
static inst_code
|
||||||
|
i1pro_set_led_state(inst *pp, inst_led_state state) {
|
||||||
|
i1pro *p = (i1pro *)pp;
|
||||||
|
|
||||||
|
if (p->dtype != instI1Pro2)
|
||||||
|
return inst_unsupported;
|
||||||
|
|
||||||
|
return i1pro_interp_code(p, i1pro_imp_set_led_state(p, state));
|
||||||
|
}
|
||||||
|
|
||||||
/* Destroy ourselves */
|
/* Destroy ourselves */
|
||||||
static void
|
static void
|
||||||
i1pro_del(inst *pp) {
|
i1pro_del(inst *pp) {
|
||||||
i1pro *p = (i1pro *)pp;
|
i1pro *p = (i1pro *)pp;
|
||||||
|
|
||||||
|
/* Shut down instrument hardware and close the port, then free state */
|
||||||
|
i1pro_close_port(p);
|
||||||
del_i1proimp(p);
|
del_i1proimp(p);
|
||||||
if (p->icom != NULL)
|
if (p->icom != NULL)
|
||||||
p->icom->del(p->icom);
|
p->icom->del(p->icom);
|
||||||
@@ -982,6 +1000,7 @@ extern i1pro *new_i1pro(icoms *icom, instType dtype) {
|
|||||||
p->meas_delay = i1pro_meas_delay;
|
p->meas_delay = i1pro_meas_delay;
|
||||||
p->white_change = i1pro_white_change;
|
p->white_change = i1pro_white_change;
|
||||||
p->interp_error = i1pro_interp_error;
|
p->interp_error = i1pro_interp_error;
|
||||||
|
p->set_led_state = i1pro_set_led_state;
|
||||||
p->del = i1pro_del;
|
p->del = i1pro_del;
|
||||||
|
|
||||||
p->icom = icom;
|
p->icom = icom;
|
||||||
|
|||||||
+305
-29
@@ -389,8 +389,121 @@ i1pro_code add_i1proimp(i1pro *p) {
|
|||||||
return I1PRO_OK;
|
return I1PRO_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shutdown instrument, and then destroy */
|
/* Stop background threads (switch monitoring & delayed trigger) */
|
||||||
/* implementation structure */
|
static void
|
||||||
|
i1pro_stop_threads(i1pro *p) {
|
||||||
|
i1proimp *m;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (p == NULL || p->m == NULL)
|
||||||
|
return;
|
||||||
|
m = (i1proimp *)p->m;
|
||||||
|
|
||||||
|
/* Stop the switch monitoring thread first so it isn't using the */
|
||||||
|
/* communication channel while we shut down the instrument. */
|
||||||
|
if (m->th != NULL) {
|
||||||
|
m->th_term = 1; /* Tell thread to exit on error */
|
||||||
|
|
||||||
|
/* Ask the instrument to stop sending switch events and cancel */
|
||||||
|
/* any outstanding switch read. Only do this if the port is still */
|
||||||
|
/* open and the required method pointers are valid. */
|
||||||
|
if (p->icom != NULL && p->icom->is_open
|
||||||
|
&& p->icom->usb_control != NULL
|
||||||
|
&& p->icom->usb_cancel_io != NULL) {
|
||||||
|
i1pro_terminate_switch(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Give the thread a chance to exit cleanly (up to 5 seconds). */
|
||||||
|
for (i = 0; m->th_termed == 0 && i < 100; i++)
|
||||||
|
msec_sleep(50);
|
||||||
|
|
||||||
|
if (m->th_termed == 0) {
|
||||||
|
a1logd(p->log,3,"i1pro switch thread did not terminate, forcing\n");
|
||||||
|
if (m->th->terminate != NULL)
|
||||||
|
m->th->terminate(m->th);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m->th->wait != NULL)
|
||||||
|
m->th->wait(m->th);
|
||||||
|
if (m->th->del != NULL)
|
||||||
|
m->th->del(m->th);
|
||||||
|
m->th = NULL;
|
||||||
|
|
||||||
|
usb_uninit_cancel(&m->sw_cancel); /* Don't need cancel token now */
|
||||||
|
usb_uninit_cancel(&m->rd_sync); /* Don't need sync token now */
|
||||||
|
a1logd(p->log,5,"i1pro switch thread terminated\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop the delayed trigger thread if it is still running */
|
||||||
|
if (m->trig_thread != NULL) {
|
||||||
|
if (m->trig_thread->wait != NULL)
|
||||||
|
m->trig_thread->wait(m->trig_thread);
|
||||||
|
if (m->trig_thread->del != NULL)
|
||||||
|
m->trig_thread->del(m->trig_thread);
|
||||||
|
m->trig_thread = NULL;
|
||||||
|
a1logd(p->log,5,"i1pro trigger thread terminated\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop the LED status feedback thread if running */
|
||||||
|
if (m->led_th != NULL) {
|
||||||
|
m->led_th_run = 0;
|
||||||
|
if (m->led_th->wait != NULL)
|
||||||
|
m->led_th->wait(m->led_th);
|
||||||
|
if (m->led_th->del != NULL)
|
||||||
|
m->led_th->del(m->led_th);
|
||||||
|
m->led_th = NULL;
|
||||||
|
a1logd(p->log,5,"i1pro led thread terminated\n");
|
||||||
|
}
|
||||||
|
if (m->led_th_init) {
|
||||||
|
amutex_del(m->led_lock);
|
||||||
|
m->led_th_init = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop any pending I/O, shut down the instrument hardware, and close the */
|
||||||
|
/* communication port. This is separate from freeing the implementation data. */
|
||||||
|
i1pro_code
|
||||||
|
i1pro_close_port(i1pro *p) {
|
||||||
|
i1pro_code ev = I1PRO_OK;
|
||||||
|
i1proimp *m;
|
||||||
|
|
||||||
|
a1logd(p->log,3,"i1pro_close_port: called\n");
|
||||||
|
|
||||||
|
if (p->m == NULL)
|
||||||
|
return I1PRO_OK;
|
||||||
|
m = (i1proimp *)p->m;
|
||||||
|
|
||||||
|
/* Stop the switch monitoring thread and trigger thread first so they */
|
||||||
|
/* aren't using the communication channel while we shut down the instrument. */
|
||||||
|
i1pro_stop_threads(p);
|
||||||
|
|
||||||
|
/* Update usage log/calibration for Rev A..D before closing the port */
|
||||||
|
if (p->dtype != instI1Pro2 && p->icom != NULL && p->icom->is_open
|
||||||
|
&& p->icom->usb_control != NULL && p->icom->usb_write != NULL) {
|
||||||
|
i1pro_code uev;
|
||||||
|
if ((uev = i1pro_update_log(p)) != I1PRO_OK) {
|
||||||
|
a1logd(p->log,2,"i1pro_update_log: Updating the cal and log parameters to"
|
||||||
|
" EEProm failed failed\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Turn off i1Pro2/Rev E indicator LEDs before closing the port. */
|
||||||
|
/* Only attempt the write if the port is still actively open and the */
|
||||||
|
/* required USB method pointers are valid. Rev A..D do not have LEDs. */
|
||||||
|
if (p->dtype == instI1Pro2 && p->icom != NULL && p->icom->is_open
|
||||||
|
&& p->icom->usb_control != NULL && p->icom->usb_write != NULL) {
|
||||||
|
i1pro2_indLEDoff(p); /* Ignore error - we're shutting down */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close the underlying communication port */
|
||||||
|
if (p->icom != NULL && p->icom->is_open && p->icom->close_port != NULL) {
|
||||||
|
p->icom->close_port(p->icom);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Destroy implementation structure */
|
||||||
void del_i1proimp(i1pro *p) {
|
void del_i1proimp(i1pro *p) {
|
||||||
|
|
||||||
a1logd(p->log,5,"i1pro_del called\n");
|
a1logd(p->log,5,"i1pro_del called\n");
|
||||||
@@ -404,38 +517,28 @@ void del_i1proimp(i1pro *p) {
|
|||||||
int i, j;
|
int i, j;
|
||||||
i1proimp *m = (i1proimp *)p->m;
|
i1proimp *m = (i1proimp *)p->m;
|
||||||
i1pro_state *s;
|
i1pro_state *s;
|
||||||
i1pro_code ev;
|
|
||||||
|
|
||||||
if (p->dtype != instI1Pro2 && (ev = i1pro_update_log(p)) != I1PRO_OK) {
|
/* Defensive guard: ensure background threads are terminated and joined */
|
||||||
|
/* before freeing state, in case i1pro_close_port() was not called. */
|
||||||
|
i1pro_stop_threads(p);
|
||||||
|
|
||||||
|
/* Defensive guard: update usage log/cal for Rev A..D if port is still open */
|
||||||
|
if (p->dtype != instI1Pro2 && p->icom != NULL && p->icom->is_open
|
||||||
|
&& p->icom->usb_control != NULL && p->icom->usb_write != NULL) {
|
||||||
|
i1pro_code uev;
|
||||||
|
if ((uev = i1pro_update_log(p)) != I1PRO_OK) {
|
||||||
a1logd(p->log,2,"i1pro_update_log: Updating the cal and log parameters to"
|
a1logd(p->log,2,"i1pro_update_log: Updating the cal and log parameters to"
|
||||||
" EEProm failed failed\n");
|
" EEProm failed failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* i1pro_terminate_switch() seems to fail on a rev A & Rev C ?? */
|
|
||||||
if (m->th != NULL) { /* Terminate switch monitor thread */
|
|
||||||
m->th_term = 1; /* Tell thread to exit on error */
|
|
||||||
i1pro_terminate_switch(p);
|
|
||||||
|
|
||||||
for (i = 0; m->th_termed == 0 && i < 5; i++)
|
|
||||||
msec_sleep(50); /* Wait for thread to terminate */
|
|
||||||
if (i >= 5) {
|
|
||||||
a1logd(p->log,5,"i1pro switch thread termination failed\n");
|
|
||||||
m->th->terminate(m->th); /* Try and force thread to terminate */
|
|
||||||
}
|
|
||||||
/* Strange Mac M2/rosetta bug ?? */
|
|
||||||
if (m->th->del == NULL) {
|
|
||||||
a1logd(p->log,1,"i1pro_del: ,m->th-del is NULL!!!");
|
|
||||||
} else {
|
|
||||||
m->th->del(m->th);
|
|
||||||
}
|
|
||||||
usb_uninit_cancel(&m->sw_cancel); /* Don't need cancel token now */
|
|
||||||
usb_uninit_cancel(&m->rd_sync); /* Don't need sync token now */
|
|
||||||
a1logd(p->log,5,"i1pro switch thread terminated\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m->trig_thread != NULL) {
|
/* Defensive guard: if the com port is still open and this is an */
|
||||||
m->trig_thread->del(m->trig_thread);
|
/* i1Pro2, make sure the indicator LEDs are turned off before any */
|
||||||
a1logd(p->log,5,"i1pro trigger thread terminated\n");
|
/* memory is freed. In normal teardown i1pro_close_port() has */
|
||||||
|
/* already done this, but the guard protects any direct call paths. */
|
||||||
|
if (p->dtype == instI1Pro2 && p->icom != NULL && p->icom->is_open
|
||||||
|
&& p->icom->usb_control != NULL && p->icom->usb_write != NULL) {
|
||||||
|
i1pro2_indLEDoff(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free any per mode data */
|
/* Free any per mode data */
|
||||||
@@ -12319,11 +12422,17 @@ i1pro2_stop_ruler(void *pp, int parm) {
|
|||||||
static int
|
static int
|
||||||
i1pro2_indLEDseq(void *pp, unsigned char *buf, int size) {
|
i1pro2_indLEDseq(void *pp, unsigned char *buf, int size) {
|
||||||
i1pro *p = (i1pro *)pp;
|
i1pro *p = (i1pro *)pp;
|
||||||
i1proimp *m = (i1proimp *)p->m;
|
i1proimp *m;
|
||||||
int rwbytes; /* Data bytes written */
|
int rwbytes; /* Data bytes written */
|
||||||
unsigned char pbuf[4]; /* Number of bytes being send */
|
unsigned char pbuf[4]; /* Number of bytes being send */
|
||||||
int se, rv = I1PRO_OK;
|
int se, rv = I1PRO_OK;
|
||||||
|
|
||||||
|
if (p == NULL || p->m == NULL || p->icom == NULL || !p->icom->is_open
|
||||||
|
|| p->icom->usb_control == NULL || p->icom->usb_write == NULL) {
|
||||||
|
return I1PRO_INT_NO_COMS;
|
||||||
|
}
|
||||||
|
m = (i1proimp *)p->m;
|
||||||
|
|
||||||
int2buf(pbuf, size);
|
int2buf(pbuf, size);
|
||||||
|
|
||||||
a1logd(p->log,2,"i1pro2_indLEDseq: length %d bytes\n", size);
|
a1logd(p->log,2,"i1pro2_indLEDseq: length %d bytes\n", size);
|
||||||
@@ -12377,6 +12486,173 @@ i1pro2_indLEDoff(void *pp) {
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set indicator LEDs to a solid color mask (or off if mask is 0) */
|
||||||
|
static int
|
||||||
|
i1pro2_indLEDset(void *pp, unsigned char mask) {
|
||||||
|
i1pro *p = (i1pro *)pp;
|
||||||
|
int rv = I1PRO_OK;
|
||||||
|
unsigned char seq[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x01,
|
||||||
|
|
||||||
|
0x00, 0x00, 0x00, 0x0a,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x00, 0x36, 0x40,
|
||||||
|
0x00, 0x00, 0x01
|
||||||
|
};
|
||||||
|
|
||||||
|
if (mask == 0)
|
||||||
|
return i1pro2_indLEDoff(pp);
|
||||||
|
|
||||||
|
seq[12] = mask;
|
||||||
|
|
||||||
|
a1logd(p->log,3,"i1pro2_indLEDset: called with mask 0x%02x\n", mask);
|
||||||
|
rv = i1pro2_indLEDseq(p, seq, sizeof(seq));
|
||||||
|
a1logd(p->log,3,"i1pro2_indLEDset: returning ICOM err 0x%x\n", rv);
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Helper to sleep up to ms while checking if state changed or thread stopping */
|
||||||
|
static void
|
||||||
|
led_sleep_ms(i1proimp *m, inst_led_state state, int ms) {
|
||||||
|
int elapsed = 0;
|
||||||
|
while (m->led_th_run && elapsed < ms) {
|
||||||
|
inst_led_state cur;
|
||||||
|
amutex_lock(m->led_lock);
|
||||||
|
cur = m->current_led_state;
|
||||||
|
amutex_unlock(m->led_lock);
|
||||||
|
if (cur != state)
|
||||||
|
break;
|
||||||
|
msec_sleep(20);
|
||||||
|
elapsed += 20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Worker thread for asynchronous LED pulsing / patterns */
|
||||||
|
static int
|
||||||
|
i1pro2_led_thread(void *context) {
|
||||||
|
i1pro *p = (i1pro *)context;
|
||||||
|
i1proimp *m;
|
||||||
|
int phase = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (p == NULL || p->m == NULL)
|
||||||
|
return 0;
|
||||||
|
m = (i1proimp *)p->m;
|
||||||
|
|
||||||
|
a1logd(p->log, 3, "i1pro2_led_thread started\n");
|
||||||
|
|
||||||
|
while (m->led_th_run) {
|
||||||
|
inst_led_state state;
|
||||||
|
|
||||||
|
amutex_lock(m->led_lock);
|
||||||
|
state = m->current_led_state;
|
||||||
|
amutex_unlock(m->led_lock);
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case inst_led_cal_wait:
|
||||||
|
/* White flashing: 500ms ON / 500ms OFF (1.0 Hz) */
|
||||||
|
if (phase % 2 == 0)
|
||||||
|
i1pro2_indLEDset(p, 0x3F); /* White = both Red+Green+Blue */
|
||||||
|
else
|
||||||
|
i1pro2_indLEDoff(p);
|
||||||
|
led_sleep_ms(m, inst_led_cal_wait, 500);
|
||||||
|
phase++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case inst_led_row_ready:
|
||||||
|
/* Blue pulsing: 300ms ON / 700ms OFF (1.0 Hz) */
|
||||||
|
i1pro2_indLEDset(p, 0x24); /* Blue = both Left & Right Blue */
|
||||||
|
led_sleep_ms(m, inst_led_row_ready, 300);
|
||||||
|
i1pro2_indLEDoff(p);
|
||||||
|
led_sleep_ms(m, inst_led_row_ready, 700);
|
||||||
|
phase = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case inst_led_row_fail:
|
||||||
|
/* Red rapid strobe: 3 short bursts (100ms ON / 100ms OFF, 600ms total) */
|
||||||
|
for (i = 0; i < 3 && m->led_th_run; i++) {
|
||||||
|
i1pro2_indLEDset(p, 0x09); /* Red = both Left & Right Red */
|
||||||
|
msec_sleep(100);
|
||||||
|
i1pro2_indLEDoff(p);
|
||||||
|
msec_sleep(100);
|
||||||
|
}
|
||||||
|
/* Revert to off until next command */
|
||||||
|
amutex_lock(m->led_lock);
|
||||||
|
if (m->current_led_state == inst_led_row_fail)
|
||||||
|
m->current_led_state = inst_led_off;
|
||||||
|
amutex_unlock(m->led_lock);
|
||||||
|
phase = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case inst_led_row_success:
|
||||||
|
/* Green pulse: Solid confirmation illumination for 400ms */
|
||||||
|
i1pro2_indLEDset(p, 0x12); /* Green = both Left & Right Green */
|
||||||
|
msec_sleep(400);
|
||||||
|
i1pro2_indLEDoff(p);
|
||||||
|
|
||||||
|
/* Revert to off until next command */
|
||||||
|
amutex_lock(m->led_lock);
|
||||||
|
if (m->current_led_state == inst_led_row_success)
|
||||||
|
m->current_led_state = inst_led_off;
|
||||||
|
amutex_unlock(m->led_lock);
|
||||||
|
phase = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case inst_led_off:
|
||||||
|
default:
|
||||||
|
i1pro2_indLEDoff(p);
|
||||||
|
led_sleep_ms(m, inst_led_off, 100);
|
||||||
|
phase = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Extinguish LEDs upon thread exit if port is still open */
|
||||||
|
if (p->icom != NULL && p->icom->is_open)
|
||||||
|
i1pro2_indLEDoff(p);
|
||||||
|
|
||||||
|
a1logd(p->log, 3, "i1pro2_led_thread exiting\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set indicator LED status */
|
||||||
|
i1pro_code
|
||||||
|
i1pro_imp_set_led_state(i1pro *p, inst_led_state state) {
|
||||||
|
i1proimp *m;
|
||||||
|
|
||||||
|
if (p == NULL || p->m == NULL)
|
||||||
|
return I1PRO_INT_NO_COMS;
|
||||||
|
m = (i1proimp *)p->m;
|
||||||
|
|
||||||
|
if (p->dtype != instI1Pro2)
|
||||||
|
return I1PRO_UNSUPPORTED;
|
||||||
|
|
||||||
|
if (!m->led_th_init) {
|
||||||
|
amutex_init(m->led_lock);
|
||||||
|
m->led_th_init = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
amutex_lock(m->led_lock);
|
||||||
|
m->current_led_state = state;
|
||||||
|
amutex_unlock(m->led_lock);
|
||||||
|
|
||||||
|
/* If thread is not yet running and state is not off, start worker thread */
|
||||||
|
if (m->led_th == NULL && state != inst_led_off) {
|
||||||
|
m->led_th_run = 1;
|
||||||
|
if ((m->led_th = new_athread(i1pro2_led_thread, (void *)p)) == NULL) {
|
||||||
|
a1logd(p->log, 1, "i1pro_imp_set_led_state: new_athread failed\n");
|
||||||
|
return I1PRO_INT_THREADFAILED;
|
||||||
|
}
|
||||||
|
} else if (state == inst_led_off && m->led_th == NULL) {
|
||||||
|
/* Directly extinguish LEDs if port is open */
|
||||||
|
if (p->icom != NULL && p->icom->is_open)
|
||||||
|
i1pro2_indLEDoff(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
return I1PRO_OK;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef NEVER
|
#ifdef NEVER
|
||||||
|
|
||||||
// ~~99 play with LED settings
|
// ~~99 play with LED settings
|
||||||
|
|||||||
@@ -340,6 +340,13 @@ struct _i1proimp {
|
|||||||
volatile double whitestamp; /* meas_delay() white timestamp */
|
volatile double whitestamp; /* meas_delay() white timestamp */
|
||||||
volatile double trigstamp; /* meas_delay() trigger timestamp */
|
volatile double trigstamp; /* meas_delay() trigger timestamp */
|
||||||
|
|
||||||
|
/* Visual LED feedback thread management */
|
||||||
|
athread *led_th;
|
||||||
|
int led_th_run;
|
||||||
|
int led_th_init;
|
||||||
|
amutex led_lock;
|
||||||
|
inst_led_state current_led_state;
|
||||||
|
|
||||||
}; typedef struct _i1proimp i1proimp;
|
}; typedef struct _i1proimp i1proimp;
|
||||||
|
|
||||||
/* Add an implementation structure */
|
/* Add an implementation structure */
|
||||||
@@ -348,6 +355,9 @@ i1pro_code add_i1proimp(i1pro *p);
|
|||||||
/* Destroy implementation structure */
|
/* Destroy implementation structure */
|
||||||
void del_i1proimp(i1pro *p);
|
void del_i1proimp(i1pro *p);
|
||||||
|
|
||||||
|
/* Close instrument (stop threads, update log, turn off LEDs, close coms) */
|
||||||
|
i1pro_code i1pro_close_port(i1pro *p);
|
||||||
|
|
||||||
/* ============================================================ */
|
/* ============================================================ */
|
||||||
/* Error codes returned from i1pro_imp */
|
/* Error codes returned from i1pro_imp */
|
||||||
|
|
||||||
@@ -532,6 +542,8 @@ i1pro_code i1pro_set_stdres(i1pro *p);
|
|||||||
/* Modify the scan consistency tollerance */
|
/* Modify the scan consistency tollerance */
|
||||||
i1pro_code i1pro_set_scan_toll(i1pro *p, double toll_ratio);
|
i1pro_code i1pro_set_scan_toll(i1pro *p, double toll_ratio);
|
||||||
|
|
||||||
|
/* Set device indicator LED status */
|
||||||
|
i1pro_code i1pro_imp_set_led_state(i1pro *p, inst_led_state state);
|
||||||
|
|
||||||
/* Update the single remission calibration and instrument usage log */
|
/* Update the single remission calibration and instrument usage log */
|
||||||
i1pro_code i1pro_update_log(i1pro *p);
|
i1pro_code i1pro_update_log(i1pro *p);
|
||||||
|
|||||||
@@ -589,6 +589,11 @@ static inst_config config_enum(inst *p, int ec) {
|
|||||||
return inst_conf_unknown;
|
return inst_conf_unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set device indicator LED status (default implementation) */
|
||||||
|
static inst_code set_led_state(inst *p, inst_led_state state) {
|
||||||
|
return inst_unsupported;
|
||||||
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------- */
|
/* ---------------------------------------------- */
|
||||||
|
|
||||||
/* Delete things set/done by new_inst() */
|
/* Delete things set/done by new_inst() */
|
||||||
@@ -824,6 +829,8 @@ void *cntx /* Context for callback */
|
|||||||
p->last_scomerr = last_scomerr;
|
p->last_scomerr = last_scomerr;
|
||||||
if (p->config_enum == NULL)
|
if (p->config_enum == NULL)
|
||||||
p->config_enum = config_enum;
|
p->config_enum = config_enum;
|
||||||
|
if (p->set_led_state == NULL)
|
||||||
|
p->set_led_state = set_led_state;
|
||||||
|
|
||||||
/* Set the provided user interaction callback */
|
/* Set the provided user interaction callback */
|
||||||
p->set_uicallback(p, uicallback, cntx);
|
p->set_uicallback(p, uicallback, cntx);
|
||||||
|
|||||||
@@ -371,6 +371,9 @@ typedef enum {
|
|||||||
|
|
||||||
} inst2_capability;
|
} inst2_capability;
|
||||||
|
|
||||||
|
/* Capability alias for instrument indicator LED status feedback */
|
||||||
|
#define INST_CAP_LED_STATUS inst2_has_leds
|
||||||
|
|
||||||
/* Instrument capabilities 3 (room for expansion) */
|
/* Instrument capabilities 3 (room for expansion) */
|
||||||
/* (Available capabilities may be mode dependent) */
|
/* (Available capabilities may be mode dependent) */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -558,6 +561,15 @@ typedef enum {
|
|||||||
|
|
||||||
} inst_opt_type;
|
} inst_opt_type;
|
||||||
|
|
||||||
|
/* Generic Instrument LED Status States */
|
||||||
|
typedef enum {
|
||||||
|
inst_led_off = 0,
|
||||||
|
inst_led_cal_wait = 1, /* Flashing White */
|
||||||
|
inst_led_row_ready = 2, /* Flashing Blue */
|
||||||
|
inst_led_row_fail = 3, /* Flashing Red */
|
||||||
|
inst_led_row_success = 4 /* Solid/Flash Green */
|
||||||
|
} inst_led_state;
|
||||||
|
|
||||||
/* Optional manufacturers instrument filter fitted to instrument (for inst_opt_set_filter) */
|
/* Optional manufacturers instrument filter fitted to instrument (for inst_opt_set_filter) */
|
||||||
/* These could be physical (i.e. Spectrolino, i1Pro3), or they could be virtual (i.e. i1Pro3) */
|
/* These could be physical (i.e. Spectrolino, i1Pro3), or they could be virtual (i.e. i1Pro3) */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -1170,6 +1182,9 @@ typedef struct _inst_meascondsel {
|
|||||||
/* (This is used for deciding fallback/retry strategies) */ \
|
/* (This is used for deciding fallback/retry strategies) */ \
|
||||||
int (*last_scomerr)(struct _inst *p); \
|
int (*last_scomerr)(struct _inst *p); \
|
||||||
\
|
\
|
||||||
|
/* Set device indicator LED status (if supported) */ \
|
||||||
|
inst_code (*set_led_state)(struct _inst *p, inst_led_state state); \
|
||||||
|
\
|
||||||
/* Destroy ourselves */ \
|
/* Destroy ourselves */ \
|
||||||
void (*del)(struct _inst *p); \
|
void (*del)(struct _inst *p); \
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user