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.
>> Check out this super fast 1Mx8bit SRAM
Also would be cool to be able to output blocky animations based on memory. Could vgax output memory values? Then could compose.
#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 ?
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)
#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() {
}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#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(){
}
#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 from a computer VGA at 800×600 passing along the sync signals:
VGA controller board :
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.