Showing posts with label c. Show all posts
Showing posts with label c. Show all posts

Tuesday, 12 April 2016

Mayhem, Amiga game, ported to Raspberry Pi

Update - I've taken Mayhem forward to create Mayhem 2.

I had a Commodore Amiga and a game I played, a lot, was Mayhem, its a multiplayer (2-4) shooter - imagine multiplayer asteroids, with gravity, fuel and shields!

It was ported to the PC in 2002 by devpack who released the code in 2011 on github and google code which is where I picked it up and ported it to the Raspberry Pi.

This is the port, but check out the original Amiga game.

I got some help from the Raspberry Pi forums in getting it to compile then it was case of sorting out a few case sensitive filename bugs (it was original written for Windows!) and tracking down a bug in the original code which was causing a memory access error and segmentation fault.

The code is on github.com/martinohanlon/mayhem-pi.

Install
sudo apt-get install liballegro4.4 liballegro4-dev
git clone https://github.com/martinohanlon/mayhem-pi

Run
cd mayhem-pi
./start

Keys
Player 1 - z, x, c, v, g
Player 2 - left, right, pad del, pad 0, pad enter
Player 3 - b, n, 'comma', m, l
Player 4 - y, u, o, i, 0
Change level - 1, 2, 3

Compile
If you want to modify the game, I've got a couple of things on my list, you can recompile it with.
cd mayhem-pi
make

Image

Monday, 18 January 2016

Pocket PiGRRL - Battery Monitor

I recently made myself an Adafruit Pocket PiGRRL and I wanted to modify it so it would warn me when the battery was running low - there is a small red LED but its hidden inside the case!

Image

The plan was to create a program which would sense the battery getting low and put a warning icon on the top left of screen giving me time to shutdown the Pi properly or plug it in.

Image

Image

TLDR - just scroll down to install Grrl Battery Monitor.

I started with the software as I, foolishly, thought this would be the hardest part, the problem with creating an icon is that is has to go over the top of everything regardless of what is on the screen (command prompt, emulators, emulation station, everything) or what hardware was rendering it.

My first plan was that I could use Picamera's overlay function which I knew used the GPU to output directly to the screen, and with a bit of help from Dave Jones who put together a prototype, it was looking good, but while the icon appeared on top of emulators and the command prompt, it didnt write over emulation station.

I came across Low Level Graphics on Raspberry Pi which walks you through writing graphics directly to the Linux framebuffer using C, this was a lot lower level than I hoped to get into but it would definitely write my icon over anything that was on the screen - using this I wrote a program to create an icon on the screen when a GPIO pin was triggered.

Next I needed to be able to read from the power booster when the battery was running low, my original plan was to use the LBO (low battery output) pin, but this proved to be way more difficult than I expected, read this post on Adafruit's forum if your really interested.

I ended up connecting a wire to the low battery warning led (red) on the power booster and using this to switch a transistor which connected a GPIO to ground.

Image

Its been frustrating but I am really pleased with how it worked out - if you want to add the batter monitor to your own Pocket PiGRRL follow the instructions below.

Install Grrl Battery Monitor

You will need a few parts:
  • Some wire
  • 2N3904 NPN transistor
  • 47k resistor
  • Strip board
Note - if you are doing this on a PiGRRL 2 with a Pi 3, be sure to check out Christian's comments about the pin to use and wiring-pi install before starting.

1. Open up your Pi GRRL and connect a small length of wire to the red (low power) led on the power booster.

Image

Image

2. Solder the components to the strip board. including 2 lengths of wire which will connect to GPIO 19 and GND.

Image

Image

Image

3. Flip over your Pi and solder the GPIO and GND wires to the underside of the Pi's GPIO header.

Image

Image
The yellow wire is for my mute / un-mute amp function.

4, Solder the wire from the low power (red) led to the strip board.

Image

5. Stick the strip board to the case in-between the power booster and the amp with a bit of glue and put your PiGRRL back together.

6. Download the program from github.com/martinohanlon/grrl-bat-monitor
cd ~
git clone https://github.com/martinohanlon/grrl-bat-monitor
7. Make the program run at boot by editing /etc/rc.local
sudo nano /etc/rc.local
Scroll down and add the command under '/usr/local/bin/retrogame &' but before 'exit 0':
/home/pi/grrl-bat-monitor/grrl_bat_mon &
8. Reboot and test!

