Arduboy Kickstarter version design discussion

(Josh Goebel) #32

Nice work on this. Would be great to see in the final production Arduboy.

0 Likes

(Scott) #33

I’ve now tried this and can say that it works nicely.

I installed the Arduino Tone Library with an updated Tone.cpp which has been modified to work with the ATmega32U4.

I wrote the following test sketch and ran it with a piezo speaker connected directly across pins A2 and A3:

#include <Tone.h>

Tone tone1, tone2;

void setup() {
  tone1.begin(A2);
  tone2.begin(A3);
}

void loop() {
  tone1.play(NOTE_C4);
  tone2.play(NOTE_E4);
  delay(2000);
  tone1.stop();
  tone1.play(NOTE_G4);
  delay(2000);
  tone2.stop();
  tone2.play(NOTE_C5);
  delay(2000);
 
  tone1.stop();
  tone2.stop();
  delay(1000);
}

Each of the two tones mixed well and sounded good. I tried a few other tone pairs and they also mixed fine.

So, I’d have to say that putting the speaker across two pins to provide mixing, as well as to provide a simple dual volume level capability, is a pretty good idea. Again, the only drawback is, if only a single pin is being used to generate audio, the other pin must be set as an output (or set as an input to mute the speaker).

0 Likes

(Chris Smith) #34

So, partly in summary - if the external hardware is configured this way, improper configuration or software usage may not produce desired outcomes. But there is no configuration or software usage that can cause hardware damage.

That seems like a fairly reasonable setup. Use it right, and you get sounds. Use it wrong, and you get silence. If you go back to using it right, you get sound, not an audio-bricked Arduboy.

Since this also provides for the option of processor-intense fast PWM sound reproduction, but also low-rate straight audio PWM, developers have a good range of options.

0 Likes

(Scott) #35

Yes, that is correct.

0 Likes

(Scott) #36

A bonus eureka thought! (verified) :smile:

I tried setting one pin to INPUT while outputting a tone on the other pin, which muted the speaker as expected.

I then tried changing the pin from input to INPUT_PULLUP, which would place an internal 20K to 50K resistor in series between the speaker and Vcc. This resulted in the tone sounding at a lower volume.

So, by placing the speaker across two pins we can use one of them to control the volume of the other, by setting the control pin as follows:

  • Mute: Set as INPUT
  • Low volume: Set as INPUT_PULLUP
  • Normal volume: Set as OUTPUT
  • High volume: Set to the opposite level (compliment) of the other pin.

There may be other useful possibilities using INPUT_PULLUP (which I haven’t yet tested):

  • A normal volume tone mixed with a low volume tone. The tone on one pin is generated by toggling the output high and low. The tone on the other pin is generated by toggling between a low output and input_pullup.

  • Two low volume tones mixed, by generating each tone by toggling between output low and input_pullup.

  • A single ??? volume tone by toggling one pin between output low and input_pullup and setting the other pin to the opposite.

  • A single ??? volume tone by toggling one pin between low and high output. The second pin is set to output low when the other is high, but set to input_pullup when the other is low

  • Other combinations and techniques?

0 Likes

Amplifier Circuit
[WIP] 4 channel Music
(Kevin) #37

Wow this thread keeps on rolling, I’m reading through this don’t have time to give detailed comments yet but I know many people have asked about the 8mhz vs 16mhz.

The plan for now is to do my best to support 16mhz by adding a voltage boost controller to bring us up to 5v so that 16mhz will be in spec

Also, I’m planning to put all the input buttons on the same port so they can all be read with one port read command.

And finally, I’ll be moving the speaker to a PWM pin, I think pin 6 was recommended?

Keep on rolling with this I’ll be trying to lock down the design by the end of July early August. Thanks guys!

1 Like

$12 Arduboy compatible system
(Scott) #38

I hope this doesn’t affect your profit margins too much, and you can make one from thin enough components.

Just keep in mind that you will still have to power the display’s VDD logic supply at 1.65V to 3.3V. So, you’ll probably need a regulator for the display, in addition to the 5V booster for the CPU.

And, as I’ve already mentioned previously, the display inputs are only tolerant of voltages up to the VDD supply voltage. Running the ATmega32U4 at 5V means its outputs used to control the display will be 5V when high. This means you will need level shifters on the display inputs: MOSI, SCLK, CS, DC and RST.

If you use a 5V booster then the technique to detect low battery, by seeing a rise in the bandgap vs. VCC, will likely not work. If battery monitoring is still desired, connecting the battery directly to an analog input pin would work if the booster output was exactly 5V with a tight tolerance, and remained so with the battery between full charge voltage and 3.4V.

Alternatively, if the display ends up being powered by a stable, accurate 3.3V regulator (such as a Micrel MIC5205), then both previously discussed battery monitoring methods could be used if the 3.3V output was connected to the CPUs AREF pin.

Only Port D could do all 7 buttons and Port F could do 6, as I summarised in this post. In the following post, @Dreamer3 argues that there may not be much value in doing this, anyway. I tend to agree. I would concentrate more on the value of the secondary functions of the pins.

Most of the following is just reiterating what I’ve said in the original post, with some input and consensus from others. Please refer to it for more details.

It would be desirable to leave pins 0/RXD1(PD2), 1/TXD1(PD3), 2/SDA(PD1), 3/SCL(PD0) and TXLED (PD5) unused and connected to pads for hacking and expanding the Arduboy or creating enhanced devices that are Arduboy software and library compatible. This rules out using Port D, leaving 6 pins on Port F.

Avoiding pins 11, 12, 13, A4, A5 if possible would help maintain compatibility with a SparkFun Pro Micro.

It’s desirable to have the start button on a pin that can generate an external interrupt to wake the unit from a low power sleep mode. It’s also desirable to have that interrupt be a standard Arduino one, so the attachInterrupt() standard library function could be used. Ruling out the above mentioned pins 0 - 3, that leaves pin 7 (int.4).

@Dreamer3 has said that he would like to see buttons A and B be interrupt capable as well. No pins on Port F can generate interrupts.

Abandoning the idea of getting all the buttons on one port, here’s how I would map the buttons:

  • Start: 7 (PE6) Arduino int.4
  • Candidates for A and B: 8 (PB4), 9 (PB5), 10 (PB6)
  • Candidates for the D-pad, after A and B are mapped:
    A0 (PF7), A1 (PF6), A2 (PF5), A3 (PF4) none can generate an interrupt.
    8 (PB4), 9 (PB5), 10 (PB6)

Unless we wanted one D-pad button to be interrupt capable, using A0 - A3 would put all the D-pad buttons on Port F, so they could all be read at once. Buttons A and B could both be read at once from Port B.

No, pin 5 (PC6) is recommended. If we wanted the dual-pin mixing and volume capabilities discussed in previous messages in this thread, the recommended pin for the other lead of the speaker is pin 12 (requiring the display reset signal to be moved to a different pin such as 13 (PC7) or 11 (PB7) ).

1 Like

(Andrew Dent) #39

+1 for added H/W functionality at the cost of doing 2x port reads for button status; a good trade-off.

0 Likes

(Josh Goebel) #40

It should be pretty obvious to most people (who stop to think about it). Unless you need every single BYTE of space, having the buttons on even say 7 ports doesn’t really matter. You only need to poll them during your event loop - and only the simplest games can really use only buttons = SINGLE_PORT type code. A lot of games need to track long/short buttons pressed and either the previous button state or a whole continuation of button states (so you can do things like fire every half second a button is held)… and as soon as you get to that point there is a lot of button management code being run in addition to just button polling. Grouping buttons smartly onto a few ports as mentioned above seems like a great plan.

Even if you argue “every byte matters”, there are MUCH easier places to trim fat from in the current Arduboy core lib than the button code. Places that require changing no hardware at all.

To me A & B make more sense to be hardware interruptible than D-PAD… I can imaging picking it up and hitting those to wake it (without knowing anything about this future start buttons or where it might live).

1 Like

(Chris Smith) #41

Definitely! I recall a reference that the PDP-8 had a chess program - with only 4K of 12 bit words. That’s one example of the type of program where you might have the Arduboy idle down while the user studies the screen, with a “press A to enter your move” prompt.

