Last active
April 29, 2025 11:21
-
-
Save mininmobile/e2c433eb39d3856d3268fb1c10aa7446 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/ash | |
# usage: rainbowd [--help|-h|--version|-V|options...] | |
# | |
# --fork do not read or write pid file (FORK=true) | |
# --dump print initialized color buffer and exit (DUMP_FRAME=true) | |
# --verbose -v print color buffer table (DEBUG=true) | |
# --loop -L play animations, rotate by default (LOOP=true) | |
# --no-loop -l only render first frame (LOOP=false) | |
# --reverse -r reverse animations (REVERSE=true) | |
# --fade -F play fade animation (FADE=true) | |
# --blink -B play blink animation | |
# | |
# --dim(-[0123])? set led intesity (DIM_LED=[0123]) based on ambient light (DIM_LED=true) | |
# --no-dim -d do not set led intesity (DIM_LED=false) | |
# --invert invert the color buffer (INVERT=true) | |
# --brightness -b dim the color buffer (0-1.0) | |
# --timeout -t time in secs to wait before killing self | |
# --interval -i time in secs to wait between updates | |
# | |
# --nop -n do not reset color buffer | |
# --clear -C fill color buffer with "blank" color | |
# --color -c fill color buffer with color | |
# --bg fill "blank" color buffer with color | |
# --spinner -s append color to hind of color buffer | |
# --frame -f set color buffer (12 hex colors with no spaces) | |
# --pastel use pastel rainbow color palette | |
# | |
# misc env vars: IO_RING IO_AMBIENT IO_LED_DIM | |
# | |
# rainbow_daemon.sh v0.9 | |
# [email protected] | |
# default pattern (12 hex colors) | |
frame='0000ff0000ff4f00cf4f00cfff0000ff0000af2f00af2f00ffff00ffff0000ff0000ff00' | |
# misc defaults | |
[ -z "$DEBUG" ] && DEBUG=false | |
[ -z "$DUMP_FRAME" ] && DUMP_FRAME=false | |
[ -z "$LOOP" ] && LOOP=true | |
[ -z "$DIM_LED" ] && DIM_LED=true | |
brightness='1' | |
interval='0.1' | |
blank_frame='000000000000000000000000000000000000000000000000000000000000000000000000' | |
# devices: led array; ambient light sensor; led power | |
[ -z "$IO_RING" ] && IO_RING='/sys/bus/i2c/devices/0-003f/frame' | |
[ -z "$IO_AMBIENT" ] && IO_AMBIENT='/sys/bus/iio/devices/iio:device0/calibrated_lux' | |
[ -z "$IO_LED_DIM" ] && IO_LED_DIM='/sys/bus/i2c/devices/0-003f/led_current' | |
while [ $# -gt 0 ]; do case $1 in | |
"--help" | "-h") sed -n "/^# usage/,/^# ~/p" "$(which $0)" | sed -E 's/(# |#)//'; exit ;; | |
"--version" | "-V") grep "rainbow_daemon.sh\sv" "$(which $0)" | sed -E 's/(# |#)//'; exit ;; | |
"--fork" ) FORK=true; shift ;; | |
"--dump" ) DUMP_FRAME=true; shift ;; | |
"--verbose" | "-v") DEBUG=true; shift ;; | |
"--loop" | "-L") LOOP=true; shift ;; | |
"--no-loop" | "-l") LOOP=false; shift ;; | |
"--reverse" | "-r") REVERSE=true; shift ;; | |
"--blink" | "-B") blink=true; shift ;; | |
"--fade" | "-F") FADE=true; shift ;; | |
"--dim" ) DIM_LED=true; shift ;; "--dim-0") DIM_LED=0; shift ;; "--dim-1") DIM_LED=1; shift ;; "--dim-2") DIM_LED=2; shift ;; "--dim-3") DIM_LED=3; shift ;; | |
"--no-dim" | "-d") DIM_LED=false; shift ;; | |
"--invert" ) INVERT=true; shift ;; | |
"--brightness" | "-b") brightness=$2; shift 2 ;; | |
"--interval" | "-i") interval=$2; shift 2 ;; | |
"--timeout" | "-t") timeout=$2; shift 2 ;; | |
"--nop" | "-n") LOOP=false; frame=$(cat /sys/bus/i2c/devices/0-003f/frame); blank_frame=$frame; shift ;; | |
"--clear" | "-C") LOOP=false; blink=false; frame=$blank_frame; shift ;; | |
"--color" | "-c") LOOP=false; frame=$(seq 12 | awk "{printf \"$2\"}"); shift 2 ;; | |
"--bg" ) blank_frame=$(seq 12 | awk "{printf \"$2\"}"); shift 2;; | |
"--spinner" | "-s") LOOP=true; frame=$2$blank_frame; shift 2 ;; | |
"--frame" | "-f") frame=$2; shift 2 ;; | |
"--pastel") frame='881177aa3355cc6666ee9944eedd0099dd5544dd8822ccbb00bbcc0099cc3366bb663399'; blank_frame=$frame; shift ;; | |
*) echo "unknown argument: $1"; exit ;; | |
esac; done | |
# helper functions | |
transcolor() { | |
r=$(printf "%02x" $(printf "($2)/1" 0x$(echo $1 | cut -c 1-2) | bc)) | |
g=$(printf "%02x" $(printf "($2)/1" 0x$(echo $1 | cut -c 3-4) | bc)) | |
b=$(printf "%02x" $(printf "($2)/1" 0x$(echo $1 | cut -c 5-6) | bc)) | |
echo -n "$r$g$b" | |
} | |
darken() { transcolor $1 "%d*$2"; } | |
invert() { transcolor $1 "255-%d"; } | |
invertframe() { for i in $(seq 1 12); do echo -n $(invert $(echo $1 | cut -c $(( i*6 - 5 ))-$(( i*6 ))) $2); done; } | |
darkenframe() { for i in $(seq 1 12); do echo -n $(darken $(echo $1 | cut -c $(( i*6 - 5 ))-$(( i*6 ))) $2); done; } | |
# debug functions | |
printc() { | |
r=$(printf "%d" 0x$(echo $1 | cut -c 1-2)) | |
g=$(printf "%d" 0x$(echo $1 | cut -c 3-4)) | |
b=$(printf "%d" 0x$(echo $1 | cut -c 5-6)) | |
echo -n "\033[48;2;${r};${g};${b}m \033[0m" | |
} | |
printframe() { | |
for i in $(seq 1 12); do echo -n $(printc $(echo $1 | cut -c $(( i*6 - 5 ))-$(( i*6 )))); done | |
echo -n "\033[0m" | |
} | |
# init rainbowd | |
# * get initial color buffer | |
frame=$(echo $frame | cut -c -72) | |
[ "$DEBUG" = true ] && echo -e "< $(printframe $frame)" & | |
# → apply invert filer | |
[ "$INVERT" = true ] && { frame=$(invertframe $frame) | |
[ "$DEBUG" = true ] && echo -e "* $(printframe $frame)" & | |
} # → apply darken filer | |
[ ! "$brightness" = 1 ] && { frame=$(darkenframe $frame $brightness) | |
[ "$DEBUG" = true ] && echo -e "* $(printframe $frame)" & | |
} | |
[ "$DUMP_FRAME" = true ] && { echo "$frame"; exit; } | |
# * replace previous instance of rainbowd | |
if [ -z "$FORK" ]; then | |
if [ -e /run/rainbow_daemon.pid ] && [ -d /proc/$(cat /run/rainbow_daemon.pid) ]; then | |
kill -9 $(cat /run/rainbow_daemon.pid) | |
fi | |
echo $$ > /run/rainbow_daemon.pid | |
fi | |
# * set timeout | |
if [ -n "$timeout" ]; then | |
{ sleep $timeout; kill -9 $$; rainbowd --fork --clear; } & | |
fi | |
# * set led brightness | |
case "$DIM_LED" in | |
0|1|2|3) echo $DIM_LED > $IO_LED_DIM ;; | |
esac | |
# blink animation | |
if [ "$blink" = true ]; then while true; do | |
FORK=true DEBUG=$DEBUG LOOP=false DIM_LED=$DIM_LED INVERT=$INVERT rainbowd --frame $blank_frame | |
sleep $interval | |
FORK=true DEBUG=$DEBUG LOOP=false DIM_LED=$DIM_LED INVERT=$INVERT rainbowd --frame $frame | |
sleep $interval | |
done; exit; fi | |
# render | |
i=12 | |
while true; do | |
if [ $i = 12 ] && [ "$DIM_LED" = true ]; then | |
ambient=$(cat $IO_AMBIENT) | |
if [ $ambient -gt 300 ]; then echo 0 > $IO_LED_DIM | |
elif [ $ambient -gt 200 ]; then echo 1 > $IO_LED_DIM | |
elif [ $ambient -gt 100 ]; then echo 2 > $IO_LED_DIM | |
else echo 3 > $IO_LED_DIM | |
fi | |
fi | |
i=$((i-1)) | |
[ $i -le 1 ] && i=12 | |
shift=000000 | |
if [ "$LOOP" = true ]; then | |
if [ "$REVERSE" = true ]; then | |
shift=$(echo $frame | cut -c 67-72) | |
frame=$(echo "${shift}${frame}" | cut -c -72) | |
else | |
shift=$(echo $frame | cut -c 1-6) | |
frame=$(echo "${frame}${shift}" | cut -c 7-78) | |
fi | |
fi | |
if [ "$FADE" = true ]; then | |
[ ! "$LOOP" = true ] && { [ "$REVERSE" = true ] && shift=$(echo $frame | cut -c 67-72) || shift=$(echo $frame | cut -c 1-6); } | |
currentcolor=$(seq 12 | awk "{printf \"$shift\"}") | |
echo "$currentcolor" > $IO_RING | |
[ "$DEBUG" = true ] && echo -e "+ $(printc $shift) = $(printframe $currentcolor)" & | |
else | |
echo "$frame" > $IO_RING | |
[ "$DEBUG" = true ] && [ "$LOOP" = true ] && echo -e "+ $(printc $shift) = $(printframe $frame)" & | |
fi | |
[ ! "$LOOP" = true ] && exit | |
sleep $interval | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment