diff options
46 files changed, 1028 insertions, 530 deletions
| diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c index 9cf4c163f..1c6e0624f 100644 --- a/firmware/microblaze/apps/txrx_uhd.c +++ b/firmware/microblaze/apps/txrx_uhd.c @@ -172,6 +172,33 @@ void handle_udp_data_packet(  #define OTW_GPIO_BANK_TO_NUM(bank) \      (((bank) == USRP2_DIR_RX)? (GPIO_RX_BANK) : (GPIO_TX_BANK)) +//setup the output data +static usrp2_ctrl_data_t ctrl_data_out; +static struct socket_address i2c_src; +static struct socket_address spi_src; + +static volatile bool i2c_done = false; +void i2c_read_done_callback(void) { +  //printf("I2C read done callback\n"); +  i2c_async_data_ready(ctrl_data_out.data.i2c_args.data); +  i2c_done = true; +  i2c_register_callback(0); +} + +void i2c_write_done_callback(void) { +  //printf("I2C write done callback\n"); +  i2c_done = true; +  i2c_register_callback(0); +} + +static volatile bool spi_done = false; +static volatile uint32_t spi_readback_data; +void get_spi_readback_data(void) { +  ctrl_data_out.data.spi_args.data = spi_get_data(); +  spi_done = true; +  spi_register_callback(0); +} +  void handle_udp_ctrl_packet(      struct socket_address src, struct socket_address dst,      unsigned char *payload, int payload_len @@ -197,11 +224,9 @@ void handle_udp_ctrl_packet(      }      //setup the output data -    usrp2_ctrl_data_t ctrl_data_out = { -        .proto_ver = USRP2_FW_COMPAT_NUM, -        .id=USRP2_CTRL_ID_HUH_WHAT, -        .seq=ctrl_data_in->seq -    }; +    ctrl_data_out.proto_ver = USRP2_FW_COMPAT_NUM; +    ctrl_data_out.id=USRP2_CTRL_ID_HUH_WHAT; +    ctrl_data_out.seq=ctrl_data_in->seq;      //handle the data based on the id      switch(ctrl_data_in_id){ @@ -212,6 +237,7 @@ void handle_udp_ctrl_packet(      case USRP2_CTRL_ID_WAZZUP_BRO:          ctrl_data_out.id = USRP2_CTRL_ID_WAZZUP_DUDE;          memcpy(&ctrl_data_out.data.ip_addr, get_ip_addr(), sizeof(struct ip_addr)); +        send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out));          break;      /******************************************************************* @@ -219,19 +245,21 @@ void handle_udp_ctrl_packet(       ******************************************************************/      case USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO:{              //transact -            uint32_t result = spi_transact( -                (ctrl_data_in->data.spi_args.readback == 0)? SPI_TXONLY : SPI_TXRX, +            bool success = spi_async_transact( +                //(ctrl_data_in->data.spi_args.readback == 0)? SPI_TXONLY : SPI_TXRX,                  ctrl_data_in->data.spi_args.dev,      //which device                  ctrl_data_in->data.spi_args.data,     //32 bit data                  ctrl_data_in->data.spi_args.num_bits, //length in bits -                (ctrl_data_in->data.spi_args.mosi_edge == USRP2_CLK_EDGE_RISE)? SPIF_PUSH_FALL : SPIF_PUSH_RISE | -                (ctrl_data_in->data.spi_args.miso_edge == USRP2_CLK_EDGE_RISE)? SPIF_LATCH_RISE : SPIF_LATCH_FALL +                (ctrl_data_in->data.spi_args.mosi_edge == USRP2_CLK_EDGE_RISE)? SPIF_PUSH_FALL : SPIF_PUSH_RISE | //flags +                (ctrl_data_in->data.spi_args.miso_edge == USRP2_CLK_EDGE_RISE)? SPIF_LATCH_RISE : SPIF_LATCH_FALL, +                get_spi_readback_data //callback              );              //load output -            ctrl_data_out.data.spi_args.data = result;              ctrl_data_out.id = USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE; +            spi_src = src;          } +//        send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out));          break;      /******************************************************************* @@ -239,11 +267,13 @@ void handle_udp_ctrl_packet(       ******************************************************************/      case USRP2_CTRL_ID_DO_AN_I2C_READ_FOR_ME_BRO:{              uint8_t num_bytes = ctrl_data_in->data.i2c_args.bytes; -            i2c_read( +            i2c_register_callback(i2c_read_done_callback); +            i2c_async_read(                  ctrl_data_in->data.i2c_args.addr, -                ctrl_data_out.data.i2c_args.data,                  num_bytes              ); +            i2c_src = src; +//            i2c_dst = dst;              ctrl_data_out.id = USRP2_CTRL_ID_HERES_THE_I2C_DATA_DUDE;              ctrl_data_out.data.i2c_args.bytes = num_bytes;          } @@ -251,11 +281,14 @@ void handle_udp_ctrl_packet(      case USRP2_CTRL_ID_WRITE_THESE_I2C_VALUES_BRO:{              uint8_t num_bytes = ctrl_data_in->data.i2c_args.bytes; -            i2c_write( +            i2c_register_callback(i2c_read_done_callback); +            i2c_async_write(                  ctrl_data_in->data.i2c_args.addr,                  ctrl_data_in->data.i2c_args.data,                  num_bytes              ); +            i2c_src = src; +//            i2c_dst = dst;              ctrl_data_out.id = USRP2_CTRL_ID_COOL_IM_DONE_I2C_WRITE_DUDE;              ctrl_data_out.data.i2c_args.bytes = num_bytes;          } @@ -287,6 +320,7 @@ void handle_udp_ctrl_packet(          }          ctrl_data_out.id = USRP2_CTRL_ID_OMG_POKED_REGISTER_SO_BAD_DUDE; +        send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out));          break;      case USRP2_CTRL_ID_PEEK_AT_THIS_REGISTER_FOR_ME_BRO: @@ -309,6 +343,7 @@ void handle_udp_ctrl_packet(          }          ctrl_data_out.id = USRP2_CTRL_ID_WOAH_I_DEFINITELY_PEEKED_IT_DUDE; +        send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out));          break;      case USRP2_CTRL_ID_SO_LIKE_CAN_YOU_READ_THIS_UART_BRO:{ @@ -335,9 +370,9 @@ void handle_udp_ctrl_packet(      default:          ctrl_data_out.id = USRP2_CTRL_ID_HUH_WHAT; - +        send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out));      } -    send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out)); +      }  /* @@ -503,6 +538,17 @@ main(void)      buffer_irq_handler(0); +    if(i2c_done) { +      i2c_done = false; +      send_udp_pkt(USRP2_UDP_CTRL_PORT, i2c_src, &ctrl_data_out, sizeof(ctrl_data_out)); +      //printf("Sending UDP packet from main loop for I2C...\n"); +    } + +    if(spi_done) { +      spi_done = false; +      send_udp_pkt(USRP2_UDP_CTRL_PORT, spi_src, &ctrl_data_out, sizeof(ctrl_data_out)); +    } +      int pending = pic_regs->pending;		// poll for under or overrun      if (pending & PIC_UNDERRUN_INT){ diff --git a/firmware/microblaze/lib/dbsm.c b/firmware/microblaze/lib/dbsm.c index d495860fd..cee343eaa 100644 --- a/firmware/microblaze/lib/dbsm.c +++ b/firmware/microblaze/lib/dbsm.c @@ -160,12 +160,12 @@ dbsm_process_status(dbsm_t *sm, uint32_t status)      putchar('E');      // Most likely an ethernet Rx error.  We just restart the transfer.      if (status & (BPS_ERROR(sm->buf0))) -      //dbsm_error_helper(sm, sm->buf0); -      dbsm_process_helper(sm, sm->buf0); //forward errors +      dbsm_error_helper(sm, sm->buf0); +      //dbsm_process_helper(sm, sm->buf0); //forward errors      if (status & (BPS_ERROR(sm->buf0 ^ 1))) -      //dbsm_error_helper(sm, sm->buf0 ^ 1); -      dbsm_process_helper(sm, sm->buf0 ^ 1); //forward errors +      dbsm_error_helper(sm, sm->buf0 ^ 1); +      //dbsm_process_helper(sm, sm->buf0 ^ 1); //forward errors    }    if (status & BPS_DONE(sm->buf0)) diff --git a/firmware/microblaze/lib/i2c.c b/firmware/microblaze/lib/i2c.c index 3f738733b..177341267 100644 --- a/firmware/microblaze/lib/i2c.c +++ b/firmware/microblaze/lib/i2c.c @@ -19,12 +19,15 @@  #include "i2c.h"  #include "memory_map.h"  #include "stdint.h" +#include <string.h> +#include "pic.h" +#include "nonstdio.h"  #define MAX_WB_DIV 4	// maximum wishbone divisor (from 100 MHz MASTER_CLK)  // prescaler divisor values for 100 kHz I2C [uses 5 * SCLK internally] -#define PRESCALER(wb_div) (((MASTER_CLK_RATE/(wb_div)) / (5 * 100000)) - 1) +#define PRESCALER(wb_div) (((MASTER_CLK_RATE/(wb_div)) / (5 * 400000)) - 1)  static uint16_t prescaler_values[MAX_WB_DIV+1] = {    0xffff,	// 0: can't happen @@ -34,6 +37,18 @@ static uint16_t prescaler_values[MAX_WB_DIV+1] = {    PRESCALER(4), // 4:  25 MHz  }; +//asynchronous (interrupt-driven) i2c state variables +volatile uint8_t i2c_buf[17]; //tx/rx data transfer buffer +volatile uint8_t *volatile i2c_bufptr = i2c_buf; //ptr to current position +volatile uint8_t i2c_len = 0; //length remaining in current transfer +volatile i2c_state_t i2c_state = I2C_STATE_IDLE; //current I2C transfer state +i2c_dir_t i2c_dir; //I2C transfer direction + +void  (*volatile i2c_callback)(void); //function pointer to i2c callback to be called when transaction is complete + +static void i2c_irq_handler(unsigned irq); +inline void i2c_async_err(void); +  void  i2c_init(void)  { @@ -47,9 +62,10 @@ i2c_init(void)    i2c_regs->prescaler_lo = prescaler_values[wb_div] & 0xff;    i2c_regs->prescaler_hi = (prescaler_values[wb_div] >> 8) & 0xff; -  i2c_regs->ctrl = I2C_CTRL_EN;	// enable core +  i2c_regs->ctrl = I2C_CTRL_EN; //| I2C_CTRL_IE;	// enable core -  // FIXME interrupt driven? +  // FIXME interrupt driven?   +  pic_register_handler(IRQ_I2C, i2c_irq_handler);  }  static inline void @@ -107,7 +123,7 @@ i2c_write(unsigned char i2c_addr, const unsigned char *buf, unsigned int len)    i2c_regs->data = (i2c_addr << 1) | 0;	 // 7 bit address and write bit (0)    // generate START and write addr (and maybe STOP) -  i2c_regs->cmd_status = I2C_CMD_WR | I2C_CMD_START | (len == 0 ? I2C_CMD_STOP : 0);   +  i2c_regs->cmd_status = I2C_CMD_WR | I2C_CMD_START | (len == 0 ? I2C_CMD_STOP : 0);    if (!wait_chk_ack())      goto fail; @@ -124,4 +140,163 @@ i2c_write(unsigned char i2c_addr, const unsigned char *buf, unsigned int len)    return false;  } -   +static void i2c_irq_handler(unsigned irq) { +//i2c state machine. + +  //printf("I2C irq handler\n"); +  //first let's make sure nothing is f'ed up +  //TODO: uncomment this error checking when we have some way to handle errors +//  if(((i2c_regs->cmd_status & I2C_ST_RXACK) != 0) && i2c_dir == I2C_DIR_WRITE) { //we got a NACK and we didn't send it +//    printf("\tNACK received\n"); +//    i2c_async_err(); +//    return; +//  }// else printf("\tACK received, proceeding\n"); + +  if(i2c_regs->cmd_status & I2C_ST_AL) {  +    printf("\tArbitration lost!\n"); +    i2c_async_err(); +    return; +  } + +  if(i2c_regs->cmd_status & I2C_ST_TIP) { +    //printf("\tI2C still busy in interrupt\n"); +    return; +  } + +  //now decide what to do +  switch(i2c_state) { + +  case I2C_STATE_IDLE: +    //this is an error. in idle state, we shouldn't be transferring data, and the fact that the IRQ fired is terrible bad. +    printf("AAAAAHHHHH INTERRUPT IN THE IDLE STATE AAAHHHHHHHHH\n"); +    i2c_async_err(); +    break; + +  case I2C_STATE_CONTROL_BYTE_SENT: //here we've sent the control byte, and we're either clocking data in or out now, but we haven't received a byte yet. +  case I2C_STATE_DATA:      //here we're sending/receiving data and if we're receiving there's data in the data reg + +    //if(i2c_state == I2C_STATE_DATA) printf("\tI2C in state DATA with dir=%d and len=%d\n", i2c_dir, i2c_len); +    //else printf("\tI2C in state CONTROL_BYTE_SENT with dir=%d and len=%d\n", i2c_dir, i2c_len); + +    if(i2c_dir == I2C_DIR_READ) { +      if(i2c_state == I2C_STATE_DATA) *(i2c_bufptr++) = i2c_regs->data; +      //printf("\tRead %x\n", *(i2c_bufptr-1)); +      //set up another data byte +      if(i2c_len > 1) //only one more byte to transfer +        i2c_regs->cmd_status = I2C_CMD_RD; +      else +        i2c_regs->cmd_status = I2C_CMD_RD | I2C_CMD_NACK | I2C_CMD_STOP; +    } +    else if(i2c_dir == I2C_DIR_WRITE) { +      //write a byte +      //printf("\tWriting %x\n", *i2c_bufptr); +      i2c_regs->data = *(i2c_bufptr++); +      if(i2c_len > 1) +        i2c_regs->cmd_status = I2C_CMD_WR; +      else { +        //printf("\tGenerating STOP\n"); +        i2c_regs->cmd_status = I2C_CMD_WR | I2C_CMD_STOP; +      } +    }; +    i2c_len--; +    if(i2c_len == 0) i2c_state = I2C_STATE_LAST_BYTE; +    else i2c_state = I2C_STATE_DATA; //takes care of the addr_sent->data transition +    break; + + +  case I2C_STATE_LAST_BYTE: //here we've already sent the last read request and the last data is waiting for us. +    //printf("\tI2C in state LAST BYTE\n"); + +    if(i2c_dir == I2C_DIR_READ) { +      *(i2c_bufptr++) = i2c_regs->data; +      //printf("\tRead %x\n", *(i2c_bufptr-1)); +      i2c_state = I2C_STATE_DATA_READY; +    } else { +      i2c_state = I2C_STATE_IDLE; +    } +    i2c_regs->ctrl &= ~I2C_CTRL_IE; //disable interrupts until next time + +    if(i2c_callback) { +      i2c_callback(); //if we registered a callback, call it! +    } + +    break; + + +  default: //terrible things have happened. +    break; +  } + +} + +void i2c_register_callback(void (*volatile callback)(void)) { +  i2c_callback = callback; +} + +inline void i2c_async_err(void) { +  i2c_state = I2C_STATE_IDLE; +  i2c_regs->ctrl &= ~I2C_CTRL_IE; +  printf("I2C error\n"); +//TODO: set an error flag instead of just dropping things on the floor +  i2c_regs->cmd_status = I2C_CMD_STOP; +} + +bool i2c_async_read(uint8_t addr, unsigned int len) { +  //printf("Starting async read\n"); +  if(i2c_state != I2C_STATE_IDLE) return false; //sorry mario but your i2c is in another castle +  if(len == 0) return true; //just idiot-proofing +  if(len > sizeof(i2c_buf)) return false; + +  //disable I2C interrupts and clear pending interrupts on the I2C device +  i2c_regs->ctrl &= ~I2C_CTRL_IE; +  i2c_regs->cmd_status |= I2C_CMD_IACK; + +  i2c_len = len; +  i2c_dir = I2C_DIR_READ; +  i2c_bufptr = i2c_buf; +  //then set up the transfer by issuing the control byte +  i2c_regs->ctrl |= I2C_CTRL_IE; +  i2c_regs->data = (addr << 1) | 0x01; //7 bit addr and read bit +  i2c_regs->cmd_status = I2C_CMD_WR | I2C_CMD_START; //generate start & start writing addr +  //update the state so the irq handler knows what's going on +  i2c_state = I2C_STATE_CONTROL_BYTE_SENT; +  return true; +} + +bool i2c_async_write(uint8_t addr, const uint8_t *buf, unsigned int len) { +  //printf("Starting async write\n"); +  if(i2c_state != I2C_STATE_IDLE) return false; //sorry mario but your i2c is in another castle +  if(len > sizeof(i2c_buf)) return false; + +  //disable I2C interrupts and clear pending interrupts on the I2C device +  i2c_regs->ctrl &= ~I2C_CTRL_IE; +  i2c_regs->cmd_status |= I2C_CMD_IACK; + +  //copy the buffer into our own if writing +  memcpy((void *)i2c_buf, buf, len); + +  i2c_len = len; +  i2c_dir = I2C_DIR_WRITE; +  i2c_bufptr = i2c_buf; +  //then set up the transfer by issuing the control byte +  i2c_regs->ctrl |= I2C_CTRL_IE; +  i2c_regs->data = (addr << 1) | 0x00; //7 bit addr and read bit +  i2c_regs->cmd_status = I2C_CMD_WR | I2C_CMD_START; //generate start & start writing addr +  //update the state so the irq handler knows what's going on +  i2c_state = I2C_STATE_CONTROL_BYTE_SENT; + +  return true; +} + +//TODO: determine if it's better to read sequentially into the user's buffer, copy on transfer complete, or copy on request (shown below). probably best to copy on request. +bool i2c_async_data_ready(void *buf) { +  if(i2c_state == I2C_STATE_DATA_READY) { +    i2c_state = I2C_STATE_IDLE; +    memcpy(buf, (void *)i2c_buf, (i2c_bufptr - i2c_buf)); //TODO: not really comfortable with this +    //printf("Copying %d bytes to user buffer\n", i2c_bufptr-i2c_buf); +    return true; +  } +  return false; +} + + diff --git a/firmware/microblaze/lib/i2c.h b/firmware/microblaze/lib/i2c.h index ecb6aa0d2..77129e922 100644 --- a/firmware/microblaze/lib/i2c.h +++ b/firmware/microblaze/lib/i2c.h @@ -20,20 +20,38 @@  #define INCLUDED_I2C_H  #include <stdbool.h> +#include "stdint.h" + +typedef enum { I2C_STATE_IDLE,  +               I2C_STATE_CONTROL_BYTE_SENT,  +               I2C_STATE_DATA,  +               I2C_STATE_LAST_BYTE,  +               I2C_STATE_DATA_READY,  +               I2C_STATE_ERROR  +             } i2c_state_t; + +typedef enum { I2C_DIR_WRITE=0, I2C_DIR_READ=1 } i2c_dir_t;  void i2c_init(void);  bool i2c_read (unsigned char i2c_addr, unsigned char *buf, unsigned int len);  bool i2c_write(unsigned char i2c_addr, const unsigned char *buf, unsigned int len); +bool i2c_async_read(uint8_t addr, unsigned int len); +bool i2c_async_write(uint8_t addr, const uint8_t *buf, unsigned int len); +bool i2c_async_data_ready(void *); +//static void i2c_irq_handler(unsigned irq); +void i2c_register_callback(void (*callback)(void));  // Write 24LC024 / 24LC025 EEPROM on motherboard or daughterboard.  // Which EEPROM is determined by i2c_addr.  See i2c_addr.h  bool eeprom_write (int i2c_addr, int eeprom_offset, const void *buf, int len); +bool eeprom_write_async (int i2c_addr, int eeprom_offset, const void *buf, int len, void (*callback)(void));  // Read 24LC024 / 24LC025 EEPROM on motherboard or daughterboard.  // Which EEPROM is determined by i2c_addr.  See i2c_addr.h  bool eeprom_read (int i2c_addr, int eeprom_offset, void *buf, int len); +bool eeprom_read_async(int i2c_addr, int eeprom_offset, void *buf, int len, void (*callback)(void));  #endif /* INCLUDED_I2C_H */ diff --git a/firmware/microblaze/lib/spi.c b/firmware/microblaze/lib/spi.c index bef808e57..2a41a1bfa 100644 --- a/firmware/microblaze/lib/spi.c +++ b/firmware/microblaze/lib/spi.c @@ -17,6 +17,12 @@  #include "spi.h"  #include "memory_map.h" +#include "pic.h" +#include "nonstdio.h" + +void (*volatile spi_callback)(void); //SPI callback when xfer complete. + +static void spi_irq_handler(unsigned irq);  void  spi_init(void)  @@ -59,3 +65,44 @@ spi_transact(bool readback, int slave, uint32_t data, int length, uint32_t flags    else      return 0;  } + +void spi_register_callback(void (*volatile callback)(void)) { +  spi_callback = callback; +} + +static void spi_irq_handler(unsigned irq) { +//  printf("SPI IRQ handler\n"); +//  uint32_t wat = spi_regs->ctrl; //read a register just to clear the interrupt +  //spi_regs->ctrl &= ~SPI_CTRL_IE; +  if(spi_callback) spi_callback(); //we could just use the PIC to register the user's callback, but this provides the ability to do other things later +} + +uint32_t spi_get_data(void) { +  return spi_regs->txrx0; +} + +bool  +spi_async_transact(int slave, uint32_t data, int length, uint32_t flags, void (*volatile callback)(void)) { +  flags &= (SPI_CTRL_TXNEG | SPI_CTRL_RXNEG); +  int ctrl = SPI_CTRL_ASS | SPI_CTRL_IE | (SPI_CTRL_CHAR_LEN_MASK & length) | flags; + +  if(spi_regs->ctrl & SPI_CTRL_GO_BSY) { +    printf("Async SPI busy!\n"); +    return false; //we don't wait on busy, we just return failure. we count on the host to not set up another transaction before the last one finishes. +  } + +  // Tell it which SPI slave device to access +  spi_regs->ss = slave & 0xffff; + +  // Data we will send +  spi_regs->txrx0 = data; + +  spi_register_callback(callback); +  pic_register_handler(IRQ_SPI, spi_irq_handler); + +  // Run it -- write once and rewrite with GO set +  spi_regs->ctrl = ctrl; +  spi_regs->ctrl = ctrl | SPI_CTRL_GO_BSY; + +  return true; +} diff --git a/firmware/microblaze/lib/spi.h b/firmware/microblaze/lib/spi.h index 01e4d26fd..54618cedd 100644 --- a/firmware/microblaze/lib/spi.h +++ b/firmware/microblaze/lib/spi.h @@ -48,6 +48,13 @@ void spi_wait(void);  uint32_t  spi_transact(bool readback, int slave, uint32_t data, int length, uint32_t flags); +uint32_t spi_get_data(void); +//static void spi_irq_handler(unsigned irq); +void spi_register_callback(void (*volatile callback)(void)); + +bool  +spi_async_transact(int slave, uint32_t data, int length, uint32_t flags, void (*volatile callback)(void)); +  // ----------------------------------------------------------------  // Routines that manipulate the FLASH SPI BUS  // ---------------------------------------------------------------- diff --git a/firmware/microblaze/lib/u2_init.c b/firmware/microblaze/lib/u2_init.c index 75bc40859..8d666b76b 100644 --- a/firmware/microblaze/lib/u2_init.c +++ b/firmware/microblaze/lib/u2_init.c @@ -45,22 +45,26 @@ get_hw_rev(void)  bool  u2_init(void)  { +  hal_disable_ints();    hal_io_init();    // init spi, so that we can switch over to the high-speed clock    spi_init(); -  // init i2c so we can read our rev -  i2c_init(); -  get_hw_rev(); -    // set up the default clocks    clocks_init(); +  hal_uart_init(); + +  // init i2c so we can read our rev    pic_init();	// progammable interrupt controller +  i2c_init(); +  hal_enable_ints(); +  get_hw_rev(); +    bp_init();	// buffer pool -  hal_enable_ints(); +    // flash all leds to let us know board is alive    hal_set_leds(0x0, 0x1f); diff --git a/fpga/usrp2/vrt/vita_rx_framer.v b/fpga/usrp2/vrt/vita_rx_framer.v index fd82263d0..235817941 100644 --- a/fpga/usrp2/vrt/vita_rx_framer.v +++ b/fpga/usrp2/vrt/vita_rx_framer.v @@ -128,7 +128,7 @@ module vita_rx_framer         VITA_ERR_SECS : pkt_fifo_line <= {2'b00,vita_time_fifo_o[63:32]};         VITA_ERR_TICS : pkt_fifo_line <= {2'b00,32'd0};         VITA_ERR_TICS2 : pkt_fifo_line <= {2'b00,vita_time_fifo_o[31:0]}; -       VITA_ERR_PAYLOAD : pkt_fifo_line <= {2'b11,28'd0,flags_fifo_o}; +       VITA_ERR_PAYLOAD : pkt_fifo_line <= {2'b10,28'd0,flags_fifo_o};         //VITA_ERR_TRAILER : pkt_fifo_line <= {2'b11,vita_trailer};         default : pkt_fifo_line <= 34'h0_FFFF_FFFF; diff --git a/host/config/Version.cmake b/host/config/Version.cmake index a592a4565..9e4b6b306 100644 --- a/host/config/Version.cmake +++ b/host/config/Version.cmake @@ -42,7 +42,7 @@ ELSE(${GIT} STREQUAL "GIT-NOTFOUND")      #extract the timestamp from the git log entry      EXECUTE_PROCESS(          WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} -        COMMAND ${PYTHON_EXECUTABLE} -c "import re; print re.match('^.*Date:\\s*(\\d*).*$', '''${_git_log}''', re.MULTILINE | re.DOTALL).groups()[0]" +        COMMAND ${PYTHON_EXECUTABLE} -c "import re; print re.match('^.*Date:\\s*(\\d*).*$', ''' ${_git_log} ''', re.MULTILINE | re.DOTALL).groups()[0]"          OUTPUT_VARIABLE _git_timestamp OUTPUT_STRIP_TRAILING_WHITESPACE      ) diff --git a/host/docs/CMakeLists.txt b/host/docs/CMakeLists.txt index d0041f71c..b4383f88d 100644 --- a/host/docs/CMakeLists.txt +++ b/host/docs/CMakeLists.txt @@ -24,6 +24,7 @@ SET(manual_sources      coding.rst      dboards.rst      general.rst +    images.rst      usrp2.rst  ) diff --git a/host/docs/images.rst b/host/docs/images.rst new file mode 100644 index 000000000..ff5c5404e --- /dev/null +++ b/host/docs/images.rst @@ -0,0 +1,104 @@ +======================================================================== +UHD - Firmware and FPGA Image Application Notes +======================================================================== + +.. contents:: Table of Contents + +------------------------------------------------------------------------ +Images Overview +------------------------------------------------------------------------ +Every USRP device must be loaded with special firmware and FPGA images. +The methods of loading images into the device varies among devices: + +* **USRP1:** The host code will automatically load the firmware and FPGA at runtime. +* **USRP2:** The user must manually write the images onto the USRP2 SD card. + +------------------------------------------------------------------------ +Pre-built images +------------------------------------------------------------------------ + +Pre-built images are available for download. +See the UHD wiki for the download link. + +The pre-built images come in platform-specific installer packages +and platform-independent archive files: + +* **Linux:** DEB or RPM installer +* **Windows:** not available yet... +* **Macintosh:** not available yet... +* **Platform-independent:** ZIP or TAR.GZ archive + +^^^^^^^^^^^^^^^^^^ +Linux installers +^^^^^^^^^^^^^^^^^^ +The Linux-based installers will install the images into /usr/share/uhd/images. +On a Linux system, the UHD will always search this path for image files. + +Commands to install a linux rpm or deb package: + +:: + +    sudo rpm -i <linux-images-installer>.rpm + +    -- OR -- + +    sudo dpkg -i <linux-images-installer>.deb + +^^^^^^^^^^^^^^^^^^^^^^ +Archive install +^^^^^^^^^^^^^^^^^^^^^^ +When installing images from an archive, there are two options: + +**Option 1:** + +Unpack the archive into the UHD installation prefix. +The UHD will always search <prefix>/share/uhd/images for image files. +Where <prefix> was set by the CMAKE_INSTALL_PREFIX at configure-time. + +**Option 2:** + +Unpack the archive anywhere and set the UHD_IMAGE_PATH environment variable. +The UHD_IMAGE_PATH may contain a list of directories to search for image files, +or paths to specific image files. + +------------------------------------------------------------------------ +Building images +------------------------------------------------------------------------ + +The UHD source repository comes with the source code necessary to build +both firmware and FPGA images for all supported devices. +The build commands for a particular image can be found in <uhd-repo-path>/images/Makefile. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Xilinx FPGA builds +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Xilinx ISE 12.x and up is required to build the Xilinx FPGA images. +The build requires that you have a unix-like environment with make. +Make sure that xtclsh from the Xilinx ISE bin directory is in your $PATH. + +See <uhd-repo-path>/fpga/usrp2/top/* + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Microblaze firmware builds +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The Microblaze GCC compiler from the Xilinx EDK is required to build the Microblaze firmware images. +The build requires that you have a unix-like environment with autotools and make. +Make sure that mb-gcc from the Xilinx EDK/microblaze directory is in your $PATH. + +See <uhd-repo-path>/firmware/microblaze + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Altera FPGA builds +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Quartus is required to build the Altera FPGA images. +Pre-built images can also be found in <uhd-repo-path>/fpga/usrp1/rbf + +See <uhd-repo-path>/fpga/usrp1/toplevel/* + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +FX2 firmware builds +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The sdcc compiler is required to build the FX2 firmware images. +The build requires that you have a unix-like environment with autotools and make. + +See <uhd-repo-path>/firmware/fx2 diff --git a/host/docs/index.rst b/host/docs/index.rst index b31a3d0ac..6973ede19 100644 --- a/host/docs/index.rst +++ b/host/docs/index.rst @@ -21,6 +21,7 @@ Building the UHD  Application Notes  ^^^^^^^^^^^^^^^^^^^^^  * `General App Notes <./general.html>`_ +* `Firmware and FPGA Image Notes <./images.html>`_  * `USRP2 App Notes <./usrp2.html>`_  * `Daughterboard App Notes <./dboards.html>`_ diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst index bc4ea0e44..3ac326f58 100644 --- a/host/docs/usrp2.rst +++ b/host/docs/usrp2.rst @@ -5,42 +5,6 @@ UHD - USRP2 Application Notes  .. contents:: Table of Contents  ------------------------------------------------------------------------ -Building firmware and FPGA images ------------------------------------------------------------------------- - -^^^^^^^^^^^^^^^^^^ -FPGA Image -^^^^^^^^^^^^^^^^^^ -Xilinx ISE 10.1 and up is required to build the FPGA image for the USRP2. -The build requires that you have a unix-like environment with make. -Make sure that xtclsh from the Xilinx ISE bin directory is in your $PATH. - -Run the following commands: -:: - -    cd <uhd-repo-path>/fpga/usrp2/top/u2_rev3 -    make -f Makefile.udp bin - -*The image file will be ./build/u2_rev3.bin* - -^^^^^^^^^^^^^^^^^^ -Firmware Image -^^^^^^^^^^^^^^^^^^ -The Microblaze GCC compiler from the Xilinx EDK is required to build the firmware. -The build requires that you have a unix-like environment with autotools and make. -Make sure that mb-gcc from the Xilinx EDK/microblaze directory is in your $PATH. - -Run the following commands: -:: - -    cd <uhd-repo-path>/firmware/microblaze -    ./boostrap -    ./configure --host=mb -    make - -*The image file will be ./usrp2/usrp2_txrx_uhd.bin* - -------------------------------------------------------------------------  Load the images onto the SD card  ------------------------------------------------------------------------  **Warning!** diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt index 76ee24e5f..130956f8a 100644 --- a/host/include/uhd/usrp/CMakeLists.txt +++ b/host/include/uhd/usrp/CMakeLists.txt @@ -33,6 +33,8 @@ INSTALL(FILES      dboard_manager.hpp      ### utilities ### +    dsp_utils.hpp +    misc_utils.hpp      subdev_spec.hpp      tune_helper.hpp diff --git a/host/include/uhd/usrp/dboard_iface.hpp b/host/include/uhd/usrp/dboard_iface.hpp index fc7ea3052..e776ecc42 100644 --- a/host/include/uhd/usrp/dboard_iface.hpp +++ b/host/include/uhd/usrp/dboard_iface.hpp @@ -65,11 +65,34 @@ public:          AUX_ADC_B = 'b'      }; +    //! Special properties that differentiate this daughterboard slot +    struct special_props_t{ +        /*! +         * Soft clock divider: +         * When a motherboard cannot provided a divided dboard clock, +         * it may provided a "soft" divided clock over an FPGA GPIO. +         * The implementation must know the type of clock provided. +         */ +        bool soft_clock_divider; + +        /*! +         * Mangle i2c addresses: +         * When i2c is shared across multiple daugterboard slots, +         * the i2c addresses will be mangled on the secondary slot +         * to avoid conflicts between slots in the i2c address space. +         * The mangling is daguhterboard specific so the implementation +         * needs to know whether it should use mangled addresses or not. +         */ +        bool mangle_i2c_addrs; +    }; +      /*! -     * Get the motherboard name of the form: usrp1, usrp2... -     * \return string representing the motherboard name +     * Get special properties information for this dboard slot. +     * This call helps the dboard code to handle implementation +     * differences between different motherboards and dboard slots. +     * \return the special properties struct       */ -    virtual std::string get_mboard_name(void) = 0; +    virtual special_props_t get_special_props(void) = 0;      /*!       * Write to an aux dac. diff --git a/host/include/uhd/usrp/dboard_manager.hpp b/host/include/uhd/usrp/dboard_manager.hpp index e5831d4cf..c68f069f0 100644 --- a/host/include/uhd/usrp/dboard_manager.hpp +++ b/host/include/uhd/usrp/dboard_manager.hpp @@ -51,7 +51,7 @@ public:          const dboard_id_t &dboard_id,          dboard_ctor_t dboard_ctor,          const std::string &name, -        const prop_names_t &subdev_names = prop_names_t(1, "") +        const prop_names_t &subdev_names = prop_names_t(1, "0")      );      /*! diff --git a/host/include/uhd/usrp/dsp_utils.hpp b/host/include/uhd/usrp/dsp_utils.hpp new file mode 100644 index 000000000..8ec04dd2f --- /dev/null +++ b/host/include/uhd/usrp/dsp_utils.hpp @@ -0,0 +1,99 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_DSP_UTILS_HPP +#define INCLUDED_UHD_USRP_DSP_UTILS_HPP + +#include <uhd/config.hpp> +#include <uhd/types/stream_cmd.hpp> +#include <uhd/usrp/subdev_props.hpp> +#include <boost/cstdint.hpp> + +namespace uhd{ namespace usrp{ + +namespace dsp_type1{ + +    /*! +     * Calculate the rx mux word from properties. +     * \param subdev_conn the subdev connection type +     * \return the 32-bit rx mux control word +     */ +    UHD_API boost::uint32_t calc_rx_mux_word(subdev_conn_t subdev_conn); + +    /*! +     * Calculate the tx mux word from properties. +     * \param subdev_conn the subdev connection type +     * \return the 32-bit tx mux control word +     */ +    UHD_API boost::uint32_t calc_tx_mux_word(subdev_conn_t subdev_conn); + +    /*! +     * Calculate the cordic word from the frequency and clock rate. +     * The frequency will be set to the actual (possible) frequency. +     * +     * \param freq the requested frequency in Hz +     * \param codec_rate the dsp codec rate in Hz +     * \return the 32-bit cordic control word +     */ +    UHD_API boost::uint32_t calc_cordic_word_and_update( +        double &freq, double codec_rate +    ); + +    /*! +     * Calculate the CIC filter word from the rate. +     * Check if requested decim/interp rate is: +     *      multiple of 4, enable two halfband filters +     *      multiple of 2, enable one halfband filter +     *      handle remainder in CIC +     * +     * \param rate the requested rate in Sps +     * \return the 32-bit cic filter control word +     */ +    UHD_API boost::uint32_t calc_cic_filter_word(unsigned rate); + +    /*! +     * Calculate the IQ scale factor word from I and Q components. +     * \param i the I component of the scalar +     * \param q the Q component of the scalar +     * \return the 32-bit scale factor control word +     */ +    UHD_API boost::uint32_t calc_iq_scale_word( +        boost::int16_t i, boost::int16_t q +    ); + +    /*! +     * Calculate the IQ scale factor word from the rate. +     * \param rate the requested rate in Sps +     * \return the 32-bit scale factor control word +     */ +    UHD_API boost::uint32_t calc_iq_scale_word(unsigned rate); + +    /*! +     * Calculate the stream command word from the stream command struct. +     * \param stream_cmd the requested stream command with mode, flags, timestamp +     * \param num_samps_continuous number of samples to request in continuous mode +     * \return the 32-bit stream command word +     */ +    UHD_API boost::uint32_t calc_stream_cmd_word( +        const stream_cmd_t &stream_cmd, size_t num_samps_continuous +    ); + +} //namespace dsp_type1 + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_DSP_UTILS_HPP */ diff --git a/host/include/uhd/usrp/misc_utils.hpp b/host/include/uhd/usrp/misc_utils.hpp new file mode 100644 index 000000000..2af9f5b40 --- /dev/null +++ b/host/include/uhd/usrp/misc_utils.hpp @@ -0,0 +1,68 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_MISC_UTILS_HPP +#define INCLUDED_UHD_USRP_MISC_UTILS_HPP + +#include <uhd/config.hpp> +#include <uhd/wax.hpp> +#include <uhd/usrp/subdev_spec.hpp> +#include <uhd/utils/gain_group.hpp> + +namespace uhd{ namespace usrp{ + +    /*! +     * Different policies for gain group prioritization. +     */ +    enum gain_group_policy_t{ +        GAIN_GROUP_POLICY_RX = 'R', +        GAIN_GROUP_POLICY_TX = 'T' +    }; + +    /*! +     * Create a gain group that represents the subdevice and its codec. +     * \param subdev the object with subdevice properties +     * \param codec the object with codec properties +     * \param gain_group_policy the policy to use +     */ +    UHD_API gain_group::sptr make_gain_group( +        wax::obj subdev, wax::obj codec, +        gain_group_policy_t gain_group_policy +    ); + +    /*! +     * Verify the rx subdevice specification. +     * If the subdev spec if empty, automatically fill it. +     * \param subdev_spec the subdev spec to verify/fill +     * \param mboard the motherboard properties object +     * \throw exception when the subdev spec is invalid +     */ +    UHD_API void verify_rx_subdev_spec(subdev_spec_t &subdev_spec, wax::obj mboard); + +    /*! +     * Verify the tx subdevice specification. +     * If the subdev spec if empty, automatically fill it. +     * \param subdev_spec the subdev spec to verify/fill +     * \param mboard the motherboard properties object +     * \throw exception when the subdev spec is invalid +     */ +    UHD_API void verify_tx_subdev_spec(subdev_spec_t &subdev_spec, wax::obj mboard); + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_MISC_UTILS_HPP */ + diff --git a/host/include/uhd/utils/algorithm.hpp b/host/include/uhd/utils/algorithm.hpp index 1b5eacfa9..53c571e4e 100644 --- a/host/include/uhd/utils/algorithm.hpp +++ b/host/include/uhd/utils/algorithm.hpp @@ -22,6 +22,9 @@  #include <boost/range/begin.hpp>  #include <boost/range/end.hpp>  #include <boost/range/size.hpp> +#include <boost/algorithm/string.hpp> +#include <vector> +#include <string>  /*! \file algorithm.hpp   * Useful templated functions and classes that I like to pretend are part of stl. @@ -30,6 +33,24 @@  namespace std{      /*! +     * Split a string at the separation characters. +     * \param string the string to split +     * \param sep the separator characters +     * \return a range of strings +     */ +    inline std::vector<std::string> split_string( +        const std::string &string, const std::string &sep = "\t " +    ){ +        std::vector<std::string> strings; +        if (not string.empty()) boost::split( +            // do not split an empty string: +            // let me tell you about the time when boost::split segfaulted... +            strings, string, boost::is_any_of(sep) +        ); +        return strings; +    } + +    /*!       * A wrapper around std::copy that takes ranges instead of iterators.       *       * Copy the elements of the source range into the destination range. diff --git a/host/include/uhd/utils/props.hpp b/host/include/uhd/utils/props.hpp index f376d2612..fbca03019 100644 --- a/host/include/uhd/utils/props.hpp +++ b/host/include/uhd/utils/props.hpp @@ -21,7 +21,6 @@  #include <uhd/config.hpp>  #include <uhd/wax.hpp>  #include <uhd/utils/exception.hpp> -#include <boost/tuple/tuple.hpp>  #include <stdexcept>  #include <vector>  #include <string> @@ -36,8 +35,25 @@ namespace uhd{       * Allows properties to be sub-sectioned by name.       */      struct UHD_API named_prop_t{ -        wax::obj key; -        std::string name; +        const wax::obj key; +        const std::string name; + +        //! Convert the key to the specified type +        template<typename T> inline T as(void){ +            return key.as<T>(); +        } + +        /*! +         * Utility function to convert generic key into a named prop. +         * If the key was already a named prop, the prop will be split. +         * Otherwise, the key will be the key, and the name will be used. +         * \param key a reference to the prop object +         * \param name a reference to the name object +         * \return a named property struct with key and name +         */ +        static named_prop_t extract( +            const wax::obj &key, const std::string &name = "" +        );          /*!           * Create a new named prop from key and name. @@ -48,17 +64,6 @@ namespace uhd{      };      /*! -     * Utility function to separate a named property into its components. -     * \param key a reference to the prop object -     * \param name a reference to the name object -     * \return a tuple that can be used with boost::tie -     */ -    UHD_API boost::tuple<wax::obj, std::string> extract_named_prop( -        const wax::obj &key, -        const std::string &name = "" -    ); - -    /*!       * Throw when getting a not-implemented or write-only property.       * Throw-site information will be included with this error.       */ diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 48cfe742e..81845de21 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -53,6 +53,17 @@ INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/utils/CMakeLists.txt)  ########################################################################  # Append to the list of sources for lib uhd  ######################################################################## +FILE(TO_NATIVE_PATH ${CMAKE_INSTALL_PREFIX}/${PKG_DATA_DIR} LOCAL_PKG_DATA_DIR) +STRING(REPLACE "\\" "\\\\" LOCAL_PKG_DATA_DIR ${LOCAL_PKG_DATA_DIR}) +MESSAGE(STATUS "Local package data directory: ${LOCAL_PKG_DATA_DIR}") + +IF(UNIX) +    #on unix systems, installers will use this directory for the package data +    FILE(TO_NATIVE_PATH /usr/${PKG_DATA_DIR} INSTALLER_PKG_DATA_DIR) +    STRING(REPLACE "\\" "\\\\" INSTALLER_PKG_DATA_DIR ${INSTALLER_PKG_DATA_DIR}) +    MESSAGE(STATUS "Installer package data directory: ${INSTALLER_PKG_DATA_DIR}") +ENDIF(UNIX) +  CONFIGURE_FILE(      ${CMAKE_CURRENT_SOURCE_DIR}/constants.hpp.in      ${CMAKE_CURRENT_BINARY_DIR}/constants.hpp diff --git a/host/lib/constants.hpp.in b/host/lib/constants.hpp.in index aa51e558c..4aedb6d4a 100644 --- a/host/lib/constants.hpp.in +++ b/host/lib/constants.hpp.in @@ -18,12 +18,9 @@  #ifndef INCLUDED_LIBUHD_CONSTANTS_HPP  #define INCLUDED_LIBUHD_CONSTANTS_HPP -#include <uhd/config.hpp> -#include <string> -  //these should be pre-processor macros to avoid static initialization issues  #define UHD_VERSION_STRING "@CPACK_PACKAGE_VERSION@" -#define UHD_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@" -#define UHD_PKG_DATA_DIR "@PKG_DATA_DIR@" +#define LOCAL_PKG_DATA_DIR "@LOCAL_PKG_DATA_DIR@" +#define INSTALLER_PKG_DATA_DIR "@INSTALLER_PKG_DATA_DIR@"  #endif /* INCLUDED_LIBUHD_CONSTANTS_HPP */ diff --git a/host/lib/types.cpp b/host/lib/types.cpp index 5c0fb1f42..f957cd83f 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -27,7 +27,6 @@  #include <uhd/types/otw_type.hpp>  #include <uhd/types/io_type.hpp>  #include <uhd/types/serial.hpp> -#include <boost/algorithm/string.hpp>  #include <boost/math/special_functions/round.hpp>  #include <boost/foreach.hpp>  #include <boost/format.hpp> @@ -181,15 +180,10 @@ static std::string trim(const std::string &in){  }  device_addr_t::device_addr_t(const std::string &args){ -    //split the args at the semi-colons -    std::vector<std::string> pairs; -    boost::split(pairs, args, boost::is_any_of(arg_delim)); -    BOOST_FOREACH(const std::string &pair, pairs){ +    BOOST_FOREACH(const std::string &pair, std::split_string(args, arg_delim)){          if (trim(pair) == "") continue; -        //split the key value pairs at the equals -        std::vector<std::string> key_val; -        boost::split(key_val, pair, boost::is_any_of(pair_delim)); +        std::vector<std::string> key_val = std::split_string(pair, pair_delim);          if (key_val.size() != 2) throw std::runtime_error("invalid args string: "+args);          (*this)[trim(key_val.front())] = trim(key_val.back());      } @@ -238,13 +232,12 @@ mac_addr_t mac_addr_t::from_string(const std::string &mac_addr_str){              throw std::runtime_error("expected exactly 5 or 17 characters");          //split the mac addr hex string at the colons -        std::vector<std::string> hex_strs; -        boost::split(hex_strs, mac_addr_str, boost::is_any_of(":")); -        for (size_t i = 0; i < hex_strs.size(); i++){ +        size_t i = 0; +        BOOST_FOREACH(const std::string &hex_str, std::split_string(mac_addr_str, ":")){              int hex_num; -            std::istringstream iss(hex_strs[i]); +            std::istringstream iss(hex_str);              iss >> std::hex >> hex_num; -            bytes[i] = boost::uint8_t(hex_num); +            bytes[i++] = boost::uint8_t(hex_num);          }      } diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt index d951ab412..2b408e479 100644 --- a/host/lib/usrp/CMakeLists.txt +++ b/host/lib/usrp/CMakeLists.txt @@ -22,10 +22,9 @@ LIBUHD_APPEND_SOURCES(      ${CMAKE_SOURCE_DIR}/lib/usrp/dboard_eeprom.cpp      ${CMAKE_SOURCE_DIR}/lib/usrp/dboard_id.cpp      ${CMAKE_SOURCE_DIR}/lib/usrp/dboard_manager.cpp -    ${CMAKE_SOURCE_DIR}/lib/usrp/dsp_utils.hpp +    ${CMAKE_SOURCE_DIR}/lib/usrp/dsp_utils.cpp      ${CMAKE_SOURCE_DIR}/lib/usrp/mimo_usrp.cpp      ${CMAKE_SOURCE_DIR}/lib/usrp/misc_utils.cpp -    ${CMAKE_SOURCE_DIR}/lib/usrp/misc_utils.hpp      ${CMAKE_SOURCE_DIR}/lib/usrp/simple_usrp.cpp      ${CMAKE_SOURCE_DIR}/lib/usrp/subdev_spec.cpp      ${CMAKE_SOURCE_DIR}/lib/usrp/tune_helper.cpp diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp index 9180828d8..f8236d598 100644 --- a/host/lib/usrp/dboard/db_basic_and_lf.cpp +++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp @@ -95,8 +95,7 @@ basic_rx::~basic_rx(void){  }  void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ @@ -161,8 +160,7 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){  }  void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ @@ -194,8 +192,7 @@ basic_tx::~basic_tx(void){  }  void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ @@ -252,8 +249,7 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){  }  void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index 03e6b6255..06cf91d3b 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -61,7 +61,7 @@ static const uhd::dict<std::string, gain_range_t> dbsrx_gain_ranges = map_list_o   **********************************************************************/  class dbsrx : public rx_dboard_base{  public: -    dbsrx(ctor_args_t args, boost::uint8_t max2118_addr); +    dbsrx(ctor_args_t args);      ~dbsrx(void);      void rx_get(const wax::obj &key, wax::obj &val); @@ -73,7 +73,9 @@ private:      uhd::dict<std::string, float> _gains;      max2118_write_regs_t _max2118_write_regs;      max2118_read_regs_t _max2118_read_regs; -    boost::uint8_t _max2118_addr; //0x67 or 0x65 depending on which side +    boost::uint8_t _max2118_addr(void){ +        return (this->get_iface()->get_special_props().mangle_i2c_addrs)? 0x65 : 0x67; +    };      void set_lo_freq(double target_freq);      void set_gain(float gain, const std::string &name); @@ -102,7 +104,7 @@ private:              //send the data              this->get_iface()->write_i2c( -                _max2118_addr, regs_vector +                _max2118_addr(), regs_vector              );          }      } @@ -120,7 +122,7 @@ private:              //read from i2c              regs_vector = this->get_iface()->read_i2c( -                _max2118_addr, num_bytes +                _max2118_addr(), num_bytes              );              for(boost::uint8_t i=0; i < num_bytes; i++){ @@ -156,10 +158,8 @@ private:  /***********************************************************************   * Register the DBSRX dboard   **********************************************************************/ -// FIXME 0x67 is the default i2c address on USRP2 -//       need to handle which side for USRP1 with different address  static dboard_base::sptr make_dbsrx(dboard_base::ctor_args_t args){ -    return dboard_base::sptr(new dbsrx(args, 0x67)); +    return dboard_base::sptr(new dbsrx(args));  }  //dbid for USRP2 version @@ -177,27 +177,27 @@ UHD_STATIC_BLOCK(reg_dbsrx_on_usrp1_dboard){  /***********************************************************************   * Structors   **********************************************************************/ -dbsrx::dbsrx(ctor_args_t args, boost::uint8_t max2118_addr) : rx_dboard_base(args){ +dbsrx::dbsrx(ctor_args_t args) : rx_dboard_base(args){      //warn user about incorrect DBID on USRP1, requires R193 populated -    if (this->get_iface()->get_mboard_name() == "usrp1" and this->get_rx_id() == 0x000D) +    if (this->get_iface()->get_special_props().soft_clock_divider and this->get_rx_id() == 0x000D)          uhd::print_warning(              str(boost::format(                  "DBSRX: incorrect dbid\n" -                "%s expects dbid 0x0002 and R193\n" +                "Expected dbid 0x0002 and R193\n"                  "found dbid == %d\n"                  "Please see the daughterboard app notes"  -                ) % (this->get_iface()->get_mboard_name()) % (this->get_rx_id().to_pp_string())) +                ) % this->get_rx_id().to_pp_string())          );      //warn user about incorrect DBID on non-USRP1, requires R194 populated -    if (this->get_iface()->get_mboard_name() != "usrp1" and this->get_rx_id() == 0x0002) +    if (not this->get_iface()->get_special_props().soft_clock_divider and this->get_rx_id() == 0x0002)          uhd::print_warning(              str(boost::format(                  "DBSRX: incorrect dbid\n" -                "%s expects dbid 0x000D and R194\n" +                "Expected dbid 0x000D and R194\n"                  "found dbid == %d\n"                  "Please see the daughterboard app notes"  -                ) % (this->get_iface()->get_mboard_name()) % (this->get_rx_id().to_pp_string())) +                ) % this->get_rx_id().to_pp_string())          );      //enable only the clocks we need @@ -207,9 +207,6 @@ dbsrx::dbsrx(ctor_args_t args, boost::uint8_t max2118_addr) : rx_dboard_base(arg      this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, 0x0); // All unused in atr      this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x0); // All Inputs -    //set the i2c address for the max2118 -    _max2118_addr = max2118_addr; -      //send initial register settings      this->send_reg(0x0, 0x5); @@ -503,8 +500,7 @@ void dbsrx::set_bandwidth(float bandwidth){   * RX Get and Set   **********************************************************************/  void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ @@ -517,13 +513,13 @@ void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){          return;      case SUBDEV_PROP_GAIN: -        assert_has(_gains.keys(), name, "dbsrx gain name"); -        val = _gains[name]; +        assert_has(_gains.keys(), key.name, "dbsrx gain name"); +        val = _gains[key.name];          return;      case SUBDEV_PROP_GAIN_RANGE: -        assert_has(dbsrx_gain_ranges.keys(), name, "dbsrx gain name"); -        val = dbsrx_gain_ranges[name]; +        assert_has(dbsrx_gain_ranges.keys(), key.name, "dbsrx gain name"); +        val = dbsrx_gain_ranges[key.name];          return;      case SUBDEV_PROP_GAIN_NAMES: @@ -546,19 +542,6 @@ void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){          val = dbsrx_antennas;          return; -/* -    case SUBDEV_PROP_QUADRATURE: -        val = true; -        return; - -    case SUBDEV_PROP_IQ_SWAPPED: -        val = false; -        return; - -    case SUBDEV_PROP_SPECTRUM_INVERTED: -        val = false; -        return; -*/      case SUBDEV_PROP_CONNECTION:          val = SUBDEV_CONN_COMPLEX_IQ;          return; @@ -586,8 +569,7 @@ void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){  }  void dbsrx::rx_set(const wax::obj &key_, const wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ @@ -597,7 +579,7 @@ void dbsrx::rx_set(const wax::obj &key_, const wax::obj &val){          return;      case SUBDEV_PROP_GAIN: -        this->set_gain(val.as<float>(), name); +        this->set_gain(val.as<float>(), key.name);          return;      case SUBDEV_PROP_BANDWIDTH: diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index b6b44199a..c3ab96e59 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -398,8 +398,7 @@ double rfx_xcvr::set_lo_freq(   * RX Get and Set   **********************************************************************/  void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ @@ -412,13 +411,13 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){          return;      case SUBDEV_PROP_GAIN: -        assert_has(_rx_gains.keys(), name, "rfx rx gain name"); -        val = _rx_gains[name]; +        assert_has(_rx_gains.keys(), key.name, "rfx rx gain name"); +        val = _rx_gains[key.name];          return;      case SUBDEV_PROP_GAIN_RANGE: -        assert_has(_rx_gain_ranges.keys(), name, "rfx rx gain name"); -        val = _rx_gain_ranges[name]; +        assert_has(_rx_gain_ranges.keys(), key.name, "rfx rx gain name"); +        val = _rx_gain_ranges[key.name];          return;      case SUBDEV_PROP_GAIN_NAMES: @@ -458,8 +457,7 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){  }  void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ @@ -469,7 +467,7 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){          return;      case SUBDEV_PROP_GAIN: -        this->set_rx_gain(val.as<float>(), name); +        this->set_rx_gain(val.as<float>(), key.name);          return;      case SUBDEV_PROP_ANTENNA: @@ -484,8 +482,7 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){   * TX Get and Set   **********************************************************************/  void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ @@ -499,7 +496,7 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){      case SUBDEV_PROP_GAIN:      case SUBDEV_PROP_GAIN_RANGE: -        assert_has(rfx_tx_gain_ranges.keys(), name, "rfx tx gain name"); +        assert_has(rfx_tx_gain_ranges.keys(), key.name, "rfx tx gain name");          //no controllable tx gains, will not get here          return; @@ -540,8 +537,7 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){  }  void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ @@ -551,7 +547,7 @@ void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){          return;      case SUBDEV_PROP_GAIN: -        this->set_tx_gain(val.as<float>(), name); +        this->set_tx_gain(val.as<float>(), key.name);          return;      case SUBDEV_PROP_ANTENNA: diff --git a/host/lib/usrp/dboard/db_unknown.cpp b/host/lib/usrp/dboard/db_unknown.cpp index 9dd9b550b..f6f4f4a61 100644 --- a/host/lib/usrp/dboard/db_unknown.cpp +++ b/host/lib/usrp/dboard/db_unknown.cpp @@ -78,8 +78,7 @@ unknown_rx::~unknown_rx(void){  }  void unknown_rx::rx_get(const wax::obj &key_, wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ @@ -136,8 +135,7 @@ void unknown_rx::rx_get(const wax::obj &key_, wax::obj &val){  }  void unknown_rx::rx_set(const wax::obj &key_, const wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ @@ -169,8 +167,7 @@ unknown_tx::~unknown_tx(void){  }  void unknown_tx::tx_get(const wax::obj &key_, wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ @@ -227,8 +224,7 @@ void unknown_tx::tx_get(const wax::obj &key_, wax::obj &val){  }  void unknown_tx::tx_set(const wax::obj &key_, const wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp index 3038ce30b..ccd897674 100644 --- a/host/lib/usrp/dboard/db_wbx.cpp +++ b/host/lib/usrp/dboard/db_wbx.cpp @@ -467,8 +467,7 @@ double wbx_xcvr::set_lo_freq(   * RX Get and Set   **********************************************************************/  void wbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ @@ -481,13 +480,13 @@ void wbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){          return;      case SUBDEV_PROP_GAIN: -        assert_has(_rx_gains.keys(), name, "wbx rx gain name"); -        val = _rx_gains[name]; +        assert_has(_rx_gains.keys(), key.name, "wbx rx gain name"); +        val = _rx_gains[key.name];          return;      case SUBDEV_PROP_GAIN_RANGE: -        assert_has(wbx_rx_gain_ranges.keys(), name, "wbx rx gain name"); -        val = wbx_rx_gain_ranges[name]; +        assert_has(wbx_rx_gain_ranges.keys(), key.name, "wbx rx gain name"); +        val = wbx_rx_gain_ranges[key.name];          return;      case SUBDEV_PROP_GAIN_NAMES: @@ -527,8 +526,7 @@ void wbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){  }  void wbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ @@ -538,7 +536,7 @@ void wbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){          return;      case SUBDEV_PROP_GAIN: -        this->set_rx_gain(val.as<float>(), name); +        this->set_rx_gain(val.as<float>(), key.name);          return;      case SUBDEV_PROP_ANTENNA: @@ -553,8 +551,7 @@ void wbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){   * TX Get and Set   **********************************************************************/  void wbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ @@ -567,13 +564,13 @@ void wbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){          return;      case SUBDEV_PROP_GAIN: -        assert_has(_tx_gains.keys(), name, "wbx tx gain name"); -        val = _tx_gains[name]; +        assert_has(_tx_gains.keys(), key.name, "wbx tx gain name"); +        val = _tx_gains[key.name];          return;      case SUBDEV_PROP_GAIN_RANGE: -        assert_has(wbx_tx_gain_ranges.keys(), name, "wbx tx gain name"); -        val = wbx_tx_gain_ranges[name]; +        assert_has(wbx_tx_gain_ranges.keys(), key.name, "wbx tx gain name"); +        val = wbx_tx_gain_ranges[key.name];          return;      case SUBDEV_PROP_GAIN_NAMES: @@ -613,8 +610,7 @@ void wbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){  }  void wbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ @@ -624,7 +620,7 @@ void wbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){          return;      case SUBDEV_PROP_GAIN: -        this->set_tx_gain(val.as<float>(), name); +        this->set_tx_gain(val.as<float>(), key.name);          return;      case SUBDEV_PROP_ANTENNA: diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index 2c94bcd2d..798ff74a3 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -438,8 +438,7 @@ void xcvr2450::set_rx_gain(float gain, const std::string &name){   * RX Get and Set   **********************************************************************/  void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ @@ -452,13 +451,13 @@ void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){          return;      case SUBDEV_PROP_GAIN: -        assert_has(_rx_gains.keys(), name, "xcvr rx gain name"); -        val = _rx_gains[name]; +        assert_has(_rx_gains.keys(), key.name, "xcvr rx gain name"); +        val = _rx_gains[key.name];          return;      case SUBDEV_PROP_GAIN_RANGE: -        assert_has(xcvr_rx_gain_ranges.keys(), name, "xcvr rx gain name"); -        val = xcvr_rx_gain_ranges[name]; +        assert_has(xcvr_rx_gain_ranges.keys(), key.name, "xcvr rx gain name"); +        val = xcvr_rx_gain_ranges[key.name];          return;      case SUBDEV_PROP_GAIN_NAMES: @@ -502,8 +501,7 @@ void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){  }  void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ @@ -513,7 +511,7 @@ void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){          return;      case SUBDEV_PROP_GAIN: -        this->set_rx_gain(val.as<float>(), name); +        this->set_rx_gain(val.as<float>(), key.name);          return;      case SUBDEV_PROP_ANTENNA: @@ -528,8 +526,7 @@ void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){   * TX Get and Set   **********************************************************************/  void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ @@ -542,13 +539,13 @@ void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){          return;      case SUBDEV_PROP_GAIN: -        assert_has(_tx_gains.keys(), name, "xcvr tx gain name"); -        val = _tx_gains[name]; +        assert_has(_tx_gains.keys(), key.name, "xcvr tx gain name"); +        val = _tx_gains[key.name];          return;      case SUBDEV_PROP_GAIN_RANGE: -        assert_has(xcvr_tx_gain_ranges.keys(), name, "xcvr tx gain name"); -        val = xcvr_tx_gain_ranges[name]; +        assert_has(xcvr_tx_gain_ranges.keys(), key.name, "xcvr tx gain name"); +        val = xcvr_tx_gain_ranges[key.name];          return;      case SUBDEV_PROP_GAIN_NAMES: @@ -588,8 +585,7 @@ void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){  }  void xcvr2450::tx_set(const wax::obj &key_, const wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<subdev_prop_t>()){ @@ -599,7 +595,7 @@ void xcvr2450::tx_set(const wax::obj &key_, const wax::obj &val){          return;      case SUBDEV_PROP_GAIN: -        this->set_tx_gain(val.as<float>(), name); +        this->set_tx_gain(val.as<float>(), key.name);          return;      case SUBDEV_PROP_ANTENNA: diff --git a/host/lib/usrp/dsp_utils.cpp b/host/lib/usrp/dsp_utils.cpp new file mode 100644 index 000000000..fe1313af1 --- /dev/null +++ b/host/lib/usrp/dsp_utils.cpp @@ -0,0 +1,124 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/usrp/dsp_utils.hpp> +#include <uhd/types/dict.hpp> +#include <uhd/utils/assert.hpp> +#include <boost/assign/list_of.hpp> +#include <boost/tuple/tuple.hpp> +#include <boost/math/special_functions/round.hpp> +#include <cmath> + +using namespace uhd; +using namespace uhd::usrp; + +template <class T> T ceil_log2(T num){ +    return std::ceil(std::log(num)/std::log(T(2))); +} + +boost::uint32_t dsp_type1::calc_rx_mux_word(subdev_conn_t subdev_conn){ +    switch(subdev_conn){ +    case SUBDEV_CONN_COMPLEX_IQ: return (0x1 << 2) | (0x0 << 0); //DDC0Q=ADC1, DDC0I=ADC0 +    case SUBDEV_CONN_COMPLEX_QI: return (0x0 << 2) | (0x1 << 0); //DDC0Q=ADC0, DDC0I=ADC1 +    case SUBDEV_CONN_REAL_I:     return (0x3 << 2) | (0x0 << 0); //DDC0Q=ZERO, DDC0I=ADC0 +    case SUBDEV_CONN_REAL_Q:     return (0x1 << 2) | (0x3 << 0); //DDC0Q=ADC1, DDC0I=ZERO +    default:                     UHD_THROW_INVALID_CODE_PATH(); +    } +} + +boost::uint32_t dsp_type1::calc_tx_mux_word(subdev_conn_t subdev_conn){ +    switch(subdev_conn){ +    case SUBDEV_CONN_COMPLEX_IQ: return (0x1 << 4) | (0x0 << 0); //DAC1=DUC0Q, DAC0=DUC0I +    case SUBDEV_CONN_COMPLEX_QI: return (0x0 << 4) | (0x1 << 0); //DAC1=DUC0I, DAC0=DUC0Q +    case SUBDEV_CONN_REAL_I:     return (0xf << 4) | (0x0 << 0); //DAC1=ZERO,  DAC0=DUC0I +    case SUBDEV_CONN_REAL_Q:     return (0x0 << 4) | (0xf << 0); //DAC1=DUC0I, DAC0=ZERO +    default:                     UHD_THROW_INVALID_CODE_PATH(); +    } +} + +boost::uint32_t dsp_type1::calc_cordic_word_and_update( +    double &freq, +    double codec_rate +){ +    UHD_ASSERT_THROW(std::abs(freq) <= codec_rate/2.0); +    static const double scale_factor = std::pow(2.0, 32); + +    //calculate the freq register word (signed) +    boost::int32_t freq_word = boost::int32_t(boost::math::round((freq / codec_rate) * scale_factor)); + +    //update the actual frequency +    freq = (double(freq_word) / scale_factor) * codec_rate; + +    return boost::uint32_t(freq_word); +} + +boost::uint32_t dsp_type1::calc_cic_filter_word(unsigned rate){ +    int hb0 = 0, hb1 = 0; +    if (not (rate & 0x1)){ +        hb0 = 1; +        rate /= 2; +    } +    if (not (rate & 0x1)){ +        hb1 = 1; +        rate /= 2; +    } +    return (hb1 << 9) | (hb0 << 8) | (rate & 0xff); +} + +boost::uint32_t dsp_type1::calc_iq_scale_word( +    boost::int16_t i, boost::int16_t q +){ +    return (boost::uint32_t(i) << 16) | (boost::uint32_t(q) << 0); +} + +boost::uint32_t dsp_type1::calc_iq_scale_word(unsigned rate){ +    // Calculate CIC interpolation (i.e., without halfband interpolators) +    unsigned tmp_rate = calc_cic_filter_word(rate) & 0xff; + +    // Calculate closest multiplier constant to reverse gain absent scale multipliers +    double rate_cubed = std::pow(double(tmp_rate), 3); +    boost::int16_t scale = boost::math::iround((4096*std::pow(2, ceil_log2(rate_cubed)))/(1.65*rate_cubed)); +    return calc_iq_scale_word(scale, scale); +} + +boost::uint32_t dsp_type1::calc_stream_cmd_word( +    const stream_cmd_t &stream_cmd, size_t num_samps_continuous +){ +    UHD_ASSERT_THROW(stream_cmd.num_samps <= 0x3fffffff); + +    //setup the mode to instruction flags +    typedef boost::tuple<bool, bool, bool> inst_t; +    static const uhd::dict<stream_cmd_t::stream_mode_t, inst_t> mode_to_inst = boost::assign::map_list_of +                                                            //reload, chain, samps +        (stream_cmd_t::STREAM_MODE_START_CONTINUOUS,   inst_t(true,  true,  false)) +        (stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS,    inst_t(false, false, false)) +        (stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE, inst_t(false, false, true)) +        (stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE, inst_t(false, true,  true)) +    ; + +    //setup the instruction flag values +    bool inst_reload, inst_chain, inst_samps; +    boost::tie(inst_reload, inst_chain, inst_samps) = mode_to_inst[stream_cmd.stream_mode]; + +    //calculate the word from flags and length +    boost::uint32_t word = 0; +    word |= boost::uint32_t((stream_cmd.stream_now)? 1 : 0) << 31; +    word |= boost::uint32_t((inst_chain)?            1 : 0) << 30; +    word |= boost::uint32_t((inst_reload)?           1 : 0) << 29; +    word |= (inst_samps)? stream_cmd.num_samps : ((inst_chain)? num_samps_continuous : 1); +    return word; +} diff --git a/host/lib/usrp/dsp_utils.hpp b/host/lib/usrp/dsp_utils.hpp deleted file mode 100644 index ebed12c41..000000000 --- a/host/lib/usrp/dsp_utils.hpp +++ /dev/null @@ -1,187 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program.  If not, see <http://www.gnu.org/licenses/>. -// - -#ifndef INCLUDED_LIBUHD_USRP_DSP_UTILS_HPP -#define INCLUDED_LIBUHD_USRP_DSP_UTILS_HPP - -#include <uhd/config.hpp> -#include <uhd/types/dict.hpp> -#include <uhd/utils/assert.hpp> -#include <uhd/types/stream_cmd.hpp> -#include <uhd/usrp/subdev_props.hpp> -#include <boost/cstdint.hpp> -#include <boost/assign/list_of.hpp> -#include <boost/tuple/tuple.hpp> -#include <boost/math/special_functions/round.hpp> - -namespace uhd{ namespace usrp{ - -namespace dsp_type1{ - -    template <class T> T ceil_log2(T num){ -        return std::ceil(std::log(num)/std::log(T(2))); -    } - -    /*! -     * Calculate the rx mux word from properties. -     * \param subdev_conn the subdev connection type -     * \param the 32-bit rx mux control word -     */ -    static inline boost::uint32_t calc_rx_mux_word( -        subdev_conn_t subdev_conn -    ){ -        switch(subdev_conn){ -        case SUBDEV_CONN_COMPLEX_IQ: return (0x1 << 2) | (0x0 << 0); //DDC0Q=ADC1, DDC0I=ADC0 -        case SUBDEV_CONN_COMPLEX_QI: return (0x0 << 2) | (0x1 << 0); //DDC0Q=ADC0, DDC0I=ADC1 -        case SUBDEV_CONN_REAL_I:     return (0x3 << 2) | (0x0 << 0); //DDC0Q=ZERO, DDC0I=ADC0 -        case SUBDEV_CONN_REAL_Q:     return (0x1 << 2) | (0x3 << 0); //DDC0Q=ADC1, DDC0I=ZERO -        default:                     UHD_THROW_INVALID_CODE_PATH(); -        } -    } - -    /*! -     * Calculate the tx mux word from properties. -     * \param subdev_conn the subdev connection type -     * \param the 32-bit tx mux control word -     */ -    static inline boost::uint32_t calc_tx_mux_word( -        subdev_conn_t subdev_conn -    ){ -        switch(subdev_conn){ -        case SUBDEV_CONN_COMPLEX_IQ: return (0x1 << 4) | (0x0 << 0); //DAC1=DUC0Q, DAC0=DUC0I -        case SUBDEV_CONN_COMPLEX_QI: return (0x0 << 4) | (0x1 << 0); //DAC1=DUC0I, DAC0=DUC0Q -        case SUBDEV_CONN_REAL_I:     return (0xf << 4) | (0x0 << 0); //DAC1=ZERO,  DAC0=DUC0I -        case SUBDEV_CONN_REAL_Q:     return (0x0 << 4) | (0xf << 0); //DAC1=DUC0I, DAC0=ZERO -        default:                     UHD_THROW_INVALID_CODE_PATH(); -        } -    } - -    /*! -     * Calculate the cordic word from the frequency and clock rate. -     * The frequency will be set to the actual (possible) frequency. -     * -     * \param freq the requested frequency in Hz -     * \param codec_rate the dsp codec rate in Hz -     * \param the 32-bit cordic control word -     */ -    static inline boost::uint32_t calc_cordic_word_and_update( -        double &freq, -        double codec_rate -    ){ -        UHD_ASSERT_THROW(std::abs(freq) <= codec_rate/2.0); -        static const double scale_factor = std::pow(2.0, 32); - -        //calculate the freq register word (signed) -        boost::int32_t freq_word = boost::int32_t(boost::math::round((freq / codec_rate) * scale_factor)); - -        //update the actual frequency -        freq = (double(freq_word) / scale_factor) * codec_rate; - -        return boost::uint32_t(freq_word); -    } - -    /*! -     * Calculate the CIC filter word from the rate. -     * Check if requested decim/interp rate is: -     *      multiple of 4, enable two halfband filters -     *      multiple of 2, enable one halfband filter -     *      handle remainder in CIC -     * -     * \param rate the requested rate in Sps -     * \return the 32-bit cic filter control word -     */ -    template <typename dsp_rate_type> -    static inline boost::uint32_t calc_cic_filter_word(dsp_rate_type rate){ -        int hb0 = 0, hb1 = 0; -        if (not (rate & 0x1)){ -            hb0 = 1; -            rate /= 2; -        } -        if (not (rate & 0x1)){ -            hb1 = 1; -            rate /= 2; -        } -        return (hb1 << 9) | (hb0 << 8) | (rate & 0xff); -    } - -    /*! -     * Calculate the IQ scale factor word from I and Q components. -     * \param i the I component of the scalar -     * \param q the Q component of the scalar -     * \return the 32-bit scale factor control word -     */ -    static inline boost::uint32_t calc_iq_scale_word( -        boost::int16_t i, boost::int16_t q -    ){ -        return (boost::uint32_t(i) << 16) | (boost::uint32_t(q) << 0); -    } - -    /*! -     * Calculate the IQ scale factor word from the rate. -     * \param rate the requested rate in Sps -     * \return the 32-bit scale factor control word -     */ -    template <typename dsp_rate_type> -    static inline boost::uint32_t calc_iq_scale_word(dsp_rate_type rate){ -        // Calculate CIC interpolation (i.e., without halfband interpolators) -        dsp_rate_type tmp_rate = calc_cic_filter_word(rate) & 0xff; - -        // Calculate closest multiplier constant to reverse gain absent scale multipliers -        double rate_cubed = std::pow(double(tmp_rate), 3); -        boost::int16_t scale = boost::math::iround((4096*std::pow(2, ceil_log2(rate_cubed)))/(1.65*rate_cubed)); -        return calc_iq_scale_word(scale, scale); -    } - -    /*! -     * Calculate the stream command word from the stream command struct. -     * \param stream_cmd the requested stream command with mode, flags, timestamp -     * \param num_samps_continuous number of samples to request in continuous mode -     * \return the 32-bit stream command word -     */ -    static inline boost::uint32_t calc_stream_cmd_word( -        const stream_cmd_t &stream_cmd, size_t num_samps_continuous -    ){ -        UHD_ASSERT_THROW(stream_cmd.num_samps <= 0x3fffffff); - -        //setup the mode to instruction flags -        typedef boost::tuple<bool, bool, bool> inst_t; -        static const uhd::dict<stream_cmd_t::stream_mode_t, inst_t> mode_to_inst = boost::assign::map_list_of -                                                                //reload, chain, samps -            (stream_cmd_t::STREAM_MODE_START_CONTINUOUS,   inst_t(true,  true,  false)) -            (stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS,    inst_t(false, false, false)) -            (stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE, inst_t(false, false, true)) -            (stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE, inst_t(false, true,  true)) -        ; - -        //setup the instruction flag values -        bool inst_reload, inst_chain, inst_samps; -        boost::tie(inst_reload, inst_chain, inst_samps) = mode_to_inst[stream_cmd.stream_mode]; - -        //calculate the word from flags and length -        boost::uint32_t word = 0; -        word |= boost::uint32_t((stream_cmd.stream_now)? 1 : 0) << 31; -        word |= boost::uint32_t((inst_chain)?            1 : 0) << 30; -        word |= boost::uint32_t((inst_reload)?           1 : 0) << 29; -        word |= (inst_samps)? stream_cmd.num_samps : ((inst_chain)? num_samps_continuous : 1); -        return word; -    } - -} //namespace dsp_type1 - -}} //namespace - -#endif /* INCLUDED_LIBUHD_USRP_DSP_UTILS_HPP */ diff --git a/host/lib/usrp/misc_utils.cpp b/host/lib/usrp/misc_utils.cpp index 0aa03a6cc..46094ba32 100644 --- a/host/lib/usrp/misc_utils.cpp +++ b/host/lib/usrp/misc_utils.cpp @@ -15,9 +15,13 @@  // along with this program.  If not, see <http://www.gnu.org/licenses/>.  // -#include "misc_utils.hpp" +#include <uhd/usrp/misc_utils.hpp> +#include <uhd/utils/assert.hpp>  #include <uhd/utils/gain_group.hpp> +#include <uhd/usrp/dboard_id.hpp>  #include <uhd/usrp/subdev_props.hpp> +#include <uhd/usrp/mboard_props.hpp> +#include <uhd/usrp/dboard_props.hpp>  #include <uhd/usrp/codec_props.hpp>  #include <boost/bind.hpp>  #include <boost/foreach.hpp> @@ -25,9 +29,6 @@  using namespace uhd;  using namespace uhd::usrp; -static const size_t subdev_gain_priority = 1; //higher, closer to the antenna -static const size_t codec_gain_priority = 0; -  /***********************************************************************   * codec gain group helper functions:   *    do this so we dont have to bind a templated function @@ -76,7 +77,15 @@ static void set_subdev_gain(wax::obj subdev, const std::string &name, float gain  /***********************************************************************   * gain group factory function for usrp   **********************************************************************/ -gain_group::sptr usrp::make_gain_group(wax::obj subdev, wax::obj codec){ +gain_group::sptr usrp::make_gain_group( +    wax::obj subdev, wax::obj codec, +    gain_group_policy_t gain_group_policy +){ +    const size_t subdev_gain_priority = 1; +    const size_t codec_gain_priority = (gain_group_policy == GAIN_GROUP_POLICY_RX)? +        (subdev_gain_priority - 1): //RX policy, codec gains fill last (lower priority) +        (subdev_gain_priority + 1); //TX policy, codec gains fill first (higher priority) +      gain_group::sptr gg = gain_group::make();      gain_fcns_t fcns;      //add all the subdev gains first (antenna to dsp order) @@ -112,3 +121,69 @@ gain_group::sptr usrp::make_gain_group(wax::obj subdev, wax::obj codec){      }      return gg;  } + +/*********************************************************************** + * verify subdev specs + **********************************************************************/ +static void verify_xx_subdev_spec( +    mboard_prop_t dboard_names_prop, +    mboard_prop_t dboard_prop, +    subdev_spec_t &subdev_spec, +    wax::obj mboard, +    std::string xx_type +){ +    prop_names_t dboard_names = mboard[dboard_names_prop].as<prop_names_t>(); +    UHD_ASSERT_THROW(dboard_names.size() > 0); //well i hope there is a dboard + +    //the subdevice specification is empty: handle automatic +    if (subdev_spec.empty()){ +        BOOST_FOREACH(const std::string &db_name, dboard_names){ +            wax::obj dboard = mboard[named_prop_t(dboard_prop, db_name)]; + +            //if the dboard slot is populated, take the first subdevice +            if (dboard[DBOARD_PROP_DBOARD_ID].as<dboard_id_t>() != dboard_id_t::none()){ +                std::string sd_name = dboard[DBOARD_PROP_SUBDEV_NAMES].as<prop_names_t>().front(); +                subdev_spec.push_back(subdev_spec_pair_t(db_name, sd_name)); +                break; +            } +        } + +        //didnt find any populated dboards: add the first subdevice +        if (subdev_spec.empty()){ +            std::string db_name = dboard_names.front(); +            wax::obj dboard = mboard[named_prop_t(dboard_prop, db_name)]; +            std::string sd_name = dboard[DBOARD_PROP_SUBDEV_NAMES].as<prop_names_t>().front(); +            subdev_spec.push_back(subdev_spec_pair_t(db_name, sd_name)); +        } +    } + +    //sanity check that the dboard/subdevice names exist for this mboard +    BOOST_FOREACH(const subdev_spec_pair_t &pair, subdev_spec){ +        //empty db name means select dboard automatically +        if (pair.db_name.empty()){ +            if (dboard_names.size() != 1) throw std::runtime_error( +                "A daughterboard name must be provided for multi-slot boards: " + subdev_spec.to_string() +            ); +            pair.db_name == dboard_names.front(); +        } +        uhd::assert_has(dboard_names, pair.db_name, xx_type + " dboard name"); +        wax::obj dboard = mboard[named_prop_t(dboard_prop, pair.db_name)]; +        uhd::assert_has(dboard[DBOARD_PROP_SUBDEV_NAMES].as<prop_names_t>(), pair.sd_name, xx_type + " subdev name"); +    } +} + +void usrp::verify_rx_subdev_spec(subdev_spec_t &subdev_spec, wax::obj mboard){ +    return verify_xx_subdev_spec( +        MBOARD_PROP_RX_DBOARD_NAMES, +        MBOARD_PROP_RX_DBOARD, +        subdev_spec, mboard, "rx" +    ); +} + +void usrp::verify_tx_subdev_spec(subdev_spec_t &subdev_spec, wax::obj mboard){ +    return verify_xx_subdev_spec( +        MBOARD_PROP_TX_DBOARD_NAMES, +        MBOARD_PROP_TX_DBOARD, +        subdev_spec, mboard, "tx" +    ); +} diff --git a/host/lib/usrp/misc_utils.hpp b/host/lib/usrp/misc_utils.hpp deleted file mode 100644 index 7fe3c899d..000000000 --- a/host/lib/usrp/misc_utils.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program.  If not, see <http://www.gnu.org/licenses/>. -// - -#ifndef INCLUDED_LIBUHD_USRP_MISC_UTILS_HPP -#define INCLUDED_LIBUHD_USRP_MISC_UTILS_HPP - -#include <uhd/config.hpp> -#include <uhd/wax.hpp> -#include <uhd/utils/gain_group.hpp> - -namespace uhd{ namespace usrp{ - -    /*! -     * Create a gain group that represents the subdevice and its codec. -     */ -    gain_group::sptr make_gain_group(wax::obj subdev, wax::obj codec); - -}} //namespace - -#endif /* INCLUDED_LIBUHD_USRP_MISC_UTILS_HPP */ - diff --git a/host/lib/usrp/subdev_spec.cpp b/host/lib/usrp/subdev_spec.cpp index 0f00e2f74..7a3e72867 100644 --- a/host/lib/usrp/subdev_spec.cpp +++ b/host/lib/usrp/subdev_spec.cpp @@ -16,7 +16,7 @@  //  #include <uhd/usrp/subdev_spec.hpp> -#include <boost/algorithm/string.hpp> +#include <uhd/utils/algorithm.hpp>  #include <boost/format.hpp>  #include <boost/foreach.hpp>  #include <stdexcept> @@ -35,12 +35,9 @@ subdev_spec_pair_t::subdev_spec_pair_t(  }  subdev_spec_t::subdev_spec_t(const std::string &markup){ -    std::vector<std::string> pairs; -    boost::split(pairs, markup, boost::is_any_of("\t ")); -    BOOST_FOREACH(const std::string &pair, pairs){ +    BOOST_FOREACH(const std::string &pair, std::split_string(markup)){          if (pair == "") continue; -        std::vector<std::string> db_sd; -        boost::split(db_sd, pair, boost::is_any_of(":")); +        std::vector<std::string> db_sd = std::split_string(pair, ":");          switch(db_sd.size()){          case 1: this->push_back(subdev_spec_pair_t("", db_sd.front())); break;          case 2: this->push_back(subdev_spec_pair_t(db_sd.front(), db_sd.back())); break; @@ -56,13 +53,9 @@ std::string subdev_spec_t::to_pp_string(void) const{      size_t count = 0;      ss << "Subdevice Specification:" << std::endl;      BOOST_FOREACH(const subdev_spec_pair_t &pair, *this){ -        std::string db_name = pair.db_name; -        if (db_name == "") db_name = "0"; -        std::string sd_name = pair.sd_name; -        if (sd_name == "") sd_name = "0";          ss << boost::format(              "    Channel %d: Daughterboard %s, Subdevice %s" -        ) % (count++) % db_name % sd_name << std::endl; +        ) % (count++) % pair.db_name % pair.sd_name << std::endl;      }      return ss.str();  } diff --git a/host/lib/usrp/usrp2/codec_impl.cpp b/host/lib/usrp/usrp2/codec_impl.cpp index 969b5b4b9..f7f9ce2d5 100644 --- a/host/lib/usrp/usrp2/codec_impl.cpp +++ b/host/lib/usrp/usrp2/codec_impl.cpp @@ -53,9 +53,7 @@ void usrp2_mboard_impl::codec_init(void){  /***********************************************************************   * RX Codec Properties   **********************************************************************/ -void usrp2_mboard_impl::rx_codec_get(const wax::obj &key_, wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +void usrp2_mboard_impl::rx_codec_get(const wax::obj &key, wax::obj &val){      //handle the get request conditioned on the key      switch(key.as<codec_prop_t>()){ @@ -136,9 +134,7 @@ void usrp2_mboard_impl::rx_codec_set_gain(float gain, const std::string &name){  /***********************************************************************   * TX Codec Properties   **********************************************************************/ -void usrp2_mboard_impl::tx_codec_get(const wax::obj &key_, wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +void usrp2_mboard_impl::tx_codec_get(const wax::obj &key, wax::obj &val){      //handle the get request conditioned on the key      switch(key.as<codec_prop_t>()){ diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp index be45c2c9e..cff13292b 100644 --- a/host/lib/usrp/usrp2/dboard_iface.cpp +++ b/host/lib/usrp/usrp2/dboard_iface.cpp @@ -37,7 +37,12 @@ public:      usrp2_dboard_iface(usrp2_iface::sptr iface, usrp2_clock_ctrl::sptr clock_ctrl);      ~usrp2_dboard_iface(void); -    std::string get_mboard_name(void){return "usrp2";} +    special_props_t get_special_props(void){ +        special_props_t props; +        props.soft_clock_divider = false; +        props.mangle_i2c_addrs = false; +        return props; +    }      void write_aux_dac(unit_t, aux_dac_t, float);      float read_aux_adc(unit_t, aux_adc_t); diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index 075f22388..a462b93c2 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -17,8 +17,8 @@  #include "usrp2_impl.hpp"  #include "usrp2_regs.hpp" -#include "../dsp_utils.hpp" -#include "../misc_utils.hpp" +#include <uhd/usrp/misc_utils.hpp> +#include <uhd/usrp/dsp_utils.hpp>  #include <uhd/usrp/subdev_props.hpp>  #include <uhd/usrp/dboard_props.hpp>  #include <uhd/utils/assert.hpp> @@ -59,8 +59,7 @@ void usrp2_mboard_impl::dboard_init(void){   * RX DBoard Properties   **********************************************************************/  void usrp2_mboard_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<dboard_prop_t>()){ @@ -69,7 +68,7 @@ void usrp2_mboard_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){          return;      case DBOARD_PROP_SUBDEV: -        val = _dboard_manager->get_rx_subdev(name); +        val = _dboard_manager->get_rx_subdev(key.name);          return;      case DBOARD_PROP_SUBDEV_NAMES: @@ -90,7 +89,9 @@ void usrp2_mboard_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){      case DBOARD_PROP_GAIN_GROUP:          val = make_gain_group( -            _dboard_manager->get_rx_subdev(name), _rx_codec_proxy->get_link() +            _dboard_manager->get_rx_subdev(key.name), +            _rx_codec_proxy->get_link(), +            GAIN_GROUP_POLICY_RX          );          return; @@ -114,8 +115,7 @@ void usrp2_mboard_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){   * TX DBoard Properties   **********************************************************************/  void usrp2_mboard_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<dboard_prop_t>()){ @@ -124,7 +124,7 @@ void usrp2_mboard_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){          return;      case DBOARD_PROP_SUBDEV: -        val = _dboard_manager->get_tx_subdev(name); +        val = _dboard_manager->get_tx_subdev(key.name);          return;      case DBOARD_PROP_SUBDEV_NAMES: @@ -145,7 +145,9 @@ void usrp2_mboard_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){      case DBOARD_PROP_GAIN_GROUP:          val = make_gain_group( -            _dboard_manager->get_tx_subdev(name), _tx_codec_proxy->get_link() +            _dboard_manager->get_tx_subdev(key.name), +            _tx_codec_proxy->get_link(), +            GAIN_GROUP_POLICY_TX          );          return; diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index 936b1f7a2..97bda51fc 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -17,9 +17,10 @@  #include "usrp2_impl.hpp"  #include "usrp2_regs.hpp" -#include "../dsp_utils.hpp" +#include <uhd/usrp/dsp_utils.hpp>  #include <uhd/usrp/dsp_props.hpp>  #include <boost/bind.hpp> +#include <cmath>  using namespace uhd;  using namespace uhd::usrp; @@ -30,10 +31,10 @@ static const size_t default_interp = 16;  /***********************************************************************   * DDC Helper Methods   **********************************************************************/ -template <class rate_t> static rate_t -pick_closest_rate(double exact_rate, const std::vector<rate_t> &rates){ -    rate_t closest_match = rates.at(0); -    BOOST_FOREACH(rate_t possible_rate, rates){ +template <typename rate_type> +static rate_type pick_closest_rate(double exact_rate, const std::vector<rate_type> &rates){ +    unsigned closest_match = rates.front(); +    BOOST_FOREACH(rate_type possible_rate, rates){          if(std::abs(exact_rate - possible_rate) < std::abs(exact_rate - closest_match))              closest_match = possible_rate;      } diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index fc1e6f2a7..4d3b62d6b 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -34,7 +34,7 @@ extern "C" {  //fpga and firmware compatibility numbers  #define USRP2_FPGA_COMPAT_NUM 1 -#define USRP2_FW_COMPAT_NUM 5 +#define USRP2_FW_COMPAT_NUM 6  //used to differentiate control packets over data port  #define USRP2_INVALID_VRT_HEADER 0 diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 6c4234641..fc1cc3a9a 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -17,13 +17,15 @@  #include "usrp2_impl.hpp"  #include "usrp2_regs.hpp" -#include "../dsp_utils.hpp" +#include <uhd/usrp/misc_utils.hpp> +#include <uhd/usrp/dsp_utils.hpp>  #include <uhd/usrp/mboard_props.hpp>  #include <uhd/utils/assert.hpp>  #include <uhd/utils/algorithm.hpp>  #include <uhd/types/mac_addr.hpp>  #include <uhd/types/dict.hpp>  #include <boost/bind.hpp> +#include <boost/assign/list_of.hpp>  #include <boost/asio/ip/address_v4.hpp>  #include <iostream>  #include <boost/date_time/posix_time/posix_time.hpp> @@ -194,12 +196,13 @@ void usrp2_mboard_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){  /***********************************************************************   * MBoard Get Properties   **********************************************************************/ +static const std::string dboard_name = "0"; +  void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the other props -    if (key.type() == typeid(std::string)){ +    if (key_.type() == typeid(std::string)){          if (key.as<std::string>() == "mac-addr"){              byte_vector_t bytes = _iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_MAC_ADDR, 6);              val = mac_addr_t::from_bytes(bytes).to_string(); @@ -230,25 +233,25 @@ void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){          return;      case MBOARD_PROP_RX_DBOARD: -        UHD_ASSERT_THROW(name == ""); +        UHD_ASSERT_THROW(key.name == dboard_name);          val = _rx_dboard_proxy->get_link();          return;      case MBOARD_PROP_RX_DBOARD_NAMES: -        val = prop_names_t(1, ""); +        val = prop_names_t(1, dboard_name);          return;      case MBOARD_PROP_TX_DBOARD: -        UHD_ASSERT_THROW(name == ""); +        UHD_ASSERT_THROW(key.name == dboard_name);          val = _tx_dboard_proxy->get_link();          return;      case MBOARD_PROP_TX_DBOARD_NAMES: -        val = prop_names_t(1, ""); +        val = prop_names_t(1, dboard_name);          return;      case MBOARD_PROP_RX_DSP: -        UHD_ASSERT_THROW(name == ""); +        UHD_ASSERT_THROW(key.name == "");          val = _rx_dsp_proxy->get_link();          return; @@ -257,7 +260,7 @@ void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){          return;      case MBOARD_PROP_TX_DSP: -        UHD_ASSERT_THROW(name == ""); +        UHD_ASSERT_THROW(key.name == "");          val = _tx_dsp_proxy->get_link();          return; @@ -333,14 +336,9 @@ void usrp2_mboard_impl::set(const wax::obj &key, const wax::obj &val){      case MBOARD_PROP_RX_SUBDEV_SPEC:          _rx_subdev_spec = val.as<subdev_spec_t>(); -        //handle automatic -        if (_rx_subdev_spec.empty()) _rx_subdev_spec.push_back( -            subdev_spec_pair_t("", _dboard_manager->get_rx_subdev_names().front()) -        ); +        verify_rx_subdev_spec(_rx_subdev_spec, this->get_link());          //sanity check          UHD_ASSERT_THROW(_rx_subdev_spec.size() == 1); -        uhd::assert_has((*this)[MBOARD_PROP_RX_DBOARD_NAMES].as<prop_names_t>(), _rx_subdev_spec.front().db_name, "rx dboard names"); -        uhd::assert_has(_dboard_manager->get_rx_subdev_names(), _rx_subdev_spec.front().sd_name, "rx subdev names");          //set the mux          _iface->poke32(_iface->regs.dsp_rx_mux, dsp_type1::calc_rx_mux_word(              _dboard_manager->get_rx_subdev(_rx_subdev_spec.front().sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>() @@ -349,14 +347,9 @@ void usrp2_mboard_impl::set(const wax::obj &key, const wax::obj &val){      case MBOARD_PROP_TX_SUBDEV_SPEC:          _tx_subdev_spec = val.as<subdev_spec_t>(); -        //handle automatic -        if (_tx_subdev_spec.empty()) _tx_subdev_spec.push_back( -            subdev_spec_pair_t("", _dboard_manager->get_tx_subdev_names().front()) -        ); +        verify_tx_subdev_spec(_tx_subdev_spec, this->get_link());          //sanity check          UHD_ASSERT_THROW(_tx_subdev_spec.size() == 1); -        uhd::assert_has((*this)[MBOARD_PROP_TX_DBOARD_NAMES].as<prop_names_t>(), _tx_subdev_spec.front().db_name, "tx dboard names"); -        uhd::assert_has(_dboard_manager->get_tx_subdev_names(), _tx_subdev_spec.front().sd_name, "tx subdev names");          //set the mux          _iface->poke32(_iface->regs.dsp_tx_mux, dsp_type1::calc_tx_mux_word(              _dboard_manager->get_tx_subdev(_tx_subdev_spec.front().sd_name)[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>() diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 21f411afe..568c87a22 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -21,7 +21,7 @@  #include <uhd/usrp/device_props.hpp>  #include <uhd/utils/assert.hpp>  #include <uhd/utils/static.hpp> -#include <boost/algorithm/string.hpp> +#include <uhd/utils/algorithm.hpp>  #include <boost/assign/list_of.hpp>  #include <boost/format.hpp>  #include <boost/foreach.hpp> @@ -41,12 +41,6 @@ static const size_t DISCOVERY_TIMEOUT_MS = 100;  /***********************************************************************   * Helper Functions   **********************************************************************/ -std::vector<std::string> split_addrs(const std::string &addrs_str){ -    std::vector<std::string> addrs; -    boost::split(addrs, addrs_str, boost::is_any_of("\t ")); -    return addrs; -} -  template <class T> std::string num2str(T num){      return boost::lexical_cast<std::string>(num);  } @@ -80,7 +74,7 @@ static uhd::device_addrs_t usrp2_find(const device_addr_t &hint){      }      //if there are multiple addresses, just return good, dont test -    std::vector<std::string> addrs = split_addrs(hint["addr"]); +    std::vector<std::string> addrs = std::split_string(hint["addr"]);      if (addrs.size() > 1){          device_addr_t new_addr;          new_addr["type"] = "usrp2"; @@ -155,7 +149,7 @@ static device::sptr usrp2_make(const device_addr_t &device_addr){      std::vector<udp_simple::sptr> ctrl_transports;      std::vector<udp_zero_copy::sptr> data_transports; -    BOOST_FOREACH(const std::string &addr, split_addrs(device_addr["addr"])){ +    BOOST_FOREACH(const std::string &addr, std::split_string(device_addr["addr"])){          ctrl_transports.push_back(udp_simple::make_connected(              addr, num2str(USRP2_UDP_CTRL_PORT)          )); @@ -207,8 +201,7 @@ usrp2_impl::~usrp2_impl(void){   * Device Properties   **********************************************************************/  void usrp2_impl::get(const wax::obj &key_, wax::obj &val){ -    wax::obj key; std::string name; -    boost::tie(key, name) = extract_named_prop(key_); +    named_prop_t key = named_prop_t::extract(key_);      //handle the get request conditioned on the key      switch(key.as<device_prop_t>()){ @@ -218,7 +211,7 @@ void usrp2_impl::get(const wax::obj &key_, wax::obj &val){          return;      case DEVICE_PROP_MBOARD: -        val = _mboard_dict[name]->get_link(); +        val = _mboard_dict[key.name]->get_link();          return;      case DEVICE_PROP_MBOARD_NAMES: diff --git a/host/lib/utils/paths.cpp b/host/lib/utils/paths.cpp index 4029bd989..6ad12d3cc 100644 --- a/host/lib/utils/paths.cpp +++ b/host/lib/utils/paths.cpp @@ -17,7 +17,7 @@  #include "constants.hpp"  #include <uhd/config.hpp> -#include <boost/algorithm/string.hpp> +#include <uhd/utils/algorithm.hpp>  #include <boost/program_options.hpp>  #include <boost/filesystem.hpp>  #include <boost/foreach.hpp> @@ -58,15 +58,9 @@ static std::vector<fs::path> get_env_paths(const std::string &var_name){      po::store(po::parse_environment(desc, boost::bind(&name_mapper, var_name, _1)), vm);      po::notify(vm); -    //split the path at the path separators -    std::vector<std::string> path_strings; -    if (not var_value.empty()) boost::split(//dont split empty strings -        path_strings, var_value, boost::is_any_of(env_path_sep) -    ); -      //convert to filesystem path, filter blank paths      std::vector<fs::path> paths; -    BOOST_FOREACH(std::string &path_string, path_strings){ +    BOOST_FOREACH(const std::string &path_string, std::split_string(var_value, env_path_sep)){          if (path_string.empty()) continue;          paths.push_back(fs::system_complete(path_string));      } @@ -78,13 +72,17 @@ static std::vector<fs::path> get_env_paths(const std::string &var_name){   **********************************************************************/  std::vector<fs::path> get_image_paths(void){      std::vector<fs::path> paths = get_env_paths("UHD_IMAGE_PATH"); -    paths.push_back(fs::path(UHD_INSTALL_PREFIX) / UHD_PKG_DATA_DIR / "images"); +    paths.push_back(fs::path(LOCAL_PKG_DATA_DIR) / "images"); +    if (not std::string(INSTALLER_PKG_DATA_DIR).empty()) +        paths.push_back(fs::path(INSTALLER_PKG_DATA_DIR) / "images");      return paths;  }  std::vector<fs::path> get_module_paths(void){      std::vector<fs::path> paths = get_env_paths("UHD_MODULE_PATH"); -    paths.push_back(fs::path(UHD_INSTALL_PREFIX) / UHD_PKG_DATA_DIR / "modules"); +    paths.push_back(fs::path(LOCAL_PKG_DATA_DIR) / "modules"); +    if (not std::string(INSTALLER_PKG_DATA_DIR).empty()) +        paths.push_back(fs::path(INSTALLER_PKG_DATA_DIR) / "modules");      return paths;  } diff --git a/host/lib/utils/props.cpp b/host/lib/utils/props.cpp index fac5fe24f..fc9f8e63f 100644 --- a/host/lib/utils/props.cpp +++ b/host/lib/utils/props.cpp @@ -29,15 +29,12 @@ named_prop_t::named_prop_t(      /* NOP */  } -typedef boost::tuple<wax::obj, std::string> named_prop_tuple; - -named_prop_tuple uhd::extract_named_prop( +named_prop_t named_prop_t::extract(      const wax::obj &key,      const std::string &name  ){      if (key.type() == typeid(named_prop_t)){ -        named_prop_t np = key.as<named_prop_t>(); -        return named_prop_tuple(np.key, np.name); +        return key.as<named_prop_t>();      } -    return named_prop_tuple(key, name); +    return named_prop_t(key, name);  } diff --git a/host/lib/utils/warning.cpp b/host/lib/utils/warning.cpp index ae4d4c7aa..8a7d35a23 100644 --- a/host/lib/utils/warning.cpp +++ b/host/lib/utils/warning.cpp @@ -16,7 +16,7 @@  //  #include <uhd/utils/warning.hpp> -#include <boost/algorithm/string.hpp> +#include <uhd/utils/algorithm.hpp>  #include <boost/foreach.hpp>  #include <iostream>  #include <vector> @@ -24,13 +24,9 @@  using namespace uhd;  void uhd::print_warning(const std::string &msg){ -    //extract the message lines -    std::vector<std::string> lines; -    boost::split(lines, msg, boost::is_any_of("\n")); -      //print the warning message      std::cerr << std::endl << "Warning:" << std::endl; -    BOOST_FOREACH(const std::string &line, lines){ +    BOOST_FOREACH(const std::string &line, std::split_string(msg, "\n")){          std::cerr << "    " << line << std::endl;      }  } diff --git a/host/utils/uhd_usrp_probe.cpp b/host/utils/uhd_usrp_probe.cpp index 097317516..8947034d7 100644 --- a/host/utils/uhd_usrp_probe.cpp +++ b/host/utils/uhd_usrp_probe.cpp @@ -18,6 +18,7 @@  #include <uhd/utils/safe_main.hpp>  #include <uhd/device.hpp>  #include <uhd/types/ranges.hpp> +#include <uhd/utils/algorithm.hpp>  #include <uhd/usrp/device_props.hpp>  #include <uhd/usrp/mboard_props.hpp>  #include <uhd/usrp/dboard_props.hpp> @@ -26,7 +27,6 @@  #include <uhd/usrp/subdev_props.hpp>  #include <uhd/usrp/dboard_id.hpp>  #include <boost/program_options.hpp> -#include <boost/algorithm/string.hpp>  #include <boost/format.hpp>  #include <boost/foreach.hpp>  #include <iostream> @@ -43,7 +43,7 @@ static std::string make_border(const std::string &text){      std::stringstream ss;      ss << boost::format("  _____________________________________________________") << std::endl;      ss << boost::format(" /") << std::endl; -    std::vector<std::string> lines; boost::split(lines, text, boost::is_any_of("\n")); +    std::vector<std::string> lines = std::split_string(text, "\n");      while (lines.back() == "") lines.pop_back(); //strip trailing newlines      if (lines.size()) lines[0] = "    " + lines[0]; //indent the title line      BOOST_FOREACH(const std::string &line, lines){ | 
