Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/comedi/drivers/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 7 kB image not shown  

Quelle  c6xdigio.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0+
/*
 * c6xdigio.c
 * Hardware driver for Mechatronic Systems Inc. C6x_DIGIO DSP daughter card.
 * http://web.archive.org/web/%2A/http://robot0.ge.uiuc.edu/~spong/mecha/
 *
 * COMEDI - Linux Control and Measurement Device Interface
 * Copyright (C) 1999 Dan Block
 */


/*
 * Driver: c6xdigio
 * Description: Mechatronic Systems Inc. C6x_DIGIO DSP daughter card
 * Author: Dan Block
 * Status: unknown
 * Devices: [Mechatronic Systems Inc.] C6x_DIGIO DSP daughter card (c6xdigio)
 * Updated: Sun Nov 20 20:18:34 EST 2005
 *
 * Configuration Options:
 * [0] - base address
 */


#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/timex.h>
#include <linux/timer.h>
#include <linux/io.h>
#include <linux/pnp.h>
#include <linux/comedi/comedidev.h>

/*
 * Register I/O map
 */

#define C6XDIGIO_DATA_REG 0x00
#define C6XDIGIO_DATA_CHAN(x) (((x) + 1) << 4)
#define C6XDIGIO_DATA_PWM BIT(5)
#define C6XDIGIO_DATA_ENCODER BIT(6)
#define C6XDIGIO_STATUS_REG 0x01
#define C6XDIGIO_CTRL_REG 0x02

#define C6XDIGIO_TIME_OUT 20

static int c6xdigio_chk_status(struct comedi_device *dev, unsigned long context)
{
 unsigned int status;
 int timeout = 0;

 do {
  status = inb(dev->iobase + C6XDIGIO_STATUS_REG);
  if ((status & 0x80) != context)
   return 0;
  timeout++;
 } while  (timeout < C6XDIGIO_TIME_OUT);

 return -EBUSY;
}

static int c6xdigio_write_data(struct comedi_device *dev,
          unsigned int val, unsigned int status)
{
 outb_p(val, dev->iobase + C6XDIGIO_DATA_REG);
 return c6xdigio_chk_status(dev, status);
}

static int c6xdigio_get_encoder_bits(struct comedi_device *dev,
         unsigned int *bits,
         unsigned int cmd,
         unsigned int status)
{
 unsigned int val;

 val = inb(dev->iobase + C6XDIGIO_STATUS_REG);
 val >>= 3;
 val &= 0x07;

 *bits = val;

 return c6xdigio_write_data(dev, cmd, status);
}

static void c6xdigio_pwm_write(struct comedi_device *dev,
          unsigned int chan, unsigned int val)
{
 unsigned int cmd = C6XDIGIO_DATA_PWM | C6XDIGIO_DATA_CHAN(chan);
 unsigned int bits;

 if (val > 498)
  val = 498;
 if (val < 2)
  val = 2;

 bits = (val >> 0) & 0x03;
 c6xdigio_write_data(dev, cmd | bits | (0 << 2), 0x00);
 bits = (val >> 2) & 0x03;
 c6xdigio_write_data(dev, cmd | bits | (1 << 2), 0x80);
 bits = (val >> 4) & 0x03;
 c6xdigio_write_data(dev, cmd | bits | (0 << 2), 0x00);
 bits = (val >> 6) & 0x03;
 c6xdigio_write_data(dev, cmd | bits | (1 << 2), 0x80);
 bits = (val >> 8) & 0x03;
 c6xdigio_write_data(dev, cmd | bits | (0 << 2), 0x00);

 c6xdigio_write_data(dev, 0x00, 0x80);
}

static int c6xdigio_encoder_read(struct comedi_device *dev,
     unsigned int chan)
{
 unsigned int cmd = C6XDIGIO_DATA_ENCODER | C6XDIGIO_DATA_CHAN(chan);
 unsigned int val = 0;
 unsigned int bits;

 c6xdigio_write_data(dev, cmd, 0x00);

 c6xdigio_get_encoder_bits(dev, &bits, cmd | (1 << 2), 0x80);
 val |= (bits << 0);

 c6xdigio_get_encoder_bits(dev, &bits, cmd | (0 << 2), 0x00);
 val |= (bits << 3);

 c6xdigio_get_encoder_bits(dev, &bits, cmd | (1 << 2), 0x80);
 val |= (bits << 6);

 c6xdigio_get_encoder_bits(dev, &bits, cmd | (0 << 2), 0x00);
 val |= (bits << 9);

 c6xdigio_get_encoder_bits(dev, &bits, cmd | (1 << 2), 0x80);
 val |= (bits << 12);

 c6xdigio_get_encoder_bits(dev, &bits, cmd | (0 << 2), 0x00);
 val |= (bits << 15);

 c6xdigio_get_encoder_bits(dev, &bits, cmd | (1 << 2), 0x80);
 val |= (bits << 18);

 c6xdigio_get_encoder_bits(dev, &bits, cmd | (0 << 2), 0x00);
 val |= (bits << 21);

 c6xdigio_write_data(dev, 0x00, 0x80);

 return val;
}

