Jump to content
IGNORED

Generic Tech Device Section For HomeBrew Pinball.


Recommended Posts

Yep, some excellent ideas there. A Rpi3 is fine, I can buy them 20 minutes away from me anyway at Element 14's warehouse.

 

The audio decoder is part of that original project I linked to https://pipresents.wordpress.com/2015/05/03/pi-presents-version-1-3-gapless-is-released/comment-page-1/#comment-351

 

These are it's features out of the box...https://pipresents.wordpress.com/features/

 

It seems to do all the requirements but I think needs a tidy up to make it simpler for the HomeBrew user.

 

It uses omxplayer as it's decoder.

 

What is required to get the most from this project is how the content is played or triggered and maybe an easier file system the user can install his clips and the control over them like stereo, mono etc.

Link to comment
Share on other sites

  • Replies 114
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Posted Images

And i think the files should be numbered: 01.wav, 02.wav, 03.wav etc. This way any file replacement can be simple and restricted to filenames that are appropriate and not requiring the coding of a whole lot of string checks.

 

I would recommend against that: it's an ergonomic design fail: for the user, there is no way to correlate a particular sound with a file name without consulting some sort of lookup table. If you really want numbers, allow anything that looks like this:

 

15.wav

15-SuperJackpot.wav

03.click.wav

 

And so on… That way, you just mask off the first two bytes, which is dead-simple, and the user still can give meaningful names to sound files and easily identify them.

 

Michi.

Link to comment
Share on other sites

I would recommend against that: it's an ergonomic design fail: for the user, there is no way to correlate a particular sound with a file name without consulting some sort of lookup table.

 

Michi.

 

ha, good point and yes thats just how id do it. im not very good with naming sound files so i always end up with a bunch of blaster01, blaster02 etc. you could maybe name them after events on the playfield too. but a numeral prefix and then some string is good as well.

Link to comment
Share on other sites

Just remember, the project is designed as a generic sound/ video player for any machine so what is "super jackpot" on one machine may not be super jackpot on another person's machine.

 

If say the second sound is "specials" on every game that would be fine but I think the second sound changes depending on the game program.

 

I don't know the sound setup well enough to know either way to tell you the truth.

 

Also, another issue is going to be finding the combination the game board sends to the sound board with it's 4 inputs combos that actually trigger each sound/video and I figure that will also depend on the game's program,

 

The Rpi player could incorporate a test button that plays each sound/video in numerical order, one after the other, to aid the user in working out where to allocate each file.

 

Maybe having the machine being able to display what inputs are triggered, say an LED on each of the 4 input lines so the user can for example, put the machine into having specials lit then score the specials and watch which of the 4 input lines LEDs light.

 

With a cheat sheet he can then work out what numbered file is actually triggered when that particular combo of LEDs is triggered because this is one constant that will be the same on every machine.

 

Just a couple of thoughts.

Link to comment
Share on other sites

Maybe I didn't express this as clearly as I should have (my apologies, if so).

 

I'm not suggesting a fixed naming scheme where "01-SuperJackot.wav" is somehow hard-coded. What I'm suggesting is that absolutely any file name would be acceptable, as long as it starts with two digits. So, if that's what I like, I can name the files "01.wav", "02.wav", and so on. Or I can name them "01my_favourite_sound.wav", "02-My-Second-most-favourite-sound.wav", and so on.

 

The idea is to create a naming scheme that suits both the software and the user.

 

Michi.

Link to comment
Share on other sites

Maybe I didn't express this as clearly as I should have (my apologies, if so).

 

I'm not suggesting a fixed naming scheme where "01-SuperJackot.wav" is somehow hard-coded. What I'm suggesting is that absolutely any file name would be acceptable, as long as it starts with two digits. So, if that's what I like, I can name the files "01.wav", "02.wav", and so on. Or I can name them "01my_favourite_sound.wav", "02-My-Second-most-favourite-sound.wav", and so on.

 

The idea is to create a naming scheme that suits both the software and the user.

 

Michi.

 

No, now that you explained it like that, it was me that misunderstood you Michi.

 

This project must be easy for all to use, that is the idea. We want it to be an ideal solution for all users that suit a multitude of applications.

 

Just one question Michi, using the naming scheme you recommend as in...01my_favourite_sound.wav.

 

How many letters/ spacers can be used in the address as in if it was in FAT it would be 42 total?.

 

@Michi

Link to comment
Share on other sites

