Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Quackles
Aug 11, 2018

Pixels of Light.


I became an engineer because I wanted to make things.

But after I graduated, the reality of the world caught up with me.



"That's just not something we do in this country. Not anymore."

It took me a while, but eventually I realized it was true:



I'd have to go somewhere else.



Somewhere I could do what I was meant to do.







From the twisted mind of Zach Barth comes another "Zachlike" programming game: Shenzhen I/O. In this game, the player takes on the role of an unnamed Engineer who has moved to China, to pursue a career in making things.

The game focuses on assembly-language programing - the manual contains a full spec for a simple, yet powerful assembly programming language, and the Engineer will have to program many, many microcontrollers to succeed at their job. It is notable for being a game that advertises that you need to read the manual - then reminds you again before the tutorial begins.

This LP will be a narrative LP: I'll be taking on the role of the Engineer, and narrating levels in-character (the premise is, it's the Engineer's blog about their job). Fear not - I'll do my best to explain and demystify what's going on. The Engineer might even answer questions from posters, if enough people ask interesting ones!

May you enjoy.

Table of Contents

Main Game: Shenzhen

Story: Welcome
Story: Important: Read the Manual!

Assignment #1: Security Camera (Fake)
Engineer's Corner #1: The Basics

Shenzhen Days: Why Are We Even Here?
Assignment #2: Replacement Factory Module
Engineer's Corner #2: MC Math 'n' More!

Solitaire: Please Enjoy a Game

Story: All the Parts!

Assignment #3: Pulse Generator
Engineer's Corner #3: The Pluses and Minuses of Conditional Execution

Spam: Take an Orbital Selfie!
Assignment #4: Light-Up Signs
Post-Assignment Optimization #1: Holy Crap, It Works!

Assignment #5: Bring Out the Baron!

Shenzhen Days: Saying Stuff Better
Assignment #6: Rubbish Audio Thing

Spam: Self-Driving Car Stuck In a Loop?
Assignment #7: Infrared Sensor - IMPORTANT

Story: Working Remotely
Assignment #8: Virtual Reality Buzzer
Post-Assignment Optimization #2: Building a Better Buzzer
Engineer's Corner #4: Putting It All Together

Sandbox: Prototyping New Ideas
Shenzhen Days: Things Visitors Say
Assignment #9: Little Help?

Spam: Feel the Connection and Get Ahead!
Assignment #10: Tag, You're It!

Assignment #11: Cool Dad!!!!!!!!!!!!!

Assignment #12: Device 2A27

Story: Undocumented Instruction
Assignment #13: Three Kingdoms Tokens
Engineer's Corner #5: Shen-gen I/O

Shenzhen Days: Say Cheese!
Assignment #14: Sandwich Assembler??

Assignment #15: Carbine Target Illuminator

Assignment #16: Can You Keep a Secret?? Haunted Doll Project
Story: Growing the Company - Please Read

Story: Custom Specifications
Assignment #17: Aquaponics Maintenance Robot

Spam: Incredible Opportunity - Land Rich in Rare Earths
Assignment #18: Remote Kill Switch

Assignment #19: Control Router - IMPORTANT

Assignment #20: Pocket I Ching Oracle

Shenzhen Days: The Electronics Wet Market
Assignment #21: Precision Food Scale

Story: What Is This?
Assignment #22: Cryptocurrency Deposit Terminal

Spam: Over 55% of Homes Are Infected - Is Yours?
Assignment #23: Pollution-Sensing Window

Assignment #24: Traffic Signal

Assignment #25: Meat-Based Printer
Engineer's Corner #6: The PGA33X6 Demystified

Spam: Cleanse Your Body of Harmful Nanoparticles
Assignment #26: Security Nightmare

Shenzhen Days: The Point of It All
Assignment #27: Ocean Monitoring System

Assignment #28: Spoiler-Blocking Headphones

Story: Cool Dad Is Back!
Assignment #29: Would You Believe It?

Spam: Hey Sexy..
Assignment #30: Airline Cocktail Mixer

Secret Project: Ra, Ra, Rasputin! (Part 1)
Secret Project (Part 2)
Secret Project (Coda)

Assignment #31: IMPORTANT - The Big One!
Story: An Invitation


Bonus Campaign: Avalon City

Story: Avalon City
Assignment #AC1: The Ocean's Bounty

Sun Haotian's Book Club: Beyond the Clockwork
Assignment #AC2: Handheld Timer

Spam?: A Message From SleepCubes
Assignment #AC3: Cat Feeder

Assignment #AC4: Target Practice
Story: Avalon City Events Calendar

Sun Haotian's Book Club: Against Prediction
Assignment #AC5: Harvest Time!

Assignment #AC6: Sushi Robot!
Post-Assignment Optimization #3A: Omakase 10500
Post-Assignment Optimization #3B: Omakase 12000

Assignment #AC7: Reactor Status Display

Story: Blast From the Past
Assignment #AC8: Interface

Assignment #AC9: Scaffold Printer
Spam: Turbocharge Your Brain!

Sun Haotian's Book Club: Existence Within
Assignment #AC10: Logic Board

Story: The Final Step

Coda: <NO SUBJECT>


Closing / Q&A

Quackles fucked around with this message at 03:41 on Jul 8, 2019

Adbot
ADBOT LOVES YOU

Quackles
Aug 11, 2018

Pixels of Light.


Supplementary Materials

Parts Datasheets



Client-Provided Assignment Info

Quackles fucked around with this message at 21:14 on Jul 7, 2019

Quackles
Aug 11, 2018

Pixels of Light.


Welcome

Here we go. Day 1 at Shenzhen Longteng Electronics. I’ve got a cubicle, a cool tablet with a keyboard and a camera view of the outside (no actual window, unfortunately), and a big manual binder sitting on the desk next to me.

My coworkers all checked in - by email, of course.



First off, we have Mr. Wang Yonghong, AKA The Big Boss. I strongly suspect this is the first and last time I will hear from him - unless I screw up royally, which I’m not planning to.



Next up, there's Carl Tesky, AKA ‘the other engineer’, and my next-door desk neighbor. We had a bit of a good conversation about the circumstances that collectively drove us here. I’m sure we’ll be partners-in-rhyme soon enough.



Whoa, this guy’s enthusiastic! Not shown in the email: Joe met me in person and he’s exactly as upbeat. He insisted I call him (just) Joe.

The only issue is I don’t really know what a Product Manager does - it’s not like he’s my boss, really, and his spiel suggests he’s more a wheeler and dealer than an actually, you know… manager.
I guess I’ll find out.



Ms. Lili Wu is straightforward, formal, and… I can just tell that when around her, you can feel that she’s in charge. ‘Nuff said.



David “Daiwei” Solomon - International Product Manager, whatever that means. From his email, I got the feeling that he’s a consultant - brought in to help with a “this is what Western audiences might like” outlook, maybe?

The other thing I should probably mention is that it’s pretty obvious that David is a biiiig Sinophile. The Chinese characters in his name are kind of the giveaway… among other things. To be fair, he did say I could come to him if I need help with translation requests, so things should work out fine.



Finally, we have Mr. Jie Zhang, AKA my boss. (Also Carl’s.) Like Ms. Wu, he’s very professional. More pertinently, he’s My Boss. It looks like I’ll be getting most of my work assignments from him.

That’s everyone in the vicinity of my office. All the people here seem really nice so far, and I’m excited to work with them. Of course, I probably shouldn’t make any judgements until I’ve been at Longteng a little while.

Let’s do this.

Quackles
Aug 11, 2018

Pixels of Light.


Important: Read the Manual!



It looks like Carl's got some advice for me before I start.

I’ve had a look at the book. It doesn’t seem too complicated. There’s your basic moving-data-around instructions, and add, subtract, multiply… no divide, though. Nothing too fancy. In fact, it feels bargain-basement, compared to the hardware-mapping exercises I did in school. But I guess programmable, modular microcontrollers turned out cheaper than custom silicon in this timeline.

There’s a space at the back of the manual for datasheets, but there’s only one so far: the MC4000. It’s a basic microcontroller. I was a little surprised to hear they cost 3 Yuan each— about a dollar— but apparently there’s a discount for purchasing them in bulk.
I’m a little MORE disconcerted at the specs. One register, four I/O pins - that I can deal with. But each can store only 9 lines of code…!

I wonder if I can start up a custom silicon fabrication company in my spare time.

Quackles
Aug 11, 2018

Pixels of Light.


Security Camera (Fake)



They’re starting me off easy with this fake security camera. Once you get rid of the security-camera-shaped casing, it's basically two lights. That blink. That’s it. I don't even have to hook up a motor to make it turn, or anything.

I’m a little relieved, to be honest. When Carl mentioned the last guy, I was worried I’d come up against something super-duper challenging— that I’d be following him out the door. Now, I’m a little bit skeptical...

[ ~ ]







I’ve found the design abandoned by the last guy. He even wrote, “why is this so hard? :(” in comments before bailing…!
 Carl said I was almost certain to do better than him, and I’m inclined to agree.

From what I could see, he did get the first light working — turn it off (even though it starts off), wait, turn it on, wait some more, repeat forever — but he couldn’t figure out the second light after that? Really?

[ ~~ ]





Job's done, and I’m pretty sure my predecessor was a fraud. This only took me a few minutes to finish.



It’s an auspicious beginning for me, at least. That said, things can only really go uphill from here...

Quackles fucked around with this message at 09:37 on Aug 15, 2018

Quackles
Aug 11, 2018

Pixels of Light.


Engineer’s Corner 1: The Basics

I got a lot of comments to the last post where people said that they had no idea what those screenshots I was posting were supposed to mean. I’m starting this series of posts to explain what’s going on.



These screenshots are from my chip design simulator, ConceptCAD. The labeled circles in the prototype board are inputs or outputs that I can get / send a signal to if I hook up a part to it with a wire. The green things are, you guessed it, the wires.

This chip is the MC4000 microcontroller I was talking about before, and the straight lines on its side are pins (note the labels). The MC4000 can read signals from pins or write signals to them, if I tell it to with the right instruction (and the pin is connected to something meaningful by a wire).

The space on the left of the MC4000 is for instructions. I can have up to 9 lines of code, which doesn’t sound like a lot! Spoiler: it’s really not. When a MC4000 is turned on, it will follow its programmed instructions forever in a loop.

So far, the instructions I’ve had to use are:

mov - push a value somewhere, or copy a value from one place to another
    mov value dest
    mov source dest
slp - wait for a set number of time units
    slp time



This is the MC for the power light of the fake security camera. The mov instructions in the image push a specific value out to p0, which then travels along the wire from p0 to the output that leads to the active LED.

The instructions start by telling the MC to wait six time units (slp 6). Then, by pushing 100 to p0 (mov 100 p0), I turn the LED on. I wait six more time units (slp 6) and then turn the LED off. (mov 0 p0) This repeats forever.

(As an aside, every MC4000 has to have at least one instruction that makes the part wait for a period of time - or to put it another way, every MC has to have a slp instruction somewhere in its instruction list. MCs process really fast, and if you don't add a timed wait, the chip will consume infinite power, create a black hole, and forge a new universe.

Also, if I don’t put in a slp instruction in a MC’s code, the simulator will throw an error. :P



There is one other instruction that sleeps a MC - slx - but I don’t fully understand that one yet, so we’ll talk about it later.)



A few more bits of the MC I haven’t talked about yet: the accumulator (acc for short) is a register, which is a fancy way of saying that it’s a box I can store numbers in. I could, for example:
• put the number 3 into acc (mov 3 acc),
• move a value received on the MC’s pin p1 into acc (mov p1 acc),
• push a value from acc out to pin p1 (mov acc p1),
...and so on.

There’s also several instructions that modify the value in acc, but we’ll cross that bridge when we come to it.

Finally, “state” and “power” are used while the simulation’s running, to show if the MC’s active or waiting, and also how much power it’s using (MCs draw full power when active, but not when waiting). This might get relevant if I ever get a job that needs to go easy on a device’s batteries.


That's the basics! I'll add new "Corner" posts if I run into any more concepts that might trip people up.

Quackles
Aug 11, 2018

Pixels of Light.


Shenzhen Days: Why Are We Even Here?



I’ve signed up for a mailing list for English-speaking types, about Shenzhen. I knew some of the background - how pretty much everything in the world gets made here - but the history’s new to me, though.

The interesting bit is Ms. Liu, the host, getting all existential towards the end of the email. 
She didn’t say what she thought the, uh, 'ultimate purpose' of Shenzhen was, but it’s a worthy thought. We’re pushing 9 billion, and we’re gonna hit the Earth’s resource limit sooner or later. So what’s the coal - er, I mean, goal, of continuing down this capitalist line?

I say. Even as I’m helping do it.

Carl wants to show me a dumpling shop that he says is pretty good. I’m off for now.

P.S.: Answers to Readers

Before I go, just wanted to mention that I'll try to answer any readers' questions that may pop up if I get a quiet moment.

@ally_1986: You've been to the McDonalds? How is the cheese?

Quackles
Aug 11, 2018

Pixels of Light.


Replacement Factory Module



SMASHED?

OK, sheer bloody-minded curiosity aside, it is nice to know that Longteng has its own factory floor, as opposed to leaving production to a subsidiary or partner. I suppose this way, it allows for vertical integration and also better quality control. That said, I'm running through all the ways you could get a factory part smashed in my head, and I'm torn between some sort of accident (robot having a bad day?) and the possibility of, like, some poor assembly line guy run amok in there.

I hope it was an accident.







Another super-easy-looking spec. You can't tell from the image, but the input signals are always only 0, 25, or 50 (meaning, the outputs are only 0, 50, or 100). I'm thinking all that's really necessary is a single MC that does exactly what the spec says, in order: read in the input value, multiply it by 2, and push it to the output.

In a way, this feels like on-the-job training— teaching me how to do math on a MC all over again.





They say a straight path is the shortest line between two points, and I think that accurately describes this design. At risk of sounding like a skipping CD, all it does is read in the input value, multiply it, and output it - with the unavoidable slp in there to finish the code.

...wait, is my audience going to know what a CD is? I had a friend in college who used to joke about 'broken records', but I ended up having to look up what a record was to get the joke.

Anyway, design sent off to Jie.

Quackles
Aug 11, 2018

Pixels of Light.


Engineer's Corner 2: MC Math 'n' More!

Sharp-eyed readers might have noticed that when I used mul to multiply the input value in the last post, I never specified either a destination or the other half of the equation. This is because microcontroller math works a little bit differently than doing it on your phone.

The basic rule is this: Every math instruction uses the acc register as the source, and also the place to store the result.



From one point of view, this is easy, because you don't have to worry about where you're getting one of your numbers from. From another, this can be really annoying - you have to move your value from the accumulator (acc) to wherever you wanted to use it (like p1 for output, in the last job I had to do), and that's another instruction.

Also, if you're using the accumulator as, say, a counter, and you want to do math in it, you have to do something with the value you *had* in acc so that you can do your math. You can't do math and leave acc untouched.

The other thing about MC math is that you can't divide. No, really. Here's the list of all the arithmetic instructions in the spec, with a few arithmetic-adjacent ones thrown in for good measure:


add - Add this number to the accumulator, and store the result there.
    add number
sub - Subtract this number from the accumulator, and store the result there.
    sub number
mul - Multiply this number by the number in the accumulator, and store the result there.
    mul number

No, there is no divide instruction. Dividing is a lot harder than multiplying, adding, or subtracting, computationally. So these low-level MCs don't have the option.

not - If the number in the accumulator is not 0, set it to 0. If it is already 0, set it to 100.
    not  

not is useful for logic stuff, mostly. But it does only affect the accumulator, so here it is in this list.

dgt - Get the nth digit of the number in acc and store that digit in acc. The ones digit is digit #0, the tens digit is digit #1, and the hundreds digit is digit #2.
    dgt target_digit
dst - Set the nth digit of acc to the number provided. Same positioning scheme as dgt.
    dgt target_digit new_number

dgt and dst strike me as the type of instructions a clever programmer could use in efficiency-related hacks. It's a far cry from the cool things you could do with bit-shifting instructions on the binary microcontrollers I learned on back in college, but decimalized MCs appear to be all the rage in Shenzhen, so that's what I'm using.


That's all of the math(-like) instructions. I think I've explained, like, half of the MC4000 instruction set to all of you already...!
Of course, it's not the size of the language, but what you do with it that matters.







...you know, MC Math would be a good name for a DJ, come to think of it.

Quackles
Aug 11, 2018

Pixels of Light.







Jie’s daughter is a game whiz.



I’ve been playing this for three hours now.

[ ~ ]

OK, in the interest of getting something useful done with my time, I figure I might explain the rules of Jie’s daughter’s game, and maybe a bit of strategy to go with it.


The Goal

First off: The goal is to get all the cards up to the spaces in the top. You can move cards that aren’t buried under anything, as well as stacks that are built down in alternating colors (like Solitaire).

The three cells in the top left are ‘free’ and any card can be moved there (though they’ll be used to stack the Dragons by the end of the game - see below). The flower card will fly into the top center as soon as it’s movable. And the number cards go into the three slots on the top right, sorted by color and in numerical order.


Number Cards



You can move a number card:
• Onto free cells
• Onto a card of the next number up (but not of the same color) to make a stack - you can repeat this to build up a big stack all the way up to 9.
• Onto a blank cell on the table
• Onto their spot in the top right if the previous number card of the same color is already there (this will happen automatically a lot)

You can move a stack of number cards in the same way, except it can’t go in a free cell or the top right (except one card at a time). It’s possible to move just part of a stack around, as long as you have somewhere you can set it down.

If you unearth a ‘1’ card, it will automatically fly up to a spot on the top right (as will a ‘2’ if the ‘1’ of the same color is already there.)
Cards of higher values will only automatically move to the top right if all the cards of the previous number are there already (so a 5 will only move there if all three 4s are present, for example).

You can also move a number cards to the top right manually if it qualifies to be there but the game hasn’t auto-moved it yet. Once you do this with a card, it can’t be moved back, so this is mostly an advanced strategic move.


The Dragons



‘Dragons’ are the cards with the large symbol on it. There’s four of each.

You can move the dragons:
• Onto free cells
• Onto a blank cell on the table
…and that’s it. As you might imagine, Dragons are going to be generally annoying to deal with

If all four of a Dragon are unburied (movable), you can push the button with the associated symbol (near the top center) to send those four Dragons to one of the free cells, permanently. This will lock that free cell for the rest of the game, but that’s usually an OK tradeoff.

You do need at least one free cell that is either {A} empty, or {B} has one of the Dragons you’re trying to clear away already in it, for this to work.


Strategy

Like a lot of solitaire games, this game has a ‘tipping point’ after which winning becomes pretty trivial. The trick is not getting stuck along the way.

When the game starts, you have two major goals to accomplish in the early to medium part of the game:

• Get the number cards 1-3 for each color up to the top right. This is your primary priority.
• Get one set (or more) of the Dragons out of the way. You’ll probably have to do this to accomplish the first goal.

Take a look at the tableau before you make any moves - try to see where the 1s, 2s, and 3s are, how buried they are, and how many cards you’ll need to move to get to them. Also note where the Dragons are. If any set of Dragons is near the top of the table piles, it might be worth trying to remove that set early - the same goes for if a particular set of Dragons is blocking access to a lot of 1-3s (though this might be harder depending on how far those Dragons are towards the bottom).

Once you start moving, building is your friend - but be careful if you build on piles that have a 1, 2, or 3 buried underneath them. Try to have an idea of what your plan is for moving your stack off the pile later so you can get at the number cards you’re going for.

It’s a good idea not to move Dragons willy-nilly if you don’t immediately have to get at what’s under them. An easy way to lose a game is to have Dragons locking up most of the piles and no valid moves. Removing a set of 4 Dragons from the board is almost always a good thing, though, especially if it leads to freeing a blank spot on the table.
You’ll do best if you plan which Dragons you’ll remove first and just how you’re going to get there - and in particular, you might want to favor moving number cards to free cells over Dragons, as the number card can be easier to get out later.

Once you have the 1-3s sorted out, your job becomes a lot easier - if you haven’t made a serious attempt at removing Dragons before, you should see if you can easily take out any sets now. Building stacks and moving number cards to the top right should be a lot easier as well.

Good luck!





I should probably learn to read Chinese at some point. Right now I’m stuck with cruddy machine translation. Or David.

That said: Poor Joe.




P.S.: Might as well respond to a few replies while I have the time…

Aesculus posted:

I've been to Shenzhen once, it's pretty great. The Pizza Huts are more upmarket dine-in establishments that serve steak and duck and the rollercoasters are insane.


@Aesculus - Thanks for the tip! I’ll have to check out a Pizza Hut here sometime.

Solumin posted:

I sure hope you got permission from your manager and from Legal to post source code and pictures of hardware to your personal blog. :colbert:

@Solumin - Tell you what: you don’t tell Jie, and I won’t tell Jie.

Ibblebibble posted:

Can you multiply by decimals to divide?

klafbang posted:

You don’t need decimals to be able to turn division into multiplication.

@Ibblebibble, also @klafbang - Alas, no. MCs use only integer math, from -999 to 999. Any value that would overflow or underflow will get capped at the most appropriate of those two values, so the idea to use modulo arithmetic doesn’t work… I think.


Tenebrais posted:

Programming is a fun and rewarding hobby that some people happen to make the mistake of doing as a job.

@Tenebrais - Well said! :hfive:


P.P.S: Jie said something about his daughter planning to submit the game to an app store or two

Quackles fucked around with this message at 07:29 on Aug 17, 2018

Quackles
Aug 11, 2018

Pixels of Light.


All the Parts!



Carl came by and dumped a bunch of datasheets on my desk. It’s the rest of the garden-variety parts that Longteng likes to use: two more variants of the MC#### line, some memory chips, a bunch of logic gates (one per chip casing? There’s no bulk deal? Really?) and something called a ‘Digital I/O Expander’, which apparently lets you control three 100/0 (on/off) outputs from one XBus (digital I/O) port.

I also got Carl to explain exactly what Joe does! Turns out "Product Manager" is a nice way way of saying "Sales". It explains a lot, especially Joe's super-excited attitude. He's definitely a people person.

Indirectly, this explains what David does, as well. My first guess was mostly on the money - if "Product Manager" is "Sales", then "International Product Manager" is... the same, but focusing on what Western audiences would like, I guess. I wonder what sort of stuff they'll come up with?

Anyway, back to the new parts.

Microcontrollers

The biggest present in this whole package is the MC6000. It's basically the MC4000's big brother - space for 14 lines of code (a pretty respectable amount, honestly), a second register (dat), and two extra digital I/O (XBus) pins!! It costs 5¥ a shot instead of 3¥, but it's pretty worth it.





There is one catch, though: all those arithmetic instructions I explained in the last Corner still only target acc - and there's no 'swap' instruction or anything that reverses the contents of the two registers. So using MCs for math, even MC6000s, will still be cumbersome.

There's also a variant version of the MC4000 called the MC4000X. It costs the same, but the 4000X has four digital I/O pins (x0-x3) rather than two simple (p0, p1) and two digital (x0, x1).




Memory Chips

I've got two types of memory chips available to me: the 100P-14 (read/write) and the 200P-14 (read-only). They each hold 14 values, and basically behave about like you'd expect for memory - you tell the chip where in its storage you want to read or write data, then write or read values in/out as appropriate. Both are ¥2 each.



There are a few wrinkles, though. The first is that the 100P starts blank, and you have to get data into it by writing it at runtime. Meanwhile, the 200P is set up with values in my simulator, and then its contents are fixed forever after - you can only read data out of it.



The second wrinkle is that both the 100P and 200P have "auto-incrementing address pointers". This is a nice way of saying that if you write to or read from a specific memory cell, your next read or write will automatically target the next cell in the memory chip (wrapping around, of course).

I'm not sure how useful and/or annoying this will be, so I'll give people updates once I have to use one chip or the other.


Logic Gates

There's some logic gate chips, which look like they mostly work with simple I/O (so they're using 0 for OFF (binary 0) and 100 for ON (binary 1)). They're all ¥1 each. I'm gonna let the datasheet do the talking about what exactly each one does, for the most part.





