/* analog.c
   L. Stewart September 23, 1982  5:09 PM
   L. Stewart November 23, 1982  6:16 PM, invert LED
   L. Stewart December 2, 1982  7:58 PM, new relays
   L. Stewart February 7, 1983  8:00 PM, new monitor
   L. Stewart February 18, 1983  6:56 PM, GetBootSwitches
   L. Stewart February 23, 1983  10:13 AM, remove wdc
   L. Stewart February 23, 1983  2:55 PM, EnableInt change
   L. Stewart March 3, 1983  2:30 PM, read xbar state
 */

#include	"Env.h"
#include	"Lark.h"
#include	"LarkSlave.h"
#include	"ec.h"
#include	"LarkNet.h"

/* pioml */
extern PIOOn();
extern PIOOff();
extern SetPIO();
extern GetPIO();
extern SetCodec();

/* interrupts */
extern ReadIRR();
extern EnableInt();
/*
extern int wdc;
 */

/* runtime */
extern StoreW();
extern OutByte();

/* context */

int inAn;
char xBarState[8];
extern /* FORWARD */ myAlDInt();

InitAnalog()
  {
  int row, col;
  /* set up apio Port A, B, C0-3 Out, Port C4-7 In, mode 0 */
  OutByte(apioctl, 0x0088);
  /* initialize state of PIOML statics */
  SetPIO(0x00c0, iapioa);  /* both relays OFF */
  SetPIO(0x0000, iapiob);
  SetPIO(0x000c, iapioc);  /* no ring or sidetone */
  SetPIO(0x00e1, ipioa);  /* LED Off */
  SetPIO(0x0000, ipiob);  /* Host ID really */
  SetPIO(0x0030, ipioc);  /* both relays off */
  SetCodec(0x0c);   /* timeslot 13 */
  ResetAnalogInt();
  myAlDInt();		/* get it set correctly on initialization */
  /* Everyone silence */
  XbarClear();
  EnableInt(&myAlDInt, AlDTyp);
  };

myAlDInt()
  {
  inAn = 0;
  for (;;) {
    PIOOff(0x000f, iapioa);
    PIOOn(inAn, iapioa);
    ResetAnalogInt();
    if ((ReadIRR() & 0x0080) == 0) break;
    inAn += 1;
    if (inAn == 16) inAn = 0;
    };
  return(true);
  };

SetXbar(row, col)
  int row, col;
  {
  int r;
  if (row == 4) {
    for (r = 0; r < 8; r += 1) xbarcom(r, col, false);
    };
  else {
    if (xBarState[col] & 0x10) xbarcom(4, col, false);
    };
  xbarcom(row, col, true);
  };

ClearXbar(row, col)
  int row, col;
  {
  xbarcom(row, col, false);
  if (xBarState[col] == 0) xbarcom(4, col, true);
  };

static xbarcom(row, col, on)
  int row, col, on;
  {
  int data, clock, shift;
  if (on) {
    PIOOn(SwData, iapioc);
    xBarState[col] |= (1 << row);
    };
  else {
    PIOOff(SwData, iapioc);
    xBarState[col] &= ((1 << row) ↑ 0xff);
    };
  data = (col & 3) | ((row & 3) << 2);
  if (row < 4) shift = 0;
  else shift = 1;
  if (col >= 4) shift += 2;
  clock = (SwStb0 << shift);
  SetPIO(data, iapiob);
  SetPIO(clock + data, iapiob);
  SetPIO(data, iapiob);
  };

Revert(active)
  int active;
  {
  if (active) PIOOn(0x0080, iapioa);
  else PIOOff(0x0080, iapioa);
  };

GoOffHook(active)
  int active;
  {
  if (active) PIOOff(0x0040, iapioa);
  else PIOOn(0x0040, iapioa);
  };

ARelay(active)
  int active;
  {
  if (active) PIOOff(0x0010, ipioc);
  else PIOOn(0x0010, ipioc);
  };

RevertHS(active)
  int active;
  {
  if (active) PIOOn(0x0020, ipioc);
  else PIOOff(0x0020, ipioc);
  };

SideTone(active)
  int active;
  {
  if (active) PIOOff(0x0004, iapioc);
  else PIOOn(0x0004, iapioc);
  };

RingEnable(active)
  int active;
  {
  if (active) PIOOff(0x0008, iapioc);
  else PIOOn(0x0008, iapioc);
  };

int GetDTMF()
  {
  int i, digit;
  if (!(inAn & AIDTMF)) return(0);
  i = GetPIO(iapioc) >> 4;
  if ((i > 0) && (i < 10)) digit = i + '0';
  else switch (i) {
    case 0: digit = 'd'; break;
    case 10: digit = '0'; break;
    case 11: digit = '*'; break;
    case 12: digit = '#'; break;
    case 13: digit = 'a'; break;
    case 14: digit = 'b'; break;
    case 15: digit = 'c'; break;
    default: digit = 0;
    };
  return(digit);
  };

int ScanIn()
  {
  return(inAn);
  };

ResetAnalogInt()
  {
  PIOOff(0x0080, ipioa);
  PIOOn(0x0080, ipioa);
  };

Led(active)
  int active;
  {
  if (active) PIOOff(0x0040, ipioa);
  else PIOOn(0x0040, ipioa);
  };

KickWDT()
  {
  PIOOn(0x0008, ipioa);
  PIOOff(0x0008, ipioa);
  };

ResetEncInt()
  {
  PIOOff(0x0001, ipioa);
  PIOOn(0x0001, ipioa);
  };

/* 0 means default, 1 means O3I1, 2 means O2I2 */
StartSlave(prog, length)
  int prog, length;
  {
  int i;
  StoreW(prog, CodeLoc);
  StoreW(length, CodeLen);
  PIOOn(0x20, ipioa);
  for (i=0; i< 20; i+= 1);
  OutByte(dmamode, 0xc0);
  OutByte(dmasmsk, 0x00);
  PIOOff(0x20, ipioa);
  for (i=0; i< 20; i+= 1);
  if (prog != 0) {
    PIOOff(0x10, ipioa);
    PIOOn(0x10, ipioa);
    PIOOff(0x10, ipioa);
    };
  };

SetIngain(ch, gain)
  int ch, gain;
  {
  int v;
  switch (gain) {
    case 0: v = InTab00; break;
    case 1: v = InTab05; break;
    case 2: v = InTab10; break;
    case 3: v = InTab15; break;
    case 4: v = InTab20; break;
    default: v = InTab00;
    };
  if (ch & 1) StoreW(v, In1Gain);
  if (ch & 2) StoreW(v, In2Gain);
  };

SetOutgain(gain)
  int gain;
  {
  int v;
  switch (gain) {
    case 0: v = OutTab00; break;
    case 1: v = OutTab03; break;
    case 2: v = OutTab06; break;
    default: v = OutTab00;
    };
  StoreW(v, OutGain);
  };

XbarClear()
  {
  int row, col;
  for (col = 0; col < 8; col += 1) {
    for (row = 0; row < 8; row += 1) xbarcom(row, col, false);
    xbarcom(4, col, true);
    };
  };

int GetBootSwitches()
  {
  int i;
  i = (GetPIO(ipiob) >> 6) & 3;
  return (i + (GetPIO(ipioc) & 4));
  };

char *GetXBarState()
  {
  return (xBarState);
  };