Browse Source

Support the new typec_virtual PDO

This commit adds support for the new, yet-to-be-released typec_virtual
PDO reported from the firmware.  This was done by adding a
TypeCVirtualPDO class, code to load them from text, and support for them
in the calculation functions.  New tests have been written for all the
new code as well.
Clara Hobbs 6 years ago
parent
commit
fbd48c6b16
2 changed files with 63 additions and 1 deletions
  1. 38
    0
      pdbuddy/__init__.py
  2. 25
    1
      test_pdbuddy/__init__.py

+ 38
- 0
pdbuddy/__init__.py View File

@@ -381,6 +381,24 @@ class SrcFixedPDO(namedtuple("SrcFixedPDO", "dual_role_pwr usb_suspend "
381 381
         return s
382 382
 
383 383
 
384
+class TypeCVirtualPDO(namedtuple("TypeCVirtualPDO", "i")):
385
+    """A Type-C Current Virtual PDO
386
+
387
+    ``i`` is the advertised current in milliamperes.
388
+    """
389
+    __slots__ = ()
390
+
391
+    pdo_type = "typec_virtual"
392
+
393
+    def __str__(self):
394
+        """Print the TypeCVirtualPDO in the manner of the configuration shell"""
395
+        s = self.pdo_type + "\n"
396
+
397
+        s += "\ti: {:.2f} A".format(self.i / 1000.0)
398
+
399
+        return s
400
+
401
+
384 402
 def read_pdo(text):
385 403
     """Create a PDO object from partial text returned by Sink.send_command"""
386 404
     # First, determine the PDO type
@@ -427,6 +445,17 @@ def read_pdo(text):
427 445
                 peak_i=peak_i,
428 446
                 v=v,
429 447
                 i=i)
448
+    elif pdo_type == TypeCVirtualPDO.pdo_type:
449
+        # Load a TypeCVirtualPDO
450
+        for line in text[1:]:
451
+            fields = line.split(b":")
452
+            fields[0] = fields[0].strip()
453
+            fields[1] = fields[1].strip()
454
+            if fields[0] == b"i":
455
+                i = round(1000*float(fields[1].split()[0]))
456
+
457
+        # Make the TypeCVirtualPDO
458
+        return TypeCVirtualPDO(i=i)
430 459
     elif pdo_type == "No Source_Capabilities":
431 460
         return None
432 461
     else:
@@ -468,6 +497,8 @@ def calculate_pdp(pdo_list):
468 497
     for pdo in pdo_list:
469 498
         if pdo.pdo_type == "fixed":
470 499
             max_power = max(max_power, pdo.v / 1000.0 * pdo.i / 1000.0)
500
+        elif pdo.pdo_type == "typec_virtual":
501
+            max_power = max(max_power, 5.0 * pdo.i / 1000.0)
471 502
 
472 503
     return max_power
473 504
 
@@ -482,6 +513,13 @@ def follows_power_rules(pdo_list):
482 513
     # First, estimate the PDP assuming the rules are being followed
483 514
     pdp = calculate_pdp(pdo_list)
484 515
 
516
+    # If there's a typec_virtual PDO, there's no Power Delivery so the Power
517
+    # Rules cannot be violated.  In truth they're not really being followed
518
+    # either since they only apply to Power Delivery, but returning True here
519
+    # seems like the safer option.
520
+    if pdo_list and pdo_list[0].pdo_type == "typec_virtual":
521
+        return True
522
+
485 523
     # Make sure nothing exceeds the PDP
486 524
     for pdo in pdo_list:
487 525
         if pdo.pdo_type == "fixed":

+ 25
- 1
test_pdbuddy/__init__.py View File

@@ -277,6 +277,15 @@ class SrcFixedPDOTestCase(unittest.TestCase):
277 277
                 "fixed\n\tv: 5.00 V\n\ti: 1.50 A")
278 278
 
279 279
 
280
+class TypeCVirtualPDOTestCase(unittest.TestCase):
281
+
282
+    def setUp(self):
283
+        self.obj_1p5a = pdbuddy.TypeCVirtualPDO(1500)
284
+
285
+    def test_str_1p5a(self):
286
+        self.assertEqual(str(self.obj_1p5a), "typec_virtual\n\ti: 1.50 A")
287
+
288
+
280 289
 class ReadPDOTestCase(unittest.TestCase):
281 290
 
282 291
     def setUp(self):
@@ -286,6 +295,7 @@ class ReadPDOTestCase(unittest.TestCase):
286 295
                 False, False, 0, 5000, 1500)
