| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,7 +5,10 @@ import processing.io.*; | |||
| 5 | 5 | // see setup.png in the sketch folder for wiring details | |
| 6 | 6 | ||
| 7 | 7 | void setup() { | |
| 8 | - GPIO.pinMode(4, GPIO.INPUT); | ||
| 8 | + // INPUT_PULLUP enables the built-in pull-up resistor for this pin | ||
| 9 | + // left alone, the pin will read as HIGH | ||
| 10 | + // connected to ground (via e.g. a button or switch) it will read LOW | ||
| 11 | + GPIO.pinMode(4, GPIO.INPUT_PULLUP); | ||
| 9 | 12 | } | |
| 10 | 13 | ||
| 11 | 14 | void draw() { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -30,6 +30,7 @@ | |||
| 30 | 30 | #include <stdlib.h> | |
| 31 | 31 | #include <string.h> | |
| 32 | 32 | #include <sys/ioctl.h> | |
| 33 | + #include <sys/mman.h> | ||
| 33 | 34 | #include <sys/param.h> | |
| 34 | 35 | #include <time.h> | |
| 35 | 36 | #include <unistd.h> | |
@@ -120,6 +121,143 @@ JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_writeFile | |||
| 120 | 121 | } | |
| 121 | 122 | ||
| 122 | 123 | ||
| 124 | + JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_raspbianGpioMemRead | ||
| 125 | + (JNIEnv *env, jclass cls, jint offset) | ||
| 126 | + { | ||
| 127 | + // validate offset | ||
| 128 | + if (4096 <= offset) { | ||
| 129 | + return -EINVAL; | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + int file = open("/dev/gpiomem", O_RDWR|O_SYNC); | ||
| 133 | + if (file < 0) { | ||
| 134 | + return -errno; | ||
| 135 | + } | ||
| 136 | + | ||
| 137 | + uint32_t *mem = mmap(NULL, 4096, PROT_READ, MAP_SHARED, file, 0); | ||
| 138 | + if (mem == MAP_FAILED) { | ||
| 139 | + close(file); | ||
| 140 | + return -errno; | ||
| 141 | + } | ||
| 142 | + | ||
| 143 | + uint32_t value = mem[offset]; | ||
| 144 | + | ||
| 145 | + munmap(mem, 4096); | ||
| 146 | + close(file); | ||
| 147 | + return value; | ||
| 148 | + } | ||
| 149 | + | ||
| 150 | + | ||
| 151 | + JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_raspbianGpioMemWrite | ||
| 152 | + (JNIEnv *env, jclass cls, jint offset, jint mask, jint value) | ||
| 153 | + { | ||
| 154 | + // validate offset | ||
| 155 | + if (4096 <= offset) { | ||
| 156 | + return -EINVAL; | ||
| 157 | + } | ||
| 158 | + | ||
| 159 | + int file = open("/dev/gpiomem", O_RDWR|O_SYNC); | ||
| 160 | + if (file < 0) { | ||
| 161 | + return -errno; | ||
| 162 | + } | ||
| 163 | + | ||
| 164 | + uint32_t *mem = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, file, 0); | ||
| 165 | + if (mem == MAP_FAILED) { | ||
| 166 | + close(file); | ||
| 167 | + return -errno; | ||
| 168 | + } | ||
| 169 | + | ||
| 170 | + mem[offset] = (mem[offset] & ~mask) | (value & mask); | ||
| 171 | + | ||
| 172 | + munmap(mem, 4096); | ||
| 173 | + close(file); | ||
| 174 | + return 1; // number of bytes written | ||
| 175 | + } | ||
| 176 | + | ||
| 177 | + | ||
| 178 | + #define BCM2835_GPPUD_OFFSET (0x94 >> 2) | ||
| 179 | + #define BCM2835_GPPUDCLK0_OFFSET (0x98 >> 2) | ||
| 180 | + #define BCM2835_GPPUDCLK1_OFFSET (0x9c >> 2) | ||
| 181 | + | ||
| 182 | + JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_raspbianGpioMemSetPinBias | ||
| 183 | + (JNIEnv *env, jclass cls, jint gpio, jint mode) | ||
| 184 | + { | ||
| 185 | + int ret = 0; // success | ||
| 186 | + | ||
| 187 | + int file = open("/dev/gpiomem", O_RDWR|O_SYNC); | ||
| 188 | + if (file < 0) { | ||
| 189 | + return -errno; | ||
| 190 | + } | ||
| 191 | + | ||
| 192 | + uint32_t *mem = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, file, 0); | ||
| 193 | + if (mem == MAP_FAILED) { | ||
| 194 | + close(file); | ||
| 195 | + return -errno; | ||
| 196 | + } | ||
| 197 | + | ||
| 198 | + // validate arguments | ||
| 199 | + if (gpio < 0 || 53 < gpio) { | ||
| 200 | + ret = -EINVAL; | ||
| 201 | + goto out; | ||
| 202 | + } | ||
| 203 | + | ||
| 204 | + // see BCM2835 datasheet, p. 101 | ||
| 205 | + uint32_t pud; | ||
| 206 | + if (mode == 0) { | ||
| 207 | + pud = 0; // floating | ||
| 208 | + } else if (mode == 2) { | ||
| 209 | + pud = 2; // pull-up | ||
| 210 | + } else if (mode == 3) { | ||
| 211 | + pud = 1; // pull-down | ||
| 212 | + } else { | ||
| 213 | + ret = -EINVAL; | ||
| 214 | + goto out; | ||
| 215 | + } | ||
| 216 | + | ||
| 217 | + /* | ||
| 218 | + * From the BCM2835 datasheet, p. 101: | ||
| 219 | + * | ||
| 220 | + * The following sequence of events is required: | ||
| 221 | + * 1. Write to GPPUD to set the required control signal (i.e. Pull-up or | ||
| 222 | + * Pull-Down or neither to remove the current Pull-up/down) | ||
| 223 | + * 2. Wait 150 cycles – this provides the required set-up time for the | ||
| 224 | + * control signal | ||
| 225 | + * 3. Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads | ||
| 226 | + * you wish to modify – NOTE only the pads which receive a clock will | ||
| 227 | + * be modified, all others will retain their previous state. | ||
| 228 | + * 4. Wait 150 cycles – this provides the required hold time for the | ||
| 229 | + * control signal | ||
| 230 | + * 5. Write to GPPUD to remove the control signal | ||
| 231 | + * 6. Write to GPPUDCLK0/1 to remove the clock | ||
| 232 | + */ | ||
| 233 | + | ||
| 234 | + // python-gpiozero uses a delay of 214 ns, so we do the same | ||
| 235 | + struct timespec wait; | ||
| 236 | + wait.tv_sec = 0; | ||
| 237 | + wait.tv_nsec = 214; | ||
| 238 | + | ||
| 239 | + mem[BCM2835_GPPUD_OFFSET] = pud; | ||
| 240 | + nanosleep(&wait, NULL); | ||
| 241 | + if (gpio < 32) { | ||
| 242 | + mem[BCM2835_GPPUDCLK0_OFFSET] = 1 << gpio; | ||
| 243 | + } else { | ||
| 244 | + mem[BCM2835_GPPUDCLK1_OFFSET] = 1 << (gpio-32); | ||
| 245 | + } | ||
| 246 | + nanosleep(&wait, NULL); | ||
| 247 | + mem[BCM2835_GPPUD_OFFSET] = 0; | ||
| 248 | + if (gpio < 32) { | ||
| 249 | + mem[BCM2835_GPPUDCLK0_OFFSET] = 0; | ||
| 250 | + } else { | ||
| 251 | + mem[BCM2835_GPPUDCLK1_OFFSET] = 0; | ||
| 252 | + } | ||
| 253 | + | ||
| 254 | + out: | ||
| 255 | + munmap(mem, 4096); | ||
| 256 | + close(file); | ||
| 257 | + return ret; | ||
| 258 | + } | ||
| 259 | + | ||
| 260 | + | ||
| 123 | 261 | JNIEXPORT jint JNICALL Java_processing_io_NativeInterface_pollDevice | |
| 124 | 262 | (JNIEnv *env, jclass cls, jstring _fn, jint timeout) | |
| 125 | 263 | { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -328,7 +328,7 @@ public static void noInterrupts() { | |||
| 328 | 328 | /** | |
| 329 | 329 | * Configures a pin to act either as input or output | |
| 330 | 330 | * @param pin GPIO pin | |
| 331 | - * @param mode GPIO.INPUT or GPIO.OUTPUT | ||
| 331 | + * @param mode GPIO.INPUT, GPIO.INPUT_PULLUP, GPIO.INPUT_PULLDOWN, or GPIO.OUTPUT | ||
| 332 | 332 | * @see digitalRead | |
| 333 | 333 | * @see digitalWrite | |
| 334 | 334 | * @see releasePin | |
@@ -369,16 +369,29 @@ public static void pinMode(int pin, int mode) { | |||
| 369 | 369 | String out; | |
| 370 | 370 | if (mode == INPUT) { | |
| 371 | 371 | out = "in"; | |
| 372 | + | ||
| 373 | + // attempt to disable any pre-set pullups on the Raspberry Pi | ||
| 374 | + NativeInterface.raspbianGpioMemSetPinBias(pin, mode); | ||
| 375 | + | ||
| 372 | 376 | } else if (mode == OUTPUT) { | |
| 373 | 377 | if (values.get(pin)) { | |
| 374 | 378 | out = "high"; | |
| 375 | 379 | } else { | |
| 376 | 380 | out = "low"; | |
| 377 | 381 | } | |
| 378 | 382 | } else if (mode == INPUT_PULLUP || mode == INPUT_PULLDOWN) { | |
| 383 | + out = "in"; | ||
| 384 | + | ||
| 385 | + // attempt to set pullups on the Raspberry Pi | ||
| 386 | + ret = NativeInterface.raspbianGpioMemSetPinBias(pin, mode); | ||
| 387 | + if (ret == -2) { // NOENT | ||
| 388 | + System.err.println("Setting pullup or pulldown resistors is currently only supported on the Raspberry Pi running Raspbian. Continuing without."); | ||
| 389 | + } else if (ret < 0) { | ||
| 390 | + System.err.println("Error setting pullup or pulldown resistors: " + NativeInterface.getError(ret) + ". Continuing without."); | ||
| 391 | + } | ||
| 379 | 392 | // currently this can't be done in a non-platform-specific way, see | |
| 380 | 393 | // http://lists.infradead.org/pipermail/linux-rpi-kernel/2015-August/002146.html | |
| 381 | - throw new RuntimeException("Not yet implemented"); | ||
| 394 | + | ||
| 382 | 395 | } else { | |
| 383 | 396 | throw new IllegalArgumentException("Unknown mode"); | |
| 384 | 397 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -62,6 +62,9 @@ public static int writeFile(String fn, String out) { | |||
| 62 | 62 | } | |
| 63 | 63 | ||
| 64 | 64 | /* GPIO */ | |
| 65 | + public static native int raspbianGpioMemRead(int offset); | ||
| 66 | + public static native int raspbianGpioMemWrite(int offset, int mask, int value); | ||
| 67 | + public static native int raspbianGpioMemSetPinBias(int gpio, int mode); | ||
| 65 | 68 | public static native int pollDevice(String fn, int timeout); | |
| 66 | 69 | /* I2C */ | |
| 67 | 70 | public static native int transferI2c(int handle, int slave, byte[] out, byte[] in); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments