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
 /* Whether or not the power supply is unconstrained */
31
 /* Whether or not the power supply is unconstrained */
32
 static bool dpm_unconstrained_power;
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
 bool pdb_dpm_evaluate_capability(const union pd_msg *capabilities, union pd_msg *request)
40
 bool pdb_dpm_evaluate_capability(const union pd_msg *capabilities, union pd_msg *request)
35
 {
41
 {
36
     /* Get the current configuration */
42
     /* Get the current configuration */
63
                 request->obj[0] = PD_RDO_FV_MAX_CURRENT_SET(cfg->i)
69
                 request->obj[0] = PD_RDO_FV_MAX_CURRENT_SET(cfg->i)
64
                     | PD_RDO_FV_CURRENT_SET(cfg->i)
70
                     | PD_RDO_FV_CURRENT_SET(cfg->i)
65
                     | PD_RDO_NO_USB_SUSPEND | PD_RDO_OBJPOS_SET(i + 1);
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
                 return true;
76
                 return true;
67
             }
77
             }
68
         }
78
         }
74
         | PD_RDO_FV_CURRENT_SET(10)
84
         | PD_RDO_FV_CURRENT_SET(10)
75
         | PD_RDO_NO_USB_SUSPEND | PD_RDO_CAP_MISMATCH
85
         | PD_RDO_NO_USB_SUSPEND | PD_RDO_CAP_MISMATCH
76
         | PD_RDO_OBJPOS_SET(1);
86
         | PD_RDO_OBJPOS_SET(1);
87
+
88
+    /* Update requested voltage */
89
+    dpm_requested_voltage = PD_MV2PDV(5000);
90
+
77
     return false;
91
     return false;
78
 }
92
 }
79
 
93
 
126
         cfg_set = true;
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
     /* If we have no configuration or don't want 5 V, Type-C Current can't
146
     /* If we have no configuration or don't want 5 V, Type-C Current can't
130
      * possibly satisfy our needs */
147
      * possibly satisfy our needs */
131
     if (cfg == NULL || cfg->v != 100) {
148
     if (cfg == NULL || cfg->v != 100) {
156
     chEvtSignal(pdb_led_thread, PDB_EVT_LED_FAST_BLINK);
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
 void pdb_dpm_pd_start(void);
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
 #endif /* PDB_DEVICE_POLICY_MANAGER_H */
68
 #endif /* PDB_DEVICE_POLICY_MANAGER_H */

+ 8
- 13
src/policy_engine.c View File

155
         /* If the source accepted our request, wait for the new power */
155
         /* If the source accepted our request, wait for the new power */
156
         if (PD_MSGTYPE_GET(policy_engine_message) == PD_MSGTYPE_ACCEPT
156
         if (PD_MSGTYPE_GET(policy_engine_message) == PD_MSGTYPE_ACCEPT
157
                 && PD_NUMOBJ_GET(policy_engine_message) == 0) {
157
                 && PD_NUMOBJ_GET(policy_engine_message) == 0) {
158
+            /* Transition to Sink Standby if necessary */
159
+            pdb_dpm_sink_standby();
160
+
158
             chPoolFree(&pdb_msg_pool, policy_engine_message);
161
             chPoolFree(&pdb_msg_pool, policy_engine_message);
159
             policy_engine_message = NULL;
162
             policy_engine_message = NULL;
160
             return PESinkTransitionSink;
163
             return PESinkTransitionSink;
209
             explicit_contract = true;
212
             explicit_contract = true;
210
 
213
 
211
             /* Set the output appropriately */
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
             chPoolFree(&pdb_msg_pool, policy_engine_message);
217
             chPoolFree(&pdb_msg_pool, policy_engine_message);
219
             policy_engine_message = NULL;
218
             policy_engine_message = NULL;
223
             /* Turn off the power output before this hard reset to make sure we
222
             /* Turn off the power output before this hard reset to make sure we
224
              * don't supply an incorrect voltage to the device we're powering.
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
             chPoolFree(&pdb_msg_pool, policy_engine_message);
227
             chPoolFree(&pdb_msg_pool, policy_engine_message);
229
             policy_engine_message = NULL;
228
             policy_engine_message = NULL;
385
 {
384
 {
386
     explicit_contract = false;
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
     /* There is no local hardware to reset. */
390
     /* There is no local hardware to reset. */
392
     /* Since we never change our data role from UFP, there is no reason to set
391
     /* Since we never change our data role from UFP, there is no reason to set
511
 
510
 
512
     /* If the last two readings are the same, set the output */
511
     /* If the last two readings are the same, set the output */
513
     if (old_tcc_match == tcc_match) {
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
     /* Remember whether or not the last measurement succeeded */
516
     /* Remember whether or not the last measurement succeeded */

Loading…
Cancel
Save