This page was last updated 18 october 2003.

frisbee, 5.5k

Contents:

How many MIPS does your frisbee have?

On a party in San Francisco (where else) many years ago I have been shown a frisbee with some attached lights. Looked like a cool idea, but the concept obviously needed some enhancement.

Now I have this frisbee on my desk, made of rather stiff white plastic. I drilled 48 holes around the rim, and glued little red 1mm LEDs behind the holes. On top, there are two 74241 line drivers (they are powerful enough to drive an LED through their internal pullups), connected to a 1468705 microcontroller. They are very nice, 2 KB of on-chip eprom if I remember correctly, and 128 bytes RAM. Just about right for the job; 128 bytes of main memory may not seem very much, but the computational demands of a frisbee are relatively light and workstations cannot usually stay airborne long enough to replace frisbees despite their superior processing power.

The application notes for the 1468705 contain a programmer for the eprom. Erasing is no problem, it has a quartz window and every well-equipped household has a professional eprom eraser, right? Well, this one does.

The FOS (Frisbee Operating System) consists of some timing loops, the multiplexers for the LED array (the chip doesn't have 48 port bits, so I am driving the LEDs in a 6*8 array at high speed), and about 40 different preprogrammed patterns. It's amazing what you can do with 2 KB and tight coding: rotating dots, growing worms, flashing segments, all of the above in a single pattern. One of my favorites was an exclusive- OR pattern that slowly alternated between all-on and all-off. XOR is obviously an essential operation for a FOS, no microcontroller designer can omit it without risking losing the frisbee market.

This frisbee is guaranteed to draw a crowd at night in the park. It takes some practice because it's twice as heavy as a regular frisbee, you want to avoid being hit on the head by it, but it's great fun to throw in long arcs. You can see it strobing and pulsing on its flight path. Patterns that just briefly flash all LEDs produce a stroboscope effect. I also liked to just hang it on a wall at night and watch the light beams radiating out in all directions.

It's been a long time, and the NiCads are pretty much dead now. Several LEDs have broken when the frisbee collided with trees, and the glue has cracked in a many places. But I'll keep it even if it doesn't work, it's one of my more bizarre hacks.


Wiring your home

panel, 8.2k One of the master control panels

I had this pile of over 1000 TTLs and 68k chips and decided to use them up for something fun and useless. So now I have a 68000-based board that controls things in my apartment, lights for the plants, door bell & buzzer, blinds, intercom, clocks, sensors and solenoids everywhere. It also talks to my SGI O2 and brings mail and (rsn) news to my bedside. There has been a lot of requests for details since I posted this to alt.hackers, so here are some technical details. I can't and won't provide detailed schematics here (they are very specific to my needs) but I will try to cover the basics, and communicate the fun I had (and have) building it.

The bus

Except for the big LCD screens, which require MHz pixel clocks, and the analog lines, everything is linked with a bus. The problem was that I can't have a central unit with hundreds of wires going everywhere. So I put substations where the data is collected, and connected the substations with a simple parallel bus. It has 14 lines:

    D0-D7	data lines, used for addressing and data i/o
    SEL		pulse to select a substation with D0-D7, or deselect
    R		read a byte from the selected station
    W		write a byte to the selected station
    PROBE	confirms successful substation selection, SEL feedback
    GND,VCC	power
Each station has up to 8 output registers and one input register. The neat thing about this is that a station consists of a single PAL16R4, of which I happened to have a rather large number, plus one latch for each output register and an octal driver for the input register. If there are more than 3 output registers, I also need a demultiplexer, a 74138 or 7442. That's all. The PAL handles substation selection, output register selection, and drives input and output enables.

What's more, the PAL does address comparison with its 8 inputs. All PALs are identically programmed and need no comparator and no DIP switches. The trick is that all PALs look for the same select address, 00001111. What makes them all respond to a different address is that D0-D7 are connected to PAL in0-in7 in different ways, so a D0-D7 bit pattern is seen differently by each PAL. Naturally, all valid addresses have four 0-bits and four 1-bits. There are 70 possible addresses, many more than I need.

The PAL also contains a state machine that interprets patterns with five 0-bits as output register selection commands, with the remaining three bits being the output register address. To write a byte to an output register, I go through four phases:

  1. select: station address on D0-D7, pulse SEL, check PROBE
  2. register select: register # on D0-D7 plus 5 0-bits, pulse SEL
  3. write: output byte on D0-D7, pulse W
  4. deselect: D0-D7 are all 1, pulse SEL

Step 2 is tricky because the register address is on different bits for every substation, but three 70-byte arrays in the central unit take care of that. Reading is easier, no step 2 and step 3 pulses R. Some of the output registers aren't really TTLs but numeric or alphanumeric LED and LCD displays, no problem. One station even acquired two static RAMs last weekend to scan a 6*5*7 dot alphanumeric LED matrix.

I am proud of this hack because of its absolute simplicity and the way it uses the PAL16R4 to the max. The central unit is a simple 68000 system with a big LCD frame buffer (all TTL plus memory), dynamic RAM, serial and parallel ports and an RTC. It also has a SCSI controller that I am not using right now. It's all handwired with thin Cu wire. No OS, just a simple loader and irq trampoline in NVRAM. I cross-compile with gcc on my O2 and use X fonts. I used xfig for the pictures on the LCDs.

CPU board, top CPU board, bottom

Right now, I am considering to put the whole thing on the Internet. Then everybody on the planet can, say, download a temperature histogram for Berlin or trigger my alarm clock at unusual times. I can already telnet to it using a fixed TCP port. Although I have a leased line I am still considering the wisdom of giving too much access to random strangers on the Internet... Move over, Coke machines. Other planned extensions are infrared and speech I/O. "HAL, open the pod bay doors, please..." And I am still looking for a really horrible death scream to replace the door bell.

A sample substation

Here is a description of one of the more complex substations. It has four large 7-segment LED displays, one 8-digit alphanumeric LED display made by Siemens, and a button. I use this in my bedroom on the wall, it displays time, date, and temperature; the button suspends or disables the alarm (I figured I better force myself to get up to shut it off).

A very similar substation is in my kitchen; it has four buttons, each with a red and a green light, that I use for egg timers, to turn lights on and off, and various other things.

There is a compressed PostScript schematic (21 KB) on this server for the substation. When you read the schematic, you'll be surprised at my choice for the registers. I used 74192 counters because I happen to have a large number of these. A better choice would be 74374 or similar registers, and much cheaper too. BTW, a line with a cross: -----X----- means that there is a resistor in the line, like ----[####]----, not a pullup. Be careful with the Siemens display, and don't connect pin 23. Here is the PAL code for the PAL16R4:

	TITEL

	CHIP PAL16R4 PAL16R4

	CLK L0 L1 L2 L3 H0 H1 H2 H3 GND
	OE RIN WIN OUT0 OUT1 OUT2 SELOUT ROUT WOUT VCC

	EQUATIONS

	/SELOUT := /L0 * /L1 * /L2 * /L3 *  H0 * H1 * H2 * H3
		 + /L0 * /L1 * /L2 * /L3 * /H0 * /SELOUT
	/OUT0   := /H0 * /H1 * /SELOUT
		 + /OUT0 * SELOUT
	/OUT1   := /H0 * /H2 * /SELOUT
		 + /OUT1 * SELOUT
	/OUT2   := /H0 * /H3 * /SELOUT
		 + /OUT2 * SELOUT
	/ROUT    = /SELOUT * /RIN
	/WOUT    = /SELOUT * /WIN

The station has 6 registers that control the numeric and alphanumeric LEDs, an LED colon between digits 1/2 (left) and 3/4 (right) that flash with 1 Hz, and a minus sign before digit 1 (for negative temperatures, we use centigrade here). Digits 3/4 are mounted upside-down, which moves the dot to the top left corner of the digit; I use that for 'c .

	i/o	bit	meaning
	------- ------- ---------------------------------------------
	ctl	000	reset alpha display, data is ignored

	ctl	001	data writes go to alpha display
	out	   0-6	data: store ascii character 40..7e
		   7	data: 1=underline
		   0-1	ctl:  0=dark, 1=25%, 2=50%, 3=100% brightness
		   2	ctl:  0=cont, 1=characters flash
		   3	ctl:  0=cont, 1=underlines flash
		   4	ctl:  0=ignore bits 2-3, 1=apply bits 2-3
		   5	ctl:  0=normal, 1=flash all characters
		   6    ctl:  0=normal, 1=lamp test
		   7	ctl:  0=normal, 1=clear all

	ctl	010	data writes go to numeric digits 1/2 (BCD)

	ctl	011	data writes go to numeric digits 3/4 (BCD)

	ctl	100	data writes go to alpha address register
	out	   0-3	0=alpha ctl, 8-15=alpha data register

	ctl	101	data writes go to lamp register
	out	   0	0=colon off, 1=colon on
		   1	0=minus off, 1=minus on
		   2	0=dot 3 on,  1=dot 3 off
		   3	0=dot 4 on,  1=dot 4 off

Control Panels

I used several different approaches for the various control panels:

  • The front of the big LCD screens are 16x28 cm epoxy boards coated with copper on one side. I cut out a large rectangle for the LCD screen and drilled 16 holes below the rectangle, for the buttons. 12 of these are just below the rectangle, such that I can draw little labeled triangles at the bottom of the LCD, each of which points at a button. The other four are in a second row, slightly offset to the sides, for things like Escape and Yes/No. I sanded the epoxy side and sprayed it a metallic gray using car paint. I soldered 3mm nuts on the other side to hold the LCD panel, and soldered stiff wire on it to hold a long thin board that holds the buttons. I bought black semicircular 19mm plastic profiles with yellow trim to build the sides. These profiles are normally used to protect the edges of shelf boards or tables, they have a large selection of colors and shapes. See the picture at the top of this section.

  • For the kitchen panel, I removed a small piece of 16x5 cm trim under the wall cupboards above the work area, and replaced it with a transparent piece of plastic. I drilled holes for the buttons, pasted plastic masking tape where I wanted the LED displays, and spray-painted it white. Then I carefully removed the masking tapes and had nice windows. All LEDs, buttons etc are held by hot-melt glue on the other unpainted side. If you do any kind of hardware design, hot melt glue is essential.

  • Originally I planned to put the bedroom LED display panel into a transparent piece of pipe, so I used standard breadboard epoxy that I covered with black paper to make it look nicer. Then I decided it looks even nicer without the pipe, so now I have this high-tech gizmo with exposed TTL chips, and everything except the metal and the LEDs painted black.

  • The panel beside the door was made from a piece of large cable tunnel cover that had the right size and is easy to cut. It holds a 16x1 LCD display and four buttons. It is held by an old 31-pin connector mounted on a piece of plastic that I mounted between the door intercom and the wall; it sticks out on top to hold the connector.
Kitchen panel
Kitchen

Bedroom panel
Bedroom

Door panel
Door

Bathroom panel
Bathroom

Door2 panel
Door 2

I have cable tunnels all over my apartment. When I moved in, I didn't like the layout and had some walls removed and rewired most of the electrical lines and fuses, which means that there were lots of cables and holes in the wall anyway. Cable tunnels are very convenient.

Software

Now I am really a software engineer, I build hardware just for fun. When I designed the software, I started thinking in terms of data sources and destinations, driven by a hierarchical multi-threaded rule-based system that can be configured dynamically. Then I stopped myself and decided to gleefully design a special-purpose system that is not at all portable. That doesn't mean it's not structured or poorly documented, I just decided that the code that controls my bedroom blinds exists to control my bedroom blinds and not some abstract virtual entity. This made it much more fun because portability issues greatly complicate matters (I have been there, I have two freeware projects running), but it also means there is little point in just publishing all my sources.

The software consists of three layers. The top layer is the user interface, one per substation that has a readout or button panel; the intermediate layer offers high-level commands such as "pulse that bit for 100 ms" or "wake me up after 5 minutes"; and the bottom layer talks to the hardware. The bottom layer includes

Here is the call interface for the bottom layer. s is a substation address (0..69), c is the register in that station (0..7), b is a bit number (0..7), v is a data bit value (0 or 1), and d is a data byte (0..255).

   io_probe(s)             FALSE if station is dead
   io_setbit(s,c,b,v)      set a single bit 0..7 at a remote station
   io_pulsebit(s,c,b,v)    set a single bit for a very short duration
   io_pollbyte(s,c)        return what software did last to a byte
   io_pollbit(s,c,b)       return what software did last to a bit
   io_setbyte(s,c,d)       set a eight data bits at a remote station
   io_getbyte(s)           read byte from remote station
   io_getbit(s,b)          read a single bit 0..7 at a remote station

There is a source code file (12 KB) on this server that contains some of the more interesting routines, including the low-level hardware driver layer, and some high-level code. I never made any timing diagrams, but this is so extremely simple that it should become clear from the sources. As I said, the only mildly complex issue is addressing the registers 0..7 in a station because each PAL is connected to a uniquely permutated set of bus data lines. The code assumes a parallel 68230 PI/T interface controller chip. pad/pbd are port A/B data, padd/pbdd are port A/B data direction. The spl* routines disable interrupts (Set Priority Level).

(I never thought I could publish any of this. Well, more bandwidth is wasted with editor wars every day. The complete sources are 4500 lines.)

BTW, the title "intelligent homes" may seem slightly exaggerated, but these days a coffee machine is called "intelligent" if it can turn itself on in the morning so I'll just borrow that definition.

Do it yourself

My design is based on my own microprocessor design - motherboard with CPU, dynamic RAM, storage, IO, frame buffer with video generator and all the necessary glue logic. It was a lot of fun, but I wouldn't recommend going to these lengths. In fact I am busy rebuilding everything from scratch for my new apartment in the center of Berlin, and this time I'll use a low-power PC running Linux, and standard external components.

Anyway, I am currently designing the whole thing. This web page has seen about 40,000 hits so far, so I'll put the complete design, with schematics, pictures, and source code, on the web when it's sufficiently evolved to be useful, on this page.

Tell me if you found this information interesting or useful, or if you have comments.