Skip to content

Commit

Permalink
Merge pull request #15 from charcole/version4
Browse files Browse the repository at this point in the history
PSX/PS2 active cable firmware and Sega Master System fixes
  • Loading branch information
charcole authored Aug 4, 2018
2 parents 38a6bc3 + 67a8b36 commit e6b637b
Show file tree
Hide file tree
Showing 5 changed files with 1,036 additions and 724 deletions.
155 changes: 155 additions & 0 deletions Firmware/ActiveCables/PSXGun.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
// Need pullup on RX. Goes to any digital IO of LightGunVerter
// Everything else goes to PSX and shouldn't need pull ups/downs

#define IN_CMD MOSI
#define OUT_DATA MISO
#define OUT_ACK 7
#define IN_ATT SS
#define IN_CLK SCK
#define OUT_LED 2

#define GUNCON 0
#define CONTROLLER_DATA_SIZE 8 // From LightGunVerter

#include <SPI.h>

#if GUNCON
#define DATA_SIZE 8 // From PSX
uint8_t ReadMask[DATA_SIZE] = { 0xFF, 0xFF, 0, 0, 0, 0, 0, 0 };
uint8_t ReadExpect[DATA_SIZE] = { 0x01, 0x42, 0, 0, 0, 0, 0, 0 };
uint8_t Reply[DATA_SIZE] = { 0x63, 0x5A, 0xFF, 0xFF, 0x01, 0x00, 0x05, 0x00 };
#else
#define DATA_SIZE 4 // From PSX
uint8_t ReadMask[DATA_SIZE] = { 0xFF, 0xFF, 0, 0 };
uint8_t ReadExpect[DATA_SIZE] = { 0x01, 0x42, 0, 0 };
uint8_t Reply[DATA_SIZE] = { 0x31, 0x5A, 0xFF, 0xFF };
#endif

uint8_t ControllerReadIndex = 0;
uint8_t ControllerData[CONTROLLER_DATA_SIZE];
uint8_t DataIndex = 0;
bool bDataGood = true;

#define ReadAttention() (PINB&(1<<2))
#define WriteAckLow() (DDRD|=(1<<7))
#define WriteAckHigh() (DDRD&=~(1<<7))
#define WriteLEDLow() (PORTD&=~(1<<2))
#define WriteLEDHigh() (PORTD|=(1<<2))
#define DelayMicro() asm("NOP\nNOP\nNOP\nNOP\nNOP\nNOP\nNOP\nNOP\n")

inline int ReadCommand()
{
return digitalRead(IN_CMD);
}

void setup()
{
// LED for debugging
pinMode(OUT_LED, OUTPUT);
digitalWrite(OUT_LED, LOW);

// Ack (open collector)
pinMode(OUT_ACK, INPUT);
digitalWrite(OUT_ACK, 0);

// Set up SPI
pinMode(MISO, OUTPUT);
SPCR |= bit (SPE)|bit(DORD)|bit(CPOL)|bit(CPHA);
SPI.attachInterrupt();

// Set up LightGunVerter serial
Serial.begin(9600);
}

ISR (SPI_STC_vect)
{
uint8_t DataIn = SPDR;

if (DataIndex < DATA_SIZE) // Acknowledge
{
bDataGood &= ((DataIn & ReadMask[DataIndex]) == ReadExpect[DataIndex]);
if (bDataGood)
{
SPDR = Reply[DataIndex];

WriteAckLow();
DelayMicro();
DelayMicro();
DelayMicro();
DelayMicro();
WriteAckHigh();
}
else
{
SPDR = 0xFF;
}
DataIndex++;
}
else
{
SPDR = 0xFF;
}
}

