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