#!/bin/bash

# dranch@trinnet.net

# 03/05/24 - Added rpi5 specific hw checks (PWM fan, RTC, power MIC output)
#          - added method to opt-in to CPU loading stage; various formatting improvements
# 01/30/23 - minor echo output improvements
# 04/11/22 - Added recognition of more RPI board revisions, made smarter; added Rpi camera detection
# 01/17/21 - fixed found and explicit path for vcgencmd, exit support and the schedutil scheduler
#          - updated the way to determine Rpi model; added finding bootloader ver; text formatting fixes
# 09/25/20 - Added more RPI hardware versions; removed hardcoding to vcgencmd
# 05/01/20 - Fixed bitmapping
# 09/26/19 - typos corrected; added examples of more Raspberry Pi boards
# 06/15/19 - corrected math precision for CtoF conversion; added vcgencmd binary check
# 06/14/19 - Added C to F conversion; added throttle bit translator and more information
#          - added CPU/GPU memory split
# 10/25/18 - Added power and max temp counter view
# 03/18/18 - Minor update
# 10/22/16 - Added showing broadcom firmware version
# 10/20/16 - show max possible clocking level
#          - improved comments

#Use if needed for troubleshooting
DEBUG=0

#Command line arguments
OPS="$1"

#-------------------------------------
# Main


echo -e "\nreview-rpi-cpu.sh : Read the script comments for lots of helpful details and URL on specific areas"
echo -e "\n   Options: loadcpu - initiate some CPU load to see CPU frequency ramp up and on-demand CPU fan "

echo -e "\nLearn more about vcgencmd details at:"
echo -e "    https://www.raspberrypi.org/documentation/raspbian/applications/vcgencmd.md"
echo -e "    https://elinux.org/RPI_vcgencmd_usage\n"

# vcgencmd is built into Raspberry Pi OS / Raspbian :: 
# Sources for vcgencmd are at https://github.com/raspberrypi/userland
which vcgencmd > /dev/null
if [ $? -ne 0 ]; then
   if [ -f /opt/vc/bin/vcgencmd ]; then
      VCGENCMD="/opt/vc/bin/vcgencmd"
      #This library path used for vcgencmd will probably also be needed
      export LD_LIBRARY_PATH=/opt/vc/lib
     else
      echo -e "vcgencmd not installed. Output will show errors and be very limited"
      echo -e "Run: apt-get install libraspberrypi-bin    to install this useful utility"
      exit 1
   fi
  else
     VCGENCMD="`which vcgencmd`"
fi

if [ $DEBUG -eq 1 ]; then
   whereis /opt/vc/bin/vcgencmd
fi

echo -e "\nCPU / GPU Memory split - reported ARM memory will be limited to 1GB due to known firmware limitations"
$VCGENCMD get_mem arm 
$VCGENCMD get_mem gpu

echo -e "\nTrue ARM Memory capacity in KB (round up to the next GB):"
free | grep "Mem:" | awk '{print $2}'

#overclock thread: http://www.raspberrypi.org/forums/viewtopic.php?f=29&t=6201&start=325#p173006

# In /config.txt
#
# default is
# ----------
# arm_freq=700
# core_freq=250
# sdram_freq=400
# over_voltage=0
#
#   I would suggest changing them in the order:
#   sdram_freq->400, core_freq->250, arm_freq->750, over_voltage->0 (this may need some of the previous 3 settings to be lowered to boot correctly).
#
#   As the corruption may cause the sdcard to not boot, you probably need to reimage the sdcard after each failure.


#How to underclock - differet hardware will support different minimum clocks
#  set to 1Mhz!
#  echo "powersave" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
#  echo 1000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq
#  cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq

# Ram Overclock
# -------------
# 500mhz on RAM is pushing it for nearly every Hynix (especially with no over-voltage for the RAM itself) and is conservative for Samsung

# SD cards
# -------------
#All of them 16GB's. Just booting up and entering lxde. No overvoltage. No change on gpu_freq, sdram_freq
#
#1. pny class 4 premium started to go funny and stopped working around
#arm_freq=850-860
#
#2. sandisk class 4 ultra started to go funny and stopped working around
#arm_freq=890-900
#
#3. sandisk class 10 ultra started to go funny and stopped working around
#arm_freq=930-940
#
#From these disks sandisk class 4 ultra had pretty neat mouse response improvements on
#arm_freq=882
#gpu_freq=294
#sdram_freq=400
#This thing actually got pretty usable without much mouse stuttering and midori got better on this setting. Hope someone's current rpi experience improve without overvolting

