rb_scope 2.0.2 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,69 @@
1
+ ##
2
+ # rb_scope
3
+ #
4
+ # ( C2Ruby wrapper to NI-Scope drivers )
5
+ #
6
+ # version 2.0.4
7
+ # author hugo benichi
8
+ # email hugo.benichi@m4x.org
9
+ # copyright 2012 hugo benichi
10
+ #
11
+ # reproduction
12
+ #
13
+ # You can use this code without restriction if you mention my name in your project.
14
+ # Other than that, you can redistribute and/or modify without restriction.
15
+ #
16
+ # description
17
+ #
18
+ # A Ruby layer wrapping around C calls to the NI-Scope drivers.
19
+ # Most C data manipulation and C calls are done through the FFI gems.
20
+ # In addition a few C methods are provided for improved efficiency when handling data
21
+ #
22
+ # installation
23
+ #
24
+ # gem install ni_scope-x.y.z.gem
25
+ #
26
+ # usage
27
+ #
28
+ # refer to rb_scope/test/test_rb_scope.rb
29
+ #
30
+ # binaries
31
+ #
32
+ # the gem comes with precompiled 32bits libraries which should run on
33
+ # Windows 32/64 bits without issues if your niScope drivers are
34
+ # installed correctly
35
+ #
36
+ # If necessary, the source files and script files to produce the binaries
37
+ # are included with this gem, in rb_scope/ext/
38
+ #
39
+ # Two binary dlls are required
40
+ # Because of a recent change in the NiScope drivers, it is now necesaary to use
41
+ # MSVS cl and link to compiles them (it should be theoretically possible with mingw
42
+ # but I have better things to do). To be able to compile the project on your PC
43
+ # you should install Visual Studio C++ Express and use the VS developper prompt
44
+ # which automatically configures your %PATH% variable and allows you to use MSVS
45
+ # compiler and linker.
46
+ #
47
+ # If everything is fine you can just compile fetch.dll and rb_scope.dll with rake
48
+ # Run at the gem root directory the commands
49
+ # rake dll_fetch
50
+ # rake dll_rb_scope
51
+ #
52
+ # My scripts assume that you have a normal NiScope driver installation when looking
53
+ # for header files from NI. In the event these hardcoded paths are not correct, you
54
+ # should edit rakefile.rb and provides paths to headers and to static libraries .lib
55
+ #
56
+ # Expected path of the necessary header files and library:
57
+ #
58
+ # niScope.h, ivi.h, iviScope.h
59
+ # C:\Program Files (x86)\IVI Foundation\IVI\Include
60
+ #
61
+ # visa.h, visatype.h, vpptype.h
62
+ # C:\Program Files (x86)\IVI Foundation\VISA\WinNT\include
63
+ #
64
+ # niScope.lib
65
+ # C:\Program Files (x86)\IVI Foundation\IVI\Lib\msc
66
+ # C:\Program Files (x86)\IVI Foundation\IVI\Lib_x64\msc
67
+ # C:\Program Files (x86)\IVI Foundation\VISA\WinNT\Lib\msc
68
+ # C:\Program Files (x86)\IVI Foundation\VISA\WinNT\Lib_x64\msc
69
+ #
Binary file
File without changes
@@ -1,10 +1,11 @@
1
-
2
1
  #include <stdio.h>
3
2
  #include <stdlib.h>
4
3
  #include "fetch.h"
5
4
  #include "niScope.h"
6
5
 
7
- #define prompt(MSG, ...) printf("RbScope::Fetching::fetch.c >> " MSG, __VA_ARGS__)
6
+
7
+ #define prompt(MSG, ...) printf("RbScope::Fetching >> " MSG, __VA_ARGS__)
8
+
8
9
 
9
10
  typedef
10
11
  struct niScope_wfmInfo
@@ -23,54 +24,45 @@ DLL int fetch(
23
24
  int frm_chk = parameters-> frm_chk;
24
25
  double timeout = parameters-> timeout;
25
26
 
26
- char* buff0 = NULL;
27
- char* buff1 = NULL;
28
- buffer_address buf_chan0 = parameters-> chan0;
29
- buffer_address buf_chan1 = parameters-> chan1;
30
- void* context0 = parameters-> chan0_context;
31
- void* context1 = parameters-> chan1_context;
27
+ char* buf = NULL;
28
+ buffer_address buf_get = parameters-> buffer_get;
29
+ void* context = parameters-> context;
32
30
  error_handler err_clbck = parameters-> err_clbck;
33
31
 
34
- wfm_info frm_inf;
35
- wfm_info *frm_inf_p = &frm_inf;
36
-
37
- int i, rez, records_done;
32
+ #define err_check(ret_code) do {\
33
+ int err_check_local_err_code = ret_code;\
34
+ if( err_check_local_err_code < 0)\
35
+ {\
36
+ if (err_clbck)\
37
+ err_clbck( err_check_local_err_code );\
38
+ prompt( "early return from error\n");\
39
+ niScope_Abort(session);\
40
+ return -1;\
41
+ }\
42
+ } while (0)
43
+
44
+ wfm_info *frm_inf_p = malloc( sizeof(wfm_info) * 2 * frm_chk );
45
+ char* loc_buffer = malloc( 2 * frm_chk * frm_siz * sizeof(char) );
38
46
 