Tuesday, 3 September 2013

Raspberry Pi Syncing data with RaspiVid

Since I used a Raspberry Pi to capture video and data from my car and then overlay the data onto the video, I've been looking for an easier way of synchronising data with video, simply put "Its was a right pain in the bum".

It was difficult because while you can note the time the data was captured, you don't know what the 'time' will be in the video because you get drift (e.g. if you specify 30 frames a second, it isn't always 'exactly' 30 frames a second, sometimes its more, sometimes its less, sometimes frames are dropped) and the longer the video the more 'drift'.

After investigating several ways of doing this I decided what I need was a way of 'asking' raspivid while it was running "where it was", that way I could tag that information alongside the data and use it to sync it to video later.

To do this I had to answer a number of questions:
  • What data in the video encoding process could I use?  I settled on current frame number
  • How could I find the frame number?  By modifying raspivid to 'count frames'
  • How could I count frames?  By examining the contents of a 'buffer' before it was written to disk to see if it contained an end frame and if it did increment a count
  • How could I get the frame count out while it was running?  By using a shared memory segment and semaphore
I have forked the raspberrypi/userland repository (which contains raspivid), https://github.com/martinohanlon/userland, the raspivid code is in /host_applications/linux/apps/raspicam/RaspiVid.c and all my changes are commented with the heading MaOH.   View my custom raspivid code here.

I created a really simple demo, which recorded the screen and noted the frame number and key pressed before formatting it as a subtitle file which I then encoded to the movie file, to test the synchronisation.  The quality is terrible but it does work.



Compile userland fork
Clone my userland fork

mkdir ~/code
cd ~/code
git clone git://github.com/martinohanlon/userland.git

See this post to on how to compile userland, if you want to keep the original raspivid software (probably a good idea!), dont run the command sudo make install.

My custom raspivid program will be compiled in the ~/code/userland/build/bin directory.

Using my custom raspivid
The custom version of raspivid I created works exactly the same as the original, but if the program is outputting the video to a file, it also outputs the frame count at run time to shared memory.

~/code/userland/build/bin/raspivid -o test.h264

Reading the frame count
To get the frame count while raspivid is running, you need to read the value from system V shared memory and to protect the value from corruption while reading it, you need to use a semaphore.

The process works like this:
  1. Acquire the semaphore, which will stop raspivid updating it
  2. Read the frame count from shared memory
  3. Release the semaphore
In order to use the shared memory and semaphore you need the keys:
  • shared memory - 20130821
  • semaphore - 20130822
Any programming language which can read from shared memory and use semaphores should be able to do this.  The frame count is written to the shared memory as a string to make it easier to consume, messing about with integer types can be bit painful.

Example Python code
The following code reads the frame count from shared memory 100 times, pausing for 0.5 seconds between each read.  It used a great python module, sysv_ipc, which greatly simplifies the interaction with shared memory, see http://semanchuk.com/philip/sysv_ipc/ for more information, download and install instructions.

To install sysv_ipc:

sudo apt-get install python-dev
wget http://semanchuk.com/philip/sysv_ipc/sysv_ipc-0.6.5.tar.gz
tar -xf sysv_ipc-0.6.5.tar.gz
cd sysv_ipc-0.6.5
sudo python setup.py install

Python code:

import sysv_ipc
import time

# Open shared memory object
memory = sysv_ipc.SharedMemory(20130821)

# Open semaphore
semaphore = sysv_ipc.Semaphore(20130822)

for count in range(0,100):
    print "acquiring semaphore"
    # Acquire the semaphore using a 2 second timeout
    semaphore.acquire(2)

    # Read value from shared memory
    frameCount = memory.read()

    # Release the semaphore
    semaphore.release()

    print "released semaphore"

    # Find the 'end' of the string and strip
    i = frameCount.find('\0')
    if i != -1:
        frameCount = frameCount[:i]

    print "value is " + frameCount

    # wait
    time.sleep(0.5)

Remember to run raspivid before running this code, otherwise you will be presented with an error saying the shared memory / semaphore doesn't exist.

I would welcome any improvements to this and would actively encourage you to download my code and "have a go".

Friday, 23 August 2013

Compile Raspberry Pi Userland / RaspiVid / RaspiStill

I've been working on a few changes to the RaspiVid program which controls the raspberry pi camera board.

The first step was to get the code from github, https://github.com/raspberrypi/userland and compile it.  The raspberry pi camera programs (RaspiVid and RaspiCam) are part of the 'userland' repository and as such I needed to compile the whole repository.

I got most of this information from http://www.darkoperator.com/blog/2013/5/23/fixin-raspistill-and-raspivid-for-headless-streaming-on-the.html.

Install dependencies

sudo apt-get install git-core gcc build-essential cmake vlc

Download code

mkdir ~/code

cd ~/code

git clone git://github.com/raspberrypi/userland.git

Create make files

cd ~/code/userland

sed -i 's/if (DEFINED CMAKE_TOOLCHAIN_FILE)/if (NOT DEFINED CMAKE_TOOLCHAIN_FILE)/g' makefiles/cmake/arm-linux.cmake

Compile

mkdir ~/code/userland/build

cd ~/code/userland/build

sudo cmake -DCMAKE_BUILD_TYPE=Release ..

sudo make

Wait - it will take about 15 minutes to compile the whole of the userland repository.

The executables will be created in the bin directory:

cd ~/code/userland/build/bin

Re-compile
If you change any of the applications, you can re-compile using:

sudo make

It will only compile the changes you have made and will taken significantly less time than the first build.

Install
If you want to install the newly built applications, use:

sudo make install


Thursday, 22 August 2013

Shared Memory C & Python IPC


I had a problem whereby I needed to use a C program to capture video, in this case RaspiVid (the raspberry pi camera capture program), but I wanted to sync the video with data being capture by a Python program; in order to get the sync right I need to grab data about the video capture as it was running.

To do this I had to find a method of doing Inter Process Communication (IPC), very quickly, with a very low performance impact on the C program.  I explored several IPC options between C and Python (stdin/stdout, named pipes, tcp, shared memory) and found that using Shared Memory was the only way to deliver the performance I needed.

I pulled together a quick proof of concept to learn the basics.

C - Writing to Shared Memory
I created a C program which writes data into a shared memory segment and then waits (to allow me time to run the python program to read it out).  See http://www.cs.cf.ac.uk/Dave/C/node27.html for a description of how to use shared memory and this video http://www.youtube.com/watch?v=QPxcOwMmpnw for a tutorial.

shmwriter.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int main(int argc, const char **argv)
{
   int shmid;
   // give your shared memory an id, anything will do
   key_t key = 123456;
   char *shared_memory;

   // Setup shared memory, 11 is the size
   if ((shmid = shmget(key, 11, IPC_CREAT | 0666)) < 0)
   {
      printf("Error getting shared memory id");
      exit(1);
   }
   // Attached shared memory
   if ((shared_memory = shmat(shmid, NULL, 0)) == (char *) -1)
   {
      printf("Error attaching shared memory id");
      exit(1);
   }
   // copy "hello world" to shared memory
   memcpy(shared_memory, "Hello World", sizeof("Hello World"));
   // sleep so there is enough time to run the reader!
   sleep(10);
   // Detach and remove shared memory
   shmdt(shmid);
   shmctl(shmid, IPC_RMID, NULL);
}

Compile using:

gcc -o shmwriter shmwriter.c

Python - Reading from Shared Memory
I found a great module for python, sysv_ipc, which greatly simplifies the interaction with shared memory, see http://semanchuk.com/philip/sysv_ipc/ for more information, download and install instructions.

shmreader.py

import sysv_ipc

# Create shared memory object
memory = sysv_ipc.SharedMemory(123456)

# Read value from shared memory
memory_value = memory.read()

# Find the 'end' of the string and strip
i = memory_value.find('\0')
if i != -1:
    memory_value = memory_value[:i]

print memory_value

Run using:

python shmreader.py

You can download the code from github, https://github.com/martinohanlon/c_python_ipc.git.