ladder_drive 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/Gemfile +8 -0
  4. data/Gemfile.lock +41 -0
  5. data/LICENSE +21 -0
  6. data/README.md +191 -0
  7. data/README_jp.md +193 -0
  8. data/Rakefile +9 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +8 -0
  11. data/exe/ladder_drive +28 -0
  12. data/ladder_drive.gemspec +33 -0
  13. data/lib/ladder_drive/asm.rb +211 -0
  14. data/lib/ladder_drive/cli.rb +55 -0
  15. data/lib/ladder_drive/config.rb +107 -0
  16. data/lib/ladder_drive/config_target.rb +93 -0
  17. data/lib/ladder_drive/console.rb +113 -0
  18. data/lib/ladder_drive/intel_hex.rb +79 -0
  19. data/lib/ladder_drive/ladder_drive.rb +36 -0
  20. data/lib/ladder_drive/plc_define.rb +35 -0
  21. data/lib/ladder_drive/plc_device.rb +171 -0
  22. data/lib/ladder_drive/protocol/emulator/emu_protocol.rb +54 -0
  23. data/lib/ladder_drive/protocol/emulator/emulator.rb +29 -0
  24. data/lib/ladder_drive/protocol/keyence/keyence.rb +31 -0
  25. data/lib/ladder_drive/protocol/keyence/kv_device.rb +51 -0
  26. data/lib/ladder_drive/protocol/keyence/kv_protocol.rb +187 -0
  27. data/lib/ladder_drive/protocol/mitsubishi/mc_protocol.rb +268 -0
  28. data/lib/ladder_drive/protocol/mitsubishi/mitsubishi.rb +30 -0
  29. data/lib/ladder_drive/protocol/mitsubishi/qdevice.rb +114 -0
  30. data/lib/ladder_drive/protocol/protocol.rb +107 -0
  31. data/lib/ladder_drive/tasks/build.rb +101 -0
  32. data/lib/ladder_drive/uploader.rb +101 -0
  33. data/lib/ladder_drive/version.rb +26 -0
  34. data/lib/ladder_drive.rb +32 -0
  35. data/lib/plc/LICENSE +21 -0
  36. data/lib/plc/emulator/emu_device.rb +121 -0
  37. data/lib/plc/emulator/emu_plc.rb +482 -0
  38. data/lib/plc/emulator/emu_plc_server.rb +71 -0
  39. data/lib/plc/emulator/emulator.rb +28 -0
  40. data/lib/plc/keyence/kv/kv-5000/DocumentWindowInfo.xml +91 -0
  41. data/lib/plc/keyence/kv/kv-5000/KvsMon.ini +0 -0
  42. data/lib/plc/keyence/kv/kv-5000/LadderDrive.mod +0 -0
  43. data/lib/plc/keyence/kv/kv-5000/LbkMdm.ini +0 -0
  44. data/lib/plc/keyence/kv/kv-5000/Main.mod +0 -0
  45. data/lib/plc/keyence/kv/kv-5000/MonEnv.kmu +1 -0
  46. data/lib/plc/keyence/kv/kv-5000/PlcSended.dky +0 -0
  47. data/lib/plc/keyence/kv/kv-5000/SensorMonitorInfo.xml +4 -0
  48. data/lib/plc/keyence/kv/kv-5000/TransInfo.tif +0 -0
  49. data/lib/plc/keyence/kv/kv-5000/UnitSet.ue2 +0 -0
  50. data/lib/plc/keyence/kv/kv-5000/UnitSet.ue2.old +0 -0
  51. data/lib/plc/keyence/kv/kv-5000/WsTreeEnv.xml +28 -0
  52. data/lib/plc/keyence/kv/kv-5000/kv-5000.cm1 +0 -0
  53. data/lib/plc/keyence/kv/kv-5000/kv-5000.cm2 +0 -0
  54. data/lib/plc/keyence/kv/kv-5000/kv-5000.ftc +0 -0
  55. data/lib/plc/keyence/kv/kv-5000/kv-5000.kpr +0 -0
  56. data/lib/plc/keyence/kv/kv-5000/kv-5000.lbl +0 -0
  57. data/lib/plc/keyence/kv/kv-5000/kv-5000.mil +0 -0
  58. data/lib/plc/keyence/kv/kv-5000/kv-5000.spl +0 -0
  59. data/lib/plc/keyence/kv/kv-5000/operand-history.txt +16 -0
  60. data/lib/plc/keyence/kv/kv-5000/sample.al2 +2 -0
  61. data/lib/plc/mitsubishi/iq-r/r08/r08.gx3 +0 -0
  62. data/lib/plc/plc.rb +27 -0
  63. data/sample/ladder_drive/sample1.esc +4 -0
  64. data/sample/ladder_drive/sample2.esc +28 -0
  65. data/sample/ladder_drive/sample2.png +0 -0
  66. data/template/escalator/config/plc.yml +27 -0
  67. data/template/ladder_drive/Rakefile +1 -0
  68. data/template/ladder_drive/asm/main.esc +70 -0
  69. data/template/ladder_drive/config/plc.yml +27 -0
  70. metadata +174 -0
@@ -0,0 +1,211 @@
1
+ # The MIT License (MIT)
2
+ #
3
+ # Copyright (c) 2016 ITO SOFT DESIGN Inc.
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ module LadderDrive
25
+
26
+ class Asm
27
+
28
+ attr_reader :codes
29
+ attr_reader :endian
30
+
31
+ LITTLE_ENDIAN = 0
32
+ BIG_ENDIAN = 1
33
+
34
+ def initialize source, endian = nil
35
+ @endian = endian || BIG_ENDIAN
36
+ @lines = []
37
+ address = 0
38
+ source.each_line do |line|
39
+ @lines << AsmLine.new(line, address, @endian)
40
+ address = @lines.last.next_address
41
+ end
42
+ end
43
+
44
+ def dump
45
+ @codes.map do |c|
46
+ c.to_s(16).rjust(2, "0")
47
+ end
48
+ end
49
+
50
+ def dump_line
51
+ @lines.map do |line|
52
+ "#{line.address.to_s(16).rjust(4, "0")} #{line.dump_line}"
53
+ end
54
+ .join("\n") << "\n"
55
+ end
56
+
57
+ def codes
58
+ @lines.map do |line|
59
+ line.codes
60
+ end.flatten
61
+ end
62
+
63
+ private
64
+
65
+ def parse line
66
+ @lines << AsmLine.new(line)
67
+ end
68
+
69
+
70
+ end
71
+
72
+ class AsmLine
73
+ attr_reader :line
74
+ attr_reader :codes
75
+ attr_reader :address
76
+ attr_reader :endian
77
+
78
+ def initialize line, address = 0, endian = nil
79
+ @endian = endian || Asm::LITTLE_ENDIAN
80
+ @line = line.upcase.chomp
81
+ @codes = []
82
+ @address = address
83
+ parse
84
+ end
85
+
86
+ def dump_line
87
+ "#{dump}\t#{line}"
88
+ end
89
+
90
+ def dump
91
+ @codes.map do |c|
92
+ c.to_s(16).rjust(2, "0")
93
+ end
94
+ .join(" ")
95
+ .ljust(12)
96
+ end
97
+
98
+ def next_address
99
+ address + codes.size
100
+ end
101
+
102
+ private
103
+
104
+ OPERAND_TYPE_NONE = 0
105
+ OPERAND_TYPE_TYPE_AND_NUMBER = 1
106
+ OPERAND_TYPE_TYPE_AND_NUMBER_NUMBER = 2
107
+
108
+ def parse
109
+ /([^#]*)/ =~ line
110
+ a = $1.split(/\s+/)
111
+ mnemonic, operand1, operand2 = a
112
+ if mnemonic
113
+ @codes << encode_mnemonic(mnemonic)
114
+ case operand_type(mnemonic)
115
+ when OPERAND_TYPE_TYPE_AND_NUMBER
116
+ @codes += parse_type_and_number(operand1)
117
+ end
118
+ end
119
+ end
120
+
121
+ def operand_type mnemonic
122
+ case mnemonic
123
+ when /LD/, /AND/, /ANI/, /OR[^B]?$/, /OUT/, "SET", "RST", "PLS", "PLF", "FF", /SF(L|R)/
124
+ OPERAND_TYPE_TYPE_AND_NUMBER
125
+ else
126
+ OPERAND_TYPE_NONE
127
+ end
128
+ end
129
+
130
+ MNEMONIC_DEF = <<EOB
131
+ | |00|10|20|30|40|50|60|70|80|90|A0|B0|C0|D0|E0|F0|
132
+ |:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
133
+ |00|END|INV|MEP|ANB|MEF|ORB|FEND|NOP|
134
+ |01|LD|LDI|LDP|LDPI|LDF|LDFI|MC|MCR|
135
+ |02|AND|ANI|ANDP|ANPI|ANDF|ANFI|
136
+ |03|OR|ORI|ORP|ORPI|ORF|ORFI|
137
+ |04|OUT|OUTI|MPS|MRD|MPP| |
138
+ |05|SET|RST|PLS| |PLF||
139
+ |06|FF||| |||
140
+ |07|
141
+ |08|SFT|SFTP|SFL|SFLP|SFR|SFRP|
142
+ |09|BSFL|BSFLP|DSFL|DSFLP|BSFR|BSFRP|DSFR|DSFRP|
143
+ |0A|SFTL|SFTLP|WSFL|WSFLP|SFTR|SFTRP|WFSR|WSFRP|
144
+ |0B|
145
+ |0C|
146
+ |0D|
147
+ |0E|
148
+ |0F|
149
+ EOB
150
+ def mnemonic_dict
151
+ @@mnemonic_dict ||= begin
152
+ h = {}
153
+ MNEMONIC_DEF.dup.split(/\n/)[2..-1].each_with_index do |line, upper|
154
+ line.split(/\|/)[2..-1].each_with_index do |mnemonic, lower|
155
+ mnemonic.strip!
156
+ next if mnemonic.nil? || mnemonic.length == 0
157
+ code = (upper << 4) | lower
158
+ h[mnemonic] = code
159
+ end
160
+ end
161
+ h
162
+ end
163
+ end
164
+
165
+ def encode_mnemonic mnemonic
166
+ mnemonic_dict[mnemonic]
167
+ end
168
+
169
+ def parse_type_and_number operand
170
+ /([[:alpha:]]*)(\d+[0-9A-Fa-f]*)\.?(\d*)?/ =~ operand
171
+ suffix = $1
172
+ number = $2
173
+ bit = $3
174
+ len = 16
175
+ case suffix
176
+ when "X", "Y"
177
+ number = number.to_i(16)
178
+ else
179
+ number = number.to_i
180
+ end
181
+ type_code = %W(X Y M - C T L SC CC TC D NOP - CS TS H SD).index(suffix)
182
+ raise "undefind suffix: #{suffix}" if type_code.nil?
183
+
184
+ case (type_code & 0xc) >> 2
185
+ when 0, 1
186
+ type_code |= 0x80
187
+ else
188
+ type_code |= 0xa0
189
+ end
190
+
191
+ if number < 256
192
+ [type_code, number]
193
+ else
194
+ case endian
195
+ when Asm::LITTLE_ENDIAN
196
+ [type_code | 0x10, number & 0xff, (number & 0xff00) >> 8]
197
+ when Asm::BIG_ENDIAN
198
+ [type_code | 0x10, (number & 0xff00) >> 8, number & 0xff]
199
+ end
200
+ end
201
+ end
202
+
203
+ end
204
+
205
+
206
+ end
207
+
208
+ if $0 == __FILE__
209
+ asm = LadderDrive::Asm.new ARGF
210
+ puts asm.dump_line
211
+ end
@@ -0,0 +1,55 @@
1
+ # The MIT License (MIT)
2
+ #
3
+ # Copyright (c) 2016 ITO SOFT DESIGN Inc.
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ require 'thor'
25
+ require 'fileutils'
26
+
27
+ include FileUtils
28
+
29
+ module LadderDrive
30
+ class CLI < Thor
31
+
32
+ desc "create", "Create a new project"
33
+ def create(name)
34
+ if File.exist? name
35
+ puts "ERROR: #{name} already exists."
36
+ exit -1
37
+ end
38
+
39
+ # copy from template file
40
+ root_dir = File.expand_path(File.join(File.dirname(__FILE__), "..", ".."))
41
+ template_path = File.join(root_dir, "template", "ladder_drive")
42
+ cp_r template_path, name
43
+
44
+ # copy plc directory
45
+ temlate_plc_path = File.join(root_dir, "lib", "plc")
46
+ cp_r temlate_plc_path, name
47
+ # remove unnecessary file from plc directory
48
+ %w(plc.rb emulator).each do |fn|
49
+ rm_r File.join(name, "plc", fn)
50
+ end
51
+ puts "#{name} was successfully created."
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,107 @@
1
+ # The MIT License (MIT)
2
+ #
3
+ # Copyright (c) 2016 ITO SOFT DESIGN Inc.
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ require 'active_support/core_ext/string/inflections'
25
+ require 'yaml'
26
+ require 'json'
27
+ require 'protocol/protocol'
28
+
29
+ include LadderDrive::Protocol::Mitsubishi
30
+ include LadderDrive::Protocol::Keyence
31
+ include LadderDrive::Protocol::Emulator
32
+
33
+ module LadderDrive
34
+
35
+ class LadderDriveConfig
36
+
37
+ class << self
38
+
39
+ def default
40
+ @config ||= begin
41
+ load File.join("config", "plc.yml")
42
+ end
43
+ end
44
+
45
+ def load path
46
+ h = {}
47
+ if File.exist?(path)
48
+ h = YAML.load(File.read(path))
49
+ h = JSON.parse(h.to_json, symbolize_names: true)
50
+ end
51
+ new h || {}
52
+ end
53
+
54
+ end
55
+
56
+ def initialize options={}
57
+ default = {
58
+ input: "asm/main.asm",
59
+ output: "build/main.hex",
60
+ }
61
+ emulator_default = {
62
+ host: "localhost",
63
+ port: 5555,
64
+ protocol: "emu_protocol",
65
+ }
66
+
67
+ @config = default.merge options
68
+ @config[:plc] ||= {}
69
+ @config[:plc][:emulator] = @config[:plc][:emulator] ? emulator_default.merge(@config[:plc][:emulator]) : emulator_default
70
+
71
+ @config[:default] ||= {}
72
+
73
+ @targets = {}
74
+ end
75
+
76
+ def [] key
77
+ @config[key]
78
+ end
79
+
80
+ def target name=nil
81
+ name ||= (@config[:default][:target] || :emulator)
82
+ name = name.to_sym if name.is_a? String
83
+ target = @targets[name]
84
+ unless target
85
+ h = @config[:plc][name]
86
+ unless h.nil? || h.empty?
87
+ h = {name:name}.merge h
88
+ target = LadderDriveConfigTarget.new h
89
+ @targets[name] = target
90
+ end
91
+ end
92
+ target
93
+ end
94
+
95
+ def method_missing(name, *args)
96
+ name = name.to_s unless name.is_a? String
97
+ case name.to_s
98
+ when /(.*)=$/
99
+ @config[$1.to_sym] = args.first
100
+ else
101
+ @config[name.to_sym]
102
+ end
103
+ end
104
+
105
+ end
106
+
107
+ end
@@ -0,0 +1,93 @@
1
+ #
2
+ # Copyright (c) 2016 ITO SOFT DESIGN Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ require 'active_support/core_ext/string/inflections'
24
+ require 'yaml'
25
+ require 'json'
26
+ require 'protocol/protocol'
27
+
28
+ include LadderDrive::Protocol::Mitsubishi
29
+ include LadderDrive::Protocol::Keyence
30
+ include LadderDrive::Protocol::Emulator
31
+
32
+ module LadderDrive
33
+
34
+ class LadderDriveConfigTarget
35
+
36
+ class << self
37
+
38
+ def finalize
39
+ proc {
40
+ EmuPlcServer.terminate
41
+ }
42
+ end
43
+
44
+ end
45
+
46
+ def initialize options={}
47
+ @target_info = options
48
+ ObjectSpace.define_finalizer(self, self.class.finalize)
49
+ end
50
+
51
+ def protocol
52
+ @protocol ||= begin
53
+ p = eval("#{@target_info[:protocol].camelize}.new")
54
+ p.host = @target_info[:host] if @target_info[:host]
55
+ p.port = @target_info[:port] if @target_info[:port]
56
+ p.log_level = @target_info[:log_level] if @target_info[:log_level]
57
+ p
58
+ rescue
59
+ nil
60
+ end
61
+ end
62
+
63
+ def uploader
64
+ @uploader ||= begin
65
+ u = Uploader.new
66
+ u.protocol = self.protocol
67
+ u
68
+ end
69
+ end
70
+
71
+ def method_missing(name, *args)
72
+ name = name.to_s unless name.is_a? String
73
+ case name.to_s
74
+ when /(.*)=$/
75
+ @target_info[$1.to_sym] = args.first
76
+ else
77
+ @target_info[name.to_sym]
78
+ end
79
+ end
80
+
81
+ def run
82
+ case self.name
83
+ when :emulator
84
+ Plc::Emulator::EmuPlcServer.launch
85
+ else
86
+ # DO NOTHIN
87
+ # Actual device is running independently.
88
+ end
89
+ end
90
+
91
+ end
92
+
93
+ end
@@ -0,0 +1,113 @@
1
+ #
2
+ # Copyright (c) 2016 ITO SOFT DESIGN Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ require 'singleton'
24
+
25
+ module LadderDrive
26
+
27
+ attr_accessor :target
28
+
29
+ class Console
30
+ include Singleton
31
+
32
+ def run
33
+ l = true
34
+ trap(:INT) { puts "\n> " }
35
+
36
+ display_title
37
+
38
+ loop do
39
+ begin
40
+ print "> "
41
+ line = STDIN.gets
42
+ case line.chomp
43
+ when /^\s*exit\s*$/, /^\s*quit\s*$/, /^\s*q\s*$/
44
+ break
45
+ when /^r\s+(\w+)(\s+(\d+))?/
46
+ d = protocol.device_by_name EscDevice.new($1)
47
+ c = $2 ? $2.to_i : 1
48
+ values = protocol.get_from_devices d, c
49
+ values = values.map{|v| case v; when true; 1; when false; 0; else; v; end}
50
+ puts values.join(" ")
51
+ when /^p\s+(\w+)(\s+(\d+))?/
52
+ d = protocol.device_by_name EscDevice.new($1)
53
+ t = $2 ? $2.to_f : 0.1
54
+ protocol.set_to_devices d, true
55
+ sleep t
56
+ protocol.set_to_devices d, false
57
+ when /^w\s+(\w+)/
58
+ d = protocol.device_by_name EscDevice.new($1)
59
+ v = $'.scan(/\d+/).map{|e| e.to_i}
60
+ protocol.set_to_devices d, v
61
+ when /^E\s+/
62
+ puts protocol.execute(line)
63
+ when /^help/, /^h/
64
+ display_help
65
+ end
66
+ rescue => e
67
+ puts "*** ERROR: #{e} ***"
68
+ end
69
+ end
70
+ end
71
+
72
+ private
73
+
74
+ def protocol
75
+ target.protocol
76
+ end
77
+
78
+ def display_title
79
+ puts <<EOB
80
+
81
+ LadderDrive is an abstract PLC.
82
+ This is a console to communicate with PLC.
83
+
84
+ EOB
85
+ end
86
+
87
+ def display_help
88
+ puts <<EOB
89
+ Commands:
90
+
91
+ r: Read values from device.
92
+ r device [count]
93
+ e.g.) it reads values from M0 to M7.
94
+ > r m0 8
95
+ w: Write values to device.
96
+ w device value1 value2 ...
97
+ e.g.) it write values from D0 to D7.
98
+ > w d0 1 2 3 4 5 6 7 8
99
+ e.g.) it write values from M0 to M7.
100
+ > w m0 0 0 0 1 1 0 1 1
101
+ p: Pulse out on device. Default duration is 0.1 sec
102
+ p device [duration]
103
+ e.g.) it write 1 to m0, then write 0 after 0.5 sec.
104
+ > w m0 0.5
105
+ q: Quit this. You can use quit and exit instead of q.
106
+ h: Show help. You can use help instead of h.
107
+
108
+ EOB
109
+ end
110
+
111
+ end
112
+
113
+ end
@@ -0,0 +1,79 @@
1
+ # The MIT License (MIT)
2
+ #
3
+ # Copyright (c) 2016 ITO SOFT DESIGN Inc.
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ module LadderDrive
25
+
26
+ class IntelHex
27
+
28
+ attr_reader :offset, :codes
29
+
30
+ def self.load path
31
+ offset = 0
32
+ codes = []
33
+ File.read(path).lines.each do |l|
34
+ case l[7,2]
35
+ when "00"
36
+ address = l[3,4].to_i(16)
37
+ offset ||= address
38
+ l.chomp[9..-3].each_char.each_slice(2).each_with_index do |pair, i|
39
+ codes[address - offset + i] = pair.join("").to_i(16)
40
+ end
41
+ end
42
+ end
43
+ new codes, offset
44
+ end
45
+
46
+ def initialize codes, offset = 0
47
+ @offset = offset
48
+ @codes = codes
49
+ end
50
+
51
+ def write_to path
52
+ File.write(path, dump)
53
+ end
54
+
55
+ def dump
56
+ addr = offset
57
+ lines = []
58
+ @codes.each_slice(16) do |line_codes|
59
+ c = line_codes.size
60
+ s = ":#{c.to_s(16).rjust(2, '0')}"
61
+ s << "#{addr.to_s(16).rjust(4, '0')}"
62
+ s << "00"
63
+ line_codes.each do |code|
64
+ s << "#{code.to_s(16).rjust(2, '0')}"
65
+ end
66
+ check_sum = 256 - (s[1..-1].scan(/.{2}/).inject(0){|sum, code| sum += code.to_i(16)} & 0xff)
67
+ s << "#{check_sum.to_s(16).rjust(2, '0')}"
68
+ lines << s
69
+ addr += c
70
+ end
71
+
72
+ lines << ":00000001FF"
73
+ lines << ""
74
+ lines.join("\n")
75
+ end
76
+
77
+ end
78
+
79
+ end
@@ -0,0 +1,36 @@
1
+ #
2
+ # Copyright (c) 2016 ITO SOFT DESIGN Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ dir = File.expand_path(File.dirname(__FILE__))
24
+ $:.unshift dir unless $:.include? dir
25
+
26
+ require "version"
27
+ require "cli"
28
+ require "asm"
29
+ require "intel_hex"
30
+ require "plc_define"
31
+ require "uploader"
32
+ require "config"
33
+ require "config_target"
34
+ require "plc_device"
35
+ require "protocol/protocol"
36
+ require "console"