In our discussion of matrix multiplexing with an octal latch (74HC573), we mentioned that it is possible to use an external memory interface to automate this task for you. Here we will walk through a specific example of this, showing its benefits and possible pitfalls. Hopefully this will make it easier for you to incorporate it into your designs.
Figure 1 – Test platform for MIDI XMEM keyboard scanner.
We built up a 48 key MIDI keyboard using an Atmega640 (running at 8MHz) and its XMEM hardware peripheral. The XMEM device has an 8 bit address/data bus (AD0:8), an 8 bit high-byte address bus (A8:15), and 3 control pins. The control pins are Address Latch Enable (ALE), Read strobe (RD), and Write strobe (WR). These are meant to control an external piece of SRAM memory, telling it that it is ready to either read or write data.
Figure 2 – Close-up of XMEM scanning circuit.
The circuit is very simple, basically requiring only a single 74HC573 and 8 pull-up resistors (2.4k). The resistors were not required for smaller size arrays, but the large capacitance of the 3 foot keyboard made it necessary. There is also a MIDI jack connected to the USART for sending note information. The green PCB is a breakout board for the Atmega640, and the protoboard has the remaining components. It’s reassuring to see the circuit working in the capacitance soup that is a protoboard, giving confidence for this method as a final design.
Setting up the XMEM
An example XMEM schematic is shown in Figure 3. Since we are only reading, we do not use the WR pin. Unfortunately it can not be repurposed, as it is blocked by the XMEM peripheral. The ALE pin goes to the latch enable on the 74HC573, and the RD pin goes to the output enable pin.
Figure 3 – Example XMEM schematic.
For this test, we only scanned one button per key, or 48 buttons, so only the first 6 rows were required (in this case we are scanning rows and reading in on the columns). But, if you want, up to 16 rows can be addressed. The number of rows is set between 8 and 16 by the XMM2:0 bits in the XMCRB register. So, for 8 lines XMCRB = 0×07, and for 16 lines XMCRB = 0×00. If the XMEM interface isn’t using address lines, they are free to be used by your program.
The only other register to set is XMCRA. This enables the XMEM interface, and determines how long it will take to scan the data bus. The address space can be divided up into 2 different sections, one with slow scanning, and one with fast scanning. These are set with the SRL2:0 bits. This can be useful if you want to scan both a piece of SRAM and your switch matrix.
In this case, we set only one section. The speed for this section is set with the SRW11:0 bits. It can be set with 1, 2, or 3 wait clock cycles. The longer you wait, the more reliable your data will be. With our keyboard, 1 wait cycle was too short, and multiple notes would trigger with each key press. It seemed to work fine with 2 wait cycles, making XMCRA = 0×84.
Finally, you should turn pull-ups on. So set whichever port AD0:7 is on to 0xff. This is not required if using external pull-ups, but also does not hurt. To get your data, merely poll the memory location matched to your row. This is basically a number with one bit being low, and all the rest high. For example, in assembly, this would be “lds r16,0xfffe” to scan the first row. In 4 clock cycles, the operation will return the button presses on all 8 columns.
Pro’s and Con’s
This is the beauty of this method of matrix scanning; the simplistic and compact code. With only one line of assembly per row you can scan your whole matrix – up to 128 buttons. The speed savings are also good, but at some point the extra 250ns isn’t that helpful. If you were to do a traditional 8 x 16 matrix, it would take 2 clock cycles to write out the address, 2 more clock cycles to wait the setup time on the input synchronization logic, and 1 more clock cycle to read in the rows. That’s 5 clock cycles, the maximal time XMEM can take, with 3 being the minimum.
It’s important to be careful with the XMEM interface. Depending upon your processor speed, the longest wait time might not be long enough, in which case it will not work. Also, at higher clock rates the HC logic might not be fast enough, and a 74AC573 or equivalent might be required. Smaller value pull-up resistors will also help in this case. We ran our processor at 8MHz and only used 2 wait cycles, so there is a bit of room left it seems.
In comparison to a standard latch multiplex setup, the XMEM is far less complicated, as the latch enable and output enable pins are manipulated for you, saving both code and time. If you need to multiplex your lines, and are running at a low of enough clock speed (or physically small enough matrix), the XMEM interface can make your job a lot easier. The only downside is that it may require external pull-up resistors, which a slower scan rate would not.
In comparison to a standard switch matrix, it does require an extra IC, although this buys you 8 more pins. If you can get away without multiplexing, then by all means do so, otherwise using the XMEM is the simplest of the remaining options. Even clocking in a shift register takes more operations and more time. You can’t even get into the SPI interrupt in the time it takes the XMEM to scan a row.