Skip to content

Commit 42d547b

Browse files
committed
#454 Add first SPI implementation, tests (with native mock driver) and minor refactoring
1 parent cdd645c commit 42d547b

File tree

17 files changed

+545
-183
lines changed

17 files changed

+545
-183
lines changed

plugins/pi4j-plugin-ffm/src/main/java/com/pi4j/plugin/ffm/FFMPlugin.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import com.pi4j.plugin.ffm.providers.gpio.DigitalOutputFFMProviderImpl;
99
import com.pi4j.plugin.ffm.providers.i2c.I2CFFMProviderImpl;
1010
import com.pi4j.plugin.ffm.providers.pwm.FFMPwmProviderImpl;
11-
import com.pi4j.plugin.ffm.providers.spi.FFMSpiProviderImpl;
11+
import com.pi4j.plugin.ffm.providers.spi.SpiFFMProviderImpl;
1212
import com.pi4j.provider.Provider;
1313

1414
import java.util.Arrays;
@@ -22,7 +22,7 @@ public void initialize(PluginService service) {
2222
new DigitalInputFFMProviderImpl(),
2323
new DigitalOutputFFMProviderImpl(),
2424
new I2CFFMProviderImpl(),
25-
new FFMSpiProviderImpl(),
25+
new SpiFFMProviderImpl(),
2626
new FFMPwmProviderImpl()
2727
};
2828
service.register(providers);

plugins/pi4j-plugin-ffm/src/main/java/com/pi4j/plugin/ffm/common/ioctl/Command.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ public static long getGpioGetChipInfoIoctl() {
1515
return IoctlMagic.GPIO_GET_CHIPINFO_IOCTL;
1616
}
1717

18+
public static long getSpiIocMessage(int n) {
19+
return IoctlMagic.SPI_IOC_MESSAGE(n);
20+
}
1821