287 296
         self.unknown_zero = pdbuddy.UnknownPDO(value=0x00000000)
288 297
         self.unknown_notzero = pdbuddy.UnknownPDO(value=0xFFFFFFFF)
298
+        self.typec_virtual = pdbuddy.TypeCVirtualPDO(1500)
289 299
 
290 300
     def test_read_src_fixed_everything(self):
291 301
         rp_src_fixed_everything = pdbuddy.read_pdo([b"PDO 1: fixed",
@@ -319,6 +329,11 @@ class ReadPDOTestCase(unittest.TestCase):
319 329
         rp_unknown_notzero = pdbuddy.read_pdo([b"PDO 1: FFFFFFFF"])
320 330
         self.assertEqual(self.unknown_notzero, rp_unknown_notzero)
321 331
 
332
+    def test_read_typec_virtual(self):
333
+        rp_typec_virtual = pdbuddy.read_pdo([b"PDO 5: typec_virtual",
334
+                b"\ti: 1.50 A"])
335
+        self.assertEqual(self.typec_virtual, rp_typec_virtual)
336
+
322 337
     def test_read_none(self):
323 338
         none_pdo = pdbuddy.read_pdo([b"No Source_Capabilities"])
324 339
         self.assertEqual(none_pdo, None)
@@ -333,6 +348,7 @@ class ReadPDOListTestCase(unittest.TestCase):
333 348
                 False, False, 0, 5000, 1500)
334 349
         self.unknown_zero = pdbuddy.UnknownPDO(value=0x00000000)
335 350
         self.unknown_notzero = pdbuddy.UnknownPDO(value=0xFFFFFFFF)
351
+        self.typec_virtual = pdbuddy.TypeCVirtualPDO(1500)
336 352
 
337 353
     def test_read_pdo_list(self):
338 354
         # It's not a legal list for USB Power Delivery, but it works fine for
@@ -350,13 +366,16 @@ class ReadPDOListTestCase(unittest.TestCase):
350 366
                 b"\tv: 5.00 V",
351 367
                 b"\ti: 1.50 A",
352 368
                 b"PDO 3: 00000000",
353
-                b"PDO 4: FFFFFFFF"]
369
+                b"PDO 4: FFFFFFFF",
370
+                b"PDO 5: typec_virtual",
371
+                b"\ti: 1.50 A"]
354 372
         pdo_list = pdbuddy.read_pdo_list(text)
355 373
 
356 374
         self.assertEqual(pdo_list[0], self.src_fixed_everything)
357 375
         self.assertEqual(pdo_list[1], self.src_fixed_minimal)
358 376
         self.assertEqual(pdo_list[2], self.unknown_zero)
359 377
         self.assertEqual(pdo_list[3], self.unknown_notzero)
378
+        self.assertEqual(pdo_list[4], self.typec_virtual)
360 379
 
361 380
 
362 381
 class PDOListCalculationsTestCase(unittest.TestCase):
@@ -382,6 +401,10 @@ class PDOListCalculationsTestCase(unittest.TestCase):
382 401
                 False, False, 0, 20000, 2250)
383 402
         self.src_fixed_20v_5a = pdbuddy.SrcFixedPDO(False, False, False, False,
384 403
                 False, 0, 20000, 5000)
404
+        self.typec_virtual_1p5a = pdbuddy.TypeCVirtualPDO(1500)
405
+
406
+    def test_calculate_pdp_typec_virtual(self):
407
+        self.assertEqual(pdbuddy.calculate_pdp([self.typec_virtual_1p5a]), 7.5)
385 408
 
386 409
     def test_calculate_pdp_15w(self):
387 410
         self.assertEqual(pdbuddy.calculate_pdp([self.src_fixed_5v_3a]), 15)
@@ -411,6 +434,7 @@ class PDOListCalculationsTestCase(unittest.TestCase):
411 434
     def test_follows_power_rules_true(self):
412 435
         # <= 15 W
413 436
         self.assertTrue(pdbuddy.follows_power_rules([]))
437
+        self.assertTrue(pdbuddy.follows_power_rules([self.typec_virtual_1p5a]))
414 438
         self.assertTrue(pdbuddy.follows_power_rules([self.src_fixed_5v_1p5a]))
415 439
         self.assertTrue(pdbuddy.follows_power_rules([self.src_fixed_5v_3a]))
416 440
         self.assertTrue(pdbuddy.follows_power_rules([self.src_fixed_5v_3a,

Loading…
Cancel
Save