aight, i think i have all the parts (jaycar is just up the road if not) and i can begin a fresh install on the rPi - using debian wheezy as i want to stick to that kernel, plus my other pi is running this so i can always test back compat with an older pi. will start as low level as possible at first, so no gui, just console. will also use ssh etc for connection, and may also use x forwarding but not sure yet. and then start with wiringPi cos this library looked pretty nice. initial coding will be for the mcp23008 but it will probably be better to use the mcp23017.

more later.

Link to comment
Share on other sites

this post is just for the record of setting up the dev environment. not all the installs will be needed or used and they are probably not in a sensible order but it took place as i read stuff and compiled test programs.

it turns out that i cant use the older kernel and wheezy distro on the pi3...

 

- latest version of raspbian-stretch-lite(2017-09-07)

 

- install PIXEL ui version for ease (aye)

 

- sudo apt-get install git

 

// from proper

- git clone wiringPi

 

- sudo apt-get install i2c-tools

 

-raspi-config > interface > advanced > enable i2c

 

// wav edits etc

- sudo apt-get install audacity

 

- check audio is going out analog (4pole) with:

amixer cset numid=3 1

 

// libAV for mp3 and other codecs, lame...

- sudo apt-get install libavcodec-dev

- sudo apt-get install libavformat-dev

 

// prob not use, but here anyway

- sudo apt-get install omxplayer

 

// broadcom api

$ /opt/vc/src/hello_pi $ make -C libs/ilclient

 

// redundant avconv from wav to pcm?

- sudo apt-get install libav-tools

 

// not needed ?

- sudo apt-get install libasound2-dev

 

so far have i2c polling the mcp23008 chip and pcm, wav playback working

Edited by kapGo
reason for distro
Link to comment
Share on other sites

Cool, looks like you have a bit of an idea what you are doing.;)

 

OmxPlayer is one of many players for the Rpi. I am using MPlayer and DVDPlayer quite well at the moment in an Openlec media player.

 

They are old players but you can throw a lot of different video types at them and they work quite well.

 

I'm on using it for basic media player operations but it handles a video playlist of about 100 music videos.

 

There is about a 1 second black screen between videos and it isn't having files cut short when a new command is received like this project has to handle but for what I want it to do as a media player, it seems to be doing quite well.

 

The biggest problem with Rpis is SD card corruption, Rpi being turned off while it is writing to the SD card.

 

The solution to this is only have the SD card working like a bios and have the main Rpi bootup software on a USB thumbstick and having it doing all the read/write functions.

 

It may seem a waste of the SD card but it does rid the Rpi of this major problem.

 

An alternative is to simply keep the Rpi powered all the time or put in a safe shutdown feature in the program.

 

Even though I use a thumbstick for the bootup process, I still use a safe shutdown along with a processor reset switch if or when the processor locks up.

 

A processor reset is simply done by grounding the processor chip's reset pin via an external switch.

 

Put in a 1k resistor in series and if that isn't grounding the reset pin correctly, start dropping down the resistance till it functions correctly.

 

The Rpi 2 handles no resistor in this circuit because it has a resistor in the high hold line to the pin but I'm not sure on the Rpi 3. As I don't have one I haven't looked at the chip's diagram yet.

 

It helps when the processor locks up and initiates a full reset of the system without needing to turn the Rpi off and back on.;)

 

Being an Rpi 3 you are using, you could incorporate WiFi and BluTooth. They are both built into the Rpi3 board.

 

Maybe the WiFi for importing different files and BluTooth for volume. Not real necessary either of them but it would possibly make a better product.

 

Just a couple of thoughts.

 

Nice work by the way. All good things take time and excellent things take longer.;)

Link to comment
Share on other sites

ah, some good info there, i hadnt really thought about the shutdown cos i always let the device(s) finish writing (led activity) before removing power source. cant really expect that in a pinball machine huh.

 

i started looking at some of the players and one issue that will come up is memory and buffer use. most of these players are expecting movies and or music files (several mins to hours) and not multiple, repetitive triggering of many different short sound effects over prolonged periods of time. this is why i stated at the lowest level and am trying to get the broadcom api stuff happening to see what sort of performance is possible. i also think that not having a gui running on the production device(s) will prove beneficial (and easier) in avoiding many of the pitfalls real-time audio can suffer.

 

 

heres an article from a proper linux audio person (who lives in melbourne):

http://www.rossbencina.com/code/real-time-audio-programming-101-time-waits-for-nothing

 

and yes, i would like latency of ~8 ms :)

Link to comment
Share on other sites

ran a bit of a test running wiringPi, it has a built in interrupt routine. this routine only works on the gpio pins (not the i2c) and calls a function on pin state change. this all seemed pretty good but it turns out that this routine only can handle two rapid events at most, before dropping any other subsequent events. not good for multiple pin triggers.

 

