rb_scope 2.0.2 → 2.0.4

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.
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