/* This file is part of MANTIS OS, Operating System for Nymph. See http://mantis.cs.colorado.edu/ Copyright (C) 2003 University of Colorado, Boulder */ /** * @File: weatherboard_test.c * @Brief: A file to test the weather-sensor board. * @Author: Charles Gruenwald III * @Date: 12-03-2004 */ #include "mos.h" #include "command_daemon.h" #include "printf.h" #include "com.h" #include "led.h" #include "dev.h" #include "avr-i2c.h" #include "avr-eeprom.h" //devines the DEV_AVR_EEPROM_SEEK ioctl #include "avr-adc.h" #include "adc.h" #define SCRATCH 16 #define CBUFSZ 256 //************************************************************************ // Declarations static char cbuf[ CBUFSZ ]; //generic buffer //static uint8_t cbuf[ CBUFSZ ]; //generic buffer static uint8_t fieldwidth; // used in prinff, sprintff static char padchar; // ditto static uint8_t buffsize; // ditto static comBuf *recvd; // used for grabbing input from operator int sprintff( char *, const char *, ...); void prinff( const char *, ... ); size_t strlen(); char * strcat(); static char * norecurse_16(char *buf, uint16_t input, uint8_t radix); static char * norecurse_long(char *buf, long input); static char * padbuf(); uint8_t prompt_uint8(); double prompt_double(); int prompt_int(); long prompt_s_long(); uint8_t prompt_string(); //************************************************************************ /* Addition to the mos/share/command_daemon * which has now: * char prompt_char(char *string) * uint16_t prompt_long(char *string) * uint32_t prompt_longlong(char *string) * uint8_t prompt_uint8(char *string) * * Add Here * prompt_int * prompt_s_long * prompt_string * prompt_double */ double prompt_double(char *string) { uint32_t wholenum=0; double fval=0; uint8_t i=0,ix,minus=0; char c; printf("%s",string); recvd = com_recv(IFACE_STDIO); if (recvd->data[0]=='-') { minus = 1; i = 1; } for (; i < recvd->size; i++) { c = recvd->data[i]; if (c >= '0' && c <= '9') { wholenum *= 10; wholenum += c - '0'; } else if ( c == '.' ) { ++i; break; } } for(ix=recvd->size-1; i < recvd->size; i++, ix--) { c = recvd->data[ix]; if (c >= '0' && c <= '9') { fval += c - '0'; fval /= 10; } } fval += wholenum; com_free_buf (recvd); if (minus) return -fval; return fval; } int prompt_int(char *string) { int ival=0; uint8_t i=0,minus=0; char c; printf("%s",string); recvd = com_recv(IFACE_STDIO); if (recvd->data[0]=='-') { minus = 1; i = 1; } for (; i < recvd->size; i++) { c = recvd->data[i]; if (c >= '0' && c <= '9') { ival *= 10; ival += c - '0'; } else break; } com_free_buf (recvd); if (minus) return -ival; return ival; } // signed long value long prompt_s_long(char *string) { long lval=0; uint8_t i=0,minus=0; char c; printf("%s",string); recvd = com_recv(IFACE_STDIO); if (recvd->data[0]=='-') { minus = 1; i = 1; } for (; i < recvd->size; i++) { c = recvd->data[i]; if (c >= '0' && c <= '9') { lval *= 10; lval += c - '0'; } else break; } com_free_buf (recvd); if (minus) return -lval; return lval; } uint8_t prompt_string(char *buf, char *string) { uint8_t i=0; printf("%s",string); recvd = com_recv(IFACE_STDIO); for(i=0; isize; i++) { *buf++=recvd->data[i]; } *buf=0; com_free_buf (recvd); return i; } /*---------------------------------------- * Stupid function to just print via putchars * a floating point value...ie substitute for printf in mos * With 23-bit mantissa, 8-bit exponent, expect at most 7 digits accuracy *----------------------------------------*/ void prinff(const char *fmt, ...) { va_list arg; uint8_t remainder; uint8_t precision; uint8_t scratch[SCRATCH]; uint32_t u_val; char *cp, ch; char *buf, fpchar; char *fp=fmt; double fval; // Check for actual format if(fmt == NULL) return; va_start(arg, fmt); buf = &cbuf[0]; // LOOK FOR THE FORMAT STUFF while( *fp ) { if(*fp != '%') { // If not conversion specifier pass it on *buf++ = *fp++; continue; } else ++fp; // Pad with zeros or spaces? // Don't allow padding char to be '0' if (*fp == '0') { fp++; } padchar = ' '; // Look for field width fieldwidth = 0; precision = 2; // Default precision while(*fp >= '0' && *fp <= '9') { fieldwidth = fieldwidth * 10 + *fp - '0'; fp++; } fpchar = *fp++; // char has hopefully '.', 'i', etc. // check the conversion type switch (fpchar ) { case '.': // set '.x' precision only for double/double fpchar = *fp++; precision=fpchar - '0'; // only .0 - .9 ++fp; // move past the 'f' and drop in case 'f': fval = (double) va_arg(arg,double); // Note double...for everything? buffsize = 0; if( fieldwidth && (fieldwidth < (precision+2)) ) { precision = fieldwidth-2 > 1? fieldwidth-2 : 0; printf("\n fieldwidth Error..."); } if( fieldwidth ) fieldwidth-= precision; // Handle the integer portion to the char buffer cp = &scratch[SCRATCH-1]; *cp-- = 0; u_val = (uint32_t) (fval<0? -fval : fval); do { ch = u_val % 10 + '0'; *cp-- = ch; u_val /= 10; ++buffsize; } while (u_val); if( fval<0 ) { *cp--= '-'; fval = -fval; buffsize++; } // Calculate amount we still need to pad. if(fieldwidth && fieldwidth > buffsize) { fieldwidth -= buffsize; while(--fieldwidth ) { *cp-- = padchar; buffsize++; } } if( fval<0 ) { *cp--= '-'; fval = -fval; } else *cp-- = padchar; ++cp; buffsize++; // copy scratch back to buffer, including null while( *cp ) { *buf++ = *cp++; ++buffsize; } // Handle the fractional portion, right justified fval = fval - (uint32_t)fval; if( precision ) { *buf++ = '.'; do { fval *= 10; remainder = (uint8_t) fval; *buf++ = remainder + '0'; fval -= remainder; } while (--precision); } break; } } *buf=0; printf("\nConverted buffer: '%s'",cbuf); } //************************************************************************ /*---------------------------------------- * simplified sprintf for %f only...for now * With 23-bit mantissa, 8-bit exponent, expect at most 7 digits accuracy *----------------------------------------*/ int sprintff(char *buf, const char *format, ...) { va_list arg; char *fp = format; char *bufbegin=buf; uint8_t scratch[SCRATCH]; uint32_t u_val=0; uint16_t i_val=0; char *cp; uint8_t precision=1; // default doubleing precsion = x.0 double fval; char ch, fpchar; // Check for actual format if(format == NULL) return -1; va_start(arg, format); while( *fp ) { if(*fp != '%') { // If not conversion specifier pass it on *buf++ = *fp++; continue; } else ++fp; // TODO the padding options are not implemented for non-numeric stuff // Pad with zeros or spaces? if (*fp == '0') { padchar = '0'; fp++; } else padchar = ' '; // Look for field width fieldwidth = 0; precision = 2; // Default precision while(*fp >= '0' && *fp <= '9') { fieldwidth = fieldwidth * 10 + *fp - '0'; fp++; } fpchar = *fp++; // char has hopefully '.', 'i', etc. // check the conversion type switch (fpchar ) { case '.': // set '.x' precision only for double/double fpchar = *fp++; precision=fpchar - '0'; // only .0 - .9 ++fp; // move past the 'f' and drop in case 'f': fval = (double) va_arg(arg,double); // Note double...for everything? buffsize = 0; // Don't allow padding char to be '0' padchar = ' '; if( fieldwidth && (fieldwidth < (precision+2)) ) { precision = fieldwidth-2 > 1? fieldwidth-2 : 0; printf("\n fieldwidth Error..."); } if( fieldwidth ) fieldwidth-= precision; // Handle the integer portion to the char buffer cp = &scratch[SCRATCH-1]; *cp-- = 0; u_val = (uint32_t) (fval<0? -fval : fval); do { ch = u_val % 10 + '0'; *cp-- = ch; u_val /= 10; ++buffsize; } while (u_val); if( fval<0 ) { *cp--= '-'; fval = -fval; buffsize++; } // Calculate amount we still need to pad. if(fieldwidth && fieldwidth > buffsize) { fieldwidth -= buffsize; while(--fieldwidth ) { *cp-- = padchar; buffsize++; } } if( fval<0 ) { *cp--= '-'; fval = -fval; } else *cp-- = padchar; ++cp; buffsize++; // copy scratch back to buffer, including null while( *cp ) { *buf++ = *cp++; ++buffsize; } // Handle the fractional portion, right justified fval = fval - (long)fval; if( precision ) { *buf++ = '.'; do { fval *= 10; i_val = (int) fval; *buf++ = i_val + '0'; fval = fval - i_val; } while (--precision); } *buf=0; break; case 's': cp = (char * ) va_arg(arg,char *); strcat(buf, cp); buf += strlen(buf); *buf=0; break; case 'i': case 'd': { int inum; // Don't allow padding char to be '0' padchar = ' '; inum = va_arg(arg, int); buf = norecurse_long(buf, (long) inum); break; } case 'u': { uint16_t num16; num16 = va_arg(arg, uint16_t); buf = norecurse_16(buf, num16, 10); break; } case 'l': { long lnum; // Don't allow padding char to be '0' padchar = ' '; lnum = va_arg(arg, long); buf = norecurse_long(buf, lnum); break; } case 'c': { uint16_t num8 = 0; num8 = (uint8_t)va_arg(arg, uint16_t); *buf++ = (char) num8; break; } case 'C': { uint16_t num8 = 0; num8 = (uint8_t) va_arg(arg, uint16_t); buf = norecurse_16(buf,(uint16_t)num8, 10); break; } case 'x': *buf++ = '0'; *buf++ = 'x'; case 'h': { uint16_t num16; num16 = va_arg(arg, uint16_t); buf = norecurse_16(buf, num16, 16); break; } case 'o': { uint16_t num16; num16 = va_arg(arg, uint16_t); buf = norecurse_16(buf, num16, 8); break; } case '%': { *buf++ = '%'; break; } case 'b': { uint16_t num16; num16 = va_arg(arg, uint16_t); buf = norecurse_16( buf, num16, 2); break; } default: *buf++ = '?'; *buf++ = '?'; *buf++ = '?'; break; } } va_end(arg); *buf=0; // make sure null terminated // return(1); return(strlen(bufbegin)); } //---------------------------------------- static char paddingbuf[ 32 ]; //generic buffer for /* Convert a signed integer/long number to base10 and put into buffer * 32-bit version */ static char * norecurse_long(char *buf, long input) { uint8_t remainder, minus=0; buffsize=0; if( input <0 ) { minus=1; input = -input; } if( input == 0 ) { paddingbuf[buffsize++] = '0'; } else { remainder=input%10; while(input >= 10) { paddingbuf[buffsize++] = remainder + '0'; input /= 10; remainder = input%10; } //last place if(remainder > 0) paddingbuf[buffsize++] = remainder + '0'; } // Don't allow padding char to be '0' padchar = ' '; if( minus ) { paddingbuf[buffsize++] = '-'; } buf = padbuf( buf ); return( buf ); } //---------------------------------------- /* Convert a number to a certain radix and put into buffer * 16-bit version */ static char * norecurse_16(char *buf, uint16_t input, uint8_t radix) { uint8_t remainder = input % radix; buffsize = 0; if(input == 0) paddingbuf[buffsize++] = '0'; while(input >= radix) { if(remainder <= 9) paddingbuf[buffsize++] = remainder + '0'; else paddingbuf[buffsize++] = remainder - 10 + 'A'; input /= radix; remainder = input % radix; } //last place if(remainder > 0) { if(remainder <= 9) paddingbuf[buffsize++] = remainder + '0'; else paddingbuf[buffsize++] = remainder - 10 + 'A'; } buf = padbuf( buf ); return( buf ); } //-------------------------------------------------------------------- // Generic use to pad the buffer with the appropriate char setup above //-------------------------------------------------------------------- static char * padbuf( char *buf ) { // Calculate amount we still need to pad. We never truncate a result. if(fieldwidth > buffsize) fieldwidth -= buffsize; else fieldwidth = 0; while(fieldwidth--) { *buf++ = padchar; } // copy padding buffer back to output buffer while(buffsize > 0) { *buf++ = paddingbuf[--buffsize]; } return( buf ); }