Tag Archives: Raspberry Pi

Raspberry Pi Internet Radio

I am a big fan of internet radio stations but it can be a bit restricting listening to my favourite stations on my laptop or phone. So over the last couple of weeks I have been building my own internet radio. A lot of people have converted old routers into radios but the best example I found was Bob Rathbones amazing Raspberry PI Radio. I had an old Raspberry Pi 2 lying around not doing much so I decided why not give it a try. Bob provides on his website an extremely comprehensive guide that takes you through the process of building an internet radio which if you’re interested you can download here.

At the heart of this radio is Music Player Daemon (MPD) running on Raspian Jessie. MPD is a flexible, powerful, server-side application for playing music. Through plugins and libraries it can play a variety of sound files while being controlled by its network protocol. Bobs manual provides a detailed overview of construction and software. It contains instructions for building the radio using either the HDD44780 LCD directly wired to the Raspberry PI GPIO pins or alternatively using an either an Adafruit RGB-backlit LCD plate or the PiFace Control and Display (CAD) . An I2C backpack is also now supported. It can be constructed using either push buttons or rotary encoders. An optional infra-red remote control can also be used. Along with the construction guidelines Bob also provides software to drive the LCD, read the switch states and interface with the MPD server.

When I started I had a pretty good idea of what I wanted to achieve with this radio. I wanted a 4×20 HDD44780 based LCD display, push buttons for control (rather than rotary encoders) and a pair of 4″ coaxial speakers. I wanted it to sound as good as possible so decided early on to use a Digital to Analogue Converter (DAC) rather than relying on the line level audio output on the Pi. A network connection would be via WiFi rather than a LAN connection. It would also have the ability to play music from an external USB device. Possible even the ability to control it with an old infra-red remote control.

The enclosure was constructed from 9mm MDF sheet. The dimensions of which were based around the two coaxial 4″ speakers and the LCD display. I didn’t want anything too big but I also didn’t want it so cramped inside that everything wasn’t going to fit.

enclosure2.Using Front Panel Designer I drew up a template to aid with the drilling of the holes for the speakers, the switches and the panel cut out for the display. The whole thing was then glued and joined with furniture blocks before being painted.

While in my local Maplin store I managed to bag a pair of 4″ Vible Slick Coaxial speakers from their clearance section for a good price. They fitted the bill perfectly. The speakers are driven via a 2x30W audio power amplifier kit from Velleman. The amplifier has an RMS output of 15W into 4 ohms and is protected against overheating and short circuits. The LCD display is driven directly by the GPIO lines of the Raspberry Pi. As are the switch inputs. inside3aIn order to minimise the wiring somewhat I built a little interface board between the display, the switches and the header on the Raspberry Pi. I added a small potentiometer to the interface board to allow the overall volume to be configured.

Power for the Raspberry Pi is provided by the official mains power supply while the amplifier is powered via a 12V 50VA toroidal transformer. As I have already mentioned I wanted the radio to sound the best it possibly could so I opted to use the HifiBerry DAC+, a little expensive costing nearly as much as the Pi itself but it was definitely worth it. I am no audiophile but when driven hard those 4″ speakers sound great. With the addition of a panel mount USB socket music can also be played from a USB device.

Total spend is probably approaching well over £100, even already having the Raspberry Pi, but I am really pleased with the result. I have now have a fully up-gradable internet radio with around 600 stations configured that I can control remotely and sounds and looks amazing.

Arcade Controller Conversion…Part 2

arcade2With the case now modified to fit the new joystick and buttons I moved onto the interface board. Rather than buying one I decided from the onset that I was going to design my own. Those you buy of the shelf in my opinion are just way overpriced for what you get. The majority of which are keyboard encoders. All I needed after all was a simple joystick to USB converter with support for up to eight buttons. The design I came up with encompasses a Minimus AVR development board I already had lying around. These boards are ideal for USB projects. They feature an Atmel  AT90USB162 micro controller with full speed USB controller which makes implementing USB applications a breeze. For the firmware I opted to use the LUFA (Lightweight USB Framework for AVRs, formerly known as MyUSB). I have used LUFA a lot in recent years because I find it extremely easy to implement as well as being extremely well documented.