39
- rez = niScope_SetAttributeViBoolean(session, VI_NULL, NISCOPE_ATTR_ALLOW_MORE_RECORDS_THAN_MEMORY, 1); // maybe have to move this before horizontal configuration
40
- if( rez < 0) err_clbck(rez);
41
- rez = niScope_SetAttributeViInt32(session, VI_NULL, NISCOPE_ATTR_HORZ_RECORD_LENGTH, frm_siz);
42
- if( rez < 0) err_clbck(rez);
43
- rez = niScope_SetAttributeViInt32(session, VI_NULL, NISCOPE_ATTR_HORZ_NUM_RECORDS, frm_tot);
44
- if( rez < 0) err_clbck(rez);
45
- rez = niScope_SetAttributeViInt32(session, VI_NULL, NISCOPE_ATTR_FETCH_NUM_RECORDS, frm_chk);
46
- if( rez < 0) err_clbck(rez);
47
-
48
- prompt("starting fetching on %s\n", address);
47
+ int i, rez, records_done;
48
+
49
+ prompt("starting fetching on %s\n record length %i | record tot num %i | chunk %i\n", address, frm_siz, frm_tot, frm_chk);
49
50
  for (i = 0; i < frm_tot; i += frm_chk)
50
- {
51
-
52
- rez = niScope_SetAttributeViInt32(session, VI_NULL, NISCOPE_ATTR_FETCH_RECORD_NUMBER, i);
53
-
54
- if( rez < 0) err_clbck(rez);
55
- if (buf_chan0 && (buff0 = buf_chan0(context0)) ) /* this call can block ! */
56
- rez = niScope_FetchBinary8(session, "0", timeout, frm_siz, buff0, frm_inf_p);
57
-
58
- if( rez < 0) err_clbck(rez);
59
- if (buf_chan1 && (buff1 = buf_chan1(context1)) ) /* this call can block ! */
60
- rez = niScope_FetchBinary8(session, "1", timeout, frm_siz, buff1, frm_inf_p);
61
-
62
- if( rez < 0) err_clbck(rez);
63
-
64
- rez = niScope_GetAttributeViInt32(session, VI_NULL, NISCOPE_ATTR_RECORDS_DONE, &records_done);
65
- if( rez < 0) err_clbck(rez);
66
- prompt("%s, frames fetched #%i | measured #%i | left %i\n", address, i, records_done, records_done - i);
51
+ {
52
+ err_check( niScope_SetAttributeViInt32(session, VI_NULL, NISCOPE_ATTR_FETCH_RECORD_NUMBER, i) );
53
+ if (buf_get && !(buf = buf_get(context)) ) buf = loc_buffer;
54
+ err_check( niScope_FetchBinary8(session, "0,1", timeout, frm_siz, buf, frm_inf_p) );
55
+ err_check( niScope_GetAttributeViInt32(session, VI_NULL, NISCOPE_ATTR_RECORDS_DONE, &records_done) );
56
+ prompt("%s, frames fetched #%i | measured #%i | in dev mem %i\n", address, i, records_done, records_done - i);
67
57
  }
68
-
69
- rez = niScope_GetAttributeViInt32(session, VI_NULL, NISCOPE_ATTR_RECORDS_DONE, &records_done);
70
- if( rez < 0) err_clbck(rez);
71
58
 
72
- prompt("%s, total frames measured per channel: %i\n", address, records_done);
59
+ free(loc_buffer);
73
60
 
74
61
  return records_done;
75
62
 
76
- }
63
+ #undef err_check
64
+
65
+ }
66
+
67
+
68
+ #undef prompt
@@ -20,10 +20,8 @@
20
20
  {
21
21
  char* address; // physical address of the device
22
22
  error_handler err_clbck; // ruby callback to manage errors
23
- buffer_address chan0; // return the address of the next
24
- buffer_address chan1; // output buffer for chan0/1
25
- void* chan0_context; // context for the buffer_address functions
26
- void* chan1_context; // one per buffer
23
+ buffer_address buffer_get; // return the address of the next
24
+ void* context; // context for the buffer_address functions
27
25
  double timeout; // in sec; -1 = infinite
28
26
  int frm_siz; // numbr of data points per one frame
29
27
  int frm_tot; // total number of frm to fetch, per channels all chans one acq
File without changes
File without changes
File without changes
Binary file
File without changes
@@ -17,8 +17,6 @@
17
17
 
18
18
  # main namespace module which encapsulates the helper methods and wrappring API calls
19
19
  module RbScope
20
-
21
- # <TO_DO> all addressedd from conf file / NiScope to auto-detect them ?
22
20
 
23
21
  class << self
24
22
 
@@ -29,6 +27,7 @@ module RbScope
29
27
 
30
28
  end
31
29
 
30
+ # load every required components
32
31
  [
33
32
  'rb_scope/api',
34
33
  'rb_scope/fetch',
@@ -1,10 +1,43 @@
1
1
  module RbScope
2
2
 
3
+ # This module acts as the Ruby interface to the C API.
4
+ # It loads the niScope dll library and links itself to the dll functions.
5
+ # It also loads all the macro constants defined in niScope.h for easier
6
+ # scripting of the digitizer devices from Ruby.
3
7
  module API
4
8
 
5
- require 'rb_scope/api/niScope_api'
9
+ require 'ffi'
10
+ require 'rb_scope/api/niScope_template'
6
11
  require 'rb_scope/api/niScope_values'
7
12
 
13
+ begin
14
+ extend FFI::Library
15
+ ffi_lib $LOAD_PATH.map{ |path| path+"/rb_scope/rb_scope.dll"}
16
+ Template.each{ |sig|
17
+ attach_function(
18
+ sig[0].to_s.sub("niScope", "rbScope").to_sym,
19
+ sig[1].map{|t| Types[:ruby][t] || t },
20
+ sig[2]
21
+ )
22
+ }
23
+ rescue
24
+ RbScope::prompt "could not load rb_scope.dll library"
25
+ end
26
+
27
+ class << self
28
+ def handle_error address, visa_id, err_code, &block
29
+ buf1 = FFI::MemoryPointer.new :char, 1024
30
+ buf2 = FFI::MemoryPointer.new :char, 1024
31
+ rbScope_errorHandler(visa_id, err_code, buf1, buf2)
32
+ puts "RbScope error for session id %s / address %i:" % [address, visa_id],
33
+ " source: %s" % buf1.read_string(),
34
+ " message: %s" % buf2.read_string()
35
+ #abord acquisition
36
+ #close ses
37
+ block.call if block
38
+ end
39
+ end
40
+
8
41
  end
9
42
 
10
43
  end
@@ -11,7 +11,7 @@ module RbScope
11
11
 
12
12
  Hash.new.tap{ |pairs|
13
13
  File.open(File.dirname(__FILE__) + '/niScope_pairs.const', 'r').readlines.tap do |lines|
14
- pairs[lines.shift] = lines.shift until lines.empty? #good 2 shift order
14
+ pairs[lines.shift] = lines.shift until lines.empty? # good 2 shift order
15
15
  end
16
16
  }.each do |k,v|
17
17
  begin
Binary file
@@ -1,25 +1,26 @@
1
1
  module RbScope
2
2
 
3
3
  module Fetch
4
+
5
+ WfmInfoSize = 7 * 8 + 4
4
6
 
5
7
  require 'ffi'
6
8
  extend FFI::Library
7
9
 
8
- #begin
10
+ begin
9
11
  ffi_lib $LOAD_PATH.map{ |path| path+"/rb_scope/fetch.dll"}
10
12
  attach_function :fetch, [:pointer], :int32, :blocking => true
11
- #rescue
12
- # RbScope::prompt "could not load fetch.dll library"
13
- #end
13
+ rescue
14
+ RbScope::prompt "could not load fetch.dll library"
15
+ end
14
16
 
15
17
  # simple Struct wrapper to pass information to fetch.c/fetch()
16
- class Helper < FFI::ManagedStruct
18
+ # no internal memory allocation so no need to use ManagedStruct
19
+ class Helper < FFI::Struct
17
20
  layout :address, :pointer,
18
21
  :error, :pointer,
19
- :buff0, :pointer,
20
- :buff1, :pointer,
21
- :context0, :pointer,
22
- :context1, :pointer,
22
+ :buf_get, :pointer,
23
+ :context, :pointer,
23
24
  :timeout, :double,
24
25
  :points, :int32, #also frn_siz
25
26
  :records, :int32, #also frm_tot
@@ -27,11 +28,6 @@ module RbScope
27
28
  :session, :uint32
28
29
 
29
30
  Default = {
30
- error: nil,
31
- buff0: nil,
32
- buff1: nil,
33
- context0: nil,
34
- context1: nil,
35
31
  timeout: 10.0,
36
32
  records: 1,
37
33
  chunk: 1,
@@ -44,25 +40,66 @@ module RbScope
44
40
  class Session
45
41
 
46
42
  def run param, &block
43
+ self[:ALLOW_MORE_RECORDS_THAN_MEMORY,:bool] = 1
44
+ self[:HORZ_NUM_RECORDS,:int] = param[:records] # number of records to fetch
45
+ self[:FETCH_NUM_RECORDS,:int] = param[:chunk] # number of records to fetch per call to Fetch
46
+ self.acquire # starts acquisition
47
+ block.call if block # call pre-fetching block if necessary
48
+ start = Time.new
49
+ Fetch::fetch Fetch::Helper.new.tap{ |h|
50
+ Fetch::Helper::Default.each_pair{ |k,v| h[k] = param[k] || v } # params or use default
51
+ h[:address] = FFI::MemoryPointer.from_string @address
52
+ h[:session] = @visa_id
53
+ h[:points] = @points
54
+ h[:buf_get], h[:context] = param[:buf]
55
+ h[:error] = param[:error] || FFI::Function.new(:void,[:int32]){ |code| self.check code }
56
+ }
57
+ puts "elapsed %ssec" % (Time.new - start)
58
+ self.stop
59
+ self
60
+ end
47
61
 
48
- h = Helper.new
49
- Helper::Default.each_pair{ |k,v| h[k] = param[k] || v } #configure from parameters or ortherwise use default
62
+ # does not work at the moment
63
+ def run_ruby param, &block
64
+ records, chunk = param[:records], param[:chunk]
65
+ wfm_info_p = FFI::MemoryPointer.new :int32, 2 * chunk * Fetch::WfmInfoSize
66
+ self[:ALLOW_MORE_RECORDS_THAN_MEMORY,:bool] = 1
67
+ self[:HORZ_NUM_RECORDS,:int] = records # number of records to fetch
68
+ self[:FETCH_NUM_RECORDS,:int] = chunk # number of records to fetch per call to Fetch
69
+ self.acquire # starts acquisition
70
+ block.call if block # call pre-fetching block if necessary
50
71
 
51
- h[:address] = FFI::MemoryPointer.from_string @address
52
- h[:session] = FFI::MemoryPointer.from_string @visa_id
53
- h[:points] = @points
54
- begin
55
- h[:buff0], h[:context0] = param[:chan0].call, param[:chan0].context if param[:chan0]
56
- h[:buff1], h[:context1] = param[:chan1].call, param[:chan1].context if param[:chan1]
57
- rescue
58
- RbScope::prompt "could not configure channels output buffers"
72
+ start = Time.new
73
+ i = 0
74
+ while i < records
75
+ self[:FETCH_RECORD_NUMBER, :int] = i
76
+ check API::niScope_FetchBinary8 @visa_id, "0,1", 10.0, @points, param[:buf].call, wfm_info_p
77
+ done = self[:RECORDS_DONE, :int]
78
+ puts "RbScope::Fetching (ruby) >> %s, frames fetched #%i | measured #%i | in dev mem %i" % [
79
+ @address,
80
+ i,
81
+ done,
82
+ done - i,
83
+ ]
84
+ i += chunk
59
85
  end
86
+ puts "elapsed %ssec" % (Time.new - start)
87
+
88
+ self.stop
89
+ self
90
+ end
60
91
 
61
- self.acquire
62
- block.call if block # call pre-fetching block if necessary
63
- Fetch::fetch h
64
- self
65
-
92
+ def waveform channel = "0"
93
+ wfm_info_p = FFI::MemoryPointer.new :int32, 2 * Fetch::WfmInfoSize
94
+ buffer = FFI::MemoryPointer.new :char, 2 * @points
95
+ self[:ALLOW_MORE_RECORDS_THAN_MEMORY,:bool] = 1
96
+ self[:HORZ_NUM_RECORDS,:int] = 1
97
+ self[:FETCH_NUM_RECORDS,:int] = 1
98
+ self.acquire
99
+ self[:FETCH_RECORD_NUMBER, :int] = 0
100
+ check API::niScope_FetchBinary8 @visa_id, channel, 10.0, @points, buffer, wfm_info_p
101
+ self.stop
102
+ buffer.get_array_of_char 0, 2 * @points
66
103
  end
67
104
 
68
105
  end
@@ -2,35 +2,38 @@ module RbScope
2
2
 
3
3
  # Helper class to encapsulate data and state relative to a device Session
4
4
  # This is the main class that clients instantiate to use the gem.
5
- # <TO_DO> 1) implement errors 2) attributes setters/getters
6
- #
7
- # typical usage: RbScope::Session.new("mydevice").configure parameters
8
- #
9
5
  class Session
10
6
 
11
7
  attr_reader :address, :visa_id, :status
12
8
 
13
- #starts a new connection
9
+ # starts a new connection
14
10
  def initialize address, &block
15
11
  @address = address
16
12
  session_p = FFI::MemoryPointer.new :pointer, 1
17
- @status = API::rbScope_init address, 1, 1, session_p
18
- #handle error if @status < 0
19
- @visa_id = session_p.read_pointer.read_uint32
20
- prompt "session ##{@visa_id} for device #{@address} initalized with status #{@status}"
13
+ check API::rbScope_init address, 1, 1, session_p
14
+ @visa_id = session_p.read_uint32
15
+ RbScope::prompt "session #%i for device %s initalized with status %i" % [@visa_id, @address, @status]
16
+ check API::rbScope_ConfigureAcquisition @visa_id, API::Values::NISCOPE_VAL_NORMAL
21
17
  self.instance_eval &block if block
22
18
  self
23
19
  end
24
20
 
25
21
  # cleanup method called by the garbage collector
26
22
  def self.release session
27
- if API::rbScope_close(session.visa_id) < 0
28
- #handle error
29
- end
23
+ session.check API::rbScope_close(session.visa_id)
30
24
  end
31
25
 
32
- require 'rb_scope/session_methods'
33
- require 'rb_scope/session_attributes'
26
+ # store the NiScope return code into @status
27
+ # and check if the return code is an error code
28
+ # if error, call error_handler
29
+ def check name = nil, code
30
+ @status = code
31
+ puts "return code for %s: %i" % [name, @status] if name
32
+ API::handle_error @address, @visa_id, @status if @status < 0
33
+ end
34
+
35
+ require 'rb_scope/session/method_dispatch'
36
+ require 'rb_scope/session/attributes'
34
37
 
35
38
  end
36
39
 
@@ -0,0 +1,78 @@
1
+ module RbScope
2
+
3
+ class Session
4
+
5
+ Attribute_Types = {
6
+ int: "Int32",
7
+ int32: "Int32",
8
+ bool: "Boolean",
9
+ uint16: "Boolean",
10
+ boolean: "Boolean",
11
+ real64: "Real64",
12
+ double: "Real64",
13
+ float: "Real64",
14
+ string: "String",
15
+ pchar: "String"
16
+ }
17
+
18
+ Pointer_Types = [
19
+ int: :int32,
20
+ int32: :int32,
21
+ bool: :uint16,
22
+ uint16: :uint16,
23
+ boolean: :uint16,
24
+ real64: :double,
25
+ double: :double,
26
+ float: :double,
27
+ string: :string,
28
+ pchar: :string
29
+ ]
30
+
31
+ # gives the actual lengtt of one measured frame
32
+ def actual_points
33
+ p = FFI::MemoryPointer.new :int32, 1
34
+ check API::rbScope_ActualRecordLength( @visa_id, p)
35
+ p.read_int32
36
+ end
37
+
38
+ # gives the actual number of recorded waveform
39
+ def actual_records chan = "0,1"
40
+ p = FFI::MemoryPointer.new :int32, 1
41
+ check API::rbScope_ActualNumWfms( @visa_id, chan, p)
42
+ p.read_int32
43
+ end
44
+
45
+ # attributes getter
46
+ def [] attrb_name = nil, attrb_type = nil
47
+ if attrb_name && attrb_type
48
+ getter = "rbScope_GetAttributeVi%s" % Attribute_Types[attrb_type]
49
+ attrb_id = API::Values.const_get "NISCOPE_ATTR_#{attrb_name}".to_sym
50
+ store_t = Pointer_Types[attrb_type]
51
+ store = FFI::MemoryPointer.new store_t, case store_t
52
+ when :string then 128
53
+ when :double then 2
54
+ else 1
55
+ end
56
+ check API.send setter, @visa_id, nil, attrb_name, store
57
+ case store_t
58
+ when :int32 then store.read_int32
59
+ when :uint16 then store.read_uint16
60
+ when :double then store.read_double
61
+ when :string then store.read_string
62
+ end
63
+ end
64
+ end
65
+
66
+ # attributes setter
67
+ def []= attrb_name = nil, attrb_type = nil, attrb_value
68
+ if attrb_name && attrb_type
69
+ setter = "rbScope_SetAttributeVi#{Attribute_Types[attrb_type]}".to_sym
70
+ attrb_id = API::Values.const_get "NISCOPE_ATTR_#{attrb_name}".to_sym
71
+ check API.send setter, @visa_id, nil, attrb_id, attrb_value
72
+ self
73
+ end
74
+ end
75
+
76
+ end
77
+
78
+ end
@@ -0,0 +1,111 @@
1
+ module RbScope
2
+
3
+ class Session
4
+
5
+ # This table defines the how the methods from the niScope dll are hooked to instances
6
+ # of the Session class.
7
+ # Arguments are passed to each methods with an Hash and through their Hash keys
8
+ Methods = [
9
+ [:calibrate, "CalSelfCalibrate", ["0,1", 0]],
10
+ [:acquire, "InitiateAcquisition", []],
11
+ [:stop, "Abort", []],
12
+
13
+ [:trig_now, "ConfigureTriggerImmediate", []],
14
+ [:trig_digi,
15
+ "ConfigureTriggerDigital",
16
+ [API::Values::NISCOPE_VAL_EXTERNAL, :slope, :deadtime, 0.0]],
17
+ [:trig_edge,
18
+ "ConfigureTriggerEdge",
19
+ [API::Values::NISCOPE_VAL_EXTERNAL, :level, :slope, :coupling, :deadtime, 0.0]],
20
+
21
+ [:vertical, "ConfigureVertical",
22
+ [:channel, :range, 0.0, :coupling, 1.0, 1]],
23
+ [:channel, "ConfigureChanCharacteristics",
24
+ [:channel, :impedance, :bandwidth]],
25
+ [:horizontal, "ConfigureHorizontalTiming",
26
+ [:rate, :points, :position, :records, 1]],
27
+ ]
28
+
29
+ # default values for parameters of configuration functions
30
+ Defaults = {
31
+ deadtime: 0.0,
32
+ slope: API::Values::NISCOPE_VAL_POSITIVE,
33
+ trig_coupling: API::Values::NISCOPE_VAL_DC,
34
+ level: 0.5,
35
+ position: 0.5,
36
+ coupling: API::Values::NISCOPE_VAL_DC,
37
+ impedance: API::Values::NISCOPE_VAL_1_MEG_OHM,
38
+ #impedance: 50.0,
39
+ bandwidth: API::Values::NISCOPE_VAL_BANDWIDTH_FULL,
40
+ rate: 100000000.0,
41
+ points: 1000,
42
+ records: 1000,
43
+ range: 1.0,
44
+ }
45
+
46
+ # this block of code does the actual patching
47
+ # for each method declared in Methods,
48
+ # it deynamically defines a dispatch method
49
+ # which sets arguments according to the info found in Methods
50
+ # if a symbol is found
51
+ # the dispatcher looks for the user provided hash
52
+ # and tries to get a value
53
+ # if it is null, it used the defaults value
54
+ # if not a symbol, then the hardcoded value is used
55
+ Methods.each do |sig|
56
+ define_method(sig[0]) do |args=nil|
57
+ meth = "rbScope_#{sig[1]}".to_sym # generate the method name found in RbScope::API
58
+ args_chain = [@visa_id] + # first arg is always the session Id number
59
+ sig[2].map{ |x|
60
+ if x.is_a? Symbol # if x is a symbol, check for user provided value
61
+ args[x] || Defaults[x] # if no value use default
62
+ else
63
+ x # else use the hardcoded value
64
+ end
65
+ }
66
+ check API::send meth, *args_chain # finally dispatch the method call to RbScope::API
67
+ self
68
+ end
69
+ end
70
+
71
+ # helper method for horizontal configuration
72
+ alias_method :horizontal_pre, :horizontal
73
+ def horizontal param
74
+ @points = param[:points] || Defaults[:points]
75
+ horizontal_pre param
76
+ end
77
+
78
+ # helper method for vertical configuration
79
+ alias_method :channel_pre, :channel
80
+ def channel i, param
81
+ param.clone.tap{ |hash|
82
+ hash[:channel] = i.to_s
83
+ self.channel_pre hash
84
+ self.vertical hash
85
+ }
86
+ end
87
+
88
+ # helper method for trigger configuration
89
+ def trigger param
90
+ case param[:type] || :edge
91
+ when :edge then self.trig_edge param
92
+ when :digi then self.trig_digi param
93
+ when :now then self.trig_now param
94
+ when :soft then self.trig_now param
95
+ end
96
+ end
97
+
98
+ # 1-in-5 configuration methods with the convention that there is a :channel key
99
+ # which points to an array of subhash for both channels which looks like:
100
+ # parameters = {:channel [ {range: 0.1, chan_impendance: 50, ... }, {...} ]}
101
+ def configure parameters
102
+ self.horizontal parameters
103
+ parameters[:channel].each_with_index{ |chan_param, i|
104
+ self.channel i, param
105
+ } if parameters[:channel]
106
+ self.trigger parameters
107
+ end
108
+
109
+ end
110
+
111
+ end
@@ -9,7 +9,7 @@ name = 'rb_scope'
9
9
  end
10
10
 
11
11
  task :gem_install => :gem_build do
12
- gemfile = Dir.new("./").entries.select{ |f| f =~ /rb_scope-[\d]+\.[\d]+\.[\d]+.gem/ }[0]
12
+ gemfile = Dir.new("./").entries.select{ |f| f =~ /rb_scope-[\d]+\.[\d]+\.[\d]+.gem/ }.sort[-1]
13
13
  sh "gem install %s" % gemfile
14
14
  end
15
15
 
@@ -46,7 +46,7 @@ end
46
46
  task :set_path do
47
47
  puts "you might need to run the command prompt as Administrator"
48
48
  #ask for VC env var batch script
49
- sh '"C:\Program Files (x86)\MVS10.0\VC\vcvarsall.bat"'
49
+ #sh '"C:\Program Files (x86)\MVS10.0\VC\vcvarsall.bat"'
50
50
  #ask for path to niScope.h
51
51
  #ask for path to ivi.h and visa.h
52
52
  path_include = '"C:\Program Files (x86)\IVI Foundation\VISA\WinNT\include"'
@@ -1,3 +1,35 @@
1
- require "rb_scope"
1
+ require "rb_scope"
2
+ require "c_buffer"
2
3
 
3
- puts "ok"
4
+ records = 10000
5
+ points = 1000
6
+ chunk = 1000
7
+ buf_num = 32
8
+ size = 2 * chunk * points
9
+ dc = RbScope::API::Values::NISCOPE_VAL_DC
10
+ megaohm = 50.0 #RbScope::API::Values::NISCOPE_VAL_1_MEG_OHM
11
+
12
+ digitizer = RbScope::Session.new 'Dev1' do |d|
13
+ d.stop
14
+ d.horizontal(rate: 1E9, points: points, records: records, position: 0.5)
15
+ d.channel 0, { range: 0.1, coupling: dc, impedance: megaohm}
16
+ d.channel 1, { range: 0.1, coupling: dc, impedance: megaohm}
17
+ d.trigger( type: :edge, level: 0.5, coupling: dc)
18
+ end
19
+
20
+ buffer = CBuffer.new( path: "data.raw", chunk: size, length: buf_num)
21
+ buffer_get = FFI::Function.new(:pointer, [:pointer]){ |v| buffer.input }
22
+
23
+ buffer.output
24
+
25
+ digitizer.run(
26
+ records: records,
27
+ chunk: chunk,
28
+ buf: [buffer_get, nil]
29
+ )
30
+
31
+ buffer.stop
32
+
33
+ RbScope::Session.release digitizer
34
+
35
+ puts "ok"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rb_scope
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: 2.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-15 00:00:00.000000000 Z
12
+ date: 2012-07-09 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: A Ruby layer wrapping around C calls to the NI-Scope drivers based on
15
15
  the ffi gem api
@@ -18,32 +18,32 @@ executables: []
18
18
  extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
- - lib/rb_scope/api/niScope_api.rb
22
21
  - lib/rb_scope/api/niScope_template.rb
23
22
  - lib/rb_scope/api/niScope_values.rb
24
- - lib/rb_scope/api.rb
23
+ - lib/rb_scope/session/attributes.rb
24
+ - lib/rb_scope/session/method_dispatch.rb
25
25
  - lib/rb_scope/fetch.rb
26
26
  - lib/rb_scope/session.rb
27
- - lib/rb_scope/session_attributes.rb
28
- - lib/rb_scope/session_methods.rb
27
+ - lib/rb_scope/api.rb
29
28
  - lib/rb_scope.rb
30
29
  - lib/rb_scope/api/niScope_pairs.const
31
30
  - lib/rb_scope/fetch.dll
32
31
  - lib/rb_scope/rb_scope.dll
33
- - lib/rb_scope/fetch.lib
34
- - lib/rb_scope/rb_scope.lib
35
- - ext/rb_scope/fetching/fetch.c
36
32
  - ext/rb_scope/wrapper.c
33
+ - ext/rb_scope/fetching/fetch.c
37
34
  - ext/rb_scope/fetching/fetch.h
38
35
  - ext/rb_scope/example.rb
39
- - ext/rb_scope/generators/extract_names.rb
40
36
  - ext/rb_scope/generators/extract_pairs.rb
41
37
  - ext/rb_scope/generators/wrapper_generator.rb
38
+ - ext/rb_scope/generators/extract_names.rb
42
39
  - ext/rb_scope/generators/extract_all.sh
40
+ - ext/rb_scope/fetch.dll
41
+ - ext/rb_scope/rb_scope.dll
42
+ - ext/rb_scope/rb_scope.lib
43
+ - ext/rb_scope/fetch.lib
43
44
  - test/test_rb_scope.rb
44
- - compile_cl.bat
45
45
  - rakefile.rb
46
- - README.txt
46
+ - README
47
47
  homepage: http://github.com/hugobenichi/rb_scope
48
48
  licenses: []
49
49
  post_install_message:
@@ -64,7 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
64
64
  version: '0'
65
65
  requirements: []
66
66
  rubyforge_project:
67
- rubygems_version: 1.8.16
67
+ rubygems_version: 1.8.11
68
68
  signing_key:
69
69
  specification_version: 3
70
70
  summary: C2Ruby wrapper to NI-Scope drivers
data/README.txt DELETED
@@ -1,26 +0,0 @@
1
- ##
2
- # ni_scope
3
- #
4
- # ( C2Ruby wrapper to NI-Scope drivers )
5
- #
6
- # version 2.0.1
7
- # author hugo benichi
8
- # email hugo.benichi@m4x.org
9
- # copyright 2012 hugo benichi
10
- #
11
- # reproduction
12
- #
13
- # You can use this code without restriction if you mention my name in your project.
14
- # Other than that, you can redistribute and/or modify without restriction.
15
- #
16
- # description
17
- #
18
- # A Ruby layer wrapping around C calls to the NI-Scope drivers.
19
- # Most C data manipulation and C calls are done through the FFI gems.
20
- # In addition a few C methods are provided for improved efficiency when handling data
21
- #
22
- # installation
23
- #
24
- # gem install ni_scope-x.y.z.gem
25
- #
26
- ##
@@ -1,17 +0,0 @@
1
-
2
- :: Bat script for compilation of the rb_scope.dll using MSVS cl and link.
3
- :: This script has been automatically generated by rake from the template in rakefile.rb.
4
- ::
5
- :: author hugo benichi
6
- :: email hugo.benichi@gmail.com
7
- :: copyright 2012 hugo benichi
8
-
9
- call "C:\Program Files (x86)\MVS10.0\VC\vcvarsall.bat"
10
-
11
- call ruby -Ilib ext\ni_scope\wrapper_generator.rb > ext\ni_scope\wrapper.c
12
-
13
- call cl -c .\ext\ni_scope\wrapper.c -I"C:\Program Files (x86)\IVI Foundation\VISA\WinNT\include"
14
-
15
- call link /DLL /OUT:ext\ni_scope\rb_scope.dll wrapper.obj "C:\Program Files (x86)\IVI Foundation\VISA\WinNT\Lib\msc\niScope.lib"
16
-
17
-
@@ -1,31 +0,0 @@
1
- module RbScope
2
-
3
- # This module acts as the Ruby interface to the C API.
4
- # It loads the niScope dll library and links itself to the dll functions.
5
- # It also loads all the macro constants defined in niScope.h for easier
6
- # scripting of the digitizer devices from Ruby.
7
- module API
8
-
9
- require 'ffi'
10
- require 'rb_scope/api/niScope_template'
11
- require 'rb_scope/api/niScope_values'
12
-
13
- extend FFI::Library
14
-
15
- #begin
16
- ffi_lib $LOAD_PATH.map{ |path| path+"/rb_scope/rb_scope.dll"}
17
- Template.each{ |sig|
18
- puts sig
19
- attach_function(
20
- sig[0].to_s.sub("niScope", "rbScope").to_sym,
21
- sig[1].map{|t| Types[:ruby][t] || t },
22
- sig[2]
23
- )
24
- }
25
- #rescue
26
- # RbScope::prompt "could not load rb_scope.dll library"
27
- #end
28
-
29
- end
30
-
31
- end
@@ -1,21 +0,0 @@
1
- module RbScope
2
-
3
- class Session
4
-
5
- Attribute = [
6
-
7
-
8
- ]
9
-
10
- Getters = [
11
-
12
-
13
- ]
14
-
15
- def define_attribute name, id, type
16
- #nantoka
17
- end
18
-
19
- end
20
-
21
- end
@@ -1,82 +0,0 @@
1
- module RbScope
2
-
3
- class Session
4
-
5
- # This table defines the how the methods from the niScope dll are hooked to instances
6
- # of the Session class.
7
- # Arguments are passed to each methods with an Hash and through their Hash keys
8
- Methods = [
9
- [:calibrate, "CalSelfCalibrate", ["0,1", 0]],
10
- [:acquire, "InitiateAcquisition", []],
11
- [:stop, "Abort", []],
12
-
13
- [:trig_now, "ConfigureTriggerImmediate", []],
14
- [:trig_digi,
15
- "ConfigureTriggerDigital",
16
- [API::Values::NISCOPE_VAL_EXTERNAL, :slope, :deadtime, 0.0]],
17
- [:trig_edge,
18
- "Configure_TriggerEdge",
19
- [API::Values::NISCOPE_VAL_EXTERNAL, :trig_voltage, :slope, :trig_coupling, :deadtime, 0.0]],
20
-
21
- [:vertical, "ConfigureVertical",
22
- [:channel, :range, 0.0, :coupling, 1.0, 1]],
23
- [:channel, "ConfigureChanCharacteristics",
24
- [:channel, :impedance, :bandwidth]],
25
- [:horizontal, "ConfigureHorizontalTiming",
26
- [:rate, :points, :trig_reference, :records, 1]],
27
- ]
28
-
29
- #this block of code does the actual patching
30
- Methods.each do |sig|
31
- define_method(sig[0]) do |*args|
32
- meth = "rbScope_#{sig[1]}".to_sym # generate the good method name found in RbScope::API
33
- args_chain = [@visa_id] # first arg is always the session Id number
34
- + sig[2].map{ |x|
35
- if x.is_a? Symbol # if x is a symbol, check for user provided value
36
- args[x] || Defaults[x] # if no value use default
37
- else
38
- x # else use the hardcoded value
39
- end
40
- }
41
- @status = API::send meth, args_chain # finally dispatch the method call to RbScope::API
42
- #handle_error if rez < 0
43
- self
44
- end
45
- end
46
-
47
- # 1-in-4 configuration methods with the convention that there is a :channel key
48
- # which points to an array of subhash for both channels which looks like:
49
- # parameters = {:channel [ {range: 0.1, chan_impendance: 50, ... }, {...} ]}
50
- def configure parameters
51
- @points = parameters[:points] || Defaults[:points]
52
- self.horizontal parameters
53
- parameters[:channel].each_with_index{ |p,i|
54
- self.channel i.to_s, p
55
- } if parameters[:channel]
56
- end
57
-
58
- #shortcut for channel configuration
59
- def channel chan, parameters
60
- param = parameters.clone.tap{ |hash| hash[:channel] = chan }
61
- [:channel, :vertical].each{ |meth| self.send meth, parame }
62
- end
63
-
64
- # default values for parameters of configuration functions
65
- Defaults = {
66
- deadtime: 0.0,
67
- slope: API::Values::NISCOPE_VAL_POSITIVE,
68
- trig_coupling: API::Values::NISCOPE_VAL_DC,
69
- trig_voltage: 0.5,
70
- trig_reference: 0.5,
71
- coupling: API::Values::NISCOPE_VAL_AC,
72
- impedance: API::Values::NISCOPE_VAL_1_MEG_OHM,
73
- bandwidth: API::Values::NISCOPE_VAL_BANDWIDTH_FULL,
74
- rate: 1000000,
75
- points: 1000,
76
- records: 1000,
77
- range: 1.0,
78
- }
79
-
80
- end
81
-
82
- end