1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-02-07 00:27:10 +00:00
Files
Gehstock.Mist_FPGA/common/Sound/opl3/fw/TEST.H
2020-05-16 06:42:10 +02:00

347 lines
8.6 KiB
C

#define delay(x) Sleep(x)
const //List of FNumbers
uint16_t FNr[12] = {
/*C*/ 343,
/*C#/Db*/ 363,
/*D*/ 385,
/*D#/Eb*/ 408,
/*E*/ 432,
/*F*/ 458,
/*F#/Gb*/ 485,
/*G*/ 514,
/*G#/Ab*/ 544,
/*A*/ 577,
/*A#/Bb*/ 611,
/*B*/ 647 };
//Flat Whole Sharp}
#define C 0
#define CSharp 1
#define DFlat 1
#define D 2
#define DSharp 3
#define EFlat 3
#define E 4
#define F 5
#define FSharp 6
#define GFlat 6
#define G 7
#define GSharp 8
#define AFlat 8
#define A 9
#define ASharp 10
#define BFlat 10
#define B 11
struct Operator {
uint8_t
//Tremolo
Tremolo,
//Vibrato
Vibrato,
//Envelop generator type
EGType,
//KSR
KSR,
//Frequency multiplier
Multi,
//Key scaling level
KSL,
//Volume
TotalLevel,
//Shape of the wave envelop
Attack, Decay, Sustain, Release,
//Type of wave
WaveShape;
};
struct Instrument {
struct Operator Modulator, Carrier;
uint8_t
//Feedback strength
Feedback,
//Synthesis type
SynType;
};
struct Instrument Flute, Piano, Harp;
uint8_t CurNote, CurBlock;
/**************************************************************************
** Writes a value to a specified index register on the FM card **
**************************************************************************/
void WriteFM(uint8_t Register, uint8_t Value)
{
OPL3Write(0, Register);
OPL3Write(1, Value);
// unsigned char Counter;
//Select register
// outportb(0x388, Register);
//Wait for card to accept value
// for (Counter = 1; Counter < 25; Counter++) { inportb(0x388); }
//Send value
// outportb(0x389, Value);
//Wait for card to accept value
// for (Counter = 1; Counter < 100; Counter++) { inportb(0x388); }
}
/**************************************************************************
** Checks for the presence of an FM card **
**************************************************************************/
uint8_t FMInstalled()
{
// unsigned char A, B;
// WriteFM(1, 0);
// WriteFM(4, 0x60);
// WriteFM(4, 0x80);
// A = inportb(0x388);
// A = OPL3Read(0);
// WriteFM(2, 0xFF);
// WriteFM(4, 0x21);
// B = inportb(0x388);
// OPL3TimerOver(0);
// B = OPL3Read(0);
// WriteFM(4, 0x60);
// WriteFM(4, 0x80);
// if ((A & 0xE0) == 0 && (B & 0xE0) == 0xC0) {
return (1);
// }
// else {
// return (0);
// }
}
/**************************************************************************
** Activates a voice on the FM card **
***************************************************************************
** Voice selects one of the 9 FM voices **
** FNumber selects the note to be played **
** Block selects the octave for the specified note **
**************************************************************************/
void NoteOn(uint8_t Voice, uint8_t Note, uint8_t Block)
{
WriteFM(0xA0 + Voice, FNr[Note] & 0xFF);
WriteFM(0xB0 + Voice, (FNr[Note] >> 8) + (Block << 2) + 32);
}
/**************************************************************************
** Deactivates a voice on the FM card **
***************************************************************************
** Make sure to give the same values for Note and Block or this will **
** sound very odd. **
**************************************************************************/
void NoteOff(uint8_t Voice, uint8_t Note, uint8_t Block)
{
WriteFM(0xA0 + Voice, FNr[Note] & 0xFF);
WriteFM(0xB0 + Voice, (FNr[Note] >> 8) + (Block << 2));
}
/**************************************************************************
** Sets instrument settings for a voice on the FM card **
**************************************************************************/
const static unsigned char OpAdr[9] = { 0, 1, 2, 8, 9, 10, 16, 17, 18 }; //Addresses of the operators used to form voice data
void SetInstrument(uint8_t Voice, struct Instrument *Instr)
{
uint8_t Value;
//Set up voice modulator
Value = Instr->Modulator.Tremolo << 8
| Instr->Modulator.Vibrato << 7
| Instr->Modulator.EGType << 6
| Instr->Modulator.KSR << 5
| Instr->Modulator.Multi;
WriteFM(0x20 + OpAdr[Voice], Value);
Value = Instr->Modulator.KSL << 7
| Instr->Modulator.TotalLevel;
WriteFM(0x40 + OpAdr[Voice], Value);
Value = Instr->Modulator.Attack << 4
| Instr->Modulator.Decay;
WriteFM(0x60 + OpAdr[Voice], Value);
Value = Instr->Modulator.Sustain << 4
| Instr->Modulator.Release;
WriteFM(0x80 + OpAdr[Voice], Value);
WriteFM(0xE0 + OpAdr[Voice], Instr->Modulator.WaveShape);
Value = Instr->Feedback << 1
| Instr->SynType;
WriteFM(0xC0 + OpAdr[Voice], Value);
//Set up voice carrier
Value = Instr->Carrier.Tremolo << 8
| Instr->Carrier.Vibrato << 7
| Instr->Carrier.EGType << 6
| Instr->Carrier.KSR << 5
| Instr->Carrier.Multi;
WriteFM(0x23 + OpAdr[Voice], Value);
Value = Instr->Carrier.KSL << 7
| Instr->Carrier.TotalLevel;
WriteFM(0x43 + OpAdr[Voice], Value);
Value = Instr->Carrier.Attack << 4
| Instr->Carrier.Decay;
WriteFM(0x63 + OpAdr[Voice], Value);
Value = Instr->Carrier.Sustain << 4
| Instr->Carrier.Release;
WriteFM(0x83 + OpAdr[Voice], Value);
WriteFM(0xE3 + OpAdr[Voice], Instr->Carrier.WaveShape);
}
void test()
{
// clrscr();
again:
printf("Demonstration of programming a FM sound card [AdLib, SB and compatibles]\n");
printf("--------------------------------------------------------------------------\n");
//Check to see if an FM sound card is present
/* if (FMInstalled()) {
printf("AdLib/SB or compatible FM sound card found.\n");
}
else {
//If not, end the programme
printf("AdLib/SB or compatible FM sound card not found.\n");
return;
}
*/
//Set up voices 0 - 3 to a "harp" - note, only the values other than 0 are set
Harp.Modulator.Attack = 15;
Harp.Modulator.Decay = 5;
Harp.Modulator.Sustain = 8;
Harp.Modulator.Release = 5;
Harp.Modulator.Multi = 2;
Harp.Modulator.TotalLevel = 41;
Harp.Carrier.Attack = 15;
Harp.Carrier.Decay = 2;
Harp.Carrier.Release = 3;
Harp.Carrier.Multi = 1;
Harp.Carrier.KSL = 2;
Harp.Carrier.TotalLevel = 3;
SetInstrument(0, &Harp);
SetInstrument(1, &Harp);
SetInstrument(2, &Harp);
//Play C chord using Harp
printf("Playing C chord.\n");
NoteOn(0, C, 4);
NoteOn(1, E, 4);
NoteOn(2, G, 4);
delay(1000); //Wait 1 second
NoteOff(0, C, 4);
NoteOff(1, E, 4);
NoteOff(2, G, 4);
//Wait a while
delay(500);
//Set up voice 3 to a "piano" - this doesn't really sound like a piano,
//but that's what they call it!
Piano.Modulator.Attack = 15;
Piano.Modulator.Decay = 1;
Piano.Modulator.Sustain = 10;
Piano.Modulator.Release = 3;
Piano.Modulator.Multi = 1;
Piano.Modulator.KSL = 1;
Piano.Modulator.TotalLevel = 16;
Piano.Carrier.Attack = 13;
Piano.Carrier.Decay = 2;
Piano.Carrier.Sustain = 8;
Piano.Carrier.Release = 4;
Piano.Carrier.Multi = 1;
Piano.Carrier.TotalLevel = 0;
Piano.Carrier.KSR = 1;
Piano.Feedback = 3;
SetInstrument(3, &Piano);
//Play all notes in octave 4 for .1 seconds using piano [voice 3]
printf("Playing all notes in octave four.\n");
CurBlock = 4;
for (CurNote = 0; CurNote < 12; CurNote++) {
NoteOn(3, CurNote, CurBlock);
delay(100); //Wait .1 seconds
NoteOff(3, CurNote, CurBlock);
}
//Wait a while
delay(500);
//Set up voice 4 to a "flute"
Flute.Modulator.Attack = 6;
Flute.Modulator.Decay = 14;
Flute.Modulator.Sustain = 7;
Flute.Modulator.Release = 15;
Flute.Modulator.Vibrato = 1;
Flute.Modulator.Tremolo = 1;
Flute.Modulator.EGType = 1;
Flute.Modulator.KSL = 3;
Flute.Modulator.TotalLevel = 44;
Flute.Carrier.Attack = 6;
Flute.Carrier.Decay = 5;
Flute.Carrier.Sustain = 13;
Flute.Carrier.Release = 10;
Flute.Carrier.Vibrato = 1;
Flute.Carrier.EGType = 1;
Flute.Carrier.Multi = 1;
Flute.Carrier.TotalLevel = 0;
Flute.Feedback = 7;
Flute.SynType = 3;
SetInstrument(4, &Flute);
//Play short tune using Flute [voice 4] as primary, Harp [voice 0] as secondary voice
printf("Playing short tune.\n");
NoteOn(4, C, 5); NoteOn(0, C, 3);
delay(250);
NoteOff(4, C, 5);
NoteOn(4, E, 5);
delay(250);
NoteOff(4, E, 5); NoteOff(0, C, 3);
NoteOn(4, C, 5); NoteOn(0, G, 3);
delay(250);
NoteOff(4, C, 5);
NoteOn(4, G, 4);
delay(250);
NoteOff(4, G, 4); NoteOff(0, G, 3);
NoteOn(4, E, 4); NoteOn(0, C, 4);
delay(250);
NoteOff(4, E, 4);
NoteOn(4, G, 4);
delay(250);
NoteOff(4, G, 4); NoteOff(0, C, 4);
NoteOn(4, E, 4); NoteOn(0, G, 3);
delay(250);
NoteOff(4, E, 4);
NoteOn(4, D, 4);
delay(250);
NoteOff(4, D, 4); NoteOff(0, G, 3);
NoteOn(4, C, 4); NoteOn(0, C, 3);
delay(2000);
NoteOff(4, C, 4); NoteOff(0, C, 3);
goto again;
}