so i think it will be best to avoid the gpio pins and stick to the i2c and get a nice byte that the rPi only has to match to a sound file and not do any parsing.

Link to comment
Share on other sites

The biggest problem with Rpis is SD card corruption, Rpi being turned off while it is writing to the SD card.

 

This is why I use a custom board with a regular micro and firmware instead of a pi for any commercial projects. Not having an OS means you do have to deal with every detail yourself of course.

Edited by David_AVD
Link to comment
Share on other sites

a bit more time on this tonight and i been looking at the mcp23008 chip which pretty much has all the off-rPi components needed: it has an interrupt pin and a pin state capture on interrupt register:

 


// direction: bits 7-0 : GP7-GP0
#define GPINTEN_ADDR    0x02    // interrupt on change - 1:enable, 0:disable
#define DEFVAL_ADDR      0x03    // default compare value - set bits to compare, enabled via GPINTEN & INTCON
#define INTCON_ADDR     0x04    // interrupt control - 1: compare to DEFVAL, 0: compare to previous pin value

#define INTF_ADDR         0x07    // interrupt flag - can update before clearing - 1:caused interrupt, 0: nothing
#define INTCAP_ADDR     0x08    // interrupt capture - remains unchanged until read or cleared - 1: high, 0:low

 

this should mean its feasible to place this chip (and circuits etc) between the system 4-7 cpu board sound select connector and the rPi. Hopefully using one of the GPIO pins on the rPi to connect to the INT pin on the mcp allows it to be read in a timely manner to then perform a register read on the INTCAP to get the bits to derive the sound triggered.

 

Once that is working then the next stage is to figure on the sound file playback. i have got a lite alsa library that hopefully i can locate the header files for, maybe in a alsa-dev or something.

Link to comment
Share on other sites

  • 2 weeks later...

long time has passed - well school holidays are a thing, and the dev rPi got turned into a kodi player for a bit. :)

 

anyway, heres the testing code as it stands so far. its at the proof-of-concept stage so its not pretty, nor is it optimised, nor proper in any way and neither does it play any audio yet. firstly get the IO stuff playing nicely and to be on par with the behaviours expected by a Williams 4-7 and then progress from there. this test code is mainly to get a reasonably useful program for running wiringPi and seeing how that behaves.

 

there are notes and rems everywhere and various vars and functions have names that make sense at this stage. it will stay this messy for a bit cos time on this is infrequent due to many reasons. Of note is that the INTCAP register is presently not clearing when read as per specs. so maybe i need to add in a straight GPIO pin read/flush, which id rather not do as im trying to keep IO access to a minimum - but this can be looked at later. the code should have all the dependencies obvious via the includes but other stuff needed can be found in the post above where i list the various libraries that were installed at setup. also there are several different methods that the wiringPi gives access to that could be utilised but the direct write/read to register seems appropriate at this stage.

 

/*
*	first test of wiringPi in c
*	-uses mcp23008
*	-play wav files at trigger
* 
* 	-dev,build,compile,exe in Geany
*	
* 	$ gcc -o pinSound-test pinSound-test.c -lwiringPi
*/

#include <stdio.h>
#include <stdlib.h>
#include <wiringPi.h>
#include <mcp23008.h>
#include <wiringPiI2C.h>

// controller cards numbered sequentially,
// dev card/breadboard is last in current series (20-23 are used)
#define TEST_ADDR		    0x24
#define INT_PIN         0  		// rPi GPIO 0, header pin 11

// mcp23008 addresses
// direction: bits 7-0 : GP7-GP0
// intcon compare to defval
#define IODIR_ADDR      0x00    // IO direction - 1:input, 0:output
#define IPOL_ADDR       0x01    // input polarity - 1:opposite, 0:same

#define GPINTEN_ADDR    0x02    // interrupt on change - 1:enable, 0:disable
#define DEFVAL_ADDR     0x03    // default compare value - set bits to compare, enabled via GPINTEN & INTCON
#define INTCON_ADDR     0x04    // interrupt control - 1: compare to DEFVAL, 0: compare to previous value

#define IOCON_ADDR		  0x05	// set INT pin active and polarity - 
#define GPPU_ADDR		    0x06	// pull up resistor (100k) - 1:enable, 0: disable

#define INTF_ADDR       0x07    // interrupt flag - can update before clearing - 1:caused interrupt, 0: nothing
#define INTCAP_ADDR     0x08    // interrupt capture - remains unchanged until read or cleared - 1: high, 0:low

