• Skip to main content
  • Skip to header right navigation
  • Skip to site footer
makerhacks-logo

Maker Hacks

Ideas, news & tutorials for makers and hackers – Arduino/Raspberry Pi, 3D printing, robotics, laser cutting, and more

  • Home
  • About
  • 3D Printing
  • Laser Cutting
  • YouTube
  • Free Arduino Course
  • Recommendations
  • Contact

Arduino SID Player: Play C64 Music on Your Uno

You are here: Home / Electronics and Hardware / Arduino SID Player: Play C64 Music on Your Uno
FacebookTweetPin
Author: Chris Garrett

Play C64 music using an Arduino Uno – without a SID chip! This project emulates the MOS 6581/8580 and can load the tunes from SD card.

SID music players already exist for desktop computers, and of course on the Commodore 64, so why create one using an Arduino Uno?

During discussions in the Neo6502 community, we got to thinking about how to add great chip-tune capability to the device.

Naturally my mind went to how lovely it would be to add a SID (MOS 6581/8580) chip, but those guys are getting scarce and therefore expensive. There are FPGA and ARM based emulators, but they are also not cheap. What is the lowest power microcontroller that can do this?

Arduino SID Emulation

Digging around in Google I found a project that had managed to hack together an imperfect but working emulation of the SID chip using an Atmega!

His approach was to create C header files containing all the music, and compile it right into the project.

Download the Arduino library .zip file and uncompress it in your Arduino/Libraries directory:

Creating them is a bit of a faff so I included a clip of Commando.SID in the Github repo.

Converting SID music for use with this Arduino code requires first turning the tune into a dump file, and then converting that dump into a C header array:

  • Extract SID music data from SID files using SID Dumper by Johannes Ahlebrand Windows application (not to be confused with the multi-platform SID Dumper)
  • JConverter.jar is then required to convert dumped SID music files into C header files – this is abandonware, searching for JConverter now brings up a Joomla migration tool!

SID Player Arduino Code

Connect PIN 9, 10 + ground to your audio jack adapter or speaker.

#include <avr/pgmspace.h>  // Lib to store data in the flash rom
#include <SID.h>           // sid-arduino-lib: Brian Tucker 1-5-2015
SID mySid;                 // https://code.google.com/p/sid-arduino-lib/ 


// Our SID music file converted into a C header file containing an array
#include "commando_sid.h"  // SID register data file in flash memory

#define LED 13

// Non-blocking sleep function
void sleep(int sleep_time)
{
  long start_time = millis();

  while(millis() < start_time + sleep_time)
  {
    // do nothing
  }
}

// Once on boot
void setup()  { 

  // Initialize the SID library
  mySid.begin();
} 

// Main loop
void loop() {

  // Get the next SID register data and set in the SID class
  for(uint16_t sidPointer=0;sidPointer<=sidLength;sidPointer++){
    for(uint8_t sidRegister=0;sidRegister<=24;sidRegister++){
      mySid.set_register(sidRegister, (pgm_read_byte(&sidData[(sidPointer+sidRegister)])));
    };

    // Wait before moving the pointer forward
    sleep(19);
    sidPointer=sidPointer+24;
  };
}

Crunchy but recognizable tunes should emanate from your speakers if you wired everything correctly.

Playing SID music on an Arduino
Playing SID music on an Arduino

Unfortunately, even the Atmega328 has extremely limited memory, and the way this has to work is to force-feed the emulated chip with all the sound registers repeatedly, so it is a lot more memory intensive than the original C64 would have to deal with.

Still, for short clips it works!

Loading SID Files from SD Card

Then I realized that we could load as much bloated SID file data as we like if we stream it from SD card instead of compiling it into the Arduino code.

Rather than grab clips of C64 music I again used the Windows SID dumper but exported a couple of full-length tunes … they were 450KB!

Clearly no attempt is made to compress these things, but that makes it easier on our little Arduino when it comes to consuming that data.

Arduino SD card reader breakout
Arduino SD card reader breakout

You will need an SD card reader breakout like the one in the photo.

In addition to the above pins, you will need to connect the SPI bus:

  • MOSI – pin 11
  • MISO – pin 12
  • CLK – pin 13
  • CS – pin 4

Then connect 3v power, Ground.

Reading Files from SD with Arduino

To read from our SD card we can simply use the SPI and SD libraries built right in to the Arduino IDE. We just have to tell the library which pin is the chip select, and in our case that is pin 4 because I followed the official example.

They provide convenient Open, Close, and Read methods, as well as being able to check Available() to see if there is data remaining:

#include <SPI.h>
#include <SD.h>

void setup() {

  Serial.begin(115200);
  while (!Serial) {
    ; // wait for the serial port 
  }

  if (!SD.begin(4)) {
    Serial.println("SD initialization failed!");
    while (1);
  }

  File myFile = SD.open("test.txt");
  if (myFile) {
    // read until end of file:
    while (myFile.available()) {
      Serial.write(myFile.read());
    }
    // close the file:
    myFile.close();
  } else {
    // file didn't open, error:
    Serial.println("error opening test.txt");
  }
}

void loop() { 
// nothing
}

Play SID from SD-Card

If you just want to boot and play a specific SID tune file, you can use this code.

Of course, you will need some SID tunes for your SD card, so I included some dumped files in a zip for your convenience (they will need to be extracted to the root of your SD drive).

Having to compile each time you want to change the tune isn’t much fun after a while, though.

I did consider making it so you can type a filename into the serial input (I am outputting the files found on the card to serial so could make sense), but instead I decided to just play a random tune from the files found in the root folder.

There are two downsides to this, one is the delay reading the list of files, especially if you have lots, and the second downside is Arduino is not particularly random when it comes to random numbers, even when providing a seed value!

