Part 15: Assignment #5: Bring Out the Baron!
Bring Out the Baron!It looks like me and David weren't the only ones at a bar last night! Joe's been having some success at his job - now it's my turn to make these... drinking game thingies.
(Joe seems to favor entertainment industry or entertainment-adjacent contracts from what I've seen of him so far. I looked up Baron von Schnapps and they're a... they market as a 'hip' sort of brand. Young people with perfect hair holding cocktail glasses, buncha commercials on Youku Tudou*... the works.)
*"Youku Tudou" = think YouTube, but Chinese.
There's no obvious design issues that come to mind just from looking at the board. There's two simple inputs and one XBus output (the display), so probably one MC4000 should be enough to drive it - as long as there's enough space in the code (there probably is). I'll make a prototype and see how things go.
[ ~ ]
Good news and bad news. Good news: This design works, and works really well. It's cheap (¥3 + the display), and reasonably efficient (268 power drawn per run on average).
The code is straightforward: if the point button is pressed, it adds 1 to the counter (the accumulator). If the foul button is pressed, it subtracts 2. If the counter is below 0, it sets it to 0. It updates the display and then sleeps.
Now for the bad news. Joe forwarded on an email from Team Baron (that's what the brand group calls themselves - very catchy) regarding additional specifications for the design. They want the device to go as low-power as possible. Something about a long-lasting quality or a long-lasting buzz being a planned slogan.
Before I dive into trying to rework my design, I want to make clear why this is probably a bad idea for them:
(1) This sounds like a complete stretch.
(2) Based on the simulation, it looks like your garden-variety button battery could power this thing uninterrupted for a solid day, already - so no one will notice the difference.
and, (3), this will almost certainly increase the price.
The way this'll probably end is with the balanced version and the low-power version being quoted to Team Baron - then they'll get to pick which design actually goes to the factory.
So, now for the interesting question. How do you optimize a design for low power usage?
It turns out that my simulator has a profiler built in. It's a software feature that tracks how often any given expression is run during a test of a chip. This is the profile for the existing design after a test run:
The yellow bar shows how often each instruction was used in the sim. It's really obvious which instructions were running all the time - the two tests and the instruction that updates the display. Next step: trying to figure out a way to cut down on how many instructions are used. Two possibilities come to mind:
(1) What if the first test checked if any button was being pushed, and the second test checked which? This way, the second test could be skipped if the first one comes up empty.
The catch with this is that you can't just wire both buttons into one pin - I'd have to add an OR gate or something to be able to test both signals at once.
(2) What if the display is only updated when the counter is? This one kind of feeds into (1), but the display update instruction currently runs every time the chip cycles. Cutting it out would be a really easy way to save some energy.
Will report back when I have something.
[ ~ ~ ]
This is my attempt at putting in both of the improvements I listed above. It's not perfect, but I think it's a step in the right direction (235 avg. power used vs. the old design's 268).
I did end up putting in an OR gate, so p1 (first pin tested) is now on if either button is pushed. I couldn't find a way to get the conditional flags to line up so that the 'display' instruction only runs if a button was pushed, so I ended up just having the no-button-pushed path jump to the end.
(It turns out you can put labels on the same line as an instruction.)
The new design only lets me test for [some button pressed] or [foul button pressed], so I always add 1 to the counter if a button's been pushed (most of the time, the button pressed 'll be "point" so this is more efficient as a default). If the foul button is pressed (testing p0), it then subtracts 3 ( acc + 1 - 3 = acc - 2) and then tests that the counter didn't go below 0. Then it displays.
It's a good design, but I do feel that it's not as efficient as it could be. "acc + 1 - 3 " is not the smoothest way to subtract 2 from something. On top of that... with the original design, at least three powered instructions** would run every time unit (the two tests and the display update). With this design, at least two will run every time unit (the first test and either the jump or the counter math).
The new design is more efficient, but it feels like a really smooth-running design would just have a single powered instruction (the first test), and nothing else if it turns out no buttons are being pressed. It feels like you'd need some sort of three-way test to pull it off, though - one branch for the point button, one branch for the foul button, and one branch for nothing.
I'll keep working at it, but any improvements would probably have to come from building a new design, rather than incrementally improving this one. I have a feeling.
**(slp is an instruction, but it doesn't consume any power.)
[ ~ ~ ~ ]
I owe Carl a favor.
Remember how back when I was talking about conditional execution I mentioned that tcp was a special three-way branching test? Well, Carl showed me a design pattern that looks to be really, really useful for dealing with multiple inputs. It's all based on how an input expander works. (Datasheet back here)
Basically: an input expander takes three simple I/Os and gives you a three-digit number. Each digit is either 0 or 1, and corresponds to whether the simple I/O pin associated with the digit is ON or OFF. The secret is: the three-digit number is also... a number. And with tcp, you can find out if a number is greater, lesser, or exactly the same compared to a reference value.
Carl pointed out that, as I'd noted above, my program had 3 'paths':
One path ( + in this version) for the 'foul' button.
One path ( in this version) for the 'point' button. The 'foul' button path also falls onto this path if the counter isn't below 0 (the instruction that resets the counter to 0 can't be a '' instruction 'cause then you'd 'fall through' to it after an addition and reset the counter so it has to be a '+' instruction and the below-0 test shunts onto the '' path when things are normal).
One path (+/ turned off) for when neither button is pushed.
So, if I wanted to use tcp to split execution three ways, it means that the expander's output value for "foul button pushed" would have to to be greater than the value output for "nothing's happening" (which has to go in the middle for tcp to turn off + and ), which should be greater than the output value for "point button pushed".
This is where the NOT gate comes in, feeding the expander ON when the point button is OFF. The resulting possible input states look like this:
Point button pushed = (blank)-OFF-OFF to expander = 0
Neither button pushed = (blank)-OFF-ON to expander = 1
Foul button pushed = (blank)-ON-ON to expander = 11
So, you do the tcp of the expander value with 1.
If it's 0, then it's less than 1, you get , you know the point button has been pushed, and you add and update the display.
If it's 11, then it's greater than 1, you get +, you know the foul button is pushed, and you subtract, test for below-0, and update the display.
If it's 1 exactly, then neither button is on, + and are both off, and you fall through to the only other instruction that doesn't have a conditional flag, which is the slp.
And that's how it works.
[ ~ ~ ~ ~ ]
We ended up giving Team Baron a choice between all three options:
My first design: ¥3 - 268 power
My second design: ¥4 - 235 power (88% of the original)
Carl's design: ¥5 - 170 power (63% of the original)
Guess which quote they picked?
Yup. The ¥3 version. Once again, replacement batteries are the fans' problem.
On the bright side, they did send over a lovely thank-you gift! Off to try some now.
P.S.: When me and David were out last night, the most popular drink was beer. David got some sort of rice wine he called huangjiu - and the brand he got came in an honest-to-god clay pot!! The picture below is not David's drink - I didn't have the presence of mind to take a photo - and is instead from the Internet.
The jars in the pic are apparently for aging the stuff, so getting your drink brought to you in a miniature one feels kind of like receiving a shot of fine whiskey in a shot-glass-size oaken barrel. Go figure...!