Tag Archive for programming

Controllerless Graphical LCDs, part 2

It is useful! As expected, RAM and CPU consumption are major issues. Saving RAM by computing the data to send to the LCD line by line proved to only be possible for text and extremely simple graphics, even with overclocking. The timing requirements are far looser than those involved in generating video signals, but the refresh rate needed to avoid flicker is actually quite high, the LCDs are intended to be driven at 60 Hz. This leaves 260 microseconds to compute each line. Another annoyance is the LCD drive voltage, which is a negative supply rated to be as much as -20 volts…I’m now using the charge pump from a MAX232 level converter for the LCD supply.

I switched to frame buffers in RAM and upgraded to an ATmega32 I had lying around. It’s still not light on the CPU: even with text and frame buffer graphics, it consumes roughly 30% of the CPU time of a ATmega32 running at 16 MHz, varying depending on refresh rate and the specifics of what is being drawn, and on display size…graphics is somewhat faster than text, and displays much larger than mine probably can’t be used without blanking the display while other operations are being performed. Worse, gray pixels are indicated by setting pixels in one of two buffers, full black by setting pixels in both buffers, and displaying each buffer for two frames before switching to the other, to avoid odd effects due to the LCD responding faster in one direction. This requires two frame buffers, doubling SRAM consumption, and also requires a higher refresh rate to avoid flicker, which means even fewer cycles free for other things. I ended up using nested interrupts to allow timely LCD updates while without bringing everything else to a halt, an approach which seems to work well.

There’s not enough RAM on the ATmega32 for a full-screen frame buffer, but mixing text and graphics is fairly trivial. You could of course store larger static bitmaps in flash, this isn’t something that interested me. It is quite straightforward to split the display into quarters based on the column controllers, though, and I’ve mostly been using it as a 7×24 character text display (with 8×8 pixel characters and 1 pixel line spacing), and a 64×64 graphics area with gray support. This takes a 168 byte character buffer and two 512 byte frame buffers, 1192 bytes in total. The ATmega32 has 2048 bytes of SRAM, leaving 856 bytes of SRAM free for other uses. I could just barely do a 7×20 + 64×96 mode (1676 B), or I could drop the grays and devote up to 3/4 of the display to graphics. Since there are 2048*8 pixels on the display, you can also simply draw all RAM onto the display, with some interesting results:

The gray pixels are a bonus, the display was never intended to support them. On my display, they flicker badly at less than 80 Hz, but this likely depends a great deal on display and driving voltage. Flicker in gray shades can be reduced by setting alternating pixels in each buffer. Eliminating gray pixel support halves frame buffer RAM usage, or doubles screen area that can be used for graphics, and considerably reduces the redraw rate required to avoid flicker, reducing CPU consumption. It should also be possible to do gray values in the text area, at the cost of higher flash usage…a full 256-character set of 8×8 pixel font bitmaps takes up 2 KB, gray values would double that. Large SRAM sizes typically come along with large flash sizes though, and I am planning to investigate the possibilities of crude antialiasing for improving legibility of text.

As mentioned, the display seems to respond differently in when driven in different directions. This could be exploited to gain two different gray levels by only displaying each buffer once, but I did not find the resulting gray levels to be of much use in my display…I got “medium gray” and “almost invisible”. The possibility merits further exploration, though…different LCDs might behave differently, and other drive voltages or tweaks to the refresh timing might help.

Source code: https://github.com/cjameshuff/glcd

Driving controller-less graphical LCD

Digging around through some old parts recently, I came across an old Epson graphical LCD display that had on-board drivers, but no controller. The LCD is an Epson EG2401, reflective, no backlight, 256×64 pixels. It has drivers…one SED1190 driving the rows and four SED1180s driving the columns…but no on-board controller. The LCD is *supposed* to be hooked up to a SED1330 controller and SRAM, but since I didn’t have such a thing, this LCD sat around in a junk box for years.