static int c6xdigio_pwm_insn_write(struct comedi_device *dev,
       struct comedi_subdevice *s,
       struct comedi_insn *insn,
       unsigned int *data)
{
 unsigned int chan = CR_CHAN(insn->chanspec);
 unsigned int val = (s->state >> (16 * chan)) & 0xffff;
 int i;

 for (i = 0; i < insn->n; i++) {
  val = data[i];
  c6xdigio_pwm_write(dev, chan, val);
 }

 /*
 * There are only 2 PWM channels and they have a maxdata of 500.
 * Instead of allocating private data to save the values in for
 * readback this driver just packs the values for the two channels
 * in the s->state.
 */

 s->state &= (0xffff << (16 * chan));
 s->state |= (val << (16 * chan));

 return insn->n;
}

static int c6xdigio_pwm_insn_read(struct comedi_device *dev,
      struct comedi_subdevice *s,
      struct comedi_insn *insn,
      unsigned int *data)
{
 unsigned int chan = CR_CHAN(insn->chanspec);
 unsigned int val;
 int i;

 val = (s->state >> (16 * chan)) & 0xffff;

 for (i = 0; i < insn->n; i++)
  data[i] = val;

 return insn->n;
}

static int c6xdigio_encoder_insn_read(struct comedi_device *dev,
          struct comedi_subdevice *s,
          struct comedi_insn *insn,
          unsigned int *data)
{
 unsigned int chan = CR_CHAN(insn->chanspec);
 unsigned int val;
 int i;

 for (i = 0; i < insn->n; i++) {
  val = c6xdigio_encoder_read(dev, chan);

  /* munge two's complement value to offset binary */
  data[i] = comedi_offset_munge(s, val);
 }

 return insn->n;
}

static void c6xdigio_init(struct comedi_device *dev)
{
 /* Initialize the PWM */
 c6xdigio_write_data(dev, 0x70, 0x00);
 c6xdigio_write_data(dev, 0x74, 0x80);
 c6xdigio_write_data(dev, 0x70, 0x00);
 c6xdigio_write_data(dev, 0x00, 0x80);

 /* Reset the encoders */
 c6xdigio_write_data(dev, 0x68, 0x00);
 c6xdigio_write_data(dev, 0x6c, 0x80);
 c6xdigio_write_data(dev, 0x68, 0x00);
 c6xdigio_write_data(dev, 0x00, 0x80);
}

static const struct pnp_device_id c6xdigio_pnp_tbl[] = {
 /* Standard LPT Printer Port */
 {.id = "PNP0400", .driver_data = 0},
 /* ECP Printer Port */
 {.id = "PNP0401", .driver_data = 0},
 {}
};

static struct pnp_driver c6xdigio_pnp_driver = {
 .name = "c6xdigio",
 .id_table = c6xdigio_pnp_tbl,
};

static int c6xdigio_attach(struct comedi_device *dev,
      struct comedi_devconfig *it)
{
 struct comedi_subdevice *s;
 int ret;

 ret = comedi_request_region(dev, it->options[0], 0x03);
 if (ret)
  return ret;

 ret = comedi_alloc_subdevices(dev, 2);
 if (ret)
  return ret;

 /*  Make sure that PnP ports get activated */
 pnp_register_driver(&c6xdigio_pnp_driver);

 s = &dev->subdevices[0];
 /* pwm output subdevice */
 s->type  = COMEDI_SUBD_PWM;
 s->subdev_flags = SDF_WRITABLE;
 s->n_chan = 2;
 s->maxdata = 500;
 s->range_table = &range_unknown;
 s->insn_write = c6xdigio_pwm_insn_write;
 s->insn_read = c6xdigio_pwm_insn_read;

 s = &dev->subdevices[1];
 /* encoder (counter) subdevice */
 s->type  = COMEDI_SUBD_COUNTER;
 s->subdev_flags = SDF_READABLE | SDF_LSAMPL;
 s->n_chan = 2;
 s->maxdata = 0xffffff;
 s->range_table = &range_unknown;
 s->insn_read = c6xdigio_encoder_insn_read;

 /*  I will call this init anyway but more than likely the DSP board */
 /*  will not be connected when device driver is loaded. */
 c6xdigio_init(dev);

 return 0;
}

static void c6xdigio_detach(struct comedi_device *dev)
{
 comedi_legacy_detach(dev);
 pnp_unregister_driver(&c6xdigio_pnp_driver);
}

static struct comedi_driver c6xdigio_driver = {
 .driver_name = "c6xdigio",
 .module  = THIS_MODULE,
 .attach  = c6xdigio_attach,
 .detach  = c6xdigio_detach,
};
module_comedi_driver(c6xdigio_driver);

MODULE_AUTHOR("Comedi https://www.comedi.org");
MODULE_DESCRIPTION("Comedi driver for the C6x_DIGIO DSP daughter card");
MODULE_LICENSE("GPL");

Messung V0.5
C=95 H=93 G=93

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.