#https://www.raspberrypi.org/forums/viewtopic.php?f=63&t=147781&p=972822#p972790

echo -e "\nUnderstanding the Throttled bitmask (translated below)"
echo -e "   View count of any previous power under-voltage or over-temp events:"
echo -e "\n   Example: for a 0x50005 result, the different bit values translate to:"
echo -e "       bit"
echo -e "        0: currently under-voltage          : occurs when input voltage drops below 4.63V"
echo -e "        1: currently arm frequency capped   : occurs with temp > 80'C"
echo -e "                                            : over-temperature occurs with temp > 85'C"
echo -e "        2: currently throttled (any reason from above)"
echo -e "     -----"
echo -e "     3-15: Not covered yet"
echo -e "     -----"
echo -e "       16: under-voltage has occurred in the past"
echo -e "       17: arm frequency capped has occurred in the past"
echo -e "       18: throttling has occurred in the past\n"

echo "Read value (hex):"
$VCGENCMD get_throttled

#Rpi3 and older have 18bits
#Rpi3+ and newer use 20bits :: Rpi3+ starts silently throttling (slows CPU by 200Mhz) at 70C
#20bit - WIP
#echo -e "\nTranslation\nbit\n211111111110000000000\n098765432109876543210\n---------------------"
echo -e "\nThrottled translation bitmask\n1111111110000000000\n8765432109876543210\n-------------------"
which bc > /dev/null
if [ $? -eq 0 ]; then
   echo "obase=2;ibase=16;`$VCGENCMD get_throttled | awk -F\x '{print $2}'| tr [a-f] [A-F]`" | bc
  else
   echo -e "bc not installed.. will not show bitmap"
fi


echo -en "\nCurrent CPU speed govrenor: (valid is 'powersave', 'ondemand', 'schedutil'): "
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

echo -en "\nCurrent CPU frequency: "
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq

echo -en "Max allowed frequency: "
cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq

if [ "$OPS" == "cpuload" ]; then
   echo -e "\n   CPU loading enabled:"
   echo -e "\n   Max CPU clock confirmation: system will clock up to max CPU speed (turbo mode) by "
   echo -e "   loading the CPUs and then report new CPU frequency: "
   # 100000 - upped by order of magnitude to handle Rpi5 speed
   #  10000 - worked ok for Rpi4 and older
   for i in {1..100000} ; do set X 1; done && cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
   #Let the CPU load heatsoak hit
   sleep 1

  else
   echo -e "\n   CPU loading not enabled on the command line: not showing CPU frequency ramp-up"
fi

echo -en "\n\nSOC Temp (in Celsius) - DD.ddd -- throttling begins at 80C: "
cat /sys/class/thermal/thermal_zone0/temp

which bc > /dev/null
if [ $? -eq 0 ]; then
   echo -en "Calc'ed Temp in C: "
   echo "scale=2; (`cat /sys/class/thermal/thermal_zone0/temp` / 1000.0)" | bc -l
   echo -en "Calc'ed Temp in F: "
   echo "scale=2; (`cat /sys/class/thermal/thermal_zone0/temp` / 1000.0) * (9/5) + 32" | bc -l
  else
   echo -e "bc not installed.. will not calculate temp in F"
fi

echo -en "\nGPU temp: "
$VCGENCMD measure_temp

echo -e "\nDetermining Raspberry Pi hardware: "
echo -en "   "
cat /sys/firmware/devicetree/base/model
echo " "

echo -en "\n   Alternative #1 Raspberry Pi HW revision: (only works on Raspberry Pi OS / Raspbian): "
echo -e "   `cat /proc/cpuinfo | grep Revision`"
REVISION="`cat /proc/cpuinfo | grep Revision | awk '{print $3}'`"

echo -e "\n   See the following URLs for more details on decoding the hardware revision codes:"
echo -e "       https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md"
echo -e "       https://www.raspberrypi.com/documentation/computers/raspberry-pi.html (see the very bottom)"
echo -e "       https://elinux.org/RPi_HardwareHistory\n"
#
#http://www.raspberrypi-spy.co.uk/2012/09/checking-your-raspberry-pi-board-version/

