diff options
Diffstat (limited to 'recipes-demo/de10-nano-adxl-apps/files')
10 files changed, 1275 insertions, 0 deletions
diff --git a/recipes-demo/de10-nano-adxl-apps/files/LICENSE b/recipes-demo/de10-nano-adxl-apps/files/LICENSE new file mode 100644 index 0000000..ab84792 --- /dev/null +++ b/recipes-demo/de10-nano-adxl-apps/files/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) +Copyright (c) 2016 Intel Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + diff --git a/recipes-demo/de10-nano-adxl-apps/files/README_SANDBOX.txt b/recipes-demo/de10-nano-adxl-apps/files/README_SANDBOX.txt new file mode 100644 index 0000000..6ac13df --- /dev/null +++ b/recipes-demo/de10-nano-adxl-apps/files/README_SANDBOX.txt @@ -0,0 +1,168 @@ +This readme describes how the Analog Devices ADXL345 Input 3-Axis Digital +Accelerometer Linux Driver is deployed on the DE10 Nano target environment. You +may find the following references useful for more information on this topic as +well. + +<linux-source-tree>/drivers/input/misc/adxl34x.c +<linux-source-tree>/drivers/input/misc/adxl34x.h +<linux-source-tree>/drivers/input/misc/adxl34x-i2c.c +<linux-source-tree>/drivers/input/misc/adxl34x-spi.c +<linux-source-tree>/include/linux/input/adxl34x.h + +http://wiki.analog.com/resources/tools-software/linux-drivers/input-misc/adxl345 + +If you cut and paste the following function into a console running on the DE10 +Nano target you can extract the useful information contained in the run time +device tree maintained by the kernel in the procfs. +################################################################################ +# find adxl34x in device tree +################################################################################ +function find_adxl_dt () { +for NEXT in $(find -L /proc/device-tree -name "compatible" | sort) +do +cat ${NEXT} | grep "adi,adxl345" > /dev/null && { +ADXL_DIRNAME="$(dirname ${NEXT})" +echo ${ADXL_DIRNAME} +echo -e "\tcompatible = '$(cat ${ADXL_DIRNAME}/compatible)'" +echo -e "\t name = '$(cat ${ADXL_DIRNAME}/name)'" +REG_HEX="$(hexdump -v -e '"0x"' -e '4/1 "%02x"' "${ADXL_DIRNAME}/reg")" +echo -e "\t reg = '${REG_HEX}'" +} +done +} +################################################################################ + +When we run the function above on the DE10 Nano target it searches for nodes +containing the 'compatible' string containing 'adi,adxl345' which is the +identifier of the ADI accelerometer in our system. The function then prints the +path to the node that it found and extracts the compatible string and 'name' and +'reg' properties and prints those statistics out as well. + +root@de10-nano:~# find_adxl_dt +/proc/device-tree/soc/i2c@ffc04000/adxl345@0 + compatible = 'adi,adxl345' + name = 'adxl345' + reg = '0x00000053' +root@de10-nano:~# + +We can tell from the above output that this accelerometer is attached to the +I2C controller at 0xFFC04000, and the I2C address of the accelerometer is 0x53. + +There are a number of ways that we can now find the sysfs resources that refer +to this hardware: + +root@de10-nano:~# ls /sys/bus/i2c +devices drivers_autoprobe uevent +drivers drivers_probe +root@de10-nano:~# ls /sys/bus/i2c/devices/ +0-0053 i2c-0 +root@de10-nano:~# ls /sys/bus/i2c/drivers +adxl34x dummy ltc2978 pmbus +at24 lcd-comm max1619 rtc-ds1307 +root@de10-nano:~# ls /sys/bus/i2c/drivers/adxl34x/ +0-0053 bind uevent unbind +root@de10-nano:~# + +In the '/sys/bus/i2c/' directory there is a 'devices' and 'drivers' directory. +The 'devices' directory contains a link called '0-0053' which represents I2C bus +0 device address 0x53. The 'drivers' directory contains a 'adxl34x' directory +which in turn contains a link called '0-0053' as well. Both of these links +point into the actual device entry: + +root@de10-nano:~# ls -l /sys/bus/i2c/devices/0-0053 +lrwxrwxrwx 1 root root 0 Jan 1 1970 /sys/bus/i2c/devices/0-0053 -> ../../../devices/platform/soc/ffc04000.i2c/i2c-0/0-0053 +root@de10-nano:~# ls -l /sys/bus/i2c/drivers/adxl34x/0-0053 +lrwxrwxrwx 1 root root 0 Jul 11 15:21 /sys/bus/i2c/drivers/adxl34x/0-0053 -> ../../../../devices/platform/soc/ffc04000.i2c/i2c-0/0-0053 +root@de10-nano:~# + +So if we look at the contents of the actual device directory we see the expected +sysfs files provided by the adxl34x driver: + +root@de10-nano:~# ls /sys/devices/platform/soc/ffc04000.i2c/i2c-0/0-0053 +autosleep disable input name power subsystem +calibrate driver modalias position rate uevent +root@de10-nano:~# + +Some of these sysfs files are provided by the adxl34x driver to provide access +from userspace into the configuration and settings of the driver. These files +are 'autosleep', 'disable', 'calibrate', 'position', and 'rate'. Please see +the adxl34x driver sources and documentation on how these files are used. + +The 'input' sysfs file provided in the device directory will tell us which input +event device the adxl345 has been register as. If we follow this path we see: + +root@de10-nano:~# ls /sys/devices/platform/soc/ffc04000.i2c/i2c-0/0-0053/input/ +input0 + +And following into 'input0' we see: + +root@de10-nano:~# ls /sys/devices/platform/soc/ffc04000.i2c/i2c-0/0-0053/input/input0/ +capabilities id name properties uniq +device modalias phys subsystem +event0 mouse0 power uevent +root@de10-nano:~# cat /sys/devices/platform/soc/ffc04000.i2c/i2c-0/0-0053/input/input0/name +ADXL34x accelerometer + +Now if we go into the 'event0' we can see the 'dev' entry that contains the +device node details: + +root@de10-nano:~# ls /sys/devices/platform/soc/ffc04000.i2c/i2c-0/0-0053/input/input0/event0/ +dev device power subsystem uevent +root@de10-nano:~# hexdump -Cv /sys/devices/platform/soc/ffc04000.i2c/i2c-0/0-0053/input/input0/event0/dev +00000000 31 33 3a 36 34 0a |13:64.| +00000006 + +And if we then list '/dev/input/' looking for device major 13 and minor 64, we +can see that indeed '/dev/input/event0' is our accelerometer input device. + +root@de10-nano:~# ls /dev/input/ -l +total 0 +drwxr-xr-x 2 root root 80 Jul 9 16:25 by-path +crw-rw---- 1 root input 13, 64 Jan 1 1970 event0 +crw-rw---- 1 root input 13, 65 Jul 9 16:25 event1 +crw-rw---- 1 root input 13, 63 Jul 9 16:25 mice +crw-rw---- 1 root input 13, 32 Jan 1 1970 mouse0 +root@de10-nano:~# + +There is actually a very convenient way to discover the input device by using +the 'by-path' directory like this: + +root@de10-nano:~# ls /dev/input/by-path/ +platform-ffc04000.i2c-event platform-soc:keys-event +root@de10-nano:~# ls -l /dev/input/by-path/platform-ffc04000.i2c-event +lrwxrwxrwx 1 root root 9 Jan 1 1970 /dev/input/by-path/platform-ffc04000.i2c-event -> ../event0 +root@de10-nano:~# + +-------------------------------------------------------------------------------- +Example programs and scripts +-------------------------------------------------------------------------------- +This directory contains a few examples to demonstrate how to interact with the +accelerometer on the DE10 Nano board. There is a shell script called +'adxl_calibrate.sh' which shows how to calibrate the accelerometer. There is a +C program called 'watch_adxl.c' that shows how to interact with the sysfs files +and the input event node provided by the adxl34x driver. And there is a C +program called 'tap_detect.c' which demonstrates how to detect the tap events +that the accelerometer produces. + +To build the 'watch_adxl.c' application simply run the 'build_watch_adxl.sh' +shell script. That will compile the 'watch_adxl.c' source file and produce the +executable 'watch_adxl' application. Refer to the 'build_watch_adxl.sh' script +to see how the application is actually compiled and refer to the C program +source file for more details on how it actually works. + +To build the 'tap_detect.c' application simply run the 'build_tap_detect.sh' +shell script. That will compile the 'tap_detect.c' source file and produce the +executable 'tap_detect' application. Refer to the 'build_tap_detect.sh' script +to see how the application is actually compiled and refer to the C program +source file for more details on how it actually works. + +Refer to the 'adxl_calibrate.sh' source file for more details on how it +actually works. + +Once you've built the applications, you can run both the script and the +applications like this: + +./adxl_calibrate.sh <<< to run the script +./watch_adxl <<< to run the program +./tap_detect <<< to run the program + diff --git a/recipes-demo/de10-nano-adxl-apps/files/README_SRC.txt b/recipes-demo/de10-nano-adxl-apps/files/README_SRC.txt new file mode 100644 index 0000000..bee2193 --- /dev/null +++ b/recipes-demo/de10-nano-adxl-apps/files/README_SRC.txt @@ -0,0 +1,10 @@ +To build the 'bubble_demo.c' application simply run the 'build_bubble_demo.sh' +shell script. That will compile the 'bubble_demo.c' source file and produce the +executable 'bubble_demo' application. Refer to the 'build_bubble_demo.sh' +script to see how the application is actually compiled and refer to the C +program source file for more details on how it actually works. + +Once you've built the application, you can run the applications like this: + +./bubble_demo + diff --git a/recipes-demo/de10-nano-adxl-apps/files/adxl_calibrate.sh b/recipes-demo/de10-nano-adxl-apps/files/adxl_calibrate.sh new file mode 100755 index 0000000..3df7d36 --- /dev/null +++ b/recipes-demo/de10-nano-adxl-apps/files/adxl_calibrate.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +SYSFS_DEVICE_DIR="/sys/devices/platform/soc/ffc04000.i2c/i2c-0/0-0053/" +DEVFS_INPUT_EVENT_FILE="/dev/input/by-path/platform-ffc04000.i2c-event" + +# enabled adxl +echo 0 > ${SYSFS_DEVICE_DIR}/disable + +# set the sample rate to maximum +echo 15 > ${SYSFS_DEVICE_DIR}/rate + +# do not auto sleep +echo 0 > ${SYSFS_DEVICE_DIR}/autosleep + +# read some samples +hexdump -n 160 ${DEVFS_INPUT_EVENT_FILE} > /dev/null + +# store calibration +echo 1 > ${SYSFS_DEVICE_DIR}/calibrate + diff --git a/recipes-demo/de10-nano-adxl-apps/files/bubble_demo.c b/recipes-demo/de10-nano-adxl-apps/files/bubble_demo.c new file mode 100644 index 0000000..41b2019 --- /dev/null +++ b/recipes-demo/de10-nano-adxl-apps/files/bubble_demo.c @@ -0,0 +1,609 @@ +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <error.h> +#include <errno.h> +#include <limits.h> +#include <unistd.h> +#include <string.h> +#include <signal.h> +#include "linux/input.h" +#include <dirent.h> +#include <poll.h> +#include <wait.h> + +#define INPUT_DEV_NODE "/dev/input/by-path/platform-ffc04000.i2c-event" +#define SYSFS_DEVICE_DIR "/sys/devices/platform/soc/ffc04000.i2c/i2c-0/0-0053/" + +#define EV_CODE_X (0) +#define EV_CODE_Y (1) +#define EV_CODE_Z (2) + +int g_stop_running = 0; +int g_termination_count = 0; + +void write_sysfs_cntl_file(const char *dir_name, const char *file_name, + const char *write_str); + +void poll_for_KEY0_press(void); + +void my_sig_child_handler(int signal_number) { + (void)signal_number; + g_stop_running = 1; +} + +void my_termination_handler(int signal_number) { + + int result; + pid_t child_pid; + int status; + + if(g_termination_count > 0) + return; + + g_termination_count++; + + // enable heartbeat LED + write_sysfs_cntl_file("/sys/class/leds/hps_led0", "trigger", + "heartbeat"); + + // disable adxl + write_sysfs_cntl_file(SYSFS_DEVICE_DIR, "disable", "1"); + + result = kill(-(getpgrp()), SIGTERM); + if(result < 0) { + error(0, errno, "SIGTERM pgrp"); + result = kill(-(getpgrp()), SIGKILL); + if(result < 0) + error(0, errno, "SIGKILL pgrp"); + } + + do { + child_pid = wait(&status); + if((child_pid == -1) && (errno != ECHILD)) + error(1, errno, "wait"); + } while(child_pid != -1); + + // print termination signal that we received + if(signal_number == SIGTERM) + printf("Bubble level demo exiting due to SIGTERM signal...\n"); + else if(signal_number == SIGINT) + printf("Bubble level demo exiting due to SIGINT signal...\n"); + else if(signal_number == SIGQUIT) + printf("Bubble level demo exiting due to SIGQUIT signal...\n"); + else + printf("Bubble level demo exiting due to unknown signal...\n"); + + exit(EXIT_SUCCESS); +} + +int main(void) { + int i; + int result; + int event_dev_fd; + const char *input_dev_node = INPUT_DEV_NODE; + struct input_absinfo the_absinfo; + int led_fd[8]; + int led_col; + int avg_array[10] = { 0 }; + int avg_array_index = 0; + int avg_value; + pid_t key0_child_pid; + pid_t main_child_pid; + struct sigaction new_action, old_action; + + const char *led_trigger[8] = { + "/sys/class/leds/fpga_led0/trigger", + "/sys/class/leds/fpga_led1/trigger", + "/sys/class/leds/fpga_led2/trigger", + "/sys/class/leds/fpga_led3/trigger", + "/sys/class/leds/fpga_led4/trigger", + "/sys/class/leds/fpga_led5/trigger", + "/sys/class/leds/fpga_led6/trigger", + "/sys/class/leds/fpga_led7/trigger" }; + + const char *led_trigger_str = "none"; + int led_trigger_str_len = 4; + + const char *led_brightness[8] = { + "/sys/class/leds/fpga_led0/brightness", + "/sys/class/leds/fpga_led1/brightness", + "/sys/class/leds/fpga_led2/brightness", + "/sys/class/leds/fpga_led3/brightness", + "/sys/class/leds/fpga_led4/brightness", + "/sys/class/leds/fpga_led5/brightness", + "/sys/class/leds/fpga_led6/brightness", + "/sys/class/leds/fpga_led7/brightness" }; + + const char *led_on_str = "1"; + int led_on_str_len = 1; + const char *led_off_str = "0"; + int led_off_str_len = 1; + + // fork main to deal with heartbeat LED + main_child_pid = fork(); + if(main_child_pid != 0) { + int int_result; + + // disable heartbeat LED + write_sysfs_cntl_file("/sys/class/leds/hps_led0", "trigger", + "none"); + + // register a SIGTERM handler + new_action.sa_handler = my_termination_handler; + sigemptyset(&new_action.sa_mask); + new_action.sa_flags = 0; + + result = sigaction(SIGTERM, NULL, &old_action); + if(result < 0) + error(1, errno, "sigaction"); + + if(old_action.sa_handler != SIG_IGN) { + result = sigaction(SIGTERM, &new_action, NULL); + if(result < 0) + error(1, errno, "sigaction"); + } + else + error(1, 0, "SIGTERM handler already installed"); + + // register a SIGINT handler + result = sigaction(SIGINT, NULL, &old_action); + if(result < 0) + error(1, errno, "sigaction"); + + if(old_action.sa_handler != SIG_IGN) { + result = sigaction(SIGINT, &new_action, NULL); + if(result < 0) + error(1, errno, "sigaction"); + } + else + error(1, 0, "SIGINT handler already installed"); + + // register a SIGQUIT handler + result = sigaction(SIGQUIT, NULL, &old_action); + if(result < 0) + error(1, errno, "sigaction"); + + if(old_action.sa_handler != SIG_IGN) { + result = sigaction(SIGQUIT, &new_action, NULL); + if(result < 0) + error(1, errno, "sigaction"); + } + else + error(1, 0, "SIGINT handler already installed"); + + // wait for the main child to terminate + waitpid(main_child_pid, &int_result, 0); + + // enable heartbeat LED + write_sysfs_cntl_file("/sys/class/leds/hps_led0", "trigger", + "heartbeat"); + + // disable adxl + write_sysfs_cntl_file(SYSFS_DEVICE_DIR, "disable", "1"); + + // return the status from the main child + if(WIFEXITED(int_result)) { + exit(WEXITSTATUS(int_result)); + } else { + error(1, 0, "main child exited abnormally"); + } + } + + + // initialize led triggers to "none" + for(i = 0 ; i < 8 ; i++) { + led_fd[i] = open(led_trigger[i], O_WRONLY | O_SYNC); + if(led_fd[i] < 0) + error(1, errno, "File: '%s'", led_trigger[i]); + + result = write(led_fd[i], led_trigger_str, led_trigger_str_len); + if(result < 0) + error(1, errno, "File: '%s'", led_trigger[i]); + if(result != led_trigger_str_len) + error(1, 0, "File: '%s'", led_trigger[i]); + + result = close(led_fd[i]); + if(result < 0) + error(1, errno, "could not close file '%s'", + led_trigger[i]); + } + + // initialize led brightness to "off" + for(i = 0 ; i < 8 ; i++) { + led_fd[i] = open(led_brightness[i], O_WRONLY | O_SYNC); + if(led_fd[i] < 0) + error(1, errno, "File: '%s'", led_brightness[i]); + + result = write(led_fd[i], led_off_str, led_off_str_len); + if(result < 0) + error(1, errno, "File: '%s'", led_brightness[i]); + if(result != led_off_str_len) + error(1, 0, "File: '%s'", led_brightness[i]); + } + + // enable adxl + write_sysfs_cntl_file(SYSFS_DEVICE_DIR, "disable", "0"); + + // set the sample rate to maximum + write_sysfs_cntl_file(SYSFS_DEVICE_DIR, "rate", "15"); + + // do not auto sleep + write_sysfs_cntl_file(SYSFS_DEVICE_DIR, "autosleep", "0"); + + // open the event device node + event_dev_fd = open(input_dev_node, O_RDONLY | O_SYNC); + if(event_dev_fd < 0) + error(1, errno, "could not open file '%s'", input_dev_node); + + printf("\ +\n\ +1 - Notice that the heartbeat LED has been stopped while this program executes.\ +\n\ +2 - Notice the 8 LEDs beside the Ethernet connector on the board, they should\n\ + behave like a bubble level. As you tip your board from side to side on\n\ + the short axis of the board, the leds will indicate the tilt as a bubble\n\ + level would.\n\ +7 - Press the KEY0 push button located near the edge of the board in order to\n\ + stop the bubble level demo program.\n\ +8 - When you successfully stop the program, the heartbeat LED will resume.\ +\n\ +\n\ +"); + + // register our SIGCHLD handler + new_action.sa_handler = my_sig_child_handler; + sigemptyset(&new_action.sa_mask); + new_action.sa_flags = 0; + + result = sigaction(SIGCHLD, NULL, &old_action); + if(result < 0) + error(1, errno, "sigaction"); + + if(old_action.sa_handler != SIG_IGN) { + result = sigaction(SIGCHLD, &new_action, NULL); + if(result < 0) + error(1, errno, "sigaction"); + } + else + error(1, 0, "SIGCHLD handler already installed"); + + // fork the KEY0 push button monitor process + key0_child_pid = fork(); + if(key0_child_pid == 0) { + poll_for_KEY0_press(); + exit(EXIT_SUCCESS); + } + + // main bubble level loop + while (1) { + + if(g_stop_running != 0) + break; + + result = ioctl (event_dev_fd, EVIOCGABS(EV_CODE_X), + &the_absinfo); + if(result < 0) + error(1, errno, "ioctl from '%s'", + input_dev_node); + + avg_array[avg_array_index++] = the_absinfo.value; + if(avg_array_index >= 10) + avg_array_index = 0; + + avg_value = 0; + for(i = 0 ; i < 10 ; i++) + avg_value += avg_array[i]; + avg_value /= 10; + + if(avg_value < -40) + led_col = 0x01; + else if(avg_value < -30) + led_col = 0x02; + else if(avg_value < -20) + led_col = 0x04; + else if(avg_value < 0) + led_col = 0x08; + else if(avg_value > 40) + led_col = 0x80; + else if(avg_value > 30) + led_col = 0x40; + else if(avg_value > 20) + led_col = 0x20; + else if(avg_value >= 0) + led_col = 0x10; + + // output each LED sequentially down the column + for(i = 0 ; i < 8 ; i++) { + int row_mask = 1 << i; + if((row_mask & led_col) == 0) { + result = write(led_fd[i], led_off_str, + led_off_str_len); + if(result < 0) + error(1, errno, "File: '%s'", + led_brightness[i]); + if(result != led_off_str_len) + error(1, 0, "File: '%s'", + led_brightness[i]); + } else { + result = write(led_fd[i], led_on_str, + led_on_str_len); + if(result < 0) + error(1, errno, "File: '%s'", + led_brightness[i]); + if(result != led_on_str_len) + error(1, 0, "File: '%s'", + led_brightness[i]); + } + } + + usleep(10 * 1000); + } + + // close the led brightness files after setting them to "off" + for(i = 0 ; i < 8 ; i++) { + result = write(led_fd[i], led_off_str, led_off_str_len); + if(result < 0) + error(1, errno, "File: '%s'", led_brightness[i]); + if(result != led_off_str_len) + error(1, 0, "File: '%s'", led_brightness[i]); + + result = close(led_fd[i]); + if(result < 0) + error(1, errno, "could not close file '%s'", + led_brightness[i]); + } + + // close the device node + result = close(event_dev_fd); + if(result < 0) + error(1, errno, "could not close file '%s'", input_dev_node); + + printf("Bubble level demo exiting due to KEY0 push button press...\n"); +} + +void write_sysfs_cntl_file(const char *dir_name, const char *file_name, + const char *write_str) { + + char path[PATH_MAX]; + int path_length; + int file_fd; + int result; + + // create the path to the file we need to open + path_length = snprintf(path, PATH_MAX, "%s/%s", dir_name, file_name); + if(path_length < 0) + error(1, 0, "path output error"); + if(path_length >= PATH_MAX) + error(1, 0, "path length overflow"); + + // open the file + file_fd = open(path, O_WRONLY | O_SYNC); + if(file_fd < 0) + error(1, errno, "could not open file '%s'", path); + + // write the string to the file + result = write(file_fd, write_str, strlen(write_str)); + if(result < 0) + error(1, errno, "writing to '%s'", path); + if((size_t)(result) != strlen(write_str)) + error(1, errno, "buffer underflow writing '%s'", path); + + // close the file + result = close(file_fd); + if(result < 0) + error(1, errno, "could not close file '%s'", path); +} + +void poll_for_KEY0_press(void) { + DIR *gpio_dir; + const char *gpio_dir_path = "/sys/class/gpio"; + const char *gpiochip_str = "gpiochip"; + const char *gpio_label = "gpio@0x100005000"; + size_t gpiochip_str_len = strlen(gpiochip_str); + int result; + struct dirent *dir_entry; + char path[PATH_MAX+1]; + int path_length; + int file_fd; + char buffer[PATH_MAX+1]; + char gpio_number_buffer[PATH_MAX+1]; + char *str_result = NULL; + char *newline_ptr; + struct pollfd pollfd_struct; + + // open the sysfs gpio directory + gpio_dir = opendir(gpio_dir_path); + if(gpio_dir == NULL) + error(1, errno, "could not open directory '%s'", gpio_dir_path); + + // find the gpio controller for the KEY0 push button 'gpio@0x100005000' + while(1) { + // read the next directory entry + errno = 0; + dir_entry = readdir(gpio_dir); + if(dir_entry == NULL) { + if(errno != 0) { + result = closedir(gpio_dir); + if(result < 0) + error(1, errno, "could not closedir"); + + error(1, errno, "reading directory '%s'", + gpio_dir_path); + } + else + break; + } + + // check if this is a gpio controller entry + result = strncmp(dir_entry->d_name, gpiochip_str, + gpiochip_str_len); + if(result != 0) + continue; + + // open the gpio controller label file and read label value + path_length = snprintf(path, PATH_MAX, "%s/%s/label", + gpio_dir_path, dir_entry->d_name); + if(path_length < 0) + error(1, 0, "path output error"); + if(path_length >= PATH_MAX) + error(1, 0, "path length overflow"); + + file_fd = open(path, O_RDONLY | O_SYNC); + if(file_fd < 0) + error(1, errno, "could not open file '%s'", path); + + result = read(file_fd, buffer, PATH_MAX); + if(result < 0) + error(1, errno, "reading from '%s'", path); + if(result == PATH_MAX) + error(1, errno, "buffer overflow reading '%s'", path); + + buffer[PATH_MAX] = 0; + + result = close(file_fd); + if(result < 0) + error(1, errno, "could not close file '%s'", path); + + // test the gpio controller label value for our gpio controller + str_result = strstr(buffer, gpio_label); + if(str_result != NULL) + break; + } + + closedir(gpio_dir); + + if(str_result == NULL) + error(1, 0, "unable to locate gpio controller"); + + // open the gpio controller base file and read base value + path_length = snprintf(path, PATH_MAX, "%s/%s/base", + gpio_dir_path, dir_entry->d_name); + if(path_length < 0) + error(1, 0, "path output error"); + if(path_length >= PATH_MAX) + error(1, 0, "path length overflow"); + + file_fd = open(path, O_RDONLY | O_SYNC); + if(file_fd < 0) + error(1, errno, "could not open file '%s'", path); + + result = read(file_fd, gpio_number_buffer, PATH_MAX); + if(result < 0) + error(1, errno, "reading from '%s'", path); + if(result == PATH_MAX) + error(1, errno, "buffer overflow reading '%s'", path); + + gpio_number_buffer[PATH_MAX] = 0; + + result = close(file_fd); + if(result < 0) + error(1, errno, "could not close file '%s'", path); + + // remove the newline at the end of the string + newline_ptr = strchr(gpio_number_buffer,'\n'); + if(newline_ptr != NULL) + memset(newline_ptr, '\0', 1); + + // open the gpio export file and write our gpio number + path_length = snprintf(path, PATH_MAX, "%s/export", + gpio_dir_path); + if(path_length < 0) + error(1, 0, "path output error"); + if(path_length >= PATH_MAX) + error(1, 0, "path length overflow"); + + file_fd = open(path, O_WRONLY | O_SYNC); + if(file_fd < 0) + error(1, errno, "could not open file '%s'", path); + + result = write(file_fd, gpio_number_buffer, strlen(gpio_number_buffer)); + // NOTE: we don't bother checking for errors here because if this gpio + // has already been exported this write will receive a device busy error + // which is perfectly normal. + + result = close(file_fd); + if(result < 0) + error(1, errno, "could not close file '%s'", path); + + // open the gpio edge file and write 'falling' to it + path_length = snprintf(path, PATH_MAX, "%s/gpio%s/edge", + gpio_dir_path, gpio_number_buffer); + if(path_length < 0) + error(1, 0, "path output error"); + if(path_length >= PATH_MAX) + error(1, 0, "path length overflow"); + + file_fd = open(path, O_WRONLY | O_SYNC); + if(file_fd < 0) + error(1, errno, "could not open file '%s'", path); + + result = write(file_fd, "falling", 7); + if(result < 0) + error(1, errno, "writing to '%s'", path); + if(result != 7) + error(1, errno, "buffer underflow writing '%s'", path); + + result = close(file_fd); + if(result < 0) + error(1, errno, "could not close file '%s'", path); + + // open the gpio value file and poll the file + path_length = snprintf(path, PATH_MAX, "%s/gpio%s/value", + gpio_dir_path, gpio_number_buffer); + if(path_length < 0) + error(1, 0, "path output error"); + if(path_length >= PATH_MAX) + error(1, 0, "path length overflow"); + + file_fd = open(path, O_RDONLY | O_SYNC); + if(file_fd < 0) + error(1, errno, "could not open file '%s'", path); + + // we first need to read the file before we can poll it, otherwise poll + // will not block + result = read(file_fd, buffer, PATH_MAX); + if(result < 0) + error(1, errno, "reading from '%s'", path); + if(result == PATH_MAX) + error(1, errno, "buffer overflow reading '%s'", path); + + buffer[PATH_MAX] = 0; + + pollfd_struct.fd = file_fd; + pollfd_struct.events = POLLPRI | POLLERR; + pollfd_struct.revents = 0; + + result = poll(&pollfd_struct, 1, -1); + if(result < 0) + error(1, errno, "poll returned error"); + + result = close(file_fd); + if(result < 0) + error(1, errno, "could not close file '%s'", path); + + // open the gpio unexport file and write our gpio number + path_length = snprintf(path, PATH_MAX, "%s/unexport", + gpio_dir_path); + if(path_length < 0) + error(1, 0, "path output error"); + if(path_length >= PATH_MAX) + error(1, 0, "path length overflow"); + + file_fd = open(path, O_WRONLY | O_SYNC); + if(file_fd < 0) + error(1, errno, "could not open file '%s'", path); + + result = write(file_fd, gpio_number_buffer, strlen(gpio_number_buffer)); + if(result < 0) + error(1, errno, "writing to '%s'", path); + if((size_t)(result) != strlen(gpio_number_buffer)) + error(1, errno, "buffer underflow writing '%s'", path); + + result = close(file_fd); + if(result < 0) + error(1, errno, "could not close file '%s'", path); +} + diff --git a/recipes-demo/de10-nano-adxl-apps/files/build_bubble_demo.sh b/recipes-demo/de10-nano-adxl-apps/files/build_bubble_demo.sh new file mode 100755 index 0000000..37d5cb7 --- /dev/null +++ b/recipes-demo/de10-nano-adxl-apps/files/build_bubble_demo.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +gcc \ + -march=armv7-a \ + -mfloat-abi=hard \ + -mfpu=vfp3 \ + -mthumb-interwork \ + -mthumb \ + -O2 \ + -g \ + -feliminate-unused-debug-types \ + -std=gnu99 \ + -W \ + -Wall \ + -Werror \ + -Wc++-compat \ + -Wwrite-strings \ + -Wstrict-prototypes \ + -pedantic \ + -o bubble_demo \ + bubble_demo.c + diff --git a/recipes-demo/de10-nano-adxl-apps/files/build_tap_detect.sh b/recipes-demo/de10-nano-adxl-apps/files/build_tap_detect.sh new file mode 100755 index 0000000..15e6e6b --- /dev/null +++ b/recipes-demo/de10-nano-adxl-apps/files/build_tap_detect.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +gcc \ + -march=armv7-a \ + -mfloat-abi=hard \ + -mfpu=vfp3 \ + -mthumb-interwork \ + -mthumb \ + -O2 \ + -g \ + -feliminate-unused-debug-types \ + -std=gnu99 \ + -W \ + -Wall \ + -Werror \ + -Wc++-compat \ + -Wwrite-strings \ + -Wstrict-prototypes \ + -pedantic \ + -o tap_detect \ + tap_detect.c + diff --git a/recipes-demo/de10-nano-adxl-apps/files/build_watch_adxl.sh b/recipes-demo/de10-nano-adxl-apps/files/build_watch_adxl.sh new file mode 100755 index 0000000..c35c221 --- /dev/null +++ b/recipes-demo/de10-nano-adxl-apps/files/build_watch_adxl.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +gcc \ + -march=armv7-a \ + -mfloat-abi=hard \ + -mfpu=vfp3 \ + -mthumb-interwork \ + -mthumb \ + -O2 \ + -g \ + -feliminate-unused-debug-types \ + -std=gnu99 \ + -W \ + -Wall \ + -Werror \ + -Wc++-compat \ + -Wwrite-strings \ + -Wstrict-prototypes \ + -pedantic \ + -o watch_adxl \ + watch_adxl.c + diff --git a/recipes-demo/de10-nano-adxl-apps/files/tap_detect.c b/recipes-demo/de10-nano-adxl-apps/files/tap_detect.c new file mode 100644 index 0000000..bbd19d1 --- /dev/null +++ b/recipes-demo/de10-nano-adxl-apps/files/tap_detect.c @@ -0,0 +1,103 @@ +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <error.h> +#include <errno.h> +#include <limits.h> +#include <unistd.h> +#include <string.h> +#include "linux/input.h" + +#define INPUT_DEV_NODE "/dev/input/by-path/platform-ffc04000.i2c-event" +#define SYSFS_DEVICE_DIR "/sys/devices/platform/soc/ffc04000.i2c/i2c-0/0-0053/" + +#define EV_CODE_X (0) +#define EV_CODE_Y (1) +#define EV_CODE_Z (2) + +#define LOOP_COUNT (100) + +void write_sysfs_cntl_file(const char *dir_name, const char *file_name, + const char *write_str) { + + char path[PATH_MAX]; + int path_length; + int file_fd; + int result; + + // create the path to the file we need to open + path_length = snprintf(path, PATH_MAX, "%s/%s", dir_name, file_name); + if(path_length < 0) + error(1, 0, "path output error"); + if(path_length >= PATH_MAX) + error(1, 0, "path length overflow"); + + // open the file + file_fd = open(path, O_WRONLY | O_SYNC); + if(file_fd < 0) + error(1, errno, "could not open file '%s'", path); + + // write the string to the file + result = write(file_fd, write_str, strlen(write_str)); + if(result < 0) + error(1, errno, "writing to '%s'", path); + if((size_t)(result) != strlen(write_str)) + error(1, errno, "buffer underflow writing '%s'", path); + + // close the file + result = close(file_fd); + if(result < 0) + error(1, errno, "could not close file '%s'", path); +} + +int main(void) { + int event_dev_fd; + const char *input_dev_node = INPUT_DEV_NODE; + int result; + struct input_event the_event; + + // enable adxl + write_sysfs_cntl_file(SYSFS_DEVICE_DIR, "disable", "0"); + + // set the sample rate to maximum + write_sysfs_cntl_file(SYSFS_DEVICE_DIR, "rate", "15"); + + // do |