Subversion Repositories Projects

Rev

Blame | Last modification | View Log | RSS feed


/****************************************************************/
/*                                                                                                                                                                                                                                                      */
/*                                                                       NG-Video 5,8GHz                                                                                                                */
/*                                                                                                                                                                                                                                                      */
/*                                                      Copyright (C) 2011 - gebad                                                                                      */
/*                                                                                                                                                                                                                                                      */
/*      This code is distributed under the GNU Public License                           */
/*      which can be found at http://www.gnu.org/licenses/gpl.txt               */
/*                                                                                                                                                                                                                                                      */
/****************************************************************/

#include <stdlib.h>
#include <util/delay.h>
#include <avr/pgmspace.h>

#include "config.h"
#include "dogm.h"
#include "tools.h"
#include "messages.h"

#define MAX_POWER                               10
#define getPower(x)                     (int32_t)pgm_read_dword(&powers[x])
const int32_t PROGMEM           powers[MAX_POWER] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};

/* Funktion zur Umwandlung einer vorzeichenbehafteten Integer
         32-Bit "Festkomma-Zahl"(gedachtes Komma in Integer) in einen String
         vereinfacht Variablenübergabe funktion change_value(uint16_t x),
         kein printf, double oder float
         siehe http://www.mikrocontroller.net/articles/Festkommaarithmetik
         len: max 13, Gesamtlänge des Resultats inklusive Vorzeichen und Komma, Rest wird mit ' ' aufgefüllt
         fixedPoint: Position des Kommas im Integer-Wert. Bei Wert in mm und Anzeige in m ist das z.B. 3
         afterPoint: Ziffern nach dem Komma = wieviele der fixedPoint Ziffern angezeigt werden sollen

         Ist nicht genug Platz für die Zahl vorhanden werden nur '*' Zeichen ausgegeben!         
         makefile derzeit somit auch ohne! Minimalistic printf version*/

 
char *my_itoa(int32_t value, uint8_t len, uint8_t fixedPoint, uint8_t afterPoint)
{       int8_t  i;
        int8_t  digits, digitsNeeded;
        uint8_t neg = 0;
        int32_t tmpvalue;
        static char str[13];
       
        // Terminate string
        str[len] = '\0';

        // Reduce precision of value if we're not supposed to show all of the mantissa
        if (fixedPoint > afterPoint) {
                value /= getPower(fixedPoint - afterPoint);
                fixedPoint = afterPoint;
        }

        // Handle negative values
        if (value < 0) {
                value = -value;
                neg = 1;
        }

        // Check how many digits we've got in total and if it fits in our space
        for (digits = 1; digits < MAX_POWER && value >= getPower(digits); digits++);
        if (neg) digits++;                                      // We also need space for the sign
        if (fixedPoint) digits++;               // Plus space for decimal point
       
        digitsNeeded = digits - len;
        if (digitsNeeded > 0) {
                // Not enough space, do something
                if (digitsNeeded == fixedPoint || (digitsNeeded == fixedPoint + 1 && fixedPoint)) {             // +1 = space for decimal point that we can get rid of
                        // If space is just big enough for integer part then simply don't show mantissa BUT ROUND CORRECTLY
                        tmpvalue = (value + 5 * getPower(fixedPoint - 1)) / getPower(fixedPoint);
                        for (digits = 1; digits < MAX_POWER && tmpvalue >= getPower(digits); digits++);
                        // wird durch Rundung Länge Darstellung überschritten?
                        if (digits + neg <= len)
                                value = tmpvalue;
                        else
                                value /= 10;
                        fixedPoint = 0;
                }
                else
                        if (digitsNeeded < fixedPoint) {
                                // We can reduce precision to make it fit (round correctly)
                                value = (value + 5 * getPower(digitsNeeded - 1)) / getPower(digitsNeeded);
                                for (digits = 1; digits < MAX_POWER && value >= getPower(digits); digits++);
                                // wird durch Rundung Länge Darstellung überschritten?
                                if (digits + neg <= len) {
                                        --fixedPoint;
                                        value /= 10;
                                }
                                fixedPoint -= digitsNeeded;
                        }
                        else {
                                // Error, cannot display value! Let's show stars
                                for (i = len - 1; i >= 0; --i) str[i] = '*';
                                return str;    
                }
        }

        for (i = len - 1; i >= neg; --i) {
            if (fixedPoint && i == len - fixedPoint - 1) {
                        // Insert decimal point at the right location
                        str[i] = Msg(MSG_KOMMA)[0];
                        fixedPoint = 0;                                 // Now in integer part
                } else {
                        str[i] = (value % 10) + '0';
                        value /= 10;
                       
                        // Break if we're in integer part and there are only zeros from this point on
                        if (value == 0 && fixedPoint == 0) {
                                --i;
                                break;
                        }
                }
        }
       
        // Insert sign
        if (neg) str[i--] = '-';
       
        // Rest is blank
        for (; i >= 0; --i)
                str[i] = ' ';

        return str;
}


// Trying to avoid floating point maths here. Converts a floating point string to an integer with a smaller unit
// i.e. floatStrToInt("4.5", 2) = 4.5 * 1E2 = 450
int32_t floatStrToInt(const char *s, int32_t power1)
{       char                            *endPtr;
        int32_t                 v = strtol(s, &endPtr, 10);

        if (*endPtr == '.') {
                for (s = endPtr + 1; *s && power1; s++) {
                        v = v * 10 + (*s - '0');
                        --power1;                              
                }
        }
        if (power1) {
                // Table to avoid multiple multiplications
                v = v * getPower(power1);
        }                              
        return v;
}


// Delay helper
void delay_ms100x(uint8_t delay)
{
        for ( uint8_t i=0; i<delay; i++)
                _delay_ms(100);
}


/************************************************************************************/
/*                                                                                                                                                                                                                                                                                                                                      */
/*      Zeitanzeige                                                                                                                                                                                                                                                                                     */
/*                                                                                                                                                                                                                                                                                                                                      */
/************************************************************************************/

uint32_t TimeBase60(char *str, uint32_t time, uint8_t idx)
{       uint32_t tmp = time % 60;

        str[idx]                        = (tmp / 10) + '0';
        str[idx + 1]    = (tmp % 10) + '0';    
        return time / 60;
}

void Displ_TimeMS(int32_t time)
{       char str[7];

        str[6] = '\0';
        if (time < 0) {
                time = abs(time);
                str[0] = '-';
        }
        else
                str[0] = ' ';
        time = TimeBase60(str, time, 4);
        str[3] = ':';
        TimeBase60(str, time, 1);
        lcdPuts(str);
}

void Displ_TimeHMS(uint32_t time)
{       char str[9];

        time /= T2SECDIV; // Zähler aller 500µs
        str[8] = '\0';
        time = TimeBase60(str, time, 6);
        str[5] = ':';
        time = TimeBase60(str, time, 3);
        str[2] = ':';
        TimeBase60(str, time, 0);
        lcdPuts(str);
}