leddrvr2 - Copyright (c) 2002 Tundraware Inc., All Rights Reserved $Id: readme.txt,v 1.3 2002/05/02 18:58:17 tundra Exp tundra $ ************************************************************************ PLEASE NOTE: Before using anything in this archive, you must read, and agree to abide by, the licensing terms found in: leddrvr2-license.txt ************************************************************************ FILE DESCRIPTIONS ================= Makefile Unix-style makefile which runs under DJGPP and should also work under MKS and Cygwin. README.txt This file. leddrvr2-sch.brd leddrvr2 PCB board layout in Eagle format. leddrvr2-license.txt Licensing terms for using this software. leddrvr2-sch.gif leddrvr2 schematic in GIF format. leddrvr2-sch.png leddrvr2 schematic in png format. leddrvr2-sch.ps leddrvr2 schematic in PostScript format. leddrvr2-sch.sch leddrvr2 schematic in Eagle format. leddrvr2.asm leddrvr2 software written in PIC assembler. leddrvr2.hex The assembled leddrvr2 software. leddrvr2.lst leddrvr2 listing file generated by assembler. leddrvr2.xrf leddrvr2 cross-reference file generated by assmbler. WHAT IS 'leddrvr2'? ================== 'leddrvr2' is a simple 7-segment LED display driver system using PIC technology. The idea is to use minimum parts count to drive up to 8, 7-segment LEDs using only 3 I/O pins on the PIC chip. This is also a useful introduction to some of the PIC microprocessor programming techniques insofar as 'leddrvr2' exercises many of the basic features of these chips including: - Programming & use of the TMR0 timer & prescaler - Timer-based interrupt handling - Asynchronous application/interrupt interaction. - Display multiplexing - Serial interfacing to external 'glue' logic. I wrote this code so *I* could learn the PICs and in the process actually do something semi-useful. I've tried to document the hardware and software sufficiently to make 'leddrvr2' useful as a learning tool for others. In order to fully understand 'leddrvr2', it is useful to first examine its predecessor design, 'leddrvr' which can be found at: http://www.tundraware.com/Software/PIC/leddrvr/ The following sections assume such familiarity and only comment upon the newly implemented features found in 'leddrvr2'. HOW DOES THE HARDWARE WORK? =========================== The original 'leddrvr' design works quite nicely but has one huge drawback: it uses all but 1 of the PIC's I/O pins. This really limits its usefulness for all but the simplest of applications. The idea behind 'leddrvr2' be able to drive an array of 7-segment LEDs using a minimum number of I/O pins - in this case the design ultimately only ends up needing *3* pins to drive up to 8 LEDs. (In fact, the design can be extended for many more LEDs simply by adding more shift registers and adjusting the code accordingly, all without the need for any more I/O pins!) 'leddrvr2' is able to do all this with only 3 I/O pins because of two outboard serial shift registers which are chained together - the output of one drives the second. Instead of loading the segment and LED selection bits in parallel as is done in 'leddrvr', this implementation writes the bits out *serially* (via RA0-RA2) to the shift registers. The shift registers take this serial stream and convert it into the equivalent parallel control word to properly drive the display hardware. One consequence of this design is that 7404 drivers had to be added. The PIC can drive enough current to light an LED segment, but the CD4094 shift registers cannot. The 7404s take the logical output level of the shift register and provide the necessary current drive to light the LED segments. HARDWARE NOTES ============== This release of 'leddrvr2' includes a Printed Circuit Board layout In Eagle format. This board has actually been built and works fine. Most of the parts used in this project are pretty standard and you should be able to find them at any good electronic supply store. However, there are a couple of specific parts used here you should know about. First, the 7-segment LED displays used are common cathode devices. The board is laid out for the Jameco #24782 (LSD3211-11) part. There is also provision for an On-Off switch. If you use an off-board switch, any standard SPST or SPDT switch should work. If you want to actually mount the switch to board as I have, use the Jameco #71597 (MTS-102-A4) part. You can see both the blank and the finished PCB at: http://www.tundraware.com/Software/PIC/leddrvr2/leddrvr2-board.jpg The original design included pulldown resistors (RN2) for the FET inputs so that I could connect and disconnect the gates from the rest of the circuit as I was debugging the hardware. In this final circuit, the gates are hardwired to the shift register outputs and this resistive termination is not needed. I left provision for RN2 in the schematic and finished PCB, but I don't actually use it. This is why you see an empty SIP socket in the upper right side of the finished PCB. In any case, it does no harm to put a 10K termination pack there if you like. One nice think about leaving the resistors out is that you can use that socket to inspect the signal at each of the FET bases with an oscilloscope. WHERE TO GET THE PRINTED CIRCUIT BOARD ====================================== I recommend: http://www.olimex.com/pcb This is a very nice PCB prototype house. They are located in Bulgaria so shipping can take a couple of weeks to the US or Canada unless you are willing to pay a premium for expedited delivery. However, their prices for boards are the lowest I've found and their product quality and turn around time are excellent judging from my experience. The board layout provided here is designed to fit twice on their standard prototype panel, so you actually get *two* boards for their standard price. As of 5/2002, I was able to get 2 boards delivered to the US for just over $40! This is *very* inexpensive. You send them the Eagle .brd file via email and they will respond with a price estimate. You then sign the order, provide Credit Card information and FAX it to them. Several weeks later, you should have your boards. I especially like the fact that I do not have to fiddle with post-production tasks like producing Gerber files, drill files, silk screen layer information, and so on. They do it all for you from the Eagle .brd file. Try these guys out - I think you will really be happy. I was. HOW DOES THE SOFTWARE WORK? =========================== The 'leddrvr2' software is structurally quite similar to the original 'leddrvr' code, though it should be noted that some of the variable names have changed. A few other core differences are worth noting: - Be forewarned: 'dsply_val' is the register set which holds the current value to display. It is allocated to be (num_led/2) bytes in size. This assembly-time allocation works so long as num_led is *even* but will fail if it is odd. Subsequent use of this array in 'display_led' also expects there to be the correct number of bytes of storage here, so make sure you have it right if you're using an odd number of LEds. - 'led_lookup' has been expanded to accomodate 8 LEDs. - The overall code works pretty much the same way it did in 'leddrvr' with one big exception: 'display_led' no longer actually writes to the LED control hardware. Instead, 'display_led' now computes the desired segment selection bit pattern and stores it in 'led_seg'. Similarly, it computes the LED selection bit pattern and stores it in 'led_sel'. 'display_led' then calls a new routine, 'led_wrt' which reads these values and shifts them out in correct order to the outboard shift registers, thereby illuminating the LEDs as desired. - In 'leddrvr', 'display_led' did some explict offset arithmetic to figure out what value to display on each LED. This has been changed in 'leddrvr2'. Now, 'display_led' does pointer arithmetic to compute an offset from the base of the 'dsply_val' array. This is a more general approach which should work without modification as more LEDs are added. - Most of 'led_wrt' should be fairly self-explanatory, but a few clarifying comments might be helpful: a) The 'STR' (strobe) input of the shift registers allows data to be moved into the register without actually having it appear on the output. When the registers are finished being loaded, the parts are strobed and the LED display is thus changed. I experimented with pulling the 'STR' pins high permanently (and thereby freeing up another I/O pin). This effectively causes all changes to the shift register to be immediately reflected on the LEDs. This does still work, but there is an annoying flicker in the unused LED segments which are being lit as data shifts across the registers. So, I went back to using the STR line. b) Clocking occurs when the 'CLK' pin of the CD4094 goes from low to high with one exception: The output of the high bit (Q8) does not propagate to the shift register ripple out (QS*) until the clock transitions from high to low. This delay is necessary so that bit ripple is properly implemented without race condition timing concerns. In any case, this is transparent to the software, which sees the two shift registers as a single 16-bit logical device. c) Data is shifted into the shift register by placing the bit value on the 'D' input (RA1) and then clocking it into the register by first raising and then lowering the 'CLK' pin (RA0). After all 16 bits have thus been shifted into the shift registers, the devices are strobed via 'STR' (RA2) as described above. This causes the new bit values to actually propagate to the LED hardware. - One word of caution: 'display_led' is called as a subroutine from the TMR0 Interrupt Service Routine. It, then, in turn, calls 'led_wrt' as a subroutine. This is kind of dangerous because the PIC has very limited stack space. So long as you are certain that you will not see another interrupt while servicing the TMR0 interrupt, this should work. However, if you end up building a system that needs to be able to interrupt during ISR handling, you should restructure this code to be inline in the TMR0 ISR and *not* use subroutine calls. TIMING ISSUES ============= The basic TMR0 interrupt rate of 1ms found in the original 'leddrvr' design is preserved here. 'leddrvr' only drove 4 LEDs so each one got updated every for 4ms - an effective multiplex/refresh rate of 250 Hz. The 'leddrvr2' design is extended to handle 8 LEDs. This means the multiplex/refresh rate is 125 Hz. This is probably as slow as you want to go or you'll begin to see some display flicker. If the design is extended for more than 8 LEDs (by adding more shift registers), the multiplex/refresh rate will degrade in direct proportion to the number of LEDs supported. This will certainly introduce unacceptable display flicker almost immediately. This problem can be solved by changing the TMR0 interrupt rate to something faster than 1ms. If you do this, note that the 'wait' subroutine assumes a basic timing interval of 1ms. This routine will have to be modified to accommodate any TMR0 timing change you make. DESIGN TRADEOFFS ================ As a matter of practicality, this design is way better than the original 'leddrvr' approach. However it raises the parts count and therefore the real estate and cost to build a real system. Even so, this higher parts count is still somewhat cheaper than using a specialty chip like a MAX7219. This approach also caused the code size to grow somewhat (from 117 to 150 bytes) but this is probably a small price to pay for the vastly reduced pin count. As a matter of simplicity and minimizing parts count/board size, using a dedicated part like the MAX7219 is probably preferred. But where cost is concerned, this design is probably somewhat better. Like all engineering, these are *tradeoffs*, not absolutes... I'D LIKE TO THANK THE ACADEMY... ================================ Lots of nice people on Usenet answered my stupid questions as I've been learning the PIC. Their help is very much appreciated. You should feel free to poke around the code, change things, and generally experiment with what is there. It's the best way I know to learn something new. If you have any other thoughts / fixes / questions / improvements for 'leddrvr2', please let tundra@tundraware.com know. Happy Hacking! ...