
#ifndef FLASH_DEV_AT45DB_H
#define FLASH_DEV_AT45DB_H


#include "../flash.h"

#ifdef __cplusplus
extern "C" {
#endif


#define AT45DB_ID_MANUFACTURER   (0x1F)
#define AT45DB_ID_CAPACITY       (0x00)

#define AT45DB_MAX_SECTORS_CNT    32


#define AT45DB041_ID_MANUFACTURER AT45DB_ID_MANUFACTURER
#define AT45DB041_ID_DEVICE       0x24
#define AT45DB041_ID_CAPACITY     AT45DB_ID_CAPACITY
#define AT45DB041_FLASH_SIZE      (512 * 1024)
#define AT45DB041_SECTORS_CNT     8
#define AT45DB041_PAGE_SIZE       (256)
#define AT45DB041_BLOCK_SIZE      (8*AT45DB041_PAGE_SIZE)
#define AT45DB041_SECTOR_SIZE     (32*AT45DB041_BLOCK_SIZE)
#define AT45DB041_SECTOR_0A_SIZE  AT45DB041_BLOCK_SIZE
#define AT45DB041_SECTOR_0B_SIZE  (AT45DB041_SECTOR_SIZE-AT45DB041_BLOCK_SIZE)

#define AT45DB161_ID_MANUFACTURER AT45DB_ID_MANUFACTURER
#define AT45DB161_ID_DEVICE       0x26
#define AT45DB161_ID_CAPACITY     AT45DB_ID_CAPACITY
#define AT45DB161_FLASH_SIZE      (2 * 1024 * 1024)
#define AT45DB161_SECTORS_CNT     16
#define AT45DB161_PAGE_SIZE       (512)
#define AT45DB161_BLOCK_SIZE      (8*AT45DB161_PAGE_SIZE)
#define AT45DB161_SECTOR_SIZE     (32*AT45DB161_BLOCK_SIZE)
#define AT45DB161_SECTOR_0A_SIZE  AT45DB161_BLOCK_SIZE
#define AT45DB161_SECTOR_0B_SIZE  (AT45DB161_SECTOR_SIZE-AT45DB161_BLOCK_SIZE)



#define AT45DB64X_ID_MANUFACTURER AT45DB_ID_MANUFACTURER
#define AT45DB64X_ID_DEVICE       0x28
#define AT45DB64X_ID_CAPACITY     AT45DB_ID_CAPACITY
#define AT45DB64X_FLASH_SIZE      (8*1024*1024)


#define AT45DB64X_SECTORS_CNT 32

/* размер сектора одинаковый для обоих типов памяти (AT45DB641 и AT45DB642) */
#define AT45DB64X_SECTOR_SIZE  (256*1024)
#define AT45DB64X_SECTOR_0A_SIZE(block_size)  (block_size)
#define AT45DB64X_SECTOR_0B_SIZE(block_size)  (AT45DB64X_SECTOR_SIZE-block_size)

#define AT45DB641_PAGE_SIZE         (256)
#define AT45DB641_BLOCK_SIZE        (8*AT45DB641_PAGE_SIZE)
#define AT45DB641_SECTOR_SIZE       (AT45DB64X_SECTOR_SIZE)
#define AT45DB641_SECTOR_0A_SIZE    AT45DB64X_SECTOR_0A_SIZE(AT45DB641_BLOCK_SIZE)
#define AT45DB641_SECTOR_0B_SIZE    AT45DB64X_SECTOR_0B_SIZE(AT45DB641_BLOCK_SIZE)

#define AT45DB642_PAGE_SIZE         (1024)
#define AT45DB642_BLOCK_SIZE        (8*AT45DB642_PAGE_SIZE)
#define AT45DB642_SECTOR_SIZE       (AT45DB64X_SECTOR_SIZE)
#define AT45DB642_SECTOR_0A_SIZE    AT45DB64X_SECTOR_0A_SIZE(AT45DB642_BLOCK_SIZE)
#define AT45DB642_SECTOR_0B_SIZE    AT45DB64X_SECTOR_0B_SIZE(AT45DB642_BLOCK_SIZE)



#define AT45DB_PROT_SECT0_A    (1UL << 0)
#define AT45DB_PROT_SECT0_B    (1UL << 1)
#define AT45DB_PROT_SECTOR(i)  (1UL << (i-1))

typedef enum {
    AT45DB_STATUS_RDY       = 1UL << 7,
    AT45DB_STATUS_COMP      = 1UL << 6,
    AT45DB_STATUS_PROTECT   = 1UL << 1,
    AT45DB_STATUS_PAGE_SIZE = 1UL << 0
} t_flash_at45db_status;

extern const t_flash_info flash_info_at45db642;
extern const t_flash_info flash_info_at45db641;
extern const t_flash_info flash_info_at45db041;
extern const t_flash_info flash_info_at45db161e;
extern const t_flash_info flash_info_at45db161d;

t_flash_errs flash_at45db_set(t_flash_iface *iface);


#define flash_at45db_get_status flash_generic_get_status
#define flash_at45db_read       flash_generic_read
t_flash_errs flash_at45db_erase_cb(t_flash_iface *iface, unsigned addr, size_t len, void (*cb)(void));
t_flash_errs flash_at45db_erase(t_flash_iface *iface, unsigned addr, size_t len);
t_flash_errs flash_at45db_write(t_flash_iface *iface, unsigned addr,
                                const unsigned char *data, size_t len,
                                unsigned flags);
#define flash_at45db_write_enable flash_generic_write_enable
#define flash_at45db_get_erase_cmd flash_generic_get_erase_cmd

t_flash_errs flash_at45db_lock_enable(t_flash_iface *iface);
t_flash_errs flash_at45db_lock(t_flash_iface *iface, unsigned addr, unsigned size);
t_flash_errs flash_at45db_unlock(t_flash_iface *iface, unsigned addr, unsigned size);
t_flash_errs flash_at45db_lock_check(t_flash_iface *iface, unsigned addr, unsigned size, int locked, int *check_ok);

t_flash_errs flash_at45db_set_page_size_pow2(t_flash_iface *iface);
t_flash_errs flash_at45db_set_sector_protection(t_flash_iface *iface, unsigned sect0, unsigned sectors);
t_flash_errs flash_at45db_get_sector_protection(t_flash_iface *iface, unsigned *sect0, unsigned *sectors);
t_flash_errs flash_at45db_protection_enable(t_flash_iface *iface);
t_flash_errs flash_at45db_protection_disable(t_flash_iface *iface);
void flash_at45db_region_sectors_mask(t_flash_iface *iface, unsigned addr, unsigned size, unsigned *psect0, unsigned *psectors);

#ifdef __cplusplus
}
#endif

#endif // FLASH_DEV_AT45DB_H
