#include "stm32f10x_conf.h"
#include <inttypes.h>
#include <stdarg.h>
#include <math.h>

#define BAUDRATE 9600

void Usart1_Init (void);
void UsartPutC (char c);
char UsartGetC (void);
void putS (char *s);
void printfTiny (char *format, ...);

#define SineAmplitude 30
#define SineFrequency 10

int main(void)
{
    SystemInit ();
    Usart1_Init ();

    for (int i = 0; i < 320; i++) {                                       // Sinus zeichnen
        double s = SineAmplitude * sin ((long double) i / SineFrequency);
        printfTiny ("SINUS %i %i ", i, (int) s);
//        ILI9341_DrawPixel (i, 75 + (int) s ,YELLOW);
//        ILI9341_DrawPixel (i, 175 + (int) s ,GREEN);
    }

    while (1) {}
}

/* ---- xtoa Konstanten (Subtraktion)---- */
static const unsigned long dv [] = {
//  4294967296                                                            // 32 bit unsigned max
    1000000000,                                                           // +0
    100000000,                                                            // +1
    10000000,                                                             // +2
    1000000,                                                              // +3
    100000,                                                               // +4
//  65535                                                                 // 16 bit unsigned max
    10000,                                                                // +5
    1000,                                                                 // +6
    100,                                                                  // +7
    10,                                                                   // +8
    1,                                                                    // +9
};

/* ---- xToASCII ---- */
static void xtoa (unsigned long x, const unsigned long *dp)
{
    char c;
    unsigned long d;

    if (x) {
        while (x < *dp) ++dp;
        do {
            d = *dp++;
            c = '0';
            while (x >= d) ++c, x -= d;
            UsartPutC (c);
        } while (!(d & 1));
    } else {
        UsartPutC ('0');
    }
}

/* ---- printfTiny ---- */
void printfTiny (char *format, ...)
{
    char c;
    int i;
    long n;

    va_list a;
    va_start (a, format);
    while ((c = *format++)) {
        if (c == '%') {
            switch (c = *format++) {
            case 's':                                                     // String
                putS (va_arg (a, char*));
                break;
            case 'c':                                                     // Char
                UsartPutC (va_arg (a, int));
                break;
            case 'i':                                                     // 16 BIT Integer
            case 'u':                                                     // 16 BIT Unsigned
                i = va_arg (a, int);
                if (c == 'i' && i < 0) i = -i, UsartPutC ('-');           // Vorzeichen setzen
                xtoa ((unsigned)i, dv + 5);                               // nur 5 Stellen bearbeiten
                break;
            case 'l':                                                     // 32 BIT Long
            case 'n':                                                     // 32 BIT unsigned long
                n = va_arg (a, long);
                if (c == 'l' &&  n < 0) n = -n, UsartPutC ('-');          // Vorzeichen setzen
                xtoa ((unsigned long)n, dv);
                break;
            case 0:
                return;
            default:
                goto bad_fmt;
            }
        } else {
bad_fmt:
            UsartPutC (c);
        }
    }
    va_end (a);
}

/* ---- simple putchar ---- */
void UsartPutC (char c)
{
    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);          // Transmitter ready/busy ?
    USART_SendData(USART1, c);                                            // Char. Ausgabe -> USART Data Register
}

/* ---- simple getchar ---- */
char UsartGetC (void)
{
    while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);         // Zeichen empfangen ?
    return USART_ReceiveData(USART1);                                     // Zeichen auslesen und zurückgeben
}

/* ---- simple puts ---- */
void putS (char *s)
{
    while (*s)
        UsartPutC (*s++);
}

void Usart1_Init (void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    /* Enable Clock für USART1 an GPIOA, PA9, PA10 als USART1 TX/RX */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1
                           | RCC_APB2Periph_GPIOA
                           | RCC_APB2Periph_AFIO, ENABLE);

    /* PA9 = alternate function push/pull output */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* PA10 = floating input */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* USART konfigurieren */
    USART_InitStructure.USART_BaudRate = BAUDRATE;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

    USART_Init(USART1, &USART_InitStructure);

    /* Enable USART1 */
    USART_Cmd(USART1, ENABLE);
}
