Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow universal audio mute control and other system operations #81

Open
MLXXXp opened this issue Feb 13, 2016 · 28 comments
Open

Allow universal audio mute control and other system operations #81

MLXXXp opened this issue Feb 13, 2016 · 28 comments

Comments

@MLXXXp
Copy link
Collaborator

MLXXXp commented Feb 13, 2016

Since the Arduboy doesn't have a physical volume control or mute switch, muting the speaker has to be done through software.

EEPROM location EEPROM_AUDIO_ON_OFF has been defined and used to control whether audio is on or off when the sketch calls begin(). There is also function audio.saveOnOff() which allows a sketch to set the EEPROM based on the current state. A sketch can change the state using audio.on() or audio.off() (which doesn't alter EEPROM). The state can be checked using audio.enabled().

I assume that sketches are expected to check the state using audio.enabled() and honor it until a user changes it via a menu or other means.

Let's say a game has set audio off state and saved it to EEPROM. The user then loads a simpler sketch that hasn't implemented audio mute control but just blindly uses audio, such as only calling audio.tunes.tone(). This new sketch won't produce any sound unless the user goes back and loads a sketch that can control audio, uses it to enable audio, and then reloads the simpler sketch.

I'd like to propose a method that would address this problem:

Specify the B button as the "System Control" button. (I like the B button but, if it's preferred, another button could be chosen.) The user would hold the B button down during power up and if a second button is pressed while B is held an operation assigned to the second button would be performed. For starters, I propose that the UP button would set EEPROM to "audio enalbled" and the DOWN button would set "audio disabled". The RIGHT, LEFT and A buttons could be used later for other operations, if need be.

More specifically: In the Arduboy::begin() function, add code that checks if the B button is pressed. While it's still held, loop and check for other assigned buttons pressed, and act accordingly. When B is released, exit the loop and continue on.

For simplicity, there would be no indication that the action had been performed, so the user would just have the hold the button for a sufficient amount of time. An alternative would be to only allow one operation per power up and exit as soon as the button for it was detected and handled, so for multiple changes, multiple power ups would be required.

I've written some code to implement this but I haven't yet tested it. If it's agreed that this is a good idea, I can test it, and clean it up if necessary, then create a pull request. The code is here:
https://github.com/MLXXXp/Arduboy/tree/sys_control

Note that holding the B button alone would just stay in the loop. This is basically the same as what "safe mode" currently does, using LEFT and UP, so we could probably remove the existing safe mode code. (Besides, there's a reset button now, so safe mode probably isn't even required regardless.)

Note that my code also changes audio.save_on_off() to audio.saveOnOff() as per Arduino guidelines. I've created issue #80 for this.

@joshgoebel
Copy link
Collaborator

Oh wow, this is neat. Let me give it some thought. I think up/down works really well for audio... but you could pair it with a beep or something for "on" at least I think.

I had a whole UI for this already written but the issue is always flash space. Setting brightness is a little harder though as you need something relevant on the screen.

@joshgoebel
Copy link
Collaborator

but you could pair it with a beep or something for "on" at least I think.

Actually I think a 8x8 icon could probably be squeezed in reasonably also.

@MLXXXp
Copy link
Collaborator Author

MLXXXp commented Feb 13, 2016

but you could pair it with a beep or something for "on" at least I think.

Actually I think a 8x8 icon could probably be squeezed in reasonably also.

I considered those kinds of things but wanted to keep code size minimal. Either is doable if we can afford the space.

@joshgoebel
Copy link
Collaborator

I considered those kinds of things but wanted to keep code size minimal. Either is doable if we can afford the space.

I've cut over 4kb from the compile size over the past few months, if we can't spare an icon or two for brightness and sound we're just being silly. :-) I'd love 16x16 icons but that's a little more expensive - probably still more than reasonable though.

The brightness control can be the icon + a direct to buffer bar that just spans say 100 px in the middle of the screen. I was doing it with drawRect before but honestly that's not eve necessary, can just pick a page of the display and draw the bytes directly in a tight loop.

Same thing with icons you'd draw them direct to pages with 0 byte alignment... we could write a function and maybe share it with the logo render (depending on how that branch goes).

@joshgoebel
Copy link
Collaborator

Although I suppose if it's one mode you might need to do both on the same screen, so that would affect the design a little. There are theoretically 10-12 useful brightness levels.

@MLXXXp
Copy link
Collaborator Author

MLXXXp commented Feb 13, 2016

The brightness control can be the icon + a direct to buffer bar that just spans say 100 px in the middle of the screen.

You could have a small icon mid-screen for audio mode, and just use the invert() function to make the rest of the screen white for brightness adjustment (and the icon black).

@joshgoebel
Copy link
Collaborator

A fully on screen isn't the best thing to judge the brightness though. If there was a way to mix both the settings on as screen that would give you some more material to judge the brightness... PLUS you need something on the screen if you just hold B without up/right... something to tell you your'e in settings mode.

Now you got me wanting a flashlight mode though. :-)

@joshgoebel joshgoebel modified the milestone: 1.1 Feb 13, 2016
@joshgoebel
Copy link
Collaborator

I don't even think you need to hold B now... B gets into settings then up/down left/right changes things, then A/B saves.?

@MLXXXp
Copy link
Collaborator Author

MLXXXp commented Feb 13, 2016

PLUS you need something on the screen if you just hold B without up/right... something to tell you your'e in settings mode.

Just seeing the entire screen inverted would suffice for that, wouldn't it? Plus, you could always display an icon for the current audio state, which would change to something different if the audio mode is changed. Perhaps a music note and the same note with an X through it.

@joshgoebel
Copy link
Collaborator

Just seeing the entire screen inverted would suffice for that, wouldn't it?

Well, it's the reason Apple changed the way brightness works on the iPhone. You know what I"m talking about? You need to see a REAL screen in order to judge brightness. Showing a FULLY lit screen you're likely to turn down the brightness too low and have to come back and readjust it because there is WAY more light than there would typically be (at least for a white on black game).

Plus, you could always display an icon for the current audio state, which would change to something different if the audio mode is changed.

Yep, at the cost of two icons. Just a single icon with a 8 byte "on" "off" font would also work.

@MLXXXp
Copy link
Collaborator Author

MLXXXp commented Feb 13, 2016

I don't even think you need to hold B now... B gets into settings then up/down left/right changes things, then A/B saves.?

Currently, my code saves immediately when the action button is detected, but only if he change is required. The release of the B button just exits the scan loop.

@joshgoebel
Copy link
Collaborator

Currently, my code saves immediately when the action button is detected, but only if he change is required. The release of the B button just exits the scan loop.

Right, I'm proposing the mode be sticky.

@joshgoebel
Copy link
Collaborator

See my take:

https://github.com/yyyc514/ArduboyLib/commits/brightness

I did a lot of work on the brightness function - to mix the charge settings + contrast and let you control it all with a single value.

@MLXXXp
Copy link
Collaborator Author

MLXXXp commented Feb 13, 2016

Right, I'm proposing the mode be sticky.

This way is possible if we have visual indication. It wouldn't have been very good with a blank screen, which is why I did it my way.

@joshgoebel
Copy link
Collaborator

This way is possible if we have visual indication. It wouldn't have been very good with a blank screen, which is why I did it my way.

Yeah I understand. :)

