#pragma once

#include "s600.h"
#include "byte_queue.h"

#define S600_CAN_BUILD_CMD(cmd) \
	(CONFIG_CAN_ID << 8 | (cmd))

#define S600_CAN_DEST_OFFSET		0
#define S600_CAN_SRC_OFFSET			7

#define S600_CAN_ALL_ID				0x7F
#define S600_CAN_BAUDRATE			250

#define S600_CAN_USE_MASK			0

#define S600_CAN_DEST_ID(id) \
	(U32(id) << S600_CAN_DEST_OFFSET)

#define S600_CAN_SRC_ID(id) \
	(U32(id) << S600_CAN_SRC_OFFSET)

typedef struct {
	u32 efid;
	u8 length;
	u8 data[8];
} s600_can_frame_t;

#pragma anon_unions

typedef struct {
	u8 dest;
	u8 src;
	u8 type;
	u8 index;
	u16 offset;
	u16 length;

#if S600_CAN_USE_MASK
	u32 mask;
#endif

	union {
		u8 data[256];
		u8 datas[32][8];
	};
} s600_can_packet_t;

void s600_can_device_config(void);
void s600_can_device_deinit(void);

u8 s600_can_find_mailbox(void);
u8 s600_can_wait_mailbox(void);
void s600_can_send_frame(u8 mailbox, u32 efid, const u8 *buff, u8 length);
void s600_can_transmit(void);
void s600_can_poll(void);

bool s600_can_send_packet(u8 dest, u8 src, u8 type, const void *data, u16 length);
void s600_can_send_packet_block(u8 dest, u8 src, u8 type, const void *data, u16 length);
bool s600_can_send_command(u8 addr, const void *command, u16 length);
bool s600_can_send_command_read_status(void);
bool s600_can_send_response(u8 addr, const void *response, u16 length);
bool s600_can_send_event(u8 addr, const void *event, u16 length);
