The Let's Play Archive

SHENZHEN I/O

by Quackles

Part 66: Assignment #31: IMPORTANT - The Big One!

IMPORTANT - The Big One!



And here we go!! As Lili puts it, Sun Haotian's big project. (I'm paraphrasing.) It's time to see exactly what Sun Haotian's masterpiece - the "SafetyNet Tracking Badge" - is all about.










Now that the specs are up there, I'm going to address the elephant in the room, because I don't think it can wait until the end of the post this time.

What is Sun Haotian Building?

So, to recap, we have:
• A robot for an automated aquaponics facility, suggesting feeding a lot of people
• A control router for smart grids of some sort
• A traffic signal for an undefined-but-probably-automated vehicle, including facilities for emergency vehicle overrides (and six-way intersections!)
• A deep-sea sensor system for monitoring ocean floor anomalies.

Then we have this. The SafetyNet Tracking Badge. It's clearly meant to be worn by a person (or, y'know, a few hundred thousand people), tracking where they are around this city. And it is supposed to be a city: I translated the Chinese characters in the document. From top, they read: "port", "government building", "commercial and residential area", "industrial area".

So: Sun Haotian is building a city that's either near, or on, an ocean or similar body of water. (I'm still a little skeptical about Junpei's it's-on-the-ocean theory, but at this point I don't think I can discount it.) And people are going to wear these badges and Mr. Haotian can digitally follow them around and/or send PA-system-style messages.

Of course, this only raises a few more questions.
• Why is Sun doing this?
• Where's the city going to be?
• Who's he expecting to move there?
• Why the damn badges?

Unfortunately, I don't have any sort of answers to those questions. And, well... I guess it's probably best for the time being to make these to the best of my ability. If need be, I can always pass on info about the design of the badges to the citizens if things go sour. I'm sure someone'll find a way to break them if it ever comes up, as long as they have the design.

So: to work.

[ ~ ]

Here's what I've got so far.





I started with the easy part - the audio player. You can handle it directly in the MC that reads from the radio - if the first packet is a '1', the MC stores the second packet in acc and makes a loop that sends that many packets to the speaker, at a rate of one packet per time unit. (It looks like the Badge isn't expected to handle requests while it's playing audio, so I don't have to get all the data from the radio immediately - I can just leave it in the radio's buffer.)

There's also a part in this MC's script that will, if the first packet is a '2', ping the MC or MCs that will handle the location information. This part isn't built yet - that's next.

[ ~ ~ ]

Here's my first attempt at the location information part.



       

The location is the combination of the radar-ping and radar-sync values read by the badge. The sync value specifies the heading around that circular diagram, and the ping value specifies how far in from the edge the wearer is. You'll note that, in the spec above, the radar-ping pulse only comes once every (roughly) six time units - so the badge has to cache (store) that value until the next ping comes in, in case it's called for. That's the job of the middle MC on the far left - it copies any non-0 ping value to its p1, making sure the value 'sticks'.

The sync value has a design challenge associated with it: if the wearer is in a sector in the middle ring, the badge has to read the sync value to determine if it should output "200", "201", "202", "203", or "204" (or "600") - and the easiest way to do this is to set up a '200' in an acc and add the right value for the ones digit afterward. Which means the Badge needs to turn the two- to three-digit sync value (20-40-60-80-100) into a single-digit value (0-1-2-3-4), without the luxury of a 'divide' instruction (except maybe using dgt to kinda-divide by 10).

In the design above, the two small MC4000s on the top row are responsible for this. The MC6000 in the top center is responsible for calculating the user's sector value, taking in both the cached ping value, and the raw and converted sync values. If it sees a middle-ring sector (other than sector 600), it'll notify the top left MC4000, by way of the top middle MC4000.
When the top left MC4000 gets the notification pulse, it reads the value from radar-sync, and, if it's over 40, starts subtracting 20 from it repeatedly. Each 20 subtracted becomes a '1' pulse to the top middle MC4000, which counts the number of '1' pulses it receives. It then passes that number onto the MC6000 to the right of it, which gets added to the '200' already in the calculator MC6000's acc.

