BrainAccess Core C API Usage Example

#include "bacore.h"
#include "eeg_manager.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>

unsigned int runtime = 1;
bool is_reading = false;
ba_eeg_manager* manager;

void chunk_callback([[maybe_unused]] const void* const* data, [[maybe_unused]] size_t size, [[maybe_unused]] void* user_data)
{
        // Get the channel index for the sample number once and reuse it
        size_t sample_number_index = ba_eeg_manager_get_channel_index(manager, BA_EEG_CHANNEL_ID_SAMPLE_NUMBER);

        for (size_t i = 0; i < size; ++i)
        {
                // Get the data for the sample number and channels
                const size_t* eeg_data_sample_number = (const size_t*)data[sample_number_index];
                const double* eeg_data_channel_0 = (const double*)data[ba_eeg_manager_get_channel_index(manager, BA_EEG_CHANNEL_ID_ELECTRODE_MEASUREMENT + 0)];
                const double* eeg_data_channel_1 = (const double*)data[ba_eeg_manager_get_channel_index(manager, BA_EEG_CHANNEL_ID_ELECTRODE_MEASUREMENT + 1)];
                const double* eeg_data_channel_2 = (const double*)data[ba_eeg_manager_get_channel_index(manager, BA_EEG_CHANNEL_ID_ELECTRODE_MEASUREMENT + 2)];
                const double* eeg_data_channel_3 = (const double*)data[ba_eeg_manager_get_channel_index(manager, BA_EEG_CHANNEL_ID_ELECTRODE_MEASUREMENT + 3)];
                const double* eeg_data_channel_4 = (const double*)data[ba_eeg_manager_get_channel_index(manager, BA_EEG_CHANNEL_ID_ELECTRODE_MEASUREMENT + 4)];
                const double* eeg_data_channel_5 = (const double*)data[ba_eeg_manager_get_channel_index(manager, BA_EEG_CHANNEL_ID_ELECTRODE_MEASUREMENT + 5)];
                const double* eeg_data_channel_6 = (const double*)data[ba_eeg_manager_get_channel_index(manager, BA_EEG_CHANNEL_ID_ELECTRODE_MEASUREMENT + 6)];
                const double* eeg_data_channel_7 = (const double*)data[ba_eeg_manager_get_channel_index(manager, BA_EEG_CHANNEL_ID_ELECTRODE_MEASUREMENT + 7)];

                // Process the data directly without storing it in a structure
                printf(
                        "%d  %d  %f  %f  %f  %f  %f  %f  %f  %f\n", eeg_data_sample_number[i], eeg_data_channel_0[i], eeg_data_channel_1[i], eeg_data_channel_2[i],
                        eeg_data_channel_3[i], eeg_data_channel_4[i], eeg_data_channel_5[i], eeg_data_channel_6[i], eeg_data_channel_7[i]);
        }
}

// Callback function for handling disconnection events.
// This function is called when the connection to the device is lost.
// It prints a message indicating the disconnection event.
void disconnect_callback([[maybe_unused]] void* data)
{
        printf("Disconnected\n");
}

// Function to print the version information.
// This function takes a text string and a version structure as input and prints the version information.
void print_version(const char* text, const ba_version* version)
{
        printf("%s %d.%d.%d\n", text, version->major, version->minor, version->patch);
}

