diff --git a/adafruit_circuitplayground/bluefruit.py b/adafruit_circuitplayground/bluefruit.py new file mode 100755 index 0000000..088470d --- /dev/null +++ b/adafruit_circuitplayground/bluefruit.py @@ -0,0 +1,152 @@ +# The MIT License (MIT) +# +# Copyright (c) 2019 Kattni Rembor for Adafruit Industries +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, bluefruit 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. + +""" +`adafruit_circuitplayground.bluefruit` +==================================================== + +CircuitPython helper for Circuit Playground Bluefruit. + +* Author(s): Kattni Rembor + +Implementation Notes +-------------------- + +**Hardware:** + +* `Circuit Playground Bluefruit `_ + +""" + +import array +import math +import digitalio +import board +import audiopwmio +import audiobusio +from adafruit_circuitplayground.circuit_playground_base import CircuitPlaygroundBase + + +__version__ = "0.0.0-auto.0" +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_CircuitPlayground.git" + + +class Bluefruit(CircuitPlaygroundBase): + """Represents a single CircuitPlayground Bluefruit.""" + + _audio_out = audiopwmio.PWMAudioOut + + def __init__(self): + # Only create the cpb module member when we aren't being imported by Sphinx + if ("__module__" in dir(digitalio.DigitalInOut) and + digitalio.DigitalInOut.__module__ == "sphinx.ext.autodoc"): + return + + super().__init__() + + self._sample = None + + # Define mic/sound sensor: + self._mic = audiobusio.PDMIn(board.MICROPHONE_CLOCK, board.MICROPHONE_DATA, + sample_rate=16000, bit_depth=16) + self._samples = None + + @staticmethod + def _normalized_rms(values): + mean_values = int(sum(values) / len(values)) + return math.sqrt(sum(float(sample - mean_values) * (sample - mean_values) + for sample in values) / len(values)) + + @property + def sound_level(self): + """Obtain the sound level from the microphone (sound sensor). + + .. image :: ../docs/_static/microphone.jpg + :alt: Microphone (sound sensor) + + This example prints the sound levels. Try clapping or blowing on + the microphone to see the levels change. + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + while True: + print(cpb.sound_level) + """ + if self._sample is None: + self._samples = array.array('H', [0] * 160) + self._mic.record(self._samples, len(self._samples)) + return self._normalized_rms(self._samples) + + def loud_sound(self, sound_threshold=200): + """Utilise a loud sound as an input. + + :param int sound_threshold: Threshold sound level must exceed to return true (Default: 200) + + .. image :: ../docs/_static/microphone.jpg + :alt: Microphone (sound sensor) + + This example turns the LEDs red each time you make a loud sound. + Try clapping or blowing onto the microphone to trigger it. + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + while True: + if cpb.loud_sound(): + cpb.pixels.fill((50, 0, 0)) + else: + cpb.pixels.fill(0) + + You may find that the code is not responding how you would like. + If this is the case, you can change the loud sound threshold to + make it more or less responsive. Setting it to a higher number + means it will take a louder sound to trigger. Setting it to a + lower number will take a quieter sound to trigger. The following + example shows the threshold being set to a higher number than + the default. + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + while True: + if cpb.loud_sound(sound_threshold=300): + cpb.pixels.fill((50, 0, 0)) + else: + cpb.pixels.fill(0) + """ + + return self.sound_level > sound_threshold + + +cpb = Bluefruit() # pylint: disable=invalid-name +"""Object that is automatically created on import. + + To use, simply import it from the module: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb +""" diff --git a/adafruit_circuitplayground/circuit_playground_base.py b/adafruit_circuitplayground/circuit_playground_base.py new file mode 100755 index 0000000..16cd2c3 --- /dev/null +++ b/adafruit_circuitplayground/circuit_playground_base.py @@ -0,0 +1,1002 @@ +# The MIT License (MIT) +# +# Copyright (c) 2016 Scott Shawcroft for Adafruit Industries +# Copyright (c) 2017-2019 Kattni Rembor for Adafruit Industries +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# 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. + +# We have a lot of attributes for this complex library, as well as a lot of documentation. +# pylint: disable=too-many-instance-attributes, too-many-lines + +""" +`adafruit_circuitplayground.circuit_playground_base` +==================================================== + +CircuitPython base class for Circuit Playground. + +* `Circuit Playground Express `_ +* `Circuit Playground Bluefruit `_. + +* Author(s): Kattni Rembor, Scott Shawcroft +""" + +import math +import array +import time +import audiocore +import adafruit_lis3dh +import adafruit_thermistor +import analogio +import board +import busio +import digitalio +import neopixel +import touchio +import gamepad + + +__version__ = "0.0.0-auto.0" +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_CircuitPlayground.git" + + +class Photocell: + """Simple driver for analog photocell on the Circuit Playground Express and Bluefruit.""" + # pylint: disable=too-few-public-methods + def __init__(self, pin): + self._photocell = analogio.AnalogIn(pin) + + # TODO(tannewt): Calibrate this against another calibrated sensor. + @property + def light(self): + """Light level.""" + return self._photocell.value * 330 // (2 ** 16) + + +class CircuitPlaygroundBase: # pylint: disable=too-many-public-methods + """Circuit Playground base class.""" + + _audio_out = None + + def __init__(self): + self._a = digitalio.DigitalInOut(board.BUTTON_A) + self._a.switch_to_input(pull=digitalio.Pull.DOWN) + self._b = digitalio.DigitalInOut(board.BUTTON_B) + self._b.switch_to_input(pull=digitalio.Pull.DOWN) + self.gamepad = gamepad.GamePad(self._a, self._b) + + # Define switch: + self._switch = digitalio.DigitalInOut(board.SLIDE_SWITCH) + self._switch.switch_to_input(pull=digitalio.Pull.UP) + + # Define LEDs: + self._led = digitalio.DigitalInOut(board.D13) + self._led.switch_to_output() + self._pixels = neopixel.NeoPixel(board.NEOPIXEL, 10) + + # Define sensors: + self._temp = adafruit_thermistor.Thermistor(board.TEMPERATURE, 10000, 10000, 25, 3950) + self._light = Photocell(board.LIGHT) + + # Define touch: + # Initially, self._touches stores the pin used for a particular touch. When that touch is + # used for the first time, the pin is replaced with the corresponding TouchIn object. + # This saves a little RAM over using a separate read-only pin tuple. + # For example, after `cpx.touch_A2`, self._touches is equivalent to: + # [None, board.A1, touchio.TouchIn(board.A2), board.A3, ...] + # Slot 0 is not used (A0 is not allowed as a touch pin). + self._touches = [None, board.A1, board.A2, board.A3, board.A4, board.A5, board.A6, board.TX] + self._touch_threshold_adjustment = 0 + + # Define acceleration: + self._i2c = busio.I2C(board.ACCELEROMETER_SCL, board.ACCELEROMETER_SDA) + self._int1 = digitalio.DigitalInOut(board.ACCELEROMETER_INTERRUPT) + self._lis3dh = adafruit_lis3dh.LIS3DH_I2C(self._i2c, address=0x19, int1=self._int1) + self._lis3dh.range = adafruit_lis3dh.RANGE_8_G + + # Define audio: + self._speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE) + self._speaker_enable.switch_to_output(value=False) + self._sample = None + self._sine_wave = None + self._sine_wave_sample = None + + # Initialise tap: + self._detect_taps = 1 + self.detect_taps = 1 + + @property + def detect_taps(self): + """Configure what type of tap is detected by ``cpx.tapped``. Use ``1`` for single-tap + detection and ``2`` for double-tap detection. This does nothing without ``cpx.tapped``. + + .. image :: ../docs/_static/accelerometer.jpg + :alt: Accelerometer + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + + cpx.detect_taps = 1 + while True: + if cpx.tapped: + print("Single tap detected!") + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + cpb.detect_taps = 1 + while True: + if cpb.tapped: + print("Single tap detected!") + """ + return self._detect_taps + + @detect_taps.setter + def detect_taps(self, value): + self._detect_taps = value + if value == 1: + self._lis3dh.set_tap(value, 90, time_limit=4, time_latency=50, time_window=255) + if value == 2: + self._lis3dh.set_tap(value, 60, time_limit=10, time_latency=50, time_window=255) + + @property + def tapped(self): + """True once after a detecting a tap. Requires ``cpx.detect_taps``. + + .. image :: ../docs/_static/accelerometer.jpg + :alt: Accelerometer + + Tap the Circuit Playground once for a single-tap, or quickly tap twice for a double-tap. + + To use with Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + + cpx.detect_taps = 1 + + while True: + if cpx.tapped: + print("Single tap detected!") + + To use with Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + cpb.detect_taps = 1 + + while True: + if cpb.tapped: + print("Single tap detected!") + + To use single and double tap together, you must have a delay between them. It + will not function properly without it. This example uses both by counting a + specified number of each type of tap before moving on in the code. + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + + # Set to check for single-taps. + cpx.detect_taps = 1 + tap_count = 0 + + # We're looking for 2 single-taps before moving on. + while tap_count < 2: + if cpx.tapped: + tap_count += 1 + print("Reached 2 single-taps!") + + # Now switch to checking for double-taps + tap_count = 0 + cpx.detect_taps = 2 + + # We're looking for 2 double-taps before moving on. + while tap_count < 2: + if cpx.tapped: + tap_count += 1 + print("Reached 2 double-taps!") + print("Done.") + + """ + return self._lis3dh.tapped + + @property + def acceleration(self): + """Obtain data from the x, y and z axes. + + .. image :: ../docs/_static/accelerometer.jpg + :alt: Accelerometer + + This example prints the values. Try moving the board to see how the + printed values change. + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + + while True: + x, y, z = cpx.acceleration + print(x, y, z) + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + while True: + x, y, z = cpb.acceleration + print(x, y, z) + """ + return self._lis3dh.acceleration + + def shake(self, shake_threshold=30): + """Detect when device is shaken. + + :param int shake_threshold: The threshold shake must exceed to return true (Default: 30) + + .. image :: ../docs/_static/accelerometer.jpg + :alt: Accelerometer + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + + while True: + if cpx.shake(): + print("Shake detected!") + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + while True: + if cpb.shake(): + print("Shake detected!") + + Decreasing ``shake_threshold`` increases shake sensitivity, i.e. the code + will return a shake detected more easily with a lower ``shake_threshold``. + Increasing it causes the opposite. ``shake_threshold`` requires a minimum + value of 10 - 10 is the value when the board is not moving, therefore + anything less than 10 will erroneously report a constant shake detected. + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + + while True: + if cpx.shake(shake_threshold=20): + print("Shake detected more easily than before!") + """ + return self._lis3dh.shake(shake_threshold=shake_threshold) + + def _touch(self, i): + if not isinstance(self._touches[i], touchio.TouchIn): + # First time referenced. Get the pin from the slot for this touch + # and replace it with a TouchIn object for the pin. + self._touches[i] = touchio.TouchIn(self._touches[i]) + self._touches[i].threshold += self._touch_threshold_adjustment + return self._touches[i].value + + # We chose these verbose touch_A# names so that beginners could use it without understanding + # lists and the capital A to match the pin name. The capitalization is not strictly Python + # style, so everywhere we use these names, we whitelist the errors using: + @property + def touch_A1(self): # pylint: disable=invalid-name + """Detect touch on capacitive touch pad A1. + + .. image :: ../docs/_static/capacitive_touch_pad_A1.jpg + :alt: Capacitive touch pad A1 + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + + while True: + if cpx.touch_A1: + print('Touched pad A1') + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + while True: + if cpb.touch_A1: + print('Touched pad A1') + """ + return self._touch(1) + + @property + def touch_A2(self): # pylint: disable=invalid-name + """Detect touch on capacitive touch pad A2. + + .. image :: ../docs/_static/capacitive_touch_pad_A2.jpg + :alt: Capacitive touch pad A2 + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + + while True: + if cpx.touch_A2: + print('Touched pad A2') + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + while True: + if cpb.touch_A2: + print('Touched pad A2') + """ + return self._touch(2) + + @property + def touch_A3(self): # pylint: disable=invalid-name + """Detect touch on capacitive touch pad A3. + + .. image :: ../docs/_static/capacitive_touch_pad_A3.jpg + :alt: Capacitive touch pad A3 + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + + while True: + if cpx.touch_A3: + print('Touched pad A3') + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + while True: + if cpb.touch_A3: + print('Touched pad A3') + """ + return self._touch(3) + + @property + def touch_A4(self): # pylint: disable=invalid-name + """Detect touch on capacitive touch pad A4. + + .. image :: ../docs/_static/capacitive_touch_pad_A4.jpg + :alt: Capacitive touch pad A4 + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + + while True: + if cpx.touch_A4: + print('Touched pad A4') + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + while True: + if cpb.touch_A4: + print('Touched pad A4') + """ + return self._touch(4) + + @property + def touch_A5(self): # pylint: disable=invalid-name + """Detect touch on capacitive touch pad A5. + + .. image :: ../docs/_static/capacitive_touch_pad_A5.jpg + :alt: Capacitive touch pad A5 + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + + while True: + if cpx.touch_A5: + print('Touched pad A5') + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + while True: + if cpb.touch_A5: + print('Touched pad A5') + """ + return self._touch(5) + + @property + def touch_A6(self): # pylint: disable=invalid-name + """Detect touch on capacitive touch pad A6. + + .. image :: ../docs/_static/capacitive_touch_pad_A6.jpg + :alt: Capacitive touch pad A6 + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + + while True: + if cpx.touch_A6: + print('Touched pad A6') + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + while True: + if cpb.touch_A6: + print('Touched pad A6') + """ + return self._touch(6) + + @property + def touch_TX(self): # pylint: disable=invalid-name + """Detect touch on capacitive touch pad TX (also known as A7 on the Circuit Playground + Express) Note: can be called as ``touch_A7`` on Circuit Playground Express. + + .. image :: ../docs/_static/capacitive_touch_pad_A7.jpg + :alt: Capacitive touch pad TX + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + + while True: + if cpx.touch_A7: + print('Touched pad A7') + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + while True: + if cpb.touch_TX: + print('Touched pad TX') + """ + return self._touch(7) + + def adjust_touch_threshold(self, adjustment): + """Adjust the threshold needed to activate the capacitive touch pads. + Higher numbers make the touch pads less sensitive. + + :param int adjustment: The desired threshold increase + + .. image :: ../docs/_static/capacitive_touch_pads.jpg + :alt: Capacitive touch pads + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + + cpx.adjust_touch_threshold(200) + + while True: + if cpx.touch_A1: + print('Touched pad A1') + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + cpb.adjust_touch_threshold(200) + + while True: + if cpb.touch_A1: + print('Touched pad A1') + """ + for touch_in in self._touches: + if isinstance(touch_in, touchio.TouchIn): + touch_in.threshold += adjustment + self._touch_threshold_adjustment += adjustment + + @property + def pixels(self): + """Sequence-like object representing the ten NeoPixels around the outside + of the Circuit Playground. Each pixel is at a certain index in the sequence + as labeled below. Colors can be RGB hex like 0x110000 for red where each + two digits are a color (0xRRGGBB) or a tuple like (17, 0, 0) where (R, G, B). + Set the global brightness using any number from 0 to 1 to represent a + percentage, i.e. 0.3 sets global brightness to 30%. + + See `neopixel.NeoPixel` for more info. + + .. image :: ../docs/_static/neopixel_numbering.jpg + :alt: NeoPixel order diagram + + Here is an example that sets the first pixel green and the ninth red. + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + + cpx.pixels.brightness = 0.3 + cpx.pixels[0] = 0x003000 + cpx.pixels[9] = (30, 0, 0) + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + cpb.pixels.brightness = 0.3 + cpb.pixels[0] = 0x003000 + cpb.pixels[9] = (30, 0, 0) + + """ + return self._pixels + + @property + def button_a(self): + """``True`` when Button A is pressed. ``False`` if not. + + .. image :: ../docs/_static/button_a.jpg + :alt: Button A + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + + while True: + if cpx.button_a: + print("Button A pressed!") + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + while True: + if cpb.button_a: + print("Button A pressed!") + """ + return self._a.value + + @property + def button_b(self): + """``True`` when Button B is pressed. ``False`` if not. + + .. image :: ../docs/_static/button_b.jpg + :alt: Button B + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + + while True: + if cpx.button_b: + print("Button B pressed!") + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + while True: + if cpb.button_b: + print("Button B pressed!") + """ + return self._b.value + + @property + def were_pressed(self): + """Returns a set of the buttons that have been pressed + + .. image :: ../docs/_static/button_b.jpg + :alt: Button B + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + + while True: + print(cpx.were_pressed) + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + while True: + print(cpb.were_pressed) + """ + ret = set() + pressed = self.gamepad.get_pressed() + for button, mask in (('A', 0x01), ('B', 0x02)): + if mask & pressed: + ret.add(button) + return ret + + @property + def switch(self): + """``True`` when the switch is to the left next to the music notes. + ``False`` when it is to the right towards the ear. + + .. image :: ../docs/_static/slide_switch.jpg + :alt: Slide switch + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + import time + + while True: + print("Slide switch:", cpx.switch) + time.sleep(1) + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + import time + + while True: + print("Slide switch:", cpb.switch) + time.sleep(1) + """ + return self._switch.value + + @property + def temperature(self): + """The temperature in Celsius. + + .. image :: ../docs/_static/thermistor.jpg + :alt: Temperature sensor + + Converting this to Fahrenheit is easy! + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + import time + + while True: + temperature_c = cpx.temperature + temperature_f = temperature_c * 1.8 + 32 + print("Temperature celsius:", temperature_c) + print("Temperature fahrenheit:", temperature_f) + time.sleep(1) + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + import time + + while True: + temperature_c = cpb.temperature + temperature_f = temperature_c * 1.8 + 32 + print("Temperature celsius:", temperature_c) + print("Temperature fahrenheit:", temperature_f) + time.sleep(1) + """ + return self._temp.temperature + + @property + def light(self): + """The light level. + + .. image :: ../docs/_static/light_sensor.jpg + :alt: Light sensor + + Try covering the sensor next to the eye to see it change. + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + import time + + while True: + print("Light:", cpx.light) + time.sleep(1) + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + import time + + while True: + print("Light:", cpb.light) + time.sleep(1) + """ + return self._light.light + + @property + def red_led(self): + """The red led next to the USB plug marked D13. + + .. image :: ../docs/_static/red_led.jpg + :alt: D13 LED + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + import time + + while True: + cpx.red_led = True + time.sleep(1) + cpx.red_led = False + time.sleep(1) + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + import time + + while True: + cpb.red_led = True + time.sleep(1) + cpb.red_led = False + time.sleep(1) + """ + return self._led.value + + @red_led.setter + def red_led(self, value): + self._led.value = value + + @staticmethod + def _sine_sample(length): + tone_volume = (2 ** 15) - 1 + shift = 2 ** 15 + for i in range(length): + yield int(tone_volume * math.sin(2*math.pi*(i / length)) + shift) + + def _generate_sample(self, length=100): + if self._sample is not None: + return + self._sine_wave = array.array("H", self._sine_sample(length)) + self._sample = self._audio_out(board.SPEAKER) # pylint: disable=not-callable + self._sine_wave_sample = audiocore.RawSample(self._sine_wave) + + def play_tone(self, frequency, duration): + """ Produce a tone using the speaker. Try changing frequency to change + the pitch of the tone. + + :param int frequency: The frequency of the tone in Hz + :param float duration: The duration of the tone in seconds + + .. image :: ../docs/_static/speaker.jpg + :alt: Onboard speaker + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + + cpx.play_tone(440, 1) + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + cpb.play_tone(440, 1) + """ + # Play a tone of the specified frequency (hz). + self.start_tone(frequency) + time.sleep(duration) + self.stop_tone() + + def start_tone(self, frequency): + """ Produce a tone using the speaker. Try changing frequency to change + the pitch of the tone. + + :param int frequency: The frequency of the tone in Hz + + .. image :: ../docs/_static/speaker.jpg + :alt: Onboard speaker + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + + while True: + if cpx.button_a: + cpx.start_tone(262) + elif cpx.button_b: + cpx.start_tone(294) + else: + cpx.stop_tone() + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + while True: + if cpb.button_a: + cpb.start_tone(262) + elif cpb.button_b: + cpb.start_tone(294) + else: + cpb.stop_tone() + """ + self._speaker_enable.value = True + length = 100 + if length * frequency > 350000: + length = 350000 // frequency + self._generate_sample(length) + # Start playing a tone of the specified frequency (hz). + self._sine_wave_sample.sample_rate = int(len(self._sine_wave) * frequency) + if not self._sample.playing: + self._sample.play(self._sine_wave_sample, loop=True) + + def stop_tone(self): + """ Use with start_tone to stop the tone produced. + + .. image :: ../docs/_static/speaker.jpg + :alt: Onboard speaker + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + + while True: + if cpx.button_a: + cpx.start_tone(262) + elif cpx.button_b: + cpx.start_tone(294) + else: + cpx.stop_tone() + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + while True: + if cpb.button_a: + cpb.start_tone(262) + elif cpb.button_b: + cpb.start_tone(294) + else: + cpb.stop_tone() + """ + # Stop playing any tones. + if self._sample is not None and self._sample.playing: + self._sample.stop() + self._sample.deinit() + self._sample = None + self._speaker_enable.value = False + + def play_file(self, file_name): + """ Play a .wav file using the onboard speaker. + + :param file_name: The name of your .wav file in quotation marks including .wav + + .. image :: ../docs/_static/speaker.jpg + :alt: Onboard speaker + + To use with the Circuit Playground Express: + + .. code-block:: python + + from adafruit_circuitplayground.express import cpx + + while True: + if cpx.button_a: + cpx.play_file("laugh.wav") + elif cpx.button_b: + cpx.play_file("rimshot.wav") + + To use with the Circuit Playground Bluefruit: + + .. code-block:: python + + from adafruit_circuitplayground.bluefruit import cpb + + while True: + if cpb.button_a: + cpb.play_file("laugh.wav") + elif cpb.button_b: + cpb.play_file("rimshot.wav") + """ + # Play a specified file. + self.stop_tone() + self._speaker_enable.value = True + with self._audio_out(board.SPEAKER) as audio: # pylint: disable=not-callable + wavefile = audiocore.WaveFile(open(file_name, "rb")) + audio.play(wavefile) + while audio.playing: + pass + self._speaker_enable.value = False diff --git a/adafruit_circuitplayground/express.py b/adafruit_circuitplayground/express.py index ccfb788..43c09c2 100755 --- a/adafruit_circuitplayground/express.py +++ b/adafruit_circuitplayground/express.py @@ -1,7 +1,7 @@ # The MIT License (MIT) # # Copyright (c) 2016 Scott Shawcroft for Adafruit Industries -# Copyright (c) 2017-2018 Kattni Rembor for Adafruit Industries +# Copyright (c) 2017-2019 Kattni Rembor for Adafruit Industries # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -21,22 +21,22 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -# We have a lot of attributes for this complex library. -# pylint: disable=too-many-instance-attributes - """ `adafruit_circuitplayground.express` ==================================================== -CircuitPython driver from `CircuitPlayground Express `_. +CircuitPython helper for Circuit Playground Express. + +**Hardware:** + +* `Circuit Playground Express `_ * Author(s): Kattni Rembor, Scott Shawcroft """ -import array -import math import sys -import time +import audioio +import digitalio # pylint: disable=wrong-import-position try: lib_index = sys.path.index("/lib") # pylint: disable=invalid-name @@ -46,681 +46,33 @@ except ValueError: # Don't change sys.path if it doesn't contain "lib" or ".frozen". pass - -import adafruit_lis3dh -import adafruit_thermistor -import analogio -import audioio -try: - import audiocore -except ImportError: - audiocore = audioio -import board -import busio -import digitalio -import neopixel -import touchio -import gamepad +from adafruit_circuitplayground.circuit_playground_base import CircuitPlaygroundBase __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_CircuitPlayground.git" -class Photocell: - """Simple driver for analog photocell on the CircuitPlayground Express.""" - # pylint: disable=too-few-public-methods - def __init__(self, pin): - self._photocell = analogio.AnalogIn(pin) - - # TODO(tannewt): Calibrate this against another calibrated sensor. - @property - def light(self): - """Light level in SI Lux.""" - return self._photocell.value * 330 // (2 ** 16) - - -class Express: # pylint: disable=too-many-public-methods +class Express(CircuitPlaygroundBase): """Represents a single CircuitPlayground Express. Do not use more than one at a time.""" + + # Touch pad A7 is labeled both A7/TX on Circuit Playground Express and only TX on + # the Circuit Playground Bluefruit. It is therefore referred to as TX in the + # CircuitPlaygroundBase class, but can be used as either for Express. + touch_A7 = CircuitPlaygroundBase.touch_TX + _audio_out = audioio.AudioOut + def __init__(self): - # Only create the cpx module member when we're aren't being imported by Sphinx + # Only create the cpx module member when we aren't being imported by Sphinx if ("__module__" in dir(digitalio.DigitalInOut) and digitalio.DigitalInOut.__module__ == "sphinx.ext.autodoc"): return - self._a = digitalio.DigitalInOut(board.BUTTON_A) - self._a.switch_to_input(pull=digitalio.Pull.DOWN) - self._b = digitalio.DigitalInOut(board.BUTTON_B) - self._b.switch_to_input(pull=digitalio.Pull.DOWN) - self.gamepad = gamepad.GamePad(self._a, self._b) - - # Define switch: - self._switch = digitalio.DigitalInOut(board.SLIDE_SWITCH) - self._switch.switch_to_input(pull=digitalio.Pull.UP) - - # Define LEDs: - self._led = digitalio.DigitalInOut(board.D13) - self._led.switch_to_output() - self._pixels = neopixel.NeoPixel(board.NEOPIXEL, 10) - - # Define sensors: - self._temp = adafruit_thermistor.Thermistor(board.TEMPERATURE, 10000, 10000, 25, 3950) - self._light = Photocell(board.LIGHT) - - # Define audio: - self._speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE) - self._speaker_enable.switch_to_output(value=False) - self._sample = None - self._sine_wave = None - self._sine_wave_sample = None - - # Define touch: - # Initially, self._touches stores the pin used for a particular touch. When that touch is - # used for the first time, the pin is replaced with the corresponding TouchIn object. - # This saves a little RAM over using a separate read-only pin tuple. - # For example, after `cpx.touch_A2`, self._touches is equivalent to: - # [None, board.A1, touchio.TouchIn(board.A2), board.A3, ...] - # Slot 0 is not used (A0 is not allowed as a touch pin). - self._touches = [None, board.A1, board.A2, board.A3, board.A4, board.A5, board.A6, board.A7] - self._touch_threshold_adjustment = 0 - - # Define acceleration: - self._i2c = busio.I2C(board.ACCELEROMETER_SCL, board.ACCELEROMETER_SDA) - self._int1 = digitalio.DigitalInOut(board.ACCELEROMETER_INTERRUPT) - self._lis3dh = adafruit_lis3dh.LIS3DH_I2C(self._i2c, address=0x19, int1=self._int1) - self._lis3dh.range = adafruit_lis3dh.RANGE_8_G - - # Initialise tap: - self._detect_taps = 1 - self.detect_taps = 1 - - @property - def detect_taps(self): - """Configure what type of tap is detected by ``cpx.tapped``. Use ``1`` for single-tap - detection and ``2`` for double-tap detection. This does nothing without ``cpx.tapped``. - - .. image :: ../docs/_static/accelerometer.jpg - :alt: Accelerometer - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - - cpx.detect_taps = 1 - while True: - if cpx.tapped: - print("Single tap detected!") - """ - return self._detect_taps - - @detect_taps.setter - def detect_taps(self, value): - self._detect_taps = value - if value == 1: - self._lis3dh.set_tap(value, 90, time_limit=4, time_latency=50, time_window=255) - if value == 2: - self._lis3dh.set_tap(value, 60, time_limit=10, time_latency=50, time_window=255) - - @property - def tapped(self): - """True once after a detecting a tap. Requires ``cpx.detect_taps``. - - .. image :: ../docs/_static/accelerometer.jpg - :alt: Accelerometer - - Tap the CPX once for a single-tap, or quickly tap twice for a double-tap. - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - - cpx.detect_taps = 1 - - while True: - if cpx.tapped: - print("Single tap detected!") - - To use single and double tap together, you must have a delay between them. It - will not function properly without it. This example uses both by counting a - specified number of each type of tap before moving on in the code. - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - - # Set to check for single-taps. - cpx.detect_taps = 1 - tap_count = 0 - - # We're looking for 2 single-taps before moving on. - while tap_count < 2: - if cpx.tapped: - tap_count += 1 - print("Reached 2 single-taps!") - - # Now switch to checking for double-taps - tap_count = 0 - cpx.detect_taps = 2 - - # We're looking for 2 double-taps before moving on. - while tap_count < 2: - if cpx.tapped: - tap_count += 1 - print("Reached 2 double-taps!") - print("Done.") - - """ - return self._lis3dh.tapped - - @property - def acceleration(self): - """Obtain data from the x, y and z axes. - - .. image :: ../docs/_static/accelerometer.jpg - :alt: Accelerometer - - This example prints the values. Try moving the board to see how the - printed values change. - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - - while True: - x, y, z = cpx.acceleration - print(x, y, z) - """ - return self._lis3dh.acceleration - - def shake(self, shake_threshold=30): - """Detect when device is shaken. - - :param int shake_threshold: The threshold shake must exceed to return true (Default: 30) - - .. image :: ../docs/_static/accelerometer.jpg - :alt: Accelerometer - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - - while True: - if cpx.shake(): - print("Shake detected!") - - Decreasing ``shake_threshold`` increases shake sensitivity, i.e. the code - will return a shake detected more easily with a lower ``shake_threshold``. - Increasing it causes the opposite. ``shake_threshold`` requires a minimum - value of 10 - 10 is the value when the board is not moving, therefore - anything less than 10 will erroneously report a constant shake detected. - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - - while True: - if cpx.shake(shake_threshold=20): - print("Shake detected more easily than before!") - """ - return self._lis3dh.shake(shake_threshold=shake_threshold) - - def _touch(self, i): - if not isinstance(self._touches[i], touchio.TouchIn): - # First time referenced. Get the pin from the slot for this touch - # and replace it with a TouchIn object for the pin. - self._touches[i] = touchio.TouchIn(self._touches[i]) - self._touches[i].threshold += self._touch_threshold_adjustment - return self._touches[i].value - - # We chose these verbose touch_A# names so that beginners could use it without understanding - # lists and the capital A to match the pin name. The capitalization is not strictly Python - # style, so everywhere we use these names, we whitelist the errors using: - @property - def touch_A1(self): # pylint: disable=invalid-name - """Detect touch on capacitive touch pad A1. - - .. image :: ../docs/_static/capacitive_touch_pad_A1.jpg - :alt: Capacitive touch pad A1 - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - - while True: - if cpx.touch_A1: - print('Touched pad A1') - """ - return self._touch(1) - - @property - def touch_A2(self): # pylint: disable=invalid-name - """Detect touch on capacitive touch pad A2. - - .. image :: ../docs/_static/capacitive_touch_pad_A2.jpg - :alt: Capacitive touch pad A2 - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - - while True: - if cpx.touch_A2: - print('Touched pad A2') - """ - return self._touch(2) - - @property - def touch_A3(self): # pylint: disable=invalid-name - """Detect touch on capacitive touch pad A3. - - .. image :: ../docs/_static/capacitive_touch_pad_A3.jpg - :alt: Capacitive touch pad A3 - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - - while True: - if cpx.touch_A3: - print('Touched pad A3') - """ - return self._touch(3) - - @property - def touch_A4(self): # pylint: disable=invalid-name - """Detect touch on capacitive touch pad A4. - - .. image :: ../docs/_static/capacitive_touch_pad_A4.jpg - :alt: Capacitive touch pad A4 - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - - while True: - if cpx.touch_A4: - print('Touched pad A4') - """ - return self._touch(4) - - @property - def touch_A5(self): # pylint: disable=invalid-name - """Detect touch on capacitive touch pad A5. - - .. image :: ../docs/_static/capacitive_touch_pad_A5.jpg - :alt: Capacitive touch pad A5 - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - - while True: - if cpx.touch_A5: - print('Touched pad A5') - """ - return self._touch(5) - - @property - def touch_A6(self): # pylint: disable=invalid-name - """Detect touch on capacitive touch pad A6. - - .. image :: ../docs/_static/capacitive_touch_pad_A6.jpg - :alt: Capacitive touch pad A6 - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - - while True: - if cpx.touch_A6: - print('Touched pad A6') - """ - return self._touch(6) - - @property - def touch_A7(self): # pylint: disable=invalid-name - """Detect touch on capacitive touch pad A7. - - .. image :: ../docs/_static/capacitive_touch_pad_A7.jpg - :alt: Capacitive touch pad A7 - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - - while True: - if cpx.touch_A7: - print('Touched pad A7') - """ - return self._touch(7) - - def adjust_touch_threshold(self, adjustment): - """Adjust the threshold needed to activate the capacitive touch pads. - Higher numbers make the touch pads less sensitive. - - :param int adjustment: The desired threshold increase - - .. image :: ../docs/_static/capacitive_touch_pads.jpg - :alt: Capacitive touch pads - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - - cpx.adjust_touch_threshold(200) - - while True: - if cpx.touch_A1: - print('Touched pad A1') - """ - for touch_in in self._touches: - if isinstance(touch_in, touchio.TouchIn): - touch_in.threshold += adjustment - self._touch_threshold_adjustment += adjustment - - @property - def pixels(self): - """Sequence-like object representing the ten NeoPixels around the outside - of the CircuitPlayground. Each pixel is at a certain index in the sequence - as labeled below. Colors can be RGB hex like 0x110000 for red where each - two digits are a color (0xRRGGBB) or a tuple like (17, 0, 0) where (R, G, B). - Set the global brightness using any number from 0 to 1 to represent a - percentage, i.e. 0.3 sets global brightness to 30%. - - See `neopixel.NeoPixel` for more info. - - .. image :: ../docs/_static/neopixel_numbering.jpg - :alt: NeoPixel order diagram - - Here is an example that sets the first pixel green and the second red. - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - - cpx.pixels.brightness = 0.3 - cpx.pixels[0] = 0x003000 - cpx.pixels[9] = (30, 0, 0) - - # Wait forever. CTRL-C to quit. - while True: - pass - """ - return self._pixels - - @property - def button_a(self): - """``True`` when Button A is pressed. ``False`` if not. - - .. image :: ../docs/_static/button_a.jpg - :alt: Button A - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - - while True: - if cpx.button_a: - print("Button A pressed!") - """ - return self._a.value - - @property - def button_b(self): - """``True`` when Button B is pressed. ``False`` if not. - - .. image :: ../docs/_static/button_b.jpg - :alt: Button B - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - - while True: - if cpx.button_b: - print("Button B pressed!") - """ - return self._b.value - - @property - def were_pressed(self): - """Returns a set of the buttons that have been pressed - - .. image :: ../docs/_static/button_b.jpg - :alt: Button B - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - - while True: - print(cpx.were_pressed) - """ - ret = set() - pressed = self.gamepad.get_pressed() - for button, mask in (('A', 0x01), ('B', 0x02)): - if mask & pressed: - ret.add(button) - return ret - - @property - def switch(self): - """ - ``True`` when the switch is to the left next to the music notes. - ``False`` when it is to the right towards the ear. - - .. image :: ../docs/_static/slide_switch.jpg - :alt: Slide switch - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - import time - - while True: - print("Slide switch:", cpx.switch) - time.sleep(1) - """ - return self._switch.value - - @property - def temperature(self): - """The temperature of the CircuitPlayground in Celsius. - - .. image :: ../docs/_static/thermistor.jpg - :alt: Temperature sensor - - Converting this to Farenheit is easy! - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - import time - - while True: - temperature_c = cpx.temperature - temperature_f = temperature_c * 1.8 + 32 - print("Temperature celsius:", temperature_c) - print("Temperature fahrenheit:", temperature_f) - time.sleep(1) - """ - return self._temp.temperature - - @property - def light(self): - """The brightness of the CircuitPlayground in approximate Lux. - - .. image :: ../docs/_static/light_sensor.jpg - :alt: Light sensor - - Try covering the sensor next to the eye to see it change. - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - import time - - while True: - print("Lux:", cpx.light) - time.sleep(1) - """ - return self._light.light - - @property - def red_led(self): - """The red led next to the USB plug marked D13. - - .. image :: ../docs/_static/red_led.jpg - :alt: D13 LED - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - import time - - while True: - cpx.red_led = True - time.sleep(1) - cpx.red_led = False - time.sleep(1) - """ - return self._led.value - - @red_led.setter - def red_led(self, value): - self._led.value = value - - @staticmethod - def _sine_sample(length): - tone_volume = (2 ** 15) - 1 - shift = 2 ** 15 - for i in range(length): - yield int(tone_volume * math.sin(2*math.pi*(i / length)) + shift) - - def _generate_sample(self, length=100): - if self._sample is not None: - return - self._sine_wave = array.array("H", Express._sine_sample(length)) - if sys.implementation.version[0] >= 3: - self._sample = audioio.AudioOut(board.SPEAKER) - self._sine_wave_sample = audiocore.RawSample(self._sine_wave) - else: - raise NotImplementedError("Please use CircuitPython 3.0 or higher.") - - - def play_tone(self, frequency, duration): - """ Produce a tone using the speaker. Try changing frequency to change - the pitch of the tone. - - :param int frequency: The frequency of the tone in Hz - :param float duration: The duration of the tone in seconds - - .. image :: ../docs/_static/speaker.jpg - :alt: Onboard speaker - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - - cpx.play_tone(440, 1) - """ - # Play a tone of the specified frequency (hz). - self.start_tone(frequency) - time.sleep(duration) - self.stop_tone() - - def start_tone(self, frequency): - """ Produce a tone using the speaker. Try changing frequency to change - the pitch of the tone. - - :param int frequency: The frequency of the tone in Hz - - .. image :: ../docs/_static/speaker.jpg - :alt: Onboard speaker - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - - while True: - if cpx.button_a: - cpx.start_tone(262) - elif cpx.button_b: - cpx.start_tone(294) - else: - cpx.stop_tone() - """ - self._speaker_enable.value = True - length = 100 - if length * frequency > 350000: - length = 350000 // frequency - self._generate_sample(length) - # Start playing a tone of the specified frequency (hz). - if sys.implementation.version[0] >= 3: - self._sine_wave_sample.sample_rate = int(len(self._sine_wave) * frequency) - if not self._sample.playing: - self._sample.play(self._sine_wave_sample, loop=True) - else: - raise NotImplementedError("Please use CircuitPython 3.0 or higher.") - - def stop_tone(self): - """ Use with start_tone to stop the tone produced. - - .. image :: ../docs/_static/speaker.jpg - :alt: Onboard speaker - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - - while True: - if cpx.button_a: - cpx.start_tone(262) - elif cpx.button_b: - cpx.start_tone(294) - else: - cpx.stop_tone() - """ - # Stop playing any tones. - if self._sample is not None and self._sample.playing: - self._sample.stop() - self._sample.deinit() - self._sample = None - self._speaker_enable.value = False - - def play_file(self, file_name): - """ Play a .wav file using the onboard speaker. - - :param file_name: The name of your .wav file in quotation marks including .wav - - .. image :: ../docs/_static/speaker.jpg - :alt: Onboard speaker - - .. code-block:: python - - from adafruit_circuitplayground.express import cpx - while True: - if cpx.button_a: - cpx.play_file("laugh.wav") - elif cpx.button_b: - cpx.play_file("rimshot.wav") - """ - # Play a specified file. - self.stop_tone() - self._speaker_enable.value = True - if sys.implementation.version[0] >= 3: - with audioio.AudioOut(board.SPEAKER) as audio: - wavefile = audiocore.WaveFile(open(file_name, "rb")) - audio.play(wavefile) - while audio.playing: - pass - else: - raise NotImplementedError("Please use CircuitPython 3.0 or higher.") - self._speaker_enable.value = False + super().__init__() -cpx = Express() # pylint: disable=invalid-name +cpx = Express() # pylint: disable=invalid-name """Object that is automatically created on import. To use, simply import it from the module: diff --git a/docs/_static/microphone.jpg b/docs/_static/microphone.jpg new file mode 100644 index 0000000..1b60761 Binary files /dev/null and b/docs/_static/microphone.jpg differ diff --git a/docs/api.rst b/docs/api.rst index 2f10513..88535f9 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -1,5 +1,11 @@ .. If you created a package, create one automodule per module in the package. +.. automodule:: adafruit_circuitplayground.circuit_playground_base + :members: + +.. automodule:: adafruit_circuitplayground.bluefruit + :members: + .. automodule:: adafruit_circuitplayground.express :members: diff --git a/docs/conf.py b/docs/conf.py index 30f104d..ca0a1e2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -20,7 +20,9 @@ 'NeoPixel': ('https://circuitpython.readthedocs.io/projects/neopixel/en/latest/', None)} # Libraries we depend on but don't need for generating docs. -autodoc_mock_imports = ["board", "analogio", "digitalio", "neopixel", "adafruit_thermistor", "audioio", "touchio", "adafruit_lis3dh", "busio", "gamepad"] +autodoc_mock_imports = ["board", "analogio", "digitalio", "neopixel", "adafruit_thermistor", + "audioio", "touchio", "adafruit_lis3dh", "busio", "gamepad", "audiocore", + "audiopwmio", "audiobusio"] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates']