#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <windows.h>

#define SAMPLE_RATE  (1024)
#define CHANNEL_MAX  (3 + 1)
#define PERIOD_CNT   (100)
#define BUFFER_SIZE  (CHANNEL_MAX * sizeof(float) * SAMPLE_RATE * PERIOD_CNT)
uint8_t buffer[BUFFER_SIZE];

int main(void) {
    DWORD actual_len;
    int total_len;
    time_t time_pre, time_now;
    int line;
    char str[100];

    HANDLE hComm = CreateFile(
        "\\\\.\\COM12", /* serial port name */
        GENERIC_READ,   /* only read privilege */ 
        0,              /* share mode */
        NULL,           /* secure attribute */
        OPEN_EXISTING,  /* open current device */
        0,              /* file attribute */
        NULL            /* template file */
    );
    if (hComm == INVALID_HANDLE_VALUE) {
        /* open serial port failed */
        printf("Error: open serial port failed\r\n");
        return -1;
    } else {
        DCB dcb = { 0 };
        dcb.DCBlength = sizeof(dcb);
        if (GetCommState(hComm, &dcb)) {
            dcb.BaudRate = 2 * 1000 * 1000;
            dcb.ByteSize = 8;
            dcb.Parity = NOPARITY;
            dcb.StopBits = ONESTOPBIT;
            if (!SetCommState(hComm, &dcb)) {
                printf("Error: Set serial port parameter failed\r\n");
                return -1;
            }
        } else {
            printf("Error: Get serial port parameter failed\r\n");
            return -1;
        }
        COMMTIMEOUTS timeouts = { 0 };
        timeouts.ReadIntervalTimeout = 10;
        timeouts.ReadTotalTimeoutConstant = 10;
        timeouts.ReadTotalTimeoutMultiplier = 10;
        SetCommTimeouts(hComm, &timeouts);
        printf("Succeed: open serial port\r\n");
    }

    /* sample data */
    PurgeComm(hComm, PURGE_RXCLEAR);
    actual_len = 0;
    total_len = 0;
    time_pre = time(NULL);
    while (1) {
        ReadFile(hComm, buffer + total_len, sizeof(buffer) - total_len, &actual_len, NULL);
        total_len += actual_len;
        if (total_len >= sizeof(buffer)) {
            break;
        }
        time_now = time(NULL);
        if (difftime(time_now, time_pre) >= 1) {
            time_pre = time_now;
            printf("Received %d bytes, %d%%\r\n", total_len, (int)(total_len * 100.0f / BUFFER_SIZE));
        }
    }
    printf("Total Received %d bytes\r\n", total_len);

    /* create and open file */
    HANDLE hFile;
    DWORD bytsWritten;
    hFile = CreateFile(
        "vofa.xls",
        GENERIC_WRITE,
        0,
        NULL,
        CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,
        NULL
    );
    if (hFile == INVALID_HANDLE_VALUE) {
        printf("Error: create file failed, %d\r\n", GetLastError());
        return 1;
    }

    /* parse data and write file */
    time_pre = time(NULL);
    WriteFile(hFile, "idx\tref\tsig\tcnt\n", 16, &bytsWritten, NULL);
    line = 0;
    for (int i = 0; i < sizeof(buffer) - 4; i++) {
        if (buffer[i] == 0 && buffer[i+1] == 0 && buffer[i+2] == 0x80 && buffer[i+3] == 0x7F) {
            if (i > CHANNEL_MAX * sizeof(float)) {
                uint8_t *p = buffer + i;
                char *pstr;
                pstr = itoa(line, str, 10);
                WriteFile(hFile, pstr, strlen(str), &bytsWritten, NULL);
                WriteFile(hFile, "\t", 1, &bytsWritten, NULL);
                for (int j = 0; j < CHANNEL_MAX - 1; j++) {
                    float *val = (float *)p - (CHANNEL_MAX - 1 - j);
                    sprintf(str, "%.*f\t", 0, *val);
                    WriteFile(hFile, str, strlen(str), &bytsWritten, NULL);
                }
                WriteFile(hFile, "\n", 1, &bytsWritten, NULL);
                line++;
            }
        } else {
            continue;
        }
        time_now = time(NULL);
        if (difftime(time_now, time_pre) >= 1) {
            time_pre = time_now;
            printf("Write %d lines, complete %d%%\r\n", line, (int)(line * 100.0f / SAMPLE_RATE / PERIOD_CNT));
        }
    }

    CloseHandle(hFile);
    CloseHandle(hComm);

    return 0;
}