diff --git a/bash/gpio b/bash/gpio new file mode 100755 index 0000000..53964cf --- /dev/null +++ b/bash/gpio @@ -0,0 +1,450 @@ +#!/bin/bash + +# There is no GPIO0 or GPIO1 +# Zero padding means p_list[2] = GPIO2 +p_list=("0" "0" "2" "3" "4" "5" "6" "7" "8" "9" "10" "11" "12" "13" "14" "15" "16" "17" "18" "19" "20" "21" "22" "23" "24" "25" "26" "27") +p_locs=(0 0 3 5 7 29 31 26 24 21 19 23 32 33 8 10 36 11 12 35 38 40 15 16 18 22 37 13) +p_cache=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) # Enabled/not +p_dir=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) # In/out +p_stat=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) # Powered/unpowered + +root=/sys/class/gpio + +p_id=0 # Pin ID +p_en=0 # Pin enabled +p_in=0 # Pin dir (in=1/out=0) + +messages=() # max 4 lines +latestdatest="" + +## Colors +c_pre="\e[38;5;" +c_default="${c_pre}15m" +c_disabled="${c_pre}244m" +c_dim="${c_pre}33m" +c_off="${c_pre}202m" +c_on="${c_pre}118m" +c_in="${c_pre}45m" +c_pink="${c_pre}207m" +c_purple="${c_pre}141m" +c_warn="${c_pre}11m" +c_ok="${c_pre}10m" +c_err="${c_pre}9m" +rst="\e[0m" +## + +trap ctrlc INT +function ctrlc() { + tput cub 99 + echo "`tput setaf 1`ctrl+c detected - exiting`tput sgr0`" + tput cnorm + exit 1 +} + +function log() { + upthedate + local words="[ ${latestdatest} ] ${1}" + local sev="$2" + local logs=${#messages[@]} + local maxlen=78 + local logcolor="${c_default}" + case $sev in + err) logcolor="${c_err}";; + warn) logcolor="${c_warn}";; + ok) logcolor="${c_ok}";; + esac + if [ $logs -ge 4 ]; then # Prune first message + # A loop would be smarter, but this is quicker + messages[0]=${messages[1]} + messages[1]=${messages[2]} + messages[2]=${messages[3]} + messages[3]="${logcolor}${words:0:$maxlen}${rst}" + else + messages[$logs]="${logcolor}${words:0:$maxlen}${rst}" + fi +} + +function upthedate(){ + latestdatest=`date "+%_I:%M:%S %P"` +} + +function showlogs() { + local line=23 + for i in `seq ${#messages[@]} -1 0`; do + tput cup $line 2 + tput el + [ -z "${messages[$i]}" ] || echo -en "${messages[$i]}" + let line=line-1 + done +} +function hidelogs() { + local line=22 + for i in `seq 1 4`; do + tput cup $line 0 + tput el + let line=line-1 + done +} +function invalidpin(){ + log "GPIO$1 is not a valid GPIO pin" "warn";showlogs +} +# Takes pin +# Returns enabled y/n +function checkpin() { + p_id=$1 + [[ "$p_id" == *"gpio"* ]] && p_id=${p_id:4} + if [ -d $root/gpio${p_id} ]; then + p_en=1 + p_cache[$p_id]=1 + if [[ `cat $root/gpio${p_id}/direction` == "in" ]]; then + p_in=1 + else + p_in=0 + p_stat[$p_id]=`cat $root/gpio${p_id}/value` + fi + p_dir[$p_id]=$p_in + else + zeroes $p_id + fi +} + +function zeroes(){ + p_id=$1 + p_en=0 + p_in=0 + p_cache[$p_id]=0 + p_dir[$p_id]=0 + p_stat[$p_id]=0 +} + +function enablepin() { + [ -z "$1" ] && return + [[ $1 -gt 27 || $1 -lt 2 ]] && invalidpin $1 && return + p_id=$1 + if [ ${p_cache[$p_id]} -eq 1 ]; then + log "Pin gpio$p_id is already enabled" "warn";showlogs + return; + fi + echo $p_id > $root/export + log "Enabling pin gpio$p_id" "ok";showlogs + sleep .05;setpindir "$p_id" "o" +} + +function disablepin() { + [ -z "$1" ] && return + [[ $1 -gt 27 || $1 -lt 2 ]] && invalidpin $1 && return + p_id=$1 + if [ ${p_cache[$p_id]} -eq 0 ]; then + log "Pin gpio$p_id is already disabled" "warn";showlogs;return + fi + echo $p_id > $root/unexport + zeroes $p_id + log "Disabling pin gpio$p_id" "ok";showlogs +} + +function turnonpin() { + [ -z "$1" ] && return + [[ $1 -gt 27 || $1 -lt 2 ]] && invalidpin $1 && return + p_id=$1 + if [ ! -d $root/gpio${p_id} ]; then + log "Pin gpio$p_id is not enabled" "warn";showlogs;return + fi + if [ ${p_stat[$p_id]} -eq 1 ]; then + log "Pin gpio$p_id is already powered" "warn";showlogs;return + fi + [[ ${p_cache[$p_id]} -eq 1 && ${p_dir[$p_id]} -eq 0 ]] && echo 1 > $root/gpio${p_id}/value + log "Powering pin gpio$p_id" "ok";showlogs +} + +function turnoffpin() { + [ -z "$1" ] && return + [[ $1 -gt 27 || $1 -lt 2 ]] && invalidpin $1 && return + p_id=$1 + if [ ! -d $root/gpio${p_id} ]; then + log "Pin gpio$p_id is not enabled" "warn";showlogs;return + fi + if [ ${p_stat[$p_id]} -eq 0 ]; then + log "Pin gpio$p_id is already off" "warn";showlogs;return + fi + [[ ${p_cache[$p_id]} -eq 1 && ${p_dir[$p_id]} -eq 0 ]] && echo 0 > $root/gpio${p_id}/value + log "Unpowering pin gpio$p_id" "ok";showlogs +} + +function setpindir() { + [ -z "$1" ] && return;[ -z "$2" ] && return + [[ $1 -gt 27 || $1 -lt 2 ]] && invalidpin $1 && return + p_id=$1;p_dir=$2 + if [ ! -d $root/gpio${p_id} ]; then + log "Pin gpio$p_id is not enabled" "warn";showlogs;return + fi + case $p_dir in + o) echo out > $root/gpio${p_id}/direction;log "Setting pin gpio$p_id as output" "ok";showlogs;; + i) echo in > $root/gpio${p_id}/direction;log "Setting pin gpio$p_id as input" "ok";showlogs;; + *) log "$p_dir is not a valid direction" "warn";showlogs;; + esac +} + +function refreshpins() { + if [ ! -d $root ]; then + tput rmcup;echo "`tput setaf 1`No gpio detected. Send help.`tput sgr0`";exit 1 + fi + + for _pin in `ls $root`; do # Check for enabled pins + if [[ "$_pin" == "gpio"* && "$_pin" != *"chip"* ]]; then + checkpin $_pin + fi + done + + for _pin in ${p_list[@]}; do # Check for disabled pins + if [ ${p_cache[$_pin]} -eq 1 ]; then + [ -d $root/gpio${_pin} ] || zeroes $_pin + fi + done +} + +function printkey() { + tput cup 0 2 + echo -en "Color key:" + tput cup 0 16 + echo -en "${c_disabled}pin disabled${rst}" + tput cup 0 33 + echo -en "${c_in}pin in${rst}" + tput cup 0 45 + echo -en "${c_on}pin out -> on${rst}" + tput cup 0 63 + echo -en "${c_default}pin out -> off${rst}" +} + +function display() { +tput sc +printkey +tput civis +# tput cup down over +tput cup 2 2 + for i in `seq 0 ${#p_list[@]}`; do + _p=${p_list[i]} + [[ "$_p" == "0" || -z $_p ]] && continue + [[ "$_p" == "15" ]] && tput cup 3 2 + [ ${p_cache[i]} -eq 0 ] && _status=$c_disabled || _status=$c_default + [[ ${p_cache[i]} -eq 1 && ${p_dir[i]} -eq 1 ]] && _status=$c_in + [[ ${p_cache[i]} -eq 1 && ${p_dir[i]} -eq 0 && ${p_stat[i]} -eq 1 ]] && _status=$c_on + echo -en "${_status}" + [[ ${#_p} -lt 2 ]] && echo -n "[ $_p]" || echo -n "[$_p]" + echo -en "${rst} " + done + echo +tput rc +} + +function printmenu() { + tput civis + local opts="$1" + local oc="$2" + local line=$3 + tput cup $line 0 + # https://stackoverflow.com/a/28104488 + IFS=, + menubottom=$line + for opt in $opts; do + tput cuf $oc + echo "${opt}" + let menubottom="menubottom+1" + done + unset IFS +} + +function monitorpins() { + local mon + clearmenu 17 0 + hidelogs + tput cup 5 2 + echo -en "${c_dim}Monitoring pins${rst}" + tput cup 6 2 + echo -en "${c_disabled}Press q to stop${rst}" + #local loading=(". " ".. " "..." ".. ") + local loading=(". " " . " " ." " . ") + local lindex=0 + while [[ "$mon" != "q" ]]; do + echo -en "${c_disabled}${loading[$lindex]}${rst}" + read -n1 -t1 -s mon + refreshpins;display + tput cup 6 17 + let lindex=lindex+1 + [ $lindex -ge ${#loading[@]} ] && lindex=0 + done + showlogs + clearmenu 6 0 +} + +function mainmenu() { + tput civis + tput cup 5 4 + echo -e "${c_pink}-=-=-= Main Menu =-=-=-${rst}" + _over=3 + availablemainmenuoptions="e) enable pin,d) disable pin,p) power pin,u) unpower pin,i) set pin direction,r) refresh display,m) monitor gpio,h) help,q) quit" + printmenu "$availablemainmenuoptions" "$_over" 7 + mymenuspot=$menubottom + let mymenuspot="mymenuspot+1" + tput cup $mymenuspot $_over + echo -n "> " + tput el + tput cnorm + read -n1 mainmenuopt + case $mainmenuopt in + e) echo -en "${c_dim}nable${rst}";enablemenu;mainmenu;; + d) echo -en "${c_dim}isable${rst}";disablemenu;mainmenu;; + p) echo -en "${c_dim}ower${rst}";powermenu;mainmenu;; + u) echo -en "${c_dim}npower${rst}";unpowermenu;mainmenu;; + i) tput cub1;echo -en "${c_dim}d${rst}i${c_dim}rection${rst}";directmenu;mainmenu;; + r) echo -en "${c_dim}efresh${rst}";refreshpins; display;mainmenu;; + m) echo -en "${c_dim}onitor${rst}";monitorpins;mainmenu;; + h) helppls;mainmenu;; + q) tput rmcup;exit 0;; + *) log "$mainmenuopt is not a valid menu choice" "warn";showlogs;mainmenu;; + esac + tput rmcup +} + +function helppls(){ + clearmenu 17 0;hidelogs;tput cup 0 0;tput el;tput civis + tput cup 5 0;echo -en "\e[38;5;219m";tput rev + echo -n " " + echo -n "GPIO Monitor & Control Script" + echo -n " " + tput sgr0 + tput cup 6 18;echo -en "${c_pink}-=-=-= Help menu and about this tool =-=-=-${rst}" + tput cup 8 0 +cat << EOF + This tool was designed to be able to monitor and control, in real-time, + the GPIO pins on my pi zero without needing to write a special python + script for a quick test or check. + + The script functions as explained below: + + All menu options are single letters and are accepted without needing + to press enter. The only time enter is required is when multiple + characters may be necessary (e.g. entering a pin number). + + This program comes with no warranty and only interacts with the GPIO + pins on the pi. Anything connected to those pins is not the + responsibility of this script. + + Enjoy <3 +EOF + read -n1 -s + tput cup 5 0;tput el + tput cup 6 0;tput el + clearmenu 18 0;hidelogs;showlogs;printkey +} + +function clearmenu(){ + tput civis + local spot=5 + local menu=0 + [ -z $2 ] && menu=40 + local max=$1 + let max=max+1 + [ $max -gt 19 ] && max=19 + while [ $spot -lt $max ]; do + tput cup $spot $menu + tput el + let spot=spot+1 + done +} +function gpiodisclaimer() { + local offset=$1;local alpha;local beta + let alpha=8+offset + let beta=9+offset + tput cup $alpha 40;echo -en "This is the GPIO# not the physical" + tput cup $beta 40;echo -en "pin location." +} +function enablemenu() { + tput cup 5 40 + echo -en "${c_purple}-=-=-= Enable Pin =-=-=-${rst}" + tput cup 7 40;echo -en "Enter the pin ID you wish to enable." + gpiodisclaimer + tput cup 11 40;echo -n "> " + tput cnorm + read enpin + enablepin $enpin + clearmenu 11;refreshpins;display +} + +function disablemenu() { + tput cup 5 40 + echo -en "${c_purple}-=-=-= Disable Pin =-=-=-${rst}" + tput cup 7 40;echo -en "Enter the pin ID you wish to disable." + gpiodisclaimer + tput cup 11 40;echo -n "> " + tput cnorm + read dispin + disablepin $dispin + clearmenu 11;refreshpins;display +} + +function powermenu() { + tput cup 5 40 + echo -en "${c_purple}-=-=-= Power Pin =-=-=-${rst}" + tput cup 7 40;echo -en "Enter the pin ID you wish to turn on." + gpiodisclaimer + tput cup 11 40;echo -n "> " + tput cnorm + read powapin + turnonpin $powapin + clearmenu 11;refreshpins;display +} + +function unpowermenu() { + tput cup 5 40 + echo -en "${c_purple}-=-=-= Unpower Pin =-=-=-${rst}" + tput cup 7 40;echo -en "Enter the pin ID you wish to turn off." + gpiodisclaimer + tput cup 11 40;echo -n "> " + tput cnorm + read powapin + turnoffpin $powapin + clearmenu 11;refreshpins;display +} + +function directmenu() { + tput cup 5 40 + echo -en "${c_purple}-=-=-= Change Direction =-=-=-${rst}" # | LAST + tput cup 7 40;echo -en "Enter the pin ID you wish to set the" + tput cup 8 40;echo -en "direction of. This is the GPIO# not" + tput cup 9 40;echo -en "the physical pin location." + tput cup 11 40;echo -n "> " + tput cnorm + read dirpin + clearmenu 11 + tput cup 5 40 + echo -en "${c_purple}-=-=-= Change Direction =-=-=-${rst}" # | LAST + tput cup 7 40;echo -en "Enter the direction you would like this" + tput cup 8 40;echo -en "pin to go in." + tput cup 10 40;echo -n "o) output" + tput cup 11 40;echo -n "i) input" + tput cup 13 40;echo -n "> " + tput cnorm + read -n1 dirdir + setpindir $dirpin $dirdir + clearmenu 13;refreshpins;display +} + +tput smcup +refreshpins +display +mainmenu + +################################################ +#pi@pizero:/sys/class/gpio/gpio2 $ cat direction +#out + +#pi@pizero:/sys/class/gpio/gpio2 $ cat edge +#none + +#pi@pizero:/sys/class/gpio/gpio2 $ cat uevent + +#pi@pizero:/sys/class/gpio/gpio2 $ cat value +#0 + +# gp=/sys/class/gpio +# for pin in `ls $gp`; do if [[ "$pin" == "gpio"* && "$pin" != *"chip"* ]]; then dir=`cat $gp/$pin/direction`;[ `cat $gp/$pin/value` -eq 0 ] && echo "pin $pin ($dir) disabled" || echo "pin $pin ($dir) enabled";fi; done