diff --git a/README.md b/README.md index e024158..31e54ed 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Streams analog input data from [Measurement Computing](https://www.mccdaq.com/) - Continuous hardware-paced acquisition via `ulAInScan` (no dropped samples) - **Scaled mode**: calibrated voltage output as `cf_float32` -- **Raw mode**: integer ADC counts matching device resolution (`cf_int16` for 12/16-bit, `cf_int32` for 18/24-bit) +- **Raw mode**: integer ADC counts matching device resolution (`cf_int16` for 12/16-bit, `cf_int32` for 18/24-bit), offset by the midpoint (0V = 0). - LSL stream metadata includes voltage range, resolution, and scaling coefficients for offline reconstruction - Automatic FIFO overrun recovery (restarts scan transparently on USB scheduling delays) - Per-device capability queries: supported voltage ranges, resolution, max scan rate @@ -145,7 +145,7 @@ Options: --high-chan N High channel (default: 5) -r, --rate RATE Sample rate in Hz (default: 16384) --range VALUE Voltage range (uldaq Range enum value, default: auto) - --raw Output raw integer ADC counts instead of scaled voltage + --raw Output raw integer ADC instead of scaled voltage ``` Examples: @@ -160,7 +160,7 @@ MCCOutletCLI --list-ranges -d 0 # Stream 6 channels at 16384 Hz (scaled voltage) MCCOutletCLI -d 0 --low-chan 0 --high-chan 5 --rate 16384 -# Stream raw ADC counts +# Stream raw ADC integers MCCOutletCLI --raw --device-name USB-1608FS # Use a config file @@ -192,14 +192,14 @@ Outputs calibrated voltage as `cf_float32`. Channel units are volts (`V`). ### Raw Mode (`--raw`) -Outputs uncalibrated ADC counts. The LSL channel format is selected based on the device's ADC resolution: +Outputs uncalibrated ADC offset by midpoint (0=0). The LSL channel format is selected based on the device's ADC resolution: -| ADC Resolution | LSL Format | Value Range | -|----------------|-------------|---------------------| -| 12-bit | `cf_int16` | 0 - 4095 | -| 16-bit | `cf_int16` | 0 - 65535 | -| 18-bit | `cf_int32` | 0 - 262143 | -| 24-bit | `cf_int32` | 0 - 16777215 | +| ADC Resolution | LSL Format | Value Range | +|----------------|-------------|-----------------------| +| 12-bit | `cf_int16` | -2048 - 2047 | +| 16-bit | `cf_int16` | -32768 - 32767 | +| 18-bit | `cf_int32` | -116072 - 116071 | +| 24-bit | `cf_int32` | -83886078 - 83886077 | ### Stream Metadata diff --git a/src/cli/main.cpp b/src/cli/main.cpp index 8e6214f..d7a7b2c 100644 --- a/src/cli/main.cpp +++ b/src/cli/main.cpp @@ -39,7 +39,7 @@ void printUsage(const char* program_name) { << " --high-chan N High channel (default: 7)\n" << " -r, --rate RATE Sample rate in Hz (default: 44100)\n" << " --range VALUE Voltage range (uldaq Range enum value, default: auto)\n" - << " --raw Output raw integer ADC counts instead of scaled voltage\n" + << " --raw Output raw integer ADC integers instead of scaled voltage\n" << "\n" << "Examples:\n" << " " << program_name << " --list-devices\n" diff --git a/src/core/include/mccoutlet/Config.hpp b/src/core/include/mccoutlet/Config.hpp index d7f6cf0..6994135 100644 --- a/src/core/include/mccoutlet/Config.hpp +++ b/src/core/include/mccoutlet/Config.hpp @@ -21,7 +21,7 @@ struct AppConfig { int high_channel = 5; double sample_rate = 16384.0; int range = -1; ///< uldaq Range enum value, -1 = auto-select first - bool scaled = true; ///< true = calibrated voltage, false = raw ADC counts + bool scaled = true; ///< true = calibrated voltage, false = raw ADC integers }; class ConfigManager { diff --git a/src/core/include/mccoutlet/Device.hpp b/src/core/include/mccoutlet/Device.hpp index a19124c..c73b024 100644 --- a/src/core/include/mccoutlet/Device.hpp +++ b/src/core/include/mccoutlet/Device.hpp @@ -112,7 +112,7 @@ class MCCDevice : public IDevice { int high_channel = 7; double sample_rate = 44100.0; int range = -1; ///< uldaq Range enum value, -1 = auto-select first - bool scaled = true; ///< true = calibrated voltage (float), false = raw ADC counts (int) + bool scaled = true; ///< true = calibrated voltage (float), false = raw ADC (int) }; using StatusCallback = std::function; diff --git a/src/core/src/Device.cpp b/src/core/src/Device.cpp index 4ce096e..e017781 100644 --- a/src/core/src/Device.cpp +++ b/src/core/src/Device.cpp @@ -537,9 +537,11 @@ bool MCCDevice::getDataInt32(std::vector& buffer, double& timestamp) { size_t read_offset = (static_cast(scans_read_) * channelCount) % total_buffer_elements; + const int64_t mid = 1LL << (capabilities_.resolution_bits - 1); for (size_t i = 0; i < num_elements; ++i) { - buffer[i] = static_cast( + auto raw = static_cast( scan_buffer_[(read_offset + i) % total_buffer_elements]); + buffer[i] = static_cast(raw - mid); } scans_read_ += available; @@ -581,9 +583,11 @@ bool MCCDevice::getDataInt16(std::vector& buffer, double& timestamp) { size_t read_offset = (static_cast(scans_read_) * channelCount) % total_buffer_elements; + const int32_t mid = 1 << (capabilities_.resolution_bits - 1); for (size_t i = 0; i < num_elements; ++i) { - buffer[i] = static_cast( + auto raw = static_cast( scan_buffer_[(read_offset + i) % total_buffer_elements]); + buffer[i] = static_cast(raw - mid); } scans_read_ += available; diff --git a/src/core/src/LSLOutlet.cpp b/src/core/src/LSLOutlet.cpp index 966b860..4c2a7da 100644 --- a/src/core/src/LSLOutlet.cpp +++ b/src/core/src/LSLOutlet.cpp @@ -40,7 +40,7 @@ LSLOutlet::LSLOutlet(const DeviceInfo& info) double full_scale = std::pow(2.0, info.resolution_bits); double span = info.range_max - info.range_min; double slope = span / full_scale; - double offset = info.range_min; + double offset = (info.range_min + info.range_max) / 2.0; acq.append_child_value("scaling_slope", std::to_string(slope)); acq.append_child_value("scaling_offset", std::to_string(offset)); } diff --git a/src/gui/MainWindow.ui b/src/gui/MainWindow.ui index af33b38..ff95aaf 100644 --- a/src/gui/MainWindow.ui +++ b/src/gui/MainWindow.ui @@ -180,7 +180,7 @@ - Raw (Integer Counts) + Raw (Integer)