MicroController

by ljdp

Program circuit network logic using FAL, a Factorio Assembly Language.

Content
5 years ago
0.16
6
Circuit network

g Questions and a few issues...?

6 years ago
(updated 6 years ago)

I've been playing around with this mod a bit and have a few questions...

Q1. Is it possible to change the output signal to something other than black?
Q2. Is there a key for the index required to access each signal?

...and encountered a few bugs:

B1. If I open the programming windows while the program is stopped, the stop button is disabled. Pressing the run button doesn't enable the stop button. I have to close the programming window and reopen it.

B2. If the program is longer than 16 lines, the line numbers don't scroll with the program. (They always show lines 1-16.)

B3. If you make an edit while stepping through the program, the microcontroller doesn't notice the edit unless you hit the stop button and start stepping again. This behavior is fine, but it would be helpful if it were noted in the instructions.

[Edit Feb 1]
Bug 3 is worse than I previously thought... it appears I have to run the program, then stop it before I can successfully step through it.

[Edit Feb 2 - Additional information and clarifications]
I realized last night that some of the instructions are moving the signals into the registers, not just moving the signal's values into the registers. Understanding this subtlety has helped.

B2: It looks like programs are capped at 16 lines, even though it's possible to scroll beyond 16 lines. Code beyond 16 lines is deleted. I'm not sure what behavior is intended.

B3: Stepping in general behaves weirdly; I've kind of given up using it.

B4: Line numbers don't change size with UI scaling, but the lines of code do.

B5: Copy/paste don't seem to work.

Q1: I've figured out how to search for a specific input signal and output that value to an arbitrary signal but it's kind of cumbersome. (No particular reason I'm doing this... simply learning how to use the microcontroller.) My design requires a constant combinator (with the signal of interest and the desired output signal) wired to one input with the signals of interest wired to the other. Is there an easier way to use a signal type in the code, or do I have to capture it from an input?

Q2: It appears the red and green wires carry only the active signals in an array, not all the signals as I previously thought, and I use the redN and greenN (or red@/green@) commands to move a signal from the array to a register. Is there any rhyme or reason behind how factorio orders the signals in the array?

Suggestions:
-It took me a long time to figure out how to use the FIR/FIG op codes. I kept putting an integer in the register thinking it indexed into the array, or read the values of the signals. It would help if the docs clarified that you have to have a signal in the register when using that op code.

-Additional Op Codes/Registers
--JSR/RET - This might be overkill if code is limited to 16 lines, but if we can exceed 16 lines this would be very handy.
--CNR/CNG - (Count Red/Green) Read-only registers containing the number of signals on the red/green wires. Useful for iterating over the signals.
--IPT - A read-only register containing the value of the instruction pointer.

6 years ago

Thanks for the thorough report.
Q1. Yes, you move a signal to the 'out' register, i.e. mov mem1 out
Q2. No there is no key for specific index. Items in the game are keyed by strings i.e. 'iron-plate', and I didn't want to have strings in FAL.

It's limited to 16 lines of code by design. The line numbers are actually images, not text, so I can highlight them and get the spacing correct. Unfortunately I did not foresee that it would mess up at different UI scales.

Copy/paste via keyboard does not copy over newlines. There's nothing I can do about that as it is a Factorio bug, that is why I added the copy/paste buttons.

In the documentation, when I refer to a signal, It means both the item and the count, unless I explicitly refer to 'signal count'. Every register always has a signal, I use Black-0 as a NULL signal. The FIR/FIG commands have the signature: "FIR R" / "FIG R", where R = Any memory or output register. If you are looking for a specific input signal, you can store the signal you are looking for from a constant combinator, which only has to be done once at setup, you can then remove the constant combinator and look for further signals with FIR/FIG.

From what I have gathered, in the Factorio UI, i.e when you click on an electric pole, it orders the signals in alphabetical order, but the actual order in game memory seems to be the order that they were created. For instance if you create a bunch of signals in a constant combinator, the order it outputs those is left to right, top to bottom.

I like the idea of some extra read-only registers. Adding subroutines might be overkill, but maybe I might add an advanced MicroController that can have subroutines and JMPs with labels.

6 years ago
(updated 6 years ago)

I've added four new read-only registers ipt (mem5), cnr (mem6), cng (mem7) and clk (mem8).
clk is a monotonic clock that starts when you first open a MicroController and is always running, even when the program is halted.

6 years ago

This is a really great idea, and it reminds me of the excellent game SHENZHEN I/O. It's deliberately minimalist, which is cool.

I'd love to use it to do clever things with AAI Programmable Vehicles!

Unfortunately, with AAI vehicles, it's often necessary to read multiple inputs and write multiple outputs. For example, an input coming to a microcontroller from the zone scanner might be:

  • { "land" = 1, "x-pos" = 300, "y-pos" = -200, "iron-ore" = 10000, "id" = 128 }

The exact signals present might vary depending on the tile scanned. For example, you might receive "copper-ore" instead. And there are also scanners for tiles and vehicles.

An output from the microcontroller might be:

  • { "hauler-id" = 5, "x-pos" = 324, "y-pos" = 123 }

This would send the specified hauler to the specified X/Y coordinates.

I wonder whether there's some clever way to do this without using strings in FAL. I could imagine having special input and output "pins" in the UI, which could be bound to specific signals when the microcontroller is set up. You could have maybe 8 little input "pins" on the left, which could be bound using clickable boxes in the UI, setting "in1" -> (picture of iron ore), "in2" -> (picture of x-pos signal), etc. And there could be output "pins" as well, mapping maybe 8 pin numbers to signal images.

To send hauler 6 to 212,-142, you'd use the GUI to bind "out1" to the "hauler-id" signal, "out2" to the "x-pos" signal, and "out2" to the "y-pos" signal. Then you could write:

mov 6, out1
mov 212, out2
mov -142, out3

...and your ore hauler would head to the specified coordinates.

Anyway, it's a very cool mod, and I totally understand you're looking for a specific aesthetic. But I feel like it might be possible to interact with many more kinds of signals with just a few tweaks, and without making FAL into a high level language. Maybe binding pins to specific signals could be the "level 2" version of the controller?

6 years ago

Interesting ideas! I'm starting to think it could be done with a separate entity, like a "demuxer", that has the input and output pins as you describe. You would place is just before the input to a micro controller, then you would still use integer memory addresses. For multiple outputs, the micro controller is based off the arithmetic combinator (all modded entities have to be based off an existing entity), and I haven't figured out a way to give it multiple outputs (basing it off a constant combinator introduces a bunch of problems). Again, I could solve this with a separate RAM entity, where you output the address for 1 tick, then output the signal for 1 tick and it stores it.

Thanks for your feedback!

6 years ago
(updated 6 years ago)

In the meantime, I recommend you use this mod alongside Useful Combinators. https://mods.factorio.com/mod/UsefulCombinators

It has a 'Converter Combinator', which essentially does I described above. Although you must keep the input and output signals different, it crashes if you convert input to itself.

6 years ago

Thank you for the recommendations!

Some of the other computation-related modules (Computer Core, AAI Programmable Vehicles) appear to use linked sub-entities, so that a computer entity can have two terminals, one on the left and one on the right.

Computer Core is actually pretty interesting. It's a much higher-level programming environment than Microcontroller, and it requires yellow science, but it provides a toy "operating system" that runs Lua scripts with a limited API. You can read and write signals, or use the "WAN" to send events between multiple computers. There might be some good coding ideas there for handling outputs without being limited by constant combinators.

Computer Core has a "learning Unix for the first time" vibe, which some people may like. But I really like Microcontroller's "SHENZHEN I/O" vibe, and the fact that it's available earlier in the game.

By the way, have you thought about putting Microcontoller behind its own research? It could be an easy research that you can get right after circuit networks.

6 years ago
(updated 6 years ago)

I just discovered your updates yesterday and tried them out. Thanks for the bug fixes and new registers! I really like the new feature of connecting microcontrollers via ports. Being able to insert information directly on an adjacent micro's memory register is very helpful! I'm using a rack of 3 micros to try and create a bulletproof Kovarex controller. I'm running into frequent "attempt to index a nil value" errors, but I haven't figured out if it's a bug in my code or your code. :)

A few requests/suggestions, which may or may not be in line with your vision:
-In keeping with the three letter op code theme, allow "grn" when referencing the green wire.
-A debug view that displays the values currently in the registers. (Bonus: and on the input wires.)
-Expand the allowable program size to 32 lines. With all the register shuffling required it's hard to do anything interesting in only 16 lines.
-Allow comments in code.
-Store programs like blueprints and provide program books to organize them.
-Allow East/West port connections.
-Expand the set instruction to allow simple inline arithmetic. (e.g. "set ipt+2 mem4")
-Expand the jmp instruction to allow relative jumps. This would simplify development as lines are being added and removed. (e.g. "jmp -2" to go back 2 lines or "jmp +3" to jmp ahead 3 lines. "jmp +1" would essentially be a nop.)

Bugs?:
-For most in game entities, if I have their interaction window open and press 'e', the window closes. When the micro interaction window is open and I press 'e', the window closes and my inventory opens at the same time. This inconsistency throws me off every time.
-When I paste code into micro A, then use the mouse to select micro B, the code is not saved in micro A.

[Later]
I have more information on the nil value error. I don't believe it's a bug in my micro code, as I have two micros with identical programs. One displays the error, the other works correctly. The error is occurring when executing the "add 1 mem1" instruction. I have a saved game that illustrates the problem if you're interested.

[Edit]
I just realized extending the jmp instruction in the way I described is limiting and I believe--assuming you want that functionality--it would be better to create a new instruction for relative jumps. (jro? jof?) Creating a new instruction makes it so we could use registers to store the value of the relative jump. (e.g. "jro mem1") That syntax is already defined for the current jmp instruction.

6 years ago

I like the idea of a relative jump command. I was considering adding labels, like Shenzhen does it you can optionally label a line like:
label: mov mem1 mem2
jmp label

  • There are single line comments with #, can't remember if they work on the same line as instructions.
  • I will add a way to save/load programs in the future.
  • You can effectively have 32 lines by having 2 Microcontrollers next to each and using SYN, no?
  • Thanks for the bug reports. The first one is a known issue, not quite sure how to fix it yet, as I use my own custom gui, Factorio doesn't see it as an 'entity gui panel'.
  • Can you send me that save game? Or just tell me the steps to reproduce it.
6 years ago

Yeah, labels would probably be more clear than relative jumps in 95% of the scenarios. Relative jumps could be used to create more dynamic programs, but it's probably beyond what users would need in Factorio.

Attaching microcontrollers via ports is great for parallelism. It feels like a kludgy workaround for longer serial programs. Plus, I don't think there's any way to jump to a specific line in the other micro, which puts significant constraints on how the program is structured and what it can do.

I've added the save game to my public dropbox folder. (Here: https://www.dropbox.com/s/lfi9uw9sakvriaz/Microcontroller.zip?dl=0) Let me know when you have it so I can take it down.

The two single micros right next to the player are the controllers I mentioned. The code simply cycles the six inputs from the constant combinator through to the output. The top micro has the error; the bottom one runs correctly.

(I was using the bank of four micros on the right to explore the syn behavior. I didn't get very far due to the errors.)

6 years ago

thanks, I'll take a look at it over the weekend.

6 years ago

I'm not trying to nag, but I'm curious if you found anything yet?

6 years ago

Hey, I didn't get a chance to work on it last weekend, but will take a look this week.

New response