escalator 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/Gemfile.lock +13 -1
- data/README.md +92 -2
- data/README_jp.md +102 -0
- data/lib/escalator/asm.rb +1 -1
- data/lib/escalator/cli.rb +8 -7
- data/lib/escalator/config.rb +84 -0
- data/lib/escalator/intel_hex.rb +43 -9
- data/lib/escalator/protocol/mitsubishi/mc_protocol.rb +228 -0
- data/lib/escalator/protocol/mitsubishi/mitsubishi.rb +36 -0
- data/lib/escalator/protocol/mitsubishi/qdevice.rb +114 -0
- data/lib/escalator/protocol/protocol.rb +78 -0
- data/lib/escalator/tasks/build.rb +20 -40
- data/lib/escalator/uploader.rb +114 -0
- data/lib/escalator/version.rb +1 -1
- data/lib/escalator.rb +6 -5
- data/plc/mitsubishi/iq-r/r08/LICENSE +21 -0
- data/plc/mitsubishi/iq-r/r08/r08.gx3 +0 -0
- data/template/escalator/config/plc.yml +7 -0
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 97963603ab6ca43c800f1457985665cde1595d64
|
4
|
+
data.tar.gz: 2655e9900ca290185648b1b5d5436a8eb2703c25
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a023765c76d3fa85ccb6c4c399e3cf57b040d0c94e5bceb0c75890d0fb60b0531ba4d1b95b3732a739b3c098a18d30e0867e8bd42e41a609073a357b8a6fa4ab
|
7
|
+
data.tar.gz: 4f772215bb2dca5a8b63e8a18f030fd3e6347ef55f355b8923baea04a049a442838788cabe2bac686b23b86e3c2cc25516237159ca9c20e9f547e5bc9ae3e949
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,22 +1,34 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
escalator (0.1.
|
4
|
+
escalator (0.1.2)
|
5
5
|
thor
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
+
activesupport (5.0.0.1)
|
11
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
12
|
+
i18n (~> 0.7)
|
13
|
+
minitest (~> 5.1)
|
14
|
+
tzinfo (~> 1.1)
|
15
|
+
concurrent-ruby (1.0.2)
|
16
|
+
i18n (0.7.0)
|
17
|
+
minitest (5.9.1)
|
10
18
|
power_assert (0.2.7)
|
11
19
|
rake (10.5.0)
|
12
20
|
test-unit (3.1.7)
|
13
21
|
power_assert
|
14
22
|
thor (0.19.1)
|
23
|
+
thread_safe (0.3.5)
|
24
|
+
tzinfo (1.2.2)
|
25
|
+
thread_safe (~> 0.1)
|
15
26
|
|
16
27
|
PLATFORMS
|
17
28
|
ruby
|
18
29
|
|
19
30
|
DEPENDENCIES
|
31
|
+
activesupport
|
20
32
|
bundler (~> 1.11)
|
21
33
|
escalator!
|
22
34
|
rake (~> 10.0)
|
data/README.md
CHANGED
@@ -2,9 +2,99 @@
|
|
2
2
|
|
3
3
|
The escalator is a simple abstract ladder for PLC (Programmable Logic Controller).
|
4
4
|
|
5
|
-
|
5
|
+
We aim to design runnable abstraction ladder which is running on any PLC with same ladder source or binary and prepare full stack tools.
|
6
|
+
|
7
|
+
# Getting started
|
8
|
+
|
9
|
+
It's required the Ruby environment.
|
10
|
+
To prepare Ruby environment, please find web sites.
|
11
|
+
|
12
|
+
Install Escalator at the command prompt.
|
13
|
+
|
14
|
+
```
|
15
|
+
$ gem install escalator
|
16
|
+
```
|
17
|
+
|
18
|
+
# Create an Escalator project
|
19
|
+
|
20
|
+
At the command prompt, create a new Escalator project.
|
21
|
+
|
22
|
+
```
|
23
|
+
$ escalator create my_project
|
24
|
+
$ cd my_project
|
25
|
+
```
|
26
|
+
|
27
|
+
Created files are consisted like below the tree.
|
28
|
+
|
29
|
+
```
|
30
|
+
.
|
31
|
+
├── Rakefile
|
32
|
+
├── asm
|
33
|
+
│ └── main.esc
|
34
|
+
├── config
|
35
|
+
│ └── plc.yml
|
36
|
+
└── plc
|
37
|
+
└── mitsubishi
|
38
|
+
└── iq-r
|
39
|
+
└── r08
|
40
|
+
├── LICENSE
|
41
|
+
└── r08.gx3
|
42
|
+
```
|
43
|
+
|
44
|
+
# Connection configuration
|
45
|
+
|
46
|
+
## PLC configuration
|
47
|
+
|
48
|
+
There is a plc project under the plc directory.
|
49
|
+
Launch the one of the plc project which you want to use.
|
50
|
+
(Currently we support MITSUBISHI iQ-R R08CUP only.)
|
51
|
+
|
52
|
+
Configure ethernet connection by the tool which is provided by plc maker.
|
53
|
+
Then upload settings and plc program to the plc.
|
54
|
+
|
55
|
+
## Escalator configuration
|
56
|
+
|
57
|
+
There is a configuration file at config/plc.yml.
|
58
|
+
Though currently we support MITSUBISHI iQ-R R08CUP only, you only change host to an ip address of your plc.
|
59
|
+
|
60
|
+
```
|
61
|
+
:plc:
|
62
|
+
:cpu: iq-r
|
63
|
+
:protocol: mc_protocol
|
64
|
+
:host: 192.168.0.1
|
65
|
+
:port: 5007
|
66
|
+
:program_area: d10000
|
67
|
+
:interaction_area: d9998
|
68
|
+
```
|
69
|
+
## Escalator programming
|
70
|
+
|
71
|
+
Escalator program file is located under the asm directory.
|
72
|
+
By default, use asm/main.esc.
|
73
|
+
Edit it and programming.
|
74
|
+
|
75
|
+
Refer [Wiki](https://github.com/ito-soft-design/escalator/wiki/mnemonic) to check mnemonic.
|
76
|
+
|
77
|
+
```
|
78
|
+
LD X0
|
79
|
+
OUT Y0
|
80
|
+
LD X1
|
81
|
+
OR M0
|
82
|
+
ANI X2
|
83
|
+
OUT M0
|
84
|
+
END
|
85
|
+
```
|
86
|
+
|
87
|
+
# Transfer the Escalator program
|
88
|
+
|
89
|
+
At the command prompt, use rake command to upload escalator program to the plc.
|
90
|
+
The Escalator program is running immediate after uploaded.
|
91
|
+
|
92
|
+
```
|
93
|
+
$ rake plc
|
94
|
+
```
|
95
|
+
|
96
|
+
|
6
97
|
|
7
98
|
## License
|
8
99
|
|
9
100
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
10
|
-
|
data/README_jp.md
CHANGED
@@ -5,6 +5,108 @@
|
|
5
5
|
|
6
6
|
まずはニーモニックレベルで実現し、その上に分かりやすい形のプログラミングツールを用意できればと考えています。
|
7
7
|
|
8
|
+
# 使い方
|
9
|
+
|
10
|
+
使用するにはRubyが実行できる環境が必要です。
|
11
|
+
Rubyの実行環境の構築はWebサイト等を検索して構築してください。
|
12
|
+
|
13
|
+
## インストール
|
14
|
+
|
15
|
+
gemでエスカレーターをインストールします。
|
16
|
+
|
17
|
+
```
|
18
|
+
$ gem install escalator
|
19
|
+
```
|
20
|
+
|
21
|
+
## プロジェクト作成
|
22
|
+
|
23
|
+
エスカレーターをインストールするとescalatorコマンドが使用できる様になります。
|
24
|
+
escalatorコマンドでラダーを構成するプロジェクトファイルを作ります。
|
25
|
+
|
26
|
+
```
|
27
|
+
$ escalator create my_project
|
28
|
+
$ cd my_project
|
29
|
+
```
|
30
|
+
|
31
|
+
ファイルの構成は下の様になっています。
|
32
|
+
plc以下にエスカレーターを実行するPLCプロジェクトの雛形があります。
|
33
|
+
現在は三菱電機のiQ-RシリーズR08CPUのみの対応となっています。
|
34
|
+
他メーカーや他の機種は今後追加する予定です。
|
35
|
+
|
36
|
+
|
37
|
+
```
|
38
|
+
.
|
39
|
+
├── Rakefile
|
40
|
+
├── asm
|
41
|
+
│ └── main.esc
|
42
|
+
├── config
|
43
|
+
│ └── plc.yml
|
44
|
+
└── plc
|
45
|
+
└── mitsubishi
|
46
|
+
└── iq-r
|
47
|
+
└── r08
|
48
|
+
├── LICENSE
|
49
|
+
└── r08.gx3
|
50
|
+
```
|
51
|
+
|
52
|
+
## 通信設定
|
53
|
+
|
54
|
+
### PLCの通信設定
|
55
|
+
|
56
|
+
plc以下のプロジェクトファイルを開いてIPアドレスなど変更します。
|
57
|
+
変更後PLCに設定とプログラムを書き込みます。
|
58
|
+
|
59
|
+
### エスカレーターの設定
|
60
|
+
|
61
|
+
config/plc.ymlファイルで設定します。
|
62
|
+
|
63
|
+
現在はiQ-Rのみの対応なので:host: 192.168.0.1の行でPLCに設定したIPアドレスを指定するのみで接続できます。
|
64
|
+
|
65
|
+
```
|
66
|
+
:plc:
|
67
|
+
:cpu: iq-r
|
68
|
+
:protocol: mc_protocol
|
69
|
+
:host: 192.168.0.1
|
70
|
+
:port: 5007
|
71
|
+
:program_area: d10000
|
72
|
+
:interaction_area: d9998
|
73
|
+
```
|
74
|
+
|
75
|
+
## エスカレータープログラム作成
|
76
|
+
|
77
|
+
エスカレーターのプログラムはasm以下にあります。
|
78
|
+
現在はmain.escファイルから生成します。
|
79
|
+
|
80
|
+
main.escを編集しプログラムを作成します。
|
81
|
+
PLC側の実装がまだ進んでいないので実行できるニーモニックはLD、OUT、AND、ORとその反転程度です。
|
82
|
+
|
83
|
+
ニーモニックについては[Wiki](https://github.com/ito-soft-design/escalator/wiki/mnemonic)の方を参照してください。
|
84
|
+
|
85
|
+
```
|
86
|
+
LD X0
|
87
|
+
OUT Y0
|
88
|
+
LD X1
|
89
|
+
OR M0
|
90
|
+
ANI X2
|
91
|
+
OUT M0
|
92
|
+
END
|
93
|
+
```
|
94
|
+
|
95
|
+
## プログラムの転送
|
96
|
+
|
97
|
+
エスカレータープログラムをplcに転送するはrakeコマンドを使用します。
|
98
|
+
転送後プログラムが実行されます。
|
99
|
+
|
100
|
+
```
|
101
|
+
$ rake plc
|
102
|
+
```
|
103
|
+
|
104
|
+
|
105
|
+
# エスカレーターに関する情報
|
106
|
+
|
107
|
+
- [一往確認日記 [escalator]](http://diary.itosoft.com/?category=escalator)
|
108
|
+
- [Wiki](https://github.com/ito-soft-design/escalator/wiki/)
|
109
|
+
|
8
110
|
# ライセンス
|
9
111
|
|
10
112
|
MIT
|
data/lib/escalator/asm.rb
CHANGED
data/lib/escalator/cli.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# The MIT License (MIT)
|
2
|
-
#
|
2
|
+
#
|
3
3
|
# Copyright (c) 2016 ITO SOFT DESIGN Inc.
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Permission is hereby granted, free of charge, to any person obtaining
|
6
6
|
# a copy of this software and associated documentation files (the
|
7
7
|
# "Software"), to deal in the Software without restriction, including
|
@@ -9,10 +9,10 @@
|
|
9
9
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
10
|
# permit persons to whom the Software is furnished to do so, subject to
|
11
11
|
# the following conditions:
|
12
|
-
#
|
12
|
+
#
|
13
13
|
# The above copyright notice and this permission notice shall be
|
14
14
|
# included in all copies or substantial portions of the Software.
|
15
|
-
#
|
15
|
+
#
|
16
16
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
17
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
18
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
@@ -28,13 +28,14 @@ include FileUtils
|
|
28
28
|
|
29
29
|
module Escalator
|
30
30
|
class CLI < Thor
|
31
|
-
|
31
|
+
|
32
32
|
desc "create", "Create a new project"
|
33
33
|
def create(name)
|
34
34
|
template_path = File.join(Escalator_root, "template", "escalator")
|
35
35
|
cp_r template_path, name
|
36
|
-
|
36
|
+
temlate_plc_path = File.join(Escalator_root, "plc")
|
37
|
+
cp_r temlate_plc_path, name
|
37
38
|
end
|
38
|
-
|
39
|
+
|
39
40
|
end
|
40
41
|
end
|
@@ -0,0 +1,84 @@
|
|
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 "escalator/protocol/protocol"
|
26
|
+
require 'escalator/uploader'
|
27
|
+
require 'yaml'
|
28
|
+
|
29
|
+
include Escalator::Protocol::Mitsubishi
|
30
|
+
|
31
|
+
module Escalator
|
32
|
+
|
33
|
+
|
34
|
+
class EscalatorConfig
|
35
|
+
|
36
|
+
def self.default
|
37
|
+
@config ||= begin
|
38
|
+
config_path = File.join "config", "plc.yml"
|
39
|
+
h = YAML.load(File.read(config_path)) if File.exist?(config_path)
|
40
|
+
new h || {}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def initialize options={}
|
45
|
+
default = {input: "asm/main.asm", output: "build/main.hex"}
|
46
|
+
@config = options.merge default
|
47
|
+
end
|
48
|
+
|
49
|
+
def protocol
|
50
|
+
@protocol ||= begin
|
51
|
+
plc_info = @config[:plc]
|
52
|
+
p = eval("#{plc_info[:protocol].camelize}.new")
|
53
|
+
p.host = plc_info[:host] if plc_info[:host]
|
54
|
+
p.port = plc_info[:port] if plc_info[:port]
|
55
|
+
p.log_level = plc_info[:log_level] if plc_info[:log_level]
|
56
|
+
p
|
57
|
+
rescue
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def uploader
|
63
|
+
@uploader ||= begin
|
64
|
+
u = Uploader.new
|
65
|
+
u.protocol = self.protocol
|
66
|
+
u.program_area = u.protocol.device_by_name(@config[:plc][:program_area]) if @config[:plc] && @config[:plc][:program_area]
|
67
|
+
u.interaction_area = u.protocol.device_by_name(@config[:plc][:interaction_area]) if @config[:plc] && @config[:plc][:interaction_area]
|
68
|
+
u
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def method_missing(name, *args)
|
73
|
+
name = name.to_s unless name.is_a? String
|
74
|
+
case name.to_s
|
75
|
+
when /(.*)=$/
|
76
|
+
@config[$1.to_sym] = args.first
|
77
|
+
else
|
78
|
+
@config[name.to_sym]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
data/lib/escalator/intel_hex.rb
CHANGED
@@ -1,14 +1,57 @@
|
|
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
|
+
|
1
24
|
module Escalator
|
2
25
|
|
3
26
|
class IntelHex
|
4
27
|
|
5
28
|
attr_reader :offset, :codes
|
6
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
|
+
|
7
46
|
def initialize codes, offset = 0
|
8
47
|
@offset = offset
|
9
48
|
@codes = codes
|
10
49
|
end
|
11
50
|
|
51
|
+
def write_to path
|
52
|
+
File.write(path, dump)
|
53
|
+
end
|
54
|
+
|
12
55
|
def dump
|
13
56
|
addr = offset
|
14
57
|
lines = []
|
@@ -31,15 +74,6 @@ module Escalator
|
|
31
74
|
lines.join("\n")
|
32
75
|
end
|
33
76
|
|
34
|
-
def gxworks_memory_image
|
35
|
-
lines = []
|
36
|
-
@codes.each_slice(8) do |line_codes|
|
37
|
-
lines << line_codes.join("\t")
|
38
|
-
end
|
39
|
-
|
40
|
-
lines.join("\n")
|
41
|
-
end
|
42
|
-
|
43
77
|
end
|
44
78
|
|
45
79
|
end
|
@@ -0,0 +1,228 @@
|
|
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 Escalator
|
25
|
+
module Protocol
|
26
|
+
module Mitsubishi
|
27
|
+
|
28
|
+
class McProtocol < Protocol
|
29
|
+
|
30
|
+
def initialize options={}
|
31
|
+
super
|
32
|
+
@host = options[:host] || "192.168.0.1"
|
33
|
+
@port = options[:port] || 5010
|
34
|
+
end
|
35
|
+
|
36
|
+
def open
|
37
|
+
@socket ||= TCPSocket.open(@host, @port)
|
38
|
+
end
|
39
|
+
|
40
|
+
def close
|
41
|
+
@socket.close if @socket
|
42
|
+
@socket = nil
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_bit_from_device device
|
46
|
+
device = device_by_name device
|
47
|
+
get_bits_from_device(1, device).first
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_bits_from_device count, device
|
51
|
+
device = device_by_name device
|
52
|
+
packet = make_packet(body_for_get_bits_from_deivce(count, device))
|
53
|
+
@logger.debug("> #{dump_packet packet}")
|
54
|
+
open
|
55
|
+
@socket.write(packet.pack("c*"))
|
56
|
+
@socket.flush
|
57
|
+
res = receive
|
58
|
+
bits = []
|
59
|
+
count.times do |i|
|
60
|
+
v = res[11 + i / 2]
|
61
|
+
if i % 2 == 0
|
62
|
+
bits << ((v >> 4) != 0)
|
63
|
+
else
|
64
|
+
bits << ((v & 0xf) != 0)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
@logger.debug("get #{device.name} => #{bits}")
|
68
|
+
bits
|
69
|
+
end
|
70
|
+
|
71
|
+
def set_bits_to_device bits, device
|
72
|
+
device = device_by_name device
|
73
|
+
packet = make_packet(body_for_set_bits_to_device(bits, device))
|
74
|
+
@logger.debug("> #{dump_packet packet}")
|
75
|
+
open
|
76
|
+
@socket.write(packet.pack("c*"))
|
77
|
+
@socket.flush
|
78
|
+
res = receive
|
79
|
+
@logger.debug("set #{bits} to:#{device.name}")
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
def get_word_from_device device
|
84
|
+
device = device_by_name device
|
85
|
+
get_words_from_device(1, device).first
|
86
|
+
end
|
87
|
+
|
88
|
+
def get_words_from_device(count, device)
|
89
|
+
device = device_by_name device
|
90
|
+
packet = make_packet(body_for_get_words_from_deivce(count, device))
|
91
|
+
@logger.debug("> #{dump_packet packet}")
|
92
|
+
open
|
93
|
+
@socket.write(packet.pack("c*"))
|
94
|
+
@socket.flush
|
95
|
+
res = receive
|
96
|
+
words = []
|
97
|
+
res[11, 2 * count].each_slice(2) do |pair|
|
98
|
+
words << pair.pack("c*").unpack("v").first
|
99
|
+
end
|
100
|
+
@logger.debug("get from: #{device.name} => #{words}")
|
101
|
+
words
|
102
|
+
end
|
103
|
+
|
104
|
+
def set_words_to_device words, device
|
105
|
+
device = device_by_name device
|
106
|
+
packet = make_packet(body_for_set_words_to_device(words, device))
|
107
|
+
@logger.debug("> #{dump_packet packet}")
|
108
|
+
open
|
109
|
+
@socket.write(packet.pack("c*"))
|
110
|
+
@socket.flush
|
111
|
+
res = receive
|
112
|
+
@logger.debug("set #{words} to: #{device.name}")
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
def device_by_name name
|
117
|
+
case name
|
118
|
+
when String
|
119
|
+
QDevice.new name
|
120
|
+
else
|
121
|
+
# it may be already QDevice
|
122
|
+
name
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
def receive
|
128
|
+
res = []
|
129
|
+
len = 0
|
130
|
+
begin
|
131
|
+
Timeout.timeout(0.1) do
|
132
|
+
while true
|
133
|
+
c = @socket.read(1)
|
134
|
+
next if c.nil? || c == ""
|
135
|
+
|
136
|
+
res << c.bytes.first
|
137
|
+
len = res[7] + res[8] << 8 if res.length >= 9
|
138
|
+
break if (len + 9 == res.length)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
rescue Timeout::Error
|
142
|
+
end
|
143
|
+
@logger.debug("< #{dump_packet res}")
|
144
|
+
res
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
def make_packet body
|
150
|
+
header = [0x50, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00]
|
151
|
+
header[7..8] = data_for_short(body.length + 2)
|
152
|
+
header + body
|
153
|
+
end
|
154
|
+
|
155
|
+
def body_for_get_bit_from_deivce device
|
156
|
+
body_for_get_bits_from_deivce 1, device
|
157
|
+
end
|
158
|
+
|
159
|
+
def body_for_get_bits_from_deivce count, device
|
160
|
+
body_for_get_words_from_deivce count, device, false
|
161
|
+
end
|
162
|
+
|
163
|
+
def body_for_get_words_from_deivce count, device, word = true
|
164
|
+
body = [0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00]
|
165
|
+
body[2] = 1 unless word
|
166
|
+
body[4..7] = data_for_device(device)
|
167
|
+
body[8..9] = data_for_short count
|
168
|
+
body
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
def body_for_set_bits_to_device bits, device
|
173
|
+
body = [0x01, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00]
|
174
|
+
d = device
|
175
|
+
bits = [bits] unless bits.is_a? Array
|
176
|
+
bits.each_slice(2) do |pair|
|
177
|
+
body << (pair.first ? 0x10 : 0x00)
|
178
|
+
body[-1] |= (pair.last ? 0x1 : 0x00) if pair.size == 2
|
179
|
+
d = d.next_device
|
180
|
+
end
|
181
|
+
body[4..7] = data_for_device(device)
|
182
|
+
body[8..9] = data_for_short bits.size
|
183
|
+
body
|
184
|
+
end
|
185
|
+
alias :body_for_set_bit_to_device :body_for_set_bits_to_device
|
186
|
+
|
187
|
+
def body_for_set_words_to_device words, device
|
188
|
+
body = [0x01, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00]
|
189
|
+
d = device
|
190
|
+
words = [words] unless words.is_a? Array
|
191
|
+
words.each do |v|
|
192
|
+
body += data_for_short v
|
193
|
+
d = d.next_device
|
194
|
+
end
|
195
|
+
body[4..7] = data_for_device(device)
|
196
|
+
body[8..9] = data_for_short words.size
|
197
|
+
body
|
198
|
+
end
|
199
|
+
|
200
|
+
def data_for_device device
|
201
|
+
a = data_for_int device.number
|
202
|
+
a[3] = device.suffix_code
|
203
|
+
a
|
204
|
+
end
|
205
|
+
|
206
|
+
def data_for_short value
|
207
|
+
[value].pack("v").unpack("c*")
|
208
|
+
end
|
209
|
+
|
210
|
+
def data_for_int value
|
211
|
+
[value].pack("V").unpack("c*")
|
212
|
+
end
|
213
|
+
|
214
|
+
def dump_packet packet
|
215
|
+
a = []
|
216
|
+
len = packet.length
|
217
|
+
bytes = packet.dup
|
218
|
+
len.times do |i|
|
219
|
+
a << ("0" + bytes[i].to_s(16))[-2, 2]
|
220
|
+
end
|
221
|
+
"[" + a.join(", ") + "]"
|
222
|
+
end
|
223
|
+
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
@@ -0,0 +1,36 @@
|
|
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
|
+
$:.unshift File.dirname(__FILE__)
|
25
|
+
|
26
|
+
module Escalator
|
27
|
+
module Protocol
|
28
|
+
|
29
|
+
require 'socket'
|
30
|
+
require 'logger'
|
31
|
+
require 'timeout'
|
32
|
+
require 'qdevice'
|
33
|
+
require 'mc_protocol'
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,114 @@
|
|
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 Escalator
|
25
|
+
module Protocol
|
26
|
+
module Mitsubishi
|
27
|
+
|
28
|
+
class QDevice
|
29
|
+
|
30
|
+
attr_reader :suffix, :number
|
31
|
+
|
32
|
+
SUFFIXES = %w(SM SD X Y M L F V B D W TS TC TN SS SC SN CS CC CN SB SW S DX DY Z R ZR)
|
33
|
+
SUFFIX_CODES = [0x91, 0xa9, 0x9c, 0x9d, 0x90, 0x92, 0x93, 0x94, 0xa0, 0xa8, 0xb4, 0xc1, 0xc0, 0xc2, 0xc7, 0xc6, 0xc8, 0xc4, 0xc3, 0xc5, 0xa1, 0xb5, 0x98, 0xa2, 0xa3, 0xcc ,0xaf, 0xb0]
|
34
|
+
|
35
|
+
def initialize a, b = nil
|
36
|
+
case a
|
37
|
+
when Array
|
38
|
+
case a.size
|
39
|
+
when 4
|
40
|
+
@suffix = suffix_for_code(a[3])
|
41
|
+
@number = ((a[2] << 8 | a[1]) << 8) | a[0]
|
42
|
+
end
|
43
|
+
when String
|
44
|
+
if b
|
45
|
+
@suffix = a.upcase
|
46
|
+
@number = b
|
47
|
+
else
|
48
|
+
if a.length == 12
|
49
|
+
@suffix = [a[0,2].to_i(16), a[2,2].to_i(16)].pack "c*"
|
50
|
+
@suffix.strip!
|
51
|
+
@number = a[4,8].to_i(16)
|
52
|
+
elsif /(X|Y)(.+)/i =~ a
|
53
|
+
@suffix = $1.upcase
|
54
|
+
@number = $2.to_i(p_adic_number)
|
55
|
+
else
|
56
|
+
/(M|L|S|B|F|T|C|D|W|R)(.+)/i =~ a
|
57
|
+
@suffix = $1.upcase
|
58
|
+
@number = $2.to_i(p_adic_number)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def p_adic_number
|
65
|
+
case @suffix
|
66
|
+
when "X", "Y", "B", "W", "SB", "SW", "DX", "DY", "ZR"
|
67
|
+
16
|
68
|
+
else
|
69
|
+
10
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def name
|
74
|
+
@suffix + @number.to_s(p_adic_number).upcase
|
75
|
+
end
|
76
|
+
|
77
|
+
def next_device
|
78
|
+
d = self.class.new @suffix, @number + 1
|
79
|
+
d
|
80
|
+
end
|
81
|
+
|
82
|
+
def bit_device?
|
83
|
+
case @suffix
|
84
|
+
when "SM", "X", "Y", "M", "L", "F", "V", "B",
|
85
|
+
"TS", "TC", "SS", "SC","CS", "CC", "SB", "S", "DX", "DY"
|
86
|
+
true
|
87
|
+
else
|
88
|
+
false
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def suffix_for_code code
|
93
|
+
index = SUFFIX_CODES.index code
|
94
|
+
index ? SUFFIXES[index] : nil
|
95
|
+
end
|
96
|
+
|
97
|
+
def suffix_code
|
98
|
+
index = SUFFIXES.index suffix
|
99
|
+
index ? SUFFIX_CODES[index] : 0
|
100
|
+
end
|
101
|
+
|
102
|
+
def + value
|
103
|
+
QDevice.new self.suffix, self.number + value
|
104
|
+
end
|
105
|
+
|
106
|
+
def - value
|
107
|
+
QDevice.new self.suffix, [self.number - value, 0].max
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,78 @@
|
|
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
|
+
$:.unshift File.dirname(__FILE__)
|
25
|
+
|
26
|
+
module Escalator
|
27
|
+
module Protocol
|
28
|
+
|
29
|
+
class Protocol
|
30
|
+
|
31
|
+
attr_accessor :host, :port, :log_level
|
32
|
+
|
33
|
+
def initialize options={}
|
34
|
+
@logger = Logger.new(STDOUT)
|
35
|
+
@logger.level = options[:log_level] || Logger::INFO
|
36
|
+
end
|
37
|
+
|
38
|
+
def log_level= level
|
39
|
+
@log_level = level.is_a?(String) ? level.to_sym : level
|
40
|
+
case @log_level
|
41
|
+
when :debug
|
42
|
+
@logger.level = Logger::DEBUG
|
43
|
+
when :error
|
44
|
+
@logger.level = Logger::ERROR
|
45
|
+
when :fatal
|
46
|
+
@logger.level = Logger::FATAL
|
47
|
+
when :info
|
48
|
+
@logger.level = Logger::INFO
|
49
|
+
when :unknown
|
50
|
+
@logger.level = Logger::UNKNOWN
|
51
|
+
when :warn
|
52
|
+
@logger.level = Logger::WARN
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# abstract methods
|
57
|
+
|
58
|
+
def open; end
|
59
|
+
def close; end
|
60
|
+
|
61
|
+
def get_bit_from_device device; end
|
62
|
+
def get_bits_from_device count, device; end
|
63
|
+
def set_bits_to_device bits, device; end
|
64
|
+
def set_bit_to_device bit, device; set_bits_to_device bit, device; end
|
65
|
+
|
66
|
+
def get_word_from_device device; end
|
67
|
+
def get_words_from_device(count, device); end
|
68
|
+
def set_words_to_device words, device; end
|
69
|
+
def set_word_to_device word, device; set_words_to_device word, device; end
|
70
|
+
|
71
|
+
def device_by_name name; nil; end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
require 'mitsubishi/mitsubishi'
|
@@ -23,9 +23,11 @@
|
|
23
23
|
|
24
24
|
Escalator_root = File.expand_path(File.join(File.dirname(__FILE__), "../../../"))
|
25
25
|
|
26
|
+
require "escalator/config"
|
26
27
|
require 'escalator/asm'
|
27
28
|
require 'escalator/intel_hex'
|
28
29
|
require 'rake/loaders/makefile'
|
30
|
+
require 'fileutils'
|
29
31
|
|
30
32
|
#directory "build"
|
31
33
|
|
@@ -61,6 +63,7 @@ rule %r{^build/.+\.hex} => ['%{^build,asm}X.esc'] do |t|
|
|
61
63
|
$stderr = STDERR
|
62
64
|
end
|
63
65
|
stream = StringIO.new
|
66
|
+
puts "hex #{t.source}"
|
64
67
|
asm = Escalator::Asm.new File.read(t.source)
|
65
68
|
hex = Escalator::IntelHex.new asm.codes
|
66
69
|
File.write(t.name, hex.dump)
|
@@ -77,51 +80,28 @@ rule %r{^build/.+\.gxwm} => ['%{^build,asm}X.esc'] do |t|
|
|
77
80
|
$stderr = STDERR
|
78
81
|
end
|
79
82
|
stream = StringIO.new
|
83
|
+
puts "gxwm #{t.source}"
|
80
84
|
asm = Escalator::Asm.new File.read(t.source)
|
81
85
|
hex = Escalator::IntelHex.new asm.codes
|
82
86
|
File.write(t.name, hex.gxworks_memory_image)
|
83
87
|
end
|
84
88
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
# @refer: https://github.com/rsutphin/handbrake.rb/issues/1
|
89
|
-
begin
|
90
|
-
$stderr = File.open('hb.log', 'w')
|
91
|
-
$stdout = $stderr
|
92
|
-
mkdir_p "build"
|
93
|
-
ensure
|
94
|
-
$stdout = STDOUT
|
95
|
-
$stderr = STDERR
|
96
|
-
end
|
97
|
-
dir = "./asm"
|
98
|
-
stream = StringIO.new
|
99
|
-
sources = Dir.glob("asm/**/*.esc").each do |filename|
|
100
|
-
puts "asm #{filename}"
|
101
|
-
asm = Escalator::Asm.new File.read(filename)
|
102
|
-
dst = File.join("build", File.basename(filename, ".*") + ".lst")
|
103
|
-
File.write(dst, asm.dump_line)
|
104
|
-
end
|
89
|
+
desc "Clean all generated files."
|
90
|
+
task :clean do
|
91
|
+
FileUtils.rm_r "build"
|
105
92
|
end
|
106
93
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
$stdout = STDOUT
|
115
|
-
$stderr = STDERR
|
116
|
-
end
|
117
|
-
dir = "./asm"
|
118
|
-
stream = StringIO.new
|
119
|
-
sources = Dir.glob("asm/**/*.esc").each do |filename|
|
120
|
-
puts "hex #{filename}"
|
121
|
-
asm = Escalator::Asm.new File.read(filename)
|
122
|
-
dst = File.join("build", File.basename(filename, ".*") + ".hex")
|
123
|
-
hex = Escalator::IntelHex.new asm.codes
|
124
|
-
File.write(dst, hex.dump)
|
125
|
-
end
|
94
|
+
@config = Escalator::EscalatorConfig.default
|
95
|
+
|
96
|
+
task :upload => @config.output do
|
97
|
+
u = @config.uploader
|
98
|
+
u.source = @config.output
|
99
|
+
u.upload
|
100
|
+
puts "upload #{u.source}"
|
126
101
|
end
|
127
|
-
|
102
|
+
|
103
|
+
desc "Install program to PLCs."
|
104
|
+
task :plc => :upload do
|
105
|
+
end
|
106
|
+
|
107
|
+
task :default => %w(build/main.lst build/main.hex build/main.gxwm)
|
@@ -0,0 +1,114 @@
|
|
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 Escalator
|
25
|
+
|
26
|
+
class Uploader
|
27
|
+
|
28
|
+
attr_accessor :protocol
|
29
|
+
attr_accessor :program_area, :interaction_area
|
30
|
+
attr_accessor :source
|
31
|
+
attr_accessor :data
|
32
|
+
|
33
|
+
def initialize options={}
|
34
|
+
@protocol = options[:protocol] if options[:protocol]
|
35
|
+
@program_area = options[:program_area] if options[:program_area]
|
36
|
+
@interaction_area = options[:interaction_area] if options[:interaction_area]
|
37
|
+
end
|
38
|
+
|
39
|
+
STOP_PLC_FLAG = 2 # bit 1
|
40
|
+
CLEAR_PROGRAM_FLAG = 4 # bit 2 require bit 1 on
|
41
|
+
|
42
|
+
CYCLE_RUN_FLAG = 2
|
43
|
+
|
44
|
+
|
45
|
+
def upload
|
46
|
+
# stop plc
|
47
|
+
stop_plc
|
48
|
+
clear_program
|
49
|
+
write_program
|
50
|
+
run_plc
|
51
|
+
end
|
52
|
+
|
53
|
+
def data
|
54
|
+
@data ||= begin
|
55
|
+
hex = IntelHex.load @source
|
56
|
+
hex.codes
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def word_data
|
61
|
+
data.each_slice(2).map do |pair|
|
62
|
+
pair.pack("c*").unpack("n*")
|
63
|
+
end.flatten
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def to_plc_status
|
69
|
+
@to_plc_status ||= interaction_area
|
70
|
+
end
|
71
|
+
|
72
|
+
def from_plc_status
|
73
|
+
@from_plc_status ||= interaction_area.next_device
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
def stop_plc
|
78
|
+
@protocol.set_word_to_device STOP_PLC_FLAG, to_plc_status
|
79
|
+
Timeout.timeout(5) do
|
80
|
+
v = @protocol.get_word_from_device from_plc_status
|
81
|
+
break if (v & STOP_PLC_FLAG) != 0
|
82
|
+
sleep 0.1
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def clear_program
|
87
|
+
@protocol.set_word_to_device STOP_PLC_FLAG | CLEAR_PROGRAM_FLAG, to_plc_status
|
88
|
+
Timeout.timeout(5) do
|
89
|
+
v = @protocol.get_word_from_device from_plc_status
|
90
|
+
break if (v & CLEAR_PROGRAM_FLAG) != 0
|
91
|
+
sleep 0.1
|
92
|
+
end
|
93
|
+
@protocol.set_word_to_device STOP_PLC_FLAG, to_plc_status
|
94
|
+
end
|
95
|
+
|
96
|
+
def run_plc
|
97
|
+
@protocol.set_word_to_device 0, to_plc_status
|
98
|
+
Timeout.timeout(5) do
|
99
|
+
v = @protocol.get_word_from_device from_plc_status
|
100
|
+
break if (v & CYCLE_RUN_FLAG) != 0
|
101
|
+
sleep 0.1
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def write_program
|
106
|
+
word_data.each_slice(2*1024) do |chunk|
|
107
|
+
@protocol.set_words_to_device chunk, @program_area
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
end
|
data/lib/escalator/version.rb
CHANGED
data/lib/escalator.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# The MIT License (MIT)
|
2
|
-
#
|
2
|
+
#
|
3
3
|
# Copyright (c) 2016 ITO SOFT DESIGN Inc.
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Permission is hereby granted, free of charge, to any person obtaining
|
6
6
|
# a copy of this software and associated documentation files (the
|
7
7
|
# "Software"), to deal in the Software without restriction, including
|
@@ -9,10 +9,10 @@
|
|
9
9
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
10
|
# permit persons to whom the Software is furnished to do so, subject to
|
11
11
|
# the following conditions:
|
12
|
-
#
|
12
|
+
#
|
13
13
|
# The above copyright notice and this permission notice shall be
|
14
14
|
# included in all copies or substantial portions of the Software.
|
15
|
-
#
|
15
|
+
#
|
16
16
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
17
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
18
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
@@ -25,6 +25,7 @@ require "escalator/version"
|
|
25
25
|
require "escalator/cli"
|
26
26
|
require "escalator/asm"
|
27
27
|
require "escalator/intel_hex"
|
28
|
+
require "escalator/config"
|
28
29
|
|
29
30
|
Escalator_root = File.expand_path(File.join(File.dirname(__FILE__), ".."))
|
30
31
|
|
@@ -32,4 +33,4 @@ module Escalator
|
|
32
33
|
end
|
33
34
|
|
34
35
|
|
35
|
-
Escalator::CLI.start
|
36
|
+
Escalator::CLI.start
|
@@ -0,0 +1,21 @@
|
|
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 a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: escalator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Katsuyoshi Ito
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-10-
|
11
|
+
date: 2016-10-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -76,14 +76,23 @@ files:
|
|
76
76
|
- lib/escalator.rb
|
77
77
|
- lib/escalator/asm.rb
|
78
78
|
- lib/escalator/cli.rb
|
79
|
+
- lib/escalator/config.rb
|
79
80
|
- lib/escalator/intel_hex.rb
|
81
|
+
- lib/escalator/protocol/mitsubishi/mc_protocol.rb
|
82
|
+
- lib/escalator/protocol/mitsubishi/mitsubishi.rb
|
83
|
+
- lib/escalator/protocol/mitsubishi/qdevice.rb
|
84
|
+
- lib/escalator/protocol/protocol.rb
|
80
85
|
- lib/escalator/tasks/build.rb
|
86
|
+
- lib/escalator/uploader.rb
|
81
87
|
- lib/escalator/version.rb
|
88
|
+
- plc/mitsubishi/iq-r/r08/LICENSE
|
89
|
+
- plc/mitsubishi/iq-r/r08/r08.gx3
|
82
90
|
- sample/escalator/sample1.esc
|
83
91
|
- sample/escalator/sample2.esc
|
84
92
|
- sample/escalator/sample2.png
|
85
93
|
- template/escalator/Rakefile
|
86
94
|
- template/escalator/asm/main.esc
|
95
|
+
- template/escalator/config/plc.yml
|
87
96
|
homepage: https://github.com/ito-soft-design/escalator/wiki
|
88
97
|
licenses:
|
89
98
|
- MIT
|