diff --git a/Makefile b/Makefile index 5449695..7d531df 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,8 @@ -# Makefile.in generated by automake 1.11.6 from Makefile.am. +# Makefile.in generated by automake 1.16.1 from Makefile.am. # Makefile. Generated from Makefile.in by configure. -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software -# Foundation, Inc. +# Copyright (C) 1994-2018 Free Software Foundation, Inc. + # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -18,23 +17,61 @@ -am__make_dryrun = \ - { \ - am__dry=no; \ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ - echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ - | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ - *) \ - for am__flg in $$MAKEFLAGS; do \ - case $$am__flg in \ - *=*|--*) ;; \ - *n*) am__dry=yes; break;; \ - esac; \ - done;; \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ - test $$am__dry = yes; \ - } + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/mediacore-hid pkgincludedir = $(includedir)/mediacore-hid pkglibdir = $(libdir)/mediacore-hid @@ -51,17 +88,16 @@ POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : +build_triplet = armv7l-unknown-linux-gnueabihf +host_triplet = armv7l-unknown-linux-gnueabihf sbin_PROGRAMS = mediacore-hid-server$(EXEEXT) -check_PROGRAMS = mcp23017-i2ctest$(EXEEXT) -TESTS = mcp23017-i2ctest$(EXEEXT) subdir = . -DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in $(srcdir)/config.hpp.in \ - $(top_srcdir)/configure depcomp install-sh missing ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d @@ -69,23 +105,19 @@ CONFIG_HEADER = config.hpp CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(init_d_dirdir)" \ - "$(DESTDIR)$(dbus_confdir)" "$(DESTDIR)$(etc_dirdir)" \ - "$(DESTDIR)$(modprobe_d_dirdir)" \ - "$(DESTDIR)$(rsyslog_confdir)" + "$(DESTDIR)$(dbus_confdir)" "$(DESTDIR)$(rsyslog_confdir)" PROGRAMS = $(sbin_PROGRAMS) am__dirstamp = $(am__leading_dot)dirstamp -am__objects_1 = src/i2c/i2c.$(OBJEXT) -am_mcp23017_i2ctest_OBJECTS = src/test/mcp23017-i2ctest.$(OBJEXT) \ +am__objects_1 = src/log/mediacore_hid_server-log.$(OBJEXT) \ + src/thread/mediacore_hid_server-thread.$(OBJEXT) \ + src/buttontimer/mediacore_hid_server-buttontimer.$(OBJEXT) \ + src/gpio/mediacore_hid_server-gpio.$(OBJEXT) \ + src/gpio/mediacore_hid_server-dma.$(OBJEXT) \ + src/gpio/mediacore_hid_server-mailbox.$(OBJEXT) +am_mediacore_hid_server_OBJECTS = \ + src/mediacore_hid_server-mc-hid-server.$(OBJEXT) \ + src/exception/mediacore_hid_server-baseexceptions.$(OBJEXT) \ $(am__objects_1) -mcp23017_i2ctest_OBJECTS = $(am_mcp23017_i2ctest_OBJECTS) -mcp23017_i2ctest_DEPENDENCIES = -am__objects_2 = src/gpio/gpio.$(OBJEXT) \ - src/mcp23017/mcp23017.$(OBJEXT) \ - src/exception/baseexceptions.$(OBJEXT) $(am__objects_1) -am__objects_3 = src/log/log.$(OBJEXT) src/thread/thread.$(OBJEXT) \ - src/buttontimer/buttontimer.$(OBJEXT) -am_mediacore_hid_server_OBJECTS = src/mc-hid-server.$(OBJEXT) \ - $(am__objects_2) $(am__objects_3) mediacore_hid_server_OBJECTS = $(am_mediacore_hid_server_OBJECTS) am__DEPENDENCIES_1 = mediacore_hid_server_DEPENDENCIES = $(am__DEPENDENCIES_1) @@ -117,33 +149,92 @@ am__uninstall_files_from_dir = { \ $(am__cd) "$$dir" && rm -f $$files; }; \ } SCRIPTS = $(init_d_dir_SCRIPTS) +AM_V_P = $(am__v_P_$(V)) +am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +am__v_at_1 = DEFAULT_INCLUDES = -I. depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = \ + src/$(DEPDIR)/mediacore_hid_server-mc-hid-server.Po \ + src/buttontimer/$(DEPDIR)/mediacore_hid_server-buttontimer.Po \ + src/exception/$(DEPDIR)/mediacore_hid_server-baseexceptions.Po \ + src/gpio/$(DEPDIR)/mediacore_hid_server-dma.Po \ + src/gpio/$(DEPDIR)/mediacore_hid_server-gpio.Po \ + src/gpio/$(DEPDIR)/mediacore_hid_server-mailbox.Po \ + src/log/$(DEPDIR)/mediacore_hid_server-log.Po \ + src/thread/$(DEPDIR)/mediacore_hid_server-thread.Po am__mv = mv -f +AM_V_lt = $(am__v_lt_$(V)) +am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +am__v_lt_0 = --silent +am__v_lt_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_$(V)) +am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_$(V)) +am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_$(V)) +am__v_CXX_ = $(am__v_CXX_$(AM_DEFAULT_VERBOSITY)) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ -SOURCES = $(mcp23017_i2ctest_SOURCES) $(mediacore_hid_server_SOURCES) -DIST_SOURCES = $(mcp23017_i2ctest_SOURCES) \ - $(mediacore_hid_server_SOURCES) +AM_V_CXXLD = $(am__v_CXXLD_$(V)) +am__v_CXXLD_ = $(am__v_CXXLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +SOURCES = $(mediacore_hid_server_SOURCES) +DIST_SOURCES = $(mediacore_hid_server_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac -DATA = $(dbus_conf_DATA) $(etc_dir_DATA) $(modprobe_d_dir_DATA) \ - $(rsyslog_conf_DATA) +DATA = $(dbus_conf_DATA) $(rsyslog_conf_DATA) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ + $(LISP)config.hpp.in +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags -am__tty_colors = \ -red=; grn=; lgn=; blu=; std= +CSCOPE = cscope +AM_RECURSIVE_TARGETS = cscope +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.hpp.in \ + compile config.guess config.sub depcomp install-sh missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) @@ -153,17 +244,20 @@ am__remove_distdir = \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi +am__post_remove_distdir = $(am__remove_distdir) DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best +DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print -ACLOCAL = ${SHELL} /opt/mediacore/mediacore_hid/missing --run aclocal-1.11 +ACLOCAL = ${SHELL} /home/pi/mediacore-hid/missing aclocal-1.16 AMTAR = $${TAR-tar} -AUTOCONF = ${SHELL} /opt/mediacore/mediacore_hid/missing --run autoconf -AUTOHEADER = ${SHELL} /opt/mediacore/mediacore_hid/missing --run autoheader -AUTOMAKE = ${SHELL} /opt/mediacore/mediacore_hid/missing --run automake-1.11 +AM_DEFAULT_VERBOSITY = 1 +AUTOCONF = ${SHELL} /home/pi/mediacore-hid/missing autoconf +AUTOHEADER = ${SHELL} /home/pi/mediacore-hid/missing autoheader +AUTOMAKE = ${SHELL} /home/pi/mediacore-hid/missing automake-1.16 AWK = mawk BOOST_CPPFLAGS = -I/usr/include BOOST_LDFLAGS = -L/usr/lib @@ -179,9 +273,9 @@ DBUSXX_CHECK = yes DEBUILD = /usr/bin/dpkg-buildpackage DEFS = -DHAVE_CONFIG_H DEPDIR = .deps -DEPS_CFLAGS = -DDBUS_API_SUBJECT_TO_CHANGE -I/usr/include/dbus-c++-1 -I/usr/include/dbus-1.0 -I/usr/lib/arm-linux-gnueabihf/dbus-1.0/include -DEPS_LIBS = -ldbus-c++-1 -ldbus-1 -DHMAKE = /usr/bin/dh_make +DEPS_CFLAGS = -DDBUS_API_SUBJECT_TO_CHANGE -I/usr/include/dbus-c++-1 -I/usr/include/dbus-1.0 -I/usr/lib/arm-linux-gnueabihf/dbus-1.0/include +DEPS_LIBS = -ldbus-c++-1 -ldbus-1 +DHMAKE = notfound ECHO_C = ECHO_N = -n ECHO_T = @@ -195,16 +289,16 @@ LDFLAGS = LIBOBJS = LIBS = LTLIBOBJS = -MAKEINFO = ${SHELL} /opt/mediacore/mediacore_hid/missing --run makeinfo -MKDIR_P = /bin/mkdir -p +MAKEINFO = ${SHELL} /home/pi/mediacore-hid/missing makeinfo +MKDIR_P = /usr/bin/mkdir -p OBJEXT = o PACKAGE = mediacore-hid PACKAGE_BUGREPORT = bugs@miqra.nl PACKAGE_NAME = MediaCore HID Server -PACKAGE_STRING = MediaCore HID Server 1.0.0 +PACKAGE_STRING = MediaCore HID Server 4.0.0 PACKAGE_TARNAME = mediacore-hid PACKAGE_URL = http://www.miqra.nl/ -PACKAGE_VERSION = 1.0.0 +PACKAGE_VERSION = 4.0.0 PATH_SEPARATOR = : PKG_CONFIG = /usr/bin/pkg-config PKG_CONFIG_LIBDIR = @@ -212,11 +306,11 @@ PKG_CONFIG_PATH = SET_MAKE = SHELL = /bin/bash STRIP = -VERSION = 1.0.0 -abs_builddir = /opt/mediacore/mediacore_hid -abs_srcdir = /opt/mediacore/mediacore_hid -abs_top_builddir = /opt/mediacore/mediacore_hid -abs_top_srcdir = /opt/mediacore/mediacore_hid +VERSION = 4.0.0 +abs_builddir = /home/pi/mediacore-hid +abs_srcdir = /home/pi/mediacore-hid +abs_top_builddir = /home/pi/mediacore-hid +abs_top_srcdir = /home/pi/mediacore-hid ac_ct_CC = gcc ac_ct_CXX = g++ am__include = include @@ -225,29 +319,38 @@ am__quote = am__tar = $${TAR-tar} chof - "$$tardir" am__untar = $${TAR-tar} xf - bindir = ${exec_prefix}/bin +build = armv7l-unknown-linux-gnueabihf build_alias = +build_cpu = armv7l +build_os = linux-gnueabihf +build_vendor = unknown builddir = . datadir = ${datarootdir} datarootdir = ${prefix}/share docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} dvidir = ${docdir} exec_prefix = ${prefix} +host = armv7l-unknown-linux-gnueabihf host_alias = +host_cpu = armv7l +host_os = linux-gnueabihf +host_vendor = unknown htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info -install_sh = ${SHELL} /opt/mediacore/mediacore_hid/install-sh +install_sh = ${SHELL} /home/pi/mediacore-hid/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale localstatedir = ${prefix}/var mandir = ${datarootdir}/man -mkdir_p = /bin/mkdir -p +mkdir_p = $(MKDIR_P) oldincludedir = /usr/include pdfdir = ${docdir} prefix = /usr/local program_transform_name = s,x,x, psdir = ${docdir} +runstatedir = ${localstatedir}/run sbindir = ${exec_prefix}/sbin sharedstatedir = ${prefix}/com srcdir = . @@ -262,31 +365,23 @@ AM_CPPFLAGS = $(DEPS_CFLAGS) DISTCLEANFILES = src/mc-hid-server-glue.hpp \ script/init.d/mediacore-hid -I2C_SRC = src/i2c/i2c.c \ - src/i2c/i2c.h - -MCP_GPIO_SRC = src/gpio/gpio.hpp \ - src/gpio/gpio.cpp \ - src/mcp23017/mcp23017.hpp \ - src/mcp23017/mcp23017.cpp \ - src/exception/baseexceptions.hpp \ - src/exception/baseexceptions.cpp \ - $(I2C_SRC) - SUPPORT_SRC = src/log/log.hpp \ src/log/log.cpp \ src/thread/thread.hpp \ src/thread/thread.cpp \ src/buttontimer/buttontimer.hpp \ - src/buttontimer/buttontimer.cpp + src/buttontimer/buttontimer.cpp \ + src/gpio/gpio.hpp \ + src/gpio/gpio.cpp \ + src/gpio/dma.hpp \ + src/gpio/dma.cpp \ + src/gpio/mailbox.h \ + src/gpio/mailbox.c -EXTRA_DIST = \ - cfg/dbus/nl.miqra.MediaCore.Hid.conf \ +EXTRA_DIST = cfg/dbus/nl.miqra.MediaCore.Hid.conf \ cfg/init.d/mediacore-hid.in \ cfg/rsyslog/syslog.MediaCore.Hid.conf \ - src/mc-hid-introspect.xml \ - cfg/modules \ - cfg/modprobe.d/raspi-blacklist.conf + src/mc-hid-introspect.xml init_d_dirdir = $(sysconfdir)/init.d init_d_dir_SCRIPTS = cfg/init.d/mediacore-hid @@ -294,22 +389,16 @@ dbus_confdir = $(sysconfdir)/dbus-1/system.d dbus_conf_DATA = cfg/dbus/nl.miqra.MediaCore.Hid.conf rsyslog_confdir = $(sysconfdir)/rsyslog.d rsyslog_conf_DATA = cfg/rsyslog/syslog.MediaCore.Hid.conf -etc_dirdir = $(sysconfdir) -etc_dir_DATA = cfg/modules -modprobe_d_dirdir = $(sysconfdir)/modprobe.d -modprobe_d_dir_DATA = cfg/modprobe.d/raspi-blacklist.conf BUILT_SOURCES = src/mc-hid-server-glue.hpp +mediacore_hid_server_CPPFLAGS = -std=c++17 -I/usr/include/dbus-c++-1/ -I/opt/vc/include/ mediacore_hid_server_SOURCES = src/mc-hid-server.cpp \ src/mc-hid-server.hpp \ src/mc-hid-server-glue.hpp \ - $(MCP_GPIO_SRC) \ + src/exception/baseexceptions.hpp \ + src/exception/baseexceptions.cpp \ $(SUPPORT_SRC) -mediacore_hid_server_LDADD = $(DEPS_LIBS) -lpthread -lrt -mcp23017_i2ctest_SOURCES = src/test/mcp23017-i2ctest.c \ - $(I2C_SRC) - -mcp23017_i2ctest_LDADD = -lpthread +mediacore_hid_server_LDADD = $(DEPS_LIBS) -L/opt/vc/lib -lpthread -lrt -lgpiodcxx -lbcm_host all: $(BUILT_SOURCES) config.hpp $(MAKE) $(AM_MAKEFLAGS) all-am @@ -330,15 +419,14 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -351,8 +439,8 @@ $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__aclocal_m4_deps): config.hpp: stamp-h1 - @if test ! -f $@; then rm -f stamp-h1; else :; fi - @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi + @test -f $@ || rm -f stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/config.hpp.in $(top_builddir)/config.status @rm -f stamp-h1 @@ -364,9 +452,6 @@ $(srcdir)/config.hpp.in: $(am__configure_deps) distclean-hdr: -rm -f config.hpp stamp-h1 - -clean-checkPROGRAMS: - -test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS) install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ @@ -376,10 +461,11 @@ install-sbinPROGRAMS: $(sbin_PROGRAMS) fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ - while read p p1; do if test -f $$p; \ - then echo "$$p"; echo "$$p"; else :; fi; \ + while read p p1; do if test -f $$p \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ - sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ @@ -400,63 +486,30 @@ uninstall-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ - -e 's/$$/$(EXEEXT)/' `; \ + -e 's/$$/$(EXEEXT)/' \ + `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) -src/test/$(am__dirstamp): - @$(MKDIR_P) src/test - @: > src/test/$(am__dirstamp) -src/test/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/test/$(DEPDIR) - @: > src/test/$(DEPDIR)/$(am__dirstamp) -src/test/mcp23017-i2ctest.$(OBJEXT): src/test/$(am__dirstamp) \ - src/test/$(DEPDIR)/$(am__dirstamp) -src/i2c/$(am__dirstamp): - @$(MKDIR_P) src/i2c - @: > src/i2c/$(am__dirstamp) -src/i2c/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/i2c/$(DEPDIR) - @: > src/i2c/$(DEPDIR)/$(am__dirstamp) -src/i2c/i2c.$(OBJEXT): src/i2c/$(am__dirstamp) \ - src/i2c/$(DEPDIR)/$(am__dirstamp) -mcp23017-i2ctest$(EXEEXT): $(mcp23017_i2ctest_OBJECTS) $(mcp23017_i2ctest_DEPENDENCIES) $(EXTRA_mcp23017_i2ctest_DEPENDENCIES) - @rm -f mcp23017-i2ctest$(EXEEXT) - $(LINK) $(mcp23017_i2ctest_OBJECTS) $(mcp23017_i2ctest_LDADD) $(LIBS) src/$(am__dirstamp): @$(MKDIR_P) src @: > src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/$(DEPDIR) @: > src/$(DEPDIR)/$(am__dirstamp) -src/mc-hid-server.$(OBJEXT): src/$(am__dirstamp) \ +src/mediacore_hid_server-mc-hid-server.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) -src/gpio/$(am__dirstamp): - @$(MKDIR_P) src/gpio - @: > src/gpio/$(am__dirstamp) -src/gpio/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/gpio/$(DEPDIR) - @: > src/gpio/$(DEPDIR)/$(am__dirstamp) -src/gpio/gpio.$(OBJEXT): src/gpio/$(am__dirstamp) \ - src/gpio/$(DEPDIR)/$(am__dirstamp) -src/mcp23017/$(am__dirstamp): - @$(MKDIR_P) src/mcp23017 - @: > src/mcp23017/$(am__dirstamp) -src/mcp23017/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) src/mcp23017/$(DEPDIR) - @: > src/mcp23017/$(DEPDIR)/$(am__dirstamp) -src/mcp23017/mcp23017.$(OBJEXT): src/mcp23017/$(am__dirstamp) \ - src/mcp23017/$(DEPDIR)/$(am__dirstamp) src/exception/$(am__dirstamp): @$(MKDIR_P) src/exception @: > src/exception/$(am__dirstamp) src/exception/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/exception/$(DEPDIR) @: > src/exception/$(DEPDIR)/$(am__dirstamp) -src/exception/baseexceptions.$(OBJEXT): src/exception/$(am__dirstamp) \ +src/exception/mediacore_hid_server-baseexceptions.$(OBJEXT): \ + src/exception/$(am__dirstamp) \ src/exception/$(DEPDIR)/$(am__dirstamp) src/log/$(am__dirstamp): @$(MKDIR_P) src/log @@ -464,7 +517,7 @@ src/log/$(am__dirstamp): src/log/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/log/$(DEPDIR) @: > src/log/$(DEPDIR)/$(am__dirstamp) -src/log/log.$(OBJEXT): src/log/$(am__dirstamp) \ +src/log/mediacore_hid_server-log.$(OBJEXT): src/log/$(am__dirstamp) \ src/log/$(DEPDIR)/$(am__dirstamp) src/thread/$(am__dirstamp): @$(MKDIR_P) src/thread @@ -472,7 +525,8 @@ src/thread/$(am__dirstamp): src/thread/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/thread/$(DEPDIR) @: > src/thread/$(DEPDIR)/$(am__dirstamp) -src/thread/thread.$(OBJEXT): src/thread/$(am__dirstamp) \ +src/thread/mediacore_hid_server-thread.$(OBJEXT): \ + src/thread/$(am__dirstamp) \ src/thread/$(DEPDIR)/$(am__dirstamp) src/buttontimer/$(am__dirstamp): @$(MKDIR_P) src/buttontimer @@ -480,12 +534,25 @@ src/buttontimer/$(am__dirstamp): src/buttontimer/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/buttontimer/$(DEPDIR) @: > src/buttontimer/$(DEPDIR)/$(am__dirstamp) -src/buttontimer/buttontimer.$(OBJEXT): \ +src/buttontimer/mediacore_hid_server-buttontimer.$(OBJEXT): \ src/buttontimer/$(am__dirstamp) \ src/buttontimer/$(DEPDIR)/$(am__dirstamp) +src/gpio/$(am__dirstamp): + @$(MKDIR_P) src/gpio + @: > src/gpio/$(am__dirstamp) +src/gpio/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/gpio/$(DEPDIR) + @: > src/gpio/$(DEPDIR)/$(am__dirstamp) +src/gpio/mediacore_hid_server-gpio.$(OBJEXT): \ + src/gpio/$(am__dirstamp) src/gpio/$(DEPDIR)/$(am__dirstamp) +src/gpio/mediacore_hid_server-dma.$(OBJEXT): src/gpio/$(am__dirstamp) \ + src/gpio/$(DEPDIR)/$(am__dirstamp) +src/gpio/mediacore_hid_server-mailbox.$(OBJEXT): \ + src/gpio/$(am__dirstamp) src/gpio/$(DEPDIR)/$(am__dirstamp) + mediacore-hid-server$(EXEEXT): $(mediacore_hid_server_OBJECTS) $(mediacore_hid_server_DEPENDENCIES) $(EXTRA_mediacore_hid_server_DEPENDENCIES) @rm -f mediacore-hid-server$(EXEEXT) - $(CXXLINK) $(mediacore_hid_server_OBJECTS) $(mediacore_hid_server_LDADD) $(LIBS) + $(AM_V_CXXLD)$(CXXLINK) $(mediacore_hid_server_OBJECTS) $(mediacore_hid_server_LDADD) $(LIBS) install-init_d_dirSCRIPTS: $(init_d_dir_SCRIPTS) @$(NORMAL_INSTALL) @list='$(init_d_dir_SCRIPTS)'; test -n "$(init_d_dirdir)" || list=; \ @@ -524,60 +591,174 @@ uninstall-init_d_dirSCRIPTS: mostlyclean-compile: -rm -f *.$(OBJEXT) - -rm -f src/buttontimer/buttontimer.$(OBJEXT) - -rm -f src/exception/baseexceptions.$(OBJEXT) - -rm -f src/gpio/gpio.$(OBJEXT) - -rm -f src/i2c/i2c.$(OBJEXT) - -rm -f src/log/log.$(OBJEXT) - -rm -f src/mc-hid-server.$(OBJEXT) - -rm -f src/mcp23017/mcp23017.$(OBJEXT) - -rm -f src/test/mcp23017-i2ctest.$(OBJEXT) - -rm -f src/thread/thread.$(OBJEXT) + -rm -f src/*.$(OBJEXT) + -rm -f src/buttontimer/*.$(OBJEXT) + -rm -f src/exception/*.$(OBJEXT) + -rm -f src/gpio/*.$(OBJEXT) + -rm -f src/log/*.$(OBJEXT) + -rm -f src/thread/*.$(OBJEXT) distclean-compile: -rm -f *.tab.c -include src/$(DEPDIR)/mc-hid-server.Po -include src/buttontimer/$(DEPDIR)/buttontimer.Po -include src/exception/$(DEPDIR)/baseexceptions.Po -include src/gpio/$(DEPDIR)/gpio.Po -include src/i2c/$(DEPDIR)/i2c.Po -include src/log/$(DEPDIR)/log.Po -include src/mcp23017/$(DEPDIR)/mcp23017.Po -include src/test/$(DEPDIR)/mcp23017-i2ctest.Po -include src/thread/$(DEPDIR)/thread.Po +include src/$(DEPDIR)/mediacore_hid_server-mc-hid-server.Po # am--include-marker +include src/buttontimer/$(DEPDIR)/mediacore_hid_server-buttontimer.Po # am--include-marker +include src/exception/$(DEPDIR)/mediacore_hid_server-baseexceptions.Po # am--include-marker +include src/gpio/$(DEPDIR)/mediacore_hid_server-dma.Po # am--include-marker +include src/gpio/$(DEPDIR)/mediacore_hid_server-gpio.Po # am--include-marker +include src/gpio/$(DEPDIR)/mediacore_hid_server-mailbox.Po # am--include-marker +include src/log/$(DEPDIR)/mediacore_hid_server-log.Po # am--include-marker +include src/thread/$(DEPDIR)/mediacore_hid_server-thread.Po # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) .c.o: - depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ + $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ $(am__mv) $$depbase.Tpo $$depbase.Po -# source='$<' object='$@' libtool=no \ +# $(AM_V_CC)source='$<' object='$@' libtool=no \ # DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ -# $(COMPILE) -c -o $@ $< +# $(AM_V_CC_no)$(COMPILE) -c -o $@ $< .c.obj: - depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ + $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ $(am__mv) $$depbase.Tpo $$depbase.Po -# source='$<' object='$@' libtool=no \ +# $(AM_V_CC)source='$<' object='$@' libtool=no \ # DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ -# $(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +# $(AM_V_CC_no)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +src/gpio/mediacore_hid_server-mailbox.o: src/gpio/mailbox.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/gpio/mediacore_hid_server-mailbox.o -MD -MP -MF src/gpio/$(DEPDIR)/mediacore_hid_server-mailbox.Tpo -c -o src/gpio/mediacore_hid_server-mailbox.o `test -f 'src/gpio/mailbox.c' || echo '$(srcdir)/'`src/gpio/mailbox.c + $(AM_V_at)$(am__mv) src/gpio/$(DEPDIR)/mediacore_hid_server-mailbox.Tpo src/gpio/$(DEPDIR)/mediacore_hid_server-mailbox.Po +# $(AM_V_CC)source='src/gpio/mailbox.c' object='src/gpio/mediacore_hid_server-mailbox.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/gpio/mediacore_hid_server-mailbox.o `test -f 'src/gpio/mailbox.c' || echo '$(srcdir)/'`src/gpio/mailbox.c + +src/gpio/mediacore_hid_server-mailbox.obj: src/gpio/mailbox.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/gpio/mediacore_hid_server-mailbox.obj -MD -MP -MF src/gpio/$(DEPDIR)/mediacore_hid_server-mailbox.Tpo -c -o src/gpio/mediacore_hid_server-mailbox.obj `if test -f 'src/gpio/mailbox.c'; then $(CYGPATH_W) 'src/gpio/mailbox.c'; else $(CYGPATH_W) '$(srcdir)/src/gpio/mailbox.c'; fi` + $(AM_V_at)$(am__mv) src/gpio/$(DEPDIR)/mediacore_hid_server-mailbox.Tpo src/gpio/$(DEPDIR)/mediacore_hid_server-mailbox.Po +# $(AM_V_CC)source='src/gpio/mailbox.c' object='src/gpio/mediacore_hid_server-mailbox.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ +# $(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/gpio/mediacore_hid_server-mailbox.obj `if test -f 'src/gpio/mailbox.c'; then $(CYGPATH_W) 'src/gpio/mailbox.c'; else $(CYGPATH_W) '$(srcdir)/src/gpio/mailbox.c'; fi` .cpp.o: - depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ + $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ $(am__mv) $$depbase.Tpo $$depbase.Po -# source='$<' object='$@' libtool=no \ +# $(AM_V_CXX)source='$<' object='$@' libtool=no \ # DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ -# $(CXXCOMPILE) -c -o $@ $< +# $(AM_V_CXX_no)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: - depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ + $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ $(am__mv) $$depbase.Tpo $$depbase.Po -# source='$<' object='$@' libtool=no \ +# $(AM_V_CXX)source='$<' object='$@' libtool=no \ # DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ -# $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +# $(AM_V_CXX_no)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +src/mediacore_hid_server-mc-hid-server.o: src/mc-hid-server.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/mediacore_hid_server-mc-hid-server.o -MD -MP -MF src/$(DEPDIR)/mediacore_hid_server-mc-hid-server.Tpo -c -o src/mediacore_hid_server-mc-hid-server.o `test -f 'src/mc-hid-server.cpp' || echo '$(srcdir)/'`src/mc-hid-server.cpp + $(AM_V_at)$(am__mv) src/$(DEPDIR)/mediacore_hid_server-mc-hid-server.Tpo src/$(DEPDIR)/mediacore_hid_server-mc-hid-server.Po +# $(AM_V_CXX)source='src/mc-hid-server.cpp' object='src/mediacore_hid_server-mc-hid-server.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(AM_V_CXX_no)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/mediacore_hid_server-mc-hid-server.o `test -f 'src/mc-hid-server.cpp' || echo '$(srcdir)/'`src/mc-hid-server.cpp + +src/mediacore_hid_server-mc-hid-server.obj: src/mc-hid-server.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/mediacore_hid_server-mc-hid-server.obj -MD -MP -MF src/$(DEPDIR)/mediacore_hid_server-mc-hid-server.Tpo -c -o src/mediacore_hid_server-mc-hid-server.obj `if test -f 'src/mc-hid-server.cpp'; then $(CYGPATH_W) 'src/mc-hid-server.cpp'; else $(CYGPATH_W) '$(srcdir)/src/mc-hid-server.cpp'; fi` + $(AM_V_at)$(am__mv) src/$(DEPDIR)/mediacore_hid_server-mc-hid-server.Tpo src/$(DEPDIR)/mediacore_hid_server-mc-hid-server.Po +# $(AM_V_CXX)source='src/mc-hid-server.cpp' object='src/mediacore_hid_server-mc-hid-server.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(AM_V_CXX_no)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/mediacore_hid_server-mc-hid-server.obj `if test -f 'src/mc-hid-server.cpp'; then $(CYGPATH_W) 'src/mc-hid-server.cpp'; else $(CYGPATH_W) '$(srcdir)/src/mc-hid-server.cpp'; fi` + +src/exception/mediacore_hid_server-baseexceptions.o: src/exception/baseexceptions.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/exception/mediacore_hid_server-baseexceptions.o -MD -MP -MF src/exception/$(DEPDIR)/mediacore_hid_server-baseexceptions.Tpo -c -o src/exception/mediacore_hid_server-baseexceptions.o `test -f 'src/exception/baseexceptions.cpp' || echo '$(srcdir)/'`src/exception/baseexceptions.cpp + $(AM_V_at)$(am__mv) src/exception/$(DEPDIR)/mediacore_hid_server-baseexceptions.Tpo src/exception/$(DEPDIR)/mediacore_hid_server-baseexceptions.Po +# $(AM_V_CXX)source='src/exception/baseexceptions.cpp' object='src/exception/mediacore_hid_server-baseexceptions.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(AM_V_CXX_no)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/exception/mediacore_hid_server-baseexceptions.o `test -f 'src/exception/baseexceptions.cpp' || echo '$(srcdir)/'`src/exception/baseexceptions.cpp + +src/exception/mediacore_hid_server-baseexceptions.obj: src/exception/baseexceptions.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/exception/mediacore_hid_server-baseexceptions.obj -MD -MP -MF src/exception/$(DEPDIR)/mediacore_hid_server-baseexceptions.Tpo -c -o src/exception/mediacore_hid_server-baseexceptions.obj `if test -f 'src/exception/baseexceptions.cpp'; then $(CYGPATH_W) 'src/exception/baseexceptions.cpp'; else $(CYGPATH_W) '$(srcdir)/src/exception/baseexceptions.cpp'; fi` + $(AM_V_at)$(am__mv) src/exception/$(DEPDIR)/mediacore_hid_server-baseexceptions.Tpo src/exception/$(DEPDIR)/mediacore_hid_server-baseexceptions.Po +# $(AM_V_CXX)source='src/exception/baseexceptions.cpp' object='src/exception/mediacore_hid_server-baseexceptions.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(AM_V_CXX_no)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/exception/mediacore_hid_server-baseexceptions.obj `if test -f 'src/exception/baseexceptions.cpp'; then $(CYGPATH_W) 'src/exception/baseexceptions.cpp'; else $(CYGPATH_W) '$(srcdir)/src/exception/baseexceptions.cpp'; fi` + +src/log/mediacore_hid_server-log.o: src/log/log.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/log/mediacore_hid_server-log.o -MD -MP -MF src/log/$(DEPDIR)/mediacore_hid_server-log.Tpo -c -o src/log/mediacore_hid_server-log.o `test -f 'src/log/log.cpp' || echo '$(srcdir)/'`src/log/log.cpp + $(AM_V_at)$(am__mv) src/log/$(DEPDIR)/mediacore_hid_server-log.Tpo src/log/$(DEPDIR)/mediacore_hid_server-log.Po +# $(AM_V_CXX)source='src/log/log.cpp' object='src/log/mediacore_hid_server-log.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(AM_V_CXX_no)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/log/mediacore_hid_server-log.o `test -f 'src/log/log.cpp' || echo '$(srcdir)/'`src/log/log.cpp + +src/log/mediacore_hid_server-log.obj: src/log/log.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/log/mediacore_hid_server-log.obj -MD -MP -MF src/log/$(DEPDIR)/mediacore_hid_server-log.Tpo -c -o src/log/mediacore_hid_server-log.obj `if test -f 'src/log/log.cpp'; then $(CYGPATH_W) 'src/log/log.cpp'; else $(CYGPATH_W) '$(srcdir)/src/log/log.cpp'; fi` + $(AM_V_at)$(am__mv) src/log/$(DEPDIR)/mediacore_hid_server-log.Tpo src/log/$(DEPDIR)/mediacore_hid_server-log.Po +# $(AM_V_CXX)source='src/log/log.cpp' object='src/log/mediacore_hid_server-log.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(AM_V_CXX_no)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/log/mediacore_hid_server-log.obj `if test -f 'src/log/log.cpp'; then $(CYGPATH_W) 'src/log/log.cpp'; else $(CYGPATH_W) '$(srcdir)/src/log/log.cpp'; fi` + +src/thread/mediacore_hid_server-thread.o: src/thread/thread.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/thread/mediacore_hid_server-thread.o -MD -MP -MF src/thread/$(DEPDIR)/mediacore_hid_server-thread.Tpo -c -o src/thread/mediacore_hid_server-thread.o `test -f 'src/thread/thread.cpp' || echo '$(srcdir)/'`src/thread/thread.cpp + $(AM_V_at)$(am__mv) src/thread/$(DEPDIR)/mediacore_hid_server-thread.Tpo src/thread/$(DEPDIR)/mediacore_hid_server-thread.Po +# $(AM_V_CXX)source='src/thread/thread.cpp' object='src/thread/mediacore_hid_server-thread.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(AM_V_CXX_no)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/thread/mediacore_hid_server-thread.o `test -f 'src/thread/thread.cpp' || echo '$(srcdir)/'`src/thread/thread.cpp + +src/thread/mediacore_hid_server-thread.obj: src/thread/thread.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/thread/mediacore_hid_server-thread.obj -MD -MP -MF src/thread/$(DEPDIR)/mediacore_hid_server-thread.Tpo -c -o src/thread/mediacore_hid_server-thread.obj `if test -f 'src/thread/thread.cpp'; then $(CYGPATH_W) 'src/thread/thread.cpp'; else $(CYGPATH_W) '$(srcdir)/src/thread/thread.cpp'; fi` + $(AM_V_at)$(am__mv) src/thread/$(DEPDIR)/mediacore_hid_server-thread.Tpo src/thread/$(DEPDIR)/mediacore_hid_server-thread.Po +# $(AM_V_CXX)source='src/thread/thread.cpp' object='src/thread/mediacore_hid_server-thread.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(AM_V_CXX_no)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/thread/mediacore_hid_server-thread.obj `if test -f 'src/thread/thread.cpp'; then $(CYGPATH_W) 'src/thread/thread.cpp'; else $(CYGPATH_W) '$(srcdir)/src/thread/thread.cpp'; fi` + +src/buttontimer/mediacore_hid_server-buttontimer.o: src/buttontimer/buttontimer.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/buttontimer/mediacore_hid_server-buttontimer.o -MD -MP -MF src/buttontimer/$(DEPDIR)/mediacore_hid_server-buttontimer.Tpo -c -o src/buttontimer/mediacore_hid_server-buttontimer.o `test -f 'src/buttontimer/buttontimer.cpp' || echo '$(srcdir)/'`src/buttontimer/buttontimer.cpp + $(AM_V_at)$(am__mv) src/buttontimer/$(DEPDIR)/mediacore_hid_server-buttontimer.Tpo src/buttontimer/$(DEPDIR)/mediacore_hid_server-buttontimer.Po +# $(AM_V_CXX)source='src/buttontimer/buttontimer.cpp' object='src/buttontimer/mediacore_hid_server-buttontimer.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(AM_V_CXX_no)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/buttontimer/mediacore_hid_server-buttontimer.o `test -f 'src/buttontimer/buttontimer.cpp' || echo '$(srcdir)/'`src/buttontimer/buttontimer.cpp + +src/buttontimer/mediacore_hid_server-buttontimer.obj: src/buttontimer/buttontimer.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/buttontimer/mediacore_hid_server-buttontimer.obj -MD -MP -MF src/buttontimer/$(DEPDIR)/mediacore_hid_server-buttontimer.Tpo -c -o src/buttontimer/mediacore_hid_server-buttontimer.obj `if test -f 'src/buttontimer/buttontimer.cpp'; then $(CYGPATH_W) 'src/buttontimer/buttontimer.cpp'; else $(CYGPATH_W) '$(srcdir)/src/buttontimer/buttontimer.cpp'; fi` + $(AM_V_at)$(am__mv) src/buttontimer/$(DEPDIR)/mediacore_hid_server-buttontimer.Tpo src/buttontimer/$(DEPDIR)/mediacore_hid_server-buttontimer.Po +# $(AM_V_CXX)source='src/buttontimer/buttontimer.cpp' object='src/buttontimer/mediacore_hid_server-buttontimer.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(AM_V_CXX_no)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/buttontimer/mediacore_hid_server-buttontimer.obj `if test -f 'src/buttontimer/buttontimer.cpp'; then $(CYGPATH_W) 'src/buttontimer/buttontimer.cpp'; else $(CYGPATH_W) '$(srcdir)/src/buttontimer/buttontimer.cpp'; fi` + +src/gpio/mediacore_hid_server-gpio.o: src/gpio/gpio.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/gpio/mediacore_hid_server-gpio.o -MD -MP -MF src/gpio/$(DEPDIR)/mediacore_hid_server-gpio.Tpo -c -o src/gpio/mediacore_hid_server-gpio.o `test -f 'src/gpio/gpio.cpp' || echo '$(srcdir)/'`src/gpio/gpio.cpp + $(AM_V_at)$(am__mv) src/gpio/$(DEPDIR)/mediacore_hid_server-gpio.Tpo src/gpio/$(DEPDIR)/mediacore_hid_server-gpio.Po +# $(AM_V_CXX)source='src/gpio/gpio.cpp' object='src/gpio/mediacore_hid_server-gpio.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(AM_V_CXX_no)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/gpio/mediacore_hid_server-gpio.o `test -f 'src/gpio/gpio.cpp' || echo '$(srcdir)/'`src/gpio/gpio.cpp + +src/gpio/mediacore_hid_server-gpio.obj: src/gpio/gpio.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/gpio/mediacore_hid_server-gpio.obj -MD -MP -MF src/gpio/$(DEPDIR)/mediacore_hid_server-gpio.Tpo -c -o src/gpio/mediacore_hid_server-gpio.obj `if test -f 'src/gpio/gpio.cpp'; then $(CYGPATH_W) 'src/gpio/gpio.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gpio/gpio.cpp'; fi` + $(AM_V_at)$(am__mv) src/gpio/$(DEPDIR)/mediacore_hid_server-gpio.Tpo src/gpio/$(DEPDIR)/mediacore_hid_server-gpio.Po +# $(AM_V_CXX)source='src/gpio/gpio.cpp' object='src/gpio/mediacore_hid_server-gpio.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(AM_V_CXX_no)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/gpio/mediacore_hid_server-gpio.obj `if test -f 'src/gpio/gpio.cpp'; then $(CYGPATH_W) 'src/gpio/gpio.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gpio/gpio.cpp'; fi` + +src/gpio/mediacore_hid_server-dma.o: src/gpio/dma.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/gpio/mediacore_hid_server-dma.o -MD -MP -MF src/gpio/$(DEPDIR)/mediacore_hid_server-dma.Tpo -c -o src/gpio/mediacore_hid_server-dma.o `test -f 'src/gpio/dma.cpp' || echo '$(srcdir)/'`src/gpio/dma.cpp + $(AM_V_at)$(am__mv) src/gpio/$(DEPDIR)/mediacore_hid_server-dma.Tpo src/gpio/$(DEPDIR)/mediacore_hid_server-dma.Po +# $(AM_V_CXX)source='src/gpio/dma.cpp' object='src/gpio/mediacore_hid_server-dma.o' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(AM_V_CXX_no)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/gpio/mediacore_hid_server-dma.o `test -f 'src/gpio/dma.cpp' || echo '$(srcdir)/'`src/gpio/dma.cpp + +src/gpio/mediacore_hid_server-dma.obj: src/gpio/dma.cpp + $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/gpio/mediacore_hid_server-dma.obj -MD -MP -MF src/gpio/$(DEPDIR)/mediacore_hid_server-dma.Tpo -c -o src/gpio/mediacore_hid_server-dma.obj `if test -f 'src/gpio/dma.cpp'; then $(CYGPATH_W) 'src/gpio/dma.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gpio/dma.cpp'; fi` + $(AM_V_at)$(am__mv) src/gpio/$(DEPDIR)/mediacore_hid_server-dma.Tpo src/gpio/$(DEPDIR)/mediacore_hid_server-dma.Po +# $(AM_V_CXX)source='src/gpio/dma.cpp' object='src/gpio/mediacore_hid_server-dma.obj' libtool=no \ +# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \ +# $(AM_V_CXX_no)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mediacore_hid_server_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/gpio/mediacore_hid_server-dma.obj `if test -f 'src/gpio/dma.cpp'; then $(CYGPATH_W) 'src/gpio/dma.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gpio/dma.cpp'; fi` install-dbus_confDATA: $(dbus_conf_DATA) @$(NORMAL_INSTALL) @list='$(dbus_conf_DATA)'; test -n "$(dbus_confdir)" || list=; \ @@ -599,48 +780,6 @@ uninstall-dbus_confDATA: @list='$(dbus_conf_DATA)'; test -n "$(dbus_confdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(dbus_confdir)'; $(am__uninstall_files_from_dir) -install-etc_dirDATA: $(etc_dir_DATA) - @$(NORMAL_INSTALL) - @list='$(etc_dir_DATA)'; test -n "$(etc_dirdir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(etc_dirdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(etc_dirdir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(etc_dirdir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(etc_dirdir)" || exit $$?; \ - done - -uninstall-etc_dirDATA: - @$(NORMAL_UNINSTALL) - @list='$(etc_dir_DATA)'; test -n "$(etc_dirdir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - dir='$(DESTDIR)$(etc_dirdir)'; $(am__uninstall_files_from_dir) -install-modprobe_d_dirDATA: $(modprobe_d_dir_DATA) - @$(NORMAL_INSTALL) - @list='$(modprobe_d_dir_DATA)'; test -n "$(modprobe_d_dirdir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(modprobe_d_dirdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(modprobe_d_dirdir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(modprobe_d_dirdir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(modprobe_d_dirdir)" || exit $$?; \ - done - -uninstall-modprobe_d_dirDATA: - @$(NORMAL_UNINSTALL) - @list='$(modprobe_d_dir_DATA)'; test -n "$(modprobe_d_dirdir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - dir='$(DESTDIR)$(modprobe_d_dirdir)'; $(am__uninstall_files_from_dir) install-rsyslog_confDATA: $(rsyslog_conf_DATA) @$(NORMAL_INSTALL) @list='$(rsyslog_conf_DATA)'; test -n "$(rsyslog_confdir)" || list=; \ @@ -663,26 +802,15 @@ uninstall-rsyslog_confDATA: files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(rsyslog_confdir)'; $(am__uninstall_files_from_dir) -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - mkid -fID $$unique -tags: TAGS +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags -TAGS: $(HEADERS) $(SOURCES) config.hpp.in $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ - list='$(SOURCES) $(HEADERS) config.hpp.in $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ + $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ @@ -694,15 +822,11 @@ TAGS: $(HEADERS) $(SOURCES) config.hpp.in $(TAGS_DEPENDENCIES) \ $$unique; \ fi; \ fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) config.hpp.in $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) config.hpp.in $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique @@ -711,104 +835,36 @@ GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files -check-TESTS: $(TESTS) - @failed=0; all=0; xfail=0; xpass=0; skip=0; \ - srcdir=$(srcdir); export srcdir; \ - list=' $(TESTS) '; \ - $(am__tty_colors); \ - if test -n "$$list"; then \ - for tst in $$list; do \ - if test -f ./$$tst; then dir=./; \ - elif test -f $$tst; then dir=; \ - else dir="$(srcdir)/"; fi; \ - if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ - all=`expr $$all + 1`; \ - case " $(XFAIL_TESTS) " in \ - *[\ \ ]$$tst[\ \ ]*) \ - xpass=`expr $$xpass + 1`; \ - failed=`expr $$failed + 1`; \ - col=$$red; res=XPASS; \ - ;; \ - *) \ - col=$$grn; res=PASS; \ - ;; \ - esac; \ - elif test $$? -ne 77; then \ - all=`expr $$all + 1`; \ - case " $(XFAIL_TESTS) " in \ - *[\ \ ]$$tst[\ \ ]*) \ - xfail=`expr $$xfail + 1`; \ - col=$$lgn; res=XFAIL; \ - ;; \ - *) \ - failed=`expr $$failed + 1`; \ - col=$$red; res=FAIL; \ - ;; \ - esac; \ - else \ - skip=`expr $$skip + 1`; \ - col=$$blu; res=SKIP; \ - fi; \ - echo "$${col}$$res$${std}: $$tst"; \ - done; \ - if test "$$all" -eq 1; then \ - tests="test"; \ - All=""; \ - else \ - tests="tests"; \ - All="All "; \ - fi; \ - if test "$$failed" -eq 0; then \ - if test "$$xfail" -eq 0; then \ - banner="$$All$$all $$tests passed"; \ - else \ - if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ - banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ - fi; \ - else \ - if test "$$xpass" -eq 0; then \ - banner="$$failed of $$all $$tests failed"; \ - else \ - if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ - banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ - fi; \ - fi; \ - dashes="$$banner"; \ - skipped=""; \ - if test "$$skip" -ne 0; then \ - if test "$$skip" -eq 1; then \ - skipped="($$skip test was not run)"; \ - else \ - skipped="($$skip tests were not run)"; \ - fi; \ - test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ - dashes="$$skipped"; \ - fi; \ - report=""; \ - if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ - report="Please report to $(PACKAGE_BUGREPORT)"; \ - test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ - dashes="$$report"; \ - fi; \ - dashes=`echo "$$dashes" | sed s/./=/g`; \ - if test "$$failed" -eq 0; then \ - col="$$grn"; \ - else \ - col="$$red"; \ - fi; \ - echo "$${col}$$dashes$${std}"; \ - echo "$${col}$$banner$${std}"; \ - test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ - test -z "$$report" || echo "$${col}$$report$${std}"; \ - echo "$${col}$$dashes$${std}"; \ - test "$$failed" -eq 0; \ - else :; fi +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am -distdir: $(DISTFILES) +distdir-am: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ @@ -848,41 +904,43 @@ distdir: $(DISTFILES) ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz - $(am__remove_distdir) + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz + $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 - $(am__remove_distdir) + $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz - $(am__remove_distdir) - -dist-lzma: distdir - tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma - $(am__remove_distdir) + $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz - $(am__remove_distdir) + $(am__post_remove_distdir) dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z - $(am__remove_distdir) + $(am__post_remove_distdir) dist-shar: distdir - shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz - $(am__remove_distdir) + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz + $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) - $(am__remove_distdir) + $(am__post_remove_distdir) -dist dist-all: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz - $(am__remove_distdir) +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another @@ -890,11 +948,9 @@ dist dist-all: distdir distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ - *.tar.lzma*) \ - lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ @@ -902,22 +958,23 @@ distcheck: dist *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac - chmod -R a-w $(distdir); chmod u+w $(distdir) - mkdir $(distdir)/_build - mkdir $(distdir)/_inst + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ - && $(am__cd) $(distdir)/_build \ - && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ @@ -940,7 +997,7 @@ distcheck: dist && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 - $(am__remove_distdir) + $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' @@ -971,13 +1028,11 @@ distcleancheck: distclean $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am - $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) - $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(PROGRAMS) $(SCRIPTS) $(DATA) config.hpp installdirs: - for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(init_d_dirdir)" "$(DESTDIR)$(dbus_confdir)" "$(DESTDIR)$(etc_dirdir)" "$(DESTDIR)$(modprobe_d_dirdir)" "$(DESTDIR)$(rsyslog_confdir)"; do \ + for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(init_d_dirdir)" "$(DESTDIR)$(dbus_confdir)" "$(DESTDIR)$(rsyslog_confdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) @@ -1015,14 +1070,8 @@ distclean-generic: -rm -f src/exception/$(am__dirstamp) -rm -f src/gpio/$(DEPDIR)/$(am__dirstamp) -rm -f src/gpio/$(am__dirstamp) - -rm -f src/i2c/$(DEPDIR)/$(am__dirstamp) - -rm -f src/i2c/$(am__dirstamp) -rm -f src/log/$(DEPDIR)/$(am__dirstamp) -rm -f src/log/$(am__dirstamp) - -rm -f src/mcp23017/$(DEPDIR)/$(am__dirstamp) - -rm -f src/mcp23017/$(am__dirstamp) - -rm -f src/test/$(DEPDIR)/$(am__dirstamp) - -rm -f src/test/$(am__dirstamp) -rm -f src/thread/$(DEPDIR)/$(am__dirstamp) -rm -f src/thread/$(am__dirstamp) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) @@ -1033,12 +1082,18 @@ maintainer-clean-generic: -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am -clean-am: clean-checkPROGRAMS clean-generic clean-sbinPROGRAMS \ - mostlyclean-am +clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf src/$(DEPDIR) src/buttontimer/$(DEPDIR) src/exception/$(DEPDIR) src/gpio/$(DEPDIR) src/i2c/$(DEPDIR) src/log/$(DEPDIR) src/mcp23017/$(DEPDIR) src/test/$(DEPDIR) src/thread/$(DEPDIR) + -rm -f src/$(DEPDIR)/mediacore_hid_server-mc-hid-server.Po + -rm -f src/buttontimer/$(DEPDIR)/mediacore_hid_server-buttontimer.Po + -rm -f src/exception/$(DEPDIR)/mediacore_hid_server-baseexceptions.Po + -rm -f src/gpio/$(DEPDIR)/mediacore_hid_server-dma.Po + -rm -f src/gpio/$(DEPDIR)/mediacore_hid_server-gpio.Po + -rm -f src/gpio/$(DEPDIR)/mediacore_hid_server-mailbox.Po + -rm -f src/log/$(DEPDIR)/mediacore_hid_server-log.Po + -rm -f src/thread/$(DEPDIR)/mediacore_hid_server-thread.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-tags @@ -1055,8 +1110,7 @@ info: info-am info-am: -install-data-am: install-dbus_confDATA install-etc_dirDATA \ - install-init_d_dirSCRIPTS install-modprobe_d_dirDATA \ +install-data-am: install-dbus_confDATA install-init_d_dirSCRIPTS \ install-rsyslog_confDATA install-dvi: install-dvi-am @@ -1088,7 +1142,14 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache - -rm -rf src/$(DEPDIR) src/buttontimer/$(DEPDIR) src/exception/$(DEPDIR) src/gpio/$(DEPDIR) src/i2c/$(DEPDIR) src/log/$(DEPDIR) src/mcp23017/$(DEPDIR) src/test/$(DEPDIR) src/thread/$(DEPDIR) + -rm -f src/$(DEPDIR)/mediacore_hid_server-mc-hid-server.Po + -rm -f src/buttontimer/$(DEPDIR)/mediacore_hid_server-buttontimer.Po + -rm -f src/exception/$(DEPDIR)/mediacore_hid_server-baseexceptions.Po + -rm -f src/gpio/$(DEPDIR)/mediacore_hid_server-dma.Po + -rm -f src/gpio/$(DEPDIR)/mediacore_hid_server-gpio.Po + -rm -f src/gpio/$(DEPDIR)/mediacore_hid_server-mailbox.Po + -rm -f src/log/$(DEPDIR)/mediacore_hid_server-log.Po + -rm -f src/thread/$(DEPDIR)/mediacore_hid_server-thread.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -1104,32 +1165,32 @@ ps: ps-am ps-am: -uninstall-am: uninstall-dbus_confDATA uninstall-etc_dirDATA \ - uninstall-init_d_dirSCRIPTS uninstall-modprobe_d_dirDATA \ +uninstall-am: uninstall-dbus_confDATA uninstall-init_d_dirSCRIPTS \ uninstall-rsyslog_confDATA uninstall-sbinPROGRAMS -.MAKE: all check check-am install install-am install-strip +.MAKE: all check install install-am install-strip -.PHONY: CTAGS GTAGS all all-am am--refresh check check-TESTS check-am \ - clean clean-checkPROGRAMS clean-generic clean-sbinPROGRAMS \ - ctags dist dist-all dist-bzip2 dist-gzip dist-lzip dist-lzma \ - dist-shar dist-tarZ dist-xz dist-zip distcheck distclean \ - distclean-compile distclean-generic distclean-hdr \ - distclean-tags distcleancheck distdir distuninstallcheck dvi \ - dvi-am html html-am info info-am install install-am \ - install-data install-data-am install-dbus_confDATA install-dvi \ - install-dvi-am install-etc_dirDATA install-exec \ +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles am--refresh check \ + check-am clean clean-cscope clean-generic clean-sbinPROGRAMS \ + cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ + dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \ + distcheck distclean distclean-compile distclean-generic \ + distclean-hdr distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dbus_confDATA install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-init_d_dirSCRIPTS install-man \ - install-modprobe_d_dirDATA install-pdf install-pdf-am \ - install-ps install-ps-am install-rsyslog_confDATA \ - install-sbinPROGRAMS install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-rsyslog_confDATA install-sbinPROGRAMS install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ - uninstall-am uninstall-dbus_confDATA uninstall-etc_dirDATA \ - uninstall-init_d_dirSCRIPTS uninstall-modprobe_d_dirDATA \ - uninstall-rsyslog_confDATA uninstall-sbinPROGRAMS + mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-dbus_confDATA \ + uninstall-init_d_dirSCRIPTS uninstall-rsyslog_confDATA \ + uninstall-sbinPROGRAMS + +.PRECIOUS: Makefile src/mc-hid-server-glue.hpp: src/mc-hid-introspect.xml diff --git a/Makefile.am b/Makefile.am index 963997d..a25812f 100755 --- a/Makefile.am +++ b/Makefile.am @@ -6,35 +6,25 @@ AM_CPPFLAGS = $(DEPS_CFLAGS) DISTCLEANFILES = src/mc-hid-server-glue.hpp \ script/init.d/mediacore-hid -I2C_SRC = src/i2c/i2c.c \ - src/i2c/i2c.h - -MCP_GPIO_SRC = src/gpio/gpio.hpp \ - src/gpio/gpio.cpp \ - src/mcp23017/mcp23017.hpp \ - src/mcp23017/mcp23017.cpp \ - src/exception/baseexceptions.hpp \ - src/exception/baseexceptions.cpp \ - $(I2C_SRC) - SUPPORT_SRC = src/log/log.hpp \ src/log/log.cpp \ src/thread/thread.hpp \ src/thread/thread.cpp \ src/buttontimer/buttontimer.hpp \ - src/buttontimer/buttontimer.cpp + src/buttontimer/buttontimer.cpp \ + src/gpio/gpio.hpp \ + src/gpio/gpio.cpp \ + src/gpio/dma.hpp \ + src/gpio/dma.cpp \ + src/gpio/mailbox.h \ + src/gpio/mailbox.c sbin_PROGRAMS = mediacore-hid-server -check_PROGRAMS = mcp23017-i2ctest -TESTS = mcp23017-i2ctest -EXTRA_DIST = \ - cfg/dbus/nl.miqra.MediaCore.Hid.conf \ +EXTRA_DIST = cfg/dbus/nl.miqra.MediaCore.Hid.conf \ cfg/init.d/mediacore-hid.in \ cfg/rsyslog/syslog.MediaCore.Hid.conf \ - src/mc-hid-introspect.xml \ - cfg/modules \ - cfg/modprobe.d/raspi-blacklist.conf + src/mc-hid-introspect.xml init_d_dirdir = $(sysconfdir)/init.d init_d_dir_SCRIPTS = cfg/init.d/mediacore-hid @@ -45,31 +35,21 @@ dbus_conf_DATA = cfg/dbus/nl.miqra.MediaCore.Hid.conf rsyslog_confdir = $(sysconfdir)/rsyslog.d rsyslog_conf_DATA = cfg/rsyslog/syslog.MediaCore.Hid.conf -etc_dirdir = $(sysconfdir) -etc_dir_DATA = cfg/modules - -modprobe_d_dirdir = $(sysconfdir)/modprobe.d -modprobe_d_dir_DATA = cfg/modprobe.d/raspi-blacklist.conf - - src/mc-hid-server-glue.hpp: src/mc-hid-introspect.xml dbusxx-xml2cpp $^ --adaptor=$@ BUILT_SOURCES = src/mc-hid-server-glue.hpp +mediacore_hid_server_CPPFLAGS = -std=c++17 -I/usr/include/dbus-c++-1/ -I/opt/vc/include/ mediacore_hid_server_SOURCES = src/mc-hid-server.cpp \ src/mc-hid-server.hpp \ src/mc-hid-server-glue.hpp \ - $(MCP_GPIO_SRC) \ + src/exception/baseexceptions.hpp \ + src/exception/baseexceptions.cpp \ $(SUPPORT_SRC) -mediacore_hid_server_LDADD = $(DEPS_LIBS) -lpthread -lrt +mediacore_hid_server_LDADD = $(DEPS_LIBS) -L/opt/vc/lib -lpthread -lrt -lgpiodcxx -lbcm_host - -mcp23017_i2ctest_SOURCES = src/test/mcp23017-i2ctest.c \ - $(I2C_SRC) - -mcp23017_i2ctest_LDADD = -lpthread cfg/init.d/mediacore-hid: cfg/init.d/mediacore-hid.in cat $^ > $@ diff --git a/cfg/init.d/mediacore-hid b/cfg/init.d/mediacore-hid new file mode 100644 index 0000000..a510642 --- /dev/null +++ b/cfg/init.d/mediacore-hid @@ -0,0 +1,163 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: mediacorehid +# Required-Start: $syslog $dbus +# Required-Stop: $syslog $dbus +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Example initscript +# Description: This file should be used to construct scripts to be +# placed in /etc/init.d. +### END INIT INFO + +# Author: Miqra Engineering <@miqra.nl> +# +# Please remove the "Author" lines above and replace them +# with your own name if you copy and modify this script. + +# Do NOT "set -e" + +# PATH should only include /usr/* if it runs after the mountnfs.sh script +PATH=/sbin:/bin:/usr/sbin:/usr/bin +DESC="Mediacore HID interface server" +NAME=mediacore-hid-server +DAEMON=/usr/local/sbin/$NAME +DAEMON_ARGS="" +PIDFILE=/var/run/$NAME.pid +SCRIPTNAME=/usr/local/etc/init.d/$NAME + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Read configuration variable file if it is present +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +VERBOSE=yes + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.2-14) to ensure that this file is present +# and status_of_proc is working. +. /lib/lsb/init-functions + +# +# Function that starts the daemon/service +# +do_start() +{ + # Return + # 0 if daemon has been started + # 1 if daemon was already running + # 2 if daemon could not be started + start-stop-daemon --start --quiet --background -m --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ + || return 1 + start-stop-daemon --start --quiet --background -m --pidfile $PIDFILE --exec $DAEMON -- \ + $DAEMON_ARGS \ + || return 2 + # Add code here, if necessary, that waits for the process to be ready + # to handle requests from services started subsequently which depend + # on this one. As a last resort, sleep for some time. + sleep 0.3 + dbus-send --system --dest=nl.miqra.MediaCore.Hid --type=method_call /nl/miqra/MediaCore/Hid nl.miqra.MediaCore.Hid.SetColor byte:128 byte:0 byte:0 +} + +# +# Function that stops the daemon/service +# +do_stop() +{ + # Return + # 0 if daemon has been stopped + # 1 if daemon was already stopped + # 2 if daemon could not be stopped + # other if a failure occurred + start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --exec $DAEMON + RETVAL="$?" + [ "$RETVAL" = 2 ] && return 2 + # Wait for children to finish too if this is a daemon that forks + # and if the daemon is only ever run from this initscript. + # If the above conditions are not satisfied then add some other code + # that waits for the process to drop all resources that could be + # needed by services started subsequently. A last resort is to + # sleep for some time. + start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON + [ "$?" = 2 ] && return 2 + # Many daemons don't delete their pidfiles when they exit. + rm -f $PIDFILE + return "$RETVAL" +} + +# +# Function that sends a SIGHUP to the daemon/service +# +do_reload() { + # + # If the daemon can reload its configuration without + # restarting (for example, when it is sent a SIGHUP), + # then implement that here. + # + start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --exec $DAEMON + return 0 +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + status) + status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? + ;; + #reload|force-reload) + # + # If do_reload() is not implemented then leave this commented out + # and leave 'force-reload' as an alias for 'restart'. + # + #log_daemon_msg "Reloading $DESC" "$NAME" + #do_reload + #log_end_msg $? + #;; + restart|force-reload) + # + # If the "reload" option is implemented then remove the + # 'force-reload' alias + # + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2 + echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 + exit 3 + ;; +esac + +: diff --git a/cfg/modprobe.d/raspi-blacklist.conf b/cfg/modprobe.d/raspi-blacklist.conf deleted file mode 100644 index d7e3a73..0000000 --- a/cfg/modprobe.d/raspi-blacklist.conf +++ /dev/null @@ -1,4 +0,0 @@ -# blacklist spi and i2c by default (many users don't need them) - -blacklist spi-bcm2708 -#blacklist i2c-bcm2708 diff --git a/cfg/modules b/cfg/modules deleted file mode 100644 index 7af9ed7..0000000 --- a/cfg/modules +++ /dev/null @@ -1,8 +0,0 @@ -# /etc/modules: kernel modules to load at boot time. -# -# This file contains the names of kernel modules that should be loaded -# at boot time, one per line. Lines beginning with "#" are ignored. -# Parameters can be specified after the module name. - -snd-bcm2835 -i2c-dev diff --git a/cfg/piio.conf b/cfg/piio.conf deleted file mode 100644 index 6dfdae6..0000000 --- a/cfg/piio.conf +++ /dev/null @@ -1,148 +0,0 @@ -# Example configuration file for PiIo -# -# Configuration is done in groups called I/O groups. -# Each IO group can only contain I/O's of one type, e.g. only Raspberry Pi GPIOs or only pins on one MCP23017 IO expander -# for each type there are parameters -# Each group has a unique name - -# Note that in this example config file, all actual code is initially commented out to avoid problems directly after install - -/* -# Io Group called GPIO -GPIO: -{ - # it is of I/O type "GPIO", indicating it uses Raspberry Pi internal GPIOS - type = "GPIO"; - - # Settings for this groups PWM generatoer - pwm-tickdelay-us = 1600; # Number of microseconds between ticks - pwm-ticks = 16; # Number of ticks in a pwm cycle - - # Settings for the individual I/O's - # Here too, each I/O has it's own type and it's own id. - - io: - { - # Input called 'intest' - intest: - { - # It is of type "MULTIBITIN", which means that it takes values from multiple - # bits and combines it into a single number value. - # (To use a multibit output, you can use the type "MULTIBITOUT", which takes the same configuration, minus the additional settings) - type: "MULTIBITIN"; - - # The 'pins' options specified the pins that are used for the multibit input. - # For the GPIO, it takes the BCM identifiers. Both revision 1 and 2 are supported, and converted to the proper pin automatically - # Bit order is important, MSB first, LSB last. - pins: [17, 18]; - - # Additional config options are: - - // pullup: True/False # Default: False - Enable/disable internal pullup (currently not functional on GPIO type) - // invert: True/False # Default: False - Invert the input pins before processing - // int-enabled: True/False # Default: True - Trigger an event on value change for this input - } - - # Button called 'btn' - btn: - { - # Input of type "BUTTON", which means a single input pin, treated as a button. - # Buttons can trigger only 'Pressed' and 'Held' events, which trigger when the button is either pressed - # for a minimum of (default) 25 ms, or held for a minimum of (default) 6000 ms - # These values can be configured in the IO Group config - type: "BUTTON"; - - # Button is connected on pin 4. - pin: 4; - - # Additional config options are: - - // pullup: True/False # Default: True - Enable/disable internal pullup (currently not functional on GPIO type) - // invert: True/False # Default: True - Invert the input pins before processing - // int-enabled: True/False # Default: True - Trigger an event on value change for this input - - # Note that defaults for buttons are different from defaults for other inputs (invert and pullup true by default for buttons) - - } - - # Output called 'led1' - led1: - { - # Output of type "OUTPUTPIN", which means a single output pin. - type: "OUTPUTPIN"; - - # Output on pin 23 - pin: 23; - }; - # Output called 'led1' - led2: - { - # Output of type "OUTPUTPIN", which means a single output pin. - type: "OUTPUTPIN"; - # Output on pin 24 - pin: 24; - }; - # PWM Output called 'led3' - led3: - { - # Output of type "PWMPIN", which means pwm on a single output pin. - # Note that using PWM takes up processor time, - # currently around 5% for mcp23017 pins, and up to 30% for GPIO pins. (This last value is being worked on) - type: "PWMPIN"; - - # Output on pin 23 - pin: 25; - }; - }; -} -*/ - -/* -# Io Group called GPIO -MCP1: -{ - # it is of I/O type "MCP23017", indicating it uses an MCP23017 I2C I/O expander chip - type = "MCP23017"; - - # The MCP23017 needs an I2C address, and optionally a GPIO I/O pin to receive interrupts on - address = 0x20; - intpin = 22; - - # Settings for the individual I/O's - # Here too, each I/O has it's own type and it's own id. - - # Note that the pin id's for an MCP23017 are counted from the GPA0 as pin 0 up to GPB7 as pin 15 - io: - { - # Input called 'sensor1' - sensor1: - { - # It is of type "INPUTPIN", which means that it takes the value from the single input pin - type: "INPUTPIN"; - - # Input on pin 7 - pin: 7; - } - leda: - { - # Output of type "PWMPIN", which means pwm on a single output pin. - # Note that using PWM takes up processor time, - # currently around 5% for mcp23017 pins, and up to 30% for GPIO pins. (This last value is being worked on) - type: "PWMPIN"; - - # Output on pin 8 - pin: 8; - } - ledb: - { - # Output of type "PWMPIN", which means pwm on a single output pin. - # Note that using PWM takes up processor time, - # currently around 5% for mcp23017 pins, and up to 30% for GPIO pins. (This last value is being worked on) - type: "PWMPIN"; - - # Output on pin 9 - pin: 9; - } - } -} -*/ \ No newline at end of file diff --git a/config.hpp b/config.hpp index 2ce0ed3..15c455b 100644 --- a/config.hpp +++ b/config.hpp @@ -11,7 +11,7 @@ #define PACKAGE_NAME "MediaCore HID Server" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "MediaCore HID Server 1.0.0" +#define PACKAGE_STRING "MediaCore HID Server 4.0.0" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "mediacore-hid" @@ -20,4 +20,4 @@ #define PACKAGE_URL "http://www.miqra.nl/" /* Define to the version of this package. */ -#define PACKAGE_VERSION "1.0.0" +#define PACKAGE_VERSION "4.0.0" diff --git a/configure.ac b/configure.ac index 2929f57..8c3afeb 100755 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([MediaCore HID Server], [1.0.0], [bugs@miqra.nl], [mediacore-hid], [http://www.miqra.nl/]) +AC_INIT([MediaCore HID Server], [4.0.0], [bugs@miqra.nl], [mediacore-hid], [http://www.miqra.nl/]) AC_PREREQ([2.59]) AM_INIT_AUTOMAKE([1.11 no-define foreign subdir-objects]) AC_CONFIG_HEADERS([config.hpp]) diff --git a/deb-dependencies.txt b/deb-dependencies.txt index 08743ab..8557ba7 100644 --- a/deb-dependencies.txt +++ b/deb-dependencies.txt @@ -3,4 +3,5 @@ libboost-all-dev libdbus-c++-bin libdbus-c++-dev libdbus-1-dev +libpigpio-dev diff --git a/debian/control b/debian/control index 420a9fe..110423e 100755 --- a/debian/control +++ b/debian/control @@ -1,15 +1,13 @@ Source: mediacore-hid Section: misc -Suite: stable Priority: optional Maintainer: Miqra Engineering Packaging -Build-Depends: debhelper (>= 8.0.0), autotools-dev, autoconf-archive, libboost-all-dev, libdbus-c++-bin, libdbus-c++-dev, libdbus-1-dev, libtclap-dev -Standards-Version: 3.9.3 -Debian-Version: 1 +Build-Depends: debhelper (>= 8.0.0), autotools-dev, autoconf-archive, libboost-all-dev, libdbus-c++-bin, libdbus-c++-dev, libdbus-1-dev, libgpiod-dev, libraspberrypi-dev +Standards-Version: 4.3.0 Homepage: Package: mediacore-hid -Architecture: any +Architecture: armhf Depends: ${shlibs:Depends}, ${misc:Depends} Description: I/O System for Mediacore Interface I/O server system for mediacore that exposes the i/o through DBUS for use in other applications diff --git a/debpackager.py b/debpackager.py index d28325b..1569d96 100644 --- a/debpackager.py +++ b/debpackager.py @@ -46,7 +46,7 @@ call(["tar","-xzvf",DEBSOURCEPKG]) print "Entering dir " + PKGDIR os.chdir(PKGDIR) print "Now in ", os.getcwd() -call(["dh_make --single -yes --copyright bsd"],shell=True) +call(["dh_make --single --yes --copyright lgpl"],shell=True) for f in glob.glob(os.path.join(CWD,"debian","*")): dst = os.path.join(CWD,PKGPATH,"debian",os.path.basename(f)) diff --git a/mediacore-hid-server b/mediacore-hid-server new file mode 100755 index 0000000..2c61268 Binary files /dev/null and b/mediacore-hid-server differ diff --git a/src/buttontimer/buttontimer.cpp b/src/buttontimer/buttontimer.cpp index 9e9e6a8..da26ff8 100644 --- a/src/buttontimer/buttontimer.cpp +++ b/src/buttontimer/buttontimer.cpp @@ -20,7 +20,7 @@ ButtonTimer::~ButtonTimer() } -void ButtonTimer::RegisterPress(uint16_t keycode) +void ButtonTimer::RegisterPress(const uint8_t keycode) { MutexLock(); // Prevent trouble when calling this from within one of our event listeners @@ -31,21 +31,18 @@ void ButtonTimer::RegisterPress(uint16_t keycode) } -void ButtonTimer::RegisterRelease(uint16_t keycode) +void ButtonTimer::RegisterRelease(const uint8_t keycode) { - uint64_t now = now_ms(); - uint64_t then; MutexLock(); // Prevent trouble when calling this from within one of our event listeners if(eventLock) { MutexUnlock(); return; } - - if(pressRegistry.count(keycode)) { // if it was a long press, the key code would already have been erased, so we // can safely fire the onShortPress event - then = pressRegistry[keycode]; + uint64_t now = now_ms(); + uint64_t then = pressRegistry[keycode]; // remove from registry after release, if it was a long press, the event should have already been fired pressRegistry.erase(keycode); @@ -60,7 +57,7 @@ void ButtonTimer::RegisterRelease(uint16_t keycode) MutexUnlock(); } -void ButtonTimer::CancelPress(uint16_t keycode) +void ButtonTimer::CancelPress(const uint8_t keycode) { // remove button id from map (but only if it is in the map already) MutexLock(); @@ -77,12 +74,12 @@ void ButtonTimer::CancelPress(uint16_t keycode) void ButtonTimer::ThreadLoop() { uint64_t now = now_ms(); - std::list btnList; + std::list btnList; boost::optional valid; MutexLock(); // list through all the items - for( std::map::iterator ii=pressRegistry.begin(); ii!=pressRegistry.end(); ++ii) + for( std::map::iterator ii=pressRegistry.begin(); ii!=pressRegistry.end(); ++ii) { if(now - (ii->second) >= longpressTime) // if it is in overtime { @@ -92,7 +89,7 @@ void ButtonTimer::ThreadLoop() } // Process listed items - for (std::list::iterator it=btnList.begin(); it != btnList.end(); ++it) + for (std::list::iterator it=btnList.begin(); it != btnList.end(); ++it) { pressRegistry.erase(*it); // If any validators are connected, they can retun false to indicate that this connection is not diff --git a/src/buttontimer/buttontimer.hpp b/src/buttontimer/buttontimer.hpp index 442df34..379d846 100644 --- a/src/buttontimer/buttontimer.hpp +++ b/src/buttontimer/buttontimer.hpp @@ -11,13 +11,13 @@ class ButtonTimer : protected Thread ButtonTimer(uint32_t shortpress_min_ms, uint32_t longpress_ms); ~ButtonTimer(); - void RegisterPress(uint16_t keycode); - void RegisterRelease(uint16_t keycode); - void CancelPress(uint16_t id); + void RegisterPress(const uint8_t keycode); + void RegisterRelease(const uint8_t keycode); + void CancelPress(const uint8_t keycode); - boost::signals2::signal onShortPress; - boost::signals2::signal onLongPress; - boost::signals2::signal onValidatePress; + boost::signals2::signal onShortPress; + boost::signals2::signal onLongPress; + boost::signals2::signal onValidatePress; protected: virtual void ThreadLoop(void); @@ -26,7 +26,7 @@ class ButtonTimer : protected Thread boost::signals2::connection onThreadErrorConnection; uint32_t longpressTime; uint32_t shortpressMinTime; - std::map pressRegistry; + std::map pressRegistry; bool eventLock; static int64_t now_ms(void); diff --git a/src/gpio/dma.cpp b/src/gpio/dma.cpp new file mode 100644 index 0000000..23d663d --- /dev/null +++ b/src/gpio/dma.cpp @@ -0,0 +1,796 @@ +/* + * This file is part of RPIO-PWM. + * + * Copyright + * + * Copyright (C) 2020 Xinkai Wang + * + * License + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details at + * + * + * Documentation + * + * https://github.com/xinkaiwang/rpio-pwm + * + * dma.c, based on the excellent servod.c by Richard Hirst, provides flexible + * PWM via DMA for the Raspberry Pi, supporting a resolution of up to 1us, + * all 15 DMA channels, multiple GPIOs per channel, timing by PWM (default) + * or PCM, a Python wrapper, and more. + * + * Feedback is much appreciated. + */ + +#include "dma.hpp" + +#include +#include +#include +#include + +#include "mailbox.h" + +#define DMY 255 // Used to represent an invalid P1 pin, or unmapped servo + +#define NUM_P1PINS 40 +#define NUM_P5PINS 8 + +#define MAX_MEMORY_USAGE \ + (16 * 1024 * 1024) /* Somewhat arbitrary limit of 16MB */ + +#define DEFAULT_CYCLE_TIME_US 20000 +#define DEFAULT_STEP_TIME_US 10 +#define DEFAULT_SERVO_MIN_US 500 +#define DEFAULT_SERVO_MAX_US 2500 + +#define DEVFILE "/dev/servoblaster" +#define CFGFILE "/dev/servoblaster-cfg" + +#define PAGE_SIZE 4096 +#define PAGE_SHIFT 12 + +#define DMA_CHAN_SIZE 0x100 +#define DMA_CHAN_MIN 0 +#define DMA_CHAN_MAX 14 +#define DMA_CHAN_DEFAULT 14 +#define DMA_CHAN_PI4 7 + +#define DMA_BASE_OFFSET 0x00007000 +#define DMA_LEN DMA_CHAN_SIZE *(DMA_CHAN_MAX + 1) +#define PWM_BASE_OFFSET 0x0020C000 +#define PWM_LEN 0x28 +#define CLK_BASE_OFFSET 0x00101000 +#define CLK_LEN 0xA8 +#define GPIO_BASE_OFFSET 0x00200000 +#define GPIO_LEN 0x100 +#define PCM_BASE_OFFSET 0x00203000 +#define PCM_LEN 0x24 + +#define DMA_VIRT_BASE(hw) ((hw).periph_virt_base + DMA_BASE_OFFSET) +#define PWM_VIRT_BASE(hw) ((hw).periph_virt_base + PWM_BASE_OFFSET) +#define CLK_VIRT_BASE(hw) ((hw).periph_virt_base + CLK_BASE_OFFSET) +#define GPIO_VIRT_BASE(hw) ((hw).periph_virt_base + GPIO_BASE_OFFSET) +#define PCM_VIRT_BASE(hw) ((hw).periph_virt_base + PCM_BASE_OFFSET) + +#define PWM_PHYS_BASE(hw) ((hw).periph_phys_base + PWM_BASE_OFFSET) +#define PCM_PHYS_BASE(hw) ((hw).periph_phys_base + PCM_BASE_OFFSET) +#define GPIO_PHYS_BASE(hw) ((hw).periph_phys_base + GPIO_BASE_OFFSET) + +#define DMA_NO_WIDE_BURSTS (1 << 26) +#define DMA_WAIT_RESP (1 << 3) +#define DMA_D_DREQ (1 << 6) +#define DMA_PER_MAP(x) ((x) << 16) +#define DMA_END (1 << 1) +#define DMA_RESET (1U << 31) +#define DMA_INT (1 << 2) + +#define DMA_CS (0x00 / 4) +#define DMA_CONBLK_AD (0x04 / 4) +#define DMA_SOURCE_AD (0x0c / 4) +#define DMA_DEBUG (0x20 / 4) + +#define GPIO_FSEL0 (0x00 / 4) +#define GPIO_SET0 (0x1c / 4) +#define GPIO_CLR0 (0x28 / 4) +#define GPIO_LEV0 (0x34 / 4) +#define GPIO_PULLEN (0x94 / 4) +#define GPIO_PULLCLK (0x98 / 4) + +#define GPIO_MODE_IN 0 +#define GPIO_MODE_OUT 1 + +#define PWM_CTL (0x00 / 4) +#define PWM_DMAC (0x08 / 4) +#define PWM_RNG1 (0x10 / 4) +#define PWM_FIFO (0x18 / 4) + +#define PWMCLK_CNTL 40 +#define PWMCLK_DIV 41 + +#define PWMCTL_MODE1 (1 << 1) +#define PWMCTL_PWEN1 (1 << 0) +#define PWMCTL_CLRF (1 << 6) +#define PWMCTL_USEF1 (1 << 5) + +#define PWMDMAC_ENAB (1U << 31) +#define PWMDMAC_THRSHLD ((15 << 8) | (15 << 0)) + +#define PCM_CS_A (0x00 / 4) +#define PCM_FIFO_A (0x04 / 4) +#define PCM_MODE_A (0x08 / 4) +#define PCM_RXC_A (0x0c / 4) +#define PCM_TXC_A (0x10 / 4) +#define PCM_DREQ_A (0x14 / 4) +#define PCM_INTEN_A (0x18 / 4) +#define PCM_INT_STC_A (0x1c / 4) +#define PCM_GRAY (0x20 / 4) + +#define PCMCLK_CNTL 38 +#define PCMCLK_DIV 39 + +#define PLLDFREQ_MHZ_DEFAULT 500 +#define PLLDFREQ_MHZ_PI4 750 + +// #define DELAY_VIA_PWM 0 +// #define DELAY_VIA_PCM 1 + +#define ROUNDUP(val, blksz) (((val) + ((blksz)-1)) & ~(blksz - 1)) + +#define BUS_TO_PHYS(x) ((x) & ~0xC0000000) + +using namespace wpp; + +namespace { + +// DmaHardware hardware{}; + +// L362 +static struct { + int handle; /* From mbox_open() */ + uint32_t size; /* Required size */ + unsigned mem_ref; /* From mem_alloc() */ + unsigned bus_addr; /* From mem_lock() */ + uint8_t *virt_addr; /* From mapmem() */ +} mbox; + +void set_servo(DmaChannel &ch, int servo, int width); + +// L375 +static void udelay(int us) { + struct timespec ts = {0, us * 1000}; + + nanosleep(&ts, NULL); +} + +// L384 +// void terminateChannel(DmaChannel &ch) { +// if (ch.dma_reg && mbox.virt_addr) { +// for (int i = 0; i < maxServoCount; i++) { +// if (ch.pins[i]) { +// set_servo(ch, i, 0); +// } +// } +// udelay(ch.cycle_time_us); +// ch.dma_reg[DMA_CS] = DMA_RESET; +// udelay(10); +// } +// // if (restore_gpio_modes) { +// // for (i = 0; i < MAX_SERVOS; i++) { +// // if (servo2gpio[i] != DMY) +// // gpio_set_mode(servo2gpio[i], gpiomode[i]); +// // } +// // } +// } + +void terminate(int dummy) { + if (DmaHardware::GetInstance().current_log_level >= LogLevel::Info) { + printf("terminate() %d\n", dummy); + } + for (auto &it : DmaHardware::GetInstance().channels) { + if (auto locked = it.lock()) { + locked->DeactivateChannel(); + } + } + + if (mbox.virt_addr != NULL) { + unmapmem(mbox.virt_addr, mbox.size); + mem_unlock(mbox.handle, mbox.mem_ref); + mem_free(mbox.handle, mbox.mem_ref); + if (mbox.handle >= 0) + mbox_close(mbox.handle); + } + + exit(1); +} + +// L480 +static uint32_t gpio_get_mode(DmaChannel &ch, uint32_t gpio) { + uint32_t fsel = ch.gpio_reg[GPIO_FSEL0 + gpio / 10]; + + return (fsel >> ((gpio % 10) * 3)) & 7; +} + +// L488 +static void gpio_set_mode(DmaChannel &ch, uint32_t gpio, uint32_t mode) { + uint32_t fsel = ch.gpio_reg[GPIO_FSEL0 + gpio / 10]; + + fsel &= ~(7 << ((gpio % 10) * 3)); + fsel |= mode << ((gpio % 10) * 3); + ch.gpio_reg[GPIO_FSEL0 + gpio / 10] = fsel; +} + +// L498 +static void gpio_set(DmaChannel &ch, int gpio, int level) { + if (level) + ch.gpio_reg[GPIO_SET0] = 1 << gpio; + else + ch.gpio_reg[GPIO_CLR0] = 1 << gpio; +} + +// L506 +static uint32_t mem_virt_to_phys(void *virt) { + uint32_t offset = (uint8_t *)virt - mbox.virt_addr; + + return mbox.bus_addr + offset; +} + +// L515 +static void *map_peripheral(uint32_t base, uint32_t len) { + int fd = open("/dev/mem", O_RDWR | O_SYNC); + void *vaddr; + + if (fd < 0) + fatal("rpio-pwm: Failed to open /dev/mem: %m\n"); + vaddr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, base); + if (vaddr == MAP_FAILED) + fatal("rpio-pwm: Failed to map peripheral at 0x%08x: %m\n", base); + close(fd); + + return vaddr; +} + +/* Carefully add or remove bits from the turnoff_mask such that regardless + * of where the DMA controller is in its cycle, and whether we are increasing + * or decreasing the pulse width, the generated pulse will only ever be the + * old width or the new width. If we don't take such care then there could be + * a cycle with some pulse width between the two requested ones. That doesn't + * really matter for servos, but when driving LEDs some odd intensity for one + * cycle can be noticeable. It may be that the servo output has been turned + * off via the inactivity timer, which is handled by always setting the turnon + * mask appropriately at the end of this function. + */ +// L556 +void set_servo(DmaChannel &ch, int servo, int newWidth) { + volatile uint32_t *dp; + int i; + uint32_t mask = 1 << ch.pins[servo]->gpioPinNum; + + int oldWidth = ch.pins[servo]->servowidth; + if (ch.hw.current_log_level >= LogLevel::Debug) { + printf("set_servo oldWidth=%d new=%d\n", oldWidth, newWidth); + } + + if (newWidth > oldWidth) { + dp = ch.turnoff_mask + ch.servostart[servo] + newWidth; + if (dp >= ch.turnoff_mask + ch.num_samples) + dp -= ch.num_samples; + + for (i = newWidth; i > oldWidth; i--) { + dp--; + if (dp < ch.turnoff_mask) + dp = ch.turnoff_mask + ch.num_samples - 1; + // printf("%5d, clearing at %p\n", dp - ctl->turnoff, dp); + *dp &= ~mask; + } + } else if (newWidth < oldWidth) { + dp = ch.turnoff_mask + ch.servostart[servo] + newWidth; + if (dp >= ch.turnoff_mask + ch.num_samples) + dp -= ch.num_samples; + + for (i = newWidth; i < oldWidth; i++) { + // printf("%5d, setting at %p\n", dp - ctl->turnoff, dp); + *dp++ |= mask; + if (dp >= ch.turnoff_mask + ch.num_samples) + dp = ch.turnoff_mask; + } + } + ch.pins[servo]->servowidth = newWidth; + if (newWidth == 0) { + ch.turnon_mask[servo] = 0; + } else { + ch.turnon_mask[servo] = mask; + } +} + +void set_mask_all(DmaChannel &ch, int servo) { + volatile uint32_t *dp; + uint32_t mask = 1 << ch.pins[servo]->gpioPinNum; + for (dp = ch.turnoff_mask; dp < ch.turnoff_mask + ch.num_samples;) { + *dp++ |= mask; + } +} + +void clear_mask_all(DmaChannel &ch, int servo) { + volatile uint32_t *dp; + uint32_t mask = 1 << ch.pins[servo]->gpioPinNum; + for (dp = ch.turnoff_mask; dp < ch.turnoff_mask + ch.num_samples;) { + *dp++ &= ~mask; + } +} + +// L596 +// static void setup_sighandlers(void) { +// int i; + +// // Catch all signals possible - it is vital we kill the DMA engine +// // on process exit! +// for (i = 0; i < 64; i++) { +// struct sigaction sa; + +// memset(&sa, 0, sizeof(sa)); +// sa.sa_handler = terminate; +// sigaction(i, &sa, NULL); +// } +// } + +// L612 +void init_ctrl_data(DmaHardware &hw, DmaChannel &ch) { + dma_cb_t *cbp = ch.cb_base; + uint32_t phys_fifo_addr, cbinfo; + uint32_t phys_gpclr0; + uint32_t phys_gpset0; + int curstart = 0; + uint32_t maskall = 0; + + if (ch.invert) { + phys_gpclr0 = GPIO_PHYS_BASE(hw) + 0x1c; + phys_gpset0 = GPIO_PHYS_BASE(hw) + 0x28; + } else { + phys_gpclr0 = GPIO_PHYS_BASE(hw) + 0x28; + phys_gpset0 = GPIO_PHYS_BASE(hw) + 0x1c; + } + + if (ch.delay_hw == DelayHardware::DELAY_VIA_PWM) { + phys_fifo_addr = PWM_PHYS_BASE(hw) + 0x18; + cbinfo = DMA_NO_WIDE_BURSTS | DMA_WAIT_RESP | DMA_D_DREQ | DMA_PER_MAP(5); + } else { + phys_fifo_addr = PCM_PHYS_BASE(hw) + 0x04; + cbinfo = DMA_NO_WIDE_BURSTS | DMA_WAIT_RESP | DMA_D_DREQ | DMA_PER_MAP(2); + } + + memset(ch.turnon_mask, 0, maxServoCount * sizeof(*(ch.turnon_mask))); + + // for (servo = 0 ; servo < MAX_SERVOS; servo++) { + // servowidth[servo] = 0; + // if (servo2gpio[servo] != DMY) { + // numservos++; + // maskall |= 1 << servo2gpio[servo]; + // } + // } + + for (int i = 0; i < ch.num_samples; i++) + ch.turnoff_mask[i] = maskall; + + for (uint32_t servo = 0; servo < ch.pins.size(); servo++) { + ch.servostart[servo] = curstart; + curstart += ch.num_samples / ch.pins.size(); + } + + for (int i = 0, servo = 0; i < ch.num_samples; i++) { + cbp->info = DMA_NO_WIDE_BURSTS | DMA_WAIT_RESP; + cbp->src = mem_virt_to_phys(ch.turnoff_mask + i); + cbp->dst = phys_gpclr0; + cbp->length = 4; + cbp->stride = 0; + cbp->next = mem_virt_to_phys(cbp + 1); + cbp++; + if (servo < maxServoCount && i == ch.servostart[servo]) { + cbp->info = DMA_NO_WIDE_BURSTS | DMA_WAIT_RESP; + cbp->src = mem_virt_to_phys(ch.turnon_mask + servo); + cbp->dst = phys_gpset0; + cbp->length = 4; + cbp->stride = 0; + cbp->next = mem_virt_to_phys(cbp + 1); + cbp++; + servo++; + } + // Delay + cbp->info = cbinfo; + cbp->src = mem_virt_to_phys(ch.turnoff_mask); // Any data will do + cbp->dst = phys_fifo_addr; + cbp->length = 4; + cbp->stride = 0; + cbp->next = mem_virt_to_phys(cbp + 1); + cbp++; + } + cbp--; + cbp->next = mem_virt_to_phys(ch.cb_base); +} + +// L695 +void init_hardware(DmaHardware &hw, DmaChannel &ch) { + if (ch.delay_hw == DelayHardware::DELAY_VIA_PWM) { + // Initialise PWM + ch.pwm_reg[PWM_CTL] = 0; + udelay(10); + ch.clk_reg[PWMCLK_CNTL] = + 0x5A000006; // Source=PLLD (500MHz or 750MHz on Pi4) + udelay(100); + ch.clk_reg[PWMCLK_DIV] = + 0x5A000000 | (hw.plldfreq_mhz << 12); // set pwm div to give 1MHz + udelay(100); + ch.clk_reg[PWMCLK_CNTL] = 0x5A000016; // Source=PLLD and enable + udelay(100); + ch.pwm_reg[PWM_RNG1] = ch.step_time_us; + udelay(10); + ch.pwm_reg[PWM_DMAC] = PWMDMAC_ENAB | PWMDMAC_THRSHLD; + udelay(10); + ch.pwm_reg[PWM_CTL] = PWMCTL_CLRF; + udelay(10); + ch.pwm_reg[PWM_CTL] = PWMCTL_USEF1 | PWMCTL_PWEN1; + udelay(10); + } else { + // Initialise PCM + ch.pcm_reg[PCM_CS_A] = 1; // Disable Rx+Tx, Enable PCM block + udelay(100); + ch.clk_reg[PCMCLK_CNTL] = + 0x5A000006; // Source=PLLD (500MHz or 750MHz on Pi4) + udelay(100); + ch.clk_reg[PCMCLK_DIV] = + 0x5A000000 | (hw.plldfreq_mhz << 12); // Set pcm div to give 1MHz + udelay(100); + ch.clk_reg[PCMCLK_CNTL] = 0x5A000016; // Source=PLLD and enable + udelay(100); + ch.pcm_reg[PCM_TXC_A] = + 0U << 31 | 1 << 30 | 0 << 20 | 0 << 16; // 1 channel, 8 bits + udelay(100); + ch.pcm_reg[PCM_MODE_A] = (ch.step_time_us - 1) << 10; + udelay(100); + ch.pcm_reg[PCM_CS_A] |= 1 << 4 | 1 << 3; // Clear FIFOs + udelay(100); + ch.pcm_reg[PCM_DREQ_A] = + 64 << 24 | 64 << 8; // DMA Req when one slot is free? + udelay(100); + ch.pcm_reg[PCM_CS_A] |= 1 << 9; // Enable DMA + udelay(100); + } + + // Initialise the DMA + ch.dma_reg[DMA_CS] = DMA_RESET; + udelay(10); + ch.dma_reg[DMA_CS] = DMA_INT | DMA_END; + ch.dma_reg[DMA_CONBLK_AD] = mem_virt_to_phys(ch.cb_base); + ch.dma_reg[DMA_DEBUG] = 7; // clear debug error flags + ch.dma_reg[DMA_CS] = + 0x10880001; // go, mid priority, wait for outstanding writes + + if (ch.delay_hw == DelayHardware::DELAY_VIA_PCM) { + ch.pcm_reg[PCM_CS_A] |= 1 << 2; // Enable Tx + } +} + +/* Determining the board revision is a lot more complicated than it should be + * (see comments in wiringPi for details). We will just look at the last two + * digits of the Revision string and treat '00' and '01' as errors, '02' and + * '03' as rev 1, and any other hex value as rev 2. 'Pi1 and Pi2 are + * differentiated by the Hardware being BCM2708 or BCM2709. + * + * NOTE: These days we should just use bcm_host_get_model_type(). + */ +// L945 +void get_model_and_revision(DmaHardware &hw) { + char buf[128], revstr[128], modelstr[128]; + char *ptr, *end, *res; + int board_revision; + FILE *fp; + + revstr[0] = modelstr[0] = '\0'; + + fp = fopen("/proc/cpuinfo", "r"); + + if (!fp) + fatal("Unable to open /proc/cpuinfo: %m\n"); + + while ((res = fgets(buf, 128, fp))) { + if (!strncasecmp("hardware", buf, 8)) + memcpy(modelstr, buf, 128); + else if (!strncasecmp(buf, "revision", 8)) + memcpy(revstr, buf, 128); + } + fclose(fp); + + if (modelstr[0] == '\0') + fatal("rpio-pwm: No 'Hardware' record in /proc/cpuinfo\n"); + if (revstr[0] == '\0') + fatal("rpio-pwm: No 'Revision' record in /proc/cpuinfo\n"); + + if (strstr(modelstr, "BCM2708")) + hw.board_model = 1; + else if (strstr(modelstr, "BCM2709") || strstr(modelstr, "BCM2835") || strstr(modelstr, "BCM2711")) + hw.board_model = 2; + else + fatal("rpio-pwm: Cannot parse the hardware name string\n"); + + /* Revisions documented at http://elinux.org/RPi_HardwareHistory */ + ptr = revstr + strlen(revstr) - 3; + board_revision = strtol(ptr, &end, 16); + if (end != ptr + 2) + fatal("rpio-pwm: Failed to parse Revision string\n"); + if (board_revision < 1) + fatal("rpio-pwm: Invalid board Revision\n"); + else if (board_revision < 4) + hw.gpio_cfg = 1; + else if (board_revision < 16) + hw.gpio_cfg = 2; + else + hw.gpio_cfg = 3; + + if (bcm_host_is_model_pi4() || strstr(modelstr, "BCM2711") ) { + hw.plldfreq_mhz = PLLDFREQ_MHZ_PI4; + hw.host_is_model_pi4 = true; + // hw.dma_chan = DMA_CHAN_PI4; + } else { + hw.plldfreq_mhz = PLLDFREQ_MHZ_DEFAULT; + hw.host_is_model_pi4 = false; + // hw.dma_chan = DMA_CHAN_DEFAULT; + } + + hw.periph_virt_base = bcm_host_get_peripheral_address(); + hw.dram_phys_base = bcm_host_get_sdram_address(); + hw.periph_phys_base = 0x7e000000; + + /* + * See https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface + * + * 1: MEM_FLAG_DISCARDABLE = 1 << 0 // can be resized to 0 at any time. Use + * for cached data + * MEM_FLAG_NORMAL = 0 << 2 // normal allocating alias. Don't + * use from ARM 4: MEM_FLAG_DIRECT = 1 << 2 // 0xC alias uncached 8: + * MEM_FLAG_COHERENT = 2 << 2 // 0x8 alias. Non-allocating in L2 but coherent + * MEM_FLAG_L1_NONALLOCATING = // Allocating in L2 + * (MEM_FLAG_DIRECT | MEM_FLAG_COHERENT) + * 16: MEM_FLAG_ZERO = 1 << 4 // initialise buffer to all zeros + * 32: MEM_FLAG_NO_INIT = 1 << 5 // don't initialise (default is + * initialise to all ones 64: MEM_FLAG_HINT_PERMALOCK = 1 << 6 // + * Likely to be locked for long periods of time + * + */ + if (hw.board_model == 1) { + hw.mem_flag = 0x0c; /* MEM_FLAG_DIRECT | MEM_FLAG_COHERENT */ + } else { + hw.mem_flag = 0x04; /* MEM_FLAG_DIRECT */ + } +} + +// L1184 main() +bool setup_hardware(DmaHardware &hw) { + get_model_and_revision(hw); + + // init_idle_timers(hw); + // setup_sighandlers(); + + return true; +} + +} // anonymous namespace + +namespace wpp { + +// L416 +void fatal(const char *fmt, ...) { + printf("fatal() %s\n", fmt); + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + terminate(0); +} + +//************************** DmaHardware **************************** +// static +DmaHardware &DmaHardware::GetInstance() { + static DmaHardware hardware{}; + static bool inited = false; + if (!inited) { + inited = setup_hardware(hardware); + } + return hardware; +} + +//************************** DmaChannel **************************** +// static +std::shared_ptr +DmaChannel::CreateInstance(const DmaChannelConfig &config) { + auto &hw = DmaHardware::GetInstance(); + auto ch = std::make_shared(hw, config); + ch->Init(); + DmaHardware::GetInstance().channels.push_back(ch); + return ch; +} + +DmaChannel::DmaChannel(DmaHardware &hw, const DmaChannelConfig &config) + : hw{hw}, delay_hw{config.delay_hw}, chNum{config.chNum}, + cycle_time_us{config.cycleTimeUs}, + step_time_us{config.stepTimeUs}, invert{config.invert} { + if (step_time_us < 2 || step_time_us > 1000) { + fatal("Invalid step-size specified"); + } + if (cycle_time_us < 1000 || cycle_time_us > 1000000) { + fatal("Invalid cycle-time specified"); + } + if (cycle_time_us % step_time_us) { + fatal("cycle-time is not a multiple of step-size"); + } + if (cycle_time_us / step_time_us < 100) { + fatal("cycle-time must be at least 100 * step-size"); + } +} + +void DmaChannel::Init() { + num_samples = cycle_time_us / step_time_us; + num_cbs = num_samples * 2 + maxServoCount; + num_pages = (num_cbs * sizeof(dma_cb_t) + num_samples * 4 + + maxServoCount * 4 + PAGE_SIZE - 1) >> + PAGE_SHIFT; + + auto &ch = *this; + ch.dma_reg = + static_cast(map_peripheral(DMA_VIRT_BASE(hw), DMA_LEN)); + ch.dma_reg += ch.chNum * DMA_CHAN_SIZE / sizeof(uint32_t); + ch.pwm_reg = + static_cast(map_peripheral(PWM_VIRT_BASE(hw), PWM_LEN)); + ch.pcm_reg = + static_cast(map_peripheral(PCM_VIRT_BASE(hw), PCM_LEN)); + ch.clk_reg = + static_cast(map_peripheral(CLK_VIRT_BASE(hw), CLK_LEN)); + ch.gpio_reg = + static_cast(map_peripheral(GPIO_VIRT_BASE(hw), GPIO_LEN)); + /* Use the mailbox interface to the VC to ask for physical memory */ + // Use the mailbox interface to request memory from the VideoCore + // We specifiy (-1) for the handle rather than calling mbox_open() + // so multiple users can share the resource. + mbox.handle = -1; // mbox_open(); + mbox.size = ch.num_pages * 4096; + mbox.mem_ref = mem_alloc(mbox.handle, mbox.size, 4096, hw.mem_flag); + if (mbox.mem_ref == 0) { + fatal("Failed to alloc memory from VideoCore\n"); + } + mbox.bus_addr = mem_lock(mbox.handle, mbox.mem_ref); + if (mbox.bus_addr == ~0U) { + mem_free(mbox.handle, mbox.size); + fatal("Failed to lock memory\n"); + } + mbox.virt_addr = + static_cast(mapmem(BUS_TO_PHYS(mbox.bus_addr), mbox.size)); + + ch.turnoff_mask = (uint32_t *)mbox.virt_addr; + ch.turnon_mask = + (uint32_t *)(mbox.virt_addr + ch.num_samples * sizeof(uint32_t)); + ch.cb_base = + (dma_cb_t *)(mbox.virt_addr + ROUNDUP(ch.num_samples + maxServoCount, 8) * + sizeof(uint32_t)); + + init_ctrl_data(hw, ch); + init_hardware(hw, ch); + ch.isActive = true; + if (hw.current_log_level >= LogLevel::Info) { + printf("DmaChannel::Init() ch=%d, cycle_time_us=%d, step_time_us=%d, " + "num_samples=%d\n", + chNum, cycle_time_us, step_time_us, num_samples); + } +} + +void DmaChannel::DeactivateChannel() { + auto &ch = *this; + if (!ch.IsActive()) + return; + if (hw.current_log_level >= LogLevel::Info) { + printf("DmaChannel::DeactivateChannel() ch=%d\n", ch.chNum); + } + ch.isActive = false; + + for (int i = 0; i < maxServoCount; i++) { + if (ch.pins[i]) { + ch.pins[i]->DeactivatePin(); + } + } + udelay(ch.cycle_time_us); + ch.dma_reg[DMA_CS] = DMA_RESET; + udelay(10); +} + +std::shared_ptr +DmaChannel::CreatePin(const DmaPwmPinConfig &pinConfig) { + auto pin = std::make_shared(this->shared_from_this(), pinConfig); + + // find next available slot in pins + int servo = 0; + while (servo < maxServoCount && pins[servo] != nullptr) { + servo++; + } + if (servo == maxServoCount) { + fatal("run out of availabel slots"); + } + pins[servo] = pin; + pin->Init(servo); + set_mask_all(*this, servo); + set_servo(*this, servo, pinConfig.widthInSteps); + + return pin; +} + +//************************** PwmPin **************************** +PwmPin::PwmPin(std::shared_ptr dmaChannel, + const DmaPwmPinConfig &pinConfig) + : ch{dmaChannel}, gpioPinNum{pinConfig.gpioPinNum}, + restoreOnExit{pinConfig.restoreOnExit} { + // +} + +void PwmPin::Init(int slotIndex) { + this->slotIndex = slotIndex; + this->gpiomode = gpio_get_mode(*ch, gpioPinNum); + gpio_set(*ch, gpioPinNum, ch->invert ? 1 : 0); + gpio_set_mode(*ch, gpioPinNum, GPIO_MODE_OUT); +} + +void PwmPin::SetByWidth(const int width) { + if (width < 0 || width > ch->num_samples) { + fatal("width out of range"); + } + set_servo(*ch, slotIndex, width); +} + +void PwmPin::SetByPercentage(const float pct) { + if (slotIndex < 0) { + fatal("already deactivated?"); + } + if (pct < 0.0f || pct > 100.0f) { + fatal("pct out of range"); + } + int newWidth = static_cast(pct * ch->num_samples / 100.0f); + set_servo(*ch, slotIndex, newWidth); +} + +void PwmPin::SetByActiveTimeUs(const int timeInUs) { + if (slotIndex < 0) { + fatal("already deactivated?"); + } + if (timeInUs < 0 || timeInUs > ch->cycle_time_us) { + fatal("timeInUs out of range"); + } + int newWidth = timeInUs / ch->step_time_us; + set_servo(*ch, slotIndex, newWidth); +} + +void PwmPin::DeactivatePin() { + if (slotIndex < 0) { + // already deactivated? + return; + } + // to avoid destruct before exit scope + std::shared_ptr self = shared_from_this(); + set_servo(*ch, slotIndex, 0 /*newWidth*/); + clear_mask_all(*ch, slotIndex); + ch->pins[slotIndex] = nullptr; + slotIndex = -1; +} + +//************************** TestDma **************************** +void TestDma() { + // setup_hardware(hardware); + // auto ch = DmaChannel::CreateInstance(14, 20000,10); + std::cout << "TestDma"; +} + +} // namespace wpp \ No newline at end of file diff --git a/src/gpio/dma.hpp b/src/gpio/dma.hpp new file mode 100644 index 0000000..b42b836 --- /dev/null +++ b/src/gpio/dma.hpp @@ -0,0 +1,180 @@ +#include +#include + +namespace wpp { + +const int maxServoCount = 12; // max to 32 + +enum class DelayHardware { DELAY_VIA_PWM = 0, DELAY_VIA_PCM = 1 }; + +class DmaChannel; +class PwmPin; + +void fatal(const char *fmt, ...); + +typedef struct { + uint32_t info, src, dst, length, stride, next, pad[2]; +} dma_cb_t; + +// need keep sync with index.js +enum class LogLevel { + Fatal = 0, + Error = 1, + Warning = 2, + Info = 3, + Debug = 4, +}; + +//************************** DmaHardware **************************** +struct DmaHardware { + // struct timeval *servo_kill_time; // for idle_timeout feature. + + uint32_t plldfreq_mhz; + // int dma_chan; + // int idle_timeout; + // int servo_min_ticks; + // int servo_max_ticks; + + int board_model; + int gpio_cfg; + + // init by get_model_and_revision() at init time (detect hardware) + uint32_t periph_phys_base; + uint32_t periph_virt_base; + uint32_t dram_phys_base; + uint32_t mem_flag; + + bool host_is_model_pi4{false}; + + std::vector> channels{}; + + LogLevel current_log_level {LogLevel::Info}; + static DmaHardware &GetInstance(); +}; + +//************************** DmaChannel **************************** +struct DmaChannelConfig { + DelayHardware delay_hw = DelayHardware::DELAY_VIA_PWM; + int chNum = 14; // default 14 (for pi2/3/zero), suggest use 7 for pi4 + int cycleTimeUs = 20000; // 20ms cycle + int stepTimeUs = 10; // 10us each step + bool invert = false; // default HIGH active +}; + +struct DmaPwmPinConfig { + int gpioPinNum = 21; + int widthInSteps = 0; + bool restoreOnExit = true; // restore gpio mode when exit +}; + +class DmaChannel : public std::enable_shared_from_this { +public: + // for Pi2/3 ch can use 14 or 13 etc. + // for Pi4 suggest use 7. + static std::shared_ptr + CreateInstance(const DmaChannelConfig &config); + +public: + DmaChannel(DmaHardware &hw, const DmaChannelConfig &config); + + DmaChannel(DmaChannel const &) = delete; + DmaChannel &operator=(DmaChannel const &) = delete; + +public: + // gpioPinNum (for example gpio_21 = P1_40 = wiringPi_29) + std::shared_ptr CreatePin(const DmaPwmPinConfig &pinConfig); + +public: + void Init(); + +public: + void DeactivateChannel(); + + inline bool IsActive() { return isActive; } + inline void ThrowIfNotActive() { + if (!IsActive()) { + fatal("not active"); + } + } + +public: + DmaHardware &hw; + const DelayHardware delay_hw; + const int chNum; + + // cycle_time_us is the pulse cycle time per servo, in microseconds. + // Typically it should be 20ms, or 20000us. + + // step_time_us is the pulse width increment granularity, again in + // microseconds. Setting step_time_us too low will likely cause problems as + // the DMA controller will use too much memory bandwidth. 10us is a good + // value, though you might be ok setting it as low as 2us. + + const int cycle_time_us; + const int step_time_us; + bool invert{false}; + // bool restore_gpio_modes{true}; + + volatile uint32_t *pwm_reg{}; + volatile uint32_t *pcm_reg{}; + volatile uint32_t *clk_reg{}; + volatile uint32_t *dma_reg{}; + volatile uint32_t *gpio_reg{}; + + int num_samples; + int num_cbs; + int num_pages; + uint32_t *turnoff_mask; + uint32_t *turnon_mask; + dma_cb_t *cb_base; + bool isActive{false}; + +public: + std::vector> pins = + std::vector>(maxServoCount); + std::vector servostart = std::vector(maxServoCount); +}; + +//************************** PwmPin **************************** +class PwmPin : public std::enable_shared_from_this { +public: + PwmPin(std::shared_ptr dmaChannel, + const DmaPwmPinConfig &pinConfig); + + PwmPin(PwmPin const &) = delete; + PwmPin &operator=(PwmPin const &) = delete; + +public: + inline bool IsActive() { return slotIndex >= 0; } + inline void ThrowIfNotActive() { + if (!IsActive()) { + fatal("not active"); + } + } + +public: + void SetByWidth(const int width); + + void SetByPercentage(const float pct); + + void SetByActiveTimeUs(const int timeInUs); + + void DeactivatePin(); + +public: + void Init(int slotIndex); + +public: + std::shared_ptr ch; + const int gpioPinNum; + uint32_t gpiomode; // when we exit, we can restore privious mode for this pin. + +public: + int slotIndex{-1}; // index in array ch.pins (start with 0) + int servowidth{0}; + bool restoreOnExit{true}; +}; + +void TestDma(); + +} // namespace wpp diff --git a/src/gpio/gpio.cpp b/src/gpio/gpio.cpp index ef7203a..ed36fd1 100644 --- a/src/gpio/gpio.cpp +++ b/src/gpio/gpio.cpp @@ -1,458 +1,472 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "gpio.hpp" -#include "../log/log.hpp" -#include - - -#define GPIO_0_2_R1 0 /*!< \def Gpio pin 0/2 (rev1/rev2) with rev2 board code */ -#define GPIO_1_3_R1 1 /*!< \def Gpio pin 1/3 (rev1/rev2) with rev2 board code */ -#define GPIO_21_27_R1 21 /*!< \def Gpio pin 21/27 (rev1/rev2) with rev2 board code */ - -#define RDBUF_LEN 10 // length of read buffer -#define POLL_TIMEOUT 100 // timeout for polling function in ms (also the maximum delay time before thread is stopped - - -#define FALSE 0 -#define TRUE 1 - -using namespace std; - -/**************************** -* * -* PRIVATE DEFINTIONS * -* * -*****************************/ - -static unsigned int HardwareRevision(void); - -/**************************** -* * -* IOPIN OBJECT FUNCS * -* * -*****************************/ - -//! Create new IOPin object -GpioPin::GpioPin(int gpiopin, GpioDirection direction, GpioEdge edge) -{ - int result; - int pin_id; - char fTemp[GPIO_FN_MAXLEN]; - - // Set tag to empty pointer - Tag = NULL; - - pin_id = verifyPin(gpiopin); - if(pin_id < 0) - throw OperationFailedException("Gpio pin %d is not a valid Gpio for this Raspberry Pi board revision",gpiopin); - - // ensure that the Gpio pin is exported - try - { - pinPreExported = !(exportPin(pin_id)); - } - catch(OperationFailedException x) - { - throw x; - } - - // Prepare the iopin object - pin = pin_id; - - // Prepare the file names for the different files - snprintf(fTemp, GPIO_FN_MAXLEN-1, "/sys/class/gpio/gpio%d/direction", pin_id); - fnDirection = std::string(fTemp); - snprintf(fTemp, GPIO_FN_MAXLEN-1, "/sys/class/gpio/gpio%d/edge", pin_id); - fnEdge = std::string(fTemp); - snprintf(fTemp, GPIO_FN_MAXLEN-1, "/sys/class/gpio/gpio%d/value", pin_id); - fnValue = std::string(fTemp); - - // Initialize callbacks to NULL - - try - { - // set initial direction or die trying - setDirection(direction); - // set initial edge or die trying - setEdge(edge); - } - catch(OperationFailedException x) - { - if(!pinPreExported) - unexportPin(pin); - throw x; - } -} - - -//! Close the IOPin connection -GpioPin::~GpioPin() -{ - if(!pinPreExported) - unexportPin(pin); -} - -//! Get the actual used pin number of the IO Pin -int GpioPin::getPinNr() -{ - return pin; -} - -//! Get current direction of pin -GpioDirection GpioPin::getDirection() -{ - std::string s = readFile(fnDirection); - // got enough info in the first byte - if(s[0] == 'i') - return kDirectionIn; - else - return kDirectionOut; -} - -//! Set new value of pin -void GpioPin::setDirection(GpioDirection direction) -{ - if (direction == kDirectionIn) writeFile(fnDirection,"in\n"); - else if (direction == kDirectionOut) writeFile(fnDirection,"out\n"); -} - -//! Get current edge detection type -GpioEdge GpioPin::getEdge() -{ - std::string s = readFile(fnEdge); - switch(s[0]) // as the first letters of each result are all different - { - default : - case 'n': - case 'N': - return kEdgeNone; - case 'r': - case 'R': - return kEdgeRising; - case 'f': - case 'F': - return kEdgeFalling; - case 'b': - case 'B': - return kEdgeBoth; - - } -} - -//! Set edge detection type -void GpioPin::setEdge(GpioEdge edge) -{ - if (edge == kEdgeNone) writeFile(fnEdge,"none\n"); - else if (edge == kEdgeRising) writeFile(fnEdge,"rising\n"); - else if (edge == kEdgeFalling) writeFile(fnEdge,"falling\n"); - else if (edge == kEdgeBoth) writeFile(fnEdge,"both\n"); -} - - -//! Get current value of pin -bool GpioPin::getValue() -{ - std::string s = readFile(fnValue); - // got enough info in the first byte - if(s[0] == '1') - return true; - else - return false; -} - -//! Set new value of pin -void GpioPin::setValue(bool value) -{ - if (value) writeFile(fnValue,"1\n"); - else writeFile(fnValue,"0\n"); -} - - - -/**************************** -* * -* INTERRUPT FUNCS * -* * -*****************************/ - -void GpioPin::InterruptStart() -{ - if(!ThreadRunning()) - { - this->ThreadStart(); - } -} - -void GpioPin::InterruptStop() -{ - if(ThreadRunning()) - { - this->ThreadStop(); - } -} - - -void GpioPin::ThreadFunc() -{ - int fd,ret; - struct pollfd pfd; - char rdbuf[RDBUF_LEN]; - - memset(rdbuf, 0x00, RDBUF_LEN); - - fd=open(fnValue.c_str(), O_RDONLY); - if(fd<0) - throw OperationFailedException("Could not open file %s for reading: [%d] %s",fnValue.c_str(), errno, strerror(errno)); - - pfd.fd=fd; - pfd.events=POLLPRI; - - ret=read(fd, rdbuf, RDBUF_LEN-1); - if(ret<0) - { - close(fd); - throw OperationFailedException("Could not read from %s: [%d] %s",fnValue.c_str(), errno, strerror(errno)); - } - - while(ThreadRunning()) - { - memset(rdbuf, 0x00, RDBUF_LEN); - lseek(fd, 0, SEEK_SET); - ret=poll(&pfd, 1, POLL_TIMEOUT); - if(ret<0) // negative result is error - { - close(fd); - throw OperationFailedException("Could not poll %s: [%d] %s",fnValue.c_str(), errno, strerror(errno)); - } - - if(ret==0) - continue; // 0 bytes read is timeout, we should retry read - // ok, poll succeesed, now we read the value - ret=read(fd, rdbuf, RDBUF_LEN-1); - if(ret<0) - { - close(fd); - throw OperationFailedException("Could not read from %s: [%d] %s",fnValue.c_str(), errno, strerror(errno)); - } - - // Kill the loop now if the thread stopped during our poll - if(!ThreadRunning()) - break; - // Continue with doing the callback, if we're still enabled. - // Now, rdbuf[0] contains 0 or 1 depending on the trigger - onInterrupt(this, kEdgeFalling, !(rdbuf[0] == '0')); - } - close(fd); - -} - - - - -/**************************** -* * -* SUPPORT FUNCTIONS * -* * -*****************************/ - -//! open a file for writing and write text to it -void GpioPin::writeFile(std::string &fname, std::string &value) -{ - writeFile(fname,value.c_str()); -} - -void GpioPin::writeFile(std::string &fname, const char *value) -{ - FILE *fd; - if ((fd = fopen (fname.c_str(), "w")) == NULL) - throw OperationFailedException("Could not open %s for writing",fname.c_str()); - - fprintf (fd, value); - fclose(fd); -} - - - -//! open a file for reading and read some text from it -/*! - function will throw an exception on empty string, since the files we use it on - will always return a value. If they don't we have serious problems -*/ -std::string GpioPin::readFile(std::string &fname) -{ - FILE *fd; - char rdbuf[RDBUF_LEN]; - int ret; - - if ((fd = fopen (fname.c_str(), "r")) == NULL) - throw OperationFailedException("Could not open %s for reading",fname.c_str()); - - ret = fread(rdbuf,1,RDBUF_LEN -1, fd); - fclose(fd); - - if(ret<0) - { - throw OperationFailedException("Error reading from %s: [%d] %s",fname.c_str(), errno, strerror(errno)); - } - else if(ret == 0) - { - throw OperationFailedException("Got empty string reading from %s: [%d] %s",fname.c_str(), errno, strerror(errno)); - } - - rdbuf[ret] = '\0'; // Ensure null termination - - return std::string(rdbuf); -} - - -//! Verifies gpio pin number, and translates pin numbers (REV2) to the proper REV1 or REV2 board gpio pin numbers -/*! - \param gpiopin The pin number to verify - \return verified and translated gpio pin, or -1 if invalid -*/ -int GpioPin::verifyPin(int gpiopin) -{ - // List of valid Gpio pins - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 - int validpinsRev1[17] = { 0, 1, 4, 7, 8, 9,10,11,14,15,17,18,21,22,23,24,25}; - int validpinsRev2[21] = { 2, 3, 4, 7, 8, 9,10,11,14,15,17,18,22,23,24,25,27,28,29,30,31}; - unsigned int i; - - // get hardware revision - unsigned int rev = HardwareRevision(); - if (rev < 4) - { // REV 1 BOARD - - // Translate pins to rev 1 equivalent - if(gpiopin == GPIO_0_2) - gpiopin = GPIO_0_2_R1; - else if(gpiopin == GPIO_1_3) - gpiopin = GPIO_1_3_R1; - else if(gpiopin == GPIO_21_27) - gpiopin = GPIO_21_27_R1; - - // Verify that the pin number is valid, otherwise return -1 - for(i=0; i +#include +#include + +using namespace std; +using namespace wpp; + +/******************************** + * * + * Internal singleton class * + * to ensure proper teardown * + * of dma channel * + * * + ********************************/ + + +class DmaPwmGenerator +{ +private: + DmaPwmGenerator() + { + int ch = (DmaHardware::GetInstance().host_is_model_pi4)?7:14; + clog << LOG_DEBUG << endl << " -- Creating DmaPwmGenerator using channel " << ch << " --" << endl; + + DmaChannelConfig config{}; + config.chNum = ch; + // cycle_time_us: typical value 10240=10.24ms each cycle + config.cycleTimeUs = 10240; + // step_time_us: typical value 10=10us each step + // (total steps = 10240/5=2048 steps) + config.stepTimeUs = 5; + // We will only use DELAY_VIA_PWM, since PCM is in use by the audio chip + config.delay_hw = DelayHardware::DELAY_VIA_PWM; + // invert: don't invert high/low output + config.invert = false; + + auto channel = DmaChannel::CreateInstance(config); + this->channel = channel; + + } + + std::shared_ptr channel; + std::unordered_map> pins; + +public: + // delete copy constructor and assignmen operator to prevent accidentally creating instance doubles + DmaPwmGenerator(DmaPwmGenerator const&) = delete; + void operator=(DmaPwmGenerator const&) = delete; + + + static DmaPwmGenerator& Instance() + { + static DmaPwmGenerator instance; + return instance; + }; + + ~DmaPwmGenerator() + { + this->channel->DeactivateChannel(); + clog << LOG_DEBUG << " -- DmaPwmGenerator destroyed -- " << endl; + } + + // initialize pin and set default puse width in steps + bool RegisterPin(uint8_t gpio, uint32_t width = 0) + { + if (this->pins.find(gpio) != this->pins.end()) { + return false; + } + DmaPwmPinConfig config{}; + config.gpioPinNum = gpio; + config.widthInSteps = width; + auto pin = channel->CreatePin(config); + pins[gpio] = pin; + return true; + } + + // unregister pin from pwm + bool UnregisterPin(int gpio) { + auto pin = this->pins.find(gpio); + if (pin == this->pins.end()) { + // pin don't exist? + return false; + } + pin->second->DeactivatePin(); + pins.erase(pin); + return true; + } + + // Change pulse width in steps + bool SetWidth(uint8_t gpio, uint32_t width) + { + auto pin = pins.find(gpio); + if (pin == pins.end()) { + // pin don't exist? + return false; + } + pin->second->SetByWidth(width); + return true; + } + +}; + +/************************ + * * + * GpioBase functions * + * * + ************************/ + + +GpioBase::GpioBase() +{ + this->gpioChip.open("gpiochip0",gpiod::chip::OPEN_BY_NAME); +} + +GpioBase::~GpioBase() +{ + +} + +gpiod::line_request GpioBase::init_linerq(GpioDirection dir, GpioEdge edge, GpioPullup pu, GpioOutput op, bool active_low) +{ + // find process name from /proc file system + std::ifstream comm("/proc/self/comm"); + std::string name; + getline(comm, name); + + // setup line request with process name as consumer name + gpiod::line_request rq; + rq.consumer = name; + + // determine the request type from requested Direction and Edge + rq.request_type = gpiod::line_request::DIRECTION_AS_IS; + if(dir == GpioDirection::Output || dir == GpioDirection::PwmOutput) { + rq.request_type = gpiod::line_request::DIRECTION_OUTPUT; + } + else if(edge == GpioEdge::Both) { + rq.request_type = gpiod::line_request::EVENT_BOTH_EDGES; + } + else if (edge == GpioEdge::Rising) { + rq.request_type = gpiod::line_request::EVENT_RISING_EDGE; + } + else if (edge == GpioEdge::Falling) { + rq.request_type = gpiod::line_request::EVENT_FALLING_EDGE; + } + else //if (edge == GpioEdge::None) + { + rq.request_type = gpiod::line_request::DIRECTION_INPUT; + } + + rq.flags = 0; + // Determine flags from the other + if(dir == GpioDirection::Output) + { + if(op == GpioOutput::OpenDrain){ + rq.flags |= ::gpiod::line_request::FLAG_OPEN_DRAIN; + } + else if(op == GpioOutput::OpenSource){ + rq.flags |= ::gpiod::line_request::FLAG_OPEN_SOURCE; + } + } + else // if(dir = GpioDirection::Input) + { + // next lines require libgpiod 1.6.2 + + if(pu == GpioPullup::PullUp){ + // rq.flags |= ::gpiod::line_request::FLAG_BIAS_PULL_UP; + } + else if(pu == GpioPullup::PullDown){ + // rq.flags |= ::gpiod::line_request::FLAG_BIAS_PULL_DOWN; + } + } + + if(active_low){ + rq.flags |= ::gpiod::line_request::FLAG_ACTIVE_LOW; + } + + return rq; +} + +void GpioBase::PinMode(GpioDirection dir, GpioOutput op, bool active_low) +{ + this->PinMode(dir,GpioPullup::None,op, active_low); +} +void GpioBase::PinMode(GpioDirection dir, GpioPullup pu, bool active_low) +{ + this->PinMode(dir,pu,GpioOutput::Both, active_low); +} + +void GpioBase::PinMode(GpioDirection dir, bool active_low) +{ + this->PinMode(dir,GpioPullup::None,GpioOutput::Both, active_low); +} + +void GpioBase::Listen(GpioEdge edge, bool active_low) +{ + this->Listen(edge, GpioPullup::None, active_low); +} + +/************************ + * * + * GpioPin functions * + * * + ************************/ + +GpioPin::GpioPin(uint8_t gpio) +{ + this->line = this->gpioChip.get_line(gpio); +} + +GpioPin::~GpioPin() +{ + if(this->dir == GpioDirection::PwmOutput) + { + DmaPwmGenerator::Instance().UnregisterPin(this->line.offset()); + } + this->line.release(); + +} + +void GpioPin::DigitalWrite(bool value) +{ + if(this->line.is_requested() && this->line.direction() == gpiod::line::DIRECTION_OUTPUT){ + this->line.set_value(value?1:0); + } +} + +bool GpioPin::DigitalRead() +{ + if(this->line.is_requested()){ + return (bool)(this->line.get_value()); + } + else + { + return false; // fallback + } +} + +bool GpioPin::IsAvailable(){ + return !(this->line.is_used() && !this->line.is_requested()); +} + +void GpioPin::PinMode(GpioDirection dir, GpioPullup pu, GpioOutput op, bool active_low) +{ + if(this->IsAvailable()) + { + this->line.release(); + gpiod::line_request cfg = this->init_linerq(dir,GpioEdge::None,pu,op, active_low); + this->line.request(cfg); + this->dir = dir; // store directionality + + if(dir == GpioDirection::PwmOutput) + { + DmaPwmGenerator::Instance().RegisterPin(this->line.offset()); + } + else + { + DmaPwmGenerator::Instance().UnregisterPin(this->line.offset()); + } + } +} + +void GpioPin::PwmWrite(uint32_t width) +{ + // only do this if the pin was set to PwmOutput + if(this->dir == GpioDirection::PwmOutput) + { + DmaPwmGenerator::Instance().SetWidth(this->line.offset(),width); + } +} + +void GpioPin::Listen(GpioEdge edge, GpioPullup pu, bool active_low) +{ + if(this->IsAvailable()) + { + this->line.release(); + gpiod::line_request cfg = this->init_linerq(GpioDirection::Input,edge,pu,GpioOutput::Both, active_low); + this->line.request(cfg); + + this->ThreadStart(); + + } +} + +void GpioPin::ThreadLoop() +{ + // wait 20 ms for an event + // if it happens, process, otherwise wait another 20 ms + bool event = this->line.event_wait(std::chrono::milliseconds(20)); + if(event) + { + gpiod::line_event evt = this->line.event_read(); + if(evt.event_type == gpiod::line_event::RISING_EDGE) + { + this->onChange(evt.source.offset(),GpioEdge::Rising,true); + } + else //if(evt.event_type == gpiod::line_event::FALLING_EDGE) + { + this->onChange(evt.source.offset(),GpioEdge::Falling,false); + } + } +} + +/************************ + * * + * GpioPins functions * + * * + ************************/ + +GpioPins::GpioPins(std::vector gpios) +{ + std::vector pins; + for (std::vector::iterator it = gpios.begin() ; it != gpios.end(); ++it) + { + pins.push_back((unsigned int)(*it)); + } + + this->lines = this->gpioChip.get_lines(pins); +} + +GpioPins::~GpioPins() +{ + if(this->dir == GpioDirection::PwmOutput) + { + for(auto& line : this->lines) + { + DmaPwmGenerator::Instance().UnregisterPin(line.offset()); + } + } + + this->lines.release(); + +} + +void GpioPins::DigitalWrite(std::vector values) +{ + std::vector vs; + for (std::vector::iterator it = values.begin() ; it != values.end(); ++it) + { + vs.push_back((*it)?1:0); + } + + this->lines.set_values(vs); +} + +std::vector GpioPins::DigitalRead() +{ + std::vector vs = this->lines.get_values(); + std::vector values; + for (std::vector::iterator it = vs.begin() ; it != vs.end(); ++it) + { + values.push_back((*it)?true:false); + } + + return values; + +} + +void GpioPins::PwmWrite(std::vector widths) +{ + int index = 0; + for (uint32_t width: widths) + { + // + if(index < this->lines.size()) + { + auto& line = this->lines.get(index); + DmaPwmGenerator::Instance().SetWidth(line.offset(),width); + } + index++; + } +} + + +void GpioPins::PinMode(GpioDirection dir, GpioPullup pu, GpioOutput op, bool active_low) +{ + this->lines.release(); + gpiod::line_request cfg = this->init_linerq(dir,GpioEdge::None,pu,op, active_low); + this->lines.request(cfg); + this->dir = dir; // store directionality + + if(dir == GpioDirection::PwmOutput) + { + for(auto& line : this->lines) + { + DmaPwmGenerator::Instance().RegisterPin(line.offset(),0); + } + } + else + { + for(auto& line : this->lines) + { + DmaPwmGenerator::Instance().UnregisterPin(line.offset()); + } + } + +} + + +void GpioPins::Listen(GpioEdge edge, GpioPullup pu, bool active_low) +{ + this->lines.release(); + gpiod::line_request cfg = this->init_linerq(GpioDirection::Input,edge,pu,GpioOutput::Both, active_low); + this->lines.request(cfg); + + this->ThreadStart(); +} + +void GpioPins::ThreadLoop() +{ + // wait 20 ms for an event + // if it happens, process, otherwise wait another 20 ms + auto event_lines = this->lines.event_wait(std::chrono::milliseconds(20)); + if(event_lines) + { + for(auto& it: event_lines) + { + gpiod::line_event evt = it.event_read(); + if(evt.event_type == gpiod::line_event::RISING_EDGE) + { + this->onChange(evt.source.offset(),GpioEdge::Rising,true); + } + else //if(evt.event_type == gpiod::line_event::FALLING_EDGE) + { + this->onChange(evt.source.offset(),GpioEdge::Falling,false); + } + } + } +} + +/************************ + * * + * RgbLeD functions * + * * + ************************/ + +RgbLed::RgbLed(const uint8_t rPin, const uint8_t gPin, const uint8_t bPin) : GpioPins(std::vector{rPin,gPin,bPin}) +{ + this->PinMode(GpioDirection::PwmOutput); +} + +uint32_t RgbLed::gamma(uint8_t value) +{ + const uint16_t gamma_lut[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, + 6, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 23, 24, 25, 27, 28, 29, 31, 32, 34, 36, 37, 39, 41, + 43, 45, 47, 49, 51, 53, 55, 57, 59, 62, 64, 67, 69, 72, 74, 77, + 80, 83, 85, 88, 91, 94, 98, 101, 104, 107, 111, 114, 118, 121, 125, 129, + 133, 137, 141, 145, 149, 153, 157, 162, 166, 171, 175, 180, 185, 189, 194, 199, + 204, 210, 215, 220, 226, 231, 237, 242, 248, 254, 260, 266, 272, 278, 284, 291, + 297, 304, 310, 317, 324, 331, 338, 345, 352, 359, 367, 374, 382, 390, 397, 405, + 413, 421, 430, 438, 446, 455, 463, 472, 481, 490, 499, 508, 517, 526, 536, 545, + 555, 565, 575, 585, 595, 605, 615, 626, 636, 647, 658, 669, 680, 691, 702, 713, + 725, 736, 748, 760, 772, 784, 796, 808, 821, 833, 846, 859, 872, 885, 898, 911, + 925, 938, 952, 966, 980, 994,1008,1022,1037,1051,1066,1081,1096,1111,1126,1142, + 1157,1173,1189,1204,1221,1237,1253,1270,1286,1303,1320,1337,1354,1371,1389,1406, + 1424,1442,1460,1478,1496,1515,1533,1552,1571,1590,1609,1629,1648,1668,1687,1707, + 1727,1748,1768,1789,1809,1830,1851,1872,1894,1915,1937,1958,1980,2002,2025,2047, + }; + + + return (uint32_t) gamma_lut[value]; +} + +void RgbLed::SetColor(const uint8_t r, const uint8_t g, const uint8_t b) +{ + std::vector values = {this->gamma(r),this->gamma(g),this->gamma(b)}; + this->PwmWrite(values); } \ No newline at end of file diff --git a/src/gpio/gpio.hpp b/src/gpio/gpio.hpp index 144b412..67eb185 100644 --- a/src/gpio/gpio.hpp +++ b/src/gpio/gpio.hpp @@ -1,125 +1,137 @@ -#ifndef __GPIO_HPP_ -#define __GPIO_HPP_ - -#include "../exception/baseexceptions.hpp" -#include "../thread/thread.hpp" - -#include - -/*! \file Gpio interrupt capture functions. Header file. -*/ - -// P1 Header pins (both board revisions) -#define GPIO_0_2 2 /*!< \def Gpio pin 0/2 (rev1/rev2) */ -#define GPIO_1_3 3 /*!< \def Gpio pin 1/3 (rev1/rev2) */ -#define GPIO_4 4 /*!< \def Gpio pin 4 */ -#define GPIO_7 7 /*!< \def Gpio pin 7 */ -#define GPIO_8 8 /*!< \def Gpio pin 8 */ -#define GPIO_9 9 /*!< \def Gpio pin 9 */ -#define GPIO_10 10 /*!< \def Gpio pin 10 */ -#define GPIO_11 11 /*!< \def Gpio pin 11 */ -#define GPIO_14 14 /*!< \def Gpio pin 14 */ -#define GPIO_15 15 /*!< \def Gpio pin 15 */ -#define GPIO_17 17 /*!< \def Gpio pin 17 */ -#define GPIO_18 18 /*!< \def Gpio pin 18 */ -#define GPIO_21_27 27 /*!< \def Gpio pin 21/27 (rev1/rev2) */ -#define GPIO_22 22 /*!< \def Gpio pin 22 */ -#define GPIO_23 23 /*!< \def Gpio pin 23 */ -#define GPIO_24 24 /*!< \def Gpio pin 24 */ -#define GPIO_25 25 /*!< \def Gpio pin 25 */ - -// P5 Header pins (only rev 2) -#define GPIO_28 28 /*!< \def Gpio pin 28 */ -#define GPIO_29 29 /*!< \def Gpio pin 29 */ -#define GPIO_30 30 /*!< \def Gpio pin 30 */ -#define GPIO_31 31 /*!< \def Gpio pin 31 */ - -#define GPIO_FN_MAXLEN 128 // length of file name field - -class GpioException : MsgException -{ - protected: - virtual std::string type() { return "GpioException"; } -}; - -//! Enum for specifying input/output direction -enum GpioDirection -{ - kDirectionOut = 0, - kDirectionIn = 1 -}; - -//! Enum for specifying edge detection type -enum GpioEdge -{ - kEdgeNone = 0, - kEdgeRising = 1, - kEdgeFalling = 2, - kEdgeBoth = 3 -}; - -class GpioPin : public Thread -{ - public: - GpioPin(int pinnr, GpioDirection direction, GpioEdge edge); - ~GpioPin(); - - //! Get the actual used pin number of the IO Pin - int getPinNr(); - - //! Get current direction of pin - GpioDirection getDirection(); - //! Set new direction of pin - void setDirection(GpioDirection direction); - - //! Get current edge detection type - GpioEdge getEdge(); - //! Set edge detection type - void setEdge(GpioEdge edge); - - //! Get current value of pin - bool getValue(); - //! Set new value of pin - void setValue(bool value); - - //! Start interrupt listener - void InterruptStart(); - //! Stop interrupt listener - void InterruptStop(); - - //! Signal on interrupt - boost::signals2::signal onInterrupt; - - // Tag to store application-dependant data - void * Tag; - - virtual void ThreadFunc(); - - private: - int pin; // Gpio pin number - std::string fnDirection; // File name for Direction file - std::string fnEdge; // File name for Edge file - std::string fnValue; // File name for Value file - bool pinPreExported; // Bool indicates if the pin was already exported - - - //! Verifies gpio pin number, and translates pin numbers (REV2) to the proper REV1 or REV2 board gpio pin numbers - static int verifyPin(int gpiopin); - - //! Export a certain Gpio pin - static bool exportPin(int gpiopin); - - //! Unexport a certain Gpio pin - static bool unexportPin(int gpiopin); - - //! open a file for writing and write text to it. - static void writeFile(std::string &fname, const char *value); - static void writeFile(std::string &fname, std::string &value); - - //! open a file for reading and read some text from it - static std::string readFile(std::string &fname); - -}; - - -#endif \ No newline at end of file +#ifndef __MC_GPIOBUTTON_HPP +#define __MC_GPIOBUTTON_HPP + +#include +#include +#include +#include +#include "../thread/thread.hpp" + +enum class GpioEdge +{ + None = 0, + Rising = 1, + Falling = 2, + Both = 3 +}; + +enum class GpioDirection +{ + Input = 0, + Output = 1, + PwmOutput = 2, +}; + +enum class GpioPullup +{ + None = 0, + PullUp = 1, + PullDown = 2, +}; + +enum class GpioOutput +{ + Both = 0, + OpenDrain = 1, + OpenSource = 2, +}; + + +enum class GpioPolarity +{ + ActiveHigh = 0, + ActiveLow = 1, +}; + + +class GpioBase : protected Thread +{ +public: + GpioBase(); + ~GpioBase(); + + boost::signals2::signal onChange; + + void PinMode(GpioDirection dir, GpioOutput op, bool active_low = false); + void PinMode(GpioDirection dir, GpioPullup pu, bool active_low = false); + void PinMode(GpioDirection dir, bool active_low = false); + + void Listen(GpioEdge edge, bool active_low = false); + + virtual void Listen(GpioEdge edge, GpioPullup pu, bool active_low = false) = 0; + +protected: + virtual void PinMode(GpioDirection dir, GpioPullup pu = GpioPullup::None, GpioOutput op = GpioOutput::Both, bool active_low = false) = 0; + gpiod::line_request init_linerq(GpioDirection dir, GpioEdge edge, GpioPullup pu, GpioOutput op, bool active_low); + gpiod::chip gpioChip; + + GpioDirection dir; + +}; + +class GpioPin : public GpioBase +{ +public: + GpioPin(uint8_t gpio); + ~GpioPin(); + + virtual void DigitalWrite(bool value); + virtual bool DigitalRead(void); + + virtual void PwmWrite(uint32_t width); + + virtual void Listen(GpioEdge edge, GpioPullup pu, bool active_low = false); + + virtual bool IsAvailable(); +protected: + virtual void PinMode(GpioDirection dir, GpioPullup pu = GpioPullup::None, GpioOutput op = GpioOutput::Both,bool active_low = false); + + virtual void ThreadLoop(); + gpiod::line line; + +}; + +class GpioPins : public GpioBase +{ +public: + GpioPins(std::vector gpios); + ~GpioPins(); + + virtual void DigitalWrite(std::vector values); + virtual std::vector DigitalRead(void); + virtual void PwmWrite(std::vector widths); + + + virtual void Listen(GpioEdge edge, GpioPullup pu, bool active_low = false); + +protected: + virtual void PinMode(GpioDirection dir, GpioPullup pu = GpioPullup::None, GpioOutput op = GpioOutput::Both,bool active_low = false); + + virtual void ThreadLoop(); + gpiod::line_bulk lines; + +}; + +class RgbLed : protected GpioPins +{ +protected: + uint32_t gamma(uint8_t value); +public: + RgbLed(const uint8_t rPin, const uint8_t gPin, const uint8_t bPin); + + /*! + \param r The red component (0 to 255) + \param g The green component (0 to 255) + \param b The blue component (0 to 255) + */ + void SetColor(const uint8_t r, const uint8_t g, const uint8_t b); + + +}; + + + + + + +#endif//__MC_HID_SERVER_HPP \ No newline at end of file diff --git a/src/gpio/mailbox.c b/src/gpio/mailbox.c new file mode 100644 index 0000000..637a129 --- /dev/null +++ b/src/gpio/mailbox.c @@ -0,0 +1,299 @@ +/* +Copyright (c) 2012, Broadcom Europe Ltd. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holder 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mailbox.h" + +//#define DEBUG + +#define PAGE_SIZE (4*1024) + +void *mapmem(unsigned base, unsigned size) +{ + int mem_fd; + unsigned offset = base % PAGE_SIZE; + base = base - offset; + /* open /dev/mem */ + if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { + printf("can't open /dev/mem\nThis program should be run as root. Try prefixing command with: sudo\n"); + exit (-1); + } + void *mem = mmap( + 0, + size, + PROT_READ|PROT_WRITE, + MAP_SHARED/*|MAP_FIXED*/, + mem_fd, + base); +#ifdef DEBUG + printf("base=0x%x, mem=%p\n", base, mem); +#endif + if (mem == MAP_FAILED) { + printf("mmap error %d\n", (int)mem); + exit (-1); + } + close(mem_fd); + return (char *)mem + offset; +} + +void *unmapmem(void *addr, unsigned size) +{ + int s = munmap(addr, size); + if (s != 0) { + printf("munmap error %d\n", s); + exit (-1); + } + + return NULL; +} + +/* + * use ioctl to send mbox property message + */ + +static int mbox_property(int file_desc, void *buf) +{ + int fd = file_desc; + int ret_val = -1; + + if (fd < 0) { + fd = mbox_open(); + } + if (fd >= 0) { + ret_val = ioctl(fd, IOCTL_MBOX_PROPERTY, buf); + + if (ret_val < 0) { + printf("ioctl_set_msg failed, errno %d: %m\n", errno); + } + } +#ifdef DEBUG + unsigned *p = buf; int i; unsigned size = *(unsigned *)buf; + for (i=0; i= 0) { + /* New kernel, we use /dev/vcio, major 249, since kernel 4.1 */ + return file_desc; + } + + /* Most likely an old kernel, so drop back to the old major=100 device */ + sprintf(filename, "/tmp/mailbox-%d", getpid()); + unlink(filename); + if (mknod(filename, S_IFCHR|0600, makedev(100, 0)) < 0) { + printf("Failed to create mailbox device %s: %m\n", filename); + return -1; + } + file_desc = open(filename, 0); + if (file_desc < 0) { + printf("Can't open device file %s: %m\n", filename); + unlink(filename); + return -1; + } + unlink(filename); + + return file_desc; +} + +void mbox_close(int file_desc) { + close(file_desc); +} diff --git a/src/gpio/mailbox.h b/src/gpio/mailbox.h new file mode 100644 index 0000000..46246d7 --- /dev/null +++ b/src/gpio/mailbox.h @@ -0,0 +1,54 @@ +/* +Copyright (c) 2012, Broadcom Europe Ltd. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holder 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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 + +#define MAJOR_NUM 100 +#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) +#define DEVICE_FILE_NAME "/dev/vcio-mb" + +#ifdef __cplusplus +extern "C" { +#endif + +int mbox_open(void); +void mbox_close(int file_desc); + +unsigned get_version(int file_desc); +unsigned mem_alloc(int file_desc, unsigned size, unsigned align, unsigned flags); +unsigned mem_free(int file_desc, unsigned handle); +unsigned mem_lock(int file_desc, unsigned handle); +unsigned mem_unlock(int file_desc, unsigned handle); +void *mapmem(unsigned base, unsigned size); +void *unmapmem(void *addr, unsigned size); + +unsigned execute_code(int file_desc, unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5); +unsigned execute_qpu(int file_desc, unsigned num_qpus, unsigned control, unsigned noflush, unsigned timeout); +unsigned qpu_enable(int file_desc, unsigned enable); +#ifdef __cplusplus +} +#endif diff --git a/src/i2c/i2c.c b/src/i2c/i2c.c deleted file mode 100644 index 2f47c0b..0000000 --- a/src/i2c/i2c.c +++ /dev/null @@ -1,127 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "i2c.h" - -static unsigned int HardwareRevision(void); - -static unsigned int HardwareRevision(void) -{ - FILE * filp; - unsigned rev; - char buf[512]; - char term; - - rev = 0; - - filp = fopen ("/proc/cpuinfo", "r"); - - if (filp != NULL) - { - while (fgets(buf, sizeof(buf), filp) != NULL) - { - if (!strncasecmp("revision\t", buf, 9)) - { - if (sscanf(buf+strlen(buf)-5, "%x%c", &rev, &term) == 2) - { - if (term == '\n') break; - rev = 0; - } - } - } - fclose(filp); - } - return rev; -} - -int i2cInit(unsigned char address) -{ - int fd; // File descrition - char *fileName = "/dev/i2c-1"; // Name of the port we will be using (using revision 2 board's /dev/i2c-1 by default) - - unsigned int rev = HardwareRevision(); - if (rev < 4){ // Switch to revision 1 board's /dev/i2c-0 if revision number is below 4; - strcpy(fileName,"/dev/i2c-0"); - } - - if ((fd = open(fileName, O_RDWR)) < 0) { // Open port for reading and writing - return -1; - } - - if (ioctl(fd, I2C_SLAVE, address) < 0) { // Set the port options and set the address of the device we wish to speak to - return -2; - } - - return fd; -} - -void i2cClose(int fd) -{ - close(fd); -} - -int i2cReadReg8(int fd, unsigned char reg) -{ - unsigned char buf[1]; // Buffer for data being read/ written on the i2c bus - buf[0] = reg; // This is the register we wish to read from - - if ((write(fd, buf, 1)) != 1) { // Send register to read from - return -1; - } - - if (read(fd, buf, 1) != 1) { // Read back data into buf[] - return -2; - } - - return buf[0]; -} - -int i2cWriteReg8(int fd, unsigned char reg, unsigned char value) -{ - unsigned char buf[2]; - buf[0] = reg; // Commands for performing a ranging on the SRF08 - buf[1] = value; - - if ((write(fd, buf, 2)) != 2) { // Write commands to the i2c port - return -1; - } - return 0; -} - -int i2cReadReg16(int fd, unsigned char reg) -{ - unsigned char buf[2]; // Buffer for data being read/ written on the i2c bus - buf[0] = reg; // This is the register we wish to read from - - if ((write(fd, buf, 1)) != 1) { // Send register to read from - return -1; - } - - if (read(fd, buf, 2) != 2) { // Read back data into buf[] - return -2; - } - return (int)(buf[1] << 8) | (int)buf[0]; - - -} - -int i2cWriteReg16(int fd, unsigned char reg,unsigned short value) -{ - unsigned char buf[3]; - buf[0] = reg; // Commands for performing a ranging on the SRF08 - buf[1] = (unsigned char)( ( value >> 0 ) & 0xFF ); - buf[2] = (unsigned char)( ( value >> 8 ) & 0xFF ); - - if ((write(fd, buf, 3)) != 3) { // Write commands to the i2c port - return -1; - } - return 0; -} diff --git a/src/i2c/i2c.h b/src/i2c/i2c.h deleted file mode 100644 index fda7bbe..0000000 --- a/src/i2c/i2c.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __USER_I2C_H__ -#define __USER_I2C_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -int i2cInit(unsigned char address); -void i2cClose(int fd); -int i2cReadReg8(int fd, unsigned char reg); -int i2cWriteReg8(int fd, unsigned char reg, unsigned char value); -int i2cReadReg16(int fd, unsigned char reg); -int i2cWriteReg16(int fd, unsigned char reg,unsigned short value); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/src/log/log.cpp b/src/log/log.cpp index 2c87099..446e85e 100644 --- a/src/log/log.cpp +++ b/src/log/log.cpp @@ -32,7 +32,7 @@ Log::Log(std::string ident, int facility) { int Log::sync() { if (buffer_.length()) { - syslog(priority_, buffer_.c_str()); + syslog(priority_, "%s", buffer_.c_str()); buffer_.erase(); priority_ = LOG_DEBUG; // default to debug for each message } diff --git a/src/mc-hid-introspect.xml b/src/mc-hid-introspect.xml index 5a3b926..667a31f 100644 --- a/src/mc-hid-introspect.xml +++ b/src/mc-hid-introspect.xml @@ -14,17 +14,12 @@ - - - - - diff --git a/src/mc-hid-server-glue.hpp b/src/mc-hid-server-glue.hpp index 1e74d83..c83ffa0 100644 --- a/src/mc-hid-server-glue.hpp +++ b/src/mc-hid-server-glue.hpp @@ -24,7 +24,6 @@ public: register_method(Hid_adaptor, SetColor, _SetColor_stub); register_method(Hid_adaptor, ClearColor, _ClearColor_stub); register_method(Hid_adaptor, PulseColor, _PulseColor_stub); - register_method(Hid_adaptor, JackState, _JackState_stub); } ::DBus::IntrospectedInterface *introspect() const @@ -48,11 +47,6 @@ public: { "interval", "d", true }, { 0, 0, 0 } }; - static ::DBus::IntrospectedArgument JackState_args[] = - { - { "jackedin", "b", false }, - { 0, 0, 0 } - }; static ::DBus::IntrospectedArgument ButtonDown_args[] = { { "button", "s", false }, @@ -63,14 +57,6 @@ public: { "button", "s", false }, { 0, 0, 0 } }; - static ::DBus::IntrospectedArgument JackIn_args[] = - { - { 0, 0, 0 } - }; - static ::DBus::IntrospectedArgument JackOut_args[] = - { - { 0, 0, 0 } - }; static ::DBus::IntrospectedArgument ButtonPress_args[] = { { "button", "s", false }, @@ -86,15 +72,12 @@ public: { "SetColor", SetColor_args }, { "ClearColor", ClearColor_args }, { "PulseColor", PulseColor_args }, - { "JackState", JackState_args }, { 0, 0 } }; static ::DBus::IntrospectedMethod Hid_adaptor_signals[] = { { "ButtonDown", ButtonDown_args }, { "ButtonUp", ButtonUp_args }, - { "JackIn", JackIn_args }, - { "JackOut", JackOut_args }, { "ButtonPress", ButtonPress_args }, { "ButtonLongPress", ButtonLongPress_args }, { 0, 0 } @@ -127,7 +110,6 @@ public: virtual void SetColor(const uint8_t& r, const uint8_t& g, const uint8_t& b) = 0; virtual void ClearColor() = 0; virtual void PulseColor(const uint8_t& r, const uint8_t& g, const uint8_t& b, const double& interval) = 0; - virtual bool JackState() = 0; public: @@ -147,16 +129,6 @@ public: wi << arg1; emit_signal(sig); } - void JackIn() - { - ::DBus::SignalMessage sig("JackIn"); - emit_signal(sig); - } - void JackOut() - { - ::DBus::SignalMessage sig("JackOut"); - emit_signal(sig); - } void ButtonPress(const std::string& arg1) { ::DBus::SignalMessage sig("ButtonPress"); @@ -207,16 +179,6 @@ private: ::DBus::ReturnMessage reply(call); return reply; } - ::DBus::Message _JackState_stub(const ::DBus::CallMessage &call) - { - ::DBus::MessageIter ri = call.reader(); - - bool argout1 = JackState(); - ::DBus::ReturnMessage reply(call); - ::DBus::MessageIter wi = reply.writer(); - wi << argout1; - return reply; - } }; } } } diff --git a/src/mc-hid-server.cpp b/src/mc-hid-server.cpp index ab63d3e..6cb8ff7 100644 --- a/src/mc-hid-server.cpp +++ b/src/mc-hid-server.cpp @@ -1,10 +1,11 @@ -#ifdef HAVE_CONFIG_H +//#ifdef HAVE_CONFIG_H #include -#endif +//#endif #include "mc-hid-server.hpp" #include "log/log.hpp" +#include #include #include #include @@ -12,50 +13,67 @@ #include #include - -// For getting current time -#include -#ifndef CLOCK_MONOTIC -# define CLOCK_MONOTIC CLOCK_REALTIME -#endif - -#define NOISE_TIMEOUT_MS 400 -#define GPIO_INT_PIN 4 -#define MCP23017_ADR 0x20 - -#define BTN_ESCAPE 0x0001 -#define BTN_FAVORITES 0x0002 -#define BTN_RECENT 0x0004 - -#define BTN_REWIND 0x0008 -#define BTN_PLAYPAUSE 0x0010 -#define BTN_FASTFORWARD 0x0020 - -#define BTN_CANCEL 0x0040 -#define BTN_OK 0x0080 -#define BTN_UP 0x0100 -#define BTN_DOWN 0x0200 - -#define SENSE_MINIJACK 0x0400 - -#define PIN_RED 12 -#define PIN_GREEN 13 -#define PIN_BLUE 14 - -#define PULSE_STEPS 32 -#define PULSE_WAIT_US 20000 - -#define TRUE 1 -#define FALSE 0 - using namespace std; +const uint8_t BTN_HOME = 7; +const uint8_t BTN_CANCEL = 8; +const uint8_t BTN_UP = 9; +const uint8_t BTN_DOWN = 10; +const uint8_t BTN_PLAY = 11; +const uint8_t BTN_FWD = 12; +const uint8_t BTN_RWD = 16; +const uint8_t BTN_OK = 17; + +// map the buttons to names +const std::map BUTTONS = { + { BTN_HOME, "BTN_ESCAPE"}, + { BTN_CANCEL, "BTN_CANCEL"}, + { BTN_UP, "BTN_UP"}, + { BTN_DOWN, "BTN_DOWN"}, + { BTN_FWD, "BTN_FASTFORWARD"}, + { BTN_PLAY, "BTN_PLAYPAUSE"}, + { BTN_RWD, "BTN_REWIND"}, + { BTN_OK, "BTN_OK"}, +}; + +// define the active state of the +const std::map BUTTONS_ACTIVE = { + { BTN_HOME, true}, + { BTN_CANCEL, false}, + { BTN_UP, false}, + { BTN_DOWN, false}, + { BTN_FWD, false}, + { BTN_PLAY, false}, + { BTN_RWD, false}, + { BTN_OK, false}, +}; + +const std::vector BUTTONS_REGULAR = { + BTN_CANCEL, + BTN_UP, + BTN_DOWN, + BTN_FWD, + BTN_PLAY, + BTN_RWD, + BTN_OK, +}; + + +const uint8_t LED_RED = 4; +const uint8_t LED_GREEN = 5; +const uint8_t LED_BLUE = 6; + +const uint8_t FAN_CTL = 13; + +const int PULSE_STEPS = 32; + + + static const char *HID_SERVER_NAME = "nl.miqra.MediaCore.Hid"; static const char *HID_SERVER_PATH = "/nl/miqra/MediaCore/Hid"; -// function to get current time in ms -int64_t now_ms(void); + // signal handler void niam(int sig); @@ -63,14 +81,11 @@ HidServer::HidServer(DBus::Connection &connection) : DBus::ObjectAdaptor(connection, HID_SERVER_PATH) { - // Initialize class variables if needed - noiseTimeout = 0; // Value of 0 means: no noise timeout - // Initialize button timer - btnTimer = new ButtonTimer(25,6000); // Short press should take at leas 25 ms, and a Long press takes 6 seconds - onShortPressConnection = btnTimer->onShortPress.connect(boost::bind(&HidServer::onShortPress, this, _1)); - onLongPressConnection = btnTimer->onLongPress.connect(boost::bind(&HidServer::onLongPress, this, _1)); - onValidatePressConnection = btnTimer->onValidatePress.connect(boost::bind(&HidServer::onValidatePress, this, _1)); + btnTimer = new ButtonTimer(10,5000); // Short press should take at leas 10 ms, and a Long press takes 5 seconds + onShortPressConnection = this->btnTimer->onShortPress.connect( boost::bind( &HidServer::onShortPress, this, _1) ); + onLongPressConnection = this->btnTimer->onLongPress.connect( boost::bind( &HidServer::onLongPress, this, _1) ); + onValidatePressConnection = this->btnTimer->onValidatePress.connect( boost::bind( &HidServer::onValidatePress, this, _1) ); // **** Initialize the GPIO Interrupt pin @@ -78,12 +93,33 @@ HidServer::HidServer(DBus::Connection &connection) try { - initHardware(); + // Setup all buttons for pullup and input + + // Setup home button (which is active-high) + clog << kLogInfo << "Connecting to Home button"; + this->btHome = new GpioPin(BTN_HOME); + clog << kLogInfo << "."; + onBtHomeConnection = this->btHome->onChange.connect( boost::bind( &HidServer::onBtChange, this, _1, _2, _3) ); + clog << kLogInfo << "."; + this->btHome->Listen(GpioEdge::Both, GpioPullup::PullUp, false); + clog << kLogInfo << "." << endl; + + // Setup theo ther butons (which are active-low) + clog << kLogInfo << "Connecting to other buttons"; + this->btOther = new GpioPins(BUTTONS_REGULAR); + clog << kLogInfo << "."; + onBtOtherConnection = this->btOther->onChange.connect( boost::bind( &HidServer::onBtChange, this, _1, _2, _3) ); + clog << kLogInfo << "."; + this->btOther->Listen(GpioEdge::Both, GpioPullup::PullUp, true); + clog << kLogInfo << "." << endl; + + // setup the LED + this->rgbLed = new RgbLed(LED_RED,LED_GREEN,LED_BLUE); } - catch(std::exception x) + catch(const std::exception& x) { - clog << kLogCrit << "Fatal error during hardware initialization: " << x.what() << endl << "Quitting now... " << endl; - niam(0); + clog << kLogCrit << endl << "Fatal error during hardware initialization: " << x.what() << endl << "Quitting now... " << endl; + exit(-1); } clog << kLogInfo << "Initialization complete, listening to HID requests." << endl; @@ -93,127 +129,27 @@ HidServer::~HidServer() { ClearColor(); - onInterruptErrorConnection.disconnect(); - onInterruptConnection.disconnect(); - - delete intpin; intpin = NULL; - delete mcp; mcp = NULL; - delete btnTimer; btnTimer = NULL; + onBtHomeConnection.disconnect(); + onBtOtherConnection.disconnect(); + onShortPressConnection.disconnect(); + + onLongPressConnection.disconnect(); + onValidatePressConnection.disconnect(); + + delete this->btnTimer; this->btnTimer = NULL; + delete this->btOther; + delete this->btHome; + delete this->rgbLed; clog << kLogInfo << "Stopping normally" << endl; } -void HidServer::initHardware(void) -{ - HWConfig hwConfig; - unsigned short value; - - clog << kLogInfo << "Opening GPIO pin " << GPIO_INT_PIN << " for interrupt listening" << endl; - // open pin - intpin = new GpioPin( GPIO_INT_PIN, // Pin number - kDirectionIn, // Data direction - kEdgeFalling); // Interrupt edge - - // **** Initialize the MCP23017 - - // Hardware config - hwConfig.DISSLEW = false; // Leave slew rate control enabled - hwConfig.INT_MIRROR = true; // Interconnect I/O pins - hwConfig.INT_ODR = false; // Interrupt is not an open drain - hwConfig.INT_POL = false; // Interrupt is Active-Low - - clog << kLogInfo << "Opening MCP23017 IO expander on I2C address " << MCP23017_ADR << endl; - - try - { - // Initialize chip system - mcp = new Mcp23017( MCP23017_ADR, // adr - 0x0fff, // iodir - 0x0fff, // ipol - 0x0fff, // pullup - hwConfig, // Hardware Config - true); // Swap A/B - - try - { - clog << kLogInfo << "Enabling interrupts on IO Expander" << endl; - // Configure interrupt - mcp->IntConfig( 0x0000, // defval - 0x0000, // intcon - 0x07ff); // int enable - - - clog << kLogInfo << "Starting interrupt listener on GPIO pin " << GPIO_INT_PIN << endl; - - // Initialize interrupts - - onInterruptErrorConnection.disconnect(); - onInterruptConnection.disconnect(); - - onInterruptErrorConnection = intpin->onThreadError.connect(boost::bind(&HidServer::onInterruptError, this, _1, _2)); - onInterruptConnection = intpin->onInterrupt.connect(boost::bind(&HidServer::onInterrupt, this, _1, _2, _3)); - - // Start interrupt event on interrupt pin - intpin->InterruptStart(); - - clog << kLogInfo << "Performing initial read of IO Expander values to clear any pending interrupts and initialize Jack state" << endl; - // Read initial value to clear any current interrupts - value = mcp->getValue(); - - // Pass the initial mini-jack state to any listeners - if(value && SENSE_MINIJACK) - JackIn(); - else - JackOut(); - - // Prepare the R/G/B pins for possible PWM usage - mcp->setPwmState(PIN_RED,TRUE); - mcp->setPwmState(PIN_GREEN,TRUE); - mcp->setPwmState(PIN_BLUE,TRUE); - - } - catch(OperationFailedException x) - { - delete mcp; mcp = NULL; - throw x; - } - - } - catch(OperationFailedException x) - { - delete intpin; intpin = NULL; - throw x; - } -} void HidServer::SetColor(const uint8_t& r, const uint8_t& g, const uint8_t& b) { - clog << kLogDebug << "Got color request: RGB("<< (int)r << "," << (int)g << "," << (int)b << ") - "; - // Check if we can do solid colors (no need for PWM) - if( (r == 0 || r==255) && - (g == 0 || g==255) && - (b == 0 || b==255)) - { - // if so, then 0 is off and non-zero is on - clog << "Using ON/OFF to produce color" << endl; - // but first disable pwm - mcp->PwmStop(); // waits for completion - mcp->setPin(PIN_RED, (bool)r); - mcp->setPin(PIN_GREEN, (bool)g); - mcp->setPin(PIN_BLUE, (bool)b); - - } - else - { - clog << "Using PWM to produce color" << endl; - // we need PWM, so enable it. - mcp->PwmStart(); - - mcp->setPwmLedValue(PIN_RED, r); - mcp->setPwmLedValue(PIN_GREEN, g); - mcp->setPwmLedValue(PIN_BLUE, b); - } - + clog << kLogDebug << "Got color request: RGB("<< (int)r << "," << (int)g << "," << (int)b << ") - " << endl; + this->ThreadStop(); + this->rgbLed->SetColor(r,g,b); } void HidServer::PulseColor(const uint8_t& r, const uint8_t& g, const uint8_t& b, const double& interval) @@ -228,33 +164,37 @@ void HidServer::PulseColor(const uint8_t& r, const uint8_t& g, const uint8_t& b, clog << kLogDebug << "Got pulse color request: RGB("<< (int)r << "," << (int)g << "," << (int)b << ")" << endl; - pulseTime = (int32_t)((interval * 1000000) / (2 * PULSE_STEPS)); + // Default PULSE_STEPS is 32, reduce accordingly when interval is below 2 seconds + // with 32 pulse steps, this results in min 2.0 / (2*32) = 31 ms per color + pulseSteps = PULSE_STEPS; + if(interval > 2.0) + { + pulseSteps = (int32_t)(interval * pulseSteps); + } + + pulseTime = (int32_t)((interval * 1000000) / (2 * pulseSteps)); // Start pulse thread and PWM system ThreadStart(); - mcp->PwmStart(); } -// contains the pulse loop +// contains the pulse loop (note: faster pulsing does use more cpu) void HidServer::ThreadLoop() { uint8_t myR, myG, myB; int32_t factor = pulseI*100; - myR = (pulseR * factor)/(100 * PULSE_STEPS); - myG = (pulseG * factor)/(100 * PULSE_STEPS); - myB = (pulseB * factor)/(100 * PULSE_STEPS); - - mcp->setPwmLedValue(PIN_RED, myR); - mcp->setPwmLedValue(PIN_GREEN, myG); - mcp->setPwmLedValue(PIN_BLUE, myB); + myR = (pulseR * factor)/(100 * pulseSteps); + myG = (pulseG * factor)/(100 * pulseSteps); + myB = (pulseB * factor)/(100 * pulseSteps); + this->rgbLed->SetColor(myR,myG,myB); if(pulseDirUp) { pulseI++; - if(pulseI>= PULSE_STEPS) + if(pulseI>= pulseSteps) pulseDirUp = false; } else @@ -270,216 +210,50 @@ void HidServer::ThreadLoop() void HidServer::ClearColor() { - clog << kLogDebug << "Got request to clear colors" << endl; - + clog << kLogDebug << "Clearing color" << endl; // Stop pulse thread ThreadStop(); // Disable PWM and turn all colors off - mcp->PwmStop(); // waits for completion - mcp->setPin(PIN_RED, false); - mcp->setPin(PIN_GREEN, false); - mcp->setPin(PIN_BLUE, false); + this->rgbLed->SetColor(0,0,0); } -bool HidServer::JackState() +void HidServer::onBtChange(uint8_t gpio, GpioEdge edge, bool level) { - uint16_t value; - - try - { - value = mcp->getValue(); + if(edge == GpioEdge::Rising){ + this->btnTimer->RegisterPress((uint8_t)gpio); +// clog << kLogDebug << " (Button down : " << getBtnName((uint8_t)gpio) << ")" << endl; } - catch(OperationFailedException x) + else { - // Log the exception - clog << kLogError << "Error while retrieving Jack State: " << x.what() << endl; - - // Return false on error - return false; + this->btnTimer->RegisterRelease((uint8_t)gpio); +// clog << kLogDebug << " (Button up : " << getBtnName((uint8_t)gpio) << ")" << endl; } - // Pass the current mini-jack state to any listeners - if(value && SENSE_MINIJACK) - return true; - else - return false; } -bool HidServer::onValidatePress(uint16_t keycode) + +bool HidServer::onValidatePress(uint8_t gpio) { // Check if the key is still pressed before sending out a long press - - if(mcp->getValue() & keycode) - return true; - else - return false; + return true; //((bool)gpioRead(gpio)) == BUTTONS_ACTIVE.at(gpio); } -void HidServer::onShortPress(uint16_t keycode) +void HidServer::onShortPress(uint8_t gpio) { - clog << kLogDebug << "SHORT PRESS : " << getBtnName(keycode) << endl; - ButtonPress(getBtnName(keycode)); + clog << kLogDebug << "SHORT PRESS : " << getBtnName(gpio) << endl; + ButtonPress(getBtnName(gpio)); } -void HidServer::onLongPress(uint16_t keycode) +void HidServer::onLongPress(uint8_t gpio) { - clog << kLogDebug << "LONG PRESS : " << getBtnName(keycode) << endl; - ButtonLongPress(getBtnName(keycode)); + clog << kLogDebug << "LONG PRESS : " << getBtnName(gpio) << endl; + ButtonLongPress(getBtnName(gpio)); } -void HidServer::keyUp(uint16_t keycode) +// Convert gpio into a string for ease of use in e.g. python or other dbus bindings +std::string HidServer::getBtnName(uint8_t gpio) { - if(keycode == SENSE_MINIJACK) - { - JackOut(); - } - else - { - ButtonUp(getBtnName(keycode)); - btnTimer->RegisterRelease(keycode); - } -} - -void HidServer::keyDown(uint16_t keycode) -{ - if(keycode == SENSE_MINIJACK) - { - JackIn(); - } - else - { - ButtonDown(getBtnName(keycode)); - btnTimer->RegisterPress(keycode); - } -} - -// Convert binary keycode into a string for ease of use in e.g. python or other dbus bindings -std::string HidServer::getBtnName(uint16_t keycode) -{ - switch(keycode) - { - case BTN_ESCAPE : - return "BTN_ESCAPE"; - case BTN_FAVORITES : - return "BTN_FAVORITES"; - case BTN_RECENT : - return "BTN_RECENT"; - - case BTN_REWIND : - return "BTN_REWIND"; - case BTN_PLAYPAUSE : - return "BTN_PLAYPAUSE"; - case BTN_FASTFORWARD : - return "BTN_FASTFORWARD"; - - case BTN_CANCEL : - return "BTN_CANCEL"; - case BTN_OK : - return "BTN_OK"; - case BTN_UP : - return "BTN_UP"; - case BTN_DOWN : - return "BTN_DOWN"; - case SENSE_MINIJACK : - return "SENSE_MINIJACK"; - default: - return "BTN_NONE"; - } - -} - -void HidServer::onInterrupt(GpioPin * sender, GpioEdge edge, bool pinval) -{ - uint16_t intf,intcap, keycode; - uint8_t i, bitcount; - - if(edge != kEdgeFalling) // Only continue on falling edge - return; - - - intf = mcp->getIntF(); - intcap = mcp->getIntCap(); - - // Check if we are in a noise timeout, and cancel if so. - if(noiseTimeout !=0 && noiseTimeout > now_ms()) - return; - else - noiseTimeout = 0; - - - // Check if only one bit is set in the interrupt cap: This indicated normal operation. - // If more than one bit is set, we should assume noise - bitcount = 0; - for(i=0;i<16;i++) - { - if(intf & (1 << i)) // Check if this key is set - bitcount++; - } - - //printf("Interrupt!\n INTF : 0x%04x\n INTCAP : 0x%04x\n KEYCODE: 0x%04x\n\n", intf, intcap, keycode); - - if(bitcount > 0 && bitcount <= 3 ) // anything above 3 key interrupts at the same time is considered noise - { - - for(i=0; i < 16; i++) - { - if(intf & (1 << i)) // check if this keycode is set - { - keycode = (1 << i); - if(intcap & keycode) - { - keyDown(keycode); - if(keycode == SENSE_MINIJACK) - clog << kLogDebug << "Jacked IN " << endl; - else - clog << kLogDebug << "Button down : " << getBtnName(keycode) << endl; - } - else - { - keyUp(keycode); - if(keycode == SENSE_MINIJACK) - clog << kLogDebug << "Jacked OUT " << endl; - else - clog << kLogDebug << "Button up : " << getBtnName(keycode) << endl; - } - } - } - } - else - { - clog << kLogDebug << "!!! Input Noise !!! (Timeout: " << NOISE_TIMEOUT_MS << "ms)" << endl; - noiseTimeout = now_ms() + NOISE_TIMEOUT_MS; - } - - -} - -void HidServer::onInterruptError(Thread* sender, ThreadException x) -{ - // When this function is called, the interrupt thread will have stopped - clog << kLogErr << "Error in interrupt listener: " << x.what() << endl; - clog << kLogErr << "Attempting to restart interrupt listener... " << endl; - try - { - delete mcp; mcp = NULL; - delete intpin; intpin = NULL; - initHardware(); // Attempt to re-init the chip system. Quit on failure - clog << kLogInfo << "Succesfully restarted interrupt listener" << endl; - } - catch(std::exception x2) - { - clog << kLogCrit << "Fatal error while attempting to restart interrupt listener : " << x2.what() << endl << "Quitting now... " << endl; - niam(0); - } -} - -// get current time in milliseconds -int64_t now_ms(void) -{ - struct timespec now; - clock_gettime(CLOCK_MONOTIC, &now); - - return ((int64_t)now.tv_sec)*1000LL + (now.tv_nsec/1000000); + return BUTTONS.at(gpio); } @@ -492,21 +266,26 @@ void niam(int sig) int main() { - signal(SIGTERM, niam); - signal(SIGINT, niam); + signal(SIGTERM, niam); + signal(SIGINT, niam); + signal(2,niam); - DBus::default_dispatcher = &dispatcher; + DBus::default_dispatcher = &dispatcher; - // Initialize clog to be redirected to syslog key "mediacore.hid.server" - Log::Init("mediacore.hid"); + // Initialize clog to be redirected to syslog key "mediacore.hid.server" +// Log::Init("mediacore.hid"); - DBus::Connection conn = DBus::Connection::SystemBus(); - conn.request_name(HID_SERVER_NAME); + DBus::Connection conn = DBus::Connection::SystemBus(); + conn.request_name(HID_SERVER_NAME); - HidServer server(conn); + //gpioCfgClock(10,1,0); + //gpioInitialise(); + + HidServer server(conn); - dispatcher.enter(); + dispatcher.enter(); - return 0; + //gpioTerminate(); + return 0; } \ No newline at end of file diff --git a/src/mc-hid-server.hpp b/src/mc-hid-server.hpp index d47e022..7e05523 100644 --- a/src/mc-hid-server.hpp +++ b/src/mc-hid-server.hpp @@ -2,15 +2,14 @@ #define __MC_HID_SERVER_HPP #include -#include +//#include // Done thhrough #include #include "mc-hid-server-glue.hpp" -#include "gpio/gpio.hpp" -#include "mcp23017/mcp23017.hpp" #include "thread/thread.hpp" #include "buttontimer/buttontimer.hpp" +#include "gpio/gpio.hpp" class HidServer : public nl::miqra::MediaCore::Hid_adaptor, // << This will be generated by the makefile using dbusxx-xml2cpp on mc-hid-introspect.xml @@ -26,36 +25,36 @@ public: virtual void SetColor(const uint8_t& r, const uint8_t& g, const uint8_t& b); virtual void PulseColor(const uint8_t& r, const uint8_t& g, const uint8_t& b, const double& interval); virtual void ClearColor(); - virtual bool JackState(); - void onInterrupt(GpioPin * sender, GpioEdge edge, bool pinval); - void onInterruptError(Thread * sender, ThreadException x); - - bool onValidatePress(uint16_t keycode); - void onShortPress(uint16_t keycode); - void onLongPress(uint16_t keycode); + bool onValidatePress(uint8_t gpio); + void onShortPress(uint8_t gpio); + void onLongPress(uint8_t gpio); + void onBtChange(uint8_t gpio, GpioEdge edge, bool level); protected: virtual void ThreadLoop(); + //void onChange(int gpio, int level, uint32_t tick); private: - Mcp23017 *mcp; - GpioPin *intpin; ButtonTimer *btnTimer; + RgbLed *rgbLed; + GpioPin *btHome; + GpioPin *btCancel; + GpioPins *btOther; - int64_t noiseTimeout; - - uint8_t pulseR, pulseG, pulseB,pulseI,pulseMin; + uint8_t pulseR, pulseG, pulseB, pulseI,pulseMin; int32_t pulseTime; + int32_t pulseSteps; bool pulseDirUp; void initHardware(void); - void keyUp(uint16_t keycode); - void keyDown(uint16_t keycode); - std::string getBtnName(uint16_t keycode); - - boost::signals2::connection onInterruptConnection; + std::string getBtnName(uint8_t gpio); + + //static void onChangeEx(int gpio, int level, uint32_t tick, void *user); + + boost::signals2::connection onBtHomeConnection; + boost::signals2::connection onBtOtherConnection; boost::signals2::connection onInterruptErrorConnection; boost::signals2::connection onShortPressConnection; boost::signals2::connection onLongPressConnection; diff --git a/src/mcp23017/mcp23017.cpp b/src/mcp23017/mcp23017.cpp deleted file mode 100644 index 45be7e8..0000000 --- a/src/mcp23017/mcp23017.cpp +++ /dev/null @@ -1,968 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - - - -#include "mcp23017.hpp" -#include "../i2c/i2c.h" - -/**************************** -* * -* DEFINITIONS * -* * -*****************************/ - -//! True/False definitions -#define TRUE 1 -#define FALSE 0 - - -/************************************ -* * -* INTERNAL FUNCTION DEFINITIONS * -* * -*************************************/ - - - -/************************************ -* * -* REGISTER ADDRESS DEFINITIONS * -* * -*************************************/ - -// This interface used only BANK=0 addresses, which are defined below -// The Init function ensures that the device is started in BANK=0 mode - -#define IODIR 0x00 -#define IODIRA 0x00 -#define IODIRB 0x01 - -#define IPOL 0x02 -#define IPOLA 0x02 -#define IPOLB 0x03 - -#define GPINTEN 0x04 -#define GPINTENA 0x04 -#define GPINTENB 0x05 - -#define DEFVAL 0x06 -#define DEFVALA 0x06 -#define DEFVALB 0x07 - -#define INTCON 0x08 -#define INTCONA 0x08 -#define INTCONB 0x09 - -#define IOCON 0x0A -#define IOCONA 0x0A -#define IOCONB 0x0B - -#define GPPU 0x0C -#define GPPUA 0x0C -#define GPPUB 0x0D - -#define INTF 0x0E -#define INTFA 0x0E -#define INTFB 0x0F - -#define INTCAP 0x10 -#define INTCAPA 0x10 -#define INTCAPB 0x11 - -#define GPIO 0x12 -#define GPIOA 0x12 -#define GPIOB 0x13 - -#define OLAT 0x14 -#define OLATA 0x14 -#define OLATB 0x15 - -/************************************ -* * -* PSEUDO-GLOBAL VARIABLES * -* * -*************************************/ - -// Reverse address lookup tables for registers. -// Used mainly in error reporting - -// 8 Bit names -const char * Registers8[22] = -{ - "IODIRA", // 00 - "IODIRB", // 01 - "IPOLA", // 02 - "IPOLB", // 03 - "GPINTENA", // 04 - "GPINTENB", // 05 - "DEFVALA", // 06 - "DEFVALB", // 07 - "INTCONA", // 08 - "INTCONB", // 09 - "IOCONA", // 0A - "IOCONB", // 0B - "GPPUA", // 0C - "GPPUB", // 0D - "INTFA", // 0E - "INTFB", // 0F - "INTCAPA", // 10 - "INTCAPB", // 11 - "GPIOA", // 12 - "GPIOB", // 13 - "OLATA", // 14 - "OLATB" // 15 -}; - -// 16 bit names -const char * Registers16[22] = -{ - "IODIR", // 00 - "IODIR", // 01 - "IPOL", // 02 - "IPOL", // 03 - "GPINTEN", // 04 - "GPINTEN", // 05 - "DEFVAL", // 06 - "DEFVAL", // 07 - "INTCON", // 08 - "INTCON", // 09 - "IOCON", // 0A - "IOCON", // 0B - "GPPU", // 0C - "GPPU", // 0D - "INTF", // 0E - "INTF", // 0F - "INTCAP", // 10 - "INTCAP", // 11 - "GPIO", // 12 - "GPIO", // 13 - "OLAT", // 14 - "OLAT" // 15 -}; - - - - -/************************************ -* * -* STRUCT RELATED FUNCTIONS * -* * -*************************************/ - -HWConfig::HWConfig() -{ - DISSLEW = false; // Leave slew rate control enabled - INT_MIRROR = true; // Mirror Interrupt pins - INT_ODR = false; // Interrupt is not an open drain - INT_POL = false; // Interrupt is Active-Low -} - -uint8_t HWConfig::parse() -{ - uint8_t val = 0; - if(DISSLEW) - val |= 0x10; - if(INT_MIRROR) - val |= 0x40; - if(INT_ODR) - val |= 0x04; - if(INT_POL) - val |= 0x02; - - val |= 0x20; // Disable the address pointer - - return val; -} - - - -//! Internal helper function that translates an IOConfig structure to an unsigned int denoting the proper configuration for an MCP23017 - -/************************************ -* * -* CONNECTION SETUP * -* * -*************************************/ - -//! Open a new connection to the MCP23017 device, and initialize it. -Mcp23017::Mcp23017( uint8_t adr, - uint16_t iodir, - uint16_t ipol, - uint16_t pullup, - HWConfig hwcfg, - bool swapAB) -{ - int i; - // Try opening the port for the specific address - fp = i2cInit(adr); - if(fp <= 0) // error - { - if(fp == 0) - throw OperationFailedException("Got NULL pointer to I2C File"); - else if (fp == -1) - throw OperationFailedException("Could not open I2C device for reading and writing"); - else if (fp == -2) - throw OperationFailedException("Could not set I2C destination address"); - else - throw OperationFailedException("Got unspecified error [%d] opening I2C device",fp); - } - - // Initialize objcect variables - this->adr = adr; // set address - this->swapAB = swapAB; // set swapAB value; - - this->pwm_enabled = false; - this->pwm_mask = 0x0000; - this->pwm_prev_val = 0x0000; - - // Initialize the PWM values to null - for(i=0; i< 16; i++) - { - this->pwm_values[i] = 0; - this->pwm_v_values[i] = 0; - } - - // Initialize to default pwm speed - this->pwm_tick_delay_us = 800; // 800us * 16 steps would result in 78Hz - this->pwm_ticks = 16; - - // Copy HWConfig to key - this->hwConfig = hwcfg; - - // Use the following trick to assure we're talking to the MCP23017 in BANK=0 mode, so we can properly set the IOCON value - - try - { - // If we're in BANK1 mode, address 0x15 corresponds to the GPINTENB register, which should be inited to 0 anyway; - tryI2CWrite8(0x05, 0x00); - // Now write the proper IOCON value - tryI2CWrite8(IOCON, hwcfg.parse()); - // Finally, initialize both GPINTENA and GPINTENB to 0x00 - tryI2CWrite8(GPINTENA, 0x00); - tryI2CWrite8(GPINTENB, 0x00); - - // Further initialization - - // Set up the IO direction - tryI2CWrite16(IODIR, iodir); - // Set up the input polarity - tryI2CWrite16(IPOL, ipol); - // Set up the pullups - tryI2CWrite16(GPPU, pullup); - } - catch(OperationFailedException x) - { - i2cClose(fp); - throw x; - } -} - - -//! Destructor -Mcp23017::~Mcp23017() -{ - PwmStop(); // try to stop the PWM driver; - i2cClose(fp); -} - - -/************************************ -* * -* INTERRUPT SETTINGS * -* * -************************************/ - -//! Set interrupt config for the -void Mcp23017::IntConfig( uint16_t intcon, uint16_t defval, uint16_t int_enable) -{ - tryI2CWrite16(INTCON,intcon); - tryI2CWrite16(DEFVAL,defval); - tryI2CWrite16(GPINTEN,int_enable); -} - -//! Get Interrupt flags -uint16_t Mcp23017::getIntF() -{ - return tryI2CRead16(INTF); -} - -//! Get state of input pins on latest interrupt -uint16_t Mcp23017::getIntCap() -{ - return tryI2CRead16(INTCAP); -} - -//! Set Default value for pins -void Mcp23017::setDefault( uint16_t value) -{ - tryI2CWrite16(DEFVAL, value); -} - -//! Get Default value for pins -uint16_t Mcp23017::getDefault() -{ - return tryI2CRead16(DEFVAL); -} - -//! Set Interrupt enable -void Mcp23017::setIntEnable( uint16_t value) -{ - tryI2CWrite16(GPINTEN, value); -} - -//! Get Interrupt enable -uint16_t Mcp23017::getIntEnable() -{ - return tryI2CRead16(GPINTEN); -} - -//! Set Interrupt control value -void Mcp23017::setIntControl(uint16_t value) -{ - tryI2CWrite16(INTCON, value); -} - -//! Get Interrupt control value -uint16_t Mcp23017::getIntControl() -{ - return tryI2CRead16(INTCON); -} - -/************************************ -* * -* REGULAR I/O FUNCTIONS * -* * -************************************/ - -//! Set input polarity -void Mcp23017::setIPol(uint16_t value) -{ - tryI2CWrite16(IPOL, value); -} - -//! Get input polarity -uint16_t Mcp23017::getIPol() -{ - return tryI2CRead16(IPOL); -} - -//! Get output latch value -uint16_t Mcp23017::getOLat() -{ - return tryI2CRead16(OLAT); -} - -//! Set IO Direction -void Mcp23017::setDirection(uint16_t value) -{ - tryI2CWrite16(IODIR, value); -} - -//! Get IO Direction -uint16_t Mcp23017::getDirection() -{ - return tryI2CRead16(IODIR); -} - -//! Set new output value of the I/O pins -void Mcp23017::setValue(uint16_t value) -{ - // if pwm is enabled, use a masked write with the inverse of the pwm_mask - // to avoid overwriting pwm values - if(this->pwm_enabled) - tryI2CMaskedWrite16(GPIO,value,~this->pwm_mask); - else - tryI2CWrite16(GPIO, value); -} - -//! Get current input value of the I/O pins -uint16_t Mcp23017::getValue() -{ - return tryI2CRead16(GPIO); -} - -//! Set new output value for a subset of the I/O pins (masked by 'mask', where high bits indicat bits to set in the output) -void Mcp23017::setMaskedValue(uint16_t value, uint16_t mask) -{ - // if pwm is enabled, join the pwm_mask with this mask - // to avoid overwriting pwm values - if(this->pwm_enabled) - mask &= ~this->pwm_mask; - - tryI2CMaskedWrite16(GPIO,value,mask); -} - -//! Get the values of a specific pin -bool Mcp23017::getPin(uint8_t pin) -{ - uint16_t value; - - if(pin > 15) - throw InvalidArgumentException("Pin number exceeds maximum pin id. Ignoring request to set pin value."); - - value = tryI2CRead16(GPIO); - - if(value & (1 << pin)) - return TRUE; - else - return FALSE; -} - -//! Set the value of a specific pin -void Mcp23017::setPin(uint8_t pin, bool value) -{ - uint16_t newval, mask; - - if(pin > 15) - throw InvalidArgumentException("Pin number exceeds maximum pin id. Ignoring request to set pin value."); - - // set mask - mask = ( 1 << pin ); - - // if pwm is enabled, join the pwm_mask with this mask - // to avoid overwriting pwm values - if(this->pwm_enabled) - mask &= ~this->pwm_mask; - - if(mask == 0x00) - throw InvalidArgumentException("Pin is active in PWM. Ignoring request to set pin value."); - - if(value) - { - newval = ( 1 << pin ); - } - else - { - newval = 0; - } - - tryI2CMaskedWrite16(GPIO, newval, mask); -} - -/************************************ -* * -* PWM FUNCTIONS * -* * -************************************/ - -//! Start the PWM routine for this I/O expander -void Mcp23017::PwmStart() -{ - - if(!ThreadRunning()) - { - ThreadStart(); - } -} - -//! Stop the PWM routine for this I/O expander -void Mcp23017::PwmStop() -{ - if(ThreadRunning()) - { - ThreadStop(); - // Set the PWM pins back to low - tryI2CMaskedWrite16(OLAT, 0x0000, this->pwm_mask); - } -} - -//! Get the PWM value for a specific pin as 0-255 value (can be different from previously set value, due to rounding errors) -uint8_t Mcp23017::getPwmValue(uint8_t pin) -{ - - if(pin > 15) - throw InvalidArgumentException("Pin number exceeds maximum pin id. Ignoring request."); - - return this->pwm_v_values[pin]; // Return the cached 0-255 value of the pin -} - -//! Set the PWM value for a specific pin as 0-255 value -void Mcp23017::setPwmValue(uint8_t pin, uint8_t value) -{ - - if(pin > 15) - throw InvalidArgumentException("Pin number exceeds maximum pin id. Ignoring request."); - - this->pwm_v_values[pin] = value; // cache the provided value for returning and for updating pwm_value on change in pwm_ticks); - this->pwm_values[pin] = value / (256/this->pwm_ticks); -} - -//! Set the PWM value for a specific pin as 0-255 value and apply gamma correction for LED light levels -void Mcp23017::setPwmLedValue(uint8_t pin, uint8_t lightvalue) -{ - // Gamma correction table - const uint8_t GammaToLinear[256] = - { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 4, 4, 4, - 4, 5, 5, 5, 5, 6, 6, 6, - 6, 7, 7, 7, 8, 8, 8, 9, - 9, 9, 10, 10, 11, 11, 11, 12, - 12, 13, 13, 14, 14, 14, 15, 15, - 16, 16, 17, 17, 18, 18, 19, 19, - 20, 21, 21, 22, 22, 23, 23, 24, - 25, 25, 26, 27, 27, 28, 28, 29, - 30, 31, 31, 32, 33, 33, 34, 35, - 36, 36, 37, 38, 39, 39, 40, 41, - 42, 43, 44, 44, 45, 46, 47, 48, - 49, 50, 51, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 70, 71, 72, - 73, 74, 75, 76, 77, 78, 80, 81, - 82, 83, 84, 86, 87, 88, 89, 91, - 92, 93, 94, 96, 97, 98, 100, 101, - 102, 104, 105, 106, 108, 109, 110, 112, - 113, 115, 116, 118, 119, 120, 122, 123, - 125, 126, 128, 129, 131, 132, 134, 136, - 137, 139, 140, 142, 143, 145, 147, 148, - 150, 152, 153, 155, 157, 158, 160, 162, - 164, 165, 167, 169, 171, 172, 174, 176, - 178, 179, 181, 183, 185, 187, 189, 191, - 192, 194, 196, 198, 200, 202, 204, 206, - 208, 210, 212, 214, 216, 218, 220, 222, - 224, 226, 228, 230, 232, 234, 237, 239, - 241, 243, 245, 247, 249, 252, 254, 255 - }; - - if(pin > 15) - throw InvalidArgumentException("Pin number exceeds maximum pin id. Ignoring request."); - - this->pwm_v_values[pin] = GammaToLinear[lightvalue]; // cache the (gamma-corrected) provided value for returning and for updating pwm_value on change in pwm_ticks); - this->pwm_values[pin] = GammaToLinear[lightvalue] / (256/this->pwm_ticks); -} - - -//! Get the PWM state (on/off) for a specific pin -bool Mcp23017::getPwmState(uint8_t pin) -{ - if(pin > 15) - throw InvalidArgumentException("Pin number exceeds maximum pin id. Ignoring request."); - - return ( (this->pwm_mask & (1 << pin)) > 0); -} - -//! Set the PWM state (on/off) for a specific pin -void Mcp23017::setPwmState(uint8_t pin, bool state) -{ - if(pin > 15) - throw InvalidArgumentException("Pin number exceeds maximum pin id. Ignoring request."); - - if(state) - this->pwm_mask |= (1 << pin); - else - this->pwm_mask &= ~(1 << pin); -} - -//! Set the PWM Configuration -void Mcp23017::setPwmConfig(uint32_t tick_delay_us, uint8_t ticks) -{ - int i; - - this->pwm_tick_delay_us = tick_delay_us; - this->pwm_ticks = ticks; - - // update the actual PWM values, according to the - for(i=0;i<16;i++) - { - if(this->pwm_mask & (1 << i)) // Check if pwm_mask is enabled for this pin - { - // if so, update the actually used pwm value, to reflect the new setting of ticks - this->pwm_values[i] = this->pwm_v_values[i] / (256/this->pwm_ticks); - } - } -} - -//! Get PWM Configuration -PwmConfig Mcp23017::getPwmConfig() -{ - - PwmConfig pcfg; - pcfg.tick_delay_us = pwm_tick_delay_us; - pcfg.ticks = pwm_ticks; - return pcfg; -} - -//! Driver function for PWM thread -void Mcp23017::ThreadFunc(void) -{ - uint8_t ctr = 0; - int i; - uint16_t pwm_out = 0x00; - // - - MakeRealtime(); - - while(ThreadRunning()) - { - - pwm_out = this->pwm_mask; // start with pin high for all pins that have pwm_enabled - - // Now check for each pin if it should be low in this step... - for(i=0;i<16;i++) - { - if(this->pwm_mask & (1 << i)) // Check if pwm_mask is enabled for this pin - { - if(ctr >= this->pwm_values[i] ) // check if the counter is greater than the pwm value for this pin. If so, turn it off. - { - pwm_out &= ~(1 << i); // mask this pin out to 0, for it should be stopped - } - } - } - - if(pwm_out != this->pwm_prev_val) - { - // write out the result, masked with the pwm_mask - muteI2CMaskedWrite16(OLAT, pwm_out, this->pwm_mask); - this->pwm_prev_val = pwm_out; - } - - ctr++; - if(ctr >= (this->pwm_ticks - 1)) - { - ctr = 0; - } - - usleep(this->pwm_tick_delay_us); - } - -} - - -/************************************ -* * -* INTERNAL HELPER FUNCTIONS * -* * -*************************************/ - -/*! Try to read an 8 bit value from a register - In case of an error, The IOKey error value will be, - and the function will return prematurely. -*/ -uint8_t Mcp23017::tryI2CRead8(uint8_t reg) -{ - int ret; - // lock process - MutexLock(); - - // Now start reading - ret = i2cReadReg8(this->fp,reg); - - // unlock process - MutexUnlock(); - - // And properly set any error messages - if(ret == -1) - throw OperationFailedException("Error writing register address, attempted to read 8bit value from register %s (0x%2x) ",Registers8[reg], reg); - else if(ret == -2) - throw OperationFailedException("Error reading value, attempted to read 8bit value from register %s (0x%2x)",Registers8[reg], reg); - else if(ret < 0) - throw OperationFailedException("Unknown error [%d], attempted to read 8bit value from register %s (0x%2x)",ret, Registers8[reg], reg); - - return (uint8_t)ret; -} - -/*! Try to write an 8 bit value to a register - In case of an error, The IOKey error value will be, - and the function will return prematurely. -*/ -void Mcp23017::tryI2CWrite8(uint8_t reg, uint8_t value) -{ - int ret; - - // lock process - MutexLock(); - - // Now start reading - ret = i2cWriteReg8(this->fp,reg,value); - - // unlock process - MutexUnlock(); - - // And properly set any error messages - if(ret == -1) - throw OperationFailedException("Error writing to register, attempted to write 8bit value 0x%2x to register %s (0x%2x)",value, Registers8[reg], reg); - else if(ret < 0) - throw OperationFailedException("Unknown error [%d], attempted to write 8bit value 0x%2x to register %s (0x%2x)",ret, value, Registers8[reg], reg); - - -} - -/*! Try to write specific bits in an 8 bit value to a register - In case of an error, The IOKey error value will be, - and the function will return prematurely. -*/ -void Mcp23017::tryI2CMaskedWrite8(uint8_t reg, uint8_t value, uint8_t mask) -{ - int ret; - uint8_t newval; - - // lock process - MutexLock(); - - // read current value; - if( (ret = i2cReadReg8(this->fp,reg)) < 0) - { - // unlock process - MutexUnlock(); - // And properly set any error messages - if(ret == -1) - throw OperationFailedException("Error writing register address, attempted to read 8bit value from register %s (0x%2x) for masked write", Registers8[reg], reg); - else if(ret == -2) - throw OperationFailedException("Error reading value, attempted to read 8bit value from register %s (0x%2x) for masked write", Registers8[reg], reg); - else if(ret < 0) - throw OperationFailedException("Unknown error [%d], attempted to read 8bit value from register %s (0x%2x) for masked write",ret, Registers8[reg], reg); - } - - // copy result to new variable - newval = (uint16_t)(ret); - // keep only the non-masked bits - newval &= ~mask; - // overwrite the masked bits with the new value - newval |= (value & mask); - - if( (ret = i2cWriteReg8(this->fp,reg,newval)) < 0) - { - // unlock process - MutexUnlock(); - - // And properly set any error messages - if(ret == -1) - throw OperationFailedException("Error writing to register, attempted to write 8bit value 0x%2x to register %s (0x%2x) for masked write",value, Registers8[reg], reg); - else if(ret < 0) - throw OperationFailedException("Unknown error [%d], attempted to write 8bit value 0x%2x to register %s (0x%2x) for masked write",ret, value, Registers8[reg], reg); - } - - // unlock process - MutexUnlock(); -} - -/*! Try to read a 16 bit value from a register - In case of an error, The IOKey error value will be, - and the function will return prematurely. -*/ -uint16_t Mcp23017::tryI2CRead16(uint8_t reg) -{ - uint8_t hwreg = reg; - int ret; - - // lock process - MutexLock(); - - // Ensure that we're initially reading from the right register in relation to the AB swap settings - // (With swap enabled, we should start reading from the odd register, with swap disabled, we should start reading from the even register) - if(this->swapAB) - hwreg |= 0x01; - else - hwreg &= 0xFE; - - // Now start reading - ret = i2cReadReg16(this->fp,hwreg); - - // unlock process - MutexUnlock(); - - // And properly set any error messages - if(this->swapAB) - { - if(ret == -1) - throw OperationFailedException("Error writing register address, attempted to read 16bit value from register %s (0x%2x) [AB Swap active, actual register read is %s (0x%2x)]", Registers16[reg], reg, Registers16[hwreg], hwreg); - else if(ret == -2) - throw OperationFailedException("Error reading value, attempted to read 16bit value from register %s (0x%2x) [AB Swap active, actual register read is %s (0x%2x)]", Registers16[reg], reg, Registers16[hwreg], hwreg); - else if(ret < 0) - throw OperationFailedException("Unknown error [%d], attempted to read 16bit value from register %s (0x%2x) [AB Swap active, actual register read is %s (0x%2x)]",ret, Registers16[reg], reg, Registers16[hwreg], hwreg); - } - else - { - if(ret == -1) - throw OperationFailedException("Error writing register address, attempted to read 16bit value from register %s (0x%2x)", Registers16[reg], reg); - else if(ret == -2) - throw OperationFailedException("Error reading value, attempted to read 16bit value from register %s (0x%2x)", Registers16[reg], reg); - else if(ret < 0) - throw OperationFailedException("Unknown error [%d], attempted to read 16bit value from register %s (0x%2x)",ret, Registers16[reg], reg); - } - -return (uint16_t)ret; -} - -/*! Try to write a 16 bit value to a register - In case of an error, The IOKey error value will be, - and the function will return prematurely. -*/ -void Mcp23017::tryI2CWrite16(uint8_t reg,uint16_t value) -{ - uint8_t hwreg = reg; - int ret; - - // lock process - MutexLock(); - - // Ensure that we're initially reading from the right register in relation to the AB swap settings - // (With swap enabled, we should start reading from the odd register, with swap disabled, we should start reading from the even register) - if(this->swapAB) - hwreg |= 0x01; - else - hwreg &= 0xFE; - - // Now start writing - ret = i2cWriteReg16(this->fp,hwreg, value); - - // unlock process - MutexUnlock(); - - // And properly set any error messages - if(this->swapAB) - { - if(ret == -1) - throw OperationFailedException("Error writing to register, attempted to write 16bit value 0x%4x to register %s (0x%2x) [AB Swap active, actual register read is %s (0x%2x)]",value, Registers16[reg], reg, Registers16[hwreg], hwreg); - else if(ret < 0) - throw OperationFailedException("Unknown error [%d], attempted to write 16bit value 0x%4x to register %s (0x%2x) [AB Swap active, actual register read is %s (0x%2x)]",ret, value, Registers16[reg], reg, Registers16[hwreg], hwreg); - } - else - { - if(ret == -1) - throw OperationFailedException("Error writing to register, attempted to write 16bit value 0x%4x to register %s (0x%2x)",value, Registers16[reg], reg); - else if(ret < 0) - throw OperationFailedException("Unknown error [%d], attempted to write 16bit value 0x%4x to register %s (0x%2x)",ret, value, Registers16[reg], reg); - } - - -} - -/*! Try to write specific bits in a 16 bit value to a register - In case of an error, The IOKey error value will be, - and the function will return prematurely. -*/ -void Mcp23017::tryI2CMaskedWrite16(uint8_t reg, uint16_t value, uint16_t mask) -{ - int ret; - uint16_t newval; - uint8_t hwreg = reg; - - // lock process - MutexLock(); - - // Ensure that we're initially reading from the right register in relation to the AB swap settings - // (With swap enabled, we should start reading from the odd register, with swap disabled, we should start reading from the even register) - if(this->swapAB) - hwreg |= 0x01; - else - hwreg &= 0xFE; - - // read current value; - if( (ret = i2cReadReg16(this->fp,hwreg)) < 0) - { - // unlock process - MutexUnlock(); - - // And properly set any error messages - if(this->swapAB) - { - if(ret == -1) - throw OperationFailedException("Error writing register address, attempted to read 16bit value from register %s (0x%2x) for masked write [AB Swap active, actual register read is %s (0x%2x)]", Registers16[reg], reg, Registers16[hwreg], hwreg); - else if(ret == -2) - throw OperationFailedException("Error reading value, attempted to read 16bit value from register %s (0x%2x) for masked write [AB Swap active, actual register read is %s (0x%2x)]", Registers16[reg], reg, Registers16[hwreg], hwreg); - else if(ret < 0) - throw OperationFailedException("Unknown error [%d], attempted to read 16bit value from register %s (0x%2x) for masked write [AB Swap active, actual register read is %s (0x%2x)]",ret, Registers16[reg], reg, Registers16[hwreg], hwreg); - } - else - { - if(ret == -1) - throw OperationFailedException("Error writing register address, attempted to read 16bit value from register %s (0x%2x) for masked write", Registers16[reg], reg); - else if(ret == -2) - throw OperationFailedException("Error reading value, attempted to read 16bit value from register %s (0x%2x) for masked write", Registers16[reg], reg); - else if(ret < 0) - throw OperationFailedException("Unknown error [%d], attempted to read 16bit value from register %s (0x%2x) for masked write",ret, Registers16[reg], reg); - } - } - - // copy result to new variable - newval = (uint16_t)(ret); - // keep only the non-masked bits - newval &= ~mask; - // overwrite the masked bits with the new value - newval |= (value & mask); - - if( (ret = i2cWriteReg16(this->fp,hwreg,newval)) < 0) - { - // unlock process - MutexUnlock(); - - // And properly set any error messages - if(this->swapAB) - { - if(ret == -1) - throw OperationFailedException("Error writing to register, attempted to write 16bit value 0x%4x to register %s (0x%2x) for masked write [AB Swap active, actual register read is %s (0x%2x)]",value, Registers16[reg], reg, Registers16[hwreg], hwreg); - else if(ret < 0) - throw OperationFailedException("Unknown error [%d], attempted to write 16bit value 0x%4x to register %s (0x%2x) for masked write [AB Swap active, actual register read is %s (0x%2x)]",ret, value, Registers16[reg], reg, Registers16[hwreg], hwreg); - } - else - { - if(ret == -1) - throw OperationFailedException("Error writing to register, attempted to write 16bit value 0x%4x to register %s (0x%2x) for masked write",value, Registers16[reg], reg); - else if(ret < 0) - throw OperationFailedException("Unknown error [%d], attempted to write 16bit value 0x%4x to register %s (0x%2x) for masked write",ret, value, Registers16[reg], reg); - } - } - - // unlock process - MutexUnlock(); -} - -/*! Attempt to write specific bits in a 16 bit value to a register - In case of an error, the function will return prematurely, - without setting an error. -*/ -void Mcp23017::muteI2CMaskedWrite16(uint8_t reg, uint16_t value, uint16_t mask) -{ - int result; - uint16_t newval; - uint8_t hwreg = reg; - - // lock process - MutexLock(); - // Ensure that we're initially reading from the right register in relation to the AB swap settings - // (With swap enabled, we should start reading from the odd register, with swap disabled, we should start reading from the even register) - if(this->swapAB) - hwreg |= 0x01; - else - hwreg &= 0xFE; - - // read current value; - if( (result = i2cReadReg16(this->fp,hwreg)) < 0) - { -// fprintf(stderr,"WARNING: Got error code [%d] attempting to read\r\n",result); - // unlock process - MutexUnlock(); - return; - } - - // copy result to new variable - newval = (uint16_t)(result); - // keep only the non-masked bits - newval &= ~mask; - // overwrite the masked bits with the new value - newval |= (value & mask); - - if( (result = i2cWriteReg16(this->fp,hwreg,newval)) < 0) - { -// fprintf(stderr,"WARNING: Got error code [%d] attempting to write\r\n",result); - // unlock process - MutexUnlock(); - return; - } - - // unlock process - MutexUnlock(); - -} diff --git a/src/mcp23017/mcp23017.hpp b/src/mcp23017/mcp23017.hpp deleted file mode 100644 index 177f4fb..0000000 --- a/src/mcp23017/mcp23017.hpp +++ /dev/null @@ -1,291 +0,0 @@ -#ifndef __MCP23017_H_ -#define __MCP23017_H_ - -#include "../exception/baseexceptions.hpp" -#include "../thread/thread.hpp" -#include - -/*! \file MCP23017 interface functions. Header file. -*/ - -/**************************** -* * -* PUBLIC STRUCTS * -* * -*****************************/ - -// Structure for IO Configuration -//! \typedef HWConfig Structure containing hardware configuration for the MCP23017 -class HWConfig -{ - public: - bool DISSLEW ; /*!< Disable slew rate control (useful in noisy circuits operating at 400kHz and below), Default: false*/ - bool INT_MIRROR; /*!< Mirror INTA and INTB pins: Both pins act as a single INT pin responding to both port A and port B, Default: true */ - bool INT_ODR; /*!< Set interrupt pins as open drain output, Default: false */ - bool INT_POL; /*!< Set interrupt polatity: 1 is active-high, 0 is active-low, Default: false */ - - HWConfig(); - uint8_t parse(); /*!< parse into usable uint8_t */ -}; - -// Structure for IO Configuration -//! \struct PWMConfig Structure containing current PWM configuration (only used as return value) -struct PwmConfig -{ - uint32_t tick_delay_us; /*!< Delay between ticks in us */ - uint8_t ticks; /*!< Number of ticks in a cycle */ -}; - -/************************************ -* * -* MAIN CLASS * -* * -*************************************/ - -class Mcp23017 : public Thread -{ - private: - uint8_t adr; // I2C Address of the IO expander chip - int fp; // File pointer for the I2C connection - bool swapAB; // Option to swap ports A and B for 8bit and 16 bit operations - - HWConfig hwConfig; // Configuration of the port - - bool pwm_enabled; // Boolean used to stop the PWM thread safely - uint16_t pwm_mask; // Masks the pins on which PWM operates - uint8_t pwm_values[16]; // PWM value for each possible pin - uint8_t pwm_v_values[16]; // Cache for the PWM values provided, before downconversion - uint32_t pwm_tick_delay_us; // Interval between PWM steps in us - uint8_t pwm_ticks; // Number of PWM steps before coming full circle - uint16_t pwm_prev_val; // Keeps state of pwm output; - - uint8_t tryI2CRead8 (uint8_t reg); - void tryI2CWrite8(uint8_t reg, uint8_t value); - void tryI2CMaskedWrite8(uint8_t reg, uint8_t value, uint8_t mask); - - uint16_t tryI2CRead16(uint8_t reg); - void tryI2CWrite16(uint8_t reg, uint16_t value); - void tryI2CMaskedWrite16(uint8_t reg, uint16_t value, uint16_t mask); - void muteI2CMaskedWrite16(uint8_t reg, uint16_t value, uint16_t mask); - - - - protected: - virtual void ThreadFunc(void); // Override this if you want the entire function customized - - public: - //! Open a new connection to the MCP23017 device, and initialize it. - /*! - \param adr The I2C address of the IC to connect to - \param iodir Initial I/O direction mask (HIGH is input, LOW is output) - \param ipol Initial input polarity mask (HIGH inverts polarity, LOW keeps it the same) - \param pullup Initial pullup mask (HIGH enables pullup, LOW disables) - \param hwcfg Hardware configuration for the IC - \param swapAB Swap A and B registers in the 16 bit operations - \sa MCP23017Close - */ - Mcp23017( uint8_t adr, - uint16_t iodir, - uint16_t ipol, - uint16_t pullup, - HWConfig hwcfg, - bool swapAB - ); - - ~Mcp23017(); - - /************************************ - * * - * INTERRUPT FUNCTIONS * - * * - ************************************/ - - //! Set interrupt config for the MCP23017 - /*! - \param intcon The interrupt control mask (HIGH bit compares to default value, LOW bit to previous value) - \param defval Initial default value for the pins - \param int_enable The interrupt enable mask (HIGH bit enables, LOW bit disables) - */ - void IntConfig(uint16_t defval, uint16_t intcon, uint16_t int_enable); - - //! Get the interrupt condition of the interrupt-enabled pins - /*! - \return Current interrupt trigger state for pins - */ - uint16_t getIntF(); - - //! //! Get state of input pins on latest interrupt - /*! - \return The state of the interrupt pins on the last interrupt - */ - uint16_t getIntCap(); - - //! Set Default value for pins - /*! - \param value The new default value for the pins - */ - void setDefault(uint16_t value); - - //! Get default value for input pins - /*! - \return Current default value for the input pins - */ - uint16_t getDefault(); - - //! Set Interrupt enable mask - /*! - \param value The new interrupt enable mask (HIGH bit enables, LOW bit disables) - */ - void setIntEnable(uint16_t value); - - //! Get Interrupt enable mask - /*! - \return Current interrupt enable mask - */ - uint16_t getIntEnable(); - - //! Set Interrupt control value - /*! - \param value The new interrupt control mask (HIGH bit compares to default value, LOW bit to previous value) - */ - void setIntControl(uint16_t value); - - //! Get Interrupt control value - /*! - \return Current interrupt control state - */ - uint16_t getIntControl(); - - /************************************ - * * - * REGULAR I/O FUNCTIONS * - * * - ************************************/ - - //! Set input polarity - /*! - \param value The input polarity - HIGH inverts input polarity, LOW does not - */ - void setIPol(uint16_t value); - - //! Get input polarity - /*! - \return Current value of the input polarity - */ - uint16_t getIPol(); - - //! Get output latch value - /*! - \return Current value of the output latches - */ - uint16_t getOLat(); - - //! Set IO Direction - /*! - \param key The new I/O direction (HIGH bit is input, LOW bit is output) - */ - void setDirection(uint16_t value); - - //! Get IO Direction - /*! - \return Current value of the IO direction - */ - uint16_t getDirection(); - - //! Set new output value of the I/O pins - /*! - \param value The new output value of the pins - */ - void setValue(uint16_t value); - - //! Get current input value of the I/O pins - /*! - \return Current value of the port - */ - uint16_t getValue(); - - //! Set new output value for a subset of the I/O pins (masked by 'mask', where high bits indicat bits to set in the output) - /*! - \param value The new output value of the pins - \param mask The mask indicating which bits to apply (HIGH bit indicated bit will be applied) - */ - void setMaskedValue(uint16_t value, uint16_t mask); - //! Get the values of a specific pin; - /*! - \return The current state (1 or 0) of the pin - */ - bool getPin(uint8_t pin); - - //! Set the value of a specific pin - /*! - \param value Boolean indicating the new value of the pin - */ - void setPin(uint8_t pin, bool value); - - /************************************ - * * - * PWM FUNCTIONS * - * * - ************************************/ - - //! Start the PWM routine for this I/O expander - void PwmStart(); - - //! Stop the PWM routine for this I/O expander - void PwmStop(); - - //! Get the PWM value for a specific pin (can be different from previously set value, due to rounding errors) - /*! - \param pin The pin number of which to retrieve the value - \return The current PWM value for the pin - */ - uint8_t getPwmValue(uint8_t pin); - - //! Set the PWM value for a specific pin as 0-255 value - /*! - \param pin The pin number of which to retrieve the value - \param value The new PWM value - */ - void setPwmValue(uint8_t pin, uint8_t value); - - //! Set the PWM value for a specific pin as 0-255 value and apply gamma correction for LED light levels - /*! - \param pin The pin number of which to retrieve the value - \param value The new PWM value - */ - void setPwmLedValue(uint8_t, uint8_t lightvalue); - - //! Get the PWM state (on/off) for a specific pin - /*! - \param pin The pin number of which to retrieve the state - \return Boolean indicating the current state of the pin - */ - bool getPwmState(uint8_t pin); - - //! Set the PWM state (on/off) for a specific pin - /*! - \param pin The pin number of which to set the state - \param state Boolean indicating the new state of pwm on this pin (HIGH is enabled, LOW is disabled) - */ - void setPwmState(uint8_t pin, bool state); - - //! Set the PWM Configuration - /*! Default value results in a 4 bit PWM of around 80Hz - Note: PWM has a fairly heavy CPU load. With default settings (4 bit pwm, 800us/step) this is around 4.5% on a raspberry pi. - Doubling the resolution to 5 bit, 400us/step takes around 7% cpu load. Use at your own discretion. - - \param tick_delay_us The number of microseconds between PWM ticks (default: 313 us) - \param ticks The number of ticks in one PWM cycle (default: 32 ticks) - */ - void setPwmConfig(uint32_t tick_delay_us, uint8_t ticks); - - //! Get PWM Configuration - /*! - \return PWMConfig object containing the current settings - */ - PwmConfig getPwmConfig(); - -}; - - -#endif \ No newline at end of file diff --git a/src/test/mcp23017-i2ctest.c b/src/test/mcp23017-i2ctest.c deleted file mode 100644 index 21c9a16..0000000 --- a/src/test/mcp23017-i2ctest.c +++ /dev/null @@ -1,130 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../i2c/i2c.h" - -int main(int argc, char ** argv) -{ - int fd,i; - int result; - - char * Registers8[22] = - { - "IODIRA ", // 00 - "IODIRB ", // 01 - "IPOLA ", // 02 - "IPOLB ", // 03 - "GPINTENA", // 04 - "GPINTENB", // 05 - "DEFVALA ", // 06 - "DEFVALB ", // 07 - "INTCONA ", // 08 - "INTCONB ", // 09 - "IOCON ", // 0A - "IOCON ", // 0B - "GPPUA ", // 0C - "GPPUB ", // 0D - "INTFA ", // 0E - "INTFB ", // 0F - "INTCAPA ", // 10 - "INTCAPB ", // 11 - "GPIOA ", // 12 - "GPIOB ", // 13 - "OLATA ", // 14 - "OLATB " // 15 - }; - - char * Registers16[22] = - { - "IODIR ", // 00 - "IODIR ", // 01 - "IPOL ", // 02 - "IPOL ", // 03 - "GPINTEN", // 04 - "GPINTEN", // 05 - "DEFVAL ", // 06 - "DEFVAL ", // 07 - "INTCON ", // 08 - "INTCON ", // 09 - "IOCON ", // 0A - "IOCON ", // 0B - "GPPU ", // 0C - "GPPU ", // 0D - "INTF ", // 0E - "INTF ", // 0F - "INTCAP ", // 10 - "INTCAP ", // 11 - "GPIO ", // 12 - "GPIO ", // 13 - "OLAT ", // 14 - "OLAT " // 15 - }; - - fd = i2cInit(0x20); - - if(argc > 2) - { - int reg = -1; - int val = -1; - - if(strlen(argv[1]) == 4 && strncmp(argv[1],"0x",2) == 0) - reg = strtol(argv[1],NULL,16); - - if( (strlen(argv[2]) == 4 || strlen(argv[2]) == 6) && strncmp(argv[2],"0x",2) == 0) - val = strtol(argv[2],NULL,16); - - if(reg < 0) - printf ("Please provide an 8 bit hexadecimal value for the register in the form of 0xHH\n"); - if(val < 0) - printf ("Please provide an 8 or 16 bit hexadecimal value for the value in the form of 0xHH\n"); - - if(reg >= 0 && val >= 0) - { - if(strlen(argv[2]) == 4) - { - printf("Setting register %s (0x%02x) to 8 bit value 0x%02x\n\n", Registers8[reg], reg, val); - i2cWriteReg8(fd,(unsigned char)reg, (unsigned char) val); - } - else if (strlen(argv[2]) == 6) - { - printf("Setting register %s (0x%02x) to 16 bit value 0x%04x\n\n", Registers16[reg], reg, val); - i2cWriteReg16(fd,(unsigned char)reg, (unsigned short) val); - } - } - - } - - - printf("Reading registers as 8 bit values\n"); - for(i=0x00; i < 0x16; i++) - { - result = i2cReadReg8(fd,i); - printf(" %s (0x%02x) : 0x%02x\n",Registers8[i], i,result); - } - - printf("\n"); - printf("Reading registers as 16 bit values\n"); - - for(i=0x00; i < 0x16; i+=2) - { - result = i2cReadReg16(fd,i); - printf(" %s (0x%02x) : 0x%04x\n",Registers16[i], i,result); - } - - printf("\n"); - printf("Reading registers as 16 bit values with A/B swapped\n"); - - for(i=0x01; i < 0x16; i+=2) - { - result = i2cReadReg16(fd,i); - printf(" %s (0x%02x) : 0x%04x\n",Registers16[i], i,result); - } - - return 0; -} diff --git a/src/thread/thread.cpp b/src/thread/thread.cpp index abbba44..9a0fdc3 100644 --- a/src/thread/thread.cpp +++ b/src/thread/thread.cpp @@ -142,4 +142,5 @@ void * thread_threadStarter(void * obj) { Thread * wt = (Thread*)obj; wt->ThreadStarter(); + return (void*) nullptr; } diff --git a/src/thread/thread.hpp b/src/thread/thread.hpp index da32eab..e9032b6 100644 --- a/src/thread/thread.hpp +++ b/src/thread/thread.hpp @@ -40,7 +40,7 @@ class Thread pthread_t wthread; pthread_mutex_t mutex; pthread_mutexattr_t mutexAttr; - bool running; + bool running; void ThreadStarter(); }; diff --git a/version.py b/version.py index 2c0d715..403db28 100644 --- a/version.py +++ b/version.py @@ -1,2 +1,2 @@ PACKAGE="mediacore-hid" -VERSION="1.0.0" +VERSION="4.0.0"