ladder_drive 0.3.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 (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"