aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/types/serial.cpp
blob: 5d03d40cf79add06db3bf951b665e28a21a06453 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//
// Copyright 2011-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 <http://www.gnu.org/licenses/>.
//

#include <uhd/types/serial.hpp>
#include <boost/thread.hpp> //for sleeping
#include <boost/assign/list_of.hpp>

using namespace uhd;

i2c_iface::~i2c_iface(void)
{
    //empty
}

spi_iface::~spi_iface(void)
{
    //empty
}

uart_iface::~uart_iface(void)
{
    //empty
}

spi_config_t::spi_config_t(edge_t edge):
    mosi_edge(edge),
    miso_edge(edge)
{
    // By default don't use a custom clock speed for the transaction
    use_custom_divider = false;
}

void i2c_iface::write_eeprom(
    uint16_t addr,
    uint16_t offset,
    const byte_vector_t &bytes
){
    for (size_t i = 0; i < bytes.size(); i++){
        //write a byte at a time, its easy that way
        byte_vector_t cmd = boost::assign::list_of(offset+i)(bytes[i]);
        this->write_i2c(addr, cmd);
        boost::this_thread::sleep(boost::posix_time::milliseconds(10)); //worst case write
    }
}

byte_vector_t i2c_iface::read_eeprom(
    uint16_t addr,
    uint16_t offset,
    size_t num_bytes
){
    byte_vector_t bytes;
    for (size_t i = 0; i < num_bytes; i++){
        //do a zero byte write to start read cycle
        this->write_i2c(addr, byte_vector_t(1, offset+i));
        bytes.push_back(this->read_i2c(addr, 1).at(0));
    }
    return bytes;
}

struct eeprom16_impl : i2c_iface
{
    eeprom16_impl(i2c_iface* internal)
    {
        _internal = internal;
    }
    i2c_iface* _internal;

    byte_vector_t read_i2c(
        uint16_t addr,
        size_t num_bytes
    ){
        return _internal->read_i2c(addr, num_bytes);
    }

    void write_i2c(
        uint16_t addr,
        const byte_vector_t &bytes
    ){
        return _internal->write_i2c(addr, bytes);
    }

    byte_vector_t read_eeprom(
        uint16_t addr,
        uint16_t offset,
        size_t num_bytes
    ){
        byte_vector_t cmd = boost::assign::list_of(offset >> 8)(offset & 0xff);
        this->write_i2c(addr, cmd);
        return this->read_i2c(addr, num_bytes);
    }

    void write_eeprom(
        uint16_t addr,
        uint16_t offset,
        const byte_vector_t &bytes
    ){
        for (size_t i = 0; i < bytes.size(); i++)
        {
            //write a byte at a time, its easy that way
            uint16_t offset_i = offset+i;
            byte_vector_t cmd = boost::assign::list_of(offset_i >> 8)(offset_i & 0xff)(bytes[i]);
            this->write_i2c(addr, cmd);
            boost::this_thread::sleep(boost::posix_time::milliseconds(10)); //worst case write
        }
    }
};

i2c_iface::sptr i2c_iface::eeprom16(void)
{
    return i2c_iface::sptr(new eeprom16_impl(this));
}

uint32_t spi_iface::read_spi(
    int which_slave,
    const spi_config_t &config,
    uint32_t data,
    size_t num_bits
){
    return transact_spi(
        which_slave, config, data, num_bits, true
    );
}

void spi_iface::write_spi(
    int which_slave,
    const spi_config_t &config,
    uint32_t data,
    size_t num_bits
){
    transact_spi(
        which_slave, config, data, num_bits, false
    );
}