la béchamel

For my first finished product for prepared instruments (preparedinstruments.com), the goal is to remake the hardware 7ch palimpsest.OS SRAM but with :

  • a square keyboard grid interface like the PEW design (knobs and switches replaced with keys)
  • an aluminium PCB substrate (with a single-sided board) ?
  • a simpler amp in path with only one pot
  • all 0805 and SOIC packages

I’ve been thinking about it and I can’t say that this board will be inexpensive. If you want to explore video synthesis inexpensively, you should do things for free in code on the computer. This is a physical digital logic / analog device so it will cost money.

Because it’s the first in a series, I would like this board to set the format of the others. I’m imagining them all like Ritter Sport square bars. Like the eurorack format, I would like to have a standard way of powering the boards and I need to decide on a way of jumping between the boards (VGA cables?).

I’d also like the boards and the packaging to be ecologically responsible. I don’t know if this means using an aluminium substrate (which can be easily recyclable in theory) or a flexible circuit (with either a thin plastic or stained steel stiffener – in theory recyclable).

Looking back on the synths from this year, I never really wanted to code/configure the things I made. Doing hardware synths makes sense as it puts me in a different spot in the market place, makes the designs harder to just copy, and it allows me to savour the suffering in the design process. The analog function board was ultimately underwhelming. Going the direction of installation pieces isn’t satisfying because they are too site-specific and local for my project I feel (though perhaps making films is the solution here). The gameboy design made me feel bad about the waste of buying a mini screen and the software challenge of communicating with it seems not crucial to my project (but I will finish at least the physical side of the project to test the layout). The memory boards were the coolest, and of them the layering board is the most elegant design and the most interesting in what it can do.

Here’s the new site where the bĂ©chamel will appear:

Thoughts from Vincent :

  • Connect with other people making video synths !
  • Try shooting some of your own film to put through the machines !
  • What is it you are trying to SAY ? Hmm

What is it you are trying to SAY:

I think I’m trying to say with this project is : Look at what I like doing, isn’t it fun and cool/silly/odd what is to be found ?!  More specifically, to share the preliminary results of my creative research project method. The project I guess is trying to say that it is possible and fun to a embark on an explorative creative process with technology at a low level (and not just use pre-packaged tech things) with some of the wrestling with constraints that that requires. I like that the objects are idiosyncratic, playful compositions but also that they are ornately routed and articulated. I like the message that machines can look different, and be more human and odd ? I guess I’m also trying to have fun with the ideas of usefulness and futility, so it is partially supposed to be humorous? I like the dĂ©tournement of industrial objects for playful means, the implication that old things can be exciting and that deconstructing a system reveals unexpected inner worlds. I like that the deconstructing of machines is also the deconstructing of how they interact with our world, like the data they save and how they represent our information.

Thinking that Alterity, oddity, idiosyncracy and animism in objects and people and culture I think are totally up there. This was a fascination of my dad’s.

To echo some artists’ quotes that resonate :  “I don’t know what I’m looking for until I see it.” (Cindy Sherman)

“The reason I play so many sounds, maybe it sounds angry, is because I’m trying so many things at one time, you see? I haven’t sorted them out. I have a whole bag of things that I’m trying to work through and get the one essential.” (John Coltrane)

 I want to learn things all the time, I want to understand the patterns behind things. I experience science through craft. With craft I try to cultivate sensitivity in a practiced, purposeful way. If you work with marbling you know just as much about viscosity and flow than a scientist, through your fingertips in a different way. (Tauba Auerbach)

 

Try shooting some of your own film to put through the machines?

I started thinking about what I would want to film and how. I thought about the beautiful cinematography I appreciate in special films like The Souvenir I & II. I think it would be cool to shoot some video because I spend a lot of time watching videos (not the case for writing because I don’t do enough reading). I thought about recording things I see on commutes, and about the forest walk in Saclay. This has made me consider that what I find interesting about the electronics side is memory, more than just modifying things with math. How the computer represents our world is mainly impacted by its ability to remember it. I’m starting to think that this project could be about memory, putting my own memories into the computer memory. I’m thinking about Iain and Brian’s film Lifesaver and the impact it’s had on me. Also Iain’s photography in general, especially his black and white stage.

I think DRAM board could be a cool project because of how inexpensive large memory is and the memory degradation which could be really poetic in a project about memory. This goes back to Paolo’s suggestion to make a project around an image put into UV erasable EEPROM and watching it slowly degrade in the sun.

I’ve been thinking about how to record as well, with a gopro discretely or with my G2 Cannon more deliberately. I also think that humor should be the primary part of my shooting, not some wanna-be poetic stuff.

**********

Trying to design the interface :

Might need latched buttons like this :

Some all metal heavy duty toggle switches look cool in an array but I’m worried toggle switches will require too much force to turn on and will therefore be annoying all arrayed together on a tiny board.

The other option is to stick with tactile buttons and to convert them into on/off buttons with a JK flipflop. When J and K are pulled high, the outputs Q and !Q toggle every time the clock rises (once per push). This would mean I could have an LED turn on when you push too (helps in the dark for performances!) but I wouldn’t have the pushed-in versus fully extended visual feedback from the button and it would add ICs to my packed board.

I am considering doing this on two boards, the top one would be a single-sided aluminium board which would look cool but also make the top interface more durable. This board would have the leds, keys, JK flip flops. The board below could have lots of space to be laid out in a relaxed, rational way without having to dodge buttons. I could enclose it in a little box or I could leave the two boards exposed on one side or all around.

This follows from the constraint that this will be a real product. I don’t want to make a super difficult to solder and debug highly compact circuit. I want to keep things easy to repair. It also makes the device modular, I could switch a new keyboard and keep the base circuit or vice versa. I would like to keep this device affordable and not using rare / exotic components. I’m more in the robust, standard design world now that Tommy is good at working with perhaps.

*******

I just cleaned by apartment and went through my lab equipment. I will be sending tens of boards and plastic bags to the recycling which makes me sad. I would like to avoid finding myself in this situation in the future.

Check out this Soviet-developed visual programming language DRAKON (https://en.wikipedia.org/wiki/DRAKON)

It would be cool to make a flow diagram like this for the FPGA code I’ve already made.

Also this automation representation called GRAFCET (https://fr.wikipedia.org/wiki/Grafcet)

*******

Check out these user interface principles (https://en.wikipedia.org/wiki/User_interface_design):

  • Clarity: the information content is conveyed quickly and accurately.
  • Discriminability: the displayed information can be distinguished accurately.
  • Conciseness: users are not overloaded with extraneous information.
  • Consistency: a unique design, conformity with user’s expectation.
  • Detectability: the user’s attention is directed towards information required.
  • Legibility: information is easy to read.
  • Comprehensibility: the meaning is clearly understandable, unambiguous, interpretable, and recognizable.

********

Just watched a Youtube video by Code Aesthetic called Don’t Write Comments. The implication is that the code should be so readable that you don’t need to comment it. (He organizes code in such a way that the high level architecture comes through and if you want to get into the details you can check out individual functions). I’m trying to do something similar with the interface, have it be directly readable without text just based on color, button size and location.

I like the idea of being more pragmatic with the design and less obsessive about composition. The cut away in the top board could be nice because it show which color bits are going from rpi to the memory.

The question of the colors is tough – RED is for recording ? Should colors follow RGB ? What colors for clock division, and for selecting between MSB and LSB ? What about the LEDs versus the buttons ? EDIT : I’ve sinced moved to greyscale…

****

Being creative in different ways : Apollonian (rational thinking, order, logic, prudence and purity) vs. Dionysian (irrationality, chaos, passion, emotion and instinct). Electronics and logic circuits are clearly Apollonian, and the effects they create on screen are more Dionysian.

****

Looking into code bloat I learned the Unix philosophy of “do one thing and do it well”. Other programming credos :

  • less functionality (“worse”) is a preferable option (“better”)’https://en.wikipedia.org/wiki/Worse_is_better)
  • “Keep it simple, stupid!” (https://en.wikipedia.org/wiki/KISS_principle)
  • rule of least power is a design principle that “suggests choosing the least powerful [computer] language suitable for a given purpose” (https://en.wikipedia.org/wiki/Rule_of_least_power)
  • a simple (low complexity) solution to a problem of high complexity is seen as elegant. (https://en.wikipedia.org/wiki/Elegance)

**********

New Prepared Instruments github : https://github.com/preparedinstruments/bechamel

OK, here’s the final version of the boards. I will finally be able to test the one-sided aluminum surface reversed with buttons going through-hole. This is (my first) double-board design, keyboard on one and memory on the other with a ribbon jumping between them. This sampler will have two bits of data for the videos which will be new. Layers will now have different colors associated with them. The gen lock turned out to not be what I thought it was so I’m trying to sync by using V and H syncs (and their inverses) connected to the 590 freq division somehow (either to OE, CLR, or RCLK). I like this new setup to select different bits of the RPI. Cool things here are the double use of the buttons in momentary and latched mode with led indicators. New in this version will also be the triple diode packages for the VGA out.

I’ve taken my favorite interface and mixed it with my favorite circuit, let’s see how it works out ! At least I got to use up a bunch of components I already had lying around. Though, I have to say that no one could pay me enough money to assemble one of these myself, and despite my best efforts it is not minimal and easy to put together. Another issue is the fact that I don’t have the skill of imagining what “customers” want, I seem to be more focused on what I want. Does that make me a wanne-be artist as opposed to a wanna-be designer ?

And some renderings :

 

**********

Having a think about what my hardware synths could do better than computers. There is the tangible interface, and the speed and fixed-low latency of using hardware to manipulate data instead of software. While I was once again looking into what I can do with a simple FPGA I came across :

  • this Elphel NC393 camera device board for handling multiple video streams using an FPGA https://wiki.elphel.com/wiki/File:Nc393-dev-sm.jpeg. Combining multiple video streams, or overlaying, sounds like an application? But in VGA you can do this with just a pot !
  • User Jeremy from eevblog’s comment about FLIR explaining that they use FPGAs in order to do “spatial (across pixels) and temporal (across time) filtering simultaneously”.
  • video transcoding from one resolution ‘https://en.wikipedia.org/wiki/Transcoding)
  • real-time edge detection
  • Mister FPGA video game console has a bunch of retro CRT scanline filters here https://boogermann.github.io/Bible_MiSTer/getting-started/extras/video-filters/
  • FPGA student projects from this Cornell class : http://people.ece.cornell.edu/land/courses/ece5760/FinalProjects/

********************

I think that this project is becoming about memory, and possibly the parallels between human memory and computer memory. I wonder what role the FPGA would have here. Would it be positioned in between the video input and the memory to act as a kind of variable filter ? I can imagine an interface that would allow you to select between many different filters by moving your hand like on a theremin or an array of trackballs?

*****

Check out this visualization of randomness :

****

First feedback : it needs HDMI – Sam

This Texas Instruments TFP410PAP is back in stock at Mouser and seems easy enough to integrate onto the board at 8euros. It can be controlled without I2C so it could be connected directly to the raspberry pi DEN, HSYNC, VSYNC, color data.  Black Mesa Labs did a board using this IC here : https://blackmesalabs.wordpress.com/2017/12/15/bml-hdmi-video-for-fpgas-over-pmod/

I also found a VGA to HDMI converter on amazon : FOINNEX Adaptateur VGA vers HDMI avec Audio, Convertisseur VGA a HDMI Vieux PC vers TV Moniteur, 1080P VGA to HDMI Adapter pour Anciens Ordinateur 

TI also makes the TFP401x TI PanelBusℱ Digital Receiver so I could have HDMI IN and HDMI OUT with the addition of 15 euros of chips…The alternative is to learn to do this with the FPGA.

*****

Check out these snazy metal container for this synth circuit :

Division 6 Business Card Synthesizer PCB and IC

https://store.synthrotek.com/Division-6-Business-Card-Synthesizer-PCB-and-IC_p_829.html

Check out this beautiful project Sam sent my by Jurg Lehni which compares different screen technologies : https://juerglehni.com/works/four-transitions

******

Thinking about modularity. If I wanted to have a signal chain with filters etc before the memory. I would need a way of daisy-chaining the power, and a way of patching cables between modules. I want it such that the thing functions with just one module but also can with multiple modules too.

Would the video in/out have to be HDMI to be in line with modern VJ practice ? Found some Chinese chips that do HDMI to VGA like the Lontium LT8511A and the Quintile CH7101B. I guess I would need one of these plus an HDMI out chip for each board for them to be truly modular.

I am thinking right now of a simple custom filter like the one in Photoshop (Nice explanation here : https://ian-albert.com/old/custom_filters/) accomplished with an FPGA and some kind of cool interface (track ball matrix ? capacitive touch array ?) :

Photoshop's custom filter dialog

pixel(x,y) = (sum(i=1..5)(sum(j=1..5)(pixel(i+x,j+y)*weight(i,j))))/scale + offset

***************

Check out this company OKW that makes cool modular knobs just outside of Paris : https://www.okw.fr/fr/Boutons-de-commande

 

**************

Working with the array of simple, robust, electronic components (switches, knobs, linear pots, track balls, etc.). Trying to think about how they could be daisy-chained together.

 

****************

Received and soldrerd PCBs !

  • The aluminum layer can be engraved ! I could put “bechamel” on it !
  • The standoff holes are too small for standard size.
  • The boards are not perfectly the same dimensions.
  • Perhaps I should have chosen white for the FR4 board instead of green
  • No caps on the keyboard board
  • Blurg, soldering components on the aluminum board without a heated plate is near impossible. I could have at least selected bigger format ICs.
  • The latched keys which are connected to the output buffer enables aren’t really useful. They should be constantly on as the amp can always be just turned down to turn off the channel.

 

ERRATA MOTHERBOARD :

  • From now on I think I will solder with a stencil and an oven, it’s too much work to solder manually.
  • The latched keys don’t activate the same channels via buffer that they activate via AND gate to analog switch SEL.
  • Also the text BLU, RED etc next to the knobs isn’t really accurate
  • Should have VCC and GND on the silkscreen next to keyboard jumper
  • Pin 13 and 11 of the 590 should by default be connected together on the next board
  • I replaced the caps at the VGA out with 0ohm jumpers because I couldn’t see anything passing through on the oscilloscope
  • I should add the turn off switch for rpi
  • I am considering getting rid of the integrated rpi, despite its advantages, for a more straightforward HDMI IN or VGA IN. It adds considerable thickness to the board with the bulky 40 pin jumper situation and the fact that it is headless makes debugging a real pain.

ERRATA KEYPAD :

  • I’m not sure the idea of using the aluminium sided boards really works, it’s all a bit too risky in terms of short circuits and it’s a real pain to solder (I need a heated plate, a nice microscope, loads of flux and a soldering iron). Fabien’s suggestion is to make the holes larger, so there is little risk of the pins touching the aluminium substrate, and then wiring flexible wire to make the necessary connections. Perhaps add some glue to keep the keys in place and move all the circuitry to the reverse side of the motherboard.
  • Fabien had the idea of using the square holes of the mechanical switches possibly to mount them in the metal, perhaps they would even clip into place ?
  • I roasted the ICs during soldering I think, the LEDs and JK latches are not working as expected.
  • The added height for the two female ribbon cable connectors butting up against each other is insane. If it’s possible to just plug one board directly into the other you can achieve some nice compact sandwich board.
  • Once again the 2mm standoff holes are too tiny
  • The slot is perfect and the LEDs passing through the holes works as expected (though I should really use insulation on the two legs).

**************

Could I use coils from floppy disk player in a matrix as capacitive touch array ?

PCB mounted motor coils in a floppy drive : r/electronics

Could I make a super low resolution LED monitor to replace the HDMI IN and HDMI OUT DSLR field monitor ? (https://www.amazon.fr/Feelworld-Moniteur-Monitor-1920×1080-Peaking/dp/B07J5C98NW/ref=sr_1_1_sspa?crid=2SJEJTOJ1C6HB&keywords=Cam%C3%A9ra+Moniteur+DSLR&qid=1707557998&s=electronics&sprefix=cam%C3%A9ra+moniteur+dslr+%2Celectronics%2C89&sr=1-1-spons&sp_csd=d2lkZ2V0TmFtZT1zcF9hdGY&psc=1) :

I could also just use the simple rpi 5″ HDMI screen.

Other connection options if I had HDMI out :

Would it be smart to keep a VGA out as a plan B if ever the HDMI stopped working ?

It would be super useful to have a micro usb out to power the portable screen / pico projector. If so not much space left, would need to maybe bring the USB C power cable to the rpi side.

*************

Check out Jim Campbell’s low res display :!

Image may contain Rug Light Text and Lighting

Jim Campbell

Jim Campbell

References to reconstructing memories from the mind too !

***************

Setting up another rpi to loop VLC videos. I used primarily this tutorial: https://forums.raspberrypi.com/viewtopic.php?t=17051

First off, I kept the language as english to simplify things (despite having a french keyboard). I believe I did the rpi Lite installation (and then downloaded VLC?) but I’m not 100% sure.

In the place of

nano /home/pi  I have my user name :

nano /home/marrs

I also needed to go to View > Show Hidden to see the .config file then autostart then autovlc.desktop

nano /home/marrs/films/.config/autostart/autovlc.desktop

I put this in the file (there is nothing else there)

[Desktop Entry] 
Type=Application
Exec=vlc --loop --fullscreen /home/marrs/playlist.m3u

Then control+O to save the file
 I put the m3u playlist here : home/marrs/playlist.m3u
The playlist file looks like this :
/home/marrs/Desktop/films/2001.mp4
etc. and avoid spaces !!
I created a folder called films on my desktop with the films.autostart
To share videos from another computer via the SD card, you can create a folder in the part of the SD card that is accessible, and whatever folder you make there can be found under bootfs / firmware
Finally, AFTER DOING THE FILM FILE TRANSFER WITH THE HDMI SCREEN, I modified the config.txt file to output DPI and not respond to HDMI:

# For more options and information see
# http://rpf.io/configtxt
# Some settings may impact device functionality. See link above for details

# uncomment if you get no picture on HDMI for a default "safe" mode
#hdmi_safe=1

# uncomment the following to adjust overscan. Use positive numbers if console
# goes off screen, and negative if there is too much border
#overscan_left=16
#overscan_right=16
#overscan_top=16
#overscan_bottom=16

# uncomment to force a console size. By default it will be display's size minus
# overscan.
#framebuffer_width=1280
#framebuffer_height=720

# uncomment if hdmi display is not detected and composite is being output
#hdmi_force_hotplug=1

# uncomment to force a specific HDMI mode (this will force VGA)
#hdmi_group=1
#hdmi_mode=1

# uncomment to force a HDMI mode rather than DVI. This can make audio work in
# DMT (computer monitor) modes
#hdmi_drive=2

# uncomment to increase signal to HDMI, if you have interference, blanking, or
# no display
#config_hdmi_boost=4

# uncomment for composite PAL
#sdtv_mode=2

#uncomment to overclock the arm. 700 MHz is the default.
#arm_freq=800

# Uncomment some or all of these to enable the optional hardware interfaces
dtparam=i2c_arm=off
#dtparam=i2s=on
dtparam=spi=off

# Uncomment this to enable infrared communication.
#dtoverlay=gpio-ir,gpio_pin=17
#dtoverlay=gpio-ir-tx,gpio_pin=18

# Additional overlays and parameters are documented /boot/overlays/README

# Enable audio (loads snd_bcm2835)
dtparam=audio=on

# Automatically load overlays for detected cameras
camera_auto_detect=1

# Automatically load overlays for detected DSI displays
#display_auto_detect=1

# Enable DRM VC4 V3D driver
#dtoverlay=vc4-kms-v3d
max_framebuffers=2

# Disable compensation for displays with overscan
disable_overscan=1

[cm4]
# Enable host mode on the 2711 built-in XHCI USB controller.
# This line should be removed if the legacy DWC2 controller is required
# (e.g. for USB device mode) or if USB support is not required.
otg_mode=1

[all]

[pi4]
# Run as fast as firmware / board allows
arm_boost=1

[all]

gpio=0-9=a2
gpio=12-17=a2
gpio=20-25=a2
gpio=26-27=a2

dtoverlay=dpi24

enable_dpi_lcd=1
display_default_lcd=1

dpi_group=2
dpi_mode=87

extra_transpose_buffer=2

dpi_output_format=0x7f216
dpi_timings=720 0 40 48 128 720 0 13 3 15 0 0 0 60 0 50000000 1

*************

A new vision for this project : it’s a lo-fi device that takes HDMI and outputs HDMI but allows all kinds of very low res transformations like super low resolution GIFs, and saving every Nth frame of a film.

****TESTING ***

  • Get sync sorted on this board. **EDIT** Unfortunately taking HSYNC, VSYNC and their inverses, and sending them to the 590 on various pins is not syncing the video. Thinking back, I think I managed this only when I was ANDing a bunch of freq divisions and then inverting the output to record images only every nth frame. *EDIT* OK I’ve got something taking VSYNC as the freq and the AND’ind the outputs to be used to reset the 4040 counters.
  • Test the keyboard interface experience. ***EDIT** oof this is painful to do with jumpers and breadboards. Everything seems to be very sensitive to wierdness. It makes me want to eliminate the double board concept and just stick with hard soldered stuff on a single board. In the moments when things were briefly working it was super cool to control things with the keyboard.
  • See what other video distortion is possible with the circuit
  • I tried out the new HDMI converter, it works well.
  • I figured out that you can save a multicolor multichannel image by recording on several channels at once !
  • I like the idea of avoiding mission creep – not going into the screen or video codec business but instead staying with the theme of the project : video memory recording and playback.
  • I like the idea of emphasizing how little memory there is here (4MB), and how I am trying to use every part of the bison rather than going for more memory.
  • the new board should have usb micro female plugs to power an rpi, a VGA to HDMI converter, or the 5″ HDMI screen.
  • No more connectors between boards that are mirrored… Thinking of a single-sided board where the buttons relate the the function (latched push button for things that need to be latched like the freq sel) keyboard keys for selecting layers to record to. I thought that having an array of the same button would make things clean but it ends up being confusing what button does what. I like the idiosyncratic and non orthogonal matrix approach.
  • Just realized that I only need the single pole analog switch and don’t need the double pole anymore.
  • I have higher quality pots I could use for smoother action

Super cool to see everything on the tiny screen actually (but when I plugged in everything from the v synth I think it went above the fuse limit so I’ll have to FIX THIS IN THE NEXT VERSION if I want all to be powered by the board):

*

Trying to make a list of cool new video distortions possible with this board :

  • RCK and CLK of 590 could be connected to different frequencies
  • could have two different counter pairs for two memories that could be desynchronized

**********

A quick redesign :

  • Different components for different functions that they control (flat pots for inputs)
  • Added DIP switches to turn on and off diff V SYNC divisions going to 4040 counter reset
  • Only two speed buttons now, and they are physically latched
  • Nicer quality top facing pots
  • HDMI in and out with TI chips
  • got rid of some replaceable components
  • two micro USB connections to allow for these options :

 

*****

Trying out some hyper symmetrical design here.

Some considerations :

  • Leaving enough room to be able to comfortably twist the knobs
  • having mechanic keys close to one another so that they can be easily tapped with adjacent fingers
  • associating each key with it’s respective knob spatially and clustering controls that are thematically related (like the dip switch and the two frequency setting pushbuttons which are both temporal)
  • components that extend beyond the board on the top and bottom leaving room for hands on the keys and knobs
  • Tommy thinks it should be hand held.

 

And a more controller-like option :

*******

Check out Vincent Rioux’s muq machine and how he show the grid of screen shots :

 

***

I want to make videos like this guy makes experimental sound sets :

****

I’m going to remake the keyboard board (but on FR4, with connector aligned to motherboard, no latched colors to activate channels) and add the sync lock functionality. This will allow me to finish that project and test it easily.

The videos I have already of the board functioning are cool : diff colors allow for multiple images to share the same frame and be legible. The freeze frame(s) is very cool and being able to freeze different chunks of time I think will add a lot of things to test.

After this board I’ll move back to FPGA as they represent the future of the project I think (also the NO SCHOOL workshop this summer). Before I make I new board I should play more with the FPGA SRAM boards I have already made. Can I , for instance, reproduce the bechamel board with an FPGA? Perhaps it is time to upgrade to an FPGA with more LUTs, even if it is harder to solder in Ball Grid Array packaging (and then why not SRAM in BGA also), and the HDMI helper chips.

The dream would be able to throw 20 of the new boards in the oven and have them all work at the end. I could then send them to friends around the world ! Would be clever to use capacitive touch in this case to avoid needing a physical interface like so : https://github.com/stnolting/captouch.

TTP226 8-way touch module Capacitive touch switch digital touch sensor - Calcutta Electronics

Looks like an ESP32 with SD card can generate video as input, that or a rpi integrated into the board.

PCB Design for FPGA SoMs and Carrier Boards | NWES Blog

This might be one of those “already solved” problems which isn’t that much fun to explore…

***

Next steps for the HX8K board :

  1. FFMPEG can output into monob or monow 1 bit pixel format and different dimensions. Test making a low resolution video and putting it on an SD card and having Arduino read it and transfer it to FPGA on the gameboy console board I made. (This will test if can replace rpi or HDMI IN with SD card in on next board)
  2. Try again to see if HDMI out is possible with FPGA using the two boards I made to test this. (This will decide if need an HDMI helper chip or not on next board)
  3. Try to use internal FPGA BRAM to save a screenshot on the Villette Makerz board. (This will test if need SRAM or not on the next board).
  4. Replace mechanical keys with capacitive touch so everything is as light as possible.
  5. Plan to get JLC PCB to assemble it ?

****

New top board, no longer aluminum, no more LEDs, which has the V SYNC ADD circuitry, debounced keys, and a female header to connect directly to the motherboard.

 

*****

Realized that I haven’t used the BRAM on the FPGA and that I could store low res recordings there. I’ve tried to create BRAM primitives in IceCube but it’s not working so far. This code from TinLethax appears to work in IceCube :

module BRAM(
input R_CLK,
input W_CLK,

input [7:0]BRAM_IN,
output reg [7:0]BRAM_OUT,

input [11:0] BRAM_ADDR_R,
input [11:0] BRAM_ADDR_W,

input B_CE_W,
input B_CE_R);

reg [7:0] mem [3003:0];

always@(posedge R_CLK) begin// reading from RAM sync with system clock 
if(!B_CE_R)
    BRAM_OUT <= mem[BRAM_ADDR_R];   
end 

always@(posedge W_CLK) begin// writing to RAM sync with Slave SPI clock.
if(!B_CE_W)
    mem[BRAM_ADDR_W] <= BRAM_IN;
end

endmodule

 

 

This code from the Lattice Memory Guide (file:///C:/Users/jm225306/Downloads/MemoryUsageGuideforiCE40Devices.pdf) also works :

 module ram (din, addr, write_en, clk, dout);// 512x8
parameter addr_width = 9;
parameter data_width = 8;
input [addr_width-1:0] addr;
input [data_width-1:0] din;
input write_en, clk;
output [data_width-1:0] dout;
reg [data_width-1:0] dout; // Register for output.
reg [data_width-1:0] mem [(1<<addr_width)-1:0];

always @(posedge clk)
begin
if (write_en)
mem[(addr)] <= din;
dout = mem[addr]; // Output register controlled by clock.
end
endmodule 

After sorting out the parameters BRAM_ADDR_WIDTH and BRAM_DATA_WIDTH, this code also works : https://github.com/Megamemnon/bram/blob/master/bram.v

Informatique préparée / Assemblages informatiques

I have an idea for a next “chapter” in my project : prepared computers or assemblages.

Each computer would be a hodge-podge of different tech from different eras, but would each include some kind of I/O, memory, ALU, and display, cooling. I could return to the e-waste side of things, but still make circuits to control them.

I could use a corps exquis method to combine different types of screens/displays :

  • mini CRT
  • LCD
  • projector
  • printer
  • e-ink
  • galvo lasers

Types of memory :

  • floppy
  • SRAM
  • DDR
  • CD
  • Tape

ALU :

  • FPGA
  • microcontroller
  • raspberry pi
  • mechanical

I/O :

  • mouse
  • keyboard
  • trackball
  • touchpad
  • speakers
  • internet

Cooling

  • Peltier
  • Fan
  • Radiator

The actual functions of the computers would be unclear, they would generate mysterious images and sequences and react to the interface. They would allow me to very clearly be in the practice of making art.

They would highlight what I’ve come to find interesting about the world of computers, the hand-madeness and social dimension of the objects. Each would be unique, idiosyncratic, and I would no longer be in the situation of working with screens and not knowing what exactly the “object” is. The object here would be clear, it would be the computer assemblage. I could revisit my obsession with miniatureness, and oddity in these hybrid “monsters”. They would also require lots of technical challenges to make work, and would not produce waste like the mass production of circuit boards does when making a kit.

This is building on Vivien’s idea to be inspired by full computer builds to emphasize materiality :

https://cdn.cnx-software.com/wp-content/uploads/2022/12/LapPi-2.0-DIY-Raspberry-Pi-laptop.jpg?lossy=0&strip=none&ssl=1

Clockwork's uConsole is a modular portable computer & "fantasy console" for $139 and up - Liliputing

It would be really cool to make everything from e-waste, but also to keep the miniature dimensions. It looks like phone screens from Nokia can be controlled by Arduino, but that others are undocumented and hard to control without finding a datasheet :

Nokia 5510 84*48 LCD and the Arduino Nano – thesolaruniverse

Some ressources for controlling a TFT display directly with Arduino :

https://community.element14.com/members-area/personalblogs/b/blog/posts/screen-success-hack-like-heck-build-update

Looks like it is doable with a raspberry pi and therefore doable with an FPGA.

None of these will be possible if I don’t have an autonomous board though – one that produces it’s own videos with data (instead of relying on video from a computer or rapsberry pi). So I will have to make this work first, and why not try to have this done for the expo next month in Germany ?

******

This Autonomous board could play videos from memory and display it all on the same board, without any wires !

 

I am now seeing this as a two board construction. The keyboard is too dense to pack any electronics into really, so it is better just as an interface with a ribbon cable going to the board behind the screen which has the FPGA and microcontroller. The bottom could be in aluminium which would make it stable and could have tabs which bend on the edges. This would provide a solid mounting place for the micrometer knob and the laptop hinge. It would also give a different look to the board as it would be all metal, combining with the micrometer, the screen and the screen hinge to make an all metal looking assemblage.

Not yet sure how to convert the linear motion of the micrometer knob, and I feel that the screen + board might look and be a little top heavy / too thick for the effect.

Check out these beautiful machines from Love Hulten : https://www.lovehulten.com/ Thanks Martin De bie for the ref !

Now I’m thinking it should be flat in fact :

Looking in to TFT LCDs, here’s what I’m finding :

  • 40 pins seems to be a kind of standard
  • There seems to be at least two modes : ‘RGB’ mode and SPI mode.
  • rectangular screens with 800×480 in 4.3″, 5″ or 7″ seems to be standard
  • TFTs seem to come with a driver chip like the ILI9341 or the ST7701S
  • Some seem to require being initialized by SPI

*****

Kristy has helped me select a nice sized screen, 2.8″ seems to be cute but not trinket-like. Adafruit’s screen sells on Mouser : https://www.adafruit.com/product/1774

It appears to have a simple 8 bit parallel mode by default with a straight-forward timing diagram :

And here’s another explanation of the same thing showing two different options :

The datasheet is detailed and I have Adafruit code to base things on as well.

****

The screen also appears to also have a “raw” Parallel RGB Interface mode which seems to involve the HSYNC, VSYNC, DOTCLOCK, DE, while sending color data to the D pins…..but it looks like first bits (RCM, RIM, and DPI) must be set from the SPI mode ? Also, it looks like you have to calculate yourself the timings of the screen based on the clock and screen dimensions (and also set these bits (DIV, RTN, etc.) ? But it looks super simple afterward :

 

*************

PROJECT UPDATE :

This project seems to be unlucky :

  • My Mouser order was stolen from inside my building or was never actually delivered.
  • The idea of having doublesided PCB + aluminum went out the window when I saw the cost (approx. 10x a normal PCB)
  • The replacement screen I ordered from Amazon has only 20 connections (instead of 50) and only allows SPI, which is very difficult for the FPGA to do and so would require a microchip + FPGA teamwork which seems technically a real headache.
  • Currently the HX4K is not starting up, despite having both PLLs connected now. I’m not sure what I’m missing but it is different enough from the HX1K to merit more research before using I guess.

    On the other hand I have been preparing for my ESDAC creative coding class and enjoying learning about the different kinds of P5JS codes that exist. I made an image to show the typologies I found so far :

    I should also have a class on Glitching !!! And on WEBGL Shader, check out this awesome book : https://thebookofshaders.com/03/

    Moiré

    Field

    Random walk

    Spirograph

    Cavegen

    Radial

    Hyper-realistic face generation

    **********

    Trying to put together an analysis of the kind of hardware effects I have been producing so far :

    Here is a slide trying to show the process of designing a board :

    And some sketches of circuits I’ve made over the course of the project :

    ****

    Older board I never photographed :

    ****

    I finally have access to opencores.org ! Some things of interest so far :

    • Math – https://opencores.org/projects/verilog_fixed_point_math_library
    • Noise and PRNG  – https://opencores.org/projects/gng
    • CORDIC core (for trig functions) – https://opencores.org/projects/verilog_cordic_core
    • ATTINY core – https://opencores.org/projects/attiny_atmega_xmega_core

    There is plenty more, like H.264 and JPEG decoding, SoC, sorting algorithms, DDR controllers, Real-time clocks, PCI bus controllers, DSP Filters, SD card controllers, SPI/UART/USB/I2C etc interfaces, etc.

     

    ****

    Some aesthetic references I was reminded of this week :

    • The fractal, “trippy”, spaceship-like camera movements, and kaleidescopic winamp visuals : https://www.youtube.com/watch?v=RBkhUg1oVIE

    Winamp Milkdrop Visualization Plugin - YouTube

    • The black and white retro dithering from Return Of The Obra Dinn https://www.youtube.com/watch?v=k2y5qH2Jn14

    *************

    Post Darmstadt workshop thoughts :

    • CNC building workshops are hard. In the Fab Academy it takes an entire team two weeks. My two attempts, a while back at CMU and in Germany this week were too ambitious. If I want to have everyone leave with a working machine I need to do a lot of prep before hand. This weekend I could have 3D printed parts before hand that clipped together in the spirit of my linear actuators for the Fab Ac (https://www.marrs.io/medium-sized-cnc-foam-cutter-with-leon-reboul/). Alternatively I could have bought a cheap drawing kit from Aliexpress for around 100 euros if I had gotten myself organized early enough. I think threaded rods may also be a better solution than belt drives which require more skill to design with. The linear rails were cool but they required special low-profile screws so the students struggled a bit with this. It also seems to be the case that servos can simply replace all the challenges of stepper motors requiring drivers for everyone but experts. Essentially : Don’t overthink it, do the most obvious tech thing that is the shortest path for beginners. This will be my strategy for the Beaux Arts workshop coming up where I’ll focus on servos only.
    • I should probably keep in mind the challenge of the workshop. The higher the challenge for the participants, the more work I need to do to prepare everything. More plug and play = less challenge.
    • Learning to be a free lancer will take time but I need to consider myself as a professional, not doing things on a shoestring budget and exhausting myself. As I move around and workshop in different places, I need to keep in mind my audience – engineering students are different from artists, designers, enthusiasts and kids.
    • It might be cool to learn to make video PDFs for future presentations when talking about video synthesis. Also maybe live coding with toy shader / P5JS to illustrate things ?
    • For the expo, I was happy to have a plug and play FPGA solution that just generated images. The boards I have made that record video all need heavy intervention on the part of the player and are not intuitive at all. I am still hoping to find a way to order the remaining parts from Mouser soon so I can test SD card reading and FPGA screen displaying.
    • For my talk, I still don’t have a way of directly connecting my earlier projects with the new video synth project.

    Next steps :

    I am feeling positively about just following my interests, and not necessarily knowing where I am going with this project. I want to :

    • make abstract generating form code with FPGA using the new trig functions, multiplication and division from opencores !
    • experiment with more filters using the FPGA.
    • move beyond my current aesthetic, which will require making the recorded image not jump around. I should be able to do this pretty easily when the FPGA is sending the sync signals.

    *************

    Post BA workshop thoughts :

    • The students this time were really into following a more formal series of prepared slides with exercises, and seemed less interested in building their own drawing machines. The Arduino exercises were well received, as well as the glitch exercise, and also the soldering workshop. I like that they bring their own projects and integrate them.
    • I tried to be extra professional this time, staying late with students to continue helping them, being extra careful to put everything back in its proper place, and generally being as uncompromising as possible in the quality I’m trying to bring to the workshop.
    • My little polyphonic synth, portable speaker, and VGA arduino board were a good thing to bring. I should have something interactive that puts images on the screen I think and a lamp to show off the solar sunflower too.
    • I had too many projects to manage in parallel at one point and was rushing about everywhere. Not sure what the solution is there, there were around 8/9 people for the first two days.
    • We need some basic boards like mic amp, speaker amp, easy stepper motor drivers, relay boards, etc. that are useful at the BD.
    • Vincent was suggesting that we think of ways of creating a virtual expo space for digital works somehow in relation to his radio station at the school which is appreciated.

    *************

    Post website being down, looking at previous pages now and having some perspective thoughts :

    • pure p5js coding I find far less exciting than hardware visual effects, it’s all too immediate and mediated. It’s not raw and unstable like analogue. I think I’m more convinced that the painful process of doing simple things the hardest way possible is actually productive creatively for the friction it affords.
    • Putting a series of bitmaps on an SD card (possibly with a custom FFMPEG running on raspberry pi) and then onto the screen would be cool. The idea for a custom FFMPEG comes from this tutorial http://dranger.com/ffmpeg/tutorial01.html which I found here https://github.com/codecrafters-io/build-your-own-x which I in turn found on reddit FREE MEDIA HECK YES 
    • I need to get the sync working to test some other (less jarring) visual experiences.
    • The Real Time Corrupter methods (piping, etc.) are brilliant and I have to copy them to experiment with FPGA memory filters. Beyond the RTC it would be very cool to experiment with DCT compression filter spectra.
    • I don’t think I need to look under each hole and check under each rock. Getting one type of memory working, and one video protocol, is good enough and I don’t need to suffer with DDR and HDMI in this way of working I’m assuming currently.
    • For marketing video synths, there is the website php like Marc did (https://muca.cc/fr) or the instagram/facebook marketplace option. Alternatively there are services that host the payment side of things like gumroad, prestashop, and wordpress https://wordpress.com/fr/ecommerce/
    • I’m doing NO SCHOOL this summer !! Planning on getting a simple FPGA v synth programmable with Arduino / RPI in python and made on an aluminum-backed board (with SMD VGA).

    *************

    Learned about live coding with hydra :

    hydra >” jsname=”kn3ccd” aria-hidden=”false”></p>
<p>Kind of like Processing, I find it too easy to make wacky stuff and unsatisfying to not have the friction of analogue.</p>
<p class=I will be VJing this month, we’ll see what that experience is like. Perhaps it will help me design boards that VJs could use. Here’s what I learned :

    • The stress of doing a live performance when everything isn’t set up and rehearsed many times before hand is high. One would need to have a bunch of backups, and a very rehearsed performance to lower stress.
    • Having a small lamp is helpful to see what connections and knobs you are messing with
    • One question is how to react to music, does a beat equal a varying of a parameter ? How to react to song changes ?
    • How should “effects” be introduced ? I defaulted towards starting simple and then going towards the more complex effects
    • Clearly having performance grade equipment means everything is super robust, easy to use, etc. This makes me think that it would make sense to make a really reliable simple filter, for instance. This also connects with a larger issue for me : I want to do things differently but there are often good reasons why things are done a particular way
    • Sending my crazy VGA to a machine that digitizes it and sends it on as HDMI is probably safer than directly sending things to the projector…

    I want to use an older media device (cassette tape, floppy, mini-VHS?) in my next board. I realized that if my practice is about “doing things the hard way”, that should be visually communicated in the design (no one understands if the electronics are done the hard way or not…). This would also signal that I am not trying to make cutting edge new things but that my interests are elsewhere.

    Here is a first look at some video synth companies and their designs :

    Trying again with the floppy drive :

    Check out this video extracting motion from video by just inverting and sliding videos sideways :

    ****************

    I finally bought preparedinstruments.com ! Here are some potential designs for the page :

     

    Paris Electronic Week Synth Workshop

    Making a simple FPGA video synth for PEW 2023 at Villette Makerz. It takes audio in and generates patterns based on the voltage threshold and the 9 keys being pressed.

    The code is here : https://github.com/merlinmarrs/iCE40HX-verilog-video-patterns

    This time the top interface side has only buttons and no electronics. I have a simplified VGA out and HDMI with the correct LVDS resistor setup this time. I am relying on raspberry pi or arduino for programming.

    Trying a grid ground pour on the Stop layer :

     

    Here’s the final soldered version :

    Nicer photos :

    Found a site called OpenCores (https://opencores.org) that has free FPGA IP like math libraries.

    Here are some tests with cool looking patterns :

    Because dividing, trig functions, etc. aren’t supported by default, the most promising is the bitwise boolean logic operating on the entire vector :

    wire[11:0] bit_or;
    assign bit_or = h_count[11:0] | v_count[11:0];
    
    [...]
    
    if (bit_or[5] == 1 | bit_or[3] == 0) begin
    wire[11:0] bit_xor;
    assign bit_xor = h_count[11:0]^v_count[11:0];
    
    [...]
    
    if (bit_xor[2] == 1 | bit_xor[4] == 1) begin
    wire[11:0] bit_and;
    assign bit_and = h_count[11:0]&v_count[11:0];
    
    ...
    
    if (bit_and[6] == 1 | bit_xor[7] == 1) begin

    I could imagine having the keys vary which logic operations are in play and having the music threshold change the color of the pixels for instance.

    ***

    This site has a module for a quasi random number generator : https://simplefpga.blogspot.com/2013/02/random-number-generator-in-verilog-fpga.html

    This site has some good Processing examples : http://www.generative-gestaltung.de/2/

    ***

    If I do this workshop again I’d like to design it to be made on aluminum as, it is at least in principle, recyclable.

    PCBWay’s diagram of a double layer board (https://www.pcbway.fr/pcb_prototype/General_introduction_of_Aluminum_PCB.html) :

    Two-layer_single_side.png

    ***

    Simplest imaginable keypad switch (and audio in post comparator) test works :

    module top (
    input hwclk,
    output led1,
    input keypad_c1
    );
    
    assign led1=keypad_c1;
    
    endmodule
    Modified and restructured the random code from this site : https://simplefpga.blogspot.com/2013/02/random-number-generator-in-verilog-fpga.html and it appears to work :
    `default_nettype none
    
    module LFSR (
    input clock,
    input reset,
    output [12:0] rnd
    );
    
    wire feedback;
    reg [12:0] random, random_done;
    reg [3:0] count; //to keep track of the shifts
    
    assign feedback = random[12] ^ random[3] ^ random[2] ^ random[0];
    assign rnd = random_done;
    always @ (posedge clock)
    begin
    if (reset)
    begin
    random <= 13'hF; //An LFSR cannot have an all 0 state, thus reset to FF
    count <= 0;
    end
    
    else
    begin
    if (count == 13)
    begin
    count <= 0;
    random_done <= random; //assign the random number to output after 13 shifts
    end
    
    else
    begin
    random <= {random[11:0], feedback}; //shift left the xor'd every posedge clock
    count <= count + 1;
    end
    end
    end
    endmodule

     

    I am using it in the top code like this :

    wire [12:0] random_number;
    
    [...]
    
    LFSR random_s(
    .clock(clk_in),
    .reset(reset),
    .rnd(random_number)
    );

    ***

    Sine gen :

    • https://miscircuitos.com/sinus-wave-generation-with-verilog-using-vivado-for-a-fpga/
    • https://zipcpu.com/dsp/2017/07/11/simplest-sinewave-generator.html
    • https://verilogcodes.blogspot.com/2015/11/verilog-code-for-simple-sine-wave.html

    I added a time delay module I modified from the led_rotation example :

    `default_nettype none
    module tempo(
    input wire clk,
    output reg half_sec_pulse
    );
    
    reg[25:0] div_cntr1;
    reg[25:0] div_cntr2;
    always@(posedge clk)
    begin
    div_cntr1 <= div_cntr1 + 1;
    if (div_cntr1 == 0)
    if (div_cntr2 == 0)
    begin
    div_cntr2 <= 0;
    half_sec_pulse <= ~half_sec_pulse;
    end
    
    else
    div_cntr2 <= div_cntr2 + 1;
    else
    half_sec_pulse <= half_sec_pulse;
    end
    
    endmodule

     

    I can’t figure out why this makes 1/2 second ish though. Google says it should last 130.312488 days…Perhaps the compiler is deciding it doesn’t have enough space to store it and it truncating it?

    From the led_rotation code I get 2^16 = 65536, this happens 91 times so 65536x91, then multiplied by the period of a 12MHz clock (83.3ns) gets me to around 0.49 seconds.

    I’m guessing it is getting clipped because the register is too big ?

    *****

    Fabien showed me that on AliExpress you can buy things like this tracking ball for cents :

    Blackberry Trackball

    https://fr.aliexpress.com/item/1005004324983317.html?spm=a2g0o.detail.0.0.3f40hagUhagUgw&gps-id=pcDetailTopMoreOtherSeller&scm=1007.40000.327270.0&scm_id=1007.40000.327270.0&scm-url=1007.40000.327270.0&pvid=83e84367-84b9-424f-b42a-31b87563ff5e&_t=gps-id:pcDetailTopMoreOtherSeller,scm-url:1007.40000.327270.0,pvid:83e84367-84b9-424f-b42a-31b87563ff5e,tpp_buckets:668%232846%238114%231999&pdp_npi=4%40dis%21EUR%210.80%210.72%21%21%216.14%21%21%40211b801516946910696348428ea8cb%2112000030031307832%21rec%21FR%21%21ABS&search_p4p_id=202309140431096642081558243384177015_4

    Each one requires four little hall effect sensors which output HI-LOW pulses. The one made by Sparkfun is the AN48841B : high sensitivity CMOS Hall IC Operates on Alternating Magnetic Field (low-speed rotation for lock detection). Trying to find an alternative for not too much on Mouser.

    https://www.mouser.fr/ProductDetail/Infineon-Technologies/TLI49632MXTSA1?qs=0DP5yvOrqYlmAP5lA6MTRA%3D%3D

    I am also thinking about an HDMI mini – not micro – (if I can get HDMI working, if not get a helper chip), an atmega2560 to handle the SD card communication. Possibly a USB charger and a battery too – so that there can really be a minimum of cables when the battery is charged up.

    A dumb-proof programming connector with an automatically controlled bus to disconnect the programmer from the FPGA when reset not asserted so I don’t need to unplug and replug every time ?

    *****

    NEXT BOARD THOUGHTS :

    Maybe I don’t need to rebuild the FPGA etc each time, but should just make interfaces that plug into it ?

    The only thing left to try in hardware is the SD card fetching video data and then putting it on screen, and perhaps test having way more bits for each color and using the 4K LUT version of the iCE40.

    I could also try using the specialized HDMI chip ? This would allow me to try the mini screen.

    VGA with like 64 bit color !!!

    put the remaining video ICs that I haven’t played with yet (video differentiator, video sync module, etc.) on the board !

    Combine the possibility of reading a video from an SD card, having memory to store it in, and having a bunch of keys to press, AND coming up with code that makes meaningful patterns.

    My leftover video ICs :

    • ADV7125 8 bit Triple HS Video – https://www.mouser.fr/pdfdocs/ADI_ADV7125_Datasheet.PDF
    • LT1251CN Video Fader – https://www.mouser.fr/datasheet/2/609/12516fa-3123106.pdf
    • 660GILFT Digital Video Clock – https://www.mouser.fr/datasheet/2/698/REN_660_DST_20100514-1995937.pdf
    • NJM2274R Low Power CI video w/ Y-C mixer – https://www.mouser.com/datasheet/2/294/NJM2274_E-1917180.pdf
    • FMS6143CSX Video Filter Driver – https://www.mouser.fr/datasheet/2/308/1/FMS6143_D-2313627.pdf
    • AD724JRZ – https://www.mouser.fr/datasheet/2/609/AD724-3118543.pdf

    *****

    PATTERN CODE THAT WORKS :

    Got a code that works :

    `default_nettype none
    
    module vga_sync_test(
    
    input wire clk_in,
    input wire reset,
    input wire key[8:0],
    input wire adc_in,
    output reg led_red,
    output reg led_green,
    
    //VGA OUT
    
    output reg [3:0] r_out,
    output reg [3:0] b_out,
    output reg [3:0] g_out,
    output wire h_sync,
    output wire v_sync
    
    );
    
    wire half_sec;
    wire [12:0] random_number_0;
    wire [12:0] random_number_1;
    wire [12:0] random_number_2;
    wire [12:0] random_number_3;
    wire [12:0] random_number_4;
    wire [12:0] random_number_5;
    wire [12:0] random_number_6;
    wire [12:0] random_number_7;
    wire [12:0] random_number_8;
    wire [12:0] random_number_9;
    wire [7:0] sine_wave;
    wire display_en;
    wire [11:0] h_count;
    wire [11:0] v_count;
    
    localparam h_pixel_max = 1280;
    localparam v_pixel_max = 960;
    localparam h_pixel_half = 640;
    localparam v_pixel_half = 480;
    localparam h_pixel_25 = 320;
    localparam v_pixel_25 = 240;
    localparam h_pixel_75 = 960;
    localparam v_pixel_75 = 700;
    
    //VGA COLOR OUT
    
    always @(posedge clk_in) begin
    
    if (display_en) begin
    
    if ( key[0] == 0 &&
    
    h_count < h_pixel_25 + random_number_1[4:0] && v_count < v_pixel_25 + random_number_7[8:5] &&
    h_count > h_pixel_25 - random_number_2[4:0] && v_count > v_pixel_25 - random_number_2[8:5]
    
    ) begin
    
    r_out <= random_number_1[3:0];
    g_out <= random_number_5[3:0];
    b_out <= random_number_9[6:4];
    
    led_green <= 1;
    
    end
    
    else if ( key[1] == 0 &&
    
    h_count < h_pixel_half + random_number_7[5:0] && v_count < v_pixel_half + random_number_7[10:5] &&
    h_count > h_pixel_25 - random_number_6[5:0] && v_count > v_pixel_25 - random_number_6[10:5]
    
    ) begin
    
    r_out <= random_number_3[7:5];
    g_out <= random_number_3[3:0];
    b_out <= random_number_6[6:4];
    
    led_green <= 1;
    
    end
    
    else if ( key[2] == 0 &&
    
    h_count < h_pixel_25 + random_number_8[6:0] && v_count < v_pixel_25 + random_number_8[12:6] &&
    h_count > h_pixel_half - random_number_9[6:0] && v_count > v_pixel_half - random_number_9[11:5]
    
    ) begin
    
    r_out <= random_number_4[7:5];
    g_out <= random_number_5[3:0];
    b_out <= random_number_7[6:4];
    led_green <= 1;
    
    end
    
    else if ( key[3] == 0 &&
    
    h_count < h_pixel_half + random_number_0[7:0] && v_count < v_pixel_half + random_number_0[7:0] &&
    h_count > h_pixel_half - random_number_3[7:0] && v_count > v_pixel_half - random_number_3[11:4]
    
    ) begin
    
    r_out <= random_number_8[7:5];
    g_out <= random_number_8[3:0];
    b_out <= random_number_8[6:4];
    led_green <= 1;
    
    end
    
    else if ( key[4] == 0 &&
    
    h_count < h_pixel_75 + random_number_2[8:0] && v_count < v_pixel_half + random_number_2[11:3] &&
    h_count > h_pixel_75 - random_number_4[8:0] && v_count > v_pixel_half - random_number_4[11:3]
    
    ) begin
    
    r_out <= random_number_7[7:5];
    g_out <= random_number_7[3:0];
    b_out <= random_number_7[6:4];
    
    led_green <= 1;
    
    end
    
    else if ( key[5] == 0 &&
    h_count < h_pixel_half + random_number_3[9:0] && v_count < v_pixel_75 + random_number_3[11:2] &&
    h_count > h_pixel_half - random_number_8[9:0] && v_count > v_pixel_75 - random_number_8[11:2]
    
    ) begin
    
    r_out <= random_number_5[7:5];
    g_out <= random_number_5[3:0];
    b_out <= random_number_5[6:4];
    led_green <= 1;
    
    end
    
    else if ( key[6] == 0 &&
    
    h_count < h_pixel_75 + random_number_4[10:0] && v_count < v_pixel_75 + random_number_4[11:1] &&
    h_count > h_pixel_75 - random_number_6[10:0] && v_count > v_pixel_75 - random_number_6[11:1]
    
    ) begin
    r_out <= random_number_4[7:5];
    g_out <= random_number_4[3:0];
    b_out <= random_number_4[6:4];
    led_green <= 1;
    end
    else begin
    r_out <= random_number_2[3:0];
    g_out <= random_number_3[6:4];
    b_out <= random_number_4[3:0];
    led_green <= 0;
    end
    end
    else begin
    r_out <= 4'b0000;
    g_out <= 4'b0000;
    b_out <= 4'b0000;
    led_green <= 0;
    end
    end
    
    vga_sync vga_s(
    
    .clk_in(clk_in),
    .reset(reset),
    .h_sync(h_sync),
    .v_sync(v_sync),
    .h_count(h_count),
    .v_count(v_count),
    
    .display_en(display_en) // '1' => pixel region
    
    );
    
    LFSR random_s(
    
    .clock(clk_in),
    .reset(reset),
    .half_sec_pulse(half_sec),
    .rnd_0(random_number_0),
    .rnd_1(random_number_1),
    .rnd_2(random_number_2),
    .rnd_3(random_number_3),
    .rnd_4(random_number_4),
    .rnd_5(random_number_5),
    .rnd_6(random_number_6),
    .rnd_7(random_number_7),
    .rnd_8(random_number_8),
    .rnd_9(random_number_9)
    );
    
    sine_wave_gen sine_wave_s(
    .clk(clk_in),
    .data_out(sine_wave)
    );
    
    tempo tempo_s(
    .clk(clk_in),
    .half_sec_pulse(half_sec)
    );
    
    endmodule

    and here is the PCF file :

    set_io v_sync 97
    set_io h_sync 76
    set_io clk_in 49
    set_io reset 66
    
    set_io r_out[0] 91
    set_io r_out[1] 95
    set_io r_out[2] 96
    
    set_io g_out[0] 75
    set_io g_out[1] 74
    set_io g_out[2] 73
    
    set_io b_out[0] 87
    set_io b_out[1] 88
    set_io b_out[2] 90
    
    set_io key[0] 37
    set_io key[1] 38
    set_io key[2] 39
    set_io key[3] 41
    set_io key[4] 42
    set_io key[5] 43
    set_io key[6] 44
    set_io key[7] 45
    set_io key[8] 47
    set_io led_red 23
    set_io led_green 24
    set_io adc_in 56

     

    ***************

    TAKEAWAYS FROM VILLETTE MAKERZ

    Getting feedback on my circuits has been really cool, getting “users” to try my boards and tell me what they would like to be able to do has to become part of my process of design and iteration if I am ever to make something people want to buy.

    Some feedback so far :

    • If people have hard time understanding the interest in “doing something the hard way” even if it is not obvious for the outcome, then you have to show them what your process is. You need to share your workspace and tools with them so they can see the advantages of doing something the hard way.
    • Using hand to modulate speaker for sequencer is cool
    • The 7 layer board is fun to let people play with. Difficult to see different layers though, would be cool if could have diff colors.
    • People like the idea of deforming an image of themselves like from a webcam and seeing it projected on the big screen
    • Kids like colors and the 9 key board board is colorful. Would be cool if once you select a pattern is stays though
    • The Arduino boards are less cool because they are not interactive or colorful
    • It would be cool for the FPGA 9 key things to have more of a relationship with sound 
    • putting circuits ontop of a screen is cool.
    • Projections kind of get lost if not in total darkness.
    • Curious to try a tiny screen, or a really big screen, or a tiling of screens ?
    • the combo of the oscilloscope and the function generator + speaker is cool to understand the basics of electronics signals.

    Aliexpress has components that are insanely inexpensive compared to Mouser. If I were ever to sell something for profit I would need to source the components from China entirely.

    I think I also need to address the environmental question too : how is continuing to manufacture circuits responsible ? Could I demonstrate how to recycle an aluminum PCB ? Obviously using e-waste is cool and should be emphasized more in my projects perhaps

    *****************

    SD CARD EXPERIMENTS

    Modified this code to write the contents of a file on the SD card as a byte to PORT D.

    Need to find a way to convert an image into a collection of bytes and store it. Then I need to iterate through the file and output the values to a port.

    /*
     * Created by ArduinoGetStarted.com
     *
     * This example code is in the public domain
     *
     * Tutorial page: https://arduinogetstarted.com/reference/library/arduino-file.readbytes
     */
    
    
    #include <SD.h>
    
    
    #define PIN_SPI_CS 4
    
    
    File file;
    char buf[200];
    
    
    void setup() {
      Serial.begin(9600);
      DDRD = B11111111;
    
    
      if (!SD.begin(PIN_SPI_CS)) {
        Serial.println(F("SD CARD FAILED, OR NOT PRESENT!"));
        while (1); // don't do anything more:
      }
    
    
      // open file for reading
      file = SD.open("albers.hex", FILE_READ);
      if (file) {
        int avail_len = file.available();
        int read_len = file.readBytes(buf, avail_len); // read all to buffer to buffer
    
    
        Serial.print("Length:");
        Serial.println(read_len);
        Serial.println("Content:");
    
    
                  for (int i=0; i<200; i++) {
       
        Serial.print(byte(buf[i]));
        PORTD = byte(buf[i]);
              }
       
    
    
        file.close();
      } else {
        Serial.print(F("SD Card: error on opening file"));
      }
    }
    
    
    void loop() {
    }

    I consulted this site : https://www.dcode.fr/binary-image to convert an image into binary (not sure yet how I will do this for video but I’ll cross that bridge later). I chose resolution 200 for this image :

    For the video I am looking into FFMPEG. It can export still images every X seconds (ffmpeg -i input.mp4 frame%04d.png) which I could then turn into bits with a simple python or processing code.

    Processing also has code to take video and convert it to ASCII : https://github.com/processing/processing-video/blob/main/examples/Capture/AsciiVideo/AsciiVideo.pde

    Maybe the best setup would be to have Processing create a series of ASCII text files based on frames from a video, and then put that on the SD card.

    Here is a schematic of how it could work with two SRAM banks in dual banking mode, writing to one while reading from the other and then switching :

    ******

    PROGRAMMING FPGA WITH ARDUINO OR RPI

    I had been trying to open the OLIMEX demo code pilot incorrectly. It does indeed work from the command line. I’ll have to test with the MEGA next.

    ****

    An attempt at mixing the pattern generation with the recording to memory functionality :

    `default_nettype none
    
    module vga_sync_test(
    
    input wire clk_in,
    input wire reset,
    
    input wire rec, // Direction of io, 1 = set output, 0 = read input
    
    //RASPBERRY PI
    input wire [3:0] r_in,
    input wire [3:0] b_in,
    input wire [3:0] g_in,
    
    //VGA OUT
    output reg [3:0] r_out,
    output reg [3:0] b_out,
    output reg [3:0] g_out,
    
    output wire h_sync,
    output wire v_sync,
    
    //SRAM
    
    output reg [20:0] addr,
    inout wire [7:0] io, // inout must be type wire
    
    output wire cs_1,
    output wire cs_0,
    output reg we_0
    
    );
    
    
    wire half_sec;
    
    wire [12:0] random_number_0;
    wire [12:0] random_number_1;
    wire [12:0] random_number_2;
    wire [12:0] random_number_3;
    wire [12:0] random_number_4;
    wire [12:0] random_number_5;
    wire [12:0] random_number_6;
    wire [12:0] random_number_7;
    wire [12:0] random_number_8;
    wire [12:0] random_number_9;
    wire [7:0] sine_wave;
    
    wire [7:0] data_in;
    wire [7:0] data_out;
    
    reg toggle;
    
    reg [7:0] a, b;
    
    assign io = rec ? a : 8'bzzzzzzzz;
    
    assign data_out = b;
    
    assign data_in[1:0] = r_in[3:2];
    assign data_in[3:2] = b_in[3:2];
    assign data_in[5:4] = g_in[3:2];
    assign data_in[7:6] = 2'b00;
    
    wire display_en;
    wire [11:0] h_count;
    wire [11:0] v_count;
    
    localparam h_pixel_max = 1280;
    localparam v_pixel_max = 960;
    localparam h_pixel_half = 640;
    localparam v_pixel_half = 480;
    
    
    reg [1:0] count2; //to keep track of the shifts
    
    wire [11:0] bit_or;
    assign bit_or = h_count[11:0]|v_count[11:0];
    
    wire [11:0] bit_xor;
    assign bit_xor = h_count[11:0]^v_count[11:0];
    
    wire [11:0] bit_and;
    assign bit_and = h_count[11:0]&v_count[11:0];
    
    wire [11:0] bit_nand;
    assign bit_nand = h_count[11:0]& ~v_count[11:0];
    
    wire [11:0] bit_xnor;
    assign bit_xnor = h_count[11:0]^ ~v_count[11:0];
    
    reg [11:0] out_bit ;
    
    
    // CS: low to select, high to deselect
    
    assign cs_0 = toggle ? 1 : 0;
    assign cs_1 = toggle ? 0 : 1;
    
    //SRAM address counter
    
    always @(posedge clk_in) begin
    
    if (addr == 0) begin
    toggle <= toggle+1;
    end
    
    if (reset) begin
    addr <= 0;
    end else begin
    addr <= addr+1;
    
    end
    end
    
    
    //REC control
    
    always @(posedge clk_in) begin
    
    b <= io;
    a <= data_in;
    
    if (rec) begin
    we_0 <= addr[0]; //not sure why it isn't the inverse of addr[0] but that doesn't make the inverse on 'scope
    end
    else begin
    we_0 <= 1;
    end
    end
    
    //VGA COLOR OUT
    
    always @(posedge clk_in) begin
    
    case(count2)
    2'b00: out_bit = bit_or;
    2'b01: out_bit = bit_xor;
    2'b10: out_bit = bit_and;
    2'b11: out_bit = bit_nand;
    
    default: out_bit = bit_xnor;
    endcase
    count2 <= count2 + 1;
    end
    
    //VGA COLOR OUT
    
    always @(posedge clk_in) begin
    if (display_en) begin
    
    if (out_bit[random_number_2[3:0]] == 1 | out_bit[random_number_6[3:0]] == 0) begin
    
    r_out <= random_number_2[3:0];
    g_out <= random_number_3[3:0];
    b_out <= random_number_4[3:0];
    
    end
    
    else begin
    
    r_out[3:2] <= data_out[1:0];
    r_out[1:0] <= data_out[1:0];
    g_out[3:2] <= data_out[3:2];
    g_out[1:0] <= data_out[3:2];
    b_out[3:2] <= data_out[5:4];
    b_out[1:0] <= data_out[5:4];
    
    end
    
    end else begin
    
    r_out <= 4'b0000;
    g_out <= 4'b0000;
    b_out <= 4'b0000;
    
    end
    end
    
    vga_sync vga_s(
    .clk_in(clk_in),
    .reset(reset),
    .h_sync(h_sync),
    .v_sync(v_sync),
    .h_count(h_count),
    .v_count(v_count),
    .display_en(display_en) // '1' => pixel region
    );
    
    LFSR random_s(
    .clock(clk_in),
    .reset(reset),
    .half_sec_pulse(half_sec),
    .rnd_0(random_number_0),
    .rnd_1(random_number_1),
    .rnd_2(random_number_2),
    .rnd_3(random_number_3),
    .rnd_4(random_number_4),
    .rnd_5(random_number_5),
    .rnd_6(random_number_6),
    .rnd_7(random_number_7),
    .rnd_8(random_number_8),
    .rnd_9(random_number_9)
    );
    
    sine_wave_gen sine_wave_s(
    .clk(clk_in),
    .data_out(sine_wave)
    );
    
    tempo tempo_s(
    .clk(clk_in),
    .half_sec_pulse(half_sec)
    );
    
    endmodule
    

     

    I just realized that I could connect the rpi pixel clock to the FPGA to have a totally synchronized clock between the videos and the graphics ! I can also connect the DEN pin. Not really working currently though.

    *****

    Miniature discovery, if you just take a single bit of information from raspberry pi sending a video, it looks really blocky and cool like a badly compressed video :

    Check out this artist Ni Hao’s  broken screens ( https://haoni.art/spin-III) :

    FPGA SRAM board

    FPGA SRAM board

     

    Shadertoy is the future of this project, so what am I doing ? This new board is a reprogrammable FPGA 2D pixel shader (aka fragment shader) which can control the color of pixels and know only of the coordinate of the pixel being drawn. Pixel shaders can also sample the values of nearby pixels. As a result, they can do 2D post-processing (https://en.wikipedia.org/wiki/Video_post-processing) or filtering for a video streams. Why do this on an FPGA rather than in-brower ? You are super low level, and you have constraints based on the number of LUTs, it has a live-playable interface. In any case, I think this is my last board for a while, unless I can make an AI board somehow.

    On the other hand, I’m not sure how profound it is to make photoshop like filters. (You can test a 5×5 grid if you go under Filters>Custom in PS). They are all kind of superficial…

    I am starting to realize that I spend loads of time debugging soldering errors (yes, I get the learning that comes with that but still). If I made boards and had them assembled elsewhere I would not have this issue. Should I also, in the same spirit, just jump ahead to what everyone else is doing, with the thinking that they are not wasting time on problems that have already been solved and are exploring an interesting space.

    I also spend a lot of time designing and building boards, interfaces, and less time programming them: the SCARA robot arm that I didn’t even plug in, the covid temperature interface board, the drone, and the MIT version of the mini swarm robot. On the other side are the projects I’ve perhaps spent too must time making and incrementally remaking perhaps : 3105 power harvester + radio transciever, the Ben Eater style memory. A nice balance was perhaps the solar sunflower protytpes which were experiments with form and function.

    *EDIT* I am now thinking that I must work on things that would be of interest to other people, like Machine Learning for instance. I must be humble, just because something is interesting to me doesn’t mean anyone else cares ! Turns our that FPGAs consume a lot less current than GPUs so they are not bad for implementing ML once the training is done. Here is a info about ML with FPGAs :

    • https://www.youtube.com/@marcowinzker3682
    • https://www.mdpi.com/2076-3417/12/1/89
    • https://github.com/verimake-team/MLonFPGA
    • https://qengineering.eu/deep-learning-with-fpga-aka-bnn.html
    • https://qengineering.eu/embedded-vision.html#FPGA_stitching

    Great post about the marble machine project : https://www.reddit.com/r/MarbleMachineX/comments/pzh5kw/an_open_letter_to_martin_on_the_state_of_the/

    • The machine is not about reliability and precision, it is about imperfection and the journey
    • It’s an art project, it is a project for the project’s sake and the documentation.
    • The project shouldn’t run like a start-up, and we are not the sum of what we produce for capitalism
    • Not specializing in one thing is what makes this project cool.

    ERRATA :

    • I think the 590 is not clock dividing as expected…Is it not 3.3V compatible ? I think so, even though unclear on Mouser website.
    • Currently only 2 bits of each raspberry pi color input are appearing despite having selected dpi24 in the rpi config file.
    • The fine pots are the wrong footprint for the pots I have.
    • I could have used DEN (display enable) from the raspi.
    • sometimes the rpi starts up and then restarts after playing only a few seconds of video…not sure why.

    To change the PLL, there is a tool in IceCube2 under Tool>Configure>Configure PLL Module

    Here is the user guide explaining how to use it : https://www.latticesemi.com/-/media/LatticeSemi/Documents/ApplicationNotes/IK2/FPGA-TN-02052-1-4-iCE40-sysCLOCK-PLL-Design-User-Guide.ashx?document_id=47778

    I want the following options :

    • General Purpose I/O Pad or Core Logic
    • Using a feedback path internal to the PLL
    • Input Frequency (MHz) : 100
    • Output Frequency (MHz) : 25

    Here is the new PCF file :

    set_io v_sync 87
    set_io h_sync 88
    set_io clk_in 64
    set_io reset 66
    set_io r0 81
    set_io r1 80
    set_io r2 79
    set_io g0 94
    set_io g1 93
    set_io g2 91
    set_io b0 76
    set_io b1 75
    set_io b2 74
    set_io led 45
    set_io locked_led 37
    
    Tested with a 12MHz external clock, it works to output VGA.
    No luck so far with 100MHz clock and multiplying all the pixel drawing, syncing and front and back porches by 4. Thinking of just switching out for a 12MHz clock like on the first version.
    *EDIT* Also working with 25MHz external clock and removing the PLL.
    *EDIT* Very strange but working with 100MHz now, except the code should only work with 50MHz…Here are the two files being used to generate the signal :
    
    module vga_sync_test(
    input wire clk_in,
    input wire reset,
    output reg r0,
    output reg r1,
    output reg r2,
    output reg b0,
    output reg b1,
    output reg b2,
    output reg g0,
    output reg g1,
    output reg g2,
    output wire h_sync,
    output wire v_sync
    );
    
    wire display_en;
    //reg [9:0] h_count;
    wire [11:0] h_count;
    //reg [9:0] v_count;
    wire [11:0] v_count;
    
    /*
    //for 100MHZ
    localparam h_pixel_max = 2560;
    localparam v_pixel_max = 1920;
    localparam h_pixel_half = 1280;
    localparam v_pixel_half = 960;
    */
    
    
    //for 50MHZ
    
    localparam h_pixel_max = 1280;
    localparam v_pixel_max = 960;
    localparam h_pixel_half = 640;
    localparam v_pixel_half = 480;
    
    /*
    //for 25MHZ
    
    localparam h_pixel_max = 640;
    localparam v_pixel_max = 480;
    localparam h_pixel_half = 320;
    localparam v_pixel_half = 240;
    */
    
    //Check if we can create RGB colors
    always @(posedge clk_in) begin
    if (display_en) begin
    if (h_count < h_pixel_half
    && v_count < v_pixel_half) begin
    //Assign here your test color
    r0 <= 1'b0;
    r1 <= 1'b0;
    r2 <= 1'b0;
    g0 <= 1'b0;
    g1 <= 1'b0;
    g2 <= 1'b0;
    b0 <= 1'b1;
    b1 <= 1'b1;
    b2 <= 1'b1;
    end else if (h_count > h_pixel_half
    && v_count < v_pixel_half) begin
    //Assign here your test color
    r0 <= 1'b0;
    r1 <= 1'b0;
    r2 <= 1'b0;
    g0 <= 1'b1;
    g1 <= 1'b1;
    g2 <= 1'b1;
    b0 <= 1'b0;
    b1 <= 1'b0;
    b2 <= 1'b0;
    end else if (h_count < h_pixel_half
    && v_count > v_pixel_half) begin
    //Assign here your test color
    r0 <= 1'b1;
    r1 <= 1'b1;
    r2 <= 1'b1;
    g0 <= 1'b0;
    g1 <= 1'b0;
    g2 <= 1'b0;
    b0 <= 1'b0;
    b1 <= 1'b0;
    b2 <= 1'b0;
    end else begin
    //Assign here your test color
    r0 <= 1'b1;
    r1 <= 1'b1;
    r2 <= 1'b1;
    g0 <= 1'b1;
    g1 <= 1'b1;
    g2 <= 1'b1;
    b0 <= 1'b1;
    b1 <= 1'b1;
    b2 <= 1'b1;
    end
    end else begin
    r0 <= 1'b0;
    r1 <= 1'b0;
    r2 <= 1'b0;
    g0 <= 1'b0;
    g1 <= 1'b0;
    g2 <= 1'b0;
    b0 <= 1'b0;
    b1 <= 1'b0;
    b2 <= 1'b0;
    end
    end
    
    vga_sync vga_s(
    .clk_in(clk_in), //100,50, OR 25MHz clock input
    .reset(reset), // RST assigned to SW1
    .h_sync(h_sync),
    .v_sync(v_sync),
    .h_count(h_count),
    .v_count(v_count),
    .display_en(display_en) // '1' => pixel region
    );
    
    endmodule
    /*
    640x480 VGA singal generator
    ============================
    
    - Creates h_sync,v_sync signals
    - Creates display enable signal and horizontal, vertical
    pixel position in display (h,v)
    */
    
    `default_nettype none
    
    
    module vga_sync(
    input wire clk_in,
    input wire reset,
    output reg h_sync,
    output reg v_sync,
    output wire clk_sys,
    output reg [11:0] h_count,
    output reg [11:0] v_count,
    output reg display_en
    );
    
    
    // Pixel counters
    reg [11:0] h_counter = 0;
    reg [11:0] v_counter = 0;
    
    /*
    
    //FOR 100MHz
    
    localparam h_pixel_total = 3200;
    localparam h_pixel_display = 2560;
    localparam h_pixel_front_porch_amount = 64;
    localparam h_pixel_sync_amount = 384;
    localparam h_pixel_back_porch_amount = 192;
    
    localparam v_pixel_total = 2100;
    localparam v_pixel_display = 1920;
    localparam v_pixel_front_porch_amount = 40;
    localparam v_pixel_sync_amount = 8;
    localparam v_pixel_back_porch_amount = 132;
    
    */
    
    // FOR 50MHz
    
    localparam h_pixel_total = 1600;
    localparam h_pixel_display = 1280;
    localparam h_pixel_front_porch_amount = 32;
    localparam h_pixel_sync_amount = 192;
    localparam h_pixel_back_porch_amount = 96;
    
    localparam v_pixel_total = 1050;
    localparam v_pixel_display = 960;
    localparam v_pixel_front_porch_amount = 20;
    localparam v_pixel_sync_amount = 4;
    localparam v_pixel_back_porch_amount = 66;
    
    
    /*
    
    //FOR 25MHz
    
    localparam h_pixel_total = 800;
    localparam h_pixel_display = 640;
    localparam h_pixel_front_porch_amount = 16;
    localparam h_pixel_sync_amount = 96;
    localparam h_pixel_back_porch_amount = 48;
    
    localparam v_pixel_total = 525;
    localparam v_pixel_display = 480;
    localparam v_pixel_front_porch_amount = 10;
    localparam v_pixel_sync_amount = 2;
    localparam v_pixel_back_porch_amount = 33;
    
    */
    
    always @(posedge clk_in) begin
    
    if (reset) begin
    //Reset counter values
    h_counter <= 0;
    v_counter <= 0;
    display_en <= 0;
    end
    else
    begin
    // Generate display enable signal
    if (h_counter < h_pixel_display && v_counter < v_pixel_display)
    display_en <= 1;
    else
    display_en <= 0;
    
    //Check if horizontal has arrived to the end
    if (h_counter >= h_pixel_total)
    begin
    h_counter <= 0;
    v_counter <= v_counter + 1;
    end
    else
    //horizontal increment pixel value
    h_counter <= h_counter + 1;
    // check if vertical has arrived to the end
    if (v_counter >= v_pixel_total)
    v_counter <= 0;
    end
    end
    
    always @(posedge clk_in) begin
    // Check if sync_pulse needs to be created
    if (h_counter >= (h_pixel_display + h_pixel_front_porch_amount)
    && h_counter < (h_pixel_display + h_pixel_front_porch_amount + h_pixel_sync_amount) )
    h_sync <= 0;
    else
    h_sync <= 1;
    // Check if sync_pulse needs to be created
    if (v_counter >= (v_pixel_display + v_pixel_front_porch_amount)
    && v_counter < (v_pixel_display + v_pixel_front_porch_amount + v_pixel_sync_amount) )
    v_sync <= 0;
    else
    v_sync <= 1;
    end
    
    // Route h_/v_counter to out
    always @ (posedge clk_in) begin
    h_count <= h_counter;
    v_count <= v_counter;
    end
    
    endmodule

    ***
    Trying to reconfigure the raspberry pi now for DPI output based on this document : https://www.raspberrypi.com/documentation/computers/raspberry-pi.html
    Here’s what I did :
    dtparam=spi=off
    dtparam=i2c_arm=off
    #display_auto_detect=1 // comment this
    #dtoverlay=vc4-kms-v3d // comment this
    gpio=0-9=a2
    gpio=12-17=a2
    gpio=20-25=a2
    gpio=26-27=a2
    dtoverlay=dpi24
    enable_dpi_lcd=1
    display_default_lcd=1
    extra_transpose_buffer=2
    dpi_group=2
    dpi_mode=87
    dpi_output_format=0x7f216
    dpi_timings=720 0 40 48 128 720 0 13 3 15 0 0 0 60 0 41000000 4
    Will now try to get the raspberry pi going at 50000000. Doesn’t seem to help FPGA with FPGA H&V to record or play anything back.
    Testing to see if I can very simply just let the raspberry pi signals pass through the FPGA :
    module vga_sync(
    input wire R7IN,
    input wire R6IN,
    input wire R5IN,
    input wire R4IN,
    input wire G7IN,
    input wire G6IN,
    input wire G5IN,
    input wire G4IN,
    input wire B7IN,
    input wire B6IN,
    input wire B5IN,
    input wire B4IN,
    output wire R7OUT,
    output wire R6OUT,
    output wire R5OUT,
    output wire R4OUT,
    output wire G7OUT,
    output wire G6OUT,
    output wire G5OUT,
    output wire G4OUT,
    output wire B7OUT,
    output wire B6OUT,
    output wire B5OUT,
    output wire B4OUT
    );
    
    assign R7OUT = R7IN;
    assign R6OUT = R6IN;
    assign R5OUT = R5IN;
    assign R4OUT = R4IN;
    assign G7OUT = G7IN;
    assign G6OUT = G6IN;
    assign G5OUT = G5IN;
    assign G4OUT = G4IN;
    assign B7OUT = B7IN;
    assign B6OUT = B6IN;
    assign B5OUT = B5IN;
    assign B4OUT = B4IN;
    

    I made a pcf to go with this test code :

    set_io R7IN 107
    set_io R6IN 106
    set_io R5IN 105
    set_io R4IN 104
    set_io G7IN 97
    set_io G6IN 96
    set_io G5IN 95
    set_io G4IN 112
    set_io B7IN 102
    set_io B6IN 101
    set_io B5IN 99
    set_io B4IN 98
    set_io R7OUT 81
    set_io R6OUT 80
    set_io R5OUT 79
    set_io R4OUT 78
    set_io G7OUT 94
    set_io G6OUT 93
    set_io G5OUT 91
    set_io G4OUT 90
    set_io B7OUT 76
    set_io B6OUT 75
    set_io B5OUT 74
    set_io B4OUT 73

    Memory soldering done, added to the pcf :

    set_io v_sync 87
    set_io h_sync 88
    set_io clk_in 64
    set_io reset 66
    set_io r0 81
    set_io r1 80
    set_io r2 79
    set_io g0 94
    set_io g1 93
    set_io g2 91
    set_io b0 76
    set_io b1 75
    set_io b2 74
    
    set_io io0 1
    set_io io1 2
    set_io io2 3
    set_io io3 4
    set_io io4 122
    set_io io5 121
    set_io io6 120
    set_io io7 119
    
    set_io a0 138
    set_io a1 139
    set_io a2 141
    set_io a3 142
    set_io a4 143
    set_io a5 8
    set_io a6 9
    set_io a7 10
    set_io a8 11
    set_io a9 12
    set_io a10 136
    set_io a11 135
    set_io a12 134
    set_io a13 129
    set_io a14 128
    set_io a15 117
    set_io a16 116
    set_io a17 115
    set_io a18 114
    set_io a19 137
    set_io a20 113
    
    set_io cs1 71
    set_io we0 7

    *********************

    Refreshing my verilog learning from HDLbits :

    A note on wire vs. reg: The right-hand-side of an assign statement must be a net type (e.g., wire), while the left-hand-side of a procedural assignment (in an always block) must be a variable type (e.g., reg).

                                                                                                      *******

    you can do assign w = a; outside of an always block

    assign continuously drives a into w

    assign out = a&b; makes out equal to a AND’ed with b

    it’s a combinational (i.e., memory-less, with no hidden state) function

    using assign is the same as using always @(*)

                                                                                                *****

    if you don’t declare it, output [3:0] a; will be a vector of type wire

    to declare a vector : type [upper:lower] vector_name;

                                                                                                  *****

    A bitwise operation between two N-bit vectors replicates the operation for each bit of the vector and produces a N-bit output, while a logical operation treats the entire vector as a boolean value (true = non-zero, false = zero) and produces a 1-bit output.

    Eg.

    output [2:0] out_or_bitwise,
    output out_or_logical,

    assign out_or_bitwise = a | b;
    assign out_or_logical = a || b;

    Beware the different symbols for bitwise or logical !
                                                                                                    ****

    module mod_a ( input in1, input in2, output out );
    // Module body
    endmodule

    When instantiating mod_a inside top_module :

    module top_module (
    input a,
    input b,
    output out
    );

    // Create an instance of “mod_a” named “inst1”, and connect ports by name:
    mod_a inst1 (
    .in1(a), // Port”in1″connects to wire “a”
    .in2(b), // Port “in2” connects to wire “b”
    .out(out) // Port “out” connects to wire “out”
    // (Note: mod_a’s port “out” is not related to top_module’s wire “out”.
    // It is simply coincidence that they have the same name)
    );

                                                                                                    ***

    ALWAYS BLOCKS :

    Clocked: always @(posedge clk)

    Procedural blocks have a richer set of statements (e.g., if-then, case), cannot contain continuous assignments,

    Clocked always blocks create a blob of combinational logic just like combinational always blocks, but also creates a set of flip-flops (or “registers”) at the output of the blob of combinational logic. Instead of the outputs of the blob of logic being visible immediately, the outputs are visible only immediately after the next (posedge clk).

    In a locked always block, only use procedural non-blocking assignment: (x <= y;)

                                                                                                ***

    Combinational circuits must have a value assigned to all outputs under all conditions. This usually means you always need else clauses or a default value assigned to the outputs.

    This can cause the Warning (10240): … inferring latch(es) error message

                                                                                                ***

    Saw some inspiring machines in Munich :

    Barrels would be cool to incorporate into my next prototype.

    I wonder if I could make an analog feedback set up with linear actuators, a screen and camera…

    I love the scientific instrument aspect. The monitor hovering on the side could be cool to incorporate.

     

    *****

    Check out this analog video feedback setup… could I do a miniature version ? :

     

    ****

    One reaction to the museum visit it to think of what makes something look like a machine.

    • an agglomeration of mainly metal (especially machined aluminum and folded steel) and plastic modules
    • rotation and linear motion, symmetry about a central axis or a pile of modules facing the user

    If I wanted to focus on the technical object itself, I could work on a custom cooling setup, with thin curving pipes, knobs that allow for various kinds of custom fine control, screens and cameras on various linear axes for feedback loop control.

    A DIY water cooler :

    Amazing! DIY Mini Liquid Cooling System - YouTube

    Importance apprenti Gonfle diy cpu water block la toux mosaĂŻque sans rapport

    A custom keyboard from https://keyboards.tanebox.com/a/blog/939/ :

    I like the exposed keyboard that extends into a circuit board with chips on the top. Could it be possible to make a kind of reprogrammable FPGA video synth computer ? Perhaps I could also learn things about video by taking a video file from a an SD card and then moving it into a dual port DRAM memory to be displayed.

    This gets at something that feels important : I am always trying to get myself to some harder to get to place, with the help of DIY tech, before making artsy stuff. It’s almost like I feel I’m not competitive enough starting from the most accessible starting point (classical art like drawing, painting, sculpture). Sam suggested that I combine my interest in hardware with software. Can I make a kind of custom programmable computer that is my own and then program it in a low level language (like assembly or verilog)?

    MechBoardsぼPlaid // ThroughHole – コトコト

    I love the windy wire plug found on the mechanical keyboard subreddit :

    r/CustomKeyboards - I Can't Get No

    r/CustomKeyboards - My totally customized split keyboard

    From https://spectrum.ieee.org/yugoslavia-diy-microcomputer :

    Keyboard buttons from Mouser : https://www.mouser.fr/ProductDetail/E-Switch/KS1100OA1AF060?qs=gt1LBUVyoHkJwqhwHM2wRw%3D%3D

    ***

    Or, in the totally opposite direction (not going for gimmicks or flashiness), super inexpensive DRAM chips (1 euro for 16Mbit) :

    https://www.mouser.fr/ProductDetail/ISSI/IS42S16100H-7TL?qs=yfIbTn1BQ2BEUPfKEYbGCA%3D%3D

    ****

    Had a thought : I am basically trying to “play” the VGA format itself like an instrument.

    ****

    So making a pin that is both input and output for an FPGA is not so simple ! This post helped : https://electronics.stackexchange.com/questions/33144/birectional-i-o-pin-in-verilog

    My attempts to make diagrams :

     

    I also cleaned up the code a bit, making vectors with indices and following naming conventions :

    I can see evidence of something being recorded and played back out of sync (only when rpi input provides H&V and the FPGA used the rpi 41MHz pixel clock or the 100MHz clock) but it’s far from working completely.

    I can send external clocks that are divisions of 41MHz clock (20.5MHz, 10.25MHz) when rpi is supplying the H&V and it just barely works.

    The FPGA works with external 25MHz clock also, but I can’t see any recordings.

    *EDIT* I can get pretty clear recordings with the RPI clock and H&V after fiddling. Still no luck with recording RPI color information and then showing it at FPGA H&V with either pixel clock. I have gotten rid of the test colors and now am showing full screen FPGA. Twiddled 4 versus 3 bits on the output.

    `default_nettype none
    
    module vga_sync_test(
    
    input wire clk_in,
    input wire reset,
    
    input wire rec, // Direction of io, 1 = set output, 0 = read input
    
    //RASPBERRY PI
    input wire [3:0] r_in,
    input wire [3:0] b_in,
    input wire [3:0] g_in,
    
    //VGA OUT
    output reg [3:0] r_out,
    output reg [3:0] b_out,
    output reg [3:0] g_out,
    
    output wire h_sync,
    output wire v_sync,
    
    //SRAM
    
    output reg [20:0] addr,
    inout wire [7:0] io, // inout must be type wire
    
    output wire cs_1,
    output reg we_0
    
    );
    
    wire [7:0] data_in;
    wire [7:0] data_out;
    
    reg [7:0] a, b;
    
    assign io = rec ? a : 8'bzzzzzzzz;
    
    assign data_out = b;
    
    assign data_in[1:0] = r_in[3:2];
    assign data_in[3:2] = b_in[3:2];
    assign data_in[5:4] = g_in[3:2];
    assign data_in[7:6] = 2'b00;
    
    wire display_en;
    wire [11:0] h_count;
    wire [11:0] v_count;
    
    assign cs_1 = 0; // low to select, high to deselect
    
    localparam h_pixel_max = 1280;
    localparam v_pixel_max = 960;
    localparam h_pixel_half = 640;
    localparam v_pixel_half = 480;
    
    
    //SRAM address counter
    
    always @(posedge clk_in) begin
        if (reset)
            addr <= 0;
        else
            addr <= addr+1;
        end
    
    
    //REC control
    
    always @(posedge clk_in) begin
          b <= io;
          a <= data_in;
         if (rec) begin
              we_0 <= addr[0]; //not sure why it isn't the inverse of addr[0] but that doesn't make the inverse on 'scope
         end
         else begin
              we_0 <= 1;
         end
    end
    
    //VGA COLOR OUT
    
    always @(posedge clk_in) begin
    if (display_en) begin
    if (h_count < h_pixel_half
    && v_count < v_pixel_half) begin
    
    r_out[1:0] <= data_out[1:0];
    r_out[2] <= 1'b0;
    g_out[1:0] <= data_out[3:2];
    g_out[2] <= 1'b0;
    b_out[1:0] <= data_out[5:4];
    b_out[2] <= 1'b0;
    
    end else if (h_count > h_pixel_half
    && v_count < v_pixel_half) begin
    
    
    r_out <= 3'b000;
    g_out <= 3'b111;
    b_out <= 3'b000;
    
    end else if (h_count < h_pixel_half
    && v_count > v_pixel_half) begin
    
    
    r_out <= 3'b111;
    g_out <= 3'b000;
    b_out <= 3'b000;
    
    end else begin
    
    
    r_out <= 3'b111;
    g_out <= 3'b111;
    b_out <= 3'b111;
    
    end
    end else begin
    
    r_out <= 3'b000;
    g_out <= 3'b000;
    b_out <= 3'b000;
    end
    end
    
    vga_sync vga_s(
    .clk_in(clk_in),
    .reset(reset),
    .h_sync(h_sync),
    .v_sync(v_sync),
    .h_count(h_count),
    .v_count(v_count),
    .display_en(display_en) // '1' => pixel region
    );
    
    endmodule
    
    

     

    Here is the complete pcf :

    set_io v_sync 87
    set_io h_sync 88
    set_io clk_in 64
    set_io reset 66
    
    set_io io[0] 1
    set_io io[1] 2
    set_io io[2] 3
    set_io io[3] 4
    set_io io[4] 122
    set_io io[5] 121
    set_io io[6] 120
    set_io io[7] 119
    
    set_io io[8] 45
    set_io io[9] 47
    set_io io[10] 48
    set_io io[11] 49
    set_io io[12] 28
    set_io io[13] 26
    set_io io[14] 25
    set_io io[15] 24
    
    set_io addr[0] 138
    set_io addr[1] 139
    set_io addr[2] 141
    set_io addr[3] 142
    set_io addr[4] 143
    set_io addr[5] 8
    set_io addr[6] 9
    set_io addr[7] 10
    set_io addr[8] 11
    set_io addr[9] 12
    set_io addr[10] 136
    set_io addr[11] 135
    set_io addr[12] 134
    set_io addr[13] 129
    set_io addr[14] 128
    set_io addr[15] 117
    set_io addr[16] 116
    set_io addr[17] 115
    set_io addr[18] 114
    set_io addr[19] 137
    set_io addr[20] 113
    
    set_io addr[21] 38
    set_io addr[22] 39
    set_io addr[23] 41
    set_io addr[24] 42
    set_io addr[25] 43
    set_io addr[26] 52
    set_io addr[27] 56
    set_io addr[28] 58
    set_io addr[29] 60
    set_io addr[30] 61
    set_io addr[31] 34
    set_io addr[32] 33
    set_io addr[33] 32
    set_io addr[34] 31
    set_io addr[35] 29
    set_io addr[36] 23
    set_io addr[37] 22
    set_io addr[38] 21
    set_io addr[39] 20
    set_io addr[40] 37
    set_io addr[41] 19
    
    set_io cs_0 144
    set_io cs_1 71
    set_io cs_2 44
    set_io cs_3 63
    
    set_io we_0 7
    set_io we_1 50
    
    set_io rec 62
    
    set_io r_in[0] 107
    set_io r_in[1] 106
    set_io r_in[2] 105
    set_io r_in[3] 104
    set_io g_in[0] 97
    set_io g_in[1] 96
    set_io g_in[2] 95
    set_io g_in[3] 112
    set_io b_in[0] 102
    set_io b_in[1] 101
    set_io b_in[2] 99
    set_io b_in[3] 98
    
    set_io r_out[0] 81
    set_io r_out[1] 80
    set_io r_out[2] 79
    set_io r_out[3] 78
    set_io g_out[0] 94
    set_io g_out[1] 93
    set_io g_out[2] 91
    set_io g_out[3] 90
    set_io b_out[0] 76
    set_io b_out[1] 75
    set_io b_out[2] 74
    set_io b_out[3] 73

    ****

    Added the third SRAM and having issues, commented out one new pin at a time and it seems like address 18 (on pin 20) is problematic. When I remove this pin everything else functions well enough for a memory with a missing pin however.

    `default_nettype none
    
    module vga_sync_test(
    
    input wire clk_in,
    input wire reset,
    
    input wire rec, // Direction of io, 1 = set output, 0 = read input
    
    //RASPBERRY PI
    input wire [3:0] r_in,
    input wire [3:0] b_in,
    input wire [3:0] g_in,
    
    //VGA OUT
    output reg [3:0] r_out,
    output reg [3:0] b_out,
    output reg [3:0] g_out,
    
    output wire h_sync,
    output wire v_sync,
    
    //SRAM
    
    output reg [20:0] addr,
    inout wire [7:0] io, // inout must be type wire
    
    output wire cs_1,
    output wire cs_0,
    output reg we_0
    
    );
    
    wire [7:0] data_in;
    wire [7:0] data_out;
    
    reg toggle;
    
    reg [7:0] a, b;
    
    assign io = rec ? a : 8'bzzzzzzzz;
    
    assign data_out = b;
    
    assign data_in[1:0] = r_in[3:2];
    assign data_in[3:2] = b_in[3:2];
    assign data_in[5:4] = g_in[3:2];
    assign data_in[7:6] = 2'b00;
    
    wire display_en;
    wire [11:0] h_count;
    wire [11:0] v_count;
    
    localparam h_pixel_max = 1280;
    localparam v_pixel_max = 960;
    localparam h_pixel_half = 640;
    localparam v_pixel_half = 480;
    
    // CS: low to select, high to deselect
    
    assign cs_0 = toggle ? 1 : 0;
    assign cs_1 = toggle ? 0 : 1;
    
    //SRAM address counter
    
    always @(posedge clk_in) begin
    
    if (addr == 0) begin
    toggle <= toggle+1;
    end
    
    if (reset) begin
    addr <= 0;
    end else begin
    addr <= addr+1;
    
    end
    end
    
    
    //REC control
    
    always @(posedge clk_in) begin
    
    b <= io;
    a <= data_in;
    
    if (rec) begin
    we_0 <= addr[0]; //not sure why it isn't the inverse of addr[0] but that doesn't make the inverse on 'scope
    end
    else begin
    we_0 <= 1;
    end
    end
    
    //VGA COLOR OUT
    
    always @(posedge clk_in) begin
    if (display_en) begin
    
    r_out[3:2] <= data_out[1:0];
    r_out[1:0] <= data_out[1:0];
    g_out[3:2] <= data_out[3:2];
    g_out[1:0] <= data_out[3:2];
    b_out[3:2] <= data_out[5:4];
    b_out[1:0] <= data_out[5:4];
    
    end else begin
    
    r_out <= 4'b0000;
    g_out <= 4'b0000;
    b_out <= 4'b0000;
    end
    end
    
    vga_sync vga_s(
    .clk_in(clk_in),
    .reset(reset),
    .h_sync(h_sync),
    .v_sync(v_sync),
    .h_count(h_count),
    .v_count(v_count),
    .display_en(display_en) // '1' => pixel region
    );
    
    endmodule

    ***

    I made an animated video of the assembly of the board :

    When I make the next board I’ll  record the eagle CAD and make another video.

    Here are some images of what a new device could look like !

    What about an FPGA chip holder ? And a snazzy pivotable SD card holder ? Using meanders this time? With its own fictional programming language like in that assembly video game ? With a mini PCI-E connector somewhere ?

    To pre-digest the videos for the FPGA before putting them on a gigantic SD card, I could use ffmpeg to output a less compressed format like .avi or an .mkv and then erase the header and footer ?

    Have a name (little Lebowski urban achiever is too long), and a format 100×80 (free Eagle max), and a rough layout (HDMI super close, USB next to FTDI and to flash memory, all the memory to the right equidistant to the chip). AND, some kind of transparent cover, a first for me, make it seem more like a legitimate product and would reduce the risk of short circuits from something conductive falling on the board. For the symbols on the keyboard, there is the Comodore 64 keyboard symbol set which is cool. Or some ancient symbols ??

    I am now moving away from SDRAM, challenging and I’m not sure why I’m putting myself through it. The real interest is going to be decoding videos stored on the SD card and putting them on screen. I want to try to do it like the pros – drawing to the screen in the blanking period and using only one SRAM.

    ****

    Still trying to resolve the A18 issue.

    • I tried soldering another IO pin to pin 20, but this led to total chaos, none of the address pins working. I could have tried severing the link between the pin 20 and the SRAM but I don’t want to damage the board before I identify the problem (it may be in the code?).
    • Trying to lower the size of the address counter to stop at 17 instead of going to 18.
    • I connected to the rpi’s DEN and changed the code to work with it instead of the FPGAs display en (it doesn’t work anyways). It is cool as it is more likely to capture the image on the rpi if I understand correctly.

    ****

    I am now trying some of the code I was dreaming about – modifying the input and output video stream based on other parallel data.

    Here is one strategy based on two bits of the same color having an impact on recording and playback.

    if (b[3]==b[2]) begin
    a <= data_in;
    end
    else begin
    a <= 8'b00000000;
    end

    I have the two memories working (excepted A18 on the second SRAM), and also tried reading DEN from the rpi. It makes some pretty funky glitches by touching the RAM pins with my hands !

    Also check out the bitmap to program the FPGA :

     

    `default_nettype none
    
    module vga_sync_test(
    
    input wire clk_in,
    input wire reset,
    
    input wire rec, // Direction of io, 1 = set output, 0 = read input
    
    //RASPBERRY PI
    input wire [3:0] r_in,
    input wire [3:0] b_in,
    input wire [3:0] g_in,
    input wire DEN,
    
    //VGA OUT
    output reg [3:0] r_out,
    output reg [3:0] b_out,
    output reg [3:0] g_out,
    
    output wire h_sync,
    output wire v_sync,
    
    //SRAM
    
    output reg [20:0] addr,
    output reg [20:0] addr_copy,
    inout wire [15:0] io, // inout must be type wire
    
    output wire cs_3,
    output wire cs_2,
    output wire cs_1,
    output wire cs_0,
    
    output reg we_1,
    output reg we_0
    
    );
    
    wire [15:0] data_in;
    wire [15:0] data_out;
    
    reg [1:0] toggle;
    
    reg [15:0] a, b;
    
    assign io = rec ? a : 16'bzzzzzzzzzzzzzzzz;
    
    assign data_out = b;
    
    assign data_in[1:0] = DEN ? r_in[3:2] : 0;
    assign data_in[3:2] = DEN ? b_in[3:2] : 0;
    assign data_in[5:4] = DEN ? g_in[3:2] : 0;
    assign data_in[7:6] = 2'b00;
    
    assign data_in[9:8] = DEN ? r_in[3:2] : 0;
    assign data_in[11:10] = DEN ? b_in[3:2] : 0;
    assign data_in[13:12] = DEN ? g_in[3:2] : 0;
    assign data_in[15:14] = 2'b00;
    
    wire display_en;
    wire [11:0] h_count;
    wire [11:0] v_count;
    
    localparam h_pixel_max = 1280;
    localparam v_pixel_max = 960;
    localparam h_pixel_half = 640;
    localparam v_pixel_half = 480;
    
    // CS: low to select, high to deselect
    
    assign cs_0 = toggle == 2'b00 ? 1 : 0;
    assign cs_1 = toggle == 2'b01 ? 1 : 0;
    assign cs_2 = toggle == 2'b10 ? 1 : 0;
    assign cs_3 = toggle == 2'b11 ? 1 : 0;
    
    //SRAM address counter
    
    always @(posedge clk_in) begin
    
    if (addr == 0) begin
       toggle <= toggle+1;
    end
    
    if (reset) begin
       addr <= 0;
    end else begin
       addr <= addr+1;
       addr_copy <= addr_copy+1;
    
    end
    end
    
    //REC control
    
    always @(posedge clk_in) begin
    
       b <= io;
       a <= data_in;
    if (rec) begin
       we_0 <= addr[0]; //not sure why it isn't the inverse of addr[0] but that doesn't make the inverse on 'scope
       we_1 <= addr[0];
    end
    else begin
       we_0 <= 1;
       we_1 <= 1;
    end
    end
    
    //VGA COLOR OUT
    
    always @(posedge clk_in) begin
    if (DEN) begin
    if (toggle==2'b00 || toggle==2'b01 ) begin
       r_out[3:2] <= data_out[1:0];
       r_out[1:0] <= data_out[1:0];
       g_out[3:2] <= data_out[3:2];
       g_out[1:0] <= data_out[3:2];
       b_out[3:2] <= data_out[5:4];
       b_out[1:0] <= data_out[5:4];
    
    end else begin
       r_out[3:2]<= data_out[9:8];
       r_out[1:0]<= data_out[9:8];
       g_out[3:2]<= data_out[11:10];
       g_out[1:0]<= data_out[11:10];
       b_out[3:2]<= data_out[13:12];
       b_out[1:0]<= data_out[13:12];
    end
    end else begin
       r_out <= 4'b0000;
       g_out <= 4'b0000;
       b_out <= 4'b0000;
    end
    end
    
    vga_sync vga_s(
    .clk_in(clk_in),
    .reset(reset),
    .h_sync(h_sync),
    .v_sync(v_sync),
    .h_count(h_count),
    .v_count(v_count),
    .display_en(display_en) // '1' => pixel region
    );
    
    endmodule

    From https://www.fpga4fun.com/VerilogTips.html:

    • I need to initialize verilog counters !!
    • Another way of selecting 4 bits in a vector : wire [3:0] thisis4also = myvalue[16+:4];
    • It might be smarter to use a PLL than to take the external clock directly.
    • I need to debounce all input buttons !

    ****

    Check out shaders that take video as input :

    https://www.shadertoy.com/view/ctsyzN

    https://www.shadertoy.com/view/XtcSRs

    ****

    Tried to make some vignettes of the new board to show the impedence matching :

    I think I will order it in white with the meanders exposed like on the VGA spaghettini.

    Color options (I’m leaning towards white or maybe green):

    ***************************

    I am now thinking about how I will be able to share all that I am trying to learn about verilog and FPGAs in workshops. The bottleneck is programming the FPGA without special hardware.

    OLIMEX has a link to a rasberry pi utility called flashrom that can program and read FLASH memory documented here : https://github.com/OLIMEX/iCE40HX1K-EVB/tree/master/programmer/olimexino-32u4%20firmware

    These raspberry pi examples program the ice40 and looks simple :

    • https://j-marjanovic.io/lattice-ice40-configuration-using-raspberry-pi.html
    • https://github.com/plex1/raspice40

    The steps have been automated here : https://notabug.org/sagaracharya/swarajya/src/master/hdl_to_hx8k/on_pi

    Also for the rpi Pico : https://github.com/dan-rodrigues/pico-hx

    I could knock off the 2232 FTDI and have made something like this: https://shop.trenz-electronic.de/en/TEM0009-02-FPGA-USB-programmer-JTAG-for-development-with-Microchip-FPGAs

    Most interestingly, it seems like Arduino Uno could program an FPGA using a library like SPIMemory by Prajwal Bhattaram : https://github.com/Marzogh/SPIMemory/tree/v2.2.0

    Finally, I could make a board like the gameduino that has an API for the Arduino to use to talk to the FPGA which handles fast screen drawing. This would mean everything could be done within the Arduino IDE.

    EDIT* Come to think of it, even if the FTDI adds cost, it would make everything so much easier for a workshop – one piece of software and no extra hardware to program after for the participants. But when I plug it in it says USB device malfunctioned…(I also realized that I think I can forgo the RS232 connections between the FTDI and the FPGA and just connect it to the EEPROM and FLASH.)

    EDIT* The OLIMEX code for Arduino is also not compiling and winIceProgDuino.exe (to program FPGA by sending serial commands to Arduino firmware I suppose) is not opening either.

    EDIT*2 The Arduino sketch compiles but only for MEGA, Leonardo, and Micro so far (no UNO or NANO or MINI) but only after removing the iceprog.cpp file.

    ******************

    Some thoughts on low-level versus high-level programming :

    Something unsatisfying about making something from a pre-digested meta language (fast.ai for instance). Lost the feeling of ownership of the thing you’re making.

    Obviously you can do much more when you stand atop of the shoulders of giants, but you are less connected with the surface of the ground because you are working with abstractions. If something goes wrong, you have no recourse because you are just a customer.
    Low level languages make the architecture of the machine visible by laying it bear. There is agency. Then again, to do something very simple can be hard and require lots of code which provides many opportunities for silly mistakes.
    Yet for workshops it seems good to avoid low level stuff. It’s not impressive, it’s discouraging, and it’s hard to debug.
    *******************
    I have soldered the new board, I love the keys !! But HDMI is still not working.

    Lots of fun could be had rearranging the keys using the same row heights  :

    I wonder if I should just transition to making interfaces directly – I am a designer after all !

    The FPGA4fun.com code is not synthesizing, I think because it requires clock dividing modules that I don’t have.
    I tried this code and it compiles but I don’t see anything on the ‘scope: https://gist.github.com/uXeBoy/0d46e2f1560f73dd573d83e78309bfa0
    This code eventually produced signals on HDMI out, will have to wait to see if it is acceptable HDMI once I have the proper resistor LVDS setup.
    `default_nettype none // disable implicit definitions by Verilog
    //-----------------------------------------------------------------
    // minimalDVID_encoder.vhd : A quick and dirty DVI-D implementation
    //
    // Author: Mike Field <hamster@snap.net.nz>
    //
    // DVI-D uses TMDS as the 'on the wire' protocol, where each 8-bit
    // value is mapped to one or two 10-bit symbols, depending on how
    // many 1s or 0s have been sent. This makes it a DC balanced protocol,
    // as a correctly implemented stream will have (almost) an equal
    // number of 1s and 0s.
    //
    // Because of this implementation quite complex. By restricting the
    // symbols to a subset of eight symbols, all of which having have
    // five ones (and therefore five zeros) this complexity drops away
    // leaving a simple implementation. Combined with a DDR register to
    // send the symbols the complexity is kept very low.
    //-----------------------------------------------------------------
    
    module top(
    clk100, hdmi_p, hdmi_n
    );
    
    input clk100;
    output [3:0] hdmi_p;
    output [3:0] hdmi_n;
    
    // For holding the outward bound TMDS symbols in the slow and fast domain
    reg [9:0] c0_symbol; reg [9:0] c0_high_speed;
    reg [9:0] c1_symbol; reg [9:0] c1_high_speed;
    reg [9:0] c2_symbol; reg [9:0] c2_high_speed;
    reg [9:0] clk_high_speed;
    
    reg [1:0] c2_output_bits;
    reg [1:0] c1_output_bits;
    reg [1:0] c0_output_bits;
    reg [1:0] clk_output_bits;
    
    wire clk_x5;
    reg [2:0] latch_high_speed = 3'b100; // Controlling the transfers into the high speed domain
    
    wire vsync, hsync;
    wire [1:0] syncs; // To glue the HSYNC and VSYNC into the control character
    assign syncs = {vsync, hsync};
    
    // video structure constants
    parameter hpixels = 800; // horizontal pixels per line
    parameter vlines = 525; // vertical lines per frame
    parameter hpulse = 96; // hsync pulse length
    parameter vpulse = 2; // vsync pulse length
    parameter hbp = 144; // end of horizontal back porch (96 + 48)
    parameter hfp = 784; // beginning of horizontal front porch (800 - 16)
    parameter vbp = 35; // end of vertical back porch (2 + 33)
    parameter vfp = 515; // beginning of vertical front porch (525 - 10)
    
    // registers for storing the horizontal & vertical counters
    reg [9:0] vc;
    reg [9:0] hc;
    // generate sync pulses (active high)
    assign vsync = (vc < vpulse);
    assign hsync = (hc < hpulse);
    
    always @(posedge clk_x5) begin
    //-------------------------------------------------------------
    // Now take the 10-bit words and take it into the high-speed
    // clock domain once every five cycles.
    //
    // Then send out two bits every clock cycle using DDR output
    // registers.
    //-------------------------------------------------------------
    c0_output_bits <= c0_high_speed[1:0];
    c1_output_bits <= c1_high_speed[1:0];
    c2_output_bits <= c2_high_speed[1:0];
    clk_output_bits <= clk_high_speed[1:0];
    if (latch_high_speed[2]) begin // pixel clock 25MHz
    c0_high_speed <= c0_symbol;
    c1_high_speed <= c1_symbol;
    c2_high_speed <= c2_symbol;
    clk_high_speed <= 10'b0000011111;
    latch_high_speed <= 3'b000;
    if (hc < hpixels)
    hc <= hc + 1;
    else
    begin
    hc <= 0;
    if (vc < vlines)
    vc <= vc + 1;
    else
    vc <= 0;
    end
    end
    else begin
    c0_high_speed <= {2'b00, c0_high_speed[9:2]};
    c1_high_speed <= {2'b00, c1_high_speed[9:2]};
    c2_high_speed <= {2'b00, c2_high_speed[9:2]};
    clk_high_speed <= {2'b00, clk_high_speed[9:2]};
    latch_high_speed <= latch_high_speed + 1'b1;
    end
    end
    
    always @(*) // display 100% saturation colourbars
    begin
    // first check if we're within vertical active video range
    if (vc >= vbp && vc < vfp)
    begin
    // now display different colours every 80 pixels
    // while we're within the active horizontal range
    // -----------------
    // display white bar
    if (hc >= hbp && hc < (hbp+80))
    begin
    c2_symbol = 10'b1011110000; // red
    c1_symbol = 10'b1011110000; // green
    c0_symbol = 10'b1011110000; // blue
    end
    // display yellow bar
    else if (hc >= (hbp+80) && hc < (hbp+160))
    begin
    c2_symbol = 10'b1011110000; // red
    c1_symbol = 10'b1011110000; // green
    c0_symbol = 10'b0111110000; // blue
    end
    // display cyan bar
    else if (hc >= (hbp+160) && hc < (hbp+240))
    begin
    c2_symbol = 10'b0111110000; // red
    c1_symbol = 10'b1011110000; // green
    c0_symbol = 10'b1011110000; // blue
    end
    // display green bar
    else if (hc >= (hbp+240) && hc < (hbp+320))
    begin
    c2_symbol = 10'b0111110000; // red
    c1_symbol = 10'b1011110000; // green
    c0_symbol = 10'b0111110000; // blue
    end
    // display magenta bar
    else if (hc >= (hbp+320) && hc < (hbp+400))
    begin
    c2_symbol = 10'b1011110000; // red
    c1_symbol = 10'b0111110000; // green
    c0_symbol = 10'b1011110000; // blue
    end
    // display red bar
    else if (hc >= (hbp+400) && hc < (hbp+480))
    begin
    c2_symbol = 10'b1011110000; // red
    c1_symbol = 10'b0111110000; // green
    c0_symbol = 10'b0111110000; // blue
    end
    // display blue bar
    else if (hc >= (hbp+480) && hc < (hbp+560))
    begin
    c2_symbol = 10'b0111110000; // red
    c1_symbol = 10'b0111110000; // green
    c0_symbol = 10'b1011110000; // blue
    end
    // display black bar
    else if (hc >= (hbp+560) && hc < hfp)
    begin
    c2_symbol = 10'b0111110000; // red
    c1_symbol = 10'b0111110000; // green
    c0_symbol = 10'b0111110000; // blue
    end
    // we're outside active horizontal range
    else
    begin
    c2_symbol = 10'b1101010100; // red
    c1_symbol = 10'b1101010100; // green
    //---------------------------------------------
    // Channel 0 carries the blue pixels, and also
    // includes the HSYNC and VSYNCs during
    // the CTL (blanking) periods.
    //---------------------------------------------
    case (syncs)
    2'b00 : c0_symbol = 10'b1101010100;
    2'b01 : c0_symbol = 10'b0010101011;
    2'b10 : c0_symbol = 10'b0101010100;
    default : c0_symbol = 10'b1010101011;
    endcase
    end
    end
    // we're outside active vertical range
    else
    begin
    c2_symbol = 10'b1101010100; // red
    c1_symbol = 10'b1101010100; // green
    //---------------------------------------------
    // Channel 0 carries the blue pixels, and also
    // includes the HSYNC and VSYNCs during
    // the CTL (blanking) periods.
    //---------------------------------------------
    case (syncs)
    2'b00 : c0_symbol = 10'b1101010100;
    2'b01 : c0_symbol = 10'b0010101011;
    2'b10 : c0_symbol = 10'b0101010100;
    default : c0_symbol = 10'b1010101011;
    endcase
    end
    end
    
    // red N
    defparam hdmin2.PIN_TYPE = 6'b010000;
    defparam hdmin2.IO_STANDARD = "SB_LVCMOS";
    SB_IO hdmin2 (
    .PACKAGE_PIN (hdmi_n[2]),
    .CLOCK_ENABLE (1'b1),
    .OUTPUT_CLK (clk_x5),
    .OUTPUT_ENABLE (1'b1),
    .D_OUT_0 (c2_output_bits[1]),
    .D_OUT_1 (c2_output_bits[0])
    );
    
    // red P
    defparam hdmip2.PIN_TYPE = 6'b010000;
    defparam hdmip2.IO_STANDARD = "SB_LVCMOS";
    SB_IO hdmip2 (
    .PACKAGE_PIN (hdmi_p[2]),
    .CLOCK_ENABLE (1'b1),
    .OUTPUT_CLK (clk_x5),
    .OUTPUT_ENABLE (1'b1),
    .D_OUT_0 (c2_output_bits[1]),
    .D_OUT_1 (c2_output_bits[0])
    );
    
    // green N
    defparam hdmin1.PIN_TYPE = 6'b010000;
    defparam hdmin1.IO_STANDARD = "SB_LVCMOS";
    SB_IO hdmin1 (
    .PACKAGE_PIN (hdmi_n[1]),
    .CLOCK_ENABLE (1'b1),
    .OUTPUT_CLK (clk_x5),
    .OUTPUT_ENABLE (1'b1),
    .D_OUT_0 (c1_output_bits[1]),
    .D_OUT_1 (c1_output_bits[0])
    );
    
    // green P
    defparam hdmip1.PIN_TYPE = 6'b010000;
    defparam hdmip1.IO_STANDARD = "SB_LVCMOS";
    SB_IO hdmip1 (
    .PACKAGE_PIN (hdmi_p[1]),
    .CLOCK_ENABLE (1'b1),
    .OUTPUT_CLK (clk_x5),
    .OUTPUT_ENABLE (1'b1),
    .D_OUT_0 (c1_output_bits[1]),
    .D_OUT_1 (c1_output_bits[0])
    );
    
    
    // blue N
    defparam hdmin0.PIN_TYPE = 6'b010000;
    defparam hdmin0.IO_STANDARD = "SB_LVCMOS";
    SB_IO hdmin0 (
    .PACKAGE_PIN (hdmi_n[0]),
    .CLOCK_ENABLE (1'b1),
    .OUTPUT_CLK (clk_x5),
    .OUTPUT_ENABLE (1'b1),
    .D_OUT_0 (c0_output_bits[1]),
    .D_OUT_1 (c0_output_bits[0])
    );
    
    // blue P
    defparam hdmip0.PIN_TYPE = 6'b010000;
    defparam hdmip0.IO_STANDARD = "SB_LVCMOS";
    SB_IO hdmip0 (
    .PACKAGE_PIN (hdmi_p[0]),
    .CLOCK_ENABLE (1'b1),
    .OUTPUT_CLK (clk_x5),
    .OUTPUT_ENABLE (1'b1),
    .D_OUT_0 (c0_output_bits[1]),
    .D_OUT_1 (c0_output_bits[0])
    );
    
    // clock N
    defparam hdmin3.PIN_TYPE = 6'b010000;
    defparam hdmin3.IO_STANDARD = "SB_LVCMOS";
    SB_IO hdmin3 (
    .PACKAGE_PIN (hdmi_n[3]),
    .CLOCK_ENABLE (1'b1),
    .OUTPUT_CLK (clk_x5),
    .OUTPUT_ENABLE (1'b1),
    .D_OUT_0 (clk_output_bits[1]),
    .D_OUT_1 (clk_output_bits[0])
    );
    
    
    // clock P
    defparam hdmip3.PIN_TYPE = 6'b010000;
    defparam hdmip3.IO_STANDARD = "SB_LVCMOS";
    SB_IO hdmip3 (
    .PACKAGE_PIN (hdmi_p[3]),
    .CLOCK_ENABLE (1'b1),
    .OUTPUT_CLK (clk_x5),
    .OUTPUT_ENABLE (1'b1),
    .D_OUT_0 (clk_output_bits[1]),
    .D_OUT_1 (clk_output_bits[0])
    );
    // D_OUT_0 and D_OUT_1 swapped?
    // https://github.com/YosysHQ/yosys/issues/330
    
    
    SB_PLL40_PAD #(
    .FEEDBACK_PATH ("SIMPLE"),
    .DIVR (4'b0000),
    .DIVF (7'b0001001),
    .DIVQ (3'b011),
    .FILTER_RANGE (3'b101)
    ) uut (
    .RESETB (1'b1),
    .BYPASS (1'b0),
    .PACKAGEPIN (clk100),
    .PLLOUTGLOBAL (clk_x5) // DVI clock 125MHz
    );
    
    endmodule
    
    I learned a bit about how HDMI is encoded to reduce strings of 1s or Os and how transitions are minimized. I currently suspect that the PLL is not working but I’m not sure why yet. I will turn on the PLL locked LED feature to check and then mess with other parameters (see https://zipcpu.com/blog/2017/09/14/even-i-get-stuck.html) if it isn’t working.
    *EDIT 1 Apparently IceCube2 doesn’t want me to attach the CLK to any pin other than 49 (GBIN5) or 129 (GBIN0) ! This explains why nothing is happening, the clock wasn’t even entering the FPGA.
    *EDIT 2 I connected the clock pin to 49, and made the original connection to pin 64 high Z, along with the accidental connection to pin 48 nextdoor, and now I see signals being output to the HDMI. (It’s too tight to try and solder in resistors to test the proper LVDS simulation as described in the Using Differential I/O (LVDS, Sub-LVDS) in iCE40 LP/HX Devices annex.) I used the pin constraints editor in IceCube and it added some info to the pcf which may have helped get things working ? :
    set_io hdmi_p[0] 139 -io_std SB_LVCMOS
    set_io hdmi_p[2] 144 -io_std SB_LVCMOS
    set_io hdmi_p[1] 142 -io_std SB_LVCMOS
    set_io hdmi_p[3] 137 -io_std SB_LVCMOS
    set_io clk100 49
    
    For the next version, I think I need to include resistors to simulate the LVDS signals and I should connect the clock at one of the dedicated input pins which seem to be optimized for this.
    Just realizing now that all the code I have been looking at involves using a dedicated chip (the TFP410 @ 8 euros) to convert the FPGA signals into. From the blogs it also seems like this solution works for some TVs but not all, and is better for monitors. Perhaps I should include a VGA + HDMI in case this is just too finicky. Looking at the OLIMEX VGA PMOD board, it looks like I only need a few resistors to get VGA working : https://www.olimex.com/Products/FPGA/iCE40/iCE40-IO/open-source-hardware
    I am looking for more ressources on DVI with Ice40 FPGAs and found these :
    • https://projectf.io/posts/fpga-graphics/
    • https://github.com/lawrie/hdmi_examples/tree/master
    The fact that the code above (before my modifications at least) is being used on another ice40 makes me think it should work in the end.
    **********
     

    Technische UniversitĂ€t MĂŒnchen Lecture

    I have a month to work on a 45 minute lecture on my work at the Technische UniversitĂ€t MĂŒnchen. I will also be doing a lecture at TU Darmstadt in November. I would like to use this opportunity to try to bring my video experiments into focus and incorporate it into my previous time-lapse projects.

    This could take the form of a video series of me playing the prepared video buffer, possibly with explanations about what is causing what effect and demonstrative images / videos ? It could be contrasted with a “typical” workflow using the constraints of a software platform like photoshop? I could prepare this a similarly focused investigation of how the prepared piano altered sound, how Sonia Sheridan altered the photocopier, Paul Schafer made custom concrete music machines, etc.

    EDIT* : I had a try !

    • It’s kind of long and I also need to get a better top view.
    • Adding text to describe what’s happening ?
    • I also see that when I’m turning knobs the device is kind of hidden. I haven’t really designed the interface to be playable and to look good and be legible while being played.
    • Looked into some other examples of video synth top down videos :

    This is making me think more about the physical presence of my devices, and how I could incorporate more mechanical parts – instead of purely making electronics. I may have to play the game a bit more, make things that look like what they do and help people understand the associations I’m trying to make.

    I could have micrometer heads for the potentiometers :

    I could have fiber optic cables too :

    Fiber Optic Cable Connectors & Assemblies | Clearfield

    I think if I every try to make a product though I would need to team up with someone who has skills I don’t.

    ***

    Why make hardware ?

    • it can be analog and digital
    • it’s faster at doing things with video than software
    • it can be custom
    • it has a live-playable interface

    ***

    What effects am I creating ? (check out Premiere to see what kinds of effects exist).

    • Recording and playing things back at different speeds (video transposition), assigning to different color channels
    • desynchronizing recordings with the screen sync so that they jump around
    • recording videos side by side in memory so that they bleed over one another.
    • Video collage and montage composer (video sampling, video looping), video plastifier, Ă©tude II, micro-montage, noise research, play, do and see, polyvideo layering, defamiliarizing of the image + reflecting the mediascape we inhabit, video as “palpable”, “nontheoretical”, and “experiential” (quotes from musique concrete wiki).
    • The structure of the videos is based on the indexicality of the medium (the SRAM and how it stores). So the recording technique is also the synthesis technique.

      Struggling to represent the painterliness of the raster videos without showing them as a video. It is completely different from my experiments with lines and triangles, and is less intuitive for me. An attempt at a kind of chronogram of a video :

      It gives some idea of the range of images I guess?

      Here are some notes I took about a year ago after visiting a painting expo that relate to my painterly video experiments :

      • Layering
      • Contour
      • Surface
      • Saturation
      • Flow vs. Choppiness
      • Roughness, relief 
      • Edges versus centers
      • Movement vs stasis 
      • Enriching of detail
      • Abstracting, cosmic making
      • Fine lines versus coarse
      • Exposure 
      • Color fields
      • Texture
      • Deep friedness
      • Films of cows, ocean. Stills of still life? Flowers, birds, drapes folding, mold, fruit, bones
      • Color mixing vs melting vs meeting
      • Paint viscosity (runny vs clotted)
      • Direction of brush strokes 
      • Contour
      • Focus direction in canvas
      • Translucent flesh, shine vs glow from interior, waxiness 
      • Graininess 
      • Composition, color pairings and form
      • Foreground displaced to background vice versa 
      • Meeting pattern planes 
      • Lighting and shadow
      • Illusion of depth
      • Cloudiness 
      • Turbulence

      Check out this “glitch” video artist Jacques Perconte that Marc shared with me : https://www.youtube.com/watch?v=8_Xhu9Vx5XM

      He works, since the 1990s, with compression and achieves a painterly, impressionistic effects and exposes them on immense projection surfaces.

      Check out also Tauba Auerbach’s work :

      Tauba Auerbach

      Tauba Auerbach at the ICA | Inside LDN

      Jack Whitten :

      Jack Whitten: Artwork Survey: 1970s | Art21

      *************

      Some quotes from Art21 series :

      James Turrel – what you are perceiving is perception itself. We don’t receive the world around us we create it.

      Jeff Wall – Art gives you an experience that alters something, it doesn’t tell you or convince you.

      Jeff Wall – When I started photography there were potential energies in the medium that weren’t being realized.

      Roland Barthes – The punctum points to those features of a photograph that seem to produce or convey a meaning without invoking any recognizable symbolic system.

      Olafur Eliasson – Art provokes a negotiation : why I am seeing this the way that I am seeing it, what does looking mean? Instead of questioning the object you are questioning yourself. Art offers the opportunity for self-evaluation.

      Tauba Auerbach – I want to learn things all the time, I want to understand the patterns behind things. I experience science through craft. With craft I try to cultivate sensitivity in a practiced, purposeful way. If you work with marbling you know just as much about viscosity and flow than a scientist, through your fingertips in a different way.

      Tauba Auerbach – Ideally I want to make an image that has a tiny effect on all the future images that you see.

      Tauba Auerbach – The pursuit of the sweet spot, cultivate the place of boundaries, limits of fraying, not hard edges.

      Cindy Sherman – I don’t know what I’m looking for until I see it.

      Richard Serra – Artists invent strategies, tools, techniques, that allow themselves to see in a way they haven’t seen before to extend their vision beyond the standardized classic reflex actions. These help us to see inside what we’re doing so we don’t get into a lock step notion of how to do what you do.

      Louise Despont – If you’re always making work for someone, and not for yourself, maybe you don’t let yourself make the mistakes that are necessary.

      Louise Despont – Each drawing is a series of tiny discoveries, it reveals/unfolds the drawing from total control. I own at most 1/4 of the drawing. The rest is something else, this is what’s exciting.

      Louise Despont – It’s best explained in the drawings, words are clumsy to describe something like the concrete feeling of spirituality.

      Liz Magor – My Studio is a space to reconcile dissonance, no one knows I’m here. When I’m not in my studio I want to be in my studio working. My tools are rudimentary. I’m here for pleasure but it’s not fun. Everyone should have a studio for mental health. I can filter out the noise and see the ever present under the radar stuff.

      Liz Magor – I’m not an animist but objects have stuff in them that comes out. I try to resurrect these objects from the netherworld.

      Liz Magor – The slowness of the material process matches the slowness of my thinking process.

      Liz Magor – I’m creating an experience for looking.

      Liz Magor – I give myself my own program, I give myself my own assignments. And art is the choices I make.

      Liz Magor – Maintaining the conditions for this production, which is not very logical, uncalled for. No one is asking me to do this, I’m barely asking me to do this. To do this I have to overlook my making with the journey of the things into the world.

      Liz Magor – After the casting I unwrap it like a little gift, there are surprises.

      Elliott Hundley – This photoshoot is so elaborate but not because I want a certain effect, because I want to not control the effects, and have a layer of unexpected results. In relinquishing control, the piece gives me something back I didn’t expect.

      Jack Whitten – I’m not a narrative painter.

      Jack Whitten – I built a device to move large amounts of acrylic paint in one gesture.

      Katherina Gross – Painting is not linear. The synchronicity in painting is compelling for your thought process. I’m trying to grasp some of those fast thoughts that are moving through my brain.

      *************

      Reading about the history of video synthesis.

      From https://museumzero.blogspot.com/2013/12/its-all-baseball-nam-june-paik-starts.html)

      Nam June Paik sees Taoist energy in working with the flow of TV video :

      “To receive simultaneously the parallel flows of many independent movements is, as Paik pointed out at the time, a classical Taoist way of meditating: by becoming aware of everything going on in the present, you discover eternity right now.” 

      “I love Chinese history, surprise, nonlinearity.  You know what judo means?  A way to be soft.  You let other guy do all the work.  I think in some Oriental way.  In TV I try not to be boss, to stay as small as possible.  So that seems to work. “ 

      “So then when I started TV, the best decision I made in life is not really to go into TV, but to do work inside TV.”

      “Imagine everything that exists is flowing, like the tao, in a perpetual motion, with endless waves, like the ocean.  We come from it; we go back to it.  Whatever surges forward falls back, so Lao-tse, who wrote the Tao Te Ching (On the Nature of the Way), urges us not to try too hard.  Relax; be like a baby; follow whatever path presents itself.  That is the way. ”

      Not striving to fit yourself to some preconceived ideal, like a Buddhist or a Confucian; simply being, following breath wherever it blows.  In this sense, the television signal is like the tao; endlessly variable, continually reversing itself, dying, being reborn, it is never idle, yet it is so vast and perpetual that it often seems calm as the sea.

      Beginning with whatever live programs came along, distorting them, then recombining his distortions like waves on the ocean surface, Paik created an indeterminate and endless show for the Galerie Parnass, in Wuppertal, Germany, in 1963.  

      From Scanimate: The Origins of Computer Motion Graphics :

      • This is about the history of television, these were the first ways to put text and make graphics on screen (Media Archaeology!). Nowadays visuals are gratuitous. What did we lose in the transition to digital ? The imperfections, the proximity to the functioning.
      • Had a role in music videos, and news segments, so was part of culture.
      • “Blooming” is the term for the glowing edges in CRT Scanimate.
      • It’s real life artefacts. It’s like exploding scale models instead of GCI.
      • They made cookbooks with the recipes of different effects that created while working with clients.

      From https://wearethemutants.com/2018/01/09/a-sloppy-machine-like-me-the-history-of-video-synthesizers/

      Like its close temporal and conceptual counterpart, the audio synthesizer, the video synthesizer was created iteratively by academics, artists, and tinkerers, then eagerly snatched up by the world’s biggest media producers once prototypes had proved their power and versatility.

      • Started with experimental musicians like John Cage and la musique concrĂšte.
      • Early pirate TV station in NYC.
      • Amiga supplants the Scanimate and analog synths.
      • The 1967 Portapak release and it’s importance for activism and experimental art.
      • Video comes from the root video of Latin video (“I see”).
      • There is a relationship between images and waves  :

      https://upload.wikimedia.org/wikipedia/commons/6/61/P-type-chirplets-for-image-processing.png

      CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=641492

      This is so hard for me to understand but this somehow relates to chirping also :

      Published in IEEE International Conference on Acoustics, Speech, and Signal Processing 1992

      Time-frequency perspectives: the ‘chirplet’ transform

      Steve MannS. Haykin

      From article about DCT for image compression :

      undefined

      By Drummyfish – Own work, CC0, https://commons.wikimedia.org/w/index.php?curid=77608151

      More cool matrix math image modifications here : https://en.wikipedia.org/wiki/Digital_image_processing

      Also this website which describes it all visually ! https://setosa.io/ev/image-kernels/

      From Video Art : An Anthology :

        • The synthesizer let’s you see things that exist only in the mind’s eye.
        • visual ingredients
        • video synthesizers churn out…images based on their own electronic structure.
        • We make the image with our eyes and brain. It’s psycho-visual
        • video as concretized imagination.
        • video is surreal, the images are ephemeral products of micro electronic pulses.
        • “electronic imagery”
        • video is a medium which works with time

      Au commencement était le bruit, la poésie électronique de Steina et Woody Vasulka | sonore visuel

      The Vasulkas

      *************

      Here is an attempt to describe what could be a model of a potential “practice” :

      *EDIT* This should include me blogging ! Maybe add a RESEARCH and/or DOCUMENTATION phase ?

      *******

      Check out this pyramid of types of work :

      Bloom's revised taxonomy organized as a pyramid of learning levels with explanations of each

      I feel like my project is about analysing (and curating), I’m not sure if I take a real position.

      *******

      Check out this amazing NIME article called The Concentric Sampler: A musical instrument from a repurposed floppy disk drive by Timothy Tate about “the redundancy and physicality of magnetic recording media” which utilizes “time-based granular synthesis” and lo-fi:

      https://nime.pubpub.org/pub/uh76shf0/release/1

      Some quotes :

      • Physical media offer an opportunity to “foreground the physical medium as a tool for musical expression.”
      • “The deterioration of old magnetic tape as it is looped, defining a … musical structure.” The “failure of the medium is in focus, rather than the mechanism.”
      • “as soon as something’s on tape, it becomes a substance which is malleable and mutable and cuttable and reversible in ways that discs aren’t.”
      • “This study emphasises working within a medium’s limitation, rather than prescribing a compositional framework or sonic agenda upon it”
      • Motivation to “foreground musical and technical possibilities…and generative sonic potentials…and novel, unique expressive and
      • compositional possibilities”…to be “discoveredexplored”
      • The device is a “performable instrument and a generative sonic tool”
      • “Rather than focusing on the authenticity of the sound reproduction, the Concentric Sampler draws focus to the byproducts and the resultant indexicality and generative sonic possibilities of the floppy disk as a medium.”
      • “the term ‘musical expression’ here places value on the ability to shape and define a musical grammar from the indexicality of themedium and mechanism.”
      • subverting traditional modes ofexpression
      • “Each section is accompanied by a demonstrative video” !!!
      • The live playable instrument can “achieve the dissociation of pitch and time
      • “imperfections in … reproduction”
      • “possibilities within a framework of … making”

      Now following up on some of the references from this article:

      • You can think of an instrument as a framework that has a predisposed range (affordances). Our tools provide a certain range of suggested usages. Some things are easier and some things harder to do with an instrument, this is the instrument’s spectrum. If you stay within those ranges, you accept the silent grain of the instrument. If you make an unusual tool then, do you risk finding yourself in an unusual affordance ? (J. Mooney) Could it be possible to make videos subtractively, instead of additively ?
      • From New Media Reader : The different between representation and simulation. P.18″Digital media process the physical properties of the input data, light and sound waves, are not converted into another object but into numbers; that is, into abstract symlbols rather than analogous objects and physical surfaces. Hence, media processes are brought into the symbolic realm of math rather than physics or chemistry. Once coded numerically, the input data in a digital media production can immediately be subjected to the math processes of addition, subtraction, multiplication and division…” AND compressed AND manipulated more easily than analogue forms because they are more mutable than objects. Also easy access and quick movement of the data of an enormous mass of data. This causes the materiality of the world around us to become unsteady…The televisual
      • Because everything else is also digitized, there is a “convergence of previously discreet media forms, now a new fluid area of media decentralized production and consumption. Remediation, Multilinearity.
      • Hand-made videos. Exploring the boundary between hand tools and large-scale machines which is a distinction Marx makes P.91.

      Check out these Bauhaus era artist’s work with the audio band in video :

      Paul Schaeffer (coiner of the “club d’essai“) designed specific tools like the morphophone and phonogĂšne for modifying audio for musique concrete :

      *******

      Watching ENSCI diploma presentations I’ve thought about how nice the sequence is : first you write something that explores a topic and cites thinkers on the subject, and then you work on a design project that relates to this somehow. Also looking back at some videos, there is already a lot of content I have produced that I could try to learn from ! Like that Amsterdam-based artist told me, I could also focus on using my tools.

      I am also doing a synth workshop in late September at Villette Makerz but I’m not sure if I can connect to that or not here. *EDIT* an FPGA board that generates patterns based on audio input is a GO !*

      I also want to make a next FPGA board which will be a software reconfigurable device so that I can move to verilog for the summer instead of making a new board for every experiment. Not sure if this could also take the form of a simple video synth for Villette Makerz or at least a simplified version perhaps.

      *******

      Some quick looking in to GPUs :

      GPUs are all about direct memory access (DMA) not mediated through the CPU. A thought about the FPGA board – perhaps I should first have Arduino mess with the clock while playing back / recording something on the 16MB board (but I’m limited to the number of pins for address and I/O – it would essentially be a counter that could change in frequency on the fly)? Having memory connected to the screen (a screen buffer) and modifying it is the fundamental computer display setup. From 1951 a memory pattern on CRT :

      It would be cool to experiment with sprites and copying parts of memory from one bank to another too like a blitter https://en.wikipedia.org/wiki/Blitter .

      It looks like what makes shaders cool is that they are programmable and have their own code languages now. Before shaders there were hardware rendering pipelines called fixed-function. Different units would be responsible for specific functions. It seems like these units would take in vertex data then output pixel colors.

      I looked in to how to do matrix multiplication in hardware. It actually seems to be more natural as an analog circuit with resistor arrays. It can also be done by multiplying two 2-bit binary numbers using this kind of logic setup :

      **********

      I am becoming more and more curious about the difference from having a screen buffer that is written to during the blanking period and having a massive bank of memory that can be recorded to like in the 128Kbit. Check out these articles about how writing and reading to video memory is dealt with in different systems :

      https://en.wikipedia.org/wiki/Tiled_rendering

      https://en.wikipedia.org/wiki/Multiple_buffering

      https://en.wikipedia.org/wiki/Vertical_blank_interrupt ,quoted from : 

      During the vertical blanking interval, the driver orders the video card to either rapidly copy the off-screen graphics area into the active display area (double buffering), or treat both memory areas as displayable, and simply switch back and forth between them (page flipping). [The two buffers are called the front and the back buffer] Some graphics systems let the software perform its memory accesses so that they stay at the same time point relative to the display hardware’s refresh cycle, known as raster interrupt or racing the beam.” [i.e. you can also draw things during the horizontal blanking interval]

      **********

      The Real-Time Corrupter is fascinating https://redscientist.com/rtc . The kinds of memory modifications it allows for are fascinating and far more dynamic than static, text-based find-and-replace experiments I’ve done in workshops. Looking at this video I learned some cool stuff (https://www.youtube.com/watch?v=n9HS6zftuSk&list=PLItZ3jvJKD7rnoxmqJJ0B5E1B9_WW9L5E&index=2). For instance, copying values from one address (in video RAM, scrolling backdrops memory space a.k.a. “nametables”, NES RAM, ROM etc.) and then reapplying them to another address every frame (called piping) or just one time, the ability to isolate specific effects with the sanitize function. It can generate noise between certain values, or shift values up or down on (called tilting), listen to a value and then reapply it after a fixed number of frames, freezing the current value somewhere for future frames, replacing values intelligently with values in certain sets (for 3D glitching). It’s like performing brain surgery while the patient is fully conscious and telling a story. All of these memory transformations could be applied with the FPGA board !

      **********

      In a similar spirit, this game called Code War involves creating a program that competes with others to write to all of the memory space. There are competing strategies (quoted from https://corewar-docs.readthedocs.io/en/latest/corewar/strategies/) for warriors :

      Rock - a warrior which rapidly bombs the core with dat instructions
      Paper - a warrior which replicates, creating multiple, parallel copies
      Scissors - a warrior which scans the core looking for other warriors

      The battle is visualized in a memory grid (https://corewar-docs.readthedocs.io/en/latest/corewar/visualisation/)

      https://upload.wikimedia.org/wikipedia/commons/c/c2/Core_War_PMars_Screenshot.png

      You can simulate and battle warrior code here : https://crypto.stanford.edu/~blynn/play/redcode.html

      **********

      Visualizing memory access in time. From https://bling.kapsi.fi/blog/x86-memory-access-visualization.html:

      *********

      Some thoughts on HCI from people at work :

      it’s research if it follows scientific method and has possible applications.

      Find your peers, try to publish in their journals.

      The idea of publishing is to get feedback from your peers.

      If you make a pedagogical tool, then you could test how effective it is at helping people learn.

      Based on this conversation, I thought about how I don’t necessarily want to promote engineering education and that I always want to be on the design/art side of things. I also have learned that I find doing something I already know how to do less exciting, and so making simple kits or small series of artworks that are guaranteed to work for days on end, is not always super rewarding for me intellectually. This leads me to the current conclusion : I want to teach and then do a kind of artistic research on the side. I should then keep building my teaching career and try to get expos of my work. I am still trying to figure out how exactly my artistic research should be communicated (through articles in design magazines, through conferences with expos connected to them?).

      **********

      I am preparing a solar workshop at Villette Makerz based on the simple solar engine with optimized SMD components. The idea is an art bot that will draw, paint, in the sun. I am working on testing the various combinations of solar panels, capacitors and voltage supervisors.

      We are also making a version 2 of the video synth modules which are all Eurorack compatible in terms of dimensions, use 3.5mm audio jacks, the eurorack power supply. The idea is that the modules be both manual and automatable for the purpose of demos and to be didactic for students learning about analog electronics.

       

      Marc is doing a great job reimagining this project – he is good at compromising and imposing the vision of the final thing on each step of the construction. I am, in contrast, driven astray I think by my fascination by what “the machine itself wants to express”…

      ********

      Finally getting around to testing the Arduino-controllable analog switch to activate record or READ mode on the SRAM 16MB board. The idea is to test taking a recorded video and then doing some bit manipulations with it and saving it back to the memory. Predictably though, I’m having issues just writing anything to the thing…

      I/O pins on Arduino 0-7
      CLK on Arduino 12
      REC on Arduino 13 connected to analog switch connecting the WR pin on SRAM to either VCC or !CLK
      
      unsigned long memory; //total number of 8bit words on the 16Mb SRAM = 2048000
      
      const byte IO_0 = 7; 
      const byte IO_1 = 6; 
      const byte IO_2 = 5; 
      const byte IO_3 = 4; 
      const byte IO_4 = 3; 
      const byte IO_5 = 2; 
      const byte IO_6 = 1; 
      const byte IO_7 = 0; 
      
      void setup() {
      //Serial.begin(115200);
      pinMode(13, OUTPUT);
      pinMode(12, OUTPUT);
      
      pinMode(IO_0, OUTPUT);
      pinMode(IO_1, OUTPUT);
      pinMode(IO_2, OUTPUT);
      pinMode(IO_3, OUTPUT);
      pinMode(IO_4, OUTPUT);
      pinMode(IO_5, OUTPUT);
      pinMode(IO_6, OUTPUT);
      pinMode(IO_7, OUTPUT);
      
      //WRITE
      while(memory<= 2048000){
      memory++;
      
      // if (memory%10000==0){
      // Serial.println(memory);
      // }
      
      if (memory%5==0){
      PORTD = B11110000; // the IO pins. simple pattern test.
      
      }
      else{
      PORTD = B00001111;// the IO pins. simple pattern test.
      }
      //WRITE MODE
      PORTB = B11101111; // PIN 12 ARDUINO CLK goes LOW/HIGH
      PORTB = B11111111; // PIN 13 ARDUINO WR STAYS HIGH
      
      }
      // Serial.println("finished writing");
      }
      
      void loop() {
      pinMode(IO_0, INPUT);
      pinMode(IO_1, INPUT);
      pinMode(IO_2, INPUT);
      pinMode(IO_3, INPUT);
      pinMode(IO_4, INPUT);
      pinMode(IO_5, INPUT);
      pinMode(IO_6, INPUT);
      pinMode(IO_7, INPUT);
      
      digitalWrite(IO_0, LOW);
      digitalWrite(IO_1, LOW);
      digitalWrite(IO_2, LOW);
      digitalWrite(IO_3, LOW);
      digitalWrite(IO_4, LOW);
      digitalWrite(IO_5, LOW);
      digitalWrite(IO_6, LOW);
      digitalWrite(IO_7, LOW);
      
      //PIN 13 REC IN LOW READ MODE
      PORTB = B11011111; // PIN 12 ARDUINO CLK goes LOW/HIGH
      PORTB = B11001111; // PIN 12 ARDUINO CLK goes LOW/HIGH
      }
      

      Not working…

      unsigned long memory; //total number of 8bit words = 2048000
      byte cell; // store the word at this address
      
      void setup() {
      
      //PD0 - PD7 are IO
      pinMode(13, OUTPUT); // REC - PB5
      pinMode(12, OUTPUT);// CLK - PB4
      
       while(memory<= 2048000){
          memory++;
      //READ
              DDRD = B00000000; // all IOs in INPUT
              PORTD = B00000000; // no pull-ups
      
              PORTB = B11011111; // WR stays LOW + CLK HIGH
              delayMicroseconds(10);
              cell = PIND; // read the cell at this memory address and store it in the variable cell
              delayMicroseconds(10);
              PORTB = B11001111; // WR stays LOW + CLK LOW
              delayMicroseconds(10);
      
      //WRITE
             
              DDRD = B11111111; // all IOs in OUTPUT
      
              PORTD = ~cell; // write  a transformed cell back to memory
              PORTB = B11111111; // WR stays HIGH + CLK HIGH
              delayMicroseconds(10);
              PORTB = B11101111; // WR stays HIGH + CLK goes LOW
              delayMicroseconds(10);
        }
      }
      
      
      void loop() {
      //READ MODE TO SEE WHAT WE HAVE IN MEMORY
              PORTB = B11011111; // WR stays LOW + CLK HIGH
              delay(500);
              PORTB = B11001111; //  WR stays LOW +  CLK LOW
              delay(500);
      }
      Not working either...

       

      ****

      I reread the manual for the SRAM and found that in the writing mode where OE is held LOW, you need to not force the SRAM IO pins for a duration of 10ns after WE goes low or else the “previously read data will drive the IO buffer”. So I need to put the IO pins into HIZ for this period of time.

      I also found that the SRAM needs a startup time of 150ns after the voltage has settled. This needs to be added in the setup.

      Looking at the 74HC590 datasheet, I am realizing that there is a significant propogation delay for the CLK to convert into a new address on the ADD pins. I can’t figure out the exact delay but the highest delays I see for any step in the pipeline are in the 100s of ns. To be conservative, after the CLK goes HIGH and WR LOW, I’m adding a big delay so that the address lines can catch up.

      *EDIT* I forgot, the SRAM is 3.3V logic level so I need a level shifter or I’ll damage it !

      However, even with that, still no dice ! Very curious…

      *****

      I just tried some different op amps with the Serpentin 128KB board.

      Recorded some different speeds in the same recording which was cool.

      Here are the things I’ve played with :

      1. Recording versus playing
      2. Clock speeds
      3. Amplifying input / output and threshold
      4. Count resetting, memory chunk selection
      5. The memory size
      6. The bit width
      7. combining several recordings

      What I want to play with :

      1. editing tiny parts of memory, possibly based on the contents of the memory
      2. moving through the memory non-linearly, and at different speeds/accelerations
      3. copying parts of one memory to another  

        ********

      FPGA synth

      Heading towards a more reliable, deployable and software-leaning approach (but not so much about automated choreography as with previous atmega boards as augmented live playable machine for manual performances) to working with video now.

      I am also trying to be a bit more strategic and attempt to think ahead a little bit beyond the one board one experiment situation. It takes a long time to trouble shoot a single board and learn all the lessons from it, I have to give each board the time it deserves and I need to be perhaps less productive and more thorough.

      I am also coming to the awareness of what is my scope with this next board :

      • I won’t be doing challenging engineering things (like implementing different ways of programming the same FPGA, interfacing with differential pair protocols like HDMI) that have no impact on the images and take loads of time to do.
      • These are boards for experimenting and live playing, so they also need to have controls on the board.
      • I also need to think about safety, avoiding the possibility of easily making short circuits and damaging the board.
      • I’d also like to move back to color, and away from the intense limits of exclusively 1bit resolution.
      • I want to keep removing superfluous cables and adapters too, this one will have only a VGA out.

      I made a map of my prototypes so far for this project :

      It’s been around two years I’ve been working on this !

      After talking with Zach at work, his idea was to show not just the screen but also me turning knobs etc. Here’s what this could look like :

      Or,

      …or,

       

      It would be nice to have a computer interfaced oscilloscope to record the signals.

      *****

      The most plug and play option would appear to already exist : a tiny raspberry pi zero can already run Processing scripts and control small screens https://learn.adafruit.com/processing-on-the-raspberry-pi-and-pitft/processing !

      Here’s a good intro to making simple patterns with processing : https://processing.org/examples/

      We would be more in the zone of software video synth : https://learn.adafruit.com/feather-rp2040-dvi-video-synth

      Also seem to be companies making just this kind of thing : https://store.excamera.com/

      Arduino talks to the FPGA by SPI as if it were a RAM space. https://excamera.com/files/gameduino/synth/doc/gen/poster.pdf

      Design / Engineer friend Paolo Salvagione pointed me to Configurable mixed-signal ICs. It appears to be like an FPGA but for mixed analog and digital circuitry and is configured in design software.

      There is also the world of ASICs and the google open-source silicon project https://developers.google.com/silicon

      *************

      My project was originally about slowing down computer processes and representing them in space. Now I just seem to order things on Amazon and design increasing numbers of PCBs. It seems that I have so little time to do the art in the end because of how much investment the technical stuff requires. How could I get back to my original project here ?

      My project also had a collection of related techniques :

      • Try to free machines from their corseted, factory settings and reveal their full range of expression that would otherwise just exist in a parallel unseen dimension
      • Try to show our files from the perspective of / through the eyes of the machines that are processing them.
      • Curate series of abstract formal compositions which emerge from figurative, architecturally-themed or culturally iconic ones.
      • Try to describe the behaviour / idiosyncracies of algorithms and make them tangible
      • Isolate specific moments of machine-to-machine interface in a larger system
      • Get one’s hands inside the black box, and make prepared machines which expose their parameters
      • Try to rebuild electronic systems based on help from the DIY internet and then hope to stumble on something unintentional
      • All the while emphasize the materiality of technology
      • Trying to go super low-level and avoiding abstract computer “visualizations”
      • Exploring the link between visual chaos and harmony, that sweet spot of medium entropy.
      • Riffing off of the music synthesizer movement of knobs and playful electronics interfaces and its anti-theory vibe
      • Exploring the surreal, bizarre space of the computational unconscious
      • Do “artistic research” projects that are educational, at least for me
      • play with form versus content

      I wonder if the pixel based screen is not really appropriate for my methodology. It’s the opposite of over-looked and black boxed. It’s an obsession for an entire culture. It also does a pretty good job of “representing” what happens inside the computer already. It doesn’t really need my help !

      ********

      I also need to do a debrief on this leg of the video synth project. What have I learned ?

      Technical stuff :

          • How to make and debug PCBs
          • To work with video + SRAM with counters as well as some op amp circuits. The difference between digital and analog in the video context.
          • To work with the VGA protocols, about resolution and brightness of the image.
          • I learned about oscillation, the difference between KHz and MHz in the context of video and what sampling is.

      Stuff about media representation

          • some aspects of the nature of visual memory, how some of our sensory apparatus work at different speeds
          • the curious experience of “searching” for an image (like when messing with ADC knobs and CLK speeds).
          • what is required to identify / recognize and image or scene, how much resolution and shape
          • Deconstructing the illusion of television by interacting with its materiality and mutability
          • Repeating historical art explorations with television (see Sans Soleil – Chris Marker)
          • synchronizing the data with the frame of the image is a key part of the illusion of video. If you mess with this suddenly the video frame becomes a malleable object. If it is desynchronized, the image is out of frame and will jump around with the SRAM recording. If you change the speed of recording or of playback you can zoom.
          • Layering of different images in a palimpsest can create textures from them.
          • I’ve made some nice abstract pattern discoveries through knob twisting.
          • Exploring the gap between legible figurative image and abstract patterns, contours, fields,
          • the texture and grain of data at various scales
          • the connection between video and abstract field painting

      What does it mean to be trying to make super simple hardware video filter in the age of AI generated video and images ? How is this activity relevant ? I feel like I’m looking for low hanging fruit here but I’m not sure there is any left. Also, the time it takes to make a single experiment in hardware is astronomical compared to the software option…

      I think the project started off about the screen itself, how to send signals and display them. At some point it became clear that the screen just displays data stored in memory.

      In this spirit, I could try to represent memory access patterns : https://en.wikipedia.org/wiki/Memory_access_pattern Or the patterns that memory is refreshed in : https://en.wikipedia.org/wiki/Memory_refresh

      http://www.overbyte.com.au/misc/Lesson3/CacheFun.html

      I could also sample images and then modify them algorithmically? But it kind of ends up looking like simple Photoshop filters. It would have to be modified in some way based on the way the image is stored in the memory ?

      Check out this image stored in DDR ram decaying over time from J. Alex Halderman’s paper : https://jhalderm.com/pub/papers/coldboot-sec08.pdf

      Also it seems like different DDR has different decay rates (from A Trustworthy Key Generation Prototype Based on DDR3 PUF for Wireless Sensor Networks https://www.researchgate.net/figure/DRAM-cells-decay-feature-with-power-switch-interval-time-of-120-s-a-DDR3-device-1-b_fig3_263586301):

       

      For comparison, check out the same Mona Lisa image sent through the air and damaged by the earth’s atmosphere :

      undefined

      ********

      I’ve never thought of this before but I guess I could generate a simple arduino code, and then take the .hex file and glitch it with any of the glitching techniques I’ve been using and see what it puts on screen.

      I could also test overclocking / overheating the atmel and seeing how they collapse !!

      ********

      I should also finish the boards I’ve already designed and had made, they offer learning opportunities and possible discoveries ! The bucket brigade, the digitally-controlled pots (meh), and the band splitter (*EDIT* completed !) are the three that are left from that series. Also the Palimpsest.OS 2 board when controlled by microchip – especially if I can get the sync working ! Of course I have the new 128Kbit memory board (*EDIT* all done !) once I get the parts too and then a final (?) FPGA v2 board.

      ********

      I am still interested in exploring FPGAs and getting my hands in the tech to possibly stumble on cool stuff though so here is a second attempt at a video FPGA board based on the iCE40HX1K-TQ144 to output HDMI, DVI, VGA, and composite video.

      For generating verilog, there is migen for python 3 (https://github.com/m-labs/migen). I’m going to try a super simple thing in Verilog first to get a feeling for it. 

      I am learning verilog here : https://hdlbits.01xz.net/wiki/Main_Page

      It looks like generating HDMI is doable even though there is a difference between LVDS and TMDS (involving possibly 100nF series capacitors ?) :

      Here is the official guide : https://www.latticesemi.com/-/media/LatticeSemi/Documents/ApplicationNotes/UZ/FPGA-TN-02213-1-7-Using-Differential-IO-LVDS-Sub-LVDS-iCE40-LP-HX.ashx?document_id=47960

      https://www.fpga4fun.com/HDMI.html

      blackmesalabs.wordpress.com/2017/12/15/bml-hdmi-video-for-fpgas-over-pmod/

      https://github.com/hdl-util/hdmi/

      Different chips being used like the PTN3360D HDMI / DVI Level Shifter (IN STOCK!), a TFP410PAP TFP410 TI PanelBusℱ Digital Transmitter (NO STOCK!),

      Question - Pluto IIX GCvideo help needed | BitBuilt - Giving Life to Old Consoles

      According to the datasheet, “The LVDS25E/subLVDSE differential output buffers are available on all banks but the LVDS/subLVDS input buffers are only available on Bank 3 ofiCE40 LP/HXdevices.” ***Those are INPUTS but there are no special OUTPUT pins.***

      I have replaced the LDO with was giving me trouble previously and am making this version USB programmable so it could be a useful for others as a cool video kit.

      *****

      Revisiting FPGA programming, here is where I got to last time :

      Here is my process for the FPGA programming so far :

      1. I signed up for an account at www.latticesemi.com.
      2. I got a licence for iCEcube2, put it somewhere easy to find and took note of the directory, and downloaded iCEcube2 and the Lattice Diamond software from here : https://www.latticesemi.com/en/Products/DesignSoftwareAndIP
      3. I plugged in the iCEstick and it blinked in a circular pattern. I also checked that it had a port under Device Manager (it had 2!). 
      4. I went into iCEcube2 then to Help > Tutorial to open a pdf called “Implementing the Design” and followed the following steps :
        1. Start new project (iCE40, HX1K, ?TQ144?)
        2. Add Design file iCElab.v and Constraint file iCElab.sdc and checked the Device Info.
        3. Run Synplify Pro Synthesis
        4. Select Implementation
        5. Add constraint file iCElab.pcf under Import P&R Input Files.
        6. Run Placer
        7. Check the Floorplan, package view, timing analysis, power estimation
        8. Generate the bitmap (.bit and .hex files) which is saved wherever the project was saved. (For instance C:\Users\Jonah\Desktop\FPGA LATTICE DEMO PROJECTS\quick_start\quick_start\quick_start_Implmnt\sbt\outputs\bitmap).
        9. Here is what everything should look like once finished :
      5. I then transitioned to Youtube for a detailed explaination of using Diamond Programmer with the iCEstick here : https://www.youtube.com/watch?v=Df9k1T0bHmA&ab_channel=Dom
        1. Launch Diamond Programmer and take the default options (or click scan and take those). Important to note that you must launch Lattice Diamond Programmer directly, not through Lattice Diamond, in order to find the iCE40HX1K chip.
        2. It will mistake the board for a JTAG interface and give the following errors : “Failed to scan board”, “Scan Failed – Creating Blank Programmer Project.”
        3. Now change the Device Family to iCE40, the device to iCE40HX1K, and under Program enter the following information :
          1. Change Access mode to SPI Flash Programming and now some other options appear. Select > Vendor: Micron, Device: N25Q032, Package:  8-pin VDFPN8
          2. Now load the bitmap (.bin) file and check that it has a non-zero datasize :
          3. Click OK and then click the green traffic light on the next to top row of icons. You should then see a completion message and have the program on your board :
          4. Presto !

      Just for info :

      For the actual pinout of the ice40 (which you can change in Pin Constraints Editor):

      ***

      And here is my attempt programming my own board with the Lattice Programmer.

      I followed the same steps as above but instead selected the HW-USBN-2B (FTDI) programmer. Important to note that you must launch Lattice Diamond Programmer directly, not through Lattice Diamond, in order to find the iCE40HX1K chip. Also note that you need Lattice iCEcube2ℱ Software, not just Diamond for some reason.

      Here are the color connections needed from the Lattice Programming Cables User Guide :

      The USB power and Board power lights should be on on the programmer and the Prog blue LED should flash a few times before the Done blue LED will flash and Lattice Programmer will display Operation: successful.

      I am taking the example LED rotation verilog .v code :

      module LED_Rotation(
      
          input  clk,
          output LED1,
          output LED2,
          output LED3,
          output LED4,
          output LED5
      
          );
      
                     reg[15:0] div_cntr1;
                     reg[6:0] div_cntr2;
                     reg[1:0] dec_cntr;
                     reg half_sec_pulse;                         
      
                     always@(posedge clk)
                                    begin
                                    div_cntr1 <= div_cntr1 + 1;
                                    if (div_cntr1 == 0)
                                                  if (div_cntr2 == 91)
      
                                                                 begin
                                                                 div_cntr2 <= 0;
                                                                 half_sec_pulse <= 1; 
                                                                 end
                                                  else
                                                                 div_cntr2 <= div_cntr2 + 1;
                                    else
                                                  half_sec_pulse <= 0;                            
      
                                    if (half_sec_pulse == 1) 
                                                  dec_cntr <= dec_cntr + 1;                                          
                                    end                                                            
                     assign LED1 = (dec_cntr == 0) ;
                     assign LED2 = (dec_cntr == 1) ;
                     assign LED3 = (dec_cntr == 2) ;
                     assign LED4 = (dec_cntr == 3) ;
                     assign LED5 = 1'b1;
                                                           
      endmodule
      

      Under Tool > Pin Constraints Editor, we can change the pins activated in the code but mine is already set up connected to pin 99:

      I am soldering a second FPGA board. I noticed that the clock was not outputing anything, and also that the max temperature for the IC for reflow soldering is around 250°C. I am making sure to use the soldering iron “kissing” technique along with loads of flux applied.

      Reading through the datasheet :

      • Bank 3 additionally supports differential LVDS25 input buffers.
      • Each bank can have it’s own voltage level.
      • I may have to power the VCC, VCCIO_2, VCC_SPI, VCC_PLL, and VPP_2V5 (with a diode) even if I don’t plan on using them all just to get the device to turn on. (There is even a proper sequence to power them up in).
      • GNDPLL must NOT be connected to the board’s ground !
      • Bank 2 has two dedicated Input pins.

      ****

      FPGA BOARD ERRATA / DIARY :

      • 1.2V is connected to 5V throughout because of an EAGLE issue 🙁
      • I tried the voltage regulator 3 times and still no luck. *UPDATE* I tried a second 1.2V LDO that I ordered and it still reads 2.2V or so. No idea why this is happening when I can power the pin directly with 1.2V with my power supply no problem (therefore it can’t be a bad connection somewhere between 1.2V and another trace right?). Positive news is that the FPGA appears to have survived the over-voltage !!
      • Maybe I should give it a higher frequency oscillator, at least 25MHz, as I’m working with video?
      • I connected pin 9 of VGA to GND, it is connected to 5V on the signal side !
      • The GNDPLL should not be connected to GND.
      • The R2R ladder has a 270ohm going to ground instead of a 536 on each ladder.
      • Unclear which pins to plug where for programming – *EDIT* SOLVED
      • I had a hard time at first soldering the FPGA but then discovered a soldering “kiss” technique that was reliable and effective. For the clock, I melted the solder and then placed it gently on top.
      • I plugged it in with 2.2V instead of 1.2V and likely destroyed the chip the first time…
      • 0805 is doable and better for compact designs
      • I can’t find the name of the chip in the Target Device menu of Diamond Programmer. *EDIT* SOLVED : You need to open Diamond Programmer directly.
      • I need to get nicer boards if I am going to be working on FPGA boards, Aisler not inexpensively manufactured.
      • It seems like exploiting the parallelism of the FPGA could be interesting to explore. For this project it would probably be to logically mix several input videos together while transforming ?

      ***

      I’ve got it blinking at different frequencies !

      Now I want to generate some VGA signals as quickly as possible and start creating images by tweaking pre-made code like for VGAX.

      And here is demo code for the OLIMEX ice40 developement board which has RAM, DAC, ADC and VGA (but it needs a 100MHz clock) : https://github.com/OLIMEX/iCE40HX1K-EVB/tree/master/demo/ice40-io-video

      Also super simple (but uses a 25MHz clock) : https://www.fpga4fun.com/PongGame.html

      Here is the one I ended up using (takes a 12MHz clock and turns it into a 25MHz with the PLL) : https://github.com/imuguruza/alhambra_II_test/blob/master/vga/vga_test/

      Here is the key part of the code that actually draws on screen :

      module vga_sync_test(
          input wire clk_in,
          input wire reset,
          output reg r0,
          output reg r1,
          output reg r2,
          output reg b0,
          output reg b1,
          output reg b2,
          output reg g0,
          output reg g1,
          output reg g2,
          output wire h_sync,
          output wire v_sync,
          output wire led,
          output wire locked_led
        );
      
      wire clk_sys;
      wire display_en;
      //reg [9:0] h_count;
      wire [9:0] h_count;
      //reg [9:0] v_count;
      wire [9:0] v_count;
      assign  led = clk_sys;
      
      localparam  h_pixel_max = 640;
      localparam  v_pixel_max = 480;
      localparam  h_pixel_half = 320;
      localparam  v_pixel_half = 240;
      
      //Check if we can create RGB colors
      always @(posedge clk_sys) begin
        if (display_en) begin
          if (h_count < h_pixel_half
              && v_count < v_pixel_half) begin
            //Assign here your test color
            r0 <= 1'b0;
            r1 <= 1'b0;
            r2 <= 1'b0;
            g0 <= 1'b0;
            g1 <= 1'b0;
            g2 <= 1'b0;
            b0 <= 1'b1;
            b1 <= 1'b1;
            b2 <= 1'b1;
          end else if (h_count > h_pixel_half
                  && v_count < v_pixel_half) begin
            //Assign here your test color
            r0 <= 1'b0;
            r1 <= 1'b0;
            r2 <= 1'b0;
            g0 <= 1'b1;
            g1 <= 1'b1;
            g2 <= 1'b1;
            b0 <= 1'b0;
            b1 <= 1'b0;
            b2 <= 1'b0;
           end else if (h_count < h_pixel_half
                  && v_count > v_pixel_half) begin
            //Assign here your test color
            r0 <= 1'b1;
            r1 <= 1'b1;
            r2 <= 1'b1;
            g0 <= 1'b0;
            g1 <= 1'b0;
            g2 <= 1'b0;
            b0 <= 1'b0;
            b1 <= 1'b0;
            b2 <= 1'b0;
          end else begin
            //Assign here your test color
            r0 <= 1'b1;
            r1 <= 1'b1;
            r2 <= 1'b1;
            g0 <= 1'b1;
            g1 <= 1'b1;
            g2 <= 1'b1;
            b0 <= 1'b1;
            b1 <= 1'b1;
            b2 <= 1'b1;
            end
        end else begin
          r0 <= 1'b0;
          r1 <= 1'b0;
          r2 <= 1'b0;
          g0 <= 1'b0;
          g1 <= 1'b0;
          g2 <= 1'b0;
          b0 <= 1'b0;
          b1 <= 1'b0;
          b2 <= 1'b0;
        end
      end
      
      vga_sync vga_s(
            .clk_in(clk_in),         //12MHz clock input
            .reset(reset),           // RST assigned to SW1
            .h_sync(h_sync),
            .v_sync(v_sync),
            .clk_sys(clk_sys),       //25.125 MHz clock generated by PLL
            .h_count(h_count),
            .v_count(v_count),
            .display_en(display_en), // '1' => pixel region
            .locked(locked_led)      // PLL signal, '1' => OK
            );
      
      endmodule
      
       

      I would like to modify this code in the spirit of VGAX bytebeat-inspired video synthesis.

      I made sure to load the three dependent .v files and then changed the pin constraints in the .pcf as follows :

      set_io b0 76
      set_io clk_in 21
      set_io led 99
      set_io r0 81
      set_io b1 75
      set_io g2 91
      set_io r1 80
      set_io v_sync 87
      set_io b2 74
      set_io g1 95
      set_io locked_led 142
      set_io r2 79
      set_io reset 2
      set_io g0 96
      set_io h_sync 88
      
      

       

      It works !

      Just waiting for the LDOs to make it more practical to plug in. I will now test some actual patterns !

      ***

      Here is my first test bench with ModelSim ! Thanks to this tutorial from Nandland : https://nandland.com/tutorial-your-fpga-program-an-led-blinker-part-2/

      I am using ModelSim Lattice FPGA 2020.3 (which downloaded with either Icecube2 or Lattice Programmer?) and followed this PDF called
      Using Mentor ModelSim Simulator with Lattice iCEcube2
      (https://www.latticesemi.com/-/media/LatticeSemi/Documents/ApplicationNotes/MP2/Modelsim_AN006_Dec2020.ashx?document_id=50795)

      The steps to follow :

      1. Open a new project
      2. Click Add Existing Files (pick only the test bench verilog file) and then Close
      3. Now Compilation > Compile All
      4. Now Simulation > Start Simulation
      5. In the console type <<view wave>>…
      6. …then <<add wave * >>…
      7. …and a time period for example : <<run 100ms>>. (It takes us, ns, ms, and sec it appears)

      The signals are a little small and it is apparently possible to change this under Tools -> Edit Preferences, Wave Font and Footer Font…but when I try it crashes !

      Looks like printing to the console is going to be useful ! They work by using display like so…

      $display("0.5 seconds");

      …and then in the console area of ModelSim:

      run -all

      Here’s a simpler version of a tb for a 10 ps period of the following module :

      module dut ( input clk ); 
      `timescale 1ps / 1ps
      module top_module ( output reg clk );
      
            dut instance2 (.clk(clk));
      
                 initial begin
                 clk = 1'b0;
                 forever #5 clk = ~clk;
           end
      endmodule

      ***

      Thinking about different ways of generating patterns on a screen :

      1. Screen coordinate based (plotting functions that take an input x and produce an output y)
      2. Time based + screen coordinate based (a counter t increases over time and modifies the function’s behaviour)

      Turns out FPGAs can’t do math like microprocessors ! To implement trig functions you need to build a CORDIC, which is like a computer to calculate functions.

      Then again there are some things FPGAs can do better than microcontrollers like cellular automata (one study I checked out said 36 times faster than a GPU and up to 2,800 times faster than software). HDL Bits has an exercise to build the rule 30, 90, rule 101, rule 184 cellular automata.

      (Similar to cellular automata, it’s possible to make a hardware psuedo random number generator using a linear feedback shift register : https://en.wikipedia.org/wiki/Linear-feedback_shift_register )

      Here was the solution to the rule 90 challenge that I had to look up in the end :

      module top_module(
      input clk,
      input load,
      input [511:0] data,
      output reg [511:0] q);
      
      always @(posedge clk) begin
             if (load)
                 q <= data; // Load the DFFs with a value.
             else begin
                // At each clock, the DFF storing each bit position becomes the XOR of its left neighbour
                // and its right neighbour. Since the operation is the same for every
                // bit position, it can be written as a single operation on vectors.
                // The shifts are accomplished using part select and concatenation operators.
      
               // left                     right
               // neighbour              neighbour
                 q <= q[511:1] ^ {q[510:0], 1'b0} ;
              end
          end
      endmodule

      Check out this processing sketch that is evocative of cellular automata :

      https://openprocessing.org/sketch/1879926 or sketch 1908904

      Could it be possible to do this live to recorded video with the FPGA and be able to vary the number of generations, speed, etc. ?

      Try changing the “rules” live (by clicking “random”) while this cellular automata scrolls : https://devinacker.github.io/celldemo/

      https://en.wikipedia.org/wiki/Cyclic_cellular_automaton

      Makes one think that you could make a video game entirely from these patterns being activated at different times and in different zones…Or a dedicated FPGA board that takes in audio and divides it into different bands, or other control signals directly, to control which rules are being used to generate the pattern + a bunch of knobs to change the speeds etc. It could be super minimal, just some knobs, an FPGA and an HDMI out.

      Hardware version of CA : tinkerings.org/2016/09/24/cellular-automata-explorer/

      Also check out rules that go beyond logic operations with neighboring cells and into modulo values : https://en.wikipedia.org/wiki/Cyclic_cellular_automaton

      I am now trying to use the test bench to better understand why this code isn’t putting any pixels on the screen currently.

      Here is my test bench. An important note is that variables that are not modified in an always or initial block should not be reg but wire instead.

      `include "rule90.v"
      `timescale 1ps / 1ps
      
      
      module rule90_tb();
      reg clk;
      reg load;
      reg [511:0] data;
      wire [511:0] q;
      
      rule90 DUT (
      .clk(clk),
      .load(load),
      .data(data),
      .q(q)
      );
      
      initial begin
      #10
      clk = 1'b1;
      #10;
      clk = 1'b0;
      #10;
      load = 1'b1;
      data = 1'b1;
      clk = 1'b1;
      #10;
      clk = 1'b0;
      #10;
      load = 1'b0;
      
      end
      
      always #10 clk = ~clk;
      endmodule

      This shows that the rule90 circuit is working. Every clock cycle it advances. If I could show one bit per pixel and refresh every clock cycle ?

      ***

       

      I’m getting some cool images :

      ***

      For the next FPGA board, I’m aiming for the following features :

      • It could have a handy mini screen (raspberry pi zero using DPI I/0 pins with video splitter to pass on the VGA to FPGA). I wonder if this isn’t a gimmick and not really in line with the “artistic research” aspect of my project.
      • FTDI chip for USB programming (this is too technical I have decided)
      • 100MHz oscillator with divider
      • 4x SRAM, possibly in two banks as I only have a total of 95 pins to work with
      • HDMI out, (possibly composite and DVI also ?). I wonder if this isn’t a gimmick and not really in line with the “artistic research” aspect of my project.
      • Some kind of basic interface ? (Knobs etc? But this would require an ADC unless I just use dip switches). One solution is to make hardware controls on the peripherals (clock divider, bit selections for incoming and outgoing signals, reset and CS sel on SRAM, etc.).
      • An atmega which can ask the FPGA to do things? Not sure this is necessary.
      • A fan and heat sink for the FPGA?? But this will hide it. Also a gimmick.
      • An FPGA with more Logic Modules – like 4K instead of 1K? But this doesn’t come in the easier to solder format…
      • A reset button ?
      • A fuse and reverse polarity protection !
      • microcontroller-accessed SPI FLASH so we can test moving between different types of memory. Except I haven’t had a lot of luck with SPI memory and video recording so far.

      Reading a bit more about what FPGAs can do well ;

      • they have tons more I/O pins than an Arduino? This means I can control multiple SRAM address and I/0 pins.
      • Architecture can be completely reconfigurable (unlike a microcontroller which keeps the same architecture).
      • low latency applications that take data as a stream in real time from sensors, cameras, etc. This means I can perform fast logic manipulations of saved data.
      • high throughput applications, pipelining
      • encryption and networking
      • digital signal processing (IIR, FIR, FFT, ADC, DAC) like video filtering
      • parallelism, like doing 128 small tasks at the same time, versus microcontrollers doing things in serial
      • algorithms that can be solved with LUTs, tasks with lots of small adding and subtracting or multiplication (?)
      • K-means clustering, Monte Carlo, neural nets, Mandelbrot fractals, cellular automata ?
      • Seems that there are more and more systems that include micrcontrollers + FPGA + DSP, and you can of course put a microchip inside an FPGA. Here the FPGA accelerates certain tasks for the CPU

      *****

      Here’s what I think I could do with an FPGA and two individually-accessible SRAM I/0 banks   banks :

      • Reverse, scramble, or move through memory addressing with different patterns
      • could change the sample rate of recorded or incoming images
      • could perform logic operations on incoming /recorded video
      • could place sprites on screen, or other parts of memory, through blitting I could selectively overwrite memory.
      • It could record 8 tracks in parallel at 1 bit resolution, or record super long 1 bit resolution videos like on previous boards.
      • It could do matrix transformations on memory like shear, rotation
      • Copying values from one address and then reapplying them to another address every frame (called piping) or just one time. I could generate noise between certain values, or shift values up or down on (called tilting), listen to a value and then reapply it after a fixed number of frames, freezing the current value somewhere for future frames, replacing values intelligently with values in certain sets. Could this be called in-memory processing (https://en.wikipedia.org/wiki/In-memory_processing)? I could copy all the kinds of ways memory is accessed : https://en.wikipedia.org/wiki/Memory_access_pattern !

      With this setup, the FPGA can increment the ADD of all memories while individually controlling which SRAM is reading or writing. Additionally, and simultaneously, it can send and receive different data between two connected SRAM banks. Bascially, it can’t simultaneously access two different parts of memory for reading or writing, if it wanted to do that it would need to remember some info in a buffer and then change the address in sequence like a normal microchip (this is all to give a greater color range to the board). So as far as I can tell the following memory reading and writing operations could be accomplished :

      1. while incrementing memory ADD, record incoming video on A, B, C, D in sequence (at various bit depths)
      2. while incrementing memory ADD, record incoming video on A, B, C, D in parallel (make 4 copies)
      3. while incrementing memory ADD, record incoming video on A, B, C, D and playback previously recorded video
      4. while incrementing memory ADD, play back video on A, B, C, D in sequence
      5. while incrementing memory ADD, playback video 4 copies of a video on A, B, C, D in sequence (i.e. loop)
      6. while decrementing memory ADD, playback a video in reverse
      7. access recorded video with different ADD patterns
      8. while incrementing memory ADD, take stored sprites from the top of one SRAM and insert them into over SRAMs at later addresses
      9. while incrementing memory ADD, perform logic operation on incoming video + an SRAM reading while writing it to a second SRAM
      10. while incrementing memory ADD, perform bit level transformation on an SRAM recording while writing it to a second SRAM

      I am starting to think that losing some color information is worth having more flexibility to work in parallel with SRAM and save me headaches later on when I’m doing verilog hardware descriptions. Here is a simpler proposal that would have a single input (possibly record/pb or “function” meaning do something to the incoming video and then show it on a loop) :

      • I lose LEDs, but I replace them with the most honest indicators possible, the signals themselves buffered.
      • Lost the ability to control individually each quarter memory with WE control.
      • No more DIP select buttons…How will I be able to play this thing live once it’s going through its code (apart from being able to mess with the clock, the RGB bias out, VGA pins coming in, and being able to reset SRAMs and the FPGA)? Should I be able to interrupt it’s functioning by directly controlling CS and WE pins ? (This is possibly dangerous as two memories both set to READ sharing the same I/O pins would be bad.) How about a single button, which activates some hardware function? I would need to load a new code if I wanted to test a new hardware function.

      I’m trying to justify doing this thing in hardware by having tons of indicator LEDs, knobs to change parameters etc. I have to acknowledge that there is a certain amount of manipulation in making art, I am pushing it further in the direction I want so that it is easier to explain to people.

      Reminder : Why am I not using an atMega 2580 which has 86 programmable IO lines and 16MHz frequency ? FPGA is parallel, and it is faster, several people in different contexts have suggested FPGAs for my project, and it’s a learning opportunity.

      In general, doing things in harder is (Fabien) Faster than software, (Vivien) emphasizing materiality, and (Marc) pushing against the genericness of software and hardware that we are increasingly using.

      ****

      Using BRAM seems pretty simple to implicity create :

      reg [15:0] memory [start_address : end_address];

      //memory[4] addresses word 4;

      Fabien at work suggested two things : Not using a resettable fuse as they take longer to stop high current destroying things. And possibly having an SD card with the videos which the FPGA can read directly and getting rid of the RPI. This is because, while writing to SD takes time, reading can be fast. This would be a kind of ROM where I could store videos.

      The best mode for an FPGA apparently is one bit SD mode, instead of SPI, as it only requires 3 pins: CMD, CLK and DAT0.

      https://www.fpga4fun.com/SD2.html

      It looks like inside the SD card is just NAND Flash memory, so maybe I could interface directly with this ?

      https://upload.wikimedia.org/wikipedia/commons/f/f0/Pretec_16GB_SDHC_without_cover_20090420.jpg

      Or I could have Arduino doing the interface with an SD card ? I’m not sure why but I feel like this is going in the engineering direction and not the artistic one. The Rasbpi solution works, why not just keep it and save the headache that won’t in any way change the artistic output of the board.

      *****

      ATmega2560 SRAM board with SD card and I2C Flash memory. Raspberry pi as video in.

      But not very interactive. More about messing with different kinds of memory, and as a parallel test as the FPGA but more familiar and constrained in C.

      ***

      Don’t know what this is yet but, some kind of typology of memory modifications ?

      Choreographable video synth (PART III)

      Making things easier, simpler, more plug and play.

      ****

      Workshop
      Organize parts 
      
      Palimpsest.OS
      Get all channels working 
      Get raspberry pi VGA out working 
      Test with raspberry pi VGA put 
      Fix VGA input/output (I know what the problem is at least :)!
      SPI SRAM 
      Get recording as fast as possible 
      Try with 4MB FRAM ?
      New board with several + raspberry pi + snake-like channel overwriting?
      
      FPGA
      Try simple VGA with LatticIce40
      Solder FPGA board 
      ****
      La Generale experience :

      So many cables and wires and machines….something more minimal / smaller and portable possible ?

      Would love to have an integrated thing with raspberry pi / FPGA generating video and the thing directly outputting it.
      Do not rely on computers to output VGA signals ! Try raspberry pi.
      Physical objects is what I should make, not projections, because my project is about materiality ! I could make circuits that go beyond just recording and have moving parts and tiny screens eventually ? Then again this is a dangerous dream as I’ve learned with VHS and Floppy Disk tests…
      Don’t make experimental stuff during residencies, test tools you’ve already built and deploy tested things.
      My project is all about trying to touch video, get my hands into the inside of the machine. It’s also all about making mistakes, and stumbling upon unexpected output as a result.
      Somewhere between a kit/workshop and an object. (It’s not a performance) 
      ****

      I’ve got a Raspberry Pi Zero outputting VGA nicely. On startup it launches VLC in fullscreen and plays a playlist of iconic film excerpts. I activated hotplugging so it keeps looping even if the adapter is unplugged for long periods of time.

      I used Win32DiskImager and downloaded the ISO Image Raspberry Pi OS with desktop (around 1GB) from the officiql website (https://www.raspberrypi.com/software/operating-systems/) and put it onto an 8GB SD Card.

      In terms of connectors I needed a SD Micro > SD card adapter, HDMI mini > HDMI, an HDMI > VGA, a USB A > USB Micro for power, and a USB Micro to USB A female in order to plug in a mouse / keyboard.

      I followed these three tutorials for setting up VLC autoplay and turning off annoying VLC text:

      https://forums.raspberrypi.com/viewtopic.php?t=17051

      Raspberry Pi: Run VLC on startup and play slideshow videos/pictures from folder

      https://www.shellhacks.com/raspberry-pi-force-hdmi-hotplug/

       

      Now adding a power off button (not good to pull the plug while running)

      https://howchoo.com/g/mwnlytk3zmm/how-to-add-a-power-button-to-your-raspberry-pi

      **EDIT The rasbpi turns off when I unplug HDMI or plug into the palimpsestOS. Is it because RGB are mixed with only 100ohm resistors ? Should I have 3 blocking caps and then mix after ?

      Here’s a write up on how to VGA :

      https://chipnetics.com/tutorials/understanding-75-ohm-video-signals/

      Looks like parallel 75ohm resistors going to GND from the input is good practice + a cap and 75 ohm resistor on output?

       

      VGA OUTPUT examples :

      MAX4032 5V, 6dB Video Buffer with Sync-Tip Clamp, Output Sag Correction, and 150nA Shutdown Current | Analog Devices

      If I understand this last one, three parallel 75ohm resistors makes a 25ohm resistor. 97ohms gets 80% of 3.3V gone before the 25ohm dissipates the rest so that there is 0.7V left for the 3 channels. For a 5V supply like mine, I’ll need to remove 86% of 5V to get it down to 0.7V.  A 160 ohm resistor then ?

      VGA INPUT examples :

       

       

      *EDIT Made the changes (RGB colors in to GND through 75ohm, one color through cap to bias + 160ohm and now there is no output…But maybe it was already broken at this point? Can test when new converters arrive.)

      Looked at some VGA in/out boards I had in my possession and saw the following :

      • H and V sync can go to a 74HC125 Line Driver / Buffer.
      • Color returns can be conected together and grounded along with chassis.
      • Examples of color pins going to grounded 75ohm resistors then on to blocking caps. Also colors to gates of transistors.
      • Colors also going to video signal switcher like this : QS4A210 – 2-Channel 4:1 Analog Mux/Demux
      • Definitely DO NOT ground pin 9 (which is 5V), as I have done in all previous boards…

      ****

      An older HDMI to VGA converter broke so I opened it up to see if I could reproduce it. It’s an ALGOLTEK AG6201 which appears to be not accessible anywhere but the manufacturer’s website.

      The alternative is using a video chip which can trasmit HDMI like this project : https://hackaday.com/2019/07/26/hdmi-from-your-arduino/ which uses a CH7035B HDMI encoder.

      Alternatively I use the HDMI to VGA adapter and solder a D Sub Standard Male connector (https://www.mouser.fr/ProductDetail/TE-Connectivity-AMP/2301843-1?qs=rrS6PyfT74crws9wAQVNoA%3D%3D&mgh=1&vip=1&gclid=Cj0KCQjw27mhBhC9ARIsAIFsETE7Rp9JFGXhYFAXh_Z2YbQUB2NfHqO8rM7yPueb-T3yFiKbUMvJkOEaAtjJEALw_wcB) to the board.

      ***

      I will be testing a pico projector and a VGA capture device soon…

      Video Coverter VGA Capture Card,VGA to USB2.0 Converter,Audio and Video Capture Device,Plug-and-Play,USB Drive-Free HD 108...Mini Projector, PVO Portable Projector for Cartoon, Kids Gift, Outdoor Movie Projector, LED Pico Video Projector for Home ...

      ***

      Trying again with SPI SRAM

      This code seems solid to me but I can’t go beyond 100Hz…

      #include <SPI.h>
      #include <SRAM_23LC.h>
      
      // SPI bus can be SPI, SPI1 (if present), etc.
      #define SPI_PERIPHERAL    SPI
      #define CHIP_SELECT_PIN   8
      
      /* Device can be:
       * 128KB: SRAM_23LCV1024, SRAM_23LC1024, SRAM_23A1024
       * 64KB: SRAM_23LCV512, SRAM_23LC512, SRAM_23A512
       * 32KB: SRAM_23A256, SRAM_23K256
       * 8KB: SRAM_23A640, SRAM_23K640
       */
      SRAM_23LC SRAM(&SPI_PERIPHERAL, CHIP_SELECT_PIN, SRAM_23LCV1024);
      
      // Additional SRAM chips
      // SRAM_23LC SRAM1(&SPI_PERIPHERAL1, CHIP_SELECT_PIN1, SRAM_23LC512);
      
      #define START_ADDRESS   0
      
      //uint8_t buffer[BUFFER_SIZE];
      //#define BUFFER_SIZE  320
      
      char buffer[1000];
      #define BUFFER_SIZE  (sizeof(buffer) / sizeof(uint8_t))
      
      void setup(void)
      {
        pinMode(2, OUTPUT);
        /* Without parameters, begin() uses the default speed for this
         * library (12MHz for samd, 14MHz for sam, and 4MHz for avr).
         * Note that SPI transaction support is required.
         */
        SRAM.begin();
       // SRAM.begin(8000000UL);      // or specify speed
        //Serial.begin(9600);
      }
      
      void loop(void)
      {
        //while (!Serial); // Wait for serial monitor to connect
      
      // Record a series of values
        for (size_t i=0; i < BUFFER_SIZE; i++) {
          //buffer[i] = byte(digitalRead(A2));
              if ( (PINC & (1 << PINC2)) == (1 << PINC2) ) { //PC2 is what we're reading
              buffer[i] = 0xFF;// pin is high
              }
              else {
              buffer[i] = 0x00;// pin is low
              }
        }
      /*
        // Print buffer to serial monitor
        Serial.print("Write Block: ");
        for (size_t i=0; i < BUFFER_SIZE; i++) {
          Serial.print(buffer[i], DEC);
        }
        Serial.println();
        */
      
        // Write block
        if (!SRAM.writeBlock(START_ADDRESS, BUFFER_SIZE, buffer)) {
          //Serial.println("Write Block Failure");
        }
      
        // Clear buffer
        //memset(&buffer[0], 0, BUFFER_SIZE);
      
        // Read block
        //Serial.print("Read Block:  ");
        if (!SRAM.readBlock(START_ADDRESS, BUFFER_SIZE, buffer)) {
          //Serial.println("Read Block Failure");
        }
      
        // Print buffer to serial monitor
        for (size_t i=0; i < BUFFER_SIZE; i++) {
          //Serial.print(buffer[i], DEC);
         if(buffer[i] == 0x00){
           //digitalWrite(2, LOW);
            PORTD &= ~(1 << PD2);    // set pin 2 of Port D low
         }  
         else{
          // digitalWrite(2, HIGH);
            PORTD |= (1 << PD2);     // set pin 2 of Port D high
         }
        }
        //Serial.println();
        //delay(1000);
      }

      I just can’t manage to get the same level of control with an SPI device as with parallel SRAM and counters.

      ****

      New board time 😀 ! Test new things but keep the plug and play idea from last board and make even more so. SPEND MORE TIME SANITY CHECKING THE DESIGN and double checking pull ups and downs.

      Goals :

      • How about using a 16Mbit SRAM to store 128MBits of data with only a few added components ?! The plan is a pair of shift registers to convert serial output from a comparator into 8 bits to be sent all at once to the SRAM and the inverse on the output side. I would need the shift register clocks to be 8 times faster than the SRAM I think?
      • Make it so power (5V – with an LDO on board to eliminate possibility for accidents) can be shared with a double power jack. Reverse polarity protection.
      • A fine and coarse threshold selection !
      • proper VGA input and output good practices that will never harm anything sending video signals in or recieving signals sent out (blocking caps, 75 ohm impedence matching, Vref for top side of variable comparator bias!!, buffers for H and V sync!!, two cables close together!! and shielding – guard rings? – on the PCB for these traces!! different grounds for different parts of the VGA cable, use BNC connectors for RGB??)
      • Raspberry pi as input VGA through converter which plugs into a male VGA on the board, add an OFF/ON switch to safely turn off
      • pass thru VGA signal switch !!
      • Have different clock cans to switch between?
      • Extended Display Identification Data chip as a test?
      • Have audio out option ?

      Here’s the preliminary circuit :

      From https://www.cs.unca.edu/~bruce/Fall11/255/Labs/Lab13AnalogInput.html

      comparator

      From https://electronics.stackexchange.com/questions/144530/circuit-for-a-coarse-and-fine-setting-potentiometer

      ****

      As for PCB inspiration, perhaps something that evokes the computer video graphics card :

      Rectangular, with metal bracket (these are called Computer brackets in the Circuit Board Hardware – PCB category of Mouser.fr. They come in low profile or high profile), fan, heatsink, memory bank in a row, name of the board somewhere, PCI connector

      Palit Daytona NVIDIA GeForce2 MX 400 AGP 32MB VGA Vintage Retro Graphics Card | eBay

      16 MB PCI VGA Video Adapter Card - Our video cards and sound cards enable you to add smooth video performance or high-end audio capability to your PC computer, through a motherboard

      143 8MB Graphics Card, VGA PCI 8MB 32Bit Desktop Computer Accessories Multi- Display for ATI Rage XL Supporting All Motherboards with PCI Plug : Amazon.co.uk: Computers & Accessories

      ****

      Here is my first attempt at simulating the logic :

      The only tricky part was activating parallel load of the output register only once per 8 clock cylces.

      This design includes a giant FPGA to control enables all broken out along the PCI-E connector (that could be played like a piano with an alligator going to GND) in time and also to match the aesthetic of the video card. It would feature a stunning 128 Mbits (16MBits SRAM x 8) of memory. Would be cool to have LEDs next to each memory which light up when that block is recording.

      ***

      Building on the idea of making physical artefacts, Vivien Roussel had the idea of moving towards displaying the chassis of the computer along with these boards. There are loads of cool test bench computer cases that could be an inspiration for this :

       

      ****

      Or a DDR SDRAM module as inspiration :

      Diferenças entre as memórias DDR2, DDR3 e DDR4 | Crucial BR

      Here’s what it’s looking like in Eagle so far :

      I still like the idea of a kind of piano controlling :

      • 3x SRAM CS sel bits
      • 3x COUNTER EN + individual RST

      And of course :

      • Threshold control (fine and coarse this time !)
      • Clock DIV
      • REC/PB

      Here’s the board as ordered :

      CIRCUIT DIARY :

      • The fine and coarse pots appear to work very well.
      • The clock divider works as expected. Though it might be interesting to be able to play with different frequencies too as it seems to be important to get the combination of sampling versus pixel frequencies.
      • I checked and the serial clock is indeed being divided by 8 and inverted (albeit super noisy!) :
      • The Overflow and CS signals appear to be working well (though I had a hard time soldering the resistor networks!)
      • The !WR signal is as expected
      • Possibly should have put pull-downs for the SRAM I/0 pins ?
      • I should have made a timing diagram not just the simulation..
      • The option to manually advance the OVERFLOW signals is cool because you can solder one SRAM and test only it without having to wait for its turn to come around !
      • I have reached a problem : the 596 is not shifting the serial into parallel. I can see it trying (little mini signals getting through), but it is as if the I/O pins are being pulled low, but by what ? The SRAM ? I’ve confirmed we’re in write mode so they should be high Z. The Serial to Parallel converter somehow? But the I/O pins are inputs for this IC…Hmmm. Is it something to do with the open drain outputs (or the Schmitt trigger inputs?) on the 596 ? **EDIT : Had a 595 with the same footprint and substituted it, seems to be working now.
      • So, the output is very stripey. I have removed the 75ohm resistor to ground and shorted the 100ohm to the output RGB pins. I’ve tried shorting the blocking cap and it makes things a tiny bit easier to see but overall it is barely legible as an image. I think it has something to do with the output parallel to serial conversion. Here is a sample of a capture :

      • For some reason it can also work much better :

      • I don’t understand how it is possible to see the screen while it is recording as there is no “pass-thru” option…. There is also sometimes quite a difference from what is somehow passing through while in record mode and what plays during PB mode. *EDIT*There is a noise issue, when the VGA input is plugged in there is static that is entering somewhere. Trying to locate it currently. *EDIT* it is coming from the VGA IN. Tried connecting a bunch of GNDs (digital GND, chassis GND, color return RED) but still getting nowhere trying to eliminate the noise.
      • I ordered the wrong type of bracket, this one is for a double row VGA…
      • I had an issue with SRAM D but then replaced it and all is good.
      • I forgot to have a pre-amp before the comparator, this is essential otherwise you don’t get any in screen peaks and basically don’t see anything unless you’re really lucky. I used the Palimpsest.OS preamp and bias setup and it works fine.
      • The tiny trimpots need to be replaced with actual knobs !!
      • I forgot to add loop LEDs ! It would have also been cool to know which SRAM is currently recording.
      • EVERYTHING IS WORKING I CAN’T BELIEVE IT. The solution was to just test everything with a simple ramp using the function generator and look at the play back. Then I checked the pins on the SRAM and saw funky signals for several address pins that looked like they were several signals being added together. Clearly when I soldered in a bunch more SRAM and there were tiny connections between five different address pins and an I/O that I did not notice. This was causing chaos. I found the connections and fixed them, now it’s recording just as expected and it’s so glorious. NOTES : I am using the op amp from Palimpsest.OS AND crucially, am connecting both Analog and Digital Grounds between the two boards and the VGA IN with VGA OUT.

      ***

      While waiting for this board to arrive :

      • Try different function generated patterns of hitting count 0 enable while recording on the 16Mbit version
      • Test the 8 layer board ! *DONE*
        • Remove pin 9 GND and fix other issues with VGA in and OUT with VGA beakout PCB
        • Test on raspberry pi / computer IN *DONE*
        • Test feedback ! *DONE*
      • Try mini projector *DONE*
      • Try VGA capture device *DONE*
      • Put restart button on rasbpi

      *******************

      *EDIT* It works with rasbpi when I connect only a color, GND, H and V syncs !! So much more convenient than previously.

      • It might be cool to be able vary the mixing of the different channels
      • The output image is quite faintweak, I think I should rexamine the resistors I put at the termination and maybe switch to B+W.
      • It’s a bit muddy with several channels, would be cool to be able to filter that
      • I need a path to feedback with a pot !
      • Switched the output resistors to a 150ohm going to R,G,B and it works nicely.
      • Dip switch hard to use without tool.
      • Hard to see which direction switches are pointing in darker light

      More technical ERRATA :

      • Pin 1 of the 40MHz clock should be pulled HIGH to be enabled, not LOW as it is on the board !
      • The THRESHOLD pot isn’t connected to GND on one side…
      • I should have tied the CCLR (pin 10, which resets when pulled LOW) of the 590 to VCC with a 10K instead of leaving it floating connected to VSYNC. This made it malfunction.
      • BIG PROBLEM : I ordered multiplexers (unidirectional) instead of analog switches (bidirectional) ! The ‘157 multiplexers mess with SRAM B’s I/Os when it is in READ mode (when the SRAM is outputing values on the I/O pins). I ordered a replacement that is pin compatible, the 74LVC1G3157 (DATASHEET : https://www.ti.com/lit/ds/symlink/sn74lvc1g3157.pdf?HQS=dis-mous-null-mousermode-dsf-pf-null-wwe&ts=1679316452048&ref_url=https%253A%252F%252Fwww.mouser.de%252F). EDIT* The new components work perfectly – everything is good !
      • The Sync Clock IC is 3.3V not 5V…
      • Image jumps around of course. When I try to record with the Burst AND IC which outputs !CLK, no writing can occur. I’m guessing this gate messes with the timing somehow? As a workaround I’m trying to connect the 4 AND’ed V SYNC counts to either the address counter IC Reset or to another reset somewhere. 
      • Lots of noise on V SYNC, I should maybe have made the input and output VGA jacks right next to one another…
      • Pin 9 of the VGA D-SUB 15 is VCC for the Display ID EEPROM chip – but I have it connected to GND !! In general I need to respect the rules around the different grounds and return pins in the VGA protocol and not just connect them all together. Hoping to fix this in the next version.

      ***

      Thinking about making a board with a small 5″ screen / or a mini projector incorperated in it

      Fabien suggests using an LCD driver from a normal sized computer screen for a smaller screen (but he says it will will in 16:9 format). The other option he suggests is to use an FPGA to control a screen directly with LVDS.

      Artist Andreas Gysin’s LCD 1 from http://lcd.ertdfgcvb.xyz/

      ***

      Just realized that I could have an raspberry pi using VGA directly from I/0 pins : https://fr.pinout.xyz/pinout/dpi#

       

      ****

      Currently thinking the next PCB should be raspberry pi sending video through I/O (not through HDMI) and FPGA controlling SRAM. This would allow messing with the sequence of the memory recording / playback. Could make a compact version of this project (a kind of black box, deployable version) without many external components but with sililar functionality. I could test making the FPGA USB programmable board too. Of course it would also be programmable.

      To get here :

      • make the automated palimpsest.OS board
      • make the simple FPGA VGA board

      ****

      I am revisiting the SPI SRAM code with renewed patience, I actually wrote it first on paper !

      Here is my simple buffer filling code first off :

      const int buffer_size = 2000;  // Only 2K bytes of SRAM on the 328P
      byte buffer[buffer_size];
      void setup() {
        DDRC = 0b00000000;  // set PC2 as input pin
        DDRD = 0b00000100;  // set PD2 as output pin
      }
      
      void loop() {
      
        //  fill the buffer
        for (int i = 0; i < buffer_size; i++) {  // iterate through buffer
          for (byte mask = 0b00000001; mask > 0; mask <<= 1) {  // iterate through a bitmask
            if ((PINC & 0b0000100) == 0b00000100) {  // if input pin high...
              buffer[i] = (buffer[i] | mask);  // set this bit
            }
            else {
              buffer[i] = (buffer[i] & ~(mask));  // clear this bit
            }
          }
        }
        // read buffer back
        for (int i = 0; i < buffer_size; i++) {  // iterate through buffer
          for (byte mask = 0b00000001; mask > 0; mask <<= 1) {  // iterate through mask
            if ((buffer[i] & mask) == mask) {  // if bit in buffer is high...
              PORTD |= 0b00000100;  // ...write output pin high
            }
            else {
              PORTD &= ~(0b00000100);  // else, write output pin low
            }
          }
        }
      }
      
      
      

      Tried to see what this produce on the screen. I’m using a comparator from the previous board to do ADC and then feeding the ouput through a 470ohm resistor to red. It just leaves little comets which don’t appear to relate to the image…

      On the scope it doesn’t look far away though :

      Hmm…

      ****************

      After skimming from Nand2Tetris and checking out the VTECH Video Painter, I realized I could make a really basic screen interface :

      • I could record an image and then have an algorithm go through it and make changes (like photoshop effects like blur or polarize).
      • I could have sprites stored and then copy them into the screen-memory mapped SRAM
      • I could even have a joystick move from pixel to pixel and let you draw, copy and paste and draw circles !
      • It could also be a non uniform mapping from memory to the screen !

      ****************

      The VGA Capture is working and it’s fantastic ! I’m using OBS, I just clicked ADD SOURCE and then Video Capture device. It needs to be plugged in to USB A, not C, for the LED to come on.

       

      I tried the mini projector but it didn’t like the signals I was sending it. I think I have to avoid intelligent interfaces that can decide to send or not along my signals. Wondering about the camcorder CRT viewfinder and if I should head back in that direction.

      Here is a popular 4″ screen :

      Il Mini Monitor CRT da 4 pollici in bianco e nero supporta l'ingresso Video 12V4W tubo per immagini elettronico da 4 pollici - AliExpress

      Choreographable video synth (PART II)

      Inspired by the history of mounting circuits on wood with screws and wire, evoking John Cage’s prepared pianos. 

      This iteration of the project is born of a few realizations :

      1. VGA is an analog signal, it’s not digital.
      2. The coolest effects are the simplest ones : XOR, HP and LP filters, comparators, etc. which can be easily made with discrete components.
      3. A simple low frequency oscillator could control these effects with an LED > LDR voltage controlled resistor set-up. 
      4. Two out of sync oscillators easily make a pattern that doesn’t repeat often and is difficult to predict.

      Pedagogically and aesthetically I like this idea : it goes back to the basics of electronics, the history of electronics, and will show the materiality of video signals. This in contrast to the overly complex use of digital components to do basic modifications…

      The three basic circuits :

        

      *TESTED* This works (powered at 5V, with pull down 10K on input and the rest 1K and two BD135s) at lower frequencies (<100KHz) around 5V.  I added a 5K variable resistor (or an LDR + resistor) to increase the resistance of R1 and it varies the threshold !

      *TESTED* Works using BD136 PNP, 10K for the pull down and 1K for the base protection. General purpose diodes. I replaced the pull down with a 5K variable resistor and got some messed up results in the MHz. Doesn’t need power – just takes it from the input signal ! (But VGA signal would need to be amplified in order to work. 

      *TESTED* With a 104 cap and 5K variable resistor I can vary the filtering of a 5V function generator signal. 

       

      ****

      OK we’re back to the original plan ! Here is the Palimsest.OS Rev.2 :

      WHY ?

      • This board is for the inauguration of the IFT at the DVIC. It has to demonstrate technical proficiency on behalf of the staff, and must run independently as an tech-art installation, modifying video independently day in day out. 
      • Rev.1 didn’t work for microchip automation, this one should work smoothly(?). If everything works I could write code that executes different video manipulations. I also added selection LEDs to show the microchip doing its thing.
      • This tests the 8 channel 1-bit WRITE/REWRITE memory idea (but not the more elegant SRAM + buffer idea of Fabien), with certain effects tied to certain channels
      • Incorporates a simple to control XOR, comparator and HP/LP/BP filter into one board
      • Has a stable clock setup with metal can oscilloscope, a gen lock IC, and V SYNC burst setup
      • Tests an (expensive) programmable filter IC
      • It is a test for a simpler, inexpensive 8 ch recorder board that could be a cool kit
      • Does away with the ADC and all its pesky issues and trades it for a simpler 1bit “ADC”. 
      • I’m also using 5V SRAM to avoid the headache of different logic levels (though this means I only have 4MB of SRAM versus 16MB).
      • For testing purposes it can be soldered as a logic-controlled board or as a physical switch controlled-board. 
      • Instead of having lots of jumpers for wires, I went for rotary switches to make things more plug and play. However this also means that there are fewer experminental tests that are facilitated (like disabling a single counter while recording etc.) that were possible on rev.1
      • Can layer different recorded portions easily in theory
      • Battery switch and edge potentiometers instead of knobs
      • Theoretically could do feedback and echo tests with this board as it can read and write from and into memory simoultaneously 
      • This board should be easier to work with than the previous stacked PCI-E motherboard design which made knob turning and mounting hard. 
      • Instead of using generic octal logic ICs I went for more specific purpose ones.
      • The board will be made at https://aisler.net/ instead of JLCPCB so I’m hoping for a really nice finish

      Here’s a possible minimal installation with it :

      ****

      PALIMPSEST.OS v2 ERRATA :

      • Pin 1 of the 40MHz clock should be pulled HIGH to be enabled, not LOW as it is on the board !
      • The THRESHOLD pot isn’t connected to GND on one side…
      • I should have tied the CCLR (pin 10, which resets when pulled LOW) of the 590 to VCC with a 10K instead of leaving it floating connected to VSYNC. This made it malfunction.
      • BIG PROBLEM : I ordered multiplexers (unidirectional) instead of analog switches (bidirectional) ! The ‘157 multiplexers mess with SRAM B’s I/Os when it is in READ mode (when the SRAM is outputing values on the I/O pins). I ordered a replacement that is pin compatible, the 74LVC1G3157 (DATASHEET : https://www.ti.com/lit/ds/symlink/sn74lvc1g3157.pdf?HQS=dis-mous-null-mousermode-dsf-pf-null-wwe&ts=1679316452048&ref_url=https%253A%252F%252Fwww.mouser.de%252F). EDIT* The new components work perfectly – everything is good !
      • The Sync Clock IC is 3.3V not 5V…
      • Image jumps around of course. When I try to record with the Burst AND IC which outputs !CLK, no writing can occur. I’m guessing this gate messes with the timing somehow? As a workaround I’m trying to connect the 4 AND’ed V SYNC counts to either the address counter IC Reset or to another reset somewhere. 
      • Lots of noise on V SYNC, I should maybe have made the input and output VGA jacks right next to one another…
      • Pin 9 of the VGA D-SUB 15 is VCC for the Display ID EEPROM chip – but I have it connected to GND !! In general I need to respect the rules around the different grounds and return pins in the VGA protocol and not just connect them all together. Hoping to fix this in the next version.

      More Meta errata :

      • It’s a bit muddy with several channels, would be cool to be able to filter that
      • I need a path to feedback with a pot !
      • Switched the output resistors to a 150ohm going to R,G,B and it works nicely.
      • Dip switch hard to use without tool.
      • Hard to see which direction switches are pointing in darker light

      Oy vey ! I realized that I could just use an I2C RAM IC and save about a billion components. Here are the more plug and play simple boards I made in the aftermath :

      Good news: The 328 works. 

      ERRATA : I fried the logic chips with 5V :(. Resoldered new ones and looks good.  I think I need to be feeding in a signal that has already been digitized (like by a comparator). Otherwise I need to mess around with knobs to get the signal right around the threshold of the logic gates with bias setup. 

      Good news: The 328 works. And I can see the effect of selecting different filters. I’m not sure why but it works best when the signal is coming in on A and I’m taking the output on B (or vice versa). I’ve also got a cap going from the output of the filter board before amplifying it again.

      ERRATA: I ordered the wrong length of bussed resistor network. 

      Good news: The 328 works. 

      errata ^ Wrong footprint (and value!) for the digital potentiometer here… Will have to wait for the correct part to test this.

      Good news: The 328 works and at least it produces an image !

      errata ^ H SYNC and V SYNC plugged in to wrong pins on Arduino (should be PD3 and PB1 respectively).

      Good news: The 328 works.

      ERRATA : the PD pin (which enables ADC IOs when low) is pulled HIGH ! I resoldered it and now it’s working great. 

      I chose a non PWM pin on the atmega to be the voltage control pin of the VCO… I soldered it to the nextdoor pin which can do PWM and all is good. 

       

      ERRATA: I tried two chips, they both come up as unidentified FRAM when I have them speak on the serial running the demo codes…I should probably pull Write Protect (WP) HIGH just in case. Still not working…I will try replacing with a 23LC1024 serial SPI SRAM as it has the same pinout. 

      ***EDIT: Just saw this on the Adafruit website : “For the 4Mbit version, you should change this to: fram.begin(3)”…Still doesn’t work though.

      I replaced with the 23LC1024 and am using the SRAMsimple libary which appears to work well. For some reason the digitalRead I’m doing in the setup is always returning 0 even if connected to 5V.

      #include <SRAMsimple.h>
      #defineCSPIN8       // Default Chip Select Line for Uno (change as needed)
      SRAMsimple sram;       //initialize an instance of this class
      /*******  Set up code to define variables and start the SCI and SPI serial interfaces  *****/
      voidsetup()
      {
      uint32_t address = 0;                       // create a 32 bit variable to hold the address (uint32_t=long)
      Serial.begin(9600);                         // set communication speed for the serial monitor
      SPI.begin();                                // start communicating with the memory chip
        // And now the fun begins:
      /**********Write a Single Byte *******************/
      bool data = digitalRead(A0);                        // initialize the data
      for(int i = 0; i <=5; i++){                 // Let's write 5 individual bytes to memory
          address = i;                              // use the loop counter as the address
      sram.WriteByte(address, byte(data));            // now write the data to that address
          data+=2;                                  // increment the data by 2
      }
      /********* Read a single Byte *********************/
      Serial.println("Reading each data byte individually: ");
        byte value;                                 // create variable to hold the data value read
      for(int i = 0; i <=5; i++){                 // start at memory location 0 and end at 5
          address = i;                              // use the loop counter as the memory address
          value = sram.ReadByte(address);           // reads a byte of data at that memory location
      Serial.println(value);                    // Let's see what we got
      }
      }

      Not sure why…

      *EDIT: Got the thing working with Fabien’s help !  

      
      #include <SPI.h>
      #include <SRAM_23LC.h>
      #define SPI_PERIPHERAL SPI
      #define CHIP_SELECT_PIN 8
      
      SRAM_23LC SRAM(&SPI_PERIPHERAL, CHIP_SELECT_PIN, SRAM_23LC1024);
      
      #define START_ADDRESS 0
      
      void setup(void)
      {
      pinMode(2, OUTPUT); // where we write the recorded data to.
      pinMode(A2, INPUT);
      SRAM.begin();
      }
      
      void loop(void)
      {
      for(unsigned long i=0; i<128000; i++)
      {
      byte val;
      if ( (PINC & (1 << PINC2)) == (1 << PINC2) ) {
      val = 255; // pin is high
      }
      else {
      val = 0; // pin is low
      }
      SRAM.writeByte(START_ADDRESS + i, val);
      }
      
      delayMicroseconds(1);
      
      for(unsigned long i=0; i<128000; i++)
      {
      byte ch = SRAM.readByte(START_ADDRESS + i);
      PORTD = ch;
      }
      
      delayMicroseconds(1);
      }

      However in this byte write/read mode the fastest I can get it going is 10KHz…The next step is to use this SPI tutorial (https://docs.arduino.cc/tutorials/generic/introduction-to-the-serial-peripheral-interface) and the SRAM datasheet ( https://ww1.microchip.com/downloads/aemDocuments/documents/MPD/ProductDocuments/DataSheets/23A1024-23LC1024-1-Mbit-SPI-Serial-SRAM-with-SDI-and-SQI-Interface-DS20005142.pdf) to operate in “sequential operation” mode where pages are ignored and its all just one big array. 

      I have tried to do this but haven’t yet succeeded. I can successfully write and read from the memory with the code below..:

      #define DATAOUT 11//MOSI
      #define DATAIN 12//MISO
      #define SPICLOCK 13//sck
      #define CHIPSELECT 8//ss
      
      //opcodes
      #define READ 0x03 // read data
      #define WRITE 0x02 // write data
      #define WRMR 0x01 // write to the Mode Register
      
      //modes
      #define SEQUENTIAL 0x20 // 0100000 in Binary
      
      byte clr;
      
      byte address0 = 0;
      byte address1 = 0;
      byte address2 = 0;
      
      byte data_to_write = 0;
      byte data_to_read = 0;
      
      char spi_transfer(volatile byte data)
      {
      SPDR = data; // Start the transmission
      while (!(SPSR & (1<<SPIF))) // Wait the end of the transmission
      {
      };
      return SPDR; // return the received byte
      }
      
      void setup(void)
      {
      
      pinMode(DATAOUT, OUTPUT);
      pinMode(DATAIN, INPUT);
      pinMode(SPICLOCK,OUTPUT);
      pinMode(CHIPSELECT,OUTPUT);
      digitalWrite(CHIPSELECT,HIGH); //disable device
      pinMode(2, OUTPUT); // where we write the recorded data to.
      //pinMode(10, OUTPUT); // LED
      pinMode(A2, INPUT); // where we read the data from
      // SPCR = 01010000
      //interrupt disabled,spi enabled,msb 1st,controller,clk low when idle,
      //sample on leading edge of clk,system clock/4 rate (fastest)
      SPCR = (1<<SPE)|(1<<MSTR);
      clr=SPSR;
      clr=SPDR;
      
      digitalWrite(CHIPSELECT,LOW);
      spi_transfer(WRMR); // access the Mode Register
      spi_transfer(SEQUENTIAL);//enter Sequential Mode
      digitalWrite(CHIPSELECT,HIGH); //disable device
      }
      void loop(void)
      {
      //WRITE
      digitalWrite(CHIPSELECT,LOW);
      spi_transfer(WRITE);
      spi_transfer(address0);
      spi_transfer(address1);
      spi_transfer(address2);
      
      for(unsigned long i=0; i<128000; i++) // address is automatically incremented internally in the SRAM in this mode
      {
      if ( (PINC & (1 << PINC2)) == (1 << PINC2) ) {
      data_to_write = 255; // pin is high
      } 
      else {
      data_to_write = 0; // pin is low
      }
      spi_transfer(data_to_write);
      }
      digitalWrite(CHIPSELECT,HIGH);
      
      //READ
      digitalWrite(CHIPSELECT,LOW);
      spi_transfer(READ); //transmit read opcode
      spi_transfer(address0);
      spi_transfer(address1);
      spi_transfer(address2); // 24 bit address in three parts (this could be a problem)
      
      for(unsigned long i=0; i<128000; i++)
      {
      data_to_read = spi_transfer(0xFF); //get data byte
      PORTD = data_to_read;
      }
      digitalWrite(CHIPSELECT,HIGH); //release chip, signal end transfer
      }

      …but when I do this in chunks with loops it doesn’t appear to work. I’m not sure if it’s because I’m reading the value of the pin during the writing and if I should perhaps do this before with a buffer array and then just read from it ?

      OVERALL ERRATA : I also need some kind of power board that distributes 5V and 3.3V 

      ***

      On the back of the boards I tried an experiment using the bmp import ULP in Eagle. Not sure what the results will look like :

         An

      **** 

      I also starting thinking that I should probably look at more existing DIY and pro analog video synth circuits…

      A collection of great video synthesizer schematics resources : https://scanlines.xyz/t/diy-resources-file-system/224

      Here are some of the ICs (that are still being manufactured) that I haven’t work with before that appear in several designs :

      • Resettable and retriggerable Monostable Multivibrators : https://assets.nexperia.com/documents/data-sheet/74HC4538.pdf
      • High speed diff comparators : https://www.ti.com/lit/ds/snosbj5c/snosbj5c.pdf?HQS=dis-mous-null-mousermode-dsf-pf-null-wwe&ts=1676232730602&ref_url=https%253A%252F%252Fwww.mouser.fr%252F
      • Video Fader IC: https://www.analog.com/media/en/technical-documentation/data-sheets/12516fa.pdf
      • Graphic EQ display filter : https://www.sparkfun.com/products/10468

      To divide a signal into 8 different bands (if you skip the MUX at the end) :

      Here’s a simple implementation with a 4051 analog mux at the end :

      This worked after I sorted out that the Atmega 328 reset was pulled LOW all the time – so it programmed fine but never did anything after that. I also removed the op amps which were supposed to follow the selected thresholds, I connected the top and bottom directly to the pots in the end. I tried slowly switching between bands at half a second and also faster at 50ms. Both as expected.

      And I’m revisiting all kinds of combined capacitor + switch circuits which move tiny charges around based on signals  :

      • sample and hold 
      • bucket brigade
      • comb filter 
      • switched capacitor circuit

       I have made this bucket brigade “delay” with 50 microchip tunable (variable) 100-200pF capacitors :

      I am now curious about some other capacitor switching circuits like this Comb Filter : https://en.wikipedia.org/wiki/Comb_filter which somehow “provides response” at different multiples of 1KHz depending on 3 bit code. All the caps are the same value.

      Here is another circuit design for the same function :

      Block diagram of comb filter including the CMOS multiplexers and the... | Download Scientific Diagram

      ****

      For the FPGA board, I’ve ordered an iCE40HX1K development board and am currently planning to test some basic VGA signal generation. The next steps could involve basing a design off of the OLIMEX dev board design (https://github.com/OLIMEX/iCE40HX1K-EVB/blob/master/ICE40-1KEVB_Rev_A.pdf) which already has SRAM and VGA OUT along with code on the internet (which I would follow closely for the first iteration). I would alter the board to be able to program directly via USB using the components from the Ice40 stick ( https://www.mouser.fr/new/lattice-semiconductor/lattice-icestick-kit/), like a fancy new FTDI chip, so I could stay within the Lattice software for my first steps. 

      Compared to the VGAX, the FPGA could generate signals much faster (being clocked with a 100MHz crystal versus the 16MHz of the Atmega), it would also be producing signals based on a a different coding paradigm (I have no idea what that would mean in terms of images), and because it has around 90 I/O it could also work with super deep colors using only a R2R ladder. The possibility of using an SDRAM is so cool but it seems hard to implement, with SRAM being much simpler to interface. The OLIMEX has only 512KB of SRAM, so I couldn’t really record a lot with it. 

      ****

      Here is my process for the FPGA programming so far :

      1. I signed up for an account at www.latticesemi.com.
      2. I got a licence for iCEcube2, put it somewhere easy to find and took note of the directory, and downloaded iCEcube2 and the Lattice Diamond software from here : https://www.latticesemi.com/en/Products/DesignSoftwareAndIP
      3. I plugged in the iCEstick and it blinked in a circular pattern. I also checked that it had a port under Device Manager (it had 2!). 
      4. I went into iCEcube2 then to Help > Tutorial to open a pdf called “Implementing the Design” and followed the following steps :
        1. Start new project (iCE40, HX1K, ?TQ144?)
        2. Add Design file iCElab.v and Constraint file iCElab.sdc and checked the Device Info.
        3. Run Synplify Pro Synthesis
        4. Select Implementation
        5. Add constraint file iCElab.pcf under Import P&R Input Files.
        6. Run Placer
        7. Check the Floorplan, package view, timing analysis, power estimation
        8. Generate the bitmap (.bit and .hex files) which is saved wherever the project was saved. (For instance C:\Users\Jonah\Desktop\FPGA LATTICE DEMO PROJECTS\quick_start\quick_start\quick_start_Implmnt\sbt\outputs\bitmap).
        9. Here is what everything should look like once finished :
      5. I then transitioned to Youtube for a detailed explaination of using Diamond Programmer with the iCEstick here : https://www.youtube.com/watch?v=Df9k1T0bHmA&ab_channel=Dom
        1. Launch Diamond Programmer and take the default options (or click scan and take those)
        2. It will mistake the board for a JTAG interface and give the following errors : “Failed to scan board”, “Scan Failed – Creating Blank Programmer Project.”
        3. Now change the Device Family to iCE40, the device to iCE40HX1K, and under Program enter the following information :
          1. Change Access mode to SPI Flash Programming and now some other options appear. Select > Vendor: Micron, Device: N25Q032, Package:  8-pin VDFPN8
          2. Now load the bitmap (.bin) file and check that it has a non-zero datasize :
          3. Click OK and then click the green traffic light on the next to top row of icons. You should then see a completion message and have the program on your board :
          4. Presto !

      Just for info :

      For the actual pinout of the ice40 (which you can change in Pin Constraints Editor):

      Generating your own .v file, you can open Notepad++ and paste :

      module AND( input A, input B, output Y ); assign Y = A&B; endmodule

      ***

       

      Here’s what ended up getting presented :

      Here is the text I made to go with it :

      La prĂ©paration d’un piano est l’action expĂ©rimentale d’ouvrir le couvercle du piano et de placer des objets (des vis, par exemple) entre les cordes. Ces « prĂ©parations » modifient la vibration des cordes et peuvent provoquer de nouveaux sons, parfois des sons de batterie plus du piano. Post-prĂ©paration, le pianiste peut composer une partition qui exploite les nouvelles modalitĂ©s soniques dĂ©couvertes, entrant en dialogue crĂ©atif avec l’instrument. L’acte d’intervenir et de dĂ©tourner le fonctionnement du piano encourage le pianiste Ă  comprendre le fonctionnement de leur instrument d’une maniĂšre concrĂšte et recadre l’instrument en tant que site d’expĂ©rimentation crĂ©ative, menant souvent Ă  des dĂ©couvertes inopinĂ©es, bien que fugaces, dans un processus artistique ouvert et indĂ©terminĂ©.
      Ce projet reprĂ©sente une tentative (ambitieuse) de fabriquer, et ensuite de « jouer » avec, un type d’écran prĂ©parĂ©. Les signaux Ă©lectroniques qui passent entre le laptop et l’écran ici sont comparables aux vibrations qui voyagent dans les cordes du ventre du piano. De la mĂȘme maniĂšre qu’une vis peut modifier le son gĂ©nĂ©rĂ© par l’activation d’une touche du piano, nous pouvons attĂ©nuer et amplifier sĂ©lectivement les voies de signaux Ă©lectroniques pour produire de nouveaux stimuli (en forme d’images cette fois).
      Notre quĂȘte pour rĂ©pertorier des prĂ©parations vidĂ©o possibles, et pour documenter leur fonctionnement, nous a menĂ© Ă  la rencontre de filtres artisanaux montĂ©s sur bois, qui Ă©voquent les radios fait maison des annĂ©es 1950s, ainsi que les technologies moins abordables et plus sophistiquĂ©es comme les FPGA (des circuits intĂ©grĂ©s de logiques programmables). Ces prototypes sont fixĂ©s dans l’arriĂšre-plan et ont vocation de rappeler le caractĂšre expĂ©rimental et ludique du projet de recherche.
      En clin d’Ɠil au monde de la synthĂšse modulaire audio, qui prend souvent une esthĂ©tique punk, nous avons fixĂ© un enchainement de modules de prĂ©paration vidĂ©o au premier plan. En concatĂ©nant des modules, tel que les filtres Ă  capacitĂ©s commutĂ©es, des mĂ©moires vives statiques, des convertisseurs analogique-numĂ©rique, des portes logiques combinatoires, et encore d’autres, nous pouvons dĂ©laminer les flux vidĂ©o, crĂ©er de nouvelles voies Ă©lectroniques, tordre, caresser et dĂ©former des signaux, les synthĂ©tiser, et finalement les tresser ensemble, avec plus ou moins de finesse, et observer les rĂ©sultats en temps-rĂ©el.
                                                                                                  ***
      A prepared piano is the result of opening up a piano and placing objects (often bolts and screws) between the piano strings. “Preparations” modify the sound of a vibrating piano string to create new sounds, sometimes more resembling a drum than a traditional piano. After a piano has been prepared, a score is developed to explore the new qualities of the instrument. Instrument preparation invites a musician to engage with and understand the inner working of their instrument, literally getting their hands inside the body of the instrument. Preparation reframes the instrument itself as a site of creative experimentation, often leading to serendipitous discovery in an exhilarating, and at times painfully anxious making (!), open-ended design process.
      This work is an attempt at making a kind of prepared computer monitor. The electrical signals passing between the laptop and the monitor are analogous to the vibrations inside the strings within the belly of the piano. Just like a bolt can create a new type of sound in the prepared piano, we can similarly dampen and accentuate the video signal pathways of the prepared computer monitor to create new types of image transformations that play out in time for our eyes.
      Our journey to explore a range of possible preparations and document their effects has taken us to different eras of technology, from simple, artisanal high pass filters mounted on nails in wood, to more sophisticated technologies like the Field Programmable Gate Array (FPGA). These exploratory prototypes are visible on the backplane and emphasize the importance of the process in this artistic research project.
      In a nod to the world of modular audio synthesis, we are displaying one of many different possible concatenations, or “patches” as they are known, of our video preparation modules in the foreground. By linking together various microchip-controlled switched capacitor filters, static RAM delay modules, Analog to Digital converters, combinatorial logic boards, and other circuits, we can playfully delaminate a video signal, open up different signal pathways, bend and warp signals, synthesize new ones altogether, and finally braid these all together on screen and observe the results.
      ***

      My takeaways :

      Do something simple, and humble, but try to do it well. Trying to do too many things, or a “universal” thing, or a multi-functional reprogrammable thing is really ambitious. This has happened to me before :

      • At the Barilla Hackathon (the team that did the best made a simple lunch surface, it was simple but really well made and designed). 
      • With my solar robot project (the one that was supposed to run on solar energy and no battery, interact with other robots, and possibly build a structure)
      • With my original solar sunflower design that was supposed to look super intricate.

      Making a machine that works for a demo is the highest level of challenge. It requires you to master the functining of the machine to a high degree to be able to fix it and adapt in changing conditions. It you do something simple, you have a higher chance of being able to do this.

      It would have been important to realize that the place this was to be shown is a corporate environment, and that my interest in the bodge / bricolage would never have found its place here. The corporate mentality is shiny, new, pro-tech, and “impressive”. I should have understood this before taking the project. 

      The simple, distilled, purified, humble and clear idea from this project was the wooden-mounted electronic circuits. This would have been in line with my “design research” interests, my aesthetic.

      If I were to make a complex machine like the one I had in mind for this expo that would have worked, I think I would have to change the following things :

      • Generate my own VGA signals. For plug and play things, generating this in software seems so much easier because you are the one making it and you have control over what is being produced. 
      • Figure out, once and for all, the story around shared grounds and blocking caps, and bias pots, and voltage in and voltage out levels, for different modules. Also, 75ohm resistors and small caps before VGA out ? Should I just get a VGA driver chip that works? (EDIT: Here is an explaination of how to calculate the output impedence for VGA cables : https://hackaday.io/project/18682-pic-graphics-demo/log/49786-vga-interface)
      • I would need to figure out what makes the VGA monitor turn off (is it sending something it doesn’t consider a video, or a voltage level that is too high?)

      I think the alternative, which would be showing pre-recorded videos, is uninteresting for a performance. Another key ingredient I think is having designers / artists to help me review the project regularly (like in design school). It should also be really clear to me if it is my design project or a commission (in which case I’m an engineer I guess?). I should also get clear right from the begining next time what are the conditions of the final thing – where will it be, what are the goals of the person commissioning the work, etc.). I should probably only work with people who share my interests and aesthetic ! 

      I think I have to acknowledge that I have an extremely constrained working process that is highly method driven. I am not focused so much on the end product directly. My friend suggested I was over constraining myself. Basically there is a confusion between whether I’m using technology to stumble upon unexpected things, or whether I’m using it to make something that works. To work efficiently on things would work well would require time developing the things that must work well, and an organized, systematic working practice. I MUST ORGANIZE MY ELECTRONIC PARTS to make this process more efficient.

      Also : all the intense pressure and hardcore work streaks I put in DID NOT HELP THE FINAL PROJECT – I can’t even think straight or debug basic circuits right now :(. It would have been better to perhaps start working on the final thing starting on day 1, with the EASIEST, SIMPLEST, AND MOST LIKELY TO WORK PAINLESSLY solutions. 

      Another key question is what is the output, and who is my audience ? I need a way of mesuring my output and comparing it. 

      • Am I making art for people who consume art ? (then I have to move towards very simple projects and focus on their EXECUTION while photographing everything super well for my PORTFOLIO)
      • Am I making “design research” papers/talks for academics and people who consume this ? (then I need to WRITE about my research)
      • Am I making open-sourced electronics kits for hobbyists ? (Then I need to spend time ENGINEERING working kits that people would be interested in making)
      • Am I making workshops for designers ? (Then I need to come up with simple exercises for workshops?)

      And am I doing several of these things simoultaneously ? I think doing any one of them well first could take a lifetime already ! My friend suggested projecting five years in the future to where I would like to be and building backwards from there. I think I would most like to be a teacher who does art/design research in the form of expos, articles and classes (a bit like Andrew Witt at the GSD).

      ********

      Where I would like to go from here :

      1. Test my basic FPGA VGA board. What can it do with video ? Possibly make another pro version (USB programmale, nicely laid out, SRAM). FPGAs feel like the future because they are good a processing video in parallel, and because coding them is essentially like building 74 series logic circuits but without all the soldering. It could also lead to some cool machine learning experiments later on..
      2. Test my automatable SRAM 4MB board. What kind of automatic looping can it make?
      3. Try to get the SPI SRAM board functioning (it is so simple it would be perfect for a video sampling workshop). It would be cool to see what kinds of images it produces. It works at 20MHz, it would be perfect !
      4. Get Spaghettini working with aluminum board (just avoid going through-hole) – this is the simplest way to generate cool simple memory based video !
      5. Have another stab at presenting my work as an art installation at my show end of march at La GĂ©nĂ©rale. 
      6. Try the bucket brigade and digitally controlled pot boards

      *******

        After my colleague Fabien told me about EDID EEPROMs, I am thinking it could be possible to mess with the memory of this EEPROM that communicates with the computer sending VGA signals and create some interesting glitches this way : https://en.wikipedia.org/wiki/Extended_Display_Identification_Data

        Also check out these types of RAM : 

        • https://en.wikipedia.org/wiki/Dual-ported_RAM
        • https://en.wikipedia.org/wiki/GDDR_SDRAM

        And this keeps coming up when looking into controlling screen rows and columns directly : https://en.wikipedia.org/wiki/Low-voltage_differential_signaling

        Check out no input mixing and electro-acoustic musique concrete, and machine exorcism. 

        Check out universal LCD driver IC RTD2556 on boards like this :

        ***

        It looks like I could build my own HMDI to VGA converter with two AD ICs : https://www.analog.com/en/analog-dialogue/articles/hdmi-made-easy.html

        I could combine this with a new board that uses a bunch of SPI SRAM memory chips controlled by arduino to approximate the 7 channel 4MB recording and mixing board I made. 

        I could also put a rasbpi zero with just power, an SD card containing videos and an HDMI mini out. For the Raspberry Pi I made the HDMI hot pluggable (hdmi_force_hotplug=1) and put a bunch of low res mp4 videos in the boot SD card which are accessible.

        Choreographable Video Synth

         This circuit is a next version from the video synth. 

        Some ideas from how this installation could look like :

        Messing around with my last synths, here are some circuits that I want to be able to reproduce with my new synth :

           

        Here are some ideas of how the circuit could take form :

        A Nintendo gameboy catridge teardown :

        Some sketches of possible configurations :

        *******

        I am currently splitting the project into two parts : 

        PART 1 : A series of independent transforming modules, VGA IN/OUT with screens, and oscillators with patch cables.

        PART 2: A board called palĂ­mpsĂȘst.OS which is a rack (or archive) of several 16MB memory modules. 

        ***********

        Palimpsest.OS

        Each memory will share the same power (5V, 3.3V, GND), timing CLK signals, control signals (to enable/disable counters, buffers, RAM, ADC etc. and to RESET things). All this can be automatically controlled by an microchip which can turn on/off these memory banks individually in time. Despite this there will be basically all the components on the board to make it function independently and, most importantly, test and debug it’s functioning. 

        Just like for the previous memory board, the following parameters will be modifiable :

        • the duration of the recording and playback,
        • the sequencing of addressing this memory,
        • the amplification of the incoming and outgoing video data,
        • the sampling rate and sampling pattern of video recording and playback,
        • the bit resolution of the recording and playback,
        • the continuity of the above processes or the frequency of their interruption

        I have corrected the errata from the previous 16MB memory board, removed jumpers (as this board will be made by JLC PCB), added a ground plane, made it more compact (by removing the burst record functionality, level shifting, and having two layers). I also added a battery so that memory is persistent as long as the battery has juice. The main work however has been breaking out pins to a bus which can be controlled by a microcontroller. There is now the possibility to have 3 memory boards A,B and C, and to control their recording and playback, and all the parameters of these two things that can easily be controlled, in time. 

        With these boards it should be possible to take an input, record it, then play it back and mix it with the input through a feedback pot. Because this can be done by three memories, they can also record their respective outputs and layer without any mixing with the VGA . 

        *****

        01/12/2022 UPDATE :

        So far debugging: For some reason the ADC is not spitting out anything, regardless of what I feed it. I changed the input op amp and it had no effect. Previously to soldering the ADC everything seemed to be working…As far as I can tell the memory is working and all the bias pots too.

        ERRATA :

        -The direction pin of the 245 buffer connecting to the R2 ladder is wrong – it should be HIGH instead of LOW.  To temporarily correct this involves jumping the DIR pin to VCC – AND CRUCIALLY – to ALSO disconnect this pin from GND unless you will have a short.****

        -Why on earth did I connect all the pins without dip switches (ADC EN, 1/0 0-7, etc.) from the memory boards together ? This makes it impossible to record on one board and not on the others. I cut the non-DIP’d traces and it seems to work. 

        -the LED needs a current limiting resistor or it just explodes.

        -one switch for master record (WR EN and ADC EN)?

        -I should follow the ADC1175 instructions and isolate the DGND and AGND with caps. 

        -Should have an input pin and 5V pin for testing on board.

        -I should add the right footprint for a big capacitor at the input of the ADC (I forgot and put a 0.1uF which didn’t work).

        -It would be super cool to have a coarse and fine knob (and or a super precise pot) for the VCO for instance on the base board. 

        -I should take the classic gameboy battery footprint.

        -There isn’t an extra pin so I can send V SYNC both to be frequency divided and pass it on to the VGA out. 

        -The populated side of the memory PCB is facing “backwards” with regards to the base board…

        -The LDO pinout on the base board is wrong

        -I can’t plug in standard jumper headers to the PCIe breakout pins because they are a different diameter

        -I tried hard syncing the VGA’s H Sync with the 4046 ( see text in description of video here : https://www.youtube.com/watch?v=S694YY7sJMw&ab_channel=drumasaurusrex ). It only works with the V Sync but that’s too slow. I can’t get a stable signal out, it looks super wobly at high frequencies.  

        *****

        TESTING THE PALIMSEST.OS

        • Not sure why but it seems like I can’t record only on one board when multiple boards are connected. I have to disconnect all but the board I want to record on to get a recording onto it. *EDIT* Because I connected all the non-dipped pins from the boards together via the PCI-E bus…
        • It would be super cool to be able to send different clock signals to each board. I should maybe not have made the same CLK hardwired to each board. 
        • It’s not possible to turn the knobs when then three boards are plugged in at once because the pot shafts are too long. 
        • Not sure exactly how the battery is working, it seems like it can “remember” something for a few minutes at least. 
        • It’s hard to palimpsest various things together – You have to get one board all calibrated, then send it something from another calibrated board, record it, then rewrite to play it back. (I am hoping the new 8 channel 1 bit device makes things easier). 
        • I can’t automatically have things read or write currently, not sure why it’s not working…
        • I can’t echo with this board because I can’t simoultaneously read and write. That said I can mix a recording with live channel and then record that together into a memory and begin layering. 
        • I would like to have the image stay stable instead of always jumping everywhere. 
        • Dephasing the ADC and RAM clocks makesa large variety of nice patterns on the output !
        • It would be nice to be able to count up and down and do that to 4 bits in the middle of memory !
        • remember to connect GNDs if using memory board with analog f(x) for example
        • Trying to hard sync with h sync and cd4046 based on these links (https://www.renesas.com/us/en/document/oth/tb476regenerating-hsync-corrupted-sog-or-csync-during-vsync and https://www.youtube.com/watch?v=5VymS65eefo&ab_channel=drumasaurusrex)… I think the solution might be an oscillator in a can (with 4 not 2 leads), which I can then divide. (I can still have a free style VCO with knob to control the sampling of the ADC though !)
        • Works great with a four lead crystal oscillator can and the f divider – a very clean image that doesn’t warp ! You can still use the knob controlled high speed VCO to trigger the ADC and it’s a nice combo. 
        • *****WOW – feeding in a quartz can 10MHz into a frequency divider (and sending diff divisions to the SRAM clock), and hooking up V Sync directly to the reset, produces a really stable image that doesn’t slide left or right !!!****
        • ***ABOVE ALSO WORKS WITH H SYNC AT LOWER FREQUENCIES – SOOO COOOL : D !!
        • I’m not able to use MOSFETs or transistors to reliably automate the switch from REC to PB for some reason. I’ve even tried using an optocoupler to isolate the arduino and also tried using and AND gate as a buffer with the WR signal but neither work. I think should use mechanical relays to get around this problem or just avoid it all together by having Arduino send the CLK and WR signals in the next version. 
        • Tying differnt oscillator cans (10MHz, 12MHz, and 40MHz) 12 is nice because it doesn’t jump too much on my screen resolution (800×600). At 1280×720, 10MHz is nicest. 
        • I did a proof of concept for the 8 track recording and rerecodording idea, it seems to work though there may be a bit of interference from neighbouring channels on one another ? Not sure how I would try to isolate them from one another but some bleeding might actually be cool ?
        • I tried doing a feedback recording (recording a mix of a play back and a live feed) and had no success. Not sure why this isn’t working.

        ***********

        Realizing that this whole massive multi-module thing could be made with just one memory module having feedback !!! That or a simple echo IC like this one I ordered (BU9253 : https://www.mouser.fr/datasheet/2/348/rohm_semiconductor_rohms16891-1-1742621.pdf ) :

        That said the delay is only 8Kbits and it’s designed for audio.

        *****

        Analog Functions Board :

        Trying to remake the previous analog functions board but at JLC and as pro-style as I can. The general idea is to make a bunch of op-amp circuits that modify video in various ways and that can be combined with the logic modification board to make a completely full suite of electronics video transformations. Not sure yet how they could be automated.

        Fixes from previous esceptionally newbie laser engraved version :

        • +15/-15V supply for all the op-amps using the handy ICL7660 negative voltage generating IC will hopefully solve many issues.
        • Using normal general purpose op amps in addition to super fast video ones 
        • Having bias pots at the inputs and outputs to sort out any different in offsets. 
        • Doing more research to get better circuit designs, notably looking at the Analog Thing, The Hackaday Logic Noise Series, Rod Elliott’s active op-amp series.
        • Making things less noisy with : seperated AGND and DGND, caps near op amps, following suggested board layouts, 2 sided board with GND plane (!)
        • Tying to take into account impedence matching with 75ohm VGA camble at the input and output and testing a specialized video line driver IC
        • Making op amp board with the possibility of automating thier switching / pot levels ?
        • Adding over-amped fuz circuit, phase-shifter, and various filters (LP, HP, BP, Notch), and adding a reset to the integrator circuit. 

        I think the theme of this board, especially seeing as I have 25 of these TL074 op amps, is showing the diversity of flavours (and range of sometimes exotic circuits) of the history of op amp filters, arithmatic, etc. circuits. I plan on highlighting the names (and dates?) somehow.

        The idea has clarified now, it will be a grid of 24 different op amp circuits in a 6 by 4 grid with the name of each circuit and a letter/number identifier. At the top will be all the power, VGA in out and bias amps.

        I collected the circuits from various places (AoE among them) but especially from Rod Elliott’s write up on active filters (which you can access with Internet Archive) : http://sound.westhost.com/articles/active-filters.htm

        I am most excited about the combination of digital and analog – like in the switched cap filter, sample and hold, resettable integrator, and demux amp circuits. Being able to modify the functioning of am amp with digital signals (even with a tunable capacity and voltage controlled potentiometer) seems to offer really cool potential. This being combined with SRAM could be a really cool composite project.

        ERRATA :

        • VCCIO and GND directly overlapping on top layer  (near A2/A3) :/
        • the preamp in and out and misaligned 
        • Should have included blocking capacitors
        • VGA not being recognized by my computer with driver chip 
        • Should have included an inductor circuit
        • awful humming from the negative 12V generator
        • not enough room for 220uF caps for the video driver on board
        • some kind of “pass through” switch would be useful to show what the input looks like
        • the driver IC can only accept one color for some reason…I should not include it next time
        • the female – female jumpers are not reliable and lead to weak contacts…maybe going towards jumpers?
        • The thing is long to set up – it’s not plug and play and is finicky for demos
        • Learn about the safety of hot plugging
        • The Voltage Control works a litte, with a 1k8 resistor and picking the right voltage range. But it is not reliable, I should move to pot ICs for the next version. 

         

        • A0  with a 200uF cap after the final amp has some filtering output
        • A1  just tears the left side of the screen
        • A2  nothing happening
        • A3 varies nicely with different frequencies, though sometimes just looks like it’s “adding” frequency pattern to input
        • A4 I think the original comparator design (with 1K resistor going to VCC and pot with middle shorted to GND going to GND is correct and this one wrong)
        • A5 same note as above, but preamp in and upper seem to work. Perhaps the best way to get abstract forms from input super easily. 
        • B0 Not working…
        • B1 nice filtering !
        • B2 needs blocking cap on output or else produces nothing. Goes from filtering to almost comparator like behaviour.
        • B3 needs a cap on output and >20MHz to produce anything, no relation to input though ?
        • B4 creates a cool zebra repeating effect at one extreme
        • B5 great filter !! Both knobs do things and there is great range.
        • C0 nothing cool happening here…Seems just to pass on a modified version of the digital in signal ?
        • C1 top knob needs resoldering. Only does stuff when top knob fully to one side then behaves a bit like A3 but can go down to low frequencies on digital in.
        • C2 Cool zebra like filtering (like B4 but messier and less repetitive.
        • C3 nothing happening…
        • C4 faintest image at one extreme
        • C5 nice filter (like B5) ! Only top knob seems to do cool stuff though. (Other knob goes haywire at one extreme).
        • D0 barely the faintest image at low frequencies…
        • D1 the HP inverts the input !
        • D2 Does add when the knobs are set right. I put a cap on the function generator input.
        • D3 Does kind of subtract ! Can invert or not.
        • D4 makes a banding across the screen, not sure what effect the 3 binary inputs have…
        • D5 doesn’t really work but with the second multiplier input floating you can touch it and send the thing into an overdrive momentarily. 

        *********

        Notes from Museum visits :

        Composite (wood, porcelaine, gold) in flat, relief, and form of object.

        Could I have both feathery frilly fuzzy video mixed with crisp solid geometric form to create similar layering ?
        Some video noise looks like different types of stone
        Rococo / Baroque video ?
        Decorative video?
        High quality video / image capture ?
        Once I’ve finished with this round of tools, I have to compose more !!

        Can I mirror an image half way to make a Rorschach like ink splot ?

        Wicker chair silhouette series, pumpkins 
        Some format of showing the circuit and the output that can end up in a book
        Shoot my own video to mess with

        Layering

        Contour
        Surface
        Saturation
        Flow vs. Choppiness
        Look at Photoshop for 
        Roughness, relief 
        Edges versus centers 

        Movement vs stasis 

        Enriching of detail possible ?
        Abstracting, cosmic making
        Fine lines versus coarse
        Exposure 
        Color fields
        Texture
        Deep friedness
        Films of cows, ocean. Stills of still life? Flowers, birds, drapes folding, mold, fruit, bones
        Color mixing vs melting vs meeting
        Paint viscosity (runny vs clotted)
        Direction of brush strokes 
        Contour
        Focus direction in canvas
        Translucent flesh, shine vs glow from interior, waxiness 
        Graininess 
        Composition, color pairings and form
        Foreground displaced to background vice versa 
        Meeting pattern planes 
        Lighting and shadow
        Illusion of depth
        Cloudiness 
        *****
        IDEA : I could take a file, put it into the memory, and then “play” it different ways (because the width is completely arbitrary below). A file could thereby become a pattern, or a long abstract video, 

        Windows PE visualization

        Or I could put an image onto a floppy, then damage the floppy, and show how it would modify the image ?

        THINGS TO TRY:

         

        • Palimpsest.OS with arduino controlling WR and COUNTER CLK (and forgetting about CLK) to control the boards recording and playing back. 

         

        • Check out Video Effects list from Adobe Premiere : https://helpx.adobe.com/premiere-pro/using/effects.html
        • test outputting to a projector !! * EDIT * WOW this was a good idea :

        • take HDMI and mess with it digitally (but not analogically?)

        • design easier to understand / less complex board which is more plug and play ? *EDIT* Try 74*8154 16 bit counter + 32K x8 IS61C256A SRAM !
        • Take photos of boards in the light box !  

        This is what a loop sounds like :

        *****

        I’m currently working on a final set of four boards for the Choreographable Video Synth that will finish this project. 

        All the boards will have the following improvements :

        • Plug and play – very little setup time, no need for a function gen, and no fiddling to get an image on the screen for demos quickly.
        • Nice 2mm banana connectors and 30cm multi colored patch cables that make reliable connections and are more modular. (Not sure about edge connecting female plugs and edge actionnable pot knobs or vertical plugs).
        • Only the best bits of the previous boards (Analog f(x), Oc74, Palimpses.OS) in a smaller square format with playful designs.
        • The three f(x) boards will have an onboard audio amp + speaker to hear the signals you are making. A speaker hole will be present.
        • Finished product for inauguration of the IFT in early March, 75mmx75mm ans nice compositions. 
        • Make this version actually be entirely controlled by digital potentiometers and buffers and then also be able to manually control these digital devices on board with hardware switches and buttons. 

        SIGNALS IN/OUT board :

        • Takes VGA, HDMI, DVI-A in, and puts out VGA and HDMI. (Or just VGA in and out?)
        • Has a passthrough switch to see directly what’s on the screen. (Or skip this?)
        • Has a final mixing stage (especially a microcontrolled matrix mixer !!)
        • Acts as a power supply for the other boards (12V because the analog board needs this?)
        • Could take 2 VGA inputs ?
        • Has an atmega 328 to output low res H and V ?

        ANALOG F(X) board:

        • Only the four best of the 24 analog functions board. (Butterworth HP, LP, Analog MUX, ADC)

        OC74 DIGITAL F(X) board :

        • Only the best functions (comparator, DAC, S+H, XOR, Bin Counter)

        MEMORY board (OR MAYBE THIS IS A SEPERATE KIT AND I SHOULD JUST MAKE A 16MB MEMORY BOARD AGAIN?) :

        • 8 channels of 1 bit memory recording on a total of 1MBit of SRAM
        • Comparators acting as 1-bit ADCs (but maybe this belongs on another board ?)
        • A battery system that actually works (where battery and input voltage Diode-OR’d and with an ON-OFF switch to conserve batt)  !
        • Double SRAM so that I can begin messing with echo and delay, and rerecord over non-new signal channels
        • Series of 74AUP1G157GW MUX to prevent any damage to memories when recording fresh signals and to make this process automizable
        • A pulse generation setup which does not need an external function generator… (like by using an oscillator can).

        Some possible playful interface designs (I especially like the gravity effected ones) :

        ***

        Arduino controlled SRAM :

        Not yet working so going to test with two mechanical relays – this HAS to work or else I’m crazy.

        This code can get the SRAM writing :

        void setup() {
        pinMode(13, OUTPUT);
        pinMode(12, OUTPUT);
        }
        
        void loop() {
        //WRITE
        PORTB = B11101111; // CLK goes LOW/HIGH
        PORTB = B11011111; //WR goes HIGH/LOW
        }

        This code seems to work but it’s results are not predictable (I think because the code runs too slowly)… :

        unsigned long startMillis; //some global variables available anywhere in the program
        unsigned long currentMillis;
        const unsigned long period = 1000; //the value is a number of milliseconds
        int WRState = HIGH; // the current state of the WR pin
        
        void setup()
        {
        pinMode(13, OUTPUT); //WR PIN
        pinMode(12, OUTPUT); //CLK PIN
        pinMode(11, OUTPUT); //ADC EN PIN
        startMillis = millis(); //initial start time
        }
        
        void loop()
        {
        
        if(WRState == HIGH)
        {
        currentMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started)
        
        //WRITE TO SRAM
        PORTB = B11101111; // CLK goes LOW/HIGH, ADC_EN HIGH
        PORTB = B11011111; //WR goes HIGH/LOW, ADC_EN HIGH
             if (currentMillis - startMillis >= period) //test whether the period has elapsed
             {
              WRState = !WRState;
              startMillis = currentMillis; //IMPORTANT to save the start time of the current LED state.
             }
        }
        
        if(WRState == LOW)
        {
        currentMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started)
        
        // READ SRAM
        PORTB = B11100111; // CLK goes LOW/HIGH, ADC_EN LOW
        PORTB = B11110111; //WR stays high, ADC_EN LOW
        
             if (currentMillis - startMillis >= period) //test whether the period has elapsed
              {
               WRState = !WRState;
               startMillis = currentMillis; //IMPORTANT to save the start time of the current LED state.
              }
        }
        }
        

        Magnetic Media Video Synthesis

         

        I want to continue messing around with magnetic media (audio cassette players/recorders, floppy disk drives, video camcorders) and try to get them recording and playing back video.

        Here is some inspiration :

        From the timeless Hardware Hacking manual. The suggestion is to use a high gain amplifier to hear the results of the tape pickup. :

        A very cool project putting video onto a cassette :

        https://www.ubergizmo.com/2020/04/audio-cassette-tape-used-to-capture-video/

        From this reply : https://electronics.stackexchange.com/questions/108907/create-input-jack-from-tape-head

        “You can use the continuity tester to check for the ground lead. This should be connected to the metal shield of the head, you can leave it unconnected. You’ll want to connect the other two wires to your two inputs”

        From this site http://stevecoates.net/walkman/ :

        This https://makezine.com/projects/turn-old-walkman-scratchbox/ Make Magazine article connects simply :

        Four-terminal play head

        Some very cool experiments with a disconnected tape head :

        And a custom loop tape :

        **************************

        I began testing a bit, it looks like I can both see and hear the audio signals from the tape (yellow is R?, blue is L?):

        It’s most audible right near the end (the hum is the tape cassette motor spining) :

         

        *****************************************

        The method is just to power the cassette rotating motor with around 3.3V, then hook up the red(R?) or white(left?) to a probe or audio in for an amp, and then the black (GND) – which looks like it’s connected to two pins – to GND.

        The next step would be to try to amplify with a high gain op-amp circuit ? And then to begin trying to write ?

        UPDATE :

        Might be easier to work with the electronics already present on the board, learn how it works, desolder it and then put it on a breakout board to mess around with? Here is one of the simplest ICs I found on one of the dissassembled tape decks in an easy to solder SOP16 package:

        I could order a series of boards like this to make tests with them : SOIC-32, SOP-32 | SMD to DIP Adapter | SchmalzTech

        UPDATE:

        I plugged in the little audio amp into the Audio out jack of the device while I touched different pins on the IC. I found that the large slide switch on the back switched from REC to PLAY. I found that during REC mode the pins that caused the most amplification were the MIC IN and EQ IN. In PLAY mode I found the most important pin for producing output on the AUDIO OUT was LINE IN.

        I also tried connecting the little speaker amp to the REC OUT, LINE OUT while I touched various pins. 

        I was unable to amplify the tape head signals however with any of the various combinations I tried. I will try the other tape cassette circuit boards to see if I have any more luck, and also test the 2.5W power amp from Adafruit. Ideally I would be able to take an input, amplify it, send it to the tape head, then read it back by reversing the sequence after rewinding to the same section. This should also work with a strip of tape taped to a desk that I can manually run the magnet head over (right??). 

        Once I’m able to do this, I want to try the same thing (amplify an analog signal, write it to the disk through the heads directly, then read the analog signal back off it) with the Floppy Circuitry. 

        *************

        A great VCR technical reference : https://www.wikiwand.com/en/VHS

        I got my hands on a VCR, took it apart and broke out the cable coming from the helical read/write head.

         

         

        It looks like there is one little board with all the drivers for the various motors. Might be able to control it. (See this video : https://www.youtube.com/watch?v=4F7xJOb32GI&ab_channel=LifeOfDiy). I’ve got a BA6878EFV 3-phase motor driver for VTR capstan, datasheets available online. It looks like you need to plug in GND (3), 5V (2), and then connect EC(7) and HYS OUT (9) together.

        So far I haven’t been able to pick anything up on the oscilloscope from moving the tape across the print heads while listening in to various output pins.

        https://www.wikiwand.com/en/VHS#Media/File:Medion_MD8910_-_VHS_Helical_scan_tape_head-8601.jpg

        There appear to be two video heads (with two wires each – one wire for each electromagnet) and two audio heads (with one wire each) making a total of 6 wires with 1 dummy. It looks like the pinout is the following :

        1. Video Green 1
        2. Video Red 1
        3. Video Green 2
        4. Video Red 2
        5. No connection (shortened turn)
        6. Audio Red
        7. Audio Green

        It seems like others have two shortened turns to help isolate signals from one another.

        I measured the resistances between the output pins:

        1. grey 
        2. white
        3. blue(1)
        4. green
        5. yellow(1)
        6. orange
        7. red
        8. blue(2)
        9. yellow(2)

        The following are connected :

        Looking up the chip LA71750 ( Video and Audio Signal-Processing IC) – on the right in the image below – and the LA7264B (Audio Signal-Processing IC) – on the left – and checking out the datasheets and inspecting the PCB, looks like the following are the important connections :

        From the LA71750 datasheet :

         

        Would appear possible to make this pinout diagram :

        I have tried connecting pins to the oscilloscope while moving the tape head, but even at 10mV level at various time scales I can’t see anything. 

        UPDATE : Just seeing now that this chip takes control data in the form of I2C. It would be super hard for me to desolder the chip and make my own controller with it as a result.

        ******************

        I have tried amplifying and sending 20V signals at various frequencies. 

        Turning to more research for answers, check out these links :

        Article about audio sampler made from floppy :

        https://nime.pubpub.org/pub/uh76shf0/release/1

        Video made from floppy :

        Freespin is a demo made for the Commodore 1541 – no, not the computer, just the floppy drive

        For more tech info about floppy heads :

        http://forums.openmusiclabs.com/viewtopic.php?f=11&t=92&sid=9a4c3a6763f9bc02426c9d3910187e70

        ******************

        From this reading break I think the following things should be attempted :

        -with a >2W class D amp can I push some signal onto the tape that I can then read ? (Just afraid that it won’t be fast enough for video signals as it is made for audio signals ? Perhaps a high power high speed amp is even better?).

        -I could get the same preamp LA IC used in the concentric sampler paper.

        -Everyone seems to say, “try different combinations with the R/W heads” and “check continuitiy” and apply the signal to continuous wires. 

        -I could try adding the bias oscillator to the signal I’m trying to R/W?

        -I should get a super strong magnet for testing purposes

        ***********

        Looking at my floppy drive, I found the following CX20185 chip which is a Read/Write Amplifier for Floppy Disk Drive.

        It looks like the pinout is the following :

        It looks like I could read the Preamp Out pins to read from the floppy. I’m not sure how I could yet wright to the floppy without giving data to the logic on the driver.

        Here is me figuring out the pinout :

        I turned on the floppy LED I have by connecting the sixth pin next to the stepper head motor to the GND, and turned on the central motor by connecting the 8th pin to GND and plugging in 12V as well :

        When I listen in to READ DUMP A or B I can see voltage when I spin the disk manually (when I plug in the brushless motor it no longer responds to spinning):

        When I listen in to PRE OUT A or B I can see the normally high voltage go down and vary :

        Meh. 

        Some stuff about data degredation :

        https://fr.wikipedia.org/wiki/The_Disintegration_Loops

        Project Kryoflux – Part 3: Recovery in Practice

        ******

        Suggestion from research engineer at DVIC for the previous experiments:

        -For the floppy, look at the input from head (but oscilloscope will probably mess this up), preamp, and digital out (READ OUT – which should be connected directly to the chip I have the datasheet for) at same time. 

        -Basically you’re not going to see anything on the oscilloscope when looking at these electromagnets. It’s all in the very sensitive amp – so all the more reason to use the amp that comes with the device !

        -Is the preamp chip IC I am looking at even enabled ? Check POWER ON.

        -Try the floppy pinout here : https://old.pinouts.ru/HD/InternalDisk_pinout.shtml

        -For the VCR, get the thing plugged in and functioning as it was in the beginning. Observe it first, then try to intervene (you’ll never be able to reinvent the thing from nothing !)

        ****

        Listening to the DATA READ pin 33 while the disk is spinning :

        ****

        UPDATES:

        I learned from watching this (https://www.youtube.com/watch?v=DdMOGvKjrfk&ab_channel=JeffHxC2001) that the way to read is to sync the oscilloscope with the INDEX pulse. The Difference Out pin is the one being listened to in this video.

        I learned from looking more into the floppy interface that the Head Select (32) is HIGH for BOTTOM and LOW for TOP head. I also learned that Floppy Write Enable (24) is HIGH to READ and LOW to WRITE. Finally, the READY pin 34 may need to be tied to GND.

        From a Floppy Maintenance Manual showing the sequence : R/W head > Pre-Amp > Differentiator > Voltage Comparator > Time/Domain Filter > DATA OUT

        UPDATES:

        I think to make this project work, I would first need to *VERY CAREFULLY* observe the correct functioning of a working device without any changes made to it. I would need to be able to confirm completely the working of the machine, and see what signals are supposed to look like at each step. 

        Only after doing this could I start intervening in this process.

        I think Floppy is the best way to go – it’s part of the history of the computer (like all my other projects) which isn’t the case with the video recorder. The floppy is the best documented, easiest to source, and least expensive to work with. It already has a nice interface which is easy to use. It also is more standardized, unlike the many different kind of video recorders that exist. 

        What is the most standard Floppy Drive Read/Write Amplifier ? The Sony CXA series (1360, 1720, 3010, 3071, 20185, etc.) seem to have specs available online. ROHM also have BH6xxx and BA6xxx series. 

        Then again if I’m only going to be recording analog, I don’t need anything but the preamp (especially for reading) ? I could just take the tape preamps I have and put them on a breakout board ? I have BA3110, CX20023, and a CXA1262 to work with. I could try getting them to work amplifying the mic first, and also get the playback working. Then I could test putting analog signals on a floppy.

        Video synth workshop

        This workshop with La Diagonale at UP Saclay is a simple circuit to begin playing with code and screen patterns. 

        Here is the github: https://github.com/merlinmarrs/spaghettini-video-synth

        Arduino Coding and Video Synthesis Workshop

        Lean to code in C with Arduino, solder and assemble a custom printed-circuit board made in the Fablab, and make your own algorithmically-generated video art!

        This workshop is inspired by the improvisational music of Live coding (https://fr.wikipedia.org/wiki/Live_coding) and the burgeoning minimalist Bytebeats movement (https://nightmachines.tv/bytebeats-tutorial).

        Our video synthesis kit plugs in to the Arduino (https://www.arduino.cc/), a reprogrammable embedded micro-controller that can interact with the world through code, and uses the VGAX library (https://github.com/smaffer/vgax) to generate funky video.

        Meet other creative technologists and sharpen your expertise in computer sciences and electronics soldering!

        Here are some initial sketches :

        The functionality that is important is :

        -being able to select between different programs (with button and leds to indicate)

        -to be able to take audio in and have it modify the patterns on screen

        -to be able to change the colors on the go

        -I have since phased out the brightness changeability but I could add an LDR easily ?

        *******************************************************************************************

        Because our lasercutter is not operational, I am trying to make this circuit with the vinyl cutter using 5cm wide copper tape. 

         

        I am worried about the headers getting pulled out when plugging/unplugging. I will try adding some hot glue to fortify them. The other option is potting the circuit in resin but that would get messy and expensive. 

        Errata:

        -button too close to headers when glue is applied

        -remember space for audio in jack plug 

        -the two columns of headers for the Arduino should not be continuous, also unclear what is first and last pin. Also they should be SMD headers. 

        -don’t mess with RX and TX pins on the Arduino. 

        -make a version with VGA plug?

        -add text but have it cut onto plastic not made from metal

        -audio offset thing doesn’t work

        I also want to think about expandability, how could people take this project further by themselves afterwards ?

        -Having a knob  or two knobs / LDR connected to an analog in on the Arduino…

        -Be able to control the program based on voltage control levels at an input. This could mean it could even be attached to the polyphonic synth !

         

        ***************************************************************************

        Here is the next version called the Spaghettini:

        -It respects the height of the 50mm wide copper tape I have on hand.

        -It makes more sense for the audio in cable to plug in at the side and not interfere with the capacitive sensor. 

        -It uses curvy lines just for the capacitive sensing functionality and straight elsewhere which feels honest. 

        -It has the ability to modify the brightness of any of the three channels, one at a time. 

        -It has a potentiometer for analog in in adition the capacitive sensor. 

        -I’m experimenting with different patterns on the left portion.

        -The sensor works with the Arduino library CapacitiveSensor 

        And here’s what it looks like all plugged in ! (But I need to add hot glue to make it really usable)

         

        Memory Experiments (continued)

        I have two goals for this project:

        1. Finish the VGA video recorder board (with op amps, bias pots, bias for ADC) – DONE!
        2. Make a version of the vectorscope image modification series but with a raster system taking the following image as the input – DONE :

        1. Finishing the VGA Video Sampler board

        For the first goal, I need to correct that last board I made:

        Errata:

        -The gain pots for the op-amp don’t work.

        -I mixed up VCC (3.3V) and VCA (5V) in several places. (I just replaced the PFET with the LDO and manually rewired)

        -The “EN” text next to the ADC was in the wrong place. 

        -I forgot to tie down the reset of 74HC590 with a 10K resistor.

        -The 74HC04 is labelled backwards, I put inputs on the right and outputs on the left for some reason.

        Things appear to work with these changes:

        It takes some knob fiddling but I can get an input sine wave digitalized. One definitely needs an oscilloscope to see what’s happening though.

        2. Vectorscope image series

        I can either load the image into memory by playing it on a computer screen and capturing the pixels, OR, loading the image into memory with a microcontroller. I’m not sure how big I should make the image, and what dimensions, if I load the image. 

        Here is the p5.js code to take an image (called p.jpg) and print the red pixel value into a text document (called OUTPUT) with a comma and space seperator :

        let img;
        
        function preload() {
        img = loadImage('p.jpg');
        }
        
        function setup() {
        createCanvas(img.width, img.height);
        background(220);
        image(img, 0, 0);
        let writer = createWriter('OUTPUT.txt');
        
        for(var y = 0; y < height; y++) {
        for(var x = 0; x < width; x++){
        let pix = img.get(x, y);
        writer.write(pix[0] + ', '); // takes RED pixel info, adds a comma and a space
        if(!(y==1-height || x==1-width))
        {
        writer.write(pix[0]); // don't put a comma if it's the last element of the list
        }
        }
        }
        writer.close();
        }

        And here is the Arduino code to take this color information and load it into the memory space (90×90 max as PROGMEM has max 8,192 bytes max):

        byte myChar;
        
        #define IMG_WIDTH 90
        #define IMG_HEIGHT 90
        //data size=900 bytes
        const unsigned char img [IMG_HEIGHT*IMG_WIDTH] PROGMEM={
        17, 19, 19, 19, 19, 20, 20, 20, 20, 20, 21, 23, 23, 22, 21, 21, 22, 22, 21, 22, 21, 22, 21, 20, 21, 21, 23, 23, 23, 23, 23, 23, 24, 23, 25, 23, 24, 23, 25, 25, 25, 25, 25, 24, 25, 26, 24, 23, 25, 24, 23, 24, 25, 21, 20, 24, 24, 23, 20, 20, 21, 23, 22, 22, 22, 22, 22, 23, 23, 24, 23, 23, 23, 25, 23, 24, 24, 23, 24, 25, 23, 25, 25, 23, 25, 24, 24, 25, 28, 28, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 19, 35, 25, 32, 32, 26, 27, 17, 23, 27, 30, 33, 33, 35, 37, 35, 29, 30, 34, 37, 44, 26, 30, 65, 65, 57, 56, 55, 57, 59, 42, 38, 46, 38, 33, 40, 41, 43, 46, 35, 3, 0, 0, 0, 0, 1, 1, 0, 9, 49, 18, 0, 4, 0, 0, 0, 3, 2, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 3, 29, 231, 255, 245, 252, 250, 247, 248, 240, 245, 249, 255, 255, 255, 255, 255, 254, 254, 255, 255, 255, 255, 252, 252, 255, 254, 255, 254, 255, 255, 255, 254, 255, 255, 254, 253, 255, 255, 255, 255, 255, 71, 1, 1, 1, 1, 0, 15, 189, 244, 255, 223, 205, 216, 183, 191, 207, 210, 221, 234, 240, 233, 220, 215, 113, 138, 251, 225, 219, 223, 224, 169, 166, 201, 208, 217, 220, 196, 190, 181, 189, 181, 188, 193, 148, 149, 207, 171, 25, 0, 50, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 250, 245, 244, 253, 255, 255, 246, 240, 239, 231, 239, 234, 255, 255, 255, 249, 238, 234, 247, 255, 255, 255, 255, 255, 254, 255, 255, 255, 255, 255, 90, 0, 1, 0, 1, 1, 43, 245, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 241, 229, 249, 255, 255, 255, 254, 249, 249, 248, 255, 251, 254, 254, 255, 242, 235, 241, 253, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 77, 0, 31, 240, 254, 249, 189, 170, 192, 190, 179, 202, 131, 12, 4, 0, 107, 226, 192, 54, 0, 11, 8, 2, 2, 146, 225, 204, 71, 0, 0, 65, 200, 206, 192, 194, 197, 185, 200, 255, 255, 255, 211, 24, 0, 1, 0, 1, 0, 8, 178, 255, 255, 243, 204, 194, 197, 198, 189, 209, 181, 25, 0, 0, 106, 217, 213, 96, 0, 6, 5, 7, 0, 126, 236, 199, 38, 0, 0, 84, 220, 208, 203, 205, 198, 210, 200, 225, 255, 255, 68, 0, 19, 226, 254, 219, 10, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 190, 255, 255, 95, 0, 3, 0, 2, 0, 3, 0, 48, 253, 255, 151, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 144, 255, 255, 80, 0, 62, 255, 255, 235, 24, 0, 0, 0, 0, 0, 3, 2, 0, 1, 2, 0, 1, 5, 3, 1, 1, 2, 4, 1, 0, 0, 1, 0, 3, 2, 0, 0, 0, 0, 0, 0, 0, 189, 255, 255, 105, 0, 1, 1, 1, 0, 3, 0, 65, 255, 255, 124, 0, 1, 0, 0, 0, 0, 0, 3, 6, 2, 1, 0, 0, 4, 3, 0, 3, 1, 1, 2, 1, 0, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 157, 255, 255, 85, 0, 45, 252, 255, 241, 31, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 2, 1, 0, 0, 187, 255, 255, 102, 0, 2, 1, 0, 0, 2, 0, 94, 255, 254, 143, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 2, 3, 1, 0, 0, 0, 134, 255, 255, 69, 0, 48, 253, 255, 227, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 0, 1, 1, 0, 1, 1, 2, 1, 1, 1, 0, 0, 0, 0, 2, 0, 0, 178, 255, 255, 119, 0, 1, 0, 0, 1, 2, 0, 66, 255, 255, 138, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 145, 255, 255, 84, 0, 49, 254, 255, 229, 19, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 0, 0, 0, 1, 1, 2, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 196, 255, 255, 110, 0, 0, 0, 0, 0, 2, 1, 54, 255, 255, 138, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 130, 254, 255, 76, 0, 39, 245, 255, 225, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 2, 1, 23, 233, 255, 255, 82, 0, 2, 1, 0, 1, 1, 0, 61, 255, 255, 124, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 142, 255, 254, 74, 0, 55, 255, 254, 246, 31, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 6, 207, 255, 255, 116, 0, 2, 0, 0, 0, 1, 1, 99, 255, 255, 137, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 92, 255, 255, 83, 0, 32, 254, 255, 107, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 1, 0, 0, 2, 1, 0, 71, 231, 255, 79, 0, 3, 0, 0, 0, 5, 0, 68, 241, 193, 48, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 159, 255, 89, 0, 55, 255, 182, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 1, 1, 0, 4, 1, 0, 0, 5, 6, 0, 0, 0, 2, 3, 1, 1, 0, 1, 2, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 3, 3, 0, 137, 255, 95, 0, 52, 255, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 3, 0, 0, 2, 1, 1, 1, 1, 14, 41, 8, 0, 1, 1, 0, 0, 2, 7, 4, 0, 1, 2, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 2, 0, 0, 173, 255, 80, 0, 40, 254, 238, 34, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 7, 5, 0, 0, 0, 1, 1, 0, 29, 124, 222, 255, 113, 0, 0, 0, 0, 0, 4, 0, 44, 174, 80, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 114, 255, 255, 75, 0, 44, 250, 255, 225, 17, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 3, 1, 5, 1, 2, 5, 6, 3, 1, 2, 4, 4, 4, 2, 0, 0, 0, 1, 0, 93, 255, 255, 254, 191, 1, 0, 0, 0, 0, 2, 0, 60, 255, 255, 101, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 1, 0, 0, 2, 0, 113, 255, 255, 87, 0, 47, 251, 255, 249, 36, 1, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 1, 1, 2, 1, 1, 3, 3, 1, 1, 1, 3, 0, 1, 1, 0, 0, 0, 0, 1, 89, 255, 255, 255, 178, 0, 0, 0, 0, 1, 2, 0, 66, 241, 255, 139, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 67, 255, 255, 87, 0, 51, 245, 254, 235, 24, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 86, 255, 255, 254, 197, 0, 0, 0, 0, 0, 3, 0, 97, 163, 192, 142, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 1, 0, 1, 0, 1, 115, 255, 255, 77, 0, 68, 254, 255, 241, 29, 1, 2, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 95, 255, 255, 255, 192, 0, 1, 0, 1, 0, 3, 0, 78, 237, 254, 114, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 118, 255, 255, 84, 0, 72, 255, 255, 251, 41, 0, 2, 0, 0, 1, 3, 1, 1, 0, 0, 3, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 2, 1, 0, 1, 2, 0, 71, 255, 254, 255, 160, 0, 0, 0, 0, 1, 3, 0, 26, 233, 255, 132, 0, 0, 2, 0, 1, 1, 2, 2, 2, 2, 2, 0, 1, 0, 1, 2, 0, 1, 2, 3, 3, 2, 1, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 165, 255, 255, 83, 0, 77, 255, 254, 227, 17, 0, 0, 0, 0, 0, 1, 4, 2, 2, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 51, 253, 255, 255, 158, 0, 0, 0, 0, 2, 0, 1, 54, 255, 255, 98, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 3, 3, 4, 2, 0, 0, 0, 0, 0, 0, 0, 139, 255, 255, 72, 0, 71, 255, 255, 229, 89, 66, 87, 83, 78, 90, 46, 0, 0, 0, 103, 142, 136, 145, 128, 162, 157, 122, 126, 127, 128, 127, 128, 130, 128, 128, 127, 127, 127, 126, 125, 106, 172, 255, 255, 255, 224, 30, 0, 0, 0, 0, 3, 0, 92, 255, 254, 135, 0, 46, 44, 8, 11, 39, 30, 25, 26, 34, 54, 45, 22, 39, 32, 28, 28, 26, 28, 27, 38, 14, 0, 4, 0, 5, 32, 37, 29, 27, 32, 25, 9, 169, 254, 255, 88, 0, 26, 227, 255, 255, 255, 255, 255, 255, 255, 255, 231, 36, 0, 61, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 255, 254, 255, 255, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 116, 0, 0, 0, 1, 0, 20, 190, 255, 254, 250, 239, 255, 255, 181, 196, 255, 245, 240, 241, 248, 255, 247, 239, 253, 246, 245, 245, 242, 243, 243, 255, 173, 0, 0, 0, 100, 254, 255, 245, 243, 247, 246, 246, 250, 255, 255, 79, 0, 46, 245, 255, 255, 254, 255, 255, 255, 255, 255, 255, 190, 0, 163, 255, 255, 254, 255, 255, 255, 255, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 254, 255, 254, 255, 255, 255, 138, 0, 0, 0, 1, 0, 61, 255, 255, 255, 254, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 119, 0, 12, 222, 255, 255, 255, 255, 255, 254, 255, 255, 255, 249, 48, 0, 80, 255, 255, 237, 139, 113, 121, 128, 127, 123, 149, 83, 1, 92, 219, 207, 197, 173, 206, 190, 150, 183, 255, 255, 255, 221, 214, 199, 170, 170, 180, 189, 242, 255, 255, 255, 254, 255, 255, 255, 255, 131, 0, 0, 0, 1, 0, 58, 255, 254, 255, 255, 254, 255, 255, 172, 80, 103, 108, 175, 220, 199, 101, 141, 255, 255, 158, 74, 100, 96, 102, 107, 87, 109, 60, 0, 4, 104, 128, 109, 115, 114, 125, 108, 97, 209, 255, 255, 88, 0, 58, 255, 255, 157, 0, 0, 0, 0, 0, 1, 0, 0, 5, 1, 1, 0, 0, 1, 0, 1, 0, 10, 221, 255, 253, 48, 2, 1, 0, 3, 12, 83, 255, 255, 254, 255, 255, 255, 254, 249, 193, 35, 0, 1, 0, 1, 1, 0, 79, 162, 233, 255, 255, 255, 255, 129, 0, 1, 8, 14, 11, 6, 8, 85, 255, 255, 70, 0, 0, 1, 1, 0, 0, 1, 1, 7, 10, 2, 1, 0, 0, 0, 0, 1, 0, 115, 255, 255, 86, 0, 80, 254, 187, 0, 0, 0, 2, 1, 1, 1, 0, 2, 6, 1, 0, 0, 0, 1, 0, 0, 0, 23, 231, 255, 255, 60, 1, 0, 1, 98, 200, 251, 254, 255, 255, 255, 241, 154, 81, 9, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 6, 70, 183, 254, 255, 254, 189, 27, 16, 8, 0, 0, 5, 169, 255, 255, 86, 0, 1, 2, 3, 5, 4, 1, 1, 3, 5, 4, 4, 0, 1, 3, 1, 3, 0, 0, 169, 255, 90, 0, 88, 255, 179, 0, 0, 0, 0, 0, 1, 2, 4, 2, 1, 5, 5, 5, 1, 0, 2, 0, 1, 57, 255, 255, 255, 86, 0, 1, 137, 255, 255, 254, 255, 254, 209, 79, 11, 1, 0, 0, 1, 2, 0, 1, 0, 0, 1, 1, 2, 1, 1, 0, 0, 42, 168, 255, 255, 252, 152, 27, 1, 0, 14, 193, 255, 255, 88, 0, 2, 0, 2, 1, 1, 3, 6, 2, 0, 6, 4, 0, 1, 0, 0, 2, 4, 0, 150, 255, 89, 0, 64, 255, 255, 73, 0, 0, 0, 0, 2, 2, 8, 8, 0, 2, 4, 3, 1, 0, 1, 1, 0, 47, 250, 255, 255, 114, 0, 141, 255, 255, 255, 255, 247, 107, 0, 0, 1, 1, 2, 0, 1, 1, 0, 0, 1, 0, 0, 1, 2, 2, 0, 2, 1, 0, 0, 77, 244, 255, 255, 200, 22, 4, 12, 141, 255, 255, 87, 0, 2, 3, 1, 1, 0, 1, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 33, 221, 255, 79, 0, 72, 255, 255, 201, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 34, 242, 255, 255, 90, 50, 255, 255, 253, 255, 220, 37, 0, 1, 9, 3, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 2, 2, 1, 1, 1, 0, 4, 4, 0, 27, 208, 255, 255, 196, 24, 8, 62, 255, 254, 86, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 174, 255, 255, 92, 0, 99, 255, 255, 227, 16, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 64, 255, 255, 255, 87, 145, 255, 255, 255, 214, 23, 0, 2, 2, 5, 5, 0, 2, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 2, 2, 1, 1, 2, 5, 0, 8, 192, 255, 185, 5, 2, 80, 255, 255, 91, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 172, 255, 255, 93, 0, 105, 255, 255, 226, 16, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 52, 253, 255, 243, 131, 217, 255, 255, 235, 33, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 2, 0, 0, 214, 207, 0, 0, 73, 254, 255, 89, 0, 3, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 173, 255, 255, 97, 0, 93, 255, 255, 221, 13, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 49, 252, 255, 253, 254, 255, 255, 255, 97, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 33, 239, 193, 81, 141, 255, 254, 93, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 168, 255, 255, 93, 0, 68, 255, 245, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 34, 242, 255, 255, 255, 254, 255, 139, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 113, 254, 255, 255, 254, 255, 94, 1, 3, 0, 0, 1, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 191, 255, 94, 0, 69, 255, 185, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 16, 228, 254, 255, 255, 255, 212, 15, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 5, 204, 255, 255, 255, 255, 88, 0, 2, 1, 1, 3, 2, 1, 5, 2, 2, 1, 1, 1, 1, 0, 0, 2, 1, 0, 153, 255, 95, 0, 92, 254, 179, 0, 1, 0, 0, 0, 0, 0, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 254, 255, 255, 255, 255, 111, 0, 7, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 3, 0, 101, 255, 255, 255, 255, 94, 1, 0, 3, 2, 3, 4, 5, 7, 3, 5, 7, 5, 2, 0, 1, 0, 0, 5, 1, 163, 255, 93, 0, 102, 255, 241, 50, 0, 0, 0, 0, 0, 1, 0, 5, 4, 2, 0, 0, 0, 0, 0, 0, 0, 81, 255, 254, 254, 255, 233, 25, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 3, 1, 10, 216, 254, 255, 254, 86, 0, 0, 1, 0, 0, 0, 1, 2, 6, 6, 4, 0, 0, 1, 0, 0, 0, 1, 21, 220, 255, 87, 0, 72, 255, 254, 235, 163, 162, 167, 164, 164, 182, 89, 0, 0, 15, 192, 233, 211, 212, 212, 210, 236, 223, 242, 255, 255, 255, 164, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 3, 2, 0, 0, 125, 255, 255, 255, 169, 87, 118, 97, 98, 106, 124, 72, 0, 5, 0, 39, 152, 148, 142, 143, 141, 146, 132, 216, 255, 255, 94, 0, 81, 255, 255, 255, 254, 255, 255, 255, 255, 255, 246, 63, 0, 115, 255, 255, 255, 255, 255, 255, 255, 254, 255, 254, 255, 255, 67, 0, 1, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 6, 0, 56, 255, 254, 255, 255, 255, 255, 255, 255, 254, 255, 255, 75, 0, 0, 165, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 98, 0, 87, 254, 255, 254, 255, 254, 255, 255, 255, 255, 255, 109, 0, 165, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 48, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 25, 232, 255, 237, 255, 244, 238, 255, 249, 248, 255, 254, 150, 0, 2, 212, 255, 255, 255, 255, 254, 254, 250, 252, 255, 255, 100, 0, 37, 224, 255, 173, 71, 81, 83, 70, 66, 70, 69, 20, 0, 81, 177, 148, 121, 117, 119, 116, 116, 119, 116, 118, 128, 82, 1, 1, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 1, 3, 2, 0, 25, 36, 15, 41, 23, 18, 46, 31, 26, 36, 30, 10, 0, 0, 34, 55, 37, 40, 41, 41, 40, 8, 91, 234, 222, 57, 0, 0, 11, 12, 3, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 3, 2, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4, 1, 0, 0, 0, 1, 1, 0, 0, 0, 2, 0, 3, 4, 3, 0, 0, 1, 4, 2, 2, 2, 1, 3, 2, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 3, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 3, 6, 1, 2, 1, 0, 0, 2, 5, 4, 0, 0, 2, 2, 0, 2, 10, 7, 0, 0, 2, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 4, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5, 8, 1, 5, 7, 2, 1, 0, 0, 0, 1, 1, 0, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 1, 0, 0, 0, 0, 0, 5, 1, 1, 0, 6, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 4, 1, 0, 0, 0, 0, 0, 7, 8, 0, 0, 1, 0, 0, 0, 0, 0, 3, 56, 60, 8, 0, 1, 161, 252, 137, 40, 65, 62, 45, 46, 68, 68, 16, 0, 18, 97, 111, 100, 100, 95, 100, 111, 113, 108, 129, 137, 42, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 1, 1, 0, 11, 183, 217, 202, 207, 213, 221, 195, 189, 202, 211, 234, 99, 0, 0, 104, 182, 142, 141, 153, 141, 145, 126, 189, 255, 253, 45, 0, 18, 225, 255, 255, 255, 255, 255, 255, 255, 255, 255, 83, 0, 73, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 177, 0, 0, 2, 1, 2, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 3, 0, 62, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 103, 0, 1, 164, 255, 255, 255, 255, 255, 254, 255, 254, 255, 251, 46, 0, 8, 210, 255, 255, 254, 252, 253, 255, 253, 255, 180, 2, 0, 0, 181, 255, 255, 254, 255, 255, 254, 254, 255, 255, 255, 233, 23, 0, 4, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 1, 1, 1, 97, 255, 255, 255, 255, 247, 244, 241, 241, 244, 255, 156, 0, 0, 0, 34, 192, 208, 191, 190, 186, 186, 166, 218, 254, 249, 43, 0, 10, 225, 255, 119, 8, 26, 29, 28, 26, 28, 10, 0, 10, 1, 12, 57, 55, 52, 49, 36, 40, 35, 199, 255, 254, 255, 84, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 3, 1, 0, 159, 255, 255, 255, 135, 1, 23, 22, 20, 22, 16, 3, 0, 7, 8, 0, 1, 0, 0, 1, 0, 0, 1, 74, 255, 255, 40, 0, 20, 248, 131, 1, 1, 0, 0, 0, 0, 1, 0, 3, 2, 4, 2, 0, 0, 0, 0, 0, 0, 0, 169, 254, 255, 255, 165, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 4, 1, 31, 240, 255, 255, 255, 117, 0, 1, 0, 0, 0, 0, 1, 3, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 136, 255, 46, 0, 21, 246, 124, 0, 1, 0, 0, 0, 0, 2, 1, 1, 2, 1, 4, 0, 0, 0, 1, 2, 0, 1, 184, 255, 255, 254, 255, 55, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 1, 0, 148, 254, 255, 255, 255, 118, 0, 0, 0, 1, 2, 1, 0, 2, 1, 0, 3, 2, 1, 0, 0, 0, 2, 6, 1, 124, 255, 45, 0, 16, 250, 156, 0, 1, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 1, 0, 0, 0, 0, 1, 0, 194, 255, 254, 255, 255, 171, 0, 0, 2, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 6, 0, 40, 245, 255, 255, 255, 255, 121, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 0, 137, 255, 42, 0, 22, 240, 255, 93, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 196, 255, 255, 255, 255, 255, 80, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 137, 255, 255, 255, 255, 254, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 255, 255, 49, 0, 13, 219, 255, 148, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191, 255, 255, 255, 176, 202, 247, 31, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 2, 0, 64, 253, 255, 254, 255, 255, 255, 122, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 255, 250, 46, 0, 13, 222, 255, 113, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 0, 1, 0, 190, 255, 254, 99, 0, 134, 255, 173, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 4, 0, 24, 248, 192, 40, 29, 128, 255, 255, 113, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 255, 255, 46, 0, 22, 227, 255, 138, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 188, 254, 197, 0, 54, 255, 255, 254, 153, 0, 1, 2, 2, 0, 0, 0, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 2, 3, 0, 1, 2, 1, 4, 7, 0, 23, 217, 255, 200, 24, 0, 94, 254, 255, 126, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 142, 255, 245, 38, 0, 17, 233, 255, 103, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 191, 255, 212, 8, 24, 181, 255, 255, 255, 186, 20, 0, 0, 3, 4, 2, 1, 2, 2, 0, 0, 0, 0, 1, 0, 2, 2, 0, 3, 2, 1, 3, 1, 0, 48, 230, 255, 255, 254, 84, 11, 84, 255, 255, 132, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 98, 254, 254, 39, 0, 18, 248, 143, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 4, 209, 255, 255, 108, 5, 4, 123, 255, 255, 255, 235, 75, 0, 0, 3, 5, 0, 4, 4, 0, 0, 1, 1, 1, 2, 0, 4, 1, 2, 4, 2, 0, 0, 109, 255, 255, 255, 254, 111, 4, 11, 165, 255, 255, 116, 1, 1, 2, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 3, 1, 0, 139, 255, 48, 0, 18, 245, 126, 0, 1, 0, 1, 2, 0, 0, 2, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 183, 255, 255, 89, 1, 1, 6, 94, 239, 255, 254, 255, 186, 52, 0, 0, 1, 0, 6, 7, 0, 0, 0, 0, 2, 7, 6, 2, 0, 0, 0, 80, 211, 255, 255, 255, 179, 33, 8, 0, 5, 162, 254, 255, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 128, 255, 47, 0, 25, 255, 173, 0, 0, 0, 0, 0, 1, 0, 0, 4, 4, 2, 1, 0, 0, 0, 0, 0, 1, 0, 200, 255, 245, 48, 6, 0, 2, 11, 15, 140, 252, 255, 255, 255, 185, 74, 0, 0, 0, 4, 2, 0, 0, 2, 5, 2, 0, 1, 7, 90, 201, 255, 255, 255, 255, 113, 9, 12, 0, 0, 5, 134, 255, 255, 123, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 143, 255, 44, 0, 31, 241, 255, 140, 7, 29, 33, 29, 14, 28, 32, 10, 0, 0, 51, 65, 51, 54, 54, 55, 36, 55, 227, 255, 235, 69, 142, 200, 122, 55, 1, 1, 189, 255, 255, 255, 254, 255, 227, 194, 108, 3, 0, 0, 0, 1, 0, 12, 102, 165, 228, 255, 255, 255, 255, 255, 123, 0, 9, 92, 135, 130, 52, 149, 255, 255, 137, 0, 19, 23, 24, 11, 0, 21, 9, 0, 5, 0, 0, 0, 0, 0, 0, 0, 1, 80, 255, 255, 64, 0, 10, 213, 255, 254, 251, 249, 251, 247, 231, 249, 255, 107, 0, 32, 243, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 243, 240, 254, 255, 255, 255, 255, 254, 255, 254, 255, 65, 0, 0, 1, 0, 0, 121, 255, 255, 255, 255, 255, 255, 255, 255, 220, 213, 241, 251, 255, 255, 253, 252, 255, 255, 250, 233, 237, 239, 241, 228, 216, 254, 185, 0, 0, 132, 189, 164, 167, 156, 163, 161, 155, 228, 254, 255, 61, 0, 17, 221, 255, 255, 255, 255, 255, 254, 255, 255, 228, 37, 0, 0, 171, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 255, 66, 0, 1, 0, 0, 1, 124, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 167, 0, 1, 176, 255, 255, 255, 255, 255, 255, 255, 255, 255, 199, 1, 0, 21, 229, 255, 172, 79, 95, 102, 99, 95, 106, 46, 0, 2, 0, 36, 133, 138, 128, 127, 130, 132, 136, 140, 142, 141, 145, 145, 140, 142, 154, 159, 147, 157, 157, 143, 143, 146, 220, 255, 255, 153, 0, 0, 0, 0, 1, 0, 16, 200, 255, 255, 211, 148, 182, 180, 192, 203, 193, 188, 194, 196, 192, 187, 196, 189, 194, 196, 177, 187, 194, 201, 206, 220, 192, 29, 0, 0, 45, 175, 173, 158, 165, 164, 163, 137, 209, 255, 209, 12, 0, 26, 237, 255, 108, 1, 0, 0, 0, 0, 0, 0, 7, 5, 5, 3, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 152, 255, 254, 55, 1, 3, 0, 0, 0, 5, 0, 99, 255, 255, 122, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 3, 7, 5, 2, 1, 0, 0, 0, 0, 0, 0, 122, 255, 251, 43, 0, 30, 238, 255, 113, 0, 2, 0, 1, 0, 2, 2, 3, 3, 1, 2, 2, 2, 2, 2, 3, 5, 1, 1, 4, 3, 3, 3, 3, 4, 1, 1, 3, 1, 1, 1, 0, 1, 185, 255, 255, 87, 0, 1, 0, 1, 1, 0, 0, 141, 255, 255, 114, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 3, 2, 1, 0, 1, 0, 0, 0, 0, 0, 0, 142, 255, 255, 57, 0, 19, 228, 255, 120, 1, 0, 1, 0, 1, 0, 2, 0, 0, 0, 1, 2, 1, 1, 1, 2, 2, 1, 4, 2, 0, 0, 2, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 163, 255, 255, 74, 1, 1, 0, 0, 2, 0, 0, 141, 254, 255, 114, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 2, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 147, 255, 255, 54, 0, 30, 238, 255, 121, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 142, 255, 255, 66, 0, 1, 1, 0, 0, 1, 0, 128, 255, 255, 105, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 152, 255, 247, 40, 0, 25, 232, 254, 119, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 174, 255, 255, 71, 0, 1, 0, 0, 2, 0, 0, 143, 255, 255, 106, 1, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 153, 255, 250, 45, 0, 28, 235, 254, 142, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 190, 255, 255, 76, 0, 1, 0, 0, 0, 0, 0, 148, 255, 255, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 255, 248, 45, 0, 20, 244, 230, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 117, 255, 255, 75, 1, 0, 0, 0, 0, 0, 1, 145, 255, 255, 94, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 118, 255, 250, 38, 0, 40, 254, 117, 1, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 70, 146, 27, 0, 1, 0, 0, 0, 2, 0, 65, 197, 84, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 143, 255, 39, 0, 25, 253, 126, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 3, 2, 0, 0, 4, 4, 0, 0, 1, 0, 2, 4, 0, 0, 0, 4, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 121, 255, 43, 0, 27, 255, 137, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 1, 8, 25, 6, 1, 0, 0, 0, 0, 0, 4, 8, 11, 3, 2, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 4, 0, 114, 255, 52, 0, 39, 254, 255, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 23, 201, 237, 27, 0, 0, 0, 1, 0, 1, 0, 39, 240, 141, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 26, 206, 255, 45, 0, 37, 244, 255, 131, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 98, 255, 236, 27, 0, 2, 1, 0, 0, 3, 0, 34, 255, 255, 52, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 138, 255, 245, 39, 0, 37, 245, 254, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 95, 255, 244, 32, 1, 0, 0, 0, 2, 1, 0, 55, 255, 255, 46, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 117, 255, 248, 39, 0, 33, 242, 255, 117, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 114, 255, 230, 21, 0, 1, 0, 0, 0, 4, 0, 51, 255, 255, 53, 0, 2, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 118, 255, 251, 43, 0, 29, 239, 255, 115, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 114, 255, 237, 35, 0, 1, 0, 0, 0, 5, 0, 45, 255, 254, 51, 0, 2, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 125, 254, 254, 48, 0, 34, 242, 255, 116, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 1, 3, 2, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 109, 255, 242, 36, 0, 1, 0, 0, 1, 2, 0, 51, 254, 255, 56, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 1, 0, 1, 124, 255, 246, 38, 0, 34, 245, 255, 111, 0, 1, 0, 0, 0, 0, 1, 0, 2, 2, 0, 0, 1, 4, 3, 7, 3, 2, 2, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 108, 255, 218, 7, 0, 0, 0, 1, 0, 3, 0, 44, 254, 255, 50, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 0, 0, 1, 3, 3, 1, 1, 3, 1, 1, 0, 1, 1, 4, 2, 2, 0, 0, 0, 0, 0, 0, 0, 128, 255, 243, 36, 0, 40, 246, 255, 157, 9, 23, 32, 30, 17, 29, 13, 0, 1, 0, 24, 61, 25, 0, 1, 0, 0, 1, 0, 0, 34, 32, 0, 1, 0, 1, 12, 6, 0, 2, 19, 22, 0, 128, 255, 240, 36, 0, 2, 1, 1, 0, 1, 1, 64, 255, 255, 64, 1, 10, 7, 10, 10, 16, 6, 0, 0, 0, 10, 35, 13, 1, 0, 0, 0, 0, 0, 0, 6, 8, 0, 0, 0, 0, 3, 8, 6, 7, 8, 2, 0, 150, 255, 248, 43, 0, 27, 229, 255, 255, 247, 242, 246, 243, 233, 254, 216, 46, 0, 43, 217, 255, 242, 61, 0, 23, 11, 18, 0, 94, 255, 255, 102, 2, 6, 121, 253, 228, 215, 220, 241, 250, 176, 197, 255, 255, 204, 6, 1, 0, 0, 2, 1, 8, 214, 255, 238, 243, 222, 230, 223, 225, 226, 255, 150, 0, 0, 49, 217, 255, 189, 22, 18, 37, 36, 41, 22, 75, 228, 250, 83, 0, 1, 44, 203, 245, 227, 226, 226, 224, 223, 249, 255, 251, 46, 0, 23, 231, 255, 254, 255, 255, 254, 255, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 255, 252, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 255, 254, 255, 255, 255, 255, 241, 33, 0, 1, 0, 1, 0, 14, 224, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 254, 255, 253, 254, 255, 255, 255, 255, 255, 254, 255, 255, 255, 255, 244, 39, 0, 10, 122, 153, 147, 144, 138, 142, 134, 131, 131, 138, 145, 136, 124, 122, 125, 139, 148, 151, 158, 139, 129, 143, 40, 74, 144, 135, 128, 127, 106, 109, 116, 106, 102, 99, 110, 117, 114, 97, 129, 96, 0, 0, 0, 0, 0, 0, 0, 102, 138, 112, 123, 116, 117, 107, 114, 131, 132, 140, 135, 135, 130, 112, 137, 86, 86, 118, 105, 101, 100, 108, 94, 93, 101, 103, 119, 120, 105, 100, 103, 102, 101, 99, 97, 95, 89, 83, 63, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
        // ARRAY OF PIXELS GOES HERE, COMMA + SPACE SEPERATED
        };
        
        void setup() {
        pinMode (0, OUTPUT);
        pinMode (1, OUTPUT);
        pinMode (2, OUTPUT);
        pinMode (3, OUTPUT);
        pinMode (4, OUTPUT);
        pinMode (5, OUTPUT);
        pinMode (6, OUTPUT);
        pinMode (7, OUTPUT); // PORT D
        
        pinMode (8, OUTPUT); // WR PIN (inverted)
        
        
        for (byte k = 0; k < strlen_P(img); k++) {
        
        digitalWrite(8, LOW); // inverted so this puts WR HIGH (to read)
        delay(10);
        
        myChar = pgm_read_byte_near(img + k);
        PORTD = myChar;
        
        digitalWrite(8, HIGH); // inverted so this puts WR LOW (to write)
        delay(10);
        
        }
        }
        void loop() {
        }
        
        

        Success finishing the board and recording Palladio distorted by the board :

         

         

         

        Here is the setup :

        I’m currently using two boards, but soon I’ll have the components to put everything on the board to the left. 

        The techniques I’m using is the one developed in the previous post :

        TO RECORD IN BURSTS: I can now save a short video : 695.45 kHz (This is the slowest I can go and still almost see an image) on the function gen AND’ed with the top 4 frequency divisions of the vertical sync. This makes for a burst of image recording every X number of frames.  I then amplify the output to make it visible on screen (and speed the clock up to 695.48 kHz). 
        TO STOP THE IMAGE JUMPING: If the reset is connected to the inverse of the freq subdivision of the vertical sync signal AND’ed with the address 20, it will play the image in a loop and always place it in the same part of the screen ! 
        EXPERIMENT : 1 bit recording 

        Recording a single bit of an image appears to produce almost the same image quality ! This means that in theory I could record 8 videos at the same time and output video to 8 screens simoultaneously !

         

        EXPERIMENT : Loading an image with Arduino
        Loading the tiny image once was a drop of water in the ocean so I recorded the image again and again until I ran out of space. This is taking a long time with a few 10ms delays in my code. 

         

        Here is the Arduino sending bits (captured after DAC) :

         

        but so far nothing that comes out looking like an image on the other side…

        I also can’t get my VGA to HDMI converter working…

        Here’s an attempt at a grid of raster variations :

        Here’s the final version of the board :

         

        Memory Experiments

         

        https://github.com/merlinmarrs/Video-Memory

        This project started with an ambitious board combining ADC, DAC and SRAM. 

         

        There were too many issues so I broke the board down into two parts: a memory board and a ADC/DAC board. This allowed me to isolate things and proceed in a step by step way.

        I discovered that the memory needed a WR signal inbetween clock address refreshing, and for the second board that my op amp choice was inappropriate and needed to work around it (by using the DAC only as an R2R ladder and skipping the op-amp for the ADC input). 

         

        During assembly I found that several 0 ohm jumpers were causing shorts. I also tore out the 8 pin header but applying too much force accidentally. Otherwise the switch system was very effective to test my understanding of the memory chip operation. It can essentially record a series of button manipulations for about 1.5 minutes.  

        Here is my first successful “recording” of a sine wave through the ADC and into SRAM and play back from SRAM through the DAC :

        BOARD ERRATA:

        -need last bit of address counter (cuts memory in half !)

        -more jumpers should be broken out for testing (like alternative op amp for input, clk for various chips, etc.)

        -leds burn out when activated and output plugged into 5V at the same time…

        -GND and 5V switched on the two boards 🙁

        -Wrong op amp spec’d. The ADC1175 suggests the LMH6702MF and a choke between power supplies. 

        -caps on all ICs

        -the LEDs I set up on the microchip are plugged into ADC…

        -Add enable header on microchip board

        -power LED on the ADC board

        -add a MSB and LSB next to LEDs on memory board **

        I calculated how much I could store in the 4K of the SRAM I am currently using, and it would be a single line of a 600×800 screen at 40Mhz pixel frequency…

        So what can I do with this ? I could record 4,000 pixels of a static image (i.e. lower the resolution of the image to 100×400 for instance) and then play it back. This would require me to control the sampling of the ADC with the CLK pin of the ADC1175 for every X pixels, somehow synchronized with the VGA in signal (use timing signals of an incoming VGA signal set), or to generate a custom VGA output signal with different timing using the VGAX library. 

        Some important references : 

        nootropicdesign.com/video-experimenter/build

        gieskes.nl/visual-equipment/?file=gvs1

        I am looking into what I could draw on screen with only 4K memory at a 20MHz clock.

        EEPROM and SD cards are also interesting before reaching the holy grail of magnetic recording media of course…

        I have the AT28C256F-15TU EEPROM chip which has 256K x 8 bits (enough to at least store an entire 600×800 static screen) and the ADV7125STZ50 8 bit triple HS video DAC. 

        https://www.mouser.fr/datasheet/2/268/doc0006-1108095.pdf

        https://www.mouser.fr/datasheet/2/609/ADV7125-1503638.pdf

        I’d like to have a standalone arduino VGAX based board (https://github.com/smaffer/vgax) which can output 120×60 pixels and reads from internal SRAM and can record and playback. With 256K I could record a static image on screen at a higher resolution or a low resolution short video.

        I have already made an SD card image saving board: 

        Just realized what I’m trying to do is called a frame grabber and it’s a massive PCB :

        https://en.wikipedia.org/wiki/Frame_grabber#:~:text=A%20frame%20grabber%20is%20an,or%20a%20digital%20video%20stream.&text=Historically%2C%20frame%20grabber%20expansion%20cards,to%20interface%20cameras%20to%20PCs.

         

        *********************************************************************************

        I have designed a similar memory board but using a 256K EEPROM chip in place of the  SRAM and with VGA connectors to begin testing images. (There do appear to be larger SRAMs, going up to 16MB. There are obviously large flash memories in SD format going into the GBs which may also be interesting to play with).

        -Added out VGA to work with VGAX library (not sure if need a second microchip to handle just the memory stuff?)

        -Added a 16MHz resonator

        -With two 8 bit counters to have the full 13 bits to control this time.

        -EEPROM will keep a recording after power down.

        -can control buffers with microchip

        Just learned that EEPROM is probably the slowest…

        Just a thought but I could save control signals for the 0c74 instead of saving actual pixel information…

        *************

        First test (WORKING):

        int switchState = 0;

        pinMode(6, OUTPUT); // CLK LED (*)
        pinMode(7, OUTPUT); // CLK

        pinMode(10, OUTPUT); // WR/RD SIGNAL TO SRAM
        pinMode(A3, INPUT); // WR/RD SWITCH (WR HIGH, READ LOW)

        pinMode(8, OUTPUT); // WR LED
        }

        // the loop function runs over and over again forever
        void loop() {

        switchState = digitalRead(A3);

        // check if the pushbutton is pressed.
        // if it is, the buttonState is HIGH:
        if (switchState == LOW) {
        // WR selected on switch so turn WR LED on and send a LOW to SRAM

        digitalWrite(8, HIGH);
        //
        digitalWrite(10, HIGH);
        digitalWrite(6, HIGH); // 
        digitalWrite(7, HIGH); // 
        delay(10);
        digitalWrite(10, LOW);
        digitalWrite(6, HIGH); // 
        digitalWrite(7, HIGH); // 
        delay(10); // 
        digitalWrite(10, LOW);
        digitalWrite(6, LOW); 
        digitalWrite(7, LOW); 
        delay(10); // 
        digitalWrite(10, HIGH);
        digitalWrite(6, LOW); // 
        digitalWrite(7, LOW); // 
        delay(10); // 

        }
        else {
        // READ selected on switch so turn WR LED OFF on and send a HIGH to SRAM
        digitalWrite(10, HIGH); // STAYS HIGH THE WHOLE TIME
        digitalWrite(8, LOW);
        //
        digitalWrite(6, HIGH); // 
        digitalWrite(7, HIGH); //
        delay(20); // 
        digitalWrite(6, LOW); // 
        digitalWrite(7, LOW); // 
        delay(20); //

        }

        }

        This is what it produces:

        Second test (WORKING): 

        int switchState = 0;

        // the setup function runs once when you press reset or power the board
        void setup() {
        // initialize digital pin 13 as an output.
        pinMode(6, OUTPUT); // CLK LED (*)
        pinMode(7, OUTPUT); // CLK

        pinMode(10, OUTPUT); // WR/RD SIGNAL TO SRAM
        pinMode(A3, INPUT); // WR/RD SWITCH (WR HIGH, READ LOW)

        pinMode(8, OUTPUT); // WR LED
        }

        // the loop function runs over and over again forever
        void loop() {

        switchState = digitalRead(A3);

        // check if the pushbutton is pressed.
        // if it is, the buttonState is HIGH:
        if (switchState == LOW) {
        // WR selected on switch so turn WR LED on and send a LOW to SRAM

        digitalWrite(8, HIGH);
        //
        digitalWrite(10, HIGH);
        digitalWrite(6, HIGH); // turn the LED on (HIGH is the voltage level)
        digitalWrite(7, HIGH); // turn the LED on (HIGH is the voltage level)
        delayMicroseconds(1);
        digitalWrite(10, LOW);
        digitalWrite(6, HIGH); // turn the LED on (HIGH is the voltage level)
        digitalWrite(7, HIGH); // turn the LED on (HIGH is the voltage level)
        delayMicroseconds(1); // wait for a second
        digitalWrite(10, LOW);
        digitalWrite(6, LOW); // turn the LED on (HIGH is the voltage level)
        digitalWrite(7, LOW); // turn the LED on (HIGH is the voltage level)
        delayMicroseconds(1); // wait for a second
        digitalWrite(10, HIGH);
        digitalWrite(6, LOW); // turn the LED on (HIGH is the voltage level)
        digitalWrite(7, LOW); // turn the LED on (HIGH is the voltage level)
        delayMicroseconds(1); // wait for a second
        // wait for a second
        }
        else {
        // READ selected on switch so turn WR LED OFF on and send a HIGH to SRAM
        digitalWrite(10, HIGH); // STAYS HIGH THE WHOLE TIME
        digitalWrite(8, LOW);
        //
        digitalWrite(6, HIGH); // turn the LED on (HIGH is the voltage level)
        digitalWrite(7, HIGH); // turn the LED on (HIGH is the voltage level)
        delayMicroseconds(1); // wait for a second
        digitalWrite(6, LOW); // turn the LED on (HIGH is the voltage level)
        digitalWrite(7, LOW); // turn the LED on (HIGH is the voltage level)
        delayMicroseconds(1); // wait for a second

        }

        }

        And here are some shots of what three different speeds (10ms, 10microseconds, 1 microseconds) as delay in the Arduino code :

         

        ***********************************************************************

        Third test (NOT WORKING):

        I recorded a sine wave at 100KHz (with WR activated on the microchip board) with the ADC being clocked at 10KHz. I made sure I had the ADC selected with the right buffers and then sent this 8 bit sequence to the memory where I recorded it with a new Arduino code:

        void setup()
        {
        DDRD = B11111111; // set PORTD (digital 7~0) to outputs
        DDRB = B11111111; // set PORTB (digital 7~0) to outputs
        }

        void loop()
        {
        if((PINC & 0b00001000)==0)
        {
        PORTD = B11111111; // set PORTD pins (digital 7~0) high
        PORTB = B00000000; // set PORTD pins (digital 7~0) low
        PORTD = B00000000; // set PORTD pins (digital 7~0) low
        PORTB = B11111111; // set PORTD pins (digital 7~0) high

        }
        else
        {
        PORTB = B00000100; // WR PULLED HIGH SO TURNED OFF
        PORTD = B11111111; // set PORTD pins (digital 7~0) high
        PORTD = B00000000; // set PORTD pins (digital 7~0) low
        }
        }

        /*
        CLOCK:
        _____ _____
        | ` | | |
        ___| |___| |____

        WR:
        _________ ____________
        ` | |
        |___|

        */

        I then switched to the DAC with the buffers and switched into READ mode on the microchip board.  Now the 8 bit sequence was being translated back into a sine wave. I took this sine wave and amplified it with an audio amp and sent it to the three color channels combined with an arduino running the VGAX pattern code without the colors plugged in and only H and V SYNC.

        I got this on the screen :

        Here is the tentacular and unoptimized setup :

        To make this actually easy to use, I need to:

        -have the microchip control the buffers and the ADC clocking based on the switch state.

        -have the memory and adc on a single board.

        -have a VGAX out setup integrated into the memory board.

        -have an op amp on the ADC board to amplify the output signal !!

        -have a dial change the speed of the playback / sampling of recording.

        *******************************************

        I added an external crystal and set the AVR dude Fuses to : Ext. Crystal Osc.8.0 – ___MHz 16K CK/14 CK + 65 ms. 

        I added F_CPU 16000000UL ABOVE the #include. 

        Forgot that if you don’t add 0b before a binary number nothing happens with the pins !

        Here is the code that still isn’t working :

        /*
        * eeprom board v.2.c
        *
        * Created: 06/02/2022 09:19:50
        * Author : Jonah
        */

        #include <avr/io.h>

        int main(void)
        {

        DDRC = 0b00000000; // PC3 is the switch for WR (0) or RD(1)

        DDRD = 0b11111111; //PD5 is CLK and PD4 is !OE

        DDRB = 0b11111111; //PB0 is the LED and PB2 is !WE

        while (1)
        {

        /*
        BYTE WRITE: A low pulse on the WE or CE input with CE or WE low (respectively) and OE high initiates a write
        cycle. The address is latched on the falling edge of CE or WE, whichever occurs last. The data is latched by the first
        rising edge of CE or WE. Once a byte write is started, it will automatically time itself to completion. Once a
        programming operation is initiated and for the duration of tWC, a read operation will effectively be a polling operation.
        */

        if((PINC & 0b00001000)==0) // WRITE MODE: (CE -> TIED LO); !WE -> TOGGLE ; !OE -> HI ; CLK -> TOGGLE
        {
        PORTD = 0b00010000; // !OE -> HI ; CLK -> LO
        PORTB = 0b00000000; // !WE -> LO
        PORTB = 0b00000001; // !WE -> LO (to make the pulse width at least 100ns)
        PORTB = 0b00000101; // !WE -> HI
        PORTD = 0b00110000; // !OE -> HI ; CLK -> HI (next address must come a max of 50 ns following !WE going HI?)

        }

        /*
        READ: The AT28C256 is accessed like a Static RAM. When CE and OE are low and WE is high, the data stored at
        the memory location determined by the address pins is asserted on the outputs.
        The outputs are put in the highimpedance state when either CE or OE is high. This dual-line control offers designers flexibility in preventing bus
        contention in their system.

        */

        else // READ MODE : (CE -> TIED LO); !WE -> HI ; !OE -> (TOGGLE ? OR JUST LO?) ; CLK -> TOGGLE
        {
        PORTB = 0b00000101; // !WE -> HI
        PORTD = 0b00100000; // !OE -> LO ; CLK -> HI
        PORTD = 0b00000000; // !OE -> LO ; CLK -> LO
        }
        }
        }

        **********************************************************************************

        One question I have is: does the EEPROM require OE to go on and off when reading unlike the SRAM I worked with in the previous board ?

        Another question is, how long does the EEPROM need to write a byte ? It talks about “access times of 150ns”…?

        Is it OK I have CE tied low the whole time ?

        As a next step I will try doing all of this but very slowly to see if that works. 

        *EDIT : tried slowing everything down and I’m still not able to load anything into the memory :(. I just get 5V and little pops of ground after writing ground into every cell of the memory. This is after changing !OE toggle and always ON also. 

        I did get the VGAX code running though so at least that works. 

        ERRATA:

        -the labeling of WR and RD are confusing, when the switch is to the RD side it is in WR mode etc. 

        -the VGA parts are COMPLETELY wrong. 

        -I need to order 16MHz of this format (I took one from a dead Arduino board). 

        -the text is too small and came off during cleaning.

         

        TROUBLESHOOTING AT28C256 EEPROM:

        -Need to wait a second before doing and writing or reading,

        -Need to either wait the maximum time for the EEPROM to write (Write Cycle Time Max AT28C256 = 10ms) or poll 1/0 7 to wait until it matches what you sent it before starting another write cycle.

        -The device may be locked (even though the devices should ship unlocked) :(. The unlock sequence is :

        LOAD DATA AA
        TO
        ADDRESS 5555

        LOAD DATA 55
        TO
        ADDRESS 2AAA

        LOAD DATA 80
        TO
        ADDRESS 5555

        LOAD DATA AA
        TO
        ADDRESS 5555

         

        LOAD DATA 55
        TO
        ADDRESS 2AAA

        LOAD DATA 20
        TO
        ADDRESS 5555

        LOAD DATA XX
        TO
        ANY ADDRESS(4)

        LOAD LAST BYTE
        TO
        LAST ADDRESS

         

        ************************

        Here are some thoughts I have on the SRAM device :

        Do I want addressed to loop or not ? (Add inverter if want to loop)

          >> Make it optional with a jumper, this expands the possibilities of experimenting.

        Max sample rate I can get from SRAM ? 
        >>Looks to be around 20MHz if the read time is 50ns ?
        What happens if I slow a recorded signal down with a knob, what visual effects produced ?
        >> I need a bunch of recorded stuff and a super fast clock or else I just output bands everyonce and a while.
        Bigger SRAM same brand? need more counters?

          >> Check out this super fast 1Mx8bit SRAM

        61-64WV10248EDBLL-276598.pdf (mouser.fr)

        Two memories ? Feedback from one memory possible ?
        Jumpers to either have vgax doing syncs or input vga.
        Record at slow speed play back at high speed ? Keeps theme of time and computation…
        How have vgax send clock and wr signal for memory circuit while doing vgax timing ? Or have separate clocks (high speed resonator) and sync somehow ? ( Or generate my own sync sign also in logic ?)
        How actually use and function with two vgas ?
        It would be cool to be able to record an image, or parts of a series of images, on an input vga signal and then play them back at different speeds and doubled with the original. This seems really challenging to do accurately but could be cool to stretch an image or sample every line from an animation.

        Also would be cool to be able to output blocky animations based on memory. Could vgax output memory values? Then could compose.

        Could the vgax do a kind of low fi screen capture ? This is a ripoff of gieske though…
        Could this thing be a composition machine, where you slowly switch 8 pin dip switches and take a “photo” of each finished byte ? Then play back at higher speeds?
        I started this board wanting to learn about memory. What have I learned ? Could have button to reset address counters, knob for clock speed, but what other Params?
        Could take memory and output it as pattern by vgax ?
        Do all first with Arduino analog read  ?? Why is this better than Arduino ? What advantage, what has it allowed me to learn ? Faster ? Physicalized memory space ?
        **********
        Retried this code modified slightly from this tutorial : https://scanlines.xyz/t/tutorials-for-generating-video-sync-signals-with-arduino/104

        #define LINE_CYCLES 508
        #define HSYNC_CYLCLES 60
        #define VSYNC_LINES 2
        #define FRAME_LINES 525
        #define PIXEL_FREQ 1

        volatile int linecount;

        void setup(){
        pinMode(7, OUTPUT); // VSync
        pinMode(9, OUTPUT); // HSync
        pinMode(6, OUTPUT); // Pixel frequency

        //inverted fast pwm mode on timer 1
        TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(WGM11);
        TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);

        ICR1 = LINE_CYCLES; // Overflow at Cycles per line
        OCR1A = HSYNC_CYLCLES; // Compare high after HSync cycles

        //timer 0 in CTC mode
        TCCR0A = _BV(COM0A0) | _BV(WGM01) ; // Toggle pin on each cycle, no CPU clock prescaling/
        TCCR0B = _BV(CS00); // no clock prescaling
        OCR0A = PIXEL_FREQ; // go super fast

        TIMSK1 = _BV(TOIE1); // Enable timer overflow interrupt
        }

        ISR(TIMER1_OVF_vect)
        {

        if (linecount == 0) PORTD = PORTD ^ 0x80; //Toggle the most significant bit of port D.;
        else if (linecount == 2) PORTD = PORTD ^ 0x80; //Toggle the most significant bit of port D.;
        else if (linecount == 3) PORTD = PORTD ^ 0x80; //Toggle the most significant bit of port D.;
        else if (linecount == FRAME_LINES) linecount = 0;
        linecount++;
        }

        void loop(){}

        *******************

        Works well. Also tried generating my own V and H sync with logic and a 4040 counter from this tutorial : https://hackaday.io/project/9782-nes-zapper-video-synth-theremin/log/32271-vga-sync-generation

        It didn’t work for me. The reset of the 4040 didn’t want to be connected to anything but GND, otherwise the whole thing was inoperational. 

        I also messed around again with floppy disk writing. I got the floppy disk motor turning, plugged the index into step, activated the drive select, and connected direction to either 5V or GND. I soldered a connector for the 5 wires froming from the recording magnets. I tried blasting them with a sine wave added to a 10KHz square wave but saw no sign of the signals when playing back the floppy. 

        I have a new plan: Triple SRAM device for copying and pasting a loop of very blocky “video” :

         

        *****************************************************************************************

        Here’s what I learned :

        version 1 :

        I need to make a smd breakout board for chips or order DIP versions so that I can do tests first. This would save a lot of time designing and redesigning boards. The idea for a minimal integrated board was good though. Break more pins out.

        version 2 :

        BOARD A : I need to make a more stable way to solder pin headers to the card so they don’t rip off easily. I should use buffers to protect the LEDs. There are also way too many jumpers between the the counter and SRAM. 

        BOARD B : The op amps don’t work. The DAC doesn’t work as I wired it. I forgot to connect the CLK of the DAC.  

        It’s a mess to connect the two boards, make the right connections. The two boards need to be integrated. 

        version 3 :

        The EEPROM doesn’t work, is it locked ? I also used the wrong VGA pins. 

        version 4 :

        It’s a beautiful board but the DAC was VERY challenging to solder by hand. I think the level of complexity and ambition of the board was a little bit too high for this production method. I think I should head back to a board that is easy to assemble, easy to test and understand. 

        version 5: 

        The idea : using buffers I can have LEDs display what is in the memory while also outputing analog output. There are fewer jumpers than in earlier versions. I am planning to use the inverter to control the SRAM WR which appears to be possible based on the datasheet. Simplified DAC with R2 ladder, I can control A12 with a switch and have an A11 LED now. I got rid of the VGA functionality – this makes things simpler. I chose switches over shunts to make connections.

        I want to make 3 of these boards, ABC, so that they can each record in two 4K memories, and then do cool logic transformations and save the results too. Connecting the ADC to the SRAM inputs requires 8 jumpers, and I’ve done away with 8 pin dip switches. To manually set data you connect the jumpers to the spare + and – headers. 

        I would like the decisions to be guided by how I could practically use this device to “record” 8 bits of data / an analog signal for a given period of time (based on the clock speed) and then play it back (while modifying the clock speed manually, and overwriting portions of the memory, possibly from another pair of memory boards) to display on a screen (with another board handling the VGA signals and optionally sharing its clock with this board to keep things in sync). I want to move to something that produces output ASAP, and away from endlessly redesigning these boards looking for something perfect. (If this works I want to make 3, then a specialized VGA board too).

        I’ve added reverse polarity protection, a STEP button, which is hardware debounced, to manually advance one address at a time. I kept the op-amp modular so that it could be used to amplify analog in or out. I switched out the edge accessible thumb pots for normal pots, so this thing is no longer really stackable.

        Not sure exactly how they stack (but many things accessible on the edges) though and not sure if I should have a battery included or not so that it remembers what it recorded…

        Version 5 UPDATE :

        Thoughts on possible  version 6 additions :

        Backup battery to record option ?

        8pin dip switch with header somewhere on board?
        Question I have to resolve with current version :
        What can I record (in analog and in digital) and for how long ?
        What does it look like on the screen with and without a generated pixel clock to do the sync?
        Going at pixel frequency speed I can draw different repeating textures on the screen when I record very slowly and then speed it up :

        Patterns are repeating, it’s like a texture. Sending a non-repeating signal, like the arbitrary function signal which leaves a non-repeating pattern on screen, seems like a cool thing to try. Another option is to have a single block of memory but to jump around in how you address it somehow ?
        How fast and how slow can it go ?
        With a 10K resistor and a 0.1uF for the CD4046 I have a max sampling speed of 1Khz that is barely enough to represent a 100 Hz sine wave.
        Apparently this max is called the Nyquist frequency :

        Nyquist Frequency=Fmax = SampleRate/2

        The SRAM module IS61C64AL can run up to 20MHz according to the datasheet (https://www.issi.com/WW/pdf/61C64AL.pdf)

        When I feed it the 3MHz pixel frequency from the modified VGAX it can record a 1.5MHz sine wave and play it back ! The problem when it is going slow is that it just outputs bands every now and then. It could act as a memory of a control signals which would change parameters in a circuit which generates more interesting output. (It could even control an analog computer like this https://the-analog-thing.org/ ).
        The other option would be to have a super fast clock that is connected to the V and H sync, one that I can divide and use to control recording of a large SRAM memory.
        Would second mem board be cool ?
        Not unless I get a bigger SRAM I think and daisy chain a series of 8 bit counters :
        https://www.mouser.fr/datasheet/2/198/62-65WV10248EALL-BLL-462620.pdf
        VERSION 5 UPDATE :

        Here are the issues :
        -I added a reset for the counters to go back to address 0. It takes a while to kick in though – I think because it resets the counter but not the 8 bit storage register ?
        -I added an LED to show when ADD21 is activated.
        -the 74F541 does not like 5V. I replaced it with an 74HCT254 and pulled the DIR pin HIGH.
        -the ADC1175 operates at 4.5-5.5V ! (I will test it’s max speed – supposedly 20MHz by powering it with 5V)
        -One pin connection missing on 8 pin dip switch
        -The phase shifter sucks and the amp doesn’t currently work.
        -CS should be held down and not toggled with WE.
        -RCO for cascading counters was not working at higher frequencies – I switched to sending the last Qout of each counter to the CLK in. 
        -I don’t have a way of taking 5V analog signals and stepping them down to 3.3V.
        -The memory should default to floating (instead of ground?) so that I can re-record over previous stuff. (Currently when I re-record, if a pin is not set it defaults to being black and just erasing everything).
        -need a 3.3V to 5V booster if you want to interface with another 5V memory. It would be nice to have an in-line 8 plug so I don’t need to plug in each wire one by one…
        -I can’t currently take VGA in at 400×800 from a computer (amplified) and saved it into the memory (it’s pixel clock is at 40MHz, I set the function generator to 4MHz). But I can record an image imperfectly from the VGAX color out at around 1.3038210 MHz.
        -I need to amplify at the input and the output (and ideally be able to offset them both and up and down – especially to hit the middly of the CMOS threshold between low and hi if I want to record in image in b&w with a single bit). The next version of the board would have two amps.
        -When I play back a recording, each time the memory restarts at zero, the frame of the video moves. (To solve this I need the freq divider, AND chip and inverter).
        -Pin 11 of the ADC should be connected to 3.3V while pin 13 should be connected to 5V.
        Possible improvements:
        -a 5V power in with 3.3V LDO so I can power things with both ?
        -if I want to upload something to memory, and then change to outputing, I have to disconnect all the wires that were connected to it previously. I should have a 74HCT254 Bus transciever that can change directions to disconnect a set of 8 wires from the memory. ALTERNATE OPTION : Just keep everything plugged in and turn off ADC?
        -Maybe an LED that tells me I’m recording (easy not to notice that it’s not in recording mode and then connect it to outputs that are pulling it up and down). 
        -Would be cool to be able to select which chunk of memory I’m replaying over with two knobs that control the start point and end point. (This could be two comparators connected to two pots ?)
        Developements:
        I can load values into the memory from Arduino’s PRGMEM like so:
        +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        /* TO LOAD DATA INTO THE MEMORY */

        #include <avr/pgmspace.h>

        byte myByte;

        #define IMG_PIRATE_BWIDTH 30
        #define IMG_PIRATE_HEIGHT 60
        //data size=900 bytes
        const byte img_pirate_data[IMG_PIRATE_HEIGHT*IMG_PIRATE_BWIDTH] PROGMEM={
        0, 7,255,192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 63,252, 6, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 0, 0, 0, 0, 0,
        2,255,112, 96,129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        15,222, 2, 4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
        255,240, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
        252, 65,144, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0,
        248, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,144, 0, 0, 0, 0, 0, 0,
        65,132, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0,
        0, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
        36,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0,
        65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0,
        8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0,
        16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 0, 0, 0, 0, 0, 0, 0, 0,
        32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,130,168,160, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34,138, 42, 32, 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        16, 0, 0, 0, 0, 0, 0, 0, 0, 34, 34, 34,136, 32,130, 0, 0, 32, 0, 0, 0, 1, 69, 64, 80, 0, 20, 5, 4, 0,
        32, 0, 0, 0, 0, 0, 0, 8,170,160, 0, 0,170,170, 40, 42,170,136, 0, 0, 0, 0, 64, 17, 4, 68, 64, 16, 68, 0,
        0, 0, 0, 0, 0, 0, 0,162, 10, 2,170,170,170,170,168, 32, 0, 34, 0, 0, 0, 0, 65, 65, 4, 16, 84, 16, 68, 0,
        64, 0, 0, 0, 0, 0, 10,130,171,239,255,238,170,170,160,162,170,162, 0, 0, 0, 0, 68, 1, 4, 16, 65, 16, 64, 0,
        36, 0, 0, 0, 0, 0, 8, 42,187,250,170,170,187,238,250, 0, 0, 34, 0, 0, 0, 0, 69, 80, 80, 68, 20, 5, 4, 0,
        0, 0, 0, 0, 0, 0, 34,170,255,234,170,170,171,187,178, 60, 0,170,160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        152, 0, 0, 0, 0, 0, 0,171,254,170, 0, 2,186,255,248, 61, 3, 2, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        1,196, 0, 0, 0, 0, 10,187,254,168,112, 4,171,191,248, 54, 0, 40,136, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 8,198, 96, 0, 0, 42,191,250,163,240, 14,174,255,254,136,170,138, 34,128, 1,128, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,139,191,250,168, 53, 26,171,255,252,138, 34,186,162, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 42,251,250,170,170,170,174,191,254, 34,187,174,232,128, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 2,170,174,255,186,170,170,187,255,255, 34,234,251,170,128, 0,128, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 1, 0, 0,138,187,187,171,170,238,187,191,255,138,175,255,238, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 10,239,255,186,186,170,238,239,255,224,235,255,250, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 46,175,255,255,238,186,190,255,255,248,171,255,250,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0,170,191,255,255,250,171,187,239,255,254, 42,255,238, 32, 0,144, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 42,238,255,255,251,170,174,187,255,254,174,190,234,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 1,128, 0, 0,174,187,255,255,254,235,171,255,255,254, 10,171,170,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 32, 0, 0, 0,138,174,255,255,255,186,163,255,255,255,162,186,186,128, 0, 4, 36, 0, 0, 0, 0, 0, 0, 0,
        0, 4, 0, 0, 0, 0, 43,187,239,255,254,170,234,170,174,234, 34, 42,168, 0, 0, 8, 2, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 10,174,186,255,251,171,168,128, 10,128, 2, 34,226, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0,
        0, 0, 64, 0, 0, 0, 2,171,239,187,254,234,170, 40, 0, 0, 0, 40, 32, 0, 0, 2,170,168, 0, 0, 0, 0, 0, 0,
        0, 0, 40, 0, 8, 0, 0, 42,190,239,190,186,128, 0, 0, 0, 0, 0,160, 0, 0, 64,170,170,160, 0, 0, 0, 0, 0,
        0, 2,160, 0, 60, 0, 0, 42,171,190,250,168, 0, 0, 10,170,168, 0, 0, 0, 0,128, 16, 10,168, 0, 0, 0, 0, 0,
        0, 42,128, 2,240, 0, 0,130,234,186,170,160, 0,170,170,170,174,128, 0, 0, 0, 6, 0,170,170,128, 0, 0, 0, 0,
        0,170,128, 47, 0, 0, 0, 10, 42,170,170,128, 42,170,175,255,250, 32, 0, 0, 1, 0, 42,170,170,168, 0, 0, 0, 0,
        10,170, 64, 40, 48, 0, 0, 0, 40,162,170, 0,171,255,255,255,234,136, 0, 0, 2, 0, 2,170,170,170, 0, 0, 0, 0,
        170,170, 0,160,176, 0, 0, 0, 0,130,168, 2,191,186,175,250,170, 32, 0, 0, 1, 56, 0,170,170,170, 0, 0, 0, 0,
        170,170,130,130, 64, 0, 0, 0, 2, 8,168, 10,239,255,234,170,170,136, 0, 0, 16, 60,128,170,170,170, 0, 0, 0, 0,
        170,170,128,138, 0, 60, 0, 0, 0, 8, 32, 2,255,255,255,234,186,128, 0, 0, 0, 7,232, 42,170,170,128, 0, 0, 0,
        170,170,160,168, 0,252, 0, 0, 0, 0, 0, 10,175,255,255,251,170,128, 0, 0, 0, 0, 26, 42,170,170,128, 0, 0, 0,
        170,170,168, 8, 0,240, 32, 0, 0, 0, 0, 8,190,187,235,238,168, 32, 0, 0, 0, 0, 4,170,170,170,160, 0, 0, 0,
        170,170,160,170, 0,240,192, 0, 0, 0, 0, 0,170,254,238,170,186, 0, 0, 0, 0, 0, 72, 42,170,170,168, 0, 0, 0,
        170,168, 0,170,128, 2, 64, 0, 0, 0, 0, 0, 2,171,170, 58,160, 0, 0, 0, 0, 0, 2, 10,170,170,170,128, 0, 0,
        170,170, 42,170,168, 3, 0, 0, 0, 0, 0, 0, 2, 10, 42, 8, 0, 0, 0, 0, 0, 0, 1, 42,170,170,170,168,128, 0,
        170,170,170,170,169, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 18, 42,170,170,170,170,168, 0,
        170,170,170,170,168, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54,128, 0, 42,170,170,170,170,170, 0,
        170,170,170,168, 36, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,188, 96, 15,170,170,170,170,170,170, 0,
        170,170,170,170, 0,130, 14, 96, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 95, 0, 63,234,170,170,170,170,170,128,
        170,170,170,170,170,170,143,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0,249,240, 63,234,170,170,170,170,170,128,
        170,170,170,170,170,170,144, 63,240, 0, 0, 0, 0, 65, 0, 0, 0, 15,192, 0, 63,144, 63,170,170,170,170,170,170,160,
        170,170,170,170,170,170,175,239,240, 0, 1, 0, 0, 2, 24, 0, 0, 15,252, 0, 7,228, 15,218,170,170,170,170,170,168,
        170,170,170,170,170,170,168,255,240, 48, 64, 0, 13,129, 1, 0, 0, 3,255, 0, 0,114, 15,250,170,170,170,170,170,170,
        170,170,170,170,170,170,170, 62,192,188, 0, 0, 63,126,192, 36, 0, 2,127,208, 0,185,191,250,170,170,170,170,170,170,
        };

        void setup() {

        Serial.begin(9600);

        pinMode(7, OUTPUT); // I/O 8
        pinMode(6, OUTPUT);
        pinMode(5, OUTPUT);
        pinMode(4, OUTPUT);
        pinMode(3, OUTPUT);
        pinMode(2, OUTPUT);
        pinMode(1, OUTPUT);
        pinMode(0, OUTPUT); // I/O 0

        pinMode(8, OUTPUT); // CLK

        for (byte k = 0; k < 200; k++) {
        myByte = pgm_read_byte_near(img_pirate_data + k);
        Serial.print(myByte);
        digitalWrite(8, LOW); //CLK LOW
        delay(1);
        PORTD = myByte;
        digitalWrite(8, HIGH); //CLK HIGH
        delay(1);
        }
        for (byte k = 0; k < 200; k++) {
        myByte = pgm_read_byte_near(img_pirate_data + 200+ k);
        Serial.print(myByte);
        digitalWrite(8, LOW); //CLK LOW
        delay(1);
        PORTD = myByte;
        digitalWrite(8, HIGH); //CLK HIGH
        delay(1);
        }
        for (byte k = 0; k < 200; k++) {
        myByte = pgm_read_byte_near(img_pirate_data + 200+ k);
        Serial.print(myByte);
        digitalWrite(8, LOW); //CLK LOW
        delay(1);
        PORTD = myByte;
        digitalWrite(8, HIGH); //CLK HIGH
        delay(1);
        }
        for (byte k = 0; k < 200; k++) {
        myByte = pgm_read_byte_near(img_pirate_data + 200+ k);
        Serial.print(myByte);
        digitalWrite(8, LOW); //CLK LOW
        delay(1);
        PORTD = myByte;
        digitalWrite(8, HIGH); //CLK HIGH
        delay(1);
        }

        Serial.print(“FINISHED”);
        }

        void loop() {

        }

         

        ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

        I have a different Arduino to trigger the memory on each pixel and generate the sync signals :
        /* TO TRIGGER MEMORY CLOCK EACH PIXEL AND GEN VGA SYNCS */

        #define LINE_CYCLES 508
        #define HSYNC_CYLCLES 60
        #define VSYNC_LINES 2
        #define FRAME_LINES 525
        #define PIXEL_FREQ 1

        volatile int linecount;

        void setup(){
        pinMode(7, OUTPUT); // VSync
        pinMode(9, OUTPUT); // HSync
        pinMode(6, OUTPUT); // Pixel frequency

        //inverted fast pwm mode on timer 1
        TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(WGM11);
        TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);

        ICR1 = LINE_CYCLES; // Overflow at Cycles per line
        OCR1A = HSYNC_CYLCLES; // Compare high after HSync cycles

        //timer 0 in CTC mode
        TCCR0A = _BV(COM0A0) | _BV(WGM01) ; // Toggle pin on each cycle, no CPU clock prescaling/
        TCCR0B = _BV(CS00); // no clock prescaling
        OCR0A=PIXEL_FREQ;

        TIMSK1 = _BV(TOIE1); // Enable timer overflow interrupt
        }

        ISR(TIMER1_OVF_vect)
        {

        if (linecount == 0) PORTD = PORTD ^ 0x80; //Toggle the most significant bit of port D.;
        else if (linecount == 2) PORTD = PORTD ^ 0x80; //Toggle the most significant bit of port D.;
        else if (linecount == 3) PORTD = PORTD ^ 0x80; //Toggle the most significant bit of port D.;
        else if (linecount == FRAME_LINES) linecount = 0;
        linecount++;
        }

        void loop(){

        }

        ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        UPDATE:
        I finally have a screen I can use to subtract the memory contents with :

        #include <VGAX.h>

        VGAX vga;

        void setup()
        {
        vga.begin();
        vga.clear(11);
        }
        void loop(){for (int y=0; y!=VGAX_HEIGHT; y++) {
        for (int x=0; x!=VGAX_BWIDTH; x++) {
        vga.putpixel(x, y, 3);
        }}}

         

        +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

        I now can use this with an AND chip and my own function gen frequency and output from the SRAM !

        And here are some of the images I’m getting (using an AND also for the clock coming from the signal gen) :

        And here I am trying to record VGA…
        …from VGAX (120×60):

         

        …and from a computer VGA at 800×600 passing along the sync signals:

        Here was what was onscreen :

        Test card - Wikipedia

        I can reproduce this reliably with :
        -op amp taking memory and amplifying it
        -a pixel clock at 1.007MHz (pixel clock for 640×480 of 25.175 MHz divided by 25)
        But it kinda turns on and off and also jumps around on the screen for some reason.
        I also found out I could use the vertical sync along with a counter (taking as input a 4MHz fucntion generated square wave) and a bunch of AND gates to essentially only record only every X frame and store it in memory. This meant I can save way more frames. Getting the right spacing for the frames will be key to be able to store a short video. 
        UPDATE 1:
        I can now save a short video : 695.45 kHz (This is the slowest I can go and still almost see an image) on the function gen AND’ed with the top 4 frequency divisions of the vertical sync. This makes for a burst of image recording every X number of frames.  I then amplify the output to make it visible on screen (and speed the clock up to 695.48 kHz). One problem is that it looks like everything is in fast forward and it’s barely possible to interpret the images. The other issue is once the video starts again from memory its frame moves with regards to the screen. 
        UPDATE 2:
        If the reset is connected to the inverse of the freq subdivision of the vertical sync signal AND’ed with the address 20, it will play the image in a loop and always place it in the same part of the screen ! 
        +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        TESTING MAX ADC SPEED:
        I’m not sure what to make of this as the signal was super noisy but, I can “follow” a sine that is at 50Hz sampling it at 5MHz fine. I’m not sure what conclusions to draw from this…

        VGA controller board :

        -Attiny(?) 
        -several clock speeds to chose from
        -knob to select diff screen resolutions
        -PLL to sync to input VGA? Use an XOR to see delay with signal and then get closer to it ?
        -easy setup to pass input VGA syncs to an output VGA
        -filters to knock out certain frequencies to tune into what I want. 

         

        ANALOG BOARD:

        Based on the Analog Thing functionality (summing, multiplying, comparing, integrating, differentiating, etc.) along with counters to divide the screen by powers of two !

         

        UPDATE:

        Working now on a next version of the 16MB board. The idea is to fix the issues in the 16MB board, add more functionality, and also to move towards a finished board that is more plug-and-play with regards to recording VGA signals and less of a prepared instrument for testing. It’s a test to see if I could make something that behaves like a product.

        One question is if it requires an analog function generator or not, and to what degree the machine is mono-functional or not. (Though I think if it could record video reliably and display to a screen that would already be not bad.)

        Fixes :

        • A21 LED added
        • Top and bottom bias of ADC now controllable with pots
        • op amps on input and output both with variable gain and bias
        • fixed 5V and 3.3V power (ADC and op amps need 5V) with onboard LDO.
        • got rid of phase shifter and 8 pin dip switch
        • CS no longer tied to WR on SRAM.
        • various enables broken out so they can be turned on an off with external control 64KBSRAM
        • counters daisy chained with last address going to clock input of the following counter (no longer using RCO)
        • Replaced 74*541 with 74*245 (so it would have big footprint to let wires pass under but work with 3.3V)
        •  Added VGA in and out connectors and made pass thru mode for input.
        • Added f divider, AND, and NOT gates.

        This board should allow me to test the idea of having a control board chroreograph a sequence of memory operations, and allow me to begin testing the analog board with a stable (not breadborded) video recorder. 

         

        Sunflower Array

         

        The github for this project :

        https://github.com/merlinmarrs/tournesol

        I’ve made the PCB for with the 74AC240 based on this design from http://www.smfr.org/robots/robot_images/dualsolarhead_schematic.png :

        Hoping that it works better than the 540 version with the solar midpoint.

        IT DOES! It is far more responsive and efficient and works with the solar panel! It has a funny quirk where it will first turn the wrong way then correct itself in one direction though…Next i’ll make it on a super small extra compact board and try the other circuit option:

        It’s much more compact that the previous version. The photodiodes could be removed to make it even smaller. It took me around 25 minutes to assemble at a comfotable speed. By far the least efficient element of the assembly is the braided wire which is causing mini shorts :

        There is already some interesting interplay with the two machines side by side…

        3D model of fancy motor version:

        Here’s a version with a tiny gear motor. The motor appears to lock up at low currents however so it doesn’t work super well. It’s also very difficult to attach the motor axle to the bottom platform. 

        With the metal gearmotor it works much better:

        And this version with the panels lower down:

        Here is a tall version:

        Here’s a compact design with a “flipper” arm:

        The idea of pulling the solar panels from the board, exposing the electronics and creating the tilt naturally.

        The little metal cap is actually a nice part of the look of the machine:

        I have made the board thinner so that it fits perfectly over the gear motor:

        Here’s a shot of it looking pretty:

        Llama edition (it’s a heat sink). This photo makes me think I could have fun with shadows like in the 1970 Il Conformista film:

        I see a monocled mustachioed Monopoly man here somehow:

        This idea distributes the things to look at around the machine (one side has solar panels and the gear motor, the other has electronics and the underside gold lettering on the solar panels). When the machine is facing the sun we get to see the electronics. I guess the electronics is also sheltered from the heat of the sun a bit?:

        Here are some feet ideas for the resin printer using small set screws and (in the right model) Pogo pins:

        Here are two versions of the tripod design. One has the electronics as a backpack and hides it from the sun, the robot has two faces. The other has the “face” of the robot face the sun, in one photograph the whole robot is visible.

        Version 1:

        Version 2:

        ****

        Side to side comparisons:

         Another idea for pogo pin feet using the crowned tips:

        ***

        I made the barebones circuit in extra slim also:

        debugging the previous version, it appears that the solar panels are indeed producing the expected voltage and current (2 x 1.67V, 18.4 mA), the voltage trigger and mosfet are working, the capacitor is charging, and the voltage to the motors is spiking. However the motors aren’t so much turning as twitching. The motors appear to be identical to others that are working however. Changing the capacitor from .22F to .15F changed nothing. 

        EDIT:

        I had another stab at this:

        I noticed that the charging and triggering part of the circuit appeared to be working but that the motor was not firing. I assumed then that there was a soldering problem on the 74AC240 pins somewhere. I tested a copy of the same boards from the same batch to see if there were any problems with the etching itself, they all seemed good with no shorts and clean traces. I tested a blank 74AC240 as well and found that the only pins that were internally connected were 9 (Y1) and 10 (GND) – though I’m not sure why this is the case. I took a voltmeter to measure if there were any shorts between the pins on the IC and found that everything was mostly normal. Looking under the microscope it occured to me that the problem might be that the pins of the IC aren’t fully touching the pads below as they appeared to have been soldered quickly. In order to assume myself that everything was indeed well connected I reheated each of the pin connections and retested that I didn’t introduce any shorts. I then switched out the larger motor for a more efficient smaller DC motor. Testing with artificial light I now have normally functionality!

        The second malfunctioning solar head has a different issue: It charges up fine from having no power and spins the motor no problem. But after a few times it stops triggering at hovers around 3.6V…I resoldered the connections and had the same issue. The voltage trigger appears to be triggering despite the voltage staying high. In the end I switched the bigger metal gearmotor for a small vibe motor and it worked just fine. I think I can conclude from this that the circuit I used is not suitable for the metal gear motors but works fine with smaller ones.

        I am now looking into making this circuit even smaller using TSSOP-20 packages of the 74AC240 and maybe 0603 smd components too. I plan to make this double sided and to have the boards made at PCB way after testing a prototype circuit in the lab.

         

        The circuit works fine after I had to resolder some of the IC pins to the pads (they seem to hover just above sometimes despite the soldering) and fixing a short between the two sides of the MOSFET by lifting up the positive side of the SMD cap up.

         

        Testing with a single 3.4V panel and…it turns! I’m going to try to add the light detection now.

        And this is how it could be integrated into the 2DOF design: 

        This is a second option which would involve probably halving the above circuit and making it double sided. 

         

        Another idea is to see how far this minimalism and miniturization can go, for instance with a single solar panel capable of charging up the cap to 3.3V ish. It could be 1DOF or 2DOF. Testing with the power supply with 4,46V @ 5,9mA it works no problem with the small gear motor. We’ll see if that’s the case with the actual solar cell soon.

        Monocrystalline Solar Cell 24.5mW (4,46V Current – Short Circuit (Isc) 5,9mA)

        https://www.digikey.fr/product-detail/en/anysolar-ltd/KXOB25-01X8F-TR/KXOB25-01X8F-DKR-ND/10127250

        KXOB25-01X8F-TR ANYSOLAR Ltd | KXOB25-01X8F-DKR-ND DigiKey Electronics

        Monocrystalline Solar Cell 26.3mW 5.53V:

        https://www.digikey.fr/product-detail/en/anysolar-ltd/KXOB25-02X8F-TR/KXOB25-02X8FDKR-ND/9990483

        KXOB25-02X8F-TR ANYSOLAR Ltd | KXOB25-02X8FDKR-ND DigiKey Electronics

        Here is what it could look like 1DOF:

        …and 2DOF:

        If the solar panels are a bit offset from the boards then the light sensors could be directly on the board and not need to be offset themselves from the board. 

        ****

        I actually have one of these lying around to test the one panel idea (3,4V
        @ 4,4mA): 

        https://www.digikey.fr/product-detail/fr/ixys/KXOB22-01X8/KXOB22-01X8-ND/2754274

        Here it is working! (remember that the “GND” side of the photo bridge actually connects to the ENABLE of the 74HC240)

        some other panel configurations:

        I could have the light sensors on either end. 

        A little higher up…

        Satellite inspired:

        Here’s a quick 3D print:

        Not even sure if adding another DOF will have a big effect, over the course of a day how much will it actually tilt up or down?…

        Dual Solar Tracking Part III

        Another idea is to start with the actual solution (two small servos) and make it look better. It’s sturdy and already balanced. It just needs a hinge and a tilting arm:

        With a makeshift hinge and tilt arm:

        This would only require an Arduino mini pro and some super caps charged by a solar panel through a diode.

        Some other more simple options:

        For a miniature 2DOF.

        A mini 1 DOF.

          The 2 metal gear motor design I was working with early on.

        *****

        Here is a super simple two servo motor controller that recharges supercaps through a diode:

        This works with the code below as a test:

        #include <Servo.h>

        Servo myservo1; // create servo object to control a servo

        Servo myservo2; // create servo object to control a servo

        int pos = 0; // variable to store the servo position
        int threshold = 100;

        void setup()
        {
        myservo1.attach(5); // attaches the servo on pin 9 to the servo object
        myservo2.attach(6); // attaches the servo on pin 9 to the servo object
        }

        void loop()
        {

        if (analogRead(A2)-analogRead(A3)>threshold)
        {
        myservo1.write(90);
        delay(15);
        }

        if (analogRead(A3)-analogRead(A2)>threshold)
        {
        myservo1.write(-90);
        delay(15);
        }

        if (analogRead(A4)-analogRead(A5)>threshold)
        {
        myservo2.write(90);
        }

        if (analogRead(A5)-analogRead(A4)>threshold)
        {
        myservo2.write(-90);
        }
        }

        This is the monster in all its tentacularity:

        ****

        Testing the barebones circuit with the solarbotics white DC gearmotors and the SMD solar engine. It works with only two mini solar cells and the SMD cap as long as the sun is medium strong!

         

        This is exciting as a result (but I just needed the change the motor wire polarity):

        Here’s what the circuit looks like:

        This suddenly stopped working and I did the following things:

        Checked to see if the cap was charging, if the voltage monitor was triggering (and I manually triggered the MOSFET to see if the motor fired), the voltage at the midpoint between the two photodiodes, and if there were any shorts.

        In the end I replaced the zener with a normal SMD diode which I found, replaced the photodiodes with green LEDs because one lead was broken on the photodiode, and then discovered the motor was broken (or at least the blue wire was disconnected on the inside)! It gave me a chance to look inside the tiny gear boxes of the motors though: 

        Here is the, once again, working prototype:

         

        I would like to be able to tune the midpoint between the LEDs. I would also like smd light sensors. 

        Phototransistor Output Voltage Circuit connects the phototransistor and 2 k-ohm resistor in series

        Some options for solar panel and motor assemblies:

        Here’s with SMD LEDs soldered on:

        Not sure why but the thing is only turning clockwise…

        I tried the following things:

        1. A 10K trimpot (with each photodiode into each side of the resistor and the variable pin going to the logic chip). The trim pot at either extreme does indeed make the circuit turn in the opposite direction. However, in the middle it stops either side from firing.
        2. Replacing the photodiodes with Silicon PIN Photodiode BP34s, green LEDs 5mm, Green SMD LEDS, and LDRs.
        3. changing the ground of the photodiode pair to the ground of the capacitor instead of the ground connected to the floating connected to the MOSfet.

        Just found this image here (http://solarbotics.net/library/circuits/bot_popper_240.html) which seems to imply I could use phototransistors also:

        Looking at other Smart Head circuits, it looks like the + side of the photodiode pair is connected directly to the Vcc but that the negative side is connected to the “local” ground, not the negative of the capacitor. However, there are also counter examples…

        I tried just setting up the dual photodiode circuit on a breadboard. Two photodiodes , two LDRs etc. They each move from a midway value up or down depending on which device is in the dark. However, they don’t always have 1/2V as a midpoint, which appears to be the important threshold point for the oscillator. **EDIT** I think what they meant was half of VCC not 0.5V. I could try to find the exact threshold voltage that is the balance point with the power supply?

        2.25V for my desktop breadboard version of the circuit while supplying 4V for the solar panel. 2.85V was the threshold with solar panels at 5V. It also has a dead zone where neither motor will fire if it is perfectly in the middle. 

        For the soldered version the threshold is around 1.3-1.4V when being fed 4V as solar panel. 

        At 3.5V solar panel supply, I have a lower threshold bound of 1.25V and a higher bound of 1.4V. In the deadzone neither direction turns. 

        At 3V funny things happen. It will only turn one direction unless I suddenly make the input 0V. This might explain why my circuit is behaving strangely! I am using a 2.92V voltage supervisor so I don’t think my current circuit is ever going to work. 

        I should replace it with a higher voltage threshold like this one perhaps: https://www.mouser.fr/ProductDetail/968-ISL88001IH46ZT7A 

        In the meantime I can use a voltage divider like I did for the 1381. 

        Here’s the scope output attached to one lead of the motor. The fat, fuzzy part is when the motor is not turning and the threshold is reached. Either side it sends between 1.5-2V to the motor turning one way or the other.

        Setting up my own little trim pot between the LDRs I was able to tune them to the correct voltage threshold and everything works well on a breadboard at least.

        Here is the 74AC240 datasheet: 

        Checked out the 74AC240 datasheet, for 3.5V the threshold should be between 0.9V-2.1V.

        ****

        Version 2 of the board has trimpots for the voltage trigger and the light sensors (which are now SMD and on either side of the board):

        Here are the parts laid out with the new board:

        Post-soldering. The size of the board versus two small solar cells:

        I had to put electric tape under the trim pots because contacts were exposed underneath…  The full assembly:

        ****

        Found this online here (http://www.smfr.org/robots/robot_images/dualsolarhead_schematic.png): 

        It uses the solar panels as the light sensors! It also lays things out in an easy to understand way (the midpoint is the boundary between what the inverter sees as HIGH or LOW. Once the solar engine has enough power this decision of HIGH vs. LOW then powers the motor through six remaining gates – presumably to increase the current as each pin seems to be limited to 75mA according to the datasheet above?).

        ***

        Testing V.2:

        I can get 3.5+ volts (4V outside in full sunlight even) with the current setup of two solar cells + little cap!

        BUT…When I short the voltage supervisor 5K trim pot the motor fires, but even in its least resistance position the supervisor is not triggering…It is also only doing mini movements, not full shots. I removed the trim pot and now it behaves normally. I don’t understand why the trim pot doesn’t work when it was flawless with the benchtop power supply…

        With a 1M trimpot the variable voltage trigger does work just as expected, however! I moved it up to 3.5V ish.

        The 5K trim pot for fine tuning the light sensors also does not appear to work. Also doesn’t work with a 1M and two green LEDs…

        I tried using the two solar panels as sensors as suggested in the found circuit and it appears to work, there remains the same problem of how to tune the voltage level however if my trim pot solution doesn’t work. 

        ***

        I think I need to order 74AC240s (I think the 74LS540s I am using might be slightly different in terms of their HIGH/LOW thresholds) or voltage triggers for 3.5V+. This is a nicely tuned circuit that seems hard to mess with.

        Just a reminder of how much the complexity has been reduced in this project!:

        ***

        I have realized I need to understand the circuit I am working with better in order to tinker with it. 

        First thing, the 74LS540 that I am using has a minimum voltage of 4.5V! It also can only supply 45mA max as an ouput if I understand correctly. However, I also have a 74F244D octal buffer which works as low as 2V. However it is Bipolar and not CMOS technology like the 74AC240 AND more importantly, it has non-inverting outputs. Clearly getting the right logic chip and family is an important element and not a detail for this circuit…

        So, the LDR “photo bridge”. After testing 10 we had lying around I arrived at these average values:

         

        Here’s some R Thevenin calculations (Thanks to Learning the Art of Electronics!) to figure out what size pot I can afford to pull up or push down the midpoint from the LDR divider:

         

        And here’s the current logic circuit in a more understandable format:

        ****

        Did some tests, looks like I need to bring the midpoint DOWN in my circuit:

        Yellow is the cap voltage (3.42V) and green in the midpoint (2V) with equal light on both phototransistors. 

        This scope image shows first both photodiodes in light, then the left (connected to GND) in darkness, and finally the right (connected to VCC) in darkness:

        Without even needing to take any measurements it’s evident that the midpoint is too high. This causes the motors to always turn the same direction when the light intensity is equal between the two phototransistors. I flipped the photo transistors and observed the same effect so I think it’s the circuit not the difference between the phototransistors.  

        This scope image shows me adjusting the phototransistor trim pot. (Fully attenuating on the left, halfway in the middle and then fully open on the right). 

        And here’s testing with the middle threshold covering and uncovering each phototransistor:

        This shows that the 10K trimpot effectively drops the entire midpoint! I can effectively dail in the midpoint to exactly half of VCC now (3.42 Vcap, 1.71V threshold)!:

        Now the machine is not turning in only one direction! But it also might need some resistors for when the two photodiodes are both seeing bring light. I also need to replace the LS540 with an AC240 because I am currently operating outside the maximum minimum voltage of the IC. It would also be nice to use the solar panel as a sensor and thereby reduce the part count (I could still tune the midpoint in the same way once I determine which way the imbalance is – it would also solve the shorting problem in high light). 

        I varied the pot and everything is working as expected. I also added heat shrink to the phototransistors. Here is a video:

        I tried some 2DOF designs but I think this needs to stay MINIMAL and the force of the project, if it comes, will come from the array more than individual complexity. Plus they already seem imbalanced and more likely to malfunction…

        Some tests with the solar panel voltage divider:

        Here’s what it looks like when I change the solar panel midpoint with the 10K trimpot:

        Here is the solar panel midpoint trim pot all the way to one side:

        Here is the solar panel midpoint trim pot all the way to the other side (not sure why it goes all the way to the ground here only):

        Here is me putting one panel in the shade, then the other. The difference is not massive.

        The problem is that now I fall into a large deadzone where no movement happens in the middle. I’m trying to find the right combination of voltage trigger trim level and solar midpoint level but it’s not easy without sunshine…

        ****

        Here’s the cost per unit of this design:

        74AC240: 0,462 €

        0.2F cap: 1,21 €

        solar cell: 3.56 € (1.78 € x 2)

        micro gear motor: 4.25€

        voltage trigger: 0,356 €

        diode + 0.47uF cap: 0,1€

        PCB: ?

        Total: 9.938€ + PCB cost

        ****

        I have now a 1M trimpot on the solar midpoint and have added a 1M between the midpoint and VCC to try to balance things out.

        I think 3×3 is better than 4×4 ? 5×5 would be out of control.

        ****

        Working towards simplifying the dual servo sun seeker. Here is a post for controlling servos without a microcontroller:

        https://www.pololu.com/blog/18/simple-hardware-approach-to-controlling-a-servo

        Could use LDR pair to replace pots inside the servos, based on ideas from Hackaday post shared with me by Paolo Salvagione:

        Light Tracking Robot Relies on LDRs

         

        ***

        Went back to the super simple business card sun shaker and added some feet. I also tested the new 0.2F caps and they work with outdoor light but might be too tough to charge with indoor light (unless it’s actually bright then they work fine). After Paolo Salvagione’s comment about using a smaller motor to rotate the device, it occured to me that I could use the vibe motors in two directions to create movement that follows the sun:

         

        ****

        Ordered this motor: 

        Here is a new design with (human) adjustable tilt. It has more of a “pro” vibe. The motor adds 5 euros to the total cost of the machine bringing it up to 15 euros:

        ****

        Looks like the trick with the light sensing is just to put the photodiodes behind the board so that the shadow cast by the sun creates a clear preference for one side or the other. They can be bent around a little bit to be perfectly tuned but it also adds a bit of idiosyncracy to the ‘bot. So it doesn’t appear that I need a trim pot for this option. I’m not sure how to create the same contrast with the solar panels as putting either in the shade is obviously not a good idea. Pointing them in different directions creates some difference but not a great deal.

        ****

        I’ve redone the circuit for the 74AC240 and make it more compact:

        Here is my next design with the smaller DC gear motor. I’m imagining a soldering a pin to the PBC in order to attach the pivoting arm to it. Otherwise the issue is how to make this attachment without creating a whole frame and bumping into components etc. It has a small M2 bolt to fix the print to the motor and to adjust the angle:

        I’ve made a cleaner video of the first prototype:

        Dual Solar Tracking Part II

        Continuing the project of making a small solar tracking device.

        ****

        Idea to simplify the circuit drastically and make the 3D model a bit more robust and less fragile so it is far easier to assemble and won’t topple over (while hopefully maintaining some elegance…) 

        -Battery-powered (and possibly solar recharging through very simple circuit):

         

        plus Attiny with two steppers only powered directly from output pins (max 40mA and danger of kick back which might be solved with diodes) and no light sensing – just the almanac algorithm for sun following. *

        *(Remember you can test the stepper resistances to know which are pairs!)

        Tried powering a stepper directly with an Atmega using the Stepper library in Arduino with a bunch of different step and speed values – if it turns at all it’s extremely weak…So this doesn’t appear to be an option.

        Tried powering an atmega328 directly to cap and solar panel through diode, in medium sun there is no action. With bright sunlight it manages to power up despite blinking a blue LED every secon. I could try with the sleep timer I recently acquired (https://www.adafruit.com/product/3573). Or maybe a simple sleep code will be enough. This seems like a viable option which would simplify the circuit considerably.

        Another cheap and simple option is the ULN2003, but this requires 5V to function unlike the low power DRV8833 I have. 

        ***

        Tried driving the stepper gearmotor chain drive and it moves very smoothly and almost imperceptably. 

        I dug up some DC DVD raft drives, they are nice mechanisms:

        The black rack was attached to the raft. 

        I tried powering these with Wilf’s SPSH circuit and the bearbones solar head and they were too big a motor to be powered unfortunately. I could still try to increase the 1381 trigger level with a resistor though…

        I’ve redesigned the microchip version of the board to make the wiring to the stepper much easier this time. I’ve also added two caps to smooth out the motor supply. 

        And here is a more robust version of the previous two stepper, this one has two parallel bars, a more robust hinge, and the lower bearing is encased completely for more stability hopefully. I am also getting rid of the lead screw plastic piece and trying to replace that part with a thin metal rod. In general it’s simplified and a bit thicker all around :

        I am using a dremel to clear out the holes before inserting things and this is reducing shattering of the more fragile white resin. 

        The bottom bearing:

        Part of the solar panel hinge:

        Only one of the two stepper drivers worked on this board but I haven’t found the issue yet…I wonder if back reverse polarity I destroyed it by accident or over heated it during soldering. I’m going to replace it with a fresh one and see if that changes anything.

         

        Here’s the assembled machine:

        Here is a look at some of the technical details:

         

        A different panel orientation option: 

        Comparing the two versions (the newer is far more compact and stable but less playful and off-beat/asymmetrical):

        Check out the angle range, it’s better than I expected!

        ERRATA:

        1. The idea of putting a pin accross to act as the lead screw is not working with only one side screwed in. AND the lead screw platform is impossible to insert into position (I had to break it in half and glue it back together once in position). I should definitely not try to go under the lead screw, with the nut that holds the pin, it actually makes contact with other nuts holding the whole linear rail assembly. I think I should go back to integrating the existing plastic lead screw – aesthetically it adds more flavour and asymmetry.
        2. The part that attaches to the panel should be one connected part because this gives more surface to attach to and more rigidity. (X)
        3. There is a volume which enters into the bearing socket that I needed to remove with the dremel. (X)
        4. The three bottom holes for screws are not evenly spread out around the circle. (X)

        POSSIBLE CHANGES:

        1. Tensioner for bottom chain or larger bottom gear?
        2. The top hinge is too symmetrical for my liking but otherwise it’s super stable.
        3. Transparent resin is definitely nicer.
        4. The bottom nut needs a tiny bit more room, but it just works.
        5. The bolts are hitting the bottom stepper gearmotor.

        Here is a new version which solves the errata, but it looks hideous:

        I am considering returning to a one bar setup. I am also considering how I can make one version of this device that will work for the different linear actuating steppers and the different rotational motors (the micro steppers and DC gear motors have the same face plate thankfully). The top and bottom of device are also not connected (so varying heights of linear drives can be accomodated). Should one single design be able to work with belt drive or chain? I think I should now focus on producing a bunch of these.

        Here is how the little plastic parts that act as lead screws work:

         

        There are all kinds of shapes but in the end they all appear to have one main screw location and a bunch of other nibs and slots to help with alignement. I can include a sliding slot for the main screw in the 3D print but I may use a dremel to adapt it to different nib locations. 

        I’ve revisited the version 1 and have made the following changes:

        1. I’ve kept the more robust base from version 2.
        2. I’ve revised the lead screw plastic part holder and made the print compatible with the highest number of these peices and allowed for longer stroke.
        3. I’ve kept the magical setup that allowed for a great variation in the panel angle.
        4. I’ve kept the circular base which is more stable and made a larger base gear so it looks more stable. (The pitch of chain I am using is 0.1227″ https://www.mcmaster.com/miniature-roller-chain-sprockets/pitch~0-1227/)
        5. I adjusted the motor so the bolts are no loner hitting the bottom stepper gearmotor.

         

        ****

        Wire management:

        I like the ribon wires from the CD drives and the mini locking sockets and plan to use them: