/* testworld.c   September 23, 1982  6:05 PM   */

#include "lark.h"
#include "Encrypt.h"
#include "LarkSlave.h"
#include "env.h"

extern int Crypt(), EncEnd();  /* encryption */

struct ccb {
  char cmd;
  char *addr;
  char count;
  char stat;
  };

struct ECB cbea, cbeb, cbd, cbdleft;  /* encryption control blocks */
struct ccb outccb, inccb;  /* ethernet control blocks */

char expsn;  /* expected serial number */
int lastic;  /* outgoing serial number */
int lasto;   /* next speaker buffer index to use */
char key[8]; /* encryption key */
char ibuf[256], obuf[256];  /* ether buffers */
int *clock, oclock;

/* audio variables */
char *inbuf1, *obuf1, *obuf2, *obuf3;
int *ingain1, *outgain, *bufptr, *silval1;

/* program variables */
int first;  /* =0 when next packet to send is first half mike buffer */
int etherb; /* ethernet active boolean */
int audiob; /* audio active boolean */
int desb;   /* encryption active boolean */
int valid;  /* for local loopback, indicates valid ibuf */

/*  Test DMA encryption */

main()
  {
  char c;
  wf("\rWorld test.\r");
  initworld();
  for (;;) {
    checktx(); /* transmit, if done */
    if (!audiob) fakeclock();
    if (etherb) checkrx();
    else checkpkt();
    if (chav()) {
      c = getchar() & 0177;
      switch (c) {
        case 'a': togaudio(); break;
        case 'e': together(); break;
        case 'd': togdes(); break;
        case 'r': initworld(); break;
        default: putchar(c);
        };
      };
    };
  };

togaudio()
  {
  wf("audio ");
  if (audiob) audiob = 0;
  else audiob = 1;
  printb(audiob);
  if (audiob) {
    outbyte(pioa, 0x0000);
    audon();
    };
  else outbyte(pioa, 0x0020);
  };

together()
  {
  wf("ether ");
  if (etherb) etherb = 0;
  else etherb = 1;
  printb(etherb);
  if (etherb) {
    inccb.count = 0;
    slrstart(&inccb);
    };
  else slcinit(0x0055);
  };

fakeclock()
  {
  int nclock;
  nclock = *clock;
  if (nclock != oclock) {
    *bufptr = (*bufptr + ((nclock-oclock) << 3)) % 320;
    oclock = nclock;
    };
  };

togdes()
  {
  wf("des ");
  if (desb) desb = 0;
  else desb = 1;
  printb(desb);
  if (desb) {
    cbea.kp = key;
    cbeb.kp = key;
    cbd.kp = key;
    cbdleft.kp = key;
    };
  else {
    cbea.kp = 0;
    cbeb.kp = 0;
    cbd.kp = 0;
    cbdleft.kp = 0;
    };
  };

printb(b)
  int b;
  {
  if (b) wf("ON\r");
  else wf("OFF\r");
  };

checktx()
  {
  if (first == 0 && bptr() >= 160) {
    Crypt(&cbea);
    first = 1;
    txone();
    };
  if (first != 0 && bptr() < 160) {
    Crypt(&cbeb);
    first = 0;
    txone();
    };
  };

txone()
  {
  obuf[5] = lastic;
  lastic += 1;
  outccb.count = 166;
  encw();
  if (etherb) {
    sltstart(&outccb);
    waitccb(&outccb);
    };
  else {
    ByteBlt(ibuf, obuf, 166);
    valid = 1;
    };
  };

checkrx()
  {
  if (!(inccb.stat & 0x80)) return;
  if (inccb.stat != 0x88) {
    inccb.count = 0;
    slrstart(&inccb);
    return;
    };
  if (ibuf[4] != 0x98) {
    inccb.count = 0;
    slrstart(&inccb);
    return;
    };
  rxone();
  expsn += 1;
  inccb.count = 0;
  slrstart(&inccb);
  };

checkpkt()
  {
  if (valid) {
    rxone();
    expsn +=1;
    valid = 0;
    };
  };

rxone()
  {
  /* lost packet, start at current point plus 10 milliseconds */
  if (ibuf[5] != expsn) {
    /* must round to multiple of 8 due to block encryption */
    lasto = (bptr() & 0xfff8) + 80;
    /* wrap around !  can't be more than 80 too big */
    expsn = ibuf[5];
    };
  /* decryption is potentially two parts, due to buffer wraparound */
  if (lasto >= 320) lasto %= 320;
  cbd.dstp = &obuf1[lasto];
  if (lasto < 160) cbd.count = 160;
  else cbd.count = 320 - lasto;
  Crypt(&cbd);
  lasto += 160;
  encw();
  if (cbd.count < 160) {
    lasto = 160 - cbd.count;
    cbdleft.srcp = &ibuf[cbd.count+6];
    cbdleft.count = lasto;
    Crypt(&cbdleft);
    encw();
    };
  if (lasto >= 320) lasto %= 320;
  };

encw()
  {
  if (desb) while(!EncEnd());
  };

audon()
  {
  inbuf1 = InBuf1;
  obuf1 = OutBuf1;
  obuf2 = OutBuf2;
  obuf3 = OutBuf3;
  ingain1 = In1Gain;
  outgain = OutGain;
  bufptr = BufPtr;
  silval1 = Sil1Val;
  InitAnalog();
  SetInGain(3, 0)
  SetOutGain(0)
  SetXbar(0, 3);
  SetXbar(3, 0);
  StartSlave(0, 0);
  first = 0; /* first xmit packet will be low half */
  };

ReadIRR() {};
int AlDInt;
EnableInt() {};

nullproc()
  {
  };

EncMore()
  {
  };

Block()
  {
  };

initworld()
  {
  int i;
  clock = clklo;
  audiob = 1;  /* audio on */
  audon();
  etherb = 0;  /* ether off */
  desb = 0;  /* des off */
  valid = 0; /* no rx packet ready */
  lasto = 0; /* first buffer address at beginning of buffer */
  expsn = 25;  /* random number */
  /* packet header */
  obuf[0] = 0x55; /* both from and to ourselves */
  obuf[1] = 0x55;
  obuf[2] = 0x01;
  obuf[3] = 0xC0;
  obuf[4] = 0x98;  /* seal */
  obuf[5] = 0x00; /* sequence number */
  inccb.cmd = 0x00;  /* rx */
  inccb.addr = ibuf;
  outccb.cmd = 0x50; /* tx */
  outccb.addr = obuf;
  lastic = 1; /* first tx sequence number = 1 */
  for (i=0; i<8; i++) key[i] = 0x01;  /* random key with odd byte parity */
  slcinit(0x0055);
  togdes(); /* turn on des, also sets up key fields of cbs */
  /* cbea is the first half of the mike buffer */
  cbea.srcp = &inbuf1[0];
  cbeb.srcp = &inbuf1[160];
  /* both encrypt into data part of packet */
  cbea.dstp = &obuf[6];
  cbeb.dstp = &obuf[6];
  cbea.count = 160;
  cbeb.count = 160;
  cbea.encrypt = true;
  cbeb.encrypt = true;
  cbea.proc = (int) &nullproc;
  cbeb.proc = (int) &nullproc;
  /* cbd is the first part of decryption */
  cbd.srcp = &ibuf[6];
  cbdleft.dstp = &obuf1[0];
  cbd.encrypt = false;
  cbdleft.encrypt = false;
  cbd.proc = (int) &nullproc;
  cbdleft.proc = (int) &nullproc;
  wf("g\r");
  };

int bptr()
  {
  return(*bufptr);
  };