forked from ChrisVeigl/BrainBay
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathNIA.cpp
242 lines (189 loc) · 7.1 KB
/
NIA.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
/* -----------------------------------------------------------------------------
BrainBay Version 1.7, GPL 2003-2010, contact: [email protected]
MODULE: NIA.CPP: contains functions for the NIA-Interface
Author: Franz Strobl 2010, contact: [email protected]
The NIA Object provides Interfacing to the NIA OCZ-Hardware with
EEG-Transducer. The NIA device is connected to any USB-Port. All
USB-Ports are scanned for a device from Vendor 0x1234 (OCZ NIA). If one
or two devices are found they will be registered and can deliver
Data to channel 1 and 2 of the eeg-object.
- NIA delivers Data with 4kHz (every 250usec. one value) each 3 or 4 samples
are transferred within one packet. This program evluates only the first
sample of one packet, because this seems to be enough for accurate signaling.
- Changes were done for normalizing the input data (24-Bit original are
converted to 16-Bit which are evaluated)
- Further the Sampling Rate is set to 1000 samples/second according Hardware.
Archiving was also adapted for NIA Data Recording.
- com-Port and Baud Rate are not considered using NIA.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; See the
GNU General Public License for more details.
-----------------------------------------------------------------------------*/
#include "windows.h"
#include "brainBay.h"
#include "ob_eeg.h"
#define NIABYTECOUNT 3 // Count of bytes to be evaluated: 24-Bit (3Byte) per 1 Sample!
RAWINPUTDEVICE Rid[2];
RAWINPUTDEVICELIST RawInputDeviceList[20];
HANDLE NIAREADERTHREAD;
HANDLE m_hNIA[2];
int m_nCountNIA=0;
BOOL fNIAThreadDone = FALSE;
int oldIndex=0;
int oldTiming=0;
//
// DisconnectNIA sollte ähnlich BreakDownCommPort die NIA Schnittstelle abkoppeln und schließen
//
BOOL DisconnectNIA(void) {
UINT ui;
UINT ret;
UINT i;
ret=GetRegisteredRawInputDevices(NULL,&ui,sizeof(RAWINPUTDEVICE)); // get size
if (ret<=sizeof(Rid)) // if okay, get structures
GetRegisteredRawInputDevices(Rid, &ui, sizeof(RAWINPUTDEVICE));
if(ret!=(UINT)-1){
for (i=0; i<ui; i++) {
Rid[i].dwFlags = RIDEV_REMOVE; // this should disable the HID device
Rid[i].hwndTarget = NULL ;
// RawInputDeviceList[i].hDevice = NULL;
if (RegisterRawInputDevices(Rid, 1, sizeof(RAWINPUTDEVICE)) == FALSE)
report_error("Could not close NIA");
}
}
ret=GetRegisteredRawInputDevices(Rid, &ui, sizeof(RAWINPUTDEVICE));
if (ret !=0)
report_error("Could not disconnect NIA");
return TRUE;
}
//
// ConnectNIA wurde abgeleitet aus NIADlg.cpp, aber ohne MFC implementiert
// Das NIA Device wird als USB HID Device angekoppelt und mit GetRawInputData ausgelesen
//
BOOL ConnectNIA(HWND hDlg) {
UINT ui;
UINT ret;
ret=GetRawInputDeviceList(NULL,&ui,0);
UINT i;
int sav_pause;
sav_pause=TTY.read_pause;
TTY.read_pause=1;
ret=GetRegisteredRawInputDevices(NULL,&ui,sizeof(RAWINPUTDEVICE)); // get size
if (ret<=sizeof(Rid)) // if okay, get structures
GetRegisteredRawInputDevices(Rid, &ui, sizeof(RAWINPUTDEVICE));
if (ui>0) {
report_error("NIA already connected!");
TTY.read_pause=sav_pause;
return (TRUE);
}
m_hNIA[0]=NULL;
m_hNIA[1]=NULL;
ui=20;
ret=GetRawInputDeviceList(&RawInputDeviceList[0],&ui,sizeof(RAWINPUTDEVICELIST));
if(ret!=(UINT)-1)
{
RID_DEVICE_INFO dev_info ;
TCHAR strName[300];
m_nCountNIA = 0;
for(i=0;i<ret;i++)
{
if(i>=20) break;
dev_info.cbSize=sizeof(RID_DEVICE_INFO);
ui=sizeof(RID_DEVICE_INFO);
GetRawInputDeviceInfo(RawInputDeviceList[i].hDevice,RIDI_DEVICEINFO,&dev_info,&ui);
ui=300;
GetRawInputDeviceInfo(RawInputDeviceList[i].hDevice,RIDI_DEVICENAME,strName,&ui);
if(dev_info.hid.dwVendorId==0x1234 /*&& dev_info.hid.dwProductId==0*/)
{
if(m_nCountNIA>=2) break; // nur an dieser Stelle vorbereitet!
m_hNIA[m_nCountNIA]=RawInputDeviceList[i].hDevice;
Rid[m_nCountNIA].usUsagePage = 0xFF00;
Rid[m_nCountNIA].usUsage = 0xFF01;
Rid[m_nCountNIA].dwFlags = RIDEV_INPUTSINK; // this enables the caller to receive the input even when the caller is not in the foreground. Note that hwndTarget must be specified.
Rid[m_nCountNIA].hwndTarget = ghWndMain ; // ist wichtig, damit die Daten an den richtigen Thread kommen!!!
m_nCountNIA++; // ToDo: für 2 NIA Devices 2! Kanäle im Amplifier??? (not tested yet!)
}
}
} else {
TTY.read_pause=sav_pause;
return (FALSE) ;
}
if(m_nCountNIA>0)
{
if (RegisterRawInputDevices(Rid, m_nCountNIA, sizeof(RAWINPUTDEVICE)) == FALSE) {
report_error("Could not register NIA");
TTY.read_pause=sav_pause;
return FALSE;
} else {
SetDlgItemText( hDlg, IDC_PORTCOMBO, "none") ;
SendDlgItemMessage( hDlg, IDC_SAMPLINGCOMBO, CB_SETCURSEL, TTY.samplingrate, 0L ) ;
TTY.read_pause=sav_pause;
return TRUE ;
}
}
TTY.read_pause=sav_pause;
return FALSE;
}
//
// ReadNIA wurde abgeleitet aus NIADlg.cpp, aber ohne MFC implementiert
// Das NIA Device wird mit GetRawInputData oder GetRawInputBuffer ausgelesen
//
int ReadNIA( UINT wParam, LONG lParam )
{
int nNIA;
int i;
UINT dwSize=0;
RAWINPUT* raw;
//first get size
GetRawInputData((HRAWINPUT)(lParam), RID_INPUT, NULL, &dwSize,
sizeof(RAWINPUTHEADER));
LPBYTE lpb = new BYTE[dwSize+sizeof(RAWINPUTHEADER)];
if (lpb == NULL)
{
report_error("Create NIA Buffer failed!");
return 0;
}
//then get data
if (GetRawInputData((HRAWINPUT)(lParam), RID_INPUT, lpb, &dwSize,
sizeof(RAWINPUTHEADER)) != dwSize )
OutputDebugString (TEXT("GetRawInputData doesn't return correct size !\n"));
raw = (RAWINPUT*)lpb;
if(m_hNIA[0]!=NULL && raw->header.hDevice==m_hNIA[0]) nNIA=1;
else if(m_hNIA[1]!=NULL && raw->header.hDevice==m_hNIA[1]) nNIA=2;
else nNIA=0;
if(nNIA>0 && raw->header.dwType == RIM_TYPEHID && raw->data.hid.dwSizeHid==56)
{
UINT ui;
RID_DEVICE_INFO dev_info;
dev_info.cbSize=sizeof(RID_DEVICE_INFO);
ui=sizeof(RID_DEVICE_INFO);
GetRawInputDeviceInfo(raw->header.hDevice,RIDI_DEVICEINFO,&dev_info,&ui);
#define MAX_SAMPLE_COUNT 16
int nFixed; // Bytes 49+50, ist an sich immer gleich
int nTiming; // Timing-Info
int nIndex; // Laufender Index bezogen auf 4kHz Sampling-Rate
int nSamples; // Anzahl der Samples
nFixed=raw->data.hid.bRawData[49]+raw->data.hid.bRawData[50]*0x100;
nTiming=raw->data.hid.bRawData[51]+raw->data.hid.bRawData[52]*0x100;
nIndex=raw->data.hid.bRawData[53]+raw->data.hid.bRawData[54]*0x100;
nSamples=raw->data.hid.bRawData[55];
if (oldIndex >0){
if (nIndex > (oldIndex+4)){
GLOBAL.syncloss++;
}
}
oldIndex= nIndex;
/* Umkopieren von lpb auf TTY.readBuf fürs Archivieren! */
nSamples = NIABYTECOUNT ; // NIA: nur 1 Sample (3Byte) statt nSamples bzw.
// nur das erste Sample aus einem packet auswerten
if ((!TTY.read_pause)) {
for (i=0; i<nSamples; i++)
TTY.readBuf[i] = (unsigned char) raw->data.hid.bRawData[1+i] ;
ParseLocalInput(nSamples);
}
} else {
report_error("NIA connection issue!");
}
if(lpb!=NULL) delete[] lpb;
return 0L;
}