origen_link 0.1.0.pre0 → 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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/bin/start_link_server +20 -0
  3. data/config/application.rb +0 -0
  4. data/config/boot.rb +3 -2
  5. data/config/commands.rb +0 -0
  6. data/config/version.rb +1 -1
  7. data/lib/origen_link.rb +1 -15
  8. data/lib/origen_link/callback_handlers.rb +13 -0
  9. data/lib/origen_link/server/jtag.rb +180 -0
  10. data/lib/origen_link/server/pin.rb +125 -0
  11. data/lib/origen_link/server/sequencer.rb +353 -0
  12. data/lib/origen_link/{includes_vector_based.rb → server_com.rb} +32 -7
  13. data/lib/origen_link/test/top_level.rb +48 -0
  14. data/lib/origen_link/test/top_level_controller.rb +44 -0
  15. data/lib/origen_link/test/vector_based.rb +25 -0
  16. data/lib/origen_link/vector_based.rb +254 -53
  17. data/lib/tasks/origen_link.rake +0 -0
  18. data/pattern/example.rb +0 -0
  19. data/pattern/jtag_100_operations.rb +0 -0
  20. data/pattern/jtag_comm_fail_test.rb +0 -0
  21. data/pattern/jtag_comm_test.rb +0 -0
  22. data/templates/web/index.md.erb +0 -0
  23. data/templates/web/layouts/_basic.html.erb +0 -0
  24. data/templates/web/partials/_navbar.html.erb +0 -0
  25. data/templates/web/release_notes.md.erb +0 -0
  26. metadata +32 -18
  27. data/lib/origen_link/test/regression_tests.rb +0 -68
  28. data/lib/origen_link/test/test_dut.rb +0 -46
  29. data/lib/origen_link/test/test_dut_controller.rb +0 -42
  30. data/lib/origen_link/test/vector_based_redefs.rb +0 -17
  31. data/lib/origen_link_server/LinkSequencer.rb +0 -333
  32. data/lib/origen_link_server/LinkTCPServer.rb +0 -45
  33. data/lib/origen_link_server/jtag_interface.rb +0 -177
  34. data/lib/origen_link_server/pin_interface.rb +0 -134
  35. data/lib/origen_link_server/test/test_Sequencer.rb +0 -51
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0e1bcf6176e63bcb31f823ec75e8171d5f41f678
4
- data.tar.gz: b8773221ecda2487be4b458341b07260f3298a38
3
+ metadata.gz: faee2177091aa943a5592a6bdf44edc8813eb3b8
4
+ data.tar.gz: f50c5b16dc546bd39c7fb45bacb11bd9340053f1
5
5
  SHA512:
6
- metadata.gz: e5f8bb591f2113d737a4e2ec9adcb035aab944e61558e7927004ef3ed6327c4438f9a0619c1ab181a41d124505aa1e6fe0e47238af876a26d1c4b88740b0f19f
7
- data.tar.gz: 5a345ff111d0fe9779bff83d317878addc8baec9551c546c471dcda03f65534d9360679e56b5d6519b66d22560975349921bc9e4bfc6b3a96f423c256e8acd3e
6
+ metadata.gz: b16813b53e7e2a87008c86055991cc18e4b113502e02437ca04ba1283d5950ffb9c41c618fb0d0e69990030ba6b82addfaa9ca552747c2607b2fab1398665af9
7
+ data.tar.gz: 71a143e7bf8008e829af1adf9cb5c6bfe7da1ec5748e824221fbf29648bcb698c19139b6a96d71064db9e81fb5938ff117f64912d6cc371128b9b5661eb9fbe3
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib'))
3
+ require 'socket'
4
+ require 'origen_link/server/sequencer'
5
+
6
+ server = TCPServer.open('', 12_777)
7
+ puts 'server started'
8
+ pinsequencer = OrigenLink::Server::Sequencer.new
9
+
10
+ loop do
11
+ client = server.accept
12
+ response = ''
13
+ while (message = client.gets) != "\n"
14
+ # process the message
15
+ # for now only pin_ messages are accepted
16
+ response = response + pinsequencer.processmessage(message.chomp) + "\n"
17
+ end
18
+ client.write(response)
19
+ client.close
20
+ end
File without changes
@@ -3,5 +3,6 @@
3
3
  # application requires
4
4
  require "origen_link"
5
5
 
6
- require "origen_link/test/test_dut"
7
- require "origen_link/test/test_dut_controller"
6
+ require "origen_link/test/top_level"
7
+ require "origen_link/test/top_level_controller"
8
+ require "origen_link/test/vector_based"
File without changes
@@ -2,7 +2,7 @@ module OrigenLink
2
2
  MAJOR = 0
3
3
  MINOR = 1
4
4
  BUGFIX = 0
5
- DEV = 0
5
+ DEV = nil
6
6
 
7
7
  VERSION = [MAJOR, MINOR, BUGFIX].join(".") + (DEV ? ".pre#{DEV}" : '')
8
8
  end
@@ -1,18 +1,4 @@
1
1
  require 'origen'
2
- require 'origen_testers'
3
2
  require 'socket'
4
3
 
5
- module OrigenLink
6
- # Load all files in the lib directory via a wildcard, if your project becomes
7
- # large or load order dependencies start to creep in then you may need to
8
- # start taking control of this manually as described above.
9
- # Note that there is no problem from requiring a file twice (Ruby will ignore
10
- # the second require), so if you have a file that must be required up front
11
- # you can do that one manually and the let the wildcard take care of the rest.
12
- # Dir.glob("#{File.dirname(__FILE__)}/**/*.rb").sort.each do |file|
13
- # require file
14
- # end
15
- Dir.glob("#{File.dirname(__FILE__)}/origen_link/*.rb").sort.each do |file|
16
- require file
17
- end
18
- end
4
+ require 'origen_link/vector_based'
@@ -0,0 +1,13 @@
1
+ module OrigenLink
2
+ class CallbackHandlers
3
+ include Origen::Callbacks
4
+
5
+ def pattern_generated(output_file)
6
+ tester.finalize_pattern(output_file)
7
+ end
8
+
9
+ def before_pattern(pattern_name)
10
+ tester.initialize_pattern
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,180 @@
1
+ require 'origen_link/server/pin'
2
+
3
+ module OrigenLink
4
+ module Server
5
+ class Jtag
6
+ attr_reader :tdoval
7
+ attr_accessor :verbose_enable
8
+ attr_accessor :anytdofail
9
+
10
+ def initialize(tdiio = 16, tdoio = 23, tmsio = 19, tckio = 26, tck_period = 0.000001)
11
+ @tdipin = Pin.new(tdiio, :out)
12
+ @tdopin = Pin.new(tdoio, :in)
13
+ @tmspin = Pin.new(tmsio, :out)
14
+ @tckpin = Pin.new(tckio, :out)
15
+ @tck_half_period = tck_period / 2
16
+ @tdoval = 0
17
+ @tdostr = ''
18
+ @verbose_enable = true
19
+ @anytdofail = false
20
+ end
21
+
22
+ def tck_period=(value)
23
+ @tck_half_period = value / 2
24
+ end
25
+
26
+ def destroy
27
+ @tdipin.destroy
28
+ @tdopin.destroy
29
+ @tmspin.destroy
30
+ @tckpin.destroy
31
+ @tdipin = nil
32
+ @tdopin = nil
33
+ @tmspin = nil
34
+ @tckpin = nil
35
+ end
36
+
37
+ def do_cycle(tdival, tmsval, capturetdo = false)
38
+ @tdipin.out(tdival)
39
+ @tmspin.out(tmsval)
40
+ sleep @tck_half_period
41
+ @tckpin.out(1)
42
+ sleep @tck_half_period
43
+
44
+ if capturetdo
45
+ @tdostr = @tdopin.in + @tdostr
46
+ end
47
+ @tckpin.out(0)
48
+ end
49
+
50
+ def do_tlr
51
+ 8.times { do_cycle(0, 1) }
52
+ do_cycle(0, 0)
53
+ end
54
+
55
+ def do_shift(numbits, value, capturetdo = false, suppresscomments = false, tdocompare = '')
56
+ @tdoval = 0
57
+ @tdostr = ''
58
+ (numbits - 1).times do |bit|
59
+ do_cycle(value[bit], 0, capturetdo)
60
+ end
61
+ do_cycle(value[numbits - 1], 1, capturetdo)
62
+
63
+ @tdoval = @tdostr.to_i(2) if capturetdo
64
+
65
+ if !(suppresscomments) && @verbose_enable && capturetdo
66
+ puts 'TDO output = 0x' + @tdoval.to_s(16)
67
+ end
68
+
69
+ if capturetdo && tdocompare != ''
70
+ thiscomparefail = false
71
+ numbits.times do |bit|
72
+ if tdocompare[numbits - 1 - bit] == 'H'
73
+ compareval = 1
74
+ elsif tdocompare[numbits - 1 - bit] == 'L'
75
+ compareval = 0
76
+ else
77
+ compareval = @tdoval[bit]
78
+ end
79
+
80
+ if @tdoval[bit] != compareval
81
+ @anytdofail = true
82
+ thiscomparefail = true
83
+ end
84
+ end
85
+
86
+ tdovalstr = @tdoval.to_s(2)
87
+ tdovalstr = '0' * (numbits - tdovalstr.length) + tdovalstr
88
+
89
+ if thiscomparefail
90
+ puts '****************************>>>>>>>>>>>>>>>>> TDO failure <<<<<<<<<<<<<<<<<<****************************'
91
+ puts 'expected: ' + tdocompare
92
+ puts 'received: ' + tdovalstr
93
+ else
94
+ puts 'TDO compare pass'
95
+ puts 'expected: ' + tdocompare
96
+ puts 'received: ' + tdovalstr
97
+ end
98
+ end
99
+ end
100
+
101
+ def do_ir(numbits, value, options = {})
102
+ defaults = {
103
+ capturetdo: false,
104
+ suppresscomments: false,
105
+ tdocompare: ''
106
+ }
107
+ options = defaults.merge(options)
108
+
109
+ if !(options[:suppresscomments]) && @verbose_enable
110
+ puts " shift IR, #{numbits} bits, value = 0x" + value.to_s(16)
111
+ end
112
+
113
+ if options[:tdocompare] != ''
114
+ capturetdo = true
115
+ else
116
+ capturetdo = options[:capturetdo]
117
+ end
118
+
119
+ # Assume starting from run test idle
120
+ # Advance to shift IR
121
+ do_cycle(0, 1)
122
+ do_cycle(0, 1)
123
+ do_cycle(0, 0)
124
+ do_cycle(0, 0)
125
+
126
+ do_shift(numbits, value, capturetdo, options[:suppresscomments], options[:tdocompare])
127
+
128
+ # Return to run test idle
129
+ do_cycle(0, 1)
130
+ do_cycle(0, 0)
131
+ end
132
+
133
+ def do_dr(numbits, value, options = {})
134
+ defaults = {
135
+ capturetdo: true,
136
+ suppresscomments: false,
137
+ tdocompare: ''
138
+ }
139
+ options = defaults.merge(options)
140
+ if !(options[:suppresscomments]) && @verbose_enable
141
+ puts " shift DR, #{numbits} bits, value = 0x" + value.to_s(16)
142
+ end
143
+
144
+ if options[:tdocompare] != ''
145
+ capturetdo = true
146
+ else
147
+ capturetdo = options[:tdocompare]
148
+ end
149
+
150
+ # Assume starting from run test idle
151
+ # Advance to shift DR
152
+ do_cycle(0, 1)
153
+ do_cycle(0, 0)
154
+ do_cycle(0, 0)
155
+
156
+ do_shift(numbits, value, capturetdo, options[:suppresscomments], options[:tdocompare])
157
+
158
+ # Return to run test idle
159
+ do_cycle(0, 1)
160
+ do_cycle(0, 0)
161
+ end
162
+
163
+ def pause_dr
164
+ do_cycle(0, 1)
165
+ do_cycle(0, 0)
166
+ do_cycle(0, 0)
167
+ do_cycle(0, 1)
168
+ do_cycle(0, 0)
169
+ do_cycle(0, 1)
170
+ do_cycle(0, 1)
171
+ do_cycle(0, 0)
172
+ end
173
+
174
+ def pause_ir
175
+ do_cycle(0, 1)
176
+ pause_dr
177
+ end
178
+ end
179
+ end
180
+ end
@@ -0,0 +1,125 @@
1
+ # OrigenLink::Server::Pin class manipulate input/output pins of the Udoo
2
+ # using exported file objects. If the pin is not exported, it
3
+ # will be exported when a pin is initialized
4
+ #
5
+ # initialize:
6
+ # description - This method will execute system command
7
+ # "sudo echo ionumber > /sys/class/gpio/export"
8
+ # to create the IO file interface. It will
9
+ # set the direction, initial pin state and initialize
10
+ # instance variables
11
+ # ionumber - required, value indicating the pin number (BCM IO number,
12
+ # not the header pin number)
13
+ # direction - optional, specifies the pin direction. A pin is
14
+ # initialized as an input if a direction isn't specified.
15
+ #
16
+ #
17
+ # out:
18
+ # description - Sets the output state of the pin. If the pin
19
+ # is setup as an input, the direction will first
20
+ # be changed to output.
21
+ #
22
+ #
23
+ # in:
24
+ # description - Reads and returns state of the pin. If the pin
25
+ # is setup as an output, the direction will first
26
+ # be changed to input.
27
+ #
28
+ #
29
+ # update_direction:
30
+ # description - Sets the pin direction
31
+ #
32
+ # direction - specifies the pin direction. A pin is
33
+ # initialized as an input if a direction isn't specified.
34
+ #
35
+ # Valid direction values:
36
+ # :in - input
37
+ # :out - output
38
+ # :out_high - output, initialized high
39
+ # :out_low - output, initialized low
40
+ module OrigenLink
41
+ module Server
42
+ class Pin
43
+ @@pin_setup = {
44
+ in: 'in',
45
+ out: 'out'
46
+ }
47
+
48
+ attr_reader :gpio_valid
49
+
50
+ def initialize(ionumber, direction = :in)
51
+ @ionumber = Integer(ionumber)
52
+ @pin_dir_name = "#{Server.gpio_dir}/gpio#{@ionumber}/direction"
53
+ @pin_val_name = "#{Server.gpio_dir}/gpio#{@ionumber}/value"
54
+ if !File.exist?(@pin_dir_name)
55
+ system("echo #{@ionumber} > #{Server.gpio_dir}/export")
56
+ sleep 0.05
57
+ if $CHILD_STATUS == 0
58
+ @gpio_valid = true
59
+ else
60
+ @gpio_valid = false
61
+ end
62
+ else
63
+ @gpio_valid = true
64
+ end
65
+ if @gpio_valid
66
+ if File.writable?(@pin_dir_name)
67
+ @pin_dir_obj = File.open(@pin_dir_name, 'w')
68
+ update_direction(direction)
69
+ else
70
+ @gpio_valid = false
71
+ puts "#{@pin_dir_name} is not writable. Fix permissions or run as super user."
72
+ end
73
+ @pin_val_obj = File.open(@pin_val_name, 'r+') if @gpio_valid
74
+ end
75
+ end
76
+
77
+ def destroy
78
+ if @gpio_valid
79
+ @pin_dir_obj.close
80
+ @pin_val_obj.close
81
+ # system("echo #{@ionumber} > /sys/class/gpio/unexport")
82
+ # puts "pin #{@ionumber} is no longer exported"
83
+ end
84
+ end
85
+
86
+ def out(value)
87
+ if @gpio_valid
88
+ if @direction == :in
89
+ update_direction(:out)
90
+ end
91
+ @pin_val_obj.write(value)
92
+ @pin_val_obj.flush
93
+ end
94
+ end
95
+
96
+ def in
97
+ if @gpio_valid
98
+ if @direction == :out
99
+ update_direction(:in)
100
+ end
101
+ # below is original read - slow to reopen every time
102
+ # File.open(@pin_val_name, 'r') do |file|
103
+ # file.read#.chomp
104
+ # end
105
+ # end original read
106
+ @pin_val_obj.pos = 0
107
+ @pin_val_obj.getc
108
+ end
109
+ end
110
+
111
+ def update_direction(direction)
112
+ if @gpio_valid
113
+ @pin_dir_obj.pos = 0
114
+ @pin_dir_obj.write(@@pin_setup[direction])
115
+ @pin_dir_obj.flush
116
+ @direction = direction
117
+ end
118
+ end
119
+
120
+ def to_s
121
+ 'OrigenLinkPin' + @ionumber.to_s
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,353 @@
1
+ require 'origen_link/server/pin'
2
+
3
+ ##################################################
4
+ # OrigenLink::Server::Sequencer Class
5
+ # Instance variables:
6
+ # pinmap: hash with ["pin name"] = pin object
7
+ # patternpinindex: hash with ["pin name"] =
8
+ # integer index into vector data
9
+ # patternpinorder: Array with pin names in
10
+ # the vector order
11
+ #
12
+ # This class processes messages targeted for
13
+ # pin sequencer interface (vector pattern
14
+ # execution).
15
+ #
16
+ # Supported messages:
17
+ # pin_assign (create pin mapping)
18
+ # ex: "pin_assign:tck,3,extal,23,tdo,5"
19
+ #
20
+ # pin_patternorder (define vector pin order)
21
+ # ex: "pin_patternorder:tdo,extal,tck"
22
+ #
23
+ # pin_cycle (execute vector data)
24
+ # ex: "pin_cycle:H11"
25
+ #
26
+ # pin_clear (clear all setup information)
27
+ # ex: "pin_clear:"
28
+ #
29
+ # pin_format (setup a pin with return format)
30
+ # first argument is the timeset
31
+ # ex: "pin_format:1,tck,rl"
32
+ #
33
+ # pin_timing (define when pin events happen)
34
+ # timing is stored in a timeset hash
35
+ # first argument is the timeset key
36
+ # ex: "pin_timing:1,tdi,0,tdo,1,tms,0
37
+ ##################################################
38
+ module OrigenLink
39
+ module Server
40
+ def self.gpio_dir=(path)
41
+ @gpio_dir = path
42
+ end
43
+
44
+ def self.gpio_dir
45
+ @gpio_dir || '/sys/class/gpio'
46
+ end
47
+
48
+ class Sequencer
49
+ attr_reader :pinmap
50
+ attr_reader :patternorder
51
+ attr_reader :cycletiming
52
+ attr_reader :patternpinindex
53
+
54
+ ##################################################
55
+ # initialize method
56
+ # Create empty pinmap, pattern pin index
57
+ # and pattern order instance variables
58
+ ##################################################
59
+ def initialize
60
+ @pinmap = Hash.new(-1)
61
+ @patternpinindex = Hash.new(-1)
62
+ @patternorder = []
63
+ @cycletiming = Hash.new(-1)
64
+ end
65
+
66
+ ##################################################
67
+ # processmessage method
68
+ # arguments: message
69
+ # message format is <group>_<command>:<args>
70
+ # returns: message response
71
+ #
72
+ # This method splits a message into it's
73
+ # command and arguments and passes this
74
+ # information to the method that performs
75
+ # the requested command
76
+ ##################################################
77
+ def processmessage(message)
78
+ command = message.split(':')
79
+
80
+ case command[0]
81
+ when 'pin_assign'
82
+ pin_assign(command[1])
83
+ when 'pin_patternorder'
84
+ pin_patternorder(command[1])
85
+ when 'pin_cycle'
86
+ pin_cycle(command[1])
87
+ when 'pin_clear'
88
+ pin_clear
89
+ when 'pin_format'
90
+ pin_format(command[1])
91
+ when 'pin_timing'
92
+ pin_timing(command[1])
93
+ else
94
+ 'Error Invalid command: ' + command[0].to_s
95
+ end
96
+ end
97
+
98
+ ##################################################
99
+ # pin_assign method
100
+ # arguments: <args> from the message request
101
+ # see "processmessage" method
102
+ # returns: "P:" or error message
103
+ #
104
+ # This method creates a pin instance for each
105
+ # pin in the pin map and builds the pinmap
106
+ # hash. Before the pinmap is created, any
107
+ # information from a previous pattern run is
108
+ # cleared.
109
+ ##################################################
110
+ def pin_assign(args)
111
+ pin_clear
112
+ success = true
113
+ fail_message = ''
114
+ argarr = args.split(',')
115
+ 0.step(argarr.length - 2, 2) do |index|
116
+ @pinmap[argarr[index]] = Pin.new(argarr[index + 1])
117
+ unless @pinmap[argarr[index]].gpio_valid
118
+ success = false
119
+ fail_message = fail_message + 'pin ' + argarr[index] + ' gpio' + argarr[index + 1] + ' is invalid'
120
+ end
121
+ end
122
+ if success
123
+ 'P:'
124
+ else
125
+ 'F:' + fail_message
126
+ end
127
+ end
128
+
129
+ ##################################################
130
+ # new_timeset(tset)
131
+ # creates a new empty timeset hash
132
+ ##################################################
133
+ def new_timeset(tset)
134
+ @cycletiming[tset] = {}
135
+ @cycletiming[tset]['timing'] = [[], [], []]
136
+ end
137
+
138
+ ##################################################
139
+ # pin_format method
140
+ # arguments: <args> from the message request
141
+ # Should be <timeset>,<pin>,rl or rh
142
+ # multi-clock not currently supported
143
+ #
144
+ ##################################################
145
+ def pin_format(args)
146
+ argarr = args.split(',')
147
+ tset_key = argarr.delete_at(0).to_i
148
+ new_timeset(tset_key) unless @cycletiming.key?(tset_key)
149
+ @cycletiming[tset_key].delete('rl')
150
+ @cycletiming[tset_key].delete('rh')
151
+ 0.step(argarr.length - 2, 2) do |index|
152
+ @cycletiming[tset_key][argarr[index + 1]] = [] unless @cycletiming[tset_key].key?(argarr[index + 1])
153
+ @cycletiming[tset_key][argarr[index + 1]] << argarr[index]
154
+ end
155
+ 'P:'
156
+ end
157
+
158
+ ##################################################
159
+ # pin_timing method
160
+ # arguments: <args> from the message request
161
+ # Should be '1,pin,-1,pin2,0,pin3,1'
162
+ # First integer is timeset number
163
+ # If argument is '', default timing is created
164
+ # Default timeset number is 0, this is used
165
+ # if no timeset is explicitly defined
166
+ #
167
+ # cycle arg: 0 1 2
168
+ # waveform : ___/***\___
169
+ #
170
+ # returns "P:" or error message
171
+ #
172
+ # This method sets up a time set. All retrun
173
+ # format pins are driven between 0 and 1 and
174
+ # return between 1 and 2. Non-return pins are
175
+ # acted upon during the 0, 1 or 2 time period.
176
+ ##################################################
177
+ def pin_timing(args)
178
+ argarr = args.split(',')
179
+ tset_key = argarr.delete_at(0).to_i
180
+ new_timeset(tset_key) unless @cycletiming.key?(tset_key)
181
+ @cycletiming[tset_key]['timing'].each do |index|
182
+ index.delete_if { true }
183
+ end
184
+ 0.step(argarr.length - 2, 2) do |index|
185
+ @cycletiming[tset_key]['timing'][argarr[index + 1].to_i] << argarr[index]
186
+ end
187
+ 'P:'
188
+ end
189
+
190
+ ##################################################
191
+ # pin_patternorder method
192
+ # arguments: <args> from the message request
193
+ # returns: "P:" or error message
194
+ #
195
+ # This method is used to define the order
196
+ # for pin vector data.
197
+ ##################################################
198
+ def pin_patternorder(args)
199
+ argarr = args.split(',')
200
+ index = 0
201
+ if @cycletiming.key?(0)
202
+ @cycletiming[0]['timing'][0].delete_if { true }
203
+ else
204
+ new_timeset(0)
205
+ end
206
+ argarr.each do |pin|
207
+ @patternorder << pin
208
+ @patternpinindex[pin] = index
209
+ @cycletiming[0]['timing'][0] << pin
210
+ index += 1
211
+ end
212
+ 'P:'
213
+ end
214
+
215
+ ##################################################
216
+ # pin_cycle method
217
+ # arguments: <args> from the message request
218
+ # returns: "P:" or "F:" followed by results
219
+ #
220
+ # This method executes one cycle of pin vector
221
+ # data. The vector data is decomposed and
222
+ # sequenced. Each pin object and pin data
223
+ # is passed to the "process_pindata" method
224
+ # for decoding and execution
225
+ ##################################################
226
+ def pin_cycle(args)
227
+ # set default repeats and timeset
228
+ repeat_count = 1
229
+ tset = 0
230
+ if args =~ /,/
231
+ parsedargs = args.split(',')
232
+ args = parsedargs.pop
233
+ parsedargs.each do |arg|
234
+ if arg =~ /repeat/
235
+ repeat_count = arg.sub(/repeat/, '').to_i
236
+ elsif arg =~ /tset/
237
+ tset = arg.sub(/tset/, '').to_i
238
+ end
239
+ end
240
+ end
241
+
242
+ message = ''
243
+ pindata = args.split('')
244
+ @cycle_failure = false
245
+ 0.upto(repeat_count - 1) do |count|
246
+ response = {}
247
+ # process time 0 events
248
+ response = process_events(@cycletiming[tset]['timing'][0], pindata)
249
+ # send drive data for return format pins
250
+ response = (process_events(@cycletiming[tset]['rl'], pindata)).merge(response)
251
+ response = (process_events(@cycletiming[tset]['rh'], pindata)).merge(response)
252
+ # process time 1 events
253
+ response = process_events(@cycletiming[tset]['timing'][1], pindata).merge(response)
254
+ # send return data
255
+ unless @cycletiming[tset]['rl'].nil?
256
+ @cycletiming[tset]['rl'].each do |pin|
257
+ process_pindata(@pinmap[pin], '0')
258
+ end
259
+ end
260
+ unless @cycletiming[tset]['rh'].nil?
261
+ @cycletiming[tset]['rh'].each do |pin|
262
+ process_pindata(@pinmap[pin], '1')
263
+ end
264
+ end
265
+ # process time 2 events
266
+ response = process_events(@cycletiming[tset]['timing'][2], pindata).merge(response)
267
+ if (count == 0) || (@cycle_failure)
268
+ message = ''
269
+ @patternorder.each do |pin|
270
+ message += response[pin]
271
+ end
272
+ end
273
+ end # end cycle through repeats
274
+ if @cycle_failure
275
+ rtnmsg = 'F:' + message + ' Expected:' + args
276
+ else
277
+ rtnmsg = 'P:' + message
278
+ end
279
+ rtnmsg += ' Repeat ' + repeat_count.to_s if repeat_count > 1
280
+ rtnmsg
281
+ end
282
+
283
+ ##################################################
284
+ # process_events
285
+ # used by pin_cycle to avoid duplicating code
286
+ ##################################################
287
+ def process_events(events, pindata)
288
+ response = {}
289
+ unless events.nil?
290
+ events.each do |pin|
291
+ response[pin] = process_pindata(@pinmap[pin], pindata[@patternpinindex[pin]])
292
+ end
293
+ end
294
+ response
295
+ end
296
+
297
+ ##################################################
298
+ # process_pindata method
299
+ # arguments:
300
+ # pin: the pin object to be operated on
301
+ # data: the pin data to be executed
302
+ # returns: the drive data or read data
303
+ #
304
+ # This method translates pin data into one
305
+ # of three possible events. Drive 0, drive 1
306
+ # or read. Supported character decode:
307
+ # drive 0: '0'
308
+ # drive 1: '1'
309
+ # read: anything else
310
+ ##################################################
311
+ def process_pindata(pin, data)
312
+ if data == '0' || data == '1'
313
+ pin.out(data)
314
+ data
315
+ else
316
+ case pin.in
317
+ when '0'
318
+ @cycle_failure = true if data == 'H'
319
+ if data == 'X'
320
+ '.'
321
+ else
322
+ 'L'
323
+ end
324
+ when '1'
325
+ @cycle_failure = true if data == 'L'
326
+ if data == 'X'
327
+ '`'
328
+ else
329
+ 'H'
330
+ end
331
+ else
332
+ 'W'
333
+ end
334
+ end
335
+ end
336
+
337
+ ##################################################
338
+ # pin_clear method
339
+ #
340
+ # This method clears all storage objects. It
341
+ # is called by the "pin_assign" method
342
+ ##################################################
343
+ def pin_clear
344
+ @pinmap.each { |pin_name, pin| pin.destroy }
345
+ @pinmap.clear
346
+ @patternpinindex.clear
347
+ @patternorder.delete_if { true }
348
+ @cycletiming.clear
349
+ 'P:'
350
+ end
351
+ end
352
+ end
353
+ end