/*
  Routines

  Pros 2007
*/



// Zoek het begin van het volgend woord in de string
char *nxtwrd(char *ptr)
{
    while ((*ptr != 0) && (*ptr > ' ')) {
        ptr++;
    }
    if (*ptr == 0) {
        return (NULL);
    }
    while ((*ptr != 0) && (*ptr < '!')) {
        ptr++;
    }
    if (*ptr == 0) {
        return (NULL);
    } else {
        return (ptr);
    }
}


void delay_ms(unsigned int ms)
{
    for (; ms > 0ms--) {
        _delay_ms(0.998);
    }
}


void delay_us(unsigned int us)
{
    for (; us > 0us--) {
        _delay_us(0.99);
    }
}


// beep aan opgegeven frequentie gedurende een aantal mS
void beep(unsigned int frequnsigned int dur)
{
    unsigned int cntdeltimes;

    sbi(DDRDPD7);
    del = 500000UL / freq;                                      // del = wachttijd tussen 2 flanken in µS
    dur *= 500;                                                 // dur = tijd in uS
    times = dur / del;

    for (cnt = 0cnt < timescnt++) {
        sbi(PORTDPD7);
        delay_us(del);
        cbi(PORTDPD7);
        delay_us(del);
    }
}


// Maak een locaal Fwip-geluid
void fwip(void)
{
    unsigned int del = 300;

    while (del > 8) {
        sbi(PORTDPD7);
        delay_us(del);
        cbi(PORTDPD7);
        delay_us(del);
        del--;
    }
}


