//
// Copyright 2013 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 .
//
#include "x300_impl.hpp"
#include
#include "x300_regs.hpp"
#include
#include
#include
#include
#include
#include
using namespace uhd;
struct x300_uart_iface : uart_iface
{
x300_uart_iface(wb_iface::sptr iface):
rxoffset(0), txoffset(0), txword32(0), rxpool(0), txpool(0), poolsize(0)
{
_iface = iface;
rxoffset = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_RX_INDEX));
txoffset = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_TX_INDEX));
rxpool = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_RX_ADDR));
txpool = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_TX_ADDR));
poolsize = _iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_WORDS32));
//this->write_uart("HELLO UART\n");
//this->read_uart(0.1);
}
void putchar(const char ch)
{
txoffset = (txoffset + 1) % (poolsize*4);
const int shift = ((txoffset%4) * 8);
if (shift == 0) txword32 = 0;
txword32 |= boost::uint32_t(ch) << shift;
_iface->poke32(SR_ADDR(txpool, txoffset/4), txword32);
_iface->poke32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_TX_INDEX), txoffset);
}
void write_uart(const std::string &buff)
{
BOOST_FOREACH(const char ch, buff)
{
if (ch == '\n') this->putchar('\r');
this->putchar(ch);
}
}
int getchar(void)
{
if (_iface->peek32(SR_ADDR(X300_FW_SHMEM_BASE, X300_FW_SHMEM_UART_RX_INDEX)) != rxoffset)
{
const int shift = ((rxoffset%4) * 8);
const char ch = _iface->peek32(SR_ADDR(rxpool, rxoffset/4)) >> shift;
rxoffset = (rxoffset + 1) % (poolsize*4);
return ch;
}
return -1;
}
std::string read_uart(double timeout)
{
const boost::system_time exit_time = boost::get_system_time() + boost::posix_time::microseconds(long(timeout*1e6));
std::string buff;
while (true)
{
const int ch = this->getchar();
if (ch == -1)
{
if (boost::get_system_time() > exit_time) break;
boost::this_thread::sleep(boost::posix_time::milliseconds(1));
continue;
}
if (ch == '\r') continue;
buff += std::string(1, (char)ch);
if (ch == '\n') break;
}
//UHD_VAR(buff);
return buff;
}
wb_iface::sptr _iface;
boost::uint32_t rxoffset, txoffset, txword32, rxpool, txpool, poolsize;
};
uart_iface::sptr x300_make_uart_iface(wb_iface::sptr iface)
{
return uart_iface::sptr(new x300_uart_iface(iface));
}