1922
public static long getSpiIocRdMode() {
2023
return IoctlMagic.SPI_IOC_RD_MODE;

plugins/pi4j-plugin-ffm/src/main/java/com/pi4j/plugin/ffm/common/ioctl/IoctlMagic.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ static int SPI_MSGSIZE(int N) {
8989

9090
static int SPI_IOC_TRANSFER_SIZE() {
9191
if (_SPI_IOC_TRANSFER_SIZE == -1) {
92-
_SPI_IOC_TRANSFER_SIZE = 44;
92+
_SPI_IOC_TRANSFER_SIZE = 32;
9393
}
9494
return _SPI_IOC_TRANSFER_SIZE;
9595
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package com.pi4j.plugin.ffm.common.spi;
2+
3+
import com.pi4j.plugin.ffm.common.Pi4JLayout;
4+
5+
import java.lang.foreign.Arena;
6+
import java.lang.foreign.MemoryLayout;
7+
import java.lang.foreign.MemorySegment;
8+
import java.lang.foreign.ValueLayout;
9+
import java.lang.invoke.VarHandle;
10+
import java.util.Arrays;
11+
12+
import static java.lang.foreign.MemoryLayout.PathElement.groupElement;
13+
14+
/**
15+
* Source: /usr/src/linux-headers-6.8.0-52-generic/include/linux/spi/spidev.h:70:0
16+
*/
17+
public record SpiIocTransfer(byte[] txBuf, byte[] rxBuf, int length, int speedHz, short delayUsecs, byte bitsPerWord,
18+
byte csChange, byte txNbits, byte rxNbits, byte wordDelayUsecs,
19+
byte pad) implements Pi4JLayout {
20+
21+
public SpiIocTransfer(byte[] txBuf, byte[] rxBuf, int length) {
22+
this(txBuf, rxBuf, length, 0, (short) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0);
23+
}
24+
25+
public static final MemoryLayout LAYOUT = MemoryLayout.structLayout(
26+
ValueLayout.JAVA_LONG.withName("tx_buf"),
27+
ValueLayout.JAVA_LONG.withName("rx_buf"),
28+
ValueLayout.JAVA_INT.withName("len"),
29+
ValueLayout.JAVA_INT.withName("speed_hz"),
30+
ValueLayout.JAVA_SHORT.withName("delay_usecs"),
31+
ValueLayout.JAVA_BYTE.withName("bits_per_word"),
32+
ValueLayout.JAVA_BYTE.withName("cs_change"),
33+
ValueLayout.JAVA_BYTE.withName("tx_nbits"),
34+
ValueLayout.JAVA_BYTE.withName("rx_nbits"),
35+
ValueLayout.JAVA_BYTE.withName("word_delay_usecs"),
36+
ValueLayout.JAVA_BYTE.withName("pad")
37+
);
38+
39+
private static final VarHandle VH_TX_BUF = LAYOUT.varHandle(groupElement("tx_buf"));
40+
private static final VarHandle VH_RX_BUF = LAYOUT.varHandle(groupElement("rx_buf"));
41+
42+
private static final VarHandle VH_LEN = LAYOUT.varHandle(groupElement("len"));
43+
private static final VarHandle VH_SPEED_HZ = LAYOUT.varHandle(groupElement("speed_hz"));
44+
private static final VarHandle VH_DELAY_USECS = LAYOUT.varHandle(groupElement("delay_usecs"));
45+
private static final VarHandle VH_BITS_PER_WORD = LAYOUT.varHandle(groupElement("bits_per_word"));
46+
private static final VarHandle VH_CS_CHANGE = LAYOUT.varHandle(groupElement("cs_change"));
47+
private static final VarHandle VH_TX_NBITS = LAYOUT.varHandle(groupElement("tx_nbits"));
48+
private static final VarHandle VH_RX_NBITS = LAYOUT.varHandle(groupElement("rx_nbits"));
49+
private static final VarHandle VH_WORD_DELAY_USECS = LAYOUT.varHandle(groupElement("word_delay_usecs"));
50+
private static final VarHandle VH_PAD = LAYOUT.varHandle(groupElement("pad"));
51+
52+
53+
public static SpiIocTransfer create(MemorySegment memorySegment) throws Throwable {
54+
var spiIocTransferInstance = SpiIocTransfer.createEmpty();
55+
if (!memorySegment.equals(MemorySegment.NULL)) {
56+
spiIocTransferInstance = spiIocTransferInstance.from(memorySegment);
57+
}
58+
return spiIocTransferInstance;
59+
}
60+
61+
public static SpiIocTransfer createEmpty() {
62+
return new SpiIocTransfer(new byte[]{}, new byte[]{}, 0, 0, (short) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0);
63+
}
64+
65+
@Override
66+
public MemoryLayout getMemoryLayout() {
67+
return LAYOUT;
68+
}
69+
70+
@Override
71+
@SuppressWarnings("unchecked")
72+
public SpiIocTransfer from(MemorySegment buffer) throws Throwable {
73+
return new SpiIocTransfer(
74+
txBuf1 != null ? txBuf1.toArray(ValueLayout.JAVA_BYTE) : new byte[]{},
75+
rxBuf1 != null ? rxBuf1.toArray(ValueLayout.JAVA_BYTE) : new byte[]{},
76+
(int) VH_LEN.get(buffer, 0L),
77+
(int) VH_SPEED_HZ.get(buffer, 0L),
78+
(short) VH_DELAY_USECS.get(buffer, 0L),
79+
(byte) VH_BITS_PER_WORD.get(buffer, 0L),
80+
(byte) VH_CS_CHANGE.get(buffer, 0L),
81+
(byte) VH_TX_NBITS.get(buffer, 0L),
82+
(byte) VH_RX_NBITS.get(buffer, 0L),
83+
(byte) VH_WORD_DELAY_USECS.get(buffer, 0L),
84+
(byte) VH_PAD.get(buffer, 0L));
85+
}
86+
87+
public static MemorySegment txBuf1;
88+
public static MemorySegment rxBuf1;
89+
90+
@Override
91+
public void to(MemorySegment buffer) throws Throwable {
92+
if (txBuf != null) {
93+
txBuf1 = Arena.global().allocateFrom(ValueLayout.JAVA_BYTE, txBuf);
94+
VH_TX_BUF.set(buffer, 0L, txBuf1.address());
95+
}
96+
if (rxBuf != null) {
97+
rxBuf1 = Arena.global().allocateFrom(ValueLayout.JAVA_BYTE, rxBuf);
98+
VH_RX_BUF.set(buffer, 0L, rxBuf1.address());
99+
}
100+
VH_LEN.set(buffer, 0L, length);
101+
VH_SPEED_HZ.set(buffer, 0L, speedHz);
102+
VH_DELAY_USECS.set(buffer, 0L, delayUsecs);
103+
VH_BITS_PER_WORD.set(buffer, 0L, bitsPerWord);
104+
VH_CS_CHANGE.set(buffer, 0L, csChange);
105+
VH_TX_NBITS.set(buffer, 0L, txNbits);
106+
VH_RX_NBITS.set(buffer, 0L, rxNbits);
107+
VH_WORD_DELAY_USECS.set(buffer, 0L, wordDelayUsecs);
108+
VH_PAD.set(buffer, 0L, pad);
109+
}
110+
111+
112+
@Override
113+
public String toString() {
114+
return "SpiIocTransfer{" +
115+
"txBuf=" + Arrays.toString(txBuf) +
116+
", rxBuf=" + Arrays.toString(rxBuf) +
117+
", length=" + length +
118+
", speedHz=" + speedHz +
119+
", delayUsecs=" + delayUsecs +
120+
", bitsPerWord=" + bitsPerWord +
121+
", csChange=" + csChange +
122+
", txNbits=" + txNbits +
123+
", rxNbits=" + rxNbits +
124+
", wordDelayUsecs=" + wordDelayUsecs +
125+
", pad=" + pad +
126+
'}';
127+
}
128+
}

plugins/pi4j-plugin-ffm/src/main/java/com/pi4j/plugin/ffm/providers/i2c/I2CSMBus.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ public int writeRegister(int register, byte[] data, int offset, int length) {
127127

128128
@Override
129129
public int writeRegister(byte[] register, byte[] data, int offset, int length) {
130-
//TODO: how to implement? That is not a part of standard.
131130
Objects.checkFromIndexSize(offset, length, data.length);
132131
// Prepare the data for multibyte register
133132
// Sequence:
@@ -144,6 +143,5 @@ public int writeRegister(byte[] register, byte[] data, int offset, int length) {
144143
public void close() {
145144
super.close();
146145
i2CBus.close();
147-
SMBUS.close();
148146
}
149147
}

plugins/pi4j-plugin-ffm/src/main/java/com/pi4j/plugin/ffm/providers/spi/FFMSpi.java

Lines changed: 0 additions & 135 deletions
This file was deleted.

0 commit comments

Comments
 (0)