#ifndef _i2c_slave_h
#define _i2c_slave_h

#include <stdint.h>

#define CMD 0x01
#define DATA 0x02
#define BLK_GET_LEN 0x04
#define GET_CHECKSUM 0x08

typedef void(*fp_t)(void);

/* Defines for CAPABILITY */
#define CAPABILITY_PEC 0x80

/* Defines for STATUS_BYTE */
#define STATUS_CML 0x1

/* Defines for STATUS_CML */
#define CML_PEC 0x20
#define CML_MEM_FAULT 0x10
#define CML_COMM_ERR 0x2
#define CML_CPU 0x80

/* Defines for BOOT_NEW_FW */
#define FW_BOOTLOADER 1
#define FW_MAIN 2

/* Defines of Magic numbers */
#define UC_RESET_MAGIC    0x5A
#define BOOT_NEW_FW_MAGIC 0xAD

// QUERY command returned data format
enum QUERY_RET_VALS {
        QUERY_SUP      = 0x80, // no need to define this for every command
        QUERY_WR       = 0x40,
        QUERY_RD       = 0x20,
        QUERY_FMT_LIN  = 0x00,
        QUERY_FMT_16B  = 0x04,
        QUERY_FMT_DIR  = 0x0c,
        QUERY_FMT_8B   = 0x10,
        QUERY_FMT_VID  = 0x14,
        QUERY_FMT_MAN  = 0x18,
        QUERY_FMT_NAN  = 0x1c};

typedef const struct {
        //! CMD code
        const uint8_t addr;
        //! transaction length for this command
        int8_t *const data_len;
        //! pointer to data
        uint8_t *const data_pnt;
        //! invoked when accessing the command, before any data transfer
        const fp_t a_callback;
        //! invoked after writing data
        const fp_t w_callback;
        //! invoked after reading data
        const fp_t r_callback;
        //! data for the query command
        const uint8_t query_byte;
        //! always disable PEC for this command if non-zero
        const uint8_t wr_pec_disabled;
} cmd_t;

typedef const struct {
        //! holds number of commands implemented
        const uint8_t n_cmds;
        //! where the command structure list is stored
        cmd_t *const cmds;
} cmd_space_t;

int16_t in_addr_space(cmd_space_t *addr_space, uint16_t addr);
void setup_I2C_slave(cmd_space_t *impl_cmds);

#endif
