Multiple Issues Connecting nRF9151 to QM13345 Antenna Switch (No RFFE Support?)

Hello,
I am developing a custom IoT device based on the nRF9151 SiP with a Qorvo QM13345 SP4T antenna switch controlled via RFFE 2.1 interface. All RFFE AT commands fail with error 65536, preventing antenna switch control and resulting in no cellular signal (CSQ: 99,99).

## Hardware Configuration
- **Device**: nRF9151 (nrf9151dk/nrf9151/ns)
- **Antenna Switch**: Qorvo QM13345 SP4T (RFFE 2.1 controlled)
- **Current Modem Firmware**: mfw_nrf91x1_2.0.2
- **SDK**: nRF Connect SDK v3.0.2-89ba1294ac9b
- **Zephyr**: v4.0.99-f791c49f492c

## RFFE Hardware Connections
```
nRF9151          QM13345
Pin 27 -------> SDATA (Pin 5)
Pin 28 -------> SCLK (Pin 6)
Pin 29 -------> VIO (Pin 4)
GND ----------> GND (Pin 7)
```

 **Connections**:
- SDATA (pin 27) → nRF9151 RFFE_SDATA
- SCLK (pin 28) → nRF9151 RFFE_SCLK
- VIO (pin 29) → nRF9151 RFFE_VIO
- RF1 (pin 3) → Main LTE antenna port
- RFC (pin 1) → nRF9151 RF output



QM13345 ID pin connected to solder bridge (SB1/SBI2) for USID configuration.

## Software Configuration
I've enabled Nordic's official modem antenna library:
```kconfig
CONFIG_MODEM_ANTENNA=y
CONFIG_MODEM_ANTENNA_AT_MAGPIO="AT%XMAGPIO=1,0,0,1,1,1574,1577"
CONFIG_MODEM_ANTENNA_AT_MIPIRFFEDEV="AT%XMIPIRFFEDEV=1,7,0"
CONFIG_MODEM_ANTENNA_AT_MIPIRFFECTRL_INIT="AT%XMIPIRFFECTRL=1,0,1,0,1"
CONFIG_MODEM_ANTENNA_AT_MIPIRFFECTRL_ON="AT%XMIPIRFFECTRL=1,1,1,0,1"
CONFIG_MODEM_ANTENNA_AT_MIPIRFFECTRL_OFF="AT%XMIPIRFFECTRL=1,2,1,0,0"
CONFIG_MODEM_ANTENNA_AT_MIPIRFFECTRL_PWROFF="AT%XMIPIRFFECTRL=1,3,1,0,0"
```

## Observed Behavior
During modem initialization, all RFFE configuration attempts fail:
```
[00:00:02.900,329] <err> modem_antenna: Failed to set configuration (err: 65536)
[00:00:02.909,454] <err> modem_antenna: Failed to set configuration (err: 65536)
[00:00:02.924,560] <err> modem_antenna: Failed to set configuration (err: 65536)
[00:00:02.939,697] <err> modem_antenna: Failed to set configuration (err: 65536)
[00:00:02.954,833] <err> modem_antenna: Failed to set configuration (err: 65536)
```

Manual AT command testing confirms RFFE commands are not supported:
```
AT%XMIPIRFFEDEV? → Error 65536
AT%XMIPIRFFE? → Error 65536
AT%XMIPIRFFECTRL=1,0,1,0,1 → Error 65536
AT%XRFTEST? → Error 65536
```

Modem otherwise functions correctly:
- Basic AT commands work (AT, AT+CGMI, etc.)
- SIM card detected and powered (IMSI: 222013423872426)
- Modem enters full functionality mode (CFUN=1) successfully
- No cellular signal: CSQ returns 99,99 (no signal detected)

## Comparison with Nordic Reference Design
I noticed the Thingy:91 X (PCA20035) with nRF9151 successfully uses RFFE commands in its configuration:

From `/home/nrf/boards/nordic/thingy91x/Kconfig.defconfig.nrf9151`:
```kconfig
config MODEM_ANTENNA_AT_MIPIRFFEDEV
    default "AT%XMIPIRFFEDEV=1,4,71,198,248"
config MODEM_ANTENNA_AT_MIPIRFFECTRL_INIT
    default "AT%XMIPIRFFECTRL=1,0,1,28,248"
config MODEM_ANTENNA_AT_MIPIRFFECTRL_ON
    default "AT%XMIPIRFFECTRL=1,1,1,28,56,13,0,0,8,8,715,4,4,770,12,12,829..."
```

This confirms that nRF9151 SHOULD support RFFE commands for antenna switch control.

## Questions

1. **Does modem firmware 2.0.2 support RFFE 2.1 commands?**
   - If not, which firmware version first introduced RFFE support?
   - Is there a firmware update roadmap for RFFE support on nRF9151?

2. **How does the Thingy:91 X control its antenna switch with nRF9151?**
   - Does it use a different modem firmware version?
   - Are there any special modem configuration steps required?

3. **Is there an alternative method to control RFFE devices on nRF9151?**
   - Can MAGPIO be used as a fallback for antenna switching?
   - Are there any undocumented AT commands for RF path control?

4. **What is the recommended approach for antenna switching on nRF9151?**
   - Should I use RFFE-controlled switches (QM13345)?
   - Or should I use GPIO-controlled switches (SKY13453, PE42423)?

## Additional Information

I've tested both production firmware 2.0.2 and production test firmware 2.3.8:
- **2.0.2**: RFFE commands fail with error 65536
- **2.3.8**: PTI firmware blocks most AT commands (restricted mode for factory testing)

The hardware design follows the QM13345 datasheet requirements:
- RFFE 2.1 interface properly connected
- VIO decoupling capacitor present
- Proper grounding
- ID pin configured for USID=0x7 (GND connection)

## Expected Outcome
I need to successfully control the QM13345 antenna switch to route RF signals from the nRF9151 modem (RFC) to the main antenna (RF1 port). This is blocking cellular connectivity testing.

## Request
Please provide:
1. Confirmation of RFFE support status in nRF9151 firmware versions
2. Recommended firmware version for RFFE-controlled antenna switches
3. Example configuration or AT command sequence for QM13345 control
4. Timeline for RFFE support if not currently available

## Attachments

- Full RTT log showing RFFE command failures
- Hardware schematic (relevant RFFE section)
- prj.conf configuration file

Thank you for your assistance.
(Connection lost)
00> [00:00:00.397,033] <inf> LSM6DSO: Initialize device lsm6dso@6b
00> [00:00:00.404,602] <inf> LSM6DSO: chip id 0x6a
00> [00:00:00.409,973] <err> nt3h2111: I2C read failed: -5
00> [00:00:00.416,168] <err> nt3h2111: Failed to read configuration: -5
00> [00:00:00.423,522] <wrn> nt3h2111: NT3H2111 may not be physically connected, continuing with defaults
00> [00:00:00.439,453] <inf> veml6030: VEML6030 initialized successfully
00> *** Booting My Application v1.0.0-704e3ba7cb7b ***
00> *** Using nRF Connect SDK v3.0.2-89ba1294ac9b ***
00> *** Using Zephyr OS v4.0.99-f791c49f492c ***
00> [00:00:00.460,021] <inf> main_app: Starting Multi-Sensor IoT Device Firmware
00> [00:00:00.467,895] <inf> main_app: Skipping config manager init for debugging
00> [00:00:00.475,860] <inf> main_app: Data transmission interval set to 60 seconds
00> [00:00:00.484,039] <inf> battery_monitor: Battery monitor initialized (LTC4060 charger)
00> [00:00:00.492,919] <inf> main_app: Battery m[00:00:02.648,162] <inf> main_app: Calling nrf_modem_lib_init()...
00> [00:00:02.902,191] <err> modem_antenna: Failed to set configuration (err: 65536)
00> [00:00:02.911,254] <err> modem_antenna: Failed to set configuration (err: 65536)
00> [00:00:02.926,391] <err> modem_antenna: Failed to set configuration (err: 65536)
00> [00:00:02.941,467] <err> modem_antenna: Failed to set configuration (err: 65536)
00> [00:00:02.956,573] <err> modem_antenna: Failed to set configuration (err: 65536)
00> [00:00:02.986,389] <inf> main_app: nrf_modem_lib_init() returned: 0
00> [00:00:02.993,469] <inf> main_app: Modem library initialized successfully
00> [00:00:03.001,098] <inf> main_app: Waiting for modem to be fully ready...
00> [00:00:13.008,728] <wrn> main_app: Modem ready timeout - proceeding anyway
00> [00:00:16.016,754] <inf> main_app: Testing AT interface (attempt 2)...
00> [00:00:16.030,456] <inf> main_app: Modem responding: OK
00> 
00> [00:00:16.036,651] <inf> main_app: Getting modem information...
00> [00:00:16.049,926] <wrn> main_app: Failed to get modem info (err=65536)
00> [00:00:16.064,147] <inf> main_app: Manufacturer: Nordic Semiconductor ASA
00> OK
00> 
00> [00:00:16.078,765] <inf> main_app: Modem firmware version: mfw_nrf91x1_2.0.2
00> OK
00> 
00> [00:00:16.087,219] <inf> main_app: === CHECKING RFFE COMMAND SUPPORT ===
00> [00:00:16.101,379] <wrn> main_app: XMIPIRFFEDEV not supported (err=65536)
00> [00:00:16.115,936] <wrn> main_app: XMIPIRFFE not supported (err=65536)
00> [00:00:16.130,218] <wrn> main_app: XRFTEST not supported (err=65536)
00> [00:00:16.144,317] <wrn> main_app: %XRFTEST not supported (err=65536)
00> [00:00:16.158,477] <wrn> main_app: %XMIPIRFFE not supported (err=65536)
00> [00:00:16.166,198] <inf> main_app: === END RFFE COMMAND CHECK ===
00> [00:00:16.173,095] <err> main_app: ====================================
00> [00:00:16.180,786] <err> main_app: CRITICAL HARDWARE ISSUE DETECTED!
00> [00:00:16.188,232] <err> main_app: ====================================
00> [00:00:16.195,953] <err> main_app: QM13345 antenna switch requires RFFE 2.1 protocol
00> [00:00:16.204,833] <err> main_app: nRF9151 modem firmware 2.0.2 does NOT support RFFE
00> [00:00:16.213,806] <err> main_app: Without RFFE, the antenna switch cannot be controlled
00> [00:00:16.223,052] <err> main_app: The switch may be in an undefined/OFF state
00> [00:00:16.231,384] <err> main_app: 
00> [00:00:16.235,839] <err> main_app: WORKAROUND ATTEMPT:
00> [00:00:16.242,004] <err> main_app: The QM13345 ID pin configuration may set a default state
00> [00:00:16.251,525] <err> main_app: Your board has ID pin connected to solder bridge SB1/SBI2
00> [00:00:16.261,138] <err> main_app: Check if the solder bridge routes to GND (USID=0x7)
00> [00:00:16.270,172] <err> main_app: ====================================
00> [00:00:16.284,301] <inf> main_app: CFUN state check succeeded: +CFUN: 0
00> OK
00> 
00> [00:00:16.292,297] <wrn> main_app: Modem is in offline/airplane mode - needs activation!
00> [00:00:16.301,544] <inf> main_app: Configuring cellular connection for Telnyx (APN: data00.telnyx)...
00> [00:00:16.311,676] <inf> main_app: Following Nordic forum recommended sequence...
00> [00:00:16.320,007] <inf> main_app: Step 1: Setting CFUN=0 to disable radio...
00> [00:00:16.365,478] <inf> main_app: Radio disabled: OK
00> 
00> [00:00:17.371,520] <inf> main_app: Step 2: Setting automatic operator selection (AT+COPS=0)...
00> [00:00:17.387,542] <inf> main_app: Operator selection set to automatic: OK
00> 
00> [00:00:17.395,446] <inf> main_app: Step 3: Setting system mode (LTE-M and NB-IoT)...
00> [00:00:17.410,705] <wrn> main_app: System mode config failed (err=65536)
00> [00:00:17.418,518] <inf> main_app: Step 4: Configuring Telnyx APN (data00.telnyx)...
00> [00:00:17.433,685] <inf> main_app: APN configured: OK
00> 
00> [00:00:17.439,666] <inf> main_app: Step 7: Activating modem (AT+CFUN=1)...
00> [00:00:17.447,387] <inf> main_app: No search commands active - safe to activate!
00> [00:00:17.500,762] <inf> main_app: CFUN=1 set successfully: OK
00> 
00> [00:00:17.507,568] <inf> main_app: Waiting for modem to stabilize...
00> [00:00:20.514,801] <inf> main_app: Verifying modem state...
00> [00:00:20.521,484] <inf> main_app: SUCCESS: Modem is in full functionality mode
00> [00:00:20.529,632] <inf> main_app: Enabling SIM card power supply...
00> [00:00:20.536,773] <inf> main_app: Forcing SIM card power enable...
00> [00:00:20.544,219] <inf> main_app: Network registration notifications enabled: OK
00> 
00> [00:00:20.553,283] <wrn> main_app: XSIM not supported (err=65536)
00> [00:00:20.560,455] <inf> main_app: Triggering SIM communication to enable power...
00> [00:00:20.569,274] <inf> main_app: IMSI read (forces SIM power): 222013423872426
00> OK
00> 
00> [00:00:20.579,040] <wrn> main_app: XICCID failed (err=65536)
00> [00:00:20.585,784] <inf> main_app: Ensuring modem is in full functionality mode...
00> [00:00:20.594,543] <inf> main_app: Current CFUN state: +CFUN: 1
00> OK
00> 
00> [00:00:20.601,806] <inf> main_app: Querying SIM status multiple times to ensure power...
00> [00:00:21.111,236] <inf> main_app: SIM status attempt 1: +CPIN: READY
00> OK
00> 
00> [00:00:21.119,049] <inf> main_app: SIM detected and powered!
00> [00:00:22.125,518] <inf> main_app: =====================================
00> [00:00:22.133,026] <inf> main_app: SIM POWER STATUS:
00> [00:00:22.138,763] <inf> main_app: =====================================
00> [00:00:22.146,270] <inf> main_app: IMPORTANT: Pin 19 (SIM_1V8) only outputs voltage during SIM communication!
00> [00:00:22.157,135] <inf> main_app: The voltage will appear when modem actively talks to SIM.
00> [00:00:22.166,473] <inf> main_app: RST showing -1.8V indicates partial SIM interface activation.
00> [00:00:22.176,147] <inf> main_app: Please measure NOW while firmware is running:
00> [00:00:22.184,387] <inf> main_app:   - SIM VCC (pin C1): Should show 1.8V during communication
00> [00:00:22.193,908] <inf> main_app:   - SIM RST (pin C2): -1.8V is normal (active low)
00> [00:00:22.202,575] <inf> main_app: =====================================
00> [00:00:22.710,510] <inf> main_app: SIM detection after power enable: +CPIN: READY
00> OK
00> 
00> [00:00:22.719,390] <inf> main_app: SUCCESS: SIM card detected and ready!
00> [00:00:22.726,928] <inf> main_app: ====================================
00> [00:00:22.734,344] <err> main_app: ANTENNA SWITCH ISSUE DETECTED!
00> [00:00:22.741,485] <inf> main_app: ====================================
00> [00:00:22.748,931] <err> main_app: QM13345 uses RFFE 2.1 protocol
00> [00:00:22.756,072] <err> main_app: nRF9151 firmware 2.0.2 does NOT support RFFE commands
00> [00:00:22.765,319] <err> main_app: The antenna switch cannot be properly controlled!
00> [00:00:22.774,200] <inf> main_app: Attempting workarounds...
00> [00:00:22.781,280] <wrn> main_app: XMIPIRFFEDEV failed (err=65536) - device may already be configured
00> [00:00:22.792,449] <wrn> main_app: XMIPIRFFECTRL INIT failed (err=65536)
00> [00:00:22.800,964] <wrn> main_app: XMIPIRFFECTRL ON failed (err=65536)
00> [00:00:22.809,448] <wrn> main_app: XMIPIRFFEDBG read failed (err=65536)
00> [00:00:22.818,115] <wrn> main_app: XANTCFG failed (err=65536)
00> [00:00:22.824,951] <inf> main_app: ====================================
00> [00:00:22.832,397] <err> main_app: RFFE Configuration FAILED - Commands Not Supported!
00> [00:00:22.841,430] <err> main_app: QM13345 antenna switch is NOT properly configured
00> [00:00:22.850,311] <inf> main_app: ====================================
00> [00:00:22.857,727] <inf> main_app: Attempting alternative antenna configuration methods...
00> [00:00:22.867,431] <wrn> main_app: MAGPIO not available (err=65536)
00> [00:00:22.875,335] <wrn> main_app: Cannot get antenna tuning (err=65536)
00> [00:00:22.883,148] <inf> main_app: ====================================
00> [00:00:22.890,594] <err> main_app: CRITICAL: HARDWARE INCOMPATIBILITY
00> [00:00:22.898,101] <err> main_app: ====================================
00> [00:00:22.905,792] <err> main_app: Problem: QM13345 antenna switch requires RFFE 2.1 protocol
00> [00:00:22.915,496] <err> main_app: Issue: nRF9151 firmware 2.0.2 does NOT support RFFE
00> [00:00:22.924,530] <err> main_app: Result: Antenna switch stuck in unknown/OFF state
00> [00:00:22.933,380] <err> main_app: 
00> [00:00:22.937,835] <err> main_app: POSSIBLE SOLUTIONS:
00> [00:00:22.944,030] <err> main_app: 1. Hardware modification: Bypass QM13345 (connect RFC to RF1 directly)
00> [00:00:22.954,772] <err> main_app: 2. Add pull-up resistor on V1 (pin 8) to force RF1 selection
00> [00:00:22.964,660] <err> main_app: 3. Wait for Nordic to release RFFE-enabled firmware
00> [00:00:22.973,693] <err> main_app: 4. Use external GPIO to control V1-V4 pins (requires PCB rework)
00> [00:00:22.983,917] <err> main_app: ====================================
00> [00:00:23.092,803] <inf> main_app: Checking RF test mode capabilities...
00> [00:00:23.100,982] <wrn> main_app: RF test mode not available (err=65536)
00> [00:00:23.109,252] <inf> main_app: Radio functionality: +CFUN: 1
00> OK
00> 
00> [00:00:23.116,607] <inf> main_app: Radio is enabled (CFUN=1)
00> [00:00:23.123,626] <inf> main_app: RF switch configuration attempts completed
00> [00:00:23.131,591] <inf> main_app: ====================================
00> [00:00:23.139,038] <inf> main_app: ====================================
00> [00:00:23.146,453] <inf> main_app: QUICK SIGNAL CHECK BEFORE ATTACHMENT
00> [00:00:23.153,869] <inf> main_app: ====================================
00> [00:00:23.161,743] <inf> main_app: Signal strength: +CSQ: 99,99
00> OK
00> 
00> [00:00:23.169,006] <wrn> main_app: NO SIGNAL DETECTED (CSQ: 99,99)
00> [00:00:23.176,239] <wrn> main_app: Check antenna connection!
00> [00:00:23.183,288] <inf> main_app: SIM status: +CPIN: READY
00> OK
00> 
00> [00:00:23.190,185] <inf> main_app: ====================================
00> [00:00:23.197,631] <inf> main_app: Step 8: Waiting for network attachment (AT+CGATT)...
00> [00:00:23.206,909] <inf> main_app: [Attempt 1/30] Not attached yet: +CGATT: 0
00> OK
00> 
(Connection lost)
 5305.prj.conf
