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.


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 drat badges? :ninja:

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

Adbot
ADBOT LOVES YOU

Quackles
Aug 11, 2018

Pixels of Light.


An Invitation





Well then.



I'm going to ask for your opinion on this one, my loyal readers. Should I move to Avalon City? I'll probably face exciting new challenges to blog about.
By comparison, if I stay in Shenzhen, it'll probably be business as usual. I'm not sure I'll have anywhere near as much to tell you guys, though - after something like that last assignment, I'm not sure what there'll be to present a challenge to me if I stay here.

Your thoughts?

Dareon
Apr 6, 2009

by vyelkin
Okay, wow. I see everything Carl's saying, but you would have to physically restrain me from slamming that "yes" button. The only thing that would limit me in my case is I would know exactly how janky and kludged together the things I designed were. But you? You're good, man, go for it.

risky business
Oct 9, 2012

Barns?
I'm going to say move. You need the challenge (...given that you have enough downtime at your job to recreate a full player piano setup), and, like, if things do go wrong, you'd be the most equipped to start some sort of cool cyberpunk rebellion from within.

Yvonmukluk
Oct 10, 2012

Everything is Sinister


'A new idea for organizing human life that combines citizenship and employment into a single concept'? NOPE. This is how you get Rapture.

inflatablefish
Oct 24, 2010
First design yourself a way to break those Big Brother badges you've just made. Then go for it and kick off the cyberpunk revolution.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
Nice job using a lookup table for division! And very serendipitous that it then gave you an easy way to solve the outer ring as well. I see there are some unused memory spaces in the ROM - often, this sort of space is an excellent place for a designer to leave their mark - for example, putting their ASCII initials in those slots, immortalizing themselves in the design.

For what it's worth, it's rather trivial to do the division by 20 by multiplying by 5, and then using dgt to divide by 100.

Pierzak
Oct 30, 2010
>want to avoid government red tape and corporate bullshit?
>makes a corporate government monopoly, with police state mechanisms built in from the start
for what purpose.jpg

Still, better you than me. Send me a postcard from the nuRapture. but first make a separate save so you can show off the other plotline when you finish this one.

mercenarynuker
Sep 10, 2008

I was super convinced that Sun was designing an underwater Star(sea?)ship Enterprise. You had hydroponics bay, turbolift control, sensor grid, and now commbadges. Even though the city is a less exciting reveal, if you're not on the next boat/helicopter/floatplane out there, I'm sure we'll all be sorely disappointed

megane
Jun 20, 2008



Kudos to his marketing dept. for managing to come up with a pitch that doesn't have the words "cyberpunk dystopia" in it.

idhrendur
Aug 20, 2016

Go for it.

Junpei
Oct 4, 2015
Probation
Can't post for 11 years!
I called it! I so called it!

But, yeah, I agree with everyone else-Go for it, if anything goes wrong you're the best shot we have at a cyberpunk rebellion dealio.

limaCAT
Dec 22, 2007

il pistone e male
Slippery Tilde

Quackles posted:

An Invitation





King Videogames says "go forth and eventually savescum".

OOrochi
Jan 19, 2017

On my honor as the Dawnspear.
Go for it! There's definitely nothing that can go wrong with full blown corporate sovereignty.

KirbyKhan
Mar 20, 2009



Soiled Meat
Man, what about loyalty. What about your crew. Stay in Shenzen for Joe.

Carbon dioxide
Oct 9, 2012

Go for it, you'll regret it for the rest of your life if you don't. And if it turns out to be not for you you can always leave. With those creds you can get a job anywhere.

ChaseSP
Mar 25, 2013



"You can always leave!" Sure buddy. Let's go to Rapture.

Dareon
Apr 6, 2009

by vyelkin
Meanwhile, thanks mostly to this thread, I got the Zachtronics bundle on sale and while I'm not that keen on the programming language games like this and TIS-100, I enjoy the object-oriented ones like Infinifactory and Opus Magnum.

In Opus Magnum, I came up with a solution that makes me feel like a real engineer. I put together an efficient, elegant machine that accidentally put half of the solution together backwards. Instead of tearing apart and rebuilding half the machine, I rotated one piece and ran a bunch of track to get the offending piece together properly.

Deathwind
Mar 3, 2013

Dareon posted:

In Opus Magnum, I came up with a solution that makes me feel like a real engineer. I put together an efficient, elegant machine that accidentally put half of the solution together backwards. Instead of tearing apart and rebuilding half the machine, I rotated one piece and ran a bunch of track to get the offending piece together properly.

Reminds me of the time a new breed of tomato was developed just to avoid re-engineering a new mechanical harvester.

Edit: I definitely understand not wanting to completely tear apart a functional system to fix something stupid, it results in things like this https://m.imgur.com/M6D0r7O

Deathwind fucked around with this message at 02:07 on Feb 12, 2019

Anticheese
Feb 13, 2008

$60,000,000 sexbot
:rodimus:

Deathwind posted:

Reminds me of the time a new breed of tomato was developed just to avoid re-engineering a new mechanical harvester.

Do you have a link to a write-up on this?

Deathwind
Mar 3, 2013

Anticheese posted:

Do you have a link to a write-up on this?

https://news.plantsciences.ucdavis.edu/2015/07/24/how-the-mechanical-tomato-harvester-prompted-the-food-movement/

https://www.nytimes.com/1977/03/08/archives/and-now-california-develops-a-square-tomato.html

Carbon dioxide
Oct 9, 2012

Dareon posted:

Meanwhile, thanks mostly to this thread, I got the Zachtronics bundle on sale and while I'm not that keen on the programming language games like this and TIS-100, I enjoy the object-oriented ones like Infinifactory and Opus Magnum.

This post confused the hell out of me at first. Object-oriented is a program language style, used in languages such as Java and C#. Infinifactory and Opus Magnum don't have any Java or C# programming. But I get what you mean.

Reminds me of the good old times of the SA LP SpaceChem competitions, where lots of people tried to solve special-made SpaceChem puzzles as efficiently as possible. For one of them I did a bunch of writeups about whether the chemicals in the puzzles were real, and if so, what their properties were. It's all in the lp archive, if you want to see what it was like.

paragon1
Nov 22, 2010

FULL COMMUNISM NOW
Absolutely not.

Do you want to get Resident Evil'd? Because this is how you get Resident Evil'd.

Dareon
Apr 6, 2009

by vyelkin

Carbon dioxide posted:

This post confused the hell out of me at first. Object-oriented is a program language style, used in languages such as Java and C#. Infinifactory and Opus Magnum don't have any Java or C# programming. But I get what you mean.

Oops, yeah, I used "entity-based" previously, and that's a more apropos term, dealing with discrete "physical" objects and issuing simple commands.

Quackles
Aug 11, 2018

Pixels of Light.


Avalon City

(( Music: Outro ))

So, what did I accomplish in Shenzhen?



Engineering stories aren't like movie stories.
I didn't find love, or save the world, or anything like that.



But it brought me here.



To the start of something new.



Maybe something good. Or maybe a disaster.
But no matter what the future holds, there's one thing I know.
One thing I can always count on:



I'm a drat good engineer.



I've arrived in Avalon City, and I'll continue this blog soon.

Quackles
Aug 11, 2018

Pixels of Light.


The Ocean's Bounty

It turns out my new office is very similar to my old one: a fairly cozy room with a tablet and a nice camera view of the outdoors. On the other hand, the outdoors itself is pretty stunning. Sun had the foresight to site Avalon City in a good latitude, so it's always warm.

You can also tell from the picture I showed in the last post - the city's nowhere near finished yet. Avalon City is built on a series of hexagonal 'plates' that are apparently modular on a grand scale (this explains the six-way traffic intersections), but all the plates aren't in place yet - in particular, a number of plates for the residential and industrial sectors are still missing. So for the time being, I'm camping out in my office.

That said, I'm near to the food! So to speak. Those aquaponics plants I helped design the control systems for are up and running, but they're designed for quickly growing large quantities of one or two kinds of fish and plants. Avalon City's diet isn't exactly monotonous- the closest cafeteria's fishcakes are pretty good - but it could be better. On top of that, (Sun alluded to this in his welcome email) the aquaponics systems need supplies for the cleaning tools and to keep the tank water in balance, so they're not truly self-sufficient... there's a whole bunch of stuff.
In short: Sun had the aquaponics plants made so you could feed a lot of people - quickly - and that's exactly what they're doing. But no more than that.

Which is why I'm helping a bunch of biochemists make a robot arm that carries crates to and from their freezer.



Lisa's the team head. I haven't met her in person yet— I got roped into this by meeting Derrick at the welcome party— but she seems fairly upbeat.
I should probably also mention that saying "a bunch of biochemists" was a bit of a misnomer. Derrick's actually a mechanical engineer, and a lot of the other team members (though I haven't exactly met many yet) are from different disciplines, though it does skew towards biochemistry and engineering. Apparently, a lot of the teams here in Avalon City are pretty multidisciplinary.

Now here's what I'm actually making:








I can already see the basic idea of the design. There'll need to be 1-2 MCs that control the movement - move/grab/drop itself; a memory chip to remember where everything is, and a MC to manage it; and possibly other MCs to respond to the radio or whatever. The spec they gave me has five 'slots' in it, but Derrick said he'd appreciate it if the design was customizable for as many slots as necessary. I told him yes - as long as he'd be OK with using a larger memory chip for 15+ slots.

The first prototype shouldn't be too hard to make. I'll get right on it.

[ ~ ]

This is my first attempt.



     

It came out pretty much as I envisioned; the top left MC responds to the radio. It'll send two values to the MC below it (which is attached to the memory chip): a value to search for in the RAM chip, and what to put in that memory slot in place of the value that the MC found. When adding a new crate, the value to search for is '0', which represents an empty slot. The value to write is the crate's ID number, representing it being stored. When removing a crate, it's the other way around; the value to search for is the crate's ID number, and '0' is written over it, to represent that slot becoming empty.

The memory-chip MC keeps track of what crate is where. It will respond to the radio MC's 'search' request, find a matching slot, and update the memory chip accordingly (sadly, due to Pingda Co.'s memory chips' auto-increment feature, it has to spend a lot of lines carefully moving the memory pointer back by one). Then, it'll signal the arm MC (the third MC6000, over on the right) with two values: which slot it should move to and grab a crate (starting from '1' and counting up), and where it should move that crate to ('0' being the loading dock).

The arm MC will do the moving job when signaled, controlling the motor directly. The smaller MC just to the right of it controls the arm extension and claw - sending it '100' (or almost any value) will make it grab, while sending it '0' will make it release.
The arm MC does use a bit of cleverness to get the job done. Depending on whether it's loading or unloading a crate, it has to tell the grab MC to either grab the crate at the loading dock (before the arm starts moving) and release it in the storage area, or grab it in the storage area and release once it's back at the loading dock. The grab and release at the loading dock are handled through conditional flags (the mov 100 x2 and mov 0 x2 lines), but I save a line of code by saying mov dat x2 - the value stored in dat will always be '0' in the case of a crate being added, and it will be the crate's ID# in the case of a crate being removed. So, the grab MC will drop (0) the crate in the storage area on a 'store' command, and grab (not 0) the crate from there on a 'retrieve' - just as designed.

