Close
0%
0%

SMSX paddle

One paddle to turn them all

Similar projects worth following
This project implements a paddle control that can be used to play games on MSX computers and in Sega Master System video game console.
On MSX it replicates the behavior of a Taito Arkanoid controller while on Master System it acts like a Japanese HPD200 paddle controller.
The circuit is composed by an Arduino Nano board and some discrete components. A couple of diodes are used to route the negative rail supply from either pin 8 (SMS) or pin 9 (MSX) to power the Arduino Board.
The host system is auto detected on power-up depending upon the signals present at the inputs.

Working around joystick port differences

The most notorious difference is the negative rail pin, being the GND at pin 8 of the Sega Master System controller port but in MSX the GND is at pin 9.

A couple of diodes is used to route either GND pin to the negative rail (GND) of the arduino board.

HOST Auto Detection

The state of pin 9 at power up is used to detect which host the circuit is connected. Pin 9 is a input on SMS and therefore shall high (pulled up, indeed). On MSX this pin will always LOW as this is a GND pin.

MSX paddle program flow

The MSX paddle follows the Taito Arkanoid model.
Each data bit is sampled then a brief low going clock pulse is generated by the MSX on pin 6 to shif out the next bit (data changes on risign edge). After the 9th bit is read another short going pulse is generated this time on pin 8. The rising edge of such pulse starts an ADC conversion. After the conversion is complete the most significant bit gets ready at pin 1 and the remaining bits are stored in a variable to be shifted later by pulses coming from pin 6. Button is sampled right after the conversion and pin 2 is updated accordingly.

Code is implemented using a couple of interrupts, one on pin 6 (clock shift) and another at pin 8 (start new sample). Main loop  does nothing else than put CPU to sleep.

SMS paddle
SMS paddle sends one nibble at a time at a rate of 8kHz (62.5us per nibble). Each nibble is signaled by the level of pin 9 ("0" for lower nibble,"1" for higher nibble). The potentiometer is read right after the higher nibble is put on the outputs, then the button is read and pin 6 is updated accordingly.
Timing synchronization is done by use of a timer that wakes up the AVR.

  • 1 × Arduino Nano
  • 2 × 560 Ohms resistor
  • 2 × 1N4148 Discrete Semiconductors / Diodes and Rectifiers
  • 1 × 10K linear potentiometer
  • 1 × Push Button

View all 7 components

  • Testing

    danjovic09/07/2019 at 08:36 0 comments

    I' ve spent some time debugging the code for SMS and MSX.

    Latency was too high to respond properly for Clock pulses coming from MSX. Analyzing the code that reads the paddle in Arkanoid game:

    430f  out     (0a1h),a    ; 12  clock low
    4311  ld      a,1fh       ; 8
    4313  out     (0a1h),a    ; 12  clock high
    4315  ld      a,0eh       ; 8  
    4317  out     (0a0h),a    ; 12
    4319  in      a,(0a2h)    ; 

    We have only 52 Z80 cpu cycles for the data to be ready from the fall of the clock (0x430f) till the moment of reading (0x4319) which translated to numbers turn into (52 * 0.28us = 14,5us.

    Initially the total latency was higher than 30us from the RISE of the clock pin to the moment that the data was effectively changing resulting in a extremely unstable position of the paddle on the screen.

    The latency was reduced down to 3.6us by:

    • Pre-shifting the shiftRegister variable at the end of the interrupt
    • Changing the pins by writing to registers DDR/PORT instead of use digitalWrite()
    • Triggering the interrupt at the FALL of the clock signal.
      // External Interrupt driven by Clock pin (6)
      ISR(INT1_vect) {
      
         if (shiftRegister & (1<<15) ){
            OUT_DDR  &= ~(1<<0); // data on bit 0
            OUT_PORT |= (1<<0);       
          } else {
            OUT_PORT  &= ~(1<<0); 
            OUT_DDR |= (1<<0);      
            }
          // shift regiter was pre-shifted 
         digitalWrite(debugPin,HIGH);  
         digitalWrite(debugPin,LOW); 
        
          // pre-shift next bit   
          shiftRegister<<=1;    
      }

    Now the next data is ready even before the Z80 rise back the clock signal!

    Last but not least, the capture below shows the moment that the button is sampled and the output (pin 2) is changed. The capure also shows the method of reading. As the ADC on the original Arkanoid controller takes too much time (3-10ms) to convert the potentiometer position, the shifts are shifted FIRST then a NEW SAMPLE is requested by a pulse on pin 8.

View project log

Enjoy this project?

Share

Discussions

Similar Projects

2.9k
43
5
Project Owner Contributor

PiMasher

joshua.vaderjoshua.vader

Does this project spark your interest?

Become a member to follow this project and never miss any updates