Skip to content

Commit 5a15eae

Browse files
authored
Merge pull request #2503 from caternuson/add_piradio
Add code for rpi pirate radio
2 parents 9ccddf5 + efaccc8 commit 5a15eae

File tree

4 files changed

+167
-0
lines changed

4 files changed

+167
-0
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# SPDX-FileCopyrightText: 2023 Carter N. for Adafruit Industries
2+
# SPDX-License-Identifier: MIT
3+
4+
import board
5+
import digitalio
6+
import adafruit_si4713
7+
8+
radio = adafruit_si4713.SI4713(
9+
board.I2C(),
10+
reset=digitalio.DigitalInOut(board.D26),
11+
timeout_s=0.5
12+
)
13+
14+
with open("freq_scan.dat", "w") as fp:
15+
for f_khz in range(87500, 108000, 50):
16+
noise = radio.received_noise_level(f_khz)
17+
fp.write("{},{}\n".format(f_khz/1000.0, noise))
18+
print('{0:0.3f} mhz = {1} dBuV'.format(f_khz/1000.0, noise))
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
music_directory "/home/pi/music"
2+
playlist_directory "/home/pi/playlists"
3+
4+
audio_output {
5+
type "alsa"
6+
name "USB Audio Adapter"
7+
device "hw:2,0"
8+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# SPDX-FileCopyrightText: 2023 Carter N. for Adafruit Industries
2+
# SPDX-License-Identifier: MIT
3+
4+
import time
5+
import board
6+
import digitalio
7+
import adafruit_si4713
8+
from PIL import Image, ImageDraw, ImageFont
9+
from adafruit_rgb_display import st7789
10+
import mpd
11+
12+
#--| User Config |-----------------------------------
13+
FREQ = 89.00
14+
PLAYLIST = "test"
15+
STATION_NAME = "PiPyPirate Radio"
16+
UPDATE_RATE = 0.5
17+
#----------------------------------------------------
18+
19+
#==| SETUP |=========================================================
20+
21+
# Display
22+
disp = st7789.ST7789(
23+
board.SPI(),
24+
height=240,
25+
y_offset=80,
26+
rotation=180,
27+
cs=digitalio.DigitalInOut(board.CE0),
28+
dc=digitalio.DigitalInOut(board.D25),
29+
rst=digitalio.DigitalInOut(board.D24),
30+
baudrate=64000000,
31+
)
32+
33+
backlight = digitalio.DigitalInOut(board.D22)
34+
backlight.switch_to_output()
35+
backlight.value = True
36+
37+
background = Image.open("radio_bg.png")
38+
STAT_FNT = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSansCondensed-Bold.ttf", 55)
39+
STAT_CLR = (30, 100, 200)
40+
INFO_FNT = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 20)
41+
ARTS_CLR = (0, 100, 0)
42+
ALBM_CLR = (0, 100, 0)
43+
TITL_CLR = (0, 100, 0)
44+
PROG_CLR = (0, 100, 0)
45+
46+
# Buttons
47+
button1 = digitalio.DigitalInOut(board.D23)
48+
button1.switch_to_input(pull=digitalio.Pull.UP)
49+
button2 = digitalio.DigitalInOut(board.D24)
50+
button2.switch_to_input(pull=digitalio.Pull.UP)
51+
52+
# Radio
53+
radio = adafruit_si4713.SI4713(
54+
board.I2C(),
55+
reset=digitalio.DigitalInOut(board.D26),
56+
timeout_s = 0.5
57+
)
58+
radio.tx_frequency_khz = int(FREQ * 1000)
59+
radio.tx_power = 115
60+
radio.configure_rds(0xADAF, station=STATION_NAME.encode())
61+
62+
# MPD
63+
mpc = mpd.MPDClient()
64+
mpc.connect("localhost", 6600)
65+
mpc.stop()
66+
mpc.clear()
67+
mpc.load(PLAYLIST)
68+
mpc.play()
69+
mpc.repeat(1)
70+
#====================================================================
71+
72+
def button1_handler():
73+
if status['state'] == 'play':
74+
mpc.pause()
75+
else:
76+
mpc.play()
77+
78+
def button2_handler():
79+
mpc.next()
80+
81+
def update_display():
82+
image = background.copy()
83+
draw = ImageDraw.Draw(image)
84+
85+
draw.text(
86+
(150, 20),
87+
"{:>5.1f}".format(FREQ),
88+
anchor="mt",
89+
font=STAT_FNT,
90+
fill=STAT_CLR
91+
)
92+
93+
if status['state'] == 'play':
94+
r = 10 * (1 + int(time.monotonic() % 3))
95+
draw.arc( (30-r, 20-r, 30+r, 20+r),
96+
120, 60,
97+
fill = (0, 0, 0),
98+
width = 3
99+
)
100+
101+
info = mpc.currentsong()
102+
artist = info.get('artist', 'unknown')
103+
album = info.get('album', 'unknown')
104+
song = info.get('title', 'unknown')
105+
draw.text( (5, 150), artist, font=INFO_FNT, fill=ARTS_CLR )
106+
draw.text( (5, 170), album, font=INFO_FNT, fill=ALBM_CLR)
107+
draw.text( (5, 190), song, font=INFO_FNT, fill=TITL_CLR)
108+
rds_info = "{}:{}:{}".format(artist, album, song)
109+
radio.rds_buffer = rds_info.encode()
110+
111+
perc = float(status['elapsed']) / float(status['duration'])
112+
draw.rectangle( (5, 215, 235, 230), outline=PROG_CLR)
113+
draw.rectangle (
114+
(5, 215, 5 + int(230*perc), 230),
115+
fill=PROG_CLR
116+
)
117+
118+
disp.image(image)
119+
120+
last_update = time.monotonic()
121+
122+
print("Now broadcasting {} on {}FM".format(STATION_NAME, FREQ))
123+
124+
while True:
125+
now = time.monotonic()
126+
try:
127+
status = mpc.status()
128+
except ConnectionError:
129+
mpc.connect("localhost", 6600)
130+
status = mpc.status()
131+
if not button1.value:
132+
button1_handler()
133+
while not button1.value:
134+
time.sleep(0.001)
135+
if not button2.value:
136+
button2_handler()
137+
while not button2.value:
138+
time.sleep(0.001)
139+
if now - last_update > UPDATE_RATE:
140+
update_display()
141+
last_update = now
9.3 KB
Loading

0 commit comments

Comments
 (0)