1
0
forked from me/IronOS
Files
IronOS/source/Core/Drivers/FUSB302/policy_engine.h
Ben V. Brown fc08dc42fa Auto notify tx
2021-04-05 14:12:44 +10:00

211 lines
7.3 KiB
C++

/*
* PD Buddy Firmware Library - USB Power Delivery for everyone
* Copyright 2017-2018 Clayton G. Hobbs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PDB_POLICY_ENGINE_H
#define PDB_POLICY_ENGINE_H
#include <pd.h>
/*
* Events for the Policy Engine thread, used internally + sent by user code
*
*/
class PolicyEngine {
public:
// Sets up internal state and registers the thread
static void init();
// Push an incoming message to the Policy Engine
static void handleMessage(union pd_msg *msg);
// Returns true if headers indicate PD3.0 compliant
static bool isPD3_0();
static bool setupCompleteOrTimedOut() {
if (pdNegotiationComplete)
return true;
if (state == policy_engine_state::PESinkSourceUnresponsive)
return true;
if (state == policy_engine_state::PESinkReady)
return true;
return false;
}
// Has pd negotiation completed
static bool pdHasNegotiated() {
if (state == policy_engine_state::PESinkSourceUnresponsive)
return false;
return true;
}
// Call this periodically, at least once every second
static void PPSTimerCallback();
enum class Notifications {
PDB_EVT_PE_RESET = EVENT_MASK(0),
PDB_EVT_PE_MSG_RX = EVENT_MASK(1),
PDB_EVT_PE_TX_DONE = EVENT_MASK(2),
PDB_EVT_PE_TX_ERR = EVENT_MASK(3),
PDB_EVT_PE_HARD_SENT = EVENT_MASK(4),
PDB_EVT_PE_I_OVRTEMP = EVENT_MASK(5),
PDB_EVT_PE_PPS_REQUEST = EVENT_MASK(6),
PDB_EVT_PE_MSG_RX_PEND = EVENT_MASK(7), /* Never send this from user area*/
PDB_EVT_PE_GET_SOURCE_CAP = EVENT_MASK(8),
PDB_EVT_PE_NEW_POWER = EVENT_MASK(9),
PDB_EVT_PE_ALL = (EVENT_MASK(10) - 1),
};
// Send a notification
static void notify(Notifications notification);
// Debugging allows looking at state
static uint32_t getState() { return (uint32_t)state; }
private:
static bool pdNegotiationComplete;
static int current_voltage_mv; // The current voltage PD is expecting
static int _requested_voltage; // The voltage the unit wanted to requests
static bool _unconstrained_power; // If the source is unconstrained
// Current message being handled
static union pd_msg currentMessage;
/* PD message header template */
static uint16_t hdr_template;
/* Whether or not we have an explicit contract */
static bool _explicit_contract;
/* The number of hard resets we've sent */
static int8_t _hard_reset_counter;
/* The result of the last Type-C Current match comparison */
static int8_t _old_tcc_match;
/* The index of the first PPS APDO */
static uint8_t _pps_index;
static void pe_task(const void *arg);
enum policy_engine_state {
PESinkStartup,
PESinkDiscovery,
PESinkWaitCap,
PESinkEvalCap,
PESinkSelectCap, // 4
PESinkTransitionSink, // 5
PESinkReady, // 6
PESinkGetSourceCap,
PESinkGiveSinkCap,
PESinkHardReset,
PESinkTransitionDefault,
PESinkSoftReset,
PESinkSendSoftReset,
PESinkSendNotSupported,
PESinkChunkReceived,
PESinkNotSupportedReceived,
PESinkSourceUnresponsive
};
static enum policy_engine_state pe_sink_startup();
static enum policy_engine_state pe_sink_discovery();
static enum policy_engine_state pe_sink_wait_cap();
static enum policy_engine_state pe_sink_eval_cap();
static enum policy_engine_state pe_sink_select_cap();
static enum policy_engine_state pe_sink_transition_sink();
static enum policy_engine_state pe_sink_ready();
static enum policy_engine_state pe_sink_get_source_cap();
static enum policy_engine_state pe_sink_give_sink_cap();
static enum policy_engine_state pe_sink_hard_reset();
static enum policy_engine_state pe_sink_transition_default();
static enum policy_engine_state pe_sink_soft_reset();
static enum policy_engine_state pe_sink_send_soft_reset();
static enum policy_engine_state pe_sink_send_not_supported();
static enum policy_engine_state pe_sink_chunk_received();
static enum policy_engine_state pe_sink_not_supported_received();
static enum policy_engine_state pe_sink_source_unresponsive();
static EventGroupHandle_t xEventGroupHandle;
static StaticEventGroup_t xCreatedEventGroup;
static EventBits_t waitForEvent(uint32_t mask, TickType_t ticksToWait = portMAX_DELAY);
// Task resources
static osThreadId TaskHandle;
static const size_t TaskStackSize = 2048 / 4;
static uint32_t TaskBuffer[TaskStackSize];
static osStaticThreadDef_t TaskControlBlock;
static union pd_msg tempMessage;
static union pd_msg _last_dpm_request;
static policy_engine_state state;
// queue of up to PDB_MSG_POOL_SIZE messages to send
static StaticQueue_t xStaticQueue;
/* The array to use as the queue's storage area. This must be at least
uxQueueLength * uxItemSize bytes. */
static uint8_t ucQueueStorageArea[PDB_MSG_POOL_SIZE * sizeof(union pd_msg)];
static QueueHandle_t messagesWaiting;
static bool messageWaiting();
// Read a pending message into the temp message
static bool readMessage();
static bool PPSTimerEnabled;
static TickType_t PPSTimeLastEvent;
// These callbacks are called to implement the logic for the iron to select the desired voltage
/*
* Create a Request message based on the given Source_Capabilities message. If
* capabilities is NULL, the last non-null Source_Capabilities message passes
* is used. If none has been provided, the behavior is undefined.
*
* Returns true if sufficient power is available, false otherwise.
*/
static bool pdbs_dpm_evaluate_capability(const union pd_msg *capabilities, union pd_msg *request);
/*
* Create a Sink_Capabilities message for our current capabilities.
*/
static void pdbs_dpm_get_sink_capability(union pd_msg *cap);
/*
* Return whether or not GiveBack support is enabled.
*/
static bool pdbs_dpm_giveback_enabled();
/*
* Evaluate whether or not the currently offered Type-C Current can fulfill our
* power needs.
*
* Returns true if sufficient power is available, false otherwise.
*/
static bool pdbs_dpm_evaluate_typec_current(enum fusb_typec_current tcc);
/*
* Indicate that power negotiations are starting.
*/
static void pdbs_dpm_pd_start();
/*
* Transition the sink to default power.
*/
static void pdbs_dpm_transition_default();
/*
* Transition to the requested minimum current.
*/
static void pdbs_dpm_transition_min();
/*
* Transition to Sink Standby if necessary.
*/
static void pdbs_dpm_transition_standby();
/*
* Transition to the requested power level
*/
static void pdbs_dpm_transition_requested();
/*
* Transition to the Type-C Current power level
*/
static void pdbs_dpm_transition_typec();
};
#endif /* PDB_POLICY_ENGINE_H */