diff --git a/.gitignore b/.gitignore index 301e929..23b89b9 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ test/gpio_test test/spi_test test/i2c_test test/pwm_test +test/adc_test libtool libsoc.pc *.la diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..45335cf --- /dev/null +++ b/Makefile @@ -0,0 +1,889 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# Makefile. Generated from Makefile.in by configure. + +# Copyright (C) 1994-2014 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + + + +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 \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + 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)/libsoc +pkgincludedir = $(includedir)/libsoc +pkglibdir = $(libdir)/libsoc +pkglibexecdir = $(libexecdir)/libsoc +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = x86_64-unknown-linux-gnu +host_triplet = x86_64-unknown-linux-gnu +target_triplet = x86_64-unknown-linux-gnu +am__append_1 = bindings/python +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \ + $(top_srcdir)/config/m4/ltoptions.m4 \ + $(top_srcdir)/config/m4/ltsugar.m4 \ + $(top_srcdir)/config/m4/ltversion.m4 \ + $(top_srcdir)/config/m4/lt~obsolete.m4 \ + $(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 +CONFIG_CLEAN_FILES = libsoc.pc +CONFIG_CLEAN_VPATH_FILES = +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 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pkgconfigdir)" +DATA = $(pkgconfig_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + cscope distdir dist dist-all distcheck +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# 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 +CSCOPE = cscope +DIST_SUBDIRS = lib contrib/board_files bindings/python +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/libsoc.pc.in \ + $(top_srcdir)/config/autoconf/compile \ + $(top_srcdir)/config/autoconf/config.guess \ + $(top_srcdir)/config/autoconf/config.sub \ + $(top_srcdir)/config/autoconf/install-sh \ + $(top_srcdir)/config/autoconf/ltmain.sh \ + $(top_srcdir)/config/autoconf/missing ChangeLog \ + config/autoconf/compile config/autoconf/config.guess \ + config/autoconf/config.sub config/autoconf/depcomp \ + config/autoconf/install-sh config/autoconf/ltmain.sh \ + config/autoconf/missing config/autoconf/py-compile +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +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} /usr/src/libsoc/config/autoconf/missing aclocal-1.15 +AMTAR = $${TAR-tar} +AM_DEFAULT_VERBOSITY = 0 +AR = ar +AUTOCONF = ${SHELL} /usr/src/libsoc/config/autoconf/missing autoconf +AUTOHEADER = ${SHELL} /usr/src/libsoc/config/autoconf/missing autoheader +AUTOMAKE = ${SHELL} /usr/src/libsoc/config/autoconf/missing automake-1.15 +AWK = gawk +CC = gcc +CCDEPMODE = depmode=gcc3 +CFLAGS = -g -O2 +CPP = gcc -E +CPPFLAGS = +CYGPATH_W = echo +DEFS = -DPACKAGE_NAME=\"libsoc\" -DPACKAGE_TARNAME=\"libsoc\" -DPACKAGE_VERSION=\"0.8.2\" -DPACKAGE_STRING=\"libsoc\ 0.8.2\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DPACKAGE=\"libsoc\" -DVERSION=\"0.8.2\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 -DLT_OBJDIR=\".libs/\" -DDEBUG=1 +DEPDIR = .deps +DLLTOOL = false +DSYMUTIL = +DUMPBIN = +ECHO_C = +ECHO_N = -n +ECHO_T = +EGREP = /bin/grep -E +EXEEXT = +FGREP = /bin/grep -F +GREP = /bin/grep +INSTALL = /usr/bin/install -c +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_PROGRAM = ${INSTALL} +INSTALL_SCRIPT = ${INSTALL} +INSTALL_STRIP_PROGRAM = $(install_sh) -c -s +LD = /usr/bin/ld -m elf_i386 +LDFLAGS = +LIBOBJS = +LIBS = -lpthread +LIBTOOL = $(SHELL) $(top_builddir)/libtool +LIPO = +LN_S = ln -s +LTLIBOBJS = +LT_SYS_LIBRARY_PATH = +MAKEINFO = ${SHELL} /usr/src/libsoc/config/autoconf/missing makeinfo +MANIFEST_TOOL = : +MKDIR_P = /bin/mkdir -p +NM = /usr/bin/nm -B +NMEDIT = +OBJDUMP = objdump +OBJEXT = o +OTOOL = +OTOOL64 = +PACKAGE = libsoc +PACKAGE_BUGREPORT = +PACKAGE_NAME = libsoc +PACKAGE_STRING = libsoc 0.8.2 +PACKAGE_TARNAME = libsoc +PACKAGE_URL = +PACKAGE_VERSION = 0.8.2 +PATH_SEPARATOR = : +PKG_CONFIG = /usr/bin/pkg-config +PKG_CONFIG_LIBDIR = +PKG_CONFIG_PATH = +PYTHON = python2 +PYTHON_CFLAGS = -I/usr/include/python2.7 -I/usr/include/i386-linux-gnu/python2.7 +PYTHON_EXEC_PREFIX = ${exec_prefix} +PYTHON_LIBS = -lpython2.7 +PYTHON_PLATFORM = linux2 +PYTHON_PREFIX = ${prefix} +PYTHON_VERSION = 2.7 +RANLIB = ranlib +SED = /bin/sed +SET_MAKE = +SHELL = /bin/bash +STRIP = strip +VERSION = 0.8.2 +abs_builddir = /usr/src/libsoc +abs_srcdir = /usr/src/libsoc +abs_top_builddir = /usr/src/libsoc +abs_top_srcdir = /usr/src/libsoc +ac_ct_AR = ar +ac_ct_CC = gcc +ac_ct_DUMPBIN = +am__include = include +am__leading_dot = . +am__quote = +am__tar = $${TAR-tar} chof - "$$tardir" +am__untar = $${TAR-tar} xf - +bindir = ${exec_prefix}/bin +board = artik_710 +build = x86_64-unknown-linux-gnu +build_alias = +build_cpu = x86_64 +build_os = linux-gnu +build_vendor = unknown +builddir = . +datadir = ${datarootdir} +datarootdir = ${prefix}/share +docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} +dvidir = ${docdir} +exec_prefix = ${prefix} +host = x86_64-unknown-linux-gnu +host_alias = +host_cpu = x86_64 +host_os = linux-gnu +host_vendor = unknown +htmldir = ${docdir} +includedir = ${prefix}/include +infodir = ${datarootdir}/info +install_sh = ${SHELL} /usr/src/libsoc/config/autoconf/install-sh +libdir = ${exec_prefix}/lib +libexecdir = ${exec_prefix}/libexec +localedir = ${datarootdir}/locale +localstatedir = ${prefix}/var +mandir = ${datarootdir}/man +mkdir_p = $(MKDIR_P) +oldincludedir = /usr/include +pdfdir = ${docdir} +pkgpyexecdir = ${pyexecdir}/libsoc +pkgpythondir = ${pythondir}/libsoc +prefix = /usr/local +program_transform_name = s,x,x, +psdir = ${docdir} +pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages +pythondir = ${prefix}/lib/python2.7/dist-packages +runstatedir = ${localstatedir}/run +sbindir = ${exec_prefix}/sbin +sharedstatedir = ${prefix}/com +srcdir = . +sysconfdir = ${prefix}/etc +target = x86_64-unknown-linux-gnu +target_alias = +target_cpu = x86_64 +target_os = linux-gnu +target_vendor = unknown +top_build_prefix = +top_builddir = . +top_srcdir = . +ACLOCAL_AMFLAGS = -I config/m4 +AUTOMAKE_OPTIONS = subdir-objects +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libsoc.pc +EXTRA_DIST = libsoc.pc.in +CLEANFILES = libsoc.pc +SUBDIRS = lib contrib/board_files $(am__append_1) +export +all: all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign 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);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): +libsoc.pc: $(top_builddir)/config.status $(srcdir)/libsoc.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || 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)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +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 + +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-recursive + +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 + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -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__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(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__post_remove_distdir) + +dist-shar: 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) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_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 +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + 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/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 \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(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' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(pkgconfigdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-libtool \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-pkgconfigDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-pkgconfigDATA + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--refresh check check-am clean clean-cscope clean-generic \ + clean-libtool 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-generic \ + distclean-libtool distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkgconfigDATA install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-pkgconfigDATA + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: +env: + env diff --git a/bindings/python/Makefile.am b/bindings/python/Makefile.am index f2ce05f..617f328 100644 --- a/bindings/python/Makefile.am +++ b/bindings/python/Makefile.am @@ -1,5 +1,5 @@ libsocdir = $(pyexecdir)/libsoc -libsoc_PYTHON = __init__.py gpio.py i2c.py spi.py +libsoc_PYTHON = __init__.py gpio.py i2c.py spi.py adc.py pwm.py AM_CPPFLAGS = $(PYTHON_CFLAGS) -I${top_srcdir}/lib/include -DLIBSOC_SO=\"libsoc.so.2\" diff --git a/bindings/python/__init__.py b/bindings/python/__init__.py index 45a4275..cd93628 100644 --- a/bindings/python/__init__.py +++ b/bindings/python/__init__.py @@ -2,3 +2,5 @@ from .gpio import * # NOQA from .i2c import * # NOQA from .spi import * # NOQA +from .adc import * # NOQA +from .pwm import * # NOQA diff --git a/bindings/python/adc.py b/bindings/python/adc.py new file mode 100755 index 0000000..7cc09a1 --- /dev/null +++ b/bindings/python/adc.py @@ -0,0 +1,59 @@ +#!/usr/bin/python -OO +import sys +from ._libsoc import api + +PY3 = sys.version_info >= (3, 0) + +class ADC(object): + ''' + Represents an ADC pin. + + Example of use: + + with ADC(0, 0) as adc: + print adc.read() + ''' + def __init__(self, chip, pin): + if not isinstance(chip, int): + raise TypeError('Invalid chip id must be an "int"') + if not isinstance(pin, int): + raise TypeError('Invalid adc pin must be an "int"') + self.chip = chip + self.pin = pin + self._adc = None + + def __enter__(self): + self.open() + return self + + def __exit__(self, type, value, traceback): + self.close() + + def open(self): + ''' + Opens a file descriptor to the GPIO and configures it. + ''' + assert self._adc is None + self._adc = api.libsoc_adc_request(self.chip, self.pin) + if self._adc == 0: # NULL from native code + raise IOError( + 'Unable to open adc chip(%d) pin(%d)' % (self.chip, self.pin)) + + def close(self): + '''Cleans up the memory and resources allocated by the open method.''' + if self._adc: + api.libsoc_adc_free(self._adc) + self._adc = None + + @staticmethod + def set_debug(enabled): + v = 0 + if enabled: + v = 1 + api.libsoc_set_debug(v) + + def read(self): + value = api.libsoc_adc_get_value(self._adc) + if value == -1: + raise IOError('Error reading adc value') + return value diff --git a/bindings/python/gpio.py b/bindings/python/gpio.py index 4c4823e..8a5bb33 100644 --- a/bindings/python/gpio.py +++ b/bindings/python/gpio.py @@ -2,6 +2,7 @@ import contextlib import threading import time +import logging from ._libsoc import ( DIRECTION_INPUT, DIRECTION_OUTPUT, @@ -11,20 +12,27 @@ class InterruptHandler(threading.Thread): - def __init__(self, gpio, interrupt_callback): - super(InterruptHandler, self).__init__() + def __init__(self, gpio, interrupt_callback, **kwargs): + ''' + Some of the kwargs you might want to supply are `name`, `args` + (to be passed to the handler) and `kwargs` (also for the handler) + ''' + super(InterruptHandler, self).__init__(**kwargs) self.gpio = gpio self.isr_cb = interrupt_callback self.running = False + self.callback_args = kwargs.get('args') or () + self.callback_kwargs = kwargs.get('kwargs') or {} def run(self): self.running = True while self.running: if self.gpio.poll(1000): - self.isr_cb() + self.isr_cb(*self.callback_args, **self.callback_kwargs) def stop(self): self.running = False + self.gpio.handler = None class GPIO(object): @@ -39,6 +47,7 @@ def __init__(self, id, direction, edge=EDGE_NONE, mode=LS_GPIO_SHARED): self._validate_direction(direction, edge) self.mode = mode self._gpio = None + self.handler = None def _validate_direction(self, direction, edge=EDGE_NONE): if direction not in (DIRECTION_INPUT, DIRECTION_OUTPUT): @@ -57,13 +66,27 @@ def open(self): raise IOError('Unable to open GPIO_%d' % self.id) self.set_direction(self.direction, self.edge) + def __enter__(self): + ''' + Allows `with` statement to open the GPIO + ''' + self.open() + return self + def close(self): '''Cleans up the memory and resources allocated by the open method.''' if self._gpio: api.libsoc_gpio_free(self._gpio) self._gpio = None + def __exit__(self, *exception): + ''' + Called automatically at end of `with` block + ''' + self.close() + def set_direction(self, direction, edge): + assert self._gpio is not None self._validate_direction(direction, edge) api.libsoc_gpio_set_direction(self._gpio, self.direction) if self.direction == DIRECTION_INPUT: @@ -71,11 +94,13 @@ def set_direction(self, direction, edge): raise IOError('Error setting edge for GPIO_%d' % self.id) def set_edge(self, edge): + assert self._gpio is not None self._validate_direction(self.direction, edge) if api.libsoc_gpio_set_edge(self._gpio, self.edge) != 0: raise IOError('Error setting edge for GPIO_%d' % self.id) def get_direction(self): + assert self._gpio is not None d = api.libsoc_gpio_get_direction(self._gpio) if d == -1: raise IOError('Error reading GPIO_%d direction: %d' % self.id) @@ -100,26 +125,31 @@ def set_debug(enabled): api.libsoc_set_debug(v) def set_high(self): + assert self._gpio is not None assert self.direction == DIRECTION_OUTPUT api.libsoc_gpio_set_level(self._gpio, 1) def set_low(self): + assert self._gpio is not None assert self.direction == DIRECTION_OUTPUT api.libsoc_gpio_set_level(self._gpio, 0) def is_high(self): + assert self._gpio is not None l = api.libsoc_gpio_get_level(self._gpio) if l == -1: raise IOError('Error reading GPIO_%d level' % self.id) return l == 1 def wait_for_interrupt(self, timeout): + assert self._gpio is not None assert self.direction == DIRECTION_INPUT if api.libsoc_gpio_wait_interrupt(self._gpio, timeout) != 0: raise IOError('Error waiting for interrupt on GPIO_%d' % self.id) def get_edge(self): '''Return the edge the GPIO is configured with.''' + assert self._gpio is not None assert self.direction == DIRECTION_INPUT e = api.libsoc_gpio_get_edge(self._gpio) if e == -1: @@ -132,19 +162,24 @@ def poll(self, timeout_ms=-1): polling. Returns True if an interrupt occurred, False on an error or timeout ''' + assert self._gpio is not None return api.libsoc_gpio_poll(self._gpio, timeout_ms) == 0 - def start_interrupt_handler(self, interrupt_callback): - '''Returns a thread that continuosly polls the GPIO. If an interrupt is - encountered, the interrupt_callback function will be run. This - thread can be stopped by calling interrupt_handler.stop() + def start_interrupt_handler(self, interrupt_callback, **kwargs): ''' - ih = InterruptHandler(self, interrupt_callback) - ih.start() - while not ih.running: - time.sleep(0.01) - return ih + Returns a thread that continuosly polls the GPIO. If an interrupt is + encountered, the interrupt_callback function will be run. This + thread can be stopped by calling interrupt_handler.stop() + The handler points to the GPIO and vice versa, so that the handler + thread can easily access its state. + ''' + assert self._gpio is not None + self.handler = InterruptHandler(self, interrupt_callback, **kwargs) + self.handler.start() + while not self.handler.running: + time.sleep(0.001) + return self.handler @contextlib.contextmanager def request_gpios(gpios): diff --git a/bindings/python/libsoc_python.c b/bindings/python/libsoc_python.c index f01a5ec..b0184d2 100644 --- a/bindings/python/libsoc_python.c +++ b/bindings/python/libsoc_python.c @@ -2,6 +2,7 @@ #include "libsoc_gpio.h" #include "libsoc_spi.h" +#include "libsoc_pwm.h" static PyMethodDef functions[] = { {NULL, NULL, 0, NULL} /* Sentinel */ @@ -30,6 +31,10 @@ _add_constants(PyObject *m) PyModule_AddIntConstant(m, "LS_GPIO_GREEDY", LS_GPIO_GREEDY); PyModule_AddIntConstant(m, "LS_GPIO_WEAK", LS_GPIO_WEAK); + PyModule_AddIntConstant(m, "LS_PWM_SHARED", LS_GPIO_SHARED); + PyModule_AddIntConstant(m, "LS_PWM_GREEDY", LS_GPIO_GREEDY); + PyModule_AddIntConstant(m, "LS_PWM_WEAK", LS_GPIO_WEAK); + PyModule_AddIntConstant(m, "BITS_8", BITS_8); PyModule_AddIntConstant(m, "BITS_16", BITS_16); PyModule_AddIntConstant(m, "BPW_ERROR", BPW_ERROR); diff --git a/bindings/python/pwm.py b/bindings/python/pwm.py new file mode 100644 index 0000000..6380969 --- /dev/null +++ b/bindings/python/pwm.py @@ -0,0 +1,120 @@ +#!/usr/bin/python -OO +import sys, logging +from ._libsoc import api, LS_PWM_SHARED, LS_PWM_GREEDY, LS_PWM_WEAK +logging.basicConfig(level=logging.DEBUG if __debug__ else logging.INFO) + +PY3 = sys.version_info >= (3, 0) + +MODE = { + 'shared': LS_PWM_SHARED, + 'greedy': LS_PWM_GREEDY, + 'weak': LS_PWM_WEAK +} + +MODE.update({v: k for k, v in MODE.items()}) + +POLARITY = { + 'normal': 0, + 'inversed': 1, + 'error': -1, +} + +POLARITY.update({v: k for k, v in POLARITY.items()}) + +class PWM(object): + ''' + Represents a GPIO configured for PWM (pulse width modulation). + + Example of use: + + with PWM(0, 0) as pwm: + pwm.enable = 1 + ''' + def __init__(self, chip, pin, mode='shared', **kwargs): + ''' + Initialize a PWM output. + + mode can be 'shared' (default), 'greedy', or 'weak' + ''' + if not isinstance(chip, int): + raise TypeError('Invalid chip id must be an "int"') + if not isinstance(pin, int): + raise TypeError('Invalid adc pin must be an "int"') + self.chip = chip + self.pin = pin + self.mode = mode + self.kwargs = kwargs + logging.debug('self.kwargs: %s', self.kwargs) + self._pwm = None + + period = property( + lambda self: api.libsoc_pwm_get_period(self._pwm), + lambda self, value: api.libsoc_pwm_set_period(self._pwm, value)) + + duty_cycle = property( + lambda self: api.libsoc_pwm_get_duty_cycle(self._pwm), + lambda self, value: api.libsoc_pwm_set_duty_cycle(self._pwm, value)) + + polarity = property( + lambda self: POLARITY[api.libsoc_pwm_get_polarity(self._pwm)], + lambda self, value: api.libsoc_pwm_set_polarity(self._pwm, + POLARITY[value])) + + enabled = property( + lambda self: api.libsoc_pwm_get_enabled(self._pwm), + lambda self, value: api.libsoc_pwm_set_enabled(self._pwm, value)) + + def __enter__(self): + self.open() + return self + + def __exit__(self, type, value, traceback): + self.close() + + def open(self): + ''' + Opens a file descriptor to the GPIO and configures it. + ''' + assert self._pwm is None + logging.debug('Opening PWM for use') + self._pwm = api.libsoc_pwm_request(self.chip, self.pin, MODE[self.mode]) + if self._pwm == 0: # NULL from native code + raise IOError( + 'Unable to open pwm chip(%d) pin(%d)' % (self.chip, self.pin)) + logging.debug('Setting values: %s', self.kwargs) + if self.kwargs.get('period') is not None: + logging.debug('setting period to %s', self.kwargs['period']) + self.period = self.kwargs['period'] + if self.kwargs.get('duty_cycle') is not None: + logging.debug('setting duty cycle to %s', self.kwargs['duty_cycle']) + self.duty_cycle = self.kwargs['duty_cycle'] + if self.kwargs.get('polarity') is not None: + logging.debug('setting polarity to %s', self.kwargs['polarity']) + self.polarity = POLARITY[self.kwargs['polarity']] + if self.kwargs.get('enabled') is not None: + logging.debug('setting enabled to %s', self.kwargs['enabled']) + self.enabled = self.kwargs['enabled'] + + def close(self): + ''' + Cleans up the memory and resources allocated by the open method. + + Note that in "shared" mode it does not unexport the pin: see + lib/pwm.c. + ''' + if self._pwm: + api.libsoc_pwm_free(self._pwm) + self._pwm = None + + @staticmethod + def set_debug(enabled): + v = 0 + if enabled: + v = 1 + api.libsoc_set_debug(v) + + def on(self): + self.enabled = 1 + + def off(self): + self.enabled = 0 diff --git a/contrib/board_files/Makefile.am b/contrib/board_files/Makefile.am index b28d6e2..dc5df5b 100644 --- a/contrib/board_files/Makefile.am +++ b/contrib/board_files/Makefile.am @@ -10,7 +10,7 @@ installdirs-local: install -d $(DESTDIR)$(sysconfdir) install-data-hook: installdirs-local - ln -srf $(DESTDIR)$(pkgdatadir)/@board@.conf $(DESTDIR)$(sysconfdir)/libsoc.conf + ln -srf $(DESTDIR)$(pkgdatadir)/@board@.conf $(DESTDIR)$(sysconfdir)/libsoc.conf || ln -sf $(DESTDIR)$(pkgdatadir)/@board@.conf $(DESTDIR)$(sysconfdir)/libsoc.conf endif uninstall-local: diff --git a/lib/Makefile.am b/lib/Makefile.am index 83020b2..5411d8a 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -3,18 +3,20 @@ include_HEADERS = include/libsoc_gpio.h \ include/libsoc_spi.h \ include/libsoc_i2c.h \ include/libsoc_pwm.h \ + include/libsoc_adc.h \ include/libsoc_board.h \ include/libsoc_conffile.h \ include/libsoc_debug.h libsoc_la_SOURCES = gpio.c \ - spi.c \ - file.c \ - i2c.c \ - pwm.c \ - board.c \ - conffile.c \ - debug.c + spi.c \ + file.c \ + i2c.c \ + pwm.c \ + adc.c \ + board.c \ + conffile.c \ + debug.c libsoc_la_CPPFLAGS = -I${top_srcdir}/lib/include @@ -22,3 +24,4 @@ libsoc_la_CPPFLAGS = -I${top_srcdir}/lib/include libsoc_la_LDFLAGS = -version-info 6:2:4 AM_CFLAGS = -DDATA_DIR=\"$(DESTDIR)$(pkgdatadir)\" -DLIBSOC_CONF=\"@sysconfdir@/libsoc.conf\" +# vim: tabstop=8 expandtab shiftwidth=2 softtabstop=2 diff --git a/lib/adc.c b/lib/adc.c new file mode 100644 index 0000000..a35042c --- /dev/null +++ b/lib/adc.c @@ -0,0 +1,145 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libsoc_file.h" +#include "libsoc_debug.h" +#include "libsoc_adc.h" + +#define STR_BUF 256 +/* https://stackoverflow.com/a/34135270/493161 */ +#define LENGTH(array) ((int) (sizeof (array) / sizeof(array)[0])) + +void libsoc_adc_debug (const char *func, unsigned int chip, + unsigned int adc, char *format, ...) +{ +#ifdef DEBUG + if (libsoc_get_debug ()) + { + va_list args; + + fprintf (stderr, "libsoc-adc-debug: "); + + va_start (args, format); + vfprintf (stderr, format, args); + va_end (args); + + fprintf (stderr, " ((%d,%d), %s)", chip, adc, func); + + fprintf (stderr, "\n"); + } +#endif +} + +adc* libsoc_adc_request (unsigned int chip, unsigned int adc_num) +{ + adc *new_adc; + char chip_str[STR_BUF]; + char adc_str[STR_BUF]; + int i, j; + int result; + + libsoc_adc_debug (__func__, chip, adc_num, "requested ADC"); + + for (i = 0; i < LENGTH(ADC_DEVICE_FORMAT); i++) + { + libsoc_adc_debug (__func__, chip, adc_num, "trying format string %d", i); + result = snprintf(chip_str, STR_BUF, ADC_DEVICE_FORMAT[i], chip); + if (result < 0) + { + perror("Failed formatting chip string"); + return NULL; + } + if (result >= STR_BUF) + { + fprintf(stderr, "Chip format string \"%s\" too long for buffer\n", + ADC_DEVICE_FORMAT[i]); + return NULL; + } + if (file_valid(chip_str)) + { + libsoc_adc_debug(__func__, chip, adc_num, "Found requested chip"); + for (j = 0; j < LENGTH(ADC_READ_FORMAT); j++) + { + libsoc_adc_debug (__func__, chip, adc_num, + "trying pin format string %d", j); + strncpy(adc_str, chip_str, STR_BUF); + result = snprintf(adc_str + strlen(adc_str), STR_BUF - strlen(adc_str), + ADC_READ_FORMAT[j], adc_num); + if (result < 0 || strlen(adc_str) > STR_BUF) + { + perror("Failed formatting device string"); + return NULL; + } + libsoc_adc_debug(__func__, chip, adc_num, "Checking path %s", adc_str); + if (file_valid(adc_str)) + { + libsoc_adc_debug(__func__, chip, adc_num, "Found requested ADC"); + new_adc = malloc(sizeof(adc)); + new_adc->fd = file_open(adc_str, O_RDONLY); + if (new_adc->fd < 0) + { + free(new_adc); + libsoc_adc_debug(__func__, chip, adc_num, + "Failed to open adc sysfs file: %d", new_adc->fd); + return NULL; + } + new_adc->chip = chip; + new_adc->adc = adc_num; + return new_adc; + } + } + } + } + libsoc_adc_debug(__func__, chip, adc_num, "Found no such ADC available"); + return NULL; +} + +int libsoc_adc_get_value (adc *adc) +{ + char value[64] = ""; // only 12 bit number but anticipating future needs + long result; + if (adc == NULL) + { + libsoc_adc_debug(__func__, -1, -1, "invalid adc pointer NULL"); + return -1; + } + result = file_read(adc->fd, value, 64); + if (result < 0 || strlen(value) < 1 || strlen(value) > 64) + { + libsoc_adc_debug(__func__, adc->chip, adc->adc, "ADC read failure"); + return -1; + } + if (value[strlen(value) - 1] == '\n') value[strlen(value) - 1] = '\0'; + libsoc_adc_debug(__func__, adc->chip, adc->adc, "ADC string: \"%s\"", value); + result = strtol(value, NULL, 10); + if (result == LONG_MAX) libsoc_adc_debug(__func__, adc->chip, adc->adc, + "Failed conversion to long integer"); + libsoc_adc_debug(__func__, adc->chip, adc->adc, "ADC value: %d", result); + return result; +} + +int libsoc_adc_free(adc *adc) +{ + if (adc == NULL) + { + libsoc_adc_debug(__func__, -1, -1, "invalid adc pointer NULL"); + return EXIT_FAILURE; + } + + if (file_close(adc->fd) < 0) + { + return EXIT_FAILURE; + } + + free(adc); + return EXIT_SUCCESS; +} +/* + * vim: tabstop=8 expandtab shiftwidth=2 softtabstop=2 + */ diff --git a/lib/board.c b/lib/board.c index 45352a7..f1956ea 100644 --- a/lib/board.c +++ b/lib/board.c @@ -30,8 +30,8 @@ _probe_config(conffile *conf) if (probed) { int rc = strcmp(probed, match); - free(probed); - return !rc; + free(probed); + return !rc; } } else @@ -60,22 +60,23 @@ _probe() char *ext = strrchr(dp->d_name, '.'); if (ext && !strcmp(ext, ".conf")) { - strcpy(tmp, confs_dir); - strcat(tmp, "/"); - strcat(tmp, dp->d_name); - conf = conffile_load(tmp); - if (conf) - { - libsoc_debug(__func__, "probing %s for board support", tmp); + strcpy(tmp, confs_dir); + strcat(tmp, "/"); + strcat(tmp, dp->d_name); + conf = conffile_load(tmp); + if (conf) + { + libsoc_debug(__func__, + "probing %s for board support", tmp); if(_probe_config(conf)) - { - libsoc_debug(__func__, "probing match for %s", tmp); + { + libsoc_debug(__func__, "probing match for %s", tmp); bc = calloc(1, sizeof(board_config)); bc->conf = conf; - } - else - conffile_free(conf); - } + } + else + conffile_free(conf); + } } } } while (dp != NULL && bc == NULL); diff --git a/lib/conffile.c b/lib/conffile.c index 924f842..cef6004 100644 --- a/lib/conffile.c +++ b/lib/conffile.c @@ -57,7 +57,7 @@ conffile_load(const char *path) while(fgets(line, sizeof(line), fp)) { if (*line == '#' || *line == '\0' || *line == '\n') - continue; + continue; if (line[0] == '[') { // new section diff --git a/lib/gpio.c b/lib/gpio.c index 040cc03..9c29b5b 100644 --- a/lib/gpio.c +++ b/lib/gpio.c @@ -36,13 +36,13 @@ libsoc_gpio_debug (const char *func, int gpio, char *format, ...) va_end (args); if (gpio >= 0) - { - fprintf (stderr, " (%d, %s)", gpio, func); - } + { + fprintf (stderr, " (%d, %s)", gpio, func); + } else - { - fprintf (stderr, " (NULL, %s)", func); - } + { + fprintf (stderr, " (NULL, %s)", func); + } fprintf (stderr, "\n"); } @@ -59,8 +59,8 @@ libsoc_gpio_request (unsigned int gpio_id, gpio_mode mode) if (mode != LS_GPIO_SHARED && mode != LS_GPIO_GREEDY && mode != LS_GPIO_WEAK) { libsoc_gpio_debug (__func__, gpio_id, - "mode was not set, or invalid," - " setting mode to LS_GPIO_SHARED"); + "mode was not set, or invalid," + " setting mode to LS_GPIO_SHARED"); mode = LS_GPIO_SHARED; } @@ -73,48 +73,48 @@ libsoc_gpio_request (unsigned int gpio_id, gpio_mode mode) libsoc_gpio_debug (__func__, gpio_id, "GPIO already exported"); switch (mode) - { - case LS_GPIO_WEAK: - { - return NULL; - } - - case LS_GPIO_SHARED: - { - shared = 1; - break; - } - - default: - { - break; - } - } + { + case LS_GPIO_WEAK: + { + return NULL; + } + + case LS_GPIO_SHARED: + { + shared = 1; + break; + } + + default: + { + break; + } + } } else { int fd = file_open ("/sys/class/gpio/export", O_SYNC | O_WRONLY); if (fd < 0) - return NULL; + return NULL; sprintf (tmp_str, "%d", gpio_id); if (file_write (fd, tmp_str, STR_BUF) < 0) - return NULL; + return NULL; if (file_close (fd)) - return NULL; + return NULL; sprintf (tmp_str, "/sys/class/gpio/gpio%d", gpio_id); if (!file_valid (tmp_str)) - { - libsoc_gpio_debug (__func__, gpio_id, - "gpio did not export correctly"); - perror ("libsoc-gpio-debug"); - return NULL; - } + { + libsoc_gpio_debug (__func__, gpio_id, + "gpio did not export correctly"); + perror ("libsoc-gpio-debug"); + return NULL; + } } new_gpio = malloc (sizeof (gpio)); @@ -212,8 +212,8 @@ libsoc_gpio_set_direction (gpio * current_gpio, gpio_direction direction) } libsoc_gpio_debug (__func__, current_gpio->gpio, - "setting direction to %s", - gpio_direction_strings[direction]); + "setting direction to %s", + gpio_direction_strings[direction]); sprintf (path, "/sys/class/gpio/gpio%d/direction", current_gpio->gpio); @@ -261,13 +261,13 @@ libsoc_gpio_get_direction (gpio * current_gpio) if (strncmp (tmp_str, "in", 2) <= 0) { libsoc_gpio_debug (__func__, current_gpio->gpio, - "read direction as input"); + "read direction as input"); return INPUT; } else { libsoc_gpio_debug (__func__, current_gpio->gpio, - "read direction as output"); + "read direction as output"); return OUTPUT; } } @@ -282,7 +282,7 @@ libsoc_gpio_set_level (gpio * current_gpio, gpio_level level) } libsoc_gpio_debug (__func__, current_gpio->gpio, "setting level to %d", - level); + level); if (file_write (current_gpio->value_fd, gpio_level_strings[level], 1) < 0) return EXIT_FAILURE; @@ -335,7 +335,7 @@ libsoc_gpio_set_edge (gpio * current_gpio, gpio_edge edge) } libsoc_gpio_debug (__func__, current_gpio->gpio, "setting edge to %s", - gpio_edge_strings[edge]); + gpio_edge_strings[edge]); sprintf (path, "/sys/class/gpio/gpio%d/edge", current_gpio->gpio); @@ -388,13 +388,13 @@ libsoc_gpio_get_edge (gpio * current_gpio) else if (strncmp (tmp_str, "f", 1) == 0) { libsoc_gpio_debug (__func__, current_gpio->gpio, - "read edge as falling"); + "read edge as falling"); return FALLING; } else if (strncmp (tmp_str, "b", 1) == 0) { libsoc_gpio_debug (__func__, current_gpio->gpio, - "read edge as both"); + "read edge as both"); return BOTH; } else @@ -411,6 +411,12 @@ libsoc_gpio_poll (gpio * gpio, int timeout) char c; // do an initial read to clear interrupt, + if (gpio == NULL) + { + libsoc_gpio_debug (__func__, -1, "invalid gpio pointer"); + return LS_INT_ERROR; + } + rc = lseek(gpio->value_fd, 0, SEEK_SET); rc = read(gpio->value_fd, &c, 1); @@ -450,7 +456,7 @@ libsoc_gpio_wait_interrupt (gpio * gpio, int timeout) if (test_edge == EDGE_ERROR || test_edge == NONE) { libsoc_gpio_debug (__func__, gpio->gpio, - "edge must be FALLING, RISING or BOTH"); + "edge must be FALLING, RISING or BOTH"); return LS_INT_ERROR; } @@ -476,7 +482,7 @@ __libsoc_new_interrupt_callback_thread (void *void_gpio) int libsoc_gpio_callback_interrupt (gpio * gpio, int (*callback_fn) (void *), - void *arg) + void *arg) { pthread_t *poll_thread = malloc (sizeof (pthread_t)); pthread_attr_t pthread_attr; @@ -500,7 +506,7 @@ libsoc_gpio_callback_interrupt (gpio * gpio, int (*callback_fn) (void *), pthread_mutex_lock(&new_gpio_callback->ready); int ret = pthread_create (poll_thread, NULL, - __libsoc_new_interrupt_callback_thread, gpio); + __libsoc_new_interrupt_callback_thread, gpio); if (ret == 0) { diff --git a/lib/i2c.c b/lib/i2c.c index 8821818..73ec651 100644 --- a/lib/i2c.c +++ b/lib/i2c.c @@ -29,14 +29,14 @@ libsoc_i2c_debug (const char *func, i2c * i2c, char *format, ...) va_end (args); if (i2c == NULL) - { - fprintf (stderr, " (NULL, %s)", func); - } + { + fprintf (stderr, " (NULL, %s)", func); + } else - { - fprintf (stderr, " (i2c-%d, %d, %s)", i2c->bus, - i2c->address, func); - } + { + fprintf (stderr, " (i2c-%d, %d, %s)", i2c->bus, + i2c->address, func); + } fprintf (stderr, "\n"); } diff --git a/lib/include/libsoc_adc.h b/lib/include/libsoc_adc.h new file mode 100644 index 0000000..03b6d94 --- /dev/null +++ b/lib/include/libsoc_adc.h @@ -0,0 +1,69 @@ +#ifndef _LIBSOC_ADC_H_ +#define _LIBSOC_ADC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +static const char ADC_DEVICE_FORMAT[][64] = { + "/sys/devices/12d10000.adc/iio:device%d", // ARTIK 1020 + "/sys/devices/platform/c0000000.soc/c0053000.adc/iio:device%d", // 710 + "/sys/devices/126c0000.adc/iio:device%d" // ARTIK 520 +}; + +static const char ADC_READ_FORMAT[][32] = { + "/in_voltage%d_raw" +}; + +/** + * \struct adc + * \brief representation of a single requested adc + * \param unsigned int adc - adc num + * \param unsigned int adc_chip - adc chip num + * \param int fd - file descriptor to adc file + */ + +typedef struct { + unsigned int chip; + unsigned int adc; + int fd; +} adc; + +/** + * \fn adc* libsoc_adc_request(unsigned int adc_chip, unsigned int adc_num) + * \brief request an adc to use + * \param unsigned int adc_chip - the chip number that controls the adc you + wish to use + * \param unsigned int adc_num - the adc number number within your adc chip + * \return pointer to adc* on success NULL on fail + * + */ + +adc* libsoc_adc_request(unsigned int adc_chip, unsigned int adc_num); + +/** + * \fn int libsoc_adc_get_value(adc *adc) + * \brief read value from ADC + * \param pointer to adc* + * \return int positive value read on success -1 on fail + * + */ + +int libsoc_adc_get_value (adc *adc); + +/** + * \fn int libsoc_adc_free(adc* adc) + * \brief free a previously requested adc + * \param adc* adc - valid pointer to a requested adc + * \return EXIT_SUCCESS or EXIT_FAILURE + */ + +int libsoc_adc_free(adc *adc); + +#ifdef __cplusplus +} +#endif +#endif +/* + * vim: tabstop=8 expandtab shiftwidth=2 softtabstop=2 + */ diff --git a/lib/pwm.c b/lib/pwm.c index da3cd01..04946af 100644 --- a/lib/pwm.c +++ b/lib/pwm.c @@ -31,7 +31,7 @@ void libsoc_pwm_debug (const char *func, unsigned int chip, vfprintf (stderr, format, args); va_end (args); - fprintf (stderr, " ((%d,%d), %s)", chip, pwm, func); + fprintf (stderr, " ((%d,%d), %s)", chip, pwm, func); fprintf (stderr, "\n"); } @@ -48,7 +48,7 @@ pwm* libsoc_pwm_request (unsigned int chip, unsigned int pwm_num, if (mode != LS_PWM_SHARED && mode != LS_PWM_GREEDY && mode != LS_PWM_WEAK) { libsoc_pwm_debug (__func__, chip, pwm_num, - "mode was not set, or invalid, setting mode to LS_PWM_SHARED"); + "mode was not set, or invalid, setting mode to LS_PWM_SHARED"); mode = LS_PWM_SHARED; } @@ -62,23 +62,23 @@ pwm* libsoc_pwm_request (unsigned int chip, unsigned int pwm_num, libsoc_pwm_debug(__func__, chip, pwm_num, "PWM already exported"); switch(mode) - { - case LS_PWM_WEAK: - { - return NULL; - } - - case LS_PWM_SHARED: - { - shared = 1; - break; - } - - default: - { - break; - } - } + { + case LS_PWM_WEAK: + { + return NULL; + } + + case LS_PWM_SHARED: + { + shared = 1; + break; + } + + default: + { + break; + } + } } else { @@ -93,13 +93,12 @@ pwm* libsoc_pwm_request (unsigned int chip, unsigned int pwm_num, sprintf(tmp_str, "/sys/class/pwm/pwmchip%d/pwm%d/enable", chip, pwm_num); if (!file_valid(tmp_str)) - { - libsoc_pwm_debug(__func__, chip, pwm_num, - "failed to export PWM"); + { + libsoc_pwm_debug(__func__, chip, pwm_num, "failed to export PWM"); perror("libsoc-pwm-debug"); - return NULL; - } + return NULL; + } } new_pwm = malloc(sizeof(pwm)); @@ -116,7 +115,8 @@ pwm* libsoc_pwm_request (unsigned int chip, unsigned int pwm_num, if (new_pwm->enable_fd < 0 || new_pwm->period_fd < 0 || new_pwm->duty_fd < 0) { free(new_pwm); - libsoc_pwm_debug(__func__, chip, pwm_num, "Failed to open pwm sysfs file: %d", new_pwm->enable_fd); + libsoc_pwm_debug(__func__, chip, pwm_num, + "Failed to open pwm sysfs file: %d", new_pwm->enable_fd); return NULL; } @@ -217,8 +217,7 @@ pwm_enabled libsoc_pwm_get_enabled(pwm *pwm) if(val == 1) { - libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, - "read as enabled"); + libsoc_pwm_debug(__func__, pwm->chip, pwm->pwm, "read as enabled"); return ENABLED; } else if (val == 0) diff --git a/static-docs/docs/index.md b/static-docs/docs/index.md index 2a1d1a3..09ab8fb 100644 --- a/static-docs/docs/index.md +++ b/static-docs/docs/index.md @@ -163,6 +163,12 @@ Install the library using make make install ``` +Run `ldconfig` to update library cache + +```text +sudo ldconfig +``` + ## Documentation Written documentation can be found at diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..9a9ef13 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,10 @@ +CPATH += ../lib/include +LIBRARY_PATH := ../lib/.libs $(LIBRARY_PATH) +export +test: adc_test adc_test.test adc_test.py.test \ + pwm_test pwm_test.test pwm_test.py.test +%: %.c + gcc -o $@ $< -lsoc +# example: `make ARGS="0 2 shared normal 1000 500" pwm_test.test` on ARTIK 710 +%.test: % + ./$< $(ARGS) diff --git a/test/adc_test.c b/test/adc_test.c new file mode 100644 index 0000000..fd4602f --- /dev/null +++ b/test/adc_test.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include + +#include "libsoc_adc.h" +#include "libsoc_debug.h" + +/** + * + * This adc_test is intended to be run on Samsung ARTIK 710 hardware, + * however, it can work on any board with an ADC sysfs implementation, + * if the lib/include/libsoc_adc.h file is modified accordingly. + * + * The ADC sysfs interface is still vendor-specific as of 2017-07-20. + * + * ADC sysfs Documentation: https://developer.artik.io/documentation/ + * developer-guide/gpio/kernel-gpio.html + */ + +int main(int argc, char *argv[]) +{ + int ret = EXIT_FAILURE; + adc *adc; + int chip = 0, pin = 0, value; + + if (argc > 1) chip = atoi(argv[1]); + if (argc > 2) pin = atoi(argv[2]); + + libsoc_set_debug(1); + + adc = libsoc_adc_request(chip, pin); + + if (!adc) + { + fprintf(stderr, "Failed to get ADC\n"); + } + else + { + value = libsoc_adc_get_value(adc); + if (value < 0) + { + fprintf(stderr, "Failed to read ADC value\n"); + } + else + { + ret = EXIT_SUCCESS; + } + libsoc_adc_free(adc); + } + return ret; +} diff --git a/test/adc_test.py b/test/adc_test.py new file mode 100755 index 0000000..04edaeb --- /dev/null +++ b/test/adc_test.py @@ -0,0 +1,25 @@ +#!/usr/bin/python -OO +''' +Test for ADC module +''' +import sys, os +from libsoc import ADC +ADC.set_debug(__debug__) + +def test_adc(): + ''' + ADC test routine + ''' + for index in range(8): + value = None + try: + with ADC(0, index) as adc: + value = adc.read() + print('Value read at ADC(%d, %d): %s' % ( + adc.chip, adc.pin, value)) + except IOError: + sys.stderr.write('No such ADC (%d, %d)\n' % (0, index)) + +if __name__ == '__main__': + test_adc() + diff --git a/test/i2c_test.py b/test/i2c_test.py old mode 100644 new mode 100755 diff --git a/test/pwm_test.c b/test/pwm_test.c index 902e9a1..4dcf7f6 100644 --- a/test/pwm_test.c +++ b/test/pwm_test.c @@ -22,13 +22,19 @@ #define PWM_OUTPUT_CHIP 0 #define PWM_CHIP_OUTPUT 1 -int main(void) +int main(int argc, char **argv) { - int ret = EXIT_SUCCESS; - + int ret = EXIT_SUCCESS, chip, output; + long period, duty_cycle; + chip = argc > 1 ? atoi(argv[1]) : PWM_OUTPUT_CHIP; + output = argc > 2 ? atoi(argv[2]) : PWM_CHIP_OUTPUT; + period = argc > 3 ? atoi(argv[3]) : 10; + duty_cycle = argc > 4 ? atoi(argv[4]) : 5; libsoc_set_debug(1); + fprintf(stderr, "Initializing PWM with parameters %d, %d, %d, %d\n", + chip, output, period, duty_cycle); - pwm *pwm = libsoc_pwm_request(PWM_OUTPUT_CHIP, PWM_CHIP_OUTPUT, LS_PWM_SHARED); + pwm *pwm = libsoc_pwm_request(chip, output, LS_PWM_SHARED); if (!pwm) { @@ -58,21 +64,21 @@ int main(void) goto fail; } - libsoc_pwm_set_period(pwm, 10); + libsoc_pwm_set_period(pwm, period); int current_period = libsoc_pwm_get_period(pwm); - if (current_period != 10) + if (current_period != period) { printf("Failed period test\n"); goto fail; } - libsoc_pwm_set_duty_cycle(pwm, 5); + libsoc_pwm_set_duty_cycle(pwm, duty_cycle); int current_duty = libsoc_pwm_get_duty_cycle(pwm); - if (current_duty != 5) + if (current_duty != duty_cycle) { printf("Failed duty test\n"); goto fail; @@ -80,11 +86,11 @@ int main(void) // This command should fail as the duty should not // be allowed to be greater than the period - libsoc_pwm_set_duty_cycle(pwm, 15); + libsoc_pwm_set_duty_cycle(pwm, period + duty_cycle); current_duty = libsoc_pwm_get_duty_cycle(pwm); - if (current_duty != 5) + if (current_duty != duty_cycle) { printf("Failed duty test, this may be a problem with the kernel driver, continuing...\n"); } diff --git a/test/pwm_test.py b/test/pwm_test.py new file mode 100755 index 0000000..90a7d59 --- /dev/null +++ b/test/pwm_test.py @@ -0,0 +1,68 @@ +#!/usr/bin/python +''' +Simple test of the PWM API + +Should duplicate function of pwm_test.c (q.v.) +''' +import sys, os, logging +from ast import literal_eval +from libsoc import PWM +PWM.set_debug(__debug__) +logging.basicConfig(level=logging.DEBUG if __debug__ else logging.INFO) + +def test_pwm(chip=0, pin=1, period=10, duty_cycle=5, + mode='shared', polarity='normal', enabled=False): + ''' + Duplicate pwm_test.c + ''' + logging.debug('locals(): %s', locals()) + kwargs = {k: safe_int(v) for k, v in locals().items()} + logging.debug('kwargs: %s', kwargs) + try: + with PWM(**kwargs) as pwm: + for key in kwargs: + value = getattr(pwm, key) + logging.debug('Check value %s for pwm.%s', value, key) + pwm.duty_cycle = pwm.period + pwm.duty_cycle + if pwm.duty_cycle != pwm.duty_cycle: + logging.error('PWM allowed a duty cycle > 100%') + else: + logging.debug('PWM properly rejected >100% duty cycle') + pass + pwm.on() + if not pwm.enabled: + logging.error('The PWM would not turn on') + pwm.off() + if pwm.enabled: + logging.error('The PWM would not shut off') + except IOError: + logging.fatal('No such PWM %s was found', kwargs) + sys.exit(1) + +def safe_int(string): + ''' + Returns an int if it parses as one, otherwise a string + ''' + if isinstance(string, int): + return string + try: + number = literal_eval(string) + if isinstance(number, int): + return number + else: + raise TypeError('Not a number') + except ValueError, TypeError: + return string or None + +if __name__ == '__main__': + ''' + You can set chip and pin number on the command line + + Also other properties in this order: + period: an integer up to hardware limit (1000000000 for ARTIK7) + duty_cycle: an integer up to `period` + mode: 'shared', 'greedy', or 'weak' + polarity: 'normal' or 'inverse' + enabled: 1 (on) or 0 (off) + ''' + test_pwm(*sys.argv[1:]) diff --git a/test/switched_led.py b/test/switched_led.py new file mode 100755 index 0000000..500d826 --- /dev/null +++ b/test/switched_led.py @@ -0,0 +1,81 @@ +#!/usr/bin/python -OO +''' +Switched LED test, using interrupts on inputs and driving outputs. + +Assumes switches are pulled low when pressed, and output must be +high to drive LED. + +The default values are for the ARTIK 710 developer board, with mapping +from https://developer.artik.io/documentation/developer-guide/gpio/ +gpio-mapping.html. + +Device Sysfs mapping Note + +SW403 GPIO 30 Nearest board edge, next to red LED400 +SW404 GPIO 32 Next to blue LED401 +LED400 GPIO 28 Red LED +LED401 GPIO 38 Blue LED +''' +import sys +import time +import logging +from libsoc import gpio +# run as `python switched_led.py` for verbose logging +logging.basicConfig(level=logging.DEBUG if __debug__ else logging.INFO) +PAIRS = {} # switch-LED pairs +NAMES = { # edit for your board, or set to empty dict + 30: 'SW403', + 32: 'SW404', + 28: 'LED400', + 38: 'LED401', +} + +def switchtest(gpios): + ''' + Run the switched LED test with given GPIO numbers. + ''' + switches = gpios[::2] + leds = gpios[1::2] + for switch, led in zip(switches, leds): + switch_signal = gpio.GPIO( + switch, gpio.DIRECTION_INPUT, gpio.EDGE_BOTH) + led_signal = gpio.GPIO(led, gpio.DIRECTION_OUTPUT) + with led_signal as signal: + signal.set_low() # start with all LEDs off + PAIRS[switch_signal] = led_signal + # now the pairs are established, we can enable interrupts + logging.debug('PAIRS: %s', PAIRS) + try: + with gpio.request_gpios(PAIRS.keys() + PAIRS.values()): + for switch_signal in PAIRS: + switch_signal.start_interrupt_handler( + activator, args=(switch_signal,)) + logging.info('Push a switch to see its LED light; ' + 'Control-C to exit.') + while True: + time.sleep(60) # wait until user gets bored + except (KeyboardInterrupt, SystemExit): + logging.info('It may take a few seconds for handlers to stop.') + for switch in PAIRS: + switch.handler.stop() + +def activator(signal): + ''' + Called when a switch transitions to high or low. + + We turn LED on or off depending on whether the switch is down or up. + ''' + logging.debug('Switch %s activated', NAMES.get(signal.id, signal.id)) + if signal.is_high(): + PAIRS[signal].set_low() + else: + PAIRS[signal].set_high() + +if __name__ == '__main__': + gpios = map(int, sys.argv[1:]) or [30, 28, 32, 38] + logging.debug('GPIOs: %s', gpios) + if len(gpios) % 2 == 0: + switchtest(gpios) + else: + logging.fatal('Must specify GPIOs of each switch followed by its LED') + diff --git a/test/test_configure.sh b/test/test_configure.sh index 473628d..fe09ef0 100755 --- a/test/test_configure.sh +++ b/test/test_configure.sh @@ -1,4 +1,4 @@ -#! /bin/sh -e +#! /bin/bash -e python2=1 python3=1