genode/repos/os/include/pin_control_session/component.h
Norman Feske 49b4b8597d os/pin_driver: support for time-multiplexed in/out
This patch equips the pin-driver framework with support for the
time-multiplexed operation of a pin as output or input. This is needed
when implementing I2C communication via a bit-banging driver.

To operate pin in both directions, a driver obtains both a pin-state and
a pin-control session for the same pin. The pin-state session can be
used to sense the current pin state. The control session allows the
client to set the pin to high or low (using the 'state' method), or to
set it to high-impedance via the 'yield' method. Once switched to
high-impedance, the pin can be used as input.

Issue genodelabs/genode-allwinner#10
2022-11-17 08:00:35 +01:00

84 lines
1.7 KiB
C++

/*
* \brief Pin-control service
* \author Norman Feske
* \date 2021-04-20
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _INCLUDE__PIN_CONTROL_SESSION__COMPONENT_H_
#define _INCLUDE__PIN_CONTROL_SESSION__COMPONENT_H_
#include <pin_control_session/pin_control_session.h>
#include <base/session_object.h>
#include <os/pin_driver.h>
namespace Pin_control {
template <typename> class Session_component;
template <typename ID>
struct Root : Pin::Root<Session_component<ID>, Pin::Direction::OUT>
{
using Pin::Root<Session_component<ID>, Pin::Direction::OUT>::Root;
};
}
template <typename ID>
class Pin_control::Session_component : public Session_object<Session>
{
private:
Pin::Assignment<ID> _assignment;
using Session_object<Session>::label;
void _state(Pin::Level level)
{
if (_assignment.target.constructed())
_assignment.driver.pin_state(_assignment.target->id, level);
}
public:
using Pin_id = ID;
Session_component(Entrypoint &ep, Resources const &resources,
Label const &label, Diag &diag, Pin::Driver<ID> &driver)
:
Session_object<Session>(ep, resources, label, diag),
_assignment(driver)
{
update_assignment();
}
/**
* Pin_control::Session interface
*/
void state(bool enabled) override
{
_state(enabled ? Pin::Level::HIGH : Pin::Level::LOW);
}
/**
* Pin_control::Session interface
*/
void yield() override
{
_state(Pin::Level::HIGH_IMPEDANCE);
}
void update_assignment()
{
_assignment.update(label(), Pin::Direction::OUT);
}
};
#endif /* _INCLUDE__PIN_CONTROL_SESSION__COMPONENT_H_ */