Browse Source

Transition to Sink Standby during voltage changes

When there is a positive or negative transition of Vbus, we Shall reduce
our power consumption to no more than 2.5 W beforehand.  This can be
easily achieved in all cases by simply turning off the output. This was
implemented, so that's one fewer Shall we aren't doing.

In the process, I made some API changes for the Device Policy Manager.
No more output_on() and output_off(), now it's output_set(true) and
output_set(false), plus a special case output_default() used during a
hard reset.  This much better matches how these functions are used by
the policy engine.
Clara Hobbs 7 years ago
parent
commit
72f360c7d4
3 changed files with 64 additions and 23 deletions
  1. 47
    6
      src/device_policy_manager.c
  2. 9
    4
      src/device_policy_manager.h
  3. 8
    13
      src/policy_engine.c

+ 47
- 6
src/device_policy_manager.c View File

@@ -31,6 +31,12 @@
31 31
 /* Whether or not the power supply is unconstrained */
32 32
 static bool dpm_unconstrained_power;
33 33
 
34
+/* The last explicitly or implicitly negotiated voltage in PDV */
35
+static int dpm_present_voltage = PD_MV2PDV(5000);
36
+
37
+/* The requested voltage */
38
+static int dpm_requested_voltage;
39
+
34 40
 bool pdb_dpm_evaluate_capability(const union pd_msg *capabilities, union pd_msg *request)
35 41
 {
36 42
     /* Get the current configuration */
@@ -63,6 +69,10 @@ bool pdb_dpm_evaluate_capability(const union pd_msg *capabilities, union pd_msg
63 69
                 request->obj[0] = PD_RDO_FV_MAX_CURRENT_SET(cfg->i)
64 70
                     | PD_RDO_FV_CURRENT_SET(cfg->i)
65 71
                     | PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(i + 1);
72
+
73
+                /* Update requested voltage */
74
+                dpm_requested_voltage = cfg->v;
75
+
66 76
                 return true;
67 77
             }
68 78
         }
@@ -74,6 +84,10 @@ bool pdb_dpm_evaluate_capability(const union pd_msg *capabilities, union pd_msg
74 84
         | PD_RDO_FV_CURRENT_SET(10)
75 85
         | PD_RDO_NO_USB_SUSPEND | PD_RDO_CAP_MISMATCH
76 86
         | PD_RDO_OBJPOS_SET(1);
87
+
88
+    /* Update requested voltage */
89
+    dpm_requested_voltage = PD_MV2PDV(5000);
90
+
77 91
     return false;
78 92
 }
79 93
 
@@ -126,6 +140,9 @@ bool pdb_dpm_evaluate_typec_current(void)
126 140
         cfg_set = true;
127 141
     }
128 142
 
143
+    /* We don't control the voltage anymore; it will always be 5 V. */
144
+    dpm_requested_voltage = PD_MV2PDV(5000);
145
+
129 146
     /* If we have no configuration or don't want 5 V, Type-C Current can't
130 147
      * possibly satisfy our needs */
131 148
     if (cfg == NULL || cfg->v != 100) {
@@ -156,14 +173,38 @@ void pdb_dpm_pd_start(void)
156 173
     chEvtSignal(pdb_led_thread, PDB_EVT_LED_FAST_BLINK);
157 174
 }
158 175
 
159
-void pdb_dpm_output_on(void)
176
+void pdb_dpm_sink_standby(void)
177
+{
178
+    /* If the voltage is changing, enter Sink Standby */
179
+    if (dpm_requested_voltage != dpm_present_voltage) {
180
+        /* For the PD Buddy Sink, entering Sink Standby is equivalent to
181
+         * turning the output off.  However, we don't want to change the LED
182
+         * state for standby mode. */
183
+        palClearLine(LINE_OUT_CTRL);
184
+    }
185
+}
186
+
187
+void pdb_dpm_output_set(bool state)
160 188
 {
161
-    chEvtSignal(pdb_led_thread, PDB_EVT_LED_MEDIUM_BLINK_OFF);
162
-    palSetLine(LINE_OUT_CTRL);
189
+    /* Update the present voltage */
190
+    dpm_present_voltage = dpm_requested_voltage;
191
+
192
+    /* Set the power output */
193
+    if (state) {
194
+        /* Turn the output on */
195
+        chEvtSignal(pdb_led_thread, PDB_EVT_LED_MEDIUM_BLINK_OFF);
196
+        palSetLine(LINE_OUT_CTRL);
197
+    } else {
198
+        /* Turn the output off */
199
+        chEvtSignal(pdb_led_thread, PDB_EVT_LED_ON);
200
+        palClearLine(LINE_OUT_CTRL);
201
+    }
163 202
 }
