/* 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);
};