pixalynx/nrf9151-gps-tracker

A compact 44×32 mm, 4-layer nRF9151 LTE-M/NB-IoT/GNSS tracker PCB with nPM1300 LiPo/USB-C power, nano-SIM/eSIM switching, nRF7002 Wi‑Fi scanning, accelerometer, antennas, buzzer, LEDs, SOS button, and SWD/debug connectors.

Version
0.1.4
License
unset
Stars
0

parts/Wifi.tsx

import type { ChipProps } from "tscircuit"
import { Nrf7002Qfn48, Crystal2016, pad, courtyard, outline } from "../lib/footprints"

/** Nordic nRF7002-QFAA-R7 Wi-Fi 6 companion IC (JLC C5370744), used here only for SSID scanning (Wi-Fi
 * positioning). The nRF7000 (scan-only variant) is pin compatible. Pin table: nRF7002 Product
 * Specification v1.2 Table 24, rechecked against v1.3 (May 2026) Table 1 (research/nrf7002.md), with the unused-pin handling of nRF7002 Revision 1 Errata
 * [9] ("IOVDD leakage current increases with floating pins"): pins 2-5 (renamed Reserved) and the unused
 * 39 QSPI_DATA2, 40 QSPI_DATA3, 41 COEX_STATUS0, 42 COEX_REQ, 45 COEX_STATUS1/SW_CTRL1 go to GND; 6, 21-24,
 * 43, 44 stay open; 35/37/38 (SPI CLK/MOSI/MISO) need pull-downs, done in the host GPIO configuration
 * (docs/firmware.md), which the erratum allows. VBAT 2.9-4.5 V, IOVDD 1.62-3.6 V, shutdown 1.7 uA,
 * scan 60 mA average, TX 191 mA (2.4 GHz) / 260 mA (5 GHz) peak. */
export const nrf7002Pins = {
  pin1: ["OTPVDD"], pin2: ["RSV2"], pin3: ["RSV3"], pin4: ["RSV4"], pin5: ["RSV5"], pin6: ["RSV6"],
  pin7: ["TXRF1"], pin8: ["PAVDD1"], pin9: ["TXRF0"], pin10: ["PAVDD0"], pin11: ["SXLDO"], pin12: ["PALDO"],
  pin13: ["VBAT"], pin14: ["RFVDD"], pin15: ["RFBUCKVDD"], pin16: ["XOLDO"], pin17: ["XOP"], pin18: ["XON"],
  pin19: ["AFELDO"], pin20: ["AFEVBAT"], pin21: ["NC21"], pin22: ["NC22"], pin23: ["NC23"], pin24: ["NC24"],
  pin25: ["BUCKVBAT"], pin26: ["BUCKOUT"], pin27: ["BUCKVSS1"], pin28: ["BUCKVSS2"], pin29: ["BUCKVMID"], pin30: ["BUCKEN"],
  pin31: ["BUCKVBATS"], pin32: ["PWRBUCKVDD"], pin33: ["DIGVDD"], pin34: ["PWRIOVDD"],
  pin35: ["SPI_CLK", "QSPI_CLK"], pin36: ["SPI_SS", "QSPI_SS"], pin37: ["SPI_MOSI", "QSPI_DATA0"], pin38: ["SPI_MISO", "QSPI_DATA1"],
  pin39: ["QSPI_DATA2"], pin40: ["QSPI_DATA3"], pin41: ["COEX_STATUS0"], pin42: ["COEX_REQ"], pin43: ["COEX_GRANT"],
  pin44: ["SW_CTRL0"], pin45: ["SW_CTRL1", "COEX_STATUS1"], pin46: ["HOST_IRQ"], pin47: ["VSS"], pin48: ["IOVDD"], pin49: ["EP"],
} as const
const ncPins = ["RSV6", "NC21", "NC22", "NC23", "NC24", "COEX_GRANT", "SW_CTRL0"]
/** tied to GND per Revision 1 Errata [9] (floating, they raise IOVDD leakage) */
export const nrf7002GroundedPins = ["RSV2", "RSV3", "RSV4", "RSV5", "QSPI_DATA2", "QSPI_DATA3", "COEX_STATUS0", "COEX_REQ", "SW_CTRL1"] as const
export const Nrf7002 = (props: ChipProps<typeof nrf7002Pins>) => (
  <chip
    {...props}
    manufacturerPartNumber="NRF7002-QFAA-R7"
    supplierPartNumbers={{ jlcpcb: ["C5370744"] }}
    pinLabels={nrf7002Pins}
    internallyConnectedPins={[["VSS", "EP", "BUCKVSS1", "BUCKVSS2"]]}
    footprint={<Nrf7002Qfn48 />}
    cadModel={{ objUrl: "https://modelcdn.tscircuit.com/easyeda_models/assets/C5370744.obj?uuid=d0fbea2586a94bf4a0c0b2823af3d10c", rotationOffset: { x: 0, y: 0, z: 0 }, positionOffset: { x: 0, y: 0, z: 0 } }}
    schWidth={2.75}
    schHeight={4.35}
    schPinArrangement={{
      leftSide: { direction: "top-to-bottom", pins: ["VBAT", "AFEVBAT", "BUCKVBAT", "BUCKVBATS", "BUCKOUT", "PWRBUCKVDD", "RFBUCKVDD", "BUCKVMID", "IOVDD", "OTPVDD", "PWRIOVDD", "DIGVDD", "PALDO", "PAVDD0", "PAVDD1", "SXLDO", "RFVDD", "XOLDO", "AFELDO"] },
      rightSide: { direction: "top-to-bottom", pins: ["SPI_CLK", "SPI_SS", "SPI_MOSI", "SPI_MISO", "HOST_IRQ", "BUCKEN", "TXRF0", "TXRF1", "XOP", "XON", "QSPI_DATA2", "QSPI_DATA3", "COEX_STATUS0", "COEX_REQ", "COEX_GRANT", "SW_CTRL0", "SW_CTRL1"] },
      bottomSide: { direction: "left-to-right", pins: ["VSS", "EP", "BUCKVSS1", "BUCKVSS2"] },
      topSide: { direction: "left-to-right", pins: ["RSV2", "RSV3", "RSV4", "RSV5", "RSV6", "NC21", "NC22", "NC23", "NC24"] },
    }}
    pinAttributes={{
      VBAT: { requiresPower: true }, IOVDD: { requiresPower: true }, VSS: { requiresGround: true }, EP: { requiresGround: true },
      ...Object.fromEntries(ncPins.map((p) => [p, { doNotConnect: true }])),
      ...Object.fromEntries(nrf7002GroundedPins.map((p) => [p, { requiresGround: true }])),
    }}
  />
)

/** TDK DPX165950DT-8148A1 2.4 / 5 GHz WLAN diplexer, 1.6 x 0.8 mm, 6 terminals (JLC C307668, 6.7k in stock).
 * Pins (JLC/EasyEDA symbol): 1 LOW_BAND (2.4 GHz), 3 HIGH_BAND (5 GHz), 5 COM (antenna), 2/4/6 GND.
 * Land pattern = the EasyEDA one of C307668 (0.35 x 0.625 mm lands, 0.55 mm pitch, rows +/-0.54 mm; pins 1-3 on
 * the lower row left to right, 4-6 on the upper row right to left), drawn explicitly because the matching
 * dfn6 footprinter string renders with width and length swapped in this core. Plays the role of U2
 * "2.4 / 5 GHz WLAN Dual Band Diplexer" in Nordic's nRF7002 reference schematic. */
export const diplexerPins = { pin1: ["LOW_BAND"], pin2: ["GND3"], pin3: ["HIGH_BAND"], pin4: ["GND2"], pin5: ["COM"], pin6: ["GND1"] } as const
export const Diplexer = (props: ChipProps<typeof diplexerPins>) => (
  <chip
    {...props}
    manufacturerPartNumber="DPX165950DT-8148A1"
    supplierPartNumbers={{ jlcpcb: ["C307668"] }}
    pinLabels={diplexerPins}
    internallyConnectedPins={[["GND1", "GND2", "GND3"]]}
    footprint={
      <footprint>
        {[1, 2, 3].map((p, i) => pad(p, -0.55 + i * 0.55, -0.54, 0.35, 0.625))}
        {[4, 5, 6].map((p, i) => pad(p, 0.55 - i * 0.55, 0.54, 0.35, 0.625))}
        {outline(1.6, 0.8)}
        {courtyard(2.2, 2.0)}
      </footprint>
    }
    cadModel={{ objUrl: "https://modelcdn.tscircuit.com/easyeda_models/assets/C307668.obj?uuid=65fbddda7e9a4bb69de86e05fa1ddb6b", rotationOffset: { x: 0, y: 0, z: 0 }, positionOffset: { x: 0, y: 0, z: 0 } }}
    schPinArrangement={{ leftSide: { direction: "top-to-bottom", pins: ["LOW_BAND", "HIGH_BAND", "GND1"] }, rightSide: { direction: "top-to-bottom", pins: ["COM", "GND2", "GND3"] } }}
    pinAttributes={{ GND1: { requiresGround: true }, GND2: { requiresGround: true }, GND3: { requiresGround: true } }}
  />
)

