/**
  Generated main.c file from MPLAB Code Configurator

  @Company
    Microchip Technology Inc.

  @File Name
    main.c

  @Summary
    This is the generated main.c using PIC24 / dsPIC33 / PIC32MM MCUs.

  @Description
    This source file provides main entry point for system initialization and application code development.
    Generation Information :
        Product Revision  :  PIC24 / dsPIC33 / PIC32MM MCUs - 1.171.5
        Device            :  PIC24FJ64GA102
    The generated drivers are tested against the following:
        Compiler          :  XC16 v2.10
        MPLAB 	          :  MPLAB X v6.05
*/

/*
    (c) 2020 Microchip Technology Inc. and its subsidiaries. You may use this
    software and any derivatives exclusively with Microchip products.

    THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
    EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
    WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
    PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION
    WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.

    IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
    INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
    WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS
    BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE
    FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN
    ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
    THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.

    MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE
    TERMS.
*/

/**
  Section: Included Files
*/
#include "mcc_generated_files/system.h"
#include "settings.h"
#include "ILI9341.h"
#include "DHT22.h"
#include "ADXL345.h"
#include "i2c.h"
#include "mcc_generated_files/fatfs/ff.h"
#include "mcc_generated_files/sd_spi/sd_spi.h"
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>


/*
                         Main application
 * 
 * 
 */
static int match_log_csv(const char *name, unsigned *idx_out);
static FRESULT ensure_log_dir(void);
static FRESULT find_next_log_index(unsigned *next_idx_out);
static FRESULT create_next_log_file(char out_path[]);
static FRESULT csv_append_line(const char *path, const char *line);

#define LOG_DIR       "log"
#define LOG_DIR_PATH  "/" LOG_DIR

volatile uint8_t temperature[8];
volatile uint8_t humidity[8];
volatile uint16_t hum_col;

volatile uint8_t temp,err;

volatile int16_t xacc,yacc,zacc;

volatile char buffer[7];

const uint8_t madctl[4] = {0xA0,0xC0,0x60,0x10};

//orientacia podla akcelerometra
//otacanie doprava
//0 - vodorovna zakladna (USB konektor vlavo dole)
//1 - zvisla zakladna (USB vlavo hore)
//2 - vodorovna opacna (USB vpravo hore)
//3 - zvisla opacna (USB konektor vpravo dole)


volatile uint8_t orientation = 0;
volatile uint8_t orientation_old;

uint16_t *desc_ptr;
uint8_t *font_ptr;

volatile uint8_t log_buffer[21];

volatile uint8_t log_timer = 0;

int main(void)
{
    static FATFS drive;
    static FIL file;
    static FRESULT sdres;
    char log_path[16];
    
    uint8_t x_pos;
    
    uint8_t i=0;
    // initialize the device
    SYSTEM_Initialize();
    I2C_init();
    ADXL_init();
    ILI9341_init();
    ILI9341_fill(0xFFFF);
    ILI9341_string("M.H.2025",0,50,0xF800,0xFFFF,droidSansMono_24ptBitmaps,droidSansMono_24ptDescriptors);
    __delay_ms(1000);
    ILI9341_fill(0xFFFF);
    ILI9341_string("°C",100,10,0,0xFFFF,droidSansMono_24ptBitmaps,droidSansMono_24ptDescriptors);
    ILI9341_string("%",100,50,0,0xFFFF,droidSansMono_24ptBitmaps,droidSansMono_24ptDescriptors);   
    Nop();
    __delay_ms(1100);
    
    font_ptr = droidSansMono_24ptBitmaps;
    desc_ptr = droidSansMono_24ptDescriptors;
    
    sdres = f_mount(&drive,"",1);
    if(sdres==FR_OK)
    {
        sdres = create_next_log_file(log_path);
    }
    
    if (sdres==FR_OK||sdres==FR_EXIST)
    {
        ILI9341_string("SD",0,110,0,0xFFFF,droidSansMono_8ptBitmaps,droidSansMono_8ptDescriptors);
    }
    else
    {
        ILI9341_string("  ",0,110,0,0xFFFF,droidSansMono_8ptBitmaps,droidSansMono_8ptDescriptors);
    }
    
    while (1)
    {
        
        if(INT_GetValue())
        {
            if(ADXL_xyz(&xacc,&yacc,&zacc)==0)
            {
                if(yacc>=170)
                {
                    orientation = 0;
                    font_ptr = droidSansMono_24ptBitmaps;
                    desc_ptr = droidSansMono_24ptDescriptors;
                    x_pos = 100;
                    
                }
                else if(xacc<=(-170))
                {
                    orientation = 1;
                    font_ptr = droidSansMono_22ptBitmaps;
                    desc_ptr = droidSansMono_22ptDescriptors;
                    x_pos = 90;
                }
                else if(yacc<=(-170))
                {
                    orientation = 2;
                    font_ptr = droidSansMono_24ptBitmaps;
                    desc_ptr = droidSansMono_24ptDescriptors;
                    x_pos = 100;
                }
                else if(xacc>=170)
                {
                    orientation = 3;
                    font_ptr = droidSansMono_22ptBitmaps;
                    desc_ptr = droidSansMono_22ptDescriptors;
                    x_pos = 90;
                }

                if(orientation != orientation_old)
                {
                    ILI9341_madctl(madctl[orientation]);
                    ILI9341_fill(0xFFFF);
                    ILI9341_string("°C",x_pos,10,0,0xFFFF,font_ptr,desc_ptr);
                    ILI9341_string("%",x_pos,50,0,0xFFFF,font_ptr,desc_ptr);  
                    if (sdres==FR_OK)
                    {
                        ILI9341_string("SD",0,110,0,0xFFFF,droidSansMono_8ptBitmaps,droidSansMono_8ptDescriptors);
                    }
                    else
                    {
                        ILI9341_string("  ",0,110,0,0xFFFF,droidSansMono_8ptBitmaps,droidSansMono_8ptDescriptors);
                    }
                }
            }
        }
        

           
        
        read_dht22_data(humidity, temperature);
        ILI9341_string(temperature,0,10,0,0xFFFF,font_ptr,desc_ptr);
        ILI9341_string(humidity,0,50,hum_col,0xFFFF,font_ptr,desc_ptr);
        if(++log_timer>=150)
        {
            strcpy(log_buffer,temperature);
            strcat(log_buffer,"\t");
            strcat(log_buffer,humidity);
            strcat(log_buffer,"\r\n");
            if(sdres==FR_OK||sdres==FR_EXIST)
                sdres = csv_append_line(log_path, log_buffer);
            else
            {
                sdres = f_mount(&drive,"",1);
                if(sdres==FR_OK)
                {
                    sdres = create_next_log_file(log_path);
                }
            }
            
            if (sdres==FR_OK)
            {
                ILI9341_string("SD",0,110,0,0xFFFF,droidSansMono_8ptBitmaps,droidSansMono_8ptDescriptors);
            }
            else
            {
                ILI9341_string("  ",0,110,0,0xFFFF,droidSansMono_8ptBitmaps,droidSansMono_8ptDescriptors);
            }
            
            log_timer = 0;
        }
        
//        int16_to_ascii(xacc,buffer);
//        ILI9341_string(buffer,0,90,0,0xFFFF,droidSansMono_8ptBitmaps,droidSansMono_8ptDescriptors);
//        int16_to_ascii(yacc,buffer);
//        ILI9341_string(buffer,50,90,0,0xFFFF,droidSansMono_8ptBitmaps,droidSansMono_8ptDescriptors);
//        int16_to_ascii(zacc,buffer);
//        ILI9341_string(buffer,100,90,0,0xFFFF,droidSansMono_8ptBitmaps,droidSansMono_8ptDescriptors);
        Nop();
        orientation_old = orientation;
        RCONbits.SWDTEN = 1;
        Nop();
        Nop();
        Sleep();
        Nop();
        Nop();
        RCONbits.SWDTEN = 0;
    }

    return 1;
}



// case-insensitive char compare
static int ch_eq_ci(char a, char b)
{
    return (char)tolower((unsigned char)a) == (char)tolower((unsigned char)b);
}