I still don’t have a SED1330 controller to hook up to the LCD, but I found more information this time around, including datasheets on the drivers. These things are essentially just serial load/parallel output shift registers, with output electronics for driving the LCD. Row select is performed by shifting a 1 in and clocking it along to each row in turn, the SED1190 can handle up to 64 rows. 4 adjacent columns are written at a time: each SED1180 has 4 16-bit shift registers with their outputs interleaved. Simple in theory, but the process of clocking data in is more complicated than you’d expect to be necessary, and rather poorly documented. There doesn’t seem to be anyone else foolish enough to try to hook these LCDs up without a controller, but after some trial and error I did finally succeed:


Caveats: you’ll need a fairly fast microcontroller. The display needs to be continually refreshed, or the image will fade to nothing, and if the frame clock is not kept changing while power is applied to the LCD, the LCD screen itself may be damaged. This will consume a notable amount of processor cycles, and if the display isn’t updated fast enough, there’s visible flicker. If the line refresh rate is not constant across the display, there will be visible glitches and artifacts, essentially varying contrast from differences in the periods the LCD is driven. If the display refresh rate is too slow, the display lifetime may also be reduced. You’ll also need lots of SRAM, bitmaps read from program memory, or graphics simple enough to rasterize on the fly (sprites/bitmap characters should be possible). Representing a 256x64x1 bit bitmap takes 2048 bytes, and the ATmega16 I used only has 1024 bytes of SRAM, so I wasn’t able to simply display from a frame buffer. It’s really a job far better suited to a FPGA, or at least a faster microcontroller with more memory (like a ATmega644 or an ARM).

On the other hand, you have relatively direct control over the LCD, and can do things unsupported by the controllers. By rapidly switching pixel states, the EG2401 can be made to display gray levels surprisingly well, though large areas of gray tend to flicker visibly, and the plot display with one half-gray trace flickered badly at 16 MHz. Overclocking the AVR helped a great deal, and with it running at 26 MHz(!), the dual sine wave plot was nice and smooth. Many of the ATmega16’s peripherals are probably non-functional at this speed, but all I need to drive the LCD was GPIO.

Source code will come in a later post, I hope to optimize it further and develop it into something of actual use.

Xorshift pseudorandom number generator

In 2003, George Marsaglia published a pseudorandom number generator based on repeated shift and XOR operations, a relative of the linear feedback shift register generators. The basic 3-shift PRNG is:

int xorshift() {
    y ^= (y << a);
    y ^= (y >> b);
    return y ^= (y << c);
}

With y seeded with any non-zero starting value. The generator will never produce zero, which is something to be careful of, but with the right values for a, b, and c, will cycle through all non-zero values. If only a subset of the bits are used, a generator with the full period results where zeros do occur, though not as frequently as the other values in the cycle: if you take 6 bits from an 8 bit generator, you will get each non-zero 6-bit number 4 times per cycle, and only 3 zeros. Alternatively, you can simply subtract 1 from the output, and take the usual approaches to obtaining the desired range without unacceptable bias.

The published generators I've found all use 32 bit values or greater, but sometimes something simpler and smaller is needed. Here is the C code for the generators I have been testing. Note that they have been verified to be full cycle and to give reasonably random-looking results, but little more...I assume that nobody needing high quality random numbers will use such a short-period PRNG, but will use the published 32, 64, or 128 bit versions, or another generator altogether.

static uint8_t y8 = 1;
static uint16_t y16 = 1;

// returns values from 1 to 255 inclusive, period is 255
uint8_t xorshift8(void) {
    y8 ^= (y8 << 7);
    y8 ^= (y8 >> 5);
    return y8 ^= (y8 << 3);
}

// returns values from 1 to 65535 inclusive, period is 65535
uint16_t xorshift16(void) {
    y16 ^= (y16 << 13);
    y16 ^= (y16 >> 9);
    return y16 ^= (y16 << 7);
}

