/***************************************************************************//** * @brief * Output the #AT_results of an AT command. * * @param[in] result * The AT_results_t result to output. ******************************************************************************/ void AT_PrintResult(int8_t result) { if (result != AT_NOTHING) { AT_last = AT_buffer; AT_buffer[0] = '\0'; } if (AT_quietResult == true) { return; } switch (result) { case AT_NOTHING: break; case AT_OK: if (AT_verbose) { AT_printf("OK\r\n"); } else { AT_printf("0\r"); } break; case AT_ERROR: if (AT_verbose) { AT_printf("ERROR\r\n"); } else { AT_printf("4\r"); } break; default: break; } }
/***************************************************************************//** * @brief * Parser AT extension function for user. * * @param[in] token * The token to parse. * * @return * The parse result. ******************************************************************************/ static int8_t user_parse(uint8_t token) { int8_t result = AT_OK; int value; switch (token) { case AT_USER_LED: if (AT_argc == 1) { value = AT_atoll(AT_argv[0]); if (value == 1) { // Turn on the LED GPIO_PinOutSet(LED_PORT, LED_BIT); } else if (value == 0) { // Turn off the LED GPIO_PinOutClear(LED_PORT, LED_BIT); } else { result = AT_ERROR; } } else { result = AT_ERROR; } break; case AT_USER_TEMPERATURE: if (AT_argc == 0) { value = TD_MEASURE_TemperatureExtended(); AT_printf("%d.%d\r\n", value / 10, value % 10); } else { result = AT_ERROR; } break; case AT_USER_VOLTAGE: if (AT_argc == 0) { value = TD_MEASURE_VoltageExtended(); AT_printf("%d.%03d\r\n", value / 1000, value % 1000); } else { result = AT_ERROR; } break; default: result = AT_NOTHING; break; } return result; }
/***************************************************************************//** * @brief * Help AT extension function for user. ******************************************************************************/ static void user_help(void) { AT_printf( "$L => Turn on/off the LED\r\n" "$T => Read the temperature\r\n" "$V => Read the voltage\r\n"); };
/***************************************************************************//** * @brief * Help AT extension function for TD Sensor Send. ******************************************************************************/ static void sensor_send_help(void) { AT_printf( "AT$DP= => Data phone\r\n" "AT$EB => Boot event\r\n" "AT$EC= => Connection event\r\n" "AT$ER= => RSSI event\r\n" "AT$ES= => Switch event\r\n" "AT$ET= => Temperature event\r\n" "AT$EV= => Battery event\r\n" "AT$KA => Keep-Alive\r\n" "AT$RAW= => Raw frame\r\n" "AT$REG => Register frame\r\n" "AT$SSMS= => Service SMS\r\n" "AT$STWT= => Service Tweet\r\n" ); }
/***************************************************************************//** * @brief * AT command parser. * * @details * This function is the main AT parser function to call when a new input * character is received from the main idle loop. * * It will perform lexical analysis, argument collection and call the piece of * code in charge of handling the corresponding AT command. * * @param[in] c * The new character to parse. ******************************************************************************/ void AT_Parse(char c) { uint32_t x, y; int extension, i; char td_serial[13]; #if defined(__ICCARM__) extern unsigned char CSTACK$$Base; extern unsigned char CSTACK$$Limit; unsigned char *memptr; #elif defined(__GNUC__) extern unsigned char __end; extern unsigned char __cs3_region_end_ram; unsigned char *memptr; #endif uint8_t token = AT_PARSE; int8_t result = AT_OK, extension_result = AT_PARSE; uint8_t echo, verbosity, quiet_result, extended_result, banner; TD_DEVICE device = {0, 0, 0, 0, 0}; TD_DEVICE_EXT device_ext = { 1, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }; for (extension = 0; extension < AT_EXTENSION_NUMBER; extension++) { if (AT_extension[extension] == 0) { break; } if (AT_extension[extension]->tokenize != 0) { token = AT_extension[extension]->tokenize(c); if (token == AT_ESCAPE) { return; } if (token > AT_BASE_LAST) { break; } } } if (AT_echo) { switch (AT_state) { case AT_A: if (c == 'A' || c == 'a') { tfp_printf("%c", c); } break; case AT_AT: if (c == 'T' || c == 't' || c == '/') { tfp_printf("%c", c); } else { tfp_printf("\b \b"); } break; default: if (c == '\b' || c == 0x7f) { if (AT_last > &AT_buffer[2]) { tfp_printf("\b \b"); } } else if (c == '\r' || c == '\n') { tfp_printf("\r"); } else { tfp_printf("%c", c); } break; } } if (token == AT_PARSE) { token = AT_Tokenize(c, &extension); } if (token > AT_BASE_LAST && extension < AT_EXTENSION_NUMBER && AT_extension[extension]->parse != 0) { extension_result = AT_extension[extension]->parse(token); if (extension_result != AT_NOTHING) { AT_PrintResult(extension_result); } return; } switch (token) { case AT_PARSE: result = AT_NOTHING; break; case AT_UNKNOWN: result = AT_ERROR; break; case AT: break; case AT_DISPLAY_CONFIG: for (extension = 0; extension < AT_EXTENSION_NUMBER; extension++) { if (AT_extension[extension] == 0) { break; } if (AT_extension[extension]->status != 0) { AT_extension[extension]->status(false); } } AT_printf("%s\r\n", CONFIG_MANUFACTURER); tfp_printf("Hardware Version: %s\r\n", CONFIG_HARDWARE_VERSION); tfp_printf("Software Version: %s\r\n", CONFIG_SOFTWARE_VERSION); TD_FLASH_DeviceRead(&device); tfp_printf("S/N: %08X\r\n", device.Serial); if (TD_FLASH_DeviceReadExtended(&device, &device_ext) == true) { for (i = 0; i < 12; i++) { td_serial[i] = device_ext.TDSerial[i]; } td_serial[12] = '\0'; if (td_serial[0] != '?') { tfp_printf("TDID: %12s\r\n", td_serial); } } tfp_printf("ACTIVE PROFILE\r\n"); tfp_printf("E%d V%d Q%d", AT_echo, AT_verbose, AT_quietResult); tfp_printf(" X%d S200:%d", AT_extended, AT_banner ); for (extension = 0; extension < AT_EXTENSION_NUMBER; extension++) { if (AT_extension[extension] == 0) { break; } if (AT_extension[extension]->status != 0) { AT_extension[extension]->status(true); } } tfp_printf("\r\n"); break; case AT_FACTORY: AT_verbose = true; AT_extended = true; AT_echo = true; AT_quietResult = false; AT_banner = AT_FORCE_BANNER ? true : false; for (extension = 0; extension < AT_EXTENSION_NUMBER; extension++) { if (AT_extension[extension] == 0) { break; } if (AT_extension[extension]->init != 0) { AT_extension[extension]->init(); } } break; case AT_GET_BANNER: if (AT_argc == 0) { AT_printf("%d\r\n", AT_banner); } else { result = AT_ERROR; } break; case AT_HARDWARE_REV: if (AT_argc == 0) { AT_printf("%s\r\n", CONFIG_HARDWARE_VERSION); } else { result = AT_ERROR; } break; case AT_HELP: if (AT_argc == 0) { AT_printf("%s", AT_help); for (extension = 0; extension < AT_EXTENSION_NUMBER; extension++) { if (AT_extension[extension] == 0) { break; } if (AT_extension[extension]->help != 0) { AT_extension[extension]->help(); } } } else { result = AT_ERROR; } break; case AT_MANUFACTURER: if (AT_argc == 0) { AT_printf("%s\r\n", CONFIG_MANUFACTURER); } else { result = AT_ERROR; } break; case AT_PRODUCT_REV: if (AT_argc == 0) { if (TD_FLASH_DeviceRead(&device)) { AT_printf("%02X\r\n", device.ProdResult); } else { result = AT_ERROR; } } else { result = AT_ERROR; } break; case AT_QUERY_BANNER: if (AT_argc != 0) { result = AT_ERROR; } else { AT_printf("0..1\r\n"); } break; case AT_RELEASE_DATE: if (AT_argc == 0) { AT_printf("%s\r\n", CONFIG_RELEASE_DATE); } else { result = AT_ERROR; } break; case AT_RESET: if (AT_argc == 0) { AT_PrintResult(result); TD_RTC_Delay(T100MS); NVIC_SystemReset(); } else { result = AT_ERROR; } break; case AT_SERIAL_NUMBER: if (AT_argc == 0) { TD_FLASH_DeviceRead(&device); AT_printf("%04X\r\n", device.Serial); if (TD_FLASH_DeviceReadExtended(&device, &device_ext) == true) { for (i = 0; i < 12; i++) { td_serial[i] = device_ext.TDSerial[i]; } td_serial[12] = '\0'; tfp_printf("TDID: %12s\r\n", td_serial); } } else { result = AT_ERROR; } break; case AT_SET_BANNER: if (AT_argc == 1) { banner = AT_atoll(AT_argv[0]); if (banner > 1) { result = AT_ERROR; } else { AT_banner = banner; } } else { result = AT_ERROR; } break; case AT_SET_ECHO: if (AT_argc == 0) { AT_echo = false; } else if (AT_argc == 1) { echo = AT_atoll(AT_argv[0]); if (echo < 2) { AT_echo = echo ? true : false; } else { result = AT_ERROR; } } else { result = AT_ERROR; } break; case AT_SET_EXTENDED_RESULTS: if (AT_argc == 0) { AT_extended = true; } else if (AT_argc == 1) { extended_result = AT_atoll(AT_argv[0]); if (extended_result < 2) { AT_extended = extended_result ? true : false; } else { result = AT_ERROR; } } else { result = AT_ERROR; } break; case AT_SET_QUIET: if (AT_argc == 0) { AT_quietResult = true; } else if (AT_argc == 1) { quiet_result = AT_atoll(AT_argv[0]); if (quiet_result < 2) { AT_quietResult = quiet_result ? true : false; } else { result = AT_ERROR; } } else { result = AT_ERROR; } break; case AT_SET_VERBOSITY: if (AT_argc == 0) { AT_verbose = true; } else if (AT_argc == 1) { verbosity = AT_atoll(AT_argv[0]); if (verbosity < 2) { AT_verbose = verbosity ? true : false; } else { result = AT_ERROR; } } else { result = AT_ERROR; } break; case AT_SOFTWARE_REV: if (AT_argc == 0) { AT_printf("%s\r\n", CONFIG_SOFTWARE_VERSION); } else { result = AT_ERROR; } break; #if defined(__ICCARM__) case AT_FREE_STACK: memptr = &CSTACK$$Base; while (memptr < &CSTACK$$Limit) { if (*memptr++ != 0xCD) { break; } } AT_printf("Free Stack: %d bytes", memptr - &CSTACK$$Base); break; #elif defined(__GNUC__) case AT_FREE_STACK: memptr = &__end; while (memptr < &__cs3_region_end_ram) { if (*memptr++ != 0xCD) { break; } } AT_printf("Free Stack: %d bytes", memptr - &__end); break; #endif case AT_UNIQUE_ID: if (AT_argc == 0) { x = DEVINFO->UNIQUEH; y = DEVINFO->UNIQUEL; AT_printf("%08X%08X\r\n", x, y); } else { result = AT_ERROR; } break; case AT_WRITE_CONFIG: if (AT_argc == 0) { AT_SavePersistBuffer(); TD_FLASH_WriteVariables(); } else { result = AT_ERROR; } break; default: result = AT_ERROR; break; } AT_PrintResult(result); }
/***************************************************************************//** * @brief * Initialize the AT command parser. ******************************************************************************/ void AT_Init(void) { int i; uint8_t extension_read, *persist_pointer; uint16_t persist_size = 1; for (i = 0; i < AT_BUFFER_SIZE; i++) { AT_buffer[i] = '\0'; } for (i = 0; i < AT_BUFFER_SIZE; i++) { AT_previousCommand[i] = '\0'; } for (i = 0; i < AT_MAX_ARGS; i++) { AT_argv[i] = 0; } AT_argc = 0; AT_last = &AT_buffer[0]; AT_state = AT_A; AT_verbose = true; AT_extended = true; AT_echo = true; AT_quietResult = false; AT_banner = AT_FORCE_BANNER ? true : false; // Find out how many persistent bytes are required by extensions for (i = 0; i < AT_EXTENSION_NUMBER; i++) { if (AT_extension[i] == 0) { break; } if (AT_extension[i]->init != 0) { AT_extension[i]->init(); } if (AT_extension[i]->persist != 0) { persist_size += AT_extension[i]->persist(false, 0, 0); } } if (persist_size > AT_PERSIST_SIZE) { persist_size = AT_PERSIST_SIZE; } /* Read persist data. If not available, create them. After that AT_persist_buffer is correctly filled */ if (!TD_FLASH_DeclareVariable((uint8_t *) AT_persist_buffer, AT_PERSIST_SIZE, 0)) { AT_SavePersistBuffer(); } // Read persistent data persist_pointer = AT_persist_buffer; AT_echo = (*persist_pointer & 0x01) ? true : false; AT_verbose = (*persist_pointer & 0x02) ? true : false; AT_quietResult = (*persist_pointer & 0x04) ? true : false; AT_extended = (*persist_pointer & 0x08) ? true : false; AT_banner = (*persist_pointer & 0x10) ? true : false; persist_pointer++; // Pass persistent data to each extension for (i = 0; i < AT_EXTENSION_NUMBER; i++) { if (AT_extension[i] == 0) { break; } if (AT_extension[i]->persist != 0) { extension_read = AT_extension[i]->persist(false, persist_pointer, persist_size); persist_pointer += extension_read; persist_size -= extension_read; } } if (AT_verbose == true && AT_quietResult == false && AT_banner == true) { AT_printf("^SYSSTART\r\n"); } }