mirror of
https://github.com/odriverobotics/ODrive.git
synced 2026-09-25 11:06:48 +08:00
make PWM/analog input work
This commit is contained in:
@@ -13,6 +13,8 @@
|
||||
#ifndef __FIBRE_INTERFACES_HPP
|
||||
#define __FIBRE_INTERFACES_HPP
|
||||
|
||||
#include <fibre/introspection.hpp>
|
||||
|
||||
namespace fibre {
|
||||
|
||||
const unsigned char embedded_json[] = [[embedded_endpoint_definitions | to_c_string]];
|
||||
@@ -48,22 +50,25 @@ bool is_endpoint_ref_valid(endpoint_ref_t endpoint_ref) {
|
||||
}
|
||||
}
|
||||
|
||||
Introspectable get_property(size_t idx) {
|
||||
switch (idx) {
|
||||
[%- for endpoint in endpoints %]
|
||||
[%- if endpoint.function.name == 'exchange' and endpoint.in_bindings | list == ['obj'] %][# //case [[endpoint.id]]: *(decltype([[endpoint.in_bindings['obj']]])*)buf = [[endpoint.in_bindings['obj']]]; break;#]
|
||||
case [[endpoint.id]]: return FibrePropertyTypeInfo<[[endpoint.function.in['obj'].type.c_type]]>::make_introspectable([[endpoint.in_bindings['obj']]]);
|
||||
[%- endif %]
|
||||
[%- endfor %]
|
||||
default: return {};
|
||||
}
|
||||
}
|
||||
|
||||
bool set_endpoint_from_float(endpoint_ref_t endpoint_ref, float value) {
|
||||
if (endpoint_ref.json_crc != json_crc_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
// TODO: implement
|
||||
/*cbufptr_t input_buffer{};
|
||||
bufptr_t output_buffer{};
|
||||
|
||||
switch (idx) {
|
||||
[%- for endpoint in endpoints %]
|
||||
case [[endpoint.id]]: return [[endpoint.function.fullname | to_snake_case]]([% for k, arg in endpoint.function.in.items() %][% if k in endpoint.in_bindings %]static_cast<[[arg.type.c_type]]>([[endpoint.in_bindings[k]]])[% else %]std::nullopt[% endif %], [% endfor %]&input_buffer, &output_buffer);
|
||||
[%- endfor %]
|
||||
default: return false;
|
||||
}*/
|
||||
Introspectable property = get_property(endpoint_ref.endpoint_id);
|
||||
const FloatSettableTypeInfo* type_info = dynamic_cast<const FloatSettableTypeInfo*>(property.get_type_info());
|
||||
return type_info && type_info->set_float(property, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -62,6 +62,8 @@ private:
|
||||
class Introspectable {
|
||||
friend class TypeInfo;
|
||||
public:
|
||||
Introspectable() {}
|
||||
|
||||
/**
|
||||
* @brief Returns an Introspectable object for the attribute referenced by
|
||||
* the specified attribute name.
|
||||
@@ -114,9 +116,11 @@ public:
|
||||
return type_info_ && type_info_->set_string(*this, buffer, length);
|
||||
}
|
||||
|
||||
private:
|
||||
Introspectable() {}
|
||||
const TypeInfo* get_type_info() {
|
||||
return type_info_;
|
||||
}
|
||||
|
||||
private:
|
||||
// We use this storage to hold generic small objects. Usually that's a pointer
|
||||
// but sometimes it's an on-demand constructed Property<...>.
|
||||
// Caution: only put objects in here which are trivially copyable, movable
|
||||
@@ -151,6 +155,10 @@ template<typename T> using maybe_underlying_type_t = typename maybe_underlying_t
|
||||
|
||||
|
||||
|
||||
struct FloatSettableTypeInfo {
|
||||
virtual bool set_float(const Introspectable& obj, float val) const { return false; }
|
||||
};
|
||||
|
||||
/* Built-in type infos ********************************************************/
|
||||
|
||||
template<typename T>
|
||||
@@ -175,10 +183,11 @@ const FibrePropertyTypeInfo<Property<const T>> FibrePropertyTypeInfo<Property<co
|
||||
|
||||
// readwrite property
|
||||
template<typename T>
|
||||
struct FibrePropertyTypeInfo<Property<T>> : TypeInfo {
|
||||
struct FibrePropertyTypeInfo<Property<T>> : FloatSettableTypeInfo, TypeInfo {
|
||||
using TypeInfo::TypeInfo;
|
||||
static const PropertyInfo property_table[];
|
||||
static const FibrePropertyTypeInfo<Property<T>> singleton;
|
||||
static const Introspectable make_introspectable(Property<T> obj) { return TypeInfo::make_introspectable(obj, &singleton); }
|
||||
|
||||
bool get_string(const Introspectable& obj, char* buffer, size_t length) const override {
|
||||
return to_string(static_cast<maybe_underlying_type_t<T>>(as<const Property<T>>(obj).read()), buffer, length, 0);
|
||||
@@ -192,6 +201,15 @@ struct FibrePropertyTypeInfo<Property<T>> : TypeInfo {
|
||||
as<const Property<T>>(obj).exchange(static_cast<T>(value));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool set_float(const Introspectable& obj, float val) const override {
|
||||
maybe_underlying_type_t<T> value;
|
||||
if (!conversion::set_from_float(val, &value)) {
|
||||
return false;
|
||||
}
|
||||
as<const Property<T>>(obj).exchange(static_cast<T>(value));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -397,6 +397,17 @@ struct Codec<T, std::enable_if_t<std::is_enum<T>::value>> {
|
||||
}
|
||||
static bool encode(T value, bufptr_t* buffer) { return SimpleSerializer<int32_t, false>::write(value, &(buffer->begin()), buffer->end()); }
|
||||
};
|
||||
template<> struct Codec<endpoint_ref_t> {
|
||||
static std::optional<endpoint_ref_t> decode(cbufptr_t* buffer) {
|
||||
std::optional<uint16_t> val0 = SimpleSerializer<uint16_t, false>::read(&(buffer->begin()), buffer->end());
|
||||
std::optional<uint16_t> val1 = SimpleSerializer<uint16_t, false>::read(&(buffer->begin()), buffer->end());
|
||||
return (val0.has_value() && val1.has_value()) ? std::make_optional(endpoint_ref_t{val1.value(), val0.value()}) : std::nullopt;
|
||||
}
|
||||
static bool encode(endpoint_ref_t value, bufptr_t* buffer) {
|
||||
return SimpleSerializer<uint16_t, false>::write(value.endpoint_id, &(buffer->begin()), buffer->end())
|
||||
&& SimpleSerializer<uint16_t, false>::write(value.json_crc, &(buffer->begin()), buffer->end());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -142,6 +142,7 @@ value_types = {
|
||||
'int16': {'builtin': True, 'fullname': 'int16', 'name': 'int16', 'c_type': 'int16_t'},
|
||||
'int32': {'builtin': True, 'fullname': 'int32', 'name': 'int32', 'c_type': 'int32_t'},
|
||||
'int64': {'builtin': True, 'fullname': 'int64', 'name': 'int64', 'c_type': 'int64_t'},
|
||||
'endpoint_ref': {'builtin': True, 'fullname': 'endpoint_ref', 'name': 'endpoint_ref', 'c_type': 'endpoint_ref_t'},
|
||||
}
|
||||
|
||||
enums = {}
|
||||
|
||||
@@ -140,12 +140,12 @@ interfaces:
|
||||
unit: A
|
||||
doc: Max current the power supply can sink. You most likely want a non-positive value here. Set to -INFINITY to disable.
|
||||
|
||||
#gpio1_pwm_mapping: Endpoint # TODO: disable for ODrive v3.2 and older
|
||||
#gpio2_pwm_mapping: Endpoint # TODO: disable for ODrive v3.2 and older
|
||||
#gpio3_pwm_mapping: Endpoint # TODO: disable for ODrive v3.2 and older
|
||||
#gpio4_pwm_mapping: Endpoint
|
||||
#gpio3_analog_mapping: Endpoint
|
||||
#gpio4_analog_mapping: Endpoint
|
||||
gpio1_pwm_mapping: {type: Endpoint, c_name: 'pwm_mappings[0]'} # TODO: disable for ODrive v3.2 and older
|
||||
gpio2_pwm_mapping: {type: Endpoint, c_name: 'pwm_mappings[1]'} # TODO: disable for ODrive v3.2 and older
|
||||
gpio3_pwm_mapping: {type: Endpoint, c_name: 'pwm_mappings[2]'} # TODO: disable for ODrive v3.2 and older
|
||||
gpio4_pwm_mapping: {type: Endpoint, c_name: 'pwm_mappings[3]'}
|
||||
gpio3_analog_mapping: {type: Endpoint, c_name: 'analog_mappings[0]'}
|
||||
gpio4_analog_mapping: {type: Endpoint, c_name: 'analog_mappings[1]'}
|
||||
user_config_loaded: readonly bool
|
||||
|
||||
axis0: {type: Axis, c_name: get_axis(0)}
|
||||
@@ -176,6 +176,13 @@ interfaces:
|
||||
functions:
|
||||
set_baud_rate: {in: {baudRate: uint32}}
|
||||
|
||||
Endpoint:
|
||||
c_is_class: False
|
||||
attributes:
|
||||
endpoint: endpoint_ref
|
||||
min: float32
|
||||
max: float32
|
||||
|
||||
Axis:
|
||||
c_is_class: True
|
||||
attributes:
|
||||
|
||||
Reference in New Issue
Block a user