brick-pi 0.0.1

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.
@@ -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: []