diff options
Diffstat (limited to 'host/lib/usrp/cores')
| -rw-r--r-- | host/lib/usrp/cores/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | host/lib/usrp/cores/gpio_atr_3000.cpp | 214 | ||||
| -rw-r--r-- | host/lib/usrp/cores/gpio_atr_3000.hpp | 168 | ||||
| -rw-r--r-- | host/lib/usrp/cores/gpio_core_200.cpp | 24 | ||||
| -rw-r--r-- | host/lib/usrp/cores/gpio_core_200.hpp | 23 | 
5 files changed, 396 insertions, 34 deletions
diff --git a/host/lib/usrp/cores/CMakeLists.txt b/host/lib/usrp/cores/CMakeLists.txt index f28ae040f..909c02941 100644 --- a/host/lib/usrp/cores/CMakeLists.txt +++ b/host/lib/usrp/cores/CMakeLists.txt @@ -40,4 +40,5 @@ LIBUHD_APPEND_SOURCES(      ${CMAKE_CURRENT_SOURCE_DIR}/rx_dsp_core_3000.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/tx_dsp_core_3000.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/radio_ctrl_core_3000.cpp +    ${CMAKE_CURRENT_SOURCE_DIR}/gpio_atr_3000.cpp  ) diff --git a/host/lib/usrp/cores/gpio_atr_3000.cpp b/host/lib/usrp/cores/gpio_atr_3000.cpp new file mode 100644 index 000000000..d067dc590 --- /dev/null +++ b/host/lib/usrp/cores/gpio_atr_3000.cpp @@ -0,0 +1,214 @@ +// +// Copyright 2011,2014 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 "gpio_atr_3000.hpp" +#include <uhd/types/dict.hpp> +#include <uhd/utils/soft_register.hpp> + +using namespace uhd; +using namespace usrp; + +//------------------------------------------------------------- +// gpio_atr_3000 +//------------------------------------------------------------- + +#define REG_ATR_IDLE_OFFSET     (base + 0) +#define REG_ATR_RX_OFFSET       (base + 4) +#define REG_ATR_TX_OFFSET       (base + 8) +#define REG_ATR_FDX_OFFSET      (base + 12) +#define REG_DDR_OFFSET          (base + 16) +#define REG_ATR_DISABLE_OFFSET  (base + 20) + +namespace uhd { namespace usrp { namespace gpio_atr { + +class gpio_atr_3000_impl : public gpio_atr_3000{ +public: +    gpio_atr_3000_impl( +        wb_iface::sptr iface, +        const wb_iface::wb_addr_type base, +        const wb_iface::wb_addr_type rb_addr = 0xFFFFFFFF +    ): +        _iface(iface), _rb_addr(rb_addr), +        _atr_idle_reg(REG_ATR_IDLE_OFFSET), +        _atr_rx_reg(REG_ATR_RX_OFFSET), +        _atr_tx_reg(REG_ATR_TX_OFFSET), +        _atr_fdx_reg(REG_ATR_FDX_OFFSET), +        _ddr_reg(REG_DDR_OFFSET), +        _atr_disable_reg(REG_ATR_DISABLE_OFFSET) +    { +        _atr_idle_reg.initialize(*_iface, true); +        _atr_rx_reg.initialize(*_iface, true); +        _atr_tx_reg.initialize(*_iface, true); +        _atr_fdx_reg.initialize(*_iface, true); +        _ddr_reg.initialize(*_iface, true); +        _atr_disable_reg.initialize(*_iface, true); +    } + +    virtual void set_atr_mode(const gpio_atr_mode_t mode, const boost::uint32_t mask) +    { +        _atr_disable_reg.set_with_mask((mode==MODE_ATR)?0:0xFFFFFFFF, mask); +        _atr_disable_reg.flush(); +    } + +    virtual void set_gpio_ddr(const gpio_ddr_t dir, const boost::uint32_t mask) +    { +        _ddr_reg.set_with_mask((dir==DDR_INPUT)?0:0xFFFFFFFF, mask); +        _ddr_reg.flush(); +    } + +    virtual void set_atr_reg(const gpio_atr_reg_t atr, const boost::uint32_t value, const boost::uint32_t mask) +    { +        masked_reg_t* reg = NULL; +        switch (atr) { +            case ATR_REG_IDLE:          reg = &_atr_idle_reg; break; +            case ATR_REG_RX_ONLY:       reg = &_atr_rx_reg;   break; +            case ATR_REG_TX_ONLY:       reg = &_atr_tx_reg;   break; +            case ATR_REG_FULL_DUPLEX:   reg = &_atr_fdx_reg;  break; +            default:                    reg = &_atr_idle_reg; break; +        } +        reg->set_with_mask(value, mask); +        reg->flush(); +    } + +    virtual boost::uint32_t read_gpio() +    { +        if (_rb_addr != 0xFFFFFFFF) { +            return _iface->peek32(_rb_addr); +        } else { +            throw uhd::runtime_error("read_gpio not supported for write-only interface."); +        } +    } + +    virtual void set_gpio_attr(const gpio_attr_t attr, const boost::uint32_t value) +    { +        switch (attr) +        { +        case GPIO_CTRL: +            set_atr_mode(MODE_ATR, value); +            set_atr_mode(MODE_GPIO, ~value); +            break; +        case GPIO_DDR: +            set_gpio_ddr(DDR_OUTPUT, value); +            set_gpio_ddr(DDR_INPUT, ~value); +            break; +        case GPIO_OUT: +            set_atr_reg(ATR_REG_IDLE, value, _atr_disable_reg.get(masked_reg_t::REGISTER)); +            break; +        case GPIO_ATR_0X: +            set_atr_reg(ATR_REG_IDLE, value, ~_atr_disable_reg.get(masked_reg_t::REGISTER)); +            break; +        case GPIO_ATR_RX: +            set_atr_reg(ATR_REG_RX_ONLY, value, ~_atr_disable_reg.get(masked_reg_t::REGISTER)); +            break; +        case GPIO_ATR_TX: +            set_atr_reg(ATR_REG_TX_ONLY, value, ~_atr_disable_reg.get(masked_reg_t::REGISTER)); +            break; +        case GPIO_ATR_XX: +            set_atr_reg(ATR_REG_FULL_DUPLEX, value, ~_atr_disable_reg.get(masked_reg_t::REGISTER)); +            break; +        default: +            UHD_THROW_INVALID_CODE_PATH(); +        } +    } + +protected: +    class masked_reg_t : public uhd::soft_reg32_wo_t { +    public: +        masked_reg_t(const wb_iface::wb_addr_type offset): uhd::soft_reg32_wo_t(offset) { +            set(REGISTER, 0); +        } + +        inline void set_with_mask(const boost::uint32_t value, const boost::uint32_t mask) { +            set(REGISTER, (value&mask)|(get(REGISTER)&(~mask))); +        } +    }; + +    wb_iface::sptr          _iface; +    wb_iface::wb_addr_type  _rb_addr; +    masked_reg_t            _atr_idle_reg; +    masked_reg_t            _atr_rx_reg; +    masked_reg_t            _atr_tx_reg; +    masked_reg_t            _atr_fdx_reg; +    masked_reg_t            _ddr_reg; +    masked_reg_t            _atr_disable_reg; +}; + +gpio_atr_3000::sptr gpio_atr_3000::make(wb_iface::sptr iface, const size_t base, const size_t rb_addr) { +    return sptr(new gpio_atr_3000_impl(iface, base, rb_addr)); +} + +gpio_atr_3000::sptr gpio_atr_3000::make_write_only(wb_iface::sptr iface, const size_t base) { +    gpio_atr_3000::sptr gpio_iface(new gpio_atr_3000_impl(iface, base)); +    gpio_iface->set_gpio_ddr(DDR_OUTPUT, 0xFFFFFFFF); +    return gpio_iface; +} + +//------------------------------------------------------------- +// db_gpio_atr_3000 +//------------------------------------------------------------- + +class db_gpio_atr_3000_impl : public gpio_atr_3000_impl, public db_gpio_atr_3000 { +public: +    db_gpio_atr_3000_impl(wb_iface::sptr iface, const wb_iface::wb_addr_type base, const wb_iface::wb_addr_type rb_addr): +        gpio_atr_3000_impl(iface, base, rb_addr) { /* NOP */ } + +    inline void set_pin_ctrl(const db_unit_t unit, const boost::uint16_t value) +    { +        gpio_atr_3000_impl::set_atr_mode(MODE_ATR,  compute_mask(unit, value)); +        gpio_atr_3000_impl::set_atr_mode(MODE_GPIO, compute_mask(unit, ~value)); +    } + +    inline void set_gpio_ddr(const db_unit_t unit, const boost::uint16_t value) +    { +        gpio_atr_3000_impl::set_gpio_ddr(DDR_OUTPUT, compute_mask(unit, value)); +        gpio_atr_3000_impl::set_gpio_ddr(DDR_INPUT,  compute_mask(unit, ~value)); +    } + +    inline void set_atr_reg(const db_unit_t unit, const gpio_atr_reg_t atr, const boost::uint16_t value) +    { +        gpio_atr_3000_impl::set_atr_reg(atr, +            static_cast<boost::uint32_t>(value) << compute_shift(unit), +            compute_mask(unit, ~(_atr_disable_reg.get(masked_reg_t::REGISTER)))); +    } + +    inline void set_gpio_out(const db_unit_t unit, const boost::uint16_t value) +    { +        gpio_atr_3000_impl::set_atr_reg(ATR_REG_IDLE, +            static_cast<boost::uint32_t>(value) << compute_shift(unit), +            compute_mask(unit, _atr_disable_reg.get(masked_reg_t::REGISTER))); +    } + +    inline boost::uint16_t read_gpio(const db_unit_t unit) +    { +        return boost::uint16_t(gpio_atr_3000_impl::read_gpio() >> compute_shift(unit)); +    } + +private: +    inline boost::uint32_t compute_shift(const db_unit_t unit) { +        return (unit == dboard_iface::UNIT_RX) ? 0 : 16; +    } + +    inline boost::uint32_t compute_mask(const db_unit_t unit, const boost::uint16_t mask) { +        return static_cast<boost::uint32_t>(mask) << (compute_shift(unit)); +    } +}; + +db_gpio_atr_3000::sptr db_gpio_atr_3000::make(wb_iface::sptr iface, const size_t base, const size_t rb_addr) { +    return sptr(new db_gpio_atr_3000_impl(iface, base, rb_addr)); +} + +}}} diff --git a/host/lib/usrp/cores/gpio_atr_3000.hpp b/host/lib/usrp/cores/gpio_atr_3000.hpp new file mode 100644 index 000000000..b9e5168d9 --- /dev/null +++ b/host/lib/usrp/cores/gpio_atr_3000.hpp @@ -0,0 +1,168 @@ +// +// Copyright 2011,2014,2015 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_GPIO_CORE_3000_HPP +#define INCLUDED_LIBUHD_USRP_GPIO_CORE_3000_HPP + +#include <uhd/config.hpp> +#include <uhd/usrp/dboard_iface.hpp> +#include <uhd/usrp/gpio_defs.hpp> +#include <boost/shared_ptr.hpp> +#include <uhd/types/wb_iface.hpp> + +namespace uhd { namespace usrp { namespace gpio_atr { + +class gpio_atr_3000 : boost::noncopyable { +public: +    typedef boost::shared_ptr<gpio_atr_3000> sptr; + +    virtual ~gpio_atr_3000(void) {}; + +    /*! +     * Create a read-write GPIO ATR interface object +     * +     * \param iface register iface to GPIO ATR registers +     * \param base base settings offset for GPIO ATR registers +     * \param base readback offset for GPIO ATR registers +     */ +    static sptr make(uhd::wb_iface::sptr iface, const size_t base, const size_t rb_addr); + +    /*! +     * Create a write-only GPIO ATR interface object +     * +     * \param iface register iface to GPIO ATR registers +     * \param base base settings offset for GPIO ATR registers +     */ +    static sptr make_write_only(uhd::wb_iface::sptr iface, const size_t base); + +    /*! +     * Select the ATR mode for all bits in the mask +     * +     * \param mode the mode to apply {ATR = outputs driven by ATR state machine, GPIO = outputs static} +     * \param mask apply the mode to all non-zero bits in the mask +     */ +    virtual void set_atr_mode(const gpio_atr_mode_t mode, const boost::uint32_t mask) = 0; + +    /*! +     * Select the data direction for all bits in the mask +     * +     * \param dir the direction {OUTPUT, INPUT} +     * \param mask apply the mode to all non-zero bits in the mask +     */ +    virtual void set_gpio_ddr(const gpio_ddr_t dir, const boost::uint32_t mask) = 0; + +    /*! +     * Write the specified (masked) value to the ATR register +     * +     * \param atr the type of ATR register to write to {IDLE, RX, TX, FDX} +     * \param value the value to write +     * \param mask only writes to the bits where mask is non-zero +     */ +    virtual void set_atr_reg(const gpio_atr_reg_t atr, const boost::uint32_t value, const boost::uint32_t mask = 0xFFFFFFFF) = 0; + +    /*! +     * Write to a static GPIO output +     * +     * \param value the value to write +     * \param mask only writes to the bits where mask is non-zero +     */ +    inline void set_gpio_out(const boost::uint32_t value, const boost::uint32_t mask = 0xFFFFFFFF) { +        set_atr_reg(ATR_REG_IDLE, value, mask); +    } + +    /*! +     * Read the state of the GPIO pins +     * If a pin is configured as an input, reads the actual value of the pin +     * If a pin is configured as an output, reads the last value written to the pin +     * +     * \return the value read back +     */ +    virtual boost::uint32_t read_gpio() = 0; + +    /*! +     * Set a GPIO attribute +     * +     * \param attr the attribute to set +     * \param value the value to write to the attribute +     */ +    virtual void set_gpio_attr(const gpio_attr_t attr, const boost::uint32_t value) = 0; +}; + +class db_gpio_atr_3000 { +public: +    typedef boost::shared_ptr<db_gpio_atr_3000> sptr; + +    typedef uhd::usrp::dboard_iface::unit_t db_unit_t; + +    virtual ~db_gpio_atr_3000(void) {}; + +    /*! +     * Create a read-write GPIO ATR interface object for a daughterboard connector +     * +     * \param iface register iface to GPIO ATR registers +     * \param base base settings offset for GPIO ATR registers +     * \param base readback offset for GPIO ATR registers +     */ +    static sptr make(uhd::wb_iface::sptr iface, const size_t base, const size_t rb_addr); + +    /*! +     * Configure the GPIO mode for all pins in the daughterboard connector +     * +     * \param unit the side of the daughterboard interface to configure (TX or RX) +     * \param value if value[i] is 1, the i'th bit is in ATR mode otherwise it is in GPIO mode +     */ +    virtual void set_pin_ctrl(const db_unit_t unit, const boost::uint16_t value) = 0; + +    /*! +     * Configure the direction for all pins in the daughterboard connector +     * +     * \param unit the side of the daughterboard interface to configure (TX or RX) +     * \param value if value[i] is 1, the i'th bit is an output otherwise it is an input +     */ +    virtual void set_gpio_ddr(const db_unit_t unit, const boost::uint16_t value) = 0; + +    /*! +     * Write the specified value to the ATR register (all bits) +     * +     * \param atr the type of ATR register to write to {IDLE, RX, TX, FDX} +     * \param unit the side of the daughterboard interface to configure (TX or RX) +     * \param value the value to write +     */ +    virtual void set_atr_reg(const db_unit_t unit, const gpio_atr_reg_t atr, const boost::uint16_t value) = 0; + +    /*! +     * Write the specified value to the GPIO register (all bits) +     * +     * \param atr the type of ATR register to write to {IDLE, RX, TX, FDX} +     * \param value the value to write +     */ +    virtual void set_gpio_out(const db_unit_t unit, const boost::uint16_t value) = 0; + +    /*! +     * Read the state of the GPIO pins +     * If a pin is configured as an input, reads the actual value of the pin +     * If a pin is configured as an output, reads the last value written to the pin +     * +     * \param unit the side of the daughterboard interface to configure (TX or RX) +     * \return the value read back +     */ +    virtual boost::uint16_t read_gpio(const db_unit_t unit) = 0; +}; + +}}} //namespaces + +#endif /* INCLUDED_LIBUHD_USRP_GPIO_CORE_3000_HPP */ diff --git a/host/lib/usrp/cores/gpio_core_200.cpp b/host/lib/usrp/cores/gpio_core_200.cpp index 4f1c25a0b..05a689845 100644 --- a/host/lib/usrp/cores/gpio_core_200.cpp +++ b/host/lib/usrp/cores/gpio_core_200.cpp @@ -77,10 +77,10 @@ private:      }      void update(void){ -        this->update(dboard_iface::ATR_REG_IDLE, REG_GPIO_IDLE); -        this->update(dboard_iface::ATR_REG_TX_ONLY, REG_GPIO_TX_ONLY); -        this->update(dboard_iface::ATR_REG_RX_ONLY, REG_GPIO_RX_ONLY); -        this->update(dboard_iface::ATR_REG_FULL_DUPLEX, REG_GPIO_BOTH); +        this->update(gpio_atr::ATR_REG_IDLE, REG_GPIO_IDLE); +        this->update(gpio_atr::ATR_REG_TX_ONLY, REG_GPIO_TX_ONLY); +        this->update(gpio_atr::ATR_REG_RX_ONLY, REG_GPIO_RX_ONLY); +        this->update(gpio_atr::ATR_REG_FULL_DUPLEX, REG_GPIO_BOTH);      }      void update(const atr_reg_t atr, const size_t addr){ @@ -122,17 +122,17 @@ public:      }      void set_atr_reg(const atr_reg_t atr, const boost::uint32_t value){ -        if (atr == dboard_iface::ATR_REG_IDLE)        _iface->poke32(REG_GPIO_IDLE, value); -        if (atr == dboard_iface::ATR_REG_TX_ONLY)     _iface->poke32(REG_GPIO_TX_ONLY, value); -        if (atr == dboard_iface::ATR_REG_RX_ONLY)     _iface->poke32(REG_GPIO_RX_ONLY, value); -        if (atr == dboard_iface::ATR_REG_FULL_DUPLEX) _iface->poke32(REG_GPIO_BOTH, value); +        if (atr == gpio_atr::ATR_REG_IDLE)        _iface->poke32(REG_GPIO_IDLE, value); +        if (atr == gpio_atr::ATR_REG_TX_ONLY)     _iface->poke32(REG_GPIO_TX_ONLY, value); +        if (atr == gpio_atr::ATR_REG_RX_ONLY)     _iface->poke32(REG_GPIO_RX_ONLY, value); +        if (atr == gpio_atr::ATR_REG_FULL_DUPLEX) _iface->poke32(REG_GPIO_BOTH, value);      }      void set_all_regs(const boost::uint32_t value){ -        this->set_atr_reg(dboard_iface::ATR_REG_IDLE,        value); -        this->set_atr_reg(dboard_iface::ATR_REG_TX_ONLY,     value); -        this->set_atr_reg(dboard_iface::ATR_REG_RX_ONLY,     value); -        this->set_atr_reg(dboard_iface::ATR_REG_FULL_DUPLEX, value); +        this->set_atr_reg(gpio_atr::ATR_REG_IDLE,        value); +        this->set_atr_reg(gpio_atr::ATR_REG_TX_ONLY,     value); +        this->set_atr_reg(gpio_atr::ATR_REG_RX_ONLY,     value); +        this->set_atr_reg(gpio_atr::ATR_REG_FULL_DUPLEX, value);      }  private: diff --git a/host/lib/usrp/cores/gpio_core_200.hpp b/host/lib/usrp/cores/gpio_core_200.hpp index e22834fd9..c60507792 100644 --- a/host/lib/usrp/cores/gpio_core_200.hpp +++ b/host/lib/usrp/cores/gpio_core_200.hpp @@ -20,6 +20,7 @@  #include <uhd/config.hpp>  #include <uhd/usrp/dboard_iface.hpp> +#include <uhd/usrp/gpio_defs.hpp>  #include <boost/assign.hpp>  #include <boost/cstdint.hpp>  #include <boost/utility.hpp> @@ -27,28 +28,6 @@  #include <uhd/types/wb_iface.hpp>  #include <map> -typedef enum { -    GPIO_CTRL, -    GPIO_DDR, -    GPIO_OUT, -    GPIO_ATR_0X, -    GPIO_ATR_RX, -    GPIO_ATR_TX, -    GPIO_ATR_XX -} gpio_attr_t; - -typedef std::map<gpio_attr_t,std::string> gpio_attr_map_t; -static const gpio_attr_map_t gpio_attr_map = -    boost::assign::map_list_of -        (GPIO_CTRL,   "CTRL") -        (GPIO_DDR,    "DDR") -        (GPIO_OUT,    "OUT") -        (GPIO_ATR_0X, "ATR_0X") -        (GPIO_ATR_RX, "ATR_RX") -        (GPIO_ATR_TX, "ATR_TX") -        (GPIO_ATR_XX, "ATR_XX") -; -  class gpio_core_200 : boost::noncopyable{  public:      typedef boost::shared_ptr<gpio_core_200> sptr;  | 
