Skip to content

Commit 19e8903

Browse files
committed
Refactored the SPI write readWrite APIs
1 parent c96b879 commit 19e8903

File tree

8 files changed

+185
-88
lines changed

8 files changed

+185
-88
lines changed

include/javaproxy.h

+3-52
Original file line numberDiff line numberDiff line change
@@ -285,51 +285,6 @@ struct JavaProxy {
285285
return result;
286286
}
287287

288-
// int readWrite(int address, byte[] write) {
289-
int invokeReadWrite(int argc, slib_par_t *arg, var_s *retval) {
290-
int result = 0;
291-
int writeLen = populateByteArray(argc, arg, 2);
292-
if (writeLen > ARRAY_SIZE) {
293-
error(retval, "write array", 1, ARRAY_SIZE);
294-
} else if (_instance != nullptr) {
295-
attachCurrentThread();
296-
jmethodID method = g_env->GetMethodID(_clazz, "readWrite", "(II[BI)J");
297-
var_int_t value = 0;
298-
if (method != nullptr) {
299-
auto address = get_param_int(argc, arg, 0, 0);
300-
auto readBytes = get_param_int(argc, arg, 1, 2);
301-
value = g_env->CallIntMethod(_instance, method, address, readBytes, _array, writeLen);
302-
}
303-
if (!checkException(retval)) {
304-
v_setint(retval, value);
305-
result = 1;
306-
}
307-
detachCurrentThread();
308-
}
309-
return result;
310-
}
311-
312-
// int write(int address, byte[] write) {
313-
int invokeWrite(int argc, slib_par_t *arg, var_s *retval) {
314-
int result = 0;
315-
int writeLen = populateByteArray(argc, arg, 1);
316-
if (writeLen > ARRAY_SIZE) {
317-
error(retval, "write array", 1, ARRAY_SIZE);
318-
} else if (_instance != nullptr) {
319-
attachCurrentThread();
320-
jmethodID method = g_env->GetMethodID(_clazz, "write", "(I[BI)V");
321-
if (method != nullptr) {
322-
auto address = get_param_int(argc, arg, 0, 0);
323-
g_env->CallVoidMethod(_instance, method, address, _array, writeLen);
324-
}
325-
if (!checkException(retval)) {
326-
result = 1;
327-
}
328-
detachCurrentThread();
329-
}
330-
return result;
331-
}
332-
333288
// populate the java byte array with the contents of the basic array
334289
int populateByteArray(int argc, slib_par_t *params, int offset) {
335290
int result;
@@ -350,7 +305,7 @@ struct JavaProxy {
350305
for (int i = offset, j = 0; i < argc && i < ARRAY_SIZE; i++, j++) {
351306
elements[j] = get_param_int(argc, params, i, 0);
352307
}
353-
result = argc - 1;
308+
result = argc - offset;
354309
}
355310
// make the changes available to the java side
356311
g_env->ReleaseByteArrayElements(_array, elements, 0);
@@ -382,7 +337,7 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void* reserved) {
382337

383338
#else
384339

385-
int createJVM(const char *arg1, const char *arg2) {
340+
int createJVM(const char *arg1, const char *arg2, bool debug) {
386341
JavaVMInitArgs vm_args;
387342
JavaVMOption options[6];
388343
options[0].optionString = (char *)"-Xrs";
@@ -392,11 +347,7 @@ int createJVM(const char *arg1, const char *arg2) {
392347
options[4].optionString = (char *)"-agentlib:jdwp=transport=dt_socket,server=y,address=5005,suspend=y";
393348
options[5].optionString = (char *)"-Xcheck:jni";
394349
vm_args.version = JNI_VERSION_1_8;
395-
#if defined(DEBUG)
396-
vm_args.nOptions = 6;
397-
#else
398-
vm_args.nOptions = 3;
399-
#endif
350+
vm_args.nOptions = debug ? 6 : 3;
400351
vm_args.ignoreUnrecognized = 1;
401352
vm_args.options = options;
402353
int result = (JNI_CreateJavaVM(&g_jvm, (void **)&g_env, &vm_args) == JNI_OK &&

ioio/README.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -100,23 +100,23 @@ A pin used for PWM (Pulse-Width Modulation) output. A PWM pin produces a logic-l
100100

101101
## TwiMaster
102102

103-
An interface for controlling a TWI module, in TWI bus-master mode, enabling communication with multiple TWI-enabled slave modules.
103+
An interface for controlling a TWI (Two Wire Interface) module, in TWI bus-master mode, enabling communication with multiple TWI-enabled slave modules.
104104

105105
`io = ioio.openTwiMaster(TWINumber, mode)`
106106

107-
Opens a TWI module number TWINumber in master mode, using its dedicated SDA and SCL pins. The TWI module will run at 100KHz and will use I2C voltage levels if mode = false (pass true for SMBus levels).
108-
109107
| Name | Description |
110108
|---------|---------------|
111-
|void write(Address, Register, DataByte) | Writes a byte of data to the given register of an I2C device with given address.|
112-
|int readwrite(Address, NumReceiveBytes, Register, DataByte) | Writes a byte of data to the given register of an I2C device with given address and reads NumReceiveBytes. NumReceiveBytes can be max 8 bytes long.|
109+
|void write(Address, Register, DataBytes)|Writes one or more bytes of data to the given register of an I2C device with given address.|
110+
|int readWrite(address, NumReceiveBytes, Register, DataBytes)|Writes one or more bytes of data to the given register of an I2C device with given address and reads NumReceiveBytes. NumReceiveBytes can be max 8 bytes long.|
113111

114112
## SpiMaster
115113

116-
An interface for controlling an SPI module, in SPI bus-master mode, enabling communication with multiple SPI-enabled slave modules
114+
An interface for controlling an SPI (Serial Peripheral Interface) module, in SPI bus-master mode, enabling communication with multiple SPI-enabled slave modules
117115

118-
`io = ioio.openSpiMaster(pin)`
116+
`io = ioio.openSpiMaster(misoPin, mosiPin, clkPin, csPin)`
119117

120118
| Name | Description |
121119
|---------|---------------|
120+
|void write(DataBytes)|Writes one or more bytes of data.|
121+
|int readWrite(NumReceiveBytes, DataBytes)|Writes one or more bytes of data and reads NumReceiveBytes. NumReceiveBytes can be max 8 bytes long.|
122122

ioio/api.json

+31-6
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@
229229
{
230230
"name": "PwmOutput",
231231
"comment": "A pin used for PWM (Pulse-Width Modulation) output. A PWM pin produces a logic-level PWM signal. These signals are typically used for simulating analog outputs for controlling the intensity of LEDs, the rotation speed of motors, etc. They are also frequently used for controlling hobby servo motors. PwmOutput instances are obtained by calling IOIO#openPwmOutput. When used for motors and LEDs, a frequency of several KHz is typically used, where there is a trade-off between switching power-loses and smoothness of operation. The pulse width is typically set by specifying the duty cycle, with the setDutyCycle method. A duty cycle of 0 is \"off\", a duty cycle of 1 is \"on\", and every intermediate value produces an intermediate intensity. Please note that any devices consuming more than 20mA of current (e.g. motors) should not by directly connected the the IOIO pins, but rather through an amplification circuit suited for the specific load. When used for hobby servos, the PWM signal is rather used for encoding of the desired angle the motor should go to. By standard, a 100Hz signal is used and the pulse width is varied between 1ms and 2ms (corresponding to both extremes of the shaft angle), using setPulseWidth. The instance is alive since its creation. If the connection with the IOIO drops at any point, the instance transitions to a disconnected state, in which every attempt to use the pin (except close()) will throw a ConnectionLostException. Whenever close() is invoked the instance may no longer be used. Any resources associated with it are freed and can be reused. Typical usage (fading LED):",
232+
"signature": "pin, frequency",
232233
"pins": 2,
233234
"methods": [
234235
{
@@ -247,14 +248,38 @@
247248
},
248249
{
249250
"name": "TwiMaster":
250-
"comment": "An interface for controlling a TWI module, in TWI bus-master mode, enabling communication with multiple TWI-enabled slave modules.",
251-
"methods": [],
252-
"pins": 2
251+
"comment": "An interface for controlling a TWI (Two Wire Interface) module, in TWI bus-master mode, enabling communication with multiple TWI-enabled slave modules.",
252+
"signature": "TWINumber, mode",
253+
"nogen" : true,
254+
"pins": 2,
255+
"methods": [{
256+
"name": "write",
257+
"rtn": "void",
258+
"signature": "Address, Register, DataBytes",
259+
"comment": "Writes one or more bytes of data to the given register of an I2C device with given address."
260+
},{
261+
"name": "readWrite",
262+
"rtn": "int",
263+
"signature": "address, NumReceiveBytes, Register, DataBytes",
264+
"comment": "Writes one or more bytes of data to the given register of an I2C device with given address and reads NumReceiveBytes. NumReceiveBytes can be max 8 bytes long."
265+
}]
253266
},
254267
{
255268
"name": "SpiMaster":
256-
"comment": "An interface for controlling an SPI module, in SPI bus-master mode, enabling communication with multiple SPI-enabled slave modules",
257-
"methods": [],
258-
"pins": 4
269+
"comment": "An interface for controlling an SPI (Serial Peripheral Interface) module, in SPI bus-master mode, enabling communication with multiple SPI-enabled slave modules",
270+
"nogen" : true,
271+
"signature": "misoPin, mosiPin, clkPin, csPin",
272+
"pins": 4,
273+
"methods": [{
274+
"name": "write",
275+
"rtn": "void",
276+
"signature": "DataBytes",
277+
"comment": "Writes one or more bytes of data."
278+
},{
279+
"name": "readWrite",
280+
"rtn": "int",
281+
"signature": "NumReceiveBytes, DataBytes",
282+
"comment": "Writes one or more bytes of data and reads NumReceiveBytes. NumReceiveBytes can be max 8 bytes long."
283+
}]
259284
}
260285
]

ioio/ioio/src/main/java/ioio/smallbasic/SpiMasterImpl.java

+15-5
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,23 @@ public void open(int miso, int mosi, int clk, int slaveSelect) throws IOExceptio
4040
validatePins();
4141
}
4242

43-
public void write(int address, final byte[] write, int writeLen) {
43+
public long readWrite(int readLen, final byte[] write, int writeLen) {
44+
handleError();
45+
return lock.invokeLong((i) -> {
46+
byte[] read = new byte[readLen];
47+
spiMaster.writeRead(write, writeLen, writeLen, read, read.length);
48+
long result = 0;
49+
for (int index = 0; index < read.length; index++) {
50+
result += ((long)Byte.toUnsignedInt(read[index])) << (index * 8);
51+
}
52+
return result;
53+
});
54+
}
55+
56+
public void write(final byte[] write, int writeLen) {
4457
handleError();
4558
lock.invoke((i) -> {
46-
byte[] buffer = new byte[writeLen + 1];
47-
buffer[0] = (byte)address;
48-
System.arraycopy(write, 0, buffer, 1, writeLen);
49-
spiMaster.writeRead(buffer, buffer.length, buffer.length, null, 0);
59+
spiMaster.writeRead(write, write.length, write.length, null, 0);
5060
});
5161
}
5262

ioio/main.cpp

+111-6
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,94 @@ struct IOTask : JavaProxy {
4141
int open4(int pin1, int pin2, int pin3, int pin4, var_s *retval) {
4242
return invokeVoidInt4("open", pin1, pin2, pin3, pin4, retval);
4343
}
44+
45+
// int readWrite(bytes, byte[] write) {
46+
int invokeSpiReadWrite(int argc, slib_par_t *arg, var_s *retval) {
47+
int result = 0;
48+
int writeLen = populateByteArray(argc, arg, 1);
49+
if (writeLen > ARRAY_SIZE) {
50+
error(retval, "write array", 1, ARRAY_SIZE);
51+
} else if (_instance != nullptr) {
52+
attachCurrentThread();
53+
jmethodID method = g_env->GetMethodID(_clazz, "readWrite", "(I[BI)J");
54+
var_int_t value = 0;
55+
if (method != nullptr) {
56+
auto readBytes = get_param_int(argc, arg, 0, 2);
57+
value = g_env->CallIntMethod(_instance, method, readBytes, _array, writeLen);
58+
}
59+
if (!checkException(retval)) {
60+
v_setint(retval, value);
61+
result = 1;
62+
}
63+
detachCurrentThread();
64+
}
65+
return result;
66+
}
67+
68+
// int write(byte[] write) {
69+
int invokeSpiWrite(int argc, slib_par_t *arg, var_s *retval) {
70+
int result = 0;
71+
int writeLen = populateByteArray(argc, arg, 0);
72+
if (writeLen > ARRAY_SIZE) {
73+
error(retval, "write array", 1, ARRAY_SIZE);
74+
} else if (_instance != nullptr) {
75+
attachCurrentThread();
76+
jmethodID method = g_env->GetMethodID(_clazz, "write", "([BI)V");
77+
if (method != nullptr) {
78+
g_env->CallVoidMethod(_instance, method, _array, writeLen);
79+
}
80+
if (!checkException(retval)) {
81+
result = 1;
82+
}
83+
detachCurrentThread();
84+
}
85+
return result;
86+
}
87+
88+
// int readWrite(int address, byte[] write) {
89+
int invokeTwiReadWrite(int argc, slib_par_t *arg, var_s *retval) {
90+
int result = 0;
91+
int writeLen = populateByteArray(argc, arg, 2);
92+
if (writeLen > ARRAY_SIZE) {
93+
error(retval, "write array", 1, ARRAY_SIZE);
94+
} else if (_instance != nullptr) {
95+
attachCurrentThread();
96+
jmethodID method = g_env->GetMethodID(_clazz, "readWrite", "(II[BI)J");
97+
var_int_t value = 0;
98+
if (method != nullptr) {
99+
auto address = get_param_int(argc, arg, 0, 0);
100+
auto readBytes = get_param_int(argc, arg, 1, 2);
101+
value = g_env->CallIntMethod(_instance, method, address, readBytes, _array, writeLen);
102+
}
103+
if (!checkException(retval)) {
104+
v_setint(retval, value);
105+
result = 1;
106+
}
107+
detachCurrentThread();
108+
}
109+
return result;
110+
}
111+
112+
// int write(int address, byte[] write) {
113+
int invokeTwiWrite(int argc, slib_par_t *arg, var_s *retval) {
114+
int result = 0;
115+
int writeLen = populateByteArray(argc, arg, 1);
116+
if (writeLen > ARRAY_SIZE) {
117+
error(retval, "write array", 1, ARRAY_SIZE);
118+
} else if (_instance != nullptr) {
119+
attachCurrentThread();
120+
jmethodID method = g_env->GetMethodID(_clazz, "write", "(I[BI)V");
121+
if (method != nullptr) {
122+
auto address = get_param_int(argc, arg, 0, 0);
123+
g_env->CallVoidMethod(_instance, method, address, _array, writeLen);
124+
}
125+
if (!checkException(retval)) {
126+
result = 1;
127+
}
128+
detachCurrentThread();
129+
}
130+
return result;
131+
}
44132
};
45133

46134
robin_hood::unordered_map<int, IOTask> g_ioTaskMap;
@@ -71,7 +159,7 @@ static int cmd_twimaster_readwrite(var_s *self, int argc, slib_par_t *arg, var_s
71159
} else {
72160
int id = get_io_class_id(self, retval);
73161
if (id != -1) {
74-
result = g_ioTaskMap.at(id).invokeReadWrite(argc, arg, retval);
162+
result = g_ioTaskMap.at(id).invokeTwiReadWrite(argc, arg, retval);
75163
}
76164
}
77165
return result;
@@ -84,20 +172,36 @@ static int cmd_twimaster_write(var_s *self, int argc, slib_par_t *arg, var_s *re
84172
} else {
85173
int id = get_io_class_id(self, retval);
86174
if (id != -1) {
87-
result = g_ioTaskMap.at(id).invokeWrite(argc, arg, retval);
175+
result = g_ioTaskMap.at(id).invokeTwiWrite(argc, arg, retval);
176+
}
177+
}
178+
return result;
179+
}
180+
181+
static int cmd_spimaster_readwrite(var_s *self, int argc, slib_par_t *arg, var_s *retval) {
182+
int result = 0;
183+
auto readBytes = get_param_int(argc, arg, 0, 0);
184+
if (argc < 2) {
185+
error(retval, "SpiMaster.readWrite(read-bytes, [data]", 2, ARRAY_SIZE);
186+
} else if (readBytes < 1 || readBytes > 8) {
187+
error(retval, "read-bytes value out of range. Expected a number between 1 and 8");
188+
} else {
189+
int id = get_io_class_id(self, retval);
190+
if (id != -1) {
191+
result = g_ioTaskMap.at(id).invokeSpiReadWrite(argc, arg, retval);
88192
}
89193
}
90194
return result;
91195
}
92196

93197
static int cmd_spimaster_write(var_s *self, int argc, slib_par_t *arg, var_s *retval) {
94198
int result = 0;
95-
if (argc != 2) {
96-
error(retval, "SpiMaster.write", 2, ARRAY_SIZE);
199+
if (argc < 1) {
200+
error(retval, "SpiMaster.write", 1, ARRAY_SIZE);
97201
} else {
98202
int id = get_io_class_id(self, retval);
99203
if (id != -1) {
100-
result = g_ioTaskMap.at(id).invokeWrite(argc, arg, retval);
204+
result = g_ioTaskMap.at(id).invokeSpiWrite(argc, arg, retval);
101205
}
102206
}
103207
return result;
@@ -110,6 +214,7 @@ static void create_twimaster(var_t *map) {
110214

111215
static void create_spimaster(var_t *map) {
112216
v_create_callback(map, "write", cmd_spimaster_write);
217+
v_create_callback(map, "readWrite", cmd_spimaster_readwrite);
113218
}
114219

115220
#include "api.h"
@@ -149,7 +254,7 @@ SBLIB_API int sblib_func_count() {
149254
//
150255
int sblib_init(const char *sourceFile) {
151256
#if defined(DESKTOP_MODULE)
152-
int result = createJVM("-Djava.class.path=./ioio-1.0-jar-with-dependencies.jar", "-Dioio.SerialPorts=IOIO0");
257+
int result = createJVM("-Djava.class.path=./ioio-1.0-jar-with-dependencies.jar", "-Dioio.SerialPorts=IOIO0", true);
153258
#else
154259
int result = 1;
155260
#endif

0 commit comments

Comments
 (0)