Logo Search packages:      
Sourcecode: cbmlink version File versions  Download package

transnib.c

Go to the documentation of this file.
/**
 * @file transnib.c
 * Transfer routines for the 4-bit/4-bit PET/C64/C128/Vic-20 to Amiga cable
 * designed by Matt Francis (m.p.francis@newcastle.ac.uk)
 * @author Marko Mäkelä (msmakela@nic.funet.fi)
 * @author Olaf Seibert (rhialto@mbfys.kun.nl)
 */

/*
 * Copyright © 1994-1997 Marko Mäkelä and Olaf Seibert
 * Copyright © 2001 Marko Mäkelä
 * Original Linux and Commodore 64/128/Vic-20 version by Marko Mäkelä
 * Ported to the PET and the Amiga series by Olaf Seibert
 * Restructured by Marko Mäkelä
 * 
 *     This program is free software; you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation; either version 2 of the License, or
 *     (at your option) any later version.
 * 
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 * 
 *     You should have received a copy of the GNU General Public License
 *     along with this program; if not, write to the Free Software
 *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifdef COMM_AMIGA

# include "info.h"
# include "transnib.h"
# include "amigapar.h"

/** Open the communication channel
 * @param dev           name of the communication device
 * @param hostinfo      (output) the computer model information
 * @return        zero on success, nonzero on failure
 */
int
transnib_init (const char* dev, struct hostinfo* hostinfo)
{
  unsigned char detectbuf[5];
  if (alloc_port (0))
    return 1;
  /* set all lines to output high */
  DATA = 0xFF;
  DATA_DDR = 0xFF;
  if (transnib_write ("", 1))
    return 1;
  if (transnib_read (detectbuf, sizeof detectbuf))
    return 2;
  hostinfo->host = detectbuf[0];
  hostinfo->driver = (unsigned) detectbuf[1] | (unsigned) detectbuf[2] << 8;
  hostinfo->basic = (unsigned) detectbuf[3] | (unsigned) detectbuf[4] << 8;
  return 0;
}

/** Close the communication channel */
void
transnib_close (void)
{
  free_port ();
}

/** Send data
 * @param buf           the data to be sent
 * @param len           length of the data in bytes
 * @return        zero on success, nonzero on failure
 */
int
transnib_write (const void* buf, unsigned len)
{
  register const unsigned char* buffer = buf;

  /*
   * $40 is DRCV (input), $80 is DRDY (output) Note that the names are
   * swapped from receiving but the data direction isn't!
   */
  DATA_DDR = 0x8f;      /* set the bidirectional signals to output */

  while (len--) {
    register unsigned char nibble;
    register unsigned char data = *buffer++;
    nibble = data >> 4;

    DATA = nibble;            /* set DRDY low */
    while (DATA & 0x40)       /* wait for DRCV to go low */
      check_break ();
    DATA = nibble | 0x80;     /* set DRDY high */
    while (!(DATA & 0x40))    /* wait for DRCV to go high */
      check_break ();

    nibble = data & 0x0F;

    DATA = nibble;            /* set DRDY low */
    while (DATA & 0x40)       /* wait for DRCV to go low */
      check_break ();
    DATA = nibble | 0x80;     /* set DRDY high */
    while (!(DATA & 0x40))    /* wait for DRCV to go high */
      check_break ();
  }

  return 0;
}

/** Receive data
 * @param buf           the data to be received
 * @param len           length of the data in bytes
 * @return        zero on success, nonzero on failure
 */
int
transnib_read (void* buf, unsigned len)
{
  register unsigned char* buffer = buf;
  /*
   * $80 is DRCV (output), $40 is DRDY (input)
   */
  DATA_DDR = 0x80;            /* set the bidirectional signals to input */

  while (len--) {
    register unsigned char data;
    while (DATA & 0x40)       /* wait for DRDY to go low */
      check_break ();
    data = (DATA & 0x0f) << 4;      /* read the high nybble */
    DATA = 0x00;        /* set DRCV low */
    while (!(DATA & 0x40))    /* wait for DRDY to go high */
      check_break ();
    DATA = 0x80;        /* set DRCV high */

    while (DATA & 0x40)       /* wait for DRDY to go low */
      check_break ();
    data |= DATA & 0x0f;      /* read the low nybble */
    DATA = 0x00;        /* set DRCV low */
    while (!(DATA & 0x40))    /* wait for DRDY to go high */
      check_break ();
    DATA = 0x80;        /* set DRCV high */

    *buffer++ = data;
  }

  return 0;
}

#endif /* COMM_AMIGA */

Generated by  Doxygen 1.6.0   Back to index