This design does have a few tiny quirks. First off, there can never be a crate with an ID# 0, though that's really a permanent design choice (as 0 is reserved for 'empty slot'). More importantly, this design currently codes for 5 slots. By changing the number on the "#limit" line of the memory-chip MC, you can get up to 13 slots, or 32 with a larger memory chip. (The last slot of the memory chip has to remain unused because the arm MC receives the address of the slot after the target slot in the memory chip, and uses that address number to know how far to move the arm. If the last slot is used, the address of the next slot will be '0', and the arm will return the crate to the loading dock.)

The total cost: ₯20, with 417 average power per run. This is the first job I've had in a long while where I don't have to specifically worry about optimizing for something— cost isn't a concern here, and power only a minor one— but I'll try to clean up the design as much as I can, anyway. One thing that's tugging at me is the empty space on the radio MC - I could switch the MC to a MC4000, except for the fact that it needs both the acc and dat registers. I'll move things around and see if there's an alternate way I can do this...

[ ~ ~ ]



     

My second prototype turned out a little bit different from my first! The main change here is that the radio MC is now responsible for writing the value to the memory chip. The MC that was originally the dedicated memory-chip MC now only searches for the crate or empty slot's location.

The way things work now is as follows:
First, the radio MC receives a message, then it sends the value to look for (be it an empty slot (0) or a crate's ID#) to the searcher MC4000X, just below. The searcher MC will check the memory chip for the value, then send the address pointer of the memory chip (pointing to the cell after the found value, 'cause of how memory chips' pointers work) to the grab MC. It will also send a '1' to notify the radio MC it's time to write.
The radio MC, once it receives the pulse from the searcher MC, will rewind the address pointer, then write the value (be it empty slot or crate ID) in the correct slot. Effectively, most all of the work I've done here is moved the writing code to the upper MC without really changing it all that much.

The arm and grab MCs are also the same as my first version, so the rest of the design works as I described above.

By moving the code around and turning the memory-chip MC6000 from the previous version into the searcher MC4000X in this one, I managed to save ₯2, while keeping the power about the same. The new stats are ₯18, and 423 average power per run. I'm going to show the design to Derrick and get his take on it.

[ ~ ~ ~ ]

OK, this is a tad embarassing. When I explained my shiny new design to Derrick, he immediately asked about what would happen if someone tried to add to a full storage bay - or if someone tried to remove a crate that wasn't there, by accident. The answer: nothing good! (The arm wouldn't move, but the memory chip would still get written to as though it had been, and the record of whatever was in the last slot of the storage array could be corrupted.)

It turns out both problems have the same underlying cause: when the searcher MC looks for a value that isn't actually in the memory chip. If the storage area is full, there will be no '0' slots in the memory chip to write a crate ID# in, and if the wrong crate ID is requested, it won't be in the memory chip either!

So, I took my design back to add error handling capabilities. Here's the updated version:



     

This design has a few changes. The first is the error handling code, which is added to the radio and searcher MCs. The searcher MC now sends the radio MC the address of (the cell two places after) the found value - the radio MC will test this value, and if it's over the limit, it won't write anything.
A side effect of this change is that now the last two cells of any memory chip have to be left blank for it to work, enabling this design to serve up to 12 slots with a small memory chip, and 31 slots with a large one.

The second change makes the arm MCs more efficient, and is unrelated to error handling; I discovered it while fiddling around with the design. The new version of the arm MC delegates more of the grabbing control to the grab MC.
The grab MC, when cued, will now grab, wait for a specified time, then release automatically. (Previously, it had to be cued twice, once for grab and once for release.) This means the arm MC has to signal the grab MC only once during a run, giving a slight power savings.

The combination of the two improvements means the new design has better statistics than the old one - still ₯18, but 411 average power per run. My best yet! (Obviously, a run that triggers the error-handling code will be less expensive, as writing and arm-moving won't happen.)
I'll get ready to send this to the team.

[ ~ ~ ~ ~ ]

So I was going to show the previous design to Derrick, but I happened to take one more look at my original design, first. Then, inspiration hit me.



     

The reason I'd had to leave lots of free space on the radio MC, the first time around, was that I was using both of its registers. The thing is, I was using those two registers so that I could have the crate ID in one, and '0' in the other! Depending on whether the crate was supposed to be stored or retrieved, the radio MC might swap the crate ID between registers. Then, I'd send the registers out in a set order - so swapping the registers would change which value went out first.

I realized it didn't need to be this complicated. Since one of the values that's sent out is always a '0', those sends can be done with some 'mov 0 x1' instructions and conditional flags. This way, the design doesn't need to use registers at all - it can send the crate ID straight from the radio's buffer, and the '0' is hardcoded! In short: the radio MC can become a MC4000, pain-free.
I'm not actually sure why I did my first prototype the way I did, come to think of it.

Anyway, I'm pretty sure this is my final design. It brings together everything I've gathered from previous versions:
• The radio MC is now at maximum efficiency.
• The memory-chip MC will ask for both values ('0' and the crate ID) at once, to make sure that if nothing is found during the search, the radio MC isn't left hanging sending the second value. This version will perform proper error handling, and do nothing if a crate or empty slot is not found.
• The arm and grab MCs are the updated, power-efficient design.
• Because I've gone back to the old version, it can handle 13 or 32 slots total, depending on memory chip size.



Final statistics: ₯18, 397 average power per run. I think it's a pretty good little machine, and I can't wait to see it in action.




I am looking forward to this (eventual) 7-course french dinner! It's actually pretty exciting to be part of Avalon City's... well, bootstrapping phases, to put it simply. Even if I do have to do a little office camping for the time being, seeing the city come together is worth it.

And now— I'm going to take a walk in the sunshine.

sincx
Jul 13, 2012

furiously masturbating to anime titties
Glad to see this thread continuing!

Grayshift
May 31, 2013
Lovely solutions.

Looking forward to seeing if the new NPC chatter lives up to Joe and Jie.

bewilderment
Nov 22, 2007
man what



I do appreciate the little bits of personality Jie had behind his professionalism.

Quackles
Aug 11, 2018

Pixels of Light.


Recommendation: Beyond the Clockwork




This is interesting. I didn't know I'd be subscribed to Sun Haotian's book club when I got this email address, but it beats getting spam every day. I'll have to check the book out.
That said, I can't think we'll ever have completely 'solved for our bodies', as Sun puts it. Suppose, for example, we find a way to prevent aging. We'll still be at risk of one kind of disease or another. And then there's the issue of inequality - a lot of people go hungry that our modern food system has the capacity for, etc.

Of course, for all I know, Sun could have considered inequality as part of doing this solving. Maybe he's got a building full of political scientists and a herd of lobbyists ready to go.
I wonder if he has looked in that direction, as well as at technological solutions?

Quackles
Aug 11, 2018

Pixels of Light.


Handheld Timer

It's been a bit since my last entry, but Avalon City has been growing astoundingly fast. We've gotten several new plates in already, at the rate of one every few days. Each plate is bare metal, attached to pilings* going down into the ocean once it's in place. From there, work crews start laying surfaces, installing foundations (fun fact: buildings are bolted to the plate base), marking spaces for roadways, and so on. I've seen my new (under construction) apartment building, and it looks pretty impressive - for a building skeleton.

*No, I don't know what the pilings are attached to. We've got kind of a deep seafloor beneath us, though I don't actually know if, or how, we're tethered to the bottom - but I assume we are.

On a more personal note, I got to see my robot arm in action in the Ocean's Bounty chemistry lab. It works like a dream! (The crates are a bit bigger than I expected. Think containers the size of a filing box - or larger.) I should note that I only visited the lab once - getting in involved wearing a cumbersome getup including a full hair net, labcoat, etc., so I've been generally staying away from the place.

It looks like they're going to need my skills again, though. And this job isn't anything I could have expected.



Yep. It me, creator of timers and stopwatches. Though this'll be a stopwatch in a hardened case, at least, so it's... kinda-custom. Let's see what they're after.








This doesn't seem too hard. It kind of reminds me, a little, of the scale I did back at Longteng - once you got used to the 'off/on/do stuff' mode, everything sort of fell into place and was simple.
Let's see what we can do...

[ ~ ]

This was a lot harder than it looked at first glance.

For those wondering why, it's a combination of the way the buttons are laid out and the timing loop. The loop is the biggest problem - the timer increments every two time units, but you need to listen for input on the buttons every time unit.

Suppose we had one MC doing the timing, and another monitoring for input. As a general rule, if you use XBus to communicate between two MCs, and the receiving MC checks for status updates every time unit (using an slx to do so), the MC sending the updates needs to send something every time unit.
This means that, if you have a MC that enters a real-time loop (such as our timing MC), and you want to stop the loop by means of a signal from outside it (such as from our input MC), the loop either (A) can't include a slx to receive messages (in which case you need to find some other way to stop the loop, probably involving simple I/O), or (B) you have to send the looping MC an XBus message every time unit. Either situation stinks in our case - especially as a start-stop button press could come in the middle of the two-time-unit wait between updating the display, so we can't even make the timing MC only respond every other time unit.

On top of that, the way the buttons are laid out brings further problems. The start-stop button starts and stops the timer when it's on, sure - but it also turns the timer on. It's not like reset-off can be a dedicated power button - both buttons have to be in a position where they can update the display to and from -999 (blank, indicating 'off').

So this took me the better part of a day to come up with, and now I have a roaring headache.



   

Here's what everything is.

The MC6000 on the left handles the input. Its acc tracks whether the timer is running (0 = stopped, 100 = running), and its dat tracks for whether the timer is on or off (0 = off, anything else = on). If the start-stop button is pushed, it checks if the timer is on - if so, it'll toggle acc with 'not' to set it to running/stopped. If not, the input MC will send a -1 to the display-handling MC6000 on the top right, to let it know to turn the display on. (It updates its dat with the value the display MC sends back.)

If the start-stop button has just been pushed and the timer is now running, the input MC will send a '1' to the timing assist MC (the MC4000 on the lower right) to let it know to start the timing loop. The input MC does not stop the timing assist MC - it'll read the start-stop button and do that by itself.

If the reset-off button gets pushed, the input MC will (assuming the timer's not running) send a '-1' to the display MC, letting it know to reset the display. It'll update dat using the display MC's reply, which indicates whether the timer is now on or not.


The small MC4000 on the bottom right is the timing-assist MC. When it receives a '1' (or any positive value) from the input MC, it starts the timing loop. During every time unit in the loop, the timing MC will use not to swap its acc between 0 and 100. It sends this value to the display MC on its output line (x1). The loop continues until the timing MC sees the start-stop button pressed again; then, it goes back to waiting for messages.

If the timing-assist MC receives a '-1' (or any negative value), usually from the display MC, it'll reset its acc to 0.


Finally, the MC6000 in the upper right is the display-handling MC. Its acc keeps track of the value currently shown on the display.
When the display MC receives a '0', it adds 1 to this value (and updates the display afterwards; every change to acc results in a display update sooner or later). Coincidentally, the display MC will receive a '0' every other time unit from the timing-assist MC, as long as the timing loop is running.
When the display MC receives a number greater than 0, it does nothing. (This is to ignore the '100's the timing-assist MC sends every other other time unit.)

Finally, when the display MC receives a negative number (-1 or less), it will reset the display. If acc was already 0, it will be set to -999, which turns the display off; otherwise, acc, and the display, will be set to 0. (This has the side effect of turning the display on if it was previously off.) Once the display is reset or turned off, the previous value of acc will be sent out to the input MC, to be used to determine whether the timer is now on or not.


Phew. I'm very, very unsatisfied with this. It's ₯15, uses 947 average power per run, and just screams 'overcomplicated' at me as I look at the spec. That said... I've been working for hours on this, and the day's almost over. I'm going to grab some fishcake and shut down my tablet for the day.

I'll come back to this tomorrow.

[ ~ ~ ]

As you can imagine, I was pretty dissatisfied with my last design. So, the next day, I threw everything out and started thinking in terms of inputs, states, and outputs.

The inputs are, of course, the two buttons. The states are Off, On (but not timing), and Running (on and timing). And the output actions that the timer needs to do are as follows:

• Turn display off
• Turn display on / set display to 0 (these both use the same command)
• Increase display by 1
• Change internal state from Off to On
• Change internal state from On to Running
• Change internal state from Running to On
• Change internal state from On to Off

I also listed about all the possible things the timer might need to check (test):

• If the start-stop button is pushed
• If the reset-off button is pushed
'nough said.

• If the timer is on or off
Used to determine behavior of both buttons.

• If the timer is running or not
Changes behavior of the start-stop button; if the timer is running, the reset-off button is inert and the timing loop happens.

• If the timer is displaying a value above 0
Used to determine whether to set the timer to '0' or turn it off when reset-off is pressed.


I was going to use those lists to try and make a one-MC version of the timer - my reasoning was: if each test and effect listed above uses one instruction, the challenge was to figure out which tests and instructions could be combined together, until I had 14 or less instructions and some way to arrange them that worked.
I couldn't find a way to do it all in one MC, but I did get the design slimmed down significantly from the first version:



 

Yeah. The first version was a bit of a rat's nest, but this one is much better. It turns out there was one thing I assumed based on the spec, but the test cases don't back up: The timer doesn't have to respond to button presses during the two-time-unit wait period while it's running - so I can just have the design wait that long with slp!
Because of this, I don't have to track 'half-values' where the timer is paused in the middle of a two-time-unit wait period, so that was a big help in making the new design.

Interestingly, though I started this design from scratch, parts of the code ended up being very similar (structurally speaking) to my earlier design. There's an input-handling MC and a display-handling MC; the input MC's code is a lot like a combination of the input MC's and the timing-assist MC's from the last design. The display MC is also fairly similar to the old version's display MC.


Here's how the new version works:

The left chip is the input-handling MC. For the most part, it behaves almost the same as the input MC from the previous version. The MC still uses its dat to determine if the timer is on or off (0 = off, anything else = on), and its acc to determine if the timer is running or not (0 = stopped, 100 = running.)
• If the user pushes start-stop, it'll check if the timer is on, and then either toggle the running/stopped status with a not, or send a -1 to the display MC on the right to handle the 'turn on' request.
• If the user pushes reset-off, the input MC will check that the timer isn't running. If not, it'll send a -1 to the display MC, indicating 'turn off or reset the display'.
In either case where a -1 value was sent out, the display MC's reply will say whether the timer is now on or not. This reply gets stored in the input MC's dat.

The main difference between the two version's MCs is this: if the timer is in the 'running' state, then the input MC will finish its script by waiting two time units, then sending a 1 to the display MC, which means, "add 1 to the value on the display".


The display-handling MC, on the right, is also very similar to the previous version's display MC. It still uses its acc to store the value on the display, and any changes to acc are pushed to the display. However, the sequence of signals it responds to is drastically simplified.

• If the MC receives a 1, it'll add one to the displayed value.
• If the display MC receives a -1, it'll reset the display to 0 if it wasn't showing a '0' (turning it on in the process), or turn off the display if it was already showing a '0'. The previous value that was on the display gets sent back to the input MC, as before, to signal whether the timer is on or not.
Usually, the display MC will get '-1' pings only when the user pushes a button, but it will get '1' pings every two time units when the timer is running.


This version clocks in at ₯10 and 403 average power per run. I'll just check it over a bit before I send it off.

[ ~ ~ ~ ]

Just a few more improvements! Here's the final version of the design.



 

I made two changes since the last version.

First off, I realized I was duplicating some code in the state-tracking MC - the bit that signals to the display MC to turn on, off, or reset the display to 0.
("+ mov -1 x3 / + mov x3 dat".)
I was able to remove the duplicate lines, and arrange things so that the code 'fell through' to the remaining copy through conditional flags.

Second, I was able to bump the display MC down to a MC4000 - I'd used mov -999 acc twice, and I was (once again, through the power of conditional flags) able to cut it down to one copy. The new mov -999 acc always runs during a display-reset request, even if acc (and the display) are immediately set to 0 right afterwards, so there'll be a very slight decrease in power efficiency.


The new version's statistics aren't bad. ₯8, and about 407 average power per run. I'm glad I was able to simplify things, though. The original version of the timer was too embarrassing to release! Now, though - the Ocean's Bounty project can have the timer they deserve.



I'm torn between curiosity about what went down, and relief I wasn't there, given how Derrick's talking about it! But it feels like things are slowly coming together. More and more plates are added every day, and buildings continue to rise. It feels like Avalon City is becoming a proper... well, a proper city.
So far, I'm excited to be a part of it.

Glazius
Jul 22, 2007

Hail all those who are able,
any mouse can,
any mouse will,
but the Guard prevail.

Clapping Larry
I'm surprised he hasn't just got people yelling at Siri to start reaction timer alpha-3. I suppose a few cents of microcontroller to do the job reliably are more preferable than the handbrain part of a scifi future.

FAT BATMAN
Dec 12, 2009

I wonder how many of these wheel-reinventing moments they’re going to have with the insistence on being like a self-sustaining arcology.

Quackles
Aug 11, 2018

Pixels of Light.


A Message From SleepCubes



Oh, god drat it.

[sigh] OK, let's think about this. I know the lock was proof against most things. I designed it myself, after all, and I cut no corners. If I had to guess, though, some enterprising thief— or gang of thieves, more likely— managed to bamboozle the clerk and make off with a master key. It only takes one filched master key before the secret is out and anyone with a card writer can make copies, so from there, I imagine things went sour very quickly.

Two things come to mind, the more I think about it:

[1] This wasn't a matter of if it would have happened, but when. Their system design had fundamental flaws we couldn't do anything about, and still wouldn't be able to do anything about if they sent the locks back to us - so now, they'll need to be replaced.

[2] Given what I know about SleepCubes and how they operate, I am almost certain that they will replace my locks with ones that have, somehow, more security holes than what I was able to come up with. Put another way: I don't trust them to pony up the money for proper security the second time around. Sic transit gloria mundi, I guess.

Quackles
Aug 11, 2018

Pixels of Light.


Cat Feeder

They used to say that if you built a better mousetrap, the world would beat a path to your door.
I haven't actually seen any mice in Avalon City— perks of bringing everyone in by boat, and making sure there's no ratty stowaways in the motor launch for the last step— but work has been slow since I moved into my new apartment, so now I'm working on a better mousetrap feeder.

The 'mousetraps', in this case, being a pair of cats.



Perhaps I should provide a little more background on how things are going before discussing the current job. The Ocean's Bounty project is progressing well. They've been working on a lot of recipes in the cleanroom, and also sent a submersible carrying some gnarly-looking support structures down into the ocean near the city, to set up kelp beds they can use to get the raw materials to feed the city in massive bulk. (I looked up kelp - apparently, it grows very fast.)

The residential areas, as I mentioned, are more fully built - at least, mine is. I see new buildings still going up on a regular basis. My apartment is actually really nice - it has a view (of some city buildings and a rooftop, but a view is a view), one bedroom, a small kitchen, and basically everything you'd expect to see in a living space. I get to work by electric car, and yes, it is self-driving. Mr. Haotian's plan seems to be to structure the city with the majority of what you'd call 'service jobs' pre-automated.

I'm still not sure the concept could work elsewhere in the world - economic inequality is a hell of a thing, and part of what biases towards this system working out here is that the great majority of the residents of the city are scientists or engineers of one kind or another, or barring that, already had some sort of fulfilling, non-automatable occupation (such as the construction workers who work to expand the city every day).
The catch is: Sun invited all of us. I don't think such a system could be easily imposed on any other city on Earth without massive disruptions and potential generalized misery from people who had their jobs replaced by bots - at least, not without significant ways of supporting the place's people to make the transition.

Anyway, back to cat feeders. Even though there's a lot of things going on in Avalon City, I've been experiencing a bit of a work drought. The Ocean's Bounty project is progressing, but hasn't needed my help for anything for a while. To be honest— I've been pretty bored!!
This is where Irina comes into the picture. I'm not sure what team she's on, but she's Lisa's friend, she needs help, I'm not busy, and she seems nice enough. So: time to build a cat feeder.





The basic idea is pretty simple. On getting the collar ID (1-3) dispense size units of food type type for that ID ... unless the cooldown for that collar is still running from last feeding, in which case do nothing.

I can see two decently-sized problems ahead of me with this design. Problem number one is the sheer number of inputs this design has: in addition to the tag reader, there's three simple I/O switches and six XBus dials. All of them are going to have to be connected to something.
Problem number two is similar to the issue I faced on the handheld timer: if you have a MC waiting for a long period of time, either with a loop or with a slp instruction, the MC can't feasibly respond to XBus input (at least, not without a design that checks the value of a received XBus pulse every time unit, where one is always sent regardless of circumstances. But such a design would probably be horribly inefficient, and I'm not gonna try it).

So, step one for me is to figure out a way around both issues that's at least reasonably efficient. I'll update this post once I come up with something.

[ ~ ]

This is my preliminary solution to both problems. The project isn't done - rather far from it - but the most important parts are in place.





     


The idea is that, when the MC attached to the tag reader gets a tag, it'll send the tag ID (minus one) down to the two big MCs clustered around the memory chip in the bottom left. The memory chip records how long is left on each pet's cooldown timer, and the two MC6000s act as its attendants.

The more centered of the two big MCs responds to input from the tag reader MC. It checks the memory chip to make sure that the pet's cooldown timer is '0' - then sets the cooldown to its full amount, using the value it gets from the small MC at the bottom, just to the right of the board's centerline.
(The small MC's job is to serve as a hookup point for the three 'time' dials, and it will yield the correct dial's value when given a tag ID.)
The timer-checking MC6000 will eventually report back to the tag reader MC whether the feeding is 'go' or 'no go', and the tag reader MC will send signals out accordingly - but that's not in yet.

Meanwhile, the MC6000 on the far bottom left is the timer MC. Every time unit, it will go through the memory chip, subtracting one from each pet's cooldown timer. (It turns its p1 on while it's doing this - the timer-checking MC will wait while this MC sends on p1, to prevent the possibility of it reading the wrong value.) This MC operates independently, allowing the timers to run freely.

This is a good start, but I'll have to get the rest hooked up. There'll have to be another small MC for the 'size' dials, like there's one for the 'time' dials right now. On top of that, the small, blank MC4000 on the right will get the information from the tag reader MC.

It'll be tricky to fit it all, but I'm not worried. I can do this!

[ ~ ~ ]

Some reorganization and coding later...





   

   

Here's the finished design. The timer MC is the same, and the tag reader and input checker MCs haven't changed much from the previous prototype - the input checker MC is now done, and properly notifies the tag reader whether or not it's OK to dispense food. If it's OK, the tag reader sends the tag's ID to the MC attached to the 'size' dials, in the top center, to get the correct food size, then sends the size and the tag ID along that big wiggly wire leading to the MC on the far right.

The far-right MC (responsible for actually doing the feeding) uses the received tag ID to get which food type to use - A or B - from the input expander above it, which is attached to the 'food type' switches. From there, it sends the 'size' value to the correct food output for one time unit, then turns the food outputs off and waits, letting everything start over again.

There's just one fly in the ointment with this design: the timer MC on the bottom left, always running in the background, weighs the statistics down a ridiculous amount. This version costs ₯25, and uses a whopping 3723 power per run, on average. I'm not sure you could run the design properly on even the largest battery!

So: I'm left with the job of coming up with a better alternative, if I can find one. This may take some time...

[ ~ ~ ~ ]

Sometimes, the solution is blindingly simple, and that means you don't see it.





 

   

I'd said up above that it was hard to make XBus work with long timed waits. I hadn't said anything about simple I/O. It took a chance remark from Derrick to get me pointed in the right direction (something about 'turning the MCs off'). The new version is a lot simpler, a lot cleaner, and most importantly, a lot less power-intensive.

When a pet activates this version of the feeder, the new tag reader MC (which has only two lines of code!) sets a simple output line to the ID# of the tag. The simple output is attached to three MCs (in the middle), each coding for one separate tag.

When a center MC sees the tag number it's coded to respond to, it'll send an XBus message to the MC on the far right (which does the feeding), indicating the tag ID, as well as the type of food to dispense. Then, the tag-handling MC will sleep, for a period of time equal to the 'time' dial attached to it. This prevents duplicate feedings - the tag reader MC still sets the simple output to the ID#, but the associated center MC won't listen until the cooldown period is over.

Once one of the center MCs notifies the new feeder MC, on the far right, that there's an incoming request, the feeder MC will use the received tag ID to determine the right amount of food to dispense (from one of the three attached 'size' dials). It uses the received food type to send that value to the right output, and so whatever pet is outside the feeder gets fed.

I'm a lot happier with this! It's not crammed for board space, it's only ₯17 instead of ₯25, and it uses 545 average power per run instead of 3.7K. What's not to love?
The design was a good lesson in when (not) to use XBus - and I bet Irina will be happy, too.



Aw, aren't they cute? And I only noticed now, but each cat has their own email address (look at the CCs in Irina's first message)!
I wonder what the 'more serious project' could be...

Bobulus
Jan 28, 2007

I think there's one tiny tweak you could make on that last design. Not super important, but...

Rather than having both + and - jump to Feed, if you have it always copy X3 to acc, and then overwrite it with X1 or X2 based on the conditional, you get the exact same result in terms of power, with two fewer lines of code.


That said, my solution was so horribly convoluted compared to yours that I feel bad even commenting! I had to redo it multiple times to even make it fit on the board, and then it was worse in all three grading criteria! That 'sleep the length of the wait' idea is genius! :D

GuavaMoment
Aug 13, 2006

YouTube dude
You can put most of those 'slp 1' lines at the beginning of the chip instead of at the end; saves power. Cats in this universe do not ask for food on the the first possible moment they can. What an unrealistic universe! At the end of the final chip, instead of '+mov 0 p1, -mov 0 p0', you can instead 'tcp p0 p1'. It clears both p0 and p1 and only uses one line of code.

Quackles
Aug 11, 2018

Pixels of Light.


Target Practice

It turns out my 'robot arm' was even more useful than I could have predicted. As I write this, I just finished troubleshooting a variant of the design to be used in a pair of giant-size cargo cranes at Avalon City's port!! It's worth noting that the cranes were produced 'in-house', so to speak - about half of Avalon City's projected industrial areas are at least complete-adjacent, and the rest is under construction. The city is a lot bigger than I imagined when I saw that diagram. I don't know what sort of population Mr Haotian's planned for exactly, but I bet the numbers are big...

Unfortunately, the latest job that came into my inbox pretty much killed my excited mood.









I'm really not sure how I feel about this. On one hand:

• I really don't feel happy about defense-related projects, I'm sorry. Just, on principle. (I didn't even know Avalon City had security teams until this email...)
Especially after making the badges before moving here.

At the same time:

• If you have a city of X thousand people, speaking purely pragmatically, you probably will eventually need some sort of people-to-provide-security role, simply because of how human nature is.

In addition:

• The police-force-types will be armed with theoretically nonlethal weapons (I'll have to look into this - humankind has historically been really bad at making 'weapons' to stop someone without hurting them).
• It's not like my accepting or rejecting the project will change things - according to the spec, literally all I'm making is a fancy dartboard.

I'll do it... with some light reservations.


So, looking at the spec again, one very large thing jumps out at me: the display outputs are XBus... and unlike the LuX Industry 7-segment displays I used for the timer and scale, the score displays on this dartboard need a value to be output to them every time unit. This pretty much guarantees that I'll need to have the central parts device in an active loop while 'on', not just an input-driven one. Fortunately, detect is a simple input, so I can check it at any point during the time unit without any trouble.

The other thing I noticed is the requirement to use the Pythagorean theorem to calculate the straight-line distance from the center of the target. The Pythagorean theorem is: X2 + Y2 = Z2 - here, X and Y are the horizontal and vertical components of the distance from the center, and Z is the straight-line distance I need to find.
Squaring the X and Y distance is as easy as multiplying each value by itself (after subtracting the distance from 50 - if the result is a negative number, squaring will make it positive). But 诚尚Micro MCs don't have a 'square root' instruction; thankfully, though, I don't need one. Distances of 10, 20, and 30 from the center translate as Z2s of...

Z < 10 == Z2 < 100
Z < 20 == Z2 < 400
Z < 30 == Z2 < 900

It's even better than it looked at first glance. I can just use dgt 2 to get the hundreds digit of the calculated result, then output the addition to the user's score based just on that!

So, based on what I've said so far, here's what this design will probably need:
• One or more MCs to perform the distance calculation
• A MC to coordinate everything and respond to input.
• A MC for storing and displaying the score - possibly two, one for each display. We'll need this in part to handle the flashing effect, which doesn't seem a good place to put elsewhere.

Let's get to work.

[ ~ ]

By now, if you've been reading this blog for a while, you'll know that "but it almost works" is a refrain that comes up now and again.

And, well— I have a prototype. And it almost works.





   
   

The design's a lot like I predicted. The two MC6000s on the left calculate the incoming shot's distance from the bullseye - the first MC (far left) performs the actual squaring and gets the hundreds digit of the resulting number. Then, the second MC (not as far left) takes that number and turns that into a score value.

The MC6000 just right of center coordinates everything. If a shot's detected, it'll get a score value from the calculator MCs on the left, then send that score to the small MC4000 just above it (which sends it on to the correct display MC, or it's supposed to. We'll cover this MC next). The central MC also keeps track of the number of shots fired; if it's the middle of a set, it'll send a '0' to each display to keep them lit up while the device waits for the next shot. If a full set of 8 are fired, it sends the special value '-900' to each display; this will trigger the flash sequence.

The MC4000 just above the central MC is there because of a problem I didn't foresee during the original design. When the central MC sends a score value out to boost a display MC, it needs to send '0' to the other display MC - or the display MC that isn't being updated will go blank. The small MC - effectively a distributor - makes sure the score updates get to the right display MC, with 0s sent to the other one.

Finally, the display MCs (which both have the same code) are the two big MC6000s on the far right. Each MC tracks the value for one display. Whenever the display MC gets a ping, it'll update its value by adding the incoming value, then display the result. (This does mean that the display MC needs to be pinged every turn when the board is on - that's the central MC's job.)
If a display MC receives the value '-900', it'll flash the display three times, then clear its value and turn off.


Now for why it almost works: I'd mistakenly assumed that the users took turns, and this design reflects that - note that the distributor MC4000 just sends incoming score updates first to one display MC, then the other next time it receives input. This is actually wrong. The first user takes four shots in succession, then passes things over to the other user.

I'll just have to make a few slight adjustments, then I'll have a working design.

[ ~ ~ ]





   
   

Adjusted version ahoy! This design only has a few changes from the first version:

• The distributor MC now keeps its own count of how many shots have been fired. It sends the results to the correct display MC accordingly - the first four to the score-1 MC, and the next four to the score-2 MC.
• The display MCs and the central MC have all had their code slightly streamlined to save power. It still runs the same.

The calculator MCs haven't changed at all. And more importantly... this version works! It's ₯28, and 1100 average power per run.
It's done; it's serviceable; let's get it out the door.



Now that that's done, I can get back to my usual work, which at the moment seems to be installing variants on those robot arms all over the place. It's actually pretty nice - I get to see a lot of the city, and I'm doing something both meaningful, and guaranteed to be unequivocally useful.

One last thing: I looked into what the 'nonlethal weapons' consisted of. They are NOT tasers, which is something I was worried about - I was previously aware that tasers can cause serious harm even if they don't necessarily kill you.
The 'weapons' Enzo had me build a dartboard for are net guns! They're larger than traditional guns, use some sort of spring mechanism, and fire a capsule containing a compressed net covered in some sort of glue. On impact, the capsule breaks open, and entangles/glues whatever it hit. Dummy capsules for training are the same weight, but don't contain glue.
(It's not a perfect solution by any stretch of the imagination - the impact could knock someone over on a bad hit and maybe give them a concussion from falling over, or do some damage if aimed at someone's head - but it's still better than actual firearms. I'll choose to be cautiously optimistic.)

Quackles
Aug 11, 2018

Pixels of Light.


Avalon City Events Calendar



I've been to three out of four of these. They're pretty cool! I really like the 'Currents' one simply because of all the things you can find out about. Biochemical developments, new materials... the last time I attended, there was even a group that had a brain-computer interface project starting up. It's a lovely way to find parallels between your work and other work, too, like the description says.

That said, 'employee-citizens' is never not going to sound suuuuuper pretentious. Sorry, Mr Haotian.



Bobulus posted:

Rather than having both + and - jump to Feed, if you have it always copy X3 to acc, and then overwrite it with X1 or X2 based on the conditional, you get the exact same result in terms of power, with two fewer lines of code.

Thank you! That's a lovely design pattern to use with a tcp - I'll have to remember that.


GuavaMoment posted:

You can put most of those 'slp 1' lines at the beginning of the chip instead of at the end; saves power. At the end of the final chip, instead of '+mov 0 p1, -mov 0 p0', you can instead 'tcp p0 p1'. It clears both p0 and p1 and only uses one line of code.

Very clever - thank you! After making all these changes (yours and Bobulus's), it's down to 544 average power per run (from 545 - it looks like only moving the line on the tag-reader MC had an effect on the power usage, as the slp 1 lines for the center chips are locked behind conditional flags).
In addition, the project is down to 30 lines of code! (It had 33 before.) It looks very clean.

GuavaMoment posted:

Cats in this universe do not ask for food on the the first possible moment they can. What an unrealistic universe!

I'm blaming the test case generation algorithm. Though maybe Valence and Isotope are particularly well-behaved...

Adbot
ADBOT LOVES YOU

AceOfFlames
Oct 9, 2012

Guys, I’m starting to get creeped out by Chinese Elon Musk and his Rapture knock off.

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