#!/usr/bin/env nickle /* * Given a main clock frequency, * compute USART clock freq and a table * of USART config parameters for our target baud rates */ real main_clock = 0; real usart_clock = 0; real[] baud_rates = { 4800, 9600, 19200, 57600, 115200 }; void compute_baud_rate(real rate) { int divaddval; int mulval; real dl_est = usart_clock / (16 * rate); if (dl_est == floor(dl_est)) { divaddval = 0; mulval = 1; } else { if (false) { /* This is how the docs suggest doing it; this * generates a rate which is reasonably close */ real fr_est = 1.5; /* Compute fractional estimate */ do { dl_est = floor(usart_clock / (16 * rate * fr_est) + 0.5); fr_est = usart_clock / (16 * rate * dl_est); } while (fr_est <= 1.1 || 1.9 <= fr_est); /* Given fractional estimate, compute divaddval/mulvals that work best */ real best_dist = 1000; for (int tmp_divaddval = 1; tmp_divaddval < 15; tmp_divaddval++) { for (int tmp_mulval = 1; tmp_mulval < 16; tmp_mulval++) { real fr = 1 + tmp_divaddval / tmp_mulval; real dist = abs(fr - fr_est); if (dist < best_dist) { divaddval = tmp_divaddval; mulval = tmp_mulval; best_dist = dist; } } } } else { /* This exhaustively searches for the best match */ real my_best_dist = 1e20; int my_best_dl; int my_best_divaddval; int my_best_mulval; for (int my_dl = 1; my_dl < 1024; my_dl++) { for (int my_mulval = 1; my_mulval < 16; my_mulval++) { for (int my_divaddval = 0; my_divaddval < my_mulval; my_divaddval++) { real my_rate = usart_clock / ((16 * my_dl) * (1 + my_divaddval/my_mulval)); real my_dist = abs(rate - my_rate); if (my_dist == 0 && my_divaddval == 0) { my_dist = -1; } if (my_dist < my_best_dist) { my_best_dl = my_dl; my_best_divaddval = my_divaddval; my_best_mulval = my_mulval; my_best_dist = my_dist; } } } } dl_est = my_best_dl; divaddval = my_best_divaddval; mulval = my_best_mulval; } } int dl = floor (dl_est); real actual = usart_clock / ((16 * dl) * (1 + divaddval/mulval)); printf("\t[AO_SERIAL_SPEED_%d] = { /* actual = %8.2f */\n", floor(rate), actual); printf("\t\t.dl = %d,\n", dl); printf("\t\t.divaddval = %d,\n", divaddval); printf("\t\t.mulval = %d\n", mulval); printf("\t},\n"); } void main() { if (dim(argv) < 2) { printf ("usage: %s \n", argv[0]); exit(1); } main_clock = string_to_real(argv[1]); for (int div = 0; div < 4; div++) { if (main_clock / (1 << div) <= 12000000) { usart_clock = main_clock / (1 << div); break; } } if (usart_clock == 0) { printf ("can't get usart clock in range\n"); exit(1); } printf ("#define AO_LPC_USARTCLK %d\n\n", floor(usart_clock)); printf("static const struct {\n"); printf("\tuint16_t dl;\n"); printf("\tuint8_t divaddval;\n"); printf("\tuint8_t mulval;\n"); printf("} ao_usart_speeds[] = {\n"); for (int i = 0; i < dim(baud_rates); i++) { compute_baud_rate(baud_rates[i]); } printf ("};\n"); } main();