'''

this program helps to compute note frequencies for a MCU based oscillator

where the selection of the optimal prescaller and counter value is

needed.

program output is a C array with counter register values.

each next note is larger than the one before it by the same ratio (the

twelfth root of 2, which is 1.05946309435929526456182529494634170077

9204317494... )

please check http://www.math.niu.edu/~rusin/uses-mat ... requencies

for list of frequencies.

to achieve excellent precission you may convert program to use numpy.

with numpy:

>>> def root(n, r):

... from numpy import roots

... return roots([1]+[0]*(r-1)+[-n])

...

root(2, r=12)[0]

(-1.0594630943592918+0j)

'''

DEBUG = False

notes = [

'C ', 'C#', 'D ', 'D#', 'E ', 'F ', 'F#', 'G ', 'G#', 'A ', 'A#', 'B ' ]

default_clock = 84000000.0 # chip clock

start_tone_frequency = 32.703195662574829 # C0

start_tone_midi = 21

stop_tone_frequency = 4186.01 # max desired frequency C8

twelfth_root_of_two = 1.059463094359295264561825294946341700779204317494

clock_frequencies = []

round_list = []

note_list = []

for clock_prescaler in range( 1, int( default_clock ) ):

if default_clock % clock_prescaler == 0:

if default_clock / clock_prescaler > stop_tone_frequency:

clock_frequencies.append( \

( default_clock / clock_prescaler, clock_prescaler ) )

elif DEBUG:

print "frequecy is less than the max desired frequency"

elif DEBUG:

print "divider does not produce round result"

print "---------------------------------------------------------------"

print "suitable frequencies: ", clock_frequencies

for clock_base_hz, clock_prescaler in clock_frequencies:

f = start_tone_frequency

f_midi_note = start_tone_midi

divider_is_less_than_oxffff = True

most_significant_frequency_gap = 0

print "---------------------------------------------------------------"

print "values for osc_base: ", clock_base_hz

print "clock_base_hz octave note f real_frequency tick_counter"

for octave in xrange( 1, 8 ):

for note in notes:

current_note_divider_is_less_than_oxffff = True

if clock_base_hz / f > 0xffff:

current_note_divider_is_less_than_oxffff = False

divider_is_less_than_oxffff = False

counter_value = round( clock_base_hz / f )

real_frequency = clock_base_hz / counter_value

real_frequency_gap = abs( real_frequency - f )

if most_significant_frequency_gap < real_frequency_gap:

most_significant_frequency_gap = real_frequency_gap

print clock_base_hz, octave, note, f, real_frequency_gap, \

counter_value

note_list.append( ( ( clock_base_hz, clock_prescaler ), \

( octave, note, f_midi_note, counter_value, f,

real_frequency, real_frequency - f, \

current_note_divider_is_less_than_oxffff ) ) )

f = f * twelfth_root_of_two

f_midi_note += 1

round_list.append( ( clock_base_hz , clock_prescaler, \

most_significant_frequency_gap, divider_is_less_than_oxffff ) )

suitable_frequencies_sorted = sorted( round_list, key=lambda l: l[2] )

print "---------------------------------------------------------------"

print "suitable frequencies (sorted by total inaccuracy): "

print "True/False shows if 16-bit long counter can be used"

for frequency in suitable_frequencies_sorted:

print frequency

print "---------------------------------------------------------------"

freq_to_list = input("Enter base freq to list notes: ")

print "octave note midi_note divider f real_f frequency_gap"

for record, values in note_list:

if record[0] == freq_to_list:

print values

print "---------------------------------------------------------------"

c_array_legend = ""

c_array_clock_prescalers = ""

c_array_clock_dividers = ""

c_count = 0

''' based on selected frequency create list of counter values '''

for record, values in note_list:

if record[0] == freq_to_list:

c_array_clock_prescalers += "%d, " % record[1]

c_count += 1

print "// osc: prescalers"

print "uint16_t clock_prescaler[%d] = { %s };" \

% ( c_count, c_array_clock_prescalers[:-2] )

''' example of values in note list:

oct note midi countr real_f computed_f f_error 0xffff

(7, 'B ', 104, 506.0, 7902.132820098011, 7905.138339920949, 3.0055198229383677, True)

'''

''' based on selected frequency create list of counter values '''

for record, values in note_list:

if record[0] == freq_to_list:

c_array_clock_dividers += "%d, " % values[3]

print "// osc: counters"

print "uint16_t clock_counter[%d] = { %s };" \

% ( c_count, c_array_clock_dividers[:-2] )

''' based on selected frequency create list of note detailed legends '''

for record, values in note_list:

if record[0] == freq_to_list:

c_array_legend += '"%s%s(%s) c: %s\\nfreq: %s", ' \

% ( values[0], values[1], \

values[2], values[3], \

values[4] )

print "// osc: legends"

print "char * clock_legend[%d] = { %s };" % ( c_count, c_array_legend[:-2] )

[ add comment ] ( 2 views ) | [ 0 trackbacks ] | permalink

**<<First <Back | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Next> Last>>**