lignite 0.1.2 → 0.2.0
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.
- checksums.yaml +4 -4
- data/.yardopts +1 -0
- data/NEWS.md +16 -0
- data/README.md +5 -1
- data/VERSION +1 -1
- data/examples/bobbee.rb +211 -0
- data/examples/light-sensor.rb +19 -0
- data/examples/motors.rb +2 -2
- data/lib/lignite.rb +6 -0
- data/lib/lignite/assembler.rb +25 -6
- data/lib/lignite/body_compiler.rb +28 -15
- data/lib/lignite/bytes.rb +5 -0
- data/lib/lignite/direct_commands.rb +23 -3
- data/lib/lignite/message.rb +1 -1
- data/lib/lignite/message_sender.rb +1 -1
- data/lib/lignite/motors.rb +165 -0
- data/lib/lignite/op_compiler.rb +15 -0
- data/lib/lignite/rbf_object.rb +6 -4
- data/lib/lignite/variables.rb +48 -5
- data/lignite.gemspec +12 -1
- data/spec/assembler_spec.rb +7 -5
- data/spec/data/ColorReadout.lms +75 -0
- data/spec/data/ColorReadout.rb +67 -0
- data/spec/data/ColorReadout.rbf +0 -0
- data/spec/data/NoDebug.lms +62 -0
- data/spec/data/NoDebug.rb +25 -0
- data/spec/data/NoDebug.rbf +0 -0
- metadata +13 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4ffc33346a586d1761204e68f028b383303cc742
|
4
|
+
data.tar.gz: a57b880c420ef54dac5ea3b0023293867f5e9bdf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 41357f5c2e71a45aef56e9de73a36b2010462417210b18ea9fbd3cd654889a0103ff1aaf82ebb81f29571fa88f0f4bf43020e7dc56ac1f5862147d6b7278dd2e
|
7
|
+
data.tar.gz: 8a278113af2c9a7500d4ca7774dcb5e99a4ce163ad24e2446eb06e0b7ae4baddae676bbd736741b2d33491b3f52c75ec9f6b0bb2e8be05eff4386cf053292535
|
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--files NEWS.md
|
data/NEWS.md
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# News
|
2
|
+
|
3
|
+
## unreleased
|
4
|
+
|
5
|
+
- (none)
|
6
|
+
|
7
|
+
## 0.2.0, 2018-02-26
|
8
|
+
|
9
|
+
- DirectCommand can handle replies, allowing to read sensor data
|
10
|
+
- Motors, for easy DirectCommands to motors
|
11
|
+
- with an example program for a [Tea Serving Robot][tea], which is a standard [Bobb3e][]
|
12
|
+
- Assembler can compile global variables
|
13
|
+
- More control flow: `if`, `loop_while_postcond`
|
14
|
+
|
15
|
+
[Bobb3e]: https://www.lego.com/mindstorms/build-a-robot/bobb3e
|
16
|
+
[tea]: https://www.youtube.com/watch?v=0KOEvz09kkA
|
data/README.md
CHANGED
@@ -41,9 +41,13 @@ section of the
|
|
41
41
|
Running the built-in demo program: Connect the brick with a USB cable. Run
|
42
42
|
|
43
43
|
```sh
|
44
|
-
sudo ev3tool run
|
44
|
+
sudo ev3tool run BrkProg_SAVE/Demo.rpf
|
45
45
|
```
|
46
46
|
|
47
|
+
In the usual case where the folder and the program name are the same, a
|
48
|
+
shortcut works: `ev3tool run everstorm` is like `ev3tool run
|
49
|
+
everstorm/everstorm.rbf`.
|
50
|
+
|
47
51
|
> The `sudo` is needed to access the USB device.
|
48
52
|
> With udev you can configure the system to allow access to all users like this:
|
49
53
|
>
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/examples/bobbee.rb
ADDED
@@ -0,0 +1,211 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# coding: utf-8
|
3
|
+
# https://www.lego.com/mindstorms/build-a-robot/bobb3e
|
4
|
+
# A Bobcat® like two-tracked forklift
|
5
|
+
|
6
|
+
require "lignite"
|
7
|
+
|
8
|
+
class Bobbee
|
9
|
+
# @return [Lignite::Motors]
|
10
|
+
attr :drive
|
11
|
+
# @return [Lignite::Motors]
|
12
|
+
attr :lift
|
13
|
+
attr :dc
|
14
|
+
|
15
|
+
def initialize(drive: Lignite::PORT_B | Lignite::PORT_C,
|
16
|
+
lift: Lignite::PORT_A,
|
17
|
+
dc: Lignite::DirectCommands.new)
|
18
|
+
layer = 0
|
19
|
+
@drive = Lignite::Motors.new(layer, drive, dc)
|
20
|
+
@lift = Lignite::Motors.new(layer, lift, dc)
|
21
|
+
@dc = dc
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param turn [Integer] -200..200
|
25
|
+
def time_sync(speed, turn, ms, brake = Lignite::BRAKE, wait: true)
|
26
|
+
# 1500 ms is about 1 boost square at speed 100
|
27
|
+
drive.time_sync(-speed, turn, ms, brake)
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param turn [Integer] -200..200
|
31
|
+
def step_sync(speed, turn, degrees, brake = Lignite::BRAKE, wait: true)
|
32
|
+
# turn 0 (straight)
|
33
|
+
# - 900 (2.5 * 360) degrees is about 1 boost square
|
34
|
+
# turn 200 (full right)
|
35
|
+
# - 2400 degrees is a full turn, 600 deg is an about-right turn
|
36
|
+
# where the center of rotation is the battery-cover of the brick,
|
37
|
+
# or between the rear axles.
|
38
|
+
# turn 100 (semi right)
|
39
|
+
# - 4800 degrees is a full turn, about one of the rear axles
|
40
|
+
drive.step_sync(-speed, turn, degrees, brake)
|
41
|
+
drive.ready if wait
|
42
|
+
end
|
43
|
+
|
44
|
+
LIFT_FULL = 220
|
45
|
+
|
46
|
+
def raise(wait: true)
|
47
|
+
lift.step_power(30, 10, LIFT_FULL - 20, 10)
|
48
|
+
lift.ready if wait
|
49
|
+
end
|
50
|
+
|
51
|
+
def third_raise(wait: true)
|
52
|
+
lift.step_power(30, 10, LIFT_FULL/3 - 20, 10)
|
53
|
+
lift.ready if wait
|
54
|
+
|
55
|
+
beep
|
56
|
+
sleep 3
|
57
|
+
end
|
58
|
+
|
59
|
+
def lower(wait: true)
|
60
|
+
lift.step_power(-1, 10, LIFT_FULL - 20, 10) #, Lignite::COAST)
|
61
|
+
lift.ready if wait
|
62
|
+
|
63
|
+
beep
|
64
|
+
sleep 3
|
65
|
+
end
|
66
|
+
|
67
|
+
def third_lower(wait: true)
|
68
|
+
lift.step_power(-1, 10, LIFT_FULL/3 - 20, 10)
|
69
|
+
lift.ready if wait
|
70
|
+
end
|
71
|
+
|
72
|
+
def beep(ms = 300)
|
73
|
+
dc.sound_tone(20, 1760, ms)
|
74
|
+
dc.sound_ready
|
75
|
+
end
|
76
|
+
|
77
|
+
SQUARE_STEPS = 920
|
78
|
+
def f(steps = SQUARE_STEPS)
|
79
|
+
step_sync(50, 0, steps)
|
80
|
+
beep
|
81
|
+
sleep 3
|
82
|
+
end
|
83
|
+
|
84
|
+
def b(steps = SQUARE_STEPS)
|
85
|
+
step_sync(-50, 0, back_factor(steps))
|
86
|
+
beep
|
87
|
+
sleep 3
|
88
|
+
end
|
89
|
+
|
90
|
+
# it moves faster when going backwards!?
|
91
|
+
def back_factor(n)
|
92
|
+
(n * 0.95).to_i
|
93
|
+
end
|
94
|
+
|
95
|
+
ROTATION_OFFSET = 350
|
96
|
+
def f1
|
97
|
+
f(ROTATION_OFFSET)
|
98
|
+
beep(100)
|
99
|
+
end
|
100
|
+
|
101
|
+
TURN_90_AT_200_STEPS = 600
|
102
|
+
def l2
|
103
|
+
step_sync(50, -200, TURN_90_AT_200_STEPS)
|
104
|
+
beep(100)
|
105
|
+
sleep 3
|
106
|
+
end
|
107
|
+
|
108
|
+
def r2
|
109
|
+
step_sync(50, 200, TURN_90_AT_200_STEPS)
|
110
|
+
beep(100)
|
111
|
+
sleep 3
|
112
|
+
end
|
113
|
+
|
114
|
+
def f3
|
115
|
+
b(ROTATION_OFFSET)
|
116
|
+
beep(100)
|
117
|
+
end
|
118
|
+
|
119
|
+
def l
|
120
|
+
# a 3 part maneuver: forward, left, and back-a-little
|
121
|
+
# to turn 1 BS left
|
122
|
+
f1
|
123
|
+
l2
|
124
|
+
f3
|
125
|
+
end
|
126
|
+
|
127
|
+
def r
|
128
|
+
# a 3 part maneuver: forward, right, and back-a-little
|
129
|
+
# to turn 1 BS right
|
130
|
+
f1
|
131
|
+
r2
|
132
|
+
f3
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
bb = Bobbee.new
|
137
|
+
# 1 BS
|
138
|
+
# bb.time_sync(100, 0, 1500)
|
139
|
+
|
140
|
+
# Put Bobb3e on the blue arrow. Move it one square left, and forward.
|
141
|
+
# Put the container on a raised platform on the "twins" square.
|
142
|
+
# Put a raised platform on the "fire" square
|
143
|
+
def from_twins_to_fire(bb)
|
144
|
+
bb.instance_exec do
|
145
|
+
beep
|
146
|
+
|
147
|
+
third_raise
|
148
|
+
third_raise
|
149
|
+
r
|
150
|
+
f
|
151
|
+
third_raise
|
152
|
+
b
|
153
|
+
l
|
154
|
+
# we're at the starting position, but carrying the load
|
155
|
+
|
156
|
+
# move towards the recipient
|
157
|
+
f; f; r
|
158
|
+
|
159
|
+
# deliver and unload
|
160
|
+
f
|
161
|
+
third_lower
|
162
|
+
b
|
163
|
+
|
164
|
+
# resting position
|
165
|
+
l; b; b
|
166
|
+
third_lower
|
167
|
+
third_lower
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def from_fire_to_twins(bb)
|
172
|
+
bb.instance_exec do
|
173
|
+
beep
|
174
|
+
|
175
|
+
third_raise
|
176
|
+
third_raise
|
177
|
+
|
178
|
+
# move towards the load
|
179
|
+
f; f; r
|
180
|
+
|
181
|
+
# load
|
182
|
+
f
|
183
|
+
third_raise
|
184
|
+
b
|
185
|
+
|
186
|
+
# starting position
|
187
|
+
l; b; b
|
188
|
+
|
189
|
+
# deliver
|
190
|
+
r
|
191
|
+
f
|
192
|
+
third_lower
|
193
|
+
b
|
194
|
+
l
|
195
|
+
|
196
|
+
# resting position
|
197
|
+
third_lower
|
198
|
+
third_lower
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def calibrate_forward_and_back(bb)
|
203
|
+
bb.instance_exec do
|
204
|
+
f; f; f; f
|
205
|
+
b; b; b; b
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
# calibrate_forward_and_back(bb)
|
210
|
+
from_twins_to_fire(bb)
|
211
|
+
# from_fire_to_twins(bb)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
require "lignite"
|
3
|
+
|
4
|
+
dc = Lignite::DirectCommands.new
|
5
|
+
|
6
|
+
# see 28/31 of Comm dev kit, read light sensor value on port 3
|
7
|
+
LAYER0 = 0
|
8
|
+
MODE = 0
|
9
|
+
count = 1
|
10
|
+
pct = dc.with_reply do
|
11
|
+
# global vars
|
12
|
+
dataf :light
|
13
|
+
|
14
|
+
# TODO: make the block optional if there are no locals. or #with_locals
|
15
|
+
block do
|
16
|
+
input_device_ready_si(LAYER0, Lignite::PORT_3, Lignite::TYPE_KEEP, MODE, count, :light)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
puts "Light sensor percentage: #{pct}"
|
data/examples/motors.rb
CHANGED
@@ -15,5 +15,5 @@ dc.output_step_speed(layer, nos, speed,
|
|
15
15
|
dc.output_ready(layer, nos)
|
16
16
|
|
17
17
|
speed = -100
|
18
|
-
|
19
|
-
|
18
|
+
m = Lignite::Motors.new(layer, nos, dc)
|
19
|
+
m.step_speed(speed, step_begin, step_do, step_end)
|
data/lib/lignite.rb
CHANGED
@@ -9,6 +9,7 @@ require "lignite/connection/usb"
|
|
9
9
|
require "lignite/direct_commands"
|
10
10
|
require "lignite/message"
|
11
11
|
require "lignite/message_sender"
|
12
|
+
require "lignite/motors"
|
12
13
|
require "lignite/op_compiler"
|
13
14
|
require "lignite/rbf_object"
|
14
15
|
require "lignite/system_commands"
|
@@ -20,6 +21,11 @@ module Lignite
|
|
20
21
|
PORT_C = 4
|
21
22
|
PORT_D = 8
|
22
23
|
|
24
|
+
PORT_1 = 0
|
25
|
+
PORT_2 = 1
|
26
|
+
PORT_3 = 2
|
27
|
+
PORT_4 = 3
|
28
|
+
|
23
29
|
COAST = 0
|
24
30
|
BRAKE = 1
|
25
31
|
|
data/lib/lignite/assembler.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
+
require "lignite/variables"
|
2
|
+
|
1
3
|
module Lignite
|
4
|
+
# Assemble a complete RBF program file.
|
2
5
|
class Assembler
|
3
6
|
include Bytes
|
4
7
|
include Logger
|
@@ -9,12 +12,22 @@ module Lignite
|
|
9
12
|
u32(global_bytes)
|
10
13
|
end
|
11
14
|
|
12
|
-
|
15
|
+
# @return [Array<RbfObject>]
|
16
|
+
attr :objects
|
17
|
+
# @return [Variables]
|
18
|
+
attr :globals
|
19
|
+
|
20
|
+
# Assemble a complete RBF program file.
|
21
|
+
# (it is OK to reuse an Assembler and call this several times in a sequence)
|
22
|
+
# TODO: redesign for Assembler.new(rb_filename).assemble(rbf_filename)?
|
23
|
+
# @param rb_filename [String] input
|
24
|
+
# @param rbf_filename [String] output
|
25
|
+
def assemble(rb_filename, rbf_filename, version: 109)
|
13
26
|
rb_text = File.read(rb_filename)
|
14
27
|
@objects = []
|
15
|
-
@
|
28
|
+
@globals = Variables.new
|
16
29
|
|
17
|
-
instance_eval(rb_text, rb_filename, 1)
|
30
|
+
instance_eval(rb_text, rb_filename, 1) # 1 is the line number
|
18
31
|
|
19
32
|
File.open(rbf_filename, "w") do |f|
|
20
33
|
dummy_header = image_header(image_size:0, version: 0, object_count: 0, global_bytes: 0)
|
@@ -28,18 +41,24 @@ module Lignite
|
|
28
41
|
size = f.tell
|
29
42
|
f.pos = 0
|
30
43
|
header = image_header(image_size: size,
|
31
|
-
version:
|
44
|
+
version: version,
|
32
45
|
object_count: @objects.size,
|
33
|
-
global_bytes: @
|
46
|
+
global_bytes: @globals.bytesize)
|
34
47
|
f.write(header)
|
35
48
|
end
|
36
49
|
end
|
37
50
|
|
51
|
+
def variables
|
52
|
+
globals
|
53
|
+
end
|
54
|
+
include VariableDeclarer
|
55
|
+
|
38
56
|
def vmthread(id, &body)
|
39
57
|
@locals = Variables.new
|
40
|
-
bodyc = BodyCompiler.new(@locals)
|
58
|
+
bodyc = BodyCompiler.new(@globals, @locals)
|
41
59
|
bodyc.instance_exec(&body)
|
42
60
|
bodyc.instance_exec { object_end }
|
61
|
+
# FIXME: id is not written?!
|
43
62
|
logger.debug "VMTHREAD #{id}"
|
44
63
|
logger.debug " size #{bodyc.bytes.bytesize}"
|
45
64
|
logger.debug " " + hexdump(bodyc.bytes)
|
@@ -3,36 +3,49 @@ module Lignite
|
|
3
3
|
# - variable declarations: {VariableDeclarer}
|
4
4
|
# - high level flow control: {#loop}
|
5
5
|
class BodyCompiler
|
6
|
+
# @return [ByteString]
|
7
|
+
attr_reader :bytes
|
8
|
+
# @return [Variables]
|
9
|
+
attr_reader :locals
|
6
10
|
|
7
|
-
|
8
|
-
|
9
|
-
def data32(id)
|
10
|
-
locals.add(id, 4)
|
11
|
-
end
|
12
|
-
|
13
|
-
def datas(id, size)
|
14
|
-
locals.add(id, size)
|
15
|
-
end
|
11
|
+
def variables
|
12
|
+
locals
|
16
13
|
end
|
17
|
-
|
18
14
|
include VariableDeclarer
|
19
|
-
attr_reader :bytes
|
20
|
-
attr_reader :locals
|
21
15
|
|
22
|
-
def initialize(locals)
|
16
|
+
def initialize(globals, locals)
|
23
17
|
@bytes = ""
|
18
|
+
@globals = globals
|
24
19
|
@locals = locals
|
25
|
-
@op_compiler = OpCompiler.new(
|
20
|
+
@op_compiler = OpCompiler.new(@globals, @locals)
|
21
|
+
end
|
22
|
+
|
23
|
+
def if(flag8, &body)
|
24
|
+
subc = BodyCompiler.new(@globals, @locals)
|
25
|
+
subc.instance_exec(&body)
|
26
|
+
|
27
|
+
jr_false(flag8, Complex(subc.bytes.bytesize, 2))
|
28
|
+
@bytes << subc.bytes
|
26
29
|
end
|
27
30
|
|
28
31
|
def loop(&body)
|
29
|
-
subc = BodyCompiler.new(@locals)
|
32
|
+
subc = BodyCompiler.new(@globals, @locals)
|
30
33
|
subc.instance_exec(&body)
|
31
34
|
@bytes << subc.bytes
|
32
35
|
# the jump takes up 4 bytes: JR, LC2, LO, HI
|
33
36
|
jr(Complex(- (subc.bytes.bytesize + 4), 2))
|
34
37
|
end
|
35
38
|
|
39
|
+
def loop_while_postcond(flag8, &body)
|
40
|
+
subc = BodyCompiler.new(@globals, @locals)
|
41
|
+
subc.instance_exec(&body)
|
42
|
+
@bytes << subc.bytes
|
43
|
+
# the jump takes up 4 bytes: JR_TRUE, LV0(flag8), LC2, LO, HI
|
44
|
+
jr_true(flag8, Complex(- (subc.bytes.bytesize + 5), 2))
|
45
|
+
end
|
46
|
+
|
47
|
+
# Delegate the ops to the {OpCompiler},
|
48
|
+
# but also aggregate the result in @bytes.
|
36
49
|
def method_missing(name, *args)
|
37
50
|
super unless @op_compiler.respond_to?(name)
|
38
51
|
|
data/lib/lignite/bytes.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
module Lignite
|
2
|
+
# Shortcut methods to convert between data and their byte representation
|
2
3
|
module Bytes
|
3
4
|
def u8(n)
|
4
5
|
(n & 0xff).chr
|
@@ -28,6 +29,10 @@ module Lignite
|
|
28
29
|
s.unpack("L<").first
|
29
30
|
end
|
30
31
|
|
32
|
+
def unpack_f32(s)
|
33
|
+
s.unpack("e").first
|
34
|
+
end
|
35
|
+
|
31
36
|
def hexdump(s)
|
32
37
|
s.unpack("H*").first
|
33
38
|
end
|
@@ -1,17 +1,37 @@
|
|
1
1
|
module Lignite
|
2
|
-
# FIXME: cannot handle replies
|
3
2
|
class DirectCommands
|
4
3
|
# @param conn [Connection]
|
5
4
|
def initialize(conn = Connection.create)
|
6
5
|
@op_compiler = OpCompiler.new
|
7
6
|
@sender = MessageSender.new(conn)
|
7
|
+
@globals = nil
|
8
|
+
end
|
9
|
+
|
10
|
+
def variables
|
11
|
+
@globals
|
12
|
+
end
|
13
|
+
include VariableDeclarer
|
14
|
+
|
15
|
+
def with_reply(&body)
|
16
|
+
@globals = Variables.new
|
17
|
+
ret_bytes = instance_exec(&body)
|
18
|
+
ret = @globals.unpack(ret_bytes)
|
19
|
+
@globals = nil
|
20
|
+
ret # TODO decode according to type
|
8
21
|
end
|
9
22
|
|
10
23
|
def block(&body)
|
11
24
|
locals = Variables.new
|
12
|
-
bodyc = BodyCompiler.new(locals)
|
25
|
+
bodyc = BodyCompiler.new(@globals, locals)
|
13
26
|
bodyc.instance_exec(&body)
|
14
|
-
|
27
|
+
|
28
|
+
bs = bodyc.bytes
|
29
|
+
lsize = locals.bytesize
|
30
|
+
if @globals
|
31
|
+
@sender.direct_command_with_reply(bs, global_size: @globals.bytesize, local_size: lsize)
|
32
|
+
else
|
33
|
+
@sender.direct_command(bs, global_size: 0, local_size: lsize)
|
34
|
+
end
|
15
35
|
end
|
16
36
|
|
17
37
|
def method_missing(name, *args)
|
data/lib/lignite/message.rb
CHANGED
@@ -0,0 +1,165 @@
|
|
1
|
+
module Lignite
|
2
|
+
# Send {DirectCommands} to motors.
|
3
|
+
# It's called Motors instead of Motor because some methods are designed
|
4
|
+
# to work on a pair if motors driving a vehicle.
|
5
|
+
class Motors
|
6
|
+
# do the DCs spawn independent threads??
|
7
|
+
# must run ready in the same block?
|
8
|
+
|
9
|
+
attr :layer
|
10
|
+
attr :nos
|
11
|
+
# @return [Lignite::DirectCommands]
|
12
|
+
attr :dc
|
13
|
+
|
14
|
+
# 0x02 | 0x04 | 0x08 -> [1, 2, 3]
|
15
|
+
def nos_as_indices
|
16
|
+
[0, 1, 2, 3].find_all do |n|
|
17
|
+
(nos & (1 << n)) != 0
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(layer, nos, dc = Lignite::DirectCommands.new)
|
22
|
+
@layer = layer
|
23
|
+
@nos = nos
|
24
|
+
@dc = dc
|
25
|
+
end
|
26
|
+
|
27
|
+
# TODO filter out support: official: no
|
28
|
+
|
29
|
+
# the type is an OUT param so the VM SETs and we GET to learn the type?
|
30
|
+
def set_type
|
31
|
+
layer = @layer
|
32
|
+
nos_as_indices.map do |no|
|
33
|
+
type = dc.with_reply do
|
34
|
+
data8 :type
|
35
|
+
block do
|
36
|
+
output_set_type(layer, no, :type)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
type
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# TODO: direct commands can do outputs? not yet
|
44
|
+
|
45
|
+
# ATTR tacho, like degrees
|
46
|
+
def reset
|
47
|
+
dc.output_reset(lay, nos) # tacho counts
|
48
|
+
end
|
49
|
+
|
50
|
+
# ATTR running
|
51
|
+
def stop(brake = Lignite::BRAKE)
|
52
|
+
dc.output_stop(layer, nos, brake)
|
53
|
+
end
|
54
|
+
|
55
|
+
# ATTR power ~ speed ?
|
56
|
+
def power(power)
|
57
|
+
dc.output_power(layer, nos, power) # does this start them also?
|
58
|
+
end
|
59
|
+
|
60
|
+
def speed(speed)
|
61
|
+
dc.output_speed(layer, nos, speed) # does this start them also?
|
62
|
+
end
|
63
|
+
|
64
|
+
def start
|
65
|
+
dc.output_start(layer, nos) # apparently not
|
66
|
+
end
|
67
|
+
|
68
|
+
# ATTR ~polarity
|
69
|
+
def polarity(pol)
|
70
|
+
dc.output_polarity(layer, nos, pol)
|
71
|
+
end
|
72
|
+
|
73
|
+
def read
|
74
|
+
layer = @layer
|
75
|
+
nos_as_indices.map do |no|
|
76
|
+
speed_tacho_pair = dc.with_reply do
|
77
|
+
data32 :tacho
|
78
|
+
data8 :speed
|
79
|
+
block do
|
80
|
+
output_read(layer, no, :speed, :tacho)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
speed_tacho_pair
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# ATTR running?
|
88
|
+
def test
|
89
|
+
layer = @layer
|
90
|
+
nos_as_indices.map do |no|
|
91
|
+
busy = dc.with_reply do
|
92
|
+
data8 :busy
|
93
|
+
block do
|
94
|
+
output_test(layer, no, :busy)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
busy
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# which commands are affected? not output_start they say
|
102
|
+
def ready
|
103
|
+
dc.output_ready(layer, nos)
|
104
|
+
end
|
105
|
+
|
106
|
+
# @param power [Integer] -100..100
|
107
|
+
# TODO better param protocol?
|
108
|
+
def step_power(power, deg1, deg2, deg3, brake = Lignite::BRAKE)
|
109
|
+
dc.output_step_power(layer, nos, power, deg1, deg2, deg3, brake)
|
110
|
+
end
|
111
|
+
|
112
|
+
# @param power [Integer] -100..100
|
113
|
+
# msec
|
114
|
+
def time_power(power, ms1, ms2, ms3, brake = Lignite::BRAKE)
|
115
|
+
dc.output_time_power(layer, nos, power, ms1, ms2, ms3, brake)
|
116
|
+
end
|
117
|
+
|
118
|
+
# @param speed [Integer] -100..100
|
119
|
+
# tachos
|
120
|
+
def step_speed(speed, deg1, deg2, deg3, brake = Lignite::BRAKE)
|
121
|
+
dc.output_step_speed(layer, nos, speed, deg1, deg2, deg3, brake)
|
122
|
+
end
|
123
|
+
|
124
|
+
# @param speed [Integer] -100..100
|
125
|
+
# msec
|
126
|
+
def time_speed(speed, ms1, ms2, ms3, brake = Lignite::BRAKE)
|
127
|
+
dc.output_time_speed(layer, nos, speed, ms1, ms2, ms3, brake)
|
128
|
+
end
|
129
|
+
|
130
|
+
# @param speed [Integer] -100..100
|
131
|
+
# @param turn [Integer] -200..200:
|
132
|
+
# 0 straight, 100 stops the right motor, -100 stops the left motor
|
133
|
+
# > 100 reverses the right motor, < -100 reverses the left motor
|
134
|
+
def step_sync(speed, turn, tachos, brake = Lignite::BRAKE)
|
135
|
+
dc.output_step_sync(layer, nos, speed, turn, tachos, brake)
|
136
|
+
end
|
137
|
+
|
138
|
+
def time_sync(speed, turn, ms, brake = Lignite::BRAKE)
|
139
|
+
dc.output_time_sync(layer, nos, speed, turn, ms, brake)
|
140
|
+
end
|
141
|
+
|
142
|
+
# zero tachos, for use as sensor
|
143
|
+
def clr_count
|
144
|
+
dc.output_clr_count(layer, nos)
|
145
|
+
end
|
146
|
+
|
147
|
+
def get_count
|
148
|
+
layer = @layer
|
149
|
+
nos_as_indices.map do |no|
|
150
|
+
tachos = dc.with_reply do
|
151
|
+
data32 :tachos
|
152
|
+
block do
|
153
|
+
output_get_count(layer, no, :tachos)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
tachos
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# WTF?
|
161
|
+
def prg_stop
|
162
|
+
dc.output_prg_stop
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
data/lib/lignite/op_compiler.rb
CHANGED
@@ -1,11 +1,21 @@
|
|
1
1
|
require "yaml"
|
2
2
|
|
3
3
|
module Lignite
|
4
|
+
# Dynamically constructs methods for all the instructions in ev3.yml
|
5
|
+
# The methods return the {ByteString}s corresponding to the ops.
|
4
6
|
class OpCompiler
|
7
|
+
# TODO: doing it dynamically
|
8
|
+
# - is slow
|
9
|
+
# - makes the implementation harder to understand
|
10
|
+
# - means we cannot use YARD to document the API
|
11
|
+
# Therefore we should generate (most of) op_compiler.rb statically from
|
12
|
+
# ev3.yml ahead of the time.
|
13
|
+
|
5
14
|
include Bytes
|
6
15
|
include Logger
|
7
16
|
extend Logger
|
8
17
|
|
18
|
+
# A marker for features that are not implemented yet
|
9
19
|
class TODO < StandardError
|
10
20
|
end
|
11
21
|
|
@@ -118,6 +128,8 @@ module Lignite
|
|
118
128
|
@loaded = true
|
119
129
|
end
|
120
130
|
|
131
|
+
# @param globals [Variables,nil]
|
132
|
+
# @param locals [Variables,nil]
|
121
133
|
def initialize(globals = nil, locals = nil)
|
122
134
|
self.class.load_yml
|
123
135
|
@globals = globals
|
@@ -190,6 +202,8 @@ module Lignite
|
|
190
202
|
n & 0xff, (n >> 8) & 0xff, (n >> 16) & 0xff, (n >> 24) & 0xff]
|
191
203
|
end
|
192
204
|
|
205
|
+
# Reference a variable.
|
206
|
+
# (For declaring, see {VariableDeclarer}.)
|
193
207
|
def make_var(sym)
|
194
208
|
raise "No variables declared, cannot process symbols" if @locals.nil? && @globals.nil?
|
195
209
|
if @locals.key?(sym)
|
@@ -209,6 +223,7 @@ module Lignite
|
|
209
223
|
when Integer
|
210
224
|
make_lc(x).map(&:chr).join("")
|
211
225
|
when Complex
|
226
|
+
# a Complex number: real: just like an Integer above, but imag tells how many bytes to use for it
|
212
227
|
make_lc(x.real, x.imag).map(&:chr).join("")
|
213
228
|
when String
|
214
229
|
u8(0x80) + x + u8(0x00)
|
data/lib/lignite/rbf_object.rb
CHANGED
@@ -2,18 +2,24 @@ module Lignite
|
|
2
2
|
# Part of an assembled RBF file
|
3
3
|
class RbfObject
|
4
4
|
include Bytes
|
5
|
+
# @return [RbfObject] make a Vmthread object
|
5
6
|
def self.vmthread(body:, local_bytes:)
|
6
7
|
new(owner: 0, triggers: 0, local_bytes: local_bytes, body: body)
|
7
8
|
end
|
8
9
|
|
10
|
+
# @return [RbfObject] make a Subcall object
|
9
11
|
def self.subcall(body:, local_bytes:)
|
10
12
|
new(owner: 0, triggers: 1, local_bytes: local_bytes, body: body)
|
11
13
|
end
|
12
14
|
|
15
|
+
# @return [RbfObject] make a Block object
|
13
16
|
def self.block(owner:, triggers:, body:)
|
14
17
|
new(owner: owner, triggers: triggers, local_bytes: 0, body: body)
|
15
18
|
end
|
16
19
|
|
20
|
+
# @return [ByteString] an already assembled body of the object
|
21
|
+
attr :body
|
22
|
+
|
17
23
|
def initialize(owner:, triggers:, local_bytes:, body:)
|
18
24
|
@owner = owner
|
19
25
|
@triggers = triggers
|
@@ -25,9 +31,5 @@ module Lignite
|
|
25
31
|
u32(pos_before_header + 12) + # size of header
|
26
32
|
u16(@owner) + u16(@triggers) + u32(@local_bytes)
|
27
33
|
end
|
28
|
-
|
29
|
-
def body
|
30
|
-
@body
|
31
|
-
end
|
32
34
|
end
|
33
35
|
end
|
data/lib/lignite/variables.rb
CHANGED
@@ -1,27 +1,70 @@
|
|
1
1
|
module Lignite
|
2
2
|
# Allocate local or global variables
|
3
|
+
# FIXME: the user can make bad alignment, resulting in VMError at runtime
|
4
|
+
# bad: data8 :speed; data32 :tacho; output_read(...)
|
5
|
+
# good data32 :tacho; data8 :speed; output_read(...)
|
3
6
|
class Variables
|
4
7
|
def initialize
|
5
8
|
@offset = 0
|
9
|
+
# for proper decoding of direct replies according to declared types
|
10
|
+
@unpacker = ""
|
6
11
|
@vars = {}
|
7
12
|
end
|
8
13
|
|
9
|
-
|
14
|
+
# declare
|
15
|
+
def add(id, size, unpacker)
|
10
16
|
raise "Duplicate variable #{id}" if @vars.key?(id)
|
11
17
|
@vars[id] = {offset: @offset, size: size}
|
12
18
|
@offset += size
|
19
|
+
@unpacker += unpacker
|
13
20
|
end
|
14
21
|
|
15
|
-
|
16
|
-
@offset
|
17
|
-
end
|
18
|
-
|
22
|
+
# use
|
19
23
|
def key?(sym)
|
20
24
|
@vars.key?(sym)
|
21
25
|
end
|
22
26
|
|
27
|
+
# use
|
23
28
|
def offset(sym)
|
24
29
|
@vars[sym][:offset]
|
25
30
|
end
|
31
|
+
|
32
|
+
# compile
|
33
|
+
def bytesize
|
34
|
+
@offset
|
35
|
+
end
|
36
|
+
|
37
|
+
# decode reply
|
38
|
+
def unpack(buf)
|
39
|
+
values = buf.unpack(@unpacker)
|
40
|
+
values.size == 1 ? values.first : values
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# {#variables} are {Variables}
|
45
|
+
module VariableDeclarer
|
46
|
+
def data8(id)
|
47
|
+
variables.add(id, 1, "C")
|
48
|
+
end
|
49
|
+
|
50
|
+
def data16(id)
|
51
|
+
variables.add(id, 2, "S<")
|
52
|
+
end
|
53
|
+
|
54
|
+
def data32(id)
|
55
|
+
variables.add(id, 4, "L<")
|
56
|
+
end
|
57
|
+
|
58
|
+
def dataf(id)
|
59
|
+
variables.add(id, 4, "e")
|
60
|
+
end
|
61
|
+
|
62
|
+
def datas(id, size)
|
63
|
+
variables.add(id, size, "a#{size}")
|
64
|
+
end
|
65
|
+
|
66
|
+
def array8(id, count)
|
67
|
+
variables.add(id, count * 1, "C#{count}")
|
68
|
+
end
|
26
69
|
end
|
27
70
|
end
|
data/lignite.gemspec
CHANGED
@@ -16,13 +16,15 @@ TXT
|
|
16
16
|
s.homepage = "https://github.com/mvidner/lignite"
|
17
17
|
s.license = "GPL-3.0-only"
|
18
18
|
|
19
|
-
# ruby -e 'puts `git ls-files`.lines.map { |f| " %s
|
19
|
+
# ruby -e 'puts `git ls-files`.lines.map { |f| " %s" % f.strip.inspect }.join ",\n"'
|
20
20
|
s.files = [
|
21
21
|
".coveralls.yml",
|
22
22
|
".gitignore",
|
23
23
|
".travis.yml",
|
24
|
+
".yardopts",
|
24
25
|
"COPYING",
|
25
26
|
"Gemfile",
|
27
|
+
"NEWS.md",
|
26
28
|
"README.md",
|
27
29
|
"Rakefile",
|
28
30
|
"VERSION",
|
@@ -30,7 +32,9 @@ TXT
|
|
30
32
|
"data/ev3.yml",
|
31
33
|
"data/lignite-btaddr",
|
32
34
|
"data/sysops.yml",
|
35
|
+
"examples/bobbee.rb",
|
33
36
|
"examples/hello.rb",
|
37
|
+
"examples/light-sensor.rb",
|
34
38
|
"examples/lights.rb",
|
35
39
|
"examples/motors.rb",
|
36
40
|
"examples/sound.rb",
|
@@ -46,6 +50,7 @@ TXT
|
|
46
50
|
"lib/lignite/logger.rb",
|
47
51
|
"lib/lignite/message.rb",
|
48
52
|
"lib/lignite/message_sender.rb",
|
53
|
+
"lib/lignite/motors.rb",
|
49
54
|
"lib/lignite/op_compiler.rb",
|
50
55
|
"lib/lignite/rbf_object.rb",
|
51
56
|
"lib/lignite/system_commands.rb",
|
@@ -53,11 +58,17 @@ TXT
|
|
53
58
|
"lib/lignite/version.rb",
|
54
59
|
"lignite.gemspec",
|
55
60
|
"spec/assembler_spec.rb",
|
61
|
+
"spec/data/ColorReadout.lms",
|
62
|
+
"spec/data/ColorReadout.rb",
|
63
|
+
"spec/data/ColorReadout.rbf",
|
56
64
|
"spec/data/HelloWorld-subop.rb",
|
57
65
|
"spec/data/HelloWorld-subop.rbf",
|
58
66
|
"spec/data/HelloWorld.lms",
|
59
67
|
"spec/data/HelloWorld.rb",
|
60
68
|
"spec/data/HelloWorld.rbf",
|
69
|
+
"spec/data/NoDebug.lms",
|
70
|
+
"spec/data/NoDebug.rb",
|
71
|
+
"spec/data/NoDebug.rbf",
|
61
72
|
"spec/data/VernierReadout.lms",
|
62
73
|
"spec/data/VernierReadout.rb",
|
63
74
|
"spec/data/VernierReadout.rbf",
|
data/spec/assembler_spec.rb
CHANGED
@@ -4,7 +4,7 @@ require "lignite"
|
|
4
4
|
require "fileutils"
|
5
5
|
|
6
6
|
describe Lignite::Assembler do
|
7
|
-
shared_examples "compiles" do |base|
|
7
|
+
shared_examples "compiles" do |base, asm_version|
|
8
8
|
let(:datadir) { File.expand_path("../data", __FILE__) }
|
9
9
|
|
10
10
|
let(:in_rb) { "#{datadir}/#{base}.rb" }
|
@@ -12,13 +12,15 @@ describe Lignite::Assembler do
|
|
12
12
|
let(:expected_rbf) { "#{datadir}/#{base}.rbf" }
|
13
13
|
|
14
14
|
it "correctly assembles #{base}" do
|
15
|
-
subject.assemble(in_rb, actual_rbf)
|
15
|
+
subject.assemble(in_rb, actual_rbf, version: asm_version)
|
16
16
|
expect(FileUtils.compare_file(expected_rbf, actual_rbf)).to be_truthy
|
17
17
|
FileUtils.rm actual_rbf
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
it_behaves_like "compiles", "HelloWorld", 109
|
22
|
+
it_behaves_like "compiles", "HelloWorld-subop", 109
|
23
|
+
it_behaves_like "compiles", "VernierReadout", 109
|
24
|
+
it_behaves_like "compiles", "ColorReadout", 106
|
25
|
+
it_behaves_like "compiles", "NoDebug", 109
|
24
26
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
define PORT 1
|
2
|
+
|
3
|
+
DATA16 Cmd
|
4
|
+
DATA8 Type
|
5
|
+
DATA8 Mode
|
6
|
+
ARRAY8 Data 6
|
7
|
+
|
8
|
+
vmthread MAIN
|
9
|
+
{
|
10
|
+
DATA32 Timer
|
11
|
+
DATA32 Data1
|
12
|
+
DATA32 Data2
|
13
|
+
DATA32 Data3
|
14
|
+
DATAS String 8
|
15
|
+
DATA8 Mode
|
16
|
+
DATA8 State
|
17
|
+
|
18
|
+
|
19
|
+
MOVE8_8(3,Mode)
|
20
|
+
|
21
|
+
Loop:
|
22
|
+
|
23
|
+
UI_DRAW(FILLWINDOW,0x00,0,0)
|
24
|
+
UI_DRAW(SELECT_FONT,SMALL_FONT)
|
25
|
+
UI_DRAW(TEXT,FG_COLOR,0,10,' Color Readout V0.00 ')
|
26
|
+
UI_DRAW(TEXT,FG_COLOR,0,30,'Mode ')
|
27
|
+
|
28
|
+
UI_DRAW(TEXT,FG_COLOR,0,50,'Raw 1')
|
29
|
+
UI_DRAW(TEXT,FG_COLOR,0,65,'Raw 2')
|
30
|
+
UI_DRAW(TEXT,FG_COLOR,0,80,'Raw 3')
|
31
|
+
UI_DRAW(TEXT,FG_COLOR,0,118,'Left = 3 Right = 4')
|
32
|
+
UI_DRAW(SELECT_FONT,NORMAL_FONT)
|
33
|
+
|
34
|
+
MOVE8_32(Mode,Data1)
|
35
|
+
AND32(Data1,0xFF,Data1)
|
36
|
+
STRINGS(NUMBER_FORMATTED,Data1,'%1d',8,String)
|
37
|
+
UI_DRAW(TEXT,FG_COLOR,64,30,String)
|
38
|
+
|
39
|
+
INPUT_DEVICE(READY_RAW,0,PORT,0,Mode,3,Data1,Data2,Data3)
|
40
|
+
|
41
|
+
AND32(Data1,0xFFFF,Data1)
|
42
|
+
STRINGS(NUMBER_FORMATTED,Data1,'%-5d',8,String)
|
43
|
+
UI_DRAW(TEXT,FG_COLOR,64,50,String)
|
44
|
+
|
45
|
+
AND32(Data2,0xFFFF,Data2)
|
46
|
+
STRINGS(NUMBER_FORMATTED,Data2,'%-5d',8,String)
|
47
|
+
UI_DRAW(TEXT,FG_COLOR,64,65,String)
|
48
|
+
|
49
|
+
AND32(Data3,0xFFFF,Data3)
|
50
|
+
STRINGS(NUMBER_FORMATTED,Data3,'%-5d',8,String)
|
51
|
+
UI_DRAW(TEXT,FG_COLOR,64,80,String)
|
52
|
+
|
53
|
+
UI_DRAW(UPDATE)
|
54
|
+
|
55
|
+
|
56
|
+
UI_BUTTON(SHORTPRESS,LEFT_BUTTON,State)
|
57
|
+
JR_FALSE(State,Not3)
|
58
|
+
|
59
|
+
MOVE8_8(3,Mode)
|
60
|
+
|
61
|
+
Not3:
|
62
|
+
|
63
|
+
UI_BUTTON(SHORTPRESS,RIGHT_BUTTON,State)
|
64
|
+
JR_FALSE(State,Not4)
|
65
|
+
|
66
|
+
MOVE8_8(4,Mode)
|
67
|
+
|
68
|
+
Not4:
|
69
|
+
|
70
|
+
TIMER_WAIT(250,Timer)
|
71
|
+
TIMER_READY(Timer)
|
72
|
+
|
73
|
+
JR(Loop)
|
74
|
+
}
|
75
|
+
|
@@ -0,0 +1,67 @@
|
|
1
|
+
PORT = 1
|
2
|
+
|
3
|
+
# global vars - unused?!
|
4
|
+
data16 :cmd
|
5
|
+
data8 :type
|
6
|
+
data8 :mode
|
7
|
+
array8 :data, 6
|
8
|
+
|
9
|
+
vmthread :MAIN do
|
10
|
+
data32 :Timer
|
11
|
+
data32 :Data1
|
12
|
+
data32 :Data2
|
13
|
+
data32 :Data3
|
14
|
+
datas :String, 8
|
15
|
+
data8 :Mode
|
16
|
+
data8 :State
|
17
|
+
|
18
|
+
|
19
|
+
move8_8(3, :Mode)
|
20
|
+
|
21
|
+
self.loop do
|
22
|
+
ui_draw(FILLWINDOW, 0x00, 0, 0)
|
23
|
+
ui_draw(SELECT_FONT, SMALL_FONT)
|
24
|
+
ui_draw(TEXT, FG_COLOR, 0, 10, ' Color Readout V0.00 ')
|
25
|
+
ui_draw(TEXT, FG_COLOR, 0, 30, 'Mode ')
|
26
|
+
|
27
|
+
ui_draw(TEXT, FG_COLOR, 0, 50, 'Raw 1')
|
28
|
+
ui_draw(TEXT, FG_COLOR, 0, 65, 'Raw 2')
|
29
|
+
ui_draw(TEXT, FG_COLOR, 0, 80, 'Raw 3')
|
30
|
+
ui_draw(TEXT, FG_COLOR, 0, 118, 'Left = 3 Right = 4')
|
31
|
+
ui_draw(SELECT_FONT, NORMAL_FONT)
|
32
|
+
|
33
|
+
move8_32(:Mode, :Data1)
|
34
|
+
and32(:Data1, 0xFF, :Data1)
|
35
|
+
strings(NUMBER_FORMATTED, :Data1, '%1d', 8, :String)
|
36
|
+
ui_draw(TEXT, FG_COLOR, 64, 30, :String)
|
37
|
+
|
38
|
+
input_device(READY_RAW, 0, PORT, 0, :Mode, 3, :Data1, :Data2, :Data3)
|
39
|
+
|
40
|
+
and32(:Data1, 0xFFFF, :Data1)
|
41
|
+
strings(NUMBER_FORMATTED, :Data1, '%-5d', 8, :String)
|
42
|
+
ui_draw(TEXT, FG_COLOR, 64, 50, :String)
|
43
|
+
|
44
|
+
and32(:Data2, 0xFFFF, :Data2)
|
45
|
+
strings(NUMBER_FORMATTED, :Data2, '%-5d', 8, :String)
|
46
|
+
ui_draw(TEXT, FG_COLOR, 64, 65, :String)
|
47
|
+
|
48
|
+
and32(:Data3, 0xFFFF, :Data3)
|
49
|
+
strings(NUMBER_FORMATTED, :Data3, '%-5d', 8, :String)
|
50
|
+
ui_draw(TEXT, FG_COLOR, 64, 80, :String)
|
51
|
+
|
52
|
+
ui_draw(UPDATE)
|
53
|
+
|
54
|
+
ui_button(SHORTPRESS, LEFT_BUTTON, :State)
|
55
|
+
self.if(:State) do
|
56
|
+
move8_8(3, :Mode)
|
57
|
+
end
|
58
|
+
|
59
|
+
ui_button(SHORTPRESS, RIGHT_BUTTON, :State)
|
60
|
+
self.if(:State) do
|
61
|
+
move8_8(4, :Mode)
|
62
|
+
end
|
63
|
+
|
64
|
+
timer_wait(250, :Timer)
|
65
|
+
timer_ready(:Timer)
|
66
|
+
end
|
67
|
+
end
|
Binary file
|
@@ -0,0 +1,62 @@
|
|
1
|
+
/*
|
2
|
+
* LEGO® MINDSTORMS EV3
|
3
|
+
*
|
4
|
+
* Copyright (C) 2010-2013 The LEGO Group
|
5
|
+
*
|
6
|
+
* This program is free software; you can redistribute it and/or modify
|
7
|
+
* it under the terms of the GNU General Public License as published by
|
8
|
+
* the Free Software Foundation; either version 2 of the License, or
|
9
|
+
* (at your option) any later version.
|
10
|
+
*
|
11
|
+
* This program is distributed in the hope that it will be useful,
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
* GNU General Public License for more details.
|
15
|
+
*
|
16
|
+
* You should have received a copy of the GNU General Public License
|
17
|
+
* along with this program; if not, write to the Free Software
|
18
|
+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
19
|
+
*/
|
20
|
+
|
21
|
+
|
22
|
+
// TCP 08.04.2013
|
23
|
+
//! \page testnodebugappcode NoDebug Application
|
24
|
+
//!
|
25
|
+
//! <hr size="1"/>
|
26
|
+
//!
|
27
|
+
//! \verbatim
|
28
|
+
//**********************************************************************
|
29
|
+
define appv 'NoDebug V1.02' //
|
30
|
+
//**********************************************************************
|
31
|
+
//
|
32
|
+
//
|
33
|
+
vmthread MAIN // void MAIN(void)
|
34
|
+
{ // {
|
35
|
+
DATA8 ShowVersion //
|
36
|
+
//
|
37
|
+
UI_BUTTON(PRESSED,RIGHT_BUTTON,ShowVersion) // UI_BUTTON(PRESSED,RIGHT_BUTTON,ShowVersion)
|
38
|
+
JR_FALSE(ShowVersion,DontShowVersion) // if (ShowVersion)
|
39
|
+
// {
|
40
|
+
UI_DRAW(FILLRECT,BG_COLOR,4,50,170,28) // UI_DRAW(FILLRECT,BG_COLOR,4,50,170,28)
|
41
|
+
UI_DRAW(RECT,FG_COLOR,6,52,166,24) // UI_DRAW(RECT,FG_COLOR,6,52,166,24)
|
42
|
+
UI_DRAW(TEXT,FG_COLOR,13,60,appv) // UI_DRAW(TEXT,FG_COLOR,13,60,appv)
|
43
|
+
UI_DRAW(UPDATE) // UI_DRAW(UPDATE)
|
44
|
+
//
|
45
|
+
ShowVersionWait: // do
|
46
|
+
// {
|
47
|
+
UI_BUTTON(PRESSED,RIGHT_BUTTON,ShowVersion) // UI_BUTTON(PRESSED,RIGHT_BUTTON,ShowVersion)
|
48
|
+
// }
|
49
|
+
JR_TRUE(ShowVersion,ShowVersionWait) // while (ShowVersion)
|
50
|
+
//
|
51
|
+
UI_BUTTON(FLUSH) // UI_BUTTON(FLUSH)
|
52
|
+
DontShowVersion: // }
|
53
|
+
//
|
54
|
+
UI_DRAW(RESTORE,0) // UI_DRAW(RESTORE,0)
|
55
|
+
UI_DRAW(TOPLINE,1) // UI_DRAW(TOPLINE,1)
|
56
|
+
UI_WRITE(LED,LED_GREEN) // UI_WRITE(LED,LED_GREEN)
|
57
|
+
//
|
58
|
+
UI_WRITE(TERMINAL,0) // UI_WRITE(TERMINAL,0)
|
59
|
+
} // }
|
60
|
+
//
|
61
|
+
//
|
62
|
+
//! \endverbatim
|
@@ -0,0 +1,25 @@
|
|
1
|
+
appv = 'NoDebug V1.02'
|
2
|
+
|
3
|
+
vmthread :MAIN do
|
4
|
+
data8 :ShowVersion
|
5
|
+
|
6
|
+
ui_button(PRESSED, RIGHT_BUTTON, :ShowVersion)
|
7
|
+
self.if :ShowVersion do
|
8
|
+
ui_draw(FILLRECT, BG_COLOR, 4, 50, 170, 28)
|
9
|
+
ui_draw(RECT, FG_COLOR, 6, 52, 166, 24)
|
10
|
+
ui_draw(TEXT, FG_COLOR, 13, 60, appv)
|
11
|
+
ui_draw(UPDATE)
|
12
|
+
|
13
|
+
loop_while_postcond(:ShowVersion) do
|
14
|
+
ui_button(PRESSED, RIGHT_BUTTON, :ShowVersion)
|
15
|
+
end
|
16
|
+
|
17
|
+
ui_button(FLUSH)
|
18
|
+
end
|
19
|
+
|
20
|
+
ui_draw(RESTORE, 0)
|
21
|
+
ui_draw(TOPLINE, 1)
|
22
|
+
ui_write(LED, LED_GREEN)
|
23
|
+
|
24
|
+
ui_write(TERMINAL, 0)
|
25
|
+
end
|
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lignite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martin Vidner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-02-
|
11
|
+
date: 2018-02-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: libusb
|
@@ -112,8 +112,10 @@ files:
|
|
112
112
|
- ".coveralls.yml"
|
113
113
|
- ".gitignore"
|
114
114
|
- ".travis.yml"
|
115
|
+
- ".yardopts"
|
115
116
|
- COPYING
|
116
117
|
- Gemfile
|
118
|
+
- NEWS.md
|
117
119
|
- README.md
|
118
120
|
- Rakefile
|
119
121
|
- VERSION
|
@@ -121,7 +123,9 @@ files:
|
|
121
123
|
- data/ev3.yml
|
122
124
|
- data/lignite-btaddr
|
123
125
|
- data/sysops.yml
|
126
|
+
- examples/bobbee.rb
|
124
127
|
- examples/hello.rb
|
128
|
+
- examples/light-sensor.rb
|
125
129
|
- examples/lights.rb
|
126
130
|
- examples/motors.rb
|
127
131
|
- examples/sound.rb
|
@@ -137,6 +141,7 @@ files:
|
|
137
141
|
- lib/lignite/logger.rb
|
138
142
|
- lib/lignite/message.rb
|
139
143
|
- lib/lignite/message_sender.rb
|
144
|
+
- lib/lignite/motors.rb
|
140
145
|
- lib/lignite/op_compiler.rb
|
141
146
|
- lib/lignite/rbf_object.rb
|
142
147
|
- lib/lignite/system_commands.rb
|
@@ -144,11 +149,17 @@ files:
|
|
144
149
|
- lib/lignite/version.rb
|
145
150
|
- lignite.gemspec
|
146
151
|
- spec/assembler_spec.rb
|
152
|
+
- spec/data/ColorReadout.lms
|
153
|
+
- spec/data/ColorReadout.rb
|
154
|
+
- spec/data/ColorReadout.rbf
|
147
155
|
- spec/data/HelloWorld-subop.rb
|
148
156
|
- spec/data/HelloWorld-subop.rbf
|
149
157
|
- spec/data/HelloWorld.lms
|
150
158
|
- spec/data/HelloWorld.rb
|
151
159
|
- spec/data/HelloWorld.rbf
|
160
|
+
- spec/data/NoDebug.lms
|
161
|
+
- spec/data/NoDebug.rb
|
162
|
+
- spec/data/NoDebug.rbf
|
152
163
|
- spec/data/VernierReadout.lms
|
153
164
|
- spec/data/VernierReadout.rb
|
154
165
|
- spec/data/VernierReadout.rbf
|