164 203
 
165
-void pdb_dpm_output_off(void)
204
+void pdb_dpm_output_default(void)
166 205
 {
167
-    chEvtSignal(pdb_led_thread, PDB_EVT_LED_ON);
168
-    palClearLine(LINE_OUT_CTRL);
206
+    /* Pretend we requested 5 V */
207
+    dpm_requested_voltage = PD_MV2PDV(5000);
208
+    /* Turn the output off */
209
+    pdb_dpm_output_set(false);
169 210
 }

+ 9
- 4
src/device_policy_manager.h View File

@@ -50,14 +50,19 @@ bool pdb_dpm_evaluate_typec_current(void);
50 50
 void pdb_dpm_pd_start(void);
51 51
 
52 52
 /*
53
- * Turn on the power output, with LED indication.
53
+ * Transition to Sink Standby if necessary.
54 54
  */
55
-void pdb_dpm_output_on(void);
55
+void pdb_dpm_sink_standby(void);
56 56
 
57 57
 /*
58
- * Turn off the power output, with LED indication.
58
+ * Set the output state, with LED indication.
59 59
  */
60
-void pdb_dpm_output_off(void);
60
+void pdb_dpm_output_set(bool state);
61
+
62
+/*
63
+ * Transition the sink to default power.
64
+ */
65
+void pdb_dpm_output_default(void);
61 66
 
62 67
 
63 68
 #endif /* PDB_DEVICE_POLICY_MANAGER_H */

+ 8
- 13
src/policy_engine.c View File

@@ -155,6 +155,9 @@ static enum policy_engine_state pe_sink_select_cap(void)
155 155
         /* If the source accepted our request, wait for the new power */
156 156
         if (PD_MSGTYPE_GET(policy_engine_message) == PD_MSGTYPE_ACCEPT
157 157
                 && PD_NUMOBJ_GET(policy_engine_message) == 0) {
158
+            /* Transition to Sink Standby if necessary */
159
+            pdb_dpm_sink_standby();
160
+
158 161
             chPoolFree(&pdb_msg_pool, policy_engine_message);
159 162
             policy_engine_message = NULL;
160 163
             return PESinkTransitionSink;
@@ -209,11 +212,7 @@ static enum policy_engine_state pe_sink_transition_sink(void)
209 212
             explicit_contract = true;
210 213
 
211 214
             /* Set the output appropriately */
212
-            if (capability_match) {
213
-                pdb_dpm_output_on();
214
-            } else {
215
-                pdb_dpm_output_off();
216
-            }
215
+            pdb_dpm_output_set(capability_match);
217 216
 
218 217
             chPoolFree(&pdb_msg_pool, policy_engine_message);
219 218
             policy_engine_message = NULL;
@@ -223,7 +222,7 @@ static enum policy_engine_state pe_sink_transition_sink(void)
223 222
             /* Turn off the power output before this hard reset to make sure we
224 223
              * don't supply an incorrect voltage to the device we're powering.
225 224
              */
226
-            pdb_dpm_output_off();
225
+            pdb_dpm_output_set(false);
227 226
 
228 227
             chPoolFree(&pdb_msg_pool, policy_engine_message);
229 228
             policy_engine_message = NULL;
@@ -385,8 +384,8 @@ static enum policy_engine_state pe_sink_transition_default(void)
385 384
 {
386 385
     explicit_contract = false;
387 386
 
388
-    /* Tell the DPM to turn off the output */
389
-    pdb_dpm_output_off();
387
+    /* Tell the DPM to transition to default power */
388
+    pdb_dpm_output_default();
390 389
 
391 390
     /* There is no local hardware to reset. */
392 391
     /* Since we never change our data role from UFP, there is no reason to set
@@ -511,11 +510,7 @@ static enum policy_engine_state pe_sink_source_unresponsive(void)
511 510
 
512 511
     /* If the last two readings are the same, set the output */
513 512
     if (old_tcc_match == tcc_match) {
514
-        if (tcc_match) {
515
-            pdb_dpm_output_on();
516
-        } else {
517
-            pdb_dpm_output_off();
518
-        }
513
+        pdb_dpm_output_set(tcc_match);
519 514
     }
520 515
 
521 516
     /* Remember whether or not the last measurement succeeded */

Loading…
Cancel
Save