We read the filenames, looking for “.DMP” to make our list (if you have more than 20 you will need to tweak the code). From this list we randomly select a filename and open that file.

All that remains for us to do is continually supply the 25 emulated SID registers with data:

myFile.read((uint8_t *)sidData, 25);

#include <string.h>
#include <SPI.h>
#include <SD.h>

File myFile;
File root;

/* Audio out: Connect PIN 9, 10 + ground */
#include <SID.h>           
SID mySid;                 
char sidData[25];

String playlist[20];
char num_files=0;

// Non-blocking sleep function
void sleep(int sleep_time)
{
  long start_time = millis();

  while(millis() < start_time + sleep_time)
  {
    // do nothing
  }
}

// Print the contents of a directory
void read_directory(File dir, int numTabs) {
  while (1) {

    // Get next file entry
    File entry =  dir.openNextFile();

    // End of files
    if (! entry) {
      break;
    } else {

   
      // Is it a directory?
      if (!entry.isDirectory() && entry.size()>0) {

        // Filename
        String filename = String(entry.name());

        if(filename.indexOf(".DMP") > 0 || filename.indexOf(".dmp") > 0) {

        // Print the filename
        Serial.print(filename + " ");
        Serial.println(entry.size());
        playlist[num_files] = filename;
        num_files++;
        }

      }


    }

    // Done with this entry
    entry.close();

  }
}

// Open the file for reading:
int load_sid(char sid_file[14]) {

  // Load the file
  myFile = SD.open(sid_file);

  if (myFile) {
    Serial.println("OPENED file:" + String(sid_file));
    return 0;
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening file " + String(sid_file));
    return 1;
  }


}

// Once on boot
void setup()  { 

  // Initialize the SID library
  mySid.begin();

  // Open serial and wait:
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port 
  }
  Serial.print("\f\n\n");
  Serial.println("Initializing SD card...");

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("\n\nReading root directory ...\n\n");

  // Open root directory and display the results
  root = SD.open("/");
  read_directory(root, 0);
  Serial.println("Directory read."); 

  // open random sid dump
  char chosen_file[13];
  for(int r; r < random(100); r++) {
    randomSeed(analogRead(A0));
    playlist[(int)random(0,num_files-1)].toCharArray(chosen_file, 13);
  }
  Serial.println("Loading tune " + String(chosen_file));
  int res=load_sid(chosen_file);

} 

// Main loop
void loop() {


    // read from the file until there's nothing else in it:
    if (myFile.available()) {
      myFile.read((uint8_t *)sidData, 25);
      for(uint8_t sidRegister=0;sidRegister<=24;sidRegister++){
        mySid.set_register(sidRegister,sidData[sidRegister]);
      }
      sleep(19);
    } else {
      // close the file:
      myFile.close();
    }

}


Next Steps

As mentioned, there are a couple of things that make this less than convenient already, so rather than almost-sometimes-random on reset it could do with some kind of user interface.

Plus it is not portable so unless I can make it compact and run off battery, you might as well use a desktop app.

For the Neo6502 of course, it needs to be under control of the 6502 chip’s IO, and that is another project entirely!

Category: Electronics and HardwareTag: arduino, Makes
FacebookTweetPin

About Chris Garrett

Marketing nerd by day, maker, retro gaming, tabletop war/roleplaying nerd by night. Co-author of the Problogger Book with Darren Rowse. Husband, Dad, ?? Canadian.

Check out Retro Game Coders for retro gaming/computing.

☕️ Support Maker Hacks on Ko-Fi and get exclusive content and rewards!

Previous Post: DIY Z80 Output to LCD: Homebrew Retro Computer Part 3
Next Post:Neo6502 GPIO Input and Output

Sidebar

  • Facebook
  • Twitter
  • Instagram
  • YouTube

Join the Newsletter

Sign up and get a free Arduino course + more!

Subscription Form

Recently Popular

  • xTool S1 Review
  • xTool P2 Review (first look)
  • IKIER K1 Pro Max Review
  • Gweike Cloud Review
  • How to choose the right 3D printer for you
  • Glowforge Review – Glowforge Laser Engraver Impressions, Plus Glowforge Versus Leading Laser Cutters
  • Flux Ador
  • Prusa i3 Mk3S Review
  • Best 3D Printing Facebook Groups
  • xTool D1 Pro Laser Cutter Review
  • Elegoo Mars Review – Review of the Elegoo Mars MSLA Resin 3D Printer
  • Glowforge ‘Pass-Through’ Hack: Tricking the Front Flap of the Glowforge with Magnets to Increase Capacity
  • How to Make a DIY “Internet of Things” Thermometer with ESP8266/Arduino
  • Wanhao Duplicator i3 Review
  • IKEA 3D Printer Enclosure Hack for Wanhao Di3
  • Creality CR-10 3d printer review – Large format, quality output, at a low price!
  • 3D Printed Tardis with Arduino Lights and Sounds
  • Anet A8 Review – Budget ($200 or less!) 3D Printer Kit Review
  • Make your own PEI 3D printer bed and get every print to stick!
  • Upgrading the Wanhao Di3 from Good to Amazing
  • How to Install and Set Up Octopi / Octoprint
  • Creality CR-10 S5 Review
  • Glowforge Air Filter Review
  • Thunder Laser Review

30 Days to Arduino

Arduino Tutorials
  • 3D Printing
  • CNC
  • Electronics and Hardware
  • Laser Cutting
  • News and Reviews
  • Software and Programming

arduino budget cad cnc diode laser glowforge Hacks Ideas laser cutter linux Makes making python raspberry pi resin Reviews technology tips xTool Lasers

.

Maker Hacks Blog Copyright © 2026 · All Rights Reserved · Privacy Policy