void loop()
{
if (ReadAttention() != 0)
{
if (DataIndex != 0)
{
DataIndex = 0;
bDataGood = true;
}
if (Serial.available())
{
uint8_t SerialData = Serial.read();
if (SerialData == 0x80)
{
if (ControllerReadIndex == CONTROLLER_DATA_SIZE) // Last lot of serial data was good
{
if (ControllerData[0] == 0x80 && ControllerData[1] == 0x00) // Player 1 data
{
uint16_t Buttons = 0xFFFF;
if (ControllerData[7] & (1<<0)) // Left
Buttons &= ~(1<<3);
if (ControllerData[7] & (1<<1)) // Right
Buttons &= ~(1<<14);
#if GUNCON
if (ControllerData[6] & (1<<3)) // B
Buttons &= ~(1<<13);
#else
if (ControllerData[6] & (1<<3)) // B
Buttons &= ~(1<<15);
uint16_t GunX = (ControllerData[2] << 7) + ControllerData[3];
uint16_t GunY = (ControllerData[4] << 7) + ControllerData[5];
if (GunX == 0x3FFF && GunY == 0x3FFF)
{
GunX = 0x01;
GunY = 0x0A;
}
else
{
GunX = 0x4D + (((1023 - GunX) * 3) >> 3);
GunY = 0x20 + ((GunY * 11) >> 5);
}
#endif
Reply[2] = Buttons & 0xFF;
Reply[3] = Buttons >> 8;
#if GUNCON
Reply[4] = GunX & 0xFF;
Reply[5] = GunX >> 8;
Reply[6] = GunY & 0xFF;
Reply[7] = GunY >> 8;
#endif
}
}
ControllerReadIndex = 0;
}
if (ControllerReadIndex < CONTROLLER_DATA_SIZE)
{
ControllerData[ControllerReadIndex] = SerialData;
}
ControllerReadIndex++;
}
}
}
16 changes: 10 additions & 6 deletions Firmware/main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ class PlayerInput
ReticuleXPosition[PlayerIdx] = TIMING_BACK_PORCH + (LineDuration*(int)Spot.X) / 1024;
ReticuleStartLineNum[PlayerIdx] = TIMING_BLANKED_LINES + (VisibleLines*(int)Spot.Y) / 1024;
SpotX = (uint16_t)Spot.X;
SpotY = (uint16_t)Spot.Y;
SpotY = (uint16_t)((Spot.Y * 3) / 4);
}
else
{
Expand Down Expand Up @@ -655,10 +655,10 @@ void WiimoteTask(void *pvParameters)
ToTransmit[8 * i + 7] = (Buttons & 0x7F);
}

gpio_matrix_out(OUT_PLAYER1_TRIGGER1_PULLED, U1TXD_OUT_IDX, false, false);
gpio_matrix_out(OUT_PLAYER1_TRIGGER2_PULLED, U1TXD_OUT_IDX, false, false);
gpio_matrix_out(OUT_PLAYER2_TRIGGER1_PULLED, U1TXD_OUT_IDX, false, false);
gpio_matrix_out(OUT_PLAYER2_TRIGGER2_PULLED, U1TXD_OUT_IDX, false, false);
gpio_matrix_out(OUT_PLAYER1_TRIGGER1_PULLED, U1TXD_OUT_IDX, true, false);
gpio_matrix_out(OUT_PLAYER1_TRIGGER2_PULLED, U1TXD_OUT_IDX, true, false);
gpio_matrix_out(OUT_PLAYER2_TRIGGER1_PULLED, U1TXD_OUT_IDX, true, false);
gpio_matrix_out(OUT_PLAYER2_TRIGGER2_PULLED, U1TXD_OUT_IDX, true, false);

uart_tx_chars(UART_NUM_1, (char*)ToTransmit, sizeof(ToTransmit));
}
Expand Down Expand Up @@ -979,7 +979,7 @@ int IRAM_ATTR SetupLine(uint32_t Bank, const int *StartingLine)
{
SourcePlayer = LastActivePlayer;
}
if (CurrentLine == StartingLine[SourcePlayer] + ARRAY_NUM(ReticuleSizeLookup[0])/2)
if (CurrentLine == StartingLine[SourcePlayer])
{
int Channel = RMT_TRIGGER_CHANNEL + Player;
int DelayChannel = RMT_DELAY_TRIGGER_CHANNEL + Player;
Expand All @@ -996,6 +996,10 @@ int IRAM_ATTR SetupLine(uint32_t Bank, const int *StartingLine)
RMTMEM.chan[DelayChannel].data32[1].val = EndTerminator.val;
Active |= (2 << Player);
}
else if (CurrentLine > StartingLine[SourcePlayer] && CurrentLine < StartingLine[SourcePlayer] + ARRAY_NUM(ReticuleSizeLookup[0]))
{
Active |= (2 << Player);
}
}

return Active;
Expand Down
Loading

0 comments on commit e6b637b

Please sign in to comment.