avruby 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +28 -0
  3. data/README.md +17 -0
  4. data/bin/avruby_shell +162 -0
  5. data/lib/avr.rb +41 -0
  6. data/lib/avr/argument.rb +23 -0
  7. data/lib/avr/clock.rb +99 -0
  8. data/lib/avr/cpu.rb +254 -0
  9. data/lib/avr/device.rb +249 -0
  10. data/lib/avr/device/atmel_atmega328p.rb +181 -0
  11. data/lib/avr/instruction.rb +72 -0
  12. data/lib/avr/memory.rb +163 -0
  13. data/lib/avr/memory/eeprom.rb +65 -0
  14. data/lib/avr/memory/flash.rb +13 -0
  15. data/lib/avr/memory/memory_byte.rb +54 -0
  16. data/lib/avr/memory/sram.rb +13 -0
  17. data/lib/avr/opcode.rb +237 -0
  18. data/lib/avr/opcode/branch/conditional.rb +61 -0
  19. data/lib/avr/opcode/branch/return.rb +23 -0
  20. data/lib/avr/opcode/branch/unconditional.rb +74 -0
  21. data/lib/avr/opcode/break.rb +14 -0
  22. data/lib/avr/opcode/compare.rb +66 -0
  23. data/lib/avr/opcode/data/immediate.rb +14 -0
  24. data/lib/avr/opcode/data/program.rb +25 -0
  25. data/lib/avr/opcode/data/sram.rb +222 -0
  26. data/lib/avr/opcode/data/stack.rb +22 -0
  27. data/lib/avr/opcode/io/bit.rb +22 -0
  28. data/lib/avr/opcode/io/in_out.rb +38 -0
  29. data/lib/avr/opcode/math/addition.rb +120 -0
  30. data/lib/avr/opcode/math/bitwise.rb +170 -0
  31. data/lib/avr/opcode/math/multiplication.rb +23 -0
  32. data/lib/avr/opcode/math/subtraction.rb +137 -0
  33. data/lib/avr/opcode/nop.rb +14 -0
  34. data/lib/avr/opcode/opcodes.rb +24 -0
  35. data/lib/avr/opcode/operand_parsers.rb +75 -0
  36. data/lib/avr/opcode/register.rb +37 -0
  37. data/lib/avr/opcode/sleep.rb +14 -0
  38. data/lib/avr/opcode/sreg.rb +56 -0
  39. data/lib/avr/opcode/wdr.rb +14 -0
  40. data/lib/avr/opcode_decoder.rb +202 -0
  41. data/lib/avr/oscillator.rb +33 -0
  42. data/lib/avr/port.rb +107 -0
  43. data/lib/avr/register.rb +18 -0
  44. data/lib/avr/register/memory_byte_register.rb +27 -0
  45. data/lib/avr/register/memory_byte_register_with_named_bits.rb +85 -0
  46. data/lib/avr/register/register_file.rb +59 -0
  47. data/lib/avr/register/register_pair.rb +46 -0
  48. data/lib/avr/register/sp.rb +41 -0
  49. data/lib/avr/register/sreg.rb +12 -0
  50. data/lib/avr/register_with_bit_number.rb +40 -0
  51. data/lib/avr/register_with_displacement.rb +31 -0
  52. data/lib/avr/register_with_modification.rb +35 -0
  53. data/lib/avr/register_with_named_bit.rb +36 -0
  54. data/lib/avr/value.rb +45 -0
  55. data/lib/avr/version.rb +6 -0
  56. metadata +182 -0