0 Likes

#42

While not a big issue, coming from gaming I would still prefer the primary buttons under the same pin for a single read. A button I think could be a prime candidate for interrupt support would be the start button if that still happens (guessing if we keep questioning between 6 & 7 buttons).

0 Likes

(Chris Smith) #43

I certainly recall games running like this on smaller 8-bit systems, but we have both 32K of program (lots), a high clock rate (lots), and minimal RAM. Getting specialized functionality out of dedicated pins strikes me as more useful, as it lets us leverage the specialized power of the ATmega32U4. Putting all buttons on a single port would help somewhat, but that strikes me as a really steep trade-off, apparently just to save a few cycles. If the plans in the works to go to 16 MHz are realized, then we will have lots of cycles.

If all the D-pad buttons could be on one port, that may help, because those buttons are typically used in closely related ways, and possibly even as an 8-way pad with chording. Even there, though, I would question the ultimate benefit. A slower processor might show some read-to-read latency, but at the the clock speeds we’re looking at - even at 8 Mhz - the delay across reading multiple ports should be very small. My rough understanding is that direct digital reads only take one cycle per port, so reading from three ports in close succession would take less than 1/2 of one millionth of a second.

Ultimately, even keeping the RX/TX pins unused (and brought out for hacking) would seem to be to be more valuable than a single port of buttons.

0 Likes

#44

A lot of older systems acted that way (and defiantly older portables like GBC/GBA, possibly GB but I never worked on it).

It’s a minor gripe but out of everything suggested it is far more relevant to what I will do or use the arduboy for anyways (which is a micro game system and nothing more).

Also a simple register read is cheap/fast but when spread across pins it will add up (if slightly) along with the fact you NEVER want to read fresh from the input and will want to use a value cashed at the start of your frame (leads to unpredictable behavior) and if the input is spread across multiple pins it will ultimately add up.

Plus I don’t expect to see people be efficient on this thing and keep to strict 8bit limits (ie variable type sizes), so that 32krom 1.5k ram (accounting for most will use the 1k vram buffer) will disappear in an instant.

Like I said, it’s a minor gripe that i’ll live with but it’s the only one really relevant to me.

0 Likes

#45

I agree that aesthetically it would feel nice to have all eight buttons on one port, and access them with a single instruction. But the NES used a parallel to serial shift register that had to be clocked eight times to read in all of the buttons - and the GameBoy used a matrix of diodes that couldn’t read them all in a single instruction either:

0 Likes

(Scott) #46

The same goes for the I2C interface: pin 2 SDA (PD1) and pin 3 SCL (PD0).

0 Likes

(Josh Goebel) #47

Adds up to a few millionths of a second, yes. For button polling or timing (for a single button or combos) one port vs even as many as 8 makes no practical difference. The only big win (at all) is saving a few bytes of flash.

0 Likes

(Andrew Dent) #48

Details from Creator on extra buttons…

0 Likes

(Scott) #49

Since @bateske has now stated that an additional Start button will not be implemented, would it be a good idea to move either the A or B button to Pin 7 (PE6) or should they both remain, as I previously suggested, on pins 8, 9 or 10?

Putting each on 8, 9 or 10 means they’re both on port B, so they could both be read at the same time.

Moving one to Pin 7 would allow easily attaching it to an interrupt using the Arduino attachInterrupt() function with int 4.

Note that pins 8, 9 and 10 can also generate interrupts but writing the code to handle them is a bit more difficult since they’re not directly supported by the Arduino libraries. I suppose functions could be added to the Arduboy library to make doing it easier.

0 Likes

(Kevin) #50

I’m digging through this today, my hope is to put all the pins on the same port so they can be read with one port read instead of the 2 it currently takes. So now I have to look if port B has 6 pins available?

0 Likes

(Kevin) #51

Went back and reading, seems like hardware interrupts is our first priority, then keeping things like serial and i2c ports open, and try to stay away from 11,12,13,A4, A5.

Now looking at the speaker port, we have a suggestion to put that on a PWM pin

0 Likes