#include "DEV_Config.h"
#include "LCD_3IN49.h"
#include "qspi_pio.h"
#include "QMI8658.h"
#include "PCF85063A.h"
#include "Touch.h"
#include "image.h"
#include "GUI_Paint.h"
#include "psram_tool.h"
#include "rp_pico_alloc.h"
#include "pico/multicore.h"  

int flag=0;
uint8_t i2c_lock = 0;
#define I2C_LOCK() i2c_lock = 1
#define I2C_UNLOCK() i2c_lock = 0

void Touch_INT_callback(uint gpio, uint32_t events);
void core1_entry();

int main() 
{
    if(DEV_Module_Init()!=0){
        return -1;
    }

    /*PWR*/
    multicore_launch_core1(core1_entry);

    /*QSPI PIO Init*/
    QSPI_GPIO_Init(qspi);
    QSPI_PIO_Init(qspi);
    QSPI_4Wrie_Mode(&qspi);
    
    /*LCD Init*/
    printf("3.49inch LCD demo...\r\n");
    LCD_3IN49_Init();

    DEV_SET_PWM(100);

    UDOUBLE Imagesize = LCD_3IN49_HEIGHT*LCD_3IN49_WIDTH*2;
    UWORD *BlackImage;
    if((BlackImage = (UWORD *)malloc(Imagesize)) == NULL) {
        printf("Failed to apply for black memory...\r\n");
        exit(0);
    }

    /*1.Create a new image cache named IMAGE_RGB and fill it with white*/    
    Paint_NewImage((UBYTE *)BlackImage, LCD_3IN49.WIDTH, LCD_3IN49.HEIGHT, 0, WHITE);
    Paint_SetScale(65);
    Paint_SetRotate(ROTATE_0);
    Paint_Clear(WHITE);
    LCD_3IN49_Display(BlackImage);
    DEV_Delay_ms(100);

    /* GUI */
    printf("drawing...\r\n");
    /*2.Drawing on the image*/
#if 1
    Paint_DrawPoint(10, 20, BLACK, DOT_PIXEL_2X2, DOT_FILL_RIGHTUP);
    Paint_DrawPoint(10, 25, BLACK, DOT_PIXEL_3X3, DOT_FILL_RIGHTUP); 
    Paint_DrawPoint(10, 30, BLACK, DOT_PIXEL_4X4, DOT_FILL_RIGHTUP); 
    Paint_DrawPoint(10, 35, BLACK, DOT_PIXEL_5X5, DOT_FILL_RIGHTUP); 
    Paint_DrawPoint(10, 42, BLACK, DOT_PIXEL_6X6, DOT_FILL_RIGHTUP);

    Paint_DrawLine(24, 20, 55, 50, MAGENTA, DOT_PIXEL_2X2, LINE_STYLE_SOLID);
    Paint_DrawLine(24, 50, 55, 20, MAGENTA, DOT_PIXEL_2X2, LINE_STYLE_SOLID);  

    Paint_DrawLine(94, 34, 125, 35, CYAN, DOT_PIXEL_1X1, LINE_STYLE_DOTTED); 
    Paint_DrawLine(110, 20, 110, 50, CYAN, DOT_PIXEL_1X1, LINE_STYLE_DOTTED);  

    Paint_DrawRectangle(24, 20, 55, 50, RED, DOT_PIXEL_2X2, DRAW_FILL_EMPTY);   
    Paint_DrawRectangle(60, 20, 90, 50, BLUE, DOT_PIXEL_2X2, DRAW_FILL_FULL); 

    Paint_DrawCircle(110, 34, 15, GREEN, DOT_PIXEL_1X1, DRAW_FILL_EMPTY);
    Paint_DrawCircle(144, 34, 15, GREEN, DOT_PIXEL_1X1, DRAW_FILL_FULL);  

    Paint_DrawNum(10, 80, 9.87654321, &Font24, 5, WHITE, BLACK);
    Paint_DrawString_EN(10, 54, "ABC", &Font24, 0x000f, 0xfff0);
    Paint_DrawString_CN(10, 104, "»¶Ó­Ê¹ÓÃ", &Font24CN, WHITE, BLUE);
    Paint_DrawString_EN(10, 144, "WaveShare", &Font24, RED, WHITE); 

    LCD_3IN49_Display(BlackImage);
    DEV_Delay_ms(1000);
#endif

#if 1
    /*3.Refresh the picture in RAM to LCD*/
    Paint_DrawImage(gImage_image,0,0,LCD_3IN49.WIDTH,LCD_3IN49.HEIGHT);
    LCD_3IN49_Display(BlackImage);
    DEV_Delay_ms(1000);
#endif

#if 1
    /*4.Display six-axis sensor and rtc data*/
    float acc[3], gyro[3];
    char str[3];
    uint8_t press_time = 0;
    unsigned int tim_count,result = 0;
    const float conversion_factor = 3.299f / (1 << 12) * 3;
    QMI8658_init();
    PCF85063A_Init();
    datetime_t Now_time;
    // Now_time.year = 2025;
    // Now_time.month = 4;
    // Now_time.day = 9;
    // Now_time.dotw = 3;
    // Now_time.hour = 8;
    // Now_time.min = 8;
    // Now_time.sec = 8;
    // PCF85063A_Set_All(Now_time);

    DEV_IRQ_SET(TOUCH_INT_PIN, GPIO_IRQ_EDGE_RISE, &Touch_INT_callback);
    Paint_Clear(WHITE);
    Paint_DrawRectangle(0, 43, 172, 91, 0XF410, DOT_PIXEL_2X2, DRAW_FILL_FULL);
    Paint_DrawString_EN(0,  43 , "---Long---Press Quit", &Font24, BLACK, 0XF410);
    Paint_DrawString_EN(45, 131, "ACC_X" , &Font24, BLACK, 0X4F30);        
    Paint_DrawString_EN(45, 185, "ACC_Y" , &Font24, BLACK, 0X4F30);
    Paint_DrawString_EN(45, 239, "ACC_Z", &Font24, BLACK, 0X4F30);
    Paint_DrawString_EN(45, 298, "GYR_X", &Font24, BLACK, 0X2595);
    Paint_DrawString_EN(45, 352, "GYR_Y", &Font24, BLACK, 0X2595);
    Paint_DrawString_EN(45, 406, "GYR_Z", &Font24, BLACK, 0X2595);
    Paint_DrawString_EN(45, 465, "RTC_H", &Font24, BLACK, 0XAD55);
    Paint_DrawString_EN(45, 519, "RTC_M", &Font24, BLACK, 0XAD55);
    Paint_DrawString_EN(45, 573, "RTC_S", &Font24, BLACK, 0XAD55);
    LCD_3IN49_Display(BlackImage);

    while (true)
    {
        while(i2c_lock);
        I2C_LOCK();
        QMI8658_read_xyz(acc, gyro, &tim_count);
        PCF85063A_Read_now(&Now_time);
        I2C_UNLOCK();
        result = adc_read();
        printf("Raw value: 0x%03x, voltage: %f V\n", result, result * conversion_factor);
        // printf("acc_x   = %4.3fmg , acc_y  = %4.3fmg , acc_z  = %4.3fmg\r\n", acc[0], acc[1], acc[2]);
        // printf("gyro_x  = %4.3fdps, gyro_y = %4.3fdps, gyro_z = %4.3fdps\r\n", gyro[0], gyro[1], gyro[2]);
        // printf("tim_count = %d\r\n", tim_count);
        
        Paint_DrawRectangle(45, 158, 172, 184, WHITE, DOT_PIXEL_2X2, DRAW_FILL_FULL);
        Paint_DrawRectangle(45, 212, 172, 238, WHITE, DOT_PIXEL_2X2, DRAW_FILL_FULL);
        Paint_DrawRectangle(45, 266, 172, 297, WHITE, DOT_PIXEL_2X2, DRAW_FILL_FULL);
        Paint_DrawRectangle(45, 325, 172, 351, WHITE, DOT_PIXEL_2X2, DRAW_FILL_FULL);
        Paint_DrawRectangle(45, 379, 172, 405, WHITE, DOT_PIXEL_2X2, DRAW_FILL_FULL);
        Paint_DrawRectangle(45, 433, 172, 464, WHITE, DOT_PIXEL_2X2, DRAW_FILL_FULL);
        Paint_DrawRectangle(45, 492, 172, 518, WHITE, DOT_PIXEL_2X2, DRAW_FILL_FULL);
        Paint_DrawRectangle(45, 546, 172, 572, WHITE, DOT_PIXEL_2X2, DRAW_FILL_FULL);
        Paint_DrawRectangle(45, 600, 172, 631, WHITE, DOT_PIXEL_2X2, DRAW_FILL_FULL);
        Paint_DrawNum(45, 158, acc[0],  &Font24, 2, BLACK, WHITE);
        Paint_DrawNum(45, 212, acc[1],  &Font24, 2, BLACK, WHITE);
        Paint_DrawNum(45, 266, acc[2],  &Font24, 2, BLACK, WHITE);
        Paint_DrawNum(45, 325, gyro[0], &Font24, 2, BLACK, WHITE);
        Paint_DrawNum(45, 379, gyro[1], &Font24, 2, BLACK, WHITE);
        Paint_DrawNum(45, 433, gyro[2], &Font24, 2, BLACK, WHITE);
        sprintf(str, "%02d    ", Now_time.hour);
        Paint_DrawString_EN(45, 492, str, &Font24, BLACK, WHITE);
        sprintf(str, "%02d    ", Now_time.min);
        Paint_DrawString_EN(45, 546, str, &Font24, BLACK, WHITE);
        sprintf(str, "%02d    ", Now_time.sec);
        Paint_DrawString_EN(45, 600, str, &Font24, BLACK, WHITE);

        // LCD_3IN49_DisplayWindows(45, 158, 172, 631, BlackImage);
        LCD_3IN49_Display(BlackImage);
        if (flag == 1)
        {
            flag = 0;
            while(i2c_lock);
            I2C_LOCK();
            Touch_Read_State();
            I2C_UNLOCK();
            if(TOUCH.Finger_Num > 0)
                press_time++;
            else
                press_time = 0;
            if(press_time > 4)
            {
                break;
            }
        }
        DEV_Delay_ms(100);
    }
#endif

#if 1
    /*5.Drawing test*/
    Paint_Clear(WHITE);
    LCD_3IN49_Display(BlackImage);
    Paint_DrawRectangle(0, 0, 172, 80, 0X2595, DOT_PIXEL_2X2, DRAW_FILL_FULL);
    Paint_DrawString_EN(0, 30, "Touch test", &Font24, BLACK, 0X2595);
    LCD_3IN49_Display(BlackImage);
    while (true)
    {
        if (flag == 1)
        {
            while(i2c_lock);
            I2C_LOCK();
            Touch_Read_State();
            I2C_UNLOCK();
            Paint_DrawPoint(TOUCH.Point1_x-2, TOUCH.Point1_y, RED, DOT_PIXEL_4X4, DOT_FILL_AROUND);
            // printf("x[1]: %d, y[1]: %d  ", TOUCH.Point1_x, TOUCH.Point1_y);
            if(TOUCH.Finger_Num > 1)
            {
                Paint_DrawPoint(TOUCH.Point2_x-2, TOUCH.Point2_y, RED, DOT_PIXEL_4X4, DOT_FILL_AROUND);
                // printf("x[x]: %d, y[x]: %d  ", TOUCH.Point2_x, TOUCH.Point2_y);
            }
            // printf("\n");
            LCD_3IN49_Display(BlackImage);
            flag = 0;
        }
        __asm__ volatile("nop");
    }
#endif
     /* Module Exit */
     free(BlackImage);
     BlackImage = NULL;

     DEV_Module_Exit();
}

void core1_entry() {
    static int press_time = 0;
    while(1)
    {
        DEV_Delay_ms(5); 
        if(DEV_Digital_Read(SYS_OUT) == 0)
        {
            press_time++;
            if(press_time > 300)//shutdown  
            {
                press_time = 0;
                DEV_Digital_Write(SYS_EN, 0);
            }
        }
        else
        {
            press_time = 0;
        }
    }
}

void Touch_INT_callback(uint gpio, uint32_t events)
{
    if(i2c_lock)return;
    if (gpio == TOUCH_INT_PIN)
    {
        flag = 1;
    }
}
