#include <stdio.h>
#include <string.h>

#include "pico/stdlib.h"
#include "hardware/pio.h"
#include "hardware/clocks.h"

#include "myapp.pio.h"			// myapp.pio: PIO ASM src name


///////////////////////////////////////////////////////////////////////////////////
#define	STDIN_BUF_SIZE	1024
char	stdin_buf_G[STDIN_BUF_SIZE + 3];
char	stdin_buf_ptr_G	= 0;

void init_stdin_buf(void)
{
	memset(stdin_buf_G, 0, STDIN_BUF_SIZE);
	*(stdin_buf_G + STDIN_BUF_SIZE + 0)	= 0x0D;		// for safety
	*(stdin_buf_G + STDIN_BUF_SIZE + 1)	= 0x0A;		// for safety
	*(stdin_buf_G + STDIN_BUF_SIZE + 2)	= 0;		// for safety
	stdin_buf_ptr_G	= 0;
}

int update_stdin_buf(void)
{
//	int	c	= getchar();
	int c	= getchar_timeout_us(0);
	if (c == PICO_ERROR_TIMEOUT)
		return 0;
	else {
		if ('0' <= c && c <= 'f') {
			stdin_buf_G[stdin_buf_ptr_G]	= c;
			if (stdin_buf_ptr_G < STDIN_BUF_SIZE) {
				stdin_buf_ptr_G++;
			}
		}
		if (c == 0x0A)
			return 1;
		else
			return 0;
	}
}
///////////////////////////////////////////////////////////////////////////////////


int	main()
{
//	setup_default_uart();
	stdio_init_all();
	sleep_ms(3000);		// wait serial connection

	// todo	get	free state_machine
	PIO		pio		= pio0;

	uint	addr	= pio_add_program(pio, &pioasm_program);

	/////////////////////////////////////////////////////////////
	// PIN 0-15		OUT
	// PIN 16-28	IN
	/////////////////////////////////////////////////////////////
	pioasm_exec(
		pio,
		0,		// sm
		addr,	// asm

		0,		// outpin base
		16,		// # of outpin

		16,		// inpin base
		7,		// # of inpin

		0,		// sidepin base
		0,		// # of sidepin

//		1.0			// 125MHz
//		4.0			// 31.25MHz
//		10.0		// 12.5MHz
//		12.50		// 10M
//		100.0		// 1.25MHz
//		125.0		// 1M
//		1000.0		// 125KHz
		1250.0		// 100KHz
//		10000.0		// 12.5KHz
					// (min 1.9kHz)
	);

	init_stdin_buf();

	while (true) {
		if (update_stdin_buf() != 0) {
			// put fifo
			if (pio_sm_is_tx_fifo_full(pio, 0) == false) {
				uint	data;
				sscanf(stdin_buf_G, "%x\n", &data);
				pio_sm_put_blocking(pio, 0, (uint32_t)data);
				printf("OUT: %08x\n", data);
			}
			init_stdin_buf();
		}

		// get fifo
		if (pio_sm_is_rx_fifo_empty(pio, 0) == false) {
			uint	data	= pio_sm_get_blocking(pio, 0);
			printf("IN: %08x\n", data);
		}
	}

}

