





[ 7.046099] spibmc spi1.1: spi link version 1.4
[ 7.046128] spibmc spi1.1: BMCboard default: do_conf=1, di_conf=1, daqbmc_conf=0
[ 7.046801] comedi comedi0: bmc protocol version 0.98
[ 7.046816] comedi comedi0: 4 cpu(s) online for threads
[ 7.046825] comedi comedi0: BMCBoard using chip select : 0x 1
[ 7.046833] comedi comedi0: BMCboard device detection started
[ 7.046847] comedi comedi0: Probing for PIC18Fx7Q84 DAQ device, SPI slave mode
[ 7.046856] comedi comedi0: BMCboard SPI setup: spi cs 1: 8000000 Hz: mode 0x3: probing for controller device PICSL12
[ 7.046866] comedi comedi0: 16 bit and less device buffers set to 16 bits
[ 7.048069] comedi comedi0: Calibration data downloaded from board
[ 7.049004] comedi comedi0: Calibration data downloaded from board
[ 7.049013] comedi comedi0: Analog Out channels 1, Analog In channels 16 : Q84 config code 0x0
[ 7.049021] comedi comedi0: PIC18F57Q84 DAQ device setup complete
[ 7.049027] comedi comedi0: DISPLAY, RS232/TTL and device serial TX/RX channels 8
[ 7.049033] comedi comedi0: Digital Out channels 16
[ 7.049039] comedi comedi0: Digital In channels 24
[ 7.049305] comedi comedi0: ao device thread start
[ 7.088331] comedi comedi0: driver 'daq_bmc' has successfully auto-configured 'BMCboard'.











That's nice! A little too much for me (I use PVC for home electrical, custom control boards and C programming instead of PLCs) but making your home like you want and are very familiar with) is the point.










static int32_t bmc_spi_packet(struct spi_device *spi, struct bmc_packet_type * packet, ktime_t slower)
{
int32_t ret = 0;
if (spi == NULL) {
ret = -ESHUTDOWN;
return ret;
}
spi_message_init_with_transfers(packet->m, &packet->one_t, 1); //one transfer per message
spi_bus_lock(spi->controller);
ret = spi_sync_locked(spi, packet->m);
spi_bus_unlock(spi->controller);
__set_current_state(TASK_INTERRUPTIBLE);
schedule_hrtimeout_range(&slower, 0, HRTIMER_MODE_REL_PINNED);
return ret;
}
static const uint32_t SPI_GAP_LONG = 12000; // time for the Q84 to process each received SPI byte
static int32_t bmc_spi_exchange(struct comedi_device *dev, struct bmc_packet_type * packet)
{
struct comedi_subdevice *s = dev->read_subdev;
struct spi_param_type *spi_data = s->private;
struct spi_device *spi = spi_data->spi;
int32_t ret = 0;
ktime_t slower = ns_to_ktime(SPI_GAP_LONG);
if (spi == NULL) {
ret = -ESHUTDOWN;
return ret;
}
/*
* use nine spi transfers for the complete SPI transaction
* we need the inter-byte processing time on the slave side
* with only a two byte FIFO on the Q84
*/
packet->one_t.speed_hz = spi->max_speed_hz;
/*
* send the cmd and 4-bit channel data
*/
packet->one_t.tx_buf = &packet->bmc_byte_t[BMC_CMD];
packet->one_t.rx_buf = &packet->bmc_byte_r[BMC_CMD];
packet->one_t.cs_change = false;
packet->one_t.len = 1;
ret = bmc_spi_packet(spi, packet, slower);
// more code
}
/*
* transfers one 16 bit value to the DAC device
*/
static void daqbmc_ao_put_sample(struct comedi_device *dev,
struct comedi_subdevice *s,
uint16_t value)
{
const struct daqbmc_board *board = dev->board_ptr;
struct daqbmc_private *devpriv = dev->private;
uint32_t chan, range;
struct bmc_packet_type *packet = kzalloc(sizeof(*packet), GFP_KERNEL | GFP_NOWAIT | GFP_ATOMIC | GFP_DMA);
if (!packet) {
return;
}
mutex_lock(&devpriv->drvdata_lock);
chan = devpriv->ao_chan & board->n_aochan_mask;
range = devpriv->ao_range;
/* use single transfer for all bytes of the complete SPI transaction */
packet->bmc_byte_t[BMC_CMD] = CMD_DAC_GO;
packet->bmc_byte_t[BMC_D0] = (uint8_t) (value & 0xff);
packet->bmc_byte_t[BMC_D1] = (uint8_t) ((value >> 8)&0xff);
packet->bmc_byte_t[BMC_D2] = (uint8_t) (value & 0xff);
packet->bmc_byte_t[BMC_D3] = BMC_D3;
packet->bmc_byte_t[BMC_D4] = BMC_D4;
packet->bmc_byte_t[BMC_EXT] = (uint8_t) range;
packet->bmc_byte_t[BMC_CKSUM] = CHECKBYTE;
packet->bmc_byte_t[BMC_DUMMY] = CHECKBYTE;
bmc_spi_exchange(dev, packet);
s->readback[chan] = value;
devpriv->ao_count++;
mutex_unlock(&devpriv->drvdata_lock);
smp_mb__after_atomic();
kfree(packet);
}