#define GPIO_ADDR       0x09    // 1:high, 0:low

//int wiringPiI2CSetup(int mcp_addr);
//int wiringPiI2CWriteReg8(int fd, int reg, int data);
//int wiringPiI2CReadReg8(int fd, int reg);

int write_data = 0;
int read_data = 0;
int device_handle;

/***************************************************************
*
*      UTILITIES
*
***************************************************************/
void pin_trig_sound(void) { 
// don't...
printf("Pin trigger test sound.\n"); 
system("tinyplay AUDIO/mess/test01.s16"); 
}

void write_error(int write_result) {
printf("write_result: %d", write_result);
// more info
}

/***************************************************************
*
*      TEST
*
***************************************************************/

void I2C_read_test() {
// stuffs
read_data = wiringPiI2CReadReg8(device_handle, IODIR_ADDR);
printf("read IODIR: %X\n", read_data);

read_data = wiringPiI2CReadReg8(device_handle, GPINTEN_ADDR);
printf("read GPINTERN: %X\n", read_data);

read_data = wiringPiI2CReadReg8(device_handle, DEFVAL_ADDR);
printf("read DEFVAL: %X\n", read_data);

read_data = wiringPiI2CReadReg8(device_handle, INTCON_ADDR);
printf("read INTCON: %X\n", read_data);

read_data = wiringPiI2CReadReg8(device_handle, GPPU_ADDR);
printf("read GPPU: %X\n", read_data);

read_data = wiringPiI2CReadReg8(device_handle, IOCON_ADDR);
printf("read IOCON: %X\n", read_data);
 
}

void int_pin_test() {
//
if (digitalRead(INT_PIN)) {
	// pin high == OFF for sys4-7
	printf("int_pin is HIGH, waiting.\n");
}
else {
	printf("int_pin is LOW, trigger.\n");
}
// read INT at MCP pin

}

/***************************************************************
*
*      INIT
*
***************************************************************/
void I2C_init() {
printf("I2C_init start...\n");
// uses wiringPi gpio pin numbering scheme
wiringPiSetup();	
device_handle = wiringPiI2CSetup(TEST_ADDR);

if (device_handle == -1) {
	write_error(device_handle);
} 
else {
	printf("device_handle: %d\n", device_handle);
}
}

void int_pin_init() {
printf("rPi gpio interrupt pin setup...\n");
pinMode(INT_PIN, INPUT);
// logic 0 is interrupt active 
pullUpDnControl(INT_PIN, PUD_UP);

}

void MCP_init() {
printf("MCP_init start...\n");
// direction: bits 7-0 : GP7-GP0
int write_result = 0; // errno == -1

// set INT pin to driver active-low
// 7,6=unused, 5=SEQOP, 4=DISSLW, 3=HAEN, 2=ODR, 1=INTPOL, 0=unused
write_data = 0x38; // 0x38=0011 1000, 0x3A=0011 1010
write_result = wiringPiI2CWriteReg8(device_handle, IOCON_ADDR, write_data);
if (write_result == -1) write_error(write_result);

write_data = 0xFF; // set to input: 1111 1111 
write_result = wiringPiI2CWriteReg8(device_handle, IODIR_ADDR, write_data);
if (write_result == -1) write_error(write_result);

write_data = 0x00; // set input polarity: 0000 0000 
write_result = wiringPiI2CWriteReg8(device_handle, IPOL_ADDR, write_data);
if (write_result == -1) write_error(write_result);

write_data = 0xFF; // set interrupt enable 0-7: 1111 1111
write_result = wiringPiI2CWriteReg8(device_handle, GPINTEN_ADDR, write_data);
if (write_result == -1) write_error(write_result);	
//write_data = 0xFF; // set default compare value 0-7: 1111 1111
// compare to logic 1 - opposite cause interrupt 
write_result = wiringPiI2CWriteReg8(device_handle, DEFVAL_ADDR, write_data);
if (write_result == -1) write_error(write_result);
//write_data = 0xFF; // set interrupt control to defval 0-7: 1111 1111
write_result = wiringPiI2CWriteReg8(device_handle, INTCON_ADDR, write_data);
if (write_result == -1) write_error(write_result);	
//write_data = 0xFF; // set pull-up on inputs: 1111 1111 
write_result = wiringPiI2CWriteReg8(device_handle, GPPU_ADDR, write_data);
if (write_result == -1) write_error(write_result);

	
// proper status report
}

