phidgets_native 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +10 -4
- data/examples/interface_kit-dualratiometric.rb +50 -0
- data/ext/phidgets_native/interfacekit.c +174 -53
- data/ext/phidgets_native/interfacekit_ruby.c +122 -5
- data/ext/phidgets_native/phidgets_native.h +16 -3
- data/phidgets_native.gemspec +1 -1
- metadata +5 -4
data/README.rdoc
CHANGED
@@ -167,10 +167,16 @@ by the Phidget API and/or hardware.
|
|
167
167
|
==Logging
|
168
168
|
The phidget api has built in debug logging which can be enabled on a global basis
|
169
169
|
for all devices. By default, logs are sent to STDOUT, but you can optionally
|
170
|
-
pass a path to a text file where output can alternatively be redirected.
|
171
|
-
also send your own messages to the logger, if you think you have something you
|
172
|
-
need to add.
|
173
|
-
|
170
|
+
pass a path to a text file where output can alternatively be redirected.
|
174
171
|
PhidgetsNative.enable_logging!(:verbose)
|
175
172
|
PhidgetsNative.log :info, "My favorite color is chartreuse"
|
176
173
|
PhidgetsNative.disable_logging!
|
174
|
+
Note that you can also use the log method to send your own messages to the logger,
|
175
|
+
if you think you have something you need to add.
|
176
|
+
|
177
|
+
=Changelog
|
178
|
+
== Version 0.2.1
|
179
|
+
- Added dual-ratiometric mode features and interfaces to the InterfaceKit
|
180
|
+
|
181
|
+
== Version 0.2.0
|
182
|
+
- First gem release, supporting all api functions of the Spatial, GPS, InterfaceKit, & AdvancedServo phidgets
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
require '%s/lib/common' % File.dirname(__FILE__)
|
5
|
+
|
6
|
+
#PhidgetsNative.enable_logging! :verbose
|
7
|
+
|
8
|
+
additional_attribs = [
|
9
|
+
%w(Digital\ Inputs input_count),
|
10
|
+
%w(Digital\ Outputs output_count),
|
11
|
+
%w(Analog\ Inputs sensor_count),
|
12
|
+
%w(Change\ Triggers change_triggers),
|
13
|
+
%w(Data\ Rates data_rates),
|
14
|
+
%w(Data\ Rates\ Min data_rates_min),
|
15
|
+
%w(Data\ Rates\ Max data_rates_max)
|
16
|
+
]
|
17
|
+
|
18
|
+
phidgets_example_for(PhidgetsNative::InterfaceKit, additional_attribs) do |ifkit|
|
19
|
+
|
20
|
+
ifkit.ratiometric = true
|
21
|
+
ifkit.ratiometric 6, false
|
22
|
+
ifkit.ratiometric 7, false
|
23
|
+
|
24
|
+
# Test sensor_raw
|
25
|
+
puts "Ratiometric states:"
|
26
|
+
ConsoleTable.new((0...ifkit.sensor_count).collect{|i| "Sensor #{i}"}).output do
|
27
|
+
[(0...ifkit.sensor_count).collect{|i| ifkit.ratiometric(i).inspect } ]
|
28
|
+
end
|
29
|
+
|
30
|
+
puts "\nPolled Values:"
|
31
|
+
i = 0
|
32
|
+
ConsoleTable.new([
|
33
|
+
'Sensor Sample Rates',
|
34
|
+
'%-40s' % 'sensors',
|
35
|
+
]).output(:header => (i == 0), :separator => false) do |columns|
|
36
|
+
i+=1
|
37
|
+
|
38
|
+
values = ifkit.sensors
|
39
|
+
if values
|
40
|
+
values[0] = '%.1f %% (RH)' % [values[0].to_f * 0.1906 - 40.2]
|
41
|
+
values[1] = '%.1f deg (C)' % [values[1].to_f * 0.22222 - 61.111]
|
42
|
+
values[2] = '%.1f deg (C)' % [values[2].to_f * 0.22222 - 61.111]
|
43
|
+
|
44
|
+
values[6] = '%.3f (V)' % [(values[6].to_f / 200 - 2.5) / 0.0681]
|
45
|
+
values[7] = '%.3f (V)' % [(values[7].to_f / 200 - 2.5) / 0.0681]
|
46
|
+
end
|
47
|
+
|
48
|
+
[ [ ifkit.sensor_sample_rates, values.inspect] ]
|
49
|
+
end while sleep(1)
|
50
|
+
end
|
@@ -40,15 +40,20 @@ int CCONV interfacekit_on_attach(CPhidgetHandle phid, void *userptr) {
|
|
40
40
|
if(ifkit_info->data_rates_min) xfree(ifkit_info->data_rates_min);
|
41
41
|
if(ifkit_info->sensor_change_triggers) xfree(ifkit_info->sensor_change_triggers);
|
42
42
|
if(ifkit_info->analog_sample_rates) xfree(ifkit_info->analog_sample_rates);
|
43
|
+
if(ifkit_info->is_ratiometric) xfree(ifkit_info->is_ratiometric);
|
44
|
+
if(ifkit_info->updated_since_last_ratiometric_cycle) xfree(ifkit_info->updated_since_last_ratiometric_cycle);
|
43
45
|
|
44
46
|
ifkit_info->data_rates = ALLOC_N(int, ifkit_info->analog_input_count);
|
45
47
|
ifkit_info->data_rates_max = ALLOC_N(int, ifkit_info->analog_input_count);
|
46
48
|
ifkit_info->data_rates_min = ALLOC_N(int, ifkit_info->analog_input_count);
|
47
49
|
ifkit_info->sensor_change_triggers = ALLOC_N(int, ifkit_info->analog_input_count);
|
48
|
-
|
49
50
|
ifkit_info->analog_sample_rates = ALLOC_N(SampleRate, ifkit_info->analog_input_count);
|
51
|
+
ifkit_info->is_ratiometric = ALLOC_N(bool, ifkit_info->analog_input_count);
|
52
|
+
ifkit_info->updated_since_last_ratiometric_cycle = ALLOC_N(bool, ifkit_info->analog_input_count);
|
50
53
|
|
51
54
|
memset(ifkit_info->analog_sample_rates, 0, sizeof(SampleRate) * ifkit_info->analog_input_count);
|
55
|
+
memset(ifkit_info->is_ratiometric, 0, sizeof(bool) * ifkit_info->analog_input_count);
|
56
|
+
memset(ifkit_info->updated_since_last_ratiometric_cycle, 0, sizeof(bool) * ifkit_info->analog_input_count);
|
52
57
|
|
53
58
|
for(int i=0;i<ifkit_info->analog_input_count;i++) {
|
54
59
|
ifkit_info->data_rates[i] = DEFAULT_INTERFACEKIT_DATA_RATE;
|
@@ -61,18 +66,15 @@ int CCONV interfacekit_on_attach(CPhidgetHandle phid, void *userptr) {
|
|
61
66
|
ifkit_info->is_data_rates_known = true;
|
62
67
|
}
|
63
68
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
report(CPhidgetInterfaceKit_setDataRate(interfacekit, i, 0));
|
74
|
-
report(CPhidgetInterfaceKit_setSensorChangeTrigger(interfacekit, i, ifkit_info->sensor_change_triggers[i]));
|
75
|
-
}
|
69
|
+
if ( interfacekit_ratiometric_state_is_uniform(ifkit_info) ) {
|
70
|
+
// Set the board's ratiometric state:
|
71
|
+
report(interfacekit_assert_ratiometric_state( info ));
|
72
|
+
// Set the data-rate/sensor-thresholds
|
73
|
+
report(interfacekit_assert_sensor_rates(info));
|
74
|
+
}
|
75
|
+
else {
|
76
|
+
report(interfacekit_assert_dual_ratiometric_mode(info));
|
77
|
+
report(interfacekit_maximize_data_rate(info));
|
76
78
|
}
|
77
79
|
|
78
80
|
// Read in all of our initial input values:
|
@@ -83,7 +85,7 @@ int CCONV interfacekit_on_attach(CPhidgetHandle phid, void *userptr) {
|
|
83
85
|
report(CPhidgetInterfaceKit_setOutputState(interfacekit,i, ifkit_info->digital_output_states[i]));
|
84
86
|
|
85
87
|
for(int i=0; i<ifkit_info->analog_input_count; i++)
|
86
|
-
if (ifkit_info->
|
88
|
+
if (ifkit_info->ratiometric_changed_usec == 0)
|
87
89
|
// We only read these in if we haven't recently been changed ratiometric status:
|
88
90
|
report(CPhidgetInterfaceKit_getSensorValue(interfacekit,i, &ifkit_info->analog_input_states[i]));
|
89
91
|
else
|
@@ -119,26 +121,18 @@ int CCONV interfacekit_on_detach(CPhidgetHandle phid, void *userptr) {
|
|
119
121
|
void interfacekit_on_free(void *type_info) {
|
120
122
|
InterfaceKitInfo *ifkit_info = type_info;
|
121
123
|
|
122
|
-
if(ifkit_info->
|
123
|
-
|
124
|
-
if(ifkit_info->
|
125
|
-
|
126
|
-
if(ifkit_info->data_rates_max)
|
127
|
-
|
128
|
-
if(ifkit_info->
|
129
|
-
|
130
|
-
if (ifkit_info->
|
131
|
-
|
132
|
-
if (ifkit_info->
|
133
|
-
|
134
|
-
if (ifkit_info->analog_input_states)
|
135
|
-
xfree(ifkit_info->analog_input_states);
|
136
|
-
if(ifkit_info->digital_sample_rates)
|
137
|
-
xfree(ifkit_info->digital_sample_rates);
|
138
|
-
if(ifkit_info->analog_sample_rates)
|
139
|
-
xfree(ifkit_info->analog_sample_rates);
|
140
|
-
if (ifkit_info)
|
141
|
-
xfree(ifkit_info);
|
124
|
+
if(ifkit_info->is_ratiometric) xfree(ifkit_info->is_ratiometric);
|
125
|
+
if(ifkit_info->updated_since_last_ratiometric_cycle) xfree(ifkit_info->updated_since_last_ratiometric_cycle);
|
126
|
+
if(ifkit_info->data_rates) xfree(ifkit_info->data_rates);
|
127
|
+
if(ifkit_info->data_rates_min) xfree(ifkit_info->data_rates_min);
|
128
|
+
if(ifkit_info->data_rates_max) xfree(ifkit_info->data_rates_max);
|
129
|
+
if(ifkit_info->sensor_change_triggers) xfree(ifkit_info->sensor_change_triggers);
|
130
|
+
if (ifkit_info->digital_input_states) xfree(ifkit_info->digital_input_states);
|
131
|
+
if (ifkit_info->digital_output_states) xfree(ifkit_info->digital_output_states);
|
132
|
+
if (ifkit_info->analog_input_states) xfree(ifkit_info->analog_input_states);
|
133
|
+
if(ifkit_info->digital_sample_rates) xfree(ifkit_info->digital_sample_rates);
|
134
|
+
if(ifkit_info->analog_sample_rates) xfree(ifkit_info->analog_sample_rates);
|
135
|
+
if (ifkit_info) xfree(ifkit_info);
|
142
136
|
return;
|
143
137
|
}
|
144
138
|
|
@@ -158,12 +152,14 @@ int interfacekit_on_analog_change(CPhidgetInterfaceKitHandle interfacekit, void
|
|
158
152
|
PhidgetInfo *info = userptr;
|
159
153
|
InterfaceKitInfo *ifkit_info = info->type_info;
|
160
154
|
|
161
|
-
|
155
|
+
bool record_value = false;
|
156
|
+
|
157
|
+
int current_ratiometric_state = PFALSE;
|
162
158
|
|
163
159
|
if (ifkit_info->analog_input_states) {
|
164
|
-
if (ifkit_info->
|
165
|
-
|
166
|
-
else {
|
160
|
+
if (ifkit_info->is_dual_ratiometric_mode && interfacekit_is_time_to_flip_ratiometric_state(info) ) {
|
161
|
+
report(interfacekit_flip_ratiometric_state(info));
|
162
|
+
} else if (ifkit_info->ratiometric_changed_usec != 0) {
|
167
163
|
// We need to wait 50 milliseconds before accepting values after a ratiometric
|
168
164
|
// state change. If we're in this path, it's TBD whether 50 ms has passed
|
169
165
|
int usec_difference;
|
@@ -171,17 +167,31 @@ int interfacekit_on_analog_change(CPhidgetInterfaceKitHandle interfacekit, void
|
|
171
167
|
gettimeofday(&now, NULL);
|
172
168
|
|
173
169
|
usec_difference = ( now.tv_usec +
|
174
|
-
( (now.tv_usec < ifkit_info->
|
175
|
-
ifkit_info->
|
176
|
-
|
170
|
+
( (now.tv_usec < ifkit_info->ratiometric_changed_usec) ? 1000000 : 0) -
|
171
|
+
ifkit_info->ratiometric_changed_usec );
|
172
|
+
|
177
173
|
// Did we wait long enough between a ratiometric status change:
|
178
174
|
if ( usec_difference > INTERFACEKIT_RATIOMETRIC_RESET_USECS ) {
|
179
|
-
ifkit_info->
|
180
|
-
|
181
|
-
// And sure, go ahead and accepti this value:
|
182
|
-
ifkit_info->analog_input_states[index] = sensorValue;
|
175
|
+
ifkit_info->ratiometric_changed_usec = 0;
|
183
176
|
}
|
184
177
|
}
|
178
|
+
|
179
|
+
if (ifkit_info->ratiometric_changed_usec == 0) {
|
180
|
+
if (ifkit_info->is_dual_ratiometric_mode) {
|
181
|
+
report(CPhidgetInterfaceKit_getRatiometric(interfacekit, ¤t_ratiometric_state));
|
182
|
+
|
183
|
+
if ( (current_ratiometric_state == PTRUE) == ifkit_info->is_ratiometric[index] )
|
184
|
+
record_value = true;
|
185
|
+
} else
|
186
|
+
record_value = true;
|
187
|
+
}
|
188
|
+
|
189
|
+
if (record_value) {
|
190
|
+
ifkit_info->analog_input_states[index] = sensorValue;
|
191
|
+
sample_tick(&ifkit_info->analog_sample_rates[index], NULL);
|
192
|
+
if(ifkit_info->is_dual_ratiometric_mode)
|
193
|
+
ifkit_info->updated_since_last_ratiometric_cycle[index] = true;
|
194
|
+
}
|
185
195
|
}
|
186
196
|
|
187
197
|
return 0;
|
@@ -192,23 +202,134 @@ int interfacekit_assert_ratiometric_state(PhidgetInfo *info) {
|
|
192
202
|
CPhidgetInterfaceKitHandle interfacekit = (CPhidgetInterfaceKitHandle) info->handle;
|
193
203
|
int ret = 0;
|
194
204
|
|
195
|
-
|
196
|
-
ret = CPhidgetInterfaceKit_getRatiometric(interfacekit, &is_ratiometric_already);
|
197
|
-
if (ret != EPHIDGET_OK) return ret;
|
205
|
+
bool change_mode = false;
|
198
206
|
|
199
|
-
if (ifkit_info->
|
200
|
-
|
207
|
+
if (ifkit_info->is_dual_ratiometric_mode) {
|
208
|
+
ifkit_info->is_dual_ratiometric_mode = false;
|
209
|
+
change_mode = true;
|
210
|
+
report(interfacekit_assert_sensor_rates(info));
|
211
|
+
} else {
|
212
|
+
int is_ratiometric_already;
|
213
|
+
ret = CPhidgetInterfaceKit_getRatiometric(interfacekit, &is_ratiometric_already);
|
214
|
+
if (ret != EPHIDGET_OK) return ret;
|
215
|
+
|
216
|
+
if (ifkit_info->is_ratiometric[0] != (is_ratiometric_already == PTRUE) )
|
217
|
+
change_mode = true;
|
218
|
+
}
|
219
|
+
|
220
|
+
if (change_mode) {
|
221
|
+
ret = CPhidgetInterfaceKit_setRatiometric(interfacekit, (ifkit_info->is_ratiometric[0]) ? PTRUE : PFALSE );
|
201
222
|
if (ret != EPHIDGET_OK) return ret;
|
202
223
|
|
203
224
|
// Zero-out the analog struct:
|
204
225
|
memset(ifkit_info->analog_input_states, 0, sizeof(int) * ifkit_info->analog_input_count);
|
205
226
|
|
206
227
|
// We need to wait 50ms after this change before we start to read in values:
|
207
|
-
|
208
|
-
|
228
|
+
interfacekit_stamp_ratiometric_change(ifkit_info);
|
229
|
+
}
|
230
|
+
|
231
|
+
return EPHIDGET_OK;
|
232
|
+
}
|
233
|
+
|
234
|
+
bool interfacekit_ratiometric_state_is_uniform(InterfaceKitInfo *ifkit_info) {
|
235
|
+
bool first_state = ifkit_info->is_ratiometric[0];
|
236
|
+
|
237
|
+
for(int i=1; i<ifkit_info->analog_input_count;i++)
|
238
|
+
if (ifkit_info->is_ratiometric[i] != first_state)
|
239
|
+
return false;
|
240
|
+
|
241
|
+
return true;
|
242
|
+
}
|
243
|
+
|
244
|
+
bool interfacekit_is_time_to_flip_ratiometric_state(PhidgetInfo *info) {
|
245
|
+
InterfaceKitInfo *ifkit_info = info->type_info;
|
246
|
+
CPhidgetInterfaceKitHandle interfacekit = (CPhidgetInterfaceKitHandle) info->handle;
|
247
|
+
|
248
|
+
int current_ratiometric_state = PFALSE;
|
249
|
+
|
250
|
+
report(CPhidgetInterfaceKit_getRatiometric(interfacekit, ¤t_ratiometric_state));
|
251
|
+
|
252
|
+
for(int i=0; i<ifkit_info->analog_input_count;i++)
|
253
|
+
if ( (ifkit_info->is_ratiometric[i] == (current_ratiometric_state == PTRUE)) &&
|
254
|
+
(ifkit_info->updated_since_last_ratiometric_cycle[i] == false) )
|
255
|
+
return false;
|
256
|
+
|
257
|
+
return true;
|
258
|
+
}
|
259
|
+
|
260
|
+
// This method ensures that the sensor data rates are set to what's been requested
|
261
|
+
// by the user. It's typically only used when initializing, and when turning on
|
262
|
+
// a uniform ratiometric state:
|
263
|
+
int interfacekit_assert_sensor_rates(PhidgetInfo *info) {
|
264
|
+
InterfaceKitInfo *ifkit_info = info->type_info;
|
265
|
+
CPhidgetInterfaceKitHandle interfacekit = (CPhidgetInterfaceKitHandle) info->handle;
|
266
|
+
|
267
|
+
for(int i=0;i<ifkit_info->analog_input_count;i++) {
|
268
|
+
if (ifkit_info->data_rates[i] > 0) {
|
269
|
+
report(CPhidgetInterfaceKit_setSensorChangeTrigger(interfacekit, i, 0));
|
270
|
+
report(CPhidgetInterfaceKit_setDataRate(interfacekit, i, ifkit_info->data_rates[i]));
|
271
|
+
} else {
|
272
|
+
report(CPhidgetInterfaceKit_setDataRate(interfacekit, i, 0));
|
273
|
+
report(CPhidgetInterfaceKit_setSensorChangeTrigger(interfacekit, i, ifkit_info->sensor_change_triggers[i]));
|
274
|
+
}
|
275
|
+
}
|
209
276
|
|
210
|
-
|
277
|
+
return EPHIDGET_OK;
|
278
|
+
}
|
279
|
+
|
280
|
+
int interfacekit_assert_dual_ratiometric_mode(PhidgetInfo *info) {
|
281
|
+
InterfaceKitInfo *ifkit_info = info->type_info;
|
282
|
+
|
283
|
+
if (!ifkit_info->is_dual_ratiometric_mode) {
|
284
|
+
ifkit_info->is_dual_ratiometric_mode = true;
|
285
|
+
memset(ifkit_info->updated_since_last_ratiometric_cycle, 0, sizeof(bool) * ifkit_info->analog_input_count);
|
286
|
+
return interfacekit_maximize_data_rate(info);
|
211
287
|
}
|
212
288
|
|
213
289
|
return EPHIDGET_OK;
|
214
290
|
}
|
291
|
+
|
292
|
+
int interfacekit_maximize_data_rate(PhidgetInfo *info) {
|
293
|
+
InterfaceKitInfo *ifkit_info = info->type_info;
|
294
|
+
CPhidgetInterfaceKitHandle interfacekit = (CPhidgetInterfaceKitHandle) info->handle;
|
295
|
+
|
296
|
+
for(int i=0;i<ifkit_info->analog_input_count;i++)
|
297
|
+
if (ifkit_info->data_rates[i] > 0) {
|
298
|
+
report(CPhidgetInterfaceKit_setSensorChangeTrigger(interfacekit, i, 0));
|
299
|
+
report(CPhidgetInterfaceKit_setDataRate(interfacekit, i, DEFAULT_INTERFACEKIT_DATA_RATE));
|
300
|
+
}
|
301
|
+
|
302
|
+
return EPHIDGET_OK;
|
303
|
+
}
|
304
|
+
|
305
|
+
int interfacekit_flip_ratiometric_state(PhidgetInfo *info) {
|
306
|
+
InterfaceKitInfo *ifkit_info = info->type_info;
|
307
|
+
CPhidgetInterfaceKitHandle interfacekit = (CPhidgetInterfaceKitHandle) info->handle;
|
308
|
+
|
309
|
+
int ret;
|
310
|
+
int current_state;
|
311
|
+
|
312
|
+
ret = CPhidgetInterfaceKit_getRatiometric(interfacekit, ¤t_state);
|
313
|
+
if (ret != EPHIDGET_OK) return ret;
|
314
|
+
|
315
|
+
ret = CPhidgetInterfaceKit_setRatiometric(interfacekit, (current_state) ? PFALSE : PTRUE );
|
316
|
+
if (ret != EPHIDGET_OK) return ret;
|
317
|
+
|
318
|
+
// We need to wait 50ms after this change before we start to read in values:
|
319
|
+
interfacekit_stamp_ratiometric_change(ifkit_info);
|
320
|
+
|
321
|
+
memset(ifkit_info->updated_since_last_ratiometric_cycle, 0, sizeof(bool) * ifkit_info->analog_input_count);
|
322
|
+
|
323
|
+
return EPHIDGET_OK;
|
324
|
+
}
|
325
|
+
|
326
|
+
// This stamps the ifkit struct with the current time. We cheat a bit to make
|
327
|
+
// our lookup code a bit easier, by stamping the case of 0 with a 1:
|
328
|
+
int interfacekit_stamp_ratiometric_change(InterfaceKitInfo *ifkit_info) {
|
329
|
+
struct timeval now;
|
330
|
+
gettimeofday(&now, NULL);
|
331
|
+
|
332
|
+
ifkit_info->ratiometric_changed_usec = (now.tv_usec == 0) ? 1 : now.tv_usec;
|
333
|
+
|
334
|
+
return EPHIDGET_OK;
|
335
|
+
}
|
@@ -12,19 +12,47 @@ const char MSG_DATA_RATE_EXCEEDS_LIMIT[] = "provided rate exceeds allowed limit"
|
|
12
12
|
const char MSG_CHANGE_TRIG_VALUE_MUST_BE_FIXNUM[] = "threshold must be a fixnum";
|
13
13
|
const char MSG_CHANGE_TRIG_EXCEEDS_LIMIT[] = "provided threshold exceeds allowed limit";
|
14
14
|
|
15
|
+
const char MSG_RATIOMETRIC_NOT_UNIFORM[] = "this action can't be performed unless all sensors are of the same ratiometric state";
|
16
|
+
|
15
17
|
/*
|
16
18
|
* Document-class: PhidgetsNative::InterfaceKit < PhidgetsNative::Device
|
17
19
|
*
|
18
20
|
* This class provides functionality specific to the "InterfaceKit" device class.
|
19
21
|
* Primarily, this phidget reports the values of analog and digital inputs, and
|
20
22
|
* provides interfaces for outputing to analog and digital components.
|
23
|
+
*
|
24
|
+
* *NOTE:* Unlike the native phidget libraries, this implementation supports a
|
25
|
+
* "Dual Ratiometric" mode for the interface kit. This dual-mode is acheived by
|
26
|
+
* rapidly cycling the controller between ratiometric on and off states in the
|
27
|
+
* device polling loop. The benefit to supporting mixed states is that you
|
28
|
+
* can support multiple devices types on a single controller. Unfortunately,
|
29
|
+
* the ramification of doing so reduces the sample rates to a small fraction
|
30
|
+
* (roughly 8 times per second) of the maximum data rate (roughly 125 times per
|
31
|
+
* second). For many applications, the sampling rates aren't so sensitive that
|
32
|
+
* dual-ratiometric mode will be a problem.
|
33
|
+
*
|
34
|
+
* "Dual ratiometric" mode will automatically enable itself if you specify per-sensor
|
35
|
+
* ratiometric states using the ratiometric() method. Similary, uniform-ratiometric
|
36
|
+
* mode will automatically return at any time that all sensors return to a uniform
|
37
|
+
* state. If you don't intend to take advantage of this feature, simply use the
|
38
|
+
* ratiometric= method to set all analog inputs to the same state, and ignore the
|
39
|
+
* ratiometric() method.
|
21
40
|
*/
|
22
41
|
|
42
|
+
/*
|
43
|
+
* Document-class: PhidgetsNative::InterfaceKit::RatiometricNotUniform
|
44
|
+
*
|
45
|
+
* This exception is raised when the library encounters a request that cannot be
|
46
|
+
* satisfied since the ratiometric state of the analog sensors are not uniform.
|
47
|
+
*/
|
23
48
|
void Init_phidgets_native_interfacekit(VALUE m_Phidget) {
|
24
49
|
VALUE c_Device = rb_const_get(m_Phidget, rb_intern("Device"));
|
25
50
|
|
26
51
|
VALUE c_InterfaceKit = rb_define_class_under(m_Phidget,"InterfaceKit",c_Device);
|
27
52
|
|
53
|
+
VALUE c_RatiometricNotUniform = rb_define_class_under(c_InterfaceKit,
|
54
|
+
"RatiometricNotUniform", rb_eStandardError);
|
55
|
+
|
28
56
|
/*
|
29
57
|
* Document-method: new
|
30
58
|
* call-seq:
|
@@ -119,6 +147,26 @@ void Init_phidgets_native_interfacekit(VALUE m_Phidget) {
|
|
119
147
|
*/
|
120
148
|
rb_define_method(c_InterfaceKit, "ratiometric=", interfacekit_ratiometric_set, 1);
|
121
149
|
|
150
|
+
/*
|
151
|
+
* Document-method: ratiometric
|
152
|
+
* call-seq:
|
153
|
+
* ratiometric(Fixnum index, Boolean state) -> Fixnum
|
154
|
+
*
|
155
|
+
* This method sets the ratiometric state for the analog sensor at the provided
|
156
|
+
* index. Note that phidget boards only support a board-wide ratiometric state.
|
157
|
+
* As such, when you set the state per the sensor in this library, the library
|
158
|
+
* will automatically toggle the board state between ratio and non-ratio metric
|
159
|
+
* modes for you. As a side-effect of the toggle action, your data rate will
|
160
|
+
* drop substantially, and you'll not be able to adjust the data_rate and
|
161
|
+
* change_trigger parameters. To re-enable the data_rate and change_trigger
|
162
|
+
* features, use the ratiometric= method to set the state for the entire board.
|
163
|
+
* The return value for this method is simply what was specified for
|
164
|
+
* the state.
|
165
|
+
* For more information on how analog inputs are polled, you can read up on the
|
166
|
+
* Phidget {Analog Input Primer}[http://www.phidgets.com/docs/Analog_Input_Primer]
|
167
|
+
*/
|
168
|
+
rb_define_method(c_InterfaceKit, "ratiometric", interfacekit_ratiometric, -1);
|
169
|
+
|
122
170
|
/*
|
123
171
|
* Document-method: data_rates_max
|
124
172
|
* call-seq:
|
@@ -256,8 +304,8 @@ VALUE interfacekit_initialize(VALUE self, VALUE serial) {
|
|
256
304
|
|
257
305
|
InterfaceKitInfo *ifkit_info = ALLOC(InterfaceKitInfo);
|
258
306
|
memset(ifkit_info, 0, sizeof(InterfaceKitInfo));
|
259
|
-
ifkit_info->is_ratiometric = false;
|
260
307
|
ifkit_info->is_data_rates_known = false;
|
308
|
+
ifkit_info->is_dual_ratiometric_mode = false;
|
261
309
|
|
262
310
|
CPhidgetInterfaceKitHandle interfacekit = 0;
|
263
311
|
ensure(CPhidgetInterfaceKit_create(&interfacekit));
|
@@ -339,6 +387,10 @@ VALUE interfacekit_sensor_count(VALUE self) {
|
|
339
387
|
VALUE interfacekit_is_ratiometric(VALUE self) {
|
340
388
|
InterfaceKitInfo *ifkit_info = device_type_info(self);
|
341
389
|
|
390
|
+
// If ratiometric state is not uniform, raise an exception
|
391
|
+
if (!interfacekit_ratiometric_state_is_uniform(ifkit_info))
|
392
|
+
interfacekit_raise_ratiometric_not_uniform();
|
393
|
+
|
342
394
|
return (ifkit_info->is_ratiometric) ? Qtrue : Qfalse;
|
343
395
|
}
|
344
396
|
|
@@ -346,19 +398,64 @@ VALUE interfacekit_ratiometric_set(VALUE self, VALUE is_ratiometric) {
|
|
346
398
|
PhidgetInfo *info = device_info(self);
|
347
399
|
InterfaceKitInfo *ifkit_info = device_type_info(self);
|
348
400
|
|
401
|
+
if (!info->is_attached) return Qnil;
|
402
|
+
|
403
|
+
bool is_ratiometric_bool;
|
404
|
+
|
349
405
|
if (TYPE(is_ratiometric) == T_TRUE)
|
350
|
-
|
406
|
+
is_ratiometric_bool = true;
|
351
407
|
else if (TYPE(is_ratiometric) == T_FALSE)
|
352
|
-
|
408
|
+
is_ratiometric_bool = false;
|
353
409
|
else
|
354
410
|
rb_raise(rb_eTypeError, MSG_RATIOMETRIC_MUST_BE_BOOL);
|
355
411
|
|
356
|
-
|
357
|
-
|
412
|
+
for(int i=0; i<ifkit_info->analog_input_count;i++)
|
413
|
+
ifkit_info->is_ratiometric[i] = is_ratiometric_bool;
|
414
|
+
|
415
|
+
ensure(interfacekit_assert_ratiometric_state( info ));
|
358
416
|
|
359
417
|
return is_ratiometric;
|
360
418
|
}
|
361
419
|
|
420
|
+
VALUE interfacekit_ratiometric(int argc, VALUE* argv, VALUE self) {
|
421
|
+
VALUE index;
|
422
|
+
VALUE is_ratiometric;
|
423
|
+
|
424
|
+
rb_scan_args(argc, argv, "11", &index, &is_ratiometric);
|
425
|
+
|
426
|
+
if (TYPE(index) != T_FIXNUM)
|
427
|
+
rb_raise(rb_eTypeError, MSG_SENSOR_INDEX_MUST_BE_FIXNUM);
|
428
|
+
|
429
|
+
PhidgetInfo *info = device_info(self);
|
430
|
+
InterfaceKitInfo *ifkit_info = info->type_info;
|
431
|
+
|
432
|
+
int index_int = FIX2INT(index);
|
433
|
+
if ((ifkit_info->analog_input_count == 0) || (index_int > (ifkit_info->analog_input_count-1)))
|
434
|
+
rb_raise(rb_eTypeError, MSG_SENSOR_INDEX_TOO_HIGH);
|
435
|
+
|
436
|
+
VALUE ret;
|
437
|
+
if(NIL_P(is_ratiometric)) {
|
438
|
+
// It's a get request:
|
439
|
+
ret = (ifkit_info->is_ratiometric[index_int]) ? Qtrue : Qfalse;
|
440
|
+
} else {
|
441
|
+
if (TYPE(is_ratiometric) == T_TRUE)
|
442
|
+
ifkit_info->is_ratiometric[index_int] = true;
|
443
|
+
else if (TYPE(is_ratiometric) == T_FALSE)
|
444
|
+
ifkit_info->is_ratiometric[index_int] = false;
|
445
|
+
else
|
446
|
+
rb_raise(rb_eTypeError, MSG_RATIOMETRIC_MUST_BE_BOOL);
|
447
|
+
|
448
|
+
ret = is_ratiometric;
|
449
|
+
|
450
|
+
if (interfacekit_ratiometric_state_is_uniform(ifkit_info))
|
451
|
+
ensure(interfacekit_assert_ratiometric_state(info));
|
452
|
+
else
|
453
|
+
ensure(interfacekit_assert_dual_ratiometric_mode(info));
|
454
|
+
}
|
455
|
+
|
456
|
+
return ret;
|
457
|
+
}
|
458
|
+
|
362
459
|
VALUE interfacekit_data_rates_max(VALUE self) {
|
363
460
|
InterfaceKitInfo *ifkit_info = device_type_info(self);
|
364
461
|
|
@@ -459,6 +556,10 @@ VALUE interfacekit_data_rate_set(VALUE self, VALUE index, VALUE rate) {
|
|
459
556
|
PhidgetInfo *info = device_info(self);
|
460
557
|
InterfaceKitInfo *ifkit_info = info->type_info;
|
461
558
|
|
559
|
+
// If ratiometric state is not uniform, raise an exception
|
560
|
+
if (!interfacekit_ratiometric_state_is_uniform(ifkit_info))
|
561
|
+
interfacekit_raise_ratiometric_not_uniform();
|
562
|
+
|
462
563
|
if (TYPE(index) != T_FIXNUM)
|
463
564
|
rb_raise(rb_eTypeError, MSG_SENSOR_INDEX_MUST_BE_FIXNUM);
|
464
565
|
|
@@ -486,6 +587,10 @@ VALUE interfacekit_change_trigger_set(VALUE self, VALUE index, VALUE rate_thresh
|
|
486
587
|
PhidgetInfo *info = device_info(self);
|
487
588
|
InterfaceKitInfo *ifkit_info = info->type_info;
|
488
589
|
|
590
|
+
// If ratiometric state is not uniform, raise an exception
|
591
|
+
if (!interfacekit_ratiometric_state_is_uniform(ifkit_info))
|
592
|
+
interfacekit_raise_ratiometric_not_uniform();
|
593
|
+
|
489
594
|
if (TYPE(index) != T_FIXNUM)
|
490
595
|
rb_raise(rb_eTypeError, MSG_SENSOR_INDEX_MUST_BE_FIXNUM);
|
491
596
|
|
@@ -509,3 +614,15 @@ VALUE interfacekit_change_trigger_set(VALUE self, VALUE index, VALUE rate_thresh
|
|
509
614
|
|
510
615
|
return rate_thresh;
|
511
616
|
}
|
617
|
+
|
618
|
+
void interfacekit_raise_ratiometric_not_uniform() {
|
619
|
+
VALUE m_Phidget = rb_const_get(rb_cObject, rb_intern("PhidgetsNative"));
|
620
|
+
|
621
|
+
VALUE c_InterfaceKit = rb_const_get(m_Phidget, rb_intern("InterfaceKit"));
|
622
|
+
|
623
|
+
VALUE c_Exception = rb_const_get(c_InterfaceKit, rb_intern("RatiometricNotUniform"));
|
624
|
+
|
625
|
+
rb_raise(c_Exception, MSG_RATIOMETRIC_NOT_UNIFORM);
|
626
|
+
|
627
|
+
return;
|
628
|
+
}
|
@@ -142,8 +142,13 @@ typedef struct interfacekit_info {
|
|
142
142
|
int digital_input_count_prior;
|
143
143
|
int digital_output_count_prior;
|
144
144
|
|
145
|
-
bool
|
146
|
-
|
145
|
+
bool is_dual_ratiometric_mode;
|
146
|
+
bool *is_ratiometric;
|
147
|
+
int ratiometric_changed_usec;
|
148
|
+
|
149
|
+
// This tracks whether it's time to change the ratiometric state, for the case
|
150
|
+
// of a dual-mode ratiometric change:
|
151
|
+
bool *updated_since_last_ratiometric_cycle;
|
147
152
|
|
148
153
|
|
149
154
|
// This flag works for all of the below properties
|
@@ -282,6 +287,14 @@ int CCONV interfacekit_on_detach(CPhidgetHandle phid, void *userptr);
|
|
282
287
|
int interfacekit_on_digital_change(CPhidgetInterfaceKitHandle interfacekit, void *userptr, int index, int inputState);
|
283
288
|
int interfacekit_on_analog_change(CPhidgetInterfaceKitHandle interfacekit, void *userptr, int index, int sensorValue);
|
284
289
|
int interfacekit_assert_ratiometric_state(PhidgetInfo *info);
|
290
|
+
bool interfacekit_ratiometric_state_is_uniform(InterfaceKitInfo *ifkit_info);
|
291
|
+
void interfacekit_raise_ratiometric_not_uniform();
|
292
|
+
int interfacekit_maximize_data_rate(PhidgetInfo *info);
|
293
|
+
int interfacekit_assert_dual_ratiometric_mode(PhidgetInfo *info);
|
294
|
+
int interfacekit_assert_sensor_rates(PhidgetInfo *info);
|
295
|
+
int interfacekit_stamp_ratiometric_change(InterfaceKitInfo *ifkit_info);
|
296
|
+
int interfacekit_flip_ratiometric_state(PhidgetInfo *info);
|
297
|
+
bool interfacekit_is_time_to_flip_ratiometric_state(PhidgetInfo *info);
|
285
298
|
VALUE interfacekit_initialize(VALUE self, VALUE serial);
|
286
299
|
VALUE interfacekit_close(VALUE self);
|
287
300
|
VALUE interfacekit_sensor_sample_rates(VALUE self);
|
@@ -291,6 +304,7 @@ VALUE interfacekit_output_count(VALUE self);
|
|
291
304
|
VALUE interfacekit_sensor_count(VALUE self);
|
292
305
|
VALUE interfacekit_is_ratiometric(VALUE self);
|
293
306
|
VALUE interfacekit_ratiometric_set(VALUE self, VALUE is_ratiometric);
|
307
|
+
VALUE interfacekit_ratiometric(int argc, VALUE* argv, VALUE self);
|
294
308
|
VALUE interfacekit_data_rates_max(VALUE self);
|
295
309
|
VALUE interfacekit_data_rates_min(VALUE self);
|
296
310
|
VALUE interfacekit_data_rates(VALUE self);
|
@@ -351,7 +365,6 @@ VALUE advancedservo_engaged_set(VALUE self, VALUE index, VALUE value);
|
|
351
365
|
VALUE advancedservo_is_stopped(VALUE self, VALUE index);
|
352
366
|
VALUE advancedservo_servo_parameters_set(VALUE self, VALUE index, VALUE min_us, VALUE max_us, VALUE degrees, VALUE velocity_max);
|
353
367
|
|
354
|
-
|
355
368
|
// Stub initializers:
|
356
369
|
VALUE accelerometer_initialize(VALUE self, VALUE serial);
|
357
370
|
VALUE advancedservo_initialize(VALUE self, VALUE serial);
|
data/phidgets_native.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: phidgets_native
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-09-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake-compiler
|
16
|
-
requirement: &
|
16
|
+
requirement: &70329854728720 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70329854728720
|
25
25
|
description: Native C-extension gem for the Phidgets library in ruby
|
26
26
|
email: cderose@derosetechnologies.com
|
27
27
|
executables: []
|
@@ -61,6 +61,7 @@ files:
|
|
61
61
|
- ext/phidgets_native/extconf.rb
|
62
62
|
- examples/advancedservo.rb
|
63
63
|
- examples/gps.rb
|
64
|
+
- examples/interface_kit-dualratiometric.rb
|
64
65
|
- examples/interface_kit.rb
|
65
66
|
- examples/list_all.rb
|
66
67
|
- examples/spatial.rb
|