Skip to content

Commit 493a217

Browse files
committed
Allow opening multiple pins
1 parent 5dfa565 commit 493a217

5 files changed

Lines changed: 85 additions & 25 deletions

File tree

ioio/main.cpp

Lines changed: 74 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,23 @@
1414
#include <cstdio>
1515
#include <jni.h>
1616
#include <pthread.h>
17+
#include "robin-hood-hashing/src/include/robin_hood.h"
1718

1819
JNIEnv *env;
1920
JavaVM *jvm;
2021

2122
struct IOClass {
2223
IOClass(): _clazz(nullptr), _instance(nullptr) {}
2324

25+
virtual ~IOClass() {
26+
_clazz = nullptr;
27+
_instance = nullptr;
28+
}
29+
2430
bool create(const char *path) {
2531
bool result;
2632
if (_instance != nullptr) {
27-
// error: already constructed
33+
// error when already constructed
2834
result = false;
2935
} else {
3036
_clazz = env->FindClass(path);
@@ -43,48 +49,75 @@ struct IOClass {
4349
return result;
4450
}
4551

46-
bool invoke(const char *name, int value) {
52+
bool invokeIV(const char *name, int value) {
4753
bool result = false;
4854
if (_instance != nullptr) {
4955
jmethodID method = env->GetMethodID(_clazz, name, "(I)V");
5056
if (method != nullptr) {
5157
env->CallVoidMethod(_instance, method, value);
52-
result = true;
53-
} else {
58+
}
59+
auto exc = env->ExceptionOccurred();
60+
if (exc) {
5461
env->ExceptionDescribe();
62+
env->ExceptionClear();
63+
} else {
64+
result = (method != nullptr);
5565
}
5666
}
5767
return result;
5868
}
5969

6070
bool open(int pin) {
61-
return invoke("open", pin);
71+
return invokeIV("open", pin);
6272
}
63-
73+
6474
bool write(int value) {
65-
return invoke("write", value);
75+
return invokeIV("write", value);
6676
}
67-
77+
6878
private:
6979
jclass _clazz;
7080
jobject _instance;
7181
};
7282

73-
IOClass analogInput;
74-
IOClass digitalOutput;
83+
#define CLS_IOCLASS 1
84+
robin_hood::unordered_map<int, IOClass> _ioClassMap;
85+
int _nextId = 1;
7586

76-
static void cmd_digital_output_write(var_s *self, var_s *retval) {
77-
static int value = !value;
78-
digitalOutput.write(value);
87+
static int get_io_class_id(var_s *map) {
88+
int result = -1;
89+
if (is_map(map)) {
90+
int id = map->v.m.id;
91+
if (id != -1 && _ioClassMap.find(id) != _ioClassMap.end()) {
92+
result = id;
93+
}
94+
}
95+
return result;
96+
}
97+
98+
int value = 0;
99+
static void cmd_digital_output_write(var_s *map, var_s *retval) {
100+
value = !value;
101+
int id = get_io_class_id(map);
102+
if (id != -1) {
103+
_ioClassMap.at(id).write(value);
104+
} else {
105+
error(retval, "IOClass not found");
106+
}
79107
}
80108

81109
static int cmd_openanaloginput(int argc, slib_par_t *params, var_t *retval) {
82110
int result;
83111
int pin = get_param_int(argc, params, 0, 0);
84-
if (analogInput.create("net/sourceforge/smallbasic/ioio/AnalogInput") &&
85-
analogInput.open(pin)) {
112+
int id = ++_nextId;
113+
IOClass &input = _ioClassMap[id];
114+
if (input.create("net/sourceforge/smallbasic/ioio/AnalogInput") &&
115+
input.open(pin)) {
116+
map_init_id(retval, id, CLS_IOCLASS);
117+
//v_create_func(retval, "write", cmd_digital_output_write);
86118
result = 1;
87119
} else {
120+
_ioClassMap.erase(id);
88121
error(retval, "openAnalogInput() failed");
89122
result = 0;
90123
}
@@ -94,12 +127,15 @@ static int cmd_openanaloginput(int argc, slib_par_t *params, var_t *retval) {
94127
static int cmd_opendigitaloutput(int argc, slib_par_t *params, var_t *retval) {
95128
int result;
96129
int pin = get_param_int(argc, params, 0, 0);
97-
if (digitalOutput.create("net/sourceforge/smallbasic/ioio/DigitalOutput") &&
98-
digitalOutput.open(pin)) {
99-
map_init(retval);
130+
int id = ++_nextId;
131+
IOClass &output = _ioClassMap[id];
132+
if (output.create("net/sourceforge/smallbasic/ioio/DigitalOutput") &&
133+
output.open(pin)) {
134+
map_init_id(retval, id, CLS_IOCLASS);
100135
v_create_func(retval, "write", cmd_digital_output_write);
101136
result = 1;
102137
} else {
138+
_ioClassMap.erase(id);
103139
error(retval, "openDigitalOutput() failed");
104140
result = 0;
105141
}
@@ -126,7 +162,10 @@ int sblib_init(const char *sourceFile) {
126162
JavaVMInitArgs vm_args;
127163
JavaVMOption options[2];
128164
options[0].optionString = (char *)"-Djava.class.path=./target/ioio-1.0-jar-with-dependencies.jar";
129-
options[1].optionString = (char *)"-Dioio.SerialPorts=ACM0";
165+
options[1].optionString = (char *)"-Dioio.SerialPorts=IOIO0";
166+
//options[2].optionString = "-Xdebug";
167+
//options[3].optionString = "-agentlib:jdwp=transport=dt_socket,server=y,address=5005,suspend=y";
168+
//options[2].optionString = (char *)"-Xcheck:jni";
130169
vm_args.version = JNI_VERSION_1_8;
131170
vm_args.nOptions = 2;
132171
vm_args.options = options;
@@ -139,9 +178,24 @@ int sblib_init(const char *sourceFile) {
139178
return result;
140179
}
141180

181+
SBLIB_API void sblib_free(int cls_id, int id) {
182+
if (id != -1) {
183+
switch (cls_id) {
184+
case CLS_IOCLASS:
185+
_ioClassMap.erase(id);
186+
break;
187+
}
188+
}
189+
}
190+
142191
void sblib_close(void) {
192+
if (!_ioClassMap.empty()) {
193+
fprintf(stderr, "IOClass leak detected\n");
194+
_ioClassMap.clear();
195+
}
143196
jvm->DetachCurrentThread();
144-
jvm->DestroyJavaVM();
197+
// hangs
198+
//jvm->DestroyJavaVM();
145199
env = nullptr;
146200
jvm = nullptr;
147201
}

ioio/samples/led.bas

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import ioio
22

33
out = ioio.openDigitalOutput(0)
4+
'delay 30000
45
value = false
5-
while (true)
6+
for i = 0 to 5
67
print "setting LED "+ value
7-
out.write(value)
8+
out.write()
89
value = !value
910
delay 1000
10-
wend
11+
next
12+
print "done"
1113

1214

1315

ioio/src/main/java/ioio/lib/pc/SerialPortIOIOConnection.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import java.io.InputStream;
3838
import java.io.OutputStream;
3939

40+
import ioio.lib.spi.Log;
4041
import purejavacomm.CommPort;
4142
import purejavacomm.CommPortIdentifier;
4243
import purejavacomm.NoSuchPortException;
@@ -49,6 +50,7 @@ class SerialPortIOIOConnection implements IOIOConnection {
4950
private SerialPort serialPort_;
5051
private InputStream inputStream_;
5152
private OutputStream outputStream_;
53+
public static final String TAG = "SerialPortIOIOConnection";
5254

5355
public SerialPortIOIOConnection(String name) {
5456
name_ = name;
@@ -78,11 +80,14 @@ public void waitForConnect() throws ConnectionLostException {
7880
}
7981
}
8082
} catch (NoSuchPortException e) {
83+
Log.d(TAG, e.toString(), e);
8184
try {
8285
Thread.sleep(1000);
8386
} catch (InterruptedException e1) {
87+
Log.d(TAG, e1.toString(), e1);
8488
}
8589
} catch (Exception e) {
90+
Log.d(TAG, e.toString(), e);
8691
if (serialPort_ != null) {
8792
serialPort_.close();
8893
}

ioio/src/main/java/net/sourceforge/smallbasic/ioio/DigitalOutput.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ public void open(int pin) {
2929
}
3030

3131
public void write(int value) {
32-
System.err.println("WRITE ! write = " + value);
3332
outputLooper.setValue(value == 1);
3433
}
3534
}

ioio/src/main/java/net/sourceforge/smallbasic/ioio/DigitalOutputLooper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class DigitalOutputLooper extends AbstractLooper {
1616

1717
public DigitalOutputLooper(BlockingQueue<Consumer<IOIO>> queue, int pin) {
1818
super(queue, pin);
19-
Log.i(TAG, "creating AnalogInputLooper");
19+
Log.i(TAG, "creating DigitalOutputLooper");
2020
}
2121

2222
@Override

0 commit comments

Comments
 (0)