#include "task_main.h"
#include "task_debug.h"
#include <stdlib.h>
#include "FreeRTOS.h"
#include "task.h"
#include "elog.h"
#include "main.h"
#include "ff.h"
#include "audio_mp3.h"
#include "audio_flac.h"
#include "bsp_aic3204.h"
// #include "lvgl.h"
// #include "lv_demos.h"
// #include "lv_port_disp.h"

static const char *TAG = "task_main";

void util_i2c_scan(I2C_HandleTypeDef *hi2c)
{
  elog_info(TAG, "scanning devices on i2c bus...");

  for (uint8_t addr = 0; addr < 128; addr ++) {
    if (HAL_I2C_Master_Transmit(hi2c, addr << 1, NULL, 0, 100) == HAL_OK) {
      elog_info(TAG, "i2c device with read address 0x%02X found", addr << 1);
    }
  }

  elog_info(TAG, "scan done");
}

// #define SDRAM_Size 32*1024*1024
// #define SDRAM_BANK_ADDR     ((uint32_t)0xC0000000)
// #define FMC_COMMAND_TARGET_BANK   FMC_SDRAM_CMD_TARGET_BANK1
// #define SDRAM_TIMEOUT     ((uint32_t)0x1000)

// #define SDRAM_MODEREG_BURST_LENGTH_1             ((uint16_t)0x0000)
// #define SDRAM_MODEREG_BURST_LENGTH_2             ((uint16_t)0x0001)
// #define SDRAM_MODEREG_BURST_LENGTH_4             ((uint16_t)0x0002)
// #define SDRAM_MODEREG_BURST_LENGTH_8             ((uint16_t)0x0004)
// #define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL      ((uint16_t)0x0000)
// #define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED     ((uint16_t)0x0008)
// #define SDRAM_MODEREG_CAS_LATENCY_2              ((uint16_t)0x0020)
// #define SDRAM_MODEREG_CAS_LATENCY_3              ((uint16_t)0x0030)
// #define SDRAM_MODEREG_OPERATING_MODE_STANDARD    ((uint16_t)0x0000)
// #define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
// #define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE     ((uint16_t)0x0200)

// void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command)
// {
// 	__IO uint32_t tmpmrd = 0;

// 	/* Configure a clock configuration enable command */
// 	Command->CommandMode 				= FMC_SDRAM_CMD_CLK_ENABLE;
// 	Command->CommandTarget 				= FMC_COMMAND_TARGET_BANK;
// 	Command->AutoRefreshNumber 		= 1;
// 	Command->ModeRegisterDefinition 	= 0;

// 	HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);

// 	/* Configure a PALL (precharge all) command */
// 	Command->CommandMode 				= FMC_SDRAM_CMD_PALL;
// 	Command->AutoRefreshNumber 		= 1;
// 	Command->ModeRegisterDefinition 	= 0;

// 	HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
// 	/* Configure a Auto-Refresh command */
// 	Command->CommandMode 				= FMC_SDRAM_CMD_AUTOREFRESH_MODE;
// 	Command->CommandTarget 				= FMC_COMMAND_TARGET_BANK;
// 	Command->AutoRefreshNumber			= 8;
// 	Command->ModeRegisterDefinition 	= 0;

// 	HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
// 	/* Program the external memory mode register */
// 	tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_2         |
// 							SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |
// 							SDRAM_MODEREG_CAS_LATENCY_3           |
// 							SDRAM_MODEREG_OPERATING_MODE_STANDARD |
// 							SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;

// 	Command->CommandMode					= FMC_SDRAM_CMD_LOAD_MODE;
// 	Command->AutoRefreshNumber 		= 1;
// 	Command->ModeRegisterDefinition 	= tmpmrd;

// 	HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
// 	HAL_SDRAM_ProgramRefreshRate(hsdram, 918);

// }

// set(CMAKE_C_LINK_FLAGS "-g -marm -mcpu=arm968e-s -mthumb-interwork -nostdlib -Xlinker -Map=beken.map -Wl,--gc-sections -Wl,-wrap,malloc -Wl,-wrap,_malloc_r -Wl,-wrap,free -Wl,-wrap,_free_r -Wl,-wrap,zalloc -Wl,-wrap,calloc -Wl,-wrap,realloc -Wl,-wrap,_realloc_r -Wl,-wrap,printf -Wl,-wrap,vsnprintf -Wl,-wrap,snprintf -Wl,-wrap,sprintf -Wl,-wrap,puts")

// uint8_t *sdram_ptr = (uint8_t *)SDRAM_BANK_ADDR;

// void codec_init(void)
// {
//   uint8_t retries = 0;
//   while (1) {
//     if (WM8904_Init(&hi2c1) == HAL_OK) {
//       break;
//     }

//     HAL_I2C_DeInit(&hi2c1);
//     vTaskDelay(pdMS_TO_TICKS(200));
//     HAL_I2C_Init(&hi2c1);

//     retries ++;
//     if (retries > 10) {
//       elog_assert(TAG, "wm8904 configuration failed");
//       while (1) {
//         vTaskDelay(1);
//       }
//     }
//   }
// }

void task_main_entry(void *param)
{
  // lv_init();
  // lv_port_disp_init();
  // lv_demo_music();

  task_debug_create(NULL);

  // FMC_SDRAM_CommandTypeDef command;
  // SDRAM_Initialization_Sequence(&hsdram1, &command);

  // memset(sdram_ptr, 0xAA, 128);
  // for (uint8_t i = 0; i < 128; i ++) {
  //   if (sdram_ptr[i] != 0xAA) {
  //     elog_error(TAG, "sdram test failed");
  //   }
  // }

  /* 挂载文件系统 */
  FATFS *fatfs = malloc(sizeof(FATFS));
  FRESULT f_result = f_mount(fatfs, "/", 1);
  if (f_result == FR_OK) {
    elog_info(TAG, "fatfs mount successful");
  } else {
    elog_error(TAG, "fatfs mount failed");
    while(1) {
      vTaskDelay(1);
    }
  }

  HAL_GPIO_WritePin(CODEC_EN_GPIO_Port, CODEC_EN_Pin, GPIO_PIN_SET);
  HAL_GPIO_WritePin(TP_RST_GPIO_Port, TP_RST_Pin, GPIO_PIN_SET);
  vTaskDelay(20);
  bsp_aic3204_init(&hi2c1);

  util_i2c_scan(&hi2c1);

  uint32_t watermark = uxTaskGetStackHighWaterMark(NULL);
  elog_debug(TAG, "task stack watermark before decode: %d", watermark * sizeof(StackType_t));

  while (1) {
    music_flac_play("96猫 - 嘘の火花.flac");
    watermark = uxTaskGetStackHighWaterMark(NULL);
    elog_debug(TAG, "task stack watermark after flac decode: %d", watermark * sizeof(StackType_t));

    music_mp3_play("倉木麻衣 - Time after time〜花舞う街で〜.mp3");
    watermark = uxTaskGetStackHighWaterMark(NULL);
    elog_debug(TAG, "task stack watermark after mp3 decode: %d", watermark * sizeof(StackType_t));

    music_flac_play("HOYO-MiX - Village Surrounded by Green 葳蕤林野间.flac");
    music_mp3_play("HoneyWorks,早見沙織 - 可愛くてごめん.mp3");
    music_flac_play("唐九夏 - 一克拉月光.flac");
    music_mp3_play("Candy_Wind - Go For The Next ！.mp3");
    music_flac_play("四季音色 - 斑光.flac");
    music_mp3_play("July - Somewhere.mp3");
  }
}

void task_main_create(void *param)
{
  xTaskCreate(task_main_entry, "task_main", 32768 / sizeof(StackType_t), param, 8, NULL);
}
