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

prlink48.c

Go to the documentation of this file.
/**
 * @file prlink48.c
 * Amiga transfer routines for the 4-bit/8-bit PET/C64/C128/Vic-20
 * to Centronics cable designed by Marko Mäkelä
 * @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 "prlink48.h"
# include "amigapar.h"

# include <stdio.h>

/** current state of the BUSY line */
static unsigned char ack;

/** flag: debounce the ack line */
# define DEBOUNCE 1

/** 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
prlink48_init (const char* dev, struct hostinfo* hostinfo)
{
  unsigned char detectbuf[5];
  if (alloc_port (1))
    return 1;
  /* set all lines to output high */
  DATA = 0xFF;
  DATA_DDR = 0xFF;
  /* turn POUT into output high and BUSY into input */
  CTL |= POUT;
  CTL_DDR = (CTL_DDR | POUT) & ~BUSY;
  /* get the current state of the BUSY line */
  ack = CTL & BUSY;
  if (prlink48_write ("", 1))
    return 1;
  if (prlink48_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
prlink48_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
prlink48_write (const void* buf, unsigned len)
{
  register const unsigned char* buffer = buf;
  DATA_DDR = 0xFF;            /* set all lines to output */

  while (len--) {
    DATA = *buffer++;
    CTL &= ~POUT;       /* drop the -FLAG to low */
    while (ack == (BUSY & CTL))     /* wait for BUSY to change */
      check_break ();
    CTL |= POUT;        /* raise -FLAG again */
    ack ^= BUSY;        /* store the new state of -BUSY */
  }

  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
prlink48_read (void* buf, unsigned len)
{
  register unsigned char* buffer = buf;

  DATA_DDR = 0x00;            /* set all signals to input */

  while (len--) {
    register unsigned char data;
    CTL &= ~POUT;       /* drop the -FLAG to low */
# ifdef DEBOUNCE
  bounced1:
# endif /* DEBOUNCE */
    while (ack == (BUSY & CTL))     /* wait for BUSY to change */
      check_break ();
# ifdef DEBOUNCE
    /*
     * With the Amiga and (PET or 64) of Olaf Seibert, the ack line
     * needs debouncing.  With the 64 even more seriously.
     * Olaf is not sure why this is...
     */
    if (ack == (BUSY & CTL)) goto bounced1;
    if (ack == (BUSY & CTL)) goto bounced1;
# endif /* DEBOUNCE */
    CTL |= POUT;        /* raise -FLAG again */
    data = DATA & 0x0f;       /* read the low nibble */

    CTL &= ~POUT;       /* drop the -FLAG to low */
# ifdef DEBOUNCE
  bounced2:
# endif /* DEBOUNCE */
    while (ack != (BUSY & CTL))     /* wait for BUSY to change */
      check_break ();
# ifdef DEBOUNCE
    if (ack != (BUSY & CTL)) goto bounced2;
    if (ack != (BUSY & CTL)) goto bounced2;
# endif /* DEBOUNCE */

    CTL |= POUT;        /* raise -FLAG again */
    data |= (DATA & 0x0f) << 4;     /* read the high nibble */

    *buffer++ = data;
  }

  return 0;
}

#endif /* COMM_AMIGA */

Generated by  Doxygen 1.6.0   Back to index