/********************************************************************** * Function: IQNtoa() * * Description: Converts IQ number to an ASCII string * * DSP: TMS320F28x * * Author: DA * * Include files: stdio.h * * Function Prototype: int __IQNtoa(char *, const char *, long, int) * * Usage: error = __IQNtoa(char *string, const char *format, * long x, int qvalue); * * Input Parameters: * string = output string * format = conversion format. Must be of form "%xx.yyf" with * xx and yy at most 2 characters in length. * Examples: "%10.12f", "%2.4f", "%11.6f" * Maximum supported integer field width (xx) is 11 * (including any negative sign). This captures the full * integer range for I2Q30 to I31Q1 numbers. * x = input value (IQ format) * qvalue = IQ format of x (e.g., 24 means I8Q24) * * Return Value: * error = error code: * 0 = no error * 1 = iwidth too small to hold integer characters * 2 = illegal format specified * * Notes: * * 1) Leading zeros are not printed for the integer part. Hence, format * specifies the maximum width of the integer field. The field may * be smaller. * 2) The output string is terminated with the null character. * 3) The integer width in "format" includes the negative sign for * negative numbers, e.g. -12.3456 is "%3.5f" * 4) The decimal width in "format" includes the decimal point, e.g. * -12.3456 is "%3.5f" * 5) "string" must be large enough to hold the output (including the * negative sign, and the terminating null character). The program * does not check for overrun. Memory corruption will occur if * "string" is too small. * 6) A non-zero return value indicates that the output string is invalid. * 7) Benchmark is roughly 200 to 800 cycles, depending on the format and * the input value. * * History: December 23, 2004 - original (D. Alter) * **********************************************************************/ //############################################################################# //! //! Copyright: Copyright (C) 2023 Texas Instruments Incorporated - //! All rights reserved not granted herein. //! Limited License. //! //! Texas Instruments Incorporated grants a world-wide, royalty-free, //! non-exclusive license under copyrights and patents it now or hereafter //! owns or controls to make, have made, use, import, offer to sell and sell //! ("Utilize") this software subject to the terms herein. With respect to the //! foregoing patent license, such license is granted solely to the extent that //! any such patent is necessary to Utilize the software alone. The patent //! license shall not apply to any combinations which include this software, //! other than combinations with devices manufactured by or for TI //! ("TI Devices"). //! No hardware patent is licensed hereunder. //! //! Redistributions must preserve existing copyright notices and reproduce this //! license (including the above copyright notice and the disclaimer and //! (if applicable) source code license limitations below) in the documentation //! and/or other materials provided with the distribution. //! //! Redistribution and use in binary form, without modification, are permitted //! provided that the following conditions are met: //! //! * No reverse engineering, decompilation, or disassembly of this software is //! permitted with respect to any software provided in binary form. //! * Any redistribution and use are licensed by TI for use only //! with TI Devices. //! * Nothing shall obligate TI to provide you with source code for the //! software licensed and provided to you in object code. //! //! If software source code is provided to you, modification and redistribution //! of the source code are permitted provided that the following conditions //! are met: //! //! * any redistribution and use of the source code, including any resulting //! derivative works, are licensed by TI for use only with TI Devices. //! * any redistribution and use of any object code compiled from the source //! code and any resulting derivative works, are licensed by TI for use //! only with TI Devices. //! //! Neither the name of Texas Instruments Incorporated nor the names of its //! suppliers may be used to endorse or promote products derived from this //! software without specific prior written permission. //############################################################################# // Function prototypes extern char _IQNtoa_get_frac_c(unsigned long); /**********************************************************************/ #pragma CODE_SECTION(__IQNtoa, "IQmath"); int __IQNtoa(char *string, const char *format, long x, int qvalue) { unsigned long uval; // working variable char *bufptr; // buffer pointer char buf[11]; // temporary char buffer (worst case length) int count; // conversion character counter int error = 0; // error value int neg = 0; // negative flag int iwidth; // integer format width int dwidth; // decimal format width int scale; // format parsing scaling value //-------------------------------------------------------------------- // Parse the format parameter // // Check that 1st character is "%" if(*format++ != '%') return(2); // error: missing the leading '%' // Extract iwidth if(*format == '.') return(2); // error: no iwidth field count = 0; // zero the counter scale = 1; // init scale iwidth = 0; // init iwidth while(*format != '.') // find the '.' { count++; // increment the count iwidth = iwidth*scale + (*format++ - '0'); scale = scale * 10; // If we don't find the '.' after, say, 4 counts, something is wrong if(count > 2) return(2); // error: iwidth field too many characters } if(iwidth > 11) return(2); // error: iwidth too large if(iwidth < 0) return(2); // error: iwidth negative // Extract dwidth format++; // advance format off the '.' if(*format == 0) return(2); // error: no dwidth field count = 0; // zero the counter scale = 1; // init scale dwidth = 0; // init dwidth while((*format != 'f') && (*format != 'F')) // find the conversion character { count++; // increment the count dwidth = dwidth*scale + (*format++ - '0'); scale = scale * 10; // If we don't find the conversion character after, say, 4 counts, something is wrong if(count > 2) return(2); // error: dwidth field too large } if(dwidth < 0) return(2); // error: dwidth negative // Check that the next character is the NULL string terminator if(*++format != 0) return(2); // error: missing null terminator //-------------------------------------------------------------------- // Check for negative value // if(x < 0) { x = -x; // make it positive neg = 1; // set negative flag } //-------------------------------------------------------------------- // Process the integer part // // Isolate the integer part uval = x >> qvalue; // Convert the integer part bufptr = buf; // init the pointer count = 0; // zero the counter do { *bufptr++ = (uval % 10) + '0'; // extract the next character count++; // increment the counter } while(uval = uval/10); // remove the character value from uval if(neg) { *bufptr++ = '-'; // insert a '-' count++; // increment the counter } if(count > iwidth) { count = iwidth; // set count = iwidth error = 1; // error: integer format too small } while(count--) { *string++ = *--bufptr; // copy the character to the string } //-------------------------------------------------------------------- // Process the fractional part // if(dwidth > 0) { // Insert the decimal point *string++ = '.'; // insert the decimal point dwidth--; // decrement the fraction length // Isolate the fractional part uval = x << (32-qvalue); // I0Q32 format // Convert the fractional part for(count = 0; count < dwidth; count++) { *string++ = _IQNtoa_get_frac_c(uval) + '0'; // extract the character uval = uval * 10; // remove the character value from uval } } // end if //-------------------------------------------------------------------- // Finish up // *string = 0; // add the NUL character to terminate string return(error); // return } // end of __IQNtoa() /*** end of file *****************************************************/