Friday, July 26, 2013

BeagleBone GamingCape


TEAM MEMBERS

Max Thrun

PROJECT DESCRIPTION

Older brother of the LaunchPad GamingPack, the BeagleBone GamingCape transforms your BeagleBone into a full fledged hand-held gaming console capable of playing all the classics such as NES, Gameboy, Sega GameGear, and even Doom. Just drop in 4 AAA batteries and you'll be playing your favourite games discretely at work in no time.

PROJECT FEATURES

- 320x240 16Bit Color TFT LCD
- Analog joystick + 2 Thumb Buttons
- 3D Gyro, 3D Accelerometer, 3D Magnetometer
- Headphone Out + Mic In
- Supports:
  • NES
  • GameBoy
  • GameBoy Color
  • GameBoy Advance
  • Sega Master System
  • Sega Game Gear
  • Doom


Video




http://www.youtube.com/watch?v=wj1T84orbeY

Cape Design



The GamingCape is a conglomerate of existing, open source, BeagleBone capes all brought together in a handheld game console form factor inspired by the original Nintendo Gameboy. The four designs that I primarily leveraged are the LCD3, Audio , and Battery capes from CircuitCo and Interacto by Chris Clark.





Doing the layout was a little tricky because I had to be aware of all the areas where the case would touch the PCB. This led to some tight layouts such as the 5V power supply stuff (top layer, right below the switch). I also had to completely re-layout the 3D gyro and accelerometer components once because I had the keep-out layers disabled and didn't realize the space I was in was going to be hit.







The schematic capture and PCB layout were done in CadSoft EAGLE and the PCBs were fabricated by Silver Circuits

Schematics, layout, and CadSoft EAGLE file can be found here and the bill of materials can be found here.

Case Design



The whole system was completely modelled in Autodesk Inventor before most of the PCB layout was even started. This was necessary as parts of the case sit directly on the PCB and their dimensions needed to be known in order to keep out of those areas while doing the layout. Rodney Hill of Logic Supply was kind enough to provide me with a great, accurate, model of the BeagleBone Black which was an enormous help.

The case is designed as a stack-up of 11 laser cut pieces of Delrin. I chose Delrin over ABS because of the two sample pieces I ordered from McMaster the Delrin seemed to be "more black".


An exploded view of the stack up:


The case is locked together by screws on either side which thread into a hex standoffs. The standoffs are locked into place and prevented from spinning by hex cutouts in the first 4 plates under the PCB.

I was fortunate enough to have access to a 3D printer and was able to print the whole case and ensure all of my dimensions were 'close enough' before I paid for it to be laser cut.



In order to reduce fabrication costs it was important to use as few different thicknesses as possible. All pieces in my design are cut from 1/8" and 1/32" sheets. The layouts that I sent to get cut are for 24"x12" sheets and yield enough pieces to build two cases:




All the layers required for one case:








All of the 3D design files can be found here: https://github.com/bear24rw/gamingcape/tree/master/3D

Games



Getting the emulators up and running on the BeagleBone proved to be a little challenging. It seems that a lot of the Linux emulators aren't actively maintained and wont even compile. Lucky, Gentoo maintains patches for a few of them and I was able to use portage to fetch a patched source tree.

For the NES emulator, fceux, I was able to fetch, unpack, and patch the source on my Gentoo host and then send it to the BeagleBone where I compiled it natively. Fceux seems to work fine although I did have to patch it to center the screen:
https://github.com/bear24rw/gamingcape_fceu/commit/ac1555d7d562ee15479374c4be103a994670e4ab

For the Gameboy emulators it seemed that VisualBoyAdvance was the go-to. Again I got a patched version from portage and tried to compile it on the BeagleBone but it not only took ages but also ate up an enormous amount of RAM. At one point I was using a USB flash drive as swap space. Needless to say it failed to compile. I ended up just cross compiling it which seemed to work okay even though I didn't really setup a proper environment and was using my hosts systems header files.

For Doom I was lucky enough to find a SDL port that pretty much "just worked" which was refreshing after I tried half a dozen others which wouldn't even build.

For Osmose I found a forum post where someone had gotten it to run on a Raspberry PI. It pretty much "just worked" too.

