#ifndef BOOTLOADER_H
#define BOOTLOADER_H

#include <stdint.h>

#define FLASH_BASE_ADDRESS           0x08000000
#define FLASH_END_ADDRESS            0x08010000  // GD32E230F8: 64KB Flash
#define APP_FLASH_END_ADDRESS        0x0800EFFF  // End of application flash
#define APPLICATION_ADDRESS          0x08002000  // Application starts at 8KB (adjust as needed)
#define FLASH_FLAG_ADDRESS           0x0800FFFC  // Address to check if application is present
#define BOOTLOADER_SIZE              0x2000      // 8KB for bootloader

// Ymodem协议常量
#define PACKET_HEADER                3      // 数据包头大小
#define PACKET_1K_SIZE               1024   // 1K数据包大小
#define FILE_NAME_LENGTH             256    // 文件名长度
#define FILE_SIZE_LENGTH             16     // 文件大小字符串长度

// Ymodem控制字符
#define SOH                          0x01   // 128字节数据包开始
#define STX                          0x02   // 1K字节数据包开始
#define EOT                          0x04   // 传输结束
#define ACK                          0x06   // 确认
#define NAK                          0x15   // 否认
#define CA                           0x18   // 取消传输
#define CRC16                        0x43   // 'C' - 请求CRC16模式

#define YMODEM_RX_BUFFER_SIZE        1100    // 接收缓冲区大小

#define ISVALIDHEX(c)    (((c) >= '0' && (c) <= '9') || \
                         ((c) >= 'A' && (c) <= 'F') || \
                         ((c) >= 'a' && (c) <= 'f'))
#define CONVERTHEX(c)    (((c) >= '0' && (c) <= '9') ? ((c) - '0') : \
                         (((c) >= 'A' && (c) <= 'F') ? ((c) - 'A' + 10) : \
                         ((c) - 'a' + 10)))
#define ISVALIDDEC(c)    ((c) >= '0' && (c) <= '9')
#define CONVERTDEC(c)    ((c) - '0')

extern uint8_t ymodem_rx_buffer[YMODEM_RX_BUFFER_SIZE];
extern uint16_t ymodem_rx_count;

/* Function pointer type for application jump */
typedef void (*pFunction)(void);

/* Function declarations */
uint8_t check_flash_and_jump(uint8_t *buf);

uint32_t str_to_int(uint8_t *input_str, int32_t *int_num);

uint16_t crc16_update(uint16_t crc_in, uint8_t byte);
uint16_t crc16_calculate(const uint8_t* data, uint32_t size);

void ymodem_read_packet_data(void);

int32_t ymodem_receive(uint8_t *buf);

#endif