Getting Started with C/C++#
C/C++ tutorial — Learn to connect, configure, and acquire EEG data using the DSI API in C/C++.
Table of Contents#
Prerequisites#
Required Components#
DSI API library (
DSI.dll/DSI.so/DSI.dylib)Header file (
DSI.h)API loader (
DSI_API_Loader.c)C/C++ compiler
Important: Before using any DSI API functions, you must:
Add
DSI_API_Loader.cto your projectCall
Load_DSI_API(NULL)at program startupCheck the return value (0 = success, non-zero = error)
Platform-Specific Requirements#
Windows:
Visual Studio 2015+ or MinGW
DSI.dllandDSI.lib
Linux:
GCC 4.8+, GLIBC 2.14+
USB permissions configured
DSI.so
macOS:
Xcode Command Line Tools
DSI.dylib
Quick Start#
This minimal example demonstrates the essential steps to connect to a headset, configure channels, and acquire data. Copy this code to get started quickly, then explore the detailed tutorials below for more information.
#include "DSI.h"
#include <stdio.h>
int main() {
// Load the API (must be first!)
if (Load_DSI_API(NULL) != 0) {
fprintf(stderr, "Failed to load DSI API\n");
return 1;
}
// Create and connect to headset
DSI_Headset h = DSI_Headset_New(NULL);
DSI_Headset_Connect(h, NULL); // NULL uses DSISerialPort env variable
if (!h || DSI_Error()) {
fprintf(stderr, "Error: %s\n", DSI_ClearError());
return 1;
}
printf("Connected!\n");
// Configure channels (montage)
// Using "" for reference uses the default linked ears reference
DSI_Headset_ChooseChannels(h, "P3,Pz,P4", "", 1);
// Start acquisition
DSI_Headset_StartDataAcquisition(h);
// Collect data
DSI_Channel pz = DSI_Headset_GetChannelByName(h, "Pz");
for (int i = 0; i < 10; i++) {
DSI_Headset_Idle(h, 0.1); // Process for 100ms
// Read latest value
double value = DSI_Channel_GetSignal(pz);
printf("Sample %d: Pz = %.2f µV\n", i, value);
}
// Cleanup
DSI_Headset_StopDataAcquisition(h);
DSI_Headset_Delete(h);
return 0;
}
Compiling#
Windows (Visual Studio):
cl quick_start.c DSI_API_Loader.c DSI.lib
Linux:
gcc quick_start.c DSI_API_Loader.c -L. -lDSI -ldl -o quick_start
macOS:
clang quick_start.c DSI_API_Loader.c -L. -lDSI -o quick_start
Tutorial 1: Basic Connection#
This tutorial walks through establishing a connection to your DSI headset. You’ll learn how to properly initialize the API, specify serial ports, create headset objects, and handle errors.
Step 0: Load the API#
Before calling any DSI functions, you must load the dynamic library. This step locates the platform-specific library file and imports all API functions into your program’s memory space.
#include "DSI.h"
int main() {
// Load the DSI API library
if (Load_DSI_API(NULL) != 0) {
fprintf(stderr, "Failed to load DSI API\n");
return 1;
}
// Now you can use DSI functions...
}
What Load_DSI_API does:
Locates and loads the platform-specific dynamic library (
DSI.dll,DSI.so, orDSI.dylib)Imports all DSI API functions
Returns 0 on success, negative if library not found, positive if function import failed
Note: You must add DSI_API_Loader.c to your project for this function to be available.
Step 1: Include the API#
Include the DSI header file and standard C libraries needed for your application. The DSI.h header defines all API functions and data types.
#include "DSI.h"
#include <stdio.h>
#include <stdlib.h>
Step 2: Specify Port or Use Environment Variable#
The serial port identifier varies by platform and connection method. You can specify it directly or use an environment variable for flexibility across different systems.
Port specification by platform:
Windows: COM ports (e.g.,
COM4,COM5,COM6)Linux:
/dev/ttyUSB0,/dev/ttyUSB1,/dev/ttyACM0,/dev/ttyACM1macOS:
/dev/cu.DSI24-xxxxx-BluetoothSerialor/dev/tty.usbserial-xxxxxEnvironment variable: Set
DSISerialPortand passNULL
// Option 1: Use environment variable (set DSISerialPort)
const char* port = NULL; // NULL uses DSISerialPort env variable
// Option 2: Specify port directly
#ifdef _WIN32
port = "COM4"; // Windows
#elif defined(__APPLE__)
port = "/dev/cu.DSI24-023-BluetoothSerial"; // macOS
#else
port = "/dev/ttyUSB0"; // Linux
#endif
printf("Using port: %s\n", port ? port : "from DSISerialPort env var");
Step 3: Create and Connect Headset Object#
Creating and connecting involves two separate steps: first allocate the headset object, then establish the serial connection. Always check for errors after each step.
// Create headset object (does not connect yet)
DSI_Headset h = DSI_Headset_New(NULL);
if (!h) {
fprintf(stderr, "Failed to create headset: %s\n", DSI_ClearError());
return 1;
}
// Connect to the serial port
DSI_Headset_Connect(h, port);
if (DSI_Error()) {
fprintf(stderr, "Failed to connect: %s\n", DSI_ClearError());
DSI_Headset_Delete(h);
return 1;
}
What happens during connection:
DSI_Headset_New(NULL)allocates the headset objectDSI_Headset_Connect(h, port)opens serial portQueries hardware model and firmware
Initializes communication
Step 4: Verify Connection#
if (!DSI_Headset_IsConnected(h)) {
fprintf(stderr, "Not connected!\n");
DSI_Headset_Delete(h);
return 1;
}
// Get device information
printf("%s\n", DSI_Headset_GetInfoString(h));
Step 5: Error Handling#
Always check for errors after critical operations. See Error Codes for a complete reference.
// ALWAYS check for errors after critical operations
DSI_Headset h = DSI_Headset_New(NULL);
if (!h || DSI_Error()) {
fprintf(stderr, "Failed to create headset: %s\n", DSI_ClearError());
return 1;
}
DSI_Headset_Connect(h, port);
if (DSI_Error()) {
fprintf(stderr, "Connection failed: %s\n", DSI_ClearError());
DSI_Headset_Delete(h);
return 1;
}
// Optional: Set error callback for automatic logging
int errorCallback(const char* msg, int level) {
fprintf(stderr, "[Level %d] %s\n", level, msg);
return 1; // Continue execution
}
DSI_SetErrorCallback(errorCallback);
Complete Connection Example#
int connectToHeadset(DSI_Headset* pHeadset, const char* port) {
// Create headset object
DSI_Headset h = DSI_Headset_New(NULL);
if (!h) {
fprintf(stderr, "Failed to create headset\n");
return 0;
}
// Connect to serial port (NULL uses DSISerialPort env variable)
DSI_Headset_Connect(h, port);
if (DSI_Error()) {
fprintf(stderr, "Connection failed: %s\n", DSI_ClearError());
DSI_Headset_Delete(h);
return 0;
}
// Verify connection
if (!DSI_Headset_IsConnected(h)) {
fprintf(stderr, "Connection verification failed\n");
DSI_Headset_Delete(h);
return 0;
}
// Get device info
printf("%s\n", DSI_Headset_GetInfoString(h));
*pHeadset = h;
return 1;
}
Tutorial 2: Channel Configuration#
Channel configuration (also called montage selection) determines which electrodes to record from and how to reference them. This tutorial covers listing available electrodes, choosing references, and configuring both referential and bipolar montages.
Understanding Montages#
A montage defines which electrodes to use and how to reference them.
Syntax: "electrode1,electrode2,electrode3"
Common montage examples:
"P3,Pz,P4,O1,O2"— Five posterior channels"Fp1,Fp2,F3,F4,C3,C4"— Frontal and central channels"@1,@2,@3,@4"— First four sensors (numbered indexing)
Available channels by model:
DSI-24: Fp1, Fp2, Fz, F3, F4, F7, F8, Cz, C3, C4, T7/T3, T8/T4, Pz, P3, P4, P7/T5, P8/T6, O1, O2, A1, A2
DSI-7: F3, F4, C3, C4, P3, Pz, P4, LE
DSI-VR300: FCz, Pz, P3, P4, PO7, PO8, Oz, LE
Step 1: List Available Sources#
Before configuring channels, it’s helpful to see which electrodes are available on your headset. Sources represent individual sensors that can be combined into channels.
// Iterate through all sources to see what's available
int nSources = DSI_Headset_GetNumberOfSources(h);
printf("Total sources: %d\n", nSources);
for (int i = 0; i < nSources; i++) {
DSI_Source src = DSI_Headset_GetSourceByIndex(h, i);
printf("%d: %s\n", i, DSI_Source_GetName(src));
}
Step 2: Choose Reference#
The reference electrode determines the baseline for measuring voltage. By default, the API automatically uses linked ears (A1/2+A2/2 on DSI-24, LE on DSI-7/VR300) as the reference. You only need to call reference functions if you want to change from this default.
Default Reference (Automatic)#
No API calls needed - just pass empty string "" or NULL to ChooseChannels():
// Uses default linked ears automatically
DSI_Headset_ChooseChannels(h, "P3,Pz,P4", "", 1);
Default reference by model:
DSI-24:
A1/2+A2/2(average of A1 and A2 channels)DSI-7:
LE(pre-averaged linked ear channel)DSI-VR300:
LE(pre-averaged linked ear channel)
Change to Hardware Reference#
To use the hardware/factory reference instead of linked ears:
// Option 1: Use "FACTORY" keyword
DSI_Headset_SetDefaultReference(h, "FACTORY", 1);
DSI_Headset_ChooseChannels(h, "P3,Pz,P4", "", 1);
// Option 2: Specify hardware reference electrode directly
DSI_Headset_ChooseChannels(h, "P3,Pz,P4", "Pz", 1); // DSI-24/DSI-7
DSI_Headset_ChooseChannels(h, "P3,Pz,P4", "P4", 1); // VR300
Hardware reference by model:
DSI-24:
PzDSI-7:
PzDSI-VR300:
P4
Change to Custom Reference#
To use any electrode as reference (e.g., P3, Cz):
// Option 1: Set default reference, then configure channels
DSI_Headset_SetDefaultReference(h, "P3", 1);
DSI_Headset_ChooseChannels(h, "Pz,P4,O1,O2", "", 1);
// Option 2: Specify directly in ChooseChannels
DSI_Headset_ChooseChannels(h, "Pz,P4,O1,O2", "P3", 1);
To check which reference is active:
const char* ref = DSI_Headset_GetReferenceString(h);
printf("Current reference: %s\n", ref);
Step 3: Configure Channels#
After choosing your montage and reference, configure the channels using ChooseChannels(). This function validates electrode names and sets up the signal processing pipeline.
// ChooseChannels(headset, montage, reference, autoswap)
// Recommended: Use empty string for default linked ear reference
DSI_Headset_ChooseChannels(h, "P3,Pz,P4,O1,O2", "", 1);
// To use hardware reference instead, specify electrode explicitly:
// DSI_Headset_ChooseChannels(h, "P3,Pz,P4,O1,O2", "Pz", 1); // DSI-24/DSI-7
// DSI_Headset_ChooseChannels(h, "P3,Pz,P4,O1,O2", "P4", 1); // VR300
if (DSI_Error()) {
fprintf(stderr, "Montage error: %s\n", DSI_ClearError());
// Troubleshoot: List available sources
fprintf(stderr, "Available sources:\n");
int nSources = DSI_Headset_GetNumberOfSources(h);
for (int i = 0; i < nSources; i++) {
DSI_Source src = DSI_Headset_GetSourceByIndex(h, i);
fprintf(stderr, " %s\n", DSI_Source_GetName(src));
}
return 0;
}
// Verify configuration
printf("Configured %d channels\n", DSI_Headset_GetNumberOfChannels(h));
Parameters:
montage— Comma-separated electrode namesreference— Reference electrode(s) specificationautoswap— Automatically swap signal/reference if needed (use1)
Step 4: Inspect Channels#
After configuration, iterate through channels to verify your montage. Channel properties help you distinguish EEG signals from triggers and auxiliary inputs.
int nChannels = DSI_Headset_GetNumberOfChannels(h);
for (int i = 0; i < nChannels; i++) {
DSI_Channel ch = DSI_Headset_GetChannelByIndex(h, i);
printf("Channel %d: %s", i, DSI_Channel_GetName(ch));
if (DSI_Channel_IsReferentialEEG(ch)) {
printf(" (EEG)");
}
if (DSI_Channel_IsTrigger(ch)) {
printf(" (Trigger)");
}
printf("\n");
}
Step 5: Access Channels by Name#
Accessing channels by name makes code more readable and maintainable than using indices. The function returns NULL if the channel doesn’t exist.
// Preferred: Access by name
DSI_Channel pz = DSI_Headset_GetChannelByName(h, "Pz");
if (!pz) {
fprintf(stderr, "Channel 'Pz' not found\n");
} else {
printf("Found channel: %s\n", DSI_Channel_GetName(pz));
}
// Alternative: Access by index
DSI_Channel ch0 = DSI_Headset_GetChannelByIndex(h, 0);
Advanced: Bipolar Montages#
// Bipolar: Each channel is difference between two electrodes
// Syntax: "electrode1-electrode2"
DSI_Headset_ChooseChannels(h, "Fp1-F3,F3-C3,C3-P3,P3-O1", "", 1);
// This creates 4 channels:
// - Fp1-F3 (voltage at Fp1 minus voltage at F3)
// - F3-C3
// - C3-P3
// - P3-O1
Complete Montage Example#
int configureMontage(DSI_Headset h) {
// Configure a standard posterior montage
const char* montage = "P3,Pz,P4,O1,O2";
const char* reference = ""; // Default linked ears
printf("Montage: %s\n", montage);
printf("Reference: %s\n", reference);
DSI_Headset_ChooseChannels(h, montage, reference, 1);
if (DSI_Error()) {
fprintf(stderr, "Montage failed: %s\n", DSI_ClearError());
return 0;
}
printf("Configured %d channels\n",
DSI_Headset_GetNumberOfChannels(h));
return 1;
}
Tutorial 3: Data Acquisition#
Once your headset is connected and channels are configured, you can start acquiring EEG data. This tutorial covers sampling rate configuration, buffer management, starting/stopping acquisition, and reading data from channels.
Step 1: Configure Sampling#
// Set sampling rate and filter mode
// DSI_Headset_ConfigureADC(h, samplesPerSecond, filterMode)
// NOTE: The default sampling rate is 300 Hz. If the SampleRate feature is unlocked,
// all DSI headsets can configure rates up to 600 Hz. Check feature availability first:
if (DSI_Headset_GetFeatureAvailability(h, "SampleRate")) {
printf("Custom sampling rates are available (up to 600 Hz)\n");
DSI_Headset_ConfigureADC(h, 600, 0); // Use 600 Hz when unlocked
} else {
printf("Using default sampling rate of 300 Hz (feature not unlocked)\n");
DSI_Headset_ConfigureADC(h, 300, 0); // Default 300 Hz
}
// Verify actual sampling rate
double fs = DSI_Headset_GetSamplingRate(h);
printf("Sampling rate: %.0f Hz\n", fs);
Filter modes:
0- No filtering (default)1- Low-pass filter2- High-pass filter3- Band-pass filter
Step 2: Understanding Buffers#
// Channel buffers are allocated automatically when you configure channels.
// The default buffer size is sufficient for most real-time applications.
// Manual buffer reallocation is only needed if:
// 1. You need to store more than a few seconds of data
// 2. You're using custom processing stages that require larger lookback windows
// Example: Allocate 10 seconds for signal, 5 seconds for impedance
DSI_Headset_ReallocateBuffers(h, 10.0, 5.0);
// Check buffer status during acquisition
size_t buffered = DSI_Headset_GetNumberOfBufferedSamples(h);
printf("Buffered samples: %zu\n", buffered);
Step 3: Start Acquisition#
DSI_Headset_StartDataAcquisition(h);
if (DSI_Error()) {
fprintf(stderr, "Failed to start acquisition: %s\n",
DSI_ClearError());
return 0;
}
printf("Acquisition started\n");
Step 4: Receive Data#
double fs = DSI_Headset_GetSamplingRate(h);
double blockDuration = 0.5; // 0.5 second blocks
while (acquiring) {
// Process events and receive data for specified time
DSI_Headset_Idle(h, blockDuration);
if (DSI_Error()) {
fprintf(stderr, "Error: %s\n", DSI_ClearError());
}
// Read buffered data from each channel
int nChannels = DSI_Headset_GetNumberOfChannels(h);
for (int i = 0; i < nChannels; i++) {
DSI_Channel ch = DSI_Headset_GetChannelByIndex(h, i);
// Get number of buffered samples
size_t buffered = DSI_Channel_GetNumberOfBufferedSamples(ch);
// Read buffered samples one at a time
for (size_t j = 0; j < buffered; j++) {
double value = DSI_Channel_ReadBuffered(ch);
processData(DSI_Channel_GetName(ch), value);
}
}
}
Step 5: Stop Acquisition#
DSI_Headset_StopDataAcquisition(h);
printf("Acquisition stopped\n");
Complete Acquisition Example#
void acquireData(DSI_Headset h, double durationSeconds) {
double blockDuration = 0.1; // 100ms blocks
int numBlocks = (int)(durationSeconds / blockDuration);
printf("Acquiring %.1f seconds of data...\n", durationSeconds);
// Start acquisition
DSI_Headset_StartDataAcquisition(h);
if (DSI_Error()) {
fprintf(stderr, "Start failed: %s\n", DSI_ClearError());
return;
}
// Collect data blocks
for (int block = 0; block < numBlocks; block++) {
DSI_Headset_Idle(h, blockDuration);
// Show progress
if (block % 10 == 0) {
printf("Progress: %.0f%%\r",
100.0 * block / numBlocks);
fflush(stdout);
}
// Check for errors/alarms
if (DSI_Error()) {
fprintf(stderr, "\nError: %s\n", DSI_ClearError());
}
if (DSI_Headset_GetNumberOfAlarms(h) > 0) {
int alarm = DSI_Headset_GetAlarm(h, 1); // 1 = remove from queue
fprintf(stderr, "\nAlarm: %d\n", alarm);
}
}
printf("\nAcquisition complete\n");
DSI_Headset_StopDataAcquisition(h);
}
Tutorial 4: Background Acquisition#
Background acquisition runs data collection in a separate thread, freeing your main application to perform other tasks (UI updates, analysis, etc.). This tutorial shows how to set up callbacks that execute automatically when new data arrives.
Step 1: Set Sample Callback#
void mySampleCallback(DSI_Headset h, double packetTime, void* userData) {
// This function is called automatically when new data arrives
// userData can be used to pass application-specific data to the callback
// Get first channel
DSI_Channel ch = DSI_Headset_GetChannelByIndex(h, 0);
// Read buffered sample (callback context - samples are buffered)
double value = DSI_Channel_ReadBuffered(ch);
printf("New sample: %.2f µV (time: %.3f)\n", value, packetTime);
}
}
// Register callback (NULL for userData if not needed)
DSI_Headset_SetSampleCallback(h, mySampleCallback, NULL);
Step 2: Start Background Acquisition#
if (!DSI_Headset_StartBackgroundAcquisition(h) || DSI_Error()) {
fprintf(stderr, "Background acquisition failed: %s\n",
DSI_ClearError());
return 0;
}
printf("Background acquisition running...\n");
Step 3: Application Continues#
// Your application can continue other work
// Data collection happens in background thread
for (int i = 0; i < 100; i++) {
// Do other work
printf("Main loop iteration %d\n", i);
DSI_Headset_Idle(h, 0.1); // Process events for 100ms
// Check buffer status
int buffered = DSI_Headset_GetNumberOfBufferedSamples(h);
printf(" Buffered samples: %d\n", buffered);
}
Step 4: Stop Background Acquisition#
DSI_Headset_StopBackgroundAcquisition(h);
printf("Background acquisition stopped\n");
Complete Background Acquisition Example#
// Global flag to control acquisition
volatile int g_acquiring = 1;
void sampleCallback(DSI_Headset h, double packetTime, void* userData) {
static int sampleCount = 0;
sampleCount++;
// Get channel data
DSI_Channel pz = DSI_Headset_GetChannelByName(h, "Pz");
if (pz) {
double value = DSI_Channel_ReadBuffered(pz);
// Print every 100 samples
if (sampleCount % 100 == 0) {
printf("Sample %d: Pz = %.2f µV\n", sampleCount, value);
}
}
}
int main() {
DSI_Headset h = /* ... connect and configure ... */;
// Set callback and start (NULL for userData)
DSI_Headset_SetSampleCallback(h, sampleCallback, NULL);
DSI_Headset_StartBackgroundAcquisition(h);
printf("Acquiring... Press Ctrl+C to stop\n");
// Main loop: monitor health
while (g_acquiring) {
DSI_Headset_Idle(h, 5.0); // Process events for 5 seconds
// Check for overflow
int overflow = DSI_Headset_GetNumberOfOverflowedSamples(h);
if (overflow > 0) {
fprintf(stderr, "WARNING: %d samples lost!\n", overflow);
}
// Check for alarms
while (DSI_Headset_GetNumberOfAlarms(h) > 0) {
int alarm = DSI_Headset_GetAlarm(h, 1); // 1 = remove from queue
fprintf(stderr, "Alarm: %d\n", alarm);
}
}
DSI_Headset_StopBackgroundAcquisition(h);
DSI_Headset_Delete(h);
return 0;
}
Common Tasks#
These practical examples demonstrate frequently needed operations: saving data to files, checking electrode impedances, and monitoring battery levels.
Task: Save Data to CSV File#
Exporting EEG data to CSV format enables analysis in tools like MATLAB, Python, or Excel. This example writes time-synchronized samples with proper column headers.
void saveToCSV(DSI_Headset h, const char* filename, double duration) {
FILE* f = fopen(filename, "w");
if (!f) {
fprintf(stderr, "Cannot open %s\n", filename);
return;
}
// Write header
fprintf(f, "Time");
int nChannels = DSI_Headset_GetNumberOfChannels(h);
for (int i = 0; i < nChannels; i++) {
DSI_Channel ch = DSI_Headset_GetChannelByIndex(h, i);
fprintf(f, ",%s", DSI_Channel_GetName(ch));
}
fprintf(f, "\n");
// Acquire and save data
double fs = DSI_Headset_GetSamplingRate(h);
int samplesPerBlock = (int)(fs * 0.1);
int numBlocks = (int)(duration / 0.1);
DSI_Headset_StartDataAcquisition(h);
double startTime = DSI_Headset_SecondsSinceConnection(h);
for (int block = 0; block < numBlocks; block++) {
DSI_Headset_Idle(h, samplesPerBlock / fs); // Process one block duration
// Read buffered samples
for (int ch = 0; ch < nChannels; ch++) {
DSI_Channel channel = DSI_Headset_GetChannelByIndex(h, ch);
size_t buffered = DSI_Channel_GetNumberOfBufferedSamples(channel);
for (size_t samp = 0; samp < buffered; samp++) {
if (ch == 0) { // Write time only once per row
double time = DSI_Headset_SecondsSinceConnection(h) - startTime;
fprintf(f, "%.6f", time);
}
double value = DSI_Channel_ReadBuffered(channel);
fprintf(f, ",%.6f", value);
if (ch == nChannels - 1) fprintf(f, "\n");
}
}
}
DSI_Headset_StopDataAcquisition(h);
fclose(f);
printf("Saved %s\n", filename);
}
Task: Check Impedances#
Impedance testing measures electrode-skin contact quality. Good impedances (below 1MΩ) are critical for clean recordings. Run this before each session to verify sensor placement.
void checkImpedances(DSI_Headset h) {
printf("Starting impedance test...\n");
// Start impedance driver
DSI_Headset_StartImpedanceDriver(h);
if (DSI_Error()) {
fprintf(stderr, "Failed to start impedance driver: %s\n", DSI_ClearError());
return;
}
// Wait for readings to stabilize
DSI_Headset_Idle(h, 2.0);
// Read impedances
int nSources = DSI_Headset_GetNumberOfSources(h);
printf("\nImpedance readings:\n");
printf("%-10s %10s\n", "Electrode", "Impedance");
printf("------------------------\n");
for (int i = 0; i < nSources; i++) {
DSI_Source src = DSI_Headset_GetSourceByIndex(h, i);
if (DSI_Source_IsReferentialEEG(src)) {
const char* name = DSI_Source_GetName(src);
double impedance = DSI_Source_GetImpedanceEEG(src);
printf("%-10s %8.0f kΩ", name, impedance / 1000.0);
// Quality indicator
if (impedance < 1000000) {
printf(" ✓ Good\n");
} else if (impedance < 2000000) {
printf(" ⚠ Fair\n");
} else {
printf(" ✗ Poor\n");
}
}
}
// Get common-mode fault metric
double cmf = DSI_Headset_GetImpedanceCMF(h);
printf("\nCommon-mode fault: %.1f\n", cmf);
DSI_Headset_StopImpedanceDriver(h);
printf("Impedance test complete\n");
}
Task: Monitor Battery Level#
Monitoring battery prevents unexpected disconnections. Query battery status periodically during long recordings to ensure data integrity.
void monitorBattery(DSI_Headset h) {
// Send battery query
DSI_Headset_SendBatteryQuery(h);
// Wait for response
DSI_Headset_Idle(h, 0.5);
// Read level (0 = main battery)
double level = DSI_Headset_GetBatteryLevel(h, 0);
printf("Battery: %.1f%%", level);
if (level < 10.0) {
printf(" CRITICAL - Charge now!\n");
} else if (level < 20.0) {
printf(" LOW - Charge soon\n");
} else {
printf(" OK\n");
}
}
Next Steps#
Explore Advanced Features#
Quick Reference - Quick lookup guide for all API functions
Error Codes - Complete error code reference
Python Getting Started - Python version of this guide
Sample Code#
Check the release/demo.c file in the release package for a complete working example.
Support#
Technical support: Contact WearableSensing support team via the contact page.