The common issue that all the emulators share is that they are using SDL to render and the BeagleBone doesn't really support OpenGL. This means that it's really expensive to scale the screen up in non-integer units. You'll notice in my video that all the emulators were running at the original systems native resolution.

All the emulators that I patched and got working are hosted on my github:

https://github.com/bear24rw/gamingcape_osmose
https://github.com/bear24rw/gamingcape_vba
https://github.com/bear24rw/gamingcape_fceu
https://github.com/bear24rw/gamingcape_doom

Resources


https://github.com/bear24rw/gamingcape
http://hipstercircuits.com/enable-serialuarttty-on-beaglebone-black/
http://azkeller.com/blog/?p=62
http://wiki.beyondlogic.org/index.php/BeagleBoneBlack_Building_Kernel
http://www.armhf.com/index.php/using-beaglebone-black-gpios/
http://beaglebone.cameon.net/home/reading-the-analog-inputs-adc
https://github.com/beagleboard/kernel/tree/3.8
http://www.eewiki.net/display/linuxonarm/BeagleBone+Black#BeagleBoneBlack-InstallBootloaders

Saturday, July 28, 2012

MSP430 Launchpad GamingPack

TEAM MEMBERS

Max Thrun
Brittany Finch
Kathleen Foster

PROJECT DESCRIPTION

Based on the Gameduino, the GamingPack transforms your MSP430 LaunchPad into a full fledged gaming console complete with audio / video output and two Nintendo controller sockets. Just hookup your computer monitor, plug in a controller and you'll be writing games in no time.

PROJECT FEATURES

- 400x300 Pixel VGA output
- 256 16x16 Pixel simultaneous sprite images
- Up to 256 colors per sprite
- 2 Nintendo (NES) controllers
- Nostalgia


Video




http://www.youtube.com/watch?v=hDE0ZfmsVrw

Design



The schematic capture and PCB layout were done in CadSoft EAGLE. The PCBs were fabricated by Silver Circuits










The GamePack is designed around a Xilinx Spartan 3A 200K Gate FPGA. It implements the same sprite rendering core as the Gameduino and communicates to the LaunchPad via SPI. The FPGA bitstream configuration is stored on an external EEPROM which was programed using a FTDI FT2232D development board and Flashrom in Linux. The FPGA 1.2V internal core voltage is provided by a TI TLV70212 low drop out regulator.

A resistor DAC provides the various voltage levels for the VGA interface and audio is achieved by passing 2 channels of digital audio through a 4KHz low pass filter. An optional SPI EEPROM can be installed to store large game data such as images and level maps. Two status LEDs indicate power and SPI data transfer to the FPGA.

2 Nintendo (NES) controller sockets are included to provide a classic gaming experience. They are ideal for this project as the interface is simple and they can be easily purchased online or simply found in a box in your closet.









With only a month and a half to complete this project designing for test was important. The GamingPack includes a 10 pin header that can plug directly into a Saleae Logic Analyzer










Schematics, layout, and CadSoft EAGLE file can be found here.

Basic Examples


Several basic examples were developed to demonstrate and show off the various functionality of the GamingPack.



sprites_256 - Demonstates the hardwares ability to draw up to 256 sprites simultaneously



palettes - Shows each of the different color palette modes



scroll - Randomly generated scrolling terrain to show off the hardwares ability to smoothly scroll backgroud images



rotate - Example program showing the different rotation and mirror options



controllers - Small program to show how to read the NES controllers



background - Simple program showing how to display a background image



random_numbers - Shows how to use random numbers and draw text



sprite_walking - Example showing to how create a smooth walking animation



Source code for these basic examples: https://github.com/bear24rw/gamepack/tree/master/code/examples/basics

Game Examples


The GamingPack wouldn't be a gaming pack without a few games.




Breakout / Brick Breaker





Tetris





Space Invaders



Source code for the game examples: https://github.com/bear24rw/gamepack/tree/master/code/examples/games


Resources


https://github.com/bear24rw/gamepack
http://excamera.com/sphinx/gameduino

Friday, August 26, 2011

RGB LED Coffee Table

