All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.diozero.internal.provider.pigpioj.PigpioJSpiDevice Maven / Gradle / Ivy

There is a newer version: 1.4.1
Show newest version
package com.diozero.internal.provider.pigpioj;

/*
 * #%L
 * Device I/O Zero - pigpioj provider
 * %%
 * Copyright (C) 2016 mattjlewis
 * %%
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 * #L%
 */

import java.nio.ByteBuffer;

import org.pmw.tinylog.Logger;

import com.diozero.api.SpiClockMode;
import com.diozero.internal.provider.AbstractDevice;
import com.diozero.internal.provider.DeviceFactoryInterface;
import com.diozero.internal.provider.SpiDeviceInterface;
import com.diozero.util.RuntimeIOException;

import uk.pigpioj.PigpioInterface;

public class PigpioJSpiDevice extends AbstractDevice implements SpiDeviceInterface {
	private static final int CLOSED = -1;
	
	private PigpioInterface pigpioImpl;
	private int handle = CLOSED;
	private int controller;
	private int chipSelect;

	public PigpioJSpiDevice(String key, DeviceFactoryInterface deviceFactory, PigpioInterface pigpioImpl,
			int controller, int chipSelect, int frequency, SpiClockMode spiClockMode, boolean lsbFirst)
			throws RuntimeIOException {
		super(key, deviceFactory);
		
		this.pigpioImpl = pigpioImpl;
		this.controller = controller;
		this.chipSelect = chipSelect;
		
		int flags = createSpiFlags(spiClockMode, controller, lsbFirst);
		int rc = pigpioImpl.spiOpen(chipSelect, frequency, flags);
		if (rc < 0) {
			handle = CLOSED;
			throw new RuntimeIOException(String.format("Error opening SPI device on controller %d, chip-select %d, response: %d",
					Integer.valueOf(controller), Integer.valueOf(chipSelect), Integer.valueOf(rc)));
		}
		handle = rc;
		Logger.debug("SPI device ({}-{}) opened, handle={}", Integer.valueOf(controller),
				Integer.valueOf(chipSelect), Integer.valueOf(handle));
	}
	
	@Override
	public void write(ByteBuffer out) {
		if (! isOpen()) {
			throw new IllegalStateException("SPI Device " + controller + "-" + chipSelect + " is closed");
		}
		
		int count = out.remaining();
		byte[] tx = new byte[count];
		int rc = pigpioImpl.spiWrite(handle, tx, count);
		if (rc < 0) {
			throw new RuntimeIOException("Error calling pigpioImpl.write(), response: " + rc);
		}
	}

	@Override
	public ByteBuffer writeAndRead(ByteBuffer out) throws RuntimeIOException {
		if (! isOpen()) {
			throw new IllegalStateException("SPI Device " + controller + "-" + chipSelect + " is closed");
		}
		
		int count = out.remaining();
		byte[] tx = new byte[count];
		out.get(tx);
		byte[] rx = new byte[count];
		int rc = pigpioImpl.spiXfer(handle, tx, rx, count);
		if (rc < 0) {
			throw new RuntimeIOException("Error calling pigpioImpl.spiXfer(), response: " + rc);
		}
		
		return ByteBuffer.wrap(rx);
	}

	@Override
	public int getController() {
		return controller;
	}

	@Override
	public int getChipSelect() {
		return chipSelect;
	}

	@Override
	public boolean isOpen() {
		return handle >= 0;
	}

	@Override
	protected void closeDevice() throws RuntimeIOException {
		int rc = pigpioImpl.spiClose(handle);
		handle = CLOSED;
		if (rc < 0) {
			throw new RuntimeIOException("Error calling pigpioImpl.spiClose(), response: " + rc);
		}
	}
	
	/**
	 * 21 20 19 18 17 16 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
	 *  b  b  b  b  b  b  R  T  n  n  n  n  W  A u2 u1 u0 p2 p1 p0  m  m
	 * mm defines the SPI mode.
	 * Warning: modes 1 and 3 do not appear to work on the auxiliary device.
	 * Mode POL PHA
	 *  0    0   0
	 *  1    0   1
	 *  2    1   0
	 *  3    1   1
	 * px is 0 if CEx is active low (default) and 1 for active high.
	 * ux is 0 if the CEx gpio is reserved for SPI (default) and 1 otherwise.
	 * A is 0 for the standard SPI device, 1 for the auxiliary SPI. The auxiliary device
	 * is only present on the A+/B+/Pi2/Zero.
	 * W is 0 if the device is not 3-wire, 1 if the device is 3-wire. Standard SPI device only.
	 * nnnn defines the number of bytes (0-15) to write before switching the MOSI line
	 * to MISO to read data. This field is ignored if W is not set. Standard SPI device only.
	 * T is 1 if the least significant bit is transmitted on MOSI first, the default (0)
	 * shifts the most significant bit out first. Auxiliary SPI device only.
	 * R is 1 if the least significant bit is received on MISO first, the default (0) receives
	 * the most significant bit first. Auxiliary SPI device only.
	 * bbbbbb defines the word size in bits (0-32).
	 * The default (0) sets 8 bits per word. Auxiliary SPI device only.
	 * The other bits in flags should be set to zero
	 */
	private static int createSpiFlags(SpiClockMode clockMode, int controller, boolean lsbFirst) {
		int flags = clockMode.getMode();
		
		// CE0 is the standard SPI device, CE1 is auxiliary
		if (controller == 1) {
			flags |= 0x100;
		}
		if (lsbFirst) {
			flags |= 0x8000;
		}
		
		return flags;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy