Path: Home => AVR-Overview => Applications => Keys and switches on an ADC => Keyboard => avr_sim matrix   Diese Seite in Deutsch: Flag DE Logo
application AVR-Single-Chip-Processors AT90S, ATtiny, ATmega
of ATMEL in practical examples.
Calculating a keypad resistor matrix with avr_sim

12/16-keypad calculation with avr_sim's matrix calculator

There are many possible ways to calculate a resistor matrix to connect a keypad to an ADC input pin. Here is an additional opportunity to do this, and to devellop assembler software for reading the keys: the AVR Assembler Simulator avr_sim from version 2.7 upwards offers a tool to do that in a convenient way. You'll find avr_sim here for download and as source code.

This text provides a step-by-step description on how-to-do-that.

Starting avr_sim

First of all we need avr_sim. It is available either as pre-compiled Linux- or Windows-executable for 64-Bit versions of those operating systems or as source code for the Pascal-Compiler Lazarus. If you download the executable, you only need to unzip the file and to start it. If you prefer compiling it: see the version-related handbook provided for your downloaded source code version on hints how to do that.

Don't be surprised that avr_sim on its first start asks you for a folder for AVR assembler source code. If you have such a folder, just navigate to that. If you don't have one: it is a good idea to create such a folder. You'll never be asked that again.

Menu after starting avr_sim The first entry in the "Project" menu is "New". If you start, select this. Later on the once started project will be available under "Open previous".

The project window for a new project Then this window opens. We enter a project name, e.g. "resistor matrix", by clicking into the editor field for the project location we select a folder for that and we click on the two fields to get a "Short version" and a "Linear program". We can then enter the target device either by selecting it with the two drop-down fields to the left, if we already know which AVR type we like to have, or by clicking on "Device selector" on the right if we are unsure which types can do what we need.

Selecting the AVR type With the device selector we mark a one on the ADC drop-down field, to which the resistor matrix shall be connected to.

From the large variety of potential devices, we can click on one of it in the window in the list. We see that device with its package and connectors in the right window. The ADC channel to connect the matrix to is converted to Adc_, where _ means a number between 0 and 7. Here, in an ATtiny13A, it is Adc1 on pin 7.

The button "Save" saves this hardware and "Ok" selects it for simulation.

Selecting from different packages Several AVR types ares available in more than one package type. We are now asked to select from one of these types. The three radio buttons (or two or four depending from the type) select one of those packages.

Picture of the AVR type The button "Show picture" shows us the type in the selected package as picture.

With "Ok" we leave the package selection dialog.

The editor Now avr_sim has constructed a short template of an Assembler program. The editor shows this, and allows to add or change the source code. By pressing the key F2 we can add the hardware of the device as ASCII text.

We can now assemble the source code via the Assemble menu entry.

If that was succesful, the menu entry "Simulate" appears.

The simulator window When selecting this, the simulator window opens. Here we mark, in the section "Show internal hardware", the field "ADC".

The ADC window The ADC window offers the following possibilities for entries: When entering numbers in an entry field, this is colored in yellow, as long as it is not really entered. Press Enter to really enter the number. Use numbers in anglosaxony format. If the number has an illegal format, the entry field turns red.

The resistor matrix The resistor matrix window shows this here. You can click on lots of selections, most the entries are self-explaining. Those who want more detailed information can consult the avr_sim-handbook's chapter on the resistor matrix. There you'll find detailed explanations on what is behind the selector "Use int. VRef", what you'll get with "View data table" enabled, what "View voltages" does and what happens if you click onto one of the resistors of the resistors table.

To read a voltage from the ADC's input pin

To read an ADC pin's voltage we replace the Main: line in the source code by the following lines:

  ; Set the ADLAR bit to enable 8-bit conversion,
  ; note that the ADLAR bit in a tiny13 is in the ADMUX
  ; port register, other devices place this bit elsewhere
  ldi rmp,(1<<ADLAR)|(1<<MUX1) ; 8-bit ADC, select ADC channel input
  out ADMUX,rmp
  ; Enable the ADC, start conversion, AD prescaler = 128
  ldi rmp,(1<<ADEN)|(1<<ADSC)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
  out ADCSRA,rmp
  sbic ADCSRA,ADSC ; Wait for ADSC bit to get clear
  rjmp WaitAdc ; ADSC bit not yet cleared, continue waiting
  in rmp,ADCH ; Read the MSB of the result
  rjmp loop

Simulating the conversion Active AD-conversion If we assemble and start the simulator, we can set a breakpoint to the line with "rjmp loop" by clicking into the gutter area of this line. This allows to use "Run/Go" instead of single stepping through the code. With this, the active conversion field in the ADC window moves faster than with single steps.

Time consumed by the conversion Because the ADC's clock is divided by 128, the conversion needs 1.39 Milliseconds. The result appears in the ADC window as left-adjusted byte (ADCH) and in register R16: a zero. Just because we didn't set the channel's voltage to a more interesting value yet.

16-key pad with R-Matrix If we display the R-matrix, we can set it to 16 keys, the vertical resistors as single, and the 1% entry has already been set. Now we press "Optimize" several times, and hopefully end with zero overlaps (if not: restart the iteration), and if we click on the key 1 in the schematic, we'll get the 571.1 mV onto our ADC channel (in the ADC window). The table says that the key '1' produces an 8-bit ADC value of 29.

AD conversion of a pressed One Indeed: the correct result of the conversion appears. The only question left is: how can we get the "1" from the 29?

Tables in the include file For this we click on one of the eight resistors in the table and we'll get the message that an include file has been saved, which can be included into our source code with the line ".include "" behind the line "rjmp loop".

This brings us two tables to the source code. The first one is "KeyTable:", consists of the lower and upper bound of each of the 16 keys and ends with the label "KeyTableEnd:".

The second table named "Keys:" has all the key's ASCII characters in the correct voltage row.

With these two tables a conversion program can be written that converts the 29 to the "1". This conversion program is 34 lines long and can be found here. It needs a functioning include file "" in the project folder. The associated flow diagram can be found in avr_sim's handbook.

Using the program for another AVR type should not be too complicated. Attention Arduino-socialized C freaks: in an ATmega328 most of the ADC's port registers are beyond the scope of the IN/OUT instructions! Use LDS/STS instead for instructions that produce an error message when assembling (and only for those, not for all!).

Equally simple should be to replace the long-lasting polling procedure by interrupt-driven AD conversion.

A little bit more complicated is the debouncing of the keys. Here one profits from the long conversion time of a few milli- seconds. If you'll get the same key over, e.g. eight, times, you can take it for serious. The next key is then to be blocked until the keyboard routine returns at least eight times with a result of zero.

And now: Good luck with sukcessive approach procedures!

An den Seitenanfang

©2022 by