This summer all the Co-ops at Texas Instruments were challenged with coming up with a project centered around a value line MSP430. My group decided to build an RGB LED coffee table that pulsed visualization to music. We won 1st place!

A write up of the project can be found here


Wednesday, August 11, 2010

Theo Jansen Matlab Simulation

My roommate had to do a simulation of a Jansen mechanism for his kinematics class. It sounded interesting so I gave it a try. Here is what I came up with:

Screenshot-14-cropped





Doing a simulation of a mechanical linkage was something I had never done, nor even really thought about. I initially tried to express all the angles as functions of each other but this soon became insane (this could very well be due to the fact that I am in Electrical Engineering and have never taken a kinematics course before so I had no idea what the proper equations would even look like). After trying to simplify gigantic trig equations in wolframalpha.com and getting back stuff that was disgustingly crazy I resorted to my middle school way of solving equations I don't really understand: brute force. (I used to make programs on my TI-83 to brute force single (and even double) variable equations way back in the day)

So there was only three things I really had values for: the length of the legs, the distance between the crank and the pivot, and the angle of the crank. So say the crank is at a certain angle and you know its length, you can find the end point x,y using simple sin and cos. Now the end of the crank (node 0) needs to be connected to node 1. Node 1 is a known length off the pivot, link_9. So basically what I do is rotate link_9 around the pivot until the distance between node 1 and node 0 are extremely close to the length of link_1. I find this really hard to explain still even after trying to do it many times. Basically I brute force the angle of a bar until the tip of the bar is a certain length away from the other bar it needs to connect to (the distance which I know, since I know the length of all the legs).

Even though this method is absolutely confusing to explain in words it is extremely modular and dead simple to implement. The code is basically the same thing over and over again just with different bars and also some angle constraints (you know link_9 will always be between 45 and 135, roughly). Adding new bars is as simple as copy and pasting and changing the names of the variables. I can literally make any mechanism this way without doing a single line of hard coded trig.

I found the paper linked below to be extremely helpful for providing good bar lengths. All the nodes and bars in my code are named the same as those in this paper
http://ujdigispace.uj.ac.za:8080/dspace/bitstream/10210/1738/39/Numerical.pdf

Edit: For some reason the link does not work, to find the paper google: "Numerical kinematic and kinetic analysis of a new class of twelve bar linkage for walking machines"




%Max Thrun
%Simulation of Jensen Mechanism

close all %Clsoes windows
clear all %Clears all variables
clc %Clear command window

%Declare variables

crank_r = 120;
link_1 = 400;
link_2 = 389;%400;
link_3 = 275;
link_4 = 400;
link_5 = 275;
link_6 = 400;
link_7 = 275;
link_8 = 275;
link_9 = 275;
link_10 = 275;
link_11 = 412;%540;

crank_x = 0;
crank_y = 0;

pin_x = crank_x - (286/1);
pin_y = crank_y;

node_1_x = pin_x;
node_1_y = 5;

link_9_t = 0;

link_10_t = pi;
link_11_t = pi;

node_2_x = pin_x - link_9;
node_2_y = pin_y;

link_8_t = 3/4*pi;

node_3_x = pin_x;
node_3_y = pin_y - link_8;

link_7_t = pi;

node_4_x = pin_x - link_7;
node_4_y = pin_y - link_3;

link_5_t = 3/4*pi;

node_5_y = pin_y - link_8 - link_5;
node_5_x = pin_x;

node_6_y = node_5_y;
node_6_x = node_5_x;

axis([-300 300 -300 300]);
grid on %Display grid on plot
xlabel('real axis'); %Give the xlabel
ylabel('imag axis'); %Give the ylabel
title('Example 1'); %Give the title of the plot


avi = moviein((8*pi+pi/2)*5);

%Animation
figure(3)

i=0;

x = [];
y = [];

for t=0:0.1:8*pi+pi/2+pi;

i = i + 1;

node_0_x = crank_x + crank_r*cos(t);
node_0_y = crank_y + crank_r*sin(t);


%
% NODE 1
%

dist = 10000000;

for link_9_t=0:0.02:pi;
node_1_x = pin_x + link_9*cos(link_9_t);
node_1_y = pin_y + link_9*sin(link_9_t);

