"""Reviewed TI pin tables and ERC modeling decisions; see IC_PIN_REVIEW_R2.md.""" import hashlib import json from schematic_maintenance import ROOT def numbered(entries): return {str(i): pair for i, pair in enumerate(entries, 1)} TABLES = { 'TPS54622RHLR': numbered([ ('RT/CLK', 'input'), ('GND', 'power_in'), ('GND', 'power_in'), ('PVIN', 'power_in'), ('PVIN', 'power_in'), ('VIN', 'power_in'), ('VSENSE', 'input'), ('COMP', 'output'), ('SS/TR', 'bidirectional'), ('EN', 'input'), ('PH', 'power_out'), ('PH', 'passive'), ('BOOT', 'passive'), ('PWRGD', 'open_collector'), ('EXP', 'power_in'), ]), 'TPS25940ARVCR': numbered([ ('DEVSLP', 'input'), ('PGOOD', 'open_collector'), ('PGTH', 'input'), ('OUT', 'power_out'), *[('OUT', 'passive')] * 4, *[('IN', 'power_in')] * 5, ('EN', 'input'), ('OVP', 'input'), ('GND', 'power_in'), ('ILIM', 'passive'), ('dVdT', 'passive'), ('IMON', 'output'), ('FLT#', 'open_collector'), ('EP', 'power_in'), ]), 'DAC63204RTER': numbered([ ('FB3', 'input'), ('OUT3', 'output'), ('OUT2', 'output'), ('FB2', 'input'), ('GPIO/SDO', 'bidirectional'), ('SCL/SYNC#', 'bidirectional'), ('A0/SDI', 'input'), ('SDA/SCLK', 'bidirectional'), ('FB1', 'input'), ('OUT1', 'output'), ('OUT0', 'output'), ('FB0', 'input'), ('CAP', 'power_out'), ('AGND', 'power_in'), ('VDD', 'power_in'), ('VREF', 'input'), ('EP', 'power_in'), ]), 'TPS22918DBVR': numbered([ ('VIN', 'power_in'), ('GND', 'power_in'), ('ON', 'input'), ('CT', 'output'), ('QOD', 'passive'), ('VOUT', 'power_out'), ]), 'TS5A3157DBVR': numbered([ ('NO', 'passive'), ('GND', 'power_in'), ('NC', 'passive'), ('COM', 'passive'), ('V+', 'power_in'), ('IN', 'input'), ]), } TABLES['TPS22918DBVR_MIRRORED'] = TABLES['TPS22918DBVR'] SOURCES = { 'TPS54622RHLR': ('TPS54622', 4, 'ca33ca93ec3849011f07573bf5b6c91dbb92f5f33e53977b5849e97d279bbcfd'), 'TPS25940ARVCR': ('TPS25940', 3, '9db4dc76b1040251f56d994041d2e6f02f1307d687aecbc5218f137a5c830adc'), 'DAC63204RTER': ('DAC63204', 3, '83e228e2cbd5f0b60b00bce6e7c3c9461e8430249a5d7ce7ef2ccddb0f30655b'), 'TPS22918DBVR': ('TPS22918', 3, '1b28eb58003d28b18bf919a15734056f296a499bebee2bd493a1e4358c4dfb1c'), 'TS5A3157DBVR': ('TS5A3157', 3, '29d243a798f52820fce6c11e42bcc07aebf939ff8a75aaf6be523af714b512a0'), } SOURCES['TPS22918DBVR_MIRRORED'] = SOURCES['TPS22918DBVR'] HUB_TABLES = {'USB2517I-JZX': numbered([ ('USBDN1_DM/PRT_DIS_M1', 'bidirectional'), ('USBDN1_DP/PRT_DIS_P1', 'bidirectional'), ('USBDN2_DM/PRT_DIS_M2', 'bidirectional'), ('USBDN2_DP/PRT_DIS_P2', 'bidirectional'), ('VDDA33', 'power_in'), ('USBDN3_DM/PRT_DIS_M3', 'bidirectional'), ('USBDN3_DP/PRT_DIS_P3', 'bidirectional'), ('USBDN4_DM/PRT_DIS_M4', 'bidirectional'), ('USBDN4_DP/PRT_DIS_P4', 'bidirectional'), ('VDDA33', 'power_in'), ('USBDN5_DM/PRT_DIS_M5', 'bidirectional'), ('USBDN5_DP/PRT_DIS_P5', 'bidirectional'), ('CFG_SEL2', 'input'), ('LED_B7_N', 'bidirectional'), ('LED_A7_N/PRT_SWP7', 'bidirectional'), ('LED_B6_N', 'bidirectional'), ('LED_A6_N/PRT_SWP6', 'bidirectional'), ('LED_B5_N', 'bidirectional'), ('TEST', 'input'), ('PRTPWR4', 'output'), ('OCS4_N', 'input'), ('OCS3_N', 'input'), ('PRTPWR3', 'output'), ('VDD33CR', 'power_in'), ('VDD18', 'power_out'), ('PRTPWR2', 'output'), ('OCS2_N', 'input'), ('OCS1_N', 'input'), ('PRTPWR1', 'output'), ('PRTPWR5', 'output'), ('LED_A5_N/PRT_SWP5', 'bidirectional'), ('LED_B4_N', 'bidirectional'), ('LED_A4_N/PRT_SWP4', 'bidirectional'), ('LED_B3_N/GANG_EN', 'bidirectional'), ('OCS5_N', 'input'), ('PRTPWR7', 'output'), ('OCS7_N', 'input'), ('OCS6_N', 'input'), ('PRTPWR6', 'output'), ('SDA/SMBDATA/NON_REM1', 'bidirectional'), ('SCL/SMBCLK/CFG_SEL0', 'bidirectional'), ('HS_IND/CFG_SEL1', 'bidirectional'), ('RESET_N', 'input'), ('VBUS_DET', 'bidirectional'), ('SUSP_IND/LOCAL_PWR/NON_REM0', 'bidirectional'), ('VDD33', 'power_in'), ('LED_A3_N/PRT_SWP3', 'bidirectional'), ('LED_B2_N/BOOST1', 'bidirectional'), ('LED_A2_N/PRT_SWP2', 'bidirectional'), ('LED_B1_N/BOOST0', 'bidirectional'), ('LED_A1_N/PRT_SWP1', 'bidirectional'), ('VDDA33', 'power_in'), ('USBDN6_DM/PRT_DIS_M6', 'bidirectional'), ('USBDN6_DP/PRT_DIS_P6', 'bidirectional'), ('USBDN7_DM/PRT_DIS_M7', 'bidirectional'), ('USBDN7_DP/PRT_DIS_P7', 'bidirectional'), ('VDDA33', 'power_in'), ('USBUP_DM', 'bidirectional'), ('USBUP_DP', 'bidirectional'), ('XTAL2', 'output'), ('XTAL1/CLKIN', 'input'), ('VDD18PLL', 'power_out'), ('RBIAS', 'passive'), ('VDD33PLL', 'power_in'), ('VSS', 'power_in'), ])} HUB_SOURCES = {'USB2517I-JZX': ('USB2517', '7, 10-16', 'fd9caf7754e5656052e73435efc339dfd459f65f1e77439ed2dfc74a14177b75')} DISCRETE_TABLES = { '2N7002': numbered([('G', 'input'), ('S', 'passive'), ('D', 'passive')]), 'AO3400A': numbered([('G', 'input'), ('S', 'passive'), ('D', 'passive')]), 'AO4407': numbered([*[('S', 'passive')] * 3, ('G', 'input'), *[('D', 'passive')] * 4]), 'AMS1117-3': numbered([('GND', 'power_in'), ('VOUT', 'power_out'), ('VIN', 'power_in'), ('VOUT', 'passive')]), 'TL431_C2887585': numbered([('REF', 'input'), ('CATHODE', 'passive'), ('ANODE', 'passive')]), } DISCRETE_SOURCES = { '2N7002': ('2N7002-CJ', 1, '7941fb423af7c6c6c8979063a7e8819bb19217ece275efcce18948950a41d9f6'), 'AO3400A': ('../fans/AO3400A', 1, '9c60d0b6c1ddc7609a4b788a91181468d8ffe6c3e9ba425c3d8ffc5ba88c5033'), 'AO4407': ('AO4407-KEXIN', 1, '1d0a7da91cb84b4aeef53e375dbbb4bd7f805cf93ba58579582b5b39f0edee1e'), 'AMS1117-3': ('AMS1117', 1, '189a2651878a87d590b768eaa9b44217a3fdf460352ce6ecaff127221282a3f0'), 'TL431_C2887585': ('TL431-YFSEMI', 1, 'bf2b255bd231944cc92b425ac58dc18b387324b44fe7a7a77bc7125d397f43d2'), } def references(hub=False, discrete=False): result = {} tables, sources = (HUB_TABLES, HUB_SOURCES) if hub else (TABLES, SOURCES) if discrete: tables, sources = DISCRETE_TABLES, DISCRETE_SOURCES for name, (part, page, expected) in sources.items(): path = (ROOT / 'datasheets/ic' / (part + '.pdf')).resolve() actual = hashlib.sha256(path.read_bytes()).hexdigest() if actual != expected: raise ValueError(f'Reviewed datasheet changed: {path}') meta = json.loads(path.with_suffix('.json').read_text(encoding='utf-8')) result[name] = {'pdf': str(path.relative_to(ROOT)), 'page': page, 'sha256': actual, 'url': meta['pdf_url'], 'pins': tables[name]} return result def check_common_pins(board): checks = [] for ref, props in board.parts.items(): if props.get('MPN') == 'TPS54622RHLR': groups = [('11', '12'), ('2', '3', '15'), ('4', '5')] elif props.get('MPN') == 'TPS25940ARVCR': groups = [('4', '5', '6', '7', '8'), ('9', '10', '11', '12', '13'), ('16', '21')] elif props.get('MPN') == 'DAC63204RTER': groups = [('14', '17')] elif props.get('MPN') == 'AO4407': groups = [('1', '2', '3'), ('5', '6', '7', '8')] elif props.get('MPN') == 'AMS1117-3.3': groups = [('2', '4')] else: continue for group in groups: nets = [board.net(ref, pin) for pin in group] good = len(set(nets)) == 1 and not nets[0].startswith('unconnected-') checks.append({'reference': ref, 'pins': group, 'nets': nets, 'pass': good}) if not good: raise ValueError(f'{ref}: internally common pins split across nets: {group}') return checks def check_hub_supply(board): if board.number != 2: return [] checks = [] def record(label, good): checks.append({'check': label, 'pass': bool(good)}) if not good: raise ValueError(label) for pin in (5, 10, 24, 46, 52, 57, 64): record(f'Hub 3V3 supply pin {pin}', board.net('U32', pin) == '+3V3_HUB') record('Hub exposed ground', board.net('U32', 65) == 'GND') for pin, ref in ((25, 'C742'), (62, 'C743')): expected = {('U32', str(pin)), (ref, '1')} record(f'Hub internal regulator {pin} only feeds its bypass', board.net_members[board.net('U32', pin)] == expected) record(f'Hub bypass {ref} ground', board.net(ref, 2) == 'GND') record(f'Hub bypass {ref} selected 1uF part', board.parts[ref]['MPN'] == 'CL05A105KA5NQNC') record('Hub internal regulators are separate', board.net('U32', 25) != board.net('U32', 62)) record('Hub TEST grounded', board.net('U32', 19) == 'GND') return checks