arcade_controllerWith the design laid out on strip board I started on the firmware. Rather than starting from scratch I took the joystick class driver example provided with the LUFA and begun modifying it to suit my needs. The example project implements a Human Interface Device (HID) class joystick driver. Since most operating systems support the USB HID classes out of the box there is no need for any third party drivers. Within the project is a call back function used to create the HID report to be transferred to the host. All that was needed was, during the call back function, to read the joystick and button states and add them to the generated report. The main USB call would then take care of transferring this report to the host.

 bool CALLBACK_HID_Device_CreateHIDReport( USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,  
                                           uint8_t* const ReportID,  
                                           const uint8_t ReportType,  
                                           void* ReportData,  
                                           uint16_t* const ReportSize)  
 {  
      /* New joystick report */  
      USB_JoystickReport_Data_t* JoystickReport = (USB_JoystickReport_Data_t*)ReportData;  
      /* Get joystick states */  
      uint8_t JoystickStatus_LCL = ( JOYSTICK_PORT_PIN & JOYSTICK_ALL_MASK ) ^ JOYSTICK_ALL_MASK;  
      /* Get button states */  
      uint8_t ButtonStatus_LCL = ( BUTTONS_PORT_PIN & BUTTONS_ALL_MASK ) ^ BUTTONS_ALL_MASK;  
      /* Check joystick Y axis */  
      if( JoystickStatus_LCL & JOYSTICK_UP_MASK ) JoystickReport->Y = -100;  
      else if( JoystickStatus_LCL & JOYSTICK_DOWN_MASK ) JoystickReport->Y = 100;  
      /* Check joystick X axis */  
      if( JoystickStatus_LCL & JOYSTICK_LEFT_MASK ) JoystickReport->X = -100;  
      else if( JoystickStatus_LCL & JOYSTICK_RIGHT_MASK ) JoystickReport->X = 100;  
      /* Check joystick buttons */  
      if( ButtonStatus_LCL & BUTTONS_BUTTON1_MASK ) JoystickReport->Button |= (1 << 0);  
      if( ButtonStatus_LCL & BUTTONS_BUTTON2_MASK ) JoystickReport->Button |= (1 << 1);  
      if( ButtonStatus_LCL & BUTTONS_BUTTON3_MASK ) JoystickReport->Button |= (1 << 2);  
      if( ButtonStatus_LCL & BUTTONS_BUTTON4_MASK ) JoystickReport->Button |= (1 << 3);  
      if( ButtonStatus_LCL & BUTTONS_BUTTON5_MASK ) JoystickReport->Button |= (1 << 4);  
      if( ButtonStatus_LCL & BUTTONS_BUTTON6_MASK ) JoystickReport->Button |= (1 << 5);  
      if( ButtonStatus_LCL & BUTTONS_BUTTON7_MASK ) JoystickReport->Button |= (1 << 6);  
      if( ButtonStatus_LCL & BUTTONS_BUTTON8_MASK ) JoystickReport->Button |= (1 << 7);  
      /* Set report size */  
      *ReportSize = sizeof(USB_JoystickReport_Data_t);  
      return false;  
 }  

Every USB device must contain an embedded device descriptor which describe to the host information such as what the device is, who makes it, what version of USB it supports etc. This device descriptor contains a vendor ID (a 16-bit number) which is assigned by the USB Implementers Forum to a specific company. Who in turn assign a product ID (again a 16-bit number) to individual products. In the case of the LUFA joystick example the vendor ID and product ID used are 0x03EB and 0x2043 respectively. Refering to the USB ID Repository on the Linux USB home page shows the registered vendor ID as “Atmel Corp.” (no surprise there) and the product ID as “LUFA Joystick Demo Application”. The VID and PID are communicated to the computer when the device is plugged in, along with text strings describing the vendor and product as well as additional descriptors. I choose to modify these vendor and product strings to something more meaningful to me.

