#ifndef _OSCILLOSK_HPP
#define _OSCILLOSK_HPP

#include "daisy.h"

#include "tft.hpp"

using namespace daisy;


#define OSCLSK_SCREEN_XSZ ILI9341_TFTHEIGHT
#define OSCLSK_SCREEN_YSZ ILI9341_TFTWIDTH


#define OSCLSK_RATE_DIV		32

#define OSCLSK_BLOCK_LEN	OSCLSK_SCREEN_XSZ
#define OSCLSK_TRIG_LOOKBACK	0x100u

#define OSCLSK_TFT_CMD_BUF_NSPLIT	4

#define OSCLSK_CMDS_LEN			8 * OSCLSK_SCREEN_XSZ
struct osclsk_scope {
	enum class osc_cc {
		FOREGROUND,
		BACKGROUND
	};

	enum class osc_state {
		INIT,
		TRIGGER,
		SAMPLE,
		SAMPLE_DONE,
		RENDER,
		RENDER_DONE,
		READY
	};

	enum class osc_trig_mode {
		RISING_EDGE,
		FALLING_EDGE,
		ABS_THRESHOLD,
		INSTANT
	};

	enum class osc_trig_state {
		INIT,
		READY,
		NO_TRIG,
		TRIG,
		TRIGGERED
	};

	volatile osc_state	st;

	float		block_y_max[OSCLSK_BLOCK_LEN];
	float		block_y_min[OSCLSK_BLOCK_LEN];
	size_t		block_fill;
	int		block_fill_nsamp;

	float		trig_lkb_y_max[OSCLSK_TRIG_LOOKBACK];
	float		trig_lkb_y_min[OSCLSK_TRIG_LOOKBACK];
	size_t		trig_lkb_idx;
	int		trig_lkb_idx_nsamp;
	size_t		trig_lkb_num;
	size_t		trig_lkb_amount;

	float		trig_margin;
	size_t		trig_num;
	size_t		trig_num_req;
	osc_trig_state	trig_state;
	osc_trig_mode	trig_mode;


	uint16_t	rate_div;



	tft_color			fg, bg;
	tft_driver_ili9341		tft;

	uint16_t	screen_px_y_max[OSCLSK_SCREEN_XSZ];
	uint16_t	screen_px_y_min[OSCLSK_SCREEN_XSZ];
	size_t		render_idx;

	osclsk_scope(void) : st(osc_state::INIT),
       	    block_fill(0), block_fill_nsamp(0),
	    trig_lkb_idx(0), trig_lkb_idx_nsamp(0),
	    trig_lkb_amount(2),
	    trig_margin(.01f), trig_num(0),
	    trig_num_req(2),
	    trig_state(osc_trig_state::INIT),
	    trig_mode(osc_trig_mode::INSTANT),
	    render_idx(0)	{};

	int init(uint8_t *dma_buf, size_t dma_sz);
	int init_block(void);
	int init_screen(void);

	osc_state state(void);

	void set_color(osc_cc which, const tft_color *to_what);

	void sample(const float *sig, size_t num);
	void sample_trigger(const float *sig, size_t num);

	int wait_ready(int ms);
	int prep(void);
	int trig(void);

	bool is_triggering(float sample);
	void trig_lkb_wr_block(void);

	int render_block(void);

	static void render_finish_tft_cb(void *ctx);
};

#endif /* _OSCILLOSK_HPP */
