SkillAgentSearch skills...

SID6581

Control a SID Chip using esp32

Install / Use

/learn @hpwit/SID6581
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

SID 6581 library

===========

arduino-library-badge

An ESP32 library to control up to 5 SID 6581 chips from the 1980s era.

<p align="center"> <img src="extras/project_logo.png" alt="SID6581 for ESP32 logo" width="512" /> </p>

Hardware requirements

  • ESP32-Wroom of ESP32-Wrover (dual core required)
  • Any SID Chip model (original, clone)
  • Any pcb using 74HC595 adressing (see schematics

Features

  • Directly push the register to the SID chip. Hence you can program like in the good old times :)
  • Play old (or new) sid tunes video here
  • Play notes over up to 15 voices (3 voices per SID chip)
  • Design and play different instruments video here with MIDI and 6 voices
  • Assign up to one instrument per voice

The sound is played in the background so your mcu can do something else at the same time.

NB: the SID chip requires a 1Mhz clock signal to work you can either provide it with an external clock circuit or use a pin of the esp32 to do it (clock generated thanks to I2s).

It should work with other mcu as it uses SPI but this hasn't been tested yet (contributors welcome).

Please look at the schematics for the setup of the shift registers. MOS 6581 documentation.

To start


// if you have a external oscillator that gives you the 1Mhz clock you can use:
begin(int clock_pin,int data_pin, int latch);

// if you do not have an external oscillator the esp32 can create the 1Mhz signal uisng i2s using this
begin(int clock_pin,int data_pin, int latch,int sid_clock_pin);
// the sid_clock_pin will need to be plugged to the 02 pin or clock pin of the SID 6581
// !!! NB: this pin number has to be >=16

Playing SID tunes

You have to ways of playing sid tunes:

  1. Playing .sid files (PSID for the moment) the player is still under development so if you have issues do not hesistate to link the file which you have encountered issues with
  2. Playing registers dump

1 - To play a SIDTune from a .sid file (PSID version only for the moment)

You can play SIDTunes stored as .sid files ont the SPIFFS or SD card Below the list of command to control the player

NB1: the sid tunes do not have an end hence they will play by default for 3 minutes. To stop a song you need to use stop()

begin(int clock_pin,int data_pin, int latch);
begin(int clock_pin,int data_pin, int latch,int sid_clock_pin);
bool playSID();
bool playSID( SID_Meta_t* sid_info );
~~bool play(); //play in loop the playlist~~
~~bool playSongAtPosition(int position); //play song at a specific position of the playlist.~~
void soundOff(); //cut off the sound
void soundOn(); //trun the sound on
void togglePause(); //pause/play the player
void setMaxVolume( uint8_t volume); //each sid tunes usually set the volume this function will allow to scale the volume
void stop(); //stop the current song restart with playNext() or playPrev()
void setDefaultDuration(uint32_t duration); //will set the default duration of a track in milliseconds
uint32_t getDefaultDuration();

void setLoopMode(loopmode mode); //set the loop mode for playing the tracks and files
loopmode getLoopMode(); // returns the current loop mode

Possible loopmode values:

  • SID_LOOP_ON: loop inside a SID track, whatever the number of subsongs
  • SID_LOOP_RANDOM : same as SID_LOOP_ON with random selection of the next song in the SID track
  • SID_LOOP_OFF : ends after playing one song in the SID track

~~bool getPlayerStatus(); //tells you if the runner is playing or not~~

bool isPlaying();

// Specific functions to have info on the current sid file
char * getFilename(); //return the filename of the current Sidfile playing
char * getName(); //get name of the current sid file
char * getPublished(); //get publish information of the current sid file
char * getAuthor(); //return the author of the current sidfile
uint32_t getCurrentTrackDuration(); //give you the duration of the current track
uint32_t getElapseTime(); //send you back the elapstimea track was played in milliseconds
int getNumberOfTunesInSid(); //get the number of tunes in a sidfile
int getCurrentTuneInSid(); // get the number of the current playing tunes in the sid (NB: the tunes are from 0->getNumberOfTunesInSid()-1
int getDefaultTuneInSid(); //get the number of the default tunes.

// SID Meta information

struct SID_Meta_t
{

  char     filename[255]; // This eliminates SPIFFS which is limited to 32 chars
  uint8_t  name[32];      // Song title
  uint8_t  author[32];    // Original author
  char     md5[32];       // The MD5 hash according to HVSC MD5 File
  uint8_t  published[32]; // This is NOT a copyright
  uint8_t  subsongs;      // How many subsongs in this track (up to 255)
  uint8_t  startsong;     // Which song should be played first
  uint32_t *durations = nullptr; // up to 255 durations in a song

};

By default the song duration is 3 minutes and can be changed with setDefaultDuration(uint32_t duration). You can retrieve the actual song durations from https://www.hvsc.de archives. DOCUMENTS/Songlengths.md5. If you have that file you can match the actual song duration with getDuration( SID_Meta_t *song ).

Example:


#include <FS.h>
#include <SD.h>

