Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

modem_cellular: add RSRP &RSRQ to U-blox SARA-R5 modem #67025

Merged
merged 1 commit into from Jan 16, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
78 changes: 72 additions & 6 deletions drivers/modem/modem_cellular.c
Expand Up @@ -33,6 +33,16 @@ LOG_MODULE_REGISTER(modem_cellular, CONFIG_MODEM_LOG_LEVEL);
#define MODEM_CELLULAR_DATA_MANUFACTURER_LEN (64)
#define MODEM_CELLULAR_DATA_FW_VERSION_LEN (64)

/* Magic constants */
#define CSQ_RSSI_UNKNOWN (99)
#define CESQ_RSRP_UNKNOWN (255)
#define CESQ_RSRQ_UNKNOWN (255)

/* Magic numbers to units conversions */
#define CSQ_RSSI_TO_DB(v) (-113 + (2 * (rssi)))
#define CESQ_RSRP_TO_DB(v) (-140 + (v))
#define CESQ_RSRQ_TO_DB(v) (-20 + ((v) / 2))

enum modem_cellular_state {
MODEM_CELLULAR_STATE_IDLE = 0,
MODEM_CELLULAR_STATE_RESET_PULSE,
Expand Down Expand Up @@ -95,6 +105,8 @@ struct modem_cellular_data {
uint8_t registration_status_gprs;
uint8_t registration_status_lte;
uint8_t rssi;
uint8_t rsrp;
uint8_t rsrq;
uint8_t imei[MODEM_CELLULAR_DATA_IMEI_LEN];
uint8_t model_id[MODEM_CELLULAR_DATA_MODEL_ID_LEN];
uint8_t imsi[MODEM_CELLULAR_DATA_IMSI_LEN];
Expand Down Expand Up @@ -340,6 +352,19 @@ static void modem_cellular_chat_on_csq(struct modem_chat *chat, char **argv, uin
data->rssi = (uint8_t)atoi(argv[1]);
}

static void modem_cellular_chat_on_cesq(struct modem_chat *chat, char **argv, uint16_t argc,
void *user_data)
{
struct modem_cellular_data *data = (struct modem_cellular_data *)user_data;

if (argc != 7) {
return;
}

data->rsrq = (uint8_t)atoi(argv[5]);
data->rsrp = (uint8_t)atoi(argv[6]);
}

static void modem_cellular_chat_on_imsi(struct modem_chat *chat, char **argv, uint16_t argc,
void *user_data)
{
Expand Down Expand Up @@ -398,6 +423,7 @@ MODEM_CHAT_MATCHES_DEFINE(allow_match,
MODEM_CHAT_MATCH_DEFINE(imei_match, "", "", modem_cellular_chat_on_imei);
MODEM_CHAT_MATCH_DEFINE(cgmm_match, "", "", modem_cellular_chat_on_cgmm);
MODEM_CHAT_MATCH_DEFINE(csq_match, "+CSQ: ", ",", modem_cellular_chat_on_csq);
MODEM_CHAT_MATCH_DEFINE(cesq_match, "+CESQ: ", ",", modem_cellular_chat_on_cesq);
MODEM_CHAT_MATCH_DEFINE(cimi_match, "", "", modem_cellular_chat_on_imsi);
MODEM_CHAT_MATCH_DEFINE(cgmi_match, "", "", modem_cellular_chat_on_cgmi);
MODEM_CHAT_MATCH_DEFINE(cgmr_match, "", "", modem_cellular_chat_on_cgmr);
Expand Down Expand Up @@ -1253,11 +1279,44 @@ static inline int modem_cellular_csq_parse_rssi(uint8_t rssi, int16_t *value)
* - ber is an integer from 0 to 7 that describes the error rate, it can also
* be 99 for an unknown error rate
*/
if (rssi == 99) {
if (rssi == CSQ_RSSI_UNKNOWN) {
return -EINVAL;
}

*value = (int16_t)CSQ_RSSI_TO_DB(rssi);
return 0;
}

MODEM_CHAT_SCRIPT_CMDS_DEFINE(get_signal_cesq_chat_script_cmds,
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CESQ", cesq_match),
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match));

MODEM_CHAT_SCRIPT_DEFINE(get_signal_cesq_chat_script, get_signal_cesq_chat_script_cmds,
abort_matches, modem_cellular_chat_callback_handler, 2);

/* AT+CESQ returns a response +CESQ: <rxlev>,<ber>,<rscp>,<ecn0>,<rsrq>,<rsrp> where:
* - rsrq is a integer from 0 to 34 whose values describes the Reference Signal Receive
* Quality between -20 dB for 0 and -3 dB for 34 (0.5 dB steps), or unknown for 255
* - rsrp is an integer from 0 to 97 that describes the Reference Signal Receive Power
* between -140 dBm for 0 and -44 dBm for 97 (1 dBm steps), or unknown for 255
*/
static inline int modem_cellular_cesq_parse_rsrp(uint8_t rsrp, int16_t *value)
{
if (rsrp == CESQ_RSRP_UNKNOWN) {
return -EINVAL;
}

*value = (int16_t)CESQ_RSRP_TO_DB(rsrp);
return 0;
}

static inline int modem_cellular_cesq_parse_rsrq(uint8_t rsrq, int16_t *value)
{
if (rsrq == CESQ_RSRQ_UNKNOWN) {
return -EINVAL;
}

*value = (int16_t)(-113 + (2 * rssi));
*value = (int16_t)CESQ_RSRQ_TO_DB(rsrq);
return 0;
}

Expand All @@ -1281,8 +1340,7 @@ static int modem_cellular_get_signal(const struct device *dev,

case CELLULAR_SIGNAL_RSRP:
case CELLULAR_SIGNAL_RSRQ:
/* TODO: Run CESQ script */
ret = -ENOTSUP;
ret = modem_chat_run_script(&data->chat, &get_signal_cesq_chat_script);
break;

default:
Expand All @@ -1302,9 +1360,11 @@ static int modem_cellular_get_signal(const struct device *dev,
break;

case CELLULAR_SIGNAL_RSRP:
ret = modem_cellular_cesq_parse_rsrp(data->rsrp, value);
break;

case CELLULAR_SIGNAL_RSRQ:
/* TODO: Validate and set values */
ret = -ENODATA;
ret = modem_cellular_cesq_parse_rsrq(data->rsrq, value);
break;

default:
Expand Down Expand Up @@ -1744,6 +1804,12 @@ MODEM_CHAT_SCRIPT_CMDS_DEFINE(u_blox_sara_r5_init_chat_script_cmds,
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match),
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMI", cgmi_match),
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMR", cgmr_match),
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CIMI", cimi_match),
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMUX=0,0,5,127", ok_match));

MODEM_CHAT_SCRIPT_DEFINE(u_blox_sara_r5_init_chat_script, u_blox_sara_r5_init_chat_script_cmds,
Expand Down