Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
ServoConsumer.hxx
1#ifndef _OPENLCB_SERVOCONSUMER_HXX_
2#define _OPENLCB_SERVOCONSUMER_HXX_
3
4#if defined(ARDUINO) || defined(ESP_PLATFORM)
5#include "freertos_drivers/arduino/DummyGPIO.hxx"
6#include "freertos_drivers/arduino/PWM.hxx"
7#else
10#endif
11#include "openlcb/ServoConsumerConfig.hxx"
12#include "os/MmapGpio.hxx"
13#include <memory>
14
15namespace openlcb
16{
17
22{
23public:
24 ServoConsumer(Node *node, const ServoConsumerConfig &cfg,
25 const uint32_t pwmCountPerMs, PWM *pwm)
27 , pwmCountPerMs_(pwmCountPerMs)
28 , pwm_(pwm) // save for apply_config, where we actually use it.
29 , pwmGpo_(nullptr) // not initialized until apply_config
30 , gpioImpl_(node, 0, 0, DummyPinWithRead())
31 , consumer_(&gpioImpl_) // don't connect consumer to PWM yet
32 , cfg_(cfg)
33 {
34 }
35
37 int fd, bool initial_load, BarrierNotifiable *done) OVERRIDE
38 {
39 AutoNotify n(done);
40
41 const EventId cfg_event_min = cfg_.event_rotate_min().read(fd);
42 const EventId cfg_event_max = cfg_.event_rotate_max().read(fd);
43 const int16_t cfg_servo_min_pct = cfg_.servo_min_percent().read(fd);
44 const int16_t cfg_servo_max_pct = cfg_.servo_max_percent().read(fd);
45
46 // 1ms duty cycle
47 const uint32_t servo_ticks_0 = pwmCountPerMs_ * 1;
48 // 2ms duty cycle
49 const uint32_t servo_ticks_180 = pwmCountPerMs_ * 2;
50
51 // Use a weighted average to determine num ticks for max/min.
52 const uint32_t cfg_srv_ticks_min =
53 ((100 - cfg_servo_min_pct) * servo_ticks_0 +
54 cfg_servo_min_pct * servo_ticks_180) /
55 100;
56 const uint32_t cfg_srv_ticks_max =
57 ((100 - cfg_servo_max_pct) * servo_ticks_0 +
58 cfg_servo_max_pct * servo_ticks_180) /
59 100;
60
61 // Defaults to CLR at startup.
62 const bool was_set = pwmGpo_ && (pwmGpo_->read() == Gpio::SET);
63
64 if (!pwmGpo_ || //
65 cfg_event_min != gpioImpl_.event_off() ||
66 cfg_event_max != gpioImpl_.event_on() ||
67 cfg_srv_ticks_min != pwmGpo_->get_off_counts() ||
68 cfg_srv_ticks_max != pwmGpo_->get_on_counts())
69 {
70 auto saved_node = gpioImpl_.node();
71
72 consumer_.~BitEventConsumer();
73 gpioImpl_.~GPIOBit();
74
75 pwmGpo_.reset(new PWMGPO(pwm_,
76 /*on_counts=*/cfg_srv_ticks_max,
77 /*off_counts=*/cfg_srv_ticks_min));
78 pwmGpo_->write(was_set ? Gpio::SET : Gpio::CLR);
79
80 new (&gpioImpl_) GPIOBit(
81 saved_node, cfg_event_min, cfg_event_max, pwmGpo_.get());
82 new (&consumer_) BitEventConsumer(&gpioImpl_);
83
84 return REINIT_NEEDED;
85 }
86
87 return UPDATED;
88 }
89
91 {
92 cfg_.description().write(fd, "");
93 CDI_FACTORY_RESET(cfg_.servo_min_percent);
94 CDI_FACTORY_RESET(cfg_.servo_max_percent);
95 }
96
97private:
99 const uint32_t pwmCountPerMs_;
100
103
106 std::unique_ptr<PWMGPO> pwmGpo_; // has PWM* and on/off counts
107
108 GPIOBit gpioImpl_;
110 const ServoConsumerConfig cfg_;
111};
112
113} // namespace openlcb
114
115#endif // _OPENLCB_SERVOCONSUMER_HXX_
#define CDI_FACTORY_RESET(PATH)
Performs factory reset on a CDI variable.
This class sends a notification in its destructor.
A BarrierNotifiable allows to create a number of child Notifiable and wait for all of them to finish.
UpdateAction
Specifies what additional steps are needed to apply the new configuration.
@ REINIT_NEEDED
Need to perform application-level reinitialization.
@ UPDATED
No additional step is necessary.
Implementation of ConfigUpdateListener that registers itself in the constructor and unregisters itsel...
General Purpose Output specialization of a PWM Bit.
Definition PWM.hxx:101
Abstract interface for a PWM driver.
Definition PWM.hxx:43
Event handler for a single-bit consumer, e.g.
uint64_t event_on()
returns the event ID for representing the state transition OFF->ON.
uint64_t event_off()
returns the event ID for representing the state transition ON->OFF.
Simple implementation of the BitEventInterface for going through GPIO ports.
Node * node() OVERRIDE
returns the OpenLCB virtual node from which to send the respective events when the bit changes.
Base class for NMRAnet nodes conforming to the asynchronous interface.
Definition Node.hxx:52
Basically a specialized ConfiguredConsumer.
const uint32_t pwmCountPerMs_
Used to compute PWM ticks for max/min servo rotation.
std::unique_ptr< PWMGPO > pwmGpo_
all the rest are owned and must be reset on config change.
PWM * pwm_
timer channel. not owned; lives forever
void factory_reset(int fd) OVERRIDE
Clears configuration file and resets the configuration settings to factory value.
BitEventConsumer consumer_
has on/off events, Node*, and Gpio*
UpdateAction apply_configuration(int fd, bool initial_load, BarrierNotifiable *done) OVERRIDE
Notifies the component that there is new configuration available for loading.
const ServoConsumerConfig cfg_
has GPIOBit*
#define OVERRIDE
Function attribute for virtual functions declaring that this funciton is overriding a funciton that s...
Definition macros.h:180
GPIO Pin definition structure with no actual pin behind it.
Definition DummyGPIO.hxx:83