One cool thing about these chips: the AND, OR, and XOR gates have an extra output (the one with the dot) that gives the opposite value to what the gate would normally give out. It feels like it'd save on having to buy extra NOT gates to reverse outputs, at least!

I imagine these'd be useful for any sort of job where you have to play around with binary 'signal math' - stuff like "This output is ON only when these other two outputs are ON", that sort of thing.


Digital I/O Expander

So this was an animal new to me, but reading the datasheet, I can see how it could be useful. It basically lets you control (or read) 3 simple I/O signals from one digital I/O port - and I get the feeling that someday, I'll be happy to pay ¥1 for this rather than ¥3 for a new MC with two more simple I/O pins.

 

Come to think of it, you could probably use this to coordinate a series of three or more MCs together, as long as the ones on the simple I/O side were only sending one bit of information to the MC on the XBus end. I should make a note of this...


P.S: I noticed some of you had questions about the parts earlier - with this infodump, I'm feeling more prepared to answer those now!

idhrendur posted:

And these chips are really about a dollar each? From what I can recall from the datasheets of some microcontrollers I've used in the past couple years, that seems pricy for the feature set. But maybe they've got some features I haven't seen or are ultra-low power or something.

TooMuchAbstraction posted:

I'm surprised that such a simple and limited chip has two analog I/O pins. Usually you only get digital on something like this.

@idhrendur - It did seem pretty pricey to me, but you have to remember that exchange rates have been volatile over the past few years. For example, back in, say, 2018, 3¥ was about $0.45 US - but here in 2026, well... ¯\_(ツ)_/¯
On top of that, there's some benefits to these MCs that aren't obviously apparent. One is that they apparently consume next to no power while sleeping, which is pretty impressive in itself - that, and their simple I/O pins can handle and emit surprisingly high voltages for microelectronics (if provided with appropriate power sources). I have no clue how they do it.

@TooMuchAbstraction, I'm guessing my musings above about the simple I/O pins might be why the MC line is so popular. Of course, they did say on the MC4000 datasheet that popular demand had gotten them to start making the MC4000X, so I'm not entirely sure what to think...

NGDBSS posted:

Though to clarify, does this language allow for complex calls within an operation? As it stands it looks like the above operation requires a few steps, and depending on whether they can be nested or not would change what one can do.

[...to swap values] in the case of microcontrollers (such as here) there's always the XOR swap algorithm or its variants.

@NGDBSS - No nesting of instructions, unfortunately. It would be nice, but it doesn't look like MCs are much for indirection and recursion.
And XOR swap would be great if I had anything that looked like XOR, or any binary operation! I get that decimalized MCs are easier to use in some ways, but I still have to wonder how they got so popular here...

Aesculus posted:

Also does your boss know you've spent three hours on solitaire just today? :ohdear:

@Aesculus - You don't tell Jie, and I won't tell Jie. 😓

Quackles fucked around with this message at 22:56 on Aug 17, 2018

Quackles
Aug 11, 2018

Pixels of Light.


Pulse Generator









So, uh, the spec is pretty straightforward at least. But, remember when I said that I read the manual? In actuality, turns out I sort of skimmed it around the parts that had to do with conditional execution (doing stuff only when certain conditions are met).

I'm assuming it works like it does in the boards I learned on: you'd have a test instruction, then you'll jump to another part in the code depending on if that test is true or not.





This is my first prototype. The first line (teq p0 100) is the test for whether the button is being pushed or not. Normally, the next instruction jumps to the label "loop", right before the slp - but the " – " at the front of the line means that the jump is only turned on when the test is false. (The " – " flag is what makes it conditional.)
So, when the button is pushed and the test is true, the jump is disabled (as in the pic) and the pulse is sent out.