This is inefficient as all get out (it's effectively division by means of a loop). It's also got a mistake in it. I originally thought the radar-ping value needed to be cached, but radar-sync didn't: that is, when the badge got the location request, it'd use whatever value of radar-sync there was at the time it received the request. This turned out to be wrong. The sync value needed turns out to be whatever sync was when the last ping came in. In short, both radar-ping and radar-sync need to be cached.

Which means it's back to the drawing board! I need to remake the location-reading part pretty much entirely. On the bright side, I'll be able to do something about using just three lines on that mid-left MC4000.

[ ~ ~ ~ ]

Here's the updated design. It almost works!



     

The basic logic of calculating the user's location hasn't really changed - what has changed is the part on the left that caches the ping, and now also sync values. The upper left MC still sends a '1' pulse for each amount that radar-sync is over 40 - but it sends it to the MC6000 just below it, which does the counting up after storing the ping value. Effectively, the middle left and the top middle MC4000s from the previous design have been combined into one.
(Once the mid left MC has finished counting for the transformed sync value, it sends it back to the top left MC by XBus, which sends it to the calculator MC in the middle by simple I/O. I didn't have enough simple I/O ports left to do it any other way.)

This works most of the time, but there's one edge case it fails on. If:

• The radar ping comes in on the same time unit as the location request, and
• The wearer is not in the center of the city (sector 100), and
• The user changed sectors since the last ping, specifically in a rotational direction,

then the badge will report the location incorrectly - the sync value isn't being transformed fast enough, and an old sync value is used for the calculation.
For those who're curious: The first condition is because the value is updated by the end of the time unit the ping comes in, so it'll work after that. The second condition is because the calculation for sector 100 doesn't use the sync value. The final condition is because, otherwise the old sync value will be the equivalent to the new sync value, and it won't matter.

I'm not sure it's possible to make the sync calculation faster using the method it currently uses. Looks like I'll have to find a way to make it faster!

[ ~ ~ ~ ~ ]

I had a brainwave, and rewrote the sync processing code. It still almost works!



     

The change to the way sync is processed is this: I realized that a lot of the back-and-forth message sending between the two MCs on the left didn't have to happen. Instead, each time the sync-transforming MC sees the number given is 20 or more, it subtracts 19 (this is the same as subtracting 20, then adding 1) until only a one-digit number is left. Because the ones digit will never go over 5 in this way, it's safe to do, and a lot faster than before.

Unfortunately, the glitch I had above is still a problem - it's just harder to trigger. It'll now only happen, in addition to the other conditions, if the badge wearer is in sector 202, 203, or 204, or the equivalent part of the '700' sector just outside those sectors.

I get the feeling I'm going to have to do something kind of hacky to get this to work.

[ ~ ~ ~ ~ ~ ]

As promised: something hacky. And yes, it finally works.



       

The biggest and most obvious difference between this version and the last version is the extra MC4000 between the input-handling MC6000 on the far right and the MC6000 in the middle that does the calculations. The only job of this MC4000 is to intercept location requests, and hold them until the wearer's location can be properly calculated.

The ping-processing MC now outputs '0' while it waits for the sync processor MC to be done. When the sync processor MC notifies the ping processor MC, it'll release its actual ping value, signaling everything's ready to go.
If the new delay MC gets a request while the ping value is still reported as '0' (i.e. 'not ready'), it'll loop until this isn't the case. Otherwise, it passes requests straight through.

So, to recap the design up until now:
• When the two left MCs get a new ping, the middle left MC (which processes the ping) outputs '0' ('wait'), and notifies the upper left MC (which processes the sync).
• The sync-processor MC divides the value of sync seen at the time of the ping by 20, subtracting 19 until only a one-digit value is left. It outputs this value, and lets the ping-processor MC below it know that it's done so it can output the actual ping.
• When the bottom right MC6000, which handles radio input, gets a '2' and the right badge ID, it notifies the big MC6000 in the middle (the location calculator). This notification messages goes through the delayer MC between the two, which will wait until the ping-processing MC outputs its value to pass the message on.
• The location calculator MC uses the output ping value, and the processed sync value, to determine the user's location. It outputs it to the radio.

• When the radio-input-handling MC gets a '1', it'll output audio using a loop. Location requests are ignored while this is going on.

This new design works properly, at a cost of ¥19 per badge, and 646 average power per run. I'm going to try and see if I can optimize it any - as I mentioned above, the delayer MC is basically a hack, there to patch a flawed design. There's almost certainly a way to make the badge run without it.

My next job: to find out what that way is.

[ ~ ~ ~ ~ ~ ~ ]



     

Here's my first attempt at alternate ways to make sync processing work. This one at least removes the need for the delayer MC. I also made a few slight tweaks to the two MC6000s to remove some jmp instructions that weren't really needed.

For the sync-processing MC, I realized that the sync value always moves in a set pattern - so there's no need to process the value every time. Instead, the sync-handling MC simply adds one to its acc each time unit, using it as a counter that goes from 0 to 5 over the course of six time units. If the MC sees a '0' as the sync input, it resets the counter to 0. The MC will also check each time unit to see if a new ping has come in; the ping-processing MC will signal the sync processor whether there is ('1') or is not ('0') a new ping. If there is a new ping, the sync-processing MC will output its counter value over its p1.

The previous version's sync-processing MC could take anywhere from 3 to 18 instructions in a time unit to process and output the sync value, depending on what input value it received. This one runs in constant time, taking 3-4 instructions per time unit to process and (if necessary) output the value - and the location-calculator MC is designed not to need the value before then!

This version is ¥16 per badge, and 633 average power per run... that said, if the radar-sync input pattern ever changes, these badges are going to be junk. I'm going to keep looking into into alternate methods of sync processing.
Still, not a bad first improvement.

[ ~ ~ ~ ~ ~ ~ ~ ]

I'm not sure if this next design is a step forward or a step back, but it's another completely different take on sync processing.



     

All my past designs either had the sync-processing MC either (A) take the sync value and perform division by 20, in software, or (B) mostly ignore the sync input's value, and predict it based on its pattern instead. This design uses the hardware to take a third way.

ROM chips have an interesting quirk regarding their address pointers: you can pass in a number lower than 0, or higher than 13. This number will be converted to a number from 0 to 13 with modulo arithmetic - in simple terms, it's the remainder when whatever value you pass in gets divided by 14.

It turns out, when you put in 0-20-40-60-80-100 into this addressing scheme, you get:
0 => 0
20 => 6
40 => 12
60 => 4
80 => 10
100 => 2

So, when the new sync-processing MC gets a notification that a ping is in, it can just plug the current radar-sync input value into the address line of the attached ROM chip, and the ROM chip will give the transformed result.

Because of this, it was easier to combine the ping- and sync-processing MCs into a single MC6000 - which means that the input-processing MC now has to send its results to the location calculator MC through XBus, which is typically wait-driven. But the input-processing MC also has to check for a new ping each time unit. What's a MC to do?

The answer is that the bottom-right MC, the one attached to the radio, will now send a '1' to the input-processing MC on time units it needs to output the stored location information. It will send a '0' the rest of the time.
(Technically, it sends the '0' on every time unit, but it sends the '1' before it if a '1' needs to be sent. The input-processing MC will throw the extra '0' out if it receives a '1'.)
Once the input-processing MC knows it needs to output values, the act of outputting those values wakes up the location-calculator MC, which will use the values to figure out the wearer's location, and send that out over the radio.

The new version is ¥17, and once again represents an improvement in power usage, drawing 531 power per run. That said, that wiring - the way the location-calculator MC is off to the upper rightish - bothers me. I'll see if I can improve it at all, though it's possible these past two versions are as good as it gets, optimization-wise.
If I can't improve the designs any past this, it might be worth passing a message along to Mr. Haotian, asking which prototype he'd prefer. Though I suspect he'd want the decreased cost, maybe he has plans for the center radar thing's pattern and would like this version for its reliability. Or maybe he'd like this one because of the decrease in power usage.

We'll have to see.

[ ~ ~ ~ ~ ~ ~ ~ ~ ]

Here's the really final version. Once again, I've made a masterpiece.



   


¥12. 517 average power per run. Efficient. Nothing unneeded. And it works because I was able to combine the input-processing and location-calculator MCs into one.
The previous versions of the location calculator would first check if you were in the center ring, and then return '100'. They'd then check if you were in the top wedge and return '600', or if you were in the outer ring ('700'). If none of those conditions held, they'd use the transformed sync value to indicate which middle-ring sector you were in.

The new version doesn't need to do all of that, because of an important quirk of how the ROM chip cells shook out: each of the cells for the values 0-20-40-60-80-100 has an unused cell after it. This means that the new location calculator is very simple:
1. If the ping says the wearer is in the inner ring, return '100'.
2. Otherwise, read the sync value, and go to that location in the ROM chip. This is the badge wearer's location for where they are on the middle ring.
3. If the ping says the wearer is in the outer ring, read another value from the ROM chip. The outer-ring location associated with a given middle-ring location is stored in the next cell in the ROM chip.
4. Store whatever location value the MC ended up with, to be output to the radio later.

The location is recalculated each time there's a new ping. Like the previous design, the MC6000 connected to the radio will notify the location-calculating MC with a '1' if the wearer's location needs to be output on that time unit, and '0' otherwise.

I'm pretty sure that's everything that I or anyone can do to improve this design. Time to send it off.

I have to wonder as I write this: am I doing the right thing?
Nothing to do but wait and find out.




Phew. I'm not sure if anything I do here at Longteng is gonna top that. I'm off to get my free cream puff!

I bet Mr. Haotian's going to make some sort of announcement soon...