aboutsummaryrefslogtreecommitdiff
path: root/recipes-demo/de10-nano-adxl-apps/files
diff options
context:
space:
mode:
authorWestergreen, Dalon <dalon.westergreen@intel.com>2017-03-29 15:41:36 -0700
committerWestergreen, Dalon <dalon.westergreen@intel.com>2017-03-30 16:35:30 -0700
commit9a293641b9abf9e4fca34f46a2de781f50847da9 (patch)
tree743a6aaa5f9834987a2e69881ced6eaf9efb3592 /recipes-demo/de10-nano-adxl-apps/files
parent8abd3fefd939f796ae49191d6f5af641f2d624d0 (diff)
downloadmeta-de10-nano-9a293641b9abf9e4fca34f46a2de781f50847da9.tar.xz
Initial commit of de10-nano recipes
Please note that this is purely for development. Only superficial efforts have been made to resolve security concerns, and it should be noted that the board ships with an EMPTY ROOT PASSWORD and support for root login via ssh. This allows passwordless access to the board via ssh. recipes-bsp/u-boot: Contains the uboot 2017.03rc2 recipe and patches to support the de10-nano board recipes-connectivity/avahi: bbappend to remove unwanted packages recipes-connectivity/bluez: bbappend to add --compat to the bluetooth service to support legacy SDP APIs recipes-connectivity/openssh: bbappend to add a custom sshd_config recipes-core/base-files: bbappend to customize fstab and inputrc recipes-core/imagemagick: bbappend to change build configuration for the de10-nano board recipes-core/packagegroups: bbappend to remove an unwanted package recipes-core/webkit: bbappend to remove support for opengl recipes-demo: Various demo applications recipes-devtools: MRAA and UPM recipes recipes-images/angstrom/de10-nano-image.bb: DE10-Nano image definition recipes-kernel/de10-nano-linux-firmware: FPGA related firmware required for fpga configuration and devicetree overlay support recipes-kernel/linux: bbappend to customize configuration of linux kernel as well as patch in the de10-nano devicetree recipes-misc: various initialization and systemd scripts recipes-qt/qt5: bbappend to modify qt build options recipes-support/neon: bbappend to remove unwanted package recipes-support/upower: bbappend to remove unwanted package recipes-webserver: webserver configuration and webcontent for board hostedweb portal recipes-xfce/thunar-volman: bbappend to remove unwanted package recipes-xfce/xfce-pointers: add configuration so that xfce does not use the adxl input as a mouse recipes-xfce/xfce4-settings: bbappend to remove unwanted package Signed-off-by: Westergreen, Dalon <dalon.westergreen@intel.com>
Diffstat (limited to 'recipes-demo/de10-nano-adxl-apps/files')
-rw-r--r--recipes-demo/de10-nano-adxl-apps/files/LICENSE22
-rw-r--r--recipes-demo/de10-nano-adxl-apps/files/README_SANDBOX.txt168
-rw-r--r--recipes-demo/de10-nano-adxl-apps/files/README_SRC.txt10
-rwxr-xr-xrecipes-demo/de10-nano-adxl-apps/files/adxl_calibrate.sh20
-rw-r--r--recipes-demo/de10-nano-adxl-apps/files/bubble_demo.c609
-rwxr-xr-xrecipes-demo/de10-nano-adxl-apps/files/build_bubble_demo.sh22
-rwxr-xr-xrecipes-demo/de10-nano-adxl-apps/files/build_tap_detect.sh22
-rwxr-xr-xrecipes-demo/de10-nano-adxl-apps/files/build_watch_adxl.sh22
-rw-r--r--recipes-demo/de10-nano-adxl-apps/files/tap_detect.c103
-rw-r--r--recipes-demo/de10-nano-adxl-apps/files/watch_adxl.c277
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 \
<