echo -e "   Alternative #2 Raspberry Pi known hardware revision details based on your hardware code: $REVISION"
echo -en "      "

case $REVISION in 
   # Zero
   # ----
   900092)
         echo -e "      revision value of 900092 is: RPi 0 Model    rev 1.2    - Released Q4 2015 - 512MB - made at: Sony UK"
         ;;
   900093)
         echo -e "      revision value of 900093 is: RPi 0 Model    rev 1.3    - Released Q4 2016 - 512MB - made at: Sony UK"
         ;;
   920093)
         echo -e "      revision value of 920093 is: RPi 0 Model    rev 1.3    - Released Q4 2016 - 512MB - made at: Embest, China"
         ;;

   # Zero W
   #-----------
   9000c1)
         echo -e "      revision value of 9000c1 is: RPi 0 Model W  rev 1.1    - Released Q1 2017 - 512MB - made at: Sony UK"
         ;;

   # Zero2 W
   #-----------
   902120)
         echo -e "      revision value of 902120 is: RPi 0 Model 2W  rev 1.0  - Release Q4 2021 - 512MB - made at: Sony UK"
         ;;

   # Rpi 1A
   #-----------
   0007)
         echo -e "      revision value of   0007 is: RPi 1 Model A  rev 2.0  - Released Q1 2013 - 256MB - made at: Egoman"
         ;;
   0008)
         echo -e "      revision value of   0008 is: RPi 1 Model A  rev 2.0  - Released Q1 2013 - 256MB - made at: Sony UK"
         ;;
   0009)
         echo -e "      revision value of   0009 is: RPi 1 Model A  rev 2.0  - Released Q1 2013 - 256MB - made at: Qisda"
         ;;

   # Rpi 1B
   #-----------
   0002)
         echo -e "      revision value of   0002 is: RPi 1 Model B  rev 1.0  - Released Q1 2012 - 256MB - made at: Sony UK"
         ;;
   0003)
         echo -e "      revision value of   0003 is: RPi 1 Model B  rev 1.0  - Released Q3 2012 - 256MB - made at: Sony UK"
         ;;
   0004)
         echo -e "      revision value of   0004 is: RPi 1 Model B  rev 2.0  - Released Q3 2012 - 256MB - made at: Sony UK"
         ;;
   0005)
         echo -e "      revision value of   0005 is: RPi 1 Model B  rev 2.0  - Released Q4 2012 - 256MB - made at: Qisda"
         ;;
   0006)
         echo -e "      revision value of   0006 is: RPi 1 Model B  rev 2.0  - Released Q4 2012 - 256MB - made at: Egoman"
         ;;
   000d)
         echo -e "      revision value of   000d is: RPi 1 Model B  rev 2.0  - Released Q4 2012 - 512MB - made at: Egoman"
         ;;
   000e)
         echo -e "      revision value of   000e is: RPi 1 Model B  rev 2.0  - Released Q4 2012 - 512MB - made at: Sony UK"
         ;;
   000f)
         echo -e "      revision value of   000f is: RPi 1 Model B  rev 2.0  - Released Q4 2012 - 512MB - made at: Egoman / Qisda"
         ;;

   # Rpi 1A+
   #-----------
   0012)
         echo -e "      revision value of   0012 is: RPi 1 Model A+ rev 1.1  - Released Q4 2014 - 256MB - made at: Sony UK"
         ;;
   0015)
         echo -e "      revision value of   0015 is: RPi 1 Model A+ rev 1.1  - Released Q? ???? - 512MB - made at: Embest, China"
         ;;
   900021)
         echo -e "      revision value of 900021 is: RPi 1 Model A+ rev 1.1  - Released Q3 2016 - 512MB - made at: Sony UK"
         ;;

   # Rpi 1B+
   #-----------
   0010)
         echo -e "      revision value of   0010 is: RPi 1 Model B+ rev 1.0  - Released Q3 2014 - 512MB - made at: Sony UK"
         ;;
   0013)
         echo -e "      revision value of   0013 is: RPi 1 Model B+ rev 1.2  - Released Q1 2015 - 512MB - made at: Embest, China"
         ;;
   900032)
         echo -e "      revision value of 900032 is: RPi 1 Model B+ rev 1.2  - Released Q2 2016 - 512MB - made at: Sony UK"
         ;;

   # Rpi CM1
   #-----------
   0011)
         echo -e "      revision value of   0011 is: RPi 1 Model CM1 rev 1.0  - Released Q2 2014 - 512MB - made at: Sony UK"
         ;;
   0014)
         echo -e "      revision value of   0014 is: RPi 1 Model CM1 rev 1.0  - Released Q2 2014 - 512MB - made at: Embest, China"
         ;;

   # Rpi 2B
   #-----------
   a01040)
         echo -e "      revision value of a01040 is: RPi 2 Model B  rev 1.0                - Released Q? ???? -   1GB - made at: Sony UK"
         ;;
   a01041)
         echo -e "      revision value of a01041 is: RPi 2 Model B  rev 1.1                - Released Q1 2015 -   1GB - made at: Sony UK"
         ;;
   a02042)
         echo -e "      revision value of a02042 is: RPi 2 Model B (new BCM2837)  rev 1.2  - Released Q3 2016 -   1GB - made at: Sony UK"
         ;;
   a21041)
         echo -e "      revision value of a21041 is: RPi 2 Model B  rev 1.1                - Released Q1 2015 -   1GB - made at: Embest, China"
         ;;
   a22042)
         echo -e "      revision value of a22042 is: RPi 2 Model B (new BCM2837)  rev 1.2  - Released Q3 2016 -   1GB - made at: Embest, China"
         ;;

   # Rpi 3A
   #-----------
   #echo -e "      revision value of ?????? is: RPi 3 Model A   -   1GB"

   # Rpi 3B
   #-----------
   a02082)
         echo -e "      revision value of a02082 is: RPi 3 Model B  rev 1.2    - Released Q1 2016 -   1GB - made at: Sony, Japan"
         ;;
   a22082)
         echo -e "      revision value of a22082 is: RPi 3 Model B  rev 1.2    - Released Q4 2016 -   1GB - made at: Embest, China"
         ;;
   a22083)
         echo -e "      revision value of a22083 is: RPi 3 Model B  rev 1.3    - Released Q? ???? -   1GB - made at: Embest, China"
         ;;
   a32082)
         echo -e "      revision value of a32082 is: RPi 3 Model B  rev 1.2    - Released Q4 2016 -   1GB - made at: Sony, Japan"
         ;;
   a52082)
         echo -e "      revision value of a52082 is: RPi 3 Model B  rev 1.2    - Released Q? ???? -   1GB - made at: Stadium"
         ;;

   # Rpi CM3
   #-----------
   a020a0)
         echo -e "      revision value of a020a0 is: RPi 3 Model CM3  rev 1.0 - Released Q1 2017 -   1GB - made at: Sony UK"
         ;;
   a220a0)
         echo -e "      revision value of a220a0 is: RPi 3 Model CM3  rev 1.0 - Released Q1 2017 -   1GB - made at: Embest, China"
         ;;

   # Rpi 3A+
   #-----------
   9020e0)
         echo -e "      revision value of 9020e0 is: RPi 3 Model A+ rev 1.0   - Released Q4 2018 - 512MB - made at: Sony UK"
         ;;

   # Rpi 3B+
   #-----------
   a020d3)
         echo -e "      revision value of a020d3 is: RPi 3 Model B+ rev 1.3   - Released Q1 2018 -   1GB - made at: Sony UK"
         ;;

   # Rpi CM3+
   #-----------
   a02100)
         echo -e "      revision value of a02100 is: RPi 3 Model CM3+ rev 1.0 - Released Q1 2019 -   1GB - made at: Sony UK"
         ;;

   # Rpi 4B
   #  v1.2 boards have USB-C power fix
   #  v1.3 boards were never relased
   #  v1.4 boards are only for the 8GB version
   #  v1.5 boards - ?
   #-----------
   a03111)
         echo -e "      revision value of a03111 is: RPi 4 Model B  rev 1.1   - Released Q2 2019 -   1GB - made at: Sony UK"
         ;;
   b03111)
         echo -e "      revision value of b03111 is: RPi 4 Model B  rev 1.1   - Released Q2 2019 -   2GB - made at: Sony UK"
         ;;
   b03112)
         echo -e "      revision value of b03112 is: RPi 4 Model B  rev 1.2   - Released Q2 2019 -   2GB - made at: Sony UK"
         ;;
   b03114)
         echo -e "      revision value of b03114 is: RPi 4 Model B  rev 1.4   - Released Q2 2020 -   2GB - made at: Sony UK"
         ;;
   b03115)
         echo -e "      revision value of b03114 is: RPi 4 Model B  rev 1.5   - Released Q2 2023 -   2GB - made at: Sony UK"
         ;;
   c03111)
         echo -e "      revision value of c03111 is: RPi 4 Model B  rev 1.1   - Released Q2 2019 -   4GB - made at: Sony UK"
         ;;
   c03112)
         echo -e "      revision value of c03112 is: RPi 4 Model B  rev 1.2   - Released Q2 2019 -   4GB - made at: Sony UK"
         ;;
   c03114)
         echo -e "      revision value of c03114 is: RPi 4 Model B  rev 1.4   - Released Q2 2020 -   4GB - made at: Sony UK"
         ;;
   d03114)
         echo -e "      revision value of d03114 is: RPi 4 Model B  rev 1.4   - Released Q2 2020 -   8GB - made at: Sony UK"
         ;;

   # Rpi 400
   #-----------
   c03130)
         echo -e "      revision value of c03130 is: RPi 400        rev 1.0   - Released Q? ???? -   4GB - made at: Sony UK"
         ;;

   *)
         echo -n "unknown"
         ;;
