Dirt-cheap Vaus paddle clone for MSX - Now supports Standard Paddles too.

Similar projects worth following
Programmable Paddle for MSX computers using one of the cheapest Arduino boards availabe, the Digispark. Can operate either as a Vaus Arkanoid paddle or a MSX Standard paddle. It can also operate in automatic, detecting the proper operating mode according to the signals sensed on MSX joystick port.
Same firmware can be compiled for UNO and Nano boards.

This project was designed to be a minimalist, easy to replicate, cheap Paddle controller for MSX computers.

It provides two operating modes: Vaus Arkanoid Paddle and Standard MSX paddle. The operating mode is programmable and is persistent, which means that the default behavior is the last mode programmed.

There is also a third (pseudo) operating mode that performs automatic selection of operating mode based on the signals sensed from joystick port

Arkanoid Mode

The Arkanoid mode is a tore down version of #SMSX paddle ported to the Digispark .

The communication with the MSX computer follows the protocol used in Taito Arkanoid paddle (Vaus) device.

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.

Potentiometer position is read using the ADC and the 10 bit value is mapped  to the defined  limits.
#define MINVAL 110
#define MAXVAL 390

The value is read from MSX as a 9 bit value and the center value of such range is close to 256.

Standard Paddle Mode
This mode uses only one interrupt, attached to the PULSE signal at pin 8. A positive going edge on this pin causes the CPU to wake and generate a 50us negative going pulse after a timing interval from 12us to 3.06ms in 256 steps (of 12us) according to the position of the potentiometer. 
This behavior is slightly different from the discrete component based paddles (a monostable) and was adopted to avoid to deal with interrupt latency, as the discrete timers can change its output within nanoseconds from trigger pulse while the microcontroller (with standard C ISR handling code) takes some a few microseconds to answer the interrupt and change the state of the output.
Nevertheless teh 50us negative going pulse is more than enough for the Z80 to detect the end of the timing cycle.
Timing for Potentiometer at minimum: 12.125us; ~50us Negative going pulse at the end.

Timing for Potentiometer at maximum: 3058us

Timing for Potentiometer at maximum: 3058us

Automatic Mode

The selection of operating mode is done by analyzing the behavior of the Clock (pin 6) and Pulse (pin 8).

When executing Arkanoid game the MSX sends clock pulses on pin 6 during normal readings and issue a pulse on pin 8 to start a new conversion (potentiometer sampling). On the other While reading Standard Paddles the MSX only issues pulses on pin 8.

The detection routine counts both Clock and Pulse pin changes until it has detected  10 pin changes on Puse pin.

The DigitalRead( ) function is rather slow to detect all the changes and as a result the 10 pin changes detected on pin 8 will will not be equivalent to 5 full sampling cycles. For the same reason the counting of the Clock pin state changes will be far below the expected (16 changes per sampling).

The experiments performed showed that it is safe to assume that if at least one state change has been detected on the Clock line then the operating mode selected should be Arkanoid Paddle. If no State change was detected then the operating mode is Standard Paddle.

Notice that the Arkanoid game uses an heuristic to select to detect the type of joystick connected. When the game runs for the first time the title screen asks for pressing Fire Button. If the game detects the DOWN directional pressed (pin 2) then it assumes that there is a Vaus controller connected, and only then starts to issue Pulse and Clock signals.

That is the...

