/* regtones.c L. Stewart October 10, 1983 3:17 PM */ #include "Lark.h" #include "Env.h" #include "LarkNet.h" #include "LarkSlave.h" #include "RegEPROM.h" extern int UDiv(); extern int DoubleUDiv(); extern MoveBlock(); extern int Sine(); extern STab06(); char *obuf1; char *obuf2; char *obuf3; char *inbuf1; int *bufptr; int *silVal1; int first; int audioMode; int gainTable[9]; int energies[64]; int epoint; int runSum[2]; struct SineCB { /* used by SineML.dsm to generate tones */ char *dest; int count, freq, sinetab; }; struct ToneCB { int f1, f2, totOn, totOff, this, active, sineTable, times; }; static int phase1, phase2; /* phase continuity */ static struct SineCB f1a, f1b, f2a, f2b; static struct ToneCB tcb; static struct ToneCB *wToneCB; InitToneStuff() { AudioIdle(); obuf1 = OutBuf1; obuf2 = OutBuf2; obuf3 = OutBuf3; inbuf1 = InBuf1; bufptr = BufPtr; silVal1 = Sil1Val; first = false; f1a.dest = obuf1; f1b.dest = &obuf1[160]; f2a.dest = obuf2; f2b.dest = &obuf2[160]; f1a.count = f1b.count = f2a.count = f2b.count = 160; wToneCB = 0; Zero(obuf1, 160); CheckWDT(); Zero(obuf2, 160); Zero(obuf3, 160); CheckWDT(); /* initialize gainTable */ FlushAverage(); gainTable[0] = 920 >> 1; /*11850 >> 1 2.5 dB */ gainTable[1] = 1560 >> 1; /*12850 >> 1 5 dB */ gainTable[2] = 2656 >> 1; /*13850 >> 1 7.5 dB */ gainTable[3] = 4630 >> 1; /*14850 >> 1 10 dB */ gainTable[4] = 8292 >> 1; /*15850 >> 1 12.5 dB */ gainTable[5] = 14320 >> 1; /*16850 >> 1 15 dB */ gainTable[6] = 24640 >> 1; /*17850 >> 1 17.5 dB */ gainTable[7] = 39000 >> 1; /*32767 >> 1 20 dB */ gainTable[8] = 65535 >> 1; /*32767 >> 1 20 dB */ }; FlushAverage() { epoint = 0; Zero(runSum, 2); Zero(energies, 64); }; DoEcho() { SPMode(false); audioMode = AMEcho; }; /* on and off are in milliseconds */ static int mf1, mf2; PlayDigit(d) int d; { switch (d) { case TT1: { mf1 = 697; mf2 = 1209; break; }; case TT2: { mf1 = 697; mf2 = 1336; break; }; case TT3: { mf1 = 697; mf2 = 1477; break; }; case TTa: { mf1 = 697; mf2 = 1633; break; }; case TT4: { mf1 = 770; mf2 = 1209; break; }; case TT5: { mf1 = 770; mf2 = 1336; break; }; case TT6: { mf1 = 770; mf2 = 1477; break; }; case TTb: { mf1 = 770; mf2 = 1633; break; }; case TT7: { mf1 = 852; mf2 = 1209; break; }; case TT8: { mf1 = 852; mf2 = 1336; break; }; case TT9: { mf1 = 852; mf2 = 1477; break; }; case TTc: { mf1 = 852; mf2 = 1633; break; }; case TT0: { mf1 = 941; mf2 = 1336; break; }; case TTst: { mf1 = 941; mf2 = 1209; break; }; case TTot: { mf1 = 941; mf2 = 1477; break; }; case TTd: { mf1 = 941; mf2 = 1633; break; }; default: return; }; PlayTone(mf1, mf2, 60, 60); }; static int FreqToFrac(freq) int freq; { int v[2]; v[1] = UDiv(freq,2); v[0] = (freq & 1) ? 0x8000: 0; /* 0 is 0 and 4000 is 08000H */ /* multiplier is freq * 32768/4000 */ return(DoubleUDiv(v, 4000)); }; AudioIdle() { audioMode = AMOff; }; /* f1 and f2 are in Hz on and off are times in milliseconds, either can be 0 */ int PlayTone(f1, f2, on, off) int f1, f2, on, off; { tcb.f1 = FreqToFrac(f1); tcb.f2 = FreqToFrac(f2); tcb.this = tcb.totOn = on/20; tcb.totOff = off/20; if ((on == 0) || (off == 0)) tcb.times = 1; else tcb.times = 2; tcb.active = true; tcb.sineTable = (int) &STab06; wToneCB = &tcb; audioMode = AMTone; SPMode(false); f1a.freq = f1b.freq = tcb.f1; f2a.freq = f2b.freq = tcb.f2; f1a.sinetab = f1b.sinetab = tcb.sineTable; f2a.sinetab = f2b.sinetab = tcb.sineTable; while (wToneCB) { TryEcho(); CheckWDT(); }; }; TryEcho() { if (!first && *bufptr >= 160) { if (audioMode != AMTone) Limit(); switch (audioMode) { case AMEcho: { CopyLow(); break; }; case AMTone: { ToneLow(); break; }; default: }; first = true; }; if (first && *bufptr < 160) { if (audioMode != AMTone) Limit(); switch (audioMode) { case AMEcho: { CopyHigh(); break; }; case AMTone: { ToneHigh(); break; }; default: }; first = false; }; }; static CopyLow() { MoveBlock(obuf1, inbuf1, 80); }; static CopyHigh() { MoveBlock(&obuf1[160], &inbuf1[160], 80); }; static ToneMode() { if (wToneCB == 0) return; if (wToneCB->times == 0) { wToneCB = 0; AudioIdle(); return; }; if (wToneCB->this == 1) wToneCB->times -= 1; if (wToneCB->this == 0) { if (wToneCB->active) { if (wToneCB->totOff > 0) wToneCB->active = false; }; else { if (wToneCB->totOn > 0) wToneCB->active = true; }; if (wToneCB->active) wToneCB->this = wToneCB->totOn; else wToneCB->this = wToneCB->totOff; }; else wToneCB->this -= 1; }; static ToneLow() { ToneMode(); if (wToneCB) { if (wToneCB->active) { phase1 = Sine(phase1, &f1a); phase2 = Sine(phase2, &f2a); }; }; }; static ToneHigh() { ToneMode(); if (wToneCB) { if (wToneCB->active) { phase1 = Sine(phase1, &f1b); phase2 = Sine(phase2, &f2b); }; }; }; Limit() { int i; int energy; energy = *silVal1 >> 1; DoubleDecrement(runSum, energies[epoint]); DoubleIncrement(runSum, energy); energies[epoint] = energy; epoint += 1; epoint &= 63; energy = DoubleUDiv(runSum, 64); for (i = 0; i < 8; i += 1) { if (energy < gainTable[i]) { SetIngain(3, i); return; }; }; SetIngain(3, 7); };