diff --git a/docs/api/audio.rst b/docs/api/audio.rst index c7e87072b28382a9205a4ae44c98f59bf5a2d4a5..c96ebffd57fedf49417d80d7281f970a5d5d8c7d 100644 --- a/docs/api/audio.rst +++ b/docs/api/audio.rst @@ -3,7 +3,9 @@ ``audio`` module ================ -(placeholder docs, to be replaced with autodocs when that's a thing) +Many of these functions are available in three variants: headphone volume, +speaker volume, and volume. If :code:`headphones_are_connected()` returns 1 +the "headphone" variant is chosen, else the "speaker" variant is chosen. .. py:function:: headset_is_connected() -> bool @@ -37,35 +39,101 @@ Note: This function uses a hardware PGA for the coarse value and software for the fine value. These two methods are as of yet not synced so that there may be a transient volume "hiccup". "p1" badges only use software - volume. The unspecified variant automatically chooses the adequate channel - (**). - -.. py:function:: headphones_adjust_volume_dB -.. py:function:: speaker_adjust_volume_dB -.. py:function:: adjust_volume_dB - -.. py:function:: headphones_get_volume_dB -.. py:function:: speaker_get_volume_dB -.. py:function:: get_volume_dB - -.. py:function:: headphones_get_mute -.. py:function:: speaker_get_mute -.. py:function:: get_mute - -.. py:function:: headphones_set_mute -.. py:function:: speaker_set_mute -.. py:function:: set_mute - -.. py:function:: headphones_set_minimum_volume_dB -.. py:function:: speaker_set_minimum_volume_dB -.. py:function:: headphones_set_maximum_volume_dB -.. py:function:: speaker_set_maximum_volume_dB - -.. py:function:: headphones_get_minimum_volume_dB -.. py:function:: speaker_get_minimum_volume_dB -.. py:function:: headphones_get_maximum_volume_dB -.. py:function:: speaker_get_maximum_volume_dB - -.. py:function:: headphones_get_volume_relative -.. py:function:: speaker_get_volume_relative -.. py:function:: get_volume_relative + volume. + +.. py:function:: headphones_adjust_volume_dB(vol_dB : float) -> float +.. py:function:: speaker_adjust_volume_dB(vol_dB : float) -> float +.. py:function:: adjust_volume_dB(vol_dB : float) -> float + + Like the :code:`audio_{headphones_/speaker_/}set_volume` family but changes + relative to last volume value. + +.. py:function:: headphones_get_volume_dB() -> float +.. py:function:: speaker_get_volume_dB() -> float +.. py:function:: get_volume_dB() -> float + + Returns volume as set with :code:`audio_{headphones/speaker}_set_volume_dB`. + +.. py:function:: headphones_get_mute() -> int +.. py:function:: speaker_get_mute() -> int +.. py:function:: get_mute() -> int + + Returns 1 if channel is muted, 0 if channel is unmuted. + +.. py:function:: headphones_set_mute(mute : int) +.. py:function:: speaker_set_mute(mute : int) +.. py:function:: set_mute(mute : int) + + Mutes (mute = 1) or unmutes (mute = 0) the specified channel. + + Note: Even if a channel is unmuted it might not play sound depending on + the return value of audio_headphone_are_connected. There is no override for + this (see HEADPHONE PORT POLICY below). + +.. py:function:: headphones_set_minimum_volume_dB(vol_dB : float) -> float +.. py:function:: speaker_set_minimum_volume_dB(vol_dB : float) -> float +.. py:function:: headphones_set_maximum_volume_dB(vol_dB : float) -> float +.. py:function:: speaker_set_maximum_volume_dB(vol_dB : float) -> float + + Set the minimum and maximum allowed volume levels for speakers and headphones + respectively. Clamps with hardware limitations. Maximum clamps below the minimum + value, minimum clamps above the maximum. Returns clamped value. + +.. py:function:: headphones_get_minimum_volume_dB() -> float +.. py:function:: speaker_get_minimum_volume_dB() -> float +.. py:function:: headphones_get_maximum_volume_dB() -> float +.. py:function:: speaker_get_maximum_volume_dB() -> float + + Returns the minimum and maximum allowed volume levels for speakers and headphones + respectively. Change with + :code:`audio_{headphones/speaker}_set_{minimum/maximum}_volume_dB`. + +.. py:function:: headphones_get_volume_relative() -> float +.. py:function:: speaker_get_volume_relative() -> float +.. py:function:: get_volume_relative() -> float + + Syntactic sugar for drawing UI: Returns channel volume in a 0..1 range, + scaled into a 0.01..1 range according to the values set with + :code:`audio_{headphones_/speaker_/}set_{maximum/minimum}_volume_` and 0 if + in a fake mute condition. + + +Headphone port policy +--------------------- + +Under normal circumstances it is an important feature to have a reliable speaker +mute when plugging in headphones. However, since the headphone port on the badge +can also be used for badge link, there are legimate cases where it is desirable to +have the speakers unmuted while a cable is plugged into the jack. + +As a person who plugs in the headphones on the tram, doesn't put them on, turns on +music to check if it's not accidentially playing on speakers and then finally puts +on headphones (temporarily, of course, intermittent checks if the speakers didn't +magically turn on are scheduled according to our general anxiety level) we wish to +make it difficult to accidentially have sound coming from the speakers. + +Our proposed logic is as follows (excluding boot conditions): + +1) Badge link TX cannot be enabled for any of the headphone jack pins without a + cable detected in the jack. This is to protect users from plugging in headphones + while badge link is active and receiving a short but potentially very loud burst + of digital data before the software can react to the state change. + +2) If the software detects that the headphone jack has changed from unplugged to + plugged it *always* turns off speakers, no exceptions. + +3) If a user wishes to TX on headphone badge link, they must confirm a warning that + having headphones plugged in may potentially cause hearing damage *every time*. + +4) If a user wishes to RX or TX on headphone badge link while playing sound on the + onboard speakers, they must confirm a warning *every time*. + +We understand that these means seem extreme, but we find them to be a sensible +default configuration to make sure people can safely operate the device without +needing to refer to a manual. + +(TX here means any state that is not constantly ~GND with whatever impedance. +While there are current limiting resistors (value TBD at the time of writing, but +presumably 100R-470R) in series with the GPIOs, they still can generate quite some +volume with standard 40Ohm-ish headphones. Ideally the analog switch will never +switch to the GPIOs without a cable plugged in.) diff --git a/docs/api/badge_link.rst b/docs/api/badge_link.rst index 565a7952a04e166e9648df75fca7ca94deb0e620..a65d296720aa85b02f26081d0d85301dd961621a 100644 --- a/docs/api/badge_link.rst +++ b/docs/api/badge_link.rst @@ -3,9 +3,36 @@ ``badge_link`` module ===================== -.. py:function:: get_active(pin_mask : int) -.. py:function:: enable(pin_mask : int) -.. py:function:: disable(pin_mask : int) +Functions that take a :code:`pin_mask` take a combination of constants from +:code:`badge_link.PIN_MASK_LINE_{IN/OUT}_{TIP/RING}` + +The GPIO indices to be used with :code:`machine.UART` are listed in +:code:`badge_link.PIN_INDEX_LINE_{OUT/IN}_{TIP/RING}`. + +Functions +--------- + +.. py:function:: get_active(pin_mask : int) -> int + + Gets active badge link ports. Returns a pin mask. + +.. py:function:: enable(pin_mask : int) -> int + + Enables badge link ports. + + Returns the output of :code:`badge_link.get_active()` after execution. + + Do NOT connect headphones to a badge link port. You might hear a ringing for + a while. Warn user. + +.. py:function:: disable(pin_mask : int) -> int + + Disables badge link ports. + + Returns the output of spio_badge_link_get_active after execution. + +Pin masks +--------- .. py:data:: PIN_MASK_LINE_IN_TIP :type: int @@ -21,6 +48,12 @@ :type: int .. py:data:: PIN_MASK_ALL :type: int + +Pin indices +----------- + +These values may vary across prototype revisions. + .. py:data:: PIN_INDEX_LINE_IN_TIP :type: int .. py:data:: PIN_INDEX_LINE_IN_RING