Read more »

  • 1 × Digispark AVR based development board
  • 1 × 10k Linear Potentiometer
  • 1 × Push Button
  • 1 × DE-9 Female
  • 1 × 1k Ohm 1/8Watt Used only with Digispark board

  • Assembling the Digi:Arka->Pad

    danjovic05/16/2021 at 16:43 0 comments

    Some pictures of the assembly. First thecomponents

    Another picture of the components. I have considered to use the Veroboard but haven't did that now. Maybe on the next project.

    The resistor is soldered under the board, from VCC to PB4

    Everything wired

    Wires organized

    Unit assembled and closed

  • Demo Videos

    danjovic04/05/2020 at 16:55 0 comments

    Recorded some videos to demonstrate the project:

  • Prototype with Digispark

    danjovic04/05/2020 at 15:04 0 comments

    Here you are the prototype that runs on Digi-Spark board.

    I have used a DIY adapter board to assemble the prototype on a protoboard.

  • Prototype with UNO

    danjovic04/05/2020 at 03:03 0 comments

    That's the prototype built with Arduino UNO. The potentiometer and button were borrowed from #Vaus Arkanoid Paddle Clone project.

  • Temporization for Standard Paddle.

    danjovic04/05/2020 at 02:13 0 comments

    According to MSX Red book:

    "Each paddle is basically a one-shot pulse generator, the length of the pulse being controlled by a variable resistor. A start pulse is issued to the specified joystick connector via PSG Register 15. A count is then kept of how many times PSG Register 14 has to be read until the relevant input times out. Each unit increment represents an approximate period of 12 µs on an MSX machine with one wait state."

    When you do the math, 256 increments of 12us yelds: 12us*256 = 3072us.

    Time for Potentiometer at minimum
    Timing for Potentiometer at minimum: 12.125us
    Timing for Potentiometer at maximum: 3058us
    Timing for Potentiometer at maximum: 3058us

    Mission Accomplished!

    A quick note, though.

    Pulse pins coming from MSX triggers a Pin Change interrupt on the AVR. At the beginning of the ISR it was necessary to read the state of the line to check whether the pin change has been a rising or a falling edge.

    The DigitalRead() function was taking too long to execute, longer than the 4.7us that the input pulse lasted.

    After the code was changed to read the AVR input register (PINB) directly the Standard paddle function worked fine.

    #define SOChigh() PINB&(1<<1) // Fast digital reading
    // Pin change interrupt driven by SOC (Start of Conversion) pin (8) - PULSE
    ISR(PCINT0_vect) { //
      if (SOChigh()  ) { //Rising edge?

  • Extended Version

    danjovic04/05/2020 at 01:41 0 comments

    I have just released an extended version named Digi:Arka->Pad with the following features:

    • Support for Standard Paddles
    • Selectable operating modes:
      • Automatic
      • MSX Standard
      • Arkanoid

    Also added support for other Arduino boards (spinoff versions)

    • Nano
    • UNO

    Mode programming is performed by holding the button pressed at power up and stored in internal EEPROM.

    Selected mode depends upon the position of the potentiometer.

  • More on glitches

    danjovic04/02/2020 at 22:10 0 comments

    I have performed more waveform captures and noticed that the occurrence of glitches depends upon what is connected to pin 8.

    • Without anything connected to the pins 8 and 6 - No glitches
    • With #Vaus Arkanoid Paddle Clone connected - No glitches
    • With #Digi:Arka connected - Glitches
    • With a 1k resistor from pin 8 to VCC - No glitches
    • With a 1K resistor from pin 8 to GND - Glitches

  • Presenting the prototype

    danjovic04/02/2020 at 01:52 0 comments

     Some pictures of the prototype

    DIY digispark clone
    Pot and button borrowed from another project

  • Glitches, and how to get rid of them -Part II like a pro!

    danjovic04/02/2020 at 01:31 0 comments

    I have studied the nature of the glitch for this particular device and verified the following fact:

    • Glitches are caused by MSX. No doubt on that;
    • Glitches occur only when CLOCK signal change its state;
    • Glitches occur simultaneously to the change in CLOCK signal.

    then I have added another facts:

    • CLOCK signal triggers INT0 on AVR;
    • PULSE signals  either real or glitches triggers Pin Change Interrupt on AVR;

    Then just as I was considering the last fact.....

    • External Interrupts have priority over Pin Change Interrupts!

    The solution slapped me in the face!


    And that was done...

    // External Interrupt driven by Clock pin (6)
    ISR(INT0_vect) {
      // output a new bit 
      if (shiftRegister & (1 << MSBIT)) {
        pinMode(DATA, INPUT_PULLUP);
      } else {
        digitalWrite(DATA, LOW);
        pinMode(DATA, OUTPUT);
      // pre-shift next bit
      shiftRegister <<= 1;
      GIFR |= (1<<PCIF );   // <- De-glitch in a single instruction!

     The result  can be seen below. Glitches still appear but they do not cause any harm !

  • Latency

    danjovic04/02/2020 at 00:08 0 comments

    Measured the latency of the interrupts from falling edge of CLOCK signal until the level at output changes state: 7.2us

    Such latency did not cause any problem on Arkanoid game but just for curiosity it is equivalent to 26 Tstates of an MSX running at 3.579MHz.

View all 11 project logs

  • 1
    Do this if you are using a Chinese Digispark clone

    The Chinese Digispark clones are very cheap and have a female USB connector which is good but they ship with RESET enabled which means that PB5 is not available for use.

    To perform the change it is necessary to change the HFuse configuration of the ATTiny85.

    I have used AVeRCADE with USBasp firmware for doing that, but any ISP programmer will do fine. The connections to a 10 pin are show below. However it is possible to use other methods, for example using an Arduino (link).

    The command for programming the High fuse to its correct configuration is:

    avrdude -c usbasp -p t85 -U hfuse:w:0x5f:m

    If everything works fine you should see something like that

    Why does black and yellow indicate danger? - Biology Stack ...Advice notice:

    After you have programmed pin 5 as an I/O it shall not be possible to change the configuration fuses again.

    If something wend wrong while programming the fuses or even while loading the sketch (it can happens with any sketch) and your board gets bricked (refusing to accept new sketches) then follow this Instructable provided by dmjlambert to unbrick it.

    Why does black and yellow indicate danger? - Biology Stack ...
  • 2
    Upload your Sketch
  • 3
    Program the Operating Mode

    If necessary, program the operating mode:

    • Plug the device with the MSX computer turned off
    • Turn the rotary knob to the desired position (refer to the figure below)
    • Press and hold fire button
    • Turn on MSX computer and wait 5 seconds (this time is necessary for digispark to quit the bootloader and start running the main program.

View all 4 instructions

Enjoy this project?



jlopez77 wrote 03/10/2022 at 10:37 point

Would this work in a bare ATtiny85?

  Are you sure? yes | no

emmajoy878 wrote 05/26/2021 at 21:13 point

Thanks for the information. I want to know about 1password APK by how to use it. Thank you

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

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