Path: Home => AVR overview => Applications => ATtiny crystals => Crystal divider   Diese Seite in Deutsch: Flag DE Logo
Tiny XTAL oscillator Applications of
AVR single chip controllers AT90S, ATtiny, ATmega and ATxmega
A crystal divider for music tones with ATtiny24

Crystal divider for music tones with ATtiny24

Slightly different than the 8-Bit-TC version here does a 16-Bit-TC version like this here look: a 16-bit-TC is clocked with a crystal and produces up to 60 different gamut tones on the output pin. Up to 60 different keys can be attached via resistor networks (either with one network with 60 different 1% resistors or up to six networks with ten, twelve, fifteen, twenty or thirty keys in every network. Note that only ONE of those keys can be pressed at a time.

Calculation as done in the LibreOffice-Calc file here is also slightly different than for the 8-bit version, as is the schematic and the flow-chart in the LibreOffice-Draw file here.

Top of page Hardware Tones Crystals Resistors Software

The hardware of the 16-bit gamut player

Schematic of the ATtiny24 gamut player This is the hardware needed:
  1. A crystal clocks an ATtiny24 on the two XTAL pins of the device.
  2. The tone to be played is selected by keys K1 to KN, that are connected, via a resistor network, to an ADC input pin. The complete number of keys (up to 60) can be connected to only one single ADC pin or it can be splitted into up to six different resistor networks, each with an identical resistor value set. Splitting eases the resistor requirements (e. g. using E12 instead of E24 resistors or 5% instead of 1% tolerance).
  3. The output signal comes from the OC1A pin of the device. The electrolytical capacitor and the speaker can be disconnected by opening the jumper J1 in case of ISP6 programming via the ISP6 interface plug.
  4. The operating voltage should be 4.5 V or higher with 10++MHz crystals, for lower frequencies you can use the full specified voltage range.
Note that, if more than four resistor networks are to be attached, those will require a small resistor of 1k for decoupling the ISP6 pins from the network. In most cases this isn't necessary, but in cases where the smallest network resistors are below 1k and if their key is pressed during programming, the current for the ISP-programmer might get too high. A rare case, but it is only one resistor to prevent this.

The crystal and the resistors can be configured with the LibreOffice spreadsheets here.

The tn24 generator on the breadboard This is all you need. Here with a 20MHz crystal, and with all 60 tones on one single trim potentiometer (cRNetw = 0).

Top of page Hardware Tones Crystals Resistors Software

Configuring the tones

The tones that can be played This sheet holds a complete list of all playable tones between note a' minor (a1m) and the note d''''''' (d7). Listed is the note's name and the frequency in Hz.

With the spreadsheet tones you can configure the tones that are to be played. With the drop-down cell B3 you can select the first tone, with B4 the last tone. The column C shows the frequencies of those two tones. The number of tones to be played is in cell B5.

Note that the entries selected here are exported to other sheets as well.

Top of page Hardware Tones Crystals Resistors Software

Selecting the crystal

List of crystals The sheet crystals holds all commerciall available crystals by their frequency. A few (e.g. 1.2/2.4/4.8/9.6) were added to include the ATtiny13's internal RC oscillator. The ones displayed here are only those with the highest frequencies, slide up for more.

The sheet further displays the dividers for all configured frequencies, that are seen in the lines 3 (Tone number), 4 (Tone name) and 5 (Tone frequency).

All numbers are based on a prescaler value of 1. If that is not possible (with minor tones at higher crystal frequencies), the cells have a yellow background and are then based on a prescaler of 8.

The best-fitting crystal is calculated in the sheet delta, only the result is presented here. The best-fitting crystal is marked in green in column A.

The sheet ctc calculates the CTC values for Compare-A of the TC1 (divider rounded and minus one). The sheet fIs calculates the generated frequency. From this, the sheet delta calculates the relative distance in % of the target value. Those differences are squared, summed up over all desired tones, the root is calculated and divided by the number of tones. From this, the best-fitting crystal is determined (as the one with the smallest deviation to all tones to be played).

Crystal-specific source code table Finally, the sheet SourceCode allows to select one of the crystals (not necessarily the best-fitting one) in the drop-down cell B6. This crystal then calculates a list of dividers (CTC compare values) for all selected tones and formats this as a table for the source code. If the note requires a prescaler value of 8 instead of 1, a hint is added as comment.

For copying the list to the source code, select all lines with a yellow background, press Ctrl-C, move to the end of the source code and press Ctrl-V. If you have lines with a prescaler of 8, it might be a good idea to place a label on the first value behind the last 8-entry, e.g. ToneTable1:, so your software can detect the prescaler change from the table entry.

Configuring the resistors

The resistor networks The sheet resistors calculates the resistors for the key-resistor-networks. To the left of this sheet, the number of resistor networks are calculated, to the right (shown below) are the resistors.

The resistors are different, depending from the number of networks that are used. Input the number of networks (between 1 and 6) in cell D3 of the sheet resistors. This distributes the tones over the desired networks. Here the 35 tones are distributed over three networks. That means that there are three exemplars of 12 different resistor values Res # necessary.

The resistor networks The 12 resistors necessary are calculated on the right side of the sheet. The white-on-green fields provide recommendations for the entries in the light-green-backgrounded entry fields below. In that case with 12 resistors, the E12 row and 1% are sufficient. The column O with Max = lists the differences over which a measured ADC value is attributed to a certain key (increases in the first half of the keys, decreases in the second half). The column P with Min = lists the difference between the high ADC value of this resistor and the low ADC value of the next resistor. These values should all be zero or positive. If not, re-adjust the resistor row (to E24) and/or the tolerance (to 2 or 1%). If that doesn't help enough, increase the resistor R0.

Note that the values in the column H stem from another sheet that provides a sophisticated value list for that purpose. This ensures that 60 different keys produce 60 specific voltage ranges and that 60 resistors of the E24 row with 1% tolerance fits (if you addionally increase the R0=4.7kΩ slightly). If you need a smaller number of resistors

The ADC table in column Q can be copied to the source code. It provides two words: the first one is the lower range of ADC values for this resistor, the second one is the higher range of ADC values plus one. So, if an ADC value is between the lower range and smaller than the upper range, the key of this resistor is pressed. If the ADC value is smaller than the lower value, the key is not pressed. The last entry in the table stops the search.

If you sum up 64 ADC measurements, leave the drop-down field in cell Q3. If you do not sum up ADC measurements, enter 1 here.

To copy the table to the source code, just select the cells with a yellow background in column Q, press Ctrl-C, move to the end of your source code and press Ctrl-V.


Flow chart of the software The software is written in assembler using the flow-chart to the right. The assembler source code can be downloaded from here. It is, by default, written for a three-resistor-networks setting, as described above. If you need a different setting, feel free to edit this source code.

Shown in the flow chart is the conversion of the ADC measurement to the tone, as well as the ADC channel control for multiple resistor networks, as well as the compare match A interrupt and the taking-over of tone values to the timer.

Note that most of the complex operations stem from the fact that up to six different resistor networks have to be checked. If in one of the networks a hit occurs, the bit bDtct has to be set in the rFlags register. This bit prevents that the tone is switched off at the end of the last resistor cycle (which had been switched active when the first hit was encountered).

The register pair XH:XL is used to calculate a displacement onto the tone table. Whenever a register network has been finished, the X pointer points to the next package of tones.

The flow diagram shows only the ADC result operations. You need to add the ADC1 initiation and the interrupt service routine for the ADC1 measurements, which sets the bAdc flag when complete (e.g. after 64 measurements and of summing those up).

TC1 should be initiated in CTC mode with the toggle of OC1A off and the compare match A interrupt enabled. The registers R0 to R3 should be set to convenient values (e. g. 100 to compare match A in R1:R0, non-toggle in R2, prescaler to 1 in R3), as those are written to the timer in every compare-match-A-ISR of the timer.

The parameter cAdcClkP should be set to a convenient value. This involves the crystal frequency, the repetition of ADC measurements that are summed up in cAdcCnt (preferably 64) and the desired reaction time between the tone-start-time and the key-press-time.

Not shown here is the init of the hardware and the ADC-Complete Interrupt-Service-Routine. This should add the ADC result to the rAdcH:rAdcL pair and down-count the rAdcCnt register. If zero, the flag bAdc should be set in the flag register rFlag. If not, the next ADC conversion must be started. The conversion of the ADC sum to the switch identification and the tone conversion should be outside the interrupt service routines, because it can require longer times.

Note that the software also includes the option that the number of resistor networks might be set to zero (.equ cRNetw = 0). In that case the voltage on ADC0 (the MSB) is multiplied by the number of tones plus one and, if zero, the tone is switched off. If the multiplication result is larger than zero, the tone is activated. This allows to attach a potentiometer onto ADC0 and to play all the tones with only one potentiometer's adjustment.

That is already it. Hear some convenient tones from your home-brewed keyboard with that.

Top of page Hardware Tones Crystals Resistors Software

©2023 by