output_BGcEfUWith the code compiled and programmed into the AT90USB162 the first test was to check it worked under windows. Once plugged in windows identified the device and installed a suitable driver. Then using the game controllers configuration wizard I was then able to confirm the joystick and buttons were functioning correctly.

Moving on time to start testing on the Raspberry Pi. RetroPie detected the controller and allowed it to be configured for use. This is fine for navigating the RetroPie front end but in order to use it with any of the emulators (apart from MAME who has its own set-up) the controller needs registering for use with RetroArch. So exiting RetroPie and checking available USB devices shows the device has been detected on bus 001 device 005. The vendor ID and product ID clearly shown.

 Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.  
 Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. 
 Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
 Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. 
 Bus 001 Device 004: ID 7392:7811 Edimax Technology Co., Ltd EW-7811Un 802.11n Wireless Adapter [Realtek RTL8188CUS]
 Bus 001 Device 005: ID 03eb:2043 Atmel Corp. LUFA Joystick Demo Application 

Then registering the controller for use with RetroArch using the “Register RetroArch controller” script. You can see the modified manufacturer and product strings read by the script.

  Using joypad: Mikes Modz Arcade Controller  
 Joypads tend to have stale state after opened.  
 Press some buttons and move some axes around to make sure joypad state is completely neutral before proceeding.  
 When done, press Enter ...   
 Configuring binds for player #1 on joypad #0.  
 B button (down)  
      Joybutton pressed: 0  
 Y button (left)  
      Joybutton pressed: 1  
 Select button  
      Joybutton pressed: 2  
 Start button  
      Joybutton pressed: 3  
 Up D-pad  
      Joyaxis moved: Axis 1, Value -32767  
 Down D-pad  
      Joyaxis moved: Axis 1, Value 32767  
 Left D-pad  
      Joyaxis moved: Axis 0, Value -32767  
 Right D-pad  
      Joyaxis moved: Axis 0, Value 32767  
 A button (right)  
      Joybutton pressed: 4  
 X button (top)  
      Joybutton pressed: 5  
 L button (shoulder)  
      Joybutton pressed: 6  
 R button (shoulder)  
      Joybutton pressed: 7  
 L2 button (trigger)  
      Timed out ...  
 R2 button (trigger)  
      Timed out ...  
 L3 button (thumb)  
      Timed out ...  
 R3 button (thumb)  
      Timed out ...  
 Left analog X+ (right)  
      Timed out ...  
 Left analog X- (left)  
      Timed out ...  
 Left analog Y+ (down)  
      Timed out ...  
 Left analog Y- (up)  
      Timed out ...  
 Right analog X+ (right)  
      Timed out ...  
 Right analog X- (left)  
      Timed out ...  
 Right analog Y+ (down)  
      Timed out ...  
 Right analog Y- (up)  
      Timed out ...  
 Writing autoconfig profile to: /opt/retropie/emulators/retroarch/configs/tempconfig.cfg.  
 input_player1_joypad_index = "0"  
 input_player1_b_btn = "0"  
 input_player1_y_btn = "1"  
 input_player1_select_btn = "2"  
 input_player1_start_btn = "3"  
 input_player1_up_axis = "-1"  
 input_player1_down_axis = "+1"  
 input_player1_left_axis = "-0"  
 input_player1_right_axis = "+0"  
 input_player1_a_btn = "4"  
 input_player1_x_btn = "5"  
 input_player1_l_btn = "6"  
 input_player1_r_btn = "7"  
 = = = = = = = = = = = = = = = = = = = = =  
 Configuring RetroArch-AutoConfigs  
 = = = = = = = = = = = = = = = = = = = = =  
 Remapping controller hotkeys  
 Processing /opt/retropie/emulators/retroarch/configs/2Axes11KeysGamePad.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/ControlBlockArcadeGamepad.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/ControlBlockSNESGamepad.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/DragonRise_Inc.___Generic___USB__Joystick__.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/Generic_X-Box_pad.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/GreenAsia_Inc.____USB_Joystick_____.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/HuiJiaSNEStoUSBConverter.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/JessTechColourRumblePad.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/LogitechGamepadF710.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/LogitechLogitechCordlessRumblePad2.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/Logitech_Logitech_Dual_Action.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/Logitech_Logitech_RumblePad_2_USB.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/Microsoft_Sidewinder_Dual_Strike_USB_version_1.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/Microsoft_X-Box_360_pad.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/MikesModzArcadeController.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/MY-POWER_CO__LTD__2In1_USB_Joystick.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/PS3ControllerBT.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/PS3Controller.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/PS3ControllerUSB.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/RockCandyGamepadforPS3.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/Saitek_P880.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/SNES-to-GamepadDevice.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/Sony_PLAYSTATION(R)3_Controller.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/Thrustmaster_Dual_Trigger_3-in-1.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/THRUSTMASTER_FireStorm_Dual_Analog_2.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/Thrustmaster_T_Mini_Wireless.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/USB_2-axis_8-button_gamepad.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/USB_Gamepad.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/USBGamepad.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/Xbox_360_Wireless_Receiver.cfg  
 Processing /opt/retropie/emulators/retroarch/configs/XboxGamepad(userspacedriver).cfg  