Its simplicity and avoidance of operations such as multiplication and division makes it particularly well suited for hardware generation. Unfortunately, it's an imperfect fit to larger AVRs: while it requires little memory, even the simple-appearing one-byte shifts for xorshift8 require several instructions to perform on an AVR, so on devices with the multiply instruction, it is a fair bit slower to compute than a linear congruential generator. However, for those devices that lack the hardware multiplier, there may be notable size and speed benefits. Larger devices with barrel shifters might also benefit (ARMs in particular, due to their ability to "fold" shifts into data-processing instructions), but devices with such instructions are also likely to be better at handling other PRNGs. There is a considerable complexity benefit for hardware or FPGA implementations, and it may still be of use in AVRs and other small microcontrollers as a simple PRNG that avoids some of the problems that LCGs have, such as poor randomness in the low bits, while not being as memory-hungry or as computation-intensive as algorithms like the Mersenne Twister.

These aren't the only choices for a, b, and c that work. For 8 and 16 bit generators, it's simple enough to perform a brute force search for possible combinations. There are 24 full-cycle 8-bit generators:

(1, 1, 2) (1, 1, 3) (1, 7, 3) (1, 7, 6) (1, 7, 7) (2, 1, 1)
(2, 5, 5) (3, 1, 1) (3, 1, 5) (3, 5, 4) (3, 5, 5) (3, 5, 7)
(3, 7, 1) (4, 5, 3) (5, 1, 3) (5, 3, 6) (5, 3, 7) (5, 5, 2)
(5, 5, 3) (6, 3, 5) (6, 7, 1) (7, 3, 5) (7, 5, 3) (7, 7, 1)

And 60 16-bit generators:

(1, 1, 14) (1, 1, 15) (1, 5, 2 ) (1, 7, 4 ) (1, 7, 11) (1, 11, 3 )
(1, 15, 6 ) (1, 15, 7 ) (2, 5, 1 ) (2, 5, 13) (2, 5, 15) (2, 7, 13)
(2, 7, 15) (3, 1, 12) (3, 1, 15) (3, 5, 11) (3, 11, 1 ) (3, 11, 11)
(3, 13, 9 ) (4, 3, 7 ) (4, 7, 1 ) (4, 11, 11) (5, 7, 14) (5, 9, 8 )
(5, 11, 6 ) (5, 11, 11) (6, 7, 13) (6, 11, 5 ) (6, 15, 1 ) (7, 1, 11)
(7, 3, 4 ) (7, 9, 8 ) (7, 9, 13) (7, 15, 1 ) (8, 9, 5 ) (8, 9, 7 )
(9, 7, 13) (9, 13, 3 ) (11, 1, 7 ) (11, 3, 13) (11, 5, 3 ) (11, 7, 1 )
(11, 11, 3 ) (11, 11, 4 ) (11, 11, 5 ) (12, 1, 3 ) (12, 3, 13) (13, 3, 11)
(13, 3, 12) (13, 5, 2 ) (13, 7, 2 ) (13, 7, 6 ) (13, 7, 9 ) (13, 9, 7 )
(14, 1, 1 ) (14, 7, 5 ) (15, 1, 1 ) (15, 1, 3 ) (15, 5, 2 ) (15, 7, 2 )

http://www.jstatsoft.org/v08/i14/paper
http://www.jstatsoft.org/v11/i04/paper

Xcode for Ruby, pt 2

A second issue with using Xcode for editing Ruby is that it by default does not correctly comment code in Ruby files. This again is easy to fix:
Open the scripts menu, choose Edit User Scripts.
Select Comments: Un/Comment Selection
This will bring up a Perl script that Xcode uses to perform the comment/uncomment function. We need to modify this to recognize Ruby file types:

Replace:

    # determine the type of file we have by looking for the #! line at the top
    # careful--it might already be commented out!
    my $commentString;
    if ($fileString =~ m!^($perlCmt|$cCmt)?#\!\s*.*?/perl|^($perlCmt|$cCmt)?#\!\s*.*?#\!\s*.*?/sh!) {
        $commentString = $perlCmt;
    } else {
        $commentString = $cCmt;
    }

with:

    my $fileName = "%%%{PBXFilePath}%%%";
    # determine the type of file we have by looking for the #! line at the top
    # careful--it might already be commented out!
    # Otherwise look at the file extension
    my $commentString;
    if ($fileString =~ m!^($perlCmt|$cCmt)?#\!\s*.*?/perl|^($perlCmt|$cCmt)?#\!\s*.*?/ruby|^($perlCmt|$cCmt)?#\!\s*.*?/sh!
            || $fileName =~ m!\.(rb|erb|rake|pl|sh)$!) {
        $commentString = $perlCmt;
    } else {
        $commentString = $cCmt;
    }

Xcode for Ruby

Xcode 3’s language support for Ruby is somewhat broken. Fortunately, fixing it only requires a few small modifications.

One major problem, Xcode doesn’t know what .erb and .rake files are.
There should be a file:
/Developer/Library/PrivateFrameworks/DevToolsCore.framework/Versions/Current/Resources/Standard file types.pbfilespec

Copy this to /Library/Application Support/Developer/Shared/Xcode/Specifications/, creating that directory if it doesn’t exist. Editing the original works, but your changes will be overwritten if you update Xcode, better to just override the standard files.
Edit the html-like files entry (line 335 in mine) to add erb:

    // html-like files
    {
          Identifier = text.html.other;
          BasedOn = text.html;
          Extensions = (shtml, jsp, rhtml, erb);
    },

I did the same to add a “rake” file type, around line 543, and also added the line “FilenamePatterns = (“[rR]akefile”);” to detect rakefiles without the .rake extension:

     {
          Identifier = text.script.ruby;
          BasedOn = text.script;
          Extensions = (rb,rbw,rake);
          FilenamePatterns = ("[rR]akefile");
          MagicWord = ("#!/bin/ruby", "#! /bin/ruby", "#!/usr/bin/ruby", "#! /usr/bin/ruby", "#!/usr/local/bin/ruby", "#! /usr/local/bin/ruby");
          ComputerLanguage = shell.ruby;
          Language = "xcode.lang.ruby";
          IsExecutable = YES;
    },

Next, the Ruby language syntax highlighting, selecting, etc need some tweaking. Copy the file
/Developer/Library/PrivateFrameworks/XcodeEdit.framework/Versions/Current/Resources/Ruby.xclangspec
to /Library/Application Support/Developer/Shared/Xcode/Specifications/

By default, Xcode will select too much when doubleclicking. When trying to select an array identifier, it will select the opening [ bracket around the indices.
Go to the lines:

    Identifier = "xcode.lang.ruby.identifier";
    Syntax = {
        StartChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_[";
        Chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_?[]";

And remove the [ and [] characters, which will make selections break at the brackets around array indices.

Now restart Xcode…the changes will not take effect until you do.

Xcode language/syntax definition files for POV-Ray

Xcode 3 allows you to specify the syntax of a language with .xclangspec files, which contain information on the structure of the language that is used not only for syntax coloring, but also for populating the symbols menu, showing the currently selected block with the “Focus Follows Selection” feature, selecting the appropriate amount of text on a double-click, etc.

The POV-Ray syntax specification file is a little crude, work still to be done with it, but already a considerable improvement over the other options on the Mac for editing POV-Ray files.

Place POVRay.pbfilespec and POVRay.xclangspec in /Library/Application Support/Developer/Shared/Xcode/Specifications/ to use, create these directories if they don’t already exist.

[POVRay.pbfilespec](http://files.arklyffe.com/POVRay.pbfilespec)
[POVRay.xclangspec](http://files.arklyffe.com/POVRay.xclangspec)