#include #include "YMZ294_Serial.h" // For SSG YMZ294 / 74HC164 shift register #define SSG_DATA_PIN (5) // 164 B(2) #define SSG_CLOCK_PIN (6) // 164 CLK(8) #define SSG_ADDRESS_SELECT_PIN (7) // 294 A0 //////////////////////////////////////////////////////////////// // YMZ294 SSG interface //////////////////////////////////////////////////////////////// void setupSSG() { pinMode(SSG_DATA_PIN,OUTPUT); pinMode(SSG_CLOCK_PIN,OUTPUT); pinMode(SSG_ADDRESS_SELECT_PIN,OUTPUT); } #define SSG_ENVELOPE_SHAPE 0x0D void SSG_CPU_Interface::write(unsigned int data) { shiftOut(SSG_DATA_PIN, SSG_CLOCK_PIN, MSBFIRST, data); digitalWrite(writePin, LOW); digitalWrite(writePin, HIGH); } SSG_CPU_Interface::SSG_CPU_Interface(byte writePin) { this->writePin = writePin; memset( (void *)registers, 0, sizeof(registers) ); } void SSG_CPU_Interface::begin() { digitalWrite(writePin,HIGH); pinMode(writePin,OUTPUT); } void SSG_CPU_Interface::setByte(byte reg, byte data) { // Check carbon-copy before change byte *r = NULL; if( reg < SSG_ENVELOPE_SHAPE && *(r = registers + reg) == data ) return; // Data not changed or 0x0D(Envelope Shape) not specified - skip digitalWrite( SSG_ADDRESS_SELECT_PIN, LOW ); write( (unsigned int)reg ); digitalWrite( SSG_ADDRESS_SELECT_PIN, HIGH ); write( (unsigned int)data ); if( r != NULL ) *r = data; // Make carbon-copy } SSG::SSG(byte writePin) : SSG_CPU_Interface(writePin) { } void SSG::begin() { SSG_CPU_Interface::begin(); allMixerOff(); } // Tone Period (12bit) : 0x00 - 0x05 : f = 4MHz / (16 * TP) void SSG::setTonePeriod(byte channel, unsigned int tp12) { if( channel >= SSG_CHANNELS_PER_CHIP ) return; setByte(channel *= 2, lowByte(tp12)); setByte(++channel, highByte(tp12)); } // Noise Period (5bit) : 0x06 : f = 4MHz / (16 * NP) void SSG::setNoisePeriod(byte data) { setByte(0x06, data); } // // Mixer (6bit) : 0x07 // --NNNTTT ... Noise/Tone // --CBACBA ... channel : on:0 / off:1 void SSG::setMixer(byte channel, boolean isOn, boolean isNoise) { byte data = registers[0x07]; byte mask = (1<<( channel + (isNoise?3:0) )); if( isOn ) data &= ~mask; else data |= mask; setByte(0x07,data); } void SSG::allMixerOff() { setByte(0x07,0xFF); } // Volume (5bit) : 0x08 - 0x0A : xxxMLLLL // M: Envelope on:1 / off:0 // L: Volume( min:0 - max:15 ) void SSG::setVolume(byte channel, byte volume) { if( channel >= SSG_CHANNELS_PER_CHIP ) return; setByte(0x08+channel, volume); } void SSG::setVolume(byte volume) { byte reg, i; for( reg = 0x08, i = SSG_CHANNELS_PER_CHIP; i>0; reg++, i-- ) setByte(reg,volume); } // Envelope Period (16bit) : 0x0B - 0x0C : f = 4MHz / (256 * EP) void SSG::setEnvelopePeriod(unsigned int data) { setByte(0x0B, lowByte(data)); setByte(0x0C, highByte(data)); } // Envelope Shape (4bit) : 0x0D : -- -- -- -- CONT ATT ALT HOLD // This function re-starts counter of envelope generator void SSG::startEnvelope(byte data) { setByte(SSG_ENVELOPE_SHAPE, data); } void SSG::startEnvelope() { startEnvelope(registers[SSG_ENVELOPE_SHAPE]); }