sicl 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ = 0.1.0 2007-05-12
2
+
3
+ * Birthday!
@@ -0,0 +1,8 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+
6
+ ext/sicl.c
7
+ ext/extconf.rb
8
+ test/test_sicl.rb
@@ -0,0 +1,71 @@
1
+ SICL/Ruby
2
+ http://rubyforge.org/projects/sicl/
3
+
4
+ == DESCRIPTION:
5
+
6
+ SICL/Ruby is SICL(Standard Instrument Control Library) API module for
7
+ Ruby. SICL is part of the Agilent IO Libraries Suite product. SICL/Ruby
8
+ gives you a capability to control your instruments via GPIB, USB, and LAN.
9
+
10
+ == SYNOPSIS:
11
+
12
+ require 'sicl'
13
+
14
+ SICL.open('gpib0,17') do |io|
15
+
16
+ io.output('*IDN?')
17
+
18
+ puts io.enter
19
+
20
+ # ... instruments specific operations ...
21
+
22
+ end
23
+
24
+ or
25
+
26
+ require 'sicl'
27
+
28
+ io = SICL.open('gpib0,17')
29
+
30
+ io.output('*RST')
31
+
32
+ puts io.spoll
33
+
34
+ puts io.query('*IDN?')
35
+
36
+ # ... instruments specific operations ...
37
+
38
+ io.close
39
+
40
+ or
41
+
42
+ require 'sicl'
43
+
44
+ class MyInst < SICL::Instrument
45
+ def reset; output('*RST'); end
46
+ end
47
+
48
+ io = MyInst.new 'gpib0,17'
49
+
50
+ io.reset
51
+
52
+ # ... instruments specific operations ...
53
+
54
+ io.close
55
+
56
+ == REQUIREMENTS:
57
+
58
+ * Aiglent IO Libraries Suite 14.2
59
+
60
+ Agilent Technologies
61
+ http://www.home.agilent.com
62
+
63
+ == INSTALL:
64
+
65
+ * sudo gem install sicl
66
+
67
+ == LICENSE:
68
+
69
+ (GPL ver.2)
70
+
71
+ Copyright (c) 2007, Naoki Kobayashi
@@ -0,0 +1,47 @@
1
+ ################################################################################
2
+ #
3
+ # Copyright (c) 2007 Naoki Kobayashi
4
+ #
5
+ # This library is free software. ( except for SICL Library )
6
+ # You can distribute/modify this file under the same terms of ruby.
7
+ #
8
+ # $Header: $
9
+ #
10
+ ################################################################################
11
+
12
+ begin
13
+ require 'rubygems'
14
+ require 'rake/gempackagetask'
15
+ rescue Exception
16
+ nil
17
+ end
18
+
19
+ require "rake/clean"
20
+ require "rake/gempackagetask"
21
+
22
+ PKG_FILES = []
23
+ File.open("Manifest.txt") do |manifest|
24
+ manifest.each do |file|
25
+ PKG_FILES << file.chomp if file =~ /\w+/
26
+ end
27
+ end
28
+
29
+ task :default => :package
30
+
31
+ spec = Gem::Specification.new do |s|
32
+ s.name = "sicl"
33
+ s.version = "0.1.0"
34
+ s.summary = "Agilent SICL API module for Ruby."
35
+ s.autorequire = "sicl"
36
+ s.files = PKG_FILES
37
+ s.default_executable = "ext/extconf.rb"
38
+ s.extensions = ["ext/extconf.rb"]
39
+ s.description = <<EOF
40
+ SICL/Ruby is SICL(Standard Instrument Control Library) API module for Ruby. SICL is part of the Agilent IO Libraries Suite product. SICL/Ruby gives you a capability to control your instruments via GPIB, USB, and LAN.
41
+ EOF
42
+ end
43
+
44
+ Rake::GemPackageTask.new(spec) do |pkg|
45
+ pkg.need_tar_bz2 = true
46
+ pkg.need_tar_gz = true
47
+ end
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/ruby -W0
2
+
3
+ # temporary solution for cygwin
4
+ case RUBY_PLATFORM
5
+ when "i386-cygwin"
6
+ # default file location settings
7
+ SICL_DIR = "/cygdrive/c/Program Files/Agilent/IO Libraries Suite"
8
+ SICL_LIB_DIR = "#{SICL_DIR}/lib"
9
+ SICL_INC_DIR = "#{SICL_DIR}/include"
10
+ SICL32LIB = "sicl32.lib"
11
+ # target options
12
+ SICL_LIB_OPT = "--with-sicl-lib"
13
+ SICL_INC_OPT = "--with-sicl-include"
14
+
15
+ ARGV.delete_if do |arg|
16
+ case arg
17
+ when /^(#{SICL_INC_OPT}=)(.*)/
18
+ SICL_INC_DIR = $2
19
+ true
20
+ when /^(#{SICL_LIB_OPT}=)(.*)/
21
+ SICL_LIB_DIR = $2
22
+ true
23
+ else
24
+ false
25
+ end
26
+ end
27
+
28
+ ARGV << "#{SICL_INC_OPT}=#{SICL_INC_DIR}"
29
+ ARGV << "#{SICL_LIB_OPT}=."
30
+ SICL32LIB = "#{SICL_LIB_DIR}/#{SICL32LIB}"
31
+
32
+ raise IOError.new("'#{SICL32LIB}': No such file") unless File.exist?(SICL32LIB)
33
+
34
+ # convert dynamic link library to static link library
35
+ `printf 'NAME sicl32.dll\nEXPORTS\n' >x.def`
36
+ `nm -g --defined '#{SICL32LIB}' | sed -n '/00000000 I __imp__/s///p' >>x.def`
37
+ `dlltool --def=x.def --output-lib=libsicl.a`
38
+ `rm x.def`
39
+ else
40
+ end
41
+
42
+ require 'mkmf'
43
+
44
+ dir_config('sicl')
45
+
46
+ if have_header('sicl.h') and have_library('sicl')
47
+ create_makefile('sicl')
48
+ end
49
+
@@ -0,0 +1,710 @@
1
+ /*
2
+ * Copyright (c) 2005-2006 Naoki Kobayashi
3
+ *
4
+ * This library is free software. ( except for SICL Library )
5
+ * You can distribute/modify this file under the same terms of ruby.
6
+ *
7
+ * $Header: $
8
+ *
9
+ */
10
+
11
+ #define _REENT_ONLY
12
+
13
+ #include <ruby.h>
14
+ #include "sicl.h"
15
+
16
+ /* -----------------------------------------------------------------------
17
+ File Local Variables
18
+ ----------------------------------------------------------------------- */
19
+
20
+ /* prototype of class and module */
21
+ static VALUE mSicl;
22
+ static VALUE cInstrument;
23
+ static VALUE eSicl;
24
+
25
+ /* hash table of internal configurations */
26
+ static VALUE gConfig;
27
+
28
+ /* id of event handlers */
29
+ static ID s_errhdlr;
30
+ static ID s_srqhdlr;
31
+ static ID s_intrhdlr;
32
+
33
+ /* id of 'call' method of Proc object */
34
+ static ID s_call;
35
+
36
+ /* id of 'buf_mode' method of SICL::Instrument object */
37
+ static ID s_buf_mode;
38
+
39
+ static const VALUE READ_ALL_DATA = INT2FIX(-1);
40
+
41
+ /* -----------------------------------------------------------------------
42
+ struct cparse_params
43
+ ----------------------------------------------------------------------- */
44
+
45
+ struct instrument {
46
+ INST id;
47
+ int errno;
48
+ };
49
+
50
+ /* -----------------------------------------------------------------------
51
+ Utils
52
+ ----------------------------------------------------------------------- */
53
+
54
+ #define CLEAR_ERROR(inst) do { inst->errno=0; } while(0)
55
+
56
+ VALUE sicl_return ( VALUE self, struct instrument * inst, int error )
57
+ {
58
+ if ( error ) {
59
+ inst->errno = error;
60
+ } else {
61
+ inst->errno = 0;
62
+ }
63
+
64
+ return error ? Qnil : self;
65
+ }
66
+
67
+ /* -----------------------------------------------------------------------
68
+ SICL wrapper Main Routines
69
+ ----------------------------------------------------------------------- */
70
+
71
+ static VALUE sicl_close ( VALUE self )
72
+ {
73
+ rb_funcall ( self, rb_intern("close"), 0, 0 );
74
+ }
75
+
76
+ /* error handler ( dummy ) for sicl_enter () */
77
+ static void SICLCALLBACK dmy_handler ( INST id, int error )
78
+ {
79
+ ; /* do nothing. */
80
+ }
81
+
82
+ /* error handler */
83
+ static void SICLCALLBACK err_handler ( INST id, int error )
84
+ {
85
+ VALUE self = rb_hash_aref ( gConfig, INT2FIX(id) );
86
+ VALUE hdlr = rb_ivar_get ( self, s_errhdlr );
87
+
88
+ if ( ! NIL_P(self) ) {
89
+ /* save error code */
90
+ struct instrument * inst = NULL;
91
+ Data_Get_Struct ( self, struct instrument, inst );
92
+ inst->errno = error;
93
+ }
94
+
95
+ if ( ! NIL_P(hdlr) ) {
96
+ VALUE err = rb_ary_new ();
97
+ rb_ary_push ( err, INT2FIX(error) );
98
+ rb_ary_push ( err, rb_str_new2(igeterrstr(error)) );
99
+
100
+ rb_funcall ( hdlr, s_call, 1, err );
101
+ } else {
102
+ rb_raise ( eSicl, igeterrstr(error) );
103
+ }
104
+ }
105
+
106
+ /* srq handler */
107
+ static void SICLCALLBACK srq_handler ( INST id )
108
+ {
109
+ VALUE self = rb_hash_aref ( gConfig, INT2FIX(id) );
110
+ VALUE hdlr = rb_ivar_get ( self, s_srqhdlr );
111
+
112
+ if ( ! NIL_P(hdlr) )
113
+ rb_funcall ( hdlr, s_call, 0 );
114
+ }
115
+
116
+ /* interrupt handler */
117
+ static void SICLCALLBACK intr_handler ( INST id, long reason, long secval )
118
+ {
119
+ VALUE self = rb_hash_aref ( gConfig, INT2FIX(id) );
120
+ VALUE hdlr = rb_ivar_get ( self, s_srqhdlr );
121
+
122
+ if ( ! NIL_P(hdlr) )
123
+ rb_funcall ( hdlr, s_call, 2, INT2FIX(reason), INT2FIX(secval) );
124
+ }
125
+
126
+ VALUE sicl_igeterrstr ( int argc, VALUE * argv, VALUE self )
127
+ {
128
+ VALUE code = 0;
129
+
130
+ rb_scan_args ( argc, argv, "01", & code );
131
+
132
+ if ( TYPE(code)!=T_FIXNUM ) {
133
+ struct instrument * inst = NULL;
134
+
135
+ Data_Get_Struct ( self, struct instrument, inst );
136
+
137
+ if ( ! inst->errno ) return Qnil;
138
+
139
+ code = INT2FIX ( inst->errno );
140
+ }
141
+
142
+ if ( NIL_P(code) ) return code;
143
+
144
+ return rb_str_new2 ( igeterrstr ( FIX2INT ( code ) ) );
145
+ }
146
+
147
+ VALUE sicl_ionerror ( VALUE self, VALUE proc )
148
+ {
149
+ if ( NIL_P(proc) || CLASS_OF(proc)==rb_cProc ) {
150
+
151
+ rb_ivar_set ( self, s_errhdlr, proc );
152
+
153
+ } else {
154
+
155
+ rb_raise ( rb_eTypeError, "Need a block or nil" );
156
+
157
+ }
158
+
159
+ return self;
160
+ }
161
+
162
+ VALUE sicl_igetonerror ( VALUE self )
163
+ {
164
+ if ( rb_block_given_p() ) {
165
+
166
+ rb_ivar_set ( self, s_errhdlr, rb_block_proc() );
167
+
168
+ return self;
169
+
170
+ } else {
171
+
172
+ return rb_ivar_get ( self, s_errhdlr );
173
+
174
+ }
175
+ }
176
+
177
+ VALUE sicl_ionsrq ( VALUE self, VALUE proc )
178
+ {
179
+ struct instrument * inst = NULL;
180
+
181
+ Data_Get_Struct ( self, struct instrument, inst );
182
+
183
+ if ( NIL_P(proc) ) {
184
+
185
+ rb_ivar_set ( self, s_srqhdlr, proc );
186
+ ionsrq ( inst->id, 0 );
187
+
188
+ } else if ( CLASS_OF(proc)==rb_cProc ) {
189
+
190
+ rb_ivar_set ( self, s_srqhdlr, proc );
191
+ ionsrq ( inst->id, srq_handler );
192
+
193
+ } else {
194
+
195
+ rb_raise ( rb_eTypeError, "Need a block or nil" );
196
+
197
+ }
198
+
199
+ return self;
200
+ }
201
+
202
+ VALUE sicl_igetonsrq ( VALUE self )
203
+ {
204
+ struct instrument * inst = NULL;
205
+
206
+ Data_Get_Struct ( self, struct instrument, inst );
207
+
208
+ if ( rb_block_given_p() ) {
209
+
210
+ rb_ivar_set ( self, s_srqhdlr, rb_block_proc() );
211
+ ionsrq ( inst->id, srq_handler );
212
+
213
+ return self;
214
+
215
+ } else {
216
+
217
+ return rb_ivar_get ( self, s_srqhdlr );
218
+
219
+ }
220
+ }
221
+
222
+ VALUE sicl_ionintr ( VALUE self, VALUE proc )
223
+ {
224
+ struct instrument * inst = NULL;
225
+
226
+ Data_Get_Struct ( self, struct instrument, inst );
227
+
228
+ if ( NIL_P(proc) ) {
229
+
230
+ rb_ivar_set ( self, s_intrhdlr, proc );
231
+ ionintr ( inst->id, 0 );
232
+
233
+ } else if ( CLASS_OF(proc)==rb_cProc ) {
234
+
235
+ rb_ivar_set ( self, s_intrhdlr, proc );
236
+ ionintr ( inst->id, intr_handler );
237
+
238
+ } else {
239
+
240
+ rb_raise ( rb_eTypeError, "Need a block or nil" );
241
+
242
+ }
243
+
244
+ return self;
245
+ }
246
+
247
+ VALUE sicl_igetonintr ( VALUE self )
248
+ {
249
+ struct instrument * inst = NULL;
250
+
251
+ Data_Get_Struct ( self, struct instrument, inst );
252
+
253
+ if ( rb_block_given_p() ) {
254
+
255
+ rb_ivar_set ( self, s_intrhdlr, rb_block_proc() );
256
+ ionintr ( inst->id, intr_handler );
257
+
258
+ return self;
259
+
260
+ } else {
261
+
262
+ return rb_ivar_get ( self, s_intrhdlr );
263
+
264
+ }
265
+ }
266
+
267
+ VALUE sicl_s_allocate ( VALUE klass )
268
+ {
269
+ VALUE self = 0;
270
+ struct instrument * inst = NULL;
271
+
272
+ self = Data_Make_Struct ( klass, struct instrument, 0, 0, inst );
273
+
274
+ rb_ivar_set ( self, s_errhdlr, Qnil );
275
+ rb_ivar_set ( self, s_srqhdlr, Qnil );
276
+ rb_ivar_set ( self, s_intrhdlr, Qnil );
277
+ rb_ivar_set ( self, s_buf_mode, Qnil );
278
+
279
+ return self;
280
+ }
281
+
282
+ VALUE sicl_iopen ( VALUE self, VALUE addr )
283
+ {
284
+ struct instrument * inst = NULL;
285
+
286
+ Data_Get_Struct ( self, struct instrument, inst );
287
+
288
+ Check_Type ( addr, T_STRING );
289
+
290
+ inst->id = iopen ( RSTRING(addr)->ptr );
291
+ itimeout ( inst->id, 5000 );
292
+
293
+ rb_hash_aset ( gConfig, INT2FIX(inst->id), self );
294
+
295
+ CLEAR_ERROR ( inst );
296
+
297
+ if ( rb_block_given_p() ) {
298
+ return rb_ensure(rb_yield, self, sicl_close, self);
299
+ }
300
+
301
+ return self;
302
+ }
303
+
304
+ VALUE sicl_s_iopen ( VALUE klass, VALUE addr )
305
+ {
306
+ VALUE self = sicl_s_allocate (cInstrument);
307
+
308
+ return sicl_iopen ( self, addr );
309
+ }
310
+
311
+ VALUE sicl_initialize ( VALUE self, VALUE addr )
312
+ {
313
+ return sicl_iopen ( self, addr );
314
+ }
315
+
316
+ VALUE sicl_itimeout ( VALUE self, VALUE ms )
317
+ {
318
+ int err = 0;
319
+ struct instrument * inst = NULL;
320
+
321
+ Check_Type ( ms, T_FIXNUM );
322
+
323
+ Data_Get_Struct ( self, struct instrument, inst );
324
+
325
+ err = itimeout ( inst->id, FIX2INT(ms) );
326
+
327
+ return sicl_return ( self, inst, err );
328
+ }
329
+
330
+ VALUE sicl_igettimeout ( VALUE self )
331
+ {
332
+ int err = 0;
333
+ long tval = 0;
334
+ struct instrument * inst = NULL;
335
+
336
+ Data_Get_Struct ( self, struct instrument, inst );
337
+
338
+ err = igettimeout ( inst->id, & tval );
339
+
340
+ return sicl_return ( INT2FIX(tval), inst, err );
341
+ }
342
+
343
+ VALUE sicl_set_buf_mode ( VALUE self, VALUE enabled )
344
+ {
345
+ if ( NIL_P(enabled) )
346
+ rb_ivar_set ( self, s_buf_mode, Qnil );
347
+ else if ( TYPE(enabled)==T_FALSE )
348
+ rb_ivar_set ( self, s_buf_mode, Qfalse );
349
+ else
350
+ rb_ivar_set ( self, s_buf_mode, Qtrue );
351
+
352
+ return self;
353
+ }
354
+
355
+ VALUE sicl_get_buf_mode ( VALUE self )
356
+ {
357
+ return rb_ivar_get ( self, s_buf_mode );
358
+ }
359
+
360
+ VALUE sicl_iwrite ( VALUE self, VALUE cmd, VALUE eoi )
361
+ {
362
+ int err = 0;
363
+ struct instrument * inst = NULL;
364
+ int endi = 0; /* send END indicator, or not */
365
+ unsigned long actualcnt = 0;
366
+ char * ptr = NULL;
367
+ long len = 0;
368
+
369
+ int ( * write )( INST, char *, unsigned long, int, unsigned long * ) = iwrite;
370
+
371
+ Check_Type ( cmd, T_STRING );
372
+
373
+ if ( TYPE(eoi)==T_TRUE ) endi = 1;
374
+
375
+ Data_Get_Struct ( self, struct instrument, inst );
376
+
377
+ ptr = RSTRING(cmd)->ptr;
378
+ len = RSTRING(cmd)->len;
379
+
380
+ if ( rb_ivar_get( self, s_buf_mode )==Qtrue ) write = ifwrite;
381
+
382
+ while ( len>0 ) {
383
+ err = write ( inst->id, ptr, len, endi, & actualcnt );
384
+
385
+ if ( err ) break;
386
+
387
+ ptr += actualcnt;
388
+ len -= actualcnt;
389
+ }
390
+
391
+ return sicl_return ( self, inst, err );
392
+ }
393
+
394
+ VALUE sicl_iwrite_arg ( int argc, VALUE * argv, VALUE self )
395
+ {
396
+ VALUE cmd = 0;
397
+ VALUE eoi = 0;
398
+
399
+ rb_scan_args ( argc, argv, "11", & cmd, & eoi );
400
+
401
+ return sicl_iwrite ( self, cmd, eoi );
402
+ }
403
+
404
+ VALUE sicl_iread ( VALUE self, VALUE max )
405
+ {
406
+ int err = 0;
407
+ struct instrument * inst = NULL;
408
+ char buf[0x100];
409
+ int size = sizeof(buf)-1;
410
+ int len = NUM2INT(READ_ALL_DATA);
411
+ int reason = 0;
412
+ unsigned long actualcnt = 0;
413
+
414
+ int ( * read )( INST, char *, unsigned long, int *, unsigned long *) = iread;
415
+
416
+ VALUE str = rb_str_new2 ("");
417
+
418
+ buf[0] = '\0';
419
+
420
+ if ( ! NIL_P(max) ) len = NUM2INT(max);
421
+
422
+ Data_Get_Struct ( self, struct instrument, inst );
423
+
424
+ if ( rb_ivar_get( self, s_buf_mode )==Qtrue ) read = ifread;
425
+
426
+ for (;;) {
427
+ if ( len==0 ) break;
428
+
429
+ if ( 0<len && len<size ) size = len;
430
+
431
+ err = read ( inst->id, buf, size, & reason, & actualcnt );
432
+
433
+ if ( err && err!=I_ERR_TIMEOUT ) break;
434
+
435
+ len -= actualcnt;
436
+ rb_str_cat ( str, buf, actualcnt );
437
+
438
+ if ( err==I_ERR_TIMEOUT ) {
439
+ if ( RSTRING(str)->len>0 ) err = I_ERR_NOERROR;
440
+ break;
441
+ }
442
+ if ( reason==I_TERM_END ) break;
443
+ if ( reason==I_TERM_CHR ) break;
444
+ }
445
+
446
+ return sicl_return ( str, inst, err );
447
+ }
448
+
449
+ VALUE sicl_iread_arg ( int argc, VALUE * argv, VALUE self )
450
+ {
451
+ VALUE max = 0;
452
+
453
+ rb_scan_args ( argc, argv, "01", & max );
454
+
455
+ return sicl_iread ( self, max );
456
+ }
457
+
458
+ VALUE sicl_output ( VALUE self, VALUE cmd )
459
+ {
460
+ VALUE tmp = 0;
461
+ VALUE eoi = Qtrue;
462
+ VALUE reg1 = 0;
463
+ VALUE reg2 = 0;
464
+ VALUE blnk = 0;
465
+ ID s_gsub = 0;
466
+
467
+ Check_Type ( cmd, T_STRING );
468
+
469
+ reg1 = rb_reg_new ( "[\\s;]*$", 7, 0 );
470
+ reg2 = rb_reg_new ( "^[\\s;]*", 7, 0 );
471
+ blnk = rb_str_new2 ( "" );
472
+ s_gsub = rb_intern ( "gsub" );
473
+
474
+ tmp = rb_funcall ( cmd, s_gsub, 2, reg1, blnk );
475
+ cmd = rb_funcall ( tmp, s_gsub, 2, reg2, blnk );
476
+
477
+ rb_str_cat2 ( cmd, "\r\n" );
478
+
479
+ self = sicl_iwrite ( self, cmd, eoi );
480
+
481
+ return self;
482
+ }
483
+
484
+ VALUE sicl_enter ( VALUE self )
485
+ {
486
+ VALUE str = 0;
487
+ const ID s_chomp = rb_intern ( "chomp" );
488
+
489
+ ionerror ( dmy_handler );
490
+
491
+ str = sicl_iread ( self, READ_ALL_DATA );
492
+
493
+ ionerror ( err_handler );
494
+
495
+ if ( NIL_P(str) ) return Qnil;
496
+
497
+ str = rb_funcall ( str, s_chomp, 0 );
498
+
499
+ return str;
500
+ }
501
+
502
+ VALUE sicl_enter2 ( VALUE self, VALUE out )
503
+ {
504
+ VALUE str = 0;
505
+ const VALUE reg = rb_reg_new ( ".*", 2, 0 );
506
+ const ID s_gsub = rb_intern ( "gsub!" );
507
+
508
+ Check_Type ( out, T_STRING );
509
+
510
+ str = sicl_enter ( self );
511
+
512
+ if ( NIL_P(str) ) return Qnil;
513
+
514
+ rb_funcall ( out, s_gsub, 2, reg, str );
515
+
516
+ return self;
517
+ }
518
+
519
+ VALUE sicl_query ( VALUE self, VALUE cmd )
520
+ {
521
+ self = sicl_output ( self, cmd );
522
+
523
+ return NIL_P(self) ? Qnil : sicl_enter ( self );
524
+ }
525
+
526
+ VALUE sicl_ireadstb ( VALUE self )
527
+ {
528
+ int err = 0;
529
+ struct instrument * inst = NULL;
530
+ unsigned char stb = 0;
531
+
532
+ Data_Get_Struct ( self, struct instrument, inst );
533
+
534
+ err = ireadstb ( inst->id, & stb );
535
+
536
+ return sicl_return ( INT2FIX( stb ), inst, err );
537
+ }
538
+
539
+ int sicl_func ( VALUE self, int (*func)( INST ) )
540
+ {
541
+ int err = 0;
542
+ struct instrument * inst = NULL;
543
+
544
+ Data_Get_Struct ( self, struct instrument, inst );
545
+
546
+ err = func ( inst->id );
547
+
548
+ return sicl_return ( self, inst, err );
549
+ }
550
+
551
+ VALUE sicl_iclose ( VALUE self )
552
+ {
553
+ int err = 0;
554
+ struct instrument * inst = NULL;
555
+ INST id = 0;
556
+
557
+ Data_Get_Struct ( self, struct instrument, inst );
558
+
559
+ id = inst->id;
560
+
561
+ err = iclose ( inst->id );
562
+
563
+ if ( !err )
564
+ rb_hash_delete ( gConfig, INT2FIX(id) );
565
+
566
+ return !err ? Qtrue : Qfalse;
567
+ }
568
+
569
+ VALUE sicl_iflush ( int argc, VALUE * argv, VALUE self )
570
+ {
571
+ int err = 0;
572
+ struct instrument * inst = NULL;
573
+ VALUE mask = 0;
574
+
575
+ rb_scan_args ( argc, argv, "01", & mask );
576
+
577
+ if ( NIL_P(mask) ) mask = INT2FIX( I_BUF_READ | I_BUF_WRITE_END );
578
+
579
+ Check_Type ( mask, T_FIXNUM );
580
+
581
+ Data_Get_Struct ( self, struct instrument, inst );
582
+
583
+ err = iflush ( inst->id, FIX2INT(mask) );
584
+
585
+ return sicl_return ( self, inst, err );
586
+ }
587
+
588
+ VALUE sicl_igetaddr ( VALUE self )
589
+ {
590
+ int err = 0;
591
+ struct instrument * inst = NULL;
592
+ char * addr = NULL;
593
+
594
+ Data_Get_Struct ( self, struct instrument, inst );
595
+
596
+ err = igetaddr ( inst->id, & addr );
597
+
598
+ return sicl_return ( rb_str_new2 ( addr ), inst, err );
599
+ }
600
+
601
+ VALUE sicl_itermchr ( VALUE self, VALUE tchr )
602
+ {
603
+ int err = 0;
604
+ struct instrument * inst = NULL;
605
+
606
+ Data_Get_Struct ( self, struct instrument, inst );
607
+
608
+ Check_Type ( tchr, T_FIXNUM );
609
+
610
+ err = itermchr ( inst->id, FIX2INT(tchr) );
611
+
612
+ return sicl_return ( self, inst, err );
613
+ }
614
+
615
+ VALUE sicl_igettermchr ( VALUE self )
616
+ {
617
+ int err = 0;
618
+ struct instrument * inst = NULL;
619
+ int tchr = 0;
620
+
621
+ Data_Get_Struct ( self, struct instrument, inst );
622
+
623
+ err = igettermchr ( inst->id, & tchr );
624
+
625
+ return sicl_return ( INT2FIX ( tchr ), inst, err );
626
+ }
627
+
628
+ VALUE sicl_iabort ( VALUE self ) { sicl_func ( self, iabort ); }
629
+ VALUE sicl_iclear ( VALUE self ) { sicl_func ( self, iclear ); }
630
+ VALUE sicl_ilocal ( VALUE self ) { sicl_func ( self, ilocal ); }
631
+ VALUE sicl_iremote ( VALUE self ) { sicl_func ( self, iremote ); }
632
+ VALUE sicl_ilock ( VALUE self ) { sicl_func ( self, ilock ); }
633
+ VALUE sicl_iunlock ( VALUE self ) { sicl_func ( self, iunlock ); }
634
+ VALUE sicl_itrigger ( VALUE self ) { sicl_func ( self, itrigger ); }
635
+
636
+ /* -----------------------------------------------------------------------
637
+ Ruby Interface
638
+ ----------------------------------------------------------------------- */
639
+
640
+ void Init_sicl ()
641
+ {
642
+ mSicl = rb_define_module ( "SICL" );
643
+
644
+ rb_define_module_function( mSicl, "open", sicl_s_iopen, 1 );
645
+
646
+ rb_define_const ( mSicl, "BUF_READ" , INT2FIX(I_BUF_READ) );
647
+ rb_define_const ( mSicl, "BUF_WRITE" , INT2FIX(I_BUF_WRITE) );
648
+ rb_define_const ( mSicl, "BUF_WRITE_END" , INT2FIX(I_BUF_WRITE_END) );
649
+ rb_define_const ( mSicl, "BUF_DISCARD_READ" , INT2FIX(I_BUF_DISCARD_READ) );
650
+ rb_define_const ( mSicl, "BUF_DISCARD_WRITE", INT2FIX(I_BUF_DISCARD_WRITE) );
651
+
652
+ eSicl = rb_define_class_under ( mSicl, "Error", rb_eStandardError );
653
+
654
+ ionerror ( err_handler );
655
+
656
+ s_call = rb_intern ( "call" );
657
+
658
+ s_buf_mode = rb_intern ( "buf_mode" );
659
+
660
+ s_errhdlr = rb_intern ( "errhdlr" );
661
+ s_srqhdlr = rb_intern ( "srqhdlr" );
662
+ s_intrhdlr = rb_intern ( "intrhdlr" );
663
+
664
+ gConfig = rb_hash_new ();
665
+ rb_global_variable( & gConfig );
666
+
667
+ cInstrument = rb_define_class_under ( mSicl, "Instrument", rb_cObject );
668
+
669
+ rb_define_alloc_func ( cInstrument, sicl_s_allocate );
670
+
671
+ rb_define_method ( cInstrument, "initialize" , sicl_initialize, 1 );
672
+ rb_define_method ( cInstrument, "close" , sicl_iclose , 0 );
673
+ rb_define_method ( cInstrument, "write" , sicl_iwrite_arg, -1 );
674
+ rb_define_method ( cInstrument, "read" , sicl_iread_arg , -1 );
675
+ rb_define_method ( cInstrument, "spoll" , sicl_ireadstb , 0 );
676
+ rb_define_method ( cInstrument, "flush" , sicl_iflush , -1 );
677
+
678
+ rb_define_method ( cInstrument, "timeout=", sicl_itimeout , 1 );
679
+ rb_define_method ( cInstrument, "timeout" , sicl_igettimeout, 0 );
680
+ rb_define_method ( cInstrument, "termchr=", sicl_itermchr , 1 );
681
+ rb_define_method ( cInstrument, "termchr" , sicl_igettermchr, 0 );
682
+ rb_define_method ( cInstrument, "addr" , sicl_igetaddr , 0 );
683
+ rb_define_method ( cInstrument, "address" , sicl_igetaddr , 0 );
684
+ rb_define_method ( cInstrument, "errstr" , sicl_igeterrstr , -1 );
685
+
686
+ rb_define_method ( cInstrument, "output" , sicl_output, 1 );
687
+ rb_define_method ( cInstrument, "enter" , sicl_enter , 0 );
688
+ rb_define_method ( cInstrument, "query" , sicl_query , 1 );
689
+ rb_define_method ( cInstrument, "<<" , sicl_output, 1 );
690
+ rb_define_method ( cInstrument, ">>" , sicl_enter2, 1 );
691
+
692
+ rb_define_method ( cInstrument, "abort" , sicl_iabort , 0 );
693
+ rb_define_method ( cInstrument, "clear" , sicl_iclear , 0 );
694
+ rb_define_method ( cInstrument, "local" , sicl_ilocal , 0 );
695
+ rb_define_method ( cInstrument, "remote" , sicl_iremote , 0 );
696
+ rb_define_method ( cInstrument, "lock" , sicl_ilock , 0 );
697
+ rb_define_method ( cInstrument, "unlock" , sicl_iunlock , 0 );
698
+ rb_define_method ( cInstrument, "trigger", sicl_itrigger, 0 );
699
+
700
+ rb_define_method ( cInstrument, "on_error=", sicl_ionerror , 1 );
701
+ rb_define_method ( cInstrument, "on_error" , sicl_igetonerror, 0 );
702
+ rb_define_method ( cInstrument, "on_srq=" , sicl_ionsrq , 1 );
703
+ rb_define_method ( cInstrument, "on_srq" , sicl_igetonsrq , 0 );
704
+ rb_define_method ( cInstrument, "on_intrrupt=" , sicl_ionintr , 1 );
705
+ rb_define_method ( cInstrument, "on_intrrupt" , sicl_igetonintr , 0 );
706
+
707
+ /* accessor for @buf_mode */
708
+ rb_define_method ( cInstrument, "buf_mode=", sicl_set_buf_mode, 1 );
709
+ rb_define_method ( cInstrument, "buf_mode" , sicl_get_buf_mode, 0 );
710
+ }
@@ -0,0 +1,373 @@
1
+ #!/usr/bin/ruby
2
+ ################################################################################
3
+ #
4
+ # Copyright (c) 2005-2006 Naoki Kobayashi
5
+ #
6
+ # This library is free software.
7
+ # You can distribute/modify this script under the same terms of ruby.
8
+ #
9
+ # $Header: $
10
+ #
11
+ ################################################################################
12
+
13
+ ################################################################################
14
+ # OPTION SETTINGS
15
+ ################################################################################
16
+
17
+ require "optparse"
18
+
19
+ Settings = Hash.new
20
+ opts = OptionParser.new
21
+ opts.on( "-a", "--address ADDRESS", String ) { |v| Settings[:address] = v }
22
+ opts.parse!( ARGV )
23
+
24
+ ################################################################################
25
+ # PARAMETER VALIDATION
26
+ ################################################################################
27
+
28
+ address = Settings[:address]
29
+ address = "gpib0,17" unless address
30
+
31
+ ################################################################################
32
+ # CLASS DECLARATION
33
+ ################################################################################
34
+
35
+ require "runit/testcase"
36
+ require "runit/cui/testrunner"
37
+ require "sicl"
38
+
39
+ class TestSicl < RUNIT::TestCase
40
+
41
+ def TestSicl.suite(address)
42
+ @@address = address
43
+ @@idn_str = SICL.open(@@address).query("*idn?")
44
+ super()
45
+ end
46
+
47
+ class MyInstrument < SICL::Instrument
48
+
49
+ def initialize(addr)
50
+ super(addr)
51
+
52
+ reset
53
+ enable_srq_detection
54
+ end
55
+
56
+ def reset
57
+ output "*cls"
58
+ output "*rst"
59
+ query "*esr?"
60
+ end
61
+
62
+ def enable_srq_detection
63
+ output "*sre #{0x20}"
64
+ output "*ese #{0x3c}"
65
+ end
66
+
67
+ def raise_timeout(timeout=1000)
68
+ self.timeout = timeout
69
+ loop { break unless self.read }
70
+ end
71
+
72
+ def raise_srq(timeout=10)
73
+ self.output "xxx"
74
+ sleep timeout
75
+ end
76
+
77
+ end
78
+
79
+ NO_ERROR = "No error"
80
+ BAD_ADDRESS = "Bad address"
81
+ TIMEOUT_OCCURRED = "Timeout occurred"
82
+ INVALID_INST = "Invalid INST"
83
+
84
+ ESR_BIT = 5 # Standard Event Register
85
+ RQS_BIT = 6 # ReQuest Service
86
+
87
+ def setup
88
+ @exp = {}
89
+ @exp[:str] = @@idn_str
90
+ @exp[:chr] = @exp[:str][0].chr
91
+ @exp[:rgx] = /^#{@exp[:str]}/
92
+
93
+ @inst = MyInstrument.new @@address
94
+ end
95
+
96
+ def teardown
97
+
98
+ begin
99
+ @inst.on_error = nil
100
+ @inst.on_srq = nil
101
+ rescue
102
+ # do nothing...
103
+ end
104
+
105
+ end
106
+
107
+ def test_open0
108
+ ret = SICL.open(@@address) { |io|
109
+
110
+ res = io.write("*idn?\n").read
111
+ assert_match @exp[:rgx], res
112
+
113
+ res = io.output("*idn?").enter
114
+ assert_match @exp[:rgx], res
115
+
116
+ res = io.query("*idn?")
117
+ assert_match @exp[:rgx], res
118
+
119
+ io.address
120
+ }
121
+
122
+ assert_equal @@address, ret
123
+ end
124
+
125
+ def test_open1
126
+ err = assert_exception(SICL::Error) { SICL.open("xxx") }
127
+
128
+ assert_equal BAD_ADDRESS, err.message
129
+ end
130
+
131
+ def test_stb0
132
+ @inst.output("*sre #{0x00}")
133
+ @inst.output("*ese #{0x00}")
134
+
135
+ rqs = @inst.query("*stb?").to_i[RQS_BIT]
136
+ assert_equal 0, rqs
137
+ end
138
+
139
+ def test_stb1
140
+ @inst.output("xxx")
141
+
142
+ sleep 0.1
143
+
144
+ stb = @inst.query("*stb?").to_i
145
+
146
+ assert_equal 1, stb[ESR_BIT]
147
+ assert_equal 1, stb[RQS_BIT]
148
+ end
149
+
150
+ def test_stb2
151
+ @inst.output("xxx")
152
+
153
+ sleep 1
154
+
155
+ stb = @inst.spoll
156
+
157
+ assert_equal 1, stb[ESR_BIT]
158
+ assert_equal 1, stb[RQS_BIT]
159
+ end
160
+
161
+ def test_srq0
162
+ srq_occured = false
163
+
164
+ @inst.on_srq { srq_occured = true }
165
+
166
+ @inst.output("xxx")
167
+
168
+ 10.times { sleep 0.1 until srq_occured }
169
+
170
+ assert_equal true, srq_occured
171
+ end
172
+
173
+ def test_srq1
174
+ stb = 0
175
+
176
+ @inst.on_srq { sleep 1; stb = @inst.spoll }
177
+
178
+ @inst.output("xxx")
179
+
180
+ 10.times { sleep 0.1 if stb == 0 }
181
+
182
+ assert_equal 1, stb[ESR_BIT]
183
+ assert_equal 1, stb[RQS_BIT]
184
+ end
185
+
186
+ def test_write_and_read0
187
+ res = @inst.write("*idn?\n")
188
+ assert res
189
+
190
+ res = @inst.read 1
191
+ assert_equal @exp[:chr], res
192
+ end
193
+ def test_write_and_read1
194
+ res = @inst.write("*idn?\n").read 1
195
+ assert_equal @exp[:chr], res
196
+ end
197
+ def test_write_and_read2
198
+ res = @inst.write("*idn?\n").read 7
199
+ assert_equal @exp[:str][0...7], res
200
+ end
201
+ def test_write_and_read3
202
+ res = @inst.write("*i").write("dn").write("?\n").read 1
203
+ assert_equal @exp[:chr], res
204
+ end
205
+
206
+ def test_output_and_enter0
207
+ res = @inst.output("*idn?")
208
+ assert res
209
+ res = @inst.enter
210
+ assert_match @exp[:rgx], res
211
+ end
212
+
213
+ def test_output_and_enter1
214
+ res = @inst.output("*idn?").enter
215
+ assert_match @exp[:rgx], res
216
+ end
217
+
218
+ def test_output_and_enter2
219
+ res = @inst.output("*idn?\r\n \r\r\r\r;;\n;;\r\n\n").enter
220
+ assert_match @exp[:rgx], res
221
+ end
222
+
223
+ def test_output_and_enter3
224
+ @inst << "*idn?"
225
+ res = "" # @inst.enter
226
+ @inst >> res
227
+ assert_match @exp[:rgx], res
228
+ end
229
+
230
+ def test_error_message0
231
+ assert_equal NO_ERROR, @inst.errstr(0)
232
+ end
233
+
234
+ def test_error_message1
235
+ assert @inst.errstr(15)
236
+ end
237
+
238
+ def test_error_message2
239
+ assert_equal nil, @inst.errstr
240
+ end
241
+
242
+ def test_error_message3
243
+ error_message = ''
244
+
245
+ @inst.on_error { |err| error_message = err[1] }
246
+
247
+ @inst.raise_timeout
248
+
249
+ assert_equal TIMEOUT_OCCURRED, error_message
250
+ end
251
+
252
+ def test_error_message4
253
+ error_message = ''
254
+
255
+ @inst.on_error { |num, msg| error_message = msg }
256
+
257
+ @inst.raise_timeout
258
+
259
+ assert_equal TIMEOUT_OCCURRED, error_message
260
+ end
261
+
262
+ def test_error_close0
263
+ @inst.close
264
+ err = assert_exception(SICL::Error) { @inst.close }
265
+
266
+ assert_equal INVALID_INST, err.message
267
+ end
268
+
269
+ def test_error_close1
270
+ @inst.close
271
+ err = assert_exception(SICL::Error) { @inst.close }
272
+
273
+ assert_equal INVALID_INST, err.message
274
+ end
275
+
276
+ def test_error_timeout0
277
+ time_limit = 10000
278
+
279
+ @inst.timeout = time_limit
280
+
281
+ assert_equal time_limit, @inst.timeout
282
+ end
283
+
284
+ def test_error_timeout1
285
+ err = assert_exception(SICL::Error) {
286
+ @inst.raise_timeout
287
+ }
288
+
289
+ assert_equal TIMEOUT_OCCURRED, err.message
290
+ end
291
+
292
+ def test_error_timeout2
293
+ @inst.on_error = lambda {}
294
+
295
+ @inst.raise_timeout
296
+
297
+ assert true
298
+ end
299
+
300
+ def test_error_timeout3
301
+ @inst.on_error = lambda {}
302
+ @inst.on_error = nil
303
+
304
+ err = assert_exception(SICL::Error) {
305
+ @inst.raise_timeout
306
+ }
307
+
308
+ assert_equal TIMEOUT_OCCURRED, err.message
309
+ end
310
+
311
+ def test_error_timeout4
312
+ @inst.on_error {}
313
+
314
+ @inst.raise_timeout
315
+
316
+ assert true
317
+ end
318
+
319
+ def test_abort
320
+ assert @inst.abort if @@address =~ /^[gh]pib/ # gpib only
321
+ end
322
+
323
+ def test_clear
324
+ assert @inst.clear
325
+ end
326
+
327
+ def test_spoll
328
+ assert @inst.spoll
329
+ end
330
+
331
+ def test_local
332
+ assert @inst.local
333
+ end
334
+
335
+ def test_remote
336
+ assert @inst.remote
337
+ end
338
+
339
+ def test_flush0
340
+ assert @inst.flush
341
+ end
342
+
343
+ def test_flush1
344
+ assert @inst.flush(SICL::BUF_DISCARD_READ | SICL::BUF_DISCARD_WRITE)
345
+ end
346
+
347
+ def test_addr
348
+ assert_equal @inst.addr, @@address
349
+ end
350
+
351
+ def test_addr
352
+ assert_equal @inst.address, @@address
353
+ end
354
+
355
+ def test_termchr0
356
+ assert @inst.termchr = 0x20
357
+ assert_equal @inst.termchr, 0x20
358
+ end
359
+
360
+ def test_termchr1
361
+ assert @inst.termchr = " "[0]
362
+ assert_equal @inst.termchr, 0x20
363
+ end
364
+
365
+ end
366
+
367
+ ################################################################################
368
+ # MAIN ROUTINE
369
+ ################################################################################
370
+
371
+ if $0 == __FILE__ then
372
+ RUNIT::CUI::TestRunner.run(TestSicl.suite(address))
373
+ end
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.2
3
+ specification_version: 1
4
+ name: sicl
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.1.0
7
+ date: 2007-05-13 00:00:00 +09:00
8
+ summary: Agilent SICL API module for Ruby.
9
+ require_paths:
10
+ - lib
11
+ email:
12
+ homepage:
13
+ rubyforge_project:
14
+ description: SICL/Ruby is SICL(Standard Instrument Control Library) API module for Ruby. SICL is part of the Agilent IO Libraries Suite product. SICL/Ruby gives you a capability to control your instruments via GPIB, USB, and LAN.
15
+ autorequire: sicl
16
+ default_executable: ext/extconf.rb
17
+ bindir: bin
18
+ has_rdoc: false
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors: []
30
+
31
+ files:
32
+ - History.txt
33
+ - Manifest.txt
34
+ - README.txt
35
+ - Rakefile
36
+ - ext/sicl.c
37
+ - ext/extconf.rb
38
+ - test/test_sicl.rb
39
+ test_files: []
40
+
41
+ rdoc_options: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ executables: []
46
+
47
+ extensions:
48
+ - ext/extconf.rb
49
+ requirements: []
50
+
51
+ dependencies: []
52
+