avruby 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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