/*
 * Copyright (c) 2016-2021 Satlab A/S <satlab@satlab.com>
 * All rights reserved. Do not distribute without permission.
 */

/**
 * @file polaris_proto.h
 *
 * This file specifies the available CSP services and ports on the Polaris
 * receiver. It should not be necessary for clients to use these definitions
 * directly. Instead, use the wrapper functions from this library which handles
 * the protocol and performs necessary byte order conversion.
 *
 *
 */

#ifndef _SL_POLARIS_CLIENT_PROTO_H_
#define _SL_POLARIS_CLIENT_PROTO_H_

#include <stdint.h>

/** Default CSP address */
#define SL_POLARIS_DEFAULT_ADDRESS		20

/** CSP ports */
#define SL_POLARIS_PORT_SAMPLEBUF		20
#define SL_POLARIS_PORT_STORE			21
#define SL_POLARIS_PORT_BOOTLOADER		25
#define SL_POLARIS_PORT_SHELL			26

/** Default mirror frame receive port */
#define SL_POLARIS_PORT_STORE_MIRROR_RECV	30

/** Error codes */
#define SL_POLARIS_ERR_NONE			0
#define SL_POLARIS_ERR_INVAL			1
#define SL_POLARIS_ERR_IO			2
#define SL_POLARIS_ERR_NOMEM			3
#define SL_POLARIS_ERR_BUSY			4

/* Generic packet types */
typedef struct {
	uint8_t type;
} __attribute__ ((packed)) sl_polaris_req_t;

typedef struct {
	uint8_t type;
	uint8_t error;
} __attribute__ ((packed)) sl_polaris_rep_t;

/*
 * SL_POLARIS_PORT_SAMPLEBUF
 */

/* Types */
#define SL_POLARIS_SAMPLEBUF_READ_REQ		1
#define SL_POLARIS_SAMPLEBUF_READ_REP		2
#define SL_POLARIS_SAMPLEBUF_READ_CHUNK		3
#define SL_POLARIS_SAMPLEBUF_FREE		4

/* Sources */
#define SL_POLARIS_SAMPLEBUF_SOURCE_RAW		0
#define SL_POLARIS_SAMPLEBUF_SOURCE_CH1		1
#define SL_POLARIS_SAMPLEBUF_SOURCE_CH2		2
#define SL_POLARIS_SAMPLEBUF_SOURCE_CH3		3
#define SL_POLARIS_SAMPLEBUF_SOURCE_CH4		4

#define SL_POLARIS_SAMPLEBUF_SOURCE_AIS1_CH87B  SL_POLARIS_SAMPLEBUF_SOURCE_CH1
#define SL_POLARIS_SAMPLEBUF_SOURCE_AIS2_CH88B  SL_POLARIS_SAMPLEBUF_SOURCE_CH2
#define SL_POLARIS_SAMPLEBUF_SOURCE_AIS3_CH75   SL_POLARIS_SAMPLEBUF_SOURCE_CH3
#define SL_POLARIS_SAMPLEBUF_SOURCE_AIS4_CH76   SL_POLARIS_SAMPLEBUF_SOURCE_CH4

/* Destinations */
#define SL_POLARIS_SAMPLEBUF_DEST_CSP		0
#define SL_POLARIS_SAMPLEBUF_DEST_MEM		1
#define SL_POLARIS_SAMPLEBUF_DEST_SDCARD	2

/* Flags */
#define SL_POLARIS_SAMPLEBUF_FL_FORCE_INTRAM	(1 << 0)
#define SL_POLARIS_SAMPLEBUF_FL_SYNC_PPS	(1 << 1)

typedef struct {
	uint8_t type;
	uint8_t source;
	uint8_t dest;
	uint8_t flags;
	uint32_t id;
	uint32_t samples;
} __attribute__ ((packed)) sl_polaris_samplebuf_read_req_t;

typedef struct {
	uint8_t type;
	uint8_t error;
	uint32_t id;
	uint32_t addr;
} __attribute__ ((packed)) sl_polaris_samplebuf_read_rep_t;

#define SL_POLARIS_SAMPLEBUF_READ_CHUNK_SAMPLES	32
typedef struct {
	uint8_t type;
	uint8_t error;
	uint16_t seq;
	uint16_t total;
	uint32_t data[SL_POLARIS_SAMPLEBUF_READ_CHUNK_SAMPLES];
} __attribute__ ((packed)) sl_polaris_samplebuf_read_chunk_t;

typedef struct {
	uint8_t type;
	uint8_t flags;
	uint32_t addr;
} __attribute__ ((packed)) sl_polaris_samplebuf_free_req_t;

typedef struct {
	uint8_t type;
	uint8_t error;
} __attribute__ ((packed)) sl_polaris_samplebuf_free_rep_t;

/*
 * SL_POLARIS_PORT_STORE
 */

/* Types */
#define SL_POLARIS_STORE_FRAME			1
#define SL_POLARIS_STORE_MIRROR_REQ		2
#define SL_POLARIS_STORE_MIRROR_REP		3
#define SL_POLARIS_STORE_READ_REQ		4
#define SL_POLARIS_STORE_READ_REP		5

#define SL_POLARIS_STORE_MAX_DATALEN		160
typedef struct {
	/** Must be SL_POLARIS_STORE_FRAME */
	uint8_t type;
	/** Error code */
	uint8_t error;
	/** Sequence number of this frame */
	uint32_t seq;
	/** Time of reception (nanoseconds since 1/1/1970) */
	uint64_t time;
	/** AIS channel this message was received on */
	uint8_t channel;
	/** Signal scale */
	uint16_t scale;
	/** Estimated frequency offset */
	int16_t mean;
	/** Number of bytes in data field */
	uint8_t length;
	/** Raw AIS message, excludes flag bytes, includes FCS */
	uint8_t data[SL_POLARIS_STORE_MAX_DATALEN];
} __attribute__ ((packed)) sl_polaris_store_frame_t;
#define SL_POLARIS_STORE_FRAME_OVERHEAD		(sizeof(sl_polaris_store_frame_t) - SL_POLARIS_STORE_MAX_DATALEN)

typedef struct {
	uint8_t type;
	uint8_t dest_node;
	uint8_t dest_port;
	uint32_t timeout_ms;
} __attribute__ ((packed)) sl_polaris_store_mirror_req_t;

typedef struct {
	uint8_t type;
	uint8_t error;
} __attribute__ ((packed)) sl_polaris_store_mirror_rep_t;

/* Bitmap size */
#define SL_POLARIS_STORE_BITMAP_SIZE		32 /* bytes */

typedef struct {
	uint8_t type;
	uint32_t start;
	uint8_t bitmap[SL_POLARIS_STORE_BITMAP_SIZE];
} __attribute__ ((packed)) sl_polaris_store_read_req_t;

typedef struct {
	uint8_t type;
	uint8_t error;
} __attribute__ ((packed)) sl_polaris_store_read_rep_t;

/*
 * SL_POLARIS_PORT_BOOTLOADER
 */

/* Types */
#define SL_POLARIS_BOOTLOADER_SET_REQ		1
#define SL_POLARIS_BOOTLOADER_SET_REP		2
#define SL_POLARIS_BOOTLOADER_FLASH_REQ		5
#define SL_POLARIS_BOOTLOADER_FLASH_REP		6
#define SL_POLARIS_BOOTLOADER_ERASE_REQ		7
#define SL_POLARIS_BOOTLOADER_ERASE_REP		8
#define SL_POLARIS_BOOTLOADER_CHECKSUM_REQ	9
#define SL_POLARIS_BOOTLOADER_CHECKSUM_REP	10
#define SL_POLARIS_BOOTLOADER_VERIFY_REQ	11
#define SL_POLARIS_BOOTLOADER_VERIFY_REP	12

/* Keys */
#define SL_POLARIS_BOOTLOADER_SET_KEY		0x5c162fba
#define SL_POLARIS_BOOTLOADER_FLASH_KEY		0x78a9df94
#define SL_POLARIS_BOOTLOADER_ERASE_KEY		0x98b5305a

typedef struct {
	/* Must be SL_POLARIS_BOOTLOADER_SET_REQ */
	uint8_t type;
	/* Flags, currently unused - set to zero */
	uint8_t flags;
	/* Number of boots to boot alternate image, 0 = boot factory */
	uint8_t boots;
	/* Must be SL_POLARIS_BOOTLOADER_SET_KEY */
	uint32_t key;
} __attribute__ ((packed)) sl_polaris_bootloader_set_req_t;

typedef struct {
	/* Must be SL_POLARIS_BOOTLOADER_SET_REP */
	uint8_t type;
	/* Error code */
	uint8_t error;
} __attribute__ ((packed)) sl_polaris_bootloader_set_rep_t;

#define SL_POLARIS_BOOTLOADER_FILENAME_MAX	40
typedef struct {
	/* Must be SL_POLARIS_BOOTLOADER_FLASH_REQ */
	uint8_t type;
	/* Flags, currently unused - set to zero */
	uint8_t flags;
	/* Must be SL_POLARIS_BOOTLOADER_FLASH_KEY */
	uint32_t key;
	/* Filename to flash to the alternate partition */
	uint8_t filename[SL_POLARIS_BOOTLOADER_FILENAME_MAX];
} __attribute__ ((packed)) sl_polaris_bootloader_flash_req_t;

typedef struct {
	/* Must be SL_POLARIS_BOOTLOADER_FLASH_REP */
	uint8_t type;
	/* Error code */
	uint8_t error;
	/* CRC32C of flash image */
	uint32_t checksum;
} __attribute__ ((packed)) sl_polaris_bootloader_flash_rep_t;

typedef struct {
	/* Must be SL_POLARIS_BOOTLOADER_ERASE_REQ */
	uint8_t type;
	/* Flags, currently unused - set to zero */
	uint8_t flags;
	/* Must be SL_POLARIS_BOOTLOADER_ERASE_KEY */
	uint32_t key;
} __attribute__ ((packed)) sl_polaris_bootloader_erase_req_t;

typedef struct {
	/* Must be SL_POLARIS_BOOTLOADER_ERASE_REP */
	uint8_t type;
	/* Error code */
	uint8_t error;
} __attribute__ ((packed)) sl_polaris_bootloader_erase_rep_t;

typedef struct {
	/* Must be SL_POLARIS_BOOTLOADER_CHECKSUM_REQ */
	uint8_t type;
	/* Flags, currently unused - set to zero */
	uint8_t flags;
	/* Number of bytes to checksum from beginning of alternate partition */
	uint32_t size;
} __attribute__ ((packed)) sl_polaris_bootloader_checksum_req_t;

typedef struct {
	/* Must be SL_POLARIS_BOOTLOADER_CHECKSUM_REP */
	uint8_t type;
	/* Error code */
	uint8_t error;
	/* CRC32C of flash image */
	uint32_t checksum;
} __attribute__ ((packed)) sl_polaris_bootloader_checksum_rep_t;

typedef struct {
	/* Must be SL_POLARIS_BOOTLOADER_VERIFY_REQ */
	uint8_t type;
	/* Flags, currently unused - set to zero */
	uint8_t flags;
	/* Partition to verify (0 = primary, 1 = alternate) */
	uint8_t partition;
} __attribute__ ((packed)) sl_polaris_bootloader_verify_req_t;

typedef struct {
	/* Must be SL_POLARIS_BOOTLOADER_VERIFY_REP */
	uint8_t type;
	/* Error code */
	uint8_t error;
	/* Read size of image */
	uint32_t size;
	/* Calculated checksum of image */
	uint32_t checksum;
} __attribute__ ((packed)) sl_polaris_bootloader_verify_rep_t;

/*
 * SL_POLARIS_PORT_SHELL
 */

/* Types */
#define SL_POLARIS_SHELL_RUN_REQ		1
#define SL_POLARIS_SHELL_RUN_REP		2

/* Keys */
#define SL_POLARIS_SHELL_RUN_KEY		0x3fb95c30

#define SL_POLARIS_SHELL_RUN_MAX		100
typedef struct {
	/** Must be SL_POLARIS_SHELL_RUN_REQ */
	uint8_t type;
	/** Flags, currently unused - set to zero */
	uint8_t flags;
	/** Must be SL_POLARIS_SHELL_RUN_KEY */
	uint32_t key;
	/** Command to execute */
	uint8_t cmd[SL_POLARIS_SHELL_RUN_MAX];
} __attribute__ ((packed)) sl_polaris_shell_run_req_t;

typedef struct {
	/** Must be SL_POLARIS_SHELL_RUN_REP */
	uint8_t type;
	/** Error code */
	uint8_t error;
} __attribute__ ((packed)) sl_polaris_shell_run_rep_t;

#endif /* _SL_POLARIS_CLIENT_PROTO_H_ */
