/* LarkTones.c L. Stewart October 26, 1982 6:52 PM L. Stewart, December 7, 1982 1:56 PM, tone event L. Stewart, December 8, 1982 3:56 PM, silent DTMF code, LarkSlave addrs L. Stewart, January 17, 1983 3:47 PM, Lark.mesa revisions L. Stewart, April 23, 1983 6:07 PM, some cleanup L. Stewart, June 2, 1983 11:50 AM, some cleanup L. Stewart, June 6, 1983 12:46 PM, new sinetables */ #include "Lark.h" #include "Env.h" #include "LarkNet.h" #include "LarkSlave.h" #include "Queue.h" extern int UDiv(); extern int DoubleUDiv(); extern MoveBlock(); extern int Sine(); extern InitQueue(); extern Enqueue(); extern ToNet(); extern STab06(); extern STab09(); extern STab12(); extern STab15(); extern STab18(); int lastHalf; extern int toneDone; /* sinewave tables */ int sTables[5]; struct SineCB { /* used by SineML.dsm to generate tones */ char *dest; int count, freq, sinetab; }; struct ToneCB { struct ToneCB *next; int f1, f2, totOn, totOff, this, active, sineTable, times, notify; }; extern struct ToneCB *Dequeue(); static int phase1, phase2; /* phase continuity */ static struct SineCB f1a, f1b, f2a, f2b; static struct Queue toneQ, toneFreeQ; static struct ToneCB tcb[20]; struct ToneCB *wToneCB; extern int bufferPointer; InitToneStuff() { int i; InitQueue(&toneQ); InitQueue(&toneFreeQ); wToneCB = 0; lastHalf = false; for (i = 0; i < 20; i += 1) Enqueue(&toneFreeQ, &tcb[i]); f1a.dest = OutBuf1; f1b.dest = OutBuf1+160; f2a.dest = OutBuf2; f2b.dest = OutBuf2+160; f1a.count = f1b.count = f2a.count = f2b.count = 160; sTables[0] = (int) &STab06; sTables[1] = (int) &STab09; sTables[2] = (int) &STab12; sTables[3] = (int) &STab15; sTables[4] = (int) &STab18; }; /* on and off are in milliseconds, pass queue argument to playtone on first digit, then pass true */ LocPlayDTMF(d, on, off, queue, tab, notify) char d; int on, off, queue, tab, notify; { int mf1, mf2; switch (d) { case '1': { mf1 = 697; mf2 = 1209; break; }; case '2': { mf1 = 697; mf2 = 1336; break; }; case '3': { mf1 = 697; mf2 = 1477; break; }; case 'A': { mf1 = 697; mf2 = 1633; break; }; case '4': { mf1 = 770; mf2 = 1209; break; }; case '5': { mf1 = 770; mf2 = 1336; break; }; case '6': { mf1 = 770; mf2 = 1477; break; }; case 'B': { mf1 = 770; mf2 = 1633; break; }; case '7': { mf1 = 852; mf2 = 1209; break; }; case '8': { mf1 = 852; mf2 = 1336; break; }; case '9': { mf1 = 852; mf2 = 1477; break; }; case 'C': { mf1 = 852; mf2 = 1633; break; }; case '0': { mf1 = 941; mf2 = 1336; break; }; case '*': { mf1 = 941; mf2 = 1209; break; }; case '#': { mf1 = 941; mf2 = 1477; break; }; case 'D': { mf1 = 941; mf2 = 1633; break; }; default: { mf1 = 0; mf2 = 0; break; }; }; PlayTone(mf1, mf2, on, off, 1, queue, tab, notify); }; 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)); }; /* f1 and f2 are in Hz on and off are times in milliseconds, either can be 0 times is the number of repititions if (queue) enqueue; else flushqueue and enqueue stIndex is the index into the table of available sine tables */ int PlayTone(f1, f2, on, off, times, queue, stIndex, notify) int f1, f2, on, off, times, queue, stIndex, notify; { struct ToneCB *t, *tt; int dontBother; dontBother = false; t = Dequeue(&toneFreeQ); if (t == 0) return(false); t->f1 = FreqToFrac(f1); t->f2 = FreqToFrac(f2); t->this = t->totOn = on/20; /* start with on cycle */ t->totOff = off/20; t->notify = ((notify >> 8) == 26) ? notify: 0; t->times = ((on == 0) || (off == 0)) ? times: times << 1; t->active = true; t->sineTable = sTables[stIndex]; if (!queue) { for (;;) { tt = Dequeue(&toneQ); if (tt) Enqueue(&toneFreeQ, tt); else break; }; if (tt = wToneCB) { wToneCB = 0; Enqueue(&toneFreeQ, tt); }; }; if ((t->totOn == 0) && (t->totOff == 0)) dontBother = true; if (t->times == 0) dontBother = true; if (dontBother) Enqueue(&toneFreeQ, t); else Enqueue(&toneQ, t); return(true); }; TryEcho() { if (!lastHalf && (bufferPointer >= 160)) { ToneMode(); if (wToneCB) { if (wToneCB->active) { phase1 = Sine(phase1, &f1a); phase2 = Sine(phase2, &f2a); }; }; ToNet(); lastHalf = true; }; if (lastHalf && (bufferPointer < 160)) { ToneMode(); if (wToneCB) { if (wToneCB->active) { phase1 = Sine(phase1, &f1b); phase2 = Sine(phase2, &f2b); }; }; ToNet(); lastHalf = false; }; }; static ToneMode() { if (wToneCB == 0) { if (wToneCB = Dequeue(&toneQ)) { f1a.freq = f1b.freq = wToneCB->f1; f2a.freq = f2b.freq = wToneCB->f2; f1a.sinetab = f1b.sinetab = f2a.sinetab = f2b.sinetab = wToneCB->sineTable; }; }; else { if (wToneCB->times == 0) { toneDone = wToneCB->notify; Enqueue(&toneFreeQ, wToneCB); wToneCB = Dequeue(&toneQ); if (wToneCB) { f1a.freq = f1b.freq = wToneCB->f1; f2a.freq = f2b.freq = wToneCB->f2; f1a.sinetab = f1b.sinetab = f2a.sinetab = f2b.sinetab = wToneCB->sineTable; }; }; }; if (wToneCB) { if (wToneCB->this == 1) wToneCB->times -= 1; /* should not be 0! */ if (wToneCB->this == 0) { /* done with whatever */ if (wToneCB->active && wToneCB->totOff > 0) { wToneCB->active = false; }; else { if (!wToneCB->active && wToneCB->totOn > 0) wToneCB->active = true; }; wToneCB->this = (wToneCB->active) ? wToneCB->totOn: wToneCB->totOff; }; else wToneCB->this -= 1; }; };