Month: December 2022

How to create a Controller Map on Raspberry Pi

How to create a Controller Map on Raspberry Pi

Game Controller map screenshotI’ve been working on my 2nd eBook and adding a GamePad is a thing I need to explain. You can see them in earlier blog posts:

  1. Fun with gamepads.
  2. More on Raspberry Pi Gamepads.

But I want readers of the book to be able to generate their own controller maps. I cannot assume that everyone has access to Windows.

What I didn’t know back then is that SDL comes with a game controller map generator application called (subtle this!) controllermap that you can run on your Pi or Linux computer.

 

I had to use the File Manager Find file facility to locate it. It’s in the installed-tests folder for SDL2 or more precisely /usr/lib/aarch64-linux-gnu/installed-tests/SDL2 on my Raspberry Pi running 64-bit Raspberry Pi OS.

On my VM Ubuntu I found it in /usr/lib/x86-64-linux-gnu/installed-tests/SDL2

I did a bit of experimenting with a clean Raspberry Pi OS setup and then I installed libsdl2-dev and saw the installed-tests/SDL2 folder installed, so that’s what you need. So install the dev files as per New tutorial on installing SDL on Linux.

Plug in a gamepad and on your Pi, cd into that folder (the Pi one not the Ubuntu one!)  and in a terminal run ./controllermap

USB Joypad

It will open with your B button highlighted. Press your B button. In the picture above it’s the circle on the right hand side that is the lowest of the four or the yellow button in this picture of my controller.

It will then go through every possible button.  Just press the corresponding button or space key if you haven’t got that. Compared to the main picture, mine lacks the two bottom joysticks, the buttons between the Stop and Start buttons and the two trigger buttons at the top. For each of those just press the space bar.  Eventually it will loop back to the B button. Just press it and it will finish and output the gamepad control map.

It outputs two copies of this. You can send one to a text file in your home folder by doing

./controllermap >~/gamepad.txt 

but you will have to press all the buttons etc. again. This is what my Pi gave.

030000001008000001e5000010010000,usb gamepad,platform:Linux,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,

And that is what you use in SDL2 code.

 

 

How to fix sound on the Raspberry Pi

How to fix sound on the Raspberry Pi

Raspi-config for Raspberry PiFirst I modded the code that inits sound to this:

	int success=Mix_OpenAudio(44000, AUDIO_F32LSB, 2, 8192);
	if (success==-1 ) {

		LogError2("InitSetup failed to init audio because %s",Mix_GetError());
	}

That extra call to Mix_GetError() returns a string saying what the problem is and in this case I got

ALSA : Couldn’t find any hardware audio formats.

ALSA is short for Advanced Linux Sound Architecture and Wikipedia is very informative. It certainly put some perspective on it.

 

Also I found this article adds a lot more information.  What fixed it though was doing

sudo raspi-config

Then pressing enter on 1. System Options and then S2 Audio and selecting the headphones option. Simple as that. After that asteroids played the sounds as expected.

There’s a lesson here which is to use the functions provided, in this case calling the Mix_GetError() function to show errors.  I added it into the PlayASound() call to see why it was failing, and it stopped doing it, i.e. it worked with lots of explosions on screen. I suspect it was the sound configuration hadn’t been properly set which is an issue with Raspberry Pis apparently.

Raspberry Pi Sound issues- trying to fix it

Raspberry Pi Sound issues- trying to fix it

Loudpeaker
Image by OpenClipart-Vectors from Pixabay

In working through my Linux/Raspberry Pi eBook(Yes – the second eBook!), I’m up to the chapter where sounds are introduced using the SDL_mixer library. And I’ve hit two sets of problems.

It sometimes refuses to initialize the sound code.  This code below hits the LogError line:

	int success=Mix_OpenAudio(22050, AUDIO_S16LSB, 2, 8192);
	if (success==-1 ) {
		LogError("InitSetup failed to init audio");
	}

The other day it was working but not today. Now I have updated the Pi’s code (sudo apt update etc) but I wouldn’t have expected that to break it. I’ve been looking on the internet and find the whole thing a bit complicated.

I’ve got my Pi running 64-bit Raspberry Pi OS. I’ve changed the output device to headphones which plug into the headphone socket. If I run the VLC media player and tell it to play into the headphones, it will happily play the .wav files I’ve got for the asteroids game.

But if I run speaker-test, a terminal application with this command line

speaker-test -c2 -twav -l7 plughw:1,0

I get

speaker-test 1.2.4

Playback device is default
Stream parameters are 48000Hz, S16_LE, 2 channels
WAV file(s)
Setting of hwparams failed: Invalid argument

By running this command:

aplay -L

I got 71 lines of output but of these these below are the most important

output
hw:CARD=Headphones,DEV=0
    bcm2835 Headphones, bcm2835 Headphones