// Function to connect to the Bluetooth EEG device and perform EEG operations
ba_init_error connect_ble()
{
        // Initialize the status variable to hold the result of the initialization
        ba_init_error status = BA_INIT_ERROR_OK;

        // Define the version constant for the Bluetooth EEG system
        const ba_version version = {1, 1, 1};

        // Initialize the Bluetooth EEG system using the defined version
        status |= ba_core_init(&version);

        // Check if the initialization was successful
        if (status != BA_INIT_ERROR_OK)
        {
                // Print an error message if the initialization failed
                printf("Core init Error: %d\n", status);
        }

        // Retrieve the current version of the Bluetooth EEG system
        const ba_version* current_version = ba_core_get_version();

        // Print the current version of the Bluetooth EEG system
        print_version("core current version: ", current_version);

        // Scan for available Bluetooth EEG devices
        status |= ba_core_scan(0);

        // Check if no devices were found after the first scan
        if (ba_core_device_count() == 0)
        {
                // Keep scanning for devices until at least one is found
                while (ba_core_device_count() == 0)
                {
                        // Print the number of scan attempts
                        printf("Found devices count: %d\n", ba_core_device_count());

                        // Scan for available devices again
                        status |= ba_core_scan(0);
                }
        }

        // Print a message indicating the end of the scanning process
        printf("Search: \n");

        // Check if no devices were found after scanning
        if (ba_core_device_count() == 0)
        {
                // Print a message indicating that no devices were found
                printf("0 Devices were found\n");

                // Close the Bluetooth EEG system
                ba_core_close();

                // Return an error code indicating that no devices were found
                return BA_INIT_ERROR_NOT_FOUND;
        }
        // Create a new EEG manager instance
        manager = ba_eeg_manager_new();

        // Print the number of available devices
        printf("devices found: %d\n", ba_core_device_count());

        // Get the address of the first device
        char address[20];
        ba_core_device_get_address(address, 0);
        printf("Address: %s\n", address);

        // Get the name of the first device
        char name[20];
        ba_core_device_get_name(name, 0);
        printf("Name: %s\n", name);

        // Find the device with the name "BA MINI 002"
        int device = -1;
        for (int i = 0; i < ba_core_device_count(); ++i)
        {
                ba_core_device_get_name(name, i);
                if (strcmp(name, "BA MINI 002") == 0)
                {
                        device = i;
                        printf("Device found!!!!!!!\n");
                }
        }

        // If the device is not found, return -1
        if (device < 0)
        {
                return -1;
        }

        // Connect to the selected device
        ba_eeg_manager_connect(manager, device, NULL, NULL);
        printf("Connected\n");

        // Get the battery information
        const ba_battery_info info = ba_eeg_manager_get_battery_info(manager);
        printf("battery level: %d | is charger connected: %d | is charging: %d ", info.level, info.is_charger_connected, info.is_charging);

        // Enable and set the gain for all electrode channels
        for (int i = 0; i < 8; ++i)
        {
                ba_eeg_manager_set_channel_enabled(manager, BA_EEG_CHANNEL_ID_ELECTRODE_CONTACT + i, true);
                ba_eeg_manager_set_channel_enabled(manager, BA_EEG_CHANNEL_ID_ELECTRODE_MEASUREMENT + i, true);
                ba_eeg_manager_set_channel_gain(manager, BA_EEG_CHANNEL_ID_ELECTRODE_MEASUREMENT + i, BA_GAIN_MODE_X8);
        }

        // Enable the sample number channel
        ba_eeg_manager_set_channel_enabled(manager, BA_EEG_CHANNEL_ID_SAMPLE_NUMBER, true);

        // Set the impedance measurement mode to off
        ba_eeg_manager_set_impedance_mode(manager, BA_IMPEDANCE_MEASUREMENT_MODE_OFF);

        // Load the configuration
        ba_eeg_manager_load_config(manager, NULL, NULL);

        // Define the callback function for handling EEG data chunks
        ba_callback_chunk my_callback = chunk_callback;

        // Define the callback function for handling disconnection events
        ba_callback_disconnect disconnect_cb = disconnect_callback;

        // Set the callback function for handling EEG data chunks
        ba_eeg_manager_set_callback_chunk(manager, my_callback, NULL);

        // Set the callback function for handling disconnection events
        ba_eeg_manager_set_callback_disconnect(manager, disconnect_cb, NULL);

        // Start the EEG data streaming
        ba_eeg_manager_start_stream(manager, NULL, NULL);

        // Check if the EEG data streaming is active
        ba_eeg_manager_is_streaming(manager);

        // Sleep for 5 seconds
        sleep(5);

        // Stop the EEG data streaming
        ba_eeg_manager_stop_stream(manager, NULL, NULL);

        // Free the EEG manager instance
        ba_eeg_manager_free(manager);

        // Close the Bluetooth EEG system
        ba_core_close();

        // Set the is_reading flag to false
        is_reading = false;

        // Return the status of the initialization
        return status;
}

int main()
{
        connect_ble();
        return 0;
}