// Returns 1 if name matches "logNNN.csv" (any case) and outputs NNN in *idx_out, else 0.
static int match_log_csv_ci(const char *name, unsigned *idx_out)
{
    if (!name) return 0;

    // Some FatFs configs may return empty fname; ignore those
    if (name[0] == '\0') return 0;

    // Expect: log + 3 digits + .csv  => 10 chars
    if (strlen(name) != 10) return 0;

    if (!ch_eq_ci(name[0], 'l') || !ch_eq_ci(name[1], 'o') || !ch_eq_ci(name[2], 'g')) return 0;

    if (!isdigit((unsigned char)name[3]) ||
        !isdigit((unsigned char)name[4]) ||
        !isdigit((unsigned char)name[5])) return 0;

    if (name[6] != '.') return 0;
    if (!ch_eq_ci(name[7], 'c') || !ch_eq_ci(name[8], 's') || !ch_eq_ci(name[9], 'v')) return 0;

    unsigned idx = (unsigned)(name[3] - '0') * 100u +
                   (unsigned)(name[4] - '0') * 10u  +
                   (unsigned)(name[5] - '0');

    if (idx == 0) return 0;   // reject 000 if you want
    *idx_out = idx;
    return 1;
}

static FRESULT ensure_log_dir(void)
{
    FILINFO fno;
    FRESULT fr = f_stat(LOG_DIR_PATH, &fno);
    if (fr == FR_OK) return FR_OK;
    if (fr == FR_NO_FILE) return f_mkdir(LOG_DIR_PATH);
    return fr;
}

static FRESULT find_next_log_index(unsigned *next_idx_out)
{
    FFDIR dir;
    FILINFO fno;
    FRESULT fr = f_opendir(&dir, LOG_DIR_PATH);
    if (fr != FR_OK) return fr;

    unsigned max_idx = 0;

    while (1)
    {
        fr = f_readdir(&dir, &fno);
        if (fr != FR_OK) break;
        if (fno.fname[0] == 0) break; // end

        // Use fname; if your config supports altname and you want a fallback, you can add it here
        const char *nm = fno.fname;

        unsigned idx;
        if (match_log_csv_ci(nm, &idx))
        {
            if (idx > max_idx) max_idx = idx;
        }
    }

    f_closedir(&dir);
    if (fr != FR_OK) return fr;

    *next_idx_out = (max_idx == 0) ? 1 : (max_idx + 1);
    if (*next_idx_out > 999) return FR_DENIED;

    return FR_OK;
}

static FRESULT create_next_log_file(char out_path[])
{
    FRESULT fr = ensure_log_dir();
    if (fr != FR_OK) return fr;

    unsigned idx;
    fr = find_next_log_index(&idx);
    if (fr != FR_OK) return fr;

    // Build "/log/logNNN.csv" without snprintf
    out_path[0]  = '/';
    out_path[1]  = 'l';
    out_path[2]  = 'o';
    out_path[3]  = 'g';
    out_path[4]  = '/';
    out_path[5]  = 'l';
    out_path[6]  = 'o';
    out_path[7]  = 'g';
    out_path[8]  = '0' + (idx / 100);
    out_path[9]  = '0' + (idx / 10) % 10;
    out_path[10] = '0' + (idx % 10);
    out_path[11] = '.';
    out_path[12] = 'c';
    out_path[13] = 's';
    out_path[14] = 'v';
    out_path[15] = '\0';

    FIL fp;
    fr = f_open(&fp, out_path, FA_WRITE | FA_CREATE_NEW); // do NOT overwrite
    if (fr != FR_OK) return fr;

    f_close(&fp);
    return FR_OK;
}

static FRESULT csv_append_line(const char *path, const char *line)
{
    if (!path || !line) return FR_INVALID_PARAMETER;

    FIL fp;
    FRESULT fr = f_open(&fp, path, FA_WRITE | FA_OPEN_APPEND);
    if (fr != FR_OK) return fr;

    UINT bw = 0;
    const UINT len = (UINT)strlen(line);

    fr = f_write(&fp, line, len, &bw);
    if (fr == FR_OK && bw != len) fr = FR_DISK_ERR;

    // Force data to be committed (safer; costs time)
    if (fr == FR_OK) fr = f_sync(&fp);

    f_close(&fp);
    return fr;
}
/**
 End of File
*/

