aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/e100/e100_ctrl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp/e100/e100_ctrl.cpp')
-rw-r--r--host/lib/usrp/e100/e100_ctrl.cpp166
1 files changed, 129 insertions, 37 deletions
diff --git a/host/lib/usrp/e100/e100_ctrl.cpp b/host/lib/usrp/e100/e100_ctrl.cpp
index eb529c9c1..5a9b93633 100644
--- a/host/lib/usrp/e100/e100_ctrl.cpp
+++ b/host/lib/usrp/e100/e100_ctrl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2011 Ettus Research LLC
+// Copyright 2011-2012 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
@@ -23,13 +23,16 @@
#include <sys/ioctl.h> //ioctl
#include <fcntl.h> //open, close
#include <linux/usrp_e.h> //ioctl structures and constants
+#include <poll.h> //poll
#include <boost/thread/thread.hpp> //sleep
#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <fstream>
using namespace uhd;
+using namespace uhd::transport;
/***********************************************************************
* Sysfs GPIO wrapper class
@@ -71,6 +74,11 @@ private:
};
/***********************************************************************
+ * Protection for dual GPIO access - sometimes MISO, sometimes have resp
+ **********************************************************************/
+static boost::mutex gpio_irq_resp_mutex;
+
+/***********************************************************************
* Aux spi implementation
**********************************************************************/
class aux_spi_iface_impl : public spi_iface{
@@ -87,6 +95,8 @@ public:
size_t num_bits,
bool readback
){
+ boost::mutex::scoped_lock lock(gpio_irq_resp_mutex);
+
boost::uint32_t rb_bits = 0;
this->spi_sen_gpio(0);
@@ -244,6 +254,57 @@ uhd::uart_iface::sptr e100_ctrl::make_gps_uart_iface(const std::string &node){
}
/***********************************************************************
+ * Simple managed buffers
+ **********************************************************************/
+struct e100_simpl_mrb : managed_recv_buffer
+{
+ usrp_e_ctl32 data;
+ e100_ctrl *ctrl;
+
+ void release(void)
+ {
+ //NOP
+ }
+
+ sptr get_new(void)
+ {
+ const size_t max_words32 = 8; //.LAST_ADDR(10'h00f)) resp_fifo_to_gpmc
+
+ //load the data struct
+ data.offset = 0;
+ data.count = max_words32;
+
+ //call the ioctl
+ ctrl->ioctl(USRP_E_READ_CTL32, &data);
+
+ if (data.buf[0] == 0 or ~data.buf[0] == 0) return sptr(); //bad VRT hdr, treat like timeout
+
+ return make(this, data.buf, sizeof(data.buf));
+ }
+};
+
+struct e100_simpl_msb : managed_send_buffer
+{
+ usrp_e_ctl32 data;
+ e100_ctrl *ctrl;
+
+ void release(void)
+ {
+ //load the data struct
+ data.offset = 0;
+ data.count = size()/4+1/*1 for header offset*/;
+
+ //call the ioctl
+ ctrl->ioctl(USRP_E_WRITE_CTL32, &data);
+ }
+
+ sptr get_new(void)
+ {
+ return make(this, data.buf+1, sizeof(data.buf)-4);
+ }
+};
+
+/***********************************************************************
* USRP-E100 control implementation
**********************************************************************/
class e100_ctrl_impl : public e100_ctrl{
@@ -273,11 +334,24 @@ public:
) % USRP_E_COMPAT_NUMBER % module_compat_num));
}
- //perform a global reset after opening
- this->poke32(E100_REG_GLOBAL_RESET, 0);
+ //hit the magic arst condition
+ //async_reset <= ~EM_NCS6 && ~EM_NWE && (EM_A[9:2] == 8'hff) && EM_D[0];
+ usrp_e_ctl16 datax;
+ datax.offset = 0x3fc;
+ datax.count = 2;
+ datax.buf[0] = 1;
+ datax.buf[1] = 0;
+ this->ioctl(USRP_E_WRITE_CTL16, &datax);
+
+ std::ofstream edge_file("/sys/class/gpio/gpio147/edge");
+ edge_file << "rising" << std::endl << std::flush;
+ edge_file.close();
+ _irq_fd = ::open("/sys/class/gpio/gpio147/value", O_RDONLY);
+ if (_irq_fd < 0) UHD_MSG(error) << "Unable to open GPIO for IRQ\n";
}
~e100_ctrl_impl(void){
+ ::close(_irq_fd);
::close(_node_fd);
}
@@ -293,58 +367,76 @@ public:
));
}
}
+
/*******************************************************************
- * Peek and Poke
+ * The managed buffer interface
******************************************************************/
- void poke32(wb_addr_type addr, boost::uint32_t value){
- //load the data struct
- usrp_e_ctl32 data;
- data.offset = addr;
- data.count = 1;
- data.buf[0] = value;
-
- //call the ioctl
- this->ioctl(USRP_E_WRITE_CTL32, &data);
+ UHD_INLINE bool resp_read(void)
+ {
+ //thread stuff ensures that this GPIO isnt shared
+ boost::mutex::scoped_lock lock(gpio_irq_resp_mutex);
+
+ //perform a read of the GPIO IRQ state
+ char ch;
+ ::read(_irq_fd, &ch, sizeof(ch));
+ ::lseek(_irq_fd, SEEK_SET, 0);
+ return ch == '1';
}
- void poke16(wb_addr_type addr, boost::uint16_t value){
- //load the data struct
- usrp_e_ctl16 data;
- data.offset = addr;
- data.count = 1;
- data.buf[0] = value;
+ UHD_INLINE bool resp_wait(const double timeout)
+ {
+ //perform a check, if it fails, poll
+ if (this->resp_read()) return true;
- //call the ioctl
- this->ioctl(USRP_E_WRITE_CTL16, &data);
+ //poll IRQ GPIO for some action
+ pollfd pfd;
+ pfd.fd = _irq_fd;
+ pfd.events = POLLPRI | POLLERR;
+ ::poll(&pfd, 1, long(timeout*1000)/*ms*/);
+
+ //perform a GPIO read again for result
+ return this->resp_read();
}
- boost::uint32_t peek32(wb_addr_type addr){
- //load the data struct
- usrp_e_ctl32 data;
- data.offset = addr;
- data.count = 1;
+ managed_recv_buffer::sptr get_recv_buff(double timeout)
+ {
+ if (not this->resp_wait(timeout))
+ {
+ return managed_recv_buffer::sptr();
+ }
- //call the ioctl
- this->ioctl(USRP_E_READ_CTL32, &data);
+ _mrb.ctrl = this;
+ return _mrb.get_new();
+ }
- return data.buf[0];
+ managed_send_buffer::sptr get_send_buff(double)
+ {
+ _msb.ctrl = this;
+ return _msb.get_new();
}
- boost::uint16_t peek16(wb_addr_type addr){
- //load the data struct
- usrp_e_ctl16 data;
- data.offset = addr;
- data.count = 1;
+ size_t get_num_recv_frames(void) const{
+ return 1;
+ }
- //call the ioctl
- this->ioctl(USRP_E_READ_CTL16, &data);
+ size_t get_recv_frame_size(void) const{
+ return sizeof(_mrb.data.buf);
+ }
+
+ size_t get_num_send_frames(void) const{
+ return 1;
+ }
- return data.buf[0];
+ size_t get_send_frame_size(void) const{
+ return sizeof(_msb.data.buf);
}
private:
int _node_fd;
+ int _irq_fd;
boost::mutex _ioctl_mutex;
+ e100_simpl_mrb _mrb;
+ e100_simpl_msb _msb;
};
/***********************************************************************