avruby 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.md +28 -0
- data/README.md +17 -0
- data/bin/avruby_shell +162 -0
- data/lib/avr.rb +41 -0
- data/lib/avr/argument.rb +23 -0
- data/lib/avr/clock.rb +99 -0
- data/lib/avr/cpu.rb +254 -0
- data/lib/avr/device.rb +249 -0
- data/lib/avr/device/atmel_atmega328p.rb +181 -0
- data/lib/avr/instruction.rb +72 -0
- data/lib/avr/memory.rb +163 -0
- data/lib/avr/memory/eeprom.rb +65 -0
- data/lib/avr/memory/flash.rb +13 -0
- data/lib/avr/memory/memory_byte.rb +54 -0
- data/lib/avr/memory/sram.rb +13 -0
- data/lib/avr/opcode.rb +237 -0
- data/lib/avr/opcode/branch/conditional.rb +61 -0
- data/lib/avr/opcode/branch/return.rb +23 -0
- data/lib/avr/opcode/branch/unconditional.rb +74 -0
- data/lib/avr/opcode/break.rb +14 -0
- data/lib/avr/opcode/compare.rb +66 -0
- data/lib/avr/opcode/data/immediate.rb +14 -0
- data/lib/avr/opcode/data/program.rb +25 -0
- data/lib/avr/opcode/data/sram.rb +222 -0
- data/lib/avr/opcode/data/stack.rb +22 -0
- data/lib/avr/opcode/io/bit.rb +22 -0
- data/lib/avr/opcode/io/in_out.rb +38 -0
- data/lib/avr/opcode/math/addition.rb +120 -0
- data/lib/avr/opcode/math/bitwise.rb +170 -0
- data/lib/avr/opcode/math/multiplication.rb +23 -0
- data/lib/avr/opcode/math/subtraction.rb +137 -0
- data/lib/avr/opcode/nop.rb +14 -0
- data/lib/avr/opcode/opcodes.rb +24 -0
- data/lib/avr/opcode/operand_parsers.rb +75 -0
- data/lib/avr/opcode/register.rb +37 -0
- data/lib/avr/opcode/sleep.rb +14 -0
- data/lib/avr/opcode/sreg.rb +56 -0
- data/lib/avr/opcode/wdr.rb +14 -0
- data/lib/avr/opcode_decoder.rb +202 -0
- data/lib/avr/oscillator.rb +33 -0
- data/lib/avr/port.rb +107 -0
- data/lib/avr/register.rb +18 -0
- data/lib/avr/register/memory_byte_register.rb +27 -0
- data/lib/avr/register/memory_byte_register_with_named_bits.rb +85 -0
- data/lib/avr/register/register_file.rb +59 -0
- data/lib/avr/register/register_pair.rb +46 -0
- data/lib/avr/register/sp.rb +41 -0
- data/lib/avr/register/sreg.rb +12 -0
- data/lib/avr/register_with_bit_number.rb +40 -0
- data/lib/avr/register_with_displacement.rb +31 -0
- data/lib/avr/register_with_modification.rb +35 -0
- data/lib/avr/register_with_named_bit.rb +36 -0
- data/lib/avr/value.rb +45 -0
- data/lib/avr/version.rb +6 -0
- metadata +182 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AVR
|
5
|
+
class Opcode
|
6
|
+
decode('0000 0000 0000 0000', :nop) do |cpu, _opcode_definition, _operands|
|
7
|
+
cpu.instruction(:nop)
|
8
|
+
end
|
9
|
+
|
10
|
+
opcode(:nop) do |_cpu, _memory, _args|
|
11
|
+
# Do nothing.
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'avr/opcode/operand_parsers'
|
5
|
+
require 'avr/opcode/nop'
|
6
|
+
require 'avr/opcode/break'
|
7
|
+
require 'avr/opcode/sleep'
|
8
|
+
require 'avr/opcode/wdr'
|
9
|
+
require 'avr/opcode/sreg'
|
10
|
+
require 'avr/opcode/register'
|
11
|
+
require 'avr/opcode/compare'
|
12
|
+
require 'avr/opcode/data/stack'
|
13
|
+
require 'avr/opcode/data/immediate'
|
14
|
+
require 'avr/opcode/data/program'
|
15
|
+
require 'avr/opcode/data/sram'
|
16
|
+
require 'avr/opcode/branch/unconditional'
|
17
|
+
require 'avr/opcode/branch/conditional'
|
18
|
+
require 'avr/opcode/branch/return'
|
19
|
+
require 'avr/opcode/math/addition'
|
20
|
+
require 'avr/opcode/math/subtraction'
|
21
|
+
require 'avr/opcode/math/multiplication'
|
22
|
+
require 'avr/opcode/math/bitwise'
|
23
|
+
require 'avr/opcode/io/bit'
|
24
|
+
require 'avr/opcode/io/in_out'
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AVR
|
5
|
+
class Opcode
|
6
|
+
sig { params(value: Integer, bits: Integer).returns(Integer) }
|
7
|
+
def self.twos_complement(value, bits)
|
8
|
+
mask = (2**(bits - 1)).to_i
|
9
|
+
-(value & mask) + (value & ~mask)
|
10
|
+
end
|
11
|
+
|
12
|
+
sig { params(k_in: Integer).returns(Integer) }
|
13
|
+
def self.bit_jumble_for_lds_sts(k_in)
|
14
|
+
k_out = k_in & 0b00001111
|
15
|
+
k_out |= k_in & 0b01100000 >> 1
|
16
|
+
k_out |= k_in & 0b00010000 << 2
|
17
|
+
k_out |= ~(k_in & 0b00010000 << 3) & 0b10000000
|
18
|
+
k_out
|
19
|
+
end
|
20
|
+
|
21
|
+
# adc add and cp cpc cpse eor mov mul muls or sbc sub
|
22
|
+
parse_operands('____ __rd dddd rrrr') do |cpu, operands|
|
23
|
+
{
|
24
|
+
Rd: cpu.registers.fetch(operands.fetch(:d).value),
|
25
|
+
Rr: cpu.registers.fetch(operands.fetch(:r).value),
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
# fmul fmuls fmulsu mulsu
|
30
|
+
parse_operands('____ ____ _ddd _rrr') do |cpu, operands|
|
31
|
+
{
|
32
|
+
Rd: cpu.registers.fetch(operands.fetch(:d).value | 0b10000),
|
33
|
+
Rr: cpu.registers.fetch(operands.fetch(:r).value | 0b10000),
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
# asr com dec elpm inc ld lds lpm lsr neg pop ror swap
|
38
|
+
parse_operands('____ ___d dddd ____') do |cpu, operands|
|
39
|
+
{
|
40
|
+
Rd: cpu.registers.fetch(operands.fetch(:d).value),
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
# lac las lat push st xch
|
45
|
+
parse_operands('____ ___r rrrr ____') do |cpu, operands|
|
46
|
+
{
|
47
|
+
Rr: cpu.registers.fetch(operands.fetch(:r).value),
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
# sbrc sbrs
|
52
|
+
parse_operands('____ ___r rrrr _bbb') do |cpu, operands|
|
53
|
+
{
|
54
|
+
Rr: cpu.registers.fetch(operands.fetch(:r).value),
|
55
|
+
b: Value.new(operands.fetch(:b).value),
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
# adiw sbiw
|
60
|
+
parse_operands('____ ____ KKdd KKKK') do |cpu, operands|
|
61
|
+
{
|
62
|
+
Rd: cpu.registers.associated_word_register(cpu.registers.fetch((operands.fetch(:d).value << 1) | 0b11000)),
|
63
|
+
K: Value.new(operands.fetch(:K).value),
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
# andi cpi ldi ori sbci sbr subi
|
68
|
+
parse_operands('____ KKKK dddd KKKK') do |cpu, operands|
|
69
|
+
{
|
70
|
+
Rd: cpu.registers.fetch(operands.fetch(:d).value | 0b10000),
|
71
|
+
K: Value.new(operands.fetch(:K).value),
|
72
|
+
}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AVR
|
5
|
+
class Opcode
|
6
|
+
decode('0010 11rd dddd rrrr', :mov) do |cpu, _opcode_definition, operands|
|
7
|
+
cpu.instruction(:mov, operands.fetch(:Rd), operands.fetch(:Rr))
|
8
|
+
end
|
9
|
+
|
10
|
+
opcode(:mov, %i[register register]) do |_cpu, _memory, args|
|
11
|
+
args.fetch(0).value = args.fetch(1).value
|
12
|
+
end
|
13
|
+
|
14
|
+
parse_operands('____ ____ dddd rrrr') do |cpu, operands|
|
15
|
+
{
|
16
|
+
Rd: RegisterPair.new(
|
17
|
+
cpu,
|
18
|
+
cpu.registers.fetch((operands.fetch(:d).value << 1) + 1),
|
19
|
+
cpu.registers.fetch(operands.fetch(:d).value << 1)
|
20
|
+
),
|
21
|
+
Rr: RegisterPair.new(
|
22
|
+
cpu,
|
23
|
+
cpu.registers.fetch((operands.fetch(:r).value << 1) + 1),
|
24
|
+
cpu.registers.fetch(operands.fetch(:r).value << 1)
|
25
|
+
),
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
decode('0000 0001 dddd rrrr', :movw) do |cpu, _opcode_definition, operands|
|
30
|
+
cpu.instruction(:movw, operands.fetch(:Rd), operands.fetch(:Rr))
|
31
|
+
end
|
32
|
+
|
33
|
+
opcode(:movw, %i[register_pair register_pair]) do |_cpu, _memory, args|
|
34
|
+
args.fetch(0).value = args.fetch(1).value
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AVR
|
5
|
+
class Opcode
|
6
|
+
decode('1001 0101 1000 1000', :sleep) do |cpu, _opcode_definition, _operands|
|
7
|
+
cpu.instruction(:sleep)
|
8
|
+
end
|
9
|
+
|
10
|
+
opcode(:sleep) do |cpu, memory, args|
|
11
|
+
# Do nothing.
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AVR
|
5
|
+
class Opcode
|
6
|
+
decode('1001 0100 0sss 1000', :bset) do |cpu, _opcode_definition, operands|
|
7
|
+
sreg_bit = RegisterWithNamedBit.new(
|
8
|
+
cpu.sreg,
|
9
|
+
SREG::STATUS_BITS.fetch(operands.fetch(:s).value)
|
10
|
+
)
|
11
|
+
cpu.instruction(:bset, sreg_bit)
|
12
|
+
end
|
13
|
+
|
14
|
+
opcode(:bset, %i[sreg_flag], %i[I T H S V N Z C]) do |cpu, _memory, args|
|
15
|
+
args.fetch(0).value = 1
|
16
|
+
end
|
17
|
+
|
18
|
+
decode('1001 0100 1sss 1000', :bclr) do |cpu, _opcode_definition, operands|
|
19
|
+
sreg_bit = RegisterWithNamedBit.new(
|
20
|
+
cpu.sreg,
|
21
|
+
SREG::STATUS_BITS.fetch(operands.fetch(:s).value)
|
22
|
+
)
|
23
|
+
cpu.instruction(:bclr, sreg_bit)
|
24
|
+
end
|
25
|
+
|
26
|
+
opcode(:bclr, %i[sreg_flag], %i[I T H S V N Z C]) do |cpu, _memory, args|
|
27
|
+
args.fetch(0).value = 0
|
28
|
+
end
|
29
|
+
|
30
|
+
parse_operands('____ ___d dddd _bbb') do |cpu, operands|
|
31
|
+
{
|
32
|
+
Rd: cpu.registers.fetch(operands.fetch(:d).value),
|
33
|
+
b: operands.fetch(:b),
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
decode('1111 100d dddd 0bbb', :bld) do |cpu, _opcode_definition, operands|
|
38
|
+
cpu.instruction(:bld, operands.fetch(:Rd), operands.fetch(:b))
|
39
|
+
end
|
40
|
+
|
41
|
+
opcode(:bld, %i[register bit_number]) do |cpu, _memory, args|
|
42
|
+
t_bit = 1 << args.fetch(1).value
|
43
|
+
t_value = cpu.sreg.T ? t_bit : 0
|
44
|
+
t_mask = ~t_bit & 0xff
|
45
|
+
args.fetch(0).value = (args.fetch(0).value & t_mask) | t_value
|
46
|
+
end
|
47
|
+
|
48
|
+
decode('1111 101d dddd 0bbb', :bst) do |cpu, _opcode_definition, operands|
|
49
|
+
cpu.instruction(:bst, operands.fetch(:Rd), operands.fetch(:b))
|
50
|
+
end
|
51
|
+
|
52
|
+
opcode(:bst, %i[register bit_number], %i[T]) do |cpu, _memory, args|
|
53
|
+
cpu.sreg.T = args.fetch(0).value & (1 << args.fetch(1).value) != 0
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AVR
|
5
|
+
class Opcode
|
6
|
+
decode('1001 0101 1010 1000', :wdr) do |cpu, _opcode_definition, _operands|
|
7
|
+
cpu.instruction(:wdr)
|
8
|
+
end
|
9
|
+
|
10
|
+
opcode(:wdr) do |_cpu, _memory, _args|
|
11
|
+
# Do nothing for now.
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AVR
|
5
|
+
class OpcodeDecoder
|
6
|
+
extend T::Sig
|
7
|
+
|
8
|
+
class OpcodeDefinition
|
9
|
+
extend T::Sig
|
10
|
+
|
11
|
+
ProcType = T.type_alias do
|
12
|
+
T.proc.params(
|
13
|
+
cpu: CPU,
|
14
|
+
opcode_definition: OpcodeDefinition,
|
15
|
+
operands: Opcode::OperandValueHashType
|
16
|
+
).returns(Instruction)
|
17
|
+
end
|
18
|
+
|
19
|
+
sig { returns(String) }
|
20
|
+
attr_reader :pattern
|
21
|
+
|
22
|
+
sig { returns(Symbol) }
|
23
|
+
attr_reader :mnemonic
|
24
|
+
|
25
|
+
sig { returns(ProcType) }
|
26
|
+
attr_reader :parse_proc
|
27
|
+
|
28
|
+
sig { params(pattern: String, mnemonic: Symbol, parse_proc: ProcType).void }
|
29
|
+
def initialize(pattern, mnemonic, parse_proc)
|
30
|
+
@pattern = T.let(pattern.gsub(/[^01a-zA-Z]/, ''), String)
|
31
|
+
raise "Incorrect pattern length for #{pattern}" unless @pattern.size == 16
|
32
|
+
|
33
|
+
@mnemonic = mnemonic
|
34
|
+
@parse_proc = parse_proc
|
35
|
+
|
36
|
+
@operand_pattern = T.let(nil, T.nilable(String))
|
37
|
+
@match_value = T.let(nil, T.nilable(Integer))
|
38
|
+
@match_mask = T.let(nil, T.nilable(Integer))
|
39
|
+
end
|
40
|
+
|
41
|
+
sig { returns(String) }
|
42
|
+
def operand_pattern
|
43
|
+
@operand_pattern ||= pattern.gsub(/[01]/, '_')
|
44
|
+
end
|
45
|
+
|
46
|
+
sig { returns(Integer) }
|
47
|
+
def match_value
|
48
|
+
@match_value ||= pattern.gsub(/[^01]/, '0').to_i(2)
|
49
|
+
end
|
50
|
+
|
51
|
+
sig { returns(Integer) }
|
52
|
+
def match_mask
|
53
|
+
@match_mask ||= pattern.gsub(/[01]/, '1').gsub(/[^01]/, '0').to_i(2)
|
54
|
+
end
|
55
|
+
|
56
|
+
sig { params(word: Integer).returns(T::Boolean) }
|
57
|
+
def match?(word)
|
58
|
+
word & match_mask == match_value
|
59
|
+
end
|
60
|
+
|
61
|
+
sig { params(word: Integer).returns(Argument::NamedValueType) }
|
62
|
+
def extract_operands(word)
|
63
|
+
operands = Hash.new(0)
|
64
|
+
mask = 0x10000
|
65
|
+
pattern.split('').each do |operand|
|
66
|
+
mask >>= 1
|
67
|
+
next if %w[0 1].include?(operand)
|
68
|
+
|
69
|
+
operands[operand.to_sym] <<= 1
|
70
|
+
operands[operand.to_sym] |= 1 if (word & mask) != 0
|
71
|
+
end
|
72
|
+
operands.each_with_object({}) { |(k, v), h| h[k] = Value.new(v) }
|
73
|
+
end
|
74
|
+
|
75
|
+
sig do
|
76
|
+
params(
|
77
|
+
cpu: CPU,
|
78
|
+
opcode_definition: OpcodeDefinition,
|
79
|
+
operands: Argument::NamedValueType
|
80
|
+
).returns(Instruction)
|
81
|
+
end
|
82
|
+
def parse(cpu, opcode_definition, operands)
|
83
|
+
parse_proc.call(cpu, opcode_definition, operands)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class OperandParser
|
88
|
+
extend T::Sig
|
89
|
+
|
90
|
+
sig { returns(String) }
|
91
|
+
attr_reader :pattern
|
92
|
+
|
93
|
+
ProcType = T.type_alias do
|
94
|
+
T.proc.params(cpu: CPU, operands: Opcode::OperandValueHashType).returns(Opcode::OperandValueHashType)
|
95
|
+
end
|
96
|
+
|
97
|
+
sig { returns(OperandParser::ProcType) }
|
98
|
+
attr_reader :parse_proc
|
99
|
+
|
100
|
+
sig { params(pattern: String, parse_proc: OperandParser::ProcType).void }
|
101
|
+
def initialize(pattern, parse_proc)
|
102
|
+
@pattern = T.let(pattern.gsub(/[^01a-zA-Z_]/, ''), String)
|
103
|
+
@parse_proc = T.let(parse_proc, OperandParser::ProcType)
|
104
|
+
end
|
105
|
+
|
106
|
+
sig { params(cpu: CPU, operands: Opcode::OperandValueHashType).returns(Opcode::OperandValueHashType) }
|
107
|
+
def parse(cpu, operands)
|
108
|
+
parse_proc.call(cpu, operands)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class DecodedOpcode
|
113
|
+
extend T::Sig
|
114
|
+
|
115
|
+
sig { returns(OpcodeDefinition) }
|
116
|
+
attr_reader :opcode_definition
|
117
|
+
|
118
|
+
sig { returns(Opcode::OperandValueHashType) }
|
119
|
+
attr_reader :operands
|
120
|
+
|
121
|
+
sig { params(opcode_definition: OpcodeDefinition, operands: Opcode::OperandValueHashType).void }
|
122
|
+
def initialize(opcode_definition, operands)
|
123
|
+
@opcode_definition = opcode_definition
|
124
|
+
@operands = operands
|
125
|
+
end
|
126
|
+
|
127
|
+
sig { params(cpu: CPU).returns(Opcode::OperandValueHashType) }
|
128
|
+
def prepare_operands(cpu)
|
129
|
+
parser = OpcodeDecoder.operand_parsers[opcode_definition.operand_pattern]
|
130
|
+
parser&.parse(cpu, operands) || operands
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
@opcode_definitions = T.let([], T::Array[OpcodeDefinition])
|
135
|
+
@opcode_match_masks = T.let({}, T::Hash[Integer, T::Hash[Integer, OpcodeDefinition]])
|
136
|
+
@operand_parsers = T.let({}, T::Hash[String, OpcodeDecoder::OperandParser])
|
137
|
+
|
138
|
+
class << self
|
139
|
+
extend T::Sig
|
140
|
+
|
141
|
+
sig { returns(T::Array[OpcodeDefinition]) }
|
142
|
+
attr_reader :opcode_definitions
|
143
|
+
|
144
|
+
sig { returns(T::Hash[Integer, T::Hash[Integer, OpcodeDefinition]]) }
|
145
|
+
attr_reader :opcode_match_masks
|
146
|
+
|
147
|
+
sig { returns(T::Hash[String, OpcodeDecoder::OperandParser]) }
|
148
|
+
attr_reader :operand_parsers
|
149
|
+
end
|
150
|
+
|
151
|
+
sig { params(opcode_definition: OpcodeDefinition).void }
|
152
|
+
def self.add_opcode_definition(opcode_definition)
|
153
|
+
opcode_definitions << opcode_definition
|
154
|
+
opcode_match_masks[opcode_definition.match_mask] ||= {}
|
155
|
+
opcode_match_masks.fetch(opcode_definition.match_mask)[opcode_definition.match_value] = opcode_definition
|
156
|
+
end
|
157
|
+
|
158
|
+
sig { params(operand_parser: OperandParser).void }
|
159
|
+
def self.add_operand_parser(operand_parser)
|
160
|
+
operand_parsers[operand_parser.pattern] = operand_parser
|
161
|
+
end
|
162
|
+
|
163
|
+
sig { returns(T::Hash[Integer, DecodedOpcode]) }
|
164
|
+
attr_reader :cache
|
165
|
+
|
166
|
+
sig { void }
|
167
|
+
def initialize
|
168
|
+
@cache = T.let({}, T::Hash[Integer, DecodedOpcode])
|
169
|
+
end
|
170
|
+
|
171
|
+
sig { params(word: Integer).returns(T.nilable(DecodedOpcode)) }
|
172
|
+
def decode(word)
|
173
|
+
cached_decoded_opcode = cache[word]
|
174
|
+
return cached_decoded_opcode if cached_decoded_opcode
|
175
|
+
|
176
|
+
OpcodeDecoder.opcode_match_masks.each do |mask, values|
|
177
|
+
opcode_definition = values[word & mask]
|
178
|
+
next unless opcode_definition
|
179
|
+
|
180
|
+
operands = opcode_definition.extract_operands(word)
|
181
|
+
decoded_opcode = DecodedOpcode.new(opcode_definition, operands)
|
182
|
+
cache[word] = decoded_opcode
|
183
|
+
return decoded_opcode
|
184
|
+
end
|
185
|
+
nil
|
186
|
+
end
|
187
|
+
|
188
|
+
sig { void }
|
189
|
+
def print_cache
|
190
|
+
puts "Opcode decoder cache (#{cache.size} opcodes cached):"
|
191
|
+
cache.sort.each do |word, decoded_opcode|
|
192
|
+
puts ' %04x = %17s = %-6s (%s)' % [
|
193
|
+
word,
|
194
|
+
word.to_s(2).rjust(16, '0').split('').each_slice(8).map(&:join).join(' '),
|
195
|
+
decoded_opcode.opcode_definition.mnemonic,
|
196
|
+
decoded_opcode.operands.map { |k, v| '%s = %5d' % [k, v] }.join(', '),
|
197
|
+
]
|
198
|
+
end
|
199
|
+
nil
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AVR
|
5
|
+
class Oscillator < Clock
|
6
|
+
extend T::Sig
|
7
|
+
|
8
|
+
sig { returns(T::Enumerator[TrueClass]) }
|
9
|
+
def infinite
|
10
|
+
[true].cycle
|
11
|
+
end
|
12
|
+
|
13
|
+
sig { params(time: T.any(Float, Integer)).returns(T::Enumerator[T.untyped]) }
|
14
|
+
def time_limit(time)
|
15
|
+
Enumerator.new do |y|
|
16
|
+
end_time = Time.now.to_f + time
|
17
|
+
y << true while Time.now.to_f < end_time
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
sig { params(limit: T::Enumerator[T.untyped]).returns(Integer) }
|
22
|
+
def run(limit = infinite)
|
23
|
+
start_ticks = ticks
|
24
|
+
limit.each { tick }
|
25
|
+
ticks - start_ticks
|
26
|
+
end
|
27
|
+
|
28
|
+
sig { params(time: T.any(Float, Integer)).returns(Integer) }
|
29
|
+
def run_timed(time)
|
30
|
+
run(time_limit(time))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|