#define SID_CLOCK 25
#define SID_DATA 33
#define SID_LATCH 27
#define SID_PLAYER
#define SID_INSTRUMENTS

#include <SID6581.h>


static MD5Archive HSVC =
{
  "HVSC 74",    // just a fancy name
  "HVSC-74"     // !! a dotfile name will be derivated from that
};

static MD5FileConfig MD5Config =
{
  &SD,                                   // The filesystem (reminder: SPIFFS is limited to 32 chars paths)
  &HVSC,                                 // High Voltage SID Collection meta info
  "/C64Music",                           // Folder where the HVSC unzipped contents can be found
  "/md5",                                // Folder where MD5 pre-parsed files will be spreaded (SD only)
  "/C64Music/DOCUMENTS/Songlengths.md5", // Where the MD5 file can be found (a custom/shorter file may be specified)
  "/md5/Songlengths.md5.idx",            // Where the Songlengths file will be indexed (SD only)
  MD5_INDEX_LOOKUP,                      // one of MD5_RAW_READ (SPIFFS), MD5_INDEX_LOOKUP (SD), or MD5_RAINBOW_LOOKUP (SD)
  nullptr                                // callback function for progress when the cache init happens, can be overloaded later
};


SIDTunesPlayer *player;

void setup() {

  Serial.begin(115200);

  player = new SIDTunesPlayer( &MD5Config );

  player->begin( SID_CLOCK, SID_DATA, SID_LATCH );

  if(!SD.begin()){
    Serial.println("SD Mount Failed");
    return;
  }

  if( !player->getInfoFromSIDFile( "/C64Music/MUSICIANS/H/Hubbard_Rob/Synth_Sample_III.sid" ) ) {
    Serial.println("SID File is not readable!");
    while(1);
  }

  player->play();

  Serial.println();
  Serial.printf("author:%s\n",player->getAuthor());
  Serial.printf("published:%s\n",player->getPublished());
  Serial.printf("name:%s\n",player->getName());
  Serial.printf("nb tunes:%d default tunes:%d\n",player->getNumberOfTunesInSid(),player->getDefaultTuneInSid());

  delay(5000);
  player->playNextSongInSid();
  delay(5000);
  Serial.println();
  Serial.printf("author:%s\n",player->getAuthor());
  Serial.printf("published:%s\n",player->getPublished());
  Serial.printf("name:%s\n",player->getName());
  Serial.printf("nb tunes:%d default tunes:%d\n",player->getNumberOfTunesInSid(),player->getDefaultTuneInSid());

}


void loop() {
    delay(5000);
    Serial.println("Pause the song");
    player->togglePause();
    delay(4000);
    Serial.println("restart the song");
    player->togglePause();
    delay(3000);
    Serial.println("hi volume");
    player->setMaxVolume(15);
    delay(3000);
    Serial.println("low volume ");
    player->setMaxVolume(3);
    delay(3000);
    Serial.println("medium");
    player->setMaxVolume(7);
    delay(6000);
}

2 - callback events of the players

Both players can fire custom events for better control:

inline void setEventCallback(void (*fptr)(sidEvent event))

possible values of the event

  • SID_NEW_TRACK : playing new song
  • SID_NEW_FILE : playing a new file
  • SID_START_PLAY : start the player
  • SID_END_PLAY : end the player
  • SID_PAUSE_PLAY :pause track
  • SID_RESUME_PLAY : resume track
  • SID_END_TRACK : end of a track
  • SID_STOP_TRACK: stop the current trak

Example:


#define SID_CLOCK 25
#define SID_DATA 33
#define SID_LATCH 27
#define SID_PLAYER
#define SID_INSTRUMENTS
#include <SD.h>
#include <FS.h>
#include <SID6581.h>

SIDRegisterPlayer * player;

void myCallback(  sidEvent event ) {
    switch( event ) {
        case SID_NEW_TRACK:
            Serial.printf( "New track: %s\n",player->getFilename() );
        break;
        case SID_START_PLAY:
            Serial.printf( "Start play: %s\n",player->getFilename() );
        break;
        case SID_END_PLAY:
            Serial.printf( "stopping play: %s\n",player->getFilename() );
        break;
        case SID_PAUSE_PLAY:
            Serial.printf( "pausing play: %s\n",player->getFilename() );
        break;
        case SID_RESUME_PLAY:
            Serial.printf( "resume play: %s\n",player->getFilename() );
        break;
        case SID_END_SONG:
            Serial.println("End of track");
        break;
    }
}

void setup() {
    Serial.begin(115200);
    player=new SIDRegisterPlayer();
    player->begin(SID_CLOCK,SID_DATA,SID_LATCH);
    player->setEventCallback(myCallback);
    if(!SPIFFS.begin(true)){
        Serial.println("SPIFFS Mount Failed");
        return;
    }
    //the following line will go through all the files in the SPIFFS
    //Do not forget to do "Tools-> ESP32 S
View on GitHub
GitHub Stars57
CategoryDevelopment
Updated2mo ago
Forks6

Languages

C++

Security Score

95/100

Audited on Jan 17, 2026

No findings