/* Larkaud.c
LCS November 1, 1982 9:01 AM, other stuff
LCS, November 11, 1982 12:08 PM, CheckFromNet
LCS, December 7, 1982 1:24 PM, New relays
LCS, December 8, 1982 4:06 PM, dismiss command, LarkSlave refs
LCS, January 14, 1983 4:09 PM, Lark.mesa revisions
LCS, March 2, 1983 3:31 PM, Larkinitial connections
LCS, March 2, 1983 4:30 PM, bonsai
LCS, March 6, 1983 3:48 PM, FixedLeft
LCS, March 10, 1983 9:12 AM, flush wf
LCS, March 10, 1983 2:12 PM, flush xbar init
LCS, March 14, 1983 1:27 PM, SPMode
LCS, March 16, 1983 9:31 AM, AudioProcess moved to LarkNet
LCS, April 18, 1983 10:32 AM, new Lark
LCS, April 21, 1983 11:52 AM, correct key parity
LCS, May 21, 1983 6:40 PM, WhatIsStatus moved to LarkEventsImpl, WhatAreConnections implemented
LCS, May 24, 1983 4:22 PM, PleaseRegister
LCS May 27, 1983 4:08 PM, reorganized, echo suppression
LCS May 31, 1983 7:29 PM, CmdString bugs
LCS June 2, 1983 11:53 AM, net cleanup
LCS June 3, 1983 9:51 AM, SetIngain bug, Codec2 wasn't working
LCS June 5, 1983 5:37 PM, squelchTail, FirstPacket
LCS June 14, 1983 10:45 AM, EchoSuppression
LCS July 18, 1983 11:51 AM, SetHostNumber
LCS August 17, 1983 12:39 PM, parameterize
*/
#include "Lark.h"
#include "Env.h"
#include "RPC.h"
#include "LarkSlave.h"
#include "Queue.h"
#include "Encrypt.h"
#include "Pup.h"
#include "LarkNet.h"
#include "LarkVCB.h"
/* context package */
extern Block();
/* Allocate package */
extern FixedLeft();
/* Lark stuff */
extern InitAnalog();
extern SetIngain();
extern SetOutGain();
extern StartSlave();
extern PlayTone();
extern SetBufferTime();
extern SendPup();
extern Encrypt();
extern ReleasePBI();
extern int localHost;
extern int currentHost;
extern int localNet;
extern int wToneCB;
extern int totAv;
extern int lostTx;
extern struct VCB vcb[1];
extern int keyTable[64];
extern int SSilThresh;
extern int MaxSquelchTail;
extern int ajdelay;
extern int tooLate;
extern int tooEarly;
extern int adjustTooEarly;
extern int firstajdelay;
int bufferClockBad;
int zeroBufferTime;
int bufferPointer;
int bufferClock;
AudioStuff()
{
InitAnalog(); /* redundant, it is in InitOS, but restarts... */
InitNetStuff();
InitToneStuff();
SetIngain(3, 0)
SetOutGain(0)
SPMode(false);
StartSlave(1, 0);
bufferClockBad = 0;
};
InitNetStuff()
{
int i;
lostTx = 0;
SSilThresh = 576;
MaxSquelchTail = 20;
ajdelay = 10;
tooLate = 3;
tooEarly = 40;
adjustTooEarly = 10;
firstajdelay = 3;
for (i = 0; i < 5; i += 1) InitVCB(i);
SetBufferTime();
Zero(keyTable, 16 * lenEncryptionKey);
for (i = 0; i < 16; i += 1) {
CorrectParity(&keyTable[i]);
Block();
};
};
InitVCB(i)
int i;
{
int j;
struct VCB *p;
p = &vcb[i];
Zero(p, lenVCB);
switch (i) {
case IIn1: {
p->bufbase = InBuf1;
p->silVal = Sil1Val;
break;
};
case IIn2: {
p->bufbase = InBuf2;
p->silVal = Sil2Val;
break;
};
case IOut1: p->bufbase = OutBuf1; break;
case IOut2: p->bufbase = OutBuf2; break;
case IOut3: p->bufbase = OutBuf3; break;
default: return;
};
/* variable initialization, others are zero */
p->firstPacket = true;
p->silThresh = SSilThresh;
InitQueue(&p->vpq);
InitQueue(&p->pq);
p->pqlength = 0;
p->squelchTail = MaxSquelchTail;
/* all but destp and item */
p->loECB.next = 0;
p->loECB.srcp = p->bufbase;
p->loECB.encrypt = true;
p->loECB.count = 160;
p->loECB.proc = (int) &SendPup;
/* hiECB is just like it except for srcp */
MoveBlock(&p->hiECB, &p->loECB, lenECB);
p->hiECB.srcp = &p->bufbase[160];
/* floECB is just like it except . . . */
MoveBlock(&p->floECB, &p->loECB, lenECB);
p->floECB.srcp = &p->bufbase[264];
p->floECB.count = 56;
p->floECB.proc = (int) &Encrypt;
p->floECB.item = (int) &p->loECB;
/* fhiECB is just like it except . . . */
MoveBlock(&p->fhiECB, &p->loECB, lenECB);
p->fhiECB.srcp = &p->bufbase[104];
p->fhiECB.count = 216;
/* needs srcp, dstp, count, proc, item */
p->daECB.next = 0;
p->daECB.encrypt = false;
/* needs srcp, count, item */
MoveBlock(&p->dbECB, &p->daECB, lenECB);
p->dbECB.dstp = p->bufbase;
p->dbECB.proc = (int) &ReleasePBI;
/* other echo suppression fields set by the call to Zero */
p->decayTime = 5;
for (j = 0; j < 5; j += 1) p->gainTable[j] = 32767;
};
AudioProcess()
{
for (;;) {
Block();
PokeWDTC();
CheckBufferTime();
TryEcho();
FromNet();
};
};
/* compute the current [zeroBufferTime, bufferPointer] pair */
GetBufferTime()
{
int newbp;
newbp = *BufPtr;
/* 0 crossing test */
if (bufferPointer > newbp) zeroBufferTime += 40;
bufferPointer = newbp;
bufferClock = zeroBufferTime + (bufferPointer >> 3);
};
SetBufferTime()
{
bufferPointer = *BufPtr;
zeroBufferTime = ReadTmr() - (bufferPointer >> 3);
bufferClock = zeroBufferTime + (bufferPointer >> 3);
};
CheckBufferTime()
{
int diff;
GetBufferTime();
/* are bufferClock and ct close? */
diff = bufferClock - ReadTmr();
if ((diff < -2) || (diff > 2)) {
SetBufferTime();
bufferClockBad += 1;
};
};
AudCmd(p)
struct EvSeq *p;
{
int i;
int d, e;
if (p->length > 20) return;
for (i = 0; i < p->length; i += 1) {
Block();
d = p->evs[i].device;
e = p->evs[i].event;
Each(d, e);
};
};
static Each(d, e)
int d, e;
{
int on;
d &= 0x00ff;
e &= 0x00ff;
if (e == 144) on = true;
else on = false;
switch (d) {
case 4: PutC(0, e); break;
case 5: PutC(1, e); break;
case 8: Revert(on); break;
case 9: GoOffHook(on); break;
case 10: SideTone(on); break;
case 11: RingEnable(on); break;
case 12: Led(on); break;
case 13: XbarClear(); break;
case 14: SetTS(e); break;
case 15: SetVoice(e); break;
case 16: case 17:
case 18: case 19:
SetTable(d, e); break;
case 22: YXBar(e); break;
case 23: XXBar(e); break;
case 24: RevertHS(on); break;
case 25: ARelay(on); break;
case 27: { on = e; Dismiss(on * 10); break; };
case 28: SPMode(on); break;
default: break;
};
};
static SetTS(c)
char c;
{
if (c == 147) SetCodec(0);
if (c == 148) SetCodec(0x0c);
};
static YXBar(c)
char c;
{
ClearXbar(((c >> 4) & 0x0f), (c & 0x0f));
};
static XXBar(c)
char c;
{
SetXbar(((c >> 4) & 0x0f), (c & 0x0f));
};
SPMode(on)
int on;
{
int *modep;
modep = (int *) ModeFlag;
if (on) *modep |= 3;
else *modep &= 0xfffc;
};
static SetVoice(c)
char c;
{
switch (c) {
case 159: StartSlave(1, 0); break;
case 160: StartSlave(2, 0); break;
default: StartSlave(1, 0); break;
};
SetBufferTime();
};
static SetTable(d, e)
char d, e;
{
int table;
table = e - 149;
switch (d) {
case 16: SetIngain(0, table); break;
case 17: SetIngain(1, table); break;
case 18: SetOutGain(table); break;
case 19: SetOutGain(table); break;
default: break;
};
};
/* Actual calls via RPC */
struct ResetArgs {
int procType;
int isNil;
int length;
/* character array */
};
/* ropes are stored with only the length word */
int Reset(sp)
int *sp;
{
struct ShortSTRING *rName;
struct ResetArgs *ra;
ra = (struct ResetArgs *) sp;
if (ra->isNil) return(0); /* no results */
ra->length = Swab(ra->length);
ra->isNil = ra->length; /* fake presence of ROPE */
rName = (struct ShortSTRING *) &ra->isNil;
AudioStuff(); /* initialize */
totAv = FixedLeft();
return (0); /* no results */
};
struct GTArgs {
int procType;
int f1, f2, modulation, on, off;
int repetitions, waveTable, queueIt, notify;
};
int GenerateTones(sp)
int *sp;
{
struct GTArgs *ga;
int i;
ga = (struct GTArgs *) sp;
SwabInPlace(&ga->f1, 9);
i = PlayTone(ga->f1, ga->f2, ga->on, ga->off, ga->repetitions, ga->queueIt, ga->waveTable, ga->notify);
*sp = (i) ? swapped1: 0; /* boolean */
return (1); /* one result */
};
struct DiscArgs {
int procType;
int id;
};
int Disconnect(sp)
int *sp;
{
struct DiscArgs *da;
da = (struct DiscArgs *) sp;
StopNet(Swab(da->id));
return (0); /* no results */
};
extern int plsRegister;
extern int plsRegTimer;
int PleaseRegister(sp)
int *sp;
{
SetTmr(2000, &plsRegTimer);
plsRegister = true;
return (0); /* no results */
};
/*
struct WACArgs {
int procType;
int which;
};
*/
int WhatAreConnections(sp)
int *sp;
{
int which, i;
struct VCB *p;
struct CSpecs *c;
which = Swab(sp[1]);
sp += 2;
c = (struct CSpecs *) sp;
sp -= 2;
if ((which >= 0) || (which < 5)) {
for (i = which; i < 5; i += 1) {
p = &vcb[i];
if (p->active) {
sp[0] = Swab((i == 4) ? 0: i + 1);
sp[1] = 0; /* isNil = false */
c->proto = 0;
c->sampleRate = Swab(8000);
c->pktSize = Swab(160);
c->buffer = Swab(i);
c->keyIndex = Swab(p->encIndex);
MoveBlock(&c->lsoc[0], &p->lport, lenPort);
MoveBlock(&c->rsoc[0], &p->rport, lenPort);
return (13);
};
};
};
*sp++ = 0; /* next = 0 */
*sp++ = swapped1; /* isNil = true */
return (2); /* two words of results */
};
int WhatAreTones(sp)
int *sp
{
*sp = (wToneCB) ? swapped1: 0;
return (1);
};
/* argument structure
struct KeyArgs {
int procType;
int isNil;
int length[2];
int sequenceTag;
int keyArray[64];
};
*/
int SetKeyTable(sp)
int *sp
{
int i;
if (sp[1]) return(0); /* isnil */
for (i = 0; i < 64; i += 4) {
CorrectParity(sp + i + 5);
Block();
};
MoveBlock(keyTable, sp+5, 64);
return (0);
};
/* argument structure */
struct CmdStrArgs {
int procType;
int device;
int isNil;
int length;
char charArray[1];
};
int CommandString(sp)
int *sp
{
int i;
struct CmdStrArgs *ca;
struct ShortSTRING *evString;
ca = (struct CmdStrArgs *) sp;
if (ca->isNil) return(0); /* no results */
ca->length = Swab(ca->length); /* fix length */
ca->isNil = ca->length; /* fake presence of ROPE */
evString = (struct ShortSTRING *) &ca->isNil;
for (i = 0; i < evString->length; i += 1) {
Block();
Each(Swab(ca->device), evString->text[i]);
};
return (0);
};
int PleaseLogin(sp)
int *sp;
{
*sp = 0;
return(1);
};
struct EchoRec {
int procType;
int isNil;
int buffer;
int control;
int decayTime;
int gain[5];
};
int EchoSupression(sp)
int *sp;
{
struct EchoRec *erp;
struct VCB *p;
if (sp[1]) return(0); /* isnil */
erp = (struct EchoRec *) sp;
SwabInPlace(sp + 2, 8);
erp->buffer &= 07;
erp->control &= 03;
erp->decayTime &= 037;
if (erp->buffer > 4) return(0);
p = &vcb[erp->buffer];
p->gainChannel = erp->control;
p->decayTime = erp->decayTime;
p->lastEnergy = 0;
MoveBlock(&p->gainTable[0], &erp->gain[0], 5);
return(0);
};
struct SetHostRec {
int procType;
char net;
char host;
};
int SetHostNumber(sp)
int *sp;
{
struct SetHostRec *hrp;
int lh;
hrp = (struct SetHostRec *) sp;
lh = hrp->net;
lh &= 0x00ff;
if (lh == localNet) {
lh = hrp->host;
lh &= 0x00ff;
if (lh == 0) lh = localHost;
currentHost = lh;
NewHost();
};
return(0);
};