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

/**
 * @file polaris_adsb_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_ADSB_CLIENT_PROTO_H_
#define _SL_POLARIS_ADSB_CLIENT_PROTO_H_

#include <stdint.h>

/** Default CSP address */
#define SL_POLARIS_ADSB_DEFAULT_ADDRESS		23

/** CSP ports */
#define SL_POLARIS_ADSB_PORT_SAMPLEBUF		20
#define SL_POLARIS_ADSB_PORT_STORE		21
#define SL_POLARIS_ADSB_PORT_BOOTLOADER		25
#define SL_POLARIS_ADSB_PORT_SHELL		26

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

/** Error codes */
#define SL_POLARIS_ADSB_ERR_NONE		0
#define SL_POLARIS_ADSB_ERR_INVAL		1
#define SL_POLARIS_ADSB_ERR_IO			2
#define SL_POLARIS_ADSB_ERR_NOMEM		3
#define SL_POLARIS_ADSB_ERR_BUSY		4

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

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

/*
 * SL_POLARIS_ADSB_PORT_SAMPLEBUF
 */

/* Types */
#define SL_POLARIS_ADSB_SAMPLEBUF_READ_REQ	1
#define SL_POLARIS_ADSB_SAMPLEBUF_READ_REP	2
#define SL_POLARIS_ADSB_SAMPLEBUF_READ_CHUNK	3
#define SL_POLARIS_ADSB_SAMPLEBUF_FREE		4

/* Sources */
#define SL_POLARIS_ADSB_SAMPLEBUF_SOURCE_RAW	0

/* Destinations */
#define SL_POLARIS_ADSB_SAMPLEBUF_DEST_CSP	0
#define SL_POLARIS_ADSB_SAMPLEBUF_DEST_MEM	1
#define SL_POLARIS_ADSB_SAMPLEBUF_DEST_SDCARD	2

/* Flags */
#define SL_POLARIS_ADSB_SAMPLEBUF_FL_FORCE_INTRAM	(1 << 0)

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

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

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

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

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

/*
 * SL_POLARIS_ADSB_PORT_STORE
 */

/* Types */
#define SL_POLARIS_ADSB_STORE_FRAME		1
#define SL_POLARIS_ADSB_STORE_MIRROR_REQ	2
#define SL_POLARIS_ADSB_STORE_MIRROR_REP	3
#define SL_POLARIS_ADSB_STORE_READ_REQ		4
#define SL_POLARIS_ADSB_STORE_READ_REP		5
#define SL_POLARIS_ADSB_STORE_MIRROR_RENEW	6

/* Bitmap size */
#define SL_POLARIS_ADSB_STORE_BITMAP_SIZE	32 /* bytes */
typedef struct {
	uint8_t type;
	uint32_t start;
	uint8_t bitmap[SL_POLARIS_ADSB_STORE_BITMAP_SIZE];
} __attribute__ ((packed)) sl_polaris_adsb_store_read_req_t;

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

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

/* Maximum frame data size */
#define SL_POLARIS_ADSB_STORE_MAX_FRAMELEN	14
/* Flags */
#define SL_POLARIS_ADSB_STORE_FLAG_CORRECTED (1 << 0) /* Frame had bit error corrected */
#define SL_POLARIS_ADSB_STORE_FLAG_TS_VALID  (1 << 8) /* Frame timestamped using external PPS */
typedef struct {
	/** Must be SL_POLARIS_ADSB_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;
	/** Signal power */
	int16_t rssi;
	/** Flags */
	uint16_t flags;
	/** Raw Mode-S message */
	uint8_t data[SL_POLARIS_ADSB_STORE_MAX_FRAMELEN];
} __attribute__ ((packed)) sl_polaris_adsb_store_frame_t;
#define SL_POLARIS_ADSB_STORE_FRAME_OVERHEAD	(sizeof(sl_polaris_adsb_store_frame_t) - SL_POLARIS_ADSB_STORE_MAX_FRAMELEN)

/*
 * SL_POLARIS_ADSB_PORT_BOOTLOADER
 */

/* Types */
#define SL_POLARIS_ADSB_BOOTLOADER_SET_REQ	1
#define SL_POLARIS_ADSB_BOOTLOADER_SET_REP	2
#define SL_POLARIS_ADSB_BOOTLOADER_FLASH_REQ	5
#define SL_POLARIS_ADSB_BOOTLOADER_FLASH_REP	6
#define SL_POLARIS_ADSB_BOOTLOADER_ERASE_REQ	7
#define SL_POLARIS_ADSB_BOOTLOADER_ERASE_REP	8
#define SL_POLARIS_ADSB_BOOTLOADER_CHECKSUM_REQ	9
#define SL_POLARIS_ADSB_BOOTLOADER_CHECKSUM_REP	10

/* Keys */
#define SL_POLARIS_ADSB_BOOTLOADER_SET_KEY	0x7e5fa710
#define SL_POLARIS_ADSB_BOOTLOADER_FLASH_KEY	0xac91e301
#define SL_POLARIS_ADSB_BOOTLOADER_ERASE_KEY	0xe33eedcb

typedef struct {
	/* Must be SL_POLARIS_ADSB_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_ADSB_BOOTLOADER_SET_KEY */
	uint32_t key;
} __attribute__ ((packed)) sl_polaris_adsb_bootloader_set_req_t;

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

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

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

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

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

typedef struct {
	/* Must be SL_POLARIS_ADSB_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_adsb_bootloader_checksum_req_t;

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

/*
 * SL_POLARIS_ADSB_PORT_SHELL
 */

/* Types */
#define SL_POLARIS_ADSB_SHELL_RUN_REQ		1
#define SL_POLARIS_ADSB_SHELL_RUN_REP		2

/* Keys */
#define SL_POLARIS_ADSB_SHELL_RUN_KEY		0x61a0d8a0

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

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

#endif /* _SL_POLARIS_ADSB_CLIENT_PROTO_H_ */
