_Project Overview (-)2.0

Apparently I've done a lot of writing and rewriting, having nearly completely forgotten that I'd written it before. Oy. Anyways, here's apparently a more "formal" overview of my most recent projects... discovered burried in SDRAMThing2.0's code-folders.

It has the benefit of going into more detail as to the actual limits pushed in these projects (SDRAMThing and LCDdirectLVDS, specifically.)

----------------

This project demonstrates several concepts which I think to be unique...

pushing the documented limits (and even far-exceeding them) in ways that

technologies that might have seemed out of reach to the typical hobbiest

are now available to them (DIYer, "Maker", "Arduin-ite", whathaveyou).

Much more worthy examples of this sort of thing being done is the

prevalence of USB devices made out of 8-bit (e.g. "AVR", as used in

Arduinos) processors... These devices were in no way intended to work as

USB devices, but someone pushed the limits and that work has since become

so common-place that even the hobbiest can create USB MIDI devices for

lighting their concerts or Burning Man projects, creating interfaces for

tool-changing in "The Gimp", or just hacking around with Max or PureDigital

SDRAM:

* "Free-Running"

Once the memory is loaded, by using a feedback loop, it can control

itself completely independent of external control (e.g. a processor).

* Refresh Requirements

The specifications claim that refreshing the entire memory must be

accomplished every 64ms... with a 64MB SDRAM that means a *significant*

amount of time must be spent doing nothing but refreshing the memory!

My experiments have shown that the reality is that many memories can

endure for far longer than this requirement. On the order of 10 seconds!

* Refresh Methods

Though not documented, the mere act of *accessing* a memory location

causes its contents to be refreshed.

* Documented "refresh" methods require that the entire memory be idle

Meaning it cannot be used for other purposes during this time

* By, instead, "activating" a memory location, as though it's about

to be read, without even intending to read it, its contents are

refreshed. Because of the design of SDRAM, this means that e.g. a

"burst read" can be going-on at the same time as satisfying memory

refresh requirements, by activating and deactivating memory

locations while reading another.

* Writing/Reading methods

While writing memory locations can be accomplished one location at a

time, *reading* always occurs in bursts.

(A "burst" of "1" memory location is an option, however with a slow

processor and many wiring-methods, it would be quite difficult to meet

the timing-requirements necessary to read back that one memory location

at the instant its output is available).

Several methods have been addressed in these experiments, depending on

the wiring-scheme.

Write:

With an 8-bit processor it's nigh impossible to send the "Write"

command to the SDRAM at the same instant as sending the addresss and

data, as the SDRAM requires.

By setting up the address and data while NOP is on the command bus,

then sending the write command followed immediately by NOP, a write

to a single location is possible.

Read is more difficult, due to its "burst" nature.

But there's something to be noted: read (and write) commands can

occur back-to- back at "random" locations.

By setting up the address first, then writing the "read command",

the memory will, essentially, receive the same "read command" from

the same memory-location repeatedly...

Each clock-cycle on the SDRAM is then a "new" read-command, which

stops the previous read-burst and initiates a new read-burst from

that same memory-location.

Giving time to set up the data-port as an input, and read it.

These methods may be usable even when the SDRAM is running at a much

faster clock-speed than the processor.

While the SDRAM specifications claim the data output will be in an

"unknown" or "undefined" state for quite some time between each data

output (on each clock cycle), experiments have shown it to be quite

stable...

When "reading" the same memory location repeatedly, it appears to

remain at that data-value constantly, making read-back at slow rates

feasible. (This may be somewhat dependent on what's in the surround-

ing memory locations, and the length of the read-burst initiated.)

Likewise, if the SDRAM is running at a much faster clock-rate than

the CPU while *writing* we can take into account that write commands

can also occur back-to-back. Thus, even holding the "write command"

on the command-bus for several SDRAM clock-cycles will just cause it

to write the same memory location with the same data repeatedly.

It's possible to do quite a bit, as well, with the DQM ("Data Mask")

pins and "burst" mode. This is especially true when the processor and

SDRAM are running at the same clock-rate

(or with some use of one-shot "glue logic").

E.G. the latest wiring-scheme uses one processor pin for each SDRAM

command pin, and because of the "free-running" method used, these

pins are *also* directly tied to the SDRAM's data-pins. When Free-

Running, the SDRAM's Data Pins output command-instructions back to

itself. E.G. at the last memory-location in a read-burst, a new

read-burst is initiated at the next memory-location. That command is

sent *from* the SDRAM's data Outputs back to its own Command pins.

Thus, writing and reading via the processor becomes more difficult,

as the processor must first use each pin to send the "Write" or

"Read" command to the SDRAM's command inputs, then switch those same

pins to the data to be read/written. So how is this accomplished

when, e.g. for "Write", the SDRAM usually looks for data at the same

instant the "Write Command" is received? Data-Masking. By essentially

telling the SDRAM to ignore what's on its data-bus until that data is

actually available.

Whereas generally the DQM pins are used for the

case where multiple SDRAM chips share the same command and data

busses, when only one chip is to be written, instead we're using it

to use the same bus for command and data on the same chip.

This leads to some timing issues. When the processor says "write at

this address" that's the address that is being masked... the actual

data will be written several addresses later (due to the write-burst)

So it's just a matter of knowing which address we intend to write to

and how long it will take to set up the data and "unmask" it.

So, again, even though we're writing only one memory-location, we're

making use of the "write-burst" method.

While this read/write method is a bit slower, it has the benefit of

saving quite a few processor pins, while also requiring zero (that's

right! Zero!) additional components; no glue-logic, no resistors...

Just the processor, the SDRAM, some wire, and a clock-source for them

both. Also, it does-so in such a way that it's wired perfectly for

free-running.

* Where can this go...? I dunno, exactly. Having 256MB of 133MHz 64bit-wide

free-running data could be useful for something. I've used it to drive

an old laptop LCD at full-resolution, full-color. Once the memory is

loaded, no processor intervention is necessary to refresh an image on

the display.

Other thoughts are:

* Data-logging; with a bit more development a 64-bit wide 133MHz

logic analyzer could be designed using little more than an Arduino,

an ancient and practically unusable SDRAM stick, and *maybe* a

handful of glue logic.

* I've vague thoughts of whether this method could actually be used

as a processor of sorts, instructions stored in certain memory

locations.

I've certainly thought of "NOP" and "Jump" which

could be used for on-the-fly signal-generation...

* Thoughts on parallel free-running SDRAMs, such that one could be used

to write another, and vice-versa...

* Not *fully* understanding USB, it may be possible to use in a way

similar to the 8bit USB devices, except running at full-speed (?)

Most of these ideas have nowhere near the potential to become as

ubiquitous as the 8bit USB devices, but who knows...

LCDs:

* TFT displays have memory at each pixel, so refresh-rates and data-rates

can often be slowed to speeds that even 8-bit processors can accomplish,

without dramatic fading of the image inbetween refreshes

* This particular display has a few quirks which can be made-use-of...

(And may, indeed, exist in other makes/models of most old TFT LCDs?)

By supplying it with a simple signal that's not at all documented,

the display can be forced into a mode where whatever data is stored in

its horizontal buffer will (gradually) be repeated across all rows.

This signal is so simple the entire circuit can be built of nothing more

than a handful of TTL chips, causing the display to hold columnar

patterns of color. E.G. by loading all the columns with a single color

the display can be used as a solid-colored "mood light". Changing the

color bits causes it to slowly fade to the next color.

One possible use: E.G. as a changeable color-filter for stage-lights...

This could *easily* be accomplished with an 8-bit microcontroller.

Another equally-simple signal/circuit causes the display to refresh.

By introducing some randomness in the signal, random color-bars can be

loaded and refreshed continuously... It's hard to describe, but one such

source of signal-randomness is simply the "bounce" on a push-button.

