|
| 1 | +# SPDX-FileCopyrightText: 2023 Liz Clark for Adafruit Industries |
| 2 | +# SPDX-License-Identifier: MIT |
| 3 | + |
| 4 | +import time |
| 5 | +import board |
| 6 | +import digitalio |
| 7 | +import audiomixer |
| 8 | +import audiomp3 |
| 9 | +from audiopwmio import PWMAudioOut as AudioOut |
| 10 | +from adafruit_seesaw import seesaw, rotaryio, digitalio as seesaw_io, neopixel as seesaw_neopixel |
| 11 | +from adafruit_led_animation.animation.pulse import Pulse |
| 12 | +import neopixel |
| 13 | + |
| 14 | +# wait a little bit so USB can stabilize and not glitch audio |
| 15 | +time.sleep(3) |
| 16 | + |
| 17 | +# enable propmaker speaker output |
| 18 | +enable = digitalio.DigitalInOut(board.D10) |
| 19 | +enable.direction = digitalio.Direction.OUTPUT |
| 20 | +enable.value = True |
| 21 | + |
| 22 | +# speaker pin on the propmaker |
| 23 | +audio = AudioOut(board.A0) |
| 24 | +# create mixer instance |
| 25 | +mixer = audiomixer.Mixer(voice_count=1, sample_rate=22050, channel_count=1, |
| 26 | + bits_per_sample=16, samples_signed=True) |
| 27 | +# attach mixer to audio playback |
| 28 | +audio.play(mixer) |
| 29 | + |
| 30 | +# open mp3 audio file |
| 31 | +audio_file = audiomp3.MP3Decoder(open("Enceladus_Hiss_NASA.mp3","rb")) |
| 32 | +# play audio file in first channel of mixer |
| 33 | +mixer.voice[0].play(audio_file, loop=True) |
| 34 | +# set mixer channel level |
| 35 | +mixer.voice[0].level = 0 |
| 36 | + |
| 37 | +# propmaker neopixel pin |
| 38 | +pixel_pin = board.D5 |
| 39 | +num_pixels = 35 |
| 40 | + |
| 41 | +pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.3, auto_write=False) |
| 42 | + |
| 43 | +# define neopixel colors |
| 44 | +RED = (255, 0, 0) |
| 45 | +BLUE = (0, 0, 255) |
| 46 | + |
| 47 | +# pulse animation |
| 48 | +pulse = Pulse(pixels, speed=0.1, color=RED, period=3) |
| 49 | + |
| 50 | +# i2c setup for rp2040 feather stemma port |
| 51 | +i2c = board.STEMMA_I2C() |
| 52 | + |
| 53 | +# rotary encoder |
| 54 | +enc0 = seesaw.Seesaw(i2c, addr=0x36) |
| 55 | +encoder0 = rotaryio.IncrementalEncoder(enc0) |
| 56 | +last_position0 = None |
| 57 | + |
| 58 | +# encoder button |
| 59 | +enc0.pin_mode(24, enc0.INPUT_PULLUP) |
| 60 | +enc_button = seesaw_io.DigitalIO(enc0, 24) |
| 61 | +enc_button_state = False |
| 62 | + |
| 63 | +# encoder neopixel |
| 64 | +pixel0 = seesaw_neopixel.NeoPixel(enc0, 6, 1) |
| 65 | +pixel0.brightness = 0.2 |
| 66 | +pixel0.fill(BLUE) |
| 67 | + |
| 68 | +# variables |
| 69 | +volume = 0 # volume |
| 70 | +pixel_level = 25 # pixel brightness for rings |
| 71 | +last_pos0 = 0 # position of the encoder |
| 72 | +ctrl_mode = 0 # control mode set with encoder |
| 73 | + |
| 74 | +while True: |
| 75 | + # run neopixel animation |
| 76 | + pulse.animate() |
| 77 | + # get encoder position |
| 78 | + pos0 = -encoder0.position |
| 79 | + |
| 80 | + # if the encoder button is pressed.. |
| 81 | + if not enc_button.value and not enc_button_state: |
| 82 | + enc_button_state = True |
| 83 | + # switch between control modes |
| 84 | + if ctrl_mode == 0: |
| 85 | + ctrl_mode = 1 |
| 86 | + else: |
| 87 | + ctrl_mode = 0 |
| 88 | + print("ctrl_mode is %d" % ctrl_mode) |
| 89 | + # button debounce |
| 90 | + if enc_button.value and enc_button_state: |
| 91 | + enc_button_state = False |
| 92 | + # if control mode is 0.. |
| 93 | + # control the volume of the white noise |
| 94 | + if ctrl_mode == 0: |
| 95 | + # encoder neopixel is blue |
| 96 | + pixel0.fill(BLUE) |
| 97 | + # if the encoder moves.. |
| 98 | + if pos0 != last_pos0: |
| 99 | + # if you increase the encoder |
| 100 | + # increase value by 0.1 |
| 101 | + # maxed out at 1 |
| 102 | + if pos0 > last_pos0: |
| 103 | + volume = volume + 0.1 |
| 104 | + if volume > 1: |
| 105 | + volume = 1 |
| 106 | + # if you decrease |
| 107 | + # decrease value by 0.1 |
| 108 | + # minimum value of 0 |
| 109 | + if pos0 < last_pos0: |
| 110 | + volume = volume - 0.1 |
| 111 | + if volume < 0: |
| 112 | + volume = 0 |
| 113 | + print(volume) |
| 114 | + # reset the position |
| 115 | + last_pos0 = pos0 |
| 116 | + # if control mode is 1.. |
| 117 | + # control the brightness of the neopixel rings |
| 118 | + # actually controlling the % of red, not brightness directly |
| 119 | + if ctrl_mode == 1: |
| 120 | + # set the encoder neopixel to red |
| 121 | + pixel0.fill(RED) |
| 122 | + # if you increase the encoder |
| 123 | + # increase value by 10 |
| 124 | + # max out at 255 |
| 125 | + if pos0 != last_pos0: |
| 126 | + if pos0 > last_pos0: |
| 127 | + pixel_level = pixel_level + 10 |
| 128 | + if pixel_level > 255: |
| 129 | + pixel_level = 255 |
| 130 | + # if you decrease the encoder |
| 131 | + # decrease value by 10 |
| 132 | + # minimum level of 25 |
| 133 | + if pos0 < last_pos0: |
| 134 | + pixel_level = pixel_level - 10 |
| 135 | + if pixel_level < 25: |
| 136 | + pixel_level = 25 |
| 137 | + print(pixel_level) |
| 138 | + # reset the position |
| 139 | + last_pos0 = pos0 |
| 140 | + # set the neopixel ring color |
| 141 | + pulse.color = (pixel_level, 0, 0) |
| 142 | + # set the audio volume |
| 143 | + mixer.voice[0].level = volume |
0 commit comments