-
Notifications
You must be signed in to change notification settings - Fork 6
/
refactor.cr
97 lines (85 loc) · 2.06 KB
/
refactor.cr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
annotation BitField
end
class BitFields
@bytes : Bytes
def initialize(b : Bytes)
@bytes = b.clone
end
macro bf(field, length)
@[BitField(length: "{{field.var}}_{{length}}")]
def {{field.var}}
range = ranges("{{field.var}}")
puts range.inspect
buffer = 0_u64
@bytes[range[:sbyte], range[:byte_count]].each.with_index do |b, i|
buffer ^= (b.to_u64 << i*8)
end
buffer >>= (range[:sbit] % 8)
buffer &= (2**{{length}}-1)
{{field.type}}.new(buffer)
end
end
# starting_bit
# bit_length
# byte_length = (bit_length/8.0).ceil.to_i
def fields
fields = Hash(String, Int32).new
{% for ivar in @type.methods %}
{% if ann = ivar.annotation(BitField) %}
f, l = {{ann[:length]}}.split("_")
fields[f] = l.to_i
{% end %}
{% end %}
fields
end
def lengths
fields.values
end
def ranges(f)
index = fields.keys.index(f) || 0
s_bit = lengths[0...index].sum
e_bit = lengths[index] + s_bit
{sbit: s_bit, ebit: e_bit, sbyte: s_bit/8, byte_count: (lengths[index]/8.0).ceil.to_i}
end
end
class CrossBit < BitFields
bf rpms : UInt32, 32
bf temp : UInt8, 4
bf psi : UInt16, 9
bf power : UInt8, 1
bf lights : UInt8, 2
bf v1 : UInt16, 16
bf v2 : UInt8, 4
bf v3 : UInt8, 8
bf v4 : UInt8, 4
bf v5 : UInt8, 8
end
bytes = Bytes[109, 121, 110, 97, 221, 181, 220, 0, 28, 156, 9]
crossbit = CrossBit.new(bytes)
# crossbit = CrossBit.new(Bytes[109, 121, 110, 97, 221, 181, 220, 0, 113, 101, 38])
puts crossbit.rpms
puts crossbit.temp # => 13_u8
puts crossbit.psi # => 342_u16
puts crossbit.power # => 1_u8
puts crossbit.lights # => 3_u8
puts crossbit.v1
puts crossbit.v2
puts crossbit.v3
puts crossbit.v4
puts crossbit.v5
# crossbit.to_slice #=> Bytes[109, 121, 110, 97, 109, 245]
# class TestB < BitFields
# bf f1 : UInt16, 10
# bf f2 : UInt8, 2
# bf f3 : UInt8, 4
# end
#
# b = TestB.new(Bytes[234, 201])
#
# # puts b.f1
# # puts b.f2
# # puts b.f3
# puts b.f1
# puts b.fields
# # puts b.bit_range("f3")
# # puts b.byte_range("f3")