dist_tmp = sqrt((node_0_x-node_1_x)^2+(node_0_y-node_1_y)^2);

diff = abs(dist_tmp - link_1);

if (diff < dist)
dist = diff;
theta = link_9_t;
%fprintf('New theta: %d Diff: %d\n', theta, diff);
end
end

link_9_t = theta;

node_1_x = pin_x + link_9*cos(link_9_t);
node_1_y = pin_y + link_9*sin(link_9_t);


%
% NODE 2
%

dist = 10000000;

for link_10_t=.75*pi:0.02:1.5*pi;
node_2_x = pin_x + link_10*cos(link_10_t);
node_2_y = pin_y + link_10*sin(link_10_t);

dist_tmp = sqrt((node_2_x-node_1_x)^2+(node_2_y-node_1_y)^2);

diff = abs(dist_tmp - link_2);

if (diff < dist)
dist = diff;
theta = link_10_t;
%fprintf('New theta: %d Diff: %d\n', theta, diff);
end
end

link_10_t = theta;

node_2_x = pin_x + link_10*cos(link_10_t);
node_2_y = pin_y + link_10*sin(link_10_t);

%
% NODE 3
%

dist = 10000000;

for link_8_t=pi:0.02:2*pi;
node_3_x = pin_x + link_8*cos(link_8_t);
node_3_y = pin_y + link_8*sin(link_8_t);

dist_tmp = sqrt((node_0_x-node_3_x)^2+(node_0_y-node_3_y)^2);

diff = abs(dist_tmp - link_6);

if (diff < dist)
dist = diff;
theta = link_8_t;
end
end

link_8_t = theta;

node_3_x = pin_x + link_8*cos(link_8_t);
node_3_y = pin_y + link_8*sin(link_8_t);

%
% NODE 4
%

dist = 10000000;

for link_7_t=.75*pi:0.02:1.5*pi;
node_4_x = node_3_x + link_7*cos(link_7_t);
node_4_y = node_3_y + link_7*sin(link_7_t);

dist_tmp = sqrt((node_4_x-node_2_x)^2+(node_4_y-node_2_y)^2);

diff = abs(dist_tmp - link_3);

if (diff < dist)
dist = diff;
theta = link_7_t;
end
end

link_7_t = theta;

node_4_x = node_3_x + link_7*cos(link_7_t);
node_4_y = node_3_y + link_7*sin(link_7_t);


%
% NODE 5
%

dist = 10000000;

for link_5_t=pi:0.02:2*pi;
node_5_x = node_3_x + link_5*cos(link_5_t);
node_5_y = node_3_y + link_5*sin(link_5_t);

dist_tmp = sqrt((node_4_x-node_5_x)^2+(node_4_y-node_5_y)^2);

diff = abs(dist_tmp - link_4);

if (diff < dist)
dist = diff;
theta = link_5_t;
%fprintf('New theta: %d Diff: %d\n', theta, diff);
end
end

link_5_t = theta;

node_5_x = node_3_x + link_5*cos(link_5_t);
node_5_y = node_3_y + link_5*sin(link_5_t);

node_6_x = node_3_x + link_11*cos(link_5_t);
node_6_y = node_3_y + link_11*sin(link_5_t);

x(end+1) = node_6_x;
y(end+1) = node_6_y;

%
% DRAW
%

plot([crank_x pin_x], [crank_y pin_y],'black','linewidth',4); hold on % crank to pin
plot([crank_x node_0_x], [crank_y node_0_y],'r','linewidth',4); hold on % crank

plot([node_0_x node_1_x], [node_0_y node_1_y],'b','linewidth',4); % link_1
plot([pin_x node_1_x], [pin_y node_1_y],'g','linewidth',4); % link_9

plot([pin_x node_2_x], [pin_y node_2_y],'g','linewidth', 4); % link_10
plot([node_1_x node_2_x], [node_1_y node_2_y],'g','linewidth', 4); % link_2

plot([node_0_x node_3_x], [node_0_y node_3_y],'b','linewidth',4); % link_6
plot([pin_x node_3_x], [pin_y node_3_y],'r','linewidth',4); % link_8

