Compare commits
360 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48a6ea9f86 | ||
|
|
c87a354258 | ||
|
|
aa955c4376 | ||
|
|
b4ce00a899 | ||
|
|
88467546ee | ||
|
|
5547ffd352 | ||
|
|
57cca7fd7d | ||
|
|
adcb740a19 | ||
|
|
2bbb0844ea | ||
|
|
e2af79a70b | ||
|
|
7ba3f50d36 | ||
|
|
d14339d748 | ||
|
|
292185d7b9 | ||
|
|
ae88fed18c | ||
|
|
10dd2cd969 | ||
|
|
160bf98cff | ||
|
|
923d409ffd | ||
|
|
fccc7ebe48 | ||
|
|
e55fd74098 | ||
|
|
cc13749b5e | ||
|
|
a29743d6af | ||
|
|
47308a7f1a | ||
|
|
14c7b7d931 | ||
|
|
a29da80873 | ||
|
|
908629430e | ||
|
|
3448db64f0 | ||
|
|
242d1275ac | ||
|
|
5bb26d8d98 | ||
|
|
7a508dce22 | ||
|
|
d7109fa827 | ||
|
|
94b83cbef9 | ||
|
|
d18a31bfec | ||
|
|
3cc46f8bdb | ||
|
|
7fa847b6b8 | ||
|
|
ff822bf77c | ||
|
|
a68ef4b415 | ||
|
|
1c3435509f | ||
|
|
faac4e8be3 | ||
|
|
3dc39067e8 | ||
|
|
bbeb37b210 | ||
|
|
b997ee5a0d | ||
|
|
e240b61dd0 | ||
|
|
ad19b39863 | ||
|
|
3a16bf08c0 | ||
|
|
9e85cf0c8e | ||
|
|
a51231a067 | ||
|
|
7b6fced70c | ||
|
|
2309e7b8ea | ||
|
|
fb589e49b7 | ||
|
|
bf97fa1b88 | ||
|
|
8c9862e1c5 | ||
|
|
1417285467 | ||
|
|
06deceb470 | ||
|
|
db8e46f7c5 | ||
|
|
163fc2ff2f | ||
|
|
3942f2cbd7 | ||
|
|
d7d1417be5 | ||
|
|
b5c25be3bf | ||
|
|
02c6b18f1c | ||
|
|
6ecf6252b5 | ||
|
|
b204f2b4b5 | ||
|
|
bfafc77e36 | ||
|
|
ff79220c58 | ||
|
|
103b133885 | ||
|
|
0173a1f2cd | ||
|
|
219781e115 | ||
|
|
c8b097bdb4 | ||
|
|
e406acfa31 | ||
|
|
a6c6d5dc16 | ||
|
|
34817dcd3a | ||
|
|
5eb36455d7 | ||
|
|
5532bfc5fb | ||
|
|
da7d04a3a7 | ||
|
|
001096d826 | ||
|
|
4ba53896e2 | ||
|
|
243a52d4b6 | ||
|
|
ed6e75053e | ||
|
|
f728f7638b | ||
|
|
b8d16b01e0 | ||
|
|
0706b27819 | ||
|
|
27ac7a9614 | ||
|
|
8f6c615f1c | ||
|
|
e6fec6078a | ||
|
|
a59177c897 | ||
|
|
caba9aa589 | ||
|
|
fc6ff17730 | ||
|
|
30b4c740b9 | ||
|
|
f5cfbca4c6 | ||
|
|
011ede8124 | ||
|
|
46632797b5 | ||
|
|
2bb0a8c447 | ||
|
|
4e477c8ba6 | ||
|
|
a122af2e43 | ||
|
|
9391a10c30 | ||
|
|
64b9fd8bf4 | ||
|
|
9710557648 | ||
|
|
1370f9e5c3 | ||
|
|
a282edbda5 | ||
|
|
117ca53fce | ||
|
|
b0028ac12c | ||
|
|
8ab58b59ed | ||
|
|
4c4f24a076 | ||
|
|
2c73c400fa | ||
|
|
bde69a70be | ||
|
|
def7058ee9 | ||
|
|
ebcc4936f7 | ||
|
|
a113de6afb | ||
|
|
26404d7674 | ||
|
|
4d091776d4 | ||
|
|
0b17bc3964 | ||
|
|
9a97fa0b40 | ||
|
|
92766ff60f | ||
|
|
4996d5b48d | ||
|
|
2772ebb1f3 | ||
|
|
0aba7ce7fd | ||
|
|
189997aae8 | ||
|
|
f9a67937b5 | ||
|
|
472040cf8f | ||
|
|
43914b6163 | ||
|
|
63377adde5 | ||
|
|
2e3f8e6dc3 | ||
|
|
04509fac88 | ||
|
|
339cccfbdd | ||
|
|
b73b9d51a2 | ||
|
|
866f780c55 | ||
|
|
97a7d43e85 | ||
|
|
d49b6e9d95 | ||
|
|
e078e2723f | ||
|
|
169377cc43 | ||
|
|
4c85441000 | ||
|
|
b3e3a1ad66 | ||
|
|
5c5fb7995a | ||
|
|
59958b8774 | ||
|
|
108f4e381b | ||
|
|
16054b3687 | ||
|
|
f9928f941f | ||
|
|
d262dedd1f | ||
|
|
0445056459 | ||
|
|
3355934bb1 | ||
|
|
3a6a8f7b5c | ||
|
|
46ef973fbb | ||
|
|
9e48166f87 | ||
|
|
60950ddddd | ||
|
|
a3532a8961 | ||
|
|
de02991724 | ||
|
|
2ebeece160 | ||
|
|
bc4b07e658 | ||
|
|
501435743e | ||
|
|
08283cf58a | ||
|
|
bc463b1099 | ||
|
|
45dc7155b2 | ||
|
|
18ab65af41 | ||
|
|
2f8e05b9fc | ||
|
|
2971dd189d | ||
|
|
62a7515f84 | ||
|
|
a779800e50 | ||
|
|
f5f8189b9b | ||
|
|
5c21b388c5 | ||
|
|
4188dec3f9 | ||
|
|
8cfa5451a4 | ||
|
|
6b60331f91 | ||
|
|
95b2af2be8 | ||
|
|
4848a15557 | ||
|
|
b9438288ed | ||
|
|
9a03fea228 | ||
|
|
ee839aa276 | ||
|
|
23179eafe9 | ||
|
|
5ed76a329e | ||
|
|
95b56a005c | ||
|
|
d25d137daf | ||
|
|
e75bbd339a | ||
|
|
f1060654ca | ||
|
|
a23e745c48 | ||
|
|
e946996f3f | ||
|
|
9112e121d7 | ||
|
|
0967b4f870 | ||
|
|
379c8d3610 | ||
|
|
7393941132 | ||
|
|
d83cd7b273 | ||
|
|
6092030e8d | ||
|
|
eb87a2206c | ||
|
|
d620d9bbcb | ||
|
|
eb56a34456 | ||
|
|
b2a3d97895 | ||
|
|
622cfa430c | ||
|
|
28aab54c0f | ||
|
|
288b439fd2 | ||
|
|
ba7406516e | ||
|
|
a9c0da65b0 | ||
|
|
99535aa278 | ||
|
|
67b8103437 | ||
|
|
1a78aab247 | ||
|
|
a0a9ec62c2 | ||
|
|
fa45350c9f | ||
|
|
d792adfc76 | ||
|
|
0355e7cc2d | ||
|
|
db7808592b | ||
|
|
b06eecc58a | ||
|
|
d980054dbd | ||
|
|
d97f80af23 | ||
|
|
c4108750c5 | ||
|
|
b5aeeec3b1 | ||
|
|
022e67421c | ||
|
|
16de141786 | ||
|
|
5d80647722 | ||
|
|
e51fb55bf0 | ||
|
|
3464d3b2f9 | ||
|
|
ef00e56b61 | ||
|
|
572e2aa874 | ||
|
|
da8a0e82bc | ||
|
|
b321ed165c | ||
|
|
242247c1f3 | ||
|
|
4136b91069 | ||
|
|
ba9f793277 | ||
|
|
ca58673271 | ||
|
|
f8564631a4 | ||
|
|
d40f66a409 | ||
|
|
745f13e4c3 | ||
|
|
5821682048 | ||
|
|
9f78e9b6a8 | ||
|
|
9a0b4995d2 | ||
|
|
d4fa6b7ca7 | ||
|
|
4c0dec3b10 | ||
|
|
caa4c95459 | ||
|
|
d9285cffa5 | ||
|
|
f9704fc473 | ||
|
|
0a514301a3 | ||
|
|
e237196448 | ||
|
|
f2958a312a | ||
|
|
f7513e009a | ||
|
|
290ea02e24 | ||
|
|
59c3fd0a91 | ||
|
|
268b88c890 | ||
|
|
163ec88b2b | ||
|
|
5cdf2f862c | ||
|
|
5c00ae3e0a | ||
|
|
8136d03488 | ||
|
|
5f3468fce2 | ||
|
|
1d979b9e84 | ||
|
|
5ae7756391 | ||
|
|
626db3e1ff | ||
|
|
ca07602e8d | ||
|
|
e1c4f810d1 | ||
|
|
60524f5831 | ||
|
|
88781715d8 | ||
|
|
0427954aa5 | ||
|
|
1c88521146 | ||
|
|
7ff0364ee8 | ||
|
|
01b8c3dafc | ||
|
|
f2c3475d9f | ||
|
|
2cdc1c3f27 | ||
|
|
210dcee138 | ||
|
|
a644569d77 | ||
|
|
aef5f7bdb6 | ||
|
|
fb47ecfa2c | ||
|
|
517637efbd | ||
|
|
b38b27e877 | ||
|
|
b2ebc27c57 | ||
|
|
a606044552 | ||
|
|
bea05b9490 | ||
|
|
715a6bda9e | ||
|
|
c4f2a384b4 | ||
|
|
e064d0d286 | ||
|
|
5627377cce | ||
|
|
2521c7574e | ||
|
|
fcdb78d315 | ||
|
|
441e5881d4 | ||
|
|
4dff4a305e | ||
|
|
f0845e36bf | ||
|
|
cfced2cb31 | ||
|
|
7c1719d67c | ||
|
|
5c9a4cc0e0 | ||
|
|
bbcad0bd0b | ||
|
|
f8e3d34caf | ||
|
|
74189e5324 | ||
|
|
7e8515bf70 | ||
|
|
53a1672188 | ||
|
|
c3f299956e | ||
|
|
5b5a200c71 | ||
|
|
5988dab792 | ||
|
|
6a96118081 | ||
|
|
35821306d3 | ||
|
|
245992f1fc | ||
|
|
1b02b83650 | ||
|
|
93fdfb8ae4 | ||
|
|
c803af1ae7 | ||
|
|
8459250b8e | ||
|
|
d3c76a3e1a | ||
|
|
9234544490 | ||
|
|
4aa0b9c354 | ||
|
|
86ff8202b9 | ||
|
|
0996221e73 | ||
|
|
021db693ad | ||
|
|
d596ff960d | ||
|
|
bce0876471 | ||
|
|
0cba038922 | ||
|
|
b7f04d58d7 | ||
|
|
450b38e10a | ||
|
|
fe48a15f6c | ||
|
|
30c45ecef3 | ||
|
|
fde1c0f526 | ||
|
|
a581a7745c | ||
|
|
1ffb79a37f | ||
|
|
533d6e60eb | ||
|
|
96eaee4493 | ||
|
|
ce6bbbcc3e | ||
|
|
77489b423b | ||
|
|
8bc1771bb2 | ||
|
|
a904ca8ca8 | ||
|
|
07a8bb9339 | ||
|
|
ccf996aef7 | ||
|
|
6fe27305d4 | ||
|
|
3973bcdc3c | ||
|
|
4fe5212f64 | ||
|
|
1d717ab82e | ||
|
|
a69c9c7efb | ||
|
|
340d2566fe | ||
|
|
a3ea15cfd9 | ||
|
|
4b41f91736 | ||
|
|
bf049e9e92 | ||
|
|
d046e3fd42 | ||
|
|
45802ac9a6 | ||
|
|
57cf3adc62 | ||
|
|
e2fe053c31 | ||
|
|
72596df87c | ||
|
|
cd981e348b | ||
|
|
72002bc814 | ||
|
|
861299c18a | ||
|
|
fc8dcd7ffb | ||
|
|
55539a84a1 | ||
|
|
6598ace123 | ||
|
|
d514547880 | ||
|
|
6ccbc2e73b | ||
|
|
673a7cfd5a | ||
|
|
6336cf1a73 | ||
|
|
c94fe6a1de | ||
|
|
e5f40f93d0 | ||
|
|
b5a6cce854 | ||
|
|
5537cfc6d2 | ||
|
|
94f147b64f | ||
|
|
0de6e91c1a | ||
|
|
3342bb2bc3 | ||
|
|
3987110b87 | ||
|
|
b946a8065f | ||
|
|
9af17f1d2b | ||
|
|
a3e70cb2d2 | ||
|
|
58cca634ac | ||
|
|
c9d0ee84ef | ||
|
|
1ccd4d3453 | ||
|
|
1b999b095f | ||
|
|
0d345d09de | ||
|
|
6d09eaa8b2 | ||
|
|
ab167175f2 | ||
|
|
fb2b5ccf27 | ||
|
|
204d71afc7 | ||
|
|
a03767c759 | ||
|
|
8c3f5dd7b6 | ||
|
|
2b541cf370 | ||
|
|
d3ea424289 | ||
|
|
a76596aa98 |
70 changed files with 7334 additions and 972 deletions
68
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
68
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
name: 🐞 Bug Report
|
||||
description: Create a bug report to help us improve
|
||||
labels:
|
||||
- bug
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: >-
|
||||
Thanks! for using the installer scripts. Now that you have encountered a
|
||||
bug... you can file a report for it.
|
||||
- type: textarea
|
||||
id: script
|
||||
attributes:
|
||||
label: Script Command
|
||||
description: >-
|
||||
Include the exact command you're running with any parameters. There are quite
|
||||
a handful of scripts and knowing which one is helpful. :)
|
||||
placeholder: sudo python3 adafruit-pitft.py --display=28r --rotation=90 --install-type=console
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: os
|
||||
attributes:
|
||||
label: Operating System
|
||||
description: >-
|
||||
Which OS was the script running under? Include details such as if it
|
||||
was 32 or 64-bit, Whether it was the Lite of Full Desktop version. If it's on an older or newer
|
||||
kernel, include that as well.
|
||||
placeholder: |
|
||||
64-bit Raspberry Pi OS Lite with Bullseye
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: hardware
|
||||
attributes:
|
||||
label: Hardware
|
||||
description: This is the board or computer you are running the script on.
|
||||
placeholder: |
|
||||
Raspberry Pi 4B
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: behavior
|
||||
attributes:
|
||||
label: Behavior
|
||||
description: What happens when you run the script above? Include error messages (if any).
|
||||
placeholder: |
|
||||
An error occurs at line 459 with this message...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: Optionally, describe the bug in more detail.
|
||||
placeholder: |
|
||||
- I selected options 1, then 3, then 4...
|
||||
- Only happens when...
|
||||
- might be related to #123...
|
||||
- type: textarea
|
||||
id: more-info
|
||||
attributes:
|
||||
label: Additional information
|
||||
description: >-
|
||||
Optionally, add any other information like hardware connection, scope
|
||||
output etc. If you have already done some debugging, mention it here.
|
||||
placeholder: Removing [this](url) line resolves the issue.
|
||||
7
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
7
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
contact_links:
|
||||
- name: 🔗 Adafruit Forum
|
||||
url: https://forums.adafruit.com/
|
||||
about: Official Adafruit technical support forum. Good for getting help on getting a project working.
|
||||
- name: 🔗 Adafruit Discord
|
||||
url: https://adafru.it/discord
|
||||
about: Unofficial chat with many helpful folks and normally prompt replies.
|
||||
11
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
11
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
name: 🚀 Feature Request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: 'enhancement'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!-- If you have an idea for any new features and enhancements to any of our scripts 🚀
|
||||
and would love ❤ to see what ideas you have for us... 🙂 -->
|
||||
16
.gitignore
vendored
Normal file
16
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# SPDX-FileCopyrightText: 2019 Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: Unlicense
|
||||
|
||||
*.mpy
|
||||
.idea
|
||||
__pycache__
|
||||
_build
|
||||
*.pyc
|
||||
.env
|
||||
build*
|
||||
bundles
|
||||
*.DS_Store
|
||||
.eggs
|
||||
dist
|
||||
**/*.egg-info
|
||||
32
README.md
32
README.md
|
|
@ -2,6 +2,36 @@
|
|||
|
||||
Some scripts for helping install Adafruit HATs, bonnets, add-on's, & friends!
|
||||
|
||||
Based heavily on get.pimoroni.com scripts!
|
||||
Many scripts are based heavily on get.pimoroni.com scripts!
|
||||
|
||||
* Install i2s amplifier with: curl -sS https://raw.githubusercontent.com/adafruit/Raspberry-Pi-Installer-Scripts/master/i2samp.sh | bash
|
||||
|
||||
## Python Scripts
|
||||
|
||||
We are in the process of converting our Shell Scripts to Python. Instructions for running specific scripts are available in the [Adafruit Learning System](https://learn.adafruit.com/). Here are the general setup instructions.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Python 3
|
||||
- [Adafruit_Python_Shell](https://github.com/adafruit/Adafruit_Python_Shell)
|
||||
- [Click](https://pypi.org/project/click/)
|
||||
|
||||
### Prepare your system
|
||||
|
||||
To install the dependencies for the python scripts, run the following commands:
|
||||
|
||||
```bash
|
||||
sudo apt-get install python3-pip
|
||||
sudo pip3 install --upgrade click
|
||||
sudo pip3 install --upgrade setuptools
|
||||
sudo pip3 install --upgrade adafruit-python-shell
|
||||
```
|
||||
Then to run the python script, type the following replacing "scriptname.py" with the actual script name:
|
||||
|
||||
```bash
|
||||
sudo python3 scriptname.py
|
||||
```
|
||||
|
||||
## Old Shell Scripts
|
||||
|
||||
If you were directed here from an external site and the script you were looking for appears to be missing, you can either use the newer python script or check the [converted_shell_scripts](https://github.com/adafruit/Raspberry-Pi-Installer-Scripts/tree/main/converted_shell_scripts) folder to use the old shell scripts.
|
||||
|
|
|
|||
1054
adafruit-pitft.py
Normal file
1054
adafruit-pitft.py
Normal file
File diff suppressed because it is too large
Load diff
93
adafruit_fanservice.py
Normal file
93
adafruit_fanservice.py
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
"""
|
||||
Adafruit Raspberry Pi Fan Service Setup Script
|
||||
(C) Adafruit Industries, Creative Commons 3.0 - Attribution Share Alike
|
||||
|
||||
Converted to Python by Melissa LeBlanc-Williams for Adafruit Industries
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
try:
|
||||
from adafruit_shell import Shell
|
||||
except ImportError:
|
||||
raise RuntimeError("The library 'adafruit_shell' was not found. To install, try typing: sudo pip3 install adafruit-python-shell")
|
||||
|
||||
shell = Shell()
|
||||
shell.group = 'ADAFRUIT'
|
||||
|
||||
def main():
|
||||
shell.clear()
|
||||
if shell.is_raspberry_pi():
|
||||
print("""This script will enable the Raspberry Pi
|
||||
fan service, which will turn on an
|
||||
external fan controlled by a given pin
|
||||
|
||||
Operations performed include:
|
||||
- Enable Fan Service
|
||||
|
||||
Run time < 1 minute. Reboot required.""")
|
||||
else:
|
||||
print("""This script will install Adafruit
|
||||
fan service, which will turn on an
|
||||
external fan controlled by a given pin
|
||||
|
||||
Operations performed include:
|
||||
- Create a Fan Service File
|
||||
- Enable Fan Service
|
||||
- Automatically Start Fan Service
|
||||
on System startup
|
||||
|
||||
Run time < 1 minute. Reboot not required.""")
|
||||
|
||||
if not shell.argument_exists('y'):
|
||||
if not shell.prompt("CONTINUE?", default='n'):
|
||||
print("Canceled.")
|
||||
shell.exit()
|
||||
print("Continuing...")
|
||||
# check init system (technique borrowed from raspi-config):
|
||||
shell.group = 'FAN'
|
||||
shell.info('Checking init system...')
|
||||
if shell.run_command("which systemctl", suppress_message=True) and shell.run_command("systemctl | grep '\-\.mount'", suppress_message=True):
|
||||
print("Found systemd, OK!")
|
||||
elif os.path.isfile("/etc/init.d/cron") and not os.path.islink("/etc/init.d/cron"):
|
||||
shell.bail("Found sysvinit, but we require systemd")
|
||||
else:
|
||||
shell.bail("Unrecognised init system")
|
||||
|
||||
if shell.is_raspberry_pi():
|
||||
shell.info('Enabling Raspberry Pi Fan Service on GPIO 4')
|
||||
shell.run_command("sudo raspi-config nonint do_fan 0 4")
|
||||
shell.info('Done!')
|
||||
shell.prompt_reboot()
|
||||
else:
|
||||
shell.info('Adding adafruit_fan.service')
|
||||
contents = """[Unit]
|
||||
Description=Fan service for some Adafruit boards
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStartPre=-/bin/bash -c 'echo 4 >/sys/class/gpio/export'
|
||||
ExecStartPre=/bin/bash -c 'echo out >/sys/class/gpio/gpio4/direction'
|
||||
ExecStart=/bin/bash -c 'echo 1 >/sys/class/gpio/gpio4/value'
|
||||
|
||||
RemainAfterExit=true
|
||||
ExecStop=/bin/bash -c 'echo 0 >/sys/class/gpio/gpio4/value'
|
||||
StandardOutput=journal
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target"""
|
||||
shell.write_text_file("/etc/systemd/system/adafruit_fan.service", contents, append=False)
|
||||
|
||||
shell.info('Enabling adafruit_fan.service')
|
||||
shell.run_command("sudo systemctl enable adafruit_fan.service")
|
||||
shell.run_command("sudo systemctl start adafruit_fan.service")
|
||||
shell.info('Done!')
|
||||
print("You can stop the fan service with 'sudo systemctl stop adafruit_fan.service'")
|
||||
print("You can start the fan service with 'sudo systemctl start adafruit_fan.service'")
|
||||
|
||||
|
||||
# Main function
|
||||
if __name__ == "__main__":
|
||||
shell.require_root()
|
||||
main()
|
||||
237
ar1100.py
Normal file
237
ar1100.py
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
#!/usr/bin/python
|
||||
import usb.core
|
||||
import usb.util
|
||||
import time
|
||||
import os
|
||||
import pygame
|
||||
from pygame.locals import *
|
||||
|
||||
def mapnum(x, in_min, in_max, out_min, out_max):
|
||||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||
|
||||
|
||||
CALIBRATED_5IN_800x480 = [
|
||||
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x55, 0x80, 0x05, 0x05, 0x40, 0x03, 0x00, 0x20, 0x00, 0x50, 0x00, 0x80, 0x00, 0xb0, 0x00, 0xe0,
|
||||
0x00, 0x20, 0x00, 0x50, 0x00, 0x80, 0x00, 0xb0, 0x00, 0xe0, 0x4d, 0x2a, 0x3a, 0x2b, 0xcb, 0x56,
|
||||
0xb5, 0x29, 0x18, 0x82, 0xe9, 0x29, 0x41, 0xad, 0x06, 0x2b, 0x16, 0xd9, 0x42, 0x2a, 0x45, 0x29,
|
||||
0x82, 0x53, 0x10, 0x56, 0xda, 0x54, 0x99, 0x81, 0xcf, 0x55, 0x5e, 0xac, 0xec, 0x55, 0x83, 0xd8,
|
||||
0xcf, 0x55, 0xf1, 0x29, 0x3d, 0x82, 0xa0, 0x55, 0x11, 0x82, 0x22, 0x81, 0x4b, 0x81, 0x47, 0xad,
|
||||
0xc2, 0x82, 0x06, 0xd9, 0xc8, 0x82, 0x65, 0x2a, 0xda, 0xac, 0xc1, 0x55, 0xa3, 0xac, 0xeb, 0x80,
|
||||
0x26, 0xae, 0x27, 0xac, 0xd9, 0xad, 0x8e, 0xd8, 0xd9, 0xae, 0x8b, 0x28, 0xb9, 0xda, 0x9a, 0x54,
|
||||
0x59, 0xdb, 0x1e, 0x7f, 0x78, 0xdc, 0x0f, 0xad, 0xdd, 0xdc, 0x88, 0xd8, 0xde, 0xdb, 0x00, 0x00,
|
||||
]
|
||||
|
||||
CALIBRATED_7IN_800x480 = [
|
||||
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x55, 0x80, 0x03, 0x03, 0x40, 0x02, 0x00, 0x20, 0x00, 0x80, 0x00, 0xe0, 0x00, 0xb0, 0x00, 0xe0,
|
||||
0x00, 0x20, 0x00, 0x80, 0x00, 0xe0, 0x00, 0xb0, 0x00, 0xe0, 0x7f, 0x22, 0x5c, 0x2d, 0xbf, 0x7d,
|
||||
0xdd, 0x2a, 0xaf, 0xdc, 0xf3, 0x2b, 0x21, 0x23, 0xb2, 0x82, 0xb4, 0x80, 0x4c, 0x82, 0x40, 0xde,
|
||||
0xe7, 0x85, 0x42, 0x23, 0xcc, 0xd6, 0xda, 0x7e, 0x7d, 0xd7, 0xd9, 0xdc, 0x8b, 0xd8, 0x83, 0xd8,
|
||||
0xcf, 0x55, 0xf1, 0x29, 0x3d, 0x82, 0xa0, 0x55, 0x11, 0x82, 0x22, 0x81, 0x4b, 0x81, 0x47, 0xad,
|
||||
0xc2, 0x82, 0x06, 0xd9, 0xc8, 0x82, 0x65, 0x2a, 0xda, 0xac, 0xc1, 0x55, 0xa3, 0xac, 0xeb, 0x80,
|
||||
0x26, 0xae, 0x27, 0xac, 0xd9, 0xad, 0x8e, 0xd8, 0xd9, 0xae, 0x8b, 0x28, 0xb9, 0xda, 0x9a, 0x54,
|
||||
0x59, 0xdb, 0x1e, 0x7f, 0x78, 0xdc, 0x0f, 0xad, 0xdd, 0xdc, 0x88, 0xd8, 0xde, 0xdb, 0x00, 0x00,
|
||||
]
|
||||
|
||||
writeeeprom = CALIBRATED_5IN_800x480;
|
||||
|
||||
USB_MODE_GENERIC = [0x55, 0x01, 0x70]
|
||||
USB_MODE_MOUSE = [0x55, 0x01, 0x71]
|
||||
|
||||
MCP_VID = 0x04D8
|
||||
MOUSE_PID = 0x0C02
|
||||
GENERIC_PID = 0x0C01
|
||||
|
||||
# Try to locate it as a mouse:
|
||||
dev = usb.core.find(idVendor=MCP_VID, idProduct=MOUSE_PID)
|
||||
if dev:
|
||||
# first endpoint
|
||||
interface = 0
|
||||
endpoint = dev[0][(0,0)][0]
|
||||
|
||||
# if the OS kernel already claimed the device, which is most likely true
|
||||
# thanks to http://stackoverflow.com/questions/8218683/pyusb-cannot-set-configuration
|
||||
|
||||
if dev.is_kernel_driver_active(interface) is True:
|
||||
# tell the kernel to detach
|
||||
dev.detach_kernel_driver(interface)
|
||||
# claim the device
|
||||
usb.util.claim_interface(dev, interface)
|
||||
|
||||
# try to send it command to swap to generic HID
|
||||
try:
|
||||
# turn into HID
|
||||
# bReq, wVal, wIndex, data
|
||||
ret = dev.ctrl_transfer(0x21, 0x09, 0x0003, 0x0000, [0x55, 0x01, 0x70])
|
||||
if (ret == 3):
|
||||
print("Turned into HID!")
|
||||
except:
|
||||
# failed to get data for this request
|
||||
print("Failed to turn into HID")
|
||||
exit(-1)
|
||||
|
||||
# Try to locate it as a mouse:
|
||||
dev = usb.core.find(idVendor=MCP_VID, idProduct=GENERIC_PID)
|
||||
|
||||
if (not dev):
|
||||
print("Couldn't find generic either :/")
|
||||
exit(-1)
|
||||
|
||||
print("Found Generic!")
|
||||
interface = 0
|
||||
endpoint = dev[0][(0,0)][1]
|
||||
|
||||
while True:
|
||||
#try:
|
||||
|
||||
if dev.is_kernel_driver_active(interface) is True:
|
||||
# tell the kernel to detach
|
||||
dev.detach_kernel_driver(interface)
|
||||
# claim the device
|
||||
usb.util.claim_interface(dev, interface)
|
||||
|
||||
time.sleep(1)
|
||||
dev.set_configuration()
|
||||
break
|
||||
#except:
|
||||
# print("retrying set config...")
|
||||
|
||||
|
||||
print("Writing EEPROM...")
|
||||
for addr in range (0x60, 0xFF, 8):
|
||||
msg = [0x55, 0x04 + 8, 0x29, 0x00, addr, 8]
|
||||
msg.extend(writeeeprom[addr-0x60:addr-0x60+8])
|
||||
|
||||
#print(msg)
|
||||
#print(', '.join([hex(i) for i in msg]))
|
||||
ret = dev.write(1, msg)
|
||||
#print("Wrote : ", ret)
|
||||
|
||||
ret = dev.read(0x81, 64)
|
||||
#print("Read : ", readeeprom.extend(ret[4:20]))
|
||||
#print(', '.join([hex(i) for i in ret[0:4]]))
|
||||
if ret[2] != 0:
|
||||
print("Failed to write")
|
||||
exit(-1)
|
||||
|
||||
|
||||
print("Reading EEPROM...")
|
||||
readeeprom = []
|
||||
for addr in range (0x60, 0xF8 , 16):
|
||||
msg = [0x55, 0x04, 0x28, 0x00, addr, 16]
|
||||
ret = dev.write(1, msg)
|
||||
#print("Wrote :", ret)
|
||||
|
||||
ret = dev.read(0x81, 64)
|
||||
#print("Read :",ret)
|
||||
readeeprom.extend(ret[4:20])
|
||||
#print(', '.join([hex(i) for i in ret[4:20]]))
|
||||
|
||||
for i in range(len(readeeprom)):
|
||||
print(("0x%02x," % readeeprom[i]), end='')
|
||||
if (i % 16 == 15):
|
||||
print("")
|
||||
#print(", 0x%2X".join([hex (i) for i in readeeprom]))
|
||||
|
||||
# compare eeproms
|
||||
if (writeeeprom != readeeprom):
|
||||
print("Failed to write eeprom correctly (verification fail)")
|
||||
exit(-1)
|
||||
|
||||
print("EEPROM verified OK!")
|
||||
|
||||
|
||||
# try to send it command to swap to generic HID
|
||||
try:
|
||||
# turn into Mouse
|
||||
# bReq, wVal, wIndex, data
|
||||
ret = dev.ctrl_transfer(0x21, 0x09, 0x0003, 0x0000, [0x55, 0x01, 0x71])
|
||||
if (ret == 3):
|
||||
print("Turned into Mouse!")
|
||||
except:
|
||||
# failed to get data for this request
|
||||
print("Failed to turn into Mouse")
|
||||
exit(-1)
|
||||
try:
|
||||
# release the device
|
||||
usb.util.release_interface(dev, interface)
|
||||
# reattach the device to the OS kernel
|
||||
dev.attach_kernel_driver(interface)
|
||||
except:
|
||||
pass
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
# Try to locate it as a mouse:
|
||||
dev = usb.core.find(idVendor=MCP_VID, idProduct=MOUSE_PID)
|
||||
if not dev:
|
||||
print("No mouse :(")
|
||||
exit(-1)
|
||||
|
||||
# first endpoint
|
||||
interface = 0
|
||||
endpoint = dev[0][(0,0)][0]
|
||||
|
||||
# if the OS kernel already claimed the device, which is most likely true
|
||||
# thanks to http://stackoverflow.com/questions/8218683/pyusb-cannot-set-configuration
|
||||
|
||||
if dev.is_kernel_driver_active(interface) is True:
|
||||
# tell the kernel to detach
|
||||
dev.detach_kernel_driver(interface)
|
||||
# claim the device
|
||||
usb.util.claim_interface(dev, interface)
|
||||
|
||||
# set up pygame
|
||||
|
||||
white = (255, 255, 255)
|
||||
w = 800
|
||||
h = 480
|
||||
|
||||
# Output to the LCD instead of the console
|
||||
os.putenv("DISPLAY", ":0")
|
||||
|
||||
pygame.init()
|
||||
|
||||
|
||||
screen = pygame.display.set_mode((w, h))
|
||||
running = 1
|
||||
|
||||
img = pygame.image.load('gradient800x480.jpg')
|
||||
|
||||
screen.fill((white))
|
||||
screen.blit(img,(0,0))
|
||||
pygame.display.flip()
|
||||
while running:
|
||||
for event in pygame.event.get():
|
||||
print(event)
|
||||
if event.type == QUIT:
|
||||
exit(0)
|
||||
elif event.type == KEYDOWN:
|
||||
if event.key == K_ESCAPE:
|
||||
pygame.quit()
|
||||
exit(0)
|
||||
|
||||
try:
|
||||
data = dev.read(endpoint.bEndpointAddress,endpoint.wMaxPacketSize)
|
||||
#print(data)
|
||||
x = data[1] + (data[2] << 8)
|
||||
y = data[3] + (data[4] << 8)
|
||||
#print(x, y)
|
||||
x = mapnum(x, 0, 4096, 0, w)
|
||||
y = mapnum(y, 0, 4096, 0, h)
|
||||
print(x, y)
|
||||
pygame.draw.circle(screen, white, (x,y), 10)
|
||||
pygame.display.flip()
|
||||
|
||||
except usb.core.USBError as e:
|
||||
data = None
|
||||
if e.args == ('Operation timed out',):
|
||||
continue
|
||||
|
||||
# release the device
|
||||
usb.util.release_interface(dev, interface)
|
||||
# reattach the device to the OS kernel
|
||||
dev.attach_kernel_driver(interface)
|
||||
|
|
@ -110,8 +110,8 @@ echo "Updating package index files..."
|
|||
apt-get update
|
||||
|
||||
echo "Installing Python libraries..."
|
||||
apt-get install -y --force-yes python-pip python-dev python-smbus
|
||||
pip install evdev
|
||||
apt-get install -y python3-pip
|
||||
pip3 install evdev smbus
|
||||
|
||||
echo "Installing Adafruit code in /boot..."
|
||||
cd /tmp
|
||||
|
|
@ -158,10 +158,10 @@ fi
|
|||
grep arcadeBonnet.py /etc/rc.local >/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
# arcadeBonnet.py already in rc.local, but make sure correct:
|
||||
sed -i "s/^.*arcadeBonnet.py.*$/cd \/boot;python arcadeBonnet.py \&/g" /etc/rc.local >/dev/null
|
||||
sed -i "s/^.*arcadeBonnet.py.*$/cd \/boot;python3 arcadeBonnet.py \&/g" /etc/rc.local >/dev/null
|
||||
else
|
||||
# Insert arcadeBonnet.py into rc.local before final 'exit 0'
|
||||
sed -i "s/^exit 0/cd \/boot;python arcadeBonnet.py \&\\nexit 0/g" /etc/rc.local >/dev/null
|
||||
sed -i "s/^exit 0/cd \/boot;python3 arcadeBonnet.py \&\\nexit 0/g" /etc/rc.local >/dev/null
|
||||
fi
|
||||
|
||||
# Add udev rule (will overwrite if present)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ fi
|
|||
|
||||
|
||||
UPDATE_DB=false
|
||||
|
||||
UNINSTALL=false
|
||||
|
||||
############################ CALIBRATIONS ############################
|
||||
# For TSLib
|
||||
|
|
@ -47,6 +47,10 @@ TRANSFORM_28c90="0 1 0 -1 0 1 0 0 1"
|
|||
TRANSFORM_28c180="1 0 0 0 1 0 0 0 1"
|
||||
TRANSFORM_28c270="0 -1 1 1 0 0 0 0 1"
|
||||
|
||||
ROTATE_28c0="rotate=90,touch-invx=true,touch-invy=true"
|
||||
ROTATE_28c90="rotate=90,touch-swapxy=true,touch-invx=true"
|
||||
ROTATE_28c180="rotate=90"
|
||||
ROTATE_28c270="rotate=270,touch-swapxy=true,touch-invy=true"
|
||||
|
||||
warning() {
|
||||
echo WARNING : $1
|
||||
|
|
@ -196,20 +200,28 @@ function softwareinstall() {
|
|||
pip install evdev 1> /dev/null || { warning "Pip failed to install software!" && exit 1; }
|
||||
}
|
||||
|
||||
# update /boot/config.txt with appropriate values
|
||||
function update_configtxt() {
|
||||
# Remove any old flexfb/fbtft stuff
|
||||
function uninstall_bootconfigtxt() {
|
||||
if grep -q "adafruit-pitft-helper" "/boot/config.txt"; then
|
||||
echo "Already have an adafruit-pitft-helper section in /boot/config.txt."
|
||||
echo "Removing old section..."
|
||||
cp /boot/config.txt /boot/configtxt.bak
|
||||
sed -i -e "/^# --- added by adafruit-pitft-helper/,/^# --- end adafruit-pitft-helper/d" /boot/config.txt
|
||||
fi
|
||||
}
|
||||
|
||||
# remove any old flexfb/fbtft stuff
|
||||
# Remove any old flexfb/fbtft stuff
|
||||
function uninstall_etc_modules() {
|
||||
rm -f /etc/modprobe.d/fbtft.conf
|
||||
sed -i 's/spi-bcm2835//g' "/etc/modules"
|
||||
sed -i 's/flexfb//g' "/etc/modules"
|
||||
sed -i 's/fbtft_device//g' "/etc/modules"
|
||||
sed -i 's/spi-bcm2835//g' "/etc/modules"
|
||||
}
|
||||
|
||||
# update /boot/config.txt with appropriate values
|
||||
function update_configtxt() {
|
||||
uninstall_bootconfigtxt
|
||||
uninstall_etc_modules
|
||||
|
||||
if [ "${pitfttype}" == "22" ]; then
|
||||
overlay="dtoverlay=pitft22,rotate=${pitftrot},speed=64000000,fps=30"
|
||||
|
|
@ -220,44 +232,50 @@ function update_configtxt() {
|
|||
fi
|
||||
|
||||
if [ "${pitfttype}" == "28c" ]; then
|
||||
overlay="dtoverlay=pitft28-capacitive,rotate=${pitftrot},speed=64000000,fps=30"
|
||||
rotateparams=$(eval echo "\$ROTATE_$pitfttype$touchrot")
|
||||
overlay=$(printf "dtoverlay=pitft28-capacitive,speed=64000000,fps=30\ndtoverlay=pitft28-capacitive,${rotateparams}")
|
||||
fi
|
||||
|
||||
if [ "${pitfttype}" == "35r" ]; then
|
||||
overlay="dtoverlay=pitft35-resistive,rotate=${pitftrot},speed=20000000,fps=20"
|
||||
fi
|
||||
|
||||
if [ "${pitfttype}" == "st7789_240x240" ]; then
|
||||
cat >> /etc/modprobe.d/fbtft.conf <<EOF
|
||||
# --- added by adafruit-pitft-helper $date ---
|
||||
options fbtft_device name=flexfb gpios=dc:25,cs:8,led:26 speed=40000000 bgr=1 fps=60
|
||||
options flexfb setaddrwin=0 width=240 height=240 init=-1,0x11,-2,120,-1,0x36,0x00,-1,0x3A,0x05,-1,0xB2,0x0C,0x0C,0x00,0x33,0x33,-1,0xB7,0x35,-1,0xBB,0x1A,-1,0xC0,0x2C,-1,0xC2,0x01,-1,0xC3,0x0B,-1,0xC4,0x20,-1,0xC6,0x0F,-1,0xD0,0xA4,0xA1,-1,0x21,-1,0xE0,0x00,0x19,0x1E,0x0A,0x09,0x15,0x3D,0x44,0x51,0x12,0x03,0x00,0x3F,0x3F,-1,0xE1,0x00,0x18,0x1E,0x0A,0x09,0x25,0x3F,0x43,0x52,0x33,0x03,0x00,0x3F,0x3F,-1,0x29,-3
|
||||
# --- end adafruit-pitft-helper $date ---
|
||||
EOF
|
||||
echo "flexfb" >> /etc/modules
|
||||
echo "fbtft_device" >> /etc/modules
|
||||
echo "spi-bcm2835" >> /etc/modules
|
||||
overlay=""
|
||||
if [ "${pitfttype}" == "st7789_240x320" ]; then
|
||||
dtc -@ -I dts -O dtb -o /boot/overlays/drm-st7789v_240x320.dtbo overlays/st7789v_240x320-overlay.dts
|
||||
overlay="dtoverlay=drm-st7789v_240x320,rotate=${pitftrot}"
|
||||
fi
|
||||
|
||||
if [ "${pitfttype}" == "st7789_240x135" ]; then
|
||||
if [ "${pitfttype}" == "st7789_240x240" ]; then
|
||||
dtc -@ -I dts -O dtb -o /boot/overlays/drm-minipitft13.dtbo overlays/minipitft13-overlay.dts
|
||||
overlay="dtoverlay=drm-minipitft13,rotate=${pitftrot}"
|
||||
fi
|
||||
|
||||
if [ "${pitfttype}" == "st7789_240x135" ]; then
|
||||
dtc -@ -I dts -O dtb -o /boot/overlays/drm-minipitft114.dtbo overlays/minipitft114-overlay.dts
|
||||
overlay="dtoverlay=drm-minipitft114,rotation=${pitftrot}"
|
||||
fi
|
||||
|
||||
# any/all st7789's need their own kernel driver
|
||||
if [ "${pitfttype}" == "st7789_240x240" ] || [ "${pitfttype}" == "st7789_240x320" ] || [ "${pitfttype}" == "st7789_240x135" ]; then
|
||||
echo "############# UPGRADING KERNEL ###############"
|
||||
sudo apt update || { warning "Apt failed to update itself!" && exit 1; }
|
||||
sudo apt-get upgrade || { warning "Apt failed to install software!" && exit 1; }
|
||||
apt-get install -y raspberrypi-kernel-headers 1> /dev/null || { warning "Apt failed to install software!" && exit 1; }
|
||||
[ -d /lib/modules/$(uname -r)/build ] || { warning "Kernel was updated, please reboot now and re-run script!" && exit 1; }
|
||||
cd st7789_module
|
||||
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules || { warning "Apt failed to compile ST7789V driver!" && exit 1; }
|
||||
mv /lib/modules/$(uname -r)/kernel/drivers/gpu/drm/tinydrm/mi0283qt.ko /lib/modules/$(uname -r)/kernel/drivers/gpu/drm/tinydrm/mi0283qt.BACK
|
||||
mv st7789v_ada.ko /lib/modules/$(uname -r)/kernel/drivers/gpu/drm/tinydrm/mi0283qt.ko
|
||||
overlay="dtoverlay=drm-minipitft114,rotation=${pitftrot}"
|
||||
pushd st7789_module
|
||||
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules || { warning "Apt failed to compile ST7789V drivers!" && exit 1; }
|
||||
mv /lib/modules/$(uname -r)/kernel/drivers/gpu/drm/tiny/mi0283qt.ko /lib/modules/$(uname -r)/kernel/drivers/gpu/drm/tiny/mi0283qt.BACK
|
||||
mv /lib/modules/$(uname -r)/kernel/drivers/staging/fbtft/fb_st7789v.ko /lib/modules/$(uname -r)/kernel/drivers/staging/fbtft/fb_st7789v.BACK
|
||||
mv st7789v_ada.ko /lib/modules/$(uname -r)/kernel/drivers/gpu/drm/tiny/mi0283qt.ko
|
||||
mv fb_st7789v.ko /lib/modules/$(uname -r)/kernel/drivers/staging/fbtft/fb_st7789v.ko
|
||||
popd
|
||||
fi
|
||||
|
||||
date=`date`
|
||||
|
||||
cat >> /boot/config.txt <<EOF
|
||||
# --- added by adafruit-pitft-helper $date ---
|
||||
hdmi_force_hotplug=1 # required for cases when HDMI is not plugged in!
|
||||
dtparam=spi=on
|
||||
dtparam=i2c1=on
|
||||
dtparam=i2c_arm=on
|
||||
|
|
@ -272,6 +290,7 @@ SUBSYSTEM=="input", ATTRS{name}=="touchmouse", ENV{DEVNAME}=="*event*", SYMLINK+
|
|||
EOF
|
||||
cat > /etc/udev/rules.d/95-ftcaptouch.rules <<EOF
|
||||
SUBSYSTEM=="input", ATTRS{name}=="EP0110M09", ENV{DEVNAME}=="*event*", SYMLINK+="input/touchscreen"
|
||||
SUBSYSTEM=="input", ATTRS{name}=="generic ft5x06*", ENV{DEVNAME}=="*event*", SYMLINK+="input/touchscreen"
|
||||
EOF
|
||||
cat > /etc/udev/rules.d/95-stmpe.rules <<EOF
|
||||
SUBSYSTEM=="input", ATTRS{name}=="*stmpe*", ENV{DEVNAME}=="*event*", SYMLINK+="input/touchscreen"
|
||||
|
|
@ -334,9 +353,9 @@ function uninstall_console() {
|
|||
|
||||
function install_fbcp() {
|
||||
echo "Installing cmake..."
|
||||
apt-get --yes --force-yes install cmake 1> /dev/null || { warning "Apt failed to install software!" && exit 1; }
|
||||
apt-get --yes --allow-downgrades --allow-remove-essential --allow-change-held-packages install cmake 1> /dev/null || { warning "Apt failed to install software!" && exit 1; }
|
||||
echo "Downloading rpi-fbcp..."
|
||||
cd /tmp
|
||||
pushd /tmp
|
||||
#curl -sLO https://github.com/tasanakorn/rpi-fbcp/archive/master.zip
|
||||
curl -sLO https://github.com/adafruit/rpi-fbcp/archive/master.zip
|
||||
echo "Uncompressing rpi-fbcp..."
|
||||
|
|
@ -351,7 +370,7 @@ function install_fbcp() {
|
|||
make 1> /dev/null || { warning "Failed to make fbcp!" && exit 1; }
|
||||
echo "Installing rpi-fbcp..."
|
||||
install fbcp /usr/local/bin/fbcp
|
||||
cd ~
|
||||
popd
|
||||
rm -rf /tmp/rpi-fbcp-master
|
||||
|
||||
# Start fbcp in the appropriate place, depending on init system:
|
||||
|
|
@ -387,6 +406,7 @@ function install_fbcp() {
|
|||
reconfig /boot/config.txt "^.*hdmi_force_hotplug.*$" "hdmi_force_hotplug=1"
|
||||
reconfig /boot/config.txt "^.*hdmi_group.*$" "hdmi_group=2"
|
||||
reconfig /boot/config.txt "^.*hdmi_mode.*$" "hdmi_mode=87"
|
||||
reconfig /boot/config.txt "^[^#]*dtoverlay=vc4-fkms-v3d.*$" "#dtoverlay=vc4-fkms-v3d"
|
||||
|
||||
# if there's X11 installed...
|
||||
if [ -e /etc/lightdm ]; then
|
||||
|
|
@ -401,11 +421,14 @@ function install_fbcp() {
|
|||
echo "Using native resolution"
|
||||
SCALE=1
|
||||
fi
|
||||
|
||||
|
||||
WIDTH=`python -c "print(int(${WIDTH_VALUES[PITFT_SELECT-1]} * ${SCALE}))"`
|
||||
HEIGHT=`python -c "print(int(${HEIGHT_VALUES[PITFT_SELECT-1]} * ${SCALE}))"`
|
||||
|
||||
reconfig /boot/config.txt "^.*hdmi_cvt.*$" "hdmi_cvt=${WIDTH} ${HEIGHT} 60 1 0 0 0"
|
||||
|
||||
if [ "${pitftrot}" == "90" ] || [ "${pitftrot}" == "270" ]; then
|
||||
if [ "${pitftrot}" == "90" ] || [ "${pitftrot}" == "270" ] || [ "${pitfttype}" == "st7789_240x320" ]; then
|
||||
# dont rotate HDMI on 90 or 270
|
||||
reconfig /boot/config.txt "^.*display_hdmi_rotate.*$" ""
|
||||
fi
|
||||
|
|
@ -445,11 +468,13 @@ EOF
|
|||
|
||||
function uninstall_fbcp() {
|
||||
uninstall_fbcp_rclocal
|
||||
sudo systemctl disable fbcp.service
|
||||
# Enable overscan compensation
|
||||
raspi-config nonint do_overscan 0
|
||||
# Set up HDMI parameters:
|
||||
echo "Configuring boot/config.txt for default HDMI"
|
||||
reconfig /boot/config.txt "^.*hdmi_force_hotplug.*$" "hdmi_force_hotplug=0"
|
||||
reconfig /boot/config.txt "^.*#.*dtoverlay=vc4-fkms-v3d.*$" "dtoverlay=vc4-fkms-v3d"
|
||||
sed -i -e '/^hdmi_group=2.*$/d' /boot/config.txt
|
||||
sed -i -e '/^hdmi_mode=87.*$/d' /boot/config.txt
|
||||
sed -i -e '/^hdmi_cvt=.*$/d' /boot/config.txt
|
||||
|
|
@ -508,29 +533,38 @@ selectN "PiTFT 2.4\", 2.8\" or 3.2\" resistive (240x320)" \
|
|||
"PiTFT 2.2\" no touch (240x320)" \
|
||||
"PiTFT 2.8\" capacitive touch (240x320)" \
|
||||
"PiTFT 3.5\" resistive touch (320x480)" \
|
||||
"Braincraft 1.54\" display (240x240)" \
|
||||
"MiniPiTFT 1.14\" display (240x135) - WARNING! CUTTING EDGE! WILL UPGRADE YOUR KERNEL TO LATEST" \
|
||||
"PiTFT Mini 1.3\" or 1.54\" display (240x240) - WARNING! WILL UPGRADE YOUR KERNEL TO LATEST" \
|
||||
"MiniPiTFT 1.14\" display (240x135) - WARNING! WILL UPGRADE YOUR KERNEL TO LATEST" \
|
||||
"ST7789V 2.0\" no touch (240x320) - WARNING! WILL UPGRADE YOUR KERNEL TO LATEST" \
|
||||
"Uninstall PiTFT" \
|
||||
"Quit without installing"
|
||||
PITFT_SELECT=$?
|
||||
if [ $PITFT_SELECT -gt 6 ]; then
|
||||
if [ $PITFT_SELECT -gt 8 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Select rotation:"
|
||||
selectN "90 degrees (landscape)" \
|
||||
"180 degrees (portait)" \
|
||||
"270 degrees (landscape)" \
|
||||
"0 degrees (portait)"
|
||||
PITFT_ROTATE=$?
|
||||
if [ $PITFT_ROTATE -gt 4 ]; then
|
||||
exit 1
|
||||
if [ $PITFT_SELECT -eq 8 ]; then
|
||||
UNINSTALL=true
|
||||
fi
|
||||
|
||||
|
||||
if ! $UNINSTALL; then
|
||||
echo "Select rotation:"
|
||||
selectN "90 degrees (landscape)" \
|
||||
"180 degrees (portrait)" \
|
||||
"270 degrees (landscape)" \
|
||||
"0 degrees (portrait)"
|
||||
PITFT_ROTATE=$?
|
||||
if [ $PITFT_ROTATE -gt 4 ]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
PITFT_ROTATIONS=("90" "180" "270" "0")
|
||||
PITFT_TYPES=("28r" "22" "28c" "35r" "st7789_240x240" "st7789_240x135")
|
||||
WIDTH_VALUES=(320 320 320 480 240)
|
||||
HEIGHT_VALUES=(240 240 240 320 240)
|
||||
HZ_VALUES=(64000000 64000000 64000000 32000000 64000000)
|
||||
PITFT_TYPES=("28r" "22" "28c" "35r" "st7789_240x240" "st7789_240x135" "st7789_240x320")
|
||||
WIDTH_VALUES=(320 320 320 480 240 240 320)
|
||||
HEIGHT_VALUES=(240 240 240 320 240 135 240)
|
||||
HZ_VALUES=(64000000 64000000 64000000 32000000 64000000 64000000)
|
||||
|
||||
|
||||
|
||||
|
|
@ -584,60 +618,73 @@ if [[ ! -e "$target_homedir" || ! -d "$target_homedir" ]]; then
|
|||
bail "$target_homedir must be an existing directory (use -u /home/foo to specify)"
|
||||
fi
|
||||
|
||||
pitfttype=${PITFT_TYPES[$PITFT_SELECT-1]}
|
||||
pitftrot=${PITFT_ROTATIONS[$PITFT_ROTATE-1]}
|
||||
if ! $UNINSTALL;
|
||||
then
|
||||
pitfttype=${PITFT_TYPES[$PITFT_SELECT-1]}
|
||||
pitftrot=${PITFT_ROTATIONS[$PITFT_ROTATE-1]}
|
||||
touchrot=$pitftrot
|
||||
|
||||
if [ "${pitfttype}" != "28r" ] && [ "${pitfttype}" != "28c" ] && [ "${pitfttype}" != "35r" ] && [ "${pitfttype}" != "22" ] && [ "${pitfttype}" != "st7789_240x240" ] && [ "${pitfttype}" != "st7789_240x320" ] && [ "${pitfttype}" != "st7789_240x135" ]; then
|
||||
echo "Type must be one of:"
|
||||
echo " '28r' (2.8\" resistive, PID 1601)"
|
||||
echo " '28c' (2.8\" capacitive, PID 1983)"
|
||||
echo " '35r' (3.5\" Resistive)"
|
||||
echo " '22' (2.2\" no touch)"
|
||||
echo " 'st7789_240x240' (1.54\" or 1.3\" no touch)"
|
||||
echo " 'st7789_320x240' (2.0\" no touch)"
|
||||
echo " 'st7789_240x135' (1.14\" no touch)"
|
||||
echo
|
||||
print_help
|
||||
fi
|
||||
|
||||
if [ "${pitfttype}" != "28r" ] && [ "${pitfttype}" != "28c" ] && [ "${pitfttype}" != "35r" ] && [ "${pitfttype}" != "22" ] && [ "${pitfttype}" != "st7789_240x240" ] && [ "${pitfttype}" != "st7789_240x135" ]; then
|
||||
echo "Type must be one of:"
|
||||
echo " '28r' (2.8\" resistive, PID 1601)"
|
||||
echo " '28c' (2.8\" capacitive, PID 1983)"
|
||||
echo " '35r' (3.5\" Resistive)"
|
||||
echo " '22' (2.2\" no touch)"
|
||||
echo " 'st7789_240x240' (1.54\" or 1.3\" no touch)"
|
||||
echo " 'st7789_240x135' 1.14\" no touch)"
|
||||
echo
|
||||
print_help
|
||||
fi
|
||||
info PITFT "System update"
|
||||
sysupdate || bail "Unable to apt-get update"
|
||||
|
||||
info PITFT "System update"
|
||||
sysupdate || bail "Unable to apt-get update"
|
||||
info PITFT "Installing Python libraries & Software..."
|
||||
softwareinstall || bail "Unable to install software"
|
||||
|
||||
info PITFT "Installing Python libraries & Software..."
|
||||
softwareinstall || bail "Unable to install software"
|
||||
info PITFT "Updating /boot/config.txt..."
|
||||
update_configtxt || bail "Unable to update /boot/config.txt"
|
||||
|
||||
info PITFT "Updating /boot/config.txt..."
|
||||
update_configtxt || bail "Unable to update /boot/config.txt"
|
||||
if [ "${pitfttype}" == "28r" ] || [ "${pitfttype}" == "35r" ] || [ "${pitfttype}" == "28c" ] ; then
|
||||
info PITFT "Updating SysFS rules for Touchscreen..."
|
||||
update_udev || bail "Unable to update /etc/udev/rules.d"
|
||||
|
||||
if [ "${pitfttype}" == "28r" ] || [ "${pitfttype}" == "35r" ] || [ "${pitfttype}" == "28c" ] ; then
|
||||
info PITFT "Updating SysFS rules for Touchscreen..."
|
||||
update_udev || bail "Unable to update /etc/udev/rules.d"
|
||||
info PITFT "Updating TSLib default calibration..."
|
||||
update_pointercal || bail "Unable to update /etc/pointercal"
|
||||
fi
|
||||
|
||||
info PITFT "Updating TSLib default calibration..."
|
||||
update_pointercal || bail "Unable to update /etc/pointercal"
|
||||
fi
|
||||
# ask for console access
|
||||
if ask "Would you like the console to appear on the PiTFT display?"; then
|
||||
info PITFT "Updating console to PiTFT..."
|
||||
uninstall_fbcp || bail "Unable to uninstall fbcp"
|
||||
install_console || bail "Unable to configure console"
|
||||
else
|
||||
info PITFT "Making sure console doesn't use PiTFT"
|
||||
uninstall_console || bail "Unable to configure console"
|
||||
|
||||
# ask for console access
|
||||
if ask "Would you like the console to appear on the PiTFT display?"; then
|
||||
info PITFT "Updating console to PiTFT..."
|
||||
uninstall_fbcp || bail "Unable to uninstall fbcp"
|
||||
install_console || bail "Unable to configure console"
|
||||
else
|
||||
info PITFT "Making sure console doesn't use PiTFT"
|
||||
uninstall_console || bail "Unable to configure console"
|
||||
if ask "Would you like the HDMI display to mirror to the PiTFT display?"; then
|
||||
info PITFT "Adding FBCP support..."
|
||||
install_fbcp || bail "Unable to configure fbcp"
|
||||
|
||||
if ask "Would you like the HDMI display to mirror to the PiTFT display?"; then
|
||||
info PITFT "Adding FBCP support..."
|
||||
install_fbcp || bail "Unable to configure fbcp"
|
||||
|
||||
if [ -e /etc/lightdm ]; then
|
||||
info PITFT "Updating X11 default calibration..."
|
||||
update_xorg || bail "Unable to update calibration"
|
||||
if [ -e /etc/lightdm ]; then
|
||||
info PITFT "Updating X11 default calibration..."
|
||||
update_xorg || bail "Unable to update calibration"
|
||||
fi
|
||||
else
|
||||
# remove fbcp
|
||||
uninstall_fbcp || bail "Unable to uninstall fbcp"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
info PITFT "Uninstalling PiTFT"
|
||||
uninstall_bootconfigtxt
|
||||
uninstall_console
|
||||
uninstall_fbcp
|
||||
uninstall_fbcp_rclocal
|
||||
uninstall_etc_modules
|
||||
fi
|
||||
|
||||
|
||||
#info PITFT "Updating X11 setup tweaks..."
|
||||
#update_x11profile || bail "Unable to update X11 setup"
|
||||
|
||||
91
converted_shell_scripts/adafruit_fanservice.sh
Normal file
91
converted_shell_scripts/adafruit_fanservice.sh
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [ $(id -u) -ne 0 ]; then
|
||||
echo "Installer must be run as root."
|
||||
echo "Try 'sudo bash $0'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
clear
|
||||
echo "This script will install Adafruit"
|
||||
echo "fan service, which will turn on an"
|
||||
echo "external fan controlled by a given pin"
|
||||
echo
|
||||
echo "Operations performed include:"
|
||||
echo "- Create a Fan Service File"
|
||||
echo "- Enable Fan Service"
|
||||
echo "- Automatically Start Fan Service"
|
||||
echo " on System startup"
|
||||
echo
|
||||
echo "Run time < 1 minute. Reboot not required."
|
||||
echo
|
||||
|
||||
group=ADAFRUIT
|
||||
function info() {
|
||||
system="$1"
|
||||
group="${system}"
|
||||
shift
|
||||
FG="1;32m"
|
||||
BG="40m"
|
||||
echo -e "[\033[${FG}\033[${BG}${system}\033[0m] $*"
|
||||
}
|
||||
|
||||
|
||||
function bail() {
|
||||
FG="1;31m"
|
||||
BG="40m"
|
||||
echo -en "[\033[${FG}\033[${BG}${group}\033[0m] "
|
||||
if [ -z "$1" ]; then
|
||||
echo "Exiting due to error"
|
||||
else
|
||||
echo "Exiting due to error: $*"
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ "$1" != '-y' ]; then
|
||||
echo -n "CONTINUE? [y/N]"
|
||||
read
|
||||
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
|
||||
echo "Canceled."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Continuing..."
|
||||
# check init system (technique borrowed from raspi-config):
|
||||
info FAN 'Checking init system...'
|
||||
if command -v systemctl > /dev/null && systemctl | grep -q '\-\.mount'; then
|
||||
echo "Found systemd, OK!"
|
||||
elif [ -f /etc/init.d/cron ] && [ ! -h /etc/init.d/cron ]; then
|
||||
bail "Found sysvinit, but we require systemd"
|
||||
else
|
||||
bail "Unrecognised init system"
|
||||
fi
|
||||
|
||||
info FAN 'Adding adafruit_fan.service'
|
||||
cat > /etc/systemd/system/adafruit_fan.service <<EOF
|
||||
[Unit]
|
||||
Description=Fan service for some Adafruit boards
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStartPre=-/bin/bash -c 'echo 4 >/sys/class/gpio/export'
|
||||
ExecStartPre=/bin/bash -c 'echo out >/sys/class/gpio/gpio4/direction'
|
||||
ExecStart=/bin/bash -c 'echo 1 >/sys/class/gpio/gpio4/value'
|
||||
|
||||
RemainAfterExit=true
|
||||
ExecStop=/bin/bash -c 'echo 0 >/sys/class/gpio/gpio4/value'
|
||||
StandardOutput=journal
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
info FAN 'Enabling adafruit_fan.service'
|
||||
sudo systemctl enable adafruit_fan.service
|
||||
sudo systemctl start adafruit_fan.service
|
||||
info FAN 'Done!'
|
||||
echo "You can stop the fan service with 'sudo systemctl stop adafruit_fan.service'"
|
||||
echo "You can start the fan service with 'sudo systemctl start adafruit_fan.service'"
|
||||
|
|
@ -31,10 +31,10 @@ forcesudo="no" # whether the script requires to be ran with root privileges
|
|||
promptreboot="no" # whether the script should always prompt user to reboot
|
||||
mininstall="no" # whether the script enforces minimum install routine
|
||||
customcmd="yes" # whether to execute commands specified before exit
|
||||
armhfonly="yes" # whether the script is allowed to run on other arch
|
||||
armv6="yes" # whether armv6 processors are supported
|
||||
armv7="yes" # whether armv7 processors are supported
|
||||
armv8="yes" # whether armv8 processors are supported
|
||||
arm64="yes" # whether arm64 processors are supported
|
||||
raspbianonly="no" # whether the script is allowed to run on other OSes
|
||||
osreleases=( "Raspbian" ) # list os-releases supported
|
||||
oswarning=( "Debian" "Kano" "Mate" "PiTop" "Ubuntu" ) # list experimental os-releases
|
||||
|
|
@ -46,14 +46,19 @@ ASK_TO_REBOOT=false
|
|||
CURRENT_SETTING=false
|
||||
UPDATE_DB=false
|
||||
|
||||
BOOTCMD=/boot/cmdline.txt
|
||||
CONFIG=/boot/config.txt
|
||||
BOOTCMD=/boot/firmware/cmdline.txt
|
||||
CONFIG=/boot/firmware/config.txt
|
||||
APTSRC=/etc/apt/sources.list
|
||||
INITABCONF=/etc/inittab
|
||||
BLACKLIST=/etc/modprobe.d/raspi-blacklist.conf
|
||||
LOADMOD=/etc/modules
|
||||
DTBODIR=/boot/overlays
|
||||
|
||||
# Fall back to old location
|
||||
if ! test -f $CONFIG; then
|
||||
CONFIG=/boot/config.txt
|
||||
fi
|
||||
|
||||
# function define
|
||||
|
||||
confirm() {
|
||||
|
|
@ -139,9 +144,13 @@ sysreboot() {
|
|||
}
|
||||
|
||||
arch_check() {
|
||||
IS_ARM64=false
|
||||
IS_ARMHF=false
|
||||
IS_ARMv6=false
|
||||
|
||||
if uname -m | grep "aarch64" > /dev/null; then
|
||||
IS_ARM64=true
|
||||
fi
|
||||
if uname -m | grep "armv.l" > /dev/null; then
|
||||
IS_ARMHF=true
|
||||
if uname -m | grep "armv6l" > /dev/null; then
|
||||
|
|
@ -228,10 +237,12 @@ raspbian_check() {
|
|||
if [ -f /etc/os-release ]; then
|
||||
if cat /etc/os-release | grep "/sid" > /dev/null; then
|
||||
IS_SUPPORTED=false && IS_EXPERIMENTAL=true
|
||||
elif cat /etc/os-release | grep "bullseye" > /dev/null; then
|
||||
IS_SUPPORTED=false && IS_EXPERIMENTAL=true
|
||||
elif cat /etc/os-release | grep "buster" > /dev/null; then
|
||||
IS_SUPPORTED=false && IS_EXPERIMENTAL=true
|
||||
elif cat /etc/os-release | grep "stretch" > /dev/null; then
|
||||
IS_SUPPORTED=false && IS_EXPERIMENTAL=true
|
||||
IS_SUPPORTED=false && IS_EXPERIMENTAL=false
|
||||
elif cat /etc/os-release | grep "jessie" > /dev/null; then
|
||||
IS_SUPPORTED=true && IS_EXPERIMENTAL=false
|
||||
elif cat /etc/os-release | grep "wheezy" > /dev/null; then
|
||||
|
|
@ -263,13 +274,16 @@ if [ $debugmode != "no" ]; then
|
|||
newline
|
||||
fi
|
||||
|
||||
if ! $IS_ARMHF; then
|
||||
if ! $IS_ARMHF && ! $IS_ARM64; then
|
||||
warning "This hardware is not supported, sorry!"
|
||||
warning "Config files have been left untouched"
|
||||
newline && exit 1
|
||||
fi
|
||||
|
||||
if $IS_ARMv8 && [ $armv8 == "no" ]; then
|
||||
if $IS_ARM64 && [ $arm64 == "no" ]; then
|
||||
warning "Sorry, your CPU is not supported by this installer"
|
||||
newline && exit 1
|
||||
elif $IS_ARMv8 && [ $armv8 == "no" ]; then
|
||||
warning "Sorry, your CPU is not supported by this installer"
|
||||
newline && exit 1
|
||||
elif $IS_ARMv7 && [ $armv7 == "no" ]; then
|
||||
119
converted_shell_scripts/i2smic.sh
Normal file
119
converted_shell_scripts/i2smic.sh
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
#!/bin/bash
|
||||
#-------------------------------------------------------------------------
|
||||
# Installer script for I2S microphone support on Raspberry Pi
|
||||
#
|
||||
# 2020/04/15
|
||||
# 2020/07/08 remove DKMS
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
############################ Script assisters ############################
|
||||
|
||||
# Given a list of strings representing options, display each option
|
||||
# preceded by a number (1 to N), display a prompt, check input until
|
||||
# a valid number within the selection range is entered.
|
||||
selectN() {
|
||||
for ((i=1; i<=$#; i++)); do
|
||||
echo $i. ${!i}
|
||||
done
|
||||
echo
|
||||
REPLY=""
|
||||
while :
|
||||
do
|
||||
echo -n "SELECT 1-$#: "
|
||||
read
|
||||
if [[ $REPLY -ge 1 ]] && [[ $REPLY -le $# ]]; then
|
||||
return $REPLY
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
function ask() {
|
||||
# http://djm.me/ask
|
||||
while true; do
|
||||
|
||||
if [ "${2:-}" = "Y" ]; then
|
||||
prompt="Y/n"
|
||||
default=Y
|
||||
elif [ "${2:-}" = "N" ]; then
|
||||
prompt="y/N"
|
||||
default=N
|
||||
else
|
||||
prompt="y/n"
|
||||
default=
|
||||
fi
|
||||
|
||||
# Ask the question
|
||||
read -p "$1 [$prompt] " REPLY
|
||||
|
||||
# Default?
|
||||
if [ -z "$REPLY" ]; then
|
||||
REPLY=$default
|
||||
fi
|
||||
|
||||
# Check if the reply is valid
|
||||
case "$REPLY" in
|
||||
Y*|y*) return 0 ;;
|
||||
N*|n*) return 1 ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
####################################################### MAIN
|
||||
|
||||
clear
|
||||
echo "This script downloads and installs"
|
||||
echo "I2S microphone support."
|
||||
echo
|
||||
|
||||
echo "Select Pi Model:"
|
||||
selectN "Pi 0 or 0W" \
|
||||
"Pi 2 or 3" \
|
||||
"Pi 4"
|
||||
PIMODEL_SELECT=$(($?-1))
|
||||
|
||||
ask "Auto load module at boot?"
|
||||
AUTO_LOAD=$?
|
||||
|
||||
echo
|
||||
echo "Installing..."
|
||||
|
||||
# Get needed packages
|
||||
apt-get -y install git raspberrypi-kernel-headers
|
||||
|
||||
# Clone the repo
|
||||
git clone https://github.com/adafruit/Raspberry-Pi-Installer-Scripts.git
|
||||
|
||||
# Build and install the module
|
||||
cd Raspberry-Pi-Installer-Scripts/i2s_mic_module
|
||||
make clean
|
||||
make
|
||||
make install
|
||||
|
||||
# Setup auto load at boot if selected
|
||||
if [ $AUTO_LOAD = 0 ]; then
|
||||
cat > /etc/modules-load.d/snd-i2smic-rpi.conf<<EOF
|
||||
snd-i2smic-rpi
|
||||
EOF
|
||||
cat > /etc/modprobe.d/snd-i2smic-rpi.conf<<EOF
|
||||
options snd-i2smic-rpi rpi_platform_generation=$PIMODEL_SELECT
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Enable I2S overlay
|
||||
sed -i -e 's/#dtparam=i2s/dtparam=i2s/g' /boot/config.txt
|
||||
|
||||
# Done
|
||||
echo "DONE."
|
||||
echo
|
||||
echo "Settings take effect on next boot."
|
||||
echo
|
||||
echo -n "REBOOT NOW? [y/N] "
|
||||
read
|
||||
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
|
||||
echo "Exiting without reboot."
|
||||
exit 0
|
||||
fi
|
||||
echo "Reboot started..."
|
||||
reboot
|
||||
exit 0
|
||||
|
||||
|
|
@ -6,6 +6,21 @@
|
|||
# chmod +x libgpiod.sh
|
||||
# ./libgpiod.sh
|
||||
|
||||
is_legacy=0
|
||||
|
||||
# Loop through arguments and process them
|
||||
for arg in "$@"
|
||||
do
|
||||
case $arg in
|
||||
-l|--legacy)
|
||||
is_legacy=1
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo "Installing build requirements - this may take a few minutes!"
|
||||
echo
|
||||
|
|
@ -35,6 +50,11 @@ echo
|
|||
cd "$build_dir"
|
||||
git clone git://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git .
|
||||
|
||||
if test $is_legacy = 1; then
|
||||
git checkout v1.4.2 -b v1.4.2
|
||||
fi
|
||||
|
||||
|
||||
echo "Building libgpiod"
|
||||
echo
|
||||
|
||||
40
converted_shell_scripts/rpi-pin-kernel-firmware.sh
Normal file
40
converted_shell_scripts/rpi-pin-kernel-firmware.sh
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#!/bin/sh
|
||||
# rpi-pin-kernel-firmware: Pin a specific version of the rpi kernel and firmware
|
||||
|
||||
set -e
|
||||
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "Usage: $0 kernel-version"
|
||||
echo
|
||||
echo "e.g., $0 1.20201126-1"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! dpkg -l raspberrypi-kernel:armhf > /dev/null 2>&1; then
|
||||
echo "This command is designed to run only on Raspbian with the armhf kernel"
|
||||
echo 99
|
||||
fi
|
||||
|
||||
|
||||
if [ `id -u` -ne 0 ]; then
|
||||
echo "If necessary, enter your password to run this script as root"
|
||||
exec sudo sh "$0" "$1"
|
||||
fi
|
||||
|
||||
version=$1
|
||||
fileversion=$(echo $version | cut -d':' -f 2)
|
||||
base=http://archive.raspberrypi.org/debian/pool/main/r/raspberrypi-firmware/
|
||||
packagelist="libraspberrypi0 libraspberrypi-bin libraspberrypi-dev libraspberrypi-doc raspberrypi-bootloader raspberrypi-kernel raspberrypi-kernel-headers"
|
||||
|
||||
set --
|
||||
for package in $packagelist; do
|
||||
filename="${package}_${fileversion}_armhf.deb"
|
||||
set -- "$@" "$filename"
|
||||
wget --continue -O "$filename" "$base/$filename"
|
||||
done
|
||||
|
||||
dpkg -i "$@"
|
||||
|
||||
for package in $packagelist; do
|
||||
/usr/bin/printf "Package: $package\nPin: version ${version}\nPin-Priority:999\n\n"
|
||||
done > /etc/apt/preferences.d/99-adafruit-pin-kernel
|
||||
54
i2s_mic_module/Makefile
Normal file
54
i2s_mic_module/Makefile
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
MOD_NAME := snd-i2smic-rpi
|
||||
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
|
||||
# call from kernel build system
|
||||
|
||||
all:
|
||||
@echo "Building from the kernel build system"
|
||||
@echo "Module build: $(CONFIG_SND_I2S_RPI)"
|
||||
@echo "Name: $(MOD_NAME)"
|
||||
|
||||
obj-$(CONFIG_SND_I2S_RPI) := $(MOD_NAME).o
|
||||
|
||||
else
|
||||
# external module build
|
||||
|
||||
EXTRA_FLAGS += -I$(PWD)
|
||||
|
||||
#
|
||||
# KDIR is a path to a directory containing kernel source.
|
||||
# It can be specified on the command line passed to make to enable the module to
|
||||
# be built and installed for a kernel other than the one currently running.
|
||||
# By default it is the path to the symbolic link created when
|
||||
# the current kernel's modules were installed, but
|
||||
# any valid path to the directory in which the target kernel's source is located
|
||||
# can be provided on the command line.
|
||||
#
|
||||
KDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
MDIR ?= /lib/modules/$(shell uname -r)
|
||||
PWD := $(shell pwd)
|
||||
|
||||
export CONFIG_SND_I2S_RPI := m
|
||||
|
||||
all:
|
||||
$(MAKE) -C $(KDIR) M=$(PWD) modules
|
||||
|
||||
clean:
|
||||
$(MAKE) -C $(KDIR) M=$(PWD) clean
|
||||
|
||||
help:
|
||||
$(MAKE) -C $(KDIR) M=$(PWD) help
|
||||
|
||||
install: snd-i2smic-rpi.ko
|
||||
rm -f ${MDIR}/kernel/sound/drivers/$(MOD_NAME).ko
|
||||
install -m644 -b -D $(MOD_NAME).ko ${MDIR}/kernel/sound/drivers/$(MOD_NAME).ko
|
||||
depmod -a
|
||||
|
||||
uninstall:
|
||||
rm -rf ${MDIR}/kernel/sound/drivers/$(MOD_NAME).ko
|
||||
depmod -a
|
||||
|
||||
endif
|
||||
|
||||
.PHONY : all clean install uninstall
|
||||
114
i2s_mic_module/README.md
Normal file
114
i2s_mic_module/README.md
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
**Driver for the Adafruit I2S MEMS Microphone**
|
||||
|
||||
[Product learn page on Adafruit](https://learn.adafruit.com/adafruit-i2s-mems-microphone-breakout/overview).
|
||||
|
||||
Known problems with this driver: Low vol level. While you can use the alsa magic socery to make an alsa softvol input, that approach won't work out of the box with anything that uses Pulseaudio. If you have any idea how to make this work with Pulse, please drop me a line.
|
||||
|
||||
Installing the I2S microphone driver the easy way
|
||||
====================================
|
||||
|
||||
If you use Raspbian or any Debian-derived distribution, [go to the releases tab](https://github.com/htruong/snd-i2s_rpi/releases) and download the newest deb version.
|
||||
|
||||
Then do the following
|
||||
|
||||
```bash
|
||||
|
||||
# Installing raspberrypi-kernel-headers works only if you haven't messed with
|
||||
# the rpi-update thing.
|
||||
# If you did, then you would have to do the rpi-source method
|
||||
# to get the kernel headers. See:
|
||||
# https://learn.adafruit.com/adafruit-i2s-mems-microphone-breakout/raspberry-pi-wiring-and-test#kernel-compiling
|
||||
|
||||
$ sudo apt install dkms raspberrypi-kernel-headers
|
||||
|
||||
$ sudo dpkg -i snd-i2s-rpi-dkms_0.0.2_all.deb
|
||||
|
||||
# For this to work, remember to modify these first:
|
||||
# /boot/firmware/config.txt -> dtparam=i2s=on
|
||||
# and
|
||||
# /etc/modules -> snd-bcm2835
|
||||
# remember to reboot
|
||||
|
||||
$ sudo modprobe snd-i2s_rpi rpi_platform_generation=0
|
||||
|
||||
# rpi_platform_generation=0 for Raspberry Pi 1 B/A/A+, 0
|
||||
# do not add anything for everything else (2/3).
|
||||
|
||||
# see if it works
|
||||
|
||||
$ dmesg | grep i2s
|
||||
|
||||
# it should say blah.i2s mapping OK
|
||||
|
||||
# [ 3.519017] snd_i2s_rpi: loading out-of-tree module taints kernel.
|
||||
# [ 3.519881] snd-i2s_rpi: Version 0.0.2
|
||||
# [ 3.519889] snd-i2s_rpi: Setting platform to 20203000.i2s
|
||||
# [ 7.624559] asoc-simple-card asoc-simple-card.0: ASoC: CPU DAI 20203000.i2s not registered - will retry
|
||||
# ... snip ...
|
||||
# [ 9.507142] asoc-simple-card asoc-simple-card.0: snd-soc-dummy-dai <-> 20203000.i2s mapping ok
|
||||
|
||||
$ arecord -l
|
||||
|
||||
# it should list your mic
|
||||
# note that the default vol level is very low, you need
|
||||
# to follow the ladyada's guide to make it hearable
|
||||
|
||||
|
||||
# If you want it to load automatically at startup
|
||||
|
||||
# 1. Add to /etc/modules
|
||||
# snd-i2s_rpi
|
||||
|
||||
# 2. If you have a Pi old-gen, you need to do this:
|
||||
# create file called /etc/modprobe.d/snd-i2s_rpi.conf
|
||||
# add this line
|
||||
# options snd-i2s_rpi rpi_platform_generation=0
|
||||
|
||||
```
|
||||
|
||||
|
||||
Installing as a stand-alone module
|
||||
====================================
|
||||
|
||||
make
|
||||
sudo make install
|
||||
|
||||
To load the driver manually, run this as root:
|
||||
|
||||
modprobe snd-i2s_rpi
|
||||
|
||||
You may also specify custom toolchains by using the `CROSS_COMPILE` flag:
|
||||
|
||||
CROSS_COMPILE=/usr/local/bin/arm-eabi-
|
||||
|
||||
|
||||
Installing as a part of the kernel
|
||||
======================================
|
||||
|
||||
Instructions to come later. Who would ever want to do that?
|
||||
|
||||
|
||||
|
||||
|
||||
Installing as a DKMS module
|
||||
=================================
|
||||
|
||||
You can have even more fun with snd-i2s\_rpi by installing it as a DKMS module has the main advantage of being auto-compiled (and thus, possibly surviving) between kernel upgrades.
|
||||
|
||||
First, get dkms. On Raspbian this should be:
|
||||
|
||||
sudo apt install dkms
|
||||
|
||||
Then copy the root of this repository to `/usr/share`:
|
||||
|
||||
sudo cp -R . /usr/src/snd-i2s_rpi-0.0.2 (or whatever version number declared on dkms.conf is)
|
||||
sudo dkms add -m snd-i2s_rpi -v 0.0.2
|
||||
|
||||
Build and load the module:
|
||||
|
||||
sudo dkms build -m snd-i2s_rpi -v 0.0.2
|
||||
sudo dkms install -m snd-i2s_rpi -v 0.0.2
|
||||
|
||||
Now you have a proper dkms module that will work for a long time... hopefully.
|
||||
|
||||
|
||||
7
i2s_mic_module/dkms.conf
Normal file
7
i2s_mic_module/dkms.conf
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
PACKAGE_NAME="snd-i2smic-rpi"
|
||||
PACKAGE_VERSION="0.1.0"
|
||||
MAKE="KDIR=/lib/modules/$kernelver/build MDIR=/lib/modules/$kernelver make"
|
||||
CLEAN="make clean"
|
||||
BUILT_MODULE_NAME[0]="snd-i2smic-rpi"
|
||||
AUTOINSTALL="yes"
|
||||
DEST_MODULE_LOCATION="/kernel/sound/drivers"
|
||||
151
i2s_mic_module/snd-i2smic-rpi.c
Normal file
151
i2s_mic_module/snd-i2smic-rpi.c
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: snd-i2smic-rpi
|
||||
*
|
||||
* Description: I2S microphone kernel module
|
||||
*
|
||||
* Version: 0.1.0
|
||||
* Created: 2020-04-14
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Pi4 Mods: Carter Nelson
|
||||
* Orig Author: Huan Truong (htruong@tnhh.net), originally written by Paul Creaser
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <sound/simple_card.h>
|
||||
#include <linux/delay.h>
|
||||
#include "snd-i2smic-rpi.h"
|
||||
|
||||
/*
|
||||
* modified for linux 4.1.5
|
||||
* inspired by https://github.com/msperl/spi-config
|
||||
* with thanks for https://github.com/notro/rpi-source/wiki
|
||||
* as well as Florian Meier for the rpi i2s and dma drivers
|
||||
*
|
||||
* to use a differant (simple-card compatible) codec
|
||||
* change the codec name string in two places and the
|
||||
* codec_dai name string. (see codec's source file)
|
||||
*
|
||||
*
|
||||
* N.B. playback vs capture is determined by the codec choice
|
||||
* */
|
||||
|
||||
static struct simple_card_info card_info;
|
||||
static struct platform_device card_device;
|
||||
|
||||
/*
|
||||
* Setup command line parameter
|
||||
*/
|
||||
static short rpi_platform_generation;
|
||||
module_param(rpi_platform_generation, short, 0);
|
||||
MODULE_PARM_DESC(rpi_platform_generation, "Raspberry Pi generation: 0=Pi0, 1=Pi2/3, 2=Pi4");
|
||||
|
||||
/*
|
||||
* Dummy callback for release
|
||||
*/
|
||||
void device_release_callback(struct device *dev) { /* do nothing */ };
|
||||
|
||||
/*
|
||||
* Setup the card info
|
||||
*/
|
||||
static struct simple_card_info default_card_info = {
|
||||
.card = "snd_rpi_i2s_card", // -> snd_soc_card.name
|
||||
.name = "simple-card_codec_link", // -> snd_soc_dai_link.name
|
||||
.codec = "snd-soc-dummy", // "dmic-codec", // -> snd_soc_dai_link.codec_name
|
||||
.platform = "not-set.i2s",
|
||||
.daifmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS,
|
||||
.cpu_dai = {
|
||||
.name = "not-set.i2s", // -> snd_soc_dai_link.cpu_dai_name
|
||||
.sysclk = 0
|
||||
},
|
||||
.codec_dai = {
|
||||
.name = "snd-soc-dummy-dai", //"dmic-codec", // -> snd_soc_dai_link.codec_dai_name
|
||||
.sysclk = 0
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Setup the card device
|
||||
*/
|
||||
static struct platform_device default_card_device = {
|
||||
.name = "asoc-simple-card", //module alias
|
||||
.id = 0,
|
||||
.num_resources = 0,
|
||||
.dev = {
|
||||
.release = &device_release_callback,
|
||||
.platform_data = &default_card_info, // *HACK ALERT*
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Callback for module initialization
|
||||
*/
|
||||
int i2s_mic_rpi_init(void)
|
||||
{
|
||||
const char *dmaengine = "bcm2708-dmaengine"; //module name
|
||||
static char *card_platform;
|
||||
int ret;
|
||||
|
||||
printk(KERN_INFO "snd-i2smic-rpi: Version %s\n", SND_I2SMIC_RPI_VERSION);
|
||||
|
||||
// Set platform
|
||||
switch (rpi_platform_generation) {
|
||||
case 0:
|
||||
// Pi Zero
|
||||
card_platform = "20203000.i2s";
|
||||
break;
|
||||
case 1:
|
||||
// Pi 2 and 3
|
||||
card_platform = "3f203000.i2s";
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
// Pi 4
|
||||
card_platform = "fe203000.i2s";
|
||||
break;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "snd-i2smic-rpi: Setting platform to %s\n", card_platform);
|
||||
|
||||
// request DMA engine module
|
||||
ret = request_module(dmaengine);
|
||||
pr_alert("request module load '%s': %d\n",dmaengine, ret);
|
||||
|
||||
// update info
|
||||
card_info = default_card_info;
|
||||
card_info.platform = card_platform;
|
||||
card_info.cpu_dai.name = card_platform;
|
||||
|
||||
card_device = default_card_device;
|
||||
card_device.dev.platform_data = &card_info;
|
||||
|
||||
// register the card device
|
||||
ret = platform_device_register(&card_device);
|
||||
pr_alert("register platform device '%s': %d\n",card_device.name, ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback for module exit
|
||||
*/
|
||||
void i2s_mic_rpi_exit(void)
|
||||
{
|
||||
platform_device_unregister(&card_device);
|
||||
pr_alert("i2s mic module unloaded\n");
|
||||
}
|
||||
|
||||
// Plumb it up
|
||||
module_init(i2s_mic_rpi_init);
|
||||
module_exit(i2s_mic_rpi_exit);
|
||||
MODULE_DESCRIPTION("ASoC simple-card I2S Microphone");
|
||||
MODULE_AUTHOR("Carter Nelson");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
6
i2s_mic_module/snd-i2smic-rpi.h
Normal file
6
i2s_mic_module/snd-i2smic-rpi.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef _SND_I2SMIC_RPI_H_
|
||||
#define _SND_I2SMIC_RPI_H_
|
||||
|
||||
#define SND_I2SMIC_RPI_VERSION "0.1.0"
|
||||
|
||||
#endif
|
||||
136
i2samp.py
Normal file
136
i2samp.py
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
import os
|
||||
|
||||
try:
|
||||
from adafruit_shell import Shell
|
||||
from clint.textui import colored
|
||||
except ImportError:
|
||||
raise RuntimeError("The library 'adafruit_shell' was not found. To install, try typing: sudo pip3 install adafruit-python-shell")
|
||||
|
||||
shell = Shell()
|
||||
|
||||
BLACKLIST = "/etc/modprobe.d/raspi-blacklist.conf"
|
||||
PRODUCT_NAME = "I2S Amplifier"
|
||||
OVERLAY = "googlevoicehat-soundcard"
|
||||
|
||||
def driver_loaded(driver_name):
|
||||
return shell.run_command(f"lsmod | grep -q '{driver_name}'", suppress_message=True)
|
||||
|
||||
def main():
|
||||
reboot = False
|
||||
shell.clear()
|
||||
if not shell.is_raspberry_pi():
|
||||
shell.bail("Non-Raspberry Pi board detected.")
|
||||
print("\nThis script will install everything needed to use\n"
|
||||
f"{PRODUCT_NAME}.\n")
|
||||
print(colored.red("--- Warning ---"))
|
||||
print("\nAlways be careful when running scripts and commands\n"
|
||||
"copied from the internet. Ensure they are from a\n"
|
||||
"trusted source.\n")
|
||||
if not shell.prompt("Do you wish to continue?"):
|
||||
print("\nAborting...")
|
||||
shell.exit()
|
||||
|
||||
print("\nChecking hardware requirements...")
|
||||
|
||||
# Enable I2S overlay
|
||||
config = shell.get_boot_config()
|
||||
if config is None:
|
||||
shell.bail("No Device Tree Detected, not supported")
|
||||
|
||||
print(f"\nAdding Device Tree Entry to {config}")
|
||||
|
||||
if shell.pattern_search(config, f"^dtoverlay={OVERLAY}$"):
|
||||
print("dtoverlay already active")
|
||||
else:
|
||||
shell.write_text_file(config, f"dtoverlay={OVERLAY}")
|
||||
reboot = True
|
||||
|
||||
if os.path.exists(BLACKLIST):
|
||||
print("\nCommenting out Blacklist entry in", BLACKLIST)
|
||||
shell.pattern_replace(BLACKLIST, "^blacklist[[:space:]]*snd_soc_max98357a.*", "#blacklist snd_soc_max98357a")
|
||||
shell.pattern_replace(BLACKLIST, "^blacklist[[:space:]]*snd_soc_max98357a_i2c.*", "#blacklist snd_soc_max98357a_i2c")
|
||||
shell.pattern_replace(BLACKLIST, "^blacklist[[:space:]]*snd_soc_max98357a.*", "#blacklist snd_soc_max98357a")
|
||||
|
||||
print("Configuring sound output")
|
||||
if os.path.exists("/etc/asound.conf"):
|
||||
if os.path.exists("/etc/asound.conf.old"):
|
||||
shell.remove("/etc/asound.conf.old")
|
||||
shell.move("/etc/asound.conf", "/etc/asound.conf.old")
|
||||
shell.write_text_file("~/asound.conf",
|
||||
"""
|
||||
pcm.speakerbonnet {
|
||||
type hw card 0
|
||||
}
|
||||
|
||||
pcm.dmixer {
|
||||
type dmix
|
||||
ipc_key 1024
|
||||
ipc_perm 0666
|
||||
slave {
|
||||
pcm "speakerbonnet"
|
||||
period_time 0
|
||||
period_size 1024
|
||||
buffer_size 8192
|
||||
rate 44100
|
||||
channels 2
|
||||
}
|
||||
}
|
||||
|
||||
ctl.dmixer {
|
||||
type hw card 0
|
||||
}
|
||||
|
||||
pcm.softvol {
|
||||
type softvol
|
||||
slave.pcm "dmixer"
|
||||
control.name "PCM"
|
||||
control.card 0
|
||||
}
|
||||
|
||||
ctl.softvol {
|
||||
type hw card 0
|
||||
}
|
||||
|
||||
pcm.!default {
|
||||
type plug
|
||||
slave.pcm "softvol"
|
||||
}
|
||||
""")
|
||||
shell.move("~/asound.conf", "/etc/asound.conf")
|
||||
|
||||
|
||||
print("Installing aplay systemd unit")
|
||||
shell.write_text_file("/etc/systemd/system/aplay.service", """
|
||||
[Unit]
|
||||
Description=Invoke aplay from /dev/zero at system start.
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/aplay -D default -t raw -r 44100 -c 2 -f S16_LE /dev/zero
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target""", append=False)
|
||||
|
||||
shell.run_command("sudo systemctl daemon-reload")
|
||||
shell.run_command("sudo systemctl disable aplay")
|
||||
print("\nYou can optionally activate '/dev/zero' playback in\n"
|
||||
"the background at boot. This will remove all\n"
|
||||
"popping/clicking but does use some processor time.\n\n")
|
||||
if shell.prompt("Activate '/dev/zero' playback in background? [RECOMMENDED]\n", default="y"):
|
||||
shell.run_command("sudo systemctl enable aplay")
|
||||
reboot = True
|
||||
|
||||
if driver_loaded("max98357a"):
|
||||
print(f"\nWe can now test your {PRODUCT_NAME}")
|
||||
shell.warn("Set your speakers at a low volume if possible!")
|
||||
if shell.prompt("Do you wish to test your system now?"):
|
||||
print("Testing...")
|
||||
shell.run_command("speaker-test -l5 -c2 -t wav")
|
||||
print("\n" + colored.green("All done!"))
|
||||
print("\nEnjoy your new $productname!")
|
||||
if reboot:
|
||||
shell.prompt_reboot()
|
||||
|
||||
# Main function
|
||||
if __name__ == "__main__":
|
||||
shell.require_root()
|
||||
main()
|
||||
77
i2smic.py
Normal file
77
i2smic.py
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
import os
|
||||
|
||||
try:
|
||||
from adafruit_shell import Shell
|
||||
except ImportError:
|
||||
raise RuntimeError("The library 'adafruit_shell' was not found. To install, try typing: sudo pip3 install adafruit-python-shell")
|
||||
|
||||
shell = Shell()
|
||||
|
||||
def main():
|
||||
shell.clear()
|
||||
boot_config = shell.get_boot_config()
|
||||
print("""This script downloads and installs
|
||||
I2S microphone support.
|
||||
""")
|
||||
if not shell.is_raspberry_pi():
|
||||
shell.bail("Non-Raspberry Pi board detected.")
|
||||
pi_model = shell.get_board_model()
|
||||
print("{} detected.\n".format(pi_model))
|
||||
if pi_model in ("RASPBERRY_PI_ZERO", "RASPBERRY_PI_ZERO_W", "RASPBERRY_PI_B_REV2"):
|
||||
pimodel_select = 0
|
||||
elif pi_model in ("RASPBERRY_PI_2B", "RASPBERRY_PI_3B", "RASPBERRY_PI_3B_PLUS", "RASPBERRY_PI_3A_PLUS", "RASPBERRY_PI_ZERO_2_W"):
|
||||
pimodel_select = 1
|
||||
elif pi_model in ("RASPBERRY_PI_4B", "RASPBERRY_PI_CM4", "RASPBERRY_PI_400"):
|
||||
pimodel_select = 2
|
||||
else:
|
||||
shell.bail("Unsupported Pi board detected.")
|
||||
|
||||
auto_load = (
|
||||
not shell.argument_exists('noautoload') and
|
||||
shell.prompt("Auto load module at boot?", force_arg="autoload"))
|
||||
|
||||
print("""
|
||||
Installing...""")
|
||||
|
||||
# Get needed packages
|
||||
shell.run_command("apt-get -y install git raspberrypi-kernel-headers")
|
||||
|
||||
# Clone the repo
|
||||
shell.run_command("git clone https://github.com/adafruit/Raspberry-Pi-Installer-Scripts.git")
|
||||
|
||||
# Build and install the module
|
||||
shell.chdir("Raspberry-Pi-Installer-Scripts/i2s_mic_module")
|
||||
shell.run_command("make clean")
|
||||
shell.run_command("make")
|
||||
shell.run_command("make install")
|
||||
|
||||
# Setup auto load at boot if selected
|
||||
if auto_load:
|
||||
shell.write_text_file(
|
||||
"/etc/modules-load.d/snd-i2smic-rpi.conf",
|
||||
"snd-i2smic-rpi"
|
||||
)
|
||||
shell.write_text_file(
|
||||
"/etc/modprobe.d/snd-i2smic-rpi.conf",
|
||||
"options snd-i2smic-rpi rpi_platform_generation={}".format(pimodel_select)
|
||||
)
|
||||
|
||||
# Enable I2S overlay
|
||||
shell.run_command(f"sed -i -e 's/#dtparam=i2s/dtparam=i2s/g' {boot_config}")
|
||||
|
||||
# Done
|
||||
print("""DONE.
|
||||
|
||||
Settings take effect on next boot.
|
||||
""")
|
||||
if not shell.argument_exists('noreboot'):
|
||||
shell.prompt_reboot(force_arg="reboot")
|
||||
|
||||
# Main function
|
||||
if __name__ == "__main__":
|
||||
shell.require_root()
|
||||
# Probably not necessary for now because the Pi 5 doesn't work anyway
|
||||
if shell.is_raspberry_pi_os() and shell.is_kernel_userspace_mismatched() and shell.is_pi5_or_newer():
|
||||
shell.bail("Unable to proceed on Pi 5 or newer boards with a with a 32-bit OS. Please reinstall with a 64-bit OS.")
|
||||
shell.check_kernel_userspace_mismatch()
|
||||
main()
|
||||
114
install_wm8960.sh
Normal file
114
install_wm8960.sh
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -o xtrace
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo "This script must be run as root (use sudo)" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f /etc/rpi-issue ]; then
|
||||
echo "Sorry, this drivers only works on raspberry pi"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
#download the archive
|
||||
rm -rf WM8960-Audio-HAT
|
||||
git clone https://github.com/waveshare/WM8960-Audio-HAT
|
||||
cd WM8960-Audio-HAT
|
||||
|
||||
apt-get -y update
|
||||
apt-get -y install raspberrypi-kernel-headers --no-install-recommends --no-install-suggests
|
||||
apt-get -y install dkms git i2c-tools libasound2-plugins --no-install-recommends --no-install-suggests
|
||||
apt-get -y clean
|
||||
|
||||
# locate currently installed kernels (may be different to running kernel if
|
||||
# it's just been updated)
|
||||
kernels=$(ls /lib/modules)
|
||||
|
||||
function install_module {
|
||||
ver="1.0"
|
||||
# we create a dir with this version to ensure that 'dkms remove' won't delete
|
||||
# the sources during kernel updates
|
||||
marker="0.0.0"
|
||||
|
||||
src=$1
|
||||
mod=$2
|
||||
|
||||
if [[ -d /var/lib/dkms/$mod/$ver/$marker ]]; then
|
||||
rmdir /var/lib/dkms/$mod/$ver/$marker
|
||||
fi
|
||||
|
||||
if [[ -e /usr/src/$mod-$ver || -e /var/lib/dkms/$mod/$ver ]]; then
|
||||
dkms remove --force -m $mod -v $ver --all || true
|
||||
rm -rf /usr/src/$mod-$ver
|
||||
fi
|
||||
mkdir -p /usr/src/$mod-$ver
|
||||
cp -a $src/* /usr/src/$mod-$ver/
|
||||
dkms add -m $mod -v $ver
|
||||
for kernel in $kernels
|
||||
do
|
||||
# It works for kernels greater than or equal 6.5
|
||||
if [ $(echo "$kernel 6.5" | awk '{if ($1 >= $2) print 1; else print 0}') -eq 0 ]; then
|
||||
continue
|
||||
fi
|
||||
dkms build "$kernel" -k "$kernel" --kernelsourcedir "/lib/modules/$kernel/build" -m $mod -v $ver &&
|
||||
dkms install --force "$kernel" -k "$kernel" -m $mod -v $ver
|
||||
done
|
||||
|
||||
mkdir -p /var/lib/dkms/$mod/$ver/$marker
|
||||
}
|
||||
|
||||
install_module "./" "wm8960-soundcard"
|
||||
|
||||
# install dtbos
|
||||
cp wm8960-soundcard.dtbo /boot/overlays
|
||||
|
||||
|
||||
#set kernel modules
|
||||
grep -q "^i2c-dev$" /etc/modules || \
|
||||
echo "i2c-dev" >> /etc/modules
|
||||
grep -q "^snd-soc-wm8960$" /etc/modules || \
|
||||
echo "snd-soc-wm8960" >> /etc/modules
|
||||
grep -q "^snd-soc-wm8960-soundcard$" /etc/modules || \
|
||||
echo "snd-soc-wm8960-soundcard" >> /etc/modules
|
||||
|
||||
# set modprobe blacklist
|
||||
grep -q "^blacklist snd_bcm2835$" /etc/modprobe.d/raspi-blacklist.conf || \
|
||||
echo "blacklist snd_bcm2835" >> /etc/modprobe.d/raspi-blacklist.conf
|
||||
|
||||
#set dtoverlays
|
||||
sed -i -e 's:#dtparam=i2s=on:dtparam=i2s=on:g' /boot/firmware/config.txt || true
|
||||
sed -i -e 's:#dtparam=i2c_arm=on:dtparam=i2c_arm=on:g' /boot/firmware/config.txt || true
|
||||
grep -q "^dtoverlay=i2s-mmap$" /boot/firmware/config.txt || \
|
||||
echo "dtoverlay=i2s-mmap" >> /boot/firmware/config.txt
|
||||
|
||||
grep -q "^dtparam=i2s=on$" /boot/firmware/config.txt || \
|
||||
echo "dtparam=i2s=on" >> /boot/firmware/config.txt
|
||||
|
||||
grep -q "^dtoverlay=wm8960-soundcard$" /boot/firmware/config.txt || \
|
||||
echo "dtoverlay=wm8960-soundcard" >> /boot/firmware/config.txt
|
||||
|
||||
#install config files
|
||||
mkdir -p /etc/wm8960-soundcard
|
||||
cp *.conf /etc/wm8960-soundcard
|
||||
cp *.state /etc/wm8960-soundcard
|
||||
|
||||
#set service
|
||||
cp wm8960-soundcard /usr/bin/
|
||||
chmod -x wm8960-soundcard.service
|
||||
cp wm8960-soundcard.service /lib/systemd/system/
|
||||
systemctl enable wm8960-soundcard.service
|
||||
|
||||
#cleanup
|
||||
cd ..
|
||||
rm -rf WM8960-Audio-HAT
|
||||
|
||||
echo "------------------------------------------------------"
|
||||
echo "Please reboot your raspberry pi to apply all settings"
|
||||
echo "Enjoy!"
|
||||
echo "------------------------------------------------------"
|
||||
121
joy-bonnet.py
Executable file
121
joy-bonnet.py
Executable file
|
|
@ -0,0 +1,121 @@
|
|||
"""
|
||||
Adafruit Raspberry Pi Joy Bonnet Setup Script
|
||||
(C) Adafruit Industries, Creative Commons 3.0 - Attribution Share Alike
|
||||
|
||||
Converted to Python by Melissa LeBlanc-Williams for Adafruit Industries
|
||||
"""
|
||||
|
||||
try:
|
||||
from adafruit_shell import Shell
|
||||
except ImportError:
|
||||
raise RuntimeError("The library 'adafruit_shell' was not found. To install, try typing: sudo pip3 install adafruit-python-shell")
|
||||
|
||||
shell = Shell()
|
||||
shell.group = "JOY"
|
||||
|
||||
def main():
|
||||
shell.clear()
|
||||
print("""This script installs software for the Adafruit
|
||||
Joy Bonnet for Raspberry Pi. Steps include:
|
||||
- Update package index files (apt-get update).
|
||||
- Install Python libraries: smbus, evdev.
|
||||
- Install joyBonnet.py in /boot and
|
||||
configure /etc/rc.local to auto-start script.
|
||||
- Enable I2C bus.
|
||||
- OPTIONAL: disable overscan.
|
||||
Run time ~10 minutes. Reboot required.
|
||||
EXISTING INSTALLATION, IF ANY, WILL BE OVERWRITTEN.
|
||||
""")
|
||||
if not shell.prompt("CONTINUE?", default='n'):
|
||||
print("Canceled.")
|
||||
shell.exit()
|
||||
print("Continuing...")
|
||||
disable_overscan = shell.prompt("Disable overscan?", default='n')
|
||||
install_halt = shell.prompt("Install GPIO-halt utility?", default='n')
|
||||
if install_halt:
|
||||
#halt_pin = shell.prompt("Install GPIO-halt utility?"
|
||||
halt_pin = input("GPIO pin for halt: ").strip()
|
||||
print("\n")
|
||||
if disable_overscan:
|
||||
print("Overscan: disable.")
|
||||
else:
|
||||
print("Overscan: keep current setting.")
|
||||
|
||||
if install_halt:
|
||||
print("Install GPIO-halt: YES (GPIO{})".format(halt_pin))
|
||||
else:
|
||||
print("Install GPIO-halt: NO")
|
||||
|
||||
if not shell.prompt("CONTINUE?", default='n'):
|
||||
print("Canceled.")
|
||||
shell.exit()
|
||||
|
||||
# START INSTALL ------------------------------------------------------------
|
||||
# All selections are validated at this point...
|
||||
|
||||
print("""
|
||||
Starting installation...
|
||||
Updating package index files...""")
|
||||
shell.run_command('sudo apt-get update', suppress_message=True)
|
||||
|
||||
print("Installing Python libraries...")
|
||||
shell.run_command('sudo apt-get install -y python3-pip python3-dev python3-smbus')
|
||||
shell.run_command('pip3 install evdev --upgrade')
|
||||
|
||||
print("Installing Adafruit code in /boot...")
|
||||
shell.chdir("/tmp")
|
||||
shell.run_command("curl -LO https://raw.githubusercontent.com/adafruit/Adafruit-Retrogame/master/joyBonnet.py")
|
||||
# Moving between filesystems requires copy-and-delete:
|
||||
shell.copy("joyBonnet.py", "/boot")
|
||||
shell.remove("joyBonnet.py")
|
||||
if install_halt:
|
||||
print("Installing gpio-halt in /usr/local/bin...")
|
||||
shell.run_command("curl -LO https://github.com/adafruit/Adafruit-GPIO-Halt/archive/master.zip")
|
||||
shell.run_command("unzip -u master.zip")
|
||||
shell.chdir("Adafruit-GPIO-Halt-master")
|
||||
shell.run_command("make")
|
||||
shell.move("gpio-halt", "/usr/local/bin")
|
||||
shell.chdir("..")
|
||||
shell.remove("Adafruit-GPIO-Halt-master")
|
||||
|
||||
# CONFIG -------------------------------------------------------------------
|
||||
|
||||
print("Configuring system...")
|
||||
|
||||
# Enable I2C using raspi-config
|
||||
shell.run_command("sudo raspi-config nonint do_i2c 0")
|
||||
|
||||
# Disable overscan compensation (use full screen):
|
||||
if disable_overscan:
|
||||
shell.run_command("sudo raspi-config nonint do_overscan 1")
|
||||
|
||||
if install_halt:
|
||||
if shell.pattern_search("/etc/rc.local", "gpio-halt"):
|
||||
# gpio-halt already in rc.local, but make sure correct:
|
||||
shell.pattern_replace("/etc/rc.local", "^.*gpio-halt.*$", "/usr/local/bin/gpio-halt {} &".format(halt_pin))
|
||||
else:
|
||||
# Insert gpio-halt into rc.local before final 'exit 0'
|
||||
shell.pattern_replace("/etc/rc.local", "^exit 0", "/usr/local/bin/gpio-halt {} &\\nexit 0".format(halt_pin))
|
||||
|
||||
# Auto-start joyBonnet.py on boot
|
||||
if shell.pattern_search("/etc/rc.local", "joyBonnet.py"):
|
||||
# joyBonnet.py already in rc.local, but make sure correct:
|
||||
shell.pattern_replace("/etc/rc.local", "^.*joyBonnet.py.*$", "cd /boot;python3 joyBonnet.py &")
|
||||
else:
|
||||
# Insert joyBonnet.py into rc.local before final 'exit 0'
|
||||
shell.pattern_replace("/etc/rc.local", "^exit 0", "cd /boot;python3 joyBonnet.py &\\nexit 0")
|
||||
|
||||
# Add udev rule (will overwrite if present)
|
||||
shell.write_text_file("/etc/udev/rules.d/10-retrogame.rules", "SUBSYSTEM==\"input\", ATTRS{name}==\"retrogame\", ENV{ID_INPUT_KEYBOARD}=\"1\"", append=False)
|
||||
|
||||
# PROMPT FOR REBOOT --------------------------------------------------------
|
||||
print("""DONE.
|
||||
|
||||
Settings take effect on next boot.
|
||||
""")
|
||||
shell.prompt_reboot()
|
||||
|
||||
# Main function
|
||||
if __name__ == "__main__":
|
||||
shell.require_root()
|
||||
main()
|
||||
60
libgpiod.py
Executable file
60
libgpiod.py
Executable file
|
|
@ -0,0 +1,60 @@
|
|||
# Instructions!
|
||||
# cd ~
|
||||
# sudo apt-get install python3-pip
|
||||
# sudo pip3 install --upgrade adafruit-python-shell click
|
||||
# wget https://raw.githubusercontent.com/adafruit/Raspberry-Pi-Installer-Scripts/master/libgpiod.py
|
||||
# sudo python3 libgpiod.py
|
||||
|
||||
import sys
|
||||
try:
|
||||
import click
|
||||
except ImportError:
|
||||
raise RuntimeError("The library 'Click' was not found. To install, try typing: sudo pip3 install --upgrade click")
|
||||
try:
|
||||
from adafruit_shell import Shell
|
||||
except ImportError:
|
||||
raise RuntimeError("The library 'adafruit_shell' was not found. To install, try typing: sudo pip3 install adafruit-python-shell")
|
||||
|
||||
shell = Shell()
|
||||
shell.group = 'LIBGPIOD'
|
||||
|
||||
@click.command()
|
||||
@click.option('-l', '--legacy', is_flag=True, help="Install a legacy version of libgpiod for systems with older libraries")
|
||||
def main(legacy):
|
||||
print("Installing build requirements - this may take a few minutes!\n")
|
||||
|
||||
# install generic linux packages required
|
||||
shell.run_command("sudo apt-get update")
|
||||
shell.run_command("sudo apt-get install -y autoconf autoconf-archive automake build-essential git libtool pkg-config python3-dev python3-setuptools swig4.0 wget")
|
||||
|
||||
# for raspberry pi we need...
|
||||
shell.run_command("sudo apt-get install -y raspberrypi-kernel-headers")
|
||||
|
||||
build_dir = shell.run_command("mktemp -d /tmp/libgpiod.XXXX", return_output=True).strip()
|
||||
print(f"Cloning libgpiod repository to {build_dir}\n")
|
||||
|
||||
shell.chdir(build_dir)
|
||||
shell.run_command("git clone git://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git .")
|
||||
|
||||
if legacy:
|
||||
shell.run_command("git checkout v1.4.2 -b v1.4.2")
|
||||
|
||||
print("Building libgpiod\n")
|
||||
|
||||
include_path = shell.run_command("python3 -c \"from sysconfig import get_paths; print(get_paths()['include'])\"", return_output=True)
|
||||
|
||||
shell.run_command("export PYTHON_VERSION=3")
|
||||
shell.run_command("./autogen.sh --enable-tools=yes --prefix=/usr/local/ --enable-bindings-python CFLAGS=\"-I/{}\" && make && sudo make install && sudo ldconfig".format(include_path))
|
||||
|
||||
if shell.exists("bindings/python/.libs"):
|
||||
version = sys.version_info
|
||||
python_folder = f"python{version.major}.{version.minor}"
|
||||
shell.run_command(f"sudo cp bindings/python/.libs/gpiod.so /usr/local/lib/{python_folder}/dist-packages/")
|
||||
shell.run_command(f"sudo cp bindings/python/.libs/gpiod.la /usr/local/lib/{python_folder}/dist-packages/")
|
||||
shell.run_command(f"sudo cp bindings/python/.libs/gpiod.a /usr/local/lib/{python_folder}/dist-packages/")
|
||||
shell.exit()
|
||||
|
||||
# Main function
|
||||
if __name__ == "__main__":
|
||||
shell.require_root()
|
||||
main()
|
||||
36
mipi/adafruit_hx8357_drm.txt
Normal file
36
mipi/adafruit_hx8357_drm.txt
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# Adafruit HX8257 PiTFT Plus TFT LCD Screen
|
||||
# width=480,height=320
|
||||
|
||||
command 0x01 # _SWRESET and Delay 100ms
|
||||
delay 100
|
||||
|
||||
command 0xB9 0xFF 0x83 0x57 # _SETC and delay 500ms
|
||||
delay 250
|
||||
delay 250
|
||||
|
||||
command 0xB3 0x80 0x00 0x06 0x06 # _SETRGB 0x80 enables SDO pin (0x00 disables)
|
||||
command 0xB6 0x25 # _SETCOM -1.52V
|
||||
command 0xB0 0x68 # _SETOSC Normal mode 70Hz, Idle mode 55 Hz
|
||||
command 0xCC 0x05 # _SETPANEL BGR, Gate direction swapped
|
||||
command 0xB1 0x00 0x15 0x1C 0x1C 0x83 0xAA # _SETPWR1 Not deep standby BT VSPR VSNR AP
|
||||
command 0xC0 0x50 0x50 0x01 0x3C 0x1E 0x08 # _SETSTBA OPON normal OPON idle STBA GEN
|
||||
command 0xB4 0x02 0x40 0x00 0x2A 0x2A 0x0D 0x78 # _SETCYC NW 0x02 RTN DIV DUM DUM GDON GDOFF
|
||||
|
||||
# _SETGAMMA
|
||||
command 0xE0 0x02 0x0A 0x11 0x1d 0x23 0x35 0x41 0x4b 0x4b 0x42 0x3A 0x27 0x1B 0x08 0x09 0x03 0x02 0x0A 0x11 0x1d 0x23 0x35 0x41 0x4b 0x4b 0x42 0x3A 0x27 0x1B 0x08 0x09 0x03 0x00 0x01
|
||||
command 0x3A 0x55 # _COLMOD 16 bit
|
||||
|
||||
# Command 36h sets the read order from frame memory to the display panel
|
||||
# Remember to swap width/height on 90/270 rotations
|
||||
command 0x36 0x00 # rotation 0
|
||||
#command 0x36 0xA0 # rotation 90
|
||||
#command 0x36 0xC0 # rotation 180
|
||||
#command 0x36 0x60 # rotation 270
|
||||
|
||||
command 0x35 0x00 # _TEON TW off
|
||||
command 0x44 0x00 0x02 # _TEARLINE
|
||||
command 0x11 # _SLPOUT
|
||||
delay 150
|
||||
|
||||
command 0x29 # _DISPON
|
||||
delay 50
|
||||
48
mipi/adafruit_ili9341_drm.txt
Normal file
48
mipi/adafruit_ili9341_drm.txt
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# Adafruit ILI9341 PiTFT TFT LCD Screen
|
||||
# width=320,height=240
|
||||
|
||||
command 0x01 # Software reset
|
||||
delay 128
|
||||
|
||||
command 0xEF 0x03 0x80 0x02
|
||||
command 0xCF 0x00 0xC1 0x30
|
||||
command 0xED 0x64 0x03 0x12 0x81
|
||||
command 0xE8 0x85 0x00 0x78
|
||||
command 0xCB 0x39 0x2C 0x00 0x34 0x02
|
||||
command 0xF7 0x20
|
||||
command 0xEA 0x00 0x00
|
||||
command 0xc0 0x23 # Power control VRH[5:0]
|
||||
command 0xc1 0x10 # Power control SAP[2:0];BT[3:0]
|
||||
command 0xc5 0x3e 0x28 # VCM control
|
||||
command 0xc7 0x86 # VCM control2
|
||||
|
||||
#define MADCTL_MY 0x80 ///< Bottom to top
|
||||
#define MADCTL_MX 0x40 ///< Right to left
|
||||
#define MADCTL_MV 0x20 ///< Reverse Mode
|
||||
#define MADCTL_ML 0x10 ///< LCD refresh Bottom to top
|
||||
#define MADCTL_RGB 0x00 ///< Red-Green-Blue pixel order
|
||||
#define MADCTL_BGR 0x08 ///< Blue-Green-Red pixel order
|
||||
#define MADCTL_MH 0x04 ///< LCD refresh right to left
|
||||
|
||||
# Command 36h sets the read order from frame memory to the display panel
|
||||
# Remember to swap width/height on 90/270 rotations
|
||||
command 0x36 0x88 # rotation 0
|
||||
#command 0x36 0xE8 # rotation 90
|
||||
#command 0x36 0x48 # rotation 180
|
||||
#command 0x36 0x28 # rotation 270
|
||||
|
||||
|
||||
command 0x37 0x00 # Vertical scroll zero
|
||||
command 0x3a 0x55 # COLMOD: Pixel Format Set
|
||||
command 0xb1 0x00 0x18 # Frame Rate Control (In Normal Mode/Full Colors)
|
||||
command 0xb6 0x08 0x82 0x27 # Display Function Control
|
||||
command 0xF2 0x00 # 3Gamma Function Disable
|
||||
command 0x26 0x01 # Gamma curve selected
|
||||
|
||||
# Set Gamma
|
||||
command 0xe0 0x0F 0x31 0x2B 0x0C 0x0E 0x08 0x4E 0xF1 0x37 0x07 0x10 0x03 0x0E 0x09 0x00
|
||||
command 0xe1 0x00 0x0E 0x14 0x03 0x11 0x07 0x31 0xC1 0x48 0x08 0x0F 0x0C 0x31 0x36 0x0F
|
||||
command 0x11 # Exit Sleep
|
||||
delay 120
|
||||
command 0x29 # Display on
|
||||
delay 120
|
||||
29
mipi/adafruit_st7789_drm.txt
Normal file
29
mipi/adafruit_st7789_drm.txt
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Adafruit ST7789 MiniPiTFT LCD and TFT Bonnet
|
||||
# width=240,height=240
|
||||
|
||||
command 0x01 # _SWRESET and Delay 150ms
|
||||
delay 150
|
||||
|
||||
command 0x11 # _SLPOUT and Delay 10ms
|
||||
delay 10
|
||||
|
||||
command 0x3A 0x55 # _COLMOD and Delay 10ms
|
||||
delay 10
|
||||
|
||||
command 0x36 0x08 # _MADCTL Botton->Top Refresh
|
||||
command 0x21 # _INVON Hack and Delay 10ms
|
||||
delay 10
|
||||
|
||||
command 0x13 # _NORON and Delay 10ms
|
||||
delay 10
|
||||
|
||||
# Command 36h sets the read order from frame memory to the display panel
|
||||
# Remember to swap width/height on 90/270 rotations if required
|
||||
command 0x36 0x00 # rotation 0
|
||||
#command 0x36 0xA0 # rotation 90
|
||||
#command 0x36 0xC0 # rotation 180
|
||||
#command 0x36 0x60 # rotation 270
|
||||
|
||||
command 0x29 # _DISPON and Delay 500ms
|
||||
delay 250
|
||||
delay 250
|
||||
559
old_scripts/adafruit-pitft-mipi.py
Executable file
559
old_scripts/adafruit-pitft-mipi.py
Executable file
|
|
@ -0,0 +1,559 @@
|
|||
"""
|
||||
Adafruit PiTFT MIPI Display Installer Script
|
||||
(C) Adafruit Industries, Creative Commons 3.0 - Attribution Share Alike
|
||||
|
||||
Written by Melissa LeBlanc-Williams for Adafruit Industries
|
||||
"""
|
||||
|
||||
import time
|
||||
import os
|
||||
try:
|
||||
import click
|
||||
except ImportError:
|
||||
raise RuntimeError("The library 'Click' was not found. To install, try typing: pip3 install Click")
|
||||
try:
|
||||
from adafruit_shell import Shell
|
||||
except ImportError:
|
||||
raise RuntimeError("The library 'adafruit_shell' was not found. To install, try typing: pip3 install adafruit-python-shell")
|
||||
|
||||
shell = Shell()
|
||||
shell.group = 'PITFT-MIPI'
|
||||
|
||||
__version__ = "1.0.1"
|
||||
|
||||
"""
|
||||
This is the main configuration. Displays should be placed in the order
|
||||
they are to appear in the menu.
|
||||
"""
|
||||
config = [
|
||||
{
|
||||
"type": "28r",
|
||||
"menulabel": "PiTFT 2.4\", 2.8\" or 3.2\" resistive (240x320)",
|
||||
"product": "2.8\" resistive, PID 1601",
|
||||
"touchscreen": {
|
||||
"identifier": "STMPE Touchscreen Calibration",
|
||||
"product": "stmpe",
|
||||
"transforms": {
|
||||
"0": "0.988809 -0.023645 0.060523 -0.028817 1.003935 0.034176 0 0 1",
|
||||
"90": "0.014773 -1.132874 1.033662 1.118701 0.009656 -0.065273 0 0 1",
|
||||
"180": "-1.115235 -0.010589 1.057967 -0.005964 -1.107968 1.025780 0 0 1",
|
||||
"270": "-0.033192 1.126869 -0.014114 -1.115846 0.006580 1.050030 0 0 1",
|
||||
},
|
||||
"calibrations": {
|
||||
"0": "4232 11 -879396 1 5786 -752768 65536",
|
||||
"90": "33 -5782 21364572 4221 35 -1006432 65536",
|
||||
"180": "-4273 61 16441290 4 -5772 21627524 65536",
|
||||
"270": "-9 5786 -784608 -4302 19 16620508 65536",
|
||||
},
|
||||
"overlay": "touch-stmpe",
|
||||
},
|
||||
"mipi_data": {
|
||||
"command_bin": "adafruit_ili9341_drm",
|
||||
"gpio": "dc-gpio=25",
|
||||
"viewport": {
|
||||
"90": "width=320,height=240",
|
||||
"180": "width=240,height=320",
|
||||
"270": "width=320,height=240",
|
||||
"0": "width=240,height=320",
|
||||
},
|
||||
},
|
||||
"width": 320,
|
||||
"height": 240,
|
||||
},
|
||||
{
|
||||
"type": "22",
|
||||
"menulabel": "PiTFT 2.2\" no touch",
|
||||
"product": "2.2\" no touch",
|
||||
"mipi_data": {
|
||||
"command_bin": "adafruit_ili9341_drm",
|
||||
"gpio": "dc-gpio=25",
|
||||
"viewport": {
|
||||
"90": "width=320,height=240",
|
||||
"180": "width=240,height=320",
|
||||
"270": "width=320,height=240",
|
||||
"0": "width=240,height=320",
|
||||
},
|
||||
},
|
||||
"width": 320,
|
||||
"height": 240,
|
||||
},
|
||||
{
|
||||
"type": "28c",
|
||||
"menulabel": "PiTFT 2.8\" capacitive touch",
|
||||
"product": "2.8\" capacitive, PID 1983",
|
||||
"touchscreen": {
|
||||
"identifier": "FocalTech Touchscreen Calibration",
|
||||
"product": "EP0110M09",
|
||||
"transforms": {
|
||||
"0": "-1 0 1 0 -1 1 0 0 1",
|
||||
"90": "0 1 0 -1 0 1 0 0 1",
|
||||
"180": "1 0 0 0 1 0 0 0 1",
|
||||
"270": "0 -1 1 1 0 0 0 0 1",
|
||||
},
|
||||
"calibrations": "320 65536 0 -65536 0 15728640 65536",
|
||||
"overlay": "touch-ft6236",
|
||||
},
|
||||
"mipi_data": {
|
||||
"command_bin": "adafruit_ili9341_drm",
|
||||
"gpio": "dc-gpio=25",
|
||||
"viewport": {
|
||||
"90": "width=320,height=240",
|
||||
"180": "width=240,height=320",
|
||||
"270": "width=320,height=240",
|
||||
"0": "width=240,height=320",
|
||||
},
|
||||
},
|
||||
"width": 320,
|
||||
"height": 240,
|
||||
},
|
||||
{
|
||||
"type": "35r",
|
||||
"menulabel": "PiTFT 3.5\" resistive touch",
|
||||
"product": "3.5\" Resistive",
|
||||
"touchscreen": {
|
||||
"identifier": "STMPE Touchscreen Calibration",
|
||||
"product": "stmpe",
|
||||
"transforms": {
|
||||
"0": "-1.098388 0.003455 1.052099 0.005512 -1.093095 1.026309 0 0 1",
|
||||
"90": "-0.000087 1.094214 -0.028826 -1.091711 -0.004364 1.057821 0 0 1",
|
||||
"180": "1.102807 0.000030 -0.066352 0.001374 1.085417 -0.027208 0 0 1",
|
||||
"270": "0.003893 -1.087542 1.025913 1.084281 0.008762 -0.060700 0 0 1",
|
||||
},
|
||||
"calibrations": {
|
||||
"0": "5724 -6 -1330074 26 8427 -1034528 65536",
|
||||
"90": "5 8425 -978304 -5747 61 22119468 65536",
|
||||
"180": "-5682 -1 22069150 13 -8452 32437698 65536",
|
||||
"270": "3 -8466 32440206 5703 -1 -1308696 65536",
|
||||
},
|
||||
"overlay": "touch-stmpe",
|
||||
},
|
||||
"mipi_data": {
|
||||
"command_bin": "adafruit_hx8357_drm",
|
||||
"gpio": "dc-gpio=25",
|
||||
"viewport": {
|
||||
"90": "width=480,height=320",
|
||||
"180": "width=320,height=480",
|
||||
"270": "width=480,height=320",
|
||||
"0": "width=320,height=480",
|
||||
},
|
||||
},
|
||||
"width": 480,
|
||||
"height": 320,
|
||||
"x11_scale": 1.5,
|
||||
},
|
||||
{
|
||||
"type": "st7789_240x240",
|
||||
"menulabel": "PiTFT Mini 1.3\" or 1.54\" display",
|
||||
"product": "1.54\" or 1.3\" no touch",
|
||||
"mipi_data": {
|
||||
"command_bin": "adafruit_st7789_drm",
|
||||
"gpio": "dc-gpio=25,backlight-gpio=22",
|
||||
"viewport": {
|
||||
"0": "width=240,height=240",
|
||||
"90": "width=240,height=240,x-offset=80",
|
||||
"180": "width=240,height=240,y-offset=80",
|
||||
"270": "width=240,height=240",
|
||||
},
|
||||
},
|
||||
"width": 240,
|
||||
"height": 240,
|
||||
},
|
||||
{
|
||||
"type": "st7789_240x320",
|
||||
"menulabel": "ST7789V 2.0\" no touch",
|
||||
"product": "2.0\" no touch",
|
||||
"mipi_data": {
|
||||
"command_bin": "adafruit_st7789_drm",
|
||||
"gpio": "dc-gpio=25,backlight-gpio=22",
|
||||
"viewport": {
|
||||
"0": "width=320,height=240",
|
||||
"90": "width=240,height=320",
|
||||
"180": "width=320,height=240",
|
||||
"270": "width=240,height=320",
|
||||
},
|
||||
},
|
||||
"width": 320,
|
||||
"height": 240,
|
||||
},
|
||||
{
|
||||
"type": "st7789_240x135",
|
||||
"menulabel": "MiniPiTFT 1.14\" display",
|
||||
"product": "1.14\" no touch",
|
||||
"mipi_data": {
|
||||
"command_bin": "adafruit_st7789_drm",
|
||||
"gpio": "dc-gpio=25,backlight-gpio=22",
|
||||
"viewport": {
|
||||
"0": "width=136,height=240,x-offset=52,y-offset=40",
|
||||
"90": "width=240,height=136,y-offset=52,x-offset=40",
|
||||
"180": "width=136,height=240,x-offset=52,y-offset=40",
|
||||
"270": "width=240,height=136,y-offset=52,x-offset=40",
|
||||
},
|
||||
},
|
||||
"width": 240,
|
||||
"height": 135,
|
||||
},
|
||||
{
|
||||
"type": "st7789v_bonnet_240x240",
|
||||
"menulabel": "BrainCraft HAT or TFT 1.3\" Bonnet + Joystick",
|
||||
"product": "1.3\" Joystick",
|
||||
"mipi_data": {
|
||||
"command_bin": "adafruit_st7789_drm",
|
||||
"gpio": "dc-gpio=25,backlight-gpio=26",
|
||||
"viewport": {
|
||||
"0": "width=240,height=240",
|
||||
"90": "width=240,height=240,x-offset=80",
|
||||
"180": "width=240,height=240,y-offset=80",
|
||||
"270": "width=240,height=240",
|
||||
},
|
||||
},
|
||||
"width": 240,
|
||||
"height": 240,
|
||||
},
|
||||
]
|
||||
|
||||
# default mipi data
|
||||
mipi_data = {
|
||||
"speed": 40000000,
|
||||
"spi": "spi0-0",
|
||||
}
|
||||
|
||||
PITFT_ROTATIONS = ("90", "180", "270", "0")
|
||||
UPDATE_DB = False
|
||||
SYSTEMD = None
|
||||
MIPI_MINIMUM_KERNEL = 5.15
|
||||
pitft_config = None
|
||||
pitftrot = None
|
||||
auto_reboot = None
|
||||
|
||||
def warn_exit(message):
|
||||
shell.warn(message)
|
||||
shell.exit(1)
|
||||
|
||||
def print_version(ctx, param, value):
|
||||
if not value or ctx.resilient_parsing:
|
||||
return
|
||||
print("Adafruit PiTFT Helper v{}".format(__version__))
|
||||
shell.exit(1)
|
||||
|
||||
def progress(ellipsis_count):
|
||||
for i in range(ellipsis_count):
|
||||
print("...", end='')
|
||||
time.sleep(1)
|
||||
print("")
|
||||
|
||||
def sysupdate():
|
||||
global UPDATE_DB
|
||||
if not UPDATE_DB:
|
||||
print("Updating apt indexes...", end='')
|
||||
progress(3)
|
||||
if not shell.run_command('sudo apt update', suppress_message=True):
|
||||
warn_exit("Apt failed to update indexes!")
|
||||
if not shell.run_command('sudo apt-get update', suppress_message=True):
|
||||
warn_exit("Apt failed to update indexes!")
|
||||
print("Reading package lists...")
|
||||
progress(3)
|
||||
UPDATE_DB = True
|
||||
return True
|
||||
|
||||
############################ Sub-Scripts ############################
|
||||
|
||||
def softwareinstall():
|
||||
print("Installing Pre-requisite Software...This may take a few minutes!")
|
||||
if not shell.run_command("apt-get install -y libts0", suppress_message=True):
|
||||
if not shell.run_command("apt-get install -y tslib"):
|
||||
if not shell.run_command("apt-get install -y libts-dev"):
|
||||
warn_exit("Apt failed to install TSLIB!")
|
||||
if not shell.run_command("apt-get install -y bc fbi git python3-dev python3-pip python3-smbus python3-spidev evtest libts-bin device-tree-compiler libraspberrypi-dev build-essential python3-evdev"):
|
||||
warn_exit("Apt failed to install software!")
|
||||
return True
|
||||
|
||||
def uninstall_bootconfigtxt():
|
||||
"""Remove any old flexfb/fbtft stuff"""
|
||||
if shell.pattern_search(f"{boot_dir}/config.txt", "adafruit-pitft-helper"):
|
||||
print(f"Already have an adafruit-pitft-helper section in {boot_dir}/config.txt.")
|
||||
print("Removing old section...")
|
||||
shell.run_command(f"cp {boot_dir}/config.txt {boot_dir}/configtxt.bak")
|
||||
shell.pattern_replace(f"{boot_dir}/config.txt", '\n# --- added by adafruit-pitft-helper.*?\n# --- end adafruit-pitft-helper.*?\n', multi_line=True)
|
||||
return True
|
||||
def update_configtxt():
|
||||
f"""update {boot_dir}/config.txt with appropriate values"""
|
||||
uninstall_bootconfigtxt()
|
||||
# Driver does not work if hdmi_force_hotplug=1 is present
|
||||
shell.pattern_replace(f"{boot_dir}/config.txt", "hdmi_force_hotplug=1", "hdmi_force_hotplug=0")
|
||||
display_overlay = f"dtoverlay=mipi-dbi-spi,{mipi_data['spi']},speed=40000000"
|
||||
display_overlay += f"\ndtparam=compatible={mipi_data['command_bin']}\\0panel-mipi-dbi-spi"
|
||||
viewport = ""
|
||||
if mipi_data['viewport'][pitftrot] is not None:
|
||||
viewport = mipi_data['viewport'][pitftrot]
|
||||
display_overlay += f"\ndtparam={viewport}"
|
||||
if "gpio" in mipi_data:
|
||||
display_overlay += f"\ndtparam={mipi_data['gpio']}"
|
||||
|
||||
# Touch Overlay
|
||||
touch_overlay = ""
|
||||
if "touchscreen" in pitft_config and "overlay" in pitft_config["touchscreen"]:
|
||||
# use dtc to compile and copy overlay
|
||||
touch_overlay = pitft_config["touchscreen"]["overlay"]
|
||||
shell.run_command(f"dtc -I dts -O dtb -o {boot_dir}/overlays/{touch_overlay}.dtbo overlays/{touch_overlay}.dts")
|
||||
touch_overlay = f"\ndtoverlay={touch_overlay}"
|
||||
date = shell.date()
|
||||
shell.write_text_file(f"{boot_dir}/config.txt", f"""
|
||||
# --- added by adafruit-pitft-helper {date} ---
|
||||
[all]
|
||||
dtparam=spi=on
|
||||
dtparam=i2c1=on
|
||||
dtparam=i2c_arm=on
|
||||
|
||||
{display_overlay}
|
||||
{touch_overlay}
|
||||
# --- end adafruit-pitft-helper {date} ---
|
||||
""")
|
||||
return True
|
||||
|
||||
def update_udev():
|
||||
shell.write_text_file("/etc/udev/rules.d/95-touchmouse.rules", """
|
||||
SUBSYSTEM=="input", ATTRS{name}=="touchmouse", ENV{DEVNAME}=="*event*", SYMLINK+="input/touchscreen"
|
||||
""", append=False)
|
||||
shell.write_text_file("/etc/udev/rules.d/95-ftcaptouch.rules", """
|
||||
SUBSYSTEM=="input", ATTRS{name}=="EP0110M09", ENV{DEVNAME}=="*event*", SYMLINK+="input/touchscreen"
|
||||
SUBSYSTEM=="input", ATTRS{name}=="generic ft5x06*", ENV{DEVNAME}=="*event*", SYMLINK+="input/touchscreen"
|
||||
""", append=False)
|
||||
shell.write_text_file("/etc/udev/rules.d/95-stmpe.rules", """
|
||||
SUBSYSTEM=="input", ATTRS{name}=="*stmpe*", ENV{DEVNAME}=="*event*", SYMLINK+="input/touchscreen"
|
||||
""", append=False)
|
||||
return True
|
||||
|
||||
def compile_display_fw():
|
||||
command_src = "mipi/panel.txt"
|
||||
|
||||
# We could just copy the file to panel.txt, edit that, then remove it after
|
||||
shell.copy(f"mipi/{mipi_data['command_bin']}.txt", command_src)
|
||||
|
||||
# Make sure each of the lines with "# rotation" starts with exactly 1 # and no more
|
||||
shell.pattern_replace(command_src, "^#*(.*?# rotation.*?$)", "#\\1")
|
||||
# Uncomment the one for the rotation we are going for
|
||||
shell.pattern_replace(command_src, "^#(.*?# rotation " + pitftrot + ".*?$)", "\\1")
|
||||
# Download the mipi-dbi-cmd script if it doesn't exist
|
||||
if not shell.exists("mipi-dbi-cmd"):
|
||||
shell.run_command("wget https://raw.githubusercontent.com/notro/panel-mipi-dbi/main/mipi-dbi-cmd")
|
||||
shell.run_command("chmod +x mipi-dbi-cmd")
|
||||
# Run the mipi-dbi-script and output directly to the /lib/firmware folder
|
||||
shell.run_command(f"./mipi-dbi-cmd /lib/firmware/{mipi_data['command_bin']}.bin mipi/panel.txt")
|
||||
shell.remove(command_src)
|
||||
return True
|
||||
|
||||
def update_pointercal():
|
||||
if "calibrations" in pitft_config["touchscreen"]:
|
||||
if isinstance(pitft_config["touchscreen"]["calibrations"], dict):
|
||||
shell.write_text_file("/etc/pointercal", pitft_config["touchscreen"]["calibrations"][pitftrot])
|
||||
else:
|
||||
shell.write_text_file("/etc/pointercal", pitft_config["touchscreen"]["calibrations"])
|
||||
return True
|
||||
|
||||
def install_mipi():
|
||||
global mipi_data
|
||||
|
||||
if "mipi_data" in pitft_config:
|
||||
mipi_data.update(pitft_config['mipi_data'])
|
||||
if not compile_display_fw():
|
||||
shell.bail("Unable to compile MIPI firmware")
|
||||
# if there's X11 installed...
|
||||
if shell.exists("/etc/lightdm"):
|
||||
print("Setting raspi-config to boot to desktop w/o login...")
|
||||
shell.run_command("raspi-config nonint do_boot_behaviour B4")
|
||||
|
||||
# Disable overscan compensation (use full screen):
|
||||
shell.run_command("raspi-config nonint do_overscan 1")
|
||||
|
||||
if not update_configtxt():
|
||||
shell.bail(f"Unable to update {boot_dir}/config.txt")
|
||||
return True
|
||||
|
||||
def update_xorg():
|
||||
if "touchscreen" in pitft_config:
|
||||
transform = "Option \"TransformationMatrix\" \"{}\"".format(pitft_config["touchscreen"]["transforms"][pitftrot])
|
||||
shell.write_text_file("/usr/share/X11/xorg.conf.d/20-calibration.conf", f"""
|
||||
Section "InputClass"
|
||||
Identifier "{pitft_config["touchscreen"]["identifier"]}"
|
||||
MatchProduct "{pitft_config["touchscreen"]["product"]}"
|
||||
MatchDevicePath "/dev/input/event*"
|
||||
Driver "libinput"
|
||||
{transform}
|
||||
EndSection
|
||||
""",
|
||||
append=False,
|
||||
)
|
||||
return True
|
||||
|
||||
def get_config_types():
|
||||
types = []
|
||||
for item in config:
|
||||
types.append(item["type"])
|
||||
return types
|
||||
|
||||
def get_config(type):
|
||||
for item in config:
|
||||
if item["type"] == type:
|
||||
return item
|
||||
return None
|
||||
|
||||
def success():
|
||||
global auto_reboot
|
||||
shell.info("Success!")
|
||||
print("""
|
||||
Settings take effect on next boot.
|
||||
""")
|
||||
if auto_reboot is None:
|
||||
auto_reboot = shell.prompt("REBOOT NOW?", default="y")
|
||||
if not auto_reboot:
|
||||
print("Exiting without reboot.")
|
||||
shell.exit()
|
||||
print("Reboot started...")
|
||||
shell.reboot()
|
||||
shell.exit()
|
||||
|
||||
####################################################### MAIN
|
||||
target_homedir = "/home/pi"
|
||||
username = os.environ["SUDO_USER"]
|
||||
user_homedir = os.path.expanduser(f"~{username}")
|
||||
if shell.isdir(user_homedir):
|
||||
target_homedir = user_homedir
|
||||
|
||||
boot_dir = "/boot/firmware"
|
||||
if not shell.exists(boot_dir) or not shell.isdir(boot_dir):
|
||||
boot_dir = "/boot"
|
||||
|
||||
@click.command()
|
||||
@click.option('-v', '--version', is_flag=True, callback=print_version, expose_value=False, is_eager=True, help="Print version information")
|
||||
@click.option('-u', '--user', nargs=1, default=target_homedir, type=str, help="Specify path of primary user's home directory", show_default=True)
|
||||
@click.option('--display', nargs=1, default=None, help="Specify a display option (1-{}) or type {}".format(len(config), get_config_types()))
|
||||
@click.option('--rotation', nargs=1, default=None, type=int, help="Specify a rotation option (1-4) or degrees {}".format(tuple(sorted([int(x) for x in PITFT_ROTATIONS]))))
|
||||
@click.option('--reboot', nargs=1, default=None, type=click.Choice(['yes', 'no']), help="Specify whether to reboot after the script is finished")
|
||||
@click.option('--boot', nargs=1, default=boot_dir, type=str, help="Specify the boot directory", show_default=True)
|
||||
|
||||
def main(user, display, rotation, reboot, boot):
|
||||
global target_homedir, pitft_config, pitftrot, auto_reboot, boot_dir
|
||||
shell.clear()
|
||||
if user != target_homedir:
|
||||
target_homedir = user
|
||||
print(f"Homedir = {target_homedir}")
|
||||
if boot != boot_dir:
|
||||
if shell.isdir(boot):
|
||||
boot_dir = boot
|
||||
print(f"Boot dir = {boot_dir}")
|
||||
else:
|
||||
print(f"{boot} not found or not a directory. Using {boot_dir} instead.")
|
||||
|
||||
print("""This script downloads and installs
|
||||
PiTFT Support using userspace touch
|
||||
controls and a DTO for display drawing.
|
||||
one of several configuration files.
|
||||
Run time of up to 5 minutes. Reboot required!
|
||||
""")
|
||||
if reboot is not None:
|
||||
auto_reboot = reboot.lower() == 'yes'
|
||||
|
||||
# Check that the user is running the minimum kernel on this device
|
||||
if not shell.kernel_minimum(MIPI_MINIMUM_KERNEL):
|
||||
shell.warn(f"In order to continue, you will need to update your kernel to a minimum of {MIPI_MINIMUM_KERNEL}. ")
|
||||
if shell.get_os() == "Raspbian":
|
||||
shell.info("It looks like you are running this on a Raspberry Pi. You can update it to the latest version by running 'sudo rpi-update'.")
|
||||
shell.exit()
|
||||
|
||||
if display in [str(x) for x in range(1, len(config) + 1)]:
|
||||
pitft_config = config[int(display) - 1]
|
||||
print("Display Type: {}".format(pitft_config["menulabel"]))
|
||||
elif display in get_config_types():
|
||||
pitft_config = get_config(display)
|
||||
print("Display Type: {}".format(pitft_config["menulabel"]))
|
||||
else:
|
||||
# Build menu from config
|
||||
selections = []
|
||||
for item in config:
|
||||
option = "{} ({}x{})".format(item['menulabel'], item['width'], item['height'])
|
||||
selections.append(option)
|
||||
selections.append("Quit without installing")
|
||||
|
||||
PITFT_SELECT = shell.select_n("Select configuration:", selections)
|
||||
if PITFT_SELECT == len(config) + 1:
|
||||
shell.exit(1)
|
||||
pitft_config = config[PITFT_SELECT - 1]
|
||||
|
||||
if rotation is not None and 1 <= rotation <= 4:
|
||||
pitftrot = PITFT_ROTATIONS[rotation - 1]
|
||||
print("Rotation: {}".format(pitftrot))
|
||||
elif str(rotation) in PITFT_ROTATIONS:
|
||||
pitftrot = str(rotation)
|
||||
print("Rotation: {}".format(pitftrot))
|
||||
else:
|
||||
PITFT_ROTATE = shell.select_n(
|
||||
"Select rotation:", (
|
||||
"90 degrees (landscape)",
|
||||
"180 degrees (portrait)",
|
||||
"270 degrees (landscape)",
|
||||
"0 degrees (portrait)"
|
||||
))
|
||||
pitftrot = PITFT_ROTATIONS[PITFT_ROTATE - 1]
|
||||
|
||||
if 'rotations' in pitft_config and isinstance(pitft_config['rotations'], dict) and pitftrot in pitft_config['rotations'] and pitft_config['rotations'][pitftrot] is None:
|
||||
shell.bail("""Unfortunately {rotation} degrees for the {display} is not working at this time. Please
|
||||
restart the script and choose a different orientation.""".format(rotation=pitftrot, display=pitft_config["menulabel"]))
|
||||
|
||||
# check init system (technique borrowed from raspi-config):
|
||||
shell.info('Checking init system...')
|
||||
if shell.run_command("which systemctl", suppress_message=True) and shell.run_command("systemctl | grep '\-\.mount'", suppress_message=True):
|
||||
SYSTEMD = True
|
||||
print("Found systemd")
|
||||
elif os.path.isfile("/etc/init.d/cron") and not os.path.islink("/etc/init.d/cron"):
|
||||
SYSTEMD = False
|
||||
print("Found sysvinit")
|
||||
else:
|
||||
shell.bail("Unrecognised init system")
|
||||
|
||||
if shell.grep("boot", "/proc/mounts"):
|
||||
print("/boot is mounted")
|
||||
else:
|
||||
print("/boot must be mounted. if you think it's not, quit here and try: sudo mount /dev/mmcblk0p1 /boot")
|
||||
if shell.prompt("Continue?"):
|
||||
print("Proceeding.")
|
||||
else:
|
||||
shell.bail("Aborting.")
|
||||
|
||||
if not shell.isdir(target_homedir):
|
||||
shell.bail("{} must be an existing directory (use -u /home/foo to specify)".format(target_homedir))
|
||||
|
||||
shell.info("System update")
|
||||
if not sysupdate():
|
||||
shell.bail("Unable to apt-get update")
|
||||
|
||||
shell.info("Installing Python libraries & Software...")
|
||||
if not softwareinstall():
|
||||
shell.bail("Unable to install software")
|
||||
|
||||
shell.info("Adding MIPI support...")
|
||||
if not install_mipi():
|
||||
shell.bail("Unable to configure mipi")
|
||||
|
||||
shell.info(f"Updating {boot_dir}/config.txt...")
|
||||
if not update_configtxt():
|
||||
shell.bail(f"Unable to update {boot_dir}/config.txt")
|
||||
|
||||
if "touchscreen" in pitft_config:
|
||||
shell.info("Updating SysFS rules for Touchscreen...")
|
||||
if not update_udev():
|
||||
shell.bail("Unable to update /etc/udev/rules.d")
|
||||
|
||||
shell.info("Updating TSLib default calibration...")
|
||||
if not update_pointercal():
|
||||
shell.bail("Unable to update /etc/pointercal")
|
||||
|
||||
if shell.exists("/etc/lightdm"):
|
||||
shell.info("Updating X11 default calibration...")
|
||||
if not update_xorg():
|
||||
shell.bail("Unable to update calibration")
|
||||
success()
|
||||
|
||||
# Main function
|
||||
if __name__ == "__main__":
|
||||
shell.require_root()
|
||||
main()
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Device Tree overlay for Adafruit Mini PiTFT 1.14" Display
|
||||
* Device Tree overlay for Adafruit Mini PiTFT 1.14" 135x240 Display
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -7,72 +7,65 @@
|
|||
/plugin/;
|
||||
|
||||
/ {
|
||||
compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
|
||||
compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
|
||||
|
||||
fragment@0 {
|
||||
target = <&spi0>;
|
||||
__overlay__ {
|
||||
status = "okay";
|
||||
fragment@0 {
|
||||
target = <&spi0>;
|
||||
__overlay__ {
|
||||
status = "okay";
|
||||
|
||||
spidev@0{
|
||||
status = "disabled";
|
||||
};
|
||||
spidev@0{
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
spidev@1{
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@1 {
|
||||
target = <&gpio>;
|
||||
__overlay__ {
|
||||
pitft_pins: pitft_pins {
|
||||
brcm,pins = <25>; /* dc pin */
|
||||
brcm,function = <1>; /* out */
|
||||
brcm,pull = <0>; /* no pull */
|
||||
};
|
||||
};
|
||||
};
|
||||
fragment@1 {
|
||||
target = <&gpio>;
|
||||
__overlay__ {
|
||||
pitft_pins: pitft_pins {
|
||||
brcm,pins = <25>;
|
||||
brcm,function = <1>; /* out */
|
||||
brcm,pull = <0>; /* none */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@2 {
|
||||
target = <&spi0>;
|
||||
__overlay__ {
|
||||
/* needed to avoid dtc warning */
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
fragment@2 {
|
||||
target = <&spi0>;
|
||||
__overlay__ {
|
||||
/* needed to avoid dtc warning */
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pitft: pitft@0{
|
||||
compatible = "multi-inno,mi0283qt";
|
||||
reg = <0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pitft_pins>;
|
||||
pitft: pitft@0{
|
||||
compatible = "fbtft,minipitft13";
|
||||
reg = <0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pitft_pins>;
|
||||
spi-max-frequency = <32000000>;
|
||||
rotate = <270>;
|
||||
width = <135>;
|
||||
height = <240>;
|
||||
txbuflen = <32768>;
|
||||
buswidth = <8>;
|
||||
dc-gpios = <&gpio 25 0>;
|
||||
led-gpios = <&gpio 26 0>;
|
||||
debug = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
spi-max-frequency = <32000000>;
|
||||
rotation = <90>;
|
||||
width = <136>;
|
||||
height = <240>;
|
||||
col_offset = <53>;
|
||||
row_offset = <40>;
|
||||
dc-gpios = <&gpio 25 0>;
|
||||
backlight = <&backlight>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@3 {
|
||||
target-path = "/soc";
|
||||
__overlay__ {
|
||||
backlight: backlight {
|
||||
compatible = "gpio-backlight";
|
||||
gpios = <&gpio 22 0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
__overrides__ {
|
||||
speed = <&pitft>,"spi-max-frequency:0";
|
||||
rotation = <&pitft>,"rotation:0";
|
||||
width = <&pitft>,"width:0";
|
||||
height = <&pitft>,"height:0";
|
||||
col_offset = <&pitft>,"col_offset:0";
|
||||
row_offset = <&pitft>,"row_offset:0";
|
||||
};
|
||||
__overrides__ {
|
||||
speed = <&pitft>,"spi-max-frequency:0";
|
||||
rotate = <&pitft>,"rotate:0";
|
||||
width = <&pitft>,"width:0";
|
||||
height = <&pitft>,"height:0";
|
||||
fps = <&pitft>,"fps:0";
|
||||
debug = <&pitft>,"debug:0";
|
||||
};
|
||||
};
|
||||
|
|
|
|||
72
overlays/minipitft13-overlay.dts
Normal file
72
overlays/minipitft13-overlay.dts
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Device Tree overlay for Adafruit Mini PiTFT 1.3" and 1.5" 240x240 Display
|
||||
*
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
/ {
|
||||
compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
|
||||
|
||||
fragment@0 {
|
||||
target = <&spi0>;
|
||||
__overlay__ {
|
||||
status = "okay";
|
||||
|
||||
spidev@0{
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spidev@1{
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@1 {
|
||||
target = <&gpio>;
|
||||
__overlay__ {
|
||||
pitft_pins: pitft_pins {
|
||||
brcm,pins = <25>;
|
||||
brcm,function = <1>; /* out */
|
||||
brcm,pull = <0>; /* none */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@2 {
|
||||
target = <&spi0>;
|
||||
__overlay__ {
|
||||
/* needed to avoid dtc warning */
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pitft: pitft@0{
|
||||
compatible = "fbtft,minipitft13";
|
||||
reg = <0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pitft_pins>;
|
||||
spi-max-frequency = <32000000>;
|
||||
rotate = <0>;
|
||||
width = <240>;
|
||||
height = <240>;
|
||||
txbuflen = <32768>;
|
||||
buswidth = <8>;
|
||||
dc-gpios = <&gpio 25 0>;
|
||||
led-gpios = <&gpio 26 0>;
|
||||
debug = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
__overrides__ {
|
||||
speed = <&pitft>,"spi-max-frequency:0";
|
||||
rotate = <&pitft>,"rotate:0";
|
||||
width = <&pitft>,"width:0";
|
||||
height = <&pitft>,"height:0";
|
||||
fps = <&pitft>,"fps:0";
|
||||
debug = <&pitft>,"debug:0";
|
||||
};
|
||||
};
|
||||
71
overlays/pitft22-overlay.dts
Normal file
71
overlays/pitft22-overlay.dts
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Device Tree overlay for pitft by Adafruit
|
||||
*
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
/ {
|
||||
compatible = "brcm,bcm2835";
|
||||
|
||||
fragment@0 {
|
||||
target = <&spidev0>;
|
||||
__overlay__ {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
fragment@1 {
|
||||
target = <&spidev1>;
|
||||
__overlay__ {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
fragment@2 {
|
||||
target = <&gpio>;
|
||||
__overlay__ {
|
||||
pitft_pins: pitft_pins {
|
||||
brcm,pins = <25>;
|
||||
brcm,function = <1>; /* out */
|
||||
brcm,pull = <0>; /* none */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@3 {
|
||||
target = <&spi0>;
|
||||
__overlay__ {
|
||||
/* needed to avoid dtc warning */
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "okay";
|
||||
|
||||
pitft: pitft@0{
|
||||
compatible = "ilitek,ili9340";
|
||||
reg = <0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pitft_pins>;
|
||||
|
||||
spi-max-frequency = <32000000>;
|
||||
rotate = <90>;
|
||||
fps = <25>;
|
||||
bgr;
|
||||
buswidth = <8>;
|
||||
dc-gpios = <&gpio 25 0>;
|
||||
debug = <0>;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
__overrides__ {
|
||||
speed = <&pitft>,"spi-max-frequency:0";
|
||||
rotate = <&pitft>,"rotate:0", /* fbtft */
|
||||
<&pitft>,"rotation:0"; /* drm */
|
||||
fps = <&pitft>,"fps:0";
|
||||
debug = <&pitft>,"debug:0";
|
||||
drm = <&pitft>,"compatible=adafruit,yx240qv29";
|
||||
};
|
||||
};
|
||||
114
overlays/pitft24v2-tsc2007-overlay.dts
Normal file
114
overlays/pitft24v2-tsc2007-overlay.dts
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Device Tree overlay for Adafruit PiTFT 2.4" resistive touch screen with tsc2007
|
||||
*
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
/ {
|
||||
compatible = "brcm,bcm2835";
|
||||
|
||||
fragment@0 {
|
||||
target = <&spi0>;
|
||||
__overlay__ {
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
fragment@2 {
|
||||
target = <&spidev0>;
|
||||
__overlay__ {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
fragment@3 {
|
||||
target = <&spidev1>;
|
||||
__overlay__ {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
fragment@4 {
|
||||
target = <&gpio>;
|
||||
__overlay__ {
|
||||
adafruit_2_4_tft_pins: adafruit_2_4_tft_pins {
|
||||
brcm,pins = <25 24 18>;
|
||||
brcm,function = <1 0 1>; /* out in out*/
|
||||
brcm,pull = <0 2 2>; /* none up up */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@5 {
|
||||
target = <&spi0>;
|
||||
__overlay__ {
|
||||
/* needed to avoid dtc warning */
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cs-gpios = <&gpio 8 1>;
|
||||
|
||||
adafruit_2_4_tft: adafruit_2_4_tft@0{
|
||||
compatible = "adafruit,yx240qv29";
|
||||
reg = <0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&adafruit_2_4_tft_pins>;
|
||||
|
||||
spi-max-frequency = <32000000>;
|
||||
rotation = <90>;
|
||||
reset-gpios = <&gpio 23 0>;
|
||||
dc-gpios = <&gpio 25 0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@7 {
|
||||
target = <&i2c1>;
|
||||
__overlay__ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
status = "okay";
|
||||
|
||||
tsc2007: tsc2007@48 {
|
||||
compatible = "ti,tsc2007";
|
||||
reg = <0x48>;
|
||||
ti,fuzzx = <4>;
|
||||
ti,fuzzy = <4>;
|
||||
ti,max-rt = <3700>;
|
||||
ti,fuzzz = <4>;
|
||||
ti,x-plate-ohms = <180>;
|
||||
|
||||
panel = <&adafruit_2_4_tft>;
|
||||
pinctrl-0 = <&adafruit_2_4_tft_pins>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <24 2>;
|
||||
gpios = <&gpio 24 1>;
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@8 {
|
||||
target-path = "/soc";
|
||||
__overlay__ {
|
||||
backlight: backlight {
|
||||
compatible = "gpio-backlight";
|
||||
pinctrl-0 = <&adafruit_2_4_tft_pins>;
|
||||
gpios = <&gpio 18 2>;
|
||||
default-on;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
__overrides__ {
|
||||
speed = <&adafruit_2_4_tft>,"spi-max-frequency:0";
|
||||
rotate = <&adafruit_2_4_tft>,"rotation:0";
|
||||
fps = <&adafruit_2_4_tft>,"fps:0";
|
||||
debug = <&adafruit_2_4_tft>,"debug:0";
|
||||
// xohms = <&tsc2007>,"touchscreen-x-plate-ohms;0";
|
||||
// swapxy = <&tsc2007>,"touchscreen-swapped-x-y?";
|
||||
};
|
||||
|
||||
};
|
||||
93
overlays/pitft28-capacitive-overlay.dts
Normal file
93
overlays/pitft28-capacitive-overlay.dts
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Device Tree overlay for Adafruit PiTFT 2.8" capacitive touch screen
|
||||
*
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
/ {
|
||||
compatible = "brcm,bcm2835";
|
||||
|
||||
fragment@0 {
|
||||
target = <&spi0>;
|
||||
__overlay__ {
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
fragment@1 {
|
||||
target = <&spidev0>;
|
||||
__overlay__ {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
fragment@2 {
|
||||
target = <&gpio>;
|
||||
__overlay__ {
|
||||
pitft_pins: pitft_pins {
|
||||
brcm,pins = <24 25>;
|
||||
brcm,function = <0 1>; /* in out */
|
||||
brcm,pull = <2 0>; /* pullup none */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@3 {
|
||||
target = <&spi0>;
|
||||
__overlay__ {
|
||||
/* needed to avoid dtc warning */
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pitft: pitft@0{
|
||||
compatible = "ilitek,ili9340";
|
||||
reg = <0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pitft_pins>;
|
||||
|
||||
spi-max-frequency = <32000000>;
|
||||
rotate = <90>;
|
||||
fps = <25>;
|
||||
bgr;
|
||||
buswidth = <8>;
|
||||
dc-gpios = <&gpio 25 0>;
|
||||
debug = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@4 {
|
||||
target = <&i2c1>;
|
||||
__overlay__ {
|
||||
/* needed to avoid dtc warning */
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ft6236: ft6236@38 {
|
||||
compatible = "focaltech,ft6236";
|
||||
reg = <0x38>;
|
||||
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <24 2>;
|
||||
touchscreen-size-x = <240>;
|
||||
touchscreen-size-y = <320>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
__overrides__ {
|
||||
speed = <&pitft>,"spi-max-frequency:0";
|
||||
rotate = <&pitft>,"rotate:0", /* fbtft */
|
||||
<&pitft>,"rotation:0"; /* drm */
|
||||
fps = <&pitft>,"fps:0";
|
||||
debug = <&pitft>,"debug:0";
|
||||
drm = <&pitft>,"compatible=adafruit,yx240qv29";
|
||||
touch-sizex = <&ft6236>,"touchscreen-size-x:0";
|
||||
touch-sizey = <&ft6236>,"touchscreen-size-y:0";
|
||||
touch-invx = <&ft6236>,"touchscreen-inverted-x?";
|
||||
touch-invy = <&ft6236>,"touchscreen-inverted-y?";
|
||||
touch-swapxy = <&ft6236>,"touchscreen-swapped-x-y?";
|
||||
};
|
||||
};
|
||||
126
overlays/pitft28-resistive-overlay.dts
Normal file
126
overlays/pitft28-resistive-overlay.dts
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Device Tree overlay for Adafruit PiTFT 2.8" resistive touch screen
|
||||
*
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
/ {
|
||||
compatible = "brcm,bcm2835";
|
||||
|
||||
fragment@0 {
|
||||
target = <&spi0>;
|
||||
__overlay__ {
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
fragment@1 {
|
||||
target = <&spidev0>;
|
||||
__overlay__ {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
fragment@2 {
|
||||
target = <&spidev1>;
|
||||
__overlay__ {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
fragment@3 {
|
||||
target = <&gpio>;
|
||||
__overlay__ {
|
||||
pitft_pins: pitft_pins {
|
||||
brcm,pins = <24 25>;
|
||||
brcm,function = <0 1>; /* in out */
|
||||
brcm,pull = <2 0>; /* pullup none */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@4 {
|
||||
target = <&spi0>;
|
||||
__overlay__ {
|
||||
/* needed to avoid dtc warning */
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pitft: pitft@0{
|
||||
compatible = "ilitek,ili9340";
|
||||
reg = <0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pitft_pins>;
|
||||
|
||||
spi-max-frequency = <32000000>;
|
||||
rotate = <90>;
|
||||
fps = <25>;
|
||||
bgr;
|
||||
buswidth = <8>;
|
||||
dc-gpios = <&gpio 25 0>;
|
||||
debug = <0>;
|
||||
};
|
||||
|
||||
pitft_ts@1 {
|
||||
/* needed to avoid dtc warning */
|
||||
#address-cells = <1>;
|
||||
#interrupt-cells = <1>;
|
||||
compatible = "st,stmpe610";
|
||||
reg = <1>;
|
||||
|
||||
spi-max-frequency = <500000>;
|
||||
interrupts = <24 2>; /* high-to-low edge triggered */
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupt-controller;
|
||||
|
||||
stmpe_touchscreen: stmpe_touchscreen {
|
||||
compatible = "st,stmpe-ts";
|
||||
st,sample-time = <4>;
|
||||
st,mod-12b = <1>;
|
||||
st,ref-sel = <0>;
|
||||
st,adc-freq = <2>;
|
||||
st,ave-ctrl = <3>;
|
||||
st,touch-det-delay = <4>;
|
||||
st,settling = <2>;
|
||||
st,fraction-z = <7>;
|
||||
st,i-drive = <0>;
|
||||
};
|
||||
|
||||
stmpe_gpio: stmpe_gpio {
|
||||
#gpio-cells = <2>;
|
||||
compatible = "st,stmpe-gpio";
|
||||
/*
|
||||
* only GPIO2 is wired/available
|
||||
* and it is wired to the backlight
|
||||
*/
|
||||
st,norequest-mask = <0x7b>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@5 {
|
||||
target-path = "/soc";
|
||||
__overlay__ {
|
||||
backlight {
|
||||
compatible = "gpio-backlight";
|
||||
gpios = <&stmpe_gpio 2 0>;
|
||||
default-on;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
__overrides__ {
|
||||
speed = <&pitft>,"spi-max-frequency:0";
|
||||
rotate = <&pitft>,"rotate:0", /* fbtft */
|
||||
<&pitft>,"rotation:0"; /* drm */
|
||||
fps = <&pitft>,"fps:0";
|
||||
debug = <&pitft>,"debug:0";
|
||||
drm = <&pitft>,"compatible=adafruit,yx240qv29";
|
||||
touch-invx = <&stmpe_touchscreen>,"touchscreen-inverted-x?";
|
||||
touch-invy = <&stmpe_touchscreen>,"touchscreen-inverted-y?";
|
||||
touch-swapxy = <&stmpe_touchscreen>,"touchscreen-swapped-x-y?";
|
||||
};
|
||||
};
|
||||
127
overlays/pitft35-resistive-overlay.dts
Normal file
127
overlays/pitft35-resistive-overlay.dts
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* Device Tree overlay for Adafruit PiTFT 3.5" resistive touch screen
|
||||
*
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
/ {
|
||||
compatible = "brcm,bcm2835";
|
||||
|
||||
fragment@0 {
|
||||
target = <&spi0>;
|
||||
__overlay__ {
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
fragment@1 {
|
||||
target = <&spidev0>;
|
||||
__overlay__ {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
fragment@2 {
|
||||
target = <&spidev1>;
|
||||
__overlay__ {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
fragment@3 {
|
||||
target = <&gpio>;
|
||||
__overlay__ {
|
||||
pitft_pins: pitft_pins {
|
||||
brcm,pins = <24 25>;
|
||||
brcm,function = <0 1>; /* in out */
|
||||
brcm,pull = <2 0>; /* pullup none */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@4 {
|
||||
target = <&spi0>;
|
||||
__overlay__ {
|
||||
/* needed to avoid dtc warning */
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pitft: pitft@0{
|
||||
compatible = "himax,hx8357d";
|
||||
reg = <0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pitft_pins>;
|
||||
|
||||
spi-max-frequency = <32000000>;
|
||||
rotate = <90>;
|
||||
fps = <25>;
|
||||
bgr;
|
||||
buswidth = <8>;
|
||||
dc-gpios = <&gpio 25 0>;
|
||||
debug = <0>;
|
||||
};
|
||||
|
||||
pitft_ts@1 {
|
||||
/* needed to avoid dtc warning */
|
||||
#address-cells = <1>;
|
||||
#interrupt-cells = <1>;
|
||||
compatible = "st,stmpe610";
|
||||
reg = <1>;
|
||||
|
||||
spi-max-frequency = <500000>;
|
||||
interrupts = <24 2>; /* high-to-low edge triggered */
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupt-controller;
|
||||
|
||||
stmpe_touchscreen: stmpe_touchscreen {
|
||||
compatible = "st,stmpe-ts";
|
||||
st,sample-time = <4>;
|
||||
st,mod-12b = <1>;
|
||||
st,ref-sel = <0>;
|
||||
st,adc-freq = <2>;
|
||||
st,ave-ctrl = <3>;
|
||||
st,touch-det-delay = <4>;
|
||||
st,settling = <2>;
|
||||
st,fraction-z = <7>;
|
||||
st,i-drive = <0>;
|
||||
};
|
||||
|
||||
stmpe_gpio: stmpe_gpio {
|
||||
#gpio-cells = <2>;
|
||||
compatible = "st,stmpe-gpio";
|
||||
/*
|
||||
* only GPIO2 is wired/available
|
||||
* and it is wired to the backlight
|
||||
*/
|
||||
st,norequest-mask = <0x7b>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@5 {
|
||||
target-path = "/soc";
|
||||
__overlay__ {
|
||||
backlight: backlight {
|
||||
compatible = "gpio-backlight";
|
||||
gpios = <&stmpe_gpio 2 0>;
|
||||
default-on;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
__overrides__ {
|
||||
speed = <&pitft>,"spi-max-frequency:0";
|
||||
rotate = <&pitft>,"rotate:0", /* fbtft */
|
||||
<&pitft>,"rotation:0"; /* drm */
|
||||
fps = <&pitft>,"fps:0";
|
||||
debug = <&pitft>,"debug:0";
|
||||
drm = <&pitft>,"compatible=adafruit,yx350hv15",
|
||||
<&pitft>,"backlight:0=",<&backlight>;
|
||||
touch-invx = <&stmpe_touchscreen>,"touchscreen-inverted-x?";
|
||||
touch-invy = <&stmpe_touchscreen>,"touchscreen-inverted-y?";
|
||||
touch-swapxy = <&stmpe_touchscreen>,"touchscreen-swapped-x-y?";
|
||||
};
|
||||
};
|
||||
71
overlays/st7789v_240x320-overlay.dts
Normal file
71
overlays/st7789v_240x320-overlay.dts
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Device Tree overlay for Adafruit Mini PiTFT 2.0" 240x320 Display
|
||||
*
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
/ {
|
||||
compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
|
||||
|
||||
fragment@0 {
|
||||
target = <&spi0>;
|
||||
__overlay__ {
|
||||
status = "okay";
|
||||
|
||||
spidev@0{
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spidev@1{
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@1 {
|
||||
target = <&gpio>;
|
||||
__overlay__ {
|
||||
pitft_pins: pitft_pins {
|
||||
brcm,pins = <25>;
|
||||
brcm,function = <1>; /* out */
|
||||
brcm,pull = <0>; /* none */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@2 {
|
||||
target = <&spi0>;
|
||||
__overlay__ {
|
||||
/* needed to avoid dtc warning */
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pitft: pitft@0{
|
||||
compatible = "sitronix,st7789v";
|
||||
reg = <0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pitft_pins>;
|
||||
spi-max-frequency = <32000000>;
|
||||
rotate = <0>;
|
||||
width = <240>;
|
||||
height = <320>;
|
||||
txbuflen = <32768>;
|
||||
buswidth = <8>;
|
||||
dc-gpios = <&gpio 25 0>;
|
||||
led-gpios = <&gpio 12 0>;
|
||||
debug = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
__overrides__ {
|
||||
speed = <&pitft>,"spi-max-frequency:0";
|
||||
rotate = <&pitft>,"rotate:0";
|
||||
width = <&pitft>,"width:0";
|
||||
height = <&pitft>,"height:0";
|
||||
fps = <&pitft>,"fps:0";
|
||||
debug = <&pitft>,"debug:0";
|
||||
};
|
||||
};
|
||||
115
overlays/tftbonnet13-overlay.dts
Normal file
115
overlays/tftbonnet13-overlay.dts
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Device Tree overlay for Adafruit TFT Bonnet 1.3" 240x240 Display + Joystick
|
||||
*
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
/ {
|
||||
compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
|
||||
|
||||
fragment@0 {
|
||||
target = <&spi0>;
|
||||
__overlay__ {
|
||||
status = "okay";
|
||||
|
||||
spidev@0{
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spidev@1{
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@1 {
|
||||
target = <&gpio>;
|
||||
__overlay__ {
|
||||
pitft_pins: pitft_pins {
|
||||
brcm,pins = <25>;
|
||||
brcm,function = <1>; /* out */
|
||||
brcm,pull = <0>; /* none */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@2 {
|
||||
target = <&spi0>;
|
||||
__overlay__ {
|
||||
/* needed to avoid dtc warning */
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pitft: pitft@0{
|
||||
compatible = "fbtft,minipitft13";
|
||||
reg = <0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pitft_pins>;
|
||||
spi-max-frequency = <32000000>;
|
||||
rotate = <0>;
|
||||
width = <240>;
|
||||
height = <240>;
|
||||
buswidth = <8>;
|
||||
dc-gpios = <&gpio 25 0>;
|
||||
led-gpios = <&gpio 26 0>;
|
||||
debug = <0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@3 {
|
||||
target-path = "/";
|
||||
__overlay__ {
|
||||
keypad: tft_bonnet_keys {
|
||||
compatible = "gpio-keys";
|
||||
|
||||
button@17 {
|
||||
label = "Controller Up";
|
||||
linux,code = <103>;
|
||||
gpios = <&gpio 17 1>;
|
||||
};
|
||||
button@22 {
|
||||
label = "Controller Down";
|
||||
linux,code = <108>;
|
||||
gpios = <&gpio 22 1>;
|
||||
};
|
||||
button@27 {
|
||||
label = "Controller Left";
|
||||
linux,code = <105>;
|
||||
gpios = <&gpio 27 1>;
|
||||
};
|
||||
button@23 {
|
||||
label = "Controller Right";
|
||||
linux,code = <106>;
|
||||
gpios = <&gpio 23 1>;
|
||||
};
|
||||
button@4 {
|
||||
label = "Controller Center";
|
||||
linux,code = <28>;
|
||||
gpios = <&gpio 4 1>;
|
||||
};
|
||||
button@5 {
|
||||
label = "Controller B";
|
||||
linux,code = <48>;
|
||||
gpios = <&gpio 5 1>;
|
||||
};
|
||||
button@6 {
|
||||
label = "Controller A";
|
||||
linux,code = <30>;
|
||||
gpios = <&gpio 6 1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
__overrides__ {
|
||||
speed = <&pitft>,"spi-max-frequency:0";
|
||||
rotate = <&pitft>,"rotate:0";
|
||||
width = <&pitft>,"width:0";
|
||||
height = <&pitft>,"height:0";
|
||||
fps = <&pitft>,"fps:0";
|
||||
debug = <&pitft>,"debug:0";
|
||||
};
|
||||
};
|
||||
53
overlays/touch-ft6236.dts
Normal file
53
overlays/touch-ft6236.dts
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Device Tree overlay for the Focaltech FT6236 capacitive
|
||||
* touch screen controller on the Adafruit PiTFT
|
||||
*
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
/ {
|
||||
compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
|
||||
|
||||
fragment@0 {
|
||||
target = <&gpio>;
|
||||
__overlay__ {
|
||||
pitft_pins: pitft_pins {
|
||||
brcm,pins = <24>;
|
||||
brcm,function = <0>; /* in out */
|
||||
brcm,pull = <2>; /* pullup none */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@1 {
|
||||
target = <&i2c1>;
|
||||
__overlay__ {
|
||||
/* needed to avoid dtc warning */
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ft6236: ft6236@38 {
|
||||
compatible = "focaltech,ft6236";
|
||||
reg = <0x38>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pitft_pins>;
|
||||
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <24 2>;
|
||||
touchscreen-size-x = <240>;
|
||||
touchscreen-size-y = <320>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
__overrides__ {
|
||||
touch-sizex = <&ft6236>,"touchscreen-size-x?";
|
||||
touch-sizey = <&ft6236>,"touchscreen-size-y?";
|
||||
touch-invx = <&ft6236>,"touchscreen-inverted-x?";
|
||||
touch-invy = <&ft6236>,"touchscreen-inverted-y?";
|
||||
touch-swapxy = <&ft6236>,"touchscreen-swapped-x-y?";
|
||||
};
|
||||
};
|
||||
81
overlays/touch-stmpe.dts
Normal file
81
overlays/touch-stmpe.dts
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Device Tree overlay for the STMPE resistive
|
||||
* touch screen controller on the Adafruit PiTFT
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
/ {
|
||||
compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
|
||||
|
||||
fragment@0 {
|
||||
target = <&spi0>;
|
||||
__overlay__ {
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
fragment@1 {
|
||||
target = <&spidev1>;
|
||||
__overlay__ {
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
fragment@2 {
|
||||
target = <&gpio>;
|
||||
__overlay__ {
|
||||
pitft_pins: pitft_pins {
|
||||
brcm,pins = <24>;
|
||||
brcm,function = <0>; /* in out */
|
||||
brcm,pull = <2>; /* pullup none */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fragment@3 {
|
||||
target = <&spi0>;
|
||||
__overlay__ {
|
||||
/* needed to avoid dtc warning */
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pitft: pitft_ts@1 {
|
||||
compatible = "st,stmpe610";
|
||||
reg = <1>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pitft_pins>;
|
||||
|
||||
spi-max-frequency = <500000>;
|
||||
irq-gpio = <&gpio 24 0x2>; /* IRQF_TRIGGER_FALLING */
|
||||
interrupts = <24 2>; /* high-to-low edge triggered */
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupt-controller;
|
||||
|
||||
stmpe_touchscreen {
|
||||
compatible = "st,stmpe-ts";
|
||||
st,sample-time = <4>;
|
||||
st,mod-12b = <1>;
|
||||
st,ref-sel = <0>;
|
||||
st,adc-freq = <2>;
|
||||
st,ave-ctrl = <3>;
|
||||
st,touch-det-delay = <4>;
|
||||
st,settling = <2>;
|
||||
st,fraction-z = <7>;
|
||||
st,i-drive = <0>;
|
||||
};
|
||||
|
||||
stmpe_gpio: stmpe_gpio {
|
||||
#gpio-cells = <2>;
|
||||
compatible = "st,stmpe-gpio";
|
||||
/*
|
||||
* only GPIO2 is wired/available
|
||||
* and it is wired to the backlight
|
||||
*/
|
||||
st,norequest-mask = <0x7b>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
BIN
packages/lgpio.zip
Normal file
BIN
packages/lgpio.zip
Normal file
Binary file not shown.
362
pi-eyes.sh
362
pi-eyes.sh
|
|
@ -1,29 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [ $(id -u) -ne 0 ]; then
|
||||
echo "Installer must be run as root."
|
||||
echo "Try 'sudo bash $0'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
clear
|
||||
|
||||
echo "This script installs software for the Adafruit"
|
||||
echo "Snake Eyes Bonnet for Raspberry Pi. Steps include:"
|
||||
echo "- Update package index files (apt-get update)"
|
||||
echo "- Install Python libraries: numpy, pi3d, svg.path,"
|
||||
echo " python-dev, python-pil"
|
||||
echo "- Install Adafruit eye code and data in /boot"
|
||||
echo "- Enable SPI0 and SPI1 peripherals if needed"
|
||||
echo "- Set HDMI resolution, disable overscan"
|
||||
echo "Run time ~25 minutes. Reboot required."
|
||||
echo "EXISTING INSTALLATION, IF ANY, WILL BE OVERWRITTEN."
|
||||
echo
|
||||
echo -n "CONTINUE? [y/N] "
|
||||
read
|
||||
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
|
||||
echo "Canceled."
|
||||
exit 0
|
||||
echo "Installer must be run as root."
|
||||
echo "Try 'sudo bash $0'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# FEATURE PROMPTS ----------------------------------------------------------
|
||||
|
|
@ -37,21 +17,60 @@ INSTALL_GADGET=0
|
|||
# preceded by a number (1 to N), display a prompt, check input until
|
||||
# a valid number within the selection range is entered.
|
||||
selectN() {
|
||||
for ((i=1; i<=$#; i++)); do
|
||||
echo $i. ${!i}
|
||||
done
|
||||
echo
|
||||
REPLY=""
|
||||
while :
|
||||
do
|
||||
echo -n "SELECT 1-$#: "
|
||||
read
|
||||
if [[ $REPLY -ge 1 ]] && [[ $REPLY -le $# ]]; then
|
||||
return $REPLY
|
||||
fi
|
||||
done
|
||||
for ((i=1; i<=$#; i++)); do
|
||||
echo $i. ${!i}
|
||||
done
|
||||
echo
|
||||
REPLY=""
|
||||
while :
|
||||
do
|
||||
echo -n "SELECT 1-$#: "
|
||||
read
|
||||
if [[ $REPLY -ge 1 ]] && [[ $REPLY -le $# ]]; then
|
||||
return $REPLY
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
clear
|
||||
|
||||
echo "This script installs Adafruit Snake Eyes Bonnet"
|
||||
echo "software for Raspberry Pi. It's best to dedicate"
|
||||
echo "a card to this, not for systems in regular use."
|
||||
echo
|
||||
echo "Target system (may be different than current host):"
|
||||
selectN "Raspberry Pi 4, Pi 400, or Compute Module 4" "All other models"
|
||||
#if [[ $? -eq "1" ]]; then
|
||||
if [ $? -eq "1" ]; then
|
||||
IS_PI4=1
|
||||
fi
|
||||
|
||||
if [ $IS_PI4 ]; then
|
||||
# Verify this is Raspbian Desktop OS (X11 should exist)
|
||||
if [ ! -d "/usr/bin/X11" ]; then
|
||||
echo "Target system is Pi 4/400/CM4 but this appears to"
|
||||
echo "be a \"Lite\" OS. \"Desktop\" OS is required."
|
||||
echo -n "Continue anyway? [y/N]"
|
||||
read
|
||||
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
|
||||
echo "Canceled."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# Verify this is Raspbian Lite OS (X11 should NOT exist)
|
||||
if [ -d "/usr/bin/X11" ]; then
|
||||
echo "Target system is not Pi 4/400/CM4 yet this appears to"
|
||||
echo "be a \"Desktop\" OS. \"Lite\" OS (Legacy) is required."
|
||||
echo -n "Continue anyway? [y/N]"
|
||||
read
|
||||
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
|
||||
echo "Canceled."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
SCREEN_VALUES=(-o -t -i)
|
||||
SCREEN_NAMES=("OLED (128x128)" "TFT (128x128)" "IPS (240x240)" HDMI)
|
||||
RADIUS_VALUES=(128 128 240)
|
||||
|
|
@ -67,40 +86,56 @@ SCREEN_SELECT=$?
|
|||
echo -n "Install GPIO-halt utility? [y/N] "
|
||||
read
|
||||
if [[ "$REPLY" =~ (yes|y|Y)$ ]]; then
|
||||
INSTALL_HALT=1
|
||||
echo -n "GPIO pin for halt: "
|
||||
read
|
||||
HALT_PIN=$REPLY
|
||||
INSTALL_HALT=1
|
||||
echo -n "GPIO pin for halt: "
|
||||
read
|
||||
HALT_PIN=$REPLY
|
||||
fi
|
||||
|
||||
echo -n "Install ADC support? [y/N] "
|
||||
echo -n "Install Bonnet ADC support? [y/N] "
|
||||
read
|
||||
if [[ "$REPLY" =~ (yes|y|Y)$ ]]; then
|
||||
INSTALL_ADC=1
|
||||
INSTALL_ADC=1
|
||||
fi
|
||||
|
||||
echo -n "Install USB Ethernet gadget support? (Pi Zero) [y/N] "
|
||||
read
|
||||
if [[ "$REPLY" =~ (yes|y|Y)$ ]]; then
|
||||
INSTALL_GADGET=1
|
||||
INSTALL_GADGET=1
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Screen type: ${SCREEN_NAMES[$SCREEN_SELECT-1]}"
|
||||
if [ $INSTALL_HALT -eq 1 ]; then
|
||||
echo "Install GPIO-halt: YES (GPIO$HALT_PIN)"
|
||||
echo "Install GPIO-halt: YES (GPIO$HALT_PIN)"
|
||||
else
|
||||
echo "Install GPIO-halt: NO"
|
||||
echo "Install GPIO-halt: NO"
|
||||
fi
|
||||
echo "ADC support: ${OPTION_NAMES[$INSTALL_ADC]}"
|
||||
echo "Bonnet ADC support: ${OPTION_NAMES[$INSTALL_ADC]}"
|
||||
echo "Ethernet USB gadget support: ${OPTION_NAMES[$INSTALL_GADGET]}"
|
||||
if [ $SCREEN_SELECT -eq 3 ]; then
|
||||
echo "Video resolution will be set to 1280x720, no overscan"
|
||||
echo "Video resolution will be set to 1280x720, no overscan"
|
||||
else
|
||||
echo "Video resolution will be set to 640x480, no overscan"
|
||||
echo "Video resolution will be set to 640x480, no overscan"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo -n "CONTINUE? [y/N] "
|
||||
echo "Installation steps include:"
|
||||
echo "- Update package index files (apt-get update)"
|
||||
echo "- Install Python libraries: numpy, pi3d, svg.path,"
|
||||
echo " rpi-gpio, python3-dev, python3-pil"
|
||||
echo "- Install Adafruit eye code and data in /boot"
|
||||
echo "- Set HDMI resolution, GPU RAM, disable overscan"
|
||||
if [ $IS_PI4 ]; then
|
||||
echo "- Disable desktop, configure video driver"
|
||||
fi
|
||||
echo "- Enable SPI0 and SPI1 peripherals if needed"
|
||||
echo
|
||||
echo "THIS IS A ONE-WAY OPERATION, NO UNINSTALL PROVIDED."
|
||||
echo "EXISTING INSTALLATION, IF ANY, WILL BE OVERWRITTEN."
|
||||
echo "Run time ~10 minutes. Reboot required."
|
||||
echo
|
||||
echo -n "Do you understand and want to proceed? [y/N]"
|
||||
read
|
||||
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
|
||||
echo "Canceled."
|
||||
|
|
@ -114,27 +149,26 @@ fi
|
|||
# perform replacement if found, else append replacement to end of file.
|
||||
# (# $1 = filename, $2 = pattern to match, $3 = replacement)
|
||||
reconfig() {
|
||||
grep $2 $1 >/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
# Pattern found; replace in file
|
||||
sed -i "s/$2/$3/g" $1 >/dev/null
|
||||
else
|
||||
# Not found; append (silently)
|
||||
echo $3 | sudo tee -a $1 >/dev/null
|
||||
fi
|
||||
grep $2 $1 >/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
# Pattern found; replace in file
|
||||
sed -i "s/$2/$3/g" $1 >/dev/null
|
||||
else
|
||||
# Not found; append (silently)
|
||||
echo $3 | sudo tee -a $1 >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
# Same as above, but appends to same line rather than new line
|
||||
reconfig2() {
|
||||
grep $2 $1 >/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
# Pattern found; replace in file
|
||||
sed -i "s/$2/$3/g" $1 >/dev/null
|
||||
else
|
||||
# Not found; append to line (silently)
|
||||
sed -i "s/$/ $3/g" $1 >/dev/null
|
||||
|
||||
fi
|
||||
grep $2 $1 >/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
# Pattern found; replace in file
|
||||
sed -i "s/$2/$3/g" $1 >/dev/null
|
||||
else
|
||||
# Not found; append to line (silently)
|
||||
sed -i "s/$/ $3/g" $1 >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
echo
|
||||
|
|
@ -144,10 +178,11 @@ apt-get update
|
|||
|
||||
echo "Installing Python libraries..."
|
||||
# WAS: apt-get install -y --force-yes python-pip python-dev python-imaging python-smbus
|
||||
apt-get install -y python-pip python-dev python-pil python-smbus
|
||||
pip install numpy pi3d svg.path adafruit-ads1x15
|
||||
# smbus and ads1x15 Python libs are installed regardless whether ADC
|
||||
# is enabled; simplifies the Python code a little (no "uncomment this")
|
||||
apt-get install -y python3-pip python3-dev python3-pil python3-smbus libatlas-base-dev
|
||||
# WAS: pip3 install numpy pi3d==2.34 svg.path rpi-gpio adafruit-ads1x15
|
||||
pip3 install numpy pi3d svg.path rpi-gpio adafruit-blinka adafruit-circuitpython-ads1x15
|
||||
# smbus and Blinka+ADC libs are installed regardless whether ADC is
|
||||
# enabled; simplifies the Python code a little (no "uncomment this")
|
||||
|
||||
echo "Installing Adafruit code and data in /boot..."
|
||||
cd /tmp
|
||||
|
|
@ -157,110 +192,165 @@ unzip master.zip
|
|||
cp -r Pi_Eyes-master /boot/Pi_Eyes
|
||||
rm -rf master.zip Pi_Eyes-master
|
||||
if [ $INSTALL_HALT -ne 0 ]; then
|
||||
echo "Installing gpio-halt in /usr/local/bin..."
|
||||
curl -LO https://github.com/adafruit/Adafruit-GPIO-Halt/archive/master.zip
|
||||
unzip master.zip
|
||||
cd Adafruit-GPIO-Halt-master
|
||||
make
|
||||
mv gpio-halt /usr/local/bin
|
||||
cd ..
|
||||
rm -rf Adafruit-GPIO-Halt-master
|
||||
echo "Installing gpio-halt in /usr/local/bin..."
|
||||
curl -LO https://github.com/adafruit/Adafruit-GPIO-Halt/archive/master.zip
|
||||
unzip master.zip
|
||||
cd Adafruit-GPIO-Halt-master
|
||||
make
|
||||
mv gpio-halt /usr/local/bin
|
||||
cd ..
|
||||
rm -rf Adafruit-GPIO-Halt-master
|
||||
fi
|
||||
|
||||
# CONFIG -------------------------------------------------------------------
|
||||
|
||||
echo "Configuring system..."
|
||||
|
||||
if [ $IS_PI4 ]; then
|
||||
# Make desktop system to boot to console (from raspi-config script):
|
||||
systemctl set-default multi-user.target
|
||||
ln -fs /lib/systemd/system/getty@.service /etc/systemd/system/getty.target.wants/getty@tty1.service
|
||||
rm -f /etc/systemd/system/getty@tty1.service.d/autologin.conf
|
||||
|
||||
# Pi3D requires "fake" KMS overlay to work. Check /boot/config.txt for
|
||||
# vc4-fkms-v3d overlay present and active. If so, nothing to do here,
|
||||
# module's already configured.
|
||||
grep '^dtoverlay=vc4-fkms-v3d' /boot/config.txt >/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
# fkms overlay not present, or is commented out. Check if vc4-kms-v3d
|
||||
# (no 'f') is present and active. That's normally the default.
|
||||
grep '^dtoverlay=vc4-kms-v3d' /boot/config.txt >/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
# It IS present. Comment out that line for posterity, and insert the
|
||||
# 'fkms' item on the next line.
|
||||
sed -i "s/^dtoverlay=vc4-kms-v3d/#&\ndtoverlay=vc4-fkms-v3d/g" /boot/config.txt >/dev/null
|
||||
else
|
||||
# It's NOT present. Silently append 'fkms' overlay to end of file.
|
||||
echo dtoverlay=vc4-fkms-v3d | sudo tee -a /boot/config.txt >/dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
# Disable screen blanking in X config
|
||||
echo "Section \"ServerFlags\"
|
||||
Option \"BlankTime\" \"0\"
|
||||
Option \"StandbyTime\" \"0\"
|
||||
Option \"SuspendTime\" \"0\"
|
||||
Option \"OffTime\" \"0\"
|
||||
Option \"dpms\" \"false\"
|
||||
EndSection" > /etc/X11/xorg.conf
|
||||
|
||||
fi
|
||||
|
||||
# Disable overscan compensation (use full screen):
|
||||
raspi-config nonint do_overscan 1
|
||||
|
||||
# Dedicate 128 MB to the GPU:
|
||||
sudo raspi-config nonint do_memory_split 128
|
||||
|
||||
# HDMI settings for Pi eyes
|
||||
reconfig /boot/config.txt "^.*hdmi_force_hotplug.*$" "hdmi_force_hotplug=1"
|
||||
reconfig /boot/config.txt "^.*hdmi_group.*$" "hdmi_group=2"
|
||||
reconfig /boot/config.txt "^.*hdmi_mode.*$" "hdmi_mode=87"
|
||||
if [ $SCREEN_SELECT -eq 3 ]; then
|
||||
# IPS display - set HDMI to 1280x720
|
||||
reconfig /boot/config.txt "^.*hdmi_cvt.*$" "hdmi_cvt=1280 720 60 1 0 0 0"
|
||||
# IPS display - set HDMI to 1280x720
|
||||
reconfig /boot/config.txt "^.*hdmi_cvt.*$" "hdmi_cvt=1280 720 60 1 0 0 0"
|
||||
else
|
||||
# All others - set HDMI to 640x480
|
||||
reconfig /boot/config.txt "^.*hdmi_cvt.*$" "hdmi_cvt=640 480 60 1 0 0 0"
|
||||
# All others - set HDMI to 640x480
|
||||
reconfig /boot/config.txt "^.*hdmi_cvt.*$" "hdmi_cvt=640 480 60 1 0 0 0"
|
||||
fi
|
||||
|
||||
|
||||
# Enable I2C for ADC
|
||||
if [ $INSTALL_ADC -ne 0 ]; then
|
||||
raspi-config nonint do_i2c 0
|
||||
raspi-config nonint do_i2c 0
|
||||
fi
|
||||
|
||||
if [ $INSTALL_HALT -ne 0 ]; then
|
||||
# Add gpio-halt to /rc.local:
|
||||
grep gpio-halt /etc/rc.local >/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
# gpio-halt already in rc.local, but make sure correct:
|
||||
sed -i "s/^.*gpio-halt.*$/\/usr\/local\/bin\/gpio-halt $HALT_PIN \&/g" /etc/rc.local >/dev/null
|
||||
else
|
||||
# Insert gpio-halt into rc.local before final 'exit 0'
|
||||
sed -i "s/^exit 0/\/usr\/local\/bin\/gpio-halt $HALT_PIN \&\\nexit 0/g" /etc/rc.local >/dev/null
|
||||
fi
|
||||
# Add gpio-halt to /rc.local:
|
||||
grep gpio-halt /etc/rc.local >/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
# gpio-halt already in rc.local, but make sure correct:
|
||||
sed -i "s/^.*gpio-halt.*$/\/usr\/local\/bin\/gpio-halt $HALT_PIN \&/g" /etc/rc.local >/dev/null
|
||||
else
|
||||
# Insert gpio-halt into rc.local before final 'exit 0'
|
||||
sed -i "s/^exit 0/\/usr\/local\/bin\/gpio-halt $HALT_PIN \&\\nexit 0/g" /etc/rc.local >/dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
# If using OLED, TFT or IPS, enable SPI and install fbx2 and eyes.py,
|
||||
# else (HDMI) skip SPI, fbx2 and install cyclops.py (single eye)
|
||||
if [ $SCREEN_SELECT -ne 4 ]; then
|
||||
|
||||
# Enable SPI0 using raspi-config
|
||||
raspi-config nonint do_spi 0
|
||||
# Enable SPI0 using raspi-config
|
||||
raspi-config nonint do_spi 0
|
||||
|
||||
# Enable SPI1 by adding overlay to /boot/config.txt
|
||||
reconfig /boot/config.txt "^.*dtparam=spi1.*$" "dtparam=spi1=on"
|
||||
reconfig /boot/config.txt "^.*dtoverlay=spi1.*$" "dtoverlay=spi1-3cs"
|
||||
# Enable SPI1 by adding overlay to /boot/config.txt
|
||||
reconfig /boot/config.txt "^.*dtparam=spi1.*$" "dtparam=spi1=on"
|
||||
reconfig /boot/config.txt "^.*dtoverlay=spi1.*$" "dtoverlay=spi1-3cs"
|
||||
|
||||
# Adjust spidev buffer size to 8K (default is 4K)
|
||||
reconfig2 /boot/cmdline.txt "spidev\.bufsiz=.*" "spidev.bufsiz=8192"
|
||||
# Adjust spidev buffer size to 8K (default is 4K)
|
||||
reconfig2 /boot/cmdline.txt "spidev\.bufsiz=.*" "spidev.bufsiz=8192"
|
||||
|
||||
SCREEN_OPT=${SCREEN_VALUES[($SCREEN_SELECT-1)]}
|
||||
SCREEN_OPT=${SCREEN_VALUES[($SCREEN_SELECT-1)]}
|
||||
|
||||
# Auto-start fbx2 on boot
|
||||
grep fbx2 /etc/rc.local >/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
# fbx2 already in rc.local, but make sure correct:
|
||||
sed -i "s/^.*fbx2.*$/\/boot\/Pi_Eyes\/fbx2 $SCREEN_OPT \&/g" /etc/rc.local >/dev/null
|
||||
else
|
||||
# Insert fbx2 into rc.local before final 'exit 0'
|
||||
sed -i "s/^exit 0/\/boot\/Pi_Eyes\/fbx2 $SCREEN_OPT \&\\nexit 0/g" /etc/rc.local >/dev/null
|
||||
fi
|
||||
# Auto-start fbx2 on boot
|
||||
grep fbx2 /etc/rc.local >/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
# fbx2 already in rc.local, but make sure correct:
|
||||
sed -i "s/^.*fbx2.*$/\/boot\/Pi_Eyes\/fbx2 $SCREEN_OPT \&/g" /etc/rc.local >/dev/null
|
||||
else
|
||||
# Insert fbx2 into rc.local before final 'exit 0'
|
||||
sed -i "s/^exit 0/\/boot\/Pi_Eyes\/fbx2 $SCREEN_OPT \&\\nexit 0/g" /etc/rc.local >/dev/null
|
||||
fi
|
||||
|
||||
RADIUS=${RADIUS_VALUES[($SCREEN_SELECT-1)]}
|
||||
# Auto-start eyes.py on boot
|
||||
grep eyes.py /etc/rc.local >/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
# eyes.py already in rc.local, but make sure correct:
|
||||
sed -i "s/^.*eyes.py.*$/cd \/boot\/Pi_Eyes;python eyes.py --radius $RADIUS \&/g" /etc/rc.local >/dev/null
|
||||
else
|
||||
# Insert eyes.py into rc.local before final 'exit 0'
|
||||
sed -i "s/^exit 0/cd \/boot\/Pi_Eyes;python eyes.py --radius $RADIUS \&\\nexit 0/g" /etc/rc.local >/dev/null
|
||||
fi
|
||||
RADIUS=${RADIUS_VALUES[($SCREEN_SELECT-1)]}
|
||||
# Auto-start eyes.py on boot
|
||||
grep eyes.py /etc/rc.local >/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
# eyes.py already in rc.local, but make sure correct:
|
||||
if [ $IS_PI4 ]; then
|
||||
sed -i "s/^.*eyes.py.*$/cd \/boot\/Pi_Eyes;xinit \/usr\/bin\/python3 eyes.py --radius $RADIUS \:0 \&/g" /etc/rc.local >/dev/null
|
||||
else
|
||||
sed -i "s/^.*eyes.py.*$/cd \/boot\/Pi_Eyes;python3 eyes.py --radius $RADIUS \&/g" /etc/rc.local >/dev/null
|
||||
fi
|
||||
else
|
||||
# Insert eyes.py into rc.local before final 'exit 0'
|
||||
if [ $IS_PI4 ]; then
|
||||
sed -i "s/^exit 0/cd \/boot\/Pi_Eyes;xinit \/usr\/bin\/python3 eyes.py --radius $RADIUS \:0 \&\\nexit 0/g" /etc/rc.local >/dev/null
|
||||
else
|
||||
sed -i "s/^exit 0/cd \/boot\/Pi_Eyes;python3 eyes.py --radius $RADIUS \&\\nexit 0/g" /etc/rc.local >/dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
else
|
||||
|
||||
# Auto-start cyclops.py on boot
|
||||
grep cyclops.py /etc/rc.local >/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
# cyclops.py already in rc.local, but make sure correct:
|
||||
sed -i "s/^.*cyclops.py.*$/cd \/boot\/Pi_Eyes;python cyclops.py \&/g" /etc/rc.local >/dev/null
|
||||
else
|
||||
# Insert cyclops.py into rc.local before final 'exit 0'
|
||||
sed -i "s/^exit 0/cd \/boot\/Pi_Eyes;python cyclops.py \&\\nexit 0/g" /etc/rc.local >/dev/null
|
||||
fi
|
||||
# Auto-start cyclops.py on boot
|
||||
grep cyclops.py /etc/rc.local >/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
# cyclops.py already in rc.local, but make sure correct:
|
||||
if [ $IS_PI4 ]; then
|
||||
sed -i "s/^.*cyclops.py.*$/cd \/boot\/Pi_Eyes;xinit \/usr\/bin\/python3 cyclops.py \:0 \&/g" /etc/rc.local >/dev/null
|
||||
else
|
||||
sed -i "s/^.*cyclops.py.*$/cd \/boot\/Pi_Eyes;python3 cyclops.py \&/g" /etc/rc.local >/dev/null
|
||||
fi
|
||||
else
|
||||
# Insert cyclops.py into rc.local before final 'exit 0'
|
||||
if [ $IS_PI4 ]; then
|
||||
sed -i "s/^exit 0/cd \/boot\/Pi_Eyes;xinit \/usr\/bin\/python3 cyclops.py \:0 \&\\nexit 0/g" /etc/rc.local >/dev/null
|
||||
else
|
||||
sed -i "s/^exit 0/cd \/boot\/Pi_Eyes;python3 cyclops.py \&\\nexit 0/g" /etc/rc.local >/dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if [ $INSTALL_GADGET -ne 0 ]; then
|
||||
reconfig /boot/config.txt "^.*dtoverlay=dwc2.*$" "dtoverlay=dwc2"
|
||||
grep "modules-load=dwc2,g_ether" /boot/cmdline.txt >/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
# Insert ethernet gadget into config.txt after 'rootwait'
|
||||
sed -i "s/rootwait/rootwait modules-load=dwc2,g_ether/g" /boot/cmdline.txt >/dev/null
|
||||
fi
|
||||
reconfig /boot/config.txt "^.*dtoverlay=dwc2.*$" "dtoverlay=dwc2"
|
||||
grep "modules-load=dwc2,g_ether" /boot/cmdline.txt >/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
# Insert ethernet gadget into config.txt after 'rootwait'
|
||||
sed -i "s/rootwait/rootwait modules-load=dwc2,g_ether/g" /boot/cmdline.txt >/dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
# PROMPT FOR REBOOT --------------------------------------------------------
|
||||
|
|
@ -272,8 +362,8 @@ echo
|
|||
echo -n "REBOOT NOW? [y/N] "
|
||||
read
|
||||
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
|
||||
echo "Exiting without reboot."
|
||||
exit 0
|
||||
echo "Exiting without reboot."
|
||||
exit 0
|
||||
fi
|
||||
echo "Reboot started..."
|
||||
reboot
|
||||
|
|
|
|||
129
pi-touch-cam.py
Executable file
129
pi-touch-cam.py
Executable file
|
|
@ -0,0 +1,129 @@
|
|||
"""
|
||||
Adafruit Pi Touch Cam Setup Script
|
||||
(C) Adafruit Industries, Creative Commons 3.0 - Attribution Share Alike
|
||||
|
||||
Converted to Python by Melissa LeBlanc-Williams for Adafruit Industries
|
||||
|
||||
Note: Currently Untested
|
||||
"""
|
||||
|
||||
try:
|
||||
from adafruit_shell import Shell
|
||||
except ImportError:
|
||||
raise RuntimeError("The library 'adafruit_shell' was not found. To install, try typing: sudo pip3 install adafruit-python-shell")
|
||||
import os
|
||||
|
||||
shell = Shell()
|
||||
shell.group="Retrogame"
|
||||
|
||||
def main():
|
||||
shell.clear()
|
||||
print("""This script will install and/or modify
|
||||
packages needed for the Adafruit Pi
|
||||
Camera project. It requires that the
|
||||
adafruit-pitft.sh installer script (for
|
||||
PiTFT display support) was run first.
|
||||
|
||||
Operations performed include:
|
||||
- In /boot/firmware/config.txt, enable camera
|
||||
- apt-get update
|
||||
- Install Python libraries:
|
||||
picamera, pygame, PIL
|
||||
- Downgrade SDL library for pygame
|
||||
touch compatibility
|
||||
- Download Dropbox Updater and
|
||||
Adafruit Pi Cam software
|
||||
|
||||
Run time 5+ minutes. Reboot required.
|
||||
""")
|
||||
|
||||
boot_config = shell.get_boot_config()
|
||||
|
||||
if not shell.prompt("CONTINUE?", default='n'):
|
||||
print("Canceled.")
|
||||
shell.exit()
|
||||
print("Continuing...")
|
||||
|
||||
|
||||
if shell.grep("dtoverlay=pitft", boot_config):
|
||||
shell.bail(f"PiTFT overlay not in {boot_config}.\n"
|
||||
"Download & run adafruit-pitft.py first.\n"
|
||||
"Canceling.")
|
||||
|
||||
print("Configuring camera + PiTFT settings...")
|
||||
|
||||
# Set PiTFT speed to 80 MHz, 60 Hz
|
||||
shell.pattern_replace(boot_config, "speed=.*,fps=.*", "speed=80000000,fps=60")
|
||||
|
||||
# Check if Pi camera is enabled. If not, add it...
|
||||
shell.reconfig(boot_config, "^start_x=.*", "start_x=1")
|
||||
|
||||
# gpu_mem must be >= 128 MB for camera to work
|
||||
result = shell.pattern_search(boot_config, "^gpu_mem=", return_match=True)
|
||||
if not result:
|
||||
# gpu_mem isn't set. Add to config
|
||||
shell.write_text_file(boot_config, "\ngpu_mem=128", append=True)
|
||||
elif result.group(1) < 128:
|
||||
# gpu_mem present but too small; increase to 128MB
|
||||
shell.reconfig(boot_config, "^gpu_mem=.*", "gpu_mem=128")
|
||||
|
||||
print("Installing prerequisite packages...")
|
||||
|
||||
# Enable Wheezy package sources (for SDL downgrade)
|
||||
shell.write_text_file("/etc/apt/sources.list.d/wheezy.list", "deb http://archive.raspbian.org/raspbian wheezy main\n", append=True)
|
||||
|
||||
# Set 'stable' as default package source (current OS)
|
||||
shell.write_text_file("/etc/apt/apt.conf.d/10defaultRelease", "APT::Default-release \"stable\";\n", append=True)
|
||||
|
||||
# Set priority for libsdl from Wheezy higher than current package
|
||||
shell.write_text_file("/etc/apt/preferences.d/libsdl", (
|
||||
"Package: libsdl1.2debian\n"
|
||||
"Pin: release n=stretch\n"
|
||||
"Pin-Priority: -10\n"
|
||||
"Pin: release n=jessie\n"
|
||||
"Pin-Priority: -10\n"
|
||||
"Package: libsdl1.2debian\n"
|
||||
"Pin: release n=wheezy\n"
|
||||
"Pin-Priority:900\n"
|
||||
))
|
||||
|
||||
# Update the APT package index files, install Python libraries
|
||||
print("Updating System Packages")
|
||||
if not shell.run_command("sudo apt-get update"):
|
||||
shell.bail("Apt failed to update indexes!")
|
||||
print("Installing packages...")
|
||||
if not shell.run_command("sudo apt-get -y --force-yes install python-picamera python-pygame python-imaging"):
|
||||
shell.bail("Apt failed to install software!")
|
||||
|
||||
print("Downgrading SDL library...")
|
||||
|
||||
if not shell.run_command("apt-get -y --force-yes install libsdl1.2debian/wheezy"):
|
||||
shell.bail("Apt failed to downgrade SDL library!")
|
||||
|
||||
print("Downloading Dropbox uploader and")
|
||||
print("Adafruit Pi Cam to home directory...")
|
||||
|
||||
shell.chdir("~pi")
|
||||
shell.run_command("wget https://github.com/andreafabrizi/Dropbox-Uploader/archive/master.zip")
|
||||
shell.run_command("unzip master.zip")
|
||||
shell.remove("master.zip")
|
||||
shell.move("Dropbox-Uploader-master", "Dropbox-Uploader")
|
||||
|
||||
shell.run_command("wget https://github.com/adafruit/adafruit-pi-cam/archive/master.zip")
|
||||
shell.run_command("unzip master.zip")
|
||||
shell.remove("master.zip")
|
||||
shell.chown("Dropbox-Uploader", "pi", recursive=True)
|
||||
shell.chown("adafruit-pi-cam-master", "pi", recursive=True)
|
||||
|
||||
# Add lines to /etc/rc.local (commented out by default):
|
||||
shell.pattern_replace("/etc/rc.local", "^exit 0", "# Enable this line to run camera at startup:\n# cd /home/pi/adafruit-pi-cam-master ; sudo python cam.py\n\nexit 0")
|
||||
|
||||
# Prompt to reboot!
|
||||
print("\nCamera and PiTFT settings won't take")
|
||||
print("effect until next boot.")
|
||||
shell.prompt_reboot()
|
||||
|
||||
# Main function
|
||||
if __name__ == "__main__":
|
||||
shell.require_root()
|
||||
main()
|
||||
181
raspi-blinka.py
Normal file
181
raspi-blinka.py
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
"""
|
||||
Adafruit Raspberry Pi Blinka Setup Script
|
||||
(C) Adafruit Industries, Creative Commons 3.0 - Attribution Share Alike
|
||||
|
||||
Written by Melissa LeBlanc-Williams for Adafruit Industries
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
try:
|
||||
from adafruit_shell import Shell
|
||||
except ImportError:
|
||||
raise RuntimeError("The library 'adafruit_shell' was not found. To install, try typing: sudo pip3 install adafruit-python-shell")
|
||||
|
||||
shell = Shell()
|
||||
shell.group="Blinka"
|
||||
default_python = 3
|
||||
blinka_minimum_python_version = 3.8
|
||||
|
||||
def default_python_version(numeric=True):
|
||||
version = shell.run_command("python -c 'import platform; print(platform.python_version())'", suppress_message=True, return_output=True)
|
||||
if numeric:
|
||||
try:
|
||||
return float(version[0:version.rfind(".")])
|
||||
except ValueError:
|
||||
return None
|
||||
return version
|
||||
|
||||
def get_python3_version(numeric=True):
|
||||
version = shell.run_command("python3 -c 'import platform; print(platform.python_version())'", suppress_message=True, return_output=True)
|
||||
if numeric:
|
||||
return float(version[0:version.rfind(".")])
|
||||
return version
|
||||
|
||||
def check_blinka_python_version():
|
||||
"""
|
||||
Check the Python 3 version for Blinka (which may be a later version than we're running this script with)
|
||||
"""
|
||||
print("Making sure the required version of Python is installed")
|
||||
current = get_python3_version(False)
|
||||
current_major, current_minor = current.split(".")[0:2]
|
||||
required_major, required_minor = str(blinka_minimum_python_version).split(".")[0:2]
|
||||
|
||||
if int(current_major) >= int(required_major) and int(current_minor) >= int(required_minor):
|
||||
return
|
||||
|
||||
shell.bail("Blinka requires a minimum of Python version {} to install, current one is {}. Please update your OS!".format(blinka_minimum_python_version, current))
|
||||
|
||||
def sys_update():
|
||||
print("Updating System Packages")
|
||||
if not shell.run_command("sudo apt-get update --allow-releaseinfo-change"):
|
||||
shell.bail("Apt failed to update indexes!")
|
||||
print("Upgrading packages...")
|
||||
if not shell.run_command("sudo apt-get -y upgrade"):
|
||||
shell.bail("Apt failed to install software!")
|
||||
|
||||
def set_raspiconfig():
|
||||
"""
|
||||
Enable various Raspberry Pi interfaces
|
||||
"""
|
||||
print("Enabling I2C")
|
||||
shell.run_command("sudo raspi-config nonint do_i2c 0")
|
||||
print("Enabling SPI")
|
||||
shell.run_command("sudo raspi-config nonint do_spi 0")
|
||||
print("Enabling Serial")
|
||||
if not shell.run_command("sudo raspi-config nonint do_serial_hw 0", suppress_message=True):
|
||||
shell.run_command("sudo raspi-config nonint do_serial 0")
|
||||
print("Enabling SSH")
|
||||
shell.run_command("sudo raspi-config nonint do_ssh 0")
|
||||
print("Enabling Camera")
|
||||
shell.run_command("sudo raspi-config nonint do_camera 0")
|
||||
print("Disable raspi-config at Boot")
|
||||
shell.run_command("sudo raspi-config nonint disable_raspi_config_at_boot 0")
|
||||
|
||||
def update_python():
|
||||
print("Making sure Python 3 is the default")
|
||||
if default_python < 3:
|
||||
shell.run_command("sudo apt-get install -y python3 git python3-pip")
|
||||
shell.run_command("sudo update-alternatives --install /usr/bin/python python $(which python2) 1")
|
||||
shell.run_command("sudo update-alternatives --install /usr/bin/python python $(which python3) 2")
|
||||
shell.run_command("sudo update-alternatives --skip-auto --config python")
|
||||
|
||||
def update_pip():
|
||||
print("Making sure PIP and setuptools is installed")
|
||||
shell.run_command("sudo apt-get install --upgrade -y python3-pip python3-setuptools")
|
||||
|
||||
def install_blinka(user=False):
|
||||
print("Installing latest version of Blinka locally")
|
||||
shell.run_command("sudo apt-get install -y i2c-tools libgpiod-dev python3-libgpiod")
|
||||
pip_command = "pip3 install --upgrade"
|
||||
username = None
|
||||
if user:
|
||||
username = os.environ["SUDO_USER"]
|
||||
shell.run_command(f"{pip_command} adafruit-blinka", run_as_user=username)
|
||||
|
||||
# Custom function to run additional commands for Pi 5
|
||||
def check_and_install_for_pi5(pi_model, user=False):
|
||||
if shell.is_pi5_or_newer():
|
||||
username = None
|
||||
if user:
|
||||
# Username should be used for PIP install commands
|
||||
username = os.environ["SUDO_USER"]
|
||||
print("Detected Raspberry Pi 5, applying additional fixes...")
|
||||
if shell.exists("lg"):
|
||||
shell.remove("lg")
|
||||
shell.run_command("sudo apt-get install -y wget swig python3-dev python3-setuptools")
|
||||
# Temporarily install setuptools to as root for the build process
|
||||
shell.run_command("sudo pip3 install -U setuptools", run_as_user=username)
|
||||
shell.run_command("wget https://github.com/adafruit/Raspberry-Pi-Installer-Scripts/raw/refs/heads/main/packages/lgpio.zip")
|
||||
shell.run_command("unzip lgpio.zip")
|
||||
if shell.exists("lgpio.zip"):
|
||||
shell.remove("lgpio.zip")
|
||||
shell.chdir("lgpio")
|
||||
shell.run_command("make")
|
||||
shell.run_command("sudo make install")
|
||||
# Remove setuptools after the build process is complete
|
||||
shell.run_command("sudo pip3 uninstall -y setuptools", run_as_user=username)
|
||||
else:
|
||||
print(f"Detected {pi_model}, no additional fixes needed.")
|
||||
|
||||
def check_user_groups():
|
||||
# Check if the user has the groups i2c, spi, gpio, input, and video. If the user is not in a group, then they need to be added.
|
||||
groups = shell.run_command("groups", suppress_message=True, return_output=True).split()
|
||||
required_groups = ["i2c", "spi", "gpio", "input", "video"]
|
||||
for group in required_groups:
|
||||
if group not in groups:
|
||||
print(f"Adding user to the group: {group}.")
|
||||
shell.run_command(f"sudo usermod -aG {group} {os.environ['SUDO_USER']}")
|
||||
|
||||
def main():
|
||||
global default_python
|
||||
shell.clear()
|
||||
# Check Raspberry Pi and Bail
|
||||
pi_model = shell.get_board_model()
|
||||
if not shell.is_raspberry_pi():
|
||||
shell.bail("This model of Raspberry Pi is not currently supported by Blinka")
|
||||
print("""This script configures your
|
||||
Raspberry Pi and installs Blinka
|
||||
""")
|
||||
print("{} detected.\n".format(pi_model))
|
||||
if not shell.is_raspberry_pi():
|
||||
shell.bail("Non-Raspberry Pi board detected. This must be run on a Raspberry Pi")
|
||||
os_identifier = shell.get_os()
|
||||
if os_identifier != "Raspbian":
|
||||
shell.bail("Sorry, the OS detected was {}. This script currently only runs on Raspberry Pi OS.".format(os_identifier))
|
||||
if not shell.is_python3():
|
||||
shell.bail("You must be running Python 3. Older versions have now been deprecated.")
|
||||
shell.check_kernel_update_reboot_required()
|
||||
python_version = default_python_version()
|
||||
if not python_version:
|
||||
shell.warn("WARNING No Default System python tied to the `python` command. It will be set to Version 3.")
|
||||
default_python = 0
|
||||
if not shell.prompt("Continue?"):
|
||||
shell.exit()
|
||||
elif int(default_python_version()) < 3:
|
||||
shell.warn("WARNING Default System python version is {}. It will be updated to Version 3.".format(default_python_version(False)))
|
||||
default_python = 2
|
||||
if not shell.prompt("Continue?"):
|
||||
shell.exit()
|
||||
sys_update()
|
||||
check_blinka_python_version()
|
||||
set_raspiconfig()
|
||||
update_python()
|
||||
update_pip()
|
||||
install_blinka(True)
|
||||
check_user_groups()
|
||||
|
||||
# Check and install any Pi 5 fixes if detected
|
||||
check_and_install_for_pi5(pi_model, True)
|
||||
|
||||
# Done
|
||||
print("""DONE.
|
||||
|
||||
Settings take effect on next boot.
|
||||
""")
|
||||
shell.prompt_reboot()
|
||||
|
||||
# Main function
|
||||
if __name__ == "__main__":
|
||||
shell.require_root()
|
||||
main()
|
||||
188
raspi-spi-reassign.py
Normal file
188
raspi-spi-reassign.py
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
"""
|
||||
Adafruit Raspberry Pi SPI Chip Enable Reassignment Script
|
||||
(C) Adafruit Industries, Creative Commons 3.0 - Attribution Share Alike
|
||||
"""
|
||||
|
||||
try:
|
||||
import click
|
||||
except ImportError:
|
||||
raise RuntimeError("The library 'Click' was not found. To install, try typing: sudo pip3 install --upgrade click")
|
||||
try:
|
||||
from adafruit_shell import Shell
|
||||
except ImportError:
|
||||
raise RuntimeError("The library 'adafruit_shell' was not found. To install, try typing: sudo pip3 install adafruit-python-shell")
|
||||
|
||||
shell = Shell()
|
||||
shell.group="SPI Reassign"
|
||||
|
||||
allowed_gpios = (4, 5, 6, 7, 8, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27)
|
||||
spi0_default_pins = (8, 7)
|
||||
|
||||
DISABLE_GPIO_TEXT = "Disabled"
|
||||
|
||||
boot_dir = "/boot/firmware"
|
||||
if not shell.exists(boot_dir) or not shell.isdir(boot_dir):
|
||||
boot_dir = "/boot"
|
||||
|
||||
"""
|
||||
For now this will only ask about SPI0, but we can later add SPI1
|
||||
"""
|
||||
|
||||
def valid_pins(ce0_pin, ce1_pin):
|
||||
if ce0_pin is None and ce1_pin is not None:
|
||||
return False
|
||||
if ce0_pin is not None and ce0_pin == ce1_pin:
|
||||
return False
|
||||
if ce0_pin is not None and int(ce0_pin) not in allowed_gpios:
|
||||
return False
|
||||
if ce1_pin is not None and int(ce1_pin) not in allowed_gpios:
|
||||
return False
|
||||
return True
|
||||
|
||||
def convert_option(pin):
|
||||
if pin == "disabled":
|
||||
return None
|
||||
return int(pin)
|
||||
|
||||
def valid_options(ce0_option, ce1_option):
|
||||
if ce0_option is None or ce1_option is None:
|
||||
return False
|
||||
return valid_pins(convert_option(ce0_option), convert_option(ce1_option))
|
||||
|
||||
def disable_spi():
|
||||
print("Disabling SPI")
|
||||
shell.run_command("sudo raspi-config nonint do_spi 1")
|
||||
|
||||
def enable_spi():
|
||||
print("Enabling SPI")
|
||||
shell.run_command("sudo raspi-config nonint do_spi 0")
|
||||
|
||||
def spi_disabled():
|
||||
return shell.run_command("sudo raspi-config nonint get_spi", suppress_message=True, return_output=True).strip() == "1"
|
||||
|
||||
def remove_custom():
|
||||
shell.pattern_replace(f"{boot_dir}/config.txt", 'dtoverlay=spi0-[0-2]cs,cs.*?\n', multi_line=True)
|
||||
|
||||
def format_gpio(gpio):
|
||||
if gpio is None:
|
||||
return DISABLE_GPIO_TEXT
|
||||
return f"GPIO {gpio}"
|
||||
|
||||
def gpio_options(pool):
|
||||
options = []
|
||||
for gpio in pool:
|
||||
options.append(format_gpio(gpio))
|
||||
return options
|
||||
|
||||
def write_new_custom(ce0_pin, ce1_pin):
|
||||
if (ce0_pin, ce1_pin) != spi0_default_pins:
|
||||
overlay_command = "dtoverlay=spi0-2cs"
|
||||
if ce0_pin is None and ce1_pin is None:
|
||||
overlay_command = "dtoverlay=spi0-0cs"
|
||||
elif ce1_pin is None:
|
||||
overlay_command = "dtoverlay=spi0-1cs"
|
||||
if ce0_pin != spi0_default_pins[0] and ce0_pin is not None:
|
||||
overlay_command += ",cs0_pin={}".format(ce0_pin)
|
||||
if ce1_pin != spi0_default_pins[1] and ce1_pin is not None:
|
||||
overlay_command += ",cs1_pin={}".format(ce1_pin)
|
||||
shell.write_text_file(f"{boot_dir}/config.txt", overlay_command + "\n")
|
||||
|
||||
@click.command()
|
||||
@click.option('--ce0', nargs=1, default=None, help="Specify a GPIO for CE0 or 'disabled' to disable", type=str)
|
||||
@click.option('--ce1', nargs=1, default=None, help="Specify a GPIO for CE1 or 'disabled' to disable", type=str)
|
||||
@click.option('--reboot', nargs=1, default=None, type=click.Choice(['yes', 'no']), help="Specify whether to reboot after the script is finished")
|
||||
def main(ce0, ce1, reboot):
|
||||
ask_reboot = True
|
||||
auto_reboot = False
|
||||
if reboot is not None:
|
||||
ask_reboot = False
|
||||
auto_reboot = reboot.lower() == 'yes'
|
||||
if valid_options(ce0, ce1):
|
||||
ce0 = convert_option(ce0)
|
||||
ce1 = convert_option(ce1)
|
||||
remove_custom()
|
||||
write_new_custom(ce0, ce1)
|
||||
if auto_reboot:
|
||||
shell.reboot()
|
||||
if ask_reboot:
|
||||
shell.prompt_reboot()
|
||||
exit(0)
|
||||
else:
|
||||
print("Invalid ce0 or ce1", ce0, ce1)
|
||||
#shell.clear()
|
||||
# Check Raspberry Pi and Bail
|
||||
pi_model = shell.get_board_model()
|
||||
print("""This script allows you
|
||||
to easily reassign the SPI Chip Enable
|
||||
pins so the OS automatic handling of the
|
||||
lines doesn't interfere with CircuitPython.
|
||||
Run time of < 1 minute. Reboot required for
|
||||
changes to take effect!
|
||||
""")
|
||||
menu_options = [
|
||||
"Reassign SPI Chip Enable Pins",
|
||||
"Reset to Defaults Pins",
|
||||
"Disable SPI",
|
||||
"Exit",
|
||||
]
|
||||
|
||||
if spi_disabled():
|
||||
menu_options[2] = "Enable SPI"
|
||||
|
||||
shell.info("{} detected.\n".format(pi_model))
|
||||
if not shell.is_raspberry_pi():
|
||||
shell.bail("Non-Raspberry Pi board detected. This must be run on a Raspberry Pi")
|
||||
os_identifier = shell.get_os()
|
||||
if os_identifier != "Raspbian":
|
||||
shell.bail("Sorry, the OS detected was {}. This script currently only runs on Raspberry Pi OS.".format(os_identifier))
|
||||
menu_selection = shell.select_n(
|
||||
"Select an option:", menu_options
|
||||
)
|
||||
if menu_selection == 1:
|
||||
while True:
|
||||
# Reassign
|
||||
gpio_pool = list(allowed_gpios)
|
||||
gpio_pool.append(None)
|
||||
# Ask for pin for CE0
|
||||
ce0_selection = shell.select_n("Select a new GPIO for CE0", gpio_options(gpio_pool))
|
||||
ce0_pin = gpio_pool[ce0_selection - 1]
|
||||
if ce0_pin is not None:
|
||||
gpio_pool.remove(ce0_pin)
|
||||
# Ask for pin for CE1
|
||||
ce1_selection = shell.select_n("Select a new GPIO for CE1", gpio_options(gpio_pool))
|
||||
ce1_pin = gpio_pool[ce1_selection - 1]
|
||||
else:
|
||||
ce1_pin = None
|
||||
if shell.prompt(f"The new settings will be {format_gpio(ce0_pin)} for CE0 and {format_gpio(ce1_pin)} for CE1. Is this correct?"):
|
||||
break
|
||||
remove_custom()
|
||||
write_new_custom(ce0_pin, ce1_pin)
|
||||
if spi_disabled():
|
||||
enable_spi()
|
||||
elif menu_selection == 2:
|
||||
# Reset to Defaults
|
||||
remove_custom()
|
||||
elif menu_selection == 3:
|
||||
# Enable/Disable SPI
|
||||
if spi_disabled():
|
||||
enable_spi()
|
||||
else:
|
||||
disable_spi()
|
||||
remove_custom()
|
||||
elif menu_selection == 4:
|
||||
# Exit
|
||||
shell.exit(0)
|
||||
# Done
|
||||
print("""DONE.
|
||||
|
||||
Settings take effect on next boot.
|
||||
""")
|
||||
if auto_reboot:
|
||||
shell.reboot()
|
||||
if ask_reboot:
|
||||
shell.prompt_reboot()
|
||||
|
||||
# Main function
|
||||
if __name__ == "__main__":
|
||||
shell.require_root()
|
||||
main()
|
||||
|
|
@ -1,5 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo "NEWS: see https://learn.adafruit.com/read-only-raspberry-pi"
|
||||
echo "This script is deprecated, with better functionality now in"
|
||||
echo "the OS without hacks. It's being kept temporarily for reference."
|
||||
echo "You can edit this part out if you really need to run it."
|
||||
exit 0
|
||||
|
||||
# CREDIT TO THESE TUTORIALS:
|
||||
# petr.io/en/blog/2015/11/09/read-only-raspberry-pi-with-jessie
|
||||
# hallard.me/raspberry-pi-read-only
|
||||
|
|
@ -284,18 +290,23 @@ replace /usr/lib/tmpfiles.d/var.conf "spool\s*0755" "spool 1777"
|
|||
touch /tmp/dhcpcd.resolv.conf
|
||||
rm /etc/resolv.conf
|
||||
ln -s /tmp/dhcpcd.resolv.conf /etc/resolv.conf
|
||||
# systemd-ntp must use systemwide /tmp to access /tmp/dhcpcd.resolv.conf
|
||||
replace /lib/systemd/system/ntp.service "PrivateTmp=true" "PrivateTmp=false"
|
||||
|
||||
# Make edits to fstab
|
||||
# make / ro
|
||||
# tmpfs /var/log tmpfs nodev,nosuid 0 0
|
||||
# tmpfs /var/tmp tmpfs nodev,nosuid 0 0
|
||||
# tmpfs /tmp tmpfs nodev,nosuid 0 0
|
||||
replace /etc/fstab "vfat\s*defaults\s" "vfat defaults,ro "
|
||||
replace /etc/fstab "ext4\s*defaults,noatime\s" "ext4 defaults,noatime,ro "
|
||||
replace /etc/fstab "vfat\s*defaults\s.*" "vfat defaults,ro\t0\t0"
|
||||
replace /etc/fstab "ext4\s*defaults,noatime\s.*" "ext4 defaults,noatime,ro\t0\t0"
|
||||
append1 /etc/fstab "/var/log" "tmpfs /var/log tmpfs nodev,nosuid 0 0"
|
||||
append1 /etc/fstab "/var/tmp" "tmpfs /var/tmp tmpfs nodev,nosuid 0 0"
|
||||
append1 /etc/fstab "\s/tmp" "tmpfs /tmp tmpfs nodev,nosuid 0 0"
|
||||
|
||||
# Stop vim creating tmp files in ~/.viminfo (ro)
|
||||
echo 'set viminfo=""' >>/etc/vim/vimrc.local
|
||||
|
||||
# PROMPT FOR REBOOT --------------------------------------------------------
|
||||
|
||||
echo "Done."
|
||||
|
|
|
|||
98
retrogame.py
Executable file
98
retrogame.py
Executable file
|
|
@ -0,0 +1,98 @@
|
|||
"""
|
||||
Adafruit Retrogame Setup Script
|
||||
(C) Adafruit Industries, Creative Commons 3.0 - Attribution Share Alike
|
||||
|
||||
Converted to Python by Melissa LeBlanc-Williams for Adafruit Industries
|
||||
|
||||
Note: Currently Untested
|
||||
"""
|
||||
|
||||
try:
|
||||
from adafruit_shell import Shell
|
||||
except ImportError:
|
||||
raise RuntimeError("The library 'adafruit_shell' was not found. To install, try typing: sudo pip3 install adafruit-python-shell")
|
||||
import os
|
||||
|
||||
shell = Shell()
|
||||
shell.group="Retrogame"
|
||||
|
||||
def main():
|
||||
shell.clear()
|
||||
print("""This script downloads and installs
|
||||
retrogame, a GPIO-to-keypress utility
|
||||
for adding buttons and joysticks, plus
|
||||
one of several configuration files.
|
||||
Run time <1 minute. Reboot recommended.
|
||||
""")
|
||||
|
||||
# Grouped by config name and menu label
|
||||
config = {
|
||||
"pigrrl2": "PiGRRL 2 controls",
|
||||
"pocket": "Pocket PiGRRL",
|
||||
"zero": "PiGRRL Zero",
|
||||
"super": "Super Game Pi",
|
||||
"2button": "Two buttons + joystick",
|
||||
"6button": "Six buttons + joystick",
|
||||
"bonnet": "Adafruit Arcade Bonnet",
|
||||
"cupcade-orig": "Cupcade (gen 1 & 2 only)"
|
||||
}
|
||||
|
||||
RETROGAME_SELECT = shell.select_n(
|
||||
"Select configuration:", list(config.values()) + ["Quit without installing"]
|
||||
)
|
||||
|
||||
if RETROGAME_SELECT <= len(config):
|
||||
CONFIG_NAME = list(config.keys())[RETROGAME_SELECT-1]
|
||||
|
||||
if shell.exists("/boot/retrogame.cfg"):
|
||||
print("/boot/retrogame.cfg already exists.\n"
|
||||
"Continuing will overwrite file.\n")
|
||||
if not shell.prompt("CONTINUE?", default='n'):
|
||||
print("Canceled.")
|
||||
shell.exit()
|
||||
|
||||
print("Downloading, installing retrogame...", end="")
|
||||
# Download to tmpfile because might already be running
|
||||
if shell.run_command("curl -f -s -o /tmp/retrogame https://raw.githubusercontent.com/adafruit/Adafruit-Retrogame/master/retrogame"):
|
||||
shell.move("/tmp/retrogame", "/usr/local/bin/")
|
||||
os.chmod("/usr/local/bin/retrogame", 0o755)
|
||||
print("OK")
|
||||
else:
|
||||
print("ERROR")
|
||||
|
||||
print("Downloading, installing retrogame.cfg...", end="")
|
||||
if shell.run_command(f"curl -f -s -o /boot/retrogame.cfg https://raw.githubusercontent.com/adafruit/Adafruit-Retrogame/master/configs/retrogame.cfg.{CONFIG_NAME}"):
|
||||
print("OK")
|
||||
else:
|
||||
print("ERROR")
|
||||
|
||||
print("Performing other system configuration...", end="")
|
||||
|
||||
# Add udev rule (will overwrite if present)
|
||||
shell.write_text_file("/etc/udev/rules.d/10-retrogame.rules", (
|
||||
r"SUBSYSTEM==\"input\", ATTRS{name}==\"retrogame\", "
|
||||
r"ENV{ID_INPUT_KEYBOARD}=\"1\""
|
||||
))
|
||||
|
||||
if CONFIG_NAME == "bonnet":
|
||||
# If Bonnet, make sure I2C is enabled. Call the I2C
|
||||
# setup function in raspi-config (noninteractive):
|
||||
shell.run_command("raspi-config nonint do_i2c 0")
|
||||
|
||||
# Start on boot
|
||||
if shell.run_command("grep retrogame /etc/rc.local", suppress_message=True):
|
||||
# retrogame already in rc.local, but make sure correct:
|
||||
shell.pattern_replace("/etc/rc.local", "^.*retrogame.*$", "/usr/local/bin/retrogame &")
|
||||
else:
|
||||
# Insert retrogame into rc.local before final 'exit 0'
|
||||
shell.pattern_replace("/etc/rc.local", "^exit 0", "/usr/local/bin/retrogame &\nexit 0")
|
||||
|
||||
print("OK")
|
||||
|
||||
shell.prompt_reboot()
|
||||
print("Done")
|
||||
|
||||
# Main function
|
||||
if __name__ == "__main__":
|
||||
shell.require_root()
|
||||
main()
|
||||
147
rgb-matrix.sh
147
rgb-matrix.sh
|
|
@ -7,7 +7,11 @@
|
|||
# we reference a specific commit (update this as needed):
|
||||
GITUSER=https://github.com/hzeller
|
||||
REPO=rpi-rgb-led-matrix
|
||||
COMMIT=e3dd56dcc0408862f39cccc47c1d9dea1b0fb2d2
|
||||
COMMIT=7a503494378a67f3baa4ac680cecbae2703cc58f
|
||||
# Previously: COMMIT=a3eea997a9254b83ab2de97ae80d83588f696387
|
||||
# Previously: COMMIT=45d3ab5d6cff6e0c14da58930d662822627471fc
|
||||
# Previously: COMMIT=21410d2b0bac006b4a1661594926af347b3ce334
|
||||
# Previously: COMMIT=e3dd56dcc0408862f39cccc47c1d9dea1b0fb2d2
|
||||
|
||||
if [ $(id -u) -ne 0 ]; then
|
||||
echo "Installer must be run as root."
|
||||
|
|
@ -15,6 +19,14 @@ if [ $(id -u) -ne 0 ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
HAS_PYTHON2=$(which python2)
|
||||
HAS_PYTHON3=$(which python3)
|
||||
if [ $HAS_PYTHON2 ] && ! [ $HAS_PYTHON3 ]; then
|
||||
"Python 2 not supported. Must use Python 3."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
clear
|
||||
|
||||
echo "This script installs software for the Adafruit"
|
||||
|
|
@ -27,10 +39,10 @@ echo "- Configure boot options"
|
|||
echo "Run time ~15 minutes. Some options require reboot."
|
||||
echo "EXISTING INSTALLATION, IF ANY, WILL BE OVERWRITTEN."
|
||||
echo
|
||||
echo -n "CONTINUE? [y/N] "
|
||||
echo -n "CONTINUE? [y/n] "
|
||||
read
|
||||
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
|
||||
echo "Canceled."
|
||||
echo "Canceled. "
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
|
@ -40,24 +52,32 @@ fi
|
|||
INTERFACE_TYPE=0
|
||||
INSTALL_RTC=0
|
||||
QUALITY_MOD=0
|
||||
#SLOWDOWN_GPIO=5
|
||||
#MATRIX_SIZE=3
|
||||
|
||||
# Given a list of strings representing options, display each option
|
||||
# preceded by a number (1 to N), display a prompt, check input until
|
||||
# a valid number within the selection range is entered.
|
||||
# Can we pass an array?
|
||||
selectN() {
|
||||
args=("${@}")
|
||||
if [[ ${args[0]} = "0" ]]; then
|
||||
OFFSET=0
|
||||
else
|
||||
OFFSET=1
|
||||
fi
|
||||
for ((i=0; i<$#; i++)); do
|
||||
echo $((i+1)). ${args[$i]}
|
||||
echo $((i+$OFFSET)). ${args[$i]}
|
||||
done
|
||||
echo
|
||||
REPLY=""
|
||||
let LAST=$#+$OFFSET-1
|
||||
while :
|
||||
do
|
||||
echo -n "SELECT 1-$#: "
|
||||
echo -n "SELECT $OFFSET-$LAST: "
|
||||
read
|
||||
if [[ $REPLY -ge 1 ]] && [[ $REPLY -le $# ]]; then
|
||||
return $REPLY
|
||||
if [[ $REPLY -ge $OFFSET ]] && [[ $REPLY -le $LAST ]]; then
|
||||
let RESULT=$REPLY-$OFFSET
|
||||
return $RESULT
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
|
@ -70,35 +90,78 @@ INTERFACES=( \
|
|||
)
|
||||
|
||||
QUALITY_OPTS=( \
|
||||
"Quality (disables sound, requires soldering)" \
|
||||
"Quality (disables sound, requires soldering on single matrix Bonnet/HAT)" \
|
||||
"Convenience (sound on, no soldering)" \
|
||||
)
|
||||
|
||||
#SLOWDOWN_OPTS=( \
|
||||
# "0" \
|
||||
# "1" \
|
||||
# "2" \
|
||||
# "3" \
|
||||
# "4" \
|
||||
# "None -- specify at runtime with --led-slowdown-gpio" \
|
||||
#)
|
||||
|
||||
# Default matrix dimensions are currently fixed at 32x32 in RGB matrix lib.
|
||||
# If that's compile-time configurable in the future, it'll happen here...
|
||||
#MATRIX_WIDTHS=(32 32 64)
|
||||
#MATRIX_HEIGHTS=(16 32 32)
|
||||
#SIZE_OPTS=( \
|
||||
# "${MATRIX_WIDTHS[0]} x ${MATRIX_HEIGHTS[0]}" \
|
||||
# "${MATRIX_WIDTHS[1]} x ${MATRIX_HEIGHTS[1]}" \
|
||||
# "${MATRIX_WIDTHS[2]} x ${MATRIX_HEIGHTS[2]}" \
|
||||
# "None/other -- specify at runtime with --led-cols and --led-rows" \
|
||||
#)
|
||||
|
||||
echo
|
||||
echo "Select interface board type:"
|
||||
selectN "${INTERFACES[@]}"
|
||||
INTERFACE_TYPE=$?
|
||||
|
||||
if [ $INTERFACE_TYPE -eq 2 ]; then
|
||||
if [ $INTERFACE_TYPE -eq 1 ]; then
|
||||
# For matrix HAT, ask about RTC install
|
||||
echo
|
||||
echo -n "Install realtime clock support? [y/N] "
|
||||
echo -n "Install realtime clock support? [y/n] "
|
||||
read
|
||||
if [[ "$REPLY" =~ (yes|y|Y)$ ]]; then
|
||||
INSTALL_RTC=1
|
||||
fi
|
||||
fi
|
||||
|
||||
#echo
|
||||
#echo "OPTIONAL: GPIO throttling can be compiled-in so"
|
||||
#echo "there's no need to specify this every time."
|
||||
#echo "For Raspberry Pi 4, it's usually 4, sometimes 3."
|
||||
#echo "Smaller values work for earlier, slower Pi models."
|
||||
#echo "If unsure, test different settings with the"
|
||||
#echo "--led-slowdown-gpio flag at runtime, then re-run"
|
||||
#echo "this installer, selecting the minimum slowdown value"
|
||||
#echo "that works reliably with your Pi and matrix."
|
||||
#echo "GPIO slowdown setting:"
|
||||
#selectN "${SLOWDOWN_OPTS[@]}"
|
||||
#SLOWDOWN_GPIO=$?
|
||||
|
||||
#echo
|
||||
#echo "OPTIONAL: matrix size can be compiled-in so"
|
||||
#echo "there's no need to specify this every time."
|
||||
#echo "Some common Adafruit matrix sizes:"
|
||||
#selectN "${SIZE_OPTS[@]}"
|
||||
#MATRIX_SIZE=$?
|
||||
|
||||
echo
|
||||
echo "Now you must choose between QUALITY and CONVENIENCE."
|
||||
echo
|
||||
echo "QUALITY: best output from the LED matrix requires"
|
||||
echo "commandeering hardware normally used for sound, plus"
|
||||
echo "some soldering. If you choose this option, there will"
|
||||
echo "some soldering on the single matrix Bonnet/HAT. If"
|
||||
echo "you choose this option, there will"
|
||||
echo "be NO sound from the audio jack or HDMI (USB audio"
|
||||
echo "adapters will work and sound best anyway), AND you"
|
||||
echo "must SOLDER a wire between GPIO4 and GPIO18 on the"
|
||||
echo "Bonnet or HAT board."
|
||||
echo "single matrix Bonnet or HAT board. For the Triple LED"
|
||||
echo "Matrix Bonnet choose QUALITY, and No soldering is"
|
||||
echo "required."
|
||||
echo
|
||||
echo "CONVENIENCE: sound works normally, no extra soldering."
|
||||
echo "Images on the LED matrix are not quite as steady, but"
|
||||
|
|
@ -113,20 +176,22 @@ QUALITY_MOD=$?
|
|||
# VERIFY SELECTIONS BEFORE CONTINUING --------------------------------------
|
||||
|
||||
echo
|
||||
echo "Interface board type: ${INTERFACES[$INTERFACE_TYPE-1]}"
|
||||
if [ $INTERFACE_TYPE -eq 2 ]; then
|
||||
echo "Interface board type: ${INTERFACES[$INTERFACE_TYPE]}"
|
||||
if [ $INTERFACE_TYPE -eq 1 ]; then
|
||||
echo "Install RTC support: ${OPTION_NAMES[$INSTALL_RTC]}"
|
||||
fi
|
||||
echo "Optimize: ${QUALITY_OPTS[$QUALITY_MOD-1]}"
|
||||
if [ $QUALITY_MOD -eq 1 ]; then
|
||||
#echo "GPIO slowdown: ${SLOWDOWN_OPTS[$SLOWDOWN_GPIO]}"
|
||||
#echo "Matrix size: ${SIZE_OPTS[$MATRIX_SIZE]}"
|
||||
echo "Optimize: ${QUALITY_OPTS[$QUALITY_MOD]}"
|
||||
if [ $QUALITY_MOD -eq 0 ]; then
|
||||
echo "Reminder: you must SOLDER a wire between GPIO4"
|
||||
echo "and GPIO18, and internal sound is DISABLED!"
|
||||
fi
|
||||
echo
|
||||
echo -n "CONTINUE? [y/N] "
|
||||
echo -n "CONTINUE? [y/n] "
|
||||
read
|
||||
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
|
||||
echo "Canceled."
|
||||
echo "Canceled. "
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
|
@ -153,7 +218,7 @@ echo "Updating package index files..."
|
|||
apt-get update
|
||||
|
||||
echo "Downloading prerequisites..."
|
||||
apt-get install -y --force-yes python2.7-dev python-pillow python3-dev python3-pillow
|
||||
apt-get install -y python3-dev python3-pillow cython3
|
||||
|
||||
echo "Downloading RGB matrix software..."
|
||||
curl -L $GITUSER/$REPO/archive/$COMMIT.zip -o $REPO-$COMMIT.zip
|
||||
|
|
@ -162,23 +227,13 @@ rm $REPO-$COMMIT.zip
|
|||
mv $REPO-$COMMIT rpi-rgb-led-matrix
|
||||
echo "Building RGB matrix software..."
|
||||
cd rpi-rgb-led-matrix
|
||||
USER_DEFINES=""
|
||||
if [ $QUALITY_MOD -eq 1 ]; then
|
||||
# Build then install for Python 2.7...
|
||||
make build-python HARDWARE_DESC=adafruit-hat-pwm
|
||||
make install-python HARDWARE_DESC=adafruit-hat-pwm
|
||||
# Do over for Python 3...
|
||||
make clean
|
||||
make build-python HARDWARE_DESC=adafruit-hat-pwm PYTHON=$(which python3)
|
||||
make install-python HARDWARE_DESC=adafruit-hat-pwm PYTHON=$(which python3)
|
||||
else
|
||||
# Build then install for Python 2.7...
|
||||
make build-python HARDWARE_DESC=adafruit-hat USER_DEFINES="-DDISABLE_HARDWARE_PULSES"
|
||||
make install-python HARDWARE_DESC=adafruit-hat USER_DEFINES="-DDISABLE_HARDWARE_PULSES"
|
||||
# Do over for Python 3...
|
||||
make clean
|
||||
make build-python HARDWARE_DESC=adafruit-hat USER_DEFINES="-DDISABLE_HARDWARE_PULSES" PYTHON=$(which python3)
|
||||
make install-python HARDWARE_DESC=adafruit-hat USER_DEFINES="-DDISABLE_HARDWARE_PULSES" PYTHON=$(which python3)
|
||||
USER_DEFINES+=" -DDISABLE_HARDWARE_PULSES"
|
||||
fi
|
||||
make clean
|
||||
make build-python USER_DEFINES="$USER_DEFINES"
|
||||
|
||||
# Change ownership to user calling sudo
|
||||
chown -R $SUDO_USER:$(id -g $SUDO_USER) `pwd`
|
||||
|
||||
|
|
@ -191,19 +246,18 @@ if [ $INSTALL_RTC -ne 0 ]; then
|
|||
# Enable I2C for RTC
|
||||
raspi-config nonint do_i2c 0
|
||||
# Do additional RTC setup for DS1307
|
||||
reconfig /boot/config.txt "^.*dtoverlay=i2c-rtc.*$" "dtoverlay=i2c-rtc,ds1307"
|
||||
reconfig /boot/firmware/config.txt "^.*dtoverlay=i2c-rtc.*$" "dtoverlay=i2c-rtc,ds1307"
|
||||
apt-get -y remove fake-hwclock
|
||||
update-rc.d -f fake-hwclock remove
|
||||
sudo sed --in-place '/if \[ -e \/run\/systemd\/system \] ; then/,+2 s/^#*/#/' /lib/udev/hwclock-set
|
||||
|
||||
sed --in-place '/if \[ -e \/run\/systemd\/system \] ; then/,+2 s/^#*/#/' /lib/udev/hwclock-set
|
||||
fi
|
||||
|
||||
if [ $QUALITY_MOD -eq 1 ]; then
|
||||
# Disable sound ('easy way' -- kernel module not blacklisted)
|
||||
reconfig /boot/config.txt "^.*dtparam=audio.*$" "dtparam=audio=off"
|
||||
if [ $QUALITY_MOD -eq 0 ]; then
|
||||
# Disable sound via blacklist
|
||||
echo "blacklist snd_bcm2835" > /etc/modprobe.d/blacklist-rgb-matrix.conf
|
||||
else
|
||||
# Enable sound (ditto)
|
||||
reconfig /boot/config.txt "^.*dtparam=audio.*$" "dtparam=audio=on"
|
||||
# Remove from blacklist
|
||||
rm -f /etc/modprobe.d/blacklist-rgb-matrix.conf
|
||||
fi
|
||||
|
||||
# PROMPT FOR REBOOT --------------------------------------------------------
|
||||
|
|
@ -214,14 +268,15 @@ echo "Settings take effect on next boot."
|
|||
if [ $INSTALL_RTC -ne 0 ]; then
|
||||
echo "RTC will be enabled then but time must be set"
|
||||
echo "up using the 'date' and 'hwclock' commands."
|
||||
echo "ref: https://learn.adafruit.com/adding-a-real-time-clock-to-raspberry-pi/set-rtc-time#sync-time-from-pi-to-rtc"
|
||||
fi
|
||||
echo
|
||||
echo -n "REBOOT NOW? [y/N] "
|
||||
echo -n "REBOOT NOW? [y/n] "
|
||||
read
|
||||
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
|
||||
echo "Exiting without reboot."
|
||||
exit 0
|
||||
fi
|
||||
echo "Reboot started..."
|
||||
echo "Reboot process started..."
|
||||
reboot
|
||||
exit 0
|
||||
sleep infinity
|
||||
|
|
|
|||
|
|
@ -1,220 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# INSTALLER SCRIPT FOR ADAFRUIT RGB MATRIX BONNET OR HAT
|
||||
|
||||
# hzeller/rpi-rgb-led-matrix sees lots of active development!
|
||||
# That's cool and all, BUT, to avoid tutorial breakage,
|
||||
# we reference a specific commit (update this as needed):
|
||||
GITUSER=https://github.com/hzeller
|
||||
REPO=rpi-rgb-led-matrix
|
||||
COMMIT=58830f7bb5dfb47fc24f1fd26cd7c4e3a20f13f7
|
||||
|
||||
if [ $(id -u) -ne 0 ]; then
|
||||
echo "Installer must be run as root."
|
||||
echo "Try 'sudo bash $0'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
clear
|
||||
|
||||
echo "This script installs software for the Adafruit"
|
||||
echo "RGB Matrix Bonnet or HAT for Raspberry Pi."
|
||||
echo "Steps include:"
|
||||
echo "- Update package index files (apt-get update)"
|
||||
echo "- Install prerequisite software"
|
||||
echo "- Install RGB matrix driver software"
|
||||
echo "- Configure boot options"
|
||||
echo "Run time ~10 minutes. Some options require reboot."
|
||||
echo "EXISTING INSTALLATION, IF ANY, WILL BE OVERWRITTEN."
|
||||
echo
|
||||
echo -n "CONTINUE? [y/N] "
|
||||
read
|
||||
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
|
||||
echo "Canceled."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# FEATURE PROMPTS ----------------------------------------------------------
|
||||
# Installation doesn't begin until after all user input is taken.
|
||||
|
||||
INTERFACE_TYPE=0
|
||||
INSTALL_RTC=0
|
||||
QUALITY_MOD=0
|
||||
|
||||
# Given a list of strings representing options, display each option
|
||||
# preceded by a number (1 to N), display a prompt, check input until
|
||||
# a valid number within the selection range is entered.
|
||||
# Can we pass an array?
|
||||
selectN() {
|
||||
args=("${@}")
|
||||
for ((i=0; i<$#; i++)); do
|
||||
echo $((i+1)). ${args[$i]}
|
||||
done
|
||||
echo
|
||||
REPLY=""
|
||||
while :
|
||||
do
|
||||
echo -n "SELECT 1-$#: "
|
||||
read
|
||||
if [[ $REPLY -ge 1 ]] && [[ $REPLY -le $# ]]; then
|
||||
return $REPLY
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
OPTION_NAMES=(NO YES)
|
||||
|
||||
INTERFACES=( \
|
||||
"Adafruit RGB Matrix Bonnet" \
|
||||
"Adafruit RGB Matrix HAT + RTC" \
|
||||
)
|
||||
|
||||
QUALITY_OPTS=( \
|
||||
"Quality (disables sound, requires soldering)" \
|
||||
"Convenience (sound on, no soldering)" \
|
||||
)
|
||||
|
||||
echo
|
||||
echo "Select interface board type:"
|
||||
selectN "${INTERFACES[@]}"
|
||||
INTERFACE_TYPE=$?
|
||||
|
||||
if [ $INTERFACE_TYPE -eq 2 ]; then
|
||||
# For matrix HAT, ask about RTC install
|
||||
echo
|
||||
echo -n "Install realtime clock support? [y/N] "
|
||||
read
|
||||
if [[ "$REPLY" =~ (yes|y|Y)$ ]]; then
|
||||
INSTALL_RTC=1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Now you must choose between QUALITY and CONVENIENCE."
|
||||
echo
|
||||
echo "QUALITY: best output from the LED matrix requires"
|
||||
echo "commandeering hardware normally used for sound, plus"
|
||||
echo "some soldering. If you choose this option, there will"
|
||||
echo "be NO sound from the audio jack or HDMI (USB audio"
|
||||
echo "adapters will work and sound best anyway), AND you"
|
||||
echo "must SOLDER a wire between GPIO4 and GPIO18 on the"
|
||||
echo "Bonnet or HAT board."
|
||||
echo
|
||||
echo "CONVENIENCE: sound works normally, no extra soldering."
|
||||
echo "Images on the LED matrix are not quite as steady, but"
|
||||
echo "maybe OK for most uses. If eager to get started, use"
|
||||
echo "'CONVENIENCE' for now, you can make the change and"
|
||||
echo "reinstall using this script later!"
|
||||
echo
|
||||
echo "What is thy bidding?"
|
||||
selectN "${QUALITY_OPTS[@]}"
|
||||
QUALITY_MOD=$?
|
||||
|
||||
# VERIFY SELECTIONS BEFORE CONTINUING --------------------------------------
|
||||
|
||||
echo
|
||||
echo "Interface board type: ${INTERFACES[$INTERFACE_TYPE-1]}"
|
||||
if [ $INTERFACE_TYPE -eq 2 ]; then
|
||||
echo "Install RTC support: ${OPTION_NAMES[$INSTALL_RTC]}"
|
||||
fi
|
||||
echo "Optimize: ${QUALITY_OPTS[$QUALITY_MOD-1]}"
|
||||
if [ $QUALITY_MOD -eq 1 ]; then
|
||||
echo "Reminder: you must SOLDER a wire between GPIO4"
|
||||
echo "and GPIO18, and internal sound is DISABLED!"
|
||||
fi
|
||||
echo
|
||||
echo -n "CONTINUE? [y/N] "
|
||||
read
|
||||
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
|
||||
echo "Canceled."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# START INSTALL ------------------------------------------------------------
|
||||
# All selections are validated at this point...
|
||||
|
||||
# Given a filename, a regex pattern to match and a replacement string,
|
||||
# perform replacement if found, else append replacement to end of file.
|
||||
# (# $1 = filename, $2 = pattern to match, $3 = replacement)
|
||||
reconfig() {
|
||||
grep $2 $1 >/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
# Pattern found; replace in file
|
||||
sed -i "s/$2/$3/g" $1 >/dev/null
|
||||
else
|
||||
# Not found; append (silently)
|
||||
echo $3 | sudo tee -a $1 >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
echo
|
||||
echo "Starting installation..."
|
||||
echo "Updating package index files..."
|
||||
apt-get update
|
||||
|
||||
echo "Downloading prerequisites..."
|
||||
apt-get install -y --force-yes python-dev python-imaging
|
||||
|
||||
echo "Downloading RGB matrix software..."
|
||||
curl -L $GITUSER/$REPO/archive/$COMMIT.zip -o $REPO-$COMMIT.zip
|
||||
unzip -q $REPO-$COMMIT.zip
|
||||
rm $REPO-$COMMIT.zip
|
||||
mv $REPO-$COMMIT rpi-rgb-led-matrix
|
||||
echo "Building RGB matrix software..."
|
||||
cd rpi-rgb-led-matrix
|
||||
if [ $QUALITY_MOD -eq 1 ]; then
|
||||
HARDWARE_DESC=adafruit-hat-pwm make
|
||||
cd bindings/python
|
||||
python setup.py install
|
||||
else
|
||||
HARDWARE_DESC=adafruit-hat make USER_DEFINES="-DDISABLE_HARDWARE_PULSES"
|
||||
cd bindings/python
|
||||
python setup.py install
|
||||
fi
|
||||
# Change ownership to user calling sudo
|
||||
cd ../../..
|
||||
chown -R $SUDO_USER:$(id -g $SUDO_USER) rpi-rgb-led-matrix
|
||||
|
||||
|
||||
# CONFIG -------------------------------------------------------------------
|
||||
|
||||
echo "Configuring system..."
|
||||
|
||||
if [ $INSTALL_RTC -ne 0 ]; then
|
||||
# Enable I2C for RTC
|
||||
raspi-config nonint do_i2c 0
|
||||
# Do additional RTC setup for DS1307
|
||||
reconfig /boot/config.txt "^.*dtoverlay=i2c-rtc.*$" "dtoverlay=i2c-rtc,ds1307"
|
||||
apt-get -y remove fake-hwclock
|
||||
update-rc.d -f fake-hwclock remove
|
||||
sudo sed --in-place '/if \[ -e \/run\/systemd\/system \] ; then/,+2 s/^#*/#/' /lib/udev/hwclock-set
|
||||
|
||||
fi
|
||||
|
||||
if [ $QUALITY_MOD -eq 1 ]; then
|
||||
# Disable sound ('easy way' -- kernel module not blacklisted)
|
||||
reconfig /boot/config.txt "^.*dtparam=audio.*$" "dtparam=audio=off"
|
||||
else
|
||||
# Enable sound (ditto)
|
||||
reconfig /boot/config.txt "^.*dtparam=audio.*$" "dtparam=audio=on"
|
||||
fi
|
||||
|
||||
# PROMPT FOR REBOOT --------------------------------------------------------
|
||||
|
||||
echo "Done."
|
||||
echo
|
||||
echo "Settings take effect on next boot."
|
||||
if [ $INSTALL_RTC -ne 0 ]; then
|
||||
echo "RTC will be enabled then but time must be set"
|
||||
echo "up using the 'date' and 'hwclock' commands."
|
||||
fi
|
||||
echo
|
||||
echo -n "REBOOT NOW? [y/N] "
|
||||
read
|
||||
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
|
||||
echo "Exiting without reboot."
|
||||
exit 0
|
||||
fi
|
||||
echo "Reboot started..."
|
||||
reboot
|
||||
exit 0
|
||||
60
rpi_pin_kernel_firmware.py
Normal file
60
rpi_pin_kernel_firmware.py
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
"""
|
||||
Adafruit Raspberry Pi Script to Pin a specific version of the rpi kernel and firmware
|
||||
(C) Adafruit Industries, Creative Commons 3.0 - Attribution Share Alike
|
||||
|
||||
Converted to Python by Melissa LeBlanc-Williams for Adafruit Industries
|
||||
"""
|
||||
|
||||
try:
|
||||
from adafruit_shell import Shell
|
||||
except ImportError:
|
||||
raise RuntimeError("The library 'adafruit_shell' was not found. To install, try typing: sudo pip3 install adafruit-python-shell")
|
||||
|
||||
shell = Shell()
|
||||
shell.group = 'PINNING'
|
||||
|
||||
def main():
|
||||
shell.clear()
|
||||
# Check Raspberry Pi and Bail
|
||||
pi_model = shell.get_board_model()
|
||||
print("{} detected.\n".format(pi_model))
|
||||
if not shell.is_raspberry_pi():
|
||||
shell.bail("Non-Raspberry Pi board detected. This must be run on a Raspberry Pi")
|
||||
if shell.get_os() != "Raspbian":
|
||||
print("OS Detected:" + shell.get_os())
|
||||
shell.bail("Sorry. This script currently only runs on Raspberry Pi OS.")
|
||||
if len(shell.args) == 1:
|
||||
print("Usage: sudo python3 {} kernel-version\n".format(shell.script()))
|
||||
print("e.g., {} 1.20201126-1".format(shell.script()))
|
||||
shell.exit(1)
|
||||
version = shell.args[1]
|
||||
base = "http://archive.raspberrypi.org/debian/pool/main/r/raspberrypi-firmware/"
|
||||
packagelist = [
|
||||
"libraspberrypi0",
|
||||
"libraspberrypi-bin",
|
||||
"libraspberrypi-dev",
|
||||
"libraspberrypi-doc",
|
||||
"raspberrypi-bootloader",
|
||||
"raspberrypi-kernel",
|
||||
"raspberrypi-kernel-headers"
|
||||
]
|
||||
new_packages = []
|
||||
for package in packagelist:
|
||||
filename = f"{package}_{version}_armhf.deb"
|
||||
new_packages.append(filename)
|
||||
shell.run_command("wget --continue -O {} {}".format(filename, base + filename))
|
||||
|
||||
shell.run_command("dpkg -i " + " ".join(new_packages))
|
||||
|
||||
for package in packagelist:
|
||||
shell.write_text_file("/etc/apt/preferences.d/99-adafruit-pin-kernel", (
|
||||
f"Package: {package}\n"
|
||||
f"Pin: version {version}\n"
|
||||
f"Pin-Priority:999\n\n"
|
||||
))
|
||||
shell.prompt_reboot()
|
||||
|
||||
# Main function
|
||||
if __name__ == "__main__":
|
||||
shell.require_root()
|
||||
main()
|
||||
163
rtc.py
Executable file
163
rtc.py
Executable file
|
|
@ -0,0 +1,163 @@
|
|||
"""
|
||||
Adafruit Raspberry Pi Real Time Clock Setup Script
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
This script is licensed under the terms of the MIT license.
|
||||
Unless otherwise noted, code reproduced herein
|
||||
was written for this script.
|
||||
|
||||
Originally written by the - The Pimoroni Crew -
|
||||
|
||||
Converted to Python by Melissa LeBlanc-Williams for Adafruit Industries
|
||||
|
||||
|
||||
Note: Currently Untested
|
||||
"""
|
||||
|
||||
try:
|
||||
from adafruit_shell import Shell
|
||||
except ImportError:
|
||||
raise RuntimeError("The library 'adafruit_shell' was not found. To install, try typing: sudo pip3 install adafruit-python-shell")
|
||||
|
||||
shell = Shell()
|
||||
|
||||
productname = "Real Time Clock module" # the name of the product to install
|
||||
rtcsubtype = "ds1307"
|
||||
baseurl = "http://www.adafru.it"
|
||||
scriptname = "rtc.py" # the name of this script
|
||||
|
||||
spacereq = 1 # minimum size required on root partition in MB
|
||||
debugmode = False # whether the script should use debug routines
|
||||
debuguser = None # optional test git user to use in debug mode
|
||||
debugpoint = None # optional git repo branch or tag to checkout
|
||||
forcesudo = True # whether the script requires to be ran with root privileges
|
||||
promptreboot = False # whether the script should always prompt user to reboot
|
||||
customcmd = True # whether to execute commands specified before exit
|
||||
i2creq = True # whether the i2c interface is required
|
||||
i2sreq = False # whether the i2s interface is required
|
||||
spireq = False # whether the spi interface is required
|
||||
uartreq = False # whether uart communication is required
|
||||
armhfonly = True # whether the script is allowed to run on other arch
|
||||
armv6 = True # whether armv6 processors are supported
|
||||
armv7 = True # whether armv7 processors are supported
|
||||
armv8 = True # whether armv8 processors are supported
|
||||
raspbianonly = True # whether the script is allowed to run on other OSes
|
||||
macosxsupport = False # whether Mac OS X is supported by the script
|
||||
osreleases = ( "Raspbian" ) # list os-releases supported
|
||||
oswarning = ( "Debian", "Ubuntu", "Mate" ) # list experimental os-releases
|
||||
squeezesupport = False # whether Squeeze is supported
|
||||
wheezysupport = False # whether Wheezy is supported
|
||||
jessiesupport = True # whether Jessie is supported
|
||||
|
||||
DEVICE_TREE = True
|
||||
ASK_TO_REBOOT = False
|
||||
CURRENT_SETTING = False
|
||||
UPDATED_DB = False
|
||||
|
||||
BOOTCMD = "/boot/cmdline.txt"
|
||||
CONFIG = shell.get_boot_config()
|
||||
APTSRC = "/etc/apt/sources.list"
|
||||
INITABCONF = "/etc/inittab"
|
||||
BLACKLIST = "/etc/modprobe.d/raspi-blacklist.conf"
|
||||
LOADMOD = "/etc/modules"
|
||||
DTBODIR = "/boot/overlays"
|
||||
|
||||
def raspbian_old():
|
||||
return shell.get_raspbian_version() in ("wheezy", "squeeze")
|
||||
|
||||
def dt_check():
|
||||
# Check if /boot/firmware/config.txt exists and de
|
||||
return shell.exists(CONFIG) and not shell.pattern_search(CONFIG, "^device_tree=$")
|
||||
|
||||
#Perform all global variables declarations as well as function definition
|
||||
#above this section for clarity, thanks!
|
||||
|
||||
def main():
|
||||
os_release = shell.get_raspbian_version()
|
||||
IS_SUPPORTED = os_release in osreleases
|
||||
IS_EXPERIMENTAL = os_release in oswarning
|
||||
|
||||
if not shell.is_armhf() or shell.is_arm64():
|
||||
shell.bail("This hardware is not supported, sorry!\n"
|
||||
"Config files have been left untouched")
|
||||
|
||||
if shell.is_raspberry_pi_os():
|
||||
if not wheezysupport and raspbian_old():
|
||||
shell.bail(
|
||||
"\n--- Warning ---\n"
|
||||
f"The {productname} installer\n"
|
||||
"does not work on this version of Raspbian.\n"
|
||||
r"Check https://github.com/{gitusername}/{gitreponame}"
|
||||
"\nfor additional information and support")
|
||||
elif raspbianonly:
|
||||
shell.bail("This script is intended for Raspbian on a Raspberry Pi!")
|
||||
else:
|
||||
if not IS_SUPPORTED and not IS_EXPERIMENTAL:
|
||||
shell.bail(
|
||||
"Your operating system is not supported, sorry!\n"
|
||||
"Config files have been left untouched")
|
||||
|
||||
if forcesudo:
|
||||
shell.require_root()
|
||||
|
||||
print(f"\nThis script will install everything needed to use {productname}\n")
|
||||
shell.warn(
|
||||
"--- Warning ---\n"
|
||||
"Always be careful when running scripts and commands\n"
|
||||
"copied from the internet. Ensure they are from a\n"
|
||||
"trusted source.\n"
|
||||
"\n"
|
||||
"If you want to see what this script does before\n"
|
||||
"running it, you should run:\n"
|
||||
" \curl -sS $baseurl/$scriptname\n"
|
||||
"\n"
|
||||
)
|
||||
|
||||
if shell.prompt("Do you wish to continue?", force_arg="y", default="n"):
|
||||
print("\nChecking hardware requirements...")
|
||||
|
||||
if i2creq == "yes":
|
||||
print()
|
||||
if shell.prompt("Hardware requires I2C, enable now?", force_arg="y", default="n"):
|
||||
shell.run_command("sudo raspi-config nonint do_i2c 0")
|
||||
|
||||
if not dt_check():
|
||||
shell.bail(
|
||||
"Device Tree support required!\n"
|
||||
"Config files have been left untouched\n"
|
||||
)
|
||||
|
||||
rtc_values = ("ds1307", "ds3231", "pcf8523")
|
||||
rtcsubtype = rtc_values[shell.select_n("What RTC would you like to install?", rtc_values) - 1]
|
||||
|
||||
print("Disabling any current RTC")
|
||||
shell.run_command(f"sudo sed --in-place '/dtoverlay[[:space:]]*=[[:space:]]*i2c-rtc/d' {CONFIG}")
|
||||
|
||||
print(f"Adding DT overlay for {rtcsubtype}")
|
||||
shell.write_text_file(CONFIG, f"dtoverlay=i2c-rtc,{rtcsubtype}", append=True)
|
||||
|
||||
print("Removing fake-hwclock")
|
||||
shell.run_command("sudo apt-get -y remove fake-hwclock")
|
||||
shell.run_command("sudo update-rc.d -f fake-hwclock remove")
|
||||
|
||||
if not shell.exists("/lib/udev/hwclock-set"):
|
||||
shell.bail("Couldn't find /lib/udev/hwclock-set")
|
||||
|
||||
shell.warn("Configuring HW Clock")
|
||||
shell.run_command("sudo sed --in-place '/if \[ -e \/run\/systemd\/system \] ; then/,+2 s/^#*/#/' /lib/udev/hwclock-set")
|
||||
shell.prompt_reboot()
|
||||
|
||||
else:
|
||||
shell.warn("\nAborting...")
|
||||
|
||||
# Main function
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
273
spectro.sh
Normal file
273
spectro.sh
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
#!/bin/bash
|
||||
|
||||
# INSTALLER SCRIPT FOR ADAFRUIT SPECTRO PROJECT
|
||||
|
||||
if [ $(id -u) -ne 0 ]; then
|
||||
echo "Installer must be run as root."
|
||||
echo "Try 'sudo bash $0'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
clear
|
||||
|
||||
echo "This script installs software for the Adafruit"
|
||||
echo "Spectro project for Raspberry Pi."
|
||||
echo "Steps include:"
|
||||
echo "- Update package index files (apt-get update)"
|
||||
echo "- Install prerequisite software"
|
||||
echo "- Install Spectro software"
|
||||
echo "- Configure hardware and boot options"
|
||||
echo "Run time ~10 minutes."
|
||||
echo
|
||||
echo "EXISTING INSTALLATION, IF ANY, WILL BE OVERWRITTEN."
|
||||
echo "If you've edited any Spectro-related files, cancel"
|
||||
echo "the installation and back up those files first."
|
||||
echo
|
||||
echo -n "CONTINUE? [y/N] "
|
||||
read
|
||||
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
|
||||
echo "Canceled."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# FEATURE PROMPTS ----------------------------------------------------------
|
||||
# Installation doesn't begin until after all user input is taken.
|
||||
|
||||
MATRIX_SIZE=0
|
||||
SLOWDOWN_GPIO=0
|
||||
ENABLE_MIC=0
|
||||
ENABLE_ACCEL=0
|
||||
HDMI_SIZE=0
|
||||
|
||||
OPTION_NAMES=(NO YES)
|
||||
MATRIX_WIDTHS=(64 32)
|
||||
MATRIX_HEIGHTS=(32 16)
|
||||
SIZE_OPTS=( \
|
||||
"${MATRIX_WIDTHS[0]} x ${MATRIX_HEIGHTS[0]}" \
|
||||
"${MATRIX_WIDTHS[1]} x ${MATRIX_HEIGHTS[1]}" \
|
||||
)
|
||||
SLOWDOWN_OPTS=( \
|
||||
"0" \
|
||||
"1" \
|
||||
"2" \
|
||||
"3" \
|
||||
"4" \
|
||||
)
|
||||
HDMI_OPTS=( \
|
||||
"640x480" \
|
||||
"320x240" \
|
||||
)
|
||||
|
||||
# Given a list of strings representing options, display each option
|
||||
# preceded by a number (1 to N), display a prompt, check input until
|
||||
# a valid number within the selection range is entered.
|
||||
selectN() {
|
||||
args=("${@}")
|
||||
# If first item in list is the literal number '0', make the list
|
||||
# indexed from 0 rather than 1. This is to avoid confusion when
|
||||
# entering the GPIO slowdown setting (e.g. entering '1' for a
|
||||
# value of '0' is awkward). In all other cases, list is indexed
|
||||
# from 1 as this is more human.
|
||||
if [[ ${args[0]} = "0" ]]; then
|
||||
OFFSET=0
|
||||
else
|
||||
OFFSET=1
|
||||
fi
|
||||
for ((i=0; i<$#; i++)); do
|
||||
echo $((i+$OFFSET)). ${args[$i]}
|
||||
done
|
||||
echo
|
||||
REPLY=""
|
||||
let LAST=$#+$OFFSET-1
|
||||
while :
|
||||
do
|
||||
echo -n "SELECT $OFFSET-$LAST: "
|
||||
read
|
||||
if [[ $REPLY -ge $OFFSET ]] && [[ $REPLY -le $LAST ]]; then
|
||||
let RESULT=$REPLY-$OFFSET
|
||||
return $RESULT
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
echo
|
||||
echo "What size LED matrix are you using with Spectro?"
|
||||
selectN "${SIZE_OPTS[@]}"
|
||||
MATRIX_SIZE=$?
|
||||
|
||||
echo
|
||||
echo "Faster Pi boards require dialing back GPIO speed"
|
||||
echo "to work with the LED matrix. For Raspberry Pi 4,"
|
||||
echo "this usually means the max '4' slowdown setting."
|
||||
echo "For Pi 2 or 3, try the '1' or '2' settings. There"
|
||||
echo "is no hard-set rule to this, it can vary with"
|
||||
echo "matrix and cabling as well. If the Spectro display"
|
||||
echo "is glitchy, just re-run this installer, selecting"
|
||||
echo "a higher setting until you find a stable value."
|
||||
echo "GPIO slowdown setting:"
|
||||
selectN "${SLOWDOWN_OPTS[@]}"
|
||||
SLOWDOWN_GPIO=$?
|
||||
|
||||
echo
|
||||
echo -n "OPTIONAL: Enable USB microphone support? [y/N] "
|
||||
read
|
||||
if [[ "$REPLY" =~ (yes|y|Y)$ ]]; then
|
||||
ENABLE_MIC=1
|
||||
fi
|
||||
|
||||
echo
|
||||
echo -n "OPTIONAL: Enable LIS3DH accelerometer support? [y/N] "
|
||||
read
|
||||
if [[ "$REPLY" =~ (yes|y|Y)$ ]]; then
|
||||
ENABLE_ACCEL=1
|
||||
fi
|
||||
|
||||
# HDMI resolution selection might be handled later; right now nothing
|
||||
# requires it. But in the future if anything relies on fb2matrix.py,
|
||||
# HDMI resolution ultimately determines the frame rate that's possible,
|
||||
# flipside being that some monitors can't handle extremely low resolutions.
|
||||
# So an option might be presented here, set to 320x240 or 640x480 (the
|
||||
# latter being the minimum resolution some displays can support).
|
||||
|
||||
# VERIFY SELECTIONS BEFORE CONTINUING --------------------------------------
|
||||
|
||||
echo
|
||||
echo "LED matrix size: ${SIZE_OPTS[$MATRIX_SIZE]}"
|
||||
echo "GPIO slowdown: ${SLOWDOWN_OPTS[$SLOWDOWN_GPIO]}"
|
||||
echo "Enable USB microphone support: ${OPTION_NAMES[$ENABLE_MIC]}"
|
||||
echo "Enable LIS3DH support: ${OPTION_NAMES[$ENABLE_ACCEL]}"
|
||||
#echo "HDMI resolution: ${HDMI_OPTS[$HDMI_SIZE]}"
|
||||
echo
|
||||
echo -n "CONTINUE? [y/N] "
|
||||
read
|
||||
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
|
||||
echo "Canceled."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check whether RGB matrix library is present.
|
||||
# If not, offer to download and run that script first (then return here).
|
||||
echo
|
||||
echo "Updating package index files..."
|
||||
apt-get update
|
||||
apt-get -qq install python3-pip python-pip
|
||||
echo -n "Checking for RGB matrix library..."
|
||||
pip3 freeze | grep rgbmatrix > /dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "OK."
|
||||
else
|
||||
echo "not present."
|
||||
echo "Would you like to download and install the RGB matrix"
|
||||
echo "library (required by Spectro) first? If so, DO NOT REBOOT"
|
||||
echo "when prompted. You’ll return to this script for more"
|
||||
echo "Spectro configuration."
|
||||
echo -n "Run RGB matrix installer? [y/N] "
|
||||
read
|
||||
if [[ "$REPLY" =~ (yes|y|Y)$ ]]; then
|
||||
wget https://raw.githubusercontent.com/adafruit/Raspberry-Pi-Installer-Scripts/master/rgb-matrix.sh -O rgb-matrix.sh
|
||||
bash rgb-matrix.sh
|
||||
echo
|
||||
echo "You are now back in the main Spectro installer script."
|
||||
echo "When prompted about reboot again, now it's OK!"
|
||||
fi
|
||||
fi
|
||||
|
||||
# START INSTALL ------------------------------------------------------------
|
||||
# All selections are validated at this point...
|
||||
|
||||
# Given a filename, a regex pattern to match and a replacement string,
|
||||
# perform replacement if found, else append replacement to end of file.
|
||||
# (# $1 = filename, $2 = pattern to match, $3 = replacement)
|
||||
reconfig() {
|
||||
grep $2 $1 >/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
# Pattern found; replace in file
|
||||
sed -i "s/$2/$3/g" $1 >/dev/null
|
||||
else
|
||||
# Not found; append (silently)
|
||||
echo $3 | sudo tee -a $1 >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
# Same as above, but skips if pattern not found
|
||||
reconfig2() {
|
||||
grep $2 $1 >/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
# Pattern found; replace in file
|
||||
sed -i "s/$2/$3/g" $1 >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
echo
|
||||
echo "Starting installation..."
|
||||
|
||||
# Although Spectro is all Python3-ready, user additions might rely on
|
||||
# Python2, so we'll install the prerequisite libraries for both 2 and 3...
|
||||
echo "Downloading prerequisites..."
|
||||
pip3 install psutil RPi.GPIO
|
||||
pip install psutil RPi.GPIO
|
||||
apt-get install -y --allow-unauthenticated python3-dev python3-pillow python2.7-dev python-pillow
|
||||
if [ $ENABLE_MIC -ne 0 ]; then
|
||||
apt-get install -y --allow-unauthenticated python3-pyaudio python3-numpy python-pyaudio python-numpy
|
||||
fi
|
||||
if [ $ENABLE_ACCEL -ne 0 ]; then
|
||||
pip3 install adafruit-circuitpython-busdevice adafruit-circuitpython-lis3dh
|
||||
pip install adafruit-circuitpython-busdevice adafruit-circuitpython-lis3dh
|
||||
fi
|
||||
|
||||
echo "Downloading Spectro software..."
|
||||
curl -L https://github.com/adafruit/Adafruit_Spectro_Pi/archive/master.zip -o Adafruit_Spectro_Pi.zip
|
||||
unzip -q -o Adafruit_Spectro_Pi.zip
|
||||
rm Adafruit_Spectro_Pi.zip
|
||||
mv Adafruit_Spectro_Pi-master Adafruit_Spectro_Pi
|
||||
chown -R pi:pi Adafruit_Spectro_Pi
|
||||
|
||||
# CONFIG -------------------------------------------------------------------
|
||||
|
||||
echo "Configuring system..."
|
||||
|
||||
if [ $ENABLE_MIC -ne 0 ]; then
|
||||
# Change ALSA settings to allow USB mic use
|
||||
reconfig2 /usr/share/alsa/alsa.conf "^defaults.ctl.card.*0" "defaults.ctl.card 1"
|
||||
reconfig2 /usr/share/alsa/alsa.conf "^defaults.pcm.card.*0" "defaults.pcm.card 1"
|
||||
fi
|
||||
|
||||
if [ $ENABLE_ACCEL -ne 0 ]; then
|
||||
# Enable I2C for accelerometer
|
||||
raspi-config nonint do_i2c 0
|
||||
fi
|
||||
|
||||
# Make default GIFs directory
|
||||
mkdir /boot/gifs
|
||||
|
||||
# Set up LED columns, rows and slowdown in selector.py script
|
||||
reconfig2 ./Adafruit_Spectro_Pi/selector.py "^FLAGS.*$" "FLAGS\ =\ [\"--led-cols=${MATRIX_WIDTHS[$MATRIX_SIZE]}\",\ \"--led-rows=${MATRIX_HEIGHTS[$MATRIX_SIZE]}\",\ \"--led-slowdown-gpio=${SLOWDOWN_OPTS[$SLOWDOWN_GPIO]}\"]"
|
||||
|
||||
# Force HDMI out so /dev/fb0 exists
|
||||
reconfig /boot/config.txt "^.*hdmi_force_hotplug.*$" "hdmi_force_hotplug=1"
|
||||
#reconfig /boot/config.txt "^.*hdmi_group.*$" "hdmi_group=2"
|
||||
#reconfig /boot/config.txt "^.*hdmi_mode.*$" "hdmi_mode=87"
|
||||
|
||||
# Auto-start selector.py on boot
|
||||
grep selector.py /etc/rc.local >/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
# Insert selector.py into rc.local before final 'exit 0'
|
||||
sed -i "s/^exit 0/cd \/home\/pi\/Adafruit_Spectro_Pi\;python3 selector.py \&\\nexit 0/g" /etc/rc.local >/dev/null
|
||||
fi
|
||||
|
||||
# PROMPT FOR REBOOT --------------------------------------------------------
|
||||
|
||||
echo "Done."
|
||||
echo
|
||||
echo "Settings take effect on next boot."
|
||||
echo "For proper clock time, set the time zone with raspi-config."
|
||||
echo
|
||||
echo -n "REBOOT NOW? [y/N] "
|
||||
read
|
||||
if [[ ! "$REPLY" =~ ^(yes|y|Y)$ ]]; then
|
||||
echo "Exiting without reboot."
|
||||
exit 0
|
||||
fi
|
||||
echo "Reboot started..."
|
||||
reboot
|
||||
sleep infinity
|
||||
|
|
@ -1,14 +1,13 @@
|
|||
obj-m+=st7789v_ada.o
|
||||
obj-m += fb_st7789v.o
|
||||
|
||||
KDIR ?= /lib/modules/`uname -r`/build
|
||||
|
||||
default:
|
||||
$(MAKE) -C $(KDIR) M=$(pwd) modules
|
||||
$(MAKE) -C $(KDIR) M=$(shell pwd) modules
|
||||
|
||||
install:
|
||||
$(MAKE) -C $(KDIR) M=$(PWD) modules_install
|
||||
$(MAKE) -C $(KDIR) M=$(shell pwd) modules_install
|
||||
$(DEPMOD)
|
||||
|
||||
clean:
|
||||
$(MAKE) -C $(KDIR) M=$(PWD) clean
|
||||
|
||||
$(MAKE) -C $(KDIR) M=$(shell pwd) clean
|
||||
|
|
|
|||
448
st7789_module/fb_st7789v.c
Normal file
448
st7789_module/fb_st7789v.c
Normal file
|
|
@ -0,0 +1,448 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* FB driver for the ST7789V LCD Controller
|
||||
*
|
||||
* Copyright (C) 2015 Dennis Menschel
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#include "fbtft.h"
|
||||
|
||||
#define DRVNAME "fb_st7789v"
|
||||
|
||||
#define DEFAULT_GAMMA \
|
||||
"70 2C 2E 15 10 09 48 33 53 0B 19 18 20 25\n" \
|
||||
"70 2C 2E 15 10 09 48 33 53 0B 19 18 20 25"
|
||||
|
||||
#define HSD20_IPS_GAMMA \
|
||||
"D0 05 0A 09 08 05 2E 44 45 0F 17 16 2B 33\n" \
|
||||
"D0 05 0A 09 08 05 2E 43 45 0F 16 16 2B 33"
|
||||
|
||||
#define HSD20_IPS 1
|
||||
|
||||
/**
|
||||
* enum st7789v_command - ST7789V display controller commands
|
||||
*
|
||||
* @PORCTRL: porch setting
|
||||
* @GCTRL: gate control
|
||||
* @VCOMS: VCOM setting
|
||||
* @VDVVRHEN: VDV and VRH command enable
|
||||
* @VRHS: VRH set
|
||||
* @VDVS: VDV set
|
||||
* @VCMOFSET: VCOM offset set
|
||||
* @PWCTRL1: power control 1
|
||||
* @PVGAMCTRL: positive voltage gamma control
|
||||
* @NVGAMCTRL: negative voltage gamma control
|
||||
*
|
||||
* The command names are the same as those found in the datasheet to ease
|
||||
* looking up their semantics and usage.
|
||||
*
|
||||
* Note that the ST7789V display controller offers quite a few more commands
|
||||
* which have been omitted from this list as they are not used at the moment.
|
||||
* Furthermore, commands that are compliant with the MIPI DCS have been left
|
||||
* out as well to avoid duplicate entries.
|
||||
*/
|
||||
enum st7789v_command {
|
||||
PORCTRL = 0xB2,
|
||||
GCTRL = 0xB7,
|
||||
VCOMS = 0xBB,
|
||||
VDVVRHEN = 0xC2,
|
||||
VRHS = 0xC3,
|
||||
VDVS = 0xC4,
|
||||
VCMOFSET = 0xC5,
|
||||
PWCTRL1 = 0xD0,
|
||||
PVGAMCTRL = 0xE0,
|
||||
NVGAMCTRL = 0xE1,
|
||||
};
|
||||
|
||||
#define MADCTL_BGR BIT(3) /* bitmask for RGB/BGR order */
|
||||
#define MADCTL_MV BIT(5) /* bitmask for page/column order */
|
||||
#define MADCTL_MX BIT(6) /* bitmask for column address order */
|
||||
#define MADCTL_MY BIT(7) /* bitmask for page address order */
|
||||
|
||||
/* 60Hz for 16.6ms, configured as 2*16.6ms */
|
||||
#define PANEL_TE_TIMEOUT_MS 33
|
||||
|
||||
static struct completion panel_te; /* completion for panel TE line */
|
||||
static int irq_te; /* Linux IRQ for LCD TE line */
|
||||
static u32 col_start_offset = 0;
|
||||
static u32 col_end_offset = 0;
|
||||
static u32 row_start_offset = 0;
|
||||
static u32 row_end_offset = 0;
|
||||
static short x_offset = 0;
|
||||
static short y_offset = 0;
|
||||
|
||||
static irqreturn_t panel_te_handler(int irq, void *data)
|
||||
{
|
||||
complete(&panel_te);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* init_tearing_effect_line() - init tearing effect line.
|
||||
* @par: FBTFT parameter object.
|
||||
*
|
||||
* Return: 0 on success, or a negative error code otherwise.
|
||||
*/
|
||||
static int init_tearing_effect_line(struct fbtft_par *par)
|
||||
{
|
||||
struct device *dev = par->info->device;
|
||||
struct gpio_desc *te;
|
||||
int rc, irq;
|
||||
|
||||
te = gpiod_get_optional(dev, "te", GPIOD_IN);
|
||||
if (IS_ERR(te))
|
||||
return dev_err_probe(dev, PTR_ERR(te), "Failed to request te GPIO\n");
|
||||
|
||||
/* if te is NULL, indicating no configuration, directly return success */
|
||||
if (!te) {
|
||||
irq_te = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
irq = gpiod_to_irq(te);
|
||||
|
||||
/* GPIO is locked as an IRQ, we may drop the reference */
|
||||
gpiod_put(te);
|
||||
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
irq_te = irq;
|
||||
init_completion(&panel_te);
|
||||
|
||||
/* The effective state is high and lasts no more than 1000 microseconds */
|
||||
rc = devm_request_irq(dev, irq_te, panel_te_handler,
|
||||
IRQF_TRIGGER_RISING, "TE_GPIO", par);
|
||||
if (rc)
|
||||
return dev_err_probe(dev, rc, "TE IRQ request failed.\n");
|
||||
|
||||
disable_irq_nosync(irq_te);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* init_display() - initialize the display controller
|
||||
*
|
||||
* @par: FBTFT parameter object
|
||||
*
|
||||
* Most of the commands in this init function set their parameters to the
|
||||
* same default values which are already in place after the display has been
|
||||
* powered up. (The main exception to this rule is the pixel format which
|
||||
* would default to 18 instead of 16 bit per pixel.)
|
||||
* Nonetheless, this sequence can be used as a template for concrete
|
||||
* displays which usually need some adjustments.
|
||||
*
|
||||
* Return: 0 on success, < 0 if error occurred.
|
||||
*/
|
||||
static int init_display(struct fbtft_par *par)
|
||||
{
|
||||
int rc;
|
||||
|
||||
par->fbtftops.reset(par);
|
||||
|
||||
rc = init_tearing_effect_line(par);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* turn off sleep mode */
|
||||
write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE);
|
||||
mdelay(120);
|
||||
|
||||
/* set pixel format to RGB-565 */
|
||||
write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT);
|
||||
if (HSD20_IPS)
|
||||
write_reg(par, PORCTRL, 0x05, 0x05, 0x00, 0x33, 0x33);
|
||||
|
||||
else
|
||||
write_reg(par, PORCTRL, 0x08, 0x08, 0x00, 0x22, 0x22);
|
||||
|
||||
/*
|
||||
* VGH = 13.26V
|
||||
* VGL = -10.43V
|
||||
*/
|
||||
if (HSD20_IPS)
|
||||
write_reg(par, GCTRL, 0x75);
|
||||
else
|
||||
write_reg(par, GCTRL, 0x35);
|
||||
|
||||
/*
|
||||
* VDV and VRH register values come from command write
|
||||
* (instead of NVM)
|
||||
*/
|
||||
write_reg(par, VDVVRHEN, 0x01, 0xFF);
|
||||
|
||||
/*
|
||||
* VAP = 4.1V + (VCOM + VCOM offset + 0.5 * VDV)
|
||||
* VAN = -4.1V + (VCOM + VCOM offset + 0.5 * VDV)
|
||||
*/
|
||||
if (HSD20_IPS)
|
||||
write_reg(par, VRHS, 0x13);
|
||||
else
|
||||
write_reg(par, VRHS, 0x0B);
|
||||
|
||||
/* VDV = 0V */
|
||||
write_reg(par, VDVS, 0x20);
|
||||
|
||||
/* VCOM = 0.9V */
|
||||
if (HSD20_IPS)
|
||||
write_reg(par, VCOMS, 0x22);
|
||||
else
|
||||
write_reg(par, VCOMS, 0x20);
|
||||
|
||||
/* VCOM offset = 0V */
|
||||
write_reg(par, VCMOFSET, 0x20);
|
||||
|
||||
/*
|
||||
* AVDD = 6.8V
|
||||
* AVCL = -4.8V
|
||||
* VDS = 2.3V
|
||||
*/
|
||||
write_reg(par, PWCTRL1, 0xA4, 0xA1);
|
||||
|
||||
/* TE line output is off by default when powering on */
|
||||
if (irq_te)
|
||||
write_reg(par, MIPI_DCS_SET_TEAR_ON, 0x00);
|
||||
|
||||
write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
|
||||
|
||||
if (HSD20_IPS)
|
||||
write_reg(par, MIPI_DCS_ENTER_INVERT_MODE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* write_vmem() - write data to display.
|
||||
* @par: FBTFT parameter object.
|
||||
* @offset: offset from screen_buffer.
|
||||
* @len: the length of data to be writte.
|
||||
*
|
||||
* Return: 0 on success, or a negative error code otherwise.
|
||||
*/
|
||||
static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
|
||||
{
|
||||
struct device *dev = par->info->device;
|
||||
int ret;
|
||||
|
||||
if (irq_te) {
|
||||
enable_irq(irq_te);
|
||||
reinit_completion(&panel_te);
|
||||
ret = wait_for_completion_timeout(&panel_te,
|
||||
msecs_to_jiffies(PANEL_TE_TIMEOUT_MS));
|
||||
if (ret == 0)
|
||||
dev_err(dev, "wait panel TE timeout\n");
|
||||
|
||||
disable_irq(irq_te);
|
||||
}
|
||||
|
||||
switch (par->pdata->display.buswidth) {
|
||||
case 8:
|
||||
ret = fbtft_write_vmem16_bus8(par, offset, len);
|
||||
break;
|
||||
case 9:
|
||||
ret = fbtft_write_vmem16_bus9(par, offset, len);
|
||||
break;
|
||||
case 16:
|
||||
ret = fbtft_write_vmem16_bus16(par, offset, len);
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "Unsupported buswidth %d\n",
|
||||
par->pdata->display.buswidth);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void minipitft13_set_addr_win(struct fbtft_par *par, int xs, int ys,
|
||||
int xe, int ye)
|
||||
{
|
||||
xs += x_offset;
|
||||
xe += x_offset;
|
||||
ys += y_offset;
|
||||
ye += y_offset;
|
||||
write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS,
|
||||
xs >> 8, xs & 0xFF, xe >> 8, xe & 0xFF);
|
||||
|
||||
write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS,
|
||||
ys >> 8, ys & 0xFF, ye >> 8, ye & 0xFF);
|
||||
|
||||
write_reg(par, MIPI_DCS_WRITE_MEMORY_START);
|
||||
}
|
||||
|
||||
/**
|
||||
* set_var() - apply LCD properties like rotation and BGR mode
|
||||
*
|
||||
* @par: FBTFT parameter object
|
||||
*
|
||||
* Return: 0 on success, < 0 if error occurred.
|
||||
*/
|
||||
static int set_var(struct fbtft_par *par)
|
||||
{
|
||||
u8 madctl_par = 0;
|
||||
struct fbtft_display *display = &par->pdata->display;
|
||||
u32 width = display->width;
|
||||
u32 height = display->height;
|
||||
if (par->bgr)
|
||||
madctl_par |= MADCTL_BGR;
|
||||
|
||||
if (width < 240) {
|
||||
// Smaller displays are centered
|
||||
row_start_offset = row_end_offset = (int)((320 - height + 1) / 2);
|
||||
col_start_offset = (int)((240 - width) / 2);
|
||||
col_end_offset = (int)((240 - width + 1) / 2); // Account for extra pixel
|
||||
} else {
|
||||
// Larger displays are left-aligned
|
||||
row_start_offset = 0;
|
||||
row_end_offset = (320 - height);
|
||||
col_start_offset = col_end_offset = 0;
|
||||
}
|
||||
|
||||
switch (par->info->var.rotate) {
|
||||
case 0:
|
||||
x_offset = col_start_offset;
|
||||
y_offset = row_start_offset;
|
||||
break;
|
||||
case 90:
|
||||
madctl_par |= (MADCTL_MV | MADCTL_MY);
|
||||
x_offset = row_start_offset;
|
||||
y_offset = col_start_offset;
|
||||
break;
|
||||
case 180:
|
||||
madctl_par |= (MADCTL_MX | MADCTL_MY);
|
||||
x_offset = col_end_offset;
|
||||
y_offset = row_end_offset;
|
||||
break;
|
||||
case 270:
|
||||
madctl_par |= (MADCTL_MV | MADCTL_MX);
|
||||
x_offset = row_end_offset;
|
||||
y_offset = col_end_offset;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, madctl_par);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_gamma() - set gamma curves
|
||||
*
|
||||
* @par: FBTFT parameter object
|
||||
* @curves: gamma curves
|
||||
*
|
||||
* Before the gamma curves are applied, they are preprocessed with a bitmask
|
||||
* to ensure syntactically correct input for the display controller.
|
||||
* This implies that the curves input parameter might be changed by this
|
||||
* function and that illegal gamma values are auto-corrected and not
|
||||
* reported as errors.
|
||||
*
|
||||
* Return: 0 on success, < 0 if error occurred.
|
||||
*/
|
||||
static int set_gamma(struct fbtft_par *par, u32 *curves)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int c; /* curve index offset */
|
||||
|
||||
/*
|
||||
* Bitmasks for gamma curve command parameters.
|
||||
* The masks are the same for both positive and negative voltage
|
||||
* gamma curves.
|
||||
*/
|
||||
static const u8 gamma_par_mask[] = {
|
||||
0xFF, /* V63[3:0], V0[3:0]*/
|
||||
0x3F, /* V1[5:0] */
|
||||
0x3F, /* V2[5:0] */
|
||||
0x1F, /* V4[4:0] */
|
||||
0x1F, /* V6[4:0] */
|
||||
0x3F, /* J0[1:0], V13[3:0] */
|
||||
0x7F, /* V20[6:0] */
|
||||
0x77, /* V36[2:0], V27[2:0] */
|
||||
0x7F, /* V43[6:0] */
|
||||
0x3F, /* J1[1:0], V50[3:0] */
|
||||
0x1F, /* V57[4:0] */
|
||||
0x1F, /* V59[4:0] */
|
||||
0x3F, /* V61[5:0] */
|
||||
0x3F, /* V62[5:0] */
|
||||
};
|
||||
|
||||
for (i = 0; i < par->gamma.num_curves; i++) {
|
||||
c = i * par->gamma.num_values;
|
||||
for (j = 0; j < par->gamma.num_values; j++)
|
||||
curves[c + j] &= gamma_par_mask[j];
|
||||
write_reg(par, PVGAMCTRL + i,
|
||||
curves[c + 0], curves[c + 1], curves[c + 2],
|
||||
curves[c + 3], curves[c + 4], curves[c + 5],
|
||||
curves[c + 6], curves[c + 7], curves[c + 8],
|
||||
curves[c + 9], curves[c + 10], curves[c + 11],
|
||||
curves[c + 12], curves[c + 13]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* blank() - blank the display
|
||||
*
|
||||
* @par: FBTFT parameter object
|
||||
* @on: whether to enable or disable blanking the display
|
||||
*
|
||||
* Return: 0 on success, < 0 if error occurred.
|
||||
*/
|
||||
static int blank(struct fbtft_par *par, bool on)
|
||||
{
|
||||
if (on)
|
||||
write_reg(par, MIPI_DCS_SET_DISPLAY_OFF);
|
||||
else
|
||||
write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct fbtft_display display = {
|
||||
.regwidth = 8,
|
||||
.width = 240,
|
||||
.height = 320,
|
||||
.gamma_num = 2,
|
||||
.gamma_len = 14,
|
||||
.gamma = HSD20_IPS_GAMMA,
|
||||
.fbtftops = {
|
||||
.init_display = init_display,
|
||||
.write_vmem = write_vmem,
|
||||
.set_var = set_var,
|
||||
.set_gamma = set_gamma,
|
||||
.blank = blank,
|
||||
},
|
||||
};
|
||||
|
||||
int variant_minipitft13(struct fbtft_display *display)
|
||||
{
|
||||
display->fbtftops.set_addr_win = minipitft13_set_addr_win;
|
||||
return 0;
|
||||
}
|
||||
|
||||
FBTFT_REGISTER_DRIVER_START(&display)
|
||||
FBTFT_COMPATIBLE("sitronix,st7789v")
|
||||
FBTFT_VARIANT_COMPATIBLE("fbtft,minipitft13", variant_minipitft13)
|
||||
FBTFT_REGISTER_DRIVER_END(DRVNAME, &display);
|
||||
|
||||
MODULE_ALIAS("spi:" DRVNAME);
|
||||
MODULE_ALIAS("platform:" DRVNAME);
|
||||
MODULE_ALIAS("spi:st7789v");
|
||||
MODULE_ALIAS("platform:st7789v");
|
||||
|
||||
MODULE_DESCRIPTION("FB driver for the ST7789V LCD Controller");
|
||||
MODULE_AUTHOR("Dennis Menschel");
|
||||
MODULE_LICENSE("GPL");
|
||||
480
st7789_module/fbtft.h
Normal file
480
st7789_module/fbtft.h
Normal file
|
|
@ -0,0 +1,480 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/* Copyright (C) 2013 Noralf Tronnes */
|
||||
|
||||
#ifndef __LINUX_FBTFT_H
|
||||
#define __LINUX_FBTFT_H
|
||||
|
||||
#include <linux/fb.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#define FBTFT_ONBOARD_BACKLIGHT 2
|
||||
|
||||
#define FBTFT_GPIO_NO_MATCH 0xFFFF
|
||||
#define FBTFT_GPIO_NAME_SIZE 32
|
||||
#define FBTFT_MAX_INIT_SEQUENCE 512
|
||||
#define FBTFT_GAMMA_MAX_VALUES_TOTAL 128
|
||||
|
||||
#define FBTFT_OF_INIT_CMD BIT(24)
|
||||
#define FBTFT_OF_INIT_DELAY BIT(25)
|
||||
|
||||
/**
|
||||
* struct fbtft_gpio - Structure that holds one pinname to gpio mapping
|
||||
* @name: pinname (reset, dc, etc.)
|
||||
* @gpio: GPIO number
|
||||
*
|
||||
*/
|
||||
struct fbtft_gpio {
|
||||
char name[FBTFT_GPIO_NAME_SIZE];
|
||||
struct gpio_desc *gpio;
|
||||
};
|
||||
|
||||
struct fbtft_par;
|
||||
|
||||
/**
|
||||
* struct fbtft_ops - FBTFT operations structure
|
||||
* @write: Writes to interface bus
|
||||
* @read: Reads from interface bus
|
||||
* @write_vmem: Writes video memory to display
|
||||
* @write_reg: Writes to controller register
|
||||
* @set_addr_win: Set the GRAM update window
|
||||
* @reset: Reset the LCD controller
|
||||
* @mkdirty: Marks display lines for update
|
||||
* @update_display: Updates the display
|
||||
* @init_display: Initializes the display
|
||||
* @blank: Blank the display (optional)
|
||||
* @request_gpios_match: Do pinname to gpio matching
|
||||
* @request_gpios: Request gpios from the kernel
|
||||
* @free_gpios: Free previously requested gpios
|
||||
* @verify_gpios: Verify that necessary gpios is present (optional)
|
||||
* @register_backlight: Used to register backlight device (optional)
|
||||
* @unregister_backlight: Unregister backlight device (optional)
|
||||
* @set_var: Configure LCD with values from variables like @rotate and @bgr
|
||||
* (optional)
|
||||
* @set_gamma: Set Gamma curve (optional)
|
||||
*
|
||||
* Most of these operations have default functions assigned to them in
|
||||
* fbtft_framebuffer_alloc()
|
||||
*/
|
||||
struct fbtft_ops {
|
||||
int (*write)(struct fbtft_par *par, void *buf, size_t len);
|
||||
int (*read)(struct fbtft_par *par, void *buf, size_t len);
|
||||
int (*write_vmem)(struct fbtft_par *par, size_t offset, size_t len);
|
||||
void (*write_register)(struct fbtft_par *par, int len, ...);
|
||||
|
||||
void (*set_addr_win)(struct fbtft_par *par,
|
||||
int xs, int ys, int xe, int ye);
|
||||
void (*reset)(struct fbtft_par *par);
|
||||
void (*mkdirty)(struct fb_info *info, int from, int to);
|
||||
void (*update_display)(struct fbtft_par *par,
|
||||
unsigned int start_line, unsigned int end_line);
|
||||
int (*init_display)(struct fbtft_par *par);
|
||||
int (*blank)(struct fbtft_par *par, bool on);
|
||||
|
||||
unsigned long (*request_gpios_match)(struct fbtft_par *par,
|
||||
const struct fbtft_gpio *gpio);
|
||||
int (*request_gpios)(struct fbtft_par *par);
|
||||
int (*verify_gpios)(struct fbtft_par *par);
|
||||
|
||||
void (*register_backlight)(struct fbtft_par *par);
|
||||
void (*unregister_backlight)(struct fbtft_par *par);
|
||||
|
||||
int (*set_var)(struct fbtft_par *par);
|
||||
int (*set_gamma)(struct fbtft_par *par, u32 *curves);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct fbtft_display - Describes the display properties
|
||||
* @width: Width of display in pixels
|
||||
* @height: Height of display in pixels
|
||||
* @regwidth: LCD Controller Register width in bits
|
||||
* @buswidth: Display interface bus width in bits
|
||||
* @backlight: Backlight type.
|
||||
* @fbtftops: FBTFT operations provided by driver or device (platform_data)
|
||||
* @bpp: Bits per pixel
|
||||
* @fps: Frames per second
|
||||
* @txbuflen: Size of transmit buffer
|
||||
* @init_sequence: Pointer to LCD initialization array
|
||||
* @gamma: String representation of Gamma curve(s)
|
||||
* @gamma_num: Number of Gamma curves
|
||||
* @gamma_len: Number of values per Gamma curve
|
||||
* @debug: Initial debug value
|
||||
*
|
||||
* This structure is not stored by FBTFT except for init_sequence.
|
||||
*/
|
||||
struct fbtft_display {
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int regwidth;
|
||||
unsigned int buswidth;
|
||||
unsigned int backlight;
|
||||
struct fbtft_ops fbtftops;
|
||||
unsigned int bpp;
|
||||
unsigned int fps;
|
||||
int txbuflen;
|
||||
const s16 *init_sequence;
|
||||
char *gamma;
|
||||
int gamma_num;
|
||||
int gamma_len;
|
||||
unsigned long debug;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct fbtft_platform_data - Passes display specific data to the driver
|
||||
* @display: Display properties
|
||||
* @gpios: Pointer to an array of pinname to gpio mappings
|
||||
* @rotate: Display rotation angle
|
||||
* @bgr: LCD Controller BGR bit
|
||||
* @fps: Frames per second (this will go away, use @fps in @fbtft_display)
|
||||
* @txbuflen: Size of transmit buffer
|
||||
* @startbyte: When set, enables use of Startbyte in transfers
|
||||
* @gamma: String representation of Gamma curve(s)
|
||||
* @extra: A way to pass extra info
|
||||
*/
|
||||
struct fbtft_platform_data {
|
||||
struct fbtft_display display;
|
||||
unsigned int rotate;
|
||||
bool bgr;
|
||||
unsigned int fps;
|
||||
int txbuflen;
|
||||
u8 startbyte;
|
||||
char *gamma;
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct fbtft_par - Main FBTFT data structure
|
||||
*
|
||||
* This structure holds all relevant data to operate the display
|
||||
*
|
||||
* See sourcefile for documentation since nested structs is not
|
||||
* supported by kernel-doc.
|
||||
*
|
||||
*/
|
||||
/* @spi: Set if it is a SPI device
|
||||
* @pdev: Set if it is a platform device
|
||||
* @info: Pointer to framebuffer fb_info structure
|
||||
* @pdata: Pointer to platform data
|
||||
* @ssbuf: Not used
|
||||
* @pseudo_palette: Used by fb_set_colreg()
|
||||
* @txbuf.buf: Transmit buffer
|
||||
* @txbuf.len: Transmit buffer length
|
||||
* @buf: Small buffer used when writing init data over SPI
|
||||
* @startbyte: Used by some controllers when in SPI mode.
|
||||
* Format: 6 bit Device id + RS bit + RW bit
|
||||
* @fbtftops: FBTFT operations provided by driver or device (platform_data)
|
||||
* @dirty_lock: Protects dirty_lines_start and dirty_lines_end
|
||||
* @dirty_lines_start: Where to begin updating display
|
||||
* @dirty_lines_end: Where to end updating display
|
||||
* @gpio.reset: GPIO used to reset display
|
||||
* @gpio.dc: Data/Command signal, also known as RS
|
||||
* @gpio.rd: Read latching signal
|
||||
* @gpio.wr: Write latching signal
|
||||
* @gpio.latch: Bus latch signal, eg. 16->8 bit bus latch
|
||||
* @gpio.cs: LCD Chip Select with parallel interface bus
|
||||
* @gpio.db[16]: Parallel databus
|
||||
* @gpio.led[16]: Led control signals
|
||||
* @gpio.aux[16]: Auxiliary signals, not used by core
|
||||
* @init_sequence: Pointer to LCD initialization array
|
||||
* @gamma.lock: Mutex for Gamma curve locking
|
||||
* @gamma.curves: Pointer to Gamma curve array
|
||||
* @gamma.num_values: Number of values per Gamma curve
|
||||
* @gamma.num_curves: Number of Gamma curves
|
||||
* @debug: Pointer to debug value
|
||||
* @current_debug:
|
||||
* @first_update_done: Used to only time the first display update
|
||||
* @update_time: Used to calculate 'fps' in debug output
|
||||
* @bgr: BGR mode/\n
|
||||
* @extra: Extra info needed by driver
|
||||
*/
|
||||
struct fbtft_par {
|
||||
struct spi_device *spi;
|
||||
struct platform_device *pdev;
|
||||
struct fb_info *info;
|
||||
struct fbtft_platform_data *pdata;
|
||||
u16 *ssbuf;
|
||||
u32 pseudo_palette[16];
|
||||
struct {
|
||||
void *buf;
|
||||
size_t len;
|
||||
} txbuf;
|
||||
u8 *buf;
|
||||
u8 startbyte;
|
||||
struct fbtft_ops fbtftops;
|
||||
spinlock_t dirty_lock;
|
||||
unsigned int dirty_lines_start;
|
||||
unsigned int dirty_lines_end;
|
||||
struct {
|
||||
struct gpio_desc *reset;
|
||||
struct gpio_desc *dc;
|
||||
struct gpio_desc *rd;
|
||||
struct gpio_desc *wr;
|
||||
struct gpio_desc *latch;
|
||||
struct gpio_desc *cs;
|
||||
struct gpio_desc *db[16];
|
||||
struct gpio_desc *led[16];
|
||||
struct gpio_desc *aux[16];
|
||||
} gpio;
|
||||
const s16 *init_sequence;
|
||||
struct {
|
||||
struct mutex lock;
|
||||
u32 *curves;
|
||||
int num_values;
|
||||
int num_curves;
|
||||
} gamma;
|
||||
unsigned long debug;
|
||||
bool first_update_done;
|
||||
ktime_t update_time;
|
||||
bool bgr;
|
||||
void *extra;
|
||||
bool polarity;
|
||||
};
|
||||
|
||||
#define NUMARGS(...) (sizeof((int[]){__VA_ARGS__}) / sizeof(int))
|
||||
|
||||
#define write_reg(par, ...) \
|
||||
((par)->fbtftops.write_register(par, NUMARGS(__VA_ARGS__), __VA_ARGS__))
|
||||
|
||||
/* fbtft-core.c */
|
||||
int fbtft_write_buf_dc(struct fbtft_par *par, void *buf, size_t len, int dc);
|
||||
__printf(5, 6)
|
||||
void fbtft_dbg_hex(const struct device *dev, int groupsize,
|
||||
const void *buf, size_t len, const char *fmt, ...);
|
||||
struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
|
||||
struct device *dev,
|
||||
struct fbtft_platform_data *pdata);
|
||||
void fbtft_framebuffer_release(struct fb_info *info);
|
||||
int fbtft_register_framebuffer(struct fb_info *fb_info);
|
||||
int fbtft_unregister_framebuffer(struct fb_info *fb_info);
|
||||
void fbtft_register_backlight(struct fbtft_par *par);
|
||||
void fbtft_unregister_backlight(struct fbtft_par *par);
|
||||
int fbtft_init_display(struct fbtft_par *par);
|
||||
int fbtft_probe_common(struct fbtft_display *display, struct spi_device *sdev,
|
||||
struct platform_device *pdev,
|
||||
const struct of_device_id *dt_ids);
|
||||
void fbtft_remove_common(struct device *dev, struct fb_info *info);
|
||||
|
||||
/* fbtft-io.c */
|
||||
int fbtft_write_spi(struct fbtft_par *par, void *buf, size_t len);
|
||||
int fbtft_write_spi_emulate_9(struct fbtft_par *par, void *buf, size_t len);
|
||||
int fbtft_read_spi(struct fbtft_par *par, void *buf, size_t len);
|
||||
int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len);
|
||||
int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len);
|
||||
int fbtft_write_gpio16_wr_latched(struct fbtft_par *par, void *buf, size_t len);
|
||||
|
||||
/* fbtft-bus.c */
|
||||
int fbtft_write_vmem8_bus8(struct fbtft_par *par, size_t offset, size_t len);
|
||||
int fbtft_write_vmem16_bus16(struct fbtft_par *par, size_t offset, size_t len);
|
||||
int fbtft_write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len);
|
||||
int fbtft_write_vmem16_bus9(struct fbtft_par *par, size_t offset, size_t len);
|
||||
void fbtft_write_reg8_bus8(struct fbtft_par *par, int len, ...);
|
||||
void fbtft_write_reg8_bus9(struct fbtft_par *par, int len, ...);
|
||||
void fbtft_write_reg16_bus8(struct fbtft_par *par, int len, ...);
|
||||
void fbtft_write_reg16_bus16(struct fbtft_par *par, int len, ...);
|
||||
|
||||
#define FBTFT_REGISTER_DRIVER_START(_display) \
|
||||
\
|
||||
static const struct of_device_id dt_ids[]; \
|
||||
\
|
||||
static int fbtft_driver_probe_spi(struct spi_device *spi) \
|
||||
{ \
|
||||
return fbtft_probe_common(_display, spi, NULL, dt_ids); \
|
||||
} \
|
||||
\
|
||||
static void fbtft_driver_remove_spi(struct spi_device *spi) \
|
||||
{ \
|
||||
struct fb_info *info = spi_get_drvdata(spi); \
|
||||
\
|
||||
fbtft_remove_common(&spi->dev, info); \
|
||||
} \
|
||||
\
|
||||
static int fbtft_driver_probe_pdev(struct platform_device *pdev) \
|
||||
{ \
|
||||
return fbtft_probe_common(_display, NULL, pdev, dt_ids); \
|
||||
} \
|
||||
\
|
||||
static int fbtft_driver_remove_pdev(struct platform_device *pdev) \
|
||||
{ \
|
||||
struct fb_info *info = platform_get_drvdata(pdev); \
|
||||
\
|
||||
fbtft_remove_common(&pdev->dev, info); \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
static const struct of_device_id dt_ids[] = {
|
||||
|
||||
#define FBTFT_COMPATIBLE(_compatible) \
|
||||
{ .compatible = _compatible },
|
||||
|
||||
#define FBTFT_VARIANT_COMPATIBLE(_compatible, _variant) \
|
||||
{ .compatible = _compatible, .data = _variant },
|
||||
|
||||
#define FBTFT_REGISTER_DRIVER_END(_name, _display) \
|
||||
\
|
||||
{}, \
|
||||
}; \
|
||||
\
|
||||
MODULE_DEVICE_TABLE(of, dt_ids); \
|
||||
\
|
||||
\
|
||||
static struct spi_driver fbtft_driver_spi_driver = { \
|
||||
.driver = { \
|
||||
.name = _name, \
|
||||
.of_match_table = dt_ids, \
|
||||
}, \
|
||||
.probe = fbtft_driver_probe_spi, \
|
||||
.remove = fbtft_driver_remove_spi, \
|
||||
}; \
|
||||
\
|
||||
static struct platform_driver fbtft_driver_platform_driver = { \
|
||||
.driver = { \
|
||||
.name = _name, \
|
||||
.owner = THIS_MODULE, \
|
||||
.of_match_table = dt_ids, \
|
||||
}, \
|
||||
.probe = fbtft_driver_probe_pdev, \
|
||||
.remove = fbtft_driver_remove_pdev, \
|
||||
}; \
|
||||
\
|
||||
static int __init fbtft_driver_module_init(void) \
|
||||
{ \
|
||||
int ret; \
|
||||
\
|
||||
ret = spi_register_driver(&fbtft_driver_spi_driver); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
ret = platform_driver_register(&fbtft_driver_platform_driver); \
|
||||
if (ret < 0) \
|
||||
spi_unregister_driver(&fbtft_driver_spi_driver); \
|
||||
return ret; \
|
||||
} \
|
||||
\
|
||||
static void __exit fbtft_driver_module_exit(void) \
|
||||
{ \
|
||||
spi_unregister_driver(&fbtft_driver_spi_driver); \
|
||||
platform_driver_unregister(&fbtft_driver_platform_driver); \
|
||||
} \
|
||||
\
|
||||
module_init(fbtft_driver_module_init); \
|
||||
module_exit(fbtft_driver_module_exit);
|
||||
|
||||
#define FBTFT_REGISTER_SPI_DRIVER(_name, _comp_vend, _comp_dev, _display) \
|
||||
\
|
||||
static const struct of_device_id dt_ids[] = { \
|
||||
{ .compatible = _comp_vend "," _comp_dev }, \
|
||||
{}, \
|
||||
}; \
|
||||
\
|
||||
static int fbtft_driver_probe_spi(struct spi_device *spi) \
|
||||
{ \
|
||||
return fbtft_probe_common(_display, spi, NULL, dt_ids); \
|
||||
} \
|
||||
\
|
||||
static void fbtft_driver_remove_spi(struct spi_device *spi) \
|
||||
{ \
|
||||
struct fb_info *info = spi_get_drvdata(spi); \
|
||||
\
|
||||
fbtft_remove_common(&spi->dev, info); \
|
||||
} \
|
||||
\
|
||||
MODULE_DEVICE_TABLE(of, dt_ids); \
|
||||
\
|
||||
static const struct spi_device_id spi_ids[] = { \
|
||||
{ .name = _comp_dev }, \
|
||||
{}, \
|
||||
}; \
|
||||
\
|
||||
MODULE_DEVICE_TABLE(spi, spi_ids); \
|
||||
\
|
||||
static struct spi_driver fbtft_driver_spi_driver = { \
|
||||
.driver = { \
|
||||
.name = _name, \
|
||||
.of_match_table = dt_ids, \
|
||||
}, \
|
||||
.id_table = spi_ids, \
|
||||
.probe = fbtft_driver_probe_spi, \
|
||||
.remove = fbtft_driver_remove_spi, \
|
||||
}; \
|
||||
\
|
||||
module_spi_driver(fbtft_driver_spi_driver);
|
||||
|
||||
#define FBTFT_REGISTER_DRIVER(_name, _compatible, _display) \
|
||||
FBTFT_REGISTER_DRIVER_START(_display) \
|
||||
FBTFT_COMPATIBLE(_compatible) \
|
||||
FBTFT_REGISTER_DRIVER_END(_name, _display)
|
||||
|
||||
/* Debug macros */
|
||||
|
||||
/* shorthand debug levels */
|
||||
#define DEBUG_LEVEL_1 DEBUG_REQUEST_GPIOS
|
||||
#define DEBUG_LEVEL_2 (DEBUG_LEVEL_1 | DEBUG_DRIVER_INIT_FUNCTIONS \
|
||||
| DEBUG_TIME_FIRST_UPDATE)
|
||||
#define DEBUG_LEVEL_3 (DEBUG_LEVEL_2 | DEBUG_RESET | DEBUG_INIT_DISPLAY \
|
||||
| DEBUG_BLANK | DEBUG_REQUEST_GPIOS \
|
||||
| DEBUG_FREE_GPIOS \
|
||||
| DEBUG_VERIFY_GPIOS \
|
||||
| DEBUG_BACKLIGHT | DEBUG_SYSFS)
|
||||
#define DEBUG_LEVEL_4 (DEBUG_LEVEL_2 | DEBUG_FB_READ | DEBUG_FB_WRITE \
|
||||
| DEBUG_FB_FILLRECT \
|
||||
| DEBUG_FB_COPYAREA \
|
||||
| DEBUG_FB_IMAGEBLIT | DEBUG_FB_BLANK)
|
||||
#define DEBUG_LEVEL_5 (DEBUG_LEVEL_3 | DEBUG_UPDATE_DISPLAY)
|
||||
#define DEBUG_LEVEL_6 (DEBUG_LEVEL_4 | DEBUG_LEVEL_5)
|
||||
#define DEBUG_LEVEL_7 0xFFFFFFFF
|
||||
|
||||
#define DEBUG_DRIVER_INIT_FUNCTIONS BIT(3)
|
||||
#define DEBUG_TIME_FIRST_UPDATE BIT(4)
|
||||
#define DEBUG_TIME_EACH_UPDATE BIT(5)
|
||||
#define DEBUG_DEFERRED_IO BIT(6)
|
||||
#define DEBUG_FBTFT_INIT_FUNCTIONS BIT(7)
|
||||
|
||||
/* fbops */
|
||||
#define DEBUG_FB_READ BIT(8)
|
||||
#define DEBUG_FB_WRITE BIT(9)
|
||||
#define DEBUG_FB_FILLRECT BIT(10)
|
||||
#define DEBUG_FB_COPYAREA BIT(11)
|
||||
#define DEBUG_FB_IMAGEBLIT BIT(12)
|
||||
#define DEBUG_FB_SETCOLREG BIT(13)
|
||||
#define DEBUG_FB_BLANK BIT(14)
|
||||
|
||||
#define DEBUG_SYSFS BIT(16)
|
||||
|
||||
/* fbtftops */
|
||||
#define DEBUG_BACKLIGHT BIT(17)
|
||||
#define DEBUG_READ BIT(18)
|
||||
#define DEBUG_WRITE BIT(19)
|
||||
#define DEBUG_WRITE_VMEM BIT(20)
|
||||
#define DEBUG_WRITE_REGISTER BIT(21)
|
||||
#define DEBUG_SET_ADDR_WIN BIT(22)
|
||||
#define DEBUG_RESET BIT(23)
|
||||
#define DEBUG_MKDIRTY BIT(24)
|
||||
#define DEBUG_UPDATE_DISPLAY BIT(25)
|
||||
#define DEBUG_INIT_DISPLAY BIT(26)
|
||||
#define DEBUG_BLANK BIT(27)
|
||||
#define DEBUG_REQUEST_GPIOS BIT(28)
|
||||
#define DEBUG_FREE_GPIOS BIT(29)
|
||||
#define DEBUG_REQUEST_GPIOS_MATCH BIT(30)
|
||||
#define DEBUG_VERIFY_GPIOS BIT(31)
|
||||
|
||||
#define fbtft_init_dbg(dev, format, arg...) \
|
||||
do { \
|
||||
if (unlikely((dev)->platform_data && \
|
||||
(((struct fbtft_platform_data *)(dev)->platform_data)->display.debug & DEBUG_DRIVER_INIT_FUNCTIONS))) \
|
||||
dev_info(dev, format, ##arg); \
|
||||
} while (0)
|
||||
|
||||
#define fbtft_par_dbg(level, par, format, arg...) \
|
||||
do { \
|
||||
if (unlikely((par)->debug & (level))) \
|
||||
dev_info((par)->info->device, format, ##arg); \
|
||||
} while (0)
|
||||
|
||||
#define fbtft_par_dbg_hex(level, par, dev, type, buf, num, format, arg...) \
|
||||
do { \
|
||||
if (unlikely((par)->debug & (level))) \
|
||||
fbtft_dbg_hex(dev, sizeof(type), buf,\
|
||||
(num) * sizeof(type), format, ##arg); \
|
||||
} while (0)
|
||||
|
||||
#endif /* __LINUX_FBTFT_H */
|
||||
14
st7789_module/reload.sh
Normal file
14
st7789_module/reload.sh
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Unload
|
||||
sudo dtoverlay -r drm-minipitft114
|
||||
sudo modprobe -r fb_st7789v
|
||||
sudo modprobe -r fbtft
|
||||
|
||||
# Compile
|
||||
sudo make
|
||||
|
||||
# Load again
|
||||
sudo modprobe fbtft
|
||||
sudo insmod ./fb_st7789v.ko
|
||||
sudo dtoverlay drm-minipitft114
|
||||
|
|
@ -1,407 +0,0 @@
|
|||
/*
|
||||
* DRM driver for ST7789V panels with flexible config
|
||||
*
|
||||
* Copyright 2019 Limor Fried
|
||||
* Copyright 2016 Noralf Trønnes
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_modeset_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/tinydrm/mipi-dbi.h>
|
||||
#include <drm/tinydrm/tinydrm-helpers.h>
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#define ST77XX_MADCTL_MY 0x80
|
||||
#define ST77XX_MADCTL_MX 0x40
|
||||
#define ST77XX_MADCTL_MV 0x20
|
||||
#define ST77XX_MADCTL_ML 0x10
|
||||
#define ST77XX_MADCTL_BGR 0x08
|
||||
#define ST77XX_MADCTL_RGB 0x00
|
||||
|
||||
static u32 col_offset = 0;
|
||||
static u32 row_offset = 0;
|
||||
static u8 col_hack_fix_offset = 0;
|
||||
static short x_offset = 0;
|
||||
static short y_offset = 0;
|
||||
|
||||
static void st7789vada_enable(struct drm_simple_display_pipe *pipe,
|
||||
struct drm_crtc_state *crtc_state,
|
||||
struct drm_plane_state *plane_state)
|
||||
{
|
||||
struct tinydrm_device *tdev = pipe_to_tinydrm(pipe);
|
||||
struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
|
||||
u8 addr_mode;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
ret = mipi_dbi_poweron_conditional_reset(mipi);
|
||||
if (ret < 0)
|
||||
return;
|
||||
if (ret == 1)
|
||||
goto out_enable;
|
||||
|
||||
mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_OFF);
|
||||
|
||||
mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET);
|
||||
msleep(150);
|
||||
mipi_dbi_command(mipi, MIPI_DCS_EXIT_SLEEP_MODE);
|
||||
msleep(10);
|
||||
mipi_dbi_command(mipi, MIPI_DCS_SET_PIXEL_FORMAT, 0x55); // 16 bit color
|
||||
msleep(10);
|
||||
mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, 0);
|
||||
mipi_dbi_command(mipi, MIPI_DCS_SET_COLUMN_ADDRESS, 0, 0, 0, 240);
|
||||
mipi_dbi_command(mipi, MIPI_DCS_SET_PAGE_ADDRESS, 0, 0, 320>>8, 320&0xFF);
|
||||
mipi_dbi_command(mipi, MIPI_DCS_ENTER_INVERT_MODE); // odd hack, displays are inverted
|
||||
mipi_dbi_command(mipi, MIPI_DCS_ENTER_NORMAL_MODE);
|
||||
msleep(10);
|
||||
mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON);
|
||||
msleep(10);
|
||||
|
||||
out_enable:
|
||||
/* The PiTFT (ili9340) has a hardware reset circuit that
|
||||
* resets only on power-on and not on each reboot through
|
||||
* a gpio like the rpi-display does.
|
||||
* As a result, we need to always apply the rotation value
|
||||
* regardless of the display "on/off" state.
|
||||
*/
|
||||
switch (mipi->rotation) {
|
||||
default:
|
||||
addr_mode = 0;
|
||||
x_offset = col_offset;
|
||||
y_offset = row_offset;
|
||||
break;
|
||||
case 90:
|
||||
addr_mode = ST77XX_MADCTL_MV | ST77XX_MADCTL_MX;
|
||||
x_offset = row_offset;
|
||||
y_offset = col_offset;
|
||||
break;
|
||||
case 180:
|
||||
addr_mode = ST77XX_MADCTL_MX | ST77XX_MADCTL_MY;
|
||||
x_offset = col_offset+col_hack_fix_offset;
|
||||
// hack tweak to account for extra pixel width to make even
|
||||
y_offset = row_offset;
|
||||
break;
|
||||
case 270:
|
||||
addr_mode = ST77XX_MADCTL_MV | ST77XX_MADCTL_MY;
|
||||
x_offset = row_offset;
|
||||
y_offset = col_offset;
|
||||
break;
|
||||
}
|
||||
mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode);
|
||||
|
||||
mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON);
|
||||
|
||||
mipi_dbi_enable_flush(mipi, crtc_state, plane_state);
|
||||
|
||||
backlight_enable(mipi->backlight);
|
||||
}
|
||||
|
||||
static const struct drm_simple_display_pipe_funcs st7789vada_pipe_funcs = {
|
||||
.enable = st7789vada_enable,
|
||||
.disable = mipi_dbi_pipe_disable,
|
||||
.update = tinydrm_display_pipe_update,
|
||||
.prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb,
|
||||
};
|
||||
|
||||
static struct drm_display_mode st7789vada_mode = {
|
||||
TINYDRM_MODE(240, 320, 25, 15), // width, height, mm_w, mm_h
|
||||
};
|
||||
|
||||
DEFINE_DRM_GEM_CMA_FOPS(st7789vada_fops);
|
||||
|
||||
static struct drm_driver st7789vada_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
|
||||
DRIVER_ATOMIC,
|
||||
.fops = &st7789vada_fops,
|
||||
TINYDRM_GEM_DRIVER_OPS,
|
||||
.debugfs_init = mipi_dbi_debugfs_init,
|
||||
.name = "st7789vada",
|
||||
.desc = "ST7789V Adafruit",
|
||||
.date = "20190914",
|
||||
.major = 1,
|
||||
.minor = 0,
|
||||
};
|
||||
|
||||
static const struct of_device_id st7789vada_of_match[] = {
|
||||
{ .compatible = "multi-inno,mi0283qt" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, st7789vada_of_match);
|
||||
|
||||
static const struct spi_device_id st7789vada_id[] = {
|
||||
{ "st7789vada", 0 },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, st7789vada_id);
|
||||
|
||||
|
||||
static const struct drm_framebuffer_funcs st7789vada_fb_funcs = {
|
||||
.destroy = drm_gem_fb_destroy,
|
||||
.create_handle = drm_gem_fb_create_handle,
|
||||
.dirty = tinydrm_fb_dirty,
|
||||
};
|
||||
|
||||
static const uint32_t st7789vada_formats[] = {
|
||||
DRM_FORMAT_RGB565,
|
||||
DRM_FORMAT_XRGB8888,
|
||||
};
|
||||
|
||||
static int st7789vada_fb_dirty(struct drm_framebuffer *fb,
|
||||
struct drm_file *file_priv,
|
||||
unsigned int flags, unsigned int color,
|
||||
struct drm_clip_rect *clips,
|
||||
unsigned int num_clips)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
|
||||
struct tinydrm_device *tdev = fb->dev->dev_private;
|
||||
struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev);
|
||||
bool swap = mipi->swap_bytes;
|
||||
struct drm_clip_rect clip;
|
||||
int ret = 0;
|
||||
bool full;
|
||||
void *tr;
|
||||
u16 x1, x2, y1, y2;
|
||||
|
||||
if (!mipi->enabled)
|
||||
return 0;
|
||||
|
||||
full = tinydrm_merge_clips(&clip, clips, num_clips, flags,
|
||||
fb->width, fb->height);
|
||||
|
||||
DRM_DEBUG("Flushing [FB:%d] x1=%u, x2=%u, y1=%u, y2=%u\n", fb->base.id,
|
||||
clip.x1, clip.x2, clip.y1, clip.y2);
|
||||
|
||||
if (!mipi->dc || !full || swap ||
|
||||
fb->format->format == DRM_FORMAT_XRGB8888) {
|
||||
tr = mipi->tx_buf;
|
||||
ret = mipi_dbi_buf_copy(mipi->tx_buf, fb, &clip, swap);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
tr = cma_obj->vaddr;
|
||||
}
|
||||
|
||||
x1 = clip.x1 + x_offset;
|
||||
x2 = clip.x2 - 1 + x_offset;
|
||||
y1 = clip.y1 + y_offset;
|
||||
y2 = clip.y2 - 1 + y_offset;
|
||||
|
||||
//printk(KERN_INFO "setaddrwin %d %d %d %d\n", x1, y1, x2, y2);
|
||||
|
||||
mipi_dbi_command(mipi, MIPI_DCS_SET_COLUMN_ADDRESS,
|
||||
(x1 >> 8) & 0xFF, x1 & 0xFF,
|
||||
(x2 >> 8) & 0xFF, x2 & 0xFF);
|
||||
mipi_dbi_command(mipi, MIPI_DCS_SET_PAGE_ADDRESS,
|
||||
(y1 >> 8) & 0xFF, y1 & 0xFF,
|
||||
(y2 >> 8) & 0xFF, y2 & 0xFF);
|
||||
|
||||
ret = mipi_dbi_command_buf(mipi, MIPI_DCS_WRITE_MEMORY_START, tr,
|
||||
(clip.x2 - clip.x1) * (clip.y2 - clip.y1) * 2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* st7789vada - MIPI DBI initialization
|
||||
* @dev: Parent device
|
||||
* @mipi: &mipi_dbi structure to initialize
|
||||
* @pipe_funcs: Display pipe functions
|
||||
* @driver: DRM driver
|
||||
* @mode: Display mode
|
||||
* @rotation: Initial rotation in degrees Counter Clock Wise
|
||||
*
|
||||
* This function initializes a &mipi_dbi structure and it's underlying
|
||||
* @tinydrm_device. It also sets up the display pipeline.
|
||||
*
|
||||
* Supported formats: Native RGB565 and emulated XRGB8888.
|
||||
*
|
||||
* Objects created by this function will be automatically freed on driver
|
||||
* detach (devres).
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, negative error code on failure.
|
||||
*/
|
||||
int st7789vada_init(struct device *dev, struct mipi_dbi *mipi,
|
||||
const struct drm_simple_display_pipe_funcs *pipe_funcs,
|
||||
struct drm_driver *driver,
|
||||
const struct drm_display_mode *mode, unsigned int rotation)
|
||||
{
|
||||
size_t bufsize = mode->vdisplay * mode->hdisplay * sizeof(u16);
|
||||
struct tinydrm_device *tdev = &mipi->tinydrm;
|
||||
int ret;
|
||||
|
||||
if (!mipi->command)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_init(&mipi->cmdlock);
|
||||
|
||||
mipi->tx_buf = devm_kmalloc(dev, bufsize, GFP_KERNEL);
|
||||
if (!mipi->tx_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = devm_tinydrm_init(dev, tdev, &st7789vada_fb_funcs, driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
tdev->fb_dirty = st7789vada_fb_dirty;
|
||||
|
||||
/* TODO: Maybe add DRM_MODE_CONNECTOR_SPI */
|
||||
ret = tinydrm_display_pipe_init(tdev, pipe_funcs,
|
||||
DRM_MODE_CONNECTOR_VIRTUAL,
|
||||
st7789vada_formats,
|
||||
ARRAY_SIZE(st7789vada_formats), mode,
|
||||
rotation);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
tdev->drm->mode_config.preferred_depth = 16;
|
||||
mipi->rotation = rotation;
|
||||
|
||||
drm_mode_config_reset(tdev->drm);
|
||||
|
||||
DRM_DEBUG_KMS("preferred_depth=%u, rotation = %u\n",
|
||||
tdev->drm->mode_config.preferred_depth, rotation);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int st7789vada_probe(struct spi_device *spi)
|
||||
{
|
||||
struct device *dev = &spi->dev;
|
||||
struct mipi_dbi *mipi;
|
||||
struct gpio_desc *dc;
|
||||
u32 rotation = 0;
|
||||
u32 width = 240;
|
||||
u32 height = 320;
|
||||
int ret;
|
||||
|
||||
mipi = devm_kzalloc(dev, sizeof(*mipi), GFP_KERNEL);
|
||||
if (!mipi)
|
||||
return -ENOMEM;
|
||||
|
||||
mipi->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(mipi->reset)) {
|
||||
DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n");
|
||||
return PTR_ERR(mipi->reset);
|
||||
}
|
||||
|
||||
dc = devm_gpiod_get_optional(dev, "dc", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(dc)) {
|
||||
DRM_DEV_ERROR(dev, "Failed to get gpio 'dc'\n");
|
||||
return PTR_ERR(dc);
|
||||
}
|
||||
|
||||
mipi->regulator = devm_regulator_get(dev, "power");
|
||||
if (IS_ERR(mipi->regulator))
|
||||
return PTR_ERR(mipi->regulator);
|
||||
|
||||
mipi->backlight = devm_of_find_backlight(dev);
|
||||
if (IS_ERR(mipi->backlight))
|
||||
return PTR_ERR(mipi->backlight);
|
||||
|
||||
device_property_read_u32(dev, "rotation", &rotation);
|
||||
//printk(KERN_INFO "Rotation %d\n", rotation);
|
||||
|
||||
device_property_read_u32(dev, "width", &width);
|
||||
if (width % 2) {
|
||||
width +=1; // odd width will cause a kernel panic
|
||||
col_hack_fix_offset = 1;
|
||||
} else {
|
||||
col_hack_fix_offset = 0;
|
||||
}
|
||||
//printk(KERN_INFO "Width %d\n", width);
|
||||
if ((width == 0) || (width > 240)) {
|
||||
width = 240; // default to full framebuff;
|
||||
}
|
||||
device_property_read_u32(dev, "height", &height);
|
||||
//printk(KERN_INFO "Height %d\n", height);
|
||||
if ((height == 0) || (height > 320)) {
|
||||
height = 320; // default to full framebuff;
|
||||
}
|
||||
|
||||
st7789vada_mode.hdisplay = st7789vada_mode.hsync_start =
|
||||
st7789vada_mode.hsync_end = st7789vada_mode.htotal = width;
|
||||
st7789vada_mode.vdisplay = st7789vada_mode.vsync_start =
|
||||
st7789vada_mode.vsync_end = st7789vada_mode.vtotal = height;
|
||||
|
||||
device_property_read_u32(dev, "col_offset", &col_offset);
|
||||
//printk(KERN_INFO "Column offset %d\n", col_offset);
|
||||
|
||||
device_property_read_u32(dev, "row_offset", &row_offset);
|
||||
//printk(KERN_INFO "Row offset %d\n", row_offset);
|
||||
|
||||
ret = mipi_dbi_spi_init(spi, mipi, dc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Cannot read from this controller via SPI */
|
||||
mipi->read_commands = NULL;
|
||||
|
||||
ret = st7789vada_init(&spi->dev, mipi, &st7789vada_pipe_funcs,
|
||||
&st7789vada_driver, &st7789vada_mode, rotation);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
spi_set_drvdata(spi, mipi);
|
||||
|
||||
return devm_tinydrm_register(&mipi->tinydrm);
|
||||
}
|
||||
|
||||
static void st7789vada_shutdown(struct spi_device *spi)
|
||||
{
|
||||
struct mipi_dbi *mipi = spi_get_drvdata(spi);
|
||||
|
||||
tinydrm_shutdown(&mipi->tinydrm);
|
||||
}
|
||||
|
||||
static int __maybe_unused st7789vada_pm_suspend(struct device *dev)
|
||||
{
|
||||
struct mipi_dbi *mipi = dev_get_drvdata(dev);
|
||||
|
||||
return drm_mode_config_helper_suspend(mipi->tinydrm.drm);
|
||||
}
|
||||
|
||||
static int __maybe_unused st7789vada_pm_resume(struct device *dev)
|
||||
{
|
||||
struct mipi_dbi *mipi = dev_get_drvdata(dev);
|
||||
|
||||
drm_mode_config_helper_resume(mipi->tinydrm.drm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops st7789vada_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(st7789vada_pm_suspend, st7789vada_pm_resume)
|
||||
};
|
||||
|
||||
static struct spi_driver st7789vada_spi_driver = {
|
||||
.driver = {
|
||||
.name = "st7789vada",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = st7789vada_of_match,
|
||||
.pm = &st7789vada_pm_ops,
|
||||
},
|
||||
.id_table = st7789vada_id,
|
||||
.probe = st7789vada_probe,
|
||||
.shutdown = st7789vada_shutdown,
|
||||
};
|
||||
module_spi_driver(st7789vada_spi_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Sitronix ST7789V Flexible DRM driver");
|
||||
MODULE_AUTHOR("Limor Fried");
|
||||
MODULE_LICENSE("GPL");
|
||||
3
templates/95-ftcaptouch.rules
Normal file
3
templates/95-ftcaptouch.rules
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# udev rule for Focaltouch Capactive Touchscreen
|
||||
SUBSYSTEM=="input", ATTRS{name}=="EP0110M09", ENV{DEVNAME}=="*event*", SYMLINK+="input/touchscreen"
|
||||
SUBSYSTEM=="input", ATTRS{name}=="generic ft5x06*", ENV{DEVNAME}=="*event*", SYMLINK+="input/touchscreen"
|
||||
2
templates/95-stmpe.rules
Normal file
2
templates/95-stmpe.rules
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
udev rule for STMPE Resistive Touchscreen Controller
|
||||
SUBSYSTEM=="input", ATTRS{name}=="*stmpe*", ENV{DEVNAME}=="*event*", SYMLINK+="input/touchscreen"
|
||||
1
templates/95-touchmouse.rules
Normal file
1
templates/95-touchmouse.rules
Normal file
|
|
@ -0,0 +1 @@
|
|||
SUBSYSTEM=="input", ATTRS{name}=="touchmouse", ENV{DEVNAME}=="*event*", SYMLINK+="input/touchscreen"
|
||||
14
templates/99-spi-tft-drm.rules
Normal file
14
templates/99-spi-tft-drm.rules
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# udev rules for SPI TFT DRM devices to create reliable symlinks
|
||||
# Supports ili9341, st7789, and other SPI TFT displays
|
||||
|
||||
# Rule for ili9341 DRM device (and other SPI TFT displays)
|
||||
SUBSYSTEM=="drm", KERNEL=="card*", KERNELS=="spi0.0", DRIVERS=="ili9341", SYMLINK+="dri/spitft"
|
||||
|
||||
# Generic rule for any SPI TFT display on spi0.0
|
||||
SUBSYSTEM=="drm", KERNEL=="card*", KERNELS=="spi0.0", SUBSYSTEMS=="spi", SYMLINK+="dri/spitft"
|
||||
|
||||
# Rule for st7789 displays (add when needed)
|
||||
SUBSYSTEM=="drm", KERNEL=="card*", KERNELS=="spi0.0", DRIVERS=="st7789", SYMLINK+="dri/spitft"
|
||||
|
||||
# Alternative rule using device path pattern
|
||||
SUBSYSTEM=="drm", KERNEL=="card*", DEVPATH=="*/spi0/spi0.0/drm/card*", SYMLINK+="dri/spitft"
|
||||
5
templates/99-tsc2007-touchscreen.rules
Normal file
5
templates/99-tsc2007-touchscreen.rules
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# udev rule for TSC2007 touchscreen to create /dev/input/touchscreen symlink and apply transformation
|
||||
SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="TSC2007 Touchscreen", SYMLINK+="input/touchscreen", ENV{LIBINPUT_CALIBRATION_MATRIX}="{calibration_matrix}"
|
||||
|
||||
# Backup rule using touchscreen capability and TSC2007 name pattern
|
||||
SUBSYSTEM=="input", KERNEL=="event*", ENV{ID_INPUT_TOUCHSCREEN}=="1", ATTRS{name}=="*TSC2007*", SYMLINK+="input/touchscreen", ENV{LIBINPUT_CALIBRATION_MATRIX}="{calibration_matrix}"
|
||||
25
templates/con2fbmap-helper.sh
Normal file
25
templates/con2fbmap-helper.sh
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Wait for TFT framebuffer to be ready
|
||||
echo "Waiting for SPI TFT framebuffer..."
|
||||
|
||||
# Wait up to 30 seconds for /dev/fb0 or /dev/fb1 to appear
|
||||
for i in {1..300}; do
|
||||
for fbdev in 0 1; do
|
||||
if [ -e /dev/fb$fbdev ]; then
|
||||
echo "Found /dev/fb$fbdev, checking if it's {display_type}..."
|
||||
|
||||
# Check if it's actually the ili9341 device
|
||||
if dmesg | grep -q "{display_type}.*fb$fbdev"; then
|
||||
echo "{display_type} framebuffer ready, mapping console..."
|
||||
con2fbmap 1 $fbdev
|
||||
echo "Console mapped to framebuffer $fbdev"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
done
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
echo "Timeout waiting for SPI TFT framebuffer"
|
||||
exit 1
|
||||
14
templates/con2fbmap.service
Normal file
14
templates/con2fbmap.service
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
[Unit]
|
||||
Description=Map console to framebuffer for SPI TFT
|
||||
After=multi-user.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/bin/con2fbmap-helper.sh
|
||||
RemainAfterExit=yes
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
TimeoutStartSec=60
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
8
templates/config_text_base.txt
Normal file
8
templates/config_text_base.txt
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# --- added by adafruit-pitft-helper {date} ---
|
||||
[all]
|
||||
hdmi_force_hotplug=1 # required for cases when HDMI is not plugged in!
|
||||
dtparam=spi=on
|
||||
dtparam=i2c1=on
|
||||
dtparam=i2c_arm=on
|
||||
{overlay}
|
||||
# --- end adafruit-pitft-helper {date} ---
|
||||
11
templates/fbcp.service
Normal file
11
templates/fbcp.service
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
[Unit]
|
||||
Description=Framebuffer copy utility for PiTFT
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStartPre=/bin/sleep 10
|
||||
ExecStart=/usr/local/bin/fbcp
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
430
voice_bonnet.sh
Executable file
430
voice_bonnet.sh
Executable file
|
|
@ -0,0 +1,430 @@
|
|||
#!/bin/bash
|
||||
|
||||
: <<'DISCLAIMER'
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
This script is licensed under the terms of the MIT license.
|
||||
Unless otherwise noted, code reproduced herein
|
||||
was written for this script.
|
||||
|
||||
- The Pimoroni Crew - (modified by Adafruit!)
|
||||
|
||||
DISCLAIMER
|
||||
|
||||
# script control variables
|
||||
|
||||
productname="voice bonnet/BrainCraft HAT" # the name of the product to install
|
||||
scriptname="voice_bonnet" # the name of this script
|
||||
spacereq=1 # minimum size required on root partition in MB
|
||||
debugmode="no" # whether the script should use debug routines
|
||||
debuguser="none" # optional test git user to use in debug mode
|
||||
debugpoint="none" # optional git repo branch or tag to checkout
|
||||
forcesudo="no" # whether the script requires to be ran with root privileges
|
||||
promptreboot="no" # whether the script should always prompt user to reboot
|
||||
mininstall="no" # whether the script enforces minimum install routine
|
||||
customcmd="yes" # whether to execute commands specified before exit
|
||||
armv6="yes" # whether armv6 processors are supported
|
||||
armv7="yes" # whether armv7 processors are supported
|
||||
armv8="yes" # whether armv8 processors are supported
|
||||
arm64="yes" # whether arm64 processors are supported
|
||||
raspbianonly="no" # whether the script is allowed to run on other OSes
|
||||
osreleases=( "Raspbian" ) # list os-releases supported
|
||||
oswarning=( "Debian" "Kano" "Mate" "PiTop" "Ubuntu" ) # list experimental os-releases
|
||||
osdeny=( "Darwin" "Kali" ) # list os-releases specifically disallowed
|
||||
|
||||
FORCE=$1
|
||||
DEVICE_TREE=true
|
||||
ASK_TO_REBOOT=false
|
||||
CURRENT_SETTING=false
|
||||
UPDATE_DB=false
|
||||
|
||||
BOOTCMD=/boot/firmware/cmdline.txt
|
||||
CONFIG=/boot/firmware/config.txt
|
||||
APTSRC=/etc/apt/sources.list
|
||||
INITABCONF=/etc/inittab
|
||||
BLACKLIST=/etc/modprobe.d/raspi-blacklist.conf
|
||||
LOADMOD=/etc/modules
|
||||
DTBODIR=/boot/overlays
|
||||
|
||||
# Fall back to old location
|
||||
if ! test -f $CONFIG; then
|
||||
CONFIG=/boot/config.txt
|
||||
fi
|
||||
|
||||
# function define
|
||||
|
||||
confirm() {
|
||||
if [ "$FORCE" == '-y' ]; then
|
||||
true
|
||||
else
|
||||
read -r -p "$1 [y/N] " response < /dev/tty
|
||||
if [[ $response =~ ^(yes|y|Y)$ ]]; then
|
||||
true
|
||||
else
|
||||
false
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
prompt() {
|
||||
read -r -p "$1 [y/N] " response < /dev/tty
|
||||
if [[ $response =~ ^(yes|y|Y)$ ]]; then
|
||||
true
|
||||
else
|
||||
false
|
||||
fi
|
||||
}
|
||||
|
||||
success() {
|
||||
echo -e "$(tput setaf 2)$1$(tput sgr0)"
|
||||
}
|
||||
|
||||
inform() {
|
||||
echo -e "$(tput setaf 6)$1$(tput sgr0)"
|
||||
}
|
||||
|
||||
warning() {
|
||||
echo -e "$(tput setaf 1)$1$(tput sgr0)"
|
||||
}
|
||||
|
||||
newline() {
|
||||
echo ""
|
||||
}
|
||||
|
||||
progress() {
|
||||
count=0
|
||||
until [ $count -eq $1 ]; do
|
||||
echo -n "..." && sleep 1
|
||||
((count++))
|
||||
done
|
||||
echo
|
||||
}
|
||||
sudocheck() {
|
||||
if [ $(id -u) -ne 0 ]; then
|
||||
echo -e "Install must be run as root. Try 'sudo ./$scriptname'\n"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
sysclean() {
|
||||
sudo apt-get clean && sudo apt-get autoclean
|
||||
sudo apt-get -y autoremove &> /dev/null
|
||||
}
|
||||
|
||||
sysupdate() {
|
||||
if ! $UPDATE_DB; then
|
||||
echo "Updating apt indexes..." && progress 3 &
|
||||
sudo apt-get update 1> /dev/null || { warning "Apt failed to update indexes!" && exit 1; }
|
||||
echo "Reading package lists..."
|
||||
progress 3 && UPDATE_DB=true
|
||||
fi
|
||||
}
|
||||
|
||||
sysupgrade() {
|
||||
sudo apt-get upgrade
|
||||
sudo apt-get clean && sudo apt-get autoclean
|
||||
sudo apt-get -y autoremove &> /dev/null
|
||||
}
|
||||
|
||||
sysreboot() {
|
||||
warning "Some changes made to your system require"
|
||||
warning "your computer to reboot to take effect."
|
||||
newline
|
||||
if prompt "Would you like to reboot now?"; then
|
||||
sync && sudo reboot
|
||||
fi
|
||||
}
|
||||
|
||||
# Given a filename, a regex pattern to match and a replacement string,
|
||||
# perform replacement if found, else append replacement to end of file.
|
||||
# (# $1 = filename, $2 = pattern to match, $3 = replacement)
|
||||
reconfig() {
|
||||
grep $2 $1 >/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
# Pattern found; replace in file
|
||||
sed -i "s/$2/$3/g" $1 >/dev/null
|
||||
else
|
||||
# Not found; append (silently)
|
||||
echo $3 | sudo tee -a $1 >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
# If /boot/firmware/config.txt exists, make sure /boot/config.txt is a symlink to it
|
||||
fix_config_symlink() {
|
||||
if [ -f /boot/firmware/config.txt ]; then
|
||||
if [ ! -L /boot/config.txt ]; then
|
||||
warning "/boot/config.txt was overwritten as a file by another script."
|
||||
if confirm "/boot/config.txt will be moved to /boot/firmware/config.txt and the symlink restored. Do you wish to continue?"; then
|
||||
sudo mv /boot/config.txt /boot/firmware/config.txt
|
||||
sudo ln -s /boot/firmware/config.txt /boot/config.txt
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
arch_check() {
|
||||
IS_ARM64=false
|
||||
IS_ARMHF=false
|
||||
IS_ARMv6=false
|
||||
|
||||
if uname -m | grep "aarch64" > /dev/null; then
|
||||
IS_ARM64=true
|
||||
fi
|
||||
if uname -m | grep "armv.l" > /dev/null; then
|
||||
IS_ARMHF=true
|
||||
if uname -m | grep "armv6l" > /dev/null; then
|
||||
IS_ARMv6=true
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
os_check() {
|
||||
IS_RASPBIAN=false
|
||||
IS_MACOSX=false
|
||||
IS_SUPPORTED=false
|
||||
IS_EXPERIMENTAL=false
|
||||
|
||||
if [ -f /etc/os-release ]; then
|
||||
if cat /etc/os-release | grep "Raspbian" > /dev/null; then
|
||||
IS_RASPBIAN=true && IS_SUPPORTED=true
|
||||
fi
|
||||
if command -v apt-get > /dev/null; then
|
||||
for os in ${osreleases[@]}; do
|
||||
if cat /etc/os-release | grep $os > /dev/null; then
|
||||
IS_SUPPORTED=true && IS_EXPERIMENTAL=false
|
||||
fi
|
||||
done
|
||||
for os in ${oswarning[@]}; do
|
||||
if cat /etc/os-release | grep $os > /dev/null; then
|
||||
IS_SUPPORTED=false && IS_EXPERIMENTAL=true
|
||||
fi
|
||||
done
|
||||
for os in ${osdeny[@]}; do
|
||||
if cat /etc/os-release | grep $os > /dev/null; then
|
||||
IS_SUPPORTED=false && IS_EXPERIMENTAL=false
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
if [ -d ~/.kano-settings ] || [ -d ~/.kanoprofile ]; then
|
||||
IS_RASPBIAN=false
|
||||
for os in ${oswarning[@]}; do
|
||||
if [ $os == "Kano" ]; then
|
||||
IS_SUPPORTED=false && IS_EXPERIMENTAL=true
|
||||
fi
|
||||
done
|
||||
for os in ${osdeny[@]}; do
|
||||
if [ $os == "Kano" ]; then
|
||||
IS_SUPPORTED=false && IS_EXPERIMENTAL=false
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [ -f ~/.pt-dashboard-config ] || [ -d ~/.pt-dashboard ] || [ -d ~/.pt-os-dashboard ]; then
|
||||
IS_RASPBIAN=false
|
||||
for os in ${oswarning[@]}; do
|
||||
if [ $os == "PiTop" ]; then
|
||||
IS_SUPPORTED=false && IS_EXPERIMENTAL=true
|
||||
fi
|
||||
done
|
||||
for os in ${osdeny[@]}; do
|
||||
if [ $os == "PiTop" ]; then
|
||||
IS_SUPPORTED=false && IS_EXPERIMENTAL=false
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [ -d ~/.config/ubuntu-mate ]; then
|
||||
for os in ${osdeny[@]}; do
|
||||
if [ $os == "Mate" ]; then
|
||||
IS_SUPPORTED=false && IS_EXPERIMENTAL=false
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if uname -s | grep "Darwin" > /dev/null; then
|
||||
IS_MACOSX=true
|
||||
for os in ${osdeny[@]}; do
|
||||
if [ $os == "Darwin" ]; then
|
||||
IS_SUPPORTED=false && IS_EXPERIMENTAL=false
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
raspbian_check() {
|
||||
IS_SUPPORTED=false
|
||||
IS_EXPERIMENTAL=false
|
||||
|
||||
if [ -f /etc/os-release ]; then
|
||||
if cat /etc/os-release | grep "/sid" > /dev/null; then
|
||||
IS_SUPPORTED=false && IS_EXPERIMENTAL=true
|
||||
elif cat /etc/os-release | grep "bullseye" > /dev/null; then
|
||||
IS_SUPPORTED=false && IS_EXPERIMENTAL=true
|
||||
elif cat /etc/os-release | grep "buster" > /dev/null; then
|
||||
IS_SUPPORTED=false && IS_EXPERIMENTAL=true
|
||||
elif cat /etc/os-release | grep "stretch" > /dev/null; then
|
||||
IS_SUPPORTED=false && IS_EXPERIMENTAL=false
|
||||
elif cat /etc/os-release | grep "jessie" > /dev/null; then
|
||||
IS_SUPPORTED=true && IS_EXPERIMENTAL=false
|
||||
elif cat /etc/os-release | grep "wheezy" > /dev/null; then
|
||||
IS_SUPPORTED=true && IS_EXPERIMENTAL=false
|
||||
else
|
||||
IS_SUPPORTED=false && IS_EXPERIMENTAL=false
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
: <<'MAINSTART'
|
||||
|
||||
Perform all global variables declarations as well as function definition
|
||||
above this section for clarity, thanks!
|
||||
|
||||
MAINSTART
|
||||
|
||||
# checks and init
|
||||
|
||||
arch_check
|
||||
os_check
|
||||
|
||||
if [ $debugmode != "no" ]; then
|
||||
echo "USER_HOME is $USER_HOME" && newline
|
||||
echo "IS_RASPBIAN is $IS_RASPBIAN"
|
||||
echo "IS_MACOSX is $IS_MACOSX"
|
||||
echo "IS_SUPPORTED is $IS_SUPPORTED"
|
||||
echo "IS_EXPERIMENTAL is $IS_EXPERIMENTAL"
|
||||
newline
|
||||
fi
|
||||
|
||||
if ! $IS_ARMHF && ! $IS_ARM64; then
|
||||
warning "This hardware is not supported, sorry!"
|
||||
warning "Config files have been left untouched"
|
||||
newline && exit 1
|
||||
fi
|
||||
|
||||
if $IS_ARM64 && [ $arm64 == "no" ]; then
|
||||
warning "Sorry, your CPU is not supported by this installer"
|
||||
newline && exit 1
|
||||
elif $IS_ARMv8 && [ $armv8 == "no" ]; then
|
||||
warning "Sorry, your CPU is not supported by this installer"
|
||||
newline && exit 1
|
||||
elif $IS_ARMv7 && [ $armv7 == "no" ]; then
|
||||
warning "Sorry, your CPU is not supported by this installer"
|
||||
newline && exit 1
|
||||
elif $IS_ARMv6 && [ $armv6 == "no" ]; then
|
||||
warning "Sorry, your CPU is not supported by this installer"
|
||||
newline && exit 1
|
||||
fi
|
||||
|
||||
if [ $raspbianonly == "yes" ] && ! $IS_RASPBIAN;then
|
||||
warning "This script is intended for Raspbian on a Raspberry Pi!"
|
||||
newline && exit 1
|
||||
fi
|
||||
|
||||
if $IS_RASPBIAN; then
|
||||
raspbian_check
|
||||
if ! $IS_SUPPORTED && ! $IS_EXPERIMENTAL; then
|
||||
newline && warning "--- Warning ---" && newline
|
||||
echo "The $productname installer"
|
||||
echo "does not work on this version of Raspbian."
|
||||
echo "Check https://github.com/$gitusername/$gitreponame"
|
||||
echo "for additional information and support"
|
||||
newline && exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! $IS_SUPPORTED && ! $IS_EXPERIMENTAL; then
|
||||
warning "Your operating system is not supported, sorry!"
|
||||
newline && exit 1
|
||||
fi
|
||||
|
||||
if $IS_EXPERIMENTAL; then
|
||||
warning "Support for your operating system is experimental. Please visit"
|
||||
warning "forums.adafruit.com if you experience issues with this product."
|
||||
newline
|
||||
fi
|
||||
|
||||
if [ $forcesudo == "yes" ]; then
|
||||
sudocheck
|
||||
fi
|
||||
|
||||
newline
|
||||
echo "This script will install everything needed to use"
|
||||
echo "$productname"
|
||||
newline
|
||||
warning "--- Warning ---"
|
||||
newline
|
||||
echo "Always be careful when running scripts and commands"
|
||||
echo "copied from the internet. Ensure they are from a"
|
||||
echo "trusted source."
|
||||
newline
|
||||
echo "If you want to see what this script does before"
|
||||
echo "running it, you should run:"
|
||||
echo " \curl -sS github.com/adafruit/Raspberry-Pi-Installer-Scripts/$scriptname"
|
||||
newline
|
||||
|
||||
if confirm "Do you wish to continue?"; then
|
||||
|
||||
newline
|
||||
echo "Checking hardware requirements..."
|
||||
|
||||
fix_config_symlink
|
||||
|
||||
if [ -e $CONFIG ] && grep -q "^device_tree=$" $CONFIG; then
|
||||
DEVICE_TREE=false
|
||||
fi
|
||||
|
||||
if $DEVICE_TREE; then
|
||||
|
||||
newline
|
||||
echo "Adding Device Tree Entry to $CONFIG"
|
||||
|
||||
if [ -e $CONFIG ] && grep -q "^dtoverlay=seeed-2mic-voicecard$" $CONFIG; then
|
||||
echo "dtoverlay already active"
|
||||
else
|
||||
echo "dtoverlay=seeed-2mic-voicecard" | sudo tee -a $CONFIG
|
||||
ASK_TO_REBOOT=true
|
||||
fi
|
||||
|
||||
if [ -e $CONFIG ] && grep -q "^dtoverlay=i2s-mmap$" $CONFIG; then
|
||||
echo "i2s mmap dtoverlay already active"
|
||||
else
|
||||
echo "dtoverlay=i2s-mmap" | sudo tee -a $CONFIG
|
||||
ASK_TO_REBOOT=true
|
||||
fi
|
||||
|
||||
if [ -e $CONFIG ] && grep -q "^dtparam=i2s=on$" $CONFIG; then
|
||||
echo "i2s interface already enabled"
|
||||
else
|
||||
reconfig $CONFIG "^#dtparam=i2s=on$" "dtparam=i2s=on"
|
||||
ASK_TO_REBOOT=true
|
||||
fi
|
||||
|
||||
else
|
||||
newline
|
||||
echo "No Device Tree Detected, not supported"
|
||||
newline
|
||||
exit 1
|
||||
fi
|
||||
|
||||
newline
|
||||
success "All done!"
|
||||
newline
|
||||
echo "Enjoy your new $productname!"
|
||||
newline
|
||||
|
||||
if [ $promptreboot == "yes" ] || $ASK_TO_REBOOT; then
|
||||
sysreboot
|
||||
fi
|
||||
else
|
||||
newline
|
||||
echo "Aborting..."
|
||||
newline
|
||||
fi
|
||||
|
||||
exit 0
|
||||
12
wm8960-soundcard.service
Normal file
12
wm8960-soundcard.service
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
[Unit]
|
||||
Description=WM8960 Soundcard service
|
||||
After=alsa-restore.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=/usr/bin/wm8960-soundcard
|
||||
User=root
|
||||
|
||||
[Install]
|
||||
WantedBy=sysinit.target
|
||||
Loading…
Reference in a new issue