Skip to content

Instantly share code, notes, and snippets.

@janisz
Last active August 29, 2015 14:19
Show Gist options
  • Save janisz/b81ff39092a77ce0841a to your computer and use it in GitHub Desktop.
Save janisz/b81ff39092a77ce0841a to your computer and use it in GitHub Desktop.
LINSW - GIPO
/* Copyright (c) 2011, RidgeRun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the RidgeRun.
* 4. Neither the name of the RidgeRun nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY RIDGERUN ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL RIDGERUN BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
/****************************************************************
* Constants
****************************************************************/
#define SYSFS_GPIO_DIR "/sys/class/gpio"
#define MAX_BUF 64
/****************************************************************
* gpio_export
****************************************************************/
int gpio_export(unsigned int gpio)
{
int fd, len;
char buf[MAX_BUF];
fd = open(SYSFS_GPIO_DIR "/export", O_WRONLY);
if (fd < 0) {
perror("gpio/export");
return fd;
}
len = snprintf(buf, sizeof(buf), "%d", gpio);
write(fd, buf, len);
close(fd);
return 0;
}
/****************************************************************
* gpio_unexport
****************************************************************/
int gpio_unexport(unsigned int gpio)
{
int fd, len;
char buf[MAX_BUF];
fd = open(SYSFS_GPIO_DIR "/unexport", O_WRONLY);
if (fd < 0) {
perror("gpio/export");
return fd;
}
len = snprintf(buf, sizeof(buf), "%d", gpio);
write(fd, buf, len);
close(fd);
return 0;
}
/****************************************************************
* gpio_set_dir
****************************************************************/
int gpio_set_dir(unsigned int gpio, unsigned int out_flag)
{
int fd, len;
char buf[MAX_BUF];
len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/direction", gpio);
fd = open(buf, O_WRONLY);
if (fd < 0) {
perror(buf);
return fd;
}
if (out_flag)
write(fd, "out", 4);
else
write(fd, "in", 3);
close(fd);
return 0;
}
/****************************************************************
* gpio_set_value
****************************************************************/
int gpio_set_value(unsigned int gpio, unsigned int value)
{
int fd, len;
char buf[MAX_BUF];
len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
fd = open(buf, O_WRONLY);
if (fd < 0) {
perror("gpio/set-value");
return fd;
}
if (value)
write(fd, "1", 2);
else
write(fd, "0", 2);
close(fd);
return 0;
}
/****************************************************************
* gpio_get_value
****************************************************************/
int gpio_get_value(unsigned int gpio, unsigned int *value)
{
int fd, len;
char buf[MAX_BUF];
char ch;
len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
fd = open(buf, O_RDONLY);
if (fd < 0) {
perror("gpio/get-value");
return fd;
}
read(fd, &ch, 1);
if (ch != '0') {
*value = 1;
} else {
*value = 0;
}
close(fd);
return 0;
}
/****************************************************************
* gpio_set_edge
****************************************************************/
int gpio_set_edge(unsigned int gpio, char *edge)
{
int fd, len;
char buf[MAX_BUF];
len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/edge", gpio);
fd = open(buf, O_WRONLY);
if (fd < 0) {
perror("gpio/set-edge");
return fd;
}
write(fd, edge, strlen(edge) + 1);
close(fd);
return 0;
}
/****************************************************************
* gpio_fd_open
****************************************************************/
int gpio_fd_open(unsigned int gpio)
{
int fd, len;
char buf[MAX_BUF];
len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
fd = open(buf, O_RDONLY | O_NONBLOCK );
if (fd < 0) {
perror("gpio/fd_open");
}
return fd;
}
/****************************************************************
* gpio_fd_close
****************************************************************/
int gpio_fd_close(int fd)
{
return close(fd);
}
#include "gpio.c"
#define POLL_TIMEOUT (3 * 1000) /* 3 seconds */
#define KEYS_COUNT 3
#define OUT 1
#define IN 0
int initialize_gpio(int gpio, unsigned int direction) {
gpio_export(gpio);
gpio_set_dir(gpio, direction);
gpio_set_edge(gpio, "rising");
return gpio_fd_open(gpio);
}
void clear_leds(unsigned int const led[]) {
for (int j=0;j<KEYS_COUNT;j++) {
gpio_set_value(led[j], 0);
}
gpio_set_value(24, 0); //HACK
}
int main(int argc, char **argv, char **envp)
{
int nfds = 3;
struct pollfd fdset[nfds];
int timeout, rc;
char *buf[MAX_BUF];
int len;
timeout = POLL_TIMEOUT;
if (argc < 2) {
printf("Usage: %s <sequence length>\n\n", argv[0]);
exit(-1);
}
int sequenceLength = atoi(argv[1]);
unsigned int const key[] = { 10, 22, 27 };
int *keysFd = malloc(KEYS_COUNT*sizeof(int));
unsigned int const led[] = { 23, 18, 17 };
for (int i=0; i<KEYS_COUNT;i++) {
unsigned int gpio;
keysFd[i] = initialize_gpio(key[i], IN);
}
for (int i=0; i<KEYS_COUNT;i++) {
initialize_gpio(led[i], OUT);
gpio_set_value(led[i], 1);
}
const int redLed = 24;
initialize_gpio(redLed, OUT);
unsigned int* sequence;
sequence = malloc(sequenceLength *sizeof(int));
srand(time(NULL));
for (int i=0; i< sequenceLength; i++) {
clear_leds(led);
sleep(1);
int random = rand() % KEYS_COUNT;
sequence[i] = random;
gpio_set_value(led[random], 1);
sleep(1);
}
int pressed_keys = -1;
int guessed_keys = 0;
while(1) {
if (pressed_keys >= sequenceLength) {
break;
}
memset((void*)fdset, 0, sizeof(fdset));
for (int i=0;i<KEYS_COUNT;i++) {
fdset[i].fd = keysFd[i];
fdset[i].events = POLLPRI;
}
rc = poll(fdset, nfds, timeout);
clear_leds(led);
if (rc < 0) {
printf("\npoll() failed!\n");
return -1;
}
if (rc == 0) {
gpio_set_value(redLed, 1);
printf("TIMEOUT!\n");
pressed_keys++;
}
//HACK
if (pressed_keys == -1) {
pressed_keys++;
for (int key_iter = 0;key_iter<KEYS_COUNT;key_iter++) {
read(fdset[key_iter].fd, buf, MAX_BUF);
}
continue;
}
for (int i=0;i<KEYS_COUNT; i++) {
if (fdset[i].revents & POLLPRI) {
len = read(fdset[i].fd, buf, MAX_BUF);
printf("\npoll() GPIO %d interrupt occurred\n", key[i]);
gpio_set_value(led[i], 1);
if (sequence[pressed_keys] != i) {
gpio_set_value(redLed, 1);
printf("Pomylka! Oczekiwano klawisza %d\n", key[sequence[pressed_keys]]);
}
pressed_keys++;
guessed_keys++;
break;
}
}
usleep(100); //HACK
fflush(stdout);
}
clear_leds(led);
for (int i=0; i< KEYS_COUNT; i++) {
gpio_fd_close(keysFd[i]);
}
printf("Wynik %d/%d", guessed_keys, sequenceLength);
return 0;
}
OBJS := main.o
memo: $(OBJS)
$(CC) -o memo $(OBJS)
$(OBJS) : %.o : %.c
$(CC) -c $(CFLAGS) $< -o $@ -std=c99
#!/usr/bin/python
# http://raspberrypi.stackexchange.com/a/4754
import os
import select
from random import randint
from time import sleep
EXPORT_PATH = '/sys/class/gpio/export'
PIN_BASE_PATH = "/sys/class/gpio/gpio"
KEYS = [10, 22, 27]
LEDS = [23, 18, 17]
fds = {}
red_led = open(os.path.join('%s%d' % (PIN_BASE_PATH, 24), 'value'), 'w')
def initialize(pin_number, direction):
try:
write_once(EXPORT_PATH, pin_number)
except:
pass
pin_path = '%s%d' % (PIN_BASE_PATH, pin_number)
print pin_path
write_once(os.path.join(pin_path, 'direction'), direction)
write_once(os.path.join(pin_path, 'edge'), 'falling')
file_io = open(os.path.join(pin_path, 'value'), 'w' if direction == 'out' else 'r', 0)
return file_io
def write_once(path, value):
with open(path, 'w') as f:
f.write("%s" % value)
def clean_leds():
red_led.write('0')
for _, f in leds.iteritems():
f.seek(0)
f.write('0')
keys = {}
for pin_number in KEYS:
file_io = initialize(pin_number, 'in')
keys[pin_number] = file_io
fds[file_io.fileno()] = pin_number
leds = {}
for pin_number in LEDS:
leds[pin_number] = initialize(pin_number, 'out')
po = select.poll()
for pin_number, fd in keys.iteritems():
po.register(fd, select.POLLPRI)
sequence = [randint(0, 2) for i in range(5)]
print sequence
for i in sequence:
clean_leds()
sleep(1)
leds[LEDS[i]].write('1')
sleep(1)
sleep(1)
clean_leds()
guessed = 0
j = 0
while 1:
events = po.poll(30000)
if not events:
clean_leds()
red_led.write('1')
print ('TIMEOUT!')
for fd, flag in events:
print 'poll() GPIO %d interrupt occurred' % fds[fd]
clicked = 0
for i in xrange(10):
sleep(1/100)
os.lseek(fd, 0, 0)
val = os.read(fd, 1)
if val == "0":
clicked += 1
if clicked > 5:
clean_leds()
keys_index = KEYS.index(fds[fd])
leds[LEDS[keys_index]].write('1')
sleep(1/10)
if keys_index == sequence[j]:
print "OK"
guessed += 1
else:
print "Expected %d but got %d" % (sequence[j], keys_index)
j += 1
if j == len(sequence):
break
clean_leds()
print "Score %d/%d" % (guessed, len(sequence))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment