lignite 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|