altos/test: Adjust CRC error rate after FEC fix
[fw/altos] / src / lpc / baud_rate
1 #!/usr/bin/env nickle
2
3 /*
4  * Given a main clock frequency,
5  * compute USART clock freq and a table
6  * of USART config parameters for our target baud rates
7  */
8
9 real main_clock = 0;
10 real usart_clock = 0;
11
12 real[] baud_rates = { 4800, 9600, 19200, 57600, 115200 };
13
14 void
15 compute_baud_rate(real rate) {
16         int     divaddval;
17         int     mulval;
18
19         real    dl_est = usart_clock / (16 * rate);
20
21         if (dl_est == floor(dl_est)) {
22                 divaddval = 0;
23                 mulval = 1;
24         } else {
25                 if (false) {
26
27                         /* This is how the docs suggest doing it; this
28                          * generates a rate which is reasonably close
29                          */
30
31                         real fr_est = 1.5;
32
33                         /* Compute fractional estimate */
34                         do {
35                                 dl_est = floor(usart_clock / (16 * rate * fr_est) + 0.5);
36                                 fr_est = usart_clock / (16 * rate * dl_est);
37                         } while (fr_est <= 1.1 || 1.9 <= fr_est);
38
39                         /* Given fractional estimate, compute divaddval/mulvals that work best */
40
41                         real best_dist = 1000;
42                         for (int tmp_divaddval = 1; tmp_divaddval < 15; tmp_divaddval++) {
43                                 for (int tmp_mulval = 1; tmp_mulval < 16; tmp_mulval++) {
44                                         real fr = 1 + tmp_divaddval / tmp_mulval;
45                                         real dist = abs(fr - fr_est);
46                                         if (dist < best_dist) {
47                                                 divaddval = tmp_divaddval;
48                                                 mulval = tmp_mulval;
49                                                 best_dist = dist;
50                                         }
51                                 }
52                         }
53                 } else {
54
55                         /* This exhaustively searches for the best match */
56
57                         real my_best_dist = 1e20;
58                         int my_best_dl;
59                         int my_best_divaddval;
60                         int my_best_mulval;
61                         for (int my_dl = 1; my_dl < 1024; my_dl++) {
62                                 for (int my_mulval = 1; my_mulval < 16; my_mulval++) {
63                                         for (int my_divaddval = 0; my_divaddval < my_mulval; my_divaddval++) {
64                                                 real my_rate = usart_clock / ((16 * my_dl) * (1 + my_divaddval/my_mulval));
65
66                                                 real my_dist = abs(rate - my_rate);
67
68                                                 if (my_dist == 0 && my_divaddval == 0) {
69                                                         my_dist = -1;
70                                                 }
71
72                                                 if (my_dist < my_best_dist) {
73                                                         my_best_dl = my_dl;
74                                                         my_best_divaddval = my_divaddval;
75                                                         my_best_mulval = my_mulval;
76                                                         my_best_dist = my_dist;
77                                                 }
78                                         }
79                                 }
80                         }
81
82                         dl_est = my_best_dl;
83                         divaddval = my_best_divaddval;
84                         mulval = my_best_mulval;
85                 }
86         }
87
88         int dl = floor (dl_est);        
89
90         real actual = usart_clock / ((16 * dl) * (1 + divaddval/mulval));
91
92         printf("\t[AO_SERIAL_SPEED_%d] = { /* actual = %8.2f */\n", floor(rate), actual);
93         printf("\t\t.dl = %d,\n", dl);
94         printf("\t\t.divaddval = %d,\n", divaddval);
95         printf("\t\t.mulval = %d\n", mulval);
96         printf("\t},\n");
97 }
98
99 void
100 main() {
101         if (dim(argv) < 2) {
102                 printf ("usage: %s <main-clock>\n", argv[0]);
103                 exit(1);
104         }
105         main_clock = string_to_real(argv[1]);
106
107         for (int div = 0; div < 4; div++) {
108                 if (main_clock / (1 << div) <= 12000000) {
109                         usart_clock = main_clock / (1 << div);
110                         break;
111                 }
112         }
113
114         if (usart_clock == 0) {
115                 printf ("can't get usart clock in range\n");
116                 exit(1);
117         }
118
119         printf ("#define AO_LPC_USARTCLK %d\n\n", floor(usart_clock));
120         printf("static const struct {\n");
121         printf("\tuint16_t dl;\n");
122         printf("\tuint8_t divaddval;\n");
123         printf("\tuint8_t mulval;\n");
124         printf("} ao_usart_speeds[] = {\n");
125         for (int i = 0; i < dim(baud_rates); i++) {
126                 compute_baud_rate(baud_rates[i]);
127         }
128         printf ("};\n");
129 }
130
131 main();