and the speaker-test command using the device parameter –Dhw:Headphones now worked. I’ve highlighted the bits in the aplay output needed to identify the device.

The new command  is

speaker-test -c2 -twav -l7 -Dhw:Headphones

I can now hear a female voice saying front left then front right a few times in my headphones.

So my Pi’s sound device is working; I just have to figure why SDL_mixer isn’t always. I’ll keep looking.

And the second problem which only occurs when the mixer is working, is when you play a lot of sounds. The PlayASound() function checks the result. On Windows it never had a problem but on Raspberry Pi, when you blow up a lot of asteroids say at one time, it plays a number of explosions then returns an error for each explosion after that. I think there’s only so many channels; that’s an easy fix; just ignore the error and return as if it succeeded.

A very useful Windows Utility in C

A very useful Windows Utility in C

ExplorerPatcher menuIf you use Windows 11 you’ll be aware of one or two issues with it; the file explorer popup menu needs a second click to take you to the Windows 10 menu with Copy, cut paste etc.

So I was pleased to discover explorer patcher which is a utility written in C that lets you get the Windows 10 right-click menu back as well as changing the File explorer right-click popup menu and a lot of other stuff.

It’s on GitHub and the authors are happy for you to look at the source code and submit improvements of your own.

If you want to see how to make changes to Windows etc in C, this is a great example.

Added to the C Code Links page.

PS. I use this and have found that after a Windows update, the right-click menu gets reset to the Windows 11. However just opening the explorer patcher settings and unticking then ticking the option for Disable the Windows 11 context menu on the File Explorer menu fixes it.

How to Configure Visual Studio Code for C/C++ development

How to Configure Visual Studio Code for C/C++ development

VS Code C/C++ extensionWhen I first started with VS Code on Linux, I found the C/C++ configuration somewhat confusing.  I blundered through, wasted a bit of time and got there in the end. After a gap of a couple of years I did the same again recently on Raspberry Pi. It’s clearer in my mind now so I thought I’d explain it here. This works for Ubuntu, Raspberry Pi OS and should for most other Linuxes. (Not that I’ve tried them all…)

We’ll start with you having already installed Clang (or GCC) and VS Code, and the C/C++ extension for VS Code (shown above). So make sure those are all done.

Start by defining a Folder for VS Code. VS code doesn’t use projects but it manages everything relative to the currently defined Folder.  It’ll ask you to open a folder initially. That’s where your source code etc will go. I created a folder called examples under my home folder and used that.

To compile anything C/C++ you also need two json files. These files are

  • tasks.json
  • c_cpp_properties.json

They are held in a hidden folder called .vscode in your current folder. Press F1 and you’ll see a popup menu. Type in C/C++ and you’ll see all the C/C++ items. Select C/C++: Edit Configurations (JSON). It’s highlighted below.

Vs Copde C++ menu

Now if you click that, and look in the folder examples you’ll see nothing but if you know how to view hidden files using the files utility (as shown below). Then you’ll see the folder .vscode.  On Raspberry Pi the file explorer always shows hidden files.

Show hidden files in files utility Now look in that folder and you’ll see c_cpp_properties.json.

Next we want tasks.json. On the Terminal menu, click the bottom item which is Configure Default Build Task

It’ll ask you to select the clang  build active task so click that and voila you now have tasks.json open in the editor.

Vs Code Configure Default Build Task

Build Active File

 

 

 

 

 

 

 

 

 

 

Now I’ve created the standard hello world file in the file hw.c.

#include <stdio.h>

int main() {
  printf("Hello world\n");
  return 0;
}

So just do Terminal/Run Build Task and it will have clang compile the currently opened file. If you get terminal failed to launch (exit code: -1) then it’s likely that your hello world source file was not the currently opened file in the editor. You can see which file is open because its tab is brightest.

Note that hw.c is brighter than tasks.json on the left. On the right, the open file is tasks.json and its tab is brighter.

Open file in VS Code

Tasks.json is open

So what are the json files for?

The c_cpp_properties.json lets you specify include file paths.  For instance if you have the SDL files installed, the include files are in /usr/include/SDL2

SDL2 include files

Note you can install SDL on linux by following these instructions.

The tasks.json file lets you specify which files are to be included and also linked.

Here I’ve just shown the args section from a tasks.json used to build SDL2 games.

	"args": [
		"-g",
		"${file}",
		"${workspaceFolder}/hr_time.c",
		"-o",
		"${fileDirname}/${fileBasenameNoExtension}",
		"-lSDL2",
		"-lSDL2_image",
		"-lSDL2_mixer",
		"-lm"
	],

The -g option includes files. The ${file} is the current opened file and {workspaceFolder{} specifies the current folder where the file hr_time.c (used for timing). The -l is for linking files and links SDL2, SDL2_image and SDL2_mixer.  The last -lm links math(s) code; technically the -l{name} flag tells the linker to link against lib{name}. So -lm links against libm, the c math library.