/** 40 MHz crystal, 2016, CL 8 pF, ESR 30 ohm, +/-10 ppm (Hosonic/TKD K2B400000810, JLC C2835990, 20k in stock).
 * Nordic: 40 MHz, CL = 8 pF, ESR <= 100 ohm; no external load capacitors (nRF7002 reference schematic X1). */
export const crystalPins = { pin1: ["X1"], pin2: ["GND1"], pin3: ["X2"], pin4: ["GND2"] } as const
export const Crystal40M = (props: ChipProps<typeof crystalPins>) => (
  <chip
    {...props}
    manufacturerPartNumber="K2B400000810"
    supplierPartNumbers={{ jlcpcb: ["C2835990"] }}
    pinLabels={crystalPins}
    footprint={<Crystal2016 />}
    cadModel={{ objUrl: "https://modelcdn.tscircuit.com/easyeda_models/assets/C2835990.obj?uuid=51ae9b24ba7a408881f7752b57b66e45", rotationOffset: { x: 0, y: 0, z: 0 }, positionOffset: { x: 0, y: 0, z: 0 } }}
    schWidth={0.6}
    schHeight={1.15}
    schPinArrangement={{ leftSide: { direction: "top-to-bottom", pins: ["X1"] }, rightSide: { direction: "top-to-bottom", pins: ["X2"] }, bottomSide: { direction: "left-to-right", pins: ["GND1", "GND2"] } }}
    pinAttributes={{ GND1: { requiresGround: true }, GND2: { requiresGround: true } }}
  />
)

/** Richtek RT9080-33GJ5 3.3 V / 600 mA LDO, TSOT-23-5 (JLC C841192, 67k in stock): 2 uA quiescent, VIN up to 5.5 V
 * (VSYS follows VBUS while charging, so the nRF7002's 4.5 V VBAT maximum rules out feeding it from VSYS directly,
 * and its 260 mA TX peak exceeds the nPM1300 bucks' 200 mA). Pins: 1 VIN, 2 GND, 3 EN, 4 NC, 5 VOUT. */
export const rt9080Pins = { pin1: ["VIN"], pin2: ["GND"], pin3: ["EN"], pin4: ["NC"], pin5: ["VOUT"] } as const
export const Rt9080 = (props: ChipProps<typeof rt9080Pins>) => (
  <chip
    {...props}
    manufacturerPartNumber="RT9080-33GJ5"
    supplierPartNumbers={{ jlcpcb: ["C841192"] }}
    pinLabels={rt9080Pins}
    footprint="sot25_w2.3mm_pw0.53mm_pl1.05mm_pin1location(bottomside,left)"
    cadModel={{ objUrl: "https://modelcdn.tscircuit.com/easyeda_models/assets/C841192.obj?uuid=c7fdf6dae3ca4abaabd1bafd2d31350d", rotationOffset: { x: 0, y: 0, z: 90 }, positionOffset: { x: 0, y: 0, z: 0 } }}
    schPinArrangement={{ leftSide: { direction: "top-to-bottom", pins: ["VIN", "EN"] }, rightSide: { direction: "top-to-bottom", pins: ["VOUT", "NC"] }, bottomSide: { direction: "left-to-right", pins: ["GND"] } }}
    pinAttributes={{ VIN: { requiresPower: true }, VOUT: { providesPower: true }, GND: { requiresGround: true }, NC: { doNotConnect: true } }}
  />
)