Parents
  • I'm using MAGPIO exclusively and the CESQ is still 99,99,255,255. I am not sure why. I am using the sample applications from https://github.com/Conexiotechnologies/conexio-firmware-sdk/tree/main/samples/conexio_stratus and modifying it for my board.

    From what I'm seeing the COEX2 isn't being activated (pasted the pin diagram below):

    The GNSS IS working as long as LTE is off. LTE seems to block it.

    00> *** Booting nRF Connect SDK v3.0.2-89ba1294ac9b ***
    00> *** Using Zephyr OS v4.0.99-f791c49f492c ***
    00> [00:00:00.249,511] <inf> GNSS_sample: Stratus GNSS sample started
    00> [00:00:00.249,603] <inf> GNSS_sample: Configuring modem for LTE + GNSS operation...
    00> [00:00:02.520,446] <inf> GNSS_sample: Modem ready
    00> [00:00:02.520,874] <inf> GNSS_sample: Modem FW: mfw_nrf91x1_2.0.2
    00> OK
    00> 
    00> [00:00:02.521,392] <inf> GNSS_sample: IMEI: 359404233656629
    00> OK
    00> 
    00> [00:00:02.521,423] <inf> GNSS_sample: Configuring RF front-end for LTE + GNSS...
    00> [00:00:02.522,521] <wrn> GNSS_sample: RF power pin still low after drive-strength boost
    00> [00:00:02.522,552] <inf> GNSS_sample: Configuring QM13345 MIPI switch for LTE path
    00> [00:00:02.529,113] <wrn> GNSS_sample: QM13345 not found at USID 0x00 (65536), trying 0x0C
    00> [00:00:02.529,602] <err> GNSS_sample: Failed to register QM13345 switch: 65536
    00> [00:00:02.529,602] <wrn> GNSS_sample: Failed to configure MIPI switch: 65536
    00> [00:00:02.529,632] <inf> GNSS_sample: Programming MAGPIO and COEX0 for Stratus board
    00> [00:00:02.530,456] <inf> GNSS_sample: MAGPIO programmed: OK
    00> [00:00:02.531,005] <inf> GNSS_sample: COEX0 programmed: OK
    00> [00:00:02.531,005] <inf> GNSS_sample: Setting modem to CFUN=0...
    00> [00:00:03.565,490] <inf> GNSS_sample: Enabling LTE-M + GNSS mode...
    00> [00:00:03.572,387] <inf> GNSS_sample: Setting modem to full functionality mode (CFUN=1)...
    00> [00:00:03.610,748] <inf> GNSS_sample: Waiting for LTE network registration...
    00> [00:00:18.611,450] <inf> GNSS_sample: System mode: %XSYSTEMMODE: 1,0,1,0
    00> OK
    00> 
    00> [00:00:18.611,816] <inf> GNSS_sample: Functional mode: +CFUN: 1
    00> OK
    00> 
    00> [00:00:18.612,243] <inf> GNSS_sample: LTE Registration: +CEREG: 0,4
    00> OK
    00> 
    00> [00:00:18.612,640] <inf> GNSS_sample: GPRS attach: +CGATT: 0
    00> OK
    00> 
    00> [00:00:18.613,098] <inf> GNSS_sample: Signal quality: +CSQ: 99,99
    00> OK
    00> 
    00> [00:00:18.613,555] <inf> GNSS_sample: Extended signal quality: +CESQ: 99,99,255,255,255,255
    00> OK
    00> 

    Here is my main.c:

    /*
     * Copyright (c) 2024-2025 Conexio Technologies, Inc
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     *
     * Enhanced GNSS Sample with proper modem configuration
     */
    
    #include <stdio.h>
    #include <zephyr/kernel.h>
    #include <zephyr/logging/log.h>
    #include <zephyr/drivers/gpio.h>
    #include <modem/nrf_modem_lib.h>
    #include <modem/lte_lc.h>
    #include <dk_buttons_and_leds.h>
    #include <nrf_modem_at.h>
    #include <nrf_modem_gnss.h>
    #include <math.h>
    #include <string.h>
    #include <hal/nrf_gpio.h>
    
    LOG_MODULE_REGISTER(GNSS_sample, LOG_LEVEL_INF);
    
    /* RF Front-end GPIO definitions */
    #define RF_PWR_GPIO_DEV		DT_NODELABEL(gpio0)
    #define RF_PWR_ENABLE_PIN	22  /* P0.22 -> RFFE_LTE_ENABLE / COEX2 net */
    #define GPS_ENABLE_PIN		19  /* P0.19 -> GPS_EN, low selects LTE path */
    
    /* LED definitions */
    #define GNSS_SEARCHING_LED	DK_LED1
    #define GNSS_FIX_LED		DK_LED2
    #define GNSS_BLOCKED_LED	DK_LED3
    #define ERROR_LED		DK_LED4
    
    /* Button definitions */
    #define START_GNSS_BTN		DK_BTN1_MSK
    #define STOP_GNSS_BTN		DK_BTN2_MSK
    
    /* Define the PVT data frame variable */
    static struct nrf_modem_gnss_pvt_data_frame pvt_data;
    
    /* Declare helper variables to find the TTFF */
    static int64_t gnss_start_time;
    static bool first_fix = false;
    
    static K_SEM_DEFINE(gnss_fix_sem, 0, 1);
    
    /* LTE event handler - simplified version */
    static void lte_handler(const struct lte_lc_evt *evt)
    {
    	if (!evt) {
    		return;
    	}
    
    	switch (evt->type) {
    	case LTE_LC_EVT_NW_REG_STATUS:
    		LOG_INF("CEREG status: %d", evt->nw_reg_status);
    		if (evt->nw_reg_status == LTE_LC_NW_REG_REGISTERED_HOME || 
    		    evt->nw_reg_status == LTE_LC_NW_REG_REGISTERED_ROAMING) {
    			LOG_INF("LTE network registered!");
    		}
    		break;
    	case LTE_LC_EVT_LTE_MODE_UPDATE:
    		LOG_INF("LTE mode update: %d", evt->lte_mode);
    		break;
    	case LTE_LC_EVT_RRC_UPDATE:
    		LOG_INF("RRC %s",
    			evt->rrc_mode == LTE_LC_RRC_MODE_CONNECTED ? "connected" : "idle");
    		break;
    	default:
    		LOG_DBG("Unhandled LTE event: %d", evt->type);
    		break;
    	}
    }
    
    /* RF Front-end configuration functions */
    static int configure_rf_front_end(void)
    {
    	int err;
    	const struct device *gpio_dev = DEVICE_DT_GET(RF_PWR_GPIO_DEV);
    
    	LOG_INF("Configuring RF front-end for LTE + GNSS...");
    
    	if (!device_is_ready(gpio_dev)) {
    		LOG_ERR("GPIO0 device not ready");
    		return -ENODEV;
    	}
    
    	/* Configure RF power enable pin (COEX2) */
    	err = gpio_pin_configure(gpio_dev, RF_PWR_ENABLE_PIN, 
    				 GPIO_OUTPUT_LOW | GPIO_PUSH_PULL | GPIO_ACTIVE_HIGH);
    	if (err) {
    		LOG_ERR("Failed to configure RF power pin: %d", err);
    		return err;
    	}
    
    	/* Configure GPS enable pin for antenna switching */
    	err = gpio_pin_configure(gpio_dev, GPS_ENABLE_PIN, 
    				 GPIO_OUTPUT_LOW | GPIO_PUSH_PULL | GPIO_ACTIVE_HIGH);
    	if (err) {
    		LOG_ERR("Failed to configure GPS_EN pin: %d", err);
    		return err;
    	}
    
    	/* Boost drive strength for COEX2 pin using Nordic HAL - exact match to working diagnostics */
    	nrf_gpio_pin_drive_t drive = NRF_GPIO_PIN_H0H1;
    	nrf_gpio_reconfigure(NRF_GPIO_PIN_MAP(0, RF_PWR_ENABLE_PIN), NULL, NULL, NULL, &drive, NULL);
    
    	/* Enable RF power, set GPS_EN low for LTE path initially - exact sequence */
    	gpio_pin_set(gpio_dev, RF_PWR_ENABLE_PIN, 1);
    	k_sleep(K_MSEC(1));  /* Let the power rail settle */
    
    	/* Verify COEX2 is high - exact same check as working diagnostics */
    	if (!gpio_pin_get(gpio_dev, RF_PWR_ENABLE_PIN)) {
    		LOG_WRN("RF power pin still low after drive-strength boost");
    	} else {
    		LOG_INF("RF power switch asserted, GPS_EN held low");
    	}
    
    	/* Explicitly set GPS_EN low after RF power is on */
    	gpio_pin_set(gpio_dev, GPS_ENABLE_PIN, 0);
    
    	return 0;
    }
    
    static int configure_qm13345_switch(void)
    {
    	int err;
    	char response[64];
    
    	LOG_INF("Configuring QM13345 MIPI switch for LTE path");
    
    	/* Try to register QM13345 at USID 0x00 first - matching working lte_diagnostics */
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT%%XMIPIRFFEDEV=0,0");
    	if (err) {
    		LOG_WRN("QM13345 not found at USID 0x00 (%d), trying 0x0C", err);
    		err = nrf_modem_at_cmd(response, sizeof(response), "AT%%XMIPIRFFEDEV=0,12");
    		if (err) {
    			LOG_ERR("Failed to register QM13345 switch: %d", err);
    			return err;
    		}
    	}
    
    	/* Configure switch for LTE path */
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT%%XMIPIRFFECTRL=0,0,1,0x1C,0x01");
    	if (err) {
    		LOG_ERR("Failed to configure QM13345 INIT phase: %d", err);
    		return err;
    	}
    
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT%%XMIPIRFFECTRL=0,1,1,0x1C,0x01");
    	if (err) {
    		LOG_ERR("Failed to configure QM13345 ON phase: %d", err);
    		return err;
    	}
    
    	LOG_INF("QM13345 switch locked to RF1");
    	return 0;
    }
    
    static int configure_magpio_and_coex(void)
    {
    	int err;
    	char response[128];
    
    	LOG_INF("Programming MAGPIO and COEX0 for Stratus board");
    
    	/* Configure MAGPIO for LTE bands */
    	err = nrf_modem_at_cmd(response, sizeof(response),
    		"AT%%XMAGPIO=1,1,1,7,1,746,803,2,698,748,2,1710,2200,3,824,894,"
    		"4,880,960,5,791,849,7,1565,1586");
    	if (err) {
    		LOG_ERR("MAGPIO programming failed: %d", err);
    		return err;
    	}
    	LOG_INF("MAGPIO programmed: OK");
    
    	/* Configure COEX0 for GNSS coexistence */
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT%%XCOEX0=1,1,1565,1586");
    	if (err) {
    		LOG_ERR("COEX0 programming failed: %d", err);
    		return err;
    	}
    	LOG_INF("COEX0 programmed: OK");
    
    	return 0;
    }
    
    
    /**
     * @brief Configure modem for LTE + GNSS operation with proper RF front-end setup
     */
    static int modem_configure_for_lte_gnss(void)
    {
    	int err;
    	char response[64];
    
    	LOG_INF("Configuring modem for LTE + GNSS operation...");
    
    	/* Initialize modem library first */
    	err = nrf_modem_lib_init();
    	if (err) {
    		if (err == -EALREADY) {
    			LOG_INF("Modem already initialized");
    		} else {
    			LOG_ERR("Failed to initialize modem library: %d", err);
    			return err;
    		}
    	}
    
    	/* Wait for modem to be ready */
    	k_sleep(K_SECONDS(2));
    
    	/* Test modem communication */
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT");
    	if (err) {
    		LOG_ERR("Modem not responding: %d", err);
    		return err;
    	}
    	LOG_INF("Modem ready");
    
    	/* Get modem info */
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT+CGMR");
    	if (err == 0) {
    		LOG_INF("Modem FW: %s", response);
    	}
    
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT+CGSN");
    	if (err == 0) {
    		LOG_INF("IMEI: %s", response);
    	}
    
    	/* Now configure the RF front-end */
    	err = configure_rf_front_end();
    	if (err) {
    		LOG_ERR("Failed to configure RF front-end: %d", err);
    		return err;
    	}
    
    	/* Configure QM13345 MIPI switch */
    	err = configure_qm13345_switch();
    	if (err) {
    		LOG_WRN("Failed to configure MIPI switch: %d", err);
    		/* Continue without MIPI switch - might not be present */
    	}
    
    	/* Configure MAGPIO and COEX0 */
    	err = configure_magpio_and_coex();
    	if (err) {
    		LOG_WRN("Failed to configure antenna settings: %d", err);
    		/* Continue without antenna configuration - will use defaults */
    	}
    
    	/* Turn off modem to change system mode */
    	LOG_INF("Setting modem to CFUN=0...");
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT+CFUN=0");
    	if (err) {
    		LOG_WRN("CFUN=0 request failed: %d", err);
    		/* Continue anyway - modem might already be in correct state */
    	}
    	k_sleep(K_SECONDS(1));
    
    	/* Enable LTE-M + GNSS in system mode (1,0,1,0) */
    	LOG_INF("Enabling LTE-M + GNSS mode...");
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT%%XSYSTEMMODE=1,0,1,0");
    	if (err) {
    		LOG_ERR("Failed to set system mode: %d", err);
    		return err;
    	}
    
    	/* Set modem to full functionality mode with LTE enabled (CFUN=1) */
    	LOG_INF("Setting modem to full functionality mode (CFUN=1)...");
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT+CFUN=1");
    	if (err) {
    		LOG_ERR("Failed to set CFUN=1: %d", err);
    		return err;
    	}
    
    	/* Wait for modem to connect to network automatically */
    	LOG_INF("Waiting for LTE network registration...");
    	k_sleep(K_SECONDS(15));
    
    	/* Verify configuration */
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT%%XSYSTEMMODE?");
    	if (err == 0) {
    		LOG_INF("System mode: %s", response);
    	}
    
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT+CFUN?");
    	if (err == 0) {
    		LOG_INF("Functional mode: %s", response);
    	}
    
    	/* Check LTE registration status and signal quality */
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT+CEREG?");
    	if (err == 0) {
    		LOG_INF("LTE Registration: %s", response);
    	}
    
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT+CGATT?");
    	if (err == 0) {
    		LOG_INF("GPRS attach: %s", response);
    	}
    
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT+CSQ");
    	if (err == 0) {
    		LOG_INF("Signal quality: %s", response);
    	}
    
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT+CESQ");
    	if (err == 0) {
    		LOG_INF("Extended signal quality: %s", response);
    	}
    
    	return 0;
    }
    
    static int modem_init(void)
    {
    	/* Modem initialization is now handled in modem_configure_for_lte_gnss() */
    	return 0;
    }
    
    /* Define a function to log fix data in a readable format */
    static void print_fix_data(struct nrf_modem_gnss_pvt_data_frame *pvt_data)
    {
    	LOG_INF("===========================================");
    	LOG_INF("           GPS POSITION ACQUIRED          ");
    	LOG_INF("===========================================");
    	LOG_INF("Latitude:       %.06f°", pvt_data->latitude);
    	LOG_INF("Longitude:      %.06f°", pvt_data->longitude);
    	LOG_INF("Altitude:       %.01f m", pvt_data->altitude);
    	LOG_INF("Accuracy:       %.01f m", pvt_data->accuracy);
    	LOG_INF("Speed:          %.01f m/s", pvt_data->speed);
    	LOG_INF("Heading:        %.01f°", pvt_data->heading);
    	LOG_INF("Time (UTC):     %04u-%02u-%02u %02u:%02u:%02u.%03u",
    	       pvt_data->datetime.year,
    	       pvt_data->datetime.month,
    	       pvt_data->datetime.day,
    	       pvt_data->datetime.hour,
    	       pvt_data->datetime.minute,
    	       pvt_data->datetime.seconds,
    	       pvt_data->datetime.ms);
    	LOG_INF("Google Maps:    https://maps.google.com/?q=%.6f,%.6f",
    	       pvt_data->latitude, pvt_data->longitude);
    	LOG_INF("===========================================");
    }
    
    static void gnss_event_handler(int event)
    {
    	int err;
    	static int satellites_tracked = 0;
    
    	switch (event) {
    	case NRF_MODEM_GNSS_EVT_PVT:
    		err = nrf_modem_gnss_read(&pvt_data, sizeof(pvt_data), NRF_MODEM_GNSS_DATA_PVT);
    		if (err) {
    			LOG_ERR("Failed to read PVT data: %d", err);
    			return;
    		}
    
    		/* Count satellites */
    		satellites_tracked = 0;
    		for (int i = 0; i < 12; i++) {
    			if (pvt_data.sv[i].signal != 0) {
    				satellites_tracked++;
    			}
    		}
    
    		if (pvt_data.flags & NRF_MODEM_GNSS_PVT_FLAG_FIX_VALID) {
    			/* Fix acquired! */
    			dk_set_led_off(GNSS_SEARCHING_LED);
    			dk_set_led_on(GNSS_FIX_LED);
    
    			print_fix_data(&pvt_data);
    
    			/* Print time to first fix */
    			if (!first_fix) {
    				LOG_INF("Time to first fix: %lld seconds",
    					(k_uptime_get() - gnss_start_time) / 1000);
    				first_fix = true;
    			}
    
    			k_sem_give(&gnss_fix_sem);
    		} else {
    			/* No fix yet */
    			dk_set_led_on(GNSS_SEARCHING_LED);
    			dk_set_led_off(GNSS_FIX_LED);
    
    			LOG_INF("GNSS: Searching for fix... (Satellites tracked: %d)",
    				satellites_tracked);
    		}
    		break;
    
    	case NRF_MODEM_GNSS_EVT_FIX:
    		LOG_INF("GNSS: Fix event");
    		break;
    
    	case NRF_MODEM_GNSS_EVT_AGNSS_REQ:
    		LOG_WRN("GNSS: A-GNSS data requested");
    		break;
    
    	case NRF_MODEM_GNSS_EVT_BLOCKED:
    		LOG_WRN("GNSS: Blocked by LTE");
    		dk_set_led_on(GNSS_BLOCKED_LED);
    		break;
    
    	case NRF_MODEM_GNSS_EVT_UNBLOCKED:
    		LOG_INF("GNSS: Unblocked");
    		dk_set_led_off(GNSS_BLOCKED_LED);
    		break;
    
    	case NRF_MODEM_GNSS_EVT_PERIODIC_WAKEUP:
    		LOG_DBG("GNSS: Periodic wakeup");
    		break;
    
    	case NRF_MODEM_GNSS_EVT_SLEEP_AFTER_FIX:
    		LOG_INF("GNSS: Sleep after fix");
    		break;
    
    	case NRF_MODEM_GNSS_EVT_SLEEP_AFTER_TIMEOUT:
    		LOG_WRN("GNSS: Sleep after timeout - no fix");
    		break;
    
    	default:
    		LOG_DBG("GNSS: Unknown event %d", event);
    		break;
    	}
    }
    
    int main(void)
    {
    	int err;
    	
    	LOG_INF("Stratus GNSS sample started");
    
    	if (dk_leds_init() != 0) {
    		LOG_ERR("Failed to initialize the LEDs Library");
    	}
    
    	/* Simple GPIO test first to verify pin driving */
    	err = configure_rf_front_end();
    	if (err) {
    		LOG_ERR("Failed to configure RF front-end: %d", err);
    		return 0;
    	}
    
    	/* Test GPIO toggling to verify pin is working */
    	const struct device *gpio_dev = DEVICE_DT_GET(RF_PWR_GPIO_DEV);
    	LOG_INF("Testing GPIO pin toggling...");
    	for (int i = 0; i < 5; i++) {
    		gpio_pin_set(gpio_dev, RF_PWR_ENABLE_PIN, 1);
    		LOG_INF("Pin %d set HIGH, reading: %d", RF_PWR_ENABLE_PIN, gpio_pin_get(gpio_dev, RF_PWR_ENABLE_PIN));
    		k_sleep(K_SECONDS(2));
    		
    		gpio_pin_set(gpio_dev, RF_PWR_ENABLE_PIN, 0);
    		LOG_INF("Pin %d set LOW, reading: %d", RF_PWR_ENABLE_PIN, gpio_pin_get(gpio_dev, RF_PWR_ENABLE_PIN));
    		k_sleep(K_SECONDS(2));
    	}
    
    	/* Leave pin high for modem test */
    	gpio_pin_set(gpio_dev, RF_PWR_ENABLE_PIN, 1);
    	LOG_INF("Pin %d left HIGH for modem test, reading: %d", RF_PWR_ENABLE_PIN, gpio_pin_get(gpio_dev, RF_PWR_ENABLE_PIN));
    	k_sleep(K_SECONDS(3));
    
    	err = modem_configure_for_lte_gnss();
    	if (err) {
    		LOG_ERR("Failed to configure modem for LTE + GNSS");
    		return 0;
    	}
    
    	/* Wait for LTE connection to establish before starting GNSS */
    	LOG_INF("LTE + GNSS mode activated, waiting for LTE connection...");
    	k_sleep(K_SECONDS(10));
    
    	/* Register the GNSS event handler */
    	if (nrf_modem_gnss_event_handler_set(gnss_event_handler) != 0) {
    		LOG_ERR("Failed to set GNSS event handler");
    		return 0;
    	}
    
    	/* Set the GNSS fix interval and GNSS fix retry period */
    	if (nrf_modem_gnss_fix_interval_set(CONFIG_GNSS_PERIODIC_INTERVAL) != 0) {
    		LOG_ERR("Failed to set GNSS fix interval");
    		return 0;
    	}
    
    	if (nrf_modem_gnss_fix_retry_set(CONFIG_GNSS_PERIODIC_TIMEOUT) != 0) {
    		LOG_ERR("Failed to set GNSS fix retry");
    		return 0;
    	}
    
    	/* Set GNSS to highest priority mode */
    	if (nrf_modem_gnss_prio_mode_enable() != 0) {
    		LOG_WRN("Failed to enable GNSS priority mode, continuing anyway");
    	} else {
    		LOG_INF("GNSS priority mode enabled");
    	}
    
    	/* Start the GNSS receiver */
    	LOG_INF("Starting GNSS");
    	if (nrf_modem_gnss_start() != 0) {
    		LOG_ERR("Failed to start GNSS");
    		return 0;
    	}
    
    	/* Log the current system uptime */
    	gnss_start_time = k_uptime_get();
    
    	return 0;
    }
    

    And the pin diagram:

    I have a feeling it might just be a software issue I'm not seeing.