/***************************************************************
*
*      READ
*
***************************************************************/
void I2C_read_intcap() {
// reading INTCAP clears the register
// any ints generated between first int and read/clear is disregarded
read_data = wiringPiI2CReadReg8(device_handle, INTCAP_ADDR);
printf("read interrupt: %X\n", read_data);
// parse hex to sound file play
}

void read_int_pin() {
//
// really
if (digitalRead(INT_PIN)) printf("int_pin is 1, WAIT.\n");
else printf("int_pin is 0, ACTIVE.\n");
}

/***************************************************************
*
*      MAIN
*
***************************************************************/

int main(void) {

I2C_init();

MCP_init();

int_pin_init(); 

printf("INIT finish, int_pin_test...\n");

int_pin_test();

I2C_read_test();

printf("Finished test, running read loop :: CTRL-C to exit.\n");	

for (;;) {
	// every read clears the int
	read_int_pin();
	I2C_read_intcap();
	//printf("wait...\n");
	delay(1000);
}	

/*
while(1) {
	// loop eternal
	// wait for exit
}
*/	
return 0;
}


Link to comment
Share on other sites

I've used one of these on a cocktail machine and have just ordered two more for pinball projects. They have a decent sound quality and volume and an extra output for a sub woofer.

Ebay item number 182682017110

Cheers Trev 280e3fb86d613477212440485518cf22.jpg6b58f8b91e2305d31b478bdc48378c82.jpg

 

Sent from my SM-G930F using Tapatalk

Link to comment
Share on other sites

I found this circuit for driving large seven segment leds from an Arduino.

34ae08c0581b2d4c5c233114ec82f67f.jpg

 

Sent from my SM-G930F using Tapatalk

Please note if using this circuit pin 10 of IC2 goes to V Led not Gnd.

Cheers Trev

 

Sent from my SM-G930F using Tapatalk

Link to comment
Share on other sites

the interrupt register clear is fixed now by reading the values held in INTF_ADDR and then performing a read of the INTCAP_ADDR to clear them. i have also added a "debounce" line that is just a blocking delay() which will make people shudder. but this will suffice for the moment as my triggering consists of me tapping a wiring against a breadboard pin. i think this is an ok stage to start looking at how to get wav files playing no the rPi and the state of rapid multiple triggers.
Link to comment
Share on other sites

i got the mcp23008 -> interrupt -> rPI reads to load a numerically associated audio file and play it. this is without its own thread or interruptible playback. the code is messy but its currently using alsa and libsndfile to do the work here, also there are some notes about using the userland libraries but i havent gotten around to linking them yet. But these will have the low level bcm_host, khronos and omx_core stuff which may or may not be useful, it depends on performance.

 

file handling is very messy at the moment but i think loading all the audio files into memory as opposed to constant IO reads is preferable. also with the audio files i have edited a folder down to 16 bit files but i think the libsndfile can deal with the whatever format automatically, it just requires a proper SF_INFO to set the parameters for playback. whether this file conversion hits performance is another matter.

 

this is a pretty useful library that ive only just started looking into:

http://www.mega-nerd.com/libsndfile/

 

i cant remember cos it was late last night but i think the rPi has it in the default repo.

 

another thing is the method to handle the stop/reset triggers. on a lot of the earlier williams 4-7 roms this is at trigger #19 but some of the later ones (Varkon, Cosmic Gunfight, etc) have this moved to other values. also there are modifier triggers and multi-tap triggers that involve an change in frequency (pitch and duration). so maybe some sort of meta_data file that has instructions will need to be included within a specific folder of audio. Also the use of the switch for speech audio or just sounds. the blackout rom for instance has some good sounds in IC12 instead of the speech rom sounds if they are switched off.

 

also i wonder how feasible it would be to get the clock signal from the pinball cpu to drive a pulse on the rPi gpio? this could be a way of clocking the rPi to a useful speed and keeping it ticking along. i know the original sound boards had their own clock and i assume they were in some way relative to the main cpu clock, though not phase locked.

Link to comment
Share on other sites

 

also i wonder how feasible it would be to get the clock signal from the pinball cpu to drive a pulse on the rPi gpio? this could be a way of clocking the rPi to a useful speed and keeping it ticking along. i know the original sound boards had their own clock and i assume they were in some way relative to the main cpu clock, though not phase locked.

 

That should be relatively easy to get but the Rpi processor has it's own clock however you can adjust it's frequency.

 

You may be better phase locking them together, the pinball and the Rpi if you absolutely need them tied.

 

Why exactly do you want them in perfect harmony with each other?. It isn't as if your ear will detect the sound being a mS or two out of sync.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...