Motherboard Software

The code on this page configures the crosspoint switches either for an individual chip, or globally by specifying row and column, starting at the top left. The code assumes use of the ISA interface detailed on this site. The listing below was written in Borland C. You can either copy and paste it, or download it by clicking here

 

#include "header.h"

#define ADDRESS 0x0300
#define HANDSHAKE 0x0301
#define PORTNUM 0


/////////////////////////////////////////////////////////////////////////

void reset_motherboard()
// resets all crosspoint switches to open by toggling the RESET line
{
  outportb(HANDSHAKE,0x80); // Use _outp for Visual C++

  delay(1);
  outportb(HANDSHAKE,0x00);
}
/////////////////////////////////////////////////////////////////////////

void setswitch(int state, unsigned char chip, unsigned int switchaddress)
// sets crosspoint switch to state at address switchaddress, chip no. chip
{
  unsigned char byte;
  // first set chip select latch
  byte = chip; // delay(1); // For fast buses a small delay may be necessary

  byte &= 0x0F;
  outportb(HANDSHAKE,byte); // delay(1);
  byte |= 0x10;
  outportb(HANDSHAKE,byte); // delay(1);
  byte &= 0x0F;
  outportb(HANDSHAKE,byte); // delay(1);

  // then set the correct switch address
  outportb(ADDRESS,switchaddress);

  // determine open or closed
  if (state == 1) // if switch to be closed...
    byte |= 0x40; // .. DATA line high

  // now strobe into relevant chip
  byte |= 0x20;
  outportb(HANDSHAKE,byte); // delay(1);
  byte &= 0xDF;
  outportb(HANDSHAKE,byte); // delay(1);
}
/////////////////////////////////////////////////////////////////////////

bool setrowcol(int state, int row, int col)
// sets up motherboard switches according to global row and column.
// row 0, col 0 are top left of the motherboard
// if there is no switch at the specified row/col, FALSE is returned
{
  int chip;
  unsigned int address;
  int x = 7 - col%8;
  int y;
  int offset = 0;

  // First determine correct chip
  if (!chip_no(row,col,&chip)) return FALSE;

  if ((col/8)%2) offset = 8;
  y = (row-offset)%16;

  // Now convert appropriate rows & cols to addresses for this chip 
  // using a lookup table
  address = _rotl(x,4);
  switch (y)
  {
    case 0 : address |= 0x0;break; case 8 : address |= 0xa;break;
    case 1 : address |= 0x1;break; case 9 : address |= 0xb;break;
    case 2 : address |= 0x2;break; case 10: address |= 0xc;break;
    case 3 : address |= 0x3;break; case 11: address |= 0xd;break;
    case 4 : address |= 0x4;break; case 12: address |= 0x6;break;
    case 5 : address |= 0x5;break; case 13: address |= 0x7;break;
    case 6 : address |= 0x8;break; case 14: address |= 0xe;break;
    case 7 : address |= 0x9;break; case 15: address |= 0xf;break;
  }
  setswitch (state, chip, address);
  return TRUE;
}
/////////////////////////////////////////////////////////////////////////
// CONVERSION ROUTINES
/////////////////////////////////////////////////////////////////////////

bool chip_no(int row, int col, int *chipno)
// gives chip no corresponding to a global row/col,
// returning FALSE if there is no chip.
{
  int chip=0;
  int xchip = col/8;
  int ychip;
  int offset = 0;
  // check for obvious illegal values;
  if ((row <0) || (col <0) || (row > 55) || (col > 47)) return FALSE;

  // Find correct chip
  if (xchip%2) offset = 8;
  ychip = (row-offset)/16;

  switch (xchip)
  {
    case (0): chip = (2 - ychip);
 	   if ((chip < 0) || (chip > 2)) return FALSE;
	    break;
    case (1): chip = (5 - ychip);
	    if ((chip < 3) || (chip > 5) || (row <8))
                return FALSE;
  	  break;
    case (2): chip = (8 - ychip);
	    if ((chip < 6) || (chip > 7))	return FALSE;
	    break;
    case (3):	chip = (10 - ychip);
	    if ((chip < 8) || (chip > 9))	return FALSE;
	    break;
    case (4):	chip = (12 - ychip);
	    if (chip != 10)	return FALSE;
	    break;
    case (5):	chip = (13 - ychip);
	    if (chip != 11)	return FALSE;
	    break;
  }
  *chipno = chip;
  return TRUE;
}
/////////////////////////////////////////////////////////////////////////

bool localrowcol_chipno(int row, int col,	int *lrow, int *lcol, int *chipno)
// gives chip no, and its local row & col nos for a given
// global row & col.
{
  int chip=0;
  int x = col%8;
  int y;
  int offset = 0;

  // First find correct chip
  if (!chip_no(row,col,&chip)) return FALSE;

  if ((col/8)%2) offset = 8;
  y = (row-offset)%16;

  *chipno = chip;*lrow = y; *lcol = x;
  return TRUE;
}
/////////////////////////////////////////////////////////////////////////

bool address_chipno(int row, int col, int *addr, int *chipno)
// gives chip no & address for a global row & col.
// row 0, col 0 are top left of diagram as drawn by routine in DRAWSTAT.C
// if there is no switch at the specified row/col, FALSE is returned
{
  unsigned int address=0;
  int chip=0;
  int xchip = col/8;
  int x = col%8;
  int ychip, y;
  int offset = 0;

  // First find correct chip
  if (!chip_no(row,col,&chip)) return FALSE;

  if ((col/8)%2) offset = 8;
  y = (row-offset)%16;


  // Now convert appropriate rows & cols to addresses for this chip
  address = _rotl(x,4);
  switch (y)
  {
    case 0 : address |= 0x0;break; case 8 : address |= 0xa;break;
    case 1 : address |= 0x1;break; case 9 : address |= 0xb;break;
    case 2 : address |= 0x2;break; case 10: address |= 0xc;break;
    case 3 : address |= 0x3;break; case 11: address |= 0xd;break;
    case 4 : address |= 0x4;break; case 12: address |= 0x6;break;
    case 5 : address |= 0x5;break; case 13: address |= 0x7;break;
    case 6 : address |= 0x8;break; case 14: address |= 0xe;break;
    case 7 : address |= 0x9;break; case 15: address |= 0xf;break;
  }
  *addr = address;*chipno = chip;
  return TRUE;
}
/////////////////////////////////////////////////////////////////////////

As for the higher level code in Visual Basic, email me for details as this is constantly changing