Class: Plc::Emulator::EmuPlc

Inherits:
Object
  • Object
show all
Defined in:
lib/plc/emulator/emu_plc.rb

Constant Summary collapse

SUFFIXES =
%w(x y m c t l sc cc tc d cs ts h sd)
STOP_PLC_FLAG =

bit 1

2
CLEAR_PROGRAM_FLAG =

bit 2 require bit 1 on

4
CYCLE_RUN_FLAG =
2
INDEX_BIT_STACK_COUNT =
4
INDEX_BIT_STACK =
5
SIZE_OF_BIT_STACK =
3

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeEmuPlc

Returns a new instance of EmuPlc.



52
53
54
55
56
57
58
# File 'lib/plc/emulator/emu_plc.rb', line 52

def initialize
  SUFFIXES.each do |k|
    eval "@#{k}_devices = []"
  end
  @lock = Mutex.new
  reset
end

Instance Attribute Details

#device_dictObject (readonly)

Returns the value of attribute device_dict.



34
35
36
# File 'lib/plc/emulator/emu_plc.rb', line 34

def device_dict
  @device_dict
end

#errorsObject (readonly)

Returns the value of attribute errors.



35
36
37
# File 'lib/plc/emulator/emu_plc.rb', line 35

def errors
  @errors
end

#program_dataObject

Returns the value of attribute program_data.



32
33
34
# File 'lib/plc/emulator/emu_plc.rb', line 32

def program_data
  @program_data
end

#program_pointerObject (readonly)

Returns the value of attribute program_pointer.



33
34
35
# File 'lib/plc/emulator/emu_plc.rb', line 33

def program_pointer
  @program_pointer
end

Instance Method Details

#boolObject



111
112
113
# File 'lib/plc/emulator/emu_plc.rb', line 111

def bool
  (stack_device.word & 1) != 0 ? true : false
end

#bool=(value) ⇒ Object



115
116
117
118
119
120
121
# File 'lib/plc/emulator/emu_plc.rb', line 115

def bool= value
  if value
    stack_device.word |= 1
  else
    stack_device.word &= 0xfffe;
  end
end

#device_by_name(name) ⇒ Object



60
61
62
63
64
65
66
67
68
69
# File 'lib/plc/emulator/emu_plc.rb', line 60

def device_by_name name
  @lock.synchronize {
    d = device_dict[name]
    unless d
      d = EmuDevice.new name
      device_dict[name] = d
    end
    d
  }
end

#device_by_type_and_number(type, number) ⇒ Object



71
72
73
74
# File 'lib/plc/emulator/emu_plc.rb', line 71

def device_by_type_and_number type, number
  d = EmuDevice.new type, number
  device_by_name d.name
end

#execute_console_commands(line) ⇒ Object



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/plc/emulator/emu_plc.rb', line 131

def execute_console_commands line
  a = line.chomp.split(/\s+/)
  case a.first
  when /^ST/i
    d = device_by_name a[1]
    d.set_value true, :in
    "OK\r"
  when /^RS/i
    d = device_by_name a[1]
    d.set_value false, :in
    "OK\r"
  when /^RDS/i
    d = device_by_name a[1]
    c = a[2].to_i
    r = []
    if d.bit_device?
      c.times do
        r << (d.bool(:out) ? 1 : 0)
        d = device_by_name (d+1).name
      end
    else
      case d.suffix
      when "PRG"
        c.times do
          r << program_data[d.number * 2, 2].pack("c*").unpack("n").first
          d = device_by_name (d+1).name
        end
      else
        c.times do
          r << d.word(:out)
          d = device_by_name (d+1).name
        end
      end
    end
    r.map{|e| e.to_s}.join(" ") + "\r"
  when /^WRS/i
    d = device_by_name a[1]
    c = a[2].to_i
    case d.suffix
    when "PRG"
      a[3, c].each do |v|
        program_data[d.number * 2, 2] = [v.to_i].pack("n").unpack("c*")
        d = device_by_name (d+1).name
      end
    else
      if d.bit_device?
        a[3, c].each do |v|
          d.set_value v == "0" ? false : true, :in
          d = device_by_name (d+1).name
        end
      else
        a[3, c].each do |v|
          d.word = v.to_i
          d.set_value v.to_i, :in
          d = device_by_name (d+1).name
        end
      end
    end
    "OK\r"
  when /E/
    eval(a[1..-1].join(" ")).inspect
  else
    raise "Unknown command #{a.first}"
  end
end

#resetObject



76
77
78
79
80
81
82
83
84
85
# File 'lib/plc/emulator/emu_plc.rb', line 76

def reset
  @word = 0
  @program_data = []
  @device_dict ||= {}
  @lock.synchronize {
    @device_dict.values.each do |d|
      d.reset
    end
  }
end

#runObject



123
124
125
126
127
128
129
# File 'lib/plc/emulator/emu_plc.rb', line 123

def run
  Thread.new do
    loop do
      run_cycle
    end
  end
end

#run_cycleObject



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/plc/emulator/emu_plc.rb', line 87

def run_cycle
  status_to_plc = device_by_name "SD0"
  status_form_plc = device_by_name "SD1"
  sync_input
  case status_to_plc.value & (STOP_PLC_FLAG | CLEAR_PROGRAM_FLAG)
  when STOP_PLC_FLAG
    status_form_plc.value = 0
    sleep 0.1
  when STOP_PLC_FLAG | CLEAR_PROGRAM_FLAG
    reset
    status_form_plc.value = CLEAR_PROGRAM_FLAG
    sleep 0.1
  when 0
    status_form_plc.value = CYCLE_RUN_FLAG
    @program_pointer = 0
    clear_stacks
    while fetch_and_execution; end
    sleep 0.0001
  else
    sleep 0.1
  end
  sync_output
end