Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: modem_ref_helper_for_v5_3_217
kal_codec.cpp
00001 /// @copyright 00002 /// ========================================================================={{{ 00003 /// Copyright (c) 20XX WizziLab / 00004 /// All rights reserved / 00005 /// / 00006 /// IMPORTANT: This Software may not be modified, copied or distributed unless / 00007 /// embedded on a WizziLab product. Other than for the foregoing purpose, this / 00008 /// Software and/or its documentation may not be used, reproduced, copied, / 00009 /// prepared derivative works of, modified, performed, distributed, displayed / 00010 /// or sold for any purpose. For the sole purpose of embedding this Software / 00011 /// on a WizziLab product, copy, modification and distribution of this / 00012 /// Software is granted provided that the following conditions are respected: / 00013 /// / 00014 /// * Redistributions of source code must retain the above copyright notice, / 00015 /// this list of conditions and the following disclaimer / 00016 /// / 00017 /// * Redistributions in binary form must reproduce the above copyright / 00018 /// notice, this list of conditions and the following disclaimer in the / 00019 /// documentation and/or other materials provided with the distribution. / 00020 /// / 00021 /// * The name of WizziLab can not be used to endorse or promote products / 00022 /// derived from this software without specific prior written permission. / 00023 /// / 00024 /// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS / 00025 /// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED / 00026 /// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR / 00027 /// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR / 00028 /// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, / 00029 /// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, / 00030 /// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, / 00031 /// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY / 00032 /// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING / 00033 /// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS / 00034 /// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. / 00035 /// WIZZILAB HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, / 00036 /// ENHANCEMENTS OR MODIFICATIONS. / 00037 /// / 00038 /// Should you have any questions regarding your right to use this Software, / 00039 /// contact WizziLab at www.wizzilab.com. / 00040 /// / 00041 /// =========================================================================}}} 00042 /// @endcopyright 00043 /// 00044 /// ======================================================================= 00045 /// 00046 /// @file kal_codec.c 00047 /// @brief Codec Utilities 00048 /// 00049 /// ======================================================================= 00050 00051 #include <string.h> 00052 #include "hal_types.h" 00053 #include "kal_codec.h" 00054 00055 00056 // ====================================================================== 00057 // 00058 // 00059 // ASCII to Binary Codec Toolkits 00060 // 00061 // 00062 // ====================================================================== 00063 00064 const char k_nybble_chars[] = "0123456789ABCDEF"; 00065 00066 //====================================================================== 00067 // hex2ascii 00068 //---------------------------------------------------------------------- 00069 /// @brief Convert hexadecimal number to ascii 00070 /// @param char* in input buffer (hex) 00071 /// @param char* out output buffer (ascii) 00072 /// @param u16 len length of inoput buffer in bytes 00073 //====================================================================== 00074 void hex2ascii( char* in, char* out, u16 length) 00075 { 00076 u8 b; 00077 while(length--) { 00078 b = *in++; 00079 *out++ = k_nybble_chars[ ( b >> 4 ) & 0x0F ]; 00080 *out++ = k_nybble_chars[ b & 0x0F ]; 00081 } 00082 } 00083 00084 //====================================================================== 00085 // itoa 00086 //---------------------------------------------------------------------- 00087 /// @brief Converts an integer value to a null-terminated string using the specified base and stores the result 00088 /// in the array given by result parameter. 00089 /// @param int value integer to convert 00090 /// @param char* result converted string 00091 /// @param int base base used for conversion 2, 8, 10, 16 00092 /// @return A pointer to the resulting null-terminated string, same as parameter result 00093 //====================================================================== 00094 char* itoa(int value, char* result, int base) 00095 { 00096 // check that the base if valid 00097 //if (base < 2 || base > 16) { return NULL; } 00098 00099 char* ptr = result, *ptr1 = result, tmp_char; 00100 int tmp_value; 00101 00102 do { 00103 tmp_value = value; 00104 value /= base; 00105 *ptr++ = "fedcba9876543210123456789abcdef" [15 + (tmp_value - value * base)]; 00106 } while ( value ); 00107 00108 // Apply negative sign 00109 if (tmp_value < 0) *ptr++ = '-'; 00110 //*ptr-- = '\0'; 00111 result = ptr--; 00112 while(ptr1 < ptr) { 00113 tmp_char = *ptr; 00114 *ptr--= *ptr1; 00115 *ptr1++ = tmp_char; 00116 } 00117 return result; 00118 } 00119 00120 //====================================================================== 00121 // atoitok 00122 //---------------------------------------------------------------------- 00123 /// @brief Extracts from a ASCII string a value (decimal or hex) and 00124 /// convert it to an integer value. 00125 /// - Blank characters are skipped 00126 /// - hexa values must begin with '0x' or '0X' 00127 /// - '-' sign is handled 00128 /// - returns after one value has been parsed or null character 00129 /// or CR character has been found. 00130 /// @param p pointer to pointer to the string to be parsed. The pointer 00131 /// to string is modified: at the end of the call it points to 00132 /// the character following the last parsed one. 00133 //====================================================================== 00134 int atoitok(u8 **p) 00135 { 00136 int k = 0; 00137 u8 base16=0; 00138 s8 sign = 1; 00139 while ((**p==' ')||(**p=='\t')||(**p==',')) (*p)++; 00140 if (**p=='-') 00141 { 00142 sign = -1; 00143 (*p)++; 00144 } 00145 if ((**p=='0') && (*(*p+1)=='x')) 00146 { 00147 base16 = 1; 00148 *p += 2; 00149 } 00150 while (**p && **p!=' ' && **p!=0xa && **p!=',') { 00151 if (!base16) 00152 { 00153 k = (k<<3)+(k<<1)+(**p)-'0'; 00154 } 00155 else 00156 { 00157 if (**p > '9') 00158 if (**p > 'F') 00159 k = (k<<4)+(10+(**p)-'a'); 00160 else 00161 k = (k<<4)+(10+(**p)-'A'); 00162 else 00163 k = (k<<4)+(**p)-'0'; 00164 } 00165 (*p)++; 00166 } 00167 return sign*k; 00168 } 00169 00170 //====================================================================== 00171 // kal_atoi 00172 //---------------------------------------------------------------------- 00173 /// @brief Extracts from a ASCII string a decimal value and 00174 /// convert it to an integer value. 00175 /// '-' and '+' signs are handled 00176 /// @param s char* string to convert 00177 /// @retval s32 integer value 00178 //====================================================================== 00179 s32 kal_atoi(u8* s) 00180 { 00181 s32 k = 0; 00182 s8 sign = 1; 00183 00184 if (*s == '-') 00185 { 00186 sign = -1; 00187 s++; 00188 } 00189 else if (*s == '+') 00190 { 00191 s++; 00192 } 00193 00194 while (*s >= '0' && *s <= '9') 00195 { 00196 k = 10 * k + *s - '0'; 00197 s++; 00198 } 00199 00200 return (sign * k); 00201 } 00202 00203 //====================================================================== 00204 // kal_atoi_float 00205 //---------------------------------------------------------------------- 00206 /// @brief Extracts from a ASCII string a float value and 00207 /// convert it to an integer value * 10^number_of_decimals. 00208 /// '-' and '+' signs are handled 00209 /// @param s char* string to convert 00210 /// @param d u8 Number of decimals 00211 /// @retval s32 integer value 00212 //====================================================================== 00213 s32 kal_atoi_float(u8* s, u8 d) 00214 { 00215 s32 k_int = 0; 00216 s32 k_dec = 0; 00217 s8 sign = 1; 00218 u8 i; 00219 00220 // Check sign 00221 if (*s == '-') 00222 { 00223 sign = -1; 00224 s++; 00225 } 00226 else if (*s == '+') 00227 { 00228 s++; 00229 } 00230 00231 // Calculate integer part 00232 while (*s >= '0' && *s <= '9') 00233 { 00234 k_int = 10 * k_int + *s - '0'; 00235 s++; 00236 } 00237 00238 for (i = 0; i < d; i++) 00239 { 00240 k_int *= 10; 00241 } 00242 00243 // Skip float separator 00244 if (*s == '.') 00245 { 00246 s++; 00247 } 00248 else 00249 { 00250 return (sign * k_int); 00251 } 00252 00253 // Calculate decimal part 00254 while (*s >= '0' && *s <= '9' && d--) 00255 { 00256 k_dec = 10 * k_dec + *s - '0'; 00257 s++; 00258 } 00259 00260 // If string is finished but all the decimals aren't there, complete as if they were followed by 0s 00261 for (i = 0; i < d; i++) 00262 { 00263 k_dec *= 10; 00264 } 00265 00266 return (sign * (k_int + k_dec)); 00267 } 00268 //====================================================================== 00269 // kal_atoi_hex 00270 //---------------------------------------------------------------------- 00271 /// @brief Extracts from a ASCII string a hex value and 00272 /// convert it to an integer value. 00273 /// @param s char* string to convert 00274 /// @retval u32 integer value 00275 //====================================================================== 00276 u32 kal_atoi_hex(u8* s) 00277 { 00278 u32 k = 0; 00279 00280 while (*s != '\0') 00281 { 00282 if (*s > '9') 00283 { 00284 k = 16 * k + 10 + (*s) - ((*s > 'F') ? 'a' : 'A'); 00285 } 00286 else 00287 { 00288 k = 16 * k + (*s) - '0'; 00289 } 00290 s++; 00291 } 00292 00293 return (k); 00294 } 00295 00296 //====================================================================== 00297 // kal_base64_strlen 00298 //---------------------------------------------------------------------- 00299 /// @brief Real length (excluding padding) of Base64-encoded string 00300 /// Note : the input string always has 4x chars, if not return 0 00301 /// @param in char* string to decode 00302 /// @retval u16 string length 00303 //====================================================================== 00304 u16 kal_base64_strlen(const char* in) 00305 { 00306 u16 len, j; 00307 register const char *p; 00308 00309 // Useful strlen 00310 len = strlen(in); 00311 00312 // the input string always has 4x chars 00313 if (len % 4) 00314 { 00315 return 0; 00316 } 00317 00318 // remove padding 00319 for (j = 0, p = in + len - 1; len > 0 && *p == '=' ; j++, p--, len--) {;} 00320 00321 // there is 0, 1 or 2 padding chars 00322 if (j > 2) 00323 { 00324 return 0; 00325 } 00326 00327 return len; 00328 } 00329 00330 //====================================================================== 00331 // kal_base64 codec tables 00332 //====================================================================== 00333 const char k_kal_base64_encode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 00334 const u8 k_kal_base64_decode[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00335 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00336 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 63, 62, 62, 63, 00337 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 00338 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 00339 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 63, 00340 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 00341 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 00342 }; 00343 00344 //====================================================================== 00345 // kal_base64_encode 00346 //---------------------------------------------------------------------- 00347 /// @brief Encode Base64-encoded buffer. The output buffer is supposed to have enough space 00348 /// Beware, the stream encoding is Big Endian. 00349 /// @param out char* string result 00350 /// @param in u8* binary buffer to encode 00351 /// @param len u16 length of the binary buffer in bytes 00352 /// @retval void 00353 //====================================================================== 00354 void kal_base64_encode(char *out, u8* in, u16 len) 00355 { 00356 u16 i = 0; 00357 register u8 a,b,c; 00358 00359 if (len > 1) 00360 { 00361 for (; i < len - 2; i += 3) 00362 { 00363 a = *in++; 00364 b = *in++; 00365 c = *in++; 00366 *out++ = k_kal_base64_encode[(((a >> 2) & 0x3F))]; 00367 *out++ = k_kal_base64_encode[(((a << 4) & 0x30) | ((b >> 4) & 0x0F))]; 00368 *out++ = k_kal_base64_encode[(((b << 2) & 0x3C) | ((c >> 6) & 0x03))]; 00369 *out++ = k_kal_base64_encode[(((c >> 0) & 0x3F))]; 00370 } 00371 } 00372 00373 if (i < len) 00374 { 00375 a = *in++; 00376 *out++ = k_kal_base64_encode[(((a >> 2) & 0x3F))]; 00377 00378 if (i == (len - 1)) 00379 { 00380 *out++ = k_kal_base64_encode[(((a << 4) & 0x30))]; 00381 *out++ = '='; 00382 } 00383 else 00384 { 00385 b = *in++; 00386 *out++ = k_kal_base64_encode[(((a << 4) & 0x30) | ((b >> 4) & 0x0F))]; 00387 *out++ = k_kal_base64_encode[(((b << 2) & 0x3C))]; 00388 } 00389 00390 *out++ = '='; 00391 } 00392 00393 *out++ = '\0'; 00394 return; 00395 } 00396 00397 //====================================================================== 00398 // kal_base64_decode 00399 //---------------------------------------------------------------------- 00400 /// @brief Decode Base64-encoded buffer. The output buffer is supposed to have enough space 00401 /// @param out u8* binary buffer result 00402 /// @param in char* string to decode 00403 /// @param len u16 string length, excluding padding 00404 /// @retval void 00405 //====================================================================== 00406 void kal_base64_decode(u8 *out, const char* in, u16 len) 00407 { 00408 register u8 a,b,c,d; 00409 00410 // Decode 00411 for (; len > 3; len -= 4) 00412 { 00413 a = k_kal_base64_decode[(u8)*in++]; 00414 b = k_kal_base64_decode[(u8)*in++]; 00415 c = k_kal_base64_decode[(u8)*in++]; 00416 d = k_kal_base64_decode[(u8)*in++]; 00417 00418 *out++ = (a << 2) | (b >> 4); 00419 *out++ = (b << 4) | (c >> 2); 00420 *out++ = (c << 6) | (d >> 0); 00421 } 00422 00423 // Note len == 1 is not possible 00424 if (len > 1) 00425 { 00426 a = k_kal_base64_decode[(u8)*in++]; 00427 b = k_kal_base64_decode[(u8)*in++]; 00428 *out++ = (a << 2) | (b >> 4); 00429 } 00430 if (len > 2) 00431 { 00432 c = k_kal_base64_decode[(u8)*in++]; 00433 *out++ = (b << 4) | (c >> 2); 00434 } 00435 } 00436 00437 //====================================================================== 00438 // kal_tolower 00439 //---------------------------------------------------------------------- 00440 /// @brief Changes inplace to lower character a non-constant string 00441 /// @param s u8* String to transform 00442 /// @retval void 00443 //====================================================================== 00444 void kal_tolower(u8* s) 00445 { 00446 while (*s != '\0') 00447 { 00448 if (*s >= 'A' && *s <= 'Z') 00449 { 00450 *s += (u8)('a' - 'A'); 00451 } 00452 s++; 00453 } 00454 } 00455 00456 00457 //====================================================================== 00458 // kal_toupper 00459 //---------------------------------------------------------------------- 00460 /// @brief Changes inplace to upper character a non-constant string 00461 /// @param s u8* String to transform 00462 /// @retval void 00463 //====================================================================== 00464 void kal_toupper(u8* s) 00465 { 00466 while (*s != '\0') 00467 { 00468 if (*s >= 'a' && *s <= 'z') 00469 { 00470 *s -= (u8)('a' - 'A'); 00471 } 00472 s++; 00473 } 00474 } 00475 00476 //====================================================================== 00477 // kal_crc8 00478 //---------------------------------------------------------------------- 00479 /// @brief Return CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial. 00480 /// A table-based algorithm would be faster, but for only a few 00481 /// bytes it isn't worth the code size. 00482 /// @param in u8* input buffer 00483 /// @param len u32 input buffer length in bytes 00484 /// @retval void 00485 //====================================================================== 00486 /* Return CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial. A 00487 * table-based algorithm would be faster, but for only a few bytes it isn't 00488 * worth the code size. */ 00489 u8 kal_crc8(u8* in, u32 len) 00490 { 00491 const u8 *data = in; 00492 u32 crc = 0; 00493 u8 i; 00494 u32 j; 00495 00496 for (j = len; j; j--, data++) 00497 { 00498 crc ^= (*data << 8); 00499 for(i = 8; i; i--) 00500 { 00501 if (crc & 0x8000) 00502 { 00503 crc ^= (0x1070 << 3); 00504 } 00505 crc <<= 1; 00506 } 00507 } 00508 return (u8)(crc >> 8); 00509 } 00510 00511 //====================================================================== 00512 // kal_ctf_encode 00513 //---------------------------------------------------------------------- 00514 /// @brief Compress u32 to D7A Compressed Time format (CTF). 00515 /// The ceil flag is used to define rounding, so that 00516 /// kal_ctf_decode(kal_ctf_encode(val, FALSE) <= val (floor) 00517 /// kal_ctf_decode(kal_ctf_encode(val, TRUE) >= val (ceiling) 00518 /// @param val u32 value to encode 00519 /// @param ceil u8 ceil value when TRUE 00520 /// @retval kal_ctf_t compressed value 00521 //====================================================================== 00522 kal_ctf_t kal_ctf_encode(u32 val, u8 ceil) 00523 { 00524 u8 exp; 00525 u32 tmp = val; 00526 kal_ctf_t ctf; 00527 00528 // serch best (smallest) exponent 00529 for (exp = 0; tmp > 31; exp++, tmp >>= 2) {}; 00530 00531 if (exp < 8) 00532 { 00533 ctf.bf.exp = exp; 00534 ctf.bf.mant = tmp; 00535 00536 // manage floor 00537 if (ceil) 00538 { 00539 if (kal_ctf_decode(ctf) < val) 00540 { 00541 if (ctf.bf.mant < 31) 00542 { 00543 ctf.bf.mant++; 00544 } 00545 else 00546 { 00547 if (ctf.bf.exp < 7) 00548 { 00549 // mant = 31+1 = 4*8 00550 ctf.bf.exp++; 00551 ctf.bf.mant = 8; 00552 } 00553 else 00554 { 00555 // exp = 7+1 -> overflow 00556 ctf.byte = 0xff; 00557 } 00558 } 00559 } 00560 } 00561 } 00562 else 00563 { 00564 ctf.byte = 0xff; 00565 } 00566 00567 return ctf; 00568 } 00569 00570 // ======================================================================= 00571 // kal_ctf_decode 00572 // ----------------------------------------------------------------------- 00573 /// @brief Decompress from Compressed Time Format to u32 00574 /// @param ctf kal_ctf_t compressed value in CTF 00575 /// @retval u32 decode result 00576 // ======================================================================= 00577 u32 kal_ctf_decode(kal_ctf_t ctf) 00578 { 00579 return ((1 << (2*ctf.bf.exp)) * ctf.bf.mant); 00580 } 00581
Generated on Wed Jul 20 2022 12:33:07 by