plot([node_3_x node_4_x], [node_3_y node_4_y],'g','linewidth', 4); % link_7
plot([node_2_x node_4_x], [node_2_y node_4_y],'r','linewidth', 4); % link_3

plot([node_3_x node_5_x], [node_3_y node_5_y],'r','linewidth', 4); % link_5
plot([node_4_x node_5_x], [node_4_y node_5_y],'b','linewidth', 4); % link_4

plot([node_3_x node_6_x], [node_3_y node_6_y],'b','linewidth', 4); % link_5

plot(x,y);

hold off %So next plot will erase the current plot
axis([-900 600 -900 600]);
%pause(0.001) %Stop execution for 0.1 sec so that the animation can be seen
avi(i) = getframe(gca);
end



movie2avi(avi,'jansen.avi','compression','cinepak') % or cinepak, indeo5

Saturday, November 14, 2009

Omegle.com Man In The Middle Attack

The other day my friend showed me this site Omegle. It's a pretty cool site that anonymously pairs you up with a 'stranger' and you chat 1 on 1 with the ability to disconnect and find a new 'stranger' at any time. It's surprisingly addicting and fun. It claims to be completely anonymous and so to check this I decided to fire up Wireshark and take a look at what information was getting passed to the server. I was surprised to find the method of communication extremely simple and completely unencrypted. When you connect to a person the process looks like this:

You: POST omegle.com/start
Omg: HTTP "123456" <-- random 6 digit 'username' (a-z A-Z 0-9 _ -)
You: POST omegle.com/events?id=123456
Omg: HTTP [["connected"]]
You: POST omegle.com/send?msg=hello&id=123456
Omg: HTTP win <-- funny
You: POST omegle.com/events?id=123456
Omg: HTTP [["gotMessage", "hey"]] <-- message from other person
...
You: POST omegle.com/disconnect?id=123456 <-- quit the chat


Seeing this immediately sparked some thought. Can I request events for other users? Can I send messages to other users? Can I disconnect other users? It seemed all you needed to do was post the command with the user id you wanted to receive events for. As it turns out its almost even better. If you post for events using someone elses user id it will "implode" their chat:

Screenshot


Whats better is that the other person is still connected and they have no idea that their 'stranger' has been imploded. Now you can keep talking to the other person and they have no idea what just happened.

There is one major problem with this however. According to:

http://omegle.com/count

there are on average only about 3k users online at a given time, but the number of possible user ids are

(26+26+10+1+1)^6 = 68,719,476,736

That is a terrible chance of you finding someone quickly. I actually started making a brute forcer (omegle_brute_force.py) but quickly realized that this was an ill fated attempted.

So if you cant find the users, why not have the users come to you? I realized that Omegle would be prime for a classic man in the middle attack. The idea is super simple. I would connect to two strangers just like normal, but instead of me talking to them they would talk to each other through me. As long as I don't inject any messages or anything weird they should have no idea that I'm even there. Here is how the program looks:

omegle


As you can see I am having a legit connection to both client 1 and client 2, but I am transparently passing their messages right through me to the other person.

Doing this was kinda tricky. Whenever you POST for events it blocks until the read is fulfilled. This means that with a single threaded program each person would have to take turns talking since the program would block every time I polled for their messages. Even most two threaded setups have the same problem. The solution I came up with I feel works pretty well. There are four total threads:

1) Sending to client 1
2) Receiving from client 1
3) Sending to client 2
4) Receiving from client 2

Every time the receive thread gets a message it queues it into a stack, so that the sending thread can retrieve the message at its leisure. The result? It doesn't matter if a POST blocks because the sender thread can still work through the queue and the other threads can still send and receive messages.

A classic man in the middle attack:

Screenshot-2

This has some interesting possibilities. I can send messages to one of the clients at the others behalf and the person will have no idea that I sent it. Also what about connecting more then 2 people together? There is no reason I couldn't connect multiple people together in a chat and maybe even append a user tag to each of their messages.

Omegle is a pretty interesting site, and you gotta hand it to Leif K-Brooks for (apparently) single handedly making such a propular site at only 18. I hope that he can implement some needed security to Omegle to prevent this kind of attack in the future.

Download my programs here [mirror].

