]> git.gag.com Git - debian/gnuradio/blob - usrp2/firmware/apps/app_common_v2.c
test the ability to read default eeprom values, for D. Symeonidis
[debian/gnuradio] / usrp2 / firmware / apps / app_common_v2.c
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2007,2008,2009 Free Software Foundation, Inc.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include "app_common_v2.h"
24 #include "buffer_pool.h"
25 #include "memcpy_wa.h"
26 #include "ethernet.h"
27 #include "nonstdio.h"
28 #include "print_rmon_regs.h"
29 #include "db.h"
30 #include "db_base.h"
31 #include "clocks.h"
32 #include "u2_init.h"
33 #include <string.h>
34 //#include "db_init.h"
35 #include "usrp2_i2c_addr.h"
36
37 volatile bool link_is_up = false;       // eth handler sets this
38 int cpu_tx_buf_dest_port = PORT_ETH;
39
40 // If this is non-zero, this dbsm could be writing to the ethernet
41 dbsm_t *ac_could_be_sending_to_eth;
42
43 static unsigned char exp_seqno __attribute__((unused)) = 0;
44
45 static inline bool
46 sync_to_pps(const op_generic_t *p)
47 {
48   timesync_regs->sync_on_next_pps = 1;
49   //putstr("SYNC to PPS\n");
50   return true;
51 }
52
53 static bool
54 sync_every_pps(const op_generic_t *p)
55 {
56   if (p->ok)
57     timesync_regs->tick_control |= TSC_TRIGGER_EVERYPPS;
58   else
59     timesync_regs->tick_control &= ~TSC_TRIGGER_EVERYPPS;
60
61   return true;
62 }
63
64 static inline bool
65 config_mimo_cmd(const op_config_mimo_t *p)
66 {
67   clocks_mimo_config(p->flags);
68   return true;
69 }
70
71 void
72 set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt)
73 {
74   reply_pkt->ehdr.dst = cmd_pkt->ehdr.src;
75   reply_pkt->ehdr.src = *ethernet_mac_addr();
76   reply_pkt->ehdr.ethertype = U2_ETHERTYPE;
77   reply_pkt->thdr.flags = 0;
78   reply_pkt->thdr.fifo_status = 0;      // written by protocol engine
79   reply_pkt->thdr.seqno = 0;            // written by protocol engine
80   reply_pkt->thdr.ack = 0;              // written by protocol engine
81   u2p_set_word0(&reply_pkt->fixed, 0, CONTROL_CHAN);
82   reply_pkt->fixed.timestamp = timer_regs->time;
83 }
84
85 static void
86 send_reply(unsigned char *reply, size_t reply_len)
87 {
88   if (reply_len < 64)
89     reply_len = 64;
90
91   // wait for buffer to become idle
92   hal_set_leds(0x4, 0x4);
93   while((buffer_pool_status->status & BPS_IDLE(CPU_TX_BUF)) == 0)
94     ;
95   hal_set_leds(0x0, 0x4);
96
97   // copy reply into CPU_TX_BUF
98   memcpy_wa(buffer_ram(CPU_TX_BUF), reply, reply_len);
99
100   // wait until nobody else is sending to the ethernet
101   if (ac_could_be_sending_to_eth){
102     hal_set_leds(0x8, 0x8);
103     dbsm_wait_for_opening(ac_could_be_sending_to_eth);
104     hal_set_leds(0x0, 0x8);
105   }
106
107   if (0){
108     printf("sending_reply to port %d, len = %d\n", cpu_tx_buf_dest_port, (int)reply_len);
109     print_buffer(buffer_ram(CPU_TX_BUF), reply_len/4);
110   }
111
112   // fire it off
113   bp_send_from_buf(CPU_TX_BUF, cpu_tx_buf_dest_port, 1, 0, reply_len/4);
114
115   // wait for it to complete (not long, it's a small pkt)
116   while((buffer_pool_status->status & (BPS_DONE(CPU_TX_BUF) | BPS_ERROR(CPU_TX_BUF))) == 0)
117     ;
118
119   bp_clear_buf(CPU_TX_BUF);
120 }
121
122
123 static size_t
124 op_id_cmd(const op_generic_t *p,
125           void *reply_payload, size_t reply_payload_space)
126 {
127   op_id_reply_t *r = (op_id_reply_t *) reply_payload;
128   if (reply_payload_space < sizeof(*r)) // no room
129     return 0;
130
131   // Build reply subpacket
132
133   r->opcode = OP_ID_REPLY;
134   r->len = sizeof(op_id_reply_t);
135   r->rid = p->rid;
136   r->addr = *ethernet_mac_addr();
137   r->hw_rev = (u2_hw_rev_major << 8) | u2_hw_rev_minor;
138   // r->fpga_md5sum = ; // FIXME
139   // r->sw_md5sum = ;   // FIXME
140
141   return r->len;
142 }
143
144
145 static size_t
146 config_tx_v2_cmd(const op_config_tx_v2_t *p,
147                  void *reply_payload, size_t reply_payload_space)
148 {
149   op_config_tx_reply_v2_t *r = (op_config_tx_reply_v2_t *) reply_payload;
150   if (reply_payload_space < sizeof(*r))
151     return 0;                                   // no room
152
153   struct tune_result    tune_result;
154   memset(&tune_result, 0, sizeof(tune_result));
155
156   bool ok = true;
157
158   if (p->valid & CFGV_GAIN){
159     ok &= db_set_gain(tx_dboard, p->gain);
160   }
161
162   if (p->valid & CFGV_FREQ){
163     bool was_streaming = is_streaming();
164     if (was_streaming)
165       stop_rx_cmd();
166
167     u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo);
168     bool tune_ok = db_tune(tx_dboard, f, &tune_result);
169     ok &= tune_ok;
170     print_tune_result("Tx", tune_ok, f, &tune_result);
171
172     if (was_streaming)
173       restart_streaming();
174   }
175
176   if (p->valid & CFGV_INTERP_DECIM){
177     int interp = p->interp;
178     int hb1 = 0;
179     int hb2 = 0;
180
181     if (!(interp & 1)){
182       hb2 = 1;
183       interp = interp >> 1;
184     }
185
186     if (!(interp & 1)){
187       hb1 = 1;
188       interp = interp >> 1;
189     }
190
191     if (interp < MIN_CIC_INTERP || interp > MAX_CIC_INTERP)
192       ok = false;
193     else {
194       dsp_tx_regs->interp_rate = (hb1<<9) | (hb2<<8) | interp;
195       // printf("Interp: %d, register %d\n", p->interp, (hb1<<9) | (hb2<<8) | interp);
196     }
197   }
198
199   if (p->valid & CFGV_SCALE_IQ){
200     dsp_tx_regs->scale_iq = p->scale_iq;
201   }
202
203   // Build reply subpacket
204
205   r->opcode = OP_CONFIG_TX_REPLY_V2;
206   r->len = sizeof(*r);
207   r->rid = p->rid;
208   r->ok = ok;
209   r->inverted = tune_result.inverted;
210   r->baseband_freq_hi = u2_fxpt_freq_hi(tune_result.baseband_freq);
211   r->baseband_freq_lo = u2_fxpt_freq_lo(tune_result.baseband_freq);
212   r->duc_freq_hi = u2_fxpt_freq_hi(tune_result.dxc_freq);
213   r->duc_freq_lo = u2_fxpt_freq_lo(tune_result.dxc_freq);
214   r->residual_freq_hi = u2_fxpt_freq_hi(tune_result.residual_freq);
215   r->residual_freq_lo = u2_fxpt_freq_lo(tune_result.residual_freq);
216   return r->len;
217 }
218
219 static size_t
220 config_rx_v2_cmd(const op_config_rx_v2_t *p,
221                  void *reply_payload, size_t reply_payload_space)
222 {
223   op_config_rx_reply_v2_t *r = (op_config_rx_reply_v2_t *) reply_payload;
224   if (reply_payload_space < sizeof(*r))
225     return 0;                           // no room
226
227   struct tune_result    tune_result;
228   memset(&tune_result, 0, sizeof(tune_result));
229
230   bool ok = true;
231
232   if (p->valid & CFGV_GAIN){
233     ok &= db_set_gain(rx_dboard, p->gain);
234   }
235
236   if (p->valid & CFGV_FREQ){
237     bool was_streaming = is_streaming();
238     if (was_streaming)
239       stop_rx_cmd();
240
241     u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo);
242     bool tune_ok = db_tune(rx_dboard, f, &tune_result);
243     ok &= tune_ok;
244     print_tune_result("Rx", tune_ok, f, &tune_result);
245
246     if (was_streaming)
247       restart_streaming();
248   }
249
250   if (p->valid & CFGV_INTERP_DECIM){
251     int decim = p->decim;
252     int hb1 = 0;
253     int hb2 = 0;
254
255     if(!(decim & 1)) {
256       hb2 = 1;
257       decim = decim >> 1;
258     }
259
260     if(!(decim & 1)) {
261       hb1 = 1;
262       decim = decim >> 1;
263     }
264
265     if (decim < MIN_CIC_DECIM || decim > MAX_CIC_DECIM)
266       ok = false;
267     else {
268       dsp_rx_regs->decim_rate = (hb1<<9) | (hb2<<8) | decim;
269       // printf("Decim: %d, register %d\n", p->decim, (hb1<<9) | (hb2<<8) | decim);
270     }
271   }
272
273   if (p->valid & CFGV_SCALE_IQ){
274     dsp_rx_regs->scale_iq = p->scale_iq;
275   }
276
277   // Build reply subpacket
278
279   r->opcode = OP_CONFIG_RX_REPLY_V2;
280   r->len = sizeof(*r);
281   r->rid = p->rid;
282   r->ok = ok;
283   r->inverted = tune_result.inverted;
284   r->baseband_freq_hi = u2_fxpt_freq_hi(tune_result.baseband_freq);
285   r->baseband_freq_lo = u2_fxpt_freq_lo(tune_result.baseband_freq);
286   r->ddc_freq_hi = u2_fxpt_freq_hi(tune_result.dxc_freq);
287   r->ddc_freq_lo = u2_fxpt_freq_lo(tune_result.dxc_freq);
288   r->residual_freq_hi = u2_fxpt_freq_hi(tune_result.residual_freq);
289   r->residual_freq_lo = u2_fxpt_freq_lo(tune_result.residual_freq);
290
291   return r->len;
292 }
293
294 static size_t
295 read_time_cmd(const op_generic_t *p,
296               void *reply_payload, size_t reply_payload_space)
297 {
298   op_read_time_reply_t *r = (op_read_time_reply_t *) reply_payload;
299   if (reply_payload_space < sizeof(*r))
300     return 0;                                   // no room
301
302   r->opcode = OP_READ_TIME_REPLY;
303   r->len = sizeof(*r);
304   r->rid = p->rid;
305   r->time = timer_regs->time;
306
307   return r->len;
308 }
309
310 static void
311 fill_db_info(u2_db_info_t *p, const struct db_base *db)
312 {
313   //p->dbid = db->dbid;
314   p->freq_min_hi = u2_fxpt_freq_hi(db->freq_min);
315   p->freq_min_lo = u2_fxpt_freq_lo(db->freq_min);
316   p->freq_max_hi = u2_fxpt_freq_hi(db->freq_max);
317   p->freq_max_lo = u2_fxpt_freq_lo(db->freq_max);
318   p->gain_min = db->gain_min;
319   p->gain_max = db->gain_max;
320   p->gain_step_size = db->gain_step_size;
321 }
322
323 static size_t
324 dboard_info_cmd(const op_generic_t *p,
325                 void *reply_payload, size_t reply_payload_space)
326 {
327   op_dboard_info_reply_t *r = (op_dboard_info_reply_t *) reply_payload;
328   if (reply_payload_space < sizeof(*r))
329     return 0;                                   // no room
330
331   r->opcode = OP_DBOARD_INFO_REPLY;
332   r->len = sizeof(*r);
333   r->rid = p->rid;
334   r->ok = true;
335
336   fill_db_info(&r->tx_db_info, tx_dboard);
337   fill_db_info(&r->rx_db_info, rx_dboard);
338
339   r->tx_db_info.dbid = read_dboard_eeprom(I2C_ADDR_TX_A);
340   r->rx_db_info.dbid = read_dboard_eeprom(I2C_ADDR_RX_A);
341
342   return r->len;
343 }
344
345 static size_t
346 peek_cmd(const op_peek_t *p,
347          void *reply_payload, size_t reply_payload_space)
348 {
349   op_generic_t *r = (op_generic_t *) reply_payload;
350
351   //putstr("peek: addr="); puthex32(p->addr);
352   //printf(" bytes=%u\n", p->bytes);
353
354   if ((reply_payload_space < (sizeof(*r) + p->bytes)) ||
355       p->bytes > MAX_SUBPKT_LEN - sizeof(op_generic_t)) {
356     putstr("peek: insufficient reply packet space\n");
357     return 0;                   // FIXME do partial read?
358   }
359
360   r->opcode = OP_PEEK_REPLY;
361   r->len = sizeof(*r)+p->bytes;
362   r->rid = p->rid;
363   r->ok = true;
364
365   memcpy_wa(reply_payload+sizeof(*r), (void *)p->addr, p->bytes);
366
367   return r->len;
368 }
369
370 static bool
371 poke_cmd(const op_poke_t *p)
372 {
373   int bytes = p->len - sizeof(*p);
374   //putstr("poke: addr="); puthex32(p->addr);
375   //printf(" bytes=%u\n", bytes);
376
377   uint8_t *src = (uint8_t *)p + sizeof(*p);
378   memcpy_wa((void *)p->addr, src, bytes);
379
380   return true;
381 }
382
383 static bool
384 set_lo_offset_cmd(const op_freq_t *p)
385 {
386   u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo);
387   if (p->opcode == OP_SET_TX_LO_OFFSET)
388     return db_set_lo_offset(tx_dboard, f);
389   else
390     return db_set_lo_offset(rx_dboard, f);
391 }
392
393 static size_t
394 gpio_read_cmd(const op_gpio_t *p,
395               void *reply_payload, size_t reply_payload_space)
396 {
397   op_gpio_read_reply_t *r = (op_gpio_read_reply_t *) reply_payload;
398   if (reply_payload_space < sizeof(*r)) // no room
399     return 0;
400
401  // Build reply subpacket
402
403   r->opcode = OP_GPIO_READ_REPLY;
404   r->len = sizeof(op_gpio_read_reply_t);
405   r->rid = p->rid;
406   r->ok = true;
407   r->mbz = 0;
408   r->value = hal_gpio_read(p->bank);
409
410   return r->len;
411 }
412
413 static size_t
414 generic_reply(const op_generic_t *p,
415               void *reply_payload, size_t reply_payload_space,
416               bool ok)
417 {
418   op_generic_t *r = (op_generic_t *) reply_payload;
419   if (reply_payload_space < sizeof(*r))
420     return 0;                                   // no room
421
422   r->opcode = p->opcode | OP_REPLY_BIT;
423   r->len = sizeof(*r);
424   r->rid = p->rid;
425   r->ok = ok;
426
427   return r->len;
428 }
429
430 static size_t
431 add_eop(void *reply_payload, size_t reply_payload_space)
432 {
433   op_generic_t *r = (op_generic_t *) reply_payload;
434   if (reply_payload_space < sizeof(*r))
435     return 0;                                   // no room
436
437   r->opcode = OP_EOP;
438   r->len = sizeof(*r);
439   r->rid = 0;
440   r->ok =  0;
441
442   return r->len;
443 }
444
445 void
446 handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len)
447 {
448   unsigned char reply[sizeof(u2_eth_packet_t) + 4 * sizeof(u2_subpkt_t)] _AL4;
449   unsigned char *reply_payload = &reply[sizeof(u2_eth_packet_t)];
450   int reply_payload_space = sizeof(reply) - sizeof(u2_eth_packet_t);
451
452   // initialize reply
453   memset(reply, 0, sizeof(reply));
454   set_reply_hdr((u2_eth_packet_t *) reply, pkt);
455
456   // point to beginning of payload (subpackets)
457   unsigned char *payload = ((unsigned char *) pkt) + sizeof(u2_eth_packet_t);
458   int payload_len = len - sizeof(u2_eth_packet_t);
459
460   size_t subpktlen = 0;
461   bool ok = false;
462
463   while (payload_len >= sizeof(op_generic_t)){
464     const op_generic_t *gp = (const op_generic_t *) payload;
465     subpktlen = 0;
466
467     // printf("\nopcode = %d\n", gp->opcode);
468
469     switch(gp->opcode){
470     case OP_EOP:                // end of subpackets
471       goto end_of_subpackets;
472
473     case OP_ID:
474       subpktlen = op_id_cmd(gp, reply_payload, reply_payload_space);
475       break;
476
477     case OP_CONFIG_TX_V2:
478       subpktlen = config_tx_v2_cmd((op_config_tx_v2_t *) payload, reply_payload, reply_payload_space);
479       break;
480
481     case OP_CONFIG_RX_V2:
482       subpktlen = config_rx_v2_cmd((op_config_rx_v2_t *) payload, reply_payload, reply_payload_space);
483       break;
484
485     case OP_START_RX_STREAMING:
486       if (pkt->fixed.timestamp == -1) // Start now (default)
487         start_rx_streaming_cmd(&pkt->ehdr.src, (op_start_rx_streaming_t *) payload);
488       else
489         start_rx_streaming_at_cmd(&pkt->ehdr.src, (op_start_rx_streaming_t *)payload, pkt->fixed.timestamp);
490       ok = true;
491       goto generic_reply;
492
493     case OP_STOP_RX:
494       stop_rx_cmd();
495       ok = true;
496       goto generic_reply;
497
498     case OP_BURN_MAC_ADDR:
499       ok = ethernet_set_mac_addr(&((op_burn_mac_addr_t *)payload)->addr);
500       goto generic_reply;
501
502     case OP_CONFIG_MIMO:
503       ok = config_mimo_cmd((op_config_mimo_t *) payload);
504       goto generic_reply;
505
506     case OP_READ_TIME:
507       subpktlen = read_time_cmd(gp, reply_payload, reply_payload_space);
508       break;
509
510     case OP_DBOARD_INFO:
511       subpktlen = dboard_info_cmd(gp, reply_payload, reply_payload_space);
512       break;
513
514     case OP_SYNC_TO_PPS:
515       sync_to_pps((op_generic_t *) payload);
516       ok = true;
517       goto generic_reply;
518
519     case OP_PEEK:
520       subpktlen = peek_cmd((op_peek_t *)payload, reply_payload, reply_payload_space);
521       break;
522
523     case OP_POKE:
524       ok = poke_cmd((op_poke_t *)payload);
525       goto generic_reply;
526
527     case OP_SET_TX_LO_OFFSET:
528     case OP_SET_RX_LO_OFFSET:
529       ok = set_lo_offset_cmd((op_freq_t *)payload);
530       goto generic_reply;
531
532     case OP_RESET_DB:
533       db_init();
534       ok = true;
535       goto generic_reply;
536
537     case OP_SYNC_EVERY_PPS:
538       ok = sync_every_pps((op_generic_t *) payload);
539       goto generic_reply;
540
541     case OP_GPIO_SET_DDR:
542       ok = true;
543       hal_gpio_set_ddr(((op_gpio_t *)payload)->bank,
544                        ((op_gpio_t *)payload)->value,
545                        ((op_gpio_t *)payload)->mask);
546       goto generic_reply;
547
548     case OP_GPIO_SET_SELS:
549       ok = true;
550       hal_gpio_set_sels(((op_gpio_set_sels_t *)payload)->bank,
551                         (char *)(&((op_gpio_set_sels_t *)payload)->sels));
552       goto generic_reply;
553
554     case OP_GPIO_READ:
555       subpktlen = gpio_read_cmd((op_gpio_t *) payload, reply_payload, reply_payload_space);
556       break;
557
558     case OP_GPIO_WRITE:
559       ok = true;
560       hal_gpio_write(((op_gpio_t *)payload)->bank,
561                      ((op_gpio_t *)payload)->value,
562                      ((op_gpio_t *)payload)->mask);
563       goto generic_reply;
564
565     case OP_GPIO_STREAM:
566       ok = true;
567       dsp_rx_regs->gpio_stream_enable = (uint32_t)((op_gpio_t *)payload)->value;
568       goto generic_reply;
569
570     // Add new opcode handlers here
571
572     generic_reply:
573       subpktlen = generic_reply(gp, reply_payload, reply_payload_space, ok);
574       break;
575
576     default:
577       printf("app_common_v2: unhandled opcode = %d\n", gp->opcode);
578       break;
579     }
580
581     int t = (gp->len + 3) & ~3;         // bump to a multiple of 4
582     payload += t;
583     payload_len -= t;
584
585     subpktlen = (subpktlen + 3) & ~3;   // bump to a multiple of 4
586     reply_payload += subpktlen;
587     reply_payload_space -= subpktlen;
588   }
589
590  end_of_subpackets:
591
592   // add the EOP marker
593   subpktlen = add_eop(reply_payload, reply_payload_space);
594   subpktlen = (subpktlen + 3) & ~3;     // bump to a multiple of 4
595   reply_payload += subpktlen;
596   reply_payload_space -= subpktlen;
597
598   send_reply(reply, reply_payload - reply);
599 }
600
601
602 /*
603  * Called when an ethernet packet is received.
604  * Return true if we handled it here, otherwise
605  * it'll be passed on to the DSP Tx pipe
606  */
607 bool
608 eth_pkt_inspector(dbsm_t *sm, int bufno)
609 {
610   u2_eth_packet_t *pkt = (u2_eth_packet_t *) buffer_ram(bufno);
611   size_t byte_len = (buffer_pool_status->last_line[bufno] - 1) * 4;
612
613   //static size_t last_len = 0;
614
615   // hal_toggle_leds(0x1);
616
617   // inspect rcvd frame and figure out what do do.
618
619   if (pkt->ehdr.ethertype != U2_ETHERTYPE)
620     return true;        // ignore, probably bogus PAUSE frame from MAC
621
622   int chan = u2p_chan(&pkt->fixed);
623
624   switch (chan){
625   case CONTROL_CHAN:
626     handle_control_chan_frame(pkt, byte_len);
627     return true;        // we handled the packet
628     break;
629
630   case 0:
631   default:
632 #if 0
633     if (last_len != 0){
634       if (byte_len != last_len){
635         printf("Len: %d last: %d\n", byte_len, last_len);
636       }
637     }
638     last_len = byte_len;
639
640     if((pkt->thdr.seqno) == exp_seqno){
641       exp_seqno++;
642       //putchar('.');
643     }
644     else {
645       // putchar('S');
646       //printf("S%d %d ",exp_seqno,pkt->thdr.seqno);
647       exp_seqno = pkt->thdr.seqno + 1;
648     }
649 #endif
650     return false;       // pass it on to Tx DSP
651     break;
652   }
653 }
654
655 /*
656  * Called when eth phy state changes (w/ interrupts disabled)
657  */
658 void
659 link_changed_callback(int speed)
660 {
661   link_is_up = speed != 0;
662   hal_set_leds(link_is_up ? LED_RJ45 : 0x0, LED_RJ45);
663   printf("\neth link changed: speed = %d\n", speed);
664 }
665
666
667 void
668 print_tune_result(char *msg, bool tune_ok,
669                   u2_fxpt_freq_t target_freq, struct tune_result *r)
670 {
671 #if 0
672   printf("db_tune %s %s\n", msg, tune_ok ? "true" : "false");
673   putstr("  target_freq   "); print_fxpt_freq(target_freq); newline();
674   putstr("  baseband_freq "); print_fxpt_freq(r->baseband_freq); newline();
675   putstr("  dxc_freq      "); print_fxpt_freq(r->dxc_freq); newline();
676   putstr("  residual_freq "); print_fxpt_freq(r->residual_freq); newline();
677   printf("  inverted      %s\n", r->inverted ? "true" : "false");
678 #endif
679 }