(There's also a " + " flag I could use if I wanted the jump to happen only if the test was true.)

[ ~ ]

😑

Jie took a look at the design, then sent it back. He didn't say it was wrong - he mentioned that jumping to the end was a useful design pattern for later - but he explained something I'd completely missed about MC#000 conditionals:

You can put a conditional flag in front of any instruction on a MC. Not just jumps. You can put them on data-moving instructions, math instructions... even other tests!
Whether any particular flags trigger is based on the state of the last test instruction the MC ran, no matter how long ago that was.

So I don't need to jump to the end - I can just run the test, then flag all the instructions that would send the pulse, to only run if the test is true ( + ).





Here's the final version. The pic is taken while the button isn't pressed (so the test is false, so " + " instructions are disabled).



Moral of story: Jie has high standards and part of my job is to live up to them.

Quackles fucked around with this message at 09:35 on Aug 18, 2018

Quackles
Aug 11, 2018

Pixels of Light.


Engineer's Corner 3: The Pluses and Minuses of Conditional Execution

So after that last job, I realized I needed to brush up on the part of the manual that deals with conditional execution - which means you get to hear about it too.

The way a MC works is that you can flag any line of code with either a + or a . When the power is switched on, + and – instructions are inactive (greyed out). This stays that way until you do a test instruction.



Basic Test Instructions

The MC has a few different test instructions you can use.

teq - test if two things are equal
tgt - test if the first item is greater than the second one
tlt - test if the first item is less than the second one
    teq/tgt/tlt  value_or_location  value_or_location

tcp - comparison test (special; I'll explain below)
    tcp  value_or_location  value_or_location

"value_or_location" can be a number, a register name, or a pin name, which is pretty convenient.

For most of the tests (teq, tgt, and tlt), if the test is true, + instructions turn on, and instructions turn off and go grey. If the test is false, it's the other way around: + instructions go grey and turn off, and instructions turn on.
This stays that way until you run another test.



tcp: the Three-Way Test

tcp is special, though. It compares the value of whatever's put in it, but it's got three possible outcomes - it seems like it could be good for saving lines of code.

• Item 1 < Item 2: instructions on, + instructions off
• Item 1 > Item 2: + instructions on, instructions off
• Item 1 = Item 2: Both + and instructions off!!

That last outcome is the only way you can reset a MC to the condition state it starts in when you first switch it on, by the way.

(At this point, I'd post some example code for a good use of tcp, but I honestly can't think of something that fits the bill! What I will do, though, is if it comes up in an assignment, I'll point it out and make a big point about why it's the best instruction for the job. Deal? 😁)

Quackles fucked around with this message at 09:32 on Aug 18, 2018

Quackles
Aug 11, 2018

Pixels of Light.


Take an Orbital Selfie! Trips Start at Just R89,999!



Even in our modern age, no matter how good Bayesian analysis gets, no matter how much machine learning we throw at the problem, it looks like a few spam emails will always get through.

Might as well answer reader questions while I have the time.

Carbon dioxide posted:

In your solitaire post there's a line that ends abruptly:

"• Onto a card of the next number up (but not of the same color) to make a stack - you can repeat this to build up a "

@Carbon dioxide - ...aaaa bigger stack of cards. Whoops. I've fixed my earlier post - thanks for catching that!


Aesculus posted:

On that note, where did Carl manage to find a decent dumpling shop in Shenzhen? Last time I was there the street stalls were usually all corn juice and steamed buns or Chinese barbecue meats, with some assorted other restaurants. The craziest I've seen was a noodle shop that had a giant pot with a radius of at least a meter that I swear they stuffed an entire cow carcass into and kept boiling 24/7, with a combination hot pot/sushi restaurant being a close second. They were pretty good, actually.

@Aesculus - Holy moly, the cow thing sounds amazing.
Anyway, the dumpling shop turned out to be a dumpling stall, actually. The vendor guy was also selling (imitation?) shark fin soup, too (we never got whether it was real shark or not made clear). Everything was delicious.
5 stars, would eat there again.


NGDBSS posted:

It sounds like [Jie's] taking a page out of Edsger Dijkstra's book about avoiding goto as much as possible.

@NGDBSS - You're probably right. I get the feeling Jie's been mostly throwing me easy jobs to get me ready to work on more complex projects - and sending the job back was his way of making sure I'd get introduced to MC conditionals properly.


ally_1986 posted:

I think you need to learn around 3000 - 4000 characters to read a newspaper.

Carbon dioxide posted:

Now, these are Mandarin pronounciations. In Shenzhen most people will be speaking Cantonese. They will probably understand you if you say simple things in Mandarin, [...] but they might give you strange looks, and once you get better at Chinese and start using more complicated phrases the difference might get difficult.

Oh, and the language tones. [...]
Don't accidentally call someone's mother a horse, that's rude.

I feel a lot better about not knowing Chinese.

Quackles
Aug 11, 2018

Pixels of Light.


Light-Up Signs



Looks like Joe's come up with something! I hadn't heard of the Solid Steel Gamer before today, but she seems pretty cool from her bio. Can you imagine at some live event with however many hundred of her fans holding up animated signs? That'd be pretty freakin' intimidating!

This is also notable as the first time I've had to optimize my designs for anything in particular. In this case, per Joe's hint, I'm going to try to make the signs as cheaply as possible.







Well, this is an interesting design problem. Up until now, I'd had one, or two, outputs to work with. Now I have five - and each MC only has two simple I/O pins.
Now, I could just brute-force this by throwing 3 MC4000s in there, wiring it up, and calling it a day, but the total cost would be ¥9 (or, as Carl might put it, "bloody expensive").

So: There's gotta be a cheaper way to do this.

[ ~ ]





This is my first shot at it. I noticed some interesting patterns in the output signal patterns for the sign: click-0 and click-1 are the reverse of each other, and only one of drink-0 through drink-2 are on at any given time.
Meaning: this is the perfect time to try out some of those logic gates I got access to the other day.

The left MC just drives the click outputs. It creates a simple pulse for click-0, and then the NOT gate below it reverses it to send to click-1.
The right MC is in charge of all the drink outputs. The secret here is that drink-1, arguably the most complex output of the three, is only on when drink-0 and drink-2 are off. So, the MC pushes the right output to drink-0 and drink-2 and lets an OR gate sort out the rest: normally, the OR gate would be on when either of drink-0 or drink-2 are on - but I'm using the reversed output (with the dot), so instead the OR gate is off when drink-0 or drink-2 are on, and on when they're both off.

The thing is, all those logic gates still cost money. So instead of a third MC (¥3), I've got two logic gates (¥2), for a total cost of ¥8.

I think I might be able to get it down to ¥7 if I make the left MC drive click-0 and click-1 from different output pins, and lose the NOT gate entirely. I'll have to check if the code'll fit, though.

When I mentioned this to Joe, he said, "Bet you can't get it down to ¥6!"
This is why Joe's in Sales. :rolleyes:

[ ~ ~ ]





¥7 came pretty easily - the code on the left MC does indeed fit. However, I was talking about other potential optimizations, and someone in the ChipOverflow chat room said they thought they could actually get the design down to ¥6. For real.
Of course, they went AFK without saying how to do it, and then someone else on ChipOverflow gave me an earful because I called the wires on the board ‘wires’. (Apparently they are ~🎉 “traces" 🎉~. Sigh…)

I'm going to try to take a decent shot at getting the sign to ¥6, now that I know that it's (probably) possible. And I'll keep the chat open. Whoever it was said they were gonna be back soon...

[ ~ ~ ~ ]

It's been three hours. They haven't been back. The ¥6 version really really hasn't worked out.



Here's what I figured out when trying to make the ¥6 version:

• Using two MC4000s is out, because that's ¥6 already and I have 4 pins and 5 nonidentical outputs.
• Therefore: Use a MC6000 (¥5), and one of those Digital I/O Expander things (¥1) to push output to all three drink pins from one XBus pin.

• I can't toggle the click wires on and off more than once in the MC's script or I'll eat up all my code space, so I'm gonna have to have a loop of some sort to tell how far into the cycle we are. The accumulator will be a counter for this.

• The script pulses p0 once, and pulses p1 once. Each of these times uses 3 lines each (mov 100 p#, slp 1, mov 0 p#).
• The script has four places where it tests to see if the counter is at the right value, then updates the drink pins. This uses 2 lines each time (teq acc #, + mov ### x3).
• The script also needs a line that increments acc so it works as a counter (add 1), and two lines that roll it back to 0 when it's at the maximum value (teq acc #, + mov 0 acc). That's 3 more lines.

• We have 14 lines to work with, and we've used 2 x 3 + 4 x 2 + 3 = 17.



I cannot think of any way to cut out 3 lines of code in this. Barring some sort of conditional logic epiphany, or chat guy coming back and explaining themselves, I'm calling this project done. Finished. Finito. ¥7 version it is.




For all that I spent spinning my wheels at the end there, the finished product looks pretty cool.



Anyway, MC assembly sucks and I have a headache. I'm gonna ask David what the popular drinks are in this part of China (and invite him to go get one.)

Quackles
Aug 11, 2018

Pixels of Light.


Holy Crap, It Works!

Omobono posted:

I've managed to fit everything in 14 lines
8 lines for the drinking loop, 5 lines for the clicking loop, one slp instruction at the end.

Suggestions:
I'm fairly sure you need the ACC register for the drink, but the DAT suffices for the click.
The light-up sign has a loop long exactly 10 cycles.
If you send two values before the slp instructions only the last one counts.
Why are you checking for all four cases?

THANK YOU! All four of those suggestions helped me solve it. I was able to create a ¥6 version.





Here's what's going on in all of this:

acc is still a counter, but it goes from 0 to 9 now instead of 0 to 4, and turns over every time unit instead of every 2 time units.

The first six lines manage the drink outputs. Normally, 001 (drink-0) is pushed to the expander (no tests passed - default case). However, if acc is 6 or more, 010 (drink-1) is pushed there instead and we run another test - in the final test, if acc is 7 or 8, 100 (drink-2) is pushed to overwrite the other values.

The next five lines handle the click outputs. dat is used to store 100 or 0, and the three lines in between the two mov dat p# instructions invert it. By putting it in between the two output lines, you can get the value and its inverse output in the same cycle without having to use a not gate.

Finally, add 1 increments the accumulator, but the fact that the cycle is exactly 10 time units lets me be clever. dgt 0 removes all but the last digit of the value of the accumulator - which is basically saying that it takes the accumulator modulo 10. If the accumulator is 0-9, nothing happens. If it's 10, it goes down to 0 again.

And then we have the obligatory slp.

This exercise has helped me think in assembly better. Thank you again!


P.S: A few fun facts and misc. comments:

• The new design uses about 3x as much power as the old one (496 units vs. 171 units for the ¥7 version), but replacement batteries are the fans' problem...

TooMuchAbstraction posted:

This is the kind of thing where I'd usually look into using memory chips. [...] Feed that to a digital I/O splitter and you're done...except that without an MC in the circuit there's no clock, so your animation would be crazy fast.

@TooMuchAbstraction - Good idea, but memory chips don't output automatically. There's gotta be a MC in there somewhere to pull the data. And, like you said, clock speeds.


Aesculus posted:

I hope your stomach is okay :ohdear:

🤔 What? I'm fine.

Aesculus posted:

Also fun fact: The characters on the sign (literally "add oil") is a chant/cheer that roughly works out as "Harder!" or "Faster!" or "More!" depending on context. I guess these signs are supposed to help fans cheer her on during a game?

@Aesculus - That makes sense. Maybe it's got something to do with the name of her sponsored sports drink, whatever it is.

Quackles
Aug 11, 2018

Pixels of Light.


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...!

Quackles fucked around with this message at 11:19 on Aug 21, 2018

Quackles
Aug 11, 2018

Pixels of Light.


Shenzhen Days: Saying Stuff Better



Tilly's checked in again. This episode has helped sort out a few things I kinda wondered about. Like the ¥ thing. The first time I saw that in my simulator, I was like, "wait, the region for this isn't set to Japan, is it?" (It was not.)
I almost even made a remark about it in one of my earlier posts - the Light-Up Signs one, I think - but it got dropped during a rewrite.

Also, I realize this might make me look a little bit ignorant, but one thing I did not know until I read this is that Hong Kong has its own currency. (I had thought it used the Yuan, but I guess not... it's almost certainly a history-related thing.) It's really interesting!

So, to summarize: y'all might think ¥ is only for yen, but right, y'aint. XD

Anyway, reader comments time.

whitehelm posted:

You don't need the expander for this, just hook up foul and point to p0 and p1 directly, then change the first line to "tcp p0 p1". Same three branches, no expensive extra chips.

Oof. How did we miss this?
This is one of the things that makes this job hard, actually - it's easy to optimize for just one metric (such as power), but hard to do it for two at once (like power and cost) - because it's not always easy to see when you've done all you can vs. when more is possible.


sincx posted:

This LP is extremely relevant to my current circumstances and I am subscribing to your newsletter.



Congratulations on your trip! I'm rooting for you, whatever you end up doing.

Quackles
Aug 11, 2018

Pixels of Light.


Rubbish Audio Thing



Before I say anything else, you should probably look at the spec. And the ad.







So. That's the HARMONIC MAXIMIZATION ALGORITHM. Let me be perfectly clear, based on this formula, what this thing does. It doesn’t care about the actual frequency (pitch) of the sound at all. It does only one thing:
If the sound is soft, or not too loud, it does almost nothing. But if the sound is sufficiently loud, the device makes it louder. The only difference is the increased contrast between softer sounds, and louder sounds. That is literally it. The device doesn’t do anything else.
(To be fair, though, the promoters are at least using the word 'maximization' correctly.)

Anyway, let's get to work. The first half of Carl's favor is him not having anything to do with the construction of this.

[ ~ ]





There was a grand total of one design issue with the device: all three inputs/outputs are simple I/O and there's only two simple I/O pins on a MC. This is fixable, though - since the maximize button is an on-off switch, an output expander can work as a handy simple-to-XBus converter. Aside from that, it's just a matter of turning the HARMONIC MAXIMIZATION ALGORITHM into code.

[ ~ ~ ]

Bonus: After the Baron incident (thanks @whitehelm 😅), I've decided to challenge myself and make optimized versions of my designs if I have a bit of spare time. In this case, I decided to try to write a version of the MC with as few lines of code as possible.



The revised version has the same wiring as the original, but two changes to the code:

(1) In the first version, the MC would move the audio sample to audio-out with a stop at acc if maximize was on, but move it directly out if maximize was off. This took 3 lines for the two different versions of the 'move' code.
This version always moves the sample into acc first, using only the same two lines of code to move it around.

(2) I did a bit of algebra on the HARMONIC MAXIMIZATION ALGORITHM.
(audio_in - 50) x 4 + 50 = audio_in x 4 - 50 x 4 + 50 = audio_in x 4 - 200 + 50 = audio_in x 4 - 150.
It's the same formula, but it only uses two math instructions instead of three.

That's as optimized (for lines of code) as you can get, I think. It turns out, by the way, that the revised version is slightly more power-efficient on average than the original, probably because of (2).
Time to send the design off.



...
I felt sorry for Joe when he got the Solitaire game taken off his work tablet.
I don't feel as sorry about what happened to his speakers, for some reason.

Quackles
Aug 11, 2018

Pixels of Light.


Self-Driving Car Stuck In a Loop? You May Be Entitled to a Settlement



Before I moved to China, I was never really in a position to afford a self-driving car. I guess it's a bit of a blessing in disguise, with this sort of thing going on.

I'd joke that bicycles are the way of the future, but the air quality readout on my tablet menu is telling me that that's a really bad idea, at least in Shenzhen.

The_White_Crane posted:

The best advice I heard for an English speaker emulating a Chinese "zh" was to use the sound that is in the middle of "pleasure" or "leisure". Though I expect that depends on what your particular dialect of English is.

Ibblebibble posted:

I'll be honest, I've been speaking Mandarin for ages and I've always pronounced it like somewhere between 'ts' and 'jj' in Korean. Might just be a Southeast Asia variant.

I've mostly been pronouncing it... OK, so you know how there's a 'juh' sound if you say 'Japan'? Or there can be. I've been pronouncing the 'zh' like that, maybe a little more blended with the 'en' at the end. So it's more of a... "Shen-j'h-eh-n".

I'm not exactly a linguist or anything, but so far so good.

Quackles
Aug 11, 2018

Pixels of Light.


Infrared Sensor - IMPORTANT








These jobs are getting a bit more complex. Not only do I have the sensor to deal with, there's also three other inputs that are in the form of self-contained parts: two dials and a real-time clock. (I can move the dials and the clock wherever I want on the board, at least.)
The job is complex enough that it almost looks like I'll have to use two MCs directly connected together (something I've been low-key dreading learning to set up). However, while I'm pretty sure I could direct-connect two MCs, one line in the specs means that today is not going to be that day:

"Whenever the device is armed and the sensor reads at or above a value of 20, the alarm output should be active."

And as in... AND gate!
With that in mind, here's my first attempt.



 

This is pretty straightforward, really. The upper MC turns its output on if the sensor is 20 or over. The lower MC turns its output on when the clock matches the On Time dial, and back off when the clock matches the Off Time dial. The AND gate turns on only if both MCs are on at once - and that's the cue for the alarm.

The spec strikes me as the type of job you could overthink pretty easily - mostly when it comes to the real-time clock. A logical (but painful) approach would be to make the timer MC check if the current time on the clock was between the 'on' and 'off' dials... each cycle. Which would require some extra math in case the Off dial is set to an earlier time than the On dial, like in the image.
I'm not gonna try to implement that here. I'm pretty sure this design is more efficient.

[ ~ ]

I've had another look at the design, and I realized you could probably fit the logic on these two MC4000s into a single MC6000. Let's try it out and see how it compares.





The updated design worked even better than I thought! The top four lines (which keep track of the clock) now set dat on or off instead of an output pin. From there, it's just a matter of testing whether dat is on and then if the sensor is reading heat, and moving the appropriate value to the alarm output (through an output expander, as I'm out of simple I/O ports again).

The simulator reports this version's power usage is about the same as the other (average 358 units - the original averaged 362), and I've saved ¥1.



Wait, we're becoming a defense supplier?

OK, so... I did come to China to make things. And a good number of the things I've helped make so far have been... junk, basically. And I wouldn't mind if I ended up getting jobs at Longteng that are a little less ignoble. It's just... I'm not sure I want it to turn into making just military gear or whatever.

I could have stayed in North America for that.



P.S: Here's the clock's datasheet.



I'm going to start organizing these datasheets into their own post on this blog, so people can refer to them all in one place, if they want to. I've just added the DT2415 (clock) to the list.

While we're talking about the clock, it's nice to see a few chips being made back in NA for once. Maybe I could convince 诚尚Micro to outsource production of their MCs to the USA. They could save a fortune in labor costs...! :D

Quackles fucked around with this message at 00:19 on Aug 28, 2018

Quackles
Aug 11, 2018

Pixels of Light.


Working Remotely





I do hope her car's not in a Rogue Loop or anything.

Pierzak posted:

Next stop: design a murderbot.

I know you're joking about this, but if they do actually ask me to design one, I'm quitting on the spot.

Carbon dioxide posted:

Do you have stairs in your house?

I am protected. Guess how you get to my (21st floor) apartment?
Yes, there's also an elevator.

Quackles
Aug 11, 2018

Pixels of Light.


Virtual Reality Buzzer





Ooh, this seems like a cool idea. And— man, I gotta congratulate David in person when I next see him!
Now, let's see what the specs are for this thing.







Uh-oh.
The bit with the radio seems straightforward. That's not the problem. As the datasheet says...

quote:

Reading from the C2S-RF901 when no data is available will yield a value of -999 instead of blocking until data arrives (which is typical XBus behavior). With the C2S-RF901, you can keep working while you wait for data to arrive!

What the problem is is that the buzzer isn't a straight on-off output like I expected. You have to pulse it. And 'off' packets can come in at the end of a pulse or right before the beginning of the next one, so it looks like ignoring input until the start of a new pulse is right out.

I think the best way to do this might be to join two MCs together (I knew this'd be the case sooner or later). MC #1 samples info from the radio, and sets its output pin to on or off depending on whether the buzzer is supposed to run. MC #2 pulses the buzzer whenever its input pin is on.

Seems pretty simple, when broken down. What could go wrong?

[ ~ ]



 

This is the first prototype. It behaves exactly like I described above (the tcp in the first MC lets it check for 0, 1, and -999 without having to store the value from the radio), but you might notice something strange about the second MC.
It turns out there's something I didn't know, or didn't realize, about chip timing:

Suppose you have two MCs connected two each other, by simple I/O ports. Chip #1 sends a value to Chip #2 midway through its script.
Chip #2's script is still running while Chip #1 gets its value ready to send.

Let's say Chip #2 is supposed to read the value that Chip #1 sends. If the "read data" instruction is earlier in Chip #2's script than the "write data" instruction is in Chip #1's, the write will happen after the read and the read will get the old value from the pin.

This is what happened to me while I was building the prototype. The effect was to make the buzzer start pulsing late.

 

This is what the 'nop' instructions are for in MC #2. 'nop' stands for "no operation" - literally, "do nothing". They're just there to make MC #2 wait for MC #1 to tell it what to do.
There's an unfortunate side effect of 'nop'. Unlike 'slp' instructions, 'nop' instructions do consume power at the usual rate. I'm paying electricity to have the chip stand around idle, and it shows. The simulator says the design has an average power usage of 348 units, which feels kind of high for this application.

There has to be a better design out there - but what? I'm going start by going back to the drawing board and trying to do it all with just one MC, maybe a MC6000. The script'll be a bit more complex, but it'll almost certainly be more efficient.

[ ~ ~ ]





Here's what I came up with. It's 10 lines of code, so it does need the MC6000, but the simulator says it's more efficient (284 average power - about a 20% savings over the original). Slightly cheaper, too, so that helps it as an impulse buy.

The first few lines are like MC #1 from the original prototype - testing the radio input, then setting dat to indicate whether the buzzer's on or off. acc is used to store the current state of the buzzer - it's set to 100 when the buzzer's switched on, set to 0 when it's turned off, and pulsed with the not / moved to the output the rest of the time.
I'm still not that satisfied with this design, though I can't see a good way to improve it. It looks like you do have to check the radio every cycle to be able to stop the pulses on time, and that's the real stumbling block here... right?

Let's send it out and see what response I get.



Just a note: that's David's first response, and it does work great for him 'cause he's got a quality headset. Regarding selling it to act as an accessory, David did note that some of the lower-powered VR headsets on the market might not quite be able to drive the current version's power requirements - the device needs to use at least 30% less power* to be compatible with everything. It feels like a better-optimized version is out there somewhere... but how?

*About 200 units or less, on average.

Readers, can I ask for your help with this?
(I'll post a Engineer's Corner about the ways you can wire MCs together once we get this sorted out.)

Quackles fucked around with this message at 00:19 on Aug 28, 2018

Quackles
Aug 11, 2018

Pixels of Light.


Building a Better Buzzer

Wow, thanks for your outpouring of support! It looks like there were, in all, three different 'camps' of solutions. I'll discuss each in no particular order.

And Gate Version

pumpinglemma posted:

I see a way to cut the cost and maybe the power - you could replace dat's role by p0, throw in an AND gate between p0 and p1, and switch out the MC6000 for the cheaper model.

But I certainly don't think that would give a 30% reduction.





This was a clever idea - abstracting the "pulse AND on" logic to a logic gate. It's certainly cheaper than my final solution (¥5 / 284 pwr), at ¥4 / 238 pwr (16% reduction). The fact that it still pulses every time unit is probably what keeps the MC from saving too much power, but it's pretty smart. Thanks @pumpinglemma!


The next two versions both rely on a fact I'd missed about the radio:

RichardA posted:

Hint2: The radio has an internal buffer.

Meaning, that when data comes in to the radio, you don't need to read it on the same time unit as when it shows up. The radio will hold the data in its buffer until you're ready.
I'm at least half tempted to blame the datasheet for being unclear, even though I did quote the relevant line (ft "buffer") right in my post.

With this in mind, you don't have to check the radio when a pulse is being made - just when you'd be about to make a pulse.


Buffered Radio - The Hacky Solution

I call this version The Hacky Solution because, at a certain level, it's a hack, relying on the fact that the doorbell (transmitter) always sends a 1 followed by a 0 later. This is exploited because it toggles on or off whenever any data is received, not bothering to check the packet's actual value.





While this solution is certainly efficient in both cost and power (¥3 / 146 pwr - 49% reduction), it does have the pitfall of potentially getting stuck so that the buzzer is on when the button is not being pushed (perhaps if the 'off' data packet is lost due to signal interference) with no way to get it back to normal (pressing and releasing the button won't reset it).

I don't normally make hacky solutions on the job out of respect for the intention of the specifications, but it's a cool optimization! Thanks, @Sydin and @Grayshift!


Buffered Radio - The Clean Solution





This solution is basically the same as the Hacky Solution, except it stores the data packet in acc and checks the value before pulsing (or not). This is what @RichardA was hinting at - thanks Richard! - with his hints.
The solution uses ¥3 and 176 power (38% reduction) - David is happy to hear about the improvement, and it looks like this is how it's going to go out on the market!


Reader Comments and So On

Carbon dioxide posted:

I think a much more sensible way to do this than using nops is by using the X-bus because an X-bus connection between two chips will block the reading chip until the writing chip is ready to send something. I wonder how much power it would save to take the prototype and change nothing other than making the inter-chip connection using the X-bus and removing the nops.

It's a good idea, but there's a fly in the ointment. XBus doesn't really work like simple I/O, where the data is always available after it's been written. For each XBus read, there has to be exactly associated XBus write - you can't read the same packet twice after writing it once*. And if you write a packet, there had better be someone to read it in the same time unit or the writing MC blocks and it's an error.**

So, even if you have MC #2 wait for XBus to turn on, you either have to keep sending XBus packets every time you want MC #2 to pulse - and if you send a packet during the pulse while MC #2 isn't listening, error.

*I/O Expanders don't work like this, because they don't have code and so always respond to every XBus read/write as it comes in.
**I'll explain more about this in my upcoming post.


I did think of a hybrid approach where MC #1 signals MC #2 to turn on with XBus, and then sets a simple I/O pin to tell MC #2 to stay on (or not). Of course, then, you're back to needing at least one nop to adjust the timing...



 

(In case you're wondering: ¥6, 279 avg power.)


mercenarynuker posted:

I know everyone is posting streamlined elegant solution ideas, but could we see some kind of burly, over-engineered, trashy solution to one of these as well?

Believe me, just hang around me long enough and I'll post a few of those. :P


klafbang posted:

I agree with this, and add that I also like that the "best" solution isn't shown but left as an exercise to the thread.

I'm not gonna do this every time, but the more a problem bothers me, the more likely I am to ask for help.


TooMuchAbstraction posted:

It bugs me that you can use nops to precisely align instruction execution timing across two different chips. That doesn't feel very realistic to me.

This only works 'cause they're both 诚尚Micro MCs, the chips have the same effective clock speed, and every instruction (not counting slp or XBus-I/O instructions, which we're deliberately not using) takes the same amount of time to run. I don't think I'd be able to pull it off, otherwise.

RichardA posted:

Also in the Infrared Sensor it might be possible to fit in a slp acc, with acc being the time until the sensor is armed instead of looping and checking each time-step.

I'm going to work on this and get back to you, actually. That's a good idea - the only issue is that the calculation of how long to wait vs run only needs to be done once - but there's also the consideration of how long to wait or run the first time when the device is started in the middle of an off (or on) period.

Carbon dioxide posted:

All you need to do is have your design pass a bunch of test runs.

In the words of Jie (I may be paraphrasing a bit): "There is a difference between finishing a design and finishing a design well."


BTW, here's the radio's full datasheet.



Anyone want to take any guesses on how you're supposed to pronounce "C2S-RF901", exactly?

Quackles
Aug 11, 2018

Pixels of Light.


Engineer's Corner #4: Putting It All Together

"It is a truth universally acknowledged that a MC in possession of output pins must be in want of being connected to a second."
Pride and Prejudice and Microcontrollers, revised edition (2022)

OK, I made that quote up. But sooner or later you will have to connect two MCs together. And there's two ways to do it. Both have benefits and drawbacks.

1. Simple I/O

Simple I/O pins can take values from 0 to 100 (the exact voltages vary depending on whatever variant of MCX000 you're using - my simulator abstracts away the details). Once you push a value out to a simple I/O pin, that pin stays set to that value until you reset it to something else. You can read it at your leisure. Simple, right?

There's a catch, of course, and it's got to do with timing when you push a value out to a pin. The time a chip has run after it wakes up at the start of a time step can be measured in single instructions (I'll call them "ticks"). With the exception of instructions dealing with XBus I/O, which can run long waiting for data, every instruction takes one tick to run.

So, here's the problem - this came up in the virtual reality buzzer job. If you have two chips, and Chip #2 reads from Chip #1... but Chip #2 reads at 2 ticks after wake, and Chip #1 writes at 4 ticks after wake, Chip #2 will read old data unless you make it wait for Chip #1 by padding its script with 'nop' or other instructions.

The rule is that Chip #1 writes and Chip #2 reads, Chip #2 must read after the tick where Chip #1 writes the value, or it won't work.



If you're not clear what's going on in this example, note that last tick, MC #1 wrote a new value and MC #2 read (the old) value, on the same tick. Next tick, MC #2 will read the new value successfully.


2. XBus

XBus: The industry standard for digital I/O. Sends values from -999 to 999, and can send multiple values per time unit in a handy 'packet' form. There's even a special instruction - slx - that will cause a MC to wait for I/O from an XBus port, as many time units as necessary*.

Like you'd expect, there's a catch or two to this, too. XBus is a synchronized I/O protocol, meaning: If you send a value over XBus, there must be someone on the other end to receive it, and during the same time unit, too. If there isn't, the sending MC will block and that's an error. In the same vein, if you try to read a value over XBus, and there's no one on the other end to send it during the same time unit - yep. The receiving MC will block, and that's an error too.
(Though if your reading MC is ready before your writing MC, you can just use slx to make it wait*.)





On top of that, any value can only be read once - if you read from an XBus pin twice, the MC'll assume you're getting a two-value data packet and wait to receive two separate values. This can trip you up with parts like the radio, which will only send each value in a data packet once, and then report -999 (no more data).

One more thing: If you send a value over XBus and there's more than one MC connected that can receive the value, only one of them will get it. Whoever reads first wins. (If they both read at the same time, it's anyone's guess.)

*You only need to use slx if you expect the MC to receive XBus input in a later time unit. If you're, for example, sending something out with XBus and getting a reply in the same time unit, no slx is necessary - the read will wait properly, without drawing extra power or erroring out.


In Summary:

1. Simple I/O

Perks:
• Write once, read more than once (value stays stable once you set it)
• Write and read in different time units if you want
• Multiple readers from one source is fine!

Perils:
• 0-100 ONLY!
• Must time reads to run after writes, if they happen in the same time unit.
• Because of timing issues, reading more than one value in the same time unit isn't recommended

2. XBus

Perks:
• Any value, from -999 to 999
• Wait until you receive input with slx
• Multiple values in one time unit

Perils:
• Can only read a value once - this is what lets you read multiple values in one time unit!
• If there's no one at the other end of the line (now), your circuit breaks
• There can be only one! (reader for each writer, and vice versa)
• If using slx to wake a MC, you have to do something with the value being sent or it's an error

Quackles
Aug 11, 2018

Pixels of Light.


Prototyping New Ideas




Looks like there's a generic prototyping area in the simulator! It's got access to a bunch of parts that I haven't run into in projects yet:

Bigger memory chips - 33-item variants of the 100P and 200P.
Basic I/O - Switches, buttons, dials, and LEDs.
Cool Parts! - A few extra parts that I haven't seen before: Keypads, LCD screens, and a math co-processor! (datasheets below)











I might make something with these...

VERY IMPORTANT: I'll take suggestions, but there's no guarantee I'll do any or all of 'em. My actual job comes first!

Quackles
Aug 11, 2018

Pixels of Light.


Shenzhen Days: Things Visitors Say



The word 'Communist' in 'Communist Party of China' is basically a historical artifact nowadays.


Sillyman posted:

"Cee Two Ess Arr Eff Nine Oh One".

Congratulations! I have successfully annoyed David by chanting the rhyme from the datasheet at him.

Quackles
Aug 11, 2018

Pixels of Light.


Little Help?



Ooh, this sounds like a fun project. A game controller! A low-end game controller, if Carl is to be believed, but who cares I'm finally working in the games biz

Er. (ahem) Anyway. On to the spec.






From the looks of this, this probably isn't doable with one MC alone (not enough simple I/O ports). Which is good! It'll give me a chance to practice my XBus chip-coordinating skills.

[ ~ ]



 

Not bad for a first try! As usual, cost is a priority (it seems to be that way with a lot of clients...), and all that empty space in the first MC is really making me wish that I could just use a MC4000. Sadly, I can't see any obvious way to save a pin from the first MC as long as it's responsible for getting the X and Y values. (I did try connecting both the radio's pins to the same XBus pin on the MC, but that gave me an error.)



What the design's actually doing is pretty straightforward for the 'get and send the x/y' values bit. For the next part, the MC6000 pings the small MC by the buttons, which does the calculation for the third item in the data packet and returns that on the same wire (where it gets promptly sent up the chain).

Looking at this, the ping-response architecture I've just set up... I'm inspired. I could extend this! Be right back.

[ ~ ~ ]



   

Here's the modular version. Both of its stats are worse than the original (¥8 / 262 avg power VS ¥9 / 333 avg power), but it's built so cleanly! Everything is nice, commented, discrete. The dispatcher MC4000X at the top pings the other two and gets back the X/Y values and the A/B button calculation, and sends them... and I even managed to use every port on the top MC!
(This is my first time using a MC4000X, by the way.)

This is almost certainly not going to be the version I submit to the client. But making it was refreshing; a balm for my soul.
[sigh] Anyway, back to work.

I've started to notice that, in general, the more chips I add, the greater the power usage is likely to be. I'm reconsidering my initial assessment that this job couldn't be done with just one MC - as long as the buttons (which are on/off inputs) get turned into values with an expander, I no longer have the port shortage that got me to split the design off into two MCs in the first place. I'll try making that design and see how it stacks up.

[ ~ ~ ~ ]





The masked avenger single MC6000 strikes again. The pattern I had previously noticed continues to hold true, as this version is cheaper than my original, and about as power-efficient (¥6, 264 avg power). The only downside comes to readability in the A/B calculation section, where I'm exploiting the full power of the MC's conditional flags to get the job done properly.



And that, as they say, is a wrap.



You know, there have been a lot of jobs lately where it's looked like two full MCs were the way to go - but a single MC6000 and attendants proved to be the most efficient solution. I wonder when I'm going to stop being able to use this design pattern?

By the way, David introduced me to Xiaomei. She seems really nice, kind of nerdy in her interests - when we weren't talking (when I got up to order, etc) she was chatting to David about what David says are various popular TV shows. (I have to take it on David's say-so, 'cause they were talking in Chinese.)

Quackles
Aug 11, 2018

Pixels of Light.


Feel the Connection and Get Ahead!



Honestly, I'm glad I have people in my life. Otherwise, I'd end up having to— I don't know— join a bunch of internet forums to meet people or something.


whitehelm posted:

You can get the correct outputs by sending 0 and 1 straight through, and subtracting 8 from 10 and 11, so the #button values section can be changed to...
[...]
which gets you down to 238 power.

Oh, that's clever! Thank you!


NGDBSS posted:

I'm guessing as before that you can't get too complicated with the arithmetic tester? I was most surprised to see it use regular Polish notation (with prefixed operators) rather than reverse Polish notation (with suffixed operators), but apparently that shows up in Lisp.

It doesn't look like you can chain operators, no. So you have to fish the result out of the MathMC if you want to use it in a second calculation.


Carbon dioxide posted:

For the modular design, would it matter at all to use parallel processing? That is, to have the radio listener first ping both other chips and then wait for both to return, instead of pinging one, waiting for that, pinging the other, waiting for that?

诚尚Micro MCs don't consume additional power while they're reading XBus data but haven't gotten a value yet. I think it's a sort of mini-slx. It doesn't matter for my simulator's metrics, but for a case like this (had I sent the modular design off to SleepCUBES) it probably would have been better to parallelize the design as much as possible, to speed the time between ping and data return - it might matter for a game console! 30 FPS = 33.3 ms, and I'm not sure what options 诚尚Micro offers for clock speeds in the MC4000/6000 lines (I just know there's more than one).

While we're on the subject of time, longtime readers might have noticed that the definition of a 'time unit' is a bit flexible to the simulator. To give an example from past jobs, the infrared sensor only wakes up once every 15 minutes or so! On the actual factory floor, "slp 1" gets translated into "slp amount_of_time". MCs are pretty customizable!

Quackles
Aug 11, 2018

Pixels of Light.


Tag, You're It!



I know Carl is disclaiming this, but, like the game controllers, this is a project idea I can definitely get behind. Laser tag's fun (one might even call it "AWESOME"), enjoyable, and I'm doing meaningful work making the things.








That said, boy howdy is that a big board! I might have to break my screenshots into pieces just so you can see everything. With the inputs (and output) regarding player vest state on one side, and the i/o for the player's gun state on the other, this design is screaming 'let two MC4000s handle it'.

So here goes. Let's see if we can get two separate circuits working, each with its own expander!

[ ~ ]



 

I've discovered I have a habit of making bold pronouncements about a design before I really dive in. This time, the wrinkle I wasn't expecting was mostly because I didn't read the spec as carefully as I'd intended. My prototype design had the two MCs separate - but the 'gun' MC does require the player to count as alive before it will fire. Which means the vest MC's output has to connect to the vest and the gun MC.

Aside from that, it's pretty straightforward. The vest MC checks if the 'hit' or 'respawn' inputs are active and passes the result on to 'alive' and the gun MC. The gun MC tcps and checks for 0 (reload) or 10 (fire), with 1 as the state if neither event is happening thanks to the NOT gate. (You might recognize this design pattern from the Team Baron drinking game scorekeeper.)
Anyway. If 'reload', the gun MC resets acc (used as an ammo counter). If 'fire', the MC checks the ammo counter, then 'alive', then fires the 'laser'* if all is OK. Pretty straightforward.

*The spec says 'laser', but that's just because it sounds cool. Laser tag guns don't actually use lasers - they use infrared signaling from the guns so no one shoots their eye out by laser beam.

Before I send this off, I feel obligated to make a shot at combining this into a single MC6000, just to see if I can keep the 'all-in-one' design pattern train rolling. I think I have enough pins and few enough lines of code to pull it off...

[ ~ ~ ]





I pulled it off. The logic is almost exactly the same, except 'alive' is also copied to dat so the 'gun' part of the code can check it easily. On top of that - yep, faster, better, cheaper again! The updated design is ¥8 / 290 avg power instead of ¥9 / 381 avg power.

I'm wishing Carl's friend the best of luck on this.



BTW, I noticed something interesting in my updated design. If you're hit JUST after you're firing (specifically on the time unit immediately after the gun pulse), the MC will be asleep and won't register the hit. I checked in the simulator and found it's possible to remove this design flaw by deleting the second slp and removing the conditional flag from the first one, at the cost of about 55 average power per run.

I've decided to leave it in - this is for an AWESOMEPLEX, after all, and it feels appropriate to leave this in as a 'difficult but AWESOME' technique for players to find. And I can use it if the office ever goes out for laser tag!!
Don't tell Joe and Lili, 'k?

Quackles
Aug 11, 2018

Pixels of Light.


Cool Dad!!!!!!!!!!!!!



We get it, Joe - you vape.





There's a few questionable design decisions that jump out at me already, reading this. First off: who's broadcasting the color-changing radio signals? This feels like the sort of promotional item that only lights up, or at least, in any meaningful color pattern, at Cool Dad concerts.

Second off is the interrupt requirement. The design I'm thinking about has a 'dispatcher' MC to translate radio signals, then a MC for each of the LED's pins (Red, Green, and Blue), each of which tracks the time and turns off appropriately - but just sending the pulse level and time to the individual-color MCs won't work so well, as each MC also has to be on the alert for an interrupt signal.

I'm not even sure if I can do this, with the allowed board space - though if so, it'll make for a complicated wiring diagram. I'll experiment and see what I come up with.

[ ~ ]



 

This one took me a day to sort out, and there's a lot to explain here.

The first MC is, as I'd initially planned, the dispatcher. It sends the color pulse value to each small MC on their individual XBus lines, then sends the time value to all the small MCs the same way. The small MC code was a lot harder to create, and for a while it wouldn't narrow down to 9 lines of code. (Can you imagine doing this with 3 MC6000s on the right side? Could everything even fit?)

All three small MCs have the same code, which waits for a signal, passes it on to the output (and acc for the counter), then sets up a loop that only ends if acc is 0 or p0 is on.

p0 - which connects all the MCs to one another - is the interrupt signal I mentioned above. When the dispatcher MC is receiving a new command, it sets p0 to alert MCs that are in the middle of pulsing something else. It's timed so that the dispatcher will always set p0 before the small MCs test for it - whereupon the small MCs will finish up immediately and get the XBus values. (The dispatcher then clears p0 before sending the new time so that the MCs go back to normal.)

This was a remarkably unpleasant amount of work to do, but I'm sure Joe will be happy with it.

[ ~ ~ ]

Joe wasn't happy with it. More specifically, Joe promised Cool Dad's people a maximum quote that my design doesn't actually hit. (In case you're wondering, ¥14, 1.2K avg power. Yikes!) He wants me to try and make it cheaper, if I can pull it off. How on earth am I supposed to do that?

I'll try and look at the design again. That power usage has me concerned. Maybe I can at least find a way to improve that, and that'll help?

[ ~ ~ ~ ]



 

It's still ¥14, but it only uses 447 power - and it's a lot easier to understand! The key was to only keep track of the timer once, in the dispatcher. This removes the need for an interrupt pin (the dispatcher MC has to check for radio signals every time unit anyway), and the instructions saved from sending the timer to three different MCs lets the MC6000 work to keep track of the timer in-chip.
(I do have to put the radio input in dat now to free up acc for the timer, but it's a minor change.)

The small MCs are now basically XBus-to-simple-output converters.

Now I just need a way to do away with some parts, and I can stop Joe from being nervous right outside my cubicle...

[ ~ ~ ~ ~ ]



Sometimes being too close to the problem means the answer is staring you in the face and you don't realize.

I had two simple I/O pins on the dispatcher MC that I wasn't using, so I could do away with two of the converter MCs and just send the output directly. Hey presto - ¥8, 377 avg power. And the one-MC6000-and-attendants train rides again!

Now time to get this job out of here.



...... all that work and ......


I have come to the conclusion that whenever Joe pitches a product, it will be a piece of overcomplicated kitsch at best, and a boondoggle like this at worst.
Sadly, I still have to listen to the guy. :nsamad:

Quackles
Aug 11, 2018

Pixels of Light.


Device 2A27





Wow, another day, another email, huh. I can't say I've ever seen anything like this before.
I wonder what it wants?







OK, so two or three things leap out at me, looking at this. The first is that Poseidon-whoever has left just enough detail in the specs to intrigue me as to what on earth this is supposed to be used for. What does 'flux point' even mean in this context? The second thing I can see, which should make things easier, is that the state space appears to be composed of two areas added together - the left-right vertical bars, worth 30, and the square near the center, worth 50.

This neatly fits into the third thing, which is that I have two simple inputs and one simple output, and none of them are expander-compatible this time. So I'll have to use at least two MCs. Probably one to determine the vertical bars, then a second (attached to it) to test for the square and pass the result on.

[ ~ ]



 

Before I say anything else, let's be clear: this prototype doesn't work. I'm still working out the kinks, and one of them is that MC that checks the square part (currently the second MC in line) does need to check the 'x' coordinate as well as the 'y' coordinate. (I thought it didn't - that's how we got the picture above.)

So, seeing as the second MC has its simple I/O pins full already (one with the y-coord and one with the output), it looks like I'll have to get MC #1 to pass the x-coord value along by XBus if I want to use it there. The only complicated part is that it might have to pass the x-coord more than once - there's more than one test that uses the coordinate, after all (40 ≤ x < 80).

[ ~ ~ ]



 

I have a dilemma. The above is what I came up with. I know it'll work - the first MC passes the x-coordinate along to the second MC twice (once for each of the two tests it has to do with it), and the second MC does the tests.
The dilemma is that the code doesn't fit - the 'mov x0 null' lines are necessary to throw out the x-coordinate values in case the second MC doesn't actually need to run those tests (because otherwise the first MC'll block when trying to write the x-coords)... but the cost is that the script is 10 instructions long. Yeah, I could just slot in a MC6000 - but it feels like I'm really missing some sort of better way to do this.

I'll keep playing with it and see if I find anything. Saving just one instruction would be enough!

[ ~ ~ ~ ]





Remember how I said I thought I was missing a simpler way? I was. The trick is to do the testing for the square first. The first MC (on the left) now tests for the square (it can attach both its I/O pins to x and y), then sends that along to the second (middle) MC, which only needs the x-value for its test (the two vertical bars). It can add the result of the two tests and send the total out easily.

The design feels pretty clean. I don't think I can do much better on this one now.



I did some digging on Decentralized Autonomous Corporations. When they were first introduced, due to using evolutionary algorithms, the corporations would routinely find 'loopholes' in laws that led to some pretty weird and undesirable behavior - weird and undesirable for the rest of us, that is.
I am given to understand that DACs have a somewhat narrower set of algorithms that may be used nowadays - that, and there's been some loophole-patching of various laws, too.

At least they're not let onto the stock market, not after the 'Flash Fire' crash of 2021. Can you imagine?

Quackles
Aug 11, 2018

Pixels of Light.


Undocumented Instruction





Holy poo poo.

Holy poo poo.

Holy poo poo!


OK, so, uh, yeah, [cough] my sentiments are almost exactly identical to Carl's in this regard. I'm not gonna start throwing around words like 'competitive advantage', but...

You know, of all the thoughts that are running through my mind, I'm flashing back to the whole business with the eSports gamer signs, months ago. That guy on ChipOverflow - I never ran into him again, and I was able to find a ¥6 solution with help from the comments, but what if his ¥6 solution was based on using gen to create pulses? I remember running out of space on a MC6000 due to pulses taking up so many instructions...

[sigh] I guess all we can really do is learn and move on. gen and @ are going to be useful tricks to know...


Carbon dioxide posted:

Do you have any idea who patches loopholes in those corporations? I mean they don't have human leadership or anything.

Not a clue! There's some more details on Wikipedia, I think.


GuavaMoment posted:

Technical question here - how come your pngs have jpg artifacts? How are you capturing these images? There's an issue somewhere in here we can fix.

I take the screenshots with my tablet's inbuilt screenshot mode, which generates .png files. For emails, I then crop them, and nothing else. For pictures of large boards, I size them down to 50% - my tablet's got a high-DPI screen, and full-size images would break the layout. (You probably won't notice unless you have a high-DPI screen yourself.)

If you're referring to the checkerboard pattern on the 'unknown sender' picture, I think that's the email program, not a JPEG artifact. Same for the background of the simulator - there, the check pattern lets you place parts accurately.

Of course, maybe it's just that I've never shown you Joe's true form...




(Postscript: Ah, I see it was on your end. It happens!)

Quackles fucked around with this message at 22:13 on Sep 3, 2018

Quackles
Aug 11, 2018

Pixels of Light.


Three Kingdoms Tokens



They used to say TV was “Life with the boring parts cut out,” and I guess this also applies to amusement parks! Honestly, I shouldn't really be surprised that there is a Three Kingdoms Land here... If Disney World can have areas themed after parts of the American past, it only makes sense for China to do the same.
Anyway, let's see the spec.








Seems pretty straightforward, though (even with I/O expanders) this is definitely a 2+ MC job - ringing the bell and giving change should probably be done by separate MCs, just because it'll be a complete pain to coordinate otherwise. It's also worth noting that when giving change, all 5-銖 coins have to be given before all 1-銖 coins.

In the same vein, the first MC has to be the one accepting input. So...

[ ~ ]





So far so good. The code I've written up to this point adds the inserted coins' value to acc - then tests it against the price. It'll ring the bell and notify the change-giving MC (not yet in) how much change to provide, but that code isn't written yet.

I know what I'm doing next.

[ ~ ~ ]



 

I've added the second MC, though right now it only gives change in 5-銖 coins. The first MC's almost complete, except for the bit where it rings the bell - it subtracts the price from the total inserted and passes that value on to the second MC.

Just a bit more work left on this one!

[ ~ ~ ~ ]



 

Here's the final version. It's ¥11 and uses 326 power per run, on average. It turns out the change-making MC needed 10 lines to make change (once I added the code that gives out 1-銖 coins), and I couldn't get it down to 9, so I had to bump it up to a MC6000.
In addition, the first MC rings the bell.

Honestly, I don't think there's any big optimizations to be made with this design. It seems pretty solid, though it really would have been nice to do it for ¥9 as I'd originally envisioned.



More ancient wisdom: They say he who runs in front of a car gets tired, while he who runs behind gets exhausted.

Quackles
Aug 11, 2018

Pixels of Light.


Engineer's Corner #5: Shen-gen I/O

You might have noticed I had the opportunity to use gen in both chips in the previous assignment, and only did it in the second one. There's a reason for this.

I did some testing. One gen is equivalent to a sequence of four mov and slp instructions, in every way, including how much power is used (4)... almost.
The catch is that gen draws a bit more of its power up front, consuming 2 power on the ticks it starts and stops the pulse (because it's doing the effect of mov and getting itself into slp mode on the same tick). By comparison, the sequence of mov/slp instructions spreads its power draw out over four ticks, one for each instruction.



This shouldn't affect power usage in the long run when a device is out in the world, but my simulator will sometimes end tests whenever it feels like - so designs that use gen may get a higher average power score compared to ones that use mov/slp for the same thing!

I know it's foolish, but I enjoy chasing the numbers if I have the opportunity (and the free space to use mov/slp instead of gen).


By the way - now that I have @ to work with, I'm able to answer a question someone asked me a long time ago...

RichardA posted:

Also in the Infrared Sensor it might be possible to fit in a slp acc with acc being the time until the sensor is armed instead of looping and checking each time-step.

I cooked up a new design that does just this:



 

Compared to my best design originally (¥6 / 358 avg power) this is ¥8 / 300 avg power. Most of the big MC's script:
1. Calculates how long until first 'on' time and sleeps that long. (This design assumes it is initially started during when the sensor is supposed to be 'off'.)
2. At the 'on' time, calculates how many time units the sensor needs to stay on out of the 96-time-unit cycle the real time clock uses.
3. Pushes that value to the small MC.
4. Waits 24 hours (96 time units), then repeats from Step 3. (The @s keep Steps 1 and 2 from reoccurring - and the 'teq dat 0' line is there to force the conditional flag to +, so that the two 'add 96' lines are disabled in addition to all the @ lines.)

The small MC takes the value (how long to stay on) from the big MC, and runs the sensor/alarm for that many time units, then goes to sleep to wait for the big MC to wake it up again.

Thanks for the inspiration, @RichardA!

Quackles fucked around with this message at 03:57 on Sep 4, 2018

Quackles
Aug 11, 2018

Pixels of Light.


Shenzhen Days: Say Cheese!



Wow, has Tilly been talking to Carl?
Even if the answer to that is 'no', I get the feeling from her emails that she's had too many somewhat uninformed North American types chatter at her one too many times.


RickVoid posted:

You gotta get a new salesman though, man. That guy is gonna drive the business you're working for straight into the ground. Do you have an escape plan if the company goes tits-up and you're jobless in Shenzhen?

Eh-heh. Well, there is still David. He has been making deals - like the thing for the amusement park, and so on.
As for if I end up jobless in Shenzhen - my work visa is kinda-sorta tied to my employment at Longteng, so the escape plan may be, obligatorially, "go back home". Not sure what I'd (be able to) do after that.

Quackles
Aug 11, 2018

Pixels of Light.


Sandwich Assembler??

Yesterday, Carl and I went on a bit of a day trip to the 'wet market'. The electronics wet market, to be clear about this. (I'm simplifying a bit because the entire district is basically... anyway.) I know someone on here said I should visit, but I wasn't expecting the scale of what there was until I walked until a several-story mall-style building...

...selling phone cases. Mostly. Let me just repeat that: a full mall building selling almost nothing but phone cases. (Wholesale, not retail - but wholesalers gotta set up somewhere.) And that's just one building.
The other thing I didn't expect to find was repair shops. I mean... OK, so suppose I was using my laptop, and it broke, for logic-board based reasons. If this were North America, the logic board would basically be junk, and I'd have to get a new one.

Here, there's almost certainly someone, SOMEWHERE, out there with some sort of automated soldering iron that would be able to try to fix it. And new parts would be available just down the road.

Of course, there were also a number of shops etc. selling various kinds of bric-a-brac, kitsch, and junk. I mention this because my latest assignment is from someone who'd feel quite at home there...










This strikes me as something that could work, though I have to wonder - who would want that many sandwiches made in an automated manner (as opposed to making them themselves)? What if you fill the mustard compartment with mayo? The keypad still says 'mustard'. What about if you want extra cheese and no mustard?
Heck, what if you're Canadian?

TLDR: This doesn't look that customizable in the grand scheme of things, and I'm having a hard time thinking of applications. This doesn't mean that 'personal sandwich maker' is a bad idea. You could probably make a more programmable and versatile design and sell lots of units. Just... as it is now, this feels like junk.

But hey. Maybe Joe's on to something, and we can get rich selling junk.

[ ~ ]





You ever have that feeling where a solution almost works, and it feels like there's a way to sort it out but you can't see what? That's where I'm stuck.
This design does everything asked of it: the 'tcp' with the keypad sets the mode (1 = normal = , 2 = no cheese = no flag set, 3 = extra mustard = +), then the MC pulses the 'bread' output with gen. After that, we start messing with the other three outputs through XBus - meat, cheese (if + or ), and mustard (extra on +) in that order. And then the final gen instructions pulse the bread and the flag.

The only problem is that I don't have the space to add an instruction that turns off the I/O expander, which would stop the flow of mustard. So, once the machine starts dispensing mustard, it never stops.



I need to figure out a way to save one instruction, or this design is toast... so to speak.


[ ~ ~ ]





It took me an embarassingly long time to figure out the solution, which is two lines of code different from the previous version. First off: I realized that... well, the bit in the middle, with 'mov 10 x3', is what does the cheese. It needs to not trigger unless a conditional flag is set - 2 is 'no cheese', and tcp won't set either flag if that button is pressed. That's why there's two different slp instructions, each with their own flag - you dispense cheese on +, and on , but not neither.

The thing is, in the original I also did 'mov 10 x3' twice with the flags in the same way. I'd forgotten how quick MCs run - now, there's only one copy of 'mov 10 x3' and it always runs, but it gets overwritten by 'mov 1 x3' (mustard) almost immediately if no flag is set (i.e. no-cheese mode).

(Fun fact: For a while, I was even considering adding a second MC before the main MC, to transform the input into something easier to sort out - but this design works, there are no further mustard spills, and my bacon isn't... toasted?)



Eh, whatever, mixed metaphors are fine for now.
¥6, 85 power... I think this design is as good as it gets.



I'm kinda torn. I really don't want to wish ill on Joe. But all the same, he's wasting everyone's time with these not-very-well-thought-out ideas, and it's hard not to get mad at him sometimes.

[sigh...]





UPDATE:

Guess what? Joe contacted me again. This time in person, and, uh, 'on the down-low' (or at least as much as is possible for Joe). He mentioned something about retrofitting the internal mechanism to work for a sandwich vending machine - which would require a few changes on how it handles input. The rest of the design is the same, though.

I had to dig the updated spec out of the old interoffice mail system. Message# 2241. It's old enough that the interface to get it ('Message Archive') was in my tablet's Control Panel, and not in the mail program directly.





(It's the exact same board, to be clear, but the spec's changed:)







I really, really do not want to have much of anything to do with this past this point - so, I'm going to toss this one at all of you, if anyone's interested.

Readers, got a good design? Make sure you're using the updated spec!

Quackles
Aug 11, 2018

Pixels of Light.


Carbine Target Illuminator



Guess who got stuck with this job? I'm not really at all happy with this, but Carl being able to say no is one of the perks of seniority in this case, I'd think.








The actual design seems quite straightforward. You listen on the inputs until you have an 'out' pulse followed by an 'in' pulse, take note of how much time passed between them, then use that to drive the laser and/or flood lights. It's a job that should be easy for a competent engineer.

I think I'm feeling pretty competent today... :eng101:

[ ~ ]



 

First off: it looks like each of the inputs, radar-out and radar-in, obviously needs its own MC. The radar-out MC will send a signal to the radar-in MC on each time unit, indicating whether or not radar-out is on - this lets the radar-in MC know whether to count or reset its counter. Then, once that MC detects a pulse on radar-in, it'll start working on the sending output bit (which I haven't coded yet). It'll also send its count back to the first MC, because I think the first MC might need to do something with it. I'll figure that out when I get to work on the outputs.

[ ~ ~ ]



 
 

There we go! Outputs are half-done. It definitely seems like each output also needs its own MC, for result-testing purposes (though thankfully they're MC4000s or else I'd hardly be able to fit them on the board!).
It's pretty simple. The upper MC on the left sends the output to the top MC on the right, which handles the laser. The lower MC sends output to both bottom right MCs. (That's why it sends acc to x3 twice - so that each MC on the right can receive it once).

I just have to finish up the code for everything, and this'll be ready to go.

[ ~ ~ ~ ]



 
 

This is the final version. I had to upgrade the top right MC (controls the laser) to a MC6000. It's unfortunate - but you have to have a test for each possible value, and then you can only use the value from an XBus pin once, right? But I also read on ChipOverflow that you also have to store the value from an XBus pin before you use it, so that's 3 lines for each of 3-4-5-6. So, 4 * 3 = 12 lines = big MC.
(The same applies to the bottom right MCs, but there it's only 6 lines each because they only check two values, so they can stay MC4000s).
All the code is really clean and understandable, so it's not like I need to comment it or anything.

The only other big change is that I finished the code for the bottom right MCs, adding extra sends on the radar-in MC as necessary - the bottom-right MCs also each needed a slp 1 in their scripts - otherwise, they were eating the sends meant for their sibling.

And that's a wrap! ¥21, and 757 average power usage. I'd say that's the best I can do.



Yeah, Carl isn't all that happy... but I'll show him my design later.

Quackles
Aug 11, 2018

Pixels of Light.


Can You Keep a Secret?? Haunted Doll Project





You know how on Looney Toons, when a cartoon character blinks? And they have the tinkling of a xylophone to go along with it?

That's about how I feel right now. After a while, you just sort of get... desensitized to bad ideas. You say to yourself, 'this is a bad idea', but... it is your job. All you can really do is be there to say "I told you so".
Mind you, I'm looking forward to saying "I told you so" for THIS.







I tried to read the writing on that smeared chip, but without any success - so I'll have to settle for thinking of it as a random number generator. No obvious pattern to its output... I wonder what it was originally for?

The first thing that feels obvious about this design is that I'm going to need to store the audio data for the two sound effects that Carl found - and that means, memory chips.

[ ~ ]



   

Did Carl fire up his copy of Internet Explorer 3.0 to get at the page with those sound effects, I wonder? Each effect snippet is conveniently 13 samples long, perfect for fitting in a 200P-14 memory chip. I can't speculate as to the actual sound quality, though.

Anyway, the memory chips are in, as is a MC6000 and the first half of the code - this half waits for the RNG to return a 1 (or 2) and moves it to acc if so. If it's not either, it sleeps until the next time unit. The only remaining part is actually playing the audio.

[ ~ ~ ]



   



Ta-da! One haunted audio-playing code part, as requested! The 'play' code loops to play the audio - it reads the audio sample from the correct chip (based on the value we put in acc earlier), pushes it out to the speaker, then waits for the next time unit. The memory chips' auto-increment is really useful here - once I read a sound sample, the memory chip will immediately provide the next one when I read again.

There's a few tricks I use to get the 'play' part to work right - first off, none of the effects have the sample '50' (audio silence) in them, and the memory chips each had a free slot at the end. So, I put a 50 in that slot. When the MC reads the 50, it knows it's read the entire sound effect and that it can go back to waiting (it doesn't jmp back to the label play:, so the code path falls through to the top).

The only other thing of note besides the audio-playing code is the @ mov 50 p1 at the front of the MC's script, which initializes the speaker when the device is turned on.

For all that this feels like a vaguely terrible thing to do to someone, I can't help wondering where this is going to end up. Could it show up on whatever the Chinese equivalent to Twitch is? That'd be interesting...!



Told you so.

I wonder if David is free this evening to indulge in some "traditional Chinese cocktails"?


PS: I looked up "ghost shifts". It took me a while to find a definition... apparently it refers to, at least traditionally, where a factory making something will make the thing on two shifts, then make more-or-less identical counterfeit versions (well, technically counterfeit) for outside sale during the 'ghost shift'.
Does our factory have ghost shifts that work like that?! :stonk:


PPS: Speaking of ghosts and supernatural monsters and so on, there is one bright spot in the stuff I've been doing lately. I’ve been getting into some of the local TV shows (thanks to the big networks helpfully providing English subtitles).
There’s one - it’s called My Roommate Is A Lamia! - that’s pretty good! The special effects are pretty amazing just by themselves, and the plot is… well, it’s pretty fun. Wacky, but fun. The main guy has just figured out that his roommate is... well, you know... and I'll keep y'all posted how it goes from there.

Adbot
ADBOT LOVES YOU

Quackles
Aug 11, 2018

Pixels of Light.


Growing the Company - Please Read



This email arrived the next day after the haunted doll thing. To be honest, Lili nailed something that has been personally bothering me for a bit - some of the stuff I've been making here is... stuff. Some of it is Joe's, uh, 'ideas'. But the ratio of potentially useful or fun projects to dubious projects has been a bit skewed for my liking.

Of course, the question is, is this going to change in the future?


RickVoid posted:

Gah, I feel a little bad now, but it's good to know that Jie is seemingly on top of things (I assume that e-mail was supposed to go to him only). Maybe this'll be the kick in the pants Joe needs.

I don't think Joe reports to Jie, actually. Jie's the chief Engineer, but that just makes him my boss and Carl's.
Of course, this just means that Joe meant to send the message to someone higher up the chain...


azsedcf posted:

Want to save ¥1?

If you drop the lower left chip 1 space then you can run the X0 from the upper left chip under itself to avoid using the bridge.

Remember: Any component that is 3 wide lets you run a wire down the middle without interfering with it's operation.

OK, two separate responses here.
First off: Bridges are actually free! Well, OK, they're not free free. Longteng does pay something for them, but the cost is really, really marginal. I think it's something like ¥.026 per bridge, or thereabouts.

Second: Wait, you can run wires under chips?!
I did not know that at all! I'm going to have to test this out at some point!!


Computer viking posted:

Something about this makes me want to write a short introduction to x86 assembly...

I miss binary shift-compatible registers. Decimalized MCs are... strange. You should totally write it, though!

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply