Shift Register+Bitwise display

This board is to show, discuss and archive useful combinator- and logic-creations.
Smart triggering, counters and sensors, useful circuitry, switching as an art :), computers.
Please provide if possible always a blueprint of your creation.
Post Reply
Yoyobuae
Filter Inserter
Filter Inserter
Posts: 499
Joined: Fri Nov 04, 2016 11:04 pm
Contact:

Shift Register+Bitwise display

Post by Yoyobuae »

After reading this other thread:
viewtopic.php?f=193&t=29444

I wondered if it was possible to extend the shift register idea to beyond 32 bits. So I came up with this:
WARNING. FLASHING LIGHTS
On each circuit network cycle each color signal is being shifted up one bit. The pattern could be anything:
WARNING. EVEN MORE FLASHING LIGHTS
The signals being shifted could be any signals (or even EVERY SINGLE signal). I only chose color signals here so they could be fed directly to lamps.

The display part might also be interesting on it's own. Each lamp is controllable by a single bit of a signal. It's seems scalable to many more signals without increasing the amount of combinators too much. Certainly something I will investigate in the future. :)

Blueprint:
shift_register.txt
Blueprint string
(7.95 KiB) Downloaded 334 times
Screenshot_2016-11-04_21-06-00.png
Screenshot_2016-11-04_21-06-00.png (1010.08 KiB) Viewed 7396 times
Input is the sole constant combinator (A in screenshot), turn it on/off to add low bits to the red signal.

The bit shifting part is accomplished by a single Arithmetic Combinator (B in screenshot):
Screenshot_2016-11-04_19-52-36.png
Screenshot_2016-11-04_19-52-36.png (314.85 KiB) Viewed 7396 times
When the highest bit of a certain color is set, then the lowest bit of the next color will be set on the next cycle. This is done with six Decider Combinators (C in screenshot):
Screenshot_2016-11-04_19-56-53.png
Screenshot_2016-11-04_19-56-53.png (223.12 KiB) Viewed 7396 times
Then when the highest bit of the last color is set, then the lowest bit of the first color will be set on the next cycle. This results in the looping behavior (D in screenshot):
Screenshot_2016-11-04_20-00-15.png
Screenshot_2016-11-04_20-00-15.png (249.54 KiB) Viewed 7396 times
Removing that last decider combinator or turning it's output off will result in the the register emptying itself out after a few seconds.

The rest of the combinators are basically to prepare the signals so the lights turn on/off as intended. Each lamp is configured to turn on when any bit higher than certain position is set (E in screenshot):
Screenshot_2016-11-04_20-07-39.png
Screenshot_2016-11-04_20-07-39.png (259.59 KiB) Viewed 7396 times
That patterns continues until the last light which turns on only when bit position 31 is set. Each row of lamps uses each own color.

There's three problems with the setup at this point:
  • Lamps don't just take the color which is set in the condition, they take the first color signal they can find (red if found, then green if found, etc)
  • Bits get shifted into the sign bit, resulting in negative values. Lamps will turn off with any negative value.
  • Lamps will remain on when any bit higher than their condition is set
The first problem was solved by filtering the signal color so that each row receives only a single color. This was done with six Decider combiners (F in screenshot):
Screenshot_2016-11-04_20-20-38.png
Screenshot_2016-11-04_20-20-38.png (111.61 KiB) Viewed 7396 times
The second problem was solved by filtering the sign bit from the output of the shift register. Used two Decider combinators and two Arithmetic combinators for this (G in screenshot):
Screenshot_2016-11-04_20-44-02.png
Screenshot_2016-11-04_20-44-02.png (180.33 KiB) Viewed 7396 times
When the value is positive it is passed thru unmodified. When it is negative the sign bit is cleared by subtracting -2147483648. Note that clearing the sign bit is not the same as multiplying by -1, because of how negative numbers work in computers (ie. two's complement).

The third problem was solved by subtracting the upper bits from the input to the lamps. This was done with two Arithmetic combiners for each column of lamps (H in screenshot):
Screenshot_2016-11-04_20-27-15.png
Screenshot_2016-11-04_20-27-15.png (218.33 KiB) Viewed 7396 times
Dividing and then multiplying by a power of 2 clears the lower bits of the value. Since the multiplication is by a negative value the result is negative. Then that signal is connected into the lamps, effectively clearing the higher bits of the signal the lamps receive, since lamps already receive the normal value via green cable:
all_bits - high_bits = low_bits

And one last problem is that the green and red cable signals going into the lamps are not synchronized. The green wire goes thru a single Decider combinator while the red wire signal goes thru two Arithmetic combinators. So a delay Decider combiner (I in screenshot) was added to the other green wire path, just to keep signal sync.

Yoyobuae
Filter Inserter
Filter Inserter
Posts: 499
Joined: Fri Nov 04, 2016 11:04 pm
Contact:

Re: Shift Register+Bitwise display

Post by Yoyobuae »

Yoyobuae wrote:The display part might also be interesting on it's own. Each lamp is controllable by a single bit of a signal. It's seems scalable to many more signals without increasing the amount of combinators too much. Certainly something I will investigate in the future. :)
Expanded the display build to a 6820 pixel display:
VIDEO
Uses all signals from vanilla factorio as input. Displays 31 bits of each of the 220 signals (220x31 display resolution).
Screenshot_2016-11-06_04-05-52.png
Screenshot_2016-11-06_04-05-52.png (842.16 KiB) Viewed 7365 times
Screenshot_2016-11-06_04-07-03.png
Screenshot_2016-11-06_04-07-03.png (1.15 MiB) Viewed 7365 times
Screenshot_2016-11-06_04-09-18.png
Screenshot_2016-11-06_04-09-18.png (699.22 KiB) Viewed 7365 times
Blueprint:
7Kdisplay.txt
Bluerprint
(194.96 KiB) Downloaded 214 times
Used some scripting magic to program the Constant Combinators inputs. Downloaded the logo from here:
https://www.factorio.com/press-and-youtube

Then converted in Gimp to 1 bit per pixel and saved as C header. Then used C program to convert each 31 bit column into hexadecimal value, then wrote Lua script which inserted those hex values into the Constant combinators one value per signal.

Each of the Constant combinators controls a section of the display. Try turning off some of them to see how it works.

Also used another script to help setting up the lamps.

Yoyobuae
Filter Inserter
Filter Inserter
Posts: 499
Joined: Fri Nov 04, 2016 11:04 pm
Contact:

Re: Shift Register+Bitwise display

Post by Yoyobuae »

So I decided to make a text console using the above display:
  • Text is typed from left to right
  • When "cursor" reaches end of line, the entire display is scrolled upward to make room for more text
  • Replaceable character map (stored as constant combinators)
I tried working with all signals simultaneously when possible. The RAM for the display is a single combinator. Scrolling upward is achieved by bit shifting down all signals. Each column of the display is mapped to a signal type, and each row is mapped to individual bits of each signal.

The character map is read as signals on a single-wire and can be send directly to display via single-wire:
Screenshot_2016-11-10_05-21-35.png
Screenshot_2016-11-10_05-21-35.png (258.46 KiB) Viewed 7308 times
Placing some character at a specific position on display was achieved by swizzling bits/signals around. First the correct column from the character map is selected:
VIDEO
Then that column is replicated to every column:
VIDEO
Next the correct row is selected and shifted to the right position:
VIDEO
And finally the correct output column is selected:
VIDEO
Once the character is at required position it's fed (pulsed) into RAM register. Also when the end of line is reached the entire RAM register is shifted down (low bits are on the top rows of the display):
VIDEO
And here is the circuit which does it:
Screenshot_2016-11-10_04-39-39.png
Screenshot_2016-11-10_04-39-39.png (1.25 MiB) Viewed 7308 times
labels.png
labels.png (1.39 MiB) Viewed 7306 times
The top left block is for generating the control signals (character map column number, row selection numbers, output column number, pulse to transfer to RAM and pulse to scroll display contents). The rest of the circuit (from left to right):
  • Character map column selector. Basically generates a -2147483648 count for the seven pixel columns which form a character. There's 31 character columns so there's 31 deciders to select the correct values. Then that value is added to the values from character map, making them negative. Then negative signals are filtered out.
  • Column replicator. This needs to replicate 7 pixel columns across 31 character column. First a pixel column is selected and transformed into black signal. Then that black signal is multiplied by a signal with a count of 1 in the columns where the value needs to be copied. There are 7 values (1 value = 1 pixel column) so this is done 7 times in parallel.
  • Row selector/shifter: Bit shifts all signals down, then up by specific amounts in order to erase the low bits. For example shifting 10 bits down, then 10 bits up clears the first row of characters. This is done twice in parallel. One path is used to clear the low bits, the other path used to generate a negative number which will clear the high bits.
  • Output column selector. Exactly the same as the character map column selector. Since there are copies of the isolated character on every column then it's just matter of selecting the right column to get the character at the right position.
  • Pulse generation. The right character is now at the right position and needs to be inserted into memory. The memory is a single decider with output looped to input. Sending a single cycle pulse copies data into the memory cell. Some combiners are used to ensure that a single cycle pulse of the data signal is fed into memory. These are the combiners pointing north.
  • Buffer scrolling. The memory cell output is disabled for one cycle and fed with the previous value divided by 1024 (2^10). In pseudo code it implements: M = M / 1024. Again this requires a single cycle pulse, so there's some combiners to generate that.
I need to clean it up and organize it a bit better, its a bit messy now. Just wanted to get it to work near the end. ;)

User avatar
hansinator
Fast Inserter
Fast Inserter
Posts: 160
Joined: Sat Sep 10, 2016 10:42 pm
Contact:

Re: Shift Register+Bitwise display

Post by hansinator »

I like this :)

Yoyobuae
Filter Inserter
Filter Inserter
Posts: 499
Joined: Fri Nov 04, 2016 11:04 pm
Contact:

Re: Shift Register+Bitwise display

Post by Yoyobuae »

hansinator wrote:I like this :)
THANKS
This was more of a proof-of-concept of some ideas I had. It seems that Factorio's circuit network is somewhat suitable implementing some kind of SIMD architecture. The parallelism happens across the different signals.

But handling 220 signals is cumbersome. The column selectors are huge and that's only selecting columns in groups of 7. I think 64 signals would be a more reasonable number, as 8 groups of 8 signals each. I think that leaves enough room for parallelism without becoming too unwieldy. Would allow 32 parallel multiplications, for example. One thing I really like is how well signal replicator worked, I though it was going to be more complicated. Those kind of operation primitives are important for implementing SIMD.

Future plans:
  • Addressable registers to read/write data from/to
  • Fixed point multiplication
  • Optimize latency
  • Actually do something useful ;)

Post Reply

Return to “Combinator Creations”