Compare commits
2
Commits
master
...
PSX_deprecated
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82ca461580 | ||
|
|
a4f48e1dd2 |
@@ -32,6 +32,8 @@ The keypad code uses the Keypad library by Mark Stanley and Alexander Brevig.
|
||||
|
||||
Switch debouncing is done with Bounce2 library by Thomas O Fredericks.
|
||||
|
||||
PSX Controller code is based on busslave's PSX_RECEIVER.cpp, with PS1 compatibility fixes by [veroxzik](https://github.com/veroxzik)
|
||||
|
||||
# Supported devices and requirements
|
||||
|
||||
This code was designed for Arduino Due. It will compile for Leonardo as well but some features are stripped due to lack of gpio (only 11 buttons and 9 lights, no keypad, lower polling rate).
|
||||
@@ -43,6 +45,18 @@ The keypad code requires the Keypad library by Mark Stanley and Alexander Brevig
|
||||
|
||||
# Features
|
||||
|
||||
## Playstation Controller (Leonardo only, Due coming soon)
|
||||
|
||||
This controller can be used as a playstation controller for Pop'n Music CS versions.
|
||||
|
||||
Note that this requires a couple hardware mods in order to work as we are using two extra pins (SS and ACK, on the RX and TX leds aka PB0 and PD5) which are not readily available on the pre-soldered headers.
|
||||
|
||||
Of course you'll need either a dualshock breakout board or a dualshock extension cable for it to work.
|
||||
|
||||
Refer to the pinout to know how to wire the controller plug to the arduino.
|
||||
|
||||
**Note:** This is PoC code, I'll try to port a more complete dualshock implementation soon and make it Due compatible as well
|
||||
|
||||
## I/O
|
||||
|
||||
This controller has 13 buttons (9 buttons + coin + service + reset + test), 4 dip-switches (only DIP4 is used in cabinets to select between 15 or 31kHz monitor resolution on boot), 8 lights (9 buttons + 5 top neon + 4 side pillar), 2 coin outputs (coin blocker, coin counter).
|
||||
@@ -93,33 +107,13 @@ You can either press button 2 (left yellow button) while holding service to swit
|
||||
|
||||
I included pre-compiled binaries and sources in the "ModeSwitch" folder. Refer to readme.md inside that folder for more details.
|
||||
|
||||
# Pinout (DUE)
|
||||
|
||||
The Arduino DUE has 3.3v logic whereas the Pop'n Music cabinet outputs use 12V.
|
||||
|
||||
Therefore I'm using transistors to do level shifting (the parts I used were three ULN2003APG or TBD62003APG chips).
|
||||
|
||||
You can also buy pre-made level shifters such as this one https://www.tindie.com/products/ddebeer/12-channel-level-shifter-and-buffer/ (you'd need two of them since there are 20 outputs to control for a Pop'n cabinet).
|
||||
|
||||
Refer to ```pinout.png``` to see how it is all wired to a Pop'n Music cabinet.
|
||||
|
||||

|
||||
|
||||
## Pop'n IOShield
|
||||
|
||||
I've also built a custom arduino shield with integrated level-shifting circuitry. This allows you to simply connect a Pop'n Music cabinet through 2 connectors present in your cab (unplug CN7 and CN8 from the power distribution board and plug them on this shield instead, then splice 12V from CN63 connector and feed it to the shield 12V in connector). You can contact me for more information.
|
||||
|
||||

|
||||
|
||||
Demo : https://www.instagram.com/p/CKE9HCQFCYM/
|
||||
|
||||
# Pinout (Leonardo)
|
||||
|
||||
Arduino Leonardo has 5V logic therefore one can directly connect 5V leds to it.
|
||||
|
||||

|
||||

