From 794210fea2876042fada399e48e249d8a7cc8144 Mon Sep 17 00:00:00 2001 From: caternuson Date: Wed, 17 May 2023 10:14:57 -0700 Subject: [PATCH] add code for rpi pirate radio --- Raspberry_Pi_PiPyPirate_Radio/freq_scan.py | 15 +++ Raspberry_Pi_PiPyPirate_Radio/mpd.conf | 8 ++ Raspberry_Pi_PiPyPirate_Radio/radio.py | 134 +++++++++++++++++++++ Raspberry_Pi_PiPyPirate_Radio/radio_bg.png | Bin 0 -> 9520 bytes 4 files changed, 157 insertions(+) create mode 100755 Raspberry_Pi_PiPyPirate_Radio/freq_scan.py create mode 100644 Raspberry_Pi_PiPyPirate_Radio/mpd.conf create mode 100755 Raspberry_Pi_PiPyPirate_Radio/radio.py create mode 100755 Raspberry_Pi_PiPyPirate_Radio/radio_bg.png diff --git a/Raspberry_Pi_PiPyPirate_Radio/freq_scan.py b/Raspberry_Pi_PiPyPirate_Radio/freq_scan.py new file mode 100755 index 000000000..347316739 --- /dev/null +++ b/Raspberry_Pi_PiPyPirate_Radio/freq_scan.py @@ -0,0 +1,15 @@ +import board +import digitalio +import adafruit_si4713 + +radio = adafruit_si4713.SI4713( + board.I2C(), + reset=digitalio.DigitalInOut(board.D26), + timeout_s=0.5 +) + +with open("freq_scan.dat", "w") as fp: + for f_khz in range(87500, 108000, 50): + noise = radio.received_noise_level(f_khz) + fp.write("{},{}\n".format(f_khz/1000.0, noise)) + print('{0:0.3f} mhz = {1} dBuV'.format(f_khz/1000.0, noise)) \ No newline at end of file diff --git a/Raspberry_Pi_PiPyPirate_Radio/mpd.conf b/Raspberry_Pi_PiPyPirate_Radio/mpd.conf new file mode 100644 index 000000000..c2a33f30f --- /dev/null +++ b/Raspberry_Pi_PiPyPirate_Radio/mpd.conf @@ -0,0 +1,8 @@ +music_directory "/home/pi/music" +playlist_directory "/home/pi/playlists" + +audio_output { + type "alsa" + name "USB Audio Adapter" + device "hw:2,0" +} diff --git a/Raspberry_Pi_PiPyPirate_Radio/radio.py b/Raspberry_Pi_PiPyPirate_Radio/radio.py new file mode 100755 index 000000000..21b5041f3 --- /dev/null +++ b/Raspberry_Pi_PiPyPirate_Radio/radio.py @@ -0,0 +1,134 @@ +import time +import board +import digitalio +import adafruit_si4713 +from PIL import Image, ImageDraw, ImageFont +from adafruit_rgb_display import st7789 +import mpd + +#--| User Config |----------------------------------- +FREQ = 89.00 +PLAYLIST = "test" +UPDATE_RATE = 0.5 +#---------------------------------------------------- + +#==| SETUP |========================================================= + +# Display +disp = st7789.ST7789( + board.SPI(), + height=240, + y_offset=80, + rotation=180, + cs=digitalio.DigitalInOut(board.CE0), + dc=digitalio.DigitalInOut(board.D25), + rst=digitalio.DigitalInOut(board.D24), + baudrate=64000000, +) + +backlight = digitalio.DigitalInOut(board.D22) +backlight.switch_to_output() +backlight.value = True + +background = Image.open("radio_bg.png") +STAT_FNT = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSansCondensed-Bold.ttf", 55) +STAT_CLR = (30, 100, 200) +INFO_FNT = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 20) +ARTS_CLR = (0, 100, 0) +ALBM_CLR = (0, 100, 0) +TITL_CLR = (0, 100, 0) +PROG_CLR = (0, 100, 0) + +# Buttons +button1 = digitalio.DigitalInOut(board.D23) +button1.switch_to_input(pull=digitalio.Pull.UP) +button2 = digitalio.DigitalInOut(board.D24) +button2.switch_to_input(pull=digitalio.Pull.UP) + +# Radio +radio = adafruit_si4713.SI4713( + board.I2C(), + reset=digitalio.DigitalInOut(board.D26), + timeout_s = 0.5 +) +radio.tx_frequency_khz = int(FREQ * 1000) +radio.tx_power = 115 + +# MPD +mpc = mpd.MPDClient() +mpc.connect("localhost", 6600) +mpc.stop() +mpc.clear() +mpc.load(PLAYLIST) +mpc.play() +mpc.repeat(1) +#==================================================================== + +def button1_handler(): + if status['state'] == 'play': + mpc.pause() + else: + mpc.play() + +def button2_handler(): + mpc.next() + +def update_display(): + image = background.copy() + draw = ImageDraw.Draw(image) + + draw.text( + (150, 20), + "{:>5.1f}".format(FREQ), + anchor="mt", + font=STAT_FNT, + fill=STAT_CLR + ) + + if status['state'] == 'play': + r = 10 * (1 + int(time.monotonic() % 3)) + draw.arc( (30-r, 20-r, 30+r, 20+r), + 120, 60, + fill = (0, 0, 0), + width = 3 + ) + + info = mpc.currentsong() + artist = info.get('artist', 'unknown') + album = info.get('album', 'unknown') + song = info.get('title', 'unknown') + draw.text( (5, 150), artist, font=INFO_FNT, fill=ARTS_CLR ) + draw.text( (5, 170), album, font=INFO_FNT, fill=ALBM_CLR) + draw.text( (5, 190), song, font=INFO_FNT, fill=TITL_CLR) + + perc = float(status['elapsed']) / float(status['duration']) + draw.rectangle( (5, 215, 235, 230), outline=PROG_CLR) + draw.rectangle ( + (5, 215, 5 + int(230*perc), 230), + fill=PROG_CLR + ) + + disp.image(image) + +last_update = time.monotonic() + +while True: + now = time.monotonic() + try: + status = mpc.status() + except ConnectionError: + mpc.connect("localhost", 6600) + status = mpc.status() + if not button1.value: + button1_handler() + while not button1.value: + time.sleep(0.001) + if not button2.value: + button2_handler() + while not button2.value: + time.sleep(0.001) + if now - last_update > UPDATE_RATE: + update_display() + last_update = now + + diff --git a/Raspberry_Pi_PiPyPirate_Radio/radio_bg.png b/Raspberry_Pi_PiPyPirate_Radio/radio_bg.png new file mode 100755 index 0000000000000000000000000000000000000000..6c918120fe2f403816d18673a859cc1ec8212237 GIT binary patch literal 9520 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 E2bol$ivR!s literal 0 HcmV?d00001