void NatcarUartUpdate(void) { if(!Enabled) return; if (CurrentState == LISTEN) { // listen for the command chars if(UARTRxBytesAvail() >= 3) { CurrentCommand[0] = UARTgetc(); CurrentCommand[1] = UARTgetc(); CurrentCommand[2] = UARTgetc(); // MAYBE? check the commands? CurrentState = ACTIVE; } } else if (CurrentState == ACTIVE) { // process commands // if..else handle each command if (strcmp(CurrentCommand, "HAI") == 0) { // write back "AOK" UARTwrite("AOK", 3); UARTFlushRx(); CurrentState = LISTEN; } else if (strcmp(CurrentCommand, "PID") == 0) { // write in pid values -> for ( ; UARTRxBytesAvail() > 0; ) NU_Buffer = NUB_Append(NU_Buffer, UARTgetc()); // if we have sufficient data in NU_Buffer and we haven't // actually processed any data yet if (NUB_Len(NU_Buffer) >= 4 && NU_MessageLength == -1) { // read message length char msgLen[4]; NU_Buffer = NUB_PopFront(NU_Buffer, &msgLen[0]); NU_Buffer = NUB_PopFront(NU_Buffer, &msgLen[1]); NU_Buffer = NUB_PopFront(NU_Buffer, &msgLen[2]); NU_Buffer = NUB_PopFront(NU_Buffer, &msgLen[3]); // do something with newfound data NU_MessageLength = atoi(msgLen); } // if buffer has enough data if (NUB_Len(NU_Buffer) >= NU_MessageLength) { // set variables accordingly } } else { // comamnd not recognized.. done with command and restart UARTFlushRx(); CurrentState = LISTEN; } // if (done with command) then // clear buffers // CurrentState = LISTEN; } else { // shouldn't be here... // flush buffer and set to LISTEN } }
void UARTwriteString (char str[]) { unsigned char i=0; while(str[i]) { UARTwrite(str[i++]); } }
// Function to print the value of a unsigned long using the formatting gathered by printf static void convert(unsigned long ulValue, unsigned long ulCount, const char *pcHex, char cNeg, char cFill, unsigned long ulBase) { char pcBuf[16]; unsigned long ulIdx, ulPos = 0; for(ulIdx = 1; (((ulIdx * ulBase) <= ulValue) && (((ulIdx * ulBase) / ulBase) == ulIdx)); ulIdx *= ulBase, ulCount--) { } // If the value is negative, reduce the count of padding // characters needed. if(cNeg) { ulCount--; } // If the value is negative and the value is padded with // zeros, then place the minus sign before the padding. if(cNeg && (cFill == '0')) { // Place the minus sign in the output buffer. pcBuf[ulPos++] = '-'; // The minus sign has been placed, so turn off the // negative flag. cNeg = 0; } // Provide additional padding at the beginning of the // string conversion if needed. if((ulCount > 1) && (ulCount < 16)) { for(ulCount--; ulCount; ulCount--) { pcBuf[ulPos++] = cFill; } } // If the value is negative, then place the minus sign // before the number. if(cNeg) { // Place the minus sign in the output buffer. pcBuf[ulPos++] = '-'; } // Convert the value into a string. for(; ulIdx; ulIdx /= ulBase) { pcBuf[ulPos++] = pcHex[(ulValue / ulIdx) % ulBase]; } // Write the string. UARTwrite(pcBuf, ulPos); }
void UARTwriteDecimal(unsigned char c) { unsigned char hC,d=100; do { hC=c/d; UARTwrite(hC+48); c-=hC*d; d/=10; }while(d); }
void teletype(const char *s) { int i; char c; while(*s) { UARTwrite(*(s++)); // delay(250); for(i=0; i<10000; i++) asm("nop"); } }
unsigned char UARTcharFromString(unsigned char c) { unsigned char rC,outF=0,c1=c-48; while(outF==0) { while(RCIF==0); if(!(RCSTA&0b00000110)) { rhead++; rhead&=RINGBUFFMASK; ringbuff[rhead]=RCREG; } RCIF=0; rC=UARTread(); UARTwrite(rC); if(rC==13)outF=1; //CR end of transmition else { c1*=10; c1+=(rC-48); } } return c1; }
/** * A simple UART based printf function supporting \%c, \%d, \%p, \%s, \%u, * \%x, and \%X. * * \param pcString is the format string. * \param ... are the optional arguments, which depend on the contents of the * format string. * * This function is very similar to the C library <tt>fprintf()</tt> function. * All of its output will be sent to the UART. Only the following formatting * characters are supported: * * - \%c to print a character * - \%d to print a decimal value * - \%s to print a string * - \%u to print an unsigned decimal value * - \%x to print a hexadecimal value using lower case letters * - \%X to print a hexadecimal value using lower case letters (not upper case * letters as would typically be used) * - \%p to print a pointer as a hexadecimal value * - \%\% to print out a \% character * * For \%s, \%d, \%u, \%p, \%x, and \%X, an optional number may reside * between the \% and the format character, which specifies the minimum number * of characters to use for that value; if preceded by a 0 then the extra * characters will be filled with zeros instead of spaces. For example, * ``\%8d'' will use eight characters to print the decimal value with spaces * added to reach eight; ``\%08d'' will use eight characters as well but will * add zeroes instead of spaces. * * The type of the arguments after \e pcString must match the requirements of * the format string. For example, if an integer was passed where a string * was expected, an error of some kind will most likely occur. * * \return None. */ void UARTprintf(const char *pcString, ...) { unsigned int idx, pos, count, base, neg; char *pcStr, pcBuf[16], cFill; va_list vaArgP; int value; /* Start the varargs processing. */ va_start(vaArgP, pcString); /* Loop while there are more characters in the string. */ while(*pcString) { /* Find the first non-% character, or the end of the string. */ for(idx = 0; (pcString[idx] != '%') && (pcString[idx] != '\0'); idx++) { } /* Write this portion of the string. */ UARTwrite(pcString, idx); /* Skip the portion of the string that was written. */ pcString += idx; /* See if the next character is a %. */ if(*pcString == '%') { /* Skip the %. */ pcString++; /* Set the digit count to zero, and the fill character to space * (i.e. to the defaults). */ count = 0; cFill = ' '; /* It may be necessary to get back here to process more characters. * Goto's aren't pretty, but effective. I feel extremely dirty for * using not one but two of the beasts. */ again: /* Determine how to handle the next character. */ switch(*pcString++) { /* Handle the digit characters. */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { /* If this is a zero, and it is the first digit, then the * fill character is a zero instead of a space. */ if((pcString[-1] == '0') && (count == 0)) { cFill = '0'; } /* Update the digit count. */ count *= 10; count += pcString[-1] - '0'; /* Get the next character. */ goto again; } /* Handle the %c command. */ case 'c': { /* Get the value from the varargs. */ value = va_arg(vaArgP, unsigned int); /* Print out the character. */ UARTwrite((char *)&value, 1); /* This command has been handled. */ break; } /* Handle the %d command. */ case 'd': { /* Get the value from the varargs. */ value = va_arg(vaArgP, unsigned int); /* Reset the buffer position. */ pos = 0; /* If the value is negative, make it positive and indicate * that a minus sign is needed. */ if((int)value < 0) { /* Make the value positive. */ value = -(int)value; /* Indicate that the value is negative. */ neg = 1; } else { /* Indicate that the value is positive so that a minus * sign isn't inserted. */ neg = 0; } /* Set the base to 10. */ base = 10; /* Convert the value to ASCII. */ goto convert; } /* Handle the %s command. */ case 's': { /* Get the string pointer from the varargs. */ pcStr = va_arg(vaArgP, char *); /* Determine the length of the string. */ for(idx = 0; pcStr[idx] != '\0'; idx++) { } /* Write the string. */ UARTwrite(pcStr, idx); /* Write any required padding spaces */ if(count > idx) { count -= idx; while(count--) { UARTwrite((const char *)" ", 1); } } /* This command has been handled. */ break; } /* Handle the %u command. */ case 'u': { /* Get the value from the varargs. */ value = va_arg(vaArgP, unsigned int); /* Reset the buffer position. */ pos = 0; /* Set the base to 10. */ base = 10; /* Indicate that the value is positive so that a minus sign * isn't inserted. */ neg = 0; /* Convert the value to ASCII. */ goto convert; } /* Handle the %x and %X commands. Note that they are treated * identically; i.e. %X will use lower case letters for a-f * instead of the upper case letters is should use. We also * alias %p to %x. */ case 'x': case 'X': case 'p': { /* Get the value from the varargs. */ value = va_arg(vaArgP, unsigned int); /* Reset the buffer position. */ pos = 0; /* Set the base to 16. */ base = 16; /* Indicate that the value is positive so that a minus sign * isn't inserted. */ neg = 0; /* Determine the number of digits in the string version of * the value. */ convert: for(idx = 1; (((idx * base) <= value) && (((idx * base) / base) == idx)); idx *= base, count--) { } /* If the value is negative, reduce the count of padding * characters needed. */ if(neg) { count--; } /* If the value is negative and the value is padded with * zeros, then place the minus sign before the padding. */ if(neg && (cFill == '0')) { /* Place the minus sign in the output buffer. */ pcBuf[pos++] = '-'; /* The minus sign has been placed, so turn off the * negative flag. */ neg = 0; } /* Provide additional padding at the beginning of the * string conversion if needed. */ if((count > 1) && (count < 16)) { for(count--; count; count--) { pcBuf[pos++] = cFill; } } /* If the value is negative, then place the minus sign * before the number. */ if(neg) { /* Place the minus sign in the output buffer. */ pcBuf[pos++] = '-'; } /* Convert the value into a string. */ for(; idx; idx /= base) { pcBuf[pos++] = g_pcHex[(value / idx) % base]; } /* Write the string. */ UARTwrite(pcBuf, pos); /* This command has been handled. */ break; } /* Handle the %% command. */ case '%': { /* Simply write a single %. */ UARTwrite(pcString - 1, 1); /* This command has been handled. */ break; } /* Handle all other commands. */ default: { /* Indicate an error. */ UARTwrite((const char *)"ERROR", 5); /* This command has been handled. */ break; } } } }
void UARTprintf(const char *pcString, ...) { unsigned long ulIdx, ulValue, ulPos, ulCount, ulBase, ulNeg; char *pcStr, pcBuf[16], cFill; va_list vaArgP; // // Check the arguments. // ASSERT(pcString != 0); // // Start the varargs processing. // va_start(vaArgP, pcString); // // Loop while there are more characters in the string. // while(*pcString) { // // Find the first non-% character, or the end of the string. // for(ulIdx = 0; (pcString[ulIdx] != '%') && (pcString[ulIdx] != '\0'); ulIdx++) { } // // Write this portion of the string. // UARTwrite(pcString, ulIdx); // // Skip the portion of the string that was written. // pcString += ulIdx; // // See if the next character is a %. // if(*pcString == '%') { // // Skip the %. // pcString++; // // Set the digit count to zero, and the fill character to space // (i.e. to the defaults). // ulCount = 0; cFill = ' '; // // It may be necessary to get back here to process more characters. // Goto's aren't pretty, but effective. I feel extremely dirty for // using not one but two of the beasts. // again: // // Determine how to handle the next character. // switch(*pcString++) { // // Handle the digit characters. // case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { // // If this is a zero, and it is the first digit, then the // fill character is a zero instead of a space. // if((pcString[-1] == '0') && (ulCount == 0)) { cFill = '0'; } // // Update the digit count. // ulCount *= 10; ulCount += pcString[-1] - '0'; // // Get the next character. // goto again; } // // Handle the %c command. // case 'c': { // // Get the value from the varargs. // ulValue = va_arg(vaArgP, unsigned long); // // Print out the character. // UARTwrite((char *)&ulValue, 1); // // This command has been handled. // break; } // // Handle the %d and %i commands. // case 'd': case 'i': { // // Get the value from the varargs. // ulValue = va_arg(vaArgP, unsigned long); // // Reset the buffer position. // ulPos = 0; // // If the value is negative, make it positive and indicate // that a minus sign is needed. // if((long)ulValue < 0) { // // Make the value positive. // ulValue = -(long)ulValue; // // Indicate that the value is negative. // ulNeg = 1; } else { // // Indicate that the value is positive so that a minus // sign isn't inserted. // ulNeg = 0; } // // Set the base to 10. // ulBase = 10; // // Convert the value to ASCII. // goto convert; } // // Handle the %s command. // case 's': { // // Get the string pointer from the varargs. // pcStr = va_arg(vaArgP, char *); // // Determine the length of the string. // for(ulIdx = 0; pcStr[ulIdx] != '\0'; ulIdx++) { } // // Write the string. // UARTwrite(pcStr, ulIdx); // // Write any required padding spaces // if(ulCount > ulIdx) { ulCount -= ulIdx; while(ulCount--) { UARTwrite(" ", 1); } } // // This command has been handled. // break; } // // Handle the %u command. // case 'u': { // // Get the value from the varargs. // ulValue = va_arg(vaArgP, unsigned long); // // Reset the buffer position. // ulPos = 0; // // Set the base to 10. // ulBase = 10; // // Indicate that the value is positive so that a minus sign // isn't inserted. // ulNeg = 0; // // Convert the value to ASCII. // goto convert; } // // Handle the %x and %X commands. Note that they are treated // identically; i.e. %X will use lower case letters for a-f // instead of the upper case letters is should use. We also // alias %p to %x. // case 'x': case 'X': case 'p': { // // Get the value from the varargs. // ulValue = va_arg(vaArgP, unsigned long); // // Reset the buffer position. // ulPos = 0; // // Set the base to 16. // ulBase = 16; // // Indicate that the value is positive so that a minus sign // isn't inserted. // ulNeg = 0; // // Determine the number of digits in the string version of // the value. // convert: for(ulIdx = 1; (((ulIdx * ulBase) <= ulValue) && (((ulIdx * ulBase) / ulBase) == ulIdx)); ulIdx *= ulBase, ulCount--) { } // // If the value is negative, reduce the count of padding // characters needed. // if(ulNeg) { ulCount--; } // // If the value is negative and the value is padded with // zeros, then place the minus sign before the padding. // if(ulNeg && (cFill == '0')) { // // Place the minus sign in the output buffer. // pcBuf[ulPos++] = '-'; // // The minus sign has been placed, so turn off the // negative flag. // ulNeg = 0; } // // Provide additional padding at the beginning of the // string conversion if needed. // if((ulCount > 1) && (ulCount < 16)) { for(ulCount--; ulCount; ulCount--) { pcBuf[ulPos++] = cFill; } } // // If the value is negative, then place the minus sign // before the number. // if(ulNeg) { // // Place the minus sign in the output buffer. // pcBuf[ulPos++] = '-'; } // // Convert the value into a string. // for(; ulIdx; ulIdx /= ulBase) { pcBuf[ulPos++] = g_pcHex[(ulValue / ulIdx) % ulBase]; } // // Write the string. // UARTwrite(pcBuf, ulPos); // // This command has been handled. // break; } // // Handle the %% command. // case '%': { // // Simply write a single %. // UARTwrite(pcString - 1, 1); // // This command has been handled. // break; } // // Handle all other commands. // default: { // // Indicate an error. // UARTwrite("ERROR", 5); // // This command has been handled. // break; } } } }
//***************************************************************************** // //! A simple UART based get string function, with some line processing. //! //! \param pcBuf points to a buffer for the incoming string from the UART. //! \param ulLen is the length of the buffer for storage of the string, //! including the trailing 0. //! //! This function will receive a string from the UART input and store the //! characters in the buffer pointed to by \e pcBuf. The characters will //! continue to be stored until a termination character is received. The //! termination characters are CR, LF, or ESC. A CRLF pair is treated as a //! single termination character. The termination characters are not stored in //! the string. The string will be terminated with a 0 and the function will //! return. If more characters are received than will fit in the buffer, then //! the extra characters will be ignored and not stored. //! //! Since the string will be null terminated, the user must ensure that the //! buffer is sized to allow for the additional null character. //! //! This function is contained in <tt>utils/uartstdio.c</tt>, with //! <tt>utils/uartstdio.h</tt> containing the API definition for use by //! applications. //! //! \return Returns the count of characters that were stored, not including //! the trailing 0. // //***************************************************************************** int UARTgets(char *pcBuf, unsigned long ulLen) { unsigned long ulCount = 0; char cChar; static char bLastWasCR = 0; // // Check the arguments. // ASSERT(pcBuf != 0); ASSERT(ulLen != 0); ASSERT(g_ulBase != 0); // // Adjust the length back by 1 to leave space for the trailing // null terminator. // ulLen--; // // Process characters until a newline is received. // while(1) { // // Read the next character from the console. // cChar = UARTCharGet(g_ulBase); // // See if the backspace key was pressed. // if(cChar == '\b') { // // If there are any characters already in the buffer, then delete // the last. // if(ulCount) { // // Rub out the previous character. // UARTwrite("\b \b", 3); // // Decrement the number of characters in the buffer. // ulCount--; } // // Skip ahead to read the next character. // continue; } // // If this character is LF and last was CR, then just gobble up the // character because the EOL processing was taken care of with the CR. // if((cChar == '\n') && bLastWasCR) { bLastWasCR = 0; continue; } // // See if a newline or escape character was received. // if((cChar == '\r') || (cChar == '\n') || (cChar == 0x1b)) { // // If the character is a CR, then it may be followed by a LF which // should be paired with the CR. So remember that a CR was // received. // if(cChar == '\r') { bLastWasCR = 1; } // // Stop processing the input and end the line. // break; } // // Process the received character as long as we are not at the end of // the buffer. If the end of the buffer has been reached then all // additional characters are ignored until a newline is received. // if(ulCount < ulLen) { // // Store the character in the caller supplied buffer. // pcBuf[ulCount] = cChar; // // Increment the count of characters received. // ulCount++; // // Reflect the character back to the user. // UARTCharPut(g_ulBase, cChar); } } // // Add a null termination to the string. // pcBuf[ulCount] = 0; // // Send a CRLF pair to the terminal to end the line. // UARTwrite("\r\n", 2); // // Return the count of chars in the buffer, not counting the trailing 0. // return(ulCount); }
void UARTworker(void) { unsigned char c,mode=0,addr=0,instruction=0,EEaddrF=0,EEaddr=0,adcc=0,helpC; initUART(); //write start message (menu) UARTwriteString(msgMenu[0]); UARTwrite('\n'); while(1) { if(RCIF) { RCIF=0; LED2ON; if(!(RCSTA&0b00000110)) { rhead++; rhead&=RINGBUFFMASK; ringbuff[rhead]=RCREG; } LED2OFF; c=UARTread(); UARTwrite(c); //c=UARTcharFromString(c); switch (mode) { case 0: mode=c-48; UARTwriteString(msgMenu[c-48]); if(mode==2)enablePWM(); else if(mode==3)enableDAC(); break; case 1://ADC switch(c) { case 'r'://single read UARTwriteString("\n\nADC value: "); helpC=getADC(adcc); UARTwriteDecimal(helpC); UARTwriteString(msgMenu[1]); break; case '1'://chanell one UARTwriteString("\n\nchannel 1 selected"); adcc=0; UARTwriteString(msgMenu[1]); break; case '2'://chanel two UARTwriteString("\n\nchannel 2 selected"); adcc=1; UARTwriteString(msgMenu[1]); break; case '3'://chanell three UARTwriteString("\n\nchannel 3 selected"); adcc=2; UARTwriteString(msgMenu[1]); break; case 't'://temp UARTwriteString("\n\nTemp sensor selected"); adcc=3; UARTwriteString(msgMenu[1]); break; case 'm'://back to start mode = 0; UARTwriteString(msgMenu[0]); break; default: break; } break; case 2://PWM if(instruction) { switch(instruction) { case 'p': //pwm period = c; setPeriod(UARTcharFromString(c)); UARTwriteString(msgMenu[2]); break; case 'd': setDuty(UARTcharFromString(c)); UARTwriteString(msgMenu[2]); //pwm period =c; break; case 'm': mode =0; //pwm off UARTwriteString(msgMenu[0]); break; default: break; } instruction = 0; } else { instruction = c; //loads the instruction if(instruction == 'p') { UARTwriteString("\n\nEnter the PWM Period: "); } else if(instruction == 'd') { UARTwriteString("\n\nEnter the PWM Duty Cycle: "); } else if(instruction == 'm') //if it's m goes back to the start menu... { mode =0; instruction =0; disablePWM(); UARTwriteString(msgMenu[0]); } } break; case 3://DAC if(instruction) { switch(instruction) { case 'v': //enter woltage setDAC(UARTcharFromString(c)); UARTwriteString(msgMenu[3]); break; case 'm': mode = 0; UARTwriteString(msgMenu[0]); break; default: break; } instruction =0; } else { instruction = c; //loads the instruction if(instruction == 'v') { UARTwriteString(msgDACsetV); } else if(instruction == 'm') //if it's m goes back to the start menu... { mode =0; instruction =0; disableDAC(); UARTwriteString(msgMenu[0]); } } break; case 4://MEM if(instruction) //if instruction has been sent previusly { if(EEaddrF) //instruction was sent previusly, check if address was sent { //address was sent if(instruction == 'w') //if instruction was W-writes recived character to EEProm[ADDR] { EEPROMwrite(EEaddr,UARTcharFromString(c)); UARTwriteString(msgMenu[4]); //write c to eeprom } else if (instruction == 'r') //if instruction was R-reads EEprom[addr] from eeprom { UARTwriteDecimal(EEPROMread(EEaddr)); UARTwriteString(msgMenu[4]); } else if (instruction == 'm') //if instruction was m --returns to start menu... { mode = 0; UARTwriteString(msgMenu[0]); } EEaddrF=0; //clears the addressing flag instruction =0; //clears the istruction flag } else { EEaddrF=1; //sets the address flage EEaddr=UARTcharFromString(c); if(instruction=='w')UARTwriteString(msgEEw); else if(instruction == 'r')UARTwriteString("\n\nHit any key to read from EEPROM.\n\n"); } } else { instruction = c; //loads the instruction if((instruction == 'w')||(instruction == 'r')) { UARTwriteString(msgEEaddr); } else if(instruction == 'm') //if it's m goes back to the start menu... { mode =0; instruction =0; UARTwriteString(msgMenu[0]); } } break; default: mode=0; UARTwriteString(msgMenu[0]); break; } } } }
// printf taken from StellarisWare with additional flag support void Printf(const char *pcString, ...) { unsigned long ulValue, ulIdx, ulCount, ulDecCount; char *pcStr, cNeg, cDec, cFill; const char *pcHex; va_list vaArgP; // Check the arguments. ASSERT(pcString != 0); // Start the varargs processing. va_start(vaArgP, pcString); // Loop while there are more characters in the string. while(*pcString) { // Find the first non-% character, or the end of the string. for(ulIdx = 0; (pcString[ulIdx] != '%') && (pcString[ulIdx] != '\0'); ulIdx++) { } // Write this portion of the string. UARTwrite(pcString, ulIdx); // Skip the portion of the string that was written. pcString += ulIdx; // See if the next character is a %. if(*pcString == '%') { // Skip the %. pcString++; // Set the digit count to zero, and the fill character to space // (i.e. to the defaults). ulCount = 0; ulDecCount = 6; cDec = 0; cFill = ' '; // Presets the template string to lowercase pcHex = g_pcHex_L; again: // Determine how to handle the next character. switch(*pcString++) { // Handle the digit characters. case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { // If this is a zero, and it is the first digit, then the // fill character is a zero instead of a space. if((pcString[-1] == '0') && (ulCount == 0)) { cFill = '0'; } // See if we're after the decimal point if(cDec) { // Update the digit count // Can only print one decimal digit worth of precision ulDecCount = pcString[-1] - '0'; } else { // Update the digit count. ulCount *= 10; ulCount += pcString[-1] - '0'; } // Get the next character. goto again; } // Handle the . character case '.' : { // Now we're looking at precision value cDec = 1; // Get the next character. goto again; } // Handle the %c command. case 'c': { // Get the value from the varargs. ulValue = va_arg(vaArgP, unsigned long); // Print out the character. UARTwrite((char *)&ulValue, 1); // This command has been handled. break; } // Handle the %d and %i commands. case 'd': case 'i': { // Get the value from the varargs. ulValue = va_arg(vaArgP, unsigned long); // If the value is negative, make it positive and indicate // that a minus sign is needed. if((long)ulValue < 0) { // Make the value positive. ulValue = -(long)ulValue; // Indicate that the value is negative. cNeg = 1; } else { // Indicate that the value is positive so that a minus // sign isn't inserted. cNeg = 0; } // Convert the value to ASCII. convert(ulValue, ulCount, pcHex, cNeg, cFill, 10); break; } // Handle the %o command. case 'o': { // Get the value from the varargs. ulValue = va_arg(vaArgP, unsigned long); // If the value is negative, make it positive and indicate // that a minus sign is needed. if((long)ulValue < 0) { // Make the value positive. ulValue = -(long)ulValue; // Indicate that the value is negative. cNeg = 1; } else { // Indicate that the value is positive so that a minus // sign isn't inserted. cNeg = 0; } // Convert the value to ASCII. convert(ulValue, ulCount, pcHex, cNeg, cFill, 8); break; } // Handle the %s command. case 's': { // Get the string pointer from the varargs. pcStr = va_arg(vaArgP, char *); // Determine the length of the string. for(ulIdx = 0; pcStr[ulIdx] != '\0'; ulIdx++) { } // Write the string. UARTwrite(pcStr, ulIdx); // Write any required padding spaces if(ulCount > ulIdx) { ulCount -= ulIdx; while(ulCount--) { UARTwrite(" ", 1); } } // This command has been handled. break; } // Handle the %u command. case 'u': { // Get the value from the varargs. ulValue = va_arg(vaArgP, unsigned long); // Indicate that the value is positive so that a minus sign // isn't inserted. cNeg = 0; // Convert the value to ASCII. convert(ulValue, ulCount, pcHex, cNeg, cFill, 10); break; } // Handle the %x and %X commands. We alias %p to %x. case 'X': // Make the template string uppercase pcHex = g_pcHex_U; case 'x': case 'p': { // Get the value from the varargs. ulValue = va_arg(vaArgP, unsigned long); // Indicate that the value is positive so that a minus sign // isn't inserted. cNeg = 0; // Convert the value to ASCII. convert(ulValue, ulCount, pcHex, cNeg, cFill, 16); break; } // Handle the %f and %F commands. case 'F': // Not different case 'f': { // Declare and read a double double dValue; dValue = va_arg(vaArgP, double); // Check if the value is negative if(dValue < 0) { cNeg = 1; dValue = 0 - dValue; } else { cNeg = 0; } // Check for out of range constants if(isnan(dValue)) { UARTwrite("NaN", 3); } else if(dValue == INFINITY) { if(cNeg) { UARTwrite("-INF", 4); } else { UARTwrite("INF", 3); } } else { // Convert the integer value to ASCII. convert((unsigned long)dValue, ulCount, pcHex, cNeg, cFill, 10); // Remove the original integer value and multiply to move decimal places forward dValue = (dValue - (float)((unsigned long)dValue)); // This loop clobbers ulCount, but it gets reset before we need it again for(ulCount = 0; ulCount < ulDecCount; ulCount++) { dValue *= 10; } UARTwrite(".", 1); convert((unsigned long)dValue, ulDecCount, pcHex, 0, '0', 10); } break; } // %E and %e for scientific notation case 'E': // Make the template string uppercase pcHex = g_pcHex_U; case 'e': { // Declare and read a double double dValue, dExp, dTmp; dValue = va_arg(vaArgP, double); // Check if the value is negative if(dValue < 0) { UARTwrite("-", 1); dValue = 0 - dValue; } // Check for out of range constants if(isnan(dValue)) { UARTwrite("NaN", 3); } else if(dValue == INFINITY) { UARTwrite("INF", 3); } else { // Print the most significant digit dExp = log10(dValue); if(dExp < 0) { // Handler for negative exponents dTmp = dValue / pow(10, (long) dExp - 1); cNeg = 1; dExp = 0 - dExp; } else { dTmp = dValue / pow(10, (long) dExp); cNeg = 0; } UARTwrite(&pcHex[(int)dTmp], 1); UARTwrite(".", 1); // Print ulDecCount following digits while(ulDecCount --> 0) { dTmp -= (long) dTmp; dTmp *= 10; UARTwrite(&pcHex[(int)dTmp], 1); } // Write the exponent UARTwrite(&pcHex[14], 1); convert((unsigned long)dExp, 0, pcHex, cNeg, cFill, 10); } break; } // Handle the %% command. case '%': { // Simply write a single %. UARTwrite(pcString - 1, 1); // This command has been handled. break; } // Handle all other commands. default: { // Indicate an error. UARTwrite("ERROR", 5); // This command has been handled. break; } } } }