|
||||
|
||||
Arduino Leonardo version is also compatible with Playstation and Playstation 2 (it can be made to be plugged directly to the controller port, please refer to the PSX branch for more information).
|
||||
For ACK (TXLED aka PD5) and SS (RXLED aka PB0) you have to solder new headers or cables directly on the leonardo PCB. For the PSX controller function to work properly you need to short SS to ground (leonardo doesn't work well as SPI slave otherwise, which is why we cannot use the "attention" line from the controller cable unfortunately).
|
||||
|
||||
## Donation
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 415 KiB After Width: | Height: | Size: 687 KiB |
@@ -5,6 +5,21 @@
|
||||
#include <Keyboard.h>
|
||||
#else
|
||||
#include <EEPROM.h>
|
||||
/* PSX DEFINE */
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <util/delay.h>
|
||||
#define SPI_PORT PORTB
|
||||
#define SPI_PINS PINB
|
||||
#define SPI_DDR DDRB
|
||||
#define SPI_PINS PINB
|
||||
#define ACK_PIN 5 //PB1
|
||||
#define ATT_PIN 0 //~SS
|
||||
#define CMD_PIN 2 //MOSI
|
||||
#define DATA_PIN 3 //MISO
|
||||
#define CLK_PIN 1 //SCK
|
||||
#define DATA_LEN 5
|
||||
/* /PSX DEFINE */
|
||||
#endif
|
||||
#include "POPNHID.h"
|
||||
/* 1 frame (as declared in POPNHID.cpp) on highspeed USB spec is 125µs */
|
||||
@@ -59,6 +74,125 @@ byte rowPins[ROWS] = {50, 40, 42, 46}; //connect to the row pinouts of the keypa
|
||||
byte colPins[COLS] = {48, 52, 44}; //connect to the column pinouts of the keypad
|
||||
|
||||
Keypad kpd = Keypad( makeKeymap(numpad), rowPins, colPins, ROWS, COLS );
|
||||
#else
|
||||
/* PSX globals */
|
||||
volatile uint8_t data_buff[DATA_LEN]={0x41,0x5A,0xBF,0xFF,0xFF};//Reply.
|
||||
volatile uint8_t command_buff[DATA_LEN]={0x01,0x42,0x00,0x00,0x00};
|
||||
|
||||
volatile uint8_t curr_byte=0;
|
||||
volatile uint8_t next_byte=0;
|
||||
|
||||
byte b4;
|
||||
byte b5;
|
||||
|
||||
void convertPopn(uint32_t buttons){
|
||||
|
||||
b4 = 0xFF;
|
||||
b5 = 0xFF;
|
||||
|
||||
if (((buttons >> 9) & 1)) {
|
||||
b4 &= ~((unsigned char) 0x01);
|
||||
} else {
|
||||
b4 |= ((unsigned char) 0x01);
|
||||
}
|
||||
if (((buttons >> 10) & 1)) {
|
||||
b4 &= ~((unsigned char) 0x08);
|
||||
} else {
|
||||
b4 |= ((unsigned char) 0x08);
|
||||
}
|
||||
|
||||
if (((buttons >> 0) & 1)) {
|
||||
b5 &= ~((unsigned char) 0x10);
|
||||
} else {
|
||||
b5 |= ((unsigned char) 0x10);
|
||||
}
|
||||
if (((buttons >> 1) & 1)) {
|
||||
b5 &= ~((unsigned char) 0x20);
|
||||
} else {
|
||||
b5 |= ((unsigned char) 0x20);
|
||||
}
|
||||
if (((buttons >> 2) & 1)) {
|
||||
b5 &= ~((unsigned char) 0x08);
|
||||
} else {
|
||||
b5 |= ((unsigned char) 0x08);
|
||||
}
|
||||
if (((buttons >> 3) & 1)) {
|
||||
b5 &= ~((unsigned char) 0x40);
|
||||
} else {
|
||||
b5 |= ((unsigned char) 0x40);
|
||||
}
|
||||
if (((buttons >> 4) & 1)) {
|
||||
b5 &= ~((unsigned char) 0x04);
|
||||
} else {
|
||||
b5 |= ((unsigned char) 0x04);
|
||||
}
|
||||
if (((buttons >> 5) & 1)) {
|
||||
b5 &= ~((unsigned char) 0x80);
|
||||
} else {
|
||||
b5 |= ((unsigned char) 0x80);
|
||||
}
|
||||
if (((buttons >> 6) & 1)) {
|
||||
b5 &= ~((unsigned char) 0x02);
|
||||
} else {
|
||||
b5 |= ((unsigned char) 0x02);
|
||||
}
|
||||
if (((buttons >> 7) & 1)) {
|
||||
b4 &= ~((unsigned char) 0x10);
|
||||
} else {
|
||||
b4 |= ((unsigned char) 0x10);
|
||||
}
|
||||
if (((buttons >> 8) & 1)) {
|
||||
b5 &= ~((unsigned char) 0x01);
|
||||
} else {
|
||||
b5 |= ((unsigned char) 0x01);
|
||||
}
|
||||
// left down right always held with popn controller
|
||||
b4 &= 0x1F;
|
||||
|
||||
data_buff[2] = b4;
|
||||
data_buff[3] = b5;
|
||||
|
||||
}
|
||||
ISR(SPI_STC_vect) {
|
||||
uint8_t inbyte=SPDR;
|
||||
|
||||
if (inbyte==command_buff[curr_byte]) {
|
||||
|
||||
SPI_DDR |= (1<<DATA_PIN);//output
|
||||
|
||||
SPDR = data_buff[curr_byte];
|
||||
curr_byte++;
|
||||
if (curr_byte<DATA_LEN) {//ACK low.
|
||||
_delay_us(8); // Necessary delay for PS1 (not needed for PS2)
|
||||
//SPI_PORT &= ~(1<<ACK_PIN);
|
||||
PORTD &= ~(1<<5);//set HIGH
|
||||
// simulate open drain
|
||||
// SPI_DDR |= (1<<ACK_PIN);//output
|
||||
// SPI_PORT &= ~(1<<ACK_PIN);//set low (simulate open collector LOW)
|
||||
|
||||
_delay_us(1);
|
||||
//SPI_PORT |= (1<<ACK_PIN);
|
||||
PORTD |= (1<<5);//set HIGH
|
||||
|
||||
// simulate open drain
|
||||
// SPI_DDR &= ~(1<<ACK_PIN);//input
|
||||
// SPI_PORT |= (1<<ACK_PIN);//set high (simulate open collector Hi-Z)
|
||||
|
||||
} else {
|
||||
SPDR = 0xFF;
|
||||
curr_byte=0;
|
||||
}
|
||||
} else {
|
||||
SPDR = 0xFF;
|
||||
curr_byte=0;
|
||||
}
|
||||
|
||||
SPI_DDR |= (1<<ATT_PIN);//out
|
||||
SPI_PORT |= (1<<ATT_PIN);//set HIGH
|
||||
_delay_us(5);
|
||||
SPI_PORT &= ~(1<<ATT_PIN);//set HIGH
|
||||
}
|
||||
/* /PSX globals */
|
||||
#endif
|
||||
|
||||
/* SETUP */
|
||||
@@ -90,11 +224,31 @@ void setup() {
|
||||
*/
|
||||
POPNHID.setLightMode(2);
|
||||
#else
|
||||
uint8_t lightMode;
|
||||
uint8_t lightMode = 2;
|
||||
EEPROM.get(0, lightMode);
|
||||
if (lightMode > 4)
|
||||
lightMode = 2;
|
||||
POPNHID.setLightMode(lightMode);
|
||||
|
||||
/* PSX setup */
|
||||
// use TXLED as ACK
|
||||
// DDRD |= (1<<5);//output
|
||||
PORTD |= (1<<5);//set HIGH
|
||||
|
||||
SPI_DDR &= ~(1 << DATA_PIN); //input
|
||||
SPI_PORT |= (1<<DATA_PIN);//set HIGH
|
||||
|
||||
//SPI setup
|
||||
SPCR |= (1 << SPR1); // Fosc/64. @16MHz==250KHz.
|
||||
SPCR |= (1 << CPHA); // Setup @ leading edge, sample @ falling edge.
|
||||
SPCR |= (1 << CPOL); // Leading edge is falling edge, trailing edge is rising edge.
|
||||
SPCR &= ~(1 << MSTR); // MSTR bit is zero, SPI is slave.
|
||||
SPCR |= (1 << DORD); // Byte is transmitted LSB first, MSB last.
|
||||
SPCR |= (1 << SPE); // Enable SPI.
|
||||
SPCR |= (1 << SPIE); // Enable Serial Transfer Complete (STC) interrupt.
|
||||
SPDR = 0xFF;
|
||||
sei(); // Enable global interrupts
|
||||
/* /PSX setup */
|
||||
#endif
|
||||
//boot animation
|
||||
uint16_t anim[] = {1, 4, 16, 64, 256, 128, 32, 8, 2};
|
||||
@@ -121,7 +275,16 @@ void loop() {
|
||||
buttonsState &= ~((uint32_t)1 << i);
|
||||
}
|
||||
}
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
/* PSX convert */
|
||||
convertPopn(buttonsState);
|
||||
|
||||
if ((SPI_PORT & (1 << ATT_PIN) > 0)) {
|
||||
SPI_DDR &= ~(1 << DATA_PIN); // input
|
||||
SPI_PORT &= ~(1 << DATA_PIN); // ensure pullup is off
|
||||
}
|
||||
|
||||
#endif
|
||||
/* USB DATA */
|
||||
if ( ( (micros() - lastReport) >= REPORT_DELAY) )
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user