esac


echo -e "\n\nRpi Serial number, model firmware and Waranty bit (MSB - see in-script code comments for details): "
#This only applied for older Rpis
#echo "   LSB shows board revisions"
#echo "   MSB shows the warantee bit"
# below shows a VOIDed unit"
# Revision        : 1000002

#Old way
#cat /proc/cpuinfo  | grep Serial
#New way
echo -en "   "
cat /sys/firmware/devicetree/base/serial-number
echo " "

#Determine the model of Rpi hardware
#
RPI_MODULE="`cat /sys/firmware/devicetree/base/model | awk '{print $3}'`"

if [ "$RPI_MODULE" == "5" ]; then
   echo -e "\nRpi 5 hardware specific details"
   echo -e "-------------------------------"

   #Test if Rpi5fan+tach is present
   ls /sys/devices/platform/cooling_fan/hwmon/*/fan1_input > /dev/null 2>&1
   if [ $? -eq 0 ]; then
     echo -en "\n   Rpi5 only fan RPM reading (value of 0 means the fan isn't spinning right now): "
     echo -e "   `cat /sys/devices/platform/cooling_fan/hwmon/*/fan1_input` RPM"
     if [ "$OPS" != "cpuload" ]; then
        echo -e "      CPU loading NOT enabled.  Consider enabling on command line to confirm the Rpi5 fan or temp controlled FAN spins"
     fi
   fi

   echo -e "\n   Rpi 5 only power (voltage / current) PMIC readings:"
   echo -e "   ---------------------------------------------------"
   echo -en "      Input 5v rail voltage: "
   $VCGENCMD pmic_read_adc  | grep EXT5V_V | awk -F= '{print $2}'
   echo -en "      Input 5v rail current: "
   $VCGENCMD pmic_read_adc  | grep VDD_CORE_A | awk -F= '{print $2}'
   echo -en "      RTC 3.3v voltage:      "
   $VCGENCMD pmic_read_adc  | grep BATT_V | awk -F= '{print $2}'
fi


echo -e "\nBroadcom firmware version:"
echo -e "--"
$VCGENCMD version
echo -e "\nBroadcom bootloader version (Rpi4 and newer hardware only):"
echo -e "--"
$VCGENCMD bootloader_version

echo -e "\nChecking for any found Raspberry Pi cameras connected via CSI connector:"
$VCGENCMD get_camera >/dev/null 2>&1
if [ $? -eq 0 ]; then
   $VCGENCMD get_camera 
   v4l2-ctl --list-devices 2>&1 | grep v4l2
   #
   # You can list all supported formats and resolutions with
   #  v4l2-ctl -d /dev/video0 --list-formats-ext
  else
   echo -e "   - No camera found"
fi


# this will void the warranty
# (force_turbo || current_limit_override || temp_limit>85) && over_voltage>0

echo -e "\nDone\n"
