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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
//
// 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/gain_handler.hpp>
#include <uhd/utils.hpp>
#include <uhd/props.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <vector>
using namespace uhd;
/***********************************************************************
* helper functions
**********************************************************************/
static gain_t gain_max(gain_t a, gain_t b){
return std::max(a, b);
}
static gain_t gain_sum(gain_t a, gain_t b){
return std::sum(a, b);
}
/***********************************************************************
* gain handler implementation interface
**********************************************************************/
class gain_handler_impl : public gain_handler{
public:
gain_handler_impl(
const wax::obj &link,
const gain_props_t &gain_props,
is_equal_t is_equal
);
~gain_handler_impl(void);
bool intercept_get(const wax::obj &key, wax::obj &val);
bool intercept_set(const wax::obj &key, const wax::obj &val);
private:
wax::obj _link;
gain_props_t _gain_props;
is_equal_t _is_equal;
prop_names_t get_gain_names(void);
std::vector<gain_t> get_gains(const wax::obj &prop_key);
gain_t get_overall_gain_val(void);
gain_t get_overall_gain_min(void);
gain_t get_overall_gain_max(void);
gain_t get_overall_gain_step(void);
};
/***********************************************************************
* the make function
**********************************************************************/
gain_handler::sptr gain_handler::make(
const wax::obj &link,
const gain_props_t &gain_props,
is_equal_t is_equal
){
return sptr(new gain_handler_impl(link, gain_props, is_equal));
}
/***********************************************************************
* gain handler implementation methods
**********************************************************************/
gain_handler::gain_props_t::gain_props_t(void){
/* NOP */
}
gain_handler_impl::gain_handler_impl(
const wax::obj &link,
const gain_props_t &gain_props,
is_equal_t is_equal
){
_link = link;
_gain_props = gain_props;
_is_equal = is_equal;
}
gain_handler_impl::~gain_handler_impl(void){
/* NOP */
}
prop_names_t gain_handler_impl::get_gain_names(void){
return wax::cast<prop_names_t>(_link[_gain_props.gain_names_prop]);
}
std::vector<gain_t> gain_handler_impl::get_gains(const wax::obj &prop_key){
std::vector<gain_t> gains;
BOOST_FOREACH(std::string name, get_gain_names()){
gains.push_back(wax::cast<gain_t>(_link[named_prop_t(prop_key, name)]));
}
return gains;
}
gain_t gain_handler_impl::get_overall_gain_val(void){
return std::reduce<gain_t>(get_gains(_gain_props.gain_val_prop), gain_sum);
}
gain_t gain_handler_impl::get_overall_gain_min(void){
return std::reduce<gain_t>(get_gains(_gain_props.gain_min_prop), gain_sum);
}
gain_t gain_handler_impl::get_overall_gain_max(void){
return std::reduce<gain_t>(get_gains(_gain_props.gain_max_prop), gain_sum);
}
gain_t gain_handler_impl::get_overall_gain_step(void){
return std::reduce<gain_t>(get_gains(_gain_props.gain_step_prop), gain_max);
}
/***********************************************************************
* gain handler implementation get method
**********************************************************************/
bool gain_handler_impl::intercept_get(const wax::obj &key_, wax::obj &val){
wax::obj key; std::string name;
boost::tie(key, name) = extract_named_prop(key_);
//not a wildcard... dont handle (but check name)
if (name != ""){
assert_has(get_gain_names(), name, "gain name");
return false;
}
if (_is_equal(key, _gain_props.gain_val_prop)){
val = get_overall_gain_val();
return true;
}
if (_is_equal(key, _gain_props.gain_min_prop)){
val = get_overall_gain_min();
return true;
}
if (_is_equal(key, _gain_props.gain_max_prop)){
val = get_overall_gain_max();
return true;
}
if (_is_equal(key, _gain_props.gain_step_prop)){
val = get_overall_gain_step();
return true;
}
return false; //not handled
}
/***********************************************************************
* gain handler implementation set method
**********************************************************************/
bool gain_handler_impl::intercept_set(const wax::obj &key_, const wax::obj &val){
wax::obj key; std::string name;
boost::tie(key, name) = extract_named_prop(key_);
//not a gain value key... dont handle
if (not _is_equal(key, _gain_props.gain_val_prop)) return false;
gain_t gain_val = wax::cast<gain_t>(val);
//not a wildcard... dont handle (but check name and range)
if (name != ""){
assert_has(get_gain_names(), name, "gain name");
gain_t gain_min = wax::cast<gain_t>(_link[named_prop_t(_gain_props.gain_min_prop, name)]);
gain_t gain_max = wax::cast<gain_t>(_link[named_prop_t(_gain_props.gain_max_prop, name)]);
if (gain_val > gain_max or gain_val < gain_min) throw std::range_error(str(
boost::format("A value of %f for gain %s is out of range of (%f, %f)")
% gain_val % name % gain_min % gain_max
));
return false;
}
//set the overall gain
BOOST_FOREACH(std::string name, get_gain_names()){
//get the min, max, step for this gain name
gain_t gain_min = wax::cast<gain_t>(_link[named_prop_t(_gain_props.gain_min_prop, name)]);
gain_t gain_max = wax::cast<gain_t>(_link[named_prop_t(_gain_props.gain_max_prop, name)]);
gain_t gain_step = wax::cast<gain_t>(_link[named_prop_t(_gain_props.gain_step_prop, name)]);
//clip g to be within the allowed range
gain_t g = std::min(std::max(gain_val, gain_min), gain_max);
//set g to be a multiple of the step size
g -= fmod(g, gain_step);
//set g to be the new gain
_link[named_prop_t(_gain_props.gain_val_prop, name)] = g;
//subtract g out of the total gain left to apply
gain_val -= g;
}
return true;
}
|