├── AT Parser.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── AT Parser.xccheckout │ └── xcuserdata │ │ └── leonidlezner.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── leonidlezner.xcuserdatad │ └── xcschemes │ ├── AT Parser.xcscheme │ └── xcschememanagement.plist ├── AT Parser ├── at_parser.c ├── at_parser.h ├── main.c ├── my_string.c ├── my_string.h └── types.h └── AT_Parser_Arduino ├── AT_Parser_Arduino.ino ├── at_parser.c ├── at_parser.h ├── my_string.c ├── my_string.h └── types.h /AT Parser.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 71EF61381AEAC9E000E210BD /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 71EF61371AEAC9E000E210BD /* main.c */; }; 11 | 71EF614B1AEACE8C00E210BD /* at_parser.c in Sources */ = {isa = PBXBuildFile; fileRef = 71EF61461AEACE8C00E210BD /* at_parser.c */; }; 12 | 71EF614C1AEACE8C00E210BD /* my_string.c in Sources */ = {isa = PBXBuildFile; fileRef = 71EF61481AEACE8C00E210BD /* my_string.c */; }; 13 | /* End PBXBuildFile section */ 14 | 15 | /* Begin PBXCopyFilesBuildPhase section */ 16 | 71EF61321AEAC9E000E210BD /* CopyFiles */ = { 17 | isa = PBXCopyFilesBuildPhase; 18 | buildActionMask = 2147483647; 19 | dstPath = /usr/share/man/man1/; 20 | dstSubfolderSpec = 0; 21 | files = ( 22 | ); 23 | runOnlyForDeploymentPostprocessing = 1; 24 | }; 25 | /* End PBXCopyFilesBuildPhase section */ 26 | 27 | /* Begin PBXFileReference section */ 28 | 71EF61341AEAC9E000E210BD /* AT Parser */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "AT Parser"; sourceTree = BUILT_PRODUCTS_DIR; }; 29 | 71EF61371AEAC9E000E210BD /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; 30 | 71EF61461AEACE8C00E210BD /* at_parser.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = at_parser.c; sourceTree = ""; }; 31 | 71EF61471AEACE8C00E210BD /* at_parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = at_parser.h; sourceTree = ""; }; 32 | 71EF61481AEACE8C00E210BD /* my_string.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = my_string.c; sourceTree = ""; }; 33 | 71EF61491AEACE8C00E210BD /* my_string.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = my_string.h; sourceTree = ""; }; 34 | 71EF614A1AEACE8C00E210BD /* types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = types.h; sourceTree = ""; }; 35 | /* End PBXFileReference section */ 36 | 37 | /* Begin PBXFrameworksBuildPhase section */ 38 | 71EF61311AEAC9E000E210BD /* Frameworks */ = { 39 | isa = PBXFrameworksBuildPhase; 40 | buildActionMask = 2147483647; 41 | files = ( 42 | ); 43 | runOnlyForDeploymentPostprocessing = 0; 44 | }; 45 | /* End PBXFrameworksBuildPhase section */ 46 | 47 | /* Begin PBXGroup section */ 48 | 71EF612B1AEAC9DF00E210BD = { 49 | isa = PBXGroup; 50 | children = ( 51 | 71EF61361AEAC9E000E210BD /* AT Parser */, 52 | 71EF61351AEAC9E000E210BD /* Products */, 53 | ); 54 | sourceTree = ""; 55 | }; 56 | 71EF61351AEAC9E000E210BD /* Products */ = { 57 | isa = PBXGroup; 58 | children = ( 59 | 71EF61341AEAC9E000E210BD /* AT Parser */, 60 | ); 61 | name = Products; 62 | sourceTree = ""; 63 | }; 64 | 71EF61361AEAC9E000E210BD /* AT Parser */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | 71EF614D1AEAD5C800E210BD /* lib */, 68 | 71EF61371AEAC9E000E210BD /* main.c */, 69 | ); 70 | path = "AT Parser"; 71 | sourceTree = ""; 72 | }; 73 | 71EF614D1AEAD5C800E210BD /* lib */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | 71EF614A1AEACE8C00E210BD /* types.h */, 77 | 71EF61461AEACE8C00E210BD /* at_parser.c */, 78 | 71EF61471AEACE8C00E210BD /* at_parser.h */, 79 | 71EF61481AEACE8C00E210BD /* my_string.c */, 80 | 71EF61491AEACE8C00E210BD /* my_string.h */, 81 | ); 82 | name = lib; 83 | sourceTree = ""; 84 | }; 85 | /* End PBXGroup section */ 86 | 87 | /* Begin PBXNativeTarget section */ 88 | 71EF61331AEAC9E000E210BD /* AT Parser */ = { 89 | isa = PBXNativeTarget; 90 | buildConfigurationList = 71EF613B1AEAC9E000E210BD /* Build configuration list for PBXNativeTarget "AT Parser" */; 91 | buildPhases = ( 92 | 71EF61301AEAC9E000E210BD /* Sources */, 93 | 71EF61311AEAC9E000E210BD /* Frameworks */, 94 | 71EF61321AEAC9E000E210BD /* CopyFiles */, 95 | ); 96 | buildRules = ( 97 | ); 98 | dependencies = ( 99 | ); 100 | name = "AT Parser"; 101 | productName = "AT Parser"; 102 | productReference = 71EF61341AEAC9E000E210BD /* AT Parser */; 103 | productType = "com.apple.product-type.tool"; 104 | }; 105 | /* End PBXNativeTarget section */ 106 | 107 | /* Begin PBXProject section */ 108 | 71EF612C1AEAC9DF00E210BD /* Project object */ = { 109 | isa = PBXProject; 110 | attributes = { 111 | LastUpgradeCheck = 0630; 112 | ORGANIZATIONNAME = "Leonid Lezner"; 113 | TargetAttributes = { 114 | 71EF61331AEAC9E000E210BD = { 115 | CreatedOnToolsVersion = 6.3.1; 116 | }; 117 | }; 118 | }; 119 | buildConfigurationList = 71EF612F1AEAC9DF00E210BD /* Build configuration list for PBXProject "AT Parser" */; 120 | compatibilityVersion = "Xcode 3.2"; 121 | developmentRegion = English; 122 | hasScannedForEncodings = 0; 123 | knownRegions = ( 124 | en, 125 | ); 126 | mainGroup = 71EF612B1AEAC9DF00E210BD; 127 | productRefGroup = 71EF61351AEAC9E000E210BD /* Products */; 128 | projectDirPath = ""; 129 | projectRoot = ""; 130 | targets = ( 131 | 71EF61331AEAC9E000E210BD /* AT Parser */, 132 | ); 133 | }; 134 | /* End PBXProject section */ 135 | 136 | /* Begin PBXSourcesBuildPhase section */ 137 | 71EF61301AEAC9E000E210BD /* Sources */ = { 138 | isa = PBXSourcesBuildPhase; 139 | buildActionMask = 2147483647; 140 | files = ( 141 | 71EF61381AEAC9E000E210BD /* main.c in Sources */, 142 | 71EF614B1AEACE8C00E210BD /* at_parser.c in Sources */, 143 | 71EF614C1AEACE8C00E210BD /* my_string.c in Sources */, 144 | ); 145 | runOnlyForDeploymentPostprocessing = 0; 146 | }; 147 | /* End PBXSourcesBuildPhase section */ 148 | 149 | /* Begin XCBuildConfiguration section */ 150 | 71EF61391AEAC9E000E210BD /* Debug */ = { 151 | isa = XCBuildConfiguration; 152 | buildSettings = { 153 | ALWAYS_SEARCH_USER_PATHS = NO; 154 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 155 | CLANG_CXX_LIBRARY = "libc++"; 156 | CLANG_ENABLE_MODULES = YES; 157 | CLANG_ENABLE_OBJC_ARC = YES; 158 | CLANG_WARN_BOOL_CONVERSION = YES; 159 | CLANG_WARN_CONSTANT_CONVERSION = YES; 160 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 161 | CLANG_WARN_EMPTY_BODY = YES; 162 | CLANG_WARN_ENUM_CONVERSION = YES; 163 | CLANG_WARN_INT_CONVERSION = YES; 164 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 165 | CLANG_WARN_UNREACHABLE_CODE = YES; 166 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 167 | COPY_PHASE_STRIP = NO; 168 | DEBUG_INFORMATION_FORMAT = dwarf; 169 | ENABLE_STRICT_OBJC_MSGSEND = YES; 170 | GCC_C_LANGUAGE_STANDARD = gnu99; 171 | GCC_DYNAMIC_NO_PIC = NO; 172 | GCC_NO_COMMON_BLOCKS = YES; 173 | GCC_OPTIMIZATION_LEVEL = 0; 174 | GCC_PREPROCESSOR_DEFINITIONS = ( 175 | "DEBUG=1", 176 | "$(inherited)", 177 | ); 178 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 179 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 180 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 181 | GCC_WARN_UNDECLARED_SELECTOR = YES; 182 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 183 | GCC_WARN_UNUSED_FUNCTION = YES; 184 | GCC_WARN_UNUSED_VARIABLE = YES; 185 | MACOSX_DEPLOYMENT_TARGET = 10.10; 186 | MTL_ENABLE_DEBUG_INFO = YES; 187 | ONLY_ACTIVE_ARCH = YES; 188 | SDKROOT = macosx; 189 | VALID_ARCHS = "i386 x86_64"; 190 | }; 191 | name = Debug; 192 | }; 193 | 71EF613A1AEAC9E000E210BD /* Release */ = { 194 | isa = XCBuildConfiguration; 195 | buildSettings = { 196 | ALWAYS_SEARCH_USER_PATHS = NO; 197 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 198 | CLANG_CXX_LIBRARY = "libc++"; 199 | CLANG_ENABLE_MODULES = YES; 200 | CLANG_ENABLE_OBJC_ARC = YES; 201 | CLANG_WARN_BOOL_CONVERSION = YES; 202 | CLANG_WARN_CONSTANT_CONVERSION = YES; 203 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 204 | CLANG_WARN_EMPTY_BODY = YES; 205 | CLANG_WARN_ENUM_CONVERSION = YES; 206 | CLANG_WARN_INT_CONVERSION = YES; 207 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 208 | CLANG_WARN_UNREACHABLE_CODE = YES; 209 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 210 | COPY_PHASE_STRIP = NO; 211 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 212 | ENABLE_NS_ASSERTIONS = NO; 213 | ENABLE_STRICT_OBJC_MSGSEND = YES; 214 | GCC_C_LANGUAGE_STANDARD = gnu99; 215 | GCC_NO_COMMON_BLOCKS = YES; 216 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 217 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 218 | GCC_WARN_UNDECLARED_SELECTOR = YES; 219 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 220 | GCC_WARN_UNUSED_FUNCTION = YES; 221 | GCC_WARN_UNUSED_VARIABLE = YES; 222 | MACOSX_DEPLOYMENT_TARGET = 10.10; 223 | MTL_ENABLE_DEBUG_INFO = NO; 224 | SDKROOT = macosx; 225 | VALID_ARCHS = "i386 x86_64"; 226 | }; 227 | name = Release; 228 | }; 229 | 71EF613C1AEAC9E000E210BD /* Debug */ = { 230 | isa = XCBuildConfiguration; 231 | buildSettings = { 232 | PRODUCT_NAME = "$(TARGET_NAME)"; 233 | }; 234 | name = Debug; 235 | }; 236 | 71EF613D1AEAC9E000E210BD /* Release */ = { 237 | isa = XCBuildConfiguration; 238 | buildSettings = { 239 | PRODUCT_NAME = "$(TARGET_NAME)"; 240 | }; 241 | name = Release; 242 | }; 243 | /* End XCBuildConfiguration section */ 244 | 245 | /* Begin XCConfigurationList section */ 246 | 71EF612F1AEAC9DF00E210BD /* Build configuration list for PBXProject "AT Parser" */ = { 247 | isa = XCConfigurationList; 248 | buildConfigurations = ( 249 | 71EF61391AEAC9E000E210BD /* Debug */, 250 | 71EF613A1AEAC9E000E210BD /* Release */, 251 | ); 252 | defaultConfigurationIsVisible = 0; 253 | defaultConfigurationName = Release; 254 | }; 255 | 71EF613B1AEAC9E000E210BD /* Build configuration list for PBXNativeTarget "AT Parser" */ = { 256 | isa = XCConfigurationList; 257 | buildConfigurations = ( 258 | 71EF613C1AEAC9E000E210BD /* Debug */, 259 | 71EF613D1AEAC9E000E210BD /* Release */, 260 | ); 261 | defaultConfigurationIsVisible = 0; 262 | }; 263 | /* End XCConfigurationList section */ 264 | }; 265 | rootObject = 71EF612C1AEAC9DF00E210BD /* Project object */; 266 | } 267 | -------------------------------------------------------------------------------- /AT Parser.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AT Parser.xcodeproj/project.xcworkspace/xcshareddata/AT Parser.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | AA2C237C-C381-4602-B5C2-510F644F164A 9 | IDESourceControlProjectName 10 | AT Parser 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 20A9424A411EFEA001F7CE2FC25E7450FAC446CF 14 | https://github.com/bitmarker/AT-Command-Parser.git 15 | 16 | IDESourceControlProjectPath 17 | AT Parser.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 20A9424A411EFEA001F7CE2FC25E7450FAC446CF 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/bitmarker/AT-Command-Parser.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 20A9424A411EFEA001F7CE2FC25E7450FAC446CF 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 20A9424A411EFEA001F7CE2FC25E7450FAC446CF 36 | IDESourceControlWCCName 37 | AT%20Parser 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /AT Parser.xcodeproj/project.xcworkspace/xcuserdata/leonidlezner.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitmarker/AT-Command-Parser/e9993d1bd9a9cb5130fcb0387f42803641253391/AT Parser.xcodeproj/project.xcworkspace/xcuserdata/leonidlezner.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /AT Parser.xcodeproj/xcuserdata/leonidlezner.xcuserdatad/xcschemes/AT Parser.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /AT Parser.xcodeproj/xcuserdata/leonidlezner.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | AT Parser.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 71EF61331AEAC9E000E210BD 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /AT Parser/at_parser.c: -------------------------------------------------------------------------------- 1 | #include "at_parser.h" 2 | 3 | typedef struct _at_command 4 | { 5 | unsigned long hash; 6 | at_callback setter; 7 | at_callback getter; 8 | at_callback test; 9 | at_callback execute; 10 | } AT_COMMAND; 11 | 12 | #ifndef AT_COMMANDS_NUM 13 | #define AT_COMMANDS_NUM 10 14 | #endif 15 | 16 | AT_COMMAND at_registered_commands[AT_COMMANDS_NUM]; 17 | 18 | unsigned long at_hash(string_t str) 19 | { 20 | unsigned long hash = 5381; 21 | int c; 22 | 23 | while((c = *str++)) 24 | hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ 25 | 26 | return hash; 27 | } 28 | 29 | void at_register_command(string_t command, at_callback getter, at_callback setter, at_callback test, at_callback execute) 30 | { 31 | int i; 32 | AT_COMMAND new_cmd; 33 | new_cmd.hash = at_hash(command); 34 | new_cmd.getter = getter; 35 | new_cmd.setter = setter; 36 | new_cmd.execute = execute; 37 | new_cmd.test = test; 38 | 39 | for(i = 0; i < AT_COMMANDS_NUM; i++) 40 | { 41 | if(at_registered_commands[i].hash == 0) 42 | { 43 | at_registered_commands[i] = new_cmd; 44 | return; 45 | } 46 | } 47 | } 48 | 49 | char at_execute_command(string_t command, unsigned char *value, unsigned char type) 50 | { 51 | int i; 52 | 53 | char result = AT_ERROR; 54 | 55 | unsigned long hash = at_hash(command); 56 | 57 | for(i = 0; i < AT_COMMANDS_NUM; i++) 58 | { 59 | if(at_registered_commands[i].hash == hash) 60 | { 61 | switch(type) 62 | { 63 | case AT_PARSER_STATE_WRITE: 64 | if(at_registered_commands[i].setter == 0) 65 | { 66 | return AT_ERROR; 67 | } 68 | result = at_registered_commands[i].setter(value); 69 | break; 70 | case AT_PARSER_STATE_READ: 71 | if(at_registered_commands[i].getter == 0) 72 | { 73 | return AT_ERROR; 74 | } 75 | result = at_registered_commands[i].getter(value); 76 | break; 77 | case AT_PARSER_STATE_TEST: 78 | if(at_registered_commands[i].test == 0) 79 | { 80 | return AT_ERROR; 81 | } 82 | result = at_registered_commands[i].test(value); 83 | break; 84 | case AT_PARSER_STATE_COMMAND: 85 | if(at_registered_commands[i].execute == 0) 86 | { 87 | return AT_ERROR; 88 | } 89 | result = at_registered_commands[i].execute(value); 90 | break; 91 | default: 92 | result = AT_ERROR; 93 | } 94 | } 95 | } 96 | 97 | return result; 98 | } 99 | 100 | /* 101 | 102 | AT+COMMAND=? -> List 103 | AT+COMMAND=VALUE -> Write 104 | AT+COMMAND? -> Read 105 | AT+COMMAND -> Execute 106 | 107 | */ 108 | 109 | char at_parse_line(string_t line, unsigned char *ret) 110 | { 111 | uint16_t i; 112 | 113 | char result = AT_ERROR; 114 | 115 | char state = AT_PARSER_STATE_COMMAND; 116 | 117 | int16_t start = ms_str_find(line, (string_t)AT_COMMAND_MARKER); 118 | 119 | uint16_t line_len = ms_strlen(line); 120 | 121 | int16_t index_write_start = -1; 122 | 123 | int16_t index_command_end = line_len - 1; 124 | 125 | unsigned char temp[AT_MAX_TEMP_STRING]; 126 | 127 | if(start >= 0) 128 | { 129 | // Skip the marker 130 | start += ms_strlen((string_t)AT_COMMAND_MARKER); 131 | 132 | for(i = start; i < line_len; i++) 133 | { 134 | // Execute 'read' command 135 | if(line[i] == '?' && state == AT_PARSER_STATE_COMMAND) 136 | { 137 | index_command_end = i - 1; 138 | state = AT_PARSER_STATE_READ; 139 | } 140 | else if(line[i] == '=' && state == AT_PARSER_STATE_COMMAND) 141 | { 142 | index_command_end = i - 1; 143 | 144 | if(i < (line_len - 1)) 145 | { 146 | if(line[i + 1] == '?') 147 | { 148 | state = AT_PARSER_STATE_TEST; 149 | } 150 | else 151 | { 152 | index_write_start = i + 1; 153 | state = AT_PARSER_STATE_WRITE; 154 | } 155 | } 156 | else 157 | { 158 | return AT_ERROR; 159 | } 160 | } 161 | } 162 | 163 | ret[0] = 0; 164 | 165 | switch(state) 166 | { 167 | case AT_PARSER_STATE_COMMAND: 168 | case AT_PARSER_STATE_READ: 169 | case AT_PARSER_STATE_TEST: 170 | ms_array_slice_to_string(line, start, index_command_end, temp); 171 | result = at_execute_command(temp, ret, state); 172 | break; 173 | 174 | case AT_PARSER_STATE_WRITE: 175 | ms_array_slice_to_string(line, start, index_command_end, temp); 176 | if(index_write_start <= (line_len - 1)) 177 | { 178 | ms_array_slice_to_string(line, index_write_start, line_len - 1, ret); 179 | result = at_execute_command(temp, ret, state); 180 | ret[0] = 0; 181 | } 182 | else 183 | { 184 | result = at_execute_command(temp, ret, state); 185 | ret[0] = 0; 186 | } 187 | break; 188 | 189 | default: 190 | return AT_ERROR; 191 | } 192 | } 193 | 194 | 195 | return result; 196 | } -------------------------------------------------------------------------------- /AT Parser/at_parser.h: -------------------------------------------------------------------------------- 1 | #ifndef AT_PARSER_H 2 | #define AT_PARSER_H 3 | 4 | #include "my_string.h" 5 | 6 | #define AT_MAX_TEMP_STRING 50 7 | 8 | typedef char (*at_callback)(unsigned char *value); 9 | 10 | #define AT_OK 0 11 | #define AT_ERROR 1 12 | 13 | #define AT_PARSER_STATE_COMMAND 0 14 | #define AT_PARSER_STATE_TEST 1 15 | #define AT_PARSER_STATE_READ 2 16 | #define AT_PARSER_STATE_WRITE 3 17 | #define AT_PARSER_STATE_EQUAL 4 18 | 19 | #ifndef AT_COMMAND_MARKER 20 | #define AT_COMMAND_MARKER "AT+" 21 | #endif 22 | 23 | unsigned long at_hash(string_t str); 24 | void at_register_command(string_t command, at_callback getter, at_callback setter, at_callback test, at_callback execute); 25 | char at_parse_line(string_t line, unsigned char *ret); 26 | 27 | 28 | 29 | #endif -------------------------------------------------------------------------------- /AT Parser/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "at_parser.h" 3 | 4 | char set_flash_port(char * value) 5 | { 6 | printf("set_flash_port: %s\n", value); 7 | return AT_OK; 8 | } 9 | 10 | char get_flash_port(char * value) 11 | { 12 | //printf("get_flash_port: %s\n", value); 13 | strcpy(value, "7"); 14 | return AT_OK; 15 | } 16 | 17 | char set_trigger_port(char * value) 18 | { 19 | printf("set_trigger_port: %s\n", value); 20 | return AT_OK; 21 | } 22 | 23 | char get_trigger_port(char * value) 24 | { 25 | strcpy(value, "Wowowow"); 26 | 27 | printf("get_trigger_port: %s\n", value); 28 | return AT_OK; 29 | } 30 | 31 | char exec_trigger(char * value) 32 | { 33 | strcpy(value, "Blink!"); 34 | 35 | printf("exec_trigger: %s\n", value); 36 | return AT_OK; 37 | } 38 | 39 | int main(int argc, char **argv) 40 | { 41 | unsigned char temp[50]; 42 | 43 | at_register_command("FLPT", (at_callback)get_flash_port, (at_callback)set_flash_port, 0, 0); 44 | at_register_command("TRPT", (at_callback)get_trigger_port, (at_callback)set_trigger_port, 0, 0); 45 | at_register_command("TRIG", 0, 0, 0, (at_callback)exec_trigger); 46 | 47 | 48 | char ret = at_parse_line("AT+TRPT=5", temp); 49 | 50 | if(ret == AT_OK) 51 | { 52 | if(ms_strlen(temp) > 0) 53 | { 54 | puts(temp); 55 | } 56 | printf("OK"); 57 | } 58 | else 59 | { 60 | printf("ERROR"); 61 | } 62 | 63 | 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /AT Parser/my_string.c: -------------------------------------------------------------------------------- 1 | #include "my_string.h" 2 | 3 | #include 4 | 5 | uint16_t ms_strlen(string_t string) 6 | { 7 | uint16_t i; 8 | for(i = 0; *string; i++, string++); 9 | return i; 10 | } 11 | 12 | void ms_shift_array(char *array, uint16_t len) 13 | { 14 | int i; 15 | for(i = 0; i < len - 1; i++) 16 | { 17 | array[i] = array[i + 1]; 18 | } 19 | } 20 | 21 | char ms_str_equal(string_t string1, uint16_t len1, string_t string2, uint16_t len2) 22 | { 23 | int i; 24 | 25 | for(i = 0; i < len2; i++) 26 | { 27 | if(string1[len1 - len2 + i] != string2[i]) 28 | { 29 | return 0; 30 | } 31 | } 32 | 33 | return 1; 34 | } 35 | 36 | int16_t ms_str_find(string_t haystack, string_t needle) 37 | { 38 | int i; 39 | uint16_t needle_len = ms_strlen(needle); 40 | uint16_t haystack_len = ms_strlen(haystack); 41 | 42 | if(needle_len > haystack_len) 43 | { 44 | return -1; 45 | } 46 | 47 | for(i = 0; i < haystack_len - needle_len; i++) 48 | { 49 | if(ms_str_equal(haystack, needle_len, needle, needle_len)) 50 | { 51 | return i; 52 | } 53 | 54 | haystack++; 55 | } 56 | 57 | return -1; 58 | } 59 | 60 | void ms_dump_array(char *array, uint16_t max_buffer, uint16_t reverse_pointer) 61 | { 62 | int i; 63 | for(i = 0; i < max_buffer - reverse_pointer; i++) 64 | { 65 | printf("[%c]", array[reverse_pointer + i]); 66 | } 67 | } 68 | 69 | uint16_t ms_power(uint16_t base, uint16_t exponent) 70 | { 71 | uint16_t ret = 1; 72 | int i; 73 | for(i = 0; i < exponent; i++) 74 | { 75 | ret *= base; 76 | } 77 | return ret; 78 | } 79 | 80 | uint16_t ms_array_to_number(char * array, uint16_t max_buffer, uint16_t reverse_pointer) 81 | { 82 | int i; 83 | 84 | uint16_t ret = 0; 85 | 86 | for(i = 0; i < max_buffer - reverse_pointer; i++) 87 | { 88 | ret += (array[reverse_pointer + i] - '0') * ms_power(10, max_buffer - reverse_pointer - i - 1); 89 | } 90 | 91 | return ret; 92 | } 93 | 94 | void ms_array_slice_to_string(string_t array, uint16_t start, uint16_t end, unsigned char *ret) 95 | { 96 | uint16_t i, n = 0; 97 | 98 | for(i = start; i <= end; i++) 99 | { 100 | ret[n] = array[i]; 101 | n++; 102 | } 103 | 104 | ret[n] = 0; 105 | } -------------------------------------------------------------------------------- /AT Parser/my_string.h: -------------------------------------------------------------------------------- 1 | #ifndef __MY_STRING__ 2 | #define __MY_STRING__ 3 | 4 | #include "types.h" 5 | 6 | int16_t ms_str_find(string_t haystack, string_t needle); 7 | void ms_array_slice_to_string(string_t array, uint16_t start, uint16_t end, unsigned char *ret); 8 | uint16_t ms_strlen(string_t string); 9 | 10 | #endif -------------------------------------------------------------------------------- /AT Parser/types.h: -------------------------------------------------------------------------------- 1 | #ifndef _TYPES_H__ 2 | #define _TYPES_H__ 3 | 4 | #ifndef NULL 5 | #define NULL 0 6 | #endif 7 | 8 | typedef unsigned short uint16_t; 9 | typedef signed short int16_t; 10 | 11 | typedef const unsigned char * string_t; 12 | 13 | #endif -------------------------------------------------------------------------------- /AT_Parser_Arduino/AT_Parser_Arduino.ino: -------------------------------------------------------------------------------- 1 | #include "at_parser.h" 2 | 3 | #define DEVICE_DESCRIPTION "MyDevice v0.0.1" 4 | 5 | int frequency = 0; 6 | 7 | int count = 0; 8 | 9 | char get_port(char *value) 10 | { 11 | 12 | return AT_OK; 13 | } 14 | 15 | char get_frequency(char *value) 16 | { 17 | sprintf(value, "%d", frequency); 18 | return AT_OK; 19 | } 20 | 21 | char set_frequency(char *value) 22 | { 23 | sscanf(value, "%d", &frequency); 24 | return AT_OK; 25 | } 26 | 27 | char test_frequency(char *value) 28 | { 29 | Serial.println("FREQ can be between 0 and 1000"); 30 | return AT_OK; 31 | } 32 | 33 | 34 | 35 | void setup() 36 | { 37 | Serial.begin(9600); 38 | 39 | pinMode(13, OUTPUT); 40 | 41 | at_register_command((string_t)"PORT", (at_callback)get_port, 0, 0, 0); 42 | at_register_command((string_t)"FREQ", (at_callback)get_frequency, (at_callback)set_frequency, (at_callback)test_frequency, 0); 43 | } 44 | 45 | void process_at_commands() 46 | { 47 | static String readString = ""; 48 | char ret[50]; 49 | char res; 50 | 51 | while (Serial.available()) 52 | { 53 | if (Serial.available() > 0) 54 | { 55 | // Get a byte from buffer 56 | char c = Serial.read(); 57 | 58 | readString += c; 59 | 60 | // Input is too long 61 | if (readString.length() > AT_MAX_TEMP_STRING) 62 | { 63 | Serial.println(AT_ERROR_STRING); 64 | readString = ""; 65 | } 66 | else 67 | { 68 | if (c == '\r' || c == ';') 69 | { 70 | readString.trim(); 71 | 72 | // Simple echo 73 | if (readString == "AT") 74 | { 75 | Serial.println(DEVICE_DESCRIPTION); 76 | Serial.println(AT_OK_STRING); 77 | readString = ""; 78 | } 79 | else 80 | { 81 | // Parsing the command 82 | res = at_parse_line((string_t)readString.c_str(), (unsigned char*)ret); 83 | 84 | readString = ""; 85 | 86 | if (res == AT_OK) 87 | { 88 | if (ms_strlen((string_t)ret) > 0) 89 | { 90 | String s_ret(ret); 91 | Serial.println(s_ret); 92 | } 93 | Serial.println(AT_OK_STRING); 94 | } 95 | else 96 | { 97 | Serial.println(AT_ERROR_STRING); 98 | } 99 | } 100 | } 101 | } 102 | } // end serial available 103 | } // end while 104 | } 105 | 106 | void loop() 107 | { 108 | process_at_commands(); 109 | 110 | 111 | count++; 112 | 113 | if (count > 0) 114 | { 115 | digitalWrite(13, 0); 116 | } 117 | 118 | if (count > frequency / 2) 119 | { 120 | digitalWrite(13, 1); 121 | } 122 | 123 | if (count > frequency) 124 | { 125 | count = 0; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /AT_Parser_Arduino/at_parser.c: -------------------------------------------------------------------------------- 1 | #include "at_parser.h" 2 | 3 | typedef struct _at_command 4 | { 5 | unsigned long hash; 6 | at_callback setter; 7 | at_callback getter; 8 | at_callback test; 9 | at_callback execute; 10 | } AT_COMMAND; 11 | 12 | #ifndef AT_COMMANDS_NUM 13 | #define AT_COMMANDS_NUM 10 14 | #endif 15 | 16 | AT_COMMAND at_registered_commands[AT_COMMANDS_NUM]; 17 | 18 | unsigned long at_hash(string_t str) 19 | { 20 | unsigned long hash = 5381; 21 | int c; 22 | 23 | while((c = *str++)) 24 | hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ 25 | 26 | return hash; 27 | } 28 | 29 | void at_register_command(string_t command, at_callback getter, at_callback setter, at_callback test, at_callback execute) 30 | { 31 | int i; 32 | AT_COMMAND new_cmd; 33 | new_cmd.hash = at_hash(command); 34 | new_cmd.getter = getter; 35 | new_cmd.setter = setter; 36 | new_cmd.execute = execute; 37 | new_cmd.test = test; 38 | 39 | for(i = 0; i < AT_COMMANDS_NUM; i++) 40 | { 41 | if(at_registered_commands[i].hash == 0) 42 | { 43 | at_registered_commands[i] = new_cmd; 44 | return; 45 | } 46 | } 47 | } 48 | 49 | char at_execute_command(string_t command, unsigned char *value, unsigned char type) 50 | { 51 | int i; 52 | 53 | char result = AT_ERROR; 54 | 55 | unsigned long hash = at_hash(command); 56 | 57 | for(i = 0; i < AT_COMMANDS_NUM; i++) 58 | { 59 | if(at_registered_commands[i].hash == hash) 60 | { 61 | switch(type) 62 | { 63 | case AT_PARSER_STATE_WRITE: 64 | if(at_registered_commands[i].setter == 0) 65 | { 66 | return AT_ERROR; 67 | } 68 | result = at_registered_commands[i].setter(value); 69 | break; 70 | case AT_PARSER_STATE_READ: 71 | if(at_registered_commands[i].getter == 0) 72 | { 73 | return AT_ERROR; 74 | } 75 | result = at_registered_commands[i].getter(value); 76 | break; 77 | case AT_PARSER_STATE_TEST: 78 | if(at_registered_commands[i].test == 0) 79 | { 80 | return AT_ERROR; 81 | } 82 | result = at_registered_commands[i].test(value); 83 | break; 84 | case AT_PARSER_STATE_COMMAND: 85 | if(at_registered_commands[i].execute == 0) 86 | { 87 | return AT_ERROR; 88 | } 89 | result = at_registered_commands[i].execute(value); 90 | break; 91 | default: 92 | result = AT_ERROR; 93 | } 94 | } 95 | } 96 | 97 | return result; 98 | } 99 | 100 | /* 101 | 102 | AT+COMMAND=? -> List 103 | AT+COMMAND=VALUE -> Write 104 | AT+COMMAND? -> Read 105 | AT+COMMAND -> Execute 106 | 107 | */ 108 | 109 | char at_parse_line(string_t line, unsigned char *ret) 110 | { 111 | uint16_t i; 112 | 113 | char result = AT_ERROR; 114 | 115 | char state = AT_PARSER_STATE_COMMAND; 116 | 117 | int16_t start = ms_str_find(line, (string_t)AT_COMMAND_MARKER); 118 | 119 | uint16_t line_len = ms_strlen(line); 120 | 121 | int16_t index_write_start = -1; 122 | 123 | int16_t index_command_end = line_len - 1; 124 | 125 | unsigned char temp[AT_MAX_TEMP_STRING]; 126 | 127 | if(start >= 0) 128 | { 129 | // Skip the marker 130 | start += ms_strlen((string_t)AT_COMMAND_MARKER); 131 | 132 | for(i = start; i < line_len; i++) 133 | { 134 | // Execute 'read' command 135 | if(line[i] == '?' && state == AT_PARSER_STATE_COMMAND) 136 | { 137 | index_command_end = i - 1; 138 | state = AT_PARSER_STATE_READ; 139 | } 140 | else if(line[i] == '=' && state == AT_PARSER_STATE_COMMAND) 141 | { 142 | index_command_end = i - 1; 143 | 144 | if(i < (line_len - 1)) 145 | { 146 | if(line[i + 1] == '?') 147 | { 148 | state = AT_PARSER_STATE_TEST; 149 | } 150 | else 151 | { 152 | index_write_start = i + 1; 153 | state = AT_PARSER_STATE_WRITE; 154 | } 155 | } 156 | else 157 | { 158 | return AT_ERROR; 159 | } 160 | } 161 | } 162 | 163 | ret[0] = 0; 164 | 165 | switch(state) 166 | { 167 | case AT_PARSER_STATE_COMMAND: 168 | case AT_PARSER_STATE_READ: 169 | case AT_PARSER_STATE_TEST: 170 | ms_array_slice_to_string(line, start, index_command_end, temp); 171 | result = at_execute_command(temp, ret, state); 172 | break; 173 | 174 | case AT_PARSER_STATE_WRITE: 175 | ms_array_slice_to_string(line, start, index_command_end, temp); 176 | if(index_write_start <= (line_len - 1)) 177 | { 178 | ms_array_slice_to_string(line, index_write_start, line_len - 1, ret); 179 | result = at_execute_command(temp, ret, state); 180 | ret[0] = 0; 181 | } 182 | else 183 | { 184 | result = at_execute_command(temp, ret, state); 185 | ret[0] = 0; 186 | } 187 | break; 188 | 189 | default: 190 | return AT_ERROR; 191 | } 192 | } 193 | 194 | 195 | return result; 196 | } 197 | -------------------------------------------------------------------------------- /AT_Parser_Arduino/at_parser.h: -------------------------------------------------------------------------------- 1 | #ifndef AT_PARSER_H 2 | #define AT_PARSER_H 3 | 4 | #include "my_string.h" 5 | 6 | #define AT_MAX_TEMP_STRING 50 7 | 8 | typedef char (*at_callback)(unsigned char *value); 9 | 10 | #define AT_OK 0 11 | #define AT_ERROR 1 12 | 13 | #define AT_ERROR_STRING "ERROR" 14 | #define AT_OK_STRING "OK" 15 | 16 | #define AT_PARSER_STATE_COMMAND 0 17 | #define AT_PARSER_STATE_TEST 1 18 | #define AT_PARSER_STATE_READ 2 19 | #define AT_PARSER_STATE_WRITE 3 20 | #define AT_PARSER_STATE_EQUAL 4 21 | 22 | #ifndef AT_COMMAND_MARKER 23 | #define AT_COMMAND_MARKER "AT+" 24 | #endif 25 | 26 | #ifdef __cplusplus 27 | extern "C"{ 28 | #endif 29 | 30 | unsigned long at_hash(string_t str); 31 | void at_register_command(string_t command, at_callback getter, at_callback setter, at_callback test, at_callback execute); 32 | char at_parse_line(string_t line, unsigned char *ret); 33 | 34 | #ifdef __cplusplus 35 | } // extern "C" 36 | #endif 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /AT_Parser_Arduino/my_string.c: -------------------------------------------------------------------------------- 1 | #include "my_string.h" 2 | 3 | #include 4 | 5 | uint16_t ms_strlen(string_t string) 6 | { 7 | uint16_t i; 8 | for(i = 0; *string; i++, string++); 9 | return i; 10 | } 11 | 12 | void ms_shift_array(char *array, uint16_t len) 13 | { 14 | int i; 15 | for(i = 0; i < len - 1; i++) 16 | { 17 | array[i] = array[i + 1]; 18 | } 19 | } 20 | 21 | char ms_str_equal(string_t string1, uint16_t len1, string_t string2, uint16_t len2) 22 | { 23 | int i; 24 | 25 | for(i = 0; i < len2; i++) 26 | { 27 | if(string1[len1 - len2 + i] != string2[i]) 28 | { 29 | return 0; 30 | } 31 | } 32 | 33 | return 1; 34 | } 35 | 36 | int16_t ms_str_find(string_t haystack, string_t needle) 37 | { 38 | int i; 39 | uint16_t needle_len = ms_strlen(needle); 40 | uint16_t haystack_len = ms_strlen(haystack); 41 | 42 | if(needle_len > haystack_len) 43 | { 44 | return -1; 45 | } 46 | 47 | for(i = 0; i < haystack_len - needle_len; i++) 48 | { 49 | if(ms_str_equal(haystack, needle_len, needle, needle_len)) 50 | { 51 | return i; 52 | } 53 | 54 | haystack++; 55 | } 56 | 57 | return -1; 58 | } 59 | 60 | void ms_dump_array(char *array, uint16_t max_buffer, uint16_t reverse_pointer) 61 | { 62 | int i; 63 | for(i = 0; i < max_buffer - reverse_pointer; i++) 64 | { 65 | printf("[%c]", array[reverse_pointer + i]); 66 | } 67 | } 68 | 69 | uint16_t ms_power(uint16_t base, uint16_t exponent) 70 | { 71 | uint16_t ret = 1; 72 | int i; 73 | for(i = 0; i < exponent; i++) 74 | { 75 | ret *= base; 76 | } 77 | return ret; 78 | } 79 | 80 | uint16_t ms_array_to_number(char * array, uint16_t max_buffer, uint16_t reverse_pointer) 81 | { 82 | int i; 83 | 84 | uint16_t ret = 0; 85 | 86 | for(i = 0; i < max_buffer - reverse_pointer; i++) 87 | { 88 | ret += (array[reverse_pointer + i] - '0') * ms_power(10, max_buffer - reverse_pointer - i - 1); 89 | } 90 | 91 | return ret; 92 | } 93 | 94 | void ms_array_slice_to_string(string_t array, uint16_t start, uint16_t end, unsigned char *ret) 95 | { 96 | uint16_t i, n = 0; 97 | 98 | for(i = start; i <= end; i++) 99 | { 100 | ret[n] = array[i]; 101 | n++; 102 | } 103 | 104 | ret[n] = 0; 105 | } -------------------------------------------------------------------------------- /AT_Parser_Arduino/my_string.h: -------------------------------------------------------------------------------- 1 | #ifndef __MY_STRING__ 2 | #define __MY_STRING__ 3 | 4 | #include "types.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C"{ 8 | #endif 9 | 10 | int16_t ms_str_find(string_t haystack, string_t needle); 11 | void ms_array_slice_to_string(string_t array, uint16_t start, uint16_t end, unsigned char *ret); 12 | uint16_t ms_strlen(string_t string); 13 | 14 | #ifdef __cplusplus 15 | } // extern "C" 16 | #endif 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /AT_Parser_Arduino/types.h: -------------------------------------------------------------------------------- 1 | #ifndef _TYPES_H__ 2 | #define _TYPES_H__ 3 | 4 | #ifndef NULL 5 | #define NULL 0 6 | #endif 7 | 8 | #include 9 | 10 | //typedef unsigned short uint16_t; 11 | //typedef signed short int16_t; 12 | 13 | typedef const unsigned char * string_t; 14 | 15 | #endif 16 | --------------------------------------------------------------------------------