commit
6ca0deda2c
4 changed files with 297 additions and 0 deletions
@ -0,0 +1,117 @@ |
|||||
|
# Check if running as root |
||||
|
if [[ $EUID -ne 0 ]]; then |
||||
|
echo "This script must be run as root. Use sudo ./setup_tft.sh" |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
# Define the configuration file path |
||||
|
CONFIG_FILE="/boot/firmware/config.txt" |
||||
|
if [ ! -f "$CONFIG_FILE" ]; then |
||||
|
CONFIG_FILE="/boot/config.txt" |
||||
|
fi |
||||
|
|
||||
|
update_config() { |
||||
|
local key=$1 |
||||
|
local value=$2 |
||||
|
|
||||
|
# Check if the line already exists |
||||
|
if grep -q "^$key" "$CONFIG_FILE"; then |
||||
|
# Remove any preceding # and update value if necessary |
||||
|
sed -i "s/^#$key/$key/" "$CONFIG_FILE" |
||||
|
if [ -n "$value" ]; then |
||||
|
sed -i "s|^$key.*|$key=$value|" "$CONFIG_FILE" |
||||
|
fi |
||||
|
else |
||||
|
# Add the line if it doesn't exist |
||||
|
if [ -z "$value" ]; then |
||||
|
echo "$key" >> "$CONFIG_FILE" |
||||
|
else |
||||
|
echo "$key=$value" >> "$CONFIG_FILE" |
||||
|
fi |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
remove_duplicates() { |
||||
|
local file=$1 |
||||
|
# Retain line breaks and remove duplicate lines |
||||
|
awk '!seen[$0]++' "$file" > "${file}.tmp" |
||||
|
mv "${file}.tmp" "$file" |
||||
|
} |
||||
|
|
||||
|
# Comment the line max_framebuffers=2 if it exists |
||||
|
if grep -q "^max_framebuffers=2" "$CONFIG_FILE"; then |
||||
|
sed -i "s|^max_framebuffers=2|#max_framebuffers=2 (line commented for TFT ILI9488 installation on $(date +%m/%d/%Y))|" "$CONFIG_FILE" |
||||
|
fi |
||||
|
|
||||
|
# Comment the dtoverlay=vc4-kms-v3d line |
||||
|
sed -i "s|^dtoverlay=vc4-kms-v3d|#dtoverlay=vc4-kms-v3d (line commented for TFT ILI9488 installation on $(date +%m/%d/%Y))|" "$CONFIG_FILE" |
||||
|
|
||||
|
# Add required configuration lines |
||||
|
echo "#Modifications for ILI9488 installation implemented by the script on $(date +%m/%d/%Y)" >> "$CONFIG_FILE" |
||||
|
update_config "dtoverlay" "spi0-0cs" |
||||
|
update_config "dtparam" "spi=on" |
||||
|
update_config "hdmi_force_hotplug" "1" |
||||
|
update_config "hdmi_cvt" "480 320 60 1 0 0 0" |
||||
|
update_config "hdmi_group" "2" |
||||
|
update_config "hdmi_mode" "87" |
||||
|
update_config "framebuffer_width" "480" |
||||
|
update_config "framebuffer_height" "320" |
||||
|
update_config "dtoverlay" "fbtft_device,name=ili9488,rotate=0,fps=30,speed=16000000" |
||||
|
update_config "dtparam" "dc_pin=22" |
||||
|
update_config "dtparam" "reset_pin=11" |
||||
|
update_config "gpu_mem" "128" |
||||
|
echo "# Utilized for TFT ILI9488 setup script by AdamoMD" >> "$CONFIG_FILE" |
||||
|
echo "# https://github.com/adamomd/4inchILI9488RpiScript/" >> "$CONFIG_FILE" |
||||
|
echo "# Feel free to send feedback and suggestions." >> "$CONFIG_FILE" |
||||
|
|
||||
|
# Remove duplicates in config.txt |
||||
|
echo "Removing duplicate lines in config.txt..." |
||||
|
remove_duplicates "$CONFIG_FILE" |
||||
|
|
||||
|
# Configure sudoers for fbcp-ili9341 |
||||
|
echo "Setting permissions in sudoers..." |
||||
|
VISUDO_FILE="/etc/sudoers.d/fbcp-ili9341" |
||||
|
if [ ! -f "$VISUDO_FILE" ]; then |
||||
|
echo "ALL ALL=(ALL) NOPASSWD: /usr/local/bin/fbcp-ili9341" > "$VISUDO_FILE" |
||||
|
chmod 440 "$VISUDO_FILE" |
||||
|
fi |
||||
|
|
||||
|
# Set binary permissions |
||||
|
echo "Configuring permissions for fbcp-ili9341..." |
||||
|
chmod u+s /usr/local/bin/fbcp-ili9341 |
||||
|
|
||||
|
# Configure rc.local to start fbcp-ili9341 |
||||
|
echo "Configuring /etc/rc.local..." |
||||
|
RC_LOCAL="/etc/rc.local" |
||||
|
if [ ! -f "$RC_LOCAL" ]; then |
||||
|
cat <<EOT > "$RC_LOCAL" |
||||
|
#!/bin/bash |
||||
|
# rc.local |
||||
|
# This script is executed at the end of each multi-user runlevel. |
||||
|
|
||||
|
# Start fbcp-ili9341 |
||||
|
/usr/local/bin/fbcp-ili9341 >> /var/log/fbcp-ili9341.log 2>&1 & |
||||
|
|
||||
|
exit 0 |
||||
|
EOT |
||||
|
chmod +x "$RC_LOCAL" |
||||
|
else |
||||
|
if ! grep -q "fbcp-ili9341" "$RC_LOCAL"; then |
||||
|
sed -i '/exit 0/i \\n# Start fbcp-ili9341\n/usr/local/bin/fbcp-ili9341 >> /var/log/fbcp-ili9341.log 2>&1 &' "$RC_LOCAL" |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
# Remove duplicates in rc.local |
||||
|
echo "Removing duplicate lines in rc.local..." |
||||
|
remove_duplicates "$RC_LOCAL" |
||||
|
|
||||
|
# Enable and start rc.local service |
||||
|
echo "Enabling rc.local service..." |
||||
|
sudo chmod +x /etc/rc.local |
||||
|
sudo systemctl enable rc-local |
||||
|
sudo systemctl start rc-local |
||||
|
|
||||
|
# Finish and force reboot |
||||
|
echo "Finalizing processes..." |
||||
|
killall -9 fbcp-ili9341 2>/dev/null || true |
||||
|
sync |
||||
@ -0,0 +1,84 @@ |
|||||
|
#raspOS Bookworm lite |
||||
|
|
||||
|
#screen support |
||||
|
# Enable SPI using raspi-config |
||||
|
echo "Enabling SPI interface using raspi-config..." |
||||
|
raspi-config nonint do_spi 0 |
||||
|
|
||||
|
# Update system and install dependencies |
||||
|
echo "Updating the system and installing dependencies..." |
||||
|
apt update && apt upgrade -y |
||||
|
apt install -y cmake git build-essential nano |
||||
|
|
||||
|
#build deps and remove raspi features |
||||
|
sudo apt install -y libraspberrypi-dev |
||||
|
git clone https://github.com/juj/fbcp-ili9341.git |
||||
|
cd fbcp-ili9341 |
||||
|
mkdir build && cd build |
||||
|
|
||||
|
#append to fix -DDISPLAY_INVERT_COLORS=ON -DSTATISTICS=0 |
||||
|
cmake -DUSE_GPU=ON -DSPI_BUS_CLOCK_DIVISOR=12 -DGPIO_TFT_DATA_CONTROL=25 -DGPIO_TFT_RESET_PIN=17 -DILI9488=ON -DUSE_DMA_TRANSFERS=OFF -DDISPLAY_INVERT_COLORS=ON -DSTATISTICS=0 .. |
||||
|
make -j$(nproc) |
||||
|
sudo install fbcp-ili9341 /usr/local/bin/ |
||||
|
./config.sh |
||||
|
|
||||
|
#make autologin |
||||
|
sudo su |
||||
|
mkdir -pv /etc/systemd/system/[email protected] |
||||
|
#nano /etc/systemd/system/[email protected]/autologin.conf |
||||
|
cat <<EOT > /etc/systemd/system/[email protected]/autologin.conf |
||||
|
[Service] |
||||
|
ExecStart= |
||||
|
ExecStart=-/sbin/agetty --autologin gsd --noclear %I $TERM |
||||
|
EOT |
||||
|
|
||||
|
#Xserver and chromium |
||||
|
apt install -y --no-install-recommends xserver-xorg x11-xserver-utils xinit chromium-browser |
||||
|
|
||||
|
cat <<EOT >> /home/gsd/.bashrc |
||||
|
|
||||
|
# Автозапуск X сервера при логине в tty1 |
||||
|
if [ -z "$DISPLAY" ] && [ $(tty) = /dev/tty1 ]; then |
||||
|
startx -- -nocursor |
||||
|
fi |
||||
|
EOT |
||||
|
|
||||
|
cat <<EOT > /home/gsd/.xinitrc |
||||
|
#!/bin/sh |
||||
|
|
||||
|
# Ждем сеть |
||||
|
#while ! ping -c1 google.com &>/dev/null; do |
||||
|
# sleep 1 |
||||
|
#done |
||||
|
|
||||
|
# Настройки отключения энергосбережения |
||||
|
xset s off |
||||
|
xset -dpms |
||||
|
xset s noblank |
||||
|
|
||||
|
# Запуск Chromium |
||||
|
exec chromium-browser --no-memcheck --noerrdialogs --disable-infobars --disable-background-timer-throttling --disable-renderer-backgrounding --disable-backgrounding-occluded-windows --check-for-update-interval=31536000 --no-first-run --kiosk http://tf2.pblr-nyk.pro |
||||
|
EOT |
||||
|
|
||||
|
#uart |
||||
|
|
||||
|
cat <<EOT >> /boot/firmware/config.txt |
||||
|
dtoverlay=disable-bt |
||||
|
enable_uart=1 |
||||
|
dtoverlay=uart0 |
||||
|
EOT |
||||
|
|
||||
|
sudo systemctl stop [email protected] |
||||
|
sudo systemctl disable [email protected] |
||||
|
sudo apt install python3-serial |
||||
|
|
||||
|
#sound https://withrow.io/simpsons-tv-build-guide-waveshare#parts-list |
||||
|
dtparam=audio=on |
||||
|
dtoverlay=audremap,enable_jack,pins_18_13 |
||||
|
#dtparam=audio=off |
||||
|
# dtparam=audio=on # закомментируйте или удалите эту строку |
||||
|
#dtoverlay=pwm-2chan,pin=18,func=2,pin2=13,func2=4 |
||||
|
#apt install git build-essential autoconf automake libtool libasound2-dev |
||||
|
|
||||
|
#rtc |
||||
|
#sudo apt-get install -y i2c-tools |
||||
@ -0,0 +1,32 @@ |
|||||
|
const int input[] = {36, 39, 34 ,35 ,32 ,33 ,25 ,26}; |
||||
|
int inputValue[] = {0, 0, 0, 0, 0, 0, 0, 0}; |
||||
|
const int numPins = sizeof(input) / sizeof(input[0]); |
||||
|
|
||||
|
#define RXD2 (16) |
||||
|
#define TXD2 (17) |
||||
|
|
||||
|
void setup() { |
||||
|
//Serial.begin(115200);
|
||||
|
Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2); |
||||
|
analogReadResolution(12); |
||||
|
analogSetAttenuation(ADC_11db); |
||||
|
} |
||||
|
|
||||
|
void values2uart() { |
||||
|
for (int i = 0; i < numPins; i++) { |
||||
|
Serial2.print(input[i]); |
||||
|
Serial2.print("-"); |
||||
|
Serial2.print(inputValue[i]); |
||||
|
Serial2.print("\n"); |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void loop() { |
||||
|
for (int i = 0; i < numPins; i++) { |
||||
|
inputValue[i] = analogRead(input[i]) / 100; |
||||
|
} |
||||
|
|
||||
|
values2uart(); |
||||
|
delay(50); |
||||
|
} |
||||
@ -0,0 +1,64 @@ |
|||||
|
import serial |
||||
|
import sys |
||||
|
|
||||
|
class Const: |
||||
|
S5 = 35 |
||||
|
S2 = 36 |
||||
|
S1 = 32 |
||||
|
S3 = 39 |
||||
|
S4 = 34 |
||||
|
|
||||
|
B1 = 26 |
||||
|
|
||||
|
class Pin: |
||||
|
def __init__(self, id, initValue): |
||||
|
self.id = id |
||||
|
self.value = initValue |
||||
|
|
||||
|
def updateValue(self, value): |
||||
|
if (self.value > value): |
||||
|
diff = self.value - value |
||||
|
self.value = value |
||||
|
return (self, -1 * diff) |
||||
|
elif (self.value < value): |
||||
|
diff = value - self.value |
||||
|
self.value = value |
||||
|
return (self, diff) |
||||
|
else: |
||||
|
return (self, 0) |
||||
|
|
||||
|
class SerialListener: |
||||
|
ser: serial.Serial = None |
||||
|
pins = {} |
||||
|
def __init__(self, device = '/dev/serial0', rate = 9600): |
||||
|
self.ser = serial.Serial(device, rate) |
||||
|
|
||||
|
def reInit(self): |
||||
|
if self.ser: |
||||
|
self.ser.close() |
||||
|
self.ser.open() |
||||
|
|
||||
|
def listen(self): |
||||
|
while True: |
||||
|
try: |
||||
|
if self.ser.in_waiting > 0: |
||||
|
data = self.ser.readline().decode().split("\n")[0].split("-") |
||||
|
pin = int(data[0]) |
||||
|
value = int(data[1]) |
||||
|
if pin not in self.pins: |
||||
|
self.pins[pin] = Pin(pin, value) |
||||
|
else: |
||||
|
yield self.pins[pin].updateValue(value) |
||||
|
except KeyboardInterrupt: |
||||
|
print("exit from main loop") |
||||
|
sys.exit(0) |
||||
|
except: |
||||
|
self.reInit() |
||||
|
|
||||
|
if __name__ == "__main__": |
||||
|
listener = SerialListener() |
||||
|
for pin in listener.listen(): |
||||
|
if (pin[1] == 0): |
||||
|
continue |
||||
|
|
||||
|
print(pin[0].id, pin[1]) |
||||
Loading…
Reference in new issue