I didn't ever get this working full stop, as I said I only played with it for about 4 hours one evening on the Naomi and then lost interest. There isn't any reason that this shouldn't work for any game you can emulate on a computer however!
Yeah I agree, you should just be able to use a transistor or something to swap to full white. The Arduino wouldn't actually have to do anything anyway R.E outputting a white screen, it doesn't need to count pixels if it's drawing all the pixels white, and it's not producing it's own SYNC signals, just reading the ones from the machine supplying the video!
I'm unforunately not going to be able to dedicate any time to this at the moment due to work and life, but I'm happy to answer any questions you have RE the arduino side. The code should be very simple, and as long as you understand the hardware and how CRT lights gun works (which it sounds like you do) then I think you'd easily be able to learn how to code up something small like this!
Sorry that I can't commit to working on it with you as I would like to, but please keep me updated if you do decide to pursue the project - I'm sure lots of people would be interested!
Hey, thanks for the fast reply! And I really appreciate the offer, I'm sure I'll have some questions for you, but I'll do my best to not bother you and do necessary research on my own. I also know some programmers that would be interested in helping I think.
Happy to pick this project up where it is, and see where I can take it. I'd be really happy to get this working on a basic MAME setup. I've used an Arduino Uno before as a USB controller so Im familiar, if this is the same thing. Haven't used it as a mouse before, but I doubt it's much different. It was a bit annoying though, that the library I used in the past required an official Uno since CH340 was not supported.
Also, I think using an ESP32 will solve the processing issue. It can work with the same code and I've had a lot of success with it in designs. Also, according to the positional code notes, it would give much higher precision (0-4096 instead of 0-255)
Current questions and goals:
1. What is the benefit / use of the library atomic.h right now?
2. Is gunPowerPin just the 5V power for the gun / optic sensor? Assuming gunPin is the optical sensor line (seems that way).
( digitalWrite(gunPin, HIGH); // enable pullup resistor - this is strange, should be just a hardware pull up I think, no?)
I will also have to do some research on the difference between the the 2 and 3 pin optic sensors (EDIT: the extra pin is 5v power:
http://forum.arcadecontrols.com/index.php?topic=114156.0)
3. For MAME games that already flash the screen white, will this already work "out of the box" so to speak? Sounds like it might, assuming there's a faster processor.
4. It would be wonderful to have just a C Sync support, so that I won't have to use a LM1883 if the video card does not output split sync. Shouldn't be too hard to edit the code for that or do it in hardware if absolutely necessary.
5. Once I get the library and drivers installed and everything working on a MAME setup for CRT-based gun games, I will work on the 24V solenoid support. After that, I'll focus on the MUX switching white circuit.
That's the game plan so far, let me know if there's anything I'm missing! And thanks again
I should point out that others have already got this working with light gun games in mame with the available drivers.
Care to share how you managed this? All the links and info I can find are abandoned and dead.
and here's the code for easy access:
#include <util/atomic.h>
const byte ledPin = 13;
const byte hsyncPin = 3;
const byte vsyncPin = 2;
const byte gunPin = 8;
const byte gunPowerPin = 7;
volatile int line = 0;
volatile int bob = 0;
unsigned long time1 = 0.0;
unsigned long time2 = 0.0;
unsigned long time1m = 0.0;
unsigned long time2m = 0.0;
volatile unsigned int blob = 0;
volatile unsigned int blob_overflows = 0;
volatile unsigned int gun_blob = 0;
volatile unsigned int gun_blob_overflows = 0;
volatile unsigned int gun_lines = 0;
volatile unsigned int overflows = 0;
volatile unsigned int av_blob = blob;
void setup() {
TCCR1A = 0;
TCCR1B = 0;
TCCR1C = 0;
TIMSK1 = _BV(TOIE1); // Enable Interrupt
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
pinMode(hsyncPin, INPUT_PULLUP);
pinMode(vsyncPin, INPUT_PULLUP);
pinMode(gunPowerPin, OUTPUT);
digitalWrite(gunPowerPin, HIGH);
pinMode(gunPin, INPUT); // set Pin as Input (default)
digitalWrite(gunPin, HIGH); // enable pullup resistor
pciSetup(gunPin);
attachInterrupt(digitalPinToInterrupt(hsyncPin), hsync, FALLING);
attachInterrupt(digitalPinToInterrupt(vsyncPin), vsync, RISING);
}
void loop() {
unsigned int local_gun_lines;
unsigned int local_lines = 0;
unsigned long local_blob_overflows;
unsigned long local_gun_blob_overflows;
unsigned long local_gun_blob;
unsigned long local_blob;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
local_lines = bob;
local_gun_lines = gun_lines;
local_blob_overflows = blob_overflows;
local_gun_blob_overflows = gun_blob_overflows;
local_gun_blob = gun_blob;
local_blob = blob;
}
av_blob = (float) ((float) 0.8 * float(av_blob)) + ((float) 0.2 * (float) local_blob);
unsigned long ticks = ((((unsigned long) local_blob_overflows) << 16) | (unsigned long) av_blob);
unsigned long gun_ticks = ((((unsigned long) local_gun_blob_overflows) << 16) | (unsigned long) local_gun_blob);
unsigned long x = 255.00 - ((float) ((float) gun_ticks / (float) ticks) * (float) 255.00);
unsigned long y = (float) ((float) gun_lines / (float) local_lines) * (float) 255.00;
Serial.print(gun_ticks);
Serial.print("/");
Serial.print(ticks);
Serial.print(", ");
Serial.print(gun_lines);
Serial.print("/");
Serial.print(local_lines);
Serial.print(" - ");
Serial.print(x);
Serial.print(",");
Serial.println(y);
delay(50);
}
void vsync() {
gun_blob = TCNT1;
gun_blob_overflows = overflows;
gun_lines = line;
}
void hsync() {
TCCR1B = 0;
blob = TCNT1;
blob_overflows = overflows;
TCNT1 = 0;
overflows = 0;
line++;
TCCR1B = 1;
}
ISR(TIM1_OVF_vect)
{
overflows++;
}//end ISR
ISR (PCINT0_vect) // handle pin change interrupt for D8 to D13 here
{
if(digitalRead(gunPin) == 1) {
time2m = time1m;
time1m = micros();
bob = line;
line = 0;
}
}
void pciSetup(byte pin)
{
*digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin)); // enable pin
PCIFR |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
PCICR |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group
}