omegle_man_in_middle.py - program described above
omegle_brute_force.py - attempts to guess user ids and post for events
omegle_class.py - generic class for interacting with omegle
omegle_connect_view.py - connect to omegle and posts for events
omegle_multi_connect.py - connects to multiple people at once. proof of concept that multi connections can be made
omegle_send.py - send messages using a user id

EDIT:

Found another omegle man in the middle attack written in perl [here]

Sunday, November 8, 2009

PS3 Eye Driver Patch

Update: A lot has happened since this was posted. The main line kernel now includes most of these fixes!

I've had a PS3 Eye lying around for a while but I hadn't gotten around to using it because when it first came out there were no drivers for it so it sat in my closet for almost a year. I decided to check out the current state of the PS3 Eye in Linux and was happy to find that there is now support in the 2.6.31 kernel.

What I was disappointed to find out though was that there was no ability to select frame rate or control a lot of the image quality. Lucky there is patch that allows selection of frames rates all the way up to 125 fps and some image quality controls. I patched my driver and tried it out but found that the color of the image was way off and none of the given controls could fix this.

I decided to do some research and add support for brightness, contrast, hue, and auto white balance.

before
With Kaswy's Patch


driver
With my patch


I'm going to just supply the whole .c file instead of a patch since they are almost the same size. Applying the patch is almost the same as Kaswy's

To apply:

Install necessary packages:

$ sudo apt-get install kernel-package libncurses5-dev wget bzip2 build-essential linux-source


Extract kernel source code:

$ sudo su
$ cd /usr/src
$ tar --bzip2 -xvf linux-source-2.6.(your version).tar.bz2
$ ln -s linux-source-2.6.(your version) linux


Replace driver:

$ cd linux
$ wget ucfilespace.uc.edu/~thrunml/ov534.c
$ rm drivers/media/video/gspca/ov534.c
$ mv ov534.c drivers/media/video/gspca/


Recompile driver:

$ cp /usr/src/linux-headers-$(uname -r)/Module.symvers /usr/src/linux
$ make oldconfig
$ make modules_prepare
$ make SUBDIRS=drivers/media/video/gspca modules


Install new driver:

$ cp drivers/media/video/gspca/gspca_ov534.ko /lib/modules/$(uname -r)/kernel/drivers/media/video/gspca
$ depmod


Check to make sure it installed:

$ modinfo gspca-ov534
filename: /lib/modules/2.6.31-14-generic/kernel/drivers/media/video/gspca/gspca_ov534.ko
license: GPL
description: GSPCA/OV534 USB Camera Driver(kaswy mod for MT use V0.5 / bear24rw patch V0.1)
author: Antonio Ospite
srcversion: 1F87820D2B0705822B61A16
alias: usb:v1415p2000d*dc*dsc*dp*ic*isc*ip*
depends: gspca_main
vermagic: 2.6.31.4 SMP mod_unload modversions
parm: videomode: = xx //Set the videomode(see doc) (int)
parm: autogain: = [0|1] //Autogain (agc,aec,awb) (bool)
parm: gain: = [0..63] //main gain (int)
parm: awb: = [0|1] //Auto White Balance (bool)
parm: exposure: = [0..255] //Exposure (int)
parm: brightness: = [0..255] //Brightness (int)
parm: contrast: = [0..255] //Contrast (int)
parm: redblc: = [0..255] //Red Balance (int)
parm: blueblc: = [0..255] //Blue Balance (int)
parm: hue: = [0..255] //Hue (int)
parm: sharpness: = [0..63] //Sharpness (int)
parm: vflip: = [0|1] //Vertical flip (bool)
parm: hflip: = [0|1] //Horizontal mirror (bool)


Now we can remove the one currently in use and load our new one:

$ modprobe -r gspca-ov534
$ modprobe gspca-ov534 videomode=10


The available video modes are:

00: 640x480@15
01: 640x480@30
02: 640x480@40
03: 640x480@50
04: 640x480@60
10: 320x240@30
11: 320x240@40
12: 320x240@50
13: 320x240@60
14: 320x240@75
15: 320x240@100
16: 320x240@125


You can adjust the image using guvcview

$ sudo apt-get install guvcview
$ guvcview


Hopefully the main line driver gets patched soon with these enhancements.