With the controller now registered it was time to start playing. First up Teenage Mutant Ninja Turtles on the SNES which worked great. The Seimitsu joystick has a great feel with lovely movement not too stiff but not too loose either. The buttons respond perfectly with minimal effort, if anything they are little bit to sensitive but that’s fine.

Arcade Controller Conversion…Part 1

I love playing retro arcade games and most recently I have taken to playing these classic games on my Raspberry Pi 2 using the RetroPie. For those who aren’t aware the RetroPie project is a collection of works that all have the overall goal to turn the Raspberry Pi into a dedicated retro-gaming console. Up until now I have been using a couple of cheap USB NES controllers. These controllers are great but nothing compares to the feel of an authentic arcade controller. So I set about building my own controller that could be plugged directly into my Raspberry Pi.

arcade4The first issue would be the enclosure. Do I build something? Or do I buy a flat packed kit from eBay? Neither option was going to be cheap. Then I stumbled on someone selling a second hand PlayStation arcade controller on eBay which at the time was listed at 99p plus postage. I figured that has got to be worth a punt. Even if I can only salvage the case and possibly a few other parts then so be it. So I placed a bid and ended up winning it for just over a pound. Result! I wasn’t expecting a lot but was pleasantly surprised when it arrived. The build quality was a lot better than I had expected. It had obviously seen a fair bit of use and the joystick micro switches were worn out. But still I wasn’t disappointed as the case was in great condition.

arcade5I begun disassembling it as soon as it arrived. I removed the bottom plate, the cable, the joystick and the eight push buttons. I had no plans to use the interface board so I de-soldered all of the connections and left the PCB in situ. Next I measured the holes for the push buttons which turned out to be 30mm which was good news since this a standard size for arcade buttons. Selecting a suitable joystick proved to be more troublesome. There isn’t a lot of clearance for the joystick once mounted so I needed to find one with the lowest possible profile.

In the end I went for a Seimitsu LS-58-01and Seimitsu PS-15 buttons. The LS-58 a great quality small form factor joystick. Not to stiff and with an adequate throw distance for my liking. The micro switches are soldered directly into a PCB. This worked out perfect as I later went on to use the PCB to mount it to the original mounting posts. Being 30mm the PS-15’s fitted perfectly with no modifications required. The joystick however required a few modifications. In order to drill the mounting holes in the PCB I first had to remove the common connections for each micro switch. Rather than completely removing the micro switches I simply cut the tabs and de-soldered. Then after drilling the holes I used Kynar wire to re-connect them.

arcade1The next problem was getting the joystick to fit flush with the case. Because of the way the case had been moulded I needed to remove some of the plastic surrounding the stick. Thankfully this didn’t comprise the rigidity of the joystick. The end result wasn’t pretty but at least it now fitted flush with the case. I finished off by connecting all of the switches to my new interface board which I will move onto in the next post.