-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathLabJackU6Device.h
executable file
·271 lines (211 loc) · 7.42 KB
/
LabJackU6Device.h
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
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
/*
* LabJack U6 Plugin for MWorks
*
* Created by Mark Histed on 4/21/2010
* (based on Nidaq plugin code by Jon Hendry and John Maunsell)
*
*/
#ifndef _LJU6_DEVICE_H_
#define _LJU6_DEVICE_H_
#include "MWorksCore/GenericData.h"
#include "MWorksCore/Utilities.h"
#include "MWorksCore/Plugin.h"
#include "MWorksCore/IODevice.h"
#include "MWorksCore/ComponentFactory.h"
#include "MWorksCore/ComponentRegistry.h"
#include "labjackusb.h"
#undef VERBOSE_IO_DEVICE
#define VERBOSE_IO_DEVICE 0 // verbosity level is 0-2, 2 is maximum
#define LJU6_DITASK_UPDATE_PERIOD_US 15000
#define LJU6_DITASK_WARN_SLOP_US 50000
#define LJU6_DITASK_FAIL_SLOP_US 50000
// dig output: Use a 12-bit word; EIO0-7, CIO0-2, all encoded below
#define LJU6_REWARD_FIO 0
#define LJU6_LEVER1_FIO 1
#define LJU6_LEVER1SOLENOID_FIO 2
#define LJU6_LASERTRIGGER_FIO 3
#define LJU6_LEVER2_FIO 4
#define LJU6_LEVER2SOLENOID_FIO 5
#define LJU6_STROBE_FIO 7
using namespace std;
namespace mw {
class LabJackU6DeviceOutputNotification;
class LabJackU6Device : public IODevice {
protected:
bool connected;
MWTime lastLever1TransitionTimeUS;
MWTime lastLever2TransitionTimeUS;
int lastLever1Value;
int lastLever2Value;
boost::shared_ptr <Scheduler> scheduler;
shared_ptr<ScheduleTask> pulseScheduleNode;
shared_ptr<ScheduleTask> pollScheduleNode;
boost::mutex pulseScheduleNodeLock;
boost::mutex pollScheduleNodeLock;
boost::mutex ljU6DriverLock;
MWTime highTimeUS; // Used to compute length of scheduled high/low pulses
HANDLE ljHandle;
boost::shared_ptr <Variable> pulseDurationMS;
boost::shared_ptr <Variable> pulseOn;
boost::shared_ptr <Variable> lever1;
boost::shared_ptr <Variable> lever2;
boost::shared_ptr <Variable> lever1Solenoid;
boost::shared_ptr <Variable> lever2Solenoid;
boost::shared_ptr <Variable> laserTrigger;
boost::shared_ptr <Variable> strobedDigitalWord;
//MWTime update_period; MH this is now hardcoded, users should not change this
bool active;
boost::mutex active_mutex;
bool deviceIOrunning;
// raw hardware functions
bool ljU6ConfigPorts(HANDLE Handle);
bool ljU6ReadDI(HANDLE Handle, long Channel, long* State);
bool ljU6WriteDO(HANDLE Handle, long Channel, long State);
bool ljU6WriteStrobedWord(HANDLE Handle, unsigned int inWord);
bool ljU6ReadPorts(HANDLE Handle, unsigned int *fioState, unsigned int *eioState, unsigned int *cioState);
public:
LabJackU6Device(const boost::shared_ptr <Scheduler> &a_scheduler,
const boost::shared_ptr <Variable> _pulseDurationMS,
const boost::shared_ptr <Variable> _pulseOn,
const boost::shared_ptr <Variable> _lever1Solenoid,
const boost::shared_ptr <Variable> _lever2Solenoid,
const boost::shared_ptr <Variable> _lever1,
const boost::shared_ptr <Variable> _lever2,
const boost::shared_ptr <Variable> _laserTrigger,
const boost::shared_ptr <Variable> _strobedDigitalWord);
~LabJackU6Device();
LabJackU6Device(const LabJackU6Device& copy);
virtual bool startup();
virtual bool shutdown();
// virtual bool attachPhysicalDevice(); DEPRECATED IN 0.4.4
virtual bool initialize();
virtual bool startDeviceIO();
virtual bool stopDeviceIO();
virtual bool pollAllDI();
void detachPhysicalDevice();
void variableSetup();
bool setupU6PortsAndRestartIfDead();
bool readLeverDI(bool *outLever1, bool *outLever2);
void pulseDOHigh(int pulseLengthUS);
void pulseDOLow();
void leverSolenoidDO(bool state, long channel);
void laserDO(bool state);
void strobedDigitalWordDO(unsigned int digWord);
virtual void dispense(Datum data){
if(getActive()){
bool doReward = (bool)data;
// Bring DO high for pulseDurationMS
if (doReward) {
this->pulseDOHigh(pulseDurationMS->getValue());
}
}
}
virtual void setLever1Solenoid(Datum data) {
//mprintf(M_IODEVICE_MESSAGE_DOMAIN, "set 1");
if (getActive()) {
bool lever1SolenoidState = (bool)data;
this->leverSolenoidDO(lever1SolenoidState, LJU6_LEVER1SOLENOID_FIO);
}
}
virtual void setLever2Solenoid(Datum data) {
//mprintf(M_IODEVICE_MESSAGE_DOMAIN, "set 2");
if (getActive()) {
bool lever2SolenoidState = (bool)data;
this->leverSolenoidDO(lever2SolenoidState, LJU6_LEVER2SOLENOID_FIO);
}
}
virtual void setLaserTrigger(Datum data) {
if (getActive()) {
bool laserState = (bool)data;
this->laserDO(laserState);
}
}
virtual void setStrobedDigitalWord(Datum data) {
if (getActive()) {
unsigned int digWord = (int)data;
this->strobedDigitalWordDO(digWord);
} else {
// silent: we need to doublecheck the active/deviceIORunning states and make sure they're doing the right thing.
// here, we set the value of this variable to zero on init; active/deviceIORunning is true only
// during a trial. I think the right thing to do is silently drop the output function.
//merror(M_IODEVICE_MESSAGE_DOMAIN, "LJU6: not running; not writing to strobed port (data was 0x%02x)", (int)data);
}
}
virtual void setActive(bool _active){
boost::mutex::scoped_lock active_lock(active_mutex);
active = _active;
}
virtual bool getActive(){
boost::mutex::scoped_lock active_lock(active_mutex);
bool is_active = active;
return is_active;
}
shared_ptr<LabJackU6Device> shared_from_this() { return static_pointer_cast<LabJackU6Device>(IODevice::shared_from_this()); }
};
class LabJackU6DeviceFactory : public ComponentFactory {
shared_ptr<Component> createObject(std::map<std::string, std::string> parameters,
mw::ComponentRegistry *reg);
};
class LabJackU6DeviceOutputNotification : public VariableNotification {
/* reward variable */
protected:
weak_ptr<LabJackU6Device> daq;
public:
LabJackU6DeviceOutputNotification(weak_ptr<LabJackU6Device> _daq){
daq = _daq;
}
virtual void notify(const Datum& data, MWTime timeUS){
shared_ptr<LabJackU6Device> shared_daq(daq);
shared_daq->dispense(data);
}
};
class LabJackU6DeviceL1SNotification : public VariableNotification {
protected:
weak_ptr<LabJackU6Device> daq;
public:
LabJackU6DeviceL1SNotification(weak_ptr<LabJackU6Device> _daq){
daq = _daq;
}
virtual void notify(const Datum& data, MWTime timeUS){
shared_ptr<LabJackU6Device> shared_daq(daq);
shared_daq->setLever1Solenoid(data);
}
};
class LabJackU6DeviceL2SNotification : public VariableNotification {
protected:
weak_ptr<LabJackU6Device> daq;
public:
LabJackU6DeviceL2SNotification(weak_ptr<LabJackU6Device> _daq){
daq = _daq;
}
virtual void notify(const Datum& data, MWTime timeUS){
shared_ptr<LabJackU6Device> shared_daq(daq);
shared_daq->setLever2Solenoid(data);
}
};
class LabJackU6DeviceLTNotification : public VariableNotification {
protected:
weak_ptr<LabJackU6Device> daq;
public:
LabJackU6DeviceLTNotification(weak_ptr<LabJackU6Device> _daq){
daq = _daq;
}
virtual void notify(const Datum& data, MWTime timeUS){
shared_ptr<LabJackU6Device> shared_daq(daq);
shared_daq->setLaserTrigger(data);
}
};
class LabJackU6DeviceSDWNotification : public VariableNotification {
protected:
weak_ptr<LabJackU6Device> daq;
public:
LabJackU6DeviceSDWNotification(weak_ptr<LabJackU6Device> _daq){
daq = _daq;
}
virtual void notify(const Datum& data, MWTime timeUS){
shared_ptr<LabJackU6Device> shared_daq(daq);
shared_daq->setStrobedDigitalWord(data);
}
};
} // namespace mw
#endif