daily_automated
This commit is contained in:
420
trunk/Arduino/libraries/SID/SID.cpp
Normal file
420
trunk/Arduino/libraries/SID/SID.cpp
Normal file
@@ -0,0 +1,420 @@
|
||||
/*
|
||||
SID.cpp - Atmega8 MOS6581 SID Emulator
|
||||
Copyright (c) 2007 Christoph Haberer, christoph(at)roboterclub-freiburg.de
|
||||
Arduino Library Conversion by Mario Patino, cybernesto(at)gmail.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/************************************************************************
|
||||
|
||||
Atmega8 MOS6581 SID Emulator
|
||||
|
||||
SID = Sound Interface Device
|
||||
|
||||
This program tries to emulate the sound chip SID of the famous
|
||||
historical C64 Commodore computer.
|
||||
The SID emulator includes all registers of the original SID, but
|
||||
some functions may not be implemented yet.
|
||||
If you want to program the SID registers to generate your own sound,
|
||||
please refer to the MOS6581 datasheet. The emulator tries to be as
|
||||
compatible as possible.
|
||||
|
||||
In the main program there is an interrupt routine which sets the
|
||||
ouptut values for the PWM-Output at 62.5kHz. Therefore the high
|
||||
frequency noise of the PWM should not be audible to normal people.
|
||||
The output is calculated with a 16kHz sample frequency to save
|
||||
processing cycles.
|
||||
|
||||
The envelope generators are updated every 1ms.
|
||||
|
||||
The amplitude value is output as an 8Bit PWM value.
|
||||
The PWM-Output may be directly connected to an audio amplifier.
|
||||
|
||||
************************************************************************
|
||||
|
||||
Hardware
|
||||
|
||||
processor: ATMEGA8, ATMEGA168
|
||||
clock: 16MHz Crystal
|
||||
|
||||
PIN15 PB1/OC1A 8Bit PWM sound output
|
||||
PIN19 PB0 test LED
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include <avr/interrupt.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "SID.h"
|
||||
|
||||
// attack, decay, release envelope timings
|
||||
const static uint16_t AttackRate[16]={2,4,16,24,38,58,68,80,100,250,500,800,1000,3000,5000,8000};
|
||||
const static uint16_t DecayReleaseRate[16]={6,24,48,72,114,168,204,240,300,750,1500,2400,3000,9000,15000,24000};
|
||||
|
||||
static uint8_t output;
|
||||
static Sid_t Sid;
|
||||
static Oscillator_t osc[OSCILLATORS];
|
||||
|
||||
void initialize()
|
||||
{
|
||||
// TIMER1 used to generate sound output
|
||||
// TIMER1: Fast PWM 8-bit
|
||||
TCCR1A = (1 << WGM10) | (1 << COM1A1) ;
|
||||
// TIMER1: no prescaling
|
||||
TCCR1B = (1 << WGM12) | (1 << CS10);
|
||||
|
||||
#if defined(__AVR_ATmega8__)|| defined(__AVR_ATmega128__)
|
||||
// TIMER2 used to generate sample and ms interrupts
|
||||
// TIMER2: Normal Mode
|
||||
TCCR2 = 0;
|
||||
// TIMER2: clock/8 prescaling
|
||||
TCCR2 |= (1 << CS21);
|
||||
// TIMER2: set compare value to generate a 16kHz sample rate
|
||||
OCR2 = SAMPLERATECOUNT;
|
||||
// interrupt mask register: enable timer2 OCR2A interrupt
|
||||
TIMSK = (1 << OCIE2);
|
||||
|
||||
// interrupt mask register: enable timer1 overflow
|
||||
TIMSK |= (1 << TOIE1);
|
||||
#else
|
||||
// TIMER2 used to generate sample and ms interrupts
|
||||
// TIMER2: Normal Mode
|
||||
TCCR2A = 0 ;
|
||||
// TIMER2: clock/8 prescaling
|
||||
TCCR2B = (1 << CS21);
|
||||
// TIMER2: set compare value to generate a 16kHz sample rate
|
||||
OCR2A = SAMPLERATECOUNT;
|
||||
// interrupt mask register: enable timer2 OCR2A interrupt
|
||||
TIMSK2 = (1 << OCIE2A);
|
||||
|
||||
// interrupt mask register: enable timer1 overflow
|
||||
TIMSK1 = (1 << TOIE1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int8_t wave(Voice_t *voice, uint16_t phase)
|
||||
{
|
||||
int8_t out;
|
||||
uint8_t n = phase >> 8;
|
||||
uint8_t wavetype = voice->ControlReg;
|
||||
|
||||
if(wavetype & SAWTOOTH)
|
||||
{
|
||||
out = n - 128;
|
||||
}
|
||||
|
||||
if(wavetype & TRIANGLE)
|
||||
{
|
||||
if(n&0x80)
|
||||
out = ((n^0xFF)<<1)-128;
|
||||
else
|
||||
out = (n<<1)-128;
|
||||
}
|
||||
|
||||
if(wavetype & RECTANGLE)
|
||||
{
|
||||
if(n > (voice->PW >> 4)) // SID has 12Bit pwm, here we use only 8Bit
|
||||
out = 127;
|
||||
else
|
||||
out = -127;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static void waveforms()
|
||||
{
|
||||
static uint16_t phase[3], sig[3];
|
||||
static int16_t temp,temp1;
|
||||
static uint8_t i,j,k;
|
||||
static uint16_t noise = 0xACE1;
|
||||
static uint8_t noise8;
|
||||
static uint16_t tempphase;
|
||||
|
||||
// noise generator based on Galois LFSR
|
||||
noise = (noise >> 1) ^ (-(noise & 1) & 0xB400u);
|
||||
noise8 = noise>>8;
|
||||
|
||||
for(i = 0; i< 3; i++)
|
||||
{
|
||||
j = (i == 0 ? 2 : i - 1);
|
||||
tempphase=phase[i]+osc[i].freq_coefficient; //0.88us
|
||||
if(Sid.block.voice[i].ControlReg&NOISE)
|
||||
{
|
||||
if((tempphase^phase[i])&0x4000) sig[i]=noise8*osc[i].envelope;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(Sid.block.voice[i].ControlReg&RINGMOD)
|
||||
{
|
||||
if(phase[j]&0x8000)
|
||||
sig[i]=osc[i].envelope*-wave(&Sid.block.voice[i],phase[i]);
|
||||
else
|
||||
sig[i]=osc[i].envelope*wave(&Sid.block.voice[i],phase[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(Sid.block.voice[i].ControlReg&SYNC)
|
||||
{
|
||||
if(tempphase < phase[j])
|
||||
phase[i] = 0;
|
||||
}
|
||||
else
|
||||
sig[i]=osc[i].envelope*wave(&Sid.block.voice[i],phase[i]); //2.07us
|
||||
}
|
||||
}
|
||||
phase[i]=tempphase;
|
||||
}
|
||||
|
||||
// voice filter selection
|
||||
temp=0; // direct output variable
|
||||
temp1=0; // filter output variable
|
||||
if(Sid.block.RES_Filt&FILT1) temp1+=sig[0];
|
||||
else temp+=sig[0];
|
||||
if(Sid.block.RES_Filt&FILT2) temp1+=sig[1];
|
||||
else temp+=sig[1];
|
||||
if(Sid.block.RES_Filt&FILT3) temp1+=sig[2];
|
||||
else if(!(Sid.block.Mode_Vol&VOICE3OFF))temp+=sig[2]; // voice 3 with special turn off bit
|
||||
|
||||
//filterOutput = IIR2((struct IIR_filter*)&filter04_06, filterInput);
|
||||
//IIR2(filter04_06, temp1);
|
||||
k=(temp>>8)+128;
|
||||
k+=temp1>>10; // no real filter implemeted yet
|
||||
|
||||
output = k; // Output to PWM
|
||||
}
|
||||
|
||||
|
||||
static void envelopes()
|
||||
{
|
||||
uint8_t n;
|
||||
uint8_t controll_regadr[3]={4,11,18};
|
||||
// if gate is ONE then the attack,decay,sustain cycle begins
|
||||
// if gate switches to zero the sound decays
|
||||
for(n=0;n<OSCILLATORS;n++)
|
||||
{
|
||||
if(Sid.sidregister[controll_regadr[n]]&GATE) // if gate set then attack,decay,sustain
|
||||
{
|
||||
if(osc[n].attackdecay_flag)
|
||||
{ // if attack cycle
|
||||
osc[n].amp+=osc[n].m_attack;
|
||||
if(osc[n].amp>MAXLEVEL)
|
||||
{
|
||||
osc[n].amp=MAXLEVEL;
|
||||
osc[n].attackdecay_flag=false; // if level reached, then switch to decay
|
||||
}
|
||||
}
|
||||
else // decay cycle
|
||||
{
|
||||
if(osc[n].amp>osc[n].level_sustain)
|
||||
{
|
||||
osc[n].amp-=osc[n].m_decay;
|
||||
if(osc[n].amp<osc[n].level_sustain) osc[n].amp=osc[n].level_sustain;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else // if gate flag is not set then release
|
||||
{
|
||||
osc[n].attackdecay_flag=true; // at next attack/decay cycle start wiht attack
|
||||
if(osc[n].amp>0)
|
||||
{
|
||||
osc[n].amp-=osc[n].m_release;
|
||||
if(osc[n].amp<0) osc[n].amp=0;
|
||||
}
|
||||
}
|
||||
osc[n].envelope=osc[n].amp>>8;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
||||
interrupt routine timer 1 overflow
|
||||
- set PWM output
|
||||
|
||||
************************************************************************/
|
||||
ISR(TIMER1_OVF_vect)
|
||||
{
|
||||
OCR1A = output; // Output to PWM
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
|
||||
interrupt routine timer 2 16kHz
|
||||
- calculate waverform phases
|
||||
- calculate waveforms
|
||||
- calculate attack decay release (1kHz)
|
||||
|
||||
************************************************************************/
|
||||
#if defined(__AVR_ATmega8__)|| defined(__AVR_ATmega128__)
|
||||
ISR(TIMER2_COMP_vect)
|
||||
{
|
||||
static uint8_t mscounter = 0;
|
||||
OCR2 += SAMPLERATECOUNT; // Output to PWM
|
||||
waveforms(); //~22us
|
||||
|
||||
if(mscounter++ >= MSCOUNT)
|
||||
{
|
||||
envelopes(); //~16us
|
||||
mscounter = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
ISR(TIMER2_COMPA_vect)
|
||||
{
|
||||
static uint8_t mscounter = 0;
|
||||
OCR2A += SAMPLERATECOUNT; // Output to PWM
|
||||
waveforms(); //~36us
|
||||
|
||||
if(mscounter++ >= MSCOUNT)
|
||||
{
|
||||
envelopes(); //~16us
|
||||
mscounter = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Constructor /////////////////////////////////////////////////////////////////
|
||||
// Function that handles the creation and setup of instances
|
||||
|
||||
void SID::begin()
|
||||
{
|
||||
pinMode(9, OUTPUT);
|
||||
initialize();
|
||||
|
||||
//initialize SID-registers
|
||||
Sid.sidregister[6]=0xF0;
|
||||
Sid.sidregister[13]=0xF0;
|
||||
Sid.sidregister[20]=0xF0;
|
||||
|
||||
|
||||
// set all amplitudes to zero
|
||||
for(int n=0;n<OSCILLATORS;n++) {
|
||||
osc[n].attackdecay_flag=true;
|
||||
setenvelope(&Sid.block.voice[n]);
|
||||
osc[n].amp=0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Public Methods //////////////////////////////////////////////////////////////
|
||||
// Functions available in Wiring sketches, this library, and other libraries
|
||||
/************************************************************************
|
||||
|
||||
uint8_t set_sidregister(uint8_t regnum, uint8_t value)
|
||||
|
||||
The registers of the virtual SID are set by this routine.
|
||||
For some registers it is necessary to transform the SID-register
|
||||
values to some internal settings of the emulator.
|
||||
To select this registers and to start the calculation, the switch/
|
||||
case statement is used.
|
||||
For instance: If setting the SID envelope register, new attach, decay
|
||||
sustain times are calculated.
|
||||
If an invalid register is requested the returned value will be 0.
|
||||
|
||||
4.2007 ch
|
||||
|
||||
************************************************************************/
|
||||
uint8_t SID::set_register(uint8_t regnum, uint8_t value)
|
||||
{
|
||||
if(regnum>NUMREGISTERS-1)
|
||||
return 0;
|
||||
|
||||
Sid.sidregister[regnum]=value;
|
||||
|
||||
switch(regnum)
|
||||
{
|
||||
//voice1
|
||||
case 1:
|
||||
osc[0].freq_coefficient=(Sid.sidregister[0]+(Sid.sidregister[1]<<8))>>2;
|
||||
break;
|
||||
case 5: setenvelope(&Sid.block.voice[0]);break;
|
||||
case 6: setenvelope(&Sid.block.voice[0]);break;
|
||||
|
||||
//voice2
|
||||
case 8:
|
||||
osc[1].freq_coefficient=(Sid.sidregister[7]+(Sid.sidregister[8]<<8))>>2;
|
||||
break;
|
||||
case 12: setenvelope(&Sid.block.voice[1]);break;
|
||||
case 13: setenvelope(&Sid.block.voice[1]);break;
|
||||
|
||||
//voice3
|
||||
case 15:
|
||||
osc[2].freq_coefficient=(Sid.sidregister[14]+(Sid.sidregister[15]<<8))>>2;
|
||||
break;
|
||||
case 19: setenvelope(&Sid.block.voice[2]);break;
|
||||
case 20: setenvelope(&Sid.block.voice[2]);break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
||||
uint8_t get_sidregister(uint8_t regnum)
|
||||
|
||||
The registers of the virtual SID are read by this routine.
|
||||
If an invalid register is requested it returns zero.
|
||||
|
||||
************************************************************************/
|
||||
uint8_t SID::get_register(uint8_t regnum)
|
||||
{
|
||||
if(regnum>NUMREGISTERS-1)
|
||||
return 0;
|
||||
return Sid.sidregister[regnum];
|
||||
}
|
||||
|
||||
// Private Methods /////////////////////////////////////////////////////////////
|
||||
// Functions only available to other functions in this library
|
||||
|
||||
uint8_t SID::get_wavenum(Voice_t *voice)
|
||||
{
|
||||
uint8_t n;
|
||||
|
||||
if(voice==&Sid.block.voice[0]) n=0;
|
||||
if(voice==&Sid.block.voice[1]) n=1;
|
||||
if(voice==&Sid.block.voice[2]) n=2;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void SID::setfreq(Voice_t *voice,uint16_t freq)
|
||||
{
|
||||
uint32_t templong;
|
||||
uint8_t n;
|
||||
|
||||
n=get_wavenum(voice);
|
||||
|
||||
templong=freq;
|
||||
osc[n].freq_coefficient=templong*4000/SAMPLEFREQ;
|
||||
}
|
||||
|
||||
|
||||
void SID::setenvelope(Voice_t *voice)
|
||||
{
|
||||
uint8_t n;
|
||||
|
||||
n=get_wavenum(voice);
|
||||
osc[n].attackdecay_flag=true;
|
||||
|
||||
osc[n].level_sustain=(voice->SustainRelease>>4)*SUSTAINFACTOR;
|
||||
osc[n].m_attack=MAXLEVEL/AttackRate[voice->AttackDecay>>4];
|
||||
osc[n].m_decay=(MAXLEVEL-osc[n].level_sustain*SUSTAINFACTOR)/DecayReleaseRate[voice->AttackDecay&0x0F];
|
||||
osc[n].m_release=(osc[n].level_sustain)/DecayReleaseRate[voice->SustainRelease&0x0F];
|
||||
}
|
||||
|
||||
|
||||
120
trunk/Arduino/libraries/SID/SID.h
Normal file
120
trunk/Arduino/libraries/SID/SID.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
SID.h - Atmega8 MOS6581 SID Emulator
|
||||
Copyright (c) 2007 Christoph Haberer, christoph(at)roboterclub-freiburg.de
|
||||
Arduino Library Conversion by Mario Patino, cybernesto(at)gmail.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
// ensure this library description is only included once
|
||||
#ifndef SID_h
|
||||
#define SID_h
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#define NUMREGISTERS 29
|
||||
#define OSCILLATORS 3
|
||||
#define MAXLEVEL ( 0xFFFF / OSCILLATORS )
|
||||
#define SUSTAINFACTOR ( MAXLEVEL / 15 )
|
||||
|
||||
#define SAMPLEFREQ 16000L
|
||||
#define SAMPLERATECOUNT (F_CPU/(8*SAMPLEFREQ)-1)
|
||||
|
||||
#define ENVELOPE_FREQ 1000L
|
||||
#define MSCOUNT (SAMPLEFREQ/ENVELOPE_FREQ-1)
|
||||
|
||||
|
||||
// SID Registers
|
||||
#define VOICE1 0
|
||||
#define VOICE2 7
|
||||
#define VOICE3 14
|
||||
#define CONTROLREG 4
|
||||
#define ATTACKDECAY 5
|
||||
#define SUSTAINRELEASE 6
|
||||
|
||||
// SID voice control register bits
|
||||
#define GATE (1<<0)
|
||||
#define SYNC (1<<1)
|
||||
#define RINGMOD (1<<2)
|
||||
#define TEST (1<<3) // not implemented
|
||||
#define TRIANGLE (1<<4)
|
||||
#define SAWTOOTH (1<<5)
|
||||
#define RECTANGLE (1<<6)
|
||||
#define NOISE (1<<7)
|
||||
|
||||
// SID RES/FILT ( reg.23 )
|
||||
#define FILT1 (1<<0)
|
||||
#define FILT2 (1<<1)
|
||||
#define FILT3 (1<<2)
|
||||
// SID MODE/VOL ( reg.24 )
|
||||
#define VOICE3OFF (1<<7)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t Freq; // Frequency: FreqLo/FreqHi
|
||||
uint16_t PW; // PulseWidth: PW LO/HI only 12 bits used in SID
|
||||
uint8_t ControlReg; // NOISE,RECTANGLE,SAWTOOTH,TRIANGLE,TEST,RINGMOD,SYNC,GATE
|
||||
uint8_t AttackDecay; // bit0-3 decay, bit4-7 attack
|
||||
uint8_t SustainRelease; // bit0-3 release, bit4-7 sustain
|
||||
} Voice_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Voice_t voice[3];
|
||||
uint16_t FC; // not implemented
|
||||
uint8_t RES_Filt; // partly implemented
|
||||
uint8_t Mode_Vol; // partly implemented
|
||||
uint8_t POTX; // not implemented
|
||||
uint8_t POTY; // not implemented
|
||||
uint8_t OSC3_Random;// not implemented
|
||||
uint8_t ENV3; // not implemented
|
||||
} Blocks_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
Blocks_t block;
|
||||
uint8_t sidregister[NUMREGISTERS];
|
||||
} Sid_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t freq_coefficient;
|
||||
uint8_t envelope;
|
||||
uint16_t m_attack;
|
||||
uint16_t m_decay;
|
||||
uint16_t m_release;
|
||||
uint8_t attackdecay_flag;
|
||||
int16_t level_sustain;
|
||||
int16_t amp;
|
||||
} Oscillator_t;
|
||||
|
||||
// library interface description
|
||||
class SID
|
||||
{
|
||||
// user-accessible "public" interface
|
||||
public:
|
||||
void begin();
|
||||
uint8_t set_register(uint8_t regnum, uint8_t value);
|
||||
uint8_t get_register(uint8_t regnum);
|
||||
// library-accessible "private" interface
|
||||
private:
|
||||
uint8_t get_wavenum(Voice_t *voice);
|
||||
void setfreq(Voice_t *voice,uint16_t freq);
|
||||
void init_waveform(Voice_t *voice);
|
||||
void setenvelope(Voice_t *voice);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
146
trunk/Arduino/libraries/SID/examples/Noise/Noise.ino
Normal file
146
trunk/Arduino/libraries/SID/examples/Noise/Noise.ino
Normal file
@@ -0,0 +1,146 @@
|
||||
#include <SID.h>
|
||||
|
||||
/************************************************************************
|
||||
|
||||
Arduino controls an
|
||||
Atmega8 MOS6581 SID Emulator
|
||||
|
||||
( SID = Sound Interface Device )
|
||||
|
||||
This example sets a noise sound in the SID and changes the frequency
|
||||
from low to high.
|
||||
|
||||
This creates a kind of space sound as used in the 1980 games.
|
||||
|
||||
****************************************************************************
|
||||
|
||||
date authors version comment
|
||||
====== ====================== ======= ==============================
|
||||
2007 (ch) Christoph Haberer V1.0 First implemetation
|
||||
2012 Mario Patino V1.1 Ported to SID Library
|
||||
Versions:
|
||||
|
||||
V1.0
|
||||
- noise with variable frequency
|
||||
|
||||
V1.1
|
||||
- The SID chip is implemented as a library thus making the serial
|
||||
communication unnecessary
|
||||
|
||||
***************************************************************************/
|
||||
/***************************************************************************
|
||||
*
|
||||
* (c) 2007 Christoph Haberer, christoph(at)roboterclub-freiburg.de
|
||||
*
|
||||
***************************************************************************
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation version 2 of the License, *
|
||||
* If you extend the program please maintain the list of authors. *
|
||||
* If you want to use this software for commercial purposes and you *
|
||||
* don't want to make it open source, please contact the authors for *
|
||||
* licensing. *
|
||||
***************************************************************************/
|
||||
|
||||
#define C4_1 1,0x11,0,0x25, // C4 tone pitch
|
||||
#define OFF 0
|
||||
#define CONTROLREG 4 // SID control register address
|
||||
#define GATE (1<<0)
|
||||
|
||||
// waveforms
|
||||
#define SETNOISE_1 4,0x81,5,0xBB,6,0xAD, // SID register setup to create noise
|
||||
|
||||
|
||||
|
||||
SID mySid;
|
||||
|
||||
void setup() {
|
||||
digitalWrite(13, HIGH); //turn on debugging LED
|
||||
mySid.begin();
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
|
||||
void setwaveform_noise(uint8_t channel)
|
||||
|
||||
Set sid registers to create a noise waveform.
|
||||
The SID has 3 channels, which should be accesed according to this
|
||||
definition:
|
||||
|
||||
#define CHANNEL1 0
|
||||
#define CHANNEL2 7
|
||||
#define CHANNEL3 14
|
||||
|
||||
For noise sounds it makes sense to use only one channel, because
|
||||
using multiple channels gives almost no audible difference.
|
||||
|
||||
************************************************************************/
|
||||
void setwaveform_noise(uint8_t channel)
|
||||
{
|
||||
uint8_t dataset[]={SETNOISE_1 C4_1 0xFF};
|
||||
uint8_t n=0;
|
||||
|
||||
while(dataset[n]!=0xFF)
|
||||
{
|
||||
mySid.set_register(channel+dataset[n], dataset[n+1]);
|
||||
// register address, register content
|
||||
n+=2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
|
||||
void set_frequency(uint16_t pitch,uint8_t channel)
|
||||
|
||||
Set sid frequncy registers.
|
||||
|
||||
The pitch has to be:
|
||||
|
||||
pitch=16.77*frequency
|
||||
|
||||
The SID has 3 channels, which should be accesed according to this
|
||||
definition:
|
||||
|
||||
#define CHANNEL1 0
|
||||
#define CHANNEL2 7
|
||||
#define CHANNEL3 14
|
||||
|
||||
************************************************************************/
|
||||
// pitch=16.77*frequency
|
||||
void set_frequency(uint16_t pitch,uint8_t channel)
|
||||
{
|
||||
mySid.set_register(channel, pitch&0xFF); // low register adress
|
||||
mySid.set_register(channel+1, pitch>>8); // high register adress
|
||||
}
|
||||
|
||||
#define CHANNEL1 0
|
||||
|
||||
/************************************************************************
|
||||
|
||||
main loop
|
||||
|
||||
create space ship noise
|
||||
|
||||
************************************************************************/
|
||||
void loop()
|
||||
{
|
||||
uint16_t n;
|
||||
uint8_t flag,k;
|
||||
uint16_t soundindex=0;
|
||||
|
||||
setwaveform_noise(CHANNEL1);
|
||||
|
||||
for(k=0;k<10;k++) // ten times space ship noise
|
||||
{
|
||||
for(n=100;n<1000;n+=50)
|
||||
{
|
||||
set_frequency(n*17,CHANNEL1); // change noise generator frequency
|
||||
delay(50);// every 50ms
|
||||
}
|
||||
}
|
||||
mySid.set_register(CONTROLREG+CHANNEL1, OFF); // be quite SID!
|
||||
|
||||
while(1); // do nothing and loop forever
|
||||
}
|
||||
166
trunk/Arduino/libraries/SID/examples/RandomPitch/RandomPitch.ino
Normal file
166
trunk/Arduino/libraries/SID/examples/RandomPitch/RandomPitch.ino
Normal file
@@ -0,0 +1,166 @@
|
||||
#include <SID.h>
|
||||
|
||||
/************************************************************************
|
||||
|
||||
Arduino controls an
|
||||
Atmega8 MOS6581 SID Emulator
|
||||
by softare serial line
|
||||
|
||||
( SID = Sound Interface Device )
|
||||
|
||||
random sound pitch example
|
||||
|
||||
|
||||
|
||||
****************************************************************************
|
||||
|
||||
date authors version comment
|
||||
====== ====================== ======= ==============================
|
||||
2007 (ch) Christoph Haberer V1.0 First implementation
|
||||
2012 Mario Patino V1.1 Adapted for Arduino SID Library
|
||||
|
||||
Versions:
|
||||
|
||||
V1.0
|
||||
- 2 channel random pitch
|
||||
|
||||
V1.1
|
||||
- Adapted to work with the Arduino SID Library
|
||||
|
||||
***************************************************************************/
|
||||
/***************************************************************************
|
||||
*
|
||||
* (c) 2007 Christoph Haberer, christoph(at)roboterclub-freiburg.de
|
||||
*
|
||||
***************************************************************************
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation version 2 of the License, *
|
||||
* If you extend the program please maintain the list of authors. *
|
||||
* If you want to use this software for commercial purposes and you *
|
||||
* don't want to make it open source, please contact the authors for *
|
||||
* licensing. *
|
||||
***************************************************************************/
|
||||
#define OFF 0
|
||||
#define SETTRIANGLE_1 4,0x11,5,0xBB,6,0xAA,
|
||||
#define C4_1 1,0x11,0,0x25,
|
||||
#define CONTROLREG 4 // SID control register address
|
||||
|
||||
// waveforms
|
||||
#define SETNOISE_1 4,0x81,5,0xBB,6,0xAD, // SID register setup to create noise
|
||||
|
||||
SID mySid;
|
||||
|
||||
void setup() {
|
||||
digitalWrite(13, HIGH); //turn on debugging LED
|
||||
mySid.begin();
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
||||
void setwaveform_noise(uint8_t channel)
|
||||
|
||||
Set sid registers to create a noise waveform.
|
||||
The SID has 3 channels, which should be accesed according to this
|
||||
definition:
|
||||
|
||||
#define CHANNEL1 0
|
||||
#define CHANNEL2 7
|
||||
#define CHANNEL3 14
|
||||
|
||||
For noise sounds it makes sense to use only one channel, because
|
||||
using multiple channels gives almost no audible difference.
|
||||
|
||||
************************************************************************/
|
||||
void setwaveform_triangle(uint8_t channel)
|
||||
{
|
||||
uint8_t dataset[]={ SETTRIANGLE_1 C4_1 0xFF };
|
||||
// uint8_t dataset[]={SETNOISE_1 C4_1 0xFF};
|
||||
uint8_t n=0;
|
||||
|
||||
while(dataset[n]!=0xFF)
|
||||
{
|
||||
mySid.set_register(channel+dataset[n], dataset[n+1]);
|
||||
// register address, register content
|
||||
n+=2;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
||||
void set_frequency(uint16_t pitch,uint8_t channel)
|
||||
|
||||
Set sid frequncy registers.
|
||||
|
||||
The pitch has to be:
|
||||
|
||||
pitch=16.77*frequency
|
||||
|
||||
The SID has 3 channels, which should be accesed according to this
|
||||
definition:
|
||||
|
||||
#define CHANNEL1 0
|
||||
#define CHANNEL2 7
|
||||
#define CHANNEL3 14
|
||||
|
||||
************************************************************************/
|
||||
// pitch=16.77*frequency
|
||||
void set_frequency(uint16_t pitch,uint8_t channel)
|
||||
{
|
||||
mySid.set_register(channel, pitch&0xFF); // low register adress
|
||||
mySid.set_register(channel+1, pitch>>8); // high register adress
|
||||
}
|
||||
|
||||
uint8_t zufall()
|
||||
{
|
||||
static uint16_t startwert=0x0AA;
|
||||
|
||||
uint16_t temp;
|
||||
uint8_t n;
|
||||
|
||||
for(n=1;n<8;n++)
|
||||
{
|
||||
temp = startwert;
|
||||
startwert=startwert << 1;
|
||||
|
||||
temp ^= startwert;
|
||||
if ( ( temp & 0x4000 ) == 0x4000 )
|
||||
{
|
||||
startwert |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return (startwert);
|
||||
}
|
||||
#define CHANNEL1 0
|
||||
#define CHANNEL2 7
|
||||
#define CHANNEL3 14
|
||||
|
||||
/************************************************************************
|
||||
|
||||
main loop
|
||||
|
||||
create space ship noise
|
||||
|
||||
************************************************************************/
|
||||
void loop()
|
||||
{
|
||||
uint16_t n;
|
||||
uint8_t flag,k;
|
||||
uint16_t soundindex=0;
|
||||
|
||||
|
||||
|
||||
setwaveform_triangle(CHANNEL1);
|
||||
setwaveform_triangle(CHANNEL2);
|
||||
|
||||
while(1)
|
||||
{
|
||||
n=zufall()*8;
|
||||
set_frequency(n*17,CHANNEL1); // change noise generator frequency
|
||||
n=zufall()*2;
|
||||
set_frequency(n*17,CHANNEL2); // change noise generator frequency
|
||||
|
||||
delay(100);
|
||||
}
|
||||
}
|
||||
32
trunk/Arduino/libraries/SID/keywords.txt
Normal file
32
trunk/Arduino/libraries/SID/keywords.txt
Normal file
@@ -0,0 +1,32 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For Test
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
SID KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
set_register KEYWORD2
|
||||
get_register KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Instances (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
GATE LITERAL1
|
||||
SYNC LITERAL1
|
||||
RINGMOD LITERAL1
|
||||
TEST LITERAL1
|
||||
TRIANGLE LITERAL1
|
||||
SAWTOOTH LITERAL1
|
||||
RECTANGLE LITERAL1
|
||||
NOISE LITERAL1
|
||||
34
trunk/Arduino/libraries/SID/readme.txt
Normal file
34
trunk/Arduino/libraries/SID/readme.txt
Normal file
@@ -0,0 +1,34 @@
|
||||
MOS6581 SID Emulator Arduino Library
|
||||
|
||||
This library emulates the SID sound chip of the famous Commodore 64.
|
||||
It is based on the Atmega8 MOS6581 SID Emulator from Christoph Haberer.
|
||||
Library conversion and memory optimization by Mario Patino.
|
||||
|
||||
Installation
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
To install this library, just place this entire folder as a subfolder in your
|
||||
Arduino/lib/targets/libraries folder.
|
||||
|
||||
When installed, this library should look like:
|
||||
|
||||
Arduino/lib/targets/libraries/SID (this library's folder)
|
||||
Arduino/lib/targets/libraries/SID/SID.cpp (the library implementation file)
|
||||
Arduino/lib/targets/libraries/SID/SID.h (the library description file)
|
||||
Arduino/lib/targets/libraries/SID/keywords.txt (the syntax coloring file)
|
||||
Arduino/lib/targets/libraries/SID/examples (the examples in the "open" menu)
|
||||
Arduino/lib/targets/libraries/SID/readme.txt (this file)
|
||||
|
||||
Building
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
After this library is installed, you just have to start the Arduino application.
|
||||
You may see a few warning messages as it's built.
|
||||
|
||||
To use this library in a sketch, go to the Sketch | Import Library menu and
|
||||
select SID. This will add a corresponding line to the top of your sketch:
|
||||
#include <SID.h>
|
||||
|
||||
To stop using this library, delete that line from your sketch.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user