E.G. with a simple circuit and a pushbutton can be made a sort of "zen

machine" which changes patterns each time the button is pressed.

LVDS:

* At the base-level, LVDS appears to have been designed around technologies

already standardized long before it was used in everyday devices.

* TTL chips from early 1980, when pushed just beyond their specifications,

actually appear to satisfy many requirements for LVDS signalling;

Voltage levels are correct, due to "heavy" loading

(These devices were made to drive a few high-impedance inputs at

close to 0V and 5V, but by driving the low-impedance load of an

LVDS input, the signals are more like .5V and 1.5V, which is

pretty durn close to exactly the LVDS specifications)

"PW-Banging":

In an earlier project, leading up to this one and not nearly so

documented, it was determined that a special mode of Pulse-Width-

Modulation signals (usually used to create variable voltage-levels for

motor-control, etc) could be used to drive the high-speed serial signals

necessary for LVDS.

Using this method serves several purposes:

* The PWM outputs on some processors can be driven at much higher

clock frequencies than the processor itself. Leading to faster

refreshing of the display, 8x in my case. Also allowing for displays

whose clock frequency requirements exceed those of the processor.

(In fact, this method was used initially to simulate signal rates

originally tested with the display connected directly to a computer)

* Much of the time used to send signals to the display is spent sending

the same data repeatedly: E.G. For a "Horizontal Sync" the data sent

on the LVDS pins is identical for dozens if not hundreds of cycles.

Thus requiring loading of the PWM control registers once, then

allowing it to run repeatedly.

Due to the nature of PWM, being that it usually turns on at a certain

point in a "cycle" then remains on until the end of that cycle, certain

considerations had to be made with regards to the types of signals

needed by the display. E.G. on the "Red" wire, it would not be able to

turn on bit 0 and bit 4 without turning on the bits inbetween.

For the wire carrying the syncing signals, this is even more complicated

as each sync bit has its own purpose, and this same wire *also* carries

the blue bits.

In the end, 48 colors were possible, spanning the whole range from full-

off, to full-on in each of the three colors, and in every combination.

Using the repeating-nature of PWM, and taking into account the frequency

difference between the CPU and the PWM, the simplest implementation, at

the LCD's documented refresh rates, allowed for 32 individual pixels by

32 pixels, stretched across the entire display.

Slowing the LVDS rate to that of the processor allowed for resolutions

as high as 3 physical pixels per each drawable pixel.

(1024/3 ~= 340 pixels, horizontally)

Because each row is drawn separately, the full vertical resolution is

attainable (340x768) at about 1/5Hz refresh-rate.

"Row-Segment Buffer"

In that same project, one of the greatest limitations is the amount of

memory in the processor; 512 *bytes* total... hardly enough for an entire

image, and not even enough for a single row of pixels (especially in color)

By taking into consideration many images drawn will consist of long

segments, in each row, of the same solid color, memory requirements can be

greatly reduced. Each item to draw on the display has its own "section" on

the screen. But much of the space between these sections is solid white or

black. Thus that entire "row-segment" can be represented in a single packed

byte containing color and duration. If the duration is longer than can be

stored in a single packed-byte, another can be used.

Text, on the other hand, requires quite a few short-horizontal-segments.

Since there's not enough memory for 340 separate segments to fill an entire

row, (in addition to the other memory requirements of the things being

displayed), rotating the text 90 degrees (and thus the screen) is a much

better method. In this way the refresh scrolls from left-to-right instead

of top-to-bottom, the "row-segments" are actually "column-segments", etc.

But, in this way, several full lines of text could be drawn.

This all implies that each row is calculated during the LCD's "Horizontal

Blanking Time". These calculations actually take longer than the time taken

to display them. But the display was found to be quite satisfied with such

long "blanking" times. And during all that time the data sent to the

display is repetative (making use of the "PW-Banging" method) requiring no

additional CPU time to keep the display supplied with a valid signal and

therefore synced.

-------------