SP8EBC-ParaTNC/system/src/gsm/sim800c_engineering.c

213 wiersze
6.0 KiB
C

/*
* sim800c_engineering.c
*
* Created on: Jan 26, 2022
* Author: mateusz
*/
#include "gsm/sim800c_engineering.h"
#include "gsm/sim800c.h"
#include "drivers/serial.h"
#include <string.h>
#include <stdlib.h>
const char * ENGINEERING_ENABLE = "AT+CENG=4,0\r\0";
const char * ENGINEERING_DISABLE = "AT+CENG=0,0\r\0";
const char * ENGINEERING_GET = "AT+CENG?\r\0";
static const char * OK = "OK\r\n\0";
static const char * CENG0 = "+CENG: 0,\0";
#define CENG0_RECORD_LN 77 // including '+CENG' heading
#define ARFCN_OFFSET 10
#define ARFCN_LN 4
#define CELLID_OFFSET 31
#define CELLID_LN 4
#define LAC_OFFSET 42
#define LAC_LN 4
/**
* Set to one if correct response to engineering enable AT command
* has been received
*/
uint8_t gsm_sim800_engineering_is_enabled = 0;
/**
* set to one if correct response has been received for engineering data request
* and new engineering data have been read. This is reset back to zero
* after disabling CENG or after 'gsm_sim800_engineering_request_data' is called
*/
uint8_t gsm_sim800_engineering_successed = 0;
/**
* Set to one in case of any failure during engineering AT commands communication
*/
uint8_t gsm_sim800_engineering_fail = 0;
static uint16_t gsm_sim800_rewind_to_ceng_0(uint8_t *srl_rx_buf_pointer, uint16_t buffer_ln, uint16_t gsm_response_start_idx) {
int comparision_result = 123;
// iterator over data returned by the modem
int i = gsm_response_start_idx;
// calculate the length of CENG0 term to omit recalculation each loop iteration
int ceng_ln = strlen(CENG0);
for (; (i < buffer_ln - ceng_ln) && *(srl_rx_buf_pointer + i) != 0; i++) {
comparision_result = memcmp((const void*)CENG0, srl_rx_buf_pointer + i, ceng_ln);
if (comparision_result == 0) {
return i;
}
}
return 0xFFFF;
}
static void gsm_sim800_engineering_parse_ceng_0(uint8_t *srl_rx_buf_pointer, uint16_t ceng_0_payload_start) {
/**
* Details:0x20000828 <srl_usart3_rx_buffer>
* "AT+CENG?\r\r\n
* +CENG: 4,0\r\n\r\n
* +CENG: 0,\"0037,44,00,260,01,43,67f4,05,05,539d,255,-69,145,145,x,x,x,x,x,x,x\"\r\n
* +CENG: 1,\"0009,25,61,260,01,539d,80,56\"\r\n
* +CENG: 2,\"0008,25,15,260,01,539d,78,54\"\r\n+CENG: 3,\"0038"...
*
*/
// temporary buffer for strings
char string_buffer[5];
// temporary variable for string -> int conversion
int integer = 0;
// zeroing string buffer
memset(string_buffer, 0x0, sizeof(string_buffer));
// check if the record has been found
if (ceng_0_payload_start > (0xFFFF - CENG0_RECORD_LN)) {
return;
}
// copying ARFCN
memcpy(string_buffer, srl_rx_buf_pointer + ceng_0_payload_start + ARFCN_OFFSET, ARFCN_LN);
// converting ARFCN to integer
integer = atoi(string_buffer);
if (integer < 125) {
gsm_sim800_bcch_frequency = 890.0f + 0.2f * integer + 45.0f;
}
else if (integer > 511 && integer < 886) {
gsm_sim800_bcch_frequency = 1710.2f + 0.2f * (integer - 512) + 95.0f;
}
else if (integer > 974 && integer < 1024) {
gsm_sim800_bcch_frequency = 890.0f + 0.2f * (integer - 1024) + 45.0f;
}
// zeroing string buffer
memset(string_buffer, 0x0, sizeof(string_buffer));
// copying CELL-ID string
memcpy(gsm_sim800_cellid, srl_rx_buf_pointer + ceng_0_payload_start + CELLID_OFFSET, CELLID_LN);
// copying LAC
memcpy(gsm_sim800_lac, srl_rx_buf_pointer + ceng_0_payload_start + LAC_OFFSET, LAC_LN);
}
void gsm_sim800_engineering_enable(srl_context_t * srl_context, gsm_sim800_state_t * state) {
if (*state == SIM800_ALIVE && gsm_sim800_engineering_is_enabled == 0) {
// send a command to module
srl_send_data(srl_context, (const uint8_t*) ENGINEERING_ENABLE, SRL_MODE_ZERO, strlen(ENGINEERING_ENABLE), SRL_INTERNAL);
// set what has been just send
gsm_at_command_sent_last = ENGINEERING_ENABLE;
// switch the internal state
*state = SIM800_ALIVE_SENDING_TO_MODEM;
}
}
void gsm_sim800_engineering_disable(srl_context_t * srl_context, gsm_sim800_state_t * state) {
if (*state == SIM800_ALIVE && gsm_sim800_engineering_is_enabled == 1) {
// send a command to module
srl_send_data(srl_context, (const uint8_t*) ENGINEERING_DISABLE, SRL_MODE_ZERO, strlen(ENGINEERING_DISABLE), SRL_INTERNAL);
// set what has been just send
gsm_at_command_sent_last = ENGINEERING_DISABLE;
// switch the internal state
*state = SIM800_ALIVE_SENDING_TO_MODEM;
// clear the flag
gsm_sim800_engineering_successed = 0;
}
}
void gsm_sim800_engineering_request_data(srl_context_t * srl_context, gsm_sim800_state_t * state) {
if (*state == SIM800_ALIVE && gsm_sim800_engineering_is_enabled == 1 && gsm_sim800_engineering_successed == 0) {
// clear the flag
gsm_sim800_engineering_successed = 0;
// send a command to module
srl_send_data(srl_context, (const uint8_t*) ENGINEERING_GET, SRL_MODE_ZERO, strlen(ENGINEERING_GET), SRL_INTERNAL);
// set what has been just send
gsm_at_command_sent_last = ENGINEERING_GET;
// switch the internal state
*state = SIM800_ALIVE_SENDING_TO_MODEM;
}
}
void gsm_sim800_engineering_response_callback(srl_context_t * srl_context, gsm_sim800_state_t * state, uint16_t gsm_response_start_idx) {
if (gsm_at_command_sent_last == ENGINEERING_ENABLE) {
int comparision_result = strcmp(OK, (const char *)(srl_context->srl_rx_buf_pointer + gsm_response_start_idx));
if (comparision_result == 0) {
gsm_sim800_engineering_is_enabled = 1;
}
else {
//gsm_sim800_engineering_is_enabled = 0;
gsm_sim800_engineering_fail = 1;
}
}
else if (gsm_at_command_sent_last == ENGINEERING_GET) {
// look for the start of '+CENG: 0,' record
uint16_t ceng_start = gsm_sim800_rewind_to_ceng_0(srl_context->srl_rx_buf_pointer, srl_context->srl_rx_buf_ln, gsm_response_start_idx);
if (ceng_start != 0xFFFF) {
// if it has been found
gsm_sim800_engineering_parse_ceng_0(srl_context->srl_rx_buf_pointer, ceng_start);
gsm_sim800_engineering_successed = 1;
}
else {
gsm_sim800_engineering_successed = 0;
gsm_sim800_engineering_fail = 1;
}
}
else if (gsm_at_command_sent_last == ENGINEERING_DISABLE) {
gsm_sim800_engineering_is_enabled = 0;
}
}