@@ -0,0 +1,107 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module AVR
5
+ class Port
6
+ extend T::Sig
7
+
8
+ PINS = T.let((0..7).to_a.freeze, T::Array[Integer])
9
+
10
+ sig { returns(CPU) }
11
+ attr_reader :cpu
12
+
13
+ sig { returns(T.any(Symbol, String)) }
14
+ attr_reader :name
15
+
16
+ sig do
17
+ params(
18
+ cpu: CPU,
19
+ name: T.any(Symbol, String),
20
+ pin_address: Integer,
21
+ ddr_address: Integer,
22
+ port_address: Integer
23
+ ).void
24
+ end
25
+ def initialize(cpu, name, pin_address, ddr_address, port_address)
26
+ @cpu = cpu
27
+ @name = name
28
+ @input = T.let(PINS.map { :Z }, T::Array[Symbol])
29
+ @pin_address = pin_address
30
+ @ddr_address = ddr_address
31
+ @port_address = port_address
32
+ @sram_watch = T.let(
33
+ Memory::Watch.new do |_memory_byte, _old_value, _new_value|
34
+ # puts "Port watch fired"
35
+ end,
36
+ Memory::Watch
37
+ )
38
+ @cpu.sram.push_watch(@sram_watch, [@ddr_address, @port_address])
39
+ end
40
+
41
+ sig { returns(MemoryByte) }
42
+ def pin
43
+ T.must(cpu.sram.memory[@pin_address])
44
+ end
45
+
46
+ sig { returns(MemoryByte) }
47
+ def ddr
48
+ T.must(cpu.sram.memory[@ddr_address])
49
+ end
50
+
51
+ sig { returns(MemoryByte) }
52
+ def port
53
+ T.must(cpu.sram.memory[@port_address])
54
+ end
55
+
56
+ sig { params(pin: Integer, state: Symbol).returns(Symbol) }
57
+ def pin_input(pin, state)
58
+ raise unless %i[H L Z].include?(state)
59
+
60
+ @input[pin] = state
61
+ end
62
+
63
+ sig do
64
+ params(
65
+ pin: Integer,
66
+ _pin_value: Integer,
67
+ ddr_value: Integer,
68
+ port_value: Integer
69
+ ).returns(Symbol)
70
+ end
71
+ def pin_state(pin, _pin_value, ddr_value, port_value)
72
+ n_bv = 1 << pin
73
+ drive = (ddr_value & n_bv) == n_bv
74
+ state = (port_value & n_bv) == n_bv
75
+
76
+ return (state ? :H : :L) if drive
77
+
78
+ @input.fetch(pin)
79
+ end
80
+
81
+ sig { returns(T::Array[Symbol]) }
82
+ def pin_states
83
+ pin_value = pin.value
84
+ ddr_value = ddr.value
85
+ port_value = port.value
86
+
87
+ PINS.map { |n| pin_state(n, pin_value, ddr_value, port_value) }
88
+ end
89
+
90
+ sig { returns(String) }
91
+ def value_pins
92
+ PINS.zip(pin_states).map { |n, s| "P#{n}=#{s}" }.join(', ')
93
+ end
94
+
95
+ sig { returns(Integer) }
96
+ def value
97
+ sum = 0
98
+ pin_states.each_with_index { |n, i| sum += (n == :H ? 1 : 0) * (2**i).to_i }
99
+ sum
100
+ end
101
+
102
+ sig { returns(String) }
103
+ def inspect
104
+ "#<#{self.class.name} #{value_pins}>"
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,18 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module AVR
5
+ class Register < Value
6
+ extend T::Sig
7
+
8
+ sig { returns(CPU) }
9
+ attr_reader :cpu
10
+
11
+ sig { params(cpu: CPU, name: T.any(String, Symbol)).void }
12
+ def initialize(cpu, name)
13
+ super()
14
+ @cpu = cpu
15
+ @name = name
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,27 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module AVR
5
+ class MemoryByteRegister < Register
6
+ extend T::Sig
7
+
8
+ sig { returns(MemoryByte) }
9
+ attr_reader :memory_byte
10
+
11
+ sig { params(cpu: CPU, name: T.any(Symbol, String), memory_byte: MemoryByte).void }
12
+ def initialize(cpu, name, memory_byte)
13
+ super(cpu, name)
14
+ @memory_byte = memory_byte
15
+ end
16
+
17
+ sig { returns(Integer) }
18
+ def value
19
+ memory_byte.value
20
+ end
21
+
22
+ sig { params(new_value: Integer).void }
23
+ def value=(new_value)
24
+ memory_byte.value = new_value
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,85 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module AVR
5
+ class MemoryByteRegisterWithNamedBits < MemoryByteRegister
6
+ attr_reader :bit_names
7
+
8
+ def initialize(cpu, name, memory_byte, bit_names)
9
+ super(cpu, name, memory_byte)
10
+ @bit_names = bit_names
11
+ @bit_names_bv = @bit_names.each_with_index.each_with_object({}) { |(b, i), h| h[b] = 2**i if b }
12
+
13
+ @bit_names_bv.each do |bit_name, bit_value|
14
+ define_singleton_method(bit_name, proc { (value & bit_value) == bit_value })
15
+
16
+ define_singleton_method((bit_name.to_s + '=').to_sym, proc { |new_value|
17
+ if [true, 1].include?(new_value)
18
+ self.value |= bit_value
19
+ elsif [false, 0].include?(new_value)
20
+ self.value &= ~bit_value
21
+ else
22
+ raise "Bad value #{new_value} for bit #{bit_name}"
23
+ end
24
+ })
25
+ end
26
+ end
27
+
28
+ def fetch(name)
29
+ send(name)
30
+ end
31
+
32
+ def fetch_bit(name)
33
+ fetch(name) ? 1 : 0
34
+ end
35
+
36
+ def mask_for_flags(flags)
37
+ mask = 0
38
+ flags.each { |flag| mask |= @bit_names_bv[flag] }
39
+ mask
40
+ end
41
+
42
+ def bit_values
43
+ @bit_names.reject(&:nil?).map { |name| name.to_s + '=' + (send(name) ? '1' : '0') }.join(', ')
44
+ end
45
+
46
+ def hash_for_value(value)
47
+ @bit_names_bv.each_with_object({}) { |(name, bv), hash| hash[name] = (value & bv != 0) }
48
+ end
49
+
50
+ def value_for_hash(hash)
51
+ mask = 0
52
+ sum = 0
53
+ hash.each do |name, status|
54
+ mask |= @bit_names_bv[name]
55
+ sum |= @bit_names_bv[name] if [true, 1].include?(status)
56
+ end
57
+ [mask, sum]
58
+ end
59
+
60
+ def reset
61
+ self.value = 0
62
+ end
63
+
64
+ def from_h(hash)
65
+ mask, sum = value_for_hash(hash)
66
+ self.value = (value & ~mask) | sum
67
+ self
68
+ end
69
+
70
+ def inspect
71
+ "#<#{self.class.name} #{bit_values}>"
72
+ end
73
+
74
+ def diff_values(old_value, new_value)
75
+ diff_mask = old_value ^ new_value
76
+ diff_strings = []
77
+ @bit_names_bv.each do |flag, mask|
78
+ old_bit = (old_value & mask) != 0 ? 1 : 0
79
+ new_bit = (new_value & mask) != 0 ? 1 : 0
80
+ diff_strings << "#{flag}=#{old_bit}->#{new_bit}" if diff_mask & mask != 0
81
+ end
82
+ '[' + diff_strings.join(', ') + ']'
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,59 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module AVR
5
+ class RegisterFile
6
+ def add(register)
7
+ @registers[register.name] = register
8
+ @cpu.send(:define_singleton_method, register.name.to_sym, proc { register })
9
+ @cpu.send(:define_singleton_method, (register.name.to_s + '=').to_sym, proc { |value| register.value = value })
10
+ @register_list << register.name
11
+ return unless register.is_a?(RegisterPair)
12
+
13
+ @word_register_map[register.l] = register
14
+ @word_register_map[register.h] = register
15
+ end
16
+
17
+ attr_reader :registers
18
+ attr_reader :word_register_map
19
+
20
+ def initialize(cpu)
21
+ @cpu = cpu
22
+ @registers = {}
23
+ @word_register_map = {}
24
+ @register_list = []
25
+ end
26
+
27
+ def reset
28
+ @registers.each_value do |register|
29
+ register.value = 0
30
+ end
31
+ end
32
+
33
+ def register_values
34
+ @register_list.map { |name| @registers[name].to_s }.join(', ')
35
+ end
36
+
37
+ def print_status
38
+ @register_list.each_slice(8) do |slice|
39
+ puts slice.map { |name| '%10s' % ["#{name}=#{@registers[name].value_hex}"] }.join + '\n'
40
+ end
41
+ end
42
+
43
+ def fetch(key)
44
+ @registers.fetch(@register_list.fetch(key)) if key.is_a?(Integer)
45
+ end
46
+
47
+ def [](key)
48
+ @registers[@register_list[key]] if key.is_a?(Integer)
49
+ end
50
+
51
+ def associated_word_register(register)
52
+ @word_register_map[register]
53
+ end
54
+
55
+ def inspect
56
+ "#<#{self.class.name} #{register_values}>"
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,46 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ # rubocop:disable Naming/MethodParameterName
5
+ module AVR
6
+ class RegisterPair < Register
7
+ extend T::Sig
8
+
9
+ sig { returns(MemoryByteRegister) }
10
+ attr_reader :l
11
+
12
+ sig { returns(MemoryByteRegister) }
13
+ attr_reader :h
14
+
15
+ sig do
16
+ params(
17
+ cpu: CPU,
18
+ l: MemoryByteRegister,
19
+ h: MemoryByteRegister,
20
+ name: T.nilable(T.any(Symbol, String))
21
+ ).void
22
+ end
23
+ def initialize(cpu, l, h, name = nil)
24
+ super(cpu, name || "Temporary[#{l.name}, #{h.name}]")
25
+ @l = l
26
+ @h = h
27
+ end
28
+
29
+ sig { returns(String) }
30
+ def format
31
+ '%04x'
32
+ end
33
+
34
+ sig { returns(Integer) }
35
+ def value
36
+ (h.value << 8) | l.value
37
+ end
38
+
39
+ sig { params(new_value: Integer).void }
40
+ def value=(new_value)
41
+ h.value = (new_value & 0xff00) >> 8
42
+ l.value = (new_value & 0x00ff)
43
+ end
44
+ end
45
+ end
46
+ # rubocop:enable Naming/MethodParameterName
@@ -0,0 +1,41 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module AVR
5
+ class SP < RegisterPair
6
+ extend T::Sig
7
+
8
+ sig do
9
+ params(
10
+ cpu: CPU,
11
+ l_memory_byte: MemoryByte,
12
+ h_memory_byte: MemoryByte,
13
+ initial_value: Integer
14
+ ).void
15
+ end
16
+ def initialize(cpu, l_memory_byte, h_memory_byte, initial_value)
17
+ super(
18
+ cpu,
19
+ MemoryByteRegister.new(cpu, 'SPL', l_memory_byte),
20
+ MemoryByteRegister.new(cpu, 'SPH', h_memory_byte),
21
+ 'SP'
22
+ )
23
+ self.value = initial_value
24
+ end
25
+
26
+ sig { params(offset: Integer).returns(Integer) }
27
+ def adjust(offset)
28
+ self.value += offset
29
+ end
30
+
31
+ sig { params(by: Integer).returns(Integer) }
32
+ def decrement(by = 1)
33
+ adjust(-by)
34
+ end
35
+
36
+ sig { params(by: Integer).returns(Integer) }
37
+ def increment(by = 1)
38
+ adjust(+by)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,12 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module AVR
5
+ class SREG < MemoryByteRegisterWithNamedBits
6
+ STATUS_BITS = T.let(%i[C Z N V S H T I].freeze, T::Array[Symbol])
7
+
8
+ def initialize(cpu)
9
+ super(cpu, 'SREG', cpu.sram.memory[cpu.device.data_memory_map[:SREG]], STATUS_BITS)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,40 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module AVR
5
+ class RegisterWithBitNumber < Value
6
+ extend T::Sig
7
+
8
+ sig { returns(MemoryByteRegister) }
9
+ attr_reader :register
10
+
11
+ sig { returns(Integer) }
12
+ attr_reader :bit_number
13
+
14
+ sig { returns(Integer) }
15
+ attr_reader :bit_mask
16
+
17
+ sig { params(register: MemoryByteRegister, bit_number: Integer).void }
18
+ def initialize(register, bit_number)
19
+ @register = register
20
+ @bit_number = bit_number
21
+ @bit_mask = T.let(1<<bit_number, Integer)
22
+ super()
23
+ end
24
+
25
+ sig { returns(Integer) }
26
+ def value
27
+ (register.value & bit_mask) >> bit_number
28
+ end
29
+
30
+ sig { params(new_value: Integer).void }
31
+ def value=(new_value)
32
+ register.value |= (new_value << bit_number) & bit_mask
33
+ end
34
+
35
+ sig { returns(String) }
36
+ def name
37
+ "#{register.name}.#{bit_number}"
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,31 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require 'forwardable'
5
+
6
+ module AVR
7
+ class RegisterWithDisplacement < Value
8
+ extend Forwardable
9
+ extend T::Sig
10
+
11
+ sig { returns(Register) }
12
+ attr_reader :register
13
+
14
+ def_delegators :register, :value, :value=
15
+
16
+ sig { returns(Integer) }
17
+ attr_reader :displacement
18
+
19
+ sig { params(register: Register, displacement: Integer).void }
20
+ def initialize(register, displacement)
21
+ @register = register
22
+ @displacement = displacement
23
+ super()
24
+ end
25
+
26
+ sig { returns(String) }
27
+ def name
28
+ "%s%+d" % [register.name, displacement]
29
+ end
30
+ end
31
+ end