Reply
  • I'm using MAGPIO exclusively and the CESQ is still 99,99,255,255. I am not sure why. I am using the sample applications from https://github.com/Conexiotechnologies/conexio-firmware-sdk/tree/main/samples/conexio_stratus and modifying it for my board.

    From what I'm seeing the COEX2 isn't being activated (pasted the pin diagram below):

    The GNSS IS working as long as LTE is off. LTE seems to block it.

    00> *** Booting nRF Connect SDK v3.0.2-89ba1294ac9b ***
    00> *** Using Zephyr OS v4.0.99-f791c49f492c ***
    00> [00:00:00.249,511] <inf> GNSS_sample: Stratus GNSS sample started
    00> [00:00:00.249,603] <inf> GNSS_sample: Configuring modem for LTE + GNSS operation...
    00> [00:00:02.520,446] <inf> GNSS_sample: Modem ready
    00> [00:00:02.520,874] <inf> GNSS_sample: Modem FW: mfw_nrf91x1_2.0.2
    00> OK
    00> 
    00> [00:00:02.521,392] <inf> GNSS_sample: IMEI: 359404233656629
    00> OK
    00> 
    00> [00:00:02.521,423] <inf> GNSS_sample: Configuring RF front-end for LTE + GNSS...
    00> [00:00:02.522,521] <wrn> GNSS_sample: RF power pin still low after drive-strength boost
    00> [00:00:02.522,552] <inf> GNSS_sample: Configuring QM13345 MIPI switch for LTE path
    00> [00:00:02.529,113] <wrn> GNSS_sample: QM13345 not found at USID 0x00 (65536), trying 0x0C
    00> [00:00:02.529,602] <err> GNSS_sample: Failed to register QM13345 switch: 65536
    00> [00:00:02.529,602] <wrn> GNSS_sample: Failed to configure MIPI switch: 65536
    00> [00:00:02.529,632] <inf> GNSS_sample: Programming MAGPIO and COEX0 for Stratus board
    00> [00:00:02.530,456] <inf> GNSS_sample: MAGPIO programmed: OK
    00> [00:00:02.531,005] <inf> GNSS_sample: COEX0 programmed: OK
    00> [00:00:02.531,005] <inf> GNSS_sample: Setting modem to CFUN=0...
    00> [00:00:03.565,490] <inf> GNSS_sample: Enabling LTE-M + GNSS mode...
    00> [00:00:03.572,387] <inf> GNSS_sample: Setting modem to full functionality mode (CFUN=1)...
    00> [00:00:03.610,748] <inf> GNSS_sample: Waiting for LTE network registration...
    00> [00:00:18.611,450] <inf> GNSS_sample: System mode: %XSYSTEMMODE: 1,0,1,0
    00> OK
    00> 
    00> [00:00:18.611,816] <inf> GNSS_sample: Functional mode: +CFUN: 1
    00> OK
    00> 
    00> [00:00:18.612,243] <inf> GNSS_sample: LTE Registration: +CEREG: 0,4
    00> OK
    00> 
    00> [00:00:18.612,640] <inf> GNSS_sample: GPRS attach: +CGATT: 0
    00> OK
    00> 
    00> [00:00:18.613,098] <inf> GNSS_sample: Signal quality: +CSQ: 99,99
    00> OK
    00> 
    00> [00:00:18.613,555] <inf> GNSS_sample: Extended signal quality: +CESQ: 99,99,255,255,255,255
    00> OK
    00> 

    Here is my main.c:

    /*
     * Copyright (c) 2024-2025 Conexio Technologies, Inc
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     *
     * Enhanced GNSS Sample with proper modem configuration
     */
    
    #include <stdio.h>
    #include <zephyr/kernel.h>
    #include <zephyr/logging/log.h>
    #include <zephyr/drivers/gpio.h>
    #include <modem/nrf_modem_lib.h>
    #include <modem/lte_lc.h>
    #include <dk_buttons_and_leds.h>
    #include <nrf_modem_at.h>
    #include <nrf_modem_gnss.h>
    #include <math.h>
    #include <string.h>
    #include <hal/nrf_gpio.h>
    
    LOG_MODULE_REGISTER(GNSS_sample, LOG_LEVEL_INF);
    
    /* RF Front-end GPIO definitions */
    #define RF_PWR_GPIO_DEV		DT_NODELABEL(gpio0)
    #define RF_PWR_ENABLE_PIN	22  /* P0.22 -> RFFE_LTE_ENABLE / COEX2 net */
    #define GPS_ENABLE_PIN		19  /* P0.19 -> GPS_EN, low selects LTE path */
    
    /* LED definitions */
    #define GNSS_SEARCHING_LED	DK_LED1
    #define GNSS_FIX_LED		DK_LED2
    #define GNSS_BLOCKED_LED	DK_LED3
    #define ERROR_LED		DK_LED4
    
    /* Button definitions */
    #define START_GNSS_BTN		DK_BTN1_MSK
    #define STOP_GNSS_BTN		DK_BTN2_MSK
    
    /* Define the PVT data frame variable */
    static struct nrf_modem_gnss_pvt_data_frame pvt_data;
    
    /* Declare helper variables to find the TTFF */
    static int64_t gnss_start_time;
    static bool first_fix = false;
    
    static K_SEM_DEFINE(gnss_fix_sem, 0, 1);
    
    /* LTE event handler - simplified version */
    static void lte_handler(const struct lte_lc_evt *evt)
    {
    	if (!evt) {
    		return;
    	}
    
    	switch (evt->type) {
    	case LTE_LC_EVT_NW_REG_STATUS:
    		LOG_INF("CEREG status: %d", evt->nw_reg_status);
    		if (evt->nw_reg_status == LTE_LC_NW_REG_REGISTERED_HOME || 
    		    evt->nw_reg_status == LTE_LC_NW_REG_REGISTERED_ROAMING) {
    			LOG_INF("LTE network registered!");
    		}
    		break;
    	case LTE_LC_EVT_LTE_MODE_UPDATE:
    		LOG_INF("LTE mode update: %d", evt->lte_mode);
    		break;
    	case LTE_LC_EVT_RRC_UPDATE:
    		LOG_INF("RRC %s",
    			evt->rrc_mode == LTE_LC_RRC_MODE_CONNECTED ? "connected" : "idle");
    		break;
    	default:
    		LOG_DBG("Unhandled LTE event: %d", evt->type);
    		break;
    	}
    }
    
    /* RF Front-end configuration functions */
    static int configure_rf_front_end(void)
    {
    	int err;
    	const struct device *gpio_dev = DEVICE_DT_GET(RF_PWR_GPIO_DEV);
    
    	LOG_INF("Configuring RF front-end for LTE + GNSS...");
    
    	if (!device_is_ready(gpio_dev)) {
    		LOG_ERR("GPIO0 device not ready");
    		return -ENODEV;
    	}
    
    	/* Configure RF power enable pin (COEX2) */
    	err = gpio_pin_configure(gpio_dev, RF_PWR_ENABLE_PIN, 
    				 GPIO_OUTPUT_LOW | GPIO_PUSH_PULL | GPIO_ACTIVE_HIGH);
    	if (err) {
    		LOG_ERR("Failed to configure RF power pin: %d", err);
    		return err;
    	}
    
    	/* Configure GPS enable pin for antenna switching */
    	err = gpio_pin_configure(gpio_dev, GPS_ENABLE_PIN, 
    				 GPIO_OUTPUT_LOW | GPIO_PUSH_PULL | GPIO_ACTIVE_HIGH);
    	if (err) {
    		LOG_ERR("Failed to configure GPS_EN pin: %d", err);
    		return err;
    	}
    
    	/* Boost drive strength for COEX2 pin using Nordic HAL - exact match to working diagnostics */
    	nrf_gpio_pin_drive_t drive = NRF_GPIO_PIN_H0H1;
    	nrf_gpio_reconfigure(NRF_GPIO_PIN_MAP(0, RF_PWR_ENABLE_PIN), NULL, NULL, NULL, &drive, NULL);
    
    	/* Enable RF power, set GPS_EN low for LTE path initially - exact sequence */
    	gpio_pin_set(gpio_dev, RF_PWR_ENABLE_PIN, 1);
    	k_sleep(K_MSEC(1));  /* Let the power rail settle */
    
    	/* Verify COEX2 is high - exact same check as working diagnostics */
    	if (!gpio_pin_get(gpio_dev, RF_PWR_ENABLE_PIN)) {
    		LOG_WRN("RF power pin still low after drive-strength boost");
    	} else {
    		LOG_INF("RF power switch asserted, GPS_EN held low");
    	}
    
    	/* Explicitly set GPS_EN low after RF power is on */
    	gpio_pin_set(gpio_dev, GPS_ENABLE_PIN, 0);
    
    	return 0;
    }
    
    static int configure_qm13345_switch(void)
    {
    	int err;
    	char response[64];
    
    	LOG_INF("Configuring QM13345 MIPI switch for LTE path");
    
    	/* Try to register QM13345 at USID 0x00 first - matching working lte_diagnostics */
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT%%XMIPIRFFEDEV=0,0");
    	if (err) {
    		LOG_WRN("QM13345 not found at USID 0x00 (%d), trying 0x0C", err);
    		err = nrf_modem_at_cmd(response, sizeof(response), "AT%%XMIPIRFFEDEV=0,12");
    		if (err) {
    			LOG_ERR("Failed to register QM13345 switch: %d", err);
    			return err;
    		}
    	}
    
    	/* Configure switch for LTE path */
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT%%XMIPIRFFECTRL=0,0,1,0x1C,0x01");
    	if (err) {
    		LOG_ERR("Failed to configure QM13345 INIT phase: %d", err);
    		return err;
    	}
    
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT%%XMIPIRFFECTRL=0,1,1,0x1C,0x01");
    	if (err) {
    		LOG_ERR("Failed to configure QM13345 ON phase: %d", err);
    		return err;
    	}
    
    	LOG_INF("QM13345 switch locked to RF1");
    	return 0;
    }
    
    static int configure_magpio_and_coex(void)
    {
    	int err;
    	char response[128];
    
    	LOG_INF("Programming MAGPIO and COEX0 for Stratus board");
    
    	/* Configure MAGPIO for LTE bands */
    	err = nrf_modem_at_cmd(response, sizeof(response),
    		"AT%%XMAGPIO=1,1,1,7,1,746,803,2,698,748,2,1710,2200,3,824,894,"
    		"4,880,960,5,791,849,7,1565,1586");
    	if (err) {
    		LOG_ERR("MAGPIO programming failed: %d", err);
    		return err;
    	}
    	LOG_INF("MAGPIO programmed: OK");
    
    	/* Configure COEX0 for GNSS coexistence */
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT%%XCOEX0=1,1,1565,1586");
    	if (err) {
    		LOG_ERR("COEX0 programming failed: %d", err);
    		return err;
    	}
    	LOG_INF("COEX0 programmed: OK");
    
    	return 0;
    }
    
    
    /**
     * @brief Configure modem for LTE + GNSS operation with proper RF front-end setup
     */
    static int modem_configure_for_lte_gnss(void)
    {
    	int err;
    	char response[64];
    
    	LOG_INF("Configuring modem for LTE + GNSS operation...");
    
    	/* Initialize modem library first */
    	err = nrf_modem_lib_init();
    	if (err) {
    		if (err == -EALREADY) {
    			LOG_INF("Modem already initialized");
    		} else {
    			LOG_ERR("Failed to initialize modem library: %d", err);
    			return err;
    		}
    	}
    
    	/* Wait for modem to be ready */
    	k_sleep(K_SECONDS(2));
    
    	/* Test modem communication */
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT");
    	if (err) {
    		LOG_ERR("Modem not responding: %d", err);
    		return err;
    	}
    	LOG_INF("Modem ready");
    
    	/* Get modem info */
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT+CGMR");
    	if (err == 0) {
    		LOG_INF("Modem FW: %s", response);
    	}
    
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT+CGSN");
    	if (err == 0) {
    		LOG_INF("IMEI: %s", response);
    	}
    
    	/* Now configure the RF front-end */
    	err = configure_rf_front_end();
    	if (err) {
    		LOG_ERR("Failed to configure RF front-end: %d", err);
    		return err;
    	}
    
    	/* Configure QM13345 MIPI switch */
    	err = configure_qm13345_switch();
    	if (err) {
    		LOG_WRN("Failed to configure MIPI switch: %d", err);
    		/* Continue without MIPI switch - might not be present */
    	}
    
    	/* Configure MAGPIO and COEX0 */
    	err = configure_magpio_and_coex();
    	if (err) {
    		LOG_WRN("Failed to configure antenna settings: %d", err);
    		/* Continue without antenna configuration - will use defaults */
    	}
    
    	/* Turn off modem to change system mode */
    	LOG_INF("Setting modem to CFUN=0...");
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT+CFUN=0");
    	if (err) {
    		LOG_WRN("CFUN=0 request failed: %d", err);
    		/* Continue anyway - modem might already be in correct state */
    	}
    	k_sleep(K_SECONDS(1));
    
    	/* Enable LTE-M + GNSS in system mode (1,0,1,0) */
    	LOG_INF("Enabling LTE-M + GNSS mode...");
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT%%XSYSTEMMODE=1,0,1,0");
    	if (err) {
    		LOG_ERR("Failed to set system mode: %d", err);
    		return err;
    	}
    
    	/* Set modem to full functionality mode with LTE enabled (CFUN=1) */
    	LOG_INF("Setting modem to full functionality mode (CFUN=1)...");
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT+CFUN=1");
    	if (err) {
    		LOG_ERR("Failed to set CFUN=1: %d", err);
    		return err;
    	}
    
    	/* Wait for modem to connect to network automatically */
    	LOG_INF("Waiting for LTE network registration...");
    	k_sleep(K_SECONDS(15));
    
    	/* Verify configuration */
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT%%XSYSTEMMODE?");
    	if (err == 0) {
    		LOG_INF("System mode: %s", response);
    	}
    
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT+CFUN?");
    	if (err == 0) {
    		LOG_INF("Functional mode: %s", response);
    	}
    
    	/* Check LTE registration status and signal quality */
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT+CEREG?");
    	if (err == 0) {
    		LOG_INF("LTE Registration: %s", response);
    	}
    
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT+CGATT?");
    	if (err == 0) {
    		LOG_INF("GPRS attach: %s", response);
    	}
    
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT+CSQ");
    	if (err == 0) {
    		LOG_INF("Signal quality: %s", response);
    	}
    
    	err = nrf_modem_at_cmd(response, sizeof(response), "AT+CESQ");
    	if (err == 0) {
    		LOG_INF("Extended signal quality: %s", response);
    	}
    
    	return 0;
    }
    
    static int modem_init(void)
    {
    	/* Modem initialization is now handled in modem_configure_for_lte_gnss() */
    	return 0;
    }
    
    /* Define a function to log fix data in a readable format */
    static void print_fix_data(struct nrf_modem_gnss_pvt_data_frame *pvt_data)
    {
    	LOG_INF("===========================================");
    	LOG_INF("           GPS POSITION ACQUIRED          ");
    	LOG_INF("===========================================");
    	LOG_INF("Latitude:       %.06f°", pvt_data->latitude);
    	LOG_INF("Longitude:      %.06f°", pvt_data->longitude);
    	LOG_INF("Altitude:       %.01f m", pvt_data->altitude);
    	LOG_INF("Accuracy:       %.01f m", pvt_data->accuracy);
    	LOG_INF("Speed:          %.01f m/s", pvt_data->speed);
    	LOG_INF("Heading:        %.01f°", pvt_data->heading);
    	LOG_INF("Time (UTC):     %04u-%02u-%02u %02u:%02u:%02u.%03u",
    	       pvt_data->datetime.year,
    	       pvt_data->datetime.month,
    	       pvt_data->datetime.day,
    	       pvt_data->datetime.hour,
    	       pvt_data->datetime.minute,
    	       pvt_data->datetime.seconds,
    	       pvt_data->datetime.ms);
    	LOG_INF("Google Maps:    https://maps.google.com/?q=%.6f,%.6f",
    	       pvt_data->latitude, pvt_data->longitude);
    	LOG_INF("===========================================");
    }
    
    static void gnss_event_handler(int event)
    {
    	int err;
    	static int satellites_tracked = 0;
    
    	switch (event) {
    	case NRF_MODEM_GNSS_EVT_PVT:
    		err = nrf_modem_gnss_read(&pvt_data, sizeof(pvt_data), NRF_MODEM_GNSS_DATA_PVT);
    		if (err) {
    			LOG_ERR("Failed to read PVT data: %d", err);
    			return;
    		}
    
    		/* Count satellites */
    		satellites_tracked = 0;
    		for (int i = 0; i < 12; i++) {
    			if (pvt_data.sv[i].signal != 0) {
    				satellites_tracked++;
    			}
    		}
    
    		if (pvt_data.flags & NRF_MODEM_GNSS_PVT_FLAG_FIX_VALID) {
    			/* Fix acquired! */
    			dk_set_led_off(GNSS_SEARCHING_LED);
    			dk_set_led_on(GNSS_FIX_LED);
    
    			print_fix_data(&pvt_data);
    
    			/* Print time to first fix */
    			if (!first_fix) {
    				LOG_INF("Time to first fix: %lld seconds",
    					(k_uptime_get() - gnss_start_time) / 1000);
    				first_fix = true;
    			}
    
    			k_sem_give(&gnss_fix_sem);
    		} else {
    			/* No fix yet */
    			dk_set_led_on(GNSS_SEARCHING_LED);
    			dk_set_led_off(GNSS_FIX_LED);
    
    			LOG_INF("GNSS: Searching for fix... (Satellites tracked: %d)",
    				satellites_tracked);
    		}
    		break;
    
    	case NRF_MODEM_GNSS_EVT_FIX:
    		LOG_INF("GNSS: Fix event");
    		break;
    
    	case NRF_MODEM_GNSS_EVT_AGNSS_REQ:
    		LOG_WRN("GNSS: A-GNSS data requested");
    		break;
    
    	case NRF_MODEM_GNSS_EVT_BLOCKED:
    		LOG_WRN("GNSS: Blocked by LTE");
    		dk_set_led_on(GNSS_BLOCKED_LED);
    		break;
    
    	case NRF_MODEM_GNSS_EVT_UNBLOCKED:
    		LOG_INF("GNSS: Unblocked");
    		dk_set_led_off(GNSS_BLOCKED_LED);
    		break;
    
    	case NRF_MODEM_GNSS_EVT_PERIODIC_WAKEUP:
    		LOG_DBG("GNSS: Periodic wakeup");
    		break;
    
    	case NRF_MODEM_GNSS_EVT_SLEEP_AFTER_FIX:
    		LOG_INF("GNSS: Sleep after fix");
    		break;
    
    	case NRF_MODEM_GNSS_EVT_SLEEP_AFTER_TIMEOUT:
    		LOG_WRN("GNSS: Sleep after timeout - no fix");
    		break;
    
    	default:
    		LOG_DBG("GNSS: Unknown event %d", event);
    		break;
    	}
    }
    
    int main(void)
    {
    	int err;
    	
    	LOG_INF("Stratus GNSS sample started");
    
    	if (dk_leds_init() != 0) {
    		LOG_ERR("Failed to initialize the LEDs Library");
    	}
    
    	/* Simple GPIO test first to verify pin driving */
    	err = configure_rf_front_end();
    	if (err) {
    		LOG_ERR("Failed to configure RF front-end: %d", err);
    		return 0;
    	}
    
    	/* Test GPIO toggling to verify pin is working */
    	const struct device *gpio_dev = DEVICE_DT_GET(RF_PWR_GPIO_DEV);
    	LOG_INF("Testing GPIO pin toggling...");
    	for (int i = 0; i < 5; i++) {
    		gpio_pin_set(gpio_dev, RF_PWR_ENABLE_PIN, 1);
    		LOG_INF("Pin %d set HIGH, reading: %d", RF_PWR_ENABLE_PIN, gpio_pin_get(gpio_dev, RF_PWR_ENABLE_PIN));
    		k_sleep(K_SECONDS(2));
    		
    		gpio_pin_set(gpio_dev, RF_PWR_ENABLE_PIN, 0);
    		LOG_INF("Pin %d set LOW, reading: %d", RF_PWR_ENABLE_PIN, gpio_pin_get(gpio_dev, RF_PWR_ENABLE_PIN));
    		k_sleep(K_SECONDS(2));
    	}
    
    	/* Leave pin high for modem test */
    	gpio_pin_set(gpio_dev, RF_PWR_ENABLE_PIN, 1);
    	LOG_INF("Pin %d left HIGH for modem test, reading: %d", RF_PWR_ENABLE_PIN, gpio_pin_get(gpio_dev, RF_PWR_ENABLE_PIN));
    	k_sleep(K_SECONDS(3));
    
    	err = modem_configure_for_lte_gnss();
    	if (err) {
    		LOG_ERR("Failed to configure modem for LTE + GNSS");
    		return 0;
    	}
    
    	/* Wait for LTE connection to establish before starting GNSS */
    	LOG_INF("LTE + GNSS mode activated, waiting for LTE connection...");
    	k_sleep(K_SECONDS(10));
    
    	/* Register the GNSS event handler */
    	if (nrf_modem_gnss_event_handler_set(gnss_event_handler) != 0) {
    		LOG_ERR("Failed to set GNSS event handler");
    		return 0;
    	}
    
    	/* Set the GNSS fix interval and GNSS fix retry period */
    	if (nrf_modem_gnss_fix_interval_set(CONFIG_GNSS_PERIODIC_INTERVAL) != 0) {
    		LOG_ERR("Failed to set GNSS fix interval");
    		return 0;
    	}
    
    	if (nrf_modem_gnss_fix_retry_set(CONFIG_GNSS_PERIODIC_TIMEOUT) != 0) {
    		LOG_ERR("Failed to set GNSS fix retry");
    		return 0;
    	}
    
    	/* Set GNSS to highest priority mode */
    	if (nrf_modem_gnss_prio_mode_enable() != 0) {
    		LOG_WRN("Failed to enable GNSS priority mode, continuing anyway");
    	} else {
    		LOG_INF("GNSS priority mode enabled");
    	}
    
    	/* Start the GNSS receiver */
    	LOG_INF("Starting GNSS");
    	if (nrf_modem_gnss_start() != 0) {
    		LOG_ERR("Failed to start GNSS");
    		return 0;
    	}
    
    	/* Log the current system uptime */
    	gnss_start_time = k_uptime_get();
    
    	return 0;
    }
    

    And the pin diagram:

    I have a feeling it might just be a software issue I'm not seeing.

Children
Related