brick-pi 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e63e867f917f20a008427c1096e7ba94b267c890
4
+ data.tar.gz: 78a16b7c6cb6a76bf6c94bcea3091a2e52d0eedb
5
+ SHA512:
6
+ metadata.gz: 34a9ac8a0def422ffd6d6fb5109d58e52288ec7efdcb4058395c6433a2b186896468c9e8b19f8d5494397da5091a78de95978a6676ca1c1f4856c1b1d395b43b
7
+ data.tar.gz: 2d082af9c7dc6311e142864f3f7164328e0c190a21dd817faef757fa657249576245649beeebdcfb66a70e3fe8017f908bf63edf48f591d2632d87a8dc236d77
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in brick_pi.gemspec
4
+ gemspec
5
+ gem "rake-compiler"
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Brandon Hays
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 TODO: Write your name
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,101 @@
1
+ # BrickBot: A BrickPi library for Ruby
2
+
3
+ ruby wrappers for the BrickPi Lego Mindstorms C library
4
+
5
+ TODO: Write a gem description
6
+ TODO: Tag, version, and publish as gem
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'brick_pi'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install brick_pi
21
+
22
+ ## Usage
23
+
24
+ Currently, you only get a set of primitives to run motors. Expect more functionality around sensors and a more robust library supporting various configurations (e.g. 2-tracked vehicle).
25
+
26
+ The Bot object starts and stops the robot. It contains 4 Motor objects, mapped to port A-D on your BrickPi.
27
+
28
+ Here's a quick & dirty script to spin a motor:
29
+
30
+ ```ruby
31
+ require 'brick_pi'
32
+
33
+ # Instantiate the Bot
34
+ bot = BrickPi::Bot.new
35
+
36
+ # Set the speed for a motor, on a scale of 0 - 100
37
+ bot.motor1.spin 50
38
+
39
+ # Get this party started
40
+ bot.start
41
+
42
+ # Stop a single motor
43
+ bot.motor1.stop
44
+
45
+ # Stop all functions for a bot
46
+ bot.stop
47
+ ```
48
+
49
+ Once your bot is started, you can change the speed or direction of the motors at any time with the `Motor#spin` method.
50
+
51
+ Here's a really yucky script I hacked together to let you drive a 2-tracked vehicle with an iCade 8-Bitty (which is basically a bluetooth keyboard that looks like an NES controller).
52
+
53
+ It requires the Highline gem, so on the BrickPi you'll need to run `gem install highline`.
54
+
55
+ ```ruby
56
+ require "highline/system_extensions"
57
+ include HighLine::SystemExtensions
58
+ HighLine::SystemExtensions.raw_no_echo_mode
59
+
60
+ bot = BrickPi::Bot.new
61
+ bot.start
62
+
63
+ speed = 20
64
+ loop do
65
+ char = HighLine::SystemExtensions.get_character
66
+ case char.chr
67
+ when 'w'
68
+ bot.motor1.spin speed
69
+ bot.motor2.spin speed
70
+ when 'd'
71
+ bot.motor1.spin speed
72
+ bot.motor2.spin 0 - speed
73
+ when 'a'
74
+ bot.motor1.spin 0 - speed
75
+ bot.motor2.spin speed
76
+ when 'x'
77
+ bot.motor1.spin 0 - speed
78
+ bot.motor2.spin 0 - speed
79
+ when 'o'
80
+ if speed >=0 && speed <= 80
81
+ speed += 20
82
+ end
83
+ when 'l'
84
+ if speed > 20 && speed <= 100
85
+ speed -= 20
86
+ end
87
+ when 'e', 'c', 'z', 'q'
88
+ bot.motor1.stop
89
+ bot.motor2.stop
90
+ end
91
+ sleep(5 / 1000)
92
+ end
93
+ ```
94
+
95
+ ## Contributing
96
+
97
+ 1. Fork it ( https://github.com/tehviking/brick_pi/fork )
98
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
99
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
100
+ 4. Push to the branch (`git push origin my-new-feature`)
101
+ 5. Create a new Pull Request
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require "rake/extensiontask"
4
+ Rake::ExtensionTask.new("native", eval(File.read("brick_pi.gemspec"))) do |ext|
5
+ ext.ext_dir = "ext/brick_pi"
6
+ ext.lib_dir = "lib/brick_pi"
7
+ ext.source_pattern = "*.{c,h}"
8
+ end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'brick_pi/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "brick-pi"
8
+ spec.version = BrickPi::VERSION
9
+ spec.authors = ["Brandon Hays", "Charles Lowell"]
10
+ spec.email = ["brandon.hays@gmail.com"]
11
+ spec.summary = %q{Ruby library to run the BrickPi drivers for Lego Mindstorms}
12
+ spec.description = %q{BrickPi uses a C library to communicate with Lego Mindstorms motors and sensors via GPIO on the Raspberry Pi. This library wraps the C and exposes a nicer, object-oriented interface via Ruby.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib", "ext"]
20
+ spec.extensions = ["ext/brick_pi/extconf.rb"]
21
+ spec.add_development_dependency "bundler", "~> 1.6"
22
+ spec.add_development_dependency "rake"
23
+ end
@@ -0,0 +1,641 @@
1
+ /*
2
+ * Matthew Richardson
3
+ * matthewrichardson37<at>gmail.com
4
+ * http://mattallen37.wordpress.com/
5
+ *
6
+ * Updated by John Cole, Dexter Industries.
7
+ *
8
+ * Initial date: June 4, 2013
9
+ * Last updated: Oct 7, 2013
10
+ *
11
+ * These files have been made available online through a Creative Commons Attribution-ShareAlike 3.0 license.
12
+ * (http://creativecommons.org/licenses/by-sa/3.0/)
13
+ *
14
+ * This is a library of functions for the RPi to communicate with the BrickPi.
15
+ */
16
+ /*
17
+ ##################################################################################################################
18
+ * Debugging:
19
+ * - NOTE THAT DEBUGGING ERROR MESSAGES ARE TURNED OFF BY DEFAULT. To debug, just take the comment out of Line 38.
20
+ *
21
+ * If you #define DEBUG in the program, the BrickPi.h drivers will print debug messages to the terminal. One common message is
22
+ * "BrickPiRx error: -2", in function BrickPiUpdateValues(). This is caused by an error in the communication with one of the
23
+ * microcontrollers on the BrickPi. When this happens, the drivers automatically re-try the communication several times before the
24
+ * function gives up and returns -1 (unsuccessful) to the user-program.
25
+
26
+ * Function BrickPiUpdateValues() will either return 0 (success), or -1 (error that could not automatically be resolved, even after
27
+ * re-trying several times). We have rarely had BrickPiUpdateValues() retry more than once before the communication was successful.
28
+ * A known cause for "BrickPiRx error: -2" is the RPi splitting the UART message. Sometimes the RPi will send e.g. 3 bytes, wait a
29
+ * while, and then send 4 more, when it should have just sent 7 at once. During the pause between the packs of bytes, the BrickPi
30
+ * microcontrollers will think the transmission is complete, realize the message doesn't make sense, throw it away, and not return
31
+ * a message to the RPi. The RPi will then fail to receive a message in the specified amount of time, timeout, and then retry the
32
+ * communication.
33
+ */
34
+
35
+ #ifndef __BrickPi_h_
36
+ #define __BrickPi_h_
37
+
38
+ // #define DEBUG
39
+
40
+ #include <wiringPi.h>
41
+
42
+ #define PORT_A 0
43
+ #define PORT_B 1
44
+ #define PORT_C 2
45
+ #define PORT_D 3
46
+
47
+ #define PORT_1 0
48
+ #define PORT_2 1
49
+ #define PORT_3 2
50
+ #define PORT_4 3
51
+
52
+ #define MASK_D0_M 0x01
53
+ #define MASK_D1_M 0x02
54
+ #define MASK_9V 0x04
55
+ #define MASK_D0_S 0x08
56
+ #define MASK_D1_S 0x10
57
+
58
+ #define BYTE_MSG_TYPE 0 // MSG_TYPE is the first byte.
59
+ #define MSG_TYPE_CHANGE_ADDR 1 // Change the UART address.
60
+ #define MSG_TYPE_SENSOR_TYPE 2 // Change/set the sensor type.
61
+ #define MSG_TYPE_VALUES 3 // Set the motor speed and direction, and return the sesnors and encoders.
62
+ #define MSG_TYPE_E_STOP 4 // Float motors immidately
63
+ #define MSG_TYPE_TIMEOUT_SETTINGS 5 // Set the timeout
64
+
65
+ // New UART address (MSG_TYPE_CHANGE_ADDR)
66
+ #define BYTE_NEW_ADDRESS 1
67
+
68
+ // Sensor setup (MSG_TYPE_SENSOR_TYPE)
69
+ #define BYTE_SENSOR_1_TYPE 1
70
+ #define BYTE_SENSOR_2_TYPE 2
71
+
72
+ // Timeout setup (MSG_TYPE_TIMEOUT_SETTINGS)
73
+ #define BYTE_TIMEOUT 1
74
+
75
+ #define TYPE_MOTOR_PWM 0
76
+ #define TYPE_MOTOR_SPEED 1
77
+ #define TYPE_MOTOR_POSITION 2
78
+
79
+ #define TYPE_SENSOR_RAW 0 // - 31
80
+ #define TYPE_SENSOR_LIGHT_OFF 0
81
+ #define TYPE_SENSOR_LIGHT_ON (MASK_D0_M | MASK_D0_S)
82
+ #define TYPE_SENSOR_TOUCH 32
83
+ #define TYPE_SENSOR_ULTRASONIC_CONT 33
84
+ #define TYPE_SENSOR_ULTRASONIC_SS 34
85
+ #define TYPE_SENSOR_RCX_LIGHT 35 // tested minimally
86
+ #define TYPE_SENSOR_COLOR_FULL 36
87
+ #define TYPE_SENSOR_COLOR_RED 37
88
+ #define TYPE_SENSOR_COLOR_GREEN 38
89
+ #define TYPE_SENSOR_COLOR_BLUE 39
90
+ #define TYPE_SENSOR_COLOR_NONE 40
91
+ #define TYPE_SENSOR_I2C 41
92
+ #define TYPE_SENSOR_I2C_9V 42
93
+
94
+ #define BIT_I2C_MID 0x01 // Do one of those funny clock pulses between writing and reading. defined for each device.
95
+ #define BIT_I2C_SAME 0x02 // The transmit data, and the number of bytes to read and write isn't going to change. defined for each device.
96
+
97
+ #define INDEX_RED 0
98
+ #define INDEX_GREEN 1
99
+ #define INDEX_BLUE 2
100
+ #define INDEX_BLANK 3
101
+
102
+ void BrickPiTx(unsigned char dest, unsigned char ByteCount, unsigned char OutArray[]);
103
+
104
+ struct BrickPiStruct{
105
+ unsigned char Address [2]; // Communication addresses
106
+ unsigned long Timeout ; // Communication timeout (how long in ms since the last valid communication before floating the motors). 0 disables the timeout.
107
+
108
+ /*
109
+ Motors
110
+ */
111
+ int MotorSpeed [4]; // Motor speeds, from -255 to 255
112
+ unsigned char MotorEnable [4]; // Motor enable/disable
113
+
114
+ /*
115
+ Encoders
116
+ */
117
+ long EncoderOffset [4]; // Encoder offsets (not yet implemented)
118
+ long Encoder [4]; // Encoder values
119
+
120
+ /*
121
+ Sensors
122
+ */
123
+ long Sensor [4]; // Primary sensor values
124
+ long SensorArray [4][4]; // For more sensor values for the sensor (e.g. for color sensor FULL mode).
125
+ unsigned char SensorType [4]; // Sensor types
126
+ unsigned char SensorSettings [4][8]; // Sensor settings, used for specifying I2C settings.
127
+
128
+ /*
129
+ I2C
130
+ */
131
+ unsigned char SensorI2CDevices[4]; // How many I2C devices are on each bus (1 - 8).
132
+ unsigned char SensorI2CSpeed [4]; // The I2C speed.
133
+ unsigned char SensorI2CAddr [4][8]; // The I2C address of each device on each bus.
134
+ unsigned char SensorI2CWrite [4][8]; // How many bytes to write
135
+ unsigned char SensorI2CRead [4][8]; // How many bytes to read
136
+ unsigned char SensorI2COut [4][8][16]; // The I2C bytes to write
137
+ unsigned char SensorI2CIn [4][8][16]; // The I2C input buffers
138
+ };
139
+
140
+ struct BrickPiStruct BrickPi;
141
+
142
+ //Store the button's of the MINDSENSORS PSP Controller
143
+ struct button
144
+ {
145
+ unsigned char l1;
146
+ unsigned char l2;
147
+ unsigned char r1;
148
+ unsigned char r2;
149
+ unsigned char a;
150
+ unsigned char b;
151
+ unsigned char c;
152
+ unsigned char d;
153
+ unsigned char tri;
154
+ unsigned char sqr;
155
+ unsigned char cir;
156
+ unsigned char cro;
157
+ unsigned char ljb; // joystick button state
158
+ unsigned char rjb; // joystick button state
159
+
160
+ int ljx; // analog value of joystick scaled from -127 to 127
161
+ int ljy; // analog value of joystick scaled from -127 to 127
162
+ int rjx; // analog value of joystick scaled from -127 to 127
163
+ int rjy; // analog value of joystick scaled from -127 to 127
164
+ };
165
+ //Initialize all the buttons to 0 of the MINDSENSORS PSP controller
166
+ struct button init_psp (struct button b)
167
+ {
168
+ b.l1 = 0;
169
+ b.l2 = 0;
170
+ b.r1 = 0;
171
+ b.r2 = 0;
172
+ b.a = 0;
173
+ b.b = 0;
174
+ b.c = 0;
175
+ b.d = 0;
176
+ b.tri = 0;
177
+ b.sqr = 0;
178
+ b.cir = 0;
179
+ b.cro = 0;
180
+ b.ljb = 0;
181
+ b.rjb = 0;
182
+ b.ljx = 0;
183
+ b.ljy = 0;
184
+ b.rjx = 0;
185
+ b.rjy = 0;
186
+ return b;
187
+ }
188
+
189
+ //Update all the buttons of the MINDSENSORS PSP controller
190
+ //For all buttons:
191
+ // 0: Unpressed
192
+ // 1: Pressed
193
+ //
194
+ // Left and right joystick: -127 to 127
195
+ struct button upd(struct button b,int port)
196
+ {
197
+ //Left and right joystick button press
198
+ b.ljb = ~(BrickPi.SensorI2CIn[port][0][0] >> 1) & 0x01;
199
+ b.rjb = ~(BrickPi.SensorI2CIn[port][0][0] >> 2) & 0x01;
200
+
201
+ //For buttons a,b,c,d
202
+ b.d = ~(BrickPi.SensorI2CIn[port][0][0] >> 4) & 0x01;
203
+ b.c = ~(BrickPi.SensorI2CIn[port][0][0] >> 5) & 0x01;
204
+ b.b = ~(BrickPi.SensorI2CIn[port][0][0] >> 6) & 0x01;
205
+ b.a = ~(BrickPi.SensorI2CIn[port][0][0] >> 7) & 0x01;
206
+
207
+ //For buttons l1,l2,r1,r2
208
+ b.l2 = ~(BrickPi.SensorI2CIn[port][0][1] ) & 0x01;
209
+ b.r2 = ~(BrickPi.SensorI2CIn[port][0][1] >> 1) & 0x01;
210
+ b.l1 = ~(BrickPi.SensorI2CIn[port][0][1] >> 2) & 0x01;
211
+ b.r1 = ~(BrickPi.SensorI2CIn[port][0][1] >> 3) & 0x01;
212
+
213
+ //For buttons square,triangle,cross,circle
214
+ b.tri = ~(BrickPi.SensorI2CIn[port][0][1] >> 4) & 0x01;
215
+ b.cir = ~(BrickPi.SensorI2CIn[port][0][1] >> 5) & 0x01;
216
+ b.cro = ~(BrickPi.SensorI2CIn[port][0][1] >> 6) & 0x01;
217
+ b.sqr = ~(BrickPi.SensorI2CIn[port][0][1] >> 7) & 0x01;
218
+
219
+ //Left joystick x and y , -127 to 127
220
+ b.ljx = -1*((BrickPi.SensorI2CIn[port][0][5]&0xff) - 128);
221
+ b.ljy = (BrickPi.SensorI2CIn[port][0][4]&0xff) - 128;
222
+
223
+ //Right joystick x and y , -127 to 127
224
+ b.rjx = -1*((BrickPi.SensorI2CIn[port][0][3]&0xff) - 128);
225
+ b.rjy = (BrickPi.SensorI2CIn[port][0][2]&0xff) - 128;
226
+ return b;
227
+ }
228
+ //Show button values of the MINDSENSORS PSP controller
229
+ void show_val(struct button b)
230
+ {
231
+ printf("ljb rjb d c b a l2 r2 l1 r1 tri cir cro sqr\tljx\tljy\trjx\trjy\n");
232
+ printf("%d ",b.ljb);
233
+ printf(" %d ",b.rjb);
234
+ printf(" %d ",b.d);
235
+ printf("%d ",b.c);
236
+ printf("%d ",b.b);
237
+ printf("%d ",b.a);
238
+
239
+ printf("%d ",b.l2);
240
+ printf(" %d ",b.r2);
241
+ printf(" %d ",b.l1);
242
+ printf(" %d ",b.r1);
243
+ printf(" %d ",b.tri);
244
+ printf(" %d ",b.cir);
245
+ printf(" %d ",b.cro);
246
+ printf(" %d ",b.sqr);
247
+ printf("\t%d ",b.ljx);
248
+ printf("\t%d ",b.rjx);
249
+ printf("\t%d ",b.ljy);
250
+ printf("\t%d\n\n",b.rjy);
251
+ }
252
+ unsigned char Array[256];
253
+ unsigned char BytesReceived;
254
+
255
+ int BrickPiChangeAddress(unsigned char OldAddr, unsigned char NewAddr){
256
+ unsigned char i = 0;
257
+ Array[BYTE_MSG_TYPE] = MSG_TYPE_CHANGE_ADDR;
258
+ Array[BYTE_NEW_ADDRESS] = NewAddr;
259
+ BrickPiTx(OldAddr, 2, Array);
260
+
261
+ if(BrickPiRx(&BytesReceived, Array, 5000))
262
+ return -1;
263
+ if(!(BytesReceived == 1 && Array[BYTE_MSG_TYPE] == MSG_TYPE_CHANGE_ADDR))
264
+ return -1;
265
+
266
+ return 0;
267
+ }
268
+
269
+ int BrickPiSetTimeout(){
270
+ unsigned char i = 0;
271
+ while(i < 2){
272
+ Array[BYTE_MSG_TYPE] = MSG_TYPE_TIMEOUT_SETTINGS;
273
+ Array[BYTE_TIMEOUT ] = ( BrickPi.Timeout & 0xFF);
274
+ Array[(BYTE_TIMEOUT + 1)] = ((BrickPi.Timeout / 256 ) & 0xFF);
275
+ Array[(BYTE_TIMEOUT + 2)] = ((BrickPi.Timeout / 65536 ) & 0xFF);
276
+ Array[(BYTE_TIMEOUT + 3)] = ((BrickPi.Timeout / 16777216) & 0xFF);
277
+ BrickPiTx(BrickPi.Address[i], 5, Array);
278
+ if(BrickPiRx(&BytesReceived, Array, 2500))
279
+ return -1;
280
+ if(!(BytesReceived == 1 && Array[BYTE_MSG_TYPE] == MSG_TYPE_TIMEOUT_SETTINGS))
281
+ return -1;
282
+ i++;
283
+ }
284
+ return 0;
285
+ }
286
+
287
+ unsigned int Bit_Offset = 0;
288
+
289
+ void AddBits(unsigned char byte_offset, unsigned char bit_offset, unsigned char bits, unsigned long value){
290
+ unsigned char i = 0;
291
+ while(i < bits){
292
+ if(value & 0x01){
293
+ Array[(byte_offset + ((bit_offset + Bit_Offset + i) / 8))] |= (0x01 << ((bit_offset + Bit_Offset + i) % 8));
294
+ }
295
+ value /= 2;
296
+ i++;
297
+ }
298
+ Bit_Offset += bits;
299
+ }
300
+
301
+ unsigned long GetBits(unsigned char byte_offset, unsigned char bit_offset, unsigned char bits){
302
+ unsigned long Result = 0;
303
+ char i = bits;
304
+ while(i){
305
+ Result *= 2;
306
+ Result |= ((Array[(byte_offset + ((bit_offset + Bit_Offset + (i - 1)) / 8))] >> ((bit_offset + Bit_Offset + (i - 1)) % 8)) & 0x01);
307
+ i--;
308
+ }
309
+ Bit_Offset += bits;
310
+ return Result;
311
+ }
312
+
313
+ unsigned char BitsNeeded(unsigned long value){
314
+ unsigned char i = 0;
315
+ while(i < 32){
316
+ if(!value)
317
+ return i;
318
+ value /= 2;
319
+ i++;
320
+ }
321
+ return 31;
322
+ }
323
+
324
+ int BrickPiSetupSensors(){
325
+ unsigned char i = 0;
326
+ while(i < 2){
327
+ int ii = 0;
328
+ while(ii < 256){
329
+ Array[ii] = 0;
330
+ ii++;
331
+ }
332
+ Bit_Offset = 0;
333
+ Array[BYTE_MSG_TYPE] = MSG_TYPE_SENSOR_TYPE;
334
+ Array[BYTE_SENSOR_1_TYPE] = BrickPi.SensorType[PORT_1 + (i * 2)];
335
+ Array[BYTE_SENSOR_2_TYPE] = BrickPi.SensorType[PORT_2 + (i * 2)];
336
+ ii = 0;
337
+ while(ii < 2){
338
+ unsigned char port = (i * 2) + ii;
339
+ if(Array[BYTE_SENSOR_1_TYPE + ii] == TYPE_SENSOR_I2C
340
+ || Array[BYTE_SENSOR_1_TYPE + ii] == TYPE_SENSOR_I2C_9V){
341
+ AddBits(3, 0, 8, BrickPi.SensorI2CSpeed[port]);
342
+
343
+ if(BrickPi.SensorI2CDevices[port] > 8)
344
+ BrickPi.SensorI2CDevices[port] = 8;
345
+
346
+ if(BrickPi.SensorI2CDevices[port] == 0)
347
+ BrickPi.SensorI2CDevices[port] = 1;
348
+
349
+ AddBits(3, 0, 3, (BrickPi.SensorI2CDevices[port] - 1));
350
+
351
+ unsigned char device = 0;
352
+ while(device < BrickPi.SensorI2CDevices[port]){
353
+ AddBits(3, 0, 7, (BrickPi.SensorI2CAddr[port][device] >> 1));
354
+ AddBits(3, 0, 2, BrickPi.SensorSettings[port][device]);
355
+ if(BrickPi.SensorSettings[port][device] & BIT_I2C_SAME){
356
+ AddBits(3, 0, 4, BrickPi.SensorI2CWrite[port][device]);
357
+ AddBits(3, 0, 4, BrickPi.SensorI2CRead [port][device]);
358
+ unsigned char out_byte = 0;
359
+ while(out_byte < BrickPi.SensorI2CWrite[port][device]){
360
+ AddBits(3, 0, 8, BrickPi.SensorI2COut[port][device][out_byte]);
361
+ out_byte++;
362
+ }
363
+ }
364
+ device++;
365
+ }
366
+ }
367
+ ii++;
368
+ }
369
+ unsigned char UART_TX_BYTES = (((Bit_Offset + 7) / 8) + 3);
370
+ BrickPiTx(BrickPi.Address[i], UART_TX_BYTES, Array);
371
+ if(BrickPiRx(&BytesReceived, Array, 500000))
372
+ return -1;
373
+ if(!(BytesReceived == 1 && Array[BYTE_MSG_TYPE] == MSG_TYPE_SENSOR_TYPE))
374
+ return -1;
375
+ i++;
376
+ }
377
+ return 0;
378
+ }
379
+
380
+ unsigned char Retried = 0; // For re-trying a failed update.
381
+
382
+ int BrickPiUpdateValues(){
383
+ unsigned char i = 0;
384
+ unsigned int ii = 0;
385
+ while(i < 2){
386
+ Retried = 0;
387
+
388
+ __RETRY_COMMUNICATION__:
389
+
390
+ ii = 0;
391
+ while(ii < 256){
392
+ Array[ii] = 0;
393
+ ii++;
394
+ }
395
+
396
+ Array[BYTE_MSG_TYPE] = MSG_TYPE_VALUES;
397
+
398
+ Bit_Offset = 0;
399
+
400
+ // AddBits(1, 0, 2, 0); use this to disable encoder offset
401
+
402
+ ii = 0; // use this for encoder offset support
403
+ while(ii < 2){
404
+ unsigned char port = (i * 2) + ii;
405
+ if(BrickPi.EncoderOffset[port]){
406
+ long Temp_Value = BrickPi.EncoderOffset[port];
407
+ unsigned char Temp_ENC_DIR;
408
+ unsigned char Temp_BitsNeeded;
409
+
410
+ AddBits(1, 0, 1, 1);
411
+ if(Temp_Value < 0){
412
+ Temp_ENC_DIR = 1;
413
+ Temp_Value *= (-1);
414
+ }
415
+ Temp_BitsNeeded = (BitsNeeded(Temp_Value) + 1);
416
+ AddBits(1, 0, 5, Temp_BitsNeeded);
417
+ Temp_Value *= 2;
418
+ Temp_Value |= Temp_ENC_DIR;
419
+ AddBits(1, 0, Temp_BitsNeeded, Temp_Value);
420
+ }
421
+ else{
422
+ AddBits(1, 0, 1, 0);
423
+ }
424
+ ii++;
425
+ }
426
+
427
+ int speed;
428
+ unsigned char dir;
429
+ ii = 0;
430
+ while(ii < 2){
431
+ unsigned char port = (i * 2) + ii;
432
+ speed = BrickPi.MotorSpeed[port];
433
+ dir = 0;
434
+ if(speed < 0){
435
+ dir = 1;
436
+ speed *= (-1);
437
+ }
438
+ if(speed > 255){
439
+ speed = 255;
440
+ }
441
+ AddBits(1, 0, 10, ((((speed & 0xFF) << 2) | (dir << 1) | (BrickPi.MotorEnable[port] & 0x01)) & 0x3FF));
442
+ ii++;
443
+ }
444
+
445
+ ii = 0;
446
+ while(ii < 2){
447
+ unsigned char port = (i * 2) + ii;
448
+ if(BrickPi.SensorType[port] == TYPE_SENSOR_I2C
449
+ || BrickPi.SensorType[port] == TYPE_SENSOR_I2C_9V){
450
+ unsigned char device = 0;
451
+ while(device < BrickPi.SensorI2CDevices[port]){
452
+ if(!(BrickPi.SensorSettings[port][device] & BIT_I2C_SAME)){
453
+ AddBits(1, 0, 4, BrickPi.SensorI2CWrite[port][device]);
454
+ AddBits(1, 0, 4, BrickPi.SensorI2CRead [port][device]);
455
+ unsigned char out_byte = 0;
456
+ while(out_byte < BrickPi.SensorI2CWrite[port][device]){
457
+ AddBits(1, 0, 8, BrickPi.SensorI2COut[port][device][out_byte]);
458
+ out_byte++;
459
+ }
460
+ }
461
+ device++;
462
+ }
463
+ }
464
+ ii++;
465
+ }
466
+
467
+ unsigned char UART_TX_BYTES = (((Bit_Offset + 7) / 8) + 1);
468
+ BrickPiTx(BrickPi.Address[i], UART_TX_BYTES, Array);
469
+
470
+ int result = BrickPiRx(&BytesReceived, Array, 7500);
471
+
472
+ if(result != -2){ // -2 is the only error that indicates that the BrickPi uC did not properly receive the message
473
+ BrickPi.EncoderOffset[((i * 2) + PORT_A)] = 0;
474
+ BrickPi.EncoderOffset[((i * 2) + PORT_B)] = 0;
475
+ }
476
+
477
+ if(result || (Array[BYTE_MSG_TYPE] != MSG_TYPE_VALUES)){
478
+ #ifdef DEBUG
479
+ printf("BrickPiRx error: %d\n", result);
480
+ #endif
481
+ if(Retried < 2){
482
+ Retried++;
483
+ goto __RETRY_COMMUNICATION__;
484
+ }
485
+ else{
486
+ #ifdef DEBUG
487
+ printf("Retry failed.\n");
488
+ #endif
489
+ return -1;
490
+ }
491
+ }
492
+
493
+ Bit_Offset = 0;
494
+
495
+ unsigned char Temp_BitsUsed[2] = {0, 0}; // Used for encoder values
496
+ Temp_BitsUsed[0] = GetBits(1, 0, 5);
497
+ Temp_BitsUsed[1] = GetBits(1, 0, 5);
498
+ unsigned long Temp_EncoderVal;
499
+
500
+ ii = 0;
501
+ while(ii < 2){
502
+ Temp_EncoderVal = GetBits(1, 0, Temp_BitsUsed[ii]);
503
+ if(Temp_EncoderVal & 0x01){
504
+ Temp_EncoderVal /= 2;
505
+ BrickPi.Encoder[ii + (i * 2)] = Temp_EncoderVal * (-1);}
506
+ else{
507
+ BrickPi.Encoder[ii + (i * 2)] = (Temp_EncoderVal / 2);}
508
+ ii++;
509
+ }
510
+
511
+ ii = 0;
512
+ while(ii < 2){
513
+ unsigned char port = ii + (i * 2);
514
+ switch(BrickPi.SensorType[port]){
515
+ case TYPE_SENSOR_TOUCH:
516
+ BrickPi.Sensor[port] = GetBits(1, 0, 1);
517
+ break;
518
+ case TYPE_SENSOR_ULTRASONIC_CONT:
519
+ case TYPE_SENSOR_ULTRASONIC_SS:
520
+ BrickPi.Sensor[port] = GetBits(1, 0, 8);
521
+ break;
522
+ case TYPE_SENSOR_COLOR_FULL:
523
+ BrickPi.Sensor[port] = GetBits(1, 0, 3);
524
+ BrickPi.SensorArray[port][INDEX_BLANK] = GetBits(1, 0, 10);
525
+ BrickPi.SensorArray[port][INDEX_RED ] = GetBits(1, 0, 10);
526
+ BrickPi.SensorArray[port][INDEX_GREEN] = GetBits(1, 0, 10);
527
+ BrickPi.SensorArray[port][INDEX_BLUE ] = GetBits(1, 0, 10);
528
+ break;
529
+ case TYPE_SENSOR_I2C:
530
+ case TYPE_SENSOR_I2C_9V:
531
+ BrickPi.Sensor[port] = GetBits(1, 0, BrickPi.SensorI2CDevices[port]);
532
+ unsigned char device = 0;
533
+ while(device < BrickPi.SensorI2CDevices[port]){
534
+ if(BrickPi.Sensor[port] & (0x01 << device)){
535
+ unsigned char in_byte = 0;
536
+ while(in_byte < BrickPi.SensorI2CRead[port][device]){
537
+ BrickPi.SensorI2CIn[port][device][in_byte] = GetBits(1, 0, 8);
538
+ in_byte++;
539
+ }
540
+ }
541
+ device++;
542
+ }
543
+ break;
544
+ case TYPE_SENSOR_LIGHT_OFF:
545
+ case TYPE_SENSOR_LIGHT_ON:
546
+ case TYPE_SENSOR_RCX_LIGHT:
547
+ case TYPE_SENSOR_COLOR_RED:
548
+ case TYPE_SENSOR_COLOR_GREEN:
549
+ case TYPE_SENSOR_COLOR_BLUE:
550
+ case TYPE_SENSOR_COLOR_NONE:
551
+ default:
552
+ BrickPi.Sensor[(ii + (i * 2))] = GetBits(1, 0, 10);
553
+ }
554
+ ii++;
555
+ }
556
+ i++;
557
+ }
558
+ return 0;
559
+ }
560
+
561
+ int UART_file_descriptor = 0;
562
+
563
+ int BrickPiSetup(){
564
+ UART_file_descriptor = serialOpen("/dev/ttyAMA0", 500000);
565
+ if(UART_file_descriptor == -1){
566
+ return -1;
567
+ }
568
+ return 0;
569
+ }
570
+
571
+ void BrickPiTx(unsigned char dest, unsigned char ByteCount, unsigned char OutArray[]){
572
+ unsigned char tx_buffer[256];
573
+ tx_buffer[0] = dest;
574
+ tx_buffer[1] = dest + ByteCount;
575
+ tx_buffer[2] = ByteCount;
576
+ unsigned char i = 0;
577
+ while(i < ByteCount){
578
+ tx_buffer[1] += OutArray[i];
579
+ tx_buffer[i + 3] = OutArray[i];
580
+ i++;
581
+ }
582
+ i = 0;
583
+ while(i < (ByteCount + 3)){
584
+ serialPutchar(UART_file_descriptor, tx_buffer[i]);
585
+ i++;
586
+ }
587
+ }
588
+
589
+ int BrickPiRx(unsigned char *InBytes, unsigned char *InArray, long timeout){ // timeout in uS, not mS
590
+ unsigned char rx_buffer[256];
591
+ unsigned char RxBytes = 0;
592
+ unsigned char CheckSum = 0;
593
+ unsigned char i = 0;
594
+ int result;
595
+ unsigned long OrigionalTick = CurrentTickUs();
596
+ while(serialDataAvail(UART_file_descriptor) <= 0){
597
+ if(timeout && ((CurrentTickUs() - OrigionalTick) >= timeout))return -2;
598
+ }
599
+
600
+ RxBytes = 0;
601
+ while(RxBytes < serialDataAvail(UART_file_descriptor)){ // If it's been 1 ms since the last data was received, assume it's the end of the message.
602
+ RxBytes = serialDataAvail(UART_file_descriptor);
603
+ usleep(75);
604
+ }
605
+
606
+ i = 0;
607
+ while(i < RxBytes){
608
+ result = serialGetchar(UART_file_descriptor);
609
+ if(result >= 0){
610
+ rx_buffer[i] = result;
611
+ }
612
+ else{
613
+ return -1;
614
+ }
615
+ i++;
616
+ }
617
+
618
+ if(RxBytes < 2)
619
+ return -4;
620
+
621
+ if(RxBytes < (rx_buffer[1] + 2))
622
+ return -6;
623
+
624
+ CheckSum = rx_buffer[1];
625
+
626
+ i = 0;
627
+ while(i < (RxBytes - 2)){
628
+ CheckSum += rx_buffer[i + 2];
629
+ InArray[i] = rx_buffer[i + 2];
630
+ i++;
631
+ }
632
+
633
+ if(CheckSum != rx_buffer[0])
634
+ return -5;
635
+
636
+ *InBytes = (RxBytes - 2);
637
+
638
+ return 0;
639
+ }
640
+
641
+ #endif
@@ -0,0 +1,4 @@
1
+ require 'mkmf'
2
+ find_header 'wiringPi.h'
3
+ find_library 'wiringPi', 'serialOpen'
4
+ create_makefile 'brick_pi/native'
@@ -0,0 +1,65 @@
1
+ #include "ruby.h";
2
+ #include "tick.h";
3
+ #include "BrickPi.h";
4
+
5
+ VALUE bprb_BrickPiSetup(VALUE self) {
6
+ return INT2FIX(BrickPiSetup());
7
+ }
8
+ VALUE bprb_ClearTick(VALUE self) {
9
+ return INT2FIX(ClearTick());
10
+ }
11
+
12
+ VALUE bprb_MotorSpeed_set(VALUE self, VALUE key, VALUE value) {
13
+ int index = FIX2INT(key);
14
+ BrickPi.MotorSpeed[index] = FIX2INT(value);
15
+ return value;
16
+ }
17
+
18
+ VALUE bprb_Address_set(VALUE self, VALUE key, VALUE value) {
19
+ int index = FIX2INT(key);
20
+ BrickPi.Address[index] = FIX2INT(value);
21
+ return value;
22
+ }
23
+
24
+ VALUE bprb_MotorEnable_set(VALUE self, VALUE key, VALUE value) {
25
+ int index = FIX2INT(key);
26
+ BrickPi.MotorEnable[index] = FIX2INT(value);
27
+ return value;
28
+ }
29
+
30
+ VALUE bprb_Timeout_set(VALUE self, VALUE timeout) {
31
+ BrickPi.Timeout = FIX2INT(timeout);
32
+ return timeout;
33
+ }
34
+
35
+ VALUE bprb_BrickPiSetTimeout(VALUE self) {
36
+ return INT2FIX(BrickPiSetTimeout());
37
+ }
38
+
39
+ VALUE bprb_BrickPiUpdateValues(VALUE self) {
40
+ return INT2FIX(BrickPiUpdateValues());
41
+ }
42
+
43
+ void Init_native() {
44
+ VALUE BrickPi = rb_define_module("BrickPi");
45
+ VALUE Native = rb_define_module_under(BrickPi, "Native");
46
+ rb_define_singleton_method(Native, "BrickPiSetup", bprb_BrickPiSetup, 0);
47
+ rb_define_singleton_method(Native, "ClearTick", bprb_ClearTick, 0);
48
+ VALUE MotorSpeed = rb_define_module_under(Native, "MotorSpeed");
49
+ rb_define_singleton_method(MotorSpeed, "[]=", bprb_MotorSpeed_set, 2);
50
+ VALUE MotorEnable = rb_define_module_under(Native, "MotorEnable");
51
+ rb_define_singleton_method(MotorEnable, "[]=", bprb_MotorEnable_set, 2);
52
+ VALUE Address = rb_define_module_under(Native, "Address");
53
+ rb_define_singleton_method(Address, "[]=", bprb_Address_set, 2);
54
+ rb_define_singleton_method(Native, "Timeout=", bprb_Timeout_set, 1);
55
+ rb_define_singleton_method(Native, "BrickPiSetTimeout", bprb_BrickPiSetTimeout, 0);
56
+ rb_define_singleton_method(Native, "BrickPiUpdateValues", bprb_BrickPiUpdateValues, 0);
57
+ rb_define_const(Native, "PORT_A", INT2FIX(0));
58
+ rb_define_const(Native, "PORT_B", INT2FIX(1));
59
+ rb_define_const(Native, "PORT_C", INT2FIX(2));
60
+ rb_define_const(Native, "PORT_D", INT2FIX(3));
61
+ rb_define_const(Native, "PORT_1", INT2FIX(0));
62
+ rb_define_const(Native, "PORT_2", INT2FIX(1));
63
+ rb_define_const(Native, "PORT_3", INT2FIX(2));
64
+ rb_define_const(Native, "PORT_4", INT2FIX(3));
65
+ }
@@ -0,0 +1,46 @@
1
+ /*
2
+ * Matthew Richardson
3
+ * matthewrichardson37<at>gmail.com
4
+ * http://mattallen37.wordpress.com/
5
+ * Initial date: June 3, 2013
6
+ * Last updated: June 4, 2013
7
+ *
8
+ * You may use this code as you wish, provided you give credit where it's due.
9
+ *
10
+ * This is a library of functions for timing.
11
+ */
12
+
13
+ #ifndef __tick_h_
14
+ #define __tick_h_
15
+
16
+ #include <time.h>
17
+
18
+ // gcc -o program test.c -lrt
19
+
20
+ struct timespec tick_struct;
21
+ unsigned long sec_offset = 0;
22
+ unsigned long nsec_offset = 0;
23
+
24
+ int ClearTick(){
25
+ clock_gettime(CLOCK_REALTIME, &tick_struct);
26
+ sec_offset = tick_struct.tv_sec;
27
+ nsec_offset = tick_struct.tv_nsec;
28
+ }
29
+
30
+ unsigned long CurrentTickMs(){
31
+ clock_gettime(CLOCK_REALTIME, &tick_struct);
32
+ tick_struct.tv_sec -= sec_offset;
33
+ tick_struct.tv_nsec -= nsec_offset;
34
+ tick_struct.tv_nsec /= 1000000;
35
+ return ((tick_struct.tv_sec * 1000) + tick_struct.tv_nsec);
36
+ }
37
+
38
+ unsigned long CurrentTickUs(){
39
+ clock_gettime(CLOCK_REALTIME, &tick_struct);
40
+ tick_struct.tv_sec -= sec_offset;
41
+ tick_struct.tv_nsec -= nsec_offset;
42
+ tick_struct.tv_nsec /= 1000;
43
+ return ((tick_struct.tv_sec * 1000000) + tick_struct.tv_nsec);
44
+ }
45
+
46
+ #endif
@@ -0,0 +1,4 @@
1
+ require "brick_pi/version"
2
+ require "brick_pi/native"
3
+ require "brick_pi/bot"
4
+ require "brick_pi/motor"
@@ -0,0 +1,36 @@
1
+ require 'brick_pi'
2
+ include BrickPi
3
+
4
+ module BrickPi
5
+ class Bot
6
+ attr_accessor :motor1, :motor2
7
+
8
+ def initialize
9
+ Native.BrickPiSetup()
10
+ @motor1 = ::BrickPi::Motor.new(Native::PORT_A)
11
+ @motor2 = ::BrickPi::Motor.new(Native::PORT_B)
12
+ @motor3 = ::BrickPi::Motor.new(Native::PORT_C)
13
+ @motor4 = ::BrickPi::Motor.new(Native::PORT_D)
14
+ Native::Address[0] = 1
15
+ Native::Address[1] = 2
16
+ end
17
+
18
+ def start
19
+ @stop = false
20
+ Native.ClearTick()
21
+ Native.Timeout = 50
22
+ Native.BrickPiSetTimeout()
23
+
24
+ Thread.new do
25
+ until @stop do
26
+ Native.BrickPiUpdateValues()
27
+ sleep(50/1000)
28
+ end
29
+ end
30
+ end
31
+
32
+ def stop
33
+ @stop = true
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,19 @@
1
+ module BrickPi
2
+ class Motor
3
+ def initialize(port)
4
+ @port = port
5
+ Native::MotorEnable[@port] = 1
6
+ end
7
+
8
+ def spin(speed)
9
+ speed = [-100, [100, speed].min].max
10
+ motor_speed = (speed * 2.55).round
11
+ puts motor_speed
12
+ Native::MotorSpeed[@port] = motor_speed
13
+ end
14
+
15
+ def stop
16
+ spin 0
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ module BrickPi
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: brick-pi
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Brandon Hays
8
+ - Charles Lowell
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-04-30 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ~>
19
+ - !ruby/object:Gem::Version
20
+ version: '1.6'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ version: '1.6'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ description: BrickPi uses a C library to communicate with Lego Mindstorms motors and
43
+ sensors via GPIO on the Raspberry Pi. This library wraps the C and exposes a nicer,
44
+ object-oriented interface via Ruby.
45
+ email:
46
+ - brandon.hays@gmail.com
47
+ executables: []
48
+ extensions:
49
+ - ext/brick_pi/extconf.rb
50
+ extra_rdoc_files: []
51
+ files:
52
+ - .gitignore
53
+ - Gemfile
54
+ - LICENSE
55
+ - LICENSE.txt
56
+ - README.md
57
+ - Rakefile
58
+ - brick_pi.gemspec
59
+ - ext/brick_pi/BrickPi.h
60
+ - ext/brick_pi/extconf.rb
61
+ - ext/brick_pi/native.c
62
+ - ext/brick_pi/tick.h
63
+ - lib/brick_pi.rb
64
+ - lib/brick_pi/bot.rb
65
+ - lib/brick_pi/motor.rb
66
+ - lib/brick_pi/version.rb
67
+ homepage: ''
68
+ licenses:
69
+ - MIT
70
+ metadata: {}
71
+ post_install_message:
72
+ rdoc_options: []
73
+ require_paths:
74
+ - lib
75
+ - ext
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 2.0.3
89
+ signing_key:
90
+ specification_version: 4
91
+ summary: Ruby library to run the BrickPi drivers for Lego Mindstorms
92
+ test_files: []