» Advertenties

Zo 5 Februari 2012, 12:47

C code -
  1. //*****************************************************************************
  2. //
  3. // File Name : rprintf.c
  4. // Title : Support for rpintf function
  5. // Author : Smoerijf.be (Orinal by Pascal Stang - edit by smoerijf)
  6. // Target MCU : Atmel AVR Series
  7. //
  8. //*****************************************************************************
  9.  
  10. #include <avr/pgmspace.h>
  11. //#include <string-avr.h>
  12. //#include <stdlib.h>
  13. #include <stdarg.h>
  14. //#include "global.h"
  15. #include "uart.c"
  16. #include "rprintf.h"
  17.  
  18. #ifndef TRUE
  19.   #define TRUE   -1
  20.   #define FALSE   0
  21. #endif
  22.  
  23. #define INF 32766   // maximum field size to print
  24. #define READMEMBYTE(a,char_ptr)   ((a)?(pgm_read_byte(char_ptr)):(*char_ptr))
  25.  
  26. #ifdef RPRINTF_COMPLEX
  27.   static unsigned char buf[128];
  28. #endif
  29.  
  30. // use this to store hex conversion in RAM
  31. //static char HexChars[] = "0123456789ABCDEF";
  32. // use this to store hex conversion in program memory
  33. //static prog_char HexChars[] = "0123456789ABCDEF";
  34. static char __attribute__ ((progmem)) HexChars[] = "0123456789ABCDEF";
  35.  
  36. #define hexchar(x)   pgm_read_byte( HexChars+((x)&0x0f) )
  37. //#define hexchar(x)   ((((x)&0x0F)>9)?((x)+'A'-10):((x)+'0'))
  38.  
  39. // function pointer to single character output routine
  40. static void (*rputchar)(unsigned char c);
  41.  
  42. // *** rprintf initialization ***
  43. // you must call this function once and supply the character output
  44. // routine before using other functions in this library
  45. void rprintfInit(void (*putchar_func)(unsigned char c))
  46. {
  47.   rputchar = putchar_func;
  48. }
  49.  
  50. // *** rprintfChar ***
  51. // send a character/byte to the current output device
  52. void rprintfChar(unsigned char c)
  53. {
  54.   // do LF -> CR/LF translation
  55.   if(c == '\n')
  56.     rputchar('\r');
  57.   // send character
  58.   rputchar(c);
  59. }
  60.  
  61. #ifdef RPRINTF_STR
  62.   // *** rprintfStr ***
  63.   // prints a null-terminated string stored in RAM
  64.   void rprintfStr(char str[])
  65.   {
  66.     // send a string stored in RAM
  67.     // check to make sure we have a good pointer
  68.     if (!str) return;
  69.  
  70.     // print the string until a null-terminator
  71.     while (*str)
  72.       rprintfChar(*str++);
  73.   }
  74. #endif
  75.  
  76. #ifdef RPRINTF_STRLEN
  77.   // *** rprintfStrLen ***
  78.   // prints a section of a string stored in RAM
  79.   // begins printing at position indicated by <start>
  80.   // prints number of characters indicated by <len>
  81.   void rprintfStrLen(char str[], unsigned int start, unsigned int len)
  82.   {
  83.     register int i=0;
  84.  
  85.     // check to make sure we have a good pointer
  86.     if (!str) return;
  87.     // spin through characters up to requested start
  88.     // keep going as long as there's no null
  89.     while((i++<start) && (*str++));
  90.   //   for(i=0; i<start; i++)
  91.   //   {
  92.   //     // keep steping through string as long as there's no null
  93.   //     if(*str) str++;
  94.   //   }
  95.  
  96.     // then print exactly len characters
  97.     for(i=0; i<len; i++)
  98.     {
  99.       // print data out of the string as long as we haven't reached a null yet
  100.       // at the null, start printing spaces
  101.       if(*str)
  102.         rprintfChar(*str++);
  103.       else
  104.         rprintfChar(' ');
  105.     }
  106.  
  107.   }
  108. #endif
  109.  
  110. #ifdef RPRINTF_PROGSTR
  111.   // *** rprintfProgStr ***
  112.   // prints a null-terminated string stored in program ROM
  113.   void rprintfProgStr(const prog_char str[])
  114.   {
  115.     // print a string stored in program memory
  116.     register char c;
  117.  
  118.     // check to make sure we have a good pointer
  119.     if (!str) return;
  120.  
  121.     // print the string until the null-terminator
  122.     while((c = pgm_read_byte(str++)))
  123.       rprintfChar(c);
  124.   }
  125. #endif
  126.  
  127. // *** rprintfCRLF ***
  128. // prints carriage return and line feed
  129. void rprintfCRLF(void)
  130. {
  131.   // print CR/LF
  132.   //rprintfChar('\r');
  133.   // LF -> CR/LF translation built-in to rprintfChar()
  134.   rprintfChar('\n');
  135. }
  136.  
  137. // *** rprintfu04 ***
  138. // prints an unsigned 4-bit number in hex (1 digit)
  139. void rprintfu04(unsigned char data)
  140. {
  141.   // print 4-bit hex value
  142. //   char Character = data&0x0f;
  143. //   if (Character>9)
  144. //     Character+='A'-10;
  145. //   else
  146. //     Character+='0';
  147.   rprintfChar(hexchar(data));
  148. }
  149.  
  150. #ifdef RPRINTF_U
  151.   // *** rprintfu08 ***
  152.   // prints an unsigned 8-bit number in hex (2 digits)
  153.   void rprintfu08(unsigned char data)
  154.   {
  155.     // print 8-bit hex value
  156.     rprintfu04(data>>4);
  157.     rprintfu04(data);
  158.   }
  159.  
  160.   // *** rprintfu16 ***
  161.   // prints an unsigned 16-bit number in hex (4 digits)
  162.   void rprintfu16(unsigned short data)
  163.   {
  164.     // print 16-bit hex value
  165.     rprintfu08(data>>8);
  166.     rprintfu08(data);
  167.   }
  168.  
  169.   // *** rprintfu32 ***
  170.   // prints an unsigned 32-bit number in hex (8 digits)
  171.   void rprintfu32(unsigned long data)
  172.   {
  173.     // print 32-bit hex value
  174.     rprintfu16(data>>16);
  175.     rprintfu16(data);
  176.   }
  177. #endif
  178.  
  179. #ifdef RPRINTF_NUM
  180.   // *** rprintfNum ***
  181.   // special printf for numbers only
  182.   // see formatting information below
  183.   //   Print the number "n" in the given "base"
  184.   //   using exactly "numDigits"
  185.   //   print +/- if signed flag "isSigned" is TRUE
  186.   //   use the character specified in "padchar" to pad extra characters
  187.   //
  188.   //   Examples:
  189.   //   uartPrintfNum(10, 6, TRUE, ' ', 1234); --> " +1234"
  190.   //   uartPrintfNum(10, 6, FALSE, '0', 1234); --> "001234"
  191.   //   uartPrintfNum(16, 6, FALSE, '.', 0x5AA5); --> "..5AA5"
  192.   void rprintfNum(char base, char numDigits, char isSigned, char padchar, long n)
  193.   {
  194.     // define a global HexChars or use line below
  195.     //static char HexChars[16] = "0123456789ABCDEF";
  196.     char *p, buf[32];
  197.     unsigned long x;
  198.     unsigned char count;
  199.  
  200.     // prepare negative number
  201.     if( isSigned && (n < 0) )
  202.     {
  203.       x = -n;
  204.     }
  205.     else
  206.     {
  207.       x = n;
  208.     }
  209.  
  210.     // setup little string buffer
  211.     count = (numDigits-1)-(isSigned?1:0);
  212.     p = buf + sizeof (buf);
  213.     *--p = '\0';
  214.  
  215.     // force calculation of first digit
  216.     // (to prevent zero from not printing at all!!!)
  217.     *--p = hexchar(x%base); x /= base;
  218.     // calculate remaining digits
  219.     while(count--)
  220.     {
  221.       if(x != 0)
  222.       {
  223.         // calculate next digit
  224.         *--p = hexchar(x%base); x /= base;
  225.       }
  226.       else
  227.       {
  228.         // no more digits left, pad out to desired length
  229.         *--p = padchar;
  230.       }
  231.     }
  232.  
  233.     // apply signed notation if requested
  234.     if( isSigned )
  235.     {
  236.       if(n < 0)
  237.       {
  238.         *--p = '-';
  239.       }
  240.       else if(n > 0)
  241.       {
  242.         *--p = '+';
  243.       }
  244.       else
  245.       {
  246.         *--p = ' ';
  247.       }
  248.     }
  249.  
  250.     // print the string right-justified
  251.     count = numDigits;
  252.     while(count--)
  253.     {
  254.       rprintfChar(*p++);
  255.     }
  256.   }
  257. #endif
  258.  
  259. #ifdef RPRINTF_FLOAT
  260. // *** rprintfFloat ***
  261. // floating-point print
  262. void rprintfFloat(char numDigits, double x)
  263. {
  264.   unsigned char firstplace = FALSE;
  265.   unsigned char negative;
  266.   unsigned char i, digit;
  267.   double place = 1.0;
  268.  
  269.   // save sign
  270.   negative = (x<0);
  271.   // convert to absolute value
  272.   x = (x>0)?(x):(-x);
  273.  
  274.   // find starting digit place
  275.   for(i=0; i<15; i++)
  276.   {
  277.     if((x/place) < 10.0)
  278.       break;
  279.     else
  280.       place *= 10.0;
  281.   }
  282.   // print polarity character
  283.   if(negative)
  284.     rprintfChar('-');
  285.   else
  286.     rprintfChar('+');
  287.  
  288.   // print digits
  289.   for(i=0; i<numDigits; i++)
  290.   {
  291.     digit = (x/place);
  292.  
  293.     if(digit | firstplace | (place == 1.0))
  294.     {
  295.       firstplace = TRUE;
  296.       rprintfChar(digit+0x30);
  297.     }
  298.     else
  299.       rprintfChar(' ');
  300.  
  301.     if(place == 1.0)
  302.     {
  303.       rprintfChar('.');
  304.     }
  305.  
  306.     x -= (digit*place);
  307.     place /= 10.0;
  308.   }
  309. }
  310. #endif
  311.  
  312. #ifdef RPRINTF_SIMPLE
  313. // *** rprintf1RamRom ***
  314. // called by rprintf() - does a simple printf (supports %d, %x, %c)
  315. // Supports:
  316. // %d - decimal
  317. // %x - hex
  318. // %c - character
  319. int rprintf1RamRom(unsigned char stringInRom, const char *format, ...)
  320. {
  321.   // simple printf routine
  322.   // define a global HexChars or use line below
  323.   //static char HexChars[16] = "0123456789ABCDEF";
  324.   char format_flag;
  325.   unsigned int u_val, div_val, base;
  326.   va_list ap;
  327.  
  328.   va_start(ap, format);
  329.   for (;;)
  330.   {
  331.     while ((format_flag = READMEMBYTE(stringInRom,format++) ) != '%')
  332.     {   // Until '%' or '\0'
  333.       if (!format_flag)
  334.       {
  335.         va_end(ap);
  336.         return(0);
  337.       }
  338.       rprintfChar(format_flag);
  339.     }
  340.  
  341.     switch (format_flag = READMEMBYTE(stringInRom,format++) )
  342.     {
  343.       case 'c': format_flag = va_arg(ap,int);
  344.       default: rprintfChar(format_flag); continue;
  345.       case 'd': base = 10; div_val = 10000; goto CONVERSION_LOOP;
  346. //       case 'x': base = 16; div_val = 0x10;
  347.       case 'x': base = 16; div_val = 0x1000;
  348.  
  349.       CONVERSION_LOOP:
  350.       u_val = va_arg(ap,int);
  351.       if (format_flag == 'd')
  352.       {
  353.         if (((int)u_val) < 0)
  354.         {
  355.           u_val = - u_val;
  356.           rprintfChar('-');
  357.         }
  358.         while (div_val > 1 && div_val > u_val) div_val /= 10;
  359.       }
  360.       do
  361.       {
  362.         //rprintfChar(pgm_read_byte(HexChars+(u_val/div_val)));
  363.         rprintfu04(u_val/div_val);
  364.         u_val %= div_val;
  365.         div_val /= base;
  366.       } while (div_val);
  367.     }
  368.   }
  369.   va_end(ap);
  370. }
  371. #endif
  372.  
  373.  
  374. #ifdef RPRINTF_COMPLEX
  375. // *** rprintf2RamRom ***
  376. // called by rprintf() - does a more powerful printf (supports %d, %u, %o, %x, %c, %s)
  377. // Supports:
  378. // %d - decimal
  379. // %u - unsigned decimal
  380. // %o - octal
  381. // %x - hex
  382. // %c - character
  383. // %s - strings
  384. // and the width,precision,padding modifiers
  385. // **this printf does not support floating point numbers
  386. int rprintf2RamRom(unsigned char stringInRom, const char *sfmt, ...)
  387. {
  388.   register unsigned char *f, *bp;
  389.   register long l;
  390.   register unsigned long u;
  391.   register int i;
  392.   register int fmt;
  393.   register unsigned char pad = ' ';
  394.   int flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
  395.   int sign = 0;
  396.  
  397.   va_list ap;
  398.   va_start(ap, sfmt);
  399.  
  400.   f = (unsigned char *) sfmt;
  401.  
  402.   for (; READMEMBYTE(stringInRom,f); f++)
  403.   {
  404.     if (READMEMBYTE(stringInRom,f) != '%')
  405.     {   // not a format character
  406.       // then just output the char
  407.       rprintfChar(READMEMBYTE(stringInRom,f));
  408.     }
  409.     else
  410.     {
  411.       f++;             // if we have a "%" then skip it
  412.       if (READMEMBYTE(stringInRom,f) == '-')
  413.       {
  414.         flush_left = 1;   // minus: flush left
  415.         f++;
  416.       }
  417. if (READMEMBYTE(stringInRom,f) == '0'
  418.         || READMEMBYTE(stringInRom,f) == '.')
  419.         {
  420.           // padding with 0 rather than blank
  421.           pad = '0';
  422.           f++;
  423. }
  424. if (READMEMBYTE(stringInRom,f) == '*')
  425.         {   // field width
  426.           f_width = va_arg(ap, int);
  427.           f++;
  428. }
  429. else if (Isdigit(READMEMBYTE(stringInRom,f)))
  430.         {
  431.           f_width = atoiRamRom(stringInRom, (char *) f);
  432.           while (Isdigit(READMEMBYTE(stringInRom,f)))
  433.             f++; // skip the digits
  434. }
  435. if (READMEMBYTE(stringInRom,f) == '.')
  436.         {   // precision
  437.           f++;
  438.           if (READMEMBYTE(stringInRom,f) == '*')
  439.           {
  440.             prec = va_arg(ap, int);
  441.             f++;
  442.           }
  443.           else if (Isdigit(READMEMBYTE(stringInRom,f)))
  444.           {
  445.             prec = atoiRamRom(stringInRom, (char *) f);
  446.             while (Isdigit(READMEMBYTE(stringInRom,f)))
  447.               f++; // skip the digits
  448.           }
  449.         }
  450. if (READMEMBYTE(stringInRom,f) == '#')
  451.         {   // alternate form
  452.           hash = 1;
  453.           f++;
  454. }
  455. if (READMEMBYTE(stringInRom,f) == 'l')
  456.         {   // long format
  457.           do_long = 1;
  458.           f++;
  459. }
  460.  
  461.         fmt = READMEMBYTE(stringInRom,f);
  462.         bp = buf;
  463.         switch (fmt) {     // do the formatting
  464.         case 'd':       // 'd' signed decimal
  465.           if (do_long)
  466.             l = va_arg(ap, long);
  467.           else
  468.             l = (long) (va_arg(ap, int));
  469.           if (l < 0)
  470.           {
  471.             sign = 1;
  472.             l = -l;
  473.           }
  474.           do   {
  475.             *bp++ = l % 10 + '0';
  476.           } while ((l /= 10) > 0);
  477.           if (sign)
  478.             *bp++ = '-';
  479.           f_width = f_width - (bp - buf);
  480.           if (!flush_left)
  481.             while (f_width-- > 0)
  482.               rprintfChar(pad);
  483.           for (bp--; bp >= buf; bp--)
  484.             rprintfChar(*bp);
  485.           if (flush_left)
  486.             while (f_width-- > 0)
  487.               rprintfChar(' ');
  488.           break;
  489. case 'o':       // 'o' octal number
  490. case 'x':       // 'x' hex number
  491. case 'u':       // 'u' unsigned decimal
  492.           if (do_long)
  493.             u = va_arg(ap, unsigned long);
  494.           else
  495.             u = (unsigned long) (va_arg(ap, unsigned));
  496.           if (fmt == 'u')
  497.           {   // unsigned decimal
  498.             do {
  499.               *bp++ = u % 10 + '0';
  500.             } while ((u /= 10) > 0);
  501.           }
  502.           else if (fmt == 'o')
  503.           { // octal
  504.             do {
  505.               *bp++ = u % 8 + '0';
  506.             } while ((u /= 8) > 0);
  507.             if (hash)
  508.               *bp++ = '0';
  509.           }
  510.           else if (fmt == 'x')
  511.           {   // hex
  512.             do {
  513.               i = u % 16;
  514.               if (i < 10)
  515.                 *bp++ = i + '0';
  516.               else
  517.                 *bp++ = i - 10 + 'a';
  518.             } while ((u /= 16) > 0);
  519.             if (hash)
  520.             {
  521.               *bp++ = 'x';
  522.               *bp++ = '0';
  523.             }
  524.           }
  525.           i = f_width - (bp - buf);
  526.           if (!flush_left)
  527.             while (i-- > 0)
  528.               rprintfChar(pad);
  529.           for (bp--; bp >= buf; bp--)
  530.             rprintfChar((int) (*bp));
  531.           if (flush_left)
  532.             while (i-- > 0)
  533.               rprintfChar(' ');
  534.           break;
  535. case 'c':       // 'c' character
  536.           i = va_arg(ap, int);
  537.           rprintfChar((int) (i));
  538.           break;
  539. case 's':       // 's' string
  540.           bp = va_arg(ap, unsigned char *);
  541.           if (!bp)
  542.             bp = (unsigned char *) "(nil)";
  543.           f_width = f_width - strlen((char *) bp);
  544.           if (!flush_left)
  545.             while (f_width-- > 0)
  546.               rprintfChar(pad);
  547.           for (i = 0; *bp && i < prec; i++)
  548.           {
  549.             rprintfChar(*bp);
  550.             bp++;
  551.           }
  552.           if (flush_left)
  553.             while (f_width-- > 0)
  554.               rprintfChar(' ');
  555.           break;
  556. case '%':       // '%' character
  557.           rprintfChar('%');
  558.           break;
  559.       }
  560.       flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
  561.       sign = 0;
  562.       pad = ' ';
  563.     }
  564.   }
  565.  
  566.   va_end(ap);
  567.   return 0;
  568. }
  569.  
  570. unsigned char Isdigit(char c)
  571. {
  572.   if((c >= 0x30) && (c <= 0x39))
  573.     return TRUE;
  574.   else
  575.     return FALSE;
  576. }
  577.  
  578. int atoiRamRom(unsigned char stringInRom, char *str)
  579. {
  580.   int num = 0;;
  581.  
  582.   while(Isdigit(READMEMBYTE(stringInRom,str)))
  583.   {
  584.     num *= 10;
  585.     num += ((READMEMBYTE(stringInRom,str++)) - 0x30);
  586.   }
  587.   return num;
  588. }
  589. #endif
  590.  
  591.  
  592. char rprint1(const char *format){
  593.   char c;
  594.   cbi(UCR, RXCIE);
  595.   while((c = READMEMBYTE(1, format++))){
  596.     uartSendByte(c);
  597.   }
  598.   c = 0;
  599.   while ( !(UCR & (1<<RXC)) )
  600.   c = UDR;
  601.   sbi(UCR, RXCIE);
  602.   return c;
  603. }
Laatste wijziging: Vr 10 April 2009, 13:03