Skip to content

Commit cf50540

Browse files
committed
Implements PARTICLE_CELLULAR_PREFERRED_BANDS / PARTICLE_CELLULAR_FORBIDDEN_BANDS
1 parent 729faaf commit cf50540

File tree

5 files changed

+353
-22
lines changed

5 files changed

+353
-22
lines changed

hal/network/ncp_client/quectel/quectel_ncp_client.cpp

Lines changed: 142 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,26 @@ const auto QUECTEL_NCP_MAX_MUXER_FRAME_SIZE = 1509;
101101
const auto QUECTEL_NCP_KEEPALIVE_PERIOD = 5000; // milliseconds
102102
const auto QUECTEL_NCP_KEEPALIVE_MAX_MISSED = 5;
103103

104+
// Bandmask same for BG95-M1 ~ BG95-M6 & BG95-MF
105+
// Note: BG95-M1 does not support NB mode
106+
// BG95-M4 not supported (bands are different as well)
107+
const uint64_t QUECTEL_NCP_BANDMASK_CATM1_1_64_BG95 = 0xF0E189F; // Bands 1,2,3,4,5,8,12,13,18,19,20,25,26,27,28 [all default enabled]
108+
const uint64_t QUECTEL_NCP_BANDMASK_CATM1_65_128_BG95 = 0x100002; // Band 66,85 enabled
109+
const uint64_t QUECTEL_NCP_BANDMASK_CATNB_1_64_BG95 = 0x90E189F; // Bands 1,2,3,4,5,8,12,13,18,19,20,25,26,27,28 [all default enabled]
110+
const uint64_t QUECTEL_NCP_BANDMASK_CATNB_65_128_BG95 = 0x100002; // Band 66,85 enabled
111+
112+
// BG96-MC
113+
const uint64_t QUECTEL_NCP_BANDMASK_CATM1_1_64_BG96_MC = 0xF8E189F; // Bands 1,2,3,4,5,8,12,13,18,19,20,25,26,28,39
114+
const uint64_t QUECTEL_NCP_BANDMASK_CATNB_1_64_BG96_MC = 0xF8E189F; // Bands 1,2,3,4,5,8,12,19,19,20,25,26,28,39
115+
116+
// EG91-E/EX (LTE Cat-1)
117+
const uint64_t QUECTEL_NCP_BANDMASK_CAT1_1_64_EG91_E_EX = 0x1010008D; // Bands 1,3,7,8,20,28
118+
// const uint64_t QUECTEL_NCP_BANDMASK_CAT1_65_128_EG91_E_EX = 0x0; // No bands in 65-128 range
119+
120+
// EG91-NAX (LTE Cat-1)
121+
const uint64_t QUECTEL_NCP_BANDMASK_CAT1_1_64_EG91_NA_NAX = 0x1836; // Bands 2,4,5,12,13
122+
// const uint64_t QUECTEL_NCP_BANDMASK_CAT1_65_128_EG91_NA_NAX = 0x0; // No bands in 65-128 range
123+
104124
// FIXME: for now using a very large buffer
105125
const auto QUECTEL_NCP_AT_CHANNEL_RX_BUFFER_SIZE = 4096;
106126
const auto QUECTEL_NCP_PPP_CHANNEL_RX_BUFFER_SIZE = 256;
@@ -1022,6 +1042,109 @@ int QuectelNcpClient::checkNetConfForImsi() {
10221042
return SYSTEM_ERROR_TIMEOUT;
10231043
}
10241044

1045+
int QuectelNcpClient::setupBands() {
1046+
uint64_t envPreferredBands[2] = {};
1047+
uint64_t envForbiddenBands[2] = {};
1048+
getEnvBands("PARTICLE_CELLULAR_PREFERRED_BANDS", envPreferredBands);
1049+
getEnvBands("PARTICLE_CELLULAR_FORBIDDEN_BANDS", envForbiddenBands);
1050+
bool useEnvBands = (envPreferredBands[0] || envPreferredBands[1] || envForbiddenBands[0] || envForbiddenBands[1]);
1051+
1052+
// At least one set of bands is set, ensure the rest have default values if not specified
1053+
if (useEnvBands) {
1054+
if (envPreferredBands[0]) {
1055+
if (isQuecBG95xDevice()) {
1056+
envPreferredBands[0] = envPreferredBands[0] & QUECTEL_NCP_BANDMASK_CATM1_1_64_BG95;
1057+
} else if (ncpId() == PLATFORM_NCP_QUECTEL_BG96) {
1058+
envPreferredBands[0] = envPreferredBands[0] & QUECTEL_NCP_BANDMASK_CATM1_1_64_BG96_MC;
1059+
} else if (ncpId() == PLATFORM_NCP_QUECTEL_EG91_NAX || ncpId() == PLATFORM_NCP_QUECTEL_EG91_NA) {
1060+
envPreferredBands[0] = envPreferredBands[0] & QUECTEL_NCP_BANDMASK_CAT1_1_64_EG91_NA_NAX;
1061+
} else if (ncpId() == PLATFORM_NCP_QUECTEL_EG91_E || ncpId() == PLATFORM_NCP_QUECTEL_EG91_EX) {
1062+
envPreferredBands[0] = envPreferredBands[0] & QUECTEL_NCP_BANDMASK_CAT1_1_64_EG91_E_EX;
1063+
}
1064+
} else {
1065+
if (isQuecBG95xDevice()) {
1066+
envPreferredBands[0] = QUECTEL_NCP_BANDMASK_CATM1_1_64_BG95;
1067+
} else if (ncpId() == PLATFORM_NCP_QUECTEL_BG96) {
1068+
envPreferredBands[0] = QUECTEL_NCP_BANDMASK_CATM1_1_64_BG96_MC;
1069+
} else if (ncpId() == PLATFORM_NCP_QUECTEL_EG91_NAX || ncpId() == PLATFORM_NCP_QUECTEL_EG91_NA) {
1070+
envPreferredBands[0] = QUECTEL_NCP_BANDMASK_CAT1_1_64_EG91_NA_NAX;
1071+
} else if (ncpId() == PLATFORM_NCP_QUECTEL_EG91_E || ncpId() == PLATFORM_NCP_QUECTEL_EG91_EX) {
1072+
envPreferredBands[0] = QUECTEL_NCP_BANDMASK_CAT1_1_64_EG91_E_EX;
1073+
}
1074+
}
1075+
if (envPreferredBands[1]) {
1076+
if (isQuecBG95xDevice()) {
1077+
envPreferredBands[1] = envPreferredBands[1] & QUECTEL_NCP_BANDMASK_CATM1_65_128_BG95;
1078+
} else if (ncpId() == PLATFORM_NCP_QUECTEL_BG96) {
1079+
envPreferredBands[1] = 0;
1080+
} else if (ncpId() == PLATFORM_NCP_QUECTEL_EG91_NAX || ncpId() == PLATFORM_NCP_QUECTEL_EG91_NA) {
1081+
envPreferredBands[1] = 0;
1082+
} else if (ncpId() == PLATFORM_NCP_QUECTEL_EG91_E || ncpId() == PLATFORM_NCP_QUECTEL_EG91_EX) {
1083+
envPreferredBands[1] = 0;
1084+
}
1085+
} else {
1086+
if (isQuecBG95xDevice()) {
1087+
envPreferredBands[1] = QUECTEL_NCP_BANDMASK_CATM1_65_128_BG95;
1088+
}
1089+
// These are effectively zero already, save some bytes
1090+
// else if (ncpId() == PLATFORM_NCP_QUECTEL_BG96) {
1091+
// envPreferredBands[1] = 0;
1092+
// } else if (ncpId() == PLATFORM_NCP_QUECTEL_EG91_NAX || ncpId() == PLATFORM_NCP_QUECTEL_EG91_NA) {
1093+
// envPreferredBands[1] = 0;
1094+
// } else if (ncpId() == PLATFORM_NCP_QUECTEL_EG91_E || ncpId() == PLATFORM_NCP_QUECTEL_EG91_EX) {
1095+
// envPreferredBands[1] = 0;
1096+
// }
1097+
}
1098+
envPreferredBands[0] = envPreferredBands[0] & ~envForbiddenBands[0];
1099+
envPreferredBands[1] = envPreferredBands[1] & ~envForbiddenBands[1];
1100+
} else {
1101+
// Simplify and reuse these variables with default bandmask if env var not set
1102+
if (isQuecBG95xDevice()) {
1103+
envPreferredBands[0] = QUECTEL_NCP_BANDMASK_CATM1_1_64_BG95;
1104+
envPreferredBands[1] = QUECTEL_NCP_BANDMASK_CATM1_65_128_BG95;
1105+
} else if (ncpId() == PLATFORM_NCP_QUECTEL_BG96) {
1106+
envPreferredBands[0] = QUECTEL_NCP_BANDMASK_CATM1_1_64_BG96_MC;
1107+
// envPreferredBands[1] = 0; // This is effectively zero already, save some bytes
1108+
} else if (ncpId() == PLATFORM_NCP_QUECTEL_EG91_NAX || ncpId() == PLATFORM_NCP_QUECTEL_EG91_NA) {
1109+
envPreferredBands[0] = QUECTEL_NCP_BANDMASK_CAT1_1_64_EG91_NA_NAX;
1110+
// envPreferredBands[1] = 0; // This is effectively zero already, save some bytes
1111+
} else if (ncpId() == PLATFORM_NCP_QUECTEL_EG91_E || ncpId() == PLATFORM_NCP_QUECTEL_EG91_EX) {
1112+
envPreferredBands[0] = QUECTEL_NCP_BANDMASK_CAT1_1_64_EG91_E_EX;
1113+
// envPreferredBands[1] = 0; // This is effectively zero already, save some bytes
1114+
}
1115+
}
1116+
// LOG(INFO, "ENV BANDS: [65-128]=0x%llx, [1-64]=0x%016llx", envPreferredBands[1], envPreferredBands[0]);
1117+
1118+
// Log bandmask, and change bandmask if necessary
1119+
auto respBand = parser_.sendCommand("AT+QCFG=\"band\"");
1120+
uint64_t uint64LTEbandsCurrent[2] = {};
1121+
char qbandGSM_Str[4+1] = {};
1122+
char qbandLTE_Str[32+1] = {};
1123+
char qbandCatNB_Str[32+1] = {};
1124+
// BG95_M5: +QCFG: "band",0xf,0x100002000000000f0e189f,0x10004200000000090e189f <GSM>,<CAT-M1-1-128>,<CAT-NB-1-128>
1125+
auto retBand = CHECK_PARSER(respBand.scanf("+QCFG: \"band\",0x%4[^,],0x%32[^,],0x%32[^,]", qbandGSM_Str, qbandLTE_Str, qbandCatNB_Str));
1126+
LOG(INFO, "%s,%s,%s", qbandGSM_Str, qbandLTE_Str, qbandCatNB_Str);
1127+
CHECK_PARSER_OK(respBand.readResult());
1128+
1129+
if (retBand == 3) {
1130+
if (isQuecBG95xDevice()) {
1131+
hexString128toUint64Array(qbandLTE_Str, uint64LTEbandsCurrent);
1132+
// LOG(INFO, "[65-128]=0x%llx, [1-64]=0x%016llx", uint64LTEbandsCurrent[1], uint64LTEbandsCurrent[0]);
1133+
1134+
if (uint64LTEbandsCurrent[0] != envPreferredBands[0] ||
1135+
uint64LTEbandsCurrent[1] != envPreferredBands[1]) {
1136+
sprintf(qbandLTE_Str, "%llx%016llx", envPreferredBands[1], envPreferredBands[0]);
1137+
// Apply band changes immediately, no reboot required. Modem may need to disconnect to apply the change though.
1138+
CHECK_PARSER_OK(setModuleFunctionality(CellularFunctionality::AIRPLANE, true /* check */));
1139+
CHECK_PARSER_OK(parser_.execCommand("AT+QCFG=\"band\",%s,%s,%s,1", qbandGSM_Str, qbandLTE_Str, qbandCatNB_Str));
1140+
CHECK_PARSER_OK(setModuleFunctionality(CellularFunctionality::FULL, false /* check */));
1141+
}
1142+
}
1143+
}
1144+
1145+
return SYSTEM_ERROR_NONE;
1146+
}
1147+
10251148
int QuectelNcpClient::selectSimCard() {
10261149
// Using numeric CME ERROR codes
10271150
// int r = CHECK_PARSER(parser_.execCommand("AT+CMEE=2"));
@@ -1148,6 +1271,7 @@ int QuectelNcpClient::initReady(ModemState state) {
11481271
setPolicymanServiceMode(CellularPolicymanServiceMode::FULL_SERVICE, true /* check */);
11491272
}
11501273

1274+
auto runtimeBaudrate = QUECTEL_NCP_DEFAULT_SERIAL_BAUDRATE;
11511275
if (state != ModemState::MuxerAtChannel) {
11521276
// Cold Boot only, Warm Boot will skip the following block...
11531277

@@ -1167,7 +1291,7 @@ int QuectelNcpClient::initReady(ModemState state) {
11671291
CHECK_PARSER_OK(parser_.execCommand("AT+IFC=2,2"));
11681292
CHECK(waitAtResponse(10000));
11691293
}
1170-
auto runtimeBaudrate = getRuntimeBaudrate();
1294+
runtimeBaudrate = getRuntimeBaudrate();
11711295
CHECK(changeBaudRate(runtimeBaudrate));
11721296
// Check that the modem is responsive at the new baudrate
11731297
skipAll(serial_.get(), 1000);
@@ -1196,7 +1320,18 @@ int QuectelNcpClient::initReady(ModemState state) {
11961320
if (isQuecCat1Device()) {
11971321
CHECK_PARSER(parser_.execCommand("AT+QDSIM=0"));
11981322
}
1323+
}
11991324

1325+
if (isQuecBG95xDevice() ||
1326+
ncpId() == PLATFORM_NCP_QUECTEL_BG96 ||
1327+
ncpId() == PLATFORM_NCP_QUECTEL_EG91_NAX ||
1328+
ncpId() == PLATFORM_NCP_QUECTEL_EG91_NA ||
1329+
ncpId() == PLATFORM_NCP_QUECTEL_EG91_E ||
1330+
ncpId() == PLATFORM_NCP_QUECTEL_EG91_EX) {
1331+
CHECK(setupBands());
1332+
}
1333+
1334+
if (state != ModemState::MuxerAtChannel) {
12001335
// Send AT+CMUX and initialize multiplexer
12011336
int portspeed;
12021337
switch (runtimeBaudrate) {
@@ -1211,9 +1346,10 @@ int QuectelNcpClient::initReady(ModemState state) {
12111346
default:
12121347
return SYSTEM_ERROR_INVALID_ARGUMENT;
12131348
}
1349+
12141350
// XXX: AT+CMUX=? says portspeed value range is (1-7), but 8 is required for it to work on BG95-M5
12151351
r = CHECK_PARSER(parser_.execCommand("AT+CMUX=0,0,%d,%u,,,,,", portspeed, QUECTEL_NCP_MAX_MUXER_FRAME_SIZE));
1216-
CHECK_TRUE(r == AtResponse::OK, SYSTEM_ERROR_UNKNOWN);
1352+
CHECK_TRUE(r == AtResponse::OK, SYSTEM_ERROR_AT_NOT_OK);
12171353

12181354
// Initialize muxer
12191355
CHECK(initMuxer());
@@ -1446,7 +1582,7 @@ int QuectelNcpClient::setPolicymanServiceMode(CellularPolicymanServiceMode mode,
14461582
int QuectelNcpClient::configureApn(const CellularNetworkConfig& conf) {
14471583
// IMPORTANT: Set modem full functionality!
14481584
// Otherwise we won't be able to query ICCID/IMSI
1449-
CHECK_PARSER_OK(parser_.execCommand("AT+CFUN=1,0"));
1585+
CHECK_PARSER_OK(setModuleFunctionality(CellularFunctionality::FULL, true /* check */));
14501586

14511587
netConf_ = conf;
14521588
if (!netConf_.isValid()) {
@@ -1522,7 +1658,7 @@ int QuectelNcpClient::configureApn(const CellularNetworkConfig& conf) {
15221658
// setApn, cgdcontIpVal, cgdcontApnVal, cgdcontFmt, netConf_.hasApn(),
15231659
// netConf_.apn(), strncmp(cgdcontApnVal, netConf_.hasApn() ? netConf_.apn() : "", sizeof(cgdcontApnVal)) != 0);
15241660
if (setApn) {
1525-
CHECK_PARSER_OK(parser_.execCommand("AT+CFUN=4,0")); // airplane mode
1661+
CHECK_PARSER_OK(setModuleFunctionality(CellularFunctionality::AIRPLANE, true /* check */));
15261662
// XXX: we've seen CGDCONT fail on cold boot, retrying here a few times
15271663
for (int i = 0; i < CGDCONT_ATTEMPTS; i++) {
15281664
// FIXME: for now IPv4 context only
@@ -1545,9 +1681,10 @@ int QuectelNcpClient::configureApn(const CellularNetworkConfig& conf) {
15451681
int QuectelNcpClient::registerNet() {
15461682
int r = 0;
15471683
// Set modem full functionality
1548-
r = CHECK_PARSER(parser_.execCommand("AT+CFUN=1,0"));
1684+
r = CHECK_PARSER(setModuleFunctionality(CellularFunctionality::FULL, true /* check */));
15491685
CHECK_TRUE(r == AtResponse::OK, SYSTEM_ERROR_UNKNOWN);
15501686

1687+
15511688
resetRegistrationState();
15521689

15531690
if (isQuecCat1Device() || ncpId() == PLATFORM_NCP_QUECTEL_BG95_M5) {

hal/network/ncp_client/quectel/quectel_ncp_client.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ class QuectelNcpClient: public CellularNcpClient {
129129
int waitAtResponse(unsigned int timeout, unsigned int period = 1000);
130130
int waitAtResponse(AtParser& parser, unsigned int timeout, unsigned int period = 1000);
131131
int checkNetConfForImsi();
132+
int setupBands();
132133
int selectSimCard();
133134
int checkSimCard();
134135
int getModuleFunctionality();

0 commit comments

Comments
 (0)