lib/ladder_drive/asm.rb in ladder_drive-0.5.2 vs lib/ladder_drive/asm.rb in ladder_drive-0.6.0
- old
+ new
@@ -32,14 +32,21 @@
BIG_ENDIAN = 1
def initialize source, endian = nil
@endian = endian || BIG_ENDIAN
@lines = []
+ line_no = 1
address = 0
source.each_line do |line|
- @lines << AsmLine.new(line, address, @endian)
- address = @lines.last.next_address
+ begin
+ @lines << AsmLine.new(line, address, @endian)
+ address = @lines.last.next_address
+ line_no += 1
+ rescue SyntaxError => e
+ puts "#{e.class}: line:#{line_no}; #{line.chomp}; #{e.to_s} "
+ throw
+ end
end
end
def dump
@codes.map do |c|
@@ -111,11 +118,11 @@
mnemonic, operand1, operand2 = a
if mnemonic
@codes << encode_mnemonic(mnemonic)
case operand_type(mnemonic)
when OPERAND_TYPE_TYPE_AND_NUMBER
- @codes += parse_type_and_number(operand1)
+ @codes += parse_type_and_number(mnemonic, operand1, operand2)
end
end
end
def operand_type mnemonic
@@ -164,11 +171,11 @@
def encode_mnemonic mnemonic
mnemonic_dict[mnemonic]
end
- def parse_type_and_number operand
+ def parse_type_and_number mnemonic, operand, value
/([[:alpha:]]*)(\d+[0-9A-Fa-f]*)\.?(\d*)?/ =~ operand
suffix = $1
number = $2
bit = $3
len = 16
@@ -187,17 +194,65 @@
else
type_code |= 0xa0
end
if number < 256
- [type_code, number]
+ codes = [type_code, number]
else
case endian
when Asm::LITTLE_ENDIAN
- [type_code | 0x10, number & 0xff, (number & 0xff00) >> 8]
+ codes = [type_code | 0x10, number & 0xff, (number & 0xff00) >> 8]
when Asm::BIG_ENDIAN
- [type_code | 0x10, (number & 0xff00) >> 8, number & 0xff]
+ codes = [type_code | 0x10, (number & 0xff00) >> 8, number & 0xff]
end
+ end
+
+ # If mnemonic is out/outi and device type is timer or counter, append time or count.
+ case mnemonic
+ when /OUT/
+ case suffix
+ when 'T'
+ codes += time_value(value)
+ when 'C'
+ codes += counter_value(value)
+ end
+ end
+
+ codes
+ end
+
+ def time_value value
+ raise SyntaxError.new "It must be required time value." unless /^\d*\.?\d*$/ =~ value
+
+ t = value.to_f
+ g = 0
+ codes = []
+ while t < 16384 && g <= 3
+ t *= 10.0
+ g += 1
+ end
+ t /= 10.0
+ g -= 1
+ v = (g << 14) | t.to_i
+
+ case endian
+ when Asm::LITTLE_ENDIAN
+ codes = [v & 0xff, (v & 0xff00) >> 8]
+ when Asm::BIG_ENDIAN
+ codes = [(v & 0xff00) >> 8, v & 0xff]
+ end
+ codes #rdlsf@de
+ end
+
+ def counter_value value
+ raise SyntaxError.new "It must be required count value." unless /^\d+$/ =~ value
+
+ v = value.to_i
+ case endian
+ when Asm::LITTLE_ENDIAN
+ codes = [v & 0xff, (v & 0xff00) >> 8]
+ when Asm::BIG_ENDIAN
+ codes = [(v & 0xff00) >> 8, v & 0xff]
end
end
end