mirror of
https://github.com/processing/processing4.git
synced 2026-06-16 04:26:26 +02:00
Merge pull request #4384 from gohai/arm-next
Add a few IO library examples
This commit is contained in:
@@ -29,4 +29,46 @@
|
||||
<target name="build" depends="compile" description="Build I/O library">
|
||||
<jar basedir="bin" destfile="library/io.jar" />
|
||||
</target>
|
||||
|
||||
<target name="dist" depends="build" description="Package standalone library">
|
||||
<!-- set revision number as library version -->
|
||||
<loadfile srcfile="../../../todo.txt" property="revision">
|
||||
<filterchain>
|
||||
<headfilter lines="1"/>
|
||||
<tokenfilter>
|
||||
<stringtokenizer suppressdelims="true"/>
|
||||
<!-- grab the thing from the first line that's 4 digits -->
|
||||
<containsregex pattern="(\d\d\d\d)" />
|
||||
</tokenfilter>
|
||||
</filterchain>
|
||||
</loadfile>
|
||||
<replaceregexp file="library.properties" match="version = .*" replace="version = ${revision}" flags="g" />
|
||||
<replaceregexp file="library.properties" match="prettyVersion = .*" replace="prettyVersion = ${revision}" flags="g" />
|
||||
|
||||
<get src="http://download.processing.org/reference.zip"
|
||||
dest="reference.zip"
|
||||
usetimestamp="true" />
|
||||
<mkdir dir="reference" />
|
||||
<unzip dest="."
|
||||
src="reference.zip"
|
||||
overwrite="true">
|
||||
<patternset>
|
||||
<include name="reference/css/**" />
|
||||
<include name="reference/img/**" />
|
||||
<include name="reference/javascript/**" />
|
||||
<include name="reference/libraries/io/**" />
|
||||
</patternset>
|
||||
</unzip>
|
||||
<delete file="reference.zip" />
|
||||
<echo file="reference/index.html" message="<html><head><meta http-equiv='refresh' content='0; url=libraries/io/index.html'></head><body></body></html>" />
|
||||
|
||||
<zip destfile="../io.zip">
|
||||
<zipfileset dir="." prefix="io">
|
||||
<exclude name="bin/**"/>
|
||||
</zipfileset>
|
||||
</zip>
|
||||
|
||||
<copy file="library.properties"
|
||||
toFile="../io.txt"/>
|
||||
</target>
|
||||
</project>
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import processing.io.*;
|
||||
|
||||
// 0.96" 128x64 OLED display ("SKU 346540")
|
||||
SSD1306 oled;
|
||||
|
||||
void setup() {
|
||||
size(128, 64);
|
||||
|
||||
// the display can be set to one of these two addresses: 0x3c (default) or 0x3d
|
||||
// (they might be listed as 0x7a and 0x7b on the circuit board)
|
||||
oled = new SSD1306(I2C.list()[0], 0x3c);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
line(0, 0, 127, 63);
|
||||
line(0, 63, 127, 0);
|
||||
oled.sendImage(get());
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
import processing.io.I2C;
|
||||
|
||||
// SSD1306 is a small, inexpensive 128x64 pixels monochrome OLED display
|
||||
// available online as "0.96" 128x64 OLED display", SKU 346540
|
||||
// or from Adafruit
|
||||
// datasheet: https://www.adafruit.com/datasheets/SSD1306.pdf
|
||||
|
||||
class SSD1306 extends I2C {
|
||||
int address;
|
||||
|
||||
// there can be more than one device connected to the bus
|
||||
// as long as they have different addresses
|
||||
SSD1306(String dev, int address) {
|
||||
super(dev);
|
||||
this.address = address;
|
||||
init();
|
||||
}
|
||||
|
||||
protected void init() {
|
||||
writeCommand(0xae); // turn display off
|
||||
writeCommand(0xa8, 0x3f); // set multiplex ratio to the highest setting
|
||||
writeCommand(0x8d, 0x14); // enable charge pump
|
||||
writeCommand(0x20, 0x00); // set memory addressing mode to horizontal
|
||||
writeCommand(0xd5, 0x80); // set display clock divide ratio & oscillator frequency to default
|
||||
writeCommand(0xd3, 0x00); // no display offset
|
||||
writeCommand(0x40 | 0x00); // set default display start line
|
||||
|
||||
// use the following two lines to flip the display
|
||||
writeCommand(0xa0 | 0x01); // set segment re-map
|
||||
writeCommand(0xc8); // set COM output scan direction
|
||||
|
||||
writeCommand(0xda, 0x12); // set COM pins hardware configuration
|
||||
writeCommand(0xd9, 0xf1); // set pre-charge period to 241x DCLK
|
||||
writeCommand(0xdB, 0x40); // set VCOMH deselect level
|
||||
writeCommand(0xa4); // display RAM content (not all-on)
|
||||
writeCommand(0xa6); // set normal (not-inverted) display
|
||||
|
||||
// set this since we don't have access to the OLED's reset pins (?)
|
||||
writeCommand(0x21, 0, 127); // set column address
|
||||
writeCommand(0x22, 0, 7); // set page address
|
||||
|
||||
writeCommand(0x81, 0xcf); // set contrast
|
||||
writeCommand(0x2e); // deactivate scroll
|
||||
writeCommand(0xaf); // turn display on
|
||||
}
|
||||
|
||||
void invert(boolean inverted) {
|
||||
if (inverted) {
|
||||
writeCommand(0xa7);
|
||||
} else {
|
||||
writeCommand(0xa6);
|
||||
}
|
||||
}
|
||||
|
||||
void sendImage(PImage img) {
|
||||
sendImage(img, 0, 0);
|
||||
}
|
||||
|
||||
void sendImage(PImage img, int startX, int startY) {
|
||||
byte[] frame = new byte[1024];
|
||||
img.loadPixels();
|
||||
for (int y=startY; y < height && y-startY < 64; y++) {
|
||||
for (int x=startX; x < width && x-startX < 128; x++) {
|
||||
if (brightness(img.pixels[y*img.width+x]) < 128) {
|
||||
// this isn't the normal (scanline) mapping, but 8 pixels below each other at a time
|
||||
// white pixels have their bit turned on
|
||||
frame[x + (y/8)*128] |= (1 << (y % 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
sendFramebuffer(frame);
|
||||
}
|
||||
|
||||
void sendFramebuffer(byte[] buf) {
|
||||
if (buf.length != 1024) {
|
||||
System.err.println("The framebuffer should be 1024 bytes long, with one bit per pixel");
|
||||
throw new IllegalArgumentException("Unexpected buffer size");
|
||||
}
|
||||
|
||||
writeCommand(0x00 | 0x0); // set start address
|
||||
writeCommand(0x10 | 0x0); // set higher column start address
|
||||
writeCommand(0x40 | 0x0); // set start line
|
||||
|
||||
// send the frame buffer as 16 byte long packets
|
||||
for (int i=0; i < buf.length/16; i++) {
|
||||
super.beginTransmission(address);
|
||||
super.write(0x40); // indicates data write
|
||||
for (int j=0; j < 16; j++) {
|
||||
super.write(buf[i*16+j]);
|
||||
}
|
||||
super.endTransmission();
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeCommand(int arg1) {
|
||||
super.beginTransmission(address);
|
||||
super.write(0x00); // indicates command write
|
||||
super.write(arg1);
|
||||
super.endTransmission();
|
||||
}
|
||||
|
||||
protected void writeCommand(int arg1, int arg2) {
|
||||
super.beginTransmission(address);
|
||||
super.write(0x00);
|
||||
super.write(arg1);
|
||||
super.write(arg2);
|
||||
super.endTransmission();
|
||||
}
|
||||
|
||||
protected void writeCommand(int arg1, int arg2, int arg3) {
|
||||
super.beginTransmission(address);
|
||||
super.write(0x00);
|
||||
super.write(arg1);
|
||||
super.write(arg2);
|
||||
super.write(arg3);
|
||||
super.endTransmission();
|
||||
}
|
||||
}
|
||||
@@ -22,9 +22,9 @@ void draw() {
|
||||
// make the LEDs count in binary
|
||||
for (int i=0; i < leds.length; i++) {
|
||||
if ((frameCount & (1 << i)) != 0) {
|
||||
leds[i].set(1.0);
|
||||
leds[i].brightness(1.0);
|
||||
} else {
|
||||
leds[i].set(0.0);
|
||||
leds[i].brightness(0.0);
|
||||
}
|
||||
}
|
||||
println(frameCount);
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import processing.io.SPI;
|
||||
|
||||
// MCP3008 is a Analog-to-Digital converter using SPI
|
||||
// other than the MCP3001, this has 8 input channels
|
||||
// datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf
|
||||
|
||||
class MCP3008 extends SPI {
|
||||
|
||||
MCP3008(String dev) {
|
||||
super(dev);
|
||||
super.settings(500000, SPI.MSBFIRST, SPI.MODE0);
|
||||
}
|
||||
|
||||
float getAnalog(int channel) {
|
||||
if (channel < 0 || 7 < channel) {
|
||||
System.err.println("The channel needs to be from 0 to 7");
|
||||
throw new IllegalArgumentException("Unexpected channel");
|
||||
}
|
||||
byte[] out = { 0, 0, 0 };
|
||||
// encode the channel number in the first byte
|
||||
out[0] = (byte)(0x18 | channel);
|
||||
byte[] in = super.transfer(out);
|
||||
int val = ((in[1] & 0x03) << 8) | (in[2] & 0xff);
|
||||
// val is between 0 and 1023
|
||||
return val/1023.0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import processing.io.*;
|
||||
MCP3008 adc;
|
||||
|
||||
// see setup.png in the sketch folder for wiring details
|
||||
|
||||
void setup() {
|
||||
//printArray(SPI.list());
|
||||
adc = new MCP3008(SPI.list()[0]);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(adc.getAnalog(0) * 255);
|
||||
fill(adc.getAnalog(1) * 255);
|
||||
ellipse(width/2, height/2, width * 0.75, width * 0.75);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import processing.io.*;
|
||||
|
||||
// using a capacitor that gets charged and discharged, while
|
||||
// measuring the time it takes, is an inexpensive way to
|
||||
// read the value of an (analog) resistive sensor, such as
|
||||
// a photocell
|
||||
// kudos to ladyada for the original tutorial
|
||||
|
||||
// see setup.png in the sketch folder for wiring details
|
||||
|
||||
int max = 0;
|
||||
int min = 9999;
|
||||
|
||||
void setup() {
|
||||
}
|
||||
|
||||
void draw() {
|
||||
int val = sensorRead(4);
|
||||
println(val);
|
||||
|
||||
// track largest and smallest reading, to get a sense
|
||||
// how we compare
|
||||
if (max < val) {
|
||||
max = val;
|
||||
}
|
||||
if (val < min) {
|
||||
min = val;
|
||||
}
|
||||
|
||||
// convert current reading into a number between 0.0 and 1.0
|
||||
float frac = map(val, min, max, 0.0, 1.0);
|
||||
|
||||
background(255 * frac);
|
||||
}
|
||||
|
||||
int sensorRead(int pin) {
|
||||
// discharge the capacitor
|
||||
GPIO.pinMode(pin, GPIO.OUTPUT);
|
||||
GPIO.digitalWrite(pin, GPIO.LOW);
|
||||
delay(100);
|
||||
// now the capacitor should be empty
|
||||
|
||||
// measure the time takes to fill it
|
||||
// up to ~ 1.4V again
|
||||
GPIO.pinMode(pin, GPIO.INPUT);
|
||||
int start = millis();
|
||||
while (GPIO.digitalRead(pin) == GPIO.LOW) {
|
||||
// wait
|
||||
}
|
||||
|
||||
// return the time elapsed
|
||||
// this will vary based on the value of the
|
||||
// resistive sensor (lower resistance will
|
||||
// make the capacitor charge faster)
|
||||
return millis() - start;
|
||||
}
|
||||
@@ -1,2 +1,9 @@
|
||||
name = Hardware I/O
|
||||
authors = The Processing Foundation
|
||||
url = http://processing.org/reference/libraries/io/index.html
|
||||
categories = Hardware
|
||||
sentence = Access peripherals on the Raspberry Pi and other Linux-based computers.
|
||||
paragraph = For other platforms, this is solely provided in order to build and export sketches that require processing.io.
|
||||
version = 1
|
||||
prettyVersion = 1
|
||||
minRevision = 247
|
||||
|
||||
@@ -177,6 +177,10 @@ public class GPIO {
|
||||
public static int digitalRead(int pin) {
|
||||
checkValidPin(pin);
|
||||
|
||||
if (NativeInterface.isSimulated()) {
|
||||
return LOW;
|
||||
}
|
||||
|
||||
String fn = String.format("/sys/class/gpio/gpio%d/value", pin);
|
||||
byte in[] = new byte[2];
|
||||
int ret = NativeInterface.readFile(fn, in);
|
||||
@@ -222,6 +226,10 @@ public class GPIO {
|
||||
throw new IllegalArgumentException("Illegal value");
|
||||
}
|
||||
|
||||
if (NativeInterface.isSimulated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String fn = String.format("/sys/class/gpio/gpio%d/value", pin);
|
||||
int ret = NativeInterface.writeFile(fn, out);
|
||||
if (ret < 0) {
|
||||
@@ -278,6 +286,10 @@ public class GPIO {
|
||||
throw new IllegalArgumentException("Unknown mode");
|
||||
}
|
||||
|
||||
if (NativeInterface.isSimulated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String fn = String.format("/sys/class/gpio/gpio%d/edge", pin);
|
||||
int ret = NativeInterface.writeFile(fn, out);
|
||||
if (ret < 0) {
|
||||
@@ -325,6 +337,10 @@ public class GPIO {
|
||||
public static void pinMode(int pin, int mode) {
|
||||
checkValidPin(pin);
|
||||
|
||||
if (NativeInterface.isSimulated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// export pin through sysfs
|
||||
String fn = "/sys/class/gpio/export";
|
||||
int ret = NativeInterface.writeFile(fn, Integer.toString(pin));
|
||||
@@ -409,6 +425,10 @@ public class GPIO {
|
||||
public static void releasePin(int pin) {
|
||||
checkValidPin(pin);
|
||||
|
||||
if (NativeInterface.isSimulated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String fn = "/sys/class/gpio/unexport";
|
||||
int ret = NativeInterface.writeFile(fn, Integer.toString(pin));
|
||||
if (ret < 0) {
|
||||
@@ -451,6 +471,14 @@ public class GPIO {
|
||||
protected static boolean waitForInterrupt(int pin, int timeout) {
|
||||
checkValidPin(pin);
|
||||
|
||||
if (NativeInterface.isSimulated()) {
|
||||
// pretend the interrupt happens after 200ms
|
||||
try {
|
||||
Thread.sleep(200);
|
||||
} catch (InterruptedException e) {}
|
||||
return true;
|
||||
}
|
||||
|
||||
String fn = String.format("/sys/class/gpio/gpio%d/value", pin);
|
||||
int ret = NativeInterface.pollDevice(fn, timeout);
|
||||
if (ret < 0) {
|
||||
|
||||
@@ -50,6 +50,11 @@ public class I2C {
|
||||
public I2C(String dev) {
|
||||
NativeInterface.loadLibrary();
|
||||
this.dev = dev;
|
||||
|
||||
if (NativeInterface.isSimulated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
handle = NativeInterface.openDevice("/dev/" + dev);
|
||||
if (handle < 0) {
|
||||
throw new RuntimeException(NativeInterface.getError(handle));
|
||||
@@ -81,6 +86,10 @@ public class I2C {
|
||||
* @webref
|
||||
*/
|
||||
public void close() {
|
||||
if (NativeInterface.isSimulated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
NativeInterface.closeDevice(handle);
|
||||
handle = 0;
|
||||
}
|
||||
@@ -107,6 +116,10 @@ public class I2C {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NativeInterface.isSimulated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// implement these flags if needed: https://github.com/raspberrypi/linux/blob/rpi-patches/Documentation/i2c/i2c-protocol
|
||||
int ret = NativeInterface.transferI2c(handle, slave, out, null);
|
||||
transmitting = false;
|
||||
@@ -126,6 +139,11 @@ public class I2C {
|
||||
* @webref
|
||||
*/
|
||||
public static String[] list() {
|
||||
if (NativeInterface.isSimulated()) {
|
||||
// as on the Raspberry Pi
|
||||
return new String[]{ "i2c-1" };
|
||||
}
|
||||
|
||||
ArrayList<String> devs = new ArrayList<String>();
|
||||
File dir = new File("/dev");
|
||||
File[] files = dir.listFiles();
|
||||
@@ -159,6 +177,10 @@ public class I2C {
|
||||
|
||||
byte[] in = new byte[len];
|
||||
|
||||
if (NativeInterface.isSimulated()) {
|
||||
return in;
|
||||
}
|
||||
|
||||
int ret = NativeInterface.transferI2c(handle, slave, out, in);
|
||||
transmitting = false;
|
||||
out = null;
|
||||
@@ -211,18 +233,30 @@ public class I2C {
|
||||
|
||||
/**
|
||||
* Adds a byte to be written to the attached device
|
||||
* @param out single byte to be written (0-255)
|
||||
* @param out single byte to be written, e.g. numeric literal (0 to 255, or -128 to 127)
|
||||
* @see beginTransmission
|
||||
* @see read
|
||||
* @see endTransmission
|
||||
*/
|
||||
public void write(int out) {
|
||||
if (out < 0 || 255 < out) {
|
||||
System.err.println("The write function can only operate on a single byte at a time. Call it with a value from 0 to 255.");
|
||||
if (out < -128 || 255 < out) {
|
||||
System.err.println("The write function can only operate on a single byte at a time. Call it with a value from 0 to 255, or -128 to 127.");
|
||||
throw new RuntimeException("Argument does not fit into a single byte");
|
||||
}
|
||||
byte[] tmp = new byte[1];
|
||||
tmp[0] = (byte)out;
|
||||
write(tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a byte to be written to the attached device
|
||||
* @param out single byte to be written
|
||||
* @see beginTransmission
|
||||
* @see read
|
||||
* @see endTransmission
|
||||
*/
|
||||
public void write(byte out) {
|
||||
// cast to (unsigned) int
|
||||
write(out & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,10 @@ public class LED {
|
||||
NativeInterface.loadLibrary();
|
||||
this.dev = dev;
|
||||
|
||||
if (NativeInterface.isSimulated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// read maximum brightness
|
||||
try {
|
||||
Path path = Paths.get("/sys/class/leds/" + dev + "/max_brightness");
|
||||
@@ -105,11 +109,16 @@ public class LED {
|
||||
* @webref
|
||||
*/
|
||||
public void brightness(float bright) {
|
||||
String fn = "/sys/class/leds/" + dev + "/brightness";
|
||||
if (bright < 0.0 || 1.0 < bright) {
|
||||
System.err.println("Brightness must be between 0.0 and 1.0.");
|
||||
throw new IllegalArgumentException("Illegal argument");
|
||||
}
|
||||
|
||||
if (NativeInterface.isSimulated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String fn = "/sys/class/leds/" + dev + "/brightness";
|
||||
int ret = NativeInterface.writeFile(fn, Integer.toString((int)(bright * maxBrightness)));
|
||||
if (ret < 0) {
|
||||
throw new RuntimeException(fn + ": " + NativeInterface.getError(ret));
|
||||
@@ -122,6 +131,10 @@ public class LED {
|
||||
* @webref
|
||||
*/
|
||||
public void close() {
|
||||
if (NativeInterface.isSimulated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// restore previous settings
|
||||
String fn = "/sys/class/leds/" + dev + "/brightness";
|
||||
int ret = NativeInterface.writeFile(fn, Integer.toString(prevBrightness));
|
||||
@@ -143,6 +156,11 @@ public class LED {
|
||||
* @webref
|
||||
*/
|
||||
public static String[] list() {
|
||||
if (NativeInterface.isSimulated()) {
|
||||
// as on the Raspberry Pi
|
||||
return new String[]{ "led0", "led1" };
|
||||
}
|
||||
|
||||
ArrayList<String> devs = new ArrayList<String>();
|
||||
File dir = new File("/sys/class/leds");
|
||||
File[] files = dir.listFiles();
|
||||
|
||||
@@ -26,17 +26,28 @@ package processing.io;
|
||||
public class NativeInterface {
|
||||
|
||||
protected static boolean loaded = false;
|
||||
protected static boolean alwaysSimulate = false;
|
||||
|
||||
public static void loadLibrary() {
|
||||
if (!loaded) {
|
||||
if (!"Linux".equals(System.getProperty("os.name"))) {
|
||||
throw new RuntimeException("The Processing I/O library is only supported on Linux");
|
||||
if (isSimulated()) {
|
||||
System.err.println("The Processing I/O library is not supported on this platform. Instead of values from actual hardware ports, your sketch will only receive stand-in values that allow you to test the remainder of its functionality.");
|
||||
} else {
|
||||
System.loadLibrary("processing-io");
|
||||
}
|
||||
System.loadLibrary("processing-io");
|
||||
loaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static void alwaysSimulate() {
|
||||
alwaysSimulate = true;
|
||||
}
|
||||
|
||||
public static boolean isSimulated() {
|
||||
return alwaysSimulate ||
|
||||
!"Linux".equals(System.getProperty("os.name"));
|
||||
}
|
||||
|
||||
|
||||
public static native int openDevice(String fn);
|
||||
public static native String getError(int errno);
|
||||
|
||||
@@ -57,6 +57,10 @@ public class PWM {
|
||||
chip = channel.substring(0, pos);
|
||||
this.channel = Integer.parseInt(channel.substring(pos+4));
|
||||
|
||||
if (NativeInterface.isSimulated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// export channel through sysfs
|
||||
String fn = "/sys/class/pwm/" + chip + "/export";
|
||||
int ret = NativeInterface.writeFile(fn, Integer.toString(this.channel));
|
||||
@@ -89,6 +93,10 @@ public class PWM {
|
||||
* @webref
|
||||
*/
|
||||
public void clear() {
|
||||
if (NativeInterface.isSimulated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String fn = String.format("/sys/class/pwm/%s/pwm%d/enable", chip, channel);
|
||||
int ret = NativeInterface.writeFile(fn, "0");
|
||||
if (ret < 0) {
|
||||
@@ -102,6 +110,10 @@ public class PWM {
|
||||
* @webref
|
||||
*/
|
||||
public void close() {
|
||||
if (NativeInterface.isSimulated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// XXX: implicit clear()?
|
||||
// XXX: also check GPIO
|
||||
|
||||
@@ -124,6 +136,10 @@ public class PWM {
|
||||
* @webref
|
||||
*/
|
||||
public static String[] list() {
|
||||
if (NativeInterface.isSimulated()) {
|
||||
return new String[]{ "pwmchip0/pwm0", "pwmchip0/pwm1" };
|
||||
}
|
||||
|
||||
ArrayList<String> devs = new ArrayList<String>();
|
||||
File dir = new File("/sys/class/pwm");
|
||||
File[] chips = dir.listFiles();
|
||||
@@ -155,6 +171,10 @@ public class PWM {
|
||||
* @webref
|
||||
*/
|
||||
public void set(int period, float duty) {
|
||||
if (NativeInterface.isSimulated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// set period
|
||||
String fn = fn = String.format("/sys/class/pwm/%s/pwm%d/period", chip, channel);
|
||||
// convert to nanoseconds
|
||||
|
||||
@@ -78,6 +78,11 @@ public class SPI {
|
||||
public SPI(String dev) {
|
||||
NativeInterface.loadLibrary();
|
||||
this.dev = dev;
|
||||
|
||||
if (NativeInterface.isSimulated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
handle = NativeInterface.openDevice("/dev/" + dev);
|
||||
if (handle < 0) {
|
||||
throw new RuntimeException(NativeInterface.getError(handle));
|
||||
@@ -90,6 +95,10 @@ public class SPI {
|
||||
* @webref
|
||||
*/
|
||||
public void close() {
|
||||
if (NativeInterface.isSimulated()) {
|
||||
return;
|
||||
}
|
||||
|
||||
NativeInterface.closeDevice(handle);
|
||||
handle = 0;
|
||||
}
|
||||
@@ -110,6 +119,11 @@ public class SPI {
|
||||
* @webref
|
||||
*/
|
||||
public static String[] list() {
|
||||
if (NativeInterface.isSimulated()) {
|
||||
// as on the Raspberry Pi
|
||||
return new String[]{ "spidev0.0", "spidev0.1" };
|
||||
}
|
||||
|
||||
ArrayList<String> devs = new ArrayList<String>();
|
||||
File dir = new File("/dev");
|
||||
File[] files = dir.listFiles();
|
||||
@@ -148,6 +162,10 @@ public class SPI {
|
||||
* @webref
|
||||
*/
|
||||
public byte[] transfer(byte[] out) {
|
||||
if (NativeInterface.isSimulated()) {
|
||||
return new byte[out.length];
|
||||
}
|
||||
|
||||
// track the current setting per device across multiple instances
|
||||
String curSettings = maxSpeed + "-" + dataOrder + "-" + mode;
|
||||
if (!curSettings.equals(settings.get(dev))) {
|
||||
@@ -182,16 +200,27 @@ public class SPI {
|
||||
|
||||
/**
|
||||
* Transfers data over the SPI bus
|
||||
* @param out single byte to send
|
||||
* @param out single byte to send, e.g. numeric literal (0 to 255, or -128 to 127)
|
||||
* @return bytes read in (array is the same length as out)
|
||||
*/
|
||||
public byte[] transfer(int out) {
|
||||
if (out < 0 || 255 < out) {
|
||||
System.err.println("The transfer function can only operate on a single byte at a time. Call it with a value from 0 to 255.");
|
||||
if (out < -128 || 255 < out) {
|
||||
System.err.println("The transfer function can only operate on a single byte at a time. Call it with a value from 0 to 255, or -128 to 127.");
|
||||
throw new RuntimeException("Argument does not fit into a single byte");
|
||||
}
|
||||
byte[] tmp = new byte[1];
|
||||
tmp[0] = (byte)out;
|
||||
return transfer(tmp);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Transfers data over the SPI bus
|
||||
* @param out single byte to send
|
||||
* @return bytes read in (array is the same length as out)
|
||||
*/
|
||||
public byte[] transfer(byte out) {
|
||||
// cast to (unsigned) int
|
||||
return transfer(out & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user