diff --git a/src/blackrock.h b/src/blackrock.h index b15ad19..35c25af 100644 --- a/src/blackrock.h +++ b/src/blackrock.h @@ -34,7 +34,9 @@ typedef struct { int16_t milliseconds; } WindowsSystemTime; -// NEV file data structure +/* + * NEV file data structure + */ typedef struct { char file_type[8]; // “NEURALEV” uint16_t file_spec; // e.g. 0x0202 = Spec 2.2 @@ -49,23 +51,88 @@ typedef struct { uint32_t extension_count; } NEVBasicHeader; +// NEV Extension info section +#define NEVArrayNameID "ARRAYNME" +#define NEVExtraCommentID "ECOMMENT" +#define NEVContinuedCommentID "CCOMMENT" +#define NEVMapFileID "MAPFILE\0" +#define NEVNeuralWaveformID "NEUEVWAV" +#define NEVNeuralLabelID "NEUEVLBL" +#define NEVNeuralFilterID "NEUEVFLT" +#define NEVDigitalLabel "DIGLABEL" +#define NEVVideoSyncID "VIDEOSYN" +#define NEVTrackableObjectID "TRACKOBJ" + typedef struct { - char id[8]; + char id[8]; // package id (see above) char data[24]; } NEVExtensionHeader; -#define NEVDigitalSerialID 0x0 -// NEVSpikeID 0x1 - 0x800 -#define NEVConfigurationID 0xFFFB -#define NEVButtonID 0xFFFC -#define NEVTrackingID 0xFFFD -#define NEVVideoSyncID 0xFFFE -#define NEVCommentID 0xFFFF -#define NEVContinuationID 0xFFFFFFFF +typedef struct { + uint16_t id; // electrode id + uint8_t bank; + uint8_t pin; + uint16_t factor; // digitization scaling factor (nV per LSB step). + uint16_t threshold; // energy threshold, 0 if none used. + int16_t high_threshold; // amplitude high threshold used (in μV) 0 to 32767. + int16_t low_threshold; // amplitude low threshold used (in μV) 0 to -32767. + uint8_t units; // number of sorted units in channel, set to 0 for no unit classification + uint8_t size; // bytes per waveform sample, 0 and 1 both indicate 1 byte + uint16_t width; // samples per waveform (48 by default) + uint8_t reserved[8]; +} NEVNeuralWaveformExtensionData; + +typedef struct { + uint16_t id; // electrode id + char label[16]; + uint8_t reserved[6]; +} NEVNeuralLabelExtensionData; + +typedef struct { + uint16_t id; // electrode id + uint32_t highpass_corner; // high cutoff frequency in MHz + uint32_t highpass_order; // order of high cutoff: 0 = NONE + uint16_t highpass_type; // type of high cutoff: 0 = NONE, 1 = Butterworth + uint32_t lowpass_corner; // low cutoff frequency in MHz + uint32_t lowpass_order; // order of low cutoff: 0 = NONE + uint16_t lowpass_type; // type of low cutoff: 0 = NONE, 1 = Butterworth + uint8_t reserved[2]; +} NEVNeuralFilterExtensionData; + +typedef struct { + char label[16]; + uint8_t mode; // 0 = serial, 1 = parallel + uint8_t reserved[7]; +} NEVDigitalLabelExtensionData; + +typedef struct { + uint16_t id; // video source id + char name[16]; + float rate; // nominal fps (> 0) + uint8_t reserved[2]; +} NEVVideoSyncExtensionData; + +typedef struct { + uint16_t type; // 0 = undef, 1 = 2D body w/ markers, 2 = 2D body w/ blobs, 3 = 3D body w/ markers, 4 = 2d boundaries + uint16_t id; // trackable id + uint16_t count; // point count + char name[16]; + uint8_t reserved[2]; +} NEVTrackableObjectExtensionData; + +// NEV Data section +#define NEVDigitalSerialDataID 0x0 +// NEVSpikeDataID 0x1 - 0x800 +#define NEVConfigurationDataID 0xFFFB +#define NEVButtonDataID 0xFFFC +#define NEVTrackingDataID 0xFFFD +#define NEVVideoSyncDataID 0xFFFE +#define NEVCommentDataID 0xFFFF +#define NEVContinuationDataID 0xFFFFFFFF typedef struct { uint32_t timestamp; - uint16_t id; + uint16_t id; // data header id (see above) } NEVDataHeader; typedef struct { @@ -93,7 +160,7 @@ typedef struct { uint16_t file_number; uint32_t frame_number; uint32_t elapsed_time; - uint32_t video_source; + uint32_t id; // video source id } NEVVideoSyncData; typedef struct { @@ -111,8 +178,9 @@ typedef struct { // Followed by char comment[size - 12]; } NEVCommentDataHeader; - -// NSX file data structure +/* + * NSX file data structure + */ typedef struct { char file_type[8]; // “NEURALCD” or “NEURALSG”. uint16_t file_spec; // e.g. 0x0202 = Spec 2.2 diff --git a/src/neveventsprovider.cpp b/src/neveventsprovider.cpp index fd7dffe..16e8fe8 100644 --- a/src/neveventsprovider.cpp +++ b/src/neveventsprovider.cpp @@ -80,7 +80,7 @@ int NEVEventsProvider::loadData(){ // Create proper label EventDescription label; switch(dataHeader.id) { - case NEVDigitalSerialID: + case NEVDigitalSerialDataID: NEVDigitalSerialData digtalData; if(!readStruct(eventFile, digtalData)) goto fail; @@ -96,7 +96,7 @@ int NEVEventsProvider::loadData(){ - sizeof(NEVDataHeader))) goto fail; break; - case NEVConfigurationID: + case NEVConfigurationDataID: NEVConfigurationDataHeader configData; if(!readStruct(eventFile, configData)) goto fail; @@ -113,7 +113,7 @@ int NEVEventsProvider::loadData(){ - sizeof(NEVDataHeader))) goto fail; break; - case NEVButtonID: + case NEVButtonDataID: NEVButtonData buttonData; if(!readStruct(eventFile, buttonData)) goto fail; @@ -130,7 +130,7 @@ int NEVEventsProvider::loadData(){ - sizeof(NEVDataHeader))) goto fail; break; - case NEVTrackingID: + case NEVTrackingDataID: NEVTrackingDataHeader trackingData; if(!readStruct(eventFile, trackingData)) goto fail; @@ -143,12 +143,12 @@ int NEVEventsProvider::loadData(){ - sizeof(NEVDataHeader))) goto fail; break; - case NEVVideoSyncID: + case NEVVideoSyncDataID: NEVVideoSyncData syncData; if(!readStruct(eventFile, syncData)) goto fail; - label = QString("video sync (s: %1)").arg(syncData.video_source); + label = QString("video sync (s: %1)").arg(syncData.id); // Skip the padding if(!eventFile.seek(eventFile.pos() + mBasicHeader.data_package_size @@ -156,7 +156,7 @@ int NEVEventsProvider::loadData(){ - sizeof(NEVDataHeader))) goto fail; break; - case NEVCommentID: + case NEVCommentDataID: label = EventDescription("comment"); if(!eventFile.seek(eventFile.pos() + mBasicHeader.data_package_size