// Transformeer een unsigned int (bv. 1234) int naar een ascii-string
// de string wordt voorafgegaan door het opgegeven karakter ( U=1234 )
// en zo nodig van een decimale punt voorzien; dp bepaalt hoeveel cijfers na de punt volgen
void printdec(unsigned int getalchar vchar dp)
{
    unsigned int tmpdeeltal = 10000;
    char *ptrcntzeroflag = 0;

    ptr = txt_buffer;
    *ptr = v;
    ptr++;
    *ptr = '=';
    ptr++;

    for (cnt = 5cnt > 0cnt--) {
        if (dp == cnt) {                                        // dp plaatsen?
            if (zeroflag == 0) {                                // reeds cijfers geplaatst??
                *ptr = '0';                                     // nee, dan eerst een 0
                ptr++;
            }
            *ptr = '.';
            ptr++;
            zeroflag = 1;                                       // na dp alle nullen afdrukken
        }
        tmp = 0;
        while (deeltal > getal) {
            getal -= deeltal;
            tmp++;
        }
        if (tmp > 0) {                                          // als dat geen 0 is
            zeroflag = 1;                                       // worden alle volgende decaden afgedrukt
            *ptr = (unsigned chartmp + '0';                   // ascii-teken verzenden
            ptr++;
        } else if (zeroflag == 1) {                             // Is dit de eerste 0?
            *ptr = '0';                                         // nee, dan een 0 plaatsen
            ptr++;
        }
        deeltal /= 10;                                          // deeltal aanpassen voor volgende decade
    }
}


//  Lees een decimaal getal.
unsigned long get_data(char *ptr)
{
    unsigned long result = 0;

    while (*ptr < '!') {
        ptr++;                                                  // spaties en tabs overslaan
    }

    while ((*ptr > 47) && (*ptr < 58)) {
        result *= 10;
        result += (*ptr - '0');
        ptr++;
    }
    return (result);
}


// String -> float
double get_float(char *ptr)
{
    unsigned long eenheden = 0;
    unsigned long honderdsten = 0;
    double resultdeeltal = 1.0;

    while (*ptr < '0') {
        if (*ptr == 0) {                                        // Einde string?
            return 0.0;                                         // Dan stoppen we
        } else {
            ptr++;                                              // spaties en tabs overslaan
        }
    }

    while ((*ptr > '/') && (*ptr < ':')) {                      // eenheden
        eenheden *= 10;
        eenheden += (*ptr - '0');
        ptr++;
    }
    if (*ptr == '.') {                                          // Komt er nog iets na de dp?
        ptr++;
        while ((*ptr > '/') && (*ptr < ':')) {                  // honderdsten
            honderdsten *= 10;
            deeltal *= 10.0;
            honderdsten += (*ptr - '0');
            ptr++;
        }
    }
    result = ((double) (eenheden)) + (((double) (honderdsten)) / deeltal);
    return (result);
}


// Keyboard-routines

unsigned char check_KB(void)
{
    unsigned char A = PA3;
    unsigned char cnt;

    PORTA |= 0x78;
    DDRD &= 0x97;
    PORTD |= 0x68;                                              // Pull-up weerstanden v KB-input activeren
    delay_us(50);
    Key = 0xFF;
    for (cnt = 0cnt < 4cnt++) {
        cbi(PORTAA);                                          // KB-uitgang laag maken
        delay_us(100);
        if (bit_is_clear(PINDPIND3)) {
            Key = cnt;
        } else if (bit_is_clear(PINDPIND5)) {
            Key = cnt | 4;
        } else if (bit_is_clear(PINDPIND6)) {
            Key = cnt | 8;
        } else if (bit_is_clear(PINBPINB5)) {
            Key = cnt | 12;
        }
        sbi(PORTAA);                                          // KB-uitgang terug hoog maken
        if (Key == 0xFF) {
            A++;                                                // Volgende keyboard-uitgang
            delay_us(100);
        } else {
            Key = KB[Key];
            beep(100020);
            if ((Key != 'u') && (Key != 'd')) {                 // Geen UP- of DOWN-toets?
                key_time = 800;                                 // Default-wachttijd voor UP en DOWN resetten
            }
            return (Key);
        }
    }
    key_time = 800;
    return (0xFF);
}


// Ga na, hoelang hoelang de mode-toets wordt ingedrukt
// Resultaat = aantal seconden * 10
#define KB_IN (_BV(PIND3) | _BV(PIND5) | _BV(PIND6))
unsigned int time_KB(void)
{
    unsigned int kb_time = 0;

    PORTA &= ~(_BV(PA3) | _BV(PA4) | _BV(PA5) | _BV(PA6));
    while (bit_is_clear(PINBPINB5)) {
        kb_time++;
        delay_ms(100);
    }
    PORTA |= 0x78;
    return (kb_time);
}


#define OVERFLOW 88
#define NO_OV    55
char detect_overflow(unsigned char a)
{
    unsigned char b;

    b = (a << 1);                                               // b is nu het dubbele van a, tenzij...
    if (b < a) {                                                // b KLEINER is dan a!
        return (OVERFLOW);                                      // Dat betekent overflow
    } else {
        return (NO_OV);
    }

}


// add_bit() beheert 8 unsigned chars als een 64-bit getal
// Hij schuift bij elke aanroep alle bits 1 plaats naar links op,
// en maakt bit 0 hoog of laag
// Byte[0] is meest-significant
// De routine schuift eerst de bits van Byte[0] naar links. Diens rechtse bit wordt daardoor 0.
// Als het linkse bit van Byte[1] hoog is, moet het rechtse bit van Byte[0] ook hoog gemaakt worden
// Deze bewerking wordt herhaald met Byte[1] ... Byte[6]
// Tot slot wordt het rechtse bit van Byte[7] hoog of laag gemaakt

unsigned char Byte[8];

void add_bitII(unsigned char Bit)
{
    unsigned char cnt;

    for (cnt = 0cnt < 7cnt++) {
        Byte[cnt] = Byte[cnt] << 1;                             // 1 bit opschuiven naar links
        if ((Byte[cnt + 1] & 0x80) == 0x80) {                   // Hoogste bit van lagere byte = 0?
            Byte[cnt] |= 0x01;                                  // Dan bit 0 hoog maken
        }
    }
    Byte[7] = Byte[7] << 1;
    Byte[7] |= Bit;
}