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
         return s
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
 def read_pdo(text):
402
 def read_pdo(text):
385
     """Create a PDO object from partial text returned by Sink.send_command"""
403
     """Create a PDO object from partial text returned by Sink.send_command"""
386
     # First, determine the PDO type
404
     # First, determine the PDO type
427
                 peak_i=peak_i,
445
                 peak_i=peak_i,
428
                 v=v,
446
                 v=v,
429
                 i=i)
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
     elif pdo_type == "No Source_Capabilities":
459
     elif pdo_type == "No Source_Capabilities":
431
         return None
460
         return None
432
     else:
461
     else:
468
     for pdo in pdo_list:
497
     for pdo in pdo_list:
469
         if pdo.pdo_type == "fixed":
498
         if pdo.pdo_type == "fixed":
470
             max_power = max(max_power, pdo.v / 1000.0 * pdo.i / 1000.0)
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
     return max_power
503
     return max_power
473
 
504
 
482
     # First, estimate the PDP assuming the rules are being followed
513
     # First, estimate the PDP assuming the rules are being followed
483
     pdp = calculate_pdp(pdo_list)
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
     # Make sure nothing exceeds the PDP
523
     # Make sure nothing exceeds the PDP
486
     for pdo in pdo_list:
524
     for pdo in pdo_list:
487
         if pdo.pdo_type == "fixed":
525
         if pdo.pdo_type == "fixed":

+ 25
- 1
test_pdbuddy/__init__.py View File

277
                 "fixed\n\tv: 5.00 V\n\ti: 1.50 A")
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
 class ReadPDOTestCase(unittest.TestCase):
289
 class ReadPDOTestCase(unittest.TestCase):
281
 
290
 
282
     def setUp(self):
291
     def setUp(self):
286
                 False, False, 0, 5000, 1500)
295
                 False, False, 0, 5000, 1500)
287
         self.unknown_zero = pdbuddy.UnknownPDO(value=0x00000000)
296
         self.unknown_zero = pdbuddy.UnknownPDO(value=0x00000000)
288
         self.unknown_notzero = pdbuddy.UnknownPDO(value=0xFFFFFFFF)
297
         self.unknown_notzero = pdbuddy.UnknownPDO(value=0xFFFFFFFF)
298
+        self.typec_virtual = pdbuddy.TypeCVirtualPDO(1500)
289
 
299
 
290
     def test_read_src_fixed_everything(self):
300
     def test_read_src_fixed_everything(self):
291
         rp_src_fixed_everything = pdbuddy.read_pdo([b"PDO 1: fixed",
301
         rp_src_fixed_everything = pdbuddy.read_pdo([b"PDO 1: fixed",
319
         rp_unknown_notzero = pdbuddy.read_pdo([b"PDO 1: FFFFFFFF"])
329
         rp_unknown_notzero = pdbuddy.read_pdo([b"PDO 1: FFFFFFFF"])
320
         self.assertEqual(self.unknown_notzero, rp_unknown_notzero)
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
     def test_read_none(self):
337
     def test_read_none(self):
323
         none_pdo = pdbuddy.read_pdo([b"No Source_Capabilities"])
338
         none_pdo = pdbuddy.read_pdo([b"No Source_Capabilities"])
324
         self.assertEqual(none_pdo, None)
339
         self.assertEqual(none_pdo, None)
333
                 False, False, 0, 5000, 1500)
348
                 False, False, 0, 5000, 1500)
334
         self.unknown_zero = pdbuddy.UnknownPDO(value=0x00000000)
349
         self.unknown_zero = pdbuddy.UnknownPDO(value=0x00000000)
335
         self.unknown_notzero = pdbuddy.UnknownPDO(value=0xFFFFFFFF)
350
         self.unknown_notzero = pdbuddy.UnknownPDO(value=0xFFFFFFFF)
351
+        self.typec_virtual = pdbuddy.TypeCVirtualPDO(1500)
336
 
352
 
337
     def test_read_pdo_list(self):
353
     def test_read_pdo_list(self):
338
         # It's not a legal list for USB Power Delivery, but it works fine for
354
         # It's not a legal list for USB Power Delivery, but it works fine for
350
                 b"\tv: 5.00 V",
366
                 b"\tv: 5.00 V",
351
                 b"\ti: 1.50 A",
367
                 b"\ti: 1.50 A",
352
                 b"PDO 3: 00000000",
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
         pdo_list = pdbuddy.read_pdo_list(text)
372
         pdo_list = pdbuddy.read_pdo_list(text)
355
 
373
 
356
         self.assertEqual(pdo_list[0], self.src_fixed_everything)
374
         self.assertEqual(pdo_list[0], self.src_fixed_everything)
357
         self.assertEqual(pdo_list[1], self.src_fixed_minimal)
375
         self.assertEqual(pdo_list[1], self.src_fixed_minimal)
358
         self.assertEqual(pdo_list[2], self.unknown_zero)
376
         self.assertEqual(pdo_list[2], self.unknown_zero)
359
         self.assertEqual(pdo_list[3], self.unknown_notzero)
377
         self.assertEqual(pdo_list[3], self.unknown_notzero)
378
+        self.assertEqual(pdo_list[4], self.typec_virtual)
360
 
379
 
361
 
380
 
362
 class PDOListCalculationsTestCase(unittest.TestCase):
381
 class PDOListCalculationsTestCase(unittest.TestCase):
382
                 False, False, 0, 20000, 2250)
401
                 False, False, 0, 20000, 2250)
383
         self.src_fixed_20v_5a = pdbuddy.SrcFixedPDO(False, False, False, False,
402
         self.src_fixed_20v_5a = pdbuddy.SrcFixedPDO(False, False, False, False,
384
                 False, 0, 20000, 5000)
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
     def test_calculate_pdp_15w(self):
409
     def test_calculate_pdp_15w(self):
387
         self.assertEqual(pdbuddy.calculate_pdp([self.src_fixed_5v_3a]), 15)
410
         self.assertEqual(pdbuddy.calculate_pdp([self.src_fixed_5v_3a]), 15)
411
     def test_follows_power_rules_true(self):
434
     def test_follows_power_rules_true(self):
412
         # <= 15 W
435
         # <= 15 W
413
         self.assertTrue(pdbuddy.follows_power_rules([]))
436
         self.assertTrue(pdbuddy.follows_power_rules([]))
437
+        self.assertTrue(pdbuddy.follows_power_rules([self.typec_virtual_1p5a]))
414
         self.assertTrue(pdbuddy.follows_power_rules([self.src_fixed_5v_1p5a]))
438
         self.assertTrue(pdbuddy.follows_power_rules([self.src_fixed_5v_1p5a]))
415
         self.assertTrue(pdbuddy.follows_power_rules([self.src_fixed_5v_3a]))
439
         self.assertTrue(pdbuddy.follows_power_rules([self.src_fixed_5v_3a]))
416
         self.assertTrue(pdbuddy.follows_power_rules([self.src_fixed_5v_3a,
440
         self.assertTrue(pdbuddy.follows_power_rules([self.src_fixed_5v_3a,

Loading…
Cancel
Save