@MLXXXp
Copy link
Collaborator Author

MLXXXp commented Feb 13, 2016

Just seeing the entire screen inverted would suffice for that, wouldn't it?

Well, it's the reason Apple changed the way brightness works on the iPhone.

Perhaps a small for() loop that fills the screen with a checkerboard pattern directly? The number and size of the squares could be set to match the number of pixels that an average game would have.

@joshgoebel
Copy link
Collaborator

Are you entirely against a simple settings screen for both audio and brightness? Then you wouldn't need any special "view" you'd see some real things on screen as you changed brightness.

@joshgoebel
Copy link
Collaborator

A checkerboard is nice, but just make that the brightness icon and slap it beside sound. :)

@MLXXXp
Copy link
Collaborator Author

MLXXXp commented Feb 13, 2016

I guess some experimentation is warranted.

@joshgoebel
Copy link
Collaborator

The original idea would be a win on it's own (sound adjust) but I think doing both sound and brightness with a little UI would be even better. :-) Just lets add a beep for "on" at the minimum. :-)

@MLXXXp
Copy link
Collaborator Author

MLXXXp commented Feb 13, 2016

So long as the "little" part is kept in mind.

@joshgoebel
Copy link
Collaborator

Again, we can't stop people front cutting stuff... if it was 1.5kb and awesome and useful... and worked for many sketches and really ambitious ones cut it, nothing we can do. We can have some sort of guide for games we might "feature" or something but other than that... super hard to keep things little.

You could even have it where holding up/down at boot turned the audio on/off with just a single key. (i.e. a nice mode and a "slim" mode that always works, hopefully)

@joshgoebel
Copy link
Collaborator

Food for thought: A lot of the nicer audio libraries are going to support volume controls, so we need to think of audio as a volume, not just on/off. If someone is using tunes then they would only have one volume level but if someone was using a more complex solution we should have a few actual volume levels - so seems like our settings should support that.

@joshgoebel
Copy link
Collaborator

That could help, as now both brightness and audio could use the same UI.

@MLXXXp
Copy link
Collaborator Author

MLXXXp commented Feb 24, 2016

Food for thought: A lot of the nicer audio libraries are going to support volume controls, so we need to think of audio as a volume, not just on/off.

I would prefer to have separate settings and controls for mute and volume. If I mute something I want it to return to the previous volume when I unmute. It's the same thing as having a separate on/off switch and volume knob on a radio, instead of a volume knob with a built in power switch which forces you to set the desired volume every time you power it on.

I don't think the kind of feature we're discussing in this issue needs to be able to adjust volume; only mute. Leave volume control up to the sketch/audio library that has volume capability. Even mute control is really only for the case of one sketch leaving the audio muted and then another sketch that used audio, but didn't implement on/off, being loaded.

We could still provide functions in the Arduboy library which allow the volume setting to be saved and read from a standardised EEPROM location, for use by sketches or audio libraries dedicated to the Arduboy. If we do this, the value saved should be from 0 to 255. Specific users of the value could abstract it to the possibly more limited volumes that they support.

@MLXXXp
Copy link
Collaborator Author

MLXXXp commented Mar 6, 2016

@yyyc514, Continuing our discussion from here

It's too bad we can't say "hold down A for settings"... but I"m not sure it's worth the space...

How about using the RGB LED to provide some feedback (which hopefully won't impact code size too much)? The RGB LED will be controlled just by setting the pins to output LOW or HIGH, not by using PWM. We'll implement your suggestion to make the mode key sticky.

  • Hold down the B button while powering up, to enter system settings mode. The blue LED is lit. Once the blue LED is on, the B button is released.
  • Press the UP button to enable audio. The blue LED is extinguished, the green LED is flashed once to indicate audio enabled and then the blue LED comes back on to indicate we're still in settings mode.
  • The DOWN button turns audio off in the same way, except the red LED is flashed instead of the green one.
  • The B button is pressed to exit settings mode. The blue LED is turned off.

I may have time tomorrow to hack at the code I've already written, to implement this, instead of you working on yours, if you wish.

This would be just for audio mute control. The whole thing could be re-worked later, if necessary, for display contrast and/or audio volume, or other stuff.

@joshgoebel
Copy link
Collaborator

How about using the RGB LED to provide some feedback

Worried more about discoverability since I plant to have a UI once you've arrived.

@MLXXXp
Copy link
Collaborator Author

MLXXXp commented Mar 6, 2016

You can't really display that the button has to be held before it's powered up 😉 (except maybe for the next time power is applied).

Or maybe put "Hold B for Settings" statically at the bottom of the boot logo screen. As long